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