xref: /openbsd/sys/dev/usb/uvideo.c (revision 54fbbda3)
1 /*	$OpenBSD: uvideo.c,v 1.222 2024/09/01 03:09:00 jsg Exp $ */
2 
3 /*
4  * Copyright (c) 2008 Robert Nagy <robert@openbsd.org>
5  * Copyright (c) 2008 Marcus Glocker <mglocker@openbsd.org>
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include <sys/param.h>
21 #include <sys/systm.h>
22 #include <sys/malloc.h>
23 #include <sys/device.h>
24 #include <sys/stat.h>
25 #include <sys/kthread.h>
26 #include <sys/stdint.h>
27 
28 #include <uvm/uvm_extern.h>
29 
30 #include <machine/bus.h>
31 
32 #include <dev/usb/usb.h>
33 #include <dev/usb/usbdi.h>
34 #include <dev/usb/usbdivar.h>
35 #include <dev/usb/usbdi_util.h>
36 #include <dev/usb/usbdevs.h>
37 #include <dev/usb/uvideo.h>
38 
39 #include <dev/video_if.h>
40 
41 #ifdef UVIDEO_DEBUG
42 int uvideo_debug = 1;
43 #define DPRINTF(l, x...) do { if ((l) <= uvideo_debug) printf(x); } while (0)
44 #else
45 #define DPRINTF(l, x...)
46 #endif
47 
48 #define DEVNAME(_s) ((_s)->sc_dev.dv_xname)
49 
50 #define byteof(x) ((x) >> 3)
51 #define bitof(x)  (1L << ((x) & 0x7))
52 
53 struct uvideo_softc {
54 	struct device				 sc_dev;
55 	struct usbd_device			*sc_udev;
56 	int					 sc_iface;
57 	int					 sc_nifaces;
58 
59 	struct device				*sc_videodev;
60 
61 	int					 sc_max_ctrl_size;
62 	int					 sc_max_fbuf_size;
63 	int					 sc_negotiated_flag;
64 	int					 sc_frame_rate;
65 
66 	struct uvideo_frame_buffer		 sc_frame_buffer;
67 
68 	struct uvideo_mmap			 sc_mmap[UVIDEO_MAX_BUFFERS];
69 	uint8_t					*sc_mmap_buffer;
70 	size_t					 sc_mmap_buffer_size;
71 	q_mmap					 sc_mmap_q;
72 	int					 sc_mmap_count;
73 	int					 sc_mmap_flag;
74 
75 	struct vnode				*sc_vp;
76 	struct usb_task				 sc_task_write;
77 
78 	int					 sc_nframes;
79 	struct usb_video_probe_commit		 sc_desc_probe;
80 	struct usb_video_header_desc_all	 sc_desc_vc_header;
81 	struct usb_video_input_header_desc_all	 sc_desc_vs_input_header;
82 
83 #define UVIDEO_MAX_PU				 8
84 	int					 sc_desc_vc_pu_num;
85 	struct usb_video_vc_processing_desc	*sc_desc_vc_pu_cur;
86 	struct usb_video_vc_processing_desc	*sc_desc_vc_pu[UVIDEO_MAX_PU];
87 
88 #define UVIDEO_MAX_FORMAT			 8
89 	int					 sc_fmtgrp_idx;
90 	int					 sc_fmtgrp_num;
91 	struct uvideo_format_group		*sc_fmtgrp_cur;
92 	struct uvideo_format_group		 sc_fmtgrp[UVIDEO_MAX_FORMAT];
93 
94 #define	UVIDEO_MAX_VS_NUM			 8
95 	struct uvideo_vs_iface			*sc_vs_cur;
96 	struct uvideo_vs_iface			 sc_vs_coll[UVIDEO_MAX_VS_NUM];
97 
98 	void					*sc_uplayer_arg;
99 	int					*sc_uplayer_fsize;
100 	uint8_t					*sc_uplayer_fbuffer;
101 	void					 (*sc_uplayer_intr)(void *);
102 
103 	const struct uvideo_devs		*sc_quirk;
104 	usbd_status				(*sc_decode_stream_header)
105 						    (struct uvideo_softc *,
106 						    uint8_t *, int);
107 };
108 
109 int		uvideo_open(void *, int, int *, uint8_t *, void (*)(void *),
110 		    void *);
111 int		uvideo_close(void *);
112 int		uvideo_match(struct device *, void *, void *);
113 void		uvideo_attach(struct device *, struct device *, void *);
114 void		uvideo_attach_hook(struct device *);
115 int		uvideo_detach(struct device *, int);
116 
117 usbd_status	uvideo_vc_parse_desc(struct uvideo_softc *);
118 usbd_status	uvideo_vc_parse_desc_header(struct uvideo_softc *,
119 		    const usb_descriptor_t *);
120 usbd_status	uvideo_vc_parse_desc_pu(struct uvideo_softc *,
121 		    const usb_descriptor_t *);
122 usbd_status	uvideo_vc_get_ctrl(struct uvideo_softc *, uint8_t *, uint8_t,
123 		    uint8_t, uint16_t, uint16_t);
124 usbd_status	uvideo_vc_set_ctrl(struct uvideo_softc *, uint8_t *, uint8_t,
125 		    uint8_t, uint16_t, uint16_t);
126 int		uvideo_find_ctrl(struct uvideo_softc *, int);
127 int		uvideo_has_ctrl(struct usb_video_vc_processing_desc *, int);
128 
129 usbd_status	uvideo_vs_parse_desc(struct uvideo_softc *,
130 		    usb_config_descriptor_t *);
131 usbd_status	uvideo_vs_parse_desc_input_header(struct uvideo_softc *,
132 		    const usb_descriptor_t *);
133 usbd_status	uvideo_vs_parse_desc_format(struct uvideo_softc *);
134 usbd_status	uvideo_vs_parse_desc_format_mjpeg(struct uvideo_softc *,
135 		    const usb_descriptor_t *);
136 usbd_status	uvideo_vs_parse_desc_format_uncompressed(struct uvideo_softc *,
137 		    const usb_descriptor_t *);
138 usbd_status	uvideo_vs_parse_desc_frame(struct uvideo_softc *);
139 usbd_status	uvideo_vs_parse_desc_frame_sub(struct uvideo_softc *,
140 		    const usb_descriptor_t *);
141 usbd_status	uvideo_vs_parse_desc_alt(struct uvideo_softc *, int, int, int);
142 usbd_status	uvideo_vs_set_alt(struct uvideo_softc *,
143 		    struct usbd_interface *, int);
144 int		uvideo_desc_len(const usb_descriptor_t *, int, int, int, int);
145 void		uvideo_find_res(struct uvideo_softc *, int, int, int,
146 		    struct uvideo_res *);
147 usbd_status	uvideo_vs_negotiation(struct uvideo_softc *, int);
148 usbd_status	uvideo_vs_set_probe(struct uvideo_softc *, uint8_t *);
149 usbd_status	uvideo_vs_get_probe(struct uvideo_softc *, uint8_t *, uint8_t);
150 usbd_status	uvideo_vs_set_commit(struct uvideo_softc *, uint8_t *);
151 usbd_status	uvideo_vs_alloc_frame(struct uvideo_softc *);
152 void		uvideo_vs_free_frame(struct uvideo_softc *);
153 usbd_status	uvideo_vs_alloc_isoc(struct uvideo_softc *);
154 usbd_status	uvideo_vs_alloc_bulk(struct uvideo_softc *);
155 void		uvideo_vs_free_isoc(struct uvideo_softc *);
156 void		uvideo_vs_free_bulk(struct uvideo_softc *);
157 usbd_status	uvideo_vs_open(struct uvideo_softc *);
158 void		uvideo_vs_close(struct uvideo_softc *);
159 usbd_status	uvideo_vs_init(struct uvideo_softc *);
160 int		uvideo_vs_start_bulk(struct uvideo_softc *);
161 void		uvideo_vs_start_bulk_thread(void *);
162 void		uvideo_vs_start_isoc(struct uvideo_softc *);
163 void		uvideo_vs_start_isoc_ixfer(struct uvideo_softc *,
164 		    struct uvideo_isoc_xfer *);
165 void		uvideo_vs_cb(struct usbd_xfer *, void *,
166 		    usbd_status);
167 usbd_status	uvideo_vs_decode_stream_header(struct uvideo_softc *,
168 		    uint8_t *, int);
169 usbd_status	uvideo_vs_decode_stream_header_isight(struct uvideo_softc *,
170 		    uint8_t *, int);
171 int		uvideo_mmap_queue(struct uvideo_softc *, uint8_t *, int);
172 void		uvideo_read(struct uvideo_softc *, uint8_t *, int);
173 usbd_status	uvideo_usb_control(struct uvideo_softc *, uint8_t, uint8_t,
174 		    uint16_t, uint8_t *, size_t);
175 
176 #ifdef UVIDEO_DEBUG
177 #include <sys/namei.h>
178 #include <sys/proc.h>
179 #include <sys/vnode.h>
180 #include <sys/fcntl.h>
181 
182 void		uvideo_dump_desc_all(struct uvideo_softc *);
183 void		uvideo_dump_desc_vc_header(struct uvideo_softc *,
184 		    const usb_descriptor_t *);
185 void		uvideo_dump_desc_input_header(struct uvideo_softc *,
186 		    const usb_descriptor_t *);
187 void		uvideo_dump_desc_input(struct uvideo_softc *,
188 		    const usb_descriptor_t *);
189 void		uvideo_dump_desc_output(struct uvideo_softc *,
190 		    const usb_descriptor_t *);
191 void		uvideo_dump_desc_endpoint(struct uvideo_softc *,
192 		    const usb_descriptor_t *);
193 void		uvideo_dump_desc_iface_assoc(struct uvideo_softc *,
194 		    const usb_descriptor_t *);
195 void		uvideo_dump_desc_interface(struct uvideo_softc *,
196 		    const usb_descriptor_t *);
197 void		uvideo_dump_desc_config(struct uvideo_softc *,
198 		    const usb_descriptor_t *);
199 void		uvideo_dump_desc_cs_endpoint(struct uvideo_softc *,
200 		    const usb_descriptor_t *);
201 void		uvideo_dump_desc_colorformat(struct uvideo_softc *,
202 		    const usb_descriptor_t *);
203 void		uvideo_dump_desc_format_mjpeg(struct uvideo_softc *,
204 		    const usb_descriptor_t *);
205 void		uvideo_dump_desc_format_uncompressed(struct uvideo_softc *,
206 		    const usb_descriptor_t *);
207 void		uvideo_dump_desc_frame(struct uvideo_softc *,
208 		    const usb_descriptor_t *);
209 void		uvideo_dump_desc_processing(struct uvideo_softc *,
210 		    const usb_descriptor_t *);
211 void		uvideo_dump_desc_extension(struct uvideo_softc *,
212 		    const usb_descriptor_t *);
213 void		uvideo_hexdump(void *, int, int);
214 int		uvideo_debug_file_open(struct uvideo_softc *);
215 void		uvideo_debug_file_write_frame(void *);
216 #endif
217 
218 /*
219  * IOCTL's
220  */
221 int		uvideo_querycap(void *, struct v4l2_capability *);
222 int		uvideo_enum_fmt(void *, struct v4l2_fmtdesc *);
223 int		uvideo_enum_fsizes(void *, struct v4l2_frmsizeenum *);
224 int		uvideo_enum_fivals(void *, struct v4l2_frmivalenum *);
225 int		uvideo_s_fmt(void *, struct v4l2_format *);
226 int		uvideo_g_fmt(void *, struct v4l2_format *);
227 int		uvideo_s_parm(void *, struct v4l2_streamparm *);
228 int		uvideo_g_parm(void *, struct v4l2_streamparm *);
229 int		uvideo_enum_input(void *, struct v4l2_input *);
230 int		uvideo_s_input(void *, int);
231 int		uvideo_g_input(void *, int *);
232 int		uvideo_reqbufs(void *, struct v4l2_requestbuffers *);
233 int		uvideo_querybuf(void *, struct v4l2_buffer *);
234 int		uvideo_qbuf(void *, struct v4l2_buffer *);
235 int		uvideo_dqbuf(void *, struct v4l2_buffer *);
236 int		uvideo_streamon(void *, int);
237 int		uvideo_streamoff(void *, int);
238 int		uvideo_try_fmt(void *, struct v4l2_format *);
239 int		uvideo_queryctrl(void *, struct v4l2_queryctrl *);
240 int		uvideo_g_ctrl(void *, struct v4l2_control *);
241 int		uvideo_s_ctrl(void *, struct v4l2_control *);
242 
243 /*
244  * Other hardware interface related functions
245  */
246 caddr_t		uvideo_mappage(void *, off_t, int);
247 int		uvideo_get_bufsize(void *);
248 int		uvideo_start_read(void *);
249 
250 /*
251  * Firmware
252  */
253 usbd_status	uvideo_ucode_loader_ricoh(struct uvideo_softc *);
254 usbd_status	uvideo_ucode_loader_apple_isight(struct uvideo_softc *);
255 
256 struct cfdriver uvideo_cd = {
257 	NULL, "uvideo", DV_DULL
258 };
259 
260 const struct cfattach uvideo_ca = {
261 	sizeof(struct uvideo_softc), uvideo_match, uvideo_attach, uvideo_detach
262 };
263 
264 const struct video_hw_if uvideo_hw_if = {
265 	uvideo_open,		/* open */
266 	uvideo_close,		/* close */
267 	uvideo_querycap,	/* VIDIOC_QUERYCAP */
268 	uvideo_enum_fmt,	/* VIDIOC_ENUM_FMT */
269 	uvideo_enum_fsizes,	/* VIDIOC_ENUM_FRAMESIZES */
270 	uvideo_enum_fivals,	/* VIDIOC_ENUM_FRAMEINTERVALS */
271 	uvideo_s_fmt,		/* VIDIOC_S_FMT */
272 	uvideo_g_fmt,		/* VIDIOC_G_FMT */
273 	uvideo_s_parm,		/* VIDIOC_S_PARM */
274 	uvideo_g_parm,		/* VIDIOC_G_PARM */
275 	uvideo_enum_input,	/* VIDIOC_ENUMINPUT */
276 	uvideo_s_input,		/* VIDIOC_S_INPUT */
277 	uvideo_g_input,		/* VIDIOC_G_INPUT */
278 	uvideo_reqbufs,		/* VIDIOC_REQBUFS */
279 	uvideo_querybuf,	/* VIDIOC_QUERYBUF */
280 	uvideo_qbuf,		/* VIDIOC_QBUF */
281 	uvideo_dqbuf,		/* VIDIOC_DQBUF */
282 	uvideo_streamon,	/* VIDIOC_STREAMON */
283 	uvideo_streamoff,	/* VIDIOC_STREAMOFF */
284 	uvideo_try_fmt,		/* VIDIOC_TRY_FMT */
285 	uvideo_queryctrl,	/* VIDIOC_QUERYCTRL */
286 	uvideo_g_ctrl,		/* VIDIOC_G_CTRL */
287 	uvideo_s_ctrl,		/* VIDIOC_S_CTRL */
288 	uvideo_mappage,		/* mmap */
289 	uvideo_get_bufsize,	/* read */
290 	uvideo_start_read	/* start stream for read */
291 };
292 
293 /*
294  * Devices which either fail to declare themselves as UICLASS_VIDEO,
295  * or which need firmware uploads or other quirk handling later on.
296  */
297 #define UVIDEO_FLAG_ISIGHT_STREAM_HEADER	0x1
298 #define UVIDEO_FLAG_REATTACH			0x2
299 #define UVIDEO_FLAG_VENDOR_CLASS		0x4
300 #define UVIDEO_FLAG_NOATTACH			0x8
301 const struct uvideo_devs {
302 	struct usb_devno	 uv_dev;
303 	char			*ucode_name;
304 	usbd_status		 (*ucode_loader)(struct uvideo_softc *);
305 	int			 flags;
306 } uvideo_devs[] = {
307 	{
308 	    /* Needs firmware */
309 	    { USB_VENDOR_RICOH, USB_PRODUCT_RICOH_VGPVCC5 },
310 	    "uvideo_r5u87x_05ca-1835",
311 	    uvideo_ucode_loader_ricoh,
312 	    0
313 	},
314 	{
315 	    /* Needs firmware */
316 	    { USB_VENDOR_RICOH, USB_PRODUCT_RICOH_VGPVCC4 },
317 	    "uvideo_r5u87x_05ca-1836",
318 	    uvideo_ucode_loader_ricoh,
319 	    0
320 	},
321 	{
322 	    /* Needs firmware */
323 	    { USB_VENDOR_RICOH, USB_PRODUCT_RICOH_VGPVCC4_2 },
324 	    "uvideo_r5u87x_05ca-1837",
325 	    uvideo_ucode_loader_ricoh,
326 	    0
327 	},
328 	{
329 	    /* Needs firmware */
330 	    { USB_VENDOR_RICOH, USB_PRODUCT_RICOH_VGPVCC6 },
331 	    "uvideo_r5u87x_05ca-1839",
332 	    uvideo_ucode_loader_ricoh,
333 	    0
334 	},
335 	{
336 	    /* Needs firmware */
337 	    { USB_VENDOR_RICOH, USB_PRODUCT_RICOH_VGPVCC7 },
338 	    "uvideo_r5u87x_05ca-183a",
339 	    uvideo_ucode_loader_ricoh,
340 	    0
341 	},
342 	{
343 	    /* Needs firmware */
344 	    { USB_VENDOR_RICOH, USB_PRODUCT_RICOH_VGPVCC8 },
345 	    "uvideo_r5u87x_05ca-183b",
346 	    uvideo_ucode_loader_ricoh,
347 	    0
348 	},
349 	{
350 	    /* Needs firmware */
351 	    { USB_VENDOR_RICOH, USB_PRODUCT_RICOH_VGPVCC9 },
352 	    "uvideo_r5u87x_05ca-183e",
353 	    uvideo_ucode_loader_ricoh,
354 	    0
355 	},
356 	{
357 	    /* Needs firmware */
358 	    { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_BLUETOOTH },
359 	    "uvideo_isight_05ac-8300",
360 	    uvideo_ucode_loader_apple_isight,
361 	    UVIDEO_FLAG_REATTACH
362 	},
363 	{
364 	    /* Has a non-standard streaming header protocol */
365 	    { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_ISIGHT_1 },
366 	    NULL,
367 	    NULL,
368 	    UVIDEO_FLAG_ISIGHT_STREAM_HEADER
369 	},
370 	{   /* Incorrectly reports as bInterfaceClass=UICLASS_VENDOR */
371 	    { USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_QUICKCAMOEM_1 },
372 	    NULL,
373 	    NULL,
374 	    UVIDEO_FLAG_VENDOR_CLASS
375 	},
376 	{   /* Infrared camera not supported */
377 	    { USB_VENDOR_CHICONY, USB_PRODUCT_CHICONY_IRCAMERA },
378 	    NULL,
379 	    NULL,
380 	    UVIDEO_FLAG_NOATTACH
381 	},
382 };
383 #define uvideo_lookup(v, p) \
384 	((const struct uvideo_devs *)usb_lookup(uvideo_devs, v, p))
385 
386 int
uvideo_open(void * addr,int flags,int * size,uint8_t * buffer,void (* intr)(void *),void * arg)387 uvideo_open(void *addr, int flags, int *size, uint8_t *buffer,
388     void (*intr)(void *), void *arg)
389 {
390 	struct uvideo_softc *sc = addr;
391 
392 	DPRINTF(1, "%s: uvideo_open: sc=%p\n", DEVNAME(sc), sc);
393 
394 	if (usbd_is_dying(sc->sc_udev))
395 		return (EIO);
396 
397 	/* pointers to upper video layer */
398 	sc->sc_uplayer_arg = arg;
399 	sc->sc_uplayer_fsize = size;
400 	sc->sc_uplayer_fbuffer = buffer;
401 	sc->sc_uplayer_intr = intr;
402 
403 	sc->sc_mmap_flag = 0;
404 	sc->sc_negotiated_flag = 0;
405 
406 	return (0);
407 }
408 
409 int
uvideo_close(void * addr)410 uvideo_close(void *addr)
411 {
412 	struct uvideo_softc *sc = addr;
413 
414 	DPRINTF(1, "%s: uvideo_close: sc=%p\n", DEVNAME(sc), sc);
415 
416 #ifdef UVIDEO_DUMP
417 	usb_rem_task(sc->sc_udev, &sc->sc_task_write);
418 #endif
419 	/* close video stream pipe */
420 	uvideo_vs_close(sc);
421 
422 	/* free video stream xfer buffer */
423 	if (sc->sc_vs_cur->bulk_endpoint)
424 		uvideo_vs_free_bulk(sc);
425 	else
426 		uvideo_vs_free_isoc(sc);
427 
428 	/* free video stream frame buffer */
429 	uvideo_vs_free_frame(sc);
430 	return (0);
431 }
432 
433 int
uvideo_match(struct device * parent,void * match,void * aux)434 uvideo_match(struct device *parent, void *match, void *aux)
435 {
436 	struct usb_attach_arg *uaa = aux;
437 	usb_interface_descriptor_t *id;
438 	const struct uvideo_devs *quirk;
439 
440 	if (uaa->iface == NULL)
441 		return (UMATCH_NONE);
442 
443 	id = usbd_get_interface_descriptor(uaa->iface);
444 	if (id == NULL)
445 		return (UMATCH_NONE);
446 
447 	/* quirk devices */
448 	quirk = uvideo_lookup(uaa->vendor, uaa->product);
449 	if (quirk != NULL) {
450 		if (quirk->flags & UVIDEO_FLAG_REATTACH)
451 			return (UMATCH_VENDOR_PRODUCT_CONF_IFACE);
452 
453 		if (quirk->flags & UVIDEO_FLAG_VENDOR_CLASS &&
454 		    id->bInterfaceClass == UICLASS_VENDOR &&
455 		    id->bInterfaceSubClass == UISUBCLASS_VIDEOCONTROL)
456 			return (UMATCH_VENDOR_PRODUCT_CONF_IFACE);
457 	}
458 
459 	if (id->bInterfaceClass == UICLASS_VIDEO &&
460 	    id->bInterfaceSubClass == UISUBCLASS_VIDEOCONTROL)
461 		return (UMATCH_VENDOR_PRODUCT_CONF_IFACE);
462 
463 	return (UMATCH_NONE);
464 }
465 
466 void
uvideo_attach(struct device * parent,struct device * self,void * aux)467 uvideo_attach(struct device *parent, struct device *self, void *aux)
468 {
469 	struct uvideo_softc *sc = (struct uvideo_softc *)self;
470 	struct usb_attach_arg *uaa = aux;
471 	usb_interface_assoc_descriptor_t *iad;
472 	usb_interface_descriptor_t *id;
473 	const usb_descriptor_t *desc;
474 	struct usbd_desc_iter iter;
475 	int i;
476 
477 	sc->sc_udev = uaa->device;
478 
479 	/* Find the first unclaimed video interface. */
480 	for (i = 0; i < uaa->nifaces; i++) {
481 		if (usbd_iface_claimed(sc->sc_udev, i))
482 			continue;
483 		id = usbd_get_interface_descriptor(&sc->sc_udev->ifaces[i]);
484 		if (id == NULL)
485 			continue;
486 		if (id->bInterfaceClass == UICLASS_VIDEO)
487 			break;
488 	}
489 	if (i == uaa->nifaces) {
490 		printf("%s: can't find video interface\n", DEVNAME(sc));
491 		return;
492 	}
493 
494 	/* Find out which interface association we belong to. */
495 	usbd_desc_iter_init(sc->sc_udev, &iter);
496 	desc = usbd_desc_iter_next(&iter);
497 	while (desc) {
498 		if (desc->bDescriptorType != UDESC_IFACE_ASSOC) {
499 			desc = usbd_desc_iter_next(&iter);
500 			continue;
501 		}
502 		iad = (usb_interface_assoc_descriptor_t *)desc;
503 		if (i >= iad->bFirstInterface &&
504 		    i < iad->bFirstInterface + iad->bInterfaceCount)
505 			break;
506 		desc = usbd_desc_iter_next(&iter);
507 	}
508 	if (desc == NULL) {
509 		printf("%s: can't find interface assoc descriptor\n",
510 		    DEVNAME(sc));
511 		return;
512 	}
513 
514 	/*
515 	 * Claim all interfaces of our association.  Interfaces must be
516 	 * claimed during attach, during attach hooks is too late.
517 	 */
518 	for (i = iad->bFirstInterface;
519 	    i < iad->bFirstInterface + iad->bInterfaceCount; i++) {
520 		if (usbd_iface_claimed(sc->sc_udev, i)) {
521 			printf("%s: interface already claimed\n",
522 			    DEVNAME(sc));
523 			return;
524 		}
525 		usbd_claim_iface(sc->sc_udev, i);
526 	}
527 
528 	/* Remember our association by saving the first interface. */
529 	sc->sc_iface = iad->bFirstInterface;
530 	sc->sc_nifaces = iad->bInterfaceCount;
531 
532 	/* maybe the device has quirks */
533 	sc->sc_quirk = uvideo_lookup(uaa->vendor, uaa->product);
534 
535 	if (sc->sc_quirk && sc->sc_quirk->flags & UVIDEO_FLAG_NOATTACH) {
536 		printf("%s: device not supported\n", DEVNAME(sc));
537 		return;
538 	}
539 
540 	if (sc->sc_quirk && sc->sc_quirk->ucode_name)
541 		config_mountroot(self, uvideo_attach_hook);
542 	else
543 		uvideo_attach_hook(self);
544 }
545 
546 void
uvideo_attach_hook(struct device * self)547 uvideo_attach_hook(struct device *self)
548 {
549 	struct uvideo_softc *sc = (struct uvideo_softc *)self;
550 	usb_config_descriptor_t *cdesc;
551 	usbd_status error;
552 
553 	/* maybe the device needs a firmware */
554 	if (sc->sc_quirk && sc->sc_quirk->ucode_name) {
555 		error = (sc->sc_quirk->ucode_loader)(sc);
556 		if (error != USBD_NORMAL_COMPLETION)
557 			return;
558 	}
559 
560 	/* map stream header decode function */
561 	if (sc->sc_quirk &&
562 	    sc->sc_quirk->flags & UVIDEO_FLAG_ISIGHT_STREAM_HEADER) {
563 		sc->sc_decode_stream_header =
564 		    uvideo_vs_decode_stream_header_isight;
565 	} else {
566 		sc->sc_decode_stream_header =
567 		    uvideo_vs_decode_stream_header;
568 	}
569 
570 	/* get the config descriptor */
571 	cdesc = usbd_get_config_descriptor(sc->sc_udev);
572 	if (cdesc == NULL) {
573 		printf("%s: failed to get configuration descriptor\n",
574 		    DEVNAME(sc));
575 		return;
576 	}
577 #ifdef UVIDEO_DEBUG
578 	uvideo_dump_desc_all(sc);
579 #endif
580 	/* parse video control descriptors */
581 	error = uvideo_vc_parse_desc(sc);
582 	if (error != USBD_NORMAL_COMPLETION)
583 		return;
584 
585 	/* parse video stream descriptors */
586 	error = uvideo_vs_parse_desc(sc, cdesc);
587 	if (error != USBD_NORMAL_COMPLETION)
588 		return;
589 
590 	/* set default video stream interface */
591 	error = usbd_set_interface(sc->sc_vs_cur->ifaceh, 0);
592 	if (error != USBD_NORMAL_COMPLETION)
593 		return;
594 
595 	/* do device negotiation without commit */
596 	error = uvideo_vs_negotiation(sc, 0);
597 	if (error != USBD_NORMAL_COMPLETION)
598 		return;
599 
600 	/* init mmap queue */
601 	SIMPLEQ_INIT(&sc->sc_mmap_q);
602 	sc->sc_mmap_count = 0;
603 
604 	DPRINTF(1, "uvideo_attach: doing video_attach_mi\n");
605 	sc->sc_videodev = video_attach_mi(&uvideo_hw_if, sc, &sc->sc_dev);
606 }
607 
608 int
uvideo_detach(struct device * self,int flags)609 uvideo_detach(struct device *self, int flags)
610 {
611 	struct uvideo_softc *sc = (struct uvideo_softc *)self;
612 	int rv = 0;
613 
614 	/* Wait for outstanding requests to complete */
615 	usbd_delay_ms(sc->sc_udev, UVIDEO_NFRAMES_MAX);
616 
617 	if (sc->sc_videodev != NULL)
618 		rv = config_detach(sc->sc_videodev, flags);
619 
620 	uvideo_vs_free_frame(sc);
621 
622 	return (rv);
623 }
624 
625 usbd_status
uvideo_vc_parse_desc(struct uvideo_softc * sc)626 uvideo_vc_parse_desc(struct uvideo_softc *sc)
627 {
628 	struct usbd_desc_iter iter;
629 	const usb_descriptor_t *desc;
630 	usb_interface_descriptor_t *id;
631 	int vc_header_found;
632 	usbd_status error;
633 
634 	DPRINTF(1, "%s: %s\n", DEVNAME(sc), __func__);
635 
636 	vc_header_found = 0;
637 
638 	usbd_desc_iter_init(sc->sc_udev, &iter);
639 	desc = usbd_desc_iter_next(&iter);
640 	while (desc) {
641 		/* Skip all interfaces until we found our first. */
642 		if (desc->bDescriptorType == UDESC_INTERFACE) {
643 			id = (usb_interface_descriptor_t *)desc;
644 			if (id->bInterfaceNumber == sc->sc_iface)
645 				break;
646 		}
647 		desc = usbd_desc_iter_next(&iter);
648 	}
649 	while (desc) {
650 		/* Crossed device function boundary. */
651 		if (desc->bDescriptorType == UDESC_IFACE_ASSOC)
652 			break;
653 		if (desc->bDescriptorType != UDESC_CS_INTERFACE) {
654 			desc = usbd_desc_iter_next(&iter);
655 			continue;
656 		}
657 
658 		switch (desc->bDescriptorSubtype) {
659 		case UDESCSUB_VC_HEADER:
660 			if (!uvideo_desc_len(desc, 12, 11, 1, 0))
661 				break;
662 			if (vc_header_found) {
663 				printf("%s: too many VC_HEADERs!\n",
664 				    DEVNAME(sc));
665 				return (USBD_INVAL);
666 			}
667 			error = uvideo_vc_parse_desc_header(sc, desc);
668 			if (error != USBD_NORMAL_COMPLETION)
669 				return (error);
670 			vc_header_found = 1;
671 			break;
672 		case UDESCSUB_VC_PROCESSING_UNIT:
673 			/* XXX do correct length calculation */
674 			if (desc->bLength <
675 			    sizeof(struct usb_video_frame_desc)) {
676 				(void)uvideo_vc_parse_desc_pu(sc, desc);
677 			}
678 			break;
679 
680 		/* TODO: which VC descriptors do we need else? */
681 		}
682 
683 		desc = usbd_desc_iter_next(&iter);
684 	}
685 
686 	if (vc_header_found == 0) {
687 		printf("%s: no VC_HEADER found!\n", DEVNAME(sc));
688 		return (USBD_INVAL);
689 	}
690 
691 	return (USBD_NORMAL_COMPLETION);
692 }
693 
694 usbd_status
uvideo_vc_parse_desc_header(struct uvideo_softc * sc,const usb_descriptor_t * desc)695 uvideo_vc_parse_desc_header(struct uvideo_softc *sc,
696     const usb_descriptor_t *desc)
697 {
698 	struct usb_video_header_desc *d;
699 
700 	d = (struct usb_video_header_desc *)(uint8_t *)desc;
701 
702 	if (d->bInCollection == 0) {
703 		printf("%s: no VS interface found!\n",
704 		    DEVNAME(sc));
705 		return (USBD_INVAL);
706 	}
707 
708 	sc->sc_desc_vc_header.fix = d;
709 	sc->sc_desc_vc_header.baInterfaceNr = (uByte *)(d + 1);
710 	if (UGETW(d->bcdUVC) < 0x0110)
711 		sc->sc_max_ctrl_size = 26;
712 	else if (UGETW(d->bcdUVC) < 0x0150)
713 		sc->sc_max_ctrl_size = 34;
714 	else
715 		sc->sc_max_ctrl_size = 48;
716 
717 	return (USBD_NORMAL_COMPLETION);
718 }
719 
720 usbd_status
uvideo_vc_parse_desc_pu(struct uvideo_softc * sc,const usb_descriptor_t * desc)721 uvideo_vc_parse_desc_pu(struct uvideo_softc *sc,
722     const usb_descriptor_t *desc)
723 {
724 	struct usb_video_vc_processing_desc *d;
725 
726 	/* PU descriptor is variable sized */
727 	d = (void *)desc;
728 
729 	if (sc->sc_desc_vc_pu_num == UVIDEO_MAX_PU) {
730 		printf("%s: too many PU descriptors found!\n", DEVNAME(sc));
731 		return (USBD_INVAL);
732 	}
733 
734 	sc->sc_desc_vc_pu[sc->sc_desc_vc_pu_num] = d;
735 	sc->sc_desc_vc_pu_num++;
736 
737 	return (USBD_NORMAL_COMPLETION);
738 }
739 
740 usbd_status
uvideo_vc_get_ctrl(struct uvideo_softc * sc,uint8_t * ctrl_data,uint8_t request,uint8_t unitid,uint16_t ctrl_selector,uint16_t ctrl_len)741 uvideo_vc_get_ctrl(struct uvideo_softc *sc, uint8_t *ctrl_data,
742     uint8_t request, uint8_t unitid, uint16_t ctrl_selector, uint16_t ctrl_len)
743 {
744 	usb_device_request_t req;
745 	usbd_status error;
746 
747 	req.bmRequestType = UVIDEO_GET_IF;
748 	req.bRequest = request;
749 	USETW(req.wValue, (ctrl_selector << 8));
750 	USETW(req.wIndex, (unitid << 8));
751 	USETW(req.wLength, ctrl_len);
752 
753 	error = usbd_do_request(sc->sc_udev, &req, ctrl_data);
754 	if (error) {
755 		DPRINTF(1, "%s: %s: could not GET ctrl request: %s\n",
756 		    DEVNAME(sc), __func__, usbd_errstr(error));
757 		return (USBD_INVAL);
758 	}
759 
760 	return (USBD_NORMAL_COMPLETION);
761 }
762 
763 usbd_status
uvideo_vc_set_ctrl(struct uvideo_softc * sc,uint8_t * ctrl_data,uint8_t request,uint8_t unitid,uint16_t ctrl_selector,uint16_t ctrl_len)764 uvideo_vc_set_ctrl(struct uvideo_softc *sc, uint8_t *ctrl_data,
765     uint8_t request, uint8_t unitid, uint16_t ctrl_selector, uint16_t ctrl_len)
766 {
767 	usb_device_request_t req;
768 	usbd_status error;
769 
770 	req.bmRequestType = UVIDEO_SET_IF;
771 	req.bRequest = request;
772 	USETW(req.wValue, (ctrl_selector << 8));
773 	USETW(req.wIndex, (unitid << 8));
774 	USETW(req.wLength, ctrl_len);
775 
776 	error = usbd_do_request(sc->sc_udev, &req, ctrl_data);
777 	if (error) {
778 		DPRINTF(1, "%s: %s: could not SET ctrl request: %s\n",
779 		    DEVNAME(sc), __func__, usbd_errstr(error));
780 		return (USBD_INVAL);
781 	}
782 
783 	return (USBD_NORMAL_COMPLETION);
784 }
785 
786 int
uvideo_find_ctrl(struct uvideo_softc * sc,int id)787 uvideo_find_ctrl(struct uvideo_softc *sc, int id)
788 {
789 	int i, j, found;
790 
791 	if (sc->sc_desc_vc_pu_num == 0) {
792 		/* no processing unit descriptors found */
793 		DPRINTF(1, "%s: %s: no processing unit descriptors found!\n",
794 		    DEVNAME(sc), __func__);
795 		return (EINVAL);
796 	}
797 
798 	/* do we support this control? */
799 	for (found = 0, i = 0; uvideo_ctrls[i].cid != 0; i++) {
800 		if (id == uvideo_ctrls[i].cid) {
801 			found = 1;
802 			break;
803 		}
804 	}
805 	if (found == 0) {
806 		DPRINTF(1, "%s: %s: control not supported by driver!\n",
807 		    DEVNAME(sc), __func__);
808 		return (EINVAL);
809 	}
810 
811 	/* does the device support this control? */
812 	for (found = 0, j = 0; j < sc->sc_desc_vc_pu_num; j++) {
813 		if (uvideo_has_ctrl(sc->sc_desc_vc_pu[j],
814 		    uvideo_ctrls[i].ctrl_bit) != 0) {
815 			found = 1;
816 			break;
817 		}
818 	}
819 	if (found == 0) {
820 		DPRINTF(1, "%s: %s: control not supported by device!\n",
821 		    DEVNAME(sc), __func__);
822 		return (EINVAL);
823 	}
824 	sc->sc_desc_vc_pu_cur = sc->sc_desc_vc_pu[j];
825 
826 	return (i);
827 }
828 
829 int
uvideo_has_ctrl(struct usb_video_vc_processing_desc * desc,int ctrl_bit)830 uvideo_has_ctrl(struct usb_video_vc_processing_desc *desc, int ctrl_bit)
831 {
832 	if (desc->bControlSize * 8 <= ctrl_bit)
833 		return (0);
834 
835 	return (desc->bmControls[byteof(ctrl_bit)] & bitof(ctrl_bit));
836 }
837 
838 usbd_status
uvideo_vs_parse_desc(struct uvideo_softc * sc,usb_config_descriptor_t * cdesc)839 uvideo_vs_parse_desc(struct uvideo_softc *sc, usb_config_descriptor_t *cdesc)
840 {
841 	struct usbd_desc_iter iter;
842 	const usb_descriptor_t *desc;
843 	usb_interface_descriptor_t *id;
844 	int i, iface, numalts;
845 	usbd_status error;
846 
847 	DPRINTF(1, "%s: number of total interfaces=%d\n",
848 	    DEVNAME(sc), sc->sc_nifaces);
849 	DPRINTF(1, "%s: number of VS interfaces=%d\n",
850 	    DEVNAME(sc), sc->sc_desc_vc_header.fix->bInCollection);
851 
852 	usbd_desc_iter_init(sc->sc_udev, &iter);
853 	desc = usbd_desc_iter_next(&iter);
854 	while (desc) {
855 		/* Skip all interfaces until we found our first. */
856 		if (desc->bDescriptorType == UDESC_INTERFACE) {
857 			id = (usb_interface_descriptor_t *)desc;
858 			if (id->bInterfaceNumber == sc->sc_iface)
859 				break;
860 		}
861 		desc = usbd_desc_iter_next(&iter);
862 	}
863 	while (desc) {
864 		/* Crossed device function boundary. */
865 		if (desc->bDescriptorType == UDESC_IFACE_ASSOC)
866 			break;
867 		if (desc->bDescriptorType != UDESC_CS_INTERFACE) {
868 			desc = usbd_desc_iter_next(&iter);
869 			continue;
870 		}
871 
872 		switch (desc->bDescriptorSubtype) {
873 		case UDESCSUB_VS_INPUT_HEADER:
874 			if (!uvideo_desc_len(desc, 13, 3, 0, 12))
875 				break;
876 			error = uvideo_vs_parse_desc_input_header(sc, desc);
877 			if (error != USBD_NORMAL_COMPLETION)
878 				return (error);
879 			break;
880 
881 		/* TODO: which VS descriptors do we need else? */
882 		}
883 
884 		desc = usbd_desc_iter_next(&iter);
885 	}
886 
887 	/* parse video stream format descriptors */
888 	error = uvideo_vs_parse_desc_format(sc);
889 	if (error != USBD_NORMAL_COMPLETION)
890 		return (error);
891 
892 	/* parse video stream frame descriptors */
893 	error = uvideo_vs_parse_desc_frame(sc);
894 	if (error != USBD_NORMAL_COMPLETION)
895 		return (error);
896 
897 	/* parse interface collection */
898 	for (i = 0; i < sc->sc_desc_vc_header.fix->bInCollection; i++) {
899 		iface = sc->sc_desc_vc_header.baInterfaceNr[i];
900 
901 		id = usbd_get_interface_descriptor(&sc->sc_udev->ifaces[iface]);
902 		if (id == NULL) {
903 			printf("%s: can't get VS interface %d!\n",
904 			    DEVNAME(sc), iface);
905 			return (USBD_INVAL);
906 		}
907 		usbd_claim_iface(sc->sc_udev, iface);
908 
909 		numalts = usbd_get_no_alts(cdesc, id->bInterfaceNumber);
910 
911 		DPRINTF(1, "%s: VS interface %d, ", DEVNAME(sc), i);
912 		DPRINTF(1, "bInterfaceNumber=0x%02x, numalts=%d\n",
913 		    id->bInterfaceNumber, numalts);
914 
915 		error = uvideo_vs_parse_desc_alt(sc, i, iface, numalts);
916 		if (error != USBD_NORMAL_COMPLETION)
917 			return (error);
918 	}
919 
920 	/* XXX for now always use the first video stream */
921 	sc->sc_vs_cur = &sc->sc_vs_coll[0];
922 
923 	return (USBD_NORMAL_COMPLETION);
924 }
925 
926 usbd_status
uvideo_vs_parse_desc_input_header(struct uvideo_softc * sc,const usb_descriptor_t * desc)927 uvideo_vs_parse_desc_input_header(struct uvideo_softc *sc,
928     const usb_descriptor_t *desc)
929 {
930 	struct usb_video_input_header_desc *d;
931 
932 	d = (struct usb_video_input_header_desc *)(uint8_t *)desc;
933 
934 	/* on some devices bNumFormats is larger than the truth */
935 	if (d->bNumFormats == 0) {
936 		printf("%s: no INPUT FORMAT descriptors found!\n", DEVNAME(sc));
937 		return (USBD_INVAL);
938 	}
939 
940 	sc->sc_desc_vs_input_header.fix = d;
941 	sc->sc_desc_vs_input_header.bmaControls = (uByte *)(d + 1);
942 
943 	return (USBD_NORMAL_COMPLETION);
944 }
945 
946 usbd_status
uvideo_vs_parse_desc_format(struct uvideo_softc * sc)947 uvideo_vs_parse_desc_format(struct uvideo_softc *sc)
948 {
949 	struct usbd_desc_iter iter;
950 	const usb_descriptor_t *desc;
951 	usb_interface_descriptor_t *id;
952 
953 	DPRINTF(1, "%s: %s\n", DEVNAME(sc), __func__);
954 
955 	usbd_desc_iter_init(sc->sc_udev, &iter);
956 	desc = usbd_desc_iter_next(&iter);
957 	while (desc) {
958 		/* Skip all interfaces until we found our first. */
959 		if (desc->bDescriptorType == UDESC_INTERFACE) {
960 			id = (usb_interface_descriptor_t *)desc;
961 			if (id->bInterfaceNumber == sc->sc_iface)
962 				break;
963 		}
964 		desc = usbd_desc_iter_next(&iter);
965 	}
966 	while (desc) {
967 		/* Crossed device function boundary. */
968 		if (desc->bDescriptorType == UDESC_IFACE_ASSOC)
969 			break;
970 		if (desc->bDescriptorType != UDESC_CS_INTERFACE) {
971 			desc = usbd_desc_iter_next(&iter);
972 			continue;
973 		}
974 
975 		switch (desc->bDescriptorSubtype) {
976 		case UDESCSUB_VS_FORMAT_MJPEG:
977 			if (desc->bLength == 11) {
978 				(void)uvideo_vs_parse_desc_format_mjpeg(
979 				    sc, desc);
980 			}
981 			break;
982 		case UDESCSUB_VS_FORMAT_UNCOMPRESSED:
983 			if (desc->bLength == 27) {
984 				(void)uvideo_vs_parse_desc_format_uncompressed(
985 				    sc, desc);
986 			}
987 			break;
988 		}
989 
990 		desc = usbd_desc_iter_next(&iter);
991 	}
992 
993 	sc->sc_fmtgrp_idx = 0;
994 
995 	if (sc->sc_fmtgrp_num == 0) {
996 		printf("%s: no format descriptors found!\n", DEVNAME(sc));
997 		return (USBD_INVAL);
998 	}
999 	DPRINTF(1, "%s: number of total format descriptors=%d\n",
1000 	    DEVNAME(sc), sc->sc_fmtgrp_num);
1001 
1002 	return (USBD_NORMAL_COMPLETION);
1003 }
1004 
1005 usbd_status
uvideo_vs_parse_desc_format_mjpeg(struct uvideo_softc * sc,const usb_descriptor_t * desc)1006 uvideo_vs_parse_desc_format_mjpeg(struct uvideo_softc *sc,
1007     const usb_descriptor_t *desc)
1008 {
1009 	struct usb_video_format_mjpeg_desc *d;
1010 
1011 	d = (struct usb_video_format_mjpeg_desc *)(uint8_t *)desc;
1012 
1013 	if (d->bNumFrameDescriptors == 0) {
1014 		printf("%s: no MJPEG frame descriptors available!\n",
1015 		    DEVNAME(sc));
1016 		return (USBD_INVAL);
1017 	}
1018 
1019 	if (sc->sc_fmtgrp_idx >= UVIDEO_MAX_FORMAT) {
1020 		printf("%s: too many format descriptors found!\n", DEVNAME(sc));
1021 		return (USBD_INVAL);
1022 	}
1023 
1024 	sc->sc_fmtgrp[sc->sc_fmtgrp_idx].format =
1025 	    (struct uvideo_format_desc *)d;
1026 	if (d->bDefaultFrameIndex > d->bNumFrameDescriptors ||
1027 	    d->bDefaultFrameIndex < 1) {
1028 		/* sanitize wrong bDefaultFrameIndex value */
1029 		sc->sc_fmtgrp[sc->sc_fmtgrp_idx].format_dfidx = 1;
1030 	} else {
1031 		sc->sc_fmtgrp[sc->sc_fmtgrp_idx].format_dfidx =
1032 		    d->bDefaultFrameIndex;
1033 	}
1034 	sc->sc_fmtgrp[sc->sc_fmtgrp_idx].pixelformat = V4L2_PIX_FMT_MJPEG;
1035 
1036 	if (sc->sc_fmtgrp_cur == NULL)
1037 		/* set MJPEG format */
1038 		sc->sc_fmtgrp_cur = &sc->sc_fmtgrp[sc->sc_fmtgrp_idx];
1039 
1040 	sc->sc_fmtgrp_idx++;
1041 	sc->sc_fmtgrp_num++;
1042 
1043 	return (USBD_NORMAL_COMPLETION);
1044 }
1045 
1046 usbd_status
uvideo_vs_parse_desc_format_uncompressed(struct uvideo_softc * sc,const usb_descriptor_t * desc)1047 uvideo_vs_parse_desc_format_uncompressed(struct uvideo_softc *sc,
1048     const usb_descriptor_t *desc)
1049 {
1050 	struct usb_video_format_uncompressed_desc *d;
1051 	uint8_t guid_8bit_ir[16] = UVIDEO_FORMAT_GUID_KSMEDIA_L8_IR;
1052 	int i;
1053 
1054 	d = (struct usb_video_format_uncompressed_desc *)(uint8_t *)desc;
1055 
1056 	if (d->bNumFrameDescriptors == 0) {
1057 		printf("%s: no UNCOMPRESSED frame descriptors available!\n",
1058 		    DEVNAME(sc));
1059 		return (USBD_INVAL);
1060 	}
1061 
1062 	if (sc->sc_fmtgrp_idx >= UVIDEO_MAX_FORMAT) {
1063 		printf("%s: too many format descriptors found!\n", DEVNAME(sc));
1064 		return (USBD_INVAL);
1065 	}
1066 
1067 	sc->sc_fmtgrp[sc->sc_fmtgrp_idx].format =
1068 	    (struct uvideo_format_desc *)d;
1069 	if (d->bDefaultFrameIndex > d->bNumFrameDescriptors ||
1070 	    d->bDefaultFrameIndex < 1) {
1071 		/* sanitize wrong bDefaultFrameIndex value */
1072 		sc->sc_fmtgrp[sc->sc_fmtgrp_idx].format_dfidx = 1;
1073 	} else {
1074 		sc->sc_fmtgrp[sc->sc_fmtgrp_idx].format_dfidx =
1075 		    d->bDefaultFrameIndex;
1076 	}
1077 	i = sc->sc_fmtgrp_idx;
1078 	if (!strcmp(sc->sc_fmtgrp[i].format->u.uc.guidFormat, "YUY2")) {
1079 		sc->sc_fmtgrp[i].pixelformat = V4L2_PIX_FMT_YUYV;
1080 	} else if (!strcmp(sc->sc_fmtgrp[i].format->u.uc.guidFormat, "NV12")) {
1081 		sc->sc_fmtgrp[i].pixelformat = V4L2_PIX_FMT_NV12;
1082 	} else if (!strcmp(sc->sc_fmtgrp[i].format->u.uc.guidFormat, "UYVY")) {
1083 		sc->sc_fmtgrp[i].pixelformat = V4L2_PIX_FMT_UYVY;
1084 	} else if (!memcmp(sc->sc_fmtgrp[i].format->u.uc.guidFormat,
1085 	    guid_8bit_ir, 16)) {
1086 		sc->sc_fmtgrp[i].pixelformat = V4L2_PIX_FMT_GREY;
1087 	} else {
1088 		sc->sc_fmtgrp[i].pixelformat = 0;
1089 	}
1090 
1091 	if (sc->sc_fmtgrp_cur == NULL)
1092 		/* set UNCOMPRESSED format */
1093 		sc->sc_fmtgrp_cur = &sc->sc_fmtgrp[sc->sc_fmtgrp_idx];
1094 
1095 	sc->sc_fmtgrp_idx++;
1096 	sc->sc_fmtgrp_num++;
1097 
1098 	return (USBD_NORMAL_COMPLETION);
1099 }
1100 
1101 usbd_status
uvideo_vs_parse_desc_frame(struct uvideo_softc * sc)1102 uvideo_vs_parse_desc_frame(struct uvideo_softc *sc)
1103 {
1104 	struct usbd_desc_iter iter;
1105 	const usb_descriptor_t *desc;
1106 	usb_interface_descriptor_t *id;
1107 	usbd_status error;
1108 
1109 	DPRINTF(1, "%s: %s\n", DEVNAME(sc), __func__);
1110 
1111 	usbd_desc_iter_init(sc->sc_udev, &iter);
1112 	desc = usbd_desc_iter_next(&iter);
1113 	while (desc) {
1114 		/* Skip all interfaces until we found our first. */
1115 		if (desc->bDescriptorType == UDESC_INTERFACE) {
1116 			id = (usb_interface_descriptor_t *)desc;
1117 			if (id->bInterfaceNumber == sc->sc_iface)
1118 				break;
1119 		}
1120 		desc = usbd_desc_iter_next(&iter);
1121 	}
1122 	while (desc) {
1123 		/* Crossed device function boundary. */
1124 		if (desc->bDescriptorType == UDESC_IFACE_ASSOC)
1125 			break;
1126 		if (desc->bDescriptorType == UDESC_CS_INTERFACE &&
1127 		    desc->bLength > sizeof(struct usb_video_frame_desc) &&
1128 		    (desc->bDescriptorSubtype == UDESCSUB_VS_FRAME_MJPEG ||
1129 		    desc->bDescriptorSubtype == UDESCSUB_VS_FRAME_UNCOMPRESSED)) {
1130 			error = uvideo_vs_parse_desc_frame_sub(sc, desc);
1131 			if (error != USBD_NORMAL_COMPLETION)
1132 				return (error);
1133 		}
1134 		desc = usbd_desc_iter_next(&iter);
1135 	}
1136 
1137 	return (USBD_NORMAL_COMPLETION);
1138 }
1139 
1140 usbd_status
uvideo_vs_parse_desc_frame_sub(struct uvideo_softc * sc,const usb_descriptor_t * desc)1141 uvideo_vs_parse_desc_frame_sub(struct uvideo_softc *sc,
1142     const usb_descriptor_t *desc)
1143 {
1144 	struct usb_video_frame_desc *fd =
1145 	    (struct usb_video_frame_desc *)(uint8_t *)desc;
1146 	int fmtidx, frame_num;
1147 	uint32_t fbuf_size;
1148 
1149 	fmtidx = sc->sc_fmtgrp_idx;
1150 	frame_num = sc->sc_fmtgrp[fmtidx].frame_num;
1151 	if (frame_num >= UVIDEO_MAX_FRAME) {
1152 		printf("%s: too many %s frame descriptors found!\n",
1153 		    DEVNAME(sc),
1154 		    desc->bDescriptorSubtype == UDESCSUB_VS_FRAME_MJPEG ?
1155 		    "MJPEG" : "UNCOMPRESSED");
1156 		return (USBD_INVAL);
1157 	}
1158 	sc->sc_fmtgrp[fmtidx].frame[frame_num] = fd;
1159 
1160 	if (sc->sc_fmtgrp[fmtidx].frame_cur == NULL ||
1161 	    sc->sc_fmtgrp[fmtidx].format_dfidx == fd->bFrameIndex)
1162 		sc->sc_fmtgrp[fmtidx].frame_cur = fd;
1163 
1164 	/*
1165 	 * On some devices, dwMaxVideoFrameBufferSize is not correct.
1166 	 * Version 1.1 of the UVC spec says this field is deprecated.
1167 	 * For uncompressed pixel formats, the frame buffer size can
1168 	 * be determined by multiplying width, height, and bytes per pixel.
1169 	 * Uncompressed formats have a fixed number of bytes per pixel.
1170 	 * Bytes per pixel can vary with compressed formats.
1171 	 */
1172 	if (desc->bDescriptorSubtype == UDESCSUB_VS_FRAME_UNCOMPRESSED) {
1173 		fbuf_size = UGETW(fd->wWidth) * UGETW(fd->wHeight) *
1174 		    sc->sc_fmtgrp[fmtidx].format->u.uc.bBitsPerPixel / NBBY;
1175 		DPRINTF(10, "%s: %s: frame buffer size=%d "
1176 		    "width=%d height=%d bpp=%d\n", DEVNAME(sc), __func__,
1177 		    fbuf_size, UGETW(fd->wWidth), UGETW(fd->wHeight),
1178 		    sc->sc_fmtgrp[fmtidx].format->u.uc.bBitsPerPixel);
1179 	} else
1180 		fbuf_size = UGETDW(fd->dwMaxVideoFrameBufferSize);
1181 
1182 	/* store max value */
1183 	if (fbuf_size > sc->sc_max_fbuf_size)
1184 		sc->sc_max_fbuf_size = fbuf_size;
1185 
1186 	/*
1187 	 * Increment frame count.  If this is the last frame in the
1188 	 * format group, go on to next group.
1189 	 */
1190 	if (++sc->sc_fmtgrp[fmtidx].frame_num ==
1191 	    sc->sc_fmtgrp[fmtidx].format->bNumFrameDescriptors) {
1192 		sc->sc_fmtgrp_idx++;
1193 	}
1194 
1195 	return (USBD_NORMAL_COMPLETION);
1196 }
1197 
1198 usbd_status
uvideo_vs_parse_desc_alt(struct uvideo_softc * sc,int vs_nr,int iface,int numalts)1199 uvideo_vs_parse_desc_alt(struct uvideo_softc *sc, int vs_nr, int iface, int numalts)
1200 {
1201 	struct uvideo_vs_iface *vs;
1202 	struct usbd_desc_iter iter;
1203 	const usb_descriptor_t *desc;
1204 	usb_interface_descriptor_t *id;
1205 	usb_endpoint_descriptor_t *ed;
1206 	uint8_t ep_dir, ep_type;
1207 
1208 	vs = &sc->sc_vs_coll[vs_nr];
1209 
1210 	usbd_desc_iter_init(sc->sc_udev, &iter);
1211 	desc = usbd_desc_iter_next(&iter);
1212 	while (desc) {
1213 		/* Skip all interfaces until we found our first. */
1214 		if (desc->bDescriptorType == UDESC_INTERFACE) {
1215 			id = (usb_interface_descriptor_t *)desc;
1216 			if (id->bInterfaceNumber == sc->sc_iface)
1217 				break;
1218 		}
1219 		desc = usbd_desc_iter_next(&iter);
1220 	}
1221 	while (desc) {
1222 		/* Crossed device function boundary. */
1223 		if (desc->bDescriptorType == UDESC_IFACE_ASSOC)
1224 			break;
1225 		/* find video stream interface */
1226 		if (desc->bDescriptorType != UDESC_INTERFACE)
1227 			goto next;
1228 		id = (usb_interface_descriptor_t *)(uint8_t *)desc;
1229 		if (id->bInterfaceNumber != iface)
1230 			goto next;
1231 		DPRINTF(1, "%s: bAlternateSetting=0x%02x, ",
1232 		    DEVNAME(sc), id->bAlternateSetting);
1233 		if (id->bNumEndpoints == 0) {
1234 			DPRINTF(1, "no endpoint descriptor\n");
1235 			goto next;
1236 		}
1237 
1238 		/* jump to corresponding endpoint descriptor */
1239 		while ((desc = usbd_desc_iter_next(&iter))) {
1240 			if (desc->bDescriptorType == UDESC_ENDPOINT)
1241 				break;
1242 		}
1243 		ed = (usb_endpoint_descriptor_t *)(uint8_t *)desc;
1244 		DPRINTF(1, "bEndpointAddress=0x%02x, ", ed->bEndpointAddress);
1245 		DPRINTF(1, "wMaxPacketSize=%d\n", UGETW(ed->wMaxPacketSize));
1246 
1247 		/* locate endpoint type */
1248 		ep_dir = UE_GET_DIR(ed->bEndpointAddress);
1249 		ep_type = UE_GET_XFERTYPE(ed->bmAttributes);
1250 		if (ep_dir == UE_DIR_IN && ep_type == UE_ISOCHRONOUS)
1251 			vs->bulk_endpoint = 0;
1252 		else if (ep_dir == UE_DIR_IN && ep_type == UE_BULK)
1253 			vs->bulk_endpoint = 1;
1254 		else
1255 			goto next;
1256 
1257 		/* save endpoint with largest bandwidth */
1258 		if (UGETW(ed->wMaxPacketSize) > vs->psize) {
1259 			vs->ifaceh = &sc->sc_udev->ifaces[iface];
1260 			vs->endpoint = ed->bEndpointAddress;
1261 			vs->numalts = numalts;
1262 			vs->curalt = id->bAlternateSetting;
1263 			vs->psize = UGETW(ed->wMaxPacketSize);
1264 			vs->iface = iface;
1265 		}
1266 next:
1267 		desc = usbd_desc_iter_next(&iter);
1268 	}
1269 
1270 	/* check if we have found a valid alternate interface */
1271 	if (vs->ifaceh == NULL) {
1272 		printf("%s: no valid alternate interface found!\n",
1273 		    DEVNAME(sc));
1274 		return (USBD_INVAL);
1275 	}
1276 
1277 	return (USBD_NORMAL_COMPLETION);
1278 }
1279 
1280 usbd_status
uvideo_vs_set_alt(struct uvideo_softc * sc,struct usbd_interface * ifaceh,int max_packet_size)1281 uvideo_vs_set_alt(struct uvideo_softc *sc, struct usbd_interface *ifaceh,
1282     int max_packet_size)
1283 {
1284 	struct usbd_desc_iter iter;
1285 	const usb_descriptor_t *desc;
1286 	usb_interface_descriptor_t *id;
1287 	usb_endpoint_descriptor_t *ed;
1288 	int diff, best_diff = INT_MAX;
1289 	usbd_status error;
1290 	uint32_t psize;
1291 
1292 	usbd_desc_iter_init(sc->sc_udev, &iter);
1293 	desc = usbd_desc_iter_next(&iter);
1294 	while (desc) {
1295 		/* Skip all interfaces until we found our first. */
1296 		if (desc->bDescriptorType == UDESC_INTERFACE) {
1297 			id = (usb_interface_descriptor_t *)desc;
1298 			if (id->bInterfaceNumber == sc->sc_iface)
1299 				break;
1300 		}
1301 		desc = usbd_desc_iter_next(&iter);
1302 	}
1303 	while (desc) {
1304 		/* Crossed device function boundary. */
1305 		if (desc->bDescriptorType == UDESC_IFACE_ASSOC)
1306 			break;
1307 		/* find video stream interface */
1308 		if (desc->bDescriptorType != UDESC_INTERFACE)
1309 			goto next;
1310 		id = (usb_interface_descriptor_t *)(uint8_t *)desc;
1311 		if (id->bInterfaceNumber != sc->sc_vs_cur->iface)
1312 			goto next;
1313 		if (id->bNumEndpoints == 0)
1314 			goto next;
1315 
1316 		/* jump to corresponding endpoint descriptor */
1317 		desc = usbd_desc_iter_next(&iter);
1318 		if (desc->bDescriptorType != UDESC_ENDPOINT)
1319 			goto next;
1320 		ed = (usb_endpoint_descriptor_t *)(uint8_t *)desc;
1321 
1322 		/* save endpoint with requested bandwidth */
1323 		psize = UGETW(ed->wMaxPacketSize);
1324 		psize = UE_GET_SIZE(psize) * (1 + UE_GET_TRANS(psize));
1325 		if (psize >= max_packet_size)
1326 			diff = psize - max_packet_size;
1327 		else
1328 			goto next;
1329 		if (diff < best_diff) {
1330 			best_diff = diff;
1331 			sc->sc_vs_cur->endpoint = ed->bEndpointAddress;
1332 			sc->sc_vs_cur->curalt = id->bAlternateSetting;
1333 			sc->sc_vs_cur->psize = psize;
1334 			if (diff == 0)
1335 				break;
1336 		}
1337 next:
1338 		desc = usbd_desc_iter_next(&iter);
1339 	}
1340 
1341 	DPRINTF(1, "%s: set alternate iface to ", DEVNAME(sc));
1342 	DPRINTF(1, "bAlternateSetting=0x%02x psize=%d max_packet_size=%d\n",
1343 	    sc->sc_vs_cur->curalt, sc->sc_vs_cur->psize, max_packet_size);
1344 
1345 	/* set alternate video stream interface */
1346 	error = usbd_set_interface(ifaceh, sc->sc_vs_cur->curalt);
1347 	if (error) {
1348 		printf("%s: could not set alternate interface %d!\n",
1349 		    DEVNAME(sc), sc->sc_vs_cur->curalt);
1350 		return (USBD_INVAL);
1351 	}
1352 
1353 	return (USBD_NORMAL_COMPLETION);
1354 }
1355 
1356 /*
1357  * Thanks to the retarded USB Video Class specs there are different
1358  * descriptors types with the same bDescriptorSubtype which makes
1359  * it necessary to differ between those types by doing descriptor
1360  * size dances :-(
1361  *
1362  * size_fix:		total size of the fixed structure part
1363  * off_num_elements:	offset which tells the number of following elements
1364  * size_element:	size of a single element
1365  * off_size_element:	if size_element is 0 the element size is taken from
1366  *			this offset in the descriptor
1367  */
1368 int
uvideo_desc_len(const usb_descriptor_t * desc,int size_fix,int off_num_elements,int size_element,int off_size_element)1369 uvideo_desc_len(const usb_descriptor_t *desc,
1370     int size_fix, int off_num_elements, int size_element, int off_size_element)
1371 {
1372 	uint8_t *buf;
1373 	int size_elements, size_total;
1374 
1375 	if (desc->bLength < size_fix)
1376 		return (0);
1377 
1378 	buf = (uint8_t *)desc;
1379 
1380 	if (size_element == 0)
1381 		size_element = buf[off_size_element];
1382 
1383 	size_elements = buf[off_num_elements] * size_element;
1384 	size_total = size_fix + size_elements;
1385 
1386 	if (desc->bLength == size_total && size_elements != 0)
1387 		return (1);
1388 
1389 	return (0);
1390 }
1391 
1392 /*
1393  * Find the next best matching resolution which we can offer and
1394  * return it.
1395  */
1396 void
uvideo_find_res(struct uvideo_softc * sc,int idx,int width,int height,struct uvideo_res * r)1397 uvideo_find_res(struct uvideo_softc *sc, int idx, int width, int height,
1398     struct uvideo_res *r)
1399 {
1400 	int i, w, h, diff, diff_best, size_want, size_is;
1401 
1402 	size_want = width * height;
1403 
1404 	for (i = 0; i < sc->sc_fmtgrp[idx].frame_num; i++) {
1405 		w = UGETW(sc->sc_fmtgrp[idx].frame[i]->wWidth);
1406 		h = UGETW(sc->sc_fmtgrp[idx].frame[i]->wHeight);
1407 		size_is = w * h;
1408 		if (size_is > size_want)
1409 			diff = size_is - size_want;
1410 		else
1411 			diff = size_want - size_is;
1412 		if (i == 0)
1413 			diff_best = diff;
1414 		if (diff <= diff_best) {
1415 			diff_best = diff;
1416 			r->width = w;
1417 			r->height = h;
1418 			r->fidx = i;
1419 		}
1420 		DPRINTF(1, "%s: %s: frame index %d: width=%d, height=%d\n",
1421 		    DEVNAME(sc), __func__, i, w, h);
1422 	}
1423 }
1424 
1425 usbd_status
uvideo_vs_negotiation(struct uvideo_softc * sc,int commit)1426 uvideo_vs_negotiation(struct uvideo_softc *sc, int commit)
1427 {
1428 	struct usb_video_probe_commit *pc;
1429 	struct uvideo_format_group *fmtgrp;
1430 	struct usb_video_header_desc *hd;
1431 	struct usb_video_frame_desc *frame;
1432 	uint8_t *p, *cur;
1433 	uint8_t probe_data[48];
1434 	uint32_t frame_ival, nivals, min, max, step, diff;
1435 	usbd_status error;
1436 	int i, ival_bytes, changed = 0;
1437 
1438 	pc = (struct usb_video_probe_commit *)probe_data;
1439 
1440 	fmtgrp = sc->sc_fmtgrp_cur;
1441 
1442 	/* check if the format descriptor contains frame descriptors */
1443 	if (fmtgrp->frame_num == 0) {
1444 		printf("%s: %s: no frame descriptors found!\n",
1445 		    __func__, DEVNAME(sc));
1446 		return (USBD_INVAL);
1447 	}
1448 
1449 	/* set probe */
1450 	bzero(probe_data, sizeof(probe_data));
1451 	/* hint that dwFrameInterval should be favored over other parameters */
1452 	USETW(pc->bmHint, 0x1);
1453 	pc->bFormatIndex = fmtgrp->format->bFormatIndex;
1454 	pc->bFrameIndex = fmtgrp->frame_cur->bFrameIndex;
1455 	/* dwFrameInterval: 30fps=333333, 15fps=666666, 10fps=1000000 */
1456 	frame_ival = UGETDW(fmtgrp->frame_cur->dwDefaultFrameInterval);
1457 	if (sc->sc_frame_rate != 0) {
1458 		frame_ival = 10000000 / sc->sc_frame_rate;
1459 		/* find closest matching interval the device supports */
1460 		p = (uint8_t *)fmtgrp->frame_cur;
1461 		p += sizeof(struct usb_video_frame_desc);
1462 		nivals = fmtgrp->frame_cur->bFrameIntervalType;
1463 		ival_bytes = fmtgrp->frame_cur->bLength -
1464 		    sizeof(struct usb_video_frame_desc);
1465 		if (!nivals && (ival_bytes >= sizeof(uDWord) * 3)) {
1466 			/* continuous */
1467 			min = UGETDW(p);
1468 			p += sizeof(uDWord);
1469 			max = UGETDW(p);
1470 			p += sizeof(uDWord);
1471 			step = UGETDW(p);
1472 			p += sizeof(uDWord);
1473 			if (frame_ival <= min)
1474 				frame_ival = min;
1475 			else if (frame_ival >= max)
1476 				frame_ival = max;
1477 			else {
1478 				for (i = min; i + step/2 < frame_ival; i+= step)
1479 					;	/* nothing */
1480 				frame_ival = i;
1481 			}
1482 		} else if (nivals > 0 && ival_bytes >= sizeof(uDWord)) {
1483 			/* discrete */
1484 			cur = p;
1485 			min = UINT_MAX;
1486 			for (i = 0; i < nivals; i++) {
1487 				if (ival_bytes < sizeof(uDWord)) {
1488 					/* short descriptor ? */
1489 					break;
1490 				}
1491 				diff = abs(UGETDW(p) - frame_ival);
1492 				if (diff < min) {
1493 					min = diff;
1494 					cur = p;
1495 					if (diff == 0)
1496 						break;
1497 				}
1498 				p += sizeof(uDWord);
1499 				ival_bytes -= sizeof(uDWord);
1500 			}
1501 			frame_ival = UGETDW(cur);
1502 		} else {
1503 			DPRINTF(1, "%s: %s: bad frame ival descriptor\n",
1504 			    DEVNAME(sc), __func__);
1505 		}
1506 	}
1507 	USETDW(pc->dwFrameInterval, frame_ival);
1508 	error = uvideo_vs_set_probe(sc, probe_data);
1509 	if (error != USBD_NORMAL_COMPLETION)
1510 		return (error);
1511 
1512 	/* get probe */
1513 	bzero(probe_data, sizeof(probe_data));
1514 	error = uvideo_vs_get_probe(sc, probe_data, GET_CUR);
1515 	if (error != USBD_NORMAL_COMPLETION)
1516 		return (error);
1517 
1518 	/* check that the format and frame indexes are what we wanted */
1519 	if (pc->bFormatIndex != fmtgrp->format->bFormatIndex) {
1520 		changed++;
1521 		DPRINTF(1, "%s: %s: wanted format 0x%x, got format 0x%x\n",
1522 		    DEVNAME(sc), __func__, fmtgrp->format->bFormatIndex,
1523 		    pc->bFormatIndex);
1524 		for (i = 0; i < sc->sc_fmtgrp_num; i++) {
1525 			if (sc->sc_fmtgrp[i].format->bFormatIndex ==
1526 			    pc->bFormatIndex) {
1527 				fmtgrp = &sc->sc_fmtgrp[i];
1528 				break;
1529 			}
1530 		}
1531 		if (i == sc->sc_fmtgrp_num) {
1532 			DPRINTF(1, "%s: %s: invalid format index 0x%x\n",
1533 			    DEVNAME(sc), __func__, pc->bFormatIndex);
1534 			return (USBD_INVAL);
1535 		}
1536 	}
1537 	if (pc->bFrameIndex != fmtgrp->frame_cur->bFrameIndex) {
1538 		changed++;
1539 		DPRINTF(1, "%s: %s: wanted frame 0x%x, got frame 0x%x\n",
1540 		    DEVNAME(sc), __func__, fmtgrp->frame_cur->bFrameIndex,
1541 		    pc->bFrameIndex);
1542 		for (i = 0; i < fmtgrp->frame_num; i++) {
1543 			if (fmtgrp->frame[i]->bFrameIndex == pc->bFrameIndex) {
1544 				frame = fmtgrp->frame[i];
1545 				break;
1546 			}
1547 		}
1548 		if (i == fmtgrp->frame_num) {
1549 			DPRINTF(1, "%s: %s: invalid frame index 0x%x\n",
1550 			    DEVNAME(sc), __func__, pc->bFrameIndex);
1551 			return (USBD_INVAL);
1552 		}
1553 	} else
1554 		frame = fmtgrp->frame_cur;
1555 
1556 	/*
1557 	 * Uncompressed formats have fixed bits per pixel, which means
1558 	 * the frame buffer size is fixed and can be calculated.  Because
1559 	 * some devices return incorrect values, always override the
1560 	 * the frame size with a calculated value.
1561 	 */
1562 	if (frame->bDescriptorSubtype == UDESCSUB_VS_FRAME_UNCOMPRESSED) {
1563 		USETDW(pc->dwMaxVideoFrameSize,
1564 		    UGETW(frame->wWidth) * UGETW(frame->wHeight) *
1565 		    fmtgrp->format->u.uc.bBitsPerPixel / NBBY);
1566 		DPRINTF(1, "fixed dwMaxVideoFrameSize=%d, "
1567 		    "width=%d height=%d bpp=%d\n",
1568 		    UGETDW(pc->dwMaxVideoFrameSize),
1569 		    UGETW(frame->wWidth), UGETW(frame->wHeight),
1570 		    fmtgrp->format->u.uc.bBitsPerPixel);
1571 	} else {
1572 		/*
1573 		 * Some UVC 1.00 devices return dwMaxVideoFrameSize = 0.
1574 		 * If so, fix it by format/frame descriptors.
1575 		 */
1576 		hd = sc->sc_desc_vc_header.fix;
1577 		if (UGETDW(pc->dwMaxVideoFrameSize) == 0 &&
1578 		    UGETW(hd->bcdUVC) < 0x0110 ) {
1579 			DPRINTF(1, "%s: dwMaxVideoFrameSize == 0, fixed\n",
1580 			    DEVNAME(sc));
1581 			USETDW(pc->dwMaxVideoFrameSize,
1582 			    UGETDW(frame->dwMaxVideoFrameBufferSize));
1583 		}
1584 	}
1585 
1586 	/* commit */
1587 	if (commit) {
1588 		if (changed > 0) {
1589 			/* didn't get the frame format or size we wanted */
1590 			return (USBD_INVAL);
1591 		}
1592 		error = uvideo_vs_set_commit(sc, probe_data);
1593 		if (error != USBD_NORMAL_COMPLETION)
1594 			return (error);
1595 	}
1596 
1597 	/* save a copy of probe commit */
1598 	bcopy(pc, &sc->sc_desc_probe, sizeof(sc->sc_desc_probe));
1599 
1600 	return (USBD_NORMAL_COMPLETION);
1601 }
1602 
1603 usbd_status
uvideo_vs_set_probe(struct uvideo_softc * sc,uint8_t * probe_data)1604 uvideo_vs_set_probe(struct uvideo_softc *sc, uint8_t *probe_data)
1605 {
1606 	usb_device_request_t req;
1607 	usbd_status error;
1608 	uint16_t tmp;
1609 	struct usb_video_probe_commit *pc;
1610 
1611 	req.bmRequestType = UVIDEO_SET_IF;
1612 	req.bRequest = SET_CUR;
1613 	tmp = VS_PROBE_CONTROL;
1614 	tmp = tmp << 8;
1615 	USETW(req.wValue, tmp);
1616 	USETW(req.wIndex, sc->sc_vs_cur->iface);
1617 	USETW(req.wLength, sc->sc_max_ctrl_size);
1618 
1619 	pc = (struct usb_video_probe_commit *)probe_data;
1620 
1621 	error = usbd_do_request(sc->sc_udev, &req, probe_data);
1622 	if (error) {
1623 		printf("%s: could not SET probe request: %s\n",
1624 		    DEVNAME(sc), usbd_errstr(error));
1625 		return (USBD_INVAL);
1626 	}
1627 	DPRINTF(1, "%s: SET probe request successfully\n", DEVNAME(sc));
1628 
1629 	DPRINTF(1, "bmHint=0x%02x\n", UGETW(pc->bmHint));
1630 	DPRINTF(1, "bFormatIndex=0x%02x\n", pc->bFormatIndex);
1631 	DPRINTF(1, "bFrameIndex=0x%02x\n", pc->bFrameIndex);
1632 	DPRINTF(1, "dwFrameInterval=%d (100ns units)\n",
1633 	    UGETDW(pc->dwFrameInterval));
1634 	DPRINTF(1, "wKeyFrameRate=%d\n", UGETW(pc->wKeyFrameRate));
1635 	DPRINTF(1, "wPFrameRate=%d\n", UGETW(pc->wPFrameRate));
1636 	DPRINTF(1, "wCompQuality=%d\n", UGETW(pc->wCompQuality));
1637 	DPRINTF(1, "wCompWindowSize=%d\n", UGETW(pc->wCompWindowSize));
1638 	DPRINTF(1, "wDelay=%d (ms)\n", UGETW(pc->wDelay));
1639 	DPRINTF(1, "dwMaxVideoFrameSize=%d (bytes)\n",
1640 	    UGETDW(pc->dwMaxVideoFrameSize));
1641 	DPRINTF(1, "dwMaxPayloadTransferSize=%d (bytes)\n",
1642 	    UGETDW(pc->dwMaxPayloadTransferSize));
1643 
1644 	return (USBD_NORMAL_COMPLETION);
1645 }
1646 
1647 usbd_status
uvideo_vs_get_probe(struct uvideo_softc * sc,uint8_t * probe_data,uint8_t request)1648 uvideo_vs_get_probe(struct uvideo_softc *sc, uint8_t *probe_data,
1649     uint8_t request)
1650 {
1651 	usb_device_request_t req;
1652 	usbd_status error;
1653 	uint16_t tmp;
1654 	struct usb_video_probe_commit *pc;
1655 
1656 	req.bmRequestType = UVIDEO_GET_IF;
1657 	req.bRequest = request;
1658 	tmp = VS_PROBE_CONTROL;
1659 	tmp = tmp << 8;
1660 	USETW(req.wValue, tmp);
1661 	USETW(req.wIndex, sc->sc_vs_cur->iface);
1662 	USETW(req.wLength, sc->sc_max_ctrl_size);
1663 
1664 	pc = (struct usb_video_probe_commit *)probe_data;
1665 
1666 	error = usbd_do_request(sc->sc_udev, &req, probe_data);
1667 	if (error) {
1668 		printf("%s: could not GET probe request: %s\n",
1669 		    DEVNAME(sc), usbd_errstr(error));
1670 		return (USBD_INVAL);
1671 	}
1672 	DPRINTF(1, "%s: GET probe request successfully\n", DEVNAME(sc));
1673 
1674 	DPRINTF(1, "bmHint=0x%02x\n", UGETW(pc->bmHint));
1675 	DPRINTF(1, "bFormatIndex=0x%02x\n", pc->bFormatIndex);
1676 	DPRINTF(1, "bFrameIndex=0x%02x\n", pc->bFrameIndex);
1677 	DPRINTF(1, "dwFrameInterval=%d (100ns units)\n",
1678 	    UGETDW(pc->dwFrameInterval));
1679 	DPRINTF(1, "wKeyFrameRate=%d\n", UGETW(pc->wKeyFrameRate));
1680 	DPRINTF(1, "wPFrameRate=%d\n", UGETW(pc->wPFrameRate));
1681 	DPRINTF(1, "wCompQuality=%d\n", UGETW(pc->wCompQuality));
1682 	DPRINTF(1, "wCompWindowSize=%d\n", UGETW(pc->wCompWindowSize));
1683 	DPRINTF(1, "wDelay=%d (ms)\n", UGETW(pc->wDelay));
1684 	DPRINTF(1, "dwMaxVideoFrameSize=%d (bytes)\n",
1685 	    UGETDW(pc->dwMaxVideoFrameSize));
1686 	DPRINTF(1, "dwMaxPayloadTransferSize=%d (bytes)\n",
1687 	    UGETDW(pc->dwMaxPayloadTransferSize));
1688 
1689 	return (USBD_NORMAL_COMPLETION);
1690 }
1691 
1692 usbd_status
uvideo_vs_set_commit(struct uvideo_softc * sc,uint8_t * probe_data)1693 uvideo_vs_set_commit(struct uvideo_softc *sc, uint8_t *probe_data)
1694 {
1695 	usb_device_request_t req;
1696 	usbd_status error;
1697 	uint16_t tmp;
1698 
1699 	req.bmRequestType = UVIDEO_SET_IF;
1700 	req.bRequest = SET_CUR;
1701 	tmp = VS_COMMIT_CONTROL;
1702 	tmp = tmp << 8;
1703 	USETW(req.wValue, tmp);
1704 	USETW(req.wIndex, sc->sc_vs_cur->iface);
1705 	USETW(req.wLength, sc->sc_max_ctrl_size);
1706 
1707 	error = usbd_do_request(sc->sc_udev, &req, probe_data);
1708 	if (error) {
1709 		printf("%s: could not SET commit request: %s\n",
1710 		    DEVNAME(sc), usbd_errstr(error));
1711 		return (USBD_INVAL);
1712 	}
1713 	DPRINTF(1, "%s: SET commit request successfully\n", DEVNAME(sc));
1714 
1715 	return (USBD_NORMAL_COMPLETION);
1716 }
1717 
1718 usbd_status
uvideo_vs_alloc_frame(struct uvideo_softc * sc)1719 uvideo_vs_alloc_frame(struct uvideo_softc *sc)
1720 {
1721 	struct uvideo_frame_buffer *fb = &sc->sc_frame_buffer;
1722 
1723 	fb->buf_size = UGETDW(sc->sc_desc_probe.dwMaxVideoFrameSize);
1724 
1725 	/* don't overflow the upper layer frame buffer */
1726 	if (sc->sc_max_fbuf_size < fb->buf_size &&
1727 	    sc->sc_mmap_flag == 0) {
1728 		printf("%s: software video buffer is too small!\n",
1729 		    DEVNAME(sc));
1730 		return (USBD_NOMEM);
1731 	}
1732 
1733 	fb->buf = malloc(fb->buf_size, M_USBDEV, M_NOWAIT);
1734 	if (fb->buf == NULL) {
1735 		printf("%s: can't allocate frame buffer!\n", DEVNAME(sc));
1736 		return (USBD_NOMEM);
1737 	}
1738 
1739 	DPRINTF(1, "%s: %s: allocated %d bytes frame buffer\n",
1740 	    DEVNAME(sc), __func__, fb->buf_size);
1741 
1742 	fb->sample = 0;
1743 	fb->fid = 0;
1744 	fb->offset = 0;
1745 	fb->fmt_flags = sc->sc_fmtgrp_cur->frame_cur->bDescriptorSubtype ==
1746 	    UDESCSUB_VS_FRAME_UNCOMPRESSED ? 0 : V4L2_FMT_FLAG_COMPRESSED;
1747 
1748 	return (USBD_NORMAL_COMPLETION);
1749 }
1750 
1751 void
uvideo_vs_free_frame(struct uvideo_softc * sc)1752 uvideo_vs_free_frame(struct uvideo_softc *sc)
1753 {
1754 	struct uvideo_frame_buffer *fb = &sc->sc_frame_buffer;
1755 
1756 	if (fb->buf != NULL) {
1757 		free(fb->buf, M_USBDEV, fb->buf_size);
1758 		fb->buf = NULL;
1759 	}
1760 
1761 	if (sc->sc_mmap_buffer != NULL) {
1762 		free(sc->sc_mmap_buffer, M_USBDEV, sc->sc_mmap_buffer_size);
1763 		sc->sc_mmap_buffer = NULL;
1764 		sc->sc_mmap_buffer_size = 0;
1765 	}
1766 
1767 	while (!SIMPLEQ_EMPTY(&sc->sc_mmap_q))
1768 		SIMPLEQ_REMOVE_HEAD(&sc->sc_mmap_q, q_frames);
1769 
1770 	sc->sc_mmap_count = 0;
1771 }
1772 
1773 usbd_status
uvideo_vs_alloc_isoc(struct uvideo_softc * sc)1774 uvideo_vs_alloc_isoc(struct uvideo_softc *sc)
1775 {
1776 	int size, i;
1777 
1778 	DPRINTF(1, "%s: %s\n", DEVNAME(sc), __func__);
1779 
1780 	for (i = 0; i < UVIDEO_IXFERS; i++) {
1781 		sc->sc_vs_cur->ixfer[i].sc = sc;
1782 
1783 		sc->sc_vs_cur->ixfer[i].xfer = usbd_alloc_xfer(sc->sc_udev);
1784 		if (sc->sc_vs_cur->ixfer[i].xfer == NULL) {
1785 			printf("%s: could not allocate isoc VS xfer!\n",
1786 			    DEVNAME(sc));
1787 			return (USBD_NOMEM);
1788 		}
1789 
1790 		size = sc->sc_vs_cur->psize * sc->sc_nframes;
1791 
1792 		sc->sc_vs_cur->ixfer[i].buf =
1793 		    usbd_alloc_buffer(sc->sc_vs_cur->ixfer[i].xfer, size);
1794 		if (sc->sc_vs_cur->ixfer[i].buf == NULL) {
1795 			printf("%s: could not allocate isoc VS buffer!\n",
1796 			    DEVNAME(sc));
1797 			return (USBD_NOMEM);
1798 		}
1799 		DPRINTF(1, "%s: allocated %d bytes isoc VS xfer buffer\n",
1800 		    DEVNAME(sc), size);
1801 	}
1802 
1803 	return (USBD_NORMAL_COMPLETION);
1804 }
1805 
1806 usbd_status
uvideo_vs_alloc_bulk(struct uvideo_softc * sc)1807 uvideo_vs_alloc_bulk(struct uvideo_softc *sc)
1808 {
1809 	int size;
1810 
1811 	sc->sc_vs_cur->bxfer.sc = sc;
1812 
1813 	sc->sc_vs_cur->bxfer.xfer = usbd_alloc_xfer(sc->sc_udev);
1814 	if (sc->sc_vs_cur->bxfer.xfer == NULL) {
1815 		printf("%s: could not allocate bulk VS xfer!\n",
1816 		    DEVNAME(sc));
1817 		return (USBD_NOMEM);
1818 	}
1819 
1820 	size = UGETDW(sc->sc_desc_probe.dwMaxPayloadTransferSize);
1821 
1822 	sc->sc_vs_cur->bxfer.buf =
1823 	    usbd_alloc_buffer(sc->sc_vs_cur->bxfer.xfer, size);
1824 	if (sc->sc_vs_cur->bxfer.buf == NULL) {
1825 		printf("%s: could not allocate bulk VS buffer!\n",
1826 		    DEVNAME(sc));
1827 		return (USBD_NOMEM);
1828 	}
1829 	DPRINTF(1, "%s: allocated %d bytes bulk VS xfer buffer\n",
1830 	    DEVNAME(sc), size);
1831 
1832 	return (USBD_NORMAL_COMPLETION);
1833 }
1834 
1835 void
uvideo_vs_free_isoc(struct uvideo_softc * sc)1836 uvideo_vs_free_isoc(struct uvideo_softc *sc)
1837 {
1838 	int i;
1839 
1840 	DPRINTF(1, "%s: %s\n", DEVNAME(sc), __func__);
1841 
1842 	for (i = 0; i < UVIDEO_IXFERS; i++) {
1843 		if (sc->sc_vs_cur->ixfer[i].buf != NULL) {
1844 			usbd_free_buffer(sc->sc_vs_cur->ixfer[i].xfer);
1845 			sc->sc_vs_cur->ixfer[i].buf = NULL;
1846 		}
1847 
1848 		if (sc->sc_vs_cur->ixfer[i].xfer != NULL) {
1849 			usbd_free_xfer(sc->sc_vs_cur->ixfer[i].xfer);
1850 			sc->sc_vs_cur->ixfer[i].xfer = NULL;
1851 		}
1852 	}
1853 }
1854 
1855 void
uvideo_vs_free_bulk(struct uvideo_softc * sc)1856 uvideo_vs_free_bulk(struct uvideo_softc *sc)
1857 {
1858 	if (sc->sc_vs_cur->bxfer.buf != NULL) {
1859 		usbd_free_buffer(sc->sc_vs_cur->bxfer.xfer);
1860 		sc->sc_vs_cur->bxfer.buf = NULL;
1861 	}
1862 
1863 	if (sc->sc_vs_cur->bxfer.xfer != NULL) {
1864 		usbd_free_xfer(sc->sc_vs_cur->bxfer.xfer);
1865 		sc->sc_vs_cur->bxfer.xfer = NULL;
1866 	}
1867 }
1868 
1869 usbd_status
uvideo_vs_open(struct uvideo_softc * sc)1870 uvideo_vs_open(struct uvideo_softc *sc)
1871 {
1872 	usb_endpoint_descriptor_t *ed;
1873 	usbd_status error;
1874 	uint32_t dwMaxVideoFrameSize;
1875 
1876 	DPRINTF(1, "%s: %s\n", DEVNAME(sc), __func__);
1877 
1878 	if (sc->sc_negotiated_flag == 0) {
1879 		/* do device negotiation with commit */
1880 		error = uvideo_vs_negotiation(sc, 1);
1881 		if (error != USBD_NORMAL_COMPLETION)
1882 			return (error);
1883 	}
1884 
1885 	error = uvideo_vs_set_alt(sc, sc->sc_vs_cur->ifaceh,
1886 	    UGETDW(sc->sc_desc_probe.dwMaxPayloadTransferSize));
1887 	if (error != USBD_NORMAL_COMPLETION) {
1888 		printf("%s: could not set alternate interface!\n",
1889 		    DEVNAME(sc));
1890 		return (error);
1891 	}
1892 
1893 	/* double check if we can access the selected endpoint descriptor */
1894 	ed = usbd_get_endpoint_descriptor(sc->sc_vs_cur->ifaceh,
1895 	    sc->sc_vs_cur->endpoint);
1896 	if (ed == NULL) {
1897 		printf("%s: no endpoint descriptor for VS iface\n",
1898 		    DEVNAME(sc));
1899 		return (USBD_INVAL);
1900 	}
1901 
1902 	DPRINTF(1, "%s: open pipe for bEndpointAddress=0x%02x\n",
1903 	    DEVNAME(sc), sc->sc_vs_cur->endpoint);
1904 	error = usbd_open_pipe(
1905 	    sc->sc_vs_cur->ifaceh,
1906 	    sc->sc_vs_cur->endpoint,
1907 	    USBD_EXCLUSIVE_USE,
1908 	    &sc->sc_vs_cur->pipeh);
1909 	if (error != USBD_NORMAL_COMPLETION) {
1910 		printf("%s: could not open VS pipe: %s\n",
1911 		    DEVNAME(sc), usbd_errstr(error));
1912 		return (error);
1913 	}
1914 
1915 	/* calculate optimal isoc xfer size */
1916 	if (strcmp(sc->sc_udev->bus->bdev.dv_cfdata->cf_driver->cd_name,
1917 	    "ohci") == 0) {
1918 		/* ohci workaround */
1919 		sc->sc_nframes = 8;
1920 	} else {
1921 		dwMaxVideoFrameSize =
1922 		    UGETDW(sc->sc_desc_probe.dwMaxVideoFrameSize);
1923 		sc->sc_nframes = (dwMaxVideoFrameSize + sc->sc_vs_cur->psize -
1924 		    1) / sc->sc_vs_cur->psize;
1925 	}
1926 	if (sc->sc_nframes > UVIDEO_NFRAMES_MAX)
1927 		sc->sc_nframes = UVIDEO_NFRAMES_MAX;
1928 	DPRINTF(1, "%s: nframes=%d\n", DEVNAME(sc), sc->sc_nframes);
1929 
1930 	return (USBD_NORMAL_COMPLETION);
1931 }
1932 
1933 void
uvideo_vs_close(struct uvideo_softc * sc)1934 uvideo_vs_close(struct uvideo_softc *sc)
1935 {
1936 	if (sc->sc_vs_cur->bulk_running == 1) {
1937 		sc->sc_vs_cur->bulk_running = 0;
1938 		usbd_ref_wait(sc->sc_udev);
1939 	}
1940 
1941 	if (sc->sc_vs_cur->pipeh) {
1942 		usbd_close_pipe(sc->sc_vs_cur->pipeh);
1943 		sc->sc_vs_cur->pipeh = NULL;
1944 	}
1945 
1946 	/*
1947 	 * Some devices need time to shutdown before we switch back to
1948 	 * the default interface (0).  Not doing so can leave the device
1949 	 * back in a undefined condition.
1950 	 */
1951 	usbd_delay_ms(sc->sc_udev, 100);
1952 
1953 	/* switch back to default interface (turns off cam LED) */
1954 	(void)usbd_set_interface(sc->sc_vs_cur->ifaceh, 0);
1955 }
1956 
1957 usbd_status
uvideo_vs_init(struct uvideo_softc * sc)1958 uvideo_vs_init(struct uvideo_softc *sc)
1959 {
1960 	usbd_status error;
1961 
1962 	/* open video stream pipe */
1963 	error = uvideo_vs_open(sc);
1964 	if (error != USBD_NORMAL_COMPLETION)
1965 		return (USBD_INVAL);
1966 
1967 	/* allocate video stream xfer buffer */
1968 	if (sc->sc_vs_cur->bulk_endpoint)
1969 		error = uvideo_vs_alloc_bulk(sc);
1970 	else
1971 		error = uvideo_vs_alloc_isoc(sc);
1972 	if (error != USBD_NORMAL_COMPLETION)
1973 		return (USBD_INVAL);
1974 
1975 	/* allocate video stream frame buffer */
1976 	error = uvideo_vs_alloc_frame(sc);
1977 	if (error != USBD_NORMAL_COMPLETION)
1978 		return (USBD_INVAL);
1979 #ifdef UVIDEO_DUMP
1980 	if (uvideo_debug_file_open(sc) != 0)
1981 		return (USBD_INVAL);
1982 	usb_init_task(&sc->sc_task_write, uvideo_debug_file_write_frame, sc,
1983 	    USB_TASK_TYPE_GENERIC);
1984 #endif
1985 	return (USBD_NORMAL_COMPLETION);
1986 }
1987 
1988 int
uvideo_vs_start_bulk(struct uvideo_softc * sc)1989 uvideo_vs_start_bulk(struct uvideo_softc *sc)
1990 {
1991 	int error;
1992 
1993 	sc->sc_vs_cur->bulk_running = 1;
1994 
1995 	error = kthread_create(uvideo_vs_start_bulk_thread, sc, NULL,
1996 	    DEVNAME(sc));
1997 	if (error) {
1998 		printf("%s: can't create kernel thread!", DEVNAME(sc));
1999 		return (error);
2000 	}
2001 
2002 	return (0);
2003 }
2004 
2005 void
uvideo_vs_start_bulk_thread(void * arg)2006 uvideo_vs_start_bulk_thread(void *arg)
2007 {
2008 	struct uvideo_softc *sc = arg;
2009 	usbd_status error;
2010 	int size;
2011 
2012 	usbd_ref_incr(sc->sc_udev);
2013 	while (sc->sc_vs_cur->bulk_running) {
2014 		size = UGETDW(sc->sc_desc_probe.dwMaxPayloadTransferSize);
2015 
2016 		usbd_setup_xfer(
2017 		    sc->sc_vs_cur->bxfer.xfer,
2018 		    sc->sc_vs_cur->pipeh,
2019 		    0,
2020 		    sc->sc_vs_cur->bxfer.buf,
2021 		    size,
2022 		    USBD_NO_COPY | USBD_SHORT_XFER_OK | USBD_SYNCHRONOUS,
2023 		    0,
2024 		    NULL);
2025 		error = usbd_transfer(sc->sc_vs_cur->bxfer.xfer);
2026 		if (error != USBD_NORMAL_COMPLETION) {
2027 			DPRINTF(1, "%s: error in bulk xfer: %s!\n",
2028 			    DEVNAME(sc), usbd_errstr(error));
2029 			break;
2030 		}
2031 
2032 		DPRINTF(2, "%s: *** buffer len = %d\n", DEVNAME(sc), size);
2033 
2034 		(void)sc->sc_decode_stream_header(sc,
2035 		    sc->sc_vs_cur->bxfer.buf, size);
2036 	}
2037 	usbd_ref_decr(sc->sc_udev);
2038 
2039 	kthread_exit(0);
2040 }
2041 
2042 void
uvideo_vs_start_isoc(struct uvideo_softc * sc)2043 uvideo_vs_start_isoc(struct uvideo_softc *sc)
2044 {
2045 	int i;
2046 
2047 	for (i = 0; i < UVIDEO_IXFERS; i++)
2048 		uvideo_vs_start_isoc_ixfer(sc, &sc->sc_vs_cur->ixfer[i]);
2049 }
2050 
2051 void
uvideo_vs_start_isoc_ixfer(struct uvideo_softc * sc,struct uvideo_isoc_xfer * ixfer)2052 uvideo_vs_start_isoc_ixfer(struct uvideo_softc *sc,
2053     struct uvideo_isoc_xfer *ixfer)
2054 {
2055 	int i;
2056 	usbd_status error;
2057 
2058 	DPRINTF(2, "%s: %s\n", DEVNAME(sc), __func__);
2059 
2060 	if (usbd_is_dying(sc->sc_udev))
2061 		return;
2062 
2063 	for (i = 0; i < sc->sc_nframes; i++)
2064 		ixfer->size[i] = sc->sc_vs_cur->psize;
2065 
2066 	usbd_setup_isoc_xfer(
2067 	    ixfer->xfer,
2068 	    sc->sc_vs_cur->pipeh,
2069 	    ixfer,
2070 	    ixfer->size,
2071 	    sc->sc_nframes,
2072 	    USBD_NO_COPY | USBD_SHORT_XFER_OK,
2073 	    uvideo_vs_cb);
2074 
2075 	error = usbd_transfer(ixfer->xfer);
2076 	if (error && error != USBD_IN_PROGRESS) {
2077 		DPRINTF(1, "%s: usbd_transfer error=%s!\n",
2078 		    DEVNAME(sc), usbd_errstr(error));
2079 	}
2080 }
2081 
2082 void
uvideo_vs_cb(struct usbd_xfer * xfer,void * priv,usbd_status status)2083 uvideo_vs_cb(struct usbd_xfer *xfer, void *priv,
2084     usbd_status status)
2085 {
2086 	struct uvideo_isoc_xfer *ixfer = priv;
2087 	struct uvideo_softc *sc = ixfer->sc;
2088 	int len, i, frame_size;
2089 	uint8_t *frame;
2090 	usbd_status error;
2091 
2092 	DPRINTF(2, "%s: %s\n", DEVNAME(sc), __func__);
2093 
2094 	if (status != USBD_NORMAL_COMPLETION) {
2095 		DPRINTF(1, "%s: %s: %s\n", DEVNAME(sc), __func__,
2096 		    usbd_errstr(status));
2097 		return;
2098 	}
2099 	usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL);
2100 
2101 	DPRINTF(2, "%s: *** buffer len = %d\n", DEVNAME(sc), len);
2102 	if (len == 0)
2103 		goto skip;
2104 
2105 	for (i = 0; i < sc->sc_nframes; i++) {
2106 		frame = ixfer->buf + (i * sc->sc_vs_cur->psize);
2107 		frame_size = ixfer->size[i];
2108 
2109 		if (frame_size == 0)
2110 			/* frame is empty */
2111 			continue;
2112 
2113 		error = sc->sc_decode_stream_header(sc, frame, frame_size);
2114 		if (error == USBD_CANCELLED)
2115 			break;
2116 	}
2117 
2118 skip:	/* setup new transfer */
2119 	uvideo_vs_start_isoc_ixfer(sc, ixfer);
2120 }
2121 
2122 usbd_status
uvideo_vs_decode_stream_header(struct uvideo_softc * sc,uint8_t * frame,int frame_size)2123 uvideo_vs_decode_stream_header(struct uvideo_softc *sc, uint8_t *frame,
2124     int frame_size)
2125 {
2126 	struct uvideo_frame_buffer *fb = &sc->sc_frame_buffer;
2127 	struct usb_video_stream_header *sh;
2128 	int sample_len;
2129 
2130 	if (frame_size < UVIDEO_SH_MIN_LEN)
2131 		/* frame too small to contain a valid stream header */
2132 		return (USBD_INVAL);
2133 
2134 	sh = (struct usb_video_stream_header *)frame;
2135 
2136 	DPRINTF(2, "%s: stream header len = %d\n", DEVNAME(sc), sh->bLength);
2137 
2138 	if (sh->bLength > UVIDEO_SH_MAX_LEN || sh->bLength < UVIDEO_SH_MIN_LEN)
2139 		/* invalid header size */
2140 		return (USBD_INVAL);
2141 	if (sh->bLength == frame_size && !(sh->bFlags & UVIDEO_SH_FLAG_EOF)) {
2142 		/* stream header without payload and no EOF */
2143 		return (USBD_INVAL);
2144 	}
2145 	if (sh->bFlags & UVIDEO_SH_FLAG_ERR) {
2146 		/* stream error, skip xfer */
2147 		DPRINTF(1, "%s: %s: stream error!\n", DEVNAME(sc), __func__);
2148 		return (USBD_CANCELLED);
2149 	}
2150 
2151 	DPRINTF(2, "%s: frame_size = %d\n", DEVNAME(sc), frame_size);
2152 
2153 	if (sh->bFlags & UVIDEO_SH_FLAG_FID) {
2154 		DPRINTF(2, "%s: %s: FID ON (0x%02x)\n",
2155 		    DEVNAME(sc), __func__,
2156 		    sh->bFlags & UVIDEO_SH_FLAG_FID);
2157 	} else {
2158 		DPRINTF(2, "%s: %s: FID OFF (0x%02x)\n",
2159 		    DEVNAME(sc), __func__,
2160 		    sh->bFlags & UVIDEO_SH_FLAG_FID);
2161 	}
2162 
2163 	if (fb->sample == 0) {
2164 		/* first sample for a frame */
2165 		fb->sample = 1;
2166 		fb->fid = sh->bFlags & UVIDEO_SH_FLAG_FID;
2167 		fb->offset = 0;
2168 	} else {
2169 		/* continues sample for a frame, check consistency */
2170 		if (fb->fid != (sh->bFlags & UVIDEO_SH_FLAG_FID)) {
2171 			DPRINTF(1, "%s: %s: wrong FID, ignore last frame!\n",
2172 			    DEVNAME(sc), __func__);
2173 			fb->sample = 1;
2174 			fb->fid = sh->bFlags & UVIDEO_SH_FLAG_FID;
2175 			fb->offset = 0;
2176 		}
2177 	}
2178 
2179 	/* save sample */
2180 	sample_len = frame_size - sh->bLength;
2181 	if ((fb->offset + sample_len) <= fb->buf_size) {
2182 		bcopy(frame + sh->bLength, fb->buf + fb->offset, sample_len);
2183 		fb->offset += sample_len;
2184 	}
2185 
2186 	if (sh->bFlags & UVIDEO_SH_FLAG_EOF) {
2187 		/* got a full frame */
2188 		DPRINTF(2, "%s: %s: EOF (frame size = %d bytes)\n",
2189 		    DEVNAME(sc), __func__, fb->offset);
2190 
2191 		if (fb->offset > fb->buf_size) {
2192 			DPRINTF(1, "%s: %s: frame too large, skipped!\n",
2193 			    DEVNAME(sc), __func__);
2194 		} else if (fb->offset < fb->buf_size &&
2195 		    !(fb->fmt_flags & V4L2_FMT_FLAG_COMPRESSED)) {
2196 			DPRINTF(1, "%s: %s: frame too small, skipped!\n",
2197 			    DEVNAME(sc), __func__);
2198 		} else {
2199 #ifdef UVIDEO_DUMP
2200 			/* do the file write in process context */
2201 			usb_rem_task(sc->sc_udev, &sc->sc_task_write);
2202 			usb_add_task(sc->sc_udev, &sc->sc_task_write);
2203 #endif
2204 			if (sc->sc_mmap_flag) {
2205 				/* mmap */
2206 				if (uvideo_mmap_queue(sc, fb->buf, fb->offset))
2207 					return (USBD_NOMEM);
2208 			} else {
2209 				/* read */
2210 				uvideo_read(sc, fb->buf, fb->offset);
2211 			}
2212 		}
2213 
2214 		fb->sample = 0;
2215 		fb->fid = 0;
2216 	}
2217 
2218 	return (USBD_NORMAL_COMPLETION);
2219 }
2220 
2221 /*
2222  * XXX Doesn't work yet.  Fix it!
2223  *
2224  * The iSight first generation device uses a own, non-standard streaming
2225  * protocol.  The stream header is just sent once per image and looks
2226  * like following:
2227  *
2228  *	uByte 	header length
2229  *	uByte	flags
2230  *	uByte	magic1[4]	always "11223344"
2231  *	uByte	magic2[8]	always "deadbeefdeadface"
2232  *	uByte	unknown[16]
2233  *
2234  * Sometimes the stream header is prefixed by a unknown byte.  Therefore
2235  * we check for the magic value on two offsets.
2236  */
2237 usbd_status
uvideo_vs_decode_stream_header_isight(struct uvideo_softc * sc,uint8_t * frame,int frame_size)2238 uvideo_vs_decode_stream_header_isight(struct uvideo_softc *sc, uint8_t *frame,
2239     int frame_size)
2240 {
2241 	struct uvideo_frame_buffer *fb = &sc->sc_frame_buffer;
2242 	int sample_len, header = 0;
2243 	uint8_t magic[] = {
2244 	    0x11, 0x22, 0x33, 0x44,
2245 	    0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xfa, 0xce };
2246 
2247 	if (frame_size > 13 && !memcmp(&frame[2], magic, 12))
2248 		header = 1;
2249 	if (frame_size > 14 && !memcmp(&frame[3], magic, 12))
2250 		header = 1;
2251 
2252 	if (header && fb->fid == 0) {
2253 		fb->fid = 1;
2254 		return (USBD_NORMAL_COMPLETION);
2255 	}
2256 
2257 	if (header) {
2258 		if (sc->sc_mmap_flag) {
2259 			/* mmap */
2260 			if (uvideo_mmap_queue(sc, fb->buf, fb->offset))
2261 				return (USBD_NOMEM);
2262 		} else {
2263 			/* read */
2264 			uvideo_read(sc, fb->buf, fb->offset);
2265 		}
2266 		fb->offset = 0;
2267 	} else {
2268 		/* save sample */
2269 		sample_len = frame_size;
2270 		if ((fb->offset + sample_len) <= fb->buf_size) {
2271 			bcopy(frame, fb->buf + fb->offset, sample_len);
2272 			fb->offset += sample_len;
2273 		}
2274 	}
2275 
2276 	return (USBD_NORMAL_COMPLETION);
2277 }
2278 
2279 int
uvideo_mmap_queue(struct uvideo_softc * sc,uint8_t * buf,int len)2280 uvideo_mmap_queue(struct uvideo_softc *sc, uint8_t *buf, int len)
2281 {
2282 	int i;
2283 
2284 	if (sc->sc_mmap_count == 0 || sc->sc_mmap_buffer == NULL)
2285 		panic("%s: mmap buffers not allocated", __func__);
2286 
2287 	/* find a buffer which is ready for queueing */
2288 	for (i = 0; i < sc->sc_mmap_count; i++) {
2289 		if (sc->sc_mmap[i].v4l2_buf.flags & V4L2_BUF_FLAG_QUEUED)
2290 			break;
2291 	}
2292 	if (i == sc->sc_mmap_count) {
2293 		DPRINTF(1, "%s: %s: mmap queue is full!",
2294 		    DEVNAME(sc), __func__);
2295 		return ENOMEM;
2296 	}
2297 
2298 	/* copy frame to mmap buffer and report length */
2299 	bcopy(buf, sc->sc_mmap[i].buf, len);
2300 	sc->sc_mmap[i].v4l2_buf.bytesused = len;
2301 
2302 	/* timestamp it */
2303 	getmicrotime(&sc->sc_mmap[i].v4l2_buf.timestamp);
2304 
2305 	/* queue it */
2306 	sc->sc_mmap[i].v4l2_buf.flags |= V4L2_BUF_FLAG_DONE;
2307 	sc->sc_mmap[i].v4l2_buf.flags &= ~V4L2_BUF_FLAG_QUEUED;
2308 	SIMPLEQ_INSERT_TAIL(&sc->sc_mmap_q, &sc->sc_mmap[i], q_frames);
2309 	DPRINTF(2, "%s: %s: frame queued on index %d\n",
2310 	    DEVNAME(sc), __func__, i);
2311 
2312 	wakeup(sc);
2313 
2314 	/*
2315 	 * In case userland uses poll(2), signal that we have a frame
2316 	 * ready to dequeue.
2317 	 */
2318 	sc->sc_uplayer_intr(sc->sc_uplayer_arg);
2319 
2320 	return 0;
2321 }
2322 
2323 void
uvideo_read(struct uvideo_softc * sc,uint8_t * buf,int len)2324 uvideo_read(struct uvideo_softc *sc, uint8_t *buf, int len)
2325 {
2326 	/*
2327 	 * Copy video frame to upper layer buffer and call
2328 	 * upper layer interrupt.
2329 	 */
2330 	*sc->sc_uplayer_fsize = len;
2331 	bcopy(buf, sc->sc_uplayer_fbuffer, len);
2332 	sc->sc_uplayer_intr(sc->sc_uplayer_arg);
2333 }
2334 
2335 #ifdef UVIDEO_DEBUG
2336 void
uvideo_dump_desc_all(struct uvideo_softc * sc)2337 uvideo_dump_desc_all(struct uvideo_softc *sc)
2338 {
2339 	struct usbd_desc_iter iter;
2340 	const usb_descriptor_t *desc;
2341 
2342 	usbd_desc_iter_init(sc->sc_udev, &iter);
2343 	desc = usbd_desc_iter_next(&iter);
2344 	while (desc) {
2345 		printf("bLength=%d\n", desc->bLength);
2346 		printf("bDescriptorType=0x%02x", desc->bDescriptorType);
2347 
2348 		switch (desc->bDescriptorType) {
2349 		case UDESC_CS_INTERFACE:
2350 			printf(" (CS_INTERFACE)\n");
2351 
2352 			switch (desc->bDescriptorSubtype) {
2353 			case UDESCSUB_VC_HEADER:
2354 				printf("bDescriptorSubtype=0x%02x",
2355 				    desc->bDescriptorSubtype);
2356 				if (uvideo_desc_len(desc, 12, 11, 1, 0)) {
2357 					printf(" (UDESCSUB_VC_HEADER)\n");
2358 					printf("|\n");
2359 					uvideo_dump_desc_vc_header(sc, desc);
2360 					break;
2361 				}
2362 				if (uvideo_desc_len(desc, 13, 3, 0, 12)) {
2363 					printf(" (UDESCSUB_VS_INPUT_HEADER)\n");
2364 					printf("|\n");
2365 					uvideo_dump_desc_input_header(sc, desc);
2366 					break;
2367 				}
2368 				printf(" (unknown)\n");
2369 				break;
2370 			case UDESCSUB_VC_INPUT_TERMINAL:
2371 				printf("bDescriptorSubtype=0x%02x",
2372 				    desc->bDescriptorSubtype);
2373 				printf(" (UDESCSUB_VC_INPUT_TERMINAL)\n");
2374 				printf("|\n");
2375 				uvideo_dump_desc_input(sc, desc);
2376 				break;
2377 			case UDESCSUB_VC_OUTPUT_TERMINAL:
2378 				printf("bDescriptorSubtype=0x%02x",
2379 				    desc->bDescriptorSubtype);
2380 				printf(" (UDESCSUB_VC_OUTPUT)\n");
2381 				printf("|\n");
2382 				uvideo_dump_desc_output(sc, desc);
2383 				break;
2384 			case UDESCSUB_VC_SELECTOR_UNIT:
2385 				printf("bDescriptorSubtype=0x%02x",
2386 				    desc->bDescriptorSubtype);
2387 				if (desc->bLength == 27) {
2388 					printf(" (UDESCSUB_VS_FORMAT_"
2389 					    "UNCOMPRESSED)\n");
2390 					uvideo_dump_desc_format_uncompressed(
2391 					    sc, desc);
2392 				} else {
2393 					printf(" (UDESCSUB_VC_SELECTOR_"
2394 					    "UNIT)\n");
2395 					/* TODO */
2396 				}
2397 				break;
2398 			case UDESCSUB_VC_PROCESSING_UNIT:
2399 				printf("bDescriptorSubtype=0x%02x",
2400 				    desc->bDescriptorSubtype);
2401 				if (desc->bLength >
2402 				    sizeof(struct usb_video_frame_desc)) {
2403 					printf(" (UDESCSUB_VS_FRAME_"
2404 					    "UNCOMPRESSED)\n");
2405 					uvideo_dump_desc_frame(sc, desc);
2406 				} else {
2407 					printf(" (UDESCSUB_VC_PROCESSING_"
2408 					    "UNIT)\n");
2409 					printf("|\n");
2410 					uvideo_dump_desc_processing(sc, desc);
2411 				}
2412 				break;
2413 			case UDESCSUB_VC_EXTENSION_UNIT:
2414 				printf("bDescriptorSubtype=0x%02x",
2415 				    desc->bDescriptorSubtype);
2416 				if (desc->bLength == 11) {
2417 					printf(" (UDESCSUB_VS_FORMAT_MJPEG)\n");
2418 					printf("|\n");
2419 					uvideo_dump_desc_format_mjpeg(sc, desc);
2420 				} else {
2421 					printf(" (UDESCSUB_VC_EXTENSION_"
2422 					    "UNIT)\n");
2423 					printf("|\n");
2424 					uvideo_dump_desc_extension(sc, desc);
2425 				}
2426 				break;
2427 			case UDESCSUB_VS_FRAME_MJPEG:
2428 				printf("bDescriptorSubtype=0x%02x",
2429 				    desc->bDescriptorSubtype);
2430 				printf(" (UDESCSUB_VS_FRAME_MJPEG)\n");
2431 				if (desc->bLength >
2432 				    sizeof(struct usb_video_frame_desc)) {
2433 					printf("|\n");
2434 					uvideo_dump_desc_frame(sc, desc);
2435 				}
2436 				break;
2437 			case UDESCSUB_VS_COLORFORMAT:
2438 				printf("bDescriptorSubtype=0x%02x",
2439 				   desc->bDescriptorSubtype);
2440 				printf(" (UDESCSUB_VS_COLORFORMAT)\n");
2441 				printf("|\n");
2442 				uvideo_dump_desc_colorformat(sc, desc);
2443 				break;
2444 			}
2445 
2446 			break;
2447 		case UDESC_CS_ENDPOINT:
2448 			printf(" (UDESC_CS_ENDPOINT)\n");
2449 
2450 			switch (desc->bDescriptorSubtype) {
2451 			case EP_INTERRUPT:
2452 				printf("bDescriptorSubtype=0x%02x",
2453 				    desc->bDescriptorSubtype);
2454 				printf(" (EP_INTERRUPT)\n");
2455 				printf("|\n");
2456 				uvideo_dump_desc_cs_endpoint(sc, desc);
2457 				break;
2458 			case EP_GENERAL:
2459 				printf("bDescriptorSubtype=0x%02x",
2460 				    desc->bDescriptorSubtype);
2461 				printf(" (EP_GENERAL)\n");
2462 				printf("|\n");
2463 				uvideo_dump_desc_cs_endpoint(sc, desc);
2464 				break;
2465 			}
2466 
2467 			break;
2468 		case UDESC_CONFIG:
2469 			printf(" (UDESC_CONFIG)\n");
2470 			printf("|\n");
2471 			uvideo_dump_desc_config(sc, desc);
2472 			break;
2473 		case UDESC_ENDPOINT:
2474 			printf(" (UDESC_ENDPOINT)\n");
2475 			printf("|\n");
2476 			uvideo_dump_desc_endpoint(sc, desc);
2477 			break;
2478 		case UDESC_INTERFACE:
2479 			printf(" (UDESC_INTERFACE)\n");
2480 			printf("|\n");
2481 			uvideo_dump_desc_interface(sc, desc);
2482 			break;
2483 		case UDESC_IFACE_ASSOC:
2484 			printf(" (UDESC_IFACE_ASSOC)\n");
2485 			printf("|\n");
2486 			uvideo_dump_desc_iface_assoc(sc, desc);
2487 			break;
2488 		default:
2489 			printf(" (unknown)\n");
2490 			break;
2491 		}
2492 
2493 		printf("\n");
2494 
2495 		desc = usbd_desc_iter_next(&iter);
2496 	}
2497 
2498 }
2499 
2500 void
uvideo_dump_desc_vc_header(struct uvideo_softc * sc,const usb_descriptor_t * desc)2501 uvideo_dump_desc_vc_header(struct uvideo_softc *sc,
2502     const usb_descriptor_t *desc)
2503 {
2504 	struct usb_video_header_desc *d;
2505 
2506 	d = (struct usb_video_header_desc *)(uint8_t *)desc;
2507 
2508 	printf("bLength=%d\n", d->bLength);
2509 	printf("bDescriptorType=0x%02x\n", d->bDescriptorType);
2510 	printf("bDescriptorSubtype=0x%02x\n", d->bDescriptorSubtype);
2511 	printf("bcdUVC=0x%04x\n", UGETW(d->bcdUVC));
2512 	printf("wTotalLength=%d\n", UGETW(d->wTotalLength));
2513 	printf("dwClockFrequency=%d\n", UGETDW(d->dwClockFrequency));
2514 	printf("bInCollection=0x%02x\n", d->bInCollection);
2515 }
2516 
2517 void
uvideo_dump_desc_input_header(struct uvideo_softc * sc,const usb_descriptor_t * desc)2518 uvideo_dump_desc_input_header(struct uvideo_softc *sc,
2519     const usb_descriptor_t *desc)
2520 {
2521 	struct usb_video_input_header_desc *d;
2522 
2523 	d = (struct usb_video_input_header_desc *)(uint8_t *)desc;
2524 
2525 	printf("bLength=%d\n", d->bLength);
2526 	printf("bDescriptorType=0x%02x\n", d->bDescriptorType);
2527 	printf("bDescriptorSubtype=0x%02x\n", d->bDescriptorSubtype);
2528 	printf("bNumFormats=%d\n", d->bNumFormats);
2529 	printf("wTotalLength=%d\n", UGETW(d->wTotalLength));
2530 	printf("bEndpointAddress=0x%02x\n", d->bEndpointAddress);
2531 	printf("bmInfo=0x%02x\n", d->bmInfo);
2532 	printf("bTerminalLink=0x%02x\n", d->bTerminalLink);
2533 	printf("bStillCaptureMethod=0x%02x\n", d->bStillCaptureMethod);
2534 	printf("bTriggerSupport=0x%02x\n", d->bTriggerSupport);
2535 	printf("bTriggerUsage=0x%02x\n", d->bTriggerUsage);
2536 	printf("bControlSize=%d\n", d->bControlSize);
2537 }
2538 
2539 void
uvideo_dump_desc_input(struct uvideo_softc * sc,const usb_descriptor_t * desc)2540 uvideo_dump_desc_input(struct uvideo_softc *sc,
2541     const usb_descriptor_t *desc)
2542 {
2543 	struct usb_video_input_terminal_desc *d;
2544 
2545 	d = (struct usb_video_input_terminal_desc *)(uint8_t *)desc;
2546 
2547 	printf("bLength=%d\n", d->bLength);
2548 	printf("bDescriptorType=0x%02x\n", d->bDescriptorType);
2549 	printf("bDescriptorSubtype=0x%02x\n", d->bDescriptorSubtype);
2550 	printf("bTerminalID=0x%02x\n", d->bTerminalID);
2551 	printf("wTerminalType=0x%04x\n", UGETW(d->wTerminalType));
2552 	printf("bAssocTerminal=0x%02x\n", d->bAssocTerminal);
2553 	printf("iTerminal=0x%02x\n", d->iTerminal);
2554 }
2555 
2556 void
uvideo_dump_desc_output(struct uvideo_softc * sc,const usb_descriptor_t * desc)2557 uvideo_dump_desc_output(struct uvideo_softc *sc,
2558     const usb_descriptor_t *desc)
2559 {
2560 	struct usb_video_output_terminal_desc *d;
2561 
2562 	d = (struct usb_video_output_terminal_desc *)(uint8_t *)desc;
2563 
2564 	printf("bLength=%d\n", d->bLength);
2565 	printf("bDescriptorType=0x%02x\n", d->bDescriptorType);
2566 	printf("bDescriptorSubtype=0x%02x\n", d->bDescriptorSubtype);
2567 	printf("bTerminalID=0x%02x\n", d->bTerminalID);
2568 	printf("bAssocTerminal=0x%02x\n", d->bAssocTerminal);
2569 	printf("bSourceID=0x%02x\n", d->bSourceID);
2570 	printf("iTerminal=0x%02x\n", d->iTerminal);
2571 
2572 }
2573 
2574 void
uvideo_dump_desc_endpoint(struct uvideo_softc * sc,const usb_descriptor_t * desc)2575 uvideo_dump_desc_endpoint(struct uvideo_softc *sc,
2576     const usb_descriptor_t *desc)
2577 {
2578 	usb_endpoint_descriptor_t *d;
2579 
2580 	d = (usb_endpoint_descriptor_t *)(uint8_t *)desc;
2581 
2582 	printf("bLength=%d\n", d->bLength);
2583 	printf("bDescriptorType=0x%02x\n", d->bDescriptorType);
2584 	printf("bEndpointAddress=0x%02x", d->bEndpointAddress);
2585 	if (UE_GET_DIR(d->bEndpointAddress) == UE_DIR_IN)
2586 		printf(" (IN)\n");
2587 	if (UE_GET_DIR(d->bEndpointAddress) == UE_DIR_OUT)
2588 		printf(" (OUT)\n");
2589 	printf("bmAttributes=0x%02x", d->bmAttributes);
2590 	if (UE_GET_XFERTYPE(d->bmAttributes) == UE_ISOCHRONOUS) {
2591 		printf(" (UE_ISOCHRONOUS,");
2592 		if (UE_GET_ISO_TYPE(d->bmAttributes) == UE_ISO_ASYNC)
2593 			printf(" UE_ISO_ASYNC)\n");
2594 		if (UE_GET_ISO_TYPE(d->bmAttributes) == UE_ISO_ADAPT)
2595 			printf(" UE_ISO_ADAPT)\n");
2596 		if (UE_GET_ISO_TYPE(d->bmAttributes) == UE_ISO_SYNC)
2597 			printf(" UE_ISO_SYNC)\n");
2598 	}
2599 	if (UE_GET_XFERTYPE(d->bmAttributes) == UE_CONTROL)
2600 		printf(" (UE_CONTROL)\n");
2601 	if (UE_GET_XFERTYPE(d->bmAttributes) == UE_BULK)
2602 		printf(" (UE_BULK)\n");
2603 	if (UE_GET_XFERTYPE(d->bmAttributes) == UE_INTERRUPT)
2604 		printf(" (UE_INTERRUPT)\n");
2605 	printf("wMaxPacketSize=%d\n", UGETW(d->wMaxPacketSize));
2606 	printf("bInterval=0x%02x\n", d->bInterval);
2607 }
2608 
2609 void
uvideo_dump_desc_iface_assoc(struct uvideo_softc * sc,const usb_descriptor_t * desc)2610 uvideo_dump_desc_iface_assoc(struct uvideo_softc *sc,
2611     const usb_descriptor_t *desc)
2612 {
2613 	usb_interface_assoc_descriptor_t *d;
2614 
2615 	d = (usb_interface_assoc_descriptor_t *)(uint8_t *)desc;
2616 
2617 	printf("bLength=%d\n", d->bLength);
2618 	printf("bDescriptorType=0x%02x\n", d->bDescriptorType);
2619 	printf("bFirstInterface=0x%02x\n", d->bFirstInterface);
2620 	printf("bInterfaceCount=%d\n", d->bInterfaceCount);
2621 	printf("bFunctionClass=0x%02x\n", d->bFunctionClass);
2622 	printf("bFunctionSubClass=0x%02x\n", d->bFunctionSubClass);
2623 	printf("bFunctionProtocol=0x%02x\n", d->bFunctionProtocol);
2624 	printf("iFunction=0x%02x\n", d->iFunction);
2625 }
2626 
2627 void
uvideo_dump_desc_interface(struct uvideo_softc * sc,const usb_descriptor_t * desc)2628 uvideo_dump_desc_interface(struct uvideo_softc *sc,
2629     const usb_descriptor_t *desc)
2630 {
2631 	usb_interface_descriptor_t *d;
2632 
2633 	d = (usb_interface_descriptor_t *)(uint8_t *)desc;
2634 
2635 	printf("bLength=%d\n", d->bLength);
2636 	printf("bDescriptorType=0x%02x\n", d->bDescriptorType);
2637 	printf("bInterfaceNumber=0x%02x\n", d->bInterfaceNumber);
2638 	printf("bAlternateSetting=0x%02x\n", d->bAlternateSetting);
2639 	printf("bNumEndpoints=%d\n", d->bNumEndpoints);
2640 	printf("bInterfaceClass=0x%02x\n", d->bInterfaceClass);
2641 	printf("bInterfaceSubClass=0x%02x\n", d->bInterfaceSubClass);
2642 	printf("bInterfaceProtocol=0x%02x\n", d->bInterfaceProtocol);
2643 	printf("iInterface=0x%02x\n", d->iInterface);
2644 }
2645 
2646 void
uvideo_dump_desc_config(struct uvideo_softc * sc,const usb_descriptor_t * desc)2647 uvideo_dump_desc_config(struct uvideo_softc *sc,
2648     const usb_descriptor_t *desc)
2649 {
2650 	usb_config_descriptor_t *d;
2651 
2652 	d = (usb_config_descriptor_t *)(uint8_t *)desc;
2653 
2654 	printf("bLength=%d\n", d->bLength);
2655 	printf("bDescriptorType=0x%02x\n", d->bDescriptorType);
2656 	printf("wTotalLength=%d\n", UGETW(d->wTotalLength));
2657 	printf("bNumInterfaces=0x%02x\n", d->bNumInterfaces);
2658 	printf("bConfigurationValue=0x%02x\n", d->bConfigurationValue);
2659 	printf("iConfiguration=0x%02x\n", d->iConfiguration);
2660 	printf("bmAttributes=0x%02x\n", d->bmAttributes);
2661 	printf("bMaxPower=0x%02x\n", d->bMaxPower);
2662 }
2663 
2664 void
uvideo_dump_desc_cs_endpoint(struct uvideo_softc * sc,const usb_descriptor_t * desc)2665 uvideo_dump_desc_cs_endpoint(struct uvideo_softc *sc,
2666     const usb_descriptor_t *desc)
2667 {
2668 	struct usb_video_vc_endpoint_desc *d;
2669 
2670 	d = (struct usb_video_vc_endpoint_desc *)(uint8_t *)desc;
2671 
2672 	printf("bLength=%d\n", d->bLength);
2673 	printf("bDescriptorType=0x%02x\n", d->bDescriptorType);
2674 	printf("bDescriptorSubtype=0x%02x\n", d->bDescriptorSubtype);
2675 	printf("wMaxTransferSize=%d\n", UGETW(d->wMaxTransferSize));
2676 }
2677 
2678 void
uvideo_dump_desc_colorformat(struct uvideo_softc * sc,const usb_descriptor_t * desc)2679 uvideo_dump_desc_colorformat(struct uvideo_softc *sc,
2680     const usb_descriptor_t *desc)
2681 {
2682 	struct usb_video_color_matching_descr *d;
2683 
2684 	d = (struct usb_video_color_matching_descr *)(uint8_t *)desc;
2685 
2686 	printf("bLength=%d\n", d->bLength);
2687 	printf("bDescriptorType=0x%02x\n", d->bDescriptorType);
2688 	printf("bDescriptorSubtype=0x%02x\n", d->bDescriptorSubtype);
2689 	printf("bColorPrimaries=0x%02x\n", d->bColorPrimaries);
2690 	printf("bTransferCharacteristics=0x%02x\n",
2691 	    d->bTransferCharacteristics);
2692 	printf("bMatrixCoefficients=0x%02x\n", d->bMatrixCoefficients);
2693 }
2694 void
uvideo_dump_desc_format_mjpeg(struct uvideo_softc * sc,const usb_descriptor_t * desc)2695 uvideo_dump_desc_format_mjpeg(struct uvideo_softc *sc,
2696     const usb_descriptor_t *desc)
2697 {
2698 	struct usb_video_format_mjpeg_desc *d;
2699 
2700 	d = (struct usb_video_format_mjpeg_desc *)(uint8_t *)desc;
2701 
2702 	printf("bLength=%d\n", d->bLength);
2703 	printf("bDescriptorType=0x%02x\n", d->bDescriptorType);
2704 	printf("bDescriptorSubtype=0x%02x\n", d->bDescriptorSubtype);
2705 	printf("bFormatIndex=0x%02x\n", d->bFormatIndex);
2706 	printf("bNumFrameDescriptors=0x%02x\n", d->bNumFrameDescriptors);
2707 	printf("bmFlags=0x%02x\n", d->bmFlags);
2708 	printf("bDefaultFrameIndex=0x%02x\n", d->bDefaultFrameIndex);
2709 	printf("bAspectRatioX=0x%02x\n", d->bAspectRatioX);
2710 	printf("bAspectRatioY=0x%02x\n", d->bAspectRatioY);
2711 	printf("bmInterlaceFlags=0x%02x\n", d->bmInterlaceFlags);
2712 	printf("bCopyProtect=0x%02x\n", d->bCopyProtect);
2713 }
2714 
2715 void
uvideo_dump_desc_frame(struct uvideo_softc * sc,const usb_descriptor_t * desc)2716 uvideo_dump_desc_frame(struct uvideo_softc *sc, const usb_descriptor_t *desc)
2717 {
2718 	struct usb_video_frame_desc *d;
2719 	uint8_t *p;
2720 	int length, i;
2721 
2722 	d = (struct usb_video_frame_desc *)(uint8_t *)desc;
2723 
2724 	printf("bLength=%d\n", d->bLength);
2725 	printf("bDescriptorType=0x%02x\n", d->bDescriptorType);
2726 	printf("bDescriptorSubtype=0x%02x\n", d->bDescriptorSubtype);
2727 	printf("bFrameIndex=0x%02x\n", d->bFrameIndex);
2728 	printf("bmCapabilities=0x%02x\n", d->bmCapabilities);
2729 	printf("wWidth=%d\n", UGETW(d->wWidth));
2730 	printf("wHeight=%d\n", UGETW(d->wHeight));
2731 	printf("dwMinBitRate=%d\n", UGETDW(d->dwMinBitRate));
2732 	printf("dwMaxBitRate=%d\n", UGETDW(d->dwMaxBitRate));
2733 	printf("dwMaxVideoFrameBufferSize=%d\n",
2734 	    UGETDW(d->dwMaxVideoFrameBufferSize));
2735 	printf("dwDefaultFrameInterval=%d\n",
2736 	    UGETDW(d->dwDefaultFrameInterval));
2737 	printf("bFrameIntervalType=0x%02x\n", d->bFrameIntervalType);
2738 
2739 	p = (uint8_t *)d;
2740 	p += sizeof(struct usb_video_frame_desc);
2741 
2742 	if (!d->bFrameIntervalType) {
2743 		/* continuous */
2744 		if (d->bLength < (sizeof(struct usb_video_frame_desc) +
2745 		    sizeof(uDWord) * 3)) {
2746 			printf("invalid frame descriptor length\n");
2747 		} else {
2748 			printf("dwMinFrameInterval = %d\n", UGETDW(p));
2749 			p += sizeof(uDWord);
2750 			printf("dwMaxFrameInterval = %d\n", UGETDW(p));
2751 			p += sizeof(uDWord);
2752 			printf("dwFrameIntervalStep = %d\n", UGETDW(p));
2753 			p += sizeof(uDWord);
2754 		}
2755 	} else {
2756 		/* discrete */
2757 		length = d->bLength - sizeof(struct usb_video_frame_desc);
2758 		for (i = 0; i < d->bFrameIntervalType; i++) {
2759 			if (length <= 0) {
2760 				printf("frame descriptor ended early\n");
2761 				break;
2762 			}
2763 			printf("dwFrameInterval = %d\n", UGETDW(p));
2764 			p += sizeof(uDWord);
2765 			length -= sizeof(uDWord);
2766 		}
2767 	}
2768 }
2769 
2770 void
uvideo_dump_desc_format_uncompressed(struct uvideo_softc * sc,const usb_descriptor_t * desc)2771 uvideo_dump_desc_format_uncompressed(struct uvideo_softc *sc,
2772     const usb_descriptor_t *desc)
2773 {
2774 	struct usb_video_format_uncompressed_desc *d;
2775 
2776 	d = (struct usb_video_format_uncompressed_desc *)(uint8_t *)desc;
2777 
2778 	printf("bLength=%d\n", d->bLength);
2779 	printf("bDescriptorType=0x%02x\n", d->bDescriptorType);
2780 	printf("bDescriptorSubtype=0x%02x\n", d->bDescriptorSubtype);
2781 	printf("bFormatIndex=0x%02x\n", d->bFormatIndex);
2782 	printf("bNumFrameDescriptors=0x%02x\n", d->bNumFrameDescriptors);
2783 	printf("guidFormat=%s\n", d->guidFormat);
2784 	printf("bBitsPerPixel=0x%02x\n", d->bBitsPerPixel);
2785 	printf("bDefaultFrameIndex=0x%02x\n", d->bDefaultFrameIndex);
2786 	printf("bAspectRatioX=0x%02x\n", d->bAspectRatioX);
2787 	printf("bAspectRatioY=0x%02x\n", d->bAspectRatioY);
2788 	printf("bmInterlaceFlags=0x%02x\n", d->bmInterlaceFlags);
2789 	printf("bCopyProtect=0x%02x\n", d->bCopyProtect);
2790 }
2791 
2792 void
uvideo_dump_desc_processing(struct uvideo_softc * sc,const usb_descriptor_t * desc)2793 uvideo_dump_desc_processing(struct uvideo_softc *sc,
2794     const usb_descriptor_t *desc)
2795 {
2796 	struct usb_video_vc_processing_desc *d;
2797 
2798 	/* PU descriptor is variable sized */
2799 	d = (void *)desc;
2800 
2801 	printf("bLength=%d\n", d->bLength);
2802 	printf("bDescriptorType=0x%02x\n", d->bDescriptorType);
2803 	printf("bDescriptorSubtype=0x%02x\n", d->bDescriptorSubtype);
2804 	printf("bUnitID=0x%02x\n", d->bUnitID);
2805 	printf("bSourceID=0x%02x\n", d->bSourceID);
2806 	printf("wMaxMultiplier=%d\n", UGETW(d->wMaxMultiplier));
2807 	printf("bControlSize=%d\n", d->bControlSize);
2808 	printf("bmControls=0x");
2809 	uvideo_hexdump(d->bmControls, d->bControlSize, 1);
2810 	printf("iProcessing=0x%02x\n", d->bmControls[d->bControlSize]);
2811 	printf("bmVideoStandards=0x%02x\n", d->bmControls[d->bControlSize + 1]);
2812 }
2813 
2814 void
uvideo_dump_desc_extension(struct uvideo_softc * sc,const usb_descriptor_t * desc)2815 uvideo_dump_desc_extension(struct uvideo_softc *sc,
2816     const usb_descriptor_t *desc)
2817 {
2818 	struct usb_video_vc_extension_desc *d;
2819 
2820 	d = (struct usb_video_vc_extension_desc *)(uint8_t *)desc;
2821 
2822 	printf("bLength=%d\n", d->bLength);
2823 	printf("bDescriptorType=0x%02x\n", d->bDescriptorType);
2824 	printf("bDescriptorSubtype=0x%02x\n", d->bDescriptorSubtype);
2825 	printf("bUnitID=0x%02x\n", d->bUnitID);
2826 	printf("guidExtensionCode=0x");
2827 	uvideo_hexdump(d->guidExtensionCode, sizeof(d->guidExtensionCode), 1);
2828 	printf("bNumControls=0x%02x\n", d->bNumControls);
2829 	printf("bNrInPins=0x%02x\n", d->bNrInPins);
2830 }
2831 
2832 void
uvideo_hexdump(void * buf,int len,int quiet)2833 uvideo_hexdump(void *buf, int len, int quiet)
2834 {
2835 	int i;
2836 
2837 	for (i = 0; i < len; i++) {
2838 		if (quiet == 0) {
2839 			if (i % 16 == 0)
2840 				printf("%s%5i:", i ? "\n" : "", i);
2841 			if (i % 4 == 0)
2842 				printf(" ");
2843 		}
2844 		printf("%02x", (int)*((u_char *)buf + i));
2845 	}
2846 	printf("\n");
2847 }
2848 
2849 int
uvideo_debug_file_open(struct uvideo_softc * sc)2850 uvideo_debug_file_open(struct uvideo_softc *sc)
2851 {
2852 	struct proc *p = curproc;
2853 	struct nameidata nd;
2854 	char name[] = "/tmp/uvideo.mjpeg";
2855 	int error;
2856 
2857 	NDINIT(&nd, 0, 0, UIO_SYSSPACE, name, p);
2858 	error = vn_open(&nd, O_CREAT | FWRITE | O_NOFOLLOW, S_IRUSR | S_IWUSR);
2859 	if (error) {
2860 		DPRINTF(1, "%s: %s: can't create debug file %s!\n",
2861 		    DEVNAME(sc), __func__, name);
2862 		return (error);
2863 	}
2864 
2865 	sc->sc_vp = nd.ni_vp;
2866 	VOP_UNLOCK(sc->sc_vp);
2867 	if (nd.ni_vp->v_type != VREG) {
2868 		vn_close(nd.ni_vp, FWRITE, p->p_ucred, p);
2869 		return (EIO);
2870 	}
2871 
2872 	DPRINTF(1, "%s: %s: created debug file %s\n",
2873 	    DEVNAME(sc), __func__, name);
2874 
2875 	return (0);
2876 }
2877 
2878 void
uvideo_debug_file_write_frame(void * arg)2879 uvideo_debug_file_write_frame(void *arg)
2880 {
2881 	struct uvideo_softc *sc = arg;
2882 	struct uvideo_frame_buffer *sb = &sc->sc_frame_buffer;
2883 	struct proc *p = curproc;
2884 	int error;
2885 
2886 	if (sc->sc_vp == NULL) {
2887 		printf("%s: %s: no file open!\n", DEVNAME(sc), __func__);
2888 		return;
2889 	}
2890 
2891 	error = vn_rdwr(UIO_WRITE, sc->sc_vp, sb->buf, sb->offset, (off_t)0,
2892 	    UIO_SYSSPACE, IO_APPEND|IO_UNIT, p->p_ucred, NULL, p);
2893 
2894 	if (error)
2895 		DPRINTF(1, "vn_rdwr error!\n");
2896 }
2897 #endif
2898 
2899 /*
2900  * IOCTL's
2901  */
2902 int
uvideo_querycap(void * v,struct v4l2_capability * caps)2903 uvideo_querycap(void *v, struct v4l2_capability *caps)
2904 {
2905 	struct uvideo_softc *sc = v;
2906 
2907 	bzero(caps, sizeof(*caps));
2908 	strlcpy(caps->driver, DEVNAME(sc), sizeof(caps->driver));
2909 	strlcpy(caps->card, sc->sc_udev->product, sizeof(caps->card));
2910 	strlcpy(caps->bus_info, "usb", sizeof(caps->bus_info));
2911 
2912 	caps->version = 1;
2913 	caps->device_caps = V4L2_CAP_VIDEO_CAPTURE
2914 	    | V4L2_CAP_STREAMING
2915 	    | V4L2_CAP_READWRITE;
2916 	caps->capabilities = caps->device_caps | V4L2_CAP_DEVICE_CAPS;
2917 
2918 	return (0);
2919 }
2920 
2921 int
uvideo_enum_fmt(void * v,struct v4l2_fmtdesc * fmtdesc)2922 uvideo_enum_fmt(void *v, struct v4l2_fmtdesc *fmtdesc)
2923 {
2924 	struct uvideo_softc *sc = v;
2925 	int idx;
2926 
2927 	if (fmtdesc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
2928 		/* type not supported */
2929 		return (EINVAL);
2930 
2931 	if (fmtdesc->index >= sc->sc_fmtgrp_num)
2932 		/* no more formats left */
2933 		return (EINVAL);
2934 	idx = fmtdesc->index;
2935 
2936 	switch (sc->sc_fmtgrp[idx].format->bDescriptorSubtype) {
2937 	case UDESCSUB_VS_FORMAT_MJPEG:
2938 		fmtdesc->flags = V4L2_FMT_FLAG_COMPRESSED;
2939 		(void)strlcpy(fmtdesc->description, "MJPEG",
2940 		    sizeof(fmtdesc->description));
2941 		fmtdesc->pixelformat = V4L2_PIX_FMT_MJPEG;
2942 		bzero(fmtdesc->reserved, sizeof(fmtdesc->reserved));
2943 		break;
2944 	case UDESCSUB_VS_FORMAT_UNCOMPRESSED:
2945 		fmtdesc->flags = 0;
2946 		if (sc->sc_fmtgrp[idx].pixelformat ==
2947 		    V4L2_PIX_FMT_YUYV) {
2948 			(void)strlcpy(fmtdesc->description, "YUYV",
2949 			    sizeof(fmtdesc->description));
2950 			fmtdesc->pixelformat = V4L2_PIX_FMT_YUYV;
2951 		} else if (sc->sc_fmtgrp[idx].pixelformat ==
2952 		    V4L2_PIX_FMT_NV12) {
2953 			(void)strlcpy(fmtdesc->description, "NV12",
2954 			    sizeof(fmtdesc->description));
2955 			fmtdesc->pixelformat = V4L2_PIX_FMT_NV12;
2956 		} else if (sc->sc_fmtgrp[idx].pixelformat ==
2957 		    V4L2_PIX_FMT_UYVY) {
2958 			(void)strlcpy(fmtdesc->description, "UYVY",
2959 			    sizeof(fmtdesc->description));
2960 			fmtdesc->pixelformat = V4L2_PIX_FMT_UYVY;
2961 		} else {
2962 			(void)strlcpy(fmtdesc->description, "Unknown UC Format",
2963 			    sizeof(fmtdesc->description));
2964 			fmtdesc->pixelformat = 0;
2965 		}
2966 		bzero(fmtdesc->reserved, sizeof(fmtdesc->reserved));
2967 		break;
2968 	default:
2969 		fmtdesc->flags = 0;
2970 		(void)strlcpy(fmtdesc->description, "Unknown Format",
2971 		    sizeof(fmtdesc->description));
2972 		fmtdesc->pixelformat = 0;
2973 		bzero(fmtdesc->reserved, sizeof(fmtdesc->reserved));
2974 		break;
2975 	}
2976 
2977 	return (0);
2978 }
2979 
2980 int
uvideo_enum_fsizes(void * v,struct v4l2_frmsizeenum * fsizes)2981 uvideo_enum_fsizes(void *v, struct v4l2_frmsizeenum *fsizes)
2982 {
2983 	struct uvideo_softc *sc = v;
2984 	int idx, found = 0;
2985 
2986 	for (idx = 0; idx < sc->sc_fmtgrp_num; idx++) {
2987 		if (sc->sc_fmtgrp[idx].pixelformat == fsizes->pixel_format) {
2988 			found = 1;
2989 			break;
2990 		}
2991 	}
2992 	if (found == 0)
2993 		return (EINVAL);
2994 
2995 	if (fsizes->index >= sc->sc_fmtgrp[idx].frame_num)
2996 		return (EINVAL);
2997 
2998 	fsizes->type = V4L2_FRMSIZE_TYPE_DISCRETE;
2999 	fsizes->discrete.width =
3000 	    UGETW(sc->sc_fmtgrp[idx].frame[fsizes->index]->wWidth);
3001 	fsizes->discrete.height =
3002 	    UGETW(sc->sc_fmtgrp[idx].frame[fsizes->index]->wHeight);
3003 
3004 	return (0);
3005 }
3006 
3007 int
uvideo_enum_fivals(void * v,struct v4l2_frmivalenum * fivals)3008 uvideo_enum_fivals(void *v, struct v4l2_frmivalenum *fivals)
3009 {
3010 	struct uvideo_softc *sc = v;
3011 	int idx;
3012 	struct uvideo_format_group *fmtgrp = NULL;
3013 	struct usb_video_frame_desc *frame = NULL;
3014 	uint8_t *p;
3015 
3016 	for (idx = 0; idx < sc->sc_fmtgrp_num; idx++) {
3017 		if (sc->sc_fmtgrp[idx].pixelformat == fivals->pixel_format) {
3018 			fmtgrp = &sc->sc_fmtgrp[idx];
3019 			break;
3020 		}
3021 	}
3022 	if (fmtgrp == NULL)
3023 		return (EINVAL);
3024 
3025 	for (idx = 0; idx < fmtgrp->frame_num; idx++) {
3026 		if (UGETW(fmtgrp->frame[idx]->wWidth) == fivals->width &&
3027 		    UGETW(fmtgrp->frame[idx]->wHeight) == fivals->height) {
3028 			frame = fmtgrp->frame[idx];
3029 			break;
3030 		}
3031 	}
3032 	if (frame == NULL)
3033 		return (EINVAL);
3034 
3035 	/* byte-wise pointer to start of frame intervals */
3036 	p = (uint8_t *)frame;
3037 	p += sizeof(struct usb_video_frame_desc);
3038 
3039 	if (frame->bFrameIntervalType == 0) {
3040 		if (fivals->index != 0)
3041 			return (EINVAL);
3042 		fivals->type = V4L2_FRMIVAL_TYPE_STEPWISE;
3043 		fivals->stepwise.min.numerator = UGETDW(p);
3044 		fivals->stepwise.min.denominator = 10000000;
3045 		p += sizeof(uDWord);
3046 		fivals->stepwise.max.numerator = UGETDW(p);
3047 		fivals->stepwise.max.denominator = 10000000;
3048 		p += sizeof(uDWord);
3049 		fivals->stepwise.step.numerator = UGETDW(p);
3050 		fivals->stepwise.step.denominator = 10000000;
3051 		p += sizeof(uDWord);
3052 	} else {
3053 		if (fivals->index >= frame->bFrameIntervalType)
3054 			return (EINVAL);
3055 		p += sizeof(uDWord) * fivals->index;
3056 		if (p > frame->bLength + (uint8_t *)frame) {
3057 			printf("%s: frame desc too short?\n", __func__);
3058 			return (EINVAL);
3059 		}
3060 		fivals->type = V4L2_FRMIVAL_TYPE_DISCRETE;
3061 		fivals->discrete.numerator = UGETDW(p);
3062 		fivals->discrete.denominator = 10000000;
3063 	}
3064 
3065 	return (0);
3066 }
3067 
3068 int
uvideo_s_fmt(void * v,struct v4l2_format * fmt)3069 uvideo_s_fmt(void *v, struct v4l2_format *fmt)
3070 {
3071 	struct uvideo_softc *sc = v;
3072 	struct uvideo_format_group *fmtgrp_save;
3073 	struct usb_video_frame_desc *frame_save;
3074 	struct uvideo_res r;
3075 	int found, i;
3076 	usbd_status error;
3077 
3078 	if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
3079 		return (EINVAL);
3080 
3081 	DPRINTF(1, "%s: %s: requested width=%d, height=%d\n",
3082 	    DEVNAME(sc), __func__, fmt->fmt.pix.width, fmt->fmt.pix.height);
3083 
3084 	/* search requested pixel format */
3085 	for (found = 0, i = 0; i < sc->sc_fmtgrp_num; i++) {
3086 		if (fmt->fmt.pix.pixelformat == sc->sc_fmtgrp[i].pixelformat) {
3087 			found = 1;
3088 			break;
3089 		}
3090 	}
3091 	if (found == 0)
3092 		return (EINVAL);
3093 
3094 	/* check if the format descriptor contains frame descriptors */
3095 	if (sc->sc_fmtgrp[i].frame_num == 0) {
3096 		printf("%s: %s: no frame descriptors found!\n",
3097 		    __func__, DEVNAME(sc));
3098 		return (EINVAL);
3099 	}
3100 
3101 	/* search requested frame resolution */
3102 	uvideo_find_res(sc, i, fmt->fmt.pix.width, fmt->fmt.pix.height, &r);
3103 
3104 	/*
3105 	 * Do negotiation.
3106 	 */
3107 	/* save a copy of current format group in case of negotiation fails */
3108 	fmtgrp_save = sc->sc_fmtgrp_cur;
3109 	frame_save = sc->sc_fmtgrp_cur->frame_cur;
3110 	/* set new format group */
3111 	sc->sc_fmtgrp_cur = &sc->sc_fmtgrp[i];
3112 	sc->sc_fmtgrp[i].frame_cur = sc->sc_fmtgrp[i].frame[r.fidx];
3113 
3114 	/* do device negotiation with commit */
3115 	error = uvideo_vs_negotiation(sc, 1);
3116 	if (error != USBD_NORMAL_COMPLETION) {
3117 		sc->sc_fmtgrp_cur = fmtgrp_save;
3118 		sc->sc_fmtgrp_cur->frame_cur = frame_save;
3119 		return (EINVAL);
3120 	}
3121 	sc->sc_negotiated_flag = 1;
3122 
3123 	/* offer closest resolution which we have found */
3124 	fmt->fmt.pix.width = r.width;
3125 	fmt->fmt.pix.height = r.height;
3126 
3127 	DPRINTF(1, "%s: %s: offered width=%d, height=%d\n",
3128 	    DEVNAME(sc), __func__, r.width, r.height);
3129 
3130 	/* tell our frame buffer size */
3131 	fmt->fmt.pix.sizeimage = UGETDW(sc->sc_desc_probe.dwMaxVideoFrameSize);
3132 
3133 	return (0);
3134 }
3135 
3136 int
uvideo_g_fmt(void * v,struct v4l2_format * fmt)3137 uvideo_g_fmt(void *v, struct v4l2_format *fmt)
3138 {
3139 	struct uvideo_softc *sc = v;
3140 
3141 	if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
3142 		return (EINVAL);
3143 
3144 	fmt->fmt.pix.pixelformat = sc->sc_fmtgrp_cur->pixelformat;
3145 	fmt->fmt.pix.width = UGETW(sc->sc_fmtgrp_cur->frame_cur->wWidth);
3146 	fmt->fmt.pix.height = UGETW(sc->sc_fmtgrp_cur->frame_cur->wHeight);
3147 	fmt->fmt.pix.sizeimage = UGETDW(sc->sc_desc_probe.dwMaxVideoFrameSize);
3148 
3149 	DPRINTF(1, "%s: %s: current width=%d, height=%d\n",
3150 	    DEVNAME(sc), __func__, fmt->fmt.pix.width, fmt->fmt.pix.height);
3151 
3152 	return (0);
3153 }
3154 
3155 int
uvideo_s_parm(void * v,struct v4l2_streamparm * parm)3156 uvideo_s_parm(void *v, struct v4l2_streamparm *parm)
3157 {
3158 	struct uvideo_softc *sc = v;
3159 	usbd_status error;
3160 
3161 	if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
3162 		/*
3163 		 * XXX Only whole number frame rates for now.  Frame
3164 		 * rate is the inverse of time per frame.
3165 		 */
3166 		if (parm->parm.capture.timeperframe.numerator == 0 ||
3167 		    parm->parm.capture.timeperframe.denominator == 0) {
3168 			sc->sc_frame_rate = 0;
3169 		} else {
3170 			sc->sc_frame_rate =
3171 			    parm->parm.capture.timeperframe.denominator /
3172 			    parm->parm.capture.timeperframe.numerator;
3173 		}
3174 	} else
3175 		return (EINVAL);
3176 
3177 	/* renegotiate if necessary */
3178 	if (sc->sc_negotiated_flag) {
3179 		error = uvideo_vs_negotiation(sc, 1);
3180 		if (error != USBD_NORMAL_COMPLETION)
3181 			return (error);
3182 	}
3183 
3184 	return (0);
3185 }
3186 
3187 int
uvideo_g_parm(void * v,struct v4l2_streamparm * parm)3188 uvideo_g_parm(void *v, struct v4l2_streamparm *parm)
3189 {
3190 	struct uvideo_softc *sc = v;
3191 
3192 	if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
3193 		parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
3194 		parm->parm.capture.capturemode = 0;
3195 		parm->parm.capture.timeperframe.numerator =
3196 		    UGETDW(sc->sc_desc_probe.dwFrameInterval);
3197 		parm->parm.capture.timeperframe.denominator = 10000000;
3198 	} else
3199 		return (EINVAL);
3200 
3201 	return (0);
3202 }
3203 
3204 int
uvideo_enum_input(void * v,struct v4l2_input * input)3205 uvideo_enum_input(void *v, struct v4l2_input *input)
3206 {
3207 	if (input->index != 0)
3208 		/* XXX we just support one input for now */
3209 		return (EINVAL);
3210 
3211 	strlcpy(input->name, "Camera Terminal", sizeof(input->name));
3212 	input->type = V4L2_INPUT_TYPE_CAMERA;
3213 
3214 	return (0);
3215 }
3216 
3217 int
uvideo_s_input(void * v,int input)3218 uvideo_s_input(void *v, int input)
3219 {
3220 	if (input != 0)
3221 		/* XXX we just support one input for now */
3222 		return (EINVAL);
3223 
3224 	return (0);
3225 }
3226 
3227 int
uvideo_g_input(void * v,int * input)3228 uvideo_g_input(void *v, int *input)
3229 {
3230 	/* XXX we just support one input for now */
3231 	*input = 0;
3232 
3233 	return (0);
3234 }
3235 
3236 int
uvideo_reqbufs(void * v,struct v4l2_requestbuffers * rb)3237 uvideo_reqbufs(void *v, struct v4l2_requestbuffers *rb)
3238 {
3239 	struct uvideo_softc *sc = v;
3240 	int i, buf_size, buf_size_total;
3241 
3242 	DPRINTF(1, "%s: %s: count=%d\n", DEVNAME(sc), __func__, rb->count);
3243 
3244 	/* We do not support freeing buffers via reqbufs(0) */
3245 	if (rb->count == 0)
3246 		return (EINVAL);
3247 
3248 	if (sc->sc_mmap_count > 0 || sc->sc_mmap_buffer != NULL) {
3249 		DPRINTF(1, "%s: %s: mmap buffers already allocated\n",
3250 		    DEVNAME(sc), __func__);
3251 		return (EINVAL);
3252 	}
3253 
3254 	/* limit the buffers */
3255 	if (rb->count > UVIDEO_MAX_BUFFERS)
3256 		sc->sc_mmap_count = UVIDEO_MAX_BUFFERS;
3257 	else
3258 		sc->sc_mmap_count = rb->count;
3259 
3260 	/* allocate the total mmap buffer */
3261 	buf_size = UGETDW(sc->sc_desc_probe.dwMaxVideoFrameSize);
3262 	if (buf_size >= SIZE_MAX / UVIDEO_MAX_BUFFERS) {
3263 		printf("%s: video frame size too large!\n", DEVNAME(sc));
3264 		sc->sc_mmap_count = 0;
3265 		return (EINVAL);
3266 	}
3267 	buf_size_total = sc->sc_mmap_count * buf_size;
3268 	buf_size_total = round_page(buf_size_total); /* page align buffer */
3269 	sc->sc_mmap_buffer = malloc(buf_size_total, M_USBDEV, M_NOWAIT);
3270 	if (sc->sc_mmap_buffer == NULL) {
3271 		printf("%s: can't allocate mmap buffer!\n", DEVNAME(sc));
3272 		sc->sc_mmap_count = 0;
3273 		return (EINVAL);
3274 	}
3275 	sc->sc_mmap_buffer_size = buf_size_total;
3276 	DPRINTF(1, "%s: allocated %d bytes mmap buffer\n",
3277 	    DEVNAME(sc), buf_size_total);
3278 
3279 	/* fill the v4l2_buffer structure */
3280 	for (i = 0; i < sc->sc_mmap_count; i++) {
3281 		sc->sc_mmap[i].buf = sc->sc_mmap_buffer + (i * buf_size);
3282 
3283 		sc->sc_mmap[i].v4l2_buf.index = i;
3284 		sc->sc_mmap[i].v4l2_buf.m.offset = i * buf_size;
3285 		sc->sc_mmap[i].v4l2_buf.length = buf_size;
3286 		sc->sc_mmap[i].v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
3287 		sc->sc_mmap[i].v4l2_buf.sequence = 0;
3288 		sc->sc_mmap[i].v4l2_buf.field = V4L2_FIELD_NONE;
3289 		sc->sc_mmap[i].v4l2_buf.memory = V4L2_MEMORY_MMAP;
3290 		sc->sc_mmap[i].v4l2_buf.flags = V4L2_BUF_FLAG_MAPPED;
3291 
3292 		DPRINTF(1, "%s: %s: index=%d, offset=%d, length=%d\n",
3293 		    DEVNAME(sc), __func__,
3294 		    sc->sc_mmap[i].v4l2_buf.index,
3295 		    sc->sc_mmap[i].v4l2_buf.m.offset,
3296 		    sc->sc_mmap[i].v4l2_buf.length);
3297 	}
3298 
3299 	/* tell how many buffers we have really allocated */
3300 	rb->count = sc->sc_mmap_count;
3301 
3302 	return (0);
3303 }
3304 
3305 int
uvideo_querybuf(void * v,struct v4l2_buffer * qb)3306 uvideo_querybuf(void *v, struct v4l2_buffer *qb)
3307 {
3308 	struct uvideo_softc *sc = v;
3309 
3310 	if (qb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
3311 	    qb->memory != V4L2_MEMORY_MMAP ||
3312 	    qb->index >= sc->sc_mmap_count)
3313 		return (EINVAL);
3314 
3315 	bcopy(&sc->sc_mmap[qb->index].v4l2_buf, qb,
3316 	    sizeof(struct v4l2_buffer));
3317 
3318 	DPRINTF(1, "%s: %s: index=%d, offset=%d, length=%d\n",
3319 	    DEVNAME(sc), __func__,
3320 	    qb->index,
3321 	    qb->m.offset,
3322 	    qb->length);
3323 
3324 	return (0);
3325 }
3326 
3327 int
uvideo_qbuf(void * v,struct v4l2_buffer * qb)3328 uvideo_qbuf(void *v, struct v4l2_buffer *qb)
3329 {
3330 	struct uvideo_softc *sc = v;
3331 
3332 	if (qb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
3333 	    qb->memory != V4L2_MEMORY_MMAP ||
3334 	    qb->index >= sc->sc_mmap_count)
3335 		return (EINVAL);
3336 
3337 	sc->sc_mmap[qb->index].v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE;
3338 	sc->sc_mmap[qb->index].v4l2_buf.flags |= V4L2_BUF_FLAG_QUEUED;
3339 
3340 	DPRINTF(2, "%s: %s: buffer on index %d ready for queueing\n",
3341 	    DEVNAME(sc), __func__, qb->index);
3342 
3343 	return (0);
3344 }
3345 
3346 int
uvideo_dqbuf(void * v,struct v4l2_buffer * dqb)3347 uvideo_dqbuf(void *v, struct v4l2_buffer *dqb)
3348 {
3349 	struct uvideo_softc *sc = v;
3350 	struct uvideo_mmap *mmap;
3351 	int error;
3352 
3353 	if (dqb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
3354 	    dqb->memory != V4L2_MEMORY_MMAP)
3355 		return (EINVAL);
3356 
3357 	if (SIMPLEQ_EMPTY(&sc->sc_mmap_q)) {
3358 		/* mmap queue is empty, block until first frame is queued */
3359 		error = tsleep_nsec(sc, 0, "vid_mmap", SEC_TO_NSEC(10));
3360 		if (error)
3361 			return (EINVAL);
3362 	}
3363 
3364 	mmap = SIMPLEQ_FIRST(&sc->sc_mmap_q);
3365 	if (mmap == NULL)
3366 		panic("uvideo_dqbuf: NULL pointer!");
3367 
3368 	bcopy(&mmap->v4l2_buf, dqb, sizeof(struct v4l2_buffer));
3369 
3370 	mmap->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE;
3371 	mmap->v4l2_buf.flags &= ~V4L2_BUF_FLAG_QUEUED;
3372 
3373 	DPRINTF(2, "%s: %s: frame dequeued from index %d\n",
3374 	    DEVNAME(sc), __func__, mmap->v4l2_buf.index);
3375 	SIMPLEQ_REMOVE_HEAD(&sc->sc_mmap_q, q_frames);
3376 
3377 	return (0);
3378 }
3379 
3380 int
uvideo_streamon(void * v,int type)3381 uvideo_streamon(void *v, int type)
3382 {
3383 	struct uvideo_softc *sc = v;
3384 	usbd_status error;
3385 
3386 	error = uvideo_vs_init(sc);
3387 	if (error != USBD_NORMAL_COMPLETION)
3388 		return (EINVAL);
3389 
3390 	if (sc->sc_vs_cur->bulk_endpoint)
3391 		uvideo_vs_start_bulk(sc);
3392 	else
3393 		uvideo_vs_start_isoc(sc);
3394 
3395 	return (0);
3396 }
3397 
3398 int
uvideo_streamoff(void * v,int type)3399 uvideo_streamoff(void *v, int type)
3400 {
3401 	struct uvideo_softc *sc = v;
3402 
3403 	uvideo_vs_close(sc);
3404 
3405 	return (0);
3406 }
3407 
3408 int
uvideo_queryctrl(void * v,struct v4l2_queryctrl * qctrl)3409 uvideo_queryctrl(void *v, struct v4l2_queryctrl *qctrl)
3410 {
3411 	struct uvideo_softc *sc = v;
3412 	int i, ret = 0;
3413 	usbd_status error;
3414 	uint8_t *ctrl_data;
3415 	uint16_t ctrl_len;
3416 
3417 	i = uvideo_find_ctrl(sc, qctrl->id);
3418 	if (i == EINVAL)
3419 		return (i);
3420 
3421 	ctrl_len = uvideo_ctrls[i].ctrl_len;
3422 	if (ctrl_len < 1 || ctrl_len > 2) {
3423 		printf("%s: invalid control length: %d\n", __func__, ctrl_len);
3424 		return (EINVAL);
3425 	}
3426 
3427 	ctrl_data = malloc(ctrl_len, M_USBDEV, M_WAITOK | M_CANFAIL);
3428 	if (ctrl_data == NULL) {
3429 		printf("%s: could not allocate control data\n", __func__);
3430 		return (ENOMEM);
3431 	}
3432 
3433 	/* set type */
3434 	qctrl->type = uvideo_ctrls[i].type;
3435 
3436 	/* set description name */
3437 	strlcpy(qctrl->name, uvideo_ctrls[i].name, sizeof(qctrl->name));
3438 
3439 	/* set minimum */
3440 	error = uvideo_vc_get_ctrl(sc, ctrl_data, GET_MIN,
3441 	    sc->sc_desc_vc_pu_cur->bUnitID,
3442 	    uvideo_ctrls[i].ctrl_selector, uvideo_ctrls[i].ctrl_len);
3443 	if (error != USBD_NORMAL_COMPLETION) {
3444 		ret = EINVAL;
3445 		goto out;
3446 	}
3447 	switch (ctrl_len) {
3448 	case 1:
3449 		qctrl->minimum = uvideo_ctrls[i].sig ?
3450 		    *(int8_t *)ctrl_data :
3451 		    *ctrl_data;
3452 		break;
3453 	case 2:
3454 		qctrl->minimum = uvideo_ctrls[i].sig ?
3455 		    (int16_t)UGETW(ctrl_data) :
3456 		    UGETW(ctrl_data);
3457 		break;
3458 	}
3459 
3460 	/* set maximum */
3461 	error = uvideo_vc_get_ctrl(sc, ctrl_data, GET_MAX,
3462 	    sc->sc_desc_vc_pu_cur->bUnitID,
3463 	    uvideo_ctrls[i].ctrl_selector, uvideo_ctrls[i].ctrl_len);
3464 	if (error != USBD_NORMAL_COMPLETION) {
3465 		ret = EINVAL;
3466 		goto out;
3467 	}
3468 	switch(ctrl_len) {
3469 	case 1:
3470 		qctrl->maximum = uvideo_ctrls[i].sig ?
3471 		    *(int8_t *)ctrl_data :
3472 		    *ctrl_data;
3473 		break;
3474 	case 2:
3475 		qctrl->maximum = uvideo_ctrls[i].sig ?
3476 		    (int16_t)UGETW(ctrl_data) :
3477 		    UGETW(ctrl_data);
3478 		break;
3479 	}
3480 
3481 	/* set resolution */
3482 	error = uvideo_vc_get_ctrl(sc, ctrl_data, GET_RES,
3483 	    sc->sc_desc_vc_pu_cur->bUnitID,
3484 	    uvideo_ctrls[i].ctrl_selector, uvideo_ctrls[i].ctrl_len);
3485 	if (error != USBD_NORMAL_COMPLETION) {
3486 		ret = EINVAL;
3487 		goto out;
3488 	}
3489 	switch(ctrl_len) {
3490 	case 1:
3491 		qctrl->step = uvideo_ctrls[i].sig ?
3492 		    *(int8_t *)ctrl_data:
3493 		    *ctrl_data;
3494 		break;
3495 	case 2:
3496 		qctrl->step = uvideo_ctrls[i].sig ?
3497 		    (int16_t)UGETW(ctrl_data) :
3498 		    UGETW(ctrl_data);
3499 		break;
3500 	}
3501 
3502 	/* set default */
3503 	error = uvideo_vc_get_ctrl(sc, ctrl_data, GET_DEF,
3504 	    sc->sc_desc_vc_pu_cur->bUnitID,
3505 	    uvideo_ctrls[i].ctrl_selector, uvideo_ctrls[i].ctrl_len);
3506 	if (error != USBD_NORMAL_COMPLETION) {
3507 		ret = EINVAL;
3508 		goto out;
3509 	}
3510 	switch(ctrl_len) {
3511 	case 1:
3512 		qctrl->default_value = uvideo_ctrls[i].sig ?
3513 		    *(int8_t *)ctrl_data :
3514 		    *ctrl_data;
3515 		break;
3516 	case 2:
3517 		qctrl->default_value = uvideo_ctrls[i].sig ?
3518 		    (int16_t)UGETW(ctrl_data) :
3519 		    UGETW(ctrl_data);
3520 		break;
3521 	}
3522 
3523 	/* set flags */
3524 	qctrl->flags = 0;
3525 
3526 out:
3527 	free(ctrl_data, M_USBDEV, ctrl_len);
3528 
3529 	return (ret);
3530 }
3531 
3532 int
uvideo_g_ctrl(void * v,struct v4l2_control * gctrl)3533 uvideo_g_ctrl(void *v, struct v4l2_control *gctrl)
3534 {
3535 	struct uvideo_softc *sc = v;
3536 	int i, ret = 0;
3537 	usbd_status error;
3538 	uint8_t *ctrl_data;
3539 	uint16_t ctrl_len;
3540 
3541 	i = uvideo_find_ctrl(sc, gctrl->id);
3542 	if (i == EINVAL)
3543 		return (i);
3544 
3545 	ctrl_len = uvideo_ctrls[i].ctrl_len;
3546 	if (ctrl_len < 1 || ctrl_len > 2) {
3547 		printf("%s: invalid control length: %d\n", __func__, ctrl_len);
3548 		return (EINVAL);
3549 	}
3550 
3551 	ctrl_data = malloc(ctrl_len, M_USBDEV, M_WAITOK | M_CANFAIL);
3552 	if (ctrl_data == NULL) {
3553 		printf("%s: could not allocate control data\n", __func__);
3554 		return (ENOMEM);
3555 	}
3556 
3557 	error = uvideo_vc_get_ctrl(sc, ctrl_data, GET_CUR,
3558 	    sc->sc_desc_vc_pu_cur->bUnitID,
3559 	    uvideo_ctrls[i].ctrl_selector, uvideo_ctrls[i].ctrl_len);
3560 	if (error != USBD_NORMAL_COMPLETION) {
3561 		ret = EINVAL;
3562 		goto out;
3563 	}
3564 	switch(ctrl_len) {
3565 	case 1:
3566 		gctrl->value = uvideo_ctrls[i].sig ?
3567 		    *(int8_t *)ctrl_data :
3568 		    *ctrl_data;
3569 		break;
3570 	case 2:
3571 		gctrl->value = uvideo_ctrls[i].sig ?
3572 		    (int16_t)UGETW(ctrl_data) :
3573 		    UGETW(ctrl_data);
3574 		break;
3575 	}
3576 
3577 out:
3578 	free(ctrl_data, M_USBDEV, ctrl_len);
3579 
3580 	return (0);
3581 }
3582 
3583 int
uvideo_s_ctrl(void * v,struct v4l2_control * sctrl)3584 uvideo_s_ctrl(void *v, struct v4l2_control *sctrl)
3585 {
3586 	struct uvideo_softc *sc = v;
3587 	int i, ret = 0;
3588 	usbd_status error;
3589 	uint8_t *ctrl_data;
3590 	uint16_t ctrl_len;
3591 
3592 	i = uvideo_find_ctrl(sc, sctrl->id);
3593 	if (i == EINVAL)
3594 		return (i);
3595 
3596 	ctrl_len = uvideo_ctrls[i].ctrl_len;
3597 	if (ctrl_len < 1 || ctrl_len > 2) {
3598 		printf("%s: invalid control length: %d\n", __func__, ctrl_len);
3599 		return (EINVAL);
3600 	}
3601 
3602 	ctrl_data = malloc(ctrl_len, M_USBDEV, M_WAITOK | M_CANFAIL);
3603 	if (ctrl_data == NULL) {
3604 		printf("%s: could not allocate control data\n", __func__);
3605 		return (ENOMEM);
3606 	}
3607 
3608 	switch(ctrl_len) {
3609 	case 1:
3610 		if (uvideo_ctrls[i].sig)
3611 			*(int8_t *)ctrl_data = sctrl->value;
3612 		else
3613 			*ctrl_data = sctrl->value;
3614 		break;
3615 	case 2:
3616 		USETW(ctrl_data, sctrl->value);
3617 		break;
3618 	}
3619 	error = uvideo_vc_set_ctrl(sc, ctrl_data, SET_CUR,
3620 	    sc->sc_desc_vc_pu_cur->bUnitID,
3621 	    uvideo_ctrls[i].ctrl_selector, uvideo_ctrls[i].ctrl_len);
3622 	if (error != USBD_NORMAL_COMPLETION)
3623 		ret = EINVAL;
3624 
3625 	free(ctrl_data, M_USBDEV, ctrl_len);
3626 
3627 	return (ret);
3628 }
3629 
3630 int
uvideo_try_fmt(void * v,struct v4l2_format * fmt)3631 uvideo_try_fmt(void *v, struct v4l2_format *fmt)
3632 {
3633 	struct uvideo_softc *sc = v;
3634 	struct uvideo_res r;
3635 	int found, i;
3636 
3637 	if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
3638 		return (EINVAL);
3639 
3640 	DPRINTF(1, "%s: %s: requested width=%d, height=%d\n",
3641 	    DEVNAME(sc), __func__, fmt->fmt.pix.width, fmt->fmt.pix.height);
3642 
3643 	/* search requested pixel format */
3644 	for (found = 0, i = 0; i < sc->sc_fmtgrp_num; i++) {
3645 		if (fmt->fmt.pix.pixelformat == sc->sc_fmtgrp[i].pixelformat) {
3646 			found = 1;
3647 			break;
3648 		}
3649 	}
3650 	if (found == 0)
3651 		return (EINVAL);
3652 
3653 	/* search requested frame resolution */
3654 	uvideo_find_res(sc, i, fmt->fmt.pix.width, fmt->fmt.pix.height, &r);
3655 
3656 	/* offer closest resolution which we have found */
3657 	fmt->fmt.pix.width = r.width;
3658 	fmt->fmt.pix.height = r.height;
3659 
3660 	DPRINTF(1, "%s: %s: offered width=%d, height=%d\n",
3661 	    DEVNAME(sc), __func__, r.width, r.height);
3662 
3663 	/* tell our frame buffer size */
3664 	fmt->fmt.pix.sizeimage = sc->sc_frame_buffer.buf_size;
3665 
3666 	return (0);
3667 }
3668 
3669 caddr_t
uvideo_mappage(void * v,off_t off,int prot)3670 uvideo_mappage(void *v, off_t off, int prot)
3671 {
3672 	struct uvideo_softc *sc = v;
3673 	caddr_t p;
3674 
3675 	if (off >= sc->sc_mmap_buffer_size)
3676 		return NULL;
3677 
3678 	if (!sc->sc_mmap_flag)
3679 		sc->sc_mmap_flag = 1;
3680 
3681 	p = sc->sc_mmap_buffer + off;
3682 
3683 	return (p);
3684 }
3685 
3686 int
uvideo_get_bufsize(void * v)3687 uvideo_get_bufsize(void *v)
3688 {
3689 	struct uvideo_softc *sc = v;
3690 
3691 	return (sc->sc_max_fbuf_size);
3692 }
3693 
3694 int
uvideo_start_read(void * v)3695 uvideo_start_read(void *v)
3696 {
3697 	struct uvideo_softc *sc = v;
3698 	usbd_status error;
3699 
3700 	if (sc->sc_mmap_flag)
3701 		sc->sc_mmap_flag = 0;
3702 
3703 	error = uvideo_vs_init(sc);
3704 	if (error != USBD_NORMAL_COMPLETION)
3705 		return (EINVAL);
3706 
3707 	if (sc->sc_vs_cur->bulk_endpoint)
3708 		uvideo_vs_start_bulk(sc);
3709 	else
3710 		uvideo_vs_start_isoc(sc);
3711 
3712 	return (0);
3713 }
3714 
3715 usbd_status
uvideo_usb_control(struct uvideo_softc * sc,uint8_t rt,uint8_t r,uint16_t value,uint8_t * data,size_t length)3716 uvideo_usb_control(struct uvideo_softc *sc, uint8_t rt, uint8_t r,
3717     uint16_t value, uint8_t *data, size_t length)
3718 {
3719 	usb_device_request_t	req;
3720 	usbd_status		err;
3721 
3722 	req.bmRequestType = rt;
3723 	req.bRequest = r;
3724 	USETW(req.wIndex, 0);
3725 	USETW(req.wValue, value);
3726 	USETW(req.wLength, length);
3727 
3728 	err = usbd_do_request(sc->sc_udev, &req, data);
3729 	if (err != USBD_NORMAL_COMPLETION)
3730 		return (err);
3731 
3732 	return (USBD_NORMAL_COMPLETION);
3733 }
3734 
3735 usbd_status
uvideo_ucode_loader_ricoh(struct uvideo_softc * sc)3736 uvideo_ucode_loader_ricoh(struct uvideo_softc *sc)
3737 {
3738 	usbd_status error;
3739 	uint8_t *ucode, len, cbuf;
3740 	size_t ucode_size;
3741 	uint16_t addr;
3742 	int offset = 0, remain;
3743 
3744 	/* get device microcode status */
3745 	cbuf = 0;
3746 	error = uvideo_usb_control(sc, UT_READ_VENDOR_DEVICE,
3747 	    0xa4, 0, &cbuf, sizeof cbuf);
3748 	if (error != USBD_NORMAL_COMPLETION) {
3749 		printf("%s: ucode status error=%s!\n",
3750 		    DEVNAME(sc), usbd_errstr(error));
3751 		return (USBD_INVAL);
3752 	}
3753 	if (cbuf) {
3754 		DPRINTF(1, "%s: microcode already loaded\n", DEVNAME(sc));
3755 		return (USBD_NORMAL_COMPLETION);
3756 	} else {
3757 		DPRINTF(1, "%s: microcode not loaded\n", DEVNAME(sc));
3758 	}
3759 
3760 	/* open microcode file */
3761 	error = loadfirmware(sc->sc_quirk->ucode_name, &ucode, &ucode_size);
3762 	if (error != 0) {
3763 		printf("%s: loadfirmware error=%d!\n", DEVNAME(sc), error);
3764 		return (USBD_INVAL);
3765 	}
3766 
3767 	/* upload microcode */
3768 	remain = ucode_size;
3769 	while (remain > 0) {
3770 		if (remain < 3) {
3771 			printf("%s: ucode file incomplete!\n", DEVNAME(sc));
3772 			free(ucode, M_DEVBUF, ucode_size);
3773 			return (USBD_INVAL);
3774 		}
3775 
3776 		len = ucode[offset];
3777 		addr = ucode[offset + 1] | (ucode[offset + 2] << 8);
3778 		offset += 3;
3779 		remain -= 3;
3780 
3781 		error = uvideo_usb_control(sc, UT_WRITE_VENDOR_DEVICE,
3782 		    0xa0, addr, &ucode[offset], len);
3783 		if (error != USBD_NORMAL_COMPLETION) {
3784 			printf("%s: ucode upload error=%s!\n",
3785 			    DEVNAME(sc), usbd_errstr(error));
3786 			free(ucode, M_DEVBUF, ucode_size);
3787 			return (USBD_INVAL);
3788 		}
3789 		DPRINTF(1, "%s: uploaded %d bytes ucode to addr 0x%x\n",
3790 		    DEVNAME(sc), len, addr);
3791 
3792 		offset += len;
3793 		remain -= len;
3794 	}
3795 	free(ucode, M_DEVBUF, ucode_size);
3796 
3797 	/* activate microcode */
3798 	cbuf = 0;
3799 	error = uvideo_usb_control(sc, UT_WRITE_VENDOR_DEVICE,
3800 	    0xa1, 0, &cbuf, sizeof cbuf);
3801 	if (error != USBD_NORMAL_COMPLETION) {
3802 		printf("%s: ucode activate error=%s!\n",
3803 		    DEVNAME(sc), usbd_errstr(error));
3804 		return (USBD_INVAL);
3805 	}
3806 	DPRINTF(1, "%s: ucode activated\n", DEVNAME(sc));
3807 
3808 	return (USBD_NORMAL_COMPLETION);
3809 }
3810 
3811 /*
3812  * The iSight first generation device will first attach as
3813  * 0x8300 non-UVC.  After the firmware is uploaded, the device
3814  * will reset and come back as 0x8501 UVC compatible.
3815  */
3816 usbd_status
uvideo_ucode_loader_apple_isight(struct uvideo_softc * sc)3817 uvideo_ucode_loader_apple_isight(struct uvideo_softc *sc)
3818 {
3819 	usbd_status error;
3820 	uint8_t *ucode, *code, cbuf;
3821 	size_t ucode_size;
3822 	uint16_t len, req, off, llen;
3823 
3824 	/* open microcode file */
3825 	error = loadfirmware(sc->sc_quirk->ucode_name, &ucode, &ucode_size);
3826 	if (error != 0) {
3827 		printf("%s: loadfirmware error=%d!\n", DEVNAME(sc), error);
3828 		return (USBD_INVAL);
3829 	}
3830 
3831 	/* send init request */
3832 	cbuf = 1;
3833 	error = uvideo_usb_control(sc, UT_WRITE_VENDOR_DEVICE, 0xa0, 0xe600,
3834 	    &cbuf, sizeof(cbuf));
3835 	if (error) {
3836 		printf("%s: failed to init firmware loading state: %s\n",
3837 		    DEVNAME(sc), usbd_errstr(error));
3838 		return (error);
3839 	}
3840 
3841 	code = ucode;
3842 	while (code < ucode + ucode_size) {
3843 		/* get header information */
3844 		len = (code[0] << 8) | code[1];
3845 		req = (code[2] << 8) | code[3];
3846 		DPRINTF(1, "%s: ucode data len=%d, request=0x%x\n",
3847 		    DEVNAME(sc), len, req);
3848 		if (len < 1 || len > 1023) {
3849 			printf("%s: ucode header contains wrong value!\n",
3850 			    DEVNAME(sc));
3851 			free(ucode, M_DEVBUF, ucode_size);
3852 			return (USBD_INVAL);
3853 		}
3854 		code += 4;
3855 
3856 		/* send data to device */
3857 		for (off = 0; len > 0; req += 50, off += 50) {
3858 			llen = len > 50 ? 50 : len;
3859 			len -= llen;
3860 
3861 			DPRINTF(1, "%s: send %d bytes data to offset 0x%x\n",
3862 			    DEVNAME(sc), llen, req);
3863 			error = uvideo_usb_control(sc, UT_WRITE_VENDOR_DEVICE,
3864 			    0xa0, req, code, llen);
3865 			if (error) {
3866 				printf("%s: ucode load failed: %s\n",
3867 				    DEVNAME(sc), usbd_errstr(error));
3868 				free(ucode, M_DEVBUF, ucode_size);
3869 				return (USBD_INVAL);
3870 			}
3871 
3872 			code += llen;
3873 		}
3874 	}
3875 	free(ucode, M_DEVBUF, ucode_size);
3876 
3877 	/* send finished request */
3878 	cbuf = 0;
3879 	error = uvideo_usb_control(sc, UT_WRITE_VENDOR_DEVICE, 0xa0, 0xe600,
3880 	    &cbuf, sizeof(cbuf));
3881 	if (error != USBD_NORMAL_COMPLETION) {
3882 		printf("%s: ucode activate error=%s!\n",
3883 		    DEVNAME(sc), usbd_errstr(error));
3884 		return (USBD_INVAL);
3885 	}
3886 	DPRINTF(1, "%s: ucode activated\n", DEVNAME(sc));
3887 
3888 	/*
3889 	 * We will always return from the attach routine since the device
3890 	 * will reset and re-attach at this point.
3891 	 */
3892 	return (USBD_INVAL);
3893 }
3894