1 /* $NetBSD: uplcom.c,v 1.20 2001/07/31 12:33:11 ichiro Exp $ */
2 /* $FreeBSD: src/sys/dev/usb/uplcom.c,v 1.8.2.1 2002/08/08 18:45:04 joe Exp $ */
3 /* $DragonFly: src/sys/dev/usbmisc/uplcom/uplcom.c,v 1.2 2003/06/17 04:28:32 dillon Exp $ */
6 * Copyright (c) 2001-2002, Shunsuke Akiyama <akiyama@jp.FreeBSD.org>.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * Copyright (c) 2001 The NetBSD Foundation, Inc.
33 * All rights reserved.
35 * This code is derived from software contributed to The NetBSD Foundation
36 * by Ichiro FUKUHARA (ichiro@ichiro.org).
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 * notice, this list of conditions and the following disclaimer in the
45 * documentation and/or other materials provided with the distribution.
46 * 3. All advertising materials mentioning features or use of this software
47 * must display the following acknowledgement:
48 * This product includes software developed by the NetBSD
49 * Foundation, Inc. and its contributors.
50 * 4. Neither the name of The NetBSD Foundation nor the names of its
51 * contributors may be used to endorse or promote products derived
52 * from this software without specific prior written permission.
54 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
55 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
56 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
57 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
58 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
59 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
60 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
61 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
62 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
63 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
64 * POSSIBILITY OF SUCH DAMAGE.
69 * http://www.prolific.com.tw/download/DataSheet/pl2303_ds11.PDF
70 * http://www.nisseisg.co.jp/jyouhou/_cp/@gif/2303.pdf
75 #include <sys/param.h>
76 #include <sys/systm.h>
77 #include <sys/kernel.h>
78 #include <sys/malloc.h>
80 #include <sys/ioccom.h>
81 #include <sys/fcntl.h>
85 #if __FreeBSD_version >= 500014
86 #include <sys/selinfo.h>
88 #include <sys/select.h>
91 #include <sys/vnode.h>
93 #include <sys/sysctl.h>
95 #include <dev/usb/usb.h>
96 #include <dev/usb/usbcdc.h>
98 #include <dev/usb/usbdi.h>
99 #include <dev/usb/usbdi_util.h>
100 #include <dev/usb/usbdevs.h>
101 #include <dev/usb/usb_quirks.h>
103 #include <dev/usb/ucomvar.h>
106 static int uplcomdebug = 0;
107 SYSCTL_NODE(_hw_usb, OID_AUTO, uplcom, CTLFLAG_RW, 0, "USB uplcom");
108 SYSCTL_INT(_hw_usb_uplcom, OID_AUTO, debug, CTLFLAG_RW,
109 &uplcomdebug, 0, "uplcom debug level");
111 #define DPRINTFN(n, x) do { \
112 if (uplcomdebug > (n)) \
116 #define DPRINTFN(n, x)
118 #define DPRINTF(x) DPRINTFN(0, x)
120 #define UPLCOM_MODVER 1 /* module version */
122 #define UPLCOM_CONFIG_INDEX 0
123 #define UPLCOM_IFACE_INDEX 0
124 #define UPLCOM_SECOND_IFACE_INDEX 1
126 #define UPLCOM_INTR_INTERVAL 100 /* ms */
128 #define UPLCOM_SET_REQUEST 0x01
129 #define UPLCOM_SET_CRTSCTS 0x41
130 #define RSAQ_STATUS_DSR 0x02
131 #define RSAQ_STATUS_DCD 0x01
133 struct uplcom_softc {
134 struct ucom_softc sc_ucom;
136 int sc_iface_number; /* interface number */
138 usbd_interface_handle sc_intr_iface; /* interrupt interface */
139 int sc_intr_number; /* interrupt number */
140 usbd_pipe_handle sc_intr_pipe; /* interrupt pipe */
141 u_char *sc_intr_buf; /* interrupt buffer */
144 usb_cdc_line_state_t sc_line_state; /* current line state */
145 u_char sc_dtr; /* current DTR state */
146 u_char sc_rts; /* current RTS state */
149 u_char sc_lsr; /* Local status register */
150 u_char sc_msr; /* uplcom status register */
154 * These are the maximum number of bytes transferred per frame.
155 * The output buffer size cannot be increased due to the size encoding.
157 #define UPLCOMIBUFSIZE 256
158 #define UPLCOMOBUFSIZE 256
160 Static usbd_status uplcom_reset(struct uplcom_softc *);
161 Static usbd_status uplcom_set_line_coding(struct uplcom_softc *,
162 usb_cdc_line_state_t *);
163 Static usbd_status uplcom_set_crtscts(struct uplcom_softc *);
164 Static void uplcom_intr(usbd_xfer_handle, usbd_private_handle, usbd_status);
166 Static void uplcom_set(void *, int, int, int);
167 Static void uplcom_dtr(struct uplcom_softc *, int);
168 Static void uplcom_rts(struct uplcom_softc *, int);
169 Static void uplcom_break(struct uplcom_softc *, int);
170 Static void uplcom_set_line_state(struct uplcom_softc *);
171 Static void uplcom_get_status(void *, int, u_char *, u_char *);
173 Static int uplcom_ioctl(void *, int, u_long, caddr_t, int, usb_proc_ptr);
175 Static int uplcom_param(void *, int, struct termios *);
176 Static int uplcom_open(void *, int);
177 Static void uplcom_close(void *, int);
179 struct ucom_callback uplcom_callback = {
183 NULL, /* uplcom_ioctl, TODO */
190 static const struct uplcom_product {
193 } uplcom_products [] = {
194 /* I/O DATA USB-RSAQ */
195 { USB_VENDOR_IODATA, USB_PRODUCT_IODATA_USBRSAQ },
196 /* I/O DATA USB-RSAQ2 */
197 { USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_RSAQ2 },
198 /* PLANEX USB-RS232 URS-03 */
199 { USB_VENDOR_ATEN, USB_PRODUCT_ATEN_UC232A },
200 /* IOGEAR/ATEN UC-232A */
201 { USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2303 },
202 /* TDK USB-PHS Adapter UHA6400 */
203 { USB_VENDOR_TDK, USB_PRODUCT_TDK_UHA6400 },
204 /* RATOC REX-USB60 */
205 { USB_VENDOR_RATOC, USB_PRODUCT_RATOC_REXUSB60 },
207 { USB_VENDOR_ELECOM, USB_PRODUCT_ELECOM_UCSGT },
211 Static device_probe_t uplcom_match;
212 Static device_attach_t uplcom_attach;
213 Static device_detach_t uplcom_detach;
215 Static device_method_t uplcom_methods[] = {
216 /* Device interface */
217 DEVMETHOD(device_probe, uplcom_match),
218 DEVMETHOD(device_attach, uplcom_attach),
219 DEVMETHOD(device_detach, uplcom_detach),
223 Static driver_t uplcom_driver = {
226 sizeof (struct uplcom_softc)
229 DRIVER_MODULE(uplcom, uhub, uplcom_driver, ucom_devclass, usbd_driver_load, 0);
230 MODULE_DEPEND(uplcom, usb, 1, 1, 1);
231 MODULE_DEPEND(uplcom, ucom, UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER);
232 MODULE_VERSION(uplcom, UPLCOM_MODVER);
236 USB_MATCH_START(uplcom, uaa);
239 if (uaa->iface != NULL)
240 return (UMATCH_NONE);
242 for (i = 0; uplcom_products[i].vendor != 0; i++) {
243 if (uplcom_products[i].vendor == uaa->vendor &&
244 uplcom_products[i].product == uaa->product) {
245 return (UMATCH_VENDOR_PRODUCT);
248 return (UMATCH_NONE);
253 USB_ATTACH_START(uplcom, sc, uaa);
254 usbd_device_handle dev = uaa->device;
255 struct ucom_softc *ucom;
256 usb_config_descriptor_t *cdesc;
257 usb_interface_descriptor_t *id;
258 usb_endpoint_descriptor_t *ed;
264 devinfo = malloc(1024, M_USBDEV, M_WAITOK);
267 bzero(sc, sizeof (struct uplcom_softc));
269 usbd_devinfo(dev, 0, devinfo);
270 /* USB_ATTACH_SETUP; */
272 device_set_desc_copy(self, devinfo);
273 /* USB_ATTACH_SETUP; */
276 ucom->sc_iface = uaa->iface;
278 devname = USBDEVNAME(ucom->sc_dev);
279 printf("%s: %s\n", devname, devinfo);
281 DPRINTF(("uplcom attach: sc = %p\n", sc));
283 /* initialize endpoints */
284 ucom->sc_bulkin_no = ucom->sc_bulkout_no = -1;
285 sc->sc_intr_number = -1;
286 sc->sc_intr_pipe = NULL;
288 /* Move the device into the configured state. */
289 err = usbd_set_config_index(dev, UPLCOM_CONFIG_INDEX, 1);
291 printf("%s: failed to set configuration: %s\n",
292 devname, usbd_errstr(err));
297 /* get the config descriptor */
298 cdesc = usbd_get_config_descriptor(ucom->sc_udev);
301 printf("%s: failed to get configuration descriptor\n",
302 USBDEVNAME(ucom->sc_dev));
307 /* get the (first/common) interface */
308 err = usbd_device2interface_handle(dev, UPLCOM_IFACE_INDEX,
311 printf("%s: failed to get interface: %s\n",
312 devname, usbd_errstr(err));
317 /* Find the interrupt endpoints */
319 id = usbd_get_interface_descriptor(ucom->sc_iface);
320 sc->sc_iface_number = id->bInterfaceNumber;
322 for (i = 0; i < id->bNumEndpoints; i++) {
323 ed = usbd_interface2endpoint_descriptor(ucom->sc_iface, i);
325 printf("%s: no endpoint descriptor for %d\n",
326 USBDEVNAME(ucom->sc_dev), i);
331 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
332 UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
333 sc->sc_intr_number = ed->bEndpointAddress;
334 sc->sc_isize = UGETW(ed->wMaxPacketSize);
338 if (sc->sc_intr_number == -1) {
339 printf("%s: Could not find interrupt in\n",
340 USBDEVNAME(ucom->sc_dev));
345 /* keep interface for interrupt */
346 sc->sc_intr_iface = ucom->sc_iface;
349 * USB-RSAQ1 has two interface
351 * USB-RSAQ1 | USB-RSAQ2
352 * -----------------+-----------------
353 * Interface 0 |Interface 0
354 * Interrupt(0x81) | Interrupt(0x81)
355 * -----------------+ BulkIN(0x02)
356 * Interface 1 | BulkOUT(0x83)
360 if (cdesc->bNumInterface == 2) {
361 err = usbd_device2interface_handle(dev,
362 UPLCOM_SECOND_IFACE_INDEX,
365 printf("%s: failed to get second interface: %s\n",
366 devname, usbd_errstr(err));
372 /* Find the bulk{in,out} endpoints */
374 id = usbd_get_interface_descriptor(ucom->sc_iface);
375 sc->sc_iface_number = id->bInterfaceNumber;
377 for (i = 0; i < id->bNumEndpoints; i++) {
378 ed = usbd_interface2endpoint_descriptor(ucom->sc_iface, i);
380 printf("%s: no endpoint descriptor for %d\n",
381 USBDEVNAME(ucom->sc_dev), i);
386 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
387 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
388 ucom->sc_bulkin_no = ed->bEndpointAddress;
389 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
390 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
391 ucom->sc_bulkout_no = ed->bEndpointAddress;
395 if (ucom->sc_bulkin_no == -1) {
396 printf("%s: Could not find data bulk in\n",
397 USBDEVNAME(ucom->sc_dev));
402 if (ucom->sc_bulkout_no == -1) {
403 printf("%s: Could not find data bulk out\n",
404 USBDEVNAME(ucom->sc_dev));
409 sc->sc_dtr = sc->sc_rts = -1;
410 ucom->sc_parent = sc;
411 ucom->sc_portno = UCOM_UNK_PORTNO;
412 /* bulkin, bulkout set above */
413 ucom->sc_ibufsize = UPLCOMIBUFSIZE;
414 ucom->sc_obufsize = UPLCOMOBUFSIZE;
415 ucom->sc_ibufsizepad = UPLCOMIBUFSIZE;
416 ucom->sc_opkthdrlen = 0;
417 ucom->sc_callback = &uplcom_callback;
419 err = uplcom_reset(sc);
422 printf("%s: reset failed: %s\n",
423 USBDEVNAME(ucom->sc_dev), usbd_errstr(err));
428 DPRINTF(("uplcom: in = 0x%x, out = 0x%x, intr = 0x%x\n",
429 ucom->sc_bulkin_no, ucom->sc_bulkout_no, sc->sc_intr_number));
431 ucom_attach(&sc->sc_ucom);
433 free(devinfo, M_USBDEV);
434 USB_ATTACH_SUCCESS_RETURN;
437 free(devinfo, M_USBDEV);
438 USB_ATTACH_ERROR_RETURN;
443 USB_DETACH_START(uplcom, sc);
446 DPRINTF(("uplcom_detach: sc = %p\n", sc));
448 if (sc->sc_intr_pipe != NULL) {
449 usbd_abort_pipe(sc->sc_intr_pipe);
450 usbd_close_pipe(sc->sc_intr_pipe);
451 free(sc->sc_intr_buf, M_USBDEV);
452 sc->sc_intr_pipe = NULL;
455 sc->sc_ucom.sc_dying = 1;
457 rv = ucom_detach(&sc->sc_ucom);
463 uplcom_reset(struct uplcom_softc *sc)
465 usb_device_request_t req;
468 req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
469 req.bRequest = UPLCOM_SET_REQUEST;
470 USETW(req.wValue, 0);
471 USETW(req.wIndex, sc->sc_iface_number);
472 USETW(req.wLength, 0);
474 err = usbd_do_request(sc->sc_ucom.sc_udev, &req, 0);
476 printf("%s: uplcom_reset: %s\n",
477 USBDEVNAME(sc->sc_ucom.sc_dev), usbd_errstr(err));
485 uplcom_set_line_state(struct uplcom_softc *sc)
487 usb_device_request_t req;
491 ls = (sc->sc_dtr ? UCDC_LINE_DTR : 0) |
492 (sc->sc_rts ? UCDC_LINE_RTS : 0);
493 req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
494 req.bRequest = UCDC_SET_CONTROL_LINE_STATE;
495 USETW(req.wValue, ls);
496 USETW(req.wIndex, sc->sc_iface_number);
497 USETW(req.wLength, 0);
499 err = usbd_do_request(sc->sc_ucom.sc_udev, &req, 0);
501 printf("%s: uplcom_set_line_status: %s\n",
502 USBDEVNAME(sc->sc_ucom.sc_dev), usbd_errstr(err));
506 uplcom_set(void *addr, int portno, int reg, int onoff)
508 struct uplcom_softc *sc = addr;
512 uplcom_dtr(sc, onoff);
515 uplcom_rts(sc, onoff);
518 uplcom_break(sc, onoff);
526 uplcom_dtr(struct uplcom_softc *sc, int onoff)
528 DPRINTF(("uplcom_dtr: onoff = %d\n", onoff));
530 if (sc->sc_dtr == onoff)
534 uplcom_set_line_state(sc);
538 uplcom_rts(struct uplcom_softc *sc, int onoff)
540 DPRINTF(("uplcom_rts: onoff = %d\n", onoff));
542 if (sc->sc_rts == onoff)
546 uplcom_set_line_state(sc);
550 uplcom_break(struct uplcom_softc *sc, int onoff)
552 usb_device_request_t req;
555 DPRINTF(("uplcom_break: onoff = %d\n", onoff));
557 req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
558 req.bRequest = UCDC_SEND_BREAK;
559 USETW(req.wValue, onoff ? UCDC_BREAK_ON : UCDC_BREAK_OFF);
560 USETW(req.wIndex, sc->sc_iface_number);
561 USETW(req.wLength, 0);
563 err = usbd_do_request(sc->sc_ucom.sc_udev, &req, 0);
565 printf("%s: uplcom_break: %s\n",
566 USBDEVNAME(sc->sc_ucom.sc_dev), usbd_errstr(err));
570 uplcom_set_crtscts(struct uplcom_softc *sc)
572 usb_device_request_t req;
575 DPRINTF(("uplcom_set_crtscts: on\n"));
577 req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
578 req.bRequest = UPLCOM_SET_REQUEST;
579 USETW(req.wValue, 0);
580 USETW(req.wIndex, UPLCOM_SET_CRTSCTS);
581 USETW(req.wLength, 0);
583 err = usbd_do_request(sc->sc_ucom.sc_udev, &req, 0);
585 printf("%s: uplcom_set_crtscts: %s\n",
586 USBDEVNAME(sc->sc_ucom.sc_dev), usbd_errstr(err));
590 return (USBD_NORMAL_COMPLETION);
594 uplcom_set_line_coding(struct uplcom_softc *sc, usb_cdc_line_state_t *state)
596 usb_device_request_t req;
600 "uplcom_set_line_coding: rate = %d, fmt = %d, parity = %d bits = %d\n",
601 UGETDW(state->dwDTERate), state->bCharFormat,
602 state->bParityType, state->bDataBits));
604 if (memcmp(state, &sc->sc_line_state, UCDC_LINE_STATE_LENGTH) == 0) {
605 DPRINTF(("uplcom_set_line_coding: already set\n"));
606 return (USBD_NORMAL_COMPLETION);
609 req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
610 req.bRequest = UCDC_SET_LINE_CODING;
611 USETW(req.wValue, 0);
612 USETW(req.wIndex, sc->sc_iface_number);
613 USETW(req.wLength, UCDC_LINE_STATE_LENGTH);
615 err = usbd_do_request(sc->sc_ucom.sc_udev, &req, state);
617 printf("%s: uplcom_set_line_coding: %s\n",
618 USBDEVNAME(sc->sc_ucom.sc_dev), usbd_errstr(err));
622 sc->sc_line_state = *state;
624 return (USBD_NORMAL_COMPLETION);
628 uplcom_param(void *addr, int portno, struct termios *t)
630 struct uplcom_softc *sc = addr;
632 usb_cdc_line_state_t ls;
634 DPRINTF(("uplcom_param: sc = %p\n", sc));
636 USETDW(ls.dwDTERate, t->c_ospeed);
637 if (ISSET(t->c_cflag, CSTOPB))
638 ls.bCharFormat = UCDC_STOP_BIT_2;
640 ls.bCharFormat = UCDC_STOP_BIT_1;
641 if (ISSET(t->c_cflag, PARENB)) {
642 if (ISSET(t->c_cflag, PARODD))
643 ls.bParityType = UCDC_PARITY_ODD;
645 ls.bParityType = UCDC_PARITY_EVEN;
647 ls.bParityType = UCDC_PARITY_NONE;
648 switch (ISSET(t->c_cflag, CSIZE)) {
663 err = uplcom_set_line_coding(sc, &ls);
667 if (ISSET(t->c_cflag, CRTSCTS)) {
668 err = uplcom_set_crtscts(sc);
677 uplcom_open(void *addr, int portno)
679 struct uplcom_softc *sc = addr;
682 if (sc->sc_ucom.sc_dying)
685 DPRINTF(("uplcom_open: sc = %p\n", sc));
687 if (sc->sc_intr_number != -1 && sc->sc_intr_pipe == NULL) {
688 sc->sc_status = 0; /* clear status bit */
689 sc->sc_intr_buf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK);
690 err = usbd_open_pipe_intr(sc->sc_intr_iface,
698 UPLCOM_INTR_INTERVAL);
700 printf("%s: cannot open interrupt pipe (addr %d)\n",
701 USBDEVNAME(sc->sc_ucom.sc_dev),
711 uplcom_close(void *addr, int portno)
713 struct uplcom_softc *sc = addr;
716 if (sc->sc_ucom.sc_dying)
719 DPRINTF(("uplcom_close: close\n"));
721 if (sc->sc_intr_pipe != NULL) {
722 err = usbd_abort_pipe(sc->sc_intr_pipe);
724 printf("%s: abort interrupt pipe failed: %s\n",
725 USBDEVNAME(sc->sc_ucom.sc_dev),
727 err = usbd_close_pipe(sc->sc_intr_pipe);
729 printf("%s: close interrupt pipe failed: %s\n",
730 USBDEVNAME(sc->sc_ucom.sc_dev),
732 free(sc->sc_intr_buf, M_USBDEV);
733 sc->sc_intr_pipe = NULL;
738 uplcom_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
740 struct uplcom_softc *sc = priv;
741 u_char *buf = sc->sc_intr_buf;
744 if (sc->sc_ucom.sc_dying)
747 if (status != USBD_NORMAL_COMPLETION) {
748 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
751 DPRINTF(("%s: uplcom_intr: abnormal status: %s\n",
752 USBDEVNAME(sc->sc_ucom.sc_dev),
753 usbd_errstr(status)));
754 usbd_clear_endpoint_stall_async(sc->sc_intr_pipe);
758 DPRINTF(("%s: uplcom status = %02x\n",
759 USBDEVNAME(sc->sc_ucom.sc_dev), buf[8]));
761 sc->sc_lsr = sc->sc_msr = 0;
763 if (ISSET(pstatus, RSAQ_STATUS_DSR))
764 sc->sc_msr |= UMSR_DSR;
765 if (ISSET(pstatus, RSAQ_STATUS_DCD))
766 sc->sc_msr |= UMSR_DCD;
767 ucom_status_change(&sc->sc_ucom);
771 uplcom_get_status(void *addr, int portno, u_char *lsr, u_char *msr)
773 struct uplcom_softc *sc = addr;
775 DPRINTF(("uplcom_get_status:\n"));
785 uplcom_ioctl(void *addr, int portno, u_long cmd, caddr_t data, int flag,
788 struct uplcom_softc *sc = addr;
791 if (sc->sc_ucom.sc_dying)
794 DPRINTF(("uplcom_ioctl: cmd = 0x%08lx\n", cmd));
800 case USB_GET_CM_OVER_DATA:
801 case USB_SET_CM_OVER_DATA:
805 DPRINTF(("uplcom_ioctl: unknown\n"));