IAR line ending warning

This commit is contained in:
hathach 2014-03-12 14:08:52 +07:00
parent 8f03dea95a
commit 9ba209cda0
15 changed files with 2989 additions and 2991 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,163 +1,163 @@
/**************************************************************************/
/*!
@file main.c
@author hathach (tinyusb.org)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2013, hathach (tinyusb.org)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This file is part of the tinyusb stack.
*/
/**************************************************************************/
//--------------------------------------------------------------------+
// INCLUDE
//--------------------------------------------------------------------+
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "boards/board.h"
#include "tusb.h"
#include "mscd_app.h"
#include "keyboardd_app.h"
#include "moused_app.h"
#include "cdcd_app.h"
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
OSAL_TASK_FUNCTION( led_blinking_task ) (void* p_task_para);
OSAL_TASK_DEF(led_blinking_task, 128, LED_BLINKING_APP_TASK_PRIO);
void print_greeting(void);
#if TUSB_CFG_OS == TUSB_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_runner();
led_blinking_task(NULL);
keyboardd_app_task(NULL);
moused_app_task(NULL);
cdcd_serial_app_task(NULL);
}
}
#endif
int main(void)
{
board_init();
print_greeting();
tusb_init();
//------------- application task init -------------//
(void) osal_task_create( OSAL_TASK_REF(led_blinking_task) );
msc_dev_app_init();
keyboardd_app_init();
moused_app_init();
cdcd_serial_app_init();
//------------- start OS scheduler (never return) -------------//
#if TUSB_CFG_OS == TUSB_OS_FREERTOS
vTaskStartScheduler();
#elif TUSB_CFG_OS == TUSB_OS_NONE
os_none_start_scheduler();
#elif TUSB_CFG_OS == TUSB_OS_CMSIS_RTX
while(1)
{
osDelay(osWaitForever); // CMSIS RTX osKernelStart already started, main() is a task
}
#else
#error need to start RTOS schduler
#endif
while(1) { } // should not reach here
return 0;
}
//--------------------------------------------------------------------+
// BLINKING TASK
//--------------------------------------------------------------------+
static uint32_t led_blink_interval_ms = 1000; // default is 1 seconda
void led_blinking_set_interval(uint32_t ms)
{
led_blink_interval_ms = ms;
}
OSAL_TASK_FUNCTION( led_blinking_task ) (void* p_task_para)
{
OSAL_TASK_LOOP_BEGIN
static uint32_t led_on_mask = 0;
osal_task_delay(led_blink_interval_ms);
board_leds(led_on_mask, 1 - led_on_mask);
led_on_mask = 1 - led_on_mask; // toggle
uint32_t btn_mask = board_buttons();
for(uint8_t i=0; i<32; i++)
{
if ( BIT_TEST_(btn_mask, i) ) printf("button %d is pressed\n", i);
}
OSAL_TASK_LOOP_END
}
//--------------------------------------------------------------------+
// HELPER FUNCTION
//--------------------------------------------------------------------+
void print_greeting(void)
{
printf("\n\
--------------------------------------------------------------------\n\
- Device 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\n"
);
puts("This demo supports the following classes");
if (TUSB_CFG_DEVICE_HID_MOUSE ) puts(" - HID Mouse");
if (TUSB_CFG_DEVICE_HID_KEYBOARD ) puts(" - HID Keyboard");
if (TUSB_CFG_DEVICE_MSC ) puts(" - Mass Storage");
if (TUSB_CFG_DEVICE_CDC ) puts(" - Communication Device Class");
}
/**************************************************************************/
/*!
@file main.c
@author hathach (tinyusb.org)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2013, hathach (tinyusb.org)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This file is part of the tinyusb stack.
*/
/**************************************************************************/
//--------------------------------------------------------------------+
// INCLUDE
//--------------------------------------------------------------------+
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "boards/board.h"
#include "tusb.h"
#include "mscd_app.h"
#include "keyboardd_app.h"
#include "moused_app.h"
#include "cdcd_app.h"
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
OSAL_TASK_FUNCTION( led_blinking_task ) (void* p_task_para);
OSAL_TASK_DEF(led_blinking_task, 128, LED_BLINKING_APP_TASK_PRIO);
void print_greeting(void);
#if TUSB_CFG_OS == TUSB_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_runner();
led_blinking_task(NULL);
keyboardd_app_task(NULL);
moused_app_task(NULL);
cdcd_serial_app_task(NULL);
}
}
#endif
int main(void)
{
board_init();
print_greeting();
tusb_init();
//------------- application task init -------------//
(void) osal_task_create( OSAL_TASK_REF(led_blinking_task) );
msc_dev_app_init();
keyboardd_app_init();
moused_app_init();
cdcd_serial_app_init();
//------------- start OS scheduler (never return) -------------//
#if TUSB_CFG_OS == TUSB_OS_FREERTOS
vTaskStartScheduler();
#elif TUSB_CFG_OS == TUSB_OS_NONE
os_none_start_scheduler();
#elif TUSB_CFG_OS == TUSB_OS_CMSIS_RTX
while(1)
{
osDelay(osWaitForever); // CMSIS RTX osKernelStart already started, main() is a task
}
#else
#error need to start RTOS schduler
#endif
while(1) { } // should not reach here
return 0;
}
//--------------------------------------------------------------------+
// BLINKING TASK
//--------------------------------------------------------------------+
static uint32_t led_blink_interval_ms = 1000; // default is 1 seconda
void led_blinking_set_interval(uint32_t ms)
{
led_blink_interval_ms = ms;
}
OSAL_TASK_FUNCTION( led_blinking_task ) (void* p_task_para)
{
OSAL_TASK_LOOP_BEGIN
static uint32_t led_on_mask = 0;
osal_task_delay(led_blink_interval_ms);
board_leds(led_on_mask, 1 - led_on_mask);
led_on_mask = 1 - led_on_mask; // toggle
uint32_t btn_mask = board_buttons();
for(uint8_t i=0; i<32; i++)
{
if ( BIT_TEST_(btn_mask, i) ) printf("button %d is pressed\n", i);
}
OSAL_TASK_LOOP_END
}
//--------------------------------------------------------------------+
// HELPER FUNCTION
//--------------------------------------------------------------------+
void print_greeting(void)
{
printf("\n\
--------------------------------------------------------------------\n\
- Device 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\n"
);
puts("This demo supports the following classes");
if (TUSB_CFG_DEVICE_HID_MOUSE ) puts(" - HID Mouse");
if (TUSB_CFG_DEVICE_HID_KEYBOARD ) puts(" - HID Keyboard");
if (TUSB_CFG_DEVICE_MSC ) puts(" - Mass Storage");
if (TUSB_CFG_DEVICE_CDC ) puts(" - Communication Device Class");
}

View File

@ -52,17 +52,15 @@
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
typedef struct {
uint8_t interface_number;
endpoint_handle_t edpt_in, edpt_out;
// must be in USB ram
ATTR_USB_MIN_ALIGNMENT uint8_t max_lun; // can STALL for one LUN
ATTR_USB_MIN_ALIGNMENT msc_cmd_block_wrapper_t cbw;
ATTR_USB_MIN_ALIGNMENT msc_cmd_status_wrapper_t csw;
ATTR_USB_MIN_ALIGNMENT uint8_t max_lun; // can STALL for one LUN
uint8_t interface_number;
endpoint_handle_t edpt_in, edpt_out;
}mscd_interface_t;
TUSB_CFG_ATTR_USBRAM STATIC_VAR mscd_interface_t mscd_data;
ATTR_USB_MIN_ALIGNMENT TUSB_CFG_ATTR_USBRAM STATIC_VAR mscd_interface_t mscd_data;
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+

View File

