Date: Sat, 10 Jun 2006 20:55:14 GMT From: Hans Petter Selasky <hselasky@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 98937 for review Message-ID: <200606102055.k5AKtEWF088344@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=98937 Change 98937 by hselasky@hselasky_mini_itx on 2006/06/10 20:54:54 Finished reworking "ucom.c" and "umodem.c". Affected files ... .. //depot/projects/usb/src/sys/dev/usb/ucom.c#4 edit .. //depot/projects/usb/src/sys/dev/usb/ucomvar.h#4 edit .. //depot/projects/usb/src/sys/dev/usb/umodem.c#4 edit .. //depot/projects/usb/src/sys/dev/usb/usb_cdc.h#1 add Differences ... ==== //depot/projects/usb/src/sys/dev/usb/ucom.c#4 (text+ko) ==== @@ -1,0 +1,742 @@ +/* $NetBSD: ucom.c,v 1.40 2001/11/13 06:24:54 lukem Exp $ */ + +/*- + * Copyright (c) 2001-2003, 2005 Shunsuke Akiyama <akiyama@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. + */ + +/*- + * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Lennart Augustsson (lennart@augustsson.net) at + * Carlstedt Research & Technology. + * + * 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 the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +#include <sys/cdefs.h> +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/malloc.h> +#include <sys/tty.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> + +__FBSDID("$FreeBSD: src/sys/dev/usb/ucom.c $"); + +#ifdef USB_DEBUG +#define DPRINTF(n,fmt,...) \ + do { if (ucom_debug > (n)) { \ + printf("%s: " fmt, __FUNCTION__,## __VA_ARGS__); } } while (0) + +static int ucom_debug = 0; +SYSCTL_NODE(_hw_usb, OID_AUTO, ucom, CTLFLAG_RW, 0, "USB ucom"); +SYSCTL_INT(_hw_usb_ucom, OID_AUTO, debug, CTLFLAG_RW, + &ucom_debug, 0, "ucom debug level"); +#else +#define DPRINTF(...) +#endif + +static void +ucom_shutdown(struct ucom_softc *sc); + +static int +ucom_open(struct tty *tp, struct cdev *dev); + +static void +ucom_close(struct tty *tp); + +static int +ucom_ioctl(struct tty *tp, u_long cmd, void *data, + int flag, struct thread *td); + +static int +ucom_modem(struct tty *tp, int sigon, int sigoff); + +static void +ucom_break(struct tty *tp, int onoff); + +static void +ucom_dtr(struct ucom_softc *sc, u_int8_t onoff); + +static void +ucom_rts(struct ucom_softc *sc, u_int8_t onoff); + +static void +ucom_notify(void *arg, int pending); + +static int +ucom_param(struct tty *tp, struct termios *t); + +static void +ucom_start_write(struct tty *tp); + +static void +ucom_stop_write(struct tty *tp, int fflags); + +devclass_t ucom_devclass; + +static moduledata_t ucom_mod = { + "ucom", + NULL, + NULL +}; + +DECLARE_MODULE(ucom, ucom_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); +MODULE_DEPEND(ucom, usb, 1, 1, 1); +MODULE_VERSION(ucom, UCOM_MODVER); + +int +ucom_attach(struct ucom_softc *sc, device_t dev) +{ + struct tty *tp; + int error = 0; + int unit; + + mtx_assert(&Giant, MA_OWNED); + + unit = device_get_unit(dev); + + tp = ttyalloc(); + + if (tp == NULL) { + error = ENOMEM; + goto done; + } + + tp->t_sc = sc; + tp->t_oproc = ucom_start_write; + tp->t_param = ucom_param; + tp->t_stop = ucom_stop_write; + tp->t_break = ucom_break; + tp->t_open = ucom_open; + tp->t_close = ucom_close; + tp->t_modem = ucom_modem; + tp->t_ioctl = ucom_ioctl; + + DPRINTF(0, "tp = %p\n", tp); + + error = ttycreate(tp, TS_CALLOUT, "U%d", unit); + if (error) { + ttyfree(tp); + goto done; + } + + sc->sc_tty = tp; + + TASK_INIT(&(sc->sc_task), 0, &ucom_notify, sc); + + DPRINTF(0, "ttycreate: ttyU%d\n", unit); + + done: + return error; +} + +void +ucom_detach(struct ucom_softc *sc) +{ + struct tty *tp = sc->sc_tty; + + mtx_assert(&Giant, MA_OWNED); + + DPRINTF(0, "sc = %p, tp = %p\n", sc, sc->sc_tty); + + sc->sc_flag |= UCOM_FLAG_GONE; + + if (tp) { + + ttygone(tp); + + if (tp->t_state & TS_ISOPEN) { + ucom_close(tp); + } + + /* make sure that read and write + * transfers are stopped + */ + if (sc->sc_callback->ucom_stop_read) { + (sc->sc_callback->ucom_stop_read)(sc); + } + + if (sc->sc_callback->ucom_stop_write) { + (sc->sc_callback->ucom_stop_write)(sc); + } + + taskqueue_drain(taskqueue_swi_giant, &(sc->sc_task)); + + ttyfree(tp); + } + return; +} + +static void +ucom_shutdown(struct ucom_softc *sc) +{ + struct tty *tp = sc->sc_tty; + + mtx_assert(&Giant, MA_OWNED); + + DPRINTF(0, "\n"); + /* + * Hang up if necessary: + */ + if (tp->t_cflag & HUPCL) { + ucom_modem(tp, 0, SER_DTR); + } + return; +} + +static int +ucom_open(struct tty *tp, struct cdev *dev) +{ + struct ucom_softc *sc = tp->t_sc; + int error; + + mtx_assert(&Giant, MA_OWNED); + + if (sc->sc_flag & UCOM_FLAG_GONE) { + return ENXIO; + } + + /* + * wait a little for previous commands + * to be flushed out: + */ + error = ttysleep(tp, tp, PCATCH | TTIPRI, "ucomsd", hz); + + if (error) { + return error; + } + + DPRINTF(0, "tp = %p\n", tp); + + sc->sc_poll = 0; + sc->sc_lsr = 0; + sc->sc_msr = 0; + sc->sc_mcr = 0; + + ucom_modem(tp, SER_DTR | SER_RTS, 0); + + /* device specific open */ + + if (sc->sc_callback->ucom_open) { + + error = (sc->sc_callback->ucom_open)(sc); + + if (error) { + ucom_shutdown(sc); + return error; + } + } + + if (sc->sc_callback->ucom_start_read) { + (sc->sc_callback->ucom_start_read)(sc); + } + + sc->sc_poll = 1; + + return 0; +} + +static void +ucom_close(struct tty *tp) +{ + struct ucom_softc *sc = tp->t_sc; + + mtx_assert(&Giant, MA_OWNED); + + DPRINTF(0, "tp=%p\n", tp); + + tp->t_state &= ~TS_BUSY; + + ucom_shutdown(sc); + + if (sc->sc_callback->ucom_stop_read) { + (sc->sc_callback->ucom_stop_read)(sc); + } + + if (sc->sc_callback->ucom_stop_write) { + (sc->sc_callback->ucom_stop_write)(sc); + } + + if (sc->sc_callback->ucom_close) { + (sc->sc_callback->ucom_close)(sc); + } + return; +} + +static int +ucom_ioctl(struct tty *tp, u_long cmd, void *data, + int flag, struct thread *td) +{ + struct ucom_softc *sc = tp->t_sc; + int error; + + mtx_assert(&Giant, MA_OWNED); + + if (sc->sc_flag & UCOM_FLAG_GONE) { + return EIO; + } + + DPRINTF(0, "cmd = 0x%08lx\n", cmd); + + error = ENOTTY; + if (sc->sc_callback->ucom_ioctl) { + error = (sc->sc_callback->ucom_ioctl)(sc, cmd, data, flag, td); + } + return error; +} + +static int +ucom_modem(struct tty *tp, int sigon, int sigoff) +{ + struct ucom_softc *sc = tp->t_sc; + u_int8_t onoff; + + mtx_assert(&Giant, MA_OWNED); + + if (sc->sc_flag & UCOM_FLAG_GONE) { + return 0; + } + + if ((sigon == 0) && (sigoff == 0)) { + + if (sc->sc_mcr & SER_DTR) { + sigon |= SER_DTR; + } + if (sc->sc_mcr & SER_RTS) { + sigon |= SER_RTS; + } + + if (sc->sc_msr & SER_CTS) { + sigon |= SER_CTS; + } + if (sc->sc_msr & SER_DCD) { + sigon |= SER_DCD; + } + if (sc->sc_msr & SER_DSR) { + sigon |= SER_DSR; + } + if (sc->sc_msr & SER_RI) { + sigon |= SER_RI; + } + return sigon; + } + + if (sigon & SER_DTR) { + sc->sc_mcr |= SER_DTR; + } + if (sigoff & SER_DTR) { + sc->sc_mcr &= ~SER_DTR; + } + if (sigon & SER_RTS) { + sc->sc_mcr |= SER_RTS; + } + if (sigoff & SER_RTS) { + sc->sc_mcr &= ~SER_RTS; + } + + onoff = (sc->sc_mcr & SER_DTR) ? 1 : 0; + ucom_dtr(sc, onoff); + + onoff = (sc->sc_mcr & SER_RTS) ? 1 : 0; + ucom_rts(sc, onoff); + + return 0; +} + +static void +ucom_break(struct tty *tp, int onoff) +{ + struct ucom_softc *sc = tp->t_sc; + + mtx_assert(&Giant, MA_OWNED); + + if (sc->sc_flag & UCOM_FLAG_GONE) { + return; + } + + DPRINTF(0, "onoff = %d\n", onoff); + if (sc->sc_callback->ucom_set_break) { + (sc->sc_callback->ucom_set_break)(sc, onoff); + } + return; +} + +static void +ucom_dtr(struct ucom_softc *sc, u_int8_t onoff) +{ + DPRINTF(0, "onoff = %d\n", onoff); + + mtx_assert(&Giant, MA_OWNED); + + if (sc->sc_callback->ucom_set_dtr) { + (sc->sc_callback->ucom_set_dtr)(sc, onoff); + } + return; +} + +static void +ucom_rts(struct ucom_softc *sc, u_int8_t onoff) +{ + DPRINTF(0, "onoff = %d\n", onoff); + + mtx_assert(&Giant, MA_OWNED); + + if (sc->sc_callback->ucom_set_rts) { + (sc->sc_callback->ucom_set_rts)(sc, onoff); + } + return; +} + +void +ucom_status_change(struct ucom_softc *sc) +{ + u_int8_t old_msr; + u_int8_t onoff; + + mtx_assert(&Giant, MA_OWNED); + + if (sc->sc_callback->ucom_get_status == NULL) { + sc->sc_lsr = 0; + sc->sc_msr = 0; + return; + } + + old_msr = sc->sc_msr; + + (sc->sc_callback->ucom_get_status)(sc, &(sc->sc_lsr), &(sc->sc_msr)); + + if ((sc->sc_msr ^ old_msr) & SER_DCD) { + if (sc->sc_poll == 0) { + return; + } + onoff = (sc->sc_msr & SER_DCD) ? 1 : 0; + DPRINTF(0, "DCD changed to %d\n", onoff); + + sc->sc_last_status = onoff; + + /* deferred notifying to the TTY layer */ + taskqueue_enqueue(taskqueue_swi_giant, &(sc->sc_task)); + } + return; +} + +static void +ucom_notify(void *arg, int pending) +{ + struct ucom_softc *sc = arg; + struct tty *tp = sc->sc_tty; + + ttyld_modem(tp, sc->sc_last_status); + + return; +} + +static int +ucom_param(struct tty *tp, struct termios *t) +{ + struct ucom_softc *sc = tp->t_sc; + int error; + + mtx_assert(&Giant, MA_OWNED); + + if (sc->sc_flag & UCOM_FLAG_GONE) { + return EIO; + } + + DPRINTF(0, "sc = %p\n", sc); + + /* Check requested parameters. */ + if (t->c_ospeed < 0) { + DPRINTF(0, "negative ospeed\n"); + return EINVAL; + } + if (t->c_ispeed && (t->c_ispeed != t->c_ospeed)) { + DPRINTF(0, "mismatch ispeed and ospeed\n"); + return EINVAL; + } + + /* + * If there were no changes, don't do anything. This avoids dropping + * input and improves performance when all we did was frob things like + * VMIN and VTIME. + */ + if ((tp->t_ospeed == t->c_ospeed) && + (tp->t_cflag == t->c_cflag)) { + return 0; + } + + /* And copy to tty. */ + tp->t_ispeed = 0; + tp->t_ospeed = t->c_ospeed; + tp->t_cflag = t->c_cflag; + + if (sc->sc_callback->ucom_param == NULL) { + return 0; + } + + if (sc->sc_callback->ucom_stop_read) { + (sc->sc_callback->ucom_stop_read)(sc); + } + + error = (sc->sc_callback->ucom_param)(sc, t); + if (error) { + DPRINTF(0, "callback error = %d\n", error); + return error; + } + + ttsetwater(tp); + + if (t->c_cflag & CRTS_IFLOW) { + sc->sc_flag |= UCOM_FLAG_RTS_IFLOW; + } else if (sc->sc_flag & UCOM_FLAG_RTS_IFLOW) { + sc->sc_flag &= ~UCOM_FLAG_RTS_IFLOW; + ucom_modem(tp, SER_RTS, 0); + } + + ttyldoptim(tp); + + if (sc->sc_callback->ucom_start_read) { + (sc->sc_callback->ucom_start_read)(sc); + } + + return 0; +} + +static void +ucom_start_write(struct tty *tp) +{ + struct ucom_softc *sc = tp->t_sc; + + mtx_assert(&Giant, MA_OWNED); + + DPRINTF(0, "sc = %p\n", sc); + + if (sc->sc_flag & UCOM_FLAG_GONE) { + return; + } + + tp->t_state |= TS_BUSY; + + if (sc->sc_callback->ucom_start_write) { + (sc->sc_callback->ucom_start_write)(sc); + } + return; +} + +static void +ucom_stop_write(struct tty *tp, int fflags) +{ + struct ucom_softc *sc = tp->t_sc; + + mtx_assert(&Giant, MA_OWNED); + + if (sc->sc_flag & UCOM_FLAG_GONE) { + return; + } + + DPRINTF(0, "fflags=%d\n", fflags); + + if (fflags & FWRITE) { + DPRINTF(0, "write\n"); + if (tp->t_state & TS_BUSY) { + /* XXX do what? */ + if (!(tp->t_state & TS_TTSTOP)) { + tp->t_state |= TS_FLUSH; + } + } + } + + ucom_start_write(tp); + + DPRINTF(0, "done\n"); + + return; +} + +/* + * the following function returns + * 1 if data is available, else 0 + */ + +u_int8_t +ucom_get_data(struct ucom_softc *sc, u_int8_t *buf, u_int32_t len, + u_int32_t *actlen) +{ + struct tty *tp = sc->sc_tty; + u_int32_t cnt; + + mtx_assert(&Giant, MA_OWNED); + + actlen[0] = 0; + + if (tp->t_state & TS_TBLOCK) { + if ((sc->sc_mcr & SER_RTS) && + (sc->sc_flag & UCOM_FLAG_RTS_IFLOW)) { + DPRINTF(0, "clear RTS\n"); + ucom_modem(tp, 0, SER_RTS); + } + } else { + if (!(sc->sc_mcr & SER_RTS) && + (tp->t_rawq.c_cc <= tp->t_ilowat) && + (sc->sc_flag & UCOM_FLAG_RTS_IFLOW)) { + DPRINTF(0, "set RTS\n"); + ucom_modem(tp, SER_RTS, 0); + } + } + + if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { + DPRINTF(0, "stopped\n"); + goto done; + } + + cnt = q_to_b(&(tp->t_outq), buf, len); + + if (cnt > len) { + DPRINTF(0, "invalid length, %d bytes\n", cnt); + goto done; + } + + if (cnt == 0) { + DPRINTF(0, "cnt == 0\n"); + goto done; + } + + actlen[0] = cnt; + + ttwwakeup(tp); + + return 1; + + done: + tp->t_state &= ~(TS_BUSY | TS_FLUSH); + + ttwwakeup(tp); + + return 0; +} + +void +ucom_put_data(struct ucom_softc *sc, u_int8_t *ptr, u_int16_t len) +{ + struct tty *tp = sc->sc_tty; + u_int16_t lostcc; + + mtx_assert(&Giant, MA_OWNED); + + /* set a flag to prevent recursation */ + + if (len == 0) { + goto done; + } + + if (tp->t_state & TS_CAN_BYPASS_L_RINT) { + if (((tp->t_rawq.c_cc + len) > tp->t_ihiwat) && + ((sc->sc_flag & UCOM_FLAG_RTS_IFLOW) || + (tp->t_iflag & IXOFF)) && + (!(tp->t_state & TS_TBLOCK))) { + ttyblock(tp); + } + + lostcc = b_to_q(ptr, len, &(tp->t_rawq)); + + tp->t_rawcc += len; + + ttwakeup(tp); + + if ((tp->t_state & TS_TTSTOP) && + ((tp->t_iflag & IXANY) || + (tp->t_cc[VSTART] == tp->t_cc[VSTOP]))) { + tp->t_state &= ~TS_TTSTOP; + tp->t_lflag &= ~FLUSHO; + ucom_start_write(tp); + } + if (lostcc > 0) { + DPRINTF(0, "tp=%p, lost %d " + "chars\n", tp, lostcc); + } + } else { + /* pass characters to tty layer */ + while (len) { + DPRINTF(7, "char = 0x%02x\n", *ptr); + + if (ttyld_rint(tp, *ptr) == -1) { + + /* XXX what should we do? */ + + DPRINTF(0, "tp=%p, lost %d " + "chars\n", tp, len); + break; + } + len--; + ptr++; + } + } + + done: + if ((sc->sc_flag & UCOM_FLAG_RTS_IFLOW) && + (!(sc->sc_mcr & SER_RTS)) && + (!(tp->t_state & TS_TBLOCK))) { + ucom_modem(tp, SER_RTS, 0); + } + return; +} ==== //depot/projects/usb/src/sys/dev/usb/ucomvar.h#4 (text+ko) ==== @@ -71,37 +71,22 @@ #define UCOM_PREFVER UCOM_MODVER #define UCOM_MAXVER 1 -/* Macros to clear/set/test flags. */ -#define SET(t, f) (t) |= (f) -#define CLR(t, f) (t) &= ~((unsigned)(f)) -#define ISSET(t, f) ((t) & (f)) - -#define UCOM_CALLOUT_MASK 0x80 - -#define UCOMUNIT_MASK 0x3ff7f -#define UCOMDIALOUT_MASK 0x80000 -#define UCOMCALLUNIT_MASK 0x40000 - -#define UCOMUNIT(x) (minor(x) & UCOMUNIT_MASK) -#define UCOMDIALOUT(x) (minor(x) & UCOMDIALOUT_MASK) -#define UCOMCALLUNIT(x) (minor(x) & UCOMCALLUNIT_MASK) - -#define UCOM_UNK_PORTNO -1 /* XXX */ - struct ucom_softc; +struct thread; struct ucom_callback { - void (*ucom_get_status)(void *, int, u_char *, u_char *); - void (*ucom_set)(void *, int, int, int); -#define UCOM_SET_DTR 1 -#define UCOM_SET_RTS 2 -#define UCOM_SET_BREAK 3 - int (*ucom_param)(void *, int, struct termios *); - int (*ucom_ioctl)(void *, int, u_long, caddr_t, int, usb_proc_ptr); - int (*ucom_open)(void *, int); - void (*ucom_close)(void *, int); - void (*ucom_read)(void *, int, u_char **, u_int32_t *); - void (*ucom_write)(void *, int, u_char *, u_char *, u_int32_t *); + void (*ucom_get_status)(struct ucom_softc *, u_int8_t *, u_int8_t *); + void (*ucom_set_dtr)(struct ucom_softc *, u_int8_t); + void (*ucom_set_rts)(struct ucom_softc *, u_int8_t); + void (*ucom_set_break)(struct ucom_softc *, u_int8_t); + int (*ucom_param)(struct ucom_softc *, struct termios *); + int (*ucom_ioctl)(struct ucom_softc *, u_long, caddr_t, int, struct thread *); + int (*ucom_open)(struct ucom_softc *); + void (*ucom_close)(struct ucom_softc *); + void (*ucom_start_read)(struct ucom_softc *); + void (*ucom_stop_read)(struct ucom_softc *); + void (*ucom_start_write)(struct ucom_softc *); + void (*ucom_stop_write)(struct ucom_softc *); }; /* line status register */ @@ -115,50 +100,41 @@ #define ULSR_RXRDY 0x01 /* Byte ready in Receive Buffer */ #define ULSR_RCV_MASK 0x1f /* Mask for incoming data or error */ -/* ucom state declarations */ -#define UCS_RXSTOP 0x0001 /* Rx stopped */ -#define UCS_RTS_IFLOW 0x0008 /* use RTS input flow control */ - struct ucom_softc { - USBBASEDEVICE sc_dev; /* base device */ - usbd_device_handle sc_udev; /* USB device */ - usbd_interface_handle sc_iface; /* data interface */ + struct task sc_task; - int sc_bulkin_no; /* bulk in endpoint address */ - usbd_pipe_handle sc_bulkin_pipe; /* bulk in pipe */ - usbd_xfer_handle sc_ixfer; /* read request */ - u_char *sc_ibuf; /* read buffer */ - u_int sc_ibufsize; /* read buffer size */ - u_int sc_ibufsizepad; /* read buffer size padded */ + const struct ucom_callback * sc_callback; + struct tty * sc_tty; + void * sc_parent; - int sc_bulkout_no; /* bulk out endpoint address */ - usbd_pipe_handle sc_bulkout_pipe;/* bulk out pipe */ - usbd_xfer_handle sc_oxfer; /* write request */ - u_char *sc_obuf; /* write buffer */ - u_int sc_obufsize; /* write buffer size */ - u_int sc_opkthdrlen; /* header length of - output packet */ + u_int16_t sc_portno; - struct ucom_callback *sc_callback; - void *sc_parent; - int sc_portno; + u_int8_t sc_flag; +#define UCOM_FLAG_RTS_IFLOW 0x01 /* use RTS input flow control */ +#define UCOM_FLAG_GONE 0x02 /* the device is gone */ - struct tty *sc_tty; /* our tty */ + u_int8_t sc_lsr; + u_int8_t sc_msr; + u_int8_t sc_mcr; + u_int8_t sc_poll; + u_int8_t sc_last_status; +}; - int sc_state; +extern devclass_t ucom_devclass; - int sc_poll; +extern int +ucom_attach(struct ucom_softc *sc, device_t dev); - u_char sc_lsr; - u_char sc_msr; - u_char sc_mcr; +extern void +ucom_detach(struct ucom_softc *); - u_char sc_dying; /* disconnecting */ +extern void +ucom_status_change(struct ucom_softc *); -}; +extern u_int8_t +ucom_get_data(struct ucom_softc *sc, u_int8_t *buf, u_int32_t len, + u_int32_t *actlen); -extern devclass_t ucom_devclass; +extern void +ucom_put_data(struct ucom_softc *sc, u_int8_t *ptr, u_int16_t len); -int ucom_attach(struct ucom_softc *); -int ucom_detach(struct ucom_softc *); -void ucom_status_change(struct ucom_softc *); ==== //depot/projects/usb/src/sys/dev/usb/umodem.c#4 (text+ko) ==== @@ -1,0 +1,1147 @@ +/* $NetBSD: umodem.c,v 1.45 2002/09/23 05:51:23 simonb Exp $ */ + +/*- + * Copyright (c) 2003, M. Warner Losh <imp@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. + */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Lennart Augustsson (lennart@augustsson.net) at + * Carlstedt Research & Technology. + * + * 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 the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +/* + * Comm Class spec: http://www.usb.org/developers/devclass_docs/usbccs10.pdf + * http://www.usb.org/developers/devclass_docs/usbcdc11.pdf + */ + +/* + * TODO: + * - Add error recovery in various places; the big problem is what + * to do in a callback if there is an error. + * - Implement a Call Device for modems without multiplexed commands. + * + */ + +#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 <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/umodem.c $"); + +#ifdef USB_DEBUG +#define DPRINTF(n,fmt,...) \ + do { if (umodem_debug > (n)) { \ + printf("%s: " fmt, __FUNCTION__,## __VA_ARGS__); } } while (0) + +static int umodem_debug = 0; +SYSCTL_NODE(_hw_usb, OID_AUTO, umodem, CTLFLAG_RW, 0, "USB umodem"); +SYSCTL_INT(_hw_usb_umodem, OID_AUTO, debug, CTLFLAG_RW, + &umodem_debug, 0, "umodem debug level"); +#else >>> TRUNCATED FOR MAIL (1000 lines) <<<
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200606102055.k5AKtEWF088344>