linux/drivers/usb/core/devio.c

// SPDX-License-Identifier: GPL-2.0+
/*****************************************************************************/

/*
 *      devio.c  --  User space communication with USB devices.
 *
 *      Copyright (C) 1999-2000  Thomas Sailer ([email protected])
 *
 *  This file implements the usbfs/x/y files, where
 *  x is the bus number and y the device number.
 *
 *  It allows user space programs/"drivers" to communicate directly
 *  with USB devices without intervening kernel driver.
 *
 *  Revision history
 *    22.12.1999   0.1   Initial release (split from proc_usb.c)
 *    04.01.2000   0.2   Turned into its own filesystem
 *    30.09.2005   0.3   Fix user-triggerable oops in async URB delivery
 *    			 (CAN-2005-3055)
 */

/*****************************************************************************/

#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/sched/signal.h>
#include <linux/slab.h>
#include <linux/signal.h>
#include <linux/poll.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/usb.h>
#include <linux/usbdevice_fs.h>
#include <linux/usb/hcd.h>	/* for usbcore internals */
#include <linux/usb/quirks.h>
#include <linux/cdev.h>
#include <linux/notifier.h>
#include <linux/security.h>
#include <linux/user_namespace.h>
#include <linux/scatterlist.h>
#include <linux/uaccess.h>
#include <linux/dma-mapping.h>
#include <asm/byteorder.h>
#include <linux/moduleparam.h>

#include "usb.h"

#ifdef CONFIG_PM
#define MAYBE_CAP_SUSPEND
#else
#define MAYBE_CAP_SUSPEND
#endif

#define USB_MAXBUS
#define USB_DEVICE_MAX
#define USB_SG_SIZE

/* Mutual exclusion for ps->list in resume vs. release and remove */
static DEFINE_MUTEX(usbfs_mutex);

struct usb_dev_state {};

struct usb_memory {};

struct async {};

