Bug Summary

File:dev/usb/uvideo.c
Warning:line 3056, column 3
Value stored to 'p' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

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