Home | History | Annotate | Line # | Download | only in usb
uirda.c revision 1.38.6.10
      1  1.38.6.10     skrll /*	$NetBSD: uirda.c,v 1.38.6.10 2016/07/09 20:25:16 skrll Exp $	*/
      2        1.1  augustss 
      3        1.1  augustss /*
      4        1.1  augustss  * Copyright (c) 2001 The NetBSD Foundation, Inc.
      5        1.1  augustss  * All rights reserved.
      6        1.1  augustss  *
      7        1.1  augustss  * This code is derived from software contributed to The NetBSD Foundation
      8        1.6  augustss  * by Lennart Augustsson (lennart (at) augustsson.net).
      9        1.1  augustss  *
     10        1.1  augustss  * Redistribution and use in source and binary forms, with or without
     11        1.1  augustss  * modification, are permitted provided that the following conditions
     12        1.1  augustss  * are met:
     13        1.1  augustss  * 1. Redistributions of source code must retain the above copyright
     14        1.1  augustss  *    notice, this list of conditions and the following disclaimer.
     15        1.1  augustss  * 2. Redistributions in binary form must reproduce the above copyright
     16        1.1  augustss  *    notice, this list of conditions and the following disclaimer in the
     17        1.1  augustss  *    documentation and/or other materials provided with the distribution.
     18        1.1  augustss  *
     19        1.1  augustss  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20        1.1  augustss  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21        1.1  augustss  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22        1.1  augustss  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23        1.1  augustss  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24        1.1  augustss  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25        1.1  augustss  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26        1.1  augustss  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27        1.1  augustss  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28        1.1  augustss  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29        1.1  augustss  * POSSIBILITY OF SUCH DAMAGE.
     30        1.1  augustss  */
     31        1.1  augustss 
     32        1.1  augustss #include <sys/cdefs.h>
     33  1.38.6.10     skrll __KERNEL_RCSID(0, "$NetBSD: uirda.c,v 1.38.6.10 2016/07/09 20:25:16 skrll Exp $");
     34        1.1  augustss 
     35        1.1  augustss #include <sys/param.h>
     36        1.1  augustss #include <sys/systm.h>
     37        1.1  augustss #include <sys/kernel.h>
     38        1.1  augustss #include <sys/device.h>
     39       1.26        ad #include <sys/mutex.h>
     40        1.1  augustss #include <sys/ioctl.h>
     41        1.1  augustss #include <sys/conf.h>
     42        1.1  augustss #include <sys/file.h>
     43        1.1  augustss #include <sys/poll.h>
     44        1.1  augustss #include <sys/select.h>
     45        1.1  augustss #include <sys/proc.h>
     46        1.1  augustss 
     47        1.1  augustss #include <dev/usb/usb.h>
     48        1.1  augustss #include <dev/usb/usbdi.h>
     49        1.1  augustss #include <dev/usb/usbdi_util.h>
     50        1.1  augustss #include <dev/usb/usbdevs.h>
     51        1.1  augustss 
     52        1.1  augustss #include <dev/ir/ir.h>
     53        1.1  augustss #include <dev/ir/irdaio.h>
     54        1.1  augustss #include <dev/ir/irframevar.h>
     55        1.1  augustss 
     56       1.25        is #include <dev/usb/uirdavar.h>
     57       1.25        is 
     58       1.12  augustss #ifdef UIRDA_DEBUG
     59       1.34    dyoung #define DPRINTF(x)	if (uirdadebug) printf x
     60       1.34    dyoung #define DPRINTFN(n,x)	if (uirdadebug>(n)) printf x
     61        1.7  augustss int	uirdadebug = 0;
     62        1.1  augustss #else
     63        1.1  augustss #define DPRINTF(x)
     64        1.1  augustss #define DPRINTFN(n,x)
     65        1.1  augustss #endif
     66        1.1  augustss 
     67        1.1  augustss 
     68        1.1  augustss /* Class specific requests */
     69        1.1  augustss #define UR_IRDA_RECEIVING		0x01	/* Receive in progress? */
     70        1.1  augustss #define UR_IRDA_CHECK_MEDIA_BUSY	0x03
     71        1.1  augustss #define UR_IRDA_SET_RATE_SNIFF		0x04	/* opt */
     72        1.1  augustss #define UR_IRDA_SET_UNICAST_LIST	0x05	/* opt */
     73        1.1  augustss #define UR_IRDA_GET_DESC		0x06
     74        1.1  augustss 
     75        1.1  augustss #define UIRDA_NEBOFS 8
     76        1.1  augustss static struct {
     77        1.1  augustss 	int count;
     78        1.1  augustss 	int mask;
     79        1.1  augustss 	int header;
     80        1.1  augustss } uirda_ebofs[UIRDA_NEBOFS] = {
     81        1.1  augustss 	{ 0, UI_EB_0, UIRDA_EB_0 },
     82        1.1  augustss 	{ 1, UI_EB_1, UIRDA_EB_1 },
     83        1.1  augustss 	{ 2, UI_EB_2, UIRDA_EB_2 },
     84        1.1  augustss 	{ 3, UI_EB_3, UIRDA_EB_3 },
     85        1.1  augustss 	{ 6, UI_EB_6, UIRDA_EB_6 },
     86        1.1  augustss 	{ 12, UI_EB_12, UIRDA_EB_12 },
     87        1.1  augustss 	{ 24, UI_EB_24, UIRDA_EB_24 },
     88        1.1  augustss 	{ 48, UI_EB_48, UIRDA_EB_48 }
     89        1.1  augustss };
     90        1.1  augustss 
     91        1.1  augustss #define UIRDA_NSPEEDS 9
     92        1.1  augustss static struct {
     93        1.1  augustss 	int speed;
     94        1.1  augustss 	int mask;
     95        1.1  augustss 	int header;
     96        1.1  augustss } uirda_speeds[UIRDA_NSPEEDS] = {
     97        1.1  augustss 	{ 4000000, UI_BR_4000000, UIRDA_4000000 },
     98        1.1  augustss 	{ 1152000, UI_BR_1152000, UIRDA_1152000 },
     99        1.1  augustss 	{ 576000, UI_BR_576000, UIRDA_576000 },
    100        1.1  augustss 	{ 115200, UI_BR_115200, UIRDA_115200 },
    101        1.1  augustss 	{ 57600, UI_BR_57600, UIRDA_57600 },
    102        1.1  augustss 	{ 38400, UI_BR_38400, UIRDA_38400 },
    103        1.1  augustss 	{ 19200, UI_BR_19200, UIRDA_19200 },
    104        1.1  augustss 	{ 9600, UI_BR_9600, UIRDA_9600 },
    105        1.1  augustss 	{ 2400, UI_BR_2400, UIRDA_2400 },
    106        1.1  augustss };
    107        1.1  augustss 
    108        1.1  augustss 
    109        1.1  augustss 
    110   1.38.6.5     skrll int uirda_open(void *, int, int, struct lwp *);
    111   1.38.6.5     skrll int uirda_close(void *, int, int, struct lwp *);
    112   1.38.6.5     skrll int uirda_read(void *, struct uio *, int);
    113   1.38.6.5     skrll int uirda_write(void *, struct uio *, int);
    114   1.38.6.5     skrll int uirda_set_params(void *, struct irda_params *);
    115   1.38.6.5     skrll int uirda_get_speeds(void *, int *);
    116   1.38.6.5     skrll int uirda_get_turnarounds(void *, int *);
    117   1.38.6.5     skrll int uirda_poll(void *, int, struct lwp *);
    118   1.38.6.5     skrll int uirda_kqfilter(void *, struct knote *);
    119        1.1  augustss 
    120        1.1  augustss struct irframe_methods uirda_methods = {
    121       1.11  augustss 	uirda_open, uirda_close, uirda_read, uirda_write, uirda_poll,
    122       1.13  jdolecek 	uirda_kqfilter, uirda_set_params, uirda_get_speeds,
    123       1.13  jdolecek 	uirda_get_turnarounds
    124        1.1  augustss };
    125        1.1  augustss 
    126   1.38.6.6     skrll void uirda_rd_cb(struct usbd_xfer *xfer,	void *priv,
    127        1.1  augustss 		 usbd_status status);
    128        1.1  augustss usbd_status uirda_start_read(struct uirda_softc *sc);
    129        1.1  augustss 
    130       1.11  augustss /*
    131        1.1  augustss  * These devices don't quite follow the spec.  Speed changing is broken
    132        1.1  augustss  * and they don't handle windows.
    133        1.1  augustss  * But we change speed in a safe way, and don't use windows now.
    134        1.1  augustss  * Some devices also seem to have an interrupt pipe that can be ignored.
    135        1.1  augustss  *
    136        1.1  augustss  * Table information taken from Linux driver.
    137        1.1  augustss  */
    138        1.1  augustss Static const struct usb_devno uirda_devs[] = {
    139        1.1  augustss 	{ USB_VENDOR_ACTISYS, USB_PRODUCT_ACTISYS_IR2000U },
    140        1.1  augustss 	{ USB_VENDOR_EXTENDED, USB_PRODUCT_EXTENDED_XTNDACCESS },
    141        1.1  augustss 	{ USB_VENDOR_KAWATSU, USB_PRODUCT_KAWATSU_KC180 },
    142        1.1  augustss };
    143        1.1  augustss #define uirda_lookup(v, p) (usb_lookup(uirda_devs, v, p))
    144        1.1  augustss 
    145       1.31      cube int uirda_match(device_t, cfdata_t, void *);
    146       1.28    dyoung void uirda_attach(device_t, device_t, void *);
    147       1.28    dyoung void uirda_childdet(device_t, device_t);
    148       1.28    dyoung int uirda_detach(device_t, int);
    149       1.28    dyoung int uirda_activate(device_t, enum devact);
    150       1.28    dyoung extern struct cfdriver uirda_cd;
    151       1.31      cube CFATTACH_DECL2_NEW(uirda, sizeof(struct uirda_softc), uirda_match,
    152       1.28    dyoung     uirda_attach, uirda_detach, uirda_activate, NULL, uirda_childdet);
    153        1.1  augustss 
    154   1.38.6.1     skrll int
    155       1.34    dyoung uirda_match(device_t parent, cfdata_t match, void *aux)
    156        1.1  augustss {
    157   1.38.6.7     skrll 	struct usbif_attach_arg *uiaa = aux;
    158        1.1  augustss 
    159        1.1  augustss 	DPRINTFN(50,("uirda_match\n"));
    160        1.1  augustss 
    161   1.38.6.7     skrll 	if (uirda_lookup(uiaa->uiaa_vendor, uiaa->uiaa_product) != NULL)
    162   1.38.6.4     skrll 		return UMATCH_VENDOR_PRODUCT;
    163        1.1  augustss 
    164   1.38.6.7     skrll 	if (uiaa->uiaa_class == UICLASS_APPL_SPEC &&
    165   1.38.6.7     skrll 	    uiaa->uiaa_subclass == UISUBCLASS_IRDA &&
    166   1.38.6.7     skrll 	    uiaa->uiaa_proto == UIPROTO_IRDA)
    167   1.38.6.4     skrll 		return UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO;
    168   1.38.6.4     skrll 	return UMATCH_NONE;
    169        1.1  augustss }
    170        1.1  augustss 
    171   1.38.6.1     skrll void
    172       1.34    dyoung uirda_attach(device_t parent, device_t self, void *aux)
    173        1.1  augustss {
    174       1.34    dyoung 	struct uirda_softc *sc = device_private(self);
    175   1.38.6.7     skrll 	struct usbif_attach_arg *uiaa = aux;
    176   1.38.6.7     skrll 	struct usbd_device *	dev = uiaa->uiaa_device;
    177   1.38.6.7     skrll 	struct usbd_interface  *iface = uiaa->uiaa_iface;
    178       1.19  augustss 	char			*devinfop;
    179        1.1  augustss 	usb_endpoint_descriptor_t *ed;
    180        1.1  augustss 	usbd_status		err;
    181   1.38.6.1     skrll 	uint8_t			epcount;
    182        1.4  augustss 	u_int			specrev;
    183        1.1  augustss 	int			i;
    184        1.1  augustss 	struct ir_attach_args	ia;
    185        1.1  augustss 
    186        1.1  augustss 	DPRINTFN(10,("uirda_attach: sc=%p\n", sc));
    187        1.1  augustss 
    188       1.31      cube 	sc->sc_dev = self;
    189       1.31      cube 
    190       1.32    plunky 	aprint_naive("\n");
    191       1.32    plunky 	aprint_normal("\n");
    192       1.32    plunky 
    193       1.19  augustss 	devinfop = usbd_devinfo_alloc(dev, 0);
    194       1.31      cube 	aprint_normal_dev(self, "%s\n", devinfop);
    195       1.19  augustss 	usbd_devinfo_free(devinfop);
    196        1.1  augustss 
    197        1.1  augustss 	sc->sc_udev = dev;
    198        1.1  augustss 	sc->sc_iface = iface;
    199        1.1  augustss 
    200       1.25        is 	if (sc->sc_hdszi == 0)
    201       1.25        is 		sc->sc_hdszi = UIRDA_INPUT_HEADER_SIZE;
    202       1.25        is 
    203        1.1  augustss 	epcount = 0;
    204        1.1  augustss 	(void)usbd_endpoint_count(iface, &epcount);
    205        1.1  augustss 
    206        1.1  augustss 	sc->sc_rd_addr = -1;
    207        1.1  augustss 	sc->sc_wr_addr = -1;
    208        1.1  augustss 	for (i = 0; i < epcount; i++) {
    209        1.1  augustss 		ed = usbd_interface2endpoint_descriptor(iface, i);
    210        1.1  augustss 		if (ed == NULL) {
    211       1.31      cube 			aprint_error_dev(self, "couldn't get ep %d\n", i);
    212       1.34    dyoung 			return;
    213        1.1  augustss 		}
    214        1.1  augustss 		if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
    215        1.1  augustss 		    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
    216        1.1  augustss 			sc->sc_rd_addr = ed->bEndpointAddress;
    217        1.1  augustss 		} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
    218        1.1  augustss 			   UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
    219        1.1  augustss 			sc->sc_wr_addr = ed->bEndpointAddress;
    220        1.1  augustss 		}
    221        1.1  augustss 	}
    222        1.1  augustss 	if (sc->sc_rd_addr == -1 || sc->sc_wr_addr == -1) {
    223       1.31      cube 		aprint_error_dev(self, "missing endpoint\n");
    224       1.34    dyoung 		return;
    225        1.1  augustss 	}
    226        1.1  augustss 
    227       1.25        is 	if (sc->sc_loadfw(sc) != 0) {
    228       1.34    dyoung 		return;
    229       1.25        is 	}
    230       1.25        is 
    231        1.1  augustss 	/* Get the IrDA descriptor */
    232       1.25        is 	err = usbd_get_class_desc(sc->sc_udev, UDESC_IRDA, 0,
    233       1.25        is 		USB_IRDA_DESCRIPTOR_SIZE, &sc->sc_irdadesc);
    234       1.31      cube 	aprint_error_dev(self, "error %d reading class desc\n", err);
    235       1.25        is 	if (err) {
    236       1.25        is 		err = usbd_get_desc(sc->sc_udev, UDESC_IRDA, 0,
    237        1.1  augustss 		  USB_IRDA_DESCRIPTOR_SIZE, &sc->sc_irdadesc);
    238       1.25        is 	}
    239       1.31      cube 	aprint_error_dev(self, "error %d reading desc\n", err);
    240        1.1  augustss 	if (err) {
    241        1.8  augustss 		/* maybe it's embedded in the config desc? */
    242       1.23  drochner 		usbd_desc_iter_t iter;
    243       1.23  drochner 		const usb_descriptor_t *d;
    244       1.23  drochner 		usb_desc_iter_init(sc->sc_udev, &iter);
    245       1.23  drochner 		for (;;) {
    246       1.23  drochner 			d = usb_desc_iter_next(&iter);
    247       1.23  drochner 			if (!d || d->bDescriptorType == UDESC_IRDA)
    248       1.23  drochner 				break;
    249       1.23  drochner 		}
    250        1.1  augustss 		if (d == NULL) {
    251       1.31      cube 			aprint_error_dev(self,
    252       1.31      cube 			    "Cannot get IrDA descriptor\n");
    253       1.34    dyoung 			return;
    254        1.1  augustss 		}
    255        1.1  augustss 		memcpy(&sc->sc_irdadesc, d, USB_IRDA_DESCRIPTOR_SIZE);
    256        1.1  augustss 	}
    257       1.25        is 	DPRINTF(("uirda_attach: bDescriptorSize %d bDescriptorType 0x%x "
    258       1.25        is 		 "bmDataSize=0x%02x bmWindowSize=0x%02x "
    259        1.8  augustss 		 "bmMinTurnaroundTime=0x%02x wBaudRate=0x%04x "
    260        1.8  augustss 		 "bmAdditionalBOFs=0x%02x bIrdaSniff=%d bMaxUnicastList=%d\n",
    261       1.25        is 		 sc->sc_irdadesc.bLength,
    262       1.25        is 		 sc->sc_irdadesc.bDescriptorType,
    263        1.4  augustss 		 sc->sc_irdadesc.bmDataSize,
    264        1.4  augustss 		 sc->sc_irdadesc.bmWindowSize,
    265        1.4  augustss 		 sc->sc_irdadesc.bmMinTurnaroundTime,
    266        1.4  augustss 		 UGETW(sc->sc_irdadesc.wBaudRate),
    267        1.4  augustss 		 sc->sc_irdadesc.bmAdditionalBOFs,
    268        1.4  augustss 		 sc->sc_irdadesc.bIrdaSniff,
    269        1.4  augustss 		 sc->sc_irdadesc.bMaxUnicastList));
    270        1.4  augustss 
    271        1.4  augustss 	specrev = UGETW(sc->sc_irdadesc.bcdSpecRevision);
    272       1.31      cube 	aprint_normal_dev(self, "USB-IrDA protocol version %x.%02x\n",
    273       1.31      cube 	    specrev >> 8, specrev & 0xff);
    274        1.1  augustss 
    275        1.1  augustss 	DPRINTFN(10, ("uirda_attach: %p\n", sc->sc_udev));
    276        1.1  augustss 
    277  1.38.6.10     skrll 	usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev);
    278        1.3  augustss 
    279       1.26        ad 	mutex_init(&sc->sc_wr_buf_lk, MUTEX_DEFAULT, IPL_NONE);
    280       1.26        ad 	mutex_init(&sc->sc_rd_buf_lk, MUTEX_DEFAULT, IPL_NONE);
    281       1.29     rmind 	selinit(&sc->sc_rd_sel);
    282       1.29     rmind 	selinit(&sc->sc_wr_sel);
    283        1.1  augustss 
    284        1.1  augustss 	ia.ia_type = IR_TYPE_IRFRAME;
    285       1.25        is 	ia.ia_methods = sc->sc_irm ? sc->sc_irm : &uirda_methods;
    286        1.1  augustss 	ia.ia_handle = sc;
    287        1.1  augustss 
    288        1.1  augustss 	sc->sc_child = config_found(self, &ia, ir_print);
    289        1.1  augustss 
    290       1.34    dyoung 	return;
    291        1.1  augustss }
    292        1.1  augustss 
    293   1.38.6.1     skrll int
    294       1.34    dyoung uirda_detach(device_t self, int flags)
    295        1.1  augustss {
    296       1.34    dyoung 	struct uirda_softc *sc = device_private(self);
    297        1.1  augustss 	int s;
    298        1.1  augustss 	int rv = 0;
    299        1.1  augustss 
    300        1.1  augustss 	DPRINTF(("uirda_detach: sc=%p flags=%d\n", sc, flags));
    301        1.1  augustss 
    302        1.1  augustss 	sc->sc_dying = 1;
    303        1.1  augustss 	/* Abort all pipes.  Causes processes waiting for transfer to wake. */
    304        1.1  augustss 	if (sc->sc_rd_pipe != NULL) {
    305        1.1  augustss 		usbd_abort_pipe(sc->sc_rd_pipe);
    306   1.38.6.9     skrll 	}
    307   1.38.6.9     skrll 	if (sc->sc_wr_pipe != NULL) {
    308   1.38.6.9     skrll 		usbd_abort_pipe(sc->sc_wr_pipe);
    309   1.38.6.9     skrll 	}
    310   1.38.6.9     skrll 	if (sc->sc_rd_xfer != NULL) {
    311   1.38.6.9     skrll 		usbd_destroy_xfer(sc->sc_rd_xfer);
    312   1.38.6.9     skrll 		sc->sc_rd_xfer = NULL;
    313   1.38.6.9     skrll 		sc->sc_rd_buf = NULL;
    314   1.38.6.9     skrll 	}
    315   1.38.6.9     skrll 	if (sc->sc_wr_xfer != NULL) {
    316   1.38.6.9     skrll 		usbd_destroy_xfer(sc->sc_wr_xfer);
    317   1.38.6.9     skrll 		sc->sc_wr_xfer = NULL;
    318   1.38.6.9     skrll 		sc->sc_wr_buf = NULL;
    319   1.38.6.9     skrll 	}
    320   1.38.6.9     skrll 	if (sc->sc_rd_pipe != NULL) {
    321        1.1  augustss 		usbd_close_pipe(sc->sc_rd_pipe);
    322        1.1  augustss 		sc->sc_rd_pipe = NULL;
    323        1.1  augustss 	}
    324        1.1  augustss 	if (sc->sc_wr_pipe != NULL) {
    325        1.1  augustss 		usbd_close_pipe(sc->sc_wr_pipe);
    326        1.1  augustss 		sc->sc_wr_pipe = NULL;
    327        1.1  augustss 	}
    328        1.1  augustss 	wakeup(&sc->sc_rd_count);
    329        1.1  augustss 
    330        1.1  augustss 	s = splusb();
    331        1.1  augustss 	if (--sc->sc_refcnt >= 0) {
    332        1.1  augustss 		/* Wait for processes to go away. */
    333       1.37       mrg 		usb_detach_waitold(sc->sc_dev);
    334        1.1  augustss 	}
    335        1.1  augustss 	splx(s);
    336        1.1  augustss 
    337       1.28    dyoung 	if (sc->sc_child != NULL)
    338        1.1  augustss 		rv = config_detach(sc->sc_child, flags);
    339        1.1  augustss 
    340  1.38.6.10     skrll 	usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev);
    341        1.1  augustss 
    342       1.26        ad 	mutex_destroy(&sc->sc_wr_buf_lk);
    343       1.26        ad 	mutex_destroy(&sc->sc_rd_buf_lk);
    344       1.29     rmind 	seldestroy(&sc->sc_rd_sel);
    345       1.29     rmind 	seldestroy(&sc->sc_wr_sel);
    346       1.26        ad 
    347   1.38.6.4     skrll 	return rv;
    348        1.1  augustss }
    349        1.1  augustss 
    350       1.28    dyoung void
    351       1.28    dyoung uirda_childdet(device_t self, device_t child)
    352       1.28    dyoung {
    353       1.28    dyoung 	struct uirda_softc *sc = device_private(self);
    354       1.28    dyoung 
    355       1.28    dyoung 	KASSERT(sc->sc_child == child);
    356       1.28    dyoung 	sc->sc_child = NULL;
    357       1.28    dyoung }
    358       1.28    dyoung 
    359        1.1  augustss int
    360       1.28    dyoung uirda_activate(device_t self, enum devact act)
    361        1.1  augustss {
    362       1.28    dyoung 	struct uirda_softc *sc = device_private(self);
    363        1.1  augustss 
    364        1.1  augustss 	switch (act) {
    365        1.1  augustss 	case DVACT_DEACTIVATE:
    366        1.1  augustss 		sc->sc_dying = 1;
    367       1.33    dyoung 		return 0;
    368       1.33    dyoung 	default:
    369       1.33    dyoung 		return EOPNOTSUPP;
    370        1.1  augustss 	}
    371        1.1  augustss }
    372        1.1  augustss 
    373        1.1  augustss int
    374       1.22  christos uirda_open(void *h, int flag, int mode,
    375       1.22  christos     struct lwp *l)
    376        1.1  augustss {
    377        1.1  augustss 	struct uirda_softc *sc = h;
    378        1.1  augustss 	int error;
    379        1.1  augustss 	usbd_status err;
    380        1.1  augustss 
    381       1.10  augustss 	DPRINTF(("%s: sc=%p\n", __func__, sc));
    382        1.1  augustss 
    383        1.1  augustss 	err = usbd_open_pipe(sc->sc_iface, sc->sc_rd_addr, 0, &sc->sc_rd_pipe);
    384        1.1  augustss 	if (err) {
    385        1.1  augustss 		error = EIO;
    386        1.1  augustss 		goto bad1;
    387        1.1  augustss 	}
    388        1.1  augustss 	err = usbd_open_pipe(sc->sc_iface, sc->sc_wr_addr, 0, &sc->sc_wr_pipe);
    389        1.1  augustss 	if (err) {
    390        1.1  augustss 		error = EIO;
    391        1.1  augustss 		goto bad2;
    392        1.1  augustss 	}
    393   1.38.6.8     skrll 	error = usbd_create_xfer(sc->sc_rd_pipe,
    394   1.38.6.8     skrll 	    IRDA_MAX_FRAME_SIZE + sc->sc_hdszi, USBD_SHORT_XFER_OK, 0,
    395   1.38.6.8     skrll 	    &sc->sc_rd_xfer);
    396   1.38.6.8     skrll 	if (error)
    397        1.1  augustss 		goto bad3;
    398   1.38.6.8     skrll 	sc->sc_rd_buf = usbd_get_buffer(sc->sc_rd_xfer);
    399   1.38.6.8     skrll 
    400   1.38.6.8     skrll 	/* worst case ST-UIRDA length */
    401   1.38.6.8     skrll 	error = usbd_create_xfer(sc->sc_wr_pipe,
    402   1.38.6.8     skrll 	    IRDA_MAX_FRAME_SIZE + UIRDA_OUTPUT_HEADER_SIZE + 2 + 1,
    403   1.38.6.8     skrll 	    USBD_FORCE_SHORT_XFER, 0, &sc->sc_wr_xfer);
    404   1.38.6.8     skrll 	if (error)
    405        1.1  augustss 		goto bad4;
    406   1.38.6.8     skrll 	sc->sc_wr_buf = usbd_get_buffer(sc->sc_wr_xfer);
    407   1.38.6.8     skrll 
    408        1.2  augustss 	sc->sc_rd_count = 0;
    409        1.4  augustss 	sc->sc_rd_err = 0;
    410        1.2  augustss 	sc->sc_params.speed = 0;
    411        1.2  augustss 	sc->sc_params.ebofs = 0;
    412        1.6  augustss 	sc->sc_params.maxsize = IRDA_MAX_FRAME_SIZE;
    413        1.6  augustss 	sc->sc_wr_hdr = -1;
    414        1.6  augustss 
    415        1.6  augustss 	err = uirda_start_read(sc);
    416        1.6  augustss 	/* XXX check err */
    417        1.2  augustss 
    418   1.38.6.4     skrll 	return 0;
    419        1.1  augustss 
    420        1.1  augustss bad4:
    421   1.38.6.8     skrll 	usbd_destroy_xfer(sc->sc_rd_xfer);
    422        1.1  augustss 	sc->sc_rd_xfer = NULL;
    423        1.1  augustss bad3:
    424        1.1  augustss 	usbd_close_pipe(sc->sc_wr_pipe);
    425        1.1  augustss 	sc->sc_wr_pipe = NULL;
    426        1.1  augustss bad2:
    427        1.1  augustss 	usbd_close_pipe(sc->sc_rd_pipe);
    428        1.1  augustss 	sc->sc_rd_pipe = NULL;
    429        1.1  augustss bad1:
    430   1.38.6.4     skrll 	return error;
    431        1.1  augustss }
    432        1.1  augustss 
    433        1.1  augustss int
    434       1.22  christos uirda_close(void *h, int flag, int mode,
    435       1.22  christos     struct lwp *l)
    436        1.1  augustss {
    437        1.1  augustss 	struct uirda_softc *sc = h;
    438        1.1  augustss 
    439       1.10  augustss 	DPRINTF(("%s: sc=%p\n", __func__, sc));
    440        1.1  augustss 
    441        1.1  augustss 	if (sc->sc_rd_pipe != NULL) {
    442        1.1  augustss 		usbd_abort_pipe(sc->sc_rd_pipe);
    443        1.1  augustss 	}
    444        1.2  augustss 	if (sc->sc_wr_pipe != NULL) {
    445        1.2  augustss 		usbd_abort_pipe(sc->sc_wr_pipe);
    446        1.2  augustss 	}
    447        1.1  augustss 	if (sc->sc_rd_xfer != NULL) {
    448   1.38.6.8     skrll 		usbd_destroy_xfer(sc->sc_rd_xfer);
    449        1.1  augustss 		sc->sc_rd_xfer = NULL;
    450        1.2  augustss 		sc->sc_rd_buf = NULL;
    451        1.1  augustss 	}
    452        1.1  augustss 	if (sc->sc_wr_xfer != NULL) {
    453   1.38.6.8     skrll 		usbd_destroy_xfer(sc->sc_wr_xfer);
    454        1.1  augustss 		sc->sc_wr_xfer = NULL;
    455        1.2  augustss 		sc->sc_wr_buf = NULL;
    456        1.1  augustss 	}
    457   1.38.6.9     skrll 	if (sc->sc_rd_pipe != NULL) {
    458   1.38.6.9     skrll 		usbd_close_pipe(sc->sc_rd_pipe);
    459   1.38.6.9     skrll 		sc->sc_rd_pipe = NULL;
    460   1.38.6.9     skrll 	}
    461   1.38.6.9     skrll 	if (sc->sc_wr_pipe != NULL) {
    462   1.38.6.9     skrll 		usbd_close_pipe(sc->sc_wr_pipe);
    463   1.38.6.9     skrll 		sc->sc_wr_pipe = NULL;
    464   1.38.6.9     skrll 	}
    465        1.1  augustss 
    466   1.38.6.4     skrll 	return 0;
    467        1.1  augustss }
    468        1.1  augustss 
    469        1.1  augustss int
    470       1.22  christos uirda_read(void *h, struct uio *uio, int flag)
    471        1.1  augustss {
    472        1.1  augustss 	struct uirda_softc *sc = h;
    473        1.1  augustss 	int s;
    474        1.1  augustss 	int error;
    475        1.2  augustss 	u_int n;
    476        1.1  augustss 
    477       1.10  augustss 	DPRINTFN(1,("%s: sc=%p\n", __func__, sc));
    478        1.1  augustss 
    479        1.1  augustss 	if (sc->sc_dying)
    480   1.38.6.4     skrll 		return EIO;
    481        1.1  augustss 
    482        1.5  augustss #ifdef DIAGNOSTIC
    483        1.1  augustss 	if (sc->sc_rd_buf == NULL)
    484   1.38.6.4     skrll 		return EINVAL;
    485        1.5  augustss #endif
    486        1.1  augustss 
    487        1.2  augustss 	sc->sc_refcnt++;
    488        1.2  augustss 
    489        1.2  augustss 	do {
    490        1.2  augustss 		s = splusb();
    491        1.2  augustss 		while (sc->sc_rd_count == 0) {
    492        1.4  augustss 			DPRINTFN(5,("uirda_read: calling tsleep()\n"));
    493        1.2  augustss 			error = tsleep(&sc->sc_rd_count, PZERO | PCATCH,
    494        1.2  augustss 				       "uirdrd", 0);
    495        1.2  augustss 			if (sc->sc_dying)
    496        1.2  augustss 				error = EIO;
    497        1.2  augustss 			if (error) {
    498        1.2  augustss 				splx(s);
    499        1.2  augustss 				DPRINTF(("uirda_read: tsleep() = %d\n", error));
    500        1.2  augustss 				goto ret;
    501        1.2  augustss 			}
    502        1.1  augustss 		}
    503        1.2  augustss 		splx(s);
    504       1.11  augustss 
    505       1.26        ad 		mutex_enter(&sc->sc_rd_buf_lk);
    506       1.25        is 		n = sc->sc_rd_count - sc->sc_hdszi;
    507       1.10  augustss 		DPRINTFN(1,("%s: sc=%p n=%u, hdr=0x%02x\n", __func__,
    508        1.7  augustss 			    sc, n, sc->sc_rd_buf[0]));
    509        1.2  augustss 		if (n > uio->uio_resid)
    510        1.2  augustss 			error = EINVAL;
    511        1.2  augustss 		else
    512       1.25        is 			error = uiomove(sc->sc_rd_buf + sc->sc_hdszi, n, uio);
    513        1.2  augustss 		sc->sc_rd_count = 0;
    514       1.26        ad 		mutex_exit(&sc->sc_rd_buf_lk);
    515       1.11  augustss 
    516       1.38    martin 		uirda_start_read(sc);
    517       1.38    martin 		/* XXX check uirda_start_read() return value */
    518        1.2  augustss 
    519        1.2  augustss 	} while (n == 0);
    520        1.2  augustss 
    521        1.2  augustss 	DPRINTFN(1,("uirda_read: return %d\n", error));
    522        1.1  augustss 
    523        1.2  augustss  ret:
    524        1.1  augustss 	if (--sc->sc_refcnt < 0)
    525       1.37       mrg 		usb_detach_wakeupold(sc->sc_dev);
    526   1.38.6.4     skrll 	return error;
    527        1.1  augustss }
    528        1.1  augustss 
    529        1.1  augustss int
    530       1.22  christos uirda_write(void *h, struct uio *uio, int flag)
    531        1.1  augustss {
    532        1.1  augustss 	struct uirda_softc *sc = h;
    533        1.1  augustss 	usbd_status err;
    534   1.38.6.1     skrll 	uint32_t n;
    535        1.1  augustss 	int error = 0;
    536        1.1  augustss 
    537       1.10  augustss 	DPRINTFN(1,("%s: sc=%p\n", __func__, sc));
    538        1.1  augustss 
    539        1.1  augustss 	if (sc->sc_dying)
    540   1.38.6.4     skrll 		return EIO;
    541        1.1  augustss 
    542        1.5  augustss #ifdef DIAGNOSTIC
    543        1.5  augustss 	if (sc->sc_wr_buf == NULL)
    544   1.38.6.4     skrll 		return EINVAL;
    545        1.5  augustss #endif
    546        1.5  augustss 
    547        1.1  augustss 	n = uio->uio_resid;
    548        1.5  augustss 	if (n > sc->sc_params.maxsize)
    549   1.38.6.4     skrll 		return EINVAL;
    550        1.1  augustss 
    551        1.1  augustss 	sc->sc_refcnt++;
    552       1.26        ad 	mutex_enter(&sc->sc_wr_buf_lk);
    553        1.1  augustss 
    554        1.1  augustss 	sc->sc_wr_buf[0] = UIRDA_EB_NO_CHANGE | UIRDA_NO_SPEED;
    555        1.7  augustss 	error = uiomove(sc->sc_wr_buf + UIRDA_OUTPUT_HEADER_SIZE, n, uio);
    556   1.38.6.8     skrll 	if (error)
    557   1.38.6.8     skrll 		goto done;
    558        1.1  augustss 
    559   1.38.6.8     skrll 	DPRINTFN(1, ("uirdawrite: transfer %d bytes\n", n));
    560        1.1  augustss 
    561   1.38.6.8     skrll 	n += UIRDA_OUTPUT_HEADER_SIZE;
    562   1.38.6.8     skrll 	err = usbd_bulk_transfer(sc->sc_wr_xfer, sc->sc_wr_pipe,
    563   1.38.6.8     skrll 	    USBD_FORCE_SHORT_XFER, UIRDA_WR_TIMEOUT, sc->sc_wr_buf, &n);
    564   1.38.6.8     skrll 	DPRINTFN(2, ("uirdawrite: err=%d\n", err));
    565   1.38.6.8     skrll 	if (err) {
    566   1.38.6.8     skrll 		if (err == USBD_INTERRUPTED)
    567   1.38.6.8     skrll 			error = EINTR;
    568   1.38.6.8     skrll 		else if (err == USBD_TIMEOUT)
    569   1.38.6.8     skrll 			error = ETIMEDOUT;
    570   1.38.6.8     skrll 		else
    571   1.38.6.8     skrll 			error = EIO;
    572   1.38.6.8     skrll 	}
    573   1.38.6.8     skrll done:
    574       1.26        ad 	mutex_exit(&sc->sc_wr_buf_lk);
    575        1.1  augustss 	if (--sc->sc_refcnt < 0)
    576       1.37       mrg 		usb_detach_wakeupold(sc->sc_dev);
    577        1.1  augustss 
    578       1.10  augustss 	DPRINTFN(1,("%s: sc=%p done\n", __func__, sc));
    579   1.38.6.4     skrll 	return error;
    580        1.1  augustss }
    581        1.1  augustss 
    582        1.1  augustss int
    583       1.20  christos uirda_poll(void *h, int events, struct lwp *l)
    584        1.1  augustss {
    585        1.1  augustss 	struct uirda_softc *sc = h;
    586        1.1  augustss 	int revents = 0;
    587        1.1  augustss 	int s;
    588        1.1  augustss 
    589       1.10  augustss 	DPRINTFN(1,("%s: sc=%p\n", __func__, sc));
    590        1.1  augustss 
    591        1.1  augustss 	s = splusb();
    592        1.1  augustss 	if (events & (POLLOUT | POLLWRNORM))
    593        1.1  augustss 		revents |= events & (POLLOUT | POLLWRNORM);
    594        1.1  augustss 	if (events & (POLLIN | POLLRDNORM)) {
    595        1.1  augustss 		if (sc->sc_rd_count != 0) {
    596       1.10  augustss 			DPRINTFN(2,("%s: have data\n", __func__));
    597        1.1  augustss 			revents |= events & (POLLIN | POLLRDNORM);
    598        1.1  augustss 		} else {
    599       1.10  augustss 			DPRINTFN(2,("%s: recording select\n", __func__));
    600       1.20  christos 			selrecord(l, &sc->sc_rd_sel);
    601        1.1  augustss 		}
    602        1.1  augustss 	}
    603        1.1  augustss 	splx(s);
    604        1.1  augustss 
    605   1.38.6.4     skrll 	return revents;
    606        1.1  augustss }
    607        1.1  augustss 
    608       1.13  jdolecek static void
    609       1.13  jdolecek filt_uirdardetach(struct knote *kn)
    610       1.13  jdolecek {
    611       1.13  jdolecek 	struct uirda_softc *sc = kn->kn_hook;
    612       1.13  jdolecek 	int s;
    613       1.13  jdolecek 
    614       1.13  jdolecek 	s = splusb();
    615       1.14  christos 	SLIST_REMOVE(&sc->sc_rd_sel.sel_klist, kn, knote, kn_selnext);
    616       1.13  jdolecek 	splx(s);
    617       1.13  jdolecek }
    618       1.13  jdolecek 
    619       1.13  jdolecek static int
    620       1.22  christos filt_uirdaread(struct knote *kn, long hint)
    621       1.13  jdolecek {
    622       1.13  jdolecek 	struct uirda_softc *sc = kn->kn_hook;
    623       1.13  jdolecek 
    624       1.13  jdolecek 	kn->kn_data = sc->sc_rd_count;
    625   1.38.6.4     skrll 	return kn->kn_data > 0;
    626       1.13  jdolecek }
    627       1.13  jdolecek 
    628       1.13  jdolecek static void
    629       1.13  jdolecek filt_uirdawdetach(struct knote *kn)
    630       1.13  jdolecek {
    631       1.13  jdolecek 	struct uirda_softc *sc = kn->kn_hook;
    632       1.13  jdolecek 	int s;
    633       1.13  jdolecek 
    634       1.13  jdolecek 	s = splusb();
    635       1.14  christos 	SLIST_REMOVE(&sc->sc_wr_sel.sel_klist, kn, knote, kn_selnext);
    636       1.13  jdolecek 	splx(s);
    637       1.13  jdolecek }
    638       1.13  jdolecek 
    639       1.13  jdolecek static const struct filterops uirdaread_filtops =
    640       1.13  jdolecek 	{ 1, NULL, filt_uirdardetach, filt_uirdaread };
    641       1.13  jdolecek static const struct filterops uirdawrite_filtops =
    642       1.13  jdolecek 	{ 1, NULL, filt_uirdawdetach, filt_seltrue };
    643       1.13  jdolecek 
    644       1.13  jdolecek int
    645       1.22  christos uirda_kqfilter(void *h, struct knote *kn)
    646       1.13  jdolecek {
    647       1.13  jdolecek 	struct uirda_softc *sc = kn->kn_hook;
    648       1.13  jdolecek 	struct klist *klist;
    649       1.13  jdolecek 	int s;
    650       1.13  jdolecek 
    651       1.13  jdolecek 	switch (kn->kn_filter) {
    652       1.13  jdolecek 	case EVFILT_READ:
    653       1.14  christos 		klist = &sc->sc_rd_sel.sel_klist;
    654       1.13  jdolecek 		kn->kn_fop = &uirdaread_filtops;
    655       1.13  jdolecek 		break;
    656       1.13  jdolecek 	case EVFILT_WRITE:
    657       1.14  christos 		klist = &sc->sc_wr_sel.sel_klist;
    658       1.13  jdolecek 		kn->kn_fop = &uirdawrite_filtops;
    659       1.13  jdolecek 		break;
    660       1.13  jdolecek 	default:
    661   1.38.6.4     skrll 		return EINVAL;
    662       1.13  jdolecek 	}
    663       1.13  jdolecek 
    664       1.13  jdolecek 	kn->kn_hook = sc;
    665       1.13  jdolecek 
    666       1.13  jdolecek 	s = splusb();
    667       1.13  jdolecek 	SLIST_INSERT_HEAD(klist, kn, kn_selnext);
    668       1.13  jdolecek 	splx(s);
    669       1.13  jdolecek 
    670   1.38.6.4     skrll 	return 0;
    671       1.13  jdolecek }
    672       1.13  jdolecek 
    673        1.1  augustss int
    674        1.1  augustss uirda_set_params(void *h, struct irda_params *p)
    675        1.1  augustss {
    676        1.1  augustss 	struct uirda_softc *sc = h;
    677        1.1  augustss 	usbd_status err;
    678        1.1  augustss 	int i;
    679   1.38.6.1     skrll 	uint8_t hdr;
    680   1.38.6.1     skrll 	uint32_t n;
    681        1.1  augustss 	u_int mask;
    682        1.1  augustss 
    683       1.10  augustss 	DPRINTF(("%s: sc=%p, speed=%d ebofs=%d maxsize=%d\n", __func__,
    684        1.1  augustss 		 sc, p->speed, p->ebofs, p->maxsize));
    685        1.1  augustss 
    686        1.1  augustss 	if (sc->sc_dying)
    687   1.38.6.4     skrll 		return EIO;
    688        1.1  augustss 
    689        1.1  augustss 	hdr = 0;
    690        1.1  augustss 	if (p->ebofs != sc->sc_params.ebofs) {
    691        1.1  augustss 		/* round up ebofs */
    692       1.25        is 		mask = 1 /* sc->sc_irdadesc.bmAdditionalBOFs*/;
    693       1.25        is 		DPRINTF(("u.s.p.: mask=0x%x, sc->ebofs=%d, p->ebofs=%d\n",
    694       1.25        is 			mask, sc->sc_params.ebofs, p->ebofs));
    695        1.1  augustss 		for (i = 0; i < UIRDA_NEBOFS; i++) {
    696       1.25        is 			DPRINTF(("u.s.p.: u_e[%d].mask=0x%x, count=%d\n",
    697       1.25        is 				i, uirda_ebofs[i].mask, uirda_ebofs[i].count));
    698        1.1  augustss 			if ((mask & uirda_ebofs[i].mask) &&
    699        1.1  augustss 			    uirda_ebofs[i].count >= p->ebofs) {
    700        1.1  augustss 				hdr = uirda_ebofs[i].header;
    701        1.1  augustss 				goto found1;
    702        1.1  augustss 			}
    703        1.1  augustss 		}
    704       1.25        is 		for (i = 0; i < UIRDA_NEBOFS; i++) {
    705       1.25        is 			DPRINTF(("u.s.p.: u_e[%d].mask=0x%x, count=%d\n",
    706       1.25        is 				i, uirda_ebofs[i].mask, uirda_ebofs[i].count));
    707       1.25        is 			if ((mask & uirda_ebofs[i].mask)) {
    708       1.25        is 				hdr = uirda_ebofs[i].header;
    709       1.25        is 				goto found1;
    710       1.25        is 			}
    711       1.25        is 		}
    712        1.1  augustss 		/* no good value found */
    713   1.38.6.4     skrll 		return EINVAL;
    714        1.1  augustss 	found1:
    715        1.6  augustss 		DPRINTF(("uirda_set_params: ebofs hdr=0x%02x\n", hdr));
    716        1.1  augustss 		;
    717       1.11  augustss 
    718        1.1  augustss 	}
    719        1.6  augustss 	if (hdr != 0 || p->speed != sc->sc_params.speed) {
    720        1.1  augustss 		/* find speed */
    721        1.1  augustss 		mask = UGETW(sc->sc_irdadesc.wBaudRate);
    722        1.1  augustss 		for (i = 0; i < UIRDA_NSPEEDS; i++) {
    723        1.1  augustss 			if ((mask & uirda_speeds[i].mask) &&
    724        1.1  augustss 			    uirda_speeds[i].speed == p->speed) {
    725        1.1  augustss 				hdr |= uirda_speeds[i].header;
    726        1.1  augustss 				goto found2;
    727        1.1  augustss 			}
    728        1.1  augustss 		}
    729        1.1  augustss 		/* no good value found */
    730   1.38.6.4     skrll 		return EINVAL;
    731        1.1  augustss 	found2:
    732        1.6  augustss 		DPRINTF(("uirda_set_params: speed hdr=0x%02x\n", hdr));
    733        1.1  augustss 		;
    734        1.1  augustss 	}
    735        1.1  augustss 	if (p->maxsize != sc->sc_params.maxsize) {
    736        1.5  augustss 		if (p->maxsize > IRDA_MAX_FRAME_SIZE)
    737   1.38.6.4     skrll 			return EINVAL;
    738        1.5  augustss 		sc->sc_params.maxsize = p->maxsize;
    739        1.5  augustss #if 0
    740       1.10  augustss 		DPRINTF(("%s: new buffers, old size=%d\n", __func__,
    741        1.2  augustss 			 sc->sc_params.maxsize));
    742        1.1  augustss 		if (p->maxsize > 10000 || p < 0) /* XXX */
    743   1.38.6.4     skrll 			return EINVAL;
    744        1.1  augustss 
    745        1.1  augustss 		/* Change the write buffer */
    746       1.26        ad 		mutex_enter(&sc->sc_wr_buf_lk);
    747        1.1  augustss 		if (sc->sc_wr_buf != NULL)
    748        1.1  augustss 			usbd_free_buffer(sc->sc_wr_xfer);
    749   1.38.6.8     skrll 		sc->sc_wr_buf = usbd_get_buffer(sc->sc_wr_xfer, p->maxsize+1);
    750       1.26        ad 		mutex_exit(&sc->sc_wr_buf_lk);
    751        1.1  augustss 		if (sc->sc_wr_buf == NULL)
    752   1.38.6.4     skrll 			return ENOMEM;
    753        1.1  augustss 
    754        1.1  augustss 		/* Change the read buffer */
    755       1.26        ad 		mutex_enter(&sc->sc_rd_buf_lk);
    756        1.1  augustss 		usbd_abort_pipe(sc->sc_rd_pipe);
    757        1.1  augustss 		if (sc->sc_rd_buf != NULL)
    758        1.1  augustss 			usbd_free_buffer(sc->sc_rd_xfer);
    759   1.38.6.8     skrll 		sc->sc_rd_buf = usbd_get_buffer(sc->sc_rd_xfer, p->maxsize+1);
    760        1.1  augustss 		sc->sc_rd_count = 0;
    761        1.2  augustss 		if (sc->sc_rd_buf == NULL) {
    762       1.26        ad 			mutex_exit(&sc->sc_rd_buf_lk);
    763   1.38.6.4     skrll 			return ENOMEM;
    764        1.2  augustss 		}
    765        1.4  augustss 		sc->sc_params.maxsize = p->maxsize;
    766        1.1  augustss 		err = uirda_start_read(sc); /* XXX check */
    767       1.26        ad 		mutex_exit(&sc->sc_rd_buf_lk);
    768        1.5  augustss #endif
    769        1.1  augustss 	}
    770        1.6  augustss 	if (hdr != 0 && hdr != sc->sc_wr_hdr) {
    771       1.11  augustss 		/*
    772        1.1  augustss 		 * A change has occurred, transmit a 0 length frame with
    773        1.1  augustss 		 * the new settings.  The 0 length frame is not sent to the
    774        1.1  augustss 		 * device.
    775        1.1  augustss 		 */
    776        1.6  augustss 		DPRINTF(("%s: sc=%p setting header 0x%02x\n",
    777       1.10  augustss 			 __func__, sc, hdr));
    778        1.6  augustss 		sc->sc_wr_hdr = hdr;
    779       1.26        ad 		mutex_enter(&sc->sc_wr_buf_lk);
    780        1.2  augustss 		sc->sc_wr_buf[0] = hdr;
    781        1.7  augustss 		n = UIRDA_OUTPUT_HEADER_SIZE;
    782        1.1  augustss 		err = usbd_bulk_transfer(sc->sc_wr_xfer, sc->sc_wr_pipe,
    783   1.38.6.8     skrll 		    USBD_FORCE_SHORT_XFER, UIRDA_WR_TIMEOUT,
    784   1.38.6.8     skrll 		    sc->sc_wr_buf, &n);
    785        1.2  augustss 		if (err) {
    786       1.31      cube 			aprint_error_dev(sc->sc_dev, "set failed, err=%d\n",
    787       1.31      cube 			    err);
    788        1.1  augustss 			usbd_clear_endpoint_stall(sc->sc_wr_pipe);
    789        1.1  augustss 		}
    790       1.26        ad 		mutex_exit(&sc->sc_wr_buf_lk);
    791        1.1  augustss 	}
    792        1.1  augustss 
    793        1.1  augustss 	sc->sc_params = *p;
    794        1.1  augustss 
    795   1.38.6.4     skrll 	return 0;
    796        1.1  augustss }
    797        1.1  augustss 
    798        1.1  augustss int
    799        1.1  augustss uirda_get_speeds(void *h, int *speeds)
    800        1.1  augustss {
    801        1.1  augustss 	struct uirda_softc *sc = h;
    802        1.1  augustss 	u_int isp;
    803        1.1  augustss 	u_int usp;
    804        1.1  augustss 
    805       1.10  augustss 	DPRINTF(("%s: sc=%p\n", __func__, sc));
    806        1.1  augustss 
    807        1.1  augustss 	if (sc->sc_dying)
    808   1.38.6.4     skrll 		return EIO;
    809        1.1  augustss 
    810        1.1  augustss 	usp = UGETW(sc->sc_irdadesc.wBaudRate);
    811        1.1  augustss 	isp = 0;
    812        1.1  augustss 	if (usp & UI_BR_4000000) isp |= IRDA_SPEED_4000000;
    813        1.1  augustss 	if (usp & UI_BR_1152000) isp |= IRDA_SPEED_1152000;
    814        1.1  augustss 	if (usp & UI_BR_576000)  isp |= IRDA_SPEED_576000;
    815        1.1  augustss 	if (usp & UI_BR_115200)  isp |= IRDA_SPEED_115200;
    816        1.1  augustss 	if (usp & UI_BR_57600)   isp |= IRDA_SPEED_57600;
    817        1.1  augustss 	if (usp & UI_BR_38400)   isp |= IRDA_SPEED_38400;
    818        1.1  augustss 	if (usp & UI_BR_19200)   isp |= IRDA_SPEED_19200;
    819        1.1  augustss 	if (usp & UI_BR_9600)    isp |= IRDA_SPEED_9600;
    820        1.1  augustss 	if (usp & UI_BR_2400)    isp |= IRDA_SPEED_2400;
    821        1.1  augustss 	*speeds = isp;
    822       1.25        is 	DPRINTF(("%s: speeds = 0x%x\n", __func__, isp));
    823   1.38.6.4     skrll 	return 0;
    824        1.1  augustss }
    825        1.1  augustss 
    826        1.1  augustss int
    827        1.1  augustss uirda_get_turnarounds(void *h, int *turnarounds)
    828        1.1  augustss {
    829        1.1  augustss 	struct uirda_softc *sc = h;
    830        1.1  augustss 	u_int ita;
    831        1.1  augustss 	u_int uta;
    832        1.1  augustss 
    833       1.10  augustss 	DPRINTF(("%s: sc=%p\n", __func__, sc));
    834        1.1  augustss 
    835        1.1  augustss 	if (sc->sc_dying)
    836   1.38.6.4     skrll 		return EIO;
    837        1.1  augustss 
    838        1.1  augustss 	uta = sc->sc_irdadesc.bmMinTurnaroundTime;
    839        1.1  augustss 	ita = 0;
    840        1.1  augustss 	if (uta & UI_TA_0)     ita |= IRDA_TURNT_0;
    841        1.1  augustss 	if (uta & UI_TA_10)    ita |= IRDA_TURNT_10;
    842        1.1  augustss 	if (uta & UI_TA_50)    ita |= IRDA_TURNT_50;
    843        1.1  augustss 	if (uta & UI_TA_100)   ita |= IRDA_TURNT_100;
    844        1.1  augustss 	if (uta & UI_TA_500)   ita |= IRDA_TURNT_500;
    845        1.1  augustss 	if (uta & UI_TA_1000)  ita |= IRDA_TURNT_1000;
    846        1.1  augustss 	if (uta & UI_TA_5000)  ita |= IRDA_TURNT_5000;
    847        1.1  augustss 	if (uta & UI_TA_10000) ita |= IRDA_TURNT_10000;
    848        1.1  augustss 	*turnarounds = ita;
    849   1.38.6.4     skrll 	return 0;
    850        1.1  augustss }
    851        1.1  augustss 
    852        1.1  augustss void
    853   1.38.6.6     skrll uirda_rd_cb(struct usbd_xfer *xfer, void *priv,
    854        1.1  augustss 	    usbd_status status)
    855        1.1  augustss {
    856        1.1  augustss 	struct uirda_softc *sc = priv;
    857   1.38.6.1     skrll 	uint32_t size;
    858        1.1  augustss 
    859       1.10  augustss 	DPRINTFN(1,("%s: sc=%p\n", __func__, sc));
    860        1.2  augustss 
    861        1.1  augustss 	if (status == USBD_CANCELLED) /* this is normal */
    862        1.1  augustss 		return;
    863        1.1  augustss 	if (status) {
    864       1.25        is 		size = sc->sc_hdszi;
    865        1.4  augustss 		sc->sc_rd_err = 1;
    866        1.4  augustss 	} else {
    867        1.4  augustss 		usbd_get_xfer_status(xfer, NULL, NULL, &size, NULL);
    868        1.1  augustss 	}
    869       1.10  augustss 	DPRINTFN(1,("%s: sc=%p size=%u, err=%d\n", __func__, sc, size,
    870        1.4  augustss 		    sc->sc_rd_err));
    871        1.1  augustss 	sc->sc_rd_count = size;
    872        1.2  augustss 	wakeup(&sc->sc_rd_count); /* XXX should use flag */
    873       1.29     rmind 	selnotify(&sc->sc_rd_sel, 0, 0);
    874        1.1  augustss }
    875        1.1  augustss 
    876        1.1  augustss usbd_status
    877        1.1  augustss uirda_start_read(struct uirda_softc *sc)
    878        1.1  augustss {
    879        1.1  augustss 	usbd_status err;
    880        1.1  augustss 
    881       1.10  augustss 	DPRINTFN(1,("%s: sc=%p, size=%d\n", __func__, sc,
    882        1.7  augustss 		    sc->sc_params.maxsize + UIRDA_INPUT_HEADER_SIZE));
    883        1.2  augustss 
    884        1.1  augustss 	if (sc->sc_dying)
    885   1.38.6.4     skrll 		return USBD_IOERROR;
    886        1.1  augustss 
    887        1.4  augustss 	if (sc->sc_rd_err) {
    888        1.4  augustss 		sc->sc_rd_err = 0;
    889        1.4  augustss 		DPRINTF(("uirda_start_read: clear stall\n"));
    890        1.4  augustss 		usbd_clear_endpoint_stall(sc->sc_rd_pipe);
    891        1.4  augustss 	}
    892        1.4  augustss 
    893   1.38.6.8     skrll 	usbd_setup_xfer(sc->sc_rd_xfer, sc, sc->sc_rd_buf,
    894   1.38.6.8     skrll 	    sc->sc_params.maxsize + sc->sc_hdszi, USBD_SHORT_XFER_OK,
    895   1.38.6.8     skrll 	    USBD_NO_TIMEOUT, uirda_rd_cb);
    896        1.1  augustss 	err = usbd_transfer(sc->sc_rd_xfer);
    897        1.4  augustss 	if (err != USBD_IN_PROGRESS) {
    898        1.4  augustss 		DPRINTF(("uirda_start_read: err=%d\n", err));
    899   1.38.6.4     skrll 		return err;
    900        1.4  augustss 	}
    901   1.38.6.4     skrll 	return USBD_NORMAL_COMPLETION;
    902        1.1  augustss }
    903       1.25        is 
    904       1.25        is usbd_status
    905   1.38.6.6     skrll usbd_get_class_desc(struct usbd_device *dev, int type, int index, int len, void *desc)
    906       1.25        is {
    907       1.25        is 	usb_device_request_t req;
    908       1.25        is 
    909       1.25        is 	DPRINTFN(3,("usbd_get_desc: type=%d, index=%d, len=%d\n",
    910       1.25        is 		    type, index, len));
    911       1.25        is 
    912       1.25        is 	req.bmRequestType = 0xa1; /* XXX ? */
    913       1.25        is 	req.bRequest = UR_GET_DESCRIPTOR;
    914       1.25        is 	USETW2(req.wValue, type, index);
    915       1.25        is 	USETW(req.wIndex, 0);
    916       1.25        is 	USETW(req.wLength, len);
    917   1.38.6.4     skrll 	return usbd_do_request(dev, &req, desc);
    918       1.25        is }
    919