Annotation of src/sys/dev/usb/ustir.c, Revision 1.33.14.1
1.33.14.1! skrll 1: /* $NetBSD: ustir.c,v 1.33 2013/05/27 16:23:20 kiyohara Exp $ */
1.1 augustss 2:
3: /*
4: * Copyright (c) 2001 The NetBSD Foundation, Inc.
5: * All rights reserved.
6: *
7: * This code is derived from software contributed to The NetBSD Foundation
8: * by David Sainty <David.Sainty@dtsp.co.nz>
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
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.
18: *
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.
30: */
31:
32: #include <sys/cdefs.h>
1.33.14.1! skrll 33: __KERNEL_RCSID(0, "$NetBSD: ustir.c,v 1.33 2013/05/27 16:23:20 kiyohara Exp $");
1.1 augustss 34:
35: #include <sys/param.h>
36: #include <sys/systm.h>
37: #include <sys/kernel.h>
38: #include <sys/device.h>
1.33.14.1! skrll 39: #include <sys/kmem.h>
1.1 augustss 40: #include <sys/conf.h>
41: #include <sys/file.h>
42: #include <sys/poll.h>
43: #include <sys/select.h>
44: #include <sys/proc.h>
45: #include <sys/kthread.h>
46:
47: #ifdef USTIR_DEBUG_IOCTLS
48: #include <sys/ioctl.h>
49: #include <dev/usb/ustir.h>
50: #endif
51:
52: #include <dev/usb/usb.h>
53: #include <dev/usb/usbdevs.h>
54: #include <dev/usb/usbdi.h>
55: #include <dev/usb/usbdi_util.h>
56: #include <dev/usb/ustirreg.h>
57:
58: #include <dev/ir/ir.h>
59: #include <dev/ir/irdaio.h>
60: #include <dev/ir/irframevar.h>
61: #include <dev/ir/sir.h>
62:
63: #ifdef USTIR_DEBUG
1.29 dyoung 64: #define DPRINTFN(n,x) if (ustirdebug>(n)) printf x
1.1 augustss 65: int ustirdebug = 0;
66: #else
67: #define DPRINTFN(n,x)
68: #endif
69:
70: /* Max size with framing. */
71: #define MAX_USTIR_OUTPUT_FRAME (2*IRDA_MAX_FRAME_SIZE + IRDA_MAX_EBOFS + STIR_OUTPUT_HEADER_SIZE + 4)
72:
73: #define USTIR_NSPEEDS 9
74: struct ustir_speedrec {
75: unsigned int speed;
76: unsigned int config;
77: };
78:
79: Static struct ustir_speedrec const ustir_speeds[USTIR_NSPEEDS] = {
80: { 4000000, STIR_BRMODE_4000000 },
81: { 1152000, STIR_BRMODE_1152000 },
82: { 576000, STIR_BRMODE_576000 },
83: { 115200, STIR_BRMODE_115200 },
84: { 57600, STIR_BRMODE_57600 },
85: { 38400, STIR_BRMODE_38400 },
86: { 19200, STIR_BRMODE_19200 },
87: { 9600, STIR_BRMODE_9600 },
88: { 2400, STIR_BRMODE_2400 }
89: };
90:
91: struct ustir_softc {
1.29 dyoung 92: device_t sc_dev;
1.33.14.1! skrll 93: struct usbd_device *sc_udev;
! 94: struct usbd_interface *sc_iface;
1.1 augustss 95:
1.33.14.1! skrll 96: uint8_t *sc_ur_buf; /* Unencapsulated frame */
1.1 augustss 97: u_int sc_ur_framelen;
98:
1.33.14.1! skrll 99: uint8_t *sc_rd_buf; /* Raw incoming data stream */
1.1 augustss 100: size_t sc_rd_index;
101: int sc_rd_addr;
1.33.14.1! skrll 102: struct usbd_pipe *sc_rd_pipe;
! 103: struct usbd_xfer *sc_rd_xfer;
1.1 augustss 104: u_int sc_rd_count;
105: int sc_rd_readinprogress;
106: u_int sc_rd_expectdataticks;
107: u_char sc_rd_err;
108: struct framestate sc_framestate;
1.20 ad 109: struct lwp *sc_thread;
1.1 augustss 110: struct selinfo sc_rd_sel;
111:
1.33.14.1! skrll 112: uint8_t *sc_wr_buf;
1.1 augustss 113: int sc_wr_addr;
1.10 dsainty 114: int sc_wr_stalewrite;
1.33.14.1! skrll 115: struct usbd_xfer *sc_wr_xfer;
! 116: struct usbd_pipe *sc_wr_pipe;
1.1 augustss 117: struct selinfo sc_wr_sel;
118:
119: enum {
120: udir_input, /* Receiving data */
121: udir_output, /* Transmitting data */
122: udir_stalled, /* Error preventing data flow */
123: udir_idle /* Neither receiving nor transmitting */
124: } sc_direction;
125:
126: struct ustir_speedrec const *sc_speedrec;
127:
1.26 cube 128: device_t sc_child;
1.1 augustss 129: struct irda_params sc_params;
130:
131: int sc_refcnt;
132: char sc_closing;
133: char sc_dying;
134: };
135:
136: /* True if we cannot safely read data from the device */
137: #define USTIR_BLOCK_RX_DATA(sc) ((sc)->sc_ur_framelen != 0)
138:
139: #define USTIR_WR_TIMEOUT 200
140:
1.33.14.1! skrll 141: Static int ustir_activate(device_t, enum devact);
! 142: Static int ustir_open(void *, int, int, struct lwp *);
! 143: Static int ustir_close(void *, int, int, struct lwp *);
! 144: Static int ustir_read(void *, struct uio *, int);
! 145: Static int ustir_write(void *, struct uio *, int);
! 146: Static int ustir_set_params(void *, struct irda_params *);
! 147: Static int ustir_get_speeds(void *, int *);
! 148: Static int ustir_get_turnarounds(void *, int *);
! 149: Static int ustir_poll(void *, int, struct lwp *);
! 150: Static int ustir_kqfilter(void *, struct knote *);
1.1 augustss 151:
152: #ifdef USTIR_DEBUG_IOCTLS
1.33.14.1! skrll 153: Static int ustir_ioctl(void *, u_long, void *, int, struct lwp *);
1.1 augustss 154: #endif
155:
156: Static struct irframe_methods const ustir_methods = {
157: ustir_open, ustir_close, ustir_read, ustir_write, ustir_poll,
1.4 jdolecek 158: ustir_kqfilter, ustir_set_params, ustir_get_speeds,
159: ustir_get_turnarounds,
1.1 augustss 160: #ifdef USTIR_DEBUG_IOCTLS
161: ustir_ioctl
162: #endif
163: };
164:
1.33.14.1! skrll 165: Static void ustir_rd_cb(struct usbd_xfer *, void *, usbd_status);
1.2 augustss 166: Static usbd_status ustir_start_read(struct ustir_softc *);
167: Static void ustir_periodic(struct ustir_softc *);
168: Static void ustir_thread(void *);
1.1 augustss 169:
170: static usbd_status
1.33.14.1! skrll 171: ustir_read_reg(struct ustir_softc *sc, unsigned int reg, uint8_t *data)
1.1 augustss 172: {
173: usb_device_request_t req;
174:
175: req.bmRequestType = UT_READ_VENDOR_DEVICE;
176: req.bRequest = STIR_CMD_READMULTIREG;
177: USETW(req.wValue, 0);
178: USETW(req.wIndex, reg);
179: USETW(req.wLength, 1);
180:
181: return usbd_do_request(sc->sc_udev, &req, data);
182: }
183:
184: static usbd_status
1.33.14.1! skrll 185: ustir_write_reg(struct ustir_softc *sc, unsigned int reg, uint8_t data)
1.1 augustss 186: {
187: usb_device_request_t req;
188:
189: req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
190: req.bRequest = STIR_CMD_WRITESINGLEREG;
191: USETW(req.wValue, data);
192: USETW(req.wIndex, reg);
193: USETW(req.wLength, 0);
194:
195: return usbd_do_request(sc->sc_udev, &req, NULL);
196: }
197:
198: #ifdef USTIR_DEBUG
199: static void
1.33.14.1! skrll 200: ustir_dumpdata(uint8_t const *data, size_t dlen, char const *desc)
1.1 augustss 201: {
202: size_t bdindex;
203: printf("%s: (%lx)", desc, (unsigned long)dlen);
204: for (bdindex = 0; bdindex < dlen; bdindex++)
1.9 dsainty 205: printf(" %02x", (unsigned int)data[bdindex]);
1.1 augustss 206: printf("\n");
207: }
208: #endif
209:
1.26 cube 210: int ustir_match(device_t, cfdata_t, void *);
1.22 dyoung 211: void ustir_attach(device_t, device_t, void *);
212: void ustir_childdet(device_t, device_t);
213: int ustir_detach(device_t, int);
214: int ustir_activate(device_t, enum devact);
215: extern struct cfdriver ustir_cd;
1.26 cube 216: CFATTACH_DECL2_NEW(ustir, sizeof(struct ustir_softc), ustir_match,
1.22 dyoung 217: ustir_attach, ustir_detach, ustir_activate, NULL, ustir_childdet);
1.1 augustss 218:
1.33.14.1! skrll 219: int
1.29 dyoung 220: ustir_match(device_t parent, cfdata_t match, void *aux)
1.1 augustss 221: {
1.29 dyoung 222: struct usb_attach_arg *uaa = aux;
1.1 augustss 223:
224: DPRINTFN(50,("ustir_match\n"));
225:
1.33.14.1! skrll 226: if (uaa->uaa_vendor == USB_VENDOR_SIGMATEL &&
! 227: uaa->uaa_product == USB_PRODUCT_SIGMATEL_IRDA)
1.1 augustss 228: return UMATCH_VENDOR_PRODUCT;
229:
230: return UMATCH_NONE;
231: }
232:
1.33.14.1! skrll 233: void
1.29 dyoung 234: ustir_attach(device_t parent, device_t self, void *aux)
1.1 augustss 235: {
1.29 dyoung 236: struct ustir_softc *sc = device_private(self);
237: struct usb_attach_arg *uaa = aux;
1.33.14.1! skrll 238: struct usbd_device *dev = uaa->uaa_device;
! 239: struct usbd_interface *iface;
1.14 augustss 240: char *devinfop;
1.1 augustss 241: usb_endpoint_descriptor_t *ed;
1.33.14.1! skrll 242: uint8_t epcount;
1.1 augustss 243: int i;
244: struct ir_attach_args ia;
245:
246: DPRINTFN(10,("ustir_attach: sc=%p\n", sc));
247:
1.26 cube 248: sc->sc_dev = self;
249:
1.27 plunky 250: aprint_naive("\n");
251: aprint_normal("\n");
252:
1.14 augustss 253: devinfop = usbd_devinfo_alloc(dev, 0);
1.26 cube 254: aprint_normal_dev(self, "%s\n", devinfop);
1.14 augustss 255: usbd_devinfo_free(devinfop);
1.1 augustss 256:
1.19 drochner 257: if (usbd_set_config_index(dev, 0, 1)
258: || usbd_device2interface_handle(dev, 0, &iface)) {
1.26 cube 259: aprint_error_dev(self, "Configuration failed\n");
1.29 dyoung 260: return;
1.19 drochner 261: }
262:
1.1 augustss 263: sc->sc_udev = dev;
264: sc->sc_iface = iface;
265:
266: epcount = 0;
267: (void)usbd_endpoint_count(iface, &epcount);
268:
269: sc->sc_rd_addr = -1;
270: sc->sc_wr_addr = -1;
271: for (i = 0; i < epcount; i++) {
272: ed = usbd_interface2endpoint_descriptor(iface, i);
273: if (ed == NULL) {
1.26 cube 274: aprint_error_dev(self, "couldn't get ep %d\n", i);
1.29 dyoung 275: return;
1.1 augustss 276: }
277: if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
278: UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
279: sc->sc_rd_addr = ed->bEndpointAddress;
280: } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
281: UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
282: sc->sc_wr_addr = ed->bEndpointAddress;
283: }
284: }
285: if (sc->sc_rd_addr == -1 || sc->sc_wr_addr == -1) {
1.26 cube 286: aprint_error_dev(self, "missing endpoint\n");
1.29 dyoung 287: return;
1.1 augustss 288: }
289:
290: DPRINTFN(10, ("ustir_attach: %p\n", sc->sc_udev));
291:
1.33.14.1! skrll 292: usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev);
1.1 augustss 293:
294: ia.ia_type = IR_TYPE_IRFRAME;
295: ia.ia_methods = &ustir_methods;
296: ia.ia_handle = sc;
297:
298: sc->sc_child = config_found(self, &ia, ir_print);
1.23 rmind 299: selinit(&sc->sc_rd_sel);
300: selinit(&sc->sc_wr_sel);
1.1 augustss 301:
1.29 dyoung 302: return;
1.1 augustss 303: }
304:
1.22 dyoung 305: void
306: ustir_childdet(device_t self, device_t child)
307: {
308: struct ustir_softc *sc = device_private(self);
309:
310: KASSERT(sc->sc_child == child);
311: sc->sc_child = NULL;
312: }
313:
1.33.14.1! skrll 314: int
1.29 dyoung 315: ustir_detach(device_t self, int flags)
1.1 augustss 316: {
1.29 dyoung 317: struct ustir_softc *sc = device_private(self);
1.1 augustss 318: int s;
319: int rv = 0;
320:
321: DPRINTFN(0, ("ustir_detach: sc=%p flags=%d\n", sc, flags));
322:
323: sc->sc_closing = sc->sc_dying = 1;
324:
325: wakeup(&sc->sc_thread);
326:
327: while (sc->sc_thread != NULL)
328: tsleep(&sc->sc_closing, PWAIT, "usircl", 0);
329:
330: /* Abort all pipes. Causes processes waiting for transfer to wake. */
331: if (sc->sc_rd_pipe != NULL) {
332: usbd_abort_pipe(sc->sc_rd_pipe);
1.33.14.1! skrll 333: }
! 334: if (sc->sc_wr_pipe != NULL) {
! 335: usbd_abort_pipe(sc->sc_wr_pipe);
! 336: }
! 337: if (sc->sc_rd_xfer != NULL) {
! 338: usbd_destroy_xfer(sc->sc_rd_xfer);
! 339: sc->sc_rd_xfer = NULL;
! 340: sc->sc_rd_buf = NULL;
! 341: }
! 342: if (sc->sc_wr_xfer != NULL) {
! 343: usbd_destroy_xfer(sc->sc_wr_xfer);
! 344: sc->sc_wr_xfer = NULL;
! 345: sc->sc_wr_buf = NULL;
! 346: }
! 347: if (sc->sc_rd_pipe != NULL) {
1.1 augustss 348: usbd_close_pipe(sc->sc_rd_pipe);
349: sc->sc_rd_pipe = NULL;
350: }
351: if (sc->sc_wr_pipe != NULL) {
352: usbd_close_pipe(sc->sc_wr_pipe);
353: sc->sc_wr_pipe = NULL;
354: }
355: wakeup(&sc->sc_ur_framelen);
356: wakeup(&sc->sc_wr_buf);
357:
358: s = splusb();
359: if (--sc->sc_refcnt >= 0) {
360: /* Wait for processes to go away. */
1.32 mrg 361: usb_detach_waitold(sc->sc_dev);
1.1 augustss 362: }
363: splx(s);
364:
1.22 dyoung 365: if (sc->sc_child != NULL)
1.1 augustss 366: rv = config_detach(sc->sc_child, flags);
367:
1.33.14.1! skrll 368: usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev);
1.1 augustss 369:
1.23 rmind 370: seldestroy(&sc->sc_rd_sel);
371: seldestroy(&sc->sc_wr_sel);
372:
1.1 augustss 373: return rv;
374: }
375:
376: /* Returns 0 if more data required, 1 if a complete frame was extracted */
377: static int
378: deframe_rd_ur(struct ustir_softc *sc)
379: {
380: while (sc->sc_rd_index < sc->sc_rd_count) {
1.33.14.1! skrll 381: uint8_t const *buf;
1.1 augustss 382: size_t buflen;
383: enum frameresult fresult;
384:
385: buf = &sc->sc_rd_buf[sc->sc_rd_index];
386: buflen = sc->sc_rd_count - sc->sc_rd_index;
387:
388: fresult = deframe_process(&sc->sc_framestate, &buf, &buflen);
389:
390: sc->sc_rd_index = sc->sc_rd_count - buflen;
391:
1.3 augustss 392: DPRINTFN(1,("%s: result=%d\n", __func__, (int)fresult));
1.1 augustss 393:
394: switch (fresult) {
395: case FR_IDLE:
396: case FR_INPROGRESS:
397: case FR_FRAMEBADFCS:
398: case FR_FRAMEMALFORMED:
399: case FR_BUFFEROVERRUN:
400: break;
401: case FR_FRAMEOK:
402: sc->sc_ur_framelen = sc->sc_framestate.bufindex;
403: wakeup(&sc->sc_ur_framelen); /* XXX should use flag */
1.23 rmind 404: selnotify(&sc->sc_rd_sel, 0, 0);
1.1 augustss 405: return 1;
406: }
407: }
408:
409: /* Reset indices into USB-side buffer */
410: sc->sc_rd_index = sc->sc_rd_count = 0;
411:
412: return 0;
413: }
414:
415: /*
416: * Direction transitions:
417: *
418: * ustir_periodic() can switch the direction from:
419: *
420: * output -> idle
421: * output -> stalled
422: * stalled -> idle
423: * idle -> input
424: *
425: * ustir_rd_cb() can switch the direction from:
426: *
427: * input -> stalled
428: * input -> idle
429: *
430: * ustir_write() can switch the direction from:
431: *
432: * idle -> output
433: */
434: Static void
435: ustir_periodic(struct ustir_softc *sc)
436: {
437: DPRINTFN(60, ("%s: direction = %d\n",
1.3 augustss 438: __func__, sc->sc_direction));
1.1 augustss 439:
440: if (sc->sc_direction == udir_output ||
441: sc->sc_direction == udir_stalled) {
442: usbd_status err;
1.33.14.1! skrll 443: uint8_t regval;
1.1 augustss 444:
445: DPRINTFN(60, ("%s: reading status register\n",
1.3 augustss 446: __func__));
1.1 augustss 447:
448: err = ustir_read_reg(sc, STIR_REG_STATUS,
449: ®val);
1.8 dsainty 450: if (err != USBD_NORMAL_COMPLETION) {
1.26 cube 451: aprint_error_dev(sc->sc_dev,
452: "status register read failed: %s\n",
453: usbd_errstr(err));
1.1 augustss 454: } else {
455: DPRINTFN(10, ("%s: status register = 0x%x\n",
1.3 augustss 456: __func__,
1.1 augustss 457: (unsigned int)regval));
458: if (sc->sc_direction == udir_output &&
459: !(regval & STIR_RSTATUS_FFDIR))
460: /* Output has completed */
461: sc->sc_direction = udir_idle;
462: if (regval & STIR_RSTATUS_FFOVER) {
463: /*
464: * On an overrun the FIFO hangs, and
465: * any data bulk transfers will stall.
466: * Reset the FIFO.
467: */
468: sc->sc_direction = udir_stalled;
469:
470: DPRINTFN(10, ("%s: clearing FIFO error\n",
1.3 augustss 471: __func__));
1.1 augustss 472:
473: err = ustir_write_reg(sc, STIR_REG_STATUS,
474: STIR_RSTATUS_FFCLR);
475: /* XXX if we fail partway through
476: * this, we may not recover? */
1.8 dsainty 477: if (err == USBD_NORMAL_COMPLETION)
1.1 augustss 478: err = ustir_write_reg(sc,
479: STIR_REG_STATUS,
480: 0);
1.8 dsainty 481: if (err != USBD_NORMAL_COMPLETION) {
1.26 cube 482: aprint_error_dev(sc->sc_dev,
483: "FIFO reset failed: %s\n",
484: usbd_errstr(err));
1.1 augustss 485: } else {
486: /* FIFO reset */
487: sc->sc_direction = udir_idle;
488: }
489: }
490: }
491: }
492:
1.10 dsainty 493: if (sc->sc_wr_stalewrite && sc->sc_direction == udir_idle) {
494: /*
495: * In a stale write case, we need to check if the
496: * write has completed. Once that has happened, the
497: * write is no longer stale.
498: *
499: * But note that we may immediately start a read poll...
500: */
501: sc->sc_wr_stalewrite = 0;
502: wakeup(&sc->sc_wr_buf);
503: }
504:
1.1 augustss 505: if (!sc->sc_rd_readinprogress &&
506: (sc->sc_direction == udir_idle ||
507: sc->sc_direction == udir_input))
508: /* Do a read poll if appropriate... */
509: ustir_start_read(sc);
510: }
511:
512: Static void
513: ustir_thread(void *arg)
514: {
515: struct ustir_softc *sc = arg;
516:
1.3 augustss 517: DPRINTFN(20, ("%s: starting polling thread\n", __func__));
1.1 augustss 518:
519: while (!sc->sc_closing) {
520: if (!sc->sc_rd_readinprogress && !USTIR_BLOCK_RX_DATA(sc))
521: ustir_periodic(sc);
522:
523: if (!sc->sc_closing) {
524: int error;
525: error = tsleep(&sc->sc_thread, PWAIT,
526: "ustir", hz / 10);
527: if (error == EWOULDBLOCK &&
528: sc->sc_rd_expectdataticks > 0)
529: /*
530: * After a timeout decrement the tick
531: * counter within which time we expect
532: * data to arrive if we are receiving
533: * data...
534: */
535: sc->sc_rd_expectdataticks--;
536: }
537: }
538:
1.3 augustss 539: DPRINTFN(20, ("%s: exiting polling thread\n", __func__));
1.1 augustss 540:
541: sc->sc_thread = NULL;
542:
543: wakeup(&sc->sc_closing);
544:
545: if (--sc->sc_refcnt < 0)
1.32 mrg 546: usb_detach_wakeupold(sc->sc_dev);
1.1 augustss 547:
548: kthread_exit(0);
549: }
550:
551: Static void
1.33.14.1! skrll 552: ustir_rd_cb(struct usbd_xfer *xfer, void *priv,
1.1 augustss 553: usbd_status status)
554: {
555: struct ustir_softc *sc = priv;
1.33.14.1! skrll 556: uint32_t size;
1.1 augustss 557:
1.3 augustss 558: DPRINTFN(60, ("%s: sc=%p\n", __func__, sc));
1.1 augustss 559:
560: /* Read is no longer in progress */
561: sc->sc_rd_readinprogress = 0;
562:
563: if (status == USBD_CANCELLED || sc->sc_closing) /* this is normal */
564: return;
565: if (status) {
566: size = 0;
567: sc->sc_rd_err = 1;
568:
569: if (sc->sc_direction == udir_input ||
570: sc->sc_direction == udir_idle) {
571: /*
572: * Receive error, probably need to clear error
573: * condition.
574: */
575: sc->sc_direction = udir_stalled;
576: }
577: } else {
578: usbd_get_xfer_status(xfer, NULL, NULL, &size, NULL);
579: }
580:
581: sc->sc_rd_index = 0;
582: sc->sc_rd_count = size;
583:
584: DPRINTFN(((size > 0 || sc->sc_rd_err != 0) ? 20 : 60),
1.3 augustss 585: ("%s: sc=%p size=%u, err=%d\n", __func__,
1.1 augustss 586: sc, size, sc->sc_rd_err));
587:
588: #ifdef USTIR_DEBUG
589: if (ustirdebug >= 20 && size > 0)
1.3 augustss 590: ustir_dumpdata(sc->sc_rd_buf, size, __func__);
1.1 augustss 591: #endif
592:
593: if (!deframe_rd_ur(sc)) {
594: if (!deframe_isclear(&sc->sc_framestate) && size == 0 &&
595: sc->sc_rd_expectdataticks == 0) {
596: /*
597: * Expected data, but didn't get it
598: * within expected time...
599: */
600: DPRINTFN(5,("%s: incoming packet timeout\n",
1.3 augustss 601: __func__));
1.1 augustss 602: deframe_clear(&sc->sc_framestate);
603: } else if (size > 0) {
604: /*
605: * If we also received actual data, reset the
606: * data read timeout and wake up the possibly
607: * sleeping thread...
608: */
609: sc->sc_rd_expectdataticks = 2;
610: wakeup(&sc->sc_thread);
611: }
612: }
613:
614: /*
615: * Check if incoming data has stopped, or that we cannot
616: * safely read any more data. In the case of the latter we
617: * must switch to idle so that a write will not block...
618: */
619: if (sc->sc_direction == udir_input &&
620: ((size == 0 && sc->sc_rd_expectdataticks == 0) ||
621: USTIR_BLOCK_RX_DATA(sc))) {
1.10 dsainty 622: DPRINTFN(8,("%s: idling on packet timeout, "
623: "complete frame, or no data\n", __func__));
1.1 augustss 624: sc->sc_direction = udir_idle;
625:
626: /* Wake up for possible output */
627: wakeup(&sc->sc_wr_buf);
1.23 rmind 628: selnotify(&sc->sc_wr_sel, 0, 0);
1.1 augustss 629: }
630: }
631:
632: Static usbd_status
633: ustir_start_read(struct ustir_softc *sc)
634: {
635: usbd_status err;
636:
1.3 augustss 637: DPRINTFN(60,("%s: sc=%p, size=%d\n", __func__, sc,
1.1 augustss 638: sc->sc_params.maxsize));
639:
640: if (sc->sc_dying)
641: return USBD_IOERROR;
642:
643: if (USTIR_BLOCK_RX_DATA(sc) || deframe_rd_ur(sc)) {
644: /*
645: * Can't start reading just yet. Since we aren't
646: * going to start a read, have to switch direction to
647: * idle.
648: */
649: sc->sc_direction = udir_idle;
650: return USBD_NORMAL_COMPLETION;
651: }
652:
653: /* Starting a read... */
654: sc->sc_rd_readinprogress = 1;
655: sc->sc_direction = udir_input;
656:
657: if (sc->sc_rd_err) {
658: sc->sc_rd_err = 0;
1.3 augustss 659: DPRINTFN(0, ("%s: clear stall\n", __func__));
1.1 augustss 660: usbd_clear_endpoint_stall(sc->sc_rd_pipe);
661: }
662:
1.33.14.1! skrll 663: usbd_setup_xfer(sc->sc_rd_xfer, sc, sc->sc_rd_buf,
! 664: sc->sc_params.maxsize, USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT,
! 665: ustir_rd_cb);
1.1 augustss 666: err = usbd_transfer(sc->sc_rd_xfer);
667: if (err != USBD_IN_PROGRESS) {
1.8 dsainty 668: DPRINTFN(0, ("%s: err=%d\n", __func__, (int)err));
1.1 augustss 669: return err;
670: }
671: return USBD_NORMAL_COMPLETION;
672: }
673:
674: Static int
1.22 dyoung 675: ustir_activate(device_t self, enum devact act)
1.1 augustss 676: {
1.22 dyoung 677: struct ustir_softc *sc = device_private(self);
1.1 augustss 678:
679: switch (act) {
680: case DVACT_DEACTIVATE:
681: sc->sc_dying = 1;
1.28 dyoung 682: return 0;
683: default:
684: return EOPNOTSUPP;
1.1 augustss 685: }
686: }
687:
1.5 dsainty 688: /* ARGSUSED */
1.1 augustss 689: Static int
1.17 christos 690: ustir_open(void *h, int flag, int mode,
691: struct lwp *l)
1.1 augustss 692: {
693: struct ustir_softc *sc = h;
694: int error;
695: usbd_status err;
696:
1.3 augustss 697: DPRINTFN(0, ("%s: sc=%p\n", __func__, sc));
1.1 augustss 698:
699: err = usbd_open_pipe(sc->sc_iface, sc->sc_rd_addr, 0, &sc->sc_rd_pipe);
1.8 dsainty 700: if (err != USBD_NORMAL_COMPLETION) {
1.1 augustss 701: error = EIO;
702: goto bad1;
703: }
704: err = usbd_open_pipe(sc->sc_iface, sc->sc_wr_addr, 0, &sc->sc_wr_pipe);
1.8 dsainty 705: if (err != USBD_NORMAL_COMPLETION) {
1.1 augustss 706: error = EIO;
707: goto bad2;
708: }
1.33.14.1! skrll 709: error = usbd_create_xfer(sc->sc_rd_pipe, IRDA_MAX_FRAME_SIZE,
! 710: USBD_SHORT_XFER_OK, 0, &sc->sc_rd_xfer);
! 711: if (error)
1.1 augustss 712: goto bad3;
1.33.14.1! skrll 713: sc->sc_rd_buf = usbd_get_buffer(sc->sc_rd_xfer);
! 714:
! 715: error = usbd_create_xfer(sc->sc_wr_pipe,
! 716: IRDA_MAX_FRAME_SIZE + STIR_OUTPUT_HEADER_SIZE,
! 717: USBD_FORCE_SHORT_XFER, 0, &sc->sc_wr_xfer);
! 718: if (error)
1.1 augustss 719: goto bad4;
1.33.14.1! skrll 720: sc->sc_wr_buf = usbd_get_buffer(sc->sc_wr_xfer);
! 721:
! 722: sc->sc_ur_buf = kmem_alloc(IRDA_MAX_FRAME_SIZE, KM_SLEEP);
1.1 augustss 723: if (sc->sc_ur_buf == NULL) {
724: error = ENOMEM;
725: goto bad5;
726: }
727:
728: sc->sc_rd_index = sc->sc_rd_count = 0;
729: sc->sc_closing = 0;
730: sc->sc_rd_readinprogress = 0;
731: sc->sc_rd_expectdataticks = 0;
732: sc->sc_ur_framelen = 0;
733: sc->sc_rd_err = 0;
1.10 dsainty 734: sc->sc_wr_stalewrite = 0;
1.1 augustss 735: sc->sc_speedrec = NULL;
736: sc->sc_direction = udir_idle;
737: sc->sc_params.speed = 0;
738: sc->sc_params.ebofs = 0;
739: sc->sc_params.maxsize = IRDA_MAX_FRAME_SIZE;
740:
1.33 kiyohara 741: deframe_init(&sc->sc_framestate, sc->sc_ur_buf, IRDA_MAX_FRAME_SIZE);
1.1 augustss 742:
743: /* Increment reference for thread */
744: sc->sc_refcnt++;
745:
1.20 ad 746: error = kthread_create(PRI_NONE, 0, NULL, ustir_thread, sc,
1.26 cube 747: &sc->sc_thread, "%s", device_xname(sc->sc_dev));
1.20 ad 748: if (error) {
749: sc->sc_refcnt--;
750: goto bad5;
751: }
752:
1.1 augustss 753: return 0;
754:
755: bad5:
1.33.14.1! skrll 756: usbd_destroy_xfer(sc->sc_wr_xfer);
1.1 augustss 757: sc->sc_wr_xfer = NULL;
758: bad4:
1.33.14.1! skrll 759: usbd_destroy_xfer(sc->sc_rd_xfer);
1.1 augustss 760: sc->sc_rd_xfer = NULL;
761: bad3:
762: usbd_close_pipe(sc->sc_wr_pipe);
763: sc->sc_wr_pipe = NULL;
764: bad2:
765: usbd_close_pipe(sc->sc_rd_pipe);
766: sc->sc_rd_pipe = NULL;
767: bad1:
768: return error;
769: }
770:
1.5 dsainty 771: /* ARGSUSED */
1.1 augustss 772: Static int
1.17 christos 773: ustir_close(void *h, int flag, int mode,
774: struct lwp *l)
1.1 augustss 775: {
776: struct ustir_softc *sc = h;
777:
1.3 augustss 778: DPRINTFN(0, ("%s: sc=%p\n", __func__, sc));
1.1 augustss 779:
780: sc->sc_refcnt++;
781:
782: sc->sc_rd_readinprogress = 1;
783: sc->sc_closing = 1;
784:
785: wakeup(&sc->sc_thread);
786:
787: while (sc->sc_thread != NULL)
788: tsleep(&sc->sc_closing, PWAIT, "usircl", 0);
789:
790: if (sc->sc_rd_pipe != NULL) {
791: usbd_abort_pipe(sc->sc_rd_pipe);
792: sc->sc_rd_pipe = NULL;
793: }
794: if (sc->sc_wr_pipe != NULL) {
795: usbd_abort_pipe(sc->sc_wr_pipe);
796: sc->sc_wr_pipe = NULL;
797: }
798: if (sc->sc_rd_xfer != NULL) {
1.33.14.1! skrll 799: usbd_destroy_xfer(sc->sc_rd_xfer);
1.1 augustss 800: sc->sc_rd_xfer = NULL;
801: sc->sc_rd_buf = NULL;
802: }
803: if (sc->sc_wr_xfer != NULL) {
1.33.14.1! skrll 804: usbd_destroy_xfer(sc->sc_wr_xfer);
1.1 augustss 805: sc->sc_wr_xfer = NULL;
806: sc->sc_wr_buf = NULL;
807: }
808: if (sc->sc_ur_buf != NULL) {
1.33.14.1! skrll 809: kmem_free(sc->sc_ur_buf, IRDA_MAX_FRAME_SIZE);
1.1 augustss 810: sc->sc_ur_buf = NULL;
811: }
1.33.14.1! skrll 812: if (sc->sc_rd_pipe != NULL) {
! 813: usbd_close_pipe(sc->sc_rd_pipe);
! 814: sc->sc_rd_pipe = NULL;
! 815: }
! 816: if (sc->sc_wr_pipe != NULL) {
! 817: usbd_close_pipe(sc->sc_wr_pipe);
! 818: sc->sc_wr_pipe = NULL;
! 819: }
1.1 augustss 820:
821: if (--sc->sc_refcnt < 0)
1.32 mrg 822: usb_detach_wakeupold(sc->sc_dev);
1.1 augustss 823:
824: return 0;
825: }
826:
1.7 dsainty 827: /* ARGSUSED */
1.1 augustss 828: Static int
1.17 christos 829: ustir_read(void *h, struct uio *uio, int flag)
1.1 augustss 830: {
831: struct ustir_softc *sc = h;
832: int s;
833: int error;
834: u_int uframelen;
835:
1.3 augustss 836: DPRINTFN(1,("%s: sc=%p\n", __func__, sc));
1.1 augustss 837:
838: if (sc->sc_dying)
839: return EIO;
840:
841: #ifdef DIAGNOSTIC
842: if (sc->sc_rd_buf == NULL)
843: return EINVAL;
844: #endif
845:
846: sc->sc_refcnt++;
847:
848: if (!sc->sc_rd_readinprogress && !USTIR_BLOCK_RX_DATA(sc))
849: /* Possibly wake up polling thread */
850: wakeup(&sc->sc_thread);
851:
852: do {
853: s = splusb();
854: while (sc->sc_ur_framelen == 0) {
1.3 augustss 855: DPRINTFN(5,("%s: calling tsleep()\n", __func__));
1.1 augustss 856: error = tsleep(&sc->sc_ur_framelen, PZERO | PCATCH,
857: "usirrd", 0);
858: if (sc->sc_dying)
859: error = EIO;
860: if (error) {
861: splx(s);
862: DPRINTFN(0, ("%s: tsleep() = %d\n",
1.3 augustss 863: __func__, error));
1.1 augustss 864: goto ret;
865: }
866: }
867: splx(s);
868:
869: uframelen = sc->sc_ur_framelen;
870: DPRINTFN(1,("%s: sc=%p framelen=%u, hdr=0x%02x\n",
1.3 augustss 871: __func__, sc, uframelen, sc->sc_ur_buf[0]));
1.1 augustss 872: if (uframelen > uio->uio_resid)
873: error = EINVAL;
874: else
875: error = uiomove(sc->sc_ur_buf, uframelen, uio);
876: sc->sc_ur_framelen = 0;
877:
878: if (!deframe_rd_ur(sc) && uframelen > 0) {
879: /*
880: * Need to wait for another read to obtain a
881: * complete frame... If we also obtained
882: * actual data, wake up the possibly sleeping
883: * thread immediately...
884: */
885: wakeup(&sc->sc_thread);
886: }
887: } while (uframelen == 0);
888:
1.3 augustss 889: DPRINTFN(1,("%s: return %d\n", __func__, error));
1.1 augustss 890:
891: ret:
892: if (--sc->sc_refcnt < 0)
1.32 mrg 893: usb_detach_wakeupold(sc->sc_dev);
1.1 augustss 894: return error;
895: }
896:
1.7 dsainty 897: /* ARGSUSED */
1.1 augustss 898: Static int
1.17 christos 899: ustir_write(void *h, struct uio *uio, int flag)
1.1 augustss 900: {
901: struct ustir_softc *sc = h;
902: usbd_status err;
1.33.14.1! skrll 903: uint32_t wrlen;
1.1 augustss 904: int error, sirlength;
1.33.14.1! skrll 905: uint8_t *wrbuf;
1.1 augustss 906: int s;
907:
1.3 augustss 908: DPRINTFN(1,("%s: sc=%p\n", __func__, sc));
1.1 augustss 909:
910: if (sc->sc_dying)
911: return EIO;
912:
913: #ifdef DIAGNOSTIC
914: if (sc->sc_wr_buf == NULL)
915: return EINVAL;
916: #endif
917:
918: wrlen = uio->uio_resid;
919: if (wrlen > sc->sc_params.maxsize)
920: return EINVAL;
921:
922: sc->sc_refcnt++;
923:
1.10 dsainty 924: if (!USTIR_BLOCK_RX_DATA(sc)) {
925: /*
926: * If reads are not blocked, determine what action we
927: * should potentially take...
928: */
929: if (sc->sc_direction == udir_output) {
930: /*
931: * If the last operation was an output, wait for the
932: * polling thread to check for incoming data.
933: */
934: sc->sc_wr_stalewrite = 1;
935: wakeup(&sc->sc_thread);
936: } else if (!sc->sc_rd_readinprogress &&
937: (sc->sc_direction == udir_idle ||
938: sc->sc_direction == udir_input)) {
939: /* If idle, check for input before outputting */
940: ustir_start_read(sc);
941: }
942: }
1.1 augustss 943:
944: s = splusb();
1.10 dsainty 945: while (sc->sc_wr_stalewrite ||
946: (sc->sc_direction != udir_output &&
947: sc->sc_direction != udir_idle)) {
948: DPRINTFN(5, ("%s: sc=%p stalewrite=%d direction=%d, "
949: "calling tsleep()\n", __func__,
950: sc, sc->sc_wr_stalewrite, sc->sc_direction));
1.1 augustss 951: error = tsleep(&sc->sc_wr_buf, PZERO | PCATCH,
952: "usirwr", 0);
953: if (sc->sc_dying)
954: error = EIO;
955: if (error) {
956: splx(s);
1.3 augustss 957: DPRINTFN(0, ("%s: tsleep() = %d\n", __func__,
1.1 augustss 958: error));
959: goto ret;
960: }
961: }
962: splx(s);
963:
964: wrbuf = sc->sc_wr_buf;
965:
966: /* Build header */
967: wrbuf[0] = STIR_OUTPUT_HEADER_BYTE0;
968: wrbuf[1] = STIR_OUTPUT_HEADER_BYTE1;
969:
970: sirlength = irda_sir_frame(&wrbuf[STIR_OUTPUT_HEADER_SIZE],
971: MAX_USTIR_OUTPUT_FRAME -
972: STIR_OUTPUT_HEADER_SIZE,
973: uio, sc->sc_params.ebofs);
974: if (sirlength < 0) {
975: error = -sirlength;
976: } else {
1.33.14.1! skrll 977: uint32_t btlen;
1.1 augustss 978:
1.3 augustss 979: DPRINTFN(1, ("%s: transfer %u bytes\n", __func__,
1.1 augustss 980: (unsigned int)wrlen));
981:
982: wrbuf[2] = sirlength & 0xff;
983: wrbuf[3] = (sirlength >> 8) & 0xff;
984:
985: btlen = STIR_OUTPUT_HEADER_SIZE + sirlength;
986:
987: sc->sc_direction = udir_output;
988:
989: #ifdef USTIR_DEBUG
990: if (ustirdebug >= 20)
1.3 augustss 991: ustir_dumpdata(wrbuf, btlen, __func__);
1.1 augustss 992: #endif
993:
994: err = usbd_bulk_transfer(sc->sc_wr_xfer, sc->sc_wr_pipe,
1.33.14.1! skrll 995: USBD_FORCE_SHORT_XFER, USTIR_WR_TIMEOUT, wrbuf, &btlen);
1.3 augustss 996: DPRINTFN(2, ("%s: err=%d\n", __func__, err));
1.8 dsainty 997: if (err != USBD_NORMAL_COMPLETION) {
1.1 augustss 998: if (err == USBD_INTERRUPTED)
999: error = EINTR;
1000: else if (err == USBD_TIMEOUT)
1001: error = ETIMEDOUT;
1002: else
1003: error = EIO;
1004: } else {
1005: error = 0;
1006: }
1007: }
1008:
1009: ret:
1010: if (--sc->sc_refcnt < 0)
1.32 mrg 1011: usb_detach_wakeupold(sc->sc_dev);
1.1 augustss 1012:
1.3 augustss 1013: DPRINTFN(1,("%s: sc=%p done\n", __func__, sc));
1.1 augustss 1014: return error;
1015: }
1016:
1017: Static int
1.15 christos 1018: ustir_poll(void *h, int events, struct lwp *l)
1.1 augustss 1019: {
1020: struct ustir_softc *sc = h;
1021: int revents = 0;
1022:
1.3 augustss 1023: DPRINTFN(1,("%s: sc=%p\n", __func__, sc));
1.1 augustss 1024:
1025: if (events & (POLLOUT | POLLWRNORM)) {
1026: if (sc->sc_direction != udir_input) {
1027: revents |= events & (POLLOUT | POLLWRNORM);
1028: } else {
1029: DPRINTFN(2,("%s: recording write select\n",
1.3 augustss 1030: __func__));
1.15 christos 1031: selrecord(l, &sc->sc_wr_sel);
1.1 augustss 1032: }
1033: }
1034:
1035: if (events & (POLLIN | POLLRDNORM)) {
1036: if (sc->sc_ur_framelen != 0) {
1.3 augustss 1037: DPRINTFN(2,("%s: have data\n", __func__));
1.1 augustss 1038: revents |= events & (POLLIN | POLLRDNORM);
1039: } else {
1040: DPRINTFN(2,("%s: recording read select\n",
1.3 augustss 1041: __func__));
1.15 christos 1042: selrecord(l, &sc->sc_rd_sel);
1.1 augustss 1043: }
1044: }
1045:
1046: return revents;
1.4 jdolecek 1047: }
1048:
1049: static void
1050: filt_ustirrdetach(struct knote *kn)
1051: {
1052: struct ustir_softc *sc = kn->kn_hook;
1053: int s;
1054:
1055: s = splusb();
1.6 christos 1056: SLIST_REMOVE(&sc->sc_rd_sel.sel_klist, kn, knote, kn_selnext);
1.4 jdolecek 1057: splx(s);
1058: }
1059:
1.7 dsainty 1060: /* ARGSUSED */
1.4 jdolecek 1061: static int
1.17 christos 1062: filt_ustirread(struct knote *kn, long hint)
1.4 jdolecek 1063: {
1064: struct ustir_softc *sc = kn->kn_hook;
1065:
1066: kn->kn_data = sc->sc_ur_framelen;
1.33.14.1! skrll 1067: return kn->kn_data > 0;
1.4 jdolecek 1068: }
1069:
1070: static void
1071: filt_ustirwdetach(struct knote *kn)
1072: {
1073: struct ustir_softc *sc = kn->kn_hook;
1074: int s;
1075:
1076: s = splusb();
1.6 christos 1077: SLIST_REMOVE(&sc->sc_wr_sel.sel_klist, kn, knote, kn_selnext);
1.4 jdolecek 1078: splx(s);
1079: }
1080:
1.7 dsainty 1081: /* ARGSUSED */
1.4 jdolecek 1082: static int
1.17 christos 1083: filt_ustirwrite(struct knote *kn, long hint)
1.4 jdolecek 1084: {
1085: struct ustir_softc *sc = kn->kn_hook;
1086:
1087: kn->kn_data = 0;
1.33.14.1! skrll 1088: return sc->sc_direction != udir_input;
1.4 jdolecek 1089: }
1090:
1091: static const struct filterops ustirread_filtops =
1092: { 1, NULL, filt_ustirrdetach, filt_ustirread };
1093: static const struct filterops ustirwrite_filtops =
1094: { 1, NULL, filt_ustirwdetach, filt_ustirwrite };
1095:
1096: Static int
1097: ustir_kqfilter(void *h, struct knote *kn)
1098: {
1099: struct ustir_softc *sc = h;
1100: struct klist *klist;
1101: int s;
1102:
1103: switch (kn->kn_filter) {
1104: case EVFILT_READ:
1.6 christos 1105: klist = &sc->sc_rd_sel.sel_klist;
1.4 jdolecek 1106: kn->kn_fop = &ustirread_filtops;
1107: break;
1108: case EVFILT_WRITE:
1.6 christos 1109: klist = &sc->sc_wr_sel.sel_klist;
1.4 jdolecek 1110: kn->kn_fop = &ustirwrite_filtops;
1111: break;
1112: default:
1.33.14.1! skrll 1113: return EINVAL;
1.4 jdolecek 1114: }
1115:
1116: kn->kn_hook = sc;
1117:
1118: s = splusb();
1119: SLIST_INSERT_HEAD(klist, kn, kn_selnext);
1120: splx(s);
1121:
1.33.14.1! skrll 1122: return 0;
1.1 augustss 1123: }
1124:
1125: #ifdef USTIR_DEBUG_IOCTLS
1.18 christos 1126: Static int ustir_ioctl(void *h, u_long cmd, void *addr, int flag, struct lwp *l)
1.1 augustss 1127: {
1128: struct ustir_softc *sc = h;
1129: int error;
1130: unsigned int regnum;
1131: usbd_status err;
1.33.14.1! skrll 1132: uint8_t regdata;
1.1 augustss 1133:
1134: if (sc->sc_dying)
1135: return EIO;
1136:
1137: sc->sc_refcnt++;
1138:
1139: error = 0;
1140: switch (cmd) {
1141: case USTIR_READ_REGISTER:
1.2 augustss 1142: regnum = *(unsigned int *)addr;
1.1 augustss 1143:
1144: if (regnum > STIR_MAX_REG) {
1145: error = EINVAL;
1146: break;
1147: }
1148:
1149: err = ustir_read_reg(sc, regnum, ®data);
1150:
1.3 augustss 1151: DPRINTFN(10, ("%s: regget(%u) = 0x%x\n", __func__,
1.1 augustss 1152: regnum, (unsigned int)regdata));
1153:
1.2 augustss 1154: *(unsigned int *)addr = regdata;
1.8 dsainty 1155: if (err != USBD_NORMAL_COMPLETION) {
1.1 augustss 1156: printf("%s: register read failed: %s\n",
1.29 dyoung 1157: device_xname(sc->sc_dev),
1.1 augustss 1158: usbd_errstr(err));
1159: error = EIO;
1160: }
1161: break;
1162:
1163: case USTIR_WRITE_REGISTER:
1.2 augustss 1164: regnum = *(unsigned int *)addr;
1.1 augustss 1165: regdata = (regnum >> 8) & 0xff;
1166: regnum = regnum & 0xff;
1167:
1168: if (regnum > STIR_MAX_REG) {
1169: error = EINVAL;
1170: break;
1171: }
1172:
1.3 augustss 1173: DPRINTFN(10, ("%s: regset(%u, 0x%x)\n", __func__,
1.1 augustss 1174: regnum, (unsigned int)regdata));
1175:
1176: err = ustir_write_reg(sc, regnum, regdata);
1.8 dsainty 1177: if (err != USBD_NORMAL_COMPLETION) {
1.1 augustss 1178: printf("%s: register write failed: %s\n",
1.29 dyoung 1179: device_xname(sc->sc_dev),
1.1 augustss 1180: usbd_errstr(err));
1181: error = EIO;
1182: }
1183: break;
1184:
1185: case USTIR_DEBUG_LEVEL:
1186: #ifdef USTIR_DEBUG
1.2 augustss 1187: ustirdebug = *(int *)addr;
1.1 augustss 1188: #endif
1189: break;
1190:
1191: case USTIR_DEBUG_OPERATION:
1192: break;
1193:
1194: default:
1195: error = EINVAL;
1196: break;
1197: }
1198:
1199: if (--sc->sc_refcnt < 0)
1.32 mrg 1200: usb_detach_wakeupold(sc->sc_dev);
1.1 augustss 1201:
1202: return error;
1203: }
1204: #endif
1205:
1206: Static int
1207: ustir_set_params(void *h, struct irda_params *p)
1208: {
1209: struct ustir_softc *sc = h;
1210: struct ustir_speedrec const *speedblk;
1211: int i;
1212:
1.3 augustss 1213: DPRINTFN(0, ("%s: sc=%p, speed=%d ebofs=%d maxsize=%d\n", __func__,
1.1 augustss 1214: sc, p->speed, p->ebofs, p->maxsize));
1215:
1216: if (sc->sc_dying)
1217: return EIO;
1218:
1219: speedblk = NULL;
1220:
1221: if (sc->sc_speedrec == NULL || p->speed != sc->sc_speedrec->speed) {
1222: /* find speed */
1223: for (i = 0; i < USTIR_NSPEEDS; i++) {
1224: if (ustir_speeds[i].speed == p->speed) {
1225: speedblk = &ustir_speeds[i];
1226: goto found2;
1227: }
1228: }
1229: /* no good value found */
1230: return EINVAL;
1231: found2:
1232: ;
1233: }
1234: if (p->maxsize != sc->sc_params.maxsize) {
1235: if (p->maxsize > IRDA_MAX_FRAME_SIZE)
1236: return EINVAL;
1237: sc->sc_params.maxsize = p->maxsize;
1238: }
1239:
1240: sc->sc_params = *p;
1241:
1242: if (speedblk != NULL) {
1243: usbd_status err;
1.33.14.1! skrll 1244: uint8_t regmode;
! 1245: uint8_t regbrate;
1.1 augustss 1246:
1247: sc->sc_speedrec = speedblk;
1248:
1249: regmode = STIR_BRMODE_MODEREG(speedblk->config);
1250: regbrate = STIR_BRMODE_BRATEREG(speedblk->config);
1251:
1252: /*
1253: * FFSPRST must be set to enable the FIFO.
1254: */
1255: regmode |= STIR_RMODE_FFSPRST;
1256:
1.3 augustss 1257: DPRINTFN(10, ("%s: setting BRATE = %x\n", __func__,
1.1 augustss 1258: (unsigned int)regbrate));
1259: err = ustir_write_reg(sc, STIR_REG_BRATE, regbrate);
1.8 dsainty 1260: if (err == USBD_NORMAL_COMPLETION) {
1.3 augustss 1261: DPRINTFN(10, ("%s: setting MODE = %x\n", __func__,
1.1 augustss 1262: (unsigned int)regmode));
1263: err = ustir_write_reg(sc, STIR_REG_MODE, regmode);
1264: }
1.8 dsainty 1265: if (err != USBD_NORMAL_COMPLETION) {
1.1 augustss 1266: DPRINTFN(10, ("%s: error setting register: %s\n",
1.3 augustss 1267: __func__, usbd_errstr(err)));
1.1 augustss 1268: return EIO;
1269: }
1270: }
1271:
1272: return 0;
1273: }
1274:
1275: Static int
1276: ustir_get_speeds(void *h, int *speeds)
1277: {
1278: struct ustir_softc *sc = h;
1279:
1.3 augustss 1280: DPRINTFN(0, ("%s: sc=%p\n", __func__, sc));
1.1 augustss 1281:
1282: if (sc->sc_dying)
1283: return EIO;
1284:
1285: /* All these speeds are supported */
1286: *speeds = IRDA_SPEED_4000000 |
1287: IRDA_SPEED_1152000 |
1288: IRDA_SPEED_576000 |
1289: IRDA_SPEED_115200 |
1290: IRDA_SPEED_57600 |
1291: IRDA_SPEED_38400 |
1292: IRDA_SPEED_19200 |
1293: IRDA_SPEED_9600 |
1294: IRDA_SPEED_2400;
1295:
1296: return 0;
1297: }
1298:
1299: Static int
1300: ustir_get_turnarounds(void *h, int *turnarounds)
1301: {
1302: struct ustir_softc *sc = h;
1303:
1.3 augustss 1304: DPRINTFN(0, ("%s: sc=%p\n", __func__, sc));
1.1 augustss 1305:
1306: if (sc->sc_dying)
1307: return EIO;
1308:
1309: /*
1310: * Documentation is on the light side with respect to
1311: * turnaround time for this device.
1312: */
1313: *turnarounds = IRDA_TURNT_10000;
1314:
1315: return 0;
1316: }
CVSweb <webmaster@jp.NetBSD.org>