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