USBDevice

Dependents:   QEI_X1_LCD_test3 macnica_test

Committer:
toucyy
Date:
Thu Apr 18 07:49:37 2013 +0000
Revision:
0:2d8d0b73e1ff
[mbed] converted /QEI_HelloWorld/USBDevice

Who changed what in which revision?

UserRevisionLine numberNew contents of line
toucyy 0:2d8d0b73e1ff 1 // USBHID.c
toucyy 0:2d8d0b73e1ff 2 // Human Interface Device (HID) class
toucyy 0:2d8d0b73e1ff 3 // Copyright (c) 2011 ARM Limited. All rights reserved.
toucyy 0:2d8d0b73e1ff 4
toucyy 0:2d8d0b73e1ff 5 #include "stdint.h"
toucyy 0:2d8d0b73e1ff 6 #include "USBBusInterface.h"
toucyy 0:2d8d0b73e1ff 7 #include "USBHID.h"
toucyy 0:2d8d0b73e1ff 8
toucyy 0:2d8d0b73e1ff 9
toucyy 0:2d8d0b73e1ff 10 USBHID::USBHID(uint8_t output_report_length, uint8_t input_report_length, uint16_t vendor_id, uint16_t product_id, uint16_t product_release, bool connect): USBDevice(vendor_id, product_id, product_release)
toucyy 0:2d8d0b73e1ff 11 {
toucyy 0:2d8d0b73e1ff 12 output_length = output_report_length;
toucyy 0:2d8d0b73e1ff 13 input_length = input_report_length;
toucyy 0:2d8d0b73e1ff 14 if(connect) {
toucyy 0:2d8d0b73e1ff 15 USBDevice::connect();
toucyy 0:2d8d0b73e1ff 16 }
toucyy 0:2d8d0b73e1ff 17 }
toucyy 0:2d8d0b73e1ff 18
toucyy 0:2d8d0b73e1ff 19
toucyy 0:2d8d0b73e1ff 20 bool USBHID::send(HID_REPORT *report)
toucyy 0:2d8d0b73e1ff 21 {
toucyy 0:2d8d0b73e1ff 22 return write(EPINT_IN, report->data, report->length, MAX_HID_REPORT_SIZE);
toucyy 0:2d8d0b73e1ff 23 }
toucyy 0:2d8d0b73e1ff 24
toucyy 0:2d8d0b73e1ff 25 bool USBHID::sendNB(HID_REPORT *report)
toucyy 0:2d8d0b73e1ff 26 {
toucyy 0:2d8d0b73e1ff 27 return writeNB(EPINT_IN, report->data, report->length, MAX_HID_REPORT_SIZE);
toucyy 0:2d8d0b73e1ff 28 }
toucyy 0:2d8d0b73e1ff 29
toucyy 0:2d8d0b73e1ff 30
toucyy 0:2d8d0b73e1ff 31 bool USBHID::read(HID_REPORT *report)
toucyy 0:2d8d0b73e1ff 32 {
toucyy 0:2d8d0b73e1ff 33 uint16_t bytesRead = 0;
toucyy 0:2d8d0b73e1ff 34 bool result;
toucyy 0:2d8d0b73e1ff 35 result = USBDevice::readEP(EPINT_OUT, report->data, &bytesRead, MAX_HID_REPORT_SIZE);
toucyy 0:2d8d0b73e1ff 36 if(!readStart(EPINT_OUT, MAX_HID_REPORT_SIZE))
toucyy 0:2d8d0b73e1ff 37 return false;
toucyy 0:2d8d0b73e1ff 38 report->length = bytesRead;
toucyy 0:2d8d0b73e1ff 39 return result;
toucyy 0:2d8d0b73e1ff 40 }
toucyy 0:2d8d0b73e1ff 41
toucyy 0:2d8d0b73e1ff 42
toucyy 0:2d8d0b73e1ff 43 bool USBHID::readNB(HID_REPORT *report)
toucyy 0:2d8d0b73e1ff 44 {
toucyy 0:2d8d0b73e1ff 45 uint16_t bytesRead = 0;
toucyy 0:2d8d0b73e1ff 46 bool result;
toucyy 0:2d8d0b73e1ff 47 result = USBDevice::readEP_NB(EPINT_OUT, report->data, &bytesRead, MAX_HID_REPORT_SIZE);
toucyy 0:2d8d0b73e1ff 48 report->length = bytesRead;
toucyy 0:2d8d0b73e1ff 49 if(!readStart(EPINT_OUT, MAX_HID_REPORT_SIZE))
toucyy 0:2d8d0b73e1ff 50 return false;
toucyy 0:2d8d0b73e1ff 51 return result;
toucyy 0:2d8d0b73e1ff 52 }
toucyy 0:2d8d0b73e1ff 53
toucyy 0:2d8d0b73e1ff 54
toucyy 0:2d8d0b73e1ff 55 uint16_t USBHID::reportDescLength() {
toucyy 0:2d8d0b73e1ff 56 reportDesc();
toucyy 0:2d8d0b73e1ff 57 return reportLength;
toucyy 0:2d8d0b73e1ff 58 }
toucyy 0:2d8d0b73e1ff 59
toucyy 0:2d8d0b73e1ff 60
toucyy 0:2d8d0b73e1ff 61
toucyy 0:2d8d0b73e1ff 62 //
toucyy 0:2d8d0b73e1ff 63 // Route callbacks from lower layers to class(es)
toucyy 0:2d8d0b73e1ff 64 //
toucyy 0:2d8d0b73e1ff 65
toucyy 0:2d8d0b73e1ff 66
toucyy 0:2d8d0b73e1ff 67 // Called in ISR context
toucyy 0:2d8d0b73e1ff 68 // Called by USBDevice on Endpoint0 request
toucyy 0:2d8d0b73e1ff 69 // This is used to handle extensions to standard requests
toucyy 0:2d8d0b73e1ff 70 // and class specific requests
toucyy 0:2d8d0b73e1ff 71 // Return true if class handles this request
toucyy 0:2d8d0b73e1ff 72 bool USBHID::USBCallback_request() {
toucyy 0:2d8d0b73e1ff 73 bool success = false;
toucyy 0:2d8d0b73e1ff 74 CONTROL_TRANSFER * transfer = getTransferPtr();
toucyy 0:2d8d0b73e1ff 75 uint8_t *hidDescriptor;
toucyy 0:2d8d0b73e1ff 76
toucyy 0:2d8d0b73e1ff 77 // Process additional standard requests
toucyy 0:2d8d0b73e1ff 78
toucyy 0:2d8d0b73e1ff 79 if ((transfer->setup.bmRequestType.Type == STANDARD_TYPE))
toucyy 0:2d8d0b73e1ff 80 {
toucyy 0:2d8d0b73e1ff 81 switch (transfer->setup.bRequest)
toucyy 0:2d8d0b73e1ff 82 {
toucyy 0:2d8d0b73e1ff 83 case GET_DESCRIPTOR:
toucyy 0:2d8d0b73e1ff 84 switch (DESCRIPTOR_TYPE(transfer->setup.wValue))
toucyy 0:2d8d0b73e1ff 85 {
toucyy 0:2d8d0b73e1ff 86 case REPORT_DESCRIPTOR:
toucyy 0:2d8d0b73e1ff 87 if ((reportDesc() != NULL) \
toucyy 0:2d8d0b73e1ff 88 && (reportDescLength() != 0))
toucyy 0:2d8d0b73e1ff 89 {
toucyy 0:2d8d0b73e1ff 90 transfer->remaining = reportDescLength();
toucyy 0:2d8d0b73e1ff 91 transfer->ptr = reportDesc();
toucyy 0:2d8d0b73e1ff 92 transfer->direction = DEVICE_TO_HOST;
toucyy 0:2d8d0b73e1ff 93 success = true;
toucyy 0:2d8d0b73e1ff 94 }
toucyy 0:2d8d0b73e1ff 95 break;
toucyy 0:2d8d0b73e1ff 96 case HID_DESCRIPTOR:
toucyy 0:2d8d0b73e1ff 97 // Find the HID descriptor, after the configuration descriptor
toucyy 0:2d8d0b73e1ff 98 hidDescriptor = findDescriptor(HID_DESCRIPTOR);
toucyy 0:2d8d0b73e1ff 99 if (hidDescriptor != NULL)
toucyy 0:2d8d0b73e1ff 100 {
toucyy 0:2d8d0b73e1ff 101 transfer->remaining = HID_DESCRIPTOR_LENGTH;
toucyy 0:2d8d0b73e1ff 102 transfer->ptr = hidDescriptor;
toucyy 0:2d8d0b73e1ff 103 transfer->direction = DEVICE_TO_HOST;
toucyy 0:2d8d0b73e1ff 104 success = true;
toucyy 0:2d8d0b73e1ff 105 }
toucyy 0:2d8d0b73e1ff 106 break;
toucyy 0:2d8d0b73e1ff 107
toucyy 0:2d8d0b73e1ff 108 default:
toucyy 0:2d8d0b73e1ff 109 break;
toucyy 0:2d8d0b73e1ff 110 }
toucyy 0:2d8d0b73e1ff 111 break;
toucyy 0:2d8d0b73e1ff 112 default:
toucyy 0:2d8d0b73e1ff 113 break;
toucyy 0:2d8d0b73e1ff 114 }
toucyy 0:2d8d0b73e1ff 115 }
toucyy 0:2d8d0b73e1ff 116
toucyy 0:2d8d0b73e1ff 117 // Process class-specific requests
toucyy 0:2d8d0b73e1ff 118
toucyy 0:2d8d0b73e1ff 119 if (transfer->setup.bmRequestType.Type == CLASS_TYPE)
toucyy 0:2d8d0b73e1ff 120 {
toucyy 0:2d8d0b73e1ff 121 switch (transfer->setup.bRequest)
toucyy 0:2d8d0b73e1ff 122 {
toucyy 0:2d8d0b73e1ff 123 case SET_REPORT:
toucyy 0:2d8d0b73e1ff 124 // First byte will be used for report ID
toucyy 0:2d8d0b73e1ff 125 outputReport.data[0] = transfer->setup.wValue & 0xff;
toucyy 0:2d8d0b73e1ff 126 outputReport.length = transfer->setup.wLength + 1;
toucyy 0:2d8d0b73e1ff 127
toucyy 0:2d8d0b73e1ff 128 transfer->remaining = sizeof(outputReport.data) - 1;
toucyy 0:2d8d0b73e1ff 129 transfer->ptr = &outputReport.data[1];
toucyy 0:2d8d0b73e1ff 130 transfer->direction = HOST_TO_DEVICE;
toucyy 0:2d8d0b73e1ff 131 transfer->notify = true;
toucyy 0:2d8d0b73e1ff 132 success = true;
toucyy 0:2d8d0b73e1ff 133 default:
toucyy 0:2d8d0b73e1ff 134 break;
toucyy 0:2d8d0b73e1ff 135 }
toucyy 0:2d8d0b73e1ff 136 }
toucyy 0:2d8d0b73e1ff 137
toucyy 0:2d8d0b73e1ff 138 return success;
toucyy 0:2d8d0b73e1ff 139 }
toucyy 0:2d8d0b73e1ff 140
toucyy 0:2d8d0b73e1ff 141
toucyy 0:2d8d0b73e1ff 142 #define DEFAULT_CONFIGURATION (1)
toucyy 0:2d8d0b73e1ff 143
toucyy 0:2d8d0b73e1ff 144
toucyy 0:2d8d0b73e1ff 145 // Called in ISR context
toucyy 0:2d8d0b73e1ff 146 // Set configuration. Return false if the
toucyy 0:2d8d0b73e1ff 147 // configuration is not supported
toucyy 0:2d8d0b73e1ff 148 bool USBHID::USBCallback_setConfiguration(uint8_t configuration) {
toucyy 0:2d8d0b73e1ff 149 if (configuration != DEFAULT_CONFIGURATION) {
toucyy 0:2d8d0b73e1ff 150 return false;
toucyy 0:2d8d0b73e1ff 151 }
toucyy 0:2d8d0b73e1ff 152
toucyy 0:2d8d0b73e1ff 153 // Configure endpoints > 0
toucyy 0:2d8d0b73e1ff 154 addEndpoint(EPINT_IN, MAX_PACKET_SIZE_EPINT);
toucyy 0:2d8d0b73e1ff 155 addEndpoint(EPINT_OUT, MAX_PACKET_SIZE_EPINT);
toucyy 0:2d8d0b73e1ff 156
toucyy 0:2d8d0b73e1ff 157 // We activate the endpoint to be able to recceive data
toucyy 0:2d8d0b73e1ff 158 readStart(EPINT_OUT, MAX_PACKET_SIZE_EPINT);
toucyy 0:2d8d0b73e1ff 159 return true;
toucyy 0:2d8d0b73e1ff 160 }
toucyy 0:2d8d0b73e1ff 161
toucyy 0:2d8d0b73e1ff 162
toucyy 0:2d8d0b73e1ff 163 uint8_t * USBHID::stringIinterfaceDesc() {
toucyy 0:2d8d0b73e1ff 164 static uint8_t stringIinterfaceDescriptor[] = {
toucyy 0:2d8d0b73e1ff 165 0x08, //bLength
toucyy 0:2d8d0b73e1ff 166 STRING_DESCRIPTOR, //bDescriptorType 0x03
toucyy 0:2d8d0b73e1ff 167 'H',0,'I',0,'D',0, //bString iInterface - HID
toucyy 0:2d8d0b73e1ff 168 };
toucyy 0:2d8d0b73e1ff 169 return stringIinterfaceDescriptor;
toucyy 0:2d8d0b73e1ff 170 }
toucyy 0:2d8d0b73e1ff 171
toucyy 0:2d8d0b73e1ff 172 uint8_t * USBHID::stringIproductDesc() {
toucyy 0:2d8d0b73e1ff 173 static uint8_t stringIproductDescriptor[] = {
toucyy 0:2d8d0b73e1ff 174 0x16, //bLength
toucyy 0:2d8d0b73e1ff 175 STRING_DESCRIPTOR, //bDescriptorType 0x03
toucyy 0:2d8d0b73e1ff 176 'H',0,'I',0,'D',0,' ',0,'D',0,'E',0,'V',0,'I',0,'C',0,'E',0 //bString iProduct - HID device
toucyy 0:2d8d0b73e1ff 177 };
toucyy 0:2d8d0b73e1ff 178 return stringIproductDescriptor;
toucyy 0:2d8d0b73e1ff 179 }
toucyy 0:2d8d0b73e1ff 180
toucyy 0:2d8d0b73e1ff 181
toucyy 0:2d8d0b73e1ff 182
toucyy 0:2d8d0b73e1ff 183 uint8_t * USBHID::reportDesc() {
toucyy 0:2d8d0b73e1ff 184 static uint8_t reportDescriptor[] = {
toucyy 0:2d8d0b73e1ff 185 0x06, LSB(0xFFAB), MSB(0xFFAB),
toucyy 0:2d8d0b73e1ff 186 0x0A, LSB(0x0200), MSB(0x0200),
toucyy 0:2d8d0b73e1ff 187 0xA1, 0x01, // Collection 0x01
toucyy 0:2d8d0b73e1ff 188 0x75, 0x08, // report size = 8 bits
toucyy 0:2d8d0b73e1ff 189 0x15, 0x00, // logical minimum = 0
toucyy 0:2d8d0b73e1ff 190 0x26, 0xFF, 0x00, // logical maximum = 255
toucyy 0:2d8d0b73e1ff 191 0x95, input_length, // report count
toucyy 0:2d8d0b73e1ff 192 0x09, 0x01, // usage
toucyy 0:2d8d0b73e1ff 193 0x81, 0x02, // Input (array)
toucyy 0:2d8d0b73e1ff 194 0x95, output_length, // report count
toucyy 0:2d8d0b73e1ff 195 0x09, 0x02, // usage
toucyy 0:2d8d0b73e1ff 196 0x91, 0x02, // Output (array)
toucyy 0:2d8d0b73e1ff 197 0xC0 // end collection
toucyy 0:2d8d0b73e1ff 198
toucyy 0:2d8d0b73e1ff 199 };
toucyy 0:2d8d0b73e1ff 200 reportLength = sizeof(reportDescriptor);
toucyy 0:2d8d0b73e1ff 201 return reportDescriptor;
toucyy 0:2d8d0b73e1ff 202 }
toucyy 0:2d8d0b73e1ff 203
toucyy 0:2d8d0b73e1ff 204 #define DEFAULT_CONFIGURATION (1)
toucyy 0:2d8d0b73e1ff 205 #define TOTAL_DESCRIPTOR_LENGTH ((1 * CONFIGURATION_DESCRIPTOR_LENGTH) \
toucyy 0:2d8d0b73e1ff 206 + (1 * INTERFACE_DESCRIPTOR_LENGTH) \
toucyy 0:2d8d0b73e1ff 207 + (1 * HID_DESCRIPTOR_LENGTH) \
toucyy 0:2d8d0b73e1ff 208 + (2 * ENDPOINT_DESCRIPTOR_LENGTH))
toucyy 0:2d8d0b73e1ff 209
toucyy 0:2d8d0b73e1ff 210 uint8_t * USBHID::configurationDesc() {
toucyy 0:2d8d0b73e1ff 211 static uint8_t configurationDescriptor[] = {
toucyy 0:2d8d0b73e1ff 212 CONFIGURATION_DESCRIPTOR_LENGTH,// bLength
toucyy 0:2d8d0b73e1ff 213 CONFIGURATION_DESCRIPTOR, // bDescriptorType
toucyy 0:2d8d0b73e1ff 214 LSB(TOTAL_DESCRIPTOR_LENGTH), // wTotalLength (LSB)
toucyy 0:2d8d0b73e1ff 215 MSB(TOTAL_DESCRIPTOR_LENGTH), // wTotalLength (MSB)
toucyy 0:2d8d0b73e1ff 216 0x01, // bNumInterfaces
toucyy 0:2d8d0b73e1ff 217 DEFAULT_CONFIGURATION, // bConfigurationValue
toucyy 0:2d8d0b73e1ff 218 0x00, // iConfiguration
toucyy 0:2d8d0b73e1ff 219 C_RESERVED | C_SELF_POWERED, // bmAttributes
toucyy 0:2d8d0b73e1ff 220 C_POWER(0), // bMaxPower
toucyy 0:2d8d0b73e1ff 221
toucyy 0:2d8d0b73e1ff 222 INTERFACE_DESCRIPTOR_LENGTH, // bLength
toucyy 0:2d8d0b73e1ff 223 INTERFACE_DESCRIPTOR, // bDescriptorType
toucyy 0:2d8d0b73e1ff 224 0x00, // bInterfaceNumber
toucyy 0:2d8d0b73e1ff 225 0x00, // bAlternateSetting
toucyy 0:2d8d0b73e1ff 226 0x02, // bNumEndpoints
toucyy 0:2d8d0b73e1ff 227 HID_CLASS, // bInterfaceClass
toucyy 0:2d8d0b73e1ff 228 HID_SUBCLASS_NONE, // bInterfaceSubClass
toucyy 0:2d8d0b73e1ff 229 HID_PROTOCOL_NONE, // bInterfaceProtocol
toucyy 0:2d8d0b73e1ff 230 0x00, // iInterface
toucyy 0:2d8d0b73e1ff 231
toucyy 0:2d8d0b73e1ff 232 HID_DESCRIPTOR_LENGTH, // bLength
toucyy 0:2d8d0b73e1ff 233 HID_DESCRIPTOR, // bDescriptorType
toucyy 0:2d8d0b73e1ff 234 LSB(HID_VERSION_1_11), // bcdHID (LSB)
toucyy 0:2d8d0b73e1ff 235 MSB(HID_VERSION_1_11), // bcdHID (MSB)
toucyy 0:2d8d0b73e1ff 236 0x00, // bCountryCode
toucyy 0:2d8d0b73e1ff 237 0x01, // bNumDescriptors
toucyy 0:2d8d0b73e1ff 238 REPORT_DESCRIPTOR, // bDescriptorType
toucyy 0:2d8d0b73e1ff 239 LSB(this->reportDescLength()), // wDescriptorLength (LSB)
toucyy 0:2d8d0b73e1ff 240 MSB(this->reportDescLength()), // wDescriptorLength (MSB)
toucyy 0:2d8d0b73e1ff 241
toucyy 0:2d8d0b73e1ff 242 ENDPOINT_DESCRIPTOR_LENGTH, // bLength
toucyy 0:2d8d0b73e1ff 243 ENDPOINT_DESCRIPTOR, // bDescriptorType
toucyy 0:2d8d0b73e1ff 244 PHY_TO_DESC(EPINT_IN), // bEndpointAddress
toucyy 0:2d8d0b73e1ff 245 E_INTERRUPT, // bmAttributes
toucyy 0:2d8d0b73e1ff 246 LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB)
toucyy 0:2d8d0b73e1ff 247 MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB)
toucyy 0:2d8d0b73e1ff 248 10, // bInterval (milliseconds)
toucyy 0:2d8d0b73e1ff 249
toucyy 0:2d8d0b73e1ff 250 ENDPOINT_DESCRIPTOR_LENGTH, // bLength
toucyy 0:2d8d0b73e1ff 251 ENDPOINT_DESCRIPTOR, // bDescriptorType
toucyy 0:2d8d0b73e1ff 252 PHY_TO_DESC(EPINT_OUT), // bEndpointAddress
toucyy 0:2d8d0b73e1ff 253 E_INTERRUPT, // bmAttributes
toucyy 0:2d8d0b73e1ff 254 LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB)
toucyy 0:2d8d0b73e1ff 255 MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB)
toucyy 0:2d8d0b73e1ff 256 10, // bInterval (milliseconds)
toucyy 0:2d8d0b73e1ff 257 };
toucyy 0:2d8d0b73e1ff 258 return configurationDescriptor;
toucyy 0:2d8d0b73e1ff 259 }