Fork of the official USBDevice library

Fork of USBDevice by mbed official

Committer:
screamer
Date:
Fri Apr 28 11:26:51 2017 +0100
Branch:
github-merge
Revision:
73:8d28a0cb7b43
Parent:
25:7c72828865f3
Merge from mbed-os @ github

Who changed what in which revision?

UserRevisionLine numberNew contents of line
screamer 73:8d28a0cb7b43 1 /* Copyright (c) 2010-2011 mbed.org, MIT License
screamer 73:8d28a0cb7b43 2 *
screamer 73:8d28a0cb7b43 3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
screamer 73:8d28a0cb7b43 4 * and associated documentation files (the "Software"), to deal in the Software without
screamer 73:8d28a0cb7b43 5 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
screamer 73:8d28a0cb7b43 6 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
screamer 73:8d28a0cb7b43 7 * Software is furnished to do so, subject to the following conditions:
screamer 73:8d28a0cb7b43 8 *
screamer 73:8d28a0cb7b43 9 * The above copyright notice and this permission notice shall be included in all copies or
screamer 73:8d28a0cb7b43 10 * substantial portions of the Software.
screamer 73:8d28a0cb7b43 11 *
screamer 73:8d28a0cb7b43 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
screamer 73:8d28a0cb7b43 13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
screamer 73:8d28a0cb7b43 14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
screamer 73:8d28a0cb7b43 15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
screamer 73:8d28a0cb7b43 16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
screamer 73:8d28a0cb7b43 17 */
screamer 73:8d28a0cb7b43 18
screamer 73:8d28a0cb7b43 19 #include "stdint.h"
screamer 73:8d28a0cb7b43 20 #include "USBHAL.h"
screamer 73:8d28a0cb7b43 21 #include "USBHID.h"
screamer 73:8d28a0cb7b43 22
screamer 73:8d28a0cb7b43 23
screamer 73:8d28a0cb7b43 24 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)
screamer 73:8d28a0cb7b43 25 {
screamer 73:8d28a0cb7b43 26 output_length = output_report_length;
screamer 73:8d28a0cb7b43 27 input_length = input_report_length;
screamer 73:8d28a0cb7b43 28 if(connect) {
screamer 73:8d28a0cb7b43 29 USBDevice::connect();
screamer 73:8d28a0cb7b43 30 }
screamer 73:8d28a0cb7b43 31 }
screamer 73:8d28a0cb7b43 32
screamer 73:8d28a0cb7b43 33
screamer 73:8d28a0cb7b43 34 bool USBHID::send(HID_REPORT *report)
screamer 73:8d28a0cb7b43 35 {
screamer 73:8d28a0cb7b43 36 return write(EPINT_IN, report->data, report->length, MAX_HID_REPORT_SIZE);
screamer 73:8d28a0cb7b43 37 }
screamer 73:8d28a0cb7b43 38
screamer 73:8d28a0cb7b43 39 bool USBHID::sendNB(HID_REPORT *report)
screamer 73:8d28a0cb7b43 40 {
screamer 73:8d28a0cb7b43 41 return writeNB(EPINT_IN, report->data, report->length, MAX_HID_REPORT_SIZE);
screamer 73:8d28a0cb7b43 42 }
screamer 73:8d28a0cb7b43 43
screamer 73:8d28a0cb7b43 44
screamer 73:8d28a0cb7b43 45 bool USBHID::read(HID_REPORT *report)
screamer 73:8d28a0cb7b43 46 {
screamer 73:8d28a0cb7b43 47 uint32_t bytesRead = 0;
screamer 73:8d28a0cb7b43 48 bool result;
screamer 73:8d28a0cb7b43 49 result = USBDevice::readEP(EPINT_OUT, report->data, &bytesRead, MAX_HID_REPORT_SIZE);
screamer 73:8d28a0cb7b43 50 if(!readStart(EPINT_OUT, MAX_HID_REPORT_SIZE))
screamer 73:8d28a0cb7b43 51 return false;
screamer 73:8d28a0cb7b43 52 report->length = bytesRead;
screamer 73:8d28a0cb7b43 53 return result;
screamer 73:8d28a0cb7b43 54 }
screamer 73:8d28a0cb7b43 55
screamer 73:8d28a0cb7b43 56
screamer 73:8d28a0cb7b43 57 bool USBHID::readNB(HID_REPORT *report)
screamer 73:8d28a0cb7b43 58 {
screamer 73:8d28a0cb7b43 59 uint32_t bytesRead = 0;
screamer 73:8d28a0cb7b43 60 bool result;
screamer 73:8d28a0cb7b43 61 result = USBDevice::readEP_NB(EPINT_OUT, report->data, &bytesRead, MAX_HID_REPORT_SIZE);
screamer 73:8d28a0cb7b43 62 // if readEP_NB did not succeed, does not issue a readStart
screamer 73:8d28a0cb7b43 63 if (!result)
screamer 73:8d28a0cb7b43 64 return false;
screamer 73:8d28a0cb7b43 65 report->length = bytesRead;
screamer 73:8d28a0cb7b43 66 if(!readStart(EPINT_OUT, MAX_HID_REPORT_SIZE))
screamer 73:8d28a0cb7b43 67 return false;
screamer 73:8d28a0cb7b43 68 return result;
screamer 73:8d28a0cb7b43 69 }
screamer 73:8d28a0cb7b43 70
screamer 73:8d28a0cb7b43 71
screamer 73:8d28a0cb7b43 72 uint16_t USBHID::reportDescLength() {
screamer 73:8d28a0cb7b43 73 reportDesc();
screamer 73:8d28a0cb7b43 74 return reportLength;
screamer 73:8d28a0cb7b43 75 }
screamer 73:8d28a0cb7b43 76
screamer 73:8d28a0cb7b43 77
screamer 73:8d28a0cb7b43 78
screamer 73:8d28a0cb7b43 79 //
screamer 73:8d28a0cb7b43 80 // Route callbacks from lower layers to class(es)
screamer 73:8d28a0cb7b43 81 //
screamer 73:8d28a0cb7b43 82
screamer 73:8d28a0cb7b43 83
screamer 73:8d28a0cb7b43 84 // Called in ISR context
screamer 73:8d28a0cb7b43 85 // Called by USBDevice on Endpoint0 request
screamer 73:8d28a0cb7b43 86 // This is used to handle extensions to standard requests
screamer 73:8d28a0cb7b43 87 // and class specific requests
screamer 73:8d28a0cb7b43 88 // Return true if class handles this request
screamer 73:8d28a0cb7b43 89 bool USBHID::USBCallback_request() {
screamer 73:8d28a0cb7b43 90 bool success = false;
screamer 73:8d28a0cb7b43 91 CONTROL_TRANSFER * transfer = getTransferPtr();
screamer 73:8d28a0cb7b43 92 uint8_t *hidDescriptor;
screamer 73:8d28a0cb7b43 93
screamer 73:8d28a0cb7b43 94 // Process additional standard requests
screamer 73:8d28a0cb7b43 95
screamer 73:8d28a0cb7b43 96 if ((transfer->setup.bmRequestType.Type == STANDARD_TYPE))
screamer 73:8d28a0cb7b43 97 {
screamer 73:8d28a0cb7b43 98 switch (transfer->setup.bRequest)
screamer 73:8d28a0cb7b43 99 {
screamer 73:8d28a0cb7b43 100 case GET_DESCRIPTOR:
screamer 73:8d28a0cb7b43 101 switch (DESCRIPTOR_TYPE(transfer->setup.wValue))
screamer 73:8d28a0cb7b43 102 {
screamer 73:8d28a0cb7b43 103 case REPORT_DESCRIPTOR:
screamer 73:8d28a0cb7b43 104 if ((reportDesc() != NULL) \
screamer 73:8d28a0cb7b43 105 && (reportDescLength() != 0))
screamer 73:8d28a0cb7b43 106 {
screamer 73:8d28a0cb7b43 107 transfer->remaining = reportDescLength();
screamer 73:8d28a0cb7b43 108 transfer->ptr = reportDesc();
screamer 73:8d28a0cb7b43 109 transfer->direction = DEVICE_TO_HOST;
screamer 73:8d28a0cb7b43 110 success = true;
screamer 73:8d28a0cb7b43 111 }
screamer 73:8d28a0cb7b43 112 break;
screamer 73:8d28a0cb7b43 113 case HID_DESCRIPTOR:
screamer 73:8d28a0cb7b43 114 // Find the HID descriptor, after the configuration descriptor
screamer 73:8d28a0cb7b43 115 hidDescriptor = findDescriptor(HID_DESCRIPTOR);
screamer 73:8d28a0cb7b43 116 if (hidDescriptor != NULL)
screamer 73:8d28a0cb7b43 117 {
screamer 73:8d28a0cb7b43 118 transfer->remaining = HID_DESCRIPTOR_LENGTH;
screamer 73:8d28a0cb7b43 119 transfer->ptr = hidDescriptor;
screamer 73:8d28a0cb7b43 120 transfer->direction = DEVICE_TO_HOST;
screamer 73:8d28a0cb7b43 121 success = true;
screamer 73:8d28a0cb7b43 122 }
screamer 73:8d28a0cb7b43 123 break;
screamer 73:8d28a0cb7b43 124
screamer 73:8d28a0cb7b43 125 default:
screamer 73:8d28a0cb7b43 126 break;
screamer 73:8d28a0cb7b43 127 }
screamer 73:8d28a0cb7b43 128 break;
screamer 73:8d28a0cb7b43 129 default:
screamer 73:8d28a0cb7b43 130 break;
screamer 73:8d28a0cb7b43 131 }
screamer 73:8d28a0cb7b43 132 }
screamer 73:8d28a0cb7b43 133
screamer 73:8d28a0cb7b43 134 // Process class-specific requests
screamer 73:8d28a0cb7b43 135
screamer 73:8d28a0cb7b43 136 if (transfer->setup.bmRequestType.Type == CLASS_TYPE)
screamer 73:8d28a0cb7b43 137 {
screamer 73:8d28a0cb7b43 138 switch (transfer->setup.bRequest)
screamer 73:8d28a0cb7b43 139 {
screamer 73:8d28a0cb7b43 140 case SET_REPORT:
screamer 73:8d28a0cb7b43 141 // First byte will be used for report ID
screamer 73:8d28a0cb7b43 142 outputReport.data[0] = transfer->setup.wValue & 0xff;
screamer 73:8d28a0cb7b43 143 outputReport.length = transfer->setup.wLength + 1;
screamer 73:8d28a0cb7b43 144
screamer 73:8d28a0cb7b43 145 transfer->remaining = sizeof(outputReport.data) - 1;
screamer 73:8d28a0cb7b43 146 transfer->ptr = &outputReport.data[1];
screamer 73:8d28a0cb7b43 147 transfer->direction = HOST_TO_DEVICE;
screamer 73:8d28a0cb7b43 148 transfer->notify = true;
screamer 73:8d28a0cb7b43 149 success = true;
screamer 73:8d28a0cb7b43 150 default:
screamer 73:8d28a0cb7b43 151 break;
screamer 73:8d28a0cb7b43 152 }
screamer 73:8d28a0cb7b43 153 }
screamer 73:8d28a0cb7b43 154
screamer 73:8d28a0cb7b43 155 return success;
screamer 73:8d28a0cb7b43 156 }
screamer 73:8d28a0cb7b43 157
screamer 73:8d28a0cb7b43 158
screamer 73:8d28a0cb7b43 159 #define DEFAULT_CONFIGURATION (1)
screamer 73:8d28a0cb7b43 160
screamer 73:8d28a0cb7b43 161
screamer 73:8d28a0cb7b43 162 // Called in ISR context
screamer 73:8d28a0cb7b43 163 // Set configuration. Return false if the
screamer 73:8d28a0cb7b43 164 // configuration is not supported
screamer 73:8d28a0cb7b43 165 bool USBHID::USBCallback_setConfiguration(uint8_t configuration) {
screamer 73:8d28a0cb7b43 166 if (configuration != DEFAULT_CONFIGURATION) {
screamer 73:8d28a0cb7b43 167 return false;
screamer 73:8d28a0cb7b43 168 }
screamer 73:8d28a0cb7b43 169
screamer 73:8d28a0cb7b43 170 // Configure endpoints > 0
screamer 73:8d28a0cb7b43 171 addEndpoint(EPINT_IN, MAX_PACKET_SIZE_EPINT);
screamer 73:8d28a0cb7b43 172 addEndpoint(EPINT_OUT, MAX_PACKET_SIZE_EPINT);
screamer 73:8d28a0cb7b43 173
screamer 73:8d28a0cb7b43 174 // We activate the endpoint to be able to recceive data
screamer 73:8d28a0cb7b43 175 readStart(EPINT_OUT, MAX_PACKET_SIZE_EPINT);
screamer 73:8d28a0cb7b43 176 return true;
screamer 73:8d28a0cb7b43 177 }
screamer 73:8d28a0cb7b43 178
screamer 73:8d28a0cb7b43 179
screamer 73:8d28a0cb7b43 180 uint8_t * USBHID::stringIinterfaceDesc() {
screamer 73:8d28a0cb7b43 181 static uint8_t stringIinterfaceDescriptor[] = {
screamer 73:8d28a0cb7b43 182 0x08, //bLength
screamer 73:8d28a0cb7b43 183 STRING_DESCRIPTOR, //bDescriptorType 0x03
screamer 73:8d28a0cb7b43 184 'H',0,'I',0,'D',0, //bString iInterface - HID
screamer 73:8d28a0cb7b43 185 };
screamer 73:8d28a0cb7b43 186 return stringIinterfaceDescriptor;
screamer 73:8d28a0cb7b43 187 }
screamer 73:8d28a0cb7b43 188
screamer 73:8d28a0cb7b43 189 uint8_t * USBHID::stringIproductDesc() {
screamer 73:8d28a0cb7b43 190 static uint8_t stringIproductDescriptor[] = {
screamer 73:8d28a0cb7b43 191 0x16, //bLength
screamer 73:8d28a0cb7b43 192 STRING_DESCRIPTOR, //bDescriptorType 0x03
screamer 73:8d28a0cb7b43 193 'H',0,'I',0,'D',0,' ',0,'D',0,'E',0,'V',0,'I',0,'C',0,'E',0 //bString iProduct - HID device
screamer 73:8d28a0cb7b43 194 };
screamer 73:8d28a0cb7b43 195 return stringIproductDescriptor;
screamer 73:8d28a0cb7b43 196 }
screamer 73:8d28a0cb7b43 197
screamer 73:8d28a0cb7b43 198
screamer 73:8d28a0cb7b43 199
screamer 73:8d28a0cb7b43 200 uint8_t * USBHID::reportDesc() {
screamer 73:8d28a0cb7b43 201 static uint8_t reportDescriptor[] = {
screamer 73:8d28a0cb7b43 202 USAGE_PAGE(2), LSB(0xFFAB), MSB(0xFFAB),
screamer 73:8d28a0cb7b43 203 USAGE(2), LSB(0x0200), MSB(0x0200),
screamer 73:8d28a0cb7b43 204 COLLECTION(1), 0x01, // Collection (Application)
screamer 73:8d28a0cb7b43 205
screamer 73:8d28a0cb7b43 206 REPORT_SIZE(1), 0x08, // 8 bits
screamer 73:8d28a0cb7b43 207 LOGICAL_MINIMUM(1), 0x00,
screamer 73:8d28a0cb7b43 208 LOGICAL_MAXIMUM(1), 0xFF,
screamer 73:8d28a0cb7b43 209
screamer 73:8d28a0cb7b43 210 REPORT_COUNT(1), input_length,
screamer 73:8d28a0cb7b43 211 USAGE(1), 0x01,
screamer 73:8d28a0cb7b43 212 INPUT(1), 0x02, // Data, Var, Abs
screamer 73:8d28a0cb7b43 213
screamer 73:8d28a0cb7b43 214 REPORT_COUNT(1), output_length,
screamer 73:8d28a0cb7b43 215 USAGE(1), 0x02,
screamer 73:8d28a0cb7b43 216 OUTPUT(1), 0x02, // Data, Var, Abs
screamer 73:8d28a0cb7b43 217
screamer 73:8d28a0cb7b43 218 END_COLLECTION(0),
screamer 73:8d28a0cb7b43 219 };
screamer 73:8d28a0cb7b43 220 reportLength = sizeof(reportDescriptor);
screamer 73:8d28a0cb7b43 221 return reportDescriptor;
screamer 73:8d28a0cb7b43 222 }
screamer 73:8d28a0cb7b43 223
screamer 73:8d28a0cb7b43 224 #define DEFAULT_CONFIGURATION (1)
screamer 73:8d28a0cb7b43 225 #define TOTAL_DESCRIPTOR_LENGTH ((1 * CONFIGURATION_DESCRIPTOR_LENGTH) \
screamer 73:8d28a0cb7b43 226 + (1 * INTERFACE_DESCRIPTOR_LENGTH) \
screamer 73:8d28a0cb7b43 227 + (1 * HID_DESCRIPTOR_LENGTH) \
screamer 73:8d28a0cb7b43 228 + (2 * ENDPOINT_DESCRIPTOR_LENGTH))
screamer 73:8d28a0cb7b43 229
screamer 73:8d28a0cb7b43 230 uint8_t * USBHID::configurationDesc() {
screamer 73:8d28a0cb7b43 231 static uint8_t configurationDescriptor[] = {
screamer 73:8d28a0cb7b43 232 CONFIGURATION_DESCRIPTOR_LENGTH, // bLength
screamer 73:8d28a0cb7b43 233 CONFIGURATION_DESCRIPTOR, // bDescriptorType
screamer 73:8d28a0cb7b43 234 LSB(TOTAL_DESCRIPTOR_LENGTH), // wTotalLength (LSB)
screamer 73:8d28a0cb7b43 235 MSB(TOTAL_DESCRIPTOR_LENGTH), // wTotalLength (MSB)
screamer 73:8d28a0cb7b43 236 0x01, // bNumInterfaces
screamer 73:8d28a0cb7b43 237 DEFAULT_CONFIGURATION, // bConfigurationValue
screamer 73:8d28a0cb7b43 238 0x00, // iConfiguration
screamer 73:8d28a0cb7b43 239 C_RESERVED | C_SELF_POWERED, // bmAttributes
screamer 73:8d28a0cb7b43 240 C_POWER(0), // bMaxPower
screamer 73:8d28a0cb7b43 241
screamer 73:8d28a0cb7b43 242 INTERFACE_DESCRIPTOR_LENGTH, // bLength
screamer 73:8d28a0cb7b43 243 INTERFACE_DESCRIPTOR, // bDescriptorType
screamer 73:8d28a0cb7b43 244 0x00, // bInterfaceNumber
screamer 73:8d28a0cb7b43 245 0x00, // bAlternateSetting
screamer 73:8d28a0cb7b43 246 0x02, // bNumEndpoints
screamer 73:8d28a0cb7b43 247 HID_CLASS, // bInterfaceClass
screamer 73:8d28a0cb7b43 248 HID_SUBCLASS_NONE, // bInterfaceSubClass
screamer 73:8d28a0cb7b43 249 HID_PROTOCOL_NONE, // bInterfaceProtocol
screamer 73:8d28a0cb7b43 250 0x00, // iInterface
screamer 73:8d28a0cb7b43 251
screamer 73:8d28a0cb7b43 252 HID_DESCRIPTOR_LENGTH, // bLength
screamer 73:8d28a0cb7b43 253 HID_DESCRIPTOR, // bDescriptorType
screamer 73:8d28a0cb7b43 254 LSB(HID_VERSION_1_11), // bcdHID (LSB)
screamer 73:8d28a0cb7b43 255 MSB(HID_VERSION_1_11), // bcdHID (MSB)
screamer 73:8d28a0cb7b43 256 0x00, // bCountryCode
screamer 73:8d28a0cb7b43 257 0x01, // bNumDescriptors
screamer 73:8d28a0cb7b43 258 REPORT_DESCRIPTOR, // bDescriptorType
screamer 73:8d28a0cb7b43 259 (uint8_t)(LSB(reportDescLength())), // wDescriptorLength (LSB)
screamer 73:8d28a0cb7b43 260 (uint8_t)(MSB(reportDescLength())), // wDescriptorLength (MSB)
screamer 73:8d28a0cb7b43 261
screamer 73:8d28a0cb7b43 262 ENDPOINT_DESCRIPTOR_LENGTH, // bLength
screamer 73:8d28a0cb7b43 263 ENDPOINT_DESCRIPTOR, // bDescriptorType
screamer 73:8d28a0cb7b43 264 PHY_TO_DESC(EPINT_IN), // bEndpointAddress
screamer 73:8d28a0cb7b43 265 E_INTERRUPT, // bmAttributes
screamer 73:8d28a0cb7b43 266 LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB)
screamer 73:8d28a0cb7b43 267 MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB)
screamer 73:8d28a0cb7b43 268 1, // bInterval (milliseconds)
screamer 73:8d28a0cb7b43 269
screamer 73:8d28a0cb7b43 270 ENDPOINT_DESCRIPTOR_LENGTH, // bLength
screamer 73:8d28a0cb7b43 271 ENDPOINT_DESCRIPTOR, // bDescriptorType
screamer 73:8d28a0cb7b43 272 PHY_TO_DESC(EPINT_OUT), // bEndpointAddress
screamer 73:8d28a0cb7b43 273 E_INTERRUPT, // bmAttributes
screamer 73:8d28a0cb7b43 274 LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB)
screamer 73:8d28a0cb7b43 275 MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB)
screamer 73:8d28a0cb7b43 276 1, // bInterval (milliseconds)
screamer 73:8d28a0cb7b43 277 };
screamer 73:8d28a0cb7b43 278 return configurationDescriptor;
screamer 73:8d28a0cb7b43 279 }