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