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