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.15 2007/08/07 09:18:11 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, struct thread
*);
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
);
237 uvscom_match(device_t self
)
239 struct usb_attach_arg
*uaa
= device_get_ivars(self
);
241 if (uaa
->iface
!= NULL
)
242 return (UMATCH_NONE
);
244 return (uvscom_lookup(uaa
->vendor
, uaa
->product
) != NULL
?
245 UMATCH_VENDOR_PRODUCT
: UMATCH_NONE
);
249 uvscom_attach(device_t self
)
251 struct uvscom_softc
*sc
= device_get_softc(self
);
252 struct usb_attach_arg
*uaa
= device_get_ivars(self
);
253 usbd_device_handle dev
= uaa
->device
;
254 struct ucom_softc
*ucom
;
255 usb_config_descriptor_t
*cdesc
;
256 usb_interface_descriptor_t
*id
;
257 usb_endpoint_descriptor_t
*ed
;
263 devinfo
= kmalloc(1024, M_USBDEV
, M_INTWAIT
);
266 bzero(sc
, sizeof (struct uvscom_softc
));
268 usbd_devinfo(dev
, 0, devinfo
);
270 device_set_desc_copy(self
, devinfo
);
273 ucom
->sc_iface
= uaa
->iface
;
275 devname
= device_get_nameunit(ucom
->sc_dev
);
276 kprintf("%s: %s\n", devname
, devinfo
);
278 DPRINTF(("uvscom attach: sc = %p\n", sc
));
280 /* initialize endpoints */
281 ucom
->sc_bulkin_no
= ucom
->sc_bulkout_no
= -1;
282 sc
->sc_intr_number
= -1;
283 sc
->sc_intr_pipe
= NULL
;
285 /* Move the device into the configured state. */
286 err
= usbd_set_config_index(dev
, UVSCOM_CONFIG_INDEX
, 1);
288 kprintf("%s: failed to set configuration, err=%s\n",
289 devname
, usbd_errstr(err
));
293 /* get the config descriptor */
294 cdesc
= usbd_get_config_descriptor(ucom
->sc_udev
);
297 kprintf("%s: failed to get configuration descriptor\n",
298 device_get_nameunit(ucom
->sc_dev
));
302 /* get the common interface */
303 err
= usbd_device2interface_handle(dev
, UVSCOM_IFACE_INDEX
,
306 kprintf("%s: failed to get interface, err=%s\n",
307 devname
, usbd_errstr(err
));
311 id
= usbd_get_interface_descriptor(ucom
->sc_iface
);
312 sc
->sc_iface_number
= id
->bInterfaceNumber
;
315 for (i
= 0; i
< id
->bNumEndpoints
; i
++) {
316 ed
= usbd_interface2endpoint_descriptor(ucom
->sc_iface
, i
);
318 kprintf("%s: no endpoint descriptor for %d\n",
319 device_get_nameunit(ucom
->sc_dev
), i
);
323 if (UE_GET_DIR(ed
->bEndpointAddress
) == UE_DIR_IN
&&
324 UE_GET_XFERTYPE(ed
->bmAttributes
) == UE_BULK
) {
325 ucom
->sc_bulkin_no
= ed
->bEndpointAddress
;
326 } else if (UE_GET_DIR(ed
->bEndpointAddress
) == UE_DIR_OUT
&&
327 UE_GET_XFERTYPE(ed
->bmAttributes
) == UE_BULK
) {
328 ucom
->sc_bulkout_no
= ed
->bEndpointAddress
;
329 } else if (UE_GET_DIR(ed
->bEndpointAddress
) == UE_DIR_IN
&&
330 UE_GET_XFERTYPE(ed
->bmAttributes
) == UE_INTERRUPT
) {
331 sc
->sc_intr_number
= ed
->bEndpointAddress
;
332 sc
->sc_isize
= UGETW(ed
->wMaxPacketSize
);
336 if (ucom
->sc_bulkin_no
== -1) {
337 kprintf("%s: Could not find data bulk in\n",
338 device_get_nameunit(ucom
->sc_dev
));
341 if (ucom
->sc_bulkout_no
== -1) {
342 kprintf("%s: Could not find data bulk out\n",
343 device_get_nameunit(ucom
->sc_dev
));
346 if (sc
->sc_intr_number
== -1) {
347 kprintf("%s: Could not find interrupt in\n",
348 device_get_nameunit(ucom
->sc_dev
));
352 sc
->sc_dtr
= sc
->sc_rts
= 0;
353 sc
->sc_lcr
= UVSCOM_LINE_INIT
;
355 ucom
->sc_parent
= sc
;
356 ucom
->sc_portno
= UCOM_UNK_PORTNO
;
357 /* bulkin, bulkout set above */
358 ucom
->sc_ibufsize
= UVSCOMIBUFSIZE
;
359 ucom
->sc_obufsize
= UVSCOMOBUFSIZE
;
360 ucom
->sc_ibufsizepad
= UVSCOMIBUFSIZE
;
361 ucom
->sc_opkthdrlen
= 0;
362 ucom
->sc_callback
= &uvscom_callback
;
364 err
= uvscom_reset(sc
);
367 kprintf("%s: reset failed, %s\n", device_get_nameunit(ucom
->sc_dev
),
372 DPRINTF(("uvscom: in = 0x%x out = 0x%x intr = 0x%x\n",
373 ucom
->sc_bulkin_no
, ucom
->sc_bulkout_no
, sc
->sc_intr_number
));
375 ucom_attach(&sc
->sc_ucom
);
377 kfree(devinfo
, M_USBDEV
);
382 kfree(devinfo
, M_USBDEV
);
387 uvscom_detach(device_t self
)
389 struct uvscom_softc
*sc
= device_get_softc(self
);
392 DPRINTF(("uvscom_detach: sc = %p\n", sc
));
394 sc
->sc_ucom
.sc_dying
= 1;
396 if (sc
->sc_intr_pipe
!= NULL
) {
397 usbd_abort_pipe(sc
->sc_intr_pipe
);
398 usbd_close_pipe(sc
->sc_intr_pipe
);
399 kfree(sc
->sc_intr_buf
, M_USBDEV
);
400 sc
->sc_intr_pipe
= NULL
;
403 rv
= ucom_detach(&sc
->sc_ucom
);
409 uvscom_readstat(struct uvscom_softc
*sc
)
411 usb_device_request_t req
;
415 DPRINTF(("%s: send readstat\n", device_get_nameunit(sc
->sc_ucom
.sc_dev
)));
417 req
.bmRequestType
= UT_READ_VENDOR_DEVICE
;
418 req
.bRequest
= UVSCOM_READ_STATUS
;
419 USETW(req
.wValue
, 0);
420 USETW(req
.wIndex
, 0);
421 USETW(req
.wLength
, 2);
423 err
= usbd_do_request(sc
->sc_ucom
.sc_udev
, &req
, &r
);
425 kprintf("%s: uvscom_readstat: %s\n",
426 device_get_nameunit(sc
->sc_ucom
.sc_dev
), usbd_errstr(err
));
430 DPRINTF(("%s: uvscom_readstat: r = %d\n",
431 device_get_nameunit(sc
->sc_ucom
.sc_dev
), r
));
433 return (USBD_NORMAL_COMPLETION
);
437 uvscom_shutdown(struct uvscom_softc
*sc
)
439 usb_device_request_t req
;
442 DPRINTF(("%s: send shutdown\n", device_get_nameunit(sc
->sc_ucom
.sc_dev
)));
444 req
.bmRequestType
= UT_WRITE_VENDOR_DEVICE
;
445 req
.bRequest
= UVSCOM_SHUTDOWN
;
446 USETW(req
.wValue
, 0);
447 USETW(req
.wIndex
, 0);
448 USETW(req
.wLength
, 0);
450 err
= usbd_do_request(sc
->sc_ucom
.sc_udev
, &req
, NULL
);
452 kprintf("%s: uvscom_shutdown: %s\n",
453 device_get_nameunit(sc
->sc_ucom
.sc_dev
), usbd_errstr(err
));
457 return (USBD_NORMAL_COMPLETION
);
461 uvscom_reset(struct uvscom_softc
*sc
)
463 DPRINTF(("%s: uvscom_reset\n", device_get_nameunit(sc
->sc_ucom
.sc_dev
)));
465 return (USBD_NORMAL_COMPLETION
);
469 uvscom_set_crtscts(struct uvscom_softc
*sc
)
471 DPRINTF(("%s: uvscom_set_crtscts\n", device_get_nameunit(sc
->sc_ucom
.sc_dev
)));
473 return (USBD_NORMAL_COMPLETION
);
477 uvscom_set_line(struct uvscom_softc
*sc
, uint16_t line
)
479 usb_device_request_t req
;
482 DPRINTF(("%s: uvscom_set_line: %04x\n",
483 device_get_nameunit(sc
->sc_ucom
.sc_dev
), line
));
485 req
.bmRequestType
= UT_WRITE_VENDOR_DEVICE
;
486 req
.bRequest
= UVSCOM_LINE_CTL
;
487 USETW(req
.wValue
, line
);
488 USETW(req
.wIndex
, 0);
489 USETW(req
.wLength
, 0);
491 err
= usbd_do_request(sc
->sc_ucom
.sc_udev
, &req
, NULL
);
493 kprintf("%s: uvscom_set_line: %s\n",
494 device_get_nameunit(sc
->sc_ucom
.sc_dev
), usbd_errstr(err
));
498 return (USBD_NORMAL_COMPLETION
);
502 uvscom_set_line_coding(struct uvscom_softc
*sc
, uint16_t lsp
, uint16_t ls
)
504 usb_device_request_t req
;
507 DPRINTF(("%s: uvscom_set_line_coding: %02x %02x\n",
508 device_get_nameunit(sc
->sc_ucom
.sc_dev
), lsp
, ls
));
510 req
.bmRequestType
= UT_WRITE_VENDOR_DEVICE
;
511 req
.bRequest
= UVSCOM_SET_SPEED
;
512 USETW(req
.wValue
, lsp
);
513 USETW(req
.wIndex
, 0);
514 USETW(req
.wLength
, 0);
516 err
= usbd_do_request(sc
->sc_ucom
.sc_udev
, &req
, NULL
);
518 kprintf("%s: uvscom_set_line_coding: %s\n",
519 device_get_nameunit(sc
->sc_ucom
.sc_dev
), usbd_errstr(err
));
523 req
.bmRequestType
= UT_WRITE_VENDOR_DEVICE
;
524 req
.bRequest
= UVSCOM_SET_PARAM
;
525 USETW(req
.wValue
, ls
);
526 USETW(req
.wIndex
, 0);
527 USETW(req
.wLength
, 0);
529 err
= usbd_do_request(sc
->sc_ucom
.sc_udev
, &req
, NULL
);
531 kprintf("%s: uvscom_set_line_coding: %s\n",
532 device_get_nameunit(sc
->sc_ucom
.sc_dev
), usbd_errstr(err
));
536 return (USBD_NORMAL_COMPLETION
);
540 uvscom_dtr(struct uvscom_softc
*sc
, int onoff
)
542 DPRINTF(("%s: uvscom_dtr: onoff = %d\n",
543 device_get_nameunit(sc
->sc_ucom
.sc_dev
), onoff
));
545 if (sc
->sc_dtr
== onoff
)
546 return; /* no change */
551 SET(sc
->sc_lcr
, UVSCOM_DTR
);
553 CLR(sc
->sc_lcr
, UVSCOM_DTR
);
555 uvscom_set_line(sc
, sc
->sc_lcr
);
559 uvscom_rts(struct uvscom_softc
*sc
, int onoff
)
561 DPRINTF(("%s: uvscom_rts: onoff = %d\n",
562 device_get_nameunit(sc
->sc_ucom
.sc_dev
), onoff
));
564 if (sc
->sc_rts
== onoff
)
565 return; /* no change */
570 SET(sc
->sc_lcr
, UVSCOM_RTS
);
572 CLR(sc
->sc_lcr
, UVSCOM_RTS
);
574 uvscom_set_line(sc
, sc
->sc_lcr
);
578 uvscom_break(struct uvscom_softc
*sc
, int onoff
)
580 DPRINTF(("%s: uvscom_break: onoff = %d\n",
581 device_get_nameunit(sc
->sc_ucom
.sc_dev
), onoff
));
584 uvscom_set_line(sc
, SET(sc
->sc_lcr
, UVSCOM_BREAK
));
588 uvscom_set(void *addr
, int portno
, int reg
, int onoff
)
590 struct uvscom_softc
*sc
= addr
;
594 uvscom_dtr(sc
, onoff
);
597 uvscom_rts(sc
, onoff
);
600 uvscom_break(sc
, onoff
);
608 uvscom_param(void *addr
, int portno
, struct termios
*t
)
610 struct uvscom_softc
*sc
= addr
;
615 DPRINTF(("%s: uvscom_param: sc = %p\n",
616 device_get_nameunit(sc
->sc_ucom
.sc_dev
), sc
));
620 switch (t
->c_ospeed
) {
622 lsp
= UVSCOM_SPEED_150BPS
;
625 lsp
= UVSCOM_SPEED_300BPS
;
628 lsp
= UVSCOM_SPEED_600BPS
;
631 lsp
= UVSCOM_SPEED_1200BPS
;
634 lsp
= UVSCOM_SPEED_2400BPS
;
637 lsp
= UVSCOM_SPEED_4800BPS
;
640 lsp
= UVSCOM_SPEED_9600BPS
;
643 lsp
= UVSCOM_SPEED_19200BPS
;
646 lsp
= UVSCOM_SPEED_38400BPS
;
649 lsp
= UVSCOM_SPEED_57600BPS
;
652 lsp
= UVSCOM_SPEED_115200BPS
;
658 if (ISSET(t
->c_cflag
, CSTOPB
))
659 SET(ls
, UVSCOM_STOP_BIT_2
);
661 SET(ls
, UVSCOM_STOP_BIT_1
);
663 if (ISSET(t
->c_cflag
, PARENB
)) {
664 if (ISSET(t
->c_cflag
, PARODD
))
665 SET(ls
, UVSCOM_PARITY_ODD
);
667 SET(ls
, UVSCOM_PARITY_EVEN
);
669 SET(ls
, UVSCOM_PARITY_NONE
);
671 switch (ISSET(t
->c_cflag
, CSIZE
)) {
673 SET(ls
, UVSCOM_DATA_BIT_5
);
676 SET(ls
, UVSCOM_DATA_BIT_6
);
679 SET(ls
, UVSCOM_DATA_BIT_7
);
682 SET(ls
, UVSCOM_DATA_BIT_8
);
688 err
= uvscom_set_line_coding(sc
, lsp
, ls
);
692 if (ISSET(t
->c_cflag
, CRTSCTS
)) {
693 err
= uvscom_set_crtscts(sc
);
702 uvscom_open(void *addr
, int portno
)
704 struct uvscom_softc
*sc
= addr
;
708 if (sc
->sc_ucom
.sc_dying
)
711 DPRINTF(("uvscom_open: sc = %p\n", sc
));
713 if (sc
->sc_intr_number
!= -1 && sc
->sc_intr_pipe
== NULL
) {
714 DPRINTF(("uvscom_open: open interrupt pipe.\n"));
716 sc
->sc_usr
= 0; /* clear unit status */
718 err
= uvscom_readstat(sc
);
720 DPRINTF(("%s: uvscom_open: readstat faild\n",
721 device_get_nameunit(sc
->sc_ucom
.sc_dev
)));
725 sc
->sc_intr_buf
= kmalloc(sc
->sc_isize
, M_USBDEV
, M_WAITOK
);
726 err
= usbd_open_pipe_intr(sc
->sc_ucom
.sc_iface
,
734 UVSCOM_INTR_INTERVAL
);
736 kprintf("%s: cannot open interrupt pipe (addr %d)\n",
737 device_get_nameunit(sc
->sc_ucom
.sc_dev
),
742 DPRINTF(("uvscom_open: did not open interrupt pipe.\n"));
745 if ((sc
->sc_usr
& UVSCOM_USTAT_MASK
) == 0) {
746 /* unit is not ready */
748 for (i
= UVSCOM_UNIT_WAIT
; i
> 0; --i
) {
749 tsleep(&err
, 0, "uvsop", hz
); /* XXX */
750 if (ISSET(sc
->sc_usr
, UVSCOM_USTAT_MASK
))
754 DPRINTF(("%s: unit is not ready\n",
755 device_get_nameunit(sc
->sc_ucom
.sc_dev
)));
759 /* check PC card was inserted */
760 if (ISSET(sc
->sc_usr
, UVSCOM_NOCARD
)) {
761 DPRINTF(("%s: no card\n",
762 device_get_nameunit(sc
->sc_ucom
.sc_dev
)));
771 uvscom_close(void *addr
, int portno
)
773 struct uvscom_softc
*sc
= addr
;
776 if (sc
->sc_ucom
.sc_dying
)
779 DPRINTF(("uvscom_close: close\n"));
783 if (sc
->sc_intr_pipe
!= NULL
) {
784 err
= usbd_abort_pipe(sc
->sc_intr_pipe
);
786 kprintf("%s: abort interrupt pipe failed: %s\n",
787 device_get_nameunit(sc
->sc_ucom
.sc_dev
),
789 err
= usbd_close_pipe(sc
->sc_intr_pipe
);
791 kprintf("%s: close interrupt pipe failed: %s\n",
792 device_get_nameunit(sc
->sc_ucom
.sc_dev
),
794 kfree(sc
->sc_intr_buf
, M_USBDEV
);
795 sc
->sc_intr_pipe
= NULL
;
800 uvscom_intr(usbd_xfer_handle xfer
, usbd_private_handle priv
, usbd_status status
)
802 struct uvscom_softc
*sc
= priv
;
803 u_char
*buf
= sc
->sc_intr_buf
;
806 if (sc
->sc_ucom
.sc_dying
)
809 if (status
!= USBD_NORMAL_COMPLETION
) {
810 if (status
== USBD_NOT_STARTED
|| status
== USBD_CANCELLED
)
813 kprintf("%s: uvscom_intr: abnormal status: %s\n",
814 device_get_nameunit(sc
->sc_ucom
.sc_dev
),
815 usbd_errstr(status
));
816 usbd_clear_endpoint_stall_async(sc
->sc_intr_pipe
);
820 DPRINTFN(2, ("%s: uvscom status = %02x %02x\n",
821 device_get_nameunit(sc
->sc_ucom
.sc_dev
), buf
[0], buf
[1]));
823 sc
->sc_lsr
= sc
->sc_msr
= 0;
827 if (ISSET(pstatus
, UVSCOM_TXRDY
))
828 SET(sc
->sc_lsr
, ULSR_TXRDY
);
829 if (ISSET(pstatus
, UVSCOM_RXRDY
))
830 SET(sc
->sc_lsr
, ULSR_RXRDY
);
833 if (ISSET(pstatus
, UVSCOM_CTS
))
834 SET(sc
->sc_msr
, UMSR_CTS
);
835 if (ISSET(pstatus
, UVSCOM_DSR
))
836 SET(sc
->sc_msr
, UMSR_DSR
);
837 if (ISSET(pstatus
, UVSCOM_DCD
))
838 SET(sc
->sc_msr
, UMSR_DCD
);
840 ucom_status_change(&sc
->sc_ucom
);
844 uvscom_get_status(void *addr
, int portno
, u_char
*lsr
, u_char
*msr
)
846 struct uvscom_softc
*sc
= addr
;
856 uvscom_ioctl(void *addr
, int portno
, u_long cmd
, caddr_t data
, int flag
,
859 struct uvscom_softc
*sc
= addr
;
862 if (sc
->sc_ucom
.sc_dying
)
865 DPRINTF(("uvscom_ioctl: cmd = 0x%08lx\n", cmd
));
874 DPRINTF(("uvscom_ioctl: unknown\n"));