BLE in Linux : Set a Simple Peripheral

Resuming from last article , I modify the bluez code to be a simple peripheral (GATT server).

Step 0.

download the last bluez .

and

Step 1.

use the parameters to configurate it.

[email protected]:~/sandbox/bluez-5.32/src$./configure --enable-experimental --enable-maintainer-mode --prefix=$PWD/built CFLAGS="$CFLAGS -Wno-sign-compare -Wno-unused-function"

If you encounter some error like that :

configure: error: libical is required

or

checking for UDEV... no
configure: error: libudev >= 172 is required

just install those libraries. I note here, in fedora, the libudev has been included in systemd package, you should use that command line:

[email protected]:~/sandbox/bluez-5.32/src$sudo yum install systemd-devel

To install libudev-dev.

After configuration has been done, the building should be passed without error.

Step2.

Stop current bluetoothd program:

In fedora :

[email protected]:~/sandbox/bluez-5.32/src$sudo killall -p bluetoothd

In Ubuntu :

[email protected]:~/sandbox/bluez-5.32/src$sudo service bluetooth  status
bluetooth start/running, process 2619

[email protected]:~/sandbox/bluez-5.32/src$ sudo service bluetooth stop
bluetooth stop/waiting

Then, goto the src folder under your bluez package, and execute that:

[[email protected] src]$ sudo ./bluetoothd -p xx -n

If the output log be :

bluetoothd[12465]: Bluetooth daemon 5.30
bluetoothd[12465]: Starting SDP server
bluetoothd[12465]: Bluetooth management interface 1.7 initialized
bluetoothd[12465]: Failed to obtain handles for "Service Changed" characteristic
bluetoothd[12465]: Failed to register org.bluez.LEAdvertisingManager1
bluetoothd[12465]: Failed to register LEAdvertisingManager1 interface for adapter
bluetoothd[12465]: Not enough free handles to register service
bluetoothd[12465]: gatt-example-adapter-driver: Input/output error (5)
bluetoothd[12465]: Not enough free handles to register service
bluetoothd[12465]: Error adding Link Loss service
bluetoothd[12465]: Not enough free handles to register service
bluetoothd[12465]: Not enough free handles to register service
bluetoothd[12465]: Not enough free handles to register service
bluetoothd[12465]: Current Time Service could not be registered
bluetoothd[12465]: gatt-time-server: Input/output error (5)
bluetoothd[12465]: Not enough free handles to register service
bluetoothd[12465]: Not enough free handles to register service
bluetoothd[12465]: Sap driver initialization failed.
bluetoothd[12465]: sap-server: Operation not permitted (1)
bluetoothd[12465]: Endpoint registered: sender=:1.122 path=/MediaEndpoint/A2DPSource
bluetoothd[12465]: Endpoint registered: sender=:1.122 path=/MediaEndpoint/A2DPSink

That is,  the gatt-server start fall. The only solution I know currently, is to use the Bluez version which is not later than
5.28. please back to Step 0, use version 5.28 and do all again.

if your result be :

[[email protected] src]$ sudo ./bluetoothd -p xx -n
bluetoothd[31541]: Bluetooth daemon 5.28
bluetoothd[31541]: Starting SDP server
bluetoothd[31541]: Ignoring (cli) hostname
bluetoothd[31541]: Ignoring (cli) wiimote
bluetoothd[31541]: Ignoring (cli) autopair
bluetoothd[31541]: Ignoring (cli) policy
bluetoothd[31541]: Ignoring (cli) gatt_example
bluetoothd[31541]: Ignoring (cli) neard
bluetoothd[31541]: Ignoring (cli) sap
bluetoothd[31541]: Ignoring (cli) a2dp
bluetoothd[31541]: Ignoring (cli) avrcp
bluetoothd[31541]: Ignoring (cli) network
bluetoothd[31541]: Ignoring (cli) input
bluetoothd[31541]: Ignoring (cli) hog
bluetoothd[31541]: Ignoring (cli) health
bluetoothd[31541]: Ignoring (cli) gap
bluetoothd[31541]: Ignoring (cli) scanparam
bluetoothd[31541]: Ignoring (cli) deviceinfo
bluetoothd[31541]: Ignoring (cli) alert
bluetoothd[31541]: Ignoring (cli) time
bluetoothd[31541]: Ignoring (cli) proximity
bluetoothd[31541]: Ignoring (cli) thermometer
bluetoothd[31541]: Ignoring (cli) heartrate
bluetoothd[31541]: Ignoring (cli) cyclingspeed
bluetoothd[31541]: Ignoring (cli) external_dummy
bluetoothd[31541]: Bluetooth management interface 1.7 initialized

