summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/device/video_capture/src/main.c4
-rw-r--r--src/class/video/video_device.c173
-rw-r--r--src/class/video/video_device.h6
3 files changed, 89 insertions, 94 deletions
diff --git a/examples/device/video_capture/src/main.c b/examples/device/video_capture/src/main.c
index ce4272639..4ca0e5d90 100644
--- a/examples/device/video_capture/src/main.c
+++ b/examples/device/video_capture/src/main.c
@@ -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 */
- 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;
if (current_frame == sizeof(frames)/sizeof(frames[0]))
current_frame = 0;
diff --git a/src/class/video/video_device.c b/src/class/video/video_device.c
index acec7a992..344c4e0f9 100644
--- a/src/class/video/video_device.c
+++ b/src/class/video/video_device.c
@@ -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)
{
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) &&
(itfnum == ((tusb_desc_interface_t const*)cur)->bInterfaceNumber)) {
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.
* @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)) {
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.
* @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 *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] 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);
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] 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);
void const *desc = _videod_itf[stm->index_vc].beg;
/* Close endpoints of previous settings. */
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;
- 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);
stm->desc.ep[i] = 0;
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 *cur = _find_desc_itf(beg, end, _desc_itfnum(beg), altnum);
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));
stm->desc.cur = cur - desc; /* Save the offset 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;
}
-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];
- void const *desc = _videod_itf[stm->index_vc].beg;
- unsigned ep_addr = 0;
- 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;
+ uint_fast16_t remaining = stm->bufsize - stm->offset;
+ uint_fast16_t hdr_len = stm->ep_buf[0];
+ uint_fast16_t pkt_len = stm->max_payload_transfer_size;
if (hdr_len + remaining < pkt_len) {
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);
stm->offset += 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;
hdr->EndOfFrame = 1;
}
- TU_LOG2(" %d\n", data_len, remaining);
- TU_ASSERT( usbd_edpt_xfer(rhport, ep_addr, stm->ep_buf, hdr_len + data_len), 0 );
- return data_len;
+ return hdr_len + data_len;
}
/** 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) {
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];
/* 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;
}
-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) {
case TUSB_REQ_TYPE_STANDARD:
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];
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;
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;
}
-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) {
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
//--------------------------------------------------------------------+
+
+/* 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 */
bool tud_video_n_streaming(uint8_t itf)
{
@@ -679,42 +671,44 @@ bool tud_video_n_streaming(uint8_t itf)
return false;
}
-bool tud_video_n_connected(uint8_t itf)
-{
- (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)
+bool tud_video_n_frame_xfer(uint8_t itf, uint32_t pts, void *buffer, size_t bufsize)
{
(void)pts;
+ if (!buffer || !buffer)
+ return false;
if (!tud_video_n_streaming(itf))
return false;
+ 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 */
- videod_streaming_interface_t *stm = &_videod_streaming_itf[itf];
tusb_video_payload_header_t *hdr = (tusb_video_payload_header_t*)stm->ep_buf;
hdr->FrameID ^= 1;
hdr->EndOfFrame = 0;
-
- stm->buffer = (uint8_t*)buffer;
- stm->bufsize = bufsize;
- TU_LOG1(" xfer %d\n", bufsize);
- _payload_xfer_in(0, itf);
- return 0;
+ /* update the packet data */
+ stm->buffer = (uint8_t*)buffer;
+ stm->bufsize = bufsize;
+ uint_fast16_t pkt_len = _prepair_in_payload(stm);
+ TU_ASSERT( usbd_edpt_xfer(0, ep_addr, stm->ep_buf, pkt_len), 0);
+ return true;
}
//--------------------------------------------------------------------+
-// READ API
-//--------------------------------------------------------------------+
-
-//--------------------------------------------------------------------+
-// WRITE API
-//--------------------------------------------------------------------+
-
-//--------------------------------------------------------------------+
// USBD Driver API
//--------------------------------------------------------------------+
void videod_init(void)
@@ -750,7 +744,7 @@ uint16_t videod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin
/* Find available interface */
videod_interface_t *self = NULL;
- unsigned itf;
+ uint_fast8_t itf;
for (itf = 0; itf < CFG_TUD_VIDEO; ++itf) {
if (_videod_itf[itf].beg)
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))
return 0;
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 */
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;
/* 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)
continue;
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) {
return false;
}
- unsigned itfnum = tu_u16_low(request->wIndex);
+ uint_fast8_t itfnum = tu_u16_low(request->wIndex);
/* Identify which control interface to use */
- int itf = -1;
- for (unsigned i = 0; i < CFG_TUD_VIDEO; ++i) {
- void const *desc = _videod_itf[i].beg;
- if (!desc) break;
- if (itfnum == _desc_itfnum(desc)) {
- itf = i;
+ uint_fast8_t itf;
+ for (itf = 0; itf < CFG_TUD_VIDEO; ++itf) {
+ void const *desc = _videod_itf[itf].beg;
+ if (!desc) continue;
+ if (itfnum == _desc_itfnum(desc))
break;
- }
}
- if (itf >= 0) {
+ if (itf < CFG_TUD_VIDEO) {
err = handle_video_ctl_req(rhport, stage, request, itf);
_videod_itf[itf].error_code = (uint8_t)err;
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 */
- for (unsigned i = 0; i < CFG_TUD_VIDEO_STREAMING; ++i) {
- videod_streaming_interface_t *stm = &_videod_streaming_itf[i];
- if (!stm->desc.beg) return false;
+ for (itf = 0; itf < CFG_TUD_VIDEO_STREAMING; ++itf) {
+ videod_streaming_interface_t *stm = &_videod_streaming_itf[itf];
+ if (!stm->desc.beg) continue;
void const *desc = _videod_itf[stm->index_vc].beg;
- if (itfnum == _desc_itfnum(desc + stm->desc.beg)) {
- itf = i;
+ if (itfnum == _desc_itfnum(desc + stm->desc.beg))
break;
- }
}
- if (itf >= 0) {
+ if (itf < CFG_TUD_VIDEO_STREAMING) {
err = handle_video_stm_req(rhport, stage, request, itf);
_videod_streaming_itf[itf].error_code = (uint8_t)err;
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)
{
- (void)rhport; (void)result; (void)xferred_bytes;
+ (void)result; (void)xferred_bytes;
/* find streaming handle */
- unsigned i;
+ uint_fast8_t itf;
videod_streaming_interface_t *stm;
- for (i = 0; i < CFG_TUD_VIDEO_STREAMING; ++i) {
- stm = &_videod_streaming_itf[i];
- unsigned const ep_ofs = stm->desc.ep[0];
+ for (itf = 0; itf < CFG_TUD_VIDEO_STREAMING; ++itf) {
+ stm = &_videod_streaming_itf[itf];
+ uint_fast16_t const ep_ofs = stm->desc.ep[0];
if (!ep_ofs) continue;
void const *desc = _videod_itf[stm->index_vc].beg;
if (ep_addr == _desc_ep_addr(desc + ep_ofs))
break;
}
- TU_ASSERT(i < CFG_TUD_VIDEO_STREAMING);
+ TU_ASSERT(itf < CFG_TUD_VIDEO_STREAMING);
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 {
stm->buffer = NULL;
stm->bufsize = 0;
stm->offset = 0;
if (tud_video_frame_xfer_complete_cb)
- tud_video_frame_xfer_complete_cb();
+ tud_video_frame_xfer_complete_cb(itf);
}
return true;
}
diff --git a/src/class/video/video_device.h b/src/class/video/video_device.h
index a1b13b9af..acf4c4d2b 100644
--- a/src/class/video/video_device.h
+++ b/src/class/video/video_device.h
@@ -42,10 +42,12 @@ extern "C" {
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 -------------*/
-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)