]> git.donarmstrong.com Git - qmk_firmware.git/blob - tmk_core/protocol/arm_atsam/usb/udi_hid_kbd.c
Use a single endpoint for HID reports (#3951)
[qmk_firmware.git] / tmk_core / protocol / arm_atsam / usb / udi_hid_kbd.c
1 /**
2  * \file
3  *
4  * \brief USB Device Human Interface Device (HID) keyboard interface.
5  *
6  * Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
7  *
8  * \asf_license_start
9  *
10  * \page License
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions are met:
14  *
15  * 1. Redistributions of source code must retain the above copyright notice,
16  *    this list of conditions and the following disclaimer.
17  *
18  * 2. Redistributions in binary form must reproduce the above copyright notice,
19  *    this list of conditions and the following disclaimer in the documentation
20  *    and/or other materials provided with the distribution.
21  *
22  * 3. The name of Atmel may not be used to endorse or promote products derived
23  *    from this software without specific prior written permission.
24  *
25  * 4. This software may only be redistributed and used in connection with an
26  *    Atmel microcontroller product.
27  *
28  * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31  * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38  * POSSIBILITY OF SUCH DAMAGE.
39  *
40  * \asf_license_stop
41  *
42  */
43 /*
44  * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45  */
46
47 #include "samd51j18a.h"
48 #include "d51_util.h"
49 #include "conf_usb.h"
50 #include "usb_protocol.h"
51 #include "udd.h"
52 #include "udc.h"
53 #include "udi_device_conf.h"
54 #include "udi_hid.h"
55 #include "udi_hid_kbd.h"
56 #include <string.h>
57 #include "report.h"
58
59 //***************************************************************************
60 // KBD
61 //***************************************************************************
62 #ifdef KBD
63
64 bool udi_hid_kbd_enable(void);
65 void udi_hid_kbd_disable(void);
66 bool udi_hid_kbd_setup(void);
67 uint8_t udi_hid_kbd_getsetting(void);
68
69 UDC_DESC_STORAGE udi_api_t udi_api_hid_kbd = {
70     .enable = (bool(*)(void))udi_hid_kbd_enable,
71     .disable = (void (*)(void))udi_hid_kbd_disable,
72     .setup = (bool(*)(void))udi_hid_kbd_setup,
73     .getsetting = (uint8_t(*)(void))udi_hid_kbd_getsetting,
74     .sof_notify = NULL,
75 };
76
77 COMPILER_WORD_ALIGNED
78 static uint8_t udi_hid_kbd_rate;
79
80 COMPILER_WORD_ALIGNED
81 static uint8_t udi_hid_kbd_protocol;
82
83 COMPILER_WORD_ALIGNED
84 uint8_t udi_hid_kbd_report_set;
85
86 bool udi_hid_kbd_b_report_valid;
87
88 COMPILER_WORD_ALIGNED
89 uint8_t udi_hid_kbd_report[UDI_HID_KBD_REPORT_SIZE];
90
91 volatile bool udi_hid_kbd_b_report_trans_ongoing;
92
93 COMPILER_WORD_ALIGNED
94 static uint8_t udi_hid_kbd_report_trans[UDI_HID_KBD_REPORT_SIZE];
95
96 COMPILER_WORD_ALIGNED
97 UDC_DESC_STORAGE udi_hid_kbd_report_desc_t udi_hid_kbd_report_desc = {
98     {
99         0x05, 0x01,     // Usage Page (Generic Desktop)
100         0x09, 0x06,     // Usage (Keyboard)
101         0xA1, 0x01,     // Collection (Application)
102         0x05, 0x07,     //   Usage Page (Keyboard)
103         0x19, 0xE0,     //   Usage Minimum (224)
104         0x29, 0xE7,     //   Usage Maximum (231)
105         0x15, 0x00,     //   Logical Minimum (0)
106         0x25, 0x01,     //   Logical Maximum (1)
107         0x75, 0x01,     //   Report Size (1)
108         0x95, 0x08,     //   Report Count (8)
109         0x81, 0x02,     //   Input (Data, Variable, Absolute)
110         0x81, 0x01,     //   Input (Constant)
111         0x19, 0x00,     //   Usage Minimum (0)
112         0x29, 0x65,     //   Usage Maximum (101)
113         0x15, 0x00,     //   Logical Minimum (0)
114         0x25, 0x65,     //   Logical Maximum (101)
115         0x75, 0x08,     //   Report Size (8)
116         0x95, 0x06,     //   Report Count (6)
117         0x81, 0x00,     //   Input (Data, Array)
118         0x05, 0x08,     //   Usage Page (LED)
119         0x19, 0x01,     //   Usage Minimum (1)
120         0x29, 0x05,     //   Usage Maximum (5)
121         0x15, 0x00,     //   Logical Minimum (0)
122         0x25, 0x01,     //   Logical Maximum (1)
123         0x75, 0x01,     //   Report Size (1)
124         0x95, 0x05,     //   Report Count (5)
125         0x91, 0x02,     //   Output (Data, Variable, Absolute)
126         0x95, 0x03,     //   Report Count (3)
127         0x91, 0x01,     //   Output (Constant)
128         0xC0            // End Collection
129     }
130 };
131
132 static bool udi_hid_kbd_setreport(void);
133
134 static void udi_hid_kbd_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep);
135
136 static void udi_hid_kbd_setreport_valid(void);
137
138 bool udi_hid_kbd_enable(void)
139 {
140     // Initialize internal values
141     udi_hid_kbd_rate = 0;
142     udi_hid_kbd_protocol = 0;
143     udi_hid_kbd_b_report_trans_ongoing = false;
144     memset(udi_hid_kbd_report, 0, UDI_HID_KBD_REPORT_SIZE);
145     udi_hid_kbd_b_report_valid = false;
146     return UDI_HID_KBD_ENABLE_EXT();
147 }
148
149 void udi_hid_kbd_disable(void)
150 {
151     UDI_HID_KBD_DISABLE_EXT();
152 }
153
154 bool udi_hid_kbd_setup(void)
155 {
156     return udi_hid_setup(&udi_hid_kbd_rate,
157                             &udi_hid_kbd_protocol,
158                             (uint8_t *) &udi_hid_kbd_report_desc,
159                             udi_hid_kbd_setreport);
160 }
161
162 uint8_t udi_hid_kbd_getsetting(void)
163 {
164     return 0;
165 }
166
167 static bool udi_hid_kbd_setreport(void)
168 {
169     if ((USB_HID_REPORT_TYPE_OUTPUT == (udd_g_ctrlreq.req.wValue >> 8))
170             && (0 == (0xFF & udd_g_ctrlreq.req.wValue))
171             && (1 == udd_g_ctrlreq.req.wLength)) {
172         // Report OUT type on report ID 0 from USB Host
173         udd_g_ctrlreq.payload = &udi_hid_kbd_report_set;
174         udd_g_ctrlreq.callback = udi_hid_kbd_setreport_valid;
175         udd_g_ctrlreq.payload_size = 1;
176         return true;
177     }
178     return false;
179 }
180
181 bool udi_hid_kbd_send_report(void)
182 {
183     if (!main_b_kbd_enable) {
184         return false;
185     }
186
187     if (udi_hid_kbd_b_report_trans_ongoing) {
188         return false;
189     }
190
191     memcpy(udi_hid_kbd_report_trans, udi_hid_kbd_report, UDI_HID_KBD_REPORT_SIZE);
192     udi_hid_kbd_b_report_valid = false;
193     udi_hid_kbd_b_report_trans_ongoing =
194             udd_ep_run(UDI_HID_KBD_EP_IN | USB_EP_DIR_IN,
195                         false,
196                         udi_hid_kbd_report_trans,
197                         UDI_HID_KBD_REPORT_SIZE,
198                         udi_hid_kbd_report_sent);
199
200     return udi_hid_kbd_b_report_trans_ongoing;
201 }
202
203 static void udi_hid_kbd_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep)
204 {
205     UNUSED(status);
206     UNUSED(nb_sent);
207     UNUSED(ep);
208     udi_hid_kbd_b_report_trans_ongoing = false;
209     if (udi_hid_kbd_b_report_valid) {
210         udi_hid_kbd_send_report();
211     }
212 }
213
214 static void udi_hid_kbd_setreport_valid(void)
215 {
216     //UDI_HID_KBD_CHANGE_LED(udi_hid_kbd_report_set);
217 }
218
219 #endif //KBD
220
221 //********************************************************************************************
222 // NKRO Keyboard
223 //********************************************************************************************
224 #ifdef NKRO
225
226 bool udi_hid_nkro_enable(void);
227 void udi_hid_nkro_disable(void);
228 bool udi_hid_nkro_setup(void);
229 uint8_t udi_hid_nkro_getsetting(void);
230
231 UDC_DESC_STORAGE udi_api_t udi_api_hid_nkro = {
232     .enable = (bool(*)(void))udi_hid_nkro_enable,
233     .disable = (void (*)(void))udi_hid_nkro_disable,
234     .setup = (bool(*)(void))udi_hid_nkro_setup,
235     .getsetting = (uint8_t(*)(void))udi_hid_nkro_getsetting,
236     .sof_notify = NULL,
237 };
238
239 COMPILER_WORD_ALIGNED
240 static uint8_t udi_hid_nkro_rate;
241
242 COMPILER_WORD_ALIGNED
243 static uint8_t udi_hid_nkro_protocol;
244
245 COMPILER_WORD_ALIGNED
246 uint8_t udi_hid_nkro_report_set;
247
248 bool udi_hid_nkro_b_report_valid;
249
250 COMPILER_WORD_ALIGNED
251 uint8_t udi_hid_nkro_report[UDI_HID_NKRO_REPORT_SIZE];
252
253 volatile bool udi_hid_nkro_b_report_trans_ongoing;
254
255 COMPILER_WORD_ALIGNED
256 static uint8_t udi_hid_nkro_report_trans[UDI_HID_NKRO_REPORT_SIZE];
257
258 COMPILER_WORD_ALIGNED
259 UDC_DESC_STORAGE udi_hid_nkro_report_desc_t udi_hid_nkro_report_desc = {
260     {
261         0x05, 0x01,     // Usage Page (Generic Desktop),
262         0x09, 0x06,     // Usage (Keyboard),
263         0xA1, 0x01,     // Collection (Application) - Keyboard,
264
265         //Mods
266         0x75, 0x01,     //   Report Size (1),
267         0x95, 0x08,     //   Report Count (8),
268         0x15, 0x00,     //   Logical Minimum (0),
269         0x25, 0x01,     //   Logical Maximum (1),
270         0x05, 0x07,     //   Usage Page (Key Codes),
271         0x19, 0xE0,     //   Usage Minimum (224),
272         0x29, 0xE7,     //   Usage Maximum (231),
273         0x81, 0x02,     //   Input (Data, Variable, Absolute),
274
275         //LED Report
276         0x75, 0x01,     //   Report Size (1),
277         0x95, 0x05,     //   Report Count (5),
278         0x05, 0x08,     //   Usage Page (LEDs),
279         0x19, 0x01,     //   Usage Minimum (1),
280         0x29, 0x05,     //   Usage Maximum (5),
281         0x91, 0x02,     //   Output (Data, Variable, Absolute),
282
283         //LED Report Padding
284         0x75, 0x03,     //   Report Size (3),
285         0x95, 0x01,     //   Report Count (1),
286         0x91, 0x03,     //   Output (Constant),
287
288         //Main keys
289         0x75, 0x01,     //   Report Size (1),
290         0x95, 0xF8,     //   Report Count (248),
291         0x15, 0x00,     //   Logical Minimum (0),
292         0x25, 0x01,     //   Logical Maximum (1),
293         0x05, 0x07,     //   Usage Page (Key Codes),
294         0x19, 0x00,     //   Usage Minimum (0),
295         0x29, 0xF7,     //   Usage Maximum (247),
296         0x81, 0x02,     //   Input (Data, Variable, Absolute, Bitfield),
297         0xc0,           // End Collection - Keyboard
298     }
299 };
300
301 static bool udi_hid_nkro_setreport(void);
302 static void udi_hid_nkro_setreport_valid(void);
303 static void udi_hid_nkro_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep);
304
305 bool udi_hid_nkro_enable(void)
306 {
307     // Initialize internal values
308     udi_hid_nkro_rate = 0;
309     udi_hid_nkro_protocol = 0;
310     udi_hid_nkro_b_report_trans_ongoing = false;
311     memset(udi_hid_nkro_report, 0, UDI_HID_NKRO_REPORT_SIZE);
312     udi_hid_nkro_b_report_valid = false;
313     return UDI_HID_NKRO_ENABLE_EXT();
314 }
315
316 void udi_hid_nkro_disable(void)
317 {
318     UDI_HID_NKRO_DISABLE_EXT();
319 }
320
321 bool udi_hid_nkro_setup(void)
322 {
323     return udi_hid_setup(&udi_hid_nkro_rate,
324                             &udi_hid_nkro_protocol,
325                             (uint8_t *) &udi_hid_nkro_report_desc,
326                             udi_hid_nkro_setreport);
327 }
328
329 uint8_t udi_hid_nkro_getsetting(void)
330 {
331     return 0;
332 }
333
334 //keyboard receives LED report here
335 static bool udi_hid_nkro_setreport(void)
336 {
337     if ((USB_HID_REPORT_TYPE_OUTPUT == (udd_g_ctrlreq.req.wValue >> 8))
338         && (0 == (0xFF & udd_g_ctrlreq.req.wValue))
339         && (1 == udd_g_ctrlreq.req.wLength)) {
340         // Report OUT type on report ID 0 from USB Host
341         udd_g_ctrlreq.payload = &udi_hid_nkro_report_set;
342         udd_g_ctrlreq.callback = udi_hid_nkro_setreport_valid; //must call routine to transform setreport to LED state
343         udd_g_ctrlreq.payload_size = 1;
344         return true;
345     }
346     return false;
347 }
348
349 bool udi_hid_nkro_send_report(void)
350 {
351     if (!main_b_nkro_enable) {
352         return false;
353     }
354
355     if (udi_hid_nkro_b_report_trans_ongoing) {
356         return false;
357     }
358
359     memcpy(udi_hid_nkro_report_trans, udi_hid_nkro_report, UDI_HID_NKRO_REPORT_SIZE);
360     udi_hid_nkro_b_report_valid = false;
361     udi_hid_nkro_b_report_trans_ongoing =
362             udd_ep_run(UDI_HID_NKRO_EP_IN | USB_EP_DIR_IN,
363                         false,
364                         udi_hid_nkro_report_trans,
365                         UDI_HID_NKRO_REPORT_SIZE,
366                         udi_hid_nkro_report_sent);
367
368     return udi_hid_nkro_b_report_trans_ongoing;
369 }
370
371 static void udi_hid_nkro_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep)
372 {
373     UNUSED(status);
374     UNUSED(nb_sent);
375     UNUSED(ep);
376     udi_hid_nkro_b_report_trans_ongoing = false;
377     if (udi_hid_nkro_b_report_valid) {
378         udi_hid_nkro_send_report();
379     }
380 }
381
382 static void udi_hid_nkro_setreport_valid(void)
383 {
384     //UDI_HID_NKRO_CHANGE_LED(udi_hid_nkro_report_set);
385 }
386
387 #endif //NKRO
388
389 //********************************************************************************************
390 // EXK (extra-keys) SYS-CTRL  Keyboard
391 //********************************************************************************************
392 #ifdef EXK
393
394 bool udi_hid_exk_enable(void);
395 void udi_hid_exk_disable(void);
396 bool udi_hid_exk_setup(void);
397 uint8_t udi_hid_exk_getsetting(void);
398
399 UDC_DESC_STORAGE udi_api_t udi_api_hid_exk = {
400     .enable = (bool(*)(void))udi_hid_exk_enable,
401     .disable = (void (*)(void))udi_hid_exk_disable,
402     .setup = (bool(*)(void))udi_hid_exk_setup,
403     .getsetting = (uint8_t(*)(void))udi_hid_exk_getsetting,
404     .sof_notify = NULL,
405 };
406
407 COMPILER_WORD_ALIGNED
408 static uint8_t udi_hid_exk_rate;
409
410 COMPILER_WORD_ALIGNED
411 static uint8_t udi_hid_exk_protocol;
412
413 COMPILER_WORD_ALIGNED
414 uint8_t udi_hid_exk_report_set;
415
416 bool udi_hid_exk_b_report_valid;
417
418 COMPILER_WORD_ALIGNED
419 udi_hid_exk_report_t udi_hid_exk_report;
420
421 static bool udi_hid_exk_b_report_trans_ongoing;
422
423 COMPILER_WORD_ALIGNED
424 static uint8_t udi_hid_exk_report_trans[UDI_HID_EXK_REPORT_SIZE];
425
426 COMPILER_WORD_ALIGNED
427 UDC_DESC_STORAGE udi_hid_exk_report_desc_t udi_hid_exk_report_desc = {
428     {
429         // System Control Collection (8 bits)
430
431         0x05, 0x01,         // Usage Page (Generic Desktop),
432         0x09, 0x80,         // Usage (System Control),
433         0xA1, 0x01,         // Collection (Application),
434         0x85, REPORT_ID_SYSTEM,         //   Report ID (2) (System),
435         0x16, 0x01, 0x00,   //   Logical Minimum (1),
436         0x26, 0x03, 0x00,   //   Logical Maximum (3),
437         0x1A, 0x81, 0x00,   //   Usage Minimum (81) (System Power Down),
438         0x2A, 0x83, 0x00,   //   Usage Maximum (83) (System Wake Up),
439         0x75, 0x10,         //   Report Size (16),
440         0x95, 0x01,         //   Report Count (1),
441         0x81, 0x00,         //   Input (Data, Array),
442         0xC0,               // End Collection - System Control
443
444         // Consumer Control Collection - Media Keys (16 bits)
445
446         0x05, 0x0C,         // Usage Page (Consumer),
447         0x09, 0x01,         // Usage (Consumer Control),
448         0xA1, 0x01,         // Collection (Application),
449         0x85, REPORT_ID_CONSUMER,         //   Report ID (3) (Consumer),
450         0x16, 0x01, 0x00,   //   Logical Minimum (1),
451         0x26, 0x9C, 0x02,   //   Logical Maximum (668),
452         0x1A, 0x01, 0x00,   //   Usage Minimum (1),
453         0x2A, 0x9C, 0x02,   //   Usage Maximum (668),
454         0x75, 0x10,         //   Report Size (16),
455         0x95, 0x01,         //   Report Count (1),
456         0x81, 0x00,         //   Input (Data, Array),
457         0xC0,               // End Collection - Consumer Control
458     }
459 };
460
461 static bool udi_hid_exk_setreport(void);
462
463 static void udi_hid_exk_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep);
464
465 static void udi_hid_exk_setreport_valid(void);
466
467 bool udi_hid_exk_enable(void)
468 {
469     // Initialize internal values
470     udi_hid_exk_rate = 0;
471     udi_hid_exk_protocol = 0;
472     udi_hid_exk_b_report_trans_ongoing = false;
473     memset(udi_hid_exk_report.raw, 0, UDI_HID_EXK_REPORT_SIZE);
474     udi_hid_exk_b_report_valid = false;
475     return UDI_HID_EXK_ENABLE_EXT();
476 }
477
478 void udi_hid_exk_disable(void)
479 {
480     UDI_HID_EXK_DISABLE_EXT();
481 }
482
483 bool udi_hid_exk_setup(void)
484 {
485     return udi_hid_setup(&udi_hid_exk_rate,
486                             &udi_hid_exk_protocol,
487                             (uint8_t *) &udi_hid_exk_report_desc,
488                             udi_hid_exk_setreport);
489 }
490
491 uint8_t udi_hid_exk_getsetting(void)
492 {
493     return 0;
494 }
495
496 static bool udi_hid_exk_setreport(void)
497 {
498     if ((USB_HID_REPORT_TYPE_OUTPUT == (udd_g_ctrlreq.req.wValue >> 8))
499             && (0 == (0xFF & udd_g_ctrlreq.req.wValue))
500             && (1 == udd_g_ctrlreq.req.wLength)) {
501         // Report OUT type on report ID 0 from USB Host
502         udd_g_ctrlreq.payload = &udi_hid_exk_report_set;
503         udd_g_ctrlreq.callback = udi_hid_exk_setreport_valid;
504         udd_g_ctrlreq.payload_size = 1;
505         return true;
506     }
507     return false;
508 }
509
510 bool udi_hid_exk_send_report(void)
511 {
512     if (!main_b_exk_enable) {
513         return false;
514     }
515
516     if (udi_hid_exk_b_report_trans_ongoing) {
517         return false;
518     }
519
520     memcpy(udi_hid_exk_report_trans, udi_hid_exk_report.raw, UDI_HID_EXK_REPORT_SIZE);
521     udi_hid_exk_b_report_valid = false;
522     udi_hid_exk_b_report_trans_ongoing =
523             udd_ep_run(UDI_HID_EXK_EP_IN | USB_EP_DIR_IN,
524                         false,
525                         udi_hid_exk_report_trans,
526                         UDI_HID_EXK_REPORT_SIZE,
527                         udi_hid_exk_report_sent);
528
529     return udi_hid_exk_b_report_trans_ongoing;
530 }
531
532 static void udi_hid_exk_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep)
533 {
534     UNUSED(status);
535     UNUSED(nb_sent);
536     UNUSED(ep);
537     udi_hid_exk_b_report_trans_ongoing = false;
538     if (udi_hid_exk_b_report_valid) {
539         udi_hid_exk_send_report();
540     }
541 }
542
543 static void udi_hid_exk_setreport_valid(void)
544 {
545
546 }
547
548 #endif //EXK
549
550 //********************************************************************************************
551 // MOU Mouse
552 //********************************************************************************************
553 #ifdef MOU
554
555 bool udi_hid_mou_enable(void);
556 void udi_hid_mou_disable(void);
557 bool udi_hid_mou_setup(void);
558 uint8_t udi_hid_mou_getsetting(void);
559
560 UDC_DESC_STORAGE udi_api_t udi_api_hid_mou = {
561     .enable = (bool(*)(void))udi_hid_mou_enable,
562     .disable = (void (*)(void))udi_hid_mou_disable,
563     .setup = (bool(*)(void))udi_hid_mou_setup,
564     .getsetting = (uint8_t(*)(void))udi_hid_mou_getsetting,
565     .sof_notify = NULL,
566 };
567
568 COMPILER_WORD_ALIGNED
569 static uint8_t udi_hid_mou_rate;
570
571 COMPILER_WORD_ALIGNED
572 static uint8_t udi_hid_mou_protocol;
573
574 //COMPILER_WORD_ALIGNED
575 //uint8_t udi_hid_mou_report_set; //No set report
576
577 bool udi_hid_mou_b_report_valid;
578
579 COMPILER_WORD_ALIGNED
580 uint8_t udi_hid_mou_report[UDI_HID_MOU_REPORT_SIZE];
581
582 static bool udi_hid_mou_b_report_trans_ongoing;
583
584 COMPILER_WORD_ALIGNED
585 static uint8_t udi_hid_mou_report_trans[UDI_HID_MOU_REPORT_SIZE];
586
587 COMPILER_WORD_ALIGNED
588 UDC_DESC_STORAGE udi_hid_mou_report_desc_t udi_hid_mou_report_desc = {
589     {
590         0x05, 0x01,         // Usage Page (Generic Desktop),
591         0x09, 0x02,         // Usage (Mouse),
592         0xA1, 0x01,         // Collection (Application),
593         0x09, 0x01,         //   Usage (Pointer),
594         0xA1, 0x00,         //   Collection (Physical),
595         0x05, 0x09,         //     Usage Page (Buttons),
596         0x19, 0x01,         //     Usage Minimum (01),
597         0x29, 0x05,         //     Usage Maximun (05),
598         0x15, 0x00,         //     Logical Minimum (0),
599         0x25, 0x01,         //     Logical Maximum (1),
600         0x95, 0x05,         //     Report Count (5),
601         0x75, 0x01,         //     Report Size (1),
602         0x81, 0x02,         //     Input (Data, Variable, Absolute), ;5 button bits
603         0x95, 0x01,         //     Report Count (1),
604         0x75, 0x03,         //     Report Size (3),
605         0x81, 0x01,         //     Input (Constant), ;3 bit padding,
606
607         0x05, 0x01,         //     Usage Page (Generic Desktop),
608         0x09, 0x30,         //     Usage (X),
609         0x09, 0x31,         //     Usage (Y),
610         0x15, 0x81,         //     Logical Minimum (-127),
611         0x25, 0x7F,         //     Logical Maximum (127),
612         0x95, 0x02,         //     Report Count (2),
613         0x75, 0x08,         //     Report Size (8),
614         0x81, 0x06,         //     Input (Data, Variable, Relative), ;2 position bytes (X & Y),
615
616         0x09, 0x38,         //     Usage (Wheel),
617         0x15, 0x81,         //     Logical Minimum (-127),
618         0x25, 0x7F,         //     Logical Maximum (127),
619         0x95, 0x01,         //     Report Count (1),
620         0x75, 0x08,         //     Report Size (8),
621         0x81, 0x06,         //     Input (Data, Variable, Relative),
622
623         0x05, 0x0C,         //     Usage Page (Consumer),
624         0x0A, 0x38, 0x02,   //     Usage (AC Pan (Horizontal wheel)),
625         0x15, 0x81,         //     Logical Minimum (-127),
626         0x25, 0x7F,         //     Logical Maximum (127),
627         0x95, 0x01,         //     Report Count (1),
628         0x75, 0x08,         //     Report Size (8),
629         0x81, 0x06,         //     Input (Data, Variable, Relative),
630
631         0xC0,               //   End Collection,
632         0xC0,               // End Collection
633     }
634 };
635
636 static void udi_hid_mou_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep);
637
638 bool udi_hid_mou_enable(void)
639 {
640     // Initialize internal values
641     udi_hid_mou_rate = 0;
642     udi_hid_mou_protocol = 0;
643     udi_hid_mou_b_report_trans_ongoing = false;
644     memset(udi_hid_mou_report, 0, UDI_HID_MOU_REPORT_SIZE);
645     udi_hid_mou_b_report_valid = false;
646     return UDI_HID_MOU_ENABLE_EXT();
647 }
648
649 void udi_hid_mou_disable(void)
650 {
651     UDI_HID_MOU_DISABLE_EXT();
652 }
653
654 bool udi_hid_mou_setup(void)
655 {
656     return udi_hid_setup(&udi_hid_mou_rate,
657                             &udi_hid_mou_protocol,
658                             (uint8_t *) &udi_hid_mou_report_desc,
659                             NULL);
660 }
661
662 uint8_t udi_hid_mou_getsetting(void)
663 {
664     return 0;
665 }
666
667 bool udi_hid_mou_send_report(void)
668 {
669     if (!main_b_mou_enable) {
670         return false;
671     }
672
673     if (udi_hid_mou_b_report_trans_ongoing) {
674         return false;
675     }
676
677     memcpy(udi_hid_mou_report_trans, udi_hid_mou_report, UDI_HID_MOU_REPORT_SIZE);
678     udi_hid_mou_b_report_valid = false;
679     udi_hid_mou_b_report_trans_ongoing =
680             udd_ep_run(UDI_HID_MOU_EP_IN | USB_EP_DIR_IN,
681                         false,
682                         udi_hid_mou_report_trans,
683                         UDI_HID_MOU_REPORT_SIZE,
684                         udi_hid_mou_report_sent);
685
686     return udi_hid_mou_b_report_trans_ongoing;
687 }
688
689 static void udi_hid_mou_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep)
690 {
691     UNUSED(status);
692     UNUSED(nb_sent);
693     UNUSED(ep);
694     udi_hid_mou_b_report_trans_ongoing = false;
695     if (udi_hid_mou_b_report_valid) {
696         udi_hid_mou_send_report();
697     }
698 }
699
700 #endif //MOU
701
702 //********************************************************************************************
703 // RAW
704 //********************************************************************************************
705 #ifdef RAW
706
707 bool udi_hid_raw_enable(void);
708 void udi_hid_raw_disable(void);
709 bool udi_hid_raw_setup(void);
710 uint8_t udi_hid_raw_getsetting(void);
711
712 UDC_DESC_STORAGE udi_api_t udi_api_hid_raw = {
713     .enable = (bool(*)(void))udi_hid_raw_enable,
714     .disable = (void (*)(void))udi_hid_raw_disable,
715     .setup = (bool(*)(void))udi_hid_raw_setup,
716     .getsetting = (uint8_t(*)(void))udi_hid_raw_getsetting,
717     .sof_notify = NULL,
718 };
719
720 COMPILER_WORD_ALIGNED
721 static uint8_t udi_hid_raw_rate;
722
723 COMPILER_WORD_ALIGNED
724 static uint8_t udi_hid_raw_protocol;
725
726 COMPILER_WORD_ALIGNED
727 uint8_t udi_hid_raw_report_set[UDI_HID_RAW_REPORT_SIZE];
728
729 static bool udi_hid_raw_b_report_valid;
730
731 COMPILER_WORD_ALIGNED
732 uint8_t udi_hid_raw_report[UDI_HID_RAW_REPORT_SIZE];
733
734 static bool udi_hid_raw_b_report_trans_ongoing;
735
736 COMPILER_WORD_ALIGNED
737 static uint8_t udi_hid_raw_report_trans[UDI_HID_RAW_REPORT_SIZE];
738
739 COMPILER_WORD_ALIGNED
740 UDC_DESC_STORAGE udi_hid_raw_report_desc_t udi_hid_raw_report_desc = {
741     {
742         0x06,         // Usage Page (Vendor Defined)
743         0xFF, 0xFF,
744         0x0A,         // Usage (Mouse)
745         0xFF, 0xFF,
746         0xA1, 0x01,   // Collection (Application)
747         0x75, 0x08,   //   Report Size (8)
748         0x15, 0x00,   //   Logical Minimum (0)
749         0x25, 0xFF,   //   Logical Maximum (255)
750         0x95, 0x40,   //     Report Count
751         0x09, 0x01,   //     Usage (Input)
752         0x81, 0x02,   //     Input (Data
753         0x95, 0x40,   //     Report Count
754         0x09, 0x02,   //     Usage (Output)
755         0x91, 0x02,   //     Output (Data
756         0xC0,         // End Collection - Consumer Control
757     }
758 };
759
760 static bool udi_hid_raw_setreport(void);
761 static void udi_hid_raw_setreport_valid(void);
762
763 static void udi_hid_raw_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep);
764
765 bool udi_hid_raw_enable(void)
766 {
767     // Initialize internal values
768     udi_hid_raw_rate = 0;
769     udi_hid_raw_protocol = 0;
770     udi_hid_raw_b_report_trans_ongoing = false;
771     memset(udi_hid_raw_report, 0, UDI_HID_RAW_REPORT_SIZE);
772     udi_hid_raw_b_report_valid = false;
773     return UDI_HID_RAW_ENABLE_EXT();
774 }
775
776 void udi_hid_raw_disable(void)
777 {
778     UDI_HID_RAW_DISABLE_EXT();
779 }
780
781 bool udi_hid_raw_setup(void)
782 {
783     return udi_hid_setup(&udi_hid_raw_rate,
784                             &udi_hid_raw_protocol,
785                             (uint8_t *) &udi_hid_raw_report_desc,
786                             udi_hid_raw_setreport);
787 }
788
789 uint8_t udi_hid_raw_getsetting(void)
790 {
791     return 0;
792 }
793
794 static bool udi_hid_raw_setreport(void)
795 {
796     if ((USB_HID_REPORT_TYPE_OUTPUT == (udd_g_ctrlreq.req.wValue >> 8))
797             && (0 == (0xFF & udd_g_ctrlreq.req.wValue))
798             && (UDI_HID_RAW_REPORT_SIZE == udd_g_ctrlreq.req.wLength)) {
799         // Report OUT type on report ID 0 from USB Host
800         udd_g_ctrlreq.payload = udi_hid_raw_report_set;
801         udd_g_ctrlreq.callback = udi_hid_raw_setreport_valid; //must call routine to transform setreport to LED state
802         udd_g_ctrlreq.payload_size = UDI_HID_RAW_REPORT_SIZE;
803         return true;
804     }
805     return false;
806 }
807
808 bool udi_hid_raw_send_report(void)
809 {
810     if (!main_b_raw_enable) {
811         return false;
812     }
813
814     if (udi_hid_raw_b_report_trans_ongoing) {
815         return false;
816     }
817
818     memcpy(udi_hid_raw_report_trans, udi_hid_raw_report,UDI_HID_RAW_REPORT_SIZE);
819     udi_hid_raw_b_report_valid = false;
820     udi_hid_raw_b_report_trans_ongoing =
821             udd_ep_run(UDI_HID_RAW_EP_IN | USB_EP_DIR_IN,
822                         false,
823                         udi_hid_raw_report_trans,
824                         UDI_HID_RAW_REPORT_SIZE,
825                         udi_hid_raw_report_sent);
826
827     return udi_hid_raw_b_report_trans_ongoing;
828 }
829
830 static void udi_hid_raw_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep)
831 {
832     UNUSED(status);
833     UNUSED(nb_sent);
834     UNUSED(ep);
835     udi_hid_raw_b_report_trans_ongoing = false;
836     if (udi_hid_raw_b_report_valid) {
837         udi_hid_raw_send_report();
838     }
839 }
840
841 static void udi_hid_raw_setreport_valid(void)
842 {
843
844 }
845
846 #endif //RAW
847
848 //********************************************************************************************
849 // CON
850 //********************************************************************************************
851 #ifdef CON
852
853 bool udi_hid_con_enable(void);
854 void udi_hid_con_disable(void);
855 bool udi_hid_con_setup(void);
856 uint8_t udi_hid_con_getsetting(void);
857
858 UDC_DESC_STORAGE udi_api_t udi_api_hid_con = {
859     .enable = (bool(*)(void))udi_hid_con_enable,
860     .disable = (void (*)(void))udi_hid_con_disable,
861     .setup = (bool(*)(void))udi_hid_con_setup,
862     .getsetting = (uint8_t(*)(void))udi_hid_con_getsetting,
863     .sof_notify = NULL,
864 };
865
866 COMPILER_WORD_ALIGNED
867 static uint8_t udi_hid_con_rate;
868
869 COMPILER_WORD_ALIGNED
870 static uint8_t udi_hid_con_protocol;
871
872 COMPILER_WORD_ALIGNED
873 uint8_t udi_hid_con_report_set[UDI_HID_CON_REPORT_SIZE];
874
875 bool udi_hid_con_b_report_valid;
876
877 COMPILER_WORD_ALIGNED
878 uint8_t udi_hid_con_report[UDI_HID_CON_REPORT_SIZE];
879
880 volatile bool udi_hid_con_b_report_trans_ongoing;
881
882 COMPILER_WORD_ALIGNED
883 static uint8_t udi_hid_con_report_trans[UDI_HID_CON_REPORT_SIZE];
884
885 COMPILER_WORD_ALIGNED
886 UDC_DESC_STORAGE udi_hid_con_report_desc_t udi_hid_con_report_desc = {
887     {
888         0x06, 0x31, 0xFF,           // Vendor Page (PJRC Teensy compatible)
889         0x09, 0x74,                 // Vendor Usage (PJRC Teensy compatible)
890         0xA1, 0x01,                 // Collection (Application)
891             0x09, 0x75,             //   Usage (Vendor)
892             0x15, 0x00,             //   Logical Minimum (0x00)
893             0x26, 0xFF, 0x00,       //   Logical Maximum (0x00FF)
894             0x95, CONSOLE_EPSIZE,   //   Report Count
895             0x75, 0x08,             //   Report Size (8)
896             0x81, 0x02,             //   Input (Data)
897             0x09, 0x76,             //   Usage (Vendor)
898             0x15, 0x00,             //   Logical Minimum (0x00)
899             0x26, 0xFF, 0x00,       //   Logical Maximum (0x00FF)
900             0x95, CONSOLE_EPSIZE,   //   Report Count
901             0x75, 0x08,             //   Report Size (8)
902             0x91, 0x02,             //   Output (Data)
903         0xC0,                       // End Collection
904     }
905 };
906
907 static bool udi_hid_con_setreport(void);
908 static void udi_hid_con_setreport_valid(void);
909
910 static void udi_hid_con_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep);
911
912 bool udi_hid_con_enable(void)
913 {
914     // Initialize internal values
915     udi_hid_con_rate = 0;
916     udi_hid_con_protocol = 0;
917     udi_hid_con_b_report_trans_ongoing = false;
918     memset(udi_hid_con_report, 0, UDI_HID_CON_REPORT_SIZE);
919     udi_hid_con_b_report_valid = false;
920     return UDI_HID_CON_ENABLE_EXT();
921 }
922
923 void udi_hid_con_disable(void)
924 {
925     UDI_HID_CON_DISABLE_EXT();
926 }
927
928 bool udi_hid_con_setup(void)
929 {
930     return udi_hid_setup(&udi_hid_con_rate,
931                             &udi_hid_con_protocol,
932                             (uint8_t *) &udi_hid_con_report_desc,
933                             udi_hid_con_setreport);
934 }
935
936 uint8_t udi_hid_con_getsetting(void)
937 {
938     return 0;
939 }
940
941 static bool udi_hid_con_setreport(void)
942 {
943     if ((USB_HID_REPORT_TYPE_OUTPUT == (udd_g_ctrlreq.req.wValue >> 8))
944             && (0 == (0xFF & udd_g_ctrlreq.req.wValue))
945             && (UDI_HID_CON_REPORT_SIZE == udd_g_ctrlreq.req.wLength)) {
946         udd_g_ctrlreq.payload = udi_hid_con_report_set;
947         udd_g_ctrlreq.callback = udi_hid_con_setreport_valid;
948         udd_g_ctrlreq.payload_size = UDI_HID_CON_REPORT_SIZE;
949         return true;
950     }
951     return false;
952 }
953
954 bool udi_hid_con_send_report(void)
955 {
956     if (!main_b_con_enable) {
957         return false;
958     }
959
960     if (udi_hid_con_b_report_trans_ongoing) {
961         return false;
962     }
963
964     memcpy(udi_hid_con_report_trans, udi_hid_con_report,UDI_HID_CON_REPORT_SIZE);
965     udi_hid_con_b_report_valid = false;
966     udi_hid_con_b_report_trans_ongoing =
967             udd_ep_run(UDI_HID_CON_EP_IN | USB_EP_DIR_IN,
968                         false,
969                         udi_hid_con_report_trans,
970                         UDI_HID_CON_REPORT_SIZE,
971                         udi_hid_con_report_sent);
972
973     return udi_hid_con_b_report_trans_ongoing;
974 }
975
976 static void udi_hid_con_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep)
977 {
978     UNUSED(status);
979     UNUSED(nb_sent);
980     UNUSED(ep);
981     udi_hid_con_b_report_trans_ongoing = false;
982     if (udi_hid_con_b_report_valid) {
983         udi_hid_con_send_report();
984     }
985 }
986
987 static void udi_hid_con_setreport_valid(void)
988 {
989
990 }
991
992 #endif //CON