summaryrefslogtreecommitdiff
path: root/usb_keyboard.c
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2024-09-16 02:49:13 -0600
committerLuke T. Shumaker <lukeshu@lukeshu.com>2024-09-16 02:49:13 -0600
commit93f054683dd5fc5b79541f4922cb34a38cb5c341 (patch)
tree5fed989181dbf1c7714c6c4fe7b910344e8ba30d /usb_keyboard.c
parent7c30fe0be98a3028964d437f5c31cc968fbf9755 (diff)
keyboard hello world?
Diffstat (limited to 'usb_keyboard.c')
-rw-r--r--usb_keyboard.c108
1 files changed, 108 insertions, 0 deletions
diff --git a/usb_keyboard.c b/usb_keyboard.c
new file mode 100644
index 0000000..5647403
--- /dev/null
+++ b/usb_keyboard.c
@@ -0,0 +1,108 @@
+#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?) */
+ });
+}
+
+#define kbd_buf_cap 1024
+static uint32_t kbd_buf[kbd_buf_cap];
+static size_t kbd_buf_beg = 0;
+static size_t kbd_buf_len = 0;
+
+static uint8_t ascii2keycode[128][2] = { HID_ASCII_TO_KEYCODE };
+
+void usb_keyboard_task(void) {
+ if (tud_hid_n_ready(kbd_ifc)) {
+ uint8_t const report_id = 0;
+ uint8_t modifier = 0;
+ uint8_t keycodes[6] = {0};
+
+ if (kbd_buf_len) {
+ if (ascii2keycode[kbd_buf[kbd_buf_beg]][0])
+ modifier = KEYBOARD_MODIFIER_LEFTSHIFT;
+ keycodes[0] = ascii2keycode[kbd_buf[kbd_buf_beg]][1];
+
+ kbd_buf_beg++;
+ if (kbd_buf_beg == kbd_buf_cap)
+ kbd_buf_beg = 0;
+ kbd_buf_len--;
+ }
+
+ tud_hid_n_keyboard_report(kbd_ifc, report_id, modifier, keycodes);
+ }
+}
+
+bool usb_keyboard_send_char(uint32_t ch) {
+ if (kbd_buf_len == kbd_buf_cap) /* buffer full */
+ return false;
+ if (ch > 0x7F) /* not ASCII */
+ return false;
+ kbd_buf[(kbd_buf_beg + kbd_buf_len++) % kbd_buf_cap] = ch;
+}
+
+bool usb_keyboard_is_flushed(void) {
+ return kbd_buf_len == 0;
+}
+
+/**
+ * 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 >= sizeof reports / sizeof reports[0])
+ 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;
+}