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