1 /* $OpenBSD: ugen.c,v 1.31 2004/10/31 12:10:52 dlg 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 * 3. All advertising materials mentioning features or use of this software
22 * must display the following acknowledgement:
23 * This product includes software developed by the NetBSD
24 * Foundation, Inc. and its contributors.
25 * 4. Neither the name of The NetBSD Foundation nor the names of its
26 * contributors may be used to endorse or promote products derived
27 * from this software without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
30 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
31 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
32 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
33 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
34 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
35 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
36 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
37 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39 * POSSIBILITY OF SUCH DAMAGE.
40 */
41
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/kernel.h>
46 #include <sys/malloc.h>
47 #if defined(__NetBSD__) || defined(__OpenBSD__)
48 #include <sys/device.h>
49 #include <sys/ioctl.h>
50 #elif defined(__FreeBSD__)
51 #include <sys/module.h>
52 #include <sys/bus.h>
53 #include <sys/ioccom.h>
54 #include <sys/conf.h>
55 #include <sys/fcntl.h>
56 #include <sys/filio.h>
57 #endif
58 #include <sys/conf.h>
59 #include <sys/tty.h>
60 #include <sys/file.h>
61 #include <sys/select.h>
62 #include <sys/proc.h>
63 #include <sys/vnode.h>
64 #include <sys/poll.h>
65
66 #include <dev/usb/usb.h>
67 #include <dev/usb/usbdi.h>
68 #include <dev/usb/usbdi_util.h>
69
70 #ifdef UGEN_DEBUG
71 #define DPRINTF(x) do { if (ugendebug) logprintf x; } while (0)
72 #define DPRINTFN(n,x) do { if (ugendebug>(n)) logprintf x; } while (0)
73 int ugendebug = 0;
74 #else
75 #define DPRINTF(x)
76 #define DPRINTFN(n,x)
77 #endif
78
79 #define UGEN_CHUNK 128 /* chunk size for read */
80 #define UGEN_IBSIZE 1020 /* buffer size */
81 #define UGEN_BBSIZE 1024
82
83 #define UGEN_NISOFRAMES 500 /* 0.5 seconds worth */
84 #define UGEN_NISOREQS 6 /* number of outstanding xfer requests */
85 #define UGEN_NISORFRMS 4 /* number of frames (miliseconds) per req */
86
87 struct ugen_endpoint {
88 struct ugen_softc *sc;
89 usb_endpoint_descriptor_t *edesc;
90 usbd_interface_handle iface;
91 int state;
92 #define UGEN_ASLP 0x02 /* waiting for data */
93 #define UGEN_SHORT_OK 0x04 /* short xfers are OK */
94 usbd_pipe_handle pipeh;
95 struct clist q;
96 struct selinfo rsel;
97 u_char *ibuf; /* start of buffer (circular for isoc) */
98 u_char *fill; /* location for input (isoc) */
99 u_char *limit; /* end of circular buffer (isoc) */
100 u_char *cur; /* current read location (isoc) */
101 u_int32_t timeout;
102 struct isoreq {
103 struct ugen_endpoint *sce;
104 usbd_xfer_handle xfer;
105 void *dmabuf;
106 u_int16_t sizes[UGEN_NISORFRMS];
107 } isoreqs[UGEN_NISOREQS];
108 };
109
110 struct ugen_softc {
111 USBBASEDEVICE sc_dev; /* base device */
112 usbd_device_handle sc_udev;
113
114 char sc_is_open[USB_MAX_ENDPOINTS];
115 struct ugen_endpoint sc_endpoints[USB_MAX_ENDPOINTS][2];
116 #define OUT 0
117 #define IN 1
118
119 int sc_refcnt;
120 u_char sc_dying;
121 };
122
123 #if defined(__NetBSD__)
124 dev_type_open(ugenopen);
125 dev_type_close(ugenclose);
126 dev_type_read(ugenread);
127 dev_type_write(ugenwrite);
128 dev_type_ioctl(ugenioctl);
129 dev_type_poll(ugenpoll);
130 dev_type_kqfilter(ugenkqfilter);
131
132 const struct cdevsw ugen_cdevsw = {
133 ugenopen, ugenclose, ugenread, ugenwrite, ugenioctl,
134 nostop, notty, ugenpoll, nommap, ugenkqfilter,
135 };
136 #elif defined(__FreeBSD__)
137 d_open_t ugenopen;
138 d_close_t ugenclose;
139 d_read_t ugenread;
140 d_write_t ugenwrite;
141 d_ioctl_t ugenioctl;
142 d_poll_t ugenpoll;
143
144 #define UGEN_CDEV_MAJOR 114
145
146 Static struct cdevsw ugen_cdevsw = {
147 /* open */ ugenopen,
148 /* close */ ugenclose,
149 /* read */ ugenread,
150 /* write */ ugenwrite,
151 /* ioctl */ ugenioctl,
152 /* poll */ ugenpoll,
153 /* mmap */ nommap,
154 /* strategy */ nostrategy,
155 /* name */ "ugen",
156 /* maj */ UGEN_CDEV_MAJOR,
157 /* dump */ nodump,
158 /* psize */ nopsize,
159 /* flags */ 0,
160 /* bmaj */ -1
161 };
162 #endif
163
164 Static void ugenintr(usbd_xfer_handle xfer, usbd_private_handle addr,
165 usbd_status status);
166 Static void ugen_isoc_rintr(usbd_xfer_handle xfer, usbd_private_handle addr,
167 usbd_status status);
168 Static int ugen_do_read(struct ugen_softc *, int, struct uio *, int);
169 Static int ugen_do_write(struct ugen_softc *, int, struct uio *, int);
170 Static int ugen_do_ioctl(struct ugen_softc *, int, u_long,
171 caddr_t, int, usb_proc_ptr);
172 Static int ugen_set_config(struct ugen_softc *sc, int configno);
173 Static usb_config_descriptor_t *ugen_get_cdesc(struct ugen_softc *sc,
174 int index, int *lenp);
175 Static usbd_status ugen_set_interface(struct ugen_softc *, int, int);
176 Static int ugen_get_alt_index(struct ugen_softc *sc, int ifaceidx);
177
178 #define UGENUNIT(n) ((minor(n) >> 4) & 0xf)
179 #define UGENENDPOINT(n) (minor(n) & 0xf)
180 #define UGENDEV(u, e) (makedev(0, ((u) << 4) | (e)))
181
182 USB_DECLARE_DRIVER(ugen);
183
USB_MATCH(ugen)184 USB_MATCH(ugen)
185 {
186 USB_MATCH_START(ugen, uaa);
187
188 #if 0
189 if (uaa->matchlvl)
190 return (uaa->matchlvl);
191 #endif
192 if (uaa->usegeneric)
193 return (UMATCH_GENERIC);
194 else
195 return (UMATCH_NONE);
196 }
197
USB_ATTACH(ugen)198 USB_ATTACH(ugen)
199 {
200 USB_ATTACH_START(ugen, sc, uaa);
201 usbd_device_handle udev;
202 char devinfo[1024];
203 usbd_status err;
204 int conf;
205
206 usbd_devinfo(uaa->device, 0, devinfo, sizeof devinfo);
207 USB_ATTACH_SETUP;
208 printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo);
209
210 sc->sc_udev = udev = uaa->device;
211
212 /* First set configuration index 0, the default one for ugen. */
213 err = usbd_set_config_index(udev, 0, 0);
214 if (err) {
215 printf("%s: setting configuration index 0 failed\n",
216 USBDEVNAME(sc->sc_dev));
217 sc->sc_dying = 1;
218 USB_ATTACH_ERROR_RETURN;
219 }
220 conf = usbd_get_config_descriptor(udev)->bConfigurationValue;
221
222 /* Set up all the local state for this configuration. */
223 err = ugen_set_config(sc, conf);
224 if (err) {
225 printf("%s: setting configuration %d failed\n",
226 USBDEVNAME(sc->sc_dev), conf);
227 sc->sc_dying = 1;
228 USB_ATTACH_ERROR_RETURN;
229 }
230
231 #ifdef __FreeBSD__
232 {
233 static int global_init_done = 0;
234 if (!global_init_done) {
235 cdevsw_add(&ugen_cdevsw);
236 global_init_done = 1;
237 }
238 }
239 #endif
240
241 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
242 USBDEV(sc->sc_dev));
243
244 USB_ATTACH_SUCCESS_RETURN;
245 }
246
247 Static int
ugen_set_config(struct ugen_softc * sc,int configno)248 ugen_set_config(struct ugen_softc *sc, int configno)
249 {
250 usbd_device_handle dev = sc->sc_udev;
251 usbd_interface_handle iface;
252 usb_endpoint_descriptor_t *ed;
253 struct ugen_endpoint *sce;
254 u_int8_t niface, nendpt;
255 int ifaceno, endptno, endpt;
256 usbd_status err;
257 int dir;
258
259 DPRINTFN(1,("ugen_set_config: %s to configno %d, sc=%p\n",
260 USBDEVNAME(sc->sc_dev), configno, sc));
261
262 /*
263 * We start at 1, not 0, because we don't care whether the
264 * control endpoint is open or not. It is always present.
265 */
266 for (endptno = 1; endptno < USB_MAX_ENDPOINTS; endptno++)
267 if (sc->sc_is_open[endptno]) {
268 DPRINTFN(1,
269 ("ugen_set_config: %s - endpoint %d is open\n",
270 USBDEVNAME(sc->sc_dev), endptno));
271 return (USBD_IN_USE);
272 }
273
274 /* Avoid setting the current value. */
275 if (usbd_get_config_descriptor(dev)->bConfigurationValue != configno) {
276 err = usbd_set_config_no(dev, configno, 1);
277 if (err)
278 return (err);
279 }
280
281 err = usbd_interface_count(dev, &niface);
282 if (err)
283 return (err);
284 memset(sc->sc_endpoints, 0, sizeof sc->sc_endpoints);
285 for (ifaceno = 0; ifaceno < niface; ifaceno++) {
286 DPRINTFN(1,("ugen_set_config: ifaceno %d\n", ifaceno));
287 err = usbd_device2interface_handle(dev, ifaceno, &iface);
288 if (err)
289 return (err);
290 err = usbd_endpoint_count(iface, &nendpt);
291 if (err)
292 return (err);
293 for (endptno = 0; endptno < nendpt; endptno++) {
294 ed = usbd_interface2endpoint_descriptor(iface,endptno);
295 endpt = ed->bEndpointAddress;
296 dir = UE_GET_DIR(endpt) == UE_DIR_IN ? IN : OUT;
297 sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir];
298 DPRINTFN(1,("ugen_set_config: endptno %d, endpt=0x%02x"
299 "(%d,%d), sce=%p\n",
300 endptno, endpt, UE_GET_ADDR(endpt),
301 UE_GET_DIR(endpt), sce));
302 sce->sc = sc;
303 sce->edesc = ed;
304 sce->iface = iface;
305 }
306 }
307 return (USBD_NORMAL_COMPLETION);
308 }
309
310 int
ugenopen(dev_t dev,int flag,int mode,usb_proc_ptr p)311 ugenopen(dev_t dev, int flag, int mode, usb_proc_ptr p)
312 {
313 struct ugen_softc *sc;
314 int unit = UGENUNIT(dev);
315 int endpt = UGENENDPOINT(dev);
316 usb_endpoint_descriptor_t *edesc;
317 struct ugen_endpoint *sce;
318 int dir, isize;
319 usbd_status err;
320 usbd_xfer_handle xfer;
321 void *buf;
322 int i, j;
323
324 USB_GET_SC_OPEN(ugen, unit, sc);
325
326 DPRINTFN(5, ("ugenopen: flag=%d, mode=%d, unit=%d endpt=%d\n",
327 flag, mode, unit, endpt));
328
329 if (sc == NULL || sc->sc_dying)
330 return (ENXIO);
331
332 if (sc->sc_is_open[endpt])
333 return (EBUSY);
334
335 if (endpt == USB_CONTROL_ENDPOINT) {
336 sc->sc_is_open[USB_CONTROL_ENDPOINT] = 1;
337 return (0);
338 }
339
340 /* Make sure there are pipes for all directions. */
341 for (dir = OUT; dir <= IN; dir++) {
342 if (flag & (dir == OUT ? FWRITE : FREAD)) {
343 sce = &sc->sc_endpoints[endpt][dir];
344 if (sce == 0 || sce->edesc == 0)
345 return (ENXIO);
346 }
347 }
348
349 /* Actually open the pipes. */
350 /* XXX Should back out properly if it fails. */
351 for (dir = OUT; dir <= IN; dir++) {
352 if (!(flag & (dir == OUT ? FWRITE : FREAD)))
353 continue;
354 sce = &sc->sc_endpoints[endpt][dir];
355 sce->state = 0;
356 sce->timeout = USBD_NO_TIMEOUT;
357 DPRINTFN(5, ("ugenopen: sc=%p, endpt=%d, dir=%d, sce=%p\n",
358 sc, endpt, dir, sce));
359 edesc = sce->edesc;
360 switch (edesc->bmAttributes & UE_XFERTYPE) {
361 case UE_INTERRUPT:
362 if (dir == OUT) {
363 err = usbd_open_pipe(sce->iface,
364 edesc->bEndpointAddress, 0, &sce->pipeh);
365 if (err)
366 return (EIO);
367 break;
368 }
369 isize = UGETW(edesc->wMaxPacketSize);
370 if (isize == 0) /* shouldn't happen */
371 return (EINVAL);
372 sce->ibuf = malloc(isize, M_USBDEV, M_WAITOK);
373 DPRINTFN(5, ("ugenopen: intr endpt=%d,isize=%d\n",
374 endpt, isize));
375 if (clalloc(&sce->q, UGEN_IBSIZE, 0) == -1)
376 return (ENOMEM);
377 err = usbd_open_pipe_intr(sce->iface,
378 edesc->bEndpointAddress,
379 USBD_SHORT_XFER_OK, &sce->pipeh, sce,
380 sce->ibuf, isize, ugenintr,
381 USBD_DEFAULT_INTERVAL);
382 if (err) {
383 free(sce->ibuf, M_USBDEV);
384 clfree(&sce->q);
385 return (EIO);
386 }
387 DPRINTFN(5, ("ugenopen: interrupt open done\n"));
388 break;
389 case UE_BULK:
390 err = usbd_open_pipe(sce->iface,
391 edesc->bEndpointAddress, 0, &sce->pipeh);
392 if (err)
393 return (EIO);
394 break;
395 case UE_ISOCHRONOUS:
396 if (dir == OUT)
397 return (EINVAL);
398 isize = UGETW(edesc->wMaxPacketSize);
399 if (isize == 0) /* shouldn't happen */
400 return (EINVAL);
401 sce->ibuf = malloc(isize * UGEN_NISOFRAMES,
402 M_USBDEV, M_WAITOK);
403 sce->cur = sce->fill = sce->ibuf;
404 sce->limit = sce->ibuf + isize * UGEN_NISOFRAMES;
405 DPRINTFN(5, ("ugenopen: isoc endpt=%d, isize=%d\n",
406 endpt, isize));
407 err = usbd_open_pipe(sce->iface,
408 edesc->bEndpointAddress, 0, &sce->pipeh);
409 if (err) {
410 free(sce->ibuf, M_USBDEV);
411 return (EIO);
412 }
413 for(i = 0; i < UGEN_NISOREQS; ++i) {
414 sce->isoreqs[i].sce = sce;
415 xfer = usbd_alloc_xfer(sc->sc_udev);
416 if (xfer == 0)
417 goto bad;
418 sce->isoreqs[i].xfer = xfer;
419 buf = usbd_alloc_buffer
420 (xfer, isize * UGEN_NISORFRMS);
421 if (buf == 0) {
422 i++;
423 goto bad;
424 }
425 sce->isoreqs[i].dmabuf = buf;
426 for(j = 0; j < UGEN_NISORFRMS; ++j)
427 sce->isoreqs[i].sizes[j] = isize;
428 usbd_setup_isoc_xfer
429 (xfer, sce->pipeh, &sce->isoreqs[i],
430 sce->isoreqs[i].sizes,
431 UGEN_NISORFRMS, USBD_NO_COPY,
432 ugen_isoc_rintr);
433 (void)usbd_transfer(xfer);
434 }
435 DPRINTFN(5, ("ugenopen: isoc open done\n"));
436 break;
437 bad:
438 while (--i >= 0) /* implicit buffer free */
439 usbd_free_xfer(sce->isoreqs[i].xfer);
440 return (ENOMEM);
441 case UE_CONTROL:
442 sce->timeout = USBD_DEFAULT_TIMEOUT;
443 return (EINVAL);
444 }
445 }
446 sc->sc_is_open[endpt] = 1;
447 return (0);
448 }
449
450 int
ugenclose(dev_t dev,int flag,int mode,usb_proc_ptr p)451 ugenclose(dev_t dev, int flag, int mode, usb_proc_ptr p)
452 {
453 int endpt = UGENENDPOINT(dev);
454 struct ugen_softc *sc;
455 struct ugen_endpoint *sce;
456 int dir;
457 int i;
458
459 USB_GET_SC(ugen, UGENUNIT(dev), sc);
460
461 DPRINTFN(5, ("ugenclose: flag=%d, mode=%d, unit=%d, endpt=%d\n",
462 flag, mode, UGENUNIT(dev), endpt));
463
464 #ifdef DIAGNOSTIC
465 if (!sc->sc_is_open[endpt]) {
466 printf("ugenclose: not open\n");
467 return (EINVAL);
468 }
469 #endif
470
471 if (endpt == USB_CONTROL_ENDPOINT) {
472 DPRINTFN(5, ("ugenclose: close control\n"));
473 sc->sc_is_open[endpt] = 0;
474 return (0);
475 }
476
477 for (dir = OUT; dir <= IN; dir++) {
478 if (!(flag & (dir == OUT ? FWRITE : FREAD)))
479 continue;
480 sce = &sc->sc_endpoints[endpt][dir];
481 if (sce == NULL || sce->pipeh == NULL)
482 continue;
483 DPRINTFN(5, ("ugenclose: endpt=%d dir=%d sce=%p\n",
484 endpt, dir, sce));
485
486 usbd_abort_pipe(sce->pipeh);
487 usbd_close_pipe(sce->pipeh);
488 sce->pipeh = NULL;
489
490 switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
491 case UE_INTERRUPT:
492 ndflush(&sce->q, sce->q.c_cc);
493 clfree(&sce->q);
494 break;
495 case UE_ISOCHRONOUS:
496 for (i = 0; i < UGEN_NISOREQS; ++i)
497 usbd_free_xfer(sce->isoreqs[i].xfer);
498
499 default:
500 break;
501 }
502
503 if (sce->ibuf != NULL) {
504 free(sce->ibuf, M_USBDEV);
505 sce->ibuf = NULL;
506 clfree(&sce->q);
507 }
508 }
509 sc->sc_is_open[endpt] = 0;
510
511 return (0);
512 }
513
514 Static int
ugen_do_read(struct ugen_softc * sc,int endpt,struct uio * uio,int flag)515 ugen_do_read(struct ugen_softc *sc, int endpt, struct uio *uio, int flag)
516 {
517 struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][IN];
518 u_int32_t n, tn;
519 char buf[UGEN_BBSIZE];
520 usbd_xfer_handle xfer;
521 usbd_status err;
522 int s;
523 int error = 0;
524 u_char buffer[UGEN_CHUNK];
525
526 DPRINTFN(5, ("%s: ugenread: %d\n", USBDEVNAME(sc->sc_dev), endpt));
527
528 if (sc->sc_dying)
529 return (EIO);
530
531 if (endpt == USB_CONTROL_ENDPOINT)
532 return (ENODEV);
533
534 #ifdef DIAGNOSTIC
535 if (sce->edesc == NULL) {
536 printf("ugenread: no edesc\n");
537 return (EIO);
538 }
539 if (sce->pipeh == NULL) {
540 printf("ugenread: no pipe\n");
541 return (EIO);
542 }
543 #endif
544
545 switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
546 case UE_INTERRUPT:
547 /* Block until activity occurred. */
548 s = splusb();
549 while (sce->q.c_cc == 0) {
550 if (flag & IO_NDELAY) {
551 splx(s);
552 return (EWOULDBLOCK);
553 }
554 sce->state |= UGEN_ASLP;
555 DPRINTFN(5, ("ugenread: sleep on %p\n", sce));
556 error = tsleep(sce, PZERO | PCATCH, "ugenri", 0);
557 DPRINTFN(5, ("ugenread: woke, error=%d\n", error));
558 if (sc->sc_dying)
559 error = EIO;
560 if (error) {
561 sce->state &= ~UGEN_ASLP;
562 break;
563 }
564 }
565 splx(s);
566
567 /* Transfer as many chunks as possible. */
568 while (sce->q.c_cc > 0 && uio->uio_resid > 0 && !error) {
569 n = min(sce->q.c_cc, uio->uio_resid);
570 if (n > sizeof(buffer))
571 n = sizeof(buffer);
572
573 /* Remove a small chunk from the input queue. */
574 q_to_b(&sce->q, buffer, n);
575 DPRINTFN(5, ("ugenread: got %d chars\n", n));
576
577 /* Copy the data to the user process. */
578 error = uiomove(buffer, n, uio);
579 if (error)
580 break;
581 }
582 break;
583 case UE_BULK:
584 xfer = usbd_alloc_xfer(sc->sc_udev);
585 if (xfer == 0)
586 return (ENOMEM);
587 while ((n = min(UGEN_BBSIZE, uio->uio_resid)) != 0) {
588 DPRINTFN(1, ("ugenread: start transfer %d bytes\n",n));
589 tn = n;
590 err = usbd_bulk_transfer(
591 xfer, sce->pipeh,
592 sce->state & UGEN_SHORT_OK ?
593 USBD_SHORT_XFER_OK : 0,
594 sce->timeout, buf, &tn, "ugenrb");
595 if (err) {
596 if (err == USBD_INTERRUPTED)
597 error = EINTR;
598 else if (err == USBD_TIMEOUT)
599 error = ETIMEDOUT;
600 else
601 error = EIO;
602 break;
603 }
604 DPRINTFN(1, ("ugenread: got %d bytes\n", tn));
605 error = uiomove(buf, tn, uio);
606 if (error || tn < n)
607 break;
608 }
609 usbd_free_xfer(xfer);
610 break;
611 case UE_ISOCHRONOUS:
612 s = splusb();
613 while (sce->cur == sce->fill) {
614 if (flag & IO_NDELAY) {
615 splx(s);
616 return (EWOULDBLOCK);
617 }
618 sce->state |= UGEN_ASLP;
619 DPRINTFN(5, ("ugenread: sleep on %p\n", sce));
620 error = tsleep(sce, PZERO | PCATCH, "ugenri", 0);
621 DPRINTFN(5, ("ugenread: woke, error=%d\n", error));
622 if (sc->sc_dying)
623 error = EIO;
624 if (error) {
625 sce->state &= ~UGEN_ASLP;
626 break;
627 }
628 }
629
630 while (sce->cur != sce->fill && uio->uio_resid > 0 && !error) {
631 if(sce->fill > sce->cur)
632 n = min(sce->fill - sce->cur, uio->uio_resid);
633 else
634 n = min(sce->limit - sce->cur, uio->uio_resid);
635
636 DPRINTFN(5, ("ugenread: isoc got %d chars\n", n));
637
638 /* Copy the data to the user process. */
639 error = uiomove(sce->cur, n, uio);
640 if (error)
641 break;
642 sce->cur += n;
643 if(sce->cur >= sce->limit)
644 sce->cur = sce->ibuf;
645 }
646 splx(s);
647 break;
648
649
650 default:
651 return (ENXIO);
652 }
653 return (error);
654 }
655
656 int
ugenread(dev_t dev,struct uio * uio,int flag)657 ugenread(dev_t dev, struct uio *uio, int flag)
658 {
659 int endpt = UGENENDPOINT(dev);
660 struct ugen_softc *sc;
661 int error;
662
663 USB_GET_SC(ugen, UGENUNIT(dev), sc);
664
665 sc->sc_refcnt++;
666 error = ugen_do_read(sc, endpt, uio, flag);
667 if (--sc->sc_refcnt < 0)
668 usb_detach_wakeup(USBDEV(sc->sc_dev));
669 return (error);
670 }
671
672 Static int
ugen_do_write(struct ugen_softc * sc,int endpt,struct uio * uio,int flag)673 ugen_do_write(struct ugen_softc *sc, int endpt, struct uio *uio, int flag)
674 {
675 struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][OUT];
676 u_int32_t n;
677 int error = 0;
678 char buf[UGEN_BBSIZE];
679 usbd_xfer_handle xfer;
680 usbd_status err;
681
682 DPRINTFN(5, ("%s: ugenwrite: %d\n", USBDEVNAME(sc->sc_dev), endpt));
683
684 if (sc->sc_dying)
685 return (EIO);
686
687 if (endpt == USB_CONTROL_ENDPOINT)
688 return (ENODEV);
689
690 #ifdef DIAGNOSTIC
691 if (sce->edesc == NULL) {
692 printf("ugenwrite: no edesc\n");
693 return (EIO);
694 }
695 if (sce->pipeh == NULL) {
696 printf("ugenwrite: no pipe\n");
697 return (EIO);
698 }
699 #endif
700
701 switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
702 case UE_BULK:
703 xfer = usbd_alloc_xfer(sc->sc_udev);
704 if (xfer == 0)
705 return (EIO);
706 while ((n = min(UGEN_BBSIZE, uio->uio_resid)) != 0) {
707 error = uiomove(buf, n, uio);
708 if (error)
709 break;
710 DPRINTFN(1, ("ugenwrite: transfer %d bytes\n", n));
711 err = usbd_bulk_transfer(xfer, sce->pipeh, 0,
712 sce->timeout, buf, &n,"ugenwb");
713 if (err) {
714 if (err == USBD_INTERRUPTED)
715 error = EINTR;
716 else if (err == USBD_TIMEOUT)
717 error = ETIMEDOUT;
718 else
719 error = EIO;
720 break;
721 }
722 }
723 usbd_free_xfer(xfer);
724 break;
725 case UE_INTERRUPT:
726 xfer = usbd_alloc_xfer(sc->sc_udev);
727 if (xfer == 0)
728 return (EIO);
729 while ((n = min(UGETW(sce->edesc->wMaxPacketSize),
730 uio->uio_resid)) != 0) {
731 error = uiomove(buf, n, uio);
732 if (error)
733 break;
734 DPRINTFN(1, ("ugenwrite: transfer %d bytes\n", n));
735 err = usbd_intr_transfer(xfer, sce->pipeh, 0,
736 sce->timeout, buf, &n, "ugenwi");
737 if (err) {
738 if (err == USBD_INTERRUPTED)
739 error = EINTR;
740 else if (err == USBD_TIMEOUT)
741 error = ETIMEDOUT;
742 else
743 error = EIO;
744 break;
745 }
746 }
747 usbd_free_xfer(xfer);
748 break;
749 default:
750 return (ENXIO);
751 }
752 return (error);
753 }
754
755 int
ugenwrite(dev_t dev,struct uio * uio,int flag)756 ugenwrite(dev_t dev, struct uio *uio, int flag)
757 {
758 int endpt = UGENENDPOINT(dev);
759 struct ugen_softc *sc;
760 int error;
761
762 USB_GET_SC(ugen, UGENUNIT(dev), sc);
763
764 sc->sc_refcnt++;
765 error = ugen_do_write(sc, endpt, uio, flag);
766 if (--sc->sc_refcnt < 0)
767 usb_detach_wakeup(USBDEV(sc->sc_dev));
768 return (error);
769 }
770
771 #if defined(__NetBSD__) || defined(__OpenBSD__)
772 int
ugen_activate(device_ptr_t self,enum devact act)773 ugen_activate(device_ptr_t self, enum devact act)
774 {
775 struct ugen_softc *sc = (struct ugen_softc *)self;
776
777 switch (act) {
778 case DVACT_ACTIVATE:
779 return (EOPNOTSUPP);
780
781 case DVACT_DEACTIVATE:
782 sc->sc_dying = 1;
783 break;
784 }
785 return (0);
786 }
787 #endif
788
USB_DETACH(ugen)789 USB_DETACH(ugen)
790 {
791 USB_DETACH_START(ugen, sc);
792 struct ugen_endpoint *sce;
793 int i, dir;
794 int s;
795 #if defined(__NetBSD__) || defined(__OpenBSD__)
796 int maj, mn;
797
798 DPRINTF(("ugen_detach: sc=%p flags=%d\n", sc, flags));
799 #elif defined(__FreeBSD__)
800 DPRINTF(("ugen_detach: sc=%p\n", sc));
801 #endif
802
803 sc->sc_dying = 1;
804 /* Abort all pipes. Causes processes waiting for transfer to wake. */
805 for (i = 0; i < USB_MAX_ENDPOINTS; i++) {
806 for (dir = OUT; dir <= IN; dir++) {
807 sce = &sc->sc_endpoints[i][dir];
808 if (sce && sce->pipeh)
809 usbd_abort_pipe(sce->pipeh);
810 }
811 }
812
813 s = splusb();
814 if (--sc->sc_refcnt >= 0) {
815 /* Wake everyone */
816 for (i = 0; i < USB_MAX_ENDPOINTS; i++)
817 wakeup(&sc->sc_endpoints[i][IN]);
818 /* Wait for processes to go away. */
819 usb_detach_wait(USBDEV(sc->sc_dev));
820 }
821 splx(s);
822
823 /* locate the major number */
824 #if defined(__NetBSD__)
825 maj = cdevsw_lookup_major(&ugen_cdevsw);
826 #elif defined(__OpenBSD__)
827 for (maj = 0; maj < nchrdev; maj++)
828 if (cdevsw[maj].d_open == ugenopen)
829 break;
830 #endif
831
832 /* Nuke the vnodes for any open instances (calls close). */
833 mn = self->dv_unit * USB_MAX_ENDPOINTS;
834 vdevgone(maj, mn, mn + USB_MAX_ENDPOINTS - 1, VCHR);
835
836 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
837 USBDEV(sc->sc_dev));
838
839 return (0);
840 }
841
842 Static void
ugenintr(usbd_xfer_handle xfer,usbd_private_handle addr,usbd_status status)843 ugenintr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status)
844 {
845 struct ugen_endpoint *sce = addr;
846 /*struct ugen_softc *sc = sce->sc;*/
847 u_int32_t count;
848 u_char *ibuf;
849
850 if (status == USBD_CANCELLED)
851 return;
852
853 if (status != USBD_NORMAL_COMPLETION) {
854 DPRINTF(("ugenintr: status=%d\n", status));
855 if (status == USBD_STALLED)
856 usbd_clear_endpoint_stall_async(sce->pipeh);
857 return;
858 }
859
860 usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
861 ibuf = sce->ibuf;
862
863 DPRINTFN(5, ("ugenintr: xfer=%p status=%d count=%d\n",
864 xfer, status, count));
865 DPRINTFN(5, (" data = %02x %02x %02x\n",
866 ibuf[0], ibuf[1], ibuf[2]));
867
868 (void)b_to_q(ibuf, count, &sce->q);
869
870 if (sce->state & UGEN_ASLP) {
871 sce->state &= ~UGEN_ASLP;
872 DPRINTFN(5, ("ugen_intr: waking %p\n", sce));
873 wakeup(sce);
874 }
875 selwakeup(&sce->rsel);
876 }
877
878 Static void
ugen_isoc_rintr(usbd_xfer_handle xfer,usbd_private_handle addr,usbd_status status)879 ugen_isoc_rintr(usbd_xfer_handle xfer, usbd_private_handle addr,
880 usbd_status status)
881 {
882 struct isoreq *req = addr;
883 struct ugen_endpoint *sce = req->sce;
884 u_int32_t count, n;
885 int i, isize;
886
887 /* Return if we are aborting. */
888 if (status == USBD_CANCELLED)
889 return;
890
891 usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
892 DPRINTFN(5,("ugen_isoc_rintr: xfer %d, count=%d\n", req - sce->isoreqs,
893 count));
894
895 /* throw away oldest input if the buffer is full */
896 if(sce->fill < sce->cur && sce->cur <= sce->fill + count) {
897 sce->cur += count;
898 if(sce->cur >= sce->limit)
899 sce->cur = sce->ibuf + (sce->limit - sce->cur);
900 DPRINTFN(5, ("ugen_isoc_rintr: throwing away %d bytes\n",
901 count));
902 }
903
904 isize = UGETW(sce->edesc->wMaxPacketSize);
905 for (i = 0; i < UGEN_NISORFRMS; i++) {
906 u_int32_t actlen = req->sizes[i];
907 char const *buf = (char const *)req->dmabuf + isize * i;
908
909 /* copy data to buffer */
910 while (actlen > 0) {
911 n = min(actlen, sce->limit - sce->fill);
912 memcpy(sce->fill, buf, n);
913
914 buf += n;
915 actlen -= n;
916 sce->fill += n;
917 if(sce->fill == sce->limit)
918 sce->fill = sce->ibuf;
919 }
920
921 /* setup size for next transfer */
922 req->sizes[i] = isize;
923 }
924
925 usbd_setup_isoc_xfer(xfer, sce->pipeh, req, req->sizes, UGEN_NISORFRMS,
926 USBD_NO_COPY, ugen_isoc_rintr);
927 (void)usbd_transfer(xfer);
928
929 if (sce->state & UGEN_ASLP) {
930 sce->state &= ~UGEN_ASLP;
931 DPRINTFN(5, ("ugen_isoc_rintr: waking %p\n", sce));
932 wakeup(sce);
933 }
934 selwakeup(&sce->rsel);
935 }
936
937 Static usbd_status
ugen_set_interface(struct ugen_softc * sc,int ifaceidx,int altno)938 ugen_set_interface(struct ugen_softc *sc, int ifaceidx, int altno)
939 {
940 usbd_interface_handle iface;
941 usb_endpoint_descriptor_t *ed;
942 usbd_status err;
943 struct ugen_endpoint *sce;
944 u_int8_t niface, nendpt, endptno, endpt;
945 int dir;
946
947 DPRINTFN(15, ("ugen_set_interface %d %d\n", ifaceidx, altno));
948
949 err = usbd_interface_count(sc->sc_udev, &niface);
950 if (err)
951 return (err);
952 if (ifaceidx < 0 || ifaceidx >= niface)
953 return (USBD_INVAL);
954
955 err = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface);
956 if (err)
957 return (err);
958 err = usbd_endpoint_count(iface, &nendpt);
959 if (err)
960 return (err);
961 /* XXX should only do this after setting new altno has succeeded */
962 for (endptno = 0; endptno < nendpt; endptno++) {
963 ed = usbd_interface2endpoint_descriptor(iface,endptno);
964 endpt = ed->bEndpointAddress;
965 dir = UE_GET_DIR(endpt) == UE_DIR_IN ? IN : OUT;
966 sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir];
967 sce->sc = 0;
968 sce->edesc = 0;
969 sce->iface = 0;
970 }
971
972 /* change setting */
973 err = usbd_set_interface(iface, altno);
974 if (err)
975 return (err);
976
977 err = usbd_endpoint_count(iface, &nendpt);
978 if (err)
979 return (err);
980 for (endptno = 0; endptno < nendpt; endptno++) {
981 ed = usbd_interface2endpoint_descriptor(iface,endptno);
982 endpt = ed->bEndpointAddress;
983 dir = UE_GET_DIR(endpt) == UE_DIR_IN ? IN : OUT;
984 sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir];
985 sce->sc = sc;
986 sce->edesc = ed;
987 sce->iface = iface;
988 }
989 return (0);
990 }
991
992 /* Retrieve a complete descriptor for a certain device and index. */
993 Static usb_config_descriptor_t *
ugen_get_cdesc(struct ugen_softc * sc,int index,int * lenp)994 ugen_get_cdesc(struct ugen_softc *sc, int index, int *lenp)
995 {
996 usb_config_descriptor_t *cdesc, *tdesc, cdescr;
997 int len;
998 usbd_status err;
999
1000 if (index == USB_CURRENT_CONFIG_INDEX) {
1001 tdesc = usbd_get_config_descriptor(sc->sc_udev);
1002 len = UGETW(tdesc->wTotalLength);
1003 if (lenp)
1004 *lenp = len;
1005 cdesc = malloc(len, M_TEMP, M_WAITOK);
1006 memcpy(cdesc, tdesc, len);
1007 DPRINTFN(5,("ugen_get_cdesc: current, len=%d\n", len));
1008 } else {
1009 err = usbd_get_config_desc(sc->sc_udev, index, &cdescr);
1010 if (err)
1011 return (0);
1012 len = UGETW(cdescr.wTotalLength);
1013 DPRINTFN(5,("ugen_get_cdesc: index=%d, len=%d\n", index, len));
1014 if (lenp)
1015 *lenp = len;
1016 cdesc = malloc(len, M_TEMP, M_WAITOK);
1017 err = usbd_get_config_desc_full(sc->sc_udev, index, cdesc,
1018 len);
1019 if (err) {
1020 free(cdesc, M_TEMP);
1021 return (0);
1022 }
1023 }
1024 return (cdesc);
1025 }
1026
1027 Static int
ugen_get_alt_index(struct ugen_softc * sc,int ifaceidx)1028 ugen_get_alt_index(struct ugen_softc *sc, int ifaceidx)
1029 {
1030 usbd_interface_handle iface;
1031 usbd_status err;
1032
1033 err = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface);
1034 if (err)
1035 return (-1);
1036 return (usbd_get_interface_altindex(iface));
1037 }
1038
1039 Static int
ugen_do_ioctl(struct ugen_softc * sc,int endpt,u_long cmd,caddr_t addr,int flag,usb_proc_ptr p)1040 ugen_do_ioctl(struct ugen_softc *sc, int endpt, u_long cmd,
1041 caddr_t addr, int flag, usb_proc_ptr p)
1042 {
1043 struct ugen_endpoint *sce;
1044 usbd_status err;
1045 usbd_interface_handle iface;
1046 struct usb_config_desc *cd;
1047 usb_config_descriptor_t *cdesc;
1048 struct usb_interface_desc *id;
1049 usb_interface_descriptor_t *idesc;
1050 struct usb_endpoint_desc *ed;
1051 usb_endpoint_descriptor_t *edesc;
1052 struct usb_alt_interface *ai;
1053 struct usb_string_desc *si;
1054 u_int8_t conf, alt;
1055
1056 DPRINTFN(5, ("ugenioctl: cmd=%08lx\n", cmd));
1057 if (sc->sc_dying)
1058 return (EIO);
1059
1060 switch (cmd) {
1061 case FIONBIO:
1062 /* All handled in the upper FS layer. */
1063 return (0);
1064 case USB_SET_SHORT_XFER:
1065 if (endpt == USB_CONTROL_ENDPOINT)
1066 return (EINVAL);
1067 /* This flag only affects read */
1068 sce = &sc->sc_endpoints[endpt][IN];
1069 if (sce == NULL || sce->pipeh == NULL)
1070 return (EINVAL);
1071 if (*(int *)addr)
1072 sce->state |= UGEN_SHORT_OK;
1073 else
1074 sce->state &= ~UGEN_SHORT_OK;
1075 return (0);
1076 case USB_SET_TIMEOUT:
1077 sce = &sc->sc_endpoints[endpt][IN];
1078 if (sce == NULL
1079 /* XXX this shouldn't happen, but the distinction between
1080 input and output pipes isn't clear enough.
1081 || sce->pipeh == NULL */
1082 )
1083 return (EINVAL);
1084 sce->timeout = *(int *)addr;
1085 return (0);
1086 default:
1087 break;
1088 }
1089
1090 if (endpt != USB_CONTROL_ENDPOINT)
1091 return (EINVAL);
1092
1093 switch (cmd) {
1094 #ifdef UGEN_DEBUG
1095 case USB_SETDEBUG:
1096 ugendebug = *(int *)addr;
1097 break;
1098 #endif
1099 case USB_GET_CONFIG:
1100 err = usbd_get_config(sc->sc_udev, &conf);
1101 if (err)
1102 return (EIO);
1103 *(int *)addr = conf;
1104 break;
1105 case USB_SET_CONFIG:
1106 if (!(flag & FWRITE))
1107 return (EPERM);
1108 err = ugen_set_config(sc, *(int *)addr);
1109 switch (err) {
1110 case USBD_NORMAL_COMPLETION:
1111 break;
1112 case USBD_IN_USE:
1113 return (EBUSY);
1114 default:
1115 return (EIO);
1116 }
1117 break;
1118 case USB_GET_ALTINTERFACE:
1119 ai = (struct usb_alt_interface *)addr;
1120 err = usbd_device2interface_handle(sc->sc_udev,
1121 ai->uai_interface_index, &iface);
1122 if (err)
1123 return (EINVAL);
1124 idesc = usbd_get_interface_descriptor(iface);
1125 if (idesc == NULL)
1126 return (EIO);
1127 ai->uai_alt_no = idesc->bAlternateSetting;
1128 break;
1129 case USB_SET_ALTINTERFACE:
1130 if (!(flag & FWRITE))
1131 return (EPERM);
1132 ai = (struct usb_alt_interface *)addr;
1133 err = usbd_device2interface_handle(sc->sc_udev,
1134 ai->uai_interface_index, &iface);
1135 if (err)
1136 return (EINVAL);
1137 err = ugen_set_interface(sc, ai->uai_interface_index,
1138 ai->uai_alt_no);
1139 if (err)
1140 return (EINVAL);
1141 break;
1142 case USB_GET_NO_ALT:
1143 ai = (struct usb_alt_interface *)addr;
1144 cdesc = ugen_get_cdesc(sc, ai->uai_config_index, 0);
1145 if (cdesc == NULL)
1146 return (EINVAL);
1147 idesc = usbd_find_idesc(cdesc, ai->uai_interface_index, 0);
1148 if (idesc == NULL) {
1149 free(cdesc, M_TEMP);
1150 return (EINVAL);
1151 }
1152 ai->uai_alt_no = usbd_get_no_alts(cdesc,
1153 idesc->bInterfaceNumber);
1154 free(cdesc, M_TEMP);
1155 break;
1156 case USB_GET_DEVICE_DESC:
1157 *(usb_device_descriptor_t *)addr =
1158 *usbd_get_device_descriptor(sc->sc_udev);
1159 break;
1160 case USB_GET_CONFIG_DESC:
1161 cd = (struct usb_config_desc *)addr;
1162 cdesc = ugen_get_cdesc(sc, cd->ucd_config_index, 0);
1163 if (cdesc == NULL)
1164 return (EINVAL);
1165 cd->ucd_desc = *cdesc;
1166 free(cdesc, M_TEMP);
1167 break;
1168 case USB_GET_INTERFACE_DESC:
1169 id = (struct usb_interface_desc *)addr;
1170 cdesc = ugen_get_cdesc(sc, id->uid_config_index, 0);
1171 if (cdesc == NULL)
1172 return (EINVAL);
1173 if (id->uid_config_index == USB_CURRENT_CONFIG_INDEX &&
1174 id->uid_alt_index == USB_CURRENT_ALT_INDEX)
1175 alt = ugen_get_alt_index(sc, id->uid_interface_index);
1176 else
1177 alt = id->uid_alt_index;
1178 idesc = usbd_find_idesc(cdesc, id->uid_interface_index, alt);
1179 if (idesc == NULL) {
1180 free(cdesc, M_TEMP);
1181 return (EINVAL);
1182 }
1183 id->uid_desc = *idesc;
1184 free(cdesc, M_TEMP);
1185 break;
1186 case USB_GET_ENDPOINT_DESC:
1187 ed = (struct usb_endpoint_desc *)addr;
1188 cdesc = ugen_get_cdesc(sc, ed->ued_config_index, 0);
1189 if (cdesc == NULL)
1190 return (EINVAL);
1191 if (ed->ued_config_index == USB_CURRENT_CONFIG_INDEX &&
1192 ed->ued_alt_index == USB_CURRENT_ALT_INDEX)
1193 alt = ugen_get_alt_index(sc, ed->ued_interface_index);
1194 else
1195 alt = ed->ued_alt_index;
1196 edesc = usbd_find_edesc(cdesc, ed->ued_interface_index,
1197 alt, ed->ued_endpoint_index);
1198 if (edesc == NULL) {
1199 free(cdesc, M_TEMP);
1200 return (EINVAL);
1201 }
1202 ed->ued_desc = *edesc;
1203 free(cdesc, M_TEMP);
1204 break;
1205 case USB_GET_FULL_DESC:
1206 {
1207 int len;
1208 struct iovec iov;
1209 struct uio uio;
1210 struct usb_full_desc *fd = (struct usb_full_desc *)addr;
1211 int error;
1212
1213 cdesc = ugen_get_cdesc(sc, fd->ufd_config_index, &len);
1214 if (len > fd->ufd_size)
1215 len = fd->ufd_size;
1216 iov.iov_base = (caddr_t)fd->ufd_data;
1217 iov.iov_len = len;
1218 uio.uio_iov = &iov;
1219 uio.uio_iovcnt = 1;
1220 uio.uio_resid = len;
1221 uio.uio_offset = 0;
1222 uio.uio_segflg = UIO_USERSPACE;
1223 uio.uio_rw = UIO_READ;
1224 uio.uio_procp = p;
1225 error = uiomove((void *)cdesc, len, &uio);
1226 free(cdesc, M_TEMP);
1227 return (error);
1228 }
1229 case USB_GET_STRING_DESC:
1230 {
1231 int len;
1232 si = (struct usb_string_desc *)addr;
1233 err = usbd_get_string_desc(sc->sc_udev, si->usd_string_index,
1234 si->usd_language_id, &si->usd_desc, &len);
1235 if (err)
1236 return (EINVAL);
1237 break;
1238 }
1239 case USB_DO_REQUEST:
1240 {
1241 struct usb_ctl_request *ur = (void *)addr;
1242 int len = UGETW(ur->ucr_request.wLength);
1243 struct iovec iov;
1244 struct uio uio;
1245 void *ptr = 0;
1246 usbd_status err;
1247 int error = 0;
1248
1249 if (!(flag & FWRITE))
1250 return (EPERM);
1251 /* Avoid requests that would damage the bus integrity. */
1252 if ((ur->ucr_request.bmRequestType == UT_WRITE_DEVICE &&
1253 ur->ucr_request.bRequest == UR_SET_ADDRESS) ||
1254 (ur->ucr_request.bmRequestType == UT_WRITE_DEVICE &&
1255 ur->ucr_request.bRequest == UR_SET_CONFIG) ||
1256 (ur->ucr_request.bmRequestType == UT_WRITE_INTERFACE &&
1257 ur->ucr_request.bRequest == UR_SET_INTERFACE))
1258 return (EINVAL);
1259
1260 if (len < 0 || len > 32767)
1261 return (EINVAL);
1262 if (len != 0) {
1263 iov.iov_base = (caddr_t)ur->ucr_data;
1264 iov.iov_len = len;
1265 uio.uio_iov = &iov;
1266 uio.uio_iovcnt = 1;
1267 uio.uio_resid = len;
1268 uio.uio_offset = 0;
1269 uio.uio_segflg = UIO_USERSPACE;
1270 uio.uio_rw =
1271 ur->ucr_request.bmRequestType & UT_READ ?
1272 UIO_READ : UIO_WRITE;
1273 uio.uio_procp = p;
1274 ptr = malloc(len, M_TEMP, M_WAITOK);
1275 if (uio.uio_rw == UIO_WRITE) {
1276 error = uiomove(ptr, len, &uio);
1277 if (error)
1278 goto ret;
1279 }
1280 }
1281 sce = &sc->sc_endpoints[endpt][IN];
1282 err = usbd_do_request_flags(sc->sc_udev, &ur->ucr_request,
1283 ptr, ur->ucr_flags, &ur->ucr_actlen, sce->timeout);
1284 if (err) {
1285 error = EIO;
1286 goto ret;
1287 }
1288 if (len != 0) {
1289 if (uio.uio_rw == UIO_READ) {
1290 error = uiomove(ptr, len, &uio);
1291 if (error)
1292 goto ret;
1293 }
1294 }
1295 ret:
1296 if (ptr)
1297 free(ptr, M_TEMP);
1298 return (error);
1299 }
1300 case USB_GET_DEVICEINFO:
1301 usbd_fill_deviceinfo(sc->sc_udev,
1302 (struct usb_device_info *)addr, 1);
1303 break;
1304 default:
1305 return (EINVAL);
1306 }
1307 return (0);
1308 }
1309
1310 int
ugenioctl(dev_t dev,u_long cmd,caddr_t addr,int flag,usb_proc_ptr p)1311 ugenioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, usb_proc_ptr p)
1312 {
1313 int endpt = UGENENDPOINT(dev);
1314 struct ugen_softc *sc;
1315 int error;
1316
1317 USB_GET_SC(ugen, UGENUNIT(dev), sc);
1318
1319 sc->sc_refcnt++;
1320 error = ugen_do_ioctl(sc, endpt, cmd, addr, flag, p);
1321 if (--sc->sc_refcnt < 0)
1322 usb_detach_wakeup(USBDEV(sc->sc_dev));
1323 return (error);
1324 }
1325
1326 int
ugenpoll(dev_t dev,int events,usb_proc_ptr p)1327 ugenpoll(dev_t dev, int events, usb_proc_ptr p)
1328 {
1329 struct ugen_softc *sc;
1330 struct ugen_endpoint *sce;
1331 int revents = 0;
1332 int s;
1333
1334 USB_GET_SC(ugen, UGENUNIT(dev), sc);
1335
1336 if (sc->sc_dying)
1337 return (EIO);
1338
1339 /* XXX always IN */
1340 sce = &sc->sc_endpoints[UGENENDPOINT(dev)][IN];
1341 if (sce == NULL)
1342 return (EINVAL);
1343 #ifdef DIAGNOSTIC
1344 if (!sce->edesc) {
1345 printf("ugenpoll: no edesc\n");
1346 return (EIO);
1347 }
1348 if (!sce->pipeh) {
1349 printf("ugenpoll: no pipe\n");
1350 return (EIO);
1351 }
1352 #endif
1353 s = splusb();
1354 switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
1355 case UE_INTERRUPT:
1356 if (events & (POLLIN | POLLRDNORM)) {
1357 if (sce->q.c_cc > 0)
1358 revents |= events & (POLLIN | POLLRDNORM);
1359 else
1360 selrecord(p, &sce->rsel);
1361 }
1362 break;
1363 case UE_ISOCHRONOUS:
1364 if (events & (POLLIN | POLLRDNORM)) {
1365 if (sce->cur != sce->fill)
1366 revents |= events & (POLLIN | POLLRDNORM);
1367 else
1368 selrecord(p, &sce->rsel);
1369 }
1370 break;
1371 case UE_BULK:
1372 /*
1373 * We have no easy way of determining if a read will
1374 * yield any data or a write will happen.
1375 * Pretend they will.
1376 */
1377 revents |= events &
1378 (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM);
1379 break;
1380 default:
1381 break;
1382 }
1383 splx(s);
1384 return (revents);
1385 }
1386
1387 Static void filt_ugenrdetach(struct knote *);
1388 Static int filt_ugenread_intr(struct knote *, long);
1389 Static int filt_ugenread_isoc(struct knote *, long);
1390 int ugenkqfilter(dev_t, struct knote *);
1391
1392 Static void
filt_ugenrdetach(struct knote * kn)1393 filt_ugenrdetach(struct knote *kn)
1394 {
1395 struct ugen_endpoint *sce = (void *)kn->kn_hook;
1396 int s;
1397
1398 s = splusb();
1399 SLIST_REMOVE(&sce->rsel.sel_klist, kn, knote, kn_selnext);
1400 splx(s);
1401 }
1402
1403 Static int
filt_ugenread_intr(struct knote * kn,long hint)1404 filt_ugenread_intr(struct knote *kn, long hint)
1405 {
1406 struct ugen_endpoint *sce = (void *)kn->kn_hook;
1407
1408 kn->kn_data = sce->q.c_cc;
1409 return (kn->kn_data > 0);
1410 }
1411
1412 Static int
filt_ugenread_isoc(struct knote * kn,long hint)1413 filt_ugenread_isoc(struct knote *kn, long hint)
1414 {
1415 struct ugen_endpoint *sce = (void *)kn->kn_hook;
1416
1417 if (sce->cur == sce->fill)
1418 return (0);
1419
1420 if (sce->cur < sce->fill)
1421 kn->kn_data = sce->fill - sce->cur;
1422 else
1423 kn->kn_data = (sce->limit - sce->cur) +
1424 (sce->fill - sce->ibuf);
1425
1426 return (1);
1427 }
1428
1429 Static struct filterops ugenread_intr_filtops =
1430 { 1, NULL, filt_ugenrdetach, filt_ugenread_intr };
1431
1432 Static struct filterops ugenread_isoc_filtops =
1433 { 1, NULL, filt_ugenrdetach, filt_ugenread_isoc };
1434
1435 Static struct filterops ugen_seltrue_filtops =
1436 { 1, NULL, filt_ugenrdetach, filt_seltrue };
1437
1438 int
ugenkqfilter(dev_t dev,struct knote * kn)1439 ugenkqfilter(dev_t dev, struct knote *kn)
1440 {
1441 struct ugen_softc *sc;
1442 struct ugen_endpoint *sce;
1443 struct klist *klist;
1444 int s;
1445
1446 USB_GET_SC(ugen, UGENUNIT(dev), sc);
1447
1448 if (sc->sc_dying)
1449 return (1);
1450
1451 /* XXX always IN */
1452 sce = &sc->sc_endpoints[UGENENDPOINT(dev)][IN];
1453 if (sce == NULL)
1454 return (1);
1455
1456 switch (kn->kn_filter) {
1457 case EVFILT_READ:
1458 klist = &sce->rsel.sel_klist;
1459 switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
1460 case UE_INTERRUPT:
1461 kn->kn_fop = &ugenread_intr_filtops;
1462 break;
1463 case UE_ISOCHRONOUS:
1464 kn->kn_fop = &ugenread_isoc_filtops;
1465 break;
1466 case UE_BULK:
1467 /*
1468 * We have no easy way of determining if a read will
1469 * yield any data or a write will happen.
1470 * So, emulate "seltrue".
1471 */
1472 kn->kn_fop = &ugen_seltrue_filtops;
1473 break;
1474 default:
1475 return (1);
1476 }
1477 break;
1478
1479 case EVFILT_WRITE:
1480 klist = &sce->rsel.sel_klist;
1481 switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
1482 case UE_INTERRUPT:
1483 case UE_ISOCHRONOUS:
1484 /* XXX poll doesn't support this */
1485 return (1);
1486
1487 case UE_BULK:
1488 /*
1489 * We have no easy way of determining if a read will
1490 * yield any data or a write will happen.
1491 * So, emulate "seltrue".
1492 */
1493 kn->kn_fop = &ugen_seltrue_filtops;
1494 break;
1495 default:
1496 return (1);
1497 }
1498 break;
1499
1500 default:
1501 return (1);
1502 }
1503
1504 kn->kn_hook = (void *)sce;
1505
1506 s = splusb();
1507 SLIST_INSERT_HEAD(klist, kn, kn_selnext);
1508 splx(s);
1509
1510 return (0);
1511 }
1512
1513 #if defined(__FreeBSD__)
1514 DRIVER_MODULE(ugen, uhub, ugen_driver, ugen_devclass, usbd_driver_load, 0);
1515 #endif
1516