2 * Copyright (c) 2001-2002, Shunsuke Akiyama <akiyama@jp.FreeBSD.org>.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * $NetBSD: usb/uvscom.c,v 1.1 2002/03/19 15:08:42 augustss Exp $
27 * $FreeBSD: src/sys/dev/usb/uvscom.c,v 1.19 2003/11/16 12:26:10 akiyama Exp $
28 * $DragonFly: src/sys/dev/usbmisc/uvscom/uvscom.c,v 1.16 2007/08/07 10:42:41 hasso Exp $
32 * uvscom: SUNTAC Slipper U VS-10U driver.
33 * Slipper U is a PC card to USB converter for data communication card
34 * adapter. It supports DDI Pocket's Air H" C@rd, C@rd H" 64, NTT's P-in,
35 * P-in m@ater and various data communication card adapters.
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/kernel.h>
41 #include <sys/malloc.h>
42 #include <sys/fcntl.h>
47 #include <sys/ioccom.h>
48 #include <sys/select.h>
51 #include <sys/sysctl.h>
53 #include <bus/usb/usb.h>
54 #include <bus/usb/usbcdc.h>
56 #include <bus/usb/usbdi.h>
57 #include <bus/usb/usbdi_util.h>
58 #include <bus/usb/usbdevs.h>
59 #include <bus/usb/usb_quirks.h>
61 #include "../ucom/ucomvar.h"
64 static int uvscomdebug
= 0;
65 SYSCTL_NODE(_hw_usb
, OID_AUTO
, uvscom
, CTLFLAG_RW
, 0, "USB uvscom");
66 SYSCTL_INT(_hw_usb_uvscom
, OID_AUTO
, debug
, CTLFLAG_RW
,
67 &uvscomdebug
, 0, "uvscom debug level");
69 #define DPRINTFN(n, x) do { \
70 if (uvscomdebug > (n)) \
74 #define DPRINTFN(n, x)
76 #define DPRINTF(x) DPRINTFN(0, x)
78 #define UVSCOM_MODVER 1 /* module version */
80 #define UVSCOM_CONFIG_INDEX 0
81 #define UVSCOM_IFACE_INDEX 0
83 #define UVSCOM_INTR_INTERVAL 100 /* mS */
85 #define UVSCOM_UNIT_WAIT 5
88 #define UVSCOM_SET_SPEED 0x10
89 #define UVSCOM_LINE_CTL 0x11
90 #define UVSCOM_SET_PARAM 0x12
91 #define UVSCOM_READ_STATUS 0xd0
92 #define UVSCOM_SHUTDOWN 0xe0
94 /* UVSCOM_SET_SPEED parameters */
95 #define UVSCOM_SPEED_150BPS 0x00
96 #define UVSCOM_SPEED_300BPS 0x01
97 #define UVSCOM_SPEED_600BPS 0x02
98 #define UVSCOM_SPEED_1200BPS 0x03
99 #define UVSCOM_SPEED_2400BPS 0x04
100 #define UVSCOM_SPEED_4800BPS 0x05
101 #define UVSCOM_SPEED_9600BPS 0x06
102 #define UVSCOM_SPEED_19200BPS 0x07
103 #define UVSCOM_SPEED_38400BPS 0x08
104 #define UVSCOM_SPEED_57600BPS 0x09
105 #define UVSCOM_SPEED_115200BPS 0x0a
107 /* UVSCOM_LINE_CTL parameters */
108 #define UVSCOM_BREAK 0x40
109 #define UVSCOM_RTS 0x02
110 #define UVSCOM_DTR 0x01
111 #define UVSCOM_LINE_INIT 0x08
113 /* UVSCOM_SET_PARAM parameters */
114 #define UVSCOM_DATA_MASK 0x03
115 #define UVSCOM_DATA_BIT_8 0x03
116 #define UVSCOM_DATA_BIT_7 0x02
117 #define UVSCOM_DATA_BIT_6 0x01
118 #define UVSCOM_DATA_BIT_5 0x00
120 #define UVSCOM_STOP_MASK 0x04
121 #define UVSCOM_STOP_BIT_2 0x04
122 #define UVSCOM_STOP_BIT_1 0x00
124 #define UVSCOM_PARITY_MASK 0x18
125 #define UVSCOM_PARITY_EVEN 0x18
127 #define UVSCOM_PARITY_UNK 0x10
129 #define UVSCOM_PARITY_ODD 0x08
130 #define UVSCOM_PARITY_NONE 0x00
133 #define UVSCOM_TXRDY 0x04
134 #define UVSCOM_RXRDY 0x01
136 #define UVSCOM_DCD 0x08
137 #define UVSCOM_NOCARD 0x04
138 #define UVSCOM_DSR 0x02
139 #define UVSCOM_CTS 0x01
140 #define UVSCOM_USTAT_MASK (UVSCOM_NOCARD | UVSCOM_DSR | UVSCOM_CTS)
142 struct uvscom_softc
{
143 struct ucom_softc sc_ucom
;
145 int sc_iface_number
;/* interface number */
147 usbd_interface_handle sc_intr_iface
; /* interrupt interface */
148 int sc_intr_number
; /* interrupt number */
149 usbd_pipe_handle sc_intr_pipe
; /* interrupt pipe */
150 u_char
*sc_intr_buf
; /* interrupt buffer */
153 u_char sc_dtr
; /* current DTR state */
154 u_char sc_rts
; /* current RTS state */
156 u_char sc_lsr
; /* Local status register */
157 u_char sc_msr
; /* uvscom status register */
159 uint16_t sc_lcr
; /* Line control */
160 u_char sc_usr
; /* unit status */
164 * These are the maximum number of bytes transferred per frame.
165 * The output buffer size cannot be increased due to the size encoding.
167 #define UVSCOMIBUFSIZE 512
168 #define UVSCOMOBUFSIZE 64
170 static usbd_status
uvscom_shutdown(struct uvscom_softc
*);
171 static usbd_status
uvscom_reset(struct uvscom_softc
*);
172 static usbd_status
uvscom_set_line_coding(struct uvscom_softc
*,
174 static usbd_status
uvscom_set_line(struct uvscom_softc
*, uint16_t);
175 static usbd_status
uvscom_set_crtscts(struct uvscom_softc
*);
176 static void uvscom_get_status(void *, int, u_char
*, u_char
*);
177 static void uvscom_dtr(struct uvscom_softc
*, int);
178 static void uvscom_rts(struct uvscom_softc
*, int);
179 static void uvscom_break(struct uvscom_softc
*, int);
181 static void uvscom_set(void *, int, int, int);
182 static void uvscom_intr(usbd_xfer_handle
, usbd_private_handle
, usbd_status
);
184 static int uvscom_ioctl(void *, int, u_long
, caddr_t
, int, struct thread
*);
186 static int uvscom_param(void *, int, struct termios
*);
187 static int uvscom_open(void *, int);
188 static void uvscom_close(void *, int);
190 struct ucom_callback uvscom_callback
= {
194 NULL
, /* uvscom_ioctl, TODO */
201 static const struct usb_devno uvscom_devs
[] = {
202 /* SUNTAC U-Cable type D2 */
203 { USB_VENDOR_SUNTAC
, USB_PRODUCT_SUNTAC_DS96L
},
204 /* SUNTAC Ir-Trinity */
205 { USB_VENDOR_SUNTAC
, USB_PRODUCT_SUNTAC_IS96U
},
206 /* SUNTAC U-Cable type P1 */
207 { USB_VENDOR_SUNTAC
, USB_PRODUCT_SUNTAC_PS64P1
},
208 /* SUNTAC Slipper U */
209 { USB_VENDOR_SUNTAC
, USB_PRODUCT_SUNTAC_VS10U
},
211 #define uvscom_lookup(v, p) usb_lookup(uvscom_devs, v, p)
213 static device_probe_t uvscom_match
;
214 static device_attach_t uvscom_attach
;
215 static device_detach_t uvscom_detach
;
217 static device_method_t uvscom_methods
[] = {
218 /* Device interface */
219 DEVMETHOD(device_probe
, uvscom_match
),
220 DEVMETHOD(device_attach
, uvscom_attach
),
221 DEVMETHOD(device_detach
, uvscom_detach
),
225 static driver_t uvscom_driver
= {
228 sizeof (struct uvscom_softc
)
231 DRIVER_MODULE(uvscom
, uhub
, uvscom_driver
, ucom_devclass
, usbd_driver_load
, 0);
232 MODULE_DEPEND(uvscom
, ucom
, UCOM_MINVER
, UCOM_PREFVER
, UCOM_MAXVER
);
233 MODULE_VERSION(uvscom
, UVSCOM_MODVER
);
236 uvscom_match(device_t self
)
238 struct usb_attach_arg
*uaa
= device_get_ivars(self
);
240 if (uaa
->iface
!= NULL
)
241 return (UMATCH_NONE
);
243 return (uvscom_lookup(uaa
->vendor
, uaa
->product
) != NULL
?
244 UMATCH_VENDOR_PRODUCT
: UMATCH_NONE
);
248 uvscom_attach(device_t self
)
250 struct uvscom_softc
*sc
= device_get_softc(self
);
251 struct usb_attach_arg
*uaa
= device_get_ivars(self
);
252 usbd_device_handle dev
= uaa
->device
;
253 struct ucom_softc
*ucom
;
254 usb_config_descriptor_t
*cdesc
;
255 usb_interface_descriptor_t
*id
;
256 usb_endpoint_descriptor_t
*ed
;
262 devinfo
= kmalloc(1024, M_USBDEV
, M_INTWAIT
);
265 bzero(sc
, sizeof (struct uvscom_softc
));
267 usbd_devinfo(dev
, 0, devinfo
);
269 device_set_desc_copy(self
, devinfo
);
272 ucom
->sc_iface
= uaa
->iface
;
274 devname
= device_get_nameunit(ucom
->sc_dev
);
275 kprintf("%s: %s\n", devname
, devinfo
);
277 DPRINTF(("uvscom attach: sc = %p\n", sc
));
279 /* initialize endpoints */
280 ucom
->sc_bulkin_no
= ucom
->sc_bulkout_no
= -1;
281 sc
->sc_intr_number
= -1;
282 sc
->sc_intr_pipe
= NULL
;
284 /* Move the device into the configured state. */
285 err
= usbd_set_config_index(dev
, UVSCOM_CONFIG_INDEX
, 1);
287 kprintf("%s: failed to set configuration, err=%s\n",
288 devname
, usbd_errstr(err
));
292 /* get the config descriptor */
293 cdesc
= usbd_get_config_descriptor(ucom
->sc_udev
);
296 kprintf("%s: failed to get configuration descriptor\n",
297 device_get_nameunit(ucom
->sc_dev
));
301 /* get the common interface */
302 err
= usbd_device2interface_handle(dev
, UVSCOM_IFACE_INDEX
,
305 kprintf("%s: failed to get interface, err=%s\n",
306 devname
, usbd_errstr(err
));
310 id
= usbd_get_interface_descriptor(ucom
->sc_iface
);
311 sc
->sc_iface_number
= id
->bInterfaceNumber
;
314 for (i
= 0; i
< id
->bNumEndpoints
; i
++) {
315 ed
= usbd_interface2endpoint_descriptor(ucom
->sc_iface
, i
);
317 kprintf("%s: no endpoint descriptor for %d\n",
318 device_get_nameunit(ucom
->sc_dev
), i
);
322 if (UE_GET_DIR(ed
->bEndpointAddress
) == UE_DIR_IN
&&
323 UE_GET_XFERTYPE(ed
->bmAttributes
) == UE_BULK
) {
324 ucom
->sc_bulkin_no
= ed
->bEndpointAddress
;
325 } else if (UE_GET_DIR(ed
->bEndpointAddress
) == UE_DIR_OUT
&&
326 UE_GET_XFERTYPE(ed
->bmAttributes
) == UE_BULK
) {
327 ucom
->sc_bulkout_no
= ed
->bEndpointAddress
;
328 } else if (UE_GET_DIR(ed
->bEndpointAddress
) == UE_DIR_IN
&&
329 UE_GET_XFERTYPE(ed
->bmAttributes
) == UE_INTERRUPT
) {
330 sc
->sc_intr_number
= ed
->bEndpointAddress
;
331 sc
->sc_isize
= UGETW(ed
->wMaxPacketSize
);
335 if (ucom
->sc_bulkin_no
== -1) {
336 kprintf("%s: Could not find data bulk in\n",
337 device_get_nameunit(ucom
->sc_dev
));
340 if (ucom
->sc_bulkout_no
== -1) {
341 kprintf("%s: Could not find data bulk out\n",
342 device_get_nameunit(ucom
->sc_dev
));
345 if (sc
->sc_intr_number
== -1) {
346 kprintf("%s: Could not find interrupt in\n",
347 device_get_nameunit(ucom
->sc_dev
));
351 sc
->sc_dtr
= sc
->sc_rts
= 0;
352 sc
->sc_lcr
= UVSCOM_LINE_INIT
;
354 ucom
->sc_parent
= sc
;
355 ucom
->sc_portno
= UCOM_UNK_PORTNO
;
356 /* bulkin, bulkout set above */
357 ucom
->sc_ibufsize
= UVSCOMIBUFSIZE
;
358 ucom
->sc_obufsize
= UVSCOMOBUFSIZE
;
359 ucom
->sc_ibufsizepad
= UVSCOMIBUFSIZE
;
360 ucom
->sc_opkthdrlen
= 0;
361 ucom
->sc_callback
= &uvscom_callback
;
363 err
= uvscom_reset(sc
);
366 kprintf("%s: reset failed, %s\n", device_get_nameunit(ucom
->sc_dev
),
371 DPRINTF(("uvscom: in = 0x%x out = 0x%x intr = 0x%x\n",
372 ucom
->sc_bulkin_no
, ucom
->sc_bulkout_no
, sc
->sc_intr_number
));
374 ucom_attach(&sc
->sc_ucom
);
376 kfree(devinfo
, M_USBDEV
);
381 kfree(devinfo
, M_USBDEV
);
386 uvscom_detach(device_t self
)
388 struct uvscom_softc
*sc
= device_get_softc(self
);
391 DPRINTF(("uvscom_detach: sc = %p\n", sc
));
393 sc
->sc_ucom
.sc_dying
= 1;
395 if (sc
->sc_intr_pipe
!= NULL
) {
396 usbd_abort_pipe(sc
->sc_intr_pipe
);
397 usbd_close_pipe(sc
->sc_intr_pipe
);
398 kfree(sc
->sc_intr_buf
, M_USBDEV
);
399 sc
->sc_intr_pipe
= NULL
;
402 rv
= ucom_detach(&sc
->sc_ucom
);
408 uvscom_readstat(struct uvscom_softc
*sc
)
410 usb_device_request_t req
;
414 DPRINTF(("%s: send readstat\n", device_get_nameunit(sc
->sc_ucom
.sc_dev
)));
416 req
.bmRequestType
= UT_READ_VENDOR_DEVICE
;
417 req
.bRequest
= UVSCOM_READ_STATUS
;
418 USETW(req
.wValue
, 0);
419 USETW(req
.wIndex
, 0);
420 USETW(req
.wLength
, 2);
422 err
= usbd_do_request(sc
->sc_ucom
.sc_udev
, &req
, &r
);
424 kprintf("%s: uvscom_readstat: %s\n",
425 device_get_nameunit(sc
->sc_ucom
.sc_dev
), usbd_errstr(err
));
429 DPRINTF(("%s: uvscom_readstat: r = %d\n",
430 device_get_nameunit(sc
->sc_ucom
.sc_dev
), r
));
432 return (USBD_NORMAL_COMPLETION
);
436 uvscom_shutdown(struct uvscom_softc
*sc
)
438 usb_device_request_t req
;
441 DPRINTF(("%s: send shutdown\n", device_get_nameunit(sc
->sc_ucom
.sc_dev
)));
443 req
.bmRequestType
= UT_WRITE_VENDOR_DEVICE
;
444 req
.bRequest
= UVSCOM_SHUTDOWN
;
445 USETW(req
.wValue
, 0);
446 USETW(req
.wIndex
, 0);
447 USETW(req
.wLength
, 0);
449 err
= usbd_do_request(sc
->sc_ucom
.sc_udev
, &req
, NULL
);
451 kprintf("%s: uvscom_shutdown: %s\n",
452 device_get_nameunit(sc
->sc_ucom
.sc_dev
), usbd_errstr(err
));
456 return (USBD_NORMAL_COMPLETION
);
460 uvscom_reset(struct uvscom_softc
*sc
)
462 DPRINTF(("%s: uvscom_reset\n", device_get_nameunit(sc
->sc_ucom
.sc_dev
)));
464 return (USBD_NORMAL_COMPLETION
);
468 uvscom_set_crtscts(struct uvscom_softc
*sc
)
470 DPRINTF(("%s: uvscom_set_crtscts\n", device_get_nameunit(sc
->sc_ucom
.sc_dev
)));
472 return (USBD_NORMAL_COMPLETION
);
476 uvscom_set_line(struct uvscom_softc
*sc
, uint16_t line
)
478 usb_device_request_t req
;
481 DPRINTF(("%s: uvscom_set_line: %04x\n",
482 device_get_nameunit(sc
->sc_ucom
.sc_dev
), line
));
484 req
.bmRequestType
= UT_WRITE_VENDOR_DEVICE
;
485 req
.bRequest
= UVSCOM_LINE_CTL
;
486 USETW(req
.wValue
, line
);
487 USETW(req
.wIndex
, 0);
488 USETW(req
.wLength
, 0);
490 err
= usbd_do_request(sc
->sc_ucom
.sc_udev
, &req
, NULL
);
492 kprintf("%s: uvscom_set_line: %s\n",
493 device_get_nameunit(sc
->sc_ucom
.sc_dev
), usbd_errstr(err
));
497 return (USBD_NORMAL_COMPLETION
);
501 uvscom_set_line_coding(struct uvscom_softc
*sc
, uint16_t lsp
, uint16_t ls
)
503 usb_device_request_t req
;
506 DPRINTF(("%s: uvscom_set_line_coding: %02x %02x\n",
507 device_get_nameunit(sc
->sc_ucom
.sc_dev
), lsp
, ls
));
509 req
.bmRequestType
= UT_WRITE_VENDOR_DEVICE
;
510 req
.bRequest
= UVSCOM_SET_SPEED
;
511 USETW(req
.wValue
, lsp
);
512 USETW(req
.wIndex
, 0);
513 USETW(req
.wLength
, 0);
515 err
= usbd_do_request(sc
->sc_ucom
.sc_udev
, &req
, NULL
);
517 kprintf("%s: uvscom_set_line_coding: %s\n",
518 device_get_nameunit(sc
->sc_ucom
.sc_dev
), usbd_errstr(err
));
522 req
.bmRequestType
= UT_WRITE_VENDOR_DEVICE
;
523 req
.bRequest
= UVSCOM_SET_PARAM
;
524 USETW(req
.wValue
, ls
);
525 USETW(req
.wIndex
, 0);
526 USETW(req
.wLength
, 0);
528 err
= usbd_do_request(sc
->sc_ucom
.sc_udev
, &req
, NULL
);
530 kprintf("%s: uvscom_set_line_coding: %s\n",
531 device_get_nameunit(sc
->sc_ucom
.sc_dev
), usbd_errstr(err
));
535 return (USBD_NORMAL_COMPLETION
);
539 uvscom_dtr(struct uvscom_softc
*sc
, int onoff
)
541 DPRINTF(("%s: uvscom_dtr: onoff = %d\n",
542 device_get_nameunit(sc
->sc_ucom
.sc_dev
), onoff
));
544 if (sc
->sc_dtr
== onoff
)
545 return; /* no change */
550 SET(sc
->sc_lcr
, UVSCOM_DTR
);
552 CLR(sc
->sc_lcr
, UVSCOM_DTR
);
554 uvscom_set_line(sc
, sc
->sc_lcr
);
558 uvscom_rts(struct uvscom_softc
*sc
, int onoff
)
560 DPRINTF(("%s: uvscom_rts: onoff = %d\n",
561 device_get_nameunit(sc
->sc_ucom
.sc_dev
), onoff
));
563 if (sc
->sc_rts
== onoff
)
564 return; /* no change */
569 SET(sc
->sc_lcr
, UVSCOM_RTS
);
571 CLR(sc
->sc_lcr
, UVSCOM_RTS
);
573 uvscom_set_line(sc
, sc
->sc_lcr
);
577 uvscom_break(struct uvscom_softc
*sc
, int onoff
)
579 DPRINTF(("%s: uvscom_break: onoff = %d\n",
580 device_get_nameunit(sc
->sc_ucom
.sc_dev
), onoff
));
583 uvscom_set_line(sc
, SET(sc
->sc_lcr
, UVSCOM_BREAK
));
587 uvscom_set(void *addr
, int portno
, int reg
, int onoff
)
589 struct uvscom_softc
*sc
= addr
;
593 uvscom_dtr(sc
, onoff
);
596 uvscom_rts(sc
, onoff
);
599 uvscom_break(sc
, onoff
);
607 uvscom_param(void *addr
, int portno
, struct termios
*t
)
609 struct uvscom_softc
*sc
= addr
;
614 DPRINTF(("%s: uvscom_param: sc = %p\n",
615 device_get_nameunit(sc
->sc_ucom
.sc_dev
), sc
));
619 switch (t
->c_ospeed
) {
621 lsp
= UVSCOM_SPEED_150BPS
;
624 lsp
= UVSCOM_SPEED_300BPS
;
627 lsp
= UVSCOM_SPEED_600BPS
;
630 lsp
= UVSCOM_SPEED_1200BPS
;
633 lsp
= UVSCOM_SPEED_2400BPS
;
636 lsp
= UVSCOM_SPEED_4800BPS
;
639 lsp
= UVSCOM_SPEED_9600BPS
;
642 lsp
= UVSCOM_SPEED_19200BPS
;
645 lsp
= UVSCOM_SPEED_38400BPS
;
648 lsp
= UVSCOM_SPEED_57600BPS
;
651 lsp
= UVSCOM_SPEED_115200BPS
;
657 if (ISSET(t
->c_cflag
, CSTOPB
))
658 SET(ls
, UVSCOM_STOP_BIT_2
);
660 SET(ls
, UVSCOM_STOP_BIT_1
);
662 if (ISSET(t
->c_cflag
, PARENB
)) {
663 if (ISSET(t
->c_cflag
, PARODD
))
664 SET(ls
, UVSCOM_PARITY_ODD
);
666 SET(ls
, UVSCOM_PARITY_EVEN
);
668 SET(ls
, UVSCOM_PARITY_NONE
);
670 switch (ISSET(t
->c_cflag
, CSIZE
)) {
672 SET(ls
, UVSCOM_DATA_BIT_5
);
675 SET(ls
, UVSCOM_DATA_BIT_6
);
678 SET(ls
, UVSCOM_DATA_BIT_7
);
681 SET(ls
, UVSCOM_DATA_BIT_8
);
687 err
= uvscom_set_line_coding(sc
, lsp
, ls
);
691 if (ISSET(t
->c_cflag
, CRTSCTS
)) {
692 err
= uvscom_set_crtscts(sc
);
701 uvscom_open(void *addr
, int portno
)
703 struct uvscom_softc
*sc
= addr
;
707 if (sc
->sc_ucom
.sc_dying
)
710 DPRINTF(("uvscom_open: sc = %p\n", sc
));
712 if (sc
->sc_intr_number
!= -1 && sc
->sc_intr_pipe
== NULL
) {
713 DPRINTF(("uvscom_open: open interrupt pipe.\n"));
715 sc
->sc_usr
= 0; /* clear unit status */
717 err
= uvscom_readstat(sc
);
719 DPRINTF(("%s: uvscom_open: readstat faild\n",
720 device_get_nameunit(sc
->sc_ucom
.sc_dev
)));
724 sc
->sc_intr_buf
= kmalloc(sc
->sc_isize
, M_USBDEV
, M_WAITOK
);
725 err
= usbd_open_pipe_intr(sc
->sc_ucom
.sc_iface
,
733 UVSCOM_INTR_INTERVAL
);
735 kprintf("%s: cannot open interrupt pipe (addr %d)\n",
736 device_get_nameunit(sc
->sc_ucom
.sc_dev
),
741 DPRINTF(("uvscom_open: did not open interrupt pipe.\n"));
744 if ((sc
->sc_usr
& UVSCOM_USTAT_MASK
) == 0) {
745 /* unit is not ready */
747 for (i
= UVSCOM_UNIT_WAIT
; i
> 0; --i
) {
748 tsleep(&err
, 0, "uvsop", hz
); /* XXX */
749 if (ISSET(sc
->sc_usr
, UVSCOM_USTAT_MASK
))
753 DPRINTF(("%s: unit is not ready\n",
754 device_get_nameunit(sc
->sc_ucom
.sc_dev
)));
758 /* check PC card was inserted */
759 if (ISSET(sc
->sc_usr
, UVSCOM_NOCARD
)) {
760 DPRINTF(("%s: no card\n",
761 device_get_nameunit(sc
->sc_ucom
.sc_dev
)));
770 uvscom_close(void *addr
, int portno
)
772 struct uvscom_softc
*sc
= addr
;
775 if (sc
->sc_ucom
.sc_dying
)
778 DPRINTF(("uvscom_close: close\n"));
782 if (sc
->sc_intr_pipe
!= NULL
) {
783 err
= usbd_abort_pipe(sc
->sc_intr_pipe
);
785 kprintf("%s: abort interrupt pipe failed: %s\n",
786 device_get_nameunit(sc
->sc_ucom
.sc_dev
),
788 err
= usbd_close_pipe(sc
->sc_intr_pipe
);
790 kprintf("%s: close interrupt pipe failed: %s\n",
791 device_get_nameunit(sc
->sc_ucom
.sc_dev
),
793 kfree(sc
->sc_intr_buf
, M_USBDEV
);
794 sc
->sc_intr_pipe
= NULL
;
799 uvscom_intr(usbd_xfer_handle xfer
, usbd_private_handle priv
, usbd_status status
)
801 struct uvscom_softc
*sc
= priv
;
802 u_char
*buf
= sc
->sc_intr_buf
;
805 if (sc
->sc_ucom
.sc_dying
)
808 if (status
!= USBD_NORMAL_COMPLETION
) {
809 if (status
== USBD_NOT_STARTED
|| status
== USBD_CANCELLED
)
812 kprintf("%s: uvscom_intr: abnormal status: %s\n",
813 device_get_nameunit(sc
->sc_ucom
.sc_dev
),
814 usbd_errstr(status
));
815 usbd_clear_endpoint_stall_async(sc
->sc_intr_pipe
);
819 DPRINTFN(2, ("%s: uvscom status = %02x %02x\n",
820 device_get_nameunit(sc
->sc_ucom
.sc_dev
), buf
[0], buf
[1]));
822 sc
->sc_lsr
= sc
->sc_msr
= 0;
826 if (ISSET(pstatus
, UVSCOM_TXRDY
))
827 SET(sc
->sc_lsr
, ULSR_TXRDY
);
828 if (ISSET(pstatus
, UVSCOM_RXRDY
))
829 SET(sc
->sc_lsr
, ULSR_RXRDY
);
832 if (ISSET(pstatus
, UVSCOM_CTS
))
833 SET(sc
->sc_msr
, UMSR_CTS
);
834 if (ISSET(pstatus
, UVSCOM_DSR
))
835 SET(sc
->sc_msr
, UMSR_DSR
);
836 if (ISSET(pstatus
, UVSCOM_DCD
))
837 SET(sc
->sc_msr
, UMSR_DCD
);
839 ucom_status_change(&sc
->sc_ucom
);
843 uvscom_get_status(void *addr
, int portno
, u_char
*lsr
, u_char
*msr
)
845 struct uvscom_softc
*sc
= addr
;
855 uvscom_ioctl(void *addr
, int portno
, u_long cmd
, caddr_t data
, int flag
,
858 struct uvscom_softc
*sc
= addr
;
861 if (sc
->sc_ucom
.sc_dying
)
864 DPRINTF(("uvscom_ioctl: cmd = 0x%08lx\n", cmd
));
873 DPRINTF(("uvscom_ioctl: unknown\n"));