1 /* $NetBSD: uhso.c,v 1.35 2021/06/13 09:27:20 mlelstv Exp $ */ 2 3 /*- 4 * Copyright (c) 2009 Iain Hibbert 5 * Copyright (c) 2008 Fredrik Lindberg 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /* 30 * This driver originated as the hso module for FreeBSD written by 31 * Fredrik Lindberg[1]. It has been rewritten almost completely for 32 * NetBSD, and to support more devices with information extracted from 33 * the Linux hso driver provided by Option N.V.[2] 34 * 35 * [1] http://www.shapeshifter.se/code/hso 36 * [2] http://www.pharscape.org/hso.htm 37 */ 38 39 #include <sys/cdefs.h> 40 __KERNEL_RCSID(0, "$NetBSD: uhso.c,v 1.35 2021/06/13 09:27:20 mlelstv Exp $"); 41 42 #ifdef _KERNEL_OPT 43 #include "opt_inet.h" 44 #include "opt_usb.h" 45 #endif 46 47 #include <sys/param.h> 48 #include <sys/conf.h> 49 #include <sys/fcntl.h> 50 #include <sys/kauth.h> 51 #include <sys/kernel.h> 52 #include <sys/kmem.h> 53 #include <sys/mbuf.h> 54 #include <sys/poll.h> 55 #include <sys/queue.h> 56 #include <sys/socket.h> 57 #include <sys/sysctl.h> 58 #include <sys/systm.h> 59 #include <sys/tty.h> 60 #include <sys/vnode.h> 61 #include <sys/lwp.h> 62 63 #include <net/bpf.h> 64 #include <net/if.h> 65 #include <net/if_dl.h> 66 #include <net/if_types.h> 67 #include <net/netisr.h> 68 69 #include <netinet/in_systm.h> 70 #include <netinet/in_var.h> 71 #include <netinet/ip.h> 72 73 #include <dev/usb/usb.h> 74 #include <dev/usb/usbcdc.h> 75 #include <dev/usb/usbdi.h> 76 #include <dev/usb/usbdi_util.h> 77 #include <dev/usb/umassvar.h> 78 79 #include <dev/scsipi/scsi_disk.h> 80 81 #include "usbdevs.h" 82 #include "ioconf.h" 83 84 #undef DPRINTF 85 #ifdef UHSO_DEBUG 86 /* 87 * defined levels 88 * 0 warnings only 89 * 1 informational 90 * 5 really chatty 91 */ 92 int uhso_debug = 0; 93 94 #define DPRINTF(n, ...) do { \ 95 if (uhso_debug >= (n)) { \ 96 printf("%s: ", __func__); \ 97 printf(__VA_ARGS__); \ 98 } \ 99 } while (/* CONSTCOND */0) 100 #else 101 #define DPRINTF(...) ((void)0) 102 #endif 103 104 /* 105 * When first attached, the device class will be 0 and the modem 106 * will attach as UMASS until a SCSI REZERO_UNIT command is sent, 107 * in which case it will detach and reattach with device class set 108 * to UDCLASS_VENDOR (0xff) and provide the serial interfaces. 109 * 110 * If autoswitch is set (the default) this will happen automatically. 111 */ 112 Static int uhso_autoswitch = 1; 113 114 SYSCTL_SETUP(sysctl_hw_uhso_setup, "uhso sysctl setup") 115 { 116 const struct sysctlnode *node = NULL; 117 118 sysctl_createv(clog, 0, NULL, &node, 119 CTLFLAG_PERMANENT, 120 CTLTYPE_NODE, "uhso", 121 NULL, 122 NULL, 0, 123 NULL, 0, 124 CTL_HW, CTL_CREATE, CTL_EOL); 125 126 if (node == NULL) 127 return; 128 129 #ifdef UHSO_DEBUG 130 sysctl_createv(clog, 0, &node, NULL, 131 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, 132 CTLTYPE_INT, "debug", 133 SYSCTL_DESCR("uhso debug level (0, 1, 5)"), 134 NULL, 0, 135 &uhso_debug, sizeof(uhso_debug), 136 CTL_CREATE, CTL_EOL); 137 #endif 138 139 sysctl_createv(clog, 0, &node, NULL, 140 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, 141 CTLTYPE_INT, "autoswitch", 142 SYSCTL_DESCR("automatically switch device into modem mode"), 143 NULL, 0, 144 &uhso_autoswitch, sizeof(uhso_autoswitch), 145 CTL_CREATE, CTL_EOL); 146 } 147 148 /* 149 * The uhso modems have a number of interfaces providing a variety of 150 * IO ports using the bulk endpoints, or multiplexed on the control 151 * endpoints. We separate the ports by function and provide each with 152 * a predictable index number used to construct the device minor number. 153 * 154 * The Network port is configured as a network interface rather than 155 * a tty as it provides raw IPv4 packets. 156 */ 157 158 Static const char *uhso_port_name[] = { 159 "Control", 160 "Diagnostic", 161 "Diagnostic2", 162 "Application", 163 "Application2", 164 "GPS", 165 "GPS Control", 166 "PC Smartcard", 167 "Modem", 168 "MSD", /* "Modem Sharing Device" ? */ 169 "Voice", 170 "Network", 171 }; 172 173 #define UHSO_PORT_CONTROL 0x00 174 #define UHSO_PORT_DIAG 0x01 175 #define UHSO_PORT_DIAG2 0x02 176 #define UHSO_PORT_APP 0x03 177 #define UHSO_PORT_APP2 0x04 178 #define UHSO_PORT_GPS 0x05 179 #define UHSO_PORT_GPS_CONTROL 0x06 180 #define UHSO_PORT_PCSC 0x07 181 #define UHSO_PORT_MODEM 0x08 182 #define UHSO_PORT_MSD 0x09 183 #define UHSO_PORT_VOICE 0x0a 184 #define UHSO_PORT_NETWORK 0x0b 185 186 #define UHSO_PORT_MAX __arraycount(uhso_port_name) 187 188 #define UHSO_IFACE_MUX 0x20 189 #define UHSO_IFACE_BULK 0x40 190 #define UHSO_IFACE_IFNET 0x80 191 192 /* 193 * The interface specification can sometimes be deduced from the device 194 * type and interface number, or some modems support a vendor specific 195 * way to read config info which we can translate to the port index. 196 */ 197 Static const uint8_t uhso_spec_default[] = { 198 UHSO_IFACE_IFNET | UHSO_PORT_NETWORK | UHSO_IFACE_MUX, 199 UHSO_IFACE_BULK | UHSO_PORT_DIAG, 200 UHSO_IFACE_BULK | UHSO_PORT_MODEM, 201 }; 202 203 Static const uint8_t uhso_spec_icon321[] = { 204 UHSO_IFACE_IFNET | UHSO_PORT_NETWORK | UHSO_IFACE_MUX, 205 UHSO_IFACE_BULK | UHSO_PORT_DIAG2, 206 UHSO_IFACE_BULK | UHSO_PORT_MODEM, 207 UHSO_IFACE_BULK | UHSO_PORT_DIAG, 208 }; 209 210 Static const uint8_t uhso_spec_config[] = { 211 0, 212 UHSO_IFACE_BULK | UHSO_PORT_DIAG, 213 UHSO_IFACE_BULK | UHSO_PORT_GPS, 214 UHSO_IFACE_BULK | UHSO_PORT_GPS_CONTROL, 215 UHSO_IFACE_BULK | UHSO_PORT_APP, 216 UHSO_IFACE_BULK | UHSO_PORT_APP2, 217 UHSO_IFACE_BULK | UHSO_PORT_CONTROL, 218 UHSO_IFACE_IFNET | UHSO_PORT_NETWORK, 219 UHSO_IFACE_BULK | UHSO_PORT_MODEM, 220 UHSO_IFACE_BULK | UHSO_PORT_MSD, 221 UHSO_IFACE_BULK | UHSO_PORT_PCSC, 222 UHSO_IFACE_BULK | UHSO_PORT_VOICE, 223 }; 224 225 struct uhso_dev { 226 uint16_t vendor; 227 uint16_t product; 228 uint16_t type; 229 }; 230 231 #define UHSOTYPE_DEFAULT 1 232 #define UHSOTYPE_ICON321 2 233 #define UHSOTYPE_CONFIG 3 234 235 Static const struct uhso_dev uhso_devs[] = { 236 { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_GSICON72, UHSOTYPE_DEFAULT }, 237 { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_ICON225, UHSOTYPE_DEFAULT }, 238 { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_GEHSUPA, UHSOTYPE_DEFAULT }, 239 { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_GTHSUPA, UHSOTYPE_DEFAULT }, 240 { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_GSHSUPA, UHSOTYPE_DEFAULT }, 241 { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_GE40X1, UHSOTYPE_CONFIG }, 242 { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_GE40X2, UHSOTYPE_CONFIG }, 243 { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_GE40X3, UHSOTYPE_CONFIG }, 244 { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_ICON401, UHSOTYPE_CONFIG }, 245 { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_GTM382, UHSOTYPE_CONFIG }, 246 { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_GE40X4, UHSOTYPE_CONFIG }, 247 { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_GTHSUPAM, UHSOTYPE_CONFIG }, 248 { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_ICONEDGE, UHSOTYPE_DEFAULT }, 249 { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_MODHSXPA, UHSOTYPE_ICON321 }, 250 { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_ICON321, UHSOTYPE_ICON321 }, 251 { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_ICON322, UHSOTYPE_ICON321 }, 252 { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_ICON505, UHSOTYPE_CONFIG }, 253 }; 254 255 #define uhso_lookup(p, v) ((const struct uhso_dev *)usb_lookup(uhso_devs, (p), (v))) 256 257 /* IO buffer sizes */ 258 #define UHSO_MUX_WSIZE 64 259 #define UHSO_MUX_RSIZE 1024 260 #define UHSO_BULK_WSIZE 8192 261 #define UHSO_BULK_RSIZE 4096 262 #define UHSO_IFNET_MTU 1500 263 264 /* 265 * Each IO port provided by the modem can be mapped to a network 266 * interface (when hp_ifp != NULL) or a tty (when hp_tp != NULL) 267 * which may be multiplexed and sharing interrupt and control endpoints 268 * from an interface, or using the dedicated bulk endpoints. 269 */ 270 271 struct uhso_port; 272 struct uhso_softc; 273 274 /* uhso callback functions return errno on failure */ 275 typedef int (*uhso_callback)(struct uhso_port *); 276 277 struct uhso_port { 278 struct uhso_softc *hp_sc; /* master softc */ 279 struct tty *hp_tp; /* tty pointer */ 280 struct ifnet *hp_ifp; /* ifnet pointer */ 281 unsigned int hp_flags; /* see below */ 282 int hp_swflags; /* persistent tty flags */ 283 int hp_status; /* modem status */ 284 285 /* port type specific handlers */ 286 uhso_callback hp_abort; /* abort any transfers */ 287 uhso_callback hp_detach; /* detach port completely */ 288 uhso_callback hp_init; /* init port (first open) */ 289 uhso_callback hp_clean; /* clean port (last close) */ 290 uhso_callback hp_write; /* write data */ 291 usbd_callback hp_write_cb; /* write callback */ 292 uhso_callback hp_read; /* read data */ 293 usbd_callback hp_read_cb; /* read callback */ 294 uhso_callback hp_control; /* set control lines */ 295 296 struct usbd_interface *hp_ifh; /* interface handle */ 297 unsigned int hp_index; /* usb request index */ 298 299 int hp_iaddr; /* interrupt endpoint */ 300 struct usbd_pipe *hp_ipipe; /* interrupt pipe */ 301 void *hp_ibuf; /* interrupt buffer */ 302 size_t hp_isize; /* allocated size */ 303 304 int hp_raddr; /* bulk in endpoint */ 305 struct usbd_pipe *hp_rpipe; /* bulk in pipe */ 306 struct usbd_xfer *hp_rxfer; /* input xfer */ 307 void *hp_rbuf; /* input buffer */ 308 size_t hp_rlen; /* fill length */ 309 size_t hp_rsize; /* allocated size */ 310 311 int hp_waddr; /* bulk out endpoint */ 312 struct usbd_pipe *hp_wpipe; /* bulk out pipe */ 313 struct usbd_xfer *hp_wxfer; /* output xfer */ 314 void *hp_wbuf; /* output buffer */ 315 size_t hp_wlen; /* fill length */ 316 size_t hp_wsize; /* allocated size */ 317 318 struct mbuf *hp_mbuf; /* partial packet */ 319 }; 320 321 /* hp_flags */ 322 #define UHSO_PORT_MUXPIPE __BIT(0) /* duplicate ipipe/ibuf references */ 323 #define UHSO_PORT_MUXREADY __BIT(1) /* input is ready */ 324 #define UHSO_PORT_MUXBUSY __BIT(2) /* read in progress */ 325 326 struct uhso_softc { 327 device_t sc_dev; /* self */ 328 struct usbd_device *sc_udev; 329 int sc_refcnt; 330 struct uhso_port *sc_port[UHSO_PORT_MAX]; 331 }; 332 333 #define UHSO_CONFIG_NO 1 334 335 static int uhso_match(device_t, cfdata_t, void *); 336 static void uhso_attach(device_t, device_t, void *); 337 static int uhso_detach(device_t, int); 338 339 340 341 CFATTACH_DECL_NEW(uhso, sizeof(struct uhso_softc), uhso_match, uhso_attach, 342 uhso_detach, NULL); 343 344 Static int uhso_switch_mode(struct usbd_device *); 345 Static int uhso_get_iface_spec(struct usb_attach_arg *, uint8_t, uint8_t *); 346 Static usb_endpoint_descriptor_t *uhso_get_endpoint(struct usbd_interface *, 347 int, int); 348 349 Static void uhso_mux_attach(struct uhso_softc *, struct usbd_interface *, int); 350 Static int uhso_mux_abort(struct uhso_port *); 351 Static int uhso_mux_detach(struct uhso_port *); 352 Static int uhso_mux_init(struct uhso_port *); 353 Static int uhso_mux_clean(struct uhso_port *); 354 Static int uhso_mux_write(struct uhso_port *); 355 Static int uhso_mux_read(struct uhso_port *); 356 Static int uhso_mux_control(struct uhso_port *); 357 Static void uhso_mux_intr(struct usbd_xfer *, void *, usbd_status); 358 359 Static void uhso_bulk_attach(struct uhso_softc *, struct usbd_interface *, int); 360 Static int uhso_bulk_abort(struct uhso_port *); 361 Static int uhso_bulk_detach(struct uhso_port *); 362 Static int uhso_bulk_init(struct uhso_port *); 363 Static int uhso_bulk_clean(struct uhso_port *); 364 Static int uhso_bulk_write(struct uhso_port *); 365 Static int uhso_bulk_read(struct uhso_port *); 366 Static int uhso_bulk_control(struct uhso_port *); 367 Static void uhso_bulk_intr(struct usbd_xfer *, void *, usbd_status); 368 369 Static void uhso_tty_attach(struct uhso_port *); 370 Static void uhso_tty_detach(struct uhso_port *); 371 Static void uhso_tty_read_cb(struct usbd_xfer *, void *, usbd_status); 372 Static void uhso_tty_write_cb(struct usbd_xfer *, void *, usbd_status); 373 374 static dev_type_open(uhso_tty_open); 375 static dev_type_close(uhso_tty_close); 376 static dev_type_read(uhso_tty_read); 377 static dev_type_write(uhso_tty_write); 378 static dev_type_ioctl(uhso_tty_ioctl); 379 static dev_type_stop(uhso_tty_stop); 380 static dev_type_tty(uhso_tty_tty); 381 static dev_type_poll(uhso_tty_poll); 382 383 const struct cdevsw uhso_cdevsw = { 384 .d_open = uhso_tty_open, 385 .d_close = uhso_tty_close, 386 .d_read = uhso_tty_read, 387 .d_write = uhso_tty_write, 388 .d_ioctl = uhso_tty_ioctl, 389 .d_stop = uhso_tty_stop, 390 .d_tty = uhso_tty_tty, 391 .d_poll = uhso_tty_poll, 392 .d_mmap = nommap, 393 .d_kqfilter = ttykqfilter, 394 .d_discard = nodiscard, 395 .d_flag = D_TTY 396 }; 397 398 Static int uhso_tty_init(struct uhso_port *); 399 Static void uhso_tty_clean(struct uhso_port *); 400 Static int uhso_tty_do_ioctl(struct uhso_port *, u_long, void *, int, struct lwp *); 401 Static void uhso_tty_start(struct tty *); 402 Static int uhso_tty_param(struct tty *, struct termios *); 403 Static int uhso_tty_control(struct uhso_port *, u_long, int); 404 405 #define UHSO_UNIT_MASK TTUNIT_MASK 406 #define UHSO_PORT_MASK 0x0000f 407 #define UHSO_DIALOUT_MASK TTDIALOUT_MASK 408 #define UHSO_CALLUNIT_MASK TTCALLUNIT_MASK 409 410 #define UHSOUNIT(x) (TTUNIT(x) >> 4) 411 #define UHSOPORT(x) (TTUNIT(x) & UHSO_PORT_MASK) 412 #define UHSODIALOUT(x) TTDIALOUT(x) 413 #define UHSOMINOR(u, p) ((((u) << 4) & UHSO_UNIT_MASK) | ((p) & UHSO_UNIT_MASK)) 414 415 Static void uhso_ifnet_attach(struct uhso_softc *, struct usbd_interface *, 416 int); 417 Static int uhso_ifnet_abort(struct uhso_port *); 418 Static int uhso_ifnet_detach(struct uhso_port *); 419 Static void uhso_ifnet_read_cb(struct usbd_xfer *, void *, usbd_status); 420 Static void uhso_ifnet_input(struct ifnet *, struct mbuf **, uint8_t *, size_t); 421 Static void uhso_ifnet_write_cb(struct usbd_xfer *, void *, usbd_status); 422 423 Static int uhso_ifnet_ioctl(struct ifnet *, u_long, void *); 424 Static int uhso_ifnet_init(struct uhso_port *); 425 Static void uhso_ifnet_clean(struct uhso_port *); 426 Static void uhso_ifnet_start(struct ifnet *); 427 Static int uhso_ifnet_output(struct ifnet *, struct mbuf *, 428 const struct sockaddr *, const struct rtentry *); 429 430 431 /******************************************************************************* 432 * 433 * USB autoconfig 434 * 435 */ 436 437 static int 438 uhso_match(device_t parent, cfdata_t match, void *aux) 439 { 440 struct usb_attach_arg *uaa = aux; 441 442 /* 443 * don't claim this device if autoswitch is disabled 444 * and it is not in modem mode already 445 */ 446 if (!uhso_autoswitch && uaa->uaa_class != UDCLASS_VENDOR) 447 return UMATCH_NONE; 448 449 if (uhso_lookup(uaa->uaa_vendor, uaa->uaa_product)) 450 return UMATCH_VENDOR_PRODUCT; 451 452 return UMATCH_NONE; 453 } 454 455 static void 456 uhso_attach(device_t parent, device_t self, void *aux) 457 { 458 struct uhso_softc *sc = device_private(self); 459 struct usb_attach_arg *uaa = aux; 460 struct usbd_interface *ifh; 461 char *devinfop; 462 uint8_t count, i, spec; 463 usbd_status status; 464 465 DPRINTF(1, ": sc = %p, self=%p", sc, self); 466 467 sc->sc_dev = self; 468 sc->sc_udev = uaa->uaa_device; 469 470 aprint_naive("\n"); 471 aprint_normal("\n"); 472 473 devinfop = usbd_devinfo_alloc(uaa->uaa_device, 0); 474 aprint_normal_dev(self, "%s\n", devinfop); 475 usbd_devinfo_free(devinfop); 476 477 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev); 478 479 status = usbd_set_config_no(sc->sc_udev, UHSO_CONFIG_NO, 1); 480 if (status != USBD_NORMAL_COMPLETION) { 481 aprint_error_dev(self, "failed to set configuration" 482 ", err=%s\n", usbd_errstr(status)); 483 return; 484 } 485 486 if (uaa->uaa_class != UDCLASS_VENDOR) { 487 aprint_verbose_dev(self, 488 "Switching device into modem mode..\n"); 489 if (uhso_switch_mode(uaa->uaa_device) != 0) 490 aprint_error_dev(self, "modem switch failed\n"); 491 492 return; 493 } 494 495 count = 0; 496 (void)usbd_interface_count(sc->sc_udev, &count); 497 DPRINTF(1, "interface count %d\n", count); 498 499 for (i = 0; i < count; i++) { 500 status = usbd_device2interface_handle(sc->sc_udev, i, &ifh); 501 if (status != USBD_NORMAL_COMPLETION) { 502 aprint_error_dev(self, 503 "could not get interface %d: %s\n", 504 i, usbd_errstr(status)); 505 506 return; 507 } 508 509 if (!uhso_get_iface_spec(uaa, i, &spec)) { 510 aprint_error_dev(self, 511 "could not get interface %d specification\n", i); 512 513 return; 514 } 515 516 if (ISSET(spec, UHSO_IFACE_MUX)) 517 uhso_mux_attach(sc, ifh, UHSOPORT(spec)); 518 519 if (ISSET(spec, UHSO_IFACE_BULK)) 520 uhso_bulk_attach(sc, ifh, UHSOPORT(spec)); 521 522 if (ISSET(spec, UHSO_IFACE_IFNET)) 523 uhso_ifnet_attach(sc, ifh, UHSOPORT(spec)); 524 } 525 526 if (!pmf_device_register(self, NULL, NULL)) 527 aprint_error_dev(self, "couldn't establish power handler\n"); 528 } 529 530 static int 531 uhso_detach(device_t self, int flags) 532 { 533 struct uhso_softc *sc = device_private(self); 534 struct uhso_port *hp; 535 devmajor_t major; 536 devminor_t minor; 537 unsigned int i; 538 int s; 539 540 pmf_device_deregister(self); 541 542 for (i = 0; i < UHSO_PORT_MAX; i++) { 543 hp = sc->sc_port[i]; 544 if (hp != NULL) 545 (*hp->hp_abort)(hp); 546 } 547 548 s = splusb(); 549 if (sc->sc_refcnt-- > 0) { 550 DPRINTF(1, "waiting for refcnt (%d)..\n", sc->sc_refcnt); 551 usb_detach_waitold(sc->sc_dev); 552 } 553 splx(s); 554 555 /* 556 * XXX the tty close routine increases/decreases refcnt causing 557 * XXX another usb_detach_wakeupold() does it matter, should these 558 * XXX be before the detach_wait? or before the abort? 559 */ 560 561 /* Nuke the vnodes for any open instances (calls close). */ 562 major = cdevsw_lookup_major(&uhso_cdevsw); 563 minor = UHSOMINOR(device_unit(sc->sc_dev), 0); 564 vdevgone(major, minor, minor + UHSO_PORT_MAX, VCHR); 565 minor = UHSOMINOR(device_unit(sc->sc_dev), 0) | UHSO_DIALOUT_MASK; 566 vdevgone(major, minor, minor + UHSO_PORT_MAX, VCHR); 567 minor = UHSOMINOR(device_unit(sc->sc_dev), 0) | UHSO_CALLUNIT_MASK; 568 vdevgone(major, minor, minor + UHSO_PORT_MAX, VCHR); 569 570 for (i = 0; i < UHSO_PORT_MAX; i++) { 571 hp = sc->sc_port[i]; 572 if (hp != NULL) 573 (*hp->hp_detach)(hp); 574 } 575 576 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev); 577 578 return 0; 579 } 580 581 /* 582 * Send SCSI REZERO_UNIT command to switch device into modem mode 583 */ 584 Static int 585 uhso_switch_mode(struct usbd_device *udev) 586 { 587 umass_bbb_cbw_t cmd; 588 usb_endpoint_descriptor_t *ed; 589 struct usbd_interface *ifh; 590 struct usbd_pipe *pipe; 591 struct usbd_xfer *xfer; 592 usbd_status status; 593 594 status = usbd_device2interface_handle(udev, 0, &ifh); 595 if (status != USBD_NORMAL_COMPLETION) 596 return EIO; 597 598 ed = uhso_get_endpoint(ifh, UE_BULK, UE_DIR_OUT); 599 if (ed == NULL) 600 return ENODEV; 601 602 status = usbd_open_pipe(ifh, ed->bEndpointAddress, 0, &pipe); 603 if (status != USBD_NORMAL_COMPLETION) 604 return EIO; 605 606 int error = usbd_create_xfer(pipe, sizeof(cmd), 0, 0, &xfer); 607 if (error) 608 return error; 609 610 USETDW(cmd.dCBWSignature, CBWSIGNATURE); 611 USETDW(cmd.dCBWTag, 1); 612 USETDW(cmd.dCBWDataTransferLength, 0); 613 cmd.bCBWFlags = CBWFLAGS_OUT; 614 cmd.bCBWLUN = 0; 615 cmd.bCDBLength = 6; 616 617 memset(&cmd.CBWCDB, 0, CBWCDBLENGTH); 618 cmd.CBWCDB[0] = SCSI_REZERO_UNIT; 619 620 usbd_setup_xfer(xfer, NULL, &cmd, sizeof(cmd), 621 USBD_SYNCHRONOUS, USBD_DEFAULT_TIMEOUT, NULL); 622 623 status = usbd_transfer(xfer); 624 625 usbd_destroy_xfer(xfer); 626 usbd_close_pipe(pipe); 627 628 return status == USBD_NORMAL_COMPLETION ? 0 : EIO; 629 } 630 631 Static int 632 uhso_get_iface_spec(struct usb_attach_arg *uaa, uint8_t ifnum, uint8_t *spec) 633 { 634 const struct uhso_dev *hd; 635 uint8_t config[17]; 636 usb_device_request_t req; 637 usbd_status status; 638 639 hd = uhso_lookup(uaa->uaa_vendor, uaa->uaa_product); 640 KASSERT(hd != NULL); 641 642 switch (hd->type) { 643 case UHSOTYPE_DEFAULT: 644 if (ifnum >= __arraycount(uhso_spec_default)) 645 break; 646 647 *spec = uhso_spec_default[ifnum]; 648 return 1; 649 650 case UHSOTYPE_ICON321: 651 if (ifnum >= __arraycount(uhso_spec_icon321)) 652 break; 653 654 *spec = uhso_spec_icon321[ifnum]; 655 return 1; 656 657 case UHSOTYPE_CONFIG: 658 req.bmRequestType = UT_READ_VENDOR_DEVICE; 659 req.bRequest = 0x86; /* "Config Info" */ 660 USETW(req.wValue, 0); 661 USETW(req.wIndex, 0); 662 USETW(req.wLength, sizeof(config)); 663 664 status = usbd_do_request(uaa->uaa_device, &req, config); 665 if (status != USBD_NORMAL_COMPLETION) 666 break; 667 668 if (ifnum >= __arraycount(config) 669 || config[ifnum] >= __arraycount(uhso_spec_config)) 670 break; 671 672 *spec = uhso_spec_config[config[ifnum]]; 673 674 /* 675 * Apparently some modems also have a CRC bug that is 676 * indicated by ISSET(config[16], __BIT(0)) but we dont 677 * handle it at this time. 678 */ 679 return 1; 680 681 default: 682 DPRINTF(0, "unknown interface type\n"); 683 break; 684 } 685 686 return 0; 687 } 688 689 Static usb_endpoint_descriptor_t * 690 uhso_get_endpoint(struct usbd_interface *ifh, int type, int dir) 691 { 692 usb_endpoint_descriptor_t *ed; 693 uint8_t count, i; 694 695 count = 0; 696 (void)usbd_endpoint_count(ifh, &count); 697 698 for (i = 0; i < count; i++) { 699 ed = usbd_interface2endpoint_descriptor(ifh, i); 700 if (ed != NULL 701 && UE_GET_XFERTYPE(ed->bmAttributes) == type 702 && UE_GET_DIR(ed->bEndpointAddress) == dir) 703 return ed; 704 } 705 706 return NULL; 707 } 708 709 710 /****************************************************************************** 711 * 712 * Multiplexed ports signal with the interrupt endpoint to indicate 713 * when data is available for reading, and a separate request is made on 714 * the control endpoint to read or write on each port. The offsets in the 715 * table below relate to bit numbers in the mux mask, identifying each port. 716 */ 717 718 Static const int uhso_mux_port[] = { 719 UHSO_PORT_CONTROL, 720 UHSO_PORT_APP, 721 UHSO_PORT_PCSC, 722 UHSO_PORT_GPS, 723 UHSO_PORT_APP2, 724 }; 725 726 Static void 727 uhso_mux_attach(struct uhso_softc *sc, struct usbd_interface *ifh, int index) 728 { 729 usbd_desc_iter_t iter; 730 const usb_descriptor_t *desc; 731 usb_endpoint_descriptor_t *ed; 732 struct usbd_pipe *pipe; 733 struct uhso_port *hp; 734 uint8_t *buf; 735 size_t size; 736 unsigned int i, mux, flags; 737 int addr; 738 usbd_status status; 739 740 ed = uhso_get_endpoint(ifh, UE_INTERRUPT, UE_DIR_IN); 741 if (ed == NULL) { 742 aprint_error_dev(sc->sc_dev, "no interrupt endpoint\n"); 743 return; 744 } 745 addr = ed->bEndpointAddress; 746 size = UGETW(ed->wMaxPacketSize); 747 748 /* 749 * There should be an additional "Class Specific" descriptor on 750 * the mux interface containing a single byte with a bitmask of 751 * enabled ports. We need to look through the device descriptor 752 * to find it and the port index is found from the uhso_mux_port 753 * array, above. 754 */ 755 usb_desc_iter_init(sc->sc_udev, &iter); 756 757 /* skip past the current interface descriptor */ 758 iter.cur = (const uByte *)usbd_get_interface_descriptor(ifh); 759 desc = usb_desc_iter_next(&iter); 760 761 for (;;) { 762 desc = usb_desc_iter_next(&iter); 763 if (desc == NULL 764 || desc->bDescriptorType == UDESC_INTERFACE) { 765 mux = 0; 766 break; /* not found */ 767 } 768 769 if (desc->bDescriptorType == UDESC_CS_INTERFACE 770 && desc->bLength == 3) { 771 mux = ((const uint8_t *)desc)[2]; 772 break; 773 } 774 } 775 776 DPRINTF(1, "addr=%d, size=%zd, mux=0x%02x\n", addr, size, mux); 777 778 buf = kmem_alloc(size, KM_SLEEP); 779 status = usbd_open_pipe_intr(ifh, addr, USBD_SHORT_XFER_OK, &pipe, 780 sc, buf, size, uhso_mux_intr, USBD_DEFAULT_INTERVAL); 781 782 if (status != USBD_NORMAL_COMPLETION) { 783 aprint_error_dev(sc->sc_dev, 784 "failed to open interrupt pipe: %s", usbd_errstr(status)); 785 786 kmem_free(buf, size); 787 return; 788 } 789 790 flags = 0; 791 for (i = 0; i < __arraycount(uhso_mux_port); i++) { 792 if (ISSET(mux, __BIT(i))) { 793 if (sc->sc_port[uhso_mux_port[i]] != NULL) { 794 aprint_error_dev(sc->sc_dev, 795 "mux port %d is duplicate!\n", i); 796 797 continue; 798 } 799 800 hp = kmem_zalloc(sizeof(struct uhso_port), KM_SLEEP); 801 sc->sc_port[uhso_mux_port[i]] = hp; 802 803 hp->hp_sc = sc; 804 hp->hp_index = i; 805 hp->hp_ipipe = pipe; 806 hp->hp_ibuf = buf; 807 hp->hp_isize = size; 808 hp->hp_flags = flags; 809 hp->hp_abort = uhso_mux_abort; 810 hp->hp_detach = uhso_mux_detach; 811 hp->hp_init = uhso_mux_init; 812 hp->hp_clean = uhso_mux_clean; 813 hp->hp_write = uhso_mux_write; 814 hp->hp_write_cb = uhso_tty_write_cb; 815 hp->hp_read = uhso_mux_read; 816 hp->hp_read_cb = uhso_tty_read_cb; 817 hp->hp_control = uhso_mux_control; 818 hp->hp_wsize = UHSO_MUX_WSIZE; 819 hp->hp_rsize = UHSO_MUX_RSIZE; 820 821 uhso_tty_attach(hp); 822 823 aprint_normal_dev(sc->sc_dev, 824 "%s (port %d) attached as mux tty\n", 825 uhso_port_name[uhso_mux_port[i]], uhso_mux_port[i]); 826 827 /* 828 * As the pipe handle is stored in each mux, mark 829 * secondary references so they don't get released 830 */ 831 flags = UHSO_PORT_MUXPIPE; 832 } 833 } 834 835 if (flags == 0) { 836 /* for whatever reasons, nothing was attached */ 837 usbd_abort_pipe(pipe); 838 usbd_close_pipe(pipe); 839 kmem_free(buf, size); 840 } 841 } 842 843 Static int 844 uhso_mux_abort(struct uhso_port *hp) 845 { 846 struct uhso_softc *sc = hp->hp_sc; 847 848 DPRINTF(1, "hp=%p\n", hp); 849 850 if (!ISSET(hp->hp_flags, UHSO_PORT_MUXPIPE)) 851 usbd_abort_pipe(hp->hp_ipipe); 852 853 usbd_abort_default_pipe(sc->sc_udev); 854 855 return (*hp->hp_clean)(hp); 856 } 857 858 Static int 859 uhso_mux_detach(struct uhso_port *hp) 860 { 861 862 DPRINTF(1, "hp=%p\n", hp); 863 864 if (!ISSET(hp->hp_flags, UHSO_PORT_MUXPIPE)) { 865 DPRINTF(1, "interrupt pipe closed\n"); 866 usbd_abort_pipe(hp->hp_ipipe); 867 usbd_close_pipe(hp->hp_ipipe); 868 kmem_free(hp->hp_ibuf, hp->hp_isize); 869 } 870 871 uhso_tty_detach(hp); 872 kmem_free(hp, sizeof(struct uhso_port)); 873 return 0; 874 } 875 876 Static int 877 uhso_mux_init(struct uhso_port *hp) 878 { 879 880 DPRINTF(1, "hp=%p\n", hp); 881 882 CLR(hp->hp_flags, UHSO_PORT_MUXBUSY | UHSO_PORT_MUXREADY); 883 SET(hp->hp_status, TIOCM_DSR | TIOCM_CAR); 884 885 struct uhso_softc *sc = hp->hp_sc; 886 struct usbd_pipe *pipe0 = usbd_get_pipe0(sc->sc_udev); 887 int error; 888 889 error = usbd_create_xfer(pipe0, hp->hp_rsize, 0, 0, &hp->hp_rxfer); 890 if (error) 891 return error; 892 893 hp->hp_rbuf = usbd_get_buffer(hp->hp_rxfer); 894 895 error = usbd_create_xfer(pipe0, hp->hp_wsize, 0, 0, &hp->hp_wxfer); 896 if (error) 897 return error; 898 899 hp->hp_wbuf = usbd_get_buffer(hp->hp_wxfer); 900 901 return 0; 902 } 903 904 Static int 905 uhso_mux_clean(struct uhso_port *hp) 906 { 907 908 DPRINTF(1, "hp=%p\n", hp); 909 910 CLR(hp->hp_flags, UHSO_PORT_MUXREADY); 911 CLR(hp->hp_status, TIOCM_DTR | TIOCM_DSR | TIOCM_CAR); 912 return 0; 913 } 914 915 Static int 916 uhso_mux_write(struct uhso_port *hp) 917 { 918 struct uhso_softc *sc = hp->hp_sc; 919 usb_device_request_t req; 920 usbd_status status; 921 922 DPRINTF(5, "hp=%p, index=%d, wlen=%zd\n", hp, hp->hp_index, 923 hp->hp_wlen); 924 925 req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 926 req.bRequest = UCDC_SEND_ENCAPSULATED_COMMAND; 927 USETW(req.wValue, 0); 928 USETW(req.wIndex, hp->hp_index); 929 USETW(req.wLength, hp->hp_wlen); 930 931 usbd_setup_default_xfer(hp->hp_wxfer, sc->sc_udev, hp, USBD_NO_TIMEOUT, 932 &req, hp->hp_wbuf, hp->hp_wlen, 0, hp->hp_write_cb); 933 934 status = usbd_transfer(hp->hp_wxfer); 935 if (status != USBD_IN_PROGRESS) { 936 DPRINTF(0, "non-normal status %s\n", usbd_errstr(status)); 937 return EIO; 938 } 939 940 sc->sc_refcnt++; 941 return 0; 942 } 943 944 Static int 945 uhso_mux_read(struct uhso_port *hp) 946 { 947 struct uhso_softc *sc = hp->hp_sc; 948 usb_device_request_t req; 949 usbd_status status; 950 951 CLR(hp->hp_flags, UHSO_PORT_MUXBUSY); 952 953 if (hp->hp_rlen == 0 && !ISSET(hp->hp_flags, UHSO_PORT_MUXREADY)) 954 return 0; 955 956 SET(hp->hp_flags, UHSO_PORT_MUXBUSY); 957 CLR(hp->hp_flags, UHSO_PORT_MUXREADY); 958 959 DPRINTF(5, "hp=%p, index=%d\n", hp, hp->hp_index); 960 961 req.bmRequestType = UT_READ_CLASS_INTERFACE; 962 req.bRequest = UCDC_GET_ENCAPSULATED_RESPONSE; 963 USETW(req.wValue, 0); 964 USETW(req.wIndex, hp->hp_index); 965 USETW(req.wLength, hp->hp_rsize); 966 967 usbd_setup_default_xfer(hp->hp_rxfer, sc->sc_udev, hp, USBD_NO_TIMEOUT, 968 &req, hp->hp_rbuf, hp->hp_rsize, USBD_SHORT_XFER_OK, 969 hp->hp_read_cb); 970 971 status = usbd_transfer(hp->hp_rxfer); 972 if (status != USBD_IN_PROGRESS) { 973 DPRINTF(0, "non-normal status %s\n", usbd_errstr(status)); 974 CLR(hp->hp_flags, UHSO_PORT_MUXBUSY); 975 return EIO; 976 } 977 978 sc->sc_refcnt++; 979 return 0; 980 } 981 982 Static int 983 uhso_mux_control(struct uhso_port *hp) 984 { 985 986 DPRINTF(1, "hp=%p\n", hp); 987 988 return 0; 989 } 990 991 Static void 992 uhso_mux_intr(struct usbd_xfer *xfer, void * p, usbd_status status) 993 { 994 struct uhso_softc *sc = p; 995 struct uhso_port *hp; 996 uint32_t cc; 997 uint8_t *buf; 998 unsigned int i; 999 1000 if (status != USBD_NORMAL_COMPLETION) { 1001 DPRINTF(0, "non-normal status %s\n", usbd_errstr(status)); 1002 return; 1003 } 1004 1005 usbd_get_xfer_status(xfer, NULL, (void **)&buf, &cc, NULL); 1006 if (cc == 0) 1007 return; 1008 1009 DPRINTF(5, "mux mask 0x%02x, cc=%u\n", buf[0], cc); 1010 1011 for (i = 0; i < __arraycount(uhso_mux_port); i++) { 1012 if (!ISSET(buf[0], __BIT(i))) 1013 continue; 1014 1015 DPRINTF(5, "mux %d port %d\n", i, uhso_mux_port[i]); 1016 hp = sc->sc_port[uhso_mux_port[i]]; 1017 if (hp == NULL 1018 || hp->hp_tp == NULL 1019 || !ISSET(hp->hp_status, TIOCM_DTR)) 1020 continue; 1021 1022 SET(hp->hp_flags, UHSO_PORT_MUXREADY); 1023 if (ISSET(hp->hp_flags, UHSO_PORT_MUXBUSY)) 1024 continue; 1025 1026 uhso_mux_read(hp); 1027 } 1028 } 1029 1030 1031 /****************************************************************************** 1032 * 1033 * Bulk ports operate using the bulk endpoints on an interface, though 1034 * the Modem port (at least) may have an interrupt endpoint that will pass 1035 * CDC Notification messages with the modem status. 1036 */ 1037 1038 Static void 1039 uhso_bulk_attach(struct uhso_softc *sc, struct usbd_interface *ifh, int index) 1040 { 1041 usb_endpoint_descriptor_t *ed; 1042 usb_interface_descriptor_t *id; 1043 struct uhso_port *hp; 1044 int in, out; 1045 1046 ed = uhso_get_endpoint(ifh, UE_BULK, UE_DIR_IN); 1047 if (ed == NULL) { 1048 aprint_error_dev(sc->sc_dev, "bulk-in endpoint not found\n"); 1049 return; 1050 } 1051 in = ed->bEndpointAddress; 1052 1053 ed = uhso_get_endpoint(ifh, UE_BULK, UE_DIR_OUT); 1054 if (ed == NULL) { 1055 aprint_error_dev(sc->sc_dev, "bulk-out endpoint not found\n"); 1056 return; 1057 } 1058 out = ed->bEndpointAddress; 1059 1060 id = usbd_get_interface_descriptor(ifh); 1061 if (id == NULL) { 1062 aprint_error_dev(sc->sc_dev, 1063 "interface descriptor not found\n"); 1064 return; 1065 } 1066 1067 DPRINTF(1, "bulk endpoints in=%x, out=%x\n", in, out); 1068 1069 if (sc->sc_port[index] != NULL) { 1070 aprint_error_dev(sc->sc_dev, "bulk port %d is duplicate!\n", 1071 index); 1072 1073 return; 1074 } 1075 1076 hp = kmem_zalloc(sizeof(struct uhso_port), KM_SLEEP); 1077 sc->sc_port[index] = hp; 1078 1079 hp->hp_sc = sc; 1080 hp->hp_ifh = ifh; 1081 hp->hp_index = id->bInterfaceNumber; 1082 hp->hp_raddr = in; 1083 hp->hp_waddr = out; 1084 hp->hp_abort = uhso_bulk_abort; 1085 hp->hp_detach = uhso_bulk_detach; 1086 hp->hp_init = uhso_bulk_init; 1087 hp->hp_clean = uhso_bulk_clean; 1088 hp->hp_write = uhso_bulk_write; 1089 hp->hp_write_cb = uhso_tty_write_cb; 1090 hp->hp_read = uhso_bulk_read; 1091 hp->hp_read_cb = uhso_tty_read_cb; 1092 hp->hp_control = uhso_bulk_control; 1093 hp->hp_wsize = UHSO_BULK_WSIZE; 1094 hp->hp_rsize = UHSO_BULK_RSIZE; 1095 1096 if (index == UHSO_PORT_MODEM) { 1097 ed = uhso_get_endpoint(ifh, UE_INTERRUPT, UE_DIR_IN); 1098 if (ed != NULL) { 1099 hp->hp_iaddr = ed->bEndpointAddress; 1100 hp->hp_isize = UGETW(ed->wMaxPacketSize); 1101 } 1102 } 1103 1104 uhso_tty_attach(hp); 1105 1106 aprint_normal_dev(sc->sc_dev, 1107 "%s (port %d) attached as bulk tty\n", 1108 uhso_port_name[index], index); 1109 } 1110 1111 Static int 1112 uhso_bulk_abort(struct uhso_port *hp) 1113 { 1114 1115 DPRINTF(1, "hp=%p\n", hp); 1116 1117 return (*hp->hp_clean)(hp); 1118 } 1119 1120 Static int 1121 uhso_bulk_detach(struct uhso_port *hp) 1122 { 1123 1124 DPRINTF(1, "hp=%p\n", hp); 1125 1126 uhso_tty_detach(hp); 1127 kmem_free(hp, sizeof(struct uhso_port)); 1128 return 0; 1129 } 1130 1131 Static int 1132 uhso_bulk_init(struct uhso_port *hp) 1133 { 1134 usbd_status status; 1135 1136 DPRINTF(1, "hp=%p\n", hp); 1137 1138 if (hp->hp_isize > 0) { 1139 hp->hp_ibuf = kmem_alloc(hp->hp_isize, KM_SLEEP); 1140 1141 status = usbd_open_pipe_intr(hp->hp_ifh, hp->hp_iaddr, 1142 USBD_SHORT_XFER_OK, &hp->hp_ipipe, hp, hp->hp_ibuf, 1143 hp->hp_isize, uhso_bulk_intr, USBD_DEFAULT_INTERVAL); 1144 1145 if (status != USBD_NORMAL_COMPLETION) { 1146 DPRINTF(0, "interrupt pipe open failed: %s\n", 1147 usbd_errstr(status)); 1148 1149 return EIO; 1150 } 1151 } 1152 1153 status = usbd_open_pipe(hp->hp_ifh, hp->hp_raddr, 0, &hp->hp_rpipe); 1154 if (status != USBD_NORMAL_COMPLETION) { 1155 DPRINTF(0, "read pipe open failed: %s\n", usbd_errstr(status)); 1156 return EIO; 1157 } 1158 1159 status = usbd_open_pipe(hp->hp_ifh, hp->hp_waddr, 0, &hp->hp_wpipe); 1160 if (status != USBD_NORMAL_COMPLETION) { 1161 DPRINTF(0, "write pipe open failed: %s\n", usbd_errstr(status)); 1162 return EIO; 1163 } 1164 1165 int error = usbd_create_xfer(hp->hp_rpipe, hp->hp_rsize, 1166 0, 0, &hp->hp_rxfer); 1167 if (error) 1168 return error; 1169 1170 hp->hp_rbuf = usbd_get_buffer(hp->hp_rxfer); 1171 1172 error = usbd_create_xfer(hp->hp_wpipe, hp->hp_wsize, 0, 0, 1173 &hp->hp_wxfer); 1174 if (error) 1175 return error; 1176 hp->hp_wbuf = usbd_get_buffer(hp->hp_wxfer); 1177 1178 return 0; 1179 } 1180 1181 Static int 1182 uhso_bulk_clean(struct uhso_port *hp) 1183 { 1184 1185 DPRINTF(1, "hp=%p\n", hp); 1186 1187 if (hp->hp_ipipe != NULL) { 1188 usbd_abort_pipe(hp->hp_ipipe); 1189 usbd_close_pipe(hp->hp_ipipe); 1190 hp->hp_ipipe = NULL; 1191 } 1192 1193 if (hp->hp_ibuf != NULL) { 1194 kmem_free(hp->hp_ibuf, hp->hp_isize); 1195 hp->hp_ibuf = NULL; 1196 } 1197 1198 if (hp->hp_rpipe != NULL) { 1199 usbd_abort_pipe(hp->hp_rpipe); 1200 } 1201 1202 if (hp->hp_wpipe != NULL) { 1203 usbd_abort_pipe(hp->hp_wpipe); 1204 } 1205 1206 if (hp->hp_rxfer != NULL) { 1207 usbd_destroy_xfer(hp->hp_rxfer); 1208 hp->hp_rxfer = NULL; 1209 hp->hp_rbuf = NULL; 1210 } 1211 1212 if (hp->hp_wxfer != NULL) { 1213 usbd_destroy_xfer(hp->hp_wxfer); 1214 hp->hp_wxfer = NULL; 1215 hp->hp_wbuf = NULL; 1216 } 1217 1218 if (hp->hp_rpipe != NULL) { 1219 usbd_close_pipe(hp->hp_rpipe); 1220 hp->hp_rpipe = NULL; 1221 } 1222 1223 if (hp->hp_wpipe != NULL) { 1224 usbd_close_pipe(hp->hp_wpipe); 1225 hp->hp_wpipe = NULL; 1226 } 1227 1228 return 0; 1229 } 1230 1231 Static int 1232 uhso_bulk_write(struct uhso_port *hp) 1233 { 1234 struct uhso_softc *sc = hp->hp_sc; 1235 usbd_status status; 1236 1237 DPRINTF(5, "hp=%p, wlen=%zd\n", hp, hp->hp_wlen); 1238 1239 usbd_setup_xfer(hp->hp_wxfer, hp, hp->hp_wbuf, hp->hp_wlen, 0, 1240 USBD_NO_TIMEOUT, hp->hp_write_cb); 1241 1242 status = usbd_transfer(hp->hp_wxfer); 1243 if (status != USBD_IN_PROGRESS) { 1244 DPRINTF(0, "non-normal status %s\n", usbd_errstr(status)); 1245 return EIO; 1246 } 1247 1248 sc->sc_refcnt++; 1249 return 0; 1250 } 1251 1252 Static int 1253 uhso_bulk_read(struct uhso_port *hp) 1254 { 1255 struct uhso_softc *sc = hp->hp_sc; 1256 usbd_status status; 1257 1258 DPRINTF(5, "hp=%p\n", hp); 1259 1260 usbd_setup_xfer(hp->hp_rxfer, hp, hp->hp_rbuf, hp->hp_rsize, 1261 USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, hp->hp_read_cb); 1262 1263 status = usbd_transfer(hp->hp_rxfer); 1264 if (status != USBD_IN_PROGRESS) { 1265 DPRINTF(0, "non-normal status %s\n", usbd_errstr(status)); 1266 return EIO; 1267 } 1268 1269 sc->sc_refcnt++; 1270 return 0; 1271 } 1272 1273 Static int 1274 uhso_bulk_control(struct uhso_port *hp) 1275 { 1276 struct uhso_softc *sc = hp->hp_sc; 1277 usb_device_request_t req; 1278 usbd_status status; 1279 int val; 1280 1281 DPRINTF(1, "hp=%p\n", hp); 1282 1283 if (hp->hp_isize == 0) 1284 return 0; 1285 1286 val = 0; 1287 if (ISSET(hp->hp_status, TIOCM_DTR)) 1288 SET(val, UCDC_LINE_DTR); 1289 if (ISSET(hp->hp_status, TIOCM_RTS)) 1290 SET(val, UCDC_LINE_RTS); 1291 1292 req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 1293 req.bRequest = UCDC_SET_CONTROL_LINE_STATE; 1294 USETW(req.wValue, val); 1295 USETW(req.wIndex, hp->hp_index); 1296 USETW(req.wLength, 0); 1297 1298 sc->sc_refcnt++; 1299 1300 status = usbd_do_request(sc->sc_udev, &req, NULL); 1301 1302 if (--sc->sc_refcnt < 0) 1303 usb_detach_wakeupold(sc->sc_dev); 1304 1305 if (status != USBD_NORMAL_COMPLETION) { 1306 DPRINTF(0, "non-normal status %s\n", usbd_errstr(status)); 1307 return EIO; 1308 } 1309 1310 return 0; 1311 } 1312 1313 Static void 1314 uhso_bulk_intr(struct usbd_xfer *xfer, void * p, usbd_status status) 1315 { 1316 struct uhso_port *hp = p; 1317 struct tty *tp = hp->hp_tp; 1318 usb_cdc_notification_t *msg; 1319 uint32_t cc; 1320 int s, old; 1321 1322 if (status != USBD_NORMAL_COMPLETION) { 1323 DPRINTF(0, "non-normal status %s\n", usbd_errstr(status)); 1324 return; 1325 } 1326 1327 usbd_get_xfer_status(xfer, NULL, (void **)&msg, &cc, NULL); 1328 1329 if (cc < UCDC_NOTIFICATION_LENGTH 1330 || msg->bmRequestType != UCDC_NOTIFICATION 1331 || msg->bNotification != UCDC_N_SERIAL_STATE 1332 || UGETW(msg->wValue) != 0 1333 || UGETW(msg->wIndex) != hp->hp_index 1334 || UGETW(msg->wLength) < 1) 1335 return; 1336 1337 DPRINTF(5, "state=%02x\n", msg->data[0]); 1338 1339 old = hp->hp_status; 1340 CLR(hp->hp_status, TIOCM_RNG | TIOCM_DSR | TIOCM_CAR); 1341 if (ISSET(msg->data[0], UCDC_N_SERIAL_RI)) 1342 SET(hp->hp_status, TIOCM_RNG); 1343 if (ISSET(msg->data[0], UCDC_N_SERIAL_DSR)) 1344 SET(hp->hp_status, TIOCM_DSR); 1345 if (ISSET(msg->data[0], UCDC_N_SERIAL_DCD)) 1346 SET(hp->hp_status, TIOCM_CAR); 1347 1348 if (ISSET(hp->hp_status ^ old, TIOCM_CAR)) { 1349 s = spltty(); 1350 tp->t_linesw->l_modem(tp, ISSET(hp->hp_status, TIOCM_CAR)); 1351 splx(s); 1352 } 1353 1354 if (ISSET((hp->hp_status ^ old), TIOCM_RNG | TIOCM_DSR | TIOCM_CAR)) 1355 DPRINTF(1, "RNG %s, DSR %s, DCD %s\n", 1356 (ISSET(hp->hp_status, TIOCM_RNG) ? "on" : "off"), 1357 (ISSET(hp->hp_status, TIOCM_DSR) ? "on" : "off"), 1358 (ISSET(hp->hp_status, TIOCM_CAR) ? "on" : "off")); 1359 } 1360 1361 1362 /****************************************************************************** 1363 * 1364 * TTY management 1365 * 1366 */ 1367 1368 Static void 1369 uhso_tty_attach(struct uhso_port *hp) 1370 { 1371 struct tty *tp; 1372 1373 tp = tty_alloc(); 1374 tp->t_oproc = uhso_tty_start; 1375 tp->t_param = uhso_tty_param; 1376 1377 hp->hp_tp = tp; 1378 tty_attach(tp); 1379 1380 DPRINTF(1, "hp=%p, tp=%p\n", hp, tp); 1381 } 1382 1383 Static void 1384 uhso_tty_detach(struct uhso_port *hp) 1385 { 1386 1387 DPRINTF(1, "hp=%p\n", hp); 1388 1389 uhso_tty_clean(hp); 1390 1391 tty_detach(hp->hp_tp); 1392 tty_free(hp->hp_tp); 1393 hp->hp_tp = NULL; 1394 } 1395 1396 Static void 1397 uhso_tty_write_cb(struct usbd_xfer *xfer, void * p, usbd_status status) 1398 { 1399 struct uhso_port *hp = p; 1400 struct uhso_softc *sc = hp->hp_sc; 1401 struct tty *tp = hp->hp_tp; 1402 uint32_t cc; 1403 int s; 1404 1405 if (--sc->sc_refcnt < 0) 1406 usb_detach_wakeupold(sc->sc_dev); 1407 1408 if (status != USBD_NORMAL_COMPLETION) { 1409 DPRINTF(0, "non-normal status %s\n", usbd_errstr(status)); 1410 1411 if (status == USBD_STALLED && hp->hp_wpipe != NULL) 1412 usbd_clear_endpoint_stall_async(hp->hp_wpipe); 1413 else 1414 return; 1415 } else { 1416 usbd_get_xfer_status(xfer, NULL, NULL, &cc, NULL); 1417 1418 DPRINTF(5, "wrote %d bytes (of %zd)\n", cc, hp->hp_wlen); 1419 if (cc != hp->hp_wlen) 1420 DPRINTF(0, "cc=%u, wlen=%zd\n", cc, hp->hp_wlen); 1421 } 1422 1423 s = spltty(); 1424 CLR(tp->t_state, TS_BUSY); 1425 tp->t_linesw->l_start(tp); 1426 splx(s); 1427 } 1428 1429 Static void 1430 uhso_tty_read_cb(struct usbd_xfer *xfer, void * p, usbd_status status) 1431 { 1432 struct uhso_port *hp = p; 1433 struct uhso_softc *sc = hp->hp_sc; 1434 struct tty *tp = hp->hp_tp; 1435 uint8_t *cp; 1436 uint32_t cc; 1437 int s; 1438 1439 if (--sc->sc_refcnt < 0) 1440 usb_detach_wakeupold(sc->sc_dev); 1441 1442 if (status != USBD_NORMAL_COMPLETION) { 1443 DPRINTF(0, "non-normal status: %s\n", usbd_errstr(status)); 1444 1445 if (status == USBD_STALLED && hp->hp_rpipe != NULL) 1446 usbd_clear_endpoint_stall_async(hp->hp_rpipe); 1447 else 1448 return; 1449 1450 hp->hp_rlen = 0; 1451 } else { 1452 usbd_get_xfer_status(xfer, NULL, (void **)&cp, &cc, NULL); 1453 1454 hp->hp_rlen = cc; 1455 DPRINTF(5, "read %d bytes\n", cc); 1456 1457 s = spltty(); 1458 while (cc > 0) { 1459 if (tp->t_linesw->l_rint(*cp++, tp) == -1) { 1460 DPRINTF(0, "lost %d bytes\n", cc); 1461 break; 1462 } 1463 1464 cc--; 1465 } 1466 splx(s); 1467 } 1468 1469 (*hp->hp_read)(hp); 1470 } 1471 1472 1473 /****************************************************************************** 1474 * 1475 * TTY subsystem 1476 * 1477 */ 1478 1479 static int 1480 uhso_tty_open(dev_t dev, int flag, int mode, struct lwp *l) 1481 { 1482 struct uhso_softc *sc; 1483 struct uhso_port *hp; 1484 struct tty *tp; 1485 int error, s; 1486 1487 DPRINTF(1, "unit %d port %d\n", UHSOUNIT(dev), UHSOPORT(dev)); 1488 1489 sc = device_lookup_private(&uhso_cd, UHSOUNIT(dev)); 1490 if (sc == NULL 1491 || !device_is_active(sc->sc_dev) 1492 || UHSOPORT(dev) >= UHSO_PORT_MAX) 1493 return ENXIO; 1494 1495 hp = sc->sc_port[UHSOPORT(dev)]; 1496 if (hp == NULL || hp->hp_tp == NULL) 1497 return ENXIO; 1498 1499 tp = hp->hp_tp; 1500 if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) 1501 return EBUSY; 1502 1503 error = 0; 1504 s = spltty(); 1505 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 1506 tp->t_dev = dev; 1507 error = uhso_tty_init(hp); 1508 } 1509 splx(s); 1510 1511 if (error == 0) { 1512 error = ttyopen(tp, UHSODIALOUT(dev), ISSET(flag, O_NONBLOCK)); 1513 if (error == 0) { 1514 error = tp->t_linesw->l_open(dev, tp); 1515 } 1516 } 1517 1518 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) 1519 uhso_tty_clean(hp); 1520 1521 DPRINTF(1, "sc=%p, hp=%p, tp=%p, error=%d\n", sc, hp, tp, error); 1522 1523 return error; 1524 } 1525 1526 Static int 1527 uhso_tty_init(struct uhso_port *hp) 1528 { 1529 struct tty *tp = hp->hp_tp; 1530 struct termios t; 1531 int error; 1532 1533 DPRINTF(1, "sc=%p, hp=%p, tp=%p\n", sc, hp, tp); 1534 1535 /* 1536 * Initialize the termios status to the defaults. Add in the 1537 * sticky bits from TIOCSFLAGS. 1538 */ 1539 t.c_ispeed = 0; 1540 t.c_ospeed = TTYDEF_SPEED; 1541 t.c_cflag = TTYDEF_CFLAG; 1542 if (ISSET(hp->hp_swflags, TIOCFLAG_CLOCAL)) 1543 SET(t.c_cflag, CLOCAL); 1544 if (ISSET(hp->hp_swflags, TIOCFLAG_CRTSCTS)) 1545 SET(t.c_cflag, CRTSCTS); 1546 if (ISSET(hp->hp_swflags, TIOCFLAG_MDMBUF)) 1547 SET(t.c_cflag, MDMBUF); 1548 1549 /* Ensure uhso_tty_param() will do something. */ 1550 tp->t_ospeed = 0; 1551 (void)uhso_tty_param(tp, &t); 1552 1553 tp->t_iflag = TTYDEF_IFLAG; 1554 tp->t_oflag = TTYDEF_OFLAG; 1555 tp->t_lflag = TTYDEF_LFLAG; 1556 ttychars(tp); 1557 ttsetwater(tp); 1558 1559 hp->hp_status = 0; 1560 error = (*hp->hp_init)(hp); 1561 if (error != 0) 1562 return error; 1563 1564 /* 1565 * Turn on DTR. We must always do this, even if carrier is not 1566 * present, because otherwise we'd have to use TIOCSDTR 1567 * immediately after setting CLOCAL, which applications do not 1568 * expect. We always assert DTR while the port is open 1569 * unless explicitly requested to deassert it. Ditto RTS. 1570 */ 1571 uhso_tty_control(hp, TIOCMBIS, TIOCM_DTR | TIOCM_RTS); 1572 1573 /* and start reading */ 1574 error = (*hp->hp_read)(hp); 1575 if (error != 0) 1576 return error; 1577 1578 return 0; 1579 } 1580 1581 static int 1582 uhso_tty_close(dev_t dev, int flag, int mode, struct lwp *l) 1583 { 1584 struct uhso_softc *sc = device_lookup_private(&uhso_cd, UHSOUNIT(dev)); 1585 struct uhso_port *hp = sc->sc_port[UHSOPORT(dev)]; 1586 struct tty *tp = hp->hp_tp; 1587 1588 if (!ISSET(tp->t_state, TS_ISOPEN)) 1589 return 0; 1590 1591 DPRINTF(1, "sc=%p, hp=%p, tp=%p\n", sc, hp, tp); 1592 1593 sc->sc_refcnt++; 1594 1595 tp->t_linesw->l_close(tp, flag); 1596 ttyclose(tp); 1597 1598 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) 1599 uhso_tty_clean(hp); 1600 1601 if (--sc->sc_refcnt < 0) 1602 usb_detach_wakeupold(sc->sc_dev); 1603 1604 return 0; 1605 } 1606 1607 Static void 1608 uhso_tty_clean(struct uhso_port *hp) 1609 { 1610 1611 DPRINTF(1, "hp=%p\n", hp); 1612 1613 if (ISSET(hp->hp_status, TIOCM_DTR) 1614 && ISSET(hp->hp_tp->t_cflag, HUPCL)) 1615 uhso_tty_control(hp, TIOCMBIC, TIOCM_DTR); 1616 1617 (*hp->hp_clean)(hp); 1618 1619 if (hp->hp_rxfer != NULL) { 1620 usbd_destroy_xfer(hp->hp_rxfer); 1621 hp->hp_rxfer = NULL; 1622 hp->hp_rbuf = NULL; 1623 } 1624 1625 if (hp->hp_wxfer != NULL) { 1626 usbd_destroy_xfer(hp->hp_wxfer); 1627 hp->hp_wxfer = NULL; 1628 hp->hp_wbuf = NULL; 1629 } 1630 } 1631 1632 static int 1633 uhso_tty_read(dev_t dev, struct uio *uio, int flag) 1634 { 1635 struct uhso_softc *sc = device_lookup_private(&uhso_cd, UHSOUNIT(dev)); 1636 struct uhso_port *hp = sc->sc_port[UHSOPORT(dev)]; 1637 struct tty *tp = hp->hp_tp; 1638 int error; 1639 1640 if (!device_is_active(sc->sc_dev)) 1641 return EIO; 1642 1643 DPRINTF(5, "sc=%p, hp=%p, tp=%p\n", sc, hp, tp); 1644 1645 sc->sc_refcnt++; 1646 1647 error = tp->t_linesw->l_read(tp, uio, flag); 1648 1649 if (--sc->sc_refcnt < 0) 1650 usb_detach_wakeupold(sc->sc_dev); 1651 1652 return error; 1653 } 1654 1655 static int 1656 uhso_tty_write(dev_t dev, struct uio *uio, int flag) 1657 { 1658 struct uhso_softc *sc = device_lookup_private(&uhso_cd, UHSOUNIT(dev)); 1659 struct uhso_port *hp = sc->sc_port[UHSOPORT(dev)]; 1660 struct tty *tp = hp->hp_tp; 1661 int error; 1662 1663 if (!device_is_active(sc->sc_dev)) 1664 return EIO; 1665 1666 DPRINTF(5, "sc=%p, hp=%p, tp=%p\n", sc, hp, tp); 1667 1668 sc->sc_refcnt++; 1669 1670 error = tp->t_linesw->l_write(tp, uio, flag); 1671 1672 if (--sc->sc_refcnt < 0) 1673 usb_detach_wakeupold(sc->sc_dev); 1674 1675 return error; 1676 } 1677 1678 static int 1679 uhso_tty_ioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 1680 { 1681 struct uhso_softc *sc = device_lookup_private(&uhso_cd, UHSOUNIT(dev)); 1682 struct uhso_port *hp = sc->sc_port[UHSOPORT(dev)]; 1683 int error; 1684 1685 if (!device_is_active(sc->sc_dev)) 1686 return EIO; 1687 1688 DPRINTF(1, "sc=%p, hp=%p\n", sc, hp); 1689 1690 sc->sc_refcnt++; 1691 1692 error = uhso_tty_do_ioctl(hp, cmd, data, flag, l); 1693 1694 if (--sc->sc_refcnt < 0) 1695 usb_detach_wakeupold(sc->sc_dev); 1696 1697 return error; 1698 } 1699 1700 Static int 1701 uhso_tty_do_ioctl(struct uhso_port *hp, u_long cmd, void *data, int flag, 1702 struct lwp *l) 1703 { 1704 struct tty *tp = hp->hp_tp; 1705 int error, s; 1706 1707 error = tp->t_linesw->l_ioctl(tp, cmd, data, flag, l); 1708 if (error != EPASSTHROUGH) 1709 return error; 1710 1711 error = ttioctl(tp, cmd, data, flag, l); 1712 if (error != EPASSTHROUGH) 1713 return error; 1714 1715 error = 0; 1716 1717 s = spltty(); 1718 1719 switch (cmd) { 1720 case TIOCSDTR: 1721 error = uhso_tty_control(hp, TIOCMBIS, TIOCM_DTR); 1722 break; 1723 1724 case TIOCCDTR: 1725 error = uhso_tty_control(hp, TIOCMBIC, TIOCM_DTR); 1726 break; 1727 1728 case TIOCGFLAGS: 1729 *(int *)data = hp->hp_swflags; 1730 break; 1731 1732 case TIOCSFLAGS: 1733 error = kauth_authorize_device_tty(l->l_cred, 1734 KAUTH_DEVICE_TTY_PRIVSET, tp); 1735 1736 if (error) 1737 break; 1738 1739 hp->hp_swflags = *(int *)data; 1740 break; 1741 1742 case TIOCMSET: 1743 case TIOCMBIS: 1744 case TIOCMBIC: 1745 error = uhso_tty_control(hp, cmd, *(int *)data); 1746 break; 1747 1748 case TIOCMGET: 1749 *(int *)data = hp->hp_status; 1750 break; 1751 1752 default: 1753 error = EPASSTHROUGH; 1754 break; 1755 } 1756 1757 splx(s); 1758 1759 return error; 1760 } 1761 1762 /* this is called with tty_lock held */ 1763 static void 1764 uhso_tty_stop(struct tty *tp, int flag) 1765 { 1766 #if 0 1767 struct uhso_softc *sc = device_lookup_private(&uhso_cd, 1768 UHSOUNIT(tp->t_dev)); 1769 struct uhso_port *hp = sc->sc_port[UHSOPORT(tp->t_dev)]; 1770 #endif 1771 } 1772 1773 static struct tty * 1774 uhso_tty_tty(dev_t dev) 1775 { 1776 struct uhso_softc *sc = device_lookup_private(&uhso_cd, UHSOUNIT(dev)); 1777 struct uhso_port *hp = sc->sc_port[UHSOPORT(dev)]; 1778 1779 return hp->hp_tp; 1780 } 1781 1782 static int 1783 uhso_tty_poll(dev_t dev, int events, struct lwp *l) 1784 { 1785 struct uhso_softc *sc = device_lookup_private(&uhso_cd, UHSOUNIT(dev)); 1786 struct uhso_port *hp = sc->sc_port[UHSOPORT(dev)]; 1787 struct tty *tp = hp->hp_tp; 1788 int revents; 1789 1790 if (!device_is_active(sc->sc_dev)) 1791 return POLLHUP; 1792 1793 sc->sc_refcnt++; 1794 1795 revents = tp->t_linesw->l_poll(tp, events, l); 1796 1797 if (--sc->sc_refcnt < 0) 1798 usb_detach_wakeupold(sc->sc_dev); 1799 1800 return revents; 1801 } 1802 1803 Static int 1804 uhso_tty_param(struct tty *tp, struct termios *t) 1805 { 1806 struct uhso_softc *sc = device_lookup_private(&uhso_cd, 1807 UHSOUNIT(tp->t_dev)); 1808 struct uhso_port *hp = sc->sc_port[UHSOPORT(tp->t_dev)]; 1809 1810 if (!device_is_active(sc->sc_dev)) 1811 return EIO; 1812 1813 DPRINTF(1, "hp=%p, tp=%p, termios iflag=%x, oflag=%x, cflag=%x\n", 1814 hp, tp, t->c_iflag, t->c_oflag, t->c_cflag); 1815 1816 /* Check requested parameters. */ 1817 if (t->c_ispeed != 0 1818 && t->c_ispeed != t->c_ospeed) 1819 return EINVAL; 1820 1821 /* force CLOCAL and !HUPCL for console */ 1822 if (ISSET(hp->hp_swflags, TIOCFLAG_SOFTCAR)) { 1823 SET(t->c_cflag, CLOCAL); 1824 CLR(t->c_cflag, HUPCL); 1825 } 1826 1827 /* If there were no changes, don't do anything. */ 1828 if (tp->t_ospeed == t->c_ospeed 1829 && tp->t_cflag == t->c_cflag) 1830 return 0; 1831 1832 tp->t_ispeed = 0; 1833 tp->t_ospeed = t->c_ospeed; 1834 tp->t_cflag = t->c_cflag; 1835 1836 /* update tty layers idea of carrier bit */ 1837 tp->t_linesw->l_modem(tp, ISSET(hp->hp_status, TIOCM_CAR)); 1838 return 0; 1839 } 1840 1841 /* this is called with tty_lock held */ 1842 Static void 1843 uhso_tty_start(struct tty *tp) 1844 { 1845 struct uhso_softc *sc = device_lookup_private(&uhso_cd, 1846 UHSOUNIT(tp->t_dev)); 1847 struct uhso_port *hp = sc->sc_port[UHSOPORT(tp->t_dev)]; 1848 int s; 1849 1850 if (!device_is_active(sc->sc_dev)) 1851 return; 1852 1853 s = spltty(); 1854 1855 if (!ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP) 1856 && ttypull(tp) != 0) { 1857 hp->hp_wlen = q_to_b(&tp->t_outq, hp->hp_wbuf, hp->hp_wsize); 1858 if (hp->hp_wlen > 0) { 1859 SET(tp->t_state, TS_BUSY); 1860 (*hp->hp_write)(hp); 1861 } 1862 } 1863 1864 splx(s); 1865 } 1866 1867 Static int 1868 uhso_tty_control(struct uhso_port *hp, u_long cmd, int bits) 1869 { 1870 1871 bits &= (TIOCM_DTR | TIOCM_RTS); 1872 DPRINTF(1, "cmd %s, DTR=%d, RTS=%d\n", 1873 (cmd == TIOCMBIC ? "BIC" : (cmd == TIOCMBIS ? "BIS" : "SET")), 1874 (bits & TIOCM_DTR) ? 1 : 0, 1875 (bits & TIOCM_RTS) ? 1 : 0); 1876 1877 switch (cmd) { 1878 case TIOCMBIC: 1879 CLR(hp->hp_status, bits); 1880 break; 1881 1882 case TIOCMBIS: 1883 SET(hp->hp_status, bits); 1884 break; 1885 1886 case TIOCMSET: 1887 CLR(hp->hp_status, TIOCM_DTR | TIOCM_RTS); 1888 SET(hp->hp_status, bits); 1889 break; 1890 } 1891 1892 return (*hp->hp_control)(hp); 1893 } 1894 1895 1896 /****************************************************************************** 1897 * 1898 * Network Interface 1899 * 1900 */ 1901 1902 Static void 1903 uhso_ifnet_attach(struct uhso_softc *sc, struct usbd_interface *ifh, int index) 1904 { 1905 usb_endpoint_descriptor_t *ed; 1906 struct uhso_port *hp; 1907 struct ifnet *ifp; 1908 int in, out; 1909 1910 ed = uhso_get_endpoint(ifh, UE_BULK, UE_DIR_IN); 1911 if (ed == NULL) { 1912 aprint_error_dev(sc->sc_dev, 1913 "could not find bulk-in endpoint\n"); 1914 1915 return; 1916 } 1917 in = ed->bEndpointAddress; 1918 1919 ed = uhso_get_endpoint(ifh, UE_BULK, UE_DIR_OUT); 1920 if (ed == NULL) { 1921 aprint_error_dev(sc->sc_dev, 1922 "could not find bulk-out endpoint\n"); 1923 1924 return; 1925 } 1926 out = ed->bEndpointAddress; 1927 1928 DPRINTF(1, "in=%d, out=%d\n", in, out); 1929 1930 if (sc->sc_port[index] != NULL) { 1931 aprint_error_dev(sc->sc_dev, 1932 "ifnet port %d is duplicate!\n", index); 1933 1934 return; 1935 } 1936 1937 hp = kmem_zalloc(sizeof(struct uhso_port), KM_SLEEP); 1938 sc->sc_port[index] = hp; 1939 1940 ifp = if_alloc(IFT_IP); 1941 strlcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ); 1942 ifp->if_softc = hp; 1943 ifp->if_mtu = UHSO_IFNET_MTU; 1944 ifp->if_dlt = DLT_RAW; 1945 ifp->if_type = IFT_IP; 1946 ifp->if_flags = IFF_NOARP | IFF_SIMPLEX; 1947 ifp->if_ioctl = uhso_ifnet_ioctl; 1948 ifp->if_start = uhso_ifnet_start; 1949 ifp->if_output = uhso_ifnet_output; 1950 IFQ_SET_READY(&ifp->if_snd); 1951 1952 hp->hp_sc = sc; 1953 hp->hp_ifp = ifp; 1954 hp->hp_ifh = ifh; 1955 hp->hp_raddr = in; 1956 hp->hp_waddr = out; 1957 hp->hp_abort = uhso_ifnet_abort; 1958 hp->hp_detach = uhso_ifnet_detach; 1959 hp->hp_init = uhso_bulk_init; 1960 hp->hp_clean = uhso_bulk_clean; 1961 hp->hp_write = uhso_bulk_write; 1962 hp->hp_write_cb = uhso_ifnet_write_cb; 1963 hp->hp_read = uhso_bulk_read; 1964 hp->hp_read_cb = uhso_ifnet_read_cb; 1965 hp->hp_wsize = MCLBYTES; 1966 hp->hp_rsize = MCLBYTES; 1967 1968 if_attach(ifp); 1969 if_alloc_sadl(ifp); 1970 bpf_attach(ifp, DLT_RAW, 0); 1971 1972 aprint_normal_dev(sc->sc_dev, "%s (port %d) attached as ifnet\n", 1973 uhso_port_name[index], index); 1974 } 1975 1976 Static int 1977 uhso_ifnet_abort(struct uhso_port *hp) 1978 { 1979 struct ifnet *ifp = hp->hp_ifp; 1980 1981 /* All ifnet IO will abort when IFF_RUNNING is not set */ 1982 CLR(ifp->if_flags, IFF_RUNNING); 1983 1984 return (*hp->hp_clean)(hp); 1985 } 1986 1987 Static int 1988 uhso_ifnet_detach(struct uhso_port *hp) 1989 { 1990 struct ifnet *ifp = hp->hp_ifp; 1991 int s; 1992 1993 s = splnet(); 1994 bpf_detach(ifp); 1995 if_detach(ifp); 1996 if_free(ifp); 1997 splx(s); 1998 1999 kmem_free(hp, sizeof(struct uhso_port)); 2000 return 0; 2001 } 2002 2003 Static void 2004 uhso_ifnet_write_cb(struct usbd_xfer *xfer, void * p, usbd_status status) 2005 { 2006 struct uhso_port *hp = p; 2007 struct uhso_softc *sc= hp->hp_sc; 2008 struct ifnet *ifp = hp->hp_ifp; 2009 uint32_t cc; 2010 int s; 2011 2012 if (--sc->sc_refcnt < 0) 2013 usb_detach_wakeupold(sc->sc_dev); 2014 2015 if (!ISSET(ifp->if_flags, IFF_RUNNING)) 2016 return; 2017 2018 if (status != USBD_NORMAL_COMPLETION) { 2019 DPRINTF(0, "non-normal status %s\n", usbd_errstr(status)); 2020 2021 if (status == USBD_STALLED && hp->hp_wpipe != NULL) 2022 usbd_clear_endpoint_stall_async(hp->hp_wpipe); 2023 else 2024 return; 2025 2026 if_statinc(ifp, if_oerrors); 2027 } else { 2028 usbd_get_xfer_status(xfer, NULL, NULL, &cc, NULL); 2029 DPRINTF(5, "wrote %d bytes (of %zd)\n", cc, hp->hp_wlen); 2030 2031 if (cc != hp->hp_wlen) 2032 DPRINTF(0, "cc=%u, wlen=%zd\n", cc, hp->hp_wlen); 2033 2034 if_statinc(ifp, if_opackets); 2035 } 2036 2037 s = splnet(); 2038 CLR(ifp->if_flags, IFF_OACTIVE); 2039 ifp->if_start(ifp); 2040 splx(s); 2041 } 2042 2043 Static void 2044 uhso_ifnet_read_cb(struct usbd_xfer *xfer, void * p, 2045 usbd_status status) 2046 { 2047 struct uhso_port *hp = p; 2048 struct uhso_softc *sc= hp->hp_sc; 2049 struct ifnet *ifp = hp->hp_ifp; 2050 void *cp; 2051 uint32_t cc; 2052 2053 if (--sc->sc_refcnt < 0) 2054 usb_detach_wakeupold(sc->sc_dev); 2055 2056 if (!ISSET(ifp->if_flags, IFF_RUNNING)) 2057 return; 2058 2059 if (status != USBD_NORMAL_COMPLETION) { 2060 DPRINTF(0, "non-normal status: %s\n", usbd_errstr(status)); 2061 2062 if (status == USBD_STALLED && hp->hp_rpipe != NULL) 2063 usbd_clear_endpoint_stall_async(hp->hp_rpipe); 2064 else 2065 return; 2066 2067 if_statinc(ifp, if_ierrors); 2068 hp->hp_rlen = 0; 2069 } else { 2070 usbd_get_xfer_status(xfer, NULL, (void **)&cp, &cc, NULL); 2071 2072 hp->hp_rlen = cc; 2073 DPRINTF(5, "read %d bytes\n", cc); 2074 2075 uhso_ifnet_input(ifp, &hp->hp_mbuf, cp, cc); 2076 } 2077 2078 (*hp->hp_read)(hp); 2079 } 2080 2081 Static void 2082 uhso_ifnet_input(struct ifnet *ifp, struct mbuf **mb, uint8_t *cp, size_t cc) 2083 { 2084 struct mbuf *m; 2085 size_t got, len, want; 2086 int s; 2087 2088 /* 2089 * Several IP packets might be in the same buffer, we need to 2090 * separate them before handing it to the ip-stack. We might 2091 * also receive partial packets which we need to defer until 2092 * we get more data. 2093 */ 2094 while (cc > 0) { 2095 if (*mb == NULL) { 2096 MGETHDR(m, M_DONTWAIT, MT_DATA); 2097 if (m == NULL) { 2098 aprint_error_ifnet(ifp, "no mbufs\n"); 2099 if_statinc(ifp, if_ierrors); 2100 break; 2101 } 2102 2103 MCLGET(m, M_DONTWAIT); 2104 if (!ISSET(m->m_flags, M_EXT)) { 2105 aprint_error_ifnet(ifp, "no mbuf clusters\n"); 2106 if_statinc(ifp, if_ierrors); 2107 m_freem(m); 2108 break; 2109 } 2110 2111 got = 0; 2112 } else { 2113 m = *mb; 2114 *mb = NULL; 2115 got = m->m_pkthdr.len; 2116 } 2117 2118 /* make sure that the incoming packet is ok */ 2119 if (got == 0) 2120 mtod(m, uint8_t *)[0] = cp[0]; 2121 2122 want = mtod(m, struct ip *)->ip_hl << 2; 2123 if (mtod(m, struct ip *)->ip_v != 4 2124 || want != sizeof(struct ip)) { 2125 aprint_error_ifnet(ifp, 2126 "bad IP header (v=%d, hl=%zd)\n", 2127 mtod(m, struct ip *)->ip_v, want); 2128 2129 if_statinc(ifp, if_ierrors); 2130 m_freem(m); 2131 break; 2132 } 2133 2134 /* ensure we have the IP header.. */ 2135 if (got < want) { 2136 len = MIN(want - got, cc); 2137 memcpy(mtod(m, uint8_t *) + got, cp, len); 2138 got += len; 2139 cc -= len; 2140 cp += len; 2141 2142 if (got < want) { 2143 DPRINTF(5, "waiting for IP header " 2144 "(got %zd want %zd)\n", got, want); 2145 2146 m->m_pkthdr.len = got; 2147 *mb = m; 2148 break; 2149 } 2150 } 2151 2152 /* ..and the packet body */ 2153 want = ntohs(mtod(m, struct ip *)->ip_len); 2154 if (got < want) { 2155 len = MIN(want - got, cc); 2156 memcpy(mtod(m, uint8_t *) + got, cp, len); 2157 got += len; 2158 cc -= len; 2159 cp += len; 2160 2161 if (got < want) { 2162 DPRINTF(5, "waiting for IP packet " 2163 "(got %zd want %zd)\n", got, want); 2164 2165 m->m_pkthdr.len = got; 2166 *mb = m; 2167 break; 2168 } 2169 } 2170 2171 m_set_rcvif(m, ifp); 2172 m->m_pkthdr.len = m->m_len = got; 2173 2174 s = splnet(); 2175 2176 bpf_mtap(ifp, m, BPF_D_IN); 2177 2178 if (__predict_false(!pktq_enqueue(ip_pktq, m, 0))) { 2179 m_freem(m); 2180 } else { 2181 if_statadd2(ifp, if_ipackets, 1, if_ibytes, got); 2182 } 2183 splx(s); 2184 } 2185 } 2186 2187 Static int 2188 uhso_ifnet_ioctl(struct ifnet *ifp, u_long cmd, void *data) 2189 { 2190 struct uhso_port *hp = ifp->if_softc; 2191 int error, s; 2192 2193 s = splnet(); 2194 2195 switch (cmd) { 2196 case SIOCINITIFADDR: 2197 switch (((struct ifaddr *)data)->ifa_addr->sa_family) { 2198 #ifdef INET 2199 case AF_INET: 2200 if (!ISSET(ifp->if_flags, IFF_RUNNING)) { 2201 SET(ifp->if_flags, IFF_UP); 2202 error = uhso_ifnet_init(hp); 2203 if (error != 0) { 2204 uhso_ifnet_clean(hp); 2205 break; 2206 } 2207 2208 SET(ifp->if_flags, IFF_RUNNING); 2209 DPRINTF(1, "hp=%p, ifp=%p INITIFADDR\n", hp, 2210 ifp); 2211 break; 2212 } 2213 2214 error = 0; 2215 break; 2216 #endif 2217 2218 default: 2219 error = EAFNOSUPPORT; 2220 break; 2221 } 2222 break; 2223 2224 case SIOCSIFMTU: 2225 if (((struct ifreq *)data)->ifr_mtu > hp->hp_wsize) { 2226 error = EINVAL; 2227 break; 2228 } 2229 2230 error = ifioctl_common(ifp, cmd, data); 2231 if (error == ENETRESET) 2232 error = 0; 2233 2234 break; 2235 2236 case SIOCSIFFLAGS: 2237 error = ifioctl_common(ifp, cmd, data); 2238 if (error != 0) 2239 break; 2240 2241 switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) { 2242 case IFF_UP: 2243 error = uhso_ifnet_init(hp); 2244 if (error != 0) { 2245 uhso_ifnet_clean(hp); 2246 break; 2247 } 2248 2249 SET(ifp->if_flags, IFF_RUNNING); 2250 DPRINTF(1, "hp=%p, ifp=%p RUNNING\n", hp, ifp); 2251 break; 2252 2253 case IFF_RUNNING: 2254 uhso_ifnet_clean(hp); 2255 CLR(ifp->if_flags, IFF_RUNNING); 2256 DPRINTF(1, "hp=%p, ifp=%p STOPPED\n", hp, ifp); 2257 break; 2258 2259 default: 2260 break; 2261 } 2262 break; 2263 2264 default: 2265 error = ifioctl_common(ifp, cmd, data); 2266 break; 2267 } 2268 2269 splx(s); 2270 2271 return error; 2272 } 2273 2274 /* is only called if IFF_RUNNING not set */ 2275 Static int 2276 uhso_ifnet_init(struct uhso_port *hp) 2277 { 2278 struct uhso_softc *sc = hp->hp_sc; 2279 int error; 2280 2281 DPRINTF(1, "sc=%p, hp=%p\n", sc, hp); 2282 2283 if (!device_is_active(sc->sc_dev)) 2284 return EIO; 2285 2286 error = (*hp->hp_init)(hp); 2287 if (error != 0) 2288 return error; 2289 2290 error = (*hp->hp_read)(hp); 2291 if (error != 0) 2292 return error; 2293 2294 return 0; 2295 } 2296 2297 Static void 2298 uhso_ifnet_clean(struct uhso_port *hp) 2299 { 2300 2301 DPRINTF(1, "hp=%p\n", hp); 2302 2303 (*hp->hp_clean)(hp); 2304 } 2305 2306 /* called at splnet() with IFF_OACTIVE not set */ 2307 Static void 2308 uhso_ifnet_start(struct ifnet *ifp) 2309 { 2310 struct uhso_port *hp = ifp->if_softc; 2311 struct mbuf *m; 2312 2313 KASSERT(!ISSET(ifp->if_flags, IFF_OACTIVE)); 2314 2315 if (!ISSET(ifp->if_flags, IFF_RUNNING)) 2316 return; 2317 2318 if (IFQ_IS_EMPTY(&ifp->if_snd)) { 2319 DPRINTF(5, "finished sending\n"); 2320 return; 2321 } 2322 2323 SET(ifp->if_flags, IFF_OACTIVE); 2324 IFQ_DEQUEUE(&ifp->if_snd, m); 2325 hp->hp_wlen = m->m_pkthdr.len; 2326 if (hp->hp_wlen > hp->hp_wsize) { 2327 aprint_error_ifnet(ifp, 2328 "packet too long (%zd > %zd), truncating\n", 2329 hp->hp_wlen, hp->hp_wsize); 2330 2331 hp->hp_wlen = hp->hp_wsize; 2332 } 2333 2334 bpf_mtap(ifp, m, BPF_D_OUT); 2335 2336 m_copydata(m, 0, hp->hp_wlen, hp->hp_wbuf); 2337 m_freem(m); 2338 2339 if ((*hp->hp_write)(hp) != 0) { 2340 if_statinc(ifp, if_oerrors); 2341 CLR(ifp->if_flags, IFF_OACTIVE); 2342 } 2343 } 2344 2345 Static int 2346 uhso_ifnet_output(struct ifnet *ifp, struct mbuf *m, 2347 const struct sockaddr *dst, const struct rtentry *rt0) 2348 { 2349 int error; 2350 2351 if (!ISSET(ifp->if_flags, IFF_RUNNING)) 2352 return EIO; 2353 2354 IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family); 2355 2356 switch (dst->sa_family) { 2357 #ifdef INET 2358 case AF_INET: 2359 error = ifq_enqueue(ifp, m); 2360 break; 2361 #endif 2362 2363 default: 2364 DPRINTF(0, "unsupported address family %d\n", dst->sa_family); 2365 error = EAFNOSUPPORT; 2366 m_freem(m); 2367 break; 2368 } 2369 2370 return error; 2371 } 2372