FORUMS
Remove All Ads from XDA

[GUIDE] How to port Bluez to Kitkat, Lollipop & Marshmallow

1,634 posts
Thanks Meter: 5,404
 
By daniel_hk, Recognized Contributor on 8th February 2014, 10:24 AM
Post Reply Email Thread
Introduction
When the bluetooth stack changed to Bluedroid in Android 4.2, it was a nightmare to some of the old devices like my GT-P6800. I didn't have any experience in Bluetooth before so I did what I know. I spent weeks to revert the 4.2 platform to Bluez. Even though I succeeded, it probably not doable for 4.3 and later.
Last Nov. I found that bluez.org announced support for Andriod in Sep. It gave me hope again! Thanks to the bluez team! The principle is straight forward - Implement the functions defined in "hardware/libhardware/include/hardware/bluetooth.h". That's what I thought but I didn't have enough knowledge nor confidence to try...
After studying for a while, I started porting bluez to Android 4.4 last Christmas. It was frustrated and helpless. Although the lastest Android 4.4 example for Mako and Flo are out, they don't help much. A bunch of prebuilt kernel objects surely doesn't help! Porting for those devices already having bluedroid support is meaningless to most of us too...
Building the bluez hal and daemon are straight forward but how to make it really work is another story. After a few painful and frustrated weekends, I finally managed to pull everything together. I can start/stop and pairing bluetooth devices in the platform now. And here I'm, sharing my experiences. I think there might be better way and I welcome any corrections.
My p6800 has CSR bluetooth chip which has no bluedroid support. I think the same approach would work for other chips too. Cheers!

** All paths assume your rom source dircetory to be the current directory **

1. Downlaod and Build
Bluez.org already has its own tutorial. I just summerize and list my suggestions.

1.1 local manifest
I learned my lesson and would avoid touching the "manifest.xml".
Add the following lines to your ".repo/local_manifests/local_menifest.xml"
For cm11, omni, etc.
Code:
  <remote name="gcode" fetch="https://code.google.com/p/"/>
  <remote name="korg" fetch="git://git.kernel.org/pub/scm/bluetooth/"/>
  <remove-project name="android_external_bluetooth_bluedroid"/>
  <project remote="korg" path="external/bluetooth/bluez" name="bluez" group="pdk" revision="master"/>
  <project remote="korg" path="external/bluetooth/sbc" name="sbc" group="pdk" revision="master"/>
  <project remote="gcode" path="external/bluetooth/glib" name="aosp-bluez.glib" group="pdk" revision="master"/>
For AOSP, replace the remove-project with:
Code:
  <remove-project name="platform/external/bluetooth/bluedroid"/>
After repo sync, bluez will replace bluedroid.

1.2 patching bionic
The patches for bionic are simple. Mainly by adding two flags and the function epoll_create1().
Bionic may vary from ROMs. It is wiser to patch the bionic of your ROM manually. You may follow the changes of the two commits below:
https://code.google.com/p/aosp-bluez...latform-bionic
https://code.google.com/p/aosp-bluez...latform-bionic

1.3 neccessary tools
There are tools in "external/bluetooth/bluez/tools". You may need some of those tools for setup or testing.
This is the "Android.mk" I added to "external/bluetooth/bluez/tools". You may cheery pick the required tools for your device.
Code:
#
# Bluetooth tools for setup and debug
#			daniel_hk
LOCAL_PATH := external/bluetooth

# Retrieve BlueZ version from configure.ac file
BLUEZ_VERSION := $(shell grep ^AC_INIT $(LOCAL_PATH)/bluez/configure.ac | cpp -P -D'AC_INIT(_,v)=v')

# Specify pathmap for glib
#pathmap_INCL += glib:external/bluetooth/glib

# Specify common compiler flags
BLUEZ_COMMON_CFLAGS := -DVERSION=\"$(BLUEZ_VERSION)\" \
	-DSTORAGEDIR=$(ANDROID_STORAGEDIR) \

