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