USB HID Joystick Example (modified USBMouse)

Dependencies:   mbed

Committer:
bricklife
Date:
Wed Jan 19 11:27:13 2011 +0000
Revision:
1:ec6deffecbd3
Parent:
0:d450e82033a1

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bricklife 0:d450e82033a1 1 /* usbhid.cpp */
bricklife 0:d450e82033a1 2 /* USB HID class device */
bricklife 0:d450e82033a1 3 /* Copyright (c) Phil Wright 2008 */
bricklife 0:d450e82033a1 4
bricklife 0:d450e82033a1 5 /* modified by Shinichiro Oba <http://mbed.org/users/bricklife/> */
bricklife 0:d450e82033a1 6
bricklife 0:d450e82033a1 7 #include "mbed.h"
bricklife 0:d450e82033a1 8 #include "usbhid.h"
bricklife 0:d450e82033a1 9 #include "asciihid.h"
bricklife 0:d450e82033a1 10
bricklife 0:d450e82033a1 11 /* Endpoint packet sizes */
bricklife 0:d450e82033a1 12 #define MAX_PACKET_SIZE_EP1 (64)
bricklife 0:d450e82033a1 13
bricklife 0:d450e82033a1 14 /* HID Class */
bricklife 0:d450e82033a1 15 #define HID_CLASS (3)
bricklife 0:d450e82033a1 16 #define HID_SUBCLASS_NONE (0)
bricklife 0:d450e82033a1 17 #define HID_PROTOCOL_NONE (0)
bricklife 0:d450e82033a1 18 #define HID_DESCRIPTOR (33)
bricklife 0:d450e82033a1 19 #define REPORT_DESCRIPTOR (34)
bricklife 0:d450e82033a1 20
bricklife 0:d450e82033a1 21 /* Class requests */
bricklife 0:d450e82033a1 22 #define GET_REPORT (0x1)
bricklife 0:d450e82033a1 23 #define GET_IDLE (0x2)
bricklife 0:d450e82033a1 24 #define SET_REPORT (0x9)
bricklife 0:d450e82033a1 25 #define SET_IDLE (0xa)
bricklife 0:d450e82033a1 26
bricklife 0:d450e82033a1 27 /* Descriptors */
bricklife 0:d450e82033a1 28 unsigned char deviceDescriptor[] = {
bricklife 0:d450e82033a1 29 0x12, /* bLength */
bricklife 0:d450e82033a1 30 DEVICE_DESCRIPTOR, /* bDescriptorType */
bricklife 0:d450e82033a1 31 0x00, /* bcdUSB (LSB) */
bricklife 0:d450e82033a1 32 0x02, /* bcdUSB (MSB) */
bricklife 0:d450e82033a1 33 0x00, /* bDeviceClass */
bricklife 0:d450e82033a1 34 0x00, /* bDeviceSubClass */
bricklife 0:d450e82033a1 35 0x00, /* bDeviceprotocol */
bricklife 0:d450e82033a1 36 MAX_PACKET_SIZE_EP0, /* bMaxPacketSize0 */
bricklife 0:d450e82033a1 37 0x28, /* idVendor (LSB) */
bricklife 0:d450e82033a1 38 0x0d, /* idVendor (MSB) */
bricklife 0:d450e82033a1 39 0x05, /* idProduct (LSB) */
bricklife 0:d450e82033a1 40 0x02, /* idProduct (MSB) */
bricklife 0:d450e82033a1 41 0x00, /* bcdDevice (LSB) */
bricklife 0:d450e82033a1 42 0x00, /* bcdDevice (MSB) */
bricklife 0:d450e82033a1 43 0x00, /* iManufacturer */
bricklife 0:d450e82033a1 44 0x00, /* iProduct */
bricklife 0:d450e82033a1 45 0x00, /* iSerialNumber */
bricklife 0:d450e82033a1 46 0x01 /* bNumConfigurations */
bricklife 0:d450e82033a1 47 };
bricklife 0:d450e82033a1 48
bricklife 0:d450e82033a1 49 unsigned char configurationDescriptor[] = {
bricklife 0:d450e82033a1 50 0x09, /* bLength */
bricklife 0:d450e82033a1 51 CONFIGURATION_DESCRIPTOR, /* bDescriptorType */
bricklife 0:d450e82033a1 52 0x09+0x09+0x09+0x07, /* wTotalLength (LSB) */
bricklife 0:d450e82033a1 53 0x00, /* wTotalLength (MSB) */
bricklife 0:d450e82033a1 54 0x01, /* bNumInterfaces */
bricklife 0:d450e82033a1 55 0x01, /* bConfigurationValue */
bricklife 0:d450e82033a1 56 0x00, /* iConfiguration */
bricklife 0:d450e82033a1 57 0xc0, /* bmAttributes */
bricklife 0:d450e82033a1 58 0x00, /* bMaxPower */
bricklife 0:d450e82033a1 59
bricklife 0:d450e82033a1 60 0x09, /* bLength */
bricklife 0:d450e82033a1 61 INTERFACE_DESCRIPTOR, /* bDescriptorType */
bricklife 0:d450e82033a1 62 0x00, /* bInterfaceNumber */
bricklife 0:d450e82033a1 63 0x00, /* bAlternateSetting */
bricklife 0:d450e82033a1 64 0x01, /* bNumEndpoints */
bricklife 0:d450e82033a1 65 HID_CLASS, /* bInterfaceClass */
bricklife 0:d450e82033a1 66 HID_SUBCLASS_NONE, /* bInterfaceSubClass */
bricklife 0:d450e82033a1 67 HID_PROTOCOL_NONE, /* bInterfaceProtocol */
bricklife 0:d450e82033a1 68 0x00, /* iInterface */
bricklife 0:d450e82033a1 69
bricklife 0:d450e82033a1 70 0x09, /* bLength */
bricklife 0:d450e82033a1 71 HID_DESCRIPTOR, /* bDescriptorType */
bricklife 0:d450e82033a1 72 0x11, /* bcdHID (LSB) */
bricklife 0:d450e82033a1 73 0x01, /* bcdHID (MSB) */
bricklife 0:d450e82033a1 74 0x00, /* bCountryCode */
bricklife 0:d450e82033a1 75 0x01, /* bNumDescriptors */
bricklife 0:d450e82033a1 76 REPORT_DESCRIPTOR, /* bDescriptorType */
bricklife 0:d450e82033a1 77 0x79, /* wDescriptorLength (LSB) */
bricklife 0:d450e82033a1 78 0x00, /* wDescriptorLength (MSB) */
bricklife 0:d450e82033a1 79
bricklife 0:d450e82033a1 80 0x07, /* bLength */
bricklife 0:d450e82033a1 81 ENDPOINT_DESCRIPTOR, /* bDescriptorType */
bricklife 0:d450e82033a1 82 0x81, /* bEndpointAddress */
bricklife 0:d450e82033a1 83 0x03, /* bmAttributes */
bricklife 0:d450e82033a1 84 MAX_PACKET_SIZE_EP1, /* wMaxPacketSize (LSB) */
bricklife 0:d450e82033a1 85 0x00, /* wMaxPacketSize (MSB) */
bricklife 0:d450e82033a1 86 0x0a, /* bInterval */
bricklife 0:d450e82033a1 87 };
bricklife 0:d450e82033a1 88
bricklife 0:d450e82033a1 89 /* HID Class Report Descriptor */
bricklife 0:d450e82033a1 90 /* Short items: size is 0, 1, 2 or 3 specifying 0, 1, 2 or 4 (four) bytes of data as per HID Class standard */
bricklife 0:d450e82033a1 91
bricklife 0:d450e82033a1 92 /* Main items */
bricklife 0:d450e82033a1 93 #define INPUT(size) (0x80 | size)
bricklife 0:d450e82033a1 94 #define OUTPUT(size) (0x90 | size)
bricklife 0:d450e82033a1 95 #define FEATURE(size) (0xb0 | size)
bricklife 0:d450e82033a1 96 #define COLLECTION(size) (0xa0 | size)
bricklife 0:d450e82033a1 97 #define END_COLLECTION(size) (0xc0 | size)
bricklife 0:d450e82033a1 98
bricklife 0:d450e82033a1 99 /* Global items */
bricklife 0:d450e82033a1 100 #define USAGE_PAGE(size) (0x04 | size)
bricklife 0:d450e82033a1 101 #define LOGICAL_MIN(size) (0x14 | size)
bricklife 0:d450e82033a1 102 #define LOGICAL_MAX(size) (0x24 | size)
bricklife 0:d450e82033a1 103 #define PHYSICAL_MIN(size) (0x34 | size)
bricklife 0:d450e82033a1 104 #define PHYSICAL_MAX(size) (0x44 | size)
bricklife 0:d450e82033a1 105 #define UNIT_EXPONENT(size) (0x54 | size)
bricklife 0:d450e82033a1 106 #define UNIT(size) (0x64 | size)
bricklife 0:d450e82033a1 107 #define REPORT_SIZE(size) (0x74 | size)
bricklife 0:d450e82033a1 108 #define REPORT_ID(size) (0x84 | size)
bricklife 0:d450e82033a1 109 #define REPORT_COUNT(size) (0x94 | size)
bricklife 0:d450e82033a1 110 #define PUSH(size) (0xa4 | size)
bricklife 0:d450e82033a1 111 #define POP(size) (0xb4 | size)
bricklife 0:d450e82033a1 112
bricklife 0:d450e82033a1 113 /* Local items */
bricklife 0:d450e82033a1 114 #define USAGE(size) (0x08 | size)
bricklife 0:d450e82033a1 115 #define USAGE_MIN(size) (0x18 | size)
bricklife 0:d450e82033a1 116 #define USAGE_MAX(size) (0x28 | size)
bricklife 0:d450e82033a1 117 #define DESIGNATOR_INDEX(size) (0x38 | size)
bricklife 0:d450e82033a1 118 #define DESIGNATOR_MIN(size) (0x48 | size)
bricklife 0:d450e82033a1 119 #define DESIGNATOR_MAX(size) (0x58 | size)
bricklife 0:d450e82033a1 120 #define STRING_INDEX(size) (0x78 | size)
bricklife 0:d450e82033a1 121 #define STRING_MIN(size) (0x88 | size)
bricklife 0:d450e82033a1 122 #define STRING_MAX(size) (0x98 | size)
bricklife 0:d450e82033a1 123 #define DELIMITER(size) (0xa8 | size)
bricklife 0:d450e82033a1 124
bricklife 0:d450e82033a1 125 #define REPORT_ID_KEYBOARD (1)
bricklife 0:d450e82033a1 126 #define REPORT_ID_MOUSE (2)
bricklife 0:d450e82033a1 127
bricklife 0:d450e82033a1 128 #define MAX_REPORT_SIZE (8)
bricklife 0:d450e82033a1 129
bricklife 0:d450e82033a1 130 unsigned char reportDescriptor[] = {
bricklife 0:d450e82033a1 131 /* Keyboard */
bricklife 0:d450e82033a1 132 USAGE_PAGE(1), 0x01,
bricklife 0:d450e82033a1 133 USAGE(1), 0x06,
bricklife 0:d450e82033a1 134 COLLECTION(1), 0x01,
bricklife 0:d450e82033a1 135 REPORT_ID(1), REPORT_ID_KEYBOARD,
bricklife 0:d450e82033a1 136 USAGE_PAGE(1), 0x07,
bricklife 0:d450e82033a1 137 USAGE_MIN(1), 0xE0,
bricklife 0:d450e82033a1 138 USAGE_MAX(1), 0xE7,
bricklife 0:d450e82033a1 139 LOGICAL_MIN(1), 0x00,
bricklife 0:d450e82033a1 140 LOGICAL_MAX(1), 0x01,
bricklife 0:d450e82033a1 141 REPORT_SIZE(1), 0x01,
bricklife 0:d450e82033a1 142 REPORT_COUNT(1), 0x08,
bricklife 0:d450e82033a1 143 INPUT(1), 0x02,
bricklife 0:d450e82033a1 144 REPORT_COUNT(1), 0x01,
bricklife 0:d450e82033a1 145 REPORT_SIZE(1), 0x08,
bricklife 0:d450e82033a1 146 INPUT(1), 0x01,
bricklife 0:d450e82033a1 147 REPORT_COUNT(1), 0x05,
bricklife 0:d450e82033a1 148 REPORT_SIZE(1), 0x01,
bricklife 0:d450e82033a1 149 USAGE_PAGE(1), 0x08,
bricklife 0:d450e82033a1 150 USAGE_MIN(1), 0x01,
bricklife 0:d450e82033a1 151 USAGE_MAX(1), 0x05,
bricklife 0:d450e82033a1 152 OUTPUT(1), 0x02,
bricklife 0:d450e82033a1 153 REPORT_COUNT(1), 0x01,
bricklife 0:d450e82033a1 154 REPORT_SIZE(1), 0x03,
bricklife 0:d450e82033a1 155 OUTPUT(1), 0x01,
bricklife 0:d450e82033a1 156 REPORT_COUNT(1), 0x06,
bricklife 0:d450e82033a1 157 REPORT_SIZE(1), 0x08,
bricklife 0:d450e82033a1 158 LOGICAL_MIN(1), 0x00,
bricklife 0:d450e82033a1 159 LOGICAL_MAX(2), 0xff, 0x00,
bricklife 0:d450e82033a1 160 USAGE_PAGE(1), 0x07,
bricklife 0:d450e82033a1 161 USAGE_MIN(1), 0x00,
bricklife 0:d450e82033a1 162 USAGE_MAX(2), 0xff, 0x00,
bricklife 0:d450e82033a1 163 INPUT(1), 0x00,
bricklife 0:d450e82033a1 164 END_COLLECTION(0),
bricklife 0:d450e82033a1 165
bricklife 0:d450e82033a1 166 /* Mouse */
bricklife 0:d450e82033a1 167 USAGE_PAGE(1), 0x01,
bricklife 0:d450e82033a1 168 USAGE(1), 0x02,
bricklife 0:d450e82033a1 169 COLLECTION(1), 0x01,
bricklife 0:d450e82033a1 170 USAGE(1), 0x01,
bricklife 0:d450e82033a1 171 COLLECTION(1), 0x00,
bricklife 0:d450e82033a1 172 REPORT_ID(1), REPORT_ID_MOUSE,
bricklife 0:d450e82033a1 173 REPORT_COUNT(1), 0x03,
bricklife 0:d450e82033a1 174 REPORT_SIZE(1), 0x01,
bricklife 0:d450e82033a1 175 USAGE_PAGE(1), 0x09,
bricklife 0:d450e82033a1 176 USAGE_MIN(1), 0x1,
bricklife 0:d450e82033a1 177 USAGE_MAX(1), 0x3,
bricklife 0:d450e82033a1 178 LOGICAL_MIN(1), 0x00,
bricklife 0:d450e82033a1 179 LOGICAL_MAX(1), 0x01,
bricklife 0:d450e82033a1 180 INPUT(1), 0x02,
bricklife 0:d450e82033a1 181 REPORT_COUNT(1), 0x01,
bricklife 0:d450e82033a1 182 REPORT_SIZE(1), 0x05,
bricklife 0:d450e82033a1 183 INPUT(1), 0x01,
bricklife 0:d450e82033a1 184 REPORT_COUNT(1), 0x03,
bricklife 0:d450e82033a1 185 REPORT_SIZE(1), 0x08,
bricklife 0:d450e82033a1 186 USAGE_PAGE(1), 0x01,
bricklife 0:d450e82033a1 187 USAGE(1), 0x30,
bricklife 0:d450e82033a1 188 USAGE(1), 0x31,
bricklife 0:d450e82033a1 189 USAGE(1), 0x38,
bricklife 0:d450e82033a1 190 LOGICAL_MIN(1), 0x81,
bricklife 0:d450e82033a1 191 LOGICAL_MAX(1), 0x7f,
bricklife 0:d450e82033a1 192 INPUT(1), 0x06,
bricklife 0:d450e82033a1 193 END_COLLECTION(0),
bricklife 0:d450e82033a1 194 END_COLLECTION(0),
bricklife 0:d450e82033a1 195 };
bricklife 0:d450e82033a1 196
bricklife 0:d450e82033a1 197 volatile bool complete;
bricklife 0:d450e82033a1 198 volatile bool configured;
bricklife 0:d450e82033a1 199 unsigned char outputReport[MAX_REPORT_SIZE];
bricklife 0:d450e82033a1 200
bricklife 0:d450e82033a1 201 usbhid::usbhid()
bricklife 0:d450e82033a1 202 {
bricklife 0:d450e82033a1 203 configured = false;
bricklife 0:d450e82033a1 204 connect();
bricklife 0:d450e82033a1 205 }
bricklife 0:d450e82033a1 206
bricklife 0:d450e82033a1 207 void usbhid::deviceEventReset()
bricklife 0:d450e82033a1 208 {
bricklife 0:d450e82033a1 209 configured = false;
bricklife 0:d450e82033a1 210
bricklife 0:d450e82033a1 211 /* Must call base class */
bricklife 0:d450e82033a1 212 usbdevice::deviceEventReset();
bricklife 0:d450e82033a1 213 }
bricklife 0:d450e82033a1 214
bricklife 0:d450e82033a1 215 bool usbhid::requestSetConfiguration(void)
bricklife 0:d450e82033a1 216 {
bricklife 0:d450e82033a1 217 bool result;
bricklife 0:d450e82033a1 218
bricklife 0:d450e82033a1 219 /* Configure IN interrupt endpoint */
bricklife 0:d450e82033a1 220 realiseEndpoint(EP1IN, MAX_PACKET_SIZE_EP1);
bricklife 0:d450e82033a1 221 enableEndpointEvent(EP1IN);
bricklife 0:d450e82033a1 222
bricklife 0:d450e82033a1 223 /* Must call base class */
bricklife 0:d450e82033a1 224 result = usbdevice::requestSetConfiguration();
bricklife 0:d450e82033a1 225
bricklife 0:d450e82033a1 226 if (result)
bricklife 0:d450e82033a1 227 {
bricklife 0:d450e82033a1 228 /* Now configured */
bricklife 0:d450e82033a1 229 configured = true;
bricklife 0:d450e82033a1 230 }
bricklife 0:d450e82033a1 231
bricklife 0:d450e82033a1 232 return result;
bricklife 0:d450e82033a1 233 }
bricklife 0:d450e82033a1 234
bricklife 0:d450e82033a1 235 bool usbhid::requestGetDescriptor(void)
bricklife 0:d450e82033a1 236 {
bricklife 0:d450e82033a1 237 bool success = false;
bricklife 0:d450e82033a1 238
bricklife 0:d450e82033a1 239 switch (DESCRIPTOR_TYPE(transfer.setup.wValue))
bricklife 0:d450e82033a1 240 {
bricklife 0:d450e82033a1 241 case DEVICE_DESCRIPTOR:
bricklife 0:d450e82033a1 242 transfer.remaining = sizeof(deviceDescriptor);
bricklife 0:d450e82033a1 243 transfer.ptr = deviceDescriptor;
bricklife 0:d450e82033a1 244 transfer.direction = DEVICE_TO_HOST;
bricklife 0:d450e82033a1 245 success = true;
bricklife 0:d450e82033a1 246 break;
bricklife 0:d450e82033a1 247 case CONFIGURATION_DESCRIPTOR:
bricklife 0:d450e82033a1 248 transfer.remaining = sizeof(configurationDescriptor);
bricklife 0:d450e82033a1 249 transfer.ptr = configurationDescriptor;
bricklife 0:d450e82033a1 250 transfer.direction = DEVICE_TO_HOST;
bricklife 0:d450e82033a1 251 success = true;
bricklife 0:d450e82033a1 252 break;
bricklife 0:d450e82033a1 253 case STRING_DESCRIPTOR:
bricklife 0:d450e82033a1 254 case INTERFACE_DESCRIPTOR:
bricklife 0:d450e82033a1 255 case ENDPOINT_DESCRIPTOR:
bricklife 0:d450e82033a1 256 /* TODO: Support is optional, not implemented here */
bricklife 0:d450e82033a1 257 break;
bricklife 0:d450e82033a1 258 case HID_DESCRIPTOR:
bricklife 0:d450e82033a1 259 transfer.remaining = 0x09; /* TODO: Fix hard coded size/offset */
bricklife 0:d450e82033a1 260 transfer.ptr = &configurationDescriptor[18];
bricklife 0:d450e82033a1 261 transfer.direction = DEVICE_TO_HOST;
bricklife 0:d450e82033a1 262 success = true;
bricklife 0:d450e82033a1 263 break;
bricklife 0:d450e82033a1 264 case REPORT_DESCRIPTOR:
bricklife 0:d450e82033a1 265 transfer.remaining = sizeof(reportDescriptor);
bricklife 0:d450e82033a1 266 transfer.ptr = reportDescriptor;
bricklife 0:d450e82033a1 267 transfer.direction = DEVICE_TO_HOST;
bricklife 0:d450e82033a1 268 success = true;
bricklife 0:d450e82033a1 269 break;
bricklife 0:d450e82033a1 270 default:
bricklife 0:d450e82033a1 271 break;
bricklife 0:d450e82033a1 272 }
bricklife 0:d450e82033a1 273
bricklife 0:d450e82033a1 274 return success;
bricklife 0:d450e82033a1 275 }
bricklife 0:d450e82033a1 276
bricklife 0:d450e82033a1 277 bool usbhid::requestSetup(void)
bricklife 0:d450e82033a1 278 {
bricklife 0:d450e82033a1 279 /* Process class requests */
bricklife 0:d450e82033a1 280 bool success = false;
bricklife 0:d450e82033a1 281
bricklife 0:d450e82033a1 282 if (transfer.setup.bmRequestType.Type == CLASS_TYPE)
bricklife 0:d450e82033a1 283 {
bricklife 0:d450e82033a1 284 switch (transfer.setup.bRequest)
bricklife 0:d450e82033a1 285 {
bricklife 0:d450e82033a1 286 case SET_REPORT:
bricklife 0:d450e82033a1 287 switch (transfer.setup.wValue & 0xff)
bricklife 0:d450e82033a1 288 {
bricklife 0:d450e82033a1 289 case REPORT_ID_KEYBOARD:
bricklife 0:d450e82033a1 290 /* TODO: LED state */
bricklife 0:d450e82033a1 291 transfer.remaining = sizeof(outputReport);
bricklife 0:d450e82033a1 292 transfer.ptr = outputReport;
bricklife 0:d450e82033a1 293 transfer.direction = HOST_TO_DEVICE;
bricklife 0:d450e82033a1 294 success = true;
bricklife 0:d450e82033a1 295 break;
bricklife 0:d450e82033a1 296 default:
bricklife 0:d450e82033a1 297 break;
bricklife 0:d450e82033a1 298 }
bricklife 0:d450e82033a1 299 break;
bricklife 0:d450e82033a1 300 default:
bricklife 0:d450e82033a1 301 break;
bricklife 0:d450e82033a1 302 }
bricklife 0:d450e82033a1 303 }
bricklife 0:d450e82033a1 304
bricklife 0:d450e82033a1 305 if (success)
bricklife 0:d450e82033a1 306 {
bricklife 0:d450e82033a1 307 /* We've handled this request */
bricklife 0:d450e82033a1 308 return true;
bricklife 0:d450e82033a1 309 }
bricklife 0:d450e82033a1 310
bricklife 0:d450e82033a1 311 return usbdevice::requestSetup();
bricklife 0:d450e82033a1 312 }
bricklife 0:d450e82033a1 313
bricklife 0:d450e82033a1 314 bool usbhid::sendInputReport(unsigned char id, unsigned char *data, unsigned char size)
bricklife 0:d450e82033a1 315 {
bricklife 0:d450e82033a1 316 /* Send an Input Report */
bricklife 0:d450e82033a1 317 /* If data is NULL an all zero report is sent */
bricklife 0:d450e82033a1 318
bricklife 0:d450e82033a1 319 static unsigned char report[MAX_REPORT_SIZE+1]; /* +1 for report ID */
bricklife 0:d450e82033a1 320 unsigned char i;
bricklife 0:d450e82033a1 321
bricklife 0:d450e82033a1 322 if (size > MAX_REPORT_SIZE)
bricklife 0:d450e82033a1 323 {
bricklife 0:d450e82033a1 324 return false;
bricklife 0:d450e82033a1 325 }
bricklife 0:d450e82033a1 326
bricklife 0:d450e82033a1 327 /* Add report ID */
bricklife 0:d450e82033a1 328 report[0]=id;
bricklife 0:d450e82033a1 329
bricklife 0:d450e82033a1 330 /* Add report data */
bricklife 0:d450e82033a1 331 if (data != NULL)
bricklife 0:d450e82033a1 332 {
bricklife 0:d450e82033a1 333 for (i=0; i<size; i++)
bricklife 0:d450e82033a1 334 {
bricklife 0:d450e82033a1 335 report[i+1] = *data++;
bricklife 0:d450e82033a1 336 }
bricklife 0:d450e82033a1 337 }
bricklife 0:d450e82033a1 338 else
bricklife 0:d450e82033a1 339 {
bricklife 0:d450e82033a1 340 for (i=0; i<size; i++)
bricklife 0:d450e82033a1 341 {
bricklife 0:d450e82033a1 342 report[i+1] = 0;
bricklife 0:d450e82033a1 343 }
bricklife 0:d450e82033a1 344 }
bricklife 0:d450e82033a1 345
bricklife 0:d450e82033a1 346 /* Block if not configured */
bricklife 0:d450e82033a1 347 while (!configured);
bricklife 0:d450e82033a1 348
bricklife 0:d450e82033a1 349 /* Send report */
bricklife 0:d450e82033a1 350 complete = false;
bricklife 0:d450e82033a1 351 disableEvents();
bricklife 0:d450e82033a1 352 endpointWrite(EP1IN, report, size+1); /* +1 for report ID */
bricklife 0:d450e82033a1 353 enableEvents();
bricklife 0:d450e82033a1 354
bricklife 0:d450e82033a1 355 /* Wait for completion */
bricklife 0:d450e82033a1 356 while(!complete && configured);
bricklife 0:d450e82033a1 357 return true;
bricklife 0:d450e82033a1 358 }
bricklife 0:d450e82033a1 359
bricklife 0:d450e82033a1 360 void usbhid::endpointEventEP1In(void)
bricklife 0:d450e82033a1 361 {
bricklife 0:d450e82033a1 362 complete = true;
bricklife 0:d450e82033a1 363 }
bricklife 0:d450e82033a1 364
bricklife 0:d450e82033a1 365 bool usbhid::keyboard(char c)
bricklife 0:d450e82033a1 366 {
bricklife 0:d450e82033a1 367 /* Send a simulated keyboard keypress. Returns true if successful. */
bricklife 0:d450e82033a1 368 unsigned char report[8]={0,0,0,0,0,0,0,0};
bricklife 0:d450e82033a1 369
bricklife 0:d450e82033a1 370 report[0] = keymap[c].modifier;
bricklife 0:d450e82033a1 371 report[2] = keymap[c].usage;
bricklife 0:d450e82033a1 372
bricklife 0:d450e82033a1 373 /* Key down */
bricklife 0:d450e82033a1 374 if (!sendInputReport(REPORT_ID_KEYBOARD, report, 8))
bricklife 0:d450e82033a1 375 {
bricklife 0:d450e82033a1 376 return false;
bricklife 0:d450e82033a1 377 }
bricklife 0:d450e82033a1 378
bricklife 0:d450e82033a1 379 /* Key up */
bricklife 0:d450e82033a1 380 if (!sendInputReport(REPORT_ID_KEYBOARD, NULL, 8))
bricklife 0:d450e82033a1 381 {
bricklife 0:d450e82033a1 382 return false;
bricklife 0:d450e82033a1 383 }
bricklife 0:d450e82033a1 384
bricklife 0:d450e82033a1 385 return true;
bricklife 0:d450e82033a1 386 }
bricklife 0:d450e82033a1 387
bricklife 0:d450e82033a1 388 bool usbhid::keyboard(char *string)
bricklife 0:d450e82033a1 389 {
bricklife 0:d450e82033a1 390 /* Send a string of characters. Returns true if successful. */
bricklife 0:d450e82033a1 391 do {
bricklife 0:d450e82033a1 392 if (!keyboard(*string++))
bricklife 0:d450e82033a1 393 {
bricklife 0:d450e82033a1 394 return false;
bricklife 0:d450e82033a1 395 }
bricklife 0:d450e82033a1 396 } while (*string != '\0');
bricklife 0:d450e82033a1 397
bricklife 0:d450e82033a1 398 return true;
bricklife 0:d450e82033a1 399 }
bricklife 0:d450e82033a1 400
bricklife 0:d450e82033a1 401 bool usbhid::mouse(signed char x, signed char y, unsigned char buttons, signed char wheel)
bricklife 0:d450e82033a1 402 {
bricklife 0:d450e82033a1 403 /* Send a simulated mouse event. Returns true if successful. */
bricklife 0:d450e82033a1 404 unsigned char report[4]={0,0,0,0};
bricklife 0:d450e82033a1 405
bricklife 0:d450e82033a1 406 report[0] = buttons;
bricklife 0:d450e82033a1 407 report[1] = x;
bricklife 0:d450e82033a1 408 report[2] = y;
bricklife 0:d450e82033a1 409 report[3] = wheel;
bricklife 0:d450e82033a1 410
bricklife 0:d450e82033a1 411 if (!sendInputReport(REPORT_ID_MOUSE, report, 4))
bricklife 0:d450e82033a1 412 {
bricklife 0:d450e82033a1 413 return false;
bricklife 0:d450e82033a1 414 }
bricklife 0:d450e82033a1 415
bricklife 0:d450e82033a1 416 return true;
bricklife 0:d450e82033a1 417 }
bricklife 0:d450e82033a1 418
bricklife 0:d450e82033a1 419
bricklife 0:d450e82033a1 420 //
bricklife 0:d450e82033a1 421 // USBJoystick
bricklife 0:d450e82033a1 422 //
bricklife 0:d450e82033a1 423
bricklife 0:d450e82033a1 424 unsigned char reportDescriptorJoystick[] = {
bricklife 0:d450e82033a1 425 USAGE_PAGE(1), 0x01,
bricklife 0:d450e82033a1 426 USAGE(1), 0x04,
bricklife 0:d450e82033a1 427 COLLECTION(1), 0x01,
bricklife 0:d450e82033a1 428 USAGE(1), 0x01,
bricklife 0:d450e82033a1 429 COLLECTION(1), 0x00,
bricklife 0:d450e82033a1 430
bricklife 0:d450e82033a1 431 USAGE_PAGE(1), 0x09,
bricklife 0:d450e82033a1 432 USAGE_MIN(1), 0x01,
bricklife 0:d450e82033a1 433 USAGE_MAX(1), 0x0C,
bricklife 0:d450e82033a1 434 LOGICAL_MIN(1), 0x00,
bricklife 0:d450e82033a1 435 LOGICAL_MAX(1), 0x01,
bricklife 0:d450e82033a1 436 PHYSICAL_MIN(1), 0x00,
bricklife 0:d450e82033a1 437 PHYSICAL_MAX(1), 0x01,
bricklife 0:d450e82033a1 438 REPORT_SIZE(1), 0x01,
bricklife 0:d450e82033a1 439 REPORT_COUNT(1), 0x0C,
bricklife 0:d450e82033a1 440 INPUT(1), 0x02,
bricklife 0:d450e82033a1 441
bricklife 0:d450e82033a1 442 USAGE_PAGE(1), 0x01,
bricklife 0:d450e82033a1 443 USAGE(1), 0x39,
bricklife 0:d450e82033a1 444 LOGICAL_MIN(1), 0x00,
bricklife 0:d450e82033a1 445 LOGICAL_MAX(1), 0x07,
bricklife 0:d450e82033a1 446 PHYSICAL_MIN(1), 0x00,
bricklife 0:d450e82033a1 447 PHYSICAL_MAX(2), 0x3B, 0x01,
bricklife 0:d450e82033a1 448 UNIT(1), 0x14,
bricklife 0:d450e82033a1 449 REPORT_SIZE(1), 0x04,
bricklife 0:d450e82033a1 450 REPORT_COUNT(1), 0x01,
bricklife 0:d450e82033a1 451 INPUT(1), 0x42,
bricklife 0:d450e82033a1 452
bricklife 0:d450e82033a1 453 USAGE_PAGE(1), 0x01,
bricklife 0:d450e82033a1 454 USAGE(1), 0x30,
bricklife 0:d450e82033a1 455 USAGE(1), 0x31,
bricklife 0:d450e82033a1 456 USAGE(1), 0x32,
bricklife 0:d450e82033a1 457 USAGE(1), 0x35,
bricklife 0:d450e82033a1 458 LOGICAL_MIN(1), 0x00,
bricklife 0:d450e82033a1 459 LOGICAL_MAX(2), 0xff, 0x00,
bricklife 0:d450e82033a1 460 PHYSICAL_MIN(1), 0x00,
bricklife 0:d450e82033a1 461 PHYSICAL_MAX(2), 0xff, 0x00,
bricklife 0:d450e82033a1 462 UNIT(2), 0x00, 0x00,
bricklife 0:d450e82033a1 463 REPORT_SIZE(1), 0x08,
bricklife 0:d450e82033a1 464 REPORT_COUNT(1), 0x04,
bricklife 0:d450e82033a1 465 INPUT(1), 0x02,
bricklife 0:d450e82033a1 466
bricklife 0:d450e82033a1 467 END_COLLECTION(0),
bricklife 0:d450e82033a1 468 END_COLLECTION(0),
bricklife 0:d450e82033a1 469 };
bricklife 0:d450e82033a1 470
bricklife 0:d450e82033a1 471 USBJoystick::USBJoystick()
bricklife 0:d450e82033a1 472 {
bricklife 0:d450e82033a1 473 int reportDescriptorSize = sizeof(reportDescriptorJoystick);
bricklife 0:d450e82033a1 474 configurationDescriptor[25] = reportDescriptorSize & 0xff;
bricklife 0:d450e82033a1 475 configurationDescriptor[26] = (reportDescriptorSize >> 8) & 0xff;
bricklife 0:d450e82033a1 476 }
bricklife 0:d450e82033a1 477
bricklife 0:d450e82033a1 478 bool USBJoystick::requestGetDescriptor(void)
bricklife 0:d450e82033a1 479 {
bricklife 0:d450e82033a1 480 bool success = false;
bricklife 0:d450e82033a1 481
bricklife 0:d450e82033a1 482 switch (DESCRIPTOR_TYPE(transfer.setup.wValue))
bricklife 0:d450e82033a1 483 {
bricklife 0:d450e82033a1 484 case REPORT_DESCRIPTOR:
bricklife 0:d450e82033a1 485 transfer.remaining = sizeof(reportDescriptorJoystick);
bricklife 0:d450e82033a1 486 transfer.ptr = reportDescriptorJoystick;
bricklife 0:d450e82033a1 487 transfer.direction = DEVICE_TO_HOST;
bricklife 0:d450e82033a1 488 success = true;
bricklife 0:d450e82033a1 489 break;
bricklife 0:d450e82033a1 490 default:
bricklife 0:d450e82033a1 491 success = usbhid::requestGetDescriptor();
bricklife 0:d450e82033a1 492 break;
bricklife 0:d450e82033a1 493 }
bricklife 0:d450e82033a1 494
bricklife 0:d450e82033a1 495 return success;
bricklife 0:d450e82033a1 496 }
bricklife 0:d450e82033a1 497
bricklife 0:d450e82033a1 498 bool USBJoystick::sendInputReport(unsigned char *data, unsigned char size)
bricklife 0:d450e82033a1 499 {
bricklife 0:d450e82033a1 500 /* Send an Input Report */
bricklife 0:d450e82033a1 501 /* If data is NULL an all zero report is sent */
bricklife 0:d450e82033a1 502
bricklife 0:d450e82033a1 503 static unsigned char report[MAX_REPORT_SIZE];
bricklife 0:d450e82033a1 504 unsigned char i;
bricklife 0:d450e82033a1 505
bricklife 0:d450e82033a1 506 if (size > MAX_REPORT_SIZE)
bricklife 0:d450e82033a1 507 {
bricklife 0:d450e82033a1 508 return false;
bricklife 0:d450e82033a1 509 }
bricklife 0:d450e82033a1 510
bricklife 0:d450e82033a1 511 /* Add report data */
bricklife 0:d450e82033a1 512 if (data != NULL)
bricklife 0:d450e82033a1 513 {
bricklife 0:d450e82033a1 514 for (i=0; i<size; i++)
bricklife 0:d450e82033a1 515 {
bricklife 0:d450e82033a1 516 report[i] = *data++;
bricklife 0:d450e82033a1 517 }
bricklife 0:d450e82033a1 518 }
bricklife 0:d450e82033a1 519 else
bricklife 0:d450e82033a1 520 {
bricklife 0:d450e82033a1 521 for (i=0; i<size; i++)
bricklife 0:d450e82033a1 522 {
bricklife 0:d450e82033a1 523 report[i] = 0;
bricklife 0:d450e82033a1 524 }
bricklife 0:d450e82033a1 525 }
bricklife 0:d450e82033a1 526
bricklife 0:d450e82033a1 527 /* Block if not configured */
bricklife 0:d450e82033a1 528 while (!configured);
bricklife 0:d450e82033a1 529
bricklife 0:d450e82033a1 530 /* Send report */
bricklife 0:d450e82033a1 531 complete = false;
bricklife 0:d450e82033a1 532 disableEvents();
bricklife 1:ec6deffecbd3 533 endpointWrite(EP1IN, report, size);
bricklife 0:d450e82033a1 534 enableEvents();
bricklife 0:d450e82033a1 535
bricklife 0:d450e82033a1 536 /* Wait for completion */
bricklife 0:d450e82033a1 537 while(!complete && configured);
bricklife 0:d450e82033a1 538 return true;
bricklife 0:d450e82033a1 539 }
bricklife 0:d450e82033a1 540
bricklife 0:d450e82033a1 541 bool USBJoystick::joystick(unsigned char stick, unsigned short buttons, signed char x, signed char y, signed char z, signed char rz)
bricklife 0:d450e82033a1 542 {
bricklife 0:d450e82033a1 543 unsigned char report[6] = {0, 0, 0, 0, 0, 0};
bricklife 0:d450e82033a1 544
bricklife 0:d450e82033a1 545 unsigned char hatswitch;
bricklife 0:d450e82033a1 546 if (stick & JOYSTICK_UP) {
bricklife 1:ec6deffecbd3 547 hatswitch = 0;
bricklife 1:ec6deffecbd3 548 if (stick & JOYSTICK_RIGHT) hatswitch = 1;
bricklife 1:ec6deffecbd3 549 if (stick &JOYSTICK_LEFT) hatswitch = 7;
bricklife 0:d450e82033a1 550 } else if (stick & JOYSTICK_RIGHT) {
bricklife 1:ec6deffecbd3 551 hatswitch = 2;
bricklife 1:ec6deffecbd3 552 if (stick & JOYSTICK_DOWN) hatswitch = 3;
bricklife 0:d450e82033a1 553 } else if (stick & JOYSTICK_DOWN) {
bricklife 1:ec6deffecbd3 554 hatswitch = 4;
bricklife 1:ec6deffecbd3 555 if (stick & JOYSTICK_LEFT) hatswitch = 5;
bricklife 0:d450e82033a1 556 } else if (stick & JOYSTICK_LEFT) {
bricklife 1:ec6deffecbd3 557 hatswitch = 6;
bricklife 0:d450e82033a1 558 } else {
bricklife 0:d450e82033a1 559 hatswitch = 0xf;
bricklife 0:d450e82033a1 560 }
bricklife 0:d450e82033a1 561
bricklife 0:d450e82033a1 562 report[0] = buttons & 0xff;
bricklife 1:ec6deffecbd3 563 report[1] = ((hatswitch << 4) & 0xf0) | ((buttons >> 8) & 0x0f);
bricklife 0:d450e82033a1 564 report[2] = x + 0x80;
bricklife 0:d450e82033a1 565 report[3] = y + 0x80;
bricklife 0:d450e82033a1 566 report[4] = z + 0x80;
bricklife 0:d450e82033a1 567 report[5] = rz + 0x80;
bricklife 0:d450e82033a1 568
bricklife 0:d450e82033a1 569 if (!sendInputReport(report, 6)) {
bricklife 0:d450e82033a1 570 return false;
bricklife 0:d450e82033a1 571 }
bricklife 0:d450e82033a1 572
bricklife 0:d450e82033a1 573 return true;
bricklife 0:d450e82033a1 574 }
bricklife 0:d450e82033a1 575