不想为想题目耗费宝贵的灵感,先起一个名字。
想获取usb设备的idProduct,不知道如何是好,一直在犹豫。利用现有资源就是直接实验,而不是一直坐那死想,插入一个USB设置的时候,可以看到是Vold尽心尽责的进行的检测:
其实一开始准备用ueventd(相当于udev/mdev)监测,但是发现不是那么回事,来看看udev的架构:
我现在的情况是 有设备而无驱动 (其实获取idProduct是为了动态加载驱动,差点搞错误先有鸡还是先有蛋的问题),就不能去用udev/ueventd的方法了,要用Vold的方法,在Vold检测到一些idProduct的时候,来进行过虑。
话说Vold管理了 各种格式的u盘 的挂载。要添加对usb其它设备的管理也要有模有样的做一套系统,不过目前先做实现,直接在打印了"== current usb device: %04X/%04X ==="这一句的后边进行idProduct的过滤,过滤出8176进行报告,分析这段代码:
SLOGD("== current usb device: %04X/%04X ===", vid, pid);
char configure_file[2048];
sprintf(configure_file, "/etc/usb_modeswitch.d/%04x_%04x", vid, pid);
if( access(configure_file, 0) == 0 )
{
// sprintf(modeswitch_cmd, "usb_modeswitch -W -I -c %s &", configure_file);
sprintf(modeswitch_cmd, "/system/bin/usb_modeswitch.sh %s &",configure_file);
SLOGD("=== USB Switch: %s", modeswitch_cmd);
system(modeswitch_cmd);
}
再看/etc/usb_modeswitch.d目录下:
都是以idProduct命名的文件,这都是一些规则,写好的规则。我对usb wifi的管理也可以参考这样的规则。关于usb_modeswitch.d参见《USB_ModeSwitch 介绍》,看完就会觉悟,原来这都是udev的那套东西。
现在开始设计上层:
1.建立/etc/usb_wifi.d/目录 和 usb_modeswitch.d一样以idProduct来命名的文件,这里以8192CU的usb wifi为例子:0bda_8176内容为RTL8188CU。
2.如果文件存在则将0bda_8176的内容RTL8188CU写入到/sys/class/rkwifi/chip or adic中,实验中可以写入/data/local/tmp/wifi_chip中。
下面开始着手写代码。
(天,逻辑怎么有点乱"end!"在怎么在“Enter”前边了,原来ALOGE和SLOGE还不一样,优先级一样,顺序也不一样,统一为SLOGE好了,这里要注意了。)
当我信心满满的时候,发现一个问题Vold是基于netlink的,但是这个好像在开机之前就有的热插拔,并不能监听。这个可苦了我了。先研究一下上述情况下udev是怎么做到的,也就是开机前插入u盘,udev后来启动后怎么知道的。
先把开机这个事放这,继续往下走,在拔出usb 设备的时候也同样判断是不是usb wifi,如果是就将标志清除,也就是写空。
这个没有什么难度,很快就完成了。
解决关机过程中的插拔:
这个问题是在我写wifi type到/data/local/tmp/wifi_chip中是出现的,具体情况是如果关机时还插着usb wifi的时候,在关机的情况下拔掉usb wifi然后再开机的时候会文件中的类型还是usb wifi。但是没有这个设备也是事实,就会引起还会去坚持插入usb wifi的驱动模块,导致逻辑不对。对于这个问题最好的解决方法是 保存usb wifi type到一个关机就消失的文件中,这样再次开机的时候就不会还是上次关机时判断的状态了。
在android中默认是没有和/tmp一个功能的目录的,所以可以考虑写的/sys文件系统中,自己实现一个小驱动。
简单说下这个小驱动的实现,基于freg,这是一个可以在/sys文件系统中一个buf,可以供读写,本来是一个整数型的,改进一下存成字符型的。每次开机时,buf是空的,就不会存在上述问题了。
解决开机前插入USB wifi的不能识别的问题:
直接说不能识别是不准确的,应该是我的测试结果是这样的。现象再仔细描述一下,在开机后插拔usb wifi和上述的截图(“效果不错”)是一样的,可以看到类型为usb。但是开机前插入的时候,就相当于先有的热插拔,后有Vold来监听,所以就监听不到了。这个是问题的总体概述。下面说下解决过程。
对于这个问题,我傻了,因为我不知如何是好,我的感觉是傻并快乐着,觉得发现了一个很有趣的逻辑,先有的hotplug事件后启动的Vold监听。针对这个现象总结了几个问题:
1.先有的hotplug事件后启动的udev/Vold监听是怎么实现的 ?
2.如果说不能实现,u盘是可以实现的这是事实?
3.如果是因为u盘有驱动,那么事件是内核中谁在发送 比如u盘中是 usb驱动在发 还是 scsi驱动在发?
4.u盘的能够接收,是不是数据包可以像Android应用程序可以保存起来,有监听就把开机后产生的相关的都发给它?
为此,我还在csdn和stackoverflow上进行了提问,但是没有答案,似乎每次我遇到的问题都是那么的冷门。为了我的问题热门一些,我尽量将问题向udev上靠。我的关键字“sys udev netlink”开始疯狂的Google。
第1篇《Linux 内核/sys 文件系统之uevent》看到一句很关键“这些 /devices/ 属性文件都支持写入,当前支持写入的参数有 "add","remove","change","move","online","offline"。如,写入 "add",这样可以向 udevd 发送一条 netlink 消息,让它再重新一遍相关的 udev 规则文件;”,然后我知道,原来可以在hotplug后也可以后知后觉的再让内核发一遍NetLink事件,且这个事件是驱动中的uevent这个调用后就会发。为此我进行了测试,确实可以的。最后实在不行,我想过要手动去做。
第2篇《Netlink实现热拔插监控》让我明白Linux内核不会主动发后启动的监听者发送事件的。
第3篇《linux驱动》群中交流。
总结一下就是 Vold中的u盘 很可能在Vold启动前进行的 事件重发操作 (这里是向uevent写“add”) 的 。
然后准备找找哪里进行的 事件重发操作 的,有点蒙,不过在system/vold/main.cpp中看到“block类型设备”进行了特殊照顾。
由于我的usb wifi还没有配置上驱动,所以没有类别,我要让所有的usb设备重新发送一下事件,测试了/sys/class/usb_devices不成功,改为/sys/bus/usb/devices这样OK了。
正是我想要的,问题就此解决。
说句后话,usb wifi驱动是归类到net类别中的,但是这里是用不到的,因为那个时候还没有驱动,更没有类别。