Skip to content

Commit 1a68f6d

Browse files
author
Josuah Demangeon
committed
usb: host: uvc: loop through every descriptor
Loop through each of the VideoStreaming and VideoControl descriptor to parse them. Signed-off-by: Josuah Demangeon <[email protected]>
1 parent c872246 commit 1a68f6d

File tree

1 file changed

+274
-18
lines changed

1 file changed

+274
-18
lines changed

subsys/usb/host/class/usbh_uvc.c

Lines changed: 274 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -33,75 +33,331 @@
3333

3434
LOG_MODULE_REGISTER(usbh_uvc, CONFIG_USBH_VIDEO_LOG_LEVEL);
3535

36-
struct usbh_uvc_config {
37-
struct usbh_contex *uhs_ctx;
36+
struct usbh_uvc_data {
37+
int todo;
3838
};
3939

4040
static int usbh_uvc_request(struct usbh_contex *const uhs_ctx, struct uhc_transfer *const xfer,
4141
int err)
4242
{
43-
LOG_INF("%p %p %d", uhs_ctx, xfer, err);
43+
LOG_DBG("%p %p %d", uhs_ctx, xfer, err);
44+
45+
return 0;
46+
}
47+
48+
static int usbh_uvc_parse_control_header(struct usbh_contex *const uhs_ctx,
49+
struct usbh_uvc_data *const uvc,
50+
struct uvc_control_header_descriptor *desc)
51+
{
52+
return 0;
53+
}
54+
55+
static int usbh_uvc_parse_output_terminal(struct usbh_contex *const uhs_ctx,
56+
struct usbh_uvc_data *const uvc,
57+
struct uvc_output_terminal_descriptor *desc)
58+
{
59+
return 0;
60+
}
61+
62+
static int usbh_uvc_parse_input_terminal(struct usbh_contex *const uhs_ctx,
63+
struct usbh_uvc_data *const uvc,
64+
struct uvc_camera_terminal_descriptor *desc)
65+
{
66+
return 0;
67+
}
68+
69+
static int usbh_uvc_parse_selector_unit(struct usbh_contex *const uhs_ctx,
70+
struct usbh_uvc_data *const uvc,
71+
struct uvc_selector_unit_descriptor *desc)
72+
{
73+
return 0;
74+
}
75+
76+
static int usbh_uvc_parse_processing_unit(struct usbh_contex *const uhs_ctx,
77+
struct usbh_uvc_data *const uvc,
78+
struct uvc_processing_unit_descriptor *desc)
79+
{
80+
return 0;
81+
}
82+
83+
static int usbh_uvc_parse_extension_unit(struct usbh_contex *const uhs_ctx,
84+
struct usbh_uvc_data *const uvc,
85+
struct uvc_extension_unit_descriptor *desc)
86+
{
87+
return 0;
88+
}
89+
90+
static int usbh_uvc_parse_encoding_unit(struct usbh_contex *const uhs_ctx,
91+
struct usbh_uvc_data *const uvc,
92+
struct uvc_encoding_unit_descriptor *desc)
93+
{
94+
return 0;
95+
}
96+
97+
static int usbh_uvc_parse_control_desc(struct usbh_contex *const uhs_ctx,
98+
struct usbh_uvc_data *const uvc,
99+
struct usb_if_descriptor *const if_control)
100+
{
101+
struct uvc_if_descriptor *desc = (void *)if_control;
102+
int ret = 0;
103+
104+
while (desc->bLength != 0) {
105+
/* Skip the interface descriptor or switch to the next descriptor */
106+
desc = (void *)((uint8_t *)desc + desc->bLength);
107+
108+
if (desc->bDescriptorType == USB_DESC_INTERFACE ||
109+
desc->bDescriptorType == USB_DESC_INTERFACE_ASSOC ||
110+
desc->bDescriptorType == 0) {
111+
break;
112+
} else if (desc->bDescriptorType == USB_DESC_CS_INTERFACE) {
113+
if (desc->bDescriptorSubtype == UVC_VC_HEADER) {
114+
struct uvc_control_header_descriptor copy;
115+
116+
memcpy(&copy, desc, MIN(sizeof(copy), desc->bLength));
117+
LOG_DBG("VideoControl interface: Header");
118+
ret = usbh_uvc_parse_control_header(uhs_ctx, uvc, &copy);
119+
} else if (desc->bDescriptorSubtype == UVC_VC_OUTPUT_TERMINAL) {
120+
struct uvc_output_terminal_descriptor copy;
121+
122+
memcpy(&copy, desc, MIN(sizeof(copy), desc->bLength));
123+
LOG_DBG("VideoControl interface: Output Terminal");
124+
ret = usbh_uvc_parse_output_terminal(uhs_ctx, uvc, &copy);
125+
} else if (desc->bDescriptorSubtype == UVC_VC_INPUT_TERMINAL) {
126+
struct uvc_camera_terminal_descriptor copy;
127+
128+
memcpy(&copy, desc, MIN(sizeof(copy), desc->bLength));
129+
LOG_DBG("VideoControl interface: Input/Camera Terminal");
130+
ret = usbh_uvc_parse_input_terminal(uhs_ctx, uvc, &copy);
131+
} else if (desc->bDescriptorSubtype == UVC_VC_SELECTOR_UNIT) {
132+
struct uvc_selector_unit_descriptor copy;
133+
134+
memcpy(&copy, desc, MIN(sizeof(copy), desc->bLength));
135+
LOG_DBG("VideoControl interface: Selector Unit");
136+
ret = usbh_uvc_parse_selector_unit(uhs_ctx, uvc, &copy);
137+
} else if (desc->bDescriptorSubtype == UVC_VC_PROCESSING_UNIT) {
138+
struct uvc_processing_unit_descriptor copy;
139+
140+
memcpy(&copy, desc, MIN(sizeof(copy), desc->bLength));
141+
LOG_DBG("VideoControl interface: Processing Unit");
142+
ret = usbh_uvc_parse_processing_unit(uhs_ctx, uvc, &copy);
143+
} else if (desc->bDescriptorSubtype == UVC_VC_EXTENSION_UNIT) {
144+
struct uvc_extension_unit_descriptor copy;
145+
146+
memcpy(&copy, desc, MIN(sizeof(copy), desc->bLength));
147+
LOG_DBG("VideoControl interface: Extension Unit");
148+
ret = usbh_uvc_parse_extension_unit(uhs_ctx, uvc, &copy);
149+
} else if (desc->bDescriptorSubtype == UVC_VC_ENCODING_UNIT) {
150+
struct uvc_encoding_unit_descriptor copy;
151+
152+
memcpy(&copy, desc, MIN(sizeof(copy), desc->bLength));
153+
LOG_DBG("VideoControl interface: Encoding Unit");
154+
ret = usbh_uvc_parse_encoding_unit(uhs_ctx, uvc, &copy);
155+
} else {
156+
LOG_WRN("VideoControl interface: unknown subtype %u, skipping",
157+
desc->bDescriptorSubtype);
158+
}
159+
} else {
160+
LOG_DBG("VideoControl descriptor: unknown type %u, skipping",
161+
desc->bDescriptorType);
162+
}
163+
164+
if (ret != 0) {
165+
LOG_ERR("Error while parsing descriptor type %u");
166+
return ret;
167+
}
168+
}
169+
170+
return 0;
171+
}
172+
173+
static int usbh_uvc_parse_input_header(struct usbh_contex *const uhs_ctx,
174+
struct usbh_uvc_data *const uvc,
175+
struct uvc_stream_header_descriptor *const desc)
176+
{
177+
return 0;
178+
}
179+
180+
static int usbh_uvc_parse_output_header(struct usbh_contex *const uhs_ctx,
181+
struct usbh_uvc_data *const uvc,
182+
struct uvc_stream_header_descriptor *const desc)
183+
{
184+
return 0;
185+
}
186+
187+
static int usbh_uvc_parse_format_uncomp(struct usbh_contex *const uhs_ctx,
188+
struct usbh_uvc_data *const uvc,
189+
struct uvc_format_uncomp_descriptor *const desc)
190+
{
191+
return 0;
192+
}
193+
194+
static int usbh_uvc_parse_format_mjpeg(struct usbh_contex *const uhs_ctx,
195+
struct usbh_uvc_data *const uvc,
196+
struct uvc_format_mjpeg_descriptor *const desc)
197+
{
198+
return 0;
199+
}
200+
201+
static int usbh_uvc_parse_frame(struct usbh_contex *const uhs_ctx,
202+
struct usbh_uvc_data *const uvc,
203+
struct uvc_frame_descriptor *const desc)
204+
{
205+
return 0;
206+
}
207+
208+
static int usbh_uvc_parse_color(struct usbh_contex *const uhs_ctx,
209+
struct usbh_uvc_data *const uvc,
210+
struct uvc_color_descriptor *const desc)
211+
{
212+
return 0;
213+
}
214+
215+
static int usbh_uvc_parse_streaming_desc(struct usbh_contex *const uhs_ctx,
216+
struct usbh_uvc_data *const uvc,
217+
struct usb_if_descriptor *const if_streaming)
218+
{
219+
struct uvc_if_descriptor *desc = (void *)if_streaming;
220+
int ret;
221+
222+
while (desc->bLength != 0) {
223+
/* Skip the interface descriptor or switch to the next descriptor */
224+
desc = (void *)((uint8_t *)desc + desc->bLength);
225+
226+
if (desc->bDescriptorType == USB_DESC_INTERFACE ||
227+
desc->bDescriptorType == USB_DESC_INTERFACE_ASSOC ||
228+
desc->bDescriptorType == 0) {
229+
break;
230+
} else if (desc->bDescriptorType == USB_DESC_CS_INTERFACE) {
231+
if (desc->bDescriptorSubtype == UVC_VS_INPUT_HEADER) {
232+
struct uvc_stream_header_descriptor copy;
233+
234+
memcpy(&copy, desc, MIN(sizeof(copy), desc->bLength));
235+
LOG_DBG("VideoStreaming interface: Input header");
236+
ret = usbh_uvc_parse_input_header(uhs_ctx, uvc, &copy);
237+
} else if (desc->bDescriptorSubtype == UVC_VS_OUTPUT_HEADER) {
238+
struct uvc_stream_header_descriptor copy;
239+
240+
memcpy(&copy, desc, MIN(sizeof(copy), desc->bLength));
241+
LOG_DBG("VideoStreaming interface: Output header");
242+
ret = usbh_uvc_parse_output_header(uhs_ctx, uvc, &copy);
243+
} else if (desc->bDescriptorSubtype == UVC_VS_FORMAT_UNCOMPRESSED) {
244+
struct uvc_format_uncomp_descriptor copy;
245+
246+
memcpy(&copy, desc, MIN(sizeof(copy), desc->bLength));
247+
LOG_DBG("VideoStreaming interface: Uncompressed format");
248+
ret = usbh_uvc_parse_format_uncomp(uhs_ctx, uvc, &copy);
249+
} else if (desc->bDescriptorSubtype == UVC_VS_FORMAT_MJPEG) {
250+
struct uvc_format_mjpeg_descriptor copy;
251+
252+
memcpy(&copy, desc, MIN(sizeof(copy), desc->bLength));
253+
LOG_DBG("VideoStreaming interface: Uncompressed format");
254+
ret = usbh_uvc_parse_format_mjpeg(uhs_ctx, uvc, &copy);
255+
} else if (desc->bDescriptorSubtype == UVC_VS_FRAME_UNCOMPRESSED ||
256+
desc->bDescriptorSubtype == UVC_VS_FRAME_MJPEG) {
257+
struct uvc_frame_descriptor copy;
258+
259+
memcpy(&copy, desc, MIN(sizeof(copy), desc->bLength));
260+
LOG_DBG("VideoStreaming interface: Frame");
261+
ret = usbh_uvc_parse_frame(uhs_ctx, uvc, &copy);
262+
} else if (desc->bDescriptorSubtype == UVC_VS_COLORFORMAT) {
263+
struct uvc_color_descriptor copy;
264+
265+
memcpy(&copy, desc, MIN(sizeof(copy), desc->bLength));
266+
LOG_DBG("VideoStreaming interface: Color");
267+
ret = usbh_uvc_parse_color(uhs_ctx, uvc, &copy);
268+
} else {
269+
LOG_DBG("VideoStreaming descriptor: unknown subtype %u, skipping",
270+
desc->bDescriptorSubtype);
271+
}
272+
} else if (desc->bDescriptorType == USB_DESC_ENDPOINT) {
273+
struct usb_ep_descriptor copy;
274+
275+
memcpy(&copy, desc, MIN(sizeof(copy), desc->bLength));
276+
LOG_DBG("VideoStreaming Endpoint", copy.bEndpointAddress);
277+
} else {
278+
LOG_DBG("VideoStreaming descriptor: unknown type %u, skipping",
279+
desc->bDescriptorType);
280+
}
281+
}
44282

45283
return 0;
46284
}
47285

48286
static int usbh_uvc_connected(struct usbh_contex *const uhs_ctx)
49287
{
50288
struct usb_device *const udev = uhs_ctx->root;
51-
const size_t len = 512;
52-
struct net_buf *buf;
289+
struct usbh_uvc_data *const uvc = NULL;
290+
struct usb_if_descriptor *if_control = NULL;
291+
struct usb_if_descriptor *if_streaming = NULL;
53292
int ret;
54293

55-
LOG_INF("%p", uhs_ctx);
294+
LOG_DBG("%p", uhs_ctx);
295+
296+
/* TODO only scan through the interfaces assigned to this class by usbh_class.c */
297+
for (unsigned int i = 0; udev->ifaces[i].dhp != NULL; i++) {
298+
struct usb_if_descriptor *if_desc = (void *)udev->ifaces[i].dhp;
56299

57-
buf = usbh_xfer_buf_alloc(udev, len);
58-
if (buf == NULL) {
59-
LOG_ERR("Failed to allocate a host transfer buffer");
60-
return -ENOMEM;
300+
if (if_desc->bInterfaceClass == USB_BCC_VIDEO &&
301+
if_desc->bInterfaceSubClass == UVC_SC_VIDEOCONTROL) {
302+
if_control = if_desc;
303+
}
304+
305+
if (if_desc->bInterfaceClass == USB_BCC_VIDEO &&
306+
if_desc->bInterfaceSubClass == UVC_SC_VIDEOSTREAMING) {
307+
if_streaming = if_desc;
308+
}
61309
}
62310

63-
ret = usbh_req_desc(udev, USB_DESC_DEVICE, 0, 0, len, buf);
311+
if (if_streaming == NULL || if_control == NULL) {
312+
LOG_ERR("Video Streaming %p or Control %p interface missing",
313+
if_streaming, if_control);
314+
return -EINVAL;
315+
}
316+
317+
ret = usbh_uvc_parse_control_desc(uhs_ctx, uvc, if_control);
64318
if (ret != 0) {
65-
LOG_ERR("Failed to request descriptor");
66319
return ret;
67320
}
68321

69-
LOG_HEXDUMP_INF(buf->data, buf->len, "buf");
322+
ret = usbh_uvc_parse_streaming_desc(uhs_ctx, uvc, if_streaming);
323+
if (ret != 0) {
324+
return ret;
325+
}
70326

71327
return 0;
72328
}
73329

74330
static int usbh_uvc_removed(struct usbh_contex *const uhs_ctx)
75331
{
76-
LOG_INF("%p", uhs_ctx);
332+
LOG_DBG("%p", uhs_ctx);
77333

78334
return 0;
79335
}
80336

81337
static int usbh_uvc_rwup(struct usbh_contex *const uhs_ctx)
82338
{
83-
LOG_INF("%p", uhs_ctx);
339+
LOG_DBG("%p", uhs_ctx);
84340

85341
return 0;
86342
}
87343

88344
static int usbh_uvc_suspended(struct usbh_contex *const uhs_ctx)
89345
{
90-
LOG_INF("%p", uhs_ctx);
346+
LOG_DBG("%p", uhs_ctx);
91347

92348
return 0;
93349
}
94350

95351
static int usbh_uvc_resumed(struct usbh_contex *const uhs_ctx)
96352
{
97-
LOG_INF("%p", uhs_ctx);
353+
LOG_DBG("%p", uhs_ctx);
98354

99355
return 0;
100356
}
101357

102358
static int usbh_uvc_preinit(const struct device *dev)
103359
{
104-
LOG_INF("%s", dev->name);
360+
LOG_DBG("%s", dev->name);
105361

106362
return 0;
107363
}

0 commit comments

Comments
 (0)