Merge branch 'master' into rp2040epaddr

This commit is contained in:
majbthrd 2021-02-25 09:15:42 -06:00 committed by GitHub
commit efea18a888
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
50 changed files with 531 additions and 3595 deletions

View File

@ -1,6 +1,6 @@
# TinyUSB
![tinyUSB_240x100](https://user-images.githubusercontent.com/249515/62646655-f9393200-b978-11e9-9c53-484862f15503.png)
![TinyUSB](https://user-images.githubusercontent.com/2847802/108847382-a0a6a580-75ad-11eb-96d9-280c79389281.png)
[![Build Status](https://github.com/hathach/tinyusb/workflows/Build/badge.svg)](https://github.com/hathach/tinyusb/actions) [![License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](https://opensource.org/licenses/MIT)

View File

@ -239,9 +239,10 @@ void tud_hid_report_complete_cb(uint8_t itf, uint8_t const* report, uint8_t len)
// Invoked when received GET_REPORT control request
// Application must fill buffer report's content and return its length.
// Return zero will cause the stack to STALL request
uint16_t tud_hid_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 itf, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen)
{
// TODO not Implemented
(void) itf;
(void) report_id;
(void) report_type;
(void) buffer;
@ -252,9 +253,10 @@ uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type,
// Invoked when received SET_REPORT control request or
// received data on OUT endpoint ( Report ID = 0, Type = 0 )
void tud_hid_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 itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize)
{
// TODO set LED based on CAPLOCK, NUMLOCK etc...
(void) itf;
(void) report_id;
(void) report_type;
(void) buffer;

View File

@ -82,8 +82,9 @@ uint8_t const desc_hid_report[] =
// Invoked when received GET HID REPORT DESCRIPTOR
// Application return pointer to descriptor
// Descriptor contents must exist long enough for transfer to complete
uint8_t const * tud_hid_descriptor_report_cb(void)
uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf)
{
(void) itf;
return desc_hid_report;
}

View File

@ -299,9 +299,10 @@ void tud_hid_report_complete_cb(uint8_t itf, uint8_t const* report, uint8_t len)
// Invoked when received GET_REPORT control request
// Application must fill buffer report's content and return its length.
// Return zero will cause the stack to STALL request
uint16_t tud_hid_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 itf, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen)
{
// TODO not Implemented
(void) itf;
(void) report_id;
(void) report_type;
(void) buffer;
@ -312,9 +313,10 @@ uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type,
// Invoked when received SET_REPORT control request or
// received data on OUT endpoint ( Report ID = 0, Type = 0 )
void tud_hid_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 itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize)
{
// TODO set LED based on CAPLOCK, NUMLOCK etc...
(void) itf;
(void) report_id;
(void) report_type;
(void) buffer;

View File

@ -82,8 +82,9 @@ uint8_t const desc_hid_report[] =
// Invoked when received GET HID REPORT DESCRIPTOR
// Application return pointer to descriptor
// Descriptor contents must exist long enough for transfer to complete
uint8_t const * tud_hid_descriptor_report_cb(void)
uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf)
{
(void) itf;
return desc_hid_report;
}

View File

@ -121,9 +121,10 @@ void tud_resume_cb(void)
// Invoked when received GET_REPORT control request
// Application must fill buffer report's content and return its length.
// Return zero will cause the stack to STALL request
uint16_t tud_hid_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 itf, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen)
{
// TODO not Implemented
(void) itf;
(void) report_id;
(void) report_type;
(void) buffer;
@ -134,9 +135,10 @@ uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type,
// Invoked when received SET_REPORT control request or
// received data on OUT endpoint ( Report ID = 0, Type = 0 )
void tud_hid_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 itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize)
{
// This example doesn't use multiple report and report ID
(void) itf;
(void) report_id;
(void) report_type;

View File

@ -78,8 +78,9 @@ uint8_t const desc_hid_report[] =
// Invoked when received GET HID REPORT DESCRIPTOR
// Application return pointer to descriptor
// Descriptor contents must exist long enough for transfer to complete
uint8_t const * tud_hid_descriptor_report_cb(void)
uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf)
{
(void) itf;
return desc_hid_report;
}

View File

@ -19,9 +19,9 @@ SRC_C += \
src/host/hub.c \
src/host/usbh.c \
src/host/usbh_control.c \
src/host/ehci/ehci.c \
src/host/ohci/ohci.c \
src/portable/nxp/lpc18_43/hcd_lpc18_43.c \
src/portable/ehci/ehci.c \
src/portable/ohci/ohci.c \
src/portable/nxp/transdimension/hcd_transdimension.c \
src/portable/nxp/lpc17_40/hcd_lpc17_40.c
include ../../rules.mk

View File

@ -31,31 +31,6 @@
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
//--------------------------------------------------------------------+
static scsi_inquiry_resp_t inquiry_resp;
static scsi_read_capacity10_resp_t capacity_resp;
uint32_t block_size;
uint32_t block_count;
bool capacity_complete_cb(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw)
{
(void) dev_addr;
(void) cbw;
if (csw->status != 0)
{
printf("Read Capacity (10) failed\r\n");
return false;
}
// Capacity response field: Block size and Last LBA are both Big-Endian
block_count = tu_ntohl(capacity_resp.last_lba) + 1;
block_size = tu_ntohl(capacity_resp.block_size);
printf("Disk Size: %lu MB\r\n", block_count / ((1024*1024)/block_size));
printf("Block Count = %lu, Block Size: %lu\r\n", block_count, block_size);
return true;
}
bool inquiry_complete_cb(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw)
{
@ -68,21 +43,23 @@ bool inquiry_complete_cb(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const
// Print out Vendor ID, Product ID and Rev
printf("%.8s %.16s rev %.4s\r\n", inquiry_resp.vendor_id, inquiry_resp.product_id, inquiry_resp.product_rev);
// Read capacity of device
tuh_msc_read_capacity(dev_addr, cbw->lun, &capacity_resp, capacity_complete_cb);
// Get capacity of device
uint32_t const block_count = tuh_msc_get_block_count(dev_addr, cbw->lun);
uint32_t const block_size = tuh_msc_get_block_size(dev_addr, cbw->lun);
printf("Disk Size: %lu MB\r\n", block_count / ((1024*1024)/block_size));
printf("Block Count = %lu, Block Size: %lu\r\n", block_count, block_size);
return true;
}
//------------- IMPLEMENTATION -------------//
void tuh_msc_mounted_cb(uint8_t dev_addr)
void tuh_msc_mount_cb(uint8_t dev_addr)
{
printf("A MassStorage device is mounted\r\n");
block_size = block_count = 0;
uint8_t const lun = 0;
tuh_msc_scsi_inquiry(dev_addr, lun, &inquiry_resp, inquiry_complete_cb);
tuh_msc_inquiry(dev_addr, lun, &inquiry_resp, inquiry_complete_cb);
//
// //------------- file system (only 1 LUN support) -------------//
// uint8_t phy_disk = dev_addr-1;
@ -96,13 +73,6 @@ void tuh_msc_mounted_cb(uint8_t dev_addr)
// return;
// }
//
// puts("---------------------------------------------------------------------");
// puts("- MASSSTORAGE CLASS CLI IS A IMMATURE CODE. DISK-WRITING COMMANDS");
// puts("- SUCH AS cp(COPY), mkdir(MAKE DIRECTORY) ARE POTENTIAL TO DAMAGE");
// puts("- YOUR USB THUMBDRIVE. USING THOSE COMMANDS ARE AT YOUR OWN RISK.");
// puts("- THE AUTHOR HAS NO RESPONSIBILITY WITH YOUR DEVICE NOR ITS DATA");
// puts("---------------------------------------------------------------------");
//
// f_chdrive(phy_disk); // change to newly mounted drive
// f_chdir("/"); // root as current dir
//
@ -110,7 +80,7 @@ void tuh_msc_mounted_cb(uint8_t dev_addr)
// }
}
void tuh_msc_unmounted_cb(uint8_t dev_addr)
void tuh_msc_unmount_cb(uint8_t dev_addr)
{
(void) dev_addr;
printf("A MassStorage device is unmounted\r\n");
@ -133,11 +103,4 @@ void tuh_msc_unmounted_cb(uint8_t dev_addr)
// }
}
//void tuh_msc_scsi_complete_cb(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw)
//{
// (void) dev_addr;
// (void) cbw;
// (void) csw;
//}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,129 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>host_os_none</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
<triggers>clean,full,incremental,</triggers>
<arguments>
<dictionary>
<key>?name?</key>
<value></value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.append_environment</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.autoBuildTarget</key>
<value>all</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.buildArguments</key>
<value></value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.buildCommand</key>
<value>make</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.buildLocation</key>
<value>${workspace_loc:/host/Debug}</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.cleanBuildTarget</key>
<value>clean</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.contents</key>
<value>org.eclipse.cdt.make.core.activeConfigSettings</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.enableAutoBuild</key>
<value>false</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.enableCleanBuild</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.enableFullBuild</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.fullBuildTarget</key>
<value>all</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.stopOnError</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key>
<value>true</value>
</dictionary>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.cdt.core.cnature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
</natures>
<linkedResources>
<link>
<name>boards</name>
<type>2</type>
<locationURI>PARENT-3-PROJECT_LOC/boards</locationURI>
</link>
<link>
<name>fatfs</name>
<type>2</type>
<locationURI>PARENT-3-PROJECT_LOC/vendor/fatfs</locationURI>
</link>
<link>
<name>mcu</name>
<type>2</type>
<locationURI>PARENT-3-PROJECT_LOC/mcu</locationURI>
</link>
<link>
<name>src</name>
<type>2</type>
<locationURI>PARENT-1-PROJECT_LOC/src</locationURI>
</link>
<link>
<name>tinyusb</name>
<type>2</type>
<locationURI>PARENT-3-PROJECT_LOC/tinyusb</locationURI>
</link>
</linkedResources>
<filteredResources>
<filter>
<id>1394685086167</id>
<name>mcu</name>
<type>26</type>
<matcher>
<id>org.eclipse.ui.ide.multiFilter</id>
<arguments>1.0-name-matches-false-false-iar</arguments>
</matcher>
</filter>
<filter>
<id>1394685086182</id>
<name>mcu</name>
<type>26</type>
<matcher>
<id>org.eclipse.ui.ide.multiFilter</id>
<arguments>1.0-name-matches-false-false-keil</arguments>
</matcher>
</filter>
</filteredResources>
</projectDescription>

View File

@ -1,70 +0,0 @@
/*
* 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.
*
* This file is part of the TinyUSB stack.
*/
/** \ingroup TBD
* \defgroup TBD
* \brief TBD
*
* @{
*/
#ifndef _TUSB_APP_OS_PRIO_H_
#define _TUSB_APP_OS_PRIO_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "tusb.h"
#if CFG_TUSB_OS == OPT_OS_NONE
#define LOWER_PRIO(x) 0 // does not matter
#elif CFG_TUSB_OS == OPT_OS_FREERTOS
#define LOWER_PRIO(x) ((x)-1) // freeRTOS lower number --> lower priority
#elif CFG_TUSB_OS == TUSB_OS_CMSIS_RTX
#define LOWER_PRIO(x) ((x)-1) // CMSIS-RTOS lower number --> lower priority
#else
#error Priority is not configured for this RTOS
#endif
enum {
STANDARD_APP_TASK_PRIO = LOWER_PRIO(CFG_TUD_TASK_PRIO), // Application Task is lower than usb system task
LED_BLINKING_APP_TASK_PRIO = LOWER_PRIO(STANDARD_APP_TASK_PRIO), // Blinking task is lower than normal task
KEYBOARD_APP_TASK_PRIO = STANDARD_APP_TASK_PRIO,
MOUSE_APP_TASK_PRIO = STANDARD_APP_TASK_PRIO,
CDC_SERIAL_APP_TASK_PRIO = STANDARD_APP_TASK_PRIO,
MSC_APP_TASK_PRIO = STANDARD_APP_TASK_PRIO
};
#ifdef __cplusplus
}
#endif
#endif /* _TUSB_APP_OS_PRIO_H_ */
/** @} */

View File

@ -1,157 +0,0 @@
/*
* 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.
*
* This file is part of the TinyUSB stack.
*/
#include "cdc_serial_host_app.h"
#include "app_os_prio.h"
#if CFG_TUH_CDC
#define QUEUE_SERIAL_DEPTH 100
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
static osal_semaphore_t sem_hdl;
enum { SERIAL_BUFFER_SIZE = 64 };
CFG_TUSB_MEM_SECTION static uint8_t serial_in_buffer[SERIAL_BUFFER_SIZE];
CFG_TUSB_MEM_SECTION static uint8_t serial_out_buffer[SERIAL_BUFFER_SIZE];
static uint8_t received_bytes; // set by transfer complete callback
//--------------------------------------------------------------------+
// tinyusb callbacks
//--------------------------------------------------------------------+
void tuh_cdc_mounted_cb(uint8_t dev_addr)
{ // application set-up
printf("\na CDC device (address %d) is mounted\n", dev_addr);
tu_memclr(serial_in_buffer, sizeof(serial_in_buffer));
tu_memclr(serial_out_buffer, sizeof(serial_out_buffer));
received_bytes = 0;
osal_semaphore_reset(sem_hdl);
tuh_cdc_receive(dev_addr, serial_in_buffer, SERIAL_BUFFER_SIZE, true); // schedule first transfer
}
void tuh_cdc_unmounted_cb(uint8_t dev_addr)
{ // application tear-down
printf("\na CDC device (address %d) is unmounted \n", dev_addr);
}
// invoked ISR context
void tuh_cdc_xfer_isr(uint8_t dev_addr, xfer_result_t event, cdc_pipeid_t pipe_id, uint32_t xferred_bytes)
{
(void) dev_addr; // compiler warnings
switch ( pipe_id )
{
case CDC_PIPE_DATA_IN:
switch(event)
{
case XFER_RESULT_SUCCESS:
received_bytes = xferred_bytes;
osal_semaphore_post(sem_hdl); // notify main task
break;
case XFER_RESULT_FAILED:
received_bytes = 0; // ignore
tuh_cdc_receive(dev_addr, serial_in_buffer, SERIAL_BUFFER_SIZE, true); // waiting for next data
break;
case XFER_RESULT_STALLED:
default :
break;
}
break;
case CDC_PIPE_DATA_OUT:
case CDC_PIPE_NOTIFICATION:
default:
break;
}
}
//--------------------------------------------------------------------+
// APPLICATION
//--------------------------------------------------------------------+
void cdc_serial_host_app_init(void)
{
sem_hdl = osal_semaphore_create(1, 0);
TU_ASSERT( sem_hdl, VOID_RETURN);
TU_VERIFY( osal_task_create(cdc_serial_host_app_task, "cdc", 128, NULL, CDC_SERIAL_APP_TASK_PRIO), );
}
//------------- main task -------------//
void cdc_serial_host_app_task( void* param )
{
(void) param;
OSAL_TASK_BEGIN
//------------- send characters got from uart terminal to the first CDC device -------------//
for(uint8_t dev_addr=1; dev_addr <= CFG_TUSB_HOST_DEVICE_MAX; dev_addr++)
{
if ( tuh_cdc_serial_is_mounted(dev_addr) )
{
int ch_tx = getchar();
if ( ch_tx > 0 )
{ // USB is much faster than serial, here we assume usb is always complete. There could be some characters missing though
serial_out_buffer[0] = (uint8_t) ch_tx;
if ( !tuh_cdc_is_busy(dev_addr, CDC_PIPE_DATA_OUT) )
{
tuh_cdc_send(dev_addr, serial_out_buffer, 1, false); // no need for callback on serial out pipe
}
}
break; // demo app only communicate with the first CDC-capable device
}
}
//------------- print out received characters -------------//
tusb_error_t error;
osal_semaphore_wait(sem_hdl, 100, &error); // waiting for incoming data
if ( TUSB_ERROR_NONE == error)
{
for(uint8_t i=0; i<received_bytes; i++) putchar(serial_in_buffer[i]);
for(uint8_t dev_addr=1; dev_addr <= CFG_TUSB_HOST_DEVICE_MAX; dev_addr++)
{
if ( tuh_cdc_serial_is_mounted(dev_addr) )
{
tuh_cdc_receive(dev_addr, serial_in_buffer, SERIAL_BUFFER_SIZE, true);
break; // demo app only communicate with the first CDC-capable device
}
}
}
OSAL_TASK_END
}
#endif

View File

@ -1,62 +0,0 @@
/*
* 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.
*
* This file is part of the TinyUSB stack.
*/
/** \ingroup TBD
* \defgroup TBD
* \brief TBD
*
* @{
*/
#ifndef _TUSB_CDC_SERIAL_HOST_APP_H_
#define _TUSB_CDC_SERIAL_HOST_APP_H_
#include "board.h"
#include "tusb.h"
#ifdef __cplusplus
extern "C" {
#endif
#if CFG_TUH_CDC
void cdc_serial_host_app_init(void);
void cdc_serial_host_app_task(void* param);
#else
#define cdc_serial_host_app_init()
#define cdc_serial_host_app_task(x)
#endif
#ifdef __cplusplus
}
#endif
#endif /* _TUSB_CDC_SERIAL_HOST_APP_H_ */
/** @} */

View File

@ -1,164 +0,0 @@
/*
* 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.
*
* This file is part of the TinyUSB stack.
*/
//--------------------------------------------------------------------+
// INCLUDE
//--------------------------------------------------------------------+
#include "keyboard_host_app.h"
#include "app_os_prio.h"
#if CFG_TUH_HID_KEYBOARD
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
#define QUEUE_KEYBOARD_REPORT_DEPTH 4
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
static osal_queue_t queue_kbd_hdl;
CFG_TUSB_MEM_SECTION static hid_keyboard_report_t usb_keyboard_report;
static inline uint8_t keycode_to_ascii(uint8_t modifier, uint8_t keycode);
static inline void process_kbd_report(hid_keyboard_report_t const * report);
//--------------------------------------------------------------------+
// tinyusb callbacks
//--------------------------------------------------------------------+
void tuh_hid_keyboard_mounted_cb(uint8_t dev_addr)
{
// application set-up
printf("\na Keyboard device (address %d) is mounted\n", dev_addr);
osal_queue_flush(queue_kbd_hdl);
tuh_hid_keyboard_get_report(dev_addr, (uint8_t*) &usb_keyboard_report); // first report
}
void tuh_hid_keyboard_unmounted_cb(uint8_t dev_addr)
{
// application tear-down
printf("\na Keyboard device (address %d) is unmounted\n", dev_addr);
}
// invoked ISR context
void tuh_hid_keyboard_isr(uint8_t dev_addr, xfer_result_t event)
{
switch(event)
{
case XFER_RESULT_SUCCESS:
osal_queue_send(queue_kbd_hdl, &usb_keyboard_report);
tuh_hid_keyboard_get_report(dev_addr, (uint8_t*) &usb_keyboard_report);
break;
case XFER_RESULT_FAILED:
tuh_hid_keyboard_get_report(dev_addr, (uint8_t*) &usb_keyboard_report); // ignore & continue
break;
default :
break;
}
}
//--------------------------------------------------------------------+
// APPLICATION
//--------------------------------------------------------------------+
void keyboard_host_app_init(void)
{
tu_memclr(&usb_keyboard_report, sizeof(hid_keyboard_report_t));
queue_kbd_hdl = osal_queue_create( QUEUE_KEYBOARD_REPORT_DEPTH, sizeof(hid_keyboard_report_t) );
TU_ASSERT( queue_kbd_hdl, VOID_RETURN );
TU_VERIFY( osal_task_create(keyboard_host_app_task, "kbd", 128, NULL, KEYBOARD_APP_TASK_PRIO), );
}
//------------- main task -------------//
void keyboard_host_app_task(void* param)
{
(void) param;
OSAL_TASK_BEGIN
hid_keyboard_report_t kbd_report;
tusb_error_t error;
osal_queue_receive(queue_kbd_hdl, &kbd_report, OSAL_TIMEOUT_WAIT_FOREVER, &error);
(void) error; // suppress compiler warning
process_kbd_report(&kbd_report);
OSAL_TASK_END
}
//--------------------------------------------------------------------+
// HELPER
//--------------------------------------------------------------------+
// look up new key in previous keys
static inline bool find_key_in_report(hid_keyboard_report_t const *p_report, uint8_t keycode)
{
for(uint8_t i=0; i<6; i++)
{
if (p_report->keycode[i] == keycode) return true;
}
return false;
}
static inline void process_kbd_report(hid_keyboard_report_t const *p_new_report)
{
static hid_keyboard_report_t prev_report = { 0, 0, {0} }; // previous report to check key released
//------------- example code ignore control (non-printable) key affects -------------//
for(uint8_t i=0; i<6; i++)
{
if ( p_new_report->keycode[i] )
{
if ( find_key_in_report(&prev_report, p_new_report->keycode[i]) )
{
// exist in previous report means the current key is holding
}else
{
// not existed in previous report means the current key is pressed
uint8_t ch = keycode_to_ascii(p_new_report->modifier, p_new_report->keycode[i]);
putchar(ch);
if ( ch == '\r' ) putchar('\n'); // added new line for enter key
}
}
// TODO example skips key released
}
prev_report = *p_new_report;
}
static inline uint8_t keycode_to_ascii(uint8_t modifier, uint8_t keycode)
{
// TODO max of keycode_ascii_tbl
return keycode > 128 ? 0 :
hid_keycode_to_ascii_tbl [modifier & (KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT) ? 1 : 0] [keycode];
}
#endif

View File

@ -1,68 +0,0 @@
/*
* 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.
*
* This file is part of the TinyUSB stack.
*/
/** \file
* \brief TBD
*
* \note TBD
*/
/** \ingroup TBD
* \defgroup TBD
* \brief TBD
*
* @{
*/
#ifndef _TUSB_KEYBOARD_HOST_APP_H_
#define _TUSB_KEYBOARD_HOST_APP_H_
#include "board.h"
#include "tusb.h"
#ifdef __cplusplus
extern "C" {
#endif
#if CFG_TUH_HID_KEYBOARD
void keyboard_host_app_init(void);
void keyboard_host_app_task(void* param);
#else
#define keyboard_host_app_init()
#define keyboard_host_app_task(x)
#endif
#ifdef __cplusplus
}
#endif
#endif /* _TUSB_KEYBOARD_HOST_APP_H_ */
/** @} */

View File

@ -1,131 +0,0 @@
/*
* 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.
*
* This file is part of the TinyUSB stack.
*/
//--------------------------------------------------------------------+
// INCLUDE
//--------------------------------------------------------------------+
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "board.h"
#include "tusb.h"
#include "mouse_host_app.h"
#include "keyboard_host_app.h"
#include "msc_host_app.h"
#include "cdc_serial_host_app.h"
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
void print_greeting(void);
//--------------------------------------------------------------------+
// IMPLEMENTATION
//--------------------------------------------------------------------+
#if CFG_TUSB_OS == OPT_OS_NONE
// like a real RTOS, this function is a main loop invoking each task in application and never return
void os_none_start_scheduler(void)
{
while (1)
{
tusb_task();
led_blinking_task(NULL);
keyboard_host_app_task(NULL);
mouse_host_app_task(NULL);
msc_host_app_task(NULL);
cdc_serial_host_app_task(NULL);
}
}
#endif
int main(void)
{
#if CFG_TUSB_OS == TUSB_OS_CMSIS_RTX
osKernelInitialize(); // CMSIS RTX requires kernel init before any other OS functions
#endif
board_init();
print_greeting();
tusb_init();
//------------- application task init -------------//
led_blinking_init();
keyboard_host_app_init();
mouse_host_app_init();
msc_host_app_init();
cdc_serial_host_app_init();
//------------- start OS scheduler (never return) -------------//
#if CFG_TUSB_OS == OPT_OS_FREERTOS
vTaskStartScheduler();
#elif CFG_TUSB_OS == OPT_OS_NONE
os_none_start_scheduler();
#elif CFG_TUSB_OS == TUSB_OS_CMSIS_RTX
osKernelStart();
#else
#error need to start RTOS schduler
#endif
return 0;
}
//--------------------------------------------------------------------+
// HELPER FUNCTION
//--------------------------------------------------------------------+
void print_greeting(void)
{
char const * const rtos_name[] =
{
[OPT_OS_NONE] = "None",
[OPT_OS_FREERTOS] = "FreeRTOS",
};
puts("\n\
--------------------------------------------------------------------\n\
- Host Demo (a tinyusb example)\n\
- if you find any bugs or get any questions, feel free to file an\n\
- issue at https://github.com/hathach/tinyusb\n\
--------------------------------------------------------------------\n"
);
puts("This HOST demo is configured to support:");
printf(" - RTOS = %s\n", rtos_name[CFG_TUSB_OS]);
if (CFG_TUH_HUB ) puts(" - Hub (1 level only)");
if (CFG_TUH_HID_MOUSE ) puts(" - HID Mouse");
if (CFG_TUH_HID_KEYBOARD ) puts(" - HID Keyboard");
if (CFG_TUH_MSC ) puts(" - Mass Storage");
if (CFG_TUH_CDC ) puts(" - Communication Device Class");
}

View File

@ -1,169 +0,0 @@
/*
* 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.
*
* This file is part of the TinyUSB stack.
*/
//--------------------------------------------------------------------+
// INCLUDE
//--------------------------------------------------------------------+
#include "mouse_host_app.h"
#include "app_os_prio.h"
#if CFG_TUH_HID_MOUSE
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
#define QUEUE_MOUSE_REPORT_DEPTH 4
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
static osal_queue_t queue_mouse_hdl;
CFG_TUSB_MEM_SECTION static hid_mouse_report_t usb_mouse_report;
static inline void process_mouse_report(hid_mouse_report_t const * p_report);
//--------------------------------------------------------------------+
// tinyusb callbacks
//--------------------------------------------------------------------+
void tuh_hid_mouse_mounted_cb(uint8_t dev_addr)
{
// application set-up
printf("\na Mouse device (address %d) is mounted\n", dev_addr);
osal_queue_flush(queue_mouse_hdl);
(void) tuh_hid_mouse_get_report(dev_addr, (uint8_t*) &usb_mouse_report); // first report
}
void tuh_hid_mouse_unmounted_cb(uint8_t dev_addr)
{
// application tear-down
printf("\na Mouse device (address %d) is unmounted\n", dev_addr);
}
// invoked ISR context
void tuh_hid_mouse_isr(uint8_t dev_addr, xfer_result_t event)
{
switch(event)
{
case XFER_RESULT_SUCCESS:
osal_queue_send(queue_mouse_hdl, &usb_mouse_report);
(void) tuh_hid_mouse_get_report(dev_addr, (uint8_t*) &usb_mouse_report);
break;
case XFER_RESULT_FAILED:
(void) tuh_hid_mouse_get_report(dev_addr, (uint8_t*) &usb_mouse_report); // ignore & continue
break;
default :
break;
}
}
//--------------------------------------------------------------------+
// APPLICATION CODE
// NOTICE: MOUSE REPORT IS NOT CORRECT UNTIL A DECENT HID PARSER IS
// IMPLEMENTED, MEANWHILE IT CAN MISS DISPLAY BUTTONS OR X,Y etc
//--------------------------------------------------------------------+
void mouse_host_app_init(void)
{
tu_memclr(&usb_mouse_report, sizeof(hid_mouse_report_t));
queue_mouse_hdl = osal_queue_create( QUEUE_MOUSE_REPORT_DEPTH, sizeof(hid_mouse_report_t) );
TU_ASSERT( queue_mouse_hdl, VOID_RETURN);
TU_VERIFY( osal_task_create(mouse_host_app_task, "mouse", 128, NULL, MOUSE_APP_TASK_PRIO), );
}
//------------- main task -------------//
void mouse_host_app_task(void* param)
{
(void) param;
OSAL_TASK_BEGIN
tusb_error_t error;
hid_mouse_report_t mouse_report;
osal_queue_receive(queue_mouse_hdl, &mouse_report, OSAL_TIMEOUT_WAIT_FOREVER, &error);
(void) error; // suppress compiler's warnings
process_mouse_report(&mouse_report);
OSAL_TASK_END
}
//--------------------------------------------------------------------+
// HELPER
//--------------------------------------------------------------------+
void cursor_movement(int8_t x, int8_t y, int8_t wheel)
{
//------------- X -------------//
if ( x < 0)
{
printf(ANSI_CURSOR_BACKWARD(%d), (-x)); // move left
}else if ( x > 0)
{
printf(ANSI_CURSOR_FORWARD(%d), x); // move right
}else { }
//------------- Y -------------//
if ( y < 0)
{
printf(ANSI_CURSOR_UP(%d), (-y)); // move up
}else if ( y > 0)
{
printf(ANSI_CURSOR_DOWN(%d), y); // move down
}else { }
//------------- wheel -------------//
if (wheel < 0)
{
printf(ANSI_SCROLL_UP(%d), (-wheel)); // scroll up
}else if (wheel > 0)
{
printf(ANSI_SCROLL_DOWN(%d), wheel); // scroll down
}else { }
}
static inline void process_mouse_report(hid_mouse_report_t const * p_report)
{
static hid_mouse_report_t prev_report = { 0, 0, 0, 0 };
//------------- button state -------------//
uint8_t button_changed_mask = p_report->buttons ^ prev_report.buttons;
if ( button_changed_mask & p_report->buttons)
{
printf(" %c%c%c ",
p_report->buttons & MOUSE_BUTTON_LEFT ? 'L' : '-',
p_report->buttons & MOUSE_BUTTON_MIDDLE ? 'M' : '-',
p_report->buttons & MOUSE_BUTTON_RIGHT ? 'R' : '-');
}
//------------- cursor movement -------------//
cursor_movement(p_report->x, p_report->y, p_report->wheel);
}
#endif

View File

@ -1,71 +0,0 @@
/*
* 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.
*
* This file is part of the TinyUSB stack.
*/
/** \file
* \brief TBD
*
* \note TBD
*/
/** \ingroup TBD
* \defgroup TBD
* \brief TBD
*
* @{
*/
#ifndef _TUSB_MOUSE_HOST_APP_H_
#define _TUSB_MOUSE_HOST_APP_H_
#include <stdint.h>
#include <stdbool.h>
#include "board.h"
#include "tusb.h"
#ifdef __cplusplus
extern "C" {
#endif
#if CFG_TUH_HID_MOUSE
void mouse_host_app_init(void);
void mouse_host_app_task(void* param);
#else
#define mouse_host_app_init()
#define mouse_host_app_task(x)
#endif
#ifdef __cplusplus
}
#endif
#endif /* _TUSB_MOUSE_HOST_APP_H_ */
/** @} */

View File

@ -1,473 +0,0 @@
/*
* 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.
*
* This file is part of the TinyUSB stack.
*/
#include "msc_cli.h"
#include "ctype.h"
#if CFG_TUH_MSC
#include "ff.h"
#include "diskio.h"
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
#define CLI_MAX_BUFFER 256
#define CLI_FILE_READ_BUFFER (4*1024)
enum {
ASCII_BACKSPACE = 8,
};
typedef enum
{
CLI_ERROR_NONE = 0,
CLI_ERROR_INVALID_PARA,
CLI_ERROR_INVALID_PATH,
CLI_ERROR_FILE_EXISTED,
CLI_ERROR_FAILED
}cli_error_t;
static char const * const cli_error_message[] =
{
[CLI_ERROR_NONE ] = 0,
[CLI_ERROR_INVALID_PARA ] = "Invalid parameter(s)",
[CLI_ERROR_INVALID_PATH ] = "No such file or directory",
[CLI_ERROR_FILE_EXISTED ] = "file or directory already exists",
[CLI_ERROR_FAILED ] = "failed to execute"
};
//--------------------------------------------------------------------+
// CLI Database definition
//--------------------------------------------------------------------+
// command, function, description
#define CLI_COMMAND_TABLE(ENTRY) \
ENTRY(unknown , cli_cmd_unknown , NULL ) \
ENTRY(help , cli_cmd_help , NULL ) \
ENTRY(cls , cli_cmd_clear , "Clear the screen.\n cls\n" ) \
ENTRY(ls , cli_cmd_list , "List information of the FILEs.\n ls\n" ) \
ENTRY(cd , cli_cmd_changedir, "change the current directory.\n cd a_folder\n" ) \
ENTRY(cat , cli_cmd_cat , "display contents of a file.\n cat a_file.txt\n" ) \
ENTRY(cp , cli_cmd_copy , "Copies one or more files to another location.\n cp a_file.txt dir1/another_file.txt\n cp a_file.txt dir1\n" ) \
ENTRY(mkdir , cli_cmd_mkdir , "Create a DIRECTORY, if it does not already exist.\n mkdir <new folder>\n" ) \
ENTRY(mv , cli_cmd_move , "Rename or move a DIRECTORY or a FILE.\n mv old_name.txt new_name.txt\n mv old_name.txt dir1/new_name.txt\n" ) \
ENTRY(rm , cli_cmd_remove , "Remove (delete) an empty DIRECTORY or FILE.\n rm deleted_name.txt\n rm empty_dir\n" ) \
//--------------------------------------------------------------------+
// Expands the function to have the standard function signature
//--------------------------------------------------------------------+
#define CLI_PROTOTYPE_EXPAND(command, function, description) \
cli_error_t function(char * p_para);
CLI_COMMAND_TABLE(CLI_PROTOTYPE_EXPAND)
//--------------------------------------------------------------------+
// Expand to enum value
//--------------------------------------------------------------------+
#define CLI_ENUM_EXPAND(command, function, description) CLI_CMDTYPE_##command,
typedef enum
{
CLI_COMMAND_TABLE(CLI_ENUM_EXPAND)
CLI_CMDTYPE_COUNT
}cli_cmdtype_t;
//--------------------------------------------------------------------+
// Expand to string table
//--------------------------------------------------------------------+
#define CLI_STRING_EXPAND(command, function, description) #command,
char const* const cli_string_tbl[] =
{
CLI_COMMAND_TABLE(CLI_STRING_EXPAND)
};
//--------------------------------------------------------------------+
// Expand to Description table
//--------------------------------------------------------------------+
#define CLI_DESCRIPTION_EXPAND(command, function, description) description,
char const* const cli_description_tbl[] =
{
CLI_COMMAND_TABLE(CLI_DESCRIPTION_EXPAND)
};
//--------------------------------------------------------------------+
// Expand to Command Lookup Table
//--------------------------------------------------------------------+
#define CMD_LOOKUP_EXPAND(command, function, description)\
[CLI_CMDTYPE_##command] = function,\
typedef cli_error_t (* const cli_cmdfunc_t)(char *);
static cli_cmdfunc_t cli_command_tbl[] =
{
CLI_COMMAND_TABLE(CMD_LOOKUP_EXPAND)
};
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
CFG_TUSB_MEM_SECTION uint8_t fileread_buffer[CLI_FILE_READ_BUFFER];
static char cli_buffer[CLI_MAX_BUFFER];
static char volume_label[20];
static inline void drive_number2letter(char * p_path)
{
if (p_path[1] == ':')
{
p_path[0] = 'E' + p_path[0] - '0' ;
}
}
static inline void drive_letter2number(char * p_path)
{
if (p_path[1] == ':')
{
p_path[0] = p_path[0] - 'E' + '0';
}
}
//--------------------------------------------------------------------+
// IMPLEMENTATION
//--------------------------------------------------------------------+
// NOTES: prompt re-use cli_buffer --> should not be called when cli_buffer has contents
void cli_command_prompt(void)
{
f_getcwd(cli_buffer, CLI_MAX_BUFFER);
drive_number2letter(cli_buffer);
printf("\n%s %s\n$ ",
(volume_label[0] !=0) ? volume_label : "No Label",
cli_buffer);
tu_memclr(cli_buffer, CLI_MAX_BUFFER);
}
void cli_init(void)
{
tu_memclr(cli_buffer, CLI_MAX_BUFFER);
f_getlabel(NULL, volume_label, NULL);
cli_command_prompt();
}
void cli_poll(char ch)
{
if ( isprint(ch) )
{ // accumulate & echo
if (strlen(cli_buffer) < CLI_MAX_BUFFER)
{
cli_buffer[ strlen(cli_buffer) ] = ch;
putchar(ch);
}else
{
puts("cli buffer overflows");
tu_memclr(cli_buffer, CLI_MAX_BUFFER);
}
}
else if ( ch == ASCII_BACKSPACE && strlen(cli_buffer))
{
printf(ANSI_CURSOR_BACKWARD(1) ANSI_ERASE_LINE(0) ); // move cursor back & clear to the end of line
cli_buffer[ strlen(cli_buffer)-1 ] = 0;
}
else if ( ch == '\r')
{ // execute command
//------------- Separate Command & Parameter -------------//
putchar('\n');
char* p_space = strchr(cli_buffer, ' ');
uint32_t command_len = (p_space == NULL) ? strlen(cli_buffer) : (uint32_t) (p_space - cli_buffer);
char* p_para = (p_space == NULL) ? (cli_buffer+command_len) : (p_space+1); // point to NULL-character or after space
//------------- Find entered command in lookup table & execute it -------------//
uint8_t cmd_id;
for(cmd_id = CLI_CMDTYPE_COUNT - 1; cmd_id > CLI_CMDTYPE_unknown; cmd_id--)
{
if( 0 == strncmp(cli_buffer, cli_string_tbl[cmd_id], command_len) ) break;
}
cli_error_t error = cli_command_tbl[cmd_id]( p_para ); // command execution, (unknown command if cannot find)
if (CLI_ERROR_NONE != error) puts(cli_error_message[error]); // error message output if any
cli_command_prompt(); // print out current path
}
else if (ch=='\t') // \t may be used for auto-complete later
{
}
}
//--------------------------------------------------------------------+
// UNKNOWN Command
//--------------------------------------------------------------------+
cli_error_t cli_cmd_unknown(char * p_para)
{
(void) p_para;
puts("unknown command, please type \"help\" for list of supported commands");
return CLI_ERROR_NONE;
}
//--------------------------------------------------------------------+
// HELP command
//--------------------------------------------------------------------+
cli_error_t cli_cmd_help(char * p_para)
{
(void) p_para;
puts("current supported commands are:");
for(uint8_t cmd_id = CLI_CMDTYPE_help+1; cmd_id < CLI_CMDTYPE_COUNT; cmd_id++)
{
printf("%s\t%s\n", cli_string_tbl[cmd_id], cli_description_tbl[cmd_id]);
}
return CLI_ERROR_NONE;
}
//--------------------------------------------------------------------+
// Clear Screen Command
//--------------------------------------------------------------------+
cli_error_t cli_cmd_clear(char* p_para)
{
(void) p_para;
printf(ANSI_ERASE_SCREEN(2) ANSI_CURSOR_POSITION(1,1) );
return CLI_ERROR_NONE;
}
//--------------------------------------------------------------------+
// LS Command
//--------------------------------------------------------------------+
cli_error_t cli_cmd_list(char * p_para)
{
if ( strlen(p_para) == 0 ) // list current directory
{
DIR target_dir;
if ( FR_OK != f_opendir(&target_dir, ".") ) return CLI_ERROR_FAILED;
TCHAR long_filename[_MAX_LFN];
FILINFO dir_entry =
{
.lfname = long_filename,
.lfsize = _MAX_LFN
};
while( (f_readdir(&target_dir, &dir_entry) == FR_OK) && dir_entry.fname[0] != 0)
{
if ( dir_entry.fname[0] != '.' ) // ignore . and .. entry
{
TCHAR const * const p_name = (dir_entry.lfname[0] != 0) ? dir_entry.lfname : dir_entry.fname;
if ( dir_entry.fattrib & AM_DIR ) // directory
{
printf("/%s", p_name);
}else
{
printf("%-40s%d KB", p_name, dir_entry.fsize / 1000);
}
putchar('\n');
}
}
// (void) f_closedir(&target_dir);
}
else
{
puts("ls only supports list current directory only, try to cd to that folder first");
return CLI_ERROR_INVALID_PARA;
}
return CLI_ERROR_NONE;
}
//--------------------------------------------------------------------+
// CD Command
//--------------------------------------------------------------------+
cli_error_t cli_cmd_changedir(char * p_para)
{
if ( strlen(p_para) == 0 ) return CLI_ERROR_INVALID_PARA;
drive_letter2number(p_para);
if ( FR_OK != f_chdir(p_para) )
{
return CLI_ERROR_INVALID_PATH;
}
if ( p_para[1] == ':')
{ // path has drive letter --> change drive, update volume label
f_chdrive(p_para[0] - '0');
f_getlabel(NULL, volume_label, NULL);
}
return CLI_ERROR_NONE;
}
//--------------------------------------------------------------------+
// CAT Command
//--------------------------------------------------------------------+
cli_error_t cli_cmd_cat(char *p_para)
{
if ( strlen(p_para) == 0 ) return CLI_ERROR_INVALID_PARA;
FIL file;
switch( f_open(&file, p_para, FA_READ) )
{
case FR_OK:
{
uint32_t bytes_read = 0;
if ( (FR_OK == f_read(&file, fileread_buffer, CLI_FILE_READ_BUFFER, &bytes_read)) && (bytes_read > 0) )
{
if ( file.fsize < 0x80000 ) // ~ 500KB
{
putchar('\n');
do {
for(uint32_t i=0; i<bytes_read; i++) putchar( fileread_buffer[i] );
}while( (FR_OK == f_read(&file, fileread_buffer, CLI_FILE_READ_BUFFER, &bytes_read)) && (bytes_read > 0) );
}else
{ // not display file contents if first character is not printable (high chance of binary file)
printf("%s 's contents is too large\n", p_para);
}
}
f_close(&file);
}
break;
case FR_INVALID_NAME:
return CLI_ERROR_INVALID_PATH;
default :
return CLI_ERROR_FAILED;
}
return CLI_ERROR_NONE;
}
//--------------------------------------------------------------------+
// Make Directory command
//--------------------------------------------------------------------+
cli_error_t cli_cmd_mkdir(char *p_para)
{
if ( strlen(p_para) == 0 ) return CLI_ERROR_INVALID_PARA;
return (f_mkdir(p_para) == FR_OK) ? CLI_ERROR_NONE : CLI_ERROR_FAILED;
}
//--------------------------------------------------------------------+
// COPY command
//--------------------------------------------------------------------+
cli_error_t cli_cmd_copy(char *p_para)
{
char* p_space = strchr(p_para, ' ');
if ( p_space == NULL ) return CLI_ERROR_INVALID_PARA;
*p_space = 0; // replace space by NULL-character
char* p_dest = p_space+1;
if ( strlen(p_dest) == 0 ) return CLI_ERROR_INVALID_PARA;
drive_letter2number(p_para);
drive_letter2number(p_dest);
//------------- Check Existence of source file -------------//
FIL src_file;
if ( FR_OK != f_open(&src_file , p_para, FA_READ) ) return CLI_ERROR_INVALID_PATH;
//------------- Check if dest path is a folder or a non-existing file (overwritten is not allowed) -------------//
FILINFO dest_entry;
if ( (f_stat(p_dest, &dest_entry) == FR_OK) && (dest_entry.fattrib & AM_DIR) )
{ // the destination is an existed folder --> auto append dest filename to be the folder
strcat(p_dest, "/");
strcat(p_dest, p_para);
}
//------------- Open dest file and start the copy -------------//
cli_error_t error = CLI_ERROR_NONE;
FIL dest_file;
switch ( f_open(&dest_file, p_dest, FA_WRITE | FA_CREATE_NEW) )
{
case FR_EXIST:
error = CLI_ERROR_FILE_EXISTED;
break;
case FR_OK:
while(1) // copying
{
uint32_t bytes_read = 0;
uint32_t bytes_write = 0;
FRESULT res;
res = f_read(&src_file, fileread_buffer, CLI_FILE_READ_BUFFER, &bytes_read); /* Read a chunk of src file */
if ( (res != FR_OK) || (bytes_read == 0) ) break; /* error or eof */
res = f_write(&dest_file, fileread_buffer, bytes_read, &bytes_write); /* Write it to the dst file */
if ( (res != FR_OK) || (bytes_write < bytes_read) ) break; /* error or disk full */
}
f_close(&dest_file);
break;
default:
error = CLI_ERROR_FAILED;
break;
}
f_close(&src_file);
return error;
}
//--------------------------------------------------------------------+
// MOVE/RENAME
//--------------------------------------------------------------------+
cli_error_t cli_cmd_move(char *p_para)
{
char* p_space = strchr(p_para, ' ');
if ( p_space == NULL ) return CLI_ERROR_INVALID_PARA;
*p_space = 0; // replace space by NULL-character
char* p_dest = p_space+1;
if ( strlen(p_dest) == 0 ) return CLI_ERROR_INVALID_PARA;
return (f_rename(p_para, p_dest) == FR_OK ) ? CLI_ERROR_NONE : CLI_ERROR_FAILED;
}
//--------------------------------------------------------------------+
// REMOVE
//--------------------------------------------------------------------+
cli_error_t cli_cmd_remove(char *p_para)
{
if ( strlen(p_para) == 0 ) return CLI_ERROR_INVALID_PARA;
switch( f_unlink(p_para) )
{
case FR_OK: return CLI_ERROR_NONE;
case FR_DENIED:
printf("cannot remove readonly file/foler or non-empty folder\n");
break;
default: break;
}
return CLI_ERROR_FAILED;
}
#endif

View File

@ -1,52 +0,0 @@
/*
* 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.
*
* This file is part of the TinyUSB stack.
*/
#ifndef _TUSB_MSC_CLI_H_
#define _TUSB_MSC_CLI_H_
#include "board.h"
#include "tusb.h"
#ifdef __cplusplus
extern "C" {
#endif
//--------------------------------------------------------------------+
// PUBLIC API
//--------------------------------------------------------------------+
void cli_init(void);
void cli_poll(char ch);
//--------------------------------------------------------------------+
// Callback API
//--------------------------------------------------------------------+
#ifdef __cplusplus
}
#endif
#endif // _TUSB_CLI_H_

View File

@ -1,170 +0,0 @@
/*
* 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.
*
* This file is part of the TinyUSB stack.
*/
//--------------------------------------------------------------------+
// INCLUDE
//--------------------------------------------------------------------+
#include "msc_host_app.h"
#include "app_os_prio.h"
#if CFG_TUH_MSC
#include "msc_cli.h"
#include "ff.h"
#include "diskio.h"
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
CFG_TUSB_MEM_SECTION static FATFS fatfs[CFG_TUSB_HOST_DEVICE_MAX];
//--------------------------------------------------------------------+
// tinyusb callbacks
//--------------------------------------------------------------------+
void tuh_msc_mounted_cb(uint8_t dev_addr)
{
puts("\na MassStorage device is mounted");
//------------- Disk Information -------------//
// SCSI VendorID[8] & ProductID[16] from Inquiry Command
uint8_t const* p_vendor = tuh_msc_get_vendor_name(dev_addr);
uint8_t const* p_product = tuh_msc_get_product_name(dev_addr);
for(uint8_t i=0; i<8; i++) putchar(p_vendor[i]);
putchar(' ');
for(uint8_t i=0; i<16; i++) putchar(p_product[i]);
putchar('\n');
uint32_t last_lba, block_size;
tuh_msc_read_capacity(dev_addr, &last_lba, &block_size);
printf("Disk Size: %d MB\n", (last_lba+1)/ ((1024*1024)/block_size) );
printf("LBA 0-0x%X Block Size: %d\n", last_lba, block_size);
//------------- file system (only 1 LUN support) -------------//
uint8_t phy_disk = dev_addr-1;
disk_initialize(phy_disk);
if ( disk_is_ready(phy_disk) )
{
if ( f_mount(phy_disk, &fatfs[phy_disk]) != FR_OK )
{
puts("mount failed");
return;
}
puts("---------------------------------------------------------------------");
puts("- MASSSTORAGE CLASS CLI IS A IMMATURE CODE. DISK-WRITING COMMANDS");
puts("- SUCH AS cp(COPY), mkdir(MAKE DIRECTORY) ARE POTENTIAL TO DAMAGE");
puts("- YOUR USB THUMBDRIVE. USING THOSE COMMANDS ARE AT YOUR OWN RISK.");
puts("- THE AUTHOR HAS NO RESPONSIBILITY WITH YOUR DEVICE NOR ITS DATA");
puts("---------------------------------------------------------------------");
f_chdrive(phy_disk); // change to newly mounted drive
f_chdir("/"); // root as current dir
cli_init();
}
}
void tuh_msc_unmounted_cb(uint8_t dev_addr)
{
puts("\na MassStorage device is unmounted");
uint8_t phy_disk = dev_addr-1;
f_mount(phy_disk, NULL); // unmount disk
disk_deinitialize(phy_disk);
if ( phy_disk == f_get_current_drive() )
{ // active drive is unplugged --> change to other drive
for(uint8_t i=0; i<CFG_TUSB_HOST_DEVICE_MAX; i++)
{
if ( disk_is_ready(i) )
{
f_chdrive(i);
cli_init(); // refractor, rename
}
}
}
}
// invoked ISR context
void tuh_msc_isr(uint8_t dev_addr, xfer_result_t event, uint32_t xferred_bytes)
{
(void) dev_addr;
(void) event;
(void) xferred_bytes;
}
//--------------------------------------------------------------------+
// APPLICATION CODE
//--------------------------------------------------------------------+
void msc_host_app_init(void)
{
osal_task_create( msc_host_app_task, "msc", 512, NULL, MSC_APP_TASK_PRIO);
diskio_init();
}
//------------- main task -------------//
void msc_host_app_task(void* param)
{
(void) param;;
OSAL_TASK_BEGIN
bool is_any_disk_mounted;
osal_task_delay(10);
is_any_disk_mounted = false;
for(uint8_t phy_disk=0; phy_disk < CFG_TUSB_HOST_DEVICE_MAX; phy_disk++)
{
if ( disk_is_ready(phy_disk) )
{
is_any_disk_mounted = true;
break;
}
}
if ( is_any_disk_mounted )
{
int ch = getchar();
if ( ch > 0 )
{
cli_poll( (char) ch);
}
}
OSAL_TASK_END
}
#endif

View File

@ -1,63 +0,0 @@
/*
* 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.
*
* This file is part of the TinyUSB stack.
*/
/** \ingroup TBD
* \defgroup TBD
* \brief TBD
*
* @{
*/
#ifndef _TUSB_MSC_HOST_APP_H_
#define _TUSB_MSC_HOST_APP_H_
#include "board.h"
#include "tusb.h"
#ifdef __cplusplus
extern "C" {
#endif
#if CFG_TUH_MSC
void msc_host_app_init(void);
void msc_host_app_task(void* param);
#else
#define msc_host_app_init()
#define msc_host_app_task(x)
#endif
#ifdef __cplusplus
}
#endif
#endif /* _TUSB_MSC_HOST_APP_H_ */
/** @} */

View File

@ -1,64 +0,0 @@
/*
* 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.
*
* This file is part of the TinyUSB stack.
*/
#include "rndis_host_app.h"
#include "app_os_prio.h"
#if CFG_TUH_CDC && CFG_TUH_CDC_RNDIS
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
void tusbh_cdc_rndis_mounted_cb(uint8_t dev_addr)
{ // application set-up
uint8_t mac_address[6];
printf("\nan RNDIS device is mounted\n");
tusbh_cdc_rndis_get_mac_addr(dev_addr, mac_address);
printf("MAC Address ");
for(uint8_t i=0; i<6; i++) printf("%X ", mac_address[i]);
printf("\n");
}
void tusbh_cdc_rndis_unmounted_cb(uint8_t dev_addr)
{
// application tear-down
printf("\nan RNDIS device is unmounted\n");
}
void rndis_host_app_init(void)
{
}
void rndis_host_app_task(void* param)
{
OSAL_TASK_BEGIN
OSAL_TASK_END
}
#endif

View File

@ -1,63 +0,0 @@
/*
* 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.
*
* This file is part of the TinyUSB stack.
*/
/** \ingroup TBD
* \defgroup TBD
* \brief TBD
*
* @{
*/
#ifndef _TUSB_RNDIS_HOST_APP_H_
#define _TUSB_RNDIS_HOST_APP_H_
#include "board.h"
#include "tusb.h"
#ifdef __cplusplus
extern "C" {
#endif
#if CFG_TUH_CDC && CFG_TUH_CDC_RNDIS
void rndis_host_app_init(void);
void rndis_host_app_task(void* param);
#else
#define rndis_host_app_init()
#define rndis_host_app_task(x)
#endif
#ifdef __cplusplus
}
#endif
#endif /* _TUSB_RNDIS_HOST_APP_H_ */
/** @} */

View File

@ -1,101 +0,0 @@
/*
* 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.
*
* This file is part of the TinyUSB stack.
*/
#ifndef _TUSB_CONFIG_H_
#define _TUSB_CONFIG_H_
#ifdef __cplusplus
extern "C" {
#endif
//--------------------------------------------------------------------+
// CONTROLLER CONFIGURATION
//--------------------------------------------------------------------+
//#define CFG_TUSB_MCU will be passed from IDE for easy board/mcu switching
#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_HOST)
//--------------------------------------------------------------------+
// HOST CONFIGURATION
//--------------------------------------------------------------------+
//------------- CLASS -------------//
#define CFG_TUH_HUB 1
#define CFG_TUH_HID_KEYBOARD 1
#define CFG_TUH_HID_MOUSE 1
#define CFG_TUSB_HOST_HID_GENERIC 0 // (not yet supported)
#define CFG_TUH_MSC 1
#define CFG_TUH_CDC 1
#define CFG_TUSB_HOST_DEVICE_MAX (CFG_TUH_HUB ? 5 : 1) // normal hub has 4 ports
//--------------------------------------------------------------------+
// COMMON CONFIGURATION
//--------------------------------------------------------------------+
#define CFG_TUSB_DEBUG 1
//#define CFG_TUSB_OS OPT_OS_NONE // defined using eclipse build
//#define CFG_TUD_TASK_PRIO 0 // defined using eclipse build
//--------------------------------------------------------------------+
// USB RAM PLACEMENT
//--------------------------------------------------------------------+
#ifdef __CODE_RED // make use of code red's support for ram region macros
#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X
#define CFG_TUSB_MEM_SECTION // LPC17xx USB DMA can access all address
#elif (CFG_TUSB_MCU == OPT_MCU_LPC43XX)
#define CFG_TUSB_MEM_SECTION TU_ATTR_SECTION(.data.$RAM3)
#endif
#elif defined __CC_ARM // Compiled with Keil armcc
#if (CFG_TUSB_MCU == OPT_MCU_LPC175X_6X)
#define CFG_TUSB_MEM_SECTION // LPC17xx USB DMA can access all address
#elif (CFG_TUSB_MCU == OPT_MCU_LPC43XX)
#define CFG_TUSB_MEM_SECTION // Use keil tool configure to have AHB SRAM as default memory
#endif
#elif defined __ICCARM__ // compiled with IAR
#if (CFG_TUSB_MCU == OPT_MCU_LPC175X_6X)
// LP175x_6x can access all but CMSIS-RTX causes overflow in 32KB SRAM --> move to AHB ram
#define CFG_TUSB_MEM_SECTION _Pragma("location=\".sram\"")
#elif (CFG_TUSB_MCU == OPT_MCU_LPC43XX)
#define CFG_TUSB_MEM_SECTION _Pragma("location=\".ahb_sram1\"")
#endif
#else
#error compiler not specified
#endif
#ifdef __cplusplus
}
#endif
#endif /* _TUSB_CONFIG_H_ */

View File

@ -172,25 +172,11 @@ void board_init(void)
*/
#if CFG_TUSB_RHPORT0_MODE
Chip_USB0_Init();
// Reset controller
LPC_USB0->USBCMD_D |= 0x02;
while( LPC_USB0->USBCMD_D & 0x02 ) {}
// Set mode
#if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST
LPC_USB0->USBMODE_H = USBMODE_HOST | (USBMODE_VBUS_HIGH << 5);
LPC_USB0->PORTSC1_D |= (1<<24); // FIXME force full speed for debugging
#else // TODO OTG
LPC_USB0->USBMODE_D = USBMODE_DEVICE;
LPC_USB0->OTGSC = (1<<3) | (1<<0) /*| (1<<16)| (1<<24)| (1<<25)| (1<<26)| (1<<27)| (1<<28)| (1<<29)| (1<<30)*/;
#endif
#endif
/* USB1
/* From EA4357 user manual
*
* For USB Device:
* For USB1 Device:
* - a 1.5Kohm pull-up resistor is needed on the USB DP data signal. There are two methods to create this.
* JP15 is inserted and the pull-up resistor is always enabled. Alternatively, the pull-up resistor is activated
* inside the USB OTG chip (U31), and this has to be done via the I2C interface of GPIO52/GPIO53. In the latter case,
@ -200,7 +186,7 @@ void board_init(void)
* of VBUS can be read via U31.
* - JP16 shall not be inserted.
*
* For USB Host:
* For USB1 Host:
* - 15Kohm pull-down resistors are needed on the USB data signals. These are activated inside the USB OTG chip (U31),
* and this has to be done via the I2C interface of GPIO52/GPIO53.
* - J20 is the connector to use when USB Host is used. In order to provide +5V to the external USB
@ -211,20 +197,6 @@ void board_init(void)
*/
#if CFG_TUSB_RHPORT1_MODE
Chip_USB1_Init();
// // Reset controller
// LPC_USB1->USBCMD_D |= 0x02;
// while( LPC_USB1->USBCMD_D & 0x02 ) {}
//
// // Set mode
// #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_HOST
// LPC_USB1->USBMODE_H = USBMODE_HOST | (USBMODE_VBUS_HIGH << 5);
// #else // TODO OTG
// LPC_USB1->USBMODE_D = USBMODE_DEVICE;
// #endif
//
// // USB1 as fullspeed
// LPC_USB1->PORTSC1_D |= (1<<24);
#endif
// USB0 Vbus Power: P2_3 on EA4357 channel B U20 GPIO26 active low (base board)

View File

@ -82,10 +82,15 @@ void board_init(void)
LPUART_Init(UART_PORT, &uart_config, (CLOCK_GetPllFreq(kCLOCK_PllUsb1) / 6U) / (CLOCK_GetDiv(kCLOCK_UartDiv) + 1U));
//------------- USB0 -------------//
// Clock
CLOCK_EnableUsbhs0PhyPllClock(kCLOCK_Usbphy480M, 480000000U);
CLOCK_EnableUsbhs0Clock(kCLOCK_Usb480M, 480000000U);
// USB1
// CLOCK_EnableUsbhs1PhyPllClock(kCLOCK_Usbphy480M, 480000000U);
// CLOCK_EnableUsbhs1Clock(kCLOCK_Usb480M, 480000000U);
USBPHY_Type* usb_phy;
// RT105x RT106x have dual USB controller. TODO support USB2
@ -106,10 +111,6 @@ void board_init(void)
phytx &= ~(USBPHY_TX_D_CAL_MASK | USBPHY_TX_TXCAL45DM_MASK | USBPHY_TX_TXCAL45DP_MASK);
phytx |= USBPHY_TX_D_CAL(0x0C) | USBPHY_TX_TXCAL45DP(0x06) | USBPHY_TX_TXCAL45DM(0x06);
usb_phy->TX = phytx;
// USB1
// CLOCK_EnableUsbhs1PhyPllClock(kCLOCK_Usbphy480M, 480000000U);
// CLOCK_EnableUsbhs1Clock(kCLOCK_Usb480M, 480000000U);
}
//--------------------------------------------------------------------+

View File

@ -157,51 +157,12 @@ void board_init(void)
Chip_UART_TXEnable(UART_DEV);
//------------- USB -------------//
enum {
USBMODE_DEVICE = 2,
USBMODE_HOST = 3
};
enum {
USBMODE_VBUS_LOW = 0,
USBMODE_VBUS_HIGH = 1
};
// USB0
#if CFG_TUSB_RHPORT0_MODE
Chip_USB0_Init();
// Host/Device mode can only be set right after controller reset
LPC_USB0->USBCMD_D |= 0x02;
while( LPC_USB0->USBCMD_D & 0x02 ) {}
// Set mode
#if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST
LPC_USB0->USBMODE_H = USBMODE_HOST | (USBMODE_VBUS_HIGH << 5);
LPC_USB0->PORTSC1_H |= (1<<24); // FIXME force full speed for debugging
#else // TODO OTG
LPC_USB0->USBMODE_D = USBMODE_DEVICE;
LPC_USB0->OTGSC = (1<<3) | (1<<0) /*| (1<<16)| (1<<24)| (1<<25)| (1<<26)| (1<<27)| (1<<28)| (1<<29)| (1<<30)*/;
#endif
#endif
// USB1
#if CFG_TUSB_RHPORT1_MODE
Chip_USB1_Init();
// // Reset controller
// LPC_USB1->USBCMD_D |= 0x02;
// while( LPC_USB1->USBCMD_D & 0x02 ) {}
//
// // Set mode
// #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_HOST
// LPC_USB1->USBMODE_H = USBMODE_HOST | (USBMODE_VBUS_HIGH << 5);
// #else // TODO OTG
// LPC_USB1->USBMODE_D = USBMODE_DEVICE;
// #endif
//
// // USB1 as fullspeed
// LPC_USB1->PORTSC1_D |= (1<<24);
#endif
}