# Disable warnings enabled by Android but not enabled in autotools build
BLUEZ_COMMON_CFLAGS += -Wno-pointer-arith -Wno-missing-field-initializers

# @ daniel, extra tools for CSR
ifeq ($(BOARD_HAVE_BLUETOOTH_CSR),true)

#
# bccmd
#
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= \
	bluez/lib/hci.c \
	bluez/lib/bluetooth.c \
	bluez/tools/bccmd.c \
	bluez/tools/csr.c \
	bluez/tools/csr_3wire.c \
	bluez/tools/csr_bcsp.c \
	bluez/tools/csr_hci.c \
	bluez/tools/csr_h4.c \
	bluez/tools/csr_usb.c \
	bluez/tools/ubcsp.c

LOCAL_CFLAGS := $(BLUEZ_COMMON_CFLAGS)

LOCAL_C_INCLUDES:=\
	$(LOCAL_PATH)/bluez \
	$(LOCAL_PATH)/bluez/lib \
	$(LOCAL_PATH)/bluez/tools \
	$(LOCAL_PATH)/bluez/src \
	$(LOCAL_PATH)/bluez/src/shared \

LOCAL_MODULE:=bccmd

include $(BUILD_EXECUTABLE)

#
# sdptool
#
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= \
	bluez/lib/hci.c \
	bluez/lib/bluetooth.c \
	bluez/lib/sdp.c \
	bluez/tools/sdptool.c \
	bluez/src/sdp-xml.c

LOCAL_CFLAGS := $(BLUEZ_COMMON_CFLAGS)

LOCAL_C_INCLUDES:=\
	$(LOCAL_PATH)/bluez \
	$(LOCAL_PATH)/bluez/lib \
	$(LOCAL_PATH)/bluez/tools \
	$(LOCAL_PATH)/bluez/src \
	$(LOCAL_PATH)/bluez/src/shared \

LOCAL_C_INCLUDES += \
	$(call include-path-for, glib) \
	$(call include-path-for, glib)/glib \

LOCAL_SHARED_LIBRARIES := \
	libglib \

LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE:=sdptool

include $(BUILD_EXECUTABLE)
endif
1.4 patches for CyanogenMod 11
In CyanogenMod 11, the function "pin_request_cb" has one more argument. The following file need some patches:
in the file "external/bluetooth/bluez/android/hal-bluetooth.c"
Code:
** in function: handle_pin_request
	bt_hal_cbacks->pin_request_cb(addr, name, ev->class_of_dev, 0);	// @ daniel, added 0 for cm11
in the file "external/bluetooth/bluez/android/client/if-bt.c"
Code:
** in function: pin_request_cb
static void pin_request_cb(bt_bdaddr_t *remote_bd_addr, bt_bdname_t *bd_name,
						uint32_t cod, uint8_t secure)	// @ daniel, added secure from cm11
{
	/* Store for command completion */
	bt_bdaddr_t2str(remote_bd_addr, last_remote_addr);
	pin_request_addr = *remote_bd_addr;

	haltest_info("%s: remote_bd_addr=%s bd_name=%s cod=%06x secure=%02x\n", __func__,
					last_remote_addr, bd_name->name, cod, secure);	// @ daniel, added
	terminal_prompt_for("Enter pin: ", pin_request_answer);
}
2. kerenl patch
In the "README" inside "external/bluetooth/bluez/android", there is the line:
Quote:

Minimal required version of management interface is 1.3. This corresponds to Linux 3.9 but latest available version is recommended.

If you have tried porting bluez and fail, check the logcat. You might probably found the error "Failed to access management interface". This is the key making bluez to work! Sadly, most of the existing Android kernels are before ver. 3.9! The latest kernel we have might be ver. 3.4.x and the kernel for my p6800 is ver. 3.0.x! As the above line stated, Bluez5 requires the kernel to have management interface 1.3 or above. That means we have to backport the bluetooth subsystem from at least ver. 3.9. I backport my kernel with the latest (3.13-1) found in linux-foundation.org: http://drvbp1.linux-foundation.org/~...tml/backports/
It was a tough and painful job! There are lots of changes. I finally got a bootable backport kernel in 2 days!
I packed my patches in kernel-3.0.x-backport-3.13-1.zip. This patch is for my 3.0.x kernel which might be different from other 3.0.x kernels. Don't have time to tidy up but it works for me. Although I've done the hard part, it still requires extra patience to get yours done. Prepare yourself...