@ -1,429 +1,429 @@
/**************************************************************************/
/*!
@file msc_host.c
@author hathach (tinyusb.org)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2013, hathach (tinyusb.org)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This file is part of the tinyusb stack.
*/
/**************************************************************************/
#include "tusb_option.h"
#if MODE_HOST_SUPPORTED & TUSB_CFG_HOST_MSC
#define _TINY_USB_SOURCE_FILE_
//--------------------------------------------------------------------+
// INCLUDE
//--------------------------------------------------------------------+
#include "common/common.h"
#include "msc_host.h"
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
TUSB_CFG_ATTR_USBRAM STATIC_VAR msch_interface_t msch_data[TUSB_CFG_HOST_DEVICE_MAX];
//------------- Initalization Data -------------//
OSAL_SEM_DEF(msch_semaphore);
static osal_semaphore_handle_t msch_sem_hdl;
// buffer used to read scsi information when mounted, largest response data currently is inquiry
TUSB_CFG_ATTR_USBRAM ATTR_ALIGNED(4) STATIC_VAR uint8_t msch_buffer[sizeof(scsi_inquiry_data_t)];
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
//--------------------------------------------------------------------+
// PUBLIC API
//--------------------------------------------------------------------+
bool tusbh_msc_is_mounted(uint8_t dev_addr)
{
return tusbh_device_is_configured(dev_addr) && // is configured can be omitted
msch_data[dev_addr-1].is_initialized;
}
bool tusbh_msc_is_busy(uint8_t dev_addr)
{
return msch_data[dev_addr-1].is_initialized &&
hcd_pipe_is_busy(msch_data[dev_addr-1].bulk_in);
}
uint8_t const* tusbh_msc_get_vendor_name(uint8_t dev_addr)
{
return msch_data[dev_addr-1].is_initialized ? msch_data[dev_addr-1].vendor_id : NULL;
}
uint8_t const* tusbh_msc_get_product_name(uint8_t dev_addr)
{
return msch_data[dev_addr-1].is_initialized ? msch_data[dev_addr-1].product_id : NULL;
}
tusb_error_t tusbh_msc_get_capacity(uint8_t dev_addr, uint32_t* p_last_lba, uint32_t* p_block_size)
{
if ( !msch_data[dev_addr-1].is_initialized ) return TUSB_ERROR_MSCH_DEVICE_NOT_MOUNTED;
ASSERT(p_last_lba != NULL && p_block_size != NULL, TUSB_ERROR_INVALID_PARA);
(*p_last_lba) = msch_data[dev_addr-1].last_lba;
(*p_block_size) = (uint32_t) msch_data[dev_addr-1].block_size;
return TUSB_ERROR_NONE;
}
//--------------------------------------------------------------------+
// PUBLIC API: SCSI COMMAND
//--------------------------------------------------------------------+
static inline void msc_cbw_add_signature(msc_cmd_block_wrapper_t *p_cbw, uint8_t lun) ATTR_ALWAYS_INLINE;
static inline void msc_cbw_add_signature(msc_cmd_block_wrapper_t *p_cbw, uint8_t lun)
{
p_cbw->signature = MSC_CBW_SIGNATURE;
p_cbw->tag = 0xCAFECAFE;
p_cbw->lun = lun;
}
static tusb_error_t msch_command_xfer(msch_interface_t * p_msch, void* p_buffer) ATTR_WARN_UNUSED_RESULT;
static tusb_error_t msch_command_xfer(msch_interface_t * p_msch, void* p_buffer)
{
if ( NULL != p_buffer)
{ // there is data phase
if (p_msch->cbw.dir & TUSB_DIR_DEV_TO_HOST_MASK)
{
ASSERT_STATUS( hcd_pipe_xfer(p_msch->bulk_out, (uint8_t*) &p_msch->cbw, sizeof(msc_cmd_block_wrapper_t), false) );
ASSERT_STATUS( hcd_pipe_queue_xfer(p_msch->bulk_in , p_buffer, p_msch->cbw.xfer_bytes) );
}else
{
ASSERT_STATUS( hcd_pipe_queue_xfer(p_msch->bulk_out, (uint8_t*) &p_msch->cbw, sizeof(msc_cmd_block_wrapper_t)) );
ASSERT_STATUS( hcd_pipe_xfer(p_msch->bulk_out , p_buffer, p_msch->cbw.xfer_bytes, false) );
}
}
ASSERT_STATUS( hcd_pipe_xfer(p_msch->bulk_in , (uint8_t*) &p_msch->csw, sizeof(msc_cmd_status_wrapper_t), true) );
return TUSB_ERROR_NONE;
}
tusb_error_t tusbh_msc_inquiry(uint8_t dev_addr, uint8_t lun, uint8_t *p_data)
{
msch_interface_t* p_msch = &msch_data[dev_addr-1];
//------------- Command Block Wrapper -------------//
msc_cbw_add_signature(&p_msch->cbw, lun);
p_msch->cbw.xfer_bytes = sizeof(scsi_inquiry_data_t);
p_msch->cbw.dir = TUSB_DIR_DEV_TO_HOST_MASK;
p_msch->cbw.cmd_len = sizeof(scsi_inquiry_t);
//------------- SCSI command -------------//
scsi_inquiry_t cmd_inquiry =
{
.cmd_code = SCSI_CMD_INQUIRY,
.alloc_length = sizeof(scsi_inquiry_data_t)
};
memcpy(p_msch->cbw.command, &cmd_inquiry, p_msch->cbw.cmd_len);
ASSERT_STATUS ( msch_command_xfer(p_msch, p_data) );
return TUSB_ERROR_NONE;
}
tusb_error_t tusbh_msc_read_capacity10(uint8_t dev_addr, uint8_t lun, uint8_t *p_data)
{
msch_interface_t* p_msch = &msch_data[dev_addr-1];
//------------- Command Block Wrapper -------------//
msc_cbw_add_signature(&p_msch->cbw, lun);
p_msch->cbw.xfer_bytes = sizeof(scsi_read_capacity10_data_t);
p_msch->cbw.dir = TUSB_DIR_DEV_TO_HOST_MASK;
p_msch->cbw.cmd_len = sizeof(scsi_read_capacity10_t);
//------------- SCSI command -------------//
scsi_read_capacity10_t cmd_read_capacity10 =
{
.cmd_code = SCSI_CMD_READ_CAPACITY_10,
.lba = 0,
.partial_medium_indicator = 0
};
memcpy(p_msch->cbw.command, &cmd_read_capacity10, p_msch->cbw.cmd_len);
ASSERT_STATUS ( msch_command_xfer(p_msch, p_data) );
return TUSB_ERROR_NONE;
}
tusb_error_t tusbh_msc_request_sense(uint8_t dev_addr, uint8_t lun, uint8_t *p_data)
{
msch_interface_t* p_msch = &msch_data[dev_addr-1];
//------------- Command Block Wrapper -------------//
p_msch->cbw.xfer_bytes = 18;
p_msch->cbw.dir = TUSB_DIR_DEV_TO_HOST_MASK;
p_msch->cbw.cmd_len = sizeof(scsi_request_sense_t);
//------------- SCSI command -------------//
scsi_request_sense_t cmd_request_sense =
{
.cmd_code = SCSI_CMD_REQUEST_SENSE,
.alloc_length = 18
};
memcpy(p_msch->cbw.command, &cmd_request_sense, p_msch->cbw.cmd_len);
ASSERT_STATUS ( msch_command_xfer(p_msch, p_data) );
return TUSB_ERROR_NONE;
}
tusb_error_t tusbh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, msc_cmd_status_wrapper_t * p_csw)
{
msch_interface_t* p_msch = &msch_data[dev_addr-1];
//------------- Command Block Wrapper -------------//
msc_cbw_add_signature(&p_msch->cbw, lun);
p_msch->cbw.xfer_bytes = 0; // Number of bytes
p_msch->cbw.dir = TUSB_DIR_HOST_TO_DEV;
p_msch->cbw.cmd_len = sizeof(scsi_test_unit_ready_t);
//------------- SCSI command -------------//
scsi_test_unit_ready_t cmd_test_unit_ready =
{
.cmd_code = SCSI_CMD_TEST_UNIT_READY,
.lun = lun // according to wiki
};
memcpy(p_msch->cbw.command, &cmd_test_unit_ready, p_msch->cbw.cmd_len);
// TODO MSCH refractor test uinit ready
ASSERT_STATUS( hcd_pipe_xfer(p_msch->bulk_out, (uint8_t*) &p_msch->cbw, sizeof(msc_cmd_block_wrapper_t), false) );
ASSERT_STATUS( hcd_pipe_xfer(p_msch->bulk_in , (uint8_t*) p_csw, sizeof(msc_cmd_status_wrapper_t), true) );
return TUSB_ERROR_NONE;
}
tusb_error_t tusbh_msc_read10(uint8_t dev_addr, uint8_t lun, void * 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.xfer_bytes = p_msch->block_size*block_count; // Number of bytes
p_msch->cbw.dir = TUSB_DIR_DEV_TO_HOST_MASK;
p_msch->cbw.cmd_len = sizeof(scsi_read10_t);
//------------- SCSI command -------------//
scsi_read10_t cmd_read10 =
{
.cmd_code = SCSI_CMD_READ_10,
.lba = __n2be(lba),
.block_count = u16_le2be(block_count)
};
memcpy(p_msch->cbw.command, &cmd_read10, p_msch->cbw.cmd_len);
ASSERT_STATUS ( msch_command_xfer(p_msch, p_buffer));
return TUSB_ERROR_NONE;
}
tusb_error_t tusbh_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.xfer_bytes = p_msch->block_size*block_count; // Number of bytes
p_msch->cbw.dir = TUSB_DIR_HOST_TO_DEV;
p_msch->cbw.cmd_len = sizeof(scsi_write10_t);
//------------- SCSI command -------------//
scsi_write10_t cmd_write10 =
{
.cmd_code = SCSI_CMD_WRITE_10,
.lba = __n2be(lba),
.block_count = u16_le2be(block_count)
};
memcpy(p_msch->cbw.command, &cmd_write10, p_msch->cbw.cmd_len);
ASSERT_STATUS ( msch_command_xfer(p_msch, (void*) p_buffer));
return TUSB_ERROR_NONE;
}
//--------------------------------------------------------------------+
// CLASS-USBH API (don't require to verify parameters)
//--------------------------------------------------------------------+
void msch_init(void)
{
memclr_(msch_data, sizeof(msch_interface_t)*TUSB_CFG_HOST_DEVICE_MAX);
msch_sem_hdl = osal_semaphore_create( OSAL_SEM_REF(msch_semaphore) );
}
tusb_error_t msch_open_subtask(uint8_t dev_addr, tusb_descriptor_interface_t const *p_interface_desc, uint16_t *p_length)
{
tusb_error_t error;
OSAL_SUBTASK_BEGIN
if (! ( MSC_SUBCLASS_SCSI == p_interface_desc->bInterfaceSubClass &&
MSC_PROTOCOL_BOT == p_interface_desc->bInterfaceProtocol ) )
{
return TUSB_ERROR_MSC_UNSUPPORTED_PROTOCOL;
}
//------------- Open Data Pipe -------------//
tusb_descriptor_endpoint_t const *p_endpoint = (tusb_descriptor_endpoint_t const *) descriptor_next( (uint8_t const*) p_interface_desc );
for(uint32_t i=0; i<2; i++)
{
SUBTASK_ASSERT(TUSB_DESC_TYPE_ENDPOINT == p_endpoint->bDescriptorType);
SUBTASK_ASSERT(TUSB_XFER_BULK == p_endpoint->bmAttributes.xfer);
pipe_handle_t * p_pipe_hdl = ( p_endpoint->bEndpointAddress & TUSB_DIR_DEV_TO_HOST_MASK ) ?
&msch_data[dev_addr-1].bulk_in : &msch_data[dev_addr-1].bulk_out;
(*p_pipe_hdl) = hcd_pipe_open(dev_addr, p_endpoint, TUSB_CLASS_MSC);
SUBTASK_ASSERT( pipehandle_is_valid(*p_pipe_hdl) );
p_endpoint = (tusb_descriptor_endpoint_t const *) descriptor_next( (uint8_t const*) p_endpoint );
}
msch_data[dev_addr-1].interface_number = p_interface_desc->bInterfaceNumber;
(*p_length) += sizeof(tusb_descriptor_interface_t) + 2*sizeof(tusb_descriptor_endpoint_t);
//------------- Get Max Lun -------------//
OSAL_SUBTASK_INVOKED_AND_WAIT(
usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_DEV_TO_HOST, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_INTERFACE),
MSC_REQUEST_GET_MAX_LUN, 0, msch_data[dev_addr-1].interface_number,
1, msch_buffer ),
error
);
SUBTASK_ASSERT( TUSB_ERROR_NONE == error /* && TODO STALL means zero */);
msch_data[dev_addr-1].max_lun = msch_buffer[0];
#if 0
//------------- Reset -------------//
OSAL_SUBTASK_INVOKED_AND_WAIT(
usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_HOST_TO_DEV, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_INTERFACE),
MSC_REQUEST_RESET, 0, msch_data[dev_addr-1].interface_number,
0, NULL ),
error
);
#endif
enum { SCSI_XFER_TIMEOUT = 2000 };
//------------- SCSI Inquiry -------------//
tusbh_msc_inquiry(dev_addr, 0, msch_buffer);
osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT, &error);
SUBTASK_ASSERT_STATUS(error);
memcpy(msch_data[dev_addr-1].vendor_id , ((scsi_inquiry_data_t*) msch_buffer)->vendor_id , 8);
memcpy(msch_data[dev_addr-1].product_id, ((scsi_inquiry_data_t*) msch_buffer)->product_id, 16);
//------------- SCSI Read Capacity 10 -------------//
tusbh_msc_read_capacity10(dev_addr, 0, msch_buffer);
osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT, &error);
SUBTASK_ASSERT_STATUS(error);
// NOTE: my toshiba thumb-drive stall the first Read Capacity and require the sequence
// Read Capacity --> Stalled --> Clear Stall --> Request Sense --> Read Capacity (2) to work
if ( hcd_pipe_is_stalled(msch_data[dev_addr-1].bulk_in) )
{ // clear stall TODO abstract clear stall function
OSAL_SUBTASK_INVOKED_AND_WAIT(
usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_HOST_TO_DEV, TUSB_REQUEST_TYPE_STANDARD, TUSB_REQUEST_RECIPIENT_ENDPOINT),
TUSB_REQUEST_CLEAR_FEATURE, 0, hcd_pipe_get_endpoint_addr(msch_data[dev_addr-1].bulk_in),
0, NULL ),
error
);
SUBTASK_ASSERT_STATUS(error);
hcd_pipe_clear_stall(msch_data[dev_addr-1].bulk_in);
osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT, &error); // wait for SCSI status
SUBTASK_ASSERT_STATUS(error);
//------------- SCSI Request Sense -------------//
tusbh_msc_request_sense(dev_addr, 0, msch_buffer);
osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT, &error);
SUBTASK_ASSERT_STATUS(error);
//------------- Re-read SCSI Read Capactity -------------//
tusbh_msc_read_capacity10(dev_addr, 0, msch_buffer);
osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT, &error);
SUBTASK_ASSERT_STATUS(error);
}
msch_data[dev_addr-1].last_lba = __be2n( ((scsi_read_capacity10_data_t*)msch_buffer)->last_lba );
msch_data[dev_addr-1].block_size = (uint16_t) __be2n( ((scsi_read_capacity10_data_t*)msch_buffer)->block_size );
msch_data[dev_addr-1].is_initialized = true;
tusbh_msc_mounted_cb(dev_addr);
OSAL_SUBTASK_END
}
void msch_isr(pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes)
{
if ( pipehandle_is_equal(pipe_hdl, msch_data[pipe_hdl.dev_addr-1].bulk_in) )
{
if (msch_data[pipe_hdl.dev_addr-1].is_initialized)
{
tusbh_msc_isr(pipe_hdl.dev_addr, event, xferred_bytes);
}else
{ // still initializing under open subtask
osal_semaphore_post(msch_sem_hdl);
}
}
}
void msch_close(uint8_t dev_addr)
{
(void) hcd_pipe_close(msch_data[dev_addr-1].bulk_in);
(void) hcd_pipe_close(msch_data[dev_addr-1].bulk_out);
memclr_(&msch_data[dev_addr-1], sizeof(msch_interface_t));
osal_semaphore_reset(msch_sem_hdl);
tusbh_msc_unmounted_cb(dev_addr); // invoke Application Callback
}
//--------------------------------------------------------------------+
// INTERNAL & HELPER
//--------------------------------------------------------------------+
#endif
/**************************************************************************/
/*!
@file msc_host.c
@author hathach (tinyusb.org)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2013, hathach (tinyusb.org)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This file is part of the tinyusb stack.
*/
/**************************************************************************/
#include "tusb_option.h"
#if MODE_HOST_SUPPORTED & TUSB_CFG_HOST_MSC
#define _TINY_USB_SOURCE_FILE_
//--------------------------------------------------------------------+
// INCLUDE
//--------------------------------------------------------------------+
#include "common/common.h"
#include "msc_host.h"
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
TUSB_CFG_ATTR_USBRAM STATIC_VAR msch_interface_t msch_data[TUSB_CFG_HOST_DEVICE_MAX];
//------------- Initalization Data -------------//
OSAL_SEM_DEF(msch_semaphore);
static osal_semaphore_handle_t msch_sem_hdl;
// buffer used to read scsi information when mounted, largest response data currently is inquiry
TUSB_CFG_ATTR_USBRAM ATTR_ALIGNED(4) STATIC_VAR uint8_t msch_buffer[sizeof(scsi_inquiry_data_t)];
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
//--------------------------------------------------------------------+
// PUBLIC API
//--------------------------------------------------------------------+
bool tusbh_msc_is_mounted(uint8_t dev_addr)
{
return tusbh_device_is_configured(dev_addr) && // is configured can be omitted
msch_data[dev_addr-1].is_initialized;
}
bool tusbh_msc_is_busy(uint8_t dev_addr)
{
return msch_data[dev_addr-1].is_initialized &&
hcd_pipe_is_busy(msch_data[dev_addr-1].bulk_in);
}
uint8_t const* tusbh_msc_get_vendor_name(uint8_t dev_addr)
{
return msch_data[dev_addr-1].is_initialized ? msch_data[dev_addr-1].vendor_id : NULL;
}
uint8_t const* tusbh_msc_get_product_name(uint8_t dev_addr)
{
return msch_data[dev_addr-1].is_initialized ? msch_data[dev_addr-1].product_id : NULL;
}
tusb_error_t tusbh_msc_get_capacity(uint8_t dev_addr, uint32_t* p_last_lba, uint32_t* p_block_size)
{
if ( !msch_data[dev_addr-1].is_initialized ) return TUSB_ERROR_MSCH_DEVICE_NOT_MOUNTED;
ASSERT(p_last_lba != NULL && p_block_size != NULL, TUSB_ERROR_INVALID_PARA);
(*p_last_lba) = msch_data[dev_addr-1].last_lba;
(*p_block_size) = (uint32_t) msch_data[dev_addr-1].block_size;
return TUSB_ERROR_NONE;
}
//--------------------------------------------------------------------+
// PUBLIC API: SCSI COMMAND
//--------------------------------------------------------------------+
static inline void msc_cbw_add_signature(msc_cmd_block_wrapper_t *p_cbw, uint8_t lun) ATTR_ALWAYS_INLINE;
static inline void msc_cbw_add_signature(msc_cmd_block_wrapper_t *p_cbw, uint8_t lun)
{
p_cbw->signature = MSC_CBW_SIGNATURE;
p_cbw->tag = 0xCAFECAFE;
p_cbw->lun = lun;
}
static tusb_error_t msch_command_xfer(msch_interface_t * p_msch, void* p_buffer) ATTR_WARN_UNUSED_RESULT;
static tusb_error_t msch_command_xfer(msch_interface_t * p_msch, void* p_buffer)
{
if ( NULL != p_buffer)
{ // there is data phase
if (p_msch->cbw.dir & TUSB_DIR_DEV_TO_HOST_MASK)
{
ASSERT_STATUS( hcd_pipe_xfer(p_msch->bulk_out, (uint8_t*) &p_msch->cbw, sizeof(msc_cmd_block_wrapper_t), false) );
ASSERT_STATUS( hcd_pipe_queue_xfer(p_msch->bulk_in , p_buffer, p_msch->cbw.xfer_bytes) );
}else
{
ASSERT_STATUS( hcd_pipe_queue_xfer(p_msch->bulk_out, (uint8_t*) &p_msch->cbw, sizeof(msc_cmd_block_wrapper_t)) );
ASSERT_STATUS( hcd_pipe_xfer(p_msch->bulk_out , p_buffer, p_msch->cbw.xfer_bytes, false) );
}
}
ASSERT_STATUS( hcd_pipe_xfer(p_msch->bulk_in , (uint8_t*) &p_msch->csw, sizeof(msc_cmd_status_wrapper_t), true) );
return TUSB_ERROR_NONE;
}
tusb_error_t tusbh_msc_inquiry(uint8_t dev_addr, uint8_t lun, uint8_t *p_data)
{
msch_interface_t* p_msch = &msch_data[dev_addr-1];
//------------- Command Block Wrapper -------------//
msc_cbw_add_signature(&p_msch->cbw, lun);
p_msch->cbw.xfer_bytes = sizeof(scsi_inquiry_data_t);
p_msch->cbw.dir = TUSB_DIR_DEV_TO_HOST_MASK;
p_msch->cbw.cmd_len = sizeof(scsi_inquiry_t);
//------------- SCSI command -------------//
scsi_inquiry_t cmd_inquiry =
{
.cmd_code = SCSI_CMD_INQUIRY,
.alloc_length = sizeof(scsi_inquiry_data_t)
};
memcpy(p_msch->cbw.command, &cmd_inquiry, p_msch->cbw.cmd_len);
ASSERT_STATUS ( msch_command_xfer(p_msch, p_data) );
return TUSB_ERROR_NONE;
}
tusb_error_t tusbh_msc_read_capacity10(uint8_t dev_addr, uint8_t lun, uint8_t *p_data)
{
msch_interface_t* p_msch = &msch_data[dev_addr-1];
//------------- Command Block Wrapper -------------//
msc_cbw_add_signature(&p_msch->cbw, lun);
p_msch->cbw.xfer_bytes = sizeof(scsi_read_capacity10_data_t);
p_msch->cbw.dir = TUSB_DIR_DEV_TO_HOST_MASK;
p_msch->cbw.cmd_len = sizeof(scsi_read_capacity10_t);
//------------- SCSI command -------------//
scsi_read_capacity10_t cmd_read_capacity10 =
{
.cmd_code = SCSI_CMD_READ_CAPACITY_10,
.lba = 0,
.partial_medium_indicator = 0
};
memcpy(p_msch->cbw.command, &cmd_read_capacity10, p_msch->cbw.cmd_len);
ASSERT_STATUS ( msch_command_xfer(p_msch, p_data) );
return TUSB_ERROR_NONE;
}
tusb_error_t tusbh_msc_request_sense(uint8_t dev_addr, uint8_t lun, uint8_t *p_data)
{
msch_interface_t* p_msch = &msch_data[dev_addr-1];
//------------- Command Block Wrapper -------------//
p_msch->cbw.xfer_bytes = 18;
p_msch->cbw.dir = TUSB_DIR_DEV_TO_HOST_MASK;
p_msch->cbw.cmd_len = sizeof(scsi_request_sense_t);
//------------- SCSI command -------------//
scsi_request_sense_t cmd_request_sense =
{
.cmd_code = SCSI_CMD_REQUEST_SENSE,
.alloc_length = 18
};
memcpy(p_msch->cbw.command, &cmd_request_sense, p_msch->cbw.cmd_len);
ASSERT_STATUS ( msch_command_xfer(p_msch, p_data) );
return TUSB_ERROR_NONE;
}
tusb_error_t tusbh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, msc_cmd_status_wrapper_t * p_csw)
{
msch_interface_t* p_msch = &msch_data[dev_addr-1];
//------------- Command Block Wrapper -------------//
msc_cbw_add_signature(&p_msch->cbw, lun);
p_msch->cbw.xfer_bytes = 0; // Number of bytes
p_msch->cbw.dir = TUSB_DIR_HOST_TO_DEV;
p_msch->cbw.cmd_len = sizeof(scsi_test_unit_ready_t);
//------------- SCSI command -------------//
scsi_test_unit_ready_t cmd_test_unit_ready =
{
.cmd_code = SCSI_CMD_TEST_UNIT_READY,
.lun = lun // according to wiki
};
memcpy(p_msch->cbw.command, &cmd_test_unit_ready, p_msch->cbw.cmd_len);
// TODO MSCH refractor test uinit ready
ASSERT_STATUS( hcd_pipe_xfer(p_msch->bulk_out, (uint8_t*) &p_msch->cbw, sizeof(msc_cmd_block_wrapper_t), false) );
ASSERT_STATUS( hcd_pipe_xfer(p_msch->bulk_in , (uint8_t*) p_csw, sizeof(msc_cmd_status_wrapper_t), true) );
return TUSB_ERROR_NONE;
}
tusb_error_t tusbh_msc_read10(uint8_t dev_addr, uint8_t lun, void * 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.xfer_bytes = p_msch->block_size*block_count; // Number of bytes
p_msch->cbw.dir = TUSB_DIR_DEV_TO_HOST_MASK;
p_msch->cbw.cmd_len = sizeof(scsi_read10_t);
//------------- SCSI command -------------//
scsi_read10_t cmd_read10 =
{
.cmd_code = SCSI_CMD_READ_10,
.lba = __n2be(lba),
.block_count = u16_le2be(block_count)
};
memcpy(p_msch->cbw.command, &cmd_read10, p_msch->cbw.cmd_len);
ASSERT_STATUS ( msch_command_xfer(p_msch, p_buffer));
return TUSB_ERROR_NONE;
}
tusb_error_t tusbh_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.xfer_bytes = p_msch->block_size*block_count; // Number of bytes
p_msch->cbw.dir = TUSB_DIR_HOST_TO_DEV;
p_msch->cbw.cmd_len = sizeof(scsi_write10_t);
//------------- SCSI command -------------//
scsi_write10_t cmd_write10 =
{
.cmd_code = SCSI_CMD_WRITE_10,
.lba = __n2be(lba),
.block_count = u16_le2be(block_count)
};
memcpy(p_msch->cbw.command, &cmd_write10, p_msch->cbw.cmd_len);
ASSERT_STATUS ( msch_command_xfer(p_msch, (void*) p_buffer));
return TUSB_ERROR_NONE;
}
//--------------------------------------------------------------------+
// CLASS-USBH API (don't require to verify parameters)
//--------------------------------------------------------------------+
void msch_init(void)
{
memclr_(msch_data, sizeof(msch_interface_t)*TUSB_CFG_HOST_DEVICE_MAX);
msch_sem_hdl = osal_semaphore_create( OSAL_SEM_REF(msch_semaphore) );
}
tusb_error_t msch_open_subtask(uint8_t dev_addr, tusb_descriptor_interface_t const *p_interface_desc, uint16_t *p_length)
{
tusb_error_t error;
OSAL_SUBTASK_BEGIN
if (! ( MSC_SUBCLASS_SCSI == p_interface_desc->bInterfaceSubClass &&
MSC_PROTOCOL_BOT == p_interface_desc->bInterfaceProtocol ) )
{
return TUSB_ERROR_MSC_UNSUPPORTED_PROTOCOL;
}
//------------- Open Data Pipe -------------//
tusb_descriptor_endpoint_t const *p_endpoint = (tusb_descriptor_endpoint_t const *) descriptor_next( (uint8_t const*) p_interface_desc );
for(uint32_t i=0; i<2; i++)
{
SUBTASK_ASSERT(TUSB_DESC_TYPE_ENDPOINT == p_endpoint->bDescriptorType);
SUBTASK_ASSERT(TUSB_XFER_BULK == p_endpoint->bmAttributes.xfer);
pipe_handle_t * p_pipe_hdl = ( p_endpoint->bEndpointAddress & TUSB_DIR_DEV_TO_HOST_MASK ) ?
&msch_data[dev_addr-1].bulk_in : &msch_data[dev_addr-1].bulk_out;
(*p_pipe_hdl) = hcd_pipe_open(dev_addr, p_endpoint, TUSB_CLASS_MSC);
SUBTASK_ASSERT( pipehandle_is_valid(*p_pipe_hdl) );
p_endpoint = (tusb_descriptor_endpoint_t const *) descriptor_next( (uint8_t const*) p_endpoint );
}
msch_data[dev_addr-1].interface_number = p_interface_desc->bInterfaceNumber;
(*p_length) += sizeof(tusb_descriptor_interface_t) + 2*sizeof(tusb_descriptor_endpoint_t);
//------------- Get Max Lun -------------//
OSAL_SUBTASK_INVOKED_AND_WAIT(
usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_DEV_TO_HOST, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_INTERFACE),
MSC_REQUEST_GET_MAX_LUN, 0, msch_data[dev_addr-1].interface_number,
1, msch_buffer ),
error
);
SUBTASK_ASSERT( TUSB_ERROR_NONE == error /* && TODO STALL means zero */);
msch_data[dev_addr-1].max_lun = msch_buffer[0];
#if 0
//------------- Reset -------------//
OSAL_SUBTASK_INVOKED_AND_WAIT(
usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_HOST_TO_DEV, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_INTERFACE),
MSC_REQUEST_RESET, 0, msch_data[dev_addr-1].interface_number,
0, NULL ),
error
);
#endif
enum { SCSI_XFER_TIMEOUT = 2000 };
//------------- SCSI Inquiry -------------//
tusbh_msc_inquiry(dev_addr, 0, msch_buffer);
osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT, &error);
SUBTASK_ASSERT_STATUS(error);
memcpy(msch_data[dev_addr-1].vendor_id , ((scsi_inquiry_data_t*) msch_buffer)->vendor_id , 8);
memcpy(msch_data[dev_addr-1].product_id, ((scsi_inquiry_data_t*) msch_buffer)->product_id, 16);
//------------- SCSI Read Capacity 10 -------------//
tusbh_msc_read_capacity10(dev_addr, 0, msch_buffer);
osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT, &error);
SUBTASK_ASSERT_STATUS(error);
// NOTE: my toshiba thumb-drive stall the first Read Capacity and require the sequence
// Read Capacity --> Stalled --> Clear Stall --> Request Sense --> Read Capacity (2) to work
if ( hcd_pipe_is_stalled(msch_data[dev_addr-1].bulk_in) )
{ // clear stall TODO abstract clear stall function
OSAL_SUBTASK_INVOKED_AND_WAIT(
usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_HOST_TO_DEV, TUSB_REQUEST_TYPE_STANDARD, TUSB_REQUEST_RECIPIENT_ENDPOINT),
TUSB_REQUEST_CLEAR_FEATURE, 0, hcd_pipe_get_endpoint_addr(msch_data[dev_addr-1].bulk_in),
0, NULL ),
error
);
SUBTASK_ASSERT_STATUS(error);
hcd_pipe_clear_stall(msch_data[dev_addr-1].bulk_in);
osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT, &error); // wait for SCSI status
SUBTASK_ASSERT_STATUS(error);
//------------- SCSI Request Sense -------------//
tusbh_msc_request_sense(dev_addr, 0, msch_buffer);
osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT, &error);
SUBTASK_ASSERT_STATUS(error);
//------------- Re-read SCSI Read Capactity -------------//
tusbh_msc_read_capacity10(dev_addr, 0, msch_buffer);
osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT, &error);
SUBTASK_ASSERT_STATUS(error);
}
msch_data[dev_addr-1].last_lba = __be2n( ((scsi_read_capacity10_data_t*)msch_buffer)->last_lba );
msch_data[dev_addr-1].block_size = (uint16_t) __be2n( ((scsi_read_capacity10_data_t*)msch_buffer)->block_size );
msch_data[dev_addr-1].is_initialized = true;
tusbh_msc_mounted_cb(dev_addr);
OSAL_SUBTASK_END
}
void msch_isr(pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes)
{
if ( pipehandle_is_equal(pipe_hdl, msch_data[pipe_hdl.dev_addr-1].bulk_in) )
{
if (msch_data[pipe_hdl.dev_addr-1].is_initialized)
{
tusbh_msc_isr(pipe_hdl.dev_addr, event, xferred_bytes);
}else
{ // still initializing under open subtask
osal_semaphore_post(msch_sem_hdl);
}
}
}
void msch_close(uint8_t dev_addr)
{
(void) hcd_pipe_close(msch_data[dev_addr-1].bulk_in);
(void) hcd_pipe_close(msch_data[dev_addr-1].bulk_out);
memclr_(&msch_data[dev_addr-1], sizeof(msch_interface_t));
osal_semaphore_reset(msch_sem_hdl);
tusbh_msc_unmounted_cb(dev_addr); // invoke Application Callback
}
//--------------------------------------------------------------------+
// INTERNAL & HELPER
//--------------------------------------------------------------------+
#endif