View File

@ -169,20 +169,6 @@ void board_init(void)
*/
#if CFG_TUSB_RHPORT0_MODE
Chip_USB0_Init();
// // Reset controller
// LPC_USB0->USBCMD_D |= 0x02;
// while( LPC_USB0->USBCMD_D & 0x02 ) {}
//
// // Set mode
// #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST
// LPC_USB0->USBMODE_H = USBMODE_HOST | (USBMODE_VBUS_HIGH << 5);
//
// LPC_USB0->PORTSC1_D |= (1<<24); // FIXME force full speed for debugging
// #else // TODO OTG
// LPC_USB0->USBMODE_D = USBMODE_DEVICE;
// LPC_USB0->OTGSC = (1<<3) | (1<<0) /*| (1<<16)| (1<<24)| (1<<25)| (1<<26)| (1<<27)| (1<<28)| (1<<29)| (1<<30)*/;
// #endif
#endif
/* USB1
@ -206,20 +192,6 @@ void board_init(void)
#if CFG_TUSB_RHPORT1_MODE
Chip_USB1_Init();
// // Reset controller
// LPC_USB1->USBCMD_D |= 0x02;
// while( LPC_USB1->USBCMD_D & 0x02 ) {}
//
// // Set mode
// #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_HOST
// LPC_USB1->USBMODE_H = USBMODE_HOST | (USBMODE_VBUS_HIGH << 5);
// #else // TODO OTG
// LPC_USB1->USBMODE_D = USBMODE_DEVICE;
// #endif
//
// // USB1 as fullspeed
// LPC_USB1->PORTSC1_D |= (1<<24);
// Chip_GPIO_SetPinDIROutput(LPC_GPIO_PORT, 5, 6); /* GPIO5[6] = USB1_PWR_EN */
// Chip_GPIO_SetPinState(LPC_GPIO_PORT, 5, 6, true); /* GPIO5[6] output high */
#endif

