Bug Summary

File:dev/usb/ugen.c
Warning:line 1212, column 19
The left operand of '==' is a garbage value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ugen.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -D CONFIG_DRM_AMD_DC_DCN3_0 -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/dev/usb/ugen.c
1/* $OpenBSD: ugen.c,v 1.115 2021/02/05 08:17:22 mglocker Exp $ */
2/* $NetBSD: ugen.c,v 1.63 2002/11/26 18:49:48 christos Exp $ */
3/* $FreeBSD: src/sys/dev/usb/ugen.c,v 1.26 1999/11/17 22:33:41 n_hibma Exp $ */
4
5/*
6 * Copyright (c) 1998 The NetBSD Foundation, Inc.
7 * All rights reserved.
8 *
9 * This code is derived from software contributed to The NetBSD Foundation
10 * by Lennart Augustsson (lennart@augustsson.net) at
11 * Carlstedt Research & Technology.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
26 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 */
34
35
36#include <sys/param.h>
37#include <sys/systm.h>
38#include <sys/kernel.h>
39#include <sys/malloc.h>
40#include <sys/device.h>
41#include <sys/ioctl.h>
42#include <sys/conf.h>
43#include <sys/tty.h>
44#include <sys/fcntl.h>
45#include <sys/selinfo.h>
46#include <sys/vnode.h>
47#include <sys/poll.h>
48
49#include <machine/bus.h>
50
51#include <dev/usb/usb.h>
52#include <dev/usb/usbdi.h>
53#include <dev/usb/usbdi_util.h>
54#include <dev/usb/usbdivar.h>
55
56#ifdef UGEN_DEBUG
57#define DPRINTF(x) do { if (ugendebug) printf x; } while (0)
58#define DPRINTFN(n,x) do { if (ugendebug>(n)) printf x; } while (0)
59int ugendebug = 0;
60#else
61#define DPRINTF(x)
62#define DPRINTFN(n,x)
63#endif
64
65#define UGEN_CHUNK128 128 /* chunk size for read */
66#define UGEN_IBSIZE1020 1020 /* buffer size */
67#define UGEN_BBSIZE1024 1024
68
69#define UGEN_NISOFRAMES500 500 /* 0.5 seconds worth */
70#define UGEN_NISOREQS6 6 /* number of outstanding xfer requests */
71#define UGEN_NISORFRMS4 4 /* number of frames (milliseconds) per req */
72
73struct ugen_endpoint {
74 struct ugen_softc *sc;
75 usb_endpoint_descriptor_t *edesc;
76 struct usbd_interface *iface;
77 int state;
78#define UGEN_ASLP0x02 0x02 /* waiting for data */
79#define UGEN_SHORT_OK0x04 0x04 /* short xfers are OK */
80 struct usbd_pipe *pipeh;
81 struct clist q;
82 struct selinfo rsel;
83 u_char *ibuf; /* start of buffer (circular for isoc) */
84 size_t ibuflen;
85 u_char *fill; /* location for input (isoc) */
86 u_char *limit; /* end of circular buffer (isoc) */
87 u_char *cur; /* current read location (isoc) */
88 u_int32_t timeout;
89 struct isoreq {
90 struct ugen_endpoint *sce;
91 struct usbd_xfer *xfer;
92 void *dmabuf;
93 u_int16_t sizes[UGEN_NISORFRMS4];
94 } isoreqs[UGEN_NISOREQS6];
95};
96
97struct ugen_softc {
98 struct device sc_dev; /* base device */
99 struct usbd_device *sc_udev;
100
101 char sc_is_open[USB_MAX_ENDPOINTS16];
102 struct ugen_endpoint sc_endpoints[USB_MAX_ENDPOINTS16][2];
103#define OUT0 0
104#define IN1 1
105
106 int sc_refcnt;
107 u_char sc_secondary;
108};
109
110void ugenintr(struct usbd_xfer *, void *, usbd_status);
111void ugen_isoc_rintr(struct usbd_xfer *, void *, usbd_status);
112int ugen_do_read(struct ugen_softc *, int, struct uio *, int);
113int ugen_do_write(struct ugen_softc *, int, struct uio *, int);
114int ugen_do_ioctl(struct ugen_softc *, int, u_long, caddr_t, int,
115 struct proc *);
116int ugen_do_close(struct ugen_softc *, int, int);
117int ugen_set_config(struct ugen_softc *, int);
118int ugen_set_interface(struct ugen_softc *, int, int);
119int ugen_get_alt_index(struct ugen_softc *, int);
120void ugen_clear_iface_eps(struct ugen_softc *, struct usbd_interface *);
121
122#define UGENUNIT(n)((((unsigned)((n) & 0xff) | (((n) & 0xffff0000) >>
8)) >> 4) & 0xf)
((minor(n)((unsigned)((n) & 0xff) | (((n) & 0xffff0000) >>
8))
>> 4) & 0xf)
123#define UGENENDPOINT(n)(((unsigned)((n) & 0xff) | (((n) & 0xffff0000) >>
8)) & 0xf)
(minor(n)((unsigned)((n) & 0xff) | (((n) & 0xffff0000) >>
8))
& 0xf)
124#define UGENDEV(u, e)(((dev_t)((((0) & 0xff) << 8) | ((((u) << 4) |
(e)) & 0xff) | (((((u) << 4) | (e)) & 0xffff00
) << 8))))
(makedev(0, ((u) << 4) | (e))((dev_t)((((0) & 0xff) << 8) | ((((u) << 4) |
(e)) & 0xff) | (((((u) << 4) | (e)) & 0xffff00
) << 8)))
)
125
126int ugen_match(struct device *, void *, void *);
127void ugen_attach(struct device *, struct device *, void *);
128int ugen_detach(struct device *, int);
129
130struct cfdriver ugen_cd = {
131 NULL((void *)0), "ugen", DV_DULL
132};
133
134const struct cfattach ugen_ca = {
135 sizeof(struct ugen_softc), ugen_match, ugen_attach, ugen_detach
136};
137
138int
139ugen_match(struct device *parent, void *match, void *aux)
140{
141 struct usb_attach_arg *uaa = aux;
142
143 if (uaa->usegeneric) {
144 return (UMATCH_GENERIC1);
145 } else
146 return (UMATCH_NONE0);
147}
148
149void
150ugen_attach(struct device *parent, struct device *self, void *aux)
151{
152 struct ugen_softc *sc = (struct ugen_softc *)self;
153 struct usb_attach_arg *uaa = aux;
154 struct usbd_device *udev;
155 usbd_status err;
156 int conf;
157
158 sc->sc_udev = udev = uaa->device;
159
160 if (usbd_get_devcnt(udev) > 0)
161 sc->sc_secondary = 1;
162
163 if (!sc->sc_secondary) {
164 /* First set configuration index 0, the default one for ugen. */
165 err = usbd_set_config_index(udev, 0, 0);
166 if (err) {
167 printf("%s: setting configuration index 0 failed\n",
168 sc->sc_dev.dv_xname);
169 usbd_deactivate(sc->sc_udev);
170 return;
171 }
172 }
173 conf = usbd_get_config_descriptor(udev)->bConfigurationValue;
174
175 /* Set up all the local state for this configuration. */
176 err = ugen_set_config(sc, conf);
177 if (err) {
178 printf("%s: setting configuration %d failed\n",
179 sc->sc_dev.dv_xname, conf);
180 usbd_deactivate(sc->sc_udev);
181 return;
182 }
183}
184
185int
186ugen_set_config(struct ugen_softc *sc, int configno)
187{
188 struct usbd_device *dev = sc->sc_udev;
189 usb_config_descriptor_t *cdesc;
190 usb_interface_descriptor_t *id;
191 struct usbd_interface *iface;
192 usb_endpoint_descriptor_t *ed;
193 struct ugen_endpoint *sce;
194 int ifaceno, endptno, endpt;
195 int err, dir;
196
197 DPRINTFN(1,("ugen_set_config: %s to configno %d, sc=%p\n",
198 sc->sc_dev.dv_xname, configno, sc));
199
200 /*
201 * We start at 1, not 0, because we don't care whether the
202 * control endpoint is open or not. It is always present.
203 */
204 for (endptno = 1; endptno < USB_MAX_ENDPOINTS16; endptno++)
205 if (sc->sc_is_open[endptno]) {
206 DPRINTFN(1,
207 ("ugen_set_config: %s - endpoint %d is open\n",
208 sc->sc_dev.dv_xname, endptno));
209 return (USBD_IN_USE);
210 }
211
212 /* Avoid setting the current value. */
213 cdesc = usbd_get_config_descriptor(dev);
214 if (cdesc == NULL((void *)0) || cdesc->bConfigurationValue != configno) {
215 if (sc->sc_secondary) {
216 printf("%s: secondary, not changing config to %d\n",
217 __func__, configno);
218 return (USBD_IN_USE);
219 } else {
220 err = usbd_set_config_no(dev, configno, 1);
221 if (err)
222 return (err);
223 cdesc = usbd_get_config_descriptor(dev);
224 if (cdesc == NULL((void *)0) ||
225 cdesc->bConfigurationValue != configno)
226 return (USBD_INVAL);
227 }
228 }
229
230 memset(sc->sc_endpoints, 0, sizeof sc->sc_endpoints)__builtin_memset((sc->sc_endpoints), (0), (sizeof sc->sc_endpoints
))
;
231 for (ifaceno = 0; ifaceno < cdesc->bNumInterfaces; ifaceno++) {
232 DPRINTFN(1,("ugen_set_config: ifaceno %d\n", ifaceno));
233 if (usbd_iface_claimed(sc->sc_udev, ifaceno)) {
234 DPRINTF(("%s: iface %d not available\n", __func__,
235 ifaceno));
236 continue;
237 }
238 err = usbd_device2interface_handle(dev, ifaceno, &iface);
239 if (err)
240 return (err);
241 id = usbd_get_interface_descriptor(iface);
242 for (endptno = 0; endptno < id->bNumEndpoints; endptno++) {
243 ed = usbd_interface2endpoint_descriptor(iface,endptno);
244 endpt = ed->bEndpointAddress;
245 dir = UE_GET_DIR(endpt)((endpt) & 0x80) == UE_DIR_IN0x80 ? IN1 : OUT0;
246 sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)((endpt) & 0x0f)][dir];
247 DPRINTFN(1,("ugen_set_config: endptno %d, endpt=0x%02x"
248 "(%d,%d), sce=%p\n",
249 endptno, endpt, UE_GET_ADDR(endpt),
250 UE_GET_DIR(endpt), sce));
251 sce->sc = sc;
252 sce->edesc = ed;
253 sce->iface = iface;
254 }
255 }
256 return (0);
257}
258
259int
260ugenopen(dev_t dev, int flag, int mode, struct proc *p)
261{
262 struct ugen_softc *sc;
263 int unit = UGENUNIT(dev)((((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) >> 4) & 0xf)
;
264 int endpt = UGENENDPOINT(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0xf)
;
265 usb_endpoint_descriptor_t *edesc;
266 struct ugen_endpoint *sce;
267 int dir, isize;
268 usbd_status err;
269 struct usbd_xfer *xfer;
270 void *buf;
271 int i, j;
272
273 if (unit >= ugen_cd.cd_ndevs)
274 return (ENXIO6);
275 sc = ugen_cd.cd_devs[unit];
276 if (sc == NULL((void *)0))
277 return (ENXIO6);
278
279 DPRINTFN(5, ("ugenopen: flag=%d, mode=%d, unit=%d endpt=%d\n",
280 flag, mode, unit, endpt));
281
282 if (sc == NULL((void *)0) || usbd_is_dying(sc->sc_udev))
283 return (ENXIO6);
284
285 if (sc->sc_is_open[endpt])
286 return (EBUSY16);
287
288 if (endpt == USB_CONTROL_ENDPOINT0) {
289 sc->sc_is_open[USB_CONTROL_ENDPOINT0] = 1;
290 return (0);
291 }
292
293 /* Make sure there are pipes for all directions. */
294 for (dir = OUT0; dir <= IN1; dir++) {
295 if (flag & (dir == OUT0 ? FWRITE0x0002 : FREAD0x0001)) {
296 sce = &sc->sc_endpoints[endpt][dir];
297 if (sce == 0 || sce->edesc == 0)
298 return (ENXIO6);
299 }
300 }
301
302 /* Actually open the pipes. */
303 /* XXX Should back out properly if it fails. */
304 for (dir = OUT0; dir <= IN1; dir++) {
305 if (!(flag & (dir == OUT0 ? FWRITE0x0002 : FREAD0x0001)))
306 continue;
307 sce = &sc->sc_endpoints[endpt][dir];
308 sce->state = 0;
309 sce->timeout = USBD_NO_TIMEOUT0;
310 DPRINTFN(5, ("ugenopen: sc=%p, endpt=%d, dir=%d, sce=%p\n",
311 sc, endpt, dir, sce));
312 edesc = sce->edesc;
313 /* Clear device endpoint toggle. */
314 ugen_clear_iface_eps(sc, sce->iface);
315 switch (UE_GET_XFERTYPE(edesc->bmAttributes)((edesc->bmAttributes) & 0x03)) {
316 case UE_INTERRUPT0x03:
317 if (dir == OUT0) {
318 err = usbd_open_pipe(sce->iface,
319 edesc->bEndpointAddress, 0, &sce->pipeh);
320 if (err)
321 return (EIO5);
322 break;
323 }
324 isize = UGETW(edesc->wMaxPacketSize)(*(u_int16_t *)(edesc->wMaxPacketSize));
325 if (isize == 0) /* shouldn't happen */
326 return (EINVAL22);
327 sce->ibuflen = isize;
328 sce->ibuf = malloc(sce->ibuflen, M_USBDEV102, M_WAITOK0x0001);
329 DPRINTFN(5, ("ugenopen: intr endpt=%d,isize=%d\n",
330 endpt, isize));
331 clalloc(&sce->q, UGEN_IBSIZE1020, 0);
332 err = usbd_open_pipe_intr(sce->iface,
333 edesc->bEndpointAddress,
334 USBD_SHORT_XFER_OK0x04, &sce->pipeh, sce,
335 sce->ibuf, isize, ugenintr,
336 USBD_DEFAULT_INTERVAL(-1));
337 if (err) {
338 free(sce->ibuf, M_USBDEV102, sce->ibuflen);
339 clfree(&sce->q);
340 return (EIO5);
341 }
342 /* Clear HC endpoint toggle. */
343 usbd_clear_endpoint_toggle(sce->pipeh);
344 DPRINTFN(5, ("ugenopen: interrupt open done\n"));
345 break;
346 case UE_BULK0x02:
347 err = usbd_open_pipe(sce->iface,
348 edesc->bEndpointAddress, 0, &sce->pipeh);
349 if (err)
350 return (EIO5);
351 /* Clear HC endpoint toggle. */
352 usbd_clear_endpoint_toggle(sce->pipeh);
353 break;
354 case UE_ISOCHRONOUS0x01:
355 if (dir == OUT0)
356 return (EINVAL22);
357 isize = UGETW(edesc->wMaxPacketSize)(*(u_int16_t *)(edesc->wMaxPacketSize));
358 if (isize == 0) /* shouldn't happen */
359 return (EINVAL22);
360 sce->ibuflen = isize * UGEN_NISOFRAMES500;
361 sce->ibuf = mallocarray(isize, UGEN_NISOFRAMES500,
362 M_USBDEV102, M_WAITOK0x0001);
363 sce->cur = sce->fill = sce->ibuf;
364 sce->limit = sce->ibuf + isize * UGEN_NISOFRAMES500;
365 DPRINTFN(5, ("ugenopen: isoc endpt=%d, isize=%d\n",
366 endpt, isize));
367 err = usbd_open_pipe(sce->iface,
368 edesc->bEndpointAddress, 0, &sce->pipeh);
369 if (err) {
370 free(sce->ibuf, M_USBDEV102, sce->ibuflen);
371 return (EIO5);
372 }
373 for(i = 0; i < UGEN_NISOREQS6; ++i) {
374 sce->isoreqs[i].sce = sce;
375 xfer = usbd_alloc_xfer(sc->sc_udev);
376 if (xfer == 0)
377 goto bad;
378 sce->isoreqs[i].xfer = xfer;
379 buf = usbd_alloc_buffer
380 (xfer, isize * UGEN_NISORFRMS4);
381 if (buf == 0) {
382 i++;
383 goto bad;
384 }
385 sce->isoreqs[i].dmabuf = buf;
386 for(j = 0; j < UGEN_NISORFRMS4; ++j)
387 sce->isoreqs[i].sizes[j] = isize;
388 usbd_setup_isoc_xfer(xfer, sce->pipeh,
389 &sce->isoreqs[i], sce->isoreqs[i].sizes,
390 UGEN_NISORFRMS4, USBD_NO_COPY0x01 |
391 USBD_SHORT_XFER_OK0x04, ugen_isoc_rintr);
392 (void)usbd_transfer(xfer);
393 }
394 DPRINTFN(5, ("ugenopen: isoc open done\n"));
395 break;
396 bad:
397 while (--i >= 0) /* implicit buffer free */
398 usbd_free_xfer(sce->isoreqs[i].xfer);
399 return (ENOMEM12);
400 case UE_CONTROL0x00:
401 sce->timeout = USBD_DEFAULT_TIMEOUT5000;
402 return (EINVAL22);
403 }
404 }
405 sc->sc_is_open[endpt] = 1;
406 return (0);
407}
408
409int
410ugenclose(dev_t dev, int flag, int mode, struct proc *p)
411{
412 struct ugen_softc *sc = ugen_cd.cd_devs[UGENUNIT(dev)((((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) >> 4) & 0xf)
];
413 int endpt = UGENENDPOINT(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0xf)
;
414 int error;
415
416 if (sc == NULL((void *)0) || usbd_is_dying(sc->sc_udev))
417 return (EIO5);
418
419 DPRINTFN(5, ("ugenclose: flag=%d, mode=%d, unit=%d, endpt=%d\n",
420 flag, mode, UGENUNIT(dev), endpt));
421
422 sc->sc_refcnt++;
423 error = ugen_do_close(sc, endpt, flag);
424 if (--sc->sc_refcnt < 0)
425 usb_detach_wakeup(&sc->sc_dev);
426
427 return (error);
428}
429
430int
431ugen_do_close(struct ugen_softc *sc, int endpt, int flag)
432{
433 struct ugen_endpoint *sce;
434 int dir, i;
435
436#ifdef DIAGNOSTIC1
437 if (!sc->sc_is_open[endpt]) {
438 printf("ugenclose: not open\n");
439 return (EINVAL22);
440 }
441#endif
442
443 if (endpt == USB_CONTROL_ENDPOINT0) {
444 DPRINTFN(5, ("ugenclose: close control\n"));
445 sc->sc_is_open[endpt] = 0;
446 return (0);
447 }
448
449 for (dir = OUT0; dir <= IN1; dir++) {
450 if (!(flag & (dir == OUT0 ? FWRITE0x0002 : FREAD0x0001)))
451 continue;
452 sce = &sc->sc_endpoints[endpt][dir];
453 if (sce == NULL((void *)0) || sce->pipeh == NULL((void *)0))
454 continue;
455 DPRINTFN(5, ("ugenclose: endpt=%d dir=%d sce=%p\n",
456 endpt, dir, sce));
457
458 usbd_close_pipe(sce->pipeh);
459 sce->pipeh = NULL((void *)0);
460
461 switch (UE_GET_XFERTYPE(sce->edesc->bmAttributes)((sce->edesc->bmAttributes) & 0x03)) {
462 case UE_INTERRUPT0x03:
463 ndflush(&sce->q, sce->q.c_cc);
464 clfree(&sce->q);
465 break;
466 case UE_ISOCHRONOUS0x01:
467 for (i = 0; i < UGEN_NISOREQS6; ++i)
468 usbd_free_xfer(sce->isoreqs[i].xfer);
469
470 default:
471 break;
472 }
473
474 if (sce->ibuf != NULL((void *)0)) {
475 free(sce->ibuf, M_USBDEV102, sce->ibuflen);
476 sce->ibuf = NULL((void *)0);
477 }
478 }
479 sc->sc_is_open[endpt] = 0;
480
481 return (0);
482}
483
484int
485ugen_do_read(struct ugen_softc *sc, int endpt, struct uio *uio, int flag)
486{
487 struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][IN1];
488 u_int32_t tn;
489 size_t n;
490 char buf[UGEN_BBSIZE1024];
491 struct usbd_xfer *xfer;
492 usbd_status err;
493 int s;
494 int flags, error = 0;
495 u_char buffer[UGEN_CHUNK128];
496
497 DPRINTFN(5, ("%s: ugenread: %d\n", sc->sc_dev.dv_xname, endpt));
498
499 if (usbd_is_dying(sc->sc_udev))
500 return (EIO5);
501
502 if (endpt == USB_CONTROL_ENDPOINT0)
503 return (ENODEV19);
504
505#ifdef DIAGNOSTIC1
506 if (sce->edesc == NULL((void *)0)) {
507 printf("ugenread: no edesc\n");
508 return (EIO5);
509 }
510 if (sce->pipeh == NULL((void *)0)) {
511 printf("ugenread: no pipe\n");
512 return (EIO5);
513 }
514#endif
515
516 switch (UE_GET_XFERTYPE(sce->edesc->bmAttributes)((sce->edesc->bmAttributes) & 0x03)) {
517 case UE_INTERRUPT0x03:
518 /* Block until activity occurred. */
519 s = splusb()splraise(0x5);
520 while (sce->q.c_cc == 0) {
521 if (flag & IO_NDELAY0x10) {
522 splx(s)spllower(s);
523 return (EWOULDBLOCK35);
524 }
525 sce->state |= UGEN_ASLP0x02;
526 DPRINTFN(5, ("ugenread: sleep on %p\n", sce));
527 error = tsleep_nsec(sce, PZERO22 | PCATCH0x100, "ugenrintr",
528 MSEC_TO_NSEC(sce->timeout));
529 sce->state &= ~UGEN_ASLP0x02;
530 DPRINTFN(5, ("ugenread: woke, error=%d\n", error));
531 if (usbd_is_dying(sc->sc_udev))
532 error = EIO5;
533 if (error == EWOULDBLOCK35) { /* timeout, return 0 */
534 error = 0;
535 break;
536 }
537 if (error)
538 break;
539 }
540 splx(s)spllower(s);
541
542 /* Transfer as many chunks as possible. */
543 while (sce->q.c_cc > 0 && uio->uio_resid > 0 && !error) {
544 n = ulmin(sce->q.c_cc, uio->uio_resid);
545 if (n > sizeof(buffer))
546 n = sizeof(buffer);
547
548 /* Remove a small chunk from the input queue. */
549 q_to_b(&sce->q, buffer, n);
550 DPRINTFN(5, ("ugenread: got %zu chars\n", n));
551
552 /* Copy the data to the user process. */
553 error = uiomove(buffer, n, uio);
554 if (error)
555 break;
556 }
557 break;
558 case UE_BULK0x02:
559 xfer = usbd_alloc_xfer(sc->sc_udev);
560 if (xfer == 0)
561 return (ENOMEM12);
562 flags = USBD_SYNCHRONOUS0x02;
563 if (sce->state & UGEN_SHORT_OK0x04)
564 flags |= USBD_SHORT_XFER_OK0x04;
565 if (sce->timeout == 0)
566 flags |= USBD_CATCH0x10;
567 while ((n = ulmin(UGEN_BBSIZE1024, uio->uio_resid)) != 0) {
568 DPRINTFN(1, ("ugenread: start transfer %zu bytes\n",n));
569 usbd_setup_xfer(xfer, sce->pipeh, 0, buf, n,
570 flags, sce->timeout, NULL((void *)0));
571 err = usbd_transfer(xfer);
572 if (err) {
573 usbd_clear_endpoint_stall(sce->pipeh);
574 if (err == USBD_INTERRUPTED)
575 error = EINTR4;
576 else if (err == USBD_TIMEOUT)
577 error = ETIMEDOUT60;
578 else
579 error = EIO5;
580 break;
581 }
582 usbd_get_xfer_status(xfer, NULL((void *)0), NULL((void *)0), &tn, NULL((void *)0));
583 DPRINTFN(1, ("ugenread: got %u bytes\n", tn));
584 error = uiomove(buf, tn, uio);
585 if (error || tn < n)
586 break;
587 }
588 usbd_free_xfer(xfer);
589 break;
590 case UE_ISOCHRONOUS0x01:
591 s = splusb()splraise(0x5);
592 while (sce->cur == sce->fill) {
593 if (flag & IO_NDELAY0x10) {
594 splx(s)spllower(s);
595 return (EWOULDBLOCK35);
596 }
597 sce->state |= UGEN_ASLP0x02;
598 DPRINTFN(5, ("ugenread: sleep on %p\n", sce));
599 error = tsleep_nsec(sce, PZERO22 | PCATCH0x100, "ugenriso",
600 MSEC_TO_NSEC(sce->timeout));
601 sce->state &= ~UGEN_ASLP0x02;
602 DPRINTFN(5, ("ugenread: woke, error=%d\n", error));
603 if (usbd_is_dying(sc->sc_udev))
604 error = EIO5;
605 if (error == EWOULDBLOCK35) { /* timeout, return 0 */
606 error = 0;
607 break;
608 }
609 if (error)
610 break;
611 }
612
613 while (sce->cur != sce->fill && uio->uio_resid > 0 && !error) {
614 if(sce->fill > sce->cur)
615 n = ulmin(sce->fill - sce->cur, uio->uio_resid);
616 else
617 n = ulmin(sce->limit - sce->cur, uio->uio_resid);
618
619 DPRINTFN(5, ("ugenread: isoc got %zu chars\n", n));
620
621 /* Copy the data to the user process. */
622 error = uiomove(sce->cur, n, uio);
623 if (error)
624 break;
625 sce->cur += n;
626 if(sce->cur >= sce->limit)
627 sce->cur = sce->ibuf;
628 }
629 splx(s)spllower(s);
630 break;
631
632
633 default:
634 return (ENXIO6);
635 }
636 return (error);
637}
638
639int
640ugenread(dev_t dev, struct uio *uio, int flag)
641{
642 int endpt = UGENENDPOINT(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0xf)
;
643 struct ugen_softc *sc;
644 int error;
645
646 sc = ugen_cd.cd_devs[UGENUNIT(dev)((((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) >> 4) & 0xf)
];
647
648 sc->sc_refcnt++;
649 error = ugen_do_read(sc, endpt, uio, flag);
650 if (--sc->sc_refcnt < 0)
651 usb_detach_wakeup(&sc->sc_dev);
652 return (error);
653}
654
655int
656ugen_do_write(struct ugen_softc *sc, int endpt, struct uio *uio, int flag)
657{
658 struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][OUT0];
659 size_t n;
660 int flags, error = 0;
661 char buf[UGEN_BBSIZE1024];
662 struct usbd_xfer *xfer;
663 usbd_status err;
664
665 DPRINTFN(5, ("%s: ugenwrite: %d\n", sc->sc_dev.dv_xname, endpt));
666
667 if (usbd_is_dying(sc->sc_udev))
668 return (EIO5);
669
670 if (endpt == USB_CONTROL_ENDPOINT0)
671 return (ENODEV19);
672
673#ifdef DIAGNOSTIC1
674 if (sce->edesc == NULL((void *)0)) {
675 printf("ugenwrite: no edesc\n");
676 return (EIO5);
677 }
678 if (sce->pipeh == NULL((void *)0)) {
679 printf("ugenwrite: no pipe\n");
680 return (EIO5);
681 }
682#endif
683 flags = USBD_SYNCHRONOUS0x02;
684 if (sce->timeout == 0)
685 flags |= USBD_CATCH0x10;
686
687 switch (UE_GET_XFERTYPE(sce->edesc->bmAttributes)((sce->edesc->bmAttributes) & 0x03)) {
688 case UE_BULK0x02:
689 xfer = usbd_alloc_xfer(sc->sc_udev);
690 if (xfer == 0)
691 return (EIO5);
692 while ((n = ulmin(UGEN_BBSIZE1024, uio->uio_resid)) != 0) {
693 error = uiomove(buf, n, uio);
694 if (error)
695 break;
696 DPRINTFN(1, ("ugenwrite: transfer %zu bytes\n", n));
697 usbd_setup_xfer(xfer, sce->pipeh, 0, buf, n,
698 flags, sce->timeout, NULL((void *)0));
699 err = usbd_transfer(xfer);
700 if (err) {
701 usbd_clear_endpoint_stall(sce->pipeh);
702 if (err == USBD_INTERRUPTED)
703 error = EINTR4;
704 else if (err == USBD_TIMEOUT)
705 error = ETIMEDOUT60;
706 else
707 error = EIO5;
708 break;
709 }
710 }
711 usbd_free_xfer(xfer);
712 break;
713 case UE_INTERRUPT0x03:
714 xfer = usbd_alloc_xfer(sc->sc_udev);
715 if (xfer == 0)
716 return (EIO5);
717 while ((n = ulmin(UGETW(sce->edesc->wMaxPacketSize)(*(u_int16_t *)(sce->edesc->wMaxPacketSize)),
718 uio->uio_resid)) != 0) {
719 error = uiomove(buf, n, uio);
720 if (error)
721 break;
722 DPRINTFN(1, ("ugenwrite: transfer %zu bytes\n", n));
723 usbd_setup_xfer(xfer, sce->pipeh, 0, buf, n,
724 flags, sce->timeout, NULL((void *)0));
725 err = usbd_transfer(xfer);
726 if (err) {
727 usbd_clear_endpoint_stall(sce->pipeh);
728 if (err == USBD_INTERRUPTED)
729 error = EINTR4;
730 else if (err == USBD_TIMEOUT)
731 error = ETIMEDOUT60;
732 else
733 error = EIO5;
734 break;
735 }
736 }
737 usbd_free_xfer(xfer);
738 break;
739 default:
740 return (ENXIO6);
741 }
742 return (error);
743}
744
745int
746ugenwrite(dev_t dev, struct uio *uio, int flag)
747{
748 int endpt = UGENENDPOINT(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0xf)
;
749 struct ugen_softc *sc;
750 int error;
751
752 sc = ugen_cd.cd_devs[UGENUNIT(dev)((((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) >> 4) & 0xf)
];
753
754 sc->sc_refcnt++;
755 error = ugen_do_write(sc, endpt, uio, flag);
756 if (--sc->sc_refcnt < 0)
757 usb_detach_wakeup(&sc->sc_dev);
758 return (error);
759}
760
761int
762ugen_detach(struct device *self, int flags)
763{
764 struct ugen_softc *sc = (struct ugen_softc *)self;
765 struct ugen_endpoint *sce;
766 int i, dir, endptno;
767 int s, maj, mn;
768
769 DPRINTF(("ugen_detach: sc=%p flags=%d\n", sc, flags));
770
771 /* Abort all pipes. Causes processes waiting for transfer to wake. */
772 for (i = 0; i < USB_MAX_ENDPOINTS16; i++) {
773 for (dir = OUT0; dir <= IN1; dir++) {
774 sce = &sc->sc_endpoints[i][dir];
775 if (sce && sce->pipeh)
776 usbd_abort_pipe(sce->pipeh);
777 }
778 }
779
780 s = splusb()splraise(0x5);
781 if (--sc->sc_refcnt >= 0) {
782 /* Wake everyone */
783 for (i = 0; i < USB_MAX_ENDPOINTS16; i++)
784 wakeup(&sc->sc_endpoints[i][IN1]);
785 /* Wait for processes to go away. */
786 usb_detach_wait(&sc->sc_dev);
787 }
788 splx(s)spllower(s);
789
790 /* locate the major number */
791 for (maj = 0; maj < nchrdev; maj++)
792 if (cdevsw[maj].d_open == ugenopen)
793 break;
794
795 /* Nuke the vnodes for any open instances (calls close). */
796 mn = self->dv_unit * USB_MAX_ENDPOINTS16;
797 vdevgone(maj, mn, mn + USB_MAX_ENDPOINTS16 - 1, VCHR);
798
799 for (endptno = 0; endptno < USB_MAX_ENDPOINTS16; endptno++) {
800 if (sc->sc_is_open[endptno])
801 ugen_do_close(sc, endptno, FREAD0x0001|FWRITE0x0002);
802 }
803 return (0);
804}
805
806void
807ugenintr(struct usbd_xfer *xfer, void *addr, usbd_status status)
808{
809 struct ugen_endpoint *sce = addr;
810 /*struct ugen_softc *sc = sce->sc;*/
811 u_int32_t count;
812 u_char *ibuf;
813
814 if (status == USBD_CANCELLED)
815 return;
816
817 if (status != USBD_NORMAL_COMPLETION) {
818 DPRINTF(("ugenintr: status=%d\n", status));
819 if (status == USBD_STALLED)
820 usbd_clear_endpoint_stall_async(sce->pipeh);
821 return;
822 }
823
824 usbd_get_xfer_status(xfer, NULL((void *)0), NULL((void *)0), &count, NULL((void *)0));
825 ibuf = sce->ibuf;
826
827 DPRINTFN(5, ("ugenintr: xfer=%p status=%d count=%d\n",
828 xfer, status, count));
829 DPRINTFN(5, (" data = %02x %02x %02x\n",
830 ibuf[0], ibuf[1], ibuf[2]));
831
832 (void)b_to_q(ibuf, count, &sce->q);
833
834 if (sce->state & UGEN_ASLP0x02) {
835 sce->state &= ~UGEN_ASLP0x02;
836 DPRINTFN(5, ("ugen_intr: waking %p\n", sce));
837 wakeup(sce);
838 }
839 selwakeup(&sce->rsel);
840}
841
842void
843ugen_isoc_rintr(struct usbd_xfer *xfer, void *addr, usbd_status status)
844{
845 struct isoreq *req = addr;
846 struct ugen_endpoint *sce = req->sce;
847 u_int32_t count, n;
848 int i, isize;
849
850 /* Return if we are aborting. */
851 if (status == USBD_CANCELLED)
852 return;
853
854 usbd_get_xfer_status(xfer, NULL((void *)0), NULL((void *)0), &count, NULL((void *)0));
855 DPRINTFN(5,("%s: xfer %ld, count=%d\n", __func__, req - sce->isoreqs,
856 count));
857
858 /* throw away oldest input if the buffer is full */
859 if(sce->fill < sce->cur && sce->cur <= sce->fill + count) {
860 sce->cur += count;
861 if(sce->cur >= sce->limit)
862 sce->cur = sce->ibuf + (sce->limit - sce->cur);
863 DPRINTFN(5, ("%s: throwing away %d bytes\n", __func__, count));
864 }
865
866 isize = UGETW(sce->edesc->wMaxPacketSize)(*(u_int16_t *)(sce->edesc->wMaxPacketSize));
867 for (i = 0; i < UGEN_NISORFRMS4; i++) {
868 u_int32_t actlen = req->sizes[i];
869 char const *buf = (char const *)req->dmabuf + isize * i;
870
871 /* copy data to buffer */
872 while (actlen > 0) {
873 n = min(actlen, sce->limit - sce->fill);
874 memcpy(sce->fill, buf, n)__builtin_memcpy((sce->fill), (buf), (n));
875
876 buf += n;
877 actlen -= n;
878 sce->fill += n;
879 if(sce->fill == sce->limit)
880 sce->fill = sce->ibuf;
881 }
882
883 /* setup size for next transfer */
884 req->sizes[i] = isize;
885 }
886
887 usbd_setup_isoc_xfer(xfer, sce->pipeh, req, req->sizes, UGEN_NISORFRMS4,
888 USBD_NO_COPY0x01 | USBD_SHORT_XFER_OK0x04, ugen_isoc_rintr);
889 (void)usbd_transfer(xfer);
890
891 if (sce->state & UGEN_ASLP0x02) {
892 sce->state &= ~UGEN_ASLP0x02;
893 DPRINTFN(5, ("ugen_isoc_rintr: waking %p\n", sce));
894 wakeup(sce);
895 }
896 selwakeup(&sce->rsel);
897}
898
899int
900ugen_set_interface(struct ugen_softc *sc, int ifaceno, int altno)
901{
902 struct usbd_interface *iface;
903 usb_config_descriptor_t *cdesc;
904 usb_interface_descriptor_t *id;
905 usb_endpoint_descriptor_t *ed;
906 struct ugen_endpoint *sce;
907 uint8_t endptno, endpt;
908 int dir, err;
909
910 DPRINTFN(15, ("ugen_set_interface %d %d\n", ifaceno, altno));
911
912 cdesc = usbd_get_config_descriptor(sc->sc_udev);
913 if (ifaceno < 0 || ifaceno >= cdesc->bNumInterfaces ||
914 usbd_iface_claimed(sc->sc_udev, ifaceno))
915 return (USBD_INVAL);
916
917 err = usbd_device2interface_handle(sc->sc_udev, ifaceno, &iface);
918 if (err)
919 return (err);
920 id = usbd_get_interface_descriptor(iface);
921 for (endptno = 0; endptno < id->bNumEndpoints; endptno++) {
922 ed = usbd_interface2endpoint_descriptor(iface,endptno);
923 endpt = ed->bEndpointAddress;
924 dir = UE_GET_DIR(endpt)((endpt) & 0x80) == UE_DIR_IN0x80 ? IN1 : OUT0;
925 sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)((endpt) & 0x0f)][dir];
926 sce->sc = 0;
927 sce->edesc = 0;
928 sce->iface = 0;
929 }
930
931 /* Try to change setting, if this fails put back the descriptors. */
932 err = usbd_set_interface(iface, altno);
933
934 id = usbd_get_interface_descriptor(iface);
935 for (endptno = 0; endptno < id->bNumEndpoints; endptno++) {
936 ed = usbd_interface2endpoint_descriptor(iface,endptno);
937 endpt = ed->bEndpointAddress;
938 dir = UE_GET_DIR(endpt)((endpt) & 0x80) == UE_DIR_IN0x80 ? IN1 : OUT0;
939 sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)((endpt) & 0x0f)][dir];
940 sce->sc = sc;
941 sce->edesc = ed;
942 sce->iface = iface;
943 }
944 return (err);
945}
946
947int
948ugen_get_alt_index(struct ugen_softc *sc, int ifaceno)
949{
950 struct usbd_interface *iface;
951 usbd_status err;
952
953 err = usbd_device2interface_handle(sc->sc_udev, ifaceno, &iface);
954 if (err)
955 return (-1);
956 return (usbd_get_interface_altindex(iface));
957}
958
959int
960ugen_do_ioctl(struct ugen_softc *sc, int endpt, u_long cmd, caddr_t addr,
961 int flag, struct proc *p)
962{
963 struct ugen_endpoint *sce;
964 int err, cdesc_len;
965 struct usbd_interface *iface;
966 struct usb_config_desc *cd;
967 usb_config_descriptor_t *cdesc;
968 struct usb_interface_desc *id;
969 usb_interface_descriptor_t *idesc;
970 struct usb_endpoint_desc *ed;
971 usb_endpoint_descriptor_t *edesc;
972 struct usb_alt_interface *ai;
973 u_int8_t conf, alt;
974
975 DPRINTFN(5, ("ugenioctl: cmd=%08lx\n", cmd));
976 if (usbd_is_dying(sc->sc_udev))
1
Assuming the condition is false
2
Taking false branch
977 return (EIO5);
978
979 switch (cmd) {
3
Control jumps to the 'default' case at line 1005
980 case FIONBIO((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('f')) << 8) | ((126)))
:
981 /* All handled in the upper FS layer. */
982 return (0);
983 case USB_SET_SHORT_XFER((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('U')) << 8) | ((113)))
:
984 if (endpt == USB_CONTROL_ENDPOINT0)
985 return (EINVAL22);
986 /* This flag only affects read */
987 sce = &sc->sc_endpoints[endpt][IN1];
988 if (sce == NULL((void *)0) || sce->pipeh == NULL((void *)0))
989 return (EINVAL22);
990 if (*(int *)addr)
991 sce->state |= UGEN_SHORT_OK0x04;
992 else
993 sce->state &= ~UGEN_SHORT_OK0x04;
994 return (0);
995 case USB_SET_TIMEOUT((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('U')) << 8) | ((114)))
:
996 sce = &sc->sc_endpoints[endpt][IN1];
997 if (sce == NULL((void *)0))
998 return (EINVAL22);
999 sce->timeout = *(int *)addr;
1000 sce = &sc->sc_endpoints[endpt][OUT0];
1001 if (sce == NULL((void *)0))
1002 return (EINVAL22);
1003 sce->timeout = *(int *)addr;
1004 return (0);
1005 default:
1006 break;
4
Execution continues on line 1009
1007 }
1008
1009 if (endpt != USB_CONTROL_ENDPOINT0)
5
Assuming 'endpt' is equal to USB_CONTROL_ENDPOINT
6
Taking false branch
1010 return (EINVAL22);
1011
1012 switch (cmd) {
7
Control jumps to 'case 3223344495:' at line 1156
1013#ifdef UGEN_DEBUG
1014 case USB_SETDEBUG((unsigned long)0x80000000 | ((sizeof(unsigned int) & 0x1fff
) << 16) | ((('U')) << 8) | ((2)))
:
1015 ugendebug = *(int *)addr;
1016 break;
1017#endif
1018 case USB_GET_CONFIG((unsigned long)0x40000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('U')) << 8) | ((100)))
:
1019 err = usbd_get_config(sc->sc_udev, &conf);
1020 if (err)
1021 return (EIO5);
1022 *(int *)addr = conf;
1023 break;
1024 case USB_SET_CONFIG((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('U')) << 8) | ((101)))
:
1025 if (!(flag & FWRITE0x0002))
1026 return (EPERM1);
1027 err = ugen_set_config(sc, *(int *)addr);
1028 switch (err) {
1029 case USBD_NORMAL_COMPLETION:
1030 break;
1031 case USBD_IN_USE:
1032 return (EBUSY16);
1033 default:
1034 return (EIO5);
1035 }
1036 break;
1037 case USB_GET_ALTINTERFACE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct usb_alt_interface) & 0x1fff) << 16) | ((('U'
)) << 8) | ((102)))
:
1038 ai = (struct usb_alt_interface *)addr;
1039 err = usbd_device2interface_handle(sc->sc_udev,
1040 ai->uai_interface_index, &iface);
1041 if (err)
1042 return (EINVAL22);
1043 idesc = usbd_get_interface_descriptor(iface);
1044 if (idesc == NULL((void *)0))
1045 return (EIO5);
1046 ai->uai_alt_no = idesc->bAlternateSetting;
1047 break;
1048 case USB_SET_ALTINTERFACE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct usb_alt_interface) & 0x1fff) << 16) | ((('U'
)) << 8) | ((103)))
:
1049 if (!(flag & FWRITE0x0002))
1050 return (EPERM1);
1051 ai = (struct usb_alt_interface *)addr;
1052 err = usbd_device2interface_handle(sc->sc_udev,
1053 ai->uai_interface_index, &iface);
1054 if (err)
1055 return (EINVAL22);
1056 err = ugen_set_interface(sc, ai->uai_interface_index,
1057 ai->uai_alt_no);
1058 if (err)
1059 return (EINVAL22);
1060 break;
1061 case USB_GET_NO_ALT(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct usb_alt_interface) & 0x1fff) << 16) | ((('U'
)) << 8) | ((104)))
:
1062 ai = (struct usb_alt_interface *)addr;
1063 cdesc = usbd_get_cdesc(sc->sc_udev, ai->uai_config_index,
1064 &cdesc_len);
1065 if (cdesc == NULL((void *)0))
1066 return (EINVAL22);
1067 idesc = usbd_find_idesc(cdesc, ai->uai_interface_index, 0);
1068 if (idesc == NULL((void *)0)) {
1069 free(cdesc, M_TEMP127, UGETW(cdesc->wTotalLength)(*(u_int16_t *)(cdesc->wTotalLength)));
1070 return (EINVAL22);
1071 }
1072 ai->uai_alt_no = usbd_get_no_alts(cdesc,
1073 idesc->bInterfaceNumber);
1074 free(cdesc, M_TEMP127, cdesc_len);
1075 break;
1076 case USB_GET_DEVICE_DESC((unsigned long)0x40000000 | ((sizeof(usb_device_descriptor_t
) & 0x1fff) << 16) | ((('U')) << 8) | ((105))
)
:
1077 *(usb_device_descriptor_t *)addr =
1078 *usbd_get_device_descriptor(sc->sc_udev);
1079 break;
1080 case USB_GET_CONFIG_DESC(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct usb_config_desc) & 0x1fff) << 16) | ((('U')
) << 8) | ((106)))
:
1081 cd = (struct usb_config_desc *)addr;
1082 cdesc = usbd_get_cdesc(sc->sc_udev, cd->ucd_config_index,
1083 &cdesc_len);
1084 if (cdesc == NULL((void *)0))
1085 return (EINVAL22);
1086 cd->ucd_desc = *cdesc;
1087 free(cdesc, M_TEMP127, cdesc_len);
1088 break;
1089 case USB_GET_INTERFACE_DESC(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct usb_interface_desc) & 0x1fff) << 16) | ((('U'
)) << 8) | ((107)))
:
1090 id = (struct usb_interface_desc *)addr;
1091 cdesc = usbd_get_cdesc(sc->sc_udev, id->uid_config_index,
1092 &cdesc_len);
1093 if (cdesc == NULL((void *)0))
1094 return (EINVAL22);
1095 if (id->uid_config_index == USB_CURRENT_CONFIG_INDEX(-1) &&
1096 id->uid_alt_index == USB_CURRENT_ALT_INDEX(-1))
1097 alt = ugen_get_alt_index(sc, id->uid_interface_index);
1098 else
1099 alt = id->uid_alt_index;
1100 idesc = usbd_find_idesc(cdesc, id->uid_interface_index, alt);
1101 if (idesc == NULL((void *)0)) {
1102 free(cdesc, M_TEMP127, UGETW(cdesc->wTotalLength)(*(u_int16_t *)(cdesc->wTotalLength)));
1103 return (EINVAL22);
1104 }
1105 id->uid_desc = *idesc;
1106 free(cdesc, M_TEMP127, cdesc_len);
1107 break;
1108 case USB_GET_ENDPOINT_DESC(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct usb_endpoint_desc) & 0x1fff) << 16) | ((('U'
)) << 8) | ((108)))
:
1109 ed = (struct usb_endpoint_desc *)addr;
1110 cdesc = usbd_get_cdesc(sc->sc_udev, ed->ued_config_index,
1111 &cdesc_len);
1112 if (cdesc == NULL((void *)0))
1113 return (EINVAL22);
1114 if (ed->ued_config_index == USB_CURRENT_CONFIG_INDEX(-1) &&
1115 ed->ued_alt_index == USB_CURRENT_ALT_INDEX(-1))
1116 alt = ugen_get_alt_index(sc, ed->ued_interface_index);
1117 else
1118 alt = ed->ued_alt_index;
1119 edesc = usbd_find_edesc(cdesc, ed->ued_interface_index,
1120 alt, ed->ued_endpoint_index);
1121 if (edesc == NULL((void *)0)) {
1122 free(cdesc, M_TEMP127, UGETW(cdesc->wTotalLength)(*(u_int16_t *)(cdesc->wTotalLength)));
1123 return (EINVAL22);
1124 }
1125 ed->ued_desc = *edesc;
1126 free(cdesc, M_TEMP127, cdesc_len);
1127 break;
1128 case USB_GET_FULL_DESC(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct usb_full_desc) & 0x1fff) << 16) | ((('U')) <<
8) | ((109)))
:
1129 {
1130 u_int len;
1131 struct iovec iov;
1132 struct uio uio;
1133 struct usb_full_desc *fd = (struct usb_full_desc *)addr;
1134 int error;
1135
1136 cdesc = usbd_get_cdesc(sc->sc_udev, fd->ufd_config_index,
1137 &cdesc_len);
1138 if (cdesc == NULL((void *)0))
1139 return (EINVAL22);
1140 len = cdesc_len;
1141 if (len > fd->ufd_size)
1142 len = fd->ufd_size;
1143 iov.iov_base = (caddr_t)fd->ufd_data;
1144 iov.iov_len = len;
1145 uio.uio_iov = &iov;
1146 uio.uio_iovcnt = 1;
1147 uio.uio_resid = len;
1148 uio.uio_offset = 0;
1149 uio.uio_segflg = UIO_USERSPACE;
1150 uio.uio_rw = UIO_READ;
1151 uio.uio_procp = p;
1152 error = uiomove((void *)cdesc, len, &uio);
1153 free(cdesc, M_TEMP127, cdesc_len);
1154 return (error);
1155 }
1156 case USB_DO_REQUEST(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct usb_ctl_request) & 0x1fff) << 16) | ((('U')
) << 8) | ((111)))
:
1157 {
1158 struct usb_ctl_request *ur = (void *)addr;
1159 size_t len = UGETW(ur->ucr_request.wLength)(*(u_int16_t *)(ur->ucr_request.wLength)), mlen;
1160 struct iovec iov;
1161 struct uio uio;
1162 void *ptr = NULL((void *)0);
1163 int error = 0;
1164
1165 if (!(flag & FWRITE0x0002))
8
Assuming the condition is false
9
Taking false branch
1166 return (EPERM1);
1167 /* Avoid requests that would damage the bus integrity. */
1168 if ((ur->ucr_request.bmRequestType == UT_WRITE_DEVICE(0x00 | 0x00 | 0x00) &&
10
Assuming the condition is false
1169 ur->ucr_request.bRequest == UR_SET_ADDRESS0x05) ||
1170 (ur->ucr_request.bmRequestType == UT_WRITE_DEVICE(0x00 | 0x00 | 0x00) &&
1171 ur->ucr_request.bRequest == UR_SET_CONFIG0x09) ||
1172 (ur->ucr_request.bmRequestType == UT_WRITE_INTERFACE(0x00 | 0x00 | 0x01) &&
11
Assuming the condition is false
1173 ur->ucr_request.bRequest == UR_SET_INTERFACE0x0b))
1174 return (EINVAL22);
1175
1176 if (len > 32767)
12
Assuming 'len' is <= 32767
13
Taking false branch
1177 return (EINVAL22);
1178 if (len != 0) {
14
Assuming 'len' is equal to 0
15
Taking false branch
1179 iov.iov_base = (caddr_t)ur->ucr_data;
1180 iov.iov_len = len;
1181 uio.uio_iov = &iov;
1182 uio.uio_iovcnt = 1;
1183 uio.uio_resid = len;
1184 uio.uio_offset = 0;
1185 uio.uio_segflg = UIO_USERSPACE;
1186 uio.uio_rw =
1187 ur->ucr_request.bmRequestType & UT_READ0x80 ?
1188 UIO_READ : UIO_WRITE;
1189 uio.uio_procp = p;
1190 if ((ptr = malloc(len, M_TEMP127, M_NOWAIT0x0002)) == NULL((void *)0)) {
1191 error = ENOMEM12;
1192 goto ret;
1193 }
1194 if (uio.uio_rw == UIO_WRITE) {
1195 error = uiomove(ptr, len, &uio);
1196 if (error)
1197 goto ret;
1198 }
1199 }
1200 sce = &sc->sc_endpoints[endpt][IN1];
1201 err = usbd_do_request_flags(sc->sc_udev, &ur->ucr_request,
1202 ptr, ur->ucr_flags, &ur->ucr_actlen, sce->timeout);
1203 if (err) {
16
Assuming 'err' is 0
17
Taking false branch
1204 error = EIO5;
1205 goto ret;
1206 }
1207 /* Only if USBD_SHORT_XFER_OK is set. */
1208 mlen = len;
1209 if (mlen > ur->ucr_actlen)
18
Assuming 'mlen' is > field 'ucr_actlen'
19
Taking true branch
1210 mlen = ur->ucr_actlen;
1211 if (mlen
19.1
'mlen' is not equal to 0
!= 0) {
20
Taking true branch
1212 if (uio.uio_rw == UIO_READ) {
21
The left operand of '==' is a garbage value
1213 error = uiomove(ptr, mlen, &uio);
1214 if (error)
1215 goto ret;
1216 }
1217 }
1218 ret:
1219 free(ptr, M_TEMP127, len);
1220 return (error);
1221 }
1222 case USB_GET_DEVICEINFO((unsigned long)0x40000000 | ((sizeof(struct usb_device_info)
& 0x1fff) << 16) | ((('U')) << 8) | ((112)))
:
1223 usbd_fill_deviceinfo(sc->sc_udev,
1224 (struct usb_device_info *)addr);
1225 break;
1226 default:
1227 return (EINVAL22);
1228 }
1229 return (0);
1230}
1231
1232int
1233ugenioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
1234{
1235 int endpt = UGENENDPOINT(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0xf)
;
1236 struct ugen_softc *sc;
1237 int error;
1238
1239 sc = ugen_cd.cd_devs[UGENUNIT(dev)((((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) >> 4) & 0xf)
];
1240
1241 sc->sc_refcnt++;
1242 error = ugen_do_ioctl(sc, endpt, cmd, addr, flag, p);
1243 if (--sc->sc_refcnt < 0)
1244 usb_detach_wakeup(&sc->sc_dev);
1245 return (error);
1246}
1247
1248int
1249ugenpoll(dev_t dev, int events, struct proc *p)
1250{
1251 struct ugen_softc *sc;
1252 struct ugen_endpoint *sce;
1253 int revents = 0;
1254 int s;
1255
1256 sc = ugen_cd.cd_devs[UGENUNIT(dev)((((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) >> 4) & 0xf)
];
1257
1258 if (usbd_is_dying(sc->sc_udev))
1259 return (POLLERR0x0008);
1260
1261 /* XXX always IN */
1262 sce = &sc->sc_endpoints[UGENENDPOINT(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0xf)
][IN1];
1263 if (sce == NULL((void *)0))
1264 return (POLLERR0x0008);
1265#ifdef DIAGNOSTIC1
1266 if (!sce->edesc) {
1267 printf("ugenpoll: no edesc\n");
1268 return (POLLERR0x0008);
1269 }
1270 if (!sce->pipeh) {
1271 printf("ugenpoll: no pipe\n");
1272 return (POLLERR0x0008);
1273 }
1274#endif
1275 s = splusb()splraise(0x5);
1276 switch (UE_GET_XFERTYPE(sce->edesc->bmAttributes)((sce->edesc->bmAttributes) & 0x03)) {
1277 case UE_INTERRUPT0x03:
1278 if (events & (POLLIN0x0001 | POLLRDNORM0x0040)) {
1279 if (sce->q.c_cc > 0)
1280 revents |= events & (POLLIN0x0001 | POLLRDNORM0x0040);
1281 else
1282 selrecord(p, &sce->rsel);
1283 }
1284 break;
1285 case UE_ISOCHRONOUS0x01:
1286 if (events & (POLLIN0x0001 | POLLRDNORM0x0040)) {
1287 if (sce->cur != sce->fill)
1288 revents |= events & (POLLIN0x0001 | POLLRDNORM0x0040);
1289 else
1290 selrecord(p, &sce->rsel);
1291 }
1292 break;
1293 case UE_BULK0x02:
1294 /*
1295 * We have no easy way of determining if a read will
1296 * yield any data or a write will happen.
1297 * Pretend they will.
1298 */
1299 revents |= events &
1300 (POLLIN0x0001 | POLLRDNORM0x0040 | POLLOUT0x0004 | POLLWRNORM0x0004);
1301 break;
1302 default:
1303 break;
1304 }
1305 splx(s)spllower(s);
1306 return (revents);
1307}
1308
1309void filt_ugenrdetach(struct knote *);
1310int filt_ugenread_intr(struct knote *, long);
1311int filt_ugenread_isoc(struct knote *, long);
1312int ugenkqfilter(dev_t, struct knote *);
1313
1314void
1315filt_ugenrdetach(struct knote *kn)
1316{
1317 struct ugen_endpoint *sce = (void *)kn->kn_hook;
1318 int s;
1319
1320 s = splusb()splraise(0x5);
1321 klist_remove_locked(&sce->rsel.si_note, kn);
1322 splx(s)spllower(s);
1323}
1324
1325int
1326filt_ugenread_intr(struct knote *kn, long hint)
1327{
1328 struct ugen_endpoint *sce = (void *)kn->kn_hook;
1329
1330 kn->kn_datakn_kevent.data = sce->q.c_cc;
1331 return (kn->kn_datakn_kevent.data > 0);
1332}
1333
1334int
1335filt_ugenread_isoc(struct knote *kn, long hint)
1336{
1337 struct ugen_endpoint *sce = (void *)kn->kn_hook;
1338
1339 if (sce->cur == sce->fill)
1340 return (0);
1341
1342 if (sce->cur < sce->fill)
1343 kn->kn_datakn_kevent.data = sce->fill - sce->cur;
1344 else
1345 kn->kn_datakn_kevent.data = (sce->limit - sce->cur) +
1346 (sce->fill - sce->ibuf);
1347
1348 return (1);
1349}
1350
1351const struct filterops ugenread_intr_filtops = {
1352 .f_flags = FILTEROP_ISFD0x00000001,
1353 .f_attach = NULL((void *)0),
1354 .f_detach = filt_ugenrdetach,
1355 .f_event = filt_ugenread_intr,
1356};
1357
1358const struct filterops ugenread_isoc_filtops = {
1359 .f_flags = FILTEROP_ISFD0x00000001,
1360 .f_attach = NULL((void *)0),
1361 .f_detach = filt_ugenrdetach,
1362 .f_event = filt_ugenread_isoc,
1363};
1364
1365int
1366ugenkqfilter(dev_t dev, struct knote *kn)
1367{
1368 struct ugen_softc *sc;
1369 struct ugen_endpoint *sce;
1370 struct klist *klist;
1371 int s;
1372
1373 sc = ugen_cd.cd_devs[UGENUNIT(dev)((((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) >> 4) & 0xf)
];
1374
1375 if (usbd_is_dying(sc->sc_udev))
1376 return (ENXIO6);
1377
1378 /* XXX always IN */
1379 sce = &sc->sc_endpoints[UGENENDPOINT(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0xf)
][IN1];
1380 if (sce == NULL((void *)0))
1381 return (ENXIO6);
1382
1383 switch (kn->kn_filterkn_kevent.filter) {
1384 case EVFILT_READ(-1):
1385 klist = &sce->rsel.si_note;
1386 switch (UE_GET_XFERTYPE(sce->edesc->bmAttributes)((sce->edesc->bmAttributes) & 0x03)) {
1387 case UE_INTERRUPT0x03:
1388 kn->kn_fop = &ugenread_intr_filtops;
1389 break;
1390 case UE_ISOCHRONOUS0x01:
1391 kn->kn_fop = &ugenread_isoc_filtops;
1392 break;
1393 case UE_BULK0x02:
1394 /*
1395 * We have no easy way of determining if a read will
1396 * yield any data or a write will happen.
1397 */
1398 return (seltrue_kqfilter(dev, kn));
1399 default:
1400 return (EINVAL22);
1401 }
1402 break;
1403
1404 case EVFILT_WRITE(-2):
1405 klist = &sce->rsel.si_note;
1406 switch (UE_GET_XFERTYPE(sce->edesc->bmAttributes)((sce->edesc->bmAttributes) & 0x03)) {
1407 case UE_INTERRUPT0x03:
1408 case UE_ISOCHRONOUS0x01:
1409 /* XXX poll doesn't support this */
1410 return (EINVAL22);
1411
1412 case UE_BULK0x02:
1413 /*
1414 * We have no easy way of determining if a read will
1415 * yield any data or a write will happen.
1416 */
1417 return (seltrue_kqfilter(dev, kn));
1418 default:
1419 return (EINVAL22);
1420 }
1421 break;
1422
1423 default:
1424 return (EINVAL22);
1425 }
1426
1427 kn->kn_hook = (void *)sce;
1428
1429 s = splusb()splraise(0x5);
1430 klist_insert_locked(klist, kn);
1431 splx(s)spllower(s);
1432
1433 return (0);
1434}
1435
1436void
1437ugen_clear_iface_eps(struct ugen_softc *sc, struct usbd_interface *iface)
1438{
1439 usb_interface_descriptor_t *id;
1440 usb_endpoint_descriptor_t *ed;
1441 uint8_t xfertype;
1442 int i;
1443
1444 /* Only clear interface endpoints when none are in use. */
1445 for (i = 0; i < USB_MAX_ENDPOINTS16; i++) {
1446 if (i == USB_CONTROL_ENDPOINT0)
1447 continue;
1448 if (sc->sc_is_open[i] != 0)
1449 return;
1450 }
1451 DPRINTFN(1,("%s: clear interface eps\n", __func__));
1452
1453 id = usbd_get_interface_descriptor(iface);
1454 if (id == NULL((void *)0))
1455 goto bad;
1456
1457 for (i = 0; i < id->bNumEndpoints; i++) {
1458 ed = usbd_interface2endpoint_descriptor(iface, i);
1459 if (ed == NULL((void *)0))
1460 goto bad;
1461
1462 xfertype = UE_GET_XFERTYPE(ed->bmAttributes)((ed->bmAttributes) & 0x03);
1463 if (xfertype == UE_BULK0x02 || xfertype == UE_INTERRUPT0x03) {
1464 if (usbd_clear_endpoint_feature(sc->sc_udev,
1465 ed->bEndpointAddress, UF_ENDPOINT_HALT0))
1466 goto bad;
1467 }
1468 }
1469 return;
1470bad:
1471 printf("%s: clear endpoints failed!\n", __func__);
1472}