标准的linux系统一般都不带ble的应用功能,需要客户自己自定义开发,不过一般可以采用开源的bluez架构,目前最新的已经到5.5版本了,我用的5.4版本。
里面包含了bt的各种应用场景,可以作为bt设备,以及ble主设备和从设备功能 ,而我们项目需要将linux系统作为一个ble从设备,所以需要使用peripheral这个文件夹。
attach.c attach.h efivars.c efivars.h gap.c gap.h gatt.c gatt.h log.c log.h main.c
代码逻辑可以从main.c开始分析, 找到其中的gap_start函数。
void gap_start(void)
{
mgmt = mgmt_new_default();
if (!mgmt) {
fprintf(stderr, "Failed to open management socket\n");
return;
}
if (!mgmt_send(mgmt, MGMT_OP_READ_COMMANDS,
MGMT_INDEX_NONE, 0, NULL,
read_commands_complete, NULL, NULL)) {
fprintf(stderr, "Failed to read supported commands\n");
return;
}
}
在这个read_commands_complete函数中找到index_added_event函数,然后进入到read_info_complete函数,在这里会初始化ble的各种配置信息,包括BD地址,以及设备初始化名称。还有其中最为关键的gatt_server_start();
void gatt_server_start(void)
{
struct sockaddr_l2 addr;
if (att_fd >= 0)
return;
att_fd = socket(PF_BLUETOOTH, SOCK_SEQPACKET | SOCK_CLOEXEC,
BTPROTO_L2CAP);
if (att_fd < 0) {
fprintf(stderr, "Failed to create ATT server socket: %m\n");
return;
}
memset(&addr, 0, sizeof(addr));
addr.l2_family = AF_BLUETOOTH;
addr.l2_cid = htobs(ATT_CID);
memcpy(&addr.l2_bdaddr, static_addr, 6);
addr.l2_bdaddr_type = BDADDR_LE_RANDOM;
if (bind(att_fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
fprintf(stderr, "Failed to bind ATT server socket: %m\n");
close(att_fd);
att_fd = -1;
return;
}
if (listen(att_fd, 1) < 0) {
fprintf(stderr, "Failed to listen on ATT server socket: %m\n");
close(att_fd);
att_fd = -1;
return;
}
gatt_db = gatt_db_new();
if (!gatt_db) {
close(att_fd);
att_fd = -1;
return;
}
populate_gap_service(gatt_db);
populate_devinfo_service(gatt_db);
gatt_cache = gatt_db_new();
conn_list = queue_new();
if (!conn_list) {
gatt_db_unref(gatt_db);
gatt_db = NULL;
close(att_fd);
att_fd = -1;
return;
}
mainloop_add_fd(att_fd, EPOLLIN, att_conn_callback, NULL, NULL);
}
这里会初始化gap 以及device的service服务。这些service里配置了ble从设备需要对外发送的信息。
static void populate_gap_service(struct gatt_db *db)
{
struct gatt_db_attribute *service;
bt_uuid_t uuid;
bt_uuid16_create(&uuid, UUID_GAP);
service = gatt_db_add_service(db, &uuid, true, 6);
bt_uuid16_create(&uuid, GATT_CHARAC_DEVICE_NAME);
gatt_db_service_add_characteristic(service, &uuid,
BT_ATT_PERM_READ,
BT_GATT_CHRC_PROP_READ,
gap_device_name_read, NULL, NULL);
gatt_db_service_set_active(service, true);
}
bluez-5.41 CMakeLists.txt src
源代码通过cmake管理,下载路径://download.csdn.net/download/punmpkin/12064879
源码解压之后路径,执行cmake即可,最终生成一个ble_emulator的bin文件,在执行这个bin文件以前需要先将ble功能打开。
需要执行ble_setup.sh脚本,内容如下
# bring up bluetooth
echo 0 > /sys/class/rfkill/rfkill2/state
echo 1 > /sys/class/rfkill/rfkill2/state
brcm_patchram_plus -d --enable_hci --no2bytes --tosleep 200000 --baudrate 3000000 --patchram /lib/firmware/bcm/APM_BCM43456/bcmdhd.hcd /dev/ttymxc2 &
sleep 25
rfkill unblock bluetooth
hciconfig hci0 up
/usr/libexec/bluetooth/bluetoothd --experimental start &
执行这个bin文件,然后在手机设置界面搜索这个ble设备,并点击配对,配对完成之后打开ble 的app,就可以在app里查看信息以及发送数据了。