Based on USBKeyboardMouse example. I added USB String Descriptor so mbed reports itself to host not only with VID & PID but also with name of manufacturer, product name, serial number, configuration number and interface name. These can be changed to matching Yours in USBhid.cpp file on lines 88 - 122.

Dependencies:   mbed

Committer:
llumpu
Date:
Thu Sep 08 15:01:33 2011 +0000
Revision:
0:f97b1f255167
Added USB String Descriptor

Who changed what in which revision?

UserRevisionLine numberNew contents of line
llumpu 0:f97b1f255167 1 /* usbhid.cpp */
llumpu 0:f97b1f255167 2 /* USB HID class device */
llumpu 0:f97b1f255167 3 /* Copyright (c) Phil Wright 2008 */
llumpu 0:f97b1f255167 4 /* USB String Descriptor by llumpu 2011*/
llumpu 0:f97b1f255167 5
llumpu 0:f97b1f255167 6 #include "mbed.h"
llumpu 0:f97b1f255167 7 #include "usbhid.h"
llumpu 0:f97b1f255167 8 #include "asciihid.h"
llumpu 0:f97b1f255167 9
llumpu 0:f97b1f255167 10 /* Endpoint packet sizes */
llumpu 0:f97b1f255167 11 #define MAX_PACKET_SIZE_EP1 (64)
llumpu 0:f97b1f255167 12
llumpu 0:f97b1f255167 13 /* HID Class */
llumpu 0:f97b1f255167 14 #define HID_CLASS (3)
llumpu 0:f97b1f255167 15 #define HID_SUBCLASS_NONE (0)
llumpu 0:f97b1f255167 16 #define HID_PROTOCOL_NONE (0)
llumpu 0:f97b1f255167 17 #define HID_DESCRIPTOR (33)
llumpu 0:f97b1f255167 18 #define REPORT_DESCRIPTOR (34)
llumpu 0:f97b1f255167 19
llumpu 0:f97b1f255167 20 /* Class requests */
llumpu 0:f97b1f255167 21 #define GET_REPORT (0x1)
llumpu 0:f97b1f255167 22 #define GET_IDLE (0x2)
llumpu 0:f97b1f255167 23 #define SET_REPORT (0x9)
llumpu 0:f97b1f255167 24 #define SET_IDLE (0xa)
llumpu 0:f97b1f255167 25
llumpu 0:f97b1f255167 26 /* Descriptors */
llumpu 0:f97b1f255167 27 unsigned char deviceDescriptor[] = {
llumpu 0:f97b1f255167 28 0x12, /* bLength */
llumpu 0:f97b1f255167 29 DEVICE_DESCRIPTOR, /* bDescriptorType */
llumpu 0:f97b1f255167 30 0x00, /* bcdUSB (LSB) */
llumpu 0:f97b1f255167 31 0x02, /* bcdUSB (MSB) */
llumpu 0:f97b1f255167 32 0x00, /* bDeviceClass */
llumpu 0:f97b1f255167 33 0x00, /* bDeviceSubClass */
llumpu 0:f97b1f255167 34 0x00, /* bDeviceprotocol */
llumpu 0:f97b1f255167 35 MAX_PACKET_SIZE_EP0, /* bMaxPacketSize0 */
llumpu 0:f97b1f255167 36 0x28, /* idVendor (LSB) */
llumpu 0:f97b1f255167 37 0x0d, /* idVendor (MSB) */
llumpu 0:f97b1f255167 38 0x05, /* idProduct (LSB) */
llumpu 0:f97b1f255167 39 0x02, /* idProduct (MSB) */
llumpu 0:f97b1f255167 40 0x00, /* bcdDevice (LSB) */
llumpu 0:f97b1f255167 41 0x00, /* bcdDevice (MSB) */
llumpu 0:f97b1f255167 42 STRING_OFFSET_IMANUFACTURER, /* iManufacturer */
llumpu 0:f97b1f255167 43 STRING_OFFSET_IPRODUCT, /* iProduct */
llumpu 0:f97b1f255167 44 STRING_OFFSET_ISERIAL, /* iSerialNumber */
llumpu 0:f97b1f255167 45 0x01 /* bNumConfigurations */
llumpu 0:f97b1f255167 46 };
llumpu 0:f97b1f255167 47
llumpu 0:f97b1f255167 48 unsigned char configurationDescriptor[] = {
llumpu 0:f97b1f255167 49 0x09, /* bLength */
llumpu 0:f97b1f255167 50 CONFIGURATION_DESCRIPTOR, /* bDescriptorType */
llumpu 0:f97b1f255167 51 0x09+0x09+0x09+0x07, /* wTotalLength (LSB) */
llumpu 0:f97b1f255167 52 0x00, /* wTotalLength (MSB) */
llumpu 0:f97b1f255167 53 0x01, /* bNumInterfaces */
llumpu 0:f97b1f255167 54 0x01, /* bConfigurationValue */
llumpu 0:f97b1f255167 55 STRING_OFFSET_ICONFIGURATION,/* iConfiguration */
llumpu 0:f97b1f255167 56 0xc0, /* bmAttributes */
llumpu 0:f97b1f255167 57 0x00, /* bMaxPower */
llumpu 0:f97b1f255167 58
llumpu 0:f97b1f255167 59 0x09, /* bLength */
llumpu 0:f97b1f255167 60 INTERFACE_DESCRIPTOR, /* bDescriptorType */
llumpu 0:f97b1f255167 61 0x00, /* bInterfaceNumber */
llumpu 0:f97b1f255167 62 0x00, /* bAlternateSetting */
llumpu 0:f97b1f255167 63 0x01, /* bNumEndpoints */
llumpu 0:f97b1f255167 64 HID_CLASS, /* bInterfaceClass */
llumpu 0:f97b1f255167 65 HID_SUBCLASS_NONE, /* bInterfaceSubClass */
llumpu 0:f97b1f255167 66 HID_PROTOCOL_NONE, /* bInterfaceProtocol */
llumpu 0:f97b1f255167 67 STRING_OFFSET_IINTERFACE, /* iInterface */
llumpu 0:f97b1f255167 68
llumpu 0:f97b1f255167 69 0x09, /* bLength */
llumpu 0:f97b1f255167 70 HID_DESCRIPTOR, /* bDescriptorType */
llumpu 0:f97b1f255167 71 0x11, /* bcdHID (LSB) */
llumpu 0:f97b1f255167 72 0x01, /* bcdHID (MSB) */
llumpu 0:f97b1f255167 73 0x00, /* bCountryCode */
llumpu 0:f97b1f255167 74 0x01, /* bNumDescriptors */
llumpu 0:f97b1f255167 75 REPORT_DESCRIPTOR, /* bDescriptorType */
llumpu 0:f97b1f255167 76 0x79, /* wDescriptorLength (LSB) */
llumpu 0:f97b1f255167 77 0x00, /* wDescriptorLength (MSB) */
llumpu 0:f97b1f255167 78
llumpu 0:f97b1f255167 79 0x07, /* bLength */
llumpu 0:f97b1f255167 80 ENDPOINT_DESCRIPTOR, /* bDescriptorType */
llumpu 0:f97b1f255167 81 0x81, /* bEndpointAddress */
llumpu 0:f97b1f255167 82 0x03, /* bmAttributes */
llumpu 0:f97b1f255167 83 MAX_PACKET_SIZE_EP1, /* wMaxPacketSize (LSB) */
llumpu 0:f97b1f255167 84 0x00, /* wMaxPacketSize (MSB) */
llumpu 0:f97b1f255167 85 0x0a, /* bInterval */
llumpu 0:f97b1f255167 86 };
llumpu 0:f97b1f255167 87
llumpu 0:f97b1f255167 88 unsigned char stringLangidDescriptor[] = {
llumpu 0:f97b1f255167 89 0x04, /*bLength - must match size of stringLangidDescriptor array (always 4 bytes - hex 0x04) */
llumpu 0:f97b1f255167 90 STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
llumpu 0:f97b1f255167 91 0x09,0x00, /*bString Lang ID - 0x009 - English*/
llumpu 0:f97b1f255167 92 };
llumpu 0:f97b1f255167 93
llumpu 0:f97b1f255167 94 unsigned char stringImanufacturerDescriptor[] = {
llumpu 0:f97b1f255167 95 0x12, /*bLength must match size of stringImanufacturerDescriptor array (here 18 bytes - hex 0x12) */
llumpu 0:f97b1f255167 96 STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
llumpu 0:f97b1f255167 97 'm',0,'b',0,'e',0,'d',0,'.',0,'o',0,'r',0,'g',0, /*bString iManufacturer - mbed.org*/
llumpu 0:f97b1f255167 98 };
llumpu 0:f97b1f255167 99
llumpu 0:f97b1f255167 100 unsigned char stringIproductDescriptor[] = {
llumpu 0:f97b1f255167 101 0x12, /*bLength must match size of stringIproductDescriptor array (here 18 bytes - hex 0x12) */
llumpu 0:f97b1f255167 102 STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
llumpu 0:f97b1f255167 103 'm',0,'b',0,'e',0,'d',0,' ',0,'H',0,'I',0,'D',0, /*bString iProduct - mbed HID*/
llumpu 0:f97b1f255167 104 };
llumpu 0:f97b1f255167 105
llumpu 0:f97b1f255167 106 unsigned char stringIserialDescriptor[] = {
llumpu 0:f97b1f255167 107 0x16, /*bLength must match size of stringIserialDescriptor array (here 22 bytes - hex 0x16) */
llumpu 0:f97b1f255167 108 STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
llumpu 0:f97b1f255167 109 '0',0,'1',0,'2',0,'3',0,'4',0,'5',0,'6',0,'7',0,'8',0,'9',0, /*bString iSerial - 0123456789*/
llumpu 0:f97b1f255167 110 };
llumpu 0:f97b1f255167 111
llumpu 0:f97b1f255167 112 unsigned char stringIconfigurationDescriptor[] = {
llumpu 0:f97b1f255167 113 0x06, /*bLength must match size of stringIconfigurationDescriptor array (here 6 bytes - hex 0x06) */
llumpu 0:f97b1f255167 114 STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
llumpu 0:f97b1f255167 115 '0',0,'1',0, /*bString iConfiguration - 01*/
llumpu 0:f97b1f255167 116 };
llumpu 0:f97b1f255167 117
llumpu 0:f97b1f255167 118 unsigned char stringIinterfaceDescriptor[] = {
llumpu 0:f97b1f255167 119 0x08, /*bLength must match size of stringIinterfaceDescriptor array (here 8 bytes - hex 0x08) */
llumpu 0:f97b1f255167 120 STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
llumpu 0:f97b1f255167 121 'H',0,'I',0,'D',0, /*bString iInterface - HID*/
llumpu 0:f97b1f255167 122 };
llumpu 0:f97b1f255167 123
llumpu 0:f97b1f255167 124 /* HID Class Report Descriptor */
llumpu 0:f97b1f255167 125 /* Short items: size is 0, 1, 2 or 3 specifying 0, 1, 2 or 4 (four) bytes of data as per HID Class standard */
llumpu 0:f97b1f255167 126
llumpu 0:f97b1f255167 127 /* Main items */
llumpu 0:f97b1f255167 128 #define INPUT(size) (0x80 | size)
llumpu 0:f97b1f255167 129 #define OUTPUT(size) (0x90 | size)
llumpu 0:f97b1f255167 130 #define FEATURE(size) (0xb0 | size)
llumpu 0:f97b1f255167 131 #define COLLECTION(size) (0xa0 | size)
llumpu 0:f97b1f255167 132 #define END_COLLECTION(size) (0xc0 | size)
llumpu 0:f97b1f255167 133
llumpu 0:f97b1f255167 134 /* Global items */
llumpu 0:f97b1f255167 135 #define USAGE_PAGE(size) (0x04 | size)
llumpu 0:f97b1f255167 136 #define LOGICAL_MIN(size) (0x14 | size)
llumpu 0:f97b1f255167 137 #define LOGICAL_MAX(size) (0x24 | size)
llumpu 0:f97b1f255167 138 #define PHYSICAL_MIN(size) (0x34 | size)
llumpu 0:f97b1f255167 139 #define PHYSICAL_MAX(size) (0x44 | size)
llumpu 0:f97b1f255167 140 #define UNIT_EXPONENT(size) (0x54 | size)
llumpu 0:f97b1f255167 141 #define UNIT(size) (0x64 | size)
llumpu 0:f97b1f255167 142 #define REPORT_SIZE(size) (0x74 | size)
llumpu 0:f97b1f255167 143 #define REPORT_ID(size) (0x84 | size)
llumpu 0:f97b1f255167 144 #define REPORT_COUNT(size) (0x94 | size)
llumpu 0:f97b1f255167 145 #define PUSH(size) (0xa4 | size)
llumpu 0:f97b1f255167 146 #define POP(size) (0xb4 | size)
llumpu 0:f97b1f255167 147
llumpu 0:f97b1f255167 148 /* Local items */
llumpu 0:f97b1f255167 149 #define USAGE(size) (0x08 | size)
llumpu 0:f97b1f255167 150 #define USAGE_MIN(size) (0x18 | size)
llumpu 0:f97b1f255167 151 #define USAGE_MAX(size) (0x28 | size)
llumpu 0:f97b1f255167 152 #define DESIGNATOR_INDEX(size) (0x38 | size)
llumpu 0:f97b1f255167 153 #define DESIGNATOR_MIN(size) (0x48 | size)
llumpu 0:f97b1f255167 154 #define DESIGNATOR_MAX(size) (0x58 | size)
llumpu 0:f97b1f255167 155 #define STRING_INDEX(size) (0x78 | size)
llumpu 0:f97b1f255167 156 #define STRING_MIN(size) (0x88 | size)
llumpu 0:f97b1f255167 157 #define STRING_MAX(size) (0x98 | size)
llumpu 0:f97b1f255167 158 #define DELIMITER(size) (0xa8 | size)
llumpu 0:f97b1f255167 159
llumpu 0:f97b1f255167 160 #define REPORT_ID_KEYBOARD (1)
llumpu 0:f97b1f255167 161 #define REPORT_ID_MOUSE (2)
llumpu 0:f97b1f255167 162
llumpu 0:f97b1f255167 163 #define MAX_REPORT_SIZE (8)
llumpu 0:f97b1f255167 164
llumpu 0:f97b1f255167 165 unsigned char reportDescriptor[] = {
llumpu 0:f97b1f255167 166 /* Keyboard */
llumpu 0:f97b1f255167 167 USAGE_PAGE(1), 0x01,
llumpu 0:f97b1f255167 168 USAGE(1), 0x06,
llumpu 0:f97b1f255167 169 COLLECTION(1), 0x01,
llumpu 0:f97b1f255167 170 REPORT_ID(1), REPORT_ID_KEYBOARD,
llumpu 0:f97b1f255167 171 USAGE_PAGE(1), 0x07,
llumpu 0:f97b1f255167 172 USAGE_MIN(1), 0xE0,
llumpu 0:f97b1f255167 173 USAGE_MAX(1), 0xE7,
llumpu 0:f97b1f255167 174 LOGICAL_MIN(1), 0x00,
llumpu 0:f97b1f255167 175 LOGICAL_MAX(1), 0x01,
llumpu 0:f97b1f255167 176 REPORT_SIZE(1), 0x01,
llumpu 0:f97b1f255167 177 REPORT_COUNT(1), 0x08,
llumpu 0:f97b1f255167 178 INPUT(1), 0x02,
llumpu 0:f97b1f255167 179 REPORT_COUNT(1), 0x01,
llumpu 0:f97b1f255167 180 REPORT_SIZE(1), 0x08,
llumpu 0:f97b1f255167 181 INPUT(1), 0x01,
llumpu 0:f97b1f255167 182 REPORT_COUNT(1), 0x05,
llumpu 0:f97b1f255167 183 REPORT_SIZE(1), 0x01,
llumpu 0:f97b1f255167 184 USAGE_PAGE(1), 0x08,
llumpu 0:f97b1f255167 185 USAGE_MIN(1), 0x01,
llumpu 0:f97b1f255167 186 USAGE_MAX(1), 0x05,
llumpu 0:f97b1f255167 187 OUTPUT(1), 0x02,
llumpu 0:f97b1f255167 188 REPORT_COUNT(1), 0x01,
llumpu 0:f97b1f255167 189 REPORT_SIZE(1), 0x03,
llumpu 0:f97b1f255167 190 OUTPUT(1), 0x01,
llumpu 0:f97b1f255167 191 REPORT_COUNT(1), 0x06,
llumpu 0:f97b1f255167 192 REPORT_SIZE(1), 0x08,
llumpu 0:f97b1f255167 193 LOGICAL_MIN(1), 0x00,
llumpu 0:f97b1f255167 194 LOGICAL_MAX(2), 0xff, 0x00,
llumpu 0:f97b1f255167 195 USAGE_PAGE(1), 0x07,
llumpu 0:f97b1f255167 196 USAGE_MIN(1), 0x00,
llumpu 0:f97b1f255167 197 USAGE_MAX(2), 0xff, 0x00,
llumpu 0:f97b1f255167 198 INPUT(1), 0x00,
llumpu 0:f97b1f255167 199 END_COLLECTION(0),
llumpu 0:f97b1f255167 200
llumpu 0:f97b1f255167 201 /* Mouse */
llumpu 0:f97b1f255167 202 USAGE_PAGE(1), 0x01,
llumpu 0:f97b1f255167 203 USAGE(1), 0x02,
llumpu 0:f97b1f255167 204 COLLECTION(1), 0x01,
llumpu 0:f97b1f255167 205 USAGE(1), 0x01,
llumpu 0:f97b1f255167 206 COLLECTION(1), 0x00,
llumpu 0:f97b1f255167 207 REPORT_ID(1), REPORT_ID_MOUSE,
llumpu 0:f97b1f255167 208 REPORT_COUNT(1), 0x03,
llumpu 0:f97b1f255167 209 REPORT_SIZE(1), 0x01,
llumpu 0:f97b1f255167 210 USAGE_PAGE(1), 0x09,
llumpu 0:f97b1f255167 211 USAGE_MIN(1), 0x1,
llumpu 0:f97b1f255167 212 USAGE_MAX(1), 0x3,
llumpu 0:f97b1f255167 213 LOGICAL_MIN(1), 0x00,
llumpu 0:f97b1f255167 214 LOGICAL_MAX(1), 0x01,
llumpu 0:f97b1f255167 215 INPUT(1), 0x02,
llumpu 0:f97b1f255167 216 REPORT_COUNT(1), 0x01,
llumpu 0:f97b1f255167 217 REPORT_SIZE(1), 0x05,
llumpu 0:f97b1f255167 218 INPUT(1), 0x01,
llumpu 0:f97b1f255167 219 REPORT_COUNT(1), 0x03,
llumpu 0:f97b1f255167 220 REPORT_SIZE(1), 0x08,
llumpu 0:f97b1f255167 221 USAGE_PAGE(1), 0x01,
llumpu 0:f97b1f255167 222 USAGE(1), 0x30,
llumpu 0:f97b1f255167 223 USAGE(1), 0x31,
llumpu 0:f97b1f255167 224 USAGE(1), 0x38,
llumpu 0:f97b1f255167 225 LOGICAL_MIN(1), 0x81,
llumpu 0:f97b1f255167 226 LOGICAL_MAX(1), 0x7f,
llumpu 0:f97b1f255167 227 INPUT(1), 0x06,
llumpu 0:f97b1f255167 228 END_COLLECTION(0),
llumpu 0:f97b1f255167 229 END_COLLECTION(0),
llumpu 0:f97b1f255167 230 };
llumpu 0:f97b1f255167 231
llumpu 0:f97b1f255167 232 volatile bool complete;
llumpu 0:f97b1f255167 233 volatile bool configured;
llumpu 0:f97b1f255167 234 unsigned char outputReport[MAX_REPORT_SIZE];
llumpu 0:f97b1f255167 235
llumpu 0:f97b1f255167 236 usbhid::usbhid()
llumpu 0:f97b1f255167 237 {
llumpu 0:f97b1f255167 238 configured = false;
llumpu 0:f97b1f255167 239 connect();
llumpu 0:f97b1f255167 240 }
llumpu 0:f97b1f255167 241
llumpu 0:f97b1f255167 242 void usbhid::deviceEventReset()
llumpu 0:f97b1f255167 243 {
llumpu 0:f97b1f255167 244 configured = false;
llumpu 0:f97b1f255167 245
llumpu 0:f97b1f255167 246 /* Must call base class */
llumpu 0:f97b1f255167 247 usbdevice::deviceEventReset();
llumpu 0:f97b1f255167 248 }
llumpu 0:f97b1f255167 249
llumpu 0:f97b1f255167 250 bool usbhid::requestSetConfiguration(void)
llumpu 0:f97b1f255167 251 {
llumpu 0:f97b1f255167 252 bool result;
llumpu 0:f97b1f255167 253
llumpu 0:f97b1f255167 254 /* Configure IN interrupt endpoint */
llumpu 0:f97b1f255167 255 realiseEndpoint(EP1IN, MAX_PACKET_SIZE_EP1);
llumpu 0:f97b1f255167 256 enableEndpointEvent(EP1IN);
llumpu 0:f97b1f255167 257
llumpu 0:f97b1f255167 258 /* Must call base class */
llumpu 0:f97b1f255167 259 result = usbdevice::requestSetConfiguration();
llumpu 0:f97b1f255167 260
llumpu 0:f97b1f255167 261 if (result)
llumpu 0:f97b1f255167 262 {
llumpu 0:f97b1f255167 263 /* Now configured */
llumpu 0:f97b1f255167 264 configured = true;
llumpu 0:f97b1f255167 265 }
llumpu 0:f97b1f255167 266
llumpu 0:f97b1f255167 267 return result;
llumpu 0:f97b1f255167 268 }
llumpu 0:f97b1f255167 269
llumpu 0:f97b1f255167 270 bool usbhid::requestGetDescriptor(void)
llumpu 0:f97b1f255167 271 {
llumpu 0:f97b1f255167 272 bool success = false;
llumpu 0:f97b1f255167 273
llumpu 0:f97b1f255167 274 switch (DESCRIPTOR_TYPE(transfer.setup.wValue))
llumpu 0:f97b1f255167 275 {
llumpu 0:f97b1f255167 276 case DEVICE_DESCRIPTOR:
llumpu 0:f97b1f255167 277 transfer.remaining = sizeof(deviceDescriptor);
llumpu 0:f97b1f255167 278 transfer.ptr = deviceDescriptor;
llumpu 0:f97b1f255167 279 transfer.direction = DEVICE_TO_HOST;
llumpu 0:f97b1f255167 280 success = true;
llumpu 0:f97b1f255167 281 break;
llumpu 0:f97b1f255167 282 case CONFIGURATION_DESCRIPTOR:
llumpu 0:f97b1f255167 283 transfer.remaining = sizeof(configurationDescriptor);
llumpu 0:f97b1f255167 284 transfer.ptr = configurationDescriptor;
llumpu 0:f97b1f255167 285 transfer.direction = DEVICE_TO_HOST;
llumpu 0:f97b1f255167 286 success = true;
llumpu 0:f97b1f255167 287 break;
llumpu 0:f97b1f255167 288 case STRING_DESCRIPTOR:
llumpu 0:f97b1f255167 289 switch (DESCRIPTOR_INDEX(transfer.setup.wValue))
llumpu 0:f97b1f255167 290 {
llumpu 0:f97b1f255167 291 case STRING_OFFSET_LANGID:
llumpu 0:f97b1f255167 292 transfer.remaining = sizeof(stringLangidDescriptor);
llumpu 0:f97b1f255167 293 transfer.ptr = stringLangidDescriptor;
llumpu 0:f97b1f255167 294 transfer.direction = DEVICE_TO_HOST;
llumpu 0:f97b1f255167 295 success = true;
llumpu 0:f97b1f255167 296 break;
llumpu 0:f97b1f255167 297 case STRING_OFFSET_IMANUFACTURER:
llumpu 0:f97b1f255167 298 transfer.remaining = sizeof(stringImanufacturerDescriptor);
llumpu 0:f97b1f255167 299 transfer.ptr = stringImanufacturerDescriptor;
llumpu 0:f97b1f255167 300 transfer.direction = DEVICE_TO_HOST;
llumpu 0:f97b1f255167 301 success = true;
llumpu 0:f97b1f255167 302 break;
llumpu 0:f97b1f255167 303 case STRING_OFFSET_IPRODUCT:
llumpu 0:f97b1f255167 304 transfer.remaining = sizeof(stringIproductDescriptor);
llumpu 0:f97b1f255167 305 transfer.ptr = stringIproductDescriptor;
llumpu 0:f97b1f255167 306 transfer.direction = DEVICE_TO_HOST;
llumpu 0:f97b1f255167 307 success = true;
llumpu 0:f97b1f255167 308 break;
llumpu 0:f97b1f255167 309 case STRING_OFFSET_ISERIAL:
llumpu 0:f97b1f255167 310 transfer.remaining = sizeof(stringIserialDescriptor);
llumpu 0:f97b1f255167 311 transfer.ptr = stringIserialDescriptor;
llumpu 0:f97b1f255167 312 transfer.direction = DEVICE_TO_HOST;
llumpu 0:f97b1f255167 313 success = true;
llumpu 0:f97b1f255167 314 break;
llumpu 0:f97b1f255167 315 case STRING_OFFSET_ICONFIGURATION:
llumpu 0:f97b1f255167 316 transfer.remaining = sizeof(stringIconfigurationDescriptor);
llumpu 0:f97b1f255167 317 transfer.ptr = stringIconfigurationDescriptor;
llumpu 0:f97b1f255167 318 transfer.direction = DEVICE_TO_HOST;
llumpu 0:f97b1f255167 319 success = true;
llumpu 0:f97b1f255167 320 break;
llumpu 0:f97b1f255167 321 case STRING_OFFSET_IINTERFACE:
llumpu 0:f97b1f255167 322 transfer.remaining = sizeof(stringIinterfaceDescriptor);
llumpu 0:f97b1f255167 323 transfer.ptr = stringIinterfaceDescriptor;
llumpu 0:f97b1f255167 324 transfer.direction = DEVICE_TO_HOST;
llumpu 0:f97b1f255167 325 success = true;
llumpu 0:f97b1f255167 326 break;
llumpu 0:f97b1f255167 327 }
llumpu 0:f97b1f255167 328 case INTERFACE_DESCRIPTOR:
llumpu 0:f97b1f255167 329 case ENDPOINT_DESCRIPTOR:
llumpu 0:f97b1f255167 330 /* TODO: Support is optional, not implemented here */
llumpu 0:f97b1f255167 331 break;
llumpu 0:f97b1f255167 332 case HID_DESCRIPTOR:
llumpu 0:f97b1f255167 333 transfer.remaining = 0x09; /* TODO: Fix hard coded size/offset */
llumpu 0:f97b1f255167 334 transfer.ptr = &configurationDescriptor[18];
llumpu 0:f97b1f255167 335 transfer.direction = DEVICE_TO_HOST;
llumpu 0:f97b1f255167 336 success = true;
llumpu 0:f97b1f255167 337 break;
llumpu 0:f97b1f255167 338 case REPORT_DESCRIPTOR:
llumpu 0:f97b1f255167 339 transfer.remaining = sizeof(reportDescriptor);
llumpu 0:f97b1f255167 340 transfer.ptr = reportDescriptor;
llumpu 0:f97b1f255167 341 transfer.direction = DEVICE_TO_HOST;
llumpu 0:f97b1f255167 342 success = true;
llumpu 0:f97b1f255167 343 break;
llumpu 0:f97b1f255167 344 default:
llumpu 0:f97b1f255167 345 break;
llumpu 0:f97b1f255167 346 }
llumpu 0:f97b1f255167 347
llumpu 0:f97b1f255167 348 return success;
llumpu 0:f97b1f255167 349 }
llumpu 0:f97b1f255167 350
llumpu 0:f97b1f255167 351 bool usbhid::requestSetup(void)
llumpu 0:f97b1f255167 352 {
llumpu 0:f97b1f255167 353 /* Process class requests */
llumpu 0:f97b1f255167 354 bool success = false;
llumpu 0:f97b1f255167 355
llumpu 0:f97b1f255167 356 if (transfer.setup.bmRequestType.Type == CLASS_TYPE)
llumpu 0:f97b1f255167 357 {
llumpu 0:f97b1f255167 358 switch (transfer.setup.bRequest)
llumpu 0:f97b1f255167 359 {
llumpu 0:f97b1f255167 360 case SET_REPORT:
llumpu 0:f97b1f255167 361 switch (transfer.setup.wValue & 0xff)
llumpu 0:f97b1f255167 362 {
llumpu 0:f97b1f255167 363 case REPORT_ID_KEYBOARD:
llumpu 0:f97b1f255167 364 /* TODO: LED state */
llumpu 0:f97b1f255167 365 transfer.remaining = sizeof(outputReport);
llumpu 0:f97b1f255167 366 transfer.ptr = outputReport;
llumpu 0:f97b1f255167 367 transfer.direction = HOST_TO_DEVICE;
llumpu 0:f97b1f255167 368 success = true;
llumpu 0:f97b1f255167 369 break;
llumpu 0:f97b1f255167 370 default:
llumpu 0:f97b1f255167 371 break;
llumpu 0:f97b1f255167 372 }
llumpu 0:f97b1f255167 373 break;
llumpu 0:f97b1f255167 374 default:
llumpu 0:f97b1f255167 375 break;
llumpu 0:f97b1f255167 376 }
llumpu 0:f97b1f255167 377 }
llumpu 0:f97b1f255167 378
llumpu 0:f97b1f255167 379 if (success)
llumpu 0:f97b1f255167 380 {
llumpu 0:f97b1f255167 381 /* We've handled this request */
llumpu 0:f97b1f255167 382 return true;
llumpu 0:f97b1f255167 383 }
llumpu 0:f97b1f255167 384
llumpu 0:f97b1f255167 385 return usbdevice::requestSetup();
llumpu 0:f97b1f255167 386 }
llumpu 0:f97b1f255167 387
llumpu 0:f97b1f255167 388 bool usbhid::sendInputReport(unsigned char id, unsigned char *data, unsigned char size)
llumpu 0:f97b1f255167 389 {
llumpu 0:f97b1f255167 390 /* Send an Input Report */
llumpu 0:f97b1f255167 391 /* If data is NULL an all zero report is sent */
llumpu 0:f97b1f255167 392
llumpu 0:f97b1f255167 393 static unsigned char report[MAX_REPORT_SIZE+1]; /* +1 for report ID */
llumpu 0:f97b1f255167 394 unsigned char i;
llumpu 0:f97b1f255167 395
llumpu 0:f97b1f255167 396 if (size > MAX_REPORT_SIZE)
llumpu 0:f97b1f255167 397 {
llumpu 0:f97b1f255167 398 return false;
llumpu 0:f97b1f255167 399 }
llumpu 0:f97b1f255167 400
llumpu 0:f97b1f255167 401 /* Add report ID */
llumpu 0:f97b1f255167 402 report[0]=id;
llumpu 0:f97b1f255167 403
llumpu 0:f97b1f255167 404 /* Add report data */
llumpu 0:f97b1f255167 405 if (data != NULL)
llumpu 0:f97b1f255167 406 {
llumpu 0:f97b1f255167 407 for (i=0; i<size; i++)
llumpu 0:f97b1f255167 408 {
llumpu 0:f97b1f255167 409 report[i+1] = *data++;
llumpu 0:f97b1f255167 410 }
llumpu 0:f97b1f255167 411 }
llumpu 0:f97b1f255167 412 else
llumpu 0:f97b1f255167 413 {
llumpu 0:f97b1f255167 414 for (i=0; i<size; i++)
llumpu 0:f97b1f255167 415 {
llumpu 0:f97b1f255167 416 report[i+1] = 0;
llumpu 0:f97b1f255167 417 }
llumpu 0:f97b1f255167 418 }
llumpu 0:f97b1f255167 419
llumpu 0:f97b1f255167 420 /* Block if not configured */
llumpu 0:f97b1f255167 421 while (!configured);
llumpu 0:f97b1f255167 422
llumpu 0:f97b1f255167 423 /* Send report */
llumpu 0:f97b1f255167 424 complete = false;
llumpu 0:f97b1f255167 425 disableEvents();
llumpu 0:f97b1f255167 426 endpointWrite(EP1IN, report, size+1); /* +1 for report ID */
llumpu 0:f97b1f255167 427 enableEvents();
llumpu 0:f97b1f255167 428
llumpu 0:f97b1f255167 429 /* Wait for completion */
llumpu 0:f97b1f255167 430 while(!complete && configured);
llumpu 0:f97b1f255167 431 return true;
llumpu 0:f97b1f255167 432 }
llumpu 0:f97b1f255167 433
llumpu 0:f97b1f255167 434 void usbhid::endpointEventEP1In(void)
llumpu 0:f97b1f255167 435 {
llumpu 0:f97b1f255167 436 complete = true;
llumpu 0:f97b1f255167 437 }
llumpu 0:f97b1f255167 438
llumpu 0:f97b1f255167 439 bool usbhid::keyboard(char c)
llumpu 0:f97b1f255167 440 {
llumpu 0:f97b1f255167 441 /* Send a simulated keyboard keypress. Returns true if successful. */
llumpu 0:f97b1f255167 442 unsigned char report[8]={0,0,0,0,0,0,0,0};
llumpu 0:f97b1f255167 443
llumpu 0:f97b1f255167 444 report[0] = keymap[c].modifier;
llumpu 0:f97b1f255167 445 report[2] = keymap[c].usage;
llumpu 0:f97b1f255167 446
llumpu 0:f97b1f255167 447 /* Key down */
llumpu 0:f97b1f255167 448 if (!sendInputReport(REPORT_ID_KEYBOARD, report, 8))
llumpu 0:f97b1f255167 449 {
llumpu 0:f97b1f255167 450 return false;
llumpu 0:f97b1f255167 451 }
llumpu 0:f97b1f255167 452
llumpu 0:f97b1f255167 453 /* Key up */
llumpu 0:f97b1f255167 454 if (!sendInputReport(REPORT_ID_KEYBOARD, NULL, 8))
llumpu 0:f97b1f255167 455 {
llumpu 0:f97b1f255167 456 return false;
llumpu 0:f97b1f255167 457 }
llumpu 0:f97b1f255167 458
llumpu 0:f97b1f255167 459 return true;
llumpu 0:f97b1f255167 460 }
llumpu 0:f97b1f255167 461
llumpu 0:f97b1f255167 462 bool usbhid::keyboard(char *string)
llumpu 0:f97b1f255167 463 {
llumpu 0:f97b1f255167 464 /* Send a string of characters. Returns true if successful. */
llumpu 0:f97b1f255167 465 do {
llumpu 0:f97b1f255167 466 if (!keyboard(*string++))
llumpu 0:f97b1f255167 467 {
llumpu 0:f97b1f255167 468 return false;
llumpu 0:f97b1f255167 469 }
llumpu 0:f97b1f255167 470 } while (*string != '\0');
llumpu 0:f97b1f255167 471
llumpu 0:f97b1f255167 472 return true;
llumpu 0:f97b1f255167 473 }
llumpu 0:f97b1f255167 474
llumpu 0:f97b1f255167 475 bool usbhid::mouse(signed char x, signed char y, unsigned char buttons, signed char wheel)
llumpu 0:f97b1f255167 476 {
llumpu 0:f97b1f255167 477 /* Send a simulated mouse event. Returns true if successful. */
llumpu 0:f97b1f255167 478 unsigned char report[4]={0,0,0,0};
llumpu 0:f97b1f255167 479
llumpu 0:f97b1f255167 480 report[0] = buttons;
llumpu 0:f97b1f255167 481 report[1] = x;
llumpu 0:f97b1f255167 482 report[2] = y;
llumpu 0:f97b1f255167 483 report[3] = wheel;
llumpu 0:f97b1f255167 484
llumpu 0:f97b1f255167 485 if (!sendInputReport(REPORT_ID_MOUSE, report, 4))
llumpu 0:f97b1f255167 486 {
llumpu 0:f97b1f255167 487 return false;
llumpu 0:f97b1f255167 488 }
llumpu 0:f97b1f255167 489
llumpu 0:f97b1f255167 490 return true;
llumpu 0:f97b1f255167 491 }