View File

@ -1,188 +1,188 @@
/**************************************************************************/
/*!
@file fifo.c
@author hathach (tinyusb.org)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2013, hathach (tinyusb.org)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This file is part of the tinyusb stack.
*/
/**************************************************************************/
#include <string.h>
#include "fifo.h"
static inline void mutex_lock (fifo_t* f) ATTR_ALWAYS_INLINE;
static inline void mutex_unlock (fifo_t* f) ATTR_ALWAYS_INLINE;
static inline bool is_fifo_initalized(fifo_t* f) ATTR_ALWAYS_INLINE;
/**************************************************************************/
/*!
@brief Read one byte out of the RX buffer.
This function will return the byte located at the array index of the
read pointer, and then increment the read pointer index. If the read
pointer exceeds the maximum buffer size, it will roll over to zero.
@param[in] f
Pointer to the FIFO buffer to manipulate
@param[in] data
Pointer to the place holder for data read from the buffer
@returns TRUE if the queue is not empty
*/
/**************************************************************************/
bool fifo_read(fifo_t* f, void * p_buffer)
{
if( !is_fifo_initalized(f) || fifo_is_empty(f) )
{
return false;
}
mutex_lock(f);
memcpy(p_buffer,
f->buffer + (f->rd_idx * f->item_size),
f->item_size);
f->rd_idx = (f->rd_idx + 1) % f->depth;
f->count--;
mutex_unlock(f);
return true;
}
/**************************************************************************/
/*!
@brief Write one byte into the RX buffer.
This function will write one byte into the array index specified by
the write pointer and increment the write index. If the write index
exceeds the max buffer size, then it will roll over to zero.
@param[in] f
Pointer to the FIFO buffer to manipulate
@param[in] data
The byte to add to the FIFO
@returns TRUE if the data was written to the FIFO (overwrittable
FIFO will always return TRUE)
*/
/**************************************************************************/
bool fifo_write(fifo_t* f, void const * p_data)
{
if ( !is_fifo_initalized(f) || (fifo_is_full(f) && !f->overwritable) )
{
return false;
}
mutex_lock(f);
memcpy( f->buffer + (f->wr_idx * f->item_size),
p_data,
f->item_size);
f->wr_idx = (f->wr_idx + 1) % f->depth;
if (fifo_is_full(f))
{
f->rd_idx = f->wr_idx; // keep the full state (rd == wr && len = size)
}else
{
f->count++;
}
mutex_unlock(f);
return true;
}
/**************************************************************************/
/*!
@brief Clear the fifo read and write pointers and set length to zero
@param[in] f
Pointer to the FIFO buffer to manipulate
*/
/**************************************************************************/
void fifo_clear(fifo_t *f)
{
mutex_lock(f);
f->rd_idx = f->wr_idx = f->count = 0;
mutex_unlock(f);
}
//--------------------------------------------------------------------+
// HELPER FUNCTIONS
//--------------------------------------------------------------------+
/**************************************************************************/
/*!
@brief Disables the IRQ specified in the FIFO's 'irq' field
to prevent reads/write issues with interrupts
@param[in] f
Pointer to the FIFO that should be protected
*/
/**************************************************************************/
static inline void mutex_lock (fifo_t* f)
{
// if (f->irq > 0)
// {
// #if !defined (_TEST_)
// NVIC_DisableIRQ(f->irq);
// #endif
// }
}
/**************************************************************************/
/*!
@brief Re-enables the IRQ specified in the FIFO's 'irq' field
@param[in] f
Pointer to the FIFO that should be protected
*/
/**************************************************************************/
static inline void mutex_unlock (fifo_t* f)
{
// if (f->irq > 0)
// {
// #if !defined (_TEST_)
// NVIC_EnableIRQ(f->irq);
// #endif
// }
}
static inline bool is_fifo_initalized(fifo_t* f)
{
return !( f->buffer == NULL || f->depth == 0 || f->item_size == 0);
}
/**************************************************************************/
/*!
@file fifo.c
@author hathach (tinyusb.org)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2013, hathach (tinyusb.org)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This file is part of the tinyusb stack.
*/
/**************************************************************************/
#include <string.h>
#include "fifo.h"
static inline void mutex_lock (fifo_t* f) ATTR_ALWAYS_INLINE;
static inline void mutex_unlock (fifo_t* f) ATTR_ALWAYS_INLINE;
static inline bool is_fifo_initalized(fifo_t* f) ATTR_ALWAYS_INLINE;
/**************************************************************************/
/*!
@brief Read one byte out of the RX buffer.
This function will return the byte located at the array index of the
read pointer, and then increment the read pointer index. If the read
pointer exceeds the maximum buffer size, it will roll over to zero.
@param[in] f
Pointer to the FIFO buffer to manipulate
@param[in] data
Pointer to the place holder for data read from the buffer
@returns TRUE if the queue is not empty
*/
/**************************************************************************/
bool fifo_read(fifo_t* f, void * p_buffer)
{
if( !is_fifo_initalized(f) || fifo_is_empty(f) )
{
return false;
}
mutex_lock(f);
memcpy(p_buffer,
f->buffer + (f->rd_idx * f->item_size),
f->item_size);
f->rd_idx = (f->rd_idx + 1) % f->depth;
f->count--;
mutex_unlock(f);
return true;
}
/**************************************************************************/
/*!
@brief Write one byte into the RX buffer.
This function will write one byte into the array index specified by
the write pointer and increment the write index. If the write index
exceeds the max buffer size, then it will roll over to zero.
@param[in] f
Pointer to the FIFO buffer to manipulate
@param[in] data
The byte to add to the FIFO
@returns TRUE if the data was written to the FIFO (overwrittable
FIFO will always return TRUE)
*/
/**************************************************************************/
bool fifo_write(fifo_t* f, void const * p_data)
{
if ( !is_fifo_initalized(f) || (fifo_is_full(f) && !f->overwritable) )
{
return false;
}
mutex_lock(f);
memcpy( f->buffer + (f->wr_idx * f->item_size),
p_data,
f->item_size);
f->wr_idx = (f->wr_idx + 1) % f->depth;
if (fifo_is_full(f))
{
f->rd_idx = f->wr_idx; // keep the full state (rd == wr && len = size)
}else
{
f->count++;
}
mutex_unlock(f);
return true;
}
/**************************************************************************/
/*!
@brief Clear the fifo read and write pointers and set length to zero
@param[in] f
Pointer to the FIFO buffer to manipulate
*/
/**************************************************************************/
void fifo_clear(fifo_t *f)
{
mutex_lock(f);
f->rd_idx = f->wr_idx = f->count = 0;
mutex_unlock(f);
}
//--------------------------------------------------------------------+
// HELPER FUNCTIONS
//--------------------------------------------------------------------+
/**************************************************************************/
/*!
@brief Disables the IRQ specified in the FIFO's 'irq' field
to prevent reads/write issues with interrupts
@param[in] f
Pointer to the FIFO that should be protected
*/
/**************************************************************************/
static inline void mutex_lock (fifo_t* f)
{
// if (f->irq > 0)
// {
// #if !defined (_TEST_)
// NVIC_DisableIRQ(f->irq);
// #endif
// }
}
/**************************************************************************/
/*!
@brief Re-enables the IRQ specified in the FIFO's 'irq' field
@param[in] f
Pointer to the FIFO that should be protected
*/
/**************************************************************************/
static inline void mutex_unlock (fifo_t* f)
{
// if (f->irq > 0)
// {
// #if !defined (_TEST_)
// NVIC_EnableIRQ(f->irq);
// #endif
// }
}
static inline bool is_fifo_initalized(fifo_t* f)
{
return !( f->buffer == NULL || f->depth == 0 || f->item_size == 0);
}

