cancel
Showing results for 
Search instead for 
Did you mean: 

Combined HID Descriptor Mouse and Keyboard doesn't work

duesentrieb
Associate II

Hello everyone,

I'm currently trying to emulate both a keyboard and the mouse as hid-devices using stm32 and the descriptor that contains two collections.

The descriptor:

 

 

// Keyboard
0x05, 0x01,                   
0x09, 0x06,                    // USAGE (Keyboard)
0xa1, 0x01,                    // COLLECTION (Application)
0x85, 0x01,					   // report id 1
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
// Mouse
0x05, 0x01,        // USAGE_PAGE (Generic Desktop)
0x09, 0x02,        // USAGE (Mouse)
0xA1, 0x01,        // COLLECTION (Application)
0x85, 0x02,        //   REPORT_ID (2)
0x09, 0x01,        //   USAGE (Pointer)
0xA1, 0x00,        //   COLLECTION (Physical)
0x05, 0x09,        //     USAGE_PAGE (Button)
0x19, 0x01,        //     USAGE_MINIMUM (Button 1)
0x29, 0x03,        //     USAGE_MAXIMUM (Button 3)
0x15, 0x00,        //     LOGICAL_MINIMUM (0)
0x25, 0x01,        //     LOGICAL_MAXIMUM (1)
0x95, 0x03,        //     REPORT_COUNT (3)
0x75, 0x01,        //     REPORT_SIZE (1)
0x81, 0x02,        //     INPUT (Data,Var,Abs)
0x95, 0x01,        //     REPORT_COUNT (1)
0x75, 0x05,        //     REPORT_SIZE (5)
0x81, 0x03,        //     INPUT (Cnst,Var,Abs)
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)
0xC0,              //   END_COLLECTION
0xC0               // END_COLLECTION

 

 

 Using only the keyboard or mouse-part of the descriptor, everything works. But if the descriptor is applied as above, neither the mouse or the keyboard emulation are working. I'm using the custom hid class generated by STM32CubeIDE. When debugging the USBD_CUSTOM_HID_SendReport function, pdev->dev_state equals USBD_STATE_CONFIGURED if only keyboard or mouse descriptor applied, or USBD_STATE_SUSPENDED if the combined one from above is applied. Also, the operating system (Windows 11) accepts and configures the devices properly, no issues with the descriptor reported. Maybe someone experienced the same issue and can help me out?

 

Best regards

1 ACCEPTED SOLUTION

Accepted Solutions

Issue fixed by setting the HID_EPIN_SIZE in the file usbd_hid.c correctly.

View solution in original post

11 REPLIES 11
Pavel A.
Evangelist III

 the operating system (Windows 11) accepts and configures the devices properly, no issues with the descriptor reported. 

So the problem is not in the descriptor, it is in other area of the firmware (likely in the code).

 

 

Ok, so I switched back to the example HID-device from STM32CubeIDE, but the mouse still doesn't work.

The codebase itself is rather small, the main function (using the mouse, doesn't work):

 

 

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  MX_USB_DEVICE_Init();
  struct keyboard_report_t
  {
  	uint8_t report_id;
  	uint8_t modifier;
  	uint8_t reserved;
  	uint8_t keycode[6];
  };
  struct mouse_report_t
  {
  	uint8_t report_id;
  	uint8_t buttons;
  	int8_t x;
  	int8_t y;
  };
  struct keyboard_report_t keyboard;
  struct mouse_report_t mouse;
  while (1)
  {
	  mouse.report_id = 0x02;
	  mouse.buttons = 0b00000000;
	  mouse.x = -10;
	  mouse.y = 10;
	  size_t res = USBD_HID_SendReport(&hUsbDeviceFS,&mouse,sizeof(mouse));
	  HAL_Delay(50);

	    // transmit part start (logs via uart console)
		uint8_t message[35] = {'\0'};
		switch(res){
			case USBD_STATE_DEFAULT:
				  sprintf(message, "USBD_STATE_DEFAULT\r\n");
				  break;
			case USBD_STATE_ADDRESSED:
				sprintf(message, "USBD_STATE_ADDRESSED\r\n");
				break;
			case USBD_STATE_CONFIGURED:
				sprintf(message, "USBD_STATE_CONFIGURED\r\n");
				break;
			case USBD_STATE_SUSPENDED:
				sprintf(message, "USBD_STATE_SUSPENDED\r\n");
				break;
			default:
				sprintf(message, "Nothing found: %d\r\n", res);
		}

	    HAL_UART_Transmit(&huart1, message, sizeof(message), 100);
	    // transmit part end
  }
}

  

 

 

