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