微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > Linux USB gadget设备驱动解析(4)--编写一个gadget驱动

Linux USB gadget设备驱动解析(4)--编写一个gadget驱动

时间:08-06 来源:互联网 点击:

ee_ep_req(ep, req);

req = NULL;

}

return req;

}

ssize_t

usb_zero_read (struct file * file, const char __user * buf, size_t count,loff_t * f_pos) //读设备

{

struct zero_dev *dev =file->private_data;

struct usb_request *req;

int status;

struct usb_ep *ep;

struct usb_gadget *gadget = dev->gadget;

ssize_t ret = 0;

int result;

ep=dev->out_ep;

source_sink_start_ep(ep);//构造、递交读请求

if (count 0)

return -EINVAL;

interruptible_sleep_on (dev->bulkrq);//睡眠,等到请求完成

if (copy_to_user (buf,dev->data,dev->data_size)) //拷贝读取的数据到用户空间

{

ret = -EFAULT;

}

else

{

ret = dev->data_size;

}

return ret;

}

struct file_operations usb_zero_fops = {

.owner = THIS_MODULE,

.read = usb_zero_read,

.open = usb_zero_open,

.release = usb_zero_release,

};

static void

usb_zero_setup_cdev (struct zero_dev *dev, int minor)//注册字符设备驱动

{

int err, devno = MKDEV (usb_zero_major, minor);

cdev_init(dev->cdev, usb_zero_fops);

dev->cdev.owner = THIS_MODULE;

err = cdev_add (dev->cdev, devno, 1);

if (err)

printk (Error adding usb_rcvn);

}

static void zero_setup_complete(struct usb_ep *ep, struct usb_request *req)//配置端点0的请求

完成处理

{

if (req->status || req->actual != req->length)

printk(setup complete --> %d, %d/%dn,

req->status, req->actual, req->length);

}

static void zero_reset_config(struct zero_dev *dev) //复位配置

{

usb_ep_disable(dev->out_ep);

dev->out_ep = NULL;

}

static void zero_disconnect(struct usb_gadget *gadget)//卸载驱动时被调用,做一些注销工作

{

struct zero_dev *dev = get_gadget_data(gadget);

unsigned long flags;

unregister_chrdev_region (MKDEV (usb_zero_major, 0), 1);

cdev_del ((dev->cdev));

zero_reset_config(dev);

printk(in %sn,__FUNCTION__);

}

static int config_buf(struct usb_gadget *gadget,

u8 *buf, u8 type, unsigned index)

{

//int is_source_sink;

int len;

const struct usb_descriptor_header **function;

int hs = 0;

function =fs_loopback_function;//根据fs_loopback_function,得到长度,

//此处len=配置(9)+1个接口(9)+1个端点(7)=25

len = usb_gadget_config_buf(loopback_config,

buf, USB_BUFSIZ, function);

if (len 0)

return len;

((struct usb_config_descriptor *) buf)->bDescriptorType = type;

return len;

}

static int set_loopback_config(struct zero_dev *dev)

{

int result = 0;

struct usb_ep *ep;

struct usb_gadget *gadget = dev->gadget;

ep=dev->out_ep;

const struct usb_endpoint_descriptor *d;

d = fs_sink_desc;

result = usb_ep_enable(ep, d); //激活端点

//printk();

if (result == 0) {

printk(connectedn); //如果成功,打印“connected”

}

else

printk(can't enable %s, result %dn, ep->name, result);

return result;

}

static int zero_set_config(struct zero_dev *dev, unsigned number)

{

int result = 0;

struct usb_gadget *gadget = dev->gadget;

result = set_loopback_config(dev);//激活设备

if (result)

zero_reset_config(dev); //复位设备

else {

char *speed;

switch (gadget->speed) {

case USB_SPEED_LOW: speed = low; break;

case USB_SPEED_FULL: speed = full; break;

case USB_SPEED_HIGH: speed = high; break;

default: speed = ; break;

}

}

return result;

}

/***

zero_setup完成USB设置阶段和具体功能相关的交互部分

***/

static int

zero_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)

{

struct zero_dev *dev = get_gadget_data(gadget);

struct usb_request *req = dev->req;

int value = -EOPNOTSUPP;

u16 w_index = le16_to_cpu(ctrl->wIndex);

u16 w_value = le16_to_cpu(ctrl->wValue);

u16 w_length = le16_to_cpu(ctrl->wLength);

/* usually this stores reply data in the pre-allocated ep0 buffer,

* but config change events will reconfigure hardware.

*/

req->zero = 0;

switch (ctrl->bRequest) {

case USB_REQ_GET_DESCRIPTOR: //获取描述符

if (ctrl->bRequestType != USB_DIR_IN)

goto unknown;

swit

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top