View File

@ -1,104 +1,104 @@
/**************************************************************************/
/*!
@file fifo.h
@author hathach (tinyusb.org)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2013, hathach (tinyusb.org)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This file is part of the tinyusb stack.
*/
/**************************************************************************/
/** \ingroup Group_Common
*
* @{
*/
#ifndef _TUSB_FIFO_H_
#define _TUSB_FIFO_H_
#include "common/common.h"
#ifdef __cplusplus
extern "C" {
#endif
/** \struct fifo_t
* \brief Simple Circular FIFO
*/
typedef struct
{
uint8_t* const buffer ; ///< buffer pointer
uint16_t const depth ; ///< max items
uint16_t const item_size ; ///< size of each item
volatile uint16_t count ; ///< number of items in queue
volatile uint16_t wr_idx ; ///< write pointer
volatile uint16_t rd_idx ; ///< read pointer
bool overwritable ;
// IRQn_Type irq;
} fifo_t;
#define FIFO_DEF(name, ff_depth, type, is_overwritable) /*, irq_mutex)*/ \
uint8_t name##_buffer[ff_depth*sizeof(type)];\
fifo_t name = {\
.buffer = name##_buffer,\
.depth = ff_depth,\
.item_size = sizeof(type),\
.overwritable = is_overwritable,\
/*.irq = irq_mutex*/\
}
bool fifo_write(fifo_t* f, void const * p_data);
bool fifo_read(fifo_t* f, void * p_buffer);
void fifo_clear(fifo_t *f);
static inline bool fifo_is_empty(fifo_t* f) ATTR_PURE ATTR_ALWAYS_INLINE;
static inline bool fifo_is_empty(fifo_t* f)
{
return (f->count == 0);
}
static inline bool fifo_is_full(fifo_t* f) ATTR_PURE ATTR_ALWAYS_INLINE;
static inline bool fifo_is_full(fifo_t* f)
{
return (f->count == f->depth);
}
static inline uint16_t fifo_get_length(fifo_t* f) ATTR_PURE ATTR_ALWAYS_INLINE;
static inline uint16_t fifo_get_length(fifo_t* f)
{
return f->count;
}
#ifdef __cplusplus
}
#endif
#endif /* _TUSB_FIFO_H_ */
/**************************************************************************/
/*!
@file fifo.h
@author hathach (tinyusb.org)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2013, hathach (tinyusb.org)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This file is part of the tinyusb stack.
*/
/**************************************************************************/
/** \ingroup Group_Common
*
* @{
*/
#ifndef _TUSB_FIFO_H_
#define _TUSB_FIFO_H_
#include "common/common.h"
#ifdef __cplusplus
extern "C" {
#endif
/** \struct fifo_t
* \brief Simple Circular FIFO
*/
typedef struct
{
uint8_t* const buffer ; ///< buffer pointer
uint16_t const depth ; ///< max items
uint16_t const item_size ; ///< size of each item
volatile uint16_t count ; ///< number of items in queue
volatile uint16_t wr_idx ; ///< write pointer
volatile uint16_t rd_idx ; ///< read pointer
bool overwritable ;
// IRQn_Type irq;
} fifo_t;
#define FIFO_DEF(name, ff_depth, type, is_overwritable) /*, irq_mutex)*/ \
uint8_t name##_buffer[ff_depth*sizeof(type)];\
fifo_t name = {\
.buffer = name##_buffer,\
.depth = ff_depth,\
.item_size = sizeof(type),\
.overwritable = is_overwritable,\
/*.irq = irq_mutex*/\
}
bool fifo_write(fifo_t* f, void const * p_data);
bool fifo_read(fifo_t* f, void * p_buffer);
void fifo_clear(fifo_t *f);
static inline bool fifo_is_empty(fifo_t* f) ATTR_PURE ATTR_ALWAYS_INLINE;
static inline bool fifo_is_empty(fifo_t* f)
{
return (f->count == 0);
}
static inline bool fifo_is_full(fifo_t* f) ATTR_PURE ATTR_ALWAYS_INLINE;
static inline bool fifo_is_full(fifo_t* f)
{
return (f->count == f->depth);
}
static inline uint16_t fifo_get_length(fifo_t* f) ATTR_PURE ATTR_ALWAYS_INLINE;
static inline uint16_t fifo_get_length(fifo_t* f)
{
return f->count;
}
#ifdef __cplusplus
}
#endif
#endif /* _TUSB_FIFO_H_ */

