Annotation of sys/dev/usb/uvscom.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: uvscom.c,v 1.18 2007/06/14 10:11:16 mbalmer Exp $ */
2: /* $NetBSD: uvscom.c,v 1.9 2003/02/12 15:36:20 ichiro Exp $ */
3: /*-
4: * Copyright (c) 2001-2002, Shunsuke Akiyama <akiyama@jp.FreeBSD.org>.
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26: * SUCH DAMAGE.
27: *
28: * $FreeBSD: src/sys/dev/usb/uvscom.c,v 1.1 2002/03/18 18:23:39 joe Exp $
29: */
30:
31: /*
32: * uvscom: SUNTAC Slipper U VS-10U driver.
33: * Slipper U is a PC card to USB converter for data communication card
34: * adapter. It supports DDI Pocket's Air H" C@rd, C@rd H" 64, NTT's P-in,
35: * P-in m@ater and various data communication card adapters.
36: */
37:
38: #include <sys/param.h>
39: #include <sys/systm.h>
40: #include <sys/kernel.h>
41: #include <sys/malloc.h>
42: #include <sys/fcntl.h>
43: #include <sys/conf.h>
44: #include <sys/tty.h>
45: #include <sys/file.h>
46: #include <sys/ioctl.h>
47: #include <sys/device.h>
48: #include <sys/proc.h>
49: #include <sys/vnode.h>
50: #include <sys/poll.h>
51:
52: #include <dev/usb/usb.h>
53: #include <dev/usb/usbcdc.h>
54:
55: #include <dev/usb/usbdi.h>
56: #include <dev/usb/usbdi_util.h>
57: #include <dev/usb/usbdevs.h>
58: #include <dev/usb/usb_quirks.h>
59:
60: #include <dev/usb/ucomvar.h>
61:
62: #ifdef UVSCOM_DEBUG
63: static int uvscomdebug = 1;
64:
65: #define DPRINTFN(n, x) do { if (uvscomdebug > (n)) printf x; } while (0)
66: #else
67: #define DPRINTFN(n, x)
68: #endif
69: #define DPRINTF(x) DPRINTFN(0, x)
70:
71: #define UVSCOM_CONFIG_INDEX 0
72: #define UVSCOM_IFACE_INDEX 0
73:
74: #define UVSCOM_INTR_INTERVAL 100 /* mS */
75:
76: #define UVSCOM_UNIT_WAIT 5
77:
78: /* Request */
79: #define UVSCOM_SET_SPEED 0x10
80: #define UVSCOM_LINE_CTL 0x11
81: #define UVSCOM_SET_PARAM 0x12
82: #define UVSCOM_READ_STATUS 0xd0
83: #define UVSCOM_SHUTDOWN 0xe0
84:
85: /* UVSCOM_SET_SPEED parameters */
86: #define UVSCOM_SPEED_150BPS 0x00
87: #define UVSCOM_SPEED_300BPS 0x01
88: #define UVSCOM_SPEED_600BPS 0x02
89: #define UVSCOM_SPEED_1200BPS 0x03
90: #define UVSCOM_SPEED_2400BPS 0x04
91: #define UVSCOM_SPEED_4800BPS 0x05
92: #define UVSCOM_SPEED_9600BPS 0x06
93: #define UVSCOM_SPEED_19200BPS 0x07
94: #define UVSCOM_SPEED_38400BPS 0x08
95: #define UVSCOM_SPEED_57600BPS 0x09
96: #define UVSCOM_SPEED_115200BPS 0x0a
97:
98: /* UVSCOM_LINE_CTL parameters */
99: #define UVSCOM_BREAK 0x40
100: #define UVSCOM_RTS 0x02
101: #define UVSCOM_DTR 0x01
102: #define UVSCOM_LINE_INIT 0x08
103:
104: /* UVSCOM_SET_PARAM parameters */
105: #define UVSCOM_DATA_MASK 0x03
106: #define UVSCOM_DATA_BIT_8 0x03
107: #define UVSCOM_DATA_BIT_7 0x02
108: #define UVSCOM_DATA_BIT_6 0x01
109: #define UVSCOM_DATA_BIT_5 0x00
110:
111: #define UVSCOM_STOP_MASK 0x04
112: #define UVSCOM_STOP_BIT_2 0x04
113: #define UVSCOM_STOP_BIT_1 0x00
114:
115: #define UVSCOM_PARITY_MASK 0x18
116: #define UVSCOM_PARITY_EVEN 0x18
117: #if 0
118: #define UVSCOM_PARITY_UNK 0x10
119: #endif
120: #define UVSCOM_PARITY_ODD 0x08
121: #define UVSCOM_PARITY_NONE 0x00
122:
123: /* Status bits */
124: #define UVSCOM_TXRDY 0x04
125: #define UVSCOM_RXRDY 0x01
126:
127: #define UVSCOM_DCD 0x08
128: #define UVSCOM_NOCARD 0x04
129: #define UVSCOM_DSR 0x02
130: #define UVSCOM_CTS 0x01
131: #define UVSCOM_USTAT_MASK (UVSCOM_NOCARD | UVSCOM_DSR | UVSCOM_CTS)
132:
133: struct uvscom_softc {
134: struct device sc_dev; /* base device */
135: usbd_device_handle sc_udev; /* USB device */
136: usbd_interface_handle sc_iface; /* interface */
137: int sc_iface_number;/* interface number */
138:
139: usbd_interface_handle sc_intr_iface; /* interrupt interface */
140: int sc_intr_number; /* interrupt number */
141: usbd_pipe_handle sc_intr_pipe; /* interrupt pipe */
142: u_char *sc_intr_buf; /* interrupt buffer */
143: int sc_isize;
144:
145: u_char sc_dtr; /* current DTR state */
146: u_char sc_rts; /* current RTS state */
147:
148: u_char sc_lsr; /* Local status register */
149: u_char sc_msr; /* uvscom status register */
150:
151: uint16_t sc_lcr; /* Line control */
152: u_char sc_usr; /* unit status */
153:
154: struct device *sc_subdev; /* ucom device */
155: u_char sc_dying; /* disconnecting */
156: };
157:
158: /*
159: * These are the maximum number of bytes transferred per frame.
160: * The output buffer size cannot be increased due to the size encoding.
161: */
162: #define UVSCOMIBUFSIZE 512
163: #define UVSCOMOBUFSIZE 64
164:
165: usbd_status uvscom_readstat(struct uvscom_softc *);
166: usbd_status uvscom_shutdown(struct uvscom_softc *);
167: usbd_status uvscom_reset(struct uvscom_softc *);
168: usbd_status uvscom_set_line_coding(struct uvscom_softc *,
169: uint16_t, uint16_t);
170: usbd_status uvscom_set_line(struct uvscom_softc *, uint16_t);
171: usbd_status uvscom_set_crtscts(struct uvscom_softc *);
172: void uvscom_get_status(void *, int, u_char *, u_char *);
173: void uvscom_dtr(struct uvscom_softc *, int);
174: void uvscom_rts(struct uvscom_softc *, int);
175: void uvscom_break(struct uvscom_softc *, int);
176:
177: void uvscom_set(void *, int, int, int);
178: void uvscom_intr(usbd_xfer_handle, usbd_private_handle, usbd_status);
179: int uvscom_param(void *, int, struct termios *);
180: int uvscom_open(void *, int);
181: void uvscom_close(void *, int);
182:
183: struct ucom_methods uvscom_methods = {
184: uvscom_get_status,
185: uvscom_set,
186: uvscom_param,
187: NULL, /* uvscom_ioctl, TODO */
188: uvscom_open,
189: uvscom_close,
190: NULL,
191: NULL
192: };
193:
194: static const struct usb_devno uvscom_devs [] = {
195: /* SUNTAC U-Cable type A3 */
196: { USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_AS64LX },
197: /* SUNTAC U-Cable type A4 */
198: { USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_AS144L4 },
199: /* SUNTAC U-Cable type D2 */
200: { USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_DS96L },
201: /* SUNTAC U-Cable type P1 */
202: { USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_PS64P1 },
203: /* SUNTAC Slipper U */
204: { USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_VS10U },
205: /* SUNTAC Ir-Trinity */
206: { USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_IS96U },
207: };
208: #define uvscom_lookup(v, p) usb_lookup(uvscom_devs, v, p)
209:
210: int uvscom_match(struct device *, void *, void *);
211: void uvscom_attach(struct device *, struct device *, void *);
212: int uvscom_detach(struct device *, int);
213: int uvscom_activate(struct device *, enum devact);
214:
215: struct cfdriver uvscom_cd = {
216: NULL, "uvscom", DV_DULL
217: };
218:
219: const struct cfattach uvscom_ca = {
220: sizeof(struct uvscom_softc),
221: uvscom_match,
222: uvscom_attach,
223: uvscom_detach,
224: uvscom_activate,
225: };
226:
227: int
228: uvscom_match(struct device *parent, void *match, void *aux)
229: {
230: struct usb_attach_arg *uaa = aux;
231:
232: if (uaa->iface != NULL)
233: return (UMATCH_NONE);
234:
235: return (uvscom_lookup(uaa->vendor, uaa->product) != NULL ?
236: UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
237: }
238:
239: void
240: uvscom_attach(struct device *parent, struct device *self, void *aux)
241: {
242: struct uvscom_softc *sc = (struct uvscom_softc *)self;
243: struct usb_attach_arg *uaa = aux;
244: usbd_device_handle dev = uaa->device;
245: usb_config_descriptor_t *cdesc;
246: usb_interface_descriptor_t *id;
247: usb_endpoint_descriptor_t *ed;
248: char *devinfop;
249: const char *devname = sc->sc_dev.dv_xname;
250: usbd_status err;
251: int i;
252: struct ucom_attach_args uca;
253:
254: devinfop = usbd_devinfo_alloc(dev, 0);
255: printf("\n%s: %s\n", devname, devinfop);
256: usbd_devinfo_free(devinfop);
257:
258: sc->sc_udev = dev;
259:
260: DPRINTF(("uvscom attach: sc = %p\n", sc));
261:
262: /* initialize endpoints */
263: uca.bulkin = uca.bulkout = -1;
264: sc->sc_intr_number = -1;
265: sc->sc_intr_pipe = NULL;
266:
267: /* Move the device into the configured state. */
268: err = usbd_set_config_index(dev, UVSCOM_CONFIG_INDEX, 1);
269: if (err) {
270: printf("%s: failed to set configuration, err=%s\n",
271: devname, usbd_errstr(err));
272: sc->sc_dying = 1;
273: return;
274: }
275:
276: /* get the config descriptor */
277: cdesc = usbd_get_config_descriptor(sc->sc_udev);
278:
279: if (cdesc == NULL) {
280: printf("%s: failed to get configuration descriptor\n",
281: sc->sc_dev.dv_xname);
282: sc->sc_dying = 1;
283: return;
284: }
285:
286: /* get the common interface */
287: err = usbd_device2interface_handle(dev, UVSCOM_IFACE_INDEX,
288: &sc->sc_iface);
289: if (err) {
290: printf("%s: failed to get interface, err=%s\n",
291: devname, usbd_errstr(err));
292: sc->sc_dying = 1;
293: return;
294: }
295:
296: id = usbd_get_interface_descriptor(sc->sc_iface);
297: sc->sc_iface_number = id->bInterfaceNumber;
298:
299: /* Find endpoints */
300: for (i = 0; i < id->bNumEndpoints; i++) {
301: ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
302: if (ed == NULL) {
303: printf("%s: no endpoint descriptor for %d\n",
304: sc->sc_dev.dv_xname, i);
305: sc->sc_dying = 1;
306: return;
307: }
308:
309: if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
310: UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
311: uca.bulkin = ed->bEndpointAddress;
312: } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
313: UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
314: uca.bulkout = ed->bEndpointAddress;
315: } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
316: UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
317: sc->sc_intr_number = ed->bEndpointAddress;
318: sc->sc_isize = UGETW(ed->wMaxPacketSize);
319: }
320: }
321:
322: if (uca.bulkin == -1) {
323: printf("%s: Could not find data bulk in\n",
324: sc->sc_dev.dv_xname);
325: sc->sc_dying = 1;
326: return;
327: }
328: if (uca.bulkout == -1) {
329: printf("%s: Could not find data bulk out\n",
330: sc->sc_dev.dv_xname);
331: sc->sc_dying = 1;
332: return;
333: }
334: if (sc->sc_intr_number == -1) {
335: printf("%s: Could not find interrupt in\n",
336: sc->sc_dev.dv_xname);
337: sc->sc_dying = 1;
338: return;
339: }
340:
341: sc->sc_dtr = sc->sc_rts = 0;
342: sc->sc_lcr = UVSCOM_LINE_INIT;
343:
344: uca.portno = UCOM_UNK_PORTNO;
345: /* bulkin, bulkout set above */
346: uca.ibufsize = UVSCOMIBUFSIZE;
347: uca.obufsize = UVSCOMOBUFSIZE;
348: uca.ibufsizepad = UVSCOMIBUFSIZE;
349: uca.opkthdrlen = 0;
350: uca.device = dev;
351: uca.iface = sc->sc_iface;
352: uca.methods = &uvscom_methods;
353: uca.arg = sc;
354: uca.info = NULL;
355:
356: err = uvscom_reset(sc);
357:
358: if (err) {
359: printf("%s: reset failed, %s\n", sc->sc_dev.dv_xname,
360: usbd_errstr(err));
361: sc->sc_dying = 1;
362: return;
363: }
364:
365: DPRINTF(("uvscom: in = 0x%x out = 0x%x intr = 0x%x\n",
366: ucom->sc_bulkin_no, ucom->sc_bulkout_no, sc->sc_intr_number));
367:
368: usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
369: &sc->sc_dev);
370:
371: DPRINTF(("uplcom: in=0x%x out=0x%x intr=0x%x\n",
372: uca.bulkin, uca.bulkout, sc->sc_intr_number ));
373: sc->sc_subdev = config_found_sm(self, &uca, ucomprint, ucomsubmatch);
374: }
375:
376: int
377: uvscom_detach(struct device *self, int flags)
378: {
379: struct uvscom_softc *sc = (struct uvscom_softc *)self;
380: int rv = 0;
381:
382: DPRINTF(("uvscom_detach: sc = %p\n", sc));
383:
384: sc->sc_dying = 1;
385:
386: if (sc->sc_intr_pipe != NULL) {
387: usbd_abort_pipe(sc->sc_intr_pipe);
388: usbd_close_pipe(sc->sc_intr_pipe);
389: free(sc->sc_intr_buf, M_USBDEV);
390: sc->sc_intr_pipe = NULL;
391: }
392:
393: sc->sc_dying = 1;
394: if (sc->sc_subdev != NULL) {
395: rv = config_detach(sc->sc_subdev, flags);
396: sc->sc_subdev = NULL;
397: }
398:
399: usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
400: &sc->sc_dev);
401:
402: return (rv);
403: }
404:
405: int
406: uvscom_activate(struct device *self, enum devact act)
407: {
408: struct uvscom_softc *sc = (struct uvscom_softc *)self;
409: int rv = 0;
410:
411: switch (act) {
412: case DVACT_ACTIVATE:
413: break;
414:
415: case DVACT_DEACTIVATE:
416: if (sc->sc_subdev != NULL)
417: rv = config_deactivate(sc->sc_subdev);
418: sc->sc_dying = 1;
419: break;
420: }
421: return (rv);
422: }
423:
424: usbd_status
425: uvscom_readstat(struct uvscom_softc *sc)
426: {
427: usb_device_request_t req;
428: usbd_status err;
429: uint16_t r;
430:
431: DPRINTF(("%s: send readstat\n", sc->sc_dev.dv_xname));
432:
433: req.bmRequestType = UT_READ_VENDOR_DEVICE;
434: req.bRequest = UVSCOM_READ_STATUS;
435: USETW(req.wValue, 0);
436: USETW(req.wIndex, 0);
437: USETW(req.wLength, 2);
438:
439: err = usbd_do_request(sc->sc_udev, &req, &r);
440: if (err) {
441: printf("%s: uvscom_readstat: %s\n",
442: sc->sc_dev.dv_xname, usbd_errstr(err));
443: return (err);
444: }
445:
446: DPRINTF(("%s: uvscom_readstat: r = %d\n",
447: sc->sc_dev.dv_xname, r));
448:
449: return (USBD_NORMAL_COMPLETION);
450: }
451:
452: usbd_status
453: uvscom_shutdown(struct uvscom_softc *sc)
454: {
455: usb_device_request_t req;
456: usbd_status err;
457:
458: DPRINTF(("%s: send shutdown\n", sc->sc_dev.dv_xname));
459:
460: req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
461: req.bRequest = UVSCOM_SHUTDOWN;
462: USETW(req.wValue, 0);
463: USETW(req.wIndex, 0);
464: USETW(req.wLength, 0);
465:
466: err = usbd_do_request(sc->sc_udev, &req, NULL);
467: if (err) {
468: printf("%s: uvscom_shutdown: %s\n",
469: sc->sc_dev.dv_xname, usbd_errstr(err));
470: return (err);
471: }
472:
473: return (USBD_NORMAL_COMPLETION);
474: }
475:
476: usbd_status
477: uvscom_reset(struct uvscom_softc *sc)
478: {
479: DPRINTF(("%s: uvscom_reset\n", sc->sc_dev.dv_xname));
480:
481: return (USBD_NORMAL_COMPLETION);
482: }
483:
484: usbd_status
485: uvscom_set_crtscts(struct uvscom_softc *sc)
486: {
487: DPRINTF(("%s: uvscom_set_crtscts\n", sc->sc_dev.dv_xname));
488:
489: return (USBD_NORMAL_COMPLETION);
490: }
491:
492: usbd_status
493: uvscom_set_line(struct uvscom_softc *sc, uint16_t line)
494: {
495: usb_device_request_t req;
496: usbd_status err;
497:
498: DPRINTF(("%s: uvscom_set_line: %04x\n",
499: sc->sc_dev.dv_xname, line));
500:
501: req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
502: req.bRequest = UVSCOM_LINE_CTL;
503: USETW(req.wValue, line);
504: USETW(req.wIndex, 0);
505: USETW(req.wLength, 0);
506:
507: err = usbd_do_request(sc->sc_udev, &req, NULL);
508: if (err) {
509: printf("%s: uvscom_set_line: %s\n",
510: sc->sc_dev.dv_xname, usbd_errstr(err));
511: return (err);
512: }
513:
514: return (USBD_NORMAL_COMPLETION);
515: }
516:
517: usbd_status
518: uvscom_set_line_coding(struct uvscom_softc *sc, uint16_t lsp, uint16_t ls)
519: {
520: usb_device_request_t req;
521: usbd_status err;
522:
523: DPRINTF(("%s: uvscom_set_line_coding: %02x %02x\n",
524: sc->sc_dev.dv_xname, lsp, ls));
525:
526: req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
527: req.bRequest = UVSCOM_SET_SPEED;
528: USETW(req.wValue, lsp);
529: USETW(req.wIndex, 0);
530: USETW(req.wLength, 0);
531:
532: err = usbd_do_request(sc->sc_udev, &req, NULL);
533: if (err) {
534: printf("%s: uvscom_set_line_coding: %s\n",
535: sc->sc_dev.dv_xname, usbd_errstr(err));
536: return (err);
537: }
538:
539: req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
540: req.bRequest = UVSCOM_SET_PARAM;
541: USETW(req.wValue, ls);
542: USETW(req.wIndex, 0);
543: USETW(req.wLength, 0);
544:
545: err = usbd_do_request(sc->sc_udev, &req, NULL);
546: if (err) {
547: printf("%s: uvscom_set_line_coding: %s\n",
548: sc->sc_dev.dv_xname, usbd_errstr(err));
549: return (err);
550: }
551:
552: return (USBD_NORMAL_COMPLETION);
553: }
554:
555: void
556: uvscom_dtr(struct uvscom_softc *sc, int onoff)
557: {
558: DPRINTF(("%s: uvscom_dtr: onoff = %d\n",
559: sc->sc_dev.dv_xname, onoff));
560:
561: if (sc->sc_dtr == onoff)
562: return; /* no change */
563:
564: sc->sc_dtr = onoff;
565:
566: if (onoff)
567: SET(sc->sc_lcr, UVSCOM_DTR);
568: else
569: CLR(sc->sc_lcr, UVSCOM_DTR);
570:
571: uvscom_set_line(sc, sc->sc_lcr);
572: }
573:
574: void
575: uvscom_rts(struct uvscom_softc *sc, int onoff)
576: {
577: DPRINTF(("%s: uvscom_rts: onoff = %d\n",
578: sc->sc_dev.dv_xname, onoff));
579:
580: if (sc->sc_rts == onoff)
581: return; /* no change */
582:
583: sc->sc_rts = onoff;
584:
585: if (onoff)
586: SET(sc->sc_lcr, UVSCOM_RTS);
587: else
588: CLR(sc->sc_lcr, UVSCOM_RTS);
589:
590: uvscom_set_line(sc, sc->sc_lcr);
591: }
592:
593: void
594: uvscom_break(struct uvscom_softc *sc, int onoff)
595: {
596: DPRINTF(("%s: uvscom_break: onoff = %d\n",
597: sc->sc_dev.dv_xname, onoff));
598:
599: if (onoff)
600: uvscom_set_line(sc, SET(sc->sc_lcr, UVSCOM_BREAK));
601: }
602:
603: void
604: uvscom_set(void *addr, int portno, int reg, int onoff)
605: {
606: struct uvscom_softc *sc = addr;
607:
608: switch (reg) {
609: case UCOM_SET_DTR:
610: uvscom_dtr(sc, onoff);
611: break;
612: case UCOM_SET_RTS:
613: uvscom_rts(sc, onoff);
614: break;
615: case UCOM_SET_BREAK:
616: uvscom_break(sc, onoff);
617: break;
618: default:
619: break;
620: }
621: }
622:
623: int
624: uvscom_param(void *addr, int portno, struct termios *t)
625: {
626: struct uvscom_softc *sc = addr;
627: usbd_status err;
628: uint16_t lsp;
629: uint16_t ls;
630:
631: DPRINTF(("%s: uvscom_param: sc = %p\n",
632: sc->sc_dev.dv_xname, sc));
633:
634: ls = 0;
635:
636: switch (t->c_ospeed) {
637: case B150:
638: lsp = UVSCOM_SPEED_150BPS;
639: break;
640: case B300:
641: lsp = UVSCOM_SPEED_300BPS;
642: break;
643: case B600:
644: lsp = UVSCOM_SPEED_600BPS;
645: break;
646: case B1200:
647: lsp = UVSCOM_SPEED_1200BPS;
648: break;
649: case B2400:
650: lsp = UVSCOM_SPEED_2400BPS;
651: break;
652: case B4800:
653: lsp = UVSCOM_SPEED_4800BPS;
654: break;
655: case B9600:
656: lsp = UVSCOM_SPEED_9600BPS;
657: break;
658: case B19200:
659: lsp = UVSCOM_SPEED_19200BPS;
660: break;
661: case B38400:
662: lsp = UVSCOM_SPEED_38400BPS;
663: break;
664: case B57600:
665: lsp = UVSCOM_SPEED_57600BPS;
666: break;
667: case B115200:
668: lsp = UVSCOM_SPEED_115200BPS;
669: break;
670: default:
671: return (EIO);
672: }
673:
674: if (ISSET(t->c_cflag, CSTOPB))
675: SET(ls, UVSCOM_STOP_BIT_2);
676: else
677: SET(ls, UVSCOM_STOP_BIT_1);
678:
679: if (ISSET(t->c_cflag, PARENB)) {
680: if (ISSET(t->c_cflag, PARODD))
681: SET(ls, UVSCOM_PARITY_ODD);
682: else
683: SET(ls, UVSCOM_PARITY_EVEN);
684: } else
685: SET(ls, UVSCOM_PARITY_NONE);
686:
687: switch (ISSET(t->c_cflag, CSIZE)) {
688: case CS5:
689: SET(ls, UVSCOM_DATA_BIT_5);
690: break;
691: case CS6:
692: SET(ls, UVSCOM_DATA_BIT_6);
693: break;
694: case CS7:
695: SET(ls, UVSCOM_DATA_BIT_7);
696: break;
697: case CS8:
698: SET(ls, UVSCOM_DATA_BIT_8);
699: break;
700: default:
701: return (EIO);
702: }
703:
704: err = uvscom_set_line_coding(sc, lsp, ls);
705: if (err)
706: return (EIO);
707:
708: if (ISSET(t->c_cflag, CRTSCTS)) {
709: err = uvscom_set_crtscts(sc);
710: if (err)
711: return (EIO);
712: }
713:
714: return (0);
715: }
716:
717: int
718: uvscom_open(void *addr, int portno)
719: {
720: struct uvscom_softc *sc = addr;
721: int err;
722: int i;
723:
724: if (sc->sc_dying)
725: return (EIO);
726:
727: DPRINTF(("uvscom_open: sc = %p\n", sc));
728:
729: if (sc->sc_intr_number != -1 && sc->sc_intr_pipe == NULL) {
730: DPRINTF(("uvscom_open: open interrupt pipe.\n"));
731:
732: sc->sc_usr = 0; /* clear unit status */
733:
734: err = uvscom_readstat(sc);
735: if (err) {
736: DPRINTF(("%s: uvscom_open: readstat faild\n",
737: sc->sc_dev.dv_xname));
738: return (EIO);
739: }
740:
741: sc->sc_intr_buf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK);
742: err = usbd_open_pipe_intr(sc->sc_iface,
743: sc->sc_intr_number,
744: USBD_SHORT_XFER_OK,
745: &sc->sc_intr_pipe,
746: sc,
747: sc->sc_intr_buf,
748: sc->sc_isize,
749: uvscom_intr,
750: UVSCOM_INTR_INTERVAL);
751: if (err) {
752: printf("%s: cannot open interrupt pipe (addr %d)\n",
753: sc->sc_dev.dv_xname,
754: sc->sc_intr_number);
755: return (EIO);
756: }
757: } else {
758: DPRINTF(("uvscom_open: did not open interrupt pipe.\n"));
759: }
760:
761: if ((sc->sc_usr & UVSCOM_USTAT_MASK) == 0) {
762: /* unit is not ready */
763:
764: for (i = UVSCOM_UNIT_WAIT; i > 0; --i) {
765: tsleep(&err, TTIPRI, "uvsop", hz); /* XXX */
766: if (ISSET(sc->sc_usr, UVSCOM_USTAT_MASK))
767: break;
768: }
769: if (i == 0) {
770: DPRINTF(("%s: unit is not ready\n",
771: sc->sc_dev.dv_xname));
772: return (EIO);
773: }
774:
775: /* check PC card was inserted */
776: if (ISSET(sc->sc_usr, UVSCOM_NOCARD)) {
777: DPRINTF(("%s: no card\n",
778: sc->sc_dev.dv_xname));
779: return (EIO);
780: }
781: }
782:
783: return (0);
784: }
785:
786: void
787: uvscom_close(void *addr, int portno)
788: {
789: struct uvscom_softc *sc = addr;
790: int err;
791:
792: if (sc->sc_dying)
793: return;
794:
795: DPRINTF(("uvscom_close: close\n"));
796:
797: uvscom_shutdown(sc);
798:
799: if (sc->sc_intr_pipe != NULL) {
800: err = usbd_abort_pipe(sc->sc_intr_pipe);
801: if (err)
802: printf("%s: abort interrupt pipe failed: %s\n",
803: sc->sc_dev.dv_xname,
804: usbd_errstr(err));
805: err = usbd_close_pipe(sc->sc_intr_pipe);
806: if (err)
807: printf("%s: close interrupt pipe failed: %s\n",
808: sc->sc_dev.dv_xname,
809: usbd_errstr(err));
810: free(sc->sc_intr_buf, M_USBDEV);
811: sc->sc_intr_pipe = NULL;
812: }
813: }
814:
815: void
816: uvscom_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
817: {
818: struct uvscom_softc *sc = priv;
819: u_char *buf = sc->sc_intr_buf;
820: u_char pstatus;
821:
822: if (sc->sc_dying)
823: return;
824:
825: if (status != USBD_NORMAL_COMPLETION) {
826: if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
827: return;
828:
829: printf("%s: uvscom_intr: abnormal status: %s\n",
830: sc->sc_dev.dv_xname,
831: usbd_errstr(status));
832: usbd_clear_endpoint_stall_async(sc->sc_intr_pipe);
833: return;
834: }
835:
836: DPRINTFN(2, ("%s: uvscom status = %02x %02x\n",
837: sc->sc_dev.dv_xname, buf[0], buf[1]));
838:
839: sc->sc_lsr = sc->sc_msr = 0;
840: sc->sc_usr = buf[1];
841:
842: pstatus = buf[0];
843: if (ISSET(pstatus, UVSCOM_TXRDY))
844: SET(sc->sc_lsr, ULSR_TXRDY);
845: if (ISSET(pstatus, UVSCOM_RXRDY))
846: SET(sc->sc_lsr, ULSR_RXRDY);
847:
848: pstatus = buf[1];
849: if (ISSET(pstatus, UVSCOM_CTS))
850: SET(sc->sc_msr, UMSR_CTS);
851: if (ISSET(pstatus, UVSCOM_DSR))
852: SET(sc->sc_msr, UMSR_DSR);
853: if (ISSET(pstatus, UVSCOM_DCD))
854: SET(sc->sc_msr, UMSR_DCD);
855:
856: ucom_status_change((struct ucom_softc *) sc->sc_subdev);
857: }
858:
859: void
860: uvscom_get_status(void *addr, int portno, u_char *lsr, u_char *msr)
861: {
862: struct uvscom_softc *sc = addr;
863:
864: if (lsr != NULL)
865: *lsr = sc->sc_lsr;
866: if (msr != NULL)
867: *msr = sc->sc_msr;
868: }
CVSweb