ugen.c revision 1.77 1 /* $NetBSD: ugen.c,v 1.77 2005/11/28 13:14:48 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.77 2005/11/28 13:14:48 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 (match->cf_flags & 1)
192 return (UMATCH_HIGHEST);
193 else if (uaa->usegeneric)
194 return (UMATCH_GENERIC);
195 else
196 return (UMATCH_NONE);
197 }
198
199 USB_ATTACH(ugen)
200 {
201 USB_ATTACH_START(ugen, sc, uaa);
202 usbd_device_handle udev;
203 char *devinfop;
204 usbd_status err;
205 int conf;
206
207 devinfop = usbd_devinfo_alloc(uaa->device, 0);
208 USB_ATTACH_SETUP;
209 printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfop);
210 usbd_devinfo_free(devinfop);
211
212 sc->sc_udev = udev = uaa->device;
213
214 /* First set configuration index 0, the default one for ugen. */
215 err = usbd_set_config_index(udev, 0, 0);
216 if (err) {
217 printf("%s: setting configuration index 0 failed\n",
218 USBDEVNAME(sc->sc_dev));
219 sc->sc_dying = 1;
220 USB_ATTACH_ERROR_RETURN;
221 }
222 conf = usbd_get_config_descriptor(udev)->bConfigurationValue;
223
224 /* Set up all the local state for this configuration. */
225 err = ugen_set_config(sc, conf);
226 if (err) {
227 printf("%s: setting configuration %d failed\n",
228 USBDEVNAME(sc->sc_dev), conf);
229 sc->sc_dying = 1;
230 USB_ATTACH_ERROR_RETURN;
231 }
232
233 #ifdef __FreeBSD__
234 {
235 static int global_init_done = 0;
236 if (!global_init_done) {
237 cdevsw_add(&ugen_cdevsw);
238 global_init_done = 1;
239 }
240 }
241 #endif
242
243 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
244 USBDEV(sc->sc_dev));
245
246 USB_ATTACH_SUCCESS_RETURN;
247 }
248
249 Static int
250 ugen_set_config(struct ugen_softc *sc, int configno)
251 {
252 usbd_device_handle dev = sc->sc_udev;
253 usbd_interface_handle iface;
254 usb_endpoint_descriptor_t *ed;
255 struct ugen_endpoint *sce;
256 u_int8_t niface, nendpt;
257 int ifaceno, endptno, endpt;
258 usbd_status err;
259 int dir;
260
261 DPRINTFN(1,("ugen_set_config: %s to configno %d, sc=%p\n",
262 USBDEVNAME(sc->sc_dev), configno, sc));
263
264 /*
265 * We start at 1, not 0, because we don't care whether the
266 * control endpoint is open or not. It is always present.
267 */
268 for (endptno = 1; endptno < USB_MAX_ENDPOINTS; endptno++)
269 if (sc->sc_is_open[endptno]) {
270 DPRINTFN(1,
271 ("ugen_set_config: %s - endpoint %d is open\n",
272 USBDEVNAME(sc->sc_dev), endptno));
273 return (USBD_IN_USE);
274 }
275
276 /* Avoid setting the current value. */
277 if (usbd_get_config_descriptor(dev)->bConfigurationValue != configno) {
278 err = usbd_set_config_no(dev, configno, 1);
279 if (err)
280 return (err);
281 }
282
283 err = usbd_interface_count(dev, &niface);
284 if (err)
285 return (err);
286 memset(sc->sc_endpoints, 0, sizeof sc->sc_endpoints);
287 for (ifaceno = 0; ifaceno < niface; ifaceno++) {
288 DPRINTFN(1,("ugen_set_config: ifaceno %d\n", ifaceno));
289 err = usbd_device2interface_handle(dev, ifaceno, &iface);
290 if (err)
291 return (err);
292 err = usbd_endpoint_count(iface, &nendpt);
293 if (err)
294 return (err);
295 for (endptno = 0; endptno < nendpt; endptno++) {
296 ed = usbd_interface2endpoint_descriptor(iface,endptno);
297 endpt = ed->bEndpointAddress;
298 dir = UE_GET_DIR(endpt) == UE_DIR_IN ? IN : OUT;
299 sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir];
300 DPRINTFN(1,("ugen_set_config: endptno %d, endpt=0x%02x"
301 "(%d,%d), sce=%p\n",
302 endptno, endpt, UE_GET_ADDR(endpt),
303 UE_GET_DIR(endpt), sce));
304 sce->sc = sc;
305 sce->edesc = ed;
306 sce->iface = iface;
307 }
308 }
309 return (USBD_NORMAL_COMPLETION);
310 }
311
312 int
313 ugenopen(dev_t dev, int flag, int mode, usb_proc_ptr p)
314 {
315 struct ugen_softc *sc;
316 int unit = UGENUNIT(dev);
317 int endpt = UGENENDPOINT(dev);
318 usb_endpoint_descriptor_t *edesc;
319 struct ugen_endpoint *sce;
320 int dir, isize;
321 usbd_status err;
322 usbd_xfer_handle xfer;
323 void *tbuf;
324 int i, j;
325
326 USB_GET_SC_OPEN(ugen, unit, sc);
327
328 DPRINTFN(5, ("ugenopen: flag=%d, mode=%d, unit=%d endpt=%d\n",
329 flag, mode, unit, endpt));
330
331 if (sc == NULL || sc->sc_dying)
332 return (ENXIO);
333
334 /* The control endpoint allows multiple opens. */
335 if (endpt == USB_CONTROL_ENDPOINT) {
336 sc->sc_is_open[USB_CONTROL_ENDPOINT] = 1;
337 return (0);
338 }
339
340 if (sc->sc_is_open[endpt])
341 return (EBUSY);
342
343 /* Make sure there are pipes for all directions. */
344 for (dir = OUT; dir <= IN; dir++) {
345 if (flag & (dir == OUT ? FWRITE : FREAD)) {
346 sce = &sc->sc_endpoints[endpt][dir];
347 if (sce == 0 || sce->edesc == 0)
348 return (ENXIO);
349 }
350 }
351
352 /* Actually open the pipes. */
353 /* XXX Should back out properly if it fails. */
354 for (dir = OUT; dir <= IN; dir++) {
355 if (!(flag & (dir == OUT ? FWRITE : FREAD)))
356 continue;
357 sce = &sc->sc_endpoints[endpt][dir];
358 sce->state = 0;
359 sce->timeout = USBD_NO_TIMEOUT;
360 DPRINTFN(5, ("ugenopen: sc=%p, endpt=%d, dir=%d, sce=%p\n",
361 sc, endpt, dir, sce));
362 edesc = sce->edesc;
363 switch (edesc->bmAttributes & UE_XFERTYPE) {
364 case UE_INTERRUPT:
365 if (dir == OUT) {
366 err = usbd_open_pipe(sce->iface,
367 edesc->bEndpointAddress, 0, &sce->pipeh);
368 if (err)
369 return (EIO);
370 break;
371 }
372 isize = UGETW(edesc->wMaxPacketSize);
373 if (isize == 0) /* shouldn't happen */
374 return (EINVAL);
375 sce->ibuf = malloc(isize, M_USBDEV, M_WAITOK);
376 DPRINTFN(5, ("ugenopen: intr endpt=%d,isize=%d\n",
377 endpt, isize));
378 if (clalloc(&sce->q, UGEN_IBSIZE, 0) == -1)
379 return (ENOMEM);
380 err = usbd_open_pipe_intr(sce->iface,
381 edesc->bEndpointAddress,
382 USBD_SHORT_XFER_OK, &sce->pipeh, sce,
383 sce->ibuf, isize, ugenintr,
384 USBD_DEFAULT_INTERVAL);
385 if (err) {
386 free(sce->ibuf, M_USBDEV);
387 clfree(&sce->q);
388 return (EIO);
389 }
390 DPRINTFN(5, ("ugenopen: interrupt open done\n"));
391 break;
392 case UE_BULK:
393 err = usbd_open_pipe(sce->iface,
394 edesc->bEndpointAddress, 0, &sce->pipeh);
395 if (err)
396 return (EIO);
397 break;
398 case UE_ISOCHRONOUS:
399 if (dir == OUT)
400 return (EINVAL);
401 isize = UGETW(edesc->wMaxPacketSize);
402 if (isize == 0) /* shouldn't happen */
403 return (EINVAL);
404 sce->ibuf = malloc(isize * UGEN_NISOFRAMES,
405 M_USBDEV, M_WAITOK);
406 sce->cur = sce->fill = sce->ibuf;
407 sce->limit = sce->ibuf + isize * UGEN_NISOFRAMES;
408 DPRINTFN(5, ("ugenopen: isoc endpt=%d, isize=%d\n",
409 endpt, isize));
410 err = usbd_open_pipe(sce->iface,
411 edesc->bEndpointAddress, 0, &sce->pipeh);
412 if (err) {
413 free(sce->ibuf, M_USBDEV);
414 return (EIO);
415 }
416 for(i = 0; i < UGEN_NISOREQS; ++i) {
417 sce->isoreqs[i].sce = sce;
418 xfer = usbd_alloc_xfer(sc->sc_udev);
419 if (xfer == 0)
420 goto bad;
421 sce->isoreqs[i].xfer = xfer;
422 tbuf = usbd_alloc_buffer
423 (xfer, isize * UGEN_NISORFRMS);
424 if (tbuf == 0) {
425 i++;
426 goto bad;
427 }
428 sce->isoreqs[i].dmabuf = tbuf;
429 for(j = 0; j < UGEN_NISORFRMS; ++j)
430 sce->isoreqs[i].sizes[j] = isize;
431 usbd_setup_isoc_xfer
432 (xfer, sce->pipeh, &sce->isoreqs[i],
433 sce->isoreqs[i].sizes,
434 UGEN_NISORFRMS, USBD_NO_COPY,
435 ugen_isoc_rintr);
436 (void)usbd_transfer(xfer);
437 }
438 DPRINTFN(5, ("ugenopen: isoc open done\n"));
439 break;
440 bad:
441 while (--i >= 0) /* implicit buffer free */
442 usbd_free_xfer(sce->isoreqs[i].xfer);
443 return (ENOMEM);
444 case UE_CONTROL:
445 sce->timeout = USBD_DEFAULT_TIMEOUT;
446 return (EINVAL);
447 }
448 }
449 sc->sc_is_open[endpt] = 1;
450 return (0);
451 }
452
453 int
454 ugenclose(dev_t dev, int flag, int mode, usb_proc_ptr p)
455 {
456 int endpt = UGENENDPOINT(dev);
457 struct ugen_softc *sc;
458 struct ugen_endpoint *sce;
459 int dir;
460 int i;
461
462 USB_GET_SC(ugen, UGENUNIT(dev), sc);
463
464 DPRINTFN(5, ("ugenclose: flag=%d, mode=%d, unit=%d, endpt=%d\n",
465 flag, mode, UGENUNIT(dev), endpt));
466
467 #ifdef DIAGNOSTIC
468 if (!sc->sc_is_open[endpt]) {
469 printf("ugenclose: not open\n");
470 return (EINVAL);
471 }
472 #endif
473
474 if (endpt == USB_CONTROL_ENDPOINT) {
475 DPRINTFN(5, ("ugenclose: close control\n"));
476 sc->sc_is_open[endpt] = 0;
477 return (0);
478 }
479
480 for (dir = OUT; dir <= IN; dir++) {
481 if (!(flag & (dir == OUT ? FWRITE : FREAD)))
482 continue;
483 sce = &sc->sc_endpoints[endpt][dir];
484 if (sce == NULL || sce->pipeh == NULL)
485 continue;
486 DPRINTFN(5, ("ugenclose: endpt=%d dir=%d sce=%p\n",
487 endpt, dir, sce));
488
489 usbd_abort_pipe(sce->pipeh);
490 usbd_close_pipe(sce->pipeh);
491 sce->pipeh = NULL;
492
493 switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
494 case UE_INTERRUPT:
495 ndflush(&sce->q, sce->q.c_cc);
496 clfree(&sce->q);
497 break;
498 case UE_ISOCHRONOUS:
499 for (i = 0; i < UGEN_NISOREQS; ++i)
500 usbd_free_xfer(sce->isoreqs[i].xfer);
501
502 default:
503 break;
504 }
505
506 if (sce->ibuf != NULL) {
507 free(sce->ibuf, M_USBDEV);
508 sce->ibuf = NULL;
509 clfree(&sce->q);
510 }
511 }
512 sc->sc_is_open[endpt] = 0;
513
514 return (0);
515 }
516
517 Static int
518 ugen_do_read(struct ugen_softc *sc, int endpt, struct uio *uio, int flag)
519 {
520 struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][IN];
521 u_int32_t n, tn;
522 char tbuf[UGEN_BBSIZE];
523 usbd_xfer_handle xfer;
524 usbd_status err;
525 int s;
526 int error = 0;
527 u_char buffer[UGEN_CHUNK];
528
529 DPRINTFN(5, ("%s: ugenread: %d\n", USBDEVNAME(sc->sc_dev), endpt));
530
531 if (sc->sc_dying)
532 return (EIO);
533
534 if (endpt == USB_CONTROL_ENDPOINT)
535 return (ENODEV);
536
537 #ifdef DIAGNOSTIC
538 if (sce->edesc == NULL) {
539 printf("ugenread: no edesc\n");
540 return (EIO);
541 }
542 if (sce->pipeh == NULL) {
543 printf("ugenread: no pipe\n");
544 return (EIO);
545 }
546 #endif
547
548 switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
549 case UE_INTERRUPT:
550 /* Block until activity occurred. */
551 s = splusb();
552 while (sce->q.c_cc == 0) {
553 if (flag & IO_NDELAY) {
554 splx(s);
555 return (EWOULDBLOCK);
556 }
557 sce->state |= UGEN_ASLP;
558 DPRINTFN(5, ("ugenread: sleep on %p\n", sce));
559 error = tsleep(sce, PZERO | PCATCH, "ugenri", 0);
560 DPRINTFN(5, ("ugenread: woke, error=%d\n", error));
561 if (sc->sc_dying)
562 error = EIO;
563 if (error) {
564 sce->state &= ~UGEN_ASLP;
565 break;
566 }
567 }
568 splx(s);
569
570 /* Transfer as many chunks as possible. */
571 while (sce->q.c_cc > 0 && uio->uio_resid > 0 && !error) {
572 n = min(sce->q.c_cc, uio->uio_resid);
573 if (n > sizeof(buffer))
574 n = sizeof(buffer);
575
576 /* Remove a small chunk from the input queue. */
577 q_to_b(&sce->q, buffer, n);
578 DPRINTFN(5, ("ugenread: got %d chars\n", n));
579
580 /* Copy the data to the user process. */
581 error = uiomove(buffer, n, uio);
582 if (error)
583 break;
584 }
585 break;
586 case UE_BULK:
587 xfer = usbd_alloc_xfer(sc->sc_udev);
588 if (xfer == 0)
589 return (ENOMEM);
590 while ((n = min(UGEN_BBSIZE, uio->uio_resid)) != 0) {
591 DPRINTFN(1, ("ugenread: start transfer %d bytes\n",n));
592 tn = n;
593 err = usbd_bulk_transfer(
594 xfer, sce->pipeh,
595 sce->state & UGEN_SHORT_OK ?
596 USBD_SHORT_XFER_OK : 0,
597 sce->timeout, tbuf, &tn, "ugenrb");
598 if (err) {
599 if (err == USBD_INTERRUPTED)
600 error = EINTR;
601 else if (err == USBD_TIMEOUT)
602 error = ETIMEDOUT;
603 else
604 error = EIO;
605 break;
606 }
607 DPRINTFN(1, ("ugenread: got %d bytes\n", tn));
608 error = uiomove(tbuf, tn, uio);
609 if (error || tn < n)
610 break;
611 }
612 usbd_free_xfer(xfer);
613 break;
614 case UE_ISOCHRONOUS:
615 s = splusb();
616 while (sce->cur == sce->fill) {
617 if (flag & IO_NDELAY) {
618 splx(s);
619 return (EWOULDBLOCK);
620 }
621 sce->state |= UGEN_ASLP;
622 DPRINTFN(5, ("ugenread: sleep on %p\n", sce));
623 error = tsleep(sce, PZERO | PCATCH, "ugenri", 0);
624 DPRINTFN(5, ("ugenread: woke, error=%d\n", error));
625 if (sc->sc_dying)
626 error = EIO;
627 if (error) {
628 sce->state &= ~UGEN_ASLP;
629 break;
630 }
631 }
632
633 while (sce->cur != sce->fill && uio->uio_resid > 0 && !error) {
634 if(sce->fill > sce->cur)
635 n = min(sce->fill - sce->cur, uio->uio_resid);
636 else
637 n = min(sce->limit - sce->cur, uio->uio_resid);
638
639 DPRINTFN(5, ("ugenread: isoc got %d chars\n", n));
640
641 /* Copy the data to the user process. */
642 error = uiomove(sce->cur, n, uio);
643 if (error)
644 break;
645 sce->cur += n;
646 if(sce->cur >= sce->limit)
647 sce->cur = sce->ibuf;
648 }
649 splx(s);
650 break;
651
652
653 default:
654 return (ENXIO);
655 }
656 return (error);
657 }
658
659 int
660 ugenread(dev_t dev, struct uio *uio, int flag)
661 {
662 int endpt = UGENENDPOINT(dev);
663 struct ugen_softc *sc;
664 int error;
665
666 USB_GET_SC(ugen, UGENUNIT(dev), sc);
667
668 sc->sc_refcnt++;
669 error = ugen_do_read(sc, endpt, uio, flag);
670 if (--sc->sc_refcnt < 0)
671 usb_detach_wakeup(USBDEV(sc->sc_dev));
672 return (error);
673 }
674
675 Static int
676 ugen_do_write(struct ugen_softc *sc, int endpt, struct uio *uio, int flag)
677 {
678 struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][OUT];
679 u_int32_t n;
680 int error = 0;
681 char tbuf[UGEN_BBSIZE];
682 usbd_xfer_handle xfer;
683 usbd_status err;
684
685 DPRINTFN(5, ("%s: ugenwrite: %d\n", USBDEVNAME(sc->sc_dev), endpt));
686
687 if (sc->sc_dying)
688 return (EIO);
689
690 if (endpt == USB_CONTROL_ENDPOINT)
691 return (ENODEV);
692
693 #ifdef DIAGNOSTIC
694 if (sce->edesc == NULL) {
695 printf("ugenwrite: no edesc\n");
696 return (EIO);
697 }
698 if (sce->pipeh == NULL) {
699 printf("ugenwrite: no pipe\n");
700 return (EIO);
701 }
702 #endif
703
704 switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
705 case UE_BULK:
706 xfer = usbd_alloc_xfer(sc->sc_udev);
707 if (xfer == 0)
708 return (EIO);
709 while ((n = min(UGEN_BBSIZE, uio->uio_resid)) != 0) {
710 error = uiomove(tbuf, n, uio);
711 if (error)
712 break;
713 DPRINTFN(1, ("ugenwrite: transfer %d bytes\n", n));
714 err = usbd_bulk_transfer(xfer, sce->pipeh, 0,
715 sce->timeout, tbuf, &n,"ugenwb");
716 if (err) {
717 if (err == USBD_INTERRUPTED)
718 error = EINTR;
719 else if (err == USBD_TIMEOUT)
720 error = ETIMEDOUT;
721 else
722 error = EIO;
723 break;
724 }
725 }
726 usbd_free_xfer(xfer);
727 break;
728 case UE_INTERRUPT:
729 xfer = usbd_alloc_xfer(sc->sc_udev);
730 if (xfer == 0)
731 return (EIO);
732 while ((n = min(UGETW(sce->edesc->wMaxPacketSize),
733 uio->uio_resid)) != 0) {
734 error = uiomove(tbuf, n, uio);
735 if (error)
736 break;
737 DPRINTFN(1, ("ugenwrite: transfer %d bytes\n", n));
738 err = usbd_intr_transfer(xfer, sce->pipeh, 0,
739 sce->timeout, tbuf, &n, "ugenwi");
740 if (err) {
741 if (err == USBD_INTERRUPTED)
742 error = EINTR;
743 else if (err == USBD_TIMEOUT)
744 error = ETIMEDOUT;
745 else
746 error = EIO;
747 break;
748 }
749 }
750 usbd_free_xfer(xfer);
751 break;
752 default:
753 return (ENXIO);
754 }
755 return (error);
756 }
757
758 int
759 ugenwrite(dev_t dev, struct uio *uio, int flag)
760 {
761 int endpt = UGENENDPOINT(dev);
762 struct ugen_softc *sc;
763 int error;
764
765 USB_GET_SC(ugen, UGENUNIT(dev), sc);
766
767 sc->sc_refcnt++;
768 error = ugen_do_write(sc, endpt, uio, flag);
769 if (--sc->sc_refcnt < 0)
770 usb_detach_wakeup(USBDEV(sc->sc_dev));
771 return (error);
772 }
773
774 #if defined(__NetBSD__) || defined(__OpenBSD__)
775 int
776 ugen_activate(device_ptr_t self, enum devact act)
777 {
778 struct ugen_softc *sc = (struct ugen_softc *)self;
779
780 switch (act) {
781 case DVACT_ACTIVATE:
782 return (EOPNOTSUPP);
783
784 case DVACT_DEACTIVATE:
785 sc->sc_dying = 1;
786 break;
787 }
788 return (0);
789 }
790 #endif
791
792 USB_DETACH(ugen)
793 {
794 USB_DETACH_START(ugen, sc);
795 struct ugen_endpoint *sce;
796 int i, dir;
797 int s;
798 #if defined(__NetBSD__) || defined(__OpenBSD__)
799 int maj, mn;
800
801 DPRINTF(("ugen_detach: sc=%p flags=%d\n", sc, flags));
802 #elif defined(__FreeBSD__)
803 DPRINTF(("ugen_detach: sc=%p\n", sc));
804 #endif
805
806 sc->sc_dying = 1;
807 /* Abort all pipes. Causes processes waiting for transfer to wake. */
808 for (i = 0; i < USB_MAX_ENDPOINTS; i++) {
809 for (dir = OUT; dir <= IN; dir++) {
810 sce = &sc->sc_endpoints[i][dir];
811 if (sce && sce->pipeh)
812 usbd_abort_pipe(sce->pipeh);
813 }
814 }
815
816 s = splusb();
817 if (--sc->sc_refcnt >= 0) {
818 /* Wake everyone */
819 for (i = 0; i < USB_MAX_ENDPOINTS; i++)
820 wakeup(&sc->sc_endpoints[i][IN]);
821 /* Wait for processes to go away. */
822 usb_detach_wait(USBDEV(sc->sc_dev));
823 }
824 splx(s);
825
826 #if defined(__NetBSD__) || defined(__OpenBSD__)
827 /* locate the major number */
828 #if defined(__NetBSD__)
829 maj = cdevsw_lookup_major(&ugen_cdevsw);
830 #elif defined(__OpenBSD__)
831 for (maj = 0; maj < nchrdev; maj++)
832 if (cdevsw[maj].d_open == ugenopen)
833 break;
834 #endif
835
836 /* Nuke the vnodes for any open instances (calls close). */
837 mn = self->dv_unit * USB_MAX_ENDPOINTS;
838 vdevgone(maj, mn, mn + USB_MAX_ENDPOINTS - 1, VCHR);
839 #elif defined(__FreeBSD__)
840 /* XXX not implemented yet */
841 #endif
842
843 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
844 USBDEV(sc->sc_dev));
845
846 return (0);
847 }
848
849 Static void
850 ugenintr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status)
851 {
852 struct ugen_endpoint *sce = addr;
853 /*struct ugen_softc *sc = sce->sc;*/
854 u_int32_t count;
855 u_char *ibuf;
856
857 if (status == USBD_CANCELLED)
858 return;
859
860 if (status != USBD_NORMAL_COMPLETION) {
861 DPRINTF(("ugenintr: status=%d\n", status));
862 if (status == USBD_STALLED)
863 usbd_clear_endpoint_stall_async(sce->pipeh);
864 return;
865 }
866
867 usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
868 ibuf = sce->ibuf;
869
870 DPRINTFN(5, ("ugenintr: xfer=%p status=%d count=%d\n",
871 xfer, status, count));
872 DPRINTFN(5, (" data = %02x %02x %02x\n",
873 ibuf[0], ibuf[1], ibuf[2]));
874
875 (void)b_to_q(ibuf, count, &sce->q);
876
877 if (sce->state & UGEN_ASLP) {
878 sce->state &= ~UGEN_ASLP;
879 DPRINTFN(5, ("ugen_intr: waking %p\n", sce));
880 wakeup(sce);
881 }
882 selnotify(&sce->rsel, 0);
883 }
884
885 Static void
886 ugen_isoc_rintr(usbd_xfer_handle xfer, usbd_private_handle addr,
887 usbd_status status)
888 {
889 struct isoreq *req = addr;
890 struct ugen_endpoint *sce = req->sce;
891 u_int32_t count, n;
892 int i, isize;
893
894 /* Return if we are aborting. */
895 if (status == USBD_CANCELLED)
896 return;
897
898 usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
899 DPRINTFN(5,("ugen_isoc_rintr: xfer %ld, count=%d\n",
900 (long)(req - sce->isoreqs), count));
901
902 /* throw away oldest input if the buffer is full */
903 if(sce->fill < sce->cur && sce->cur <= sce->fill + count) {
904 sce->cur += count;
905 if(sce->cur >= sce->limit)
906 sce->cur = sce->ibuf + (sce->limit - sce->cur);
907 DPRINTFN(5, ("ugen_isoc_rintr: throwing away %d bytes\n",
908 count));
909 }
910
911 isize = UGETW(sce->edesc->wMaxPacketSize);
912 for (i = 0; i < UGEN_NISORFRMS; i++) {
913 u_int32_t actlen = req->sizes[i];
914 char const *tbuf = (char const *)req->dmabuf + isize * i;
915
916 /* copy data to buffer */
917 while (actlen > 0) {
918 n = min(actlen, sce->limit - sce->fill);
919 memcpy(sce->fill, tbuf, n);
920
921 tbuf += n;
922 actlen -= n;
923 sce->fill += n;
924 if(sce->fill == sce->limit)
925 sce->fill = sce->ibuf;
926 }
927
928 /* setup size for next transfer */
929 req->sizes[i] = isize;
930 }
931
932 usbd_setup_isoc_xfer(xfer, sce->pipeh, req, req->sizes, UGEN_NISORFRMS,
933 USBD_NO_COPY, ugen_isoc_rintr);
934 (void)usbd_transfer(xfer);
935
936 if (sce->state & UGEN_ASLP) {
937 sce->state &= ~UGEN_ASLP;
938 DPRINTFN(5, ("ugen_isoc_rintr: waking %p\n", sce));
939 wakeup(sce);
940 }
941 selnotify(&sce->rsel, 0);
942 }
943
944 Static usbd_status
945 ugen_set_interface(struct ugen_softc *sc, int ifaceidx, int altno)
946 {
947 usbd_interface_handle iface;
948 usb_endpoint_descriptor_t *ed;
949 usbd_status err;
950 struct ugen_endpoint *sce;
951 u_int8_t niface, nendpt, endptno, endpt;
952 int dir;
953
954 DPRINTFN(15, ("ugen_set_interface %d %d\n", ifaceidx, altno));
955
956 err = usbd_interface_count(sc->sc_udev, &niface);
957 if (err)
958 return (err);
959 if (ifaceidx < 0 || ifaceidx >= niface)
960 return (USBD_INVAL);
961
962 err = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface);
963 if (err)
964 return (err);
965 err = usbd_endpoint_count(iface, &nendpt);
966 if (err)
967 return (err);
968 /* XXX should only do this after setting new altno has succeeded */
969 for (endptno = 0; endptno < nendpt; endptno++) {
970 ed = usbd_interface2endpoint_descriptor(iface,endptno);
971 endpt = ed->bEndpointAddress;
972 dir = UE_GET_DIR(endpt) == UE_DIR_IN ? IN : OUT;
973 sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir];
974 sce->sc = 0;
975 sce->edesc = 0;
976 sce->iface = 0;
977 }
978
979 /* change setting */
980 err = usbd_set_interface(iface, altno);
981 if (err)
982 return (err);
983
984 err = usbd_endpoint_count(iface, &nendpt);
985 if (err)
986 return (err);
987 for (endptno = 0; endptno < nendpt; endptno++) {
988 ed = usbd_interface2endpoint_descriptor(iface,endptno);
989 endpt = ed->bEndpointAddress;
990 dir = UE_GET_DIR(endpt) == UE_DIR_IN ? IN : OUT;
991 sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir];
992 sce->sc = sc;
993 sce->edesc = ed;
994 sce->iface = iface;
995 }
996 return (0);
997 }
998
999 /* Retrieve a complete descriptor for a certain device and index. */
1000 Static usb_config_descriptor_t *
1001 ugen_get_cdesc(struct ugen_softc *sc, int index, int *lenp)
1002 {
1003 usb_config_descriptor_t *cdesc, *tdesc, cdescr;
1004 int len;
1005 usbd_status err;
1006
1007 if (index == USB_CURRENT_CONFIG_INDEX) {
1008 tdesc = usbd_get_config_descriptor(sc->sc_udev);
1009 len = UGETW(tdesc->wTotalLength);
1010 if (lenp)
1011 *lenp = len;
1012 cdesc = malloc(len, M_TEMP, M_WAITOK);
1013 memcpy(cdesc, tdesc, len);
1014 DPRINTFN(5,("ugen_get_cdesc: current, len=%d\n", len));
1015 } else {
1016 err = usbd_get_config_desc(sc->sc_udev, index, &cdescr);
1017 if (err)
1018 return (0);
1019 len = UGETW(cdescr.wTotalLength);
1020 DPRINTFN(5,("ugen_get_cdesc: index=%d, len=%d\n", index, len));
1021 if (lenp)
1022 *lenp = len;
1023 cdesc = malloc(len, M_TEMP, M_WAITOK);
1024 err = usbd_get_config_desc_full(sc->sc_udev, index, cdesc, len);
1025 if (err) {
1026 free(cdesc, M_TEMP);
1027 return (0);
1028 }
1029 }
1030 return (cdesc);
1031 }
1032
1033 Static int
1034 ugen_get_alt_index(struct ugen_softc *sc, int ifaceidx)
1035 {
1036 usbd_interface_handle iface;
1037 usbd_status err;
1038
1039 err = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface);
1040 if (err)
1041 return (-1);
1042 return (usbd_get_interface_altindex(iface));
1043 }
1044
1045 Static int
1046 ugen_do_ioctl(struct ugen_softc *sc, int endpt, u_long cmd,
1047 caddr_t addr, int flag, usb_proc_ptr p)
1048 {
1049 struct ugen_endpoint *sce;
1050 usbd_status err;
1051 usbd_interface_handle iface;
1052 struct usb_config_desc *cd;
1053 usb_config_descriptor_t *cdesc;
1054 struct usb_interface_desc *id;
1055 usb_interface_descriptor_t *idesc;
1056 struct usb_endpoint_desc *ed;
1057 usb_endpoint_descriptor_t *edesc;
1058 struct usb_alt_interface *ai;
1059 struct usb_string_desc *si;
1060 u_int8_t conf, alt;
1061
1062 DPRINTFN(5, ("ugenioctl: cmd=%08lx\n", cmd));
1063 if (sc->sc_dying)
1064 return (EIO);
1065
1066 switch (cmd) {
1067 case FIONBIO:
1068 /* All handled in the upper FS layer. */
1069 return (0);
1070 case USB_SET_SHORT_XFER:
1071 if (endpt == USB_CONTROL_ENDPOINT)
1072 return (EINVAL);
1073 /* This flag only affects read */
1074 sce = &sc->sc_endpoints[endpt][IN];
1075 if (sce == NULL || sce->pipeh == NULL)
1076 return (EINVAL);
1077 if (*(int *)addr)
1078 sce->state |= UGEN_SHORT_OK;
1079 else
1080 sce->state &= ~UGEN_SHORT_OK;
1081 return (0);
1082 case USB_SET_TIMEOUT:
1083 sce = &sc->sc_endpoints[endpt][IN];
1084 if (sce == NULL
1085 /* XXX this shouldn't happen, but the distinction between
1086 input and output pipes isn't clear enough.
1087 || sce->pipeh == NULL */
1088 )
1089 return (EINVAL);
1090 sce->timeout = *(int *)addr;
1091 return (0);
1092 default:
1093 break;
1094 }
1095
1096 if (endpt != USB_CONTROL_ENDPOINT)
1097 return (EINVAL);
1098
1099 switch (cmd) {
1100 #ifdef UGEN_DEBUG
1101 case USB_SETDEBUG:
1102 ugendebug = *(int *)addr;
1103 break;
1104 #endif
1105 case USB_GET_CONFIG:
1106 err = usbd_get_config(sc->sc_udev, &conf);
1107 if (err)
1108 return (EIO);
1109 *(int *)addr = conf;
1110 break;
1111 case USB_SET_CONFIG:
1112 if (!(flag & FWRITE))
1113 return (EPERM);
1114 err = ugen_set_config(sc, *(int *)addr);
1115 switch (err) {
1116 case USBD_NORMAL_COMPLETION:
1117 break;
1118 case USBD_IN_USE:
1119 return (EBUSY);
1120 default:
1121 return (EIO);
1122 }
1123 break;
1124 case USB_GET_ALTINTERFACE:
1125 ai = (struct usb_alt_interface *)addr;
1126 err = usbd_device2interface_handle(sc->sc_udev,
1127 ai->uai_interface_index, &iface);
1128 if (err)
1129 return (EINVAL);
1130 idesc = usbd_get_interface_descriptor(iface);
1131 if (idesc == NULL)
1132 return (EIO);
1133 ai->uai_alt_no = idesc->bAlternateSetting;
1134 break;
1135 case USB_SET_ALTINTERFACE:
1136 if (!(flag & FWRITE))
1137 return (EPERM);
1138 ai = (struct usb_alt_interface *)addr;
1139 err = usbd_device2interface_handle(sc->sc_udev,
1140 ai->uai_interface_index, &iface);
1141 if (err)
1142 return (EINVAL);
1143 err = ugen_set_interface(sc, ai->uai_interface_index,
1144 ai->uai_alt_no);
1145 if (err)
1146 return (EINVAL);
1147 break;
1148 case USB_GET_NO_ALT:
1149 ai = (struct usb_alt_interface *)addr;
1150 cdesc = ugen_get_cdesc(sc, ai->uai_config_index, 0);
1151 if (cdesc == NULL)
1152 return (EINVAL);
1153 idesc = usbd_find_idesc(cdesc, ai->uai_interface_index, 0);
1154 if (idesc == NULL) {
1155 free(cdesc, M_TEMP);
1156 return (EINVAL);
1157 }
1158 ai->uai_alt_no = usbd_get_no_alts(cdesc,
1159 idesc->bInterfaceNumber);
1160 free(cdesc, M_TEMP);
1161 break;
1162 case USB_GET_DEVICE_DESC:
1163 *(usb_device_descriptor_t *)addr =
1164 *usbd_get_device_descriptor(sc->sc_udev);
1165 break;
1166 case USB_GET_CONFIG_DESC:
1167 cd = (struct usb_config_desc *)addr;
1168 cdesc = ugen_get_cdesc(sc, cd->ucd_config_index, 0);
1169 if (cdesc == NULL)
1170 return (EINVAL);
1171 cd->ucd_desc = *cdesc;
1172 free(cdesc, M_TEMP);
1173 break;
1174 case USB_GET_INTERFACE_DESC:
1175 id = (struct usb_interface_desc *)addr;
1176 cdesc = ugen_get_cdesc(sc, id->uid_config_index, 0);
1177 if (cdesc == NULL)
1178 return (EINVAL);
1179 if (id->uid_config_index == USB_CURRENT_CONFIG_INDEX &&
1180 id->uid_alt_index == USB_CURRENT_ALT_INDEX)
1181 alt = ugen_get_alt_index(sc, id->uid_interface_index);
1182 else
1183 alt = id->uid_alt_index;
1184 idesc = usbd_find_idesc(cdesc, id->uid_interface_index, alt);
1185 if (idesc == NULL) {
1186 free(cdesc, M_TEMP);
1187 return (EINVAL);
1188 }
1189 id->uid_desc = *idesc;
1190 free(cdesc, M_TEMP);
1191 break;
1192 case USB_GET_ENDPOINT_DESC:
1193 ed = (struct usb_endpoint_desc *)addr;
1194 cdesc = ugen_get_cdesc(sc, ed->ued_config_index, 0);
1195 if (cdesc == NULL)
1196 return (EINVAL);
1197 if (ed->ued_config_index == USB_CURRENT_CONFIG_INDEX &&
1198 ed->ued_alt_index == USB_CURRENT_ALT_INDEX)
1199 alt = ugen_get_alt_index(sc, ed->ued_interface_index);
1200 else
1201 alt = ed->ued_alt_index;
1202 edesc = usbd_find_edesc(cdesc, ed->ued_interface_index,
1203 alt, ed->ued_endpoint_index);
1204 if (edesc == NULL) {
1205 free(cdesc, M_TEMP);
1206 return (EINVAL);
1207 }
1208 ed->ued_desc = *edesc;
1209 free(cdesc, M_TEMP);
1210 break;
1211 case USB_GET_FULL_DESC:
1212 {
1213 int len;
1214 struct iovec iov;
1215 struct uio uio;
1216 struct usb_full_desc *fd = (struct usb_full_desc *)addr;
1217 int error;
1218
1219 cdesc = ugen_get_cdesc(sc, fd->ufd_config_index, &len);
1220 if (len > fd->ufd_size)
1221 len = fd->ufd_size;
1222 iov.iov_base = (caddr_t)fd->ufd_data;
1223 iov.iov_len = len;
1224 uio.uio_iov = &iov;
1225 uio.uio_iovcnt = 1;
1226 uio.uio_resid = len;
1227 uio.uio_offset = 0;
1228 uio.uio_segflg = UIO_USERSPACE;
1229 uio.uio_rw = UIO_READ;
1230 uio.uio_procp = p;
1231 error = uiomove((void *)cdesc, len, &uio);
1232 free(cdesc, M_TEMP);
1233 return (error);
1234 }
1235 case USB_GET_STRING_DESC: {
1236 int len;
1237 si = (struct usb_string_desc *)addr;
1238 err = usbd_get_string_desc(sc->sc_udev, si->usd_string_index,
1239 si->usd_language_id, &si->usd_desc, &len);
1240 if (err)
1241 return (EINVAL);
1242 break;
1243 }
1244 case USB_DO_REQUEST:
1245 {
1246 struct usb_ctl_request *ur = (void *)addr;
1247 int len = UGETW(ur->ucr_request.wLength);
1248 struct iovec iov;
1249 struct uio uio;
1250 void *ptr = 0;
1251 usbd_status xerr;
1252 int error = 0;
1253
1254 if (!(flag & FWRITE))
1255 return (EPERM);
1256 /* Avoid requests that would damage the bus integrity. */
1257 if ((ur->ucr_request.bmRequestType == UT_WRITE_DEVICE &&
1258 ur->ucr_request.bRequest == UR_SET_ADDRESS) ||
1259 (ur->ucr_request.bmRequestType == UT_WRITE_DEVICE &&
1260 ur->ucr_request.bRequest == UR_SET_CONFIG) ||
1261 (ur->ucr_request.bmRequestType == UT_WRITE_INTERFACE &&
1262 ur->ucr_request.bRequest == UR_SET_INTERFACE))
1263 return (EINVAL);
1264
1265 if (len < 0 || len > 32767)
1266 return (EINVAL);
1267 if (len != 0) {
1268 iov.iov_base = (caddr_t)ur->ucr_data;
1269 iov.iov_len = len;
1270 uio.uio_iov = &iov;
1271 uio.uio_iovcnt = 1;
1272 uio.uio_resid = len;
1273 uio.uio_offset = 0;
1274 uio.uio_segflg = UIO_USERSPACE;
1275 uio.uio_rw =
1276 ur->ucr_request.bmRequestType & UT_READ ?
1277 UIO_READ : UIO_WRITE;
1278 uio.uio_procp = p;
1279 ptr = malloc(len, M_TEMP, M_WAITOK);
1280 if (uio.uio_rw == UIO_WRITE) {
1281 error = uiomove(ptr, len, &uio);
1282 if (error)
1283 goto ret;
1284 }
1285 }
1286 sce = &sc->sc_endpoints[endpt][IN];
1287 xerr = usbd_do_request_flags(sc->sc_udev, &ur->ucr_request,
1288 ptr, ur->ucr_flags, &ur->ucr_actlen, sce->timeout);
1289 if (xerr) {
1290 error = EIO;
1291 goto ret;
1292 }
1293 if (len != 0) {
1294 if (uio.uio_rw == UIO_READ) {
1295 error = uiomove(ptr, len, &uio);
1296 if (error)
1297 goto ret;
1298 }
1299 }
1300 ret:
1301 if (ptr)
1302 free(ptr, M_TEMP);
1303 return (error);
1304 }
1305 case USB_GET_DEVICEINFO:
1306 usbd_fill_deviceinfo(sc->sc_udev,
1307 (struct usb_device_info *)addr, 1);
1308 break;
1309 default:
1310 return (EINVAL);
1311 }
1312 return (0);
1313 }
1314
1315 int
1316 ugenioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, usb_proc_ptr p)
1317 {
1318 int endpt = UGENENDPOINT(dev);
1319 struct ugen_softc *sc;
1320 int error;
1321
1322 USB_GET_SC(ugen, UGENUNIT(dev), sc);
1323
1324 sc->sc_refcnt++;
1325 error = ugen_do_ioctl(sc, endpt, cmd, addr, flag, p);
1326 if (--sc->sc_refcnt < 0)
1327 usb_detach_wakeup(USBDEV(sc->sc_dev));
1328 return (error);
1329 }
1330
1331 int
1332 ugenpoll(dev_t dev, int events, usb_proc_ptr p)
1333 {
1334 struct ugen_softc *sc;
1335 struct ugen_endpoint *sce;
1336 int revents = 0;
1337 int s;
1338
1339 USB_GET_SC(ugen, UGENUNIT(dev), sc);
1340
1341 if (sc->sc_dying)
1342 return (POLLHUP);
1343
1344 /* XXX always IN */
1345 sce = &sc->sc_endpoints[UGENENDPOINT(dev)][IN];
1346 if (sce == NULL)
1347 return (POLLERR);
1348 #ifdef DIAGNOSTIC
1349 if (!sce->edesc) {
1350 printf("ugenpoll: no edesc\n");
1351 return (POLLERR);
1352 }
1353 if (!sce->pipeh) {
1354 printf("ugenpoll: no pipe\n");
1355 return (POLLERR);
1356 }
1357 #endif
1358 s = splusb();
1359 switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
1360 case UE_INTERRUPT:
1361 if (events & (POLLIN | POLLRDNORM)) {
1362 if (sce->q.c_cc > 0)
1363 revents |= events & (POLLIN | POLLRDNORM);
1364 else
1365 selrecord(p, &sce->rsel);
1366 }
1367 break;
1368 case UE_ISOCHRONOUS:
1369 if (events & (POLLIN | POLLRDNORM)) {
1370 if (sce->cur != sce->fill)
1371 revents |= events & (POLLIN | POLLRDNORM);
1372 else
1373 selrecord(p, &sce->rsel);
1374 }
1375 break;
1376 case UE_BULK:
1377 /*
1378 * We have no easy way of determining if a read will
1379 * yield any data or a write will happen.
1380 * Pretend they will.
1381 */
1382 revents |= events &
1383 (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM);
1384 break;
1385 default:
1386 break;
1387 }
1388 splx(s);
1389 return (revents);
1390 }
1391
1392 static void
1393 filt_ugenrdetach(struct knote *kn)
1394 {
1395 struct ugen_endpoint *sce = 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
1404 filt_ugenread_intr(struct knote *kn, long hint)
1405 {
1406 struct ugen_endpoint *sce = kn->kn_hook;
1407
1408 kn->kn_data = sce->q.c_cc;
1409 return (kn->kn_data > 0);
1410 }
1411
1412 static int
1413 filt_ugenread_isoc(struct knote *kn, long hint)
1414 {
1415 struct ugen_endpoint *sce = 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 const struct filterops ugenread_intr_filtops =
1430 { 1, NULL, filt_ugenrdetach, filt_ugenread_intr };
1431
1432 static const struct filterops ugenread_isoc_filtops =
1433 { 1, NULL, filt_ugenrdetach, filt_ugenread_isoc };
1434
1435 static const struct filterops ugen_seltrue_filtops =
1436 { 1, NULL, filt_ugenrdetach, filt_seltrue };
1437
1438 int
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 = 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