1 /* $OpenBSD: ubsa.c,v 1.10 2005/03/18 00:33:28 reyk Exp $ */
2 /* $NetBSD: ubsa.c,v 1.5 2002/11/25 00:51:33 fvdl Exp $ */
3 /*-
4 * Copyright (c) 2002, Alexander Kabaev <kan.FreeBSD.org>.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28 /*
29 * Copyright (c) 2001 The NetBSD Foundation, Inc.
30 * All rights reserved.
31 *
32 * This code is derived from software contributed to The NetBSD Foundation
33 * by Ichiro FUKUHARA (ichiro@ichiro.org).
34 *
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
37 * are met:
38 * 1. Redistributions of source code must retain the above copyright
39 * notice, this list of conditions and the following disclaimer.
40 * 2. Redistributions in binary form must reproduce the above copyright
41 * notice, this list of conditions and the following disclaimer in the
42 * documentation and/or other materials provided with the distribution.
43 * 3. All advertising materials mentioning features or use of this software
44 * must display the following acknowledgement:
45 * This product includes software developed by the NetBSD
46 * Foundation, Inc. and its contributors.
47 * 4. Neither the name of The NetBSD Foundation nor the names of its
48 * contributors may be used to endorse or promote products derived
49 * from this software without specific prior written permission.
50 *
51 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
52 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
53 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
54 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
55 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
56 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
57 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
58 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
59 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
60 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
61 * POSSIBILITY OF SUCH DAMAGE.
62 */
63
64 #include <sys/cdefs.h>
65
66 #include <sys/param.h>
67 #include <sys/systm.h>
68 #include <sys/kernel.h>
69 #include <sys/malloc.h>
70 #if defined(__OpenBSD__)
71 #include <sys/device.h>
72 #elif defined(__FreeBSD__)
73 #include <sys/bus.h>
74 #endif
75 #include <sys/ioccom.h>
76 #include <sys/fcntl.h>
77 #include <sys/conf.h>
78 #include <sys/tty.h>
79 #include <sys/file.h>
80 #if __FreeBSD_version >= 500014
81 #include <sys/selinfo.h>
82 #else
83 #include <sys/select.h>
84 #endif
85 #include <sys/proc.h>
86 #include <sys/vnode.h>
87 #include <sys/poll.h>
88 #include <sys/sysctl.h>
89
90 #include <dev/usb/usb.h>
91 #include <dev/usb/usbcdc.h>
92
93 #include <dev/usb/usbdi.h>
94 #include <dev/usb/usbdi_util.h>
95 #include <dev/usb/usbdevs.h>
96 #include <dev/usb/usb_quirks.h>
97
98 #include <dev/usb/ucomvar.h>
99
100 #ifdef USB_DEBUG
101 #define UBSA_DEBUG
102 #endif
103
104 #ifdef UBSA_DEBUG
105 Static int ubsadebug = 0;
106 #ifdef __FreeBSD__
107 SYSCTL_NODE(_hw_usb, OID_AUTO, ubsa, CTLFLAG_RW, 0, "USB ubsa");
108 SYSCTL_INT(_hw_usb_ubsa, OID_AUTO, debug, CTLFLAG_RW,
109 &ubsadebug, 0, "ubsa debug level");
110 #endif
111
112 #define DPRINTFN(n, x) do { if (ubsadebug > (n)) logprintf x; } while (0)
113 #else
114 #define DPRINTFN(n, x)
115 #endif
116 #define DPRINTF(x) DPRINTFN(0, x)
117
118 #define UBSA_MODVER 1 /* module version */
119
120 #define UBSA_CONFIG_INDEX 1
121 #define UBSA_IFACE_INDEX 0
122
123 #define UBSA_INTR_INTERVAL 100 /* ms */
124
125 #define UBSA_SET_BAUDRATE 0x00
126 #define UBSA_SET_STOP_BITS 0x01
127 #define UBSA_SET_DATA_BITS 0x02
128 #define UBSA_SET_PARITY 0x03
129 #define UBSA_SET_DTR 0x0A
130 #define UBSA_SET_RTS 0x0B
131 #define UBSA_SET_BREAK 0x0C
132 #define UBSA_SET_FLOW_CTRL 0x10
133
134 #define UBSA_PARITY_NONE 0x00
135 #define UBSA_PARITY_EVEN 0x01
136 #define UBSA_PARITY_ODD 0x02
137 #define UBSA_PARITY_MARK 0x03
138 #define UBSA_PARITY_SPACE 0x04
139
140 #define UBSA_FLOW_NONE 0x0000
141 #define UBSA_FLOW_OCTS 0x0001
142 #define UBSA_FLOW_ODSR 0x0002
143 #define UBSA_FLOW_IDSR 0x0004
144 #define UBSA_FLOW_IDTR 0x0008
145 #define UBSA_FLOW_IRTS 0x0010
146 #define UBSA_FLOW_ORTS 0x0020
147 #define UBSA_FLOW_UNKNOWN 0x0040
148 #define UBSA_FLOW_OXON 0x0080
149 #define UBSA_FLOW_IXON 0x0100
150
151 /* line status register */
152 #define UBSA_LSR_TSRE 0x40 /* Transmitter empty: byte sent */
153 #define UBSA_LSR_TXRDY 0x20 /* Transmitter buffer empty */
154 #define UBSA_LSR_BI 0x10 /* Break detected */
155 #define UBSA_LSR_FE 0x08 /* Framing error: bad stop bit */
156 #define UBSA_LSR_PE 0x04 /* Parity error */
157 #define UBSA_LSR_OE 0x02 /* Overrun, lost incoming byte */
158 #define UBSA_LSR_RXRDY 0x01 /* Byte ready in Receive Buffer */
159 #define UBSA_LSR_RCV_MASK 0x1f /* Mask for incoming data or error */
160
161 /* modem status register */
162 /* All deltas are from the last read of the MSR. */
163 #define UBSA_MSR_DCD 0x80 /* Current Data Carrier Detect */
164 #define UBSA_MSR_RI 0x40 /* Current Ring Indicator */
165 #define UBSA_MSR_DSR 0x20 /* Current Data Set Ready */
166 #define UBSA_MSR_CTS 0x10 /* Current Clear to Send */
167 #define UBSA_MSR_DDCD 0x08 /* DCD has changed state */
168 #define UBSA_MSR_TERI 0x04 /* RI has toggled low to high */
169 #define UBSA_MSR_DDSR 0x02 /* DSR has changed state */
170 #define UBSA_MSR_DCTS 0x01 /* CTS has changed state */
171
172 struct ubsa_softc {
173 USBBASEDEVICE sc_dev; /* base device */
174 usbd_device_handle sc_udev; /* USB device */
175 usbd_interface_handle sc_iface; /* interface */
176
177 int sc_iface_number; /* interface number */
178
179 usbd_interface_handle sc_intr_iface; /* interrupt interface */
180 int sc_intr_number; /* interrupt number */
181 usbd_pipe_handle sc_intr_pipe; /* interrupt pipe */
182 u_char *sc_intr_buf; /* interrupt buffer */
183 int sc_isize;
184
185 u_char sc_dtr; /* current DTR state */
186 u_char sc_rts; /* current RTS state */
187
188 u_char sc_lsr; /* Local status register */
189 u_char sc_msr; /* ubsa status register */
190
191 device_ptr_t sc_subdev; /* ucom device */
192
193 u_char sc_dying; /* disconnecting */
194
195 };
196
197 Static void ubsa_intr(usbd_xfer_handle, usbd_private_handle, usbd_status);
198
199 Static void ubsa_get_status(void *, int, u_char *, u_char *);
200 Static void ubsa_set(void *, int, int, int);
201 Static int ubsa_param(void *, int, struct termios *);
202 Static int ubsa_open(void *, int);
203 Static void ubsa_close(void *, int);
204
205 Static void ubsa_break(struct ubsa_softc *sc, int onoff);
206 Static int ubsa_request(struct ubsa_softc *, u_int8_t, u_int16_t);
207 Static void ubsa_dtr(struct ubsa_softc *, int);
208 Static void ubsa_rts(struct ubsa_softc *, int);
209 Static void ubsa_baudrate(struct ubsa_softc *, speed_t);
210 Static void ubsa_parity(struct ubsa_softc *, tcflag_t);
211 Static void ubsa_databits(struct ubsa_softc *, tcflag_t);
212 Static void ubsa_stopbits(struct ubsa_softc *, tcflag_t);
213 Static void ubsa_flow(struct ubsa_softc *, tcflag_t, tcflag_t);
214
215 struct ucom_methods ubsa_methods = {
216 ubsa_get_status,
217 ubsa_set,
218 ubsa_param,
219 NULL,
220 ubsa_open,
221 ubsa_close,
222 NULL,
223 NULL
224 };
225
226 Static const struct usb_devno ubsa_devs[] = {
227 /* BELKIN F5U103 */
228 { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5U103 },
229 /* BELKIN F5U120 */
230 { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5U120 },
231 /* GoHubs GO-COM232 */
232 { USB_VENDOR_ETEK, USB_PRODUCT_ETEK_1COM },
233 /* GoHubs GO-COM232 */
234 { USB_VENDOR_GOHUBS, USB_PRODUCT_GOHUBS_GOCOM232 },
235 /* Peracom */
236 { USB_VENDOR_PERACOM, USB_PRODUCT_PERACOM_SERIAL1 },
237 /* Option Vodafone Mobile Connect 3G */
238 { USB_VENDOR_OPTION, USB_PRODUCT_OPTION_VODAFONEMC3G },
239 /* Option GlobeTrotter 3G FUSION */
240 { USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GT3GFUSION },
241 /* Option GlobeTrotter 3G QUAD */
242 { USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GT3GQUAD },
243 };
244 #define ubsa_lookup(v, p) usb_lookup(ubsa_devs, v, p)
245
246 USB_DECLARE_DRIVER(ubsa);
247
USB_MATCH(ubsa)248 USB_MATCH(ubsa)
249 {
250 USB_MATCH_START(ubsa, uaa);
251
252 if (uaa->iface != NULL)
253 return (UMATCH_NONE);
254
255 return (ubsa_lookup(uaa->vendor, uaa->product) != NULL ?
256 UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
257 }
258
USB_ATTACH(ubsa)259 USB_ATTACH(ubsa)
260 {
261 USB_ATTACH_START(ubsa, sc, uaa);
262 usbd_device_handle dev = uaa->device;
263 usb_config_descriptor_t *cdesc;
264 usb_interface_descriptor_t *id;
265 usb_endpoint_descriptor_t *ed;
266 char devinfo[1024];
267 const char *devname = USBDEVNAME(sc->sc_dev);
268 usbd_status err;
269 struct ucom_attach_args uca;
270 int i;
271
272 usbd_devinfo(dev, 0, devinfo, sizeof devinfo);
273 USB_ATTACH_SETUP;
274 printf("%s: %s\n", devname, devinfo);
275
276 sc->sc_udev = dev;
277
278 /*
279 * initialize rts, dtr variables to something
280 * different from boolean 0, 1
281 */
282 sc->sc_dtr = -1;
283 sc->sc_rts = -1;
284
285 DPRINTF(("ubsa attach: sc = %p\n", sc));
286
287 /* initialize endpoints */
288 uca.bulkin = uca.bulkout = -1;
289 sc->sc_intr_number = -1;
290 sc->sc_intr_pipe = NULL;
291
292 /* Move the device into the configured state. */
293 err = usbd_set_config_index(dev, UBSA_CONFIG_INDEX, 1);
294 if (err) {
295 printf("%s: failed to set configuration: %s\n",
296 devname, usbd_errstr(err));
297 sc->sc_dying = 1;
298 goto error;
299 }
300
301 /* get the config descriptor */
302 cdesc = usbd_get_config_descriptor(sc->sc_udev);
303
304 if (cdesc == NULL) {
305 printf("%s: failed to get configuration descriptor\n",
306 devname);
307 sc->sc_dying = 1;
308 goto error;
309 }
310
311 /* get the first interface */
312 err = usbd_device2interface_handle(dev, UBSA_IFACE_INDEX,
313 &sc->sc_iface);
314 if (err) {
315 printf("%s: failed to get interface: %s\n",
316 devname, usbd_errstr(err));
317 sc->sc_dying = 1;
318 goto error;
319 }
320
321 /* Find the endpoints */
322
323 id = usbd_get_interface_descriptor(sc->sc_iface);
324 sc->sc_iface_number = id->bInterfaceNumber;
325
326 for (i = 0; i < id->bNumEndpoints; i++) {
327 ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
328 if (ed == NULL) {
329 printf("%s: no endpoint descriptor for %d\n",
330 USBDEVNAME(sc->sc_dev), i);
331 sc->sc_dying = 1;
332 goto error;
333 }
334
335 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
336 UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
337 sc->sc_intr_number = ed->bEndpointAddress;
338 sc->sc_isize = UGETW(ed->wMaxPacketSize);
339 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
340 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
341 uca.bulkin = ed->bEndpointAddress;
342 uca.ibufsize = UGETW(ed->wMaxPacketSize);
343 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
344 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
345 uca.bulkout = ed->bEndpointAddress;
346 uca.obufsize = UGETW(ed->wMaxPacketSize);
347 }
348 }
349
350 if (sc->sc_intr_number == -1) {
351 printf("%s: Could not find interrupt in\n", devname);
352 sc->sc_dying = 1;
353 goto error;
354 }
355
356 /* keep interface for interrupt */
357 sc->sc_intr_iface = sc->sc_iface;
358
359 if (uca.bulkin == -1) {
360 printf("%s: Could not find data bulk in\n", devname);
361 sc->sc_dying = 1;
362 goto error;
363 }
364
365 if (uca.bulkout == -1) {
366 printf("%s: Could not find data bulk out\n", devname);
367 sc->sc_dying = 1;
368 goto error;
369 }
370
371 uca.portno = UCOM_UNK_PORTNO;
372 /* bulkin, bulkout set above */
373 uca.ibufsizepad = uca.ibufsize;
374 uca.opkthdrlen = 0;
375 uca.device = dev;
376 uca.iface = sc->sc_iface;
377 uca.methods = &ubsa_methods;
378 uca.arg = sc;
379 uca.info = NULL;
380
381 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
382 USBDEV(sc->sc_dev));
383
384 DPRINTF(("ubsa: in = 0x%x, out = 0x%x, intr = 0x%x\n",
385 uca.bulkin, uca.bulkout, sc->sc_intr_number));
386
387 sc->sc_subdev = config_found_sm(self, &uca, ucomprint, ucomsubmatch);
388
389 USB_ATTACH_SUCCESS_RETURN;
390
391 error:
392 USB_ATTACH_ERROR_RETURN;
393 }
394
USB_DETACH(ubsa)395 USB_DETACH(ubsa)
396 {
397 USB_DETACH_START(ubsa, sc);
398 int rv = 0;
399
400
401 DPRINTF(("ubsa_detach: sc = %p\n", sc));
402
403 if (sc->sc_intr_pipe != NULL) {
404 usbd_abort_pipe(sc->sc_intr_pipe);
405 usbd_close_pipe(sc->sc_intr_pipe);
406 free(sc->sc_intr_buf, M_USBDEV);
407 sc->sc_intr_pipe = NULL;
408 }
409
410 sc->sc_dying = 1;
411 if (sc->sc_subdev != NULL) {
412 rv = config_detach(sc->sc_subdev, flags);
413 sc->sc_subdev = NULL;
414 }
415
416 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
417 USBDEV(sc->sc_dev));
418
419 return (rv);
420 }
421
422 int
ubsa_activate(device_ptr_t self,enum devact act)423 ubsa_activate(device_ptr_t self, enum devact act)
424 {
425 struct ubsa_softc *sc = (struct ubsa_softc *)self;
426 int rv = 0;
427
428 switch (act) {
429 case DVACT_ACTIVATE:
430 return (EOPNOTSUPP);
431
432 case DVACT_DEACTIVATE:
433 if (sc->sc_subdev != NULL)
434 rv = config_deactivate(sc->sc_subdev);
435 sc->sc_dying = 1;
436 break;
437 }
438 return (rv);
439 }
440
441 Static int
ubsa_request(struct ubsa_softc * sc,u_int8_t request,u_int16_t value)442 ubsa_request(struct ubsa_softc *sc, u_int8_t request, u_int16_t value)
443 {
444 usb_device_request_t req;
445 usbd_status err;
446
447 req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
448 req.bRequest = request;
449 USETW(req.wValue, value);
450 USETW(req.wIndex, sc->sc_iface_number);
451 USETW(req.wLength, 0);
452
453 err = usbd_do_request(sc->sc_udev, &req, 0);
454 if (err && err != USBD_STALLED)
455 printf("%s: ubsa_request: %s\n",
456 USBDEVNAME(sc->sc_dev), usbd_errstr(err));
457 return (err);
458 }
459
460 Static void
ubsa_dtr(struct ubsa_softc * sc,int onoff)461 ubsa_dtr(struct ubsa_softc *sc, int onoff)
462 {
463
464 DPRINTF(("ubsa_dtr: onoff = %d\n", onoff));
465
466 if (sc->sc_dtr == onoff)
467 return;
468 sc->sc_dtr = onoff;
469
470 ubsa_request(sc, UBSA_SET_DTR, onoff ? 1 : 0);
471 }
472
473 Static void
ubsa_rts(struct ubsa_softc * sc,int onoff)474 ubsa_rts(struct ubsa_softc *sc, int onoff)
475 {
476
477 DPRINTF(("ubsa_rts: onoff = %d\n", onoff));
478
479 if (sc->sc_rts == onoff)
480 return;
481 sc->sc_rts = onoff;
482
483 ubsa_request(sc, UBSA_SET_RTS, onoff ? 1 : 0);
484 }
485
486 Static void
ubsa_break(struct ubsa_softc * sc,int onoff)487 ubsa_break(struct ubsa_softc *sc, int onoff)
488 {
489
490 DPRINTF(("ubsa_rts: onoff = %d\n", onoff));
491
492 ubsa_request(sc, UBSA_SET_BREAK, onoff ? 1 : 0);
493 }
494
495 Static void
ubsa_set(void * addr,int portno,int reg,int onoff)496 ubsa_set(void *addr, int portno, int reg, int onoff)
497 {
498 struct ubsa_softc *sc;
499
500 sc = addr;
501 switch (reg) {
502 case UCOM_SET_DTR:
503 ubsa_dtr(sc, onoff);
504 break;
505 case UCOM_SET_RTS:
506 ubsa_rts(sc, onoff);
507 break;
508 case UCOM_SET_BREAK:
509 ubsa_break(sc, onoff);
510 break;
511 default:
512 break;
513 }
514 }
515
516 Static void
ubsa_baudrate(struct ubsa_softc * sc,speed_t speed)517 ubsa_baudrate(struct ubsa_softc *sc, speed_t speed)
518 {
519 u_int16_t value = 0;
520
521 DPRINTF(("ubsa_baudrate: speed = %d\n", speed));
522
523 switch(speed) {
524 case B0:
525 break;
526 case B300:
527 case B600:
528 case B1200:
529 case B2400:
530 case B4800:
531 case B9600:
532 case B19200:
533 case B38400:
534 case B57600:
535 case B115200:
536 case B230400:
537 value = B230400 / speed;
538 break;
539 default:
540 DPRINTF(("%s: ubsa_param: unsupported baudrate, "
541 "forcing default of 9600\n",
542 USBDEVNAME(sc->sc_dev)));
543 value = B230400 / B9600;
544 break;
545 };
546
547 if (speed == B0) {
548 ubsa_flow(sc, 0, 0);
549 ubsa_dtr(sc, 0);
550 ubsa_rts(sc, 0);
551 } else
552 ubsa_request(sc, UBSA_SET_BAUDRATE, value);
553 }
554
555 Static void
ubsa_parity(struct ubsa_softc * sc,tcflag_t cflag)556 ubsa_parity(struct ubsa_softc *sc, tcflag_t cflag)
557 {
558 int value;
559
560 DPRINTF(("ubsa_parity: cflag = 0x%x\n", cflag));
561
562 if (cflag & PARENB)
563 value = (cflag & PARODD) ? UBSA_PARITY_ODD : UBSA_PARITY_EVEN;
564 else
565 value = UBSA_PARITY_NONE;
566
567 ubsa_request(sc, UBSA_SET_PARITY, value);
568 }
569
570 Static void
ubsa_databits(struct ubsa_softc * sc,tcflag_t cflag)571 ubsa_databits(struct ubsa_softc *sc, tcflag_t cflag)
572 {
573 int value;
574
575 DPRINTF(("ubsa_databits: cflag = 0x%x\n", cflag));
576
577 switch (cflag & CSIZE) {
578 case CS5: value = 0; break;
579 case CS6: value = 1; break;
580 case CS7: value = 2; break;
581 case CS8: value = 3; break;
582 default:
583 DPRINTF(("%s: ubsa_param: unsupported databits requested, "
584 "forcing default of 8\n",
585 USBDEVNAME(sc->sc_dev)));
586 value = 3;
587 }
588
589 ubsa_request(sc, UBSA_SET_DATA_BITS, value);
590 }
591
592 Static void
ubsa_stopbits(struct ubsa_softc * sc,tcflag_t cflag)593 ubsa_stopbits(struct ubsa_softc *sc, tcflag_t cflag)
594 {
595 int value;
596
597 DPRINTF(("ubsa_stopbits: cflag = 0x%x\n", cflag));
598
599 value = (cflag & CSTOPB) ? 1 : 0;
600
601 ubsa_request(sc, UBSA_SET_STOP_BITS, value);
602 }
603
604 Static void
ubsa_flow(struct ubsa_softc * sc,tcflag_t cflag,tcflag_t iflag)605 ubsa_flow(struct ubsa_softc *sc, tcflag_t cflag, tcflag_t iflag)
606 {
607 int value;
608
609 DPRINTF(("ubsa_flow: cflag = 0x%x, iflag = 0x%x\n", cflag, iflag));
610
611 value = 0;
612 if (cflag & CRTSCTS)
613 value |= UBSA_FLOW_OCTS | UBSA_FLOW_IRTS;
614 if (iflag & (IXON|IXOFF))
615 value |= UBSA_FLOW_OXON | UBSA_FLOW_IXON;
616
617 ubsa_request(sc, UBSA_SET_FLOW_CTRL, value);
618 }
619
620 Static int
ubsa_param(void * addr,int portno,struct termios * ti)621 ubsa_param(void *addr, int portno, struct termios *ti)
622 {
623 struct ubsa_softc *sc = addr;
624
625 DPRINTF(("ubsa_param: sc = %p\n", sc));
626
627 ubsa_baudrate(sc, ti->c_ospeed);
628 ubsa_parity(sc, ti->c_cflag);
629 ubsa_databits(sc, ti->c_cflag);
630 ubsa_stopbits(sc, ti->c_cflag);
631 ubsa_flow(sc, ti->c_cflag, ti->c_iflag);
632
633 return (0);
634 }
635
636 Static int
ubsa_open(void * addr,int portno)637 ubsa_open(void *addr, int portno)
638 {
639 struct ubsa_softc *sc = addr;
640 int err;
641
642 if (sc->sc_dying)
643 return (ENXIO);
644
645 DPRINTF(("ubsa_open: sc = %p\n", sc));
646
647 if (sc->sc_intr_number != -1 && sc->sc_intr_pipe == NULL) {
648 sc->sc_intr_buf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK);
649 err = usbd_open_pipe_intr(sc->sc_intr_iface,
650 sc->sc_intr_number,
651 USBD_SHORT_XFER_OK,
652 &sc->sc_intr_pipe,
653 sc,
654 sc->sc_intr_buf,
655 sc->sc_isize,
656 ubsa_intr,
657 UBSA_INTR_INTERVAL);
658 if (err) {
659 printf("%s: cannot open interrupt pipe (addr %d)\n",
660 USBDEVNAME(sc->sc_dev),
661 sc->sc_intr_number);
662 return (EIO);
663 }
664 }
665
666 return (0);
667 }
668
669 Static void
ubsa_close(void * addr,int portno)670 ubsa_close(void *addr, int portno)
671 {
672 struct ubsa_softc *sc = addr;
673 int err;
674
675 if (sc->sc_dying)
676 return;
677
678 DPRINTF(("ubsa_close: close\n"));
679
680 if (sc->sc_intr_pipe != NULL) {
681 err = usbd_abort_pipe(sc->sc_intr_pipe);
682 if (err)
683 printf("%s: abort interrupt pipe failed: %s\n",
684 USBDEVNAME(sc->sc_dev),
685 usbd_errstr(err));
686 err = usbd_close_pipe(sc->sc_intr_pipe);
687 if (err)
688 printf("%s: close interrupt pipe failed: %s\n",
689 USBDEVNAME(sc->sc_dev),
690 usbd_errstr(err));
691 free(sc->sc_intr_buf, M_USBDEV);
692 sc->sc_intr_pipe = NULL;
693 }
694 }
695
696 Static void
ubsa_intr(usbd_xfer_handle xfer,usbd_private_handle priv,usbd_status status)697 ubsa_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
698 {
699 struct ubsa_softc *sc = priv;
700 u_char *buf;
701
702 buf = sc->sc_intr_buf;
703 if (sc->sc_dying)
704 return;
705
706 if (status != USBD_NORMAL_COMPLETION) {
707 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
708 return;
709
710 DPRINTF(("%s: ubsa_intr: abnormal status: %s\n",
711 USBDEVNAME(sc->sc_dev), usbd_errstr(status)));
712 usbd_clear_endpoint_stall_async(sc->sc_intr_pipe);
713 return;
714 }
715
716 /* incidentally, Belkin adapter status bits match UART 16550 bits */
717 sc->sc_lsr = buf[2];
718 sc->sc_msr = buf[3];
719
720 DPRINTF(("%s: ubsa lsr = 0x%02x, msr = 0x%02x\n",
721 USBDEVNAME(sc->sc_dev), sc->sc_lsr, sc->sc_msr));
722
723 ucom_status_change((struct ucom_softc *)sc->sc_subdev);
724 }
725
726 Static void
ubsa_get_status(void * addr,int portno,u_char * lsr,u_char * msr)727 ubsa_get_status(void *addr, int portno, u_char *lsr, u_char *msr)
728 {
729 struct ubsa_softc *sc = addr;
730
731 DPRINTF(("ubsa_get_status\n"));
732
733 if (lsr != NULL)
734 *lsr = sc->sc_lsr;
735 if (msr != NULL)
736 *msr = sc->sc_msr;
737 }
738