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