WIP PID

Dependencies:   USBDEVICE USBJoystick mbed

Fork of USBJoystick_HelloWorld2 by Wim Huiskamp

Committer:
Cirrus01
Date:
Sat Jul 07 10:48:38 2018 +0000
Revision:
1:caf8a4134cbf
First

Who changed what in which revision?

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