[android源码分析]sdp Server的启动分析

SDP server是蓝牙启动过程中的一个非常重要部分。本文简单介绍一下这个函数的实现。


[cpp] view plaincopy
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来进行独立地访问。具体我们还是从代码的角度来分析:


[cpp] view plaincopy
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);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值