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