linux/drivers/usb/class/cdc-wdm.c

// SPDX-License-Identifier: GPL-2.0
/*
 * cdc-wdm.c
 *
 * This driver supports USB CDC WCM Device Management.
 *
 * Copyright (c) 2007-2009 Oliver Neukum
 *
 * Some code taken from cdc-acm.c
 *
 * Released under the GPLv2.
 *
 * Many thanks to Carl Nordbeck
 */
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/uaccess.h>
#include <linux/bitops.h>
#include <linux/poll.h>
#include <linux/skbuff.h>
#include <linux/usb.h>
#include <linux/usb/cdc.h>
#include <linux/wwan.h>
#include <asm/byteorder.h>
#include <asm/unaligned.h>
#include <linux/usb/cdc-wdm.h>

#define DRIVER_AUTHOR
#define DRIVER_DESC

static const struct usb_device_id wdm_ids[] =;

MODULE_DEVICE_TABLE (usb, wdm_ids);

#define WDM_MINOR_BASE


#define WDM_IN_USE
#define WDM_DISCONNECTING
#define WDM_RESULT
#define WDM_READ
#define WDM_INT_STALL
#define WDM_POLL_RUNNING
#define WDM_RESPONDING
#define WDM_SUSPENDING
#define WDM_RESETTING
#define WDM_OVERFLOW
#define WDM_WWAN_IN_USE

#define WDM_MAX

/* we cannot wait forever at flush() */
#define WDM_FLUSH_TIMEOUT

/* CDC-WMC r1.1 requires wMaxCommand to be "at least 256 decimal (0x100)" */
#define WDM_DEFAULT_BUFSIZE

static DEFINE_MUTEX(wdm_mutex);
static DEFINE_SPINLOCK(wdm_device_list_lock);
static LIST_HEAD(wdm_device_list);

/* --- method tables --- */

struct wdm_device {};

static struct usb_driver wdm_driver;

/* return intfdata if we own the interface, else look up intf in the list */
static struct wdm_device *wdm_find_device(struct usb_interface *intf)
{}

static struct wdm_device *wdm_find_device_by_minor(int minor)
{}

/* --- callbacks --- */
static void wdm_out_callback(struct urb *urb)
{}

static void wdm_wwan_rx(struct wdm_device *desc, int length);

static void wdm_in_callback(struct urb *urb)
{}

static void wdm_int_callback(struct urb *urb)
{}

static void poison_urbs(struct wdm_device *desc)
{}

static void unpoison_urbs(struct wdm_device *desc)
{}

static void free_urbs(struct wdm_device *desc)
{}

static void cleanup(struct wdm_device *desc)
{}

static ssize_t wdm_write
(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
{}

/*
 * Submit the read urb if resp_count is non-zero.
 *
 * Called with desc->iuspin locked
 */
static int service_outstanding_interrupt(struct wdm_device *desc)
{}

static ssize_t wdm_read
(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
{}

static int wdm_wait_for_response(struct file *file, long timeout)
{}

/*
 * You need to send a signal when you react to malicious or defective hardware.
 * Also, don't abort when fsync() returned -EINVAL, for older kernels which do
 * not implement wdm_flush() will return -EINVAL.
 */
static int wdm_fsync(struct file *file, loff_t start, loff_t end, int datasync)
{}

/*
 * Same with wdm_fsync(), except it uses finite timeout in order to react to
 * malicious or defective hardware which ceased communication after close() was
 * implicitly called due to process termination.
 */
static int wdm_flush(struct file *file, fl_owner_t id)
{}

static __poll_t wdm_poll(struct file *file, struct poll_table_struct *wait)
{}

static int wdm_open(struct inode *inode, struct file *file)
{}

static int wdm_release(struct inode *inode, struct file *file)
{}

static long wdm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{}

static const struct file_operations wdm_fops =;

static struct usb_class_driver wdm_class =;

/* --- WWAN framework integration --- */
#ifdef CONFIG_WWAN
static int wdm_wwan_port_start(struct wwan_port *port)
{}

static void wdm_wwan_port_stop(struct wwan_port *port)
{}

static void wdm_wwan_port_tx_complete(struct urb *urb)
{}

static int wdm_wwan_port_tx(struct wwan_port *port, struct sk_buff *skb)
{}

static const struct wwan_port_ops wdm_wwan_port_ops =;

static void wdm_wwan_init(struct wdm_device *desc)
{}

static void wdm_wwan_deinit(struct wdm_device *desc)
{}

static void wdm_wwan_rx(struct wdm_device *desc, int length)
{}
#else /* CONFIG_WWAN */
static void wdm_wwan_init(struct wdm_device *desc) {}
static void wdm_wwan_deinit(struct wdm_device *desc) {}
static void wdm_wwan_rx(struct wdm_device *desc, int length) {}
#endif /* CONFIG_WWAN */

/* --- error handling --- */
static void wdm_rxwork(struct work_struct *work)
{}

static void service_interrupt_work(struct work_struct *work)
{}

/* --- hotplug --- */

static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor *ep,
		      u16 bufsize, enum wwan_port_type type,
		      int (*manage_power)(struct usb_interface *, int))
{}

static int wdm_manage_power(struct usb_interface *intf, int on)
{}

static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id)
{}

/**
 * usb_cdc_wdm_register - register a WDM subdriver
 * @intf: usb interface the subdriver will associate with
 * @ep: interrupt endpoint to monitor for notifications
 * @bufsize: maximum message size to support for read/write
 * @type: Type/protocol of the transported data (MBIM, QMI...)
 * @manage_power: call-back invoked during open and release to
 *                manage the device's power
 * Create WDM usb class character device and associate it with intf
 * without binding, allowing another driver to manage the interface.
 *
 * The subdriver will manage the given interrupt endpoint exclusively
 * and will issue control requests referring to the given intf. It
 * will otherwise avoid interferring, and in particular not do
 * usb_set_intfdata/usb_get_intfdata on intf.
 *
 * The return value is a pointer to the subdriver's struct usb_driver.
 * The registering driver is responsible for calling this subdriver's
 * disconnect, suspend, resume, pre_reset and post_reset methods from
 * its own.
 */
struct usb_driver *usb_cdc_wdm_register(struct usb_interface *intf,
					struct usb_endpoint_descriptor *ep,
					int bufsize, enum wwan_port_type type,
					int (*manage_power)(struct usb_interface *, int))
{}
EXPORT_SYMBOL();

static void wdm_disconnect(struct usb_interface *intf)
{}

#ifdef CONFIG_PM
static int wdm_suspend(struct usb_interface *intf, pm_message_t message)
{}
#endif

static int recover_from_urb_loss(struct wdm_device *desc)
{}

#ifdef CONFIG_PM
static int wdm_resume(struct usb_interface *intf)
{}
#endif

static int wdm_pre_reset(struct usb_interface *intf)
{}

static int wdm_post_reset(struct usb_interface *intf)
{}

static struct usb_driver wdm_driver =;

module_usb_driver();

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();