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 "USBMouse.h"
andrewhead 0:4df415dde990 21
andrewhead 0:4df415dde990 22 bool USBMouse::update(int16_t x, int16_t y, uint8_t button, int8_t z) {
andrewhead 0:4df415dde990 23 switch (mouse_type) {
andrewhead 0:4df415dde990 24 case REL_MOUSE:
andrewhead 0:4df415dde990 25 while (x > 127) {
andrewhead 0:4df415dde990 26 if (!mouseSend(127, 0, button, z)) return false;
andrewhead 0:4df415dde990 27 x = x - 127;
andrewhead 0:4df415dde990 28 }
andrewhead 0:4df415dde990 29 while (x < -128) {
andrewhead 0:4df415dde990 30 if (!mouseSend(-128, 0, button, z)) return false;
andrewhead 0:4df415dde990 31 x = x + 128;
andrewhead 0:4df415dde990 32 }
andrewhead 0:4df415dde990 33 while (y > 127) {
andrewhead 0:4df415dde990 34 if (!mouseSend(0, 127, button, z)) return false;
andrewhead 0:4df415dde990 35 y = y - 127;
andrewhead 0:4df415dde990 36 }
andrewhead 0:4df415dde990 37 while (y < -128) {
andrewhead 0:4df415dde990 38 if (!mouseSend(0, -128, button, z)) return false;
andrewhead 0:4df415dde990 39 y = y + 128;
andrewhead 0:4df415dde990 40 }
andrewhead 0:4df415dde990 41 return mouseSend(x, y, button, z);
andrewhead 0:4df415dde990 42 case ABS_MOUSE:
andrewhead 0:4df415dde990 43 HID_REPORT report;
andrewhead 0:4df415dde990 44
andrewhead 0:4df415dde990 45 report.data[0] = x & 0xff;
andrewhead 0:4df415dde990 46 report.data[1] = (x >> 8) & 0xff;
andrewhead 0:4df415dde990 47 report.data[2] = y & 0xff;
andrewhead 0:4df415dde990 48 report.data[3] = (y >> 8) & 0xff;
andrewhead 0:4df415dde990 49 report.data[4] = -z;
andrewhead 0:4df415dde990 50 report.data[5] = button & 0x07;
andrewhead 0:4df415dde990 51
andrewhead 0:4df415dde990 52 report.length = 6;
andrewhead 0:4df415dde990 53
andrewhead 0:4df415dde990 54 return send(&report);
andrewhead 0:4df415dde990 55 default:
andrewhead 0:4df415dde990 56 return false;
andrewhead 0:4df415dde990 57 }
andrewhead 0:4df415dde990 58 }
andrewhead 0:4df415dde990 59
andrewhead 0:4df415dde990 60 bool USBMouse::mouseSend(int8_t x, int8_t y, uint8_t buttons, int8_t z) {
andrewhead 0:4df415dde990 61 HID_REPORT report;
andrewhead 0:4df415dde990 62 report.data[0] = buttons & 0x07;
andrewhead 0:4df415dde990 63 report.data[1] = x;
andrewhead 0:4df415dde990 64 report.data[2] = y;
andrewhead 0:4df415dde990 65 report.data[3] = -z; // >0 to scroll down, <0 to scroll up
andrewhead 0:4df415dde990 66
andrewhead 0:4df415dde990 67 report.length = 4;
andrewhead 0:4df415dde990 68
andrewhead 0:4df415dde990 69 return send(&report);
andrewhead 0:4df415dde990 70 }
andrewhead 0:4df415dde990 71
andrewhead 0:4df415dde990 72 bool USBMouse::move(int16_t x, int16_t y) {
andrewhead 0:4df415dde990 73 return update(x, y, button, 0);
andrewhead 0:4df415dde990 74 }
andrewhead 0:4df415dde990 75
andrewhead 0:4df415dde990 76 bool USBMouse::scroll(int8_t z) {
andrewhead 0:4df415dde990 77 return update(0, 0, button, z);
andrewhead 0:4df415dde990 78 }
andrewhead 0:4df415dde990 79
andrewhead 0:4df415dde990 80
andrewhead 0:4df415dde990 81 bool USBMouse::doubleClick() {
andrewhead 0:4df415dde990 82 /*
andrewhead 0:4df415dde990 83 if (!click(MOUSE_LEFT))
andrewhead 0:4df415dde990 84 return false;
andrewhead 0:4df415dde990 85 wait(0.1);
andrewhead 0:4df415dde990 86 return click(MOUSE_LEFT);
andrewhead 0:4df415dde990 87 */
andrewhead 0:4df415dde990 88 return false;
andrewhead 0:4df415dde990 89 }
andrewhead 0:4df415dde990 90
andrewhead 0:4df415dde990 91 bool USBMouse::click(uint16_t x, uint16_t y, uint8_t button) {
andrewhead 0:4df415dde990 92 if (!update(x, y, button, 0))
andrewhead 0:4df415dde990 93 return false;
andrewhead 0:4df415dde990 94 wait(0.01);
andrewhead 0:4df415dde990 95 return update(x, y, 0, 0);
andrewhead 0:4df415dde990 96 }
andrewhead 0:4df415dde990 97
andrewhead 0:4df415dde990 98 bool USBMouse::press(uint8_t button_) {
andrewhead 0:4df415dde990 99 button = button_ & 0x07;
andrewhead 0:4df415dde990 100 return update(0, 0, button, 0);
andrewhead 0:4df415dde990 101 }
andrewhead 0:4df415dde990 102
andrewhead 0:4df415dde990 103 bool USBMouse::release(uint8_t button_) {
andrewhead 0:4df415dde990 104 button = (button & (~button_)) & 0x07;
andrewhead 0:4df415dde990 105 return update(0, 0, button, 0);
andrewhead 0:4df415dde990 106 }
andrewhead 0:4df415dde990 107
andrewhead 0:4df415dde990 108
andrewhead 0:4df415dde990 109 uint8_t * USBMouse::reportDesc() {
andrewhead 0:4df415dde990 110
andrewhead 0:4df415dde990 111 if (mouse_type == REL_MOUSE) {
andrewhead 0:4df415dde990 112 static uint8_t reportDescriptor[] = {
andrewhead 0:4df415dde990 113 USAGE_PAGE(1), 0x01, // Genric Desktop
andrewhead 0:4df415dde990 114 USAGE(1), 0x02, // Mouse
andrewhead 0:4df415dde990 115 COLLECTION(1), 0x01, // Application
andrewhead 0:4df415dde990 116 USAGE(1), 0x01, // Pointer
andrewhead 0:4df415dde990 117 COLLECTION(1), 0x00, // Physical
andrewhead 0:4df415dde990 118
andrewhead 0:4df415dde990 119 REPORT_COUNT(1), 0x03,
andrewhead 0:4df415dde990 120 REPORT_SIZE(1), 0x01,
andrewhead 0:4df415dde990 121 USAGE_PAGE(1), 0x09, // Buttons
andrewhead 0:4df415dde990 122 USAGE_MINIMUM(1), 0x1,
andrewhead 0:4df415dde990 123 USAGE_MAXIMUM(1), 0x3,
andrewhead 0:4df415dde990 124 LOGICAL_MINIMUM(1), 0x00,
andrewhead 0:4df415dde990 125 LOGICAL_MAXIMUM(1), 0x01,
andrewhead 0:4df415dde990 126 INPUT(1), 0x02,
andrewhead 0:4df415dde990 127 REPORT_COUNT(1), 0x01,
andrewhead 0:4df415dde990 128 REPORT_SIZE(1), 0x05,
andrewhead 0:4df415dde990 129 INPUT(1), 0x01,
andrewhead 0:4df415dde990 130
andrewhead 0:4df415dde990 131 REPORT_COUNT(1), 0x03,
andrewhead 0:4df415dde990 132 REPORT_SIZE(1), 0x08,
andrewhead 0:4df415dde990 133 USAGE_PAGE(1), 0x01,
andrewhead 0:4df415dde990 134 USAGE(1), 0x30, // X
andrewhead 0:4df415dde990 135 USAGE(1), 0x31, // Y
andrewhead 0:4df415dde990 136 USAGE(1), 0x38, // scroll
andrewhead 0:4df415dde990 137 LOGICAL_MINIMUM(1), 0x81,
andrewhead 0:4df415dde990 138 LOGICAL_MAXIMUM(1), 0x7f,
andrewhead 0:4df415dde990 139 INPUT(1), 0x06, // Relative data
andrewhead 0:4df415dde990 140
andrewhead 0:4df415dde990 141 END_COLLECTION(0),
andrewhead 0:4df415dde990 142 END_COLLECTION(0),
andrewhead 0:4df415dde990 143 };
andrewhead 0:4df415dde990 144 reportLength = sizeof(reportDescriptor);
andrewhead 0:4df415dde990 145 return reportDescriptor;
andrewhead 0:4df415dde990 146 } else if (mouse_type == ABS_MOUSE) {
andrewhead 0:4df415dde990 147 static uint8_t reportDescriptor[] = {
andrewhead 0:4df415dde990 148
andrewhead 0:4df415dde990 149 USAGE_PAGE(1), 0x01, // Generic Desktop
andrewhead 0:4df415dde990 150 USAGE(1), 0x02, // Mouse
andrewhead 0:4df415dde990 151 COLLECTION(1), 0x01, // Application
andrewhead 0:4df415dde990 152 USAGE(1), 0x01, // Pointer
andrewhead 0:4df415dde990 153 COLLECTION(1), 0x00, // Physical
andrewhead 0:4df415dde990 154
andrewhead 0:4df415dde990 155 USAGE_PAGE(1), 0x01, // Generic Desktop
andrewhead 0:4df415dde990 156 USAGE(1), 0x30, // X
andrewhead 0:4df415dde990 157 USAGE(1), 0x31, // Y
andrewhead 0:4df415dde990 158 LOGICAL_MINIMUM(1), 0x00, // 0
andrewhead 0:4df415dde990 159 LOGICAL_MAXIMUM(2), 0xff, 0x7f, // 32767
andrewhead 0:4df415dde990 160 REPORT_SIZE(1), 0x10,
andrewhead 0:4df415dde990 161 REPORT_COUNT(1), 0x02,
andrewhead 0:4df415dde990 162 INPUT(1), 0x02, // Data, Variable, Absolute
andrewhead 0:4df415dde990 163
andrewhead 0:4df415dde990 164 USAGE_PAGE(1), 0x01, // Generic Desktop
andrewhead 0:4df415dde990 165 USAGE(1), 0x38, // scroll
andrewhead 0:4df415dde990 166 LOGICAL_MINIMUM(1), 0x81, // -127
andrewhead 0:4df415dde990 167 LOGICAL_MAXIMUM(1), 0x7f, // 127
andrewhead 0:4df415dde990 168 REPORT_SIZE(1), 0x08,
andrewhead 0:4df415dde990 169 REPORT_COUNT(1), 0x01,
andrewhead 0:4df415dde990 170 INPUT(1), 0x06, // Data, Variable, Relative
andrewhead 0:4df415dde990 171
andrewhead 0:4df415dde990 172 USAGE_PAGE(1), 0x09, // Buttons
andrewhead 0:4df415dde990 173 USAGE_MINIMUM(1), 0x01,
andrewhead 0:4df415dde990 174 USAGE_MAXIMUM(1), 0x03,
andrewhead 0:4df415dde990 175 LOGICAL_MINIMUM(1), 0x00, // 0
andrewhead 0:4df415dde990 176 LOGICAL_MAXIMUM(1), 0x01, // 1
andrewhead 0:4df415dde990 177 REPORT_COUNT(1), 0x03,
andrewhead 0:4df415dde990 178 REPORT_SIZE(1), 0x01,
andrewhead 0:4df415dde990 179 INPUT(1), 0x02, // Data, Variable, Absolute
andrewhead 0:4df415dde990 180 REPORT_COUNT(1), 0x01,
andrewhead 0:4df415dde990 181 REPORT_SIZE(1), 0x05,
andrewhead 0:4df415dde990 182 INPUT(1), 0x01, // Constant
andrewhead 0:4df415dde990 183
andrewhead 0:4df415dde990 184 END_COLLECTION(0),
andrewhead 0:4df415dde990 185 END_COLLECTION(0)
andrewhead 0:4df415dde990 186 };
andrewhead 0:4df415dde990 187 reportLength = sizeof(reportDescriptor);
andrewhead 0:4df415dde990 188 return reportDescriptor;
andrewhead 0:4df415dde990 189 }
andrewhead 0:4df415dde990 190 return NULL;
andrewhead 0:4df415dde990 191 }
andrewhead 0:4df415dde990 192
andrewhead 0:4df415dde990 193 #define DEFAULT_CONFIGURATION (1)
andrewhead 0:4df415dde990 194 #define TOTAL_DESCRIPTOR_LENGTH ((1 * CONFIGURATION_DESCRIPTOR_LENGTH) \
andrewhead 0:4df415dde990 195 + (1 * INTERFACE_DESCRIPTOR_LENGTH) \
andrewhead 0:4df415dde990 196 + (1 * HID_DESCRIPTOR_LENGTH) \
andrewhead 0:4df415dde990 197 + (2 * ENDPOINT_DESCRIPTOR_LENGTH))
andrewhead 0:4df415dde990 198
andrewhead 0:4df415dde990 199 uint8_t * USBMouse::configurationDesc() {
andrewhead 0:4df415dde990 200 static uint8_t configurationDescriptor[] = {
andrewhead 0:4df415dde990 201 CONFIGURATION_DESCRIPTOR_LENGTH,// bLength
andrewhead 0:4df415dde990 202 CONFIGURATION_DESCRIPTOR, // bDescriptorType
andrewhead 0:4df415dde990 203 LSB(TOTAL_DESCRIPTOR_LENGTH), // wTotalLength (LSB)
andrewhead 0:4df415dde990 204 MSB(TOTAL_DESCRIPTOR_LENGTH), // wTotalLength (MSB)
andrewhead 0:4df415dde990 205 0x01, // bNumInterfaces
andrewhead 0:4df415dde990 206 DEFAULT_CONFIGURATION, // bConfigurationValue
andrewhead 0:4df415dde990 207 0x00, // iConfiguration
andrewhead 0:4df415dde990 208 C_RESERVED | C_SELF_POWERED, // bmAttributes
andrewhead 0:4df415dde990 209 C_POWER(0), // bMaxPowerHello World from Mbed
andrewhead 0:4df415dde990 210
andrewhead 0:4df415dde990 211 INTERFACE_DESCRIPTOR_LENGTH, // bLength
andrewhead 0:4df415dde990 212 INTERFACE_DESCRIPTOR, // bDescriptorType
andrewhead 0:4df415dde990 213 0x00, // bInterfaceNumber
andrewhead 0:4df415dde990 214 0x00, // bAlternateSetting
andrewhead 0:4df415dde990 215 0x02, // bNumEndpoints
andrewhead 0:4df415dde990 216 HID_CLASS, // bInterfaceClass
andrewhead 0:4df415dde990 217 1, // bInterfaceSubClass
andrewhead 0:4df415dde990 218 2, // bInterfaceProtocol (mouse)
andrewhead 0:4df415dde990 219 0x00, // iInterface
andrewhead 0:4df415dde990 220
andrewhead 0:4df415dde990 221 HID_DESCRIPTOR_LENGTH, // bLength
andrewhead 0:4df415dde990 222 HID_DESCRIPTOR, // bDescriptorType
andrewhead 0:4df415dde990 223 LSB(HID_VERSION_1_11), // bcdHID (LSB)
andrewhead 0:4df415dde990 224 MSB(HID_VERSION_1_11), // bcdHID (MSB)
andrewhead 0:4df415dde990 225 0x00, // bCountryCode
andrewhead 0:4df415dde990 226 0x01, // bNumDescriptors
andrewhead 0:4df415dde990 227 REPORT_DESCRIPTOR, // bDescriptorType
andrewhead 0:4df415dde990 228 (uint8_t)(LSB(reportDescLength())), // wDescriptorLength (LSB)
andrewhead 0:4df415dde990 229 (uint8_t)(MSB(reportDescLength())), // wDescriptorLength (MSB)
andrewhead 0:4df415dde990 230
andrewhead 0:4df415dde990 231 ENDPOINT_DESCRIPTOR_LENGTH, // bLength
andrewhead 0:4df415dde990 232 ENDPOINT_DESCRIPTOR, // bDescriptorType
andrewhead 0:4df415dde990 233 PHY_TO_DESC(EPINT_IN), // bEndpointAddress
andrewhead 0:4df415dde990 234 E_INTERRUPT, // bmAttributes
andrewhead 0:4df415dde990 235 LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB)
andrewhead 0:4df415dde990 236 MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB)
andrewhead 0:4df415dde990 237 1, // bInterval (milliseconds)
andrewhead 0:4df415dde990 238
andrewhead 0:4df415dde990 239 ENDPOINT_DESCRIPTOR_LENGTH, // bLength
andrewhead 0:4df415dde990 240 ENDPOINT_DESCRIPTOR, // bDescriptorType
andrewhead 0:4df415dde990 241 PHY_TO_DESC(EPINT_OUT), // bEndpointAddress
andrewhead 0:4df415dde990 242 E_INTERRUPT, // bmAttributes
andrewhead 0:4df415dde990 243 LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB)
andrewhead 0:4df415dde990 244 MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB)
andrewhead 0:4df415dde990 245 1, // bInterval (milliseconds)
andrewhead 0:4df415dde990 246 };
andrewhead 0:4df415dde990 247 return configurationDescriptor;
andrewhead 0:4df415dde990 248 }