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