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