]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/usb/usb_generic.c
[run] Set ampdu rxmax same as linux; RF2020 isn't an 11n NIC
[FreeBSD/FreeBSD.git] / sys / dev / usb / usb_generic.c
1 /* $FreeBSD$ */
2 /*-
3  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4  *
5  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28
29 #ifdef USB_GLOBAL_INCLUDE_FILE
30 #include USB_GLOBAL_INCLUDE_FILE
31 #else
32 #include <sys/stdint.h>
33 #include <sys/stddef.h>
34 #include <sys/param.h>
35 #include <sys/queue.h>
36 #include <sys/types.h>
37 #include <sys/systm.h>
38 #include <sys/kernel.h>
39 #include <sys/bus.h>
40 #include <sys/module.h>
41 #include <sys/lock.h>
42 #include <sys/mutex.h>
43 #include <sys/condvar.h>
44 #include <sys/sysctl.h>
45 #include <sys/sx.h>
46 #include <sys/unistd.h>
47 #include <sys/callout.h>
48 #include <sys/malloc.h>
49 #include <sys/priv.h>
50 #include <sys/conf.h>
51 #include <sys/fcntl.h>
52
53 #include <dev/usb/usb.h>
54 #include <dev/usb/usb_ioctl.h>
55 #include <dev/usb/usbdi.h>
56 #include <dev/usb/usbdi_util.h>
57
58 #define USB_DEBUG_VAR ugen_debug
59
60 #include <dev/usb/usb_core.h>
61 #include <dev/usb/usb_dev.h>
62 #include <dev/usb/usb_mbuf.h>
63 #include <dev/usb/usb_process.h>
64 #include <dev/usb/usb_device.h>
65 #include <dev/usb/usb_debug.h>
66 #include <dev/usb/usb_request.h>
67 #include <dev/usb/usb_busdma.h>
68 #include <dev/usb/usb_util.h>
69 #include <dev/usb/usb_hub.h>
70 #include <dev/usb/usb_generic.h>
71 #include <dev/usb/usb_transfer.h>
72
73 #include <dev/usb/usb_controller.h>
74 #include <dev/usb/usb_bus.h>
75 #endif                  /* USB_GLOBAL_INCLUDE_FILE */
76
77 #if USB_HAVE_UGEN
78
79 /* defines */
80
81 #define UGEN_BULK_FS_BUFFER_SIZE        (64*32) /* bytes */
82 #define UGEN_BULK_HS_BUFFER_SIZE        (1024*32)       /* bytes */
83 #define UGEN_HW_FRAMES  50              /* number of milliseconds per transfer */
84
85 /* function prototypes */
86
87 static usb_callback_t ugen_read_clear_stall_callback;
88 static usb_callback_t ugen_write_clear_stall_callback;
89 static usb_callback_t ugen_ctrl_read_callback;
90 static usb_callback_t ugen_ctrl_write_callback;
91 static usb_callback_t ugen_isoc_read_callback;
92 static usb_callback_t ugen_isoc_write_callback;
93 static usb_callback_t ugen_ctrl_fs_callback;
94
95 static usb_fifo_open_t ugen_open;
96 static usb_fifo_close_t ugen_close;
97 static usb_fifo_ioctl_t ugen_ioctl;
98 static usb_fifo_ioctl_t ugen_ioctl_post;
99 static usb_fifo_cmd_t ugen_start_read;
100 static usb_fifo_cmd_t ugen_start_write;
101 static usb_fifo_cmd_t ugen_stop_io;
102
103 static int      ugen_transfer_setup(struct usb_fifo *,
104                      const struct usb_config *, uint8_t);
105 static int      ugen_open_pipe_write(struct usb_fifo *);
106 static int      ugen_open_pipe_read(struct usb_fifo *);
107 static int      ugen_set_config(struct usb_fifo *, uint8_t);
108 static int      ugen_set_interface(struct usb_fifo *, uint8_t, uint8_t);
109 static int      ugen_get_cdesc(struct usb_fifo *, struct usb_gen_descriptor *);
110 static int      ugen_get_sdesc(struct usb_fifo *, struct usb_gen_descriptor *);
111 static int      ugen_get_iface_driver(struct usb_fifo *f, struct usb_gen_descriptor *ugd);
112 static int      usb_gen_fill_deviceinfo(struct usb_fifo *,
113                     struct usb_device_info *);
114 static int      ugen_re_enumerate(struct usb_fifo *);
115 static int      ugen_iface_ioctl(struct usb_fifo *, u_long, void *, int);
116 static uint8_t  ugen_fs_get_complete(struct usb_fifo *, uint8_t *);
117 static int      ugen_fs_uninit(struct usb_fifo *f);
118
119 /* structures */
120
121 struct usb_fifo_methods usb_ugen_methods = {
122         .f_open = &ugen_open,
123         .f_close = &ugen_close,
124         .f_ioctl = &ugen_ioctl,
125         .f_ioctl_post = &ugen_ioctl_post,
126         .f_start_read = &ugen_start_read,
127         .f_stop_read = &ugen_stop_io,
128         .f_start_write = &ugen_start_write,
129         .f_stop_write = &ugen_stop_io,
130 };
131
132 #ifdef USB_DEBUG
133 static int ugen_debug = 0;
134
135 static SYSCTL_NODE(_hw_usb, OID_AUTO, ugen, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
136     "USB generic");
137 SYSCTL_INT(_hw_usb_ugen, OID_AUTO, debug, CTLFLAG_RWTUN, &ugen_debug,
138     0, "Debug level");
139 #endif
140
141
142 /* prototypes */
143
144 static int
145 ugen_transfer_setup(struct usb_fifo *f,
146     const struct usb_config *setup, uint8_t n_setup)
147 {
148         struct usb_endpoint *ep = usb_fifo_softc(f);
149         struct usb_device *udev = f->udev;
150         uint8_t iface_index = ep->iface_index;
151         int error;
152
153         mtx_unlock(f->priv_mtx);
154
155         /*
156          * "usbd_transfer_setup()" can sleep so one needs to make a wrapper,
157          * exiting the mutex and checking things
158          */
159         error = usbd_transfer_setup(udev, &iface_index, f->xfer,
160             setup, n_setup, f, f->priv_mtx);
161         if (error == 0) {
162
163                 if (f->xfer[0]->nframes == 1) {
164                         error = usb_fifo_alloc_buffer(f,
165                             f->xfer[0]->max_data_length, 2);
166                 } else {
167                         error = usb_fifo_alloc_buffer(f,
168                             f->xfer[0]->max_frame_size,
169                             2 * f->xfer[0]->nframes);
170                 }
171                 if (error) {
172                         usbd_transfer_unsetup(f->xfer, n_setup);
173                 }
174         }
175         mtx_lock(f->priv_mtx);
176
177         return (error);
178 }
179
180 static int
181 ugen_open(struct usb_fifo *f, int fflags)
182 {
183         struct usb_endpoint *ep = usb_fifo_softc(f);
184         struct usb_endpoint_descriptor *ed = ep->edesc;
185         uint8_t type;
186
187         DPRINTFN(1, "flag=0x%x pid=%d name=%s\n", fflags,
188             curthread->td_proc->p_pid, curthread->td_proc->p_comm);
189
190         mtx_lock(f->priv_mtx);
191         switch (usbd_get_speed(f->udev)) {
192         case USB_SPEED_LOW:
193         case USB_SPEED_FULL:
194                 f->nframes = UGEN_HW_FRAMES;
195                 f->bufsize = UGEN_BULK_FS_BUFFER_SIZE;
196                 break;
197         default:
198                 f->nframes = UGEN_HW_FRAMES * 8;
199                 f->bufsize = UGEN_BULK_HS_BUFFER_SIZE;
200                 break;
201         }
202
203         type = ed->bmAttributes & UE_XFERTYPE;
204         if (type == UE_INTERRUPT) {
205                 f->bufsize = 0;         /* use "wMaxPacketSize" */
206         }
207         f->timeout = USB_NO_TIMEOUT;
208         f->flag_short = 0;
209         f->fifo_zlp = 0;
210         mtx_unlock(f->priv_mtx);
211
212         return (0);
213 }
214
215 static void
216 ugen_close(struct usb_fifo *f, int fflags)
217 {
218
219         DPRINTFN(1, "flag=0x%x pid=%d name=%s\n", fflags,
220             curthread->td_proc->p_pid, curthread->td_proc->p_comm);
221
222         /* cleanup */
223
224         mtx_lock(f->priv_mtx);
225         usbd_transfer_stop(f->xfer[0]);
226         usbd_transfer_stop(f->xfer[1]);
227         mtx_unlock(f->priv_mtx);
228
229         usbd_transfer_unsetup(f->xfer, 2);
230         usb_fifo_free_buffer(f);
231
232         if (ugen_fs_uninit(f)) {
233                 /* ignore any errors - we are closing */
234                 DPRINTFN(6, "no FIFOs\n");
235         }
236 }
237
238 static int
239 ugen_open_pipe_write(struct usb_fifo *f)
240 {
241         struct usb_config usb_config[2];
242         struct usb_endpoint *ep = usb_fifo_softc(f);
243         struct usb_endpoint_descriptor *ed = ep->edesc;
244
245         USB_MTX_ASSERT(f->priv_mtx, MA_OWNED);
246
247         if (f->xfer[0] || f->xfer[1]) {
248                 /* transfers are already opened */
249                 return (0);
250         }
251         memset(usb_config, 0, sizeof(usb_config));
252
253         usb_config[1].type = UE_CONTROL;
254         usb_config[1].endpoint = 0;
255         usb_config[1].direction = UE_DIR_ANY;
256         usb_config[1].timeout = 1000;   /* 1 second */
257         usb_config[1].interval = 50;/* 50 milliseconds */
258         usb_config[1].bufsize = sizeof(struct usb_device_request);
259         usb_config[1].callback = &ugen_write_clear_stall_callback;
260         usb_config[1].usb_mode = USB_MODE_HOST;
261
262         usb_config[0].type = ed->bmAttributes & UE_XFERTYPE;
263         usb_config[0].endpoint = ed->bEndpointAddress & UE_ADDR;
264         usb_config[0].stream_id = 0;    /* XXX support more stream ID's */
265         usb_config[0].direction = UE_DIR_TX;
266         usb_config[0].interval = USB_DEFAULT_INTERVAL;
267         usb_config[0].flags.proxy_buffer = 1;
268         usb_config[0].usb_mode = USB_MODE_DUAL; /* both modes */
269
270         switch (ed->bmAttributes & UE_XFERTYPE) {
271         case UE_INTERRUPT:
272         case UE_BULK:
273                 if (f->flag_short) {
274                         usb_config[0].flags.force_short_xfer = 1;
275                 }
276                 usb_config[0].callback = &ugen_ctrl_write_callback;
277                 usb_config[0].timeout = f->timeout;
278                 usb_config[0].frames = 1;
279                 usb_config[0].bufsize = f->bufsize;
280                 if (ugen_transfer_setup(f, usb_config, 2)) {
281                         return (EIO);
282                 }
283                 /* first transfer does not clear stall */
284                 f->flag_stall = 0;
285                 break;
286
287         case UE_ISOCHRONOUS:
288                 usb_config[0].flags.short_xfer_ok = 1;
289                 usb_config[0].bufsize = 0;      /* use default */
290                 usb_config[0].frames = f->nframes;
291                 usb_config[0].callback = &ugen_isoc_write_callback;
292                 usb_config[0].timeout = 0;
293
294                 /* clone configuration */
295                 usb_config[1] = usb_config[0];
296
297                 if (ugen_transfer_setup(f, usb_config, 2)) {
298                         return (EIO);
299                 }
300                 break;
301         default:
302                 return (EINVAL);
303         }
304         return (0);
305 }
306
307 static int
308 ugen_open_pipe_read(struct usb_fifo *f)
309 {
310         struct usb_config usb_config[2];
311         struct usb_endpoint *ep = usb_fifo_softc(f);
312         struct usb_endpoint_descriptor *ed = ep->edesc;
313
314         USB_MTX_ASSERT(f->priv_mtx, MA_OWNED);
315
316         if (f->xfer[0] || f->xfer[1]) {
317                 /* transfers are already opened */
318                 return (0);
319         }
320         memset(usb_config, 0, sizeof(usb_config));
321
322         usb_config[1].type = UE_CONTROL;
323         usb_config[1].endpoint = 0;
324         usb_config[1].direction = UE_DIR_ANY;
325         usb_config[1].timeout = 1000;   /* 1 second */
326         usb_config[1].interval = 50;/* 50 milliseconds */
327         usb_config[1].bufsize = sizeof(struct usb_device_request);
328         usb_config[1].callback = &ugen_read_clear_stall_callback;
329         usb_config[1].usb_mode = USB_MODE_HOST;
330
331         usb_config[0].type = ed->bmAttributes & UE_XFERTYPE;
332         usb_config[0].endpoint = ed->bEndpointAddress & UE_ADDR;
333         usb_config[0].stream_id = 0;    /* XXX support more stream ID's */
334         usb_config[0].direction = UE_DIR_RX;
335         usb_config[0].interval = USB_DEFAULT_INTERVAL;
336         usb_config[0].flags.proxy_buffer = 1;
337         usb_config[0].usb_mode = USB_MODE_DUAL; /* both modes */
338
339         switch (ed->bmAttributes & UE_XFERTYPE) {
340         case UE_INTERRUPT:
341         case UE_BULK:
342                 if (f->flag_short) {
343                         usb_config[0].flags.short_xfer_ok = 1;
344                 }
345                 usb_config[0].timeout = f->timeout;
346                 usb_config[0].frames = 1;
347                 usb_config[0].callback = &ugen_ctrl_read_callback;
348                 usb_config[0].bufsize = f->bufsize;
349
350                 if (ugen_transfer_setup(f, usb_config, 2)) {
351                         return (EIO);
352                 }
353                 /* first transfer does not clear stall */
354                 f->flag_stall = 0;
355                 break;
356
357         case UE_ISOCHRONOUS:
358                 usb_config[0].flags.short_xfer_ok = 1;
359                 usb_config[0].bufsize = 0;      /* use default */
360                 usb_config[0].frames = f->nframes;
361                 usb_config[0].callback = &ugen_isoc_read_callback;
362                 usb_config[0].timeout = 0;
363
364                 /* clone configuration */
365                 usb_config[1] = usb_config[0];
366
367                 if (ugen_transfer_setup(f, usb_config, 2)) {
368                         return (EIO);
369                 }
370                 break;
371
372         default:
373                 return (EINVAL);
374         }
375         return (0);
376 }
377
378 static void
379 ugen_start_read(struct usb_fifo *f)
380 {
381         /* check that pipes are open */
382         if (ugen_open_pipe_read(f)) {
383                 /* signal error */
384                 usb_fifo_put_data_error(f);
385         }
386         /* start transfers */
387         usbd_transfer_start(f->xfer[0]);
388         usbd_transfer_start(f->xfer[1]);
389 }
390
391 static void
392 ugen_start_write(struct usb_fifo *f)
393 {
394         /* check that pipes are open */
395         if (ugen_open_pipe_write(f)) {
396                 /* signal error */
397                 usb_fifo_get_data_error(f);
398         }
399         /* start transfers */
400         usbd_transfer_start(f->xfer[0]);
401         usbd_transfer_start(f->xfer[1]);
402 }
403
404 static void
405 ugen_stop_io(struct usb_fifo *f)
406 {
407         /* stop transfers */
408         usbd_transfer_stop(f->xfer[0]);
409         usbd_transfer_stop(f->xfer[1]);
410 }
411
412 static void
413 ugen_ctrl_read_callback(struct usb_xfer *xfer, usb_error_t error)
414 {
415         struct usb_fifo *f = usbd_xfer_softc(xfer);
416         struct usb_mbuf *m;
417
418         DPRINTFN(4, "actlen=%u, aframes=%u\n", xfer->actlen, xfer->aframes);
419
420         switch (USB_GET_STATE(xfer)) {
421         case USB_ST_TRANSFERRED:
422                 if (xfer->actlen == 0) {
423                         if (f->fifo_zlp != 4) {
424                                 f->fifo_zlp++;
425                         } else {
426                                 /*
427                                  * Throttle a little bit we have multiple ZLPs
428                                  * in a row!
429                                  */
430                                 xfer->interval = 64;    /* ms */
431                         }
432                 } else {
433                         /* clear throttle */
434                         xfer->interval = 0;
435                         f->fifo_zlp = 0;
436                 }
437                 usb_fifo_put_data(f, xfer->frbuffers, 0,
438                     xfer->actlen, 1);
439
440         case USB_ST_SETUP:
441                 if (f->flag_stall) {
442                         usbd_transfer_start(f->xfer[1]);
443                         break;
444                 }
445                 USB_IF_POLL(&f->free_q, m);
446                 if (m) {
447                         usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
448                         usbd_transfer_submit(xfer);
449                 }
450                 break;
451
452         default:                        /* Error */
453                 if (xfer->error != USB_ERR_CANCELLED) {
454                         /* send a zero length packet to userland */
455                         usb_fifo_put_data(f, xfer->frbuffers, 0, 0, 1);
456                         f->flag_stall = 1;
457                         f->fifo_zlp = 0;
458                         usbd_transfer_start(f->xfer[1]);
459                 }
460                 break;
461         }
462 }
463
464 static void
465 ugen_ctrl_write_callback(struct usb_xfer *xfer, usb_error_t error)
466 {
467         struct usb_fifo *f = usbd_xfer_softc(xfer);
468         usb_frlength_t actlen;
469
470         DPRINTFN(4, "actlen=%u, aframes=%u\n", xfer->actlen, xfer->aframes);
471
472         switch (USB_GET_STATE(xfer)) {
473         case USB_ST_SETUP:
474         case USB_ST_TRANSFERRED:
475                 /*
476                  * If writing is in stall, just jump to clear stall
477                  * callback and solve the situation.
478                  */
479                 if (f->flag_stall) {
480                         usbd_transfer_start(f->xfer[1]);
481                         break;
482                 }
483                 /*
484                  * Write data, setup and perform hardware transfer.
485                  */
486                 if (usb_fifo_get_data(f, xfer->frbuffers, 0,
487                     xfer->max_data_length, &actlen, 0)) {
488                         usbd_xfer_set_frame_len(xfer, 0, actlen);
489                         usbd_transfer_submit(xfer);
490                 }
491                 break;
492
493         default:                        /* Error */
494                 if (xfer->error != USB_ERR_CANCELLED) {
495                         f->flag_stall = 1;
496                         usbd_transfer_start(f->xfer[1]);
497                 }
498                 break;
499         }
500 }
501
502 static void
503 ugen_read_clear_stall_callback(struct usb_xfer *xfer, usb_error_t error)
504 {
505         struct usb_fifo *f = usbd_xfer_softc(xfer);
506         struct usb_xfer *xfer_other = f->xfer[0];
507
508         if (f->flag_stall == 0) {
509                 /* nothing to do */
510                 return;
511         }
512         if (usbd_clear_stall_callback(xfer, xfer_other)) {
513                 DPRINTFN(5, "f=%p: stall cleared\n", f);
514                 f->flag_stall = 0;
515                 usbd_transfer_start(xfer_other);
516         }
517 }
518
519 static void
520 ugen_write_clear_stall_callback(struct usb_xfer *xfer, usb_error_t error)
521 {
522         struct usb_fifo *f = usbd_xfer_softc(xfer);
523         struct usb_xfer *xfer_other = f->xfer[0];
524
525         if (f->flag_stall == 0) {
526                 /* nothing to do */
527                 return;
528         }
529         if (usbd_clear_stall_callback(xfer, xfer_other)) {
530                 DPRINTFN(5, "f=%p: stall cleared\n", f);
531                 f->flag_stall = 0;
532                 usbd_transfer_start(xfer_other);
533         }
534 }
535
536 static void
537 ugen_isoc_read_callback(struct usb_xfer *xfer, usb_error_t error)
538 {
539         struct usb_fifo *f = usbd_xfer_softc(xfer);
540         usb_frlength_t offset;
541         usb_frcount_t n;
542
543         DPRINTFN(4, "actlen=%u, aframes=%u\n", xfer->actlen, xfer->aframes);
544
545         switch (USB_GET_STATE(xfer)) {
546         case USB_ST_TRANSFERRED:
547
548                 DPRINTFN(6, "actlen=%d\n", xfer->actlen);
549
550                 offset = 0;
551
552                 for (n = 0; n != xfer->aframes; n++) {
553                         usb_fifo_put_data(f, xfer->frbuffers, offset,
554                             xfer->frlengths[n], 1);
555                         offset += xfer->max_frame_size;
556                 }
557
558         case USB_ST_SETUP:
559 tr_setup:
560                 for (n = 0; n != xfer->nframes; n++) {
561                         /* setup size for next transfer */
562                         usbd_xfer_set_frame_len(xfer, n, xfer->max_frame_size);
563                 }
564                 usbd_transfer_submit(xfer);
565                 break;
566
567         default:                        /* Error */
568                 if (xfer->error == USB_ERR_CANCELLED) {
569                         break;
570                 }
571                 goto tr_setup;
572         }
573 }
574
575 static void
576 ugen_isoc_write_callback(struct usb_xfer *xfer, usb_error_t error)
577 {
578         struct usb_fifo *f = usbd_xfer_softc(xfer);
579         usb_frlength_t actlen;
580         usb_frlength_t offset;
581         usb_frcount_t n;
582
583         DPRINTFN(4, "actlen=%u, aframes=%u\n", xfer->actlen, xfer->aframes);
584
585         switch (USB_GET_STATE(xfer)) {
586         case USB_ST_TRANSFERRED:
587         case USB_ST_SETUP:
588 tr_setup:
589                 offset = 0;
590                 for (n = 0; n != xfer->nframes; n++) {
591                         if (usb_fifo_get_data(f, xfer->frbuffers, offset,
592                             xfer->max_frame_size, &actlen, 1)) {
593                                 usbd_xfer_set_frame_len(xfer, n, actlen);
594                                 offset += actlen;
595                         } else {
596                                 break;
597                         }
598                 }
599
600                 for (; n != xfer->nframes; n++) {
601                         /* fill in zero frames */
602                         usbd_xfer_set_frame_len(xfer, n, 0);
603                 }
604                 usbd_transfer_submit(xfer);
605                 break;
606
607         default:                        /* Error */
608                 if (xfer->error == USB_ERR_CANCELLED) {
609                         break;
610                 }
611                 goto tr_setup;
612         }
613 }
614
615 static int
616 ugen_set_config(struct usb_fifo *f, uint8_t index)
617 {
618         DPRINTFN(2, "index %u\n", index);
619
620         if (f->udev->flags.usb_mode != USB_MODE_HOST) {
621                 /* not possible in device side mode */
622                 return (ENOTTY);
623         }
624
625         /* make sure all FIFO's are gone */
626         /* else there can be a deadlock */
627         if (ugen_fs_uninit(f)) {
628                 /* ignore any errors */
629                 DPRINTFN(6, "no FIFOs\n");
630         }
631
632         if (usbd_start_set_config(f->udev, index) != 0)
633                 return (EIO);
634
635         return (0);
636 }
637
638 static int
639 ugen_set_interface(struct usb_fifo *f,
640     uint8_t iface_index, uint8_t alt_index)
641 {
642         DPRINTFN(2, "%u, %u\n", iface_index, alt_index);
643
644         if (f->udev->flags.usb_mode != USB_MODE_HOST) {
645                 /* not possible in device side mode */
646                 return (ENOTTY);
647         }
648         /* make sure all FIFO's are gone */
649         /* else there can be a deadlock */
650         if (ugen_fs_uninit(f)) {
651                 /* ignore any errors */
652                 DPRINTFN(6, "no FIFOs\n");
653         }
654         /* change setting - will free generic FIFOs, if any */
655         if (usbd_set_alt_interface_index(f->udev, iface_index, alt_index)) {
656                 return (EIO);
657         }
658         /* probe and attach */
659         if (usb_probe_and_attach(f->udev, iface_index)) {
660                 return (EIO);
661         }
662         return (0);
663 }
664
665 /*------------------------------------------------------------------------*
666  *      ugen_get_cdesc
667  *
668  * This function will retrieve the complete configuration descriptor
669  * at the given index.
670  *------------------------------------------------------------------------*/
671 static int
672 ugen_get_cdesc(struct usb_fifo *f, struct usb_gen_descriptor *ugd)
673 {
674         struct usb_config_descriptor *cdesc;
675         struct usb_device *udev = f->udev;
676         int error;
677         uint16_t len;
678         uint8_t free_data;
679
680         DPRINTFN(6, "\n");
681
682         if (ugd->ugd_data == NULL) {
683                 /* userland pointer should not be zero */
684                 return (EINVAL);
685         }
686         if ((ugd->ugd_config_index == USB_UNCONFIG_INDEX) ||
687             (ugd->ugd_config_index == udev->curr_config_index)) {
688                 cdesc = usbd_get_config_descriptor(udev);
689                 if (cdesc == NULL)
690                         return (ENXIO);
691                 free_data = 0;
692
693         } else {
694 #if (USB_HAVE_FIXED_CONFIG == 0)
695                 if (usbd_req_get_config_desc_full(udev,
696                     NULL, &cdesc, ugd->ugd_config_index)) {
697                         return (ENXIO);
698                 }
699                 free_data = 1;
700 #else
701                 /* configuration descriptor data is shared */
702                 return (EINVAL);
703 #endif
704         }
705
706         len = UGETW(cdesc->wTotalLength);
707         if (len > ugd->ugd_maxlen) {
708                 len = ugd->ugd_maxlen;
709         }
710         DPRINTFN(6, "len=%u\n", len);
711
712         ugd->ugd_actlen = len;
713         ugd->ugd_offset = 0;
714
715         error = copyout(cdesc, ugd->ugd_data, len);
716
717         if (free_data)
718                 usbd_free_config_desc(udev, cdesc);
719
720         return (error);
721 }
722
723 static int
724 ugen_get_sdesc(struct usb_fifo *f, struct usb_gen_descriptor *ugd)
725 {
726         void *ptr;
727         uint16_t size;
728         int error;
729         uint8_t do_unlock;
730
731         /* Protect scratch area */
732         do_unlock = usbd_ctrl_lock(f->udev);
733
734         ptr = f->udev->scratch.data;
735         size = sizeof(f->udev->scratch.data);
736
737         if (usbd_req_get_string_desc(f->udev, NULL, ptr,
738             size, ugd->ugd_lang_id, ugd->ugd_string_index)) {
739                 error = EINVAL;
740         } else {
741
742                 if (size > ((uint8_t *)ptr)[0]) {
743                         size = ((uint8_t *)ptr)[0];
744                 }
745                 if (size > ugd->ugd_maxlen) {
746                         size = ugd->ugd_maxlen;
747                 }
748                 ugd->ugd_actlen = size;
749                 ugd->ugd_offset = 0;
750
751                 error = copyout(ptr, ugd->ugd_data, size);
752         }
753         if (do_unlock)
754                 usbd_ctrl_unlock(f->udev);
755
756         return (error);
757 }
758
759 /*------------------------------------------------------------------------*
760  *      ugen_get_iface_driver
761  *
762  * This function generates an USB interface description for userland.
763  *
764  * Returns:
765  *    0: Success
766  * Else: Failure
767  *------------------------------------------------------------------------*/
768 static int
769 ugen_get_iface_driver(struct usb_fifo *f, struct usb_gen_descriptor *ugd)
770 {
771         struct usb_device *udev = f->udev;
772         struct usb_interface *iface;
773         const char *ptr;
774         const char *desc;
775         unsigned int len;
776         unsigned int maxlen;
777         char buf[128];
778         int error;
779
780         DPRINTFN(6, "\n");
781
782         if ((ugd->ugd_data == NULL) || (ugd->ugd_maxlen == 0)) {
783                 /* userland pointer should not be zero */
784                 return (EINVAL);
785         }
786
787         iface = usbd_get_iface(udev, ugd->ugd_iface_index);
788         if ((iface == NULL) || (iface->idesc == NULL)) {
789                 /* invalid interface index */
790                 return (EINVAL);
791         }
792
793         /* read out device nameunit string, if any */
794         if ((iface->subdev != NULL) &&
795             device_is_attached(iface->subdev) &&
796             (ptr = device_get_nameunit(iface->subdev)) &&
797             (desc = device_get_desc(iface->subdev))) {
798
799                 /* print description */
800                 snprintf(buf, sizeof(buf), "%s: <%s>", ptr, desc);
801
802                 /* range checks */
803                 maxlen = ugd->ugd_maxlen - 1;
804                 len = strlen(buf);
805                 if (len > maxlen)
806                         len = maxlen;
807
808                 /* update actual length, including terminating zero */
809                 ugd->ugd_actlen = len + 1;
810
811                 /* copy out interface description */
812                 error = copyout(buf, ugd->ugd_data, ugd->ugd_actlen);
813         } else {
814                 /* zero length string is default */
815                 error = copyout("", ugd->ugd_data, 1);
816         }
817         return (error);
818 }
819
820 /*------------------------------------------------------------------------*
821  *      usb_gen_fill_deviceinfo
822  *
823  * This function dumps information about an USB device to the
824  * structure pointed to by the "di" argument.
825  *
826  * Returns:
827  *    0: Success
828  * Else: Failure
829  *------------------------------------------------------------------------*/
830 static int
831 usb_gen_fill_deviceinfo(struct usb_fifo *f, struct usb_device_info *di)
832 {
833         struct usb_device *udev;
834         struct usb_device *hub;
835
836         udev = f->udev;
837
838         bzero(di, sizeof(di[0]));
839
840         di->udi_bus = device_get_unit(udev->bus->bdev);
841         di->udi_addr = udev->address;
842         di->udi_index = udev->device_index;
843         strlcpy(di->udi_serial, usb_get_serial(udev), sizeof(di->udi_serial));
844         strlcpy(di->udi_vendor, usb_get_manufacturer(udev), sizeof(di->udi_vendor));
845         strlcpy(di->udi_product, usb_get_product(udev), sizeof(di->udi_product));
846         usb_printbcd(di->udi_release, sizeof(di->udi_release),
847             UGETW(udev->ddesc.bcdDevice));
848         di->udi_vendorNo = UGETW(udev->ddesc.idVendor);
849         di->udi_productNo = UGETW(udev->ddesc.idProduct);
850         di->udi_releaseNo = UGETW(udev->ddesc.bcdDevice);
851         di->udi_class = udev->ddesc.bDeviceClass;
852         di->udi_subclass = udev->ddesc.bDeviceSubClass;
853         di->udi_protocol = udev->ddesc.bDeviceProtocol;
854         di->udi_config_no = udev->curr_config_no;
855         di->udi_config_index = udev->curr_config_index;
856         di->udi_power = udev->flags.self_powered ? 0 : udev->power;
857         di->udi_speed = udev->speed;
858         di->udi_mode = udev->flags.usb_mode;
859         di->udi_power_mode = udev->power_mode;
860         di->udi_suspended = udev->flags.peer_suspended;
861
862         hub = udev->parent_hub;
863         if (hub) {
864                 di->udi_hubaddr = hub->address;
865                 di->udi_hubindex = hub->device_index;
866                 di->udi_hubport = udev->port_no;
867         }
868         return (0);
869 }
870
871 /*------------------------------------------------------------------------*
872  *      ugen_check_request
873  *
874  * Return values:
875  * 0: Access allowed
876  * Else: No access
877  *------------------------------------------------------------------------*/
878 static int
879 ugen_check_request(struct usb_device *udev, struct usb_device_request *req)
880 {
881         struct usb_endpoint *ep;
882         int error;
883
884         /*
885          * Avoid requests that would damage the bus integrity:
886          */
887         if (((req->bmRequestType == UT_WRITE_DEVICE) &&
888             (req->bRequest == UR_SET_ADDRESS)) ||
889             ((req->bmRequestType == UT_WRITE_DEVICE) &&
890             (req->bRequest == UR_SET_CONFIG)) ||
891             ((req->bmRequestType == UT_WRITE_INTERFACE) &&
892             (req->bRequest == UR_SET_INTERFACE))) {
893                 /*
894                  * These requests can be useful for testing USB drivers.
895                  */
896                 error = priv_check(curthread, PRIV_DRIVER);
897                 if (error) {
898                         return (error);
899                 }
900         }
901         /*
902          * Special case - handle clearing of stall
903          */
904         if (req->bmRequestType == UT_WRITE_ENDPOINT) {
905
906                 ep = usbd_get_ep_by_addr(udev, req->wIndex[0]);
907                 if (ep == NULL) {
908                         return (EINVAL);
909                 }
910                 if ((req->bRequest == UR_CLEAR_FEATURE) &&
911                     (UGETW(req->wValue) == UF_ENDPOINT_HALT)) {
912                         usbd_clear_data_toggle(udev, ep);
913                 }
914         }
915         /* TODO: add more checks to verify the interface index */
916
917         return (0);
918 }
919
920 int
921 ugen_do_request(struct usb_fifo *f, struct usb_ctl_request *ur)
922 {
923         int error;
924         uint16_t len;
925         uint16_t actlen;
926
927         if (ugen_check_request(f->udev, &ur->ucr_request)) {
928                 return (EPERM);
929         }
930         len = UGETW(ur->ucr_request.wLength);
931
932         /* check if "ucr_data" is valid */
933         if (len != 0) {
934                 if (ur->ucr_data == NULL) {
935                         return (EFAULT);
936                 }
937         }
938         /* do the USB request */
939         error = usbd_do_request_flags
940             (f->udev, NULL, &ur->ucr_request, ur->ucr_data,
941             (ur->ucr_flags & USB_SHORT_XFER_OK) |
942             USB_USER_DATA_PTR, &actlen,
943             USB_DEFAULT_TIMEOUT);
944
945         ur->ucr_actlen = actlen;
946
947         if (error) {
948                 error = EIO;
949         }
950         return (error);
951 }
952
953 /*------------------------------------------------------------------------
954  *      ugen_re_enumerate
955  *------------------------------------------------------------------------*/
956 static int
957 ugen_re_enumerate(struct usb_fifo *f)
958 {
959         struct usb_device *udev = f->udev;
960         int error;
961
962         /*
963          * This request can be useful for testing USB drivers:
964          */
965         error = priv_check(curthread, PRIV_DRIVER);
966         if (error) {
967                 return (error);
968         }
969         if (udev->flags.usb_mode != USB_MODE_HOST) {
970                 /* not possible in device side mode */
971                 DPRINTFN(6, "device mode\n");
972                 return (ENOTTY);
973         }
974         /* make sure all FIFO's are gone */
975         /* else there can be a deadlock */
976         if (ugen_fs_uninit(f)) {
977                 /* ignore any errors */
978                 DPRINTFN(6, "no FIFOs\n");
979         }
980         /* start re-enumeration of device */
981         usbd_start_re_enumerate(udev);
982         return (0);
983 }
984
985 int
986 ugen_fs_uninit(struct usb_fifo *f)
987 {
988         if (f->fs_xfer == NULL) {
989                 return (EINVAL);
990         }
991         usbd_transfer_unsetup(f->fs_xfer, f->fs_ep_max);
992         free(f->fs_xfer, M_USB);
993         f->fs_xfer = NULL;
994         f->fs_ep_max = 0;
995         f->fs_ep_ptr = NULL;
996         f->flag_iscomplete = 0;
997         usb_fifo_free_buffer(f);
998         return (0);
999 }
1000
1001 static uint8_t
1002 ugen_fs_get_complete(struct usb_fifo *f, uint8_t *pindex)
1003 {
1004         struct usb_mbuf *m;
1005
1006         USB_IF_DEQUEUE(&f->used_q, m);
1007
1008         if (m) {
1009                 *pindex = *((uint8_t *)(m->cur_data_ptr));
1010
1011                 USB_IF_ENQUEUE(&f->free_q, m);
1012
1013                 return (0);             /* success */
1014         } else {
1015
1016                 *pindex = 0;            /* fix compiler warning */
1017
1018                 f->flag_iscomplete = 0;
1019         }
1020         return (1);                     /* failure */
1021 }
1022
1023 static void
1024 ugen_fs_set_complete(struct usb_fifo *f, uint8_t index)
1025 {
1026         struct usb_mbuf *m;
1027
1028         USB_IF_DEQUEUE(&f->free_q, m);
1029
1030         if (m == NULL) {
1031                 /* can happen during close */
1032                 DPRINTF("out of buffers\n");
1033                 return;
1034         }
1035         USB_MBUF_RESET(m);
1036
1037         *((uint8_t *)(m->cur_data_ptr)) = index;
1038
1039         USB_IF_ENQUEUE(&f->used_q, m);
1040
1041         f->flag_iscomplete = 1;
1042
1043         usb_fifo_wakeup(f);
1044 }
1045
1046 static int
1047 ugen_fs_copy_in(struct usb_fifo *f, uint8_t ep_index)
1048 {
1049         struct usb_device_request *req;
1050         struct usb_xfer *xfer;
1051         struct usb_fs_endpoint fs_ep;
1052         void *uaddr;                    /* userland pointer */
1053         void *kaddr;
1054         usb_frlength_t offset;
1055         usb_frlength_t rem;
1056         usb_frcount_t n;
1057         uint32_t length;
1058         int error;
1059         uint8_t isread;
1060
1061         if (ep_index >= f->fs_ep_max) {
1062                 return (EINVAL);
1063         }
1064         xfer = f->fs_xfer[ep_index];
1065         if (xfer == NULL) {
1066                 return (EINVAL);
1067         }
1068         mtx_lock(f->priv_mtx);
1069         if (usbd_transfer_pending(xfer)) {
1070                 mtx_unlock(f->priv_mtx);
1071                 return (EBUSY);         /* should not happen */
1072         }
1073         mtx_unlock(f->priv_mtx);
1074
1075         error = copyin(f->fs_ep_ptr +
1076             ep_index, &fs_ep, sizeof(fs_ep));
1077         if (error) {
1078                 return (error);
1079         }
1080         /* security checks */
1081
1082         if (fs_ep.nFrames > xfer->max_frame_count) {
1083                 xfer->error = USB_ERR_INVAL;
1084                 goto complete;
1085         }
1086         if (fs_ep.nFrames == 0) {
1087                 xfer->error = USB_ERR_INVAL;
1088                 goto complete;
1089         }
1090         error = copyin(fs_ep.ppBuffer,
1091             &uaddr, sizeof(uaddr));
1092         if (error) {
1093                 return (error);
1094         }
1095         /* reset first frame */
1096         usbd_xfer_set_frame_offset(xfer, 0, 0);
1097
1098         if (xfer->flags_int.control_xfr) {
1099
1100                 req = xfer->frbuffers[0].buffer;
1101
1102                 error = copyin(fs_ep.pLength,
1103                     &length, sizeof(length));
1104                 if (error) {
1105                         return (error);
1106                 }
1107                 if (length != sizeof(*req)) {
1108                         xfer->error = USB_ERR_INVAL;
1109                         goto complete;
1110                 }
1111                 if (length != 0) {
1112                         error = copyin(uaddr, req, length);
1113                         if (error) {
1114                                 return (error);
1115                         }
1116                 }
1117                 if (ugen_check_request(f->udev, req)) {
1118                         xfer->error = USB_ERR_INVAL;
1119                         goto complete;
1120                 }
1121                 usbd_xfer_set_frame_len(xfer, 0, length);
1122
1123                 /* Host mode only ! */
1124                 if ((req->bmRequestType &
1125                     (UT_READ | UT_WRITE)) == UT_READ) {
1126                         isread = 1;
1127                 } else {
1128                         isread = 0;
1129                 }
1130                 n = 1;
1131                 offset = sizeof(*req);
1132
1133         } else {
1134                 /* Device and Host mode */
1135                 if (USB_GET_DATA_ISREAD(xfer)) {
1136                         isread = 1;
1137                 } else {
1138                         isread = 0;
1139                 }
1140                 n = 0;
1141                 offset = 0;
1142         }
1143
1144         rem = usbd_xfer_max_len(xfer);
1145         xfer->nframes = fs_ep.nFrames;
1146         xfer->timeout = fs_ep.timeout;
1147         if (xfer->timeout > 65535) {
1148                 xfer->timeout = 65535;
1149         }
1150         if (fs_ep.flags & USB_FS_FLAG_SINGLE_SHORT_OK)
1151                 xfer->flags.short_xfer_ok = 1;
1152         else
1153                 xfer->flags.short_xfer_ok = 0;
1154
1155         if (fs_ep.flags & USB_FS_FLAG_MULTI_SHORT_OK)
1156                 xfer->flags.short_frames_ok = 1;
1157         else
1158                 xfer->flags.short_frames_ok = 0;
1159
1160         if (fs_ep.flags & USB_FS_FLAG_FORCE_SHORT)
1161                 xfer->flags.force_short_xfer = 1;
1162         else
1163                 xfer->flags.force_short_xfer = 0;
1164
1165         if (fs_ep.flags & USB_FS_FLAG_CLEAR_STALL)
1166                 usbd_xfer_set_stall(xfer);
1167         else
1168                 xfer->flags.stall_pipe = 0;
1169
1170         for (; n != xfer->nframes; n++) {
1171
1172                 error = copyin(fs_ep.pLength + n,
1173                     &length, sizeof(length));
1174                 if (error) {
1175                         break;
1176                 }
1177                 usbd_xfer_set_frame_len(xfer, n, length);
1178
1179                 if (length > rem) {
1180                         xfer->error = USB_ERR_INVAL;
1181                         goto complete;
1182                 }
1183                 rem -= length;
1184
1185                 if (!isread) {
1186
1187                         /* we need to know the source buffer */
1188                         error = copyin(fs_ep.ppBuffer + n,
1189                             &uaddr, sizeof(uaddr));
1190                         if (error) {
1191                                 break;
1192                         }
1193                         if (xfer->flags_int.isochronous_xfr) {
1194                                 /* get kernel buffer address */
1195                                 kaddr = xfer->frbuffers[0].buffer;
1196                                 kaddr = USB_ADD_BYTES(kaddr, offset);
1197                         } else {
1198                                 /* set current frame offset */
1199                                 usbd_xfer_set_frame_offset(xfer, offset, n);
1200
1201                                 /* get kernel buffer address */
1202                                 kaddr = xfer->frbuffers[n].buffer;
1203                         }
1204
1205                         /* move data */
1206                         error = copyin(uaddr, kaddr, length);
1207                         if (error) {
1208                                 break;
1209                         }
1210                 }
1211                 offset += length;
1212         }
1213         return (error);
1214
1215 complete:
1216         mtx_lock(f->priv_mtx);
1217         ugen_fs_set_complete(f, ep_index);
1218         mtx_unlock(f->priv_mtx);
1219         return (0);
1220 }
1221
1222 static int
1223 ugen_fs_copy_out_cancelled(struct usb_fs_endpoint *fs_ep_uptr)
1224 {
1225         struct usb_fs_endpoint fs_ep;
1226         int error;
1227
1228         error = copyin(fs_ep_uptr, &fs_ep, sizeof(fs_ep));
1229         if (error)
1230                 return (error);
1231
1232         fs_ep.status = USB_ERR_CANCELLED;
1233         fs_ep.aFrames = 0;
1234         fs_ep.isoc_time_complete = 0;
1235
1236         /* update "aFrames" */
1237         error = copyout(&fs_ep.aFrames, &fs_ep_uptr->aFrames,
1238             sizeof(fs_ep.aFrames));
1239         if (error)
1240                 goto done;
1241
1242         /* update "isoc_time_complete" */
1243         error = copyout(&fs_ep.isoc_time_complete,
1244             &fs_ep_uptr->isoc_time_complete,
1245             sizeof(fs_ep.isoc_time_complete));
1246         if (error)
1247                 goto done;
1248
1249         /* update "status" */
1250         error = copyout(&fs_ep.status, &fs_ep_uptr->status,
1251             sizeof(fs_ep.status));
1252 done:
1253         return (error);
1254 }
1255
1256 static int
1257 ugen_fs_copy_out(struct usb_fifo *f, uint8_t ep_index)
1258 {
1259         struct usb_device_request *req;
1260         struct usb_xfer *xfer;
1261         struct usb_fs_endpoint fs_ep;
1262         struct usb_fs_endpoint *fs_ep_uptr;     /* userland ptr */
1263         void *uaddr;                    /* userland ptr */
1264         void *kaddr;
1265         usb_frlength_t offset;
1266         usb_frlength_t rem;
1267         usb_frcount_t n;
1268         uint32_t length;
1269         uint32_t temp;
1270         int error;
1271         uint8_t isread;
1272
1273         if (ep_index >= f->fs_ep_max)
1274                 return (EINVAL);
1275
1276         xfer = f->fs_xfer[ep_index];
1277         if (xfer == NULL)
1278                 return (EINVAL);
1279
1280         mtx_lock(f->priv_mtx);
1281         if (!xfer->flags_int.transferring &&
1282             !xfer->flags_int.started) {
1283                 mtx_unlock(f->priv_mtx);
1284                 DPRINTF("Returning fake cancel event\n");
1285                 return (ugen_fs_copy_out_cancelled(f->fs_ep_ptr + ep_index));
1286         } else if (usbd_transfer_pending(xfer)) {
1287                 mtx_unlock(f->priv_mtx);
1288                 return (EBUSY);         /* should not happen */
1289         }
1290         mtx_unlock(f->priv_mtx);
1291
1292         fs_ep_uptr = f->fs_ep_ptr + ep_index;
1293         error = copyin(fs_ep_uptr, &fs_ep, sizeof(fs_ep));
1294         if (error) {
1295                 return (error);
1296         }
1297         fs_ep.status = xfer->error;
1298         fs_ep.aFrames = xfer->aframes;
1299         fs_ep.isoc_time_complete = xfer->isoc_time_complete;
1300         if (xfer->error) {
1301                 goto complete;
1302         }
1303         if (xfer->flags_int.control_xfr) {
1304                 req = xfer->frbuffers[0].buffer;
1305
1306                 /* Host mode only ! */
1307                 if ((req->bmRequestType & (UT_READ | UT_WRITE)) == UT_READ) {
1308                         isread = 1;
1309                 } else {
1310                         isread = 0;
1311                 }
1312                 if (xfer->nframes == 0)
1313                         n = 0;          /* should never happen */
1314                 else
1315                         n = 1;
1316         } else {
1317                 /* Device and Host mode */
1318                 if (USB_GET_DATA_ISREAD(xfer)) {
1319                         isread = 1;
1320                 } else {
1321                         isread = 0;
1322                 }
1323                 n = 0;
1324         }
1325
1326         /* Update lengths and copy out data */
1327
1328         rem = usbd_xfer_max_len(xfer);
1329         offset = 0;
1330
1331         for (; n != xfer->nframes; n++) {
1332
1333                 /* get initial length into "temp" */
1334                 error = copyin(fs_ep.pLength + n,
1335                     &temp, sizeof(temp));
1336                 if (error) {
1337                         return (error);
1338                 }
1339                 if (temp > rem) {
1340                         /* the userland length has been corrupted */
1341                         DPRINTF("corrupt userland length "
1342                             "%u > %u\n", temp, rem);
1343                         fs_ep.status = USB_ERR_INVAL;
1344                         goto complete;
1345                 }
1346                 rem -= temp;
1347
1348                 /* get actual transfer length */
1349                 length = xfer->frlengths[n];
1350                 if (length > temp) {
1351                         /* data overflow */
1352                         fs_ep.status = USB_ERR_INVAL;
1353                         DPRINTF("data overflow %u > %u\n",
1354                             length, temp);
1355                         goto complete;
1356                 }
1357                 if (isread) {
1358
1359                         /* we need to know the destination buffer */
1360                         error = copyin(fs_ep.ppBuffer + n,
1361                             &uaddr, sizeof(uaddr));
1362                         if (error) {
1363                                 return (error);
1364                         }
1365                         if (xfer->flags_int.isochronous_xfr) {
1366                                 /* only one frame buffer */
1367                                 kaddr = USB_ADD_BYTES(
1368                                     xfer->frbuffers[0].buffer, offset);
1369                         } else {
1370                                 /* multiple frame buffers */
1371                                 kaddr = xfer->frbuffers[n].buffer;
1372                         }
1373
1374                         /* move data */
1375                         error = copyout(kaddr, uaddr, length);
1376                         if (error) {
1377                                 return (error);
1378                         }
1379                 }
1380                 /*
1381                  * Update offset according to initial length, which is
1382                  * needed by isochronous transfers!
1383                  */
1384                 offset += temp;
1385
1386                 /* update length */
1387                 error = copyout(&length,
1388                     fs_ep.pLength + n, sizeof(length));
1389                 if (error) {
1390                         return (error);
1391                 }
1392         }
1393
1394 complete:
1395         /* update "aFrames" */
1396         error = copyout(&fs_ep.aFrames, &fs_ep_uptr->aFrames,
1397             sizeof(fs_ep.aFrames));
1398         if (error)
1399                 goto done;
1400
1401         /* update "isoc_time_complete" */
1402         error = copyout(&fs_ep.isoc_time_complete,
1403             &fs_ep_uptr->isoc_time_complete,
1404             sizeof(fs_ep.isoc_time_complete));
1405         if (error)
1406                 goto done;
1407
1408         /* update "status" */
1409         error = copyout(&fs_ep.status, &fs_ep_uptr->status,
1410             sizeof(fs_ep.status));
1411 done:
1412         return (error);
1413 }
1414
1415 static uint8_t
1416 ugen_fifo_in_use(struct usb_fifo *f, int fflags)
1417 {
1418         struct usb_fifo *f_rx;
1419         struct usb_fifo *f_tx;
1420
1421         f_rx = f->udev->fifo[(f->fifo_index & ~1) + USB_FIFO_RX];
1422         f_tx = f->udev->fifo[(f->fifo_index & ~1) + USB_FIFO_TX];
1423
1424         if ((fflags & FREAD) && f_rx &&
1425             (f_rx->xfer[0] || f_rx->xfer[1])) {
1426                 return (1);             /* RX FIFO in use */
1427         }
1428         if ((fflags & FWRITE) && f_tx &&
1429             (f_tx->xfer[0] || f_tx->xfer[1])) {
1430                 return (1);             /* TX FIFO in use */
1431         }
1432         return (0);                     /* not in use */
1433 }
1434
1435 static int
1436 ugen_ioctl(struct usb_fifo *f, u_long cmd, void *addr, int fflags)
1437 {
1438         struct usb_config usb_config[1];
1439         struct usb_device_request req;
1440         union {
1441                 struct usb_fs_complete *pcomp;
1442                 struct usb_fs_start *pstart;
1443                 struct usb_fs_stop *pstop;
1444                 struct usb_fs_open *popen;
1445                 struct usb_fs_open_stream *popen_stream;
1446                 struct usb_fs_close *pclose;
1447                 struct usb_fs_clear_stall_sync *pstall;
1448                 void   *addr;
1449         }     u;
1450         struct usb_endpoint *ep;
1451         struct usb_endpoint_descriptor *ed;
1452         struct usb_xfer *xfer;
1453         int error = 0;
1454         uint8_t iface_index;
1455         uint8_t isread;
1456         uint8_t ep_index;
1457         uint8_t pre_scale;
1458
1459         u.addr = addr;
1460
1461         DPRINTFN(6, "cmd=0x%08lx\n", cmd);
1462
1463         switch (cmd) {
1464         case USB_FS_COMPLETE:
1465                 mtx_lock(f->priv_mtx);
1466                 error = ugen_fs_get_complete(f, &ep_index);
1467                 mtx_unlock(f->priv_mtx);
1468
1469                 if (error) {
1470                         error = EBUSY;
1471                         break;
1472                 }
1473                 u.pcomp->ep_index = ep_index;
1474                 error = ugen_fs_copy_out(f, u.pcomp->ep_index);
1475                 break;
1476
1477         case USB_FS_START:
1478                 error = ugen_fs_copy_in(f, u.pstart->ep_index);
1479                 if (error)
1480                         break;
1481                 mtx_lock(f->priv_mtx);
1482                 xfer = f->fs_xfer[u.pstart->ep_index];
1483                 usbd_transfer_start(xfer);
1484                 mtx_unlock(f->priv_mtx);
1485                 break;
1486
1487         case USB_FS_STOP:
1488                 if (u.pstop->ep_index >= f->fs_ep_max) {
1489                         error = EINVAL;
1490                         break;
1491                 }
1492                 mtx_lock(f->priv_mtx);
1493                 xfer = f->fs_xfer[u.pstart->ep_index];
1494                 if (usbd_transfer_pending(xfer)) {
1495                         usbd_transfer_stop(xfer);
1496
1497                         /*
1498                          * Check if the USB transfer was stopped
1499                          * before it was even started and fake a
1500                          * cancel event.
1501                          */
1502                         if (!xfer->flags_int.transferring &&
1503                             !xfer->flags_int.started) {
1504                                 DPRINTF("Issuing fake completion event\n");
1505                                 ugen_fs_set_complete(xfer->priv_sc,
1506                                     USB_P2U(xfer->priv_fifo));
1507                         }
1508                 }
1509                 mtx_unlock(f->priv_mtx);
1510                 break;
1511
1512         case USB_FS_OPEN:
1513         case USB_FS_OPEN_STREAM:
1514                 if (u.popen->ep_index >= f->fs_ep_max) {
1515                         error = EINVAL;
1516                         break;
1517                 }
1518                 if (f->fs_xfer[u.popen->ep_index] != NULL) {
1519                         error = EBUSY;
1520                         break;
1521                 }
1522                 if (u.popen->max_bufsize > USB_FS_MAX_BUFSIZE) {
1523                         u.popen->max_bufsize = USB_FS_MAX_BUFSIZE;
1524                 }
1525                 if (u.popen->max_frames & USB_FS_MAX_FRAMES_PRE_SCALE) {
1526                         pre_scale = 1;
1527                         u.popen->max_frames &= ~USB_FS_MAX_FRAMES_PRE_SCALE;
1528                 } else {
1529                         pre_scale = 0;
1530                 }
1531                 if (u.popen->max_frames > USB_FS_MAX_FRAMES) {
1532                         u.popen->max_frames = USB_FS_MAX_FRAMES;
1533                         break;
1534                 }
1535                 if (u.popen->max_frames == 0) {
1536                         error = EINVAL;
1537                         break;
1538                 }
1539                 ep = usbd_get_ep_by_addr(f->udev, u.popen->ep_no);
1540                 if (ep == NULL) {
1541                         error = EINVAL;
1542                         break;
1543                 }
1544                 ed = ep->edesc;
1545                 if (ed == NULL) {
1546                         error = ENXIO;
1547                         break;
1548                 }
1549                 iface_index = ep->iface_index;
1550
1551                 memset(usb_config, 0, sizeof(usb_config));
1552
1553                 usb_config[0].type = ed->bmAttributes & UE_XFERTYPE;
1554                 usb_config[0].endpoint = ed->bEndpointAddress & UE_ADDR;
1555                 usb_config[0].direction = ed->bEndpointAddress & (UE_DIR_OUT | UE_DIR_IN);
1556                 usb_config[0].interval = USB_DEFAULT_INTERVAL;
1557                 usb_config[0].flags.proxy_buffer = 1;
1558                 if (pre_scale != 0)
1559                         usb_config[0].flags.pre_scale_frames = 1;
1560                 usb_config[0].callback = &ugen_ctrl_fs_callback;
1561                 usb_config[0].timeout = 0;      /* no timeout */
1562                 usb_config[0].frames = u.popen->max_frames;
1563                 usb_config[0].bufsize = u.popen->max_bufsize;
1564                 usb_config[0].usb_mode = USB_MODE_DUAL; /* both modes */
1565                 if (cmd == USB_FS_OPEN_STREAM)
1566                         usb_config[0].stream_id = u.popen_stream->stream_id;
1567
1568                 if (usb_config[0].type == UE_CONTROL) {
1569                         if (f->udev->flags.usb_mode != USB_MODE_HOST) {
1570                                 error = EINVAL;
1571                                 break;
1572                         }
1573                 } else {
1574
1575                         isread = ((usb_config[0].endpoint &
1576                             (UE_DIR_IN | UE_DIR_OUT)) == UE_DIR_IN);
1577
1578                         if (f->udev->flags.usb_mode != USB_MODE_HOST) {
1579                                 isread = !isread;
1580                         }
1581                         /* check permissions */
1582                         if (isread) {
1583                                 if (!(fflags & FREAD)) {
1584                                         error = EPERM;
1585                                         break;
1586                                 }
1587                         } else {
1588                                 if (!(fflags & FWRITE)) {
1589                                         error = EPERM;
1590                                         break;
1591                                 }
1592                         }
1593                 }
1594                 error = usbd_transfer_setup(f->udev, &iface_index,
1595                     f->fs_xfer + u.popen->ep_index, usb_config, 1,
1596                     f, f->priv_mtx);
1597                 if (error == 0) {
1598                         /* update maximums */
1599                         u.popen->max_packet_length =
1600                             f->fs_xfer[u.popen->ep_index]->max_frame_size;
1601                         u.popen->max_bufsize =
1602                             f->fs_xfer[u.popen->ep_index]->max_data_length;
1603                         /* update number of frames */
1604                         u.popen->max_frames =
1605                             f->fs_xfer[u.popen->ep_index]->nframes;
1606                         /* store index of endpoint */
1607                         f->fs_xfer[u.popen->ep_index]->priv_fifo =
1608                             ((uint8_t *)0) + u.popen->ep_index;
1609                 } else {
1610                         error = ENOMEM;
1611                 }
1612                 break;
1613
1614         case USB_FS_CLOSE:
1615                 if (u.pclose->ep_index >= f->fs_ep_max) {
1616                         error = EINVAL;
1617                         break;
1618                 }
1619                 if (f->fs_xfer[u.pclose->ep_index] == NULL) {
1620                         error = EINVAL;
1621                         break;
1622                 }
1623                 usbd_transfer_unsetup(f->fs_xfer + u.pclose->ep_index, 1);
1624                 break;
1625
1626         case USB_FS_CLEAR_STALL_SYNC:
1627                 if (u.pstall->ep_index >= f->fs_ep_max) {
1628                         error = EINVAL;
1629                         break;
1630                 }
1631                 if (f->fs_xfer[u.pstall->ep_index] == NULL) {
1632                         error = EINVAL;
1633                         break;
1634                 }
1635                 if (f->udev->flags.usb_mode != USB_MODE_HOST) {
1636                         error = EINVAL;
1637                         break;
1638                 }
1639                 mtx_lock(f->priv_mtx);
1640                 error = usbd_transfer_pending(f->fs_xfer[u.pstall->ep_index]);
1641                 mtx_unlock(f->priv_mtx);
1642
1643                 if (error) {
1644                         return (EBUSY);
1645                 }
1646                 ep = f->fs_xfer[u.pstall->ep_index]->endpoint;
1647
1648                 /* setup a clear-stall packet */
1649                 req.bmRequestType = UT_WRITE_ENDPOINT;
1650                 req.bRequest = UR_CLEAR_FEATURE;
1651                 USETW(req.wValue, UF_ENDPOINT_HALT);
1652                 req.wIndex[0] = ep->edesc->bEndpointAddress;
1653                 req.wIndex[1] = 0;
1654                 USETW(req.wLength, 0);
1655
1656                 error = usbd_do_request(f->udev, NULL, &req, NULL);
1657                 if (error == 0) {
1658                         usbd_clear_data_toggle(f->udev, ep);
1659                 } else {
1660                         error = ENXIO;
1661                 }
1662                 break;
1663
1664         default:
1665                 error = ENOIOCTL;
1666                 break;
1667         }
1668
1669         DPRINTFN(6, "error=%d\n", error);
1670
1671         return (error);
1672 }
1673
1674 static int
1675 ugen_set_short_xfer(struct usb_fifo *f, void *addr)
1676 {
1677         uint8_t t;
1678
1679         if (*(int *)addr)
1680                 t = 1;
1681         else
1682                 t = 0;
1683
1684         if (f->flag_short == t) {
1685                 /* same value like before - accept */
1686                 return (0);
1687         }
1688         if (f->xfer[0] || f->xfer[1]) {
1689                 /* cannot change this during transfer */
1690                 return (EBUSY);
1691         }
1692         f->flag_short = t;
1693         return (0);
1694 }
1695
1696 static int
1697 ugen_set_timeout(struct usb_fifo *f, void *addr)
1698 {
1699         f->timeout = *(int *)addr;
1700         if (f->timeout > 65535) {
1701                 /* limit user input */
1702                 f->timeout = 65535;
1703         }
1704         return (0);
1705 }
1706
1707 static int
1708 ugen_get_frame_size(struct usb_fifo *f, void *addr)
1709 {
1710         if (f->xfer[0]) {
1711                 *(int *)addr = f->xfer[0]->max_frame_size;
1712         } else {
1713                 return (EINVAL);
1714         }
1715         return (0);
1716 }
1717
1718 static int
1719 ugen_set_buffer_size(struct usb_fifo *f, void *addr)
1720 {
1721         usb_frlength_t t;
1722
1723         if (*(int *)addr < 0)
1724                 t = 0;          /* use "wMaxPacketSize" */
1725         else if (*(int *)addr < (256 * 1024))
1726                 t = *(int *)addr;
1727         else
1728                 t = 256 * 1024;
1729
1730         if (f->bufsize == t) {
1731                 /* same value like before - accept */
1732                 return (0);
1733         }
1734         if (f->xfer[0] || f->xfer[1]) {
1735                 /* cannot change this during transfer */
1736                 return (EBUSY);
1737         }
1738         f->bufsize = t;
1739         return (0);
1740 }
1741
1742 static int
1743 ugen_get_buffer_size(struct usb_fifo *f, void *addr)
1744 {
1745         *(int *)addr = f->bufsize;
1746         return (0);
1747 }
1748
1749 static int
1750 ugen_get_iface_desc(struct usb_fifo *f,
1751     struct usb_interface_descriptor *idesc)
1752 {
1753         struct usb_interface *iface;
1754
1755         iface = usbd_get_iface(f->udev, f->iface_index);
1756         if (iface && iface->idesc) {
1757                 *idesc = *(iface->idesc);
1758         } else {
1759                 return (EIO);
1760         }
1761         return (0);
1762 }
1763
1764 static int
1765 ugen_get_endpoint_desc(struct usb_fifo *f,
1766     struct usb_endpoint_descriptor *ed)
1767 {
1768         struct usb_endpoint *ep;
1769
1770         ep = usb_fifo_softc(f);
1771
1772         if (ep && ep->edesc) {
1773                 *ed = *ep->edesc;
1774         } else {
1775                 return (EINVAL);
1776         }
1777         return (0);
1778 }
1779
1780 static int
1781 ugen_set_power_mode(struct usb_fifo *f, int mode)
1782 {
1783         struct usb_device *udev = f->udev;
1784         int err;
1785         uint8_t old_mode;
1786
1787         if ((udev == NULL) ||
1788             (udev->parent_hub == NULL)) {
1789                 return (EINVAL);
1790         }
1791         err = priv_check(curthread, PRIV_DRIVER);
1792         if (err)
1793                 return (err);
1794
1795         /* get old power mode */
1796         old_mode = udev->power_mode;
1797
1798         /* if no change, then just return */
1799         if (old_mode == mode)
1800                 return (0);
1801
1802         switch (mode) {
1803         case USB_POWER_MODE_OFF:
1804                 if (udev->flags.usb_mode == USB_MODE_HOST &&
1805                     udev->re_enumerate_wait == USB_RE_ENUM_DONE) {
1806                         udev->re_enumerate_wait = USB_RE_ENUM_PWR_OFF;
1807                 }
1808                 /* set power mode will wake up the explore thread */
1809                 break;
1810
1811         case USB_POWER_MODE_ON:
1812         case USB_POWER_MODE_SAVE:
1813                 break;
1814
1815         case USB_POWER_MODE_RESUME:
1816 #if USB_HAVE_POWERD
1817                 /* let USB-powerd handle resume */
1818                 USB_BUS_LOCK(udev->bus);
1819                 udev->pwr_save.write_refs++;
1820                 udev->pwr_save.last_xfer_time = ticks;
1821                 USB_BUS_UNLOCK(udev->bus);
1822
1823                 /* set new power mode */
1824                 usbd_set_power_mode(udev, USB_POWER_MODE_SAVE);
1825
1826                 /* wait for resume to complete */
1827                 usb_pause_mtx(NULL, hz / 4);
1828
1829                 /* clear write reference */
1830                 USB_BUS_LOCK(udev->bus);
1831                 udev->pwr_save.write_refs--;
1832                 USB_BUS_UNLOCK(udev->bus);
1833 #endif
1834                 mode = USB_POWER_MODE_SAVE;
1835                 break;
1836
1837         case USB_POWER_MODE_SUSPEND:
1838 #if USB_HAVE_POWERD
1839                 /* let USB-powerd handle suspend */
1840                 USB_BUS_LOCK(udev->bus);
1841                 udev->pwr_save.last_xfer_time = ticks - (256 * hz);
1842                 USB_BUS_UNLOCK(udev->bus);
1843 #endif
1844                 mode = USB_POWER_MODE_SAVE;
1845                 break;
1846
1847         default:
1848                 return (EINVAL);
1849         }
1850
1851         if (err)
1852                 return (ENXIO);         /* I/O failure */
1853
1854         /* if we are powered off we need to re-enumerate first */
1855         if (old_mode == USB_POWER_MODE_OFF) {
1856                 if (udev->flags.usb_mode == USB_MODE_HOST &&
1857                     udev->re_enumerate_wait == USB_RE_ENUM_DONE) {
1858                         udev->re_enumerate_wait = USB_RE_ENUM_START;
1859                 }
1860                 /* set power mode will wake up the explore thread */
1861         }
1862
1863         /* set new power mode */
1864         usbd_set_power_mode(udev, mode);
1865
1866         return (0);                     /* success */
1867 }
1868
1869 static int
1870 ugen_get_power_mode(struct usb_fifo *f)
1871 {
1872         struct usb_device *udev = f->udev;
1873
1874         if (udev == NULL)
1875                 return (USB_POWER_MODE_ON);
1876
1877         return (udev->power_mode);
1878 }
1879
1880 static int
1881 ugen_get_port_path(struct usb_fifo *f, struct usb_device_port_path *dpp)
1882 {
1883         struct usb_device *udev = f->udev;
1884         struct usb_device *next;
1885         unsigned int nlevel = 0;
1886
1887         if (udev == NULL)
1888                 goto error;
1889
1890         dpp->udp_bus = device_get_unit(udev->bus->bdev);
1891         dpp->udp_index = udev->device_index;
1892
1893         /* count port levels */
1894         next = udev;
1895         while (next->parent_hub != NULL) {
1896                 nlevel++;
1897                 next = next->parent_hub;
1898         }
1899
1900         /* check if too many levels */
1901         if (nlevel > USB_DEVICE_PORT_PATH_MAX)
1902                 goto error;
1903
1904         /* store total level of ports */
1905         dpp->udp_port_level = nlevel;
1906
1907         /* store port index array */
1908         next = udev;
1909         while (next->parent_hub != NULL) {
1910                 dpp->udp_port_no[--nlevel] = next->port_no;
1911                 next = next->parent_hub;
1912         }
1913         return (0);     /* success */
1914
1915 error:
1916         return (EINVAL);        /* failure */
1917 }
1918
1919 static int
1920 ugen_get_power_usage(struct usb_fifo *f)
1921 {
1922         struct usb_device *udev = f->udev;
1923
1924         if (udev == NULL)
1925                 return (0);
1926
1927         return (udev->power);
1928 }
1929
1930 static int
1931 ugen_do_port_feature(struct usb_fifo *f, uint8_t port_no,
1932     uint8_t set, uint16_t feature)
1933 {
1934         struct usb_device *udev = f->udev;
1935         struct usb_hub *hub;
1936         int err;
1937
1938         err = priv_check(curthread, PRIV_DRIVER);
1939         if (err) {
1940                 return (err);
1941         }
1942         if (port_no == 0) {
1943                 return (EINVAL);
1944         }
1945         if ((udev == NULL) ||
1946             (udev->hub == NULL)) {
1947                 return (EINVAL);
1948         }
1949         hub = udev->hub;
1950
1951         if (port_no > hub->nports) {
1952                 return (EINVAL);
1953         }
1954         if (set)
1955                 err = usbd_req_set_port_feature(udev,
1956                     NULL, port_no, feature);
1957         else
1958                 err = usbd_req_clear_port_feature(udev,
1959                     NULL, port_no, feature);
1960
1961         if (err)
1962                 return (ENXIO);         /* failure */
1963
1964         return (0);                     /* success */
1965 }
1966
1967 static int
1968 ugen_iface_ioctl(struct usb_fifo *f, u_long cmd, void *addr, int fflags)
1969 {
1970         struct usb_fifo *f_rx;
1971         struct usb_fifo *f_tx;
1972         int error = 0;
1973
1974         f_rx = f->udev->fifo[(f->fifo_index & ~1) + USB_FIFO_RX];
1975         f_tx = f->udev->fifo[(f->fifo_index & ~1) + USB_FIFO_TX];
1976
1977         switch (cmd) {
1978         case USB_SET_RX_SHORT_XFER:
1979                 if (fflags & FREAD) {
1980                         error = ugen_set_short_xfer(f_rx, addr);
1981                 } else {
1982                         error = EINVAL;
1983                 }
1984                 break;
1985
1986         case USB_SET_TX_FORCE_SHORT:
1987                 if (fflags & FWRITE) {
1988                         error = ugen_set_short_xfer(f_tx, addr);
1989                 } else {
1990                         error = EINVAL;
1991                 }
1992                 break;
1993
1994         case USB_SET_RX_TIMEOUT:
1995                 if (fflags & FREAD) {
1996                         error = ugen_set_timeout(f_rx, addr);
1997                 } else {
1998                         error = EINVAL;
1999                 }
2000                 break;
2001
2002         case USB_SET_TX_TIMEOUT:
2003                 if (fflags & FWRITE) {
2004                         error = ugen_set_timeout(f_tx, addr);
2005                 } else {
2006                         error = EINVAL;
2007                 }
2008                 break;
2009
2010         case USB_GET_RX_FRAME_SIZE:
2011                 if (fflags & FREAD) {
2012                         error = ugen_get_frame_size(f_rx, addr);
2013                 } else {
2014                         error = EINVAL;
2015                 }
2016                 break;
2017
2018         case USB_GET_TX_FRAME_SIZE:
2019                 if (fflags & FWRITE) {
2020                         error = ugen_get_frame_size(f_tx, addr);
2021                 } else {
2022                         error = EINVAL;
2023                 }
2024                 break;
2025
2026         case USB_SET_RX_BUFFER_SIZE:
2027                 if (fflags & FREAD) {
2028                         error = ugen_set_buffer_size(f_rx, addr);
2029                 } else {
2030                         error = EINVAL;
2031                 }
2032                 break;
2033
2034         case USB_SET_TX_BUFFER_SIZE:
2035                 if (fflags & FWRITE) {
2036                         error = ugen_set_buffer_size(f_tx, addr);
2037                 } else {
2038                         error = EINVAL;
2039                 }
2040                 break;
2041
2042         case USB_GET_RX_BUFFER_SIZE:
2043                 if (fflags & FREAD) {
2044                         error = ugen_get_buffer_size(f_rx, addr);
2045                 } else {
2046                         error = EINVAL;
2047                 }
2048                 break;
2049
2050         case USB_GET_TX_BUFFER_SIZE:
2051                 if (fflags & FWRITE) {
2052                         error = ugen_get_buffer_size(f_tx, addr);
2053                 } else {
2054                         error = EINVAL;
2055                 }
2056                 break;
2057
2058         case USB_GET_RX_INTERFACE_DESC:
2059                 if (fflags & FREAD) {
2060                         error = ugen_get_iface_desc(f_rx, addr);
2061                 } else {
2062                         error = EINVAL;
2063                 }
2064                 break;
2065
2066         case USB_GET_TX_INTERFACE_DESC:
2067                 if (fflags & FWRITE) {
2068                         error = ugen_get_iface_desc(f_tx, addr);
2069                 } else {
2070                         error = EINVAL;
2071                 }
2072                 break;
2073
2074         case USB_GET_RX_ENDPOINT_DESC:
2075                 if (fflags & FREAD) {
2076                         error = ugen_get_endpoint_desc(f_rx, addr);
2077                 } else {
2078                         error = EINVAL;
2079                 }
2080                 break;
2081
2082         case USB_GET_TX_ENDPOINT_DESC:
2083                 if (fflags & FWRITE) {
2084                         error = ugen_get_endpoint_desc(f_tx, addr);
2085                 } else {
2086                         error = EINVAL;
2087                 }
2088                 break;
2089
2090         case USB_SET_RX_STALL_FLAG:
2091                 if ((fflags & FREAD) && (*(int *)addr)) {
2092                         f_rx->flag_stall = 1;
2093                 }
2094                 break;
2095
2096         case USB_SET_TX_STALL_FLAG:
2097                 if ((fflags & FWRITE) && (*(int *)addr)) {
2098                         f_tx->flag_stall = 1;
2099                 }
2100                 break;
2101
2102         default:
2103                 error = ENOIOCTL;
2104                 break;
2105         }
2106         return (error);
2107 }
2108
2109 static int
2110 ugen_ioctl_post(struct usb_fifo *f, u_long cmd, void *addr, int fflags)
2111 {
2112         union {
2113                 struct usb_interface_descriptor *idesc;
2114                 struct usb_alt_interface *ai;
2115                 struct usb_device_descriptor *ddesc;
2116                 struct usb_config_descriptor *cdesc;
2117                 struct usb_device_stats *stat;
2118                 struct usb_fs_init *pinit;
2119                 struct usb_fs_uninit *puninit;
2120                 struct usb_device_port_path *dpp;
2121                 uint32_t *ptime;
2122                 void   *addr;
2123                 int    *pint;
2124         }     u;
2125         struct usb_device_descriptor *dtemp;
2126         struct usb_config_descriptor *ctemp;
2127         struct usb_interface *iface;
2128         int error = 0;
2129         uint8_t n;
2130
2131         u.addr = addr;
2132
2133         DPRINTFN(6, "cmd=0x%08lx\n", cmd);
2134
2135         switch (cmd) {
2136         case USB_DISCOVER:
2137                 usb_needs_explore_all();
2138                 break;
2139
2140         case USB_SETDEBUG:
2141                 if (!(fflags & FWRITE)) {
2142                         error = EPERM;
2143                         break;
2144                 }
2145                 usb_debug = *(int *)addr;
2146                 break;
2147
2148         case USB_GET_CONFIG:
2149                 *(int *)addr = f->udev->curr_config_index;
2150                 break;
2151
2152         case USB_SET_CONFIG:
2153                 if (!(fflags & FWRITE)) {
2154                         error = EPERM;
2155                         break;
2156                 }
2157                 error = ugen_set_config(f, *(int *)addr);
2158                 break;
2159
2160         case USB_GET_ALTINTERFACE:
2161                 iface = usbd_get_iface(f->udev,
2162                     u.ai->uai_interface_index);
2163                 if (iface && iface->idesc) {
2164                         u.ai->uai_alt_index = iface->alt_index;
2165                 } else {
2166                         error = EINVAL;
2167                 }
2168                 break;
2169
2170         case USB_SET_ALTINTERFACE:
2171                 if (!(fflags & FWRITE)) {
2172                         error = EPERM;
2173                         break;
2174                 }
2175                 error = ugen_set_interface(f,
2176                     u.ai->uai_interface_index, u.ai->uai_alt_index);
2177                 break;
2178
2179         case USB_GET_DEVICE_DESC:
2180                 dtemp = usbd_get_device_descriptor(f->udev);
2181                 if (!dtemp) {
2182                         error = EIO;
2183                         break;
2184                 }
2185                 *u.ddesc = *dtemp;
2186                 break;
2187
2188         case USB_GET_CONFIG_DESC:
2189                 ctemp = usbd_get_config_descriptor(f->udev);
2190                 if (!ctemp) {
2191                         error = EIO;
2192                         break;
2193                 }
2194                 *u.cdesc = *ctemp;
2195                 break;
2196
2197         case USB_GET_FULL_DESC:
2198                 error = ugen_get_cdesc(f, addr);
2199                 break;
2200
2201         case USB_GET_STRING_DESC:
2202                 error = ugen_get_sdesc(f, addr);
2203                 break;
2204
2205         case USB_GET_IFACE_DRIVER:
2206                 error = ugen_get_iface_driver(f, addr);
2207                 break;
2208
2209         case USB_REQUEST:
2210         case USB_DO_REQUEST:
2211                 if (!(fflags & FWRITE)) {
2212                         error = EPERM;
2213                         break;
2214                 }
2215                 error = ugen_do_request(f, addr);
2216                 break;
2217
2218         case USB_DEVICEINFO:
2219         case USB_GET_DEVICEINFO:
2220                 error = usb_gen_fill_deviceinfo(f, addr);
2221                 break;
2222
2223         case USB_DEVICESTATS:
2224                 for (n = 0; n != 4; n++) {
2225
2226                         u.stat->uds_requests_fail[n] =
2227                             f->udev->stats_err.uds_requests[n];
2228                         u.stat->uds_requests_ok[n] =
2229                             f->udev->stats_ok.uds_requests[n];
2230                 }
2231                 break;
2232
2233         case USB_DEVICEENUMERATE:
2234                 error = ugen_re_enumerate(f);
2235                 break;
2236
2237         case USB_GET_PLUGTIME:
2238                 *u.ptime = f->udev->plugtime;
2239                 break;
2240
2241         case USB_CLAIM_INTERFACE:
2242         case USB_RELEASE_INTERFACE:
2243                 /* TODO */
2244                 break;
2245
2246         case USB_IFACE_DRIVER_ACTIVE:
2247
2248                 n = *u.pint & 0xFF;
2249
2250                 iface = usbd_get_iface(f->udev, n);
2251
2252                 if (iface && iface->subdev)
2253                         error = 0;
2254                 else
2255                         error = ENXIO;
2256                 break;
2257
2258         case USB_IFACE_DRIVER_DETACH:
2259
2260                 error = priv_check(curthread, PRIV_DRIVER);
2261
2262                 if (error)
2263                         break;
2264
2265                 n = *u.pint & 0xFF;
2266
2267                 if (n == USB_IFACE_INDEX_ANY) {
2268                         error = EINVAL;
2269                         break;
2270                 }
2271
2272                 /*
2273                  * Detach the currently attached driver.
2274                  */
2275                 usb_detach_device(f->udev, n, 0);
2276
2277                 /*
2278                  * Set parent to self, this should keep attach away
2279                  * until the next set configuration event.
2280                  */
2281                 usbd_set_parent_iface(f->udev, n, n);
2282                 break;
2283
2284         case USB_SET_POWER_MODE:
2285                 error = ugen_set_power_mode(f, *u.pint);
2286                 break;
2287
2288         case USB_GET_POWER_MODE:
2289                 *u.pint = ugen_get_power_mode(f);
2290                 break;
2291
2292         case USB_GET_DEV_PORT_PATH:
2293                 error = ugen_get_port_path(f, u.dpp);
2294                 break;
2295
2296         case USB_GET_POWER_USAGE:
2297                 *u.pint = ugen_get_power_usage(f);
2298                 break;
2299
2300         case USB_SET_PORT_ENABLE:
2301                 error = ugen_do_port_feature(f,
2302                     *u.pint, 1, UHF_PORT_ENABLE);
2303                 break;
2304
2305         case USB_SET_PORT_DISABLE:
2306                 error = ugen_do_port_feature(f,
2307                     *u.pint, 0, UHF_PORT_ENABLE);
2308                 break;
2309
2310         case USB_FS_INIT:
2311                 /* verify input parameters */
2312                 if (u.pinit->pEndpoints == NULL) {
2313                         error = EINVAL;
2314                         break;
2315                 }
2316                 if (u.pinit->ep_index_max > 127) {
2317                         error = EINVAL;
2318                         break;
2319                 }
2320                 if (u.pinit->ep_index_max == 0) {
2321                         error = EINVAL;
2322                         break;
2323                 }
2324                 if (f->fs_xfer != NULL) {
2325                         error = EBUSY;
2326                         break;
2327                 }
2328                 if (f->dev_ep_index != 0) {
2329                         error = EINVAL;
2330                         break;
2331                 }
2332                 if (ugen_fifo_in_use(f, fflags)) {
2333                         error = EBUSY;
2334                         break;
2335                 }
2336                 error = usb_fifo_alloc_buffer(f, 1, u.pinit->ep_index_max);
2337                 if (error) {
2338                         break;
2339                 }
2340                 f->fs_xfer = malloc(sizeof(f->fs_xfer[0]) *
2341                     u.pinit->ep_index_max, M_USB, M_WAITOK | M_ZERO);
2342                 if (f->fs_xfer == NULL) {
2343                         usb_fifo_free_buffer(f);
2344                         error = ENOMEM;
2345                         break;
2346                 }
2347                 f->fs_ep_max = u.pinit->ep_index_max;
2348                 f->fs_ep_ptr = u.pinit->pEndpoints;
2349                 break;
2350
2351         case USB_FS_UNINIT:
2352                 if (u.puninit->dummy != 0) {
2353                         error = EINVAL;
2354                         break;
2355                 }
2356                 error = ugen_fs_uninit(f);
2357                 break;
2358
2359         default:
2360                 mtx_lock(f->priv_mtx);
2361                 error = ugen_iface_ioctl(f, cmd, addr, fflags);
2362                 mtx_unlock(f->priv_mtx);
2363                 break;
2364         }
2365         DPRINTFN(6, "error=%d\n", error);
2366         return (error);
2367 }
2368
2369 static void
2370 ugen_ctrl_fs_callback(struct usb_xfer *xfer, usb_error_t error)
2371 {
2372         ;                               /* workaround for a bug in "indent" */
2373
2374         DPRINTF("st=%u alen=%u aframes=%u\n",
2375             USB_GET_STATE(xfer), xfer->actlen, xfer->aframes);
2376
2377         switch (USB_GET_STATE(xfer)) {
2378         case USB_ST_SETUP:
2379                 usbd_transfer_submit(xfer);
2380                 break;
2381         default:
2382                 ugen_fs_set_complete(xfer->priv_sc, USB_P2U(xfer->priv_fifo));
2383                 break;
2384         }
2385 }
2386 #endif  /* USB_HAVE_UGEN */