新闻中心

EEPW首页 > 嵌入式系统 > 设计应用 > Linux USB gadget设备驱动解析(4)--编写一个gadget驱动

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

作者:时间:2012-08-06来源:网络收藏

value = min(w_length, (u16) sizeof device_desc);

memcpy(req->buf, device_desc, value);

break;

case _DT_CONFIG: //获取配置,注意:会根据fs_loopback_function读取到接口、端点描述符,注意通过config_buf完成读取数据及数量的统计。

value = config_buf(, req->buf,

w_value >> 8,

w_value 0xff);

if (value >= 0)

value = min(w_length, (u16) value);

break;

case _DT_STRING:

value = usb__get_string(stringtab,

w_value 0xff, req->buf);

if (value >= 0)

value = min(w_length, (u16) value);

break;

}

break;

case _REQ_SET_CONFIGURATION:

if (ctrl->bRequestType != 0)

goto unknown;

spin_lock(dev->lock);

value = zero_set_config(dev, w_value);//激活相应的端点

spin_unlock(dev->lock);

break;

default:

unknown:

printk(

unknown control req%02x.%02x v%04x i%04x l%dn,

ctrl->bRequestType, ctrl->bRequest,

w_value, w_index, w_length);

}

/* respond with data transfer before status phase */

if (value >= 0) {

req->length = value;

req->zero = value w_length;

value = usb_ep_queue(->ep0, req, GFP_ATOMIC);//通过端点0完成setup

if (value 0) {

printk(ep_queue --> %dn, value);

req->status = 0;

zero_setup_complete(gadget->ep0, req);

}

}

/* device either stalls (value 0) or reports success */

return value;

}

static void zero_unbind(struct usb_gadget *gadget) //解除绑定

{

struct zero_dev *dev = get_gadget_data(gadget);

printk(unbindn);

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

cdev_del ((dev->cdev));

/* we've already been disconnected ... no i/o is active */

if (dev->req) {

dev->req->length = USB_BUFSIZ;

free_ep_req(gadget->ep0, dev->req);

}

kfree(dev);

set_gadget_data(gadget, NULL);

}

static int __init zero_bind(struct usb_gadget *gadget) //绑定过程

{

struct zero_dev *dev;

struct usb_ep *ep;

int gcnum;

usb_ep_autoconfig_reset(gadget);

ep = usb_ep_autoconfig(gadget, fs_sink_desc);//根据端点描述符及控制器端点情况,分配合适的端点。

if (!ep)

goto enomem;

EP_OUT_NAME = ep->name; //记录名称

gcnum = usb_gadget_controller_number(gadget);//获得控制器代号

if (gcnum >= 0)

device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum);//赋值设备描述符

else {

pr_warning(%s: controller '%s' not recognizedn,

shortname, gadget->name);

device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);

}

dev = kzalloc(sizeof(*dev), GFP_KERNEL); //分配设备结构体

if (!dev)

return -ENOMEM;

spin_lock_init(dev->lock);

dev->gadget = gadget;

set_gadget_data(gadget, dev);

dev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL);//分配请求

if (!dev->req)

goto enomem;

dev->req->buf = kmalloc(USB_BUFSIZ, GFP_KERNEL);

if (!dev->req->buf)

goto enomem;

dev->req->complete = zero_setup_complete;

dev->out_ep=ep; //记录端点(就是接收host端数据的端点)

printk(name=%sn,dev->out_ep->name); //打印出这个端点的名称

ep->driver_data=dev;

device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;

usb_gadget_set_selfpowered(gadget);

gadget->ep0->driver_data = dev;

snprintf(manufacturer, sizeof manufacturer, %s %s with %s,

init_utsname()->sysname, init_utsname()->release,

gadget->name);

/**************************字符设备注册*******************/

dev_t usb_zero_dev = MKDEV (usb_zero_major, 0);

int result = register_chrdev_region (usb_zero_dev, 1, usb_zero);

if (result 0)

{

printk (KERN_NOTICE Unable to get usb_transfer region, error %dn,result);

return 0;

}

usb_zero_setup_cdev (dev, 0);

return 0;

enomem:

zero_unbind(gadget);

return -ENOMEM;

}

/*-------------------------------------------------------------------------*/

static struct usb_gadget_driver zero_driver = { //gadget的核心数据结构

#ifdef CONFIG_USB_GADGET_DUALSPEED

.speed = USB_SPEED_HIGH,

#else

.speed = USB_SPEED_FULL,

#endif

.function = (char *) longname,

.bind = zero_bind,

.unbind = __exit_p(zero_unbind),

.setup = zero_setup,

linux操作系统文章专题:linux操作系统详解(linux不再难懂)

linux相关文章:linux教程




评论


相关推荐

技术专区

关闭