Yang Shanghai

人与人的差距取决于工作、睡觉之外的8个小时!
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Android4.0实现usb类3g上网卡Modem模式自动转换

Posted on 2014-05-04 21:35  yangshanghai  阅读(916)  评论(0)    收藏  举报

环境系统: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