ON Semiconductor / mbed-os

Dependents:   mbed-TFT-example-NCS36510 mbed-Accelerometer-example-NCS36510 mbed-Accelerometer-example-NCS36510

Committer:
group-onsemi
Date:
Wed Jan 25 20:34:15 2017 +0000
Revision:
0:098463de4c5d
Initial commit

Who changed what in which revision?

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