linux/drivers/usb/gadget/function/f_ncm.c

// SPDX-License-Identifier: GPL-2.0+
/*
 * f_ncm.c -- USB CDC Network (NCM) link function driver
 *
 * Copyright (C) 2010 Nokia Corporation
 * Contact: Yauheni Kaliuta <[email protected]>
 *
 * The driver borrows from f_ecm.c which is:
 *
 * Copyright (C) 2003-2005,2008 David Brownell
 * Copyright (C) 2008 Nokia Corporation
 */

#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/etherdevice.h>
#include <linux/crc32.h>

#include <linux/usb/cdc.h>

#include "u_ether.h"
#include "u_ether_configfs.h"
#include "u_ncm.h"
#include "configfs.h"

/*
 * This function is a "CDC Network Control Model" (CDC NCM) Ethernet link.
 * NCM is intended to be used with high-speed network attachments.
 *
 * Note that NCM requires the use of "alternate settings" for its data
 * interface.  This means that the set_alt() method has real work to do,
 * and also means that a get_alt() method is required.
 */

/* to trigger crc/non-crc ndp signature */

#define NCM_NDP_HDR_CRC

enum ncm_notify_state {};

struct f_ncm {};

static inline struct f_ncm *func_to_ncm(struct usb_function *f)
{}

/*-------------------------------------------------------------------------*/

/*
 * We cannot group frames so use just the minimal size which ok to put
 * one max-size ethernet frame.
 * If the host can group frames, allow it to do that, 16K is selected,
 * because it's used by default by the current linux host driver
 */
#define NTB_DEFAULT_IN_SIZE
#define NTB_OUT_SIZE

/* Allocation for storing the NDP, 32 should suffice for a
 * 16k packet. This allows a maximum of 32 * 507 Byte packets to
 * be transmitted in a single 16kB skb, though when sending full size
 * packets this limit will be plenty.
 * Smaller packets are not likely to be trying to maximize the
 * throughput and will be mstly sending smaller infrequent frames.
 */
#define TX_MAX_NUM_DPE

/* Delay for the transmit to wait before sending an unfilled NTB frame. */
#define TX_TIMEOUT_NSECS

/*
 * Although max mtu as dictated by u_ether is 15412 bytes, setting
 * max_segment_size to 15426 would not be efficient. If user chooses segment
 * size to be (>= 8192), then we can't aggregate more than one buffer in each
 * NTB (assuming each packet coming from network layer is >= 8192 bytes) as ep
 * maxpacket limit is 16384. So let max_segment_size be limited to 8000 to allow
 * at least 2 packets to be aggregated reducing wastage of NTB buffer space
 */
#define MAX_DATAGRAM_SIZE

#define FORMATS_SUPPORTED

static struct usb_cdc_ncm_ntb_parameters ntb_parameters =;

/*
 * Use wMaxPacketSize big enough to fit CDC_NOTIFY_SPEED_CHANGE in one
 * packet, to simplify cancellation; and a big transfer interval, to
 * waste less bandwidth.
 */

#define NCM_STATUS_INTERVAL_MS
#define NCM_STATUS_BYTECOUNT

static struct usb_interface_assoc_descriptor ncm_iad_desc =;

/* interface descriptor: */

static struct usb_interface_descriptor ncm_control_intf =;

static struct usb_cdc_header_desc ncm_header_desc =;

static struct usb_cdc_union_desc ncm_union_desc =;

static struct usb_cdc_ether_desc ecm_desc =;

#define NCAPS

static struct usb_cdc_ncm_desc ncm_desc =;

/* the default data interface has no endpoints ... */

static struct usb_interface_descriptor ncm_data_nop_intf =;

/* ... but the "real" data interface has two bulk endpoints */

static struct usb_interface_descriptor ncm_data_intf =;

/* full speed support: */

static struct usb_endpoint_descriptor fs_ncm_notify_desc =;

static struct usb_endpoint_descriptor fs_ncm_in_desc =;

static struct usb_endpoint_descriptor fs_ncm_out_desc =;

static struct usb_descriptor_header *ncm_fs_function[] =;

/* high speed support: */

static struct usb_endpoint_descriptor hs_ncm_notify_desc =;
static struct usb_endpoint_descriptor hs_ncm_in_desc =;

static struct usb_endpoint_descriptor hs_ncm_out_desc =;

static struct usb_descriptor_header *ncm_hs_function[] =;


/* super speed support: */

static struct usb_endpoint_descriptor ss_ncm_notify_desc =;

static struct usb_ss_ep_comp_descriptor ss_ncm_notify_comp_desc =;

static struct usb_endpoint_descriptor ss_ncm_in_desc =;

static struct usb_endpoint_descriptor ss_ncm_out_desc =;

static struct usb_ss_ep_comp_descriptor ss_ncm_bulk_comp_desc =;

static struct usb_descriptor_header *ncm_ss_function[] =;