View File

@ -1,103 +1,103 @@
/**************************************************************************/
/*!
@file dcd.h
@author hathach (tinyusb.org)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2013, hathach (tinyusb.org)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This file is part of the tinyusb stack.
*/
/**************************************************************************/
/** \addtogroup Port Port
* @{
* \defgroup Port_DCD Device Controller Driver (DCD)
* @{
*/
#ifndef _TUSB_DCD_H_
#define _TUSB_DCD_H_
#include "common/common.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
uint8_t coreid;
uint8_t reserved; // TODO redundant, cannot be control as control uses separated API
uint8_t index;
uint8_t class_code;
} endpoint_handle_t;
static inline bool endpointhandle_is_valid(endpoint_handle_t edpt_hdl) ATTR_CONST ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
static inline bool endpointhandle_is_valid(endpoint_handle_t edpt_hdl)
{
return (edpt_hdl.class_code != 0);
}
static inline bool endpointhandle_is_equal(endpoint_handle_t x, endpoint_handle_t y) ATTR_CONST ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
static inline bool endpointhandle_is_equal(endpoint_handle_t x, endpoint_handle_t y)
{
return (x.coreid == y.coreid) && (x.index == y.index) && (x.class_code == y.class_code);
}
tusb_error_t dcd_init(void) ATTR_WARN_UNUSED_RESULT;
void dcd_isr(uint8_t coreid);
//------------- Controller API -------------//
void dcd_controller_connect (uint8_t coreid);
void dcd_controller_disconnect (uint8_t coreid);
void dcd_controller_set_address (uint8_t coreid, uint8_t dev_addr);
void dcd_controller_set_configuration (uint8_t coreid);
//------------- PIPE API -------------//
tusb_error_t dcd_pipe_control_xfer(uint8_t coreid, tusb_direction_t dir, uint8_t * p_buffer, uint16_t length, bool int_on_complete);
void dcd_pipe_control_stall(uint8_t coreid);
endpoint_handle_t dcd_pipe_open(uint8_t coreid, tusb_descriptor_endpoint_t const * p_endpoint_desc, uint8_t class_code) ATTR_WARN_UNUSED_RESULT;
tusb_error_t dcd_pipe_queue_xfer(endpoint_handle_t edpt_hdl, uint8_t * buffer, uint16_t total_bytes) ATTR_WARN_UNUSED_RESULT; // only queue, not transferring yet
tusb_error_t dcd_pipe_xfer(endpoint_handle_t edpt_hdl, uint8_t * buffer, uint16_t total_bytes, bool int_on_complete) ATTR_WARN_UNUSED_RESULT;
tusb_error_t dcd_pipe_stall(endpoint_handle_t edpt_hdl) ATTR_WARN_UNUSED_RESULT;
bool dcd_pipe_is_busy(endpoint_handle_t edpt_hdl) ATTR_WARN_UNUSED_RESULT ;
// TODO coreid + endpoint address are part of endpoint handle, not endpoint handle, data toggle also need to be reset
tusb_error_t dcd_pipe_clear_stall(uint8_t coreid, uint8_t edpt_addr);
#ifdef __cplusplus
}
#endif
#endif /* _TUSB_DCD_H_ */
/// @}
/// @}
/**************************************************************************/
/*!
@file dcd.h
@author hathach (tinyusb.org)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2013, hathach (tinyusb.org)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This file is part of the tinyusb stack.
*/
/**************************************************************************/
/** \addtogroup Port Port
* @{
* \defgroup Port_DCD Device Controller Driver (DCD)
* @{
*/
#ifndef _TUSB_DCD_H_
#define _TUSB_DCD_H_
#include "common/common.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
uint8_t coreid;
uint8_t reserved; // TODO redundant, cannot be control as control uses separated API
uint8_t index;
uint8_t class_code;
} endpoint_handle_t;
static inline bool endpointhandle_is_valid(endpoint_handle_t edpt_hdl) ATTR_CONST ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
static inline bool endpointhandle_is_valid(endpoint_handle_t edpt_hdl)
{
return (edpt_hdl.class_code != 0);
}
static inline bool endpointhandle_is_equal(endpoint_handle_t x, endpoint_handle_t y) ATTR_CONST ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
static inline bool endpointhandle_is_equal(endpoint_handle_t x, endpoint_handle_t y)
{
return (x.coreid == y.coreid) && (x.index == y.index) && (x.class_code == y.class_code);
}
tusb_error_t dcd_init(void) ATTR_WARN_UNUSED_RESULT;
void dcd_isr(uint8_t coreid);
//------------- Controller API -------------//
void dcd_controller_connect (uint8_t coreid);
void dcd_controller_disconnect (uint8_t coreid);
void dcd_controller_set_address (uint8_t coreid, uint8_t dev_addr);
void dcd_controller_set_configuration (uint8_t coreid);
//------------- PIPE API -------------//
tusb_error_t dcd_pipe_control_xfer(uint8_t coreid, tusb_direction_t dir, uint8_t * p_buffer, uint16_t length, bool int_on_complete);
void dcd_pipe_control_stall(uint8_t coreid);
endpoint_handle_t dcd_pipe_open(uint8_t coreid, tusb_descriptor_endpoint_t const * p_endpoint_desc, uint8_t class_code) ATTR_WARN_UNUSED_RESULT;
tusb_error_t dcd_pipe_queue_xfer(endpoint_handle_t edpt_hdl, uint8_t * buffer, uint16_t total_bytes) ATTR_WARN_UNUSED_RESULT; // only queue, not transferring yet
tusb_error_t dcd_pipe_xfer(endpoint_handle_t edpt_hdl, uint8_t * buffer, uint16_t total_bytes, bool int_on_complete) ATTR_WARN_UNUSED_RESULT;
tusb_error_t dcd_pipe_stall(endpoint_handle_t edpt_hdl) ATTR_WARN_UNUSED_RESULT;
bool dcd_pipe_is_busy(endpoint_handle_t edpt_hdl) ATTR_WARN_UNUSED_RESULT ;
// TODO coreid + endpoint address are part of endpoint handle, not endpoint handle, data toggle also need to be reset
tusb_error_t dcd_pipe_clear_stall(uint8_t coreid, uint8_t edpt_addr);
#ifdef __cplusplus
}
#endif
#endif /* _TUSB_DCD_H_ */
/// @}
/// @}

File diff suppressed because it is too large Load Diff

View File

@ -1,69 +1,69 @@
/**************************************************************************/
/*!
@file hal_lpc11uxx.c
@author hathach (tinyusb.org)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2013, hathach (tinyusb.org)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This file is part of the tinyusb stack.
*/
/**************************************************************************/
#include "common/common.h"
#include "hal.h"
#if TUSB_CFG_MCU == MCU_LPC11UXX
tusb_error_t hal_init(void)
{
// TODO remove magic number
/* Enable AHB clock to the USB block and USB RAM. */
LPC_SYSCON->SYSAHBCLKCTRL |= ((0x1<<14) | (0x1<<27));
LPC_SYSCON->PDRUNCFG &= ~( BIT_(8) | BIT_(10) ); // enable USB PLL & USB transceiver
/* Pull-down is needed, or internally, VBUS will be floating. This is to
address the wrong status in VBUSDebouncing bit in CmdStatus register. */
// set PIO0_3 as USB_VBUS
LPC_IOCON->PIO0_3 &= ~0x1F;
LPC_IOCON->PIO0_3 |= (0x01<<0) | (1 << 3); /* Secondary function VBUS */
// set PIO0_6 as usb connect
LPC_IOCON->PIO0_6 &= ~0x07;
LPC_IOCON->PIO0_6 |= (0x01<<0); /* Secondary function SoftConn */
return TUSB_ERROR_NONE;
}
void USB_IRQHandler(void)
{
tusb_isr(0);
}
#endif
/**************************************************************************/
/*!
@file hal_lpc11uxx.c
@author hathach (tinyusb.org)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2013, hathach (tinyusb.org)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This file is part of the tinyusb stack.
*/
/**************************************************************************/
#include "common/common.h"
#include "hal.h"
#if TUSB_CFG_MCU == MCU_LPC11UXX
tusb_error_t hal_init(void)
{
// TODO remove magic number
/* Enable AHB clock to the USB block and USB RAM. */
LPC_SYSCON->SYSAHBCLKCTRL |= ((0x1<<14) | (0x1<<27));
LPC_SYSCON->PDRUNCFG &= ~( BIT_(8) | BIT_(10) ); // enable USB PLL & USB transceiver
/* Pull-down is needed, or internally, VBUS will be floating. This is to
address the wrong status in VBUSDebouncing bit in CmdStatus register. */
// set PIO0_3 as USB_VBUS
LPC_IOCON->PIO0_3 &= ~0x1F;
LPC_IOCON->PIO0_3 |= (0x01<<0) | (1 << 3); /* Secondary function VBUS */
// set PIO0_6 as usb connect
LPC_IOCON->PIO0_6 &= ~0x07;
LPC_IOCON->PIO0_6 |= (0x01<<0); /* Secondary function SoftConn */
return TUSB_ERROR_NONE;
}
void USB_IRQHandler(void)
{
tusb_isr(0);
}
#endif

View File

