PERFORCE change 99035 for review
Hans Petter Selasky
hselasky at FreeBSD.org
Mon Jun 12 05:25:13 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=99035
Change 99035 by hselasky at hselasky_mini_itx on 2006/06/12 05:22:47
Compilation fix for FreeBSD-6.
Affected files ...
.. //depot/projects/usb/src/sys/dev/usb/usb_cdev.c#4 edit
.. //depot/projects/usb/src/sys/dev/usb/uvscom.c#4 edit
Differences ...
==== //depot/projects/usb/src/sys/dev/usb/usb_cdev.c#4 (text+ko) ====
@@ -39,6 +39,7 @@
#include <sys/vnode.h>
#include <sys/proc.h>
#include <sys/poll.h>
+#include <sys/signalvar.h>
#include <dev/usb/usb_port.h>
#include <dev/usb/usb.h>
==== //depot/projects/usb/src/sys/dev/usb/uvscom.c#4 (text+ko) ====
@@ -1,0 +1,985 @@
+/* $NetBSD: usb/uvscom.c,v 1.1 2002/03/19 15:08:42 augustss Exp $ */
+/*-
+ * Copyright (c) 2001-2003, 2005 Shunsuke Akiyama <akiyama at jp.FreeBSD.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.
+ *
+ * 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.
+ *
+ */
+
+/*
+ * uvscom: SUNTAC Slipper U VS-10U driver.
+ * Slipper U is a PC Card to USB converter for data communication card
+ * adapter. It supports DDI Pocket's Air H" C at rd, C at rd H" 64, NTT's P-in,
+ * P-in m at ater and various data communication card adapters.
+ */
+
+#include "opt_uvscom.h" /* XXX remove this */
+
+#include <sys/cdefs.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/termios.h>
+#include <sys/serial.h>
+#include <sys/taskqueue.h>
+
+#include <dev/usb/usb_port.h>
+#include <dev/usb/usb.h>
+#include <dev/usb/usb_subr.h>
+#include <dev/usb/usb_quirks.h>
+#include <dev/usb/usb_cdc.h>
+
+#include <dev/usb/ucomvar.h>
+
+#include "usbdevs.h"
+
+__FBSDID("$FreeBSD: src/sys/dev/usb/uvscom.c $");
+
+#ifdef USB_DEBUG
+#define DPRINTF(n,fmt,...) \
+ do { if (uvscom_debug > (n)) { \
+ printf("%s: " fmt, __FUNCTION__,## __VA_ARGS__); } } while (0)
+
+static int uvscom_debug = 0;
+SYSCTL_NODE(_hw_usb, OID_AUTO, uvscom, CTLFLAG_RW, 0, "USB uvscom");
+SYSCTL_INT(_hw_usb_uvscom, OID_AUTO, debug, CTLFLAG_RW,
+ &uvscom_debug, 0, "uvscom debug level");
+#else
+#define DPRINTF(...)
+#endif
+
+#define UVSCOM_MODVER 1 /* module version */
+
+#define UVSCOM_CONFIG_INDEX 0
+#define UVSCOM_IFACE_INDEX 0
+
+#ifndef UVSCOM_INTR_INTERVAL
+#define UVSCOM_INTR_INTERVAL 0 /* default */
+#endif
+
+#define UVSCOM_UNIT_WAIT 5
+
+/* Request */
+#define UVSCOM_SET_SPEED 0x10
+#define UVSCOM_LINE_CTL 0x11
+#define UVSCOM_SET_PARAM 0x12
+#define UVSCOM_READ_STATUS 0xd0
+#define UVSCOM_SHUTDOWN 0xe0
+
+/* UVSCOM_SET_SPEED parameters */
+#define UVSCOM_SPEED_150BPS 0x00
+#define UVSCOM_SPEED_300BPS 0x01
+#define UVSCOM_SPEED_600BPS 0x02
+#define UVSCOM_SPEED_1200BPS 0x03
+#define UVSCOM_SPEED_2400BPS 0x04
+#define UVSCOM_SPEED_4800BPS 0x05
+#define UVSCOM_SPEED_9600BPS 0x06
+#define UVSCOM_SPEED_19200BPS 0x07
+#define UVSCOM_SPEED_38400BPS 0x08
+#define UVSCOM_SPEED_57600BPS 0x09
+#define UVSCOM_SPEED_115200BPS 0x0a
+
+/* UVSCOM_LINE_CTL parameters */
+#define UVSCOM_BREAK 0x40
+#define UVSCOM_RTS 0x02
+#define UVSCOM_DTR 0x01
+#define UVSCOM_LINE_INIT 0x08
+
+/* UVSCOM_SET_PARAM parameters */
+#define UVSCOM_DATA_MASK 0x03
+#define UVSCOM_DATA_BIT_8 0x03
+#define UVSCOM_DATA_BIT_7 0x02
+#define UVSCOM_DATA_BIT_6 0x01
+#define UVSCOM_DATA_BIT_5 0x00
+
+#define UVSCOM_STOP_MASK 0x04
+#define UVSCOM_STOP_BIT_2 0x04
+#define UVSCOM_STOP_BIT_1 0x00
+
+#define UVSCOM_PARITY_MASK 0x18
+#define UVSCOM_PARITY_EVEN 0x18
+#if 0
+#define UVSCOM_PARITY_UNK 0x10
+#endif
+#define UVSCOM_PARITY_ODD 0x08
+#define UVSCOM_PARITY_NONE 0x00
+
+/* Status bits */
+#define UVSCOM_TXRDY 0x04
+#define UVSCOM_RXRDY 0x01
+
+#define UVSCOM_DCD 0x08
+#define UVSCOM_NOCARD 0x04
+#define UVSCOM_DSR 0x02
+#define UVSCOM_CTS 0x01
+#define UVSCOM_USTAT_MASK (UVSCOM_NOCARD | UVSCOM_DSR | UVSCOM_CTS)
+
+struct uvscom_softc {
+ struct ucom_softc sc_ucom;
+ struct __callout sc_watchdog;
+
+ u_int16_t sc_line_ctrl; /* line control register */
+ u_int16_t sc_line_speed; /* line speed */
+ u_int16_t sc_line_param; /* line parameters */
+
+ u_int8_t sc_iface_no; /* interface number */
+ u_int8_t sc_iface_index; /* interface index */
+ u_int8_t sc_dtr; /* current DTR state */
+ u_int8_t sc_rts; /* current RTS state */
+ u_int8_t sc_lsr; /* local status register */
+ u_int8_t sc_msr; /* uvscom status register */
+
+
+ XXX:
+ int sc_iface_number;/* interface number */
+
+ usbd_interface_handle sc_intr_iface; /* interrupt interface */
+ int sc_intr_number; /* interrupt number */
+ usbd_pipe_handle sc_intr_pipe; /* interrupt pipe */
+ u_int8_t *sc_intr_buf; /* interrupt buffer */
+ int sc_isize;
+
+
+ u_int8_t sc_unit_status; /* unit status */
+
+ struct task sc_task;
+};
+
+/*
+ * These are the maximum number of bytes transferred per frame.
+ * The output buffer size cannot be increased due to the size encoding.
+ */
+#define UVSCOM_IBUFSIZE 512
+#define UVSCOM_OBUFSIZE 64
+
+#ifndef UVSCOM_DEFAULT_OPKTSIZE
+#define UVSCOM_DEFAULT_OPKTSIZE 8
+#endif
+
+#define UVSCOM_N_TRANSFER X
+
+static const struct usbd_config umodem_config_data[UVSCOM_N_TRANSFER] = {
+
+ [0] = {
+ .type = UE_BULK,
+ .endpoint = -1, /* any */
+ .direction = UE_DIR_OUT,
+ .bufsize = UVSCOM_OBUFSIZE,
+ .flags = 0,
+ .callback = &umodem_write_callback,
+ },
+
+ [1] = {
+ .type = UE_BULK,
+ .endpoint = -1, /* any */
+ .direction = UE_DIR_IN,
+ .bufsize = UVSCOM_IBUFSIZE,
+ .flags = USBD_SHORT_XFER_OK,
+ .callback = &umodem_read_callback,
+ },
+
+ [2] = {
+ .type = UE_CONTROL,
+ .endpoint = 0x00, /* Control pipe */
+ .direction = -1,
+ .bufsize = sizeof(usb_device_request_t),
+ .callback = &umodem_write_clear_stall_callback,
+ .timeout = 1000, /* 1 second */
+ },
+
+ [3] = {
+ .type = UE_CONTROL,
+ .endpoint = 0x00, /* Control pipe */
+ .direction = -1,
+ .bufsize = sizeof(usb_device_request_t),
+ .callback = &umodem_read_clear_stall_callback,
+ .timeout = 1000, /* 1 second */
+ },
+
+ [4] = {
+ .type = UE_INTERRUPT,
+ .endpoint = -1, /* any */
+ .direction = UE_DIR_IN,
+ .flags = USBD_SHORT_XFER_OK,
+ .bufsize = XXX,
+ .callback = &umodem_intr_callback,
+ },
+
+ [5] = {
+ .type = UE_CONTROL,
+ .endpoint = 0x00, /* Control pipe */
+ .direction = -1,
+ .bufsize = sizeof(usb_device_request_t),
+ .callback = &umodem_intr_clear_stall_callback,
+ .timeout = 1000, /* 1 second */
+ },
+
+ [6] = {
+ .type = UE_CONTROL,
+ .endpoint = 0x00, /* Control pipe */
+ .direction = -1,
+ .bufsize = sizeof(usb_device_request_t) + 2,
+ .callback = &uvscom_read_status_callback,
+ .timeout = 1000, /* 1 second */
+ },
+
+ [7] = {
+ .type = UE_CONTROL,
+ .endpoint = 0x00, /* Control pipe */
+ .direction = -1,
+ .bufsize = sizeof(usb_device_request_t),
+ .callback = &uvscom_shutdown_callback,
+ .timeout = 1000, /* 1 second */
+ },
+
+ [8] = {
+ .type = UE_CONTROL,
+ .endpoint = 0x00, /* Control pipe */
+ .direction = -1,
+ .bufsize = sizeof(usb_device_request_t),
+ .callback = &uvscom_set_line_callback,
+ .timeout = 1000, /* 1 second */
+ },
+
+ [9] = {
+ .type = UE_CONTROL,
+ .endpoint = 0x00, /* Control pipe */
+ .direction = -1,
+ .bufsize = sizeof(usb_device_request_t),
+ .callback = &uvscom_set_line_coding_callback,
+ .timeout = 1000, /* 1 second */
+ },
+
+
+
+
+XXX
+};
+
+static const struct ucom_callback uvscom_callback = {
+ .ucom_get_status = &uvscom_get_status,
+ .ucom_set_dtr = &uvscom_set_dtr,
+ .ucom_set_rts = &uvscom_set_rts,
+ .ucom_break = &uvscom_set_break,
+ .ucom_param = &uvscom_param,
+ .ucom_ioctl = &uvscom_ioctl,
+ .ucom_open = &uvscom_open,
+ .ucom_close = &uvscom_close,
+ .ucom_start_read = &uvscom_start_read,
+ .ucom_stop_read = &uvscom_stop_read,
+ .ucom_start_write = &uvscom_start_write,
+ .ucom_stop_write = &uvscom_stop_write,
+};
+
+static const struct usb_devno uvscom_devs [] = {
+ /* SUNTAC U-Cable type A4 */
+ { USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_AS144L4 },
+ /* SUNTAC U-Cable type D2 */
+ { USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_DS96L },
+ /* SUNTAC Ir-Trinity */
+ { USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_IS96U },
+ /* SUNTAC U-Cable type P1 */
+ { USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_PS64P1 },
+ /* SUNTAC Slipper U */
+ { USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_VS10U },
+};
+
+static device_probe_t uvscom_match;
+static device_attach_t uvscom_attach;
+static device_detach_t uvscom_detach;
+
+static device_method_t uvscom_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, uvscom_match),
+ DEVMETHOD(device_attach, uvscom_attach),
+ DEVMETHOD(device_detach, uvscom_detach),
+ { 0, 0 }
+};
+
+static driver_t uvscom_driver = {
+ "ucom",
+ uvscom_methods,
+ sizeof (struct uvscom_softc)
+};
+
+DRIVER_MODULE(uvscom, uhub, uvscom_driver, ucom_devclass, usbd_driver_load, 0);
+MODULE_DEPEND(uvscom, usb, 1, 1, 1);
+MODULE_DEPEND(uvscom, ucom, UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER);
+MODULE_VERSION(uvscom, UVSCOM_MODVER);
+
+static int uvscomobufsiz = UVSCOM_DEFAULT_OPKTSIZE;
+static int uvscominterval = UVSCOM_INTR_INTERVAL;
+
+remove:
+
+static int
+sysctl_hw_usb_uvscom_opktsize(SYSCTL_HANDLER_ARGS)
+{
+ int err, val;
+
+ val = uvscomobufsiz;
+ err = sysctl_handle_int(oidp, &val, sizeof(val), req);
+ if (err != 0 || req->newptr == NULL)
+ return (err);
+ if (0 < val && val <= UVSCOM_OBUFSIZE)
+ uvscomobufsiz = val;
+ else
+ err = EINVAL;
+
+ return (err);
+}
+
+static int
+sysctl_hw_usb_uvscom_interval(SYSCTL_HANDLER_ARGS)
+{
+ int err, val;
+
+ val = uvscominterval;
+ err = sysctl_handle_int(oidp, &val, sizeof(val), req);
+ if (err != 0 || req->newptr == NULL)
+ return (err);
+ if (0 < val && val <= 1000)
+ uvscominterval = val;
+ else
+ err = EINVAL;
+
+ return (err);
+}
+
+SYSCTL_PROC(_hw_usb_uvscom, OID_AUTO, opktsize, CTLTYPE_INT | CTLFLAG_RW,
+ 0, sizeof(int), sysctl_hw_usb_uvscom_opktsize,
+ "I", "uvscom output packet size");
+SYSCTL_PROC(_hw_usb_uvscom, OID_AUTO, interval, CTLTYPE_INT | CTLFLAG_RW,
+ 0, sizeof(int), sysctl_hw_usb_uvscom_interval,
+ "I", "uvscom interrpt pipe interval");
+
+static int
+uvscom_probe(device_t dev)
+{
+ struct usb_attach_arg *uaa = device_get_ivars(dev);
+
+ if (uaa->iface) {
+ return UMATCH_NONE;
+ }
+
+ return (usb_lookup(uvscom_devs, uaa->vendor, uaa->product) ?
+ UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
+}
+
+static int
+uvscom_attach(device_t dev)
+{
+ struct usb_attach_arg *uaa = device_get_ivars(dev);
+ struct uvscom_softc *sc = device_get_softc(dev);
+ usb_interface_descriptor_t *id;
+ struct usbd_interface *iface;
+ u_int16_t isize;
+ int error;
+
+ if (sc == NULL) {
+ return ENOMEM;
+ }
+
+ usbd_set_desc(dev, uaa->device);
+
+ DPRINTF(0, "sc=%p\n", sc);
+
+ __callout_init_mtx(&(sc->sc_watchdog), &Giant,
+ CALLOUT_RETURNUNLOCKED);
+
+ /* configure the device */
+
+ error = usbd_set_config_index(uaa->device, UVSCOM_CONFIG_INDEX, 1);
+ if (error) {
+ device_printf(dev, "failed to set configuration, "
+ "error=%s\n", usbd_errstr(error));
+ goto detach;
+ }
+
+ iface = usbd_get_iface(uaa->device, UVSCOM_IFACE_INDEX);
+
+ if (iface == NULL) {
+ DPRINTF(0, "no interface\n");
+ goto detach;
+ }
+
+ id = usbd_get_interface_descriptor(iface);
+
+ if (id == NULL) {
+ DPRINTF(0, "no interface descriptor\n");
+ goto detach;
+ }
+
+ sc->sc_iface_no = id->bInterfaceNumber;
+ sc->sc_iface_index = UVSCOM_IFACE_INDEX;
+
+ error = usbd_transfer_setup(uaa->device, sc->sc_iface_index,
+ sc->sc_xfer, uvscom_config,
+ UVSCOM_N_TRANSFER,
+ sc, &Giant, &(uvscom_detach_complete));
+ if (error) {
+ DPRINTF(0, "could not allocate all USB transfers!\n");
+ goto detach;
+ }
+
+ sc->sc_flag |= UVSCOM_FLAG_WAIT_USB;
+
+isize = UGETW(sc->sc_xfer[->wMaxPacketSize)
+
+ if (isize > UPLCOM_INTR_SIZE) {
+ DPRINTF(0, "cannot handle an interrupt "
+ "packet of %d bytes\n", isize);
+ goto detach;
+ }
+
+ /* set transfer length */
+ sc->sc_xfer_intr[0]->length = isize;
+
+ sc->sc_dtr = -1;
+ sc->sc_rts = -1;
+ sc->sc_break = -1;
+ sc->sc_line_ctrl = UVSCOM_LINE_INIT;
+
+ ucom->sc_parent = sc;
+ ucom->sc_portno = 0;
+ ucom->sc_callback = &uvscom_callback;
+
+ error = ucom_attach(&(sc->sc_ucom), dev);
+
+ if (error) {
+ goto detach;
+ }
+
+ /* start interrupt pipe */
+
+ usbd_transfer_start(sc->sc_xfer[4]);
+
+ /* start watchdog (returns unlocked) */
+
+ mtx_lock(&Giant);
+
+ uvscom_watchdog(sc);
+
+ return 0;
+
+ detach:
+ uvscom_detach(dev);
+ return ENXIO;
+}
+
+#if 0
+{
+ UCOM_UNK_PORTNO;
+ /* bulkin, bulkout set above */
+ ucom->sc_ibufsize = UVSCOM_IBUFSIZE;
+ ucom->sc_obufsize = uvscomobufsiz;
+ ucom->sc_ibufsizepad = UVSCOM_IBUFSIZE;
+ ucom->sc_opkthdrlen = 0;
+ }
+#endif
+
+static int
+uvscom_detach(device_t dev)
+{
+ struct umodem_softc *sc = device_get_softc(dev);
+ int error;
+
+ DPRINTF(0, "sc=%p\n", sc);
+
+ __callout_stop(&(sc->sc_watchdog));
+
+ /* stop interrupt pipe */
+
+ if (sc->sc_xfer[4]) {
+ usbd_transfer_stop(sc->sc_xfer[4]);
+ }
+
+ ucom_detach(&(sc->sc_ucom));
+
+ usbd_transfer_unsetup(sc->sc_xfer, UVSCOM_N_TRANSFER);
+
+ /* wait for callbacks to finish */
+
+ while (sc->sc_flag & UMODEM_FLAG_WAIT_USB) {
+
+ error = msleep(&(sc->sc_wakeup_detach), &Giant,
+ PRIBIO, "uvscom_sync", 0);
+ }
+
+ return 0;
+}
+
+static void
+uvscom_watchdog(void *arg)
+{
+ struct uvscom_softc *sc = arg;
+
+ mtx_assert(&Giant, MA_OWNED);
+
+ usbd_transfer_start(sc->sc_xfer[6]);
+
+ __callout_reset(&(sc->sc_watchdog), hz,
+ &(uvscom_watchdog), sc);
+
+ mtx_unlock(&Giant);
+
+ return;
+}
+
+static void
+uvscom_read_status_callback(struct usbd_xfer *xfer)
+{
+ usb_device_request_t *req = xfer->buffer;
+ struct uvscom_softc *sc = xfer->priv_sc;
+
+ USBD_CHECK_STATUS(xfer);
+
+ tr_error:
+ DPRINTF(0, "error=%s\n", usbd_errstr(xfer->error));
+
+ tr_transferred:
+ return;
+
+ tr_setup:
+ req->bmRequestType = UT_READ_VENDOR_DEVICE;
+ req->bRequest = UVSCOM_READ_STATUS;
+ USETW(req->wValue, 0);
+ USETW(req->wIndex, 0);
+ USETW(req->wLength, 2);
+ usbd_start_hardware(xfer);
+ return;
+}
+
+static usbd_status
+uvscom_readstat(struct uvscom_softc *sc)
+{
+ usbd_transfer_start(sc->sc_xfer[6]);
+ return USBD_NORMAL_COMPLETION;
+}
+
+static void
+uvscom_shutdown_callback(struct usbd_xfer *xfer)
+{
+ usb_device_request_t *req = xfer->buffer;
+ struct uvscom_softc *sc = xfer->priv_sc;
+
+ USBD_CHECK_STATUS(xfer);
+
+ tr_error:
+ DPRINTF(0, "error=%s\n", usbd_errstr(xfer->error));
+
+ tr_transferred:
+ return;
+
+ tr_setup:
+ req->bmRequestType = UT_WRITE_VENDOR_DEVICE;
+ req->bRequest = UVSCOM_SHUTDOWN;
+ USETW(req->wValue, 0);
+ USETW(req->wIndex, 0);
+ USETW(req->wLength, 0);
+ usbd_start_hardware(xfer);
+ return;
+}
+
+static void
+uvscom_shutdown(struct uvscom_softc *sc)
+{
+ usbd_transfer_start(sc->sc_xfer[7]);
+ return;
+}
+
+static void
+uvscom_set_line_callback(struct usbd_xfer *xfer)
+{
+ usb_device_request_t *req = xfer->buffer;
+ struct uvscom_softc *sc = xfer->priv_sc;
+
+ USBD_CHECK_STATUS(xfer);
+
+ tr_error:
+ DPRINTF(0, "error=%s\n", usbd_errstr(xfer->error));
+
+ tr_transferred:
+ tr_setup:
+ if (sc->sc_flag & UVSCOM_FLAG_SET_LINE) {
+ sc->sc_flag &= ~UVSCOM_FLAG_SET_LINE;
+
+ req->bmRequestType = UT_WRITE_VENDOR_DEVICE;
+ req->bRequest = UVSCOM_LINE_CTL;
+ USETW(req->wValue, sc->sc_line_ctrl);
+ USETW(req->wIndex, 0);
+ USETW(req->wLength, 0);
+
+ usbd_start_hardware(xfer);
+ }
+ return;
+}
+
+static void
+uvscom_set_line_coding_callback(struct usbd_xfer *xfer)
+{
+ usb_device_request_t *req = xfer->buffer;
+ struct uvscom_softc *sc = xfer->priv_sc;
+
+ USBD_CHECK_STATUS(xfer);
+
+ tr_error:
+ DPRINTF(0, "error=%s\n", usbd_errstr(xfer->error));
+
+ tr_transferred:
+ tr_setup:
+ if (sc->sc_flag & UVSCOM_FLAG_SET_LINE_SPEED) {
+ sc->sc_flag &= ~UVSCOM_FLAG_SET_LINE_SPEED;
+
+ req->bmRequestType = UT_WRITE_VENDOR_DEVICE;
+ req->bRequest = UVSCOM_SET_SPEED;
+ USETW(req->wValue, sc->sc_line_speed);
+ USETW(req->wIndex, 0);
+ USETW(req->wLength, 0);
+ usbd_start_hardware(xfer);
+ return;
+ }
+ if (sc->sc_flag & UVSCOM_FLAG_SET_LINE_PARM) {
+ sc->sc_flag &= ~UVSCOM_FLAG_SET_LINE_PARM;
+
+ req->bmRequestType = UT_WRITE_VENDOR_DEVICE;
+ req->bRequest = UVSCOM_SET_PARAM;
+ USETW(req->wValue, sc->sc_line_parm);
+ USETW(req->wIndex, 0);
+ USETW(req->wLength, 0);
+ usbd_start_hardware(xfer);
+ return;
+ }
+ return;
+}
+
+static void
+uvscom_set_dtr(struct uvscom_softc *sc, u_int8_t onoff)
+{
+ DPRINTF(0, "onoff = %d\n", onoff);
+
+ if (sc->sc_dtr != onoff) {
+ sc->sc_dtr = onoff;
+
+ if (onoff)
+ sc->sc_line_ctrl |= UVSCOM_DTR;
+ else
+ sc->sc_line_ctrl &= ~UVSCOM_DTR;
+
+ sc->sc_flag |= UVSCOM_FLAG_SET_LINE;
+ usbd_transfer_start(sc->sc_xfer[8]);
+ }
+ return;
+}
+
+static void
+uvscom_set_rts(struct uvscom_softc *sc, u_int8_t onoff)
+{
+ DPRINTF(0, "onoff = %d\n", onoff);
+
+ if (sc->sc_rts != onoff) {
+ sc->sc_rts = onoff;
+
+ if (onoff)
+ sc->sc_line_ctrl |= UVSCOM_RTS;
+ else
+ sc->sc_line_ctrl &= ~UVSCOM_RTS;
+
+ sc->sc_flag |= UVSCOM_FLAG_SET_LINE;
+ usbd_transfer_start(sc->sc_xfer[8]);
+ }
+ return;
+}
+
+static void
+uvscom_set_break(struct uvscom_softc *sc, u_int8_t onoff)
+{
+ DPRINTF(0, "onoff = %d\n", onoff);
+
+ if (onoff)
+ sc->sc_line_ctrl |= UVSCOM_BREAK;
+ else
+ sc->sc_line_ctrl &= ~UVSCOM_BREAK;
+
+ sc->sc_flag |= UVSCOM_FLAG_SET_LINE;
+ usbd_transfer_start(sc->sc_xfer[8]);
+ return;
+}
+
+static int
+uvscom_param(struct ucom_softc *ucom, struct termios *t)
+{
+ struct uvscom_softc *sc = ucom->sc_parent;
+
+ DPRINTF(0, "\n");
+
+ switch (t->c_ospeed) {
+ case B150:
+ sc->sc_line_speed = UVSCOM_SPEED_150BPS;
+ break;
+ case B300:
+ sc->sc_line_speed = UVSCOM_SPEED_300BPS;
+ break;
+ case B600:
+ sc->sc_line_speed = UVSCOM_SPEED_600BPS;
+ break;
+ case B1200:
+ sc->sc_line_speed = UVSCOM_SPEED_1200BPS;
+ break;
+ case B2400:
+ sc->sc_line_speed = UVSCOM_SPEED_2400BPS;
+ break;
+ case B4800:
+ sc->sc_line_speed = UVSCOM_SPEED_4800BPS;
+ break;
+ case B9600:
+ sc->sc_line_speed = UVSCOM_SPEED_9600BPS;
+ break;
+ case B19200:
+ sc->sc_line_speed = UVSCOM_SPEED_19200BPS;
+ break;
+ case B38400:
+ sc->sc_line_speed = UVSCOM_SPEED_38400BPS;
+ break;
+ case B57600:
+ sc->sc_line_speed = UVSCOM_SPEED_57600BPS;
+ break;
+ case B115200:
+ sc->sc_line_speed = UVSCOM_SPEED_115200BPS;
+ break;
+ default:
+ return (EIO);
+ }
+
+ sc->sc_line_parm = 0; /* reset */
+
+ sc->sc_line_parm |= ((t->c_cflag & CSTOPB) ?
+ UVSCOM_STOP_BIT_2 : UVSCOM_STOP_BIT_1);
+
+ sc->sc_line_parm |= ((t->c_cflag & PARENB) ?
+ ((t->c_cflag & PARODD) ?
+ UVSCOM_PARITY_ODD :
+ UVSCOM_PARITY_EVEN) :
+ UVSCOM_PARITY_NONE);
+
+ switch (t->c_cflag & CSIZE) {
+ case CS5:
+ sc->sc_line_parm |= UVSCOM_DATA_BIT_5;
+ break;
+ case CS6:
+ sc->sc_line_parm |= UVSCOM_DATA_BIT_6;
+ break;
+ case CS7:
+ sc->sc_line_parm |= UVSCOM_DATA_BIT_7;
+ break;
+ case CS8:
+ sc->sc_line_parm |= UVSCOM_DATA_BIT_8;
+ break;
+ default:
+ return EIO;
+ }
+
+ sc->sc_flag |= (UVSCOM_FLAG_SET_LINE_SPEED|
+ UVSCOM_FLAG_SET_LINE_PARM);
+
+ usbd_transfer_start(sc->sc_xfer[9]);
+
+ return;
+}
+
+static int
+uvscom_open(struct ucom_softc *ucom)
+{
+ struct uvscom_softc *sc = ucom->sc_parent;
+ int err;
+ int i;
+
+ if (sc->sc_ucom.sc_dying)
+ return (ENXIO);
+
+ DPRINTF(("uvscom_open: sc = %p\n", sc));
+
+ /* change output packet size */
+ sc->sc_ucom.sc_obufsize = uvscomobufsiz;
+
+
+ sc->sc_intr_buf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK);
+ err = usbd_open_pipe_intr(sc->sc_ucom.sc_iface,
+ sc->sc_intr_number,
+ USBD_SHORT_XFER_OK,
+ &sc->sc_intr_pipe,
+ sc,
+ sc->sc_intr_buf,
+ sc->sc_isize,
+ uvscom_intr,
+ uvscominterval);
+ if (err) {
+ printf("%s: cannot open interrupt pipe (addr %d)\n",
+ USBDEVNAME(sc->sc_ucom.sc_dev),
+ sc->sc_intr_number);
+ return (ENXIO);
+ }
+ } else {
+ DPRINTF(("uvscom_open: did not open interrupt pipe.\n"));
+ }
+
+ if ((sc->sc_unit_status & UVSCOM_USTAT_MASK) == 0) {
+ /* unit is not ready */
+
+ for (i = UVSCOM_UNIT_WAIT; i > 0; --i) {
+ tsleep(&err, TTIPRI, "uvsop", hz); /* XXX */
+ if (ISSET(sc->sc_unit_status, UVSCOM_USTAT_MASK))
+ break;
+ }
+ if (i == 0) {
+ DPRINTF(("%s: unit is not ready\n",
+ USBDEVNAME(sc->sc_ucom.sc_dev)));
+ return (ENXIO);
+ }
+
+ /* check PC Card was inserted */
+ if (ISSET(sc->sc_unit_status, UVSCOM_NOCARD)) {
+ DPRINTF(("%s: no card\n",
+ USBDEVNAME(sc->sc_ucom.sc_dev)));
+ return (ENXIO);
+ }
+ }
+
+ return (0);
+}
+
+static void
+uvscom_close(struct ucom_softc *ucom)
+{
+ struct uvscom_softc *sc = ucom->sc_parent;
+ int err;
+
+ if (sc->sc_ucom.sc_dying)
+ return;
+
+ DPRINTF(("uvscom_close: close\n"));
+
+ uvscom_shutdown(sc);
+
+ if (sc->sc_intr_pipe != NULL) {
+ err = usbd_abort_pipe(sc->sc_intr_pipe);
+ if (err)
+ printf("%s: abort interrupt pipe failed: %s\n",
+ USBDEVNAME(sc->sc_ucom.sc_dev),
+ usbd_errstr(err));
+ err = usbd_close_pipe(sc->sc_intr_pipe);
+ if (err)
+ printf("%s: close interrupt pipe failed: %s\n",
+ USBDEVNAME(sc->sc_ucom.sc_dev),
+ usbd_errstr(err));
+ free(sc->sc_intr_buf, M_USBDEV);
+ sc->sc_intr_pipe = NULL;
+ }
+}
+
+static void
+uvscom_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
+{
+ struct uvscom_softc *sc = priv;
+ u_int8_t *buf = sc->sc_intr_buf;
+ u_int8_t pstatus;
+
+ if (sc->sc_ucom.sc_dying)
+ return;
+
+ if (status != USBD_NORMAL_COMPLETION) {
+ if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
+ return;
+
+ printf("%s: uvscom_intr: abnormal status: %s\n",
+ USBDEVNAME(sc->sc_ucom.sc_dev),
+ usbd_errstr(status));
+ usbd_clear_endpoint_stall_async(sc->sc_intr_pipe);
+ return;
+ }
+
+ DPRINTFN(2, ("%s: uvscom status = %02x %02x\n",
+ USBDEVNAME(sc->sc_ucom.sc_dev), buf[0], buf[1]));
+
+ sc->sc_lsr = sc->sc_msr = 0;
+ sc->sc_unit_status = buf[1];
+
+ pstatus = buf[0];
+ if (ISSET(pstatus, UVSCOM_TXRDY))
+ SET(sc->sc_lsr, ULSR_TXRDY);
+ if (ISSET(pstatus, UVSCOM_RXRDY))
+ SET(sc->sc_lsr, ULSR_RXRDY);
+
+ pstatus = buf[1];
+ if (ISSET(pstatus, UVSCOM_CTS))
+ SET(sc->sc_msr, SER_CTS);
+ if (ISSET(pstatus, UVSCOM_DSR))
+ SET(sc->sc_msr, SER_DSR);
+ if (ISSET(pstatus, UVSCOM_DCD))
+ SET(sc->sc_msr, SER_DCD);
+
+ if (sc->sc_flag & UVSCOM_FLAG_OPEN) {
+ ucom_status_change(&(sc->sc_ucom));
+ }
+ return;
+}
+
+static void
+uvscom_get_status(struct ucom_softc *ucom, u_int8_t *lsr, u_int8_t *msr)
+{
+ struct uvscom_softc *sc = ucom->sc_parent;
+
+ if (lsr != NULL)
+ *lsr = sc->sc_lsr;
+ if (msr != NULL)
+ *msr = sc->sc_msr;
+}
+
+#if 0 /* TODO */
+static int
+uvscom_ioctl(struct ucom_softc *ucom, u_long cmd, caddr_t data, int flag,
+ usb_proc_ptr p)
+{
+ struct uvscom_softc *sc = ucom->sc_parent;
+ int error = 0;
+
+ if (sc->sc_ucom.sc_dying)
+ return (EIO);
+
+ DPRINTF(("uvscom_ioctl: cmd = 0x%08lx\n", cmd));
+
+ switch (cmd) {
+ case TIOCNOTTY:
+ case TIOCMGET:
+ case TIOCMSET:
+ break;
>>> TRUNCATED FOR MAIL (1000 lines) <<<
More information about the p4-projects
mailing list