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