1 /* $NetBSD: uvscom.c,v 1.23 2009/09/23 19:07:19 plunky Exp $ */
3 * Copyright (c) 2001-2002, Shunsuke Akiyama <akiyama@jp.FreeBSD.org>.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * $FreeBSD: src/sys/dev/usb/uvscom.c,v 1.1 2002/03/18 18:23:39 joe Exp $
31 * uvscom: SUNTAC Slipper U VS-10U driver.
32 * Slipper U is a PC card to USB converter for data communication card
33 * adapter. It supports DDI Pocket's Air H" C@rd, C@rd H" 64, NTT's P-in,
34 * P-in m@ater and various data communication card adapters.
37 #include <sys/cdefs.h>
38 __KERNEL_RCSID(0, "$NetBSD: uvscom.c,v 1.23 2009/09/23 19:07:19 plunky Exp $");
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/kernel.h>
43 #include <sys/malloc.h>
44 #include <sys/fcntl.h>
48 #if defined(__FreeBSD__)
50 #include <sys/ioccom.h>
51 #if __FreeBSD_version >= 500014
52 #include <sys/selinfo.h>
54 #include <sys/select.h>
57 #include <sys/ioctl.h>
58 #include <sys/device.h>
63 #include <dev/usb/usb.h>
64 #include <dev/usb/usbcdc.h>
66 #include <dev/usb/usbdi.h>
67 #include <dev/usb/usbdi_util.h>
68 #include <dev/usb/usbdevs.h>
69 #include <dev/usb/usb_quirks.h>
71 #include <dev/usb/ucomvar.h>
74 static int uvscomdebug
= 1;
76 #if defined(__FreeBSD__)
77 #include <sys/sysctl.h>
79 SYSCTL_DECL(_debug_usb
);
80 SYSCTL_INT(_debug_usb
, OID_AUTO
, uvscom
, CTLFLAG_RW
,
81 &uvscomdebug
, 0, "uvscom debug level");
85 #define DPRINTFN(n, x) do { \
86 if (uvscomdebug > (n)) \
90 #define DPRINTFN(n, x)
92 #define DPRINTF(x) DPRINTFN(0, x)
94 #if defined(__FreeBSD__)
95 #define UVSCOM_MODVER 1 /* module version */
98 #define UVSCOM_CONFIG_INDEX 0
99 #define UVSCOM_IFACE_INDEX 0
101 #define UVSCOM_INTR_INTERVAL 100 /* mS */
103 #define UVSCOM_UNIT_WAIT 5
106 #define UVSCOM_SET_SPEED 0x10
107 #define UVSCOM_LINE_CTL 0x11
108 #define UVSCOM_SET_PARAM 0x12
109 #define UVSCOM_READ_STATUS 0xd0
110 #define UVSCOM_SHUTDOWN 0xe0
112 /* UVSCOM_SET_SPEED parameters */
113 #define UVSCOM_SPEED_150BPS 0x00
114 #define UVSCOM_SPEED_300BPS 0x01
115 #define UVSCOM_SPEED_600BPS 0x02
116 #define UVSCOM_SPEED_1200BPS 0x03
117 #define UVSCOM_SPEED_2400BPS 0x04
118 #define UVSCOM_SPEED_4800BPS 0x05
119 #define UVSCOM_SPEED_9600BPS 0x06
120 #define UVSCOM_SPEED_19200BPS 0x07
121 #define UVSCOM_SPEED_38400BPS 0x08
122 #define UVSCOM_SPEED_57600BPS 0x09
123 #define UVSCOM_SPEED_115200BPS 0x0a
125 /* UVSCOM_LINE_CTL parameters */
126 #define UVSCOM_BREAK 0x40
127 #define UVSCOM_RTS 0x02
128 #define UVSCOM_DTR 0x01
129 #define UVSCOM_LINE_INIT 0x08
131 /* UVSCOM_SET_PARAM parameters */
132 #define UVSCOM_DATA_MASK 0x03
133 #define UVSCOM_DATA_BIT_8 0x03
134 #define UVSCOM_DATA_BIT_7 0x02
135 #define UVSCOM_DATA_BIT_6 0x01
136 #define UVSCOM_DATA_BIT_5 0x00
138 #define UVSCOM_STOP_MASK 0x04
139 #define UVSCOM_STOP_BIT_2 0x04
140 #define UVSCOM_STOP_BIT_1 0x00
142 #define UVSCOM_PARITY_MASK 0x18
143 #define UVSCOM_PARITY_EVEN 0x18
145 #define UVSCOM_PARITY_UNK 0x10
147 #define UVSCOM_PARITY_ODD 0x08
148 #define UVSCOM_PARITY_NONE 0x00
151 #define UVSCOM_TXRDY 0x04
152 #define UVSCOM_RXRDY 0x01
154 #define UVSCOM_DCD 0x08
155 #define UVSCOM_NOCARD 0x04
156 #define UVSCOM_DSR 0x02
157 #define UVSCOM_CTS 0x01
158 #define UVSCOM_USTAT_MASK (UVSCOM_NOCARD | UVSCOM_DSR | UVSCOM_CTS)
160 struct uvscom_softc
{
161 USBBASEDEVICE sc_dev
; /* base device */
162 usbd_device_handle sc_udev
; /* USB device */
163 usbd_interface_handle sc_iface
; /* interface */
164 int sc_iface_number
;/* interface number */
166 usbd_interface_handle sc_intr_iface
; /* interrupt interface */
167 int sc_intr_number
; /* interrupt number */
168 usbd_pipe_handle sc_intr_pipe
; /* interrupt pipe */
169 u_char
*sc_intr_buf
; /* interrupt buffer */
172 u_char sc_dtr
; /* current DTR state */
173 u_char sc_rts
; /* current RTS state */
175 u_char sc_lsr
; /* Local status register */
176 u_char sc_msr
; /* uvscom status register */
178 uint16_t sc_lcr
; /* Line control */
179 u_char sc_usr
; /* unit status */
181 device_ptr_t sc_subdev
; /* ucom device */
182 u_char sc_dying
; /* disconnecting */
186 * These are the maximum number of bytes transferred per frame.
187 * The output buffer size cannot be increased due to the size encoding.
189 #define UVSCOMIBUFSIZE 512
190 #define UVSCOMOBUFSIZE 64
192 Static usbd_status
uvscom_readstat(struct uvscom_softc
*);
193 Static usbd_status
uvscom_shutdown(struct uvscom_softc
*);
194 Static usbd_status
uvscom_reset(struct uvscom_softc
*);
195 Static usbd_status
uvscom_set_line_coding(struct uvscom_softc
*,
197 Static usbd_status
uvscom_set_line(struct uvscom_softc
*, uint16_t);
198 Static usbd_status
uvscom_set_crtscts(struct uvscom_softc
*);
199 Static
void uvscom_get_status(void *, int, u_char
*, u_char
*);
200 Static
void uvscom_dtr(struct uvscom_softc
*, int);
201 Static
void uvscom_rts(struct uvscom_softc
*, int);
202 Static
void uvscom_break(struct uvscom_softc
*, int);
204 Static
void uvscom_set(void *, int, int, int);
205 Static
void uvscom_intr(usbd_xfer_handle
, usbd_private_handle
, usbd_status
);
206 Static
int uvscom_param(void *, int, struct termios
*);
207 Static
int uvscom_open(void *, int);
208 Static
void uvscom_close(void *, int);
210 struct ucom_methods uvscom_methods
= {
214 NULL
, /* uvscom_ioctl, TODO */
221 static const struct usb_devno uvscom_devs
[] = {
222 /* SUNTAC U-Cable type A4 */
223 { USB_VENDOR_SUNTAC
, USB_PRODUCT_SUNTAC_AS144L4
},
224 /* SUNTAC U-Cable type D2 */
225 { USB_VENDOR_SUNTAC
, USB_PRODUCT_SUNTAC_DS96L
},
226 /* SUNTAC U-Cable type P1 */
227 { USB_VENDOR_SUNTAC
, USB_PRODUCT_SUNTAC_PS64P1
},
228 /* SUNTAC Slipper U */
229 { USB_VENDOR_SUNTAC
, USB_PRODUCT_SUNTAC_VS10U
},
230 /* SUNTAC Ir-Trinity */
231 { USB_VENDOR_SUNTAC
, USB_PRODUCT_SUNTAC_IS96U
},
233 #define uvscom_lookup(v, p) usb_lookup(uvscom_devs, v, p)
235 int uvscom_match(device_t
, cfdata_t
, void *);
236 void uvscom_attach(device_t
, device_t
, void *);
237 void uvscom_childdet(device_t
, device_t
);
238 int uvscom_detach(device_t
, int);
239 int uvscom_activate(device_t
, enum devact
);
240 extern struct cfdriver uvscom_cd
;
241 CFATTACH_DECL2_NEW(uvscom
, sizeof(struct uvscom_softc
), uvscom_match
,
242 uvscom_attach
, uvscom_detach
, uvscom_activate
, NULL
, uvscom_childdet
);
246 USB_MATCH_START(uvscom
, uaa
);
248 return (uvscom_lookup(uaa
->vendor
, uaa
->product
) != NULL
?
249 UMATCH_VENDOR_PRODUCT
: UMATCH_NONE
);
254 USB_ATTACH_START(uvscom
, sc
, uaa
);
255 usbd_device_handle dev
= uaa
->device
;
256 usb_config_descriptor_t
*cdesc
;
257 usb_interface_descriptor_t
*id
;
258 usb_endpoint_descriptor_t
*ed
;
262 struct ucom_attach_args uca
;
267 devinfop
= usbd_devinfo_alloc(dev
, 0);
268 aprint_normal_dev(self
, "%s\n", devinfop
);
269 usbd_devinfo_free(devinfop
);
274 DPRINTF(("uvscom attach: sc = %p\n", sc
));
276 /* initialize endpoints */
277 uca
.bulkin
= uca
.bulkout
= -1;
278 sc
->sc_intr_number
= -1;
279 sc
->sc_intr_pipe
= NULL
;
281 /* Move the device into the configured state. */
282 err
= usbd_set_config_index(dev
, UVSCOM_CONFIG_INDEX
, 1);
284 aprint_error_dev(self
, "failed to set configuration, err=%s\n",
287 USB_ATTACH_ERROR_RETURN
;
290 /* get the config descriptor */
291 cdesc
= usbd_get_config_descriptor(sc
->sc_udev
);
294 aprint_error_dev(self
,
295 "failed to get configuration descriptor\n");
297 USB_ATTACH_ERROR_RETURN
;
300 /* get the common interface */
301 err
= usbd_device2interface_handle(dev
, UVSCOM_IFACE_INDEX
,
304 aprint_error_dev(self
, "failed to get interface, err=%s\n",
307 USB_ATTACH_ERROR_RETURN
;
310 id
= usbd_get_interface_descriptor(sc
->sc_iface
);
311 sc
->sc_iface_number
= id
->bInterfaceNumber
;
314 for (i
= 0; i
< id
->bNumEndpoints
; i
++) {
315 ed
= usbd_interface2endpoint_descriptor(sc
->sc_iface
, i
);
317 aprint_error_dev(self
,
318 "no endpoint descriptor for %d\n", i
);
320 USB_ATTACH_ERROR_RETURN
;
323 if (UE_GET_DIR(ed
->bEndpointAddress
) == UE_DIR_IN
&&
324 UE_GET_XFERTYPE(ed
->bmAttributes
) == UE_BULK
) {
325 uca
.bulkin
= ed
->bEndpointAddress
;
326 } else if (UE_GET_DIR(ed
->bEndpointAddress
) == UE_DIR_OUT
&&
327 UE_GET_XFERTYPE(ed
->bmAttributes
) == UE_BULK
) {
328 uca
.bulkout
= 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 (uca
.bulkin
== -1) {
337 aprint_error_dev(self
, "Could not find data bulk in\n");
339 USB_ATTACH_ERROR_RETURN
;
341 if (uca
.bulkout
== -1) {
342 aprint_error_dev(self
, "Could not find data bulk out\n");
344 USB_ATTACH_ERROR_RETURN
;
346 if (sc
->sc_intr_number
== -1) {
347 aprint_error_dev(self
, "Could not find interrupt in\n");
349 USB_ATTACH_ERROR_RETURN
;
352 sc
->sc_dtr
= sc
->sc_rts
= 0;
353 sc
->sc_lcr
= UVSCOM_LINE_INIT
;
355 uca
.portno
= UCOM_UNK_PORTNO
;
356 /* bulkin, bulkout set above */
357 uca
.ibufsize
= UVSCOMIBUFSIZE
;
358 uca
.obufsize
= UVSCOMOBUFSIZE
;
359 uca
.ibufsizepad
= UVSCOMIBUFSIZE
;
362 uca
.iface
= sc
->sc_iface
;
363 uca
.methods
= &uvscom_methods
;
367 err
= uvscom_reset(sc
);
370 aprint_error_dev(self
, "reset failed, %s\n", usbd_errstr(err
));
372 USB_ATTACH_ERROR_RETURN
;
375 DPRINTF(("uvscom: in = 0x%x out = 0x%x intr = 0x%x\n",
376 uca
.bulkin
, uca
.bulkout
, sc
->sc_intr_number
));
378 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH
, sc
->sc_udev
,
381 DPRINTF(("uplcom: in=0x%x out=0x%x intr=0x%x\n",
382 uca
.bulkin
, uca
.bulkout
, sc
->sc_intr_number
));
383 sc
->sc_subdev
= config_found_sm_loc(self
, "ucombus", NULL
, &uca
,
384 ucomprint
, ucomsubmatch
);
386 USB_ATTACH_SUCCESS_RETURN
;
390 uvscom_childdet(device_t self
, device_t child
)
392 struct uvscom_softc
*sc
= device_private(self
);
394 KASSERT(sc
->sc_subdev
== child
);
395 sc
->sc_subdev
= NULL
;
400 USB_DETACH_START(uvscom
, sc
);
403 DPRINTF(("uvscom_detach: sc = %p\n", sc
));
407 if (sc
->sc_intr_pipe
!= NULL
) {
408 usbd_abort_pipe(sc
->sc_intr_pipe
);
409 usbd_close_pipe(sc
->sc_intr_pipe
);
410 free(sc
->sc_intr_buf
, M_USBDEV
);
411 sc
->sc_intr_pipe
= NULL
;
415 if (sc
->sc_subdev
!= NULL
)
416 rv
= config_detach(sc
->sc_subdev
, flags
);
418 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH
, sc
->sc_udev
,
425 uvscom_activate(device_t self
, enum devact act
)
427 struct uvscom_softc
*sc
= device_private(self
);
430 case DVACT_DEACTIVATE
:
439 uvscom_readstat(struct uvscom_softc
*sc
)
441 usb_device_request_t req
;
445 DPRINTF(("%s: send readstat\n", USBDEVNAME(sc
->sc_dev
)));
447 req
.bmRequestType
= UT_READ_VENDOR_DEVICE
;
448 req
.bRequest
= UVSCOM_READ_STATUS
;
449 USETW(req
.wValue
, 0);
450 USETW(req
.wIndex
, 0);
451 USETW(req
.wLength
, 2);
453 err
= usbd_do_request(sc
->sc_udev
, &req
, &r
);
455 aprint_error_dev(sc
->sc_dev
, "uvscom_readstat: %s\n",
460 DPRINTF(("%s: uvscom_readstat: r = %d\n",
461 USBDEVNAME(sc
->sc_dev
), r
));
463 return (USBD_NORMAL_COMPLETION
);
467 uvscom_shutdown(struct uvscom_softc
*sc
)
469 usb_device_request_t req
;
472 DPRINTF(("%s: send shutdown\n", USBDEVNAME(sc
->sc_dev
)));
474 req
.bmRequestType
= UT_WRITE_VENDOR_DEVICE
;
475 req
.bRequest
= UVSCOM_SHUTDOWN
;
476 USETW(req
.wValue
, 0);
477 USETW(req
.wIndex
, 0);
478 USETW(req
.wLength
, 0);
480 err
= usbd_do_request(sc
->sc_udev
, &req
, NULL
);
482 aprint_error_dev(sc
->sc_dev
, "uvscom_shutdown: %s\n",
487 return (USBD_NORMAL_COMPLETION
);
491 uvscom_reset(struct uvscom_softc
*sc
)
493 DPRINTF(("%s: uvscom_reset\n", USBDEVNAME(sc
->sc_dev
)));
495 return (USBD_NORMAL_COMPLETION
);
499 uvscom_set_crtscts(struct uvscom_softc
*sc
)
501 DPRINTF(("%s: uvscom_set_crtscts\n", USBDEVNAME(sc
->sc_dev
)));
503 return (USBD_NORMAL_COMPLETION
);
507 uvscom_set_line(struct uvscom_softc
*sc
, uint16_t line
)
509 usb_device_request_t req
;
512 DPRINTF(("%s: uvscom_set_line: %04x\n",
513 USBDEVNAME(sc
->sc_dev
), line
));
515 req
.bmRequestType
= UT_WRITE_VENDOR_DEVICE
;
516 req
.bRequest
= UVSCOM_LINE_CTL
;
517 USETW(req
.wValue
, line
);
518 USETW(req
.wIndex
, 0);
519 USETW(req
.wLength
, 0);
521 err
= usbd_do_request(sc
->sc_udev
, &req
, NULL
);
523 aprint_error_dev(sc
->sc_dev
, "uvscom_set_line: %s\n",
528 return (USBD_NORMAL_COMPLETION
);
532 uvscom_set_line_coding(struct uvscom_softc
*sc
, uint16_t lsp
, uint16_t ls
)
534 usb_device_request_t req
;
537 DPRINTF(("%s: uvscom_set_line_coding: %02x %02x\n",
538 USBDEVNAME(sc
->sc_dev
), lsp
, ls
));
540 req
.bmRequestType
= UT_WRITE_VENDOR_DEVICE
;
541 req
.bRequest
= UVSCOM_SET_SPEED
;
542 USETW(req
.wValue
, lsp
);
543 USETW(req
.wIndex
, 0);
544 USETW(req
.wLength
, 0);
546 err
= usbd_do_request(sc
->sc_udev
, &req
, NULL
);
548 aprint_error_dev(sc
->sc_dev
, "uvscom_set_line_coding: %s\n",
553 req
.bmRequestType
= UT_WRITE_VENDOR_DEVICE
;
554 req
.bRequest
= UVSCOM_SET_PARAM
;
555 USETW(req
.wValue
, ls
);
556 USETW(req
.wIndex
, 0);
557 USETW(req
.wLength
, 0);
559 err
= usbd_do_request(sc
->sc_udev
, &req
, NULL
);
561 aprint_error_dev(sc
->sc_dev
, "uvscom_set_line_coding: %s\n",
566 return (USBD_NORMAL_COMPLETION
);
570 uvscom_dtr(struct uvscom_softc
*sc
, int onoff
)
572 DPRINTF(("%s: uvscom_dtr: onoff = %d\n",
573 USBDEVNAME(sc
->sc_dev
), onoff
));
575 if (sc
->sc_dtr
== onoff
)
576 return; /* no change */
581 SET(sc
->sc_lcr
, UVSCOM_DTR
);
583 CLR(sc
->sc_lcr
, UVSCOM_DTR
);
585 uvscom_set_line(sc
, sc
->sc_lcr
);
589 uvscom_rts(struct uvscom_softc
*sc
, int onoff
)
591 DPRINTF(("%s: uvscom_rts: onoff = %d\n",
592 USBDEVNAME(sc
->sc_dev
), onoff
));
594 if (sc
->sc_rts
== onoff
)
595 return; /* no change */
600 SET(sc
->sc_lcr
, UVSCOM_RTS
);
602 CLR(sc
->sc_lcr
, UVSCOM_RTS
);
604 uvscom_set_line(sc
, sc
->sc_lcr
);
608 uvscom_break(struct uvscom_softc
*sc
, int onoff
)
610 DPRINTF(("%s: uvscom_break: onoff = %d\n",
611 USBDEVNAME(sc
->sc_dev
), onoff
));
614 uvscom_set_line(sc
, SET(sc
->sc_lcr
, UVSCOM_BREAK
));
618 uvscom_set(void *addr
, int portno
, int reg
, int onoff
)
620 struct uvscom_softc
*sc
= addr
;
624 uvscom_dtr(sc
, onoff
);
627 uvscom_rts(sc
, onoff
);
630 uvscom_break(sc
, onoff
);
638 uvscom_param(void *addr
, int portno
, struct termios
*t
)
640 struct uvscom_softc
*sc
= addr
;
645 DPRINTF(("%s: uvscom_param: sc = %p\n",
646 USBDEVNAME(sc
->sc_dev
), sc
));
650 switch (t
->c_ospeed
) {
652 lsp
= UVSCOM_SPEED_150BPS
;
655 lsp
= UVSCOM_SPEED_300BPS
;
658 lsp
= UVSCOM_SPEED_600BPS
;
661 lsp
= UVSCOM_SPEED_1200BPS
;
664 lsp
= UVSCOM_SPEED_2400BPS
;
667 lsp
= UVSCOM_SPEED_4800BPS
;
670 lsp
= UVSCOM_SPEED_9600BPS
;
673 lsp
= UVSCOM_SPEED_19200BPS
;
676 lsp
= UVSCOM_SPEED_38400BPS
;
679 lsp
= UVSCOM_SPEED_57600BPS
;
682 lsp
= UVSCOM_SPEED_115200BPS
;
688 if (ISSET(t
->c_cflag
, CSTOPB
))
689 SET(ls
, UVSCOM_STOP_BIT_2
);
691 SET(ls
, UVSCOM_STOP_BIT_1
);
693 if (ISSET(t
->c_cflag
, PARENB
)) {
694 if (ISSET(t
->c_cflag
, PARODD
))
695 SET(ls
, UVSCOM_PARITY_ODD
);
697 SET(ls
, UVSCOM_PARITY_EVEN
);
699 SET(ls
, UVSCOM_PARITY_NONE
);
701 switch (ISSET(t
->c_cflag
, CSIZE
)) {
703 SET(ls
, UVSCOM_DATA_BIT_5
);
706 SET(ls
, UVSCOM_DATA_BIT_6
);
709 SET(ls
, UVSCOM_DATA_BIT_7
);
712 SET(ls
, UVSCOM_DATA_BIT_8
);
718 err
= uvscom_set_line_coding(sc
, lsp
, ls
);
722 if (ISSET(t
->c_cflag
, CRTSCTS
)) {
723 err
= uvscom_set_crtscts(sc
);
732 uvscom_open(void *addr
, int portno
)
734 struct uvscom_softc
*sc
= addr
;
741 DPRINTF(("uvscom_open: sc = %p\n", sc
));
743 if (sc
->sc_intr_number
!= -1 && sc
->sc_intr_pipe
== NULL
) {
744 DPRINTF(("uvscom_open: open interrupt pipe.\n"));
746 sc
->sc_usr
= 0; /* clear unit status */
748 err
= uvscom_readstat(sc
);
750 DPRINTF(("%s: uvscom_open: readstat faild\n",
751 USBDEVNAME(sc
->sc_dev
)));
755 sc
->sc_intr_buf
= malloc(sc
->sc_isize
, M_USBDEV
, M_WAITOK
);
756 err
= usbd_open_pipe_intr(sc
->sc_iface
,
764 UVSCOM_INTR_INTERVAL
);
766 aprint_error_dev(sc
->sc_dev
,
767 "cannot open interrupt pipe (addr %d)\n",
772 DPRINTF(("uvscom_open: did not open interrupt pipe.\n"));
775 if ((sc
->sc_usr
& UVSCOM_USTAT_MASK
) == 0) {
776 /* unit is not ready */
778 for (i
= UVSCOM_UNIT_WAIT
; i
> 0; --i
) {
779 tsleep(&err
, TTIPRI
, "uvsop", hz
); /* XXX */
780 if (ISSET(sc
->sc_usr
, UVSCOM_USTAT_MASK
))
784 DPRINTF(("%s: unit is not ready\n",
785 USBDEVNAME(sc
->sc_dev
)));
789 /* check PC card was inserted */
790 if (ISSET(sc
->sc_usr
, UVSCOM_NOCARD
)) {
791 DPRINTF(("%s: no card\n",
792 USBDEVNAME(sc
->sc_dev
)));
801 uvscom_close(void *addr
, int portno
)
803 struct uvscom_softc
*sc
= addr
;
809 DPRINTF(("uvscom_close: close\n"));
813 if (sc
->sc_intr_pipe
!= NULL
) {
814 err
= usbd_abort_pipe(sc
->sc_intr_pipe
);
816 aprint_error_dev(sc
->sc_dev
,
817 "abort interrupt pipe failed: %s\n",
819 err
= usbd_close_pipe(sc
->sc_intr_pipe
);
821 aprint_error_dev(sc
->sc_dev
,
822 "lose interrupt pipe failed: %s\n",
824 free(sc
->sc_intr_buf
, M_USBDEV
);
825 sc
->sc_intr_pipe
= NULL
;
830 uvscom_intr(usbd_xfer_handle xfer
, usbd_private_handle priv
,
833 struct uvscom_softc
*sc
= priv
;
834 u_char
*buf
= sc
->sc_intr_buf
;
840 if (status
!= USBD_NORMAL_COMPLETION
) {
841 if (status
== USBD_NOT_STARTED
|| status
== USBD_CANCELLED
)
844 aprint_error_dev(sc
->sc_dev
,
845 "uvscom_intr: abnormal status: %s\n",
846 usbd_errstr(status
));
847 usbd_clear_endpoint_stall_async(sc
->sc_intr_pipe
);
851 DPRINTFN(2, ("%s: uvscom status = %02x %02x\n",
852 USBDEVNAME(sc
->sc_dev
), buf
[0], buf
[1]));
854 sc
->sc_lsr
= sc
->sc_msr
= 0;
858 if (ISSET(pstatus
, UVSCOM_TXRDY
))
859 SET(sc
->sc_lsr
, ULSR_TXRDY
);
860 if (ISSET(pstatus
, UVSCOM_RXRDY
))
861 SET(sc
->sc_lsr
, ULSR_RXRDY
);
864 if (ISSET(pstatus
, UVSCOM_CTS
))
865 SET(sc
->sc_msr
, UMSR_CTS
);
866 if (ISSET(pstatus
, UVSCOM_DSR
))
867 SET(sc
->sc_msr
, UMSR_DSR
);
868 if (ISSET(pstatus
, UVSCOM_DCD
))
869 SET(sc
->sc_msr
, UMSR_DCD
);
871 ucom_status_change(device_private(sc
->sc_subdev
));
875 uvscom_get_status(void *addr
, int portno
, u_char
*lsr
, u_char
*msr
)
877 struct uvscom_softc
*sc
= addr
;