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); }
若您觉得该文章对您有帮助,请在下面用鼠标轻轻按一下“顶”,哈哈~~·