View File

@ -48,7 +48,7 @@ static DSTATUS disk_state[CFG_TUSB_HOST_DEVICE_MAX];
static DRESULT wait_for_io_complete(uint8_t usb_addr)
{
// TODO with RTOS, this should use semaphore instead of blocking
while ( tuh_msc_is_busy(usb_addr) )
while ( !tuh_msc_ready(usb_addr) )
{
// TODO should have timeout here
#if CFG_TUSB_OS != OPT_OS_NONE

View File

@ -251,11 +251,7 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t
}
else if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT)
{
uint8_t const * desc_report = tud_hid_descriptor_report_cb(
#if CFG_TUD_HID > 1
hid_itf // TODO for backward compatible callback, remove later when appropriate
#endif
);
uint8_t const * desc_report = tud_hid_descriptor_report_cb(hid_itf);
tud_control_xfer(rhport, request, (void*) desc_report, p_hid->report_desc_len);
}
else
@ -275,12 +271,7 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t
uint8_t const report_type = tu_u16_high(request->wValue);
uint8_t const report_id = tu_u16_low(request->wValue);
uint16_t xferlen = tud_hid_get_report_cb(
#if CFG_TUD_HID > 1
hid_itf, // TODO for backward compatible callback, remove later when appropriate
#endif
report_id, (hid_report_type_t) report_type, p_hid->epin_buf, request->wLength
);
uint16_t xferlen = tud_hid_get_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, p_hid->epin_buf, request->wLength);
TU_ASSERT( xferlen > 0 );
tud_control_xfer(rhport, request, p_hid->epin_buf, xferlen);
@ -298,12 +289,7 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t
uint8_t const report_type = tu_u16_high(request->wValue);
uint8_t const report_id = tu_u16_low(request->wValue);
tud_hid_set_report_cb(
#if CFG_TUD_HID > 1
hid_itf, // TODO for backward compatible callback, remove later when appropriate
#endif
report_id, (hid_report_type_t) report_type, p_hid->epout_buf, request->wLength
);
tud_hid_set_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, p_hid->epout_buf, request->wLength);
}
break;
@ -314,12 +300,7 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t
if ( tud_hid_set_idle_cb )
{
// stall request if callback return false
TU_VERIFY( tud_hid_set_idle_cb(
#if CFG_TUD_HID > 1
hid_itf, // TODO for backward compatible callback, remove later when appropriate
#endif
p_hid->idle_rate)
);
TU_VERIFY( tud_hid_set_idle_cb( hid_itf, p_hid->idle_rate) );
}
tud_control_status(rhport, request);
@ -354,12 +335,7 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t
{
if (tud_hid_boot_mode_cb)
{
tud_hid_boot_mode_cb(
#if CFG_TUD_HID > 1
hid_itf, // TODO for backward compatible callback, remove later when appropriate
#endif
p_hid->boot_mode
);
tud_hid_boot_mode_cb(hid_itf, p_hid->boot_mode);
}
}
break;
@ -400,12 +376,7 @@ bool hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_
// Received report
else if (ep_addr == p_hid->ep_out)
{
tud_hid_set_report_cb(
#if CFG_TUD_HID > 1
itf, // TODO for backward compatible callback, remove later when appropriate
#endif
0, HID_REPORT_TYPE_INVALID, p_hid->epout_buf, xferred_bytes
);
tud_hid_set_report_cb(itf, 0, HID_REPORT_TYPE_INVALID, p_hid->epout_buf, xferred_bytes);
TU_ASSERT(usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf)));
}

