Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

CDC-NCM: add support for Apple's private interface

Available on iOS/iPadOS >= 17, where this new interface is used by
developer tools using the new RemoteXPC protocol.

This private interface lacks a status endpoint, presumably because there
isn't a physical cable that can be unplugged, nor any speed changes to
be notified about.

Note that NCM interfaces are not exposed until a mode switch is
requested, which macOS does automatically.

The mode switch can be performed like this:

uint8_t status;
libusb_control_transfer(device_handle,
LIBUSB_RECIPIENT_DEVICE | LIBUSB_REQUEST_TYPE_VENDOR |
LIBUSB_ENDPOINT_IN,
82, /* bRequest */
0, /* wValue */
3, /* wIndex */
&status,
sizeof(status),
0);

Newer versions of usbmuxd do this automatically.

Co-developed-by: Håvard Sørbø <havard@hsorbo.no>
Signed-off-by: Håvard Sørbø <havard@hsorbo.no>
Signed-off-by: Ole André Vadla Ravnås <oleavr@frida.re>
Link: https://lore.kernel.org/r/20240607074117.31322-1-oleavr@frida.re
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Ole André Vadla Ravnås and committed by
Jakub Kicinski
3ec8d757 6fc1b322

+46 -1
+46 -1
drivers/net/usb/cdc_ncm.c
··· 933 933 934 934 cdc_ncm_find_endpoints(dev, ctx->data); 935 935 cdc_ncm_find_endpoints(dev, ctx->control); 936 - if (!dev->in || !dev->out || !dev->status) { 936 + if (!dev->in || !dev->out || 937 + (!dev->status && dev->driver_info->flags & FLAG_LINK_INTR)) { 937 938 dev_dbg(&intf->dev, "failed to collect endpoints\n"); 938 939 goto error2; 939 940 } ··· 1926 1925 .set_rx_mode = usbnet_cdc_update_filter, 1927 1926 }; 1928 1927 1928 + /* Same as cdc_ncm_info, but with FLAG_SEND_ZLP */ 1929 + static const struct driver_info apple_tethering_interface_info = { 1930 + .description = "CDC NCM (Apple Tethering)", 1931 + .flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT | FLAG_MULTI_PACKET 1932 + | FLAG_LINK_INTR | FLAG_ETHER | FLAG_SEND_ZLP, 1933 + .bind = cdc_ncm_bind, 1934 + .unbind = cdc_ncm_unbind, 1935 + .manage_power = usbnet_manage_power, 1936 + .status = cdc_ncm_status, 1937 + .rx_fixup = cdc_ncm_rx_fixup, 1938 + .tx_fixup = cdc_ncm_tx_fixup, 1939 + .set_rx_mode = usbnet_cdc_update_filter, 1940 + }; 1941 + 1942 + /* Same as apple_tethering_interface_info, but without FLAG_LINK_INTR */ 1943 + static const struct driver_info apple_private_interface_info = { 1944 + .description = "CDC NCM (Apple Private)", 1945 + .flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT | FLAG_MULTI_PACKET 1946 + | FLAG_ETHER | FLAG_SEND_ZLP, 1947 + .bind = cdc_ncm_bind, 1948 + .unbind = cdc_ncm_unbind, 1949 + .manage_power = usbnet_manage_power, 1950 + .status = cdc_ncm_status, 1951 + .rx_fixup = cdc_ncm_rx_fixup, 1952 + .tx_fixup = cdc_ncm_tx_fixup, 1953 + .set_rx_mode = usbnet_cdc_update_filter, 1954 + }; 1955 + 1929 1956 /* Same as cdc_ncm_info, but with FLAG_WWAN */ 1930 1957 static const struct driver_info wwan_info = { 1931 1958 .description = "Mobile Broadband Network Device", ··· 1983 1954 }; 1984 1955 1985 1956 static const struct usb_device_id cdc_devs[] = { 1957 + /* iPhone */ 1958 + { USB_DEVICE_INTERFACE_NUMBER(0x05ac, 0x12a8, 2), 1959 + .driver_info = (unsigned long)&apple_tethering_interface_info, 1960 + }, 1961 + { USB_DEVICE_INTERFACE_NUMBER(0x05ac, 0x12a8, 4), 1962 + .driver_info = (unsigned long)&apple_private_interface_info, 1963 + }, 1964 + 1965 + /* iPad */ 1966 + { USB_DEVICE_INTERFACE_NUMBER(0x05ac, 0x12ab, 2), 1967 + .driver_info = (unsigned long)&apple_tethering_interface_info, 1968 + }, 1969 + { USB_DEVICE_INTERFACE_NUMBER(0x05ac, 0x12ab, 4), 1970 + .driver_info = (unsigned long)&apple_private_interface_info, 1971 + }, 1972 + 1986 1973 /* Ericsson MBM devices like F5521gw */ 1987 1974 { .match_flags = USB_DEVICE_ID_MATCH_INT_INFO 1988 1975 | USB_DEVICE_ID_MATCH_VENDOR,