mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
tests: add tinyUSB CDC and MSC device test application
This commit is contained in:
parent
990feeec39
commit
3367b106bb
@ -29,4 +29,4 @@ FEATURES_CONFLICT += periph_gpio_irq:periph_gpio_ll_irq
|
||||
FEATURES_CONFLICT_MSG += "Only one GPIO IRQ implementation can be used"
|
||||
|
||||
FEATURES_CONFLICT += periph_usbdev:tinyusb
|
||||
FEATURES_CONFLICT_MSG += "Package tinyUSB is not yet compatible with periph/usdev"
|
||||
FEATURES_CONFLICT_MSG += "Package tinyUSB is not yet compatible with periph/usbdev"
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2021 HAW Hamburg
|
||||
# Copyright (c) 2022 Gunar Schorcht
|
||||
#
|
||||
# This file is subject to the terms and conditions of the GNU Lesser
|
||||
# General Public License v2.1. See the file LICENSE in the top level
|
||||
|
@ -1,10 +1,10 @@
|
||||
# Package tinyUSB has its own USB device driver. Therefore, it cannot be used
|
||||
# together with periph/usbdev for now.
|
||||
ifneq (,$(filter periph_usbdev,$(USEMODULE)))
|
||||
$(error "Package tinyUSB is not yet compatible with periph/usdev")
|
||||
$(error "Package tinyUSB is not yet compatible with periph/usbdev")
|
||||
endif
|
||||
|
||||
# tinyUSB muteces use priority inheritance
|
||||
# tinyUSB mutexes use priority inheritance
|
||||
# USEMODULE += core_mutex_priority_inheritance
|
||||
|
||||
# tinyUSB modules always needed
|
||||
|
@ -32,12 +32,12 @@
|
||||
#endif
|
||||
|
||||
#ifndef TINYUSB_TUD_RHPORT
|
||||
/** tinyUSB RHPort number used for device, default value is 0 */
|
||||
/** tinyUSB RHPort number used for the device stack, default value is 0 */
|
||||
#define TINYUSB_TUD_RHPORT 0
|
||||
#endif
|
||||
|
||||
#ifndef TINYUSB_TUH_RHPORT
|
||||
/** tinyUSB RHPort number used for host, defaults value is 0 */
|
||||
/** tinyUSB RHPort number used for the host stack, defaults value is 0 */
|
||||
#define TINYUSB_TUH_RHPORT 0
|
||||
#endif
|
||||
|
||||
|
13
tests/pkg_tinyusb_cdc_msc/Makefile
Normal file
13
tests/pkg_tinyusb_cdc_msc/Makefile
Normal file
@ -0,0 +1,13 @@
|
||||
include ../Makefile.tests_common
|
||||
|
||||
USB_VID ?= $(USB_VID_TESTING)
|
||||
USB_PID ?= $(USB_PID_TESTING)
|
||||
|
||||
USEPKG += tinyusb
|
||||
USEMODULE += tinyusb_class_cdc
|
||||
USEMODULE += tinyusb_class_msc
|
||||
USEMODULE += tinyusb_device
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
||||
|
||||
INCLUDES += -I$(APPDIR)
|
43
tests/pkg_tinyusb_cdc_msc/README.md
Normal file
43
tests/pkg_tinyusb_cdc_msc/README.md
Normal file
@ -0,0 +1,43 @@
|
||||
# TinyUSB package test application
|
||||
|
||||
## Overview
|
||||
|
||||
This application uses the tinyUSB device stack to emulate a mass storage
|
||||
device (MSC) with a communication interface (CDC).
|
||||
|
||||
**Please note:** RIOT doesn't own any USB vendor and product ID. The test
|
||||
application therefore uses `USB_VID_TESTING=0x1209` as manufacturer ID and
|
||||
`USB_PID_TESTING=0x7d01` as product ID. Do not use these IDs outside of
|
||||
test environments! They MUST NOT be used on any device that is redistributed,
|
||||
sold or manufactured, as they are not unique!
|
||||
|
||||
To compile this application with your own vendor and product ID, set the
|
||||
variables `USB_VID` and `USB_PID` in the makefile or at the command line,
|
||||
for example
|
||||
|
||||
```
|
||||
USB_VID=1234 USB_PID=5678 BOARD=... make -C tests/pkg_tinyusb_cdc_msc
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Once the application is flashed, the device should be mounted when it is
|
||||
connected to a host. That is,
|
||||
|
||||
- the mass storage interface is mounted as volume `TinyUSB MSC` in the
|
||||
operating system and
|
||||
- the communication interface is mounted as a serial device, for example
|
||||
as `/dev/ttyACM0` on Linux.
|
||||
|
||||
It should then be possible
|
||||
|
||||
1. to read from and write to the mass storage with the usual file operations
|
||||
of the operating system
|
||||
2. to connect to the serial interface of the device with a terminal program, e.g.
|
||||
```
|
||||
python -m serial.tools.miniterm /dev/ttyACM0 115200
|
||||
```
|
||||
and get the entered characters sent back.
|
||||
|
||||
The test application uses LED0, if present, to indicate the status of the
|
||||
device by blinking at different frequencies.
|
5
tests/pkg_tinyusb_cdc_msc/app.config.test
Normal file
5
tests/pkg_tinyusb_cdc_msc/app.config.test
Normal file
@ -0,0 +1,5 @@
|
||||
CONFIG_PACKAGE_TINYUSB=y
|
||||
CONFIG_MODULE_TINYUSB_CLASS_CDC=y
|
||||
CONFIG_MODULE_TINYUSB_CLASS_MSC=y
|
||||
CONFIG_MODULE_TINYUSB_COMMON=y
|
||||
CONFIG_MODULE_TINYUSB_DEVICE=y
|
195
tests/pkg_tinyusb_cdc_msc/main.c
Normal file
195
tests/pkg_tinyusb_cdc_msc/main.c
Normal file
@ -0,0 +1,195 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Ha Thach (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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "board.h"
|
||||
#include "log.h"
|
||||
#include "ztimer.h"
|
||||
|
||||
#include "tusb.h"
|
||||
#include "tinyusb.h"
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------------
|
||||
* MACRO CONSTANT TYPEDEF PROTYPES
|
||||
* --------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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,
|
||||
};
|
||||
|
||||
static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED;
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------------
|
||||
* BLINKING TASK
|
||||
* --------------------------------------------------------------------
|
||||
*/
|
||||
char led_thread_stack[THREAD_STACKSIZE_MAIN];
|
||||
|
||||
void *led_thread_impl(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
while (1) {
|
||||
ztimer_sleep(ZTIMER_MSEC, blink_interval_ms);
|
||||
#ifdef LED0_TOGGLE
|
||||
LED0_TOGGLE;
|
||||
#else
|
||||
printf("Blinking with %"PRIu32" msec!\n", blink_interval_ms);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void cdc_task(void);
|
||||
|
||||
/* ------------- MAIN ------------- */
|
||||
|
||||
int main(void)
|
||||
{
|
||||
ztimer_sleep(ZTIMER_MSEC, 200);
|
||||
|
||||
thread_create(led_thread_stack, sizeof(led_thread_stack),
|
||||
THREAD_PRIORITY_MAIN + 1,
|
||||
THREAD_CREATE_WOUT_YIELD | THREAD_CREATE_STACKTEST,
|
||||
led_thread_impl, NULL, "led");
|
||||
|
||||
/* initialize the tinyUSB stack including used peripherals and
|
||||
* start the tinyUSB thread */
|
||||
tinyusb_setup();
|
||||
|
||||
while (1) {
|
||||
ztimer_sleep(ZTIMER_MSEC, 10);
|
||||
cdc_task();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------------
|
||||
* Device callbacks to be implemented
|
||||
* --------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* Invoked when device is mounted
|
||||
*/
|
||||
void tud_mount_cb(void)
|
||||
{
|
||||
printf("tinyUSB %s\n", __func__);
|
||||
blink_interval_ms = BLINK_MOUNTED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Invoked when device is unmounted
|
||||
*/
|
||||
void tud_umount_cb(void)
|
||||
{
|
||||
printf("tinyUSB %s\n", __func__);
|
||||
blink_interval_ms = BLINK_NOT_MOUNTED;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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) remote_wakeup_en;
|
||||
printf("tinyUSB %s\n", __func__);
|
||||
blink_interval_ms = BLINK_SUSPENDED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Invoked when usb bus is resumed
|
||||
*/
|
||||
void tud_resume_cb(void)
|
||||
{
|
||||
printf("tinyUSB %s\n", __func__);
|
||||
blink_interval_ms = BLINK_MOUNTED;
|
||||
}
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------------+
|
||||
* USB CDC
|
||||
* --------------------------------------------------------------------+
|
||||
*/
|
||||
void cdc_task(void)
|
||||
{
|
||||
/*
|
||||
* connected() check for DTR bit
|
||||
* Most but not all terminal client set this when making connection
|
||||
*/
|
||||
if ( tud_cdc_connected() ) {
|
||||
/* connected and there are data available */
|
||||
if ( tud_cdc_available() )
|
||||
{
|
||||
/* read data */
|
||||
char buf[64];
|
||||
uint32_t count = tud_cdc_read(buf, sizeof(buf));
|
||||
(void) count;
|
||||
|
||||
/*
|
||||
* Echo back
|
||||
* Note: Skip echo by commenting out write() and write_flush()
|
||||
* for throughput test e.g
|
||||
* $ dd if=/dev/zero of=/dev/ttyACM0 count=10000
|
||||
*/
|
||||
tud_cdc_write(buf, count);
|
||||
tud_cdc_write_flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
(void) rts;
|
||||
|
||||
/* TODO set some indicator */
|
||||
if ( dtr ) {
|
||||
/* Terminal connected */
|
||||
}
|
||||
else {
|
||||
/* Terminal disconnected */
|
||||
}
|
||||
}
|
360
tests/pkg_tinyusb_cdc_msc/msc_disk.c
Normal file
360
tests/pkg_tinyusb_cdc_msc/msc_disk.c
Normal file
@ -0,0 +1,360 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Ha Thach (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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "tusb.h"
|
||||
|
||||
#define ENABLE_DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
#if CFG_TUD_MSC
|
||||
|
||||
/* whether host does safe-eject */
|
||||
static bool ejected = false;
|
||||
|
||||
/* Some MCU doesn't have enough 8KB SRAM to store the whole disk
|
||||
* We will use Flash as read-only disk with board that has
|
||||
* CFG_EXAMPLE_MSC_READONLY defined
|
||||
*/
|
||||
|
||||
#define README_CONTENTS \
|
||||
"This is tinyusb's MassStorage Class demo.\r\n\r\n" \
|
||||
"If you find any bugs or get any questions, feel free to file an\r\n" \
|
||||
"issue at github.com/hathach/tinyusb"
|
||||
|
||||
enum {
|
||||
DISK_BLOCK_NUM = 16, /* 8KB is the smallest size that windows allow to mount */
|
||||
DISK_BLOCK_SIZE = 512
|
||||
};
|
||||
|
||||
#ifdef CFG_EXAMPLE_MSC_READONLY
|
||||
const
|
||||
#endif
|
||||
uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] = {
|
||||
/*------------- Block0: Boot Sector ------------- *
|
||||
* byte_per_sector = DISK_BLOCK_SIZE;
|
||||
fat12_sector_num_16 = DISK_BLOCK_NUM;
|
||||
* sector_per_cluster = 1;
|
||||
* reserved_sectors = 1;
|
||||
* fat_num = 1;
|
||||
* fat12_root_entry_num = 16;
|
||||
* sector_per_fat = 1;
|
||||
* sector_per_track = 1;
|
||||
* head_num = 1;
|
||||
* hidden_sectors = 0;
|
||||
* drive_number = 0x80;
|
||||
* media_type = 0xf8;
|
||||
* extended_boot_signature = 0x29;
|
||||
* filesystem_type = "FAT12 ";
|
||||
* volume_serial_number = 0x1234;
|
||||
* volume_label = "TinyUSB MSC";
|
||||
* FAT magic code at offset 510-511
|
||||
*/
|
||||
{
|
||||
0xEB, 0x3C, 0x90, 0x4D, 0x53, 0x44, 0x4F, 0x53,
|
||||
0x35, 0x2E, 0x30, 0x00, 0x02, 0x01, 0x01, 0x00,
|
||||
0x01, 0x10, 0x00, 0x10, 0x00, 0xF8, 0x01, 0x00,
|
||||
0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x29, 0x34,
|
||||
0x12, 0x00, 0x00, 'T' , 'i' , 'n' , 'y' , 'U' ,
|
||||
'S' , 'B' , ' ' , 'M' , 'S' , 'C' , 0x46, 0x41,
|
||||
0x54, 0x31, 0x32, 0x20, 0x20, 0x20, 0x00, 0x00,
|
||||
|
||||
/* Zero up to 2 last bytes of FAT magic code */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xAA
|
||||
},
|
||||
|
||||
/* ------------- Block1: FAT12 Table ------------- */
|
||||
{
|
||||
0xF8, 0xFF, 0xFF, 0xFF, 0x0F /* first 2 entries must be F8FF,
|
||||
* third entry is cluster end of readme file */
|
||||
},
|
||||
|
||||
/* ------------- Block2: Root Directory ------------- */
|
||||
{
|
||||
/* first entry is volume label */
|
||||
'T' , 'i' , 'n' , 'y' , 'U' , 'S' , 'B' , ' ' ,
|
||||
'M' , 'S' , 'C' , 0x08, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4F, 0x6D,
|
||||
0x65, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 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 files size (4 Bytes) */
|
||||
},
|
||||
|
||||
/* ------------- Block3: Readme Content ------------- */
|
||||
README_CONTENTS
|
||||
};
|
||||
|
||||
/*
|
||||
* Invoked when received SCSI_CMD_INQUIRY
|
||||
* Application fill vendor id, product id and revision with string up to 8, 16, 4
|
||||
* characters respectively
|
||||
*/
|
||||
void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8],
|
||||
uint8_t product_id[16], uint8_t product_rev[4])
|
||||
{
|
||||
(void)lun;
|
||||
|
||||
DEBUG("tinyUSB %s\n", __func__);
|
||||
|
||||
const char vid[] = "TinyUSB";
|
||||
const char pid[] = "Mass Storage";
|
||||
const char rev[] = "1.0";
|
||||
|
||||
memcpy(vendor_id, vid, strlen(vid));
|
||||
memcpy(product_id, pid, strlen(pid));
|
||||
memcpy(product_rev, rev, strlen(rev));
|
||||
}
|
||||
|
||||
/*
|
||||
* Invoked when received Test Unit Ready command.
|
||||
* return true allowing host to read/write this LUN e.g SD card inserted
|
||||
*/
|
||||
bool tud_msc_test_unit_ready_cb(uint8_t lun)
|
||||
{
|
||||
(void)lun;
|
||||
|
||||
DEBUG("tinyUSB %s\n", __func__);
|
||||
|
||||
/* RAM disk is ready until ejected */
|
||||
if (ejected) {
|
||||
/* Additional Sense 3A-00 is NOT_FOUND */
|
||||
tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3a, 0x00);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Invoked when received SCSI_CMD_READ_CAPACITY_10 and
|
||||
* SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size
|
||||
* Application update block count and block size
|
||||
*/
|
||||
void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size)
|
||||
{
|
||||
(void)lun;
|
||||
|
||||
DEBUG("tinyUSB %s\n", __func__);
|
||||
|
||||
*block_count = DISK_BLOCK_NUM;
|
||||
*block_size = DISK_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Invoked when received Start Stop Unit command
|
||||
* - Start = 0 : stopped power mode, if load_eject = 1 : unload disk storage
|
||||
* - Start = 1 : active mode, if load_eject = 1 : load disk storage
|
||||
*/
|
||||
bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition,
|
||||
bool start, bool load_eject)
|
||||
{
|
||||
(void)lun;
|
||||
(void)power_condition;
|
||||
|
||||
DEBUG("tinyUSB %s\n", __func__);
|
||||
|
||||
if (load_eject) {
|
||||
if (start) {
|
||||
/* load disk storage */
|
||||
}
|
||||
else {
|
||||
/* unload disk storage */
|
||||
ejected = true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
DEBUG("tinyUSB %s\n", __func__);
|
||||
|
||||
/* out of ramdisk */
|
||||
if (lba >= DISK_BLOCK_NUM) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t const* addr = msc_disk[lba] + offset;
|
||||
memcpy(buffer, addr, bufsize);
|
||||
|
||||
return (int32_t)bufsize;
|
||||
}
|
||||
|
||||
bool tud_msc_is_writable_cb(uint8_t lun)
|
||||
{
|
||||
(void)lun;
|
||||
|
||||
DEBUG("tinyUSB %s\n", __func__);
|
||||
|
||||
#ifdef CFG_EXAMPLE_MSC_READONLY
|
||||
return false;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* 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,
|
||||
uint8_t* buffer, uint32_t bufsize)
|
||||
{
|
||||
(void)lun;
|
||||
|
||||
DEBUG("tinyUSB %s\n", __func__);
|
||||
|
||||
/* out of ramdisk */
|
||||
if (lba >= DISK_BLOCK_NUM) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifndef CFG_EXAMPLE_MSC_READONLY
|
||||
uint8_t* addr = msc_disk[lba] + offset;
|
||||
memcpy(addr, buffer, bufsize);
|
||||
#else
|
||||
(void)lba;
|
||||
(void)offset;
|
||||
(void)buffer;
|
||||
#endif
|
||||
|
||||
return (int32_t) bufsize;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
|
||||
DEBUG("tinyUSB %s\n", __func__);
|
||||
|
||||
void const* response = NULL;
|
||||
int32_t resplen = 0;
|
||||
|
||||
/* most scsi handled is input */
|
||||
bool in_xfer = true;
|
||||
|
||||
switch (scsi_cmd[0]) {
|
||||
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, (size_t) resplen);
|
||||
}
|
||||
else {
|
||||
/* SCSI output */
|
||||
}
|
||||
}
|
||||
|
||||
return (int32_t)resplen;
|
||||
}
|
||||
|
||||
#endif
|
41
tests/pkg_tinyusb_cdc_msc/tusb_config.h
Normal file
41
tests/pkg_tinyusb_cdc_msc/tusb_config.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Gunar Schorcht
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
#ifndef TUSB_CONFIG_H
|
||||
#define TUSB_CONFIG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* By default, the number of `CFG_TUD_*` device class and `CFG_TUH_*`
|
||||
* host class interfaces is defined to 1 if the corresponding `tinyusb_class_*`
|
||||
* and `tinyusb_device`/`tinyusb_host` module are enabled, and 0 otherwise.
|
||||
* That is, there is one interface of each class.
|
||||
*
|
||||
* For example, if the `tinyusb_device` and `tinyusb_class_cdc` modules are
|
||||
* enabled, `CFG_TUD_CDC` is defined to 1 by default. The number of all other
|
||||
* `CFG_TUD_*` device class interfaces are 0.
|
||||
*
|
||||
* To define a different number of device class or host class interfaces,
|
||||
* just define them here to override these default values, for example:
|
||||
* ```c
|
||||
* #define CFG_TUD_CDC 2
|
||||
* #define CFG_TUD_HID 3
|
||||
* ```
|
||||
*/
|
||||
|
||||
/* Default configuration defined by RIOT package tinyUSB has to be included last */
|
||||
#include "tinyusb_config.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* TUSB_CONFIG_H */
|
340
tests/pkg_tinyusb_cdc_msc/usb_descriptors.c
Normal file
340
tests/pkg_tinyusb_cdc_msc/usb_descriptors.c
Normal file
@ -0,0 +1,340 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Ha Thach (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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "tusb.h"
|
||||
|
||||
#ifdef CONFIG_USB_PID
|
||||
#define USB_PID CONFIG_USB_PID
|
||||
#else
|
||||
/*
|
||||
* 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] VIDEO | AUDIO | MIDI | 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) \
|
||||
| _PID_MAP(MIDI, 3) \
|
||||
| _PID_MAP(AUDIO, 4) \
|
||||
| _PID_MAP(VIDEO, 5) )
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_VID
|
||||
#define USB_VID CONFIG_USB_VID
|
||||
#else
|
||||
#error USB_VID has to be defined
|
||||
#endif
|
||||
|
||||
#define USB_BCD 0x0200
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------------+
|
||||
* Device Descriptors
|
||||
* --------------------------------------------------------------------+
|
||||
*/
|
||||
static tusb_desc_device_t const desc_device = {
|
||||
.bLength = sizeof(tusb_desc_device_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE,
|
||||
.bcdUSB = USB_BCD,
|
||||
|
||||
/* 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,
|
||||
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
|
||||
.idVendor = USB_VID,
|
||||
.idProduct = USB_PID,
|
||||
.bcdDevice = 0x0100,
|
||||
|
||||
.iManufacturer = 0x01,
|
||||
.iProduct = 0x02,
|
||||
.iSerialNumber = 0x03,
|
||||
|
||||
.bNumConfigurations = 0x01
|
||||
};
|
||||
|
||||
/*
|
||||
* Invoked when received GET DEVICE DESCRIPTOR
|
||||
* Application return pointer to descriptor
|
||||
*/
|
||||
uint8_t const *tud_descriptor_device_cb(void)
|
||||
{
|
||||
return (uint8_t const *)&desc_device;
|
||||
}
|
||||
|
||||
/*
|
||||
*--------------------------------------------------------------------+
|
||||
* Configuration Descriptor
|
||||
*--------------------------------------------------------------------+
|
||||
*/
|
||||
enum {
|
||||
ITF_NUM_CDC = 0,
|
||||
ITF_NUM_CDC_DATA,
|
||||
ITF_NUM_MSC,
|
||||
ITF_NUM_TOTAL
|
||||
};
|
||||
|
||||
#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, 5 Bulk etc ...
|
||||
*/
|
||||
#define EPNUM_CDC_NOTIF 0x81
|
||||
#define EPNUM_CDC_OUT 0x02
|
||||
#define EPNUM_CDC_IN 0x82
|
||||
|
||||
#define EPNUM_MSC_OUT 0x05
|
||||
#define EPNUM_MSC_IN 0x85
|
||||
|
||||
#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAMX7X
|
||||
/*
|
||||
* SAMG & SAME70 don't support a same endpoint number with different
|
||||
* direction IN and OUT, e.g EP1 OUT & EP1 IN cannot exist together
|
||||
*/
|
||||
#define EPNUM_CDC_NOTIF 0x81
|
||||
#define EPNUM_CDC_OUT 0x02
|
||||
#define EPNUM_CDC_IN 0x83
|
||||
|
||||
#define EPNUM_MSC_OUT 0x04
|
||||
#define EPNUM_MSC_IN 0x85
|
||||
|
||||
#elif CFG_TUSB_MCU == OPT_MCU_CXD56
|
||||
/*
|
||||
* CXD56 doesn't support a same endpoint number with different direction IN
|
||||
* and OUT, e.g EP1 OUT & EP1 IN cannot exist together
|
||||
* CXD56 USB driver has fixed endpoint type (bulk/interrupt/iso) and
|
||||
* direction (IN/OUT) by its number
|
||||
* 0 control (IN/OUT), 1 Bulk (IN), 2 Bulk (OUT), 3 In (IN), 4 Bulk (IN),
|
||||
* 5 Bulk (OUT), 6 In (IN)
|
||||
*/
|
||||
#define EPNUM_CDC_NOTIF 0x83
|
||||
#define EPNUM_CDC_OUT 0x02
|
||||
#define EPNUM_CDC_IN 0x81
|
||||
|
||||
#define EPNUM_MSC_OUT 0x05
|
||||
#define EPNUM_MSC_IN 0x84
|
||||
|
||||
#elif CFG_TUSB_MCU == OPT_MCU_FT90X || CFG_TUSB_MCU == OPT_MCU_FT93X
|
||||
/*
|
||||
* FT9XX doesn't support a same endpoint number with different direction
|
||||
* IN and OUT, e.g EP1 OUT & EP1 IN cannot exist together
|
||||
*/
|
||||
#define EPNUM_CDC_NOTIF 0x81
|
||||
#define EPNUM_CDC_OUT 0x02
|
||||
#define EPNUM_CDC_IN 0x83
|
||||
|
||||
#define EPNUM_MSC_OUT 0x04
|
||||
#define EPNUM_MSC_IN 0x85
|
||||
|
||||
#else
|
||||
#define EPNUM_CDC_NOTIF 0x81
|
||||
#define EPNUM_CDC_OUT 0x02
|
||||
#define EPNUM_CDC_IN 0x82
|
||||
|
||||
#define EPNUM_MSC_OUT 0x03
|
||||
#define EPNUM_MSC_IN 0x83
|
||||
|
||||
#endif
|
||||
|
||||
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_MSC_DESC_LEN)
|
||||
|
||||
/* full speed configuration */
|
||||
uint8_t const desc_fs_configuration[] = {
|
||||
/* Config number, interface count, string index, total length, attribute,
|
||||
* power in mA */
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
|
||||
|
||||
/* Interface number, string index, EP notification address and size, EP data
|
||||
* address (out, in) and size. */
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64),
|
||||
|
||||
/* Interface number, string index, EP Out & EP In address, EP size */
|
||||
TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 64),
|
||||
};
|
||||
|
||||
#if TUD_OPT_HIGH_SPEED
|
||||
/* Per USB specs: high speed capable device must report device_qualifier
|
||||
* and other_speed_configuration */
|
||||
|
||||
/* high speed configuration */
|
||||
uint8_t const desc_hs_configuration[] =
|
||||
{
|
||||
/* Config number, interface count, string index, total length, attribute,
|
||||
* power in mA */
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
|
||||
|
||||
/* Interface number, string index, EP notification address and size, EP data
|
||||
* address (out, in) and size. */
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 512),
|
||||
|
||||
/* Interface number, string index, EP Out & EP In address, EP size */
|
||||
TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 512),
|
||||
};
|
||||
|
||||
/* other speed configuration */
|
||||
uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN];
|
||||
|
||||
/* device qualifier is mostly similar to device descriptor since we don't
|
||||
* change configuration based on speed */
|
||||
tusb_desc_device_qualifier_t const desc_device_qualifier = {
|
||||
.bLength = sizeof(tusb_desc_device_qualifier_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER,
|
||||
.bcdUSB = USB_BCD,
|
||||
|
||||
.bDeviceClass = TUSB_CLASS_MISC,
|
||||
.bDeviceSubClass = MISC_SUBCLASS_COMMON,
|
||||
.bDeviceProtocol = MISC_PROTOCOL_IAD,
|
||||
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
.bNumConfigurations = 0x01,
|
||||
.bReserved = 0x00
|
||||
};
|
||||
|
||||
/*
|
||||
* Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request
|
||||
* Application return pointer to descriptor, whose contents must exist long
|
||||
* enough for transfer to complete. Device_qualifier descriptor describes
|
||||
* information about a high-speed capable device that would change if the
|
||||
* device were operating at the other speed. If not highspeed capable stall
|
||||
* this request.
|
||||
*/
|
||||
uint8_t const* tud_descriptor_device_qualifier_cb(void)
|
||||
{
|
||||
return (uint8_t const*)&desc_device_qualifier;
|
||||
}
|
||||
|
||||
/*
|
||||
* Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request
|
||||
* Application return pointer to descriptor, whose contents must exist long
|
||||
* enough for transfer to complete. Configuration descriptor in the other
|
||||
* speed e.g if high speed then this is for full speed and vice versa
|
||||
*/
|
||||
uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index)
|
||||
{
|
||||
(void)index; /* for multiple configurations */
|
||||
|
||||
/* if link speed is high return fullspeed config, and vice versa
|
||||
* Note: the descriptor type is OHER_SPEED_CONFIG instead of CONFIG */
|
||||
memcpy(desc_other_speed_config,
|
||||
(tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration
|
||||
: desc_hs_configuration,
|
||||
CONFIG_TOTAL_LEN);
|
||||
|
||||
desc_other_speed_config[1] = TUSB_DESC_OTHER_SPEED_CONFIG;
|
||||
|
||||
return desc_other_speed_config;
|
||||
}
|
||||
|
||||
#endif /* highspeed */
|
||||
|
||||
/*
|
||||
* Invoked when received GET CONFIGURATION DESCRIPTOR
|
||||
* Application return pointer to descriptor
|
||||
* Descriptor contents must exist long enough for transfer to complete
|
||||
*/
|
||||
uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
|
||||
{
|
||||
(void)index; /* for multiple configurations */
|
||||
|
||||
#if TUD_OPT_HIGH_SPEED
|
||||
/* Although we are highspeed, host may be fullspeed. */
|
||||
return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_hs_configuration
|
||||
: desc_fs_configuration;
|
||||
#else
|
||||
return desc_fs_configuration;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
*--------------------------------------------------------------------+
|
||||
* String Descriptors
|
||||
*--------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* array of pointer to string descriptors */
|
||||
char const* string_desc_arr [] = {
|
||||
(const char[]){ 0x09, 0x04 }, /* 0: is supported language is English (0x0409) */
|
||||
"RIOT-OS", /* 1: Manufacturer */
|
||||
"TinyUSB Device", /* 2: Product */
|
||||
"123456789012", /* 3: Serials, should use chip ID */
|
||||
"TinyUSB CDC", /* 4: CDC Interface */
|
||||
"TinyUSB MSC", /* 5: MSC Interface */
|
||||
};
|
||||
|
||||
static uint16_t _desc_str[32];
|
||||
|
||||
/*
|
||||
* Invoked when received GET STRING DESCRIPTOR request
|
||||
* Application return pointer to descriptor, whose contents must exist long
|
||||
* enough for transfer to complete.
|
||||
*/
|
||||
uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid)
|
||||
{
|
||||
(void)langid;
|
||||
|
||||
uint8_t chr_count;
|
||||
|
||||
if ( index == 0) {
|
||||
memcpy(&_desc_str[1], string_desc_arr[0], 2);
|
||||
chr_count = 1;
|
||||
}
|
||||
else {
|
||||
/* Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors.
|
||||
* https: *docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors
|
||||
*/
|
||||
|
||||
if (!(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0]))) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* str = string_desc_arr[index];
|
||||
|
||||
/* Cap at max char */
|
||||
chr_count = (uint8_t) strlen(str);
|
||||
if (chr_count > 31) {
|
||||
chr_count = 31;
|
||||
}
|
||||
|
||||
/* Convert ASCII string into UTF-16 */
|
||||
for (uint8_t i=0; i<chr_count; i++) {
|
||||
_desc_str[1+i] = str[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* first byte is length (including header), second byte is string type */
|
||||
_desc_str[0] = (uint16_t)((TUSB_DESC_STRING << 8 ) | (2*chr_count + 2));
|
||||
|
||||
return _desc_str;
|
||||
}
|
Loading…
Reference in New Issue
Block a user