I'm trying to connect a Newport AGILIS AG-UC8 controller to my Linux via USB.
Internally, this controller has an FT232R usb-to-serial chip, that should accept simple text commands, such as "VE\r\n" to print the version.
This works fine when using the provided windows driver and software, but on Linux (tested with pyserial and others), the chip doesn't answer. Basically I initialized the device with the values that the Windows device manager showed and then just sent the command.
ser = serial.Serial(port='/dev/ttyUSB0', baudrate=9600, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS)
ser.write("VE\r\n")
I did some debugging with wireshark USB captures:
Windows packet (working, from the provided software):
0000 1b 00 20 9a 40 55 8a ad ff ff 00 00 00 00 09 00 .. .#U..........
0010 00 01 00 03 00 02 03 04 00 00 00 56 45 0d 0a ...........VE..
Linux packet (not working, from pyserial):
0000 80 dd 35 82 e5 99 ff ff 53 03 02 08 02 00 2d 00 ..5.....S.....-.
0010 b6 08 41 60 00 00 00 00 3a 6f 00 00 8d ff ff ff ..A`....:o......
0020 04 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 ................
0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0040 56 45 0d 0a VE..
As you can see, the packet on windows is much smaller, and does not contain the padding zeros. These zeros follow immediately after the data-length field (04), so I am wondering whether they pose the problem to the controller.
Is there a way to send the data without zero padding? Preferably in pyserial, but for now I'd be happy with any solution that lets me speak to my device.
Answering your question, but not necessarily solving your problem: those extra zeros are due to the sniffer capturing traffic between the kernel and libusb. It is also the reason why your capture looks different between environments.
Specifically they are the values stuffed into the pcap_usb_setup structure that sits after urb and data length. There's no particular way or reason to try to eliminate them.
/*
* Header prepended by linux kernel to each event.
* Appears at the front of each packet in DLT_USB_LINUX captures.
*/
typedef struct _usb_header {
uint64_t id;
uint8_t event_type;
uint8_t transfer_type;
uint8_t endpoint_number;
uint8_t device_address;
uint16_t bus_id;
char setup_flag;/*if !=0 the urb setup header is not present*/
char data_flag; /*if !=0 no urb data is present*/
int64_t ts_sec;
int32_t ts_usec;
int32_t status;
uint32_t urb_len;
uint32_t data_len; /* amount of urb data really present in this event*/
pcap_usb_setup setup;
} pcap_usb_header;
/*
* USB setup header as defined in USB specification.
* Appears at the front of each Control S-type packet in DLT_USB captures.
*/
typedef struct _usb_setup {
uint8_t bmRequestType;
uint8_t bRequest;
uint16_t wValue;
uint16_t wIndex;
uint16_t wLength;
} pcap_usb_setup;
I have written a program to use an external (wireless) numpad as an input device for gaming. I am using NUMPAD0, NUMPAD. and ENTER for the modifier keys shift, ctrl and alt respectively and I've keymapped the rest of the numpad keys to WASD and some other keys. I've setup a LowLevelKeyboardProc to intercept and eat the "real" input of the numpad and send a custom WM_MESSAGE to my application's Windows Message loop to then send the keymapped "new" input via SendInput (using the scan codes of the keys I want to simulate).
This all works fine and as expected. Except for the left shift key:
Whenever I press NUMPAD0, which is mapped to left shift, not only the correct scan code 0x2A = 42 is send, but also another key with scan code 0x022a = 554. This seems like some sort of flag in bit #9, since 554 is 42 + 2^9, but I can find any documentation on this.
I've read about extended 2-byte scan codes with prefix 0xE0, but not 0x02 as in this case. This also only happens with the simulated shift key; ctrl and alt a behaving just fine.
Relevant parts of both the keyboard hook and the windows messaging stuff:
LowLevelKeyboardProc:
LPWSTR convertToHex(LPBYTE in, size_t size_in_Bytes)
{
std::stringstream tempS;
tempS << std::hex;
for(int i = 0; i<size_in_Bytes; i++)
{
tempS << std::setfill('0') << std::setw(2) << int(in[i]) << " ";
}
std::string tempString = tempS.str();
std::wstring tempW(tempString.begin(), tempString.end());
LPWSTR out= (LPWSTR) malloc((tempW.size()+2)* sizeof(WCHAR));
StringCbCopyW(out, tempW.size()* sizeof(WCHAR), tempW.c_str());
return out;
}
LRESULT CALLBACK LowLevelKeyboardProc(__in int nCode, __in WPARAM wParam, __in LPARAM lParam)
{
KBDLLHOOKSTRUCT *key=(KBDLLHOOKSTRUCT *)lParam;
wchar_t tempString[128];
LPWSTR hexOut = convertToHex((LPBYTE) key , sizeof(KBDLLHOOKSTRUCT));
StringCbPrintfW(tempString, sizeof(tempString), L"HEX: %s \n", hexOut);
OutputDebugStringW(tempString);
free(hexOut);
//if(key->scanCode > 0xFF)
// return -1; //ignore strange scancode
if(nCode==HC_ACTION)
{
if(isNumpad)
{
auto it = KeyMap.find(key->scanCode);
if(it != KeyMap.end())
{
PostMessage(hwndMain, WM_MY_KEYDOWN, (key->flags & 128), it->first);
StringCbPrintfW(tempString, sizeof(tempString), L"Intercept Key, VK: %d, scan: %d, flags: %d, time: %d, event: %d \n", key->vkCode, key->scanCode, key->flags, key->time, wParam);
OutputDebugStringW(tempString);
return -1;
}
}
}
// delete injected flag
//UINT mask = (1<<4);
//if(key->flags & mask)
// key->flags ^= mask;
//key->scanCode = MapVirtualKey(key->vkCode, MAPVK_VK_TO_VSC);
StringCbPrintfW(tempString, sizeof(tempString), L"Output key: VK: %d, scan: %d, flags: %d, time: %d, event: %d \n", key->vkCode, key->scanCode, key->flags, key->time, wParam);
OutputDebugStringW(tempString);
return CallNextHookEx(hhkHook,nCode,wParam,lParam);
}
Windows Message stuff:
case WM_MY_KEYDOWN:
{
DWORD OLD_KEY = lParam;
DWORD NEW_KEY = KeyMap[OLD_KEY];
bool keyUP = wParam;
INPUT inputdata;
inputdata.type=INPUT_KEYBOARD;
inputdata.ki.dwFlags=KEYEVENTF_SCANCODE ;
inputdata.ki.wScan=NEW_KEY;
inputdata.ki.wVk=MapVirtualKey(NEW_KEY, MAPVK_VSC_TO_VK);
inputdata.ki.time = 0;//key->time;
inputdata.ki.dwExtraInfo = 0;//key->dwExtraInfo;
if(keyUP)
{
inputdata.ki.dwFlags |= KEYEVENTF_KEYUP;
}
Sleep(1);
bool sendKey=false;
switch(inputdata.ki.wScan)
{
//there once was some additional logic here to handle the modifier keys ctrl, alt and shift seperately, but not anymore
default:
{
sendKey=true;
}
break;
}
if (sendKey)
{
UINT result = SendInput(1, &inputdata, sizeof(INPUT));
if(!result)
ErrorExit(L"SendInput didn't work!");
}
}
break;
Output when pressing the normal shift key on a physical keyboard:
//key down
HEX: a0 00 00 00 2a 00 00 00 00 00 00 00 29 cf d2 00 00 00 00 00 00 00 00 00
Output key: VK: 160, scan: 42, flags: 0, time: 13815593, event: 256
//key up
HEX: a0 00 00 00 2a 00 00 00 80 00 00 00 e5 cf d2 00 00 00 00 00 00 00 00 00
Output key: VK: 160, scan: 42, flags: 128, time: 13815781, event: 257
Output when pressing the simulated shift key on the numpad:
//keydown event numpad
HEX: 60 00 00 00 52 00 00 00 00 00 00 00 a1 ea d2 00 00 00 00 00 00 00 00 00
Intercept Key, VK: 96, scan: 82, flags: 0, time: 13822625, event: 256
//keydown event simulated shift key
HEX: a0 00 00 00 2a 00 00 00 10 00 00 00 a1 ea d2 00 00 00 00 00 00 00 00 00
Output key: VK: 160, scan: 42, flags: 0, time: 13822625, event: 256
// key up event with strange scancode 554 <- THIS IS WHAT I AM TALKING ABOUT!
HEX: a0 00 00 00 2a 02 00 00 80 00 00 00 3d eb d2 00 00 00 00 00 00 00 00 00
Output key: VK: 160, scan: 554, flags: 128, time: 13822781, event: 257
// key up event numpad
HEX: 2d 00 00 00 52 00 00 00 80 00 00 00 3d eb d2 00 00 00 00 00 00 00 00 00
Intercept Key, VK: 45, scan: 82, flags: 128, time: 13822781, event: 257
// key down with strange scan code
HEX: a0 00 00 00 2a 02 00 00 00 00 00 00 3d eb d2 00 00 00 00 00 00 00 00 00
Output key: VK: 160, scan: 554, flags: 0, time: 13822781, event: 256
//key up event simulated shift key
HEX: a0 00 00 00 2a 00 00 00 90 00 00 00 3d eb d2 00 00 00 00 00 00 00 00 00
Output key: VK: 160, scan: 42, flags: 128, time: 13822781, event: 257
Another thing to note is that the key-up event of this strange key scan code 554 is also exactly in reverse to what the rest is (see output).
As I can simply eat the key event for this strange scan code 554, this is actually not much of a problem functionality-wise, but I would still like to know what this scan code 554 is all about.
I'm trying to change the card manager AID on a JavaCard 3.x smartcard by using a STORE DATA command. The current card manager AID is the factory default of A0 00 00 01 51 00 00 00. After authenticating with the card manager, the command I'm sending is:
=> 80 E2 80 00 0A 4F 08 A0 00 00 00 03 00 00 00
<= 6A 88
This command executes successfully on a JavaCard 2.2.x card - has this feature been deprecated on JC 3.x?
Looks like the JavaCard 3 needs the command data in DGI format for this to work:
=> 80 E2 80 00 0D 00 70 0A 4F 08 A0 00 00 00 03 00 00 00
<= 90 00
I'm working to get useful data from a VISA (such as PAN, expiry date...) credit card using a list of AIDs I got stuck.
I have been able to access to all the data manually. Using the next tutorial: http://www.openscdp.org/scripts/tutorial/emv/reademv.html
>>00 A4 04 00 07 A0 00 00 00 03 10 10 00
In ASCII:
<<o<EM>„<BEL> <0><0><0><ETX><DLE><DLE>¥<SO>P<EOT>VISA¿<FF><ENQ>ŸM<STX><VT><LF><0>
In Hexadecimal:
<<6F 19 84 07 A0 00 00 00 03 10 10 A5 0E 50 04 56 49 53 41 BF 0C 05 9F 4D 02 0B 0A 90 00
After that I used:
>>33 00 B2 01 0C 00 //sfi1, rec1
...
...
>>33 00 B2 10 FC 00 //sfi31, rec16
I continued with the tutorial and learned that the proper way to obtain the data was using GPO (Get Processing Options) command. And tried that next:
>>80 A8 00 00 0D 83 0B 00 00 00 00 00 00 00 00 00 00 00 00 // pdo = 83 0B 00 00 00 00 00 00 00 00 00 00 00 which suposse to be the correct one for VISA.
<< 69 85
So the condition of use is not satisfied.
>> 80 A8 00 00 02 83 00 00 //pdo= 83 00 that should work with every non visa card
<< 80 0E 3C 00 08 01 01 00 10 01 04 00 18 01 03 01 90 00
If this response is correct and it looks quite well for me as it starts by 80 and ends by 90 00, I am not able to identify AFL which I think that would make me possible to determine the PAN, expiry date... Can somebody help me?
The FCI that you received in response to the select command (00 A4 0400 07 A0000000031010 00) decodes to
6F 19 (File Control Information (FCI) Template)
84 07 (Dedicated File (DF) Name)
A0000000031010
A5 0E (File Control Information (FCI) Proprietary Template)
50 04 (Application Label)
56495341 ("VISA")
BF0C 05 (File Control Information (FCI) Issuer Discretionary Data)
9F4D 02 (Log Entry)
0B0A (SFI = 11; # of records = 10)
This FCI does not include any PDOL (processing options data list). Consequently, you need to assume a default value for the PDOL (which is an empty list for your card type). Consequently, the PDOL-related data field in the GET PROCESSING OPTIONS command must be empty:
83 00
Where 0x83 is the tag for PDOL-related data and 0x00 is a length of zero bytes.
Thus, the correct GPO command is (as you already found out):
80 A8 0000 02 8300 00
You got the response
800E3C00080101001001040018010301 9000
This decodes to
80 0E (Response Message Template Format 1)
3C00 (Application Interchange Profile)
08010100 10010400 18010301 (Application File Locator)
Consequently, the Application File Locator contains the following three entries:
08010100: SFI = 1, first record = 1, last record = 1, records involved in offline data authentication = 0
10010400: SFI = 2, first record = 1, last record = 4, records involved in offline data authentication = 0
18010301: SFI = 3, first record = 1, last record = 3, records involved in offline data authentication = 1
Consequently, you can read those record with the READ RECORD commands:
00 B2 010C 00
00 B2 0114 00
00 B2 0214 00
00 B2 0314 00
00 B2 0414 00
00 B2 011C 00
00 B2 021C 00
00 B2 031C 00
I am trying to replicate a packet.
This packet:
2C 00 65 00 03 00 00 00 00 00 00 00 42 4C 41 5A
45 00 00 00 00 00 00 00 00 42 4C 41 5A 45......
2c 00 is the size of the packet...
65 00 is the packet id 101...
03 00 is the number of elements in the array...
Now here comes my problem, 42 4C 41 5A 45 is a string... There are exactly 3 Instances of that string in that packet if it is complete... But my problem is it is not just null terminated it has 00 00 00 00 spaces between those instances.
My code:
function channel_list(channels) {
var packet = new SmartBuffer();
packet.writeUInt16LE(101); // response packet for list of channels
packet.writeUInt16LE(channels.length)
channels.forEach(function (key){
console.log(key);
packet.writeStringNT(key);
});
packet.writeUInt16LE(packet.length + 2, 0);
console.log(packet.toBuffer());
}
But how do I add the padding?
I am using this package, https://github.com/JoshGlazebrook/smart-buffer/
Smart-Buffer keeps track of its position for you so you do not need to specify an offset to know where to insert the data to pad your string. You could do something like this with your existing code:
channels.forEach(function (key){
console.log(key);
packet.writeString(key); // This is the string with no padding added.
packet.writeUInt32BE(0); // Four 0x00's are added after the string itself.
});
I'm assuming you want: 42 4C 41 5A 45 00 00 00 00 42 4C 41 5A 45 00 00 00 00 etc.
Editing based on comments:
There is no built in way to do what you want, but you could do something like this:
channels.forEach(function (key){
console.log(key);
packet.writeString(key);
for(var i = 0; i <= (9 - key.length); i++)
packet.writeInt8(0);
});