xref: /netbsd-src/sys/dev/usb/ubsa_common.c (revision 0ee61f5593551c5336fe269066af755da9498c3e)
1*0ee61f55Smlelstv /*	$NetBSD: ubsa_common.c,v 1.15 2021/06/13 09:29:38 mlelstv Exp $	*/
2817e003aSichiro /*-
3817e003aSichiro  * Copyright (c) 2002, Alexander Kabaev <kan.FreeBSD.org>.
4817e003aSichiro  * All rights reserved.
5817e003aSichiro  *
6817e003aSichiro  * Redistribution and use in source and binary forms, with or without
7817e003aSichiro  * modification, are permitted provided that the following conditions
8817e003aSichiro  * are met:
9817e003aSichiro  * 1. Redistributions of source code must retain the above copyright
10817e003aSichiro  *    notice, this list of conditions and the following disclaimer.
11817e003aSichiro  * 2. Redistributions in binary form must reproduce the above copyright
12817e003aSichiro  *    notice, this list of conditions and the following disclaimer in the
13817e003aSichiro  *    documentation and/or other materials provided with the distribution.
14817e003aSichiro  *
15817e003aSichiro  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16817e003aSichiro  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17817e003aSichiro  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18817e003aSichiro  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19817e003aSichiro  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20817e003aSichiro  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21817e003aSichiro  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22817e003aSichiro  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23817e003aSichiro  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24817e003aSichiro  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25817e003aSichiro  * SUCH DAMAGE.
26817e003aSichiro  */
27817e003aSichiro /*
28817e003aSichiro  * Copyright (c) 2001 The NetBSD Foundation, Inc.
29817e003aSichiro  * All rights reserved.
30817e003aSichiro  *
31817e003aSichiro  * This code is derived from software contributed to The NetBSD Foundation
32817e003aSichiro  * by Ichiro FUKUHARA (ichiro@ichiro.org).
33817e003aSichiro  *
34817e003aSichiro  * Redistribution and use in source and binary forms, with or without
35817e003aSichiro  * modification, are permitted provided that the following conditions
36817e003aSichiro  * are met:
37817e003aSichiro  * 1. Redistributions of source code must retain the above copyright
38817e003aSichiro  *    notice, this list of conditions and the following disclaimer.
39817e003aSichiro  * 2. Redistributions in binary form must reproduce the above copyright
40817e003aSichiro  *    notice, this list of conditions and the following disclaimer in the
41817e003aSichiro  *    documentation and/or other materials provided with the distribution.
42817e003aSichiro  *
43817e003aSichiro  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
44817e003aSichiro  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
45817e003aSichiro  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
46817e003aSichiro  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
47817e003aSichiro  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
48817e003aSichiro  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
49817e003aSichiro  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
50817e003aSichiro  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
51817e003aSichiro  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
52817e003aSichiro  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
53817e003aSichiro  * POSSIBILITY OF SUCH DAMAGE.
54817e003aSichiro  */
55817e003aSichiro 
56817e003aSichiro #include <sys/cdefs.h>
57*0ee61f55Smlelstv __KERNEL_RCSID(0, "$NetBSD: ubsa_common.c,v 1.15 2021/06/13 09:29:38 mlelstv Exp $");
58817e003aSichiro 
59817e003aSichiro #include <sys/param.h>
60817e003aSichiro #include <sys/systm.h>
61817e003aSichiro #include <sys/kernel.h>
624e8e6643Sskrll #include <sys/kmem.h>
63817e003aSichiro #include <sys/ioccom.h>
64817e003aSichiro #include <sys/fcntl.h>
65817e003aSichiro #include <sys/conf.h>
66817e003aSichiro #include <sys/tty.h>
67817e003aSichiro #include <sys/file.h>
68817e003aSichiro #include <sys/select.h>
69817e003aSichiro #include <sys/proc.h>
70817e003aSichiro #include <sys/device.h>
71817e003aSichiro #include <sys/poll.h>
72817e003aSichiro #include <sys/sysctl.h>
73817e003aSichiro #include <sys/bus.h>
74817e003aSichiro 
75817e003aSichiro #include <dev/usb/usb.h>
76817e003aSichiro #include <dev/usb/usbdi.h>
77817e003aSichiro #include <dev/usb/usbdi_util.h>
78817e003aSichiro #include <dev/usb/usbdivar.h>
79817e003aSichiro 
80817e003aSichiro #include <dev/usb/usbcdc.h>
81817e003aSichiro #include <dev/usb/usbdevs.h>
82817e003aSichiro #include <dev/usb/usb_quirks.h>
83817e003aSichiro #include <dev/usb/ucomvar.h>
84817e003aSichiro #include <dev/usb/ubsavar.h>
85817e003aSichiro 
86817e003aSichiro #ifdef UBSA_DEBUG
87817e003aSichiro extern	int	ubsadebug;
88817e003aSichiro #define	DPRINTFN(n, x)	do { \
89817e003aSichiro 				if (ubsadebug > (n)) \
9049337c88Sdyoung 					printf x; \
91817e003aSichiro 			} while (0)
92817e003aSichiro #else
93817e003aSichiro #define	DPRINTFN(n, x)
94817e003aSichiro #endif
95817e003aSichiro #define	DPRINTF(x) DPRINTFN(0, x)
96817e003aSichiro 
972e9fa9ffSichiro int
ubsa_request(struct ubsa_softc * sc,int portno,uint8_t request,uint16_t value)984e8e6643Sskrll ubsa_request(struct ubsa_softc *sc, int portno, uint8_t request, uint16_t value)
99817e003aSichiro {
100817e003aSichiro 	usb_device_request_t req;
101817e003aSichiro 	usbd_status err;
102817e003aSichiro 
103817e003aSichiro 	if (sc->sc_quadumts)
104817e003aSichiro 		req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
105817e003aSichiro 	else
106817e003aSichiro 		req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
107817e003aSichiro 
1085d8b710dSmsaitoh 	if (portno >= UBSA_MAXCONN) {
109817e003aSichiro 		printf("%s: ubsa_request: invalid port(%d)#\n",
11049337c88Sdyoung 			device_xname(sc->sc_dev), portno);
111817e003aSichiro 		return USBD_INVAL;
112817e003aSichiro 	}
113817e003aSichiro 
114817e003aSichiro 	req.bRequest = request;
115817e003aSichiro 	USETW(req.wValue, value);
116817e003aSichiro 	USETW(req.wIndex, sc->sc_iface_number[portno]);
117817e003aSichiro 	USETW(req.wLength, 0);
118817e003aSichiro 
119817e003aSichiro 	err = usbd_do_request(sc->sc_udev, &req, 0);
120817e003aSichiro 	if (err)
121817e003aSichiro 		printf("%s: ubsa_request: %s\n",
12249337c88Sdyoung 		    device_xname(sc->sc_dev), usbd_errstr(err));
1234e8e6643Sskrll 	return err;
124817e003aSichiro }
125817e003aSichiro 
1262e9fa9ffSichiro void
ubsa_dtr(struct ubsa_softc * sc,int portno,int onoff)127817e003aSichiro ubsa_dtr(struct ubsa_softc *sc, int portno, int onoff)
128817e003aSichiro {
129817e003aSichiro 
130817e003aSichiro 	DPRINTF(("ubsa_dtr: onoff = %d\n", onoff));
131817e003aSichiro 
132817e003aSichiro 	if (sc->sc_dtr == onoff)
133817e003aSichiro 		return;
134817e003aSichiro 	sc->sc_dtr = onoff;
135817e003aSichiro 
136817e003aSichiro 	ubsa_request(sc, portno, UBSA_SET_DTR, onoff ? 1 : 0);
137817e003aSichiro }
138817e003aSichiro 
1392e9fa9ffSichiro void
ubsa_rts(struct ubsa_softc * sc,int portno,int onoff)140817e003aSichiro ubsa_rts(struct ubsa_softc *sc, int portno, int onoff)
141817e003aSichiro {
142817e003aSichiro 
143817e003aSichiro 	DPRINTF(("ubsa_rts: onoff = %d\n", onoff));
144817e003aSichiro 
145817e003aSichiro 	if (sc->sc_rts == onoff)
146817e003aSichiro 		return;
147817e003aSichiro 	sc->sc_rts = onoff;
148817e003aSichiro 
149817e003aSichiro 	ubsa_request(sc, portno, UBSA_SET_RTS, onoff ? 1 : 0);
150817e003aSichiro }
151817e003aSichiro 
1522e9fa9ffSichiro void
ubsa_quadumts_dtr(struct ubsa_softc * sc,int portno,int onoff)153817e003aSichiro ubsa_quadumts_dtr(struct ubsa_softc *sc, int portno, int onoff)
154817e003aSichiro {
155817e003aSichiro 
156817e003aSichiro 	DPRINTF(("ubsa_dtr: onoff = %d\n", onoff));
157817e003aSichiro 
158817e003aSichiro 	if (sc->sc_dtr == onoff)
159817e003aSichiro 		return;
160817e003aSichiro 	sc->sc_dtr = onoff;
161817e003aSichiro 
162817e003aSichiro 	ubsa_request(sc, portno, UBSA_QUADUMTS_SET_PIN,
163817e003aSichiro 		 (sc->sc_rts ? 2 : 0)+(sc->sc_dtr ? 1 : 0));
164817e003aSichiro }
165817e003aSichiro 
1662e9fa9ffSichiro void
ubsa_quadumts_rts(struct ubsa_softc * sc,int portno,int onoff)167817e003aSichiro ubsa_quadumts_rts(struct ubsa_softc *sc, int portno, int onoff)
168817e003aSichiro {
169817e003aSichiro 
170817e003aSichiro 	DPRINTF(("ubsa_rts: onoff = %d\n", onoff));
171817e003aSichiro 
172817e003aSichiro 	if (sc->sc_rts == onoff)
173817e003aSichiro 		return;
174817e003aSichiro 	sc->sc_rts = onoff;
175817e003aSichiro 
176817e003aSichiro 	ubsa_request(sc, portno, UBSA_QUADUMTS_SET_PIN,
177817e003aSichiro 		 (sc->sc_rts ? 2 : 0)+(sc->sc_dtr ? 1 : 0));
178817e003aSichiro }
179817e003aSichiro 
1802e9fa9ffSichiro void
ubsa_break(struct ubsa_softc * sc,int portno,int onoff)181817e003aSichiro ubsa_break(struct ubsa_softc *sc, int portno, int onoff)
182817e003aSichiro {
183817e003aSichiro 	DPRINTF(("ubsa_rts: onoff = %d\n", onoff));
184817e003aSichiro 
185cc0cad1eSmrg 	if (sc->sc_dying)
186cc0cad1eSmrg 		return;
187cc0cad1eSmrg 
188817e003aSichiro 	ubsa_request(sc, portno, UBSA_SET_BREAK, onoff ? 1 : 0);
189817e003aSichiro }
190817e003aSichiro 
1912e9fa9ffSichiro void
ubsa_set(void * addr,int portno,int reg,int onoff)192817e003aSichiro ubsa_set(void *addr, int portno, int reg, int onoff)
193817e003aSichiro {
194cc0cad1eSmrg 	struct ubsa_softc *sc = addr;
195817e003aSichiro 
196cc0cad1eSmrg 	if (sc->sc_dying)
197cc0cad1eSmrg 		return;
198cc0cad1eSmrg 
199817e003aSichiro 	switch (reg) {
200817e003aSichiro 	case UCOM_SET_DTR:
201817e003aSichiro 		if (sc->sc_quadumts)
202817e003aSichiro 			ubsa_quadumts_dtr(sc, portno, onoff);
203817e003aSichiro 		else
204817e003aSichiro 			ubsa_dtr(sc, portno, onoff);
205817e003aSichiro 		break;
206817e003aSichiro 	case UCOM_SET_RTS:
207817e003aSichiro 		if (sc->sc_quadumts)
208817e003aSichiro 			ubsa_quadumts_rts(sc, portno, onoff);
209817e003aSichiro 		else
210817e003aSichiro 			ubsa_rts(sc, portno, onoff);
211817e003aSichiro 		break;
212817e003aSichiro 	case UCOM_SET_BREAK:
213817e003aSichiro 		if (!sc->sc_quadumts)
214817e003aSichiro 			ubsa_break(sc, portno, onoff);
215817e003aSichiro 		break;
216817e003aSichiro 	default:
217817e003aSichiro 		break;
218817e003aSichiro 	}
219817e003aSichiro }
220817e003aSichiro 
2212e9fa9ffSichiro void
ubsa_baudrate(struct ubsa_softc * sc,int portno,speed_t speed)222817e003aSichiro ubsa_baudrate(struct ubsa_softc *sc, int portno, speed_t speed)
223817e003aSichiro {
2244e8e6643Sskrll 	uint16_t value = 0;
225817e003aSichiro 
226817e003aSichiro 	DPRINTF(("ubsa_baudrate: speed = %d\n", speed));
227817e003aSichiro 
228817e003aSichiro 	switch(speed) {
229817e003aSichiro 	case B0:
230817e003aSichiro 		break;
231817e003aSichiro 	case B300:
232817e003aSichiro 	case B600:
233817e003aSichiro 	case B1200:
234817e003aSichiro 	case B2400:
235817e003aSichiro 	case B4800:
236817e003aSichiro 	case B9600:
237817e003aSichiro 	case B19200:
238817e003aSichiro 	case B38400:
239817e003aSichiro 	case B57600:
240817e003aSichiro 	case B115200:
241817e003aSichiro 	case B230400:
242817e003aSichiro 		value = B230400 / speed;
243817e003aSichiro 		break;
244817e003aSichiro 	default:
245817e003aSichiro 		printf("%s: ubsa_param: unsupported baudrate, "
246817e003aSichiro 		    "forcing default of 9600\n",
24749337c88Sdyoung 		    device_xname(sc->sc_dev));
248817e003aSichiro 		value = B230400 / B9600;
249817e003aSichiro 		break;
250817e003aSichiro 	};
251817e003aSichiro 
252817e003aSichiro 	if (speed == B0) {
253817e003aSichiro 		ubsa_flow(sc, portno, 0, 0);
254817e003aSichiro 		ubsa_dtr(sc, portno, 0);
255817e003aSichiro 		ubsa_rts(sc, portno, 0);
256817e003aSichiro 	} else
257817e003aSichiro 		ubsa_request(sc, portno, UBSA_SET_BAUDRATE, value);
258817e003aSichiro }
259817e003aSichiro 
2602e9fa9ffSichiro void
ubsa_parity(struct ubsa_softc * sc,int portno,tcflag_t cflag)261817e003aSichiro ubsa_parity(struct ubsa_softc *sc, int portno, tcflag_t cflag)
262817e003aSichiro {
263817e003aSichiro 	int value;
264817e003aSichiro 
265d3dde16cSchristos 	DPRINTF(("ubsa_parity: cflag = %#x\n", cflag));
266817e003aSichiro 
267817e003aSichiro 	if (cflag & PARENB)
268817e003aSichiro 		value = (cflag & PARODD) ? UBSA_PARITY_ODD : UBSA_PARITY_EVEN;
269817e003aSichiro 	else
270817e003aSichiro 		value = UBSA_PARITY_NONE;
271817e003aSichiro 
272817e003aSichiro 	ubsa_request(sc, portno, UBSA_SET_PARITY, value);
273817e003aSichiro }
274817e003aSichiro 
2752e9fa9ffSichiro void
ubsa_databits(struct ubsa_softc * sc,int portno,tcflag_t cflag)276817e003aSichiro ubsa_databits(struct ubsa_softc *sc, int portno, tcflag_t cflag)
277817e003aSichiro {
278817e003aSichiro 	int value;
279817e003aSichiro 
280d3dde16cSchristos 	DPRINTF(("ubsa_databits: cflag = %#x\n", cflag));
281817e003aSichiro 
282817e003aSichiro 	switch (cflag & CSIZE) {
283817e003aSichiro 	case CS5: value = 0; break;
284817e003aSichiro 	case CS6: value = 1; break;
285817e003aSichiro 	case CS7: value = 2; break;
286817e003aSichiro 	case CS8: value = 3; break;
287817e003aSichiro 	default:
288817e003aSichiro 		printf("%s: ubsa_param: unsupported databits requested, "
289817e003aSichiro 		    "forcing default of 8\n",
29049337c88Sdyoung 		    device_xname(sc->sc_dev));
291817e003aSichiro 		value = 3;
292817e003aSichiro 	}
293817e003aSichiro 
294817e003aSichiro 	ubsa_request(sc, portno, UBSA_SET_DATA_BITS, value);
295817e003aSichiro }
296817e003aSichiro 
2972e9fa9ffSichiro void
ubsa_stopbits(struct ubsa_softc * sc,int portno,tcflag_t cflag)298817e003aSichiro ubsa_stopbits(struct ubsa_softc *sc, int portno, tcflag_t cflag)
299817e003aSichiro {
300817e003aSichiro 	int value;
301817e003aSichiro 
302d3dde16cSchristos 	DPRINTF(("ubsa_stopbits: cflag = %#x\n", cflag));
303817e003aSichiro 
304817e003aSichiro 	value = (cflag & CSTOPB) ? 1 : 0;
305817e003aSichiro 
306817e003aSichiro 	ubsa_request(sc, portno, UBSA_SET_STOP_BITS, value);
307817e003aSichiro }
308817e003aSichiro 
3092e9fa9ffSichiro void
ubsa_flow(struct ubsa_softc * sc,int portno,tcflag_t cflag,tcflag_t iflag)310817e003aSichiro ubsa_flow(struct ubsa_softc *sc, int portno, tcflag_t cflag, tcflag_t iflag)
311817e003aSichiro {
312817e003aSichiro 	int value;
313817e003aSichiro 
314d3dde16cSchristos 	DPRINTF(("ubsa_flow: cflag = %#x, iflag = %#x\n", cflag, iflag));
315817e003aSichiro 
316817e003aSichiro 	value = 0;
317817e003aSichiro 	if (cflag & CRTSCTS)
318817e003aSichiro 		value |= UBSA_FLOW_OCTS | UBSA_FLOW_IRTS;
319*0ee61f55Smlelstv 	if (iflag & IXOFF)
320*0ee61f55Smlelstv 		value |= UBSA_FLOW_OXON;
321*0ee61f55Smlelstv 	if (iflag & IXON)
322*0ee61f55Smlelstv 		value |= UBSA_FLOW_IXON;
323817e003aSichiro 
324817e003aSichiro 	ubsa_request(sc, portno, UBSA_SET_FLOW_CTRL, value);
325817e003aSichiro }
326817e003aSichiro 
3272e9fa9ffSichiro int
ubsa_param(void * addr,int portno,struct termios * ti)328817e003aSichiro ubsa_param(void *addr, int portno, struct termios *ti)
329817e003aSichiro {
330817e003aSichiro 	struct ubsa_softc *sc = addr;
331817e003aSichiro 
332cc0cad1eSmrg 	if (sc->sc_dying)
333cc0cad1eSmrg 		return EIO;
334cc0cad1eSmrg 
335817e003aSichiro 	DPRINTF(("ubsa_param: sc = %p\n", sc));
336817e003aSichiro 
337817e003aSichiro 	if (!sc->sc_quadumts) {
338817e003aSichiro 		ubsa_baudrate(sc, portno, ti->c_ospeed);
339817e003aSichiro 		ubsa_parity(sc, portno, ti->c_cflag);
340817e003aSichiro 		ubsa_databits(sc, portno, ti->c_cflag);
341817e003aSichiro 		ubsa_stopbits(sc, portno, ti->c_cflag);
342817e003aSichiro 		ubsa_flow(sc, portno, ti->c_cflag, ti->c_iflag);
343817e003aSichiro 	}
344817e003aSichiro 
3454e8e6643Sskrll 	return 0;
346817e003aSichiro }
347817e003aSichiro 
3482e9fa9ffSichiro int
ubsa_open(void * addr,int portno)349817e003aSichiro ubsa_open(void *addr, int portno)
350817e003aSichiro {
351817e003aSichiro 	struct ubsa_softc *sc = addr;
352817e003aSichiro 	int err;
353817e003aSichiro 
354817e003aSichiro 	if (sc->sc_dying)
355cc0cad1eSmrg 		return EIO;
356817e003aSichiro 
357817e003aSichiro 	if (sc->sc_intr_number != -1 && sc->sc_intr_pipe == NULL) {
3584e8e6643Sskrll 		sc->sc_intr_buf = kmem_alloc(sc->sc_isize, KM_SLEEP);
359817e003aSichiro 		/* XXX only iface# = 0 has intr line */
360817e003aSichiro 		/* XXX E220 specific? need to check */
361817e003aSichiro 		err = usbd_open_pipe_intr(sc->sc_iface[0],
362817e003aSichiro 		    sc->sc_intr_number,
363817e003aSichiro 		    USBD_SHORT_XFER_OK,
364817e003aSichiro 		    &sc->sc_intr_pipe,
365817e003aSichiro 		    sc,
366817e003aSichiro 		    sc->sc_intr_buf,
367817e003aSichiro 		    sc->sc_isize,
368817e003aSichiro 		    ubsa_intr,
369817e003aSichiro 		    UBSA_INTR_INTERVAL);
370817e003aSichiro 		if (err) {
371817e003aSichiro 			printf("%s: cannot open interrupt pipe (addr %d)\n",
37249337c88Sdyoung 			    device_xname(sc->sc_dev),
373817e003aSichiro 			    sc->sc_intr_number);
3744e8e6643Sskrll 			return EIO;
375817e003aSichiro 		}
376817e003aSichiro 	}
377817e003aSichiro 
3784e8e6643Sskrll 	return 0;
379817e003aSichiro }
380817e003aSichiro 
3812e9fa9ffSichiro void
ubsa_close_pipe(struct ubsa_softc * sc)382cc0cad1eSmrg ubsa_close_pipe(struct ubsa_softc *sc)
383cc0cad1eSmrg {
384cc0cad1eSmrg 
385cc0cad1eSmrg 	if (sc->sc_intr_pipe != NULL) {
386cc0cad1eSmrg 		usbd_abort_pipe(sc->sc_intr_pipe);
387cc0cad1eSmrg 		usbd_close_pipe(sc->sc_intr_pipe);
388cc0cad1eSmrg 		sc->sc_intr_pipe = NULL;
389cc0cad1eSmrg 	}
390cc0cad1eSmrg 	if (sc->sc_intr_buf) {
391cc0cad1eSmrg 		kmem_free(sc->sc_intr_buf, sc->sc_isize);
392cc0cad1eSmrg 		sc->sc_intr_buf = NULL;
393cc0cad1eSmrg 	}
394cc0cad1eSmrg }
395cc0cad1eSmrg 
396cc0cad1eSmrg void
ubsa_close(void * addr,int portno)397817e003aSichiro ubsa_close(void *addr, int portno)
398817e003aSichiro {
399817e003aSichiro 	struct ubsa_softc *sc = addr;
400cc0cad1eSmrg 
401cc0cad1eSmrg 	DPRINTF(("ubsa_close: close\n"));
402817e003aSichiro 
403817e003aSichiro 	if (sc->sc_dying)
404817e003aSichiro 		return;
405817e003aSichiro 
406cc0cad1eSmrg 	ubsa_close_pipe(sc);
407817e003aSichiro }
408817e003aSichiro 
4092e9fa9ffSichiro void
ubsa_intr(struct usbd_xfer * xfer,void * priv,usbd_status status)4104e8e6643Sskrll ubsa_intr(struct usbd_xfer *xfer, void *priv,
411817e003aSichiro     usbd_status status)
412817e003aSichiro {
413817e003aSichiro 	struct ubsa_softc *sc = priv;
414817e003aSichiro 	u_char *buf;
415817e003aSichiro 	int i;
416817e003aSichiro 
417817e003aSichiro 	buf = sc->sc_intr_buf;
418817e003aSichiro 	if (sc->sc_dying)
419817e003aSichiro 		return;
420817e003aSichiro 
421817e003aSichiro 	if (status != USBD_NORMAL_COMPLETION) {
422817e003aSichiro 		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
423817e003aSichiro 			return;
424817e003aSichiro 
425817e003aSichiro 		DPRINTF(("%s: ubsa_intr: abnormal status: %s\n",
42649337c88Sdyoung 		    device_xname(sc->sc_dev), usbd_errstr(status)));
427817e003aSichiro 		usbd_clear_endpoint_stall_async(sc->sc_intr_pipe);
428817e003aSichiro 		return;
429817e003aSichiro 	}
430817e003aSichiro 
431817e003aSichiro 	/* incidentally, Belkin adapter status bits match UART 16550 bits */
432817e003aSichiro 	sc->sc_lsr = buf[2];
433817e003aSichiro 	sc->sc_msr = buf[3];
434817e003aSichiro 
435aa3d6ec1Schristos 	DPRINTF(("%s: ubsa lsr = 0x%02x, msr = 0x%02x\n",
43649337c88Sdyoung 	    device_xname(sc->sc_dev), sc->sc_lsr, sc->sc_msr));
437817e003aSichiro 
438817e003aSichiro 	for (i = 0; i < sc->sc_numif; i++) {
4393624455eScube 		ucom_status_change(device_private(sc->sc_subdevs[i]));
440817e003aSichiro 	}
441817e003aSichiro }
442817e003aSichiro 
4432e9fa9ffSichiro void
ubsa_get_status(void * addr,int portno,u_char * lsr,u_char * msr)444817e003aSichiro ubsa_get_status(void *addr, int portno, u_char *lsr, u_char *msr)
445817e003aSichiro {
446817e003aSichiro 	struct ubsa_softc *sc = addr;
447817e003aSichiro 
448817e003aSichiro 	DPRINTF(("ubsa_get_status\n"));
449817e003aSichiro 
450817e003aSichiro 	*lsr = sc->sc_lsr;
451817e003aSichiro 	*msr = sc->sc_msr;
452817e003aSichiro }
453817e003aSichiro 
454