xref: /freebsd/sys/dev/usb/serial/umct.c (revision 13ea0450a9c8742119d36f3bf8f47accdce46e54)
1 #include <sys/cdefs.h>
2 __FBSDID("$FreeBSD$");
3 
4 /*-
5  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
6  *
7  * Copyright (c) 2003 Scott Long
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  *
31  */
32 
33 /*
34  * Driver for the MCT (Magic Control Technology) USB-RS232 Converter.
35  * Based on the superb documentation from the linux mct_u232 driver by
36  * Wolfgang Grandeggar <wolfgang@cec.ch>.
37  * This device smells a lot like the Belkin F5U103, except that it has
38  * suffered some mild brain-damage.  This driver is based off of the ubsa.c
39  * driver from Alexander Kabaev <kan@FreeBSD.org>.  Merging the two together
40  * might be useful, though the subtle differences might lead to lots of
41  * #ifdef's.
42  */
43 
44 /*
45  * NOTE: all function names beginning like "umct_cfg_" can only
46  * be called from within the config thread function !
47  */
48 
49 #include <sys/stdint.h>
50 #include <sys/stddef.h>
51 #include <sys/param.h>
52 #include <sys/queue.h>
53 #include <sys/types.h>
54 #include <sys/systm.h>
55 #include <sys/kernel.h>
56 #include <sys/bus.h>
57 #include <sys/module.h>
58 #include <sys/lock.h>
59 #include <sys/mutex.h>
60 #include <sys/condvar.h>
61 #include <sys/sysctl.h>
62 #include <sys/sx.h>
63 #include <sys/unistd.h>
64 #include <sys/callout.h>
65 #include <sys/malloc.h>
66 #include <sys/priv.h>
67 
68 #include <dev/usb/usb.h>
69 #include <dev/usb/usbdi.h>
70 #include <dev/usb/usbdi_util.h>
71 #include "usbdevs.h"
72 
73 #define	USB_DEBUG_VAR usb_debug
74 #include <dev/usb/usb_debug.h>
75 #include <dev/usb/usb_process.h>
76 
77 #include <dev/usb/serial/usb_serial.h>
78 
79 /* The UMCT advertises the standard 8250 UART registers */
80 #define	UMCT_GET_MSR		2	/* Get Modem Status Register */
81 #define	UMCT_GET_MSR_SIZE	1
82 #define	UMCT_GET_LCR		6	/* Get Line Control Register */
83 #define	UMCT_GET_LCR_SIZE	1
84 #define	UMCT_SET_BAUD		5	/* Set the Baud Rate Divisor */
85 #define	UMCT_SET_BAUD_SIZE	4
86 #define	UMCT_SET_LCR		7	/* Set Line Control Register */
87 #define	UMCT_SET_LCR_SIZE	1
88 #define	UMCT_SET_MCR		10	/* Set Modem Control Register */
89 #define	UMCT_SET_MCR_SIZE	1
90 
91 #define	UMCT_MSR_CTS_CHG	0x01
92 #define	UMCT_MSR_DSR_CHG	0x02
93 #define	UMCT_MSR_RI_CHG		0x04
94 #define	UMCT_MSR_CD_CHG		0x08
95 #define	UMCT_MSR_CTS		0x10
96 #define	UMCT_MSR_RTS		0x20
97 #define	UMCT_MSR_RI		0x40
98 #define	UMCT_MSR_CD		0x80
99 
100 #define	UMCT_INTR_INTERVAL	100
101 #define	UMCT_IFACE_INDEX	0
102 #define	UMCT_CONFIG_INDEX	0
103 
104 enum {
105 	UMCT_BULK_DT_WR,
106 	UMCT_BULK_DT_RD,
107 	UMCT_INTR_DT_RD,
108 	UMCT_N_TRANSFER,
109 };
110 
111 struct umct_softc {
112 	struct ucom_super_softc sc_super_ucom;
113 	struct ucom_softc sc_ucom;
114 
115 	struct usb_device *sc_udev;
116 	struct usb_xfer *sc_xfer[UMCT_N_TRANSFER];
117 	struct mtx sc_mtx;
118 
119 	uint32_t sc_unit;
120 
121 	uint16_t sc_obufsize;
122 
123 	uint8_t	sc_lsr;
124 	uint8_t	sc_msr;
125 	uint8_t	sc_lcr;
126 	uint8_t	sc_mcr;
127 	uint8_t	sc_iface_no;
128 	uint8_t sc_swap_cb;
129 };
130 
131 /* prototypes */
132 
133 static device_probe_t umct_probe;
134 static device_attach_t umct_attach;
135 static device_detach_t umct_detach;
136 static void umct_free_softc(struct umct_softc *);
137 
138 static usb_callback_t umct_intr_callback;
139 static usb_callback_t umct_intr_callback_sub;
140 static usb_callback_t umct_read_callback;
141 static usb_callback_t umct_read_callback_sub;
142 static usb_callback_t umct_write_callback;
143 
144 static void	umct_cfg_do_request(struct umct_softc *sc, uint8_t request,
145 		    uint16_t len, uint32_t value);
146 static void	umct_free(struct ucom_softc *);
147 static void	umct_cfg_get_status(struct ucom_softc *, uint8_t *,
148 		    uint8_t *);
149 static void	umct_cfg_set_break(struct ucom_softc *, uint8_t);
150 static void	umct_cfg_set_dtr(struct ucom_softc *, uint8_t);
151 static void	umct_cfg_set_rts(struct ucom_softc *, uint8_t);
152 static uint8_t	umct_calc_baud(uint32_t);
153 static int	umct_pre_param(struct ucom_softc *, struct termios *);
154 static void	umct_cfg_param(struct ucom_softc *, struct termios *);
155 static void	umct_start_read(struct ucom_softc *);
156 static void	umct_stop_read(struct ucom_softc *);
157 static void	umct_start_write(struct ucom_softc *);
158 static void	umct_stop_write(struct ucom_softc *);
159 static void	umct_poll(struct ucom_softc *ucom);
160 
161 static const struct usb_config umct_config[UMCT_N_TRANSFER] = {
162 
163 	[UMCT_BULK_DT_WR] = {
164 		.type = UE_BULK,
165 		.endpoint = UE_ADDR_ANY,
166 		.direction = UE_DIR_OUT,
167 		.bufsize = 0,	/* use wMaxPacketSize */
168 		.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
169 		.callback = &umct_write_callback,
170 	},
171 
172 	[UMCT_BULK_DT_RD] = {
173 		.type = UE_INTERRUPT,
174 		.endpoint = UE_ADDR_ANY,
175 		.direction = UE_DIR_IN,
176 		.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
177 		.bufsize = 0,	/* use wMaxPacketSize */
178 		.callback = &umct_read_callback,
179 		.ep_index = 0,		/* first interrupt endpoint */
180 	},
181 
182 	[UMCT_INTR_DT_RD] = {
183 		.type = UE_INTERRUPT,
184 		.endpoint = UE_ADDR_ANY,
185 		.direction = UE_DIR_IN,
186 		.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
187 		.bufsize = 0,	/* use wMaxPacketSize */
188 		.callback = &umct_intr_callback,
189 		.ep_index = 1,		/* second interrupt endpoint */
190 	},
191 };
192 
193 static const struct ucom_callback umct_callback = {
194 	.ucom_cfg_get_status = &umct_cfg_get_status,
195 	.ucom_cfg_set_dtr = &umct_cfg_set_dtr,
196 	.ucom_cfg_set_rts = &umct_cfg_set_rts,
197 	.ucom_cfg_set_break = &umct_cfg_set_break,
198 	.ucom_cfg_param = &umct_cfg_param,
199 	.ucom_pre_param = &umct_pre_param,
200 	.ucom_start_read = &umct_start_read,
201 	.ucom_stop_read = &umct_stop_read,
202 	.ucom_start_write = &umct_start_write,
203 	.ucom_stop_write = &umct_stop_write,
204 	.ucom_poll = &umct_poll,
205 	.ucom_free = &umct_free,
206 };
207 
208 static const STRUCT_USB_HOST_ID umct_devs[] = {
209 	{USB_VPI(USB_VENDOR_MCT, USB_PRODUCT_MCT_USB232, 0)},
210 	{USB_VPI(USB_VENDOR_MCT, USB_PRODUCT_MCT_SITECOM_USB232, 0)},
211 	{USB_VPI(USB_VENDOR_MCT, USB_PRODUCT_MCT_DU_H3SP_USB232, 0)},
212 	{USB_VPI(USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5U109, 0)},
213 	{USB_VPI(USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5U409, 0)},
214 };
215 
216 static device_method_t umct_methods[] = {
217 	DEVMETHOD(device_probe, umct_probe),
218 	DEVMETHOD(device_attach, umct_attach),
219 	DEVMETHOD(device_detach, umct_detach),
220 	DEVMETHOD_END
221 };
222 
223 static devclass_t umct_devclass;
224 
225 static driver_t umct_driver = {
226 	.name = "umct",
227 	.methods = umct_methods,
228 	.size = sizeof(struct umct_softc),
229 };
230 
231 DRIVER_MODULE(umct, uhub, umct_driver, umct_devclass, NULL, 0);
232 MODULE_DEPEND(umct, ucom, 1, 1, 1);
233 MODULE_DEPEND(umct, usb, 1, 1, 1);
234 MODULE_VERSION(umct, 1);
235 USB_PNP_HOST_INFO(umct_devs);
236 
237 static int
238 umct_probe(device_t dev)
239 {
240 	struct usb_attach_arg *uaa = device_get_ivars(dev);
241 
242 	if (uaa->usb_mode != USB_MODE_HOST) {
243 		return (ENXIO);
244 	}
245 	if (uaa->info.bConfigIndex != UMCT_CONFIG_INDEX) {
246 		return (ENXIO);
247 	}
248 	if (uaa->info.bIfaceIndex != UMCT_IFACE_INDEX) {
249 		return (ENXIO);
250 	}
251 	return (usbd_lookup_id_by_uaa(umct_devs, sizeof(umct_devs), uaa));
252 }
253 
254 static int
255 umct_attach(device_t dev)
256 {
257 	struct usb_attach_arg *uaa = device_get_ivars(dev);
258 	struct umct_softc *sc = device_get_softc(dev);
259 	int32_t error;
260 	uint16_t maxp;
261 	uint8_t iface_index;
262 
263 	sc->sc_udev = uaa->device;
264 	sc->sc_unit = device_get_unit(dev);
265 
266 	device_set_usb_desc(dev);
267 	mtx_init(&sc->sc_mtx, "umct", NULL, MTX_DEF);
268 	ucom_ref(&sc->sc_super_ucom);
269 
270 	sc->sc_iface_no = uaa->info.bIfaceNum;
271 
272 	iface_index = UMCT_IFACE_INDEX;
273 	error = usbd_transfer_setup(uaa->device, &iface_index,
274 	    sc->sc_xfer, umct_config, UMCT_N_TRANSFER, sc, &sc->sc_mtx);
275 
276 	if (error) {
277 		device_printf(dev, "allocating USB "
278 		    "transfers failed\n");
279 		goto detach;
280 	}
281 
282 	/*
283 	 * The real bulk-in endpoint is also marked as an interrupt.
284 	 * The only way to differentiate it from the real interrupt
285 	 * endpoint is to look at the wMaxPacketSize field.
286 	 */
287 	maxp = usbd_xfer_max_framelen(sc->sc_xfer[UMCT_BULK_DT_RD]);
288 	if (maxp == 0x2) {
289 
290 		/* guessed wrong - switch around endpoints */
291 
292 		struct usb_xfer *temp = sc->sc_xfer[UMCT_INTR_DT_RD];
293 
294 		sc->sc_xfer[UMCT_INTR_DT_RD] = sc->sc_xfer[UMCT_BULK_DT_RD];
295 		sc->sc_xfer[UMCT_BULK_DT_RD] = temp;
296 		sc->sc_swap_cb = 1;
297 	}
298 
299 	sc->sc_obufsize = usbd_xfer_max_len(sc->sc_xfer[UMCT_BULK_DT_WR]);
300 
301 	if (uaa->info.idProduct == USB_PRODUCT_MCT_SITECOM_USB232) {
302 		if (sc->sc_obufsize > 16) {
303 			sc->sc_obufsize = 16;
304 		}
305 	}
306 	error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc,
307 	    &umct_callback, &sc->sc_mtx);
308 	if (error) {
309 		goto detach;
310 	}
311 	ucom_set_pnpinfo_usb(&sc->sc_super_ucom, dev);
312 
313 	return (0);			/* success */
314 
315 detach:
316 	umct_detach(dev);
317 	return (ENXIO);			/* failure */
318 }
319 
320 static int
321 umct_detach(device_t dev)
322 {
323 	struct umct_softc *sc = device_get_softc(dev);
324 
325 	ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
326 	usbd_transfer_unsetup(sc->sc_xfer, UMCT_N_TRANSFER);
327 
328 	device_claim_softc(dev);
329 
330 	umct_free_softc(sc);
331 
332 	return (0);
333 }
334 
335 UCOM_UNLOAD_DRAIN(umct);
336 
337 static void
338 umct_free_softc(struct umct_softc *sc)
339 {
340 	if (ucom_unref(&sc->sc_super_ucom)) {
341 		mtx_destroy(&sc->sc_mtx);
342 		device_free_softc(sc);
343 	}
344 }
345 
346 static void
347 umct_free(struct ucom_softc *ucom)
348 {
349 	umct_free_softc(ucom->sc_parent);
350 }
351 
352 static void
353 umct_cfg_do_request(struct umct_softc *sc, uint8_t request,
354     uint16_t len, uint32_t value)
355 {
356 	struct usb_device_request req;
357 	usb_error_t err;
358 	uint8_t temp[4];
359 
360 	if (len > 4)
361 		len = 4;
362 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
363 	req.bRequest = request;
364 	USETW(req.wValue, 0);
365 	req.wIndex[0] = sc->sc_iface_no;
366 	req.wIndex[1] = 0;
367 	USETW(req.wLength, len);
368 	USETDW(temp, value);
369 
370 	err = ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom,
371 	    &req, temp, 0, 1000);
372 	if (err) {
373 		DPRINTFN(0, "device request failed, err=%s "
374 		    "(ignored)\n", usbd_errstr(err));
375 	}
376 	return;
377 }
378 
379 static void
380 umct_intr_callback_sub(struct usb_xfer *xfer, usb_error_t error)
381 {
382 	struct umct_softc *sc = usbd_xfer_softc(xfer);
383 	struct usb_page_cache *pc;
384 	uint8_t buf[2];
385 	int actlen;
386 
387 	usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
388 
389 	switch (USB_GET_STATE(xfer)) {
390 	case USB_ST_TRANSFERRED:
391 		if (actlen < 2) {
392 			DPRINTF("too short message\n");
393 			goto tr_setup;
394 		}
395 		pc = usbd_xfer_get_frame(xfer, 0);
396 		usbd_copy_out(pc, 0, buf, sizeof(buf));
397 
398 		/*
399 		 * MSR bits need translation from ns16550 to SER_* values.
400 		 * LSR bits are ns16550 in hardware and ucom.
401 		 */
402 		sc->sc_msr = 0;
403 		if (buf[0] & UMCT_MSR_CTS)
404 			sc->sc_msr |= SER_CTS;
405 		if (buf[0] & UMCT_MSR_CD)
406 			sc->sc_msr |= SER_DCD;
407 		if (buf[0] & UMCT_MSR_RI)
408 			sc->sc_msr |= SER_RI;
409 		if (buf[0] & UMCT_MSR_RTS)
410 			sc->sc_msr |= SER_DSR;
411 		sc->sc_lsr = buf[1];
412 
413 		ucom_status_change(&sc->sc_ucom);
414 		/* FALLTHROUGH */
415 	case USB_ST_SETUP:
416 tr_setup:
417 		usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
418 		usbd_transfer_submit(xfer);
419 		return;
420 
421 	default:			/* Error */
422 		if (error != USB_ERR_CANCELLED) {
423 			/* try to clear stall first */
424 			usbd_xfer_set_stall(xfer);
425 			goto tr_setup;
426 		}
427 		return;
428 	}
429 }
430 
431 static void
432 umct_cfg_get_status(struct ucom_softc *ucom, uint8_t *lsr, uint8_t *msr)
433 {
434 	struct umct_softc *sc = ucom->sc_parent;
435 
436 	*lsr = sc->sc_lsr;
437 	*msr = sc->sc_msr;
438 }
439 
440 static void
441 umct_cfg_set_break(struct ucom_softc *ucom, uint8_t onoff)
442 {
443 	struct umct_softc *sc = ucom->sc_parent;
444 
445 	if (onoff)
446 		sc->sc_lcr |= 0x40;
447 	else
448 		sc->sc_lcr &= ~0x40;
449 
450 	umct_cfg_do_request(sc, UMCT_SET_LCR, UMCT_SET_LCR_SIZE, sc->sc_lcr);
451 }
452 
453 static void
454 umct_cfg_set_dtr(struct ucom_softc *ucom, uint8_t onoff)
455 {
456 	struct umct_softc *sc = ucom->sc_parent;
457 
458 	if (onoff)
459 		sc->sc_mcr |= 0x01;
460 	else
461 		sc->sc_mcr &= ~0x01;
462 
463 	umct_cfg_do_request(sc, UMCT_SET_MCR, UMCT_SET_MCR_SIZE, sc->sc_mcr);
464 }
465 
466 static void
467 umct_cfg_set_rts(struct ucom_softc *ucom, uint8_t onoff)
468 {
469 	struct umct_softc *sc = ucom->sc_parent;
470 
471 	if (onoff)
472 		sc->sc_mcr |= 0x02;
473 	else
474 		sc->sc_mcr &= ~0x02;
475 
476 	umct_cfg_do_request(sc, UMCT_SET_MCR, UMCT_SET_MCR_SIZE, sc->sc_mcr);
477 }
478 
479 static uint8_t
480 umct_calc_baud(uint32_t baud)
481 {
482 	switch (baud) {
483 		case B300:return (0x1);
484 	case B600:
485 		return (0x2);
486 	case B1200:
487 		return (0x3);
488 	case B2400:
489 		return (0x4);
490 	case B4800:
491 		return (0x6);
492 	case B9600:
493 		return (0x8);
494 	case B19200:
495 		return (0x9);
496 	case B38400:
497 		return (0xa);
498 	case B57600:
499 		return (0xb);
500 	case 115200:
501 		return (0xc);
502 	case B0:
503 	default:
504 		break;
505 	}
506 	return (0x0);
507 }
508 
509 static int
510 umct_pre_param(struct ucom_softc *ucom, struct termios *t)
511 {
512 	return (0);			/* we accept anything */
513 }
514 
515 static void
516 umct_cfg_param(struct ucom_softc *ucom, struct termios *t)
517 {
518 	struct umct_softc *sc = ucom->sc_parent;
519 	uint32_t value;
520 
521 	value = umct_calc_baud(t->c_ospeed);
522 	umct_cfg_do_request(sc, UMCT_SET_BAUD, UMCT_SET_BAUD_SIZE, value);
523 
524 	value = (sc->sc_lcr & 0x40);
525 
526 	switch (t->c_cflag & CSIZE) {
527 	case CS5:
528 		value |= 0x0;
529 		break;
530 	case CS6:
531 		value |= 0x1;
532 		break;
533 	case CS7:
534 		value |= 0x2;
535 		break;
536 	default:
537 	case CS8:
538 		value |= 0x3;
539 		break;
540 	}
541 
542 	value |= (t->c_cflag & CSTOPB) ? 0x4 : 0;
543 	if (t->c_cflag & PARENB) {
544 		value |= 0x8;
545 		value |= (t->c_cflag & PARODD) ? 0x0 : 0x10;
546 	}
547 	/*
548 	 * XXX There doesn't seem to be a way to tell the device
549 	 * to use flow control.
550 	 */
551 
552 	sc->sc_lcr = value;
553 	umct_cfg_do_request(sc, UMCT_SET_LCR, UMCT_SET_LCR_SIZE, value);
554 }
555 
556 static void
557 umct_start_read(struct ucom_softc *ucom)
558 {
559 	struct umct_softc *sc = ucom->sc_parent;
560 
561 	/* start interrupt endpoint */
562 	usbd_transfer_start(sc->sc_xfer[UMCT_INTR_DT_RD]);
563 
564 	/* start read endpoint */
565 	usbd_transfer_start(sc->sc_xfer[UMCT_BULK_DT_RD]);
566 }
567 
568 static void
569 umct_stop_read(struct ucom_softc *ucom)
570 {
571 	struct umct_softc *sc = ucom->sc_parent;
572 
573 	/* stop interrupt endpoint */
574 	usbd_transfer_stop(sc->sc_xfer[UMCT_INTR_DT_RD]);
575 
576 	/* stop read endpoint */
577 	usbd_transfer_stop(sc->sc_xfer[UMCT_BULK_DT_RD]);
578 }
579 
580 static void
581 umct_start_write(struct ucom_softc *ucom)
582 {
583 	struct umct_softc *sc = ucom->sc_parent;
584 
585 	usbd_transfer_start(sc->sc_xfer[UMCT_BULK_DT_WR]);
586 }
587 
588 static void
589 umct_stop_write(struct ucom_softc *ucom)
590 {
591 	struct umct_softc *sc = ucom->sc_parent;
592 
593 	usbd_transfer_stop(sc->sc_xfer[UMCT_BULK_DT_WR]);
594 }
595 
596 static void
597 umct_read_callback(struct usb_xfer *xfer, usb_error_t error)
598 {
599 	struct umct_softc *sc = usbd_xfer_softc(xfer);
600 
601 	if (sc->sc_swap_cb)
602 		umct_intr_callback_sub(xfer, error);
603 	else
604 		umct_read_callback_sub(xfer, error);
605 }
606 
607 static void
608 umct_intr_callback(struct usb_xfer *xfer, usb_error_t error)
609 {
610 	struct umct_softc *sc = usbd_xfer_softc(xfer);
611 
612 	if (sc->sc_swap_cb)
613 		umct_read_callback_sub(xfer, error);
614 	else
615 		umct_intr_callback_sub(xfer, error);
616 }
617 
618 static void
619 umct_write_callback(struct usb_xfer *xfer, usb_error_t error)
620 {
621 	struct umct_softc *sc = usbd_xfer_softc(xfer);
622 	struct usb_page_cache *pc;
623 	uint32_t actlen;
624 
625 	switch (USB_GET_STATE(xfer)) {
626 	case USB_ST_SETUP:
627 	case USB_ST_TRANSFERRED:
628 tr_setup:
629 		pc = usbd_xfer_get_frame(xfer, 0);
630 		if (ucom_get_data(&sc->sc_ucom, pc, 0,
631 		    sc->sc_obufsize, &actlen)) {
632 
633 			usbd_xfer_set_frame_len(xfer, 0, actlen);
634 			usbd_transfer_submit(xfer);
635 		}
636 		return;
637 
638 	default:			/* Error */
639 		if (error != USB_ERR_CANCELLED) {
640 			/* try to clear stall first */
641 			usbd_xfer_set_stall(xfer);
642 			goto tr_setup;
643 		}
644 		return;
645 	}
646 }
647 
648 static void
649 umct_read_callback_sub(struct usb_xfer *xfer, usb_error_t error)
650 {
651 	struct umct_softc *sc = usbd_xfer_softc(xfer);
652 	struct usb_page_cache *pc;
653 	int actlen;
654 
655 	usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
656 
657 	switch (USB_GET_STATE(xfer)) {
658 	case USB_ST_TRANSFERRED:
659 		pc = usbd_xfer_get_frame(xfer, 0);
660 		ucom_put_data(&sc->sc_ucom, pc, 0, actlen);
661 
662 	case USB_ST_SETUP:
663 tr_setup:
664 		usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
665 		usbd_transfer_submit(xfer);
666 		return;
667 
668 	default:			/* Error */
669 		if (error != USB_ERR_CANCELLED) {
670 			/* try to clear stall first */
671 			usbd_xfer_set_stall(xfer);
672 			goto tr_setup;
673 		}
674 		return;
675 	}
676 }
677 
678 static void
679 umct_poll(struct ucom_softc *ucom)
680 {
681 	struct umct_softc *sc = ucom->sc_parent;
682 	usbd_transfer_poll(sc->sc_xfer, UMCT_N_TRANSFER);
683 }
684