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