1 1.15 thorpej /* $NetBSD: udsir.c,v 1.15 2021/09/26 01:16:09 thorpej Exp $ */ 2 1.1 kiyohara 3 1.1 kiyohara /* 4 1.1 kiyohara * Copyright (c) 2001 The NetBSD Foundation, Inc. 5 1.1 kiyohara * All rights reserved. 6 1.1 kiyohara * 7 1.1 kiyohara * This code is derived from software contributed to The NetBSD Foundation 8 1.9 dsainty * by David Sainty <dsainty (at) NetBSD.org> 9 1.1 kiyohara * 10 1.1 kiyohara * Redistribution and use in source and binary forms, with or without 11 1.1 kiyohara * modification, are permitted provided that the following conditions 12 1.1 kiyohara * are met: 13 1.1 kiyohara * 1. Redistributions of source code must retain the above copyright 14 1.1 kiyohara * notice, this list of conditions and the following disclaimer. 15 1.1 kiyohara * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 kiyohara * notice, this list of conditions and the following disclaimer in the 17 1.1 kiyohara * documentation and/or other materials provided with the distribution. 18 1.1 kiyohara * 19 1.1 kiyohara * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 kiyohara * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 kiyohara * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 kiyohara * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 kiyohara * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 kiyohara * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 kiyohara * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 kiyohara * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 kiyohara * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 kiyohara * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 kiyohara * POSSIBILITY OF SUCH DAMAGE. 30 1.1 kiyohara */ 31 1.1 kiyohara 32 1.1 kiyohara #include <sys/cdefs.h> 33 1.15 thorpej __KERNEL_RCSID(0, "$NetBSD: udsir.c,v 1.15 2021/09/26 01:16:09 thorpej Exp $"); 34 1.1 kiyohara 35 1.1 kiyohara #include <sys/param.h> 36 1.1 kiyohara #include <sys/device.h> 37 1.1 kiyohara #include <sys/errno.h> 38 1.1 kiyohara #include <sys/systm.h> 39 1.1 kiyohara #include <sys/kernel.h> 40 1.2 skrll #include <sys/kmem.h> 41 1.1 kiyohara #include <sys/conf.h> 42 1.1 kiyohara #include <sys/file.h> 43 1.1 kiyohara #include <sys/poll.h> 44 1.1 kiyohara #include <sys/select.h> 45 1.1 kiyohara #include <sys/proc.h> 46 1.1 kiyohara #include <sys/kthread.h> 47 1.1 kiyohara 48 1.1 kiyohara #include <dev/usb/usb.h> 49 1.1 kiyohara #include <dev/usb/usbdevs.h> 50 1.1 kiyohara #include <dev/usb/usbdi.h> 51 1.1 kiyohara #include <dev/usb/usbdi_util.h> 52 1.1 kiyohara 53 1.1 kiyohara #include <dev/ir/ir.h> 54 1.1 kiyohara #include <dev/ir/irdaio.h> 55 1.1 kiyohara #include <dev/ir/irframevar.h> 56 1.1 kiyohara #include <dev/ir/sir.h> 57 1.1 kiyohara 58 1.1 kiyohara #ifdef UDSIR_DEBUG 59 1.1 kiyohara #define DPRINTFN(n,x) if (udsirdebug > (n)) printf x 60 1.1 kiyohara int udsirdebug = 0; 61 1.1 kiyohara #else 62 1.1 kiyohara #define DPRINTFN(n,x) 63 1.1 kiyohara #endif 64 1.1 kiyohara 65 1.1 kiyohara /* Max size with framing. */ 66 1.1 kiyohara #define MAX_UDSIR_OUTPUT_FRAME (2 * IRDA_MAX_FRAME_SIZE + IRDA_MAX_EBOFS + 4) 67 1.1 kiyohara 68 1.1 kiyohara struct udsir_softc { 69 1.1 kiyohara device_t sc_dev; 70 1.2 skrll struct usbd_device *sc_udev; 71 1.2 skrll struct usbd_interface *sc_iface; 72 1.1 kiyohara 73 1.1 kiyohara uint8_t *sc_ur_buf; /* Unencapsulated frame */ 74 1.1 kiyohara u_int sc_ur_framelen; 75 1.1 kiyohara 76 1.1 kiyohara uint8_t *sc_rd_buf; /* Raw incoming data stream */ 77 1.1 kiyohara int sc_rd_maxpsz; 78 1.1 kiyohara size_t sc_rd_index; 79 1.1 kiyohara int sc_rd_addr; 80 1.2 skrll struct usbd_pipe *sc_rd_pipe; 81 1.2 skrll struct usbd_xfer *sc_rd_xfer; 82 1.1 kiyohara u_int sc_rd_count; 83 1.1 kiyohara int sc_rd_readinprogress; 84 1.1 kiyohara int sc_rd_expectdataticks; 85 1.1 kiyohara u_char sc_rd_err; 86 1.1 kiyohara struct framestate sc_framestate; 87 1.1 kiyohara struct lwp *sc_thread; 88 1.1 kiyohara struct selinfo sc_rd_sel; 89 1.1 kiyohara 90 1.1 kiyohara uint8_t *sc_wr_buf; 91 1.1 kiyohara int sc_wr_maxpsz; 92 1.1 kiyohara int sc_wr_addr; 93 1.1 kiyohara int sc_wr_stalewrite; 94 1.2 skrll struct usbd_xfer *sc_wr_xfer; 95 1.2 skrll struct usbd_pipe *sc_wr_pipe; 96 1.1 kiyohara struct selinfo sc_wr_sel; 97 1.1 kiyohara 98 1.1 kiyohara enum { 99 1.1 kiyohara udir_input, /* Receiving data */ 100 1.1 kiyohara udir_output, /* Transmitting data */ 101 1.1 kiyohara udir_stalled, /* Error preventing data flow */ 102 1.1 kiyohara udir_idle /* Neither receiving nor transmitting */ 103 1.1 kiyohara } sc_direction; 104 1.1 kiyohara 105 1.1 kiyohara device_t sc_child; 106 1.1 kiyohara struct irda_params sc_params; 107 1.1 kiyohara 108 1.1 kiyohara int sc_refcnt; 109 1.1 kiyohara char sc_closing; 110 1.1 kiyohara char sc_dying; 111 1.1 kiyohara }; 112 1.1 kiyohara 113 1.1 kiyohara /* True if we cannot safely read data from the device */ 114 1.1 kiyohara #define UDSIR_BLOCK_RX_DATA(sc) ((sc)->sc_ur_framelen != 0) 115 1.1 kiyohara 116 1.1 kiyohara #define UDSIR_WR_TIMEOUT 200 117 1.1 kiyohara 118 1.1 kiyohara static int udsir_match(device_t, cfdata_t, void *); 119 1.1 kiyohara static void udsir_attach(device_t, device_t, void *); 120 1.1 kiyohara static int udsir_detach(device_t, int); 121 1.1 kiyohara static void udsir_childdet(device_t, device_t); 122 1.1 kiyohara static int udsir_activate(device_t, enum devact); 123 1.1 kiyohara 124 1.1 kiyohara static int udsir_open(void *, int, int, struct lwp *); 125 1.1 kiyohara static int udsir_close(void *, int, int, struct lwp *); 126 1.1 kiyohara static int udsir_read(void *, struct uio *, int); 127 1.1 kiyohara static int udsir_write(void *, struct uio *, int); 128 1.1 kiyohara static int udsir_poll(void *, int, struct lwp *); 129 1.1 kiyohara static int udsir_kqfilter(void *, struct knote *); 130 1.1 kiyohara static int udsir_set_params(void *, struct irda_params *); 131 1.1 kiyohara static int udsir_get_speeds(void *, int *); 132 1.1 kiyohara static int udsir_get_turnarounds(void *, int *); 133 1.1 kiyohara 134 1.1 kiyohara static void filt_udsirrdetach(struct knote *); 135 1.1 kiyohara static int filt_udsirread(struct knote *, long); 136 1.1 kiyohara static void filt_udsirwdetach(struct knote *); 137 1.1 kiyohara static int filt_udsirwrite(struct knote *, long); 138 1.1 kiyohara 139 1.1 kiyohara static void udsir_thread(void *); 140 1.1 kiyohara 141 1.1 kiyohara #ifdef UDSIR_DEBUG 142 1.1 kiyohara static void udsir_dumpdata(uint8_t const *, size_t, char const *); 143 1.1 kiyohara #endif 144 1.1 kiyohara static int deframe_rd_ur(struct udsir_softc *); 145 1.1 kiyohara static void udsir_periodic(struct udsir_softc *); 146 1.2 skrll static void udsir_rd_cb(struct usbd_xfer *, void *, usbd_status); 147 1.1 kiyohara static usbd_status udsir_start_read(struct udsir_softc *); 148 1.1 kiyohara 149 1.1 kiyohara CFATTACH_DECL2_NEW(udsir, sizeof(struct udsir_softc), 150 1.1 kiyohara udsir_match, udsir_attach, udsir_detach, 151 1.1 kiyohara udsir_activate, NULL, udsir_childdet); 152 1.1 kiyohara 153 1.1 kiyohara static struct irframe_methods const udsir_methods = { 154 1.1 kiyohara udsir_open, udsir_close, udsir_read, udsir_write, udsir_poll, 155 1.1 kiyohara udsir_kqfilter, udsir_set_params, udsir_get_speeds, udsir_get_turnarounds, 156 1.1 kiyohara }; 157 1.1 kiyohara 158 1.1 kiyohara static int 159 1.1 kiyohara udsir_match(device_t parent, cfdata_t match, void *aux) 160 1.1 kiyohara { 161 1.2 skrll struct usbif_attach_arg *uiaa = aux; 162 1.1 kiyohara 163 1.1 kiyohara DPRINTFN(50, ("udsir_match\n")); 164 1.1 kiyohara 165 1.2 skrll if (uiaa->uiaa_vendor == USB_VENDOR_KINGSUN && 166 1.2 skrll uiaa->uiaa_product == USB_PRODUCT_KINGSUN_IRDA) 167 1.1 kiyohara return UMATCH_VENDOR_PRODUCT; 168 1.1 kiyohara 169 1.1 kiyohara return UMATCH_NONE; 170 1.1 kiyohara } 171 1.1 kiyohara 172 1.1 kiyohara static void 173 1.1 kiyohara udsir_attach(device_t parent, device_t self, void *aux) 174 1.1 kiyohara { 175 1.1 kiyohara struct udsir_softc *sc = device_private(self); 176 1.2 skrll struct usbif_attach_arg *uiaa = aux; 177 1.2 skrll struct usbd_device *dev = uiaa->uiaa_device; 178 1.2 skrll struct usbd_interface *iface = uiaa->uiaa_iface; 179 1.1 kiyohara char *devinfop; 180 1.1 kiyohara usb_endpoint_descriptor_t *ed; 181 1.1 kiyohara uint8_t epcount; 182 1.1 kiyohara int i; 183 1.1 kiyohara struct ir_attach_args ia; 184 1.1 kiyohara 185 1.1 kiyohara DPRINTFN(10, ("udsir_attach: sc=%p\n", sc)); 186 1.1 kiyohara 187 1.1 kiyohara sc->sc_dev = self; 188 1.1 kiyohara 189 1.1 kiyohara aprint_naive("\n"); 190 1.1 kiyohara aprint_normal("\n"); 191 1.1 kiyohara 192 1.1 kiyohara devinfop = usbd_devinfo_alloc(dev, 0); 193 1.1 kiyohara aprint_normal_dev(self, "%s\n", devinfop); 194 1.1 kiyohara usbd_devinfo_free(devinfop); 195 1.1 kiyohara 196 1.1 kiyohara sc->sc_udev = dev; 197 1.1 kiyohara sc->sc_iface = iface; 198 1.1 kiyohara 199 1.1 kiyohara epcount = 0; 200 1.1 kiyohara (void)usbd_endpoint_count(iface, &epcount); 201 1.1 kiyohara 202 1.1 kiyohara sc->sc_rd_addr = -1; 203 1.1 kiyohara sc->sc_wr_addr = -1; 204 1.1 kiyohara for (i = 0; i < epcount; i++) { 205 1.1 kiyohara ed = usbd_interface2endpoint_descriptor(iface, i); 206 1.1 kiyohara if (ed == NULL) { 207 1.1 kiyohara aprint_error_dev(self, "couldn't get ep %d\n", i); 208 1.1 kiyohara return; 209 1.1 kiyohara } 210 1.1 kiyohara if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 211 1.1 kiyohara UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { 212 1.1 kiyohara sc->sc_rd_addr = ed->bEndpointAddress; 213 1.1 kiyohara sc->sc_rd_maxpsz = UGETW(ed->wMaxPacketSize); 214 1.1 kiyohara } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && 215 1.1 kiyohara UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { 216 1.1 kiyohara sc->sc_wr_addr = ed->bEndpointAddress; 217 1.1 kiyohara sc->sc_wr_maxpsz = UGETW(ed->wMaxPacketSize); 218 1.1 kiyohara } 219 1.1 kiyohara } 220 1.1 kiyohara if (sc->sc_rd_addr == -1 || sc->sc_wr_addr == -1) { 221 1.1 kiyohara aprint_error_dev(self, "missing endpoint\n"); 222 1.1 kiyohara return; 223 1.1 kiyohara } 224 1.1 kiyohara 225 1.1 kiyohara DPRINTFN(10, ("udsir_attach: %p\n", sc->sc_udev)); 226 1.1 kiyohara 227 1.3 msaitoh usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev); 228 1.1 kiyohara 229 1.1 kiyohara ia.ia_type = IR_TYPE_IRFRAME; 230 1.1 kiyohara ia.ia_methods = &udsir_methods; 231 1.1 kiyohara ia.ia_handle = sc; 232 1.1 kiyohara 233 1.14 thorpej sc->sc_child = config_found(self, &ia, ir_print, CFARGS_NONE); 234 1.1 kiyohara selinit(&sc->sc_rd_sel); 235 1.1 kiyohara selinit(&sc->sc_wr_sel); 236 1.1 kiyohara 237 1.1 kiyohara return; 238 1.1 kiyohara } 239 1.1 kiyohara 240 1.1 kiyohara static int 241 1.1 kiyohara udsir_detach(device_t self, int flags) 242 1.1 kiyohara { 243 1.1 kiyohara struct udsir_softc *sc = device_private(self); 244 1.1 kiyohara int s; 245 1.1 kiyohara int rv = 0; 246 1.1 kiyohara 247 1.1 kiyohara DPRINTFN(0, ("udsir_detach: sc=%p flags=%d\n", sc, flags)); 248 1.1 kiyohara 249 1.1 kiyohara sc->sc_closing = sc->sc_dying = 1; 250 1.1 kiyohara 251 1.1 kiyohara wakeup(&sc->sc_thread); 252 1.1 kiyohara 253 1.1 kiyohara while (sc->sc_thread != NULL) 254 1.1 kiyohara tsleep(&sc->sc_closing, PWAIT, "usircl", 0); 255 1.1 kiyohara 256 1.1 kiyohara /* Abort all pipes. Causes processes waiting for transfer to wake. */ 257 1.1 kiyohara if (sc->sc_rd_pipe != NULL) { 258 1.1 kiyohara usbd_abort_pipe(sc->sc_rd_pipe); 259 1.2 skrll } 260 1.2 skrll if (sc->sc_wr_pipe != NULL) { 261 1.2 skrll usbd_abort_pipe(sc->sc_wr_pipe); 262 1.2 skrll } 263 1.2 skrll if (sc->sc_rd_xfer != NULL) { 264 1.2 skrll usbd_destroy_xfer(sc->sc_rd_xfer); 265 1.2 skrll sc->sc_rd_xfer = NULL; 266 1.2 skrll sc->sc_rd_buf = NULL; 267 1.2 skrll } 268 1.2 skrll if (sc->sc_wr_xfer != NULL) { 269 1.2 skrll usbd_destroy_xfer(sc->sc_wr_xfer); 270 1.2 skrll sc->sc_wr_xfer = NULL; 271 1.2 skrll sc->sc_wr_buf = NULL; 272 1.2 skrll } 273 1.2 skrll /* Close pipes. */ 274 1.2 skrll if (sc->sc_rd_pipe != NULL) { 275 1.1 kiyohara usbd_close_pipe(sc->sc_rd_pipe); 276 1.1 kiyohara sc->sc_rd_pipe = NULL; 277 1.1 kiyohara } 278 1.1 kiyohara if (sc->sc_wr_pipe != NULL) { 279 1.1 kiyohara usbd_close_pipe(sc->sc_wr_pipe); 280 1.1 kiyohara sc->sc_wr_pipe = NULL; 281 1.1 kiyohara } 282 1.1 kiyohara wakeup(&sc->sc_ur_framelen); 283 1.1 kiyohara wakeup(&sc->sc_wr_buf); 284 1.1 kiyohara 285 1.1 kiyohara s = splusb(); 286 1.1 kiyohara if (--sc->sc_refcnt >= 0) { 287 1.1 kiyohara /* Wait for processes to go away. */ 288 1.1 kiyohara usb_detach_waitold(sc->sc_dev); 289 1.1 kiyohara } 290 1.1 kiyohara splx(s); 291 1.1 kiyohara 292 1.1 kiyohara if (sc->sc_child != NULL) 293 1.1 kiyohara rv = config_detach(sc->sc_child, flags); 294 1.1 kiyohara 295 1.1 kiyohara usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev); 296 1.1 kiyohara 297 1.1 kiyohara seldestroy(&sc->sc_rd_sel); 298 1.1 kiyohara seldestroy(&sc->sc_wr_sel); 299 1.1 kiyohara 300 1.1 kiyohara return rv; 301 1.1 kiyohara } 302 1.1 kiyohara 303 1.1 kiyohara static void 304 1.1 kiyohara udsir_childdet(device_t self, device_t child) 305 1.1 kiyohara { 306 1.1 kiyohara struct udsir_softc *sc = device_private(self); 307 1.1 kiyohara 308 1.1 kiyohara KASSERT(sc->sc_child == child); 309 1.1 kiyohara sc->sc_child = NULL; 310 1.1 kiyohara } 311 1.1 kiyohara 312 1.1 kiyohara static int 313 1.1 kiyohara udsir_activate(device_t self, enum devact act) 314 1.1 kiyohara { 315 1.1 kiyohara struct udsir_softc *sc = device_private(self); 316 1.1 kiyohara 317 1.1 kiyohara switch (act) { 318 1.1 kiyohara case DVACT_DEACTIVATE: 319 1.1 kiyohara sc->sc_dying = 1; 320 1.1 kiyohara return 0; 321 1.1 kiyohara default: 322 1.1 kiyohara return EOPNOTSUPP; 323 1.1 kiyohara } 324 1.1 kiyohara } 325 1.1 kiyohara 326 1.1 kiyohara /* ARGSUSED */ 327 1.1 kiyohara static int 328 1.1 kiyohara udsir_open(void *h, int flag, int mode, struct lwp *l) 329 1.1 kiyohara { 330 1.1 kiyohara struct udsir_softc *sc = h; 331 1.1 kiyohara int error; 332 1.1 kiyohara usbd_status err; 333 1.1 kiyohara 334 1.1 kiyohara DPRINTFN(0, ("%s: sc=%p\n", __func__, sc)); 335 1.1 kiyohara 336 1.1 kiyohara err = usbd_open_pipe(sc->sc_iface, sc->sc_rd_addr, 0, &sc->sc_rd_pipe); 337 1.1 kiyohara if (err != USBD_NORMAL_COMPLETION) { 338 1.1 kiyohara error = EIO; 339 1.1 kiyohara goto bad1; 340 1.1 kiyohara } 341 1.1 kiyohara err = usbd_open_pipe(sc->sc_iface, sc->sc_wr_addr, 0, &sc->sc_wr_pipe); 342 1.1 kiyohara if (err != USBD_NORMAL_COMPLETION) { 343 1.1 kiyohara error = EIO; 344 1.1 kiyohara goto bad2; 345 1.1 kiyohara } 346 1.2 skrll error = usbd_create_xfer(sc->sc_rd_pipe, sc->sc_rd_maxpsz, 347 1.6 skrll 0, 0, &sc->sc_rd_xfer); 348 1.2 skrll if (error) 349 1.2 skrll goto bad3; 350 1.2 skrll 351 1.2 skrll error = usbd_create_xfer(sc->sc_wr_pipe, IRDA_MAX_FRAME_SIZE, 352 1.2 skrll USBD_FORCE_SHORT_XFER, 0, &sc->sc_wr_xfer); 353 1.2 skrll if (error) 354 1.1 kiyohara goto bad4; 355 1.2 skrll 356 1.2 skrll sc->sc_rd_buf = usbd_get_buffer(sc->sc_rd_xfer); 357 1.2 skrll sc->sc_wr_buf = usbd_get_buffer(sc->sc_wr_xfer); 358 1.2 skrll 359 1.2 skrll sc->sc_ur_buf = kmem_alloc(IRDA_MAX_FRAME_SIZE, KM_SLEEP); 360 1.1 kiyohara sc->sc_rd_index = sc->sc_rd_count = 0; 361 1.1 kiyohara sc->sc_closing = 0; 362 1.1 kiyohara sc->sc_rd_readinprogress = 0; 363 1.1 kiyohara sc->sc_rd_expectdataticks = 0; 364 1.1 kiyohara sc->sc_ur_framelen = 0; 365 1.1 kiyohara sc->sc_rd_err = 0; 366 1.1 kiyohara sc->sc_wr_stalewrite = 0; 367 1.1 kiyohara sc->sc_direction = udir_idle; 368 1.1 kiyohara sc->sc_params.speed = 0; 369 1.1 kiyohara sc->sc_params.ebofs = 0; 370 1.7 riastrad sc->sc_params.maxsize = uimin(sc->sc_rd_maxpsz, sc->sc_wr_maxpsz); 371 1.1 kiyohara 372 1.1 kiyohara deframe_init(&sc->sc_framestate, sc->sc_ur_buf, IRDA_MAX_FRAME_SIZE); 373 1.1 kiyohara 374 1.1 kiyohara /* Increment reference for thread */ 375 1.1 kiyohara sc->sc_refcnt++; 376 1.1 kiyohara 377 1.1 kiyohara error = kthread_create(PRI_NONE, 0, NULL, udsir_thread, sc, 378 1.1 kiyohara &sc->sc_thread, "%s", device_xname(sc->sc_dev)); 379 1.1 kiyohara if (error) { 380 1.1 kiyohara sc->sc_refcnt--; 381 1.1 kiyohara goto bad5; 382 1.1 kiyohara } 383 1.1 kiyohara 384 1.1 kiyohara return 0; 385 1.1 kiyohara 386 1.1 kiyohara bad5: 387 1.2 skrll usbd_destroy_xfer(sc->sc_wr_xfer); 388 1.1 kiyohara sc->sc_wr_xfer = NULL; 389 1.1 kiyohara bad4: 390 1.2 skrll usbd_destroy_xfer(sc->sc_rd_xfer); 391 1.1 kiyohara sc->sc_rd_xfer = NULL; 392 1.1 kiyohara bad3: 393 1.1 kiyohara usbd_close_pipe(sc->sc_wr_pipe); 394 1.1 kiyohara sc->sc_wr_pipe = NULL; 395 1.1 kiyohara bad2: 396 1.1 kiyohara usbd_close_pipe(sc->sc_rd_pipe); 397 1.1 kiyohara sc->sc_rd_pipe = NULL; 398 1.1 kiyohara bad1: 399 1.1 kiyohara return error; 400 1.1 kiyohara } 401 1.1 kiyohara 402 1.1 kiyohara /* ARGSUSED */ 403 1.1 kiyohara static int 404 1.1 kiyohara udsir_close(void *h, int flag, int mode, struct lwp *l) 405 1.1 kiyohara { 406 1.1 kiyohara struct udsir_softc *sc = h; 407 1.1 kiyohara 408 1.1 kiyohara DPRINTFN(0, ("%s: sc=%p\n", __func__, sc)); 409 1.1 kiyohara 410 1.1 kiyohara sc->sc_refcnt++; 411 1.1 kiyohara 412 1.1 kiyohara sc->sc_rd_readinprogress = 1; 413 1.1 kiyohara sc->sc_closing = 1; 414 1.1 kiyohara 415 1.1 kiyohara wakeup(&sc->sc_thread); 416 1.1 kiyohara 417 1.1 kiyohara while (sc->sc_thread != NULL) 418 1.1 kiyohara tsleep(&sc->sc_closing, PWAIT, "usircl", 0); 419 1.1 kiyohara 420 1.1 kiyohara if (sc->sc_rd_pipe != NULL) { 421 1.1 kiyohara usbd_abort_pipe(sc->sc_rd_pipe); 422 1.1 kiyohara } 423 1.1 kiyohara if (sc->sc_wr_pipe != NULL) { 424 1.1 kiyohara usbd_abort_pipe(sc->sc_wr_pipe); 425 1.1 kiyohara } 426 1.1 kiyohara if (sc->sc_rd_xfer != NULL) { 427 1.2 skrll usbd_destroy_xfer(sc->sc_rd_xfer); 428 1.1 kiyohara sc->sc_rd_xfer = NULL; 429 1.1 kiyohara sc->sc_rd_buf = NULL; 430 1.1 kiyohara } 431 1.1 kiyohara if (sc->sc_wr_xfer != NULL) { 432 1.2 skrll usbd_destroy_xfer(sc->sc_wr_xfer); 433 1.1 kiyohara sc->sc_wr_xfer = NULL; 434 1.1 kiyohara sc->sc_wr_buf = NULL; 435 1.1 kiyohara } 436 1.2 skrll if (sc->sc_rd_pipe != NULL) { 437 1.2 skrll usbd_close_pipe(sc->sc_rd_pipe); 438 1.2 skrll sc->sc_rd_pipe = NULL; 439 1.2 skrll } 440 1.2 skrll if (sc->sc_wr_pipe != NULL) { 441 1.2 skrll usbd_close_pipe(sc->sc_wr_pipe); 442 1.2 skrll sc->sc_wr_pipe = NULL; 443 1.2 skrll } 444 1.1 kiyohara if (sc->sc_ur_buf != NULL) { 445 1.2 skrll kmem_free(sc->sc_ur_buf, IRDA_MAX_FRAME_SIZE); 446 1.1 kiyohara sc->sc_ur_buf = NULL; 447 1.1 kiyohara } 448 1.1 kiyohara 449 1.1 kiyohara if (--sc->sc_refcnt < 0) 450 1.1 kiyohara usb_detach_wakeupold(sc->sc_dev); 451 1.1 kiyohara 452 1.1 kiyohara return 0; 453 1.1 kiyohara } 454 1.1 kiyohara 455 1.1 kiyohara /* ARGSUSED */ 456 1.1 kiyohara static int 457 1.1 kiyohara udsir_read(void *h, struct uio *uio, int flag) 458 1.1 kiyohara { 459 1.1 kiyohara struct udsir_softc *sc = h; 460 1.1 kiyohara int s; 461 1.1 kiyohara int error; 462 1.1 kiyohara u_int uframelen; 463 1.1 kiyohara 464 1.1 kiyohara DPRINTFN(1, ("%s: sc=%p\n", __func__, sc)); 465 1.1 kiyohara 466 1.1 kiyohara if (sc->sc_dying) 467 1.1 kiyohara return EIO; 468 1.1 kiyohara 469 1.1 kiyohara #ifdef DIAGNOSTIC 470 1.1 kiyohara if (sc->sc_rd_buf == NULL) 471 1.1 kiyohara return EINVAL; 472 1.1 kiyohara #endif 473 1.1 kiyohara 474 1.1 kiyohara sc->sc_refcnt++; 475 1.1 kiyohara 476 1.1 kiyohara if (!sc->sc_rd_readinprogress && !UDSIR_BLOCK_RX_DATA(sc)) 477 1.1 kiyohara /* Possibly wake up polling thread */ 478 1.1 kiyohara wakeup(&sc->sc_thread); 479 1.1 kiyohara 480 1.1 kiyohara do { 481 1.1 kiyohara s = splusb(); 482 1.1 kiyohara while (sc->sc_ur_framelen == 0) { 483 1.1 kiyohara DPRINTFN(5, ("%s: calling tsleep()\n", __func__)); 484 1.1 kiyohara error = tsleep(&sc->sc_ur_framelen, PZERO | PCATCH, 485 1.1 kiyohara "usirrd", 0); 486 1.1 kiyohara if (sc->sc_dying) 487 1.1 kiyohara error = EIO; 488 1.1 kiyohara if (error) { 489 1.1 kiyohara splx(s); 490 1.1 kiyohara DPRINTFN(0, ("%s: tsleep() = %d\n", 491 1.1 kiyohara __func__, error)); 492 1.1 kiyohara goto ret; 493 1.1 kiyohara } 494 1.1 kiyohara } 495 1.1 kiyohara splx(s); 496 1.1 kiyohara 497 1.1 kiyohara uframelen = sc->sc_ur_framelen; 498 1.11 christos DPRINTFN(1, ("%s: sc=%p framelen=%u, hdr=0x%02x\n", 499 1.1 kiyohara __func__, sc, uframelen, sc->sc_ur_buf[0])); 500 1.1 kiyohara if (uframelen > uio->uio_resid) 501 1.1 kiyohara error = EINVAL; 502 1.1 kiyohara else 503 1.1 kiyohara error = uiomove(sc->sc_ur_buf, uframelen, uio); 504 1.1 kiyohara sc->sc_ur_framelen = 0; 505 1.1 kiyohara 506 1.1 kiyohara if (deframe_rd_ur(sc) == 0 && uframelen > 0) { 507 1.1 kiyohara /* 508 1.1 kiyohara * Need to wait for another read to obtain a 509 1.1 kiyohara * complete frame... If we also obtained 510 1.1 kiyohara * actual data, wake up the possibly sleeping 511 1.1 kiyohara * thread immediately... 512 1.1 kiyohara */ 513 1.1 kiyohara wakeup(&sc->sc_thread); 514 1.1 kiyohara } 515 1.1 kiyohara } while (uframelen == 0); 516 1.1 kiyohara 517 1.1 kiyohara DPRINTFN(1, ("%s: return %d\n", __func__, error)); 518 1.1 kiyohara 519 1.1 kiyohara ret: 520 1.1 kiyohara if (--sc->sc_refcnt < 0) 521 1.1 kiyohara usb_detach_wakeupold(sc->sc_dev); 522 1.1 kiyohara return error; 523 1.1 kiyohara } 524 1.1 kiyohara 525 1.1 kiyohara /* ARGSUSED */ 526 1.1 kiyohara static int 527 1.1 kiyohara udsir_write(void *h, struct uio *uio, int flag) 528 1.1 kiyohara { 529 1.1 kiyohara struct udsir_softc *sc = h; 530 1.1 kiyohara usbd_status err; 531 1.1 kiyohara uint32_t wrlen; 532 1.1 kiyohara int error, sirlength; 533 1.1 kiyohara uint8_t *wrbuf; 534 1.1 kiyohara int s; 535 1.1 kiyohara 536 1.1 kiyohara DPRINTFN(1, ("%s: sc=%p\n", __func__, sc)); 537 1.1 kiyohara 538 1.1 kiyohara if (sc->sc_dying) 539 1.1 kiyohara return EIO; 540 1.1 kiyohara 541 1.1 kiyohara #ifdef DIAGNOSTIC 542 1.1 kiyohara if (sc->sc_wr_buf == NULL) 543 1.1 kiyohara return EINVAL; 544 1.1 kiyohara #endif 545 1.1 kiyohara 546 1.1 kiyohara wrlen = uio->uio_resid; 547 1.1 kiyohara if (wrlen > sc->sc_wr_maxpsz) 548 1.1 kiyohara return EINVAL; 549 1.1 kiyohara 550 1.1 kiyohara sc->sc_refcnt++; 551 1.1 kiyohara 552 1.1 kiyohara if (!UDSIR_BLOCK_RX_DATA(sc)) { 553 1.1 kiyohara /* 554 1.1 kiyohara * If reads are not blocked, determine what action we 555 1.1 kiyohara * should potentially take... 556 1.1 kiyohara */ 557 1.1 kiyohara if (sc->sc_direction == udir_output) { 558 1.1 kiyohara /* 559 1.1 kiyohara * If the last operation was an output, wait for the 560 1.1 kiyohara * polling thread to check for incoming data. 561 1.1 kiyohara */ 562 1.1 kiyohara sc->sc_wr_stalewrite = 1; 563 1.1 kiyohara wakeup(&sc->sc_thread); 564 1.1 kiyohara } else if (!sc->sc_rd_readinprogress && 565 1.1 kiyohara (sc->sc_direction == udir_idle || 566 1.1 kiyohara sc->sc_direction == udir_input)) { 567 1.1 kiyohara /* If idle, check for input before outputting */ 568 1.1 kiyohara udsir_start_read(sc); 569 1.1 kiyohara } 570 1.1 kiyohara } 571 1.1 kiyohara 572 1.1 kiyohara s = splusb(); 573 1.1 kiyohara while (sc->sc_wr_stalewrite || 574 1.1 kiyohara (sc->sc_direction != udir_output && 575 1.1 kiyohara sc->sc_direction != udir_idle)) { 576 1.1 kiyohara DPRINTFN(5, ("%s: sc=%p stalewrite=%d direction=%d, " 577 1.1 kiyohara "calling tsleep()\n", 578 1.1 kiyohara __func__, sc, sc->sc_wr_stalewrite, 579 1.1 kiyohara sc->sc_direction)); 580 1.1 kiyohara error = tsleep(&sc->sc_wr_buf, PZERO | PCATCH, "usirwr", 0); 581 1.1 kiyohara if (sc->sc_dying) 582 1.1 kiyohara error = EIO; 583 1.1 kiyohara if (error) { 584 1.1 kiyohara splx(s); 585 1.1 kiyohara DPRINTFN(0, ("%s: tsleep() = %d\n", __func__, error)); 586 1.1 kiyohara goto ret; 587 1.1 kiyohara } 588 1.1 kiyohara } 589 1.1 kiyohara splx(s); 590 1.1 kiyohara 591 1.1 kiyohara wrbuf = sc->sc_wr_buf; 592 1.1 kiyohara 593 1.1 kiyohara sirlength = irda_sir_frame(wrbuf, MAX_UDSIR_OUTPUT_FRAME, 594 1.1 kiyohara uio, sc->sc_params.ebofs); 595 1.1 kiyohara if (sirlength < 0) 596 1.1 kiyohara error = -sirlength; 597 1.1 kiyohara else { 598 1.1 kiyohara uint32_t btlen; 599 1.1 kiyohara 600 1.1 kiyohara DPRINTFN(1, ("%s: transfer %u bytes\n", 601 1.1 kiyohara __func__, (unsigned int)wrlen)); 602 1.1 kiyohara 603 1.1 kiyohara btlen = sirlength; 604 1.1 kiyohara 605 1.1 kiyohara sc->sc_direction = udir_output; 606 1.1 kiyohara 607 1.1 kiyohara #ifdef UDSIR_DEBUG 608 1.1 kiyohara if (udsirdebug >= 20) 609 1.1 kiyohara udsir_dumpdata(wrbuf, btlen, __func__); 610 1.1 kiyohara #endif 611 1.1 kiyohara 612 1.1 kiyohara err = usbd_intr_transfer(sc->sc_wr_xfer, sc->sc_wr_pipe, 613 1.2 skrll USBD_FORCE_SHORT_XFER, UDSIR_WR_TIMEOUT, 614 1.2 skrll wrbuf, &btlen); 615 1.1 kiyohara DPRINTFN(2, ("%s: err=%d\n", __func__, err)); 616 1.1 kiyohara if (err != USBD_NORMAL_COMPLETION) { 617 1.1 kiyohara if (err == USBD_INTERRUPTED) 618 1.1 kiyohara error = EINTR; 619 1.1 kiyohara else if (err == USBD_TIMEOUT) 620 1.1 kiyohara error = ETIMEDOUT; 621 1.1 kiyohara else 622 1.1 kiyohara error = EIO; 623 1.1 kiyohara } else 624 1.1 kiyohara error = 0; 625 1.1 kiyohara } 626 1.1 kiyohara 627 1.1 kiyohara ret: 628 1.1 kiyohara if (--sc->sc_refcnt < 0) 629 1.1 kiyohara usb_detach_wakeupold(sc->sc_dev); 630 1.1 kiyohara 631 1.1 kiyohara DPRINTFN(1, ("%s: sc=%p done\n", __func__, sc)); 632 1.1 kiyohara return error; 633 1.1 kiyohara } 634 1.1 kiyohara 635 1.1 kiyohara static int 636 1.1 kiyohara udsir_poll(void *h, int events, struct lwp *l) 637 1.1 kiyohara { 638 1.1 kiyohara struct udsir_softc *sc = h; 639 1.1 kiyohara int revents = 0; 640 1.1 kiyohara 641 1.1 kiyohara DPRINTFN(1, ("%s: sc=%p\n", __func__, sc)); 642 1.1 kiyohara 643 1.1 kiyohara if (events & (POLLOUT | POLLWRNORM)) { 644 1.1 kiyohara if (sc->sc_direction != udir_input) 645 1.1 kiyohara revents |= events & (POLLOUT | POLLWRNORM); 646 1.1 kiyohara else { 647 1.1 kiyohara DPRINTFN(2, ("%s: recording write select\n", __func__)); 648 1.1 kiyohara selrecord(l, &sc->sc_wr_sel); 649 1.1 kiyohara } 650 1.1 kiyohara } 651 1.1 kiyohara 652 1.1 kiyohara if (events & (POLLIN | POLLRDNORM)) { 653 1.1 kiyohara if (sc->sc_ur_framelen != 0) { 654 1.1 kiyohara DPRINTFN(2, ("%s: have data\n", __func__)); 655 1.1 kiyohara revents |= events & (POLLIN | POLLRDNORM); 656 1.1 kiyohara } else { 657 1.1 kiyohara DPRINTFN(2, ("%s: recording read select\n", __func__)); 658 1.1 kiyohara selrecord(l, &sc->sc_rd_sel); 659 1.1 kiyohara } 660 1.1 kiyohara } 661 1.1 kiyohara 662 1.1 kiyohara return revents; 663 1.1 kiyohara } 664 1.1 kiyohara 665 1.5 maya static const struct filterops udsirread_filtops = { 666 1.15 thorpej .f_flags = FILTEROP_ISFD, 667 1.5 maya .f_attach = NULL, 668 1.5 maya .f_detach = filt_udsirrdetach, 669 1.5 maya .f_event = filt_udsirread, 670 1.5 maya }; 671 1.5 maya 672 1.5 maya static const struct filterops udsirwrite_filtops = { 673 1.15 thorpej .f_flags = FILTEROP_ISFD, 674 1.5 maya .f_attach = NULL, 675 1.5 maya .f_detach = filt_udsirwdetach, 676 1.5 maya .f_event = filt_udsirwrite, 677 1.5 maya }; 678 1.1 kiyohara 679 1.1 kiyohara static int 680 1.1 kiyohara udsir_kqfilter(void *h, struct knote *kn) 681 1.1 kiyohara { 682 1.1 kiyohara struct udsir_softc *sc = h; 683 1.12 thorpej struct selinfo *sip; 684 1.1 kiyohara int s; 685 1.1 kiyohara 686 1.1 kiyohara switch (kn->kn_filter) { 687 1.1 kiyohara case EVFILT_READ: 688 1.12 thorpej sip = &sc->sc_rd_sel; 689 1.1 kiyohara kn->kn_fop = &udsirread_filtops; 690 1.1 kiyohara break; 691 1.1 kiyohara case EVFILT_WRITE: 692 1.12 thorpej sip = &sc->sc_wr_sel; 693 1.1 kiyohara kn->kn_fop = &udsirwrite_filtops; 694 1.1 kiyohara break; 695 1.1 kiyohara default: 696 1.8 skrll return EINVAL; 697 1.1 kiyohara } 698 1.1 kiyohara 699 1.1 kiyohara kn->kn_hook = sc; 700 1.1 kiyohara 701 1.1 kiyohara s = splusb(); 702 1.12 thorpej selrecord_knote(sip, kn); 703 1.1 kiyohara splx(s); 704 1.1 kiyohara 705 1.8 skrll return 0; 706 1.1 kiyohara } 707 1.1 kiyohara 708 1.1 kiyohara static int 709 1.1 kiyohara udsir_set_params(void *h, struct irda_params *p) 710 1.1 kiyohara { 711 1.1 kiyohara struct udsir_softc *sc = h; 712 1.1 kiyohara 713 1.1 kiyohara DPRINTFN(0, ("%s: sc=%p, speed=%d ebofs=%d maxsize=%d\n", 714 1.1 kiyohara __func__, sc, p->speed, p->ebofs, p->maxsize)); 715 1.1 kiyohara 716 1.1 kiyohara if (sc->sc_dying) 717 1.1 kiyohara return EIO; 718 1.1 kiyohara 719 1.1 kiyohara if (p->speed != 9600) 720 1.1 kiyohara return EINVAL; 721 1.1 kiyohara 722 1.1 kiyohara if (p->maxsize != sc->sc_params.maxsize) { 723 1.7 riastrad if (p->maxsize > uimin(sc->sc_rd_maxpsz, sc->sc_wr_maxpsz)) 724 1.1 kiyohara return EINVAL; 725 1.1 kiyohara sc->sc_params.maxsize = p->maxsize; 726 1.1 kiyohara } 727 1.1 kiyohara 728 1.1 kiyohara sc->sc_params = *p; 729 1.1 kiyohara 730 1.1 kiyohara return 0; 731 1.1 kiyohara } 732 1.1 kiyohara 733 1.1 kiyohara static int 734 1.1 kiyohara udsir_get_speeds(void *h, int *speeds) 735 1.1 kiyohara { 736 1.1 kiyohara struct udsir_softc *sc = h; 737 1.1 kiyohara 738 1.1 kiyohara DPRINTFN(0, ("%s: sc=%p\n", __func__, sc)); 739 1.1 kiyohara 740 1.1 kiyohara if (sc->sc_dying) 741 1.1 kiyohara return EIO; 742 1.1 kiyohara 743 1.1 kiyohara /* Support only 9600bps now. */ 744 1.1 kiyohara *speeds = IRDA_SPEED_9600; 745 1.1 kiyohara 746 1.1 kiyohara return 0; 747 1.1 kiyohara } 748 1.1 kiyohara 749 1.1 kiyohara static int 750 1.1 kiyohara udsir_get_turnarounds(void *h, int *turnarounds) 751 1.1 kiyohara { 752 1.1 kiyohara struct udsir_softc *sc = h; 753 1.1 kiyohara 754 1.1 kiyohara DPRINTFN(0, ("%s: sc=%p\n", __func__, sc)); 755 1.1 kiyohara 756 1.1 kiyohara if (sc->sc_dying) 757 1.1 kiyohara return EIO; 758 1.1 kiyohara 759 1.1 kiyohara /* 760 1.1 kiyohara * Documentation is on the light side with respect to 761 1.1 kiyohara * turnaround time for this device. 762 1.1 kiyohara */ 763 1.1 kiyohara *turnarounds = IRDA_TURNT_10000; 764 1.1 kiyohara 765 1.1 kiyohara return 0; 766 1.1 kiyohara } 767 1.1 kiyohara 768 1.1 kiyohara static void 769 1.1 kiyohara filt_udsirrdetach(struct knote *kn) 770 1.1 kiyohara { 771 1.1 kiyohara struct udsir_softc *sc = kn->kn_hook; 772 1.1 kiyohara int s; 773 1.1 kiyohara 774 1.1 kiyohara s = splusb(); 775 1.12 thorpej selremove_knote(&sc->sc_rd_sel, kn); 776 1.1 kiyohara splx(s); 777 1.1 kiyohara } 778 1.1 kiyohara 779 1.1 kiyohara /* ARGSUSED */ 780 1.1 kiyohara static int 781 1.1 kiyohara filt_udsirread(struct knote *kn, long hint) 782 1.1 kiyohara { 783 1.1 kiyohara struct udsir_softc *sc = kn->kn_hook; 784 1.1 kiyohara 785 1.1 kiyohara kn->kn_data = sc->sc_ur_framelen; 786 1.8 skrll return kn->kn_data > 0; 787 1.1 kiyohara } 788 1.1 kiyohara 789 1.1 kiyohara static void 790 1.1 kiyohara filt_udsirwdetach(struct knote *kn) 791 1.1 kiyohara { 792 1.1 kiyohara struct udsir_softc *sc = kn->kn_hook; 793 1.1 kiyohara int s; 794 1.1 kiyohara 795 1.1 kiyohara s = splusb(); 796 1.12 thorpej selremove_knote(&sc->sc_wr_sel, kn); 797 1.1 kiyohara splx(s); 798 1.1 kiyohara } 799 1.1 kiyohara 800 1.1 kiyohara /* ARGSUSED */ 801 1.1 kiyohara static int 802 1.1 kiyohara filt_udsirwrite(struct knote *kn, long hint) 803 1.1 kiyohara { 804 1.1 kiyohara struct udsir_softc *sc = kn->kn_hook; 805 1.1 kiyohara 806 1.1 kiyohara kn->kn_data = 0; 807 1.8 skrll return sc->sc_direction != udir_input; 808 1.1 kiyohara } 809 1.1 kiyohara 810 1.1 kiyohara 811 1.1 kiyohara static void 812 1.1 kiyohara udsir_thread(void *arg) 813 1.1 kiyohara { 814 1.1 kiyohara struct udsir_softc *sc = arg; 815 1.1 kiyohara int error; 816 1.1 kiyohara 817 1.1 kiyohara DPRINTFN(20, ("%s: starting polling thread\n", __func__)); 818 1.1 kiyohara 819 1.1 kiyohara while (!sc->sc_closing) { 820 1.1 kiyohara if (!sc->sc_rd_readinprogress && !UDSIR_BLOCK_RX_DATA(sc)) 821 1.1 kiyohara udsir_periodic(sc); 822 1.1 kiyohara 823 1.1 kiyohara if (!sc->sc_closing) { 824 1.1 kiyohara error = tsleep(&sc->sc_thread, PWAIT, "udsir", hz / 10); 825 1.1 kiyohara if (error == EWOULDBLOCK && 826 1.1 kiyohara sc->sc_rd_expectdataticks > 0) 827 1.1 kiyohara /* 828 1.1 kiyohara * After a timeout decrement the tick 829 1.1 kiyohara * counter within which time we expect 830 1.1 kiyohara * data to arrive if we are receiving 831 1.1 kiyohara * data... 832 1.1 kiyohara */ 833 1.1 kiyohara sc->sc_rd_expectdataticks--; 834 1.1 kiyohara } 835 1.1 kiyohara } 836 1.1 kiyohara 837 1.1 kiyohara DPRINTFN(20, ("%s: exiting polling thread\n", __func__)); 838 1.1 kiyohara 839 1.1 kiyohara sc->sc_thread = NULL; 840 1.1 kiyohara 841 1.1 kiyohara wakeup(&sc->sc_closing); 842 1.1 kiyohara 843 1.1 kiyohara if (--sc->sc_refcnt < 0) 844 1.1 kiyohara usb_detach_wakeupold(sc->sc_dev); 845 1.1 kiyohara 846 1.1 kiyohara kthread_exit(0); 847 1.1 kiyohara } 848 1.1 kiyohara 849 1.1 kiyohara #ifdef UDSIR_DEBUG 850 1.1 kiyohara static void 851 1.1 kiyohara udsir_dumpdata(uint8_t const *data, size_t dlen, char const *desc) 852 1.1 kiyohara { 853 1.1 kiyohara size_t bdindex; 854 1.1 kiyohara 855 1.1 kiyohara printf("%s: (%lx)", desc, (unsigned long)dlen); 856 1.1 kiyohara for (bdindex = 0; bdindex < dlen; bdindex++) 857 1.1 kiyohara printf(" %02x", (unsigned int)data[bdindex]); 858 1.1 kiyohara printf("\n"); 859 1.1 kiyohara } 860 1.1 kiyohara #endif 861 1.1 kiyohara 862 1.1 kiyohara /* Returns 0 if more data required, 1 if a complete frame was extracted */ 863 1.1 kiyohara static int 864 1.1 kiyohara deframe_rd_ur(struct udsir_softc *sc) 865 1.1 kiyohara { 866 1.1 kiyohara 867 1.1 kiyohara if (sc->sc_rd_index == 0) { 868 1.1 kiyohara KASSERT(sc->sc_rd_count == sc->sc_rd_maxpsz); 869 1.1 kiyohara /* valid count */ 870 1.1 kiyohara sc->sc_rd_count = sc->sc_rd_buf[sc->sc_rd_index++] + 1; 871 1.1 kiyohara KASSERT(sc->sc_rd_count < sc->sc_rd_maxpsz); 872 1.1 kiyohara } 873 1.1 kiyohara 874 1.1 kiyohara while (sc->sc_rd_index < sc->sc_rd_count) { 875 1.1 kiyohara uint8_t const *buf; 876 1.1 kiyohara size_t buflen; 877 1.1 kiyohara enum frameresult fresult; 878 1.1 kiyohara 879 1.1 kiyohara buf = &sc->sc_rd_buf[sc->sc_rd_index]; 880 1.1 kiyohara buflen = sc->sc_rd_count - sc->sc_rd_index; 881 1.1 kiyohara 882 1.1 kiyohara fresult = deframe_process(&sc->sc_framestate, &buf, &buflen); 883 1.1 kiyohara 884 1.1 kiyohara sc->sc_rd_index = sc->sc_rd_count - buflen; 885 1.1 kiyohara 886 1.1 kiyohara DPRINTFN(1,("%s: result=%d\n", __func__, (int)fresult)); 887 1.1 kiyohara 888 1.1 kiyohara switch (fresult) { 889 1.1 kiyohara case FR_IDLE: 890 1.1 kiyohara case FR_INPROGRESS: 891 1.1 kiyohara case FR_FRAMEBADFCS: 892 1.1 kiyohara case FR_FRAMEMALFORMED: 893 1.1 kiyohara case FR_BUFFEROVERRUN: 894 1.1 kiyohara break; 895 1.1 kiyohara case FR_FRAMEOK: 896 1.1 kiyohara sc->sc_ur_framelen = sc->sc_framestate.bufindex; 897 1.1 kiyohara wakeup(&sc->sc_ur_framelen); /* XXX should use flag */ 898 1.1 kiyohara selnotify(&sc->sc_rd_sel, 0, 0); 899 1.1 kiyohara return 1; 900 1.1 kiyohara } 901 1.1 kiyohara } 902 1.1 kiyohara 903 1.1 kiyohara /* Reset indices into USB-side buffer */ 904 1.1 kiyohara sc->sc_rd_index = sc->sc_rd_count = 0; 905 1.1 kiyohara 906 1.1 kiyohara return 0; 907 1.1 kiyohara } 908 1.1 kiyohara 909 1.1 kiyohara /* 910 1.1 kiyohara * Direction transitions: 911 1.1 kiyohara * 912 1.1 kiyohara * udsir_periodic() can switch the direction from: 913 1.1 kiyohara * 914 1.1 kiyohara * output -> idle 915 1.1 kiyohara * output -> stalled 916 1.1 kiyohara * stalled -> idle 917 1.1 kiyohara * idle -> input 918 1.1 kiyohara * 919 1.1 kiyohara * udsir_rd_cb() can switch the direction from: 920 1.1 kiyohara * 921 1.1 kiyohara * input -> stalled 922 1.1 kiyohara * input -> idle 923 1.1 kiyohara * 924 1.1 kiyohara * udsir_write() can switch the direction from: 925 1.1 kiyohara * 926 1.1 kiyohara * idle -> output 927 1.1 kiyohara */ 928 1.1 kiyohara static void 929 1.1 kiyohara udsir_periodic(struct udsir_softc *sc) 930 1.1 kiyohara { 931 1.1 kiyohara 932 1.1 kiyohara DPRINTFN(60, ("%s: direction = %d\n", __func__, sc->sc_direction)); 933 1.1 kiyohara 934 1.1 kiyohara if (sc->sc_wr_stalewrite && sc->sc_direction == udir_idle) { 935 1.1 kiyohara /* 936 1.1 kiyohara * In a stale write case, we need to check if the 937 1.1 kiyohara * write has completed. Once that has happened, the 938 1.1 kiyohara * write is no longer stale. 939 1.1 kiyohara * 940 1.1 kiyohara * But note that we may immediately start a read poll... 941 1.1 kiyohara */ 942 1.1 kiyohara sc->sc_wr_stalewrite = 0; 943 1.1 kiyohara wakeup(&sc->sc_wr_buf); 944 1.1 kiyohara } 945 1.1 kiyohara 946 1.1 kiyohara if (!sc->sc_rd_readinprogress && 947 1.1 kiyohara (sc->sc_direction == udir_idle || 948 1.1 kiyohara sc->sc_direction == udir_input)) 949 1.1 kiyohara /* Do a read poll if appropriate... */ 950 1.1 kiyohara udsir_start_read(sc); 951 1.1 kiyohara } 952 1.1 kiyohara 953 1.1 kiyohara static void 954 1.2 skrll udsir_rd_cb(struct usbd_xfer *xfer, void * priv, usbd_status status) 955 1.1 kiyohara { 956 1.1 kiyohara struct udsir_softc *sc = priv; 957 1.1 kiyohara uint32_t size; 958 1.1 kiyohara 959 1.1 kiyohara DPRINTFN(60, ("%s: sc=%p\n", __func__, sc)); 960 1.1 kiyohara 961 1.1 kiyohara /* Read is no longer in progress */ 962 1.1 kiyohara sc->sc_rd_readinprogress = 0; 963 1.1 kiyohara 964 1.1 kiyohara if (status == USBD_CANCELLED || sc->sc_closing) /* this is normal */ 965 1.1 kiyohara return; 966 1.1 kiyohara if (status) { 967 1.1 kiyohara size = 0; 968 1.1 kiyohara sc->sc_rd_err = 1; 969 1.1 kiyohara 970 1.1 kiyohara if (sc->sc_direction == udir_input || 971 1.1 kiyohara sc->sc_direction == udir_idle) { 972 1.1 kiyohara /* 973 1.1 kiyohara * Receive error, probably need to clear error 974 1.1 kiyohara * condition. 975 1.1 kiyohara */ 976 1.1 kiyohara sc->sc_direction = udir_stalled; 977 1.1 kiyohara } 978 1.1 kiyohara } else 979 1.1 kiyohara usbd_get_xfer_status(xfer, NULL, NULL, &size, NULL); 980 1.1 kiyohara 981 1.1 kiyohara sc->sc_rd_index = 0; 982 1.1 kiyohara sc->sc_rd_count = size; 983 1.1 kiyohara 984 1.1 kiyohara DPRINTFN(((size > 0 || sc->sc_rd_err != 0) ? 20 : 60), 985 1.1 kiyohara ("%s: sc=%p size=%u, err=%d\n", 986 1.1 kiyohara __func__, sc, size, sc->sc_rd_err)); 987 1.1 kiyohara 988 1.1 kiyohara #ifdef UDSIR_DEBUG 989 1.1 kiyohara if (udsirdebug >= 20 && size > 0) 990 1.1 kiyohara udsir_dumpdata(sc->sc_rd_buf, size, __func__); 991 1.1 kiyohara #endif 992 1.1 kiyohara 993 1.1 kiyohara if (deframe_rd_ur(sc) == 0) { 994 1.1 kiyohara if (!deframe_isclear(&sc->sc_framestate) && size == 0 && 995 1.1 kiyohara sc->sc_rd_expectdataticks == 0) { 996 1.1 kiyohara /* 997 1.1 kiyohara * Expected data, but didn't get it 998 1.1 kiyohara * within expected time... 999 1.1 kiyohara */ 1000 1.1 kiyohara DPRINTFN(5,("%s: incoming packet timeout\n", 1001 1.1 kiyohara __func__)); 1002 1.1 kiyohara deframe_clear(&sc->sc_framestate); 1003 1.1 kiyohara } else if (size > 0) { 1004 1.1 kiyohara /* 1005 1.1 kiyohara * If we also received actual data, reset the 1006 1.1 kiyohara * data read timeout and wake up the possibly 1007 1.1 kiyohara * sleeping thread... 1008 1.1 kiyohara */ 1009 1.1 kiyohara sc->sc_rd_expectdataticks = 2; 1010 1.1 kiyohara wakeup(&sc->sc_thread); 1011 1.1 kiyohara } 1012 1.1 kiyohara } 1013 1.1 kiyohara 1014 1.1 kiyohara /* 1015 1.1 kiyohara * Check if incoming data has stopped, or that we cannot 1016 1.1 kiyohara * safely read any more data. In the case of the latter we 1017 1.1 kiyohara * must switch to idle so that a write will not block... 1018 1.1 kiyohara */ 1019 1.1 kiyohara if (sc->sc_direction == udir_input && 1020 1.1 kiyohara ((size == 0 && sc->sc_rd_expectdataticks == 0) || 1021 1.1 kiyohara UDSIR_BLOCK_RX_DATA(sc))) { 1022 1.1 kiyohara DPRINTFN(8, ("%s: idling on packet timeout, " 1023 1.1 kiyohara "complete frame, or no data\n", __func__)); 1024 1.1 kiyohara sc->sc_direction = udir_idle; 1025 1.1 kiyohara 1026 1.1 kiyohara /* Wake up for possible output */ 1027 1.1 kiyohara wakeup(&sc->sc_wr_buf); 1028 1.1 kiyohara selnotify(&sc->sc_wr_sel, 0, 0); 1029 1.1 kiyohara } 1030 1.1 kiyohara } 1031 1.1 kiyohara 1032 1.1 kiyohara static usbd_status 1033 1.1 kiyohara udsir_start_read(struct udsir_softc *sc) 1034 1.1 kiyohara { 1035 1.1 kiyohara usbd_status err; 1036 1.1 kiyohara 1037 1.1 kiyohara DPRINTFN(60, ("%s: sc=%p, size=%d\n", __func__, sc, sc->sc_rd_maxpsz)); 1038 1.1 kiyohara 1039 1.1 kiyohara if (sc->sc_dying) 1040 1.1 kiyohara return USBD_IOERROR; 1041 1.1 kiyohara 1042 1.1 kiyohara if (UDSIR_BLOCK_RX_DATA(sc) || deframe_rd_ur(sc)) { 1043 1.1 kiyohara /* 1044 1.1 kiyohara * Can't start reading just yet. Since we aren't 1045 1.1 kiyohara * going to start a read, have to switch direction to 1046 1.1 kiyohara * idle. 1047 1.1 kiyohara */ 1048 1.1 kiyohara sc->sc_direction = udir_idle; 1049 1.1 kiyohara return USBD_NORMAL_COMPLETION; 1050 1.1 kiyohara } 1051 1.1 kiyohara 1052 1.1 kiyohara /* Starting a read... */ 1053 1.1 kiyohara sc->sc_rd_readinprogress = 1; 1054 1.1 kiyohara sc->sc_direction = udir_input; 1055 1.1 kiyohara 1056 1.1 kiyohara if (sc->sc_rd_err) { 1057 1.1 kiyohara sc->sc_rd_err = 0; 1058 1.1 kiyohara DPRINTFN(0, ("%s: clear stall\n", __func__)); 1059 1.1 kiyohara usbd_clear_endpoint_stall(sc->sc_rd_pipe); 1060 1.1 kiyohara } 1061 1.1 kiyohara 1062 1.2 skrll usbd_setup_xfer(sc->sc_rd_xfer, sc, sc->sc_rd_buf, sc->sc_rd_maxpsz, 1063 1.2 skrll USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, udsir_rd_cb); 1064 1.1 kiyohara err = usbd_transfer(sc->sc_rd_xfer); 1065 1.1 kiyohara if (err != USBD_IN_PROGRESS) { 1066 1.1 kiyohara DPRINTFN(0, ("%s: err=%d\n", __func__, (int)err)); 1067 1.1 kiyohara return err; 1068 1.1 kiyohara } 1069 1.1 kiyohara return USBD_NORMAL_COMPLETION; 1070 1.1 kiyohara } 1071