static bool usbfs_snoop;
module_param(usbfs_snoop, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC();

static unsigned usbfs_snoop_max =;
module_param(usbfs_snoop_max, uint, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC();

#define snoop(dev, format, arg...)

enum snoop_when {};

#define USB_DEVICE_DEV

/* Limit on the total amount of memory we can allocate for transfers */
static u32 usbfs_memory_mb =;
module_param(usbfs_memory_mb, uint, 0644);
MODULE_PARM_DESC();

/* Hard limit, necessary to avoid arithmetic overflow */
#define USBFS_XFER_MAX

static DEFINE_SPINLOCK(usbfs_memory_usage_lock);
static u64 usbfs_memory_usage;	/* Total memory currently allocated */

/* Check whether it's okay to allocate more memory for a transfer */
static int usbfs_increase_memory_usage(u64 amount)
{}

/* Memory for a transfer is being deallocated */
static void usbfs_decrease_memory_usage(u64 amount)
{}

static int connected(struct usb_dev_state *ps)
{}

static void dec_usb_memory_use_count(struct usb_memory *usbm, int *count)
{}

static void usbdev_vm_open(struct vm_area_struct *vma)
{}

static void usbdev_vm_close(struct vm_area_struct *vma)
{}

static const struct vm_operations_struct usbdev_vm_ops =;

static int usbdev_mmap(struct file *file, struct vm_area_struct *vma)
{}

static ssize_t usbdev_read(struct file *file, char __user *buf, size_t nbytes,
			   loff_t *ppos)
{}

/*
 * async list handling
 */

static struct async *alloc_async(unsigned int numisoframes)
{}

static void free_async(struct async *as)
{}

static void async_newpending(struct async *as)
{}

static void async_removepending(struct async *as)
{}

static struct async *async_getcompleted(struct usb_dev_state *ps)
{}

static struct async *async_getpending(struct usb_dev_state *ps,
					     void __user *userurb)
{}

static void snoop_urb(struct usb_device *udev,
		void __user *userurb, int pipe, unsigned length,
		int timeout_or_status, enum snoop_when when,
		unsigned char *data, unsigned data_len)
{}

static void snoop_urb_data(struct urb *urb, unsigned len)
{}

static int copy_urb_data_to_user(u8 __user *userbuffer, struct urb *urb)
{}

#define AS_CONTINUATION
#define AS_UNLINK

static void cancel_bulk_urbs(struct usb_dev_state *ps, unsigned bulk_addr)
__releases(ps->lock)
__acquires(ps->lock)
{}

static void async_completed(struct urb *urb)
{}

static void destroy_async(struct usb_dev_state *ps, struct list_head *list)
{}

static void destroy_async_on_interface(struct usb_dev_state *ps,
				       unsigned int ifnum)
{}

static void destroy_all_async(struct usb_dev_state *ps)
{}

/*
 * interface claims are made only at the request of user level code,
 * which can also release them (explicitly or by closing files).
 * they're also undone when devices disconnect.
 */

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

static void driver_disconnect(struct usb_interface *intf)
{}

/* We don't care about suspend/resume of claimed interfaces */
static int driver_suspend(struct usb_interface *intf, pm_message_t msg)
{}

static int driver_resume(struct usb_interface *intf)
{}

#ifdef CONFIG_PM
/* The following routines apply to the entire device, not interfaces */
void usbfs_notify_suspend(struct usb_device *udev)
{}

void usbfs_notify_resume(struct usb_device *udev)
{}
#endif

struct usb_driver usbfs_driver =;

static int claimintf(struct usb_dev_state *ps, unsigned int ifnum)
{}

static int releaseintf(struct usb_dev_state *ps, unsigned int ifnum)
{}

static int checkintf(struct usb_dev_state *ps, unsigned int ifnum)
{}

static int findintfep(struct usb_device *dev, unsigned int ep)
{}

static int check_ctrlrecip(struct usb_dev_state *ps, unsigned int requesttype,
			   unsigned int request, unsigned int index)
{}

static struct usb_host_endpoint *ep_to_host_endpoint(struct usb_device *dev,
						     unsigned char ep)
{}

static int parse_usbdevfs_streams(struct usb_dev_state *ps,
				  struct usbdevfs_streams __user *streams,
				  unsigned int *num_streams_ret,
				  unsigned int *num_eps_ret,
				  struct usb_host_endpoint ***eps_ret,
				  struct usb_interface **intf_ret)
{}

static struct usb_device *usbdev_lookup_by_devt(dev_t devt)
{}

/*
 * file operations
 */
static int usbdev_open(struct inode *inode, struct file *file)
{}

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

static void usbfs_blocking_completion(struct urb *urb)
{}

/*
 * Much like usb_start_wait_urb, but returns status separately from
 * actual_length and uses a killable wait.
 */
static int usbfs_start_wait_urb(struct urb *urb, int timeout,
		unsigned int *actlen)
{}

static int do_proc_control(struct usb_dev_state *ps,
		struct usbdevfs_ctrltransfer *ctrl)
{}

static int proc_control(struct usb_dev_state *ps, void __user *arg)
{}

static int do_proc_bulk(struct usb_dev_state *ps,
		struct usbdevfs_bulktransfer *bulk)
{}

static int proc_bulk(struct usb_dev_state *ps, void __user *arg)
{}

static void check_reset_of_active_ep(struct usb_device *udev,
		unsigned int epnum, char *ioctl_name)
{}

static int proc_resetep(struct usb_dev_state *ps, void __user *arg)
{}

static int proc_clearhalt(struct usb_dev_state *ps, void __user *arg)
{}

static int proc_getdriver(struct usb_dev_state *ps, void __user *arg)
{}

static int proc_connectinfo(struct usb_dev_state *ps, void __user *arg)
{}

static int proc_conninfo_ex(struct usb_dev_state *ps,
			    void __user *arg, size_t size)
{}

static int proc_resetdevice(struct usb_dev_state *ps)
{}

static int proc_setintf(struct usb_dev_state *ps, void __user *arg)
{}

static int proc_setconfig(struct usb_dev_state *ps, void __user *arg)
{}

static struct usb_memory *
find_memory_area(struct usb_dev_state *ps, const struct usbdevfs_urb *uurb)
{}

static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb,
			struct usbdevfs_iso_packet_desc __user *iso_frame_desc,
			void __user *arg, sigval_t userurb_sigval)
{}

static int proc_submiturb(struct usb_dev_state *ps, void __user *arg)
{}

static int proc_unlinkurb(struct usb_dev_state *ps, void __user *arg)
{}

static void compute_isochronous_actual_length(struct urb *urb)
{}

static int processcompl(struct async *as, void __user * __user *arg)
{}

static struct async *reap_as(struct usb_dev_state *ps)
{}

static int proc_reapurb(struct usb_dev_state *ps, void __user *arg)
{}

static int proc_reapurbnonblock(struct usb_dev_state *ps, void __user *arg)
{}

#ifdef CONFIG_COMPAT
static int proc_control_compat(struct usb_dev_state *ps,
				struct usbdevfs_ctrltransfer32 __user *p32)
{}

static int proc_bulk_compat(struct usb_dev_state *ps,
			struct usbdevfs_bulktransfer32 __user *p32)
{}

static int proc_disconnectsignal_compat(struct usb_dev_state *ps, void __user *arg)
{}

static int get_urb32(struct usbdevfs_urb *kurb,
		     struct usbdevfs_urb32 __user *uurb)
{}

static int proc_submiturb_compat(struct usb_dev_state *ps, void __user *arg)
{}

static int processcompl_compat(struct async *as, void __user * __user *arg)
{}

static int proc_reapurb_compat(struct usb_dev_state *ps, void __user *arg)
{}

static int proc_reapurbnonblock_compat(struct usb_dev_state *ps, void __user *arg)
{}


#endif

static int proc_disconnectsignal(struct usb_dev_state *ps, void __user *arg)
{}

static int proc_claiminterface(struct usb_dev_state *ps, void __user *arg)
{}

static int proc_releaseinterface(struct usb_dev_state *ps, void __user *arg)
{}

static int proc_ioctl(struct usb_dev_state *ps, struct usbdevfs_ioctl *ctl)
{}

static int proc_ioctl_default(struct usb_dev_state *ps, void __user *arg)
{}

#ifdef CONFIG_COMPAT
static int proc_ioctl_compat(struct usb_dev_state *ps, compat_uptr_t arg)
{}
#endif

static int proc_claim_port(struct usb_dev_state *ps, void __user *arg)
{}

static int proc_release_port(struct usb_dev_state *ps, void __user *arg)
{}

static int proc_get_capabilities(struct usb_dev_state *ps, void __user *arg)
{}

static int proc_disconnect_claim(struct usb_dev_state *ps, void __user *arg)
{}

static int proc_alloc_streams(struct usb_dev_state *ps, void __user *arg)
{}

static int proc_free_streams(struct usb_dev_state *ps, void __user *arg)
{}

static int proc_drop_privileges(struct usb_dev_state *ps, void __user *arg)
{}

static int proc_forbid_suspend(struct usb_dev_state *ps)
{}

static int proc_allow_suspend(struct usb_dev_state *ps)
{}

static int proc_wait_for_resume(struct usb_dev_state *ps)
{}

/*
 * NOTE:  All requests here that have interface numbers as parameters
 * are assuming that somehow the configuration has been prevented from
 * changing.  But there's no mechanism to ensure that...
 */
static long usbdev_do_ioctl(struct file *file, unsigned int cmd,
				void __user *p)
{}

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

/* No kernel lock - fine */
static __poll_t usbdev_poll(struct file *file,
				struct poll_table_struct *wait)
{}

const struct file_operations usbdev_file_operations =;

static void usbdev_remove(struct usb_device *udev)
{}

static int usbdev_notify(struct notifier_block *self,
			       unsigned long action, void *dev)
{}

static struct notifier_block usbdev_nb =;

static struct cdev usb_device_cdev;

int __init usb_devio_init(void)
{}

void usb_devio_cleanup(void)
{}