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.11 2007/06/28 06:32:33 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>
50 #include <sys/vnode.h>
52 #include <sys/sysctl.h>
54 #include <bus/usb/usb.h>
55 #include <bus/usb/usbcdc.h>
57 #include <bus/usb/usbdi.h>
58 #include <bus/usb/usbdi_util.h>
59 #include <bus/usb/usbdevs.h>
60 #include <bus/usb/usb_quirks.h>
62 #include "../ucom/ucomvar.h"
65 static int uvscomdebug
= 0;
66 SYSCTL_NODE(_hw_usb
, OID_AUTO
, uvscom
, CTLFLAG_RW
, 0, "USB uvscom");
67 SYSCTL_INT(_hw_usb_uvscom
, OID_AUTO
, debug
, CTLFLAG_RW
,
68 &uvscomdebug
, 0, "uvscom debug level");
70 #define DPRINTFN(n, x) do { \
71 if (uvscomdebug > (n)) \
75 #define DPRINTFN(n, x)
77 #define DPRINTF(x) DPRINTFN(0, x)
79 #define UVSCOM_MODVER 1 /* module version */
81 #define UVSCOM_CONFIG_INDEX 0
82 #define UVSCOM_IFACE_INDEX 0
84 #define UVSCOM_INTR_INTERVAL 100 /* mS */
86 #define UVSCOM_UNIT_WAIT 5
89 #define UVSCOM_SET_SPEED 0x10
90 #define UVSCOM_LINE_CTL 0x11
91 #define UVSCOM_SET_PARAM 0x12
92 #define UVSCOM_READ_STATUS 0xd0
93 #define UVSCOM_SHUTDOWN 0xe0
95 /* UVSCOM_SET_SPEED parameters */
96 #define UVSCOM_SPEED_150BPS 0x00
97 #define UVSCOM_SPEED_300BPS 0x01
98 #define UVSCOM_SPEED_600BPS 0x02
99 #define UVSCOM_SPEED_1200BPS 0x03
100 #define UVSCOM_SPEED_2400BPS 0x04
101 #define UVSCOM_SPEED_4800BPS 0x05
102 #define UVSCOM_SPEED_9600BPS 0x06
103 #define UVSCOM_SPEED_19200BPS 0x07
104 #define UVSCOM_SPEED_38400BPS 0x08
105 #define UVSCOM_SPEED_57600BPS 0x09
106 #define UVSCOM_SPEED_115200BPS 0x0a
108 /* UVSCOM_LINE_CTL parameters */
109 #define UVSCOM_BREAK 0x40
110 #define UVSCOM_RTS 0x02
111 #define UVSCOM_DTR 0x01
112 #define UVSCOM_LINE_INIT 0x08
114 /* UVSCOM_SET_PARAM parameters */
115 #define UVSCOM_DATA_MASK 0x03
116 #define UVSCOM_DATA_BIT_8 0x03
117 #define UVSCOM_DATA_BIT_7 0x02
118 #define UVSCOM_DATA_BIT_6 0x01
119 #define UVSCOM_DATA_BIT_5 0x00
121 #define UVSCOM_STOP_MASK 0x04
122 #define UVSCOM_STOP_BIT_2 0x04
123 #define UVSCOM_STOP_BIT_1 0x00
125 #define UVSCOM_PARITY_MASK 0x18
126 #define UVSCOM_PARITY_EVEN 0x18
128 #define UVSCOM_PARITY_UNK 0x10
130 #define UVSCOM_PARITY_ODD 0x08
131 #define UVSCOM_PARITY_NONE 0x00
134 #define UVSCOM_TXRDY 0x04
135 #define UVSCOM_RXRDY 0x01
137 #define UVSCOM_DCD 0x08
138 #define UVSCOM_NOCARD 0x04
139 #define UVSCOM_DSR 0x02
140 #define UVSCOM_CTS 0x01
141 #define UVSCOM_USTAT_MASK (UVSCOM_NOCARD | UVSCOM_DSR | UVSCOM_CTS)
143 struct uvscom_softc
{
144 struct ucom_softc sc_ucom
;
146 int sc_iface_number
;/* interface number */
148 usbd_interface_handle sc_intr_iface
; /* interrupt interface */
149 int sc_intr_number
; /* interrupt number */
150 usbd_pipe_handle sc_intr_pipe
; /* interrupt pipe */
151 u_char
*sc_intr_buf
; /* interrupt buffer */
154 u_char sc_dtr
; /* current DTR state */
155 u_char sc_rts
; /* current RTS state */
157 u_char sc_lsr
; /* Local status register */
158 u_char sc_msr
; /* uvscom status register */
160 uint16_t sc_lcr
; /* Line control */
161 u_char sc_usr
; /* unit status */
165 * These are the maximum number of bytes transferred per frame.
166 * The output buffer size cannot be increased due to the size encoding.
168 #define UVSCOMIBUFSIZE 512
169 #define UVSCOMOBUFSIZE 64
171 static usbd_status
uvscom_shutdown(struct uvscom_softc
*);
172 static usbd_status
uvscom_reset(struct uvscom_softc
*);
173 static usbd_status
uvscom_set_line_coding(struct uvscom_softc
*,
175 static usbd_status
uvscom_set_line(struct uvscom_softc
*, uint16_t);
176 static usbd_status
uvscom_set_crtscts(struct uvscom_softc
*);
177 static void uvscom_get_status(void *, int, u_char
*, u_char
*);
178 static void uvscom_dtr(struct uvscom_softc
*, int);
179 static void uvscom_rts(struct uvscom_softc
*, int);
180 static void uvscom_break(struct uvscom_softc
*, int);
182 static void uvscom_set(void *, int, int, int);
183 static void uvscom_intr(usbd_xfer_handle
, usbd_private_handle
, usbd_status
);
185 static int uvscom_ioctl(void *, int, u_long
, caddr_t
, int, usb_proc_ptr
);
187 static int uvscom_param(void *, int, struct termios
*);
188 static int uvscom_open(void *, int);
189 static void uvscom_close(void *, int);
191 struct ucom_callback uvscom_callback
= {
195 NULL
, /* uvscom_ioctl, TODO */
202 static const struct usb_devno uvscom_devs
[] = {
203 /* SUNTAC U-Cable type D2 */
204 { USB_VENDOR_SUNTAC
, USB_PRODUCT_SUNTAC_DS96L
},
205 /* SUNTAC Ir-Trinity */
206 { USB_VENDOR_SUNTAC
, USB_PRODUCT_SUNTAC_IS96U
},
207 /* SUNTAC U-Cable type P1 */
208 { USB_VENDOR_SUNTAC
, USB_PRODUCT_SUNTAC_PS64P1
},
209 /* SUNTAC Slipper U */
210 { USB_VENDOR_SUNTAC
, USB_PRODUCT_SUNTAC_VS10U
},
212 #define uvscom_lookup(v, p) usb_lookup(uvscom_devs, v, p)
214 static device_probe_t uvscom_match
;
215 static device_attach_t uvscom_attach
;
216 static device_detach_t uvscom_detach
;
218 static device_method_t uvscom_methods
[] = {
219 /* Device interface */
220 DEVMETHOD(device_probe
, uvscom_match
),
221 DEVMETHOD(device_attach
, uvscom_attach
),
222 DEVMETHOD(device_detach
, uvscom_detach
),
226 static driver_t uvscom_driver
= {
229 sizeof (struct uvscom_softc
)
232 DRIVER_MODULE(uvscom
, uhub
, uvscom_driver
, ucom_devclass
, usbd_driver_load
, 0);
233 MODULE_DEPEND(uvscom
, ucom
, UCOM_MINVER
, UCOM_PREFVER
, UCOM_MAXVER
);
234 MODULE_VERSION(uvscom
, UVSCOM_MODVER
);
238 USB_MATCH_START(uvscom
, uaa
);
240 if (uaa
->iface
!= NULL
)
241 return (UMATCH_NONE
);
243 return (uvscom_lookup(uaa
->vendor
, uaa
->product
) != NULL
?
244 UMATCH_VENDOR_PRODUCT
: UMATCH_NONE
);
249 USB_ATTACH_START(uvscom
, sc
, uaa
);
250 usbd_device_handle dev
= uaa
->device
;
251 struct ucom_softc
*ucom
;
252 usb_config_descriptor_t
*cdesc
;
253 usb_interface_descriptor_t
*id
;
254 usb_endpoint_descriptor_t
*ed
;
260 devinfo
= kmalloc(1024, M_USBDEV
, M_INTWAIT
);
263 bzero(sc
, sizeof (struct uvscom_softc
));
265 usbd_devinfo(dev
, 0, devinfo
);
266 /* USB_ATTACH_SETUP; */
268 device_set_desc_copy(self
, devinfo
);
269 /* USB_ATTACH_SETUP; */
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
);
377 USB_ATTACH_SUCCESS_RETURN
;
381 kfree(devinfo
, M_USBDEV
);
382 USB_ATTACH_ERROR_RETURN
;
387 USB_DETACH_START(uvscom
, sc
);
390 DPRINTF(("uvscom_detach: sc = %p\n", sc
));
392 sc
->sc_ucom
.sc_dying
= 1;
394 if (sc
->sc_intr_pipe
!= NULL
) {
395 usbd_abort_pipe(sc
->sc_intr_pipe
);
396 usbd_close_pipe(sc
->sc_intr_pipe
);
397 kfree(sc
->sc_intr_buf
, M_USBDEV
);
398 sc
->sc_intr_pipe
= NULL
;
401 rv
= ucom_detach(&sc
->sc_ucom
);
407 uvscom_readstat(struct uvscom_softc
*sc
)
409 usb_device_request_t req
;
413 DPRINTF(("%s: send readstat\n", device_get_nameunit(sc
->sc_ucom
.sc_dev
)));
415 req
.bmRequestType
= UT_READ_VENDOR_DEVICE
;
416 req
.bRequest
= UVSCOM_READ_STATUS
;
417 USETW(req
.wValue
, 0);
418 USETW(req
.wIndex
, 0);
419 USETW(req
.wLength
, 2);
421 err
= usbd_do_request(sc
->sc_ucom
.sc_udev
, &req
, &r
);
423 kprintf("%s: uvscom_readstat: %s\n",
424 device_get_nameunit(sc
->sc_ucom
.sc_dev
), usbd_errstr(err
));
428 DPRINTF(("%s: uvscom_readstat: r = %d\n",
429 device_get_nameunit(sc
->sc_ucom
.sc_dev
), r
));
431 return (USBD_NORMAL_COMPLETION
);
435 uvscom_shutdown(struct uvscom_softc
*sc
)
437 usb_device_request_t req
;
440 DPRINTF(("%s: send shutdown\n", device_get_nameunit(sc
->sc_ucom
.sc_dev
)));
442 req
.bmRequestType
= UT_WRITE_VENDOR_DEVICE
;
443 req
.bRequest
= UVSCOM_SHUTDOWN
;
444 USETW(req
.wValue
, 0);
445 USETW(req
.wIndex
, 0);
446 USETW(req
.wLength
, 0);
448 err
= usbd_do_request(sc
->sc_ucom
.sc_udev
, &req
, NULL
);
450 kprintf("%s: uvscom_shutdown: %s\n",
451 device_get_nameunit(sc
->sc_ucom
.sc_dev
), usbd_errstr(err
));
455 return (USBD_NORMAL_COMPLETION
);
459 uvscom_reset(struct uvscom_softc
*sc
)
461 DPRINTF(("%s: uvscom_reset\n", device_get_nameunit(sc
->sc_ucom
.sc_dev
)));
463 return (USBD_NORMAL_COMPLETION
);
467 uvscom_set_crtscts(struct uvscom_softc
*sc
)
469 DPRINTF(("%s: uvscom_set_crtscts\n", device_get_nameunit(sc
->sc_ucom
.sc_dev
)));
471 return (USBD_NORMAL_COMPLETION
);
475 uvscom_set_line(struct uvscom_softc
*sc
, uint16_t line
)
477 usb_device_request_t req
;
480 DPRINTF(("%s: uvscom_set_line: %04x\n",
481 device_get_nameunit(sc
->sc_ucom
.sc_dev
), line
));
483 req
.bmRequestType
= UT_WRITE_VENDOR_DEVICE
;
484 req
.bRequest
= UVSCOM_LINE_CTL
;
485 USETW(req
.wValue
, line
);
486 USETW(req
.wIndex
, 0);
487 USETW(req
.wLength
, 0);
489 err
= usbd_do_request(sc
->sc_ucom
.sc_udev
, &req
, NULL
);
491 kprintf("%s: uvscom_set_line: %s\n",
492 device_get_nameunit(sc
->sc_ucom
.sc_dev
), usbd_errstr(err
));
496 return (USBD_NORMAL_COMPLETION
);
500 uvscom_set_line_coding(struct uvscom_softc
*sc
, uint16_t lsp
, uint16_t ls
)
502 usb_device_request_t req
;
505 DPRINTF(("%s: uvscom_set_line_coding: %02x %02x\n",
506 device_get_nameunit(sc
->sc_ucom
.sc_dev
), lsp
, ls
));
508 req
.bmRequestType
= UT_WRITE_VENDOR_DEVICE
;
509 req
.bRequest
= UVSCOM_SET_SPEED
;
510 USETW(req
.wValue
, lsp
);
511 USETW(req
.wIndex
, 0);
512 USETW(req
.wLength
, 0);
514 err
= usbd_do_request(sc
->sc_ucom
.sc_udev
, &req
, NULL
);
516 kprintf("%s: uvscom_set_line_coding: %s\n",
517 device_get_nameunit(sc
->sc_ucom
.sc_dev
), usbd_errstr(err
));
521 req
.bmRequestType
= UT_WRITE_VENDOR_DEVICE
;
522 req
.bRequest
= UVSCOM_SET_PARAM
;
523 USETW(req
.wValue
, ls
);
524 USETW(req
.wIndex
, 0);
525 USETW(req
.wLength
, 0);
527 err
= usbd_do_request(sc
->sc_ucom
.sc_udev
, &req
, NULL
);
529 kprintf("%s: uvscom_set_line_coding: %s\n",
530 device_get_nameunit(sc
->sc_ucom
.sc_dev
), usbd_errstr(err
));
534 return (USBD_NORMAL_COMPLETION
);
538 uvscom_dtr(struct uvscom_softc
*sc
, int onoff
)
540 DPRINTF(("%s: uvscom_dtr: onoff = %d\n",
541 device_get_nameunit(sc
->sc_ucom
.sc_dev
), onoff
));
543 if (sc
->sc_dtr
== onoff
)
544 return; /* no change */
549 SET(sc
->sc_lcr
, UVSCOM_DTR
);
551 CLR(sc
->sc_lcr
, UVSCOM_DTR
);
553 uvscom_set_line(sc
, sc
->sc_lcr
);
557 uvscom_rts(struct uvscom_softc
*sc
, int onoff
)
559 DPRINTF(("%s: uvscom_rts: onoff = %d\n",
560 device_get_nameunit(sc
->sc_ucom
.sc_dev
), onoff
));
562 if (sc
->sc_rts
== onoff
)
563 return; /* no change */
568 SET(sc
->sc_lcr
, UVSCOM_RTS
);
570 CLR(sc
->sc_lcr
, UVSCOM_RTS
);
572 uvscom_set_line(sc
, sc
->sc_lcr
);
576 uvscom_break(struct uvscom_softc
*sc
, int onoff
)
578 DPRINTF(("%s: uvscom_break: onoff = %d\n",
579 device_get_nameunit(sc
->sc_ucom
.sc_dev
), onoff
));
582 uvscom_set_line(sc
, SET(sc
->sc_lcr
, UVSCOM_BREAK
));
586 uvscom_set(void *addr
, int portno
, int reg
, int onoff
)
588 struct uvscom_softc
*sc
= addr
;
592 uvscom_dtr(sc
, onoff
);
595 uvscom_rts(sc
, onoff
);
598 uvscom_break(sc
, onoff
);
606 uvscom_param(void *addr
, int portno
, struct termios
*t
)
608 struct uvscom_softc
*sc
= addr
;
613 DPRINTF(("%s: uvscom_param: sc = %p\n",
614 device_get_nameunit(sc
->sc_ucom
.sc_dev
), sc
));
618 switch (t
->c_ospeed
) {
620 lsp
= UVSCOM_SPEED_150BPS
;
623 lsp
= UVSCOM_SPEED_300BPS
;
626 lsp
= UVSCOM_SPEED_600BPS
;
629 lsp
= UVSCOM_SPEED_1200BPS
;
632 lsp
= UVSCOM_SPEED_2400BPS
;
635 lsp
= UVSCOM_SPEED_4800BPS
;
638 lsp
= UVSCOM_SPEED_9600BPS
;
641 lsp
= UVSCOM_SPEED_19200BPS
;
644 lsp
= UVSCOM_SPEED_38400BPS
;
647 lsp
= UVSCOM_SPEED_57600BPS
;
650 lsp
= UVSCOM_SPEED_115200BPS
;
656 if (ISSET(t
->c_cflag
, CSTOPB
))
657 SET(ls
, UVSCOM_STOP_BIT_2
);
659 SET(ls
, UVSCOM_STOP_BIT_1
);
661 if (ISSET(t
->c_cflag
, PARENB
)) {
662 if (ISSET(t
->c_cflag
, PARODD
))
663 SET(ls
, UVSCOM_PARITY_ODD
);
665 SET(ls
, UVSCOM_PARITY_EVEN
);
667 SET(ls
, UVSCOM_PARITY_NONE
);
669 switch (ISSET(t
->c_cflag
, CSIZE
)) {
671 SET(ls
, UVSCOM_DATA_BIT_5
);
674 SET(ls
, UVSCOM_DATA_BIT_6
);
677 SET(ls
, UVSCOM_DATA_BIT_7
);
680 SET(ls
, UVSCOM_DATA_BIT_8
);
686 err
= uvscom_set_line_coding(sc
, lsp
, ls
);
690 if (ISSET(t
->c_cflag
, CRTSCTS
)) {
691 err
= uvscom_set_crtscts(sc
);
700 uvscom_open(void *addr
, int portno
)
702 struct uvscom_softc
*sc
= addr
;
706 if (sc
->sc_ucom
.sc_dying
)
709 DPRINTF(("uvscom_open: sc = %p\n", sc
));
711 if (sc
->sc_intr_number
!= -1 && sc
->sc_intr_pipe
== NULL
) {
712 DPRINTF(("uvscom_open: open interrupt pipe.\n"));
714 sc
->sc_usr
= 0; /* clear unit status */
716 err
= uvscom_readstat(sc
);
718 DPRINTF(("%s: uvscom_open: readstat faild\n",
719 device_get_nameunit(sc
->sc_ucom
.sc_dev
)));
723 sc
->sc_intr_buf
= kmalloc(sc
->sc_isize
, M_USBDEV
, M_WAITOK
);
724 err
= usbd_open_pipe_intr(sc
->sc_ucom
.sc_iface
,
732 UVSCOM_INTR_INTERVAL
);
734 kprintf("%s: cannot open interrupt pipe (addr %d)\n",
735 device_get_nameunit(sc
->sc_ucom
.sc_dev
),
740 DPRINTF(("uvscom_open: did not open interrupt pipe.\n"));
743 if ((sc
->sc_usr
& UVSCOM_USTAT_MASK
) == 0) {
744 /* unit is not ready */
746 for (i
= UVSCOM_UNIT_WAIT
; i
> 0; --i
) {
747 tsleep(&err
, 0, "uvsop", hz
); /* XXX */
748 if (ISSET(sc
->sc_usr
, UVSCOM_USTAT_MASK
))
752 DPRINTF(("%s: unit is not ready\n",
753 device_get_nameunit(sc
->sc_ucom
.sc_dev
)));
757 /* check PC card was inserted */
758 if (ISSET(sc
->sc_usr
, UVSCOM_NOCARD
)) {
759 DPRINTF(("%s: no card\n",
760 device_get_nameunit(sc
->sc_ucom
.sc_dev
)));
769 uvscom_close(void *addr
, int portno
)
771 struct uvscom_softc
*sc
= addr
;
774 if (sc
->sc_ucom
.sc_dying
)
777 DPRINTF(("uvscom_close: close\n"));
781 if (sc
->sc_intr_pipe
!= NULL
) {
782 err
= usbd_abort_pipe(sc
->sc_intr_pipe
);
784 kprintf("%s: abort interrupt pipe failed: %s\n",
785 device_get_nameunit(sc
->sc_ucom
.sc_dev
),
787 err
= usbd_close_pipe(sc
->sc_intr_pipe
);
789 kprintf("%s: close interrupt pipe failed: %s\n",
790 device_get_nameunit(sc
->sc_ucom
.sc_dev
),
792 kfree(sc
->sc_intr_buf
, M_USBDEV
);
793 sc
->sc_intr_pipe
= NULL
;
798 uvscom_intr(usbd_xfer_handle xfer
, usbd_private_handle priv
, usbd_status status
)
800 struct uvscom_softc
*sc
= priv
;
801 u_char
*buf
= sc
->sc_intr_buf
;
804 if (sc
->sc_ucom
.sc_dying
)
807 if (status
!= USBD_NORMAL_COMPLETION
) {
808 if (status
== USBD_NOT_STARTED
|| status
== USBD_CANCELLED
)
811 kprintf("%s: uvscom_intr: abnormal status: %s\n",
812 device_get_nameunit(sc
->sc_ucom
.sc_dev
),
813 usbd_errstr(status
));
814 usbd_clear_endpoint_stall_async(sc
->sc_intr_pipe
);
818 DPRINTFN(2, ("%s: uvscom status = %02x %02x\n",
819 device_get_nameunit(sc
->sc_ucom
.sc_dev
), buf
[0], buf
[1]));
821 sc
->sc_lsr
= sc
->sc_msr
= 0;
825 if (ISSET(pstatus
, UVSCOM_TXRDY
))
826 SET(sc
->sc_lsr
, ULSR_TXRDY
);
827 if (ISSET(pstatus
, UVSCOM_RXRDY
))
828 SET(sc
->sc_lsr
, ULSR_RXRDY
);
831 if (ISSET(pstatus
, UVSCOM_CTS
))
832 SET(sc
->sc_msr
, UMSR_CTS
);
833 if (ISSET(pstatus
, UVSCOM_DSR
))
834 SET(sc
->sc_msr
, UMSR_DSR
);
835 if (ISSET(pstatus
, UVSCOM_DCD
))
836 SET(sc
->sc_msr
, UMSR_DCD
);
838 ucom_status_change(&sc
->sc_ucom
);
842 uvscom_get_status(void *addr
, int portno
, u_char
*lsr
, u_char
*msr
)
844 struct uvscom_softc
*sc
= addr
;
854 uvscom_ioctl(void *addr
, int portno
, u_long cmd
, caddr_t data
, int flag
,
857 struct uvscom_softc
*sc
= addr
;
860 if (sc
->sc_ucom
.sc_dying
)
863 DPRINTF(("uvscom_ioctl: cmd = 0x%08lx\n", cmd
));
872 DPRINTF(("uvscom_ioctl: unknown\n"));