STM32 HID Keyboard - stm32
I am trying to use and STM32F0-disco as a keyboard for a Windows PC. I'm having a problem with the characters that are being printed.
The code below waits until the onboard button is pressed then should print the three characters once.
/* USER CODE BEGIN 2 */
USBDelay = USBD_HID_GetPollingInterval(&hUsbDeviceFS);
while (HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin) == 0);
if (HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin) == 1) {
HAL_GPIO_TogglePin(LD3_GPIO_Port, LD3_Pin);
buff[0] = 0x00;
buff[2] = 0x04;
buff[3] = 0x05;
buff[4] = 0x06;
USBD_HID_SendReport(&hUsbDeviceFS, buff, 8);
HAL_Delay(USBDelay);
buff[0] = 0x00;
buff[2] = 0x00;
buff[3] = 0x00;
buff[4] = 0x00;
USBD_HID_SendReport(&hUsbDeviceFS, buff, 8);
HAL_GPIO_TogglePin(LD4_GPIO_Port, LD4_Pin);
HAL_Delay(1000);
}
while (HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin) == 1);
/* USER CODE END 2 */
The problem I'm having is that the only the characters in the first two key positions of the buffer (which would be the third and fourth elements of the array since element one is the modifier and the second element is reserved). Also, instead of printing once, the characters print continuously without stopping.
Based on the LED's I've added for testing purposes, the characters that I want to print don't print until the second USB_SendReport, which should be sending blank characters to stop the printing.
I've made the necessary changes to usbd_hid.c and usbd_hid.h, as well as the Clock configuration and enabling USB and such. I've put my keyboard descriptor below.
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x08, // REPORT_COUNT (8)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x95, 0x05, // REPORT_COUNT (5)
0x75, 0x01, // REPORT_SIZE (1)
0x05, 0x08, // USAGE_PAGE (LEDs)
0x19, 0x01, // USAGE_MINIMUM (Num Lock)
0x29, 0x05, // USAGE_MAXIMUM (Kana)
0x91, 0x02, // OUTPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x03, // REPORT_SIZE (3)
0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
0x95, 0x06, // REPORT_COUNT (6)
0x75, 0x08, // REPORT_SIZE (8)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x65, // LOGICAL_MAXIMUM (101)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
0x81, 0x00, // INPUT (Data,Ary,Abs)
0xc0 // END_COLLECTION
Any ideas?
The USB HID protocol works differently than you assume. If the input report contains multiple pressed keys, the host (your Windows PC) assumes that they have been pressed at the same time. So they can be inserted in any order. And it might also be the reason the third key is not inserted.
So you need to send a separate output report for each key. And after the last report you need to send another empty one (with all 0s) to indicate the keys have been released (as you are already doing). Such an additional report is also needed between two presses of the same key.
The reason the keys are inserted continuously indicates the empty report was not received. Even though the function uses the term send (USBD_HID_SendReport()), the USB protocol works such that the host needs to pick up the input report. And since it is an USB interrupt endpoint, this only happens ever so often. If a report hasn't been picked up yet, USBD_HID_SendReport() does nothing. It not even returns an error.
While querying to polling interval (USBD_HID_GetPollingInterval()) looks ok at first, it's the polling interval declared in the USB endpoint descriptor. However, Windows only supports a few interval values and rounds up to the next supported value. So you have to increase the value.
Related
how to read data from the BNO085 sensor
How to read and write the data in the BNO085 sensor through I2C. I2C interface is available sensor but no register data are available in datasheet.
It has something called a 'sensor-hub' and you can use SH2 specific commands, which are written through the I2C to configure BNO and get data. For instance, writing the following through I2C will configure BNO to stream orientation as 'ARVR-Stabilized Rotation Vector (0x28)' at 50 Hz (20us = 0x4e20). CARGO_NO++; START_BNO_ALGO[21] = {0x15, 0x00, 0x02, CARGO_NO, 0xFD, 0x28, 0x00, 0x00, 0x00, 0x20, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; I2C_Write(BNO085_ADDRESS, START_BNO_ALGO, 21); Then you can simply I2C_Read the BNO at 50Hz (ideally at BNO interrupt) to get orientation. Hope this will help you to get started. Please check the 'SH-2 Reference Manual' and the 'Sensor Hub Transport Protocol' for more details.
Is there a way to print the APDU command generated by NFCISO7816APDU
I want to debug the following code and see what is the raw APDU it produces. I mean byte by byte from the header to the Le parameter. let selectFileAPDU = NFCISO7816APDU( instructionClass: 0x0C, instructionCode: 0xA4, p1Parameter: 0x02, p2Parameter: 0x0C, data: selectFileCommand, expectedResponseLength: -1)
Incorporate V and H wheel to HID report
I have been working with the HID reports and I have been able to compile and run a report for keyboard, 3 button mouse, and 3 button mouse with wheel (vertical only). Right now I have been trying to use the 5 buttons with vertical and horizontal wheel. So following this // Input report - 5 bytes // // Byte | D7 D6 D5 D4 D3 D2 D1 D0 // ------+--------------------------------------------------------------------- // 0 | 0 0 0 Forward Back Middle Right Left (Buttons) // 1 | X // 2 | Y // 3 | Vertical Wheel // 4 | Horizontal (Tilt) Wheel Now I have this report descriptor 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x09, 0x02, // USAGE (Mouse) 0xa1, 0x01, // COLLECTION (Application) 0x09, 0x02, // USAGE (Mouse) 0xa1, 0x02, // COLLECTION (Logical) 0x09, 0x01, // USAGE (Pointer) 0xa1, 0x00, // COLLECTION (Physical) // ------------------------------ Buttons 0x05, 0x09, // USAGE_PAGE (Button) 0x19, 0x01, // USAGE_MINIMUM (Button 1) 0x29, 0x05, // USAGE_MAXIMUM (Button 5) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0x01, // LOGICAL_MAXIMUM (1) 0x75, 0x01, // REPORT_SIZE (1) 0x95, 0x05, // REPORT_COUNT (5 Buttons) 0x81, 0x02, // INPUT (Data,Var,Abs) // ------------------------------ Padding 0x75, 0x03, // REPORT_SIZE (8-5buttons 3) 0x95, 0x01, // REPORT_COUNT (1) 0x81, 0x03, // INPUT (Cnst,Var,Abs) // ------------------------------ X,Y position 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x09, 0x30, // USAGE (X) 0x09, 0x31, // USAGE (Y) 0x15, 0x81, // LOGICAL_MINIMUM (-127) 0x25, 0x7f, // LOGICAL_MAXIMUM (127) 0x75, 0x08, // REPORT_SIZE (8) 0x95, 0x02, // REPORT_COUNT (2) 0x81, 0x06, // INPUT (Data,Var,Rel) 0xa1, 0x02, // COLLECTION (Logical) // ------------------------------ Vertical wheel res multiplier 0x09, 0x48, // USAGE (Resolution Multiplier) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0x01, // LOGICAL_MAXIMUM (1) 0x35, 0x01, // PHYSICAL_MINIMUM (1) 0x45, 0x04, // PHYSICAL_MAXIMUM (4) 0x75, 0x02, // REPORT_SIZE (2) 0x95, 0x01, // REPORT_COUNT (1) 0xa4, // PUSH 0xb1, 0x02, // FEATURE (Data,Var,Abs) // ------------------------------ Vertical wheel 0x09, 0x38, // USAGE (Wheel) 0x15, 0x81, // LOGICAL_MINIMUM (-127) 0x25, 0x7f, // LOGICAL_MAXIMUM (127) 0x35, 0x00, // PHYSICAL_MINIMUM (0) - reset physical 0x45, 0x00, // PHYSICAL_MAXIMUM (0) 0x75, 0x08, // REPORT_SIZE (8) 0x81, 0x06, // INPUT (Data,Var,Rel) 0xc0, // END_COLLECTION 0xa1, 0x02, // COLLECTION (Logical) // ------------------------------ Horizontal wheel res multiplier 0x09, 0x48, // USAGE (Resolution Multiplier) 0xb4, // POP 0xb1, 0x02, // FEATURE (Data,Var,Abs) // ------------------------------ Padding for Feature report 0x35, 0x00, // PHYSICAL_MINIMUM (0) - reset physical 0x45, 0x00, // PHYSICAL_MAXIMUM (0) 0x75, 0x04, // REPORT_SIZE (4) 0xb1, 0x03, // FEATURE (Cnst,Var,Abs) // ------------------------------ Horizontal wheel 0x05, 0x0c, // USAGE_PAGE (Consumer Devices) 0x0a, 0x38, 0x02, // USAGE (AC Pan) 0x15, 0x81, // LOGICAL_MINIMUM (-127) 0x25, 0x7f, // LOGICAL_MAXIMUM (127) 0x75, 0x08, // REPORT_SIZE (8) 0x81, 0x06, // INPUT (Data,Var,Rel) 0xc0, // END_COLLECTION 0xc0, // END_COLLECTION 0xc0, // END_COLLECTION 0xc0 // END_COLLECTION Which includes the 5 buttons, vertical and horizontal. This compiles without any issue, but I'm trying to send the following information to test if its working correctly mouseReport.buttons = 0; mouseReport.x = 0; mouseReport.y = 0; mouseReport.v = 1; mouseReport.h = 0; But that 1 on the Vertical wheel byte makes my mouse, click and scroll randomly. Could anyone tell me what am I missing? I'm using the exact same code, with a different report and 4 bytes, and the scroll works perfect.
Well I found the issue. I was using a struct to send the byte array and it seems that my micro controller didn't like that because it was getting bad resolution, hence why the random movement and clicks. Changing it to an array of unint8_t fixed the issue.
Type conversion in opencl
I want to convert 'unsigned char' 'uchar16'. At first, I Direct convert it, but it run error. uchar16* out; unsigned char ciphertext[16]; /* * */ out[0] = (uchar16)(ciphertext[0], ciphertext[1], ciphertext[2], ciphertext[3], ciphertext[4], ciphertext[5], ciphertext[6], ciphertext[7], ciphertext[8], ciphertext[9], ciphertext[10], ciphertext[11], ciphertext[12], ciphertext[13], ciphertext[14], ciphertext[15]); When I use real value instead of the variable, it runs. out[0] = (uchar16)(0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C); I searched in Google and Stackoverflow, and I did not find the answer.
For vector conversion in OpenCL there is the suite of functions: convert_destType(sourceType) See point 6.2.3 of the standard (v1.2). So in your case it would be: uchar16 out = convert_uchar16(ciphertext);
What is the error you get? It is simpler and generally more efficient to call vload16 in this case: uchar16 u = vload16(0,ciphertext);
How to set sockaddr_in6::sin6_addr byte order to network byte order?
I developing a network application and using socket APIs. I want to set sin6_addr byte order of sockaddr_in6 structure. For 16 bits or 32 bits variables, it is simple: Using htons or htonl: // IPv4 sockaddr_in addr; addr.sin_port = htons(123); addr.sin_addr.s_addr = htonl(123456); But for 128 bits variables, I dont know how to set byte order to network byte order: // IPv6 sockaddr_in6 addr; addr.sin6_port = htons(123); addr.sin6_addr.s6_addr = ??? // 16 bytes with network byte order but how to set? Some answers may be using htons for 8 times (2 * 8 = 16 bytes), or using htonl for 4 times (4 * 4 = 16 bytes), but I don't know which way is correct. Thanks.
The s6_addr member of struct in6_addr is defined as: uint8_t s6_addr[16]; Since it is an array of uint8_t, rather than being a single 128-bit integer type, the issue of endianness does not arise: you simply copy from your source uint8_t [16] array to the destination. For example, to copy in the address 2001:888:0:2:0:0:0:2 you would use: static const uint8_t myaddr[16] = { 0x20, 0x01, 0x08, 0x88, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }; memcpy(addr.sin6_addr.s6_addr, myaddr, sizeof myaddr);
The usual thing would be to use one of the hostname lookup routines and use the result of that, which is already in network byte order. How come you're dealing with hardcoded numeric IP addresses at all?