How to create a new USB device type with a Teensy 3.2

Status
Not open for further replies.

Etienne

Well-known member
Hi,

I'm trying to create a new USB device type with a Teensy 3.2, which will present a Joystick hid and a virtual serial interface. It is working but as I would like to include FFB feature to the joystick (and raw Hid as well later), I need another endpoint and a different descriptor. I have a working FFB descriptor from another project, but as I would like to avoid breaking the Joystick that is already available, I would like to have a new type of interface.

To have the Joystick+Emulated Serial, I did this :

I modified the usb_desc.h file in the teensy3 core, and added a new type that I've called "USB_FFB_RAWHID" with the following definitions :

Code:
	#elif defined(USB_FFB_RAWHID)
		#define VENDOR_ID		0x16C0
		#define PRODUCT_ID		0x048A
		#define MANUFACTURER_NAME		{'A','i','-','W','a','v','e'}
		#define MANUFACTURER_NAME_LEN	7
		#define PRODUCT_NAME			{'E','S','P',' ','W','h','e','e','l'}
		#define PRODUCT_NAME_LEN		9
		#define EP0_SIZE				64

		#define NUM_ENDPOINTS			3
		#define NUM_USB_BUFFERS	 	24
		#define NUM_INTERFACE			2

		#define JOYSTICK_INTERFACE		0// Joystick
		#define JOYSTICK_ENDPOINT	        3
		#define JOYSTICK_SIZE		        16
		#define JOYSTICK_INTERVAL	        2

	        #define SEREMU_INTERFACE      1	// Serial emulation
		#define SEREMU_TX_ENDPOINT    1
		#define SEREMU_TX_SIZE        64
		#define SEREMU_TX_INTERVAL    1
		#define SEREMU_RX_ENDPOINT    2
		#define SEREMU_RX_SIZE        32
		#define SEREMU_RX_INTERVAL    2

		#define ENDPOINT1_CONFIG	ENDPOINT_TRANSIMIT_ONLY
		#define ENDPOINT2_CONFIG	ENDPOINT_RECEIVE_ONLY
		#define ENDPOINT3_CONFIG	ENDPOINT_TRANSIMIT_ONLY

I also modified the boards.txt that you find in the "arduino-1.6.7\hardware\teensy\avr folder", I added the following lines just after "teensy31.menu.usb.rawhid.fake_serial=teensy_gateway":

Code:
teensy31.menu.usb.ffb_hid=Joystick
teensy31.menu.usb.ffb_hid.build.usbtype=USB_FFB_RAWHID
teensy31.menu.usb.ffb_hid.fake_serial=teensy_gateway

If I select "Joystick" in the "Arduino/Tools/Usb Type" menu, it is working as expected, which is pretty cool.

Now I want to add FFB support, so I replaced the all the JOYSTICK_xxx defines with "FFB_JOYSTICK_xxx" defines, which results in usb_desc.h is :

Code:
		#elif defined(USB_FFB_RAWHID)
		#define VENDOR_ID		0x16C0
		#define PRODUCT_ID		0x048A
		#define MANUFACTURER_NAME		{'A','i','-','W','a','v','e'}
		#define MANUFACTURER_NAME_LEN	7
		#define PRODUCT_NAME			{'E','S','P',' ','W','h','e','e','l'}
		#define PRODUCT_NAME_LEN		9
		#define EP0_SIZE				64

		#define NUM_ENDPOINTS			3
		#define NUM_USB_BUFFERS			24
		#define NUM_INTERFACE			2

		#define FFB_JOYSTICK_INTERFACE		0// Joystick
		#define FFB_JOYSTICK_TX_ENDPOINT	3
		#define FFB_JOYSTICK_TX_SIZE		16
		#define FFB_JOYSTICK_TX_INTERVAL	1

	        #define SEREMU_INTERFACE      1	// Serial emulation
		#define SEREMU_TX_ENDPOINT    1
		#define SEREMU_TX_SIZE        64
		#define SEREMU_TX_INTERVAL    1
		#define SEREMU_RX_ENDPOINT    2
		#define SEREMU_RX_SIZE        32
		#define SEREMU_RX_INTERVAL    2

		#define ENDPOINT1_CONFIG	ENDPOINT_TRANSIMIT_ONLY
		#define ENDPOINT2_CONFIG	ENDPOINT_RECEIVE_ONLY
		#define ENDPOINT3_CONFIG	ENDPOINT_TRANSIMIT_ONLY

I also duplicated all the code in usb_desc.c where I have "#ifdef JOYSTICK_INTERFACE" and have replaced with "#ifdef FFB_JOYSTICK_INTERFACE" :

