]> git.donarmstrong.com Git - qmk_firmware.git/blob - tmk_core/protocol/mbed/HIDKeyboard.cpp
[Docs] Remove some outdated FAQ items (#7607)
[qmk_firmware.git] / tmk_core / protocol / mbed / HIDKeyboard.cpp
1 #include <stdint.h>
2 #include "USBHID.h"
3 #include "USBHID_Types.h"
4 #include "USBDescriptor.h"
5 #include "HIDKeyboard.h"
6
7 #define DEFAULT_CONFIGURATION (1)
8
9 HIDKeyboard::HIDKeyboard(uint16_t vendor_id, uint16_t product_id, uint16_t product_release) : USBDevice(vendor_id, product_id, product_release) { USBDevice::connect(); }
10
11 bool HIDKeyboard::sendReport(report_keyboard_t report) {
12     USBDevice::write(EP1IN, report.raw, sizeof(report), MAX_PACKET_SIZE_EP1);
13     return true;
14 }
15
16 uint8_t HIDKeyboard::leds() { return led_state; }
17
18 bool HIDKeyboard::USBCallback_setConfiguration(uint8_t configuration) {
19     if (configuration != DEFAULT_CONFIGURATION) {
20         return false;
21     }
22
23     // Configure endpoints > 0
24     addEndpoint(EPINT_IN, MAX_PACKET_SIZE_EPINT);
25     // addEndpoint(EPINT_OUT, MAX_PACKET_SIZE_EPINT);
26
27     // We activate the endpoint to be able to recceive data
28     // readStart(EPINT_OUT, MAX_PACKET_SIZE_EPINT);
29     return true;
30 }
31
32 uint8_t *HIDKeyboard::stringImanufacturerDesc() {
33     static uint8_t stringImanufacturerDescriptor[] = {
34         0x18,              /*bLength*/
35         STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
36         't',
37         0,
38         'm',
39         0,
40         'k',
41         0,
42         '-',
43         0,
44         'k',
45         0,
46         'b',
47         0,
48         'd',
49         0,
50         '.',
51         0,
52         'c',
53         0,
54         'o',
55         0,
56         'm',
57         0 /*bString iManufacturer*/
58     };
59     return stringImanufacturerDescriptor;
60 }
61
62 uint8_t *HIDKeyboard::stringIproductDesc() {
63     static uint8_t stringIproductDescriptor[] = {
64         0x0a,              /*bLength*/
65         STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
66         'm',
67         0,
68         'b',
69         0,
70         'e',
71         0,
72         'd',
73         0 /*bString iProduct*/
74     };
75     return stringIproductDescriptor;
76 }
77
78 uint8_t *HIDKeyboard::stringIserialDesc() {
79     static uint8_t stringIserialDescriptor[] = {
80         0x04,              /*bLength*/
81         STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
82         '0', 0             /*bString iSerial*/
83     };
84     return stringIserialDescriptor;
85 }
86
87 uint8_t *HIDKeyboard::reportDesc() {
88     static uint8_t reportDescriptor[] = {
89         USAGE_PAGE(1),     0x01,  // Generic Desktop
90         USAGE(1),          0x06,  // Keyboard
91         COLLECTION(1),     0x01,  // Application
92
93         USAGE_PAGE(1),     0x07,                                                                                                                                           // Key Codes
94         USAGE_MINIMUM(1),  0xE0, USAGE_MAXIMUM(1), 0xE7, LOGICAL_MINIMUM(1), 0x00, LOGICAL_MAXIMUM(1), 0x01, REPORT_SIZE(1), 0x01, REPORT_COUNT(1), 0x08, INPUT(1), 0x02,  // Data, Variable, Absolute
95
96         REPORT_COUNT(1),   0x01, REPORT_SIZE(1),   0x08, INPUT(1),           0x01,  // Constant
97
98         REPORT_COUNT(1),   0x05, REPORT_SIZE(1),   0x01, USAGE_PAGE(1),      0x08,  // LEDs
99         USAGE_MINIMUM(1),  0x01, USAGE_MAXIMUM(1), 0x05, OUTPUT(1),          0x02,  // Data, Variable, Absolute
100
101         REPORT_COUNT(1),   0x01, REPORT_SIZE(1),   0x03, OUTPUT(1),          0x01,  // Constant
102
103         REPORT_COUNT(1),   0x06, REPORT_SIZE(1),   0x08, LOGICAL_MINIMUM(1), 0x00, LOGICAL_MAXIMUM(1), 0xFF, USAGE_PAGE(1),  0x07,  // Key Codes
104         USAGE_MINIMUM(1),  0x00, USAGE_MAXIMUM(1), 0xFF, INPUT(1),           0x00,                                                  // Data, Array
105         END_COLLECTION(0),
106     };
107     reportLength = sizeof(reportDescriptor);
108     return reportDescriptor;
109 }
110
111 uint16_t HIDKeyboard::reportDescLength() {
112     reportDesc();
113     return reportLength;
114 }
115
116 #define TOTAL_DESCRIPTOR_LENGTH ((1 * CONFIGURATION_DESCRIPTOR_LENGTH) + (1 * INTERFACE_DESCRIPTOR_LENGTH) + (1 * HID_DESCRIPTOR_LENGTH) + (1 * ENDPOINT_DESCRIPTOR_LENGTH))
117 uint8_t *HIDKeyboard::configurationDesc() {
118     static uint8_t configurationDescriptor[] = {
119         CONFIGURATION_DESCRIPTOR_LENGTH,  // bLength
120         CONFIGURATION_DESCRIPTOR,         // bDescriptorType
121         LSB(TOTAL_DESCRIPTOR_LENGTH),     // wTotalLength (LSB)
122         MSB(TOTAL_DESCRIPTOR_LENGTH),     // wTotalLength (MSB)
123         0x01,                             // bNumInterfaces
124         DEFAULT_CONFIGURATION,            // bConfigurationValue
125         0x00,                             // iConfiguration
126         C_RESERVED | C_REMOTE_WAKEUP,     // bmAttributes
127         C_POWER(100),                     // bMaxPowerHello World from Mbed
128
129         INTERFACE_DESCRIPTOR_LENGTH,  // bLength
130         INTERFACE_DESCRIPTOR,         // bDescriptorType
131         0x00,                         // bInterfaceNumber
132         0x00,                         // bAlternateSetting
133         0x01,                         // bNumEndpoints
134         HID_CLASS,                    // bInterfaceClass
135         1,                            // bInterfaceSubClass (boot)
136         1,                            // bInterfaceProtocol (keyboard)
137         0x00,                         // iInterface
138
139         HID_DESCRIPTOR_LENGTH,               // bLength
140         HID_DESCRIPTOR,                      // bDescriptorType
141         LSB(HID_VERSION_1_11),               // bcdHID (LSB)
142         MSB(HID_VERSION_1_11),               // bcdHID (MSB)
143         0x00,                                // bCountryCode
144         0x01,                                // bNumDescriptors
145         REPORT_DESCRIPTOR,                   // bDescriptorType
146         (uint8_t)(LSB(reportDescLength())),  // wDescriptorLength (LSB)
147         (uint8_t)(MSB(reportDescLength())),  // wDescriptorLength (MSB)
148
149         ENDPOINT_DESCRIPTOR_LENGTH,  // bLength
150         ENDPOINT_DESCRIPTOR,         // bDescriptorType
151         PHY_TO_DESC(EP1IN),          // bEndpointAddress
152         E_INTERRUPT,                 // bmAttributes
153         LSB(MAX_PACKET_SIZE_EPINT),  // wMaxPacketSize (LSB)
154         MSB(MAX_PACKET_SIZE_EPINT),  // wMaxPacketSize (MSB)
155         1,                           // bInterval (milliseconds)
156     };
157     return configurationDescriptor;
158 }
159
160 #if 0
161 uint8_t * HIDKeyboard::deviceDesc() {
162     static uint8_t deviceDescriptor[] = {
163         DEVICE_DESCRIPTOR_LENGTH,       /* bLength */
164         DEVICE_DESCRIPTOR,              /* bDescriptorType */
165         LSB(USB_VERSION_2_0),           /* bcdUSB (LSB) */
166         MSB(USB_VERSION_2_0),           /* bcdUSB (MSB) */
167         0x00,                           /* bDeviceClass */
168         0x00,                           /* bDeviceSubClass */
169         0x00,                           /* bDeviceprotocol */
170         MAX_PACKET_SIZE_EP0,            /* bMaxPacketSize0 */
171         (uint8_t)(LSB(0xfeed)),                 /* idVendor (LSB) */
172         (uint8_t)(MSB(0xfeed)),                 /* idVendor (MSB) */
173         (uint8_t)(LSB(0x1bed)),                /* idProduct (LSB) */
174         (uint8_t)(MSB(0x1bed)),                /* idProduct (MSB) */
175         (uint8_t)(LSB(0x0002)),           /* bcdDevice (LSB) */
176         (uint8_t)(MSB(0x0002)),           /* bcdDevice (MSB) */
177         0,    /* iManufacturer */
178         0,         /* iProduct */
179         0,          /* iSerialNumber */
180         0x01                            /* bNumConfigurations */
181     };
182     return deviceDescriptor;
183 }
184 #endif
185
186 bool HIDKeyboard::USBCallback_request() {
187     bool              success  = false;
188     CONTROL_TRANSFER *transfer = getTransferPtr();
189     uint8_t *         hidDescriptor;
190
191     // Process additional standard requests
192
193     if ((transfer->setup.bmRequestType.Type == STANDARD_TYPE)) {
194         switch (transfer->setup.bRequest) {
195             case GET_DESCRIPTOR:
196                 switch (DESCRIPTOR_TYPE(transfer->setup.wValue)) {
197                     case REPORT_DESCRIPTOR:
198                         if ((reportDesc() != NULL) && (reportDescLength() != 0)) {
199                             transfer->remaining = reportDescLength();
200                             transfer->ptr       = reportDesc();
201                             transfer->direction = DEVICE_TO_HOST;
202                             success             = true;
203                         }
204                         break;
205                     case HID_DESCRIPTOR:
206                         // Find the HID descriptor, after the configuration descriptor
207                         hidDescriptor = findDescriptor(HID_DESCRIPTOR);
208                         if (hidDescriptor != NULL) {
209                             transfer->remaining = HID_DESCRIPTOR_LENGTH;
210                             transfer->ptr       = hidDescriptor;
211                             transfer->direction = DEVICE_TO_HOST;
212                             success             = true;
213                         }
214                         break;
215
216                     default:
217                         break;
218                 }
219                 break;
220             default:
221                 break;
222         }
223     }
224
225     // Process class-specific requests
226     if (transfer->setup.bmRequestType.Type == CLASS_TYPE) {
227         switch (transfer->setup.bRequest) {
228             case SET_REPORT:
229                 // LED indicator
230                 // TODO: check Interface and Report length?
231                 // if (transfer->setup.wIndex == INTERFACE_KEYBOAD) { }
232                 // if (transfer->setup.wLength == 1)
233
234                 transfer->remaining = 1;
235                 // transfer->ptr = ?? what ptr should be set when OUT(not used?)
236                 transfer->direction = HOST_TO_DEVICE;
237                 transfer->notify    = true; /* notify with USBCallback_requestCompleted */
238                 success             = true;
239             default:
240                 break;
241         }
242     }
243
244     return success;
245 }
246
247 void HIDKeyboard::USBCallback_requestCompleted(uint8_t *buf, uint32_t length) {
248     if (length > 0) {
249         CONTROL_TRANSFER *transfer = getTransferPtr();
250         if (transfer->setup.bmRequestType.Type == CLASS_TYPE) {
251             switch (transfer->setup.bRequest) {
252                 case SET_REPORT:
253                     led_state = buf[0];
254                     break;
255                 default:
256                     break;
257             }
258         }
259     }
260 }