This source file includes following definitions.
- ucom_lock
- ucom_unlock
- ucom_match
- ucom_attach
- ucom_detach
- ucom_activate
- ucom_shutdown
- ucomopen
- ucomclose
- ucomread
- ucomwrite
- ucomtty
- ucomioctl
- ucom_do_ioctl
- tiocm_to_ucom
- ucom_to_tiocm
- ucom_break
- ucom_dtr
- ucom_rts
- ucom_status_change
- ucomparam
- ucom_hwiflow
- ucomstart
- ucomstop
- ucomwritecb
- ucomstartread
- ucomreadcb
- ucom_cleanup
- ucomprint
- ucomsubmatch
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
39
40
41
42
43
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/kernel.h>
47 #include <sys/rwlock.h>
48 #include <sys/ioctl.h>
49 #include <sys/conf.h>
50 #include <sys/tty.h>
51 #include <sys/file.h>
52 #include <sys/selinfo.h>
53 #include <sys/proc.h>
54 #include <sys/vnode.h>
55 #include <sys/device.h>
56 #include <sys/poll.h>
57
58 #include <dev/usb/usb.h>
59
60 #include <dev/usb/usbdi.h>
61 #include <dev/usb/usbdi_util.h>
62 #include <dev/usb/uhidev.h>
63 #include <dev/usb/usbdevs.h>
64 #include <dev/usb/usb_quirks.h>
65
66 #include <dev/usb/ucomvar.h>
67
68 #include "ucom.h"
69
70 #if NUCOM > 0
71
72 #ifdef UCOM_DEBUG
73 #define DPRINTFN(n, x) do { if (ucomdebug > (n)) printf x; } while (0)
74 int ucomdebug = 0;
75 #else
76 #define DPRINTFN(n, x)
77 #endif
78 #define DPRINTF(x) DPRINTFN(0, x)
79
80 #define UCOMUNIT_MASK 0x7f
81 #define UCOMCUA_MASK 0x80
82
83 #define LINESW(tp, func) (linesw[(tp)->t_line].func)
84
85 #define UCOMUNIT(x) (minor(x) & UCOMUNIT_MASK)
86 #define UCOMCUA(x) (minor(x) & UCOMCUA_MASK)
87
88 struct ucom_softc {
89 struct device sc_dev;
90
91 usbd_device_handle sc_udev;
92 struct uhidev_softc *sc_uhidev;
93
94 usbd_interface_handle sc_iface;
95
96 int sc_bulkin_no;
97 usbd_pipe_handle sc_bulkin_pipe;
98 usbd_xfer_handle sc_ixfer;
99 u_char *sc_ibuf;
100 u_int sc_ibufsize;
101 u_int sc_ibufsizepad;
102
103 int sc_bulkout_no;
104 usbd_pipe_handle sc_bulkout_pipe;
105 usbd_xfer_handle sc_oxfer;
106 u_char *sc_obuf;
107 u_int sc_obufsize;
108 u_int sc_opkthdrlen;
109
110
111 usbd_pipe_handle sc_ipipe;
112 usbd_pipe_handle sc_opipe;
113
114 struct ucom_methods *sc_methods;
115 void *sc_parent;
116 int sc_portno;
117
118 struct tty *sc_tty;
119 u_char sc_lsr;
120 u_char sc_msr;
121 u_char sc_mcr;
122 u_char sc_tx_stopped;
123 int sc_swflags;
124
125 u_char sc_cua;
126
127 struct rwlock sc_lock;
128 int sc_open;
129 int sc_refcnt;
130 u_char sc_dying;
131 };
132
133 void ucom_cleanup(struct ucom_softc *);
134 void ucom_hwiflow(struct ucom_softc *);
135 int ucomparam(struct tty *, struct termios *);
136 void ucomstart(struct tty *);
137 void ucom_shutdown(struct ucom_softc *);
138 int ucom_do_ioctl(struct ucom_softc *, u_long, caddr_t,
139 int, struct proc *);
140 void ucom_dtr(struct ucom_softc *, int);
141 void ucom_rts(struct ucom_softc *, int);
142 void ucom_break(struct ucom_softc *, int);
143 usbd_status ucomstartread(struct ucom_softc *);
144 void ucomreadcb(usbd_xfer_handle, usbd_private_handle, usbd_status);
145 void ucomwritecb(usbd_xfer_handle, usbd_private_handle, usbd_status);
146 void tiocm_to_ucom(struct ucom_softc *, u_long, int);
147 int ucom_to_tiocm(struct ucom_softc *);
148 void ucom_lock(struct ucom_softc *);
149 void ucom_unlock(struct ucom_softc *);
150
151 int ucom_match(struct device *, void *, void *);
152 void ucom_attach(struct device *, struct device *, void *);
153 int ucom_detach(struct device *, int);
154 int ucom_activate(struct device *, enum devact);
155
156 struct cfdriver ucom_cd = {
157 NULL, "ucom", DV_DULL
158 };
159
160 const struct cfattach ucom_ca = {
161 sizeof(struct ucom_softc),
162 ucom_match,
163 ucom_attach,
164 ucom_detach,
165 ucom_activate,
166 };
167
168 void
169 ucom_lock(struct ucom_softc *sc)
170 {
171 sc->sc_refcnt++;
172 rw_enter_write(&sc->sc_lock);
173 }
174
175 void
176 ucom_unlock(struct ucom_softc *sc)
177 {
178 rw_exit_write(&sc->sc_lock);
179 if (--sc->sc_refcnt < 0)
180 usb_detach_wakeup(&sc->sc_dev);
181 }
182
183 int
184 ucom_match(struct device *parent, void *match, void *aux)
185 {
186 return (1);
187 }
188
189 void
190 ucom_attach(struct device *parent, struct device *self, void *aux)
191 {
192 struct ucom_softc *sc = (struct ucom_softc *)self;
193 struct ucom_attach_args *uca = aux;
194 struct tty *tp;
195
196 if (uca->info != NULL)
197 printf(", %s", uca->info);
198 printf("\n");
199
200 sc->sc_udev = uca->device;
201 sc->sc_iface = uca->iface;
202 sc->sc_bulkout_no = uca->bulkout;
203 sc->sc_bulkin_no = uca->bulkin;
204 sc->sc_uhidev = uca->uhidev;
205 sc->sc_ibufsize = uca->ibufsize;
206 sc->sc_ibufsizepad = uca->ibufsizepad;
207 sc->sc_obufsize = uca->obufsize;
208 sc->sc_opkthdrlen = uca->opkthdrlen;
209 sc->sc_methods = uca->methods;
210 sc->sc_parent = uca->arg;
211 sc->sc_portno = uca->portno;
212
213 tp = ttymalloc();
214 tp->t_oproc = ucomstart;
215 tp->t_param = ucomparam;
216 sc->sc_tty = tp;
217 sc->sc_cua = 0;
218
219 rw_init(&sc->sc_lock, "ucomlk");
220
221 sc->sc_open = 0;
222 }
223
224 int
225 ucom_detach(struct device *self, int flags)
226 {
227 struct ucom_softc *sc = (struct ucom_softc *)self;
228 struct tty *tp = sc->sc_tty;
229 int maj, mn;
230 int s;
231
232 DPRINTF(("ucom_detach: sc=%p flags=%d tp=%p, pipe=%d,%d\n",
233 sc, flags, tp, sc->sc_bulkin_no, sc->sc_bulkout_no));
234
235 sc->sc_dying = 1;
236
237 if (sc->sc_bulkin_pipe != NULL)
238 usbd_abort_pipe(sc->sc_bulkin_pipe);
239 if (sc->sc_bulkout_pipe != NULL)
240 usbd_abort_pipe(sc->sc_bulkout_pipe);
241
242 s = splusb();
243 if (--sc->sc_refcnt >= 0) {
244
245 if (tp != NULL) {
246 CLR(tp->t_state, TS_CARR_ON);
247 CLR(tp->t_cflag, CLOCAL | MDMBUF);
248 ttyflush(tp, FREAD|FWRITE);
249 }
250
251 usb_detach_wait(&sc->sc_dev);
252 }
253 splx(s);
254
255
256 for (maj = 0; maj < nchrdev; maj++)
257 if (cdevsw[maj].d_open == ucomopen)
258 break;
259
260
261 mn = self->dv_unit;
262 DPRINTF(("ucom_detach: maj=%d mn=%d\n", maj, mn));
263 vdevgone(maj, mn, mn, VCHR);
264 vdevgone(maj, mn | UCOMCUA_MASK, mn | UCOMCUA_MASK, VCHR);
265
266
267 if (tp != NULL) {
268 ttyfree(tp);
269 sc->sc_tty = NULL;
270 }
271
272 return (0);
273 }
274
275 int
276 ucom_activate(struct device *self, enum devact act)
277 {
278 struct ucom_softc *sc = (struct ucom_softc *)self;
279
280 DPRINTFN(5,("ucom_activate: %d\n", act));
281
282 switch (act) {
283 case DVACT_ACTIVATE:
284 break;
285
286 case DVACT_DEACTIVATE:
287 sc->sc_dying = 1;
288 break;
289 }
290 return (0);
291 }
292
293 void
294 ucom_shutdown(struct ucom_softc *sc)
295 {
296 struct tty *tp = sc->sc_tty;
297
298 DPRINTF(("ucom_shutdown\n"));
299
300
301
302
303 if (ISSET(tp->t_cflag, HUPCL)) {
304 ucom_dtr(sc, 0);
305 (void)tsleep(sc, TTIPRI, ttclos, hz);
306 }
307 }
308
309 int
310 ucomopen(dev_t dev, int flag, int mode, struct proc *p)
311 {
312 int unit = UCOMUNIT(dev);
313 usbd_status err;
314 struct ucom_softc *sc;
315 struct tty *tp;
316 struct termios t;
317 int s;
318 int error;
319
320 if (unit >= ucom_cd.cd_ndevs)
321 return (ENXIO);
322 sc = ucom_cd.cd_devs[unit];
323 if (sc == NULL)
324 return (ENXIO);
325
326 if (sc->sc_dying)
327 return (EIO);
328
329 if (ISSET(sc->sc_dev.dv_flags, DVF_ACTIVE) == 0)
330 return (ENXIO);
331
332
333 ucom_lock(sc);
334 if (sc->sc_open++ == 0) {
335 s = splusb();
336
337 DPRINTF(("ucomopen: open pipes in=%d out=%d\n",
338 sc->sc_bulkin_no, sc->sc_bulkout_no));
339 DPRINTF(("ucomopen: hid %p pipes in=%p out=%p\n",
340 sc->sc_uhidev, sc->sc_ipipe, sc->sc_opipe));
341
342 if (sc->sc_bulkin_no != -1) {
343
344
345 err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkin_no, 0,
346 &sc->sc_bulkin_pipe);
347 if (err) {
348 DPRINTF(("%s: open bulk out error (addr %d), err=%s\n",
349 sc->sc_dev.dv_xname, sc->sc_bulkin_no,
350 usbd_errstr(err)));
351 error = EIO;
352 goto fail_0;
353 }
354 err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkout_no,
355 USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe);
356 if (err) {
357 DPRINTF(("%s: open bulk in error (addr %d), err=%s\n",
358 sc->sc_dev.dv_xname, sc->sc_bulkout_no,
359 usbd_errstr(err)));
360 error = EIO;
361 goto fail_1;
362 }
363
364
365 sc->sc_ixfer = usbd_alloc_xfer(sc->sc_udev);
366 if (sc->sc_ixfer == NULL) {
367 error = ENOMEM;
368 goto fail_2;
369 }
370
371 sc->sc_ibuf = usbd_alloc_buffer(sc->sc_ixfer,
372 sc->sc_ibufsizepad);
373 if (sc->sc_ibuf == NULL) {
374 error = ENOMEM;
375 goto fail_2;
376 }
377
378 sc->sc_oxfer = usbd_alloc_xfer(sc->sc_udev);
379 if (sc->sc_oxfer == NULL) {
380 error = ENOMEM;
381 goto fail_3;
382 }
383 } else {
384
385
386
387
388 sc->sc_ipipe = sc->sc_uhidev->sc_ipipe;
389 sc->sc_ixfer = sc->sc_uhidev->sc_ixfer;
390 sc->sc_opipe = sc->sc_uhidev->sc_opipe;
391 sc->sc_oxfer = sc->sc_uhidev->sc_oxfer;
392 }
393
394 sc->sc_obuf = usbd_alloc_buffer(sc->sc_oxfer,
395 sc->sc_obufsize + sc->sc_opkthdrlen);
396 if (sc->sc_obuf == NULL) {
397 error = ENOMEM;
398 goto fail_4;
399 }
400
401 if (sc->sc_methods->ucom_open != NULL) {
402 error = sc->sc_methods->ucom_open(sc->sc_parent,
403 sc->sc_portno);
404 if (error) {
405 ucom_cleanup(sc);
406 splx(s);
407 ucom_unlock(sc);
408 return (error);
409 }
410 }
411
412 ucom_status_change(sc);
413
414 ucomstartread(sc);
415
416 splx(s);
417 }
418 ucom_unlock(sc);
419
420 s = spltty();
421 tp = sc->sc_tty;
422 splx(s);
423
424 DPRINTF(("ucomopen: unit=%d, tp=%p\n", unit, tp));
425
426 tp->t_dev = dev;
427 if (!ISSET(tp->t_state, TS_ISOPEN)) {
428 SET(tp->t_state, TS_WOPEN);
429 ttychars(tp);
430
431
432
433
434
435 t.c_ispeed = 0;
436 t.c_ospeed = TTYDEF_SPEED;
437 t.c_cflag = TTYDEF_CFLAG;
438 if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL))
439 SET(t.c_cflag, CLOCAL);
440 if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS))
441 SET(t.c_cflag, CRTSCTS);
442 if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF))
443 SET(t.c_cflag, MDMBUF);
444
445
446 tp->t_ospeed = 0;
447 (void) ucomparam(tp, &t);
448 tp->t_iflag = TTYDEF_IFLAG;
449 tp->t_oflag = TTYDEF_OFLAG;
450 tp->t_lflag = TTYDEF_LFLAG;
451
452 s = spltty();
453 ttsetwater(tp);
454
455
456
457
458
459
460
461
462 ucom_dtr(sc, 1);
463
464
465 ucom_hwiflow(sc);
466
467 if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR) || UCOMCUA(dev) ||
468 ISSET(sc->sc_msr, UMSR_DCD) || ISSET(tp->t_cflag, MDMBUF))
469 SET(tp->t_state, TS_CARR_ON);
470 else
471 CLR(tp->t_state, TS_CARR_ON);
472 } else if (ISSET(tp->t_state, TS_XCLUDE) && p->p_ucred->cr_uid != 0) {
473 error = EBUSY;
474 goto bad;
475 } else
476 s = spltty();
477
478 if (UCOMCUA(dev)) {
479 if (ISSET(tp->t_state, TS_ISOPEN)) {
480
481 error = EBUSY;
482 goto bad1;
483 }
484 sc->sc_cua = 1;
485 } else {
486
487 if (ISSET(flag, O_NONBLOCK)) {
488 if (sc->sc_cua) {
489 error = EBUSY;
490 goto bad1;
491 }
492 } else {
493 while (sc->sc_cua || (!ISSET(tp->t_cflag, CLOCAL) &&
494 !ISSET(tp->t_state, TS_CARR_ON))) {
495 SET(tp->t_state, TS_WOPEN);
496 error = ttysleep(tp, &tp->t_rawq,
497 TTIPRI | PCATCH, ttopen, 0);
498
499
500
501
502
503
504 if (error && ISSET(tp->t_state, TS_WOPEN)) {
505 CLR(tp->t_state, TS_WOPEN);
506 goto bad1;
507 }
508 }
509 }
510 }
511 splx(s);
512
513 error = ttyopen(UCOMUNIT(dev), tp);
514 if (error)
515 goto bad;
516
517 error = (*LINESW(tp, l_open))(dev, tp);
518 if (error)
519 goto bad;
520
521 return (0);
522
523 fail_4:
524 if (sc->sc_uhidev == NULL)
525 usbd_free_xfer(sc->sc_oxfer);
526 sc->sc_oxfer = NULL;
527 fail_3:
528 usbd_free_xfer(sc->sc_ixfer);
529 sc->sc_ixfer = NULL;
530 fail_2:
531 usbd_close_pipe(sc->sc_bulkout_pipe);
532 sc->sc_bulkout_pipe = NULL;
533 fail_1:
534 usbd_close_pipe(sc->sc_bulkin_pipe);
535 sc->sc_bulkin_pipe = NULL;
536 fail_0:
537 splx(s);
538 ucom_unlock(sc);
539 return (error);
540
541 bad1:
542 splx(s);
543 bad:
544 ucom_lock(sc);
545 ucom_cleanup(sc);
546 ucom_unlock(sc);
547
548 return (error);
549 }
550
551 int
552 ucomclose(dev_t dev, int flag, int mode, struct proc *p)
553 {
554 struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)];
555 struct tty *tp = sc->sc_tty;
556 int s;
557
558 if (!ISSET(tp->t_state, TS_ISOPEN))
559 return (0);
560
561 DPRINTF(("ucomclose: unit=%d\n", UCOMUNIT(dev)));
562 ucom_lock(sc);
563
564 (*LINESW(tp, l_close))(tp, flag);
565 s = spltty();
566 CLR(tp->t_state, TS_BUSY | TS_FLUSH);
567 sc->sc_cua = 0;
568 ttyclose(tp);
569 ucom_cleanup(sc);
570 splx(s);
571
572 if (sc->sc_methods->ucom_close != NULL)
573 sc->sc_methods->ucom_close(sc->sc_parent, sc->sc_portno);
574
575 ucom_unlock(sc);
576
577 return (0);
578 }
579
580 int
581 ucomread(dev_t dev, struct uio *uio, int flag)
582 {
583 struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)];
584 struct tty *tp = sc->sc_tty;
585 int error;
586
587 if (sc->sc_dying)
588 return (EIO);
589
590 sc->sc_refcnt++;
591 error = (*LINESW(tp, l_read))(tp, uio, flag);
592 if (--sc->sc_refcnt < 0)
593 usb_detach_wakeup(&sc->sc_dev);
594 return (error);
595 }
596
597 int
598 ucomwrite(dev_t dev, struct uio *uio, int flag)
599 {
600 struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)];
601 struct tty *tp = sc->sc_tty;
602 int error;
603
604 if (sc->sc_dying)
605 return (EIO);
606
607 sc->sc_refcnt++;
608 error = (*LINESW(tp, l_write))(tp, uio, flag);
609 if (--sc->sc_refcnt < 0)
610 usb_detach_wakeup(&sc->sc_dev);
611 return (error);
612 }
613
614 struct tty *
615 ucomtty(dev_t dev)
616 {
617 struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)];
618 struct tty *tp = sc->sc_tty;
619
620 return (tp);
621 }
622
623 int
624 ucomioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
625 {
626 struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)];
627 int error;
628
629 sc->sc_refcnt++;
630 error = ucom_do_ioctl(sc, cmd, data, flag, p);
631 if (--sc->sc_refcnt < 0)
632 usb_detach_wakeup(&sc->sc_dev);
633 return (error);
634 }
635
636 int
637 ucom_do_ioctl(struct ucom_softc *sc, u_long cmd, caddr_t data,
638 int flag, struct proc *p)
639 {
640 struct tty *tp = sc->sc_tty;
641 int error;
642 int s;
643
644 if (sc->sc_dying)
645 return (EIO);
646
647 DPRINTF(("ucomioctl: cmd=0x%08lx\n", cmd));
648
649 error = (*LINESW(tp, l_ioctl))(tp, cmd, data, flag, p);
650 if (error >= 0)
651 return (error);
652
653 error = ttioctl(tp, cmd, data, flag, p);
654 if (error >= 0)
655 return (error);
656
657 if (sc->sc_methods->ucom_ioctl != NULL) {
658 error = sc->sc_methods->ucom_ioctl(sc->sc_parent,
659 sc->sc_portno, cmd, data, flag, p);
660 if (error >= 0)
661 return (error);
662 }
663
664 error = 0;
665
666 DPRINTF(("ucomioctl: our cmd=0x%08lx\n", cmd));
667 s = spltty();
668
669 switch (cmd) {
670 case TIOCSBRK:
671 ucom_break(sc, 1);
672 break;
673
674 case TIOCCBRK:
675 ucom_break(sc, 0);
676 break;
677
678 case TIOCSDTR:
679 ucom_dtr(sc, 1);
680 break;
681
682 case TIOCCDTR:
683 ucom_dtr(sc, 0);
684 break;
685
686 case TIOCGFLAGS:
687 *(int *)data = sc->sc_swflags;
688 break;
689
690 case TIOCSFLAGS:
691 error = suser(p, 0);
692 if (error)
693 break;
694 sc->sc_swflags = *(int *)data;
695 break;
696
697 case TIOCMSET:
698 case TIOCMBIS:
699 case TIOCMBIC:
700 tiocm_to_ucom(sc, cmd, *(int *)data);
701 break;
702
703 case TIOCMGET:
704 *(int *)data = ucom_to_tiocm(sc);
705 break;
706
707 default:
708 error = ENOTTY;
709 break;
710 }
711
712 splx(s);
713
714 return (error);
715 }
716
717 void
718 tiocm_to_ucom(struct ucom_softc *sc, u_long how, int ttybits)
719 {
720 u_char combits;
721
722 combits = 0;
723 if (ISSET(ttybits, TIOCM_DTR))
724 SET(combits, UMCR_DTR);
725 if (ISSET(ttybits, TIOCM_RTS))
726 SET(combits, UMCR_RTS);
727
728 switch (how) {
729 case TIOCMBIC:
730 CLR(sc->sc_mcr, combits);
731 break;
732
733 case TIOCMBIS:
734 SET(sc->sc_mcr, combits);
735 break;
736
737 case TIOCMSET:
738 CLR(sc->sc_mcr, UMCR_DTR | UMCR_RTS);
739 SET(sc->sc_mcr, combits);
740 break;
741 }
742
743 if (how == TIOCMSET || ISSET(combits, UMCR_DTR))
744 ucom_dtr(sc, (sc->sc_mcr & UMCR_DTR) != 0);
745 if (how == TIOCMSET || ISSET(combits, UMCR_RTS))
746 ucom_rts(sc, (sc->sc_mcr & UMCR_RTS) != 0);
747 }
748
749 int
750 ucom_to_tiocm(struct ucom_softc *sc)
751 {
752 u_char combits;
753 int ttybits = 0;
754
755 combits = sc->sc_mcr;
756 if (ISSET(combits, UMCR_DTR))
757 SET(ttybits, TIOCM_DTR);
758 if (ISSET(combits, UMCR_RTS))
759 SET(ttybits, TIOCM_RTS);
760
761 combits = sc->sc_msr;
762 if (ISSET(combits, UMSR_DCD))
763 SET(ttybits, TIOCM_CD);
764 if (ISSET(combits, UMSR_CTS))
765 SET(ttybits, TIOCM_CTS);
766 if (ISSET(combits, UMSR_DSR))
767 SET(ttybits, TIOCM_DSR);
768 if (ISSET(combits, UMSR_RI | UMSR_TERI))
769 SET(ttybits, TIOCM_RI);
770
771 #if 0
772 XXX;
773 if (sc->sc_ier != 0)
774 SET(ttybits, TIOCM_LE);
775 #endif
776
777 return (ttybits);
778 }
779
780 void
781 ucom_break(sc, onoff)
782 struct ucom_softc *sc;
783 int onoff;
784 {
785 DPRINTF(("ucom_break: onoff=%d\n", onoff));
786
787 if (sc->sc_methods->ucom_set != NULL)
788 sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno,
789 UCOM_SET_BREAK, onoff);
790 }
791
792 void
793 ucom_dtr(struct ucom_softc *sc, int onoff)
794 {
795 DPRINTF(("ucom_dtr: onoff=%d\n", onoff));
796
797 if (sc->sc_methods->ucom_set != NULL) {
798 sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno,
799 UCOM_SET_DTR, onoff);
800
801 if (!(sc->sc_swflags & TIOCFLAG_CRTSCTS))
802 ucom_rts(sc, onoff);
803 }
804 }
805
806 void
807 ucom_rts(struct ucom_softc *sc, int onoff)
808 {
809 DPRINTF(("ucom_rts: onoff=%d\n", onoff));
810
811 if (sc->sc_methods->ucom_set != NULL)
812 sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno,
813 UCOM_SET_RTS, onoff);
814 }
815
816 void
817 ucom_status_change(struct ucom_softc *sc)
818 {
819 struct tty *tp = sc->sc_tty;
820 u_char old_msr;
821
822 if (sc->sc_methods->ucom_get_status != NULL) {
823 old_msr = sc->sc_msr;
824 sc->sc_methods->ucom_get_status(sc->sc_parent, sc->sc_portno,
825 &sc->sc_lsr, &sc->sc_msr);
826
827 ttytstamp(tp, old_msr & UMSR_CTS, sc->sc_msr & UMSR_CTS,
828 old_msr & UMSR_DCD, sc->sc_msr & UMSR_DCD);
829
830 if (ISSET((sc->sc_msr ^ old_msr), UMSR_DCD))
831 (*LINESW(tp, l_modem))(tp,
832 ISSET(sc->sc_msr, UMSR_DCD));
833 } else {
834 sc->sc_lsr = 0;
835 sc->sc_msr = 0;
836 }
837 }
838
839 int
840 ucomparam(struct tty *tp, struct termios *t)
841 {
842 struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(tp->t_dev)];
843 int error;
844
845 if (sc->sc_dying)
846 return (EIO);
847
848
849 if (t->c_ispeed && t->c_ispeed != t->c_ospeed)
850 return (EINVAL);
851
852
853
854
855
856 if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR)) {
857 SET(t->c_cflag, CLOCAL);
858 CLR(t->c_cflag, HUPCL);
859 }
860
861
862
863
864
865
866 if (tp->t_ospeed == t->c_ospeed &&
867 tp->t_cflag == t->c_cflag)
868 return (0);
869
870
871
872
873 tp->t_ispeed = 0;
874 tp->t_ospeed = t->c_ospeed;
875 tp->t_cflag = t->c_cflag;
876
877 if (sc->sc_methods->ucom_param != NULL) {
878 error = sc->sc_methods->ucom_param(sc->sc_parent, sc->sc_portno,
879 t);
880 if (error)
881 return (error);
882 }
883
884
885
886
887
888
889
890
891 DPRINTF(("ucomparam: l_modem\n"));
892 (void) (*LINESW(tp, l_modem))(tp, 1 );
893
894 #if 0
895 XXX what if the hardware is not open
896 if (!ISSET(t->c_cflag, CHWFLOW)) {
897 if (sc->sc_tx_stopped) {
898 sc->sc_tx_stopped = 0;
899 ucomstart(tp);
900 }
901 }
902 #endif
903
904 return (0);
905 }
906
907
908
909
910 void
911 ucom_hwiflow(struct ucom_softc *sc)
912 {
913 DPRINTF(("ucom_hwiflow:\n"));
914 #if 0
915 XXX
916 bus_space_tag_t iot = sc->sc_iot;
917 bus_space_handle_t ioh = sc->sc_ioh;
918
919 if (sc->sc_mcr_rts == 0)
920 return;
921
922 if (ISSET(sc->sc_rx_flags, RX_ANY_BLOCK)) {
923 CLR(sc->sc_mcr, sc->sc_mcr_rts);
924 CLR(sc->sc_mcr_active, sc->sc_mcr_rts);
925 } else {
926 SET(sc->sc_mcr, sc->sc_mcr_rts);
927 SET(sc->sc_mcr_active, sc->sc_mcr_rts);
928 }
929 bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr_active);
930 #endif
931 }
932
933 void
934 ucomstart(struct tty *tp)
935 {
936 struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(tp->t_dev)];
937 usbd_status err;
938 int s;
939 u_char *data;
940 int cnt;
941
942 if (sc->sc_dying)
943 return;
944
945 s = spltty();
946 if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) {
947 DPRINTFN(4,("ucomstart: no go, state=0x%x\n", tp->t_state));
948 goto out;
949 }
950 if (sc->sc_tx_stopped)
951 goto out;
952
953 if (tp->t_outq.c_cc <= tp->t_lowat) {
954 if (ISSET(tp->t_state, TS_ASLEEP)) {
955 CLR(tp->t_state, TS_ASLEEP);
956 wakeup(&tp->t_outq);
957 }
958 selwakeup(&tp->t_wsel);
959 if (tp->t_outq.c_cc == 0)
960 goto out;
961 }
962
963
964 data = tp->t_outq.c_cf;
965 cnt = ndqb(&tp->t_outq, 0);
966
967 if (cnt == 0) {
968 DPRINTF(("ucomstart: cnt==0\n"));
969 goto out;
970 }
971
972 SET(tp->t_state, TS_BUSY);
973
974 if (cnt > sc->sc_obufsize) {
975 DPRINTF(("ucomstart: big buffer %d chars\n", cnt));
976 cnt = sc->sc_obufsize;
977 }
978 if (sc->sc_methods->ucom_write != NULL)
979 sc->sc_methods->ucom_write(sc->sc_parent, sc->sc_portno,
980 sc->sc_obuf, data, &cnt);
981 else
982 memcpy(sc->sc_obuf, data, cnt);
983
984 DPRINTFN(4,("ucomstart: %d chars\n", cnt));
985 #ifdef DIAGNOSTIC
986 if (sc->sc_oxfer == NULL) {
987 printf("ucomstart: null oxfer\n");
988 goto out;
989 }
990 #endif
991 if (sc->sc_bulkout_pipe != NULL) {
992 usbd_setup_xfer(sc->sc_oxfer, sc->sc_bulkout_pipe,
993 (usbd_private_handle)sc, sc->sc_obuf, cnt,
994 USBD_NO_COPY, USBD_NO_TIMEOUT, ucomwritecb);
995 } else {
996 usbd_setup_xfer(sc->sc_oxfer, sc->sc_opipe,
997 (usbd_private_handle)sc, sc->sc_obuf, cnt,
998 USBD_NO_COPY, USBD_NO_TIMEOUT, ucomwritecb);
999 }
1000
1001 err = usbd_transfer(sc->sc_oxfer);
1002 #ifdef DIAGNOSTIC
1003 if (err != USBD_IN_PROGRESS)
1004 printf("ucomstart: err=%s\n", usbd_errstr(err));
1005 #endif
1006
1007 out:
1008 splx(s);
1009 }
1010
1011 int
1012 ucomstop(struct tty *tp, int flag)
1013 {
1014 DPRINTF(("ucomstop: flag=%d\n", flag));
1015 #if 0
1016
1017 int s;
1018
1019 s = spltty();
1020 if (ISSET(tp->t_state, TS_BUSY)) {
1021 DPRINTF(("ucomstop: XXX\n"));
1022
1023 if (!ISSET(tp->t_state, TS_TTSTOP))
1024 SET(tp->t_state, TS_FLUSH);
1025 }
1026 splx(s);
1027 #endif
1028 return (0);
1029 }
1030
1031 void
1032 ucomwritecb(usbd_xfer_handle xfer, usbd_private_handle p, usbd_status status)
1033 {
1034 struct ucom_softc *sc = (struct ucom_softc *)p;
1035 struct tty *tp = sc->sc_tty;
1036 u_int32_t cc;
1037 int s;
1038
1039 DPRINTFN(5,("ucomwritecb: %p %p status=%d\n", xfer, p, status));
1040
1041 if (status == USBD_CANCELLED || sc->sc_dying)
1042 goto error;
1043
1044 if (sc->sc_bulkin_pipe != NULL) {
1045 if (status) {
1046 usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe);
1047
1048 goto error;
1049 }
1050 usbd_get_xfer_status(xfer, NULL, NULL, &cc, NULL);
1051 } else {
1052 usbd_get_xfer_status(xfer, NULL, NULL, &cc, NULL);
1053
1054 }
1055
1056 DPRINTFN(5,("ucomwritecb: cc=%d\n", cc));
1057
1058 cc -= sc->sc_opkthdrlen;
1059
1060 s = spltty();
1061 CLR(tp->t_state, TS_BUSY);
1062 if (ISSET(tp->t_state, TS_FLUSH))
1063 CLR(tp->t_state, TS_FLUSH);
1064 else
1065 ndflush(&tp->t_outq, cc);
1066 (*LINESW(tp, l_start))(tp);
1067 splx(s);
1068 return;
1069
1070 error:
1071 s = spltty();
1072 CLR(tp->t_state, TS_BUSY);
1073 splx(s);
1074 }
1075
1076 usbd_status
1077 ucomstartread(struct ucom_softc *sc)
1078 {
1079 usbd_status err;
1080
1081 DPRINTFN(5,("ucomstartread: start\n"));
1082 #ifdef DIAGNOSTIC
1083 if (sc->sc_ixfer == NULL) {
1084 DPRINTF(("ucomstartread: null ixfer\n"));
1085 return (USBD_INVAL);
1086 }
1087 #endif
1088
1089 if (sc->sc_bulkin_pipe != NULL) {
1090 usbd_setup_xfer(sc->sc_ixfer, sc->sc_bulkin_pipe,
1091 (usbd_private_handle)sc,
1092 sc->sc_ibuf, sc->sc_ibufsize,
1093 USBD_SHORT_XFER_OK | USBD_NO_COPY,
1094 USBD_NO_TIMEOUT, ucomreadcb);
1095 err = usbd_transfer(sc->sc_ixfer);
1096 if (err != USBD_IN_PROGRESS) {
1097 DPRINTF(("ucomstartread: err=%s\n", usbd_errstr(err)));
1098 return (err);
1099 }
1100 }
1101
1102 return (USBD_NORMAL_COMPLETION);
1103 }
1104
1105 void
1106 ucomreadcb(usbd_xfer_handle xfer, usbd_private_handle p, usbd_status status)
1107 {
1108 struct ucom_softc *sc = (struct ucom_softc *)p;
1109 struct tty *tp = sc->sc_tty;
1110 int (*rint)(int c, struct tty *tp) = LINESW(tp, l_rint);
1111 usbd_status err;
1112 u_int32_t cc;
1113 u_char *cp;
1114 int s;
1115
1116 DPRINTFN(5,("ucomreadcb: status=%d\n", status));
1117
1118 if (status == USBD_CANCELLED || status == USBD_IOERROR ||
1119 sc->sc_dying) {
1120 DPRINTF(("ucomreadcb: dying\n"));
1121
1122 s = spltty();
1123 (*rint)('\n', tp);
1124 ttwakeup(tp);
1125 splx(s);
1126 return;
1127 }
1128
1129 if (status) {
1130 if (sc->sc_bulkin_pipe != NULL) {
1131 usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe);
1132
1133 return;
1134 }
1135 }
1136
1137 usbd_get_xfer_status(xfer, NULL, (void *)&cp, &cc, NULL);
1138 DPRINTFN(5,("ucomreadcb: got %d chars, tp=%p\n", cc, tp));
1139 if (sc->sc_methods->ucom_read != NULL)
1140 sc->sc_methods->ucom_read(sc->sc_parent, sc->sc_portno,
1141 &cp, &cc);
1142
1143 s = spltty();
1144
1145 while (cc-- > 0) {
1146 DPRINTFN(7,("ucomreadcb: char=0x%02x\n", *cp));
1147 if ((*rint)(*cp++, tp) == -1) {
1148
1149 printf("%s: lost %d chars\n", sc->sc_dev.dv_xname,
1150 cc);
1151 break;
1152 }
1153 }
1154 splx(s);
1155
1156 err = ucomstartread(sc);
1157 if (err) {
1158 printf("%s: read start failed\n", sc->sc_dev.dv_xname);
1159
1160 }
1161 }
1162
1163 void
1164 ucom_cleanup(struct ucom_softc *sc)
1165 {
1166 if (--sc->sc_open == 0) {
1167 DPRINTF(("ucom_cleanup: closing pipes\n"));
1168
1169 ucom_shutdown(sc);
1170 if (sc->sc_bulkin_pipe != NULL) {
1171 usbd_abort_pipe(sc->sc_bulkin_pipe);
1172 usbd_close_pipe(sc->sc_bulkin_pipe);
1173 sc->sc_bulkin_pipe = NULL;
1174 }
1175 if (sc->sc_bulkout_pipe != NULL) {
1176 usbd_abort_pipe(sc->sc_bulkout_pipe);
1177 usbd_close_pipe(sc->sc_bulkout_pipe);
1178 sc->sc_bulkout_pipe = NULL;
1179 }
1180 if (sc->sc_ixfer != NULL) {
1181 if (sc->sc_uhidev == NULL)
1182 usbd_free_xfer(sc->sc_ixfer);
1183 sc->sc_ixfer = NULL;
1184 }
1185 if (sc->sc_oxfer != NULL) {
1186 usbd_free_buffer(sc->sc_oxfer);
1187 if (sc->sc_uhidev == NULL)
1188 usbd_free_xfer(sc->sc_oxfer);
1189 sc->sc_oxfer = NULL;
1190 }
1191 }
1192 }
1193
1194 #endif
1195
1196 int
1197 ucomprint(void *aux, const char *pnp)
1198 {
1199 struct ucom_attach_args *uca = aux;
1200
1201 if (pnp)
1202 printf("ucom at %s", pnp);
1203 if (uca->portno != UCOM_UNK_PORTNO)
1204 printf(" portno %d", uca->portno);
1205 return (UNCONF);
1206 }
1207
1208 int
1209 ucomsubmatch(struct device *parent, void *match, void *aux)
1210 {
1211 struct ucom_attach_args *uca = aux;
1212 struct cfdata *cf = match;
1213
1214 if (uca->portno != UCOM_UNK_PORTNO &&
1215 cf->ucomcf_portno != UCOM_UNK_PORTNO &&
1216 cf->ucomcf_portno != uca->portno)
1217 return (0);
1218 return ((*cf->cf_attach->ca_match)(parent, cf, aux));
1219 }