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