View File

@ -88,8 +88,6 @@ static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8
// Callbacks (Weak is optional)
//--------------------------------------------------------------------+
#if CFG_TUD_HID > 1
// Invoked when received GET HID REPORT DESCRIPTOR request
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf);
@ -111,18 +109,6 @@ TU_ATTR_WEAK void tud_hid_boot_mode_cb(uint8_t itf, uint8_t boot_mode);
// - Idle Rate > 0 : skip duplication, but send at least 1 report every idle rate (in unit of 4 ms).
TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t itf, uint8_t idle_rate);
#else
// TODO for backward compatible callback, remove later when appropriate
uint8_t const * tud_hid_descriptor_report_cb(void);
uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen);
void tud_hid_set_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize);
TU_ATTR_WEAK void tud_hid_boot_mode_cb(uint8_t boot_mode);
TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t idle_rate);
#endif
// Invoked when sent REPORT successfully to host
// Application can use this to send the next report
// Note: For composite reports, report[0] is report ID

View File

@ -47,14 +47,21 @@ enum
typedef struct
{
uint8_t itf_num;
uint8_t ep_in;
uint8_t ep_out;
uint8_t itf_num;
uint8_t ep_in;
uint8_t ep_out;
uint8_t max_lun;
uint8_t max_lun;
volatile bool mounted;
volatile bool configured; // Receive SET_CONFIGURE
volatile bool mounted; // Enumeration is complete
struct {
uint32_t block_size;
uint32_t block_count;
} capacity[CFG_TUH_MSC_MAXLUN];
//------------- SCSI -------------//
uint8_t stage;
void* buffer;
tuh_msc_complete_cb_t complete_cb;
@ -63,14 +70,15 @@ typedef struct
msc_csw_t csw;
}msch_interface_t;
CFG_TUSB_MEM_SECTION static msch_interface_t msch_data[CFG_TUSB_HOST_DEVICE_MAX];
CFG_TUSB_MEM_SECTION static msch_interface_t _msch_itf[CFG_TUSB_HOST_DEVICE_MAX];
// buffer used to read scsi information when mounted, largest response data currently is inquiry
CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t msch_buffer[sizeof(scsi_inquiry_resp_t)];
// buffer used to read scsi information when mounted
// largest response data currently is inquiry TODO Inquiry is not part of enum anymore
CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t _msch_buffer[sizeof(scsi_inquiry_resp_t)];
static inline msch_interface_t* get_itf(uint8_t dev_addr)
{
return &msch_data[dev_addr-1];
return &_msch_itf[dev_addr-1];
}
//--------------------------------------------------------------------+
@ -82,34 +90,45 @@ uint8_t tuh_msc_get_maxlun(uint8_t dev_addr)
return p_msc->max_lun;
}
uint32_t tuh_msc_get_block_count(uint8_t dev_addr, uint8_t lun)
{
msch_interface_t* p_msc = get_itf(dev_addr);
return p_msc->capacity[lun].block_count;
}
uint32_t tuh_msc_get_block_size(uint8_t dev_addr, uint8_t lun)
{
msch_interface_t* p_msc = get_itf(dev_addr);
return p_msc->capacity[lun].block_size;
}
bool tuh_msc_mounted(uint8_t dev_addr)
{
msch_interface_t* p_msc = get_itf(dev_addr);
// is configured can be omitted
return tuh_device_is_configured(dev_addr) && p_msc->mounted;
return p_msc->mounted;
}
bool tuh_msc_is_busy(uint8_t dev_addr)
bool tuh_msc_ready(uint8_t dev_addr)
{
msch_interface_t* p_msc = get_itf(dev_addr);
return p_msc->mounted && hcd_edpt_busy(dev_addr, p_msc->ep_in);
return p_msc->mounted && !hcd_edpt_busy(dev_addr, p_msc->ep_in);
}
//--------------------------------------------------------------------+
// PUBLIC API: SCSI COMMAND
//--------------------------------------------------------------------+
static inline void msc_cbw_add_signature(msc_cbw_t *p_cbw, uint8_t lun)
static inline void cbw_init(msc_cbw_t *cbw, uint8_t lun)
{
p_cbw->signature = MSC_CBW_SIGNATURE;
p_cbw->tag = 0x54555342; // TUSB
p_cbw->lun = lun;
tu_memclr(cbw, sizeof(msc_cbw_t));
cbw->signature = MSC_CBW_SIGNATURE;
cbw->tag = 0x54555342; // TUSB
cbw->lun = lun;
}
bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb)
{
msch_interface_t* p_msc = get_itf(dev_addr);
// TU_VERIFY(p_msc->mounted); // TODO part of the enumeration also use scsi command
TU_VERIFY(p_msc->configured);
// TODO claim endpoint
@ -125,12 +144,12 @@ bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tu
bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb)
{
msch_interface_t* p_msc = get_itf(dev_addr);
if ( !p_msc->mounted ) return false;
msch_interface_t* p_msc = get_itf(dev_addr);
TU_VERIFY(p_msc->configured);
msc_cbw_t cbw = { 0 };
msc_cbw_t cbw;
cbw_init(&cbw, lun);
msc_cbw_add_signature(&cbw, lun);
cbw.total_bytes = sizeof(scsi_read_capacity10_resp_t);
cbw.dir = TUSB_DIR_IN_MASK;
cbw.cmd_len = sizeof(scsi_read_capacity10_t);
@ -139,11 +158,14 @@ bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_r
return tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb);
}
bool tuh_msc_scsi_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb)
bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb)
{
msc_cbw_t cbw = { 0 };
msch_interface_t* p_msc = get_itf(dev_addr);
TU_VERIFY(p_msc->mounted);
msc_cbw_t cbw;
cbw_init(&cbw, lun);
msc_cbw_add_signature(&cbw, lun);
cbw.total_bytes = sizeof(scsi_inquiry_resp_t);
cbw.dir = TUSB_DIR_IN_MASK;
cbw.cmd_len = sizeof(scsi_inquiry_t);
@ -160,26 +182,29 @@ bool tuh_msc_scsi_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* re
bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb)
{
msc_cbw_t cbw = { 0 };
msc_cbw_add_signature(&cbw, lun);
msch_interface_t* p_msc = get_itf(dev_addr);
TU_VERIFY(p_msc->configured);
cbw.total_bytes = 0; // Number of bytes
cbw.dir = TUSB_DIR_OUT;
cbw.cmd_len = sizeof(scsi_test_unit_ready_t);
cbw.command[0] = SCSI_CMD_TEST_UNIT_READY;
cbw.command[1] = lun; // according to wiki TODO need verification
msc_cbw_t cbw;
cbw_init(&cbw, lun);
cbw.total_bytes = 0;
cbw.dir = TUSB_DIR_OUT;
cbw.cmd_len = sizeof(scsi_test_unit_ready_t);
cbw.command[0] = SCSI_CMD_TEST_UNIT_READY;
cbw.command[1] = lun; // according to wiki TODO need verification
return tuh_msc_scsi_command(dev_addr, &cbw, NULL, complete_cb);
}
bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_msc_complete_cb_t complete_cb)
{
msc_cbw_t cbw = { 0 };
msc_cbw_add_signature(&cbw, lun);
msc_cbw_t cbw;
cbw_init(&cbw, lun);
cbw.total_bytes = 18; // TODO sense response
cbw.dir = TUSB_DIR_IN_MASK;
cbw.cmd_len = sizeof(scsi_request_sense_t);
cbw.dir = TUSB_DIR_IN_MASK;
cbw.cmd_len = sizeof(scsi_request_sense_t);
scsi_request_sense_t const cmd_request_sense =
{
@ -192,61 +217,54 @@ bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_ms
return tuh_msc_scsi_command(dev_addr, &cbw, resposne, complete_cb);
}
#if 0
tusb_error_t tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint16_t block_count)
bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb)
{
msch_interface_t* p_msch = &msch_data[dev_addr-1];
msch_interface_t* p_msc = get_itf(dev_addr);
TU_VERIFY(p_msc->mounted);
//------------- Command Block Wrapper -------------//
msc_cbw_add_signature(&p_msch->cbw, lun);
p_msch->cbw.total_bytes = p_msch->block_size*block_count; // Number of bytes
p_msch->cbw.dir = TUSB_DIR_IN_MASK;
p_msch->cbw.cmd_len = sizeof(scsi_read10_t);
//------------- SCSI command -------------//
scsi_read10_t cmd_read10 =msch_sem_hdl
msc_cbw_t cbw;
cbw_init(&cbw, lun);
cbw.total_bytes = block_count*p_msc->capacity[lun].block_size;
cbw.dir = TUSB_DIR_IN_MASK;
cbw.cmd_len = sizeof(scsi_read10_t);
scsi_read10_t const cmd_read10 =
{
.cmd_code = SCSI_CMD_READ_10,
.lba = tu_htonl(lba),
.block_count = tu_htons(block_count)
.cmd_code = SCSI_CMD_READ_10,
.lba = tu_htonl(lba),
.block_count = tu_htons(block_count)
};
memcpy(cbw.command, &cmd_read10, cbw.cmd_len);
return tuh_msc_scsi_command(dev_addr, &cbw, buffer, complete_cb);
}
bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb)
{
msch_interface_t* p_msc = get_itf(dev_addr);
TU_VERIFY(p_msc->mounted);
msc_cbw_t cbw;
cbw_init(&cbw, lun);
cbw.total_bytes = block_count*p_msc->capacity[lun].block_size;
cbw.dir = TUSB_DIR_OUT;
cbw.cmd_len = sizeof(scsi_write10_t);
scsi_write10_t const cmd_write10 =
{
.cmd_code = SCSI_CMD_WRITE_10,
.lba = tu_htonl(lba),
.block_count = tu_htons(block_count)
};
memcpy(p_msch->cbw.command, &cmd_read10, p_msch->cbw.cmd_len);
memcpy(cbw.command, &cmd_write10, cbw.cmd_len);
TU_ASSERT_ERR ( send_cbw(dev_addr, p_msch, p_buffer));
return TUSB_ERROR_NONE;
return tuh_msc_scsi_command(dev_addr, &cbw, (void*) buffer, complete_cb);
}
tusb_error_t tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * p_buffer, uint32_t lba, uint16_t block_count)
{
msch_interface_t* p_msch = &msch_data[dev_addr-1];
//------------- Command Block Wrapper -------------//
msc_cbw_add_signature(&p_msch->cbw, lun);
p_msch->cbw.total_bytes = p_msch->block_size*block_count; // Number of bytes
p_msch->cbw.dir = TUSB_DIR_OUT;
p_msch->cbw.cmd_len = sizeof(scsi_write10_t);
//------------- SCSI command -------------//
scsi_write10_t cmd_write10 =
{
.cmd_code = SCSI_CMD_WRITE_10,
.lba = tu_htonl(lba),
.block_count = tu_htons(block_count)
};
memcpy(p_msch->cbw.command, &cmd_write10, p_msch->cbw.cmd_len);
TU_ASSERT_ERR ( send_cbw(dev_addr, p_msch, (void*) p_buffer));
return TUSB_ERROR_NONE;
}
#endif
#if 0
// MSC interface Reset (not used now)
bool tuh_msc_reset(uint8_t dev_addr)
@ -273,14 +291,14 @@ bool tuh_msc_reset(uint8_t dev_addr)
//--------------------------------------------------------------------+
void msch_init(void)
{
tu_memclr(msch_data, sizeof(msch_interface_t)*CFG_TUSB_HOST_DEVICE_MAX);
tu_memclr(_msch_itf, sizeof(msch_interface_t)*CFG_TUSB_HOST_DEVICE_MAX);
}
void msch_close(uint8_t dev_addr)
{
msch_interface_t* p_msc = get_itf(dev_addr);
tu_memclr(p_msc, sizeof(msch_interface_t));
tuh_msc_unmounted_cb(dev_addr); // invoke Application Callback
tuh_msc_unmount_cb(dev_addr); // invoke Application Callback
}
bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes)
@ -337,6 +355,7 @@ bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32
static bool config_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result);
static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw);
static bool config_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw);
static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw);
bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length)
{
@ -375,6 +394,8 @@ bool msch_set_config(uint8_t dev_addr, uint8_t itf_num)
msch_interface_t* p_msc = get_itf(dev_addr);
TU_ASSERT(p_msc->itf_num == itf_num);
p_msc->configured = true;
//------------- Get Max Lun -------------//
TU_LOG2("MSC Get Max Lun\r\n");
tusb_control_request_t request =
@ -402,12 +423,13 @@ static bool config_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t
msch_interface_t* p_msc = get_itf(dev_addr);
// STALL means zero
p_msc->max_lun = (XFER_RESULT_SUCCESS == result) ? msch_buffer[0] : 0;
p_msc->max_lun = (XFER_RESULT_SUCCESS == result) ? _msch_buffer[0] : 0;
p_msc->max_lun++; // MAX LUN is minus 1 by specs
// TODO multiple LUN support
TU_LOG2("SCSI Test Unit Ready\r\n");
tuh_msc_test_unit_ready(dev_addr, 0, config_test_unit_ready_complete);
uint8_t const lun = 0;
tuh_msc_test_unit_ready(dev_addr, lun, config_test_unit_ready_complete);
return true;
}
@ -416,19 +438,16 @@ static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* c
{
if (csw->status == 0)
{
msch_interface_t* p_msc = get_itf(dev_addr);
usbh_driver_set_config_complete(dev_addr, p_msc->itf_num);
// Unit is ready, Enumeration is complete
p_msc->mounted = true;
tuh_msc_mounted_cb(dev_addr);
// Unit is ready, read its capacity
TU_LOG2("SCSI Read Capacity\r\n");
tuh_msc_read_capacity(dev_addr, cbw->lun, (scsi_read_capacity10_resp_t*) _msch_buffer, config_read_capacity_complete);
}else
{
// Note: During enumeration, some device fails Test Unit Ready and require a few retries
// with Request Sense to start working !!
// TODO limit number of retries
TU_ASSERT(tuh_msc_request_sense(dev_addr, cbw->lun, msch_buffer, config_request_sense_complete));
TU_LOG2("SCSI Request Sense\r\n");
TU_ASSERT(tuh_msc_request_sense(dev_addr, cbw->lun, _msch_buffer, config_request_sense_complete));
}
return true;
@ -441,4 +460,24 @@ static bool config_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw
return true;
}
static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw)
{
TU_ASSERT(csw->status == 0);
msch_interface_t* p_msc = get_itf(dev_addr);
// Capacity response field: Block size and Last LBA are both Big-Endian
scsi_read_capacity10_resp_t* resp = (scsi_read_capacity10_resp_t*) _msch_buffer;
p_msc->capacity[cbw->lun].block_count = tu_ntohl(resp->last_lba) + 1;
p_msc->capacity[cbw->lun].block_size = tu_ntohl(resp->block_size);
// Mark enumeration is complete
p_msc->mounted = true;
tuh_msc_mount_cb(dev_addr);
usbh_driver_set_config_complete(dev_addr, p_msc->itf_num);
return true;
}
#endif

