summaryrefslogtreecommitdiffstats
path: root/plugins/lib/bluetooth
diff options
context:
space:
mode:
authorJonathan Aillet <jonathan.aillet@iot.bzh>2018-08-24 20:17:12 +0200
committerJonathan Aillet <jonathan.aillet@iot.bzh>2018-10-08 15:56:09 +0200
commit92eb34c496de489f288c0eb59c9d84d6cf31decd (patch)
treec2b4a69c98ad8cb3017ecb824e7e2955586a572d /plugins/lib/bluetooth
parentdeb99447f014426cf2aed8263932b38d412bd376 (diff)
Add bluetooth hal plugin
Add first version of a hal plugin that will handle hal that wants bluetooth as an audio device. Change-Id: I4f5628ef9688c417b1b443fc3c4948cb23c17214 Signed-off-by: Jonathan Aillet <jonathan.aillet@iot.bzh>
Diffstat (limited to 'plugins/lib/bluetooth')
-rw-r--r--plugins/lib/bluetooth/CMakeLists.txt45
-rw-r--r--plugins/lib/bluetooth/hal-bt-cb.c171
-rw-r--r--plugins/lib/bluetooth/hal-bt-cb.h40
-rw-r--r--plugins/lib/bluetooth/hal-bt-data.c220
-rw-r--r--plugins/lib/bluetooth/hal-bt-data.h52
-rw-r--r--plugins/lib/bluetooth/hal-bt.c195
-rw-r--r--plugins/lib/bluetooth/hal-bt.h33
7 files changed, 756 insertions, 0 deletions
diff --git a/plugins/lib/bluetooth/CMakeLists.txt b/plugins/lib/bluetooth/CMakeLists.txt
new file mode 100644
index 0000000..fa28ae1
--- /dev/null
+++ b/plugins/lib/bluetooth/CMakeLists.txt
@@ -0,0 +1,45 @@
+###########################################################################
+# Copyright 2015, 2016, 2017, 2018 IoT.bzh
+#
+# author: Jonathan Aillet <jonathan.aillet@iot.bzh>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+###########################################################################
+
+PROJECT_TARGET_ADD(hal-bt)
+
+ # Define targets
+ ADD_LIBRARY(${TARGET_NAME} MODULE
+ hal-bt.c
+ hal-bt-cb.c
+ hal-bt-data.c
+ )
+
+ # Alsa Plugin properties
+ SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES
+ LABELS "PLUGIN"
+ PREFIX ""
+ SUFFIX ".ctlso"
+ OUTPUT_NAME ${TARGET_NAME}
+ )
+
+ # Library dependencies (include updates automatically)
+ TARGET_LINK_LIBRARIES(${TARGET_NAME}
+ afb-helpers
+ ctl-utilities
+ ${link_libraries}
+ )
+
+ target_include_directories(${TARGET_NAME}
+ PRIVATE "${CMAKE_SOURCE_DIR}/app-controller/ctl-lib"
+ )
diff --git a/plugins/lib/bluetooth/hal-bt-cb.c b/plugins/lib/bluetooth/hal-bt-cb.c
new file mode 100644
index 0000000..c4f0231
--- /dev/null
+++ b/plugins/lib/bluetooth/hal-bt-cb.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2018 "IoT.bzh"
+ * Author Jonathan Aillet <jonathan.aillet@iot.bzh>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include <wrap-json.h>
+
+#include <ctl-plugin.h>
+
+#include "hal-bt-data.h"
+
+/*******************************************************************************
+ * HAL Bluetooth plugin verbs functions *
+ ******************************************************************************/
+
+void HalBtGetStreamingStatus(AFB_ReqT request)
+{
+ struct HalBtPluginData *localHalBtPluginData;
+
+ if(! (localHalBtPluginData = (struct HalBtPluginData *) afb_request_get_vcbdata(request))) {
+ AFB_ReqFail(request, "bt_plugin_data", "Can't get bluetooth plugin data");
+ return;
+ }
+
+ AFB_ReqSuccess(request, json_object_new_string(localHalBtPluginData->btStreamEnabled ? "enabled" : "disabled"), "Bluetooth streaming status");
+}
+
+void HalBtSetStreamingStatus(AFB_ReqT request)
+{
+ unsigned int requestedBtStreamingStatus;
+
+ struct HalBtPluginData *localHalBtPluginData;
+
+ json_object *requestJson;
+
+ if(! (localHalBtPluginData = (struct HalBtPluginData *) afb_request_get_vcbdata(request))) {
+ AFB_ReqFail(request, "bt_plugin_data", "Can't get bluetooth plugin data");
+ return;
+ }
+
+ if(! (requestJson = AFB_ReqJson(request))) {
+ AFB_ReqFail(request, "request_json", "Can't get request json");
+ return;
+ }
+
+ if(wrap_json_unpack(requestJson, "{s:b}", "status", &requestedBtStreamingStatus)) {
+ AFB_ReqFail(request, "requested_status", "Can't get requested bluetooth streaming status");
+ return;
+ }
+
+ localHalBtPluginData->btStreamEnabled = requestedBtStreamingStatus;
+
+ // TODO JAI : Enable capture stream to playback using 'uid' used at 'set-capture' call
+
+ AFB_ReqSuccess(request, NULL, "Bluetooth streaming status successfully set");
+}
+
+void HalBtGetConnectedBluetoothDevices(AFB_ReqT request)
+{
+ struct HalBtPluginData *localHalBtPluginData;
+ struct HalBtDeviceData *currentBtDeviceData;
+
+ json_object *requestAnswer, *currentBtDeviceObjectJ;
+
+ if(! (localHalBtPluginData = (struct HalBtPluginData *) afb_request_get_vcbdata(request))) {
+ AFB_ReqFail(request, "bt_plugin_data", "Can't get bluetooth plugin data");
+ return;
+ }
+
+ if(! (currentBtDeviceData = localHalBtPluginData->first)) {
+ AFB_ReqSuccess(request, NULL, "No bluetooth device connected");
+ return;
+ }
+
+ requestAnswer = json_object_new_array();
+ if(! requestAnswer) {
+ AFB_ReqFail(request, "json_answer", "Can't generate json answer");
+ return;
+ }
+
+ while(currentBtDeviceData) {
+ wrap_json_pack(&currentBtDeviceObjectJ,
+ "{s:s s:s}",
+ "Name", currentBtDeviceData->name,
+ "Address", currentBtDeviceData->address);
+ json_object_array_add(requestAnswer, currentBtDeviceObjectJ);
+
+ currentBtDeviceData = currentBtDeviceData->next;
+ }
+
+ AFB_ReqSuccess(request, requestAnswer, "Connected bluetooth devices list");
+}
+
+void HalBtGetSelectedBluetoothDevice(AFB_ReqT request)
+{
+ struct HalBtPluginData *localHalBtPluginData;
+
+ json_object *selectedBtDeviceObject;
+
+ if(! (localHalBtPluginData = (struct HalBtPluginData *) afb_request_get_vcbdata(request))) {
+ AFB_ReqFail(request, "bt_plugin_data", "Can't get bluetooth plugin data");
+ return;
+ }
+
+ if(! localHalBtPluginData->selectedBtDevice) {
+ AFB_ReqSuccess(request, NULL, "No bluetooth device connected, cannot provide selected device");
+ return;
+ }
+
+ wrap_json_pack(&selectedBtDeviceObject,
+ "{s:s s:s}",
+ "Name", localHalBtPluginData->selectedBtDevice->name,
+ "Address", localHalBtPluginData->selectedBtDevice->address);
+
+ AFB_ReqSuccess(request, selectedBtDeviceObject, "Selected Bluetooth device");
+}
+
+void HalBtSetSelectedBluetoothDevice(AFB_ReqT request)
+{
+ char *requestedBtDeviceToSelect;
+
+ struct HalBtPluginData *localHalBtPluginData;
+ struct HalBtDeviceData *selectedBtDeviceData;
+
+ json_object *requestJson;
+
+ if(! (localHalBtPluginData = (struct HalBtPluginData *) afb_request_get_vcbdata(request))) {
+ AFB_ReqFail(request, "bt_plugin_data", "Can't get bluetooth plugin data");
+ return;
+ }
+
+ if(! (requestJson = AFB_ReqJson(request))) {
+ AFB_ReqFail(request, "request_json", "Can't get request json");
+ return;
+ }
+
+ if(wrap_json_unpack(requestJson, "{s:s}", "Address", &requestedBtDeviceToSelect)) {
+ AFB_ReqFail(request, "requested_device_to_select", "Can't get requested bluetooth device to select");
+ return;
+ }
+
+ if(! (selectedBtDeviceData = HalBtDataSearchBtDeviceByAddress(&localHalBtPluginData->first, requestedBtDeviceToSelect))) {
+ AFB_ReqFail(request, "requested_device_to_select", "Requested bluetooth device to select is not currently connected");
+ return;
+ }
+
+ localHalBtPluginData->selectedBtDevice = selectedBtDeviceData;
+
+ // TODO JAI : Tell the softmixer that we want it as an input using 'bluealsa:HCI=hci0,DEV=F6:32:15:2A:80:70,PROFILE=a2dp'
+ // string as capture associated with an 'uid' using smixer verb 'set-capture'
+
+ AFB_ReqSuccess(request, NULL, "Selected bluetooth device successfully set");
+} \ No newline at end of file
diff --git a/plugins/lib/bluetooth/hal-bt-cb.h b/plugins/lib/bluetooth/hal-bt-cb.h
new file mode 100644
index 0000000..269da4f
--- /dev/null
+++ b/plugins/lib/bluetooth/hal-bt-cb.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2018 "IoT.bzh"
+ * Author Jonathan Aillet <jonathan.aillet@iot.bzh>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _HAL_BT_CB_INCLUDE_
+#define _HAL_BT_CB_INCLUDE_
+
+#include <stdio.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include <ctl-plugin.h>
+
+#define HAL_BT_GET_STREAMING_STATUS_VERB "get_bt_streaming_status"
+#define HAL_BT_SET_STREAMING_STATUS_VERB "set_bt_streaming_status"
+#define HAL_BT_GET_CONNECTED_DEVICES_VERB "get_connected_bt_devices"
+#define HAL_BT_GET_SELECTED_DEVICE_VERB "get_selected_bt_device"
+#define HAL_BT_SET_SELECTED_DEVICE_VERB "set_selected_bt_device"
+
+// HAL Bluetooth plugin verbs functions
+void HalBtGetStreamingStatus(AFB_ReqT request);
+void HalBtSetStreamingStatus(AFB_ReqT request);
+void HalBtGetConnectedBluetoothDevices(AFB_ReqT request);
+void HalBtGetSelectedBluetoothDevice(AFB_ReqT request);
+void HalBtSetSelectedBluetoothDevice(AFB_ReqT request);
+
+#endif /* _HAL_BT_CB_INCLUDE_ */ \ No newline at end of file
diff --git a/plugins/lib/bluetooth/hal-bt-data.c b/plugins/lib/bluetooth/hal-bt-data.c
new file mode 100644
index 0000000..d56d0db
--- /dev/null
+++ b/plugins/lib/bluetooth/hal-bt-data.c
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2018 "IoT.bzh"
+ * Author Jonathan Aillet <jonathan.aillet@iot.bzh>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include <wrap-json.h>
+
+#include "hal-bt-data.h"
+
+/*******************************************************************************
+ * Bt device data handling functions *
+ ******************************************************************************/
+
+int HalBtDataRemoveSelectedBtDeviceFromList(struct HalBtDeviceData **firstBtDeviceData, struct HalBtDeviceData *btDeviceDataToRemove)
+{
+ struct HalBtDeviceData *currentBtDevice, *matchingBtDevice;
+
+ if(! firstBtDeviceData || ! btDeviceDataToRemove)
+ return -1;
+
+ currentBtDevice = *firstBtDeviceData;
+
+ if(currentBtDevice == btDeviceDataToRemove) {
+ *firstBtDeviceData = currentBtDevice->next;
+ matchingBtDevice = currentBtDevice;
+ }
+ else {
+ while(currentBtDevice && currentBtDevice->next != btDeviceDataToRemove)
+ currentBtDevice = currentBtDevice->next;
+
+ if(currentBtDevice) {
+ matchingBtDevice = currentBtDevice->next;
+ currentBtDevice->next = currentBtDevice->next->next;
+ }
+ else {
+ return -2;
+ }
+ }
+
+ free(matchingBtDevice->uid);
+ free(matchingBtDevice->name);
+ free(matchingBtDevice->address);
+
+ free(matchingBtDevice);
+
+ return 0;
+}
+
+struct HalBtDeviceData *HalBtDataAddBtDeviceToBtDeviceList(struct HalBtDeviceData **firstBtDeviceData, json_object *currentSingleBtDeviceDataJ)
+{
+ char *currentBtDeviceName, *currentBtDeviceAddress;
+
+ struct HalBtDeviceData *currentBtDeviceData;
+
+ if(! firstBtDeviceData || ! currentSingleBtDeviceDataJ)
+ return NULL;
+
+ currentBtDeviceData = *firstBtDeviceData;
+
+ if(! currentBtDeviceData) {
+
+ currentBtDeviceData = (struct HalBtDeviceData *) calloc(1, sizeof(struct HalBtDeviceData));
+ if(! currentBtDeviceData)
+ return NULL;
+
+ *firstBtDeviceData = currentBtDeviceData;
+ }
+ else {
+
+ while(currentBtDeviceData->next)
+ currentBtDeviceData = currentBtDeviceData->next;
+
+ currentBtDeviceData->next = calloc(1, sizeof(struct HalBtDeviceData));
+ if(! currentBtDeviceData)
+ return NULL;
+
+ currentBtDeviceData = currentBtDeviceData->next;
+ }
+
+ if(wrap_json_unpack(currentSingleBtDeviceDataJ,
+ "{s:s s:s}",
+ "Name", &currentBtDeviceName,
+ "Address", &currentBtDeviceAddress)) {
+ HalBtDataRemoveSelectedBtDeviceFromList(firstBtDeviceData, currentBtDeviceData);
+ return NULL;
+ }
+
+ if(asprintf(&currentBtDeviceData->uid, "BT#%s", currentBtDeviceAddress) == -1) {
+ HalBtDataRemoveSelectedBtDeviceFromList(firstBtDeviceData, currentBtDeviceData);
+ return NULL;
+ }
+
+ if(! (currentBtDeviceData->name = strdup(currentBtDeviceName))) {
+ HalBtDataRemoveSelectedBtDeviceFromList(firstBtDeviceData, currentBtDeviceData);
+ return NULL;
+ }
+
+ if(! (currentBtDeviceData->address = strdup(currentBtDeviceAddress))) {
+ HalBtDataRemoveSelectedBtDeviceFromList(firstBtDeviceData, currentBtDeviceData);
+ return NULL;
+ }
+
+ return currentBtDeviceData;
+}
+
+int HalBtDataGetNumberOfBtDeviceInList(struct HalBtDeviceData **firstBtDeviceData)
+{
+ unsigned int btDeviceNb = 0;
+
+ struct HalBtDeviceData *currentBtDeviceData;
+
+ if(! firstBtDeviceData)
+ return -1;
+
+ currentBtDeviceData = *firstBtDeviceData;
+
+ while(currentBtDeviceData) {
+ currentBtDeviceData = currentBtDeviceData->next;
+ btDeviceNb++;
+ }
+
+ return btDeviceNb;
+}
+
+struct HalBtDeviceData *HalBtDataSearchBtDeviceByAddress(struct HalBtDeviceData **firstBtDeviceData, char *btAddress)
+{
+ struct HalBtDeviceData *currentBtDevice;
+
+ if(! firstBtDeviceData || ! btAddress)
+ return NULL;
+
+ currentBtDevice = *firstBtDeviceData;
+
+ while(currentBtDevice) {
+ if(! strcmp(btAddress, currentBtDevice->address))
+ return currentBtDevice;
+
+ currentBtDevice = currentBtDevice->next;
+ }
+
+ return NULL;
+}
+
+int HalBtDataHandleReceivedSingleBtDeviceData(struct HalBtPluginData *halBtPluginData, json_object *currentSingleBtDeviceDataJ)
+{
+ unsigned int currentBtDeviceIsConnected;
+
+ char *currentBtDeviceAddress, *currentBtDeviceIsConnectedString;
+
+ struct HalBtDeviceData *currentBtDevice;
+ if(! halBtPluginData || ! currentSingleBtDeviceDataJ)
+ return -1;
+
+ if(wrap_json_unpack(currentSingleBtDeviceDataJ,
+ "{s:s s:s}",
+ "Address", &currentBtDeviceAddress,
+ "Connected", &currentBtDeviceIsConnectedString)) {
+ return -2;
+ }
+
+ currentBtDeviceIsConnected = ! strncmp(currentBtDeviceIsConnectedString, "True", strlen(currentBtDeviceIsConnectedString));
+ currentBtDevice = HalBtDataSearchBtDeviceByAddress(&halBtPluginData->first, currentBtDeviceAddress);
+
+ if(currentBtDevice && ! currentBtDeviceIsConnected) {
+ if(HalBtDataRemoveSelectedBtDeviceFromList(&halBtPluginData->first, currentBtDevice))
+ return -3;
+
+ if(halBtPluginData->selectedBtDevice == currentBtDevice)
+ halBtPluginData->selectedBtDevice = halBtPluginData->first;
+ }
+ else if(! currentBtDevice && currentBtDeviceIsConnected) {
+
+ if(! HalBtDataAddBtDeviceToBtDeviceList(&halBtPluginData->first, currentSingleBtDeviceDataJ))
+ return -4;
+
+ if(! halBtPluginData->selectedBtDevice)
+ halBtPluginData->selectedBtDevice = halBtPluginData->first;
+ }
+
+ return 0;
+}
+
+int HalBtDataHandleReceivedMutlipleBtDeviceData(struct HalBtPluginData *halBtPluginData, json_object *currentMultipleBtDeviceDataJ)
+{
+ int err = 0;
+ size_t idx, btDeviceNumber;
+
+ if(! halBtPluginData || ! currentMultipleBtDeviceDataJ)
+ return -1;
+
+ if(! json_object_is_type(currentMultipleBtDeviceDataJ, json_type_array))
+ return -2;
+
+ btDeviceNumber = json_object_array_length(currentMultipleBtDeviceDataJ);
+
+ for(idx = 0; idx < btDeviceNumber; idx++) {
+ if((err = HalBtDataHandleReceivedSingleBtDeviceData(halBtPluginData, json_object_array_get_idx(currentMultipleBtDeviceDataJ, (unsigned int) idx))))
+ return ((int) idx * err * 10);
+ }
+
+ return 0;
+} \ No newline at end of file
diff --git a/plugins/lib/bluetooth/hal-bt-data.h b/plugins/lib/bluetooth/hal-bt-data.h
new file mode 100644
index 0000000..030c8d1
--- /dev/null
+++ b/plugins/lib/bluetooth/hal-bt-data.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2018 "IoT.bzh"
+ * Author Jonathan Aillet <jonathan.aillet@iot.bzh>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _HAL_BT_DATA_INCLUDE_
+#define _HAL_BT_DATA_INCLUDE_
+
+#include <stdio.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include <json-c/json.h>
+
+// Structure to store bluetooth device data
+struct HalBtDeviceData {
+ char *uid;
+ char *name;
+ char *address;
+ // TODO JAI : Get bluetooth device's profile and store it here
+
+ struct HalBtDeviceData *next;
+};
+
+// Structure to store hal bluetooth plugin data
+struct HalBtPluginData {
+ // TODO JAI : Get hci device and store it here
+ unsigned int btStreamEnabled;
+
+ struct HalBtDeviceData *selectedBtDevice;
+ struct HalBtDeviceData *first;
+};
+
+// Exported verbs for 'struct HalBtDeviceData' list (available in 'struct HalBtPluginData') handling
+int HalBtDataGetNumberOfBtDeviceInList(struct HalBtDeviceData **firstBtDeviceData);
+struct HalBtDeviceData *HalBtDataSearchBtDeviceByAddress(struct HalBtDeviceData **firstBtDeviceData, char *btAddress);
+int HalBtDataHandleReceivedSingleBtDeviceData(struct HalBtPluginData *halBtPluginData, json_object *currentSingleBtDeviceDataJ);
+int HalBtDataHandleReceivedMutlipleBtDeviceData(struct HalBtPluginData *halBtPluginData, json_object *currentMultipleBtDeviceDataJ);
+
+#endif /* _HAL_BT_DATA_INCLUDE_ */ \ No newline at end of file
diff --git a/plugins/lib/bluetooth/hal-bt.c b/plugins/lib/bluetooth/hal-bt.c
new file mode 100644
index 0000000..32fbbf7
--- /dev/null
+++ b/plugins/lib/bluetooth/hal-bt.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2018 "IoT.bzh"
+ * Author Jonathan Aillet <jonathan.aillet@iot.bzh>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include <wrap-json.h>
+
+#include <ctl-plugin.h>
+
+#include "hal-bt.h"
+#include "hal-bt-cb.h"
+#include "hal-bt-data.h"
+
+// Local (static) Hal manager data structure
+static struct HalBtPluginData localHalBtPluginData;
+
+CTLP_CAPI_REGISTER(HAL_BT_PLUGIN_NAME)
+
+// Call at initialisation time
+CTLP_ONLOAD(plugin, callbacks)
+{
+ AFB_ApiNotice(plugin->api, "Hal-Bt Plugin Register: uid='%s' 'info='%s'", plugin->uid, plugin->info);
+
+ memset(&localHalBtPluginData, '\0', sizeof(localHalBtPluginData));
+
+ AFB_RequireApi(plugin->api, BT_MANAGER_API, 1);
+
+ /* TDB JAI :
+ - Register 'init' plugin function (HAL_BT_PLUGIN_NAME#init) as onload action here (to avoid adding it in json)
+ - Register 'event' plugin function (HAL_BT_PLUGIN_NAME#event) as action for BT_MANAGER_API#BT_MANAGER_DEVICE_UPDATE_EVENT event here (to avoid adding it in json)
+ */
+
+ return 0;
+}
+
+// Call at onload time
+CTLP_CAPI(init, source, argsJ, queryJ)
+{
+ unsigned int err;
+
+ struct json_object *toSendJ, *returnedJ, *returnedBtList = NULL;
+
+ AFB_ApiNotice(source->api, "Initializing HAL-BT plugin");
+
+ // Loading hal BT plugin specific verbs
+ if(afb_dynapi_add_verb(source->api,
+ HAL_BT_GET_STREAMING_STATUS_VERB,
+ "Get Bluetooth streaming status",
+ HalBtGetStreamingStatus,
+ (void *) &localHalBtPluginData,
+ NULL,
+ 0)) {
+ AFB_ApiError(source->api, "%s: error while creating verb for bluetooth plugin : '%s'", __func__, HAL_BT_GET_STREAMING_STATUS_VERB);
+ return -1;
+ }
+
+ if(afb_dynapi_add_verb(source->api,
+ HAL_BT_SET_STREAMING_STATUS_VERB,
+ "Set Bluetooth streaming status",
+ HalBtSetStreamingStatus,
+ (void *) &localHalBtPluginData,
+ NULL,
+ 0)) {
+ AFB_ApiError(source->api, "%s: error while creating verb for bluetooth plugin : '%s'", __func__, HAL_BT_SET_STREAMING_STATUS_VERB);
+ return -2;
+ }
+
+ if(afb_dynapi_add_verb(source->api,
+ HAL_BT_GET_CONNECTED_DEVICES_VERB,
+ "Get connected Bluetooth devices list",
+ HalBtGetConnectedBluetoothDevices,
+ (void *) &localHalBtPluginData,
+ NULL,
+ 0)) {
+ AFB_ApiError(source->api, "%s: error while creating verb for bluetooth plugin : '%s'", __func__, HAL_BT_GET_CONNECTED_DEVICES_VERB);
+ return -3;
+ }
+
+ if(afb_dynapi_add_verb(source->api,
+ HAL_BT_GET_SELECTED_DEVICE_VERB,
+ "Get selected Bluetooth device",
+ HalBtGetSelectedBluetoothDevice,
+ (void *) &localHalBtPluginData,
+ NULL,
+ 0)) {
+ AFB_ApiError(source->api, "%s: error while creating verb for bluetooth plugin : '%s'", __func__, HAL_BT_GET_SELECTED_DEVICE_VERB);
+ return -4;
+ }
+
+ if(afb_dynapi_add_verb(source->api,
+ HAL_BT_SET_SELECTED_DEVICE_VERB,
+ "Set selected Bluetooth device",
+ HalBtSetSelectedBluetoothDevice,
+ (void *) &localHalBtPluginData,
+ NULL,
+ 0)) {
+ AFB_ApiError(source->api, "%s: error while creating verb for bluetooth plugin : '%s'", __func__, HAL_BT_SET_SELECTED_DEVICE_VERB);
+ return -5;
+ }
+
+ // Register to Bluetooth manager
+ wrap_json_pack(&toSendJ, "{s:s}", "value", BT_MANAGER_DEVICE_UPDATE_EVENT);
+ if(AFB_ServiceSync(source->api, BT_MANAGER_API, BT_MANAGER_SUBSCRIBE_VERB, toSendJ, &returnedJ)) {
+ AFB_ApiError(source->api,
+ "Error during call to verb %s of %s api",
+ BT_MANAGER_API,
+ BT_MANAGER_SUBSCRIBE_VERB);
+
+ return -6;
+ }
+ else if(! wrap_json_unpack(returnedJ, "{s:{s:s}}", "request", "info", NULL)) {
+ AFB_ApiError(source->api,
+ "Couldn't subscribe to event '%s' during call to verb '%s' of api '%s'",
+ BT_MANAGER_DEVICE_UPDATE_EVENT,
+ BT_MANAGER_SUBSCRIBE_VERB,
+ BT_MANAGER_API);
+ return -7;
+ }
+
+ if(AFB_ServiceSync(source->api, BT_MANAGER_API, BT_MANAGER_GET_DEVICES_VERB, NULL, &returnedJ)) {
+ AFB_ApiError(source->api,
+ "Error during call to verb %s of %s api",
+ BT_MANAGER_API,
+ BT_MANAGER_GET_DEVICES_VERB);
+
+ return -8;
+ }
+ else if(wrap_json_unpack(returnedJ, "{s:{s:o}}", "response", "list", &returnedBtList)) {
+ AFB_ApiError(source->api,
+ "Couldn't get bluetooth device list during call to verb '%s' of api '%s'",
+ BT_MANAGER_GET_DEVICES_VERB,
+ BT_MANAGER_API);
+ return -9;
+ }
+
+ if((err = HalBtDataHandleReceivedMutlipleBtDeviceData(&localHalBtPluginData, returnedBtList)))
+ return (10 * err);
+
+ if(localHalBtPluginData.selectedBtDevice) {
+ localHalBtPluginData.btStreamEnabled = 1;
+ /* TODO JAI : send selected device to softmixer (and enable stream here for now)
+ * Tell the softmixer that we want it as an input using 'bluealsa:HCI=hci0,DEV=F6:32:15:2A:80:70,PROFILE=a2dp'
+ string as capture associated with an 'uid' using smixer verb 'set-capture'
+ * Enable capture stream to playback using 'uid' used at 'set-capture' call
+ */
+ }
+
+ return 0;
+}
+
+// This receive Hal bluetooth plugin events
+CTLP_CAPI(events, source, argsJ, queryJ)
+{
+ struct HalBtDeviceData *previouslySelectedBtDevice = localHalBtPluginData.selectedBtDevice;
+
+ AFB_ApiNotice(source->api, "JAI: bt event received: %s", json_object_get_string(queryJ));
+
+ if(HalBtDataHandleReceivedSingleBtDeviceData(&localHalBtPluginData, queryJ)) {
+ AFB_ApiError(source->api, "Error while decoding bluetooth event received json (%s)", json_object_get_string(queryJ));
+ return -1;
+ }
+
+ if(localHalBtPluginData.selectedBtDevice && localHalBtPluginData.selectedBtDevice != previouslySelectedBtDevice) {
+ localHalBtPluginData.btStreamEnabled = 1;
+ /* TODO JAI : send selected device to softmixer (and enable stream here for now)
+ * Tell the softmixer that we want it as an input using 'bluealsa:HCI=hci0,DEV=F6:32:15:2A:80:70,PROFILE=a2dp'
+ string as capture associated with an 'uid' using smixer verb 'set-capture'
+ * Enable capture stream to playback using 'uid' used at 'set-capture' call
+ */
+ }
+ else if (! localHalBtPluginData.selectedBtDevice) {
+ localHalBtPluginData.btStreamEnabled = 0;
+ // TODO JAI: Disable capture stream to playback using 'uid' used at 'set-capture' call
+ }
+
+ return 0;
+} \ No newline at end of file
diff --git a/plugins/lib/bluetooth/hal-bt.h b/plugins/lib/bluetooth/hal-bt.h
new file mode 100644
index 0000000..ad94a7e
--- /dev/null
+++ b/plugins/lib/bluetooth/hal-bt.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2018 "IoT.bzh"
+ * Author Jonathan Aillet <jonathan.aillet@iot.bzh>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _HAL_BT_INCLUDE_
+#define _HAL_BT_INCLUDE_
+
+#include <stdio.h>
+#include <string.h>
+#include <stdbool.h>
+
+#define HAL_BT_PLUGIN_NAME "hal-bt"
+
+#define BT_MANAGER_API "Bluetooth-Manager"
+#define BT_MANAGER_SUBSCRIBE_VERB "subscribe"
+#define BT_MANAGER_GET_DEVICES_VERB "discovery_result"
+
+#define BT_MANAGER_DEVICE_UPDATE_EVENT "device_updated"
+
+#endif /* _HAL_BT_INCLUDE_ */ \ No newline at end of file