xref: /freebsd/sys/dev/usb/serial/usb_serial.c (revision 39beb93c3f8bdbf72a61fda42300b5ebed7390c8)
1 /*	$NetBSD: ucom.c,v 1.40 2001/11/13 06:24:54 lukem Exp $	*/
2 
3 /*-
4  * Copyright (c) 2001-2003, 2005, 2008
5  *	Shunsuke Akiyama <akiyama@jp.FreeBSD.org>.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32 
33 /*-
34  * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
35  * All rights reserved.
36  *
37  * This code is derived from software contributed to The NetBSD Foundation
38  * by Lennart Augustsson (lennart@augustsson.net) at
39  * Carlstedt Research & Technology.
40  *
41  * Redistribution and use in source and binary forms, with or without
42  * modification, are permitted provided that the following conditions
43  * are met:
44  * 1. Redistributions of source code must retain the above copyright
45  *    notice, this list of conditions and the following disclaimer.
46  * 2. Redistributions in binary form must reproduce the above copyright
47  *    notice, this list of conditions and the following disclaimer in the
48  *    documentation and/or other materials provided with the distribution.
49  * 3. All advertising materials mentioning features or use of this software
50  *    must display the following acknowledgement:
51  *        This product includes software developed by the NetBSD
52  *        Foundation, Inc. and its contributors.
53  * 4. Neither the name of The NetBSD Foundation nor the names of its
54  *    contributors may be used to endorse or promote products derived
55  *    from this software without specific prior written permission.
56  *
57  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
58  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
59  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
60  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
61  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
62  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
63  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
64  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
65  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
66  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
67  * POSSIBILITY OF SUCH DAMAGE.
68  */
69 
70 #include <dev/usb/usb.h>
71 #include <dev/usb/usb_mfunc.h>
72 #include <dev/usb/usb_error.h>
73 #include <dev/usb/usb_cdc.h>
74 #include <dev/usb/usb_ioctl.h>
75 
76 #define	USB_DEBUG_VAR usb2_com_debug
77 
78 #include <dev/usb/usb_core.h>
79 #include <dev/usb/usb_debug.h>
80 #include <dev/usb/usb_process.h>
81 #include <dev/usb/usb_request.h>
82 #include <dev/usb/usb_busdma.h>
83 #include <dev/usb/usb_util.h>
84 
85 #include <dev/usb/serial/usb_serial.h>
86 
87 #if USB_DEBUG
88 static int usb2_com_debug = 0;
89 
90 SYSCTL_NODE(_hw_usb2, OID_AUTO, ucom, CTLFLAG_RW, 0, "USB ucom");
91 SYSCTL_INT(_hw_usb2_ucom, OID_AUTO, debug, CTLFLAG_RW,
92     &usb2_com_debug, 0, "ucom debug level");
93 #endif
94 
95 static usb2_proc_callback_t usb2_com_cfg_start_transfers;
96 static usb2_proc_callback_t usb2_com_cfg_open;
97 static usb2_proc_callback_t usb2_com_cfg_close;
98 static usb2_proc_callback_t usb2_com_cfg_line_state;
99 static usb2_proc_callback_t usb2_com_cfg_status_change;
100 static usb2_proc_callback_t usb2_com_cfg_param;
101 
102 static uint8_t	usb2_com_units_alloc(uint32_t, uint32_t *);
103 static void	usb2_com_units_free(uint32_t, uint32_t);
104 static int	usb2_com_attach_tty(struct usb2_com_softc *, uint32_t);
105 static void	usb2_com_detach_tty(struct usb2_com_softc *);
106 static void	usb2_com_queue_command(struct usb2_com_softc *,
107 		    usb2_proc_callback_t *, struct termios *pt,
108 		    struct usb2_proc_msg *t0, struct usb2_proc_msg *t1);
109 static void	usb2_com_shutdown(struct usb2_com_softc *);
110 static void	usb2_com_break(struct usb2_com_softc *, uint8_t);
111 static void	usb2_com_dtr(struct usb2_com_softc *, uint8_t);
112 static void	usb2_com_rts(struct usb2_com_softc *, uint8_t);
113 
114 static tsw_open_t usb2_com_open;
115 static tsw_close_t usb2_com_close;
116 static tsw_ioctl_t usb2_com_ioctl;
117 static tsw_modem_t usb2_com_modem;
118 static tsw_param_t usb2_com_param;
119 static tsw_outwakeup_t usb2_com_outwakeup;
120 static tsw_free_t usb2_com_free;
121 
122 static struct ttydevsw usb2_com_class = {
123 	.tsw_flags = TF_INITLOCK | TF_CALLOUT,
124 	.tsw_open = usb2_com_open,
125 	.tsw_close = usb2_com_close,
126 	.tsw_outwakeup = usb2_com_outwakeup,
127 	.tsw_ioctl = usb2_com_ioctl,
128 	.tsw_param = usb2_com_param,
129 	.tsw_modem = usb2_com_modem,
130 	.tsw_free = usb2_com_free,
131 };
132 
133 MODULE_DEPEND(ucom, usb, 1, 1, 1);
134 MODULE_VERSION(ucom, 1);
135 
136 #define	UCOM_UNIT_MAX 0x1000		/* exclusive */
137 #define	UCOM_SUB_UNIT_MAX 0x100		/* exclusive */
138 
139 static uint8_t usb2_com_bitmap[(UCOM_UNIT_MAX + 7) / 8];
140 
141 static uint8_t
142 usb2_com_units_alloc(uint32_t sub_units, uint32_t *p_root_unit)
143 {
144 	uint32_t n;
145 	uint32_t o;
146 	uint32_t x;
147 	uint32_t max = UCOM_UNIT_MAX - (UCOM_UNIT_MAX % sub_units);
148 	uint8_t error = 1;
149 
150 	mtx_lock(&Giant);
151 
152 	for (n = 0; n < max; n += sub_units) {
153 
154 		/* check for free consecutive bits */
155 
156 		for (o = 0; o < sub_units; o++) {
157 
158 			x = n + o;
159 
160 			if (usb2_com_bitmap[x / 8] & (1 << (x % 8))) {
161 				goto skip;
162 			}
163 		}
164 
165 		/* allocate */
166 
167 		for (o = 0; o < sub_units; o++) {
168 
169 			x = n + o;
170 
171 			usb2_com_bitmap[x / 8] |= (1 << (x % 8));
172 		}
173 
174 		error = 0;
175 
176 		break;
177 
178 skip:		;
179 	}
180 
181 	mtx_unlock(&Giant);
182 
183 	/*
184 	 * Always set the variable pointed to by "p_root_unit" so that
185 	 * the compiler does not think that it is used uninitialised:
186 	 */
187 	*p_root_unit = n;
188 
189 	return (error);
190 }
191 
192 static void
193 usb2_com_units_free(uint32_t root_unit, uint32_t sub_units)
194 {
195 	uint32_t x;
196 
197 	mtx_lock(&Giant);
198 
199 	while (sub_units--) {
200 		x = root_unit + sub_units;
201 		usb2_com_bitmap[x / 8] &= ~(1 << (x % 8));
202 	}
203 
204 	mtx_unlock(&Giant);
205 }
206 
207 /*
208  * "N" sub_units are setup at a time. All sub-units will
209  * be given sequential unit numbers. The number of
210  * sub-units can be used to differentiate among
211  * different types of devices.
212  *
213  * The mutex pointed to by "mtx" is applied before all
214  * callbacks are called back. Also "mtx" must be applied
215  * before calling into the ucom-layer!
216  */
217 int
218 usb2_com_attach(struct usb2_com_super_softc *ssc, struct usb2_com_softc *sc,
219     uint32_t sub_units, void *parent,
220     const struct usb2_com_callback *callback, struct mtx *mtx)
221 {
222 	uint32_t n;
223 	uint32_t root_unit;
224 	int error = 0;
225 
226 	if ((sc == NULL) ||
227 	    (sub_units == 0) ||
228 	    (sub_units > UCOM_SUB_UNIT_MAX) ||
229 	    (callback == NULL)) {
230 		return (EINVAL);
231 	}
232 
233 	/* XXX unit management does not really belong here */
234 	if (usb2_com_units_alloc(sub_units, &root_unit)) {
235 		return (ENOMEM);
236 	}
237 
238 	error = usb2_proc_create(&ssc->sc_tq, mtx, "ucom", USB_PRI_MED);
239 	if (error) {
240 		usb2_com_units_free(root_unit, sub_units);
241 		return (error);
242 	}
243 
244 	for (n = 0; n != sub_units; n++, sc++) {
245 		sc->sc_unit = root_unit + n;
246 		sc->sc_local_unit = n;
247 		sc->sc_super = ssc;
248 		sc->sc_mtx = mtx;
249 		sc->sc_parent = parent;
250 		sc->sc_callback = callback;
251 
252 		error = usb2_com_attach_tty(sc, sub_units);
253 		if (error) {
254 			usb2_com_detach(ssc, sc - n, n);
255 			usb2_com_units_free(root_unit + n, sub_units - n);
256 			return (error);
257 		}
258 		sc->sc_flag |= UCOM_FLAG_ATTACHED;
259 	}
260 	return (0);
261 }
262 
263 /*
264  * NOTE: the following function will do nothing if
265  * the structure pointed to by "ssc" and "sc" is zero.
266  */
267 void
268 usb2_com_detach(struct usb2_com_super_softc *ssc, struct usb2_com_softc *sc,
269     uint32_t sub_units)
270 {
271 	uint32_t n;
272 
273 	usb2_proc_drain(&ssc->sc_tq);
274 
275 	for (n = 0; n != sub_units; n++, sc++) {
276 		if (sc->sc_flag & UCOM_FLAG_ATTACHED) {
277 
278 			usb2_com_detach_tty(sc);
279 
280 			usb2_com_units_free(sc->sc_unit, 1);
281 
282 			/* avoid duplicate detach: */
283 			sc->sc_flag &= ~UCOM_FLAG_ATTACHED;
284 		}
285 	}
286 	usb2_proc_free(&ssc->sc_tq);
287 }
288 
289 static int
290 usb2_com_attach_tty(struct usb2_com_softc *sc, uint32_t sub_units)
291 {
292 	struct tty *tp;
293 	int error = 0;
294 	char buf[32];			/* temporary TTY device name buffer */
295 
296 	tp = tty_alloc(&usb2_com_class, sc, sc->sc_mtx);
297 	if (tp == NULL) {
298 		error = ENOMEM;
299 		goto done;
300 	}
301 	DPRINTF("tp = %p, unit = %d\n", tp, sc->sc_unit);
302 
303 	buf[0] = 0;			/* set some default value */
304 
305 	/* Check if the client has a custom TTY name */
306 	if (sc->sc_callback->usb2_com_tty_name) {
307 		sc->sc_callback->usb2_com_tty_name(sc, buf,
308 		    sizeof(buf), sc->sc_local_unit);
309 	}
310 	if (buf[0] == 0) {
311 		/* Use default TTY name */
312 		if (sub_units > 1) {
313 			/* multiple modems in one */
314 			if (snprintf(buf, sizeof(buf), "U%u.%u",
315 			    sc->sc_unit - sc->sc_local_unit,
316 			    sc->sc_local_unit)) {
317 				/* ignore */
318 			}
319 		} else {
320 			/* single modem */
321 			if (snprintf(buf, sizeof(buf), "U%u", sc->sc_unit)) {
322 				/* ignore */
323 			}
324 		}
325 	}
326 	tty_makedev(tp, NULL, "%s", buf);
327 
328 	sc->sc_tty = tp;
329 
330 	DPRINTF("ttycreate: %s\n", buf);
331 	usb2_cv_init(&sc->sc_cv, "usb2_com");
332 
333 done:
334 	return (error);
335 }
336 
337 static void
338 usb2_com_detach_tty(struct usb2_com_softc *sc)
339 {
340 	struct tty *tp = sc->sc_tty;
341 
342 	DPRINTF("sc = %p, tp = %p\n", sc, sc->sc_tty);
343 
344 	/* the config thread has been stopped when we get here */
345 
346 	mtx_lock(sc->sc_mtx);
347 	sc->sc_flag |= UCOM_FLAG_GONE;
348 	sc->sc_flag &= ~(UCOM_FLAG_HL_READY |
349 	    UCOM_FLAG_LL_READY);
350 	mtx_unlock(sc->sc_mtx);
351 	if (tp) {
352 		tty_lock(tp);
353 
354 		usb2_com_close(tp);	/* close, if any */
355 
356 		tty_rel_gone(tp);
357 
358 		mtx_lock(sc->sc_mtx);
359 		/* Wait for the callback after the TTY is torn down */
360 		while (sc->sc_ttyfreed == 0)
361 			usb2_cv_wait(&sc->sc_cv, sc->sc_mtx);
362 		/*
363 		 * make sure that read and write transfers are stopped
364 		 */
365 		if (sc->sc_callback->usb2_com_stop_read) {
366 			(sc->sc_callback->usb2_com_stop_read) (sc);
367 		}
368 		if (sc->sc_callback->usb2_com_stop_write) {
369 			(sc->sc_callback->usb2_com_stop_write) (sc);
370 		}
371 		mtx_unlock(sc->sc_mtx);
372 	}
373 	usb2_cv_destroy(&sc->sc_cv);
374 }
375 
376 static void
377 usb2_com_queue_command(struct usb2_com_softc *sc,
378     usb2_proc_callback_t *fn, struct termios *pt,
379     struct usb2_proc_msg *t0, struct usb2_proc_msg *t1)
380 {
381 	struct usb2_com_super_softc *ssc = sc->sc_super;
382 	struct usb2_com_param_task *task;
383 
384 	mtx_assert(sc->sc_mtx, MA_OWNED);
385 
386 	if (usb2_proc_is_gone(&ssc->sc_tq)) {
387 		DPRINTF("proc is gone\n");
388 		return;         /* nothing to do */
389 	}
390 	/*
391 	 * NOTE: The task cannot get executed before we drop the
392 	 * "sc_mtx" mutex. It is safe to update fields in the message
393 	 * structure after that the message got queued.
394 	 */
395 	task = (struct usb2_com_param_task *)
396 	  usb2_proc_msignal(&ssc->sc_tq, t0, t1);
397 
398 	/* Setup callback and softc pointers */
399 	task->hdr.pm_callback = fn;
400 	task->sc = sc;
401 
402 	/*
403 	 * Make a copy of the termios. This field is only present if
404 	 * the "pt" field is not NULL.
405 	 */
406 	if (pt != NULL)
407 		task->termios_copy = *pt;
408 
409 	/*
410 	 * Closing the device should be synchronous.
411 	 */
412 	if (fn == usb2_com_cfg_close)
413 		usb2_proc_mwait(&ssc->sc_tq, t0, t1);
414 
415 }
416 
417 static void
418 usb2_com_shutdown(struct usb2_com_softc *sc)
419 {
420 	struct tty *tp = sc->sc_tty;
421 
422 	mtx_assert(sc->sc_mtx, MA_OWNED);
423 
424 	DPRINTF("\n");
425 
426 	/*
427 	 * Hang up if necessary:
428 	 */
429 	if (tp->t_termios.c_cflag & HUPCL) {
430 		usb2_com_modem(tp, 0, SER_DTR);
431 	}
432 }
433 
434 /*
435  * Return values:
436  *    0: normal
437  * else: taskqueue is draining or gone
438  */
439 uint8_t
440 usb2_com_cfg_is_gone(struct usb2_com_softc *sc)
441 {
442 	struct usb2_com_super_softc *ssc = sc->sc_super;
443 
444 	return (usb2_proc_is_gone(&ssc->sc_tq));
445 }
446 
447 static void
448 usb2_com_cfg_start_transfers(struct usb2_proc_msg *_task)
449 {
450 	struct usb2_com_cfg_task *task =
451 	    (struct usb2_com_cfg_task *)_task;
452 	struct usb2_com_softc *sc = task->sc;
453 
454 	if (!(sc->sc_flag & UCOM_FLAG_LL_READY)) {
455 		return;
456 	}
457 	if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) {
458 		/* TTY device closed */
459 		return;
460 	}
461 	sc->sc_flag |= UCOM_FLAG_GP_DATA;
462 
463 	if (sc->sc_callback->usb2_com_start_read) {
464 		(sc->sc_callback->usb2_com_start_read) (sc);
465 	}
466 	if (sc->sc_callback->usb2_com_start_write) {
467 		(sc->sc_callback->usb2_com_start_write) (sc);
468 	}
469 }
470 
471 static void
472 usb2_com_start_transfers(struct usb2_com_softc *sc)
473 {
474 	if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) {
475 		return;
476 	}
477 	/*
478 	 * Make sure that data transfers are started in both
479 	 * directions:
480 	 */
481 	if (sc->sc_callback->usb2_com_start_read) {
482 		(sc->sc_callback->usb2_com_start_read) (sc);
483 	}
484 	if (sc->sc_callback->usb2_com_start_write) {
485 		(sc->sc_callback->usb2_com_start_write) (sc);
486 	}
487 }
488 
489 static void
490 usb2_com_cfg_open(struct usb2_proc_msg *_task)
491 {
492 	struct usb2_com_cfg_task *task =
493 	    (struct usb2_com_cfg_task *)_task;
494 	struct usb2_com_softc *sc = task->sc;
495 
496 	DPRINTF("\n");
497 
498 	if (sc->sc_flag & UCOM_FLAG_LL_READY) {
499 
500 		/* already opened */
501 
502 	} else {
503 
504 		sc->sc_flag |= UCOM_FLAG_LL_READY;
505 
506 		if (sc->sc_callback->usb2_com_cfg_open) {
507 			(sc->sc_callback->usb2_com_cfg_open) (sc);
508 
509 			/* wait a little */
510 			usb2_pause_mtx(sc->sc_mtx, hz / 10);
511 		}
512 	}
513 }
514 
515 static int
516 usb2_com_open(struct tty *tp)
517 {
518 	struct usb2_com_softc *sc = tty_softc(tp);
519 	int error;
520 
521 	mtx_assert(sc->sc_mtx, MA_OWNED);
522 
523 	if (sc->sc_flag & UCOM_FLAG_GONE) {
524 		return (ENXIO);
525 	}
526 	if (sc->sc_flag & UCOM_FLAG_HL_READY) {
527 		/* already opened */
528 		return (0);
529 	}
530 	DPRINTF("tp = %p\n", tp);
531 
532 	if (sc->sc_callback->usb2_com_pre_open) {
533 		/*
534 		 * give the lower layer a chance to disallow TTY open, for
535 		 * example if the device is not present:
536 		 */
537 		error = (sc->sc_callback->usb2_com_pre_open) (sc);
538 		if (error) {
539 			return (error);
540 		}
541 	}
542 	sc->sc_flag |= UCOM_FLAG_HL_READY;
543 
544 	/* Disable transfers */
545 	sc->sc_flag &= ~UCOM_FLAG_GP_DATA;
546 
547 	sc->sc_lsr = 0;
548 	sc->sc_msr = 0;
549 	sc->sc_mcr = 0;
550 
551 	/* reset programmed line state */
552 	sc->sc_pls_curr = 0;
553 	sc->sc_pls_set = 0;
554 	sc->sc_pls_clr = 0;
555 
556 	usb2_com_queue_command(sc, usb2_com_cfg_open, NULL,
557 	    &sc->sc_open_task[0].hdr,
558 	    &sc->sc_open_task[1].hdr);
559 
560 	/* Queue transfer enable command last */
561 	usb2_com_queue_command(sc, usb2_com_cfg_start_transfers, NULL,
562 	    &sc->sc_start_task[0].hdr,
563 	    &sc->sc_start_task[1].hdr);
564 
565 	usb2_com_modem(tp, SER_DTR | SER_RTS, 0);
566 
567 	usb2_com_break(sc, 0);
568 
569 	usb2_com_status_change(sc);
570 
571 	return (0);
572 }
573 
574 static void
575 usb2_com_cfg_close(struct usb2_proc_msg *_task)
576 {
577 	struct usb2_com_cfg_task *task =
578 	    (struct usb2_com_cfg_task *)_task;
579 	struct usb2_com_softc *sc = task->sc;
580 
581 	DPRINTF("\n");
582 
583 	if (sc->sc_flag & UCOM_FLAG_LL_READY) {
584 
585 		sc->sc_flag &= ~(UCOM_FLAG_LL_READY |
586 		    UCOM_FLAG_GP_DATA);
587 
588 		if (sc->sc_callback->usb2_com_cfg_close) {
589 			(sc->sc_callback->usb2_com_cfg_close) (sc);
590 		}
591 	} else {
592 		/* already closed */
593 	}
594 }
595 
596 static void
597 usb2_com_close(struct tty *tp)
598 {
599 	struct usb2_com_softc *sc = tty_softc(tp);
600 
601 	mtx_assert(sc->sc_mtx, MA_OWNED);
602 
603 	DPRINTF("tp=%p\n", tp);
604 
605 	if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) {
606 		DPRINTF("tp=%p already closed\n", tp);
607 		return;
608 	}
609 	usb2_com_shutdown(sc);
610 
611 	usb2_com_queue_command(sc, usb2_com_cfg_close, NULL,
612 	    &sc->sc_close_task[0].hdr,
613 	    &sc->sc_close_task[1].hdr);
614 
615 	sc->sc_flag &= ~(UCOM_FLAG_HL_READY |
616 	    UCOM_FLAG_WR_START |
617 	    UCOM_FLAG_RTS_IFLOW);
618 
619 	if (sc->sc_callback->usb2_com_stop_read) {
620 		(sc->sc_callback->usb2_com_stop_read) (sc);
621 	}
622 	if (sc->sc_callback->usb2_com_stop_write) {
623 		(sc->sc_callback->usb2_com_stop_write) (sc);
624 	}
625 }
626 
627 static int
628 usb2_com_ioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td)
629 {
630 	struct usb2_com_softc *sc = tty_softc(tp);
631 	int error;
632 
633 	mtx_assert(sc->sc_mtx, MA_OWNED);
634 
635 	if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) {
636 		return (EIO);
637 	}
638 	DPRINTF("cmd = 0x%08lx\n", cmd);
639 
640 	switch (cmd) {
641 	case TIOCSBRK:
642 		usb2_com_break(sc, 1);
643 		error = 0;
644 		break;
645 	case TIOCCBRK:
646 		usb2_com_break(sc, 0);
647 		error = 0;
648 		break;
649 	default:
650 		if (sc->sc_callback->usb2_com_ioctl) {
651 			error = (sc->sc_callback->usb2_com_ioctl)
652 			    (sc, cmd, data, 0, td);
653 		} else {
654 			error = ENOIOCTL;
655 		}
656 		break;
657 	}
658 	return (error);
659 }
660 
661 static int
662 usb2_com_modem(struct tty *tp, int sigon, int sigoff)
663 {
664 	struct usb2_com_softc *sc = tty_softc(tp);
665 	uint8_t onoff;
666 
667 	mtx_assert(sc->sc_mtx, MA_OWNED);
668 
669 	if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) {
670 		return (0);
671 	}
672 	if ((sigon == 0) && (sigoff == 0)) {
673 
674 		if (sc->sc_mcr & SER_DTR) {
675 			sigon |= SER_DTR;
676 		}
677 		if (sc->sc_mcr & SER_RTS) {
678 			sigon |= SER_RTS;
679 		}
680 		if (sc->sc_msr & SER_CTS) {
681 			sigon |= SER_CTS;
682 		}
683 		if (sc->sc_msr & SER_DCD) {
684 			sigon |= SER_DCD;
685 		}
686 		if (sc->sc_msr & SER_DSR) {
687 			sigon |= SER_DSR;
688 		}
689 		if (sc->sc_msr & SER_RI) {
690 			sigon |= SER_RI;
691 		}
692 		return (sigon);
693 	}
694 	if (sigon & SER_DTR) {
695 		sc->sc_mcr |= SER_DTR;
696 	}
697 	if (sigoff & SER_DTR) {
698 		sc->sc_mcr &= ~SER_DTR;
699 	}
700 	if (sigon & SER_RTS) {
701 		sc->sc_mcr |= SER_RTS;
702 	}
703 	if (sigoff & SER_RTS) {
704 		sc->sc_mcr &= ~SER_RTS;
705 	}
706 	onoff = (sc->sc_mcr & SER_DTR) ? 1 : 0;
707 	usb2_com_dtr(sc, onoff);
708 
709 	onoff = (sc->sc_mcr & SER_RTS) ? 1 : 0;
710 	usb2_com_rts(sc, onoff);
711 
712 	return (0);
713 }
714 
715 static void
716 usb2_com_cfg_line_state(struct usb2_proc_msg *_task)
717 {
718 	struct usb2_com_cfg_task *task =
719 	    (struct usb2_com_cfg_task *)_task;
720 	struct usb2_com_softc *sc = task->sc;
721 	uint8_t notch_bits;
722 	uint8_t any_bits;
723 	uint8_t prev_value;
724 	uint8_t last_value;
725 	uint8_t mask;
726 
727 	if (!(sc->sc_flag & UCOM_FLAG_LL_READY)) {
728 		return;
729 	}
730 
731 	mask = 0;
732 	/* compute callback mask */
733 	if (sc->sc_callback->usb2_com_cfg_set_dtr)
734 		mask |= UCOM_LS_DTR;
735 	if (sc->sc_callback->usb2_com_cfg_set_rts)
736 		mask |= UCOM_LS_RTS;
737 	if (sc->sc_callback->usb2_com_cfg_set_break)
738 		mask |= UCOM_LS_BREAK;
739 
740 	/* compute the bits we are to program */
741 	notch_bits = (sc->sc_pls_set & sc->sc_pls_clr) & mask;
742 	any_bits = (sc->sc_pls_set | sc->sc_pls_clr) & mask;
743 	prev_value = sc->sc_pls_curr ^ notch_bits;
744 	last_value = sc->sc_pls_curr;
745 
746 	/* reset programmed line state */
747 	sc->sc_pls_curr = 0;
748 	sc->sc_pls_set = 0;
749 	sc->sc_pls_clr = 0;
750 
751 	/* ensure that we don't loose any levels */
752 	if (notch_bits & UCOM_LS_DTR)
753 		sc->sc_callback->usb2_com_cfg_set_dtr(sc,
754 		    (prev_value & UCOM_LS_DTR) ? 1 : 0);
755 	if (notch_bits & UCOM_LS_RTS)
756 		sc->sc_callback->usb2_com_cfg_set_rts(sc,
757 		    (prev_value & UCOM_LS_RTS) ? 1 : 0);
758 	if (notch_bits & UCOM_LS_BREAK)
759 		sc->sc_callback->usb2_com_cfg_set_break(sc,
760 		    (prev_value & UCOM_LS_BREAK) ? 1 : 0);
761 
762 	/* set last value */
763 	if (any_bits & UCOM_LS_DTR)
764 		sc->sc_callback->usb2_com_cfg_set_dtr(sc,
765 		    (last_value & UCOM_LS_DTR) ? 1 : 0);
766 	if (any_bits & UCOM_LS_RTS)
767 		sc->sc_callback->usb2_com_cfg_set_rts(sc,
768 		    (last_value & UCOM_LS_RTS) ? 1 : 0);
769 	if (any_bits & UCOM_LS_BREAK)
770 		sc->sc_callback->usb2_com_cfg_set_break(sc,
771 		    (last_value & UCOM_LS_BREAK) ? 1 : 0);
772 }
773 
774 static void
775 usb2_com_line_state(struct usb2_com_softc *sc,
776     uint8_t set_bits, uint8_t clear_bits)
777 {
778 	mtx_assert(sc->sc_mtx, MA_OWNED);
779 
780 	if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) {
781 		return;
782 	}
783 
784 	DPRINTF("on=0x%02x, off=0x%02x\n", set_bits, clear_bits);
785 
786 	/* update current programmed line state */
787 	sc->sc_pls_curr |= set_bits;
788 	sc->sc_pls_curr &= ~clear_bits;
789 	sc->sc_pls_set |= set_bits;
790 	sc->sc_pls_clr |= clear_bits;
791 
792 	/* defer driver programming */
793 	usb2_com_queue_command(sc, usb2_com_cfg_line_state, NULL,
794 	    &sc->sc_line_state_task[0].hdr,
795 	    &sc->sc_line_state_task[1].hdr);
796 }
797 
798 static void
799 usb2_com_break(struct usb2_com_softc *sc, uint8_t onoff)
800 {
801 	DPRINTF("onoff = %d\n", onoff);
802 
803 	if (onoff)
804 		usb2_com_line_state(sc, UCOM_LS_BREAK, 0);
805 	else
806 		usb2_com_line_state(sc, 0, UCOM_LS_BREAK);
807 }
808 
809 static void
810 usb2_com_dtr(struct usb2_com_softc *sc, uint8_t onoff)
811 {
812 	DPRINTF("onoff = %d\n", onoff);
813 
814 	if (onoff)
815 		usb2_com_line_state(sc, UCOM_LS_DTR, 0);
816 	else
817 		usb2_com_line_state(sc, 0, UCOM_LS_DTR);
818 }
819 
820 static void
821 usb2_com_rts(struct usb2_com_softc *sc, uint8_t onoff)
822 {
823 	DPRINTF("onoff = %d\n", onoff);
824 
825 	if (onoff)
826 		usb2_com_line_state(sc, UCOM_LS_RTS, 0);
827 	else
828 		usb2_com_line_state(sc, 0, UCOM_LS_RTS);
829 }
830 
831 static void
832 usb2_com_cfg_status_change(struct usb2_proc_msg *_task)
833 {
834 	struct usb2_com_cfg_task *task =
835 	    (struct usb2_com_cfg_task *)_task;
836 	struct usb2_com_softc *sc = task->sc;
837 	struct tty *tp;
838 	uint8_t new_msr;
839 	uint8_t new_lsr;
840 	uint8_t onoff;
841 
842 	tp = sc->sc_tty;
843 
844 	mtx_assert(sc->sc_mtx, MA_OWNED);
845 
846 	if (!(sc->sc_flag & UCOM_FLAG_LL_READY)) {
847 		return;
848 	}
849 	if (sc->sc_callback->usb2_com_cfg_get_status == NULL) {
850 		return;
851 	}
852 	/* get status */
853 
854 	new_msr = 0;
855 	new_lsr = 0;
856 
857 	(sc->sc_callback->usb2_com_cfg_get_status) (sc, &new_lsr, &new_msr);
858 
859 	if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) {
860 		/* TTY device closed */
861 		return;
862 	}
863 	onoff = ((sc->sc_msr ^ new_msr) & SER_DCD);
864 
865 	sc->sc_msr = new_msr;
866 	sc->sc_lsr = new_lsr;
867 
868 	if (onoff) {
869 
870 		onoff = (sc->sc_msr & SER_DCD) ? 1 : 0;
871 
872 		DPRINTF("DCD changed to %d\n", onoff);
873 
874 		ttydisc_modem(tp, onoff);
875 	}
876 }
877 
878 void
879 usb2_com_status_change(struct usb2_com_softc *sc)
880 {
881 	mtx_assert(sc->sc_mtx, MA_OWNED);
882 
883 	if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) {
884 		return;
885 	}
886 	DPRINTF("\n");
887 
888 	usb2_com_queue_command(sc, usb2_com_cfg_status_change, NULL,
889 	    &sc->sc_status_task[0].hdr,
890 	    &sc->sc_status_task[1].hdr);
891 }
892 
893 static void
894 usb2_com_cfg_param(struct usb2_proc_msg *_task)
895 {
896 	struct usb2_com_param_task *task =
897 	    (struct usb2_com_param_task *)_task;
898 	struct usb2_com_softc *sc = task->sc;
899 
900 	if (!(sc->sc_flag & UCOM_FLAG_LL_READY)) {
901 		return;
902 	}
903 	if (sc->sc_callback->usb2_com_cfg_param == NULL) {
904 		return;
905 	}
906 
907 	(sc->sc_callback->usb2_com_cfg_param) (sc, &task->termios_copy);
908 
909 	/* wait a little */
910 	usb2_pause_mtx(sc->sc_mtx, hz / 10);
911 }
912 
913 static int
914 usb2_com_param(struct tty *tp, struct termios *t)
915 {
916 	struct usb2_com_softc *sc = tty_softc(tp);
917 	uint8_t opened;
918 	int error;
919 
920 	mtx_assert(sc->sc_mtx, MA_OWNED);
921 
922 	opened = 0;
923 	error = 0;
924 
925 	if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) {
926 
927 		/* XXX the TTY layer should call "open()" first! */
928 
929 		error = usb2_com_open(tp);
930 		if (error) {
931 			goto done;
932 		}
933 		opened = 1;
934 	}
935 	DPRINTF("sc = %p\n", sc);
936 
937 	/* Check requested parameters. */
938 	if (t->c_ospeed < 0) {
939 		DPRINTF("negative ospeed\n");
940 		error = EINVAL;
941 		goto done;
942 	}
943 	if (t->c_ispeed && (t->c_ispeed != t->c_ospeed)) {
944 		DPRINTF("mismatch ispeed and ospeed\n");
945 		error = EINVAL;
946 		goto done;
947 	}
948 	t->c_ispeed = t->c_ospeed;
949 
950 	if (sc->sc_callback->usb2_com_pre_param) {
951 		/* Let the lower layer verify the parameters */
952 		error = (sc->sc_callback->usb2_com_pre_param) (sc, t);
953 		if (error) {
954 			DPRINTF("callback error = %d\n", error);
955 			goto done;
956 		}
957 	}
958 
959 	/* Disable transfers */
960 	sc->sc_flag &= ~UCOM_FLAG_GP_DATA;
961 
962 	/* Queue baud rate programming command first */
963 	usb2_com_queue_command(sc, usb2_com_cfg_param, t,
964 	    &sc->sc_param_task[0].hdr,
965 	    &sc->sc_param_task[1].hdr);
966 
967 	/* Queue transfer enable command last */
968 	usb2_com_queue_command(sc, usb2_com_cfg_start_transfers, NULL,
969 	    &sc->sc_start_task[0].hdr,
970 	    &sc->sc_start_task[1].hdr);
971 
972 	if (t->c_cflag & CRTS_IFLOW) {
973 		sc->sc_flag |= UCOM_FLAG_RTS_IFLOW;
974 	} else if (sc->sc_flag & UCOM_FLAG_RTS_IFLOW) {
975 		sc->sc_flag &= ~UCOM_FLAG_RTS_IFLOW;
976 		usb2_com_modem(tp, SER_RTS, 0);
977 	}
978 done:
979 	if (error) {
980 		if (opened) {
981 			usb2_com_close(tp);
982 		}
983 	}
984 	return (error);
985 }
986 
987 static void
988 usb2_com_outwakeup(struct tty *tp)
989 {
990 	struct usb2_com_softc *sc = tty_softc(tp);
991 
992 	mtx_assert(sc->sc_mtx, MA_OWNED);
993 
994 	DPRINTF("sc = %p\n", sc);
995 
996 	if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) {
997 		/* The higher layer is not ready */
998 		return;
999 	}
1000 	sc->sc_flag |= UCOM_FLAG_WR_START;
1001 
1002 	usb2_com_start_transfers(sc);
1003 }
1004 
1005 /*------------------------------------------------------------------------*
1006  *	usb2_com_get_data
1007  *
1008  * Return values:
1009  * 0: No data is available.
1010  * Else: Data is available.
1011  *------------------------------------------------------------------------*/
1012 uint8_t
1013 usb2_com_get_data(struct usb2_com_softc *sc, struct usb2_page_cache *pc,
1014     uint32_t offset, uint32_t len, uint32_t *actlen)
1015 {
1016 	struct usb2_page_search res;
1017 	struct tty *tp = sc->sc_tty;
1018 	uint32_t cnt;
1019 	uint32_t offset_orig;
1020 
1021 	mtx_assert(sc->sc_mtx, MA_OWNED);
1022 
1023 	if ((!(sc->sc_flag & UCOM_FLAG_HL_READY)) ||
1024 	    (!(sc->sc_flag & UCOM_FLAG_GP_DATA)) ||
1025 	    (!(sc->sc_flag & UCOM_FLAG_WR_START))) {
1026 		actlen[0] = 0;
1027 		return (0);		/* multiport device polling */
1028 	}
1029 	offset_orig = offset;
1030 
1031 	while (len != 0) {
1032 
1033 		usb2_get_page(pc, offset, &res);
1034 
1035 		if (res.length > len) {
1036 			res.length = len;
1037 		}
1038 		/* copy data directly into USB buffer */
1039 		cnt = ttydisc_getc(tp, res.buffer, res.length);
1040 
1041 		offset += cnt;
1042 		len -= cnt;
1043 
1044 		if (cnt < res.length) {
1045 			/* end of buffer */
1046 			break;
1047 		}
1048 	}
1049 
1050 	actlen[0] = offset - offset_orig;
1051 
1052 	DPRINTF("cnt=%d\n", actlen[0]);
1053 
1054 	if (actlen[0] == 0) {
1055 		return (0);
1056 	}
1057 	return (1);
1058 }
1059 
1060 void
1061 usb2_com_put_data(struct usb2_com_softc *sc, struct usb2_page_cache *pc,
1062     uint32_t offset, uint32_t len)
1063 {
1064 	struct usb2_page_search res;
1065 	struct tty *tp = sc->sc_tty;
1066 	char *buf;
1067 	uint32_t cnt;
1068 
1069 	mtx_assert(sc->sc_mtx, MA_OWNED);
1070 
1071 	if ((!(sc->sc_flag & UCOM_FLAG_HL_READY)) ||
1072 	    (!(sc->sc_flag & UCOM_FLAG_GP_DATA))) {
1073 		return;			/* multiport device polling */
1074 	}
1075 	if (len == 0)
1076 		return;			/* no data */
1077 
1078 	/* set a flag to prevent recursation ? */
1079 
1080 	while (len > 0) {
1081 
1082 		usb2_get_page(pc, offset, &res);
1083 
1084 		if (res.length > len) {
1085 			res.length = len;
1086 		}
1087 		len -= res.length;
1088 		offset += res.length;
1089 
1090 		/* pass characters to tty layer */
1091 
1092 		buf = res.buffer;
1093 		cnt = res.length;
1094 
1095 		/* first check if we can pass the buffer directly */
1096 
1097 		if (ttydisc_can_bypass(tp)) {
1098 			if (ttydisc_rint_bypass(tp, buf, cnt) != cnt) {
1099 				DPRINTF("tp=%p, data lost\n", tp);
1100 			}
1101 			continue;
1102 		}
1103 		/* need to loop */
1104 
1105 		for (cnt = 0; cnt != res.length; cnt++) {
1106 			if (ttydisc_rint(tp, buf[cnt], 0) == -1) {
1107 				/* XXX what should we do? */
1108 
1109 				DPRINTF("tp=%p, lost %d "
1110 				    "chars\n", tp, res.length - cnt);
1111 				break;
1112 			}
1113 		}
1114 	}
1115 	ttydisc_rint_done(tp);
1116 }
1117 
1118 static void
1119 usb2_com_free(void *xsc)
1120 {
1121 	struct usb2_com_softc *sc = xsc;
1122 
1123 	mtx_lock(sc->sc_mtx);
1124 	sc->sc_ttyfreed = 1;
1125 	usb2_cv_signal(&sc->sc_cv);
1126 	mtx_unlock(sc->sc_mtx);
1127 }
1128