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