@ -1,68 +1,68 @@
/**************************************************************************/
/*!
@file hal_lpc13uxx.c
@author hathach (tinyusb.org)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2013, hathach (tinyusb.org)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This file is part of the tinyusb stack.
*/
/**************************************************************************/
#include "common/common.h"
#include "hal.h"
#if TUSB_CFG_MCU == MCU_LPC13UXX
tusb_error_t hal_init(void)
{
// TODO remove magic number
LPC_SYSCON->SYSAHBCLKCTRL |= ((0x1<<14) | (0x1<<27)); /* Enable AHB clock to the USB block and USB RAM. */
LPC_SYSCON->PDRUNCFG &= ~( BIT_(8) | BIT_(10) ); // enable USB PLL & USB transceiver
/* Pull-down is needed, or internally, VBUS will be floating. This is to
address the wrong status in VBUSDebouncing bit in CmdStatus register. */
// set PIO0_3 as USB_VBUS
LPC_IOCON->PIO0_3 &= ~0x1F;
LPC_IOCON->PIO0_3 |= (0x01<<0) | (1 << 3); /* Secondary function VBUS */
// set PIO0_6 as usb connect
LPC_IOCON->PIO0_6 &= ~0x07;
LPC_IOCON->PIO0_6 |= (0x01<<0); /* Secondary function SoftConn */
return TUSB_ERROR_NONE;
}
void USB_IRQHandler(void)
{
tusb_isr(0);
}
#endif
/**************************************************************************/
/*!
@file hal_lpc13uxx.c
@author hathach (tinyusb.org)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2013, hathach (tinyusb.org)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This file is part of the tinyusb stack.
*/
/**************************************************************************/
#include "common/common.h"
#include "hal.h"
#if TUSB_CFG_MCU == MCU_LPC13UXX
tusb_error_t hal_init(void)
{
// TODO remove magic number
LPC_SYSCON->SYSAHBCLKCTRL |= ((0x1<<14) | (0x1<<27)); /* Enable AHB clock to the USB block and USB RAM. */
LPC_SYSCON->PDRUNCFG &= ~( BIT_(8) | BIT_(10) ); // enable USB PLL & USB transceiver
/* Pull-down is needed, or internally, VBUS will be floating. This is to
address the wrong status in VBUSDebouncing bit in CmdStatus register. */
// set PIO0_3 as USB_VBUS
LPC_IOCON->PIO0_3 &= ~0x1F;
LPC_IOCON->PIO0_3 |= (0x01<<0) | (1 << 3); /* Secondary function VBUS */
// set PIO0_6 as usb connect
LPC_IOCON->PIO0_6 &= ~0x07;
LPC_IOCON->PIO0_6 |= (0x01<<0); /* Secondary function SoftConn */
return TUSB_ERROR_NONE;
}
void USB_IRQHandler(void)
{
tusb_isr(0);
}
#endif

View File

@ -1,99 +1,99 @@
/**************************************************************************/
/*!
@file hal_lpc175x_6x.c
@author hathach (tinyusb.org)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2013, hathach (tinyusb.org)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This file is part of the tinyusb stack.
*/
/**************************************************************************/
#include "tusb_option.h"
#if TUSB_CFG_MCU == MCU_LPC175X_6X
//--------------------------------------------------------------------+
// INCLUDE
//--------------------------------------------------------------------+
#include "common/common.h"
#include "hal.h"
//--------------------------------------------------------------------+
// IMPLEMENTATION
//--------------------------------------------------------------------+
tusb_error_t hal_init(void)
{
enum {
USBCLK_DEVCIE = 0x12, // AHB + Device
USBCLK_HOST = 0x19 // AHB + Host + OTG (!)
};
LPC_SC->PCONP |= CLKPWR_PCONP_PCUSB; // enable USB Peripherals
//------------- user manual 11.13 usb device controller initialization -------------//
PINSEL_ConfigPin( &(PINSEL_CFG_Type) { .Portnum = 0, .Pinnum = 29, .Funcnum = 1} ); // P0.29 as D+
PINSEL_ConfigPin( &(PINSEL_CFG_Type) { .Portnum = 0, .Pinnum = 30, .Funcnum = 1} ); // P0.30 as D-
#if MODE_HOST_SUPPORTED
PINSEL_ConfigPin( &(PINSEL_CFG_Type) { .Portnum = 1, .Pinnum = 22, .Funcnum = 2} ); // P1.22 as USB_PWRD
PINSEL_ConfigPin( &(PINSEL_CFG_Type) { .Portnum = 1, .Pinnum = 19, .Funcnum = 2} ); // P1.19 as USB_PPWR
LPC_USB->USBClkCtrl = USBCLK_HOST;
while ((LPC_USB->USBClkSt & USBCLK_HOST) != USBCLK_HOST);
LPC_USB->OTGStCtrl = 0x3;
#endif
#if MODE_DEVICE_SUPPORTED
LPC_PINCON->PINSEL4 = bit_set_range(LPC_PINCON->PINSEL4, 18, 19, BIN8(01)); // P2_9 as USB Connect
// P1_30 as VBUS, ignore if it is already in VBUS mode
if ( !(!BIT_TEST_(LPC_PINCON->PINSEL3, 28) && BIT_TEST_(LPC_PINCON->PINSEL3, 29)) )
{
// some board like lpcxpresso1769 does not connect VBUS signal to pin P1_30, this allow those board to overwrite
// by always pulling P1_30 to high
PINSEL_ConfigPin( &(PINSEL_CFG_Type) {
.Portnum = 1, .Pinnum = 30,
.Funcnum = 2, .Pinmode = PINSEL_PINMODE_PULLDOWN} );
}
LPC_USB->USBClkCtrl = USBCLK_DEVCIE;
while ((LPC_USB->USBClkSt & USBCLK_DEVCIE) != USBCLK_DEVCIE);
#endif
return TUSB_ERROR_NONE;
}
void USB_IRQHandler(void)
{
tusb_isr(0);
}
#endif
/**************************************************************************/
/*!
@file hal_lpc175x_6x.c
@author hathach (tinyusb.org)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2013, hathach (tinyusb.org)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This file is part of the tinyusb stack.
*/
/**************************************************************************/
#include "tusb_option.h"
#if TUSB_CFG_MCU == MCU_LPC175X_6X
//--------------------------------------------------------------------+
// INCLUDE
//--------------------------------------------------------------------+
#include "common/common.h"
#include "hal.h"
//--------------------------------------------------------------------+
// IMPLEMENTATION
//--------------------------------------------------------------------+
tusb_error_t hal_init(void)
{
enum {
USBCLK_DEVCIE = 0x12, // AHB + Device
USBCLK_HOST = 0x19 // AHB + Host + OTG (!)
};
LPC_SC->PCONP |= CLKPWR_PCONP_PCUSB; // enable USB Peripherals
//------------- user manual 11.13 usb device controller initialization -------------//
PINSEL_ConfigPin( &(PINSEL_CFG_Type) { .Portnum = 0, .Pinnum = 29, .Funcnum = 1} ); // P0.29 as D+
PINSEL_ConfigPin( &(PINSEL_CFG_Type) { .Portnum = 0, .Pinnum = 30, .Funcnum = 1} ); // P0.30 as D-
#if MODE_HOST_SUPPORTED
PINSEL_ConfigPin( &(PINSEL_CFG_Type) { .Portnum = 1, .Pinnum = 22, .Funcnum = 2} ); // P1.22 as USB_PWRD
PINSEL_ConfigPin( &(PINSEL_CFG_Type) { .Portnum = 1, .Pinnum = 19, .Funcnum = 2} ); // P1.19 as USB_PPWR
LPC_USB->USBClkCtrl = USBCLK_HOST;
while ((LPC_USB->USBClkSt & USBCLK_HOST) != USBCLK_HOST);
LPC_USB->OTGStCtrl = 0x3;
#endif
#if MODE_DEVICE_SUPPORTED
LPC_PINCON->PINSEL4 = bit_set_range(LPC_PINCON->PINSEL4, 18, 19, BIN8(01)); // P2_9 as USB Connect
// P1_30 as VBUS, ignore if it is already in VBUS mode
if ( !(!BIT_TEST_(LPC_PINCON->PINSEL3, 28) && BIT_TEST_(LPC_PINCON->PINSEL3, 29)) )
{
// some board like lpcxpresso1769 does not connect VBUS signal to pin P1_30, this allow those board to overwrite
// by always pulling P1_30 to high
PINSEL_ConfigPin( &(PINSEL_CFG_Type) {
.Portnum = 1, .Pinnum = 30,
.Funcnum = 2, .Pinmode = PINSEL_PINMODE_PULLDOWN} );
}
LPC_USB->USBClkCtrl = USBCLK_DEVCIE;
while ((LPC_USB->USBClkSt & USBCLK_DEVCIE) != USBCLK_DEVCIE);
#endif
return TUSB_ERROR_NONE;
}
void USB_IRQHandler(void)
{
tusb_isr(0);
}
#endif

View File

@ -1,44 +1,44 @@
/**************************************************************************/
/*!
@file hcd.c
@author hathach (tinyusb.org)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2013, hathach (tinyusb.org)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This file is part of the tinyusb stack.
*/
/**************************************************************************/
#include "hcd.h"
#if MODE_HOST_SUPPORTED
#endif
/**************************************************************************/
/*!
@file hcd.c
@author hathach (tinyusb.org)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2013, hathach (tinyusb.org)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This file is part of the tinyusb stack.
*/
/**************************************************************************/
#include "hcd.h"
#if MODE_HOST_SUPPORTED
#endif

View File