And simulating a keyboard (works):

 

 

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  MX_USB_DEVICE_Init();
  struct keyboard_report_t
  {
  	uint8_t report_id;
  	uint8_t modifier;
  	uint8_t reserved;
  	uint8_t keycode[6];
  };
  struct mouse_report_t
  {
  	uint8_t report_id;
  	uint8_t buttons;
  	int8_t x;
  	int8_t y;
  };
  struct keyboard_report_t keyboard;
  struct mouse_report_t mouse;
  while (1)
  {
	  keyboard.report_id = 0x01;
	  keyboard.modifier = 0x00;
	  keyboard.reserved = 0x00;
	  keyboard.keycode[0] = 0x05;
	  keyboard.keycode[1] = 0x00;
	  keyboard.keycode[2] = 0x00;
	  keyboard.keycode[3] = 0x00;
	  keyboard.keycode[4] = 0x00;
	  keyboard.keycode[5] = 0x00;
	  size_t res = USBD_HID_SendReport(&hUsbDeviceFS,&keyboard,sizeof(keyboard));
	  HAL_Delay(50);
	    // transmit part start
		uint8_t message[35] = {'\0'};
		#define USBD_STATE_DEFAULT                              0x01U
		#define USBD_STATE_ADDRESSED                            0x02U
		#define USBD_STATE_CONFIGURED                           0x03U
		#define USBD_STATE_SUSPENDED                            0x04U
		switch(res){
			case USBD_STATE_DEFAULT:
				  sprintf(message, "USBD_STATE_DEFAULT\r\n");
				  break;
			case USBD_STATE_ADDRESSED:
				sprintf(message, "USBD_STATE_ADDRESSED\r\n");
				break;
			case USBD_STATE_CONFIGURED:
				sprintf(message, "USBD_STATE_CONFIGURED\r\n");
				break;
			case USBD_STATE_SUSPENDED:
				sprintf(message, "USBD_STATE_SUSPENDED\r\n");
				break;
			default:
				sprintf(message, "Nothing found: %d\r\n", res);
		}
	    HAL_UART_Transmit(&huart1, message, sizeof(message), 100);
	    // transmit part end
	    keyboard.keycode[0] = 0x00;
	    res = USBD_HID_SendReport(&hUsbDeviceFS,&keyboard,sizeof(keyboard));
	    HAL_Delay(50);
  }
}

 

 

The descriptor including and its length are written into usbd_custom_hid.c. Rest of the code is the generated one from STM32CubeIDE. When using the mouse-code from above, no interaction:

duesentrieb_0-1717706204400.png

- Descriptor with both keyboard ANDmouse: only keyboard example works

- Descriptor with mouse OR keyboard: the specified device works

I've also attached the project's code as a 7z-file.

Screenshot 2024-06-06 232416.png

Screenshot 2024-06-06 232631.png

  

Issue fixed by setting the HID_EPIN_SIZE in the file usbd_hid.c correctly.

What is the correct setting though?

I read a post that stated that to use both keyboard and mouse on STM32 MCUs (Host mode of course) required a Hub, which isn't supported on the ST Cube driver.

Is that correct?

I read a post that stated that to use both keyboard and mouse on STM32 MCUs (Host mode of course) required a Hub

Correct if keyboard and mouse are separate USB devices. But they can be functions of a composite device or HID "collections". Not a likely thing though. Hub is supported by other (more advanced) USB libraries.

USB and mouse are usually physically separate devices.

So you're saying STM have no driver that can handle both at the same time, that's really poor support.

So what is the recommendation for an embedded MCU that does not want to pay a license fee to some "partner" company?

Are we limited to Microsoft RTOS (ex ThreadEx)?

Or Tiny USB, which is not so tiny.

Does any one at actually have a good solution?

 

Hi @Robmar 

Would you start new discussion for better visibility. 

For DualHID examples, in Host mode, we can confirm we do not have examples since Hub is not supported in ST Library.

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Pavel A.
Evangelist III

But you can connect two devices to STM32 which have two host controllers. the ST library supports this.

 

You mean modify our hardware to get around a lack of STM USB Host combined device support, by adding a second physical USB host port?  Are you kidding me?