A fully-Android-compatible two joysticks USB driver for LPC1768. The joysticks have 1 hat, 6 buttons, and there are 1P, 2P buttons.
Fork of app-board-Joystick by
usbhid.cpp
- Committer:
- Alberto_Wino
- Date:
- 2016-12-17
- Revision:
- 3:f1a8ec4659f8
- Parent:
- 2:84ea6e2fb4b6
File content as of revision 3:f1a8ec4659f8:
/* usbhid.cpp */ /* USB HID class device */ /* Copyright (c) Phil Wright 2008 */ /* Modified by yours truly. */ #include "config.h" #include "mbed.h" #include "usbhid.h" #ifdef CONFIG_TWO_REPORTS /* Report for 2 arcade joysticks */ static uint8_t report_descriptor_joystick[] = { 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x09, 0x05, // USAGE (Gamepad) 0xa1, 0x01, // COLLECTION (Application) 0xa1, 0x00, // COLLECTION (Physical) 0x85, 0x01, // REPORT ID 1 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0x01, // LOGICAL_MAXIMUM (1) 0x35, 0x00, // PHYSICAL_MINIMUM (0) 0x45, 0x01, // PHYSICAL_MAXIMUM (1) 0x75, 0x01, // REPORT_SIZE (1) 0x95, 0x08, // REPORT_COUNT (8) 0x05, 0x09, // USAGE_PAGE (Button) 0x19, 0x01, // USAGE_MINIMUM (Button 1) 0x29, 0x08, // USAGE_MAXIMUM (Button 8) 0x81, 0x02, // INPUT (Data,Var,Abs) 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x25, 0x07, // LOGICAL_MAXIMUM (7) 0x46, 0x3b, 0x01, // PHYSICAL_MAXIMUM (315) 0x75, 0x04, // REPORT_SIZE (4) 0x95, 0x01, // REPORT_COUNT (1) 0x65, 0x14, // UNIT (Eng Rot:Angular Pos) 0x09, 0x39, // USAGE (Hat switch) 0x81, 0x42, // INPUT (Data,Var,Abs,Null) 0x65, 0x00, // UNIT (None) 0x95, 0x01, // REPORT_COUNT (1) 0x81, 0x01, // INPUT (Cnst,Ary,Abs) 0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255) 0x46, 0xff, 0x00, // PHYSICAL_MAXIMUM (255) /* For some reason, this is necessary (though we never put it in the report). */ 0x09, 0x30, // USAGE (X) 0x09, 0x31, // USAGE (Y) 0x75, 0x04, // REPORT_SIZE (4) 0x95, 0x02, // REPORT_COUNT (2) 0x81, 0x02, // INPUT (Data,Var,Abs) 0xc0, // END_COLLECTION -- physical /* second report */ 0xa1, 0x00, // COLLECTION (Physical) 0x85, 0x02, // REPORT ID 2 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0x01, // LOGICAL_MAXIMUM (1) 0x35, 0x00, // PHYSICAL_MINIMUM (0) 0x45, 0x01, // PHYSICAL_MAXIMUM (1) 0x75, 0x01, // REPORT_SIZE (1) 0x95, 0x08, // REPORT_COUNT (8) 0x05, 0x09, // USAGE_PAGE (Button) 0x19, 0x01, // USAGE_MINIMUM (Button 1) 0x29, 0x08, // USAGE_MAXIMUM (Button 8) 0x81, 0x02, // INPUT (Data,Var,Abs) 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x25, 0x07, // LOGICAL_MAXIMUM (7) 0x46, 0x3b, 0x01, // PHYSICAL_MAXIMUM (315) 0x75, 0x04, // REPORT_SIZE (4) 0x95, 0x01, // REPORT_COUNT (1) 0x65, 0x14, // UNIT (Eng Rot:Angular Pos) 0x09, 0x39, // USAGE (Hat switch) 0x81, 0x42, // INPUT (Data,Var,Abs,Null) 0x65, 0x00, // UNIT (None) #if 0 /* For some reason, this is not necessary! */ 0x95, 0x01, // REPORT_COUNT (1) 0x81, 0x01, // INPUT (Cnst,Ary,Abs) 0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255) 0x46, 0xff, 0x00, // PHYSICAL_MAXIMUM (255) 0x09, 0x30, // USAGE (X) 0x09, 0x31, // USAGE (Y) 0x75, 0x04, // REPORT_SIZE (4) 0x95, 0x02, // REPORT_COUNT (2) 0x81, 0x02, // INPUT (Data,Var,Abs) #endif 0xc0, // END_COLLECTION -- physical 0xc0, // END_COLLECTION -- application }; #endif #ifdef CONFIG_2ND_PAD_AS_BUTTONS static uint8_t report_descriptor_joystick[] = { 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x09, 0x05, // USAGE (Gamepad) 0xa1, 0x01, // COLLECTION (Application) 0xa1, 0x00, // COLLECTION (Physical) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0x01, // LOGICAL_MAXIMUM (1) 0x35, 0x00, // PHYSICAL_MINIMUM (0) 0x45, 0x01, // PHYSICAL_MAXIMUM (1) 0x75, 0x01, // REPORT_SIZE (1) 0x95, 0x12, // REPORT_COUNT (18) 0x05, 0x09, // USAGE_PAGE (Button) 0x19, 0x01, // USAGE_MINIMUM (Button 1) 0x29, 0x12, // USAGE_MAXIMUM (Button 18) 0x81, 0x02, // INPUT (Data,Var,Abs) 0x95, 0x06, // REPORT_COUNT (6) 0x81, 0x01, // INPUT (Cnst,Ary,Abs) 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x25, 0x07, // LOGICAL_MAXIMUM (7) 0x46, 0x3b, 0x01, // PHYSICAL_MAXIMUM (315) 0x75, 0x04, // REPORT_SIZE (4) 0x95, 0x01, // REPORT_COUNT (1) 0x65, 0x14, // UNIT (Eng Rot:Angular Pos) 0x09, 0x39, // USAGE (Hat switch) 0x81, 0x42, // INPUT (Data,Var,Abs,Null) 0x65, 0x00, // UNIT (None) 0x95, 0x01, // REPORT_COUNT (1) 0x81, 0x01, // INPUT (Cnst,Ary,Abs) 0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255) 0x46, 0xff, 0x00, // PHYSICAL_MAXIMUM (255) /* For some reason, this is necessary (though we never put it in the report). */ 0x09, 0x30, // USAGE (X) 0x09, 0x31, // USAGE (Y) 0x75, 0x04, // REPORT_SIZE (4) 0x95, 0x02, // REPORT_COUNT (2) 0x81, 0x02, // INPUT (Data,Var,Abs) 0xc0, // END_COLLECTION -- physical 0xc0, // END_COLLECTION -- application }; #endif #ifdef CONFIG_TWO_INTERFACES static uint8_t report_descriptor_joystick[] = { 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x09, 0x05, // USAGE (Gamepad) 0xa1, 0x01, // COLLECTION (Application) 0xa1, 0x00, // COLLECTION (Physical) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0x01, // LOGICAL_MAXIMUM (1) 0x35, 0x00, // PHYSICAL_MINIMUM (0) 0x45, 0x01, // PHYSICAL_MAXIMUM (1) 0x75, 0x01, // REPORT_SIZE (1) 0x95, 0x08, // REPORT_COUNT (8) 0x05, 0x09, // USAGE_PAGE (Button) 0x19, 0x01, // USAGE_MINIMUM (Button 1) 0x29, 0x08, // USAGE_MAXIMUM (Button 8) 0x81, 0x02, // INPUT (Data,Var,Abs) 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x25, 0x07, // LOGICAL_MAXIMUM (7) 0x46, 0x3b, 0x01, // PHYSICAL_MAXIMUM (315) 0x75, 0x04, // REPORT_SIZE (4) 0x95, 0x01, // REPORT_COUNT (1) 0x65, 0x14, // UNIT (Eng Rot:Angular Pos) 0x09, 0x39, // USAGE (Hat switch) 0x81, 0x42, // INPUT (Data,Var,Abs,Null) 0x65, 0x00, // UNIT (None) 0x95, 0x01, // REPORT_COUNT (1) 0x81, 0x01, // INPUT (Cnst,Ary,Abs) 0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255) 0x46, 0xff, 0x00, // PHYSICAL_MAXIMUM (255) /* For some reason, this is necessary (though we never put it in the report). */ 0x09, 0x30, // USAGE (X) 0x09, 0x31, // USAGE (Y) 0x75, 0x04, // REPORT_SIZE (4) 0x95, 0x02, // REPORT_COUNT (2) 0x81, 0x02, // INPUT (Data,Var,Abs) 0xc0, // END_COLLECTION -- physical 0xc0, // END_COLLECTION -- application }; #endif /* Endpoint packet sizes */ #define MAX_PACKET_SIZE_EP1 64 /* HID Class */ #define HID_CLASS 3 #define HID_SUBCLASS_NONE 0 #define HID_PROTOCOL_NONE 0 #define HID_DESCRIPTOR 33 #define REPORT_DESCRIPTOR 34 /* Descriptors */ unsigned char deviceDescriptor[] = { 0x12, /* bLength */ DEVICE_DESCRIPTOR, /* bDescriptorType */ 0x10, /* bcdUSB (LSB) */ 0x01, /* bcdUSB (MSB) */ // USB release 1.1 0x00, /* bDeviceClass */ 0x00, /* bDeviceSubClass */ 0x00, /* bDeviceprotocol */ MAX_PACKET_SIZE_EP0, /* bMaxPacketSize0 */ 0xFE, /* idVendor (LSB) */ 0xCA, /* idVendor (MSB) */ 0xBE, /* idProduct (LSB) */ 0xBA, /* idProduct (MSB) */ 0x01, /* bcdDevice (LSB) */ 0x00, /* bcdDevice (MSB) */ // device version number 0x01, /* iManufacturer */ // string index (0 = none) 0x02, /* iProduct */ // string index 0x00, /* iSerialNumber */ // string index 0x01 /* bNumConfigurations */ }; #ifdef CONFIG_TWO_INTERFACES unsigned char configurationDescriptor[] = { 0x09, /* bLength */ CONFIGURATION_DESCRIPTOR, /* bDescriptorType */ 0x00, /* wTotalLength (LSB), set later */ 0x00, /* wTotalLength (MSB), set later */ 0x02, /* bNumInterfaces */ 0x01, /* bConfigurationValue */ 0x00, /* iConfiguration */ 0x80, /* bmAttributes */ 0x32, /* bMaxPower */ /*9*/ 0x09, /* bLength */ INTERFACE_DESCRIPTOR, /* bDescriptorType */ 0x00, /* bInterfaceNumber */ 0x00, /* bAlternateSetting */ 0x01, /* bNumEndpoints */ HID_CLASS, /* bInterfaceClass */ HID_SUBCLASS_NONE, /* bInterfaceSubClass */ HID_PROTOCOL_NONE, /* bInterfaceProtocol */ 0x00, /* iInterface */ /*18*/ 0x09, /* bLength */ HID_DESCRIPTOR, /* bDescriptorType */ 0x11, /* bcdHID (LSB) */ 0x01, /* bcdHID (MSB) */ 0x00, /* bCountryCode */ 0x01, /* bNumDescriptors */ REPORT_DESCRIPTOR, /* bDescriptorType */ sizeof(report_descriptor_joystick) & 0xff, /* wDescriptorLength (LSB) */ (sizeof(report_descriptor_joystick) >> 8) & 0xff, /* wDescriptorLength (MSB) */ /*27*/ 0x07, /* bLength */ ENDPOINT_DESCRIPTOR, /* bDescriptorType */ 0x81, /* bEndpointAddress */ 0x03, /* bmAttributes */ MAX_PACKET_SIZE_EP1, /* wMaxPacketSize (LSB) */ 0x00, /* wMaxPacketSize (MSB) */ 0x05, /* bInterval */ /* second interface */ 0x09, /* bLength */ INTERFACE_DESCRIPTOR, /* bDescriptorType */ 0x01, /* bInterfaceNumber */ 0x00, /* bAlternateSetting */ 0x01, /* bNumEndpoints */ HID_CLASS, /* bInterfaceClass */ HID_SUBCLASS_NONE, /* bInterfaceSubClass */ HID_PROTOCOL_NONE, /* bInterfaceProtocol */ 0x00, /* iInterface */ 0x09, /* bLength */ HID_DESCRIPTOR, /* bDescriptorType */ 0x11, /* bcdHID (LSB) */ 0x01, /* bcdHID (MSB) */ 0x00, /* bCountryCode */ 0x01, /* bNumDescriptors */ REPORT_DESCRIPTOR, /* bDescriptorType */ sizeof(report_descriptor_joystick) & 0xff, /* wDescriptorLength (LSB) */ (sizeof(report_descriptor_joystick) >> 8) & 0xff, /* wDescriptorLength (MSB) */ 0x07, /* bLength */ ENDPOINT_DESCRIPTOR, /* bDescriptorType */ 0x82, /* bEndpointAddress */ 0x03, /* bmAttributes */ MAX_PACKET_SIZE_EP1, /* wMaxPacketSize (LSB) */ 0x00, /* wMaxPacketSize (MSB) */ 0x05 /* bInterval */ }; #else unsigned char configurationDescriptor[] = { 0x09, /* bLength */ CONFIGURATION_DESCRIPTOR, /* bDescriptorType */ 0x00, /* wTotalLength (LSB), set later */ 0x00, /* wTotalLength (MSB), set later */ 0x01, /* bNumInterfaces */ 0x01, /* bConfigurationValue */ 0x00, /* iConfiguration */ 0x80, /* bmAttributes */ 0x32, /* bMaxPower */ /*9*/ 0x09, /* bLength */ INTERFACE_DESCRIPTOR, /* bDescriptorType */ 0x00, /* bInterfaceNumber */ 0x00, /* bAlternateSetting */ 0x01, /* bNumEndpoints */ HID_CLASS, /* bInterfaceClass */ HID_SUBCLASS_NONE, /* bInterfaceSubClass */ HID_PROTOCOL_NONE, /* bInterfaceProtocol */ 0x00, /* iInterface */ /*18*/ 0x09, /* bLength */ HID_DESCRIPTOR, /* bDescriptorType */ 0x11, /* bcdHID (LSB) */ 0x01, /* bcdHID (MSB) */ 0x00, /* bCountryCode */ 0x01, /* bNumDescriptors */ REPORT_DESCRIPTOR, /* bDescriptorType */ sizeof(report_descriptor_joystick) & 0xff, /* wDescriptorLength (LSB) */ (sizeof(report_descriptor_joystick) >> 8) & 0xff, /* wDescriptorLength (MSB) */ /*27*/ 0x07, /* bLength */ ENDPOINT_DESCRIPTOR, /* bDescriptorType */ 0x81, /* bEndpointAddress */ 0x03, /* bmAttributes */ MAX_PACKET_SIZE_EP1, /* wMaxPacketSize (LSB) */ 0x00, /* wMaxPacketSize (MSB) */ 0x05 /* bInterval */ }; #endif static volatile bool complete; #if CONFIG_TWO_INTERFACES static volatile bool complete_ep2; #endif static volatile bool configured; /* */ usbhid::usbhid() { configured = false; connect(); } void usbhid::deviceEventReset() { configured = false; /* Must call base class */ usbdevice::deviceEventReset(); } bool usbhid::requestSetConfiguration() { bool result; /* Configure IN interrupt endpoint */ realiseEndpoint(EP1IN, MAX_PACKET_SIZE_EP1); enableEndpointEvent(EP1IN); #if CONFIG_TWO_INTERFACES /* Configure second IN interrupt endpoint */ realiseEndpoint(EP2IN, MAX_PACKET_SIZE_EP1); enableEndpointEvent(EP2IN); #endif /* Must call base class */ result = usbdevice::requestSetConfiguration(); if (result) { /* Now configured */ configured = true; } return result; } bool usbhid::requestGetDescriptor() { bool success = false; switch (DESCRIPTOR_TYPE(transfer.setup.wValue)) { case DEVICE_DESCRIPTOR: transfer.remaining = sizeof(deviceDescriptor); transfer.ptr = deviceDescriptor; transfer.direction = DEVICE_TO_HOST; success = true; break; case CONFIGURATION_DESCRIPTOR: transfer.remaining = sizeof(configurationDescriptor); transfer.ptr = configurationDescriptor; transfer.direction = DEVICE_TO_HOST; success = true; break; case STRING_DESCRIPTOR: case INTERFACE_DESCRIPTOR: case ENDPOINT_DESCRIPTOR: /* TODO: Support is optional, not implemented here */ break; case HID_DESCRIPTOR: transfer.remaining = configurationDescriptor[18]; transfer.ptr = configurationDescriptor + 18; transfer.direction = DEVICE_TO_HOST; success = true; break; // case REPORT_DESCRIPTOR: /* Handled in the derived class */ default: break; } return success; } void usbhid::endpointEventEP1In() { complete = true; } void usbhid::endpointEventEP2In() { complete_ep2 = true; } /* */ USBJoystick::USBJoystick() { const unsigned config_descriptor_size = sizeof(configurationDescriptor); configurationDescriptor[2] = config_descriptor_size & 0xff; configurationDescriptor[3] = (config_descriptor_size >> 8) & 0xff; } bool USBJoystick::requestGetDescriptor() { switch(DESCRIPTOR_TYPE(transfer.setup.wValue)) { case REPORT_DESCRIPTOR: transfer.remaining = sizeof(report_descriptor_joystick); transfer.ptr = report_descriptor_joystick; transfer.direction = DEVICE_TO_HOST; return true; default: return usbhid::requestGetDescriptor(); } } bool USBJoystick::update(uint8_t gamepad_id, uint8_t stick, uint32_t buttons) { unsigned char hatswitch; if (stick & JOYSTICK_UP) { hatswitch = 0; if (stick & JOYSTICK_RIGHT) hatswitch = 1; if (stick & JOYSTICK_LEFT) hatswitch = 7; } else if (stick & JOYSTICK_RIGHT) { hatswitch = (stick & JOYSTICK_DOWN) ? 3 : 2; } else if (stick & JOYSTICK_DOWN) { hatswitch = (stick & JOYSTICK_LEFT) ? 5 : 4; } else if (stick & JOYSTICK_LEFT) hatswitch = 6; else hatswitch = 0xf; /* Prepare report */ #if CONFIG_TWO_INTERFACES const uint8_t report_size = 2; unsigned char report[2]; report[0] = buttons; report[1] = hatswitch; #endif #if CONFIG_TWO_REPORTS const uint8_t report_size = 3; unsigned char report[3]; report[0] = gamepad_id; report[1] = buttons; report[2] = hatswitch; #endif #if CONFIG_2ND_PAD_AS_BUTTONS const uint8_t report_size = 4; unsigned char report[4]; report[0] = buttons & 0xff; report[1] = (buttons >> 8) & 0xff; report[2] = (buttons >> 16) & 0x03; report[3] = hatswitch; #endif /* Block if not configured */ while(!configured) ; /* Send report */ #if CONFIG_TWO_INTERFACES if (gamepad_id == 2) complete_ep2 = false; else #endif complete = false; disableEvents(); #if CONFIG_TWO_INTERFACES if (gamepad_id == 2) { endpointWrite(EP2IN, report, report_size); enableEvents(); while(!complete_ep2 && configured) ; return true; } #endif endpointWrite(EP1IN, report, report_size); enableEvents(); /* Wait for completion */ while(!complete && configured) ; return true; }