#include <linux/compiler.h>
#include <linux/ctype.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/idr.h>
#include <linux/kref.h>
#include <linux/miscdevice.h>
#include <linux/module.h>
#include <linux/semaphore.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/wait.h>
#include <linux/usb.h>
#include <linux/usb/ch9.h>
#include <linux/usb/ch11.h>
#include <linux/usb/gadget.h>
#include <linux/usb/composite.h>
#include <uapi/linux/usb/raw_gadget.h>
#define DRIVER_DESC …
#define DRIVER_NAME …
MODULE_DESCRIPTION(…);
MODULE_AUTHOR(…) …;
MODULE_LICENSE(…) …;
static DEFINE_IDA(driver_id_numbers);
#define DRIVER_DRIVER_NAME_LENGTH_MAX …
#define RAW_EVENT_QUEUE_SIZE …
struct raw_event_queue { … };
static void raw_event_queue_init(struct raw_event_queue *queue)
{ … }
static int raw_event_queue_add(struct raw_event_queue *queue,
enum usb_raw_event_type type, size_t length, const void *data)
{ … }
static struct usb_raw_event *raw_event_queue_fetch(
struct raw_event_queue *queue)
{ … }
static void raw_event_queue_destroy(struct raw_event_queue *queue)
{ … }
struct raw_dev;
enum ep_state { … };
struct raw_ep { … };
enum dev_state { … };
struct raw_dev { … };
static struct raw_dev *dev_new(void)
{ … }
static void dev_free(struct kref *kref)
{ … }
static int raw_queue_event(struct raw_dev *dev,
enum usb_raw_event_type type, size_t length, const void *data)
{ … }
static void gadget_ep0_complete(struct usb_ep *ep, struct usb_request *req)
{ … }
static u8 get_ep_addr(const char *name)
{ … }
static int gadget_bind(struct usb_gadget *gadget,
struct usb_gadget_driver *driver)
{ … }
static void gadget_unbind(struct usb_gadget *gadget)
{ … }
static int gadget_setup(struct usb_gadget *gadget,
const struct usb_ctrlrequest *ctrl)
{ … }
static void gadget_disconnect(struct usb_gadget *gadget)
{ … }
static void gadget_suspend(struct usb_gadget *gadget)
{ … }
static void gadget_resume(struct usb_gadget *gadget)
{ … }
static void gadget_reset(struct usb_gadget *gadget)
{ … }
static struct miscdevice raw_misc_device;
static int raw_open(struct inode *inode, struct file *fd)
{ … }
static int raw_release(struct inode *inode, struct file *fd)
{ … }
static int raw_ioctl_init(struct raw_dev *dev, unsigned long value)
{ … }
static int raw_ioctl_run(struct raw_dev *dev, unsigned long value)
{ … }
static int raw_ioctl_event_fetch(struct raw_dev *dev, unsigned long value)
{ … }
static void *raw_alloc_io_data(struct usb_raw_ep_io *io, void __user *ptr,
bool get_from_user)
{ … }
static int raw_process_ep0_io(struct raw_dev *dev, struct usb_raw_ep_io *io,
void *data, bool in)
{ … }
static int raw_ioctl_ep0_write(struct raw_dev *dev, unsigned long value)
{ … }
static int raw_ioctl_ep0_read(struct raw_dev *dev, unsigned long value)
{ … }
static int raw_ioctl_ep0_stall(struct raw_dev *dev, unsigned long value)
{ … }
static int raw_ioctl_ep_enable(struct raw_dev *dev, unsigned long value)
{ … }
static int raw_ioctl_ep_disable(struct raw_dev *dev, unsigned long value)
{ … }
static int raw_ioctl_ep_set_clear_halt_wedge(struct raw_dev *dev,
unsigned long value, bool set, bool halt)
{ … }
static void gadget_ep_complete(struct usb_ep *ep, struct usb_request *req)
{ … }
static int raw_process_ep_io(struct raw_dev *dev, struct usb_raw_ep_io *io,
void *data, bool in)
{ … }
static int raw_ioctl_ep_write(struct raw_dev *dev, unsigned long value)
{ … }
static int raw_ioctl_ep_read(struct raw_dev *dev, unsigned long value)
{ … }
static int raw_ioctl_configure(struct raw_dev *dev, unsigned long value)
{ … }
static int raw_ioctl_vbus_draw(struct raw_dev *dev, unsigned long value)
{ … }
static void fill_ep_caps(struct usb_ep_caps *caps,
struct usb_raw_ep_caps *raw_caps)
{ … }
static void fill_ep_limits(struct usb_ep *ep, struct usb_raw_ep_limits *limits)
{ … }
static int raw_ioctl_eps_info(struct raw_dev *dev, unsigned long value)
{ … }
static long raw_ioctl(struct file *fd, unsigned int cmd, unsigned long value)
{ … }
static const struct file_operations raw_fops = …;
static struct miscdevice raw_misc_device = …;
module_misc_device(…);