View File

@ -35,6 +35,15 @@
extern "C" {
#endif
//--------------------------------------------------------------------+
// Class Driver Configuration
//--------------------------------------------------------------------+
#ifndef CFG_TUH_MSC_MAXLUN
#define CFG_TUH_MSC_MAXLUN 4
#endif
/** \addtogroup ClassDriver_MSC
* @{
* \defgroup MSC_Host Host
@ -51,73 +60,56 @@ typedef bool (*tuh_msc_complete_cb_t)(uint8_t dev_addr, msc_cbw_t const* cbw, ms
// This function true after tuh_msc_mounted_cb() and false after tuh_msc_unmounted_cb()
bool tuh_msc_mounted(uint8_t dev_addr);
/** \brief Check if the interface is currently busy or not
* \param[in] dev_addr device address
* \retval true if the interface is busy meaning the stack is still transferring/waiting data from/to device
* \retval false if the interface is not busy meaning the stack successfully transferred data from/to device
* \note This function is used to check if previous transfer is complete (success or error), so that the next transfer
* can be scheduled. User needs to make sure the corresponding interface is mounted (by \ref tuh_msc_is_mounted)
* before calling this function
*/
bool tuh_msc_is_busy(uint8_t dev_addr);
// Check if the interface is currently ready or busy transferring data
bool tuh_msc_ready(uint8_t dev_addr);
// Get Max Lun
uint8_t tuh_msc_get_maxlun(uint8_t dev_addr);
// Carry out a full SCSI command (cbw, data, csw) in non-blocking manner.
// `complete_cb` callback is invoked when SCSI op is complete.
// Get number of block
uint32_t tuh_msc_get_block_count(uint8_t dev_addr, uint8_t lun);
// Get block size in bytes
uint32_t tuh_msc_get_block_size(uint8_t dev_addr, uint8_t lun);
// Perform a full SCSI command (cbw, data, csw) in non-blocking manner.
// Complete callback is invoked when SCSI op is complete.
// return true if success, false if there is already pending operation.
bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb);
// Carry out SCSI INQUIRY command in non-blocking manner.
bool tuh_msc_scsi_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb);
// Perform SCSI Inquiry command
// Complete callback is invoked when SCSI op is complete.
bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb);
// Carry out SCSI REQUEST SENSE (10) command in non-blocking manner.
// Perform SCSI Test Unit Ready command
// Complete callback is invoked when SCSI op is complete.
bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb);
// Carry out SCSI REQUEST SENSE (10) command in non-blocking manner.
// Perform SCSI Request Sense 10 command
// Complete callback is invoked when SCSI op is complete.
bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_msc_complete_cb_t complete_cb);
// Carry out SCSI READ CAPACITY (10) command in non-blocking manner.
// Perform SCSI Read 10 command. Read n blocks starting from LBA to buffer
// Complete callback is invoked when SCSI op is complete.
bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb);
// Perform SCSI Write 10 command. Write n blocks starting from LBA to device
// Complete callback is invoked when SCSI op is complete.
bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb);
// Perform SCSI Read Capacity 10 command
// Complete callback is invoked when SCSI op is complete.
// Note: during enumeration, host stack already carried out this request. Application can retrieve capacity by
// simply call tuh_msc_get_block_count() and tuh_msc_get_block_size()
bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb);
#if 0
/** \brief Perform SCSI READ 10 command to read data from MassStorage device
* \param[in] dev_addr device address
* \param[in] lun Targeted Logical Unit
* \param[out] p_buffer Buffer used to store data read from device. Must be accessible by USB controller (see \ref CFG_TUSB_MEM_SECTION)
* \param[in] lba Starting Logical Block Address to be read
* \param[in] block_count Number of Block to be read
* \retval TUSB_ERROR_NONE on success
* \retval TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device
* \retval TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request)
* \retval TUSB_ERROR_INVALID_PARA if input parameters are not correct
* \note This function is non-blocking and returns immediately. The result of USB transfer will be reported by the interface's callback function
*/
tusb_error_t tuh_msc_read10 (uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint16_t block_count);
/** \brief Perform SCSI WRITE 10 command to write data to MassStorage device
* \param[in] dev_addr device address
* \param[in] lun Targeted Logical Unit
* \param[in] p_buffer Buffer containing data. Must be accessible by USB controller (see \ref CFG_TUSB_MEM_SECTION)
* \param[in] lba Starting Logical Block Address to be written
* \param[in] block_count Number of Block to be written
* \retval TUSB_ERROR_NONE on success
* \retval TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device
* \retval TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request)
* \retval TUSB_ERROR_INVALID_PARA if input parameters are not correct
* \note This function is non-blocking and returns immediately. The result of USB transfer will be reported by the interface's callback function
*/
tusb_error_t tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * p_buffer, uint32_t lba, uint16_t block_count);
#endif
//------------- Application Callback -------------//
// Invoked when a device with MassStorage interface is mounted
void tuh_msc_mounted_cb(uint8_t dev_addr);
void tuh_msc_mount_cb(uint8_t dev_addr);
// Invoked when a device with MassStorage interface is unmounted
void tuh_msc_unmounted_cb(uint8_t dev_addr);
void tuh_msc_unmount_cb(uint8_t dev_addr);
//--------------------------------------------------------------------+
// Internal Class Driver API