2.1 Backport 3.13-1 to your kernel
  • Direct replacements.
    Replace the following folders in the zip with the one in your kernel source:
    drivers/bluetooth
    net/bluetooth
    include/net/bluetooth
    include/backport
  • Direct replacement might not work!
    Check include/linux in the zip
    For each file,
    add the required part (which I delimited with comments @ daniel and //@ ) to the corresponding file in your kernel source.
    If file not exist,
    copy the files to your kernel source
  • Check your defconfig. As README suggested, defconfig should have:
    CONFIG_BT
    CONFIG_BT_RFCOMM
    CONFIG_BT_RFCOMM_TTY
    CONFIG_BT_BNEP
    CONFIG_BT_BNEP_MC_FILTER
    CONFIG_BT_BNEP_PROTO_FILTER
    CONFIG_BRIDGE
    CONFIG_UHID
    # and for CSR chips
    CONFIG_BT_HCIUART=y
    CONFIG_BT_HCIUART_H4=y
    CONFIG_BT_HCIUART_BCSP=y
You probably need to compile the kernel many times to get it work. I worte a build script build-k.zip to compile the kernel only.
Copy build-k to your ROM source directory and type:
Code:
./build-k <your device>
2.2 Backport-hid-generic to your kernel
There is another patch in the Mako-kern example:
https://code.google.com/p/aosp-bluez...-lge-mako-kern
Don't know if it is required for your kernel but adding this patch seems doesn't hurt.

If you do it right, you may find "Bluetooth management interface 1.4" in your logcat. Congratulation! Bluetoothd can connect to your kernel now!

3. initialization and setup
Take a look at your devices tree's TARGET_CUSTOM_BLUEDROID definition. If you have a file assigned, it supposed to replace the file "bluetooth.c" in the "system/bluetooth" project. In Android 4.4, this project is no longer exist/needed. Before Android 4.2, this project provide the functions "bt_enable()" and "bt_disable()" which are called in the frameworks. These functions will tell you how to "power on", "power off" and init your device's Bluetooth chip.
For CSR:
  • set /sys/class/rfkill/rfkill0/state to 1 ("power on")
  • start the service "bccmd" which will setup the chip and upload a PSConfig to the chip
  • start the service "hciattach" which init the port hci0 with parameters
  • start the service "bluetoothd" which is the bluez stack
The services are defined in init.rc or init.${ro.hardware}.rc.

3.1 Test your device and the tools
Disable the "import init.bluetooth.rc" line if you have added it before.
Example for CSR chips. Follow the steps in bt_enable. In a terminal or via adb:
Code:
$ su				-- root user is required
# echo "1" > /sys/class/rfkill/rfkill0/state
# bccmd -t bcsp -d /dev/ttySAC0 -b 115200 psload -r /system/etc/PSConfig_8811.psr
  Loading 0x212c ... done
  Loading 0x212d ... done
	...
  Loading PSKEY_CLOCK_REQUEST_ENABLE ... done
  Loading PSKEY_UART_HOST_WAKE ... done
# hciattach -p /dev/ttySAC0 bcsp 3000000 flow
  Device setup complete
# hciconfig hci0 up
# hcitool scan			-- turn on a device's bluetooth for testing
	Nexus 4			-- found the device means bluetooth is working now
3.2 Init sequence
In Bluez5, the HAL (bluetooth.default.so) driver will be loaded at boot and the daemon (bluetoothd) will be started inside too. Take a look at the function "bool hal_ipc_init(void)" in "external/bluetooth/bluez/android/hal-ipc.c". You may find how the HAL is init which is different from pre-4.2 Androids.
In order to get the daemon (bluetoothd) to work, we have to init the chip before that.
I worte a shell script init.bt.sh to init the chip/port:
Code:
#!/system/bin/sh
# modified by daniel_hk

LOG_TAG="CSR8811-HCI"
BTUART_PORT=/dev/ttySAC0
BTSTATE=/sys/class/rfkill/rfkill0/state
PSCONFIG=/system/etc/PSConfig_8811.psr

logi ()
{
  /system/bin/log -t $LOG_TAG -p i ": [email protected]"
}

loge ()
{
  /system/bin/log -t $LOG_TAG -p e ": [email protected]"
}

failed ()
{
  loge "$1: exit code $2"
  exit $2
}

#Enable power of csr chip
echo "1" > $BTSTATE

# PS Config with bccmd
logwrapper /system/bin/bccmd -t bcsp -d $BTUART_PORT -b 115200 psload -r $PSCONFIG
case $? in
  0) logi "bccmd init port....done";;
  *) failed "port: $BTUART_PORT - bccmd failed" $?;
     exit $?;;
