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