Skip to content

Commit 31f5b6a

Browse files
committed
WIP: simple working HID
1 parent 9d928b5 commit 31f5b6a

15 files changed

Lines changed: 206 additions & 223 deletions

File tree

main.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -286,12 +286,12 @@ int __attribute__((used)) main(void) {
286286
#endif
287287

288288
// Reset to remove any state that boot.py setup. It should only be used to
289-
// change internal state thats not in the heap.
289+
// change internal state that's not in the heap.
290290
reset_port();
291291
reset_mp();
292292
}
293293

294-
// Start serial after giving boot.py a chance to tweak behavior.
294+
// Start serial and HID after giving boot.py a chance to tweak behavior.
295295
serial_init();
296296

297297
// Boot script is finished, so now go into REPL/main mode.

ports/atmel-samd/Makefile

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ ifeq ($(DEBUG), 1)
9797
# Turn on Python modules useful for debugging (e.g. uheap, ustack).
9898
CFLAGS += -ggdb
9999
CFLAGS += -flto
100-
## CFLAGS += -fno-inline
100+
CFLAGS += -fno-inline
101101
ifeq ($(CHIP_FAMILY), samd21)
102102
CFLAGS += -DENABLE_MICRO_TRACE_BUFFER
103103
endif
@@ -193,6 +193,8 @@ SRC_ASF := \
193193
hpl/systick/hpl_systick.c \
194194
hpl/usb/hpl_usb.c \
195195
usb/class/cdc/device/cdcdf_acm.c \
196+
usb/class/hid/device/hiddf_keyboard.c \
197+
usb/class/hid/device/hiddf_mouse.c \
196198
usb/class/msc/device/mscdf.c \
197199
usb/device/usbdc.c \
198200
usb/usb_protocol.c \
@@ -282,6 +284,8 @@ SRC_COMMON_HAL = \
282284
pulseio/PulseIn.c \
283285
pulseio/PulseOut.c \
284286
pulseio/PWMOut.c \
287+
usb_hid/__init__.c \
288+
usb_hid/Device.c
285289
# audiobusio/__init__.c \
286290
audiobusio/PDMIn.c \
287291
audioio/__init__.c \
@@ -290,8 +294,6 @@ SRC_COMMON_HAL = \
290294
nvm/ByteArray.c \
291295
touchio/__init__.c \
292296
touchio/TouchIn.c \
293-
usb_hid/__init__.c \
294-
usb_hid/Device.c
295297
296298
ifeq ($(INTERNAL_LIBM),1)
297299
SRC_LIBM = $(addprefix lib/,\

ports/atmel-samd/common-hal/usb_hid/Device.c

Lines changed: 62 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -26,60 +26,65 @@
2626

2727
#include <string.h>
2828

29-
#include "py/nlr.h"
30-
#include "common-hal/usb_hid/__init__.h"
29+
#include "common-hal/usb_hid/Device.h"
30+
31+
#include "py/runtime.h"
3132
#include "shared-bindings/microcontroller/__init__.h"
3233
#include "shared-bindings/usb_hid/Device.h"
34+
#include "tools/autogen_usb_descriptor.h"
3335

34-
static void report_sent(udd_ep_status_t status, iram_size_t nb_sent,
35-
udd_ep_id_t ep) {
36-
UNUSED(status);
37-
UNUSED(nb_sent);
38-
for (uint8_t i = 0; i < 2; i++) {
39-
if (ep == usb_hid_devices[i].endpoint) {
40-
usb_hid_devices[i].transaction_ongoing = false;
41-
return;
42-
}
43-
}
44-
}
36+
#include "tick.h"
4537

46-
bool usb_hid_send_report(usb_hid_device_obj_t *self, uint8_t* report, uint8_t len) {
47-
if (!self->enabled) {
48-
return true;
49-
}
50-
// Wait for the previous transaction to finish. Shouldn't happen.
51-
uint32_t timeout = 0xffff;
38+
#include "usb/class/hid/device/hiddf_mouse.h"
39+
#include "usb/class/hid/device/hiddf_keyboard.h"
5240

53-
while (self->transaction_ongoing && timeout > 0) {
54-
timeout--;
55-
}
41+
static uint32_t usb_hid_send_report(usb_hid_device_obj_t *self, uint8_t* report, uint8_t len) {
5642

57-
if (self->transaction_ongoing) {
58-
return false;
43+
int32_t status;
44+
45+
// Don't get stuck if USB fails in some way; timeout after a while.
46+
uint64_t end_ticks = ticks_ms + 2000;
47+
48+
while (ticks_ms < end_ticks) {
49+
status = usb_d_ep_get_status(self->endpoint, NULL);
50+
if (status == USB_BUSY) {
51+
continue;
52+
}
53+
if (status == USB_OK) {
54+
break;
55+
}
56+
// Some error. Give up.
57+
return status;
5958
}
6059

60+
// Copy the data only when endpoint is ready to send. The previous
61+
// buffer load gets zero'd out when transaction completes, so if
62+
// you copy before it's ready, only zeros will get sent.
6163
memcpy(self->report_buffer, report, len);
6264

63-
// Disable interrupts to make sure we save the ongoing state before the
64-
// report_sent interrupt.
65-
common_hal_mcu_disable_interrupts();
66-
bool ok = udd_ep_run(self->endpoint, false,
67-
self->report_buffer, self->report_length, report_sent);
68-
self->transaction_ongoing = ok;
69-
common_hal_mcu_enable_interrupts();
70-
return ok;
65+
switch (self->kind) {
66+
case USB_HID_MOUSE:
67+
status = hiddf_mouse_write(self->report_buffer, self->report_length);
68+
break;
69+
70+
case USB_HID_KEYBOARD:
71+
status = hiddf_keyboard_write(self->report_buffer, self->report_length);
72+
break;
73+
74+
default:
75+
mp_raise_ValueError("Unknown HID device");
76+
}
77+
78+
return status;
7179
}
7280

7381
void common_hal_usb_hid_device_send_report(usb_hid_device_obj_t *self, uint8_t* report, uint8_t len) {
7482
if (len != self->report_length) {
75-
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
76-
"Buffer incorrect size. Should be %d bytes.", self->report_length));
83+
mp_raise_ValueError_varg("Buffer incorrect size. Should be %d bytes.", self->report_length);
7784
}
78-
if (!self->enabled) {
79-
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "USB Inactive"));
80-
}
81-
if (!usb_hid_send_report(self, report, len)) {
82-
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "USB Busy"));
85+
int32_t status = usb_hid_send_report(self, report, len);
86+
if (status != ERR_NONE) {
87+
mp_raise_msg(&mp_type_OSError, status == USB_BUSY ? "USB Busy" : "USB Error");
8388
}
8489
}
8590

