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