Skip to content

Commit d39c7aa

Browse files
committed
stmhal: Add Python-configurable USB HID mode.
Different HID modes can be configured in Python. You can either use predefined mouse or keyboard, or write your own report descriptor.
1 parent b384bcc commit d39c7aa

File tree

13 files changed

+461
-202
lines changed

13 files changed

+461
-202
lines changed

docs/library/pyb.USB_VCP.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ Methods
2626
Set to -1 to disable this interrupt feature. This is useful when you
2727
want to send raw bytes over the USB VCP port.
2828

29+
.. method:: usb_vcp.isconnected()
30+
31+
Return ``True`` if USB is connected as a serial device, else ``False``.
32+
2933
.. method:: usb_vcp.any()
3034

3135
Return ``True`` if any characters waiting, else ``False``.

docs/library/pyb.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,11 +149,15 @@ Miscellaneous functions
149149

150150
Return True if USB is connected as a serial device, False otherwise.
151151

152+
.. note:: This function is deprecated. Use pyb.USB_VCP().isconnected() instead.
153+
152154
.. function:: hid((buttons, x, y, z))
153155

154156
Takes a 4-tuple (or list) and sends it to the USB host (the PC) to
155157
signal a HID mouse-motion event.
156158

159+
.. note:: This function is deprecated. Use pyb.USB_HID().send(...) instead.
160+
157161
.. function:: info([dump_alloc_table])
158162

159163
Print out lots of information about the board.

stmhal/main.c

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -120,14 +120,6 @@ STATIC mp_obj_t pyb_main(mp_obj_t main) {
120120
}
121121
MP_DEFINE_CONST_FUN_OBJ_1(pyb_main_obj, pyb_main);
122122

123-
STATIC mp_obj_t pyb_usb_mode(mp_obj_t usb_mode) {
124-
if (MP_OBJ_IS_STR(usb_mode)) {
125-
MP_STATE_PORT(pyb_config_usb_mode) = usb_mode;
126-
}
127-
return mp_const_none;
128-
}
129-
MP_DEFINE_CONST_FUN_OBJ_1(pyb_usb_mode_obj, pyb_usb_mode);
130-
131123
static const char fresh_boot_py[] =
132124
"# boot.py -- run on boot-up\r\n"
133125
"# can run arbitrary Python, but best to keep it minimal\r\n"
@@ -309,6 +301,11 @@ int main(void) {
309301
switch_init0();
310302
#endif
311303

304+
#if defined(USE_DEVICE_MODE)
305+
// default to internal flash being the usb medium
306+
pyb_usb_storage_medium = PYB_USB_STORAGE_MEDIUM_FLASH;
307+
#endif
308+
312309
int first_soft_reset = true;
313310

314311
soft_reset:
@@ -415,37 +412,38 @@ int main(void) {
415412
// Create it if needed, mount in on /flash, and set it as current dir.
416413
init_flash_fs(reset_mode);
417414

418-
#if defined(USE_DEVICE_MODE)
419-
usb_storage_medium_t usb_medium = USB_STORAGE_MEDIUM_FLASH;
420-
#endif
421-
422415
#if MICROPY_HW_HAS_SDCARD
423416
// if an SD card is present then mount it on /sd/
424417
if (sdcard_is_present()) {
425418
FRESULT res = f_mount(&fatfs1, "/sd", 1);
426419
if (res != FR_OK) {
427420
printf("[SD] could not mount SD card\n");
428421
} else {
429-
// use SD card as current directory
430-
f_chdrive("/sd");
431-
432422
// TODO these should go before the /flash entries in the path
433423
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_sd));
434424
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_sd_slash_lib));
435425

436426
if (first_soft_reset) {
437427
// use SD card as medium for the USB MSD
438428
#if defined(USE_DEVICE_MODE)
439-
usb_medium = USB_STORAGE_MEDIUM_SDCARD;
429+
pyb_usb_storage_medium = PYB_USB_STORAGE_MEDIUM_SDCARD;
440430
#endif
441431
}
432+
433+
#if defined(USE_DEVICE_MODE)
434+
// only use SD card as current directory if that's what the USB medium is
435+
if (pyb_usb_storage_medium == PYB_USB_STORAGE_MEDIUM_SDCARD)
436+
#endif
437+
{
438+
// use SD card as current directory
439+
f_chdrive("/sd");
440+
}
442441
}
443442
}
444443
#endif
445444

