mirror of
https://github.com/hathach/tinyusb.git
synced 2025-01-31 05:52:55 +08:00
added usbd_edpt_xfer/usbd_edpt_busy to replace dcd_edpt_transfer/dcd_edpt_busy()
- improve fifo write/read_n with only one lock - use usbd_edpt_xfer/usbd_edpt_busy for hid/cdc/msc class driver - replace cdc read's pending_read_from_host by usbd_edpt_busy()
This commit is contained in:
parent
dfdae7a4d2
commit
a0307bafda
@ -201,7 +201,7 @@ void hid_task(void)
|
||||
tud_hid_mouse_report(REPORT_ID_MOUSE, 0x00, delta, delta, 0, 0);
|
||||
|
||||
// delay a bit before attempt to send keyboard report
|
||||
board_delay(2);
|
||||
board_delay(10);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -73,23 +73,21 @@ typedef struct
|
||||
//--------------------------------------------------------------------+
|
||||
CFG_TUSB_MEM_SECTION static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC];
|
||||
|
||||
// TODO will be replaced by dcd_edpt_busy()
|
||||
bool pending_read_from_host;
|
||||
//bool pending_read_from_host; TODO remove
|
||||
static void _prep_out_transaction (uint8_t itf)
|
||||
{
|
||||
cdcd_interface_t* p_cdc = &_cdcd_itf[itf];
|
||||
|
||||
// skip if previous transfer not complete
|
||||
// dcd_edpt_busy() doesn't work, probably transfer is complete but not properly handled by the stack
|
||||
// if ( dcd_edpt_busy(TUD_OPT_RHPORT, p_cdc->ep_out) ) return;
|
||||
if (pending_read_from_host) return;
|
||||
if ( usbd_edpt_busy(TUD_OPT_RHPORT, p_cdc->ep_out) ) return;
|
||||
//if (pending_read_from_host) return;
|
||||
|
||||
// Prepare for incoming data but only allow what we can store in the ring buffer.
|
||||
uint16_t max_read = tu_fifo_remaining(&p_cdc->rx_ff);
|
||||
if ( max_read >= CFG_TUD_CDC_EPSIZE )
|
||||
{
|
||||
dcd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_out, p_cdc->epout_buf, CFG_TUD_CDC_EPSIZE);
|
||||
pending_read_from_host = true;
|
||||
usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_out, p_cdc->epout_buf, CFG_TUD_CDC_EPSIZE);
|
||||
// pending_read_from_host = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -183,13 +181,13 @@ uint32_t tud_cdc_n_write(uint8_t itf, void const* buffer, uint32_t bufsize)
|
||||
bool tud_cdc_n_write_flush (uint8_t itf)
|
||||
{
|
||||
cdcd_interface_t* p_cdc = &_cdcd_itf[itf];
|
||||
TU_VERIFY( !dcd_edpt_busy(TUD_OPT_RHPORT, p_cdc->ep_in) ); // skip if previous transfer not complete
|
||||
TU_VERIFY( !usbd_edpt_busy(TUD_OPT_RHPORT, p_cdc->ep_in) ); // skip if previous transfer not complete
|
||||
|
||||
uint16_t count = tu_fifo_read_n(&_cdcd_itf[itf].tx_ff, p_cdc->epin_buf, CFG_TUD_CDC_EPSIZE);
|
||||
if ( count )
|
||||
{
|
||||
TU_VERIFY( tud_cdc_n_connected(itf) ); // fifo is empty if not connected
|
||||
TU_ASSERT( dcd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, p_cdc->epin_buf, count) );
|
||||
TU_ASSERT( usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, p_cdc->epin_buf, count) );
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -298,7 +296,7 @@ bool cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t
|
||||
}
|
||||
|
||||
// Prepare for incoming data
|
||||
pending_read_from_host = false;
|
||||
// pending_read_from_host = false;
|
||||
_prep_out_transaction(cdc_id);
|
||||
|
||||
return true;
|
||||
@ -394,7 +392,7 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_
|
||||
if (tud_cdc_rx_cb && tu_fifo_count(&p_cdc->rx_ff) ) tud_cdc_rx_cb(itf);
|
||||
|
||||
// prepare for OUT transaction
|
||||
pending_read_from_host = false;
|
||||
// pending_read_from_host = false;
|
||||
_prep_out_transaction(itf);
|
||||
}
|
||||
|
||||
|
@ -73,28 +73,31 @@ bool tud_hid_ready(void)
|
||||
{
|
||||
uint8_t itf = 0;
|
||||
uint8_t const ep_in = _hidd_itf[itf].ep_in;
|
||||
return tud_ready() && (ep_in != 0) && !dcd_edpt_busy(TUD_OPT_RHPORT, ep_in);
|
||||
return tud_ready() && (ep_in != 0) && !usbd_edpt_busy(TUD_OPT_RHPORT, ep_in);
|
||||
}
|
||||
|
||||
bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len)
|
||||
{
|
||||
TU_VERIFY( tud_hid_ready() && (len <= CFG_TUD_HID_BUFSIZE) );
|
||||
TU_VERIFY( tud_hid_ready() );
|
||||
|
||||
uint8_t itf = 0;
|
||||
hidd_interface_t * p_hid = &_hidd_itf[itf];
|
||||
|
||||
// If report id = 0, skip ID field
|
||||
if (report_id)
|
||||
{
|
||||
len = tu_min8(len, CFG_TUD_HID_BUFSIZE-1);
|
||||
|
||||
p_hid->epin_buf[0] = report_id;
|
||||
memcpy(p_hid->epin_buf+1, report, len);
|
||||
len++;
|
||||
}else
|
||||
{
|
||||
// If report id = 0, skip ID field
|
||||
len = tu_min8(len, CFG_TUD_HID_BUFSIZE);
|
||||
memcpy(p_hid->epin_buf, report, len);
|
||||
}
|
||||
|
||||
return dcd_edpt_xfer(TUD_OPT_RHPORT, p_hid->ep_in, p_hid->epin_buf, len);
|
||||
return usbd_edpt_xfer(TUD_OPT_RHPORT, p_hid->ep_in, p_hid->epin_buf, len);
|
||||
}
|
||||
|
||||
bool tud_hid_boot_mode(void)
|
||||
@ -180,7 +183,7 @@ bool hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t
|
||||
*p_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t);
|
||||
|
||||
// Prepare for output endpoint
|
||||
if (p_hid->ep_out) TU_ASSERT(dcd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf)));
|
||||
if (p_hid->ep_out) TU_ASSERT(usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf)));
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -303,7 +306,7 @@ bool hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_
|
||||
if (ep_addr == p_hid->ep_out)
|
||||
{
|
||||
tud_hid_set_report_cb(0, HID_REPORT_TYPE_INVALID, p_hid->epout_buf, xferred_bytes);
|
||||
TU_ASSERT(dcd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf)));
|
||||
TU_ASSERT(usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf)));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -139,7 +139,7 @@ bool mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t
|
||||
(*p_len) = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t);
|
||||
|
||||
// Prepare for Command Block Wrapper
|
||||
TU_ASSERT( dcd_edpt_xfer(rhport, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t)) );
|
||||
TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t)) );
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -394,7 +394,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
|
||||
if ( (p_cbw->total_bytes > 0 ) && !tu_bit_test(p_cbw->dir, 7) )
|
||||
{
|
||||
// queue transfer
|
||||
TU_ASSERT( dcd_edpt_xfer(rhport, p_msc->ep_out, _mscd_buf, p_msc->total_len) );
|
||||
TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, _mscd_buf, p_msc->total_len) );
|
||||
}else
|
||||
{
|
||||
int32_t resplen;
|
||||
@ -428,7 +428,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
|
||||
if (p_msc->total_len)
|
||||
{
|
||||
TU_ASSERT( p_cbw->total_bytes >= p_msc->total_len ); // cannot return more than host expect
|
||||
TU_ASSERT( dcd_edpt_xfer(rhport, p_msc->ep_in, _mscd_buf, p_msc->total_len) );
|
||||
TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_in, _mscd_buf, p_msc->total_len) );
|
||||
}else
|
||||
{
|
||||
p_msc->stage = MSC_STAGE_STATUS;
|
||||
@ -543,7 +543,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
|
||||
p_msc->stage = MSC_STAGE_CMD;
|
||||
|
||||
// Send SCSI Status
|
||||
TU_ASSERT( dcd_edpt_xfer(rhport, p_msc->ep_in , (uint8_t*) &p_msc->csw, sizeof(msc_csw_t)) );
|
||||
TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_in , (uint8_t*) &p_msc->csw, sizeof(msc_csw_t)) );
|
||||
|
||||
// Invoke complete callback if defined
|
||||
if ( SCSI_CMD_READ_10 == p_cbw->command[0])
|
||||
@ -560,7 +560,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
|
||||
}
|
||||
|
||||
// Queue for the next CBW
|
||||
TU_ASSERT( dcd_edpt_xfer(rhport, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t)) );
|
||||
TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t)) );
|
||||
}
|
||||
}
|
||||
|
||||
@ -602,7 +602,7 @@ static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc)
|
||||
}
|
||||
else
|
||||
{
|
||||
TU_ASSERT( dcd_edpt_xfer(rhport, p_msc->ep_in, _mscd_buf, nbytes), );
|
||||
TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_in, _mscd_buf, nbytes), );
|
||||
}
|
||||
}
|
||||
|
||||
@ -627,7 +627,7 @@ static void proc_write10_cmd(uint8_t rhport, mscd_interface_t* p_msc)
|
||||
int32_t nbytes = (int32_t) tu_min32(sizeof(_mscd_buf), p_cbw->total_bytes-p_msc->xferred_len);
|
||||
|
||||
// Write10 callback will be called later when usb transfer complete
|
||||
TU_ASSERT( dcd_edpt_xfer(rhport, p_msc->ep_out, _mscd_buf, nbytes), );
|
||||
TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, _mscd_buf, nbytes), );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -71,6 +71,35 @@ bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_si
|
||||
return true;
|
||||
}
|
||||
|
||||
// retrieve data from fifo
|
||||
static void _tu_ff_pull(tu_fifo_t* f, void * buffer)
|
||||
{
|
||||
memcpy(buffer,
|
||||
f->buffer + (f->rd_idx * f->item_size),
|
||||
f->item_size);
|
||||
|
||||
f->rd_idx = (f->rd_idx + 1) % f->depth;
|
||||
f->count--;
|
||||
}
|
||||
|
||||
// send data to fifo
|
||||
static void _tu_ff_push(tu_fifo_t* f, void const * data)
|
||||
{
|
||||
memcpy( f->buffer + (f->wr_idx * f->item_size),
|
||||
data,
|
||||
f->item_size);
|
||||
|
||||
f->wr_idx = (f->wr_idx + 1) % f->depth;
|
||||
|
||||
if (tu_fifo_full(f))
|
||||
{
|
||||
f->rd_idx = f->wr_idx; // keep the full state (rd == wr && len = size)
|
||||
}
|
||||
else
|
||||
{
|
||||
f->count++;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*!
|
||||
@ -82,23 +111,19 @@ bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_si
|
||||
|
||||
@param[in] f
|
||||
Pointer to the FIFO buffer to manipulate
|
||||
@param[in] p_buffer
|
||||
@param[in] buffer
|
||||
Pointer to the place holder for data read from the buffer
|
||||
|
||||
@returns TRUE if the queue is not empty
|
||||
*/
|
||||
/******************************************************************************/
|
||||
bool tu_fifo_read(tu_fifo_t* f, void * p_buffer)
|
||||
bool tu_fifo_read(tu_fifo_t* f, void * buffer)
|
||||
{
|
||||
if( tu_fifo_empty(f) ) return false;
|
||||
|
||||
tu_fifo_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--;
|
||||
_tu_ff_pull(f, buffer);
|
||||
|
||||
tu_fifo_unlock(f);
|
||||
|
||||
@ -113,7 +138,7 @@ bool tu_fifo_read(tu_fifo_t* f, void * p_buffer)
|
||||
|
||||
@param[in] f
|
||||
Pointer to the FIFO buffer to manipulate
|
||||
@param[in] p_data
|
||||
@param[in] buffer
|
||||
The pointer to data location
|
||||
@param[in] count
|
||||
Number of element that buffer can afford
|
||||
@ -121,27 +146,28 @@ bool tu_fifo_read(tu_fifo_t* f, void * p_buffer)
|
||||
@returns number of items read from the FIFO
|
||||
*/
|
||||
/******************************************************************************/
|
||||
uint16_t tu_fifo_read_n (tu_fifo_t* f, void * p_buffer, uint16_t count)
|
||||
uint16_t tu_fifo_read_n (tu_fifo_t* f, void * buffer, uint16_t count)
|
||||
{
|
||||
if( tu_fifo_empty(f) ) return 0;
|
||||
|
||||
tu_fifo_lock(f);
|
||||
|
||||
/* Limit up to fifo's count */
|
||||
if ( count > f->count ) count = f->count;
|
||||
|
||||
/* Could copy up to 2 portions marked as 'x' if queue is wrapped around
|
||||
* case 1: ....RxxxxW.......
|
||||
* case 2: xxxxxW....Rxxxxxx
|
||||
*/
|
||||
// uint16_t index2upper = tu_min16(count, f->count-f->rd_idx);
|
||||
|
||||
uint8_t* p_buf = (uint8_t*) p_buffer;
|
||||
uint8_t* buf8 = (uint8_t*) buffer;
|
||||
uint16_t len = 0;
|
||||
while( (len < count) && tu_fifo_read(f, p_buf) )
|
||||
|
||||
while (len < count)
|
||||
{
|
||||
_tu_ff_pull(f, buf8);
|
||||
|
||||
len++;
|
||||
p_buf += f->item_size;
|
||||
buf8 += f->item_size;
|
||||
}
|
||||
|
||||
tu_fifo_unlock(f);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
@ -182,33 +208,20 @@ bool tu_fifo_peek_at(tu_fifo_t* f, uint16_t pos, void * p_buffer)
|
||||
|
||||
@param[in] f
|
||||
Pointer to the FIFO buffer to manipulate
|
||||
@param[in] p_data
|
||||
@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 tu_fifo_write (tu_fifo_t* f, const void * p_data)
|
||||
bool tu_fifo_write (tu_fifo_t* f, const void * data)
|
||||
{
|
||||
if ( tu_fifo_full(f) && !f->overwritable ) return false;
|
||||
|
||||
tu_fifo_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 (tu_fifo_full(f))
|
||||
{
|
||||
f->rd_idx = f->wr_idx; // keep the full state (rd == wr && len = size)
|
||||
}
|
||||
else
|
||||
{
|
||||
f->count++;
|
||||
}
|
||||
_tu_ff_push(f, data);
|
||||
|
||||
tu_fifo_unlock(f);
|
||||
|
||||
@ -223,26 +236,35 @@ bool tu_fifo_write (tu_fifo_t* f, const void * p_data)
|
||||
|
||||
@param[in] f
|
||||
Pointer to the FIFO buffer to manipulate
|
||||
@param[in] p_data
|
||||
@param[in] data
|
||||
The pointer to data to add to the FIFO
|
||||
@param[in] count
|
||||
Number of element
|
||||
@return Number of written elements
|
||||
*/
|
||||
/******************************************************************************/
|
||||
uint16_t tu_fifo_write_n (tu_fifo_t* f, const void * p_data, uint16_t count)
|
||||
uint16_t tu_fifo_write_n (tu_fifo_t* f, const void * data, uint16_t count)
|
||||
{
|
||||
if ( count == 0 ) return 0;
|
||||
|
||||
uint8_t const* p_buf = (uint8_t const*) p_data;
|
||||
tu_fifo_lock(f);
|
||||
|
||||
// Not overwritable limit up to full
|
||||
if (!f->overwritable) count = tu_min16(count, tu_fifo_remaining(f));
|
||||
|
||||
uint8_t const* buf8 = (uint8_t const*) data;
|
||||
uint16_t len = 0;
|
||||
while( (len < count) && tu_fifo_write(f, p_buf) )
|
||||
|
||||
while (len < count)
|
||||
{
|
||||
_tu_ff_push(f, buf8);
|
||||
|
||||
len++;
|
||||
p_buf += f->item_size;
|
||||
buf8 += f->item_size;
|
||||
}
|
||||
|
||||
tu_fifo_unlock(f);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
@ -100,25 +100,28 @@ void dcd_set_config (uint8_t rhport, uint8_t config_num);
|
||||
// Wake up host
|
||||
void dcd_remote_wakeup(uint8_t rhport);
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Endpoint API
|
||||
* - open : Configure endpoint's registers
|
||||
* - xfer : Submit a transfer. When complete dcd_event_xfer_complete
|
||||
* must be called to notify the stack
|
||||
* - busy : Check if endpoint transferring is complete (TODO remove)
|
||||
* - stall : stall endpoint
|
||||
* - clear_stall : clear stall, data toggle is also reset to DATA0
|
||||
*------------------------------------------------------------------*/
|
||||
//--------------------------------------------------------------------+
|
||||
// Endpoint API
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// Configure endpoint's registers according to descriptor
|
||||
bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc);
|
||||
|
||||
// Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack
|
||||
bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes);
|
||||
|
||||
// Check if endpoint transferring is complete (TODO remove)
|
||||
bool dcd_edpt_busy (uint8_t rhport, uint8_t ep_addr);
|
||||
|
||||
// Stall endpoint
|
||||
void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr);
|
||||
|
||||
// clear stall, data toggle is also reset to DATA0
|
||||
void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr);
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Event Function
|
||||
* Called by DCD to notify USBD
|
||||
* Called by DCD to notify device stack
|
||||
*------------------------------------------------------------------*/
|
||||
void dcd_event_handler(dcd_event_t const * event, bool in_isr);
|
||||
|
||||
|
@ -51,8 +51,8 @@ typedef struct {
|
||||
uint8_t self_powered : 1; // configuration descriptor's attribute
|
||||
};
|
||||
|
||||
// uint8_t ep_busy_mask[2]; // bit mask for busy endpoint
|
||||
uint8_t ep_stall_mask[2]; // bit mask for stalled endpoint
|
||||
uint8_t ep_busy_map[2]; // bit mask for busy endpoint
|
||||
uint8_t ep_stall_map[2]; // bit map for stalled endpoint
|
||||
|
||||
uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid)
|
||||
uint8_t ep2drv[8][2]; // map endpoint to driver ( 0xff is invalid )
|
||||
@ -287,6 +287,10 @@ void tud_task (void)
|
||||
{
|
||||
// Invoke the class callback associated with the endpoint address
|
||||
uint8_t const ep_addr = event.xfer_complete.ep_addr;
|
||||
uint8_t const epnum = tu_edpt_number(ep_addr);
|
||||
uint8_t const dir = tu_edpt_dir(ep_addr);
|
||||
|
||||
_usbd_dev.ep_busy_map[dir] = (uint8_t) tu_bit_clear(_usbd_dev.ep_busy_map[dir], epnum);
|
||||
|
||||
if ( 0 == tu_edpt_number(ep_addr) )
|
||||
{
|
||||
@ -621,7 +625,7 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr)
|
||||
|
||||
case DCD_EVENT_SUSPEND:
|
||||
// NOTE: When plugging/unplugging device, the D+/D- state are unstable and can accidentally meet the
|
||||
// SUSPEND condition ( Idle for 3ms ). Some MCUs such as samd don't distinguish suspend vs disconnect as well.
|
||||
// SUSPEND condition ( Idle for 3ms ). Some MCUs such as SAMD doesn't distinguish suspend vs disconnect as well.
|
||||
// We will skip handling SUSPEND/RESUME event if not currently connected
|
||||
if ( _usbd_dev.connected )
|
||||
{
|
||||
@ -643,7 +647,8 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr)
|
||||
break;
|
||||
|
||||
case DCD_EVENT_XFER_COMPLETE:
|
||||
// skip zero-length control status complete event, should dcd notifies us.
|
||||
// skip zero-length control status complete event, should DCD notify us.
|
||||
// TODO could cause issue with actual zero length data used by class such as DFU
|
||||
if ( (0 == tu_edpt_number(event->xfer_complete.ep_addr)) && (event->xfer_complete.len == 0) ) break;
|
||||
|
||||
osal_queue_send(_usbd_q, event, in_isr);
|
||||
@ -733,13 +738,37 @@ void usbd_defer_func(osal_task_func_t func, void* param, bool in_isr)
|
||||
//--------------------------------------------------------------------+
|
||||
// USBD Endpoint API
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
|
||||
{
|
||||
uint8_t const epnum = tu_edpt_number(ep_addr);
|
||||
uint8_t const dir = tu_edpt_dir(ep_addr);
|
||||
|
||||
TU_VERIFY( dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes) );
|
||||
|
||||
_usbd_dev.ep_busy_map[dir] = (uint8_t) tu_bit_set(_usbd_dev.ep_busy_map[dir], epnum);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr)
|
||||
{
|
||||
(void) rhport;
|
||||
|
||||
uint8_t const epnum = tu_edpt_number(ep_addr);
|
||||
uint8_t const dir = tu_edpt_dir(ep_addr);
|
||||
|
||||
return tu_bit_test(_usbd_dev.ep_busy_map[dir], epnum);
|
||||
}
|
||||
|
||||
|
||||
void usbd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
|
||||
{
|
||||
uint8_t const epnum = tu_edpt_number(ep_addr);
|
||||
uint8_t const dir = tu_edpt_dir(ep_addr);
|
||||
|
||||
dcd_edpt_stall(rhport, ep_addr);
|
||||
_usbd_dev.ep_stall_mask[dir] = (uint8_t) tu_bit_set(_usbd_dev.ep_stall_mask[dir], epnum);
|
||||
_usbd_dev.ep_stall_map[dir] = (uint8_t) tu_bit_set(_usbd_dev.ep_stall_map[dir], epnum);
|
||||
}
|
||||
|
||||
void usbd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
|
||||
@ -748,7 +777,7 @@ void usbd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
|
||||
uint8_t const dir = tu_edpt_dir(ep_addr);
|
||||
|
||||
dcd_edpt_clear_stall(rhport, ep_addr);
|
||||
_usbd_dev.ep_stall_mask[dir] = (uint8_t) tu_bit_clear(_usbd_dev.ep_stall_mask[dir], epnum);
|
||||
_usbd_dev.ep_stall_map[dir] = (uint8_t) tu_bit_clear(_usbd_dev.ep_stall_map[dir], epnum);
|
||||
}
|
||||
|
||||
bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr)
|
||||
@ -758,7 +787,7 @@ bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr)
|
||||
uint8_t const epnum = tu_edpt_number(ep_addr);
|
||||
uint8_t const dir = tu_edpt_dir(ep_addr);
|
||||
|
||||
return tu_bit_test(_usbd_dev.ep_stall_mask[dir], epnum);
|
||||
return tu_bit_test(_usbd_dev.ep_stall_map[dir], epnum);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -33,11 +33,12 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// INTERNAL API for stack management
|
||||
//--------------------------------------------------------------------+
|
||||
bool usbd_init (void);
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// USBD Endpoint API
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// Carry out Data and Status stage of control transfer
|
||||
// - If len = 0, it is equivalent to sending status only
|
||||
// - If len > wLength : it will be truncated
|
||||
@ -46,6 +47,12 @@ bool usbd_control_xfer(uint8_t rhport, tusb_control_request_t const * request, v
|
||||
// Send STATUS (zero length) packet
|
||||
bool usbd_control_status(uint8_t rhport, tusb_control_request_t const * request);
|
||||
|
||||
// Submit a usb transfer
|
||||
bool usbd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes);
|
||||
|
||||
// Check if endpoint transferring is complete
|
||||
bool usbd_edpt_busy (uint8_t rhport, uint8_t ep_addr);
|
||||
|
||||
void usbd_edpt_stall(uint8_t rhport, uint8_t ep_addr);
|
||||
void usbd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr);
|
||||
bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr);
|
||||
|
Loading…
x
Reference in New Issue
Block a user