diff options
author | thompsa <thompsa@FreeBSD.org> | 2009-05-27 16:16:56 +0000 |
---|---|---|
committer | thompsa <thompsa@FreeBSD.org> | 2009-05-27 16:16:56 +0000 |
commit | 14ea3ee2bb371575697cd652ca2064877b187983 (patch) | |
tree | 723b0aed327f79b20884592648d5b64748a24f12 /sys/legacy/dev/usb/ucycom.c | |
parent | 3f72bbde95ea9eee2e163b14ffdca8533a85e6c1 (diff) | |
download | FreeBSD-src-14ea3ee2bb371575697cd652ca2064877b187983.zip FreeBSD-src-14ea3ee2bb371575697cd652ca2064877b187983.tar.gz |
Delete the old USB stack. The new stack has settled in and has all the
drivers/functionality and then some.
Diffstat (limited to 'sys/legacy/dev/usb/ucycom.c')
-rw-r--r-- | sys/legacy/dev/usb/ucycom.c | 543 |
1 files changed, 0 insertions, 543 deletions
diff --git a/sys/legacy/dev/usb/ucycom.c b/sys/legacy/dev/usb/ucycom.c deleted file mode 100644 index ecf115f..0000000 --- a/sys/legacy/dev/usb/ucycom.c +++ /dev/null @@ -1,543 +0,0 @@ -/*- - * Copyright (c) 2004 Dag-Erling Coïdan Smørgrav - * 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 - * in this position and unchanged. - * 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. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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$ - */ - -/* - * Device driver for Cypress CY7C637xx and CY7C640/1xx series USB to - * RS232 bridges. - * - * Normally, a driver for a USB-to-serial chip would hang off the ucom(4) - * driver, but ucom(4) was written under the assumption that all USB-to- - * serial chips use bulk pipes for I/O, while the Cypress parts use HID - * reports. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/conf.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/sysctl.h> -#include <sys/bus.h> -#include <sys/tty.h> - -#include "usbdevs.h" -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include <dev/usb/usbhid.h> -#include <dev/usb/hid.h> - -#define UCYCOM_EP_INPUT 0 -#define UCYCOM_EP_OUTPUT 1 - -#define UCYCOM_MAX_IOLEN 32U - -struct ucycom_softc { - device_t sc_dev; - struct tty *sc_tty; - int sc_error; - unsigned long sc_cintr; - unsigned long sc_cin; - unsigned long sc_clost; - unsigned long sc_cout; - - /* usb parameters */ - usbd_device_handle sc_usbdev; - usbd_interface_handle sc_iface; - usbd_pipe_handle sc_pipe; - uint8_t sc_iep; /* input endpoint */ - uint8_t sc_fid; /* feature report id*/ - uint8_t sc_iid; /* input report id */ - uint8_t sc_oid; /* output report id */ - size_t sc_flen; /* feature report length */ - size_t sc_ilen; /* input report length */ - size_t sc_olen; /* output report length */ - uint8_t sc_ibuf[UCYCOM_MAX_IOLEN]; - - /* model and settings */ - uint32_t sc_model; -#define MODEL_CY7C63743 0x63743 -#define MODEL_CY7C64013 0x64013 - uint32_t sc_baud; - uint8_t sc_cfg; -#define UCYCOM_CFG_RESET 0x80 -#define UCYCOM_CFG_PARODD 0x20 -#define UCYCOM_CFG_PAREN 0x10 -#define UCYCOM_CFG_STOPB 0x08 -#define UCYCOM_CFG_DATAB 0x03 - uint8_t sc_ist; /* status flags from last input */ - uint8_t sc_ost; /* status flags for next output */ - - /* flags */ - char sc_dying; -}; - -static device_probe_t ucycom_probe; -static device_attach_t ucycom_attach; -static device_detach_t ucycom_detach; -static t_open_t ucycom_open; -static t_close_t ucycom_close; -static void ucycom_start(struct tty *); -static void ucycom_stop(struct tty *, int); -static int ucycom_param(struct tty *, struct termios *); -static int ucycom_configure(struct ucycom_softc *, uint32_t, uint8_t); -static void ucycom_intr(usbd_xfer_handle, usbd_private_handle, usbd_status); - -static device_method_t ucycom_methods[] = { - DEVMETHOD(device_probe, ucycom_probe), - DEVMETHOD(device_attach, ucycom_attach), - DEVMETHOD(device_detach, ucycom_detach), - { 0, 0 } -}; - -static driver_t ucycom_driver = { - "ucycom", - ucycom_methods, - sizeof(struct ucycom_softc), -}; - -static devclass_t ucycom_devclass; - -DRIVER_MODULE(ucycom, uhub, ucycom_driver, ucycom_devclass, usbd_driver_load, 0); -MODULE_VERSION(ucycom, 1); -MODULE_DEPEND(ucycom, usb, 1, 1, 1); - -/* - * Supported devices - */ - -static struct ucycom_device { - uint16_t vendor; - uint16_t product; - uint32_t model; -} ucycom_devices[] = { - { USB_VENDOR_DELORME, USB_PRODUCT_DELORME_EARTHMATE, MODEL_CY7C64013 }, - { 0, 0, 0 }, -}; - -#define UCYCOM_DEFAULT_RATE 4800 -#define UCYCOM_DEFAULT_CFG 0x03 /* N-8-1 */ - -/***************************************************************************** - * - * Driver interface - * - */ - -static int -ucycom_probe(device_t dev) -{ - struct usb_attach_arg *uaa; - struct ucycom_device *ud; - - uaa = device_get_ivars(dev); - if (uaa->iface != NULL) - return (UMATCH_NONE); - for (ud = ucycom_devices; ud->model != 0; ++ud) - if (ud->vendor == uaa->vendor && ud->product == uaa->product) - return (UMATCH_VENDOR_PRODUCT); - return (UMATCH_NONE); -} - -static int -ucycom_attach(device_t dev) -{ - struct usb_attach_arg *uaa; - struct ucycom_softc *sc; - struct ucycom_device *ud; - usb_endpoint_descriptor_t *ued; - void *urd; - int error, urdlen; - - /* get arguments and softc */ - uaa = device_get_ivars(dev); - sc = device_get_softc(dev); - bzero(sc, sizeof *sc); - sc->sc_dev = dev; - sc->sc_usbdev = uaa->device; - - /* get chip model */ - for (ud = ucycom_devices; ud->model != 0; ++ud) - if (ud->vendor == uaa->vendor && ud->product == uaa->product) - sc->sc_model = ud->model; - if (sc->sc_model == 0) { - device_printf(dev, "unsupported device\n"); - return (ENXIO); - } - device_printf(dev, "Cypress CY7C%X USB to RS232 bridge\n", sc->sc_model); - - /* select configuration */ - error = usbd_set_config_index(sc->sc_usbdev, 0, 1 /* verbose */); - if (error != 0) { - device_printf(dev, "failed to select configuration: %s\n", - usbd_errstr(error)); - return (ENXIO); - } - - /* get first interface handle */ - error = usbd_device2interface_handle(sc->sc_usbdev, 0, &sc->sc_iface); - if (error != 0) { - device_printf(dev, "failed to get interface handle: %s\n", - usbd_errstr(error)); - return (ENXIO); - } - - /* get report descriptor */ - error = usbd_read_report_desc(sc->sc_iface, &urd, &urdlen, M_USBDEV); - if (error != 0) { - device_printf(dev, "failed to get report descriptor: %s\n", - usbd_errstr(error)); - return (ENXIO); - } - - /* get report sizes */ - sc->sc_flen = hid_report_size(urd, urdlen, hid_feature, &sc->sc_fid); - sc->sc_ilen = hid_report_size(urd, urdlen, hid_input, &sc->sc_iid); - sc->sc_olen = hid_report_size(urd, urdlen, hid_output, &sc->sc_oid); - - if (sc->sc_ilen > UCYCOM_MAX_IOLEN || sc->sc_olen > UCYCOM_MAX_IOLEN) { - device_printf(dev, "I/O report size too big (%zu, %zu, %u)\n", - sc->sc_ilen, sc->sc_olen, UCYCOM_MAX_IOLEN); - return (ENXIO); - } - - /* get and verify input endpoint descriptor */ - ued = usbd_interface2endpoint_descriptor(sc->sc_iface, UCYCOM_EP_INPUT); - if (ued == NULL) { - device_printf(dev, "failed to get input endpoint descriptor\n"); - return (ENXIO); - } - if (UE_GET_DIR(ued->bEndpointAddress) != UE_DIR_IN) { - device_printf(dev, "not an input endpoint\n"); - return (ENXIO); - } - if ((ued->bmAttributes & UE_XFERTYPE) != UE_INTERRUPT) { - device_printf(dev, "not an interrupt endpoint\n"); - return (ENXIO); - } - sc->sc_iep = ued->bEndpointAddress; - - /* set up tty */ - sc->sc_tty = ttyalloc(); - sc->sc_tty->t_sc = sc; - sc->sc_tty->t_oproc = ucycom_start; - sc->sc_tty->t_stop = ucycom_stop; - sc->sc_tty->t_param = ucycom_param; - sc->sc_tty->t_open = ucycom_open; - sc->sc_tty->t_close = ucycom_close; - - SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), - SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), - OID_AUTO, "intr", CTLFLAG_RD, &sc->sc_cintr, 0, - "interrupt count"); - SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), - SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), - OID_AUTO, "in", CTLFLAG_RD, &sc->sc_cin, 0, - "input bytes read"); - SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), - SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), - OID_AUTO, "lost", CTLFLAG_RD, &sc->sc_clost, 0, - "input bytes lost"); - SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), - SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), - OID_AUTO, "out", CTLFLAG_RD, &sc->sc_cout, 0, - "output bytes"); - - /* create character device node */ - ttycreate(sc->sc_tty, 0, "y%r", device_get_unit(sc->sc_dev)); - - return (0); -} - -static int -ucycom_detach(device_t dev) -{ - struct ucycom_softc *sc; - - sc = device_get_softc(dev); - - ttyfree(sc->sc_tty); - - return (0); -} - -/***************************************************************************** - * - * Device interface - * - */ - -static int -ucycom_open(struct tty *tp, struct cdev *cdev) -{ - struct ucycom_softc *sc = tp->t_sc; - int error; - - /* set default configuration */ - ucycom_configure(sc, UCYCOM_DEFAULT_RATE, UCYCOM_DEFAULT_CFG); - - /* open interrupt pipe */ - error = usbd_open_pipe_intr(sc->sc_iface, sc->sc_iep, 0, - &sc->sc_pipe, sc, sc->sc_ibuf, sc->sc_ilen, - ucycom_intr, USBD_DEFAULT_INTERVAL); - if (error != 0) { - device_printf(sc->sc_dev, "failed to open interrupt pipe: %s\n", - usbd_errstr(error)); - return (ENXIO); - } - - if (bootverbose) - device_printf(sc->sc_dev, "%s bypass l_rint()\n", - (sc->sc_tty->t_state & TS_CAN_BYPASS_L_RINT) ? - "can" : "can't"); - - /* done! */ - return (0); -} - -static void -ucycom_close(struct tty *tp) -{ - struct ucycom_softc *sc = tp->t_sc; - - /* stop interrupts and close the interrupt pipe */ - usbd_abort_pipe(sc->sc_pipe); - usbd_close_pipe(sc->sc_pipe); - sc->sc_pipe = 0; - - return; -} - -/***************************************************************************** - * - * TTY interface - * - */ - -static void -ucycom_start(struct tty *tty) -{ - struct ucycom_softc *sc = tty->t_sc; - uint8_t report[sc->sc_olen]; - int error, len; - - while (sc->sc_error == 0 && sc->sc_tty->t_outq.c_cc > 0) { - switch (sc->sc_model) { - case MODEL_CY7C63743: - len = q_to_b(&sc->sc_tty->t_outq, - report + 1, sc->sc_olen - 1); - sc->sc_cout += len; - report[0] = len; - len += 1; - break; - case MODEL_CY7C64013: - len = q_to_b(&sc->sc_tty->t_outq, - report + 2, sc->sc_olen - 2); - sc->sc_cout += len; - report[0] = 0; - report[1] = len; - len += 2; - break; - default: - panic("unsupported model (driver error)"); - } - - while (len < sc->sc_olen) - report[len++] = 0; - error = usbd_set_report(sc->sc_iface, UHID_OUTPUT_REPORT, - sc->sc_oid, report, sc->sc_olen); -#if 0 - if (error != 0) { - device_printf(sc->sc_dev, - "failed to set output report: %s\n", - usbd_errstr(error)); - sc->sc_error = error; - } -#endif - } -} - -static void -ucycom_stop(struct tty *tty, int flags) -{ - struct ucycom_softc *sc; - - sc = tty->t_sc; - if (bootverbose) - device_printf(sc->sc_dev, "%s()\n", __func__); -} - -static int -ucycom_param(struct tty *tty, struct termios *t) -{ - struct ucycom_softc *sc; - uint32_t baud; - uint8_t cfg; - int error; - - sc = tty->t_sc; - - if (t->c_ispeed != t->c_ospeed) - return (EINVAL); - baud = t->c_ispeed; - - if (t->c_cflag & CIGNORE) { - cfg = sc->sc_cfg; - } else { - cfg = 0; - switch (t->c_cflag & CSIZE) { - case CS8: - ++cfg; - case CS7: - ++cfg; - case CS6: - ++cfg; - case CS5: - break; - default: - return (EINVAL); - } - if (t->c_cflag & CSTOPB) - cfg |= UCYCOM_CFG_STOPB; - if (t->c_cflag & PARENB) - cfg |= UCYCOM_CFG_PAREN; - if (t->c_cflag & PARODD) - cfg |= UCYCOM_CFG_PARODD; - } - - error = ucycom_configure(sc, baud, cfg); - return (error); -} - -/***************************************************************************** - * - * Hardware interface - * - */ - -static int -ucycom_configure(struct ucycom_softc *sc, uint32_t baud, uint8_t cfg) -{ - uint8_t report[sc->sc_flen]; - int error; - - switch (baud) { - case 600: - case 1200: - case 2400: - case 4800: - case 9600: - case 19200: - case 38400: - case 57600: -#if 0 - /* - * Stock chips only support standard baud rates in the 600 - 57600 - * range, but higher rates can be achieved using custom firmware. - */ - case 115200: - case 153600: - case 192000: -#endif - break; - default: - return (EINVAL); - } - - if (bootverbose) - device_printf(sc->sc_dev, "%d baud, %c-%d-%d\n", baud, - (cfg & UCYCOM_CFG_PAREN) ? - ((cfg & UCYCOM_CFG_PARODD) ? 'O' : 'E') : 'N', - 5 + (cfg & UCYCOM_CFG_DATAB), - (cfg & UCYCOM_CFG_STOPB) ? 2 : 1); - report[0] = baud & 0xff; - report[1] = (baud >> 8) & 0xff; - report[2] = (baud >> 16) & 0xff; - report[3] = (baud >> 24) & 0xff; - report[4] = cfg; - error = usbd_set_report(sc->sc_iface, UHID_FEATURE_REPORT, - sc->sc_fid, report, sc->sc_flen); - if (error != 0) { - device_printf(sc->sc_dev, "%s\n", usbd_errstr(error)); - return (EIO); - } - sc->sc_baud = baud; - sc->sc_cfg = cfg; - return (0); -} - -static void -ucycom_intr(usbd_xfer_handle xfer, usbd_private_handle scp, usbd_status status) -{ - struct ucycom_softc *sc = scp; - uint8_t *data; - int i, len, lost; - - sc->sc_cintr++; - - switch (sc->sc_model) { - case MODEL_CY7C63743: - sc->sc_ist = sc->sc_ibuf[0] & ~0x07; - len = sc->sc_ibuf[0] & 0x07; - data = sc->sc_ibuf + 1; - break; - case MODEL_CY7C64013: - sc->sc_ist = sc->sc_ibuf[0] & ~0x07; - len = sc->sc_ibuf[1]; - data = sc->sc_ibuf + 2; - break; - default: - panic("unsupported model (driver error)"); - } - - switch (status) { - case USBD_NORMAL_COMPLETION: - break; - default: - /* XXX */ - return; - } - - if (sc->sc_tty->t_state & TS_CAN_BYPASS_L_RINT) { - /* XXX flow control! */ - lost = b_to_q(data, len, &sc->sc_tty->t_rawq); - sc->sc_tty->t_rawcc += len - lost; - ttwakeup(sc->sc_tty); - } else { - for (i = 0, lost = len; i < len; ++i, --lost) - if (ttyld_rint(sc->sc_tty, data[i]) != 0) - break; - } - sc->sc_cin += len - lost; - sc->sc_clost += lost; -} |