@ -1,122 +1,122 @@
/**************************************************************************/
/*!
@file hcd.h
@author hathach (tinyusb.org)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2013, hathach (tinyusb.org)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This file is part of the tinyusb stack.
*/
/**************************************************************************/
/** \addtogroup Port Port
* @{
* \defgroup Port_HCD Host Controller Driver (HCD)
* @{
*/
#ifndef _TUSB_HCD_H_
#define _TUSB_HCD_H_
#include "common/common.h"
#ifdef __cplusplus
extern "C" {
#endif
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
typedef struct {
uint8_t dev_addr;
uint8_t xfer_type;
uint8_t index;
uint8_t reserved;
} pipe_handle_t;
static inline bool pipehandle_is_valid(pipe_handle_t pipe_hdl) ATTR_CONST ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
static inline bool pipehandle_is_valid(pipe_handle_t pipe_hdl)
{
return pipe_hdl.dev_addr > 0;
}
static inline bool pipehandle_is_equal(pipe_handle_t x, pipe_handle_t y) ATTR_CONST ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
static inline bool pipehandle_is_equal(pipe_handle_t x, pipe_handle_t y)
{
return (x.dev_addr == y.dev_addr) && (x.xfer_type == y.xfer_type) && (x.index == y.index);
}
//--------------------------------------------------------------------+
// USBH-HCD API
//--------------------------------------------------------------------+
tusb_error_t hcd_init(void) ATTR_WARN_UNUSED_RESULT;
void hcd_isr(uint8_t hostid);
//--------------------------------------------------------------------+
// PIPE API
//--------------------------------------------------------------------+
// TODO control xfer should be used via usbh layer
tusb_error_t hcd_pipe_control_open(uint8_t dev_addr, uint8_t max_packet_size) ATTR_WARN_UNUSED_RESULT;
tusb_error_t hcd_pipe_control_xfer(uint8_t dev_addr, tusb_control_request_t const * p_request, uint8_t data[]) ATTR_WARN_UNUSED_RESULT;
tusb_error_t hcd_pipe_control_close(uint8_t dev_addr) ATTR_WARN_UNUSED_RESULT;
pipe_handle_t hcd_pipe_open(uint8_t dev_addr, tusb_descriptor_endpoint_t const * endpoint_desc, uint8_t class_code) ATTR_WARN_UNUSED_RESULT;
tusb_error_t hcd_pipe_queue_xfer(pipe_handle_t pipe_hdl, uint8_t buffer[], uint16_t total_bytes) ATTR_WARN_UNUSED_RESULT; // only queue, not transferring yet
tusb_error_t hcd_pipe_xfer(pipe_handle_t pipe_hdl, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete) ATTR_WARN_UNUSED_RESULT;
tusb_error_t hcd_pipe_close(pipe_handle_t pipe_hdl) /*ATTR_WARN_UNUSED_RESULT*/;
bool hcd_pipe_is_busy(pipe_handle_t pipe_hdl) ATTR_PURE;
bool hcd_pipe_is_error(pipe_handle_t pipe_hdl) ATTR_PURE;
bool hcd_pipe_is_stalled(pipe_handle_t pipe_hdl) ATTR_PURE; // stalled also counted as error
uint8_t hcd_pipe_get_endpoint_addr(pipe_handle_t pipe_hdl) ATTR_PURE;
tusb_error_t hcd_pipe_clear_stall(pipe_handle_t pipe_hdl);
#if 0
tusb_error_t hcd_pipe_cancel()ATTR_WARN_UNUSED_RESULT;
#endif
//--------------------------------------------------------------------+
// PORT API
//--------------------------------------------------------------------+
/// return the current connect status of roothub port
bool hcd_port_connect_status(uint8_t hostid) ATTR_PURE ATTR_WARN_UNUSED_RESULT; // TODO make inline if possible
void hcd_port_reset(uint8_t hostid);
tusb_speed_t hcd_port_speed_get(uint8_t hostid) ATTR_PURE ATTR_WARN_UNUSED_RESULT; // TODO make inline if possible
void hcd_port_unplug(uint8_t hostid); // called by usbh to instruct hcd that it can execute unplug procedure
#ifdef __cplusplus
}
#endif
#endif /* _TUSB_HCD_H_ */
/// @}
/// @}
/**************************************************************************/
/*!
@file hcd.h
@author hathach (tinyusb.org)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2013, hathach (tinyusb.org)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This file is part of the tinyusb stack.
*/
/**************************************************************************/
/** \addtogroup Port Port
* @{
* \defgroup Port_HCD Host Controller Driver (HCD)
* @{
*/
#ifndef _TUSB_HCD_H_
#define _TUSB_HCD_H_
#include "common/common.h"
#ifdef __cplusplus
extern "C" {
#endif
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
typedef struct {
uint8_t dev_addr;
uint8_t xfer_type;
uint8_t index;
uint8_t reserved;
} pipe_handle_t;
static inline bool pipehandle_is_valid(pipe_handle_t pipe_hdl) ATTR_CONST ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
static inline bool pipehandle_is_valid(pipe_handle_t pipe_hdl)
{
return pipe_hdl.dev_addr > 0;
}
static inline bool pipehandle_is_equal(pipe_handle_t x, pipe_handle_t y) ATTR_CONST ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
static inline bool pipehandle_is_equal(pipe_handle_t x, pipe_handle_t y)
{
return (x.dev_addr == y.dev_addr) && (x.xfer_type == y.xfer_type) && (x.index == y.index);
}
//--------------------------------------------------------------------+
// USBH-HCD API
//--------------------------------------------------------------------+
tusb_error_t hcd_init(void) ATTR_WARN_UNUSED_RESULT;
void hcd_isr(uint8_t hostid);
//--------------------------------------------------------------------+
// PIPE API
//--------------------------------------------------------------------+
// TODO control xfer should be used via usbh layer
tusb_error_t hcd_pipe_control_open(uint8_t dev_addr, uint8_t max_packet_size) ATTR_WARN_UNUSED_RESULT;
tusb_error_t hcd_pipe_control_xfer(uint8_t dev_addr, tusb_control_request_t const * p_request, uint8_t data[]) ATTR_WARN_UNUSED_RESULT;
tusb_error_t hcd_pipe_control_close(uint8_t dev_addr) ATTR_WARN_UNUSED_RESULT;
pipe_handle_t hcd_pipe_open(uint8_t dev_addr, tusb_descriptor_endpoint_t const * endpoint_desc, uint8_t class_code) ATTR_WARN_UNUSED_RESULT;
tusb_error_t hcd_pipe_queue_xfer(pipe_handle_t pipe_hdl, uint8_t buffer[], uint16_t total_bytes) ATTR_WARN_UNUSED_RESULT; // only queue, not transferring yet
tusb_error_t hcd_pipe_xfer(pipe_handle_t pipe_hdl, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete) ATTR_WARN_UNUSED_RESULT;
tusb_error_t hcd_pipe_close(pipe_handle_t pipe_hdl) /*ATTR_WARN_UNUSED_RESULT*/;
bool hcd_pipe_is_busy(pipe_handle_t pipe_hdl) ATTR_PURE;
bool hcd_pipe_is_error(pipe_handle_t pipe_hdl) ATTR_PURE;
bool hcd_pipe_is_stalled(pipe_handle_t pipe_hdl) ATTR_PURE; // stalled also counted as error
uint8_t hcd_pipe_get_endpoint_addr(pipe_handle_t pipe_hdl) ATTR_PURE;
tusb_error_t hcd_pipe_clear_stall(pipe_handle_t pipe_hdl);
#if 0
tusb_error_t hcd_pipe_cancel()ATTR_WARN_UNUSED_RESULT;
#endif
//--------------------------------------------------------------------+
// PORT API
//--------------------------------------------------------------------+
/// return the current connect status of roothub port
bool hcd_port_connect_status(uint8_t hostid) ATTR_PURE ATTR_WARN_UNUSED_RESULT; // TODO make inline if possible
void hcd_port_reset(uint8_t hostid);
tusb_speed_t hcd_port_speed_get(uint8_t hostid) ATTR_PURE ATTR_WARN_UNUSED_RESULT; // TODO make inline if possible
void hcd_port_unplug(uint8_t hostid); // called by usbh to instruct hcd that it can execute unplug procedure
#ifdef __cplusplus
}
#endif
#endif /* _TUSB_HCD_H_ */
/// @}
/// @}

View File

@ -1,233 +1,233 @@
/**************************************************************************/
/*!
@file hub.c
@author hathach (tinyusb.org)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2013, hathach (tinyusb.org)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This file is part of the tinyusb stack.
*/
/**************************************************************************/
#include "tusb_option.h"
#if (MODE_HOST_SUPPORTED && TUSB_CFG_HOST_HUB)
#define _TINY_USB_SOURCE_FILE_
//--------------------------------------------------------------------+
// INCLUDE
//--------------------------------------------------------------------+
#include "hub.h"
#include "usbh_hub.h"
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
typedef struct {
pipe_handle_t pipe_status;
uint8_t interface_number;
uint8_t port_number;
uint8_t status_change; // data from status change interrupt endpoint
}usbh_hub_t;
TUSB_CFG_ATTR_USBRAM usbh_hub_t hub_data[TUSB_CFG_HOST_DEVICE_MAX];
TUSB_CFG_ATTR_USBRAM uint8_t hub_enum_buffer[sizeof(descriptor_hub_desc_t)];
//OSAL_SEM_DEF(hub_enum_semaphore);
//static osal_semaphore_handle_t hub_enum_sem_hdl;
//--------------------------------------------------------------------+
// HUB
//--------------------------------------------------------------------+
tusb_error_t hub_port_clear_feature_subtask(uint8_t hub_addr, uint8_t hub_port, uint8_t feature)
{
tusb_error_t error;
OSAL_SUBTASK_BEGIN
SUBTASK_ASSERT(HUB_FEATURE_PORT_CONNECTION_CHANGE <= feature &&
feature <= HUB_FEATURE_PORT_RESET_CHANGE);
//------------- Clear Port Feature request -------------//
OSAL_SUBTASK_INVOKED_AND_WAIT(
usbh_control_xfer_subtask( hub_addr, bm_request_type(TUSB_DIR_HOST_TO_DEV, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_OTHER),
HUB_REQUEST_CLEAR_FEATURE, feature, hub_port,
0, NULL ),
error
);
SUBTASK_ASSERT_STATUS( error );
//------------- Get Port Status to check if feature is cleared -------------//
OSAL_SUBTASK_INVOKED_AND_WAIT(
usbh_control_xfer_subtask( hub_addr, bm_request_type(TUSB_DIR_DEV_TO_HOST, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_OTHER),
HUB_REQUEST_GET_STATUS, 0, hub_port,
4, hub_enum_buffer ),
error
);
SUBTASK_ASSERT_STATUS( error );
//------------- Check if feature is cleared -------------//
hub_port_status_response_t * p_port_status = (hub_port_status_response_t *) hub_enum_buffer;
SUBTASK_ASSERT( !BIT_TEST_(p_port_status->status_change.value, feature-16) );
OSAL_SUBTASK_END
}
tusb_error_t hub_port_reset_subtask(uint8_t hub_addr, uint8_t hub_port)
{
tusb_error_t error;
OSAL_SUBTASK_BEGIN
//------------- Set Port Reset -------------//
OSAL_SUBTASK_INVOKED_AND_WAIT(
usbh_control_xfer_subtask( hub_addr, bm_request_type(TUSB_DIR_HOST_TO_DEV, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_OTHER),
HUB_REQUEST_SET_FEATURE, HUB_FEATURE_PORT_RESET, hub_port,
0, NULL ),
error
);
SUBTASK_ASSERT_STATUS( error );
osal_task_delay(50); // TODO Hub wait for Status Endpoint on Reset Change
//------------- Get Port Status to check if port is enabled, powered and reset_change -------------//
OSAL_SUBTASK_INVOKED_AND_WAIT(
usbh_control_xfer_subtask( hub_addr, bm_request_type(TUSB_DIR_DEV_TO_HOST, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_OTHER),
HUB_REQUEST_GET_STATUS, 0, hub_port,
4, hub_enum_buffer ),
error
);
SUBTASK_ASSERT_STATUS( error );
hub_port_status_response_t * p_port_status = (hub_port_status_response_t *) hub_enum_buffer;
SUBTASK_ASSERT ( p_port_status->status_change.reset && p_port_status->status_current.connect_status &&
p_port_status->status_current.port_power && p_port_status->status_current.port_enable);
OSAL_SUBTASK_END
}
// can only get the speed RIGHT AFTER hub_port_reset_subtask call
tusb_speed_t hub_port_get_speed(void)
{
hub_port_status_response_t * p_port_status = (hub_port_status_response_t *) hub_enum_buffer;
return (p_port_status->status_current.high_speed_device_attached) ? TUSB_SPEED_HIGH :
(p_port_status->status_current.low_speed_device_attached ) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL;
}
//--------------------------------------------------------------------+
// CLASS-USBH API (don't require to verify parameters)
//--------------------------------------------------------------------+
void hub_init(void)
{
memclr_(hub_data, TUSB_CFG_HOST_DEVICE_MAX*sizeof(usbh_hub_t));
// hub_enum_sem_hdl = osal_semaphore_create( OSAL_SEM_REF(hub_enum_semaphore) );
}
tusb_error_t hub_open_subtask(uint8_t dev_addr, tusb_descriptor_interface_t const *p_interface_desc, uint16_t *p_length)
{
tusb_error_t error;
OSAL_SUBTASK_BEGIN
// not support multiple TT yet
if ( p_interface_desc->bInterfaceProtocol > 1 ) return TUSB_ERROR_HUB_FEATURE_NOT_SUPPORTED;
//------------- Open Interrupt Status Pipe -------------//
tusb_descriptor_endpoint_t const *p_endpoint = (tusb_descriptor_endpoint_t const *) descriptor_next( (uint8_t const*) p_interface_desc );
SUBTASK_ASSERT(TUSB_DESC_TYPE_ENDPOINT == p_endpoint->bDescriptorType);
SUBTASK_ASSERT(TUSB_XFER_INTERRUPT == p_endpoint->bmAttributes.xfer);
hub_data[dev_addr-1].pipe_status = hcd_pipe_open(dev_addr, p_endpoint, TUSB_CLASS_HUB);
SUBTASK_ASSERT( pipehandle_is_valid(hub_data[dev_addr-1].pipe_status) );
hub_data[dev_addr-1].interface_number = p_interface_desc->bInterfaceNumber;
(*p_length) = sizeof(tusb_descriptor_interface_t) + sizeof(tusb_descriptor_endpoint_t);
//------------- Get Hub Descriptor -------------//
OSAL_SUBTASK_INVOKED_AND_WAIT(
usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_DEV_TO_HOST, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_DEVICE),
HUB_REQUEST_GET_DESCRIPTOR, 0, 0,
sizeof(descriptor_hub_desc_t), hub_enum_buffer ),
error
);
SUBTASK_ASSERT_STATUS(error);
// only care about this field in hub descriptor
hub_data[dev_addr-1].port_number = ((descriptor_hub_desc_t*) hub_enum_buffer)->bNbrPorts;
//------------- Set Port_Power on all ports -------------//
static uint8_t i;
for(i=1; i <= hub_data[dev_addr-1].port_number; i++)
{
OSAL_SUBTASK_INVOKED_AND_WAIT(
usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_HOST_TO_DEV, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_OTHER),
HUB_REQUEST_SET_FEATURE, HUB_FEATURE_PORT_POWER, i,
0, NULL ),
error
);
}
//------------- Queue the initial Status endpoint transfer -------------//
SUBTASK_ASSERT_STATUS ( hcd_pipe_xfer(hub_data[dev_addr-1].pipe_status, &hub_data[dev_addr-1].status_change, 1, true) );
OSAL_SUBTASK_END
}
void hub_isr(pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes)
{
usbh_hub_t * p_hub = &hub_data[pipe_hdl.dev_addr-1];
for (uint8_t port=1; port <= p_hub->port_number; port++)
{ // TODO HUB ignore bit0 hub_status_change
if ( BIT_TEST_(p_hub->status_change, port) )
{
usbh_hub_port_plugged_isr(pipe_hdl.dev_addr, port);
}
}
// NOTE: next status transfer is queued by usbh.c after handling this request
}
void hub_close(uint8_t dev_addr)
{
(void) hcd_pipe_close(hub_data[dev_addr-1].pipe_status);
memclr_(&hub_data[dev_addr-1], sizeof(usbh_hub_t));
// osal_semaphore_reset(hub_enum_sem_hdl);
}
tusb_error_t hub_status_pipe_queue(uint8_t dev_addr)
{
return hcd_pipe_xfer(hub_data[dev_addr-1].pipe_status, &hub_data[dev_addr-1].status_change, 1, true);
}
#endif
/**************************************************************************/
/*!
@file hub.c
@author hathach (tinyusb.org)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2013, hathach (tinyusb.org)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This file is part of the tinyusb stack.
*/
/**************************************************************************/
#include "tusb_option.h"
#if (MODE_HOST_SUPPORTED && TUSB_CFG_HOST_HUB)
#define _TINY_USB_SOURCE_FILE_
//--------------------------------------------------------------------+
// INCLUDE
//--------------------------------------------------------------------+
#include "hub.h"
#include "usbh_hub.h"
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
typedef struct {
pipe_handle_t pipe_status;
uint8_t interface_number;
uint8_t port_number;
uint8_t status_change; // data from status change interrupt endpoint
}usbh_hub_t;
TUSB_CFG_ATTR_USBRAM usbh_hub_t hub_data[TUSB_CFG_HOST_DEVICE_MAX];
TUSB_CFG_ATTR_USBRAM uint8_t hub_enum_buffer[sizeof(descriptor_hub_desc_t)];
//OSAL_SEM_DEF(hub_enum_semaphore);
//static osal_semaphore_handle_t hub_enum_sem_hdl;
//--------------------------------------------------------------------+
// HUB
//--------------------------------------------------------------------+
tusb_error_t hub_port_clear_feature_subtask(uint8_t hub_addr, uint8_t hub_port, uint8_t feature)
{
tusb_error_t error;
OSAL_SUBTASK_BEGIN
SUBTASK_ASSERT(HUB_FEATURE_PORT_CONNECTION_CHANGE <= feature &&
feature <= HUB_FEATURE_PORT_RESET_CHANGE);
//------------- Clear Port Feature request -------------//
OSAL_SUBTASK_INVOKED_AND_WAIT(
usbh_control_xfer_subtask( hub_addr, bm_request_type(TUSB_DIR_HOST_TO_DEV, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_OTHER),
HUB_REQUEST_CLEAR_FEATURE, feature, hub_port,
0, NULL ),
error
);
SUBTASK_ASSERT_STATUS( error );
//------------- Get Port Status to check if feature is cleared -------------//
OSAL_SUBTASK_INVOKED_AND_WAIT(
usbh_control_xfer_subtask( hub_addr, bm_request_type(TUSB_DIR_DEV_TO_HOST, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_OTHER),
HUB_REQUEST_GET_STATUS, 0, hub_port,
4, hub_enum_buffer ),
error
);
SUBTASK_ASSERT_STATUS( error );
//------------- Check if feature is cleared -------------//
hub_port_status_response_t * p_port_status = (hub_port_status_response_t *) hub_enum_buffer;
SUBTASK_ASSERT( !BIT_TEST_(p_port_status->status_change.value, feature-16) );
OSAL_SUBTASK_END
}
tusb_error_t hub_port_reset_subtask(uint8_t hub_addr, uint8_t hub_port)
{
tusb_error_t error;
OSAL_SUBTASK_BEGIN
//------------- Set Port Reset -------------//
OSAL_SUBTASK_INVOKED_AND_WAIT(
usbh_control_xfer_subtask( hub_addr, bm_request_type(TUSB_DIR_HOST_TO_DEV, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_OTHER),
HUB_REQUEST_SET_FEATURE, HUB_FEATURE_PORT_RESET, hub_port,
0, NULL ),
error
);
SUBTASK_ASSERT_STATUS( error );
osal_task_delay(50); // TODO Hub wait for Status Endpoint on Reset Change
//------------- Get Port Status to check if port is enabled, powered and reset_change -------------//
OSAL_SUBTASK_INVOKED_AND_WAIT(
usbh_control_xfer_subtask( hub_addr, bm_request_type(TUSB_DIR_DEV_TO_HOST, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_OTHER),
HUB_REQUEST_GET_STATUS, 0, hub_port,
4, hub_enum_buffer ),
error
);
SUBTASK_ASSERT_STATUS( error );
hub_port_status_response_t * p_port_status = (hub_port_status_response_t *) hub_enum_buffer;
SUBTASK_ASSERT ( p_port_status->status_change.reset && p_port_status->status_current.connect_status &&
p_port_status->status_current.port_power && p_port_status->status_current.port_enable);
OSAL_SUBTASK_END
}
// can only get the speed RIGHT AFTER hub_port_reset_subtask call
tusb_speed_t hub_port_get_speed(void)
{
hub_port_status_response_t * p_port_status = (hub_port_status_response_t *) hub_enum_buffer;
return (p_port_status->status_current.high_speed_device_attached) ? TUSB_SPEED_HIGH :
(p_port_status->status_current.low_speed_device_attached ) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL;
}
//--------------------------------------------------------------------+
// CLASS-USBH API (don't require to verify parameters)
//--------------------------------------------------------------------+
void hub_init(void)
{
memclr_(hub_data, TUSB_CFG_HOST_DEVICE_MAX*sizeof(usbh_hub_t));
// hub_enum_sem_hdl = osal_semaphore_create( OSAL_SEM_REF(hub_enum_semaphore) );
}
tusb_error_t hub_open_subtask(uint8_t dev_addr, tusb_descriptor_interface_t const *p_interface_desc, uint16_t *p_length)
{
tusb_error_t error;
OSAL_SUBTASK_BEGIN
// not support multiple TT yet
if ( p_interface_desc->bInterfaceProtocol > 1 ) return TUSB_ERROR_HUB_FEATURE_NOT_SUPPORTED;
//------------- Open Interrupt Status Pipe -------------//
tusb_descriptor_endpoint_t const *p_endpoint = (tusb_descriptor_endpoint_t const *) descriptor_next( (uint8_t const*) p_interface_desc );
SUBTASK_ASSERT(TUSB_DESC_TYPE_ENDPOINT == p_endpoint->bDescriptorType);
SUBTASK_ASSERT(TUSB_XFER_INTERRUPT == p_endpoint->bmAttributes.xfer);
hub_data[dev_addr-1].pipe_status = hcd_pipe_open(dev_addr, p_endpoint, TUSB_CLASS_HUB);
SUBTASK_ASSERT( pipehandle_is_valid(hub_data[dev_addr-1].pipe_status) );
hub_data[dev_addr-1].interface_number = p_interface_desc->bInterfaceNumber;
(*p_length) = sizeof(tusb_descriptor_interface_t) + sizeof(tusb_descriptor_endpoint_t);
//------------- Get Hub Descriptor -------------//
OSAL_SUBTASK_INVOKED_AND_WAIT(
usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_DEV_TO_HOST, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_DEVICE),
HUB_REQUEST_GET_DESCRIPTOR, 0, 0,
sizeof(descriptor_hub_desc_t), hub_enum_buffer ),
error
);
SUBTASK_ASSERT_STATUS(error);
// only care about this field in hub descriptor
hub_data[dev_addr-1].port_number = ((descriptor_hub_desc_t*) hub_enum_buffer)->bNbrPorts;
//------------- Set Port_Power on all ports -------------//
static uint8_t i;
for(i=1; i <= hub_data[dev_addr-1].port_number; i++)
{
OSAL_SUBTASK_INVOKED_AND_WAIT(
usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_HOST_TO_DEV, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_OTHER),
HUB_REQUEST_SET_FEATURE, HUB_FEATURE_PORT_POWER, i,
0, NULL ),
error
);
}
//------------- Queue the initial Status endpoint transfer -------------//
SUBTASK_ASSERT_STATUS ( hcd_pipe_xfer(hub_data[dev_addr-1].pipe_status, &hub_data[dev_addr-1].status_change, 1, true) );
OSAL_SUBTASK_END
}
void hub_isr(pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes)
{
usbh_hub_t * p_hub = &hub_data[pipe_hdl.dev_addr-1];
for (uint8_t port=1; port <= p_hub->port_number; port++)
{ // TODO HUB ignore bit0 hub_status_change
if ( BIT_TEST_(p_hub->status_change, port) )
{
usbh_hub_port_plugged_isr(pipe_hdl.dev_addr, port);
}
}
// NOTE: next status transfer is queued by usbh.c after handling this request
}
void hub_close(uint8_t dev_addr)
{
(void) hcd_pipe_close(hub_data[dev_addr-1].pipe_status);
memclr_(&hub_data[dev_addr-1], sizeof(usbh_hub_t));
// osal_semaphore_reset(hub_enum_sem_hdl);
}
tusb_error_t hub_status_pipe_queue(uint8_t dev_addr)
{
return hcd_pipe_xfer(hub_data[dev_addr-1].pipe_status, &hub_data[dev_addr-1].status_change, 1, true);
}
#endif

View File

@ -1,75 +1,75 @@
/**************************************************************************/
/*!
@file osal_common.h
@author hathach (tinyusb.org)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2013, hathach (tinyusb.org)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This file is part of the tinyusb stack.
*/
/**************************************************************************/
/** \ingroup TBD
* \defgroup TBD
* \brief TBD
*
* @{
*/
#ifndef _TUSB_OSAL_COMMON_H_
#define _TUSB_OSAL_COMMON_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "common/common.h"
enum
{
OSAL_TIMEOUT_NOTIMEOUT = 0, // for use within ISR, return immediately
OSAL_TIMEOUT_NORMAL = 10*5, // default is 10 msec, FIXME CMSIS-RTX easily timeout with 10 msec
OSAL_TIMEOUT_WAIT_FOREVER = 0x0EEEEEEE
};
// TODO refractor/remove this function and/or TUSB_CFG_OS_TICKS_PER_SECOND if using an RTOS
static inline uint32_t osal_tick_from_msec(uint32_t msec) ATTR_CONST ATTR_ALWAYS_INLINE;
static inline uint32_t osal_tick_from_msec(uint32_t msec)
{
return (msec * TUSB_CFG_OS_TICKS_PER_SECOND)/1000;
}
#ifdef __cplusplus
}
#endif
#endif /* _TUSB_OSAL_COMMON_H_ */
/** @} */
/**************************************************************************/
/*!
@file osal_common.h
@author hathach (tinyusb.org)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2013, hathach (tinyusb.org)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This file is part of the tinyusb stack.
*/
/**************************************************************************/
/** \ingroup TBD
* \defgroup TBD
* \brief TBD
*
* @{
*/
#ifndef _TUSB_OSAL_COMMON_H_
#define _TUSB_OSAL_COMMON_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "common/common.h"
enum
{
OSAL_TIMEOUT_NOTIMEOUT = 0, // for use within ISR, return immediately
OSAL_TIMEOUT_NORMAL = 10*5, // default is 10 msec, FIXME CMSIS-RTX easily timeout with 10 msec
OSAL_TIMEOUT_WAIT_FOREVER = 0x0EEEEEEE
};
// TODO refractor/remove this function and/or TUSB_CFG_OS_TICKS_PER_SECOND if using an RTOS
static inline uint32_t osal_tick_from_msec(uint32_t msec) ATTR_CONST ATTR_ALWAYS_INLINE;
static inline uint32_t osal_tick_from_msec(uint32_t msec)
{
return (msec * TUSB_CFG_OS_TICKS_PER_SECOND)/1000;
}
#ifdef __cplusplus
}
#endif
#endif /* _TUSB_OSAL_COMMON_H_ */
/** @} */