1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2010 Hans Petter Selasky. All rights reserved. 5 * Copyright (c) 2009 Diego Giagio. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 /* 30 * Thanks to Diego Giagio for figuring out the programming details for 31 * the Apple iPhone Ethernet driver. 32 */ 33 34 #include <sys/stdint.h> 35 #include <sys/stddef.h> 36 #include <sys/param.h> 37 #include <sys/queue.h> 38 #include <sys/types.h> 39 #include <sys/systm.h> 40 #include <sys/kernel.h> 41 #include <sys/bus.h> 42 #include <sys/module.h> 43 #include <sys/lock.h> 44 #include <sys/mutex.h> 45 #include <sys/condvar.h> 46 #include <sys/socket.h> 47 #include <sys/sysctl.h> 48 #include <sys/sx.h> 49 #include <sys/unistd.h> 50 #include <sys/callout.h> 51 #include <sys/malloc.h> 52 #include <sys/priv.h> 53 54 #include <net/if.h> 55 #include <net/if_var.h> 56 57 #include <dev/usb/usb.h> 58 #include <dev/usb/usbdi.h> 59 #include <dev/usb/usbdi_util.h> 60 #include "usbdevs.h" 61 62 #define USB_DEBUG_VAR ipheth_debug 63 #include <dev/usb/usb_debug.h> 64 #include <dev/usb/usb_process.h> 65 66 #include <dev/usb/net/usb_ethernet.h> 67 #include <dev/usb/net/if_iphethvar.h> 68 69 static device_probe_t ipheth_probe; 70 static device_attach_t ipheth_attach; 71 static device_detach_t ipheth_detach; 72 73 static usb_callback_t ipheth_bulk_write_callback; 74 static usb_callback_t ipheth_bulk_read_callback; 75 76 static uether_fn_t ipheth_attach_post; 77 static uether_fn_t ipheth_tick; 78 static uether_fn_t ipheth_init; 79 static uether_fn_t ipheth_stop; 80 static uether_fn_t ipheth_start; 81 static uether_fn_t ipheth_setmulti; 82 static uether_fn_t ipheth_setpromisc; 83 84 #ifdef USB_DEBUG 85 static int ipheth_debug = 0; 86 87 static SYSCTL_NODE(_hw_usb, OID_AUTO, ipheth, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, 88 "USB iPhone ethernet"); 89 SYSCTL_INT(_hw_usb_ipheth, OID_AUTO, debug, CTLFLAG_RWTUN, &ipheth_debug, 0, "Debug level"); 90 #endif 91 92 static const struct usb_config ipheth_config[IPHETH_N_TRANSFER] = { 93 [IPHETH_BULK_RX] = { 94 .type = UE_BULK, 95 .endpoint = UE_ADDR_ANY, 96 .direction = UE_DIR_RX, 97 .frames = IPHETH_RX_FRAMES_MAX, 98 .bufsize = (IPHETH_RX_FRAMES_MAX * MCLBYTES), 99 .flags = {.short_frames_ok = 1,.short_xfer_ok = 1,.ext_buffer = 1,}, 100 .callback = ipheth_bulk_read_callback, 101 .timeout = 0, /* no timeout */ 102 }, 103 104 [IPHETH_BULK_TX] = { 105 .type = UE_BULK, 106 .endpoint = UE_ADDR_ANY, 107 .direction = UE_DIR_TX, 108 .frames = IPHETH_TX_FRAMES_MAX, 109 .bufsize = (IPHETH_TX_FRAMES_MAX * IPHETH_BUF_SIZE), 110 .flags = {.force_short_xfer = 1,}, 111 .callback = ipheth_bulk_write_callback, 112 .timeout = IPHETH_TX_TIMEOUT, 113 }, 114 }; 115 116 static device_method_t ipheth_methods[] = { 117 /* Device interface */ 118 DEVMETHOD(device_probe, ipheth_probe), 119 DEVMETHOD(device_attach, ipheth_attach), 120 DEVMETHOD(device_detach, ipheth_detach), 121 122 DEVMETHOD_END 123 }; 124 125 static driver_t ipheth_driver = { 126 .name = "ipheth", 127 .methods = ipheth_methods, 128 .size = sizeof(struct ipheth_softc), 129 }; 130 131 static const STRUCT_USB_HOST_ID ipheth_devs[] = { 132 #if 0 133 {IPHETH_ID(USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE, 134 IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, 135 IPHETH_USBINTF_PROTO)}, 136 {IPHETH_ID(USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_3G, 137 IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, 138 IPHETH_USBINTF_PROTO)}, 139 {IPHETH_ID(USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_3GS, 140 IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, 141 IPHETH_USBINTF_PROTO)}, 142 {IPHETH_ID(USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_4, 143 IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, 144 IPHETH_USBINTF_PROTO)}, 145 {IPHETH_ID(USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_4S, 146 IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, 147 IPHETH_USBINTF_PROTO)}, 148 {IPHETH_ID(USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_5, 149 IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, 150 IPHETH_USBINTF_PROTO)}, 151 #else 152 /* product agnostic interface match */ 153 {USB_VENDOR(USB_VENDOR_APPLE), 154 USB_IFACE_CLASS(IPHETH_USBINTF_CLASS), 155 USB_IFACE_SUBCLASS(IPHETH_USBINTF_SUBCLASS), 156 USB_IFACE_PROTOCOL(IPHETH_USBINTF_PROTO)}, 157 #endif 158 }; 159 160 DRIVER_MODULE(ipheth, uhub, ipheth_driver, NULL, NULL); 161 MODULE_VERSION(ipheth, 1); 162 MODULE_DEPEND(ipheth, uether, 1, 1, 1); 163 MODULE_DEPEND(ipheth, usb, 1, 1, 1); 164 MODULE_DEPEND(ipheth, ether, 1, 1, 1); 165 USB_PNP_HOST_INFO(ipheth_devs); 166 167 static const struct usb_ether_methods ipheth_ue_methods = { 168 .ue_attach_post = ipheth_attach_post, 169 .ue_start = ipheth_start, 170 .ue_init = ipheth_init, 171 .ue_tick = ipheth_tick, 172 .ue_stop = ipheth_stop, 173 .ue_setmulti = ipheth_setmulti, 174 .ue_setpromisc = ipheth_setpromisc, 175 }; 176 177 #define IPHETH_ID(v,p,c,sc,pt) \ 178 USB_VENDOR(v), USB_PRODUCT(p), \ 179 USB_IFACE_CLASS(c), USB_IFACE_SUBCLASS(sc), \ 180 USB_IFACE_PROTOCOL(pt) 181 182 static int 183 ipheth_get_mac_addr(struct ipheth_softc *sc) 184 { 185 struct usb_device_request req; 186 int error; 187 188 req.bmRequestType = UT_READ_VENDOR_DEVICE; 189 req.bRequest = IPHETH_CMD_GET_MACADDR; 190 req.wValue[0] = 0; 191 req.wValue[1] = 0; 192 req.wIndex[0] = sc->sc_iface_no; 193 req.wIndex[1] = 0; 194 req.wLength[0] = ETHER_ADDR_LEN; 195 req.wLength[1] = 0; 196 197 error = usbd_do_request(sc->sc_ue.ue_udev, NULL, &req, sc->sc_data); 198 199 if (error) 200 return (error); 201 202 memcpy(sc->sc_ue.ue_eaddr, sc->sc_data, ETHER_ADDR_LEN); 203 204 return (0); 205 } 206 207 static int 208 ipheth_probe(device_t dev) 209 { 210 struct usb_attach_arg *uaa = device_get_ivars(dev); 211 212 if (uaa->usb_mode != USB_MODE_HOST) 213 return (ENXIO); 214 215 return (usbd_lookup_id_by_uaa(ipheth_devs, sizeof(ipheth_devs), uaa)); 216 } 217 218 static int 219 ipheth_attach(device_t dev) 220 { 221 struct ipheth_softc *sc = device_get_softc(dev); 222 struct usb_ether *ue = &sc->sc_ue; 223 struct usb_attach_arg *uaa = device_get_ivars(dev); 224 int error; 225 226 sc->sc_iface_no = uaa->info.bIfaceIndex; 227 228 device_set_usb_desc(dev); 229 230 mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF); 231 232 error = usbd_set_alt_interface_index(uaa->device, 233 uaa->info.bIfaceIndex, IPHETH_ALT_INTFNUM); 234 if (error) { 235 device_printf(dev, "Cannot set alternate setting\n"); 236 goto detach; 237 } 238 error = usbd_transfer_setup(uaa->device, &sc->sc_iface_no, 239 sc->sc_xfer, ipheth_config, IPHETH_N_TRANSFER, sc, &sc->sc_mtx); 240 if (error) { 241 device_printf(dev, "Cannot setup USB transfers\n"); 242 goto detach; 243 } 244 ue->ue_sc = sc; 245 ue->ue_dev = dev; 246 ue->ue_udev = uaa->device; 247 ue->ue_mtx = &sc->sc_mtx; 248 ue->ue_methods = &ipheth_ue_methods; 249 250 error = ipheth_get_mac_addr(sc); 251 if (error) { 252 device_printf(dev, "Cannot get MAC address\n"); 253 goto detach; 254 } 255 256 error = uether_ifattach(ue); 257 if (error) { 258 device_printf(dev, "could not attach interface\n"); 259 goto detach; 260 } 261 return (0); /* success */ 262 263 detach: 264 ipheth_detach(dev); 265 return (ENXIO); /* failure */ 266 } 267 268 static int 269 ipheth_detach(device_t dev) 270 { 271 struct ipheth_softc *sc = device_get_softc(dev); 272 struct usb_ether *ue = &sc->sc_ue; 273 274 /* stop all USB transfers first */ 275 usbd_transfer_unsetup(sc->sc_xfer, IPHETH_N_TRANSFER); 276 277 uether_ifdetach(ue); 278 279 mtx_destroy(&sc->sc_mtx); 280 281 return (0); 282 } 283 284 static void 285 ipheth_start(struct usb_ether *ue) 286 { 287 struct ipheth_softc *sc = uether_getsc(ue); 288 289 /* 290 * Start the USB transfers, if not already started: 291 */ 292 usbd_transfer_start(sc->sc_xfer[IPHETH_BULK_TX]); 293 usbd_transfer_start(sc->sc_xfer[IPHETH_BULK_RX]); 294 } 295 296 static void 297 ipheth_stop(struct usb_ether *ue) 298 { 299 struct ipheth_softc *sc = uether_getsc(ue); 300 301 /* 302 * Stop the USB transfers, if not already stopped: 303 */ 304 usbd_transfer_stop(sc->sc_xfer[IPHETH_BULK_TX]); 305 usbd_transfer_stop(sc->sc_xfer[IPHETH_BULK_RX]); 306 } 307 308 static void 309 ipheth_tick(struct usb_ether *ue) 310 { 311 struct ipheth_softc *sc = uether_getsc(ue); 312 struct usb_device_request req; 313 int error; 314 315 req.bmRequestType = UT_READ_VENDOR_DEVICE; 316 req.bRequest = IPHETH_CMD_CARRIER_CHECK; 317 req.wValue[0] = 0; 318 req.wValue[1] = 0; 319 req.wIndex[0] = sc->sc_iface_no; 320 req.wIndex[1] = 0; 321 req.wLength[0] = IPHETH_CTRL_BUF_SIZE; 322 req.wLength[1] = 0; 323 324 error = uether_do_request(ue, &req, sc->sc_data, IPHETH_CTRL_TIMEOUT); 325 326 if (error) 327 return; 328 329 sc->sc_carrier_on = 330 (sc->sc_data[0] == IPHETH_CARRIER_ON); 331 } 332 333 static void 334 ipheth_attach_post(struct usb_ether *ue) 335 { 336 337 } 338 339 static void 340 ipheth_init(struct usb_ether *ue) 341 { 342 struct ipheth_softc *sc = uether_getsc(ue); 343 if_t ifp = uether_getifp(ue); 344 345 IPHETH_LOCK_ASSERT(sc, MA_OWNED); 346 347 if_setdrvflagbits(ifp, IFF_DRV_RUNNING, 0); 348 349 /* stall data write direction, which depends on USB mode */ 350 usbd_xfer_set_stall(sc->sc_xfer[IPHETH_BULK_TX]); 351 352 /* start data transfers */ 353 ipheth_start(ue); 354 } 355 356 static void 357 ipheth_setmulti(struct usb_ether *ue) 358 { 359 360 } 361 362 static void 363 ipheth_setpromisc(struct usb_ether *ue) 364 { 365 366 } 367 368 static void 369 ipheth_free_queue(struct mbuf **ppm, uint8_t n) 370 { 371 uint8_t x; 372 373 for (x = 0; x != n; x++) { 374 if (ppm[x] != NULL) { 375 m_freem(ppm[x]); 376 ppm[x] = NULL; 377 } 378 } 379 } 380 381 static void 382 ipheth_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) 383 { 384 struct ipheth_softc *sc = usbd_xfer_softc(xfer); 385 if_t ifp = uether_getifp(&sc->sc_ue); 386 struct usb_page_cache *pc; 387 struct mbuf *m; 388 uint8_t x; 389 int actlen; 390 int aframes; 391 392 usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL); 393 394 DPRINTFN(1, "\n"); 395 396 switch (USB_GET_STATE(xfer)) { 397 case USB_ST_TRANSFERRED: 398 DPRINTFN(11, "transfer complete: %u bytes in %u frames\n", 399 actlen, aframes); 400 401 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); 402 403 /* free all previous TX buffers */ 404 ipheth_free_queue(sc->sc_tx_buf, IPHETH_TX_FRAMES_MAX); 405 406 /* FALLTHROUGH */ 407 case USB_ST_SETUP: 408 tr_setup: 409 for (x = 0; x != IPHETH_TX_FRAMES_MAX; x++) { 410 m = if_dequeue(ifp); 411 412 if (m == NULL) 413 break; 414 415 usbd_xfer_set_frame_offset(xfer, 416 x * IPHETH_BUF_SIZE, x); 417 418 pc = usbd_xfer_get_frame(xfer, x); 419 420 sc->sc_tx_buf[x] = m; 421 422 if (m->m_pkthdr.len > IPHETH_BUF_SIZE) 423 m->m_pkthdr.len = IPHETH_BUF_SIZE; 424 425 usbd_m_copy_in(pc, 0, m, 0, m->m_pkthdr.len); 426 427 usbd_xfer_set_frame_len(xfer, x, IPHETH_BUF_SIZE); 428 429 if (IPHETH_BUF_SIZE != m->m_pkthdr.len) { 430 usbd_frame_zero(pc, m->m_pkthdr.len, 431 IPHETH_BUF_SIZE - m->m_pkthdr.len); 432 } 433 434 /* 435 * If there's a BPF listener, bounce a copy of 436 * this frame to him: 437 */ 438 BPF_MTAP(ifp, m); 439 } 440 if (x != 0) { 441 usbd_xfer_set_frames(xfer, x); 442 443 usbd_transfer_submit(xfer); 444 } 445 break; 446 447 default: /* Error */ 448 DPRINTFN(11, "transfer error, %s\n", 449 usbd_errstr(error)); 450 451 /* free all previous TX buffers */ 452 ipheth_free_queue(sc->sc_tx_buf, IPHETH_TX_FRAMES_MAX); 453 454 /* count output errors */ 455 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 456 457 if (error != USB_ERR_CANCELLED) { 458 /* try to clear stall first */ 459 usbd_xfer_set_stall(xfer); 460 goto tr_setup; 461 } 462 break; 463 } 464 } 465 466 static void 467 ipheth_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) 468 { 469 struct ipheth_softc *sc = usbd_xfer_softc(xfer); 470 struct mbuf *m; 471 uint8_t x; 472 int actlen; 473 int aframes; 474 int len; 475 476 usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL); 477 478 switch (USB_GET_STATE(xfer)) { 479 case USB_ST_TRANSFERRED: 480 481 DPRINTF("received %u bytes in %u frames\n", actlen, aframes); 482 483 for (x = 0; x != aframes; x++) { 484 m = sc->sc_rx_buf[x]; 485 sc->sc_rx_buf[x] = NULL; 486 len = usbd_xfer_frame_len(xfer, x); 487 488 if (len < (int)(sizeof(struct ether_header) + 489 IPHETH_RX_ADJ)) { 490 m_freem(m); 491 continue; 492 } 493 494 m_adj(m, IPHETH_RX_ADJ); 495 496 /* queue up mbuf */ 497 uether_rxmbuf(&sc->sc_ue, m, len - IPHETH_RX_ADJ); 498 } 499 500 /* FALLTHROUGH */ 501 case USB_ST_SETUP: 502 503 for (x = 0; x != IPHETH_RX_FRAMES_MAX; x++) { 504 if (sc->sc_rx_buf[x] == NULL) { 505 m = uether_newbuf(); 506 if (m == NULL) 507 goto tr_stall; 508 509 /* cancel alignment for ethernet */ 510 m_adj(m, ETHER_ALIGN); 511 512 sc->sc_rx_buf[x] = m; 513 } else { 514 m = sc->sc_rx_buf[x]; 515 } 516 517 usbd_xfer_set_frame_data(xfer, x, m->m_data, m->m_len); 518 } 519 /* set number of frames and start hardware */ 520 usbd_xfer_set_frames(xfer, x); 521 usbd_transfer_submit(xfer); 522 /* flush any received frames */ 523 uether_rxflush(&sc->sc_ue); 524 break; 525 526 default: /* Error */ 527 DPRINTF("error = %s\n", usbd_errstr(error)); 528 529 if (error != USB_ERR_CANCELLED) { 530 tr_stall: 531 /* try to clear stall first */ 532 usbd_xfer_set_stall(xfer); 533 usbd_xfer_set_frames(xfer, 0); 534 usbd_transfer_submit(xfer); 535 break; 536 } 537 /* need to free the RX-mbufs when we are cancelled */ 538 ipheth_free_queue(sc->sc_rx_buf, IPHETH_RX_FRAMES_MAX); 539 break; 540 } 541 } 542