/* string descriptors: */

#define STRING_CTRL_IDX
#define STRING_MAC_IDX
#define STRING_DATA_IDX
#define STRING_IAD_IDX

static struct usb_string ncm_string_defs[] =;

static struct usb_gadget_strings ncm_string_table =;

static struct usb_gadget_strings *ncm_strings[] =;

/*
 * Here are options for NCM Datagram Pointer table (NDP) parser.
 * There are 2 different formats: NDP16 and NDP32 in the spec (ch. 3),
 * in NDP16 offsets and sizes fields are 1 16bit word wide,
 * in NDP32 -- 2 16bit words wide. Also signatures are different.
 * To make the parser code the same, put the differences in the structure,
 * and switch pointers to the structures when the format is changed.
 */

struct ndp_parser_opts {};

static const struct ndp_parser_opts ndp16_opts =;

static const struct ndp_parser_opts ndp32_opts =;

static inline void put_ncm(__le16 **p, unsigned size, unsigned val)
{}

static inline unsigned get_ncm(__le16 **p, unsigned size)
{}

/*-------------------------------------------------------------------------*/

static inline void ncm_reset_values(struct f_ncm *ncm)
{}

/*
 * Context: ncm->lock held
 */
static void ncm_do_notify(struct f_ncm *ncm)
{}

/*
 * Context: ncm->lock held
 */
static void ncm_notify(struct f_ncm *ncm)
{}

static void ncm_notify_complete(struct usb_ep *ep, struct usb_request *req)
{}

static void ncm_ep0out_complete(struct usb_ep *ep, struct usb_request *req)
{}

static int ncm_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
{}


static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
{}

/*
 * Because the data interface supports multiple altsettings,
 * this NCM function *MUST* implement a get_alt() method.
 */
static int ncm_get_alt(struct usb_function *f, unsigned intf)
{}

static struct sk_buff *package_for_tx(struct f_ncm *ncm)
{}

static struct sk_buff *ncm_wrap_ntb(struct gether *port,
				    struct sk_buff *skb)
{}

/*
 * The transmit should only be run if no skb data has been sent
 * for a certain duration.
 */
static enum hrtimer_restart ncm_tx_timeout(struct hrtimer *data)
{}

static int ncm_unwrap_ntb(struct gether *port,
			  struct sk_buff *skb,
			  struct sk_buff_head *list)
{}

static void ncm_disable(struct usb_function *f)
{}

/*-------------------------------------------------------------------------*/

/*
 * Callbacks let us notify the host about connect/disconnect when the
 * net device is opened or closed.
 *
 * For testing, note that link states on this side include both opened
 * and closed variants of:
 *
 *   - disconnected/unconfigured
 *   - configured but inactive (data alt 0)
 *   - configured and active (data alt 1)
 *
 * Each needs to be tested with unplug, rmmod, SET_CONFIGURATION, and
 * SET_INTERFACE (altsetting).  Remember also that "configured" doesn't
 * imply the host is actually polling the notification endpoint, and
 * likewise that "active" doesn't imply it's actually using the data
 * endpoints for traffic.
 */

static void ncm_open(struct gether *geth)
{}

static void ncm_close(struct gether *geth)
{}

/*-------------------------------------------------------------------------*/

/* ethernet function driver setup/binding */

static int ncm_bind(struct usb_configuration *c, struct usb_function *f)
{}

static inline struct f_ncm_opts *to_f_ncm_opts(struct config_item *item)
{}

/* f_ncm_item_ops */
USB_ETHERNET_CONFIGFS_ITEM();

/* f_ncm_opts_dev_addr */
USB_ETHERNET_CONFIGFS_ITEM_ATTR_DEV_ADDR();

/* f_ncm_opts_host_addr */
USB_ETHERNET_CONFIGFS_ITEM_ATTR_HOST_ADDR();

/* f_ncm_opts_qmult */
USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT();

/* f_ncm_opts_ifname */
USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME();

static ssize_t ncm_opts_max_segment_size_show(struct config_item *item,
					      char *page)
{}

static ssize_t ncm_opts_max_segment_size_store(struct config_item *item,
					       const char *page, size_t len)
{}

CONFIGFS_ATTR();

static struct configfs_attribute *ncm_attrs[] =;

static const struct config_item_type ncm_func_type =;

static void ncm_free_inst(struct usb_function_instance *f)
{}

static struct usb_function_instance *ncm_alloc_inst(void)
{}

static void ncm_free(struct usb_function *f)
{}

static void ncm_unbind(struct usb_configuration *c, struct usb_function *f)
{}

static struct usb_function *ncm_alloc(struct usb_function_instance *fi)
{}

DECLARE_USB_FUNCTION_INIT(ncm, ncm_alloc_inst, ncm_alloc);
MODULE_DESCRIPTION();
MODULE_LICENSE();
MODULE_AUTHOR();