USB CDC (serial) and USB MSC (strage) Composite Device. http://mbed.org/users/okini3939/notebook/USB_Device/

Dependencies:   ChaNFSSD mbed ChaNFS

Committer:
okini3939
Date:
Fri Dec 16 15:22:36 2011 +0000
Revision:
0:9b1d17d54055

        

Who changed what in which revision?

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