Emulate three USB devices with one Teensy device - Page 1
Forum section: electronics / general

author: luiHS
author_rank: Frequent Contributor
timestamp: March 07, 2019, 07:12:49 am
content: Hello.I need emulate three USB devices (Mouse, Keyboard, Xbox360 gamepad), with one Teensy board (based on kinetis MK20, MK22, MKL26, MK64 or MK66 microcontroller).I have modify the USB descriptors to add support to Xbox360, the code compile but only can emulate Mouse/Keyboard or Xbox360, not the three. Mouse and Keyboard are HID, Xbox360 is Xinput device.If I put these VID PID then work emulating an Xbox360 gamepad#define VENDOR_ID 0x045e#define PRODUCT_ID 0x028eIf I put these VID PID then work and emulate a Mouse + Keyboard#define VENDOR_ID 0x16C0#define PRODUCT_ID 0x0482I do not know what is the problem, and if its really possible mix HID and non HID USB devices to emulate with one microcontroller.Regards

author: up8051
author_rank: Frequent Contributor
timestamp: March 07, 2019, 09:30:10 am
content: Did you try to build composite device?Show the descriptors for HID and XInput.Regardsup8051

author: Xmaxyama
author_rank: Newbie
timestamp: March 07, 2019, 09:41:29 am
content: Each of these stories may not be the same.

