Linux USB gadget设备驱动解析(4)--编写一个gadget驱动
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
gadget 一个 驱动 编写 设备驱动 USB Linux 解析 相关文章:
- 关于spiflash存储器读写一个字节的问题方案(11-27)
- 第1节:单片机到底是学什么?我的两个比喻和一个规则(11-22)
- 汇编入门学习笔记 (三) —— 第一个程序(11-09)
- DIY一个MSP430F149最小系统的设计(07-22)
- 视频显示卡直接写屏的一个实例(09-14)
- 单片机c语言教程:建立你的第一个KeilC51项目(09-11)