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