解决usb虚拟u盘无法probe驱动的问题--Apple的学习笔
1.前言:
一开始想使用usb gadget来虚拟网卡的,结果按网上的简单配置后,无法使用,Document中貌似没看到什么特别有帮助的,所以先降低难度使用usb gadget来虚拟一个u盘。其它的之后再慢慢深入。先进入Kernel驱动实战
2.在使用modprobe时候思考如何用insmod
modprob比insmod好用,但是需要知道原理
linux设备驱动有两种加载方式insmod和modprobe,下面谈谈它们用法上的区别
1、insmod一次只能加载特定的一个设备驱动,且需要驱动的具体地址。
2. modprobe则可以一次将有依赖关系的驱动全部加载到内核。不加驱动的具体地址,但需要在安装文件系统时是按照make modues_install的方式安装驱动模块的。驱动被安装在/lib/modules/$(uname -r)/...下。写法为:
modprob drv
modprobe 和insmod一样都是用来加载内核module的
不过modprobe比较智能,它可以根据module的依赖性来自动为你加载;而insmod就做不到这点。智能识别的原理是什么呢!
手工又应该如何加载模块呢!随意加载就会报错。
方法一
在编译后,modinfo xx.ko可以查看详细信息。其中depends 一项我们可以看到该模块依赖 x模块。
方法二
modules.dep文件是一个依赖关系图,在此文件的目录中,通过搜索命令可以知道依赖关系。
grep -nr phy-am335x.ko modules.dep
- 添加模块后不成功,需要调试
常用的就是打印信息,为了输出pr_debug和dev_debug驱动加载的调试信息配置kernel
image.png
image.png
其它方法
驱动文件定义#define DEBUG,如果需要调试的文件很多,或者调试初期无法确定问题是在哪个文件时,如何处理?这里提供一个参考,kernel顶层Makefile中KBUILD_CFLAGS+=DDEBUG可实现,但又会引入更多问题,比如DVFS的大量日志等等。
打印信息过多,导致printk messages dropped
解决方法config LOG_BUF_SHIFT int"Kernel log buffer size (16 => 64KB, 17 => 128KB)设置内核日志缓冲区的最小尺寸(合理的设置应该等于CONFIG_LOG_CPU_MAX_BUF_SHIFT*最大CPU数量): 12(最小值)=4KB,...,16=64KB,17=128KB,18=256KB,...,25(最大值)
3.通过调试信息找到突破口
之前modprobe g_multi加载虚拟网卡或者modprobe usb_f_mass_storage加载模块的时候都会报错
udc-core: couldn't find an available UDC - added [g_mass_storage] to list of pending drivers
找到对应模块的c文件为core.c
udc-core-y := core.o trace.o
#
# USB peripheral controller drivers
#
obj-$(CONFIG_USB_GADGET) += udc-core.o
搜索打印的关键字,找到usb_gadget_probe_driver函数报错。for循环没有在udc_list中找到所以报错,继续搜索udc_list,通过代码搜索发现usb文件夹只有一个list_add_tail(&udc->list, &udc_list);那么理解为必须先添加到list中才能找到。所以看谁调用usb_add_gadget_udc_release。
4.对比tisdk来验证我分析代码的正确性
usb_add_gadget_udc_release应该是在musb_init_controller中调用的。
所以我认为在musb_core.c中musb_probe必须被调用。而且需要加载模块musb_hdrc.ko。结果我的理解正确。
[ 38.760443] bus: 'platform': add driver musb-dsps
[ 38.760713] bus: 'platform': driver_probe_device: matched device 47401400.usb with driver musb-dsps
[ 38.760788] bus: 'platform': really_probe: probing driver musb-dsps with device 47401400.usb
[ 38.760842] musb-dsps 47401400.usb: no pinctrl handle
[ 38.761038] irq: a:virq=61,type=0
[ 38.761043] irq: b
[ 38.765453] Registering platform device 'musb-hdrc.0'. Parent at 47401400.usb
[ 38.765467] device: 'musb-hdrc.0': device_add
[ 38.765528] bus: 'platform': add device musb-hdrc.0
[ 38.765573] PM: Adding info for platform:musb-hdrc.0
[ 38.766259] bus: 'platform': driver_probe_device: matched device musb-hdrc.0 with driver musb-hdrc
[ 38.766274] bus: 'platform': really_probe: probing driver musb-hdrc with device musb-hdrc.0
[ 38.766369] irq: a:virq=63,type=0
[ 38.766373] irq: b
[ 38.766377] musb_probe
[ 38.766453] musb_init_controller
[ 38.769207] musb->port_mode is 2
[ 38.769214] go musb_gadget_setup
[ 38.769252] go usb_add_gadget_udc
[ 38.769257] go usb_add_gadget_udc_release
[ 38.769272] device: 'gadget': device_add
5.分析我的kernel代码
果然,自己在5.4.61kernel中做的zImage的CONFIG_USB_MUSB_HDRC为y,但是没有信息打印出啦,说明没有probe成功。
将其编译到内核后,发现如下add driver musb-hdrc但是没有输出我在probe添加的调试信息。并且之前对比发现/sys/class/uds下面没有创建设备musb-hdrc.0。但是通过modprobe musb_hdrc是可以在/sys/bus下面创建usb的。
所以,有了tisdk我就找到捷径了。这几个KO文件对应的宏开关我把他打开。配置了CONFIG_USB_MUSB_HDRC和CONFIG_USB_MUSB_DSPS,然后bb black能虚拟一个u盘连接到主机PC咯~
6.进一步解决bus下没有usb总线的问题
已经可以虚拟出u盘,为什么bus下没有usb总线。难道都是通过/sys/class/udc来连接的吗?这一点我暂时先放放。先解决为什么usb总线没有创建问题。通过调试信息真是没有看到usb bus的创建呀!
调查步骤:
- 通过搜索': registered。没有搜索到bus usb被register。
- 通过代码搜索usb子系统初始化函数usb_init。是属于subsys_initcall,那么在do_initcalls中应该被调用的呀。
- 然后我去System.map里看看usb_init函数是否编译入。通过命令grep -nr usb_init System.map发现找不到。
- 此bus初始化函数在core文件夹,在Makefile查看,需要配置CONFIG_USB。另外,它对应的usbcore.o
- 难道是没有配置,不会吧!然后去看.config文件CONFIG_USB=m。
至此已经知道原因,若我希望在/sys/bus下面看到usb总线,只要重新配置kernel或者手工加载usbcore.ko即可。
7.总结
通过如下3个步骤,完成bb black虚拟u盘的操作
modprobe usbcore
modprobe usb_f_mass_storage
modprobe g_mass_storage file=/dev/mmcblk0p1 removable=1
Welcome to Buildroot
buildroot login: root
# cd /sys/bus
# ls
clockevents gpio mmc_rpmb scsi virtio
clocksource hid nvmem sdio workqueue
container i2c pci serial
cpu mdio_bus pci-epf soc
event_source mmc platform spi
# modprobe usbcore
[ 71.089616] bus: 'usb': registered
[ 71.093291] bus: 'usb': add driver usbfs
[ 71.097310] usbcore: registered new interface driver usbfs
[ 71.102893] bus: 'usb': add driver hub
[ 71.106705] usbcore: registered new interface driver hub
[ 71.112118] bus: 'usb': add driver usb
[ 71.115924] usbcore: registered new device driver usb
# cd /sys/bus/usb
# ls
devices drivers_autoprobe uevent
drivers drivers_probe
# cd devices/
# ls
# cd ..
# ls
devices drivers_autoprobe uevent
drivers drivers_probe
# cd /sys/class/udc
# ls
musb-hdrc.0
# cd musb-hdrc.0/
# ls
a_alt_hnp_support device is_selfpowered srp
a_hnp_support function maximum_speed state
b_hnp_enable is_a_peripheral power subsystem
current_speed is_otg soft_connect uevent
# cd ..
# cd ..
# cd /sys/bus/usb
# ls
devices drivers_autoprobe uevent
drivers drivers_probe
# cd devices/
# modprobe usb_f_mass_storage
# [ 167.200445] random: crng init done
# modprobe g_mass_storage file=/dev/mmcblk0p1 removable=1
[ 173.939807] driver_name is g_mass_storage
[ 173.939818] go 2
[ 173.945862] myUDC is found
[ 173.948592] udc musb-hdrc.0: registering UDC driver [g_mass_storage]
[ 173.955089] Mass Storage Function, version: 2009/09/11
[ 173.960261] LUN: removable file: (no medium)
[ 173.964622] device: 'lun0': device_add
[ 173.968444] PM: Adding info for No Bus:lun0
[ 173.972823] lun0: open backing file: /dev/mmcblk0p1
[ 173.977734] LUN: removable file: /dev/mmcblk0p1
[ 173.982322] Number of LUNs=1
[ 173.985233] g_mass_storage gadget: adding config #1 'Linux File-Backed Storage'/c7b2a844
[ 173.993389] g_mass_storage gadget: adding 'Mass Storage Function'/d03f0dd3 to config 'Linux File-Backed Storage'/c7b2a844
[ 174.006354] g_mass_storage gadget: I/O thread pid: 116
[ 174.011679] g_mass_storage gadget: cfg 1/c7b2a844 speeds: high full
[ 174.017980] g_mass_storage gadget: interface 0 = Mass Storage Function/d03f0dd3
[ 174.025557] g_mass_storage gadget: Mass Storage Gadget, version: 2009/09/11
[ 174.032579] g_mass_storage gadget: userspace failed to provide iSerialNumber
[ 174.039657] g_mass_storage gadget: g_mass_storage ready
# [ 174.481041] g_mass_storage gadget: high-speed config #1: Linux File-Backed Storage
[ 174.488703] g_mass_storage gadget: set_config: interface 0 (Mass Storage Function) requested delayed status
[ 174.498487] g_mass_storage gadget: delayed_status count 1
[ 174.503977] g_mass_storage gadget: usb_composite_setup_continue
[ 174.509925] g_mass_storage gadget: usb_composite_setup_continue: Completing delayed status
[ 175.534012] g_mass_storage gadget: sending command-failure status
[ 175.541790] g_mass_storage gadget: bulk-in set halt
[ 175.547398] g_mass_storage gadget: bulk-in set halt
[ 175.574254] g_mass_storage gadget: bulk-in set halt
[ 175.579798] g_mass_storage gadget: bulk-in set halt
[ 175.589653] g_mass_storage gadget: bulk-in set halt
[ 175.595534] g_mass_storage gadget: bulk-in set halt
8.后记
关于此次解决问题突破口采用了捷径,就是去查tisdk的调试信息来反推需要填写哪些模块。这是不对的,若遇到没有参考的情况下,我该怎么办。所以后续要对这些c代码的功能进一步了解。我需要知道哪些c模块代码拥有这些功能,这是我本次的败笔,本次比较好的就是能充分利用调试信息及设备模型匹配框架还有Makefile这张地图。自己虚拟一个u盘,觉得好好玩,所以先用起来,之后会继续深入学习的。