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