Refactor packet handling

This commit is contained in:
kkitayam 2021-09-25 16:59:17 +09:00
parent a978828c3a
commit d88cc23ca5
3 changed files with 90 additions and 95 deletions

View File

@ -141,10 +141,10 @@ void video_task(void)
} }
} }
int tud_video_frame_xfer_complete_cb(void) int tud_video_frame_xfer_complete_cb(unsigned itf)
{ {
/* prepare tx */ /* prepare tx */
tud_video_n_frame_xfer(0, 0, (void*)frames[current_frame], 128 * 96 * 12/8); tud_video_n_frame_xfer(itf, 0, (void*)frames[current_frame], 128 * 96 * 12/8);
++current_frame; ++current_frame;
if (current_frame == sizeof(frames)/sizeof(frames[0])) if (current_frame == sizeof(frames)/sizeof(frames[0]))
current_frame = 0; current_frame = 0;

View File

@ -191,7 +191,7 @@ static void const* _find_desc(void const *beg, void const *end, uint8_t target)
static void const* _next_desc_itf(void const *beg, void const *end) static void const* _next_desc_itf(void const *beg, void const *end)
{ {
void const *cur = beg; void const *cur = beg;
unsigned itfnum = ((tusb_desc_interface_t const*)cur)->bInterfaceNumber; uint_fast8_t itfnum = ((tusb_desc_interface_t const*)cur)->bInterfaceNumber;
while ((cur < end) && while ((cur < end) &&
(itfnum == ((tusb_desc_interface_t const*)cur)->bInterfaceNumber)) { (itfnum == ((tusb_desc_interface_t const*)cur)->bInterfaceNumber)) {
cur = _find_desc(tu_desc_next(cur), end, TUSB_DESC_INTERFACE); cur = _find_desc(tu_desc_next(cur), end, TUSB_DESC_INTERFACE);
@ -208,7 +208,7 @@ static void const* _next_desc_itf(void const *beg, void const *end)
* *
* @return The pointer for interface descriptor. * @return The pointer for interface descriptor.
* @retval end did not found interface descriptor */ * @retval end did not found interface descriptor */
static void const* _find_desc_itf(void const *beg, void const *end, unsigned itfnum, unsigned altnum) static void const* _find_desc_itf(void const *beg, void const *end, uint_fast8_t itfnum, uint_fast8_t altnum)
{ {
for (void const *cur = beg; cur < end; cur = _find_desc(cur, end, TUSB_DESC_INTERFACE)) { for (void const *cur = beg; cur < end; cur = _find_desc(cur, end, TUSB_DESC_INTERFACE)) {
tusb_desc_interface_t const *itf = (tusb_desc_interface_t const *)cur; tusb_desc_interface_t const *itf = (tusb_desc_interface_t const *)cur;
@ -244,7 +244,7 @@ static void const* _find_desc_ep(void const *beg, void const *end)
* *
* @return The pointer for interface descriptor. * @return The pointer for interface descriptor.
* @retval end did not found interface descriptor */ * @retval end did not found interface descriptor */
static void const* _find_desc_entity(tusb_desc_vc_itf_t const *vc, unsigned entityid) static void const* _find_desc_entity(tusb_desc_vc_itf_t const *vc, uint_fast8_t entityid)
{ {
void const *beg = (void const*)vc; void const *beg = (void const*)vc;
void const *end = beg + vc->std.bLength + vc->ctl.wTotalLength; void const *end = beg + vc->std.bLength + vc->ctl.wTotalLength;
@ -286,7 +286,7 @@ static bool _close_vc_itf(uint8_t rhport, videod_interface_t *self)
* *
* @param[in,out] self The context. * @param[in,out] self The context.
* @param[in] altnum The target alternate setting number. */ * @param[in] altnum The target alternate setting number. */
static bool _open_vc_itf(uint8_t rhport, videod_interface_t *self, unsigned altnum) static bool _open_vc_itf(uint8_t rhport, videod_interface_t *self, uint_fast8_t altnum)
{ {
TU_LOG2(" open VC %d\r\n", altnum); TU_LOG2(" open VC %d\r\n", altnum);
void const *beg = self->beg; void const *beg = self->beg;
@ -325,17 +325,17 @@ static bool _open_vc_itf(uint8_t rhport, videod_interface_t *self, unsigned altn
* *
* @param[in,out] self The context. * @param[in,out] self The context.
* @param[in] altnum The target alternate setting number. */ * @param[in] altnum The target alternate setting number. */
static bool _open_vs_itf(uint8_t rhport, videod_streaming_interface_t *stm, unsigned altnum) static bool _open_vs_itf(uint8_t rhport, videod_streaming_interface_t *stm, uint_fast8_t altnum)
{ {
unsigned i; uint_fast8_t i;
TU_LOG1(" reopen VS %d\r\n", altnum); TU_LOG1(" reopen VS %d\r\n", altnum);
void const *desc = _videod_itf[stm->index_vc].beg; void const *desc = _videod_itf[stm->index_vc].beg;
/* Close endpoints of previous settings. */ /* Close endpoints of previous settings. */
for (i = 0; i < TU_ARRAY_SIZE(stm->desc.ep); ++i) { for (i = 0; i < TU_ARRAY_SIZE(stm->desc.ep); ++i) {
unsigned ofs_ep = stm->desc.ep[i]; uint_fast16_t ofs_ep = stm->desc.ep[i];
if (!ofs_ep) break; if (!ofs_ep) break;
unsigned ep_adr = _desc_ep_addr(desc + ofs_ep); uint_fast8_t ep_adr = _desc_ep_addr(desc + ofs_ep);
usbd_edpt_close(rhport, ep_adr); usbd_edpt_close(rhport, ep_adr);
stm->desc.ep[i] = 0; stm->desc.ep[i] = 0;
TU_LOG1(" close EP%02x\n", ep_adr); TU_LOG1(" close EP%02x\n", ep_adr);
@ -346,7 +346,7 @@ static bool _open_vs_itf(uint8_t rhport, videod_streaming_interface_t *stm, unsi
void const *end = desc + stm->desc.end; void const *end = desc + stm->desc.end;
void const *cur = _find_desc_itf(beg, end, _desc_itfnum(beg), altnum); void const *cur = _find_desc_itf(beg, end, _desc_itfnum(beg), altnum);
TU_VERIFY(cur < end); TU_VERIFY(cur < end);
unsigned numeps = ((tusb_desc_interface_t const *)cur)->bNumEndpoints; uint_fast8_t numeps = ((tusb_desc_interface_t const *)cur)->bNumEndpoints;
TU_ASSERT(numeps <= TU_ARRAY_SIZE(stm->desc.ep)); TU_ASSERT(numeps <= TU_ARRAY_SIZE(stm->desc.ep));
stm->desc.cur = cur - desc; /* Save the offset of the new settings */ stm->desc.cur = cur - desc; /* Save the offset of the new settings */
/* Open endpoints of the new settings. */ /* Open endpoints of the new settings. */
@ -366,30 +366,15 @@ static bool _open_vs_itf(uint8_t rhport, videod_streaming_interface_t *stm, unsi
return true; return true;
} }
static int _payload_xfer_in(uint8_t rhport, uint8_t itf) static uint_fast16_t _prepair_in_payload(videod_streaming_interface_t *stm)
{ {
videod_streaming_interface_t *stm = &_videod_streaming_itf[itf]; uint_fast16_t remaining = stm->bufsize - stm->offset;
void const *desc = _videod_itf[stm->index_vc].beg; uint_fast16_t hdr_len = stm->ep_buf[0];
unsigned ep_addr = 0; uint_fast16_t pkt_len = stm->max_payload_transfer_size;
for (unsigned i = 0; i < CFG_TUD_VIDEO_STREAMING; ++i) {
unsigned ofs_ep = stm->desc.ep[i];
if (!ofs_ep) continue;
ep_addr = _desc_ep_addr(desc + ofs_ep);
if (tu_edpt_dir(ep_addr))
break;
}
TU_ASSERT(ep_addr, 0);
/* Claim the endpoint */
TU_VERIFY( usbd_edpt_claim(rhport, ep_addr), 0);
/* prepare a payload */
uint32_t remaining = stm->bufsize - stm->offset;
unsigned hdr_len = stm->ep_buf[0];
unsigned pkt_len = stm->max_payload_transfer_size;
if (hdr_len + remaining < pkt_len) { if (hdr_len + remaining < pkt_len) {
pkt_len = hdr_len + remaining; pkt_len = hdr_len + remaining;
} }
uint32_t data_len = pkt_len - hdr_len; uint_fast16_t data_len = pkt_len - hdr_len;
memcpy(&stm->ep_buf[hdr_len], stm->buffer + stm->offset, data_len); memcpy(&stm->ep_buf[hdr_len], stm->buffer + stm->offset, data_len);
stm->offset += data_len; stm->offset += data_len;
remaining -= data_len; remaining -= data_len;
@ -397,13 +382,11 @@ static int _payload_xfer_in(uint8_t rhport, uint8_t itf)
tusb_video_payload_header_t *hdr = (tusb_video_payload_header_t*)stm->ep_buf; tusb_video_payload_header_t *hdr = (tusb_video_payload_header_t*)stm->ep_buf;
hdr->EndOfFrame = 1; hdr->EndOfFrame = 1;
} }
TU_LOG2(" %d\n", data_len, remaining); return hdr_len + data_len;
TU_ASSERT( usbd_edpt_xfer(rhport, ep_addr, stm->ep_buf, hdr_len + data_len), 0 );
return data_len;
} }
/** Handle a standard request to the video control interface. */ /** Handle a standard request to the video control interface. */
static int handle_video_ctl_std_req(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request, unsigned itf) static int handle_video_ctl_std_req(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request, uint_fast8_t itf)
{ {
switch (request->bRequest) { switch (request->bRequest) {
case TUSB_REQ_GET_INTERFACE: case TUSB_REQ_GET_INTERFACE:
@ -431,7 +414,7 @@ static int handle_video_ctl_std_req(uint8_t rhport, uint8_t stage, tusb_control_
} }
} }
static int handle_video_ctl_cs_req(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request, unsigned itf) static int handle_video_ctl_cs_req(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request, uint_fast8_t itf)
{ {
videod_interface_t *self = &_videod_itf[itf]; videod_interface_t *self = &_videod_itf[itf];
/* 4.2.1 Interface Control Request */ /* 4.2.1 Interface Control Request */
@ -491,9 +474,9 @@ static int handle_video_ctl_cs_req(uint8_t rhport, uint8_t stage, tusb_control_r
return VIDEO_INVALID_REQUEST; return VIDEO_INVALID_REQUEST;
} }
static int handle_video_ctl_req(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request, unsigned itf) static int handle_video_ctl_req(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request, uint_fast8_t itf)
{ {
unsigned entity_id; uint_fast8_t entity_id;
switch (request->bmRequestType_bit.type) { switch (request->bmRequestType_bit.type) {
case TUSB_REQ_TYPE_STANDARD: case TUSB_REQ_TYPE_STANDARD:
return handle_video_ctl_std_req(rhport, stage, request, itf); return handle_video_ctl_std_req(rhport, stage, request, itf);
@ -511,7 +494,7 @@ static int handle_video_ctl_req(uint8_t rhport, uint8_t stage, tusb_control_requ
} }
} }
static int handle_video_stm_std_req(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request, unsigned itf) static int handle_video_stm_std_req(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request, uint_fast8_t itf)
{ {
videod_streaming_interface_t *self = &_videod_streaming_itf[itf]; videod_streaming_interface_t *self = &_videod_streaming_itf[itf];
switch (request->bRequest) { switch (request->bRequest) {
@ -537,7 +520,7 @@ static int handle_video_stm_std_req(uint8_t rhport, uint8_t stage, tusb_control_
} }
} }
static int handle_video_stm_cs_req(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request, unsigned itf) static int handle_video_stm_cs_req(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request, uint_fast8_t itf)
{ {
(void)rhport; (void)rhport;
videod_streaming_interface_t *self = &_videod_streaming_itf[itf]; videod_streaming_interface_t *self = &_videod_streaming_itf[itf];
@ -652,7 +635,7 @@ static int handle_video_stm_cs_req(uint8_t rhport, uint8_t stage, tusb_control_r
return VIDEO_INVALID_REQUEST; return VIDEO_INVALID_REQUEST;
} }
static int handle_video_stm_req(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request, unsigned itf) static int handle_video_stm_req(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request, uint_fast8_t itf)
{ {
switch (request->bmRequestType_bit.type) { switch (request->bmRequestType_bit.type) {
case TUSB_REQ_TYPE_STANDARD: case TUSB_REQ_TYPE_STANDARD:
@ -670,6 +653,15 @@ static int handle_video_stm_req(uint8_t rhport, uint8_t stage, tusb_control_requ
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// APPLICATION API // APPLICATION API
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
/* itf control interface number */
bool tud_video_n_connected(uint8_t itf)
{
(void)itf;
// DTR (bit 0) active is considered as connected
return tud_ready();
}
/* itf streaming interface number */ /* itf streaming interface number */
bool tud_video_n_streaming(uint8_t itf) bool tud_video_n_streaming(uint8_t itf)
{ {
@ -679,41 +671,43 @@ bool tud_video_n_streaming(uint8_t itf)
return false; return false;
} }
bool tud_video_n_connected(uint8_t itf) bool tud_video_n_frame_xfer(uint8_t itf, uint32_t pts, void *buffer, size_t bufsize)
{
(void)itf;
// DTR (bit 0) active is considered as connected
return tud_ready();
}
int tud_video_n_frame_xfer(uint8_t itf, uint32_t pts, void *buffer, size_t bufsize)
{ {
(void)pts; (void)pts;
if (!buffer || !buffer)
return false;
if (!tud_video_n_streaming(itf)) if (!tud_video_n_streaming(itf))
return false; return false;
/* update the packet header */
videod_streaming_interface_t *stm = &_videod_streaming_itf[itf]; videod_streaming_interface_t *stm = &_videod_streaming_itf[itf];
if (stm->buffer)
return false;
/* find EP address */
void const *desc = _videod_itf[stm->index_vc].beg;
uint_fast8_t ep_addr = 0;
for (uint_fast8_t i = 0; i < CFG_TUD_VIDEO_STREAMING; ++i) {
uint_fast16_t ofs_ep = stm->desc.ep[i];
if (!ofs_ep) continue;
ep_addr = _desc_ep_addr(desc + ofs_ep);
break;
}
if (!ep_addr)
return false;
TU_VERIFY( usbd_edpt_claim(0, ep_addr));
/* update the packet header */
tusb_video_payload_header_t *hdr = (tusb_video_payload_header_t*)stm->ep_buf; tusb_video_payload_header_t *hdr = (tusb_video_payload_header_t*)stm->ep_buf;
hdr->FrameID ^= 1; hdr->FrameID ^= 1;
hdr->EndOfFrame = 0; hdr->EndOfFrame = 0;
/* update the packet data */
stm->buffer = (uint8_t*)buffer; stm->buffer = (uint8_t*)buffer;
stm->bufsize = bufsize; stm->bufsize = bufsize;
TU_LOG1(" xfer %d\n", bufsize); uint_fast16_t pkt_len = _prepair_in_payload(stm);
_payload_xfer_in(0, itf); TU_ASSERT( usbd_edpt_xfer(0, ep_addr, stm->ep_buf, pkt_len), 0);
return 0; return true;
} }
//--------------------------------------------------------------------+
// READ API
//--------------------------------------------------------------------+
//--------------------------------------------------------------------+
// WRITE API
//--------------------------------------------------------------------+
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// USBD Driver API // USBD Driver API
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
@ -750,7 +744,7 @@ uint16_t videod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin
/* Find available interface */ /* Find available interface */
videod_interface_t *self = NULL; videod_interface_t *self = NULL;
unsigned itf; uint_fast8_t itf;
for (itf = 0; itf < CFG_TUD_VIDEO; ++itf) { for (itf = 0; itf < CFG_TUD_VIDEO; ++itf) {
if (_videod_itf[itf].beg) if (_videod_itf[itf].beg)
continue; continue;
@ -766,13 +760,13 @@ uint16_t videod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin
if (!_open_vc_itf(rhport, self, 0)) if (!_open_vc_itf(rhport, self, 0))
return 0; return 0;
tusb_desc_vc_itf_t const *vc = _get_desc_vc(self); tusb_desc_vc_itf_t const *vc = _get_desc_vc(self);
unsigned bInCollection = vc->ctl.bInCollection; uint_fast8_t bInCollection = vc->ctl.bInCollection;
/* Find the end of the video interface descriptor */ /* Find the end of the video interface descriptor */
void const *cur = _next_desc_itf(itf_desc, end); void const *cur = _next_desc_itf(itf_desc, end);
for (unsigned i = 0; i < bInCollection; ++i) { for (uint_fast8_t i = 0; i < bInCollection; ++i) {
videod_streaming_interface_t *stm = NULL; videod_streaming_interface_t *stm = NULL;
/* find free streaming interface handle */ /* find free streaming interface handle */
for (unsigned j = 0; j < TU_ARRAY_SIZE(_videod_streaming_itf); ++j) { for (uint_fast8_t j = 0; j < TU_ARRAY_SIZE(_videod_streaming_itf); ++j) {
if (_videod_streaming_itf[i].desc.beg) if (_videod_streaming_itf[i].desc.beg)
continue; continue;
stm = &_videod_streaming_itf[i]; stm = &_videod_streaming_itf[i];
@ -798,19 +792,17 @@ bool videod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_
if (request->bmRequestType_bit.recipient != TUSB_REQ_RCPT_INTERFACE) { if (request->bmRequestType_bit.recipient != TUSB_REQ_RCPT_INTERFACE) {
return false; return false;
} }
unsigned itfnum = tu_u16_low(request->wIndex); uint_fast8_t itfnum = tu_u16_low(request->wIndex);
/* Identify which control interface to use */ /* Identify which control interface to use */
int itf = -1; uint_fast8_t itf;
for (unsigned i = 0; i < CFG_TUD_VIDEO; ++i) { for (itf = 0; itf < CFG_TUD_VIDEO; ++itf) {
void const *desc = _videod_itf[i].beg; void const *desc = _videod_itf[itf].beg;
if (!desc) break; if (!desc) continue;
if (itfnum == _desc_itfnum(desc)) { if (itfnum == _desc_itfnum(desc))
itf = i;
break; break;
}
} }
if (itf >= 0) { if (itf < CFG_TUD_VIDEO) {
err = handle_video_ctl_req(rhport, stage, request, itf); err = handle_video_ctl_req(rhport, stage, request, itf);
_videod_itf[itf].error_code = (uint8_t)err; _videod_itf[itf].error_code = (uint8_t)err;
if (err) return false; if (err) return false;
@ -818,16 +810,14 @@ bool videod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_
} }
/* Identify which streaming interface to use */ /* Identify which streaming interface to use */
for (unsigned i = 0; i < CFG_TUD_VIDEO_STREAMING; ++i) { for (itf = 0; itf < CFG_TUD_VIDEO_STREAMING; ++itf) {
videod_streaming_interface_t *stm = &_videod_streaming_itf[i]; videod_streaming_interface_t *stm = &_videod_streaming_itf[itf];
if (!stm->desc.beg) return false; if (!stm->desc.beg) continue;
void const *desc = _videod_itf[stm->index_vc].beg; void const *desc = _videod_itf[stm->index_vc].beg;
if (itfnum == _desc_itfnum(desc + stm->desc.beg)) { if (itfnum == _desc_itfnum(desc + stm->desc.beg))
itf = i;
break; break;
}
} }
if (itf >= 0) { if (itf < CFG_TUD_VIDEO_STREAMING) {
err = handle_video_stm_req(rhport, stage, request, itf); err = handle_video_stm_req(rhport, stage, request, itf);
_videod_streaming_itf[itf].error_code = (uint8_t)err; _videod_streaming_itf[itf].error_code = (uint8_t)err;
if (err) return false; if (err) return false;
@ -838,28 +828,31 @@ bool videod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_
bool videod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) bool videod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes)
{ {
(void)rhport; (void)result; (void)xferred_bytes; (void)result; (void)xferred_bytes;
/* find streaming handle */ /* find streaming handle */
unsigned i; uint_fast8_t itf;
videod_streaming_interface_t *stm; videod_streaming_interface_t *stm;
for (i = 0; i < CFG_TUD_VIDEO_STREAMING; ++i) { for (itf = 0; itf < CFG_TUD_VIDEO_STREAMING; ++itf) {
stm = &_videod_streaming_itf[i]; stm = &_videod_streaming_itf[itf];
unsigned const ep_ofs = stm->desc.ep[0]; uint_fast16_t const ep_ofs = stm->desc.ep[0];
if (!ep_ofs) continue; if (!ep_ofs) continue;
void const *desc = _videod_itf[stm->index_vc].beg; void const *desc = _videod_itf[stm->index_vc].beg;
if (ep_addr == _desc_ep_addr(desc + ep_ofs)) if (ep_addr == _desc_ep_addr(desc + ep_ofs))
break; break;
} }
TU_ASSERT(i < CFG_TUD_VIDEO_STREAMING); TU_ASSERT(itf < CFG_TUD_VIDEO_STREAMING);
if (stm->offset < stm->bufsize) { if (stm->offset < stm->bufsize) {
_payload_xfer_in(rhport, i); /* Claim the endpoint */
TU_VERIFY( usbd_edpt_claim(rhport, ep_addr), 0);
uint_fast16_t pkt_len = _prepair_in_payload(stm);
TU_ASSERT( usbd_edpt_xfer(rhport, ep_addr, stm->ep_buf, pkt_len), 0);
} else { } else {
stm->buffer = NULL; stm->buffer = NULL;
stm->bufsize = 0; stm->bufsize = 0;
stm->offset = 0; stm->offset = 0;
if (tud_video_frame_xfer_complete_cb) if (tud_video_frame_xfer_complete_cb)
tud_video_frame_xfer_complete_cb(); tud_video_frame_xfer_complete_cb(itf);
} }
return true; return true;
} }

View File

@ -42,10 +42,12 @@ extern "C" {
bool tud_video_n_streaming(uint8_t itf); bool tud_video_n_streaming(uint8_t itf);
int tud_video_n_frame_xfer(uint8_t itf, uint32_t pts, void *buffer, size_t bufsize); /* itf instance number of streaming interface */
bool tud_video_n_frame_xfer(uint8_t itf, uint32_t pts, void *buffer, size_t bufsize);
/*------------- Optional callbacks -------------*/ /*------------- Optional callbacks -------------*/
TU_ATTR_WEAK int tud_video_frame_xfer_complete_cb(void); /* itf instance number of streaming interface */
TU_ATTR_WEAK int tud_video_frame_xfer_complete_cb(unsigned itf);
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// Application Callback API (weak is optional) // Application Callback API (weak is optional)