esac

# attach HCI 
logwrapper /system/bin/hciattach -p $BTUART_PORT bcsp 3000000 flow
case $? in
  0) logi "hci attached to : $BTUART_PORT";;
  *) failed "port: $BTUART_PORT - hciattach failed" $?;
     exit $?;;
esac

exit 0
It takes time for bccmd and hciattach to complete. Putting them in seperate services requires delay in between. I think it is better to run them as application one after one.

A new rc file init.${ro.hardware}.bt.rc is created and need to be imported in your init.${ro.hardware}.rc
Code:
on boot
    start bt_init

on property:init.svc.bluetoothd=running
    start hci0_up

on property:init.svc.bluetoothd=stopped
    start hci0_down

service bt_init /system/bin/logwrapper /system/bin/sh /system/etc/init.bt.sh
    class main
    user root
    group bluetooth net_bt_admin system
    disabled
    oneshot

service hci0_up /system/bin/logwrapper /system/xbin/hciconfig hci0 up
    class main
    group bluetooth
    disabled
    oneshot

service hci0_down /system/bin/logwrapper /system/xbin/hciconfig hci0 down
    class main
    group bluetooth
    disabled
    oneshot

import init.bluetooth.rc
Since HAL (bluetooth.default.so) is started quite early, I start the service bt_init at boot. I have tried a few places, daemon might timed out before bt_init finish. It also seems no need to repeat the init process everytime.
When bluetoothd is running (system/core/init will set the property init.svc.bluetoothd=running), set hci0 up with hciconfig. And when the service bluetoothd is stopped, set hci0 down with hciconfig. There might be a better way. Please indulge me if something better coming up.

You may turn ON/OFF bluetooth in settings now. Pairing and file transfer is working too.

4. Further porting
Take a look at the function get_profile_interface() in the file external/bluetooth/bluez/android/hal-bluetooth.c. Some interfaces which frameworks requested are missing.
eg.
Bluetooth Handsfree interface
Bluetooth Map Client Interface
Bluetooth Health Interface
Bluetooth GATT Interface
Update: Fully support for Kitkat now. Check the README inside the android folder for detail.

As I mentioned before, I'm new to bluetooth. Further reading is required for me to fix other services. I also don't have enough time now. I have to process the stuck works after the Chinese New Year holiday. Hoping I can continue by the end of Feb. In the mean time, I hope someone have better knowledge may help fix other services.

For those devices don't have bluedroid support, we have a chance to carry on now!
Attached Thumbnails
Click image for larger version

Name:	Screenshot_2014-02-07-12-55-39.png
Views:	4617
Size:	57.3 KB
ID:	2566469  
The Following 30 Users Say Thank You to daniel_hk For This Useful Post: [ View ] Gift daniel_hk Ad-Free
 
 
8th February 2014, 10:26 AM |#2  
daniel_hk's Avatar
OP Recognized Contributor
Flag Hong Kong
Thanks Meter: 5,404
 
