This source file includes following definitions.
- uvscom_match
- uvscom_attach
- uvscom_detach
- uvscom_activate
- uvscom_readstat
- uvscom_shutdown
- uvscom_reset
- uvscom_set_crtscts
- uvscom_set_line
- uvscom_set_line_coding
- uvscom_dtr
- uvscom_rts
- uvscom_break
- uvscom_set
- uvscom_param
- uvscom_open
- uvscom_close
- uvscom_intr
- uvscom_get_status
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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
75
76 #define UVSCOM_UNIT_WAIT 5
77
78
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
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
99 #define UVSCOM_BREAK 0x40
100 #define UVSCOM_RTS 0x02
101 #define UVSCOM_DTR 0x01
102 #define UVSCOM_LINE_INIT 0x08
103
104
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
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;
135 usbd_device_handle sc_udev;
136 usbd_interface_handle sc_iface;
137 int sc_iface_number;
138
139 usbd_interface_handle sc_intr_iface;
140 int sc_intr_number;
141 usbd_pipe_handle sc_intr_pipe;
142 u_char *sc_intr_buf;
143 int sc_isize;
144
145 u_char sc_dtr;
146 u_char sc_rts;
147
148 u_char sc_lsr;
149 u_char sc_msr;
150
151 uint16_t sc_lcr;
152 u_char sc_usr;
153
154 struct device *sc_subdev;
155 u_char sc_dying;
156 };
157
158
159
160
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,
188 uvscom_open,
189 uvscom_close,
190 NULL,
191 NULL
192 };
193
194 static const struct usb_devno uvscom_devs [] = {
195
196 { USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_AS64LX },
197
198 { USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_AS144L4 },
199
200 { USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_DS96L },
201
202 { USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_PS64P1 },
203
204 { USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_VS10U },
205
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
263 uca.bulkin = uca.bulkout = -1;
264 sc->sc_intr_number = -1;
265 sc->sc_intr_pipe = NULL;
266
267
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
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
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
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
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;
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;
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;
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
763
764 for (i = UVSCOM_UNIT_WAIT; i > 0; --i) {
765 tsleep(&err, TTIPRI, "uvsop", hz);
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
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 }