USB Keyboard and mouse Example. Based on USBMouse
Fork of USBKeyboardMouse by
USBKeyboardMouse/usbhid.cpp@1:9c83250ce43b, 2013-05-08 (annotated)
- Committer:
- Wabouz
- Date:
- Wed May 08 09:33:27 2013 +0000
- Revision:
- 1:9c83250ce43b
- Parent:
- 0:86603687efec
Un petit programme.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
zackc | 0:86603687efec | 1 | /* usbhid.cpp */ |
zackc | 0:86603687efec | 2 | /* USB HID class device */ |
zackc | 0:86603687efec | 3 | /* Copyright (c) Phil Wright 2008 */ |
zackc | 0:86603687efec | 4 | |
zackc | 0:86603687efec | 5 | #include "mbed.h" |
zackc | 0:86603687efec | 6 | #include "usbhid.h" |
zackc | 0:86603687efec | 7 | #include "asciihid.h" |
zackc | 0:86603687efec | 8 | |
zackc | 0:86603687efec | 9 | /* Endpoint packet sizes */ |
zackc | 0:86603687efec | 10 | #define MAX_PACKET_SIZE_EP1 (64) |
zackc | 0:86603687efec | 11 | |
zackc | 0:86603687efec | 12 | /* HID Class */ |
zackc | 0:86603687efec | 13 | #define HID_CLASS (3) |
zackc | 0:86603687efec | 14 | #define HID_SUBCLASS_NONE (0) |
zackc | 0:86603687efec | 15 | #define HID_PROTOCOL_NONE (0) |
zackc | 0:86603687efec | 16 | #define HID_DESCRIPTOR (33) |
zackc | 0:86603687efec | 17 | #define REPORT_DESCRIPTOR (34) |
zackc | 0:86603687efec | 18 | |
zackc | 0:86603687efec | 19 | /* Class requests */ |
zackc | 0:86603687efec | 20 | #define GET_REPORT (0x1) |
zackc | 0:86603687efec | 21 | #define GET_IDLE (0x2) |
zackc | 0:86603687efec | 22 | #define SET_REPORT (0x9) |
zackc | 0:86603687efec | 23 | #define SET_IDLE (0xa) |
zackc | 0:86603687efec | 24 | |
zackc | 0:86603687efec | 25 | /* Descriptors */ |
zackc | 0:86603687efec | 26 | unsigned char deviceDescriptor[] = { |
zackc | 0:86603687efec | 27 | 0x12, /* bLength */ |
zackc | 0:86603687efec | 28 | DEVICE_DESCRIPTOR, /* bDescriptorType */ |
zackc | 0:86603687efec | 29 | 0x00, /* bcdUSB (LSB) */ |
zackc | 0:86603687efec | 30 | 0x02, /* bcdUSB (MSB) */ |
zackc | 0:86603687efec | 31 | 0x00, /* bDeviceClass */ |
zackc | 0:86603687efec | 32 | 0x00, /* bDeviceSubClass */ |
zackc | 0:86603687efec | 33 | 0x00, /* bDeviceprotocol */ |
zackc | 0:86603687efec | 34 | MAX_PACKET_SIZE_EP0, /* bMaxPacketSize0 */ |
zackc | 0:86603687efec | 35 | 0x28, /* idVendor (LSB) */ |
zackc | 0:86603687efec | 36 | 0x0d, /* idVendor (MSB) */ |
zackc | 0:86603687efec | 37 | 0x05, /* idProduct (LSB) */ |
zackc | 0:86603687efec | 38 | 0x02, /* idProduct (MSB) */ |
zackc | 0:86603687efec | 39 | 0x00, /* bcdDevice (LSB) */ |
zackc | 0:86603687efec | 40 | 0x00, /* bcdDevice (MSB) */ |
zackc | 0:86603687efec | 41 | 0x00, /* iManufacturer */ |
zackc | 0:86603687efec | 42 | 0x00, /* iProduct */ |
zackc | 0:86603687efec | 43 | 0x00, /* iSerialNumber */ |
zackc | 0:86603687efec | 44 | 0x01 /* bNumConfigurations */ |
zackc | 0:86603687efec | 45 | }; |
zackc | 0:86603687efec | 46 | |
zackc | 0:86603687efec | 47 | unsigned char configurationDescriptor[] = { |
zackc | 0:86603687efec | 48 | 0x09, /* bLength */ |
zackc | 0:86603687efec | 49 | CONFIGURATION_DESCRIPTOR, /* bDescriptorType */ |
zackc | 0:86603687efec | 50 | 0x09+0x09+0x09+0x07, /* wTotalLength (LSB) */ |
zackc | 0:86603687efec | 51 | 0x00, /* wTotalLength (MSB) */ |
zackc | 0:86603687efec | 52 | 0x01, /* bNumInterfaces */ |
zackc | 0:86603687efec | 53 | 0x01, /* bConfigurationValue */ |
zackc | 0:86603687efec | 54 | 0x00, /* iConfiguration */ |
zackc | 0:86603687efec | 55 | 0xc0, /* bmAttributes */ |
zackc | 0:86603687efec | 56 | 0x00, /* bMaxPower */ |
zackc | 0:86603687efec | 57 | |
zackc | 0:86603687efec | 58 | 0x09, /* bLength */ |
zackc | 0:86603687efec | 59 | INTERFACE_DESCRIPTOR, /* bDescriptorType */ |
zackc | 0:86603687efec | 60 | 0x00, /* bInterfaceNumber */ |
zackc | 0:86603687efec | 61 | 0x00, /* bAlternateSetting */ |
zackc | 0:86603687efec | 62 | 0x01, /* bNumEndpoints */ |
zackc | 0:86603687efec | 63 | HID_CLASS, /* bInterfaceClass */ |
zackc | 0:86603687efec | 64 | HID_SUBCLASS_NONE, /* bInterfaceSubClass */ |
zackc | 0:86603687efec | 65 | HID_PROTOCOL_NONE, /* bInterfaceProtocol */ |
zackc | 0:86603687efec | 66 | 0x00, /* iInterface */ |
zackc | 0:86603687efec | 67 | |
zackc | 0:86603687efec | 68 | 0x09, /* bLength */ |
zackc | 0:86603687efec | 69 | HID_DESCRIPTOR, /* bDescriptorType */ |
zackc | 0:86603687efec | 70 | 0x11, /* bcdHID (LSB) */ |
zackc | 0:86603687efec | 71 | 0x01, /* bcdHID (MSB) */ |
zackc | 0:86603687efec | 72 | 0x00, /* bCountryCode */ |
zackc | 0:86603687efec | 73 | 0x01, /* bNumDescriptors */ |
zackc | 0:86603687efec | 74 | REPORT_DESCRIPTOR, /* bDescriptorType */ |
zackc | 0:86603687efec | 75 | 0x79, /* wDescriptorLength (LSB) */ |
zackc | 0:86603687efec | 76 | 0x00, /* wDescriptorLength (MSB) */ |
zackc | 0:86603687efec | 77 | |
zackc | 0:86603687efec | 78 | 0x07, /* bLength */ |
zackc | 0:86603687efec | 79 | ENDPOINT_DESCRIPTOR, /* bDescriptorType */ |
zackc | 0:86603687efec | 80 | 0x81, /* bEndpointAddress */ |
zackc | 0:86603687efec | 81 | 0x03, /* bmAttributes */ |
zackc | 0:86603687efec | 82 | MAX_PACKET_SIZE_EP1, /* wMaxPacketSize (LSB) */ |
zackc | 0:86603687efec | 83 | 0x00, /* wMaxPacketSize (MSB) */ |
zackc | 0:86603687efec | 84 | 0x0a, /* bInterval */ |
zackc | 0:86603687efec | 85 | }; |
zackc | 0:86603687efec | 86 | |
zackc | 0:86603687efec | 87 | /* HID Class Report Descriptor */ |
zackc | 0:86603687efec | 88 | /* Short items: size is 0, 1, 2 or 3 specifying 0, 1, 2 or 4 (four) bytes of data as per HID Class standard */ |
zackc | 0:86603687efec | 89 | |
zackc | 0:86603687efec | 90 | /* Main items */ |
zackc | 0:86603687efec | 91 | #define INPUT(size) (0x80 | size) |
zackc | 0:86603687efec | 92 | #define OUTPUT(size) (0x90 | size) |
zackc | 0:86603687efec | 93 | #define FEATURE(size) (0xb0 | size) |
zackc | 0:86603687efec | 94 | #define COLLECTION(size) (0xa0 | size) |
zackc | 0:86603687efec | 95 | #define END_COLLECTION(size) (0xc0 | size) |
zackc | 0:86603687efec | 96 | |
zackc | 0:86603687efec | 97 | /* Global items */ |
zackc | 0:86603687efec | 98 | #define USAGE_PAGE(size) (0x04 | size) |
zackc | 0:86603687efec | 99 | #define LOGICAL_MIN(size) (0x14 | size) |
zackc | 0:86603687efec | 100 | #define LOGICAL_MAX(size) (0x24 | size) |
zackc | 0:86603687efec | 101 | #define PHYSICAL_MIN(size) (0x34 | size) |
zackc | 0:86603687efec | 102 | #define PHYSICAL_MAX(size) (0x44 | size) |
zackc | 0:86603687efec | 103 | #define UNIT_EXPONENT(size) (0x54 | size) |
zackc | 0:86603687efec | 104 | #define UNIT(size) (0x64 | size) |
zackc | 0:86603687efec | 105 | #define REPORT_SIZE(size) (0x74 | size) |
zackc | 0:86603687efec | 106 | #define REPORT_ID(size) (0x84 | size) |
zackc | 0:86603687efec | 107 | #define REPORT_COUNT(size) (0x94 | size) |
zackc | 0:86603687efec | 108 | #define PUSH(size) (0xa4 | size) |
zackc | 0:86603687efec | 109 | #define POP(size) (0xb4 | size) |
zackc | 0:86603687efec | 110 | |
zackc | 0:86603687efec | 111 | /* Local items */ |
zackc | 0:86603687efec | 112 | #define USAGE(size) (0x08 | size) |
zackc | 0:86603687efec | 113 | #define USAGE_MIN(size) (0x18 | size) |
zackc | 0:86603687efec | 114 | #define USAGE_MAX(size) (0x28 | size) |
zackc | 0:86603687efec | 115 | #define DESIGNATOR_INDEX(size) (0x38 | size) |
zackc | 0:86603687efec | 116 | #define DESIGNATOR_MIN(size) (0x48 | size) |
zackc | 0:86603687efec | 117 | #define DESIGNATOR_MAX(size) (0x58 | size) |
zackc | 0:86603687efec | 118 | #define STRING_INDEX(size) (0x78 | size) |
zackc | 0:86603687efec | 119 | #define STRING_MIN(size) (0x88 | size) |
zackc | 0:86603687efec | 120 | #define STRING_MAX(size) (0x98 | size) |
zackc | 0:86603687efec | 121 | #define DELIMITER(size) (0xa8 | size) |
zackc | 0:86603687efec | 122 | |
zackc | 0:86603687efec | 123 | #define REPORT_ID_KEYBOARD (1) |
zackc | 0:86603687efec | 124 | #define REPORT_ID_MOUSE (2) |
zackc | 0:86603687efec | 125 | |
zackc | 0:86603687efec | 126 | #define MAX_REPORT_SIZE (8) |
zackc | 0:86603687efec | 127 | |
zackc | 0:86603687efec | 128 | unsigned char reportDescriptor[] = { |
zackc | 0:86603687efec | 129 | /* Keyboard */ |
zackc | 0:86603687efec | 130 | USAGE_PAGE(1), 0x01, |
zackc | 0:86603687efec | 131 | USAGE(1), 0x06, |
zackc | 0:86603687efec | 132 | COLLECTION(1), 0x01, |
zackc | 0:86603687efec | 133 | REPORT_ID(1), REPORT_ID_KEYBOARD, |
zackc | 0:86603687efec | 134 | USAGE_PAGE(1), 0x07, |
zackc | 0:86603687efec | 135 | USAGE_MIN(1), 0xE0, |
zackc | 0:86603687efec | 136 | USAGE_MAX(1), 0xE7, |
zackc | 0:86603687efec | 137 | LOGICAL_MIN(1), 0x00, |
zackc | 0:86603687efec | 138 | LOGICAL_MAX(1), 0x01, |
zackc | 0:86603687efec | 139 | REPORT_SIZE(1), 0x01, |
zackc | 0:86603687efec | 140 | REPORT_COUNT(1), 0x08, |
zackc | 0:86603687efec | 141 | INPUT(1), 0x02, |
zackc | 0:86603687efec | 142 | REPORT_COUNT(1), 0x01, |
zackc | 0:86603687efec | 143 | REPORT_SIZE(1), 0x08, |
zackc | 0:86603687efec | 144 | INPUT(1), 0x01, |
zackc | 0:86603687efec | 145 | REPORT_COUNT(1), 0x05, |
zackc | 0:86603687efec | 146 | REPORT_SIZE(1), 0x01, |
zackc | 0:86603687efec | 147 | USAGE_PAGE(1), 0x08, |
zackc | 0:86603687efec | 148 | USAGE_MIN(1), 0x01, |
zackc | 0:86603687efec | 149 | USAGE_MAX(1), 0x05, |
zackc | 0:86603687efec | 150 | OUTPUT(1), 0x02, |
zackc | 0:86603687efec | 151 | REPORT_COUNT(1), 0x01, |
zackc | 0:86603687efec | 152 | REPORT_SIZE(1), 0x03, |
zackc | 0:86603687efec | 153 | OUTPUT(1), 0x01, |
zackc | 0:86603687efec | 154 | REPORT_COUNT(1), 0x06, |
zackc | 0:86603687efec | 155 | REPORT_SIZE(1), 0x08, |
zackc | 0:86603687efec | 156 | LOGICAL_MIN(1), 0x00, |
zackc | 0:86603687efec | 157 | LOGICAL_MAX(2), 0xff, 0x00, |
zackc | 0:86603687efec | 158 | USAGE_PAGE(1), 0x07, |
zackc | 0:86603687efec | 159 | USAGE_MIN(1), 0x00, |
zackc | 0:86603687efec | 160 | USAGE_MAX(2), 0xff, 0x00, |
zackc | 0:86603687efec | 161 | INPUT(1), 0x00, |
zackc | 0:86603687efec | 162 | END_COLLECTION(0), |
zackc | 0:86603687efec | 163 | |
zackc | 0:86603687efec | 164 | /* Mouse */ |
zackc | 0:86603687efec | 165 | USAGE_PAGE(1), 0x01, |
zackc | 0:86603687efec | 166 | USAGE(1), 0x02, |
zackc | 0:86603687efec | 167 | COLLECTION(1), 0x01, |
zackc | 0:86603687efec | 168 | USAGE(1), 0x01, |
zackc | 0:86603687efec | 169 | COLLECTION(1), 0x00, |
zackc | 0:86603687efec | 170 | REPORT_ID(1), REPORT_ID_MOUSE, |
zackc | 0:86603687efec | 171 | REPORT_COUNT(1), 0x03, |
zackc | 0:86603687efec | 172 | REPORT_SIZE(1), 0x01, |
zackc | 0:86603687efec | 173 | USAGE_PAGE(1), 0x09, |
zackc | 0:86603687efec | 174 | USAGE_MIN(1), 0x1, |
zackc | 0:86603687efec | 175 | USAGE_MAX(1), 0x3, |
zackc | 0:86603687efec | 176 | LOGICAL_MIN(1), 0x00, |
zackc | 0:86603687efec | 177 | LOGICAL_MAX(1), 0x01, |
zackc | 0:86603687efec | 178 | INPUT(1), 0x02, |
zackc | 0:86603687efec | 179 | REPORT_COUNT(1), 0x01, |
zackc | 0:86603687efec | 180 | REPORT_SIZE(1), 0x05, |
zackc | 0:86603687efec | 181 | INPUT(1), 0x01, |
zackc | 0:86603687efec | 182 | REPORT_COUNT(1), 0x03, |
zackc | 0:86603687efec | 183 | REPORT_SIZE(1), 0x08, |
zackc | 0:86603687efec | 184 | USAGE_PAGE(1), 0x01, |
zackc | 0:86603687efec | 185 | USAGE(1), 0x30, |
zackc | 0:86603687efec | 186 | USAGE(1), 0x31, |
zackc | 0:86603687efec | 187 | USAGE(1), 0x38, |
zackc | 0:86603687efec | 188 | LOGICAL_MIN(1), 0x81, |
zackc | 0:86603687efec | 189 | LOGICAL_MAX(1), 0x7f, |
zackc | 0:86603687efec | 190 | INPUT(1), 0x06, |
zackc | 0:86603687efec | 191 | END_COLLECTION(0), |
zackc | 0:86603687efec | 192 | END_COLLECTION(0), |
zackc | 0:86603687efec | 193 | }; |
zackc | 0:86603687efec | 194 | |
zackc | 0:86603687efec | 195 | volatile bool complete; |
zackc | 0:86603687efec | 196 | volatile bool configured; |
zackc | 0:86603687efec | 197 | unsigned char outputReport[MAX_REPORT_SIZE]; |
zackc | 0:86603687efec | 198 | |
zackc | 0:86603687efec | 199 | usbhid::usbhid() |
zackc | 0:86603687efec | 200 | { |
zackc | 0:86603687efec | 201 | configured = false; |
zackc | 0:86603687efec | 202 | connect(); |
zackc | 0:86603687efec | 203 | } |
zackc | 0:86603687efec | 204 | |
zackc | 0:86603687efec | 205 | void usbhid::deviceEventReset() |
zackc | 0:86603687efec | 206 | { |
zackc | 0:86603687efec | 207 | configured = false; |
zackc | 0:86603687efec | 208 | |
zackc | 0:86603687efec | 209 | /* Must call base class */ |
zackc | 0:86603687efec | 210 | usbdevice::deviceEventReset(); |
zackc | 0:86603687efec | 211 | } |
zackc | 0:86603687efec | 212 | |
zackc | 0:86603687efec | 213 | bool usbhid::requestSetConfiguration(void) |
zackc | 0:86603687efec | 214 | { |
zackc | 0:86603687efec | 215 | bool result; |
zackc | 0:86603687efec | 216 | |
zackc | 0:86603687efec | 217 | /* Configure IN interrupt endpoint */ |
zackc | 0:86603687efec | 218 | realiseEndpoint(EP1IN, MAX_PACKET_SIZE_EP1); |
zackc | 0:86603687efec | 219 | enableEndpointEvent(EP1IN); |
zackc | 0:86603687efec | 220 | |
zackc | 0:86603687efec | 221 | /* Must call base class */ |
zackc | 0:86603687efec | 222 | result = usbdevice::requestSetConfiguration(); |
zackc | 0:86603687efec | 223 | |
zackc | 0:86603687efec | 224 | if (result) |
zackc | 0:86603687efec | 225 | { |
zackc | 0:86603687efec | 226 | /* Now configured */ |
zackc | 0:86603687efec | 227 | configured = true; |
zackc | 0:86603687efec | 228 | } |
zackc | 0:86603687efec | 229 | |
zackc | 0:86603687efec | 230 | return result; |
zackc | 0:86603687efec | 231 | } |
zackc | 0:86603687efec | 232 | |
zackc | 0:86603687efec | 233 | bool usbhid::requestGetDescriptor(void) |
zackc | 0:86603687efec | 234 | { |
zackc | 0:86603687efec | 235 | bool success = false; |
zackc | 0:86603687efec | 236 | |
zackc | 0:86603687efec | 237 | switch (DESCRIPTOR_TYPE(transfer.setup.wValue)) |
zackc | 0:86603687efec | 238 | { |
zackc | 0:86603687efec | 239 | case DEVICE_DESCRIPTOR: |
zackc | 0:86603687efec | 240 | transfer.remaining = sizeof(deviceDescriptor); |
zackc | 0:86603687efec | 241 | transfer.ptr = deviceDescriptor; |
zackc | 0:86603687efec | 242 | transfer.direction = DEVICE_TO_HOST; |
zackc | 0:86603687efec | 243 | success = true; |
zackc | 0:86603687efec | 244 | break; |
zackc | 0:86603687efec | 245 | case CONFIGURATION_DESCRIPTOR: |
zackc | 0:86603687efec | 246 | transfer.remaining = sizeof(configurationDescriptor); |
zackc | 0:86603687efec | 247 | transfer.ptr = configurationDescriptor; |
zackc | 0:86603687efec | 248 | transfer.direction = DEVICE_TO_HOST; |
zackc | 0:86603687efec | 249 | success = true; |
zackc | 0:86603687efec | 250 | break; |
zackc | 0:86603687efec | 251 | case STRING_DESCRIPTOR: |
zackc | 0:86603687efec | 252 | case INTERFACE_DESCRIPTOR: |
zackc | 0:86603687efec | 253 | case ENDPOINT_DESCRIPTOR: |
zackc | 0:86603687efec | 254 | /* TODO: Support is optional, not implemented here */ |
zackc | 0:86603687efec | 255 | break; |
zackc | 0:86603687efec | 256 | case HID_DESCRIPTOR: |
zackc | 0:86603687efec | 257 | transfer.remaining = 0x09; /* TODO: Fix hard coded size/offset */ |
zackc | 0:86603687efec | 258 | transfer.ptr = &configurationDescriptor[18]; |
zackc | 0:86603687efec | 259 | transfer.direction = DEVICE_TO_HOST; |
zackc | 0:86603687efec | 260 | success = true; |
zackc | 0:86603687efec | 261 | break; |
zackc | 0:86603687efec | 262 | case REPORT_DESCRIPTOR: |
zackc | 0:86603687efec | 263 | transfer.remaining = sizeof(reportDescriptor); |
zackc | 0:86603687efec | 264 | transfer.ptr = reportDescriptor; |
zackc | 0:86603687efec | 265 | transfer.direction = DEVICE_TO_HOST; |
zackc | 0:86603687efec | 266 | success = true; |
zackc | 0:86603687efec | 267 | break; |
zackc | 0:86603687efec | 268 | default: |
zackc | 0:86603687efec | 269 | break; |
zackc | 0:86603687efec | 270 | } |
zackc | 0:86603687efec | 271 | |
zackc | 0:86603687efec | 272 | return success; |
zackc | 0:86603687efec | 273 | } |
zackc | 0:86603687efec | 274 | |
zackc | 0:86603687efec | 275 | bool usbhid::requestSetup(void) |
zackc | 0:86603687efec | 276 | { |
zackc | 0:86603687efec | 277 | /* Process class requests */ |
zackc | 0:86603687efec | 278 | bool success = false; |
zackc | 0:86603687efec | 279 | |
zackc | 0:86603687efec | 280 | if (transfer.setup.bmRequestType.Type == CLASS_TYPE) |
zackc | 0:86603687efec | 281 | { |
zackc | 0:86603687efec | 282 | switch (transfer.setup.bRequest) |
zackc | 0:86603687efec | 283 | { |
zackc | 0:86603687efec | 284 | case SET_REPORT: |
zackc | 0:86603687efec | 285 | switch (transfer.setup.wValue & 0xff) |
zackc | 0:86603687efec | 286 | { |
zackc | 0:86603687efec | 287 | case REPORT_ID_KEYBOARD: |
zackc | 0:86603687efec | 288 | /* TODO: LED state */ |
zackc | 0:86603687efec | 289 | transfer.remaining = sizeof(outputReport); |
zackc | 0:86603687efec | 290 | transfer.ptr = outputReport; |
zackc | 0:86603687efec | 291 | transfer.direction = HOST_TO_DEVICE; |
zackc | 0:86603687efec | 292 | success = true; |
zackc | 0:86603687efec | 293 | break; |
zackc | 0:86603687efec | 294 | default: |
zackc | 0:86603687efec | 295 | break; |
zackc | 0:86603687efec | 296 | } |
zackc | 0:86603687efec | 297 | break; |
zackc | 0:86603687efec | 298 | default: |
zackc | 0:86603687efec | 299 | break; |
zackc | 0:86603687efec | 300 | } |
zackc | 0:86603687efec | 301 | } |
zackc | 0:86603687efec | 302 | |
zackc | 0:86603687efec | 303 | if (success) |
zackc | 0:86603687efec | 304 | { |
zackc | 0:86603687efec | 305 | /* We've handled this request */ |
zackc | 0:86603687efec | 306 | return true; |
zackc | 0:86603687efec | 307 | } |
zackc | 0:86603687efec | 308 | |
zackc | 0:86603687efec | 309 | return usbdevice::requestSetup(); |
zackc | 0:86603687efec | 310 | } |
zackc | 0:86603687efec | 311 | |
zackc | 0:86603687efec | 312 | bool usbhid::sendInputReport(unsigned char id, unsigned char *data, unsigned char size) |
zackc | 0:86603687efec | 313 | { |
zackc | 0:86603687efec | 314 | /* Send an Input Report */ |
zackc | 0:86603687efec | 315 | /* If data is NULL an all zero report is sent */ |
zackc | 0:86603687efec | 316 | |
zackc | 0:86603687efec | 317 | static unsigned char report[MAX_REPORT_SIZE+1]; /* +1 for report ID */ |
zackc | 0:86603687efec | 318 | unsigned char i; |
zackc | 0:86603687efec | 319 | |
zackc | 0:86603687efec | 320 | if (size > MAX_REPORT_SIZE) |
zackc | 0:86603687efec | 321 | { |
zackc | 0:86603687efec | 322 | return false; |
zackc | 0:86603687efec | 323 | } |
zackc | 0:86603687efec | 324 | |
zackc | 0:86603687efec | 325 | /* Add report ID */ |
zackc | 0:86603687efec | 326 | report[0]=id; |
zackc | 0:86603687efec | 327 | |
zackc | 0:86603687efec | 328 | /* Add report data */ |
zackc | 0:86603687efec | 329 | if (data != NULL) |
zackc | 0:86603687efec | 330 | { |
zackc | 0:86603687efec | 331 | for (i=0; i<size; i++) |
zackc | 0:86603687efec | 332 | { |
zackc | 0:86603687efec | 333 | report[i+1] = *data++; |
zackc | 0:86603687efec | 334 | } |
zackc | 0:86603687efec | 335 | } |
zackc | 0:86603687efec | 336 | else |
zackc | 0:86603687efec | 337 | { |
zackc | 0:86603687efec | 338 | for (i=0; i<size; i++) |
zackc | 0:86603687efec | 339 | { |
zackc | 0:86603687efec | 340 | report[i+1] = 0; |
zackc | 0:86603687efec | 341 | } |
zackc | 0:86603687efec | 342 | } |
zackc | 0:86603687efec | 343 | |
zackc | 0:86603687efec | 344 | /* Block if not configured */ |
zackc | 0:86603687efec | 345 | while (!configured); |
zackc | 0:86603687efec | 346 | |
zackc | 0:86603687efec | 347 | /* Send report */ |
zackc | 0:86603687efec | 348 | complete = false; |
zackc | 0:86603687efec | 349 | disableEvents(); |
zackc | 0:86603687efec | 350 | endpointWrite(EP1IN, report, size+1); /* +1 for report ID */ |
zackc | 0:86603687efec | 351 | enableEvents(); |
zackc | 0:86603687efec | 352 | |
zackc | 0:86603687efec | 353 | /* Wait for completion */ |
zackc | 0:86603687efec | 354 | while(!complete && configured); |
zackc | 0:86603687efec | 355 | return true; |
zackc | 0:86603687efec | 356 | } |
zackc | 0:86603687efec | 357 | |
zackc | 0:86603687efec | 358 | void usbhid::endpointEventEP1In(void) |
zackc | 0:86603687efec | 359 | { |
zackc | 0:86603687efec | 360 | complete = true; |
zackc | 0:86603687efec | 361 | } |
zackc | 0:86603687efec | 362 | |
zackc | 0:86603687efec | 363 | bool usbhid::keyboard(char c) |
zackc | 0:86603687efec | 364 | { |
zackc | 0:86603687efec | 365 | /* Send a simulated keyboard keypress. Returns true if successful. */ |
zackc | 0:86603687efec | 366 | unsigned char report[8]={0,0,0,0,0,0,0,0}; |
zackc | 0:86603687efec | 367 | |
zackc | 0:86603687efec | 368 | report[0] = keymap[c].modifier; |
zackc | 0:86603687efec | 369 | report[2] = keymap[c].usage; |
zackc | 0:86603687efec | 370 | |
zackc | 0:86603687efec | 371 | /* Key down */ |
zackc | 0:86603687efec | 372 | if (!sendInputReport(REPORT_ID_KEYBOARD, report, 8)) |
zackc | 0:86603687efec | 373 | { |
zackc | 0:86603687efec | 374 | return false; |
zackc | 0:86603687efec | 375 | } |
zackc | 0:86603687efec | 376 | |
zackc | 0:86603687efec | 377 | /* Key up */ |
zackc | 0:86603687efec | 378 | if (!sendInputReport(REPORT_ID_KEYBOARD, NULL, 8)) |
zackc | 0:86603687efec | 379 | { |
zackc | 0:86603687efec | 380 | return false; |
zackc | 0:86603687efec | 381 | } |
zackc | 0:86603687efec | 382 | |
zackc | 0:86603687efec | 383 | return true; |
zackc | 0:86603687efec | 384 | } |
zackc | 0:86603687efec | 385 | |
zackc | 0:86603687efec | 386 | bool usbhid::keyboard(char *string) |
zackc | 0:86603687efec | 387 | { |
zackc | 0:86603687efec | 388 | /* Send a string of characters. Returns true if successful. */ |
zackc | 0:86603687efec | 389 | do { |
zackc | 0:86603687efec | 390 | if (!keyboard(*string++)) |
zackc | 0:86603687efec | 391 | { |
zackc | 0:86603687efec | 392 | return false; |
zackc | 0:86603687efec | 393 | } |
zackc | 0:86603687efec | 394 | } while (*string != '\0'); |
zackc | 0:86603687efec | 395 | |
zackc | 0:86603687efec | 396 | return true; |
zackc | 0:86603687efec | 397 | } |
zackc | 0:86603687efec | 398 | |
zackc | 0:86603687efec | 399 | bool usbhid::mouse(signed char x, signed char y, unsigned char buttons, signed char wheel) |
zackc | 0:86603687efec | 400 | { |
zackc | 0:86603687efec | 401 | /* Send a simulated mouse event. Returns true if successful. */ |
zackc | 0:86603687efec | 402 | unsigned char report[4]={0,0,0,0}; |
zackc | 0:86603687efec | 403 | |
zackc | 0:86603687efec | 404 | report[0] = buttons; |
zackc | 0:86603687efec | 405 | report[1] = x; |
zackc | 0:86603687efec | 406 | report[2] = y; |
zackc | 0:86603687efec | 407 | report[3] = wheel; |
zackc | 0:86603687efec | 408 | |
zackc | 0:86603687efec | 409 | if (!sendInputReport(REPORT_ID_MOUSE, report, 4)) |
zackc | 0:86603687efec | 410 | { |
zackc | 0:86603687efec | 411 | return false; |
zackc | 0:86603687efec | 412 | } |
zackc | 0:86603687efec | 413 | |
zackc | 0:86603687efec | 414 | return true; |
zackc | 0:86603687efec | 415 | } |