author: luiHS
author_rank: Frequent Contributor
timestamp: March 07, 2019, 04:31:18 pm
content: Quote from: up8051 on March 07, 2019, 09:30:10 amYes, a USB composite device.First there is a source file with several defines, according the USB device that I choose from and Arduino Menu. Here I define the interfaces, endpoints, VID, PID and some values for the descriptors.This is what I have configure for my composite USB device, where I have try with two sets of VID/PID, I can only define one set, I tried with these two pair of VID/PID, one only work for Xbox360 gamepad, the other only for Keyboard/Mouse:Code:// This work only with Xinput#define VENDOR_ID0x045e#define PRODUCT_ID0x028e// And this work only with Mouse - Keyboard (HID devices)//#define VENDOR_ID0x16C0//#define PRODUCT_ID0x0482#define MANUFACTURER_NAME{'©','M','i','c','r','o','s','o','f','t'}#define MANUFACTURER_NAME_LEN10#define PRODUCT_NAME{'C','o','n','t','r','o','l','l','e','r'}#define PRODUCT_NAME_LEN10#define EP0_SIZE64#define NUM_ENDPOINTS 11#define NUM_USB_BUFFERS31#define NUM_INTERFACE8#define SEREMU_INTERFACE 4// Serial emulation#define SEREMU_TX_ENDPOINT 7#define SEREMU_TX_SIZE 64#define SEREMU_TX_INTERVAL 1#define SEREMU_RX_ENDPOINT 8#define SEREMU_RX_SIZE 32#define SEREMU_RX_INTERVAL 2#define KEYBOARD_INTERFACE 5// Keyboard#define KEYBOARD_ENDPOINT 9#define KEYBOARD_SIZE 8#define KEYBOARD_INTERVAL 1#define KEYMEDIA_INTERFACE 6// Keyboard Media Keys#define KEYMEDIA_ENDPOINT 10#define KEYMEDIA_SIZE 8#define KEYMEDIA_INTERVAL 4#define MOUSE_INTERFACE 7// Mouse#define MOUSE_ENDPOINT 11#define MOUSE_SIZE 8#define MOUSE_INTERVAL 1#define XINPUT_INTERFACE0 // XINPUT 4 interfaces (0, 1, 2, 3) with 6 Endpoints#define XINPUT_RX_ENDPOINT2#define XINPUT_RX_SIZE 8#define XINPUT_TX_ENDPOINT1#define XINPUT_TX_SIZE 20#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY#define ENDPOINT3_CONFIG ENDPOINT_TRANSIMIT_ONLY#define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY#define ENDPOINT5_CONFIG ENDPOINT_TRANSMIT_AND_RECEIVE#define ENDPOINT6_CONFIG ENDPOINT_TRANSIMIT_ONLY#define ENDPOINT7_CONFIG ENDPOINT_TRANSIMIT_ONLY#define ENDPOINT8_CONFIG ENDPOINT_RECEIVE_ONLY#define ENDPOINT9_CONFIG ENDPOINT_TRANSIMIT_ONLY#define ENDPOINT10_CONFIG ENDPOINT_TRANSIMIT_ONLY#define ENDPOINT11_CONFIG ENDPOINT_TRANSIMIT_ONLYAnd these are the USB descriptors for each interface.Code:#ifdef SEREMU_INTERFACE// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-129, // bLength4, // bDescriptorTypeSEREMU_INTERFACE, // bInterfaceNumber0, // bAlternateSetting2, // bNumEndpoints0x03, // bInterfaceClass (0x03 = HID)0x00, // bInterfaceSubClass0x00, // bInterfaceProtocol0, // iInterface// HID interface descriptor, HID 1.11 spec, section 6.2.19, // bLength0x21, // bDescriptorType0x11, 0x01, // bcdHID0, // bCountryCode1, // bNumDescriptors0x22, // bDescriptorTypeLSB(sizeof(seremu_report_desc)), // wDescriptorLengthMSB(sizeof(seremu_report_desc)),// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-137, // bLength5, // bDescriptorTypeSEREMU_TX_ENDPOINT | 0x80, // bEndpointAddress0x03, // bmAttributes (0x03=intr)SEREMU_TX_SIZE, 0, // wMaxPacketSizeSEREMU_TX_INTERVAL, // bInterval// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-137, // bLength5, // bDescriptorTypeSEREMU_RX_ENDPOINT, // bEndpointAddress0x03, // bmAttributes (0x03=intr)SEREMU_RX_SIZE, 0, // wMaxPacketSizeSEREMU_RX_INTERVAL,// bInterval#endif // SEREMU_INTERFACECode:#ifdef KEYBOARD_INTERFACE// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-129, // bLength4, // bDescriptorTypeKEYBOARD_INTERFACE, // bInterfaceNumber0, // bAlternateSetting1, // bNumEndpoints0x03, // bInterfaceClass (0x03 = HID)0x01, // bInterfaceSubClass (0x01 = Boot)0x01, // bInterfaceProtocol (0x01 = Keyboard)0, // iInterface// HID interface descriptor, HID 1.11 spec, section 6.2.19, // bLength0x21, // bDescriptorType0x11, 0x01, // bcdHID0, // bCountryCode1, // bNumDescriptors0x22, // bDescriptorTypeLSB(sizeof(keyboard_report_desc)), // wDescriptorLengthMSB(sizeof(keyboard_report_desc)),// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-137, // bLength5, // bDescriptorTypeKEYBOARD_ENDPOINT | 0x80, // bEndpointAddress0x03, // bmAttributes (0x03=intr)KEYBOARD_SIZE, 0, // wMaxPacketSizeKEYBOARD_INTERVAL, // bInterval#endif // KEYBOARD_INTERFACECode:#ifdef KEYMEDIA_INTERFACE// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-129, // bLength4, // bDescriptorTypeKEYMEDIA_INTERFACE, // bInterfaceNumber0, // bAlternateSetting1, // bNumEndpoints0x03, // bInterfaceClass (0x03 = HID)0x00, // bInterfaceSubClass0x00, // bInterfaceProtocol0, // iInterface// HID interface descriptor, HID 1.11 spec, section 6.2.19, // bLength0x21, // bDescriptorType0x11, 0x01, // bcdHID0, // bCountryCode1, // bNumDescriptors0x22, // bDescriptorTypeLSB(sizeof(keymedia_report_desc)), // wDescriptorLengthMSB(sizeof(keymedia_report_desc)),// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-137, // bLength5, // bDescriptorTypeKEYMEDIA_ENDPOINT | 0x80, // bEndpointAddress0x03, // bmAttributes (0x03=intr)KEYMEDIA_SIZE, 0, // wMaxPacketSizeKEYMEDIA_INTERVAL, // bInterval#endif // KEYMEDIA_INTERFACECode:#ifdef MOUSE_INTERFACE// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-129, // bLength4, // bDescriptorTypeMOUSE_INTERFACE, // bInterfaceNumber0, // bAlternateSetting1, // bNumEndpoints0x03, // bInterfaceClass (0x03 = HID)0x00, // bInterfaceSubClass (0x01 = Boot)0x00, // bInterfaceProtocol (0x02 = Mouse)0, // iInterface// HID interface descriptor, HID 1.11 spec, section 6.2.19, // bLength0x21, // bDescriptorType0x11, 0x01, // bcdHID0, // bCountryCode1, // bNumDescriptors0x22, // bDescriptorTypeLSB(sizeof(mouse_report_desc)), // wDescriptorLengthMSB(sizeof(mouse_report_desc)),// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-137, // bLength5, // bDescriptorTypeMOUSE_ENDPOINT | 0x80, // bEndpointAddress0x03, // bmAttributes (0x03=intr)MOUSE_SIZE, 0, // wMaxPacketSizeMOUSE_INTERVAL, // bInterval#endif // MOUSE_INTERFACECode:#ifdef XINPUT_INTERFACE//Interface 09,//bLength (length of interface descriptor 9 bytes)4,//bDescriptorType (4 is interface)0,//bInterfaceNumber (This is interface 0)0,//bAlternateSetting (used to select alternate setting. notused)2,//bNumEndpoints (this interface has 2 endpoints)0xFF,//bInterfaceClass (Vendor Defined is 255)0x5D,//bInterfaceSubClass0x01,//bInterfaceProtocol0,//iInterface (Index of string descriptor for describing this notused)//Some sort of common descriptor? I pulled this from Message Analyzer dumps of an actual controller17,33,0,1,1,37,129,20,0,0,0,0,19,2,8,0,0,//Endpoint 1 IN7,//bLength (length of ep1in in descriptor 7 bytes)5,//bDescriptorType (5 is endpoint)0x81,//bEndpointAddress (0x81 is IN1)0x03,//bmAttributes (0x03 is interrupt no synch, usage type data)0x20, 0x00,//wMaxPacketSize (0x0020 is 1x32 bytes)4,//bInterval (polling interval in frames 4 frames)//Endpoint 2 OUT7,//bLength (length of ep2out in descriptor 7 bytes)5,//bDescriptorType (5 is endpoint)0x02,//bEndpointAddress (0x02 is OUT2)0x03,//bmAttributes (0x03 is interrupt no synch, usage type data)0x20, 0x00,//wMaxPacketSize (0x0020 is 1x32 bytes)8,//bInterval (polling interval in frames 8 frames)//Interface 19,//bLength (length of interface descriptor 9 bytes)4,//bDescriptorType (4 is interface)1,//bInterfaceNumber (This is interface 1)0,//bAlternateSetting (used to select alternate setting. notused)4,//bNumEndpoints (this interface has 4 endpoints)0xFF,//bInterfaceClass (Vendor Defined is 255)0x5D,//bInterfaceSubClass (93)0x03,//bInterfaceProtocol (3)0,//iInterface (Index of string descriptor for describing this notused)//A different common descriptor? I pulled this from Message Analyzer dumps of an actual controller27,33,0,1,1,1,131,64,1,4,32,22,133,0,0,0,0,0,0,22,5,0,0,0,0,0,0,//Endpoint 3 IN7,//bLength (length of ep3in descriptor 7 bytes)5,//bDescriptorType (5 is endpoint)0x83,//bEndpointAddress (0x83 is IN3)0x03,//bmAttributes (0x03 is interrupt no synch, usage type data)0x20, 0x00,//wMaxPacketSize (0x0020 is 1x32 bytes)2,//bInterval (polling interval in frames 2 frames)//Endpoint 4 OUT7,//bLength (length of ep4out descriptor 7 bytes)5,//bDescriptorType (5 is endpoint)0x04,//bEndpointAddress (0x04 is OUT4)0x03,//bmAttributes (0x03 is interrupt no synch, usage type data)0x20, 0x00,//wMaxPacketSize (0x0020 is 1x32 bytes)4,//bInterval (polling interval in frames 4 frames)//Endpoint 5 IN7,//bLength (length of ep5in descriptor 7 bytes)5,//bDescriptorType (5 is endpoint)0x85,//bEndpointAddress (0x85 is IN5)0x03,//bmAttributes (0x03 is interrupt no synch, usage type data)0x20, 0x00,//wMaxPacketSize (0x0020 is 1x32 bytes)64,//bInterval (polling interval in frames 64 frames)//Endpoint 5 OUT (shares endpoint number with previous)7,//bLength (length of ep5out descriptor 7 bytes)5,//bDescriptorType (5 is endpoint)0x05,//bEndpointAddress (0x05 is OUT5)0x03,//bmAttributes (0x03 is interrupt no synch, usage type data)0x20, 0x00,//wMaxPacketSize (0x0020 is 1x32 bytes)16,//bInterval (polling interval in frames 16 frames)//Interface 29,//bLength (length of interface descriptor 9 bytes)4,//bDescriptorType (4 is interface)2,//bInterfaceNumber (This is interface 2)0,//bAlternateSetting (used to select alternate setting. notused)1,//bNumEndpoints (this interface has 4 endpoints)0xFF,//bInterfaceClass (Vendor Defined is 255)0x5D,//bInterfaceSubClass (93)0x02,//bInterfaceProtocol (3)0,//iInterface (Index of string descriptor for describing this notused)//Common Descriptor. Seems that these come after every interface description?9,33,0,1,1,34,134,7,0,//Endpoint 6 IN7,//bLength (length of ep6in descriptor 7 bytes)5,//bDescriptorType (5 is endpoint)0x86,//bEndpointAddress (0x86 is IN6)0x03,//bmAttributes (0x03 is interrupt no synch, usage type data)0x20, 0x00,//wMaxPacketSize (0x0020 is 1x32 bytes)16,//bInterval (polling interval in frames 64 frames)+//Interface 3//This is the interface on which all the security handshaking takes place//We don't use this but it could be used for man-in-the-middle stuff9,//bLength (length of interface descriptor 9 bytes)4,//bDescriptorType (4 is interface)3,//bInterfaceNumber (This is interface 3)0,//bAlternateSetting (used to select alternate setting. notused)0,//bNumEndpoints (this interface has 0 endpoints ??? )0xFF,//bInterfaceClass (Vendor Defined is 255)0xFD,//bInterfaceSubClass (253)0x13,//bInterfaceProtocol (19)4,//iInterface (Computer never asks for this, but an x360 would. so include one day?)//Another interface another Common Descriptor6,65,0,1,1,3#endif // XINPUT_INTERFACE