Joystick enabled version of USBHID -library. Has full Playstation 3 functionality including button pressures and a working home-button implementation, while maintaining full PC/MAC/linux -compatibility. basic operation of the lib: #include "mbed.h" #include "usbhid.h" USBJoystick joystick; int main() { while(1) { char dpad = 0xf; /*only the rightmost 4 bits matter*/ short button = 0xff; /*only the rightmost 13 bits matter*/ /*buttons are square, cross, circle, triangle, l1, r1, l2, r2, l3, r3, home.*/ char stick1x = 0; char stick1y = 0; char stick2x = 0; char stick2y = 0; joystick.joystick(dpad, buttons, stick1x, stick1y, stick2x, stick2y); wait_ms(5); } }

Committer:
innocopter
Date:
Fri May 11 13:35:59 2012 +0000
Revision:
0:237d5ef643e9

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
innocopter 0:237d5ef643e9 1 /* usbhid.cpp */
innocopter 0:237d5ef643e9 2 /* USB HID class device */
innocopter 0:237d5ef643e9 3 /* Copyright (c) Phil Wright 2008 */
innocopter 0:237d5ef643e9 4
innocopter 0:237d5ef643e9 5 /* modified by Shinichiro Oba <http://mbed.org/users/bricklife/> */
innocopter 0:237d5ef643e9 6
innocopter 0:237d5ef643e9 7 /* additional modification (PS3 home button functionality) by Panu Kauppinen*/
innocopter 0:237d5ef643e9 8
innocopter 0:237d5ef643e9 9 #include "mbed.h"
innocopter 0:237d5ef643e9 10 #include "usbhid.h"
innocopter 0:237d5ef643e9 11 #include "asciihid.h"
innocopter 0:237d5ef643e9 12
innocopter 0:237d5ef643e9 13 /* Endpoint packet sizes */
innocopter 0:237d5ef643e9 14 #define MAX_PACKET_SIZE_EP1 (64)
innocopter 0:237d5ef643e9 15
innocopter 0:237d5ef643e9 16 /* HID Class */
innocopter 0:237d5ef643e9 17 #define HID_CLASS (3)
innocopter 0:237d5ef643e9 18 #define HID_SUBCLASS_NONE (0)
innocopter 0:237d5ef643e9 19 #define HID_PROTOCOL_NONE (0)
innocopter 0:237d5ef643e9 20 #define HID_DESCRIPTOR (33)
innocopter 0:237d5ef643e9 21 #define REPORT_DESCRIPTOR (34)
innocopter 0:237d5ef643e9 22
innocopter 0:237d5ef643e9 23 /* Class requests */
innocopter 0:237d5ef643e9 24 #define GET_REPORT (0x1)
innocopter 0:237d5ef643e9 25 #define GET_IDLE (0x2)
innocopter 0:237d5ef643e9 26 #define SET_REPORT (0x9)
innocopter 0:237d5ef643e9 27 #define SET_IDLE (0xa)
innocopter 0:237d5ef643e9 28
innocopter 0:237d5ef643e9 29
innocopter 0:237d5ef643e9 30 /* HID Class Report Descriptor */
innocopter 0:237d5ef643e9 31 /* Short items: size is 0, 1, 2 or 3 specifying 0, 1, 2 or 4 (four) bytes of data as per HID Class standard */
innocopter 0:237d5ef643e9 32
innocopter 0:237d5ef643e9 33 /* Main items */
innocopter 0:237d5ef643e9 34 #define INPUT(size) (0x80 | size)
innocopter 0:237d5ef643e9 35 #define OUTPUT(size) (0x90 | size)
innocopter 0:237d5ef643e9 36 #define FEATURE(size) (0xb0 | size)
innocopter 0:237d5ef643e9 37 #define COLLECTION(size) (0xa0 | size)
innocopter 0:237d5ef643e9 38 #define END_COLLECTION(size) (0xc0 | size)
innocopter 0:237d5ef643e9 39
innocopter 0:237d5ef643e9 40 /* Global items */
innocopter 0:237d5ef643e9 41 #define USAGE_PAGE(size) (0x04 | size)
innocopter 0:237d5ef643e9 42 #define LOGICAL_MIN(size) (0x14 | size)
innocopter 0:237d5ef643e9 43 #define LOGICAL_MAX(size) (0x24 | size)
innocopter 0:237d5ef643e9 44 #define PHYSICAL_MIN(size) (0x34 | size)
innocopter 0:237d5ef643e9 45 #define PHYSICAL_MAX(size) (0x44 | size)
innocopter 0:237d5ef643e9 46 #define UNIT_EXPONENT(size) (0x54 | size)
innocopter 0:237d5ef643e9 47 #define UNIT(size) (0x64 | size)
innocopter 0:237d5ef643e9 48 #define REPORT_SIZE(size) (0x74 | size)
innocopter 0:237d5ef643e9 49 #define REPORT_ID(size) (0x84 | size)
innocopter 0:237d5ef643e9 50 #define REPORT_COUNT(size) (0x94 | size)
innocopter 0:237d5ef643e9 51 #define PUSH(size) (0xa4 | size)
innocopter 0:237d5ef643e9 52 #define POP(size) (0xb4 | size)
innocopter 0:237d5ef643e9 53
innocopter 0:237d5ef643e9 54 /* Local items */
innocopter 0:237d5ef643e9 55 #define USAGE(size) (0x08 | size)
innocopter 0:237d5ef643e9 56 #define USAGE_MIN(size) (0x18 | size)
innocopter 0:237d5ef643e9 57 #define USAGE_MAX(size) (0x28 | size)
innocopter 0:237d5ef643e9 58 #define DESIGNATOR_INDEX(size) (0x38 | size)
innocopter 0:237d5ef643e9 59 #define DESIGNATOR_MIN(size) (0x48 | size)
innocopter 0:237d5ef643e9 60 #define DESIGNATOR_MAX(size) (0x58 | size)
innocopter 0:237d5ef643e9 61 #define STRING_INDEX(size) (0x78 | size)
innocopter 0:237d5ef643e9 62 #define STRING_MIN(size) (0x88 | size)
innocopter 0:237d5ef643e9 63 #define STRING_MAX(size) (0x98 | size)
innocopter 0:237d5ef643e9 64 #define DELIMITER(size) (0xa8 | size)
innocopter 0:237d5ef643e9 65
innocopter 0:237d5ef643e9 66 #define REPORT_ID_KEYBOARD (1)
innocopter 0:237d5ef643e9 67 #define REPORT_ID_MOUSE (2)
innocopter 0:237d5ef643e9 68
innocopter 0:237d5ef643e9 69 #define MAX_REPORT_SIZE (64)
innocopter 0:237d5ef643e9 70
innocopter 0:237d5ef643e9 71 unsigned char reportDescriptor[] = {
innocopter 0:237d5ef643e9 72 /* Keyboard */
innocopter 0:237d5ef643e9 73 USAGE_PAGE(1), 0x01,
innocopter 0:237d5ef643e9 74 USAGE(1), 0x06,
innocopter 0:237d5ef643e9 75 COLLECTION(1), 0x01,
innocopter 0:237d5ef643e9 76 REPORT_ID(1), REPORT_ID_KEYBOARD,
innocopter 0:237d5ef643e9 77 USAGE_PAGE(1), 0x07,
innocopter 0:237d5ef643e9 78 USAGE_MIN(1), 0xE0,
innocopter 0:237d5ef643e9 79 USAGE_MAX(1), 0xE7,
innocopter 0:237d5ef643e9 80 LOGICAL_MIN(1), 0x00,
innocopter 0:237d5ef643e9 81 LOGICAL_MAX(1), 0x01,
innocopter 0:237d5ef643e9 82 REPORT_SIZE(1), 0x01,
innocopter 0:237d5ef643e9 83 REPORT_COUNT(1), 0x08,
innocopter 0:237d5ef643e9 84 INPUT(1), 0x02,
innocopter 0:237d5ef643e9 85 REPORT_COUNT(1), 0x01,
innocopter 0:237d5ef643e9 86 REPORT_SIZE(1), 0x08,
innocopter 0:237d5ef643e9 87 INPUT(1), 0x01,
innocopter 0:237d5ef643e9 88 REPORT_COUNT(1), 0x05,
innocopter 0:237d5ef643e9 89 REPORT_SIZE(1), 0x01,
innocopter 0:237d5ef643e9 90 USAGE_PAGE(1), 0x08,
innocopter 0:237d5ef643e9 91 USAGE_MIN(1), 0x01,
innocopter 0:237d5ef643e9 92 USAGE_MAX(1), 0x05,
innocopter 0:237d5ef643e9 93 OUTPUT(1), 0x02,
innocopter 0:237d5ef643e9 94 REPORT_COUNT(1), 0x01,
innocopter 0:237d5ef643e9 95 REPORT_SIZE(1), 0x03,
innocopter 0:237d5ef643e9 96 OUTPUT(1), 0x01,
innocopter 0:237d5ef643e9 97 REPORT_COUNT(1), 0x06,
innocopter 0:237d5ef643e9 98 REPORT_SIZE(1), 0x08,
innocopter 0:237d5ef643e9 99 LOGICAL_MIN(1), 0x00,
innocopter 0:237d5ef643e9 100 LOGICAL_MAX(2), 0xff, 0x00,
innocopter 0:237d5ef643e9 101 USAGE_PAGE(1), 0x07,
innocopter 0:237d5ef643e9 102 USAGE_MIN(1), 0x00,
innocopter 0:237d5ef643e9 103 USAGE_MAX(2), 0xff, 0x00,
innocopter 0:237d5ef643e9 104 INPUT(1), 0x00,
innocopter 0:237d5ef643e9 105 END_COLLECTION(0),
innocopter 0:237d5ef643e9 106
innocopter 0:237d5ef643e9 107 /* Mouse */
innocopter 0:237d5ef643e9 108 USAGE_PAGE(1), 0x01,
innocopter 0:237d5ef643e9 109 USAGE(1), 0x02,
innocopter 0:237d5ef643e9 110 COLLECTION(1), 0x01,
innocopter 0:237d5ef643e9 111 USAGE(1), 0x01,
innocopter 0:237d5ef643e9 112 COLLECTION(1), 0x00,
innocopter 0:237d5ef643e9 113 REPORT_ID(1), REPORT_ID_MOUSE,
innocopter 0:237d5ef643e9 114 REPORT_COUNT(1), 0x03,
innocopter 0:237d5ef643e9 115 REPORT_SIZE(1), 0x01,
innocopter 0:237d5ef643e9 116 USAGE_PAGE(1), 0x09,
innocopter 0:237d5ef643e9 117 USAGE_MIN(1), 0x1,
innocopter 0:237d5ef643e9 118 USAGE_MAX(1), 0x3,
innocopter 0:237d5ef643e9 119 LOGICAL_MIN(1), 0x00,
innocopter 0:237d5ef643e9 120 LOGICAL_MAX(1), 0x01,
innocopter 0:237d5ef643e9 121 INPUT(1), 0x02,
innocopter 0:237d5ef643e9 122 REPORT_COUNT(1), 0x01,
innocopter 0:237d5ef643e9 123 REPORT_SIZE(1), 0x05,
innocopter 0:237d5ef643e9 124 INPUT(1), 0x01,
innocopter 0:237d5ef643e9 125 REPORT_COUNT(1), 0x03,
innocopter 0:237d5ef643e9 126 REPORT_SIZE(1), 0x08,
innocopter 0:237d5ef643e9 127 USAGE_PAGE(1), 0x01,
innocopter 0:237d5ef643e9 128 USAGE(1), 0x30,
innocopter 0:237d5ef643e9 129 USAGE(1), 0x31,
innocopter 0:237d5ef643e9 130 USAGE(1), 0x38,
innocopter 0:237d5ef643e9 131 LOGICAL_MIN(1), 0x81,
innocopter 0:237d5ef643e9 132 LOGICAL_MAX(1), 0x7f,
innocopter 0:237d5ef643e9 133 INPUT(1), 0x06,
innocopter 0:237d5ef643e9 134 END_COLLECTION(0),
innocopter 0:237d5ef643e9 135 END_COLLECTION(0),
innocopter 0:237d5ef643e9 136 };
innocopter 0:237d5ef643e9 137
innocopter 0:237d5ef643e9 138
innocopter 0:237d5ef643e9 139
innocopter 0:237d5ef643e9 140
innocopter 0:237d5ef643e9 141 /* Descriptors */
innocopter 0:237d5ef643e9 142 unsigned char deviceDescriptor[] = {
innocopter 0:237d5ef643e9 143 0x12, /* bLength */
innocopter 0:237d5ef643e9 144 DEVICE_DESCRIPTOR, /* bDescriptorType */
innocopter 0:237d5ef643e9 145 0x10, /* bcdUSB (LSB) */
innocopter 0:237d5ef643e9 146 0x01, /* bcdUSB (MSB) */
innocopter 0:237d5ef643e9 147 0x00, /* bDeviceClass */
innocopter 0:237d5ef643e9 148 0x00, /* bDeviceSubClass */
innocopter 0:237d5ef643e9 149 0x00, /* bDeviceprotocol */
innocopter 0:237d5ef643e9 150 MAX_PACKET_SIZE_EP0, /* bMaxPacketSize0 */
innocopter 0:237d5ef643e9 151 0xC4, /* idVendor (LSB) */
innocopter 0:237d5ef643e9 152 0x10, /* idVendor (MSB) */
innocopter 0:237d5ef643e9 153 0xC0, /* idProduct (LSB) */
innocopter 0:237d5ef643e9 154 0x82, /* idProduct (MSB) */
innocopter 0:237d5ef643e9 155 0x01, /* bcdDevice (LSB) */
innocopter 0:237d5ef643e9 156 0x00, /* bcdDevice (MSB) */
innocopter 0:237d5ef643e9 157 0x01, /* iManufacturer */
innocopter 0:237d5ef643e9 158 0x02, /* iProduct */
innocopter 0:237d5ef643e9 159 0x00, /* iSerialNumber */
innocopter 0:237d5ef643e9 160 0x01 /* bNumConfigurations */
innocopter 0:237d5ef643e9 161 };
innocopter 0:237d5ef643e9 162
innocopter 0:237d5ef643e9 163 unsigned char configurationDescriptor[] = {
innocopter 0:237d5ef643e9 164 0x09, /* bLength */
innocopter 0:237d5ef643e9 165 CONFIGURATION_DESCRIPTOR, /* bDescriptorType */
innocopter 0:237d5ef643e9 166 0x09+0x09+0x09+0x07, /* wTotalLength (LSB) */
innocopter 0:237d5ef643e9 167 0x00, /* wTotalLength (MSB) */
innocopter 0:237d5ef643e9 168 0x01, /* bNumInterfaces */
innocopter 0:237d5ef643e9 169 0x01, /* bConfigurationValue */
innocopter 0:237d5ef643e9 170 0x00, /* iConfiguration */
innocopter 0:237d5ef643e9 171 0x80, /* bmAttributes */
innocopter 0:237d5ef643e9 172 0x32, /* bMaxPower */
innocopter 0:237d5ef643e9 173
innocopter 0:237d5ef643e9 174 0x09, /* bLength */
innocopter 0:237d5ef643e9 175 INTERFACE_DESCRIPTOR, /* bDescriptorType */
innocopter 0:237d5ef643e9 176 0x00, /* bInterfaceNumber */
innocopter 0:237d5ef643e9 177 0x00, /* bAlternateSetting */
innocopter 0:237d5ef643e9 178 0x01, /* bNumEndpoints */
innocopter 0:237d5ef643e9 179 HID_CLASS, /* bInterfaceClass */
innocopter 0:237d5ef643e9 180 HID_SUBCLASS_NONE, /* bInterfaceSubClass */
innocopter 0:237d5ef643e9 181 HID_PROTOCOL_NONE, /* bInterfaceProtocol */
innocopter 0:237d5ef643e9 182 0x00, /* iInterface */
innocopter 0:237d5ef643e9 183
innocopter 0:237d5ef643e9 184 0x09, /* bLength */
innocopter 0:237d5ef643e9 185 HID_DESCRIPTOR, /* bDescriptorType */
innocopter 0:237d5ef643e9 186 0x11, /* bcdHID (LSB) */
innocopter 0:237d5ef643e9 187 0x01, /* bcdHID (MSB) */
innocopter 0:237d5ef643e9 188 0x00, /* bCountryCode */
innocopter 0:237d5ef643e9 189 0x01, /* bNumDescriptors */
innocopter 0:237d5ef643e9 190 REPORT_DESCRIPTOR, /* bDescriptorType */
innocopter 0:237d5ef643e9 191 0x79, /* wDescriptorLength (LSB) */
innocopter 0:237d5ef643e9 192 0x00, /* wDescriptorLength (MSB) */
innocopter 0:237d5ef643e9 193
innocopter 0:237d5ef643e9 194 0x07, /* bLength */
innocopter 0:237d5ef643e9 195 ENDPOINT_DESCRIPTOR, /* bDescriptorType */
innocopter 0:237d5ef643e9 196 0x81, /* bEndpointAddress */
innocopter 0:237d5ef643e9 197 0x03, /* bmAttributes */
innocopter 0:237d5ef643e9 198 MAX_PACKET_SIZE_EP1, /* wMaxPacketSize (LSB) */
innocopter 0:237d5ef643e9 199 0x00, /* wMaxPacketSize (MSB) */
innocopter 0:237d5ef643e9 200 0x05, /* bInterval */
innocopter 0:237d5ef643e9 201 };
innocopter 0:237d5ef643e9 202
innocopter 0:237d5ef643e9 203
innocopter 0:237d5ef643e9 204
innocopter 0:237d5ef643e9 205 volatile bool complete;
innocopter 0:237d5ef643e9 206 volatile bool configured;
innocopter 0:237d5ef643e9 207 unsigned char outputReport[MAX_REPORT_SIZE];
innocopter 0:237d5ef643e9 208
innocopter 0:237d5ef643e9 209 usbhid::usbhid()
innocopter 0:237d5ef643e9 210 {
innocopter 0:237d5ef643e9 211 configured = false;
innocopter 0:237d5ef643e9 212 connect();
innocopter 0:237d5ef643e9 213 }
innocopter 0:237d5ef643e9 214
innocopter 0:237d5ef643e9 215 void usbhid::deviceEventReset()
innocopter 0:237d5ef643e9 216 {
innocopter 0:237d5ef643e9 217 configured = false;
innocopter 0:237d5ef643e9 218
innocopter 0:237d5ef643e9 219 /* Must call base class */
innocopter 0:237d5ef643e9 220 usbdevice::deviceEventReset();
innocopter 0:237d5ef643e9 221 }
innocopter 0:237d5ef643e9 222
innocopter 0:237d5ef643e9 223 bool usbhid::requestSetConfiguration(void)
innocopter 0:237d5ef643e9 224 {
innocopter 0:237d5ef643e9 225 bool result;
innocopter 0:237d5ef643e9 226
innocopter 0:237d5ef643e9 227 /* Configure IN interrupt endpoint */
innocopter 0:237d5ef643e9 228 realiseEndpoint(EP1IN, MAX_PACKET_SIZE_EP1);
innocopter 0:237d5ef643e9 229 enableEndpointEvent(EP1IN);
innocopter 0:237d5ef643e9 230
innocopter 0:237d5ef643e9 231 /* Must call base class */
innocopter 0:237d5ef643e9 232 result = usbdevice::requestSetConfiguration();
innocopter 0:237d5ef643e9 233
innocopter 0:237d5ef643e9 234 if (result)
innocopter 0:237d5ef643e9 235 {
innocopter 0:237d5ef643e9 236 /* Now configured */
innocopter 0:237d5ef643e9 237 configured = true;
innocopter 0:237d5ef643e9 238 }
innocopter 0:237d5ef643e9 239
innocopter 0:237d5ef643e9 240 return result;
innocopter 0:237d5ef643e9 241 }
innocopter 0:237d5ef643e9 242
innocopter 0:237d5ef643e9 243 bool usbhid::requestGetDescriptor(void)
innocopter 0:237d5ef643e9 244 {
innocopter 0:237d5ef643e9 245 bool success = false;
innocopter 0:237d5ef643e9 246
innocopter 0:237d5ef643e9 247
innocopter 0:237d5ef643e9 248 switch (DESCRIPTOR_TYPE(transfer.setup.wValue))
innocopter 0:237d5ef643e9 249 {
innocopter 0:237d5ef643e9 250 case DEVICE_DESCRIPTOR:
innocopter 0:237d5ef643e9 251 transfer.remaining = sizeof(deviceDescriptor);
innocopter 0:237d5ef643e9 252 transfer.ptr = deviceDescriptor;
innocopter 0:237d5ef643e9 253 transfer.direction = DEVICE_TO_HOST;
innocopter 0:237d5ef643e9 254 success = true;
innocopter 0:237d5ef643e9 255 break;
innocopter 0:237d5ef643e9 256 case CONFIGURATION_DESCRIPTOR:
innocopter 0:237d5ef643e9 257 transfer.remaining = sizeof(configurationDescriptor);
innocopter 0:237d5ef643e9 258 transfer.ptr = configurationDescriptor;
innocopter 0:237d5ef643e9 259 transfer.direction = DEVICE_TO_HOST;
innocopter 0:237d5ef643e9 260 success = true;
innocopter 0:237d5ef643e9 261 break;
innocopter 0:237d5ef643e9 262 case STRING_DESCRIPTOR:
innocopter 0:237d5ef643e9 263 case INTERFACE_DESCRIPTOR:
innocopter 0:237d5ef643e9 264 case ENDPOINT_DESCRIPTOR:
innocopter 0:237d5ef643e9 265 /* TODO: Support is optional, not implemented here */
innocopter 0:237d5ef643e9 266 break;
innocopter 0:237d5ef643e9 267 case HID_DESCRIPTOR:
innocopter 0:237d5ef643e9 268 transfer.remaining = 0x09; /* TODO: Fix hard coded size/offset */
innocopter 0:237d5ef643e9 269 transfer.ptr = &configurationDescriptor[18];
innocopter 0:237d5ef643e9 270 transfer.direction = DEVICE_TO_HOST;
innocopter 0:237d5ef643e9 271 success = true;
innocopter 0:237d5ef643e9 272 break;
innocopter 0:237d5ef643e9 273 case REPORT_DESCRIPTOR:
innocopter 0:237d5ef643e9 274 transfer.remaining = sizeof(reportDescriptor);
innocopter 0:237d5ef643e9 275 transfer.ptr = reportDescriptor;
innocopter 0:237d5ef643e9 276 transfer.direction = DEVICE_TO_HOST;
innocopter 0:237d5ef643e9 277 success = true;
innocopter 0:237d5ef643e9 278 break;
innocopter 0:237d5ef643e9 279 default:
innocopter 0:237d5ef643e9 280 break;
innocopter 0:237d5ef643e9 281 }
innocopter 0:237d5ef643e9 282
innocopter 0:237d5ef643e9 283 return success;
innocopter 0:237d5ef643e9 284 }
innocopter 0:237d5ef643e9 285
innocopter 0:237d5ef643e9 286 bool usbhid::requestSetup(void)
innocopter 0:237d5ef643e9 287 {
innocopter 0:237d5ef643e9 288 /* Process class requests */
innocopter 0:237d5ef643e9 289 bool success = false;
innocopter 0:237d5ef643e9 290
innocopter 0:237d5ef643e9 291 if (transfer.setup.bmRequestType.Type == CLASS_TYPE)
innocopter 0:237d5ef643e9 292 {
innocopter 0:237d5ef643e9 293 switch (transfer.setup.bRequest)
innocopter 0:237d5ef643e9 294 {
innocopter 0:237d5ef643e9 295 case SET_REPORT:
innocopter 0:237d5ef643e9 296 switch (transfer.setup.wValue & 0xff)
innocopter 0:237d5ef643e9 297 {
innocopter 0:237d5ef643e9 298 case REPORT_ID_KEYBOARD:
innocopter 0:237d5ef643e9 299 /* TODO: LED state */
innocopter 0:237d5ef643e9 300 transfer.remaining = sizeof(outputReport);
innocopter 0:237d5ef643e9 301 transfer.ptr = outputReport;
innocopter 0:237d5ef643e9 302 transfer.direction = HOST_TO_DEVICE;
innocopter 0:237d5ef643e9 303 success = true;
innocopter 0:237d5ef643e9 304 break;
innocopter 0:237d5ef643e9 305 default:
innocopter 0:237d5ef643e9 306 break;
innocopter 0:237d5ef643e9 307 }
innocopter 0:237d5ef643e9 308 break;
innocopter 0:237d5ef643e9 309 default:
innocopter 0:237d5ef643e9 310 break;
innocopter 0:237d5ef643e9 311 }
innocopter 0:237d5ef643e9 312 }
innocopter 0:237d5ef643e9 313
innocopter 0:237d5ef643e9 314 if (success)
innocopter 0:237d5ef643e9 315 {
innocopter 0:237d5ef643e9 316 /* We've handled this request */
innocopter 0:237d5ef643e9 317 return true;
innocopter 0:237d5ef643e9 318 }
innocopter 0:237d5ef643e9 319
innocopter 0:237d5ef643e9 320 return usbdevice::requestSetup();
innocopter 0:237d5ef643e9 321 }
innocopter 0:237d5ef643e9 322
innocopter 0:237d5ef643e9 323 bool usbhid::sendInputReport(unsigned char id, unsigned char *data, unsigned char size)
innocopter 0:237d5ef643e9 324 {
innocopter 0:237d5ef643e9 325 /* Send an Input Report */
innocopter 0:237d5ef643e9 326 /* If data is NULL an all zero report is sent */
innocopter 0:237d5ef643e9 327
innocopter 0:237d5ef643e9 328 static unsigned char report[MAX_REPORT_SIZE+1]; /* +1 for report ID */
innocopter 0:237d5ef643e9 329 unsigned char i;
innocopter 0:237d5ef643e9 330
innocopter 0:237d5ef643e9 331 if (size > MAX_REPORT_SIZE)
innocopter 0:237d5ef643e9 332 {
innocopter 0:237d5ef643e9 333 return false;
innocopter 0:237d5ef643e9 334 }
innocopter 0:237d5ef643e9 335
innocopter 0:237d5ef643e9 336 /* Add report ID */
innocopter 0:237d5ef643e9 337 report[0]=id;
innocopter 0:237d5ef643e9 338
innocopter 0:237d5ef643e9 339 /* Add report data */
innocopter 0:237d5ef643e9 340 if (data != NULL)
innocopter 0:237d5ef643e9 341 {
innocopter 0:237d5ef643e9 342 for (i=0; i<size; i++)
innocopter 0:237d5ef643e9 343 {
innocopter 0:237d5ef643e9 344 report[i+1] = *data++;
innocopter 0:237d5ef643e9 345 }
innocopter 0:237d5ef643e9 346 }
innocopter 0:237d5ef643e9 347 else
innocopter 0:237d5ef643e9 348 {
innocopter 0:237d5ef643e9 349 for (i=0; i<size; i++)
innocopter 0:237d5ef643e9 350 {
innocopter 0:237d5ef643e9 351 report[i+1] = 0;
innocopter 0:237d5ef643e9 352 }
innocopter 0:237d5ef643e9 353 }
innocopter 0:237d5ef643e9 354
innocopter 0:237d5ef643e9 355 /* Block if not configured */
innocopter 0:237d5ef643e9 356 while (!configured);
innocopter 0:237d5ef643e9 357
innocopter 0:237d5ef643e9 358 /* Send report */
innocopter 0:237d5ef643e9 359 complete = false;
innocopter 0:237d5ef643e9 360 disableEvents();
innocopter 0:237d5ef643e9 361 endpointWrite(EP1IN, report, size+1); /* +1 for report ID */
innocopter 0:237d5ef643e9 362 enableEvents();
innocopter 0:237d5ef643e9 363
innocopter 0:237d5ef643e9 364 /* Wait for completion */
innocopter 0:237d5ef643e9 365 while(!complete && configured);
innocopter 0:237d5ef643e9 366 return true;
innocopter 0:237d5ef643e9 367 }
innocopter 0:237d5ef643e9 368
innocopter 0:237d5ef643e9 369 void usbhid::endpointEventEP1In(void)
innocopter 0:237d5ef643e9 370 {
innocopter 0:237d5ef643e9 371 complete = true;
innocopter 0:237d5ef643e9 372 }
innocopter 0:237d5ef643e9 373
innocopter 0:237d5ef643e9 374 bool usbhid::keyboard(char c)
innocopter 0:237d5ef643e9 375 {
innocopter 0:237d5ef643e9 376 /* Send a simulated keyboard keypress. Returns true if successful. */
innocopter 0:237d5ef643e9 377 unsigned char report[8]={0,0,0,0,0,0,0,0};
innocopter 0:237d5ef643e9 378
innocopter 0:237d5ef643e9 379 report[0] = keymap[c].modifier;
innocopter 0:237d5ef643e9 380 report[2] = keymap[c].usage;
innocopter 0:237d5ef643e9 381
innocopter 0:237d5ef643e9 382 /* Key down */
innocopter 0:237d5ef643e9 383 if (!sendInputReport(REPORT_ID_KEYBOARD, report, 8))
innocopter 0:237d5ef643e9 384 {
innocopter 0:237d5ef643e9 385 return false;
innocopter 0:237d5ef643e9 386 }
innocopter 0:237d5ef643e9 387
innocopter 0:237d5ef643e9 388 /* Key up */
innocopter 0:237d5ef643e9 389 if (!sendInputReport(REPORT_ID_KEYBOARD, NULL, 8))
innocopter 0:237d5ef643e9 390 {
innocopter 0:237d5ef643e9 391 return false;
innocopter 0:237d5ef643e9 392 }
innocopter 0:237d5ef643e9 393
innocopter 0:237d5ef643e9 394 return true;
innocopter 0:237d5ef643e9 395 }
innocopter 0:237d5ef643e9 396
innocopter 0:237d5ef643e9 397 bool usbhid::keyboard(char *string)
innocopter 0:237d5ef643e9 398 {
innocopter 0:237d5ef643e9 399 /* Send a string of characters. Returns true if successful. */
innocopter 0:237d5ef643e9 400 do {
innocopter 0:237d5ef643e9 401 if (!keyboard(*string++))
innocopter 0:237d5ef643e9 402 {
innocopter 0:237d5ef643e9 403 return false;
innocopter 0:237d5ef643e9 404 }
innocopter 0:237d5ef643e9 405 } while (*string != '\0');
innocopter 0:237d5ef643e9 406
innocopter 0:237d5ef643e9 407 return true;
innocopter 0:237d5ef643e9 408 }
innocopter 0:237d5ef643e9 409
innocopter 0:237d5ef643e9 410 bool usbhid::mouse(signed char x, signed char y, unsigned char buttons, signed char wheel)
innocopter 0:237d5ef643e9 411 {
innocopter 0:237d5ef643e9 412 /* Send a simulated mouse event. Returns true if successful. */
innocopter 0:237d5ef643e9 413 unsigned char report[4]={0,0,0,0};
innocopter 0:237d5ef643e9 414
innocopter 0:237d5ef643e9 415 report[0] = buttons;
innocopter 0:237d5ef643e9 416 report[1] = x;
innocopter 0:237d5ef643e9 417 report[2] = y;
innocopter 0:237d5ef643e9 418 report[3] = wheel;
innocopter 0:237d5ef643e9 419
innocopter 0:237d5ef643e9 420 if (!sendInputReport(REPORT_ID_MOUSE, report, 4))
innocopter 0:237d5ef643e9 421 {
innocopter 0:237d5ef643e9 422 return false;
innocopter 0:237d5ef643e9 423 }
innocopter 0:237d5ef643e9 424
innocopter 0:237d5ef643e9 425 return true;
innocopter 0:237d5ef643e9 426 }
innocopter 0:237d5ef643e9 427
innocopter 0:237d5ef643e9 428
innocopter 0:237d5ef643e9 429 //
innocopter 0:237d5ef643e9 430 // USBJoystick
innocopter 0:237d5ef643e9 431 //
innocopter 0:237d5ef643e9 432
innocopter 0:237d5ef643e9 433 unsigned char magic_init_bytes[] = {0x21, 0x26, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00}; // PS3 will request these bytes as a class type report 0x0300
innocopter 0:237d5ef643e9 434
innocopter 0:237d5ef643e9 435 /* Joystick */
innocopter 0:237d5ef643e9 436 unsigned char reportDescriptorJoystick[] = {
innocopter 0:237d5ef643e9 437 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
innocopter 0:237d5ef643e9 438 0x09, 0x05, // USAGE (Gamepad)
innocopter 0:237d5ef643e9 439 0xa1, 0x01, // COLLECTION (Application)
innocopter 0:237d5ef643e9 440
innocopter 0:237d5ef643e9 441 0x15, 0x00, // LOGICAL_MINIMUM (0)
innocopter 0:237d5ef643e9 442 0x25, 0x01, // LOGICAL_MAXIMUM (1)
innocopter 0:237d5ef643e9 443 0x35, 0x00, // PHYSICAL_MINIMUM (0)
innocopter 0:237d5ef643e9 444 0x45, 0x01, // PHYSICAL_MAXIMUM (1)
innocopter 0:237d5ef643e9 445 0x75, 0x01, // REPORT_SIZE (1)
innocopter 0:237d5ef643e9 446 0x95, 0x0d, // REPORT_COUNT (13)
innocopter 0:237d5ef643e9 447 0x05, 0x09, // USAGE_PAGE (Button)
innocopter 0:237d5ef643e9 448 0x19, 0x01, // USAGE_MINIMUM (Button 1)
innocopter 0:237d5ef643e9 449 0x29, 0x0d, // USAGE_MAXIMUM (Button 13)
innocopter 0:237d5ef643e9 450 0x81, 0x02, // INPUT (Data,Var,Abs)
innocopter 0:237d5ef643e9 451 0x95, 0x03, // REPORT_COUNT (3)
innocopter 0:237d5ef643e9 452 0x81, 0x01, // INPUT (Cnst,Ary,Abs)
innocopter 0:237d5ef643e9 453 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
innocopter 0:237d5ef643e9 454 0x25, 0x07, // LOGICAL_MAXIMUM (7)
innocopter 0:237d5ef643e9 455 0x46, 0x3b, 0x01, // PHYSICAL_MAXIMUM (315)
innocopter 0:237d5ef643e9 456 0x75, 0x04, // REPORT_SIZE (4)
innocopter 0:237d5ef643e9 457 0x95, 0x01, // REPORT_COUNT (1)
innocopter 0:237d5ef643e9 458 0x65, 0x14, // UNIT (Eng Rot:Angular Pos)
innocopter 0:237d5ef643e9 459 0x09, 0x39, // USAGE (Hat switch)
innocopter 0:237d5ef643e9 460 0x81, 0x42, // INPUT (Data,Var,Abs,Null)
innocopter 0:237d5ef643e9 461 0x65, 0x00, // UNIT (None)
innocopter 0:237d5ef643e9 462 0x95, 0x01, // REPORT_COUNT (1)
innocopter 0:237d5ef643e9 463 0x81, 0x01, // INPUT (Cnst,Ary,Abs)
innocopter 0:237d5ef643e9 464
innocopter 0:237d5ef643e9 465 0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
innocopter 0:237d5ef643e9 466 0x46, 0xff, 0x00, // PHYSICAL_MAXIMUM (255)
innocopter 0:237d5ef643e9 467 0x09, 0x30, // USAGE (X)
innocopter 0:237d5ef643e9 468 0x09, 0x31, // USAGE (Y)
innocopter 0:237d5ef643e9 469 0x09, 0x32, // USAGE (Z)
innocopter 0:237d5ef643e9 470 0x09, 0x35, // USAGE (Rz)
innocopter 0:237d5ef643e9 471 0x75, 0x08, // REPORT_SIZE (8)
innocopter 0:237d5ef643e9 472 0x95, 0x04, // REPORT_COUNT (4)
innocopter 0:237d5ef643e9 473 0x81, 0x02, // INPUT (Data,Var,Abs)
innocopter 0:237d5ef643e9 474
innocopter 0:237d5ef643e9 475 0x06, 0x00, 0xff, // USAGE_PAGE (Vendor Specific)
innocopter 0:237d5ef643e9 476 0x09, 0x20, // Unknown
innocopter 0:237d5ef643e9 477 0x09, 0x21, // Unknown
innocopter 0:237d5ef643e9 478 0x09, 0x22, // Unknown
innocopter 0:237d5ef643e9 479 0x09, 0x23, // Unknown
innocopter 0:237d5ef643e9 480 0x09, 0x24, // Unknown
innocopter 0:237d5ef643e9 481 0x09, 0x25, // Unknown
innocopter 0:237d5ef643e9 482 0x09, 0x26, // Unknown
innocopter 0:237d5ef643e9 483 0x09, 0x27, // Unknown
innocopter 0:237d5ef643e9 484 0x09, 0x28, // Unknown
innocopter 0:237d5ef643e9 485 0x09, 0x29, // Unknown
innocopter 0:237d5ef643e9 486 0x09, 0x2a, // Unknown
innocopter 0:237d5ef643e9 487 0x09, 0x2b, // Unknown
innocopter 0:237d5ef643e9 488 0x95, 0x0c, // REPORT_COUNT (12)
innocopter 0:237d5ef643e9 489 0x81, 0x02, // INPUT (Data,Var,Abs)
innocopter 0:237d5ef643e9 490 0x0a, 0x21, 0x26, // Unknown
innocopter 0:237d5ef643e9 491 0x95, 0x08, // REPORT_COUNT (8)
innocopter 0:237d5ef643e9 492 0xb1, 0x02, // FEATURE (Data,Var,Abs)
innocopter 0:237d5ef643e9 493
innocopter 0:237d5ef643e9 494 0xc0, // END_COLLECTION
innocopter 0:237d5ef643e9 495 };
innocopter 0:237d5ef643e9 496
innocopter 0:237d5ef643e9 497 USBJoystick::USBJoystick()
innocopter 0:237d5ef643e9 498 {
innocopter 0:237d5ef643e9 499 int reportDescriptorSize = sizeof(reportDescriptorJoystick);
innocopter 0:237d5ef643e9 500 configurationDescriptor[25] = reportDescriptorSize & 0xff;
innocopter 0:237d5ef643e9 501 configurationDescriptor[26] = (reportDescriptorSize >> 8) & 0xff;
innocopter 0:237d5ef643e9 502 }
innocopter 0:237d5ef643e9 503
innocopter 0:237d5ef643e9 504 bool USBJoystick::requestGetDescriptor(void)
innocopter 0:237d5ef643e9 505 {
innocopter 0:237d5ef643e9 506 bool success = false;
innocopter 0:237d5ef643e9 507
innocopter 0:237d5ef643e9 508 switch (DESCRIPTOR_TYPE(transfer.setup.wValue))
innocopter 0:237d5ef643e9 509 {
innocopter 0:237d5ef643e9 510 case REPORT_DESCRIPTOR:
innocopter 0:237d5ef643e9 511 transfer.remaining = sizeof(reportDescriptorJoystick);
innocopter 0:237d5ef643e9 512 transfer.ptr = reportDescriptorJoystick;
innocopter 0:237d5ef643e9 513 transfer.direction = DEVICE_TO_HOST;
innocopter 0:237d5ef643e9 514 success = true;
innocopter 0:237d5ef643e9 515 break;
innocopter 0:237d5ef643e9 516 default:
innocopter 0:237d5ef643e9 517 success = usbhid::requestGetDescriptor();
innocopter 0:237d5ef643e9 518 break;
innocopter 0:237d5ef643e9 519 }
innocopter 0:237d5ef643e9 520
innocopter 0:237d5ef643e9 521 return success;
innocopter 0:237d5ef643e9 522 }
innocopter 0:237d5ef643e9 523
innocopter 0:237d5ef643e9 524 bool USBJoystick::sendInputReport(unsigned char *data, unsigned char size)
innocopter 0:237d5ef643e9 525 {
innocopter 0:237d5ef643e9 526 /* Send an Input Report */
innocopter 0:237d5ef643e9 527 /* If data is NULL an all zero report is sent */
innocopter 0:237d5ef643e9 528
innocopter 0:237d5ef643e9 529 static unsigned char report[MAX_REPORT_SIZE];
innocopter 0:237d5ef643e9 530 unsigned char i;
innocopter 0:237d5ef643e9 531
innocopter 0:237d5ef643e9 532 if (size > MAX_REPORT_SIZE)
innocopter 0:237d5ef643e9 533 {
innocopter 0:237d5ef643e9 534 return false;
innocopter 0:237d5ef643e9 535 }
innocopter 0:237d5ef643e9 536
innocopter 0:237d5ef643e9 537 /* Add report data */
innocopter 0:237d5ef643e9 538 if (data != NULL)
innocopter 0:237d5ef643e9 539 {
innocopter 0:237d5ef643e9 540 for (i=0; i<size; i++)
innocopter 0:237d5ef643e9 541 {
innocopter 0:237d5ef643e9 542 report[i] = *data++;
innocopter 0:237d5ef643e9 543 }
innocopter 0:237d5ef643e9 544 }
innocopter 0:237d5ef643e9 545 else
innocopter 0:237d5ef643e9 546 {
innocopter 0:237d5ef643e9 547 for (i=0; i<size; i++)
innocopter 0:237d5ef643e9 548 {
innocopter 0:237d5ef643e9 549 report[i] = 0;
innocopter 0:237d5ef643e9 550 }
innocopter 0:237d5ef643e9 551 }
innocopter 0:237d5ef643e9 552
innocopter 0:237d5ef643e9 553 /* Block if not configured */
innocopter 0:237d5ef643e9 554 while (!configured);
innocopter 0:237d5ef643e9 555
innocopter 0:237d5ef643e9 556
innocopter 0:237d5ef643e9 557 /* Send report */
innocopter 0:237d5ef643e9 558 complete = false;
innocopter 0:237d5ef643e9 559
innocopter 0:237d5ef643e9 560 disableEvents();
innocopter 0:237d5ef643e9 561 endpointWrite(EP1IN, report, size);
innocopter 0:237d5ef643e9 562 enableEvents();
innocopter 0:237d5ef643e9 563
innocopter 0:237d5ef643e9 564
innocopter 0:237d5ef643e9 565 /* Wait for completion */
innocopter 0:237d5ef643e9 566 while(!complete && configured);
innocopter 0:237d5ef643e9 567
innocopter 0:237d5ef643e9 568
innocopter 0:237d5ef643e9 569 return true;
innocopter 0:237d5ef643e9 570 }
innocopter 0:237d5ef643e9 571
innocopter 0:237d5ef643e9 572 bool USBJoystick::joystick(unsigned char stick, unsigned short buttons, signed char x, signed char y, signed char z, signed char rz)
innocopter 0:237d5ef643e9 573 {
innocopter 0:237d5ef643e9 574 unsigned char report[8+8+3] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
innocopter 0:237d5ef643e9 575
innocopter 0:237d5ef643e9 576 unsigned char hatswitch;
innocopter 0:237d5ef643e9 577 if (stick & JOYSTICK_UP) {
innocopter 0:237d5ef643e9 578 hatswitch = 0;
innocopter 0:237d5ef643e9 579 if (stick & JOYSTICK_RIGHT) hatswitch = 1;
innocopter 0:237d5ef643e9 580 if (stick & JOYSTICK_LEFT) hatswitch = 7;
innocopter 0:237d5ef643e9 581 } else if (stick & JOYSTICK_RIGHT) {
innocopter 0:237d5ef643e9 582 hatswitch = 2;
innocopter 0:237d5ef643e9 583 if (stick & JOYSTICK_DOWN) hatswitch = 3;
innocopter 0:237d5ef643e9 584 } else if (stick & JOYSTICK_DOWN) {
innocopter 0:237d5ef643e9 585 hatswitch = 4;
innocopter 0:237d5ef643e9 586 if (stick & JOYSTICK_LEFT) hatswitch = 5;
innocopter 0:237d5ef643e9 587 } else if (stick & JOYSTICK_LEFT) {
innocopter 0:237d5ef643e9 588 hatswitch = 6;
innocopter 0:237d5ef643e9 589 } else {
innocopter 0:237d5ef643e9 590 hatswitch = 0xf;
innocopter 0:237d5ef643e9 591 }
innocopter 0:237d5ef643e9 592
innocopter 0:237d5ef643e9 593 report[0] = buttons & 0xff; //buttons 1-8
innocopter 0:237d5ef643e9 594 report[1] = ( buttons >> 8 ) & 0xff;//buttons 9-13
innocopter 0:237d5ef643e9 595 report[2] = ((hatswitch ) & 0x0f); // d-pad
innocopter 0:237d5ef643e9 596 report[3] = x + 0x80; //sticks
innocopter 0:237d5ef643e9 597 report[4] = y + 0x80;
innocopter 0:237d5ef643e9 598 report[5] = z + 0x80;
innocopter 0:237d5ef643e9 599 report[6] = rz + 0x80;
innocopter 0:237d5ef643e9 600
innocopter 0:237d5ef643e9 601 report[7] = 0x00; //unknown
innocopter 0:237d5ef643e9 602 report[8] = 0x00; //unknown
innocopter 0:237d5ef643e9 603 report[9] = 0x00; //unknown
innocopter 0:237d5ef643e9 604 report[10] = 0x00; //unknown
innocopter 0:237d5ef643e9 605
innocopter 0:237d5ef643e9 606 report[11] = 0x00; //button pressures
innocopter 0:237d5ef643e9 607 report[12] = 0x00; //button pressures
innocopter 0:237d5ef643e9 608 report[13] = 0x00; //button pressures
innocopter 0:237d5ef643e9 609 report[14] = 0x00; //button pressures
innocopter 0:237d5ef643e9 610
innocopter 0:237d5ef643e9 611 report[15] = 0x00; //trigger pressures
innocopter 0:237d5ef643e9 612 report[16] = 0x00; //trigger pressures
innocopter 0:237d5ef643e9 613 report[17] = 0x00; //trigger pressures
innocopter 0:237d5ef643e9 614 report[18] = 0x00; //trigger pressures
innocopter 0:237d5ef643e9 615
innocopter 0:237d5ef643e9 616 if (!sendInputReport(report, 19)) {
innocopter 0:237d5ef643e9 617 return false;
innocopter 0:237d5ef643e9 618 }
innocopter 0:237d5ef643e9 619
innocopter 0:237d5ef643e9 620
innocopter 0:237d5ef643e9 621 return true;
innocopter 0:237d5ef643e9 622 }
innocopter 0:237d5ef643e9 623
innocopter 0:237d5ef643e9 624 bool USBJoystick::requestSetup(void)
innocopter 0:237d5ef643e9 625 {
innocopter 0:237d5ef643e9 626 /* Process class requests */
innocopter 0:237d5ef643e9 627 bool success = false;
innocopter 0:237d5ef643e9 628
innocopter 0:237d5ef643e9 629 if (transfer.setup.bmRequestType.Type == CLASS_TYPE)
innocopter 0:237d5ef643e9 630 {
innocopter 0:237d5ef643e9 631 switch (transfer.setup.bRequest)
innocopter 0:237d5ef643e9 632 {
innocopter 0:237d5ef643e9 633 case GET_REPORT:
innocopter 0:237d5ef643e9 634 switch (transfer.setup.wValue & 0xffff)
innocopter 0:237d5ef643e9 635 {
innocopter 0:237d5ef643e9 636 case 0x0300: //vendor specific request
innocopter 0:237d5ef643e9 637
innocopter 0:237d5ef643e9 638 transfer.ptr = (unsigned char*)magic_init_bytes;
innocopter 0:237d5ef643e9 639 transfer.remaining = sizeof(magic_init_bytes);
innocopter 0:237d5ef643e9 640 transfer.direction = DEVICE_TO_HOST;
innocopter 0:237d5ef643e9 641 success = true;
innocopter 0:237d5ef643e9 642
innocopter 0:237d5ef643e9 643 break;
innocopter 0:237d5ef643e9 644 default:
innocopter 0:237d5ef643e9 645 break;
innocopter 0:237d5ef643e9 646 }
innocopter 0:237d5ef643e9 647 break;
innocopter 0:237d5ef643e9 648 default:
innocopter 0:237d5ef643e9 649 break;
innocopter 0:237d5ef643e9 650 }
innocopter 0:237d5ef643e9 651 }
innocopter 0:237d5ef643e9 652
innocopter 0:237d5ef643e9 653 if (success)
innocopter 0:237d5ef643e9 654 {
innocopter 0:237d5ef643e9 655 /* We've handled this request */
innocopter 0:237d5ef643e9 656 return true;
innocopter 0:237d5ef643e9 657 }
innocopter 0:237d5ef643e9 658
innocopter 0:237d5ef643e9 659 return usbdevice::requestSetup();
innocopter 0:237d5ef643e9 660 }