summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorhathach <[email protected]>2019-04-19 00:49:32 +0700
committerGitHub <[email protected]>2019-04-19 00:49:32 +0700
commitee3504fdb06ad83a0d4896b56a4181c114fda703 (patch)
treeb88a4144ee3fc2799268e6f51869756eea18ba23 /examples
parent074898099da6bfd8784019d97c64712f73b779b0 (diff)
parent6796026476e14fc82402cdbd2dc4418f51240ae5 (diff)
Merge pull request #56 from hathach/develop
refactor hid device, remove auto descriptor, update example
Diffstat (limited to 'examples')
-rw-r--r--examples/device/cdc_msc_hid/Makefile6
-rw-r--r--examples/device/cdc_msc_hid/src/main.c87
-rw-r--r--examples/device/cdc_msc_hid/src/msc_app.c104
-rw-r--r--examples/device/cdc_msc_hid/src/msc_disk.c (renamed from examples/device/cdc_msc_hid/src/msc_disk_ram.c)63
-rw-r--r--examples/device/cdc_msc_hid/src/tusb_config.h47
-rw-r--r--examples/device/cdc_msc_hid/src/tusb_descriptors.c86
-rw-r--r--examples/device/cdc_msc_hid/src/usb_descriptors.c171
-rw-r--r--examples/device/cdc_msc_hid_freertos/ses/nrf5x/nrf5x.emProject2
-rw-r--r--examples/device/cdc_msc_hid_freertos/src/main.c148
-rw-r--r--examples/device/cdc_msc_hid_freertos/src/msc_app.c104
-rw-r--r--examples/device/cdc_msc_hid_freertos/src/msc_disk.c (renamed from examples/device/cdc_msc_hid_freertos/src/msc_disk_ram.c)71
-rw-r--r--examples/device/cdc_msc_hid_freertos/src/tusb_config.h49
-rw-r--r--examples/device/cdc_msc_hid_freertos/src/tusb_descriptors.c86
-rw-r--r--examples/device/cdc_msc_hid_freertos/src/usb_descriptors.c171
-rw-r--r--examples/host/cdc_msc_hid/src/main.c12
15 files changed, 653 insertions, 554 deletions
diff --git a/examples/device/cdc_msc_hid/Makefile b/examples/device/cdc_msc_hid/Makefile
index a2156e1b1..fc89b0fa7 100644
--- a/examples/device/cdc_msc_hid/Makefile
+++ b/examples/device/cdc_msc_hid/Makefile
@@ -85,9 +85,8 @@ LIBS = -lgcc -lc -lm -lnosys
EXAMPLE_SOURCE += \
src/main.c \
- src/msc_app.c \
- src/msc_disk_ram.c \
- src/tusb_descriptors.c
+ src/msc_disk.c \
+ src/usb_descriptors.c
SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE))
@@ -95,7 +94,6 @@ LIB_SOURCE += \
hw/bsp/$(BOARD)/board_$(BOARD).c \
src/common/tusb_fifo.c \
src/device/usbd.c \
- src/device/usbd_auto_desc.c \
src/device/usbd_control.c \
src/class/msc/msc_device.c \
src/class/cdc/cdc_device.c \
diff --git a/examples/device/cdc_msc_hid/src/main.c b/examples/device/cdc_msc_hid/src/main.c
index 78e07910d..c5e7a3068 100644
--- a/examples/device/cdc_msc_hid/src/main.c
+++ b/examples/device/cdc_msc_hid/src/main.c
@@ -40,12 +40,18 @@
* - 1000 ms : device mounted
* - 2500 ms : device is suspended
*/
-static uint32_t blink_interval_ms = 250;
+enum {
+ BLINK_NOT_MOUNTED = 250,
+ BLINK_MOUNTED = 1000,
+ BLINK_SUSPENDED = 2500,
+};
+
+static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED;
void led_blinking_task(void);
-extern void virtual_com_task(void);
-extern void usb_hid_task(void);
+extern void cdc_task(void);
+extern void hid_task(void);
/*------------- MAIN -------------*/
int main(void)
@@ -62,11 +68,11 @@ int main(void)
led_blinking_task();
#if CFG_TUD_CDC
- virtual_com_task();
+ cdc_task();
#endif
#if CFG_TUD_HID
- usb_hid_task();
+ hid_task();
#endif
}
@@ -77,7 +83,7 @@ int main(void)
// USB CDC
//--------------------------------------------------------------------+
#if CFG_TUD_CDC
-void virtual_com_task(void)
+void cdc_task(void)
{
if ( tud_cdc_connected() )
{
@@ -126,7 +132,15 @@ void tud_cdc_rx_cb(uint8_t itf)
// USB HID
//--------------------------------------------------------------------+
#if CFG_TUD_HID
-void usb_hid_task(void)
+
+// Must match with ID declared by HID Report Descriptor, better to be in header file
+enum
+{
+ REPORT_ID_KEYBOARD = 1,
+ REPORT_ID_MOUSE
+};
+
+void hid_task(void)
{
// Poll every 10ms
const uint32_t interval_ms = 10;
@@ -137,6 +151,7 @@ void usb_hid_task(void)
uint32_t const btn = board_button_read();
+ // Remote wakeup
if ( tud_suspended() && btn )
{
// Wake up host if we are in suspend mode
@@ -144,43 +159,43 @@ void usb_hid_task(void)
tud_remote_wakeup();
}
-#if 0
+ /*------------- Mouse -------------*/
+ if ( tud_hid_ready() )
+ {
+ if ( btn )
+ {
+ int8_t const delta = 5;
+ tud_hid_mouse_move(REPORT_ID_MOUSE, delta, delta); // right + down
+
+ // delay a bit before attempt to send keyboard report
+ board_delay(2);
+ }
+ }
+
/*------------- Keyboard -------------*/
- if ( tud_hid_keyboard_ready() )
+ if ( tud_hid_ready() )
{
+ // use to avoid send multiple consecutive zero report for keyboard
+ static bool has_key = false;
+
if ( btn )
{
uint8_t keycode[6] = { 0 };
+ keycode[0] = HID_KEY_A;
- for(uint8_t i=0; i < 6; i++)
- {
- if ( btn & (1 << i) ) keycode[i] = HID_KEY_A + i;
- }
+ tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, keycode);
- tud_hid_keyboard_keycode(0, keycode);
+ has_key = true;
}else
{
- // Null means all zeroes keycodes
- tud_hid_keyboard_keycode(0, NULL);
+ // send empty key report if previously has key pressed
+ if (has_key) tud_hid_keyboard_key_release(REPORT_ID_KEYBOARD);
+ has_key = false;
}
}
-#endif
-
-#if 0
- /*------------- Mouse -------------*/
- if ( tud_hid_mouse_ready() )
- {
- enum { DELTA = 5 };
-
- if ( btn & 0x01 ) tud_hid_mouse_move(-DELTA, 0); // left
- if ( btn & 0x02 ) tud_hid_mouse_move( DELTA, 0); // right
- if ( btn & 0x04 ) tud_hid_mouse_move( 0 , -DELTA); // up
- if ( btn & 0x08 ) tud_hid_mouse_move( 0 , DELTA); // down
- }
-#endif
}
-uint16_t tud_hid_generic_get_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen)
+uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen)
{
// TODO not Implemented
(void) report_id;
@@ -191,7 +206,7 @@ uint16_t tud_hid_generic_get_report_cb(uint8_t report_id, hid_report_type_t repo
return 0;
}
-void tud_hid_generic_set_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize)
+void tud_hid_set_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize)
{
// TODO not Implemented
(void) report_id;
@@ -209,13 +224,13 @@ void tud_hid_generic_set_report_cb(uint8_t report_id, hid_report_type_t report_t
// Invoked when device is mounted
void tud_mount_cb(void)
{
- blink_interval_ms = 1000;
+ blink_interval_ms = BLINK_MOUNTED;
}
// Invoked when device is unmounted
void tud_umount_cb(void)
{
- blink_interval_ms = 250;
+ blink_interval_ms = BLINK_NOT_MOUNTED;
}
// Invoked when usb bus is suspended
@@ -224,13 +239,13 @@ void tud_umount_cb(void)
void tud_suspend_cb(bool remote_wakeup_en)
{
(void) remote_wakeup_en;
- blink_interval_ms = 2500;
+ blink_interval_ms = BLINK_SUSPENDED;
}
// Invoked when usb bus is resumed
void tud_resume_cb(void)
{
- blink_interval_ms = 1000;
+ blink_interval_ms = BLINK_MOUNTED;
}
//--------------------------------------------------------------------+
diff --git a/examples/device/cdc_msc_hid/src/msc_app.c b/examples/device/cdc_msc_hid/src/msc_app.c
deleted file mode 100644
index d50af7810..000000000
--- a/examples/device/cdc_msc_hid/src/msc_app.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2018, hathach (tinyusb.org)
- *
- * 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.
- *
- * This file is part of the TinyUSB stack.
- */
-
-#include "bsp/board.h"
-#include "tusb.h"
-
-#if CFG_TUD_MSC
-
-//--------------------------------------------------------------------+
-// MACRO CONSTANT TYPEDEF
-//--------------------------------------------------------------------+
-
-//--------------------------------------------------------------------+
-// tinyusb callbacks
-//--------------------------------------------------------------------+
-
-// 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)
-{
- // read10 & write10 has their own callback and MUST not be handled here
-
- void const* response = NULL;
- uint16_t resplen = 0;
-
- // most scsi handled is input
- bool in_xfer = true;
-
- switch (scsi_cmd[0])
- {
- case SCSI_CMD_TEST_UNIT_READY:
- // Command that host uses to check our readiness before sending other commands
- resplen = 0;
- break;
-
- case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
- // 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:
- // 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 resplen must not larger than bufsize
- if ( resplen > bufsize ) resplen = bufsize;
-
- if ( response && (resplen > 0) )
- {
- if(in_xfer)
- {
- memcpy(buffer, response, resplen);
- }else
- {
- // SCSI output
- }
- }
-
- return resplen;
-}
-
-
-#endif
diff --git a/examples/device/cdc_msc_hid/src/msc_disk_ram.c b/examples/device/cdc_msc_hid/src/msc_disk.c
index 72b703cac..8bcd056e3 100644
--- a/examples/device/cdc_msc_hid/src/msc_disk_ram.c
+++ b/examples/device/cdc_msc_hid/src/msc_disk.c
@@ -126,4 +126,67 @@ void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_siz
*block_size = DISK_BLOCK_SIZE;
}
+// 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)
+{
+ // read10 & write10 has their own callback and MUST not be handled here
+
+ void const* response = NULL;
+ uint16_t resplen = 0;
+
+ // most scsi handled is input
+ bool in_xfer = true;
+
+ switch (scsi_cmd[0])
+ {
+ case SCSI_CMD_TEST_UNIT_READY:
+ // Command that host uses to check our readiness before sending other commands
+ resplen = 0;
+ break;
+
+ case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
+ // 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:
+ // 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 resplen must not larger than bufsize
+ if ( resplen > bufsize ) resplen = bufsize;
+
+ if ( response && (resplen > 0) )
+ {
+ if(in_xfer)
+ {
+ memcpy(buffer, response, resplen);
+ }else
+ {
+ // SCSI output
+ }
+ }
+
+ return resplen;
+}
+
#endif
diff --git a/examples/device/cdc_msc_hid/src/tusb_config.h b/examples/device/cdc_msc_hid/src/tusb_config.h
index 98a214d52..2614bcb6f 100644
--- a/examples/device/cdc_msc_hid/src/tusb_config.h
+++ b/examples/device/cdc_msc_hid/src/tusb_config.h
@@ -46,8 +46,8 @@
#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE
#endif
-#define CFG_TUSB_DEBUG 2
#define CFG_TUSB_OS OPT_OS_NONE
+#define CFG_TUSB_DEBUG 2
/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
* Tinyusb use follows macros to declare transferring memory so that they can be put
@@ -67,49 +67,17 @@
//--------------------------------------------------------------------
// DEVICE CONFIGURATION
//--------------------------------------------------------------------
-#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 1
-
-/* If USB VID/PID is not defined, tinyusb will use default value
- * 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 CFG_TUD_DESC_VID 0xCAFE
-// #define CFG_TUD_DESC_PID 0x0001
-// LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number
-// Therefore we need to force endpoint number to correct type on lpc17xx
-#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX
-#define CFG_TUD_DESC_CDC_EPNUM_NOTIF 1
-#define CFG_TUD_DESC_CDC_EPNUM 2
-#define CFG_TUD_DESC_MSC_EPNUM 5
-#define CFG_TUD_DESC_HID_KEYBOARD_EPNUM 4
-#define CFG_TUD_DESC_HID_MOUSE_EPNUM 7
-#endif
+#define CFG_TUD_ENDOINT0_SIZE 64
//------------- CLASS -------------//
#define CFG_TUD_CDC 1
#define CFG_TUD_MSC 1
+#define CFG_TUD_HID 1
+
#define CFG_TUD_MIDI 0
#define CFG_TUD_CUSTOM_CLASS 0
-#define CFG_TUD_HID 0
-#define CFG_TUD_HID_KEYBOARD 0
-#define CFG_TUD_HID_MOUSE 0
-
-/* Use Boot Protocol for Keyboard, Mouse. Enable this will create separated HID interface
- * require more IN endpoints. If disabled, they they are all packed into a single
- * multiple report interface called "Generic". */
-#define CFG_TUD_HID_KEYBOARD_BOOT 1
-#define CFG_TUD_HID_MOUSE_BOOT 1
-
//--------------------------------------------------------------------
// CDC
//--------------------------------------------------------------------
@@ -121,6 +89,7 @@
//--------------------------------------------------------------------
// MSC
//--------------------------------------------------------------------
+
// Number of supported Logical Unit Number (At least 1)
#define CFG_TUD_MSC_MAXLUN 1
@@ -140,14 +109,12 @@
// HID
//--------------------------------------------------------------------
-/* Use the HID_ASCII_TO_KEYCODE lookup if CFG_TUD_HID_KEYBOARD is enabled.
- * This will occupies 256 bytes of ROM. It will also enable the use of 2 extra APIs
+/* Use the HID_ASCII_TO_KEYCODE lookup
+ * This will occupies 256 bytes of ROM. It will also enable the use of extra APIs
* - tud_hid_keyboard_send_char()
- * - tud_hid_keyboard_send_string()
*/
#define CFG_TUD_HID_ASCII_TO_KEYCODE_LOOKUP 1
-
#ifdef __cplusplus
}
#endif
diff --git a/examples/device/cdc_msc_hid/src/tusb_descriptors.c b/examples/device/cdc_msc_hid/src/tusb_descriptors.c
deleted file mode 100644
index 866005e3f..000000000
--- a/examples/device/cdc_msc_hid/src/tusb_descriptors.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2018, hathach (tinyusb.org)
- *
- * 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.
- *
- * This file is part of the TinyUSB stack.
- */
-
-#include "tusb.h"
-
-//--------------------------------------------------------------------+
-// STRING DESCRIPTORS
-//--------------------------------------------------------------------+
-
-// array of pointer to string descriptors
-uint16_t const * const string_desc_arr [] =
-{
- // 0: is supported language = English
- TUD_DESC_STRCONV(0x0409),
-
- // 1: Manufacturer
- TUD_DESC_STRCONV('t', 'i', 'n', 'y', 'u', 's', 'b', '.', 'o', 'r', 'g'),
-
- // 2: Product
- TUD_DESC_STRCONV('t', 'i', 'n', 'y', 'u', 's', 'b', ' ', 'd', 'e', 'v', 'i', 'c', 'e'),
-
- // 3: Serials TODO use chip ID
- TUD_DESC_STRCONV('1', '2', '3', '4', '5', '6'),
-
-#if CFG_TUD_CDC
- // 4: CDC Interface
- TUD_DESC_STRCONV('t','u','s','b',' ','c','d','c'),
-#endif
-
-#if CFG_TUD_MSC
- // 5: MSC Interface
- TUD_DESC_STRCONV('t','u','s','b',' ','m','s','c'),
-#endif
-
-#if CFG_TUD_HID_KEYBOARD
- // 6: Keyboard
- TUD_DESC_STRCONV('t','u','s','b',' ','k','e','y','b','o','a','r','d'),
-#endif
-
-#if CFG_TUD_HID_MOUSE
- // 7: Mouse
- TUD_DESC_STRCONV('t','u','s','b',' ','m', 'o','u','s','e'),
-#endif
-
-};
-
-// 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,
- .string_count = sizeof(string_desc_arr)/sizeof(string_desc_arr[0]),
-
- .hid_report =
- {
- .generic = NULL,
- .boot_keyboard = NULL,
- .boot_mouse = NULL
- }
-};
diff --git a/examples/device/cdc_msc_hid/src/usb_descriptors.c b/examples/device/cdc_msc_hid/src/usb_descriptors.c
new file mode 100644
index 000000000..28a4b28d1
--- /dev/null
+++ b/examples/device/cdc_msc_hid/src/usb_descriptors.c
@@ -0,0 +1,171 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018, hathach (tinyusb.org)
+ *
+ * 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.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#include "tusb.h"
+
+/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug.
+ * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC.
+ *
+ * Auto ProductID layout's Bitmap:
+ * [MSB] HID | MSC | CDC [LSB]
+ */
+#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) )
+#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) )
+
+//------------- Device Descriptors -------------//
+tusb_desc_device_t const desc_device =
+{
+ .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 = 0xCafe,
+ .idProduct = USB_PID,
+ .bcdDevice = 0x0100,
+
+ .iManufacturer = 0x01,
+ .iProduct = 0x02,
+ .iSerialNumber = 0x03,
+
+ .bNumConfigurations = 0x01
+};
+
+//------------- HID Report Descriptor -------------//
+enum
+{
+ REPORT_ID_KEYBOARD = 1,
+ REPORT_ID_MOUSE
+};
+
+uint8_t const desc_hid_report[] =
+{
+ HID_REPORT_DESC_KEYBOARD( HID_REPORT_ID(REPORT_ID_KEYBOARD), ),
+ HID_REPORT_DESC_MOUSE ( HID_REPORT_ID(REPORT_ID_MOUSE), )
+};
+
+//------------- Configuration Descriptor -------------//
+enum
+{
+ #if CFG_TUD_CDC
+ ITF_NUM_CDC = 0,
+ ITF_NUM_CDC_DATA,
+ #endif
+
+ #if CFG_TUD_MSC
+ ITF_NUM_MSC,
+ #endif
+
+ #if CFG_TUD_HID
+ ITF_NUM_HID,
+ #endif
+
+ ITF_NUM_TOTAL
+};
+
+enum
+{
+ CONFIG_DESC_LEN = sizeof(tusb_desc_configuration_t) + CFG_TUD_CDC*TUD_CDC_DESC_LEN + CFG_TUD_MSC*TUD_MSC_DESC_LEN + CFG_TUD_HID*TUD_HID_DESC_LEN
+};
+
+#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX
+ // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number
+ // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ...
+ // Note: since CDC EP ( 1 & 2), HID (4) are spot-on, thus we only need to force
+ // endpoint number for MSC to 5
+ #define EPNUM_MSC 0x05
+#else
+ #define EPNUM_MSC 0x03
+#endif
+
+uint8_t const desc_configuration[] =
+{
+ // Config: self-powered with remote wakeup support, max power up to 100 mA
+ TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_DESC_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
+
+#if CFG_TUD_CDC
+ TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, 0x81, 8, 0x02, 0x82, 64),
+#endif
+
+#if CFG_TUD_MSC
+ TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC, 0x80 | EPNUM_MSC, 64), // highspeed 512
+#endif
+
+#if CFG_TUD_HID
+ TUD_HID_DESCRIPTOR(ITF_NUM_HID, 6, HID_PROTOCOL_KEYBOARD, sizeof(desc_hid_report), 0x84, 16, 10)
+#endif
+};
+
+//------------- String Descriptors -------------//
+// array of pointer to string descriptors
+uint16_t const * const string_desc_arr [] =
+{
+ // 0: is supported language = English
+ TUD_DESC_STRCONV(0x0409),
+
+ // 1: Manufacturer
+ TUD_DESC_STRCONV('t', 'i', 'n', 'y', 'u', 's', 'b', '.', 'o', 'r', 'g'),
+
+ // 2: Product
+ TUD_DESC_STRCONV('t', 'i', 'n', 'y', 'u', 's', 'b', ' ', 'd', 'e', 'v', 'i', 'c', 'e'),
+
+ // 3: Serials, should use chip ID
+ TUD_DESC_STRCONV('1', '2', '3', '4', '5', '6'),
+
+ // 4: CDC Interface
+ TUD_DESC_STRCONV('t','u','s','b',' ','c','d','c'),
+
+ // 5: MSC Interface
+ TUD_DESC_STRCONV('t','u','s','b',' ','m','s','c'),
+
+ // 6: HID
+ TUD_DESC_STRCONV('t','u','s','b',' ','h','i','d')
+};
+
+// tud_desc_set is required by tinyusb stack
+tud_desc_set_t tud_desc_set =
+{
+ .device = &desc_device,
+ .config = desc_configuration,
+
+ .string_arr = (uint8_t const **) string_desc_arr,
+ .string_count = sizeof(string_desc_arr)/sizeof(string_desc_arr[0]),
+
+ .hid_report = desc_hid_report,
+};
diff --git a/examples/device/cdc_msc_hid_freertos/ses/nrf5x/nrf5x.emProject b/examples/device/cdc_msc_hid_freertos/ses/nrf5x/nrf5x.emProject
index ad236ae66..ee387958e 100644
--- a/examples/device/cdc_msc_hid_freertos/ses/nrf5x/nrf5x.emProject
+++ b/examples/device/cdc_msc_hid_freertos/ses/nrf5x/nrf5x.emProject
@@ -20,7 +20,7 @@
arm_target_interface_type="SWD"
build_treat_warnings_as_errors="No"
c_preprocessor_definitions="NRF52840_XXAA;__nRF_FAMILY;ARM_MATH_CM4;FLASH_PLACEMENT=1;CFG_TUSB_MCU=OPT_MCU_NRF5X"
- c_user_include_directories="./;../../src;$(rootDir)/hw/cmsis/Include;$(rootDir)/hw;$(rootDir)/src;$(nrfxDir)/..;$(nrfxDir);$(nrfxDir)/mdk;$(nrfxDir)/hal;$(nrfxDir)/drivers/include;$(freertosDir)/Source/include;$(freertosDir)/Source/portable/GCC/ARM_CM4F"
+ c_user_include_directories="./;../../src;$(rootDir)/hw/cmsis/Include;$(rootDir)/hw;$(rootDir)/src;$(nrfxDir)/..;$(nrfxDir);$(nrfxDir)/mdk;$(nrfxDir)/hal;$(nrfxDir)/drivers/include;$(nrfxDir)/drivers/src;$(freertosDir)/Source/include;$(freertosDir)/Source/portable/GCC/ARM_CM4F"
debug_register_definition_file="nrf52840_Registers.xml"
debug_target_connection="J-Link"
gcc_enable_all_warnings="Yes"
diff --git a/examples/device/cdc_msc_hid_freertos/src/main.c b/examples/device/cdc_msc_hid_freertos/src/main.c
index c4b970a81..2877cd382 100644
--- a/examples/device/cdc_msc_hid_freertos/src/main.c
+++ b/examples/device/cdc_msc_hid_freertos/src/main.c
@@ -24,9 +24,6 @@
* This file is part of the TinyUSB stack.
*/
-//--------------------------------------------------------------------+
-// INCLUDE
-//--------------------------------------------------------------------+
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -41,12 +38,22 @@
#include "tusb.h"
//--------------------------------------------------------------------+
-// MACRO CONSTANT TYPEDEF
+// MACRO CONSTANT TYPEDEF PROTYPES
//--------------------------------------------------------------------+
-//--------------------------------------------------------------------+
-// INTERNAL OBJECT & FUNCTION DECLARATION
-//--------------------------------------------------------------------+
+/* Blink pattern
+ * - 250 ms : device not mounted
+ * - 1000 ms : device mounted
+ * - 2500 ms : device is suspended
+ */
+enum {
+ BLINK_NOT_MOUNTED = 250,
+ BLINK_MOUNTED = 1000,
+ BLINK_SUSPENDED = 2500,
+};
+
+TimerHandle_t blink_tm;
+
void led_blinky_cb(TimerHandle_t xTimer);
void usb_device_task(void* param);
@@ -56,8 +63,8 @@ int main(void)
board_init();
// soft timer for blinky
- TimerHandle_t tm_hdl = xTimerCreate(NULL, pdMS_TO_TICKS(1000), true, NULL, led_blinky_cb);
- xTimerStart(tm_hdl, 0);
+ blink_tm = xTimerCreate(NULL, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), true, NULL, led_blinky_cb);
+ xTimerStart(blink_tm, 0);
tusb_init();
@@ -71,7 +78,8 @@ int main(void)
#endif
#if CFG_TUD_HID
- extern void usb_hid_task(void* params);
+ extern void hid_task(void* params);
+ xTaskCreate( hid_task, "hid", 256, NULL, configMAX_PRIORITIES-2, NULL);
#endif
vTaskStartScheduler();
@@ -130,6 +138,7 @@ void cdc_task(void* params)
}
}
+// Invoked when cdc when line state changed e.g connected/disconnected
void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts)
{
(void) itf;
@@ -141,85 +150,134 @@ void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts)
tud_cdc_write_str("\r\nTinyUSB CDC MSC HID device with FreeRTOS example\r\n");
}
}
+
+// Invoked when CDC interface received data from host
+void tud_cdc_rx_cb(uint8_t itf)
+{
+ (void) itf;
+}
+
#endif
//--------------------------------------------------------------------+
// USB HID
//--------------------------------------------------------------------+
#if CFG_TUD_HID
-void usb_hid_task(void* params)
+
+// Must match with ID declared by HID Report Descriptor, better to be in header file
+enum
{
- (void) params;
+ REPORT_ID_KEYBOARD = 1,
+ REPORT_ID_MOUSE
+};
- // Poll every 10ms
- const uint32_t interval_ms = 10;
- static uint32_t start_ms = 0;
+void hid_task(void* params)
+{
+ (void) params;
- if ( board_millis() < start_ms + interval_ms) return; // not enough time
- start_ms += interval_ms;
+ while (1)
+ {
+ // Poll every 10ms
+ vTaskDelay(pdMS_TO_TICKS(10));
- uint32_t const btn = board_button_read();
+ uint32_t const btn = board_button_read();
- /*------------- Keyboard -------------*/
- if ( tud_hid_keyboard_ready() )
- {
- if ( btn )
+ // Remote wakeup
+ if ( tud_suspended() && btn )
{
- uint8_t keycode[6] = { 0 };
+ // Wake up host if we are in suspend mode
+ // and REMOTE_WAKEUP feature is enabled by host
+ tud_remote_wakeup();
+ }
- for(uint8_t i=0; i < 6; i++)
+ /*------------- Mouse -------------*/
+ if ( tud_hid_ready() )
+ {
+ if ( btn )
{
- if ( btn & (1 << i) ) keycode[i] = HID_KEY_A + i;
+ int8_t const delta = 5;
+ tud_hid_mouse_move(REPORT_ID_MOUSE, delta, delta); // right + down
+
+ // delay a bit before attempt to send keyboard report
+ vTaskDelay(pdMS_TO_TICKS(2));
}
+ }
- tud_hid_keyboard_keycode(0, keycode);
- }else
+ /*------------- Keyboard -------------*/
+ if ( tud_hid_ready() )
{
- // Null means all zeroes keycodes
- tud_hid_keyboard_keycode(0, NULL);
- }
- }
+ // use to avoid send multiple consecutive zero report for keyboard
+ static bool has_key = false;
+ if ( btn )
+ {
+ uint8_t keycode[6] = { 0 };
+ keycode[0] = HID_KEY_A;
- /*------------- Mouse -------------*/
- if ( tud_hid_mouse_ready() )
- {
- enum { DELTA = 5 };
+ tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, keycode);
- if ( btn & 0x01 ) tud_hid_mouse_move(-DELTA, 0); // left
- if ( btn & 0x02 ) tud_hid_mouse_move( DELTA, 0); // right
- if ( btn & 0x04 ) tud_hid_mouse_move( 0 , -DELTA); // up
- if ( btn & 0x08 ) tud_hid_mouse_move( 0 , DELTA); // down
+ has_key = true;
+ }else
+ {
+ // send empty key report if previously has key pressed
+ if (has_key) tud_hid_keyboard_key_release(REPORT_ID_KEYBOARD);
+ has_key = false;
+ }
+ }
}
}
-uint16_t tud_hid_generic_get_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen)
+uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen)
{
// TODO not Implemented
+ (void) report_id;
+ (void) report_type;
+ (void) buffer;
+ (void) reqlen;
+
return 0;
}
-void tud_hid_generic_set_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize)
+void tud_hid_set_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize)
{
// TODO not Implemented
+ (void) report_id;
+ (void) report_type;
+ (void) buffer;
+ (void) bufsize;
}
+
#endif
//--------------------------------------------------------------------+
-// tinyusb callbacks
+// Device callbacks
//--------------------------------------------------------------------+
+
+// Invoked when device is mounted
void tud_mount_cb(void)
{
-
+ xTimerChangePeriod(blink_tm, pdMS_TO_TICKS(BLINK_MOUNTED), 0);
}
+// Invoked when device is unmounted
void tud_umount_cb(void)
{
+ xTimerChangePeriod(blink_tm, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), 0);
}
-void tud_cdc_rx_cb(uint8_t itf)
+// Invoked when usb bus is suspended
+// remote_wakeup_en : if host allow us to perform remote wakeup
+// Within 7ms, device must draw an average of current less than 2.5 mA from bus
+void tud_suspend_cb(bool remote_wakeup_en)
{
- (void) itf;
+ (void) remote_wakeup_en;
+ xTimerChangePeriod(blink_tm, pdMS_TO_TICKS(BLINK_SUSPENDED), 0);
+}
+
+// Invoked when usb bus is resumed
+void tud_resume_cb(void)
+{
+ xTimerChangePeriod(blink_tm, pdMS_TO_TICKS(BLINK_MOUNTED), 0);
}
//--------------------------------------------------------------------+
diff --git a/examples/device/cdc_msc_hid_freertos/src/msc_app.c b/examples/device/cdc_msc_hid_freertos/src/msc_app.c
deleted file mode 100644
index d50af7810..000000000
--- a/examples/device/cdc_msc_hid_freertos/src/msc_app.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2018, hathach (tinyusb.org)
- *
- * 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.
- *
- * This file is part of the TinyUSB stack.
- */
-
-#include "bsp/board.h"
-#include "tusb.h"
-
-#if CFG_TUD_MSC
-
-//--------------------------------------------------------------------+
-// MACRO CONSTANT TYPEDEF
-//--------------------------------------------------------------------+
-
-//--------------------------------------------------------------------+
-// tinyusb callbacks
-//--------------------------------------------------------------------+
-
-// 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)
-{
- // read10 & write10 has their own callback and MUST not be handled here
-
- void const* response = NULL;
- uint16_t resplen = 0;
-
- // most scsi handled is input
- bool in_xfer = true;
-
- switch (scsi_cmd[0])
- {
- case SCSI_CMD_TEST_UNIT_READY:
- // Command that host uses to check our readiness before sending other commands
- resplen = 0;
- break;
-
- case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
- // 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:
- // 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 resplen must not larger than bufsize
- if ( resplen > bufsize ) resplen = bufsize;
-
- if ( response && (resplen > 0) )
- {
- if(in_xfer)
- {
- memcpy(buffer, response, resplen);
- }else
- {
- // SCSI output
- }
- }
-
- return resplen;
-}
-
-
-#endif
diff --git a/examples/device/cdc_msc_hid_freertos/src/msc_disk_ram.c b/examples/device/cdc_msc_hid_freertos/src/msc_disk.c
index 1906edb8b..8bcd056e3 100644
--- a/examples/device/cdc_msc_hid_freertos/src/msc_disk_ram.c
+++ b/examples/device/cdc_msc_hid_freertos/src/msc_disk.c
@@ -49,7 +49,7 @@ enum
#ifdef DISK_READONLY
const
#endif
-static uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] =
+uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] =
{
//------------- Boot Sector -------------//
// byte_per_sector = DISK_BLOCK_SIZE; fat12_sector_num_16 = DISK_BLOCK_NUM;
@@ -82,7 +82,7 @@ static uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] =
// second entry is readme file
'R' , 'E' , 'A' , 'D' , 'M' , 'E' , ' ' , ' ' , 'T' , 'X' , 'T' , 0x20, 0x00, 0xC6, 0x52, 0x6D,
0x65, 0x43, 0x65, 0x43, 0x00, 0x00, 0x88, 0x6D, 0x65, 0x43, 0x02, 0x00,
- sizeof(README_CONTENTS)-1, 0x00, 0x00, 0x00 // readme's filesize (4 Bytes)
+ sizeof(README_CONTENTS)-1, 0x00, 0x00, 0x00 // readme's files ize (4 Bytes)
},
//------------- Readme Content -------------//
@@ -96,7 +96,7 @@ int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buff
{
(void) lun;
- uint8_t* addr = msc_disk[lba] + offset;
+ uint8_t const* addr = msc_disk[lba] + offset;
memcpy(buffer, addr, bufsize);
return bufsize;
@@ -111,6 +111,8 @@ int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t*
#ifndef DISK_READONLY
uint8_t* addr = msc_disk[lba] + offset;
memcpy(addr, buffer, bufsize);
+#else
+ (void) lba; (void) offset; (void) buffer;
#endif
return bufsize;
@@ -124,4 +126,67 @@ void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_siz
*block_size = DISK_BLOCK_SIZE;
}
+// 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)
+{
+ // read10 & write10 has their own callback and MUST not be handled here
+
+ void const* response = NULL;
+ uint16_t resplen = 0;
+
+ // most scsi handled is input
+ bool in_xfer = true;
+
+ switch (scsi_cmd[0])
+ {
+ case SCSI_CMD_TEST_UNIT_READY:
+ // Command that host uses to check our readiness before sending other commands
+ resplen = 0;
+ break;
+
+ case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
+ // 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:
+ // 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 resplen must not larger than bufsize
+ if ( resplen > bufsize ) resplen = bufsize;
+
+ if ( response && (resplen > 0) )
+ {
+ if(in_xfer)
+ {
+ memcpy(buffer, response, resplen);
+ }else
+ {
+ // SCSI output
+ }
+ }
+
+ return resplen;
+}
+
#endif
diff --git a/examples/device/cdc_msc_hid_freertos/src/tusb_config.h b/examples/device/cdc_msc_hid_freertos/src/tusb_config.h
index 6004caf8c..9444ca890 100644
--- a/examples/device/cdc_msc_hid_freertos/src/tusb_config.h
+++ b/examples/device/cdc_msc_hid_freertos/src/tusb_config.h
@@ -40,7 +40,12 @@
#error CFG_TUSB_MCU must be defined
#endif
+#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX
+#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED)
+#else
#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE
+#endif
+
#define CFG_TUSB_OS OPT_OS_FREERTOS
#define CFG_TUSB_DEBUG 2
@@ -65,46 +70,13 @@
#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 1
-
-/* If USB VID/PID is not defined, tinyusb will use default value
- * 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 CFG_TUD_DESC_VID 0xCAFE
-// #define CFG_TUD_DESC_PID 0x0001
-
-// LPC175x_6x's endpoint type (bulk/interrupt/iso) are fixed by its number
-// Therefor we need to force endpoint number to correct type on lpc17xx
-#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X
-#define CFG_TUD_DESC_CDC_EPNUM_NOTIF 1
-#define CFG_TUD_DESC_CDC_EPNUM 2
-#define CFG_TUD_DESC_MSC_EPNUM 5
-#define CFG_TUD_DESC_HID_KEYBOARD_EPNUM 4
-#define CFG_TUD_DESC_HID_MOUSE_EPNUM 7
-#endif
-
-
//------------- CLASS -------------//
#define CFG_TUD_CDC 1
#define CFG_TUD_MSC 1
+#define CFG_TUD_HID 1
-#define CFG_TUD_HID 0
-#define CFG_TUD_HID_KEYBOARD 0
-#define CFG_TUD_HID_MOUSE 0
-
-/* Use Boot Protocol for Keyboard, Mouse. Enable this will create separated HID interface
- * require more IN endpoints. If disabled, they they are all packed into a single
- * multiple report interface called "Generic". */
-#define CFG_TUD_HID_KEYBOARD_BOOT 1
-#define CFG_TUD_HID_MOUSE_BOOT 1
-
+#define CFG_TUD_MIDI 0
+#define CFG_TUD_CUSTOM_CLASS 0
//--------------------------------------------------------------------
// CDC
@@ -137,10 +109,9 @@
// HID
//--------------------------------------------------------------------
-/* Use the HID_ASCII_TO_KEYCODE lookup if CFG_TUD_HID_KEYBOARD is enabled.
- * This will occupies 256 bytes of ROM. It will also enable the use of 2 extra APIs
+/* Use the HID_ASCII_TO_KEYCODE lookup
+ * This will occupies 256 bytes of ROM. It will also enable the use of extra APIs
* - tud_hid_keyboard_send_char()
- * - tud_hid_keyboard_send_string()
*/
#define CFG_TUD_HID_ASCII_TO_KEYCODE_LOOKUP 1
diff --git a/examples/device/cdc_msc_hid_freertos/src/tusb_descriptors.c b/examples/device/cdc_msc_hid_freertos/src/tusb_descriptors.c
deleted file mode 100644
index 866005e3f..000000000
--- a/examples/device/cdc_msc_hid_freertos/src/tusb_descriptors.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2018, hathach (tinyusb.org)
- *
- * 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.
- *
- * This file is part of the TinyUSB stack.
- */
-
-#include "tusb.h"
-
-//--------------------------------------------------------------------+
-// STRING DESCRIPTORS
-//--------------------------------------------------------------------+
-
-// array of pointer to string descriptors
-uint16_t const * const string_desc_arr [] =
-{
- // 0: is supported language = English
- TUD_DESC_STRCONV(0x0409),
-
- // 1: Manufacturer
- TUD_DESC_STRCONV('t', 'i', 'n', 'y', 'u', 's', 'b', '.', 'o', 'r', 'g'),
-
- // 2: Product
- TUD_DESC_STRCONV('t', 'i', 'n', 'y', 'u', 's', 'b', ' ', 'd', 'e', 'v', 'i', 'c', 'e'),
-
- // 3: Serials TODO use chip ID
- TUD_DESC_STRCONV('1', '2', '3', '4', '5', '6'),
-
-#if CFG_TUD_CDC
- // 4: CDC Interface
- TUD_DESC_STRCONV('t','u','s','b',' ','c','d','c'),
-#endif
-
-#if CFG_TUD_MSC
- // 5: MSC Interface
- TUD_DESC_STRCONV('t','u','s','b',' ','m','s','c'),
-#endif
-
-#if CFG_TUD_HID_KEYBOARD
- // 6: Keyboard
- TUD_DESC_STRCONV('t','u','s','b',' ','k','e','y','b','o','a','r','d'),
-#endif
-
-#if CFG_TUD_HID_MOUSE
- // 7: Mouse
- TUD_DESC_STRCONV('t','u','s','b',' ','m', 'o','u','s','e'),
-#endif
-
-};
-
-// 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,
- .string_count = sizeof(string_desc_arr)/sizeof(string_desc_arr[0]),
-
- .hid_report =
- {
- .generic = NULL,
- .boot_keyboard = NULL,
- .boot_mouse = NULL
- }
-};
diff --git a/examples/device/cdc_msc_hid_freertos/src/usb_descriptors.c b/examples/device/cdc_msc_hid_freertos/src/usb_descriptors.c
new file mode 100644
index 000000000..28a4b28d1
--- /dev/null
+++ b/examples/device/cdc_msc_hid_freertos/src/usb_descriptors.c
@@ -0,0 +1,171 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018, hathach (tinyusb.org)
+ *
+ * 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.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#include "tusb.h"
+
+/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug.
+ * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC.
+ *
+ * Auto ProductID layout's Bitmap:
+ * [MSB] HID | MSC | CDC [LSB]
+ */
+#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) )
+#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) )
+
+//------------- Device Descriptors -------------//
+tusb_desc_device_t const desc_device =
+{
+ .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 = 0xCafe,
+ .idProduct = USB_PID,
+ .bcdDevice = 0x0100,
+
+ .iManufacturer = 0x01,
+ .iProduct = 0x02,
+ .iSerialNumber = 0x03,
+
+ .bNumConfigurations = 0x01
+};
+
+//------------- HID Report Descriptor -------------//
+enum
+{
+ REPORT_ID_KEYBOARD = 1,
+ REPORT_ID_MOUSE
+};
+
+uint8_t const desc_hid_report[] =
+{
+ HID_REPORT_DESC_KEYBOARD( HID_REPORT_ID(REPORT_ID_KEYBOARD), ),
+ HID_REPORT_DESC_MOUSE ( HID_REPORT_ID(REPORT_ID_MOUSE), )
+};
+
+//------------- Configuration Descriptor -------------//
+enum
+{
+ #if CFG_TUD_CDC
+ ITF_NUM_CDC = 0,
+ ITF_NUM_CDC_DATA,
+ #endif
+
+ #if CFG_TUD_MSC
+ ITF_NUM_MSC,
+ #endif
+
+ #if CFG_TUD_HID
+ ITF_NUM_HID,
+ #endif
+
+ ITF_NUM_TOTAL
+};
+
+enum
+{
+ CONFIG_DESC_LEN = sizeof(tusb_desc_configuration_t) + CFG_TUD_CDC*TUD_CDC_DESC_LEN + CFG_TUD_MSC*TUD_MSC_DESC_LEN + CFG_TUD_HID*TUD_HID_DESC_LEN
+};
+
+#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX
+ // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number
+ // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ...
+ // Note: since CDC EP ( 1 & 2), HID (4) are spot-on, thus we only need to force
+ // endpoint number for MSC to 5
+ #define EPNUM_MSC 0x05
+#else
+ #define EPNUM_MSC 0x03
+#endif
+
+uint8_t const desc_configuration[] =
+{
+ // Config: self-powered with remote wakeup support, max power up to 100 mA
+ TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_DESC_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
+
+#if CFG_TUD_CDC
+ TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, 0x81, 8, 0x02, 0x82, 64),
+#endif
+
+#if CFG_TUD_MSC
+ TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC, 0x80 | EPNUM_MSC, 64), // highspeed 512
+#endif
+
+#if CFG_TUD_HID
+ TUD_HID_DESCRIPTOR(ITF_NUM_HID, 6, HID_PROTOCOL_KEYBOARD, sizeof(desc_hid_report), 0x84, 16, 10)
+#endif
+};
+
+//------------- String Descriptors -------------//
+// array of pointer to string descriptors
+uint16_t const * const string_desc_arr [] =
+{
+ // 0: is supported language = English
+ TUD_DESC_STRCONV(0x0409),
+
+ // 1: Manufacturer
+ TUD_DESC_STRCONV('t', 'i', 'n', 'y', 'u', 's', 'b', '.', 'o', 'r', 'g'),
+
+ // 2: Product
+ TUD_DESC_STRCONV('t', 'i', 'n', 'y', 'u', 's', 'b', ' ', 'd', 'e', 'v', 'i', 'c', 'e'),
+
+ // 3: Serials, should use chip ID
+ TUD_DESC_STRCONV('1', '2', '3', '4', '5', '6'),
+
+ // 4: CDC Interface
+ TUD_DESC_STRCONV('t','u','s','b',' ','c','d','c'),
+
+ // 5: MSC Interface
+ TUD_DESC_STRCONV('t','u','s','b',' ','m','s','c'),
+
+ // 6: HID
+ TUD_DESC_STRCONV('t','u','s','b',' ','h','i','d')
+};
+
+// tud_desc_set is required by tinyusb stack
+tud_desc_set_t tud_desc_set =
+{
+ .device = &desc_device,
+ .config = desc_configuration,
+
+ .string_arr = (uint8_t const **) string_desc_arr,
+ .string_count = sizeof(string_desc_arr)/sizeof(string_desc_arr[0]),
+
+ .hid_report = desc_hid_report,
+};
diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c
index 4f31c6d3f..1c9a5ded2 100644
--- a/examples/host/cdc_msc_hid/src/main.c
+++ b/examples/host/cdc_msc_hid/src/main.c
@@ -37,8 +37,8 @@
void print_greeting(void);
void led_blinking_task(void);
-extern void virtual_com_task(void);
-extern void usb_hid_task(void);
+extern void cdc_task(void);
+extern void hid_task(void);
/*------------- MAIN -------------*/
int main(void)
@@ -56,11 +56,11 @@ int main(void)
led_blinking_task();
#if CFG_TUH_CDC
- virtual_com_task();
+ cdc_task();
#endif
#if CFG_TUD_HID
- usb_hid_task();
+ hid_task();
#endif
}
@@ -100,7 +100,7 @@ void tuh_cdc_xfer_isr(uint8_t dev_addr, xfer_result_t event, cdc_pipeid_t pipe_i
tuh_cdc_receive(dev_addr, serial_in_buffer, sizeof(serial_in_buffer), true); // waiting for next data
}
-void virtual_com_task(void)
+void cdc_task(void)
{
}
@@ -111,7 +111,7 @@ void virtual_com_task(void)
// USB HID
//--------------------------------------------------------------------+
#if CFG_TUH_HID_KEYBOARD
-void usb_hid_task(void)
+void hid_task(void)
{
}