当前位置:编程学习 > C/C++ >>

[源码级分析][android4.0]sdp Server的启动分析

SDP server是蓝牙启动过程中的一个非常重要部分。本文简单介绍一下这个函数的实现。
 
int start_sdp_server(uint16_t mtu, const char *did, uint32_t flags)  
{  
    //这里传入的flags是SDP_SERVER_COMPAT  
//所以compat值是有效的,master应该是0  
    int compat = flags & SDP_SERVER_COMPAT;  
    int master = flags & SDP_SERVER_MASTER;  
    GIOChannel *io;  
  
    info("Starting SDP server");  
    //初始化server,详细见2.3.4.1  
    if (init_server(mtu, master, compat) < 0) {  
        error("Server initialization failed");  
        return -1;  
    }  
    //did就是传入的device id,也就是main_opts.deviceid,他是根据DeviceID这个值来设置的,根据我们的main.conf,他的值就是android:generic:1.5  
    if (did && strlen(did) > 0) {  
        const char *ptr = did;  
        uint16_t vid = 0x0000, pid = 0x0000, ver = 0x0000;  
        //vid=android  
        //pid=generic  
        //version=1.5  
        vid = (uint16_t) strtol(ptr, NULL, 16);  
        ptr = strchr(ptr, ':');  
        if (ptr) {  
            pid = (uint16_t) strtol(ptr + 1, NULL, 16);  
            ptr = strchr(ptr + 1, ':');  
            if (ptr)  
                ver = (uint16_t) strtol(ptr + 1, NULL, 16);  
            //注册device id,仍然是一个service record的注册,不详细分析了,也会有UUIDS的property change哦  
            register_device_id(vid, pid, ver);  
        }  
    }  
//对刚刚建的L2cap通道进行监听  
    io = g_io_channel_unix_new(l2cap_sock);  
    g_io_channel_set_close_on_unref(io, TRUE);  
    //也就是accept了,处理函数是io_accept_event  
    l2cap_id = g_io_add_watch(io, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,  
                    io_accept_event, &l2cap_sock);  
    g_io_channel_unref(io);  
    //若是compat,则对unix_sock进行监听,处理函数同样是io_accept_event  
    if (compat && unix_sock > fileno(stderr)) {  
        io = g_io_channel_unix_new(unix_sock);  
        g_io_channel_set_close_on_unref(io, TRUE);  
  
        unix_id = g_io_add_watch(io,  
                    G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,  
                    io_accept_event, &unix_sock);  
        g_io_channel_unref(io);  
    }  
  
    return 0;  
}  

 

 
2.3.4.1 init_server
 
         这个从注释来看,就是sdp server的一些初始化,包括创建l2cap和unix socket用于discovery和registerclient来进行独立地访问。具体我们还是从代码的角度来分析:
 
 
static int init_server(uint16_t mtu, int master, int compat)  
{  
    struct l2cap_options opts;  
    struct sockaddr_l2 l2addr;  
    struct sockaddr_un unaddr;  
    socklen_t optlen;  
  
    /* Register the public browse group root */  
    //注册public browse group root,不详细介绍,上面的service record创建中有详细介绍过  
    register_public_browse_group();  
    //注册一个sdp server的service record  
    /* Register the SDP server's service record */  
    register_server_service();  
    //创建L2CAP的socket  
    /* Create L2CAP socket */  
    l2cap_sock = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);  
    if (l2cap_sock < 0) {  
        error("opening L2CAP socket: %s", strerror(errno));  
        return -1;  
    }  
  
    memset(&l2addr, 0, sizeof(l2addr));  
    l2addr.l2_family = AF_BLUETOOTH;  
    //addr 是any  
    bacpy(&l2addr.l2_bdaddr, BDADDR_ANY);  
    //psm是SDP  
    l2addr.l2_psm = htobs(SDP_PSM);  
    //就是把该l2cap和bdaddr_any绑定  
if (bind(l2cap_sock, (struct sockaddr *) &l2addr, sizeof(l2addr)) < 0) {  
        error("binding L2CAP socket: %s", strerror(errno));  
        return -1;  
    }     
    //要做master,其实我们默认配置可选的,所以,这里就不会走到了  
    if (master) {  
        int opt = L2CAP_LM_MASTER;  
        if (setsockopt(l2cap_sock, SOL_L2CAP, L2CAP_LM, &opt, sizeof(opt)) < 0) {  
            error("setsockopt: %s", strerror(errno));  
            return -1;  
        }  
    }  
    //设置mtu,默认传入的mtu是0,也就是使用kernel中的默认配置  
    if (mtu > 0) {  
        memset(&opts, 0, sizeof(opts));  
        optlen = sizeof(opts);  
  
        if (getsockopt(l2cap_sock, SOL_L2CAP, L2CAP_OPTIONS, &opts, &optlen) < 0) {  
            error("getsockopt: %s", strerror(errno));  
            return -1;  
        }  
  
        opts.omtu = mtu;  
        opts.imtu = mtu;  
  
        if (setsockopt(l2cap_sock, SOL_L2CAP, L2CAP_OPTIONS, &opts, sizeof(opts)) < 0) {  
            error("setsockopt: %s", strerror(errno));  
            return -1;  
        }  
    }  
    //开始监听,最多5个,下面就可以accept了  
    if (listen(l2cap_sock, 5) < 0) {  
        error("listen: %s", strerror(errno));  
        return -1;  
    }  
    //compat默认是1  
    if (!compat) {  
        unix_sock = -1;  
        return 0;  
    }  
    //得到bluetooth的控制socket  
//这是和上层socket的一个通信,具体在上层用到的时候,我们再来分析  
        unix_sock = android_get_control_socket("bluetooth");  
        if (unix_sock < 0) {  
                error("Unable to get the control socket for 'bluetooth'");  
                return -1;  
        }  
    //监听  
        if (listen(unix_sock, 5)) {  
                error("Listening on local socket failed: %s", strerror(errno));  
                return -1;  
        }  
  
        info("Got Unix socket fd '%d' from environment", unix_sock);  
}  

 

 
补充:软件开发 , C++ ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,