diff options
-rw-r--r-- | share/man/man4/urio.4 | 103 | ||||
-rw-r--r-- | sys/amd64/conf/GENERIC | 1 | ||||
-rw-r--r-- | sys/conf/NOTES | 3 | ||||
-rw-r--r-- | sys/conf/files | 1 | ||||
-rw-r--r-- | sys/conf/options | 1 | ||||
-rw-r--r-- | sys/dev/usb/rio_usb.h | 61 | ||||
-rw-r--r-- | sys/dev/usb/urio.c | 564 | ||||
-rw-r--r-- | sys/i386/conf/GENERIC | 1 | ||||
-rw-r--r-- | sys/i386/conf/LINT | 3 | ||||
-rw-r--r-- | sys/i386/conf/NOTES | 3 | ||||
-rw-r--r-- | sys/modules/Makefile | 3 | ||||
-rw-r--r-- | sys/modules/urio/Makefile | 10 |
12 files changed, 753 insertions, 1 deletions
diff --git a/share/man/man4/urio.4 b/share/man/man4/urio.4 new file mode 100644 index 0000000..d0b3d99 --- /dev/null +++ b/share/man/man4/urio.4 @@ -0,0 +1,103 @@ +.\" Copyright (c) 2000 Dirk-Willem van Gulik +.\" <dirkx@webweaving.org>. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by Bill Paul. +.\" 4. Neither the name of the author nor the names of any co-contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY NICK HIBMA AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL NICK HIBMA OR THE VOICES IN HIS HEAD +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +.\" THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd March 5, 2000 +.Dt URIO 4 +.Os FreeBSD +.Sh NAME +.Nm urio +.Nd USB driver for the Rio500 MP3 player +.Sh SYNOPSIS +.Cd "device urio0" +.Sh DESCRIPTION +The +.Nm +driver provides support for the Rio500 MP3 player from Diamond MultiMedia which attaches to the USB port. The +.Nm +device must be configured in the kernel, along with +.Nm usb +and one of the controllers: +.Nm uhci +or +.Nm ohci +.Pp +The +.Nm /dev/urio0 +device can subsequentlty be used by the Rio500 userland applications. +.Sh FILES +.Bl -tag -width /dev/ums0 -compact +.It Pa /dev/urio0 +blocking device node +.Sh EXAMPLE +.Dl device urio0 +.Pp +Adds the +.Nm +driver to the kernel. Create the device node in the /dev directory: +.Pp +.Dl cd /dev +.Dl sh MAKEDEV urio0 +.Pp +And finally +.Pp +.Dl rio_add_song /local/MP3/TraceyChapman/02-Fast-Car.mp3 +.Pp +Will download a song over the +.Nm USB +connection into your Rio500. +.Pp +.Sh SEE ALSO +.Xr ohci 4 , +.Xr uhci 4 , +.Xr usb 4 , +.Xr http://rio500.sourceforge.org WWW +.Pp +The rio500 tools from the SourceForge are the actual userland tools +you use to download, format or rename songs on your players. When +compiling you must make sure that +.Nm /usr/include/dev/usb/rio_usb.h +is in your include path, and that you configure the +.Nm /dev/urio0 +as the device with following configure: +.Pp +CFLAGS="-I/usr/include/dev/usb" ./configure --with-devicepath='/dev' --with-deviceentry='urio0' +.\".Sh HISTORY +.Sh AUTHORS +The +.Nm +driver was written by +.An Iwasa Kazmi Aq kzmi@ca2.so-net.ne.jp +for +.Fx +.Pp +This manual page was written by +.An Dirk-Willem van Gulik Aq dirkx@webweaving.org diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC index 38bf15a..4c58389 100644 --- a/sys/amd64/conf/GENERIC +++ b/sys/amd64/conf/GENERIC @@ -223,6 +223,7 @@ pseudo-device bpf #Berkeley packet filter #device ulpt # Printer #device umass # Disks/Mass storage - Requires scbus and da #device ums # Mouse +#device urio # Diamond Rio 500 MP3 player # USB Ethernet, requires mii #device aue # ADMtek USB ethernet #device cue # CATC USB ethernet diff --git a/sys/conf/NOTES b/sys/conf/NOTES index 15d72f5..e6a31db 100644 --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -2292,6 +2292,8 @@ device ulpt device umass # USB mouse device ums +# Diamond Rio 500 Mp3 player +device urio # # ADMtek USB ethernet. Supports the LinkSys USB100TX, # the Billionton USB100, the Melco LU-ATX, the D-Link DSB-650TX @@ -2323,6 +2325,7 @@ options UKBD_DEBUG options ULPT_DEBUG options UMASS_DEBUG options UMS_DEBUG +options URIO_DEBUG # options for ukbd: options UKBD_DFLT_KEYMAP # specify the built-in keymap diff --git a/sys/conf/files b/sys/conf/files index 7e131d5..326b4b2 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -935,6 +935,7 @@ dev/usb/ulpt.c optional ulpt dev/usb/ukbd.c optional ukbd dev/usb/umass.c optional umass dev/usb/uhub.c optional usb +dev/usb/urio.c optional urio dev/usb/if_aue.c optional aue dev/usb/if_cue.c optional cue dev/usb/if_kue.c optional kue diff --git a/sys/conf/options b/sys/conf/options index 472d7b8..b88f60d 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -430,6 +430,7 @@ UKBD_DEBUG opt_usb.h ULPT_DEBUG opt_usb.h UMASS_DEBUG opt_usb.h UMS_DEBUG opt_usb.h +URIO_DEBUG opt_usb.h # Vinum options VINUMDEBUG opt_vinum.h diff --git a/sys/dev/usb/rio_usb.h b/sys/dev/usb/rio_usb.h new file mode 100644 index 0000000..56c8ebb --- /dev/null +++ b/sys/dev/usb/rio_usb.h @@ -0,0 +1,61 @@ +/* ---------------------------------------------------------------------- + + Copyright (C) 2000 Cesar Miquel (miquel@df.uba.ar) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + ---------------------------------------------------------------------- */ + +/* modified for FreeBSD by Iwasa Kazmi <kzmi@ca2.so-net.ne.jp> */ + +/* $FreeBSD$ */ + +#ifdef __FreeBSD__ +#include <sys/ioccom.h> +#ifndef USB_VENDOR_DIAMOND +#define USB_VENDOR_DIAMOND 0x841 +#endif +#ifndef USB_PRODUCT_DIAMOND_RIO500USB +#define USB_PRODUCT_DIAMOND_RIO500USB 0x1 +#endif +#endif + +struct RioCommand +{ +#ifdef __FreeBSD__ + u_int16_t length; +#else + short length; +#endif + int request; + int requesttype; + int value; + int index; + void *buffer; + int timeout; +}; + +#ifdef __FreeBSD__ +#define RIO_SEND_COMMAND _IOWR('U', 200, struct RioCommand) +#define RIO_RECV_COMMAND _IOWR('U', 201, struct RioCommand) +#else +#define RIO_SEND_COMMAND 0x1 +#define RIO_RECV_COMMAND 0x2 +#endif + +#define RIO_DIR_OUT 0x0 +#define RIO_DIR_IN 0x1 + + diff --git a/sys/dev/usb/urio.c b/sys/dev/usb/urio.c new file mode 100644 index 0000000..8a87682 --- /dev/null +++ b/sys/dev/usb/urio.c @@ -0,0 +1,564 @@ +/* + * Copyright (c) 2000 Iwasa Kazmi <kzmi@ca2.so-net.ne.jp> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This code is based on ugen.c and ulpt.c developed by Lennart Augustsson. + * This code includes software developed by the NetBSD Foundation, Inc. and + * its contributors. + */ + +/* $FreeBSD$ */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/malloc.h> +#if defined(__NetBSD__) +#include <sys/device.h> +#include <sys/ioctl.h> +#elif defined(__FreeBSD__) +#include <sys/module.h> +#include <sys/bus.h> +#include <sys/ioccom.h> +#include <sys/conf.h> +#include <sys/fcntl.h> +#include <sys/filio.h> +#endif +#include <sys/tty.h> +#include <sys/file.h> +#include <sys/select.h> +#include <sys/proc.h> +#include <sys/vnode.h> +#include <sys/poll.h> + +#include <dev/usb/usb.h> +#include <dev/usb/usbdi.h> +#include <dev/usb/usbdi_util.h> + +#include <dev/usb/usbdevs.h> +#include <dev/usb/rio_usb.h> + +#ifdef URIO_DEBUG +#define DPRINTF(x) if (uriodebug) logprintf x +#define DPRINTFN(n,x) if (uriodebug>(n)) logprintf x +int uriodebug = 100; +#else +#define DPRINTF(x) +#define DPRINTFN(n,x) +#endif + + +#if defined(__NetBSD__) +int urioopen __P((dev_t, int, int, struct proc *)); +int urioclose __P((dev_t, int, int, struct proc *p)); +int urioread __P((dev_t, struct uio *uio, int)); +int uriowrite __P((dev_t, struct uio *uio, int)); +int urioioctl __P((dev_t, u_long, caddr_t, int, struct proc *)); +#elif defined(__FreeBSD__) +d_open_t urioopen; +d_close_t urioclose; +d_read_t urioread; +d_write_t uriowrite; +d_ioctl_t urioioctl; + +#define URIO_CDEV_MAJOR 143 + +#define RIO_OUT 0 +#define RIO_IN 1 +#define RIO_NODIR 2 + +#if (__FreeBSD__ >= 4) +static struct cdevsw urio_cdevsw = { + urioopen, urioclose, urioread, uriowrite, + urioioctl, nopoll, nommap, nostrategy, + "urio", URIO_CDEV_MAJOR,nodump, nopsize, + 0, -1 +}; +#define RIO_UE_GET_DIR(p) ((UE_GET_DIR(p) == UE_DIR_IN) ? RIO_IN :\ + ((UE_GET_DIR(p) == UE_DIR_OUT) ? RIO_OUT :\ + RIO_NODIR)) +#else +static struct cdevsw urio_cdevsw = { + urioopen, urioclose, urioread, uriowrite, + urioioctl, nostop, nullreset, nodevtotty, + seltrue, nommap, nostrat, + "urio", NULL, -1 +}; +#define USBBASEDEVICE bdevice +#define RIO_UE_GET_DIR(p) UE_GET_IN(p) +#endif + +#endif /*defined(__FreeBSD__)*/ + +#define URIO_BBSIZE 1024 + +struct urio_softc { + USBBASEDEVICE sc_dev; + usbd_device_handle sc_udev; + usbd_interface_handle sc_iface; + + int sc_opened; + usbd_pipe_handle sc_pipeh; + int sc_dir; + + int sc_epaddr[2]; +}; + +#define URIOUNIT(n) (minor(n)) + +#define RIO_RW_TIMEOUT 4000 /* ms */ + +USB_DECLARE_DRIVER(urio); + +USB_MATCH(urio) +{ + USB_MATCH_START(urio, uaa); + usb_device_descriptor_t *dd; + + DPRINTFN(10,("urio_match\n")); + if (!uaa->iface) + return UMATCH_NONE; + + dd = usbd_get_device_descriptor(uaa->device); + + if (dd && + UGETW(dd->idVendor) == USB_VENDOR_DIAMOND && + UGETW(dd->idProduct) == USB_PRODUCT_DIAMOND_RIO500USB) + return UMATCH_VENDOR_PRODUCT; + else + return UMATCH_NONE; +} + +USB_ATTACH(urio) +{ + USB_ATTACH_START(urio, sc, uaa); + char devinfo[1024]; + usb_endpoint_descriptor_t *edesc; + u_int8_t epcount; + usbd_status r; + char * ermsg = "<none>"; + int i; + + DPRINTFN(10,("urio_attach: sc=%p\n", sc)); + usbd_devinfo(uaa->device, 0, devinfo); + USB_ATTACH_SETUP; + printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo); + + sc->sc_udev = uaa->device; + if ((!uaa->device) || (!uaa->iface)) { + ermsg = "device or iface"; + goto nobulk; + } + + sc->sc_iface = uaa->iface; + sc->sc_opened = 0; + + r = usbd_endpoint_count(uaa->iface, &epcount); + if (r != USBD_NORMAL_COMPLETION) { + ermsg = "endpoints"; + goto nobulk; + } + + sc->sc_epaddr[RIO_OUT] = 0xff; + sc->sc_epaddr[RIO_IN] = 0x00; + for (i = 0; i < epcount; i++) { + edesc = usbd_interface2endpoint_descriptor(uaa->iface, i); + if (!edesc) { + ermsg = "interface endpoint"; + goto nobulk; + } + sc->sc_epaddr[RIO_UE_GET_DIR(edesc->bEndpointAddress)] + = edesc->bEndpointAddress; + } + if ( sc->sc_epaddr[RIO_OUT] == 0xff || + sc->sc_epaddr[RIO_IN] == 0x00) { + ermsg = "Rio I&O"; + goto nobulk; + } + +#if (__FreeBSD__ >= 4) + /* XXX no error trapping, no storing of dev_t */ + (void) make_dev(&urio_cdevsw, device_get_unit(self), + UID_ROOT, GID_OPERATOR, + 0644, "urio%d", device_get_unit(self)); +#endif + + DPRINTFN(10, ("urio_attach: %p\n", sc->sc_udev)); + + USB_ATTACH_SUCCESS_RETURN; + + nobulk: + printf("%s: could not find %s\n", USBDEVNAME(sc->sc_dev),ermsg); + USB_ATTACH_ERROR_RETURN; +} + + +int +urioopen(dev, flag, mode, p) + dev_t dev; + int flag; + int mode; + struct proc *p; +{ +#if (__FreeBSD__ >= 4) + struct urio_softc * sc; +#endif + int unit = URIOUNIT(dev); + USB_GET_SC_OPEN(urio, unit, sc); + + DPRINTFN(5, ("urioopen: flag=%d, mode=%d, unit=%d\n", + flag, mode, unit)); + + if (sc->sc_opened) + return EBUSY; + + if ((flag & (FWRITE|FREAD)) != (FWRITE|FREAD)) + return EACCES; + + sc->sc_opened = 1; + sc->sc_pipeh = 0; + sc->sc_dir = RIO_NODIR; + return 0; +} + +int +urioclose(dev, flag, mode, p) + dev_t dev; + int flag; + int mode; + struct proc *p; +{ +#if (__FreeBSD__ >= 4) + struct urio_softc * sc; +#endif + int unit = URIOUNIT(dev); + USB_GET_SC(urio, unit, sc); + + DPRINTFN(5, ("urioclose: flag=%d, mode=%d, unit=%d\n", flag, mode, unit)); + if (sc->sc_pipeh) { + /*usbd_abort_pipe(sc->sc_pipeh);*/ + usbd_close_pipe(sc->sc_pipeh); + } + sc->sc_opened = 0; + + return 0; +} + +int +urioread(dev, uio, flag) + dev_t dev; + struct uio *uio; + int flag; +{ +#if (__FreeBSD__ >= 4) + struct urio_softc * sc; + usbd_xfer_handle reqh; +#else + usbd_request_handle reqh; + usbd_private_handle r_priv; + void *r_buff; + usbd_status r_status; +#endif + int unit = URIOUNIT(dev); + usbd_status r; + char buf[URIO_BBSIZE]; + u_int32_t n, tn; + int error = 0; + + USB_GET_SC(urio, unit, sc); + + DPRINTFN(5, ("urioread: %d\n", unit)); + if (!sc->sc_opened) + return EIO; + + if (sc->sc_dir != RIO_IN) { + if (sc->sc_pipeh) { + /*usbd_abort_pipe(sc->sc_pipeh);*/ + usbd_close_pipe(sc->sc_pipeh); + } + sc->sc_pipeh = 0; + sc->sc_dir = RIO_NODIR; + r = usbd_open_pipe(sc->sc_iface, + sc->sc_epaddr[RIO_IN], 0, + &sc->sc_pipeh); + if (r != USBD_NORMAL_COMPLETION) + return EIO; + sc->sc_dir = RIO_IN; + } + +#if (__FreeBSD__ >= 4) + reqh = usbd_alloc_xfer(sc->sc_udev); +#else + reqh = usbd_alloc_request(); +#endif + if (reqh == 0) + return ENOMEM; + while ((n = min(URIO_BBSIZE, uio->uio_resid)) != 0) { + DPRINTFN(1, ("urioread: start transfer %d bytes\n", n)); + tn = n; +#if (__FreeBSD__ >= 4) + usbd_setup_xfer(reqh, sc->sc_pipeh, 0, buf, tn, + 0, RIO_RW_TIMEOUT, 0); +#else + r = usbd_setup_request(reqh, sc->sc_pipeh, 0, buf, tn, + 0, RIO_RW_TIMEOUT, 0); + if (r != USBD_NORMAL_COMPLETION) { + error = EIO; + break; + } +#endif + r = usbd_sync_transfer(reqh); + if (r != USBD_NORMAL_COMPLETION) { + DPRINTFN(1, ("urioread: error=%d\n", r)); + usbd_clear_endpoint_stall(sc->sc_pipeh); + tn = 0; + error = EIO; + break; + } +#if (__FreeBSD__ >= 4) + usbd_get_xfer_status(reqh, 0, 0, &tn, 0); +#else + usbd_get_request_status(reqh, &r_priv, &r_buff, &tn, &r_status); +#endif + + DPRINTFN(1, ("urioread: got %d bytes\n", tn)); + error = uiomove(buf, tn, uio); + if (error || tn < n) + break; + } +#if (__FreeBSD__ >= 4) + usbd_free_xfer(reqh); +#else + usbd_free_request(reqh); +#endif + + return error; +} + +int +uriowrite(dev, uio, flag) + dev_t dev; + struct uio *uio; + int flag; +{ +#if (__FreeBSD__ >= 4) + struct urio_softc * sc; + usbd_xfer_handle reqh; +#else + usbd_request_handle reqh; +#endif + int unit = URIOUNIT(dev); + usbd_status r; + char buf[URIO_BBSIZE]; + u_int32_t n; + int error = 0; + + USB_GET_SC(urio, unit, sc); + + DPRINTFN(5, ("uriowrite: %d\n", unit)); + if (!sc->sc_opened) + return EIO; + + if (sc->sc_dir != RIO_OUT) { + if (sc->sc_pipeh) { + /*usbd_abort_pipe(sc->sc_pipeh);*/ + usbd_close_pipe(sc->sc_pipeh); + } + sc->sc_pipeh = 0; + sc->sc_dir = RIO_NODIR; + r = usbd_open_pipe(sc->sc_iface, + sc->sc_epaddr[RIO_OUT], 0, + &sc->sc_pipeh); + if (r != USBD_NORMAL_COMPLETION) + return EIO; + sc->sc_dir = RIO_OUT; + } + +#if (__FreeBSD__ >= 4) + reqh = usbd_alloc_xfer(sc->sc_udev); +#else + reqh = usbd_alloc_request(); +#endif + if (reqh == 0) + return EIO; + while ((n = min(URIO_BBSIZE, uio->uio_resid)) != 0) { + error = uiomove(buf, n, uio); + if (error) + break; + DPRINTFN(1, ("uriowrite: transfer %d bytes\n", n)); +#if (__FreeBSD__ >= 4) + usbd_setup_xfer(reqh, sc->sc_pipeh, 0, buf, n, + 0, RIO_RW_TIMEOUT, 0); +#else + r = usbd_setup_request(reqh, sc->sc_pipeh, 0, buf, n, + 0, RIO_RW_TIMEOUT, 0); + if (r != USBD_NORMAL_COMPLETION) { + error = EIO; + break; + } +#endif + r = usbd_sync_transfer(reqh); + if (r != USBD_NORMAL_COMPLETION) { + DPRINTFN(1, ("uriowrite: error=%d\n", r)); + usbd_clear_endpoint_stall(sc->sc_pipeh); + error = EIO; + break; + } +#if (__FreeBSD__ >= 4) + usbd_get_xfer_status(reqh, 0, 0, 0, 0); +#endif + } + +#if (__FreeBSD__ >= 4) + usbd_free_xfer(reqh); +#else + usbd_free_request(reqh); +#endif + + return error; +} + + +int +urioioctl(dev, cmd, addr, flag, p) + dev_t dev; + u_long cmd; + caddr_t addr; + int flag; + struct proc *p; +{ +#if (__FreeBSD__ >= 4) + struct urio_softc * sc; +#endif + int unit = URIOUNIT(dev); + struct RioCommand *rio_cmd; + int requesttype, len; + struct iovec iov; + struct uio uio; + usb_device_request_t req; + int req_flags = 0, req_actlen = 0; + void *ptr = 0; + int error = 0; + usbd_status r; + + USB_GET_SC(urio, unit, sc); + + switch (cmd) { + case RIO_RECV_COMMAND: + if (!(flag & FWRITE)) + return EPERM; + rio_cmd = (struct RioCommand *)addr; + if (rio_cmd == NULL) + return EINVAL; + len = rio_cmd->length; + + requesttype = rio_cmd->requesttype | UT_READ_VENDOR_DEVICE; + DPRINTFN(1,("sending command:reqtype=%0x req=%0x value=%0x index=%0x len=%0x\n", + requesttype, rio_cmd->request, rio_cmd->value, rio_cmd->index, len)); + break; + + case RIO_SEND_COMMAND: + if (!(flag & FWRITE)) + return EPERM; + rio_cmd = (struct RioCommand *)addr; + if (rio_cmd == NULL) + return EINVAL; + len = rio_cmd->length; + + requesttype = rio_cmd->requesttype | UT_WRITE_VENDOR_DEVICE; + DPRINTFN(1,("sending command:reqtype=%0x req=%0x value=%0x index=%0x len=%0x\n", + requesttype, rio_cmd->request, rio_cmd->value, rio_cmd->index, len)); + break; + + default: + return EINVAL; + break; + } + + /* Send rio control message */ + req.bmRequestType = requesttype; + req.bRequest = rio_cmd->request; + USETW(req.wValue, rio_cmd->value); + USETW(req.wIndex, rio_cmd->index); + USETW(req.wLength, len); + + if (len < 0 || len > 32767) + return EINVAL; + if (len != 0) { + iov.iov_base = (caddr_t)rio_cmd->buffer; + iov.iov_len = len; + uio.uio_iov = &iov; + uio.uio_iovcnt = 1; + uio.uio_resid = len; + uio.uio_offset = 0; + uio.uio_segflg = UIO_USERSPACE; + uio.uio_rw = + req.bmRequestType & UT_READ ? + UIO_READ : UIO_WRITE; + uio.uio_procp = p; + ptr = malloc(len, M_TEMP, M_WAITOK); + if (uio.uio_rw == UIO_WRITE) { + error = uiomove(ptr, len, &uio); + if (error) + goto ret; + } + } + + r = usbd_do_request_flags(sc->sc_udev, &req, + ptr, req_flags, &req_actlen); + if (r == USBD_NORMAL_COMPLETION) { + error = 0; + if (len != 0) { + if (uio.uio_rw == UIO_READ) { + error = uiomove(ptr, len, &uio); + } + } + } else { + error = EIO; + } + +ret: + if (ptr) + free(ptr, M_TEMP); + return error; +} + + +#if defined(__FreeBSD__) +static int +urio_detach(device_t self) +{ + DPRINTF(("%s: disconnected\n", USBDEVNAME(self))); + device_set_desc(self, NULL); + return 0; +} + +#if (__FreeBSD__ >= 4) +DRIVER_MODULE(urio, uhub, urio_driver, urio_devclass, usbd_driver_load, 0); +#else +CDEV_DRIVER_MODULE(urio, uhub, urio_driver, urio_devclass, + URIO_CDEV_MAJOR, urio_cdevsw, usbd_driver_load, 0); +#endif + +#endif diff --git a/sys/i386/conf/GENERIC b/sys/i386/conf/GENERIC index 38bf15a..4c58389 100644 --- a/sys/i386/conf/GENERIC +++ b/sys/i386/conf/GENERIC @@ -223,6 +223,7 @@ pseudo-device bpf #Berkeley packet filter #device ulpt # Printer #device umass # Disks/Mass storage - Requires scbus and da #device ums # Mouse +#device urio # Diamond Rio 500 MP3 player # USB Ethernet, requires mii #device aue # ADMtek USB ethernet #device cue # CATC USB ethernet diff --git a/sys/i386/conf/LINT b/sys/i386/conf/LINT index 15d72f5..e6a31db 100644 --- a/sys/i386/conf/LINT +++ b/sys/i386/conf/LINT @@ -2292,6 +2292,8 @@ device ulpt device umass # USB mouse device ums +# Diamond Rio 500 Mp3 player +device urio # # ADMtek USB ethernet. Supports the LinkSys USB100TX, # the Billionton USB100, the Melco LU-ATX, the D-Link DSB-650TX @@ -2323,6 +2325,7 @@ options UKBD_DEBUG options ULPT_DEBUG options UMASS_DEBUG options UMS_DEBUG +options URIO_DEBUG # options for ukbd: options UKBD_DFLT_KEYMAP # specify the built-in keymap diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES index 15d72f5..e6a31db 100644 --- a/sys/i386/conf/NOTES +++ b/sys/i386/conf/NOTES @@ -2292,6 +2292,8 @@ device ulpt device umass # USB mouse device ums +# Diamond Rio 500 Mp3 player +device urio # # ADMtek USB ethernet. Supports the LinkSys USB100TX, # the Billionton USB100, the Melco LU-ATX, the D-Link DSB-650TX @@ -2323,6 +2325,7 @@ options UKBD_DEBUG options ULPT_DEBUG options UMASS_DEBUG options UMS_DEBUG +options URIO_DEBUG # options for ukbd: options UKBD_DFLT_KEYMAP # specify the built-in keymap diff --git a/sys/modules/Makefile b/sys/modules/Makefile index f4ec818..5051051 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -6,7 +6,8 @@ SUBDIR= aha amr an aue ccd cd9660 coda cue dc fdesc fxp if_disc if_ef if_ppp \ if_sl if_tun ipfilter ipfw joy kernfs kue md mfs mii mlx msdos \ ncp netgraph nfs ntfs nullfs \ nwfs portal procfs rl sf sis sk ste ti tl \ - ugen uhid ukbd ulpt umapfs umass umodem ums union usb vn vpo vr wb xl + ugen uhid ukbd ulpt umapfs umass umodem ums union urio usb \ + vn vpo vr wb xl # XXX some of these can move to the general case when de-i386'ed .if ${MACHINE_ARCH} == "i386" diff --git a/sys/modules/urio/Makefile b/sys/modules/urio/Makefile new file mode 100644 index 0000000..6d7fba6 --- /dev/null +++ b/sys/modules/urio/Makefile @@ -0,0 +1,10 @@ +# $FreeBSD$ + +MAINTAINER = Iwasa Kazmi <kzmi@ca2.so-net.ne.jp> + +.PATH: ${.CURDIR}/../../dev/usb +KMOD = urio +SRCS = bus_if.h device_if.h vnode_if.h opt_usb.h urio.c +NOMAN = + +.include <bsd.kmod.mk> |