下冰雹 · 2021年12月29日

全志R329如何解决调用Bluez mainloop_add_fd函数失败的问题?

请问全志R329如何解决调用Bluez mainloop_add_fd函数失败的问题?

1 个回答 得票排序 · 时间排序
极术小姐姐 · 2021年12月29日
本回答来源全志R329如何解决调用Bluez mainloop_add_fd函数失败的问题?

可参考以下方法

问题背景

Tina系统使用的蓝牙协议栈为开源bluez协议栈,在上层应用开发的时候会常常使用mainloop_add_fd函数,尤其是btmanager中也有很多模块是调用了该函数。

问题描述

在使用Tina btmanager ble模块时,启动异常,提示打印"Failed to add listen socket(11),error(-38)",详细如下:

1607334876.975885: [gatt_run:355]:  ++
1607334876.976066: [l2cap_le_att_listen:263]:  ++
1607334876.976208: [l2cap_le_att_listen:296]:  Started listening on ATT channel
1607334876.976311: [gatt_run:371]:  sockfds 12 13
1607334876.976820: [gatt_set_bta_mainloop_id:27]:  tid: 3047021836
1607334876.977276: [gatt_run:373]:  tid 3047021836
1607334876.977541: [gatt_set_bta_cmd_fd:39]:  gatt_commfds 12 13
1607334876.977884: [gatt_bta_register_handler:44]:  ++
1607334876.979351: [gatt_run:383]:  Failed to add listen socket(11),error(-38)

问题分析
"[gatt_run:383]: Failed to add listen socket(11),error(-38)"该行错误打印,提示的源代码如下:

ret = mainloop_add_fd(fd, EPOLLIN, server_listen_cb, server, NULL);
if (ret < 0) {
BTMG_ERROR("Failed to add listen socket(%d),error(%d)\n",fd,ret);
close(fd);
netcfg_state = 0;
return NULL;
}

从上可以判断是调用了mainloop_add_fd函数异常,该函数是链接的开源bluez协议栈中的库,于是搜索了bluez中关于mainloop_add_fd的实现,发现实现该函数有有三处地方,分别是

(1)src/shared/mainloop-ell.c:编入到src/.libs/libshared-ell.a库中。

int mainloop_add_fd(int fd, uint32_t events, mainloop_event_func callback,
void *user_data, mainloop_destroy_func destroy)
{
return -ENOSYS;
}

(2)src/shared/mainloop-glib.c:编入到src/.libs/libshared-glib.a库中。

int mainloop_add_fd(int fd, uint32_t events, mainloop_event_func callback,
void *user_data, mainloop_destroy_func destroy)
{
return -ENOSYS;
}

(3) src/shared/mainloop.c:编入到src/.libs/libshared-mainloop.a库中。

int mainloop_add_fd(int fd, uint32_t events, mainloop_event_func callback,
void *user_data, mainloop_destroy_func destroy)
{
struct mainloop_data *data;
struct epoll_event ev;
int err;
if (fd < 0 || fd > MAX_MAINLOOP_ENTRIES - 1 || !callback)
return -EINVAL;
data = malloc(sizeof(*data));
if (!data)
return -ENOMEM;
memset(data, 0, sizeof(*data));
data->fd = fd;
data->events = events;
data->callback = callback;
data->destroy = destroy;
data->user_data = user_data;
memset(&ev, 0, sizeof(ev));
ev.events = events;
ev.data.ptr = data;
err = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, data->fd, &ev);
if (err < 0) {
free(data);
return err;
}
mainloop_list[fd] = data;
return 0;
}

而 Failed to add listen socket(11),error(-38)提示-38正好是"-ENOSYS", 在errno.h中有定义

#define ENOSYS 38 /* Function not implemented */

所以排查到是链接的函数不对,应用程序中同时链接了libshared-glib.a和libshared-mainloop.a,最后取用的是libshared-glib.a,应该使用的是libshared-mainloop.a。

解决办法

在使用mainloop_add_fd函数的时候,要尤其注意,要链接使用正确的库。使用libshared-mainloop.a而不是libshared-glib.a和libshared-ell.a。

你的回答
关注数
1
收藏数
0
浏览数
2673
极术小姐姐
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息