博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
继续写usb gadget驱动
阅读量:3560 次
发布时间:2019-05-20

本文共 9784 字,大约阅读时间需要 32 分钟。

继续写usb gadget驱动...

枚举都没过...

(只添加设备描述符, 配置描述符和接口描述符时可以完成枚举..., 一添加端点描述符后枚举就不过了...

win10报错获取配置描述符失败...)

 

先贴代码吧, 换台ubuntu主机试着枚举看看......

#include 
#include
/* min() */#include
#include
#include
#include
MODULE_LICENSE("GPL");MODULE_AUTHOR("River");#define USB_BUFSIZE 256struct g_loop_dev { struct usb_gadget *gadget; // gadget device struct usb_request *req; // for ep0 request struct usb_ep *out_ep; // TBD: for ep out transfer // struct cdev cdev; // TBD: char dev};#define STR_ID_MANUFACTURER 25#define STR_ID_PRODUCT 42#define STR_ID_SERIAL 101#define STR_ID_LOOPBACK 251/* my specific vid&pid */// #define DRIVER_VENDOR_NUM 0x1234// #define DRIVER_PRODUCT_NUM 0x5678#define DRIVER_VENDOR_NUM 0x0525 /* NetChip */#define DRIVER_PRODUCT_NUM 0xa4a0 /* Linux-USB "Gadget Zero" */static struct usb_device_descriptor device_desc = { .bLength = sizeof (device_desc), .bDescriptorType = USB_DT_DEVICE, .bcdUSB = __constant_cpu_to_le16(0x0320), // .bcdUSB = __constant_cpu_to_le16(0x0110), .bDeviceClass = USB_CLASS_VENDOR_SPEC, .bMaxPacketSize0 = 9, .idVendor = __constant_cpu_to_le16(DRIVER_VENDOR_NUM), .idProduct = __constant_cpu_to_le16(DRIVER_PRODUCT_NUM), .iManufacturer = STR_ID_MANUFACTURER, .iProduct = STR_ID_PRODUCT, .iSerialNumber = STR_ID_SERIAL, .bNumConfigurations = 1,};static struct usb_config_descriptor g_loop_config = { .bLength = sizeof g_loop_config, .bDescriptorType = USB_DT_CONFIG, .bNumInterfaces = 1, .bConfigurationValue = 1, .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, .bMaxPower = 1, /* self-powered */};/* interface descriptor */static struct usb_interface_descriptor g_loop_interface = { .bLength = sizeof(g_loop_interface), .bDescriptorType = USB_DT_INTERFACE, .bNumEndpoints = 1, .bInterfaceClass = USB_CLASS_VENDOR_SPEC, .iInterface = STR_ID_LOOPBACK,};/* endpoint descriptor */static struct usb_endpoint_descriptor fs_sink_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType= USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_OUT, // for pc host, it is out ep. .bmAttributes = USB_ENDPOINT_XFER_BULK, // .wMaxPacketSize = __constant_cpu_to_le16(1024),};/* function/interface description... */static const struct usb_descriptor_header *fs_g_loop_function[] = { (struct usb_descriptor_header *) &g_loop_interface, (struct usb_descriptor_header *) &fs_sink_desc, NULL,};static struct usb_string strings[] = { {STR_ID_MANUFACTURER, "river run", }, {STR_ID_PRODUCT, "river loop", }, {STR_ID_SERIAL, "1234567890", }, {STR_ID_LOOPBACK, "loop in to out", }, { },};static struct usb_gadget_strings string_table = { .language = 0x0409, /* en-us */ .strings = strings,};static void g_loop_setup_complete(struct usb_ep *ep, struct usb_request *req) { printk(KERN_INFO "g_loop_setup complete --> %d, %d, %d\n", req->status, req->actual, req->length); return;}static void free_ep_req(struct usb_ep *ep, struct usb_request *req){ kfree(req->buf); usb_ep_free_request(ep, req);}static int g_loop_dev_prepare(struct g_loop_dev *dev) { struct usb_gadget *gadget = dev->gadget; int ret; /* reset ep autoconfig state */ usb_ep_autoconfig_reset(gadget); /* config & prepare an endpoint */ dev->out_ep = usb_ep_autoconfig(gadget, &fs_sink_desc); if (!dev->out_ep) { printk(KERN_ERR "usb_ep_autoconfig failed\n"); ret = - ENOMEM; goto config_fail; } printk(KERN_INFO "ep_desc = %p\n", dev->out_ep->desc); printk(KERN_INFO "fs_sink_desc = %p\n", &fs_sink_desc); printk(KERN_INFO "ep->addr = %d\n", dev->out_ep->address); printk(KERN_INFO "ep->claimed = %d\n", dev->out_ep->claimed); printk(KERN_INFO "ep->enabled = %d\n", dev->out_ep->enabled); printk(KERN_INFO "usb_ep_autoconfig succeed\n"); /* preallocate control response and buffer */ dev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL); if (!dev->req) { ret = -ENOMEM; goto ep_fail; } dev->req->buf = kmalloc(USB_BUFSIZE, GFP_KERNEL); if (!dev->req->buf) goto malloc_fail; dev->req->complete = g_loop_setup_complete; dev->req->context = dev; gadget->ep0->driver_data = dev; usb_gadget_set_selfpowered(gadget); return 0;malloc_fail: usb_ep_free_request(gadget->ep0, dev->req); dev->req = NULL;ep_fail:config_fail: return ret;}static int g_loop_bind(struct usb_gadget *gadget, struct usb_gadget_driver *driver) { int ret = 0; struct g_loop_dev *dev; if (!gadget ||!driver) { ret = -EINVAL; goto invalid_param; } printk(KERN_INFO "gadget info: speed(%d), max_speed(%d)", gadget->speed, gadget->max_speed); printk(KERN_INFO "gadget info: maxpacket(%d), claimed(%d), enabled(%d)", gadget->ep0->maxpacket, gadget->ep0->claimed?1:0, gadget->ep0->enabled?1:0); dev = kzalloc(sizeof(struct g_loop_dev), GFP_KERNEL); if (!dev) { printk(KERN_ERR "malloc failed for g_loop_dev\n"); ret = -ENOMEM; goto malloc_fail; } dev->gadget = gadget; set_gadget_data(gadget, dev); /* bMaxPacketSize format is 2^bMaxPacketSize0, eg, 2^9 = 512 */ // device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket; ret = g_loop_dev_prepare(dev); if (ret < 0) { printk(KERN_ERR "g_loop_dev_prepare failed...\n"); goto prepare_fail; } printk(KERN_INFO "simple composite ready...\n"); return ret;prepare_fail: if (dev) { kfree(dev); dev = NULL; }malloc_fail:invalid_param: return ret;}static void g_loop_unbind(struct usb_gadget *gadget) { struct g_loop_dev *dev = get_gadget_data(gadget); if (dev->req) { dev->req->length= USB_BUFSIZE; free_ep_req(gadget->ep0, dev->req); } kfree(dev); set_gadget_data(gadget, NULL); printk(KERN_INFO "g_loop_unbind callback complete\n"); return;}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; printk(KERN_INFO "config_buf, type = %d, index = %d\n", type, index); function = fs_g_loop_function; len = usb_gadget_config_buf(&g_loop_config, buf, USB_BUFSIZE, function); if (len < 0) return len; ((struct usb_config_descriptor *) buf)->bDescriptorType = type; return len;}/* * ep0 setup callback, we need to tell what kind of * device we are... * according to ch9, we need to response to get_descriptor * control command... */static int g_loop_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctl_req) { struct g_loop_dev *loop_dev = get_gadget_data(gadget); struct usb_request *req = NULL; int value = 0; // u16 w_index = le16_to_cpu(ctl_req->wIndex); u16 w_value = le16_to_cpu(ctl_req->wValue); u16 w_length = le16_to_cpu(ctl_req->wLength); int ret = 0; int i = 0; unsigned char *buf; printk(KERN_INFO "g_loop_setup callback\n"); if (!loop_dev) { ret = -EFAULT; goto unknown; } req = loop_dev->req; buf = req->buf; // dump_stack(); printk(KERN_INFO "setup request: %d, desc_type: 0x%x, " "w_lenght:%d\n", ctl_req->bRequest, w_value>>8, w_length); switch (ctl_req->bRequest) { /* handle some standard request... */ case USB_REQ_GET_DESCRIPTOR: { if (ctl_req->bRequestType != USB_DIR_IN ) { printk(KERN_ERR "error request type(0x%x)\n", ctl_req->bRequestType); ret = -EFAULT; goto unknown; } /* high byte means descriptor type, * descriptor index in low byte... */ switch (w_value>>8) { case USB_DT_DEVICE: value = min(w_length, (u16) sizeof device_desc); memcpy(req->buf, &device_desc, value); break; case USB_DT_CONFIG: /* use some help function fill config descriptor... */ value = config_buf(gadget, req->buf, w_value >> 8, w_value & 0xff); if (value >= 0) value = min(w_length, (u16) value); break; case USB_DT_STRING: value = usb_gadget_get_string(&string_table, w_value&0xff, req->buf); if (value >= 0) value = min(w_length, (u16) value); break; default: printk(KERN_INFO "descriptor type: %d, do nothing\n", w_value>>8); break; } } break; case USB_REQ_SET_DESCRIPTOR: printk(KERN_INFO "set descriptor request, do nothing...\n"); break; case USB_REQ_GET_CONFIGURATION: printk(KERN_INFO "get configuration request, do nothing...\n"); break; case USB_REQ_SET_CONFIGURATION: printk(KERN_INFO "set configuration request, do nothing...\n"); break; case USB_REQ_GET_INTERFACE: printk(KERN_INFO "get interfafe request, do nothing...\n"); break; case USB_REQ_SET_INTERFACE: printk(KERN_INFO "set interfafe request, do nothing...\n"); break; default: printk(KERN_INFO "bRequestType - %d, no handler...\n", ctl_req->bRequestType); break; } if (value <= 0) { printk(KERN_ERR "no data needs to be sent\n"); goto do_nothing; } printk(KERN_INFO "buf:\n"); for (i=0; i
length = value; req->zero = value < w_length; printk(KERN_INFO "value: %d, w_length: %d\n", value, w_length); printk(KERN_INFO "req->zero: %d\n", req->zero); ret = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC); if (ret < 0) { printk(KERN_ERR "usb_ep_queue failed, ret(%d)\n", ret); req->status = 0; g_loop_setup_complete(gadget->ep0, req); } return ret;do_nothing:unknown: return ret;}static void g_loop_reset(struct usb_gadget *gadget) { printk(KERN_INFO "g_loop_reset callback\n"); usb_ep_autoconfig_reset(gadget); return;}static void g_loop_disconnect(struct usb_gadget *gadget) { printk(KERN_INFO "g_loop_disconnect callback\n"); return;}static struct usb_gadget_driver g_loop_driver = { .function = "gadget_g_loop", .max_speed = USB_SPEED_SUPER, // .max_speed = USB_SPEED_HIGH, .bind = g_loop_bind, .unbind = g_loop_unbind, .setup = g_loop_setup, .reset = g_loop_reset, .disconnect = g_loop_disconnect,};static int __init g_loop_init(void) { int ret = 0; printk(KERN_INFO "g_loop_init in\n"); ret = usb_gadget_probe_driver(&g_loop_driver); if (ret < 0) { printk(KERN_ERR "usb gaget driver register failed, " "ret(%d)\n", ret); goto probe_failed; } printk(KERN_INFO "g_loop_init succeed\n"); return 0;probe_failed: return ret;}static void __exit g_loop_exit(void) { printk(KERN_INFO "g_loop_exit in\n"); usb_gadget_unregister_driver(&g_loop_driver); printk(KERN_INFO "g_loop_exit succeed\n"); return;}module_init(g_loop_init);module_exit(g_loop_exit);

 

转载地址:http://ricrj.baihongyu.com/

你可能感兴趣的文章
TCP协议
查看>>
关于Linux系统使用遇到的问题-1:vi 打开只读(readonly)文件如何退出保存?
查看>>
redis 持久化详解,RDB和AOF是什么?他们优缺点是什么?运行流程是什么?
查看>>
spring注解版(一)
查看>>
SpringBoot中访问控制层(controller)得不到Json数据
查看>>
react项目报出警告Warning: Cannot update during an existing state transition (such as within `render`).
查看>>
BFC(Block Formatting Context)
查看>>
什么是作用域,什么是闭包,什么是作用域链
查看>>
惰性求值,面向对象
查看>>
数据结构之列表
查看>>
发布/订阅模式 vs 观察者模式
查看>>
es5中的arguments对象
查看>>
git本地仓库和远程仓库关联,分支重命名
查看>>
js对象的深拷贝,你真的觉得很简单吗?
查看>>
你真的了解map方法吗?手动实现数组map方法。
查看>>
带你手动实现call方法,让你收获满满
查看>>
前端知识体系
查看>>
查找入职员工时间排名倒数第三的员工所有信息
查看>>
使用join查询方式找出没有分类的电影id以及名称
查看>>
Qt教程(2) : Qt元对象系统
查看>>