1 /* $OpenBSD: umct.c,v 1.45 2016/09/02 09:14:59 mpi Exp $ */ 2 /* $NetBSD: umct.c,v 1.10 2003/02/23 04:20:07 simonb Exp $ */ 3 /* 4 * Copyright (c) 2001 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Ichiro FUKUHARA (ichiro@ichiro.org). 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * MCT USB-RS232 Interface Controller 34 * http://www.mct.com.tw/prod/rs232.html 35 * http://www.dlink.com/products/usb/dsbs25 36 */ 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/kernel.h> 41 #include <sys/malloc.h> 42 #include <sys/ioctl.h> 43 #include <sys/conf.h> 44 #include <sys/tty.h> 45 #include <sys/file.h> 46 #include <sys/selinfo.h> 47 #include <sys/device.h> 48 #include <sys/poll.h> 49 50 #include <dev/usb/usb.h> 51 #include <dev/usb/usbcdc.h> 52 53 #include <dev/usb/usbdi.h> 54 #include <dev/usb/usbdi_util.h> 55 #include <dev/usb/usbdevs.h> 56 57 #include <dev/usb/ucomvar.h> 58 59 #include <dev/usb/umct.h> 60 61 #ifdef UMCT_DEBUG 62 #define DPRINTFN(n, x) do { if (umctdebug > (n)) printf x; } while (0) 63 int umctdebug = 0; 64 #else 65 #define DPRINTFN(n, x) 66 #endif 67 #define DPRINTF(x) DPRINTFN(0, x) 68 69 #define UMCT_IFACE_INDEX 0 70 71 struct umct_softc { 72 struct device sc_dev; /* base device */ 73 struct usbd_device *sc_udev; /* USB device */ 74 struct usbd_interface *sc_iface; /* interface */ 75 int sc_iface_number; /* interface number */ 76 u_int16_t sc_product; 77 78 int sc_intr_number; /* interrupt number */ 79 struct usbd_pipe *sc_intr_pipe; /* interrupt pipe */ 80 u_char *sc_intr_buf; /* interrupt buffer */ 81 int sc_isize; 82 83 struct usb_cdc_line_state sc_line_state; /* current line state */ 84 u_char sc_dtr; /* current DTR state */ 85 u_char sc_rts; /* current RTS state */ 86 u_char sc_break; /* set break */ 87 88 u_char sc_status; 89 90 struct device *sc_subdev; /* ucom device */ 91 92 u_char sc_lsr; /* Local status register */ 93 u_char sc_msr; /* umct status register */ 94 95 u_int last_lcr; /* keep lcr register */ 96 }; 97 98 /* 99 * These are the maximum number of bytes transferred per frame. 100 * The output buffer size cannot be increased due to the size encoding. 101 */ 102 #define UMCTIBUFSIZE 256 103 #define UMCTOBUFSIZE 256 104 105 void umct_init(struct umct_softc *); 106 void umct_set_baudrate(struct umct_softc *, u_int, int); 107 void umct_set_lcr(struct umct_softc *, u_int); 108 void umct_intr(struct usbd_xfer *, void *, usbd_status); 109 110 void umct_set(void *, int, int, int); 111 void umct_dtr(struct umct_softc *, int); 112 void umct_rts(struct umct_softc *, int); 113 void umct_break(struct umct_softc *, int); 114 void umct_set_line_state(struct umct_softc *); 115 void umct_get_status(void *, int portno, u_char *lsr, u_char *msr); 116 int umct_param(void *, int, struct termios *); 117 int umct_open(void *, int); 118 void umct_close(void *, int); 119 120 struct ucom_methods umct_methods = { 121 umct_get_status, 122 umct_set, 123 umct_param, 124 NULL, 125 umct_open, 126 umct_close, 127 NULL, 128 NULL, 129 }; 130 131 static const struct usb_devno umct_devs[] = { 132 /* MCT USB-232 Interface Products */ 133 { USB_VENDOR_MCT, USB_PRODUCT_MCT_USB232 }, 134 /* Sitecom USB-232 Products */ 135 { USB_VENDOR_MCT, USB_PRODUCT_MCT_SITECOM_USB232 }, 136 /* D-Link DU-H3SP USB BAY Hub Products */ 137 { USB_VENDOR_MCT, USB_PRODUCT_MCT_DU_H3SP_USB232 }, 138 /* BELKIN F5U109 */ 139 { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5U109 }, 140 /* BELKIN F5U409 */ 141 { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5U409 }, 142 }; 143 144 int umct_match(struct device *, void *, void *); 145 void umct_attach(struct device *, struct device *, void *); 146 int umct_detach(struct device *, int); 147 148 struct cfdriver umct_cd = { 149 NULL, "umct", DV_DULL 150 }; 151 152 const struct cfattach umct_ca = { 153 sizeof(struct umct_softc), umct_match, umct_attach, umct_detach 154 }; 155 156 int 157 umct_match(struct device *parent, void *match, void *aux) 158 { 159 struct usb_attach_arg *uaa = aux; 160 161 if (uaa->iface == NULL) 162 return (UMATCH_NONE); 163 164 return (usb_lookup(umct_devs, uaa->vendor, uaa->product) != NULL ? 165 UMATCH_VENDOR_PRODUCT : UMATCH_NONE); 166 } 167 168 void 169 umct_attach(struct device *parent, struct device *self, void *aux) 170 { 171 struct umct_softc *sc = (struct umct_softc *)self; 172 struct usb_attach_arg *uaa = aux; 173 struct usbd_device *dev = uaa->device; 174 usb_config_descriptor_t *cdesc; 175 usb_interface_descriptor_t *id; 176 usb_endpoint_descriptor_t *ed; 177 178 char *devname = sc->sc_dev.dv_xname; 179 usbd_status err; 180 int i; 181 struct ucom_attach_args uca; 182 183 sc->sc_udev = dev; 184 sc->sc_product = uaa->product; 185 186 DPRINTF(("\n\numct attach: sc=%p\n", sc)); 187 188 /* initialize endpoints */ 189 uca.bulkin = uca.bulkout = -1; 190 sc->sc_intr_number = -1; 191 sc->sc_intr_pipe = NULL; 192 193 /* get the config descriptor */ 194 cdesc = usbd_get_config_descriptor(sc->sc_udev); 195 196 if (cdesc == NULL) { 197 printf("%s: failed to get configuration descriptor\n", 198 sc->sc_dev.dv_xname); 199 usbd_deactivate(sc->sc_udev); 200 return; 201 } 202 203 /* get the interface */ 204 err = usbd_device2interface_handle(dev, UMCT_IFACE_INDEX, 205 &sc->sc_iface); 206 if (err) { 207 printf("\n%s: failed to get interface, err=%s\n", 208 devname, usbd_errstr(err)); 209 usbd_deactivate(sc->sc_udev); 210 return; 211 } 212 213 /* Find the bulk{in,out} and interrupt endpoints */ 214 215 id = usbd_get_interface_descriptor(sc->sc_iface); 216 sc->sc_iface_number = id->bInterfaceNumber; 217 218 for (i = 0; i < id->bNumEndpoints; i++) { 219 ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i); 220 if (ed == NULL) { 221 printf("%s: no endpoint descriptor for %d\n", 222 sc->sc_dev.dv_xname, i); 223 usbd_deactivate(sc->sc_udev); 224 return; 225 } 226 227 /* 228 * The Bulkin endpoint is marked as an interrupt. Since 229 * we can't rely on the endpoint descriptor order, we'll 230 * check the wMaxPacketSize field to differentiate. 231 */ 232 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 233 UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT && 234 UGETW(ed->wMaxPacketSize) != 0x2) { 235 uca.bulkin = ed->bEndpointAddress; 236 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && 237 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 238 uca.bulkout = ed->bEndpointAddress; 239 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 240 UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { 241 sc->sc_intr_number = ed->bEndpointAddress; 242 sc->sc_isize = UGETW(ed->wMaxPacketSize); 243 } 244 } 245 246 if (uca.bulkin == -1) { 247 printf("%s: Could not find data bulk in\n", 248 sc->sc_dev.dv_xname); 249 usbd_deactivate(sc->sc_udev); 250 return; 251 } 252 253 if (uca.bulkout == -1) { 254 printf("%s: Could not find data bulk out\n", 255 sc->sc_dev.dv_xname); 256 usbd_deactivate(sc->sc_udev); 257 return; 258 } 259 260 if (sc->sc_intr_number== -1) { 261 printf("%s: Could not find interrupt in\n", 262 sc->sc_dev.dv_xname); 263 usbd_deactivate(sc->sc_udev); 264 return; 265 } 266 267 sc->sc_dtr = sc->sc_rts = 0; 268 uca.portno = UCOM_UNK_PORTNO; 269 /* bulkin, bulkout set above */ 270 uca.ibufsize = UMCTIBUFSIZE; 271 if (sc->sc_product == USB_PRODUCT_MCT_SITECOM_USB232) 272 uca.obufsize = 16; /* device is broken */ 273 else 274 uca.obufsize = UMCTOBUFSIZE; 275 uca.ibufsizepad = UMCTIBUFSIZE; 276 uca.opkthdrlen = 0; 277 uca.device = dev; 278 uca.iface = sc->sc_iface; 279 uca.methods = &umct_methods; 280 uca.arg = sc; 281 uca.info = NULL; 282 283 umct_init(sc); 284 285 DPRINTF(("umct: in=0x%x out=0x%x intr=0x%x\n", 286 uca.bulkin, uca.bulkout, sc->sc_intr_number )); 287 sc->sc_subdev = config_found_sm(self, &uca, ucomprint, ucomsubmatch); 288 } 289 290 int 291 umct_detach(struct device *self, int flags) 292 { 293 struct umct_softc *sc = (struct umct_softc *)self; 294 int rv = 0; 295 296 DPRINTF(("umct_detach: sc=%p flags=%d\n", sc, flags)); 297 298 if (sc->sc_intr_pipe != NULL) { 299 usbd_abort_pipe(sc->sc_intr_pipe); 300 usbd_close_pipe(sc->sc_intr_pipe); 301 free(sc->sc_intr_buf, M_USBDEV, 0); 302 sc->sc_intr_pipe = NULL; 303 } 304 305 if (sc->sc_subdev != NULL) { 306 rv = config_detach(sc->sc_subdev, flags); 307 sc->sc_subdev = NULL; 308 } 309 310 return (rv); 311 } 312 313 void 314 umct_set_line_state(struct umct_softc *sc) 315 { 316 usb_device_request_t req; 317 uByte ls; 318 319 ls = (sc->sc_dtr ? MCR_DTR : 0) | 320 (sc->sc_rts ? MCR_RTS : 0); 321 322 DPRINTF(("umct_set_line_state: DTR=%d,RTS=%d,ls=%02x\n", 323 sc->sc_dtr, sc->sc_rts, ls)); 324 325 req.bmRequestType = UMCT_SET_REQUEST; 326 req.bRequest = REQ_SET_MCR; 327 USETW(req.wValue, 0); 328 USETW(req.wIndex, sc->sc_iface_number); 329 USETW(req.wLength, LENGTH_SET_MCR); 330 331 (void)usbd_do_request(sc->sc_udev, &req, &ls); 332 } 333 334 void 335 umct_set(void *addr, int portno, int reg, int onoff) 336 { 337 struct umct_softc *sc = addr; 338 339 switch (reg) { 340 case UCOM_SET_DTR: 341 umct_dtr(sc, onoff); 342 break; 343 case UCOM_SET_RTS: 344 umct_rts(sc, onoff); 345 break; 346 case UCOM_SET_BREAK: 347 umct_break(sc, onoff); 348 break; 349 default: 350 break; 351 } 352 } 353 354 void 355 umct_dtr(struct umct_softc *sc, int onoff) 356 { 357 358 DPRINTF(("umct_dtr: onoff=%d\n", onoff)); 359 360 if (sc->sc_dtr == onoff) 361 return; 362 sc->sc_dtr = onoff; 363 364 umct_set_line_state(sc); 365 } 366 367 void 368 umct_rts(struct umct_softc *sc, int onoff) 369 { 370 DPRINTF(("umct_rts: onoff=%d\n", onoff)); 371 372 if (sc->sc_rts == onoff) 373 return; 374 sc->sc_rts = onoff; 375 376 umct_set_line_state(sc); 377 } 378 379 void 380 umct_break(struct umct_softc *sc, int onoff) 381 { 382 DPRINTF(("umct_break: onoff=%d\n", onoff)); 383 384 umct_set_lcr(sc, onoff ? sc->last_lcr | LCR_SET_BREAK : 385 sc->last_lcr); 386 } 387 388 void 389 umct_set_lcr(struct umct_softc *sc, u_int data) 390 { 391 usb_device_request_t req; 392 uByte adata; 393 394 adata = data; 395 req.bmRequestType = UMCT_SET_REQUEST; 396 req.bRequest = REQ_SET_LCR; 397 USETW(req.wValue, 0); 398 USETW(req.wIndex, sc->sc_iface_number); 399 USETW(req.wLength, LENGTH_SET_LCR); 400 401 /* XXX should check */ 402 (void)usbd_do_request(sc->sc_udev, &req, &adata); 403 } 404 405 void 406 umct_set_baudrate(struct umct_softc *sc, u_int rate, int cts) 407 { 408 usb_device_request_t req; 409 uDWord arate; 410 u_int val; 411 412 if (sc->sc_product == USB_PRODUCT_MCT_SITECOM_USB232 || 413 sc->sc_product == USB_PRODUCT_BELKIN_F5U109) { 414 switch (rate) { 415 case 300: val = 0x01; break; 416 case 600: val = 0x02; break; 417 case 1200: val = 0x03; break; 418 case 2400: val = 0x04; break; 419 case 4800: val = 0x06; break; 420 case 9600: val = 0x08; break; 421 case 19200: val = 0x09; break; 422 case 38400: val = 0x0a; break; 423 case 57600: val = 0x0b; break; 424 case 115200: val = 0x0c; break; 425 default: val = -1; break; 426 } 427 } else { 428 val = UMCT_BAUD_RATE(rate); 429 } 430 USETDW(arate, val); 431 432 req.bmRequestType = UMCT_SET_REQUEST; 433 req.bRequest = REQ_SET_BAUD_RATE; 434 USETW(req.wValue, 0); 435 USETW(req.wIndex, sc->sc_iface_number); 436 USETW(req.wLength, LENGTH_BAUD_RATE); 437 438 /* XXX should check */ 439 (void)usbd_do_request(sc->sc_udev, &req, arate); 440 441 /* unknown request, required after setting baud rate */ 442 USETDW(arate, 0); 443 req.bmRequestType = UMCT_SET_REQUEST; 444 req.bRequest = REQ_UNKNOWN1; 445 USETW(req.wValue, 0); 446 USETW(req.wIndex, sc->sc_iface_number); 447 USETW(req.wLength, LENGTH_UNKNOWN1); 448 (void)usbd_do_request(sc->sc_udev, &req, arate); 449 450 /* update CTS, also required after setting baud rate */ 451 USETDW(arate, cts); 452 req.bmRequestType = UMCT_SET_REQUEST; 453 req.bRequest = REQ_SET_CTS; 454 USETW(req.wValue, 0); 455 USETW(req.wIndex, sc->sc_iface_number); 456 USETW(req.wLength, LENGTH_SET_CTS); 457 (void)usbd_do_request(sc->sc_udev, &req, arate); 458 } 459 460 void 461 umct_init(struct umct_softc *sc) 462 { 463 umct_set_baudrate(sc, 9600, 0); 464 umct_set_lcr(sc, LCR_DATA_BITS_8 | LCR_PARITY_NONE | LCR_STOP_BITS_1); 465 } 466 467 int 468 umct_param(void *addr, int portno, struct termios *t) 469 { 470 struct umct_softc *sc = addr; 471 u_int data = 0; 472 473 DPRINTF(("umct_param: sc=%p\n", sc)); 474 475 DPRINTF(("umct_param: BAUDRATE=%d\n", t->c_ospeed)); 476 477 if (ISSET(t->c_cflag, CSTOPB)) 478 data |= LCR_STOP_BITS_2; 479 else 480 data |= LCR_STOP_BITS_1; 481 if (ISSET(t->c_cflag, PARENB)) { 482 if (ISSET(t->c_cflag, PARODD)) 483 data |= LCR_PARITY_ODD; 484 else 485 data |= LCR_PARITY_EVEN; 486 } else 487 data |= LCR_PARITY_NONE; 488 switch (ISSET(t->c_cflag, CSIZE)) { 489 case CS5: 490 data |= LCR_DATA_BITS_5; 491 break; 492 case CS6: 493 data |= LCR_DATA_BITS_6; 494 break; 495 case CS7: 496 data |= LCR_DATA_BITS_7; 497 break; 498 case CS8: 499 data |= LCR_DATA_BITS_8; 500 break; 501 } 502 503 umct_set_baudrate(sc, t->c_ospeed, ISSET(t->c_cflag, CRTSCTS)); 504 505 sc->last_lcr = data; 506 umct_set_lcr(sc, data); 507 508 return (0); 509 } 510 511 int 512 umct_open(void *addr, int portno) 513 { 514 struct umct_softc *sc = addr; 515 int err, lcr_data; 516 517 if (usbd_is_dying(sc->sc_udev)) 518 return (EIO); 519 520 DPRINTF(("umct_open: sc=%p\n", sc)); 521 522 /* initialize LCR */ 523 lcr_data = LCR_DATA_BITS_8 | LCR_PARITY_NONE | 524 LCR_STOP_BITS_1; 525 umct_set_lcr(sc, lcr_data); 526 527 if (sc->sc_intr_number != -1 && sc->sc_intr_pipe == NULL) { 528 sc->sc_status = 0; /* clear status bit */ 529 sc->sc_intr_buf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK); 530 err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_intr_number, 531 USBD_SHORT_XFER_OK, &sc->sc_intr_pipe, sc, 532 sc->sc_intr_buf, sc->sc_isize, 533 umct_intr, USBD_DEFAULT_INTERVAL); 534 if (err) { 535 DPRINTF(("%s: cannot open interrupt pipe (addr %d)\n", 536 sc->sc_dev.dv_xname, sc->sc_intr_number)); 537 return (EIO); 538 } 539 } 540 541 return (0); 542 } 543 544 void 545 umct_close(void *addr, int portno) 546 { 547 struct umct_softc *sc = addr; 548 int err; 549 550 if (usbd_is_dying(sc->sc_udev)) 551 return; 552 553 DPRINTF(("umct_close: close\n")); 554 555 if (sc->sc_intr_pipe != NULL) { 556 usbd_abort_pipe(sc->sc_intr_pipe); 557 err = usbd_close_pipe(sc->sc_intr_pipe); 558 if (err) 559 printf("%s: close interrupt pipe failed: %s\n", 560 sc->sc_dev.dv_xname, usbd_errstr(err)); 561 free(sc->sc_intr_buf, M_USBDEV, 0); 562 sc->sc_intr_pipe = NULL; 563 } 564 } 565 566 void 567 umct_intr(struct usbd_xfer *xfer, void *priv, usbd_status status) 568 { 569 struct umct_softc *sc = priv; 570 u_char *buf = sc->sc_intr_buf; 571 u_char mstatus; 572 573 if (usbd_is_dying(sc->sc_udev)) 574 return; 575 576 if (status != USBD_NORMAL_COMPLETION) { 577 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) 578 return; 579 580 DPRINTF(("%s: abnormal status: %s\n", sc->sc_dev.dv_xname, 581 usbd_errstr(status))); 582 usbd_clear_endpoint_stall_async(sc->sc_intr_pipe); 583 return; 584 } 585 586 DPRINTF(("%s: umct status = MSR:%02x, LSR:%02x\n", 587 sc->sc_dev.dv_xname, buf[0],buf[1])); 588 589 sc->sc_lsr = sc->sc_msr = 0; 590 mstatus = buf[0]; 591 if (ISSET(mstatus, MSR_DSR)) 592 sc->sc_msr |= UMSR_DSR; 593 if (ISSET(mstatus, MSR_DCD)) 594 sc->sc_msr |= UMSR_DCD; 595 ucom_status_change((struct ucom_softc *)sc->sc_subdev); 596 } 597 598 void 599 umct_get_status(void *addr, int portno, u_char *lsr, u_char *msr) 600 { 601 struct umct_softc *sc = addr; 602 603 DPRINTF(("umct_get_status:\n")); 604 605 if (lsr != NULL) 606 *lsr = sc->sc_lsr; 607 if (msr != NULL) 608 *msr = sc->sc_msr; 609 } 610