Bug Summary

File:dev/usb/uvideo.c
Warning:line 3700, column 21
Assigned value is garbage or undefined

Annotated Source Code

Press '?' to see keyboard shortcuts

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