Control the wondrous spinning-frog game of Zuma's Revenge with a rotating chair and an Airzooka. Maps compass rotation, flex sensor and push button input to USB actions to control Zuma's Revenge (http://www.popcap.com/games/zumas-revenge/online)

Dependencies:   LSM303DLHC mbed

Note that content for USB HID and USB Device is actually from the USBDevice mbed library. However, we made a couple of small changes to this library (allowing USB clicks at a particular location) that required us to break it off from the main project if we wanted to publish without pushing upstream.

Committer:
andrewhead
Date:
Mon Sep 29 01:12:20 2014 +0000
Revision:
0:4df415dde990
Initial Commit.

Who changed what in which revision?

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