19f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta/* 29f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * f_ncm.c -- USB CDC Network (NCM) link function driver 39f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * 49f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * Copyright (C) 2010 Nokia Corporation 59f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * Contact: Yauheni Kaliuta <yauheni.kaliuta@nokia.com> 69f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * 79f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * The driver borrows from f_ecm.c which is: 89f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * 99f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * Copyright (C) 2003-2005,2008 David Brownell 109f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * Copyright (C) 2008 Nokia Corporation 119f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * 129f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * This program is free software; you can redistribute it and/or modify 139f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * it under the terms of the GNU General Public License as published by 149f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * the Free Software Foundation; either version 2 of the License, or 159f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * (at your option) any later version. 169f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta */ 179f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 189f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta#include <linux/kernel.h> 199f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta#include <linux/device.h> 209f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta#include <linux/etherdevice.h> 219f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta#include <linux/crc32.h> 229f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 239f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta#include <linux/usb/cdc.h> 249f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 259f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta#include "u_ether.h" 269f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 279f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta/* 289f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * This function is a "CDC Network Control Model" (CDC NCM) Ethernet link. 299f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * NCM is intended to be used with high-speed network attachments. 309f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * 319f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * Note that NCM requires the use of "alternate settings" for its data 329f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * interface. This means that the set_alt() method has real work to do, 339f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * and also means that a get_alt() method is required. 349f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta */ 359f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 369f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta/* to trigger crc/non-crc ndp signature */ 379f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 389f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta#define NCM_NDP_HDR_CRC_MASK 0x01000000 399f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta#define NCM_NDP_HDR_CRC 0x01000000 409f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta#define NCM_NDP_HDR_NOCRC 0x00000000 419f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 429f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutaenum ncm_notify_state { 439f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta NCM_NOTIFY_NONE, /* don't notify */ 449f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta NCM_NOTIFY_CONNECT, /* issue CONNECT next */ 459f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta NCM_NOTIFY_SPEED, /* issue SPEED_CHANGE next */ 469f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta}; 479f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 489f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastruct f_ncm { 499f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta struct gether port; 509f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta u8 ctrl_id, data_id; 519f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 529f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta char ethaddr[14]; 539f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 549f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta struct usb_ep *notify; 559f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta struct usb_request *notify_req; 569f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta u8 notify_state; 579f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta bool is_open; 589f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 599f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta struct ndp_parser_opts *parser_opts; 609f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta bool is_crc; 619f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 629f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* 639f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * for notification, it is accessed from both 649f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * callback and ethernet open/close 659f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta */ 669f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta spinlock_t lock; 679f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta}; 689f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 699f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastatic inline struct f_ncm *func_to_ncm(struct usb_function *f) 709f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta{ 719f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta return container_of(f, struct f_ncm, port.func); 729f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta} 739f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 749f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta/* peak (theoretical) bulk transfer rate in bits-per-second */ 759f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastatic inline unsigned ncm_bitrate(struct usb_gadget *g) 769f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta{ 779f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) 789f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta return 13 * 512 * 8 * 1000 * 8; 799f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta else 809f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta return 19 * 64 * 1 * 1000 * 8; 819f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta} 829f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 839f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta/*-------------------------------------------------------------------------*/ 849f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 859f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta/* 869f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * We cannot group frames so use just the minimal size which ok to put 879f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * one max-size ethernet frame. 889f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * If the host can group frames, allow it to do that, 16K is selected, 899f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * because it's used by default by the current linux host driver 909f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta */ 919f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta#define NTB_DEFAULT_IN_SIZE USB_CDC_NCM_NTB_MIN_IN_SIZE 929f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta#define NTB_OUT_SIZE 16384 939f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 949f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta/* 9525985edcedea6396277003854657b5f3cb31a628Lucas De Marchi * skbs of size less than that will not be aligned 969f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * to NCM's dwNtbInMaxSize to save bus bandwidth 979f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta */ 989f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 999f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta#define MAX_TX_NONFIXED (512 * 3) 1009f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 1019f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta#define FORMATS_SUPPORTED (USB_CDC_NCM_NTB16_SUPPORTED | \ 1029f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta USB_CDC_NCM_NTB32_SUPPORTED) 1039f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 1049f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastatic struct usb_cdc_ncm_ntb_parameters ntb_parameters = { 1059f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .wLength = sizeof ntb_parameters, 1069f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bmNtbFormatsSupported = cpu_to_le16(FORMATS_SUPPORTED), 1079f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .dwNtbInMaxSize = cpu_to_le32(NTB_DEFAULT_IN_SIZE), 1089f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .wNdpInDivisor = cpu_to_le16(4), 1099f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .wNdpInPayloadRemainder = cpu_to_le16(0), 1109f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .wNdpInAlignment = cpu_to_le16(4), 1119f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 1129f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .dwNtbOutMaxSize = cpu_to_le32(NTB_OUT_SIZE), 1139f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .wNdpOutDivisor = cpu_to_le16(4), 1149f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .wNdpOutPayloadRemainder = cpu_to_le16(0), 1159f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .wNdpOutAlignment = cpu_to_le16(4), 1169f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta}; 1179f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 1189f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta/* 1199f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * Use wMaxPacketSize big enough to fit CDC_NOTIFY_SPEED_CHANGE in one 1209f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * packet, to simplify cancellation; and a big transfer interval, to 1219f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * waste less bandwidth. 1229f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta */ 1239f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 1249f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta#define LOG2_STATUS_INTERVAL_MSEC 5 /* 1 << 5 == 32 msec */ 1259f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta#define NCM_STATUS_BYTECOUNT 16 /* 8 byte header + data */ 1269f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 1279f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastatic struct usb_interface_assoc_descriptor ncm_iad_desc __initdata = { 1289f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bLength = sizeof ncm_iad_desc, 1299f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, 1309f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 1319f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* .bFirstInterface = DYNAMIC, */ 1329f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bInterfaceCount = 2, /* control + data */ 1339f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bFunctionClass = USB_CLASS_COMM, 1349f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bFunctionSubClass = USB_CDC_SUBCLASS_NCM, 1359f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bFunctionProtocol = USB_CDC_PROTO_NONE, 1369f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* .iFunction = DYNAMIC */ 1379f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta}; 1389f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 1399f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta/* interface descriptor: */ 1409f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 1419f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastatic struct usb_interface_descriptor ncm_control_intf __initdata = { 1429f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bLength = sizeof ncm_control_intf, 1439f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bDescriptorType = USB_DT_INTERFACE, 1449f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 1459f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* .bInterfaceNumber = DYNAMIC */ 1469f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bNumEndpoints = 1, 1479f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bInterfaceClass = USB_CLASS_COMM, 1489f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bInterfaceSubClass = USB_CDC_SUBCLASS_NCM, 1499f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bInterfaceProtocol = USB_CDC_PROTO_NONE, 1509f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* .iInterface = DYNAMIC */ 1519f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta}; 1529f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 1539f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastatic struct usb_cdc_header_desc ncm_header_desc __initdata = { 1549f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bLength = sizeof ncm_header_desc, 1559f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bDescriptorType = USB_DT_CS_INTERFACE, 1569f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bDescriptorSubType = USB_CDC_HEADER_TYPE, 1579f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 1589f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bcdCDC = cpu_to_le16(0x0110), 1599f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta}; 1609f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 1619f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastatic struct usb_cdc_union_desc ncm_union_desc __initdata = { 1629f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bLength = sizeof(ncm_union_desc), 1639f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bDescriptorType = USB_DT_CS_INTERFACE, 1649f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bDescriptorSubType = USB_CDC_UNION_TYPE, 1659f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* .bMasterInterface0 = DYNAMIC */ 1669f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* .bSlaveInterface0 = DYNAMIC */ 1679f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta}; 1689f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 1699f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastatic struct usb_cdc_ether_desc ecm_desc __initdata = { 1709f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bLength = sizeof ecm_desc, 1719f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bDescriptorType = USB_DT_CS_INTERFACE, 1729f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bDescriptorSubType = USB_CDC_ETHERNET_TYPE, 1739f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 1749f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* this descriptor actually adds value, surprise! */ 1759f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* .iMACAddress = DYNAMIC */ 1769f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bmEthernetStatistics = cpu_to_le32(0), /* no statistics */ 1779f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .wMaxSegmentSize = cpu_to_le16(ETH_FRAME_LEN), 1789f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .wNumberMCFilters = cpu_to_le16(0), 1799f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bNumberPowerFilters = 0, 1809f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta}; 1819f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 1829f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta#define NCAPS (USB_CDC_NCM_NCAP_ETH_FILTER | USB_CDC_NCM_NCAP_CRC_MODE) 1839f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 1849f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastatic struct usb_cdc_ncm_desc ncm_desc __initdata = { 1859f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bLength = sizeof ncm_desc, 1869f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bDescriptorType = USB_DT_CS_INTERFACE, 1879f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bDescriptorSubType = USB_CDC_NCM_TYPE, 1889f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 1899f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bcdNcmVersion = cpu_to_le16(0x0100), 1909f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* can process SetEthernetPacketFilter */ 1919f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bmNetworkCapabilities = NCAPS, 1929f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta}; 1939f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 1949f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta/* the default data interface has no endpoints ... */ 1959f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 1969f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastatic struct usb_interface_descriptor ncm_data_nop_intf __initdata = { 1979f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bLength = sizeof ncm_data_nop_intf, 1989f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bDescriptorType = USB_DT_INTERFACE, 1999f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 2009f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bInterfaceNumber = 1, 2019f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bAlternateSetting = 0, 2029f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bNumEndpoints = 0, 2039f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bInterfaceClass = USB_CLASS_CDC_DATA, 2049f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bInterfaceSubClass = 0, 2059f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bInterfaceProtocol = USB_CDC_NCM_PROTO_NTB, 2069f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* .iInterface = DYNAMIC */ 2079f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta}; 2089f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 2099f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta/* ... but the "real" data interface has two bulk endpoints */ 2109f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 2119f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastatic struct usb_interface_descriptor ncm_data_intf __initdata = { 2129f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bLength = sizeof ncm_data_intf, 2139f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bDescriptorType = USB_DT_INTERFACE, 2149f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 2159f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bInterfaceNumber = 1, 2169f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bAlternateSetting = 1, 2179f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bNumEndpoints = 2, 2189f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bInterfaceClass = USB_CLASS_CDC_DATA, 2199f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bInterfaceSubClass = 0, 2209f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bInterfaceProtocol = USB_CDC_NCM_PROTO_NTB, 2219f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* .iInterface = DYNAMIC */ 2229f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta}; 2239f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 2249f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta/* full speed support: */ 2259f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 2269f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastatic struct usb_endpoint_descriptor fs_ncm_notify_desc __initdata = { 2279f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bLength = USB_DT_ENDPOINT_SIZE, 2289f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bDescriptorType = USB_DT_ENDPOINT, 2299f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 2309f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bEndpointAddress = USB_DIR_IN, 2319f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bmAttributes = USB_ENDPOINT_XFER_INT, 2329f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .wMaxPacketSize = cpu_to_le16(NCM_STATUS_BYTECOUNT), 2339f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC, 2349f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta}; 2359f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 2369f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastatic struct usb_endpoint_descriptor fs_ncm_in_desc __initdata = { 2379f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bLength = USB_DT_ENDPOINT_SIZE, 2389f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bDescriptorType = USB_DT_ENDPOINT, 2399f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 2409f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bEndpointAddress = USB_DIR_IN, 2419f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bmAttributes = USB_ENDPOINT_XFER_BULK, 2429f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta}; 2439f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 2449f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastatic struct usb_endpoint_descriptor fs_ncm_out_desc __initdata = { 2459f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bLength = USB_DT_ENDPOINT_SIZE, 2469f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bDescriptorType = USB_DT_ENDPOINT, 2479f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 2489f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bEndpointAddress = USB_DIR_OUT, 2499f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bmAttributes = USB_ENDPOINT_XFER_BULK, 2509f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta}; 2519f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 2529f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastatic struct usb_descriptor_header *ncm_fs_function[] __initdata = { 2539f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta (struct usb_descriptor_header *) &ncm_iad_desc, 2549f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* CDC NCM control descriptors */ 2559f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta (struct usb_descriptor_header *) &ncm_control_intf, 2569f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta (struct usb_descriptor_header *) &ncm_header_desc, 2579f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta (struct usb_descriptor_header *) &ncm_union_desc, 2589f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta (struct usb_descriptor_header *) &ecm_desc, 2599f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta (struct usb_descriptor_header *) &ncm_desc, 2609f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta (struct usb_descriptor_header *) &fs_ncm_notify_desc, 2619f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* data interface, altsettings 0 and 1 */ 2629f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta (struct usb_descriptor_header *) &ncm_data_nop_intf, 2639f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta (struct usb_descriptor_header *) &ncm_data_intf, 2649f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta (struct usb_descriptor_header *) &fs_ncm_in_desc, 2659f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta (struct usb_descriptor_header *) &fs_ncm_out_desc, 2669f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta NULL, 2679f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta}; 2689f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 2699f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta/* high speed support: */ 2709f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 2719f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastatic struct usb_endpoint_descriptor hs_ncm_notify_desc __initdata = { 2729f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bLength = USB_DT_ENDPOINT_SIZE, 2739f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bDescriptorType = USB_DT_ENDPOINT, 2749f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 2759f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bEndpointAddress = USB_DIR_IN, 2769f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bmAttributes = USB_ENDPOINT_XFER_INT, 2779f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .wMaxPacketSize = cpu_to_le16(NCM_STATUS_BYTECOUNT), 2789f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bInterval = LOG2_STATUS_INTERVAL_MSEC + 4, 2799f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta}; 2809f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastatic struct usb_endpoint_descriptor hs_ncm_in_desc __initdata = { 2819f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bLength = USB_DT_ENDPOINT_SIZE, 2829f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bDescriptorType = USB_DT_ENDPOINT, 2839f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 2849f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bEndpointAddress = USB_DIR_IN, 2859f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bmAttributes = USB_ENDPOINT_XFER_BULK, 2869f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .wMaxPacketSize = cpu_to_le16(512), 2879f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta}; 2889f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 2899f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastatic struct usb_endpoint_descriptor hs_ncm_out_desc __initdata = { 2909f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bLength = USB_DT_ENDPOINT_SIZE, 2919f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bDescriptorType = USB_DT_ENDPOINT, 2929f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 2939f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bEndpointAddress = USB_DIR_OUT, 2949f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .bmAttributes = USB_ENDPOINT_XFER_BULK, 2959f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .wMaxPacketSize = cpu_to_le16(512), 2969f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta}; 2979f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 2989f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastatic struct usb_descriptor_header *ncm_hs_function[] __initdata = { 2999f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta (struct usb_descriptor_header *) &ncm_iad_desc, 3009f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* CDC NCM control descriptors */ 3019f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta (struct usb_descriptor_header *) &ncm_control_intf, 3029f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta (struct usb_descriptor_header *) &ncm_header_desc, 3039f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta (struct usb_descriptor_header *) &ncm_union_desc, 3049f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta (struct usb_descriptor_header *) &ecm_desc, 3059f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta (struct usb_descriptor_header *) &ncm_desc, 3069f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta (struct usb_descriptor_header *) &hs_ncm_notify_desc, 3079f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* data interface, altsettings 0 and 1 */ 3089f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta (struct usb_descriptor_header *) &ncm_data_nop_intf, 3099f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta (struct usb_descriptor_header *) &ncm_data_intf, 3109f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta (struct usb_descriptor_header *) &hs_ncm_in_desc, 3119f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta (struct usb_descriptor_header *) &hs_ncm_out_desc, 3129f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta NULL, 3139f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta}; 3149f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 3159f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta/* string descriptors: */ 3169f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 3179f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta#define STRING_CTRL_IDX 0 3189f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta#define STRING_MAC_IDX 1 3199f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta#define STRING_DATA_IDX 2 3209f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta#define STRING_IAD_IDX 3 3219f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 3229f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastatic struct usb_string ncm_string_defs[] = { 3239f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta [STRING_CTRL_IDX].s = "CDC Network Control Model (NCM)", 3249f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta [STRING_MAC_IDX].s = NULL /* DYNAMIC */, 3259f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta [STRING_DATA_IDX].s = "CDC Network Data", 3269f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta [STRING_IAD_IDX].s = "CDC NCM", 3279f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta { } /* end of list */ 3289f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta}; 3299f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 3309f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastatic struct usb_gadget_strings ncm_string_table = { 3319f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .language = 0x0409, /* en-us */ 3329f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .strings = ncm_string_defs, 3339f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta}; 3349f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 3359f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastatic struct usb_gadget_strings *ncm_strings[] = { 3369f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta &ncm_string_table, 3379f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta NULL, 3389f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta}; 3399f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 3409f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta/* 3419f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * Here are options for NCM Datagram Pointer table (NDP) parser. 3429f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * There are 2 different formats: NDP16 and NDP32 in the spec (ch. 3), 3439f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * in NDP16 offsets and sizes fields are 1 16bit word wide, 3449f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * in NDP32 -- 2 16bit words wide. Also signatures are different. 3459f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * To make the parser code the same, put the differences in the structure, 3469f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * and switch pointers to the structures when the format is changed. 3479f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta */ 3489f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 3499f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastruct ndp_parser_opts { 3509f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta u32 nth_sign; 3519f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta u32 ndp_sign; 3529f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta unsigned nth_size; 3539f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta unsigned ndp_size; 3549f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta unsigned ndplen_align; 3559f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* sizes in u16 units */ 3569f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta unsigned dgram_item_len; /* index or length */ 3579f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta unsigned block_length; 3589f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta unsigned fp_index; 3599f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta unsigned reserved1; 3609f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta unsigned reserved2; 3619f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta unsigned next_fp_index; 3629f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta}; 3639f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 3649f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta#define INIT_NDP16_OPTS { \ 3659f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .nth_sign = USB_CDC_NCM_NTH16_SIGN, \ 3669f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .ndp_sign = USB_CDC_NCM_NDP16_NOCRC_SIGN, \ 3679f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .nth_size = sizeof(struct usb_cdc_ncm_nth16), \ 3689f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .ndp_size = sizeof(struct usb_cdc_ncm_ndp16), \ 3699f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .ndplen_align = 4, \ 3709f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .dgram_item_len = 1, \ 3719f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .block_length = 1, \ 3729f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .fp_index = 1, \ 3739f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .reserved1 = 0, \ 3749f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .reserved2 = 0, \ 3759f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .next_fp_index = 1, \ 3769f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } 3779f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 3789f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 3799f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta#define INIT_NDP32_OPTS { \ 3809f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .nth_sign = USB_CDC_NCM_NTH32_SIGN, \ 3819f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .ndp_sign = USB_CDC_NCM_NDP32_NOCRC_SIGN, \ 3829f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .nth_size = sizeof(struct usb_cdc_ncm_nth32), \ 3839f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .ndp_size = sizeof(struct usb_cdc_ncm_ndp32), \ 3849f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .ndplen_align = 8, \ 3859f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .dgram_item_len = 2, \ 3869f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .block_length = 2, \ 3879f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .fp_index = 2, \ 3889f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .reserved1 = 1, \ 3899f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .reserved2 = 2, \ 3909f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta .next_fp_index = 2, \ 3919f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } 3929f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 3939f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastatic struct ndp_parser_opts ndp16_opts = INIT_NDP16_OPTS; 3949f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastatic struct ndp_parser_opts ndp32_opts = INIT_NDP32_OPTS; 3959f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 3969f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastatic inline void put_ncm(__le16 **p, unsigned size, unsigned val) 3979f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta{ 3989f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta switch (size) { 3999f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta case 1: 4009f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta put_unaligned_le16((u16)val, *p); 4019f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta break; 4029f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta case 2: 4039f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta put_unaligned_le32((u32)val, *p); 4049f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 4059f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta break; 4069f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta default: 4079f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta BUG(); 4089f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } 4099f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 4109f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta *p += size; 4119f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta} 4129f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 4139f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastatic inline unsigned get_ncm(__le16 **p, unsigned size) 4149f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta{ 4159f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta unsigned tmp; 4169f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 4179f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta switch (size) { 4189f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta case 1: 4199f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta tmp = get_unaligned_le16(*p); 4209f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta break; 4219f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta case 2: 4229f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta tmp = get_unaligned_le32(*p); 4239f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta break; 4249f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta default: 4259f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta BUG(); 4269f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } 4279f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 4289f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta *p += size; 4299f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta return tmp; 4309f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta} 4319f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 4329f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta/*-------------------------------------------------------------------------*/ 4339f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 4349f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastatic inline void ncm_reset_values(struct f_ncm *ncm) 4359f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta{ 4369f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->parser_opts = &ndp16_opts; 4379f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->is_crc = false; 4389f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->port.cdc_filter = DEFAULT_FILTER; 4399f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 4409f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* doesn't make sense for ncm, fixed size used */ 4419f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->port.header_len = 0; 4429f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 4439f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->port.fixed_out_len = le32_to_cpu(ntb_parameters.dwNtbOutMaxSize); 4449f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->port.fixed_in_len = NTB_DEFAULT_IN_SIZE; 4459f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta} 4469f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 4479f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta/* 4489f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * Context: ncm->lock held 4499f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta */ 4509f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastatic void ncm_do_notify(struct f_ncm *ncm) 4519f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta{ 4529f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta struct usb_request *req = ncm->notify_req; 4539f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta struct usb_cdc_notification *event; 4549f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta struct usb_composite_dev *cdev = ncm->port.func.config->cdev; 4559f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta __le32 *data; 4569f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta int status; 4579f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 4589f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* notification already in flight? */ 4599f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (!req) 4609f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta return; 4619f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 4629f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta event = req->buf; 4639f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta switch (ncm->notify_state) { 4649f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta case NCM_NOTIFY_NONE: 4659f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta return; 4669f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 4679f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta case NCM_NOTIFY_CONNECT: 4689f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta event->bNotificationType = USB_CDC_NOTIFY_NETWORK_CONNECTION; 4699f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (ncm->is_open) 4709f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta event->wValue = cpu_to_le16(1); 4719f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta else 4729f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta event->wValue = cpu_to_le16(0); 4739f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta event->wLength = 0; 4749f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta req->length = sizeof *event; 4759f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 4769f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta DBG(cdev, "notify connect %s\n", 4779f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->is_open ? "true" : "false"); 4789f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->notify_state = NCM_NOTIFY_NONE; 4799f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta break; 4809f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 4819f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta case NCM_NOTIFY_SPEED: 4829f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta event->bNotificationType = USB_CDC_NOTIFY_SPEED_CHANGE; 4839f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta event->wValue = cpu_to_le16(0); 4849f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta event->wLength = cpu_to_le16(8); 4859f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta req->length = NCM_STATUS_BYTECOUNT; 4869f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 4879f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* SPEED_CHANGE data is up/down speeds in bits/sec */ 4889f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta data = req->buf + sizeof *event; 4899f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta data[0] = cpu_to_le32(ncm_bitrate(cdev->gadget)); 4909f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta data[1] = data[0]; 4919f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 4929f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta DBG(cdev, "notify speed %d\n", ncm_bitrate(cdev->gadget)); 4939f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->notify_state = NCM_NOTIFY_CONNECT; 4949f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta break; 4959f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } 4969f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta event->bmRequestType = 0xA1; 4979f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta event->wIndex = cpu_to_le16(ncm->ctrl_id); 4989f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 4999f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->notify_req = NULL; 5009f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* 5019f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * In double buffering if there is a space in FIFO, 5029f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * completion callback can be called right after the call, 5039f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * so unlocking 5049f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta */ 5059f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta spin_unlock(&ncm->lock); 5069f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta status = usb_ep_queue(ncm->notify, req, GFP_ATOMIC); 5079f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta spin_lock(&ncm->lock); 5089f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (status < 0) { 5099f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->notify_req = req; 5109f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta DBG(cdev, "notify --> %d\n", status); 5119f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } 5129f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta} 5139f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 5149f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta/* 5159f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * Context: ncm->lock held 5169f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta */ 5179f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastatic void ncm_notify(struct f_ncm *ncm) 5189f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta{ 5199f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* 5209f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * NOTE on most versions of Linux, host side cdc-ethernet 5219f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * won't listen for notifications until its netdevice opens. 5229f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * The first notification then sits in the FIFO for a long 5239f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * time, and the second one is queued. 5249f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * 5259f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * If ncm_notify() is called before the second (CONNECT) 5269f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * notification is sent, then it will reset to send the SPEED 5279f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * notificaion again (and again, and again), but it's not a problem 5289f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta */ 5299f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->notify_state = NCM_NOTIFY_SPEED; 5309f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm_do_notify(ncm); 5319f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta} 5329f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 5339f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastatic void ncm_notify_complete(struct usb_ep *ep, struct usb_request *req) 5349f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta{ 5359f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta struct f_ncm *ncm = req->context; 5369f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta struct usb_composite_dev *cdev = ncm->port.func.config->cdev; 5379f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta struct usb_cdc_notification *event = req->buf; 5389f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 5399f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta spin_lock(&ncm->lock); 5409f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta switch (req->status) { 5419f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta case 0: 5429f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta VDBG(cdev, "Notification %02x sent\n", 5439f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta event->bNotificationType); 5449f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta break; 5459f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta case -ECONNRESET: 5469f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta case -ESHUTDOWN: 5479f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->notify_state = NCM_NOTIFY_NONE; 5489f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta break; 5499f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta default: 5509f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta DBG(cdev, "event %02x --> %d\n", 5519f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta event->bNotificationType, req->status); 5529f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta break; 5539f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } 5549f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->notify_req = req; 5559f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm_do_notify(ncm); 5569f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta spin_unlock(&ncm->lock); 5579f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta} 5589f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 5599f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastatic void ncm_ep0out_complete(struct usb_ep *ep, struct usb_request *req) 5609f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta{ 5619f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* now for SET_NTB_INPUT_SIZE only */ 5629f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta unsigned in_size; 5639f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta struct usb_function *f = req->context; 5649f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta struct f_ncm *ncm = func_to_ncm(f); 5659f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta struct usb_composite_dev *cdev = ep->driver_data; 5669f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 5679f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta req->context = NULL; 5689f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (req->status || req->actual != req->length) { 5699f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta DBG(cdev, "Bad control-OUT transfer\n"); 5709f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta goto invalid; 5719f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } 5729f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 5739f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta in_size = get_unaligned_le32(req->buf); 5749f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (in_size < USB_CDC_NCM_NTB_MIN_IN_SIZE || 5759f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta in_size > le32_to_cpu(ntb_parameters.dwNtbInMaxSize)) { 5769f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta DBG(cdev, "Got wrong INPUT SIZE (%d) from host\n", in_size); 5779f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta goto invalid; 5789f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } 5799f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 5809f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->port.fixed_in_len = in_size; 5819f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta VDBG(cdev, "Set NTB INPUT SIZE %d\n", in_size); 5829f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta return; 5839f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 5849f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutainvalid: 5859f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta usb_ep_set_halt(ep); 5869f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta return; 5879f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta} 5889f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 5899f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastatic int ncm_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) 5909f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta{ 5919f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta struct f_ncm *ncm = func_to_ncm(f); 5929f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta struct usb_composite_dev *cdev = f->config->cdev; 5939f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta struct usb_request *req = cdev->req; 5949f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta int value = -EOPNOTSUPP; 5959f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta u16 w_index = le16_to_cpu(ctrl->wIndex); 5969f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta u16 w_value = le16_to_cpu(ctrl->wValue); 5979f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta u16 w_length = le16_to_cpu(ctrl->wLength); 5989f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 5999f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* 6009f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * composite driver infrastructure handles everything except 6019f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * CDC class messages; interface activation uses set_alt(). 6029f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta */ 6039f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta switch ((ctrl->bRequestType << 8) | ctrl->bRequest) { 6049f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) 6059f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta | USB_CDC_SET_ETHERNET_PACKET_FILTER: 6069f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* 6079f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * see 6.2.30: no data, wIndex = interface, 6089f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * wValue = packet filter bitmap 6099f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta */ 6109f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (w_length != 0 || w_index != ncm->ctrl_id) 6119f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta goto invalid; 6129f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta DBG(cdev, "packet filter %02x\n", w_value); 6139f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* 6149f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * REVISIT locking of cdc_filter. This assumes the UDC 6159f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * driver won't have a concurrent packet TX irq running on 6169f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * another CPU; or that if it does, this write is atomic... 6179f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta */ 6189f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->port.cdc_filter = w_value; 6199f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta value = 0; 6209f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta break; 6219f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* 6229f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * and optionally: 6239f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * case USB_CDC_SEND_ENCAPSULATED_COMMAND: 6249f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * case USB_CDC_GET_ENCAPSULATED_RESPONSE: 6259f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * case USB_CDC_SET_ETHERNET_MULTICAST_FILTERS: 6269f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * case USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER: 6279f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * case USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER: 6289f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * case USB_CDC_GET_ETHERNET_STATISTIC: 6299f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta */ 6309f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 6319f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) 6329f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta | USB_CDC_GET_NTB_PARAMETERS: 6339f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 6349f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (w_length == 0 || w_value != 0 || w_index != ncm->ctrl_id) 6359f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta goto invalid; 6369f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta value = w_length > sizeof ntb_parameters ? 6379f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta sizeof ntb_parameters : w_length; 6389f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta memcpy(req->buf, &ntb_parameters, value); 6399f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta VDBG(cdev, "Host asked NTB parameters\n"); 6409f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta break; 6419f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 6429f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) 6439f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta | USB_CDC_GET_NTB_INPUT_SIZE: 6449f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 6459f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (w_length < 4 || w_value != 0 || w_index != ncm->ctrl_id) 6469f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta goto invalid; 6479f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta put_unaligned_le32(ncm->port.fixed_in_len, req->buf); 6489f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta value = 4; 6499f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta VDBG(cdev, "Host asked INPUT SIZE, sending %d\n", 6509f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->port.fixed_in_len); 6519f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta break; 6529f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 6539f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) 6549f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta | USB_CDC_SET_NTB_INPUT_SIZE: 6559f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta { 6569f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (w_length != 4 || w_value != 0 || w_index != ncm->ctrl_id) 6579f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta goto invalid; 6589f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta req->complete = ncm_ep0out_complete; 6599f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta req->length = w_length; 6609f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta req->context = f; 6619f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 6629f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta value = req->length; 6639f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta break; 6649f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } 6659f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 6669f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) 6679f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta | USB_CDC_GET_NTB_FORMAT: 6689f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta { 6699f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta uint16_t format; 6709f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 6719f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (w_length < 2 || w_value != 0 || w_index != ncm->ctrl_id) 6729f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta goto invalid; 6739f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta format = (ncm->parser_opts == &ndp16_opts) ? 0x0000 : 0x0001; 6749f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta put_unaligned_le16(format, req->buf); 6759f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta value = 2; 6769f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta VDBG(cdev, "Host asked NTB FORMAT, sending %d\n", format); 6779f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta break; 6789f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } 6799f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 6809f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) 6819f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta | USB_CDC_SET_NTB_FORMAT: 6829f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta { 6839f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (w_length != 0 || w_index != ncm->ctrl_id) 6849f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta goto invalid; 6859f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta switch (w_value) { 6869f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta case 0x0000: 6879f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->parser_opts = &ndp16_opts; 6889f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta DBG(cdev, "NCM16 selected\n"); 6899f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta break; 6909f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta case 0x0001: 6919f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->parser_opts = &ndp32_opts; 6929f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta DBG(cdev, "NCM32 selected\n"); 6939f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta break; 6949f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta default: 6959f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta goto invalid; 6969f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } 6979f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta value = 0; 6989f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta break; 6999f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } 7009f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) 7019f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta | USB_CDC_GET_CRC_MODE: 7029f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta { 7039f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta uint16_t is_crc; 7049f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 7059f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (w_length < 2 || w_value != 0 || w_index != ncm->ctrl_id) 7069f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta goto invalid; 7079f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta is_crc = ncm->is_crc ? 0x0001 : 0x0000; 7089f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta put_unaligned_le16(is_crc, req->buf); 7099f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta value = 2; 7109f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta VDBG(cdev, "Host asked CRC MODE, sending %d\n", is_crc); 7119f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta break; 7129f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } 7139f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 7149f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) 7159f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta | USB_CDC_SET_CRC_MODE: 7169f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta { 7179f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta int ndp_hdr_crc = 0; 7189f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 7199f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (w_length != 0 || w_index != ncm->ctrl_id) 7209f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta goto invalid; 7219f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta switch (w_value) { 7229f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta case 0x0000: 7239f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->is_crc = false; 7249f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ndp_hdr_crc = NCM_NDP_HDR_NOCRC; 7259f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta DBG(cdev, "non-CRC mode selected\n"); 7269f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta break; 7279f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta case 0x0001: 7289f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->is_crc = true; 7299f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ndp_hdr_crc = NCM_NDP_HDR_CRC; 7309f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta DBG(cdev, "CRC mode selected\n"); 7319f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta break; 7329f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta default: 7339f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta goto invalid; 7349f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } 7359f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->parser_opts->ndp_sign &= ~NCM_NDP_HDR_CRC_MASK; 7369f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->parser_opts->ndp_sign |= ndp_hdr_crc; 7379f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta value = 0; 7389f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta break; 7399f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } 7409f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 7419f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* and disabled in ncm descriptor: */ 7429f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* case USB_CDC_GET_NET_ADDRESS: */ 7439f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* case USB_CDC_SET_NET_ADDRESS: */ 7449f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* case USB_CDC_GET_MAX_DATAGRAM_SIZE: */ 7459f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* case USB_CDC_SET_MAX_DATAGRAM_SIZE: */ 7469f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 7479f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta default: 7489f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutainvalid: 7499f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta DBG(cdev, "invalid control req%02x.%02x v%04x i%04x l%d\n", 7509f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ctrl->bRequestType, ctrl->bRequest, 7519f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta w_value, w_index, w_length); 7529f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } 7539f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 7549f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* respond with data transfer or status phase? */ 7559f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (value >= 0) { 7569f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta DBG(cdev, "ncm req%02x.%02x v%04x i%04x l%d\n", 7579f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ctrl->bRequestType, ctrl->bRequest, 7589f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta w_value, w_index, w_length); 7599f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta req->zero = 0; 7609f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta req->length = value; 7619f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC); 7629f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (value < 0) 7639f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ERROR(cdev, "ncm req %02x.%02x response err %d\n", 7649f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ctrl->bRequestType, ctrl->bRequest, 7659f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta value); 7669f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } 7679f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 7689f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* device either stalls (value < 0) or reports success */ 7699f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta return value; 7709f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta} 7719f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 7729f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 7739f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastatic int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt) 7749f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta{ 7759f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta struct f_ncm *ncm = func_to_ncm(f); 7769f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta struct usb_composite_dev *cdev = f->config->cdev; 7779f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 7789f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* Control interface has only altsetting 0 */ 7799f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (intf == ncm->ctrl_id) { 7809f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (alt != 0) 7819f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta goto fail; 7829f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 7839f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (ncm->notify->driver_data) { 7849f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta DBG(cdev, "reset ncm control %d\n", intf); 7859f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta usb_ep_disable(ncm->notify); 786ea2a1df7b2b1de839a72217d85bfb4b7b049010cTatyana Brokhman } 787ea2a1df7b2b1de839a72217d85bfb4b7b049010cTatyana Brokhman 788ea2a1df7b2b1de839a72217d85bfb4b7b049010cTatyana Brokhman if (!(ncm->notify->desc)) { 7899f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta DBG(cdev, "init ncm ctrl %d\n", intf); 790ea2a1df7b2b1de839a72217d85bfb4b7b049010cTatyana Brokhman if (config_ep_by_speed(cdev->gadget, f, ncm->notify)) 791ea2a1df7b2b1de839a72217d85bfb4b7b049010cTatyana Brokhman goto fail; 7929f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } 79372c973dd2b01b212a159faa330a2bc641a3ed809Tatyana Brokhman usb_ep_enable(ncm->notify); 7949f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->notify->driver_data = ncm; 7959f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 7969f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* Data interface has two altsettings, 0 and 1 */ 7979f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } else if (intf == ncm->data_id) { 7989f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (alt > 1) 7999f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta goto fail; 8009f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 8019f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (ncm->port.in_ep->driver_data) { 8029f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta DBG(cdev, "reset ncm\n"); 8039f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta gether_disconnect(&ncm->port); 8049f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm_reset_values(ncm); 8059f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } 8069f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 8079f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* 8089f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * CDC Network only sends data in non-default altsettings. 8099f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * Changing altsettings resets filters, statistics, etc. 8109f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta */ 8119f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (alt == 1) { 8129f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta struct net_device *net; 8139f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 814ea2a1df7b2b1de839a72217d85bfb4b7b049010cTatyana Brokhman if (!ncm->port.in_ep->desc || 815ea2a1df7b2b1de839a72217d85bfb4b7b049010cTatyana Brokhman !ncm->port.out_ep->desc) { 8169f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta DBG(cdev, "init ncm\n"); 817ea2a1df7b2b1de839a72217d85bfb4b7b049010cTatyana Brokhman if (config_ep_by_speed(cdev->gadget, f, 818ea2a1df7b2b1de839a72217d85bfb4b7b049010cTatyana Brokhman ncm->port.in_ep) || 819ea2a1df7b2b1de839a72217d85bfb4b7b049010cTatyana Brokhman config_ep_by_speed(cdev->gadget, f, 820ea2a1df7b2b1de839a72217d85bfb4b7b049010cTatyana Brokhman ncm->port.out_ep)) { 821ea2a1df7b2b1de839a72217d85bfb4b7b049010cTatyana Brokhman ncm->port.in_ep->desc = NULL; 822ea2a1df7b2b1de839a72217d85bfb4b7b049010cTatyana Brokhman ncm->port.out_ep->desc = NULL; 823ea2a1df7b2b1de839a72217d85bfb4b7b049010cTatyana Brokhman goto fail; 824ea2a1df7b2b1de839a72217d85bfb4b7b049010cTatyana Brokhman } 8259f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } 8269f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 8279f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* TODO */ 8289f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* Enable zlps by default for NCM conformance; 8299f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * override for musb_hdrc (avoids txdma ovhead) 8309f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta */ 8319f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->port.is_zlp_ok = !( 8329f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta gadget_is_musbhdrc(cdev->gadget) 8339f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ); 8349f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->port.cdc_filter = DEFAULT_FILTER; 8359f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta DBG(cdev, "activate ncm\n"); 8369f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta net = gether_connect(&ncm->port); 8379f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (IS_ERR(net)) 8389f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta return PTR_ERR(net); 8399f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } 8409f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 8419f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta spin_lock(&ncm->lock); 8429f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm_notify(ncm); 8439f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta spin_unlock(&ncm->lock); 8449f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } else 8459f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta goto fail; 8469f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 8479f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta return 0; 8489f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutafail: 8499f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta return -EINVAL; 8509f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta} 8519f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 8529f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta/* 8539f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * Because the data interface supports multiple altsettings, 8549f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * this NCM function *MUST* implement a get_alt() method. 8559f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta */ 8569f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastatic int ncm_get_alt(struct usb_function *f, unsigned intf) 8579f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta{ 8589f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta struct f_ncm *ncm = func_to_ncm(f); 8599f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 8609f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (intf == ncm->ctrl_id) 8619f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta return 0; 8629f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta return ncm->port.in_ep->driver_data ? 1 : 0; 8639f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta} 8649f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 8659f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastatic struct sk_buff *ncm_wrap_ntb(struct gether *port, 8669f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta struct sk_buff *skb) 8679f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta{ 8689f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta struct f_ncm *ncm = func_to_ncm(&port->func); 8699f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta struct sk_buff *skb2; 8709f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta int ncb_len = 0; 8719f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta __le16 *tmp; 8729f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta int div = ntb_parameters.wNdpInDivisor; 8739f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta int rem = ntb_parameters.wNdpInPayloadRemainder; 8749f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta int pad; 8759f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta int ndp_align = ntb_parameters.wNdpInAlignment; 8769f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta int ndp_pad; 8779f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta unsigned max_size = ncm->port.fixed_in_len; 8789f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta struct ndp_parser_opts *opts = ncm->parser_opts; 8799f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta unsigned crc_len = ncm->is_crc ? sizeof(uint32_t) : 0; 8809f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 8819f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncb_len += opts->nth_size; 8829f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ndp_pad = ALIGN(ncb_len, ndp_align) - ncb_len; 8839f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncb_len += ndp_pad; 8849f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncb_len += opts->ndp_size; 8859f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncb_len += 2 * 2 * opts->dgram_item_len; /* Datagram entry */ 8869f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncb_len += 2 * 2 * opts->dgram_item_len; /* Zero datagram entry */ 8879f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta pad = ALIGN(ncb_len, div) + rem - ncb_len; 8889f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncb_len += pad; 8899f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 8909f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (ncb_len + skb->len + crc_len > max_size) { 8919f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta dev_kfree_skb_any(skb); 8929f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta return NULL; 8939f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } 8949f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 8959f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta skb2 = skb_copy_expand(skb, ncb_len, 8969f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta max_size - skb->len - ncb_len - crc_len, 8979f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta GFP_ATOMIC); 8989f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta dev_kfree_skb_any(skb); 8999f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (!skb2) 9009f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta return NULL; 9019f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 9029f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta skb = skb2; 9039f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 9049f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta tmp = (void *) skb_push(skb, ncb_len); 9059f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta memset(tmp, 0, ncb_len); 9069f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 9079f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta put_unaligned_le32(opts->nth_sign, tmp); /* dwSignature */ 9089f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta tmp += 2; 9099f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* wHeaderLength */ 9109f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta put_unaligned_le16(opts->nth_size, tmp++); 9119f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta tmp++; /* skip wSequence */ 9129f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta put_ncm(&tmp, opts->block_length, skb->len); /* (d)wBlockLength */ 9139f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* (d)wFpIndex */ 9149f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* the first pointer is right after the NTH + align */ 9159f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta put_ncm(&tmp, opts->fp_index, opts->nth_size + ndp_pad); 9169f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 9179f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta tmp = (void *)tmp + ndp_pad; 9189f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 9199f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* NDP */ 9209f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta put_unaligned_le32(opts->ndp_sign, tmp); /* dwSignature */ 9219f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta tmp += 2; 9229f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* wLength */ 9239f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta put_unaligned_le16(ncb_len - opts->nth_size - pad, tmp++); 9249f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 9259f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta tmp += opts->reserved1; 9269f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta tmp += opts->next_fp_index; /* skip reserved (d)wNextFpIndex */ 9279f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta tmp += opts->reserved2; 9289f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 9299f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (ncm->is_crc) { 9309f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta uint32_t crc; 9319f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 9329f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta crc = ~crc32_le(~0, 9339f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta skb->data + ncb_len, 9349f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta skb->len - ncb_len); 9359f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta put_unaligned_le32(crc, skb->data + skb->len); 9369f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta skb_put(skb, crc_len); 9379f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } 9389f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 9399f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* (d)wDatagramIndex[0] */ 9409f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta put_ncm(&tmp, opts->dgram_item_len, ncb_len); 9419f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* (d)wDatagramLength[0] */ 9429f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta put_ncm(&tmp, opts->dgram_item_len, skb->len - ncb_len); 9439f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* (d)wDatagramIndex[1] and (d)wDatagramLength[1] already zeroed */ 9449f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 9459f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (skb->len > MAX_TX_NONFIXED) 9469f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta memset(skb_put(skb, max_size - skb->len), 9479f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 0, max_size - skb->len); 9489f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 9499f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta return skb; 9509f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta} 9519f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 9529f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastatic int ncm_unwrap_ntb(struct gether *port, 9539f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta struct sk_buff *skb, 9549f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta struct sk_buff_head *list) 9559f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta{ 9569f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta struct f_ncm *ncm = func_to_ncm(&port->func); 9579f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta __le16 *tmp = (void *) skb->data; 9589f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta unsigned index, index2; 9599f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta unsigned dg_len, dg_len2; 9609f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta unsigned ndp_len; 9619f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta struct sk_buff *skb2; 9629f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta int ret = -EINVAL; 9639f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta unsigned max_size = le32_to_cpu(ntb_parameters.dwNtbOutMaxSize); 9649f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta struct ndp_parser_opts *opts = ncm->parser_opts; 9659f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta unsigned crc_len = ncm->is_crc ? sizeof(uint32_t) : 0; 9669f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta int dgram_counter; 9679f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 9689f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* dwSignature */ 9699f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (get_unaligned_le32(tmp) != opts->nth_sign) { 9709f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta INFO(port->func.config->cdev, "Wrong NTH SIGN, skblen %d\n", 9719f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta skb->len); 9729f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta print_hex_dump(KERN_INFO, "HEAD:", DUMP_PREFIX_ADDRESS, 32, 1, 9739f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta skb->data, 32, false); 9749f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 9759f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta goto err; 9769f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } 9779f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta tmp += 2; 9789f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* wHeaderLength */ 9799f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (get_unaligned_le16(tmp++) != opts->nth_size) { 9809f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta INFO(port->func.config->cdev, "Wrong NTB headersize\n"); 9819f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta goto err; 9829f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } 9839f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta tmp++; /* skip wSequence */ 9849f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 9859f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* (d)wBlockLength */ 9869f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (get_ncm(&tmp, opts->block_length) > max_size) { 9879f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta INFO(port->func.config->cdev, "OUT size exceeded\n"); 9889f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta goto err; 9899f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } 9909f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 9919f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta index = get_ncm(&tmp, opts->fp_index); 9929f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* NCM 3.2 */ 9939f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (((index % 4) != 0) && (index < opts->nth_size)) { 9949f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta INFO(port->func.config->cdev, "Bad index: %x\n", 9959f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta index); 9969f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta goto err; 9979f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } 9989f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 9999f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* walk through NDP */ 10009f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta tmp = ((void *)skb->data) + index; 10019f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (get_unaligned_le32(tmp) != opts->ndp_sign) { 10029f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta INFO(port->func.config->cdev, "Wrong NDP SIGN\n"); 10039f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta goto err; 10049f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } 10059f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta tmp += 2; 10069f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 10079f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ndp_len = get_unaligned_le16(tmp++); 10089f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* 10099f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * NCM 3.3.1 10109f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * entry is 2 items 10119f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * item size is 16/32 bits, opts->dgram_item_len * 2 bytes 10129f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * minimal: struct usb_cdc_ncm_ndpX + normal entry + zero entry 10139f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta */ 10149f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if ((ndp_len < opts->ndp_size + 2 * 2 * (opts->dgram_item_len * 2)) 10159f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta || (ndp_len % opts->ndplen_align != 0)) { 10169f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta INFO(port->func.config->cdev, "Bad NDP length: %x\n", ndp_len); 10179f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta goto err; 10189f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } 10199f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta tmp += opts->reserved1; 10209f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta tmp += opts->next_fp_index; /* skip reserved (d)wNextFpIndex */ 10219f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta tmp += opts->reserved2; 10229f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 10239f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ndp_len -= opts->ndp_size; 10249f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta index2 = get_ncm(&tmp, opts->dgram_item_len); 10259f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta dg_len2 = get_ncm(&tmp, opts->dgram_item_len); 10269f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta dgram_counter = 0; 10279f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 10289f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta do { 10299f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta index = index2; 10309f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta dg_len = dg_len2; 10319f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (dg_len < 14 + crc_len) { /* ethernet header + crc */ 10329f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta INFO(port->func.config->cdev, "Bad dgram length: %x\n", 10339f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta dg_len); 10349f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta goto err; 10359f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } 10369f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (ncm->is_crc) { 10379f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta uint32_t crc, crc2; 10389f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 10399f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta crc = get_unaligned_le32(skb->data + 10409f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta index + dg_len - crc_len); 10419f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta crc2 = ~crc32_le(~0, 10429f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta skb->data + index, 10439f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta dg_len - crc_len); 10449f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (crc != crc2) { 10459f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta INFO(port->func.config->cdev, "Bad CRC\n"); 10469f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta goto err; 10479f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } 10489f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } 10499f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 10509f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta index2 = get_ncm(&tmp, opts->dgram_item_len); 10519f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta dg_len2 = get_ncm(&tmp, opts->dgram_item_len); 10529f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 10539f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (index2 == 0 || dg_len2 == 0) { 10549f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta skb2 = skb; 10559f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } else { 10569f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta skb2 = skb_clone(skb, GFP_ATOMIC); 10579f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (skb2 == NULL) 10589f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta goto err; 10599f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } 10609f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 10619f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (!skb_pull(skb2, index)) { 10629f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ret = -EOVERFLOW; 10639f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta goto err; 10649f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } 10659f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 10669f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta skb_trim(skb2, dg_len - crc_len); 10679f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta skb_queue_tail(list, skb2); 10689f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 10699f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ndp_len -= 2 * (opts->dgram_item_len * 2); 10709f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 10719f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta dgram_counter++; 10729f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 10739f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (index2 == 0 || dg_len2 == 0) 10749f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta break; 10759f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } while (ndp_len > 2 * (opts->dgram_item_len * 2)); /* zero entry */ 10769f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 10779f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta VDBG(port->func.config->cdev, 10789f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta "Parsed NTB with %d frames\n", dgram_counter); 10799f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta return 0; 10809f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutaerr: 10819f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta skb_queue_purge(list); 10829f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta dev_kfree_skb_any(skb); 10839f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta return ret; 10849f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta} 10859f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 10869f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastatic void ncm_disable(struct usb_function *f) 10879f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta{ 10889f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta struct f_ncm *ncm = func_to_ncm(f); 10899f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta struct usb_composite_dev *cdev = f->config->cdev; 10909f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 10919f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta DBG(cdev, "ncm deactivated\n"); 10929f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 10939f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (ncm->port.in_ep->driver_data) 10949f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta gether_disconnect(&ncm->port); 10959f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 10969f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (ncm->notify->driver_data) { 10979f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta usb_ep_disable(ncm->notify); 10989f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->notify->driver_data = NULL; 109972c973dd2b01b212a159faa330a2bc641a3ed809Tatyana Brokhman ncm->notify->desc = NULL; 11009f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } 11019f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta} 11029f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 11039f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta/*-------------------------------------------------------------------------*/ 11049f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 11059f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta/* 11069f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * Callbacks let us notify the host about connect/disconnect when the 11079f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * net device is opened or closed. 11089f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * 11099f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * For testing, note that link states on this side include both opened 11109f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * and closed variants of: 11119f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * 11129f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * - disconnected/unconfigured 11139f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * - configured but inactive (data alt 0) 11149f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * - configured and active (data alt 1) 11159f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * 11169f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * Each needs to be tested with unplug, rmmod, SET_CONFIGURATION, and 11179f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * SET_INTERFACE (altsetting). Remember also that "configured" doesn't 11189f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * imply the host is actually polling the notification endpoint, and 11199f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * likewise that "active" doesn't imply it's actually using the data 11209f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * endpoints for traffic. 11219f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta */ 11229f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 11239f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastatic void ncm_open(struct gether *geth) 11249f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta{ 11259f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta struct f_ncm *ncm = func_to_ncm(&geth->func); 11269f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 11279f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta DBG(ncm->port.func.config->cdev, "%s\n", __func__); 11289f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 11299f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta spin_lock(&ncm->lock); 11309f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->is_open = true; 11319f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm_notify(ncm); 11329f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta spin_unlock(&ncm->lock); 11339f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta} 11349f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 11359f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastatic void ncm_close(struct gether *geth) 11369f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta{ 11379f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta struct f_ncm *ncm = func_to_ncm(&geth->func); 11389f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 11399f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta DBG(ncm->port.func.config->cdev, "%s\n", __func__); 11409f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 11419f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta spin_lock(&ncm->lock); 11429f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->is_open = false; 11439f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm_notify(ncm); 11449f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta spin_unlock(&ncm->lock); 11459f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta} 11469f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 11479f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta/*-------------------------------------------------------------------------*/ 11489f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 11499f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta/* ethernet function driver setup/binding */ 11509f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 11519f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastatic int __init 11529f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutancm_bind(struct usb_configuration *c, struct usb_function *f) 11539f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta{ 11549f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta struct usb_composite_dev *cdev = c->cdev; 11559f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta struct f_ncm *ncm = func_to_ncm(f); 11569f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta int status; 11579f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta struct usb_ep *ep; 11589f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 11599f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* allocate instance-specific interface IDs */ 11609f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta status = usb_interface_id(c, f); 11619f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (status < 0) 11629f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta goto fail; 11639f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->ctrl_id = status; 11649f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm_iad_desc.bFirstInterface = status; 11659f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 11669f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm_control_intf.bInterfaceNumber = status; 11679f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm_union_desc.bMasterInterface0 = status; 11689f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 11699f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta status = usb_interface_id(c, f); 11709f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (status < 0) 11719f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta goto fail; 11729f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->data_id = status; 11739f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 11749f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm_data_nop_intf.bInterfaceNumber = status; 11759f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm_data_intf.bInterfaceNumber = status; 11769f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm_union_desc.bSlaveInterface0 = status; 11779f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 11789f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta status = -ENODEV; 11799f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 11809f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* allocate instance-specific endpoints */ 11819f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ep = usb_ep_autoconfig(cdev->gadget, &fs_ncm_in_desc); 11829f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (!ep) 11839f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta goto fail; 11849f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->port.in_ep = ep; 11859f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ep->driver_data = cdev; /* claim */ 11869f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 11879f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ep = usb_ep_autoconfig(cdev->gadget, &fs_ncm_out_desc); 11889f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (!ep) 11899f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta goto fail; 11909f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->port.out_ep = ep; 11919f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ep->driver_data = cdev; /* claim */ 11929f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 11939f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ep = usb_ep_autoconfig(cdev->gadget, &fs_ncm_notify_desc); 11949f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (!ep) 11959f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta goto fail; 11969f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->notify = ep; 11979f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ep->driver_data = cdev; /* claim */ 11989f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 11999f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta status = -ENOMEM; 12009f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 12019f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* allocate notification request and buffer */ 12029f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->notify_req = usb_ep_alloc_request(ep, GFP_KERNEL); 12039f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (!ncm->notify_req) 12049f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta goto fail; 12059f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->notify_req->buf = kmalloc(NCM_STATUS_BYTECOUNT, GFP_KERNEL); 12069f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (!ncm->notify_req->buf) 12079f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta goto fail; 12089f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->notify_req->context = ncm; 12099f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->notify_req->complete = ncm_notify_complete; 12109f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 12119f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* copy descriptors, and track endpoint copies */ 12129f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta f->descriptors = usb_copy_descriptors(ncm_fs_function); 12139f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (!f->descriptors) 12149f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta goto fail; 12159f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 12169f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* 12179f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * support all relevant hardware speeds... we expect that when 12189f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * hardware is dual speed, all bulk-capable endpoints work at 12199f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * both speeds 12209f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta */ 12219f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (gadget_is_dualspeed(c->cdev->gadget)) { 12229f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta hs_ncm_in_desc.bEndpointAddress = 12239f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta fs_ncm_in_desc.bEndpointAddress; 12249f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta hs_ncm_out_desc.bEndpointAddress = 12259f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta fs_ncm_out_desc.bEndpointAddress; 12269f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta hs_ncm_notify_desc.bEndpointAddress = 12279f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta fs_ncm_notify_desc.bEndpointAddress; 12289f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 12299f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* copy descriptors, and track endpoint copies */ 12309f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta f->hs_descriptors = usb_copy_descriptors(ncm_hs_function); 12319f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (!f->hs_descriptors) 12329f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta goto fail; 12339f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } 12349f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 12359f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* 12369f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * NOTE: all that is done without knowing or caring about 12379f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * the network link ... which is unavailable to this code 12389f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * until we're activated via set_alt(). 12399f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta */ 12409f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 12419f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->port.open = ncm_open; 12429f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->port.close = ncm_close; 12439f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 12449f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta DBG(cdev, "CDC Network: %s speed IN/%s OUT/%s NOTIFY/%s\n", 12459f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", 12469f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->port.in_ep->name, ncm->port.out_ep->name, 12479f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->notify->name); 12489f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta return 0; 12499f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 12509f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutafail: 12519f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (f->descriptors) 12529f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta usb_free_descriptors(f->descriptors); 12539f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 12549f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (ncm->notify_req) { 12559f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta kfree(ncm->notify_req->buf); 12569f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta usb_ep_free_request(ncm->notify, ncm->notify_req); 12579f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } 12589f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 12599f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* we might as well release our claims on endpoints */ 12609f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (ncm->notify) 12619f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->notify->driver_data = NULL; 126272c973dd2b01b212a159faa330a2bc641a3ed809Tatyana Brokhman if (ncm->port.out_ep->desc) 12639f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->port.out_ep->driver_data = NULL; 126472c973dd2b01b212a159faa330a2bc641a3ed809Tatyana Brokhman if (ncm->port.in_ep->desc) 12659f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->port.in_ep->driver_data = NULL; 12669f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 12679f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ERROR(cdev, "%s: can't bind, err %d\n", f->name, status); 12689f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 12699f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta return status; 12709f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta} 12719f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 12729f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutastatic void 12739f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutancm_unbind(struct usb_configuration *c, struct usb_function *f) 12749f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta{ 12759f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta struct f_ncm *ncm = func_to_ncm(f); 12769f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 12779f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta DBG(c->cdev, "ncm unbind\n"); 12789f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 12799f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (gadget_is_dualspeed(c->cdev->gadget)) 12809f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta usb_free_descriptors(f->hs_descriptors); 12819f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta usb_free_descriptors(f->descriptors); 12829f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 12839f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta kfree(ncm->notify_req->buf); 12849f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta usb_ep_free_request(ncm->notify, ncm->notify_req); 12859f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 12869f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm_string_defs[1].s = NULL; 12879f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta kfree(ncm); 12889f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta} 12899f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 12909f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta/** 12919f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * ncm_bind_config - add CDC Network link to a configuration 12929f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * @c: the configuration to support the network link 12939f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * @ethaddr: a buffer in which the ethernet address of the host side 12949f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * side of the link was recorded 12959f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * Context: single threaded during gadget setup 12969f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * 12979f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * Returns zero on success, else negative errno. 12989f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * 12999f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * Caller must have called @gether_setup(). Caller is also responsible 13009f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta * for calling @gether_cleanup() before module unload. 13019f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta */ 13029f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliutaint __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]) 13039f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta{ 13049f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta struct f_ncm *ncm; 13059f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta int status; 13069f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 13079f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (!can_support_ecm(c->cdev->gadget) || !ethaddr) 13089f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta return -EINVAL; 13099f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 13109f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* maybe allocate device-global string IDs */ 13119f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (ncm_string_defs[0].id == 0) { 13129f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 13139f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* control interface label */ 13149f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta status = usb_string_id(c->cdev); 13159f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (status < 0) 13169f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta return status; 13179f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm_string_defs[STRING_CTRL_IDX].id = status; 13189f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm_control_intf.iInterface = status; 13199f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 13209f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* data interface label */ 13219f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta status = usb_string_id(c->cdev); 13229f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (status < 0) 13239f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta return status; 13249f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm_string_defs[STRING_DATA_IDX].id = status; 13259f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm_data_nop_intf.iInterface = status; 13269f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm_data_intf.iInterface = status; 13279f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 13289f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* MAC address */ 13299f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta status = usb_string_id(c->cdev); 13309f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (status < 0) 13319f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta return status; 13329f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm_string_defs[STRING_MAC_IDX].id = status; 13339f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ecm_desc.iMACAddress = status; 13349f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 13359f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* IAD */ 13369f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta status = usb_string_id(c->cdev); 13379f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (status < 0) 13389f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta return status; 13399f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm_string_defs[STRING_IAD_IDX].id = status; 13409f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm_iad_desc.iFunction = status; 13419f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } 13429f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 13439f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* allocate and initialize one new instance */ 13449f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm = kzalloc(sizeof *ncm, GFP_KERNEL); 13459f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (!ncm) 13469f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta return -ENOMEM; 13479f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 13489f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* export host's Ethernet address in CDC format */ 13499f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta snprintf(ncm->ethaddr, sizeof ncm->ethaddr, 13509f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta "%02X%02X%02X%02X%02X%02X", 13519f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ethaddr[0], ethaddr[1], ethaddr[2], 13529f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ethaddr[3], ethaddr[4], ethaddr[5]); 13539f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm_string_defs[1].s = ncm->ethaddr; 13549f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 13559f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta spin_lock_init(&ncm->lock); 13569f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm_reset_values(ncm); 13579f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->port.is_fixed = true; 13589f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 13599f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->port.func.name = "cdc_network"; 13609f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->port.func.strings = ncm_strings; 13619f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta /* descriptors are per-instance copies */ 13629f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->port.func.bind = ncm_bind; 13639f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->port.func.unbind = ncm_unbind; 13649f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->port.func.set_alt = ncm_set_alt; 13659f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->port.func.get_alt = ncm_get_alt; 13669f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->port.func.setup = ncm_setup; 13679f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->port.func.disable = ncm_disable; 13689f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 13699f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->port.wrap = ncm_wrap_ntb; 13709f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm->port.unwrap = ncm_unwrap_ntb; 13719f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta 13729f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta status = usb_add_function(c, &ncm->port.func); 13739f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta if (status) { 13749f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta ncm_string_defs[1].s = NULL; 13759f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta kfree(ncm); 13769f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta } 13779f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta return status; 13789f6ce4240a2bf456402c15c06768059e5973f28cYauheni Kaliuta} 1379