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

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

usb主机端class驱动比较简单, 利用usb_register_driver, 向usb core子系统注册相应的class驱动即可。

主要填充usb_driver数据结构, 主要的包括id_table为设备-驱动匹配的依据(如pid, vid或class, protocol等),

其次就是probe, disconnect等回调函数, probe即匹配驱动后的探测函数, 需要做class驱动的初始化, 

比如, 鼠标: 向input device子系统注册设备, 描述event事件, 

之后就是循环读取bulk in的数据, 根据协议 判断各个bit, 解析相应鼠标的位置 和动作。

 

另外如UVC Webcam等class驱动, usb设备匹配后, 主要是注册video_device设备, 实现相应的v4l2的各种ioctl操作。


下面是关于usb_gadget驱动, 即作为usb 从设备时, linux的gadget function驱动该如何写。

其实也很简单, 主要就是利用usb_gadget_register_driver(...最新linux换名字了.. usb_gadget_probe_driver)向usb gadget驱动框架注册gadget驱动。

填充usb_gadget_driver数据结构, 比较重要的有bind, reset, setup等函数。


* 注, class driver可参考usb-skeleton 驱动, function driver可参考g_zero驱动。

可惜, 由于g_zero是一个双配置, 多接口,  多端点的复合设备, 故最新版本Linux的zero.c使用了usb_composite_probe函数进行注册。其中有帮助的宏module_usb_composite_driver简化操作。


ok, 写一个gadget驱动跑跑看...

#include 
#include
#include
#include
MODULE_LICENSE("GPL");MODULE_AUTHOR("River");/* 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,};static int g_loop_bind(struct usb_gadget *gadget, struct usb_gadget_driver *driver) { int ret = 0; struct usb_ep *ep; printk(KERN_INFO "g_loop bind callback, " "bind driver to gadget!\n"); /* reset ep autoconfig state */ usb_ep_autoconfig_reset(gadget); /* auto config the gadget ep */ ep = usb_ep_autoconfig(gadget, &fs_sink_desc); if (!ep) { printk(KERN_ERR "ep auto config failed. ret(%d)\n", ret); ret = -ENOMEM; goto config_fail; } printk(KERN_INFO "g_loop_bind succeed!\n"); return 0;config_fail: return ret;}static void g_loop_unbind(struct usb_gadget *gadget) { /* reset ep autoconfig state */ usb_ep_autoconfig_reset(gadget); printk(KERN_INFO "g_loop_unbind callback\n"); return;}/* ep0 setup callback, something udc doesn't do?? * for example, the no-standard/vendor specific * control command?? Just let us see... */static int g_loop_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctl_req) { printk(KERN_INFO "g_loop_setup callback\n"); dump_stack(); return 0;}static void g_loop_reset(struct usb_gadget *gadget) { printk(KERN_INFO "g_loop_reset callback\n"); dump_stack(); 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_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);

设备端log:

root@xxx:/mnt/module# insmod g_loop.ko [  803.757659] g_loop: loading out-of-tree module taints kernel.[  803.763672] g_loop_init in[  803.766377] driver->udc_name: (null)[  803.769948] no udc_name...[  803.772652] udc_bind_to_driver...[  803.775960] registering UDC driver [gadget_g_loop][  803.780742] dwc3_gadget_set_speed[  803.784054] g_loop bind callback, bind driver to gadget![  803.789366] g_loop_bind succeed![  803.792590] dwc3_gadget_start[  803.796047] dwc3_gadget_pullup[  803.799109] g_loop_init succeed...[  803.920487] Call trace:[  803.922934] [
] dump_backtrace+0x0/0x350[ 803.928320] [
] show_stack+0x14/0x20[ 803.933364] [
] dump_stack+0x90/0xb4[ 803.938408] [
] g_loop_reset+0x14/0x28 [g_loop][ 803.944406] [
] usb_gadget_udc_reset+0x18/0x40[ 803.950315] [
] dwc3_gadget_reset_interrupt+0x110/0x128[ 803.957007] [
] dwc3_thread_interrupt+0x4e8/0x870[ 803.963180] [
] irq_thread_fn+0x28/0x68[ 803.968482] [
] irq_thread+0x114/0x198[ 803.973699] [
] kthread+0x12c/0x130[ 803.978655] [
] ret_from_fork+0x10/0x18[ 803.992688] g_loop_setup callback...[ 809.497983] g_loop_reset callback

dwc3设备控制器一直在那里向gic发reset中断... 

为什么?? 看下主机端情况, win10上报未知USB设备(设备描述符请求失败)

嗯,  因为我代码就搭了个框架...

所有回调函数, 数据结构基本都是空的...

 

所以这个usb gadget是什么设备, 它的设备描述符, 配置项, 接口, 以及具体的功能我都没填...

 

无法识别也就好理解了...

 

* 注:  这里reset回调函数是由reset事件触发的,  具体中断号内核中是 25

root@xxx:/mnt/module# cat /proc/interrupts            CPU0       CPU1       CPU2       CPU3        25:         16          0          0          0     GICv2  97 Level    26:          0          0          0          0     GICv2 101 Level     dwc3_otg

 

具体设备树的中断号是65...

›   ›   ›   dwc3_0: dwc3@fe200000 {                                                                                             .....                                                                           ›   ›   ›   ›   interrupt-parent = <&gic>;                                                                                      ›   ›   ›   ›   interrupts = <0 65 4>, <0 69 4>, <0 75 4>;.....

根据zynqmp的datasheet... (datasheet中看gic有好几个, GIC0 ~ GIC4)

每个GIC有32个中断位, 对应如下:

65: GICP2[1] - USB0_Endpoint, 控制端点中断(66~68 是bulk, isoc, interrupt传输中断)

69: USB0_OTG  (内核中断号26, 我暂时没触发, 反正跟otg有关, 可能需要otg线+drd设备一类的吧)

75: USB0_Wakeup (USB0 controller to wake-up PMU, usb0控制器去唤醒platform manage unit模块, 我也没触发...)


ok, 不管了, 先这样, 下面继续熟悉gadget框架, 把这个设备配置起来...

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

你可能感兴趣的文章
Java Agent简介及使用Byte Buddy和AspectJ LTW监控方法执行耗时
查看>>
记录一下最近的学习经历
查看>>
hadoop3.0+spark2.0两台云服务器集群环境配置。
查看>>
网站实现qq登录(springboot后台)
查看>>
简单的用户头像修改功能(springboot后台)
查看>>
springboot+mybatis实现分页
查看>>
leetcode332. 重新安排行程
查看>>
为什么局域网网段不同不能通信?
查看>>
itchat微信助手,kaggle 电影数据集分析,基于内容的电影推荐
查看>>
认识和使用JWT
查看>>
通过springboot框架,自己动手实现oauth2.0授权码模式认证
查看>>
条件表达式于运算符的点点滴滴的积累
查看>>
最短路径最基本的三种算法【此后无良辰】
查看>>
class的点点滴滴的总结
查看>>
vector 的点点滴滴的总结
查看>>
测试用例
查看>>
自动化测试学习步骤
查看>>
自动化测试需要掌握的知识
查看>>
HTTP协议
查看>>
Python小程序——冒泡排序
查看>>