1 /* $NetBSD: uirda.c,v 1.32 2009/09/23 19:07:19 plunky Exp $ */
4 * Copyright (c) 2001 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Lennart Augustsson (lennart@augustsson.net).
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: uirda.c,v 1.32 2009/09/23 19:07:19 plunky Exp $");
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/device.h>
39 #include <sys/mutex.h>
40 #include <sys/ioctl.h>
44 #include <sys/select.h>
47 #include <dev/usb/usb.h>
48 #include <dev/usb/usbdi.h>
49 #include <dev/usb/usbdi_util.h>
50 #include <dev/usb/usbdevs.h>
52 #include <dev/ir/ir.h>
53 #include <dev/ir/irdaio.h>
54 #include <dev/ir/irframevar.h>
56 #include <dev/usb/uirdavar.h>
59 #define DPRINTF(x) if (uirdadebug) logprintf x
60 #define DPRINTFN(n,x) if (uirdadebug>(n)) logprintf x
68 /* Class specific requests */
69 #define UR_IRDA_RECEIVING 0x01 /* Receive in progress? */
70 #define UR_IRDA_CHECK_MEDIA_BUSY 0x03
71 #define UR_IRDA_SET_RATE_SNIFF 0x04 /* opt */
72 #define UR_IRDA_SET_UNICAST_LIST 0x05 /* opt */
73 #define UR_IRDA_GET_DESC 0x06
75 #define UIRDA_NEBOFS 8
80 } uirda_ebofs
[UIRDA_NEBOFS
] = {
81 { 0, UI_EB_0
, UIRDA_EB_0
},
82 { 1, UI_EB_1
, UIRDA_EB_1
},
83 { 2, UI_EB_2
, UIRDA_EB_2
},
84 { 3, UI_EB_3
, UIRDA_EB_3
},
85 { 6, UI_EB_6
, UIRDA_EB_6
},
86 { 12, UI_EB_12
, UIRDA_EB_12
},
87 { 24, UI_EB_24
, UIRDA_EB_24
},
88 { 48, UI_EB_48
, UIRDA_EB_48
}
91 #define UIRDA_NSPEEDS 9
96 } uirda_speeds
[UIRDA_NSPEEDS
] = {
97 { 4000000, UI_BR_4000000
, UIRDA_4000000
},
98 { 1152000, UI_BR_1152000
, UIRDA_1152000
},
99 { 576000, UI_BR_576000
, UIRDA_576000
},
100 { 115200, UI_BR_115200
, UIRDA_115200
},
101 { 57600, UI_BR_57600
, UIRDA_57600
},
102 { 38400, UI_BR_38400
, UIRDA_38400
},
103 { 19200, UI_BR_19200
, UIRDA_19200
},
104 { 9600, UI_BR_9600
, UIRDA_9600
},
105 { 2400, UI_BR_2400
, UIRDA_2400
},
110 int uirda_open(void *h
, int flag
, int mode
, struct lwp
*l
);
111 int uirda_close(void *h
, int flag
, int mode
, struct lwp
*l
);
112 int uirda_read(void *h
, struct uio
*uio
, int flag
);
113 int uirda_write(void *h
, struct uio
*uio
, int flag
);
114 int uirda_set_params(void *h
, struct irda_params
*params
);
115 int uirda_get_speeds(void *h
, int *speeds
);
116 int uirda_get_turnarounds(void *h
, int *times
);
117 int uirda_poll(void *h
, int events
, struct lwp
*l
);
118 int uirda_kqfilter(void *h
, struct knote
*kn
);
120 struct irframe_methods uirda_methods
= {
121 uirda_open
, uirda_close
, uirda_read
, uirda_write
, uirda_poll
,
122 uirda_kqfilter
, uirda_set_params
, uirda_get_speeds
,
123 uirda_get_turnarounds
126 void uirda_rd_cb(usbd_xfer_handle xfer
, usbd_private_handle priv
,
128 usbd_status
uirda_start_read(struct uirda_softc
*sc
);
131 * These devices don't quite follow the spec. Speed changing is broken
132 * and they don't handle windows.
133 * But we change speed in a safe way, and don't use windows now.
134 * Some devices also seem to have an interrupt pipe that can be ignored.
136 * Table information taken from Linux driver.
138 Static
const struct usb_devno uirda_devs
[] = {
139 { USB_VENDOR_ACTISYS
, USB_PRODUCT_ACTISYS_IR2000U
},
140 { USB_VENDOR_EXTENDED
, USB_PRODUCT_EXTENDED_XTNDACCESS
},
141 { USB_VENDOR_KAWATSU
, USB_PRODUCT_KAWATSU_KC180
},
143 #define uirda_lookup(v, p) (usb_lookup(uirda_devs, v, p))
145 int uirda_match(device_t
, cfdata_t
, void *);
146 void uirda_attach(device_t
, device_t
, void *);
147 void uirda_childdet(device_t
, device_t
);
148 int uirda_detach(device_t
, int);
149 int uirda_activate(device_t
, enum devact
);
150 extern struct cfdriver uirda_cd
;
151 CFATTACH_DECL2_NEW(uirda
, sizeof(struct uirda_softc
), uirda_match
,
152 uirda_attach
, uirda_detach
, uirda_activate
, NULL
, uirda_childdet
);
156 USB_IFMATCH_START(uirda
, uaa
);
158 DPRINTFN(50,("uirda_match\n"));
160 if (uirda_lookup(uaa
->vendor
, uaa
->product
) != NULL
)
161 return (UMATCH_VENDOR_PRODUCT
);
163 if (uaa
->class == UICLASS_APPL_SPEC
&&
164 uaa
->subclass
== UISUBCLASS_IRDA
&&
165 uaa
->proto
== UIPROTO_IRDA
)
166 return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO
);
167 return (UMATCH_NONE
);
172 USB_IFATTACH_START(uirda
, sc
, uaa
);
173 usbd_device_handle dev
= uaa
->device
;
174 usbd_interface_handle iface
= uaa
->iface
;
176 usb_endpoint_descriptor_t
*ed
;
181 struct ir_attach_args ia
;
183 DPRINTFN(10,("uirda_attach: sc=%p\n", sc
));
190 devinfop
= usbd_devinfo_alloc(dev
, 0);
191 aprint_normal_dev(self
, "%s\n", devinfop
);
192 usbd_devinfo_free(devinfop
);
195 sc
->sc_iface
= iface
;
197 if (sc
->sc_hdszi
== 0)
198 sc
->sc_hdszi
= UIRDA_INPUT_HEADER_SIZE
;
201 (void)usbd_endpoint_count(iface
, &epcount
);
205 for (i
= 0; i
< epcount
; i
++) {
206 ed
= usbd_interface2endpoint_descriptor(iface
, i
);
208 aprint_error_dev(self
, "couldn't get ep %d\n", i
);
209 USB_ATTACH_ERROR_RETURN
;
211 if (UE_GET_DIR(ed
->bEndpointAddress
) == UE_DIR_IN
&&
212 UE_GET_XFERTYPE(ed
->bmAttributes
) == UE_BULK
) {
213 sc
->sc_rd_addr
= ed
->bEndpointAddress
;
214 } else if (UE_GET_DIR(ed
->bEndpointAddress
) == UE_DIR_OUT
&&
215 UE_GET_XFERTYPE(ed
->bmAttributes
) == UE_BULK
) {
216 sc
->sc_wr_addr
= ed
->bEndpointAddress
;
219 if (sc
->sc_rd_addr
== -1 || sc
->sc_wr_addr
== -1) {
220 aprint_error_dev(self
, "missing endpoint\n");
221 USB_ATTACH_ERROR_RETURN
;
224 if (sc
->sc_loadfw(sc
) != 0) {
225 USB_ATTACH_ERROR_RETURN
;
228 /* Get the IrDA descriptor */
229 err
= usbd_get_class_desc(sc
->sc_udev
, UDESC_IRDA
, 0,
230 USB_IRDA_DESCRIPTOR_SIZE
, &sc
->sc_irdadesc
);
231 aprint_error_dev(self
, "error %d reading class desc\n", err
);
233 err
= usbd_get_desc(sc
->sc_udev
, UDESC_IRDA
, 0,
234 USB_IRDA_DESCRIPTOR_SIZE
, &sc
->sc_irdadesc
);
236 aprint_error_dev(self
, "error %d reading desc\n", err
);
238 /* maybe it's embedded in the config desc? */
239 usbd_desc_iter_t iter
;
240 const usb_descriptor_t
*d
;
241 usb_desc_iter_init(sc
->sc_udev
, &iter
);
243 d
= usb_desc_iter_next(&iter
);
244 if (!d
|| d
->bDescriptorType
== UDESC_IRDA
)
248 aprint_error_dev(self
,
249 "Cannot get IrDA descriptor\n");
250 USB_ATTACH_ERROR_RETURN
;
252 memcpy(&sc
->sc_irdadesc
, d
, USB_IRDA_DESCRIPTOR_SIZE
);
254 DPRINTF(("uirda_attach: bDescriptorSize %d bDescriptorType 0x%x "
255 "bmDataSize=0x%02x bmWindowSize=0x%02x "
256 "bmMinTurnaroundTime=0x%02x wBaudRate=0x%04x "
257 "bmAdditionalBOFs=0x%02x bIrdaSniff=%d bMaxUnicastList=%d\n",
258 sc
->sc_irdadesc
.bLength
,
259 sc
->sc_irdadesc
.bDescriptorType
,
260 sc
->sc_irdadesc
.bmDataSize
,
261 sc
->sc_irdadesc
.bmWindowSize
,
262 sc
->sc_irdadesc
.bmMinTurnaroundTime
,
263 UGETW(sc
->sc_irdadesc
.wBaudRate
),
264 sc
->sc_irdadesc
.bmAdditionalBOFs
,
265 sc
->sc_irdadesc
.bIrdaSniff
,
266 sc
->sc_irdadesc
.bMaxUnicastList
));
268 specrev
= UGETW(sc
->sc_irdadesc
.bcdSpecRevision
);
269 aprint_normal_dev(self
, "USB-IrDA protocol version %x.%02x\n",
270 specrev
>> 8, specrev
& 0xff);
272 DPRINTFN(10, ("uirda_attach: %p\n", sc
->sc_udev
));
274 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH
, sc
->sc_udev
,
277 mutex_init(&sc
->sc_wr_buf_lk
, MUTEX_DEFAULT
, IPL_NONE
);
278 mutex_init(&sc
->sc_rd_buf_lk
, MUTEX_DEFAULT
, IPL_NONE
);
279 selinit(&sc
->sc_rd_sel
);
280 selinit(&sc
->sc_wr_sel
);
282 ia
.ia_type
= IR_TYPE_IRFRAME
;
283 ia
.ia_methods
= sc
->sc_irm
? sc
->sc_irm
: &uirda_methods
;
286 sc
->sc_child
= config_found(self
, &ia
, ir_print
);
288 USB_ATTACH_SUCCESS_RETURN
;
293 USB_DETACH_START(uirda
, sc
);
297 DPRINTF(("uirda_detach: sc=%p flags=%d\n", sc
, flags
));
300 /* Abort all pipes. Causes processes waiting for transfer to wake. */
301 if (sc
->sc_rd_pipe
!= NULL
) {
302 usbd_abort_pipe(sc
->sc_rd_pipe
);
303 usbd_close_pipe(sc
->sc_rd_pipe
);
304 sc
->sc_rd_pipe
= NULL
;
306 if (sc
->sc_wr_pipe
!= NULL
) {
307 usbd_abort_pipe(sc
->sc_wr_pipe
);
308 usbd_close_pipe(sc
->sc_wr_pipe
);
309 sc
->sc_wr_pipe
= NULL
;
311 wakeup(&sc
->sc_rd_count
);
314 if (--sc
->sc_refcnt
>= 0) {
315 /* Wait for processes to go away. */
316 usb_detach_wait(USBDEV(sc
->sc_dev
));
320 if (sc
->sc_child
!= NULL
)
321 rv
= config_detach(sc
->sc_child
, flags
);
323 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH
, sc
->sc_udev
,
326 mutex_destroy(&sc
->sc_wr_buf_lk
);
327 mutex_destroy(&sc
->sc_rd_buf_lk
);
328 seldestroy(&sc
->sc_rd_sel
);
329 seldestroy(&sc
->sc_wr_sel
);
335 uirda_childdet(device_t self
, device_t child
)
337 struct uirda_softc
*sc
= device_private(self
);
339 KASSERT(sc
->sc_child
== child
);
344 uirda_activate(device_t self
, enum devact act
)
346 struct uirda_softc
*sc
= device_private(self
);
349 case DVACT_DEACTIVATE
:
358 uirda_open(void *h
, int flag
, int mode
,
361 struct uirda_softc
*sc
= h
;
365 DPRINTF(("%s: sc=%p\n", __func__
, sc
));
367 err
= usbd_open_pipe(sc
->sc_iface
, sc
->sc_rd_addr
, 0, &sc
->sc_rd_pipe
);
372 err
= usbd_open_pipe(sc
->sc_iface
, sc
->sc_wr_addr
, 0, &sc
->sc_wr_pipe
);
377 sc
->sc_rd_xfer
= usbd_alloc_xfer(sc
->sc_udev
);
378 if (sc
->sc_rd_xfer
== NULL
) {
382 sc
->sc_wr_xfer
= usbd_alloc_xfer(sc
->sc_udev
);
383 if (sc
->sc_wr_xfer
== NULL
) {
387 sc
->sc_rd_buf
= usbd_alloc_buffer(sc
->sc_rd_xfer
,
388 IRDA_MAX_FRAME_SIZE
+ sc
->sc_hdszi
);
389 if (sc
->sc_rd_buf
== NULL
) {
393 sc
->sc_wr_buf
= usbd_alloc_buffer(sc
->sc_wr_xfer
,
394 IRDA_MAX_FRAME_SIZE
+ UIRDA_OUTPUT_HEADER_SIZE
+
395 2 + 1 /* worst case ST-UIRDA */);
396 if (sc
->sc_wr_buf
== NULL
) {
402 sc
->sc_params
.speed
= 0;
403 sc
->sc_params
.ebofs
= 0;
404 sc
->sc_params
.maxsize
= IRDA_MAX_FRAME_SIZE
;
407 err
= uirda_start_read(sc
);
413 usbd_free_xfer(sc
->sc_wr_xfer
);
414 sc
->sc_wr_xfer
= NULL
;
416 usbd_free_xfer(sc
->sc_rd_xfer
);
417 sc
->sc_rd_xfer
= NULL
;
419 usbd_close_pipe(sc
->sc_wr_pipe
);
420 sc
->sc_wr_pipe
= NULL
;
422 usbd_close_pipe(sc
->sc_rd_pipe
);
423 sc
->sc_rd_pipe
= NULL
;
429 uirda_close(void *h
, int flag
, int mode
,
432 struct uirda_softc
*sc
= h
;
434 DPRINTF(("%s: sc=%p\n", __func__
, sc
));
436 if (sc
->sc_rd_pipe
!= NULL
) {
437 usbd_abort_pipe(sc
->sc_rd_pipe
);
438 usbd_close_pipe(sc
->sc_rd_pipe
);
439 sc
->sc_rd_pipe
= NULL
;
441 if (sc
->sc_wr_pipe
!= NULL
) {
442 usbd_abort_pipe(sc
->sc_wr_pipe
);
443 usbd_close_pipe(sc
->sc_wr_pipe
);
444 sc
->sc_wr_pipe
= NULL
;
446 if (sc
->sc_rd_xfer
!= NULL
) {
447 usbd_free_xfer(sc
->sc_rd_xfer
);
448 sc
->sc_rd_xfer
= NULL
;
449 sc
->sc_rd_buf
= NULL
;
451 if (sc
->sc_wr_xfer
!= NULL
) {
452 usbd_free_xfer(sc
->sc_wr_xfer
);
453 sc
->sc_wr_xfer
= NULL
;
454 sc
->sc_wr_buf
= NULL
;
461 uirda_read(void *h
, struct uio
*uio
, int flag
)
463 struct uirda_softc
*sc
= h
;
469 DPRINTFN(1,("%s: sc=%p\n", __func__
, sc
));
475 if (sc
->sc_rd_buf
== NULL
)
483 while (sc
->sc_rd_count
== 0) {
484 DPRINTFN(5,("uirda_read: calling tsleep()\n"));
485 error
= tsleep(&sc
->sc_rd_count
, PZERO
| PCATCH
,
491 DPRINTF(("uirda_read: tsleep() = %d\n", error
));
497 mutex_enter(&sc
->sc_rd_buf_lk
);
498 n
= sc
->sc_rd_count
- sc
->sc_hdszi
;
499 DPRINTFN(1,("%s: sc=%p n=%u, hdr=0x%02x\n", __func__
,
500 sc
, n
, sc
->sc_rd_buf
[0]));
501 if (n
> uio
->uio_resid
)
504 error
= uiomove(sc
->sc_rd_buf
+ sc
->sc_hdszi
, n
, uio
);
506 mutex_exit(&sc
->sc_rd_buf_lk
);
508 err
= uirda_start_read(sc
);
513 DPRINTFN(1,("uirda_read: return %d\n", error
));
516 if (--sc
->sc_refcnt
< 0)
517 usb_detach_wakeup(USBDEV(sc
->sc_dev
));
522 uirda_write(void *h
, struct uio
*uio
, int flag
)
524 struct uirda_softc
*sc
= h
;
529 DPRINTFN(1,("%s: sc=%p\n", __func__
, sc
));
535 if (sc
->sc_wr_buf
== NULL
)
540 if (n
> sc
->sc_params
.maxsize
)
544 mutex_enter(&sc
->sc_wr_buf_lk
);
546 sc
->sc_wr_buf
[0] = UIRDA_EB_NO_CHANGE
| UIRDA_NO_SPEED
;
547 error
= uiomove(sc
->sc_wr_buf
+ UIRDA_OUTPUT_HEADER_SIZE
, n
, uio
);
549 DPRINTFN(1, ("uirdawrite: transfer %d bytes\n", n
));
551 n
+= UIRDA_OUTPUT_HEADER_SIZE
;
552 err
= usbd_bulk_transfer(sc
->sc_wr_xfer
, sc
->sc_wr_pipe
,
553 USBD_FORCE_SHORT_XFER
| USBD_NO_COPY
,
555 sc
->sc_wr_buf
, &n
, "uirdawr");
556 DPRINTFN(2, ("uirdawrite: err=%d\n", err
));
558 if (err
== USBD_INTERRUPTED
)
560 else if (err
== USBD_TIMEOUT
)
567 mutex_exit(&sc
->sc_wr_buf_lk
);
568 if (--sc
->sc_refcnt
< 0)
569 usb_detach_wakeup(USBDEV(sc
->sc_dev
));
571 DPRINTFN(1,("%s: sc=%p done\n", __func__
, sc
));
576 uirda_poll(void *h
, int events
, struct lwp
*l
)
578 struct uirda_softc
*sc
= h
;
582 DPRINTFN(1,("%s: sc=%p\n", __func__
, sc
));
585 if (events
& (POLLOUT
| POLLWRNORM
))
586 revents
|= events
& (POLLOUT
| POLLWRNORM
);
587 if (events
& (POLLIN
| POLLRDNORM
)) {
588 if (sc
->sc_rd_count
!= 0) {
589 DPRINTFN(2,("%s: have data\n", __func__
));
590 revents
|= events
& (POLLIN
| POLLRDNORM
);
592 DPRINTFN(2,("%s: recording select\n", __func__
));
593 selrecord(l
, &sc
->sc_rd_sel
);
602 filt_uirdardetach(struct knote
*kn
)
604 struct uirda_softc
*sc
= kn
->kn_hook
;
608 SLIST_REMOVE(&sc
->sc_rd_sel
.sel_klist
, kn
, knote
, kn_selnext
);
613 filt_uirdaread(struct knote
*kn
, long hint
)
615 struct uirda_softc
*sc
= kn
->kn_hook
;
617 kn
->kn_data
= sc
->sc_rd_count
;
618 return (kn
->kn_data
> 0);
622 filt_uirdawdetach(struct knote
*kn
)
624 struct uirda_softc
*sc
= kn
->kn_hook
;
628 SLIST_REMOVE(&sc
->sc_wr_sel
.sel_klist
, kn
, knote
, kn_selnext
);
632 static const struct filterops uirdaread_filtops
=
633 { 1, NULL
, filt_uirdardetach
, filt_uirdaread
};
634 static const struct filterops uirdawrite_filtops
=
635 { 1, NULL
, filt_uirdawdetach
, filt_seltrue
};
638 uirda_kqfilter(void *h
, struct knote
*kn
)
640 struct uirda_softc
*sc
= kn
->kn_hook
;
644 switch (kn
->kn_filter
) {
646 klist
= &sc
->sc_rd_sel
.sel_klist
;
647 kn
->kn_fop
= &uirdaread_filtops
;
650 klist
= &sc
->sc_wr_sel
.sel_klist
;
651 kn
->kn_fop
= &uirdawrite_filtops
;
660 SLIST_INSERT_HEAD(klist
, kn
, kn_selnext
);
667 uirda_set_params(void *h
, struct irda_params
*p
)
669 struct uirda_softc
*sc
= h
;
676 DPRINTF(("%s: sc=%p, speed=%d ebofs=%d maxsize=%d\n", __func__
,
677 sc
, p
->speed
, p
->ebofs
, p
->maxsize
));
683 if (p
->ebofs
!= sc
->sc_params
.ebofs
) {
685 mask
= 1 /* sc->sc_irdadesc.bmAdditionalBOFs*/;
686 DPRINTF(("u.s.p.: mask=0x%x, sc->ebofs=%d, p->ebofs=%d\n",
687 mask
, sc
->sc_params
.ebofs
, p
->ebofs
));
688 for (i
= 0; i
< UIRDA_NEBOFS
; i
++) {
689 DPRINTF(("u.s.p.: u_e[%d].mask=0x%x, count=%d\n",
690 i
, uirda_ebofs
[i
].mask
, uirda_ebofs
[i
].count
));
691 if ((mask
& uirda_ebofs
[i
].mask
) &&
692 uirda_ebofs
[i
].count
>= p
->ebofs
) {
693 hdr
= uirda_ebofs
[i
].header
;
697 for (i
= 0; i
< UIRDA_NEBOFS
; i
++) {
698 DPRINTF(("u.s.p.: u_e[%d].mask=0x%x, count=%d\n",
699 i
, uirda_ebofs
[i
].mask
, uirda_ebofs
[i
].count
));
700 if ((mask
& uirda_ebofs
[i
].mask
)) {
701 hdr
= uirda_ebofs
[i
].header
;
705 /* no good value found */
708 DPRINTF(("uirda_set_params: ebofs hdr=0x%02x\n", hdr
));
712 if (hdr
!= 0 || p
->speed
!= sc
->sc_params
.speed
) {
714 mask
= UGETW(sc
->sc_irdadesc
.wBaudRate
);
715 for (i
= 0; i
< UIRDA_NSPEEDS
; i
++) {
716 if ((mask
& uirda_speeds
[i
].mask
) &&
717 uirda_speeds
[i
].speed
== p
->speed
) {
718 hdr
|= uirda_speeds
[i
].header
;
722 /* no good value found */
725 DPRINTF(("uirda_set_params: speed hdr=0x%02x\n", hdr
));
728 if (p
->maxsize
!= sc
->sc_params
.maxsize
) {
729 if (p
->maxsize
> IRDA_MAX_FRAME_SIZE
)
731 sc
->sc_params
.maxsize
= p
->maxsize
;
733 DPRINTF(("%s: new buffers, old size=%d\n", __func__
,
734 sc
->sc_params
.maxsize
));
735 if (p
->maxsize
> 10000 || p
< 0) /* XXX */
738 /* Change the write buffer */
739 mutex_enter(&sc
->sc_wr_buf_lk
);
740 if (sc
->sc_wr_buf
!= NULL
)
741 usbd_free_buffer(sc
->sc_wr_xfer
);
742 sc
->sc_wr_buf
= usbd_alloc_buffer(sc
->sc_wr_xfer
, p
->maxsize
+1);
743 mutex_exit(&sc
->sc_wr_buf_lk
);
744 if (sc
->sc_wr_buf
== NULL
)
747 /* Change the read buffer */
748 mutex_enter(&sc
->sc_rd_buf_lk
);
749 usbd_abort_pipe(sc
->sc_rd_pipe
);
750 if (sc
->sc_rd_buf
!= NULL
)
751 usbd_free_buffer(sc
->sc_rd_xfer
);
752 sc
->sc_rd_buf
= usbd_alloc_buffer(sc
->sc_rd_xfer
, p
->maxsize
+1);
754 if (sc
->sc_rd_buf
== NULL
) {
755 mutex_exit(&sc
->sc_rd_buf_lk
);
758 sc
->sc_params
.maxsize
= p
->maxsize
;
759 err
= uirda_start_read(sc
); /* XXX check */
760 mutex_exit(&sc
->sc_rd_buf_lk
);
763 if (hdr
!= 0 && hdr
!= sc
->sc_wr_hdr
) {
765 * A change has occurred, transmit a 0 length frame with
766 * the new settings. The 0 length frame is not sent to the
769 DPRINTF(("%s: sc=%p setting header 0x%02x\n",
772 mutex_enter(&sc
->sc_wr_buf_lk
);
773 sc
->sc_wr_buf
[0] = hdr
;
774 n
= UIRDA_OUTPUT_HEADER_SIZE
;
775 err
= usbd_bulk_transfer(sc
->sc_wr_xfer
, sc
->sc_wr_pipe
,
776 USBD_FORCE_SHORT_XFER
| USBD_NO_COPY
,
777 UIRDA_WR_TIMEOUT
, sc
->sc_wr_buf
, &n
, "uirdast");
779 aprint_error_dev(sc
->sc_dev
, "set failed, err=%d\n",
781 usbd_clear_endpoint_stall(sc
->sc_wr_pipe
);
783 mutex_exit(&sc
->sc_wr_buf_lk
);
792 uirda_get_speeds(void *h
, int *speeds
)
794 struct uirda_softc
*sc
= h
;
798 DPRINTF(("%s: sc=%p\n", __func__
, sc
));
803 usp
= UGETW(sc
->sc_irdadesc
.wBaudRate
);
805 if (usp
& UI_BR_4000000
) isp
|= IRDA_SPEED_4000000
;
806 if (usp
& UI_BR_1152000
) isp
|= IRDA_SPEED_1152000
;
807 if (usp
& UI_BR_576000
) isp
|= IRDA_SPEED_576000
;
808 if (usp
& UI_BR_115200
) isp
|= IRDA_SPEED_115200
;
809 if (usp
& UI_BR_57600
) isp
|= IRDA_SPEED_57600
;
810 if (usp
& UI_BR_38400
) isp
|= IRDA_SPEED_38400
;
811 if (usp
& UI_BR_19200
) isp
|= IRDA_SPEED_19200
;
812 if (usp
& UI_BR_9600
) isp
|= IRDA_SPEED_9600
;
813 if (usp
& UI_BR_2400
) isp
|= IRDA_SPEED_2400
;
815 DPRINTF(("%s: speeds = 0x%x\n", __func__
, isp
));
820 uirda_get_turnarounds(void *h
, int *turnarounds
)
822 struct uirda_softc
*sc
= h
;
826 DPRINTF(("%s: sc=%p\n", __func__
, sc
));
831 uta
= sc
->sc_irdadesc
.bmMinTurnaroundTime
;
833 if (uta
& UI_TA_0
) ita
|= IRDA_TURNT_0
;
834 if (uta
& UI_TA_10
) ita
|= IRDA_TURNT_10
;
835 if (uta
& UI_TA_50
) ita
|= IRDA_TURNT_50
;
836 if (uta
& UI_TA_100
) ita
|= IRDA_TURNT_100
;
837 if (uta
& UI_TA_500
) ita
|= IRDA_TURNT_500
;
838 if (uta
& UI_TA_1000
) ita
|= IRDA_TURNT_1000
;
839 if (uta
& UI_TA_5000
) ita
|= IRDA_TURNT_5000
;
840 if (uta
& UI_TA_10000
) ita
|= IRDA_TURNT_10000
;
846 uirda_rd_cb(usbd_xfer_handle xfer
, usbd_private_handle priv
,
849 struct uirda_softc
*sc
= priv
;
852 DPRINTFN(1,("%s: sc=%p\n", __func__
, sc
));
854 if (status
== USBD_CANCELLED
) /* this is normal */
860 usbd_get_xfer_status(xfer
, NULL
, NULL
, &size
, NULL
);
862 DPRINTFN(1,("%s: sc=%p size=%u, err=%d\n", __func__
, sc
, size
,
864 sc
->sc_rd_count
= size
;
865 wakeup(&sc
->sc_rd_count
); /* XXX should use flag */
866 selnotify(&sc
->sc_rd_sel
, 0, 0);
870 uirda_start_read(struct uirda_softc
*sc
)
874 DPRINTFN(1,("%s: sc=%p, size=%d\n", __func__
, sc
,
875 sc
->sc_params
.maxsize
+ UIRDA_INPUT_HEADER_SIZE
));
878 return (USBD_IOERROR
);
882 DPRINTF(("uirda_start_read: clear stall\n"));
883 usbd_clear_endpoint_stall(sc
->sc_rd_pipe
);
886 usbd_setup_xfer(sc
->sc_rd_xfer
, sc
->sc_rd_pipe
, sc
, sc
->sc_rd_buf
,
887 sc
->sc_params
.maxsize
+ sc
->sc_hdszi
,
888 USBD_SHORT_XFER_OK
| USBD_NO_COPY
,
889 USBD_NO_TIMEOUT
, uirda_rd_cb
);
890 err
= usbd_transfer(sc
->sc_rd_xfer
);
891 if (err
!= USBD_IN_PROGRESS
) {
892 DPRINTF(("uirda_start_read: err=%d\n", err
));
895 return (USBD_NORMAL_COMPLETION
);
899 usbd_get_class_desc(usbd_device_handle dev
, int type
, int index
, int len
, void *desc
)
901 usb_device_request_t req
;
903 DPRINTFN(3,("usbd_get_desc: type=%d, index=%d, len=%d\n",
906 req
.bmRequestType
= 0xa1; /* XXX ? */
907 req
.bRequest
= UR_GET_DESCRIPTOR
;
908 USETW2(req
.wValue
, type
, index
);
909 USETW(req
.wIndex
, 0);
910 USETW(req
.wLength
, len
);
911 return (usbd_do_request(dev
, &req
, desc
));