Code:
#ifdef FFB_JOYSTICK_INTERFACE
static uint8_t ffb_joystick_report_desc[] = {
	0x05, 0x01,                     // Usage Page (Generic Desktop)
	0x09, 0x04,                     // Usage (Joystick)
	0xA1, 0x01,                     // Collection (Application)
	0x15, 0x00,                     // Logical Minimum (0)
	0x25, 0x01,                     // Logical Maximum (1)
	0x75, 0x01,                     // Report Size (1)
	0x95, 0x20,                     // Report Count (32)
	0x05, 0x09,                     // Usage Page (Button)
	0x19, 0x01,                     // Usage Minimum (Button #1)
	0x29, 0x20,                     // Usage Maximum (Button #32)
	0x81, 0x02,                     // Input (variable,absolute)
	0x15, 0x00,                     // Logical Minimum (0)
	0x25, 0x07,                     // Logical Maximum (7)
	0x35, 0x00,                     // Physical Minimum (0)
	0x46, 0x3B, 0x01,               // Physical Maximum (315)
	0x75, 0x04,                     // Report Size (4)
	0x95, 0x01,                     // Report Count (1)
	0x65, 0x14,                     // Unit (20)
	0x05, 0x01,                     // Usage Page (Generic Desktop)
	0x09, 0x39,                     // Usage (Hat switch)
	0x81, 0x42,                     // Input (variable,absolute,null_state)
	0x05, 0x01,                     // Usage Page (Generic Desktop)
	0x09, 0x01,                     // Usage (Pointer)
	0xA1, 0x00,                     // Collection ()
	0x15, 0x00,                     //   Logical Minimum (0)
	0x26, 0xFF, 0x03,               //   Logical Maximum (1023)
	0x75, 0x0A,                     //   Report Size (10)
	0x95, 0x04,                     //   Report Count (4)
	0x09, 0x30,                     //   Usage (X)
	0x09, 0x31,                     //   Usage (Y)
	0x09, 0x32,                     //   Usage (Z)
	0x09, 0x35,                     //   Usage (Rz)
	0x81, 0x02,                     //   Input (variable,absolute)
	0xC0,                           // End Collection
	0x15, 0x00,                     // Logical Minimum (0)
	0x26, 0xFF, 0x03,               // Logical Maximum (1023)
	0x75, 0x0A,                     // Report Size (10)
	0x95, 0x02,                     // Report Count (2)
	0x09, 0x36,                     // Usage (Slider)
	0x09, 0x36,                     // Usage (Slider)
	0x81, 0x02,                     // Input (variable,absolute)
	0xC0                            // End Collection
};

Code:
#define FFB_JOYSTICK_INTERFACE_DESC_POS	JOYSTICK_INTERFACE_DESC_POS+JOYSTICK_INTERFACE_DESC_SIZE
#ifdef  FFB_JOYSTICK_INTERFACE
#define FFB_JOYSTICK_INTERFACE_DESC_SIZE	9+9+7
#define FFB_JOYSTICK_HID_DESC_OFFSET	FFB_JOYSTICK_INTERFACE_DESC_POS+9
#else
#define FFB_JOYSTICK_INTERFACE_DESC_SIZE	0
#endif

I also modified the line related to the MTP device :

Code:
#define MTP_INTERFACE_DESC_POS		FFB_JOYSTICK_INTERFACE_DESC_POS+FFB_JOYSTICK_INTERFACE_DESC_SIZE

Added also

Code:
#ifdef FFB_JOYSTICK_INTERFACE
		// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
		9,                                      // bLength
		4,                                      // bDescriptorType
		FFB_JOYSTICK_INTERFACE,                     // bInterfaceNumber
		0,                                      // bAlternateSetting
		1,                                      // bNumEndpoints
		0x03,                                   // bInterfaceClass (0x03 = HID)
		0x00,                                   // bInterfaceSubClass
		0x00,                                   // bInterfaceProtocol
		0,                                      // iInterface
		// HID interface descriptor, HID 1.11 spec, section 6.2.1
		9,                                      // bLength
		0x21,                                   // bDescriptorType
		0x11, 0x01,                             // bcdHID
		0,                                      // bCountryCode
		1,                                      // bNumDescriptors
		0x22,                                   // bDescriptorType
		LSB(sizeof(ffb_joystick_report_desc)),      // wDescriptorLength
		MSB(sizeof(ffb_joystick_report_desc)),
		// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
		7,                                      // bLength
		5,                                      // bDescriptorType
		FFB_JOYSTICK_TX_ENDPOINT | 0x80,        // bEndpointAddress
		0x03,                                   // bmAttributes (0x03=intr)
		FFB_JOYSTICK_TX_SIZE, 0,                // wMaxPacketSize
		FFB_JOYSTICK_TX_INTERVAL,               // bInterval
#endif // FFB_JOYSTICK_INTERFACE

and finally :
Code:
#ifdef FFB_JOYSTICK_INTERFACE
	{ 0x2200, FFB_JOYSTICK_INTERFACE, ffb_joystick_report_desc, sizeof(ffb_joystick_report_desc) },
	{ 0x2100, FFB_JOYSTICK_INTERFACE, config_descriptor + FFB_JOYSTICK_HID_DESC_OFFSET, 9 },
#endif

After these changes, the device is still recognised under windows but it doesn't behave as before (axis are not moving anymore).

I tried to create a new folder called "usb_ffb_hid" by duplicating the folder "usb_hid" at the same level as the "teensy3" core folder, but when I change the code in "usb.c" of this folder, it doesn't seem to be taken into account.

So my question is : these folders (usb_disk,usb_flightsim,usb_hid, etc...) that you find near teensy3, are they used with the teensy 3.2 board ?
I don't know where to look for in order to have my new interface type working like the first type I did, and also where to look for to add the code dealing with FFB, anyone having any idea ?

Thanks

Edit : I got it working as the initial joystick I did, it was the code I modified in joystick.cpp that was wrong. Now the axis are moving again. But to go further (adding FFB), my questions about the folders remain (usb_disk,usb_flightsim,usb_hid, etc...).
 
Last edited:
So my question is : these folders (usb_disk,usb_flightsim,usb_hid, etc...) that you find near teensy3, are they used with the teensy 3.2 board ?

No, those are all for Teensy 2.0 & Teensy++ 2.0.

My earlier USB code for Teensy 2.0 wasn't designed to be flexible, so more device types were added by making more copies.
 
Ok thank you very much for the quick reply.
So I guess that everything happens in usb_dev.c if I want to deal with force feedback reports ?
 
Status
Not open for further replies.
Back
Top