Sensor reporting over USB CDC

Dependencies:   MAG3110 MMA8451Q SLCD- TSI USBDevice mbed

Committer:
wue
Date:
Wed Apr 16 12:20:12 2014 +0000
Revision:
0:7b58cdacf811
Sensor reporting over USB CDC

Who changed what in which revision?

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