Bug Summary

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