// 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 "Oliver Neukum"#define DRIVER_DESC "USB Abstract Control Model driver for USB WCM Device Management"staticconststructusb_device_idwdm_ids[]={{.match_flags=USB_DEVICE_ID_MATCH_INT_CLASS|USB_DEVICE_ID_MATCH_INT_SUBCLASS,.bInterfaceClass=USB_CLASS_COMM,.bInterfaceSubClass=USB_CDC_SUBCLASS_DMM},{}};MODULE_DEVICE_TABLE(usb,wdm_ids);#define WDM_MINOR_BASE 176#define WDM_IN_USE 1#define WDM_DISCONNECTING 2#define WDM_RESULT 3#define WDM_READ 4#define WDM_INT_STALL 5#define WDM_POLL_RUNNING 6#define WDM_RESPONDING 7#define WDM_SUSPENDING 8#define WDM_RESETTING 9#define WDM_OVERFLOW 10#define WDM_WWAN_IN_USE 11#define WDM_MAX 16/* we cannot wait forever at flush() */#define WDM_FLUSH_TIMEOUT (30 * HZ)/* CDC-WMC r1.1 requires wMaxCommand to be "at least 256 decimal (0x100)" */#define WDM_DEFAULT_BUFSIZE 256staticDEFINE_MUTEX(wdm_mutex);staticDEFINE_SPINLOCK(wdm_device_list_lock);staticLIST_HEAD(wdm_device_list);/* --- method tables --- */structwdm_device{u8*inbuf;/* buffer for response */u8*outbuf;/* buffer for command */u8*sbuf;/* buffer for status */u8*ubuf;/* buffer for copy to user space */structurb*command;structurb*response;structurb*validity;structusb_interface*intf;structusb_ctrlrequest*orq;structusb_ctrlrequest*irq;spinlock_tiuspin;unsignedlongflags;u16bufsize;u16wMaxCommand;u16wMaxPacketSize;__le16inum;intreslength;intlength;intread;intcount;dma_addr_tshandle;dma_addr_tihandle;structmutexwlock;structmutexrlock;wait_queue_head_twait;structwork_structrxwork;structwork_structservice_outs_intr;intwerr;intrerr;intresp_count;structlist_headdevice_list;int(*manage_power)(struct