Congratulation, you could go below.

Step 3.

Excute the command :

[[email protected] src]$ sudo ./bluetoothd -p gatt_example -n

And run this script, bleAdvertise:

#!/bin/bash
# ref: http://www.theregister.co.uk/Print/2013/11/29/feature_diy_apple_ibeacons/
set -x
# inquiry local bluetooth device
#hcitool dev
export BLUETOOTH_DEVICE=hci0
#sudo hcitool -i hcix cmd <OGF> <OCF> <No. Significant Data Octets> <iBeacon Prefix> <UUID> <Major> <Minor> <Tx Power> <Placeholder Octets>

#OGF = Operation Group Field = Bluetooth Command Group = 0x08
#OCF = Operation Command Field = HCI_LE_Set_Advertising_Data = 0x0008
#No. Significant Data Octets (Max of 31) = 1E (Decimal 30)
#iBeacon Prefix (Always Fixed) = 02 01 1A 1A FF 4C 00 02 15

export OGF="0x08"
export OCF="0x0008"
#export IBEACONPROFIX="1E 02 01 1A 1A FF 4C 00 02 15"
export IBEACONPROFIX="1E 02 01 16 1A FF 4C 00 02 15"

#uuidgen  could gerenate uuid
export UUID="4a 4e ce 60 7e b0 11 e4 b4 a9 08 00 20 0c 9a 66"
#export UUID="B9 40 7F 30 F5 F8 46 6E AF F9 25 55 6B 57 FE 6D"
#export UUID="76 E8 B4 E0 7E B5 11 E4 B4 A9 08 00 20 0C 9A 66"

export MAJOR="00 01"
export MINOR="00 00"
export POWER="C5 00"

 initialize device
sudo hciconfig $BLUETOOTH_DEVICE up
# disable advertising
sudo hciconfig $BLUETOOTH_DEVICE noleadv
# stop the dongle looking for other Bluetooth devices
sudo hciconfig $BLUETOOTH_DEVICE noscan

sudo hciconfig $BLUETOOTH_DEVICE pscan

#hciconfig $BLUETOOTH_DEVICE iscan
#sudo hciconfig $BLUETOOTH_DEVICE name "i5-3210M "$BLUETOOTH_DEVICE
sudo hciconfig $BLUETOOTH_DEVICE leadv

# advertise
sudo hcitool -i $BLUETOOTH_DEVICE cmd 0x08 0x0008 $IBEACONPROFIX $UUID $MAJOR $MINOR $POWER
#sudo hcitool -i $BLUETOOTH_DEVICE cmd 0x08 0x0006 A0 00 A0 00 00 00 00 00 00 00 00 00 00 07 00
#sudo hcitool -i $BLUETOOTH_DEVICE cmd 0x08 0x000a 01

#sudo hciconfig $BLUETOOTH_DEVICE leadv
#sudo hciconfig $BLUETOOTH_DEVICE pscan
echo "complete" 

You should be able to use your moblie appication (BLE scanner for android, LightBlue for iOS)

to scan and connect to this Bluez peripheral.

 

 


That Shows the bluez gatt-server works.

Step 4.

Backup the plugin/wiimote.c , and replace that as below code completely:

  
 
/*
 *
 *  BlueZ - Bluetooth protocol stack for Linux
 *
 *  Copyright (C) 2011-2012 David Herrmann <[email protected]>
 *
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <unistd.h>

#include <stdbool.h>

#include <bluetooth/bluetooth.h>
#include <glib.h>

#include "lib/uuid.h"
#include "src/plugin.h"
#include "src/adapter.h"
#include "src/shared/util.h"
#include "src/log.h"
#include "attrib/gattrib.h"
#include "attrib/gatt-service.h"
#include "attrib/att.h"
#include "attrib/gatt.h"
#include "attrib/att-database.h"
#include "src/attrib-server.h"

#define MAX_STR_LEN       (256)

#define SIMPLE_SVC_UUID      0xfff0
#define SIMPLE_READ1_CHAR_UUID    0xfff1
#define SIMPLE_READ2_CHAR_UUID    0xfff2
#define SIMPLE_WRITE_CHAR_UUID    0xfff3
#define SIMPLE_NOTIFY_CHAR_UUID    0xfff4

static char read1Data[MAX_STR_LEN];
static char read2Data[MAX_STR_LEN];

static int notifyData;

static uint8_t SimpleCharacteristic1Read(struct attribute *a,
      struct btd_device *device, gpointer user_data)
{
 struct btd_adapter *adapter;

 printf("__FILE__ = %s, __FUNCTION__ = %s, __LINE__ =%d\n",
  __FILE__, __FUNCTION__, __LINE__);

 adapter = user_data;

 attrib_db_update(adapter, a->handle, NULL,
  (uint8_t*)&read1Data[0], strlen(&read1Data[0]), NULL);

 return 0;
}/*Characteristic1Read*/      

