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