环境系统:Android-4.0 内核:linux3.08 板子:icool210
当一个新的usb插入时,内核会发送一个uevent时间。上层接收到后,做出相应的处理。
如:我使用的为电信的3G网卡AC2787,插入arm板上后。没有正确识别成为ttyUSB*设备。无法进行AT命令发送。这时。我们需要转换模式。
我使用的是usb_modeswitch可以去官网下载,然后使用arm-gcc进行编译。参考http://blog.csdn.net/w6028819321/article/details/8883044
(1)首先看一下消息流向
在Android-4.0/system/core/libsysutils/src/NetlinkListener.cpp文件中
1 bool NetlinkListener::onDataAvailable(SocketClient *cli) 2 { 3 int socket = cli->getSocket(); 4 ssize_t count; 5 6 count = TEMP_FAILURE_RETRY(uevent_kernel_multicast_recv(socket, mBuffer, sizeof(mBuffer))); 7 if (count < 0) { 8 SLOGE("recvmsg failed (%s)", strerror(errno)); 9 return false; 10 } 11 //这里buffer形式为:add@/devices/platform/s3c2410-ohci/usb1/1-1/1-1.2 12 NetlinkEvent *evt = new NetlinkEvent(); 13 if (!evt->decode(mBuffer, count, mFormat)) { 14 SLOGE("Error decoding NetlinkEvent"); 15 } else { 16 onEvent(evt); 17 } 18 19 delete evt; 20 return true; 21 }
(2)这里的decode调用的为
//Android-4.0/system/core/libsysutils/src/NetlinkEvent.cpp 这里循环将buffer数据提取出来 bool NetlinkEvent::decode(char *buffer, int size) { while (s < end) { if (first) { ...... for (p = s; *p != '@'; p++); mPath = strdup(p); ....... } else { if (!strncmp(s, "ACTION=", strlen("ACTION="))) { char *a = s + strlen("ACTION="); if (!strcmp(a, "add")) mAction = NlActionAdd; else if (!strcmp(a, "remove")) mAction = NlActionRemove; else if (!strcmp(a, "change")) mAction = NlActionChange; } else if (!strncmp(s, "SEQNUM=", strlen("SEQNUM="))) mSeq = atoi(s + strlen("SEQNUM=")); else if (!strncmp(s, "SUBSYSTEM=", strlen("SUBSYSTEM="))) mSubsystem = strdup(s + strlen("SUBSYSTEM=")); else mParams[param_idx++] = strdup(s); } } }
(3)继续调用onEvent函数,会有两处调用onEvent函数,1:为vold 2:为netd 程序。 两者类似。 只看下vold;添加usb事件处理;
//Android4.0/system/vold/NetlinkHandler.cpp void NetlinkHandler::onEvent(NetlinkEvent *evt) { VolumeManager *vm = VolumeManager::Instance(); const char *subsys = evt->getSubsystem(); if (!subsys) { SLOGW("No subsystem found in netlink event"); return; } if (!strcmp(subsys, "block")) { vm->handleBlockEvent(evt); } #if defined(BOARD_USES_HDMI) || defined(S5P_BOARD_USES_HDMI) else if ((!strcmp(subsys, "misc")) || (!strcmp(subsys, "video4linux"))) { vm->handleMiscEvent(evt); } #endif //这里没有usb,我们添加一项,如下3行 else if (!strcmp(subsys, "usb")) { vm->handleUsbEvent(evt); //此函数需要在 Event类中添加 } }
//在/Android-4.0/system/vold/VolumeManager.h class VolumeManager { public: //增加如下一行 void handleUsbEvent(NetlinkEvent *evt); }
//文件Android-4.0/system/vold/VolumeManager.cpp中,增加函数 void VolumeManager::handleUsbEvent(NetlinkEvent *evt) { const char *devtype = evt->findParam("DEVTYPE"); char *cmd; //如下判断设备类型,和是否为add模式。 进行相应操作 if(1 == evt->getAction() && !strcmp(devtype, "usb_device")) { /*call usb mode switch function*/ asprintf(&cmd, "usb_modeswitch -W -c /etc/usb_modeswitch.conf"); //usb_modeswitch.conf system(cmd); free(cmd); } }
(4)重新编译,烧到板子里,启动系统后,插进3g上网卡,自动转换成功,打印出一下信息。免去使用命令转换的不方便[ 4418.695387] usb 1-1.4: USB disconnect, device number 7
[ 4419.876390] usb 1-1.4: new full speed USB device number 8 using s5p-ohci [ 4419.975390] usb 1-1.4: config 1 has an invalid interface number: 5 but max is 4 [ 4419.975455] usb 1-1.4: config 1 has no interface number 4 [ 4419.988319] option 1-1.4:1.0: GSM modem (1-port) converter detected [ 4419.990765] usb 1-1.4: GSM modem (1-port) converter now attached to ttyUSB0 [ 4419.992446] option 1-1.4:1.1: GSM modem (1-port) converter detected [ 4419.994522] usb 1-1.4: GSM modem (1-port) converter now attached to ttyUSB1 [ 4419.996984] option 1-1.4:1.2: GSM modem (1-port) converter detected [ 4420.001650] usb 1-1.4: GSM modem (1-port) converter now attached to ttyUSB3 [ 4420.007196] option 1-1.4:1.3: GSM modem (1-port) converter detected [ 4420.013768] usb 1-1.4: GSM modem (1-port) converter now attached to ttyUSB4
(5)参考文章http://blog.csdn.net/maeom/article/details/6583858