@@ -90,3 +95,21 @@ uint8_t common_hal_usb_hid_device_get_usage_page(usb_hid_device_obj_t *self) {
9095
uint8_t common_hal_usb_hid_device_get_usage(usb_hid_device_obj_t *self) {
9196
return self->usage;
9297
}
98+
99+
100+
void usb_hid_init() {
101+
usb_hid_devices[USB_HID_DEVICE_MOUSE].base.type = &usb_hid_device_type;
102+
usb_hid_devices[USB_HID_DEVICE_MOUSE].endpoint = hid_mouse_endpoint_in;
103+
104+
usb_hid_devices[USB_HID_DEVICE_KEYBOARD].base.type = &usb_hid_device_type;
105+
usb_hid_devices[USB_HID_DEVICE_KEYBOARD].endpoint = hid_keyboard_endpoint_in;
106+
}
107+
108+
void usb_hid_reset() {
109+
// We don't actually reset. We just set a report that is empty to prevent
110+
// long keypresses and such.
111+
uint8_t report[8] = {0, 0, 0, 0, 0, 0, 0, 0};
112+
113+
usb_hid_send_report(&usb_hid_devices[USB_HID_DEVICE_MOUSE], report, UDI_HID_MOUSE_REPORT_SIZE);
114+
usb_hid_send_report(&usb_hid_devices[USB_HID_DEVICE_KEYBOARD], report, UDI_HID_KBD_REPORT_SIZE);
115+
}

ports/atmel-samd/common-hal/usb_hid/Device.h

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,34 @@
3030
#include <stdint.h>
3131
#include <stdbool.h>
3232

33-
#include "common-hal/usb_hid/types.h"
33+
#include "py/obj.h"
3434

35-
bool usb_hid_send_report(usb_hid_device_obj_t *self, uint8_t* report, uint8_t len);
35+
#define UDI_HID_MOUSE_REPORT_SIZE 4
36+
#define UDI_HID_KBD_REPORT_SIZE 8
37+
38+
enum usb_hid_device_kind {
39+
USB_HID_UNKNOWN,
40+
USB_HID_MOUSE,
41+
USB_HID_KEYBOARD,
42+
};
43+
44+
typedef struct {
45+
mp_obj_base_t base;
46+
enum usb_hid_device_kind kind;
47+
uint8_t endpoint;
48+
uint8_t report_length;
49+
uint8_t* report_buffer;
50+
uint8_t usage_page;
51+
uint8_t usage;
52+
53+
} usb_hid_device_obj_t;
54+
55+
usb_hid_device_obj_t usb_hid_devices[2];
56+
// Indices into usb_hid_devices:
57+
#define USB_HID_DEVICE_MOUSE 0
58+
#define USB_HID_DEVICE_KEYBOARD 1
59+
60+
void usb_hid_init(void);
61+
void usb_hid_reset(void);
3662

3763
#endif // COMMON_HAL_USB_HID_DEVICE_H

ports/atmel-samd/common-hal/usb_hid/__init__.c

Lines changed: 7 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -28,37 +28,29 @@
2828
#include "py/mphal.h"
2929
#include "py/runtime.h"
3030

31-
#include "common-hal/usb_hid/__init__.h"
3231
#include "common-hal/usb_hid/Device.h"
33-
#include "common-hal/usb_hid/types.h"
3432

35-
#include "shared-bindings/usb_hid/__init__.h"
3633
#include "shared-bindings/usb_hid/Device.h"
3734

38-
#define UDI_HID_MOUSE_REPORT_SIZE 4
39-
#define UDI_HID_KBD_REPORT_SIZE 8
35+
#include "tools/autogen_usb_descriptor.h"
4036

41-
uint8_t mouse_report_buffer[UDI_HID_MOUSE_REPORT_SIZE];
42-
uint8_t kbd_report_buffer[UDI_HID_KBD_REPORT_SIZE];
37+
static uint8_t mouse_report_buffer[UDI_HID_MOUSE_REPORT_SIZE];
38+
static uint8_t kbd_report_buffer[UDI_HID_KBD_REPORT_SIZE];
4339

4440
usb_hid_device_obj_t usb_hid_devices[2] = {
4541
{
46-
.endpoint = UDI_HID_MOUSE_EP_IN,
42+
.kind = USB_HID_MOUSE,
4743
.report_length = UDI_HID_MOUSE_REPORT_SIZE,
4844
.report_buffer = mouse_report_buffer,
4945
.usage_page = 0x01,
5046
.usage = 0x02,
51-
.enabled = false,
52-
.transaction_ongoing = false
5347
},
5448
{
55-
.endpoint = UDI_HID_KBD_EP_IN,
49+
.kind = USB_HID_KEYBOARD,
5650
.report_length = UDI_HID_KBD_REPORT_SIZE,
5751
.report_buffer = kbd_report_buffer,
5852
.usage_page = 0x01,
5953
.usage = 0x06,
60-
.enabled = false,
61-
.transaction_ongoing = false
6254
}
6355
};
6456

@@ -70,48 +62,7 @@ mp_obj_tuple2_t common_hal_usb_hid_devices = {
7062
},
7163
.len = 2,
7264
.items = {
73-
(mp_obj_t) &usb_hid_devices[0],
74-
(mp_obj_t) &usb_hid_devices[1]
65+
(mp_obj_t) &usb_hid_devices[USB_HID_DEVICE_MOUSE],
66+
(mp_obj_t) &usb_hid_devices[USB_HID_DEVICE_KEYBOARD],
7567
}
7668
};
77-
78-
void usb_hid_init() {
79-
usb_hid_devices[0].base.type = &usb_hid_device_type;
80-
usb_hid_devices[1].base.type = &usb_hid_device_type;
81-
}
82-
83-
void usb_hid_reset() {
84-
// We don't actually reset. We just set a report that is empty to prevent
85-
// long keypresses and such.
86-
uint8_t report[8] = {0, 0, 0, 0, 0, 0, 0, 0};
87-
88-
usb_hid_send_report(&usb_hid_devices[0], report, 4);
89-
usb_hid_send_report(&usb_hid_devices[1], report, 8);
90-
}
91-
92-
bool mp_mouse_enable(void)
93-
{
94-
usb_hid_devices[0].enabled = true;
95-
return true;
96-
}
97-
98-
void mp_mouse_disable(void)
99-
{
100-
usb_hid_devices[0].enabled = false;
101-
}
102-
103-
bool mp_keyboard_enable(void)
104-
{
105-
usb_hid_devices[1].enabled = true;
106-
return true;
107-
}
108-
109-
void mp_keyboard_disable(void)
110-
{
111-
usb_hid_devices[1].enabled = false;
112-
}
113-
114-
void mp_keyboard_led(uint8_t leds)
115-
{
116-
UNUSED(leds);
117-
}

ports/atmel-samd/common-hal/usb_hid/__init__.h

Lines changed: 0 additions & 40 deletions
This file was deleted.

ports/atmel-samd/common-hal/usb_hid/types.h

Lines changed: 0 additions & 43 deletions
This file was deleted.

0 commit comments

Comments
 (0)