Donate to Me
More
[GUIDE] Porting Bluez to Marshmallow
Check the modified Bluez in my github.
It has been tested with Omni6 (Android-6.0.1_r3)
You have to remove system_bt in local_manifest.xml (similar to bluedroid, check post #1 for detail)

CM needs extra modifications. Will be available after testing.
The Following 2 Users Say Thank You to daniel_hk For This Useful Post: [ View ] Gift daniel_hk Ad-Free
9th February 2014, 03:58 PM |#3  
Senior Member
Flag Bangalore
Thanks Meter: 16,185
 
Donate to Me
More
Nice , Xperia Novathor devs also working on stable bluez
@95A31
The Following 2 Users Say Thank You to percy_g2 For This Useful Post: [ View ] Gift percy_g2 Ad-Free
9th February 2014, 04:46 PM |#4  
Senior Member
Thanks Meter: 2,152
 
Donate to Me
More
Nice guide In CM11 you need also revert this https://github.com/CyanogenMod/andro...00f52830ffe2d8
10th February 2014, 12:21 AM |#5  
daniel_hk's Avatar
OP Recognized Contributor
Flag Hong Kong
Thanks Meter: 5,404
 
Donate to Me
More
Quote:
Originally Posted by 95A31

Nice guide In CM11 you need also revert this https://github.com/CyanogenMod/andro...00f52830ffe2d8

Thanks! Patch in section 1.4 is another alternative for cm11.
10th February 2014, 07:21 AM |#6  
Senior Member
Thanks Meter: 2,152
 
Donate to Me
More
Quote:
Originally Posted by daniel_hk

Thanks! Patch in section 1.4 is another alternative for cm11.

Wops my fault , you have right
18th February 2014, 06:04 PM |#7  
Senior Member
Thanks Meter: 7,599
 
Donate to Me
More
although i dont have my previous device which has csr chip..but those still have csr will get greatly benefited ..your work is incredible......god bless u!!!
keep the good work!!!
22nd February 2014, 01:04 PM |#8  
Senior Member
Thanks Meter: 2,152
 
Donate to Me
More
static void pin_request_cb is defined in external/bluetooth/bluez/android/client/if-bt.c
22nd February 2014, 01:28 PM |#9  
daniel_hk's Avatar
OP Recognized Contributor
Flag Hong Kong
Thanks Meter: 5,404
 
Donate to Me
More
Quote:
Originally Posted by 95A31

static void pin_request_cb is defined in external/bluetooth/bluez/android/client/if-bt.c

yeah, it is also defined in if-bt.c but if you check android/Android.mk, only haltest use it. If you want to build haltest, you need to change if-bt.c too.
Take a look the file android/Android.mk which is the make file for android. bluetooth.default.so which cm11 refered to, use the definition in hal-bluetoth.c.


Sent from my Nexus 7 using Tapatalk
22nd February 2014, 01:32 PM |#10  
Senior Member
Thanks Meter: 2,152
 
Donate to Me
More
Quote:
Originally Posted by daniel_hk

yeah, it is also defined in if-bt.c but if you check android/Android.mk, only haltest use it. If you want to build haltest, you need to change if-bt.c too.
Take a look the file android/Android.mk which is the make file for android. bluetooth.default.so which cm11 refered to, use the definition in hal-bluetoth.c.


Sent from my Nexus 7 using Tapatalk

Forgot my unknowledge/newbie but I can not find it in hal-bluetoth.c (In BLueZ git)
22nd February 2014, 02:13 PM |#11  
daniel_hk's Avatar
OP Recognized Contributor
Flag Hong Kong
Thanks Meter: 5,404
 
Donate to Me
More
Quote:
Originally Posted by 95A31

Forgot my unknowledge/newbie but I can not find it in hal-bluetoth.c (In BLueZ git)

It's in the android folder. In the same place as Android.mk.
If you can't find inside the file, you might have the old version. Try include the project in manifest and sync again.
I have a suggested local_manifest in post #1.
Good luck!

Sent from my Nexus 7 using Tapatalk
Post Reply Subscribe to Thread

Guest Quick Reply (no urls or BBcode)
Message:
Previous Thread Next Thread
Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes