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