446445
// reset config variables; they should be set by boot.py
447446
MP_STATE_PORT(pyb_config_main) = MP_OBJ_NULL;
448-
MP_STATE_PORT(pyb_config_usb_mode) = MP_OBJ_NULL;
449447

450448
// run boot.py, if it exists
451449
// TODO perhaps have pyb.reboot([bootpy]) function to soft-reboot and execute custom boot.py
@@ -472,19 +470,11 @@ int main(void) {
472470
// or whose initialisation can be safely deferred until after running
473471
// boot.py.
474472

475-
#if defined(USE_HOST_MODE)
476-
// USB host
477-
pyb_usb_host_init();
478-
#elif defined(USE_DEVICE_MODE)
479-
// USB device
480-
usb_device_mode_t usb_mode = USB_DEVICE_MODE_CDC_MSC;
481-
// if we are not in reset_mode==1, this config variable will always be NULL
482-
if (MP_STATE_PORT(pyb_config_usb_mode) != MP_OBJ_NULL) {
483-
if (strcmp(mp_obj_str_get_str(MP_STATE_PORT(pyb_config_usb_mode)), "CDC+HID") == 0) {
484-
usb_mode = USB_DEVICE_MODE_CDC_HID;
485-
}
473+
#if defined(USE_DEVICE_MODE)
474+
// init USB device to default setting if it was not already configured
475+
if (!(pyb_usb_flags & PYB_USB_FLAG_USB_MODE_CALLED)) {
476+
pyb_usb_dev_init(USBD_PID_DEFAULT, USBD_MODE_CDC_MSC, NULL);
486477
}
487-
pyb_usb_dev_init(usb_mode, usb_medium);
488478
#endif
489479

490480
#if MICROPY_HW_HAS_MMA7660

stmhal/modpyb.c

Lines changed: 8 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@
6969
/// \function bootloader()
7070
/// Activate the bootloader without BOOT* pins.
7171
STATIC NORETURN mp_obj_t pyb_bootloader(void) {
72-
pyb_usb_dev_stop();
72+
pyb_usb_dev_deinit();
7373
storage_flush();
7474

7575
HAL_RCC_DeInit();
@@ -465,13 +465,6 @@ STATIC mp_obj_t pyb_standby(void) {
465465
}
466466
MP_DEFINE_CONST_FUN_OBJ_0(pyb_standby_obj, pyb_standby);
467467

468-
/// \function have_cdc()
469-
/// Return True if USB is connected as a serial device, False otherwise.
470-
STATIC mp_obj_t pyb_have_cdc(void ) {
471-
return MP_BOOL(usb_vcp_is_connected());
472-
}
473-
STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_have_cdc_obj, pyb_have_cdc);
474-
475468
/// \function repl_uart(uart)
476469
/// Get or set the UART object that the REPL is repeated on.
477470
STATIC mp_obj_t pyb_repl_uart(mp_uint_t n_args, const mp_obj_t *args) {
@@ -494,24 +487,7 @@ STATIC mp_obj_t pyb_repl_uart(mp_uint_t n_args, const mp_obj_t *args) {
494487
}
495488
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_repl_uart_obj, 0, 1, pyb_repl_uart);
496489

497-
/// \function hid((buttons, x, y, z))
498-
/// Takes a 4-tuple (or list) and sends it to the USB host (the PC) to
499-
/// signal a HID mouse-motion event.
500-
STATIC mp_obj_t pyb_hid_send_report(mp_obj_t arg) {
501-
mp_obj_t *items;
502-
mp_obj_get_array_fixed_n(arg, 4, &items);
503-
uint8_t data[4];
504-
data[0] = mp_obj_get_int(items[0]);
505-
data[1] = mp_obj_get_int(items[1]);
506-
data[2] = mp_obj_get_int(items[2]);
507-
data[3] = mp_obj_get_int(items[3]);
508-
usb_hid_send_report(data);
509-
return mp_const_none;
510-
}
511-
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_hid_send_report_obj, pyb_hid_send_report);
512-
513490
MP_DECLARE_CONST_FUN_OBJ(pyb_main_obj); // defined in main.c
514-
MP_DECLARE_CONST_FUN_OBJ(pyb_usb_mode_obj); // defined in main.c
515491

516492
STATIC const mp_map_elem_t pyb_module_globals_table[] = {
517493
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_pyb) },
@@ -530,12 +506,16 @@ STATIC const mp_map_elem_t pyb_module_globals_table[] = {
530506
{ MP_OBJ_NEW_QSTR(MP_QSTR_stop), (mp_obj_t)&pyb_stop_obj },
531507
{ MP_OBJ_NEW_QSTR(MP_QSTR_standby), (mp_obj_t)&pyb_standby_obj },
532508
{ MP_OBJ_NEW_QSTR(MP_QSTR_main), (mp_obj_t)&pyb_main_obj },
533-
{ MP_OBJ_NEW_QSTR(MP_QSTR_usb_mode), (mp_obj_t)&pyb_usb_mode_obj },
509+
{ MP_OBJ_NEW_QSTR(MP_QSTR_repl_uart), (mp_obj_t)&pyb_repl_uart_obj },
534510

511+
{ MP_OBJ_NEW_QSTR(MP_QSTR_usb_mode), (mp_obj_t)&pyb_usb_mode_obj },
512+
{ MP_OBJ_NEW_QSTR(MP_QSTR_hid_mouse), (mp_obj_t)&pyb_usb_hid_mouse_obj },
513+
{ MP_OBJ_NEW_QSTR(MP_QSTR_hid_keyboard), (mp_obj_t)&pyb_usb_hid_keyboard_obj },
514+
{ MP_OBJ_NEW_QSTR(MP_QSTR_USB_VCP), (mp_obj_t)&pyb_usb_vcp_type },
515+
{ MP_OBJ_NEW_QSTR(MP_QSTR_USB_HID), (mp_obj_t)&pyb_usb_hid_type },
516+
// these 2 are deprecated; use USB_VCP.isconnected and USB_HID.send instead
535517
{ MP_OBJ_NEW_QSTR(MP_QSTR_have_cdc), (mp_obj_t)&pyb_have_cdc_obj },
536-
{ MP_OBJ_NEW_QSTR(MP_QSTR_repl_uart), (mp_obj_t)&pyb_repl_uart_obj },
537518
{ MP_OBJ_NEW_QSTR(MP_QSTR_hid), (mp_obj_t)&pyb_hid_send_report_obj },
538-
{ MP_OBJ_NEW_QSTR(MP_QSTR_USB_VCP), (mp_obj_t)&pyb_usb_vcp_type },
539519

540520
{ MP_OBJ_NEW_QSTR(MP_QSTR_millis), (mp_obj_t)&pyb_millis_obj },
541521
{ MP_OBJ_NEW_QSTR(MP_QSTR_elapsed_millis), (mp_obj_t)&pyb_elapsed_millis_obj },

stmhal/mpconfigport.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,9 +133,9 @@ extern const struct _mp_obj_module_t mp_module_network;
133133
const char *readline_hist[8]; \
134134
\
135135
mp_obj_t mp_const_vcp_interrupt; \
136+
mp_obj_t pyb_hid_report_desc; \
136137
\
137138
mp_obj_t pyb_config_main; \
138-
mp_obj_t pyb_config_usb_mode; \
139139
\
140140
mp_obj_t pyb_switch_callback; \
141141
\

stmhal/qstrdefsport.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ Q(stop)
4242
Q(standby)
4343
Q(main)
4444
Q(usb_mode)
45+
Q(hid_mouse)
46+
Q(hid_keyboard)
4547
Q(sync)
4648
Q(gc)
4749
Q(repl_info)
@@ -53,7 +55,6 @@ Q(read)
5355
Q(readall)
5456
Q(readline)
5557
Q(write)
56-
Q(have_cdc)
5758
Q(repl_uart)
5859
Q(hid)
5960
Q(time)
@@ -98,10 +99,19 @@ Q(tell)
9899
// for USB VCP class
99100
Q(USB_VCP)
100101
Q(setinterrupt)
102+
Q(isconnected)
103+
Q(have_cdc)
104+
Q(any)
101105
Q(send)
102106
Q(recv)
103107
Q(timeout)
104108

109+
// for USB HID class
110+
Q(USB_HID)
111+
Q(any)
112+
Q(send)
113+
Q(recv)
114+
105115
// for RTC class
106116
Q(RTC)
107117
Q(info)

0 commit comments

Comments
 (0)