ubser.c revision 189275
1184610Salfred/*-
2189002Sed * Copyright (c) 2004 Bernd Walter <ticso@FreeBSD.org>
3184610Salfred *
4184610Salfred * $URL: https://devel.bwct.de/svn/projects/ubser/ubser.c $
5184610Salfred * $Date: 2004-02-29 01:53:10 +0100 (Sun, 29 Feb 2004) $
6184610Salfred * $Author: ticso $
7184610Salfred * $Rev: 1127 $
8184610Salfred */
9184610Salfred
10184610Salfred/*-
11184610Salfred * Copyright (c) 2001-2002, Shunsuke Akiyama <akiyama@jp.FreeBSD.org>.
12184610Salfred * All rights reserved.
13184610Salfred *
14184610Salfred * Redistribution and use in source and binary forms, with or without
15184610Salfred * modification, are permitted provided that the following conditions
16184610Salfred * are met:
17184610Salfred * 1. Redistributions of source code must retain the above copyright
18184610Salfred *    notice, this list of conditions and the following disclaimer.
19184610Salfred * 2. Redistributions in binary form must reproduce the above copyright
20184610Salfred *    notice, this list of conditions and the following disclaimer in the
21184610Salfred *    documentation and/or other materials provided with the distribution.
22184610Salfred *
23184610Salfred * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24184610Salfred * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25184610Salfred * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26184610Salfred * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
27184610Salfred * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28184610Salfred * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29184610Salfred * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30184610Salfred * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31184610Salfred * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32184610Salfred * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33184610Salfred * SUCH DAMAGE.
34184610Salfred */
35184610Salfred
36184610Salfred/*-
37184610Salfred * Copyright (c) 2000 The NetBSD Foundation, Inc.
38184610Salfred * All rights reserved.
39184610Salfred *
40184610Salfred * This code is derived from software contributed to The NetBSD Foundation
41184610Salfred * by Lennart Augustsson (lennart@augustsson.net).
42184610Salfred *
43184610Salfred * Redistribution and use in source and binary forms, with or without
44184610Salfred * modification, are permitted provided that the following conditions
45184610Salfred * are met:
46184610Salfred * 1. Redistributions of source code must retain the above copyright
47184610Salfred *    notice, this list of conditions and the following disclaimer.
48184610Salfred * 2. Redistributions in binary form must reproduce the above copyright
49184610Salfred *    notice, this list of conditions and the following disclaimer in the
50184610Salfred *    documentation and/or other materials provided with the distribution.
51184610Salfred * 3. All advertising materials mentioning features or use of this software
52184610Salfred *    must display the following acknowledgement:
53184610Salfred *        This product includes software developed by the NetBSD
54184610Salfred *        Foundation, Inc. and its contributors.
55184610Salfred * 4. Neither the name of The NetBSD Foundation nor the names of its
56184610Salfred *    contributors may be used to endorse or promote products derived
57184610Salfred *    from this software without specific prior written permission.
58184610Salfred *
59184610Salfred * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
60184610Salfred * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
61184610Salfred * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
62184610Salfred * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
63184610Salfred * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
64184610Salfred * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
65184610Salfred * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
66184610Salfred * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
67184610Salfred * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
68184610Salfred * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
69184610Salfred * POSSIBILITY OF SUCH DAMAGE.
70184610Salfred */
71184610Salfred
72184610Salfred#include <sys/cdefs.h>
73184610Salfred__FBSDID("$FreeBSD: head/sys/dev/usb/serial/ubser.c 189275 2009-03-02 05:37:05Z thompsa $");
74184610Salfred
75184610Salfred/*
76184610Salfred * BWCT serial adapter driver
77184610Salfred */
78184610Salfred
79188942Sthompsa#include <dev/usb/usb.h>
80188942Sthompsa#include <dev/usb/usb_mfunc.h>
81188942Sthompsa#include <dev/usb/usb_error.h>
82188942Sthompsa#include <dev/usb/usb_cdc.h>
83188942Sthompsa#include <dev/usb/usb_defs.h>
84184610Salfred
85184610Salfred#define	USB_DEBUG_VAR ubser_debug
86184610Salfred
87188942Sthompsa#include <dev/usb/usb_core.h>
88188942Sthompsa#include <dev/usb/usb_debug.h>
89188942Sthompsa#include <dev/usb/usb_process.h>
90188942Sthompsa#include <dev/usb/usb_request.h>
91188942Sthompsa#include <dev/usb/usb_lookup.h>
92188942Sthompsa#include <dev/usb/usb_util.h>
93188942Sthompsa#include <dev/usb/usb_busdma.h>
94188942Sthompsa#include <dev/usb/usb_device.h>
95184610Salfred
96188942Sthompsa#include <dev/usb/serial/usb_serial.h>
97184610Salfred
98184610Salfred#define	UBSER_UNIT_MAX	32
99184610Salfred
100184610Salfred/* Vendor Interface Requests */
101184610Salfred#define	VENDOR_GET_NUMSER		0x01
102184610Salfred#define	VENDOR_SET_BREAK		0x02
103184610Salfred#define	VENDOR_CLEAR_BREAK		0x03
104184610Salfred
105184610Salfred#if USB_DEBUG
106184610Salfredstatic int ubser_debug = 0;
107184610Salfred
108184610SalfredSYSCTL_NODE(_hw_usb2, OID_AUTO, ubser, CTLFLAG_RW, 0, "USB ubser");
109184610SalfredSYSCTL_INT(_hw_usb2_ubser, OID_AUTO, debug, CTLFLAG_RW,
110184610Salfred    &ubser_debug, 0, "ubser debug level");
111184610Salfred#endif
112184610Salfred
113187259Sthompsaenum {
114187259Sthompsa	UBSER_BULK_DT_WR,
115187259Sthompsa	UBSER_BULK_DT_RD,
116188413Sthompsa	UBSER_N_TRANSFER,
117187259Sthompsa};
118184610Salfred
119184610Salfredstruct ubser_softc {
120184610Salfred	struct usb2_com_super_softc sc_super_ucom;
121184610Salfred	struct usb2_com_softc sc_ucom[UBSER_UNIT_MAX];
122184610Salfred
123187259Sthompsa	struct usb2_xfer *sc_xfer[UBSER_N_TRANSFER];
124184610Salfred	struct usb2_device *sc_udev;
125189265Sthompsa	struct mtx sc_mtx;
126184610Salfred
127184610Salfred	uint16_t sc_tx_size;
128184610Salfred
129184610Salfred	uint8_t	sc_numser;
130184610Salfred	uint8_t	sc_iface_no;
131184610Salfred	uint8_t	sc_iface_index;
132184610Salfred	uint8_t	sc_curr_tx_unit;
133184610Salfred	uint8_t	sc_name[16];
134184610Salfred};
135184610Salfred
136184610Salfred/* prototypes */
137184610Salfred
138184610Salfredstatic device_probe_t ubser_probe;
139184610Salfredstatic device_attach_t ubser_attach;
140184610Salfredstatic device_detach_t ubser_detach;
141184610Salfred
142184610Salfredstatic usb2_callback_t ubser_write_callback;
143184610Salfredstatic usb2_callback_t ubser_read_callback;
144184610Salfred
145185948Sthompsastatic int	ubser_pre_param(struct usb2_com_softc *, struct termios *);
146185948Sthompsastatic void	ubser_cfg_set_break(struct usb2_com_softc *, uint8_t);
147185948Sthompsastatic void	ubser_cfg_get_status(struct usb2_com_softc *, uint8_t *,
148185948Sthompsa		    uint8_t *);
149185948Sthompsastatic void	ubser_start_read(struct usb2_com_softc *);
150185948Sthompsastatic void	ubser_stop_read(struct usb2_com_softc *);
151185948Sthompsastatic void	ubser_start_write(struct usb2_com_softc *);
152185948Sthompsastatic void	ubser_stop_write(struct usb2_com_softc *);
153184610Salfred
154187259Sthompsastatic const struct usb2_config ubser_config[UBSER_N_TRANSFER] = {
155184610Salfred
156187259Sthompsa	[UBSER_BULK_DT_WR] = {
157184610Salfred		.type = UE_BULK,
158184610Salfred		.endpoint = UE_ADDR_ANY,
159184610Salfred		.direction = UE_DIR_OUT,
160184610Salfred		.mh.bufsize = 0,	/* use wMaxPacketSize */
161184610Salfred		.mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
162184610Salfred		.mh.callback = &ubser_write_callback,
163184610Salfred	},
164184610Salfred
165187259Sthompsa	[UBSER_BULK_DT_RD] = {
166184610Salfred		.type = UE_BULK,
167184610Salfred		.endpoint = UE_ADDR_ANY,
168184610Salfred		.direction = UE_DIR_IN,
169184610Salfred		.mh.bufsize = 0,	/* use wMaxPacketSize */
170184610Salfred		.mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
171184610Salfred		.mh.callback = &ubser_read_callback,
172184610Salfred	},
173184610Salfred};
174184610Salfred
175184610Salfredstatic const struct usb2_com_callback ubser_callback = {
176184610Salfred	.usb2_com_cfg_set_break = &ubser_cfg_set_break,
177184610Salfred	.usb2_com_cfg_get_status = &ubser_cfg_get_status,
178184610Salfred	.usb2_com_pre_param = &ubser_pre_param,
179184610Salfred	.usb2_com_start_read = &ubser_start_read,
180184610Salfred	.usb2_com_stop_read = &ubser_stop_read,
181184610Salfred	.usb2_com_start_write = &ubser_start_write,
182184610Salfred	.usb2_com_stop_write = &ubser_stop_write,
183184610Salfred};
184184610Salfred
185184610Salfredstatic device_method_t ubser_methods[] = {
186184610Salfred	DEVMETHOD(device_probe, ubser_probe),
187184610Salfred	DEVMETHOD(device_attach, ubser_attach),
188184610Salfred	DEVMETHOD(device_detach, ubser_detach),
189184610Salfred	{0, 0}
190184610Salfred};
191184610Salfred
192184610Salfredstatic devclass_t ubser_devclass;
193184610Salfred
194184610Salfredstatic driver_t ubser_driver = {
195184610Salfred	.name = "ubser",
196184610Salfred	.methods = ubser_methods,
197184610Salfred	.size = sizeof(struct ubser_softc),
198184610Salfred};
199184610Salfred
200189275SthompsaDRIVER_MODULE(ubser, uhub, ubser_driver, ubser_devclass, NULL, 0);
201188942SthompsaMODULE_DEPEND(ubser, ucom, 1, 1, 1);
202188942SthompsaMODULE_DEPEND(ubser, usb, 1, 1, 1);
203184610Salfred
204184610Salfredstatic int
205184610Salfredubser_probe(device_t dev)
206184610Salfred{
207184610Salfred	struct usb2_attach_arg *uaa = device_get_ivars(dev);
208184610Salfred
209184610Salfred	if (uaa->usb2_mode != USB_MODE_HOST) {
210184610Salfred		return (ENXIO);
211184610Salfred	}
212184610Salfred	/* check if this is a BWCT vendor specific ubser interface */
213184610Salfred	if ((strcmp(uaa->device->manufacturer, "BWCT") == 0) &&
214184610Salfred	    (uaa->info.bInterfaceClass == 0xff) &&
215184610Salfred	    (uaa->info.bInterfaceSubClass == 0x00))
216184610Salfred		return (0);
217184610Salfred
218184610Salfred	return (ENXIO);
219184610Salfred}
220184610Salfred
221184610Salfredstatic int
222184610Salfredubser_attach(device_t dev)
223184610Salfred{
224184610Salfred	struct usb2_attach_arg *uaa = device_get_ivars(dev);
225184610Salfred	struct ubser_softc *sc = device_get_softc(dev);
226184610Salfred	struct usb2_device_request req;
227184610Salfred	uint8_t n;
228184610Salfred	int error;
229184610Salfred
230184610Salfred	device_set_usb2_desc(dev);
231189265Sthompsa	mtx_init(&sc->sc_mtx, "ubser", NULL, MTX_DEF);
232184610Salfred
233184610Salfred	snprintf(sc->sc_name, sizeof(sc->sc_name), "%s",
234184610Salfred	    device_get_nameunit(dev));
235184610Salfred
236184610Salfred	sc->sc_iface_no = uaa->info.bIfaceNum;
237184610Salfred	sc->sc_iface_index = uaa->info.bIfaceIndex;
238184610Salfred	sc->sc_udev = uaa->device;
239184610Salfred
240184610Salfred	/* get number of serials */
241184610Salfred	req.bmRequestType = UT_READ_VENDOR_INTERFACE;
242184610Salfred	req.bRequest = VENDOR_GET_NUMSER;
243184610Salfred	USETW(req.wValue, 0);
244184610Salfred	req.wIndex[0] = sc->sc_iface_no;
245184610Salfred	req.wIndex[1] = 0;
246184610Salfred	USETW(req.wLength, 1);
247184610Salfred	error = usb2_do_request_flags
248184610Salfred	    (uaa->device, &Giant, &req, &sc->sc_numser,
249184610Salfred	    0, NULL, USB_DEFAULT_TIMEOUT);
250184610Salfred
251184610Salfred	if (error || (sc->sc_numser == 0)) {
252184610Salfred		device_printf(dev, "failed to get number "
253184610Salfred		    "of serial ports: %s\n",
254184610Salfred		    usb2_errstr(error));
255184610Salfred		goto detach;
256184610Salfred	}
257184610Salfred	if (sc->sc_numser > UBSER_UNIT_MAX)
258184610Salfred		sc->sc_numser = UBSER_UNIT_MAX;
259184610Salfred
260184610Salfred	device_printf(dev, "found %i serials\n", sc->sc_numser);
261184610Salfred
262184610Salfred	error = usb2_transfer_setup(uaa->device, &sc->sc_iface_index,
263189265Sthompsa	    sc->sc_xfer, ubser_config, UBSER_N_TRANSFER, sc, &sc->sc_mtx);
264184610Salfred	if (error) {
265184610Salfred		goto detach;
266184610Salfred	}
267187259Sthompsa	sc->sc_tx_size = sc->sc_xfer[UBSER_BULK_DT_WR]->max_data_length;
268184610Salfred
269184610Salfred	if (sc->sc_tx_size == 0) {
270184610Salfred		DPRINTFN(0, "invalid tx_size!\n");
271184610Salfred		goto detach;
272184610Salfred	}
273184610Salfred	/* initialize port numbers */
274184610Salfred
275184610Salfred	for (n = 0; n < sc->sc_numser; n++) {
276184610Salfred		sc->sc_ucom[n].sc_portno = n;
277184610Salfred	}
278184610Salfred
279184610Salfred	error = usb2_com_attach(&sc->sc_super_ucom, sc->sc_ucom,
280189265Sthompsa	    sc->sc_numser, sc, &ubser_callback, &sc->sc_mtx);
281184610Salfred	if (error) {
282184610Salfred		goto detach;
283184610Salfred	}
284184610Salfred
285189265Sthompsa	mtx_lock(&sc->sc_mtx);
286188413Sthompsa	usb2_transfer_set_stall(sc->sc_xfer[UBSER_BULK_DT_WR]);
287188413Sthompsa	usb2_transfer_set_stall(sc->sc_xfer[UBSER_BULK_DT_RD]);
288187259Sthompsa	usb2_transfer_start(sc->sc_xfer[UBSER_BULK_DT_RD]);
289189265Sthompsa	mtx_unlock(&sc->sc_mtx);
290184610Salfred
291184610Salfred	return (0);			/* success */
292184610Salfred
293184610Salfreddetach:
294184610Salfred	ubser_detach(dev);
295184610Salfred	return (ENXIO);			/* failure */
296184610Salfred}
297184610Salfred
298184610Salfredstatic int
299184610Salfredubser_detach(device_t dev)
300184610Salfred{
301184610Salfred	struct ubser_softc *sc = device_get_softc(dev);
302184610Salfred
303184610Salfred	DPRINTF("\n");
304184610Salfred
305184610Salfred	usb2_com_detach(&sc->sc_super_ucom, sc->sc_ucom, sc->sc_numser);
306187259Sthompsa	usb2_transfer_unsetup(sc->sc_xfer, UBSER_N_TRANSFER);
307189265Sthompsa	mtx_destroy(&sc->sc_mtx);
308184610Salfred
309184610Salfred	return (0);
310184610Salfred}
311184610Salfred
312184610Salfredstatic int
313184610Salfredubser_pre_param(struct usb2_com_softc *ucom, struct termios *t)
314184610Salfred{
315184610Salfred	DPRINTF("\n");
316184610Salfred
317184610Salfred	/*
318184610Salfred	 * The firmware on our devices can only do 8n1@9600bps
319184610Salfred	 * without handshake.
320184610Salfred	 * We refuse to accept other configurations.
321184610Salfred	 */
322184610Salfred
323184610Salfred	/* ensure 9600bps */
324184610Salfred	switch (t->c_ospeed) {
325184610Salfred	case 9600:
326184610Salfred		break;
327184610Salfred	default:
328184610Salfred		return (EINVAL);
329184610Salfred	}
330184610Salfred
331184610Salfred	/* 2 stop bits not possible */
332184610Salfred	if (t->c_cflag & CSTOPB)
333184610Salfred		return (EINVAL);
334184610Salfred
335184610Salfred	/* XXX parity handling not possible with current firmware */
336184610Salfred	if (t->c_cflag & PARENB)
337184610Salfred		return (EINVAL);
338184610Salfred
339184610Salfred	/* we can only do 8 data bits */
340184610Salfred	switch (t->c_cflag & CSIZE) {
341184610Salfred	case CS8:
342184610Salfred		break;
343184610Salfred	default:
344184610Salfred		return (EINVAL);
345184610Salfred	}
346184610Salfred
347184610Salfred	/* we can't do any kind of hardware handshaking */
348184610Salfred	if ((t->c_cflag &
349184610Salfred	    (CRTS_IFLOW | CDTR_IFLOW | CDSR_OFLOW | CCAR_OFLOW)) != 0)
350184610Salfred		return (EINVAL);
351184610Salfred
352184610Salfred	/*
353184610Salfred	 * XXX xon/xoff not supported by the firmware!
354184610Salfred	 * This is handled within FreeBSD only and may overflow buffers
355184610Salfred	 * because of delayed reaction due to device buffering.
356184610Salfred	 */
357184610Salfred
358184610Salfred	return (0);
359184610Salfred}
360184610Salfred
361184610Salfredstatic __inline void
362184610Salfredubser_inc_tx_unit(struct ubser_softc *sc)
363184610Salfred{
364184610Salfred	sc->sc_curr_tx_unit++;
365184610Salfred	if (sc->sc_curr_tx_unit >= sc->sc_numser) {
366184610Salfred		sc->sc_curr_tx_unit = 0;
367184610Salfred	}
368184610Salfred}
369184610Salfred
370184610Salfredstatic void
371184610Salfredubser_write_callback(struct usb2_xfer *xfer)
372184610Salfred{
373184610Salfred	struct ubser_softc *sc = xfer->priv_sc;
374184610Salfred	uint8_t buf[1];
375184610Salfred	uint8_t first_unit = sc->sc_curr_tx_unit;
376184610Salfred	uint32_t actlen;
377184610Salfred
378184610Salfred	switch (USB_GET_STATE(xfer)) {
379184610Salfred	case USB_ST_SETUP:
380184610Salfred	case USB_ST_TRANSFERRED:
381188413Sthompsatr_setup:
382184610Salfred		do {
383184610Salfred			if (usb2_com_get_data(sc->sc_ucom + sc->sc_curr_tx_unit,
384184610Salfred			    xfer->frbuffers, 1, sc->sc_tx_size - 1,
385184610Salfred			    &actlen)) {
386184610Salfred
387184610Salfred				buf[0] = sc->sc_curr_tx_unit;
388184610Salfred
389184610Salfred				usb2_copy_in(xfer->frbuffers, 0, buf, 1);
390184610Salfred
391184610Salfred				xfer->frlengths[0] = actlen + 1;
392184610Salfred				usb2_start_hardware(xfer);
393184610Salfred
394184610Salfred				ubser_inc_tx_unit(sc);	/* round robin */
395184610Salfred
396184610Salfred				break;
397184610Salfred			}
398184610Salfred			ubser_inc_tx_unit(sc);
399184610Salfred
400184610Salfred		} while (sc->sc_curr_tx_unit != first_unit);
401184610Salfred
402184610Salfred		return;
403184610Salfred
404184610Salfred	default:			/* Error */
405184610Salfred		if (xfer->error != USB_ERR_CANCELLED) {
406188413Sthompsa			/* try to clear stall first */
407188413Sthompsa			xfer->flags.stall_pipe = 1;
408188413Sthompsa			goto tr_setup;
409184610Salfred		}
410184610Salfred		return;
411184610Salfred
412184610Salfred	}
413184610Salfred}
414184610Salfred
415184610Salfredstatic void
416184610Salfredubser_read_callback(struct usb2_xfer *xfer)
417184610Salfred{
418184610Salfred	struct ubser_softc *sc = xfer->priv_sc;
419184610Salfred	uint8_t buf[1];
420184610Salfred
421184610Salfred	switch (USB_GET_STATE(xfer)) {
422184610Salfred	case USB_ST_TRANSFERRED:
423184610Salfred		if (xfer->actlen < 1) {
424184610Salfred			DPRINTF("invalid actlen=0!\n");
425184610Salfred			goto tr_setup;
426184610Salfred		}
427184610Salfred		usb2_copy_out(xfer->frbuffers, 0, buf, 1);
428184610Salfred
429184610Salfred		if (buf[0] >= sc->sc_numser) {
430184610Salfred			DPRINTF("invalid serial number!\n");
431184610Salfred			goto tr_setup;
432184610Salfred		}
433184610Salfred		usb2_com_put_data(sc->sc_ucom + buf[0],
434184610Salfred		    xfer->frbuffers, 1, xfer->actlen - 1);
435184610Salfred
436184610Salfred	case USB_ST_SETUP:
437184610Salfredtr_setup:
438188413Sthompsa		xfer->frlengths[0] = xfer->max_data_length;
439188413Sthompsa		usb2_start_hardware(xfer);
440184610Salfred		return;
441184610Salfred
442184610Salfred	default:			/* Error */
443184610Salfred		if (xfer->error != USB_ERR_CANCELLED) {
444188413Sthompsa			/* try to clear stall first */
445188413Sthompsa			xfer->flags.stall_pipe = 1;
446188413Sthompsa			goto tr_setup;
447184610Salfred		}
448184610Salfred		return;
449184610Salfred
450184610Salfred	}
451184610Salfred}
452184610Salfred
453184610Salfredstatic void
454184610Salfredubser_cfg_set_break(struct usb2_com_softc *ucom, uint8_t onoff)
455184610Salfred{
456184610Salfred	struct ubser_softc *sc = ucom->sc_parent;
457184610Salfred	uint8_t x = ucom->sc_portno;
458184610Salfred	struct usb2_device_request req;
459184610Salfred	usb2_error_t err;
460184610Salfred
461184610Salfred	if (onoff) {
462184610Salfred
463184610Salfred		req.bmRequestType = UT_READ_VENDOR_INTERFACE;
464184610Salfred		req.bRequest = VENDOR_SET_BREAK;
465184610Salfred		req.wValue[0] = x;
466184610Salfred		req.wValue[1] = 0;
467184610Salfred		req.wIndex[0] = sc->sc_iface_no;
468184610Salfred		req.wIndex[1] = 0;
469184610Salfred		USETW(req.wLength, 0);
470184610Salfred
471188413Sthompsa		err = usb2_com_cfg_do_request(sc->sc_udev, ucom,
472188413Sthompsa		    &req, NULL, 0, 1000);
473184610Salfred		if (err) {
474184610Salfred			DPRINTFN(0, "send break failed, error=%s\n",
475184610Salfred			    usb2_errstr(err));
476184610Salfred		}
477184610Salfred	}
478184610Salfred}
479184610Salfred
480184610Salfredstatic void
481184610Salfredubser_cfg_get_status(struct usb2_com_softc *ucom, uint8_t *lsr, uint8_t *msr)
482184610Salfred{
483184610Salfred	/* fake status bits */
484184610Salfred	*lsr = 0;
485184610Salfred	*msr = SER_DCD;
486184610Salfred}
487184610Salfred
488184610Salfredstatic void
489184610Salfredubser_start_read(struct usb2_com_softc *ucom)
490184610Salfred{
491184610Salfred	struct ubser_softc *sc = ucom->sc_parent;
492184610Salfred
493187259Sthompsa	usb2_transfer_start(sc->sc_xfer[UBSER_BULK_DT_RD]);
494184610Salfred}
495184610Salfred
496184610Salfredstatic void
497184610Salfredubser_stop_read(struct usb2_com_softc *ucom)
498184610Salfred{
499184610Salfred	struct ubser_softc *sc = ucom->sc_parent;
500184610Salfred
501187259Sthompsa	usb2_transfer_stop(sc->sc_xfer[UBSER_BULK_DT_RD]);
502184610Salfred}
503184610Salfred
504184610Salfredstatic void
505184610Salfredubser_start_write(struct usb2_com_softc *ucom)
506184610Salfred{
507184610Salfred	struct ubser_softc *sc = ucom->sc_parent;
508184610Salfred
509187259Sthompsa	usb2_transfer_start(sc->sc_xfer[UBSER_BULK_DT_WR]);
510184610Salfred}
511184610Salfred
512184610Salfredstatic void
513184610Salfredubser_stop_write(struct usb2_com_softc *ucom)
514184610Salfred{
515184610Salfred	struct ubser_softc *sc = ucom->sc_parent;
516184610Salfred
517187259Sthompsa	usb2_transfer_stop(sc->sc_xfer[UBSER_BULK_DT_WR]);
518184610Salfred}
519