View File

@ -98,7 +98,7 @@ enum {
//--------------------------------------------------------------------+
// Controller & Port API
//--------------------------------------------------------------------+
bool hcd_init(void);
bool hcd_init(uint8_t rhport);
void hcd_int_handler(uint8_t rhport);
void hcd_int_enable (uint8_t rhport);
void hcd_int_disable(uint8_t rhport);

View File

@ -197,7 +197,7 @@ bool tuh_init(void)
usbh_class_drivers[drv_id].init();
}
TU_ASSERT(hcd_init());
TU_ASSERT(hcd_init(TUH_OPT_RHPORT));
hcd_int_enable(TUH_OPT_RHPORT);
return true;

View File

@ -26,14 +26,17 @@
#include "common/tusb_common.h"
#if TUSB_OPT_HOST_ENABLED && (CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX)
#if TUSB_OPT_HOST_ENABLED && \
(CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || \
CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX )
//--------------------------------------------------------------------+
// INCLUDE
//--------------------------------------------------------------------+
#include "osal/osal.h"
#include "../hcd.h"
#include "../usbh_hcd.h"
#include "host/hcd.h"
#include "host/usbh_hcd.h"
#include "ehci.h"
//--------------------------------------------------------------------+
@ -48,6 +51,7 @@ CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4096) static ehci_data_t ehci_data;
// EHCI portable
uint32_t hcd_ehci_register_addr(uint8_t rhport);
bool hcd_ehci_init (uint8_t rhport); // TODO move later
//--------------------------------------------------------------------+
// PROTOTYPE
@ -97,16 +101,9 @@ static void qtd_init (ehci_qtd_t* p_qtd, void* buffer, uint16_t total_bytes);
static inline void list_insert (ehci_link_t *current, ehci_link_t *new, uint8_t new_type);
static inline ehci_link_t* list_next (ehci_link_t *p_link_pointer);
static bool ehci_init (uint8_t rhport);
//--------------------------------------------------------------------+
// HCD API
//--------------------------------------------------------------------+
bool hcd_init(void)
{
tu_memclr(&ehci_data, sizeof(ehci_data_t));
return ehci_init(TUH_OPT_RHPORT);
}
uint32_t hcd_uframe_number(uint8_t rhport)
{
@ -203,8 +200,10 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr)
}
// EHCI controller init
static bool ehci_init(uint8_t rhport)
bool hcd_ehci_init(uint8_t rhport)
{
tu_memclr(&ehci_data, sizeof(ehci_data_t));
ehci_data.regs = (ehci_registers_t* ) hcd_ehci_register_addr(rhport);
ehci_registers_t* regs = ehci_data.regs;

View File

@ -33,8 +33,6 @@
#ifndef _TUSB_EHCI_H_
#define _TUSB_EHCI_H_
#include "common/tusb_common.h"
#include "../hcd.h"
/* Abbreviation
* HC: Host Controller

View File

@ -1,50 +0,0 @@
/*
* 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.
*
* This file is part of the TinyUSB stack.
*/
#include "tusb_option.h"
#if TUSB_OPT_HOST_ENABLED && (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX)
#include "chip.h"
// LPC18xx and 43xx use EHCI driver
void hcd_int_enable(uint8_t rhport)
{
NVIC_EnableIRQ(rhport ? USB1_IRQn : USB0_IRQn);
}
void hcd_int_disable(uint8_t rhport)
{
NVIC_DisableIRQ(rhport ? USB1_IRQn : USB0_IRQn);
}
uint32_t hcd_ehci_register_addr(uint8_t rhport)
{
return (uint32_t) (rhport ? &LPC_USB1->USBCMD_H : &LPC_USB0->USBCMD_H );
}
#endif

View File

@ -0,0 +1,136 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2021, 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.
*
* This file is part of the TinyUSB stack.
*/
#ifndef COMMON_TRANSDIMENSION_H_
#define COMMON_TRANSDIMENSION_H_
#ifdef __cplusplus
extern "C" {
#endif
// USBCMD
enum {
USBCMD_RUN_STOP = TU_BIT(0),
USBCMD_RESET = TU_BIT(1),
USBCMD_SETUP_TRIPWIRE = TU_BIT(13),
USBCMD_ADD_QTD_TRIPWIRE = TU_BIT(14) ///< This bit is used as a semaphore to ensure the to proper addition of a new dTD to an active (primed) endpoints linked list. This bit is set and cleared by software during the process of adding a new dTD
// Interrupt Threshold bit 23:16
};
// PORTSC1
#define PORTSC1_PORT_SPEED_POS 26
enum {
PORTSC1_CURRENT_CONNECT_STATUS = TU_BIT(0),
PORTSC1_FORCE_PORT_RESUME = TU_BIT(6),
PORTSC1_SUSPEND = TU_BIT(7),
PORTSC1_FORCE_FULL_SPEED = TU_BIT(24),
PORTSC1_PORT_SPEED = TU_BIT(26) | TU_BIT(27)
};
// OTGSC
enum {
OTGSC_VBUS_DISCHARGE = TU_BIT(0),
OTGSC_VBUS_CHARGE = TU_BIT(1),
// OTGSC_HWASSIST_AUTORESET = TU_BIT(2),
OTGSC_OTG_TERMINATION = TU_BIT(3), ///< Must set to 1 when OTG go to device mode
OTGSC_DATA_PULSING = TU_BIT(4),
OTGSC_ID_PULLUP = TU_BIT(5),
// OTGSC_HWASSIT_DATA_PULSE = TU_BIT(6),
// OTGSC_HWASSIT_BDIS_ACONN = TU_BIT(7),
OTGSC_ID = TU_BIT(8), ///< 0 = A device, 1 = B Device
OTGSC_A_VBUS_VALID = TU_BIT(9),
OTGSC_A_SESSION_VALID = TU_BIT(10),
OTGSC_B_SESSION_VALID = TU_BIT(11),
OTGSC_B_SESSION_END = TU_BIT(12),
OTGSC_1MS_TOGGLE = TU_BIT(13),
OTGSC_DATA_BUS_PULSING_STATUS = TU_BIT(14),
};
// USBMode
enum {
USBMODE_CM_DEVICE = 2,
USBMODE_CM_HOST = 3,
USBMODE_SLOM = TU_BIT(3),
USBMODE_SDIS = TU_BIT(4),
USBMODE_VBUS_POWER_SELECT = TU_BIT(5), // Need to be enabled for LPC18XX/43XX in host mode
};
// Device Registers
typedef struct
{
//------------- ID + HW Parameter Registers-------------//
__I uint32_t TU_RESERVED[64]; ///< For iMX RT10xx, but not used by LPC18XX/LPC43XX
//------------- Capability Registers-------------//
__I uint8_t CAPLENGTH; ///< Capability Registers Length
__I uint8_t TU_RESERVED[1];
__I uint16_t HCIVERSION; ///< Host Controller Interface Version
__I uint32_t HCSPARAMS; ///< Host Controller Structural Parameters
__I uint32_t HCCPARAMS; ///< Host Controller Capability Parameters
__I uint32_t TU_RESERVED[5];
__I uint16_t DCIVERSION; ///< Device Controller Interface Version
__I uint8_t TU_RESERVED[2];
__I uint32_t DCCPARAMS; ///< Device Controller Capability Parameters
__I uint32_t TU_RESERVED[6];
//------------- Operational Registers -------------//
__IO uint32_t USBCMD; ///< USB Command Register
__IO uint32_t USBSTS; ///< USB Status Register
__IO uint32_t USBINTR; ///< Interrupt Enable Register
__IO uint32_t FRINDEX; ///< USB Frame Index
__I uint32_t TU_RESERVED;
__IO uint32_t DEVICEADDR; ///< Device Address
__IO uint32_t ENDPTLISTADDR; ///< Endpoint List Address
__I uint32_t TU_RESERVED;
__IO uint32_t BURSTSIZE; ///< Programmable Burst Size
__IO uint32_t TXFILLTUNING; ///< TX FIFO Fill Tuning
uint32_t TU_RESERVED[4];
__IO uint32_t ENDPTNAK; ///< Endpoint NAK
__IO uint32_t ENDPTNAKEN; ///< Endpoint NAK Enable
__I uint32_t TU_RESERVED;
__IO uint32_t PORTSC1; ///< Port Status & Control
__I uint32_t TU_RESERVED[7];
__IO uint32_t OTGSC; ///< On-The-Go Status & control
__IO uint32_t USBMODE; ///< USB Device Mode
__IO uint32_t ENDPTSETUPSTAT; ///< Endpoint Setup Status
__IO uint32_t ENDPTPRIME; ///< Endpoint Prime
__IO uint32_t ENDPTFLUSH; ///< Endpoint Flush
__I uint32_t ENDPTSTAT; ///< Endpoint Status
__IO uint32_t ENDPTCOMPLETE; ///< Endpoint Complete
__IO uint32_t ENDPTCTRL[8]; ///< Endpoint Control 0 - 7
} dcd_registers_t;
#ifdef __cplusplus
}
#endif
#endif /* COMMON_TRANSDIMENSION_H_ */

View File

@ -26,16 +26,12 @@
#include "tusb_option.h"
#if TUSB_OPT_DEVICE_ENABLED && (CFG_TUSB_MCU == OPT_MCU_LPC18XX || \
CFG_TUSB_MCU == OPT_MCU_LPC43XX || \
CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX)
#if TUSB_OPT_DEVICE_ENABLED && \
(CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX)
//--------------------------------------------------------------------+
// INCLUDE
//--------------------------------------------------------------------+
#include "common/tusb_common.h"
#include "device/dcd.h"
#if CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX
#include "fsl_device_registers.h"
#else
@ -43,6 +39,10 @@
#include "chip.h"
#endif
#include "common/tusb_common.h"
#include "device/dcd.h"
#include "common_transdimension.h"
#if defined(__CORTEX_M) && __CORTEX_M == 7 && __DCACHE_PRESENT == 1
#define CleanInvalidateDCache_by_Addr SCB_CleanInvalidateDCache_by_Addr
#else
@ -61,15 +61,6 @@ enum {
ENDPTCTRL_ENABLE = TU_BIT(7)
};
// USBCMD
enum {
USBCMD_RUN_STOP = TU_BIT(0),
USBCMD_RESET = TU_BIT(1),
USBCMD_SETUP_TRIPWIRE = TU_BIT(13),
USBCMD_ADD_QTD_TRIPWIRE = TU_BIT(14) ///< This bit is used as a semaphore to ensure the to proper addition of a new dTD to an active (primed) endpoints linked list. This bit is set and cleared by software during the process of adding a new dTD
};
// Interrupt Threshold bit 23:16
// USBSTS, USBINTR
enum {
INTR_USB = TU_BIT(0),
@ -81,96 +72,6 @@ enum {
INTR_NAK = TU_BIT(16)
};
// PORTSC1
#define PORTSC1_PORT_SPEED_POS 26
enum {
PORTSC1_CURRENT_CONNECT_STATUS = TU_BIT(0),
PORTSC1_FORCE_PORT_RESUME = TU_BIT(6),
PORTSC1_SUSPEND = TU_BIT(7),
PORTSC1_FORCE_FULL_SPEED = TU_BIT(24),
PORTSC1_PORT_SPEED = TU_BIT(26) | TU_BIT(27)
};
// OTGSC
enum {
OTGSC_VBUS_DISCHARGE = TU_BIT(0),
OTGSC_VBUS_CHARGE = TU_BIT(1),
// OTGSC_HWASSIST_AUTORESET = TU_BIT(2),
OTGSC_OTG_TERMINATION = TU_BIT(3), ///< Must set to 1 when OTG go to device mode
OTGSC_DATA_PULSING = TU_BIT(4),
OTGSC_ID_PULLUP = TU_BIT(5),
// OTGSC_HWASSIT_DATA_PULSE = TU_BIT(6),
// OTGSC_HWASSIT_BDIS_ACONN = TU_BIT(7),
OTGSC_ID = TU_BIT(8), ///< 0 = A device, 1 = B Device
OTGSC_A_VBUS_VALID = TU_BIT(9),
OTGSC_A_SESSION_VALID = TU_BIT(10),
OTGSC_B_SESSION_VALID = TU_BIT(11),
OTGSC_B_SESSION_END = TU_BIT(12),
OTGSC_1MS_TOGGLE = TU_BIT(13),
OTGSC_DATA_BUS_PULSING_STATUS = TU_BIT(14),
};
// USBMode
enum {
USBMODE_CM_DEVICE = 2,
USBMODE_CM_HOST = 3,
USBMODE_SLOM = TU_BIT(3),
USBMODE_SDIS = TU_BIT(4),
USBMODE_VBUS_POWER_SELCT = TU_BIT(5), // Enable for LPC18XX/43XX in host most only
};
// Device Registers
typedef struct
{
//------------- ID + HW Parameter Registers-------------//
__I uint32_t TU_RESERVED[64]; ///< For iMX RT10xx, but not used by LPC18XX/LPC43XX
//------------- Capability Registers-------------//
__I uint8_t CAPLENGTH; ///< Capability Registers Length
__I uint8_t TU_RESERVED[1];
__I uint16_t HCIVERSION; ///< Host Controller Interface Version
__I uint32_t HCSPARAMS; ///< Host Controller Structural Parameters
__I uint32_t HCCPARAMS; ///< Host Controller Capability Parameters
__I uint32_t TU_RESERVED[5];
__I uint16_t DCIVERSION; ///< Device Controller Interface Version
__I uint8_t TU_RESERVED[2];
__I uint32_t DCCPARAMS; ///< Device Controller Capability Parameters
__I uint32_t TU_RESERVED[6];
//------------- Operational Registers -------------//
__IO uint32_t USBCMD; ///< USB Command Register
__IO uint32_t USBSTS; ///< USB Status Register
__IO uint32_t USBINTR; ///< Interrupt Enable Register
__IO uint32_t FRINDEX; ///< USB Frame Index
__I uint32_t TU_RESERVED;
__IO uint32_t DEVICEADDR; ///< Device Address
__IO uint32_t ENDPTLISTADDR; ///< Endpoint List Address
__I uint32_t TU_RESERVED;
__IO uint32_t BURSTSIZE; ///< Programmable Burst Size
__IO uint32_t TXFILLTUNING; ///< TX FIFO Fill Tuning
uint32_t TU_RESERVED[4];
__IO uint32_t ENDPTNAK; ///< Endpoint NAK
__IO uint32_t ENDPTNAKEN; ///< Endpoint NAK Enable
__I uint32_t TU_RESERVED;
__IO uint32_t PORTSC1; ///< Port Status & Control
__I uint32_t TU_RESERVED[7];
__IO uint32_t OTGSC; ///< On-The-Go Status & control
__IO uint32_t USBMODE; ///< USB Device Mode
__IO uint32_t ENDPTSETUPSTAT; ///< Endpoint Setup Status
__IO uint32_t ENDPTPRIME; ///< Endpoint Prime
__IO uint32_t ENDPTFLUSH; ///< Endpoint Flush
__I uint32_t ENDPTSTAT; ///< Endpoint Status
__IO uint32_t ENDPTCOMPLETE; ///< Endpoint Complete
__IO uint32_t ENDPTCTRL[8]; ///< Endpoint Control 0 - 7
} dcd_registers_t;
// Queue Transfer Descriptor
typedef struct
{
@ -280,7 +181,7 @@ CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(2048)
static dcd_data_t _dcd_data;
//--------------------------------------------------------------------+
// CONTROLLER API
// Controller API
//--------------------------------------------------------------------+
/// follows LPC43xx User Manual 23.10.3

View File

@ -0,0 +1,127 @@
/*
* 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.
*
* This file is part of the TinyUSB stack.
*/
#include "tusb_option.h"
// NXP Trans-Dimension USB IP implement EHCI for host functionality
#if TUSB_OPT_HOST_ENABLED && \
(CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX)
//--------------------------------------------------------------------+
// INCLUDE
//--------------------------------------------------------------------+
#if CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX
#include "fsl_device_registers.h"
#else
// LPCOpen for 18xx & 43xx
#include "chip.h"
#endif
#include "common/tusb_common.h"
#include "common_transdimension.h"
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
// TODO can be merged with dcd_controller_t
typedef struct
{
uint32_t regs_base; // registers base
const IRQn_Type irqnum; // IRQ number
}hcd_controller_t;
#if CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX
static const hcd_controller_t _hcd_controller[] =
{
// RT1010 and RT1020 only has 1 USB controller
#if FSL_FEATURE_SOC_USBHS_COUNT == 1
{ .regs_base = USB_BASE , .irqnum = USB_OTG1_IRQn }
#else
{ .regs_base = USB1_BASE, .irqnum = USB_OTG1_IRQn },
{ .regs_base = USB2_BASE, .irqnum = USB_OTG2_IRQn }
#endif
};
#else
static const hcd_controller_t _hcd_controller[] =
{
{ .regs_base = LPC_USB0_BASE, .irqnum = USB0_IRQn },
{ .regs_base = LPC_USB1_BASE, .irqnum = USB1_IRQn }
};
#endif
// TODO better prototype later
extern bool hcd_ehci_init (uint8_t rhport); // from ehci.c
//--------------------------------------------------------------------+
// Controller API
//--------------------------------------------------------------------+
bool hcd_init(uint8_t rhport)
{
dcd_registers_t* dcd_reg = (dcd_registers_t*) _hcd_controller[rhport].regs_base;
// Reset controller
dcd_reg->USBCMD |= USBCMD_RESET;
while( dcd_reg->USBCMD & USBCMD_RESET ) {}
// Set mode to device, must be set immediately after reset
#if CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX
// LPC18XX/43XX need to set VBUS Power Select to HIGH
// RHPORT1 is fullspeed only (need external PHY for Highspeed)
dcd_reg->USBMODE = USBMODE_CM_HOST | USBMODE_VBUS_POWER_SELECT;
if (rhport == 1) dcd_reg->PORTSC1 |= PORTSC1_FORCE_FULL_SPEED;
#else
dcd_reg->USBMODE = USBMODE_CM_HOST;
#endif
// FIXME force full speed, still have issue with Highspeed enumeration
dcd_reg->PORTSC1 |= PORTSC1_FORCE_FULL_SPEED;
return hcd_ehci_init(rhport);
}
void hcd_int_enable(uint8_t rhport)
{
NVIC_EnableIRQ(_hcd_controller[rhport].irqnum);
}
void hcd_int_disable(uint8_t rhport)
{
NVIC_DisableIRQ(_hcd_controller[rhport].irqnum);
}
uint32_t hcd_ehci_register_addr(uint8_t rhport)
{
dcd_registers_t* hcd_reg = (dcd_registers_t*) _hcd_controller[rhport].regs_base;
// EHCI USBCMD has same address within dcd_register_t
return (uint32_t) &hcd_reg->USBCMD;
}
#endif

View File

@ -26,14 +26,16 @@
#include <common/tusb_common.h>
#if TUSB_OPT_HOST_ENABLED && (CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC40XX)
#if TUSB_OPT_HOST_ENABLED && \
(CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC40XX)
//--------------------------------------------------------------------+
// INCLUDE
//--------------------------------------------------------------------+
#include "osal/osal.h"
#include "../hcd.h"
#include "../usbh_hcd.h"
#include "host/hcd.h"
#include "host/usbh_hcd.h"
#include "ohci.h"
// TODO remove
@ -141,8 +143,10 @@ static void ed_list_remove_by_addr(ohci_ed_t * p_head, uint8_t dev_addr);
// USBH-HCD API
//--------------------------------------------------------------------+
// Initialization according to 5.1.1.4
bool hcd_init(void)
bool hcd_init(uint8_t rhport)
{
(void) rhport;
//------------- Data Structure init -------------//
tu_memclr(&ohci_data, sizeof(ohci_data_t));
for(uint8_t i=0; i<32; i++)

View File

@ -37,8 +37,6 @@
extern "C" {
#endif
#include "common/tusb_common.h"
//--------------------------------------------------------------------+
// OHCI CONFIGURATION & CONSTANTS
//--------------------------------------------------------------------+

View File

@ -48,8 +48,8 @@
// Init these in dcd_init
static uint8_t *next_buffer_ptr;
// Endpoints 0-15, direction TUSB_DIR_OUT for out and TUSB_DIR_IN for in.
static struct hw_endpoint hw_endpoints[16][2] = {0};
// USB_MAX_ENDPOINTS Endpoints, direction TUSB_DIR_OUT for out and TUSB_DIR_IN for in.
static struct hw_endpoint hw_endpoints[USB_MAX_ENDPOINTS][2] = {0};
static inline struct hw_endpoint *hw_endpoint_get_by_num(uint8_t num, tusb_dir_t dir)
{
@ -65,7 +65,7 @@ static struct hw_endpoint *hw_endpoint_get_by_addr(uint8_t ep_addr)
static void _hw_endpoint_alloc(struct hw_endpoint *ep)
{
uint size = TU_MIN(64, ep->wMaxPacketSize);
uint16_t size = tu_min16(64, ep->wMaxPacketSize);
// Assumes single buffered for now
ep->hw_data_buf = next_buffer_ptr;
@ -100,7 +100,7 @@ static void _hw_endpoint_alloc(struct hw_endpoint *ep)
*ep->endpoint_control = reg;
}
static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t ep_addr, uint wMaxPacketSize, uint8_t transfer_type)
static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type)
{
uint8_t num = tu_edpt_number(ep_addr);
tusb_dir_t dir = tu_edpt_dir(ep_addr);
@ -193,7 +193,7 @@ static void hw_endpoint_close(uint8_t ep_addr)
}
#endif
static void hw_endpoint_init(uint8_t ep_addr, uint wMaxPacketSize, uint8_t bmAttributes)
static void hw_endpoint_init(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t bmAttributes)
{
struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr);
_hw_endpoint_init(ep, ep_addr, wMaxPacketSize, bmAttributes);

View File

@ -30,7 +30,6 @@
#include <stdlib.h>
#include "rp2040_usb.h"
#include "hardware/clocks.h"
// Direction strings for debug
const char *ep_dir_string[] = {
@ -153,7 +152,7 @@ void _hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t t
// Fill in info now that we're kicking off the hw
ep->total_len = total_len;
ep->len = 0;
ep->transfer_size = tu_min32(total_len, ep->wMaxPacketSize);
ep->transfer_size = tu_min16(total_len, ep->wMaxPacketSize);
ep->active = true;
ep->user_buf = buffer;
// Recalculate if this is the last buffer
@ -172,7 +171,7 @@ void _hw_endpoint_xfer_sync(struct hw_endpoint *ep)
// Get the buffer state and amount of bytes we have
// transferred
uint32_t buf_ctrl = _hw_endpoint_buffer_control_get_value32(ep);
uint transferred_bytes = buf_ctrl & USB_BUF_CTRL_LEN_MASK;
uint16_t transferred_bytes = buf_ctrl & USB_BUF_CTRL_LEN_MASK;
#ifdef RP2040_USB_HOST_MODE
// tag::host_buf_sel_fix[]
@ -230,8 +229,8 @@ bool _hw_endpoint_xfer_continue(struct hw_endpoint *ep)
_hw_endpoint_xfer_sync(ep);
// Now we have synced our state with the hardware. Is there more data to transfer?
uint remaining_bytes = ep->total_len - ep->len;
ep->transfer_size = tu_min32(remaining_bytes, ep->wMaxPacketSize);
uint16_t remaining_bytes = ep->total_len - ep->len;
ep->transfer_size = tu_min16(remaining_bytes, ep->wMaxPacketSize);
_hw_endpoint_update_last_buf(ep);
// Can happen because of programmer error so check for it

View File

@ -63,10 +63,10 @@ struct hw_endpoint
// Current transfer information
bool active;
uint total_len;
uint len;
uint16_t total_len;
uint16_t len;
// Amount of data with the hardware
uint transfer_size;
uint16_t transfer_size;
// Only needed for host mode
bool last_buf;
// HOST BUG. Host will incorrect write status to top half of buffer
@ -76,7 +76,7 @@ struct hw_endpoint
uint8_t *user_buf;
// Data needed from EP descriptor
uint wMaxPacketSize;
uint16_t wMaxPacketSize;
// Interrupt, bulk, etc
uint8_t transfer_type;

View File

@ -329,6 +329,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to
{
if (total_bytes == 0)
{
usbdcd_driver.setup_processed = true;
dcd_event_xfer_complete(0, ep_addr, 0, XFER_RESULT_SUCCESS, false);
}
else if (ep_addr == 0x00 && total_bytes == usbdcd_driver.outlen)
@ -350,12 +351,15 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to
}
}
usbdcd_driver.setup_processed = true;
struct usb_ctrlreq_s ctrl;
if (osal_queue_receive(usbdcd_driver.setup_queue, &ctrl))
if (usbdcd_driver.setup_processed)
{
dcd_event_setup_received(0, (uint8_t *)&ctrl, false);
if (osal_queue_receive(usbdcd_driver.setup_queue, &ctrl))
{
usbdcd_driver.setup_processed = false;
dcd_event_setup_received(0, (uint8_t *)&ctrl, false);
}
}
}
else