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
7381void 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) {
9095uint8_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+ }
0 commit comments