FreeBSD kernel usb device Code
urio.c
Go to the documentation of this file.
1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2000 Iwasa Kazmi
5 * 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 FOR
20 * 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 * This code is based on ugen.c and ulpt.c developed by Lennart Augustsson.
29 * This code includes software developed by the NetBSD Foundation, Inc. and
30 * its contributors.
31 */
32
33#include <sys/cdefs.h>
34__FBSDID("$FreeBSD$");
35
36/*
37 * 2000/3/24 added NetBSD/OpenBSD support (from Alex Nemirovsky)
38 * 2000/3/07 use two bulk-pipe handles for read and write (Dirk)
39 * 2000/3/06 change major number(143), and copyright header
40 * some fix for 4.0 (Dirk)
41 * 2000/3/05 codes for FreeBSD 4.x - CURRENT (Thanks to Dirk-Willem van Gulik)
42 * 2000/3/01 remove retry code from urioioctl()
43 * change method of bulk transfer (no interrupt)
44 * 2000/2/28 small fixes for new rio_usb.h
45 * 2000/2/24 first version.
46 */
47
48#include <sys/stdint.h>
49#include <sys/stddef.h>
50#include <sys/param.h>
51#include <sys/queue.h>
52#include <sys/types.h>
53#include <sys/systm.h>
54#include <sys/kernel.h>
55#include <sys/bus.h>
56#include <sys/module.h>
57#include <sys/lock.h>
58#include <sys/mutex.h>
59#include <sys/condvar.h>
60#include <sys/sysctl.h>
61#include <sys/sx.h>
62#include <sys/unistd.h>
63#include <sys/callout.h>
64#include <sys/malloc.h>
65#include <sys/priv.h>
66#include <sys/conf.h>
67#include <sys/fcntl.h>
68
69#include <dev/usb/usb.h>
70#include <dev/usb/usbdi.h>
71#include "usbdevs.h"
72
73#include <dev/usb/usb_ioctl.h>
74#include <dev/usb/usb_generic.h>
75
76#define USB_DEBUG_VAR urio_debug
77#include <dev/usb/usb_debug.h>
78
80
81#ifdef USB_DEBUG
82static int urio_debug = 0;
83
84static SYSCTL_NODE(_hw_usb, OID_AUTO, urio, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
85 "USB urio");
86SYSCTL_INT(_hw_usb_urio, OID_AUTO, debug, CTLFLAG_RWTUN,
87 &urio_debug, 0, "urio debug level");
88#endif
89
90#define URIO_T_WR 0
91#define URIO_T_RD 1
92#define URIO_T_WR_CS 2
93#define URIO_T_RD_CS 3
94#define URIO_T_MAX 4
95
96#define URIO_BSIZE (1<<12) /* bytes */
97#define URIO_IFQ_MAXLEN 2 /* units */
98
99struct urio_softc {
101 struct mtx sc_mtx;
102
105
106 uint8_t sc_flags;
107#define URIO_FLAG_READ_STALL 0x01 /* read transfer stalled */
108#define URIO_FLAG_WRITE_STALL 0x02 /* write transfer stalled */
109
110 uint8_t sc_name[16];
111};
112
113/* prototypes */
114
115static device_probe_t urio_probe;
116static device_attach_t urio_attach;
117static device_detach_t urio_detach;
118
123
131
134 .f_ioctl = &urio_ioctl,
135 .f_open = &urio_open,
136 .f_start_read = &urio_start_read,
137 .f_start_write = &urio_start_write,
138 .f_stop_read = &urio_stop_read,
139 .f_stop_write = &urio_stop_write,
140 .basename[0] = "urio",
141};
142
143static const struct usb_config urio_config[URIO_T_MAX] = {
144 [URIO_T_WR] = {
145 .type = UE_BULK,
146 .endpoint = UE_ADDR_ANY,
147 .direction = UE_DIR_OUT,
148 .bufsize = URIO_BSIZE,
149 .flags = {.pipe_bof = 1,.force_short_xfer = 1,.proxy_buffer = 1,},
150 .callback = &urio_write_callback,
151 },
152
153 [URIO_T_RD] = {
154 .type = UE_BULK,
155 .endpoint = UE_ADDR_ANY,
156 .direction = UE_DIR_IN,
157 .bufsize = URIO_BSIZE,
158 .flags = {.pipe_bof = 1,.short_xfer_ok = 1,.proxy_buffer = 1,},
159 .callback = &urio_read_callback,
160 },
161
162 [URIO_T_WR_CS] = {
163 .type = UE_CONTROL,
164 .endpoint = 0x00, /* Control pipe */
165 .direction = UE_DIR_ANY,
166 .bufsize = sizeof(struct usb_device_request),
168 .timeout = 1000, /* 1 second */
169 .interval = 50, /* 50ms */
170 },
171
172 [URIO_T_RD_CS] = {
173 .type = UE_CONTROL,
174 .endpoint = 0x00, /* Control pipe */
175 .direction = UE_DIR_ANY,
176 .bufsize = sizeof(struct usb_device_request),
178 .timeout = 1000, /* 1 second */
179 .interval = 50, /* 50ms */
180 },
181};
182
183static devclass_t urio_devclass;
184
185static device_method_t urio_methods[] = {
186 /* Device interface */
187 DEVMETHOD(device_probe, urio_probe),
188 DEVMETHOD(device_attach, urio_attach),
189 DEVMETHOD(device_detach, urio_detach),
190
191 DEVMETHOD_END
192};
193
194static driver_t urio_driver = {
195 .name = "urio",
196 .methods = urio_methods,
197 .size = sizeof(struct urio_softc),
198};
199
202 {USB_VPI(USB_VENDOR_DIAMOND2, USB_PRODUCT_DIAMOND2_RIO600USB, 0)},
203 {USB_VPI(USB_VENDOR_DIAMOND2, USB_PRODUCT_DIAMOND2_RIO800USB, 0)},
204};
205
207MODULE_DEPEND(urio, usb, 1, 1, 1);
210
211static int
212urio_probe(device_t dev)
213{
214 struct usb_attach_arg *uaa = device_get_ivars(dev);
215
216 if (uaa->usb_mode != USB_MODE_HOST)
217 return (ENXIO);
218 if (uaa->info.bConfigIndex != 0)
219 return (ENXIO);
220 if (uaa->info.bIfaceIndex != 0)
221 return (ENXIO);
222
223 return (usbd_lookup_id_by_uaa(urio_devs, sizeof(urio_devs), uaa));
224}
225
226static int
227urio_attach(device_t dev)
228{
229 struct usb_attach_arg *uaa = device_get_ivars(dev);
230 struct urio_softc *sc = device_get_softc(dev);
231 int error;
232
234
235 sc->sc_udev = uaa->device;
236
237 mtx_init(&sc->sc_mtx, "urio lock", NULL, MTX_DEF | MTX_RECURSE);
238
239 snprintf(sc->sc_name, sizeof(sc->sc_name),
240 "%s", device_get_nameunit(dev));
241
243 &uaa->info.bIfaceIndex, sc->sc_xfer,
244 urio_config, URIO_T_MAX, sc, &sc->sc_mtx);
245
246 if (error) {
247 DPRINTF("error=%s\n", usbd_errstr(error));
248 goto detach;
249 }
250
251 error = usb_fifo_attach(uaa->device, sc, &sc->sc_mtx,
253 device_get_unit(dev), -1, uaa->info.bIfaceIndex,
254 UID_ROOT, GID_OPERATOR, 0644);
255 if (error) {
256 goto detach;
257 }
258 return (0); /* success */
259
260detach:
262 return (ENOMEM); /* failure */
263}
264
265static void
267{
268 struct urio_softc *sc = usbd_xfer_softc(xfer);
269 struct usb_fifo *f = sc->sc_fifo.fp[USB_FIFO_TX];
270 struct usb_page_cache *pc;
271 uint32_t actlen;
272
273 switch (USB_GET_STATE(xfer)) {
275 case USB_ST_SETUP:
278 return;
279 }
280 pc = usbd_xfer_get_frame(xfer, 0);
281 if (usb_fifo_get_data(f, pc, 0,
282 usbd_xfer_max_len(xfer), &actlen, 0)) {
283 usbd_xfer_set_frame_len(xfer, 0, actlen);
285 }
286 return;
287
288 default: /* Error */
289 if (error != USB_ERR_CANCELLED) {
290 /* try to clear stall first */
293 }
294 return;
295 }
296}
297
298static void
300{
301 struct urio_softc *sc = usbd_xfer_softc(xfer);
302 struct usb_xfer *xfer_other = sc->sc_xfer[URIO_T_WR];
303
304 if (usbd_clear_stall_callback(xfer, xfer_other)) {
305 DPRINTF("stall cleared\n");
306 sc->sc_flags &= ~URIO_FLAG_WRITE_STALL;
307 usbd_transfer_start(xfer_other);
308 }
309}
310
311static void
313{
314 struct urio_softc *sc = usbd_xfer_softc(xfer);
315 struct usb_fifo *f = sc->sc_fifo.fp[USB_FIFO_RX];
316 struct usb_page_cache *pc;
317 int actlen;
318
319 usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
320
321 switch (USB_GET_STATE(xfer)) {
323 pc = usbd_xfer_get_frame(xfer, 0);
324 usb_fifo_put_data(f, pc, 0, actlen, 1);
325
326 case USB_ST_SETUP:
327 if (sc->sc_flags & URIO_FLAG_READ_STALL) {
329 return;
330 }
331 if (usb_fifo_put_bytes_max(f) != 0) {
334 }
335 return;
336
337 default: /* Error */
338 if (error != USB_ERR_CANCELLED) {
339 /* try to clear stall first */
342 }
343 return;
344 }
345}
346
347static void
349{
350 struct urio_softc *sc = usbd_xfer_softc(xfer);
351 struct usb_xfer *xfer_other = sc->sc_xfer[URIO_T_RD];
352
353 if (usbd_clear_stall_callback(xfer, xfer_other)) {
354 DPRINTF("stall cleared\n");
355 sc->sc_flags &= ~URIO_FLAG_READ_STALL;
356 usbd_transfer_start(xfer_other);
357 }
358}
359
360static void
362{
363 struct urio_softc *sc = usb_fifo_softc(fifo);
364
366}
367
368static void
370{
371 struct urio_softc *sc = usb_fifo_softc(fifo);
372
375}
376
377static void
379{
380 struct urio_softc *sc = usb_fifo_softc(fifo);
381
383}
384
385static void
387{
388 struct urio_softc *sc = usb_fifo_softc(fifo);
389
392}
393
394static int
395urio_open(struct usb_fifo *fifo, int fflags)
396{
397 struct urio_softc *sc = usb_fifo_softc(fifo);
398
399 if (fflags & FREAD) {
400 /* clear stall first */
401 mtx_lock(&sc->sc_mtx);
403 mtx_unlock(&sc->sc_mtx);
404
405 if (usb_fifo_alloc_buffer(fifo,
408 return (ENOMEM);
409 }
410 }
411 if (fflags & FWRITE) {
412 /* clear stall first */
414
415 if (usb_fifo_alloc_buffer(fifo,
418 return (ENOMEM);
419 }
420 }
421 return (0); /* success */
422}
423
424static void
425urio_close(struct usb_fifo *fifo, int fflags)
426{
427 if (fflags & (FREAD | FWRITE)) {
429 }
430}
431
432static int
433urio_ioctl(struct usb_fifo *fifo, u_long cmd, void *addr,
434 int fflags)
435{
436 struct usb_ctl_request ur;
437 struct RioCommand *rio_cmd;
438 int error;
439
440 switch (cmd) {
441 case RIO_RECV_COMMAND:
442 if (!(fflags & FWRITE)) {
443 error = EPERM;
444 goto done;
445 }
446 memset(&ur, 0, sizeof(ur));
447 rio_cmd = addr;
450 break;
451
452 case RIO_SEND_COMMAND:
453 if (!(fflags & FWRITE)) {
454 error = EPERM;
455 goto done;
456 }
457 memset(&ur, 0, sizeof(ur));
458 rio_cmd = addr;
461 break;
462
463 default:
464 error = EINVAL;
465 goto done;
466 }
467
468 DPRINTFN(2, "Sending command\n");
469
470 /* Send rio control message */
471 ur.ucr_request.bRequest = rio_cmd->request;
472 USETW(ur.ucr_request.wValue, rio_cmd->value);
473 USETW(ur.ucr_request.wIndex, rio_cmd->index);
474 USETW(ur.ucr_request.wLength, rio_cmd->length);
475 ur.ucr_data = rio_cmd->buffer;
476
477 /* reuse generic USB code */
478 error = ugen_do_request(fifo, &ur);
479
480done:
481 return (error);
482}
483
484static int
485urio_detach(device_t dev)
486{
487 struct urio_softc *sc = device_get_softc(dev);
488
489 DPRINTF("\n");
490
492
494
495 mtx_destroy(&sc->sc_mtx);
496
497 return (0);
498}
static int debug
Definition: cfumass.c:73
static SYSCTL_NODE(_hw_usb, OID_AUTO, dwc_otg, CTLFLAG_RW|CTLFLAG_MPSAFE, 0, "USB DWC OTG")
SYSCTL_INT(_hw_usb_dwc_otg, OID_AUTO, phy_type, CTLFLAG_RDTUN, &dwc_otg_phy_type, 0, "DWC OTG PHY TYPE - 0/1/2/3 - ULPI/HSIC/INTERNAL/UTMI+")
struct @109 error
device_t dev
uint64_t * addr
#define RIO_RECV_COMMAND
Definition: rio500_usb.h:45
#define USB_PRODUCT_DIAMOND_RIO500USB
Definition: rio500_usb.h:30
#define USB_VENDOR_DIAMOND
Definition: rio500_usb.h:27
#define RIO_SEND_COMMAND
Definition: rio500_usb.h:44
int request
Definition: rio500_usb.h:36
void * buffer
Definition: rio500_usb.h:40
uint16_t length
Definition: rio500_usb.h:35
int requesttype
Definition: rio500_usb.h:37
uint8_t sc_name[16]
Definition: urio.c:110
struct usb_fifo_sc sc_fifo
Definition: urio.c:100
uint8_t sc_flags
Definition: urio.c:106
struct mtx sc_mtx
Definition: urio.c:101
struct usb_xfer * sc_xfer[URIO_T_MAX]
Definition: urio.c:104
struct usb_device * sc_udev
Definition: urio.c:103
enum usb_hc_mode usb_mode
Definition: usbdi.h:432
struct usbd_lookup_info info
Definition: usbdi.h:426
struct usb_device * device
Definition: usbdi.h:430
uint8_t type
Definition: usbdi.h:238
void * ucr_data
Definition: usb_ioctl.h:74
struct usb_device_request ucr_request
Definition: usb_ioctl.h:78
uWord wLength
Definition: usb.h:152
uWord wIndex
Definition: usb.h:151
uWord wValue
Definition: usb.h:150
uByte bRequest
Definition: usb.h:149
uByte bmRequestType
Definition: usb.h:148
usb_fifo_close_t * f_close
Definition: usbdi.h:536
struct usb_fifo * fp[2]
Definition: usbdi.h:554
uint8_t bIfaceIndex
Definition: usbdi.h:417
uint8_t bConfigIndex
Definition: usbdi.h:419
#define DPRINTF(...)
Definition: umass.c:179
#define URIO_FLAG_WRITE_STALL
Definition: urio.c:108
#define URIO_FLAG_READ_STALL
Definition: urio.c:107
static usb_fifo_cmd_t urio_start_write
Definition: urio.c:126
DRIVER_MODULE(urio, uhub, urio_driver, urio_devclass, NULL, 0)
#define URIO_T_RD
Definition: urio.c:91
#define URIO_T_WR
Definition: urio.c:90
static usb_fifo_open_t urio_open
Definition: urio.c:130
#define URIO_T_MAX
Definition: urio.c:94
static devclass_t urio_devclass
Definition: urio.c:183
static device_probe_t urio_probe
Definition: urio.c:115
static usb_fifo_cmd_t urio_stop_read
Definition: urio.c:127
static usb_fifo_ioctl_t urio_ioctl
Definition: urio.c:129
static usb_callback_t urio_write_clear_stall_callback
Definition: urio.c:120
MODULE_VERSION(urio, 1)
static driver_t urio_driver
Definition: urio.c:194
#define URIO_BSIZE
Definition: urio.c:96
static usb_callback_t urio_read_callback
Definition: urio.c:121
__FBSDID("$FreeBSD$")
static device_detach_t urio_detach
Definition: urio.c:117
static const STRUCT_USB_HOST_ID urio_devs[]
Definition: urio.c:200
static const struct usb_config urio_config[URIO_T_MAX]
Definition: urio.c:143
static usb_fifo_cmd_t urio_stop_write
Definition: urio.c:128
static device_attach_t urio_attach
Definition: urio.c:116
#define URIO_IFQ_MAXLEN
Definition: urio.c:97
USB_PNP_HOST_INFO(urio_devs)
static struct usb_fifo_methods urio_fifo_methods
Definition: urio.c:132
MODULE_DEPEND(urio, usb, 1, 1, 1)
static usb_fifo_cmd_t urio_start_read
Definition: urio.c:125
#define URIO_T_RD_CS
Definition: urio.c:93
static usb_fifo_close_t urio_close
Definition: urio.c:124
#define URIO_T_WR_CS
Definition: urio.c:92
static device_method_t urio_methods[]
Definition: urio.c:185
static usb_callback_t urio_read_clear_stall_callback
Definition: urio.c:122
static usb_callback_t urio_write_callback
Definition: urio.c:119
#define UE_DIR_ANY
Definition: usb.h:535
#define UE_ADDR_ANY
Definition: usb.h:537
#define UE_BULK
Definition: usb.h:543
#define UT_WRITE_VENDOR_DEVICE
Definition: usb.h:184
#define UT_READ_VENDOR_DEVICE
Definition: usb.h:180
#define UE_DIR_IN
Definition: usb.h:531
#define UE_DIR_OUT
Definition: usb.h:532
@ USB_MODE_HOST
Definition: usb.h:778
#define UE_CONTROL
Definition: usb.h:541
#define USETW(w, v)
Definition: usb_endian.h:77
const char * usbd_errstr(usb_error_t err)
Definition: usb_error.c:93
int ugen_do_request(struct usb_fifo *f, struct usb_ctl_request *ur)
INTERFACE usb
Definition: usb_if.m:35
int usbd_lookup_id_by_uaa(const struct usb_device_id *id, usb_size_t sizeof_id, struct usb_attach_arg *uaa)
Definition: usb_lookup.c:143
void usbd_transfer_submit(struct usb_xfer *xfer)
void usbd_transfer_unsetup(struct usb_xfer **pxfer, uint16_t n_setup)
void usbd_xfer_set_frame_len(struct usb_xfer *xfer, usb_frcount_t frindex, usb_frlength_t len)
uint8_t usbd_clear_stall_callback(struct usb_xfer *xfer1, struct usb_xfer *xfer2)
struct usb_page_cache * usbd_xfer_get_frame(struct usb_xfer *xfer, usb_frcount_t frindex)
usb_error_t usbd_transfer_setup(struct usb_device *udev, const uint8_t *ifaces, struct usb_xfer **ppxfer, const struct usb_config *setup_start, uint16_t n_setup, void *priv_sc, struct mtx *xfer_mtx)
Definition: usb_transfer.c:987
void usbd_transfer_start(struct usb_xfer *xfer)
void * usbd_xfer_softc(struct usb_xfer *xfer)
void usbd_transfer_stop(struct usb_xfer *xfer)
void usbd_xfer_status(struct usb_xfer *xfer, int *actlen, int *sumlen, int *aframes, int *nframes)
usb_frlength_t usbd_xfer_max_len(struct usb_xfer *xfer)
void device_set_usb_desc(device_t dev)
Definition: usb_util.c:73
int usb_fifo_alloc_buffer(struct usb_fifo *f, uint32_t bufsize, uint16_t nbuf)
int() usb_fifo_ioctl_t(struct usb_fifo *fifo, u_long cmd, void *addr, int fflags)
Definition: usbdi.h:101
void * usb_fifo_softc(struct usb_fifo *fifo)
void() usb_fifo_close_t(struct usb_fifo *fifo, int fflags)
Definition: usbdi.h:100
void usb_fifo_detach(struct usb_fifo_sc *f_sc)
#define USB_ST_SETUP
Definition: usbdi.h:502
void usb_fifo_put_data(struct usb_fifo *fifo, struct usb_page_cache *pc, usb_frlength_t offset, usb_frlength_t len, uint8_t what)
int usb_fifo_attach(struct usb_device *udev, void *priv_sc, struct mtx *priv_mtx, struct usb_fifo_methods *pm, struct usb_fifo_sc *f_sc, uint16_t unit, int16_t subunit, uint8_t iface_index, uid_t uid, gid_t gid, int mode)
usb_error_t
Definition: usbdi.h:45
@ USB_ERR_CANCELLED
Definition: usbdi.h:51
void() usb_fifo_cmd_t(struct usb_fifo *fifo)
Definition: usbdi.h:102
void usb_fifo_free_buffer(struct usb_fifo *f)
uint8_t usb_fifo_get_data(struct usb_fifo *fifo, struct usb_page_cache *pc, usb_frlength_t offset, usb_frlength_t len, usb_frlength_t *actlen, uint8_t what)
#define USB_ST_TRANSFERRED
Definition: usbdi.h:503
#define USB_FIFO_RX
Definition: usbdi.h:527
void() usb_callback_t(struct usb_xfer *, usb_error_t)
Definition: usbdi.h:94
#define USB_FIFO_TX
Definition: usbdi.h:526
int() usb_fifo_open_t(struct usb_fifo *fifo, int fflags)
Definition: usbdi.h:99
#define USB_VPI(vend, prod, info)
Definition: usbdi.h:367
#define STRUCT_USB_HOST_ID
Definition: usbdi.h:258
#define USB_GET_STATE(xfer)
Definition: usbdi.h:515
uint32_t usb_fifo_put_bytes_max(struct usb_fifo *fifo)