diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/usb/files.usb | 7 | ||||
-rw-r--r-- | sys/dev/usb/uscom.c | 184 |
2 files changed, 190 insertions, 1 deletions
diff --git a/sys/dev/usb/files.usb b/sys/dev/usb/files.usb index 2043f88a1a2..06729e6784e 100644 --- a/sys/dev/usb/files.usb +++ b/sys/dev/usb/files.usb @@ -1,4 +1,4 @@ -# $OpenBSD: files.usb,v 1.113 2014/03/17 18:40:46 andre Exp $ +# $OpenBSD: files.usb,v 1.114 2014/03/25 03:29:23 jsg Exp $ # $NetBSD: files.usb,v 1.16 2000/02/14 20:29:54 augustss Exp $ # # Config file and device description for machine-independent USB code. @@ -319,6 +319,11 @@ device moscom: ucombus attach moscom at uhub file dev/usb/moscom.c moscom +# simple serial +device uscom: ucombus +attach uscom at uhub +file dev/usb/uscom.c uscom + # iPAQ PDAs # Generic ipaq support device uipaq: ucombus diff --git a/sys/dev/usb/uscom.c b/sys/dev/usb/uscom.c new file mode 100644 index 00000000000..9e4cf5bde23 --- /dev/null +++ b/sys/dev/usb/uscom.c @@ -0,0 +1,184 @@ +/* $OpenBSD: uscom.c,v 1.1 2014/03/25 03:29:23 jsg Exp $ */ + +/* + * Copyright (c) 2006 Jonathan Gray <jsg@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/conf.h> +#include <sys/tty.h> +#include <sys/device.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/usbdevs.h> +#include <dev/usb/ucomvar.h> + +#define USCOMBUFSZ 256 +#define USCOM_CONFIG_NO 0 +#define USCOM_IFACE_NO 0 + +struct uscom_softc { + struct device sc_dev; + struct usbd_device *sc_udev; + struct usbd_interface *sc_iface; + struct device *sc_subdev; +}; + +struct ucom_methods uscom_methods = { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +static const struct usb_devno uscom_devs[] = { + { USB_VENDOR_HP, USB_PRODUCT_HP_HPX9GP } +}; + +int uscom_match(struct device *, void *, void *); +void uscom_attach(struct device *, struct device *, void *); +int uscom_detach(struct device *, int); +int uscom_activate(struct device *, int); + +struct cfdriver uscom_cd = { + NULL, "uscom", DV_DULL +}; + +const struct cfattach uscom_ca = { + sizeof(struct uscom_softc), + uscom_match, + uscom_attach, + uscom_detach, + uscom_activate, +}; + +int +uscom_match(struct device *parent, void *match, void *aux) +{ + struct usb_attach_arg *uaa = aux; + + if (uaa->iface != NULL) + return UMATCH_NONE; + + return (usb_lookup(uscom_devs, uaa->vendor, uaa->product) != NULL) ? + UMATCH_VENDOR_PRODUCT : UMATCH_NONE; +} + +void +uscom_attach(struct device *parent, struct device *self, void *aux) +{ + struct uscom_softc *sc = (struct uscom_softc *)self; + struct usb_attach_arg *uaa = aux; + struct ucom_attach_args uca; + usb_interface_descriptor_t *id; + usb_endpoint_descriptor_t *ed; + usbd_status error; + int i; + + bzero(&uca, sizeof(uca)); + sc->sc_udev = uaa->device; + + if (usbd_set_config_index(sc->sc_udev, USCOM_CONFIG_NO, 1) != 0) { + printf("%s: could not set configuration no\n", + sc->sc_dev.dv_xname); + usbd_deactivate(sc->sc_udev); + return; + } + + /* get the first interface handle */ + error = usbd_device2interface_handle(sc->sc_udev, USCOM_IFACE_NO, + &sc->sc_iface); + if (error != 0) { + printf("%s: could not get interface handle\n", + sc->sc_dev.dv_xname); + usbd_deactivate(sc->sc_udev); + return; + } + + id = usbd_get_interface_descriptor(sc->sc_iface); + + uca.bulkin = uca.bulkout = -1; + for (i = 0; i < id->bNumEndpoints; i++) { + ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i); + if (ed == NULL) { + printf("%s: no endpoint descriptor found for %d\n", + sc->sc_dev.dv_xname, i); + usbd_deactivate(sc->sc_udev); + return; + } + + if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && + UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) + uca.bulkin = ed->bEndpointAddress; + else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && + UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) + uca.bulkout = ed->bEndpointAddress; + } + + if (uca.bulkin == -1 || uca.bulkout == -1) { + printf("%s: missing endpoint\n", sc->sc_dev.dv_xname); + usbd_deactivate(sc->sc_udev); + return; + } + + uca.ibufsize = USCOMBUFSZ; + uca.obufsize = USCOMBUFSZ; + uca.ibufsizepad = USCOMBUFSZ; + uca.opkthdrlen = 0; + uca.device = sc->sc_udev; + uca.iface = sc->sc_iface; + uca.methods = &uscom_methods; + uca.arg = sc; + uca.info = NULL; + + sc->sc_subdev = config_found_sm(self, &uca, ucomprint, ucomsubmatch); +} + +int +uscom_detach(struct device *self, int flags) +{ + struct uscom_softc *sc = (struct uscom_softc *)self; + int rv = 0; + + if (sc->sc_subdev != NULL) { + rv = config_detach(sc->sc_subdev, flags); + sc->sc_subdev = NULL; + } + + return (rv); +} + +int +uscom_activate(struct device *self, int act) +{ + struct uscom_softc *sc = (struct uscom_softc *)self; + + switch (act) { + case DVACT_DEACTIVATE: + usbd_deactivate(sc->sc_udev); + break; + } + return (0); +} |