static uint8_t SimpleCharacteristic2Read(struct attribute *a,
      struct btd_device *device, gpointer user_data)
{
 struct btd_adapter *adapter;

 printf("__FILE__ = %s, __FUNCTION__ = %s, __LINE__ =%d\n",
  __FILE__, __FUNCTION__, __LINE__);

 adapter = user_data;

 attrib_db_update(adapter, a->handle, NULL,
  (uint8_t*)&read2Data[0], strlen(&read2Data[0]), NULL);

 return 0;
}/*Characteristic2Read*/ 

static uint8_t SimpleCharacteristicWrite(struct attribute *a,
      struct btd_device *device, gpointer user_data)
{

 unsigned char data[MAX_STR_LEN];
 int i;

 printf("__FILE__ = %s, __FUNCTION__ = %s, __LINE__ =%d\n",
  __FILE__, __FUNCTION__, __LINE__);

 memset(&data[0], 0, MAX_STR_LEN);

 memcpy(&data[0], a->data, a->len);

 printf("written data : %s \n", &data[0]); 

 for(i = 0; i< a->len;i++)
  printf("%#1x ", (unsigned char)(data[i]));
 printf("\n"); 

 return 0;
}/*CharacteristicWrite*/

static uint8_t SimpleCharacteristicNotify(struct attribute *a,
      struct btd_device *device, gpointer user_data)
{
 struct btd_adapter *adapter;

 adapter = user_data;

 printf("__FILE__ = %s, __FUNCTION__ = %s, __LINE__ =%d\n",
  __FILE__, __FUNCTION__, __LINE__);

 do
 {
  attrib_db_update(adapter, a->handle, NULL,
   (uint8_t*)&notifyData, sizeof(notifyData), NULL);  

  //usleep(1*1000*1000);
  notifyData++;
 }while(0); 

 return 0;
}/*CharacteristicNotify*/

static void RegisterSimpleService(struct btd_adapter *adapter)
{
 bt_uuid_t uuid;
 printf("__FILE__ = %s, __FUNCTION__ = %s, __LINE__ =%d\n",
  __FILE__, __FUNCTION__, __LINE__);

 bt_uuid16_create(&uuid, SIMPLE_SVC_UUID);

 gatt_service_add(adapter, GATT_PRIM_SVC_UUID, &uuid,

 /* characteristic register*/

   /*read 1*/
   GATT_OPT_CHR_UUID16, SIMPLE_READ1_CHAR_UUID,
   GATT_OPT_CHR_PROPS, GATT_CHR_PROP_READ ,
   GATT_OPT_CHR_VALUE_CB, ATTRIB_READ,
     SimpleCharacteristic1Read, adapter,

   /*read 2*/
   GATT_OPT_CHR_UUID16, SIMPLE_READ1_CHAR_UUID,
   GATT_OPT_CHR_PROPS, GATT_CHR_PROP_READ ,
   GATT_OPT_CHR_VALUE_CB, ATTRIB_READ,
     SimpleCharacteristic2Read, adapter,

   /*write*/
   GATT_OPT_CHR_UUID16, SIMPLE_WRITE_CHAR_UUID,
   GATT_OPT_CHR_PROPS, GATT_CHR_PROP_WRITE_WITHOUT_RESP,
   GATT_OPT_CHR_VALUE_CB, ATTRIB_WRITE,
     SimpleCharacteristicWrite, adapter,

   /*NOTIFY*/
   GATT_OPT_CHR_UUID16, SIMPLE_NOTIFY_CHAR_UUID,
   GATT_OPT_CHR_PROPS, GATT_CHR_PROP_READ|GATT_CHR_PROP_NOTIFY,
   GATT_OPT_CHR_VALUE_CB, ATTRIB_READ,
     SimpleCharacteristicNotify, adapter,
   /*end*/
 GATT_OPT_INVALID);

 return ;
}/*RegisterSimpleService*/

#define DEVICEINFO_SVC_UUID     0x180a 

char versionStr[MAX_STR_LEN] = "0.0.0";
char manufacturerStr[MAX_STR_LEN] = "Gaiger";   

static uint8_t SoftwareRevisionStringRead(struct attribute *a,
      struct btd_device *device, gpointer user_data)
{
 struct btd_adapter *adapter;

 printf("__FILE__ = %s, __FUNCTION__ = %s, __LINE__ =%d\n",
  __FILE__, __FUNCTION__, __LINE__);

 adapter = user_data;

 attrib_db_update(adapter, a->handle, NULL,
  (uint8_t*)&versionStr[0], strlen(&versionStr[0]), NULL);

 return 0;
}/*SoftwareRevisionStringRead*/ 

static uint8_t ManufacturerStringRead(struct attribute *a,
      struct btd_device *device, gpointer user_data)
{
 struct btd_adapter *adapter;

 printf("__FILE__ = %s, __FUNCTION__ = %s, __LINE__ =%d\n",
  __FILE__, __FUNCTION__, __LINE__);

 adapter = user_data;

 attrib_db_update(adapter, a->handle, NULL,
  (uint8_t*)&manufacturerStr[0], strlen(&manufacturerStr[0]), NULL);

 return 0;
}/*ManufacturerStringRead*/ 

static void RegisterDeviceInfo(struct btd_adapter *adapter)
{
 bt_uuid_t uuid;
 printf("__FILE__ = %s, __FUNCTION__ = %s, __LINE__ =%d\n",
  __FILE__, __FUNCTION__, __LINE__);

 bt_uuid16_create(&uuid, DEVICEINFO_SVC_UUID);

 gatt_service_add(adapter, GATT_PRIM_SVC_UUID, &uuid,

 /* characteristic register*/

   /*GATT_CHARAC_SOFTWARE_REVISION_STRING*/
   GATT_OPT_CHR_UUID16, GATT_CHARAC_SOFTWARE_REVISION_STRING,
   GATT_OPT_CHR_PROPS, GATT_CHR_PROP_READ ,
   GATT_OPT_CHR_VALUE_CB, ATTRIB_READ,
     SoftwareRevisionStringRead, adapter,

   /*GATT_CHARAC_MANUFACTURER_NAME_STRING*/
   GATT_OPT_CHR_UUID16, GATT_CHARAC_MANUFACTURER_NAME_STRING,
   GATT_OPT_CHR_PROPS, GATT_CHR_PROP_READ ,
   GATT_OPT_CHR_VALUE_CB, ATTRIB_READ,
     ManufacturerStringRead, adapter,
   /*end*/
 GATT_OPT_INVALID);

 return ;
}/*RegisterSimpleService*/

static void update_name(struct btd_adapter *adapter, gpointer user_data)
{
 adapter_set_name(adapter, (char*)user_data);
}/*update_name*/

static int wii_probe(struct btd_adapter *adapter)
{

 update_name(adapter, "SimplePeripherial");
 RegisterDeviceInfo(adapter);
 RegisterSimpleService(adapter);

 return 0;
}/*wii_probe*/

static void wii_remove(struct btd_adapter *adapter)
{

}/*wii_remove*/

/*function pointers*/
static struct btd_adapter_driver wii_driver = {
 .name = "wiimote",
 .probe = wii_probe,
 .remove = wii_remove,
};

static int wii_init(void)
{
 printf("__FUNCTION__ = %s\n", __FUNCTION__);

 memset(&read1Data[0], 0, MAX_STR_LEN);
 memset(&read2Data[0], 0, MAX_STR_LEN);
 notifyData = 0;

 snprintf(&read1Data[0], MAX_STR_LEN, "it is read 1");
 snprintf(&read2Data[0], MAX_STR_LEN, "it is read 2");

 return btd_register_adapter_driver(&wii_driver);
}

static void wii_exit(void)
{
 printf("__FUNCTION__ = %s\n", __FUNCTION__);
 btd_unregister_adapter_driver(&wii_driver);
}

BLUETOOTH_PLUGIN_DEFINE(wiimote, VERSION,
  BLUETOOTH_PLUGIN_PRIORITY_LOW, wii_init, wii_exit)

 

And re-compiler the bluez library (you could just delete plugins/bluetoothd-wiimote.o and

type make again to boost the compilation time).

Step 5.

Similar with Step 3

Execute the command line under src folder:

[[email protected] src]$ sudo ./bluetoothd -p wiimote -n

And Run the BleAdvertise script again : you may need to run it twice, to ensure that has

been executed indeedly.

Now you could use your BLE Scanner or LightBlue to confirm your Pheripheral has been run:





Known Insuffiecient :

If a central device (moblie) access the Notify characteristic, the bluez peripheral would  be led to crash.

After the disconneciton event occurs, the Bluez perihpheral would not start again, it is,

You need to run the BleAdvertise script again.

 

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-13 02:25:11

BLE in Linux : Set a Simple Peripheral的相关文章

USB Gadget API for Linux

USB Gadget API for Linux Author: David Brownell Date: 20 August 2004 Introduction This document presents a Linux-USB “Gadget” kernel mode API, for use within peripherals and other USB devices that embed Linux. It provides an overview of the API struc

如何利用mono把.net windows service程序迁移到linux上

How to migrate a .NET Windows Service application to Linux using mono? 写在最前:之所以用要把windows程序迁移到Linux上,主要是由于一些成本问题,这个就不多解释了. 如何把之前用.net写的windows服务程序迁移到linux上运行.答案是有很多种的,今天我只提一下mono(我只实验了mono,呵呵). 如何在Linux部署mono,并成功的运行.net程序,还请大家多多查询吧,我在这方面也只是搭建成功了,遇到的问

第32课 Linux内核链表剖析

1. Linux内核链表的位置及依赖 (1)位置:{linux-2.6.39}\\include\linux\list.h (2)依赖 ①#include<linux\types.h> ②#include<linux\stddef.h> ③#include<linux\poison.h> ④#include<linux\prefetch.h> 2. 移植及注意事项 (1)清除文件间的依赖:剥离依赖文件中与链表实现相关的代码 (2)清除与平台相关代码(GNU

Linux系统实时数据同步inotify+rsync

一.inotify简介 inotify是Linux内核的一个功能,它能监控文件系统的变化,比如删除.读.写和卸载等操作.它监控到这些事件的发生后会默认往标准输出打印事件信息.要使用inotify,Linux内核版本必须是大于2.6.13,在这之前的内核都没有这个功能.我们可以利用inotify去监控我们要监控的资源,当资源发生变化时,我们扑捉它的事件,从而触发同步数据等操作. 二.inotify软件介绍 inotify是内核的一个功能,众所周知内核的功能我们必须要配合工具才能使用,通常情况下用户

Windows Phone 8.1 驱动开发——SPB 简介

SPB是Simple Peripheral Bus的简称,直译过来就是简单外设总线,它包括I2C总线.SPI总线.SPB是在Windows 8以后才被驱动支持的,而在之前如果系统想访问I2C外围设备,则只能通过BIOS程序间接的访问,没法直接访问外设寄存器.在系统启动时,ACPI固件会根据配置表扫描SPB设备,并将它们的资源信息传递给PnP(即插即用设备)管理器,这些资源就包括I2C从设备地址.I2C总线时钟频率以及该设备的中断号.需要注意的一点,在ACPI资源配置表中,是不允许使用Memory

Configure mutiple IBM HTTP Server / Other Apache based WEB server on 1 physical server (Section 2)

Continue from the last article...... 2) Confirmed the 80 port of the new added IP is not listened by any other services.   Why need to test this? This is to ensure the 80/443 port of the new created IP is not listened by any other application. Test m

Docker Resources

Menu Main Resources Books Websites Documents Archives Community Blogs Personal Blogs Videos Related Projects OS Virtual Machine Competitors Management Tools Paas Platforms Integration Projects Monitoring Networking Continuous Integration Development

SOLVED: GATT callback fails to register

I finally figured this problem out. The device I am using is a Samsung Galaxy S4 and the actual problem (thanks Wibble for guidance in your answer, but you are slightly off in your conclusion) appears to be a threading issue. In Wibble's answer, he s

如何在ubuntu下使用samba创建共享

快速简单的创建共享,比网上那些乱七八糟过时的文档强太多 原文地址: https://help.ubuntu.com/community/How%20to%20Create%20a%20Network%20Share%20Via%20Samba%20Via%20CLI%20%28Command-line%20interface/Linux%20Terminal%29%20-%20Uncomplicated,%20Simple%20and%20Brief%20Way! How to Create a