mirror of
https://github.com/hathach/tinyusb.git
synced 2025-03-26 08:37:16 +00:00
add usbh_edpt_claim/release
implement USBH_EVENT_FUNC_CALL
This commit is contained in:
parent
b5d4c8185d
commit
87b989e8b4
@ -77,7 +77,7 @@ typedef struct TU_ATTR_ALIGNED(4)
|
||||
uint32_t len;
|
||||
}xfer_complete;
|
||||
|
||||
// USBD_EVENT_FUNC_CALL
|
||||
// FUNC_CALL
|
||||
struct {
|
||||
void (*func) (void*);
|
||||
void* param;
|
||||
|
@ -45,6 +45,11 @@ typedef enum
|
||||
HCD_EVENT_DEVICE_ATTACH,
|
||||
HCD_EVENT_DEVICE_REMOVE,
|
||||
HCD_EVENT_XFER_COMPLETE,
|
||||
|
||||
// Not an HCD event, just a convenient way to defer ISR function
|
||||
USBH_EVENT_FUNC_CALL,
|
||||
|
||||
HCD_EVENT_COUNT
|
||||
} hcd_eventid_t;
|
||||
|
||||
typedef struct
|
||||
@ -67,6 +72,12 @@ typedef struct
|
||||
uint8_t result;
|
||||
uint32_t len;
|
||||
} xfer_complete;
|
||||
|
||||
// FUNC_CALL
|
||||
struct {
|
||||
void (*func) (void*);
|
||||
void* param;
|
||||
}func_call;
|
||||
};
|
||||
|
||||
} hcd_event_t;
|
||||
|
@ -169,6 +169,11 @@ bool tuh_init(void)
|
||||
dev->control.sem_hdl = osal_semaphore_create(&dev->control.sem_def);
|
||||
TU_ASSERT(dev->control.sem_hdl != NULL);
|
||||
|
||||
#if CFG_TUSB_OS != OPT_OS_NONE
|
||||
dev->mutex = osal_mutex_create(&dev->mutexdef);
|
||||
TU_ASSERT(dev->mutex);
|
||||
#endif
|
||||
|
||||
memset(dev->itf2drv, 0xff, sizeof(dev->itf2drv)); // invalid mapping
|
||||
memset(dev->ep2drv , 0xff, sizeof(dev->ep2drv )); // invalid mapping
|
||||
}
|
||||
@ -187,6 +192,8 @@ bool tuh_init(void)
|
||||
}
|
||||
|
||||
//------------- USBH control transfer -------------//
|
||||
|
||||
// TODO remove
|
||||
bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t* request, uint8_t* data)
|
||||
{
|
||||
usbh_device_t* dev = &_usbh_devices[dev_addr];
|
||||
@ -216,6 +223,58 @@ bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t* request, uint8
|
||||
return true;
|
||||
}
|
||||
|
||||
bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr)
|
||||
{
|
||||
uint8_t const epnum = tu_edpt_number(ep_addr);
|
||||
uint8_t const dir = tu_edpt_dir(ep_addr);
|
||||
|
||||
usbh_device_t* dev = &_usbh_devices[dev_addr];
|
||||
|
||||
#if CFG_TUSB_OS != OPT_OS_NONE
|
||||
// pre-check to help reducing mutex lock
|
||||
TU_VERIFY((dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 0));
|
||||
osal_mutex_lock(dev->mutex, OSAL_TIMEOUT_WAIT_FOREVER);
|
||||
#endif
|
||||
|
||||
// can only claim the endpoint if it is not busy and not claimed yet.
|
||||
bool const ret = (dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 0);
|
||||
if (ret)
|
||||
{
|
||||
dev->ep_status[epnum][dir].claimed = 1;
|
||||
}
|
||||
|
||||
#if CFG_TUSB_OS != OPT_OS_NONE
|
||||
osal_mutex_unlock(dev->mutex);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr)
|
||||
{
|
||||
uint8_t const epnum = tu_edpt_number(ep_addr);
|
||||
uint8_t const dir = tu_edpt_dir(ep_addr);
|
||||
|
||||
usbh_device_t* dev = &_usbh_devices[dev_addr];
|
||||
|
||||
#if CFG_TUSB_OS != OPT_OS_NONE
|
||||
osal_mutex_lock(dev->mutex, OSAL_TIMEOUT_WAIT_FOREVER);
|
||||
#endif
|
||||
|
||||
// can only release the endpoint if it is claimed and not busy
|
||||
bool const ret = (dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 1);
|
||||
if (ret)
|
||||
{
|
||||
dev->ep_status[epnum][dir].claimed = 0;
|
||||
}
|
||||
|
||||
#if CFG_TUSB_OS != OPT_OS_NONE
|
||||
osal_mutex_unlock(dev->mutex);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
|
||||
{
|
||||
usbh_device_t* dev = &_usbh_devices[dev_addr];
|
||||
@ -402,6 +461,8 @@ void tuh_task(void)
|
||||
switch (event.event_id)
|
||||
{
|
||||
case HCD_EVENT_DEVICE_ATTACH:
|
||||
// TODO due to the shared _usbh_ctrl_buf, we must complete enumerating
|
||||
// one device before enumerating another one.
|
||||
TU_LOG2("USBH DEVICE ATTACH\r\n");
|
||||
enum_new_device(&event);
|
||||
break;
|
||||
@ -443,6 +504,10 @@ void tuh_task(void)
|
||||
}
|
||||
break;
|
||||
|
||||
case USBH_EVENT_FUNC_CALL:
|
||||
if ( event.func_call.func ) event.func_call.func(event.func_call.param);
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
@ -465,6 +530,8 @@ static uint8_t get_new_address(void)
|
||||
// is a lengthy process with a seires of control transfer to configure
|
||||
// newly attached device. Each step is handled by a function in this
|
||||
// section
|
||||
// TODO due to the shared _usbh_ctrl_buf, we must complete enumerating
|
||||
// one device before enumerating another one.
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
static bool enum_get_addr0_device_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result);
|
||||
@ -785,7 +852,7 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura
|
||||
{
|
||||
tusb_desc_interface_t const* desc_itf = (tusb_desc_interface_t const*) p_desc;
|
||||
|
||||
// Check if class is supportedVe
|
||||
// Check if class is supported
|
||||
uint8_t drv_id;
|
||||
for (drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++)
|
||||
{
|
||||
@ -799,6 +866,8 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura
|
||||
}
|
||||
else
|
||||
{
|
||||
usbh_class_driver_t const * driver = &usbh_class_drivers[drv_id];
|
||||
|
||||
// Interface number must not be used already TODO alternate interface
|
||||
TU_ASSERT( dev->itf2drv[desc_itf->bInterfaceNumber] == 0xff );
|
||||
dev->itf2drv[desc_itf->bInterfaceNumber] = drv_id;
|
||||
@ -813,8 +882,8 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura
|
||||
{
|
||||
uint16_t itf_len = 0;
|
||||
|
||||
TU_LOG2("%s open\r\n", usbh_class_drivers[drv_id].name);
|
||||
TU_ASSERT( usbh_class_drivers[drv_id].open(dev->rhport, dev_addr, desc_itf, &itf_len) );
|
||||
TU_LOG2("%s open\r\n", driver->name);
|
||||
TU_ASSERT( driver->open(dev->rhport, dev_addr, desc_itf, &itf_len) );
|
||||
TU_ASSERT( itf_len >= sizeof(tusb_desc_interface_t) );
|
||||
p_desc += itf_len;
|
||||
}
|
||||
|
@ -65,6 +65,7 @@ typedef struct {
|
||||
} usbh_class_driver_t;
|
||||
|
||||
typedef bool (*tuh_control_complete_cb_t)(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result);
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// INTERNAL OBJECT & FUNCTION DECLARATION
|
||||
//--------------------------------------------------------------------+
|
||||
@ -106,11 +107,15 @@ TU_ATTR_WEAK void tuh_umount_cb(uint8_t dev_addr);
|
||||
// CLASS-USBH & INTERNAL API
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t* request, uint8_t* data);
|
||||
bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc);
|
||||
|
||||
bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes);
|
||||
|
||||
// Claim an endpoint before submitting a transfer.
|
||||
// If caller does not make any transfer, it must release endpoint for others.
|
||||
bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr);
|
||||
|
||||
bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t* request, uint8_t* data); // TODO remove later
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -58,6 +58,8 @@ static usbh_control_xfer_t _ctrl_xfer;
|
||||
|
||||
bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb)
|
||||
{
|
||||
// TODO need to claim the endpoint first
|
||||
|
||||
usbh_device_t* dev = &_usbh_devices[dev_addr];
|
||||
const uint8_t rhport = dev->rhport;
|
||||
|
||||
@ -83,6 +85,10 @@ static void _xfer_complete(uint8_t dev_addr, xfer_result_t result)
|
||||
|
||||
bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes)
|
||||
{
|
||||
(void) ep_addr;
|
||||
(void) xferred_bytes;
|
||||
|
||||
|
||||
usbh_device_t* dev = &_usbh_devices[dev_addr];
|
||||
const uint8_t rhport = dev->rhport;
|
||||
|
||||
@ -106,7 +112,7 @@ bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t resu
|
||||
hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, request->bmRequestType_bit.direction), _ctrl_xfer.buffer, request->wLength);
|
||||
return true;
|
||||
}
|
||||
__attribute__((fallthrough));
|
||||
__attribute__((fallthrough));
|
||||
|
||||
case STAGE_DATA:
|
||||
_ctrl_xfer.stage = STAGE_ACK;
|
||||
|
@ -40,6 +40,10 @@
|
||||
#include "common/tusb_common.h"
|
||||
#include "osal/osal.h"
|
||||
|
||||
#ifndef CFG_TUH_EP_MAX
|
||||
#define CFG_TUH_EP_MAX 9
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// USBH-HCD common data structure
|
||||
//--------------------------------------------------------------------+
|
||||
@ -80,7 +84,24 @@ typedef struct {
|
||||
} control;
|
||||
|
||||
uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid)
|
||||
uint8_t ep2drv[8][2]; // map endpoint to driver ( 0xff is invalid )
|
||||
uint8_t ep2drv[CFG_TUH_EP_MAX][2]; // map endpoint to driver ( 0xff is invalid )
|
||||
|
||||
struct TU_ATTR_PACKED
|
||||
{
|
||||
volatile bool busy : 1;
|
||||
volatile bool stalled : 1;
|
||||
volatile bool claimed : 1;
|
||||
|
||||
// TODO merge ep2drv here, 4-bit should be sufficient
|
||||
}ep_status[CFG_TUH_EP_MAX][2];
|
||||
|
||||
|
||||
// Mutex for claiming endpoint, only needed when using with preempted RTOS
|
||||
#if CFG_TUSB_OS != OPT_OS_NONE
|
||||
osal_mutex_def_t mutexdef;
|
||||
osal_mutex_t mutex;
|
||||
#endif
|
||||
|
||||
} usbh_device_t;
|
||||
|
||||
extern usbh_device_t _usbh_devices[CFG_TUSB_HOST_DEVICE_MAX+1]; // including zero-address
|
||||
|
Loading…
x
Reference in New Issue
Block a user