summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
m---------lib/tinyusb0
-rwxr-xr-xports/nrf/Makefile42
-rw-r--r--ports/nrf/common-hal/usb_hid/Device.c88
-rw-r--r--ports/nrf/common-hal/usb_hid/Device.h94
-rw-r--r--ports/nrf/common-hal/usb_hid/__init__.c160
-rw-r--r--ports/nrf/interrupt_char.c58
-rw-r--r--ports/nrf/mpconfigport.h22
-rw-r--r--ports/nrf/usb/tusb_config.h32
-rw-r--r--ports/nrf/usb/usb.c49
-rw-r--r--ports/nrf/usb/usb_desc.c391
-rw-r--r--ports/nrf/usb/usb_desc.h87
-rw-r--r--ports/nrf/usb/usb_msc_flash.c116
12 files changed, 930 insertions, 209 deletions
diff --git a/lib/tinyusb b/lib/tinyusb
-Subproject 421ae8fc82b884e087e99c8ab3fa25883a3dd62
+Subproject 6d96b12e27ae60ca500365ee2137105145ada9d
diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile
index 99b1e88b3..8e1154369 100755
--- a/ports/nrf/Makefile
+++ b/ports/nrf/Makefile
@@ -102,7 +102,6 @@ SRC_C += \
tick.c \
background.c \
internal_flash.c \
- interrupt_char.c \
drivers/bluetooth/ble_drv.c \
drivers/bluetooth/ble_uart.c \
boards/$(BOARD)/board.c \
@@ -115,27 +114,12 @@ SRC_C += \
lib/utils/buffer_helper.c \
lib/utils/context_manager_helpers.c \
lib/utils/pyexec.c \
+ lib/utils/interrupt_char.c \
lib/utils/stdout_helpers.c \
lib/utils/sys_stdio_mphal.c \
lib/libc/string0.c \
lib/mp-readline/readline.c \
-ifeq ($(MCU_SUB_VARIANT),nrf52840)
-
-SRC_C += \
- usb/usb.c \
- usb/usb_msc_flash.c \
- lib/tinyusb/src/portable/nordic/nrf5x/dcd_nrf5x.c \
- lib/tinyusb/src/portable/nordic/nrf5x/hal_nrf5x.c \
- lib/tinyusb/src/common/tusb_fifo.c \
- lib/tinyusb/src/device/usbd.c \
- lib/tinyusb/src/device/usbd_desc.c \
- lib/tinyusb/src/class/msc/msc_device.c \
- lib/tinyusb/src/class/cdc/cdc_device.c \
- lib/tinyusb/src/tusb.c \
-
-endif
-
DRIVERS_SRC_C += $(addprefix modules/,\
ubluepy/modubluepy.c \
ubluepy/ubluepy_peripheral.c \
@@ -219,7 +203,29 @@ SRC_SHARED_BINDINGS = \
bitbangio/I2C.c \
bitbangio/SPI.c \
bitbangio/OneWire.c \
- random/__init__.c
+ random/__init__.c \
+
+# USB source files for nrf52840
+ifeq ($(MCU_SUB_VARIANT),nrf52840)
+
+SRC_C += \
+ usb/usb.c \
+ usb/usb_msc_flash.c \
+ usb/usb_desc.c \
+ lib/tinyusb/src/portable/nordic/nrf5x/dcd_nrf5x.c \
+ lib/tinyusb/src/portable/nordic/nrf5x/hal_nrf5x.c \
+ lib/tinyusb/src/common/tusb_fifo.c \
+ lib/tinyusb/src/device/usbd.c \
+ lib/tinyusb/src/class/msc/msc_device.c \
+ lib/tinyusb/src/class/cdc/cdc_device.c \
+ lib/tinyusb/src/class/hid/hid_device.c \
+ lib/tinyusb/src/tusb.c \
+
+SRC_COMMON_HAL += \
+ usb_hid/__init__.c \
+ usb_hid/Device.c \
+
+endif
SRC_SHARED_MODULE_EXPANDED = $(addprefix shared-bindings/, $(SRC_SHARED_BINDINGS)) \
diff --git a/ports/nrf/common-hal/usb_hid/Device.c b/ports/nrf/common-hal/usb_hid/Device.c
new file mode 100644
index 000000000..c2fff7001
--- /dev/null
+++ b/ports/nrf/common-hal/usb_hid/Device.c
@@ -0,0 +1,88 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 hathach for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <string.h>
+#include "tick.h"
+#include "common-hal/usb_hid/Device.h"
+#include "py/runtime.h"
+#include "shared-bindings/usb_hid/Device.h"
+#include "tusb.h"
+
+uint8_t common_hal_usb_hid_device_get_usage_page(usb_hid_device_obj_t *self) {
+ return self->usage_page;
+}
+
+uint8_t common_hal_usb_hid_device_get_usage(usb_hid_device_obj_t *self) {
+ return self->usage;
+}
+
+void common_hal_usb_hid_device_send_report(usb_hid_device_obj_t *self, uint8_t* report, uint8_t len) {
+ if (len != self->report_length) {
+ mp_raise_ValueError_varg("Buffer incorrect size. Should be %d bytes.", self->report_length);
+ }
+
+ // Wait until interface is ready, timeout = 2 seconds
+ uint64_t end_ticks = ticks_ms + 2000;
+ while ( (ticks_ms < end_ticks) && !tud_hid_generic_ready() ) { }
+
+ if ( !tud_hid_generic_ready() ) {
+ mp_raise_msg(&mp_type_OSError, "USB Busy");
+ }
+
+ memcpy(self->report_buffer, report, len);
+
+ if ( !tud_hid_generic_report(self->report_id, self->report_buffer, len) ) {
+ mp_raise_msg(&mp_type_OSError, "USB Error");
+ }
+}
+
+// Callbacks invoked when receive Get_Report request through control endpoint
+uint16_t tud_hid_generic_get_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) {
+ // only support Input Report
+ if ( report_type != HID_REPORT_TYPE_INPUT ) return 0;
+
+ // index is ID-1
+ uint8_t idx = ( report_id ? (report_id-1) : 0 );
+
+ // fill buffer with current report
+ memcpy(buffer, usb_hid_devices[idx].report_buffer, reqlen);
+ return reqlen;
+}
+
+// Callbacks invoked when receive Set_Report request through control endpoint
+void tud_hid_generic_set_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) {
+ // index is ID-1
+ uint8_t idx = ( report_id ? (report_id-1) : 0 );
+
+ if ( report_type == HID_REPORT_TYPE_OUTPUT ) {
+ // Check if it is Keyboard device
+ if ( (usb_hid_devices[idx].usage_page == HID_USAGE_PAGE_DESKTOP) && (usb_hid_devices[idx].usage == HID_USAGE_DESKTOP_KEYBOARD) ) {
+ // This is LED indicator (CapsLock, NumLock)
+ // TODO Light up some LED here
+ }
+ }
+}
+
diff --git a/ports/nrf/common-hal/usb_hid/Device.h b/ports/nrf/common-hal/usb_hid/Device.h
new file mode 100644
index 000000000..612423715
--- /dev/null
+++ b/ports/nrf/common-hal/usb_hid/Device.h
@@ -0,0 +1,94 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 hathach for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef COMMON_HAL_USB_HID_DEVICE_H
+#define COMMON_HAL_USB_HID_DEVICE_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "py/obj.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+// 1 to enable device, 0 to disable
+#define USB_HID_DEVICE_KEYBOARD 1
+#define USB_HID_DEVICE_MOUSE 1
+#define USB_HID_DEVICE_CONSUMER 1
+#define USB_HID_DEVICE_SYS_CONTROL 1
+#define USB_HID_DEVICE_GAMEPAD 1
+#define USB_HID_DEVICE_DIGITIZER 0 // not supported yet
+
+enum {
+ USB_HID_REPORT_ID_UNUSED = 0,
+
+#if USB_HID_DEVICE_KEYBOARD
+ USB_HID_REPORT_ID_KEYBOARD,
+#endif
+
+#if USB_HID_DEVICE_MOUSE
+ USB_HID_REPORT_ID_MOUSE,
+#endif
+
+#if USB_HID_DEVICE_CONSUMER
+ USB_HID_REPORT_ID_CONSUMER,
+#endif
+
+#if USB_HID_DEVICE_SYS_CONTROL
+ USB_HID_REPORT_ID_SYS_CONTROL,
+#endif
+
+#if USB_HID_DEVICE_GAMEPAD
+ USB_HID_REPORT_ID_GAMEPAD,
+#endif
+
+#if USB_HID_DEVICE_DIGITIZER
+ USB_HID_REPORT_ID_DIGITIZER,
+#endif
+};
+
+#define USB_HID_NUM_DEVICES (USB_HID_DEVICE_KEYBOARD + USB_HID_DEVICE_MOUSE + USB_HID_DEVICE_CONSUMER + \
+ USB_HID_DEVICE_SYS_CONTROL + USB_HID_DEVICE_GAMEPAD + USB_HID_DEVICE_DIGITIZER )
+
+typedef struct {
+ mp_obj_base_t base;
+ uint8_t* report_buffer;
+ uint8_t report_id;
+ uint8_t report_length;
+ uint8_t usage_page;
+ uint8_t usage;
+} usb_hid_device_obj_t;
+
+
+extern usb_hid_device_obj_t usb_hid_devices[];
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* COMMON_HAL_USB_HID_DEVICE_H */
diff --git a/ports/nrf/common-hal/usb_hid/__init__.c b/ports/nrf/common-hal/usb_hid/__init__.c
new file mode 100644
index 000000000..00fc8bd00
--- /dev/null
+++ b/ports/nrf/common-hal/usb_hid/__init__.c
@@ -0,0 +1,160 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 hathach for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "py/obj.h"
+#include "py/mphal.h"
+#include "py/runtime.h"
+
+#include "common-hal/usb_hid/Device.h"
+#include "shared-bindings/usb_hid/Device.h"
+#include "tusb.h"
+
+#define USB_HID_REPORT_LENGTH_KEYBOARD 8
+#define USB_HID_REPORT_LENGTH_MOUSE 4
+#define USB_HID_REPORT_LENGTH_CONSUMER 2
+#define USB_HID_REPORT_LENGTH_SYS_CONTROL 1
+#define USB_HID_REPORT_LENGTH_GAMEPAD 6
+#define USB_HID_REPORT_LENGTH_DIGITIZER 5
+
+#if USB_HID_DEVICE_KEYBOARD
+static uint8_t keyboard_report_buffer[USB_HID_REPORT_LENGTH_KEYBOARD];
+#endif
+
+#if USB_HID_DEVICE_MOUSE
+static uint8_t mouse_report_buffer[USB_HID_REPORT_LENGTH_MOUSE];
+#endif
+
+#if USB_HID_DEVICE_CONSUMER
+static uint8_t consumer_report_buffer[USB_HID_REPORT_LENGTH_CONSUMER];
+#endif
+
+#if USB_HID_DEVICE_SYS_CONTROL
+static uint8_t sys_control_report_buffer[USB_HID_REPORT_LENGTH_SYS_CONTROL];
+#endif
+
+#if USB_HID_DEVICE_GAMEPAD
+static uint8_t gamepad_report_buffer[USB_HID_REPORT_LENGTH_GAMEPAD];
+#endif
+
+#if USB_HID_DEVICE_DIGITIZER
+static uint8_t digitizer_report_buffer[USB_HID_REPORT_LENGTH_DIGITIZER];
+#endif
+
+usb_hid_device_obj_t usb_hid_devices[] = {
+#if USB_HID_DEVICE_KEYBOARD
+ {
+ .base = { .type = &usb_hid_device_type } ,
+ .report_buffer = keyboard_report_buffer ,
+ .report_id = USB_HID_REPORT_ID_KEYBOARD ,
+ .report_length = USB_HID_REPORT_LENGTH_KEYBOARD ,
+ .usage_page = HID_USAGE_PAGE_DESKTOP ,
+ .usage = HID_USAGE_DESKTOP_KEYBOARD ,
+ },
+#endif
+
+#if USB_HID_DEVICE_MOUSE
+ {
+ .base = { .type = &usb_hid_device_type } ,
+ .report_buffer = mouse_report_buffer ,
+ .report_id = USB_HID_REPORT_ID_MOUSE ,
+ .report_length = USB_HID_REPORT_LENGTH_MOUSE ,
+ .usage_page = HID_USAGE_PAGE_DESKTOP ,
+ .usage = HID_USAGE_DESKTOP_MOUSE ,
+ },
+#endif
+
+#if USB_HID_DEVICE_CONSUMER
+ {
+ .base = { .type = &usb_hid_device_type } ,
+ .report_buffer = consumer_report_buffer ,
+ .report_id = USB_HID_REPORT_ID_CONSUMER ,
+ .report_length = USB_HID_REPORT_LENGTH_CONSUMER ,
+ .usage_page = HID_USAGE_PAGE_CONSUMER ,
+ .usage = HID_USAGE_CONSUMER_CONTROL ,
+ },
+#endif
+
+#if USB_HID_DEVICE_SYS_CONTROL
+ {
+ .base = { .type = &usb_hid_device_type } ,
+ .report_buffer = sys_control_report_buffer ,
+ .report_id = USB_HID_REPORT_ID_SYS_CONTROL ,
+ .report_length = USB_HID_REPORT_LENGTH_SYS_CONTROL ,
+ .usage_page = HID_USAGE_PAGE_DESKTOP ,
+ .usage = HID_USAGE_DESKTOP_SYSTEM_CONTROL ,
+ },
+#endif
+
+#if USB_HID_DEVICE_GAMEPAD
+ {
+ .base = { .type = &usb_hid_device_type } ,
+ .report_buffer = gamepad_report_buffer ,
+ .report_id = USB_HID_REPORT_ID_GAMEPAD ,
+ .report_length = USB_HID_REPORT_LENGTH_GAMEPAD ,
+ .usage_page = HID_USAGE_PAGE_DESKTOP ,
+ .usage = HID_USAGE_DESKTOP_GAMEPAD ,
+ },
+#endif
+
+#if USB_HID_DEVICE_DIGITIZER
+ {
+ .base = { .type = &usb_hid_device_type } ,
+ .report_buffer = digitizer_report_buffer ,
+ .report_id = USB_HID_REPORT_ID_DIGITIZER ,
+ .report_length = USB_HID_REPORT_LENGTH_DIGITIZER ,
+ .usage_page = 0x0D ,
+ .usage = 0x02 ,
+ },
+#endif
+};
+
+
+mp_obj_tuple_t common_hal_usb_hid_devices = {
+ .base = {
+ .type = &mp_type_tuple,
+ },
+ .len = USB_HID_NUM_DEVICES,
+ .items = {
+#if USB_HID_NUM_DEVICES >= 1
+ (mp_obj_t) &usb_hid_devices[0],
+#endif
+#if USB_HID_NUM_DEVICES >= 2
+ (mp_obj_t) &usb_hid_devices[1],
+#endif
+#if USB_HID_NUM_DEVICES >= 3
+ (mp_obj_t) &usb_hid_devices[2],
+#endif
+#if USB_HID_NUM_DEVICES >= 4
+ (mp_obj_t) &usb_hid_devices[3],
+#endif
+#if USB_HID_NUM_DEVICES >= 5
+ (mp_obj_t) &usb_hid_devices[4],
+#endif
+#if USB_HID_NUM_DEVICES >= 6
+ (mp_obj_t) &usb_hid_devices[5],
+#endif
+ }
+};
diff --git a/ports/nrf/interrupt_char.c b/ports/nrf/interrupt_char.c
deleted file mode 100644
index 8793b0d88..000000000
--- a/ports/nrf/interrupt_char.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2013-2016 Damien P. George
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "py/obj.h"
-#include "py/mpstate.h"
-
-#ifdef NRF52840_XXAA
-#include "usb.h"
-#endif
-
-#if MICROPY_KBD_EXCEPTION
-
-int mp_interrupt_char;
-
-void mp_hal_set_interrupt_char(int c) {
- if (c != -1) {
- mp_obj_exception_clear_traceback(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)));
- }
- mp_interrupt_char = c;
-
-#ifdef NRF52840_XXAA
- tud_cdc_set_wanted_char(c);
-#endif
-}
-
-void mp_keyboard_interrupt(void) {
- MP_STATE_VM(mp_pending_exception) = MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception));
- #if MICROPY_ENABLE_SCHEDULER
- if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE) {
- MP_STATE_VM(sched_state) = MP_SCHED_PENDING;
- }
- #endif
-}
-
-#endif
diff --git a/ports/nrf/mpconfigport.h b/ports/nrf/mpconfigport.h
index a04ddc180..0068f85b8 100644
--- a/ports/nrf/mpconfigport.h
+++ b/ports/nrf/mpconfigport.h
@@ -95,9 +95,9 @@
#define MICROPY_MODULE_BUILTIN_INIT (1)
#define MICROPY_PY_ALL_SPECIAL_METHODS (0)
#define MICROPY_PY_MICROPYTHON_MEM_INFO (1)
-#define MICROPY_PY_ARRAY_SLICE_ASSIGN (0)
+#define MICROPY_PY_ARRAY_SLICE_ASSIGN (1)
#define MICROPY_NONSTANDARD_TYPECODES (0)
-#define MICROPY_PY_BUILTINS_SLICE_ATTRS (0)
+#define MICROPY_PY_BUILTINS_SLICE_ATTRS (1)
#define MICROPY_PY_SYS_EXIT (1)
#define MICROPY_PY_SYS_MAXSIZE (1)
#define MICROPY_PY_SYS_STDFILES (1)
@@ -180,6 +180,7 @@ extern const struct _mp_obj_module_t struct_module;
extern const struct _mp_obj_module_t time_module;
extern const struct _mp_obj_module_t supervisor_module;
extern const struct _mp_obj_module_t gamepad_module;
+extern const struct _mp_obj_module_t usb_hid_module;
extern const struct _mp_obj_module_t bleio_module;
extern const struct _mp_obj_module_t mp_module_ubluepy;
@@ -196,6 +197,12 @@ extern const struct _mp_obj_module_t mp_module_ubluepy;
#define BLEIO_MODULE
#endif
+#ifdef NRF52840_XXAA
+#define USBHID_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_usb_hid), (mp_obj_t)&usb_hid_module },
+#else
+#define USBHID_MODULE
+#endif
+
#define MICROPY_PORT_BUILTIN_MODULES \
{ MP_OBJ_NEW_QSTR (MP_QSTR_board ), (mp_obj_t)&board_module }, \
{ MP_OBJ_NEW_QSTR (MP_QSTR_busio ), (mp_obj_t)&busio_module }, \
@@ -206,19 +213,20 @@ extern const struct _mp_obj_module_t mp_module_ubluepy;
{ MP_OBJ_NEW_QSTR (MP_QSTR_bitbangio ), (mp_obj_t)&bitbangio_module }, \
{ MP_OBJ_NEW_QSTR (MP_QSTR_os ), (mp_obj_t)&os_module }, \
{ MP_OBJ_NEW_QSTR (MP_QSTR_random ), (mp_obj_t)&random_module }, \
- { MP_OBJ_NEW_QSTR (MP_QSTR_storage ), (mp_obj_t)&storage_module },\
+ { MP_OBJ_NEW_QSTR (MP_QSTR_storage ), (mp_obj_t)&storage_module }, \
{ MP_OBJ_NEW_QSTR (MP_QSTR_struct ), (mp_obj_t)&struct_module }, \
{ MP_OBJ_NEW_QSTR (MP_QSTR_supervisor ), (mp_obj_t)&supervisor_module }, \
{ MP_OBJ_NEW_QSTR (MP_QSTR_gamepad ), (mp_obj_t)&gamepad_module }, \
{ MP_OBJ_NEW_QSTR (MP_QSTR_time ), (mp_obj_t)&time_module }, \
- BLEIO_MODULE \
+ USBHID_MODULE \
+ BLEIO_MODULE \
UBLUEPY_MODULE \
// extra built in names to add to the global namespace
#define MICROPY_PORT_BUILTINS \
- { MP_ROM_QSTR (MP_QSTR_help), MP_ROM_PTR(&mp_builtin_help_obj) }, \
- { MP_OBJ_NEW_QSTR (MP_QSTR_input), (mp_obj_t)&mp_builtin_input_obj }, \
- { MP_ROM_QSTR (MP_QSTR_open), MP_ROM_PTR(&mp_builtin_open_obj) }, \
+ { MP_ROM_QSTR (MP_QSTR_help ), MP_ROM_PTR(&mp_builtin_help_obj) }, \
+ { MP_OBJ_NEW_QSTR (MP_QSTR_input ), (mp_obj_t)&mp_builtin_input_obj }, \
+ { MP_ROM_QSTR (MP_QSTR_open ), MP_ROM_PTR(&mp_builtin_open_obj) }, \
#define MP_STATE_PORT MP_STATE_VM
diff --git a/ports/nrf/usb/tusb_config.h b/ports/nrf/usb/tusb_config.h
index 755e4cb6a..626b99eeb 100644
--- a/ports/nrf/usb/tusb_config.h
+++ b/ports/nrf/usb/tusb_config.h
@@ -45,13 +45,13 @@
//--------------------------------------------------------------------+
// COMMON CONFIGURATION
//--------------------------------------------------------------------+
-#define CFG_TUSB_MCU OPT_MCU_NRF5X
-#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE
+#define CFG_TUSB_MCU OPT_MCU_NRF5X
+#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE
-#define CFG_TUSB_DEBUG 0
+#define CFG_TUSB_DEBUG 0
/*------------- RTOS -------------*/
-#define CFG_TUSB_OS OPT_OS_NONE
+#define CFG_TUSB_OS OPT_OS_NONE
//#define CFG_TUD_TASK_QUEUE_SZ 16
//#define CFG_TUD_TASK_PRIO 0
//#define CFG_TUD_TASK_STACK_SZ 150
@@ -60,24 +60,26 @@
// DEVICE CONFIGURATION
//--------------------------------------------------------------------+
-/*------------- Core -------------*/
-#define CFG_TUD_DESC_AUTO 1
-#define CFG_TUD_DESC_VID 0x239A
-#define CFG_TUD_DESC_PID 0x802A
+#define CFG_TUD_ENDOINT0_SIZE 64
-#define CFG_TUD_ENDOINT0_SIZE 64
+/*------------- Descriptors -------------*/
+/* Enable auto generated descriptor, tinyusb will try its best to create
+ * descriptor ( device, configuration, hid ) that matches enabled CFG_* in this file
+ *
+ * Note: All CFG_TUD_DESC_* are relevant only if CFG_TUD_DESC_AUTO is enabled
+ */
+#define CFG_TUD_DESC_AUTO 0
//------------- CLASS -------------//
-#define CFG_TUD_CDC 1
-#define CFG_TUD_MSC 1
-#define CFG_TUD_HID_KEYBOARD 0
-#define CFG_TUD_HID_MOUSE 0
-#define CFG_TUD_HID_GENERIC 0
+#define CFG_TUD_CDC 1
+#define CFG_TUD_MSC 1
+#define CFG_TUD_HID 1
/*------------------------------------------------------------------*/
/* CLASS DRIVER
*------------------------------------------------------------------*/
+/*------------- CDC -------------*/
// FIFO size of CDC TX and RX
#define CFG_TUD_CDC_RX_BUFSIZE 1024
#define CFG_TUD_CDC_TX_BUFSIZE 1024
@@ -89,6 +91,8 @@
*/
#define CFG_TUD_CDC_FLUSH_ON_SOF 0
+
+/*------------- MSC -------------*/
// Number of supported Logical Unit Number (At least 1)
#define CFG_TUD_MSC_MAXLUN 1
diff --git a/ports/nrf/usb/usb.c b/ports/nrf/usb/usb.c
index 648ee708d..953b61e39 100644
--- a/ports/nrf/usb/usb.c
+++ b/ports/nrf/usb/usb.c
@@ -29,52 +29,13 @@
#include "tick.h"
#include "usb.h"
#include "lib/utils/interrupt_char.h"
+#include "lib/mp-readline/readline.h"
#ifdef SOFTDEVICE_PRESENT
#include "nrf_sdm.h"
#include "nrf_soc.h"
#endif
-//--------------------------------------------------------------------+
-// STRING DESCRIPTORS
-//--------------------------------------------------------------------+
-
-// array of pointer to string descriptors
-uint16_t const * const string_desc_arr [] =
-{
- // 0 index is supported language = English
- TUD_DESC_STRCONV(0x0409),
-
- // Manufacturer
- TUD_DESC_STRCONV('A','d','a','f','r','u','i','t',' ','I','n','d','u','s','t','r','i','e','s'),
-
- // Product
- TUD_DESC_STRCONV('C','i','r','c','u','i','t','P','Y',' ','n','R','F','5','2'),
-
- // Serials TODO use chip ID
- TUD_DESC_STRCONV('1', '2', '3', '4', '5'),
-
- // CDC Interface
- TUD_DESC_STRCONV('B','l','u','e','f','r','u','i','t',' ','S','e','r','i','a','l'),
-
- // MSC Interface
- TUD_DESC_STRCONV('B','l','u','e','f','r','u','i','t',' ','S','t','o','r','a','g','e'),
-
- // Custom Interface
- TUD_DESC_STRCONV('B','l','u','e','f','r','u','i','t',' ','C','u','s','t','o','m')
-};
-
-// tud_desc_set is required by tinyusb stack
-// since CFG_TUD_DESC_AUTO is enabled, we only need to set string_arr
-tud_desc_set_t tud_desc_set =
-{
- .device = NULL,
- .config = NULL,
- .string_arr = (uint8_t const **) string_desc_arr,
- .hid_report = NULL
-};
-
-
/* tinyusb function that handles power event (detected, ready, removed)
* We must call it within SD's SOC event handler, or set it as power event handler if SD is not enabled.
*/
@@ -122,6 +83,12 @@ void usb_init(void) {
}
tusb_init();
+
+#if MICROPY_KBD_EXCEPTION
+ // Set Ctrl+C as wanted char, tud_cdc_rx_wanted_cb() callback will be invoked when Ctrl+C is received
+ // This callback always got invoked regardless of mp_interrupt_char value since we only set it once here
+ tud_cdc_set_wanted_char(CHAR_CTRL_C);
+#endif
}
//--------------------------------------------------------------------+
@@ -151,6 +118,8 @@ void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char)
{
(void) itf; // not used
+ // Workaround for using lib/utils/interrupt_char.c
+ // Compare mp_interrupt_char with wanted_char and ignore if not matched
if (mp_interrupt_char == wanted_char) {
tud_cdc_read_flush(); // flush read fifo
mp_keyboard_interrupt();
diff --git a/ports/nrf/usb/usb_desc.c b/ports/nrf/usb/usb_desc.c
new file mode 100644
index 000000000..31f80b80d
--- /dev/null
+++ b/ports/nrf/usb/usb_desc.c
@@ -0,0 +1,391 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 hathach for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "usb_desc.h"
+#include "common-hal/usb_hid/Device.h"
+
+//--------------------------------------------------------------------+
+// MACRO TYPEDEF CONSTANT ENUM DECLARATION
+//--------------------------------------------------------------------+
+#define USB_VID 0x239A
+
+/* Note: different class combination e.g CDC and (CDC + MSC) should have different
+ * PID since Host OS will "remembered" device driver after the first plug */
+#define USB_PID 0x802A
+
+/*------------- Interface Numbering -------------*/
+enum {
+ ITF_NUM_CDC = 0 ,
+ ITF_NUM_CDC_DATA ,
+ ITF_NUM_MSC ,
+ ITF_NUM_HID_GEN ,
+ ITF_NUM_TOTAL
+};
+
+enum {
+ ITF_STR_LANGUAGE = 0 ,
+ ITF_STR_MANUFACTURER ,
+ ITF_STR_PRODUCT ,
+ ITF_STR_SERIAL ,
+ ITF_STR_CDC ,
+ ITF_STR_MSC ,
+ ITF_STR_HID
+};
+
+/*------------- Endpoint Numbering & Size -------------*/
+#define _EP_IN(x) (0x80 | (x))
+#define _EP_OUT(x) (x)
+
+// CDC
+#define EP_CDC_NOTIF _EP_IN ( ITF_NUM_CDC+1 )
+#define EP_CDC_NOTIF_SIZE 8
+
+#define EP_CDC_OUT _EP_OUT( ITF_NUM_CDC+2 )
+#define EP_CDC_IN _EP_IN ( ITF_NUM_CDC+2 )
+
+// Mass Storage
+#define EP_MSC_OUT _EP_OUT( ITF_NUM_MSC+1 )
+#define EP_MSC_IN _EP_IN ( ITF_NUM_MSC+1 )
+
+// HID composite = keyboard + mouse + gamepad + etc ...
+#define EP_HID_GEN _EP_IN ( ITF_NUM_HID_GEN+1 )
+#define EP_HID_GEN_SIZE 16
+
+//--------------------------------------------------------------------+
+// STRING DESCRIPTORS
+//--------------------------------------------------------------------+
+
+// array of pointer to string descriptors
+uint16_t const * const string_desc_arr [] =
+{
+ // 0 index is supported language = English
+ TUD_DESC_STRCONV(0x0409),
+
+ // 1 Manufacturer
+ TUD_DESC_STRCONV('A','d','a','f','r','u','i','t',' ','I','n','d','u','s','t','r','i','e','s'),
+
+ // 2 Product
+ TUD_DESC_STRCONV('C','i','r','c','u','i','t','P','y',' ','n','R','F','5','2'),
+
+ // 3 Serials TODO use chip ID
+ TUD_DESC_STRCONV('1', '2', '3', '4', '5'),
+
+ // 4 CDC Interface
+ TUD_DESC_STRCONV('C','i','r','c','u','i','t','P','y',' ','S','e','r','i','a','l'),
+
+ // 5 MSC Interface
+ TUD_DESC_STRCONV('C','i','r','c','u','i','t','P','y',' ','S','t','o','r','a','g','e'),
+
+ // 6 HID Interface
+ TUD_DESC_STRCONV('C','i','r','c','u','i','t','P','y',' ','H','I','D'),
+
+ // Custom Interface
+// TUD_DESC_STRCONV('C','i','r','c','u','i','t','P','y',' ','C','u','s','t','o','m')
+};
+
+
+//--------------------------------------------------------------------+
+// Device Descriptor
+//--------------------------------------------------------------------+
+tusb_desc_device_t const usb_desc_dev =
+{
+ .bLength = sizeof(tusb_desc_device_t),
+ .bDescriptorType = TUSB_DESC_DEVICE,
+ .bcdUSB = 0x0200,
+
+ #if CFG_TUD_CDC
+ // Use Interface Association Descriptor (IAD) for CDC
+ // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1)
+ .bDeviceClass = TUSB_CLASS_MISC,
+ .bDeviceSubClass = MISC_SUBCLASS_COMMON,
+ .bDeviceProtocol = MISC_PROTOCOL_IAD,
+ #else
+ .bDeviceClass = 0x00,
+ .bDeviceSubClass = 0x00,
+ .bDeviceProtocol = 0x00,
+ #endif
+
+ .bMaxPacketSize0 = CFG_TUD_ENDOINT0_SIZE,
+
+ .idVendor = USB_VID,
+ .idProduct = USB_PID,
+ .bcdDevice = 0x0100,
+
+ .iManufacturer = 0x01,
+ .iProduct = 0x02,
+ .iSerialNumber = 0x03,
+
+ .bNumConfigurations = 0x01 // TODO multiple configurations
+};
+
+//--------------------------------------------------------------------+
+// HID Report Descriptor
+//--------------------------------------------------------------------+
+uint8_t const usb_desc_hid_generic_report[] =
+{
+#if USB_HID_DEVICE_KEYBOARD
+ HID_REPORT_DESC_KEYBOARD( HID_REPORT_ID(USB_HID_REPORT_ID_KEYBOARD), ),
+#endif
+
+#if USB_HID_DEVICE_MOUSE
+ HID_REPORT_DESC_MOUSE( HID_REPORT_ID(USB_HID_REPORT_ID_MOUSE), ),
+#endif
+
+#if USB_HID_DEVICE_CONSUMER
+ HID_REPORT_DESC_CONSUMER( HID_REPORT_ID(USB_HID_REPORT_ID_CONSUMER), ),
+#endif
+
+#if USB_HID_DEVICE_SYS_CONTROL
+ HID_REPORT_DESC_SYSTEM_CONTROL( HID_REPORT_ID(USB_HID_REPORT_ID_SYS_CONTROL ), ),
+#endif
+
+#if USB_HID_DEVICE_GAMEPAD
+ HID_REPORT_DESC_GAMEPAD( HID_REPORT_ID(USB_HID_REPORT_ID_GAMEPAD ), )
+#endif
+
+};
+
+//--------------------------------------------------------------------+
+// Configuration Descriptor
+//--------------------------------------------------------------------+
+usb_desc_cfg_t const usb_desc_cfg =
+{
+ .config =
+ {
+ .bLength = sizeof(tusb_desc_configuration_t),
+ .bDescriptorType = TUSB_DESC_CONFIGURATION,
+ .wTotalLength = sizeof(usb_desc_cfg_t),
+ .bNumInterfaces = ITF_NUM_TOTAL,
+ .bConfigurationValue = 1,
+ .iConfiguration = 0x00,
+ .bmAttributes = TUSB_DESC_CONFIG_ATT_BUS_POWER,
+ .bMaxPower = TUSB_DESC_CONFIG_POWER_MA(100)
+ },
+
+ // IAD points to CDC Interfaces
+ .cdc =
+ {
+ .iad =
+ {
+ .bLength = sizeof(tusb_desc_interface_assoc_t),
+ .bDescriptorType = TUSB_DESC_INTERFACE_ASSOCIATION,
+
+ .bFirstInterface = ITF_NUM_CDC,
+ .bInterfaceCount = 2,
+
+ .bFunctionClass = TUSB_CLASS_CDC,
+ .bFunctionSubClass = CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL,
+ .bFunctionProtocol = CDC_COMM_PROTOCOL_ATCOMMAND,
+ .iFunction = 0
+ },
+
+ //------------- CDC Communication Interface -------------//
+ .comm_itf =
+ {
+ .bLength = sizeof(tusb_desc_interface_t),
+ .bDescriptorType = TUSB_DESC_INTERFACE,
+ .bInterfaceNumber = ITF_NUM_CDC,
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 1,
+ .bInterfaceClass = TUSB_CLASS_CDC,
+ .bInterfaceSubClass = CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL,
+ .bInterfaceProtocol = CDC_COMM_PROTOCOL_ATCOMMAND,
+ .iInterface = ITF_STR_CDC
+ },
+
+ .header =
+ {
+ .bLength = sizeof(cdc_desc_func_header_t),
+ .bDescriptorType = TUSB_DESC_CLASS_SPECIFIC,
+ .bDescriptorSubType = CDC_FUNC_DESC_HEADER,
+ .bcdCDC = 0x0120
+ },
+
+ .call =
+ {
+ .bLength = sizeof(cdc_desc_func_call_management_t),
+ .bDescriptorType = TUSB_DESC_CLASS_SPECIFIC,
+ .bDescriptorSubType = CDC_FUNC_DESC_CALL_MANAGEMENT,
+ .bmCapabilities = { 0 },
+ .bDataInterface = ITF_NUM_CDC+1,
+ },
+
+ .acm =
+ {
+ .bLength = sizeof(cdc_desc_func_acm_t),
+ .bDescriptorType = TUSB_DESC_CLASS_SPECIFIC,
+ .bDescriptorSubType = CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT,
+ .bmCapabilities = { // 0x02
+ .support_line_request = 1,
+ }
+ },
+
+ .union_func =
+ {
+ .bLength = sizeof(cdc_desc_func_union_t), // plus number of
+ .bDescriptorType = TUSB_DESC_CLASS_SPECIFIC,
+ .bDescriptorSubType = CDC_FUNC_DESC_UNION,
+ .bControlInterface = ITF_NUM_CDC,
+ .bSubordinateInterface = ITF_NUM_CDC+1,
+ },
+
+ .ep_notif =
+ {
+ .bLength = sizeof(tusb_desc_endpoint_t),
+ .bDescriptorType = TUSB_DESC_ENDPOINT,
+ .bEndpointAddress = EP_CDC_NOTIF,
+ .bmAttributes = { .xfer = TUSB_XFER_INTERRUPT },
+ .wMaxPacketSize = { .size = EP_CDC_NOTIF_SIZE },
+ .bInterval = 0x10
+ },
+
+ //------------- CDC Data Interface -------------//
+ .data_itf =
+ {
+ .bLength = sizeof(tusb_desc_interface_t),
+ .bDescriptorType = TUSB_DESC_INTERFACE,
+ .bInterfaceNumber = ITF_NUM_CDC+1,
+ .bAlternateSetting = 0x00,
+ .bNumEndpoints = 2,
+ .bInterfaceClass = TUSB_CLASS_CDC_DATA,
+ .bInterfaceSubClass = 0,
+ .bInterfaceProtocol = 0,
+ .iInterface = 0x00
+ },
+
+ .ep_out =
+ {
+ .bLength = sizeof(tusb_desc_endpoint_t),
+ .bDescriptorType = TUSB_DESC_ENDPOINT,
+ .bEndpointAddress = EP_CDC_OUT,
+ .bmAttributes = { .xfer = TUSB_XFER_BULK },
+ .wMaxPacketSize = { .size = CFG_TUD_CDC_EPSIZE },
+ .bInterval = 0
+ },
+
+ .ep_in =
+ {
+ .bLength = sizeof(tusb_desc_endpoint_t),
+ .bDescriptorType = TUSB_DESC_ENDPOINT,
+ .bEndpointAddress = EP_CDC_IN,
+ .bmAttributes = { .xfer = TUSB_XFER_BULK },
+ .wMaxPacketSize = { .size = CFG_TUD_CDC_EPSIZE },
+ .bInterval = 0
+ },
+ },
+
+ //------------- Mass Storage-------------//
+ .msc =
+ {
+ .itf =
+ {
+ .bLength = sizeof(tusb_desc_interface_t),
+ .bDescriptorType = TUSB_DESC_INTERFACE,
+ .bInterfaceNumber = ITF_NUM_MSC,
+ .bAlternateSetting = 0x00,
+ .bNumEndpoints = 2,
+ .bInterfaceClass = TUSB_CLASS_MSC,
+ .bInterfaceSubClass = MSC_SUBCLASS_SCSI,
+ .bInterfaceProtocol = MSC_PROTOCOL_BOT,
+ .iInterface = ITF_STR_MSC
+ },
+
+ .ep_out =
+ {
+ .bLength = sizeof(tusb_desc_endpoint_t),
+ .bDescriptorType = TUSB_DESC_ENDPOINT,
+ .bEndpointAddress = EP_MSC_OUT,
+ .bmAttributes = { .xfer = TUSB_XFER_BULK },
+ .wMaxPacketSize = { .size = CFG_TUD_MSC_EPSIZE},
+ .bInterval = 1
+ },
+
+ .ep_in =
+ {
+ .bLength = sizeof(tusb_desc_endpoint_t),
+ .bDescriptorType = TUSB_DESC_ENDPOINT,
+ .bEndpointAddress = EP_MSC_IN,
+ .bmAttributes = { .xfer = TUSB_XFER_BULK },
+ .wMaxPacketSize = { .size = CFG_TUD_MSC_EPSIZE},
+ .bInterval = 1
+ }
+ },
+
+ //------------- HID Generic Multiple report -------------//
+ .hid_generic =
+ {
+ .itf =
+ {
+ .bLength = sizeof(tusb_desc_interface_t),
+ .bDescriptorType = TUSB_DESC_INTERFACE,
+ .bInterfaceNumber = ITF_NUM_HID_GEN,
+ .bAlternateSetting = 0x00,
+ .bNumEndpoints = 1,
+ .bInterfaceClass = TUSB_CLASS_HID,
+ .bInterfaceSubClass = 0,
+ .bInterfaceProtocol = 0,
+ .iInterface = ITF_STR_HID
+ },
+
+ .hid_desc =
+ {
+ .bLength = sizeof(tusb_hid_descriptor_hid_t),
+ .bDescriptorType = HID_DESC_TYPE_HID,
+ .bcdHID = 0x0111,
+ .bCountryCode = HID_Local_NotSupported,
+ .bNumDescriptors = 1,
+ .bReportType = HID_DESC_TYPE_REPORT,
+ .wReportLength = sizeof(usb_desc_hid_generic_report)
+ },
+
+ .ep_in =
+ {
+ .bLength = sizeof(tusb_desc_endpoint_t),
+ .bDescriptorType = TUSB_DESC_ENDPOINT,
+ .bEndpointAddress = EP_HID_GEN,
+ .bmAttributes = { .xfer = TUSB_XFER_INTERRUPT },
+ .wMaxPacketSize = { .size = EP_HID_GEN_SIZE },
+ .bInterval = 0x0A
+ }
+ }
+};
+
+
+// tud_desc_set is required by tinyusb stack
+tud_desc_set_t tud_desc_set =
+{
+ .device = &usb_desc_dev,
+ .config = &usb_desc_cfg,
+ .string_arr = (uint8_t const **) string_desc_arr,
+ .string_count = sizeof(string_desc_arr)/sizeof(string_desc_arr[0]),
+
+ .hid_report =
+ {
+ .generic = usb_desc_hid_generic_report,
+ .boot_keyboard = NULL,
+ .boot_mouse = NULL
+ }
+};
diff --git a/ports/nrf/usb/usb_desc.h b/ports/nrf/usb/usb_desc.h
new file mode 100644
index 000000000..19f3f6d5b
--- /dev/null
+++ b/ports/nrf/usb/usb_desc.h
@@ -0,0 +1,87 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 hathach for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef USB_DESC_H_
+#define USB_DESC_H_
+
+#include "tusb.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/*------------- Configuration Descriptor -------------*/
+typedef struct ATTR_PACKED
+{
+ tusb_desc_configuration_t config;
+
+ //------------- CDC -------------//
+ struct ATTR_PACKED
+ {
+ tusb_desc_interface_assoc_t iad;
+
+ //CDC Control Interface
+ tusb_desc_interface_t comm_itf;
+ cdc_desc_func_header_t header;
+ cdc_desc_func_call_management_t call;
+ cdc_desc_func_acm_t acm;
+ cdc_desc_func_union_t union_func;
+ tusb_desc_endpoint_t ep_notif;
+
+ //CDC Data Interface
+ tusb_desc_interface_t data_itf;
+ tusb_desc_endpoint_t ep_out;
+ tusb_desc_endpoint_t ep_in;
+ }cdc;
+
+ //------------- Mass Storage -------------//
+ struct ATTR_PACKED
+ {
+ tusb_desc_interface_t itf;
+ tusb_desc_endpoint_t ep_out;
+ tusb_desc_endpoint_t ep_in;
+ } msc;
+
+ //------------- HID -------------//
+ struct ATTR_PACKED
+ {
+ tusb_desc_interface_t itf;
+ tusb_hid_descriptor_hid_t hid_desc;
+ tusb_desc_endpoint_t ep_in;
+ } hid_generic;
+
+} usb_desc_cfg_t;
+
+
+// Descriptors set used by tinyusb stack
+extern tud_desc_set_t tud_desc_set;
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* USB_DESC_H_ */
diff --git a/ports/nrf/usb/usb_msc_flash.c b/ports/nrf/usb/usb_msc_flash.c
index f77a9e5c5..2d0e9bec7 100644
--- a/ports/nrf/usb/usb_msc_flash.c
+++ b/ports/nrf/usb/usb_msc_flash.c
@@ -53,90 +53,60 @@
#define FL_PAGE_SZ 4096
-static scsi_sense_fixed_data_t mscd_sense_data =
-{
- .response_code = 0x70,
- .sense_key = 0, // no errors
- .additional_sense_len = sizeof(scsi_sense_fixed_data_t) - 8
-};
-
-static scsi_mode_parameters_t const msc_dev_mode_para =
-{
- .mode_data_length = 3,
- .medium_type = 0,
- .device_specific_para = 0,
- .block_descriptor_length = 0
-};
-
-//--------------------------------------------------------------------+
-// tinyusb callbacks
-//--------------------------------------------------------------------+
-int32_t tud_msc_scsi_cb (uint8_t rhport, uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize) {
- // read10 & write10 has their own callback and MUST not be handled here
-
- void const* ptr = NULL;
- uint16_t len = 0;
-
- // most scsi handled is input
- bool in_xfer = true;
-
- switch ( scsi_cmd[0] )
- {
- case SCSI_CMD_REQUEST_SENSE:
- ptr = &mscd_sense_data;
- len = sizeof(scsi_sense_fixed_data_t);
- break;
-
- case SCSI_CMD_MODE_SENSE_6:
- ptr = &msc_dev_mode_para;
- len = sizeof(msc_dev_mode_para);
- break;
-
+// Callback invoked when received an SCSI command not in built-in list below
+// - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, MODE_SENSE6, REQUEST_SENSE
+// - READ10 and WRITE10 has their own callbacks
+int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize) {
+ void const* response = NULL;
+ uint16_t resplen = 0;
+
+ switch ( scsi_cmd[0] ) {
case SCSI_CMD_TEST_UNIT_READY:
- ptr = NULL;
- len = 0;
+ // Command that host uses to check our readiness before sending other commands
+ resplen = 0;
break;
case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
- ptr = NULL;
- len = 0;
+ // Host is about to read/write etc ... better not to disconnect disk
+ resplen = 0;
+ break;
+
+ case SCSI_CMD_START_STOP_UNIT:
+ // Host try to eject/safe remove/poweroff us. We could safely disconnect with disk storage, or go into lower power
+ /* scsi_start_stop_unit_t const * start_stop = (scsi_start_stop_unit_t const *) scsi_cmd;
+ // Start bit = 0 : low power mode, if load_eject = 1 : unmount disk storage as well
+ // Start bit = 1 : Ready mode, if load_eject = 1 : mount disk storage
+ start_stop->start;
+ start_stop->load_eject;
+ */
+ resplen = 0;
break;
default:
- // negative is error -> Data stage is STALL, status = failed
- return -1;
+ // Set Sense = Invalid Command Operation
+ tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00);
+
+ // negative means error -> tinyusb could stall and/or response with failed status
+ resplen = -1;
+ break;
}
// return len must not larger than bufsize
- TU_ASSERT(bufsize >= len);
-
- if ( ptr && len )
- {
- if ( in_xfer )
- {
- memcpy(buffer, ptr, len);
- } else
- {
- // SCSI output
- }
+ if ( resplen > bufsize ) {
+ resplen = bufsize;
}
- //------------- clear sense data if it is not request sense command -------------//
- if ( SCSI_CMD_REQUEST_SENSE != scsi_cmd[0] )
- {
- mscd_sense_data.sense_key = SCSI_SENSEKEY_NONE;
- mscd_sense_data.additional_sense_code = 0;
- mscd_sense_data.additional_sense_qualifier = 0;
+ // copy response to stack's buffer if any
+ if ( response && resplen ) {
+ memcpy(buffer, response, resplen);
}
- return len;
+ return resplen;
}
-/*------------------------------------------------------------------*/
-/* Tinyusb Flash READ10 & WRITE10
- *------------------------------------------------------------------*/
-int32_t tud_msc_read10_cb (uint8_t rhport, uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize) {
- (void) rhport;
+// Callback invoked when received READ10 command.
+// Copy disk's data to buffer (up to bufsize) and return number of copied bytes.
+int32_t tud_msc_read10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize) {
(void) lun;
(void) offset;
@@ -147,8 +117,9 @@ int32_t tud_msc_read10_cb (uint8_t rhport, uint8_t lun, uint32_t lba, uint32_t o
return block_count * MSC_FLASH_BLOCK_SIZE;
}
-int32_t tud_msc_write10_cb (uint8_t rhport, uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize) {
- (void) rhport;
+// Callback invoked when received WRITE10 command.
+// Process data in buffer to disk's storage and return number of written bytes
+int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize) {
(void) lun;
(void) offset;
@@ -167,8 +138,9 @@ int32_t tud_msc_write10_cb (uint8_t rhport, uint8_t lun, uint32_t lba, uint32_t
return block_count * MSC_FLASH_BLOCK_SIZE;
}
-void tud_msc_write10_complete_cb (uint8_t rhport, uint8_t lun) {
- (void) rhport;
+// Callback invoked when WRITE10 command is completed (status received and accepted by host).
+// used to flush any pending cache.
+void tud_msc_write10_complete_cb (uint8_t lun) {
(void) lun;
// flush pending cache when write10 is complete