1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
/* usb_keyboard.c - Implementation of a USB keyboard device
*
* Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
* SPDX-Licence-Identifier: AGPL-3.0-or-later
*/
#include "tusb.h"
#include "tusb_helpers.h" /* for TUD_ENDPOINT_IN */
#include "usb_common.h"
#include "usb_keyboard.h"
/**
* A USB-HID "Report Descriptor" (see USB-HID 1.11 §6.2.2 "Report
* Descriptor") describing a keyboard.
*/
static uint8_t const hid_report_descriptor_keyboard[] = { TUD_HID_REPORT_DESC_KEYBOARD() };
static uint8_t kbd_ifc = 0;
void usb_keyboard_init() {
if (kbd_ifc)
return;
usb_common_init();
kbd_ifc = usb_add_interface(cfgnum_std, TUD_HID_DESC_LEN, (uint8_t[]){
/* USB-HID input-only descriptor for inclusion in the config descriptor; consisting of 3 parts:
* 1. an interface descriptor (USB 2.0 §9.6.5 "Interface"),
* 2. a class-specific (class=HID) descriptor of type HID (USB-HID 1.11 §6.2.1 "HID Descriptor"),
* 3. an endpoint descriptor for inputs (USB 2.0 §9.6.6 "Endpoint").
* The TUD_HID_DESCRIPTOR() macro takes care of this for us. */
TUD_HID_DESCRIPTOR(
0, /* interface : bInterfaceNumber ; Number of this interface (0-indexed) */
STRID_KBD_IFC, /* interface : iInterface ; Index of string descriptor describing this interface */
HID_ITF_PROTOCOL_KEYBOARD, /* interface : bInterfaceProtocol ; see USB-HID 1.11 §4.3 "Protocols" */
sizeof(hid_report_descriptor_keyboard), /* hid : wDescriptorLength ; Total size of report descriptor */
TUD_ENDPOINT_IN | 1, /* endpoint : bEndpointAddress ; Direction | endpoint number (arbitrary?) */
CFG_TUD_HID_EP_BUFSIZE, /* endpoint : wMaxPacketSize ; Maximum packet size this endpoint is capable of sending or receiving */
10), /* endpoint : bInterval ; poll interval (in milliseconds?) */
});
}
static uint8_t ascii2keycode[128][2] = { HID_ASCII_TO_KEYCODE };
void usb_keyboard_cr(void *_stack) {
usb_keyboard_stack_t *stack = _stack;
cr_begin();
for (;;) {
while (!tud_hid_n_ready(kbd_ifc))
cr_yield();
if (cr_chan_have_req(stack->chan)) {
cr_chan_recv_req(stack->chan, &stack->rune);
stack->modifier = ascii2keycode[stack->rune][0] ? KEYBOARD_MODIFIER_LEFTSHIFT : 0;
stack->keycodes[0] = ascii2keycode[stack->rune][1];
tud_hid_n_keyboard_report(kbd_ifc, stack->report_id, stack->modifier, stack->keycodes);
while (!tud_hid_n_ready(kbd_ifc))
cr_yield();
stack->modifier = 0;
stack->keycodes[0] = 0;
tud_hid_n_keyboard_report(kbd_ifc, stack->report_id, stack->modifier, stack->keycodes);
cr_chan_send_resp(stack->chan, 1);
} else {
stack->modifier = 0;
stack->keycodes[0] = 0;
tud_hid_n_keyboard_report(kbd_ifc, stack->report_id, stack->modifier, stack->keycodes);
}
}
cr_end()
}
/**
* Return a pointer to the HID "Report Descriptor" (see USB-HID 1.11
* §6.2.2 "Report Descriptor") for the given index.
*/
uint8_t const *tud_hid_descriptor_report_cb(uint8_t index) {
static uint8_t const *reports[] = {
hid_report_descriptor_keyboard,
};
if (index >= TU_ARRAY_SIZE(reports))
return NULL;
return reports[index];
}
uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen)
{
// TODO not Implemented
(void) instance;
(void) report_id;
(void) report_type;
(void) buffer;
(void) reqlen;
return 0;
}
// Invoked when received SET_REPORT control request or
// received data on OUT endpoint ( Report ID = 0, Type = 0 )
void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize)
{
// TODO not implemented
(void) report_id;
}
|