Adb server 进程改造 (一)

来源:互联网 发布:DNF数据芯片是干嘛用的 编辑:程序博客网 时间:2024/05/22 10:56

在一些特殊的场景下,一个电脑需要连接大量手机,现在的群控 就是一个很好的例子,同时连接50,100 台那是很常见的。但是随之而来的问题就是不稳定,掉线等等。除了PC 的原因之外更多的是adb server 的问题。adb 的源码很复杂,一套代码可以编译出adb,adbd。 adb 又可以区分为client和server。 所以代码还是很复杂的。 于是萌发了个念头,自己通过winusb 和手机直接交互,不再使用adb 了。

一  发现设备

     adb 代码里面有一个find_devices 函数,在usb_windows.cpp 里面,这个就是用来枚举PC 上的所有android 设备的。这部分核心代码可以抄下来,处理逻辑和流程基本一致。


二  数据通信

      adb 代码里面的transport 搞得非常复杂。这一块自己完全重写了。

     transport_usb.cpp 这个文件里面封装了和usb 交互的代码,但是协议需要自己调试。我用了个笨方法,在发包和收包的时候加上日志打印。 adb 有一个函数 dump_packet。 用这个函数可以打印出 发包的重新编译adb ,就可以看到所有的收发包了。


static int remote_read(apacket *p, atransport *t)
{



    if(usb_read(t->usb, &p->msg, sizeof(amessage))){
        D("remote usb: read terminated (message)");
        return -1;
    }


    if(check_header(p, t)) {
        D("remote usb: check_header failed");
        return -1;
    }


    if(p->msg.data_length) {
        if(usb_read(t->usb, p->data, p->msg.data_length)){
            D("remote usb: terminated (data)");
            return -1;
        }
    }


    if(check_data(p)) {
        D("remote usb: check_data failed");
        return -1;
    }


//添加的打印
std::string strOut = dump_packet("usb read", "remote_read", p);
OutputDebugStringA(strOut.c_str());
OutputDebugStringA("\r\n");
    return 0;
}



static int remote_write(apacket *p, atransport *t)
{


//添加的打印
std::string strOut = dump_packet("usb write", "remote_write", p);
OutputDebugStringA(strOut.c_str());
OutputDebugStringA("\r\n");


    unsigned size = p->msg.data_length;

    if(usb_write(t->usb, &p->msg, sizeof(amessage))) {
        D("remote usb: 1 - write terminated");
        return -1;
    }
    if(p->msg.data_length == 0) return 0;
    if(usb_write(t->usb, &p->data, size)) {
        D("remote usb: 2 - write terminated");
        return -1;
    }

    return 0;
}


发送的包格式:

struct amessage {
    uint32_t command;     /* command identifier constant      */
    uint32_t arg0;        /* first argument                   */
    uint32_t arg1;        /* second argument                  */
    uint32_t data_length; /* length of payload (0 is allowed) */
    uint32_t data_check;  /* checksum of data payload         */
    uint32_t magic;       /* command ^ 0xffffffff             */
};

struct apacket
{
    apacket *next;


    size_t len;
    char* ptr;

 //上面三个字段和发包没有关系

    amessage msg;
    char data[MAX_PAYLOAD];
};


最简单交互

1)发送一个A_OPEN 命令,可以附带一些参数。比如 shell 命令等 shell:xxxxx

2)接收到一个A_OKAY命令

3)   接收到A_WRTE数据命令 

4)写入一个 A_OKAY 命令

5)接收到 A_CLSE 命令

6)回复一个A_CLSE 命令。 交互完成


下回接着写吧

QQ:2506314894 





阅读全文
0 0
原创粉丝点击