summaryrefslogtreecommitdiffstats
path: root/plugins/lib/bluetooth/hal-bt.c
diff options
context:
space:
mode:
authorThierry Bultel <thierry.bultel@iot.bzh>2018-12-05 14:05:10 +0100
committerThierry Bultel <thierry.bultel@iot.bzh>2018-12-20 16:55:46 +0000
commit01d55ed8cdd01ca4a7b391ca61c80084bd5a6f2f (patch)
treed73ce778a2177e82e07e9d31891a827467fbadd4 /plugins/lib/bluetooth/hal-bt.c
parentdbe555be80dd10bb315b14bbebcb42f8b883e2c9 (diff)
Adds support for bluetooth audio through bluez-alsaguppy_6.99.4guppy_6.99.3guppy/6.99.4guppy/6.99.36.99.46.99.3
Implements a new bluealsa plugin to the HAL manager, reacting to the changes of the available transports. This plugin is linked with the new bluealsa.so shared library. New transports (SCO & A2DP) result in softmixer invocations of the "attach" verb, that creates the new capture (eg, A2DP capture from bluealsa ioplug PCM, SCO microphone capture), playbacks (SCO playback to a softmixer zone, and SCO output to bluealsa iogplug PCM). When a transport disappears, the hal manager calls the transaction deletion verb that will tell the softmixer to remove the created streams and associated objects. Change-Id: I36037a4f14ef7fee38070fc0df66c40b4ce46e8b Signed-off-by: Thierry Bultel <thierry.bultel@iot.bzh>
Diffstat (limited to 'plugins/lib/bluetooth/hal-bt.c')
-rw-r--r--plugins/lib/bluetooth/hal-bt.c437
1 files changed, 0 insertions, 437 deletions
diff --git a/plugins/lib/bluetooth/hal-bt.c b/plugins/lib/bluetooth/hal-bt.c
deleted file mode 100644
index f270593..0000000
--- a/plugins/lib/bluetooth/hal-bt.c
+++ /dev/null
@@ -1,437 +0,0 @@
-/*
- * 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-config.h>
-
-#include "hal-bt.h"
-#include "hal-bt-cb.h"
-#include "hal-bt-data.h"
-#include "hal-bt-mixer-link.h"
-
-CTLP_CAPI_REGISTER(HAL_BT_PLUGIN_NAME)
-
-// Call at initialisation time
-CTLP_ONLOAD(plugin, callbacks)
-{
- struct HalBtPluginData *currentBtPluginData;
-
- AFB_ApiInfo(plugin->api, "%s Plugin Registering: uid='%s' 'info='%s'", HAL_BT_PLUGIN_NAME, plugin->uid, plugin->info);
-
- currentBtPluginData = calloc(1, sizeof(struct HalBtPluginData));
- if(! currentBtPluginData) {
- AFB_ApiError(plugin->api, "An error happenned during allocation of %s plugin data structure ", HAL_BT_PLUGIN_NAME);
- return -1;
- }
-
- setPluginContext(plugin, (void *) currentBtPluginData);
-
- currentBtPluginData->currentHalApiHandle = plugin->api;
-
- AFB_ApiNotice(plugin->api, "%s Plugin Registered correctly: uid='%s' 'info='%s'", HAL_BT_PLUGIN_NAME, plugin->uid, plugin->info);
-
- return 0;
-}
-
-CTLP_INIT(plugin, callbacks)
-{
- int btChannelsNumber;
-
- unsigned int idx;
-
- char *btStreamZone, *returnedInfo;
-
- CtlConfigT *ctrlConfig;
-
- struct HalBtPluginData *currentBtPluginData;
-
- json_object *actionsToAdd, *returnedJ, *halMixerJ, *halOrigCaptureJ, *halNewCaptureJ, *halOrigStreamJ, *halNewStreamJ, *btCaptureJ, *btCaptureParamsJ, *btStreamJ;
-
- AFB_ApiInfo(plugin->api, "Plugin initialization of %s plugin", HAL_BT_PLUGIN_NAME);
-
- if(AFB_RequireApi(plugin->api, BT_MANAGER_API, 1)) {
- AFB_ApiWarning(plugin->api, "Didn't succeed to require %s api, bluetooth is disable because not reachable", BT_MANAGER_API);
- return 0;
- }
-
- if(! (currentBtPluginData = (struct HalBtPluginData *) getPluginContext(plugin))) {
- AFB_ApiError(plugin->api, "Can't get current %s plugin data", HAL_BT_PLUGIN_NAME);
- return -1;
- }
-
- if(! (ctrlConfig = (CtlConfigT *) AFB_ApiGetUserData(plugin->api))) {
- AFB_ApiError(plugin->api, "Can't get current hal controller config");
- return -2;
- }
-
- if(! (currentBtPluginData->currentHalData = getExternalData(ctrlConfig))) {
- AFB_ApiError(plugin->api, "Can't get current hal controller data");
- return -3;
- }
-
- if(currentBtPluginData->currentHalData->status != HAL_STATUS_AVAILABLE) {
- AFB_ApiWarning(plugin->api, "Controller initialization of %s plugin cannot be done because hal is not ready to be used", HAL_BT_PLUGIN_NAME);
- return 0;
- }
-
- if((! currentBtPluginData->currentHalData->ctlHalSpecificData) ||
- (! (halMixerJ = currentBtPluginData->currentHalData->ctlHalSpecificData->halMixerJ))) {
- AFB_ApiError(plugin->api, "Can't get current hal mixer json section");
- return -4;
- }
-
- if(AFB_ServiceSync(plugin->api, BT_MANAGER_API, BT_MANAGER_GET_POWER_INFO, NULL, &returnedJ)) {
- if((! wrap_json_unpack(returnedJ, "{s:{s:s}}", "request", "info", &returnedInfo)) &&
- (! strncmp(returnedInfo, "Unable to get power status", strlen(returnedInfo)))) {
- AFB_ApiWarning(plugin->api,
- "No bluetooth receiver detected when calling verb '%s' of '%s' api, bluetooth is disable because not reachable",
- BT_MANAGER_GET_POWER_INFO,
- BT_MANAGER_API);
- return 0;
- }
- else {
- AFB_ApiError(plugin->api,
- "Error during call to verb '%s' of '%s' api (%s)",
- BT_MANAGER_GET_POWER_INFO,
- BT_MANAGER_API,
- json_object_get_string(returnedJ));
- return -5;
- }
- }
-
- if((! json_object_is_type(plugin->paramsJ, json_type_object)) ||
- (wrap_json_unpack(plugin->paramsJ, "{s:i, s:s}", "channels", &btChannelsNumber, "zone", &btStreamZone))) {
- AFB_ApiError(plugin->api, "Can't get %s plugin parameters from json ('%s')", HAL_BT_PLUGIN_NAME, json_object_get_string(plugin->paramsJ));
- return -6;
- }
-
- wrap_json_pack(&actionsToAdd, "{s:s s:s}",
- "uid", "Bluetooth-Manager/device_updated",
- "action", "plugin://hal-bt#events");
-
- idx = 0;
- while(ctrlConfig->sections[idx].key && strcasecmp(ctrlConfig->sections[idx].key, "events"))
- idx++;
-
- if(! ctrlConfig->sections[idx].key) {
- AFB_ApiError(plugin->api, "Wasn't able to add '%s' as a new event, 'events' section not found", json_object_get_string(actionsToAdd));
- json_object_put(actionsToAdd);
- return -7;
- }
-
- if(AddActionsToSection(plugin->api, &ctrlConfig->sections[idx], actionsToAdd, 0)) {
- AFB_ApiError(plugin->api, "Wasn't able to add '%s' as a new event to %s", json_object_get_string(actionsToAdd), ctrlConfig->sections[idx].key);
- json_object_put(actionsToAdd);
- return -8;
- }
-
- wrap_json_pack(&actionsToAdd, "{s:s s:s s:s}",
- "uid", "init-bt-plugin",
- "info", "Init Bluetooth hal plugin",
- "action", "plugin://hal-bt#init");
-
- idx = 0;
- while(ctrlConfig->sections[idx].key && strcasecmp(ctrlConfig->sections[idx].key, "onload"))
- idx++;
-
- if(! ctrlConfig->sections[idx].key) {
- AFB_ApiError(plugin->api, "Wasn't able to add '%s' as a new onload, 'onload' section not found", json_object_get_string(actionsToAdd));
- json_object_put(actionsToAdd);
- return -9;
- }
-
- if(AddActionsToSection(plugin->api, &ctrlConfig->sections[idx], actionsToAdd, 0)) {
- AFB_ApiError(plugin->api, "Wasn't able to add '%s' as a new onload to %s", json_object_get_string(actionsToAdd), ctrlConfig->sections[idx].uid);
- json_object_put(actionsToAdd);
- return -10;
- }
-
- btCaptureJ = json_tokener_parse(MIXER_BT_CAPTURE_JSON_SECTION);
- wrap_json_pack(&btCaptureParamsJ, "{s:i}", "channels", btChannelsNumber);
- json_object_object_add(btCaptureJ, "params", btCaptureParamsJ);
-
- if(! json_object_object_get_ex(halMixerJ, "captures", &halOrigCaptureJ)) {
- halNewCaptureJ = json_object_new_array();
- json_object_array_add(halNewCaptureJ, btCaptureJ);
- json_object_object_add(halMixerJ, "captures", halNewCaptureJ);
- }
- else if(json_object_is_type(halOrigCaptureJ, json_type_array)) {
- halNewCaptureJ = halOrigCaptureJ;
- json_object_array_add(halNewCaptureJ, btCaptureJ);
- }
- else if(json_object_is_type(halOrigCaptureJ, json_type_object)) {
- json_object_get(halOrigCaptureJ);
- json_object_object_del(halMixerJ, "captures");
- halNewCaptureJ = json_object_new_array();
- json_object_array_add(halNewCaptureJ, halOrigCaptureJ);
- json_object_array_add(halNewCaptureJ, btCaptureJ);
- json_object_object_add(halMixerJ, "captures", halNewCaptureJ);
- }
- else {
- AFB_ApiError(plugin->api, "Unrecognized 'halmixer' captures format");
- return -11;
- }
-
- btStreamJ = json_tokener_parse(MIXER_BT_STREAM_JSON_SECTION);
- json_object_object_add(btStreamJ, "zone", json_object_new_string(btStreamZone));
-
- if(! json_object_object_get_ex(halMixerJ, "streams", &halOrigStreamJ)) {
- halNewStreamJ = json_object_new_array();
- json_object_array_add(halNewStreamJ, btStreamJ);
- json_object_object_add(halMixerJ, "streams", halNewStreamJ);
- }
- else if(json_object_is_type(halOrigStreamJ, json_type_array)) {
- halNewStreamJ = halOrigStreamJ;
- json_object_array_add(halNewStreamJ, btStreamJ);
- }
- else if(json_object_is_type(halOrigStreamJ, json_type_object)) {
- json_object_get(halOrigStreamJ);
- json_object_object_del(halMixerJ, "streams");
- halNewStreamJ = json_object_new_array();
- json_object_array_add(halNewStreamJ, halOrigStreamJ);
- json_object_array_add(halNewStreamJ, btStreamJ);
- json_object_object_add(halMixerJ, "streams", halNewStreamJ);
- }
- else {
- AFB_ApiError(plugin->api, "Unrecognized 'halmixer' streams format");
- return -12;
- }
-
- currentBtPluginData->halBtPluginEnabled = 1;
-
- AFB_ApiNotice(plugin->api, "Plugin initialization of %s plugin correctly done", HAL_BT_PLUGIN_NAME);
-
- return 0;
-}
-
-// Call at contoller onload time
-CTLP_CAPI(init, source, argsJ, queryJ)
-{
- int err;
-
- char *returnedInfo;
-
- struct HalBtPluginData *currentBtPluginData;
-
- json_object *toSendJ, *returnedJ, *returnedBtList = NULL;
-
- if(! (currentBtPluginData = (struct HalBtPluginData *) getPluginContext(source->plugin))) {
- AFB_ApiError(source->api, "Can't get current %s plugin data", HAL_BT_PLUGIN_NAME);
- return -1;
- }
-
- if(! currentBtPluginData->halBtPluginEnabled) {
- AFB_ApiWarning(source->api, "Controller onload initialization of %s plugin cannot be done because bluetooth is not reachable", HAL_BT_PLUGIN_NAME);
- return 0;
- }
-
- AFB_ApiInfo(source->api, "Controller onload initialization of %s plugin", HAL_BT_PLUGIN_NAME);
-
- // Loading hal BT plugin specific verbs
- if(AFB_ApiAddVerb(source->api,
- HAL_BT_GET_STREAMING_STATUS_VERB,
- "Get Bluetooth streaming status",
- HalBtGetStreamingStatus,
- (void *) currentBtPluginData,
- NULL,
- 0,
- 0)) {
- AFB_ApiError(source->api, "Error while creating verb for bluetooth plugin : '%s'", HAL_BT_GET_STREAMING_STATUS_VERB);
- return -2;
- }
-
- if(AFB_ApiAddVerb(source->api,
- HAL_BT_SET_STREAMING_STATUS_VERB,
- "Set Bluetooth streaming status",
- HalBtSetStreamingStatus,
- (void *) currentBtPluginData,
- NULL,
- 0,
- 0)) {
- AFB_ApiError(source->api, "Error while creating verb for bluetooth plugin : '%s'", HAL_BT_SET_STREAMING_STATUS_VERB);
- return -3;
- }
-
- if(AFB_ApiAddVerb(source->api,
- HAL_BT_GET_CONNECTED_A2DP_DEVICES_VERB,
- "Get connected Bluetooth A2DP devices list",
- HalBtGetA2DPBluetoothDevices,
- (void *) currentBtPluginData,
- NULL,
- 0,
- 0)) {
- AFB_ApiError(source->api, "Error while creating verb for bluetooth plugin : '%s'", HAL_BT_GET_CONNECTED_A2DP_DEVICES_VERB);
- return -4;
- }
-
- if(AFB_ApiAddVerb(source->api,
- HAL_BT_GET_SELECTED_A2DP_DEVICE_VERB,
- "Get selected Bluetooth A2DP device",
- HalBtGetSelectedA2DPBluetoothDevice,
- (void *) currentBtPluginData,
- NULL,
- 0,
- 0)) {
- AFB_ApiError(source->api, "Error while creating verb for bluetooth plugin : '%s'", HAL_BT_GET_SELECTED_A2DP_DEVICE_VERB);
- return -5;
- }
-
- if(AFB_ApiAddVerb(source->api,
- HAL_BT_SET_SELECTED_A2DP_DEVICE_VERB,
- "Set selected Bluetooth A2DP device",
- HalBtSetSelectedA2DPBluetoothDevice,
- (void *) currentBtPluginData,
- NULL,
- 0,
- 0)) {
- AFB_ApiError(source->api, "Error while creating verb for bluetooth plugin : '%s'", HAL_BT_SET_SELECTED_A2DP_DEVICE_VERB);
- return -6;
- }
-
- // 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 (%s)",
- BT_MANAGER_SUBSCRIBE_VERB,
- BT_MANAGER_API,
- json_object_get_string(returnedJ));
-
- return -7;
- }
- else if(! wrap_json_unpack(returnedJ, "{s:{s:s}}", "request", "info", &returnedInfo)) {
- AFB_ApiError(source->api,
- "Couldn't subscribe to event '%s' during call to verb '%s' of api '%s' (error '%s')",
- BT_MANAGER_DEVICE_UPDATE_EVENT,
- BT_MANAGER_SUBSCRIBE_VERB,
- BT_MANAGER_API,
- returnedInfo);
- json_object_put(returnedJ);
- return -7;
- }
- json_object_put(returnedJ);
-
- if(AFB_ServiceSync(source->api, BT_MANAGER_API, BT_MANAGER_GET_DEVICES_VERB, NULL, &returnedJ)) {
- if((! wrap_json_unpack(returnedJ, "{s:{s:s}}", "request", "info", &returnedInfo)) &&
- (! strncmp(returnedInfo, "No find devices", strlen(returnedInfo)))) {
- AFB_ApiInfo(source->api,
- "No bluetooth devices returned by call to verb '%s' of '%s' api",
- BT_MANAGER_GET_DEVICES_VERB,
- BT_MANAGER_API);
- }
- else {
- AFB_ApiError(source->api,
- "Error during call to verb '%s' of '%s' api (%s)",
- BT_MANAGER_GET_DEVICES_VERB,
- BT_MANAGER_API,
- json_object_get_string(returnedJ));
-
- 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);
- json_object_put(returnedJ);
- return -8;
- }
-
- if((returnedBtList) && (err = HalBtDataHandleReceivedMutlipleBtDeviceData(currentBtPluginData, returnedBtList)))
- return (10 * err);
-
- json_object_put(returnedJ);
-
- if(currentBtPluginData->selectedBtDevice) {
- currentBtPluginData->btStreamEnabled = 1;
-
- AFB_ApiInfo(source->api, "Useable bluetooth device detected at initialization, will try to use it");
-
- if(HalBtMixerLinkSetBtStreamingSettings(source->api,
- currentBtPluginData->currentHalData->ctlHalSpecificData->mixerApiName,
- currentBtPluginData->btStreamEnabled,
- currentBtPluginData->selectedBtDevice->hci,
- currentBtPluginData->selectedBtDevice->address)) {
- AFB_ApiError(source->api,
- "Couldn't set bluetooth streaming settings during call to verb '%s' of api '%s'",
- MIXER_SET_STREAMED_BT_DEVICE_VERB,
- currentBtPluginData->currentHalData->ctlHalSpecificData->mixerApiName);
- return -9;
- }
- }
-
- AFB_ApiNotice(source->api, "Controller onload initialization of %s plugin correctly done", HAL_BT_PLUGIN_NAME);
-
- return 0;
-}
-
-// This receive Hal bluetooth plugin events
-CTLP_CAPI(events, source, argsJ, queryJ)
-{
- struct HalBtPluginData *currentBtPluginData;
-
- struct HalBtDeviceData *previouslySelectedBtDevice;
-
- if(! (currentBtPluginData = (struct HalBtPluginData *) getPluginContext(source->plugin))) {
- AFB_ApiError(source->api, "Can't get current %s plugin data", HAL_BT_PLUGIN_NAME);
- return -1;
- }
-
- if(! currentBtPluginData->halBtPluginEnabled) {
- AFB_ApiWarning(source->api, "Bluetooth event received but cannot be handled because bluetooth is not reachable");
- return 0;
- }
-
- previouslySelectedBtDevice = currentBtPluginData->selectedBtDevice;
-
- if(HalBtDataHandleReceivedSingleBtDeviceData(currentBtPluginData, queryJ)) {
- AFB_ApiError(source->api, "Error while decoding bluetooth event received json (%s)", json_object_get_string(queryJ));
- return -2;
- }
-
- if(currentBtPluginData->selectedBtDevice == previouslySelectedBtDevice) {
- AFB_ApiDebug(source->api, "Bluetooth event received but device didn't change");
- return 0;
- }
-
- if(currentBtPluginData->selectedBtDevice)
- currentBtPluginData->btStreamEnabled = 1;
- else
- currentBtPluginData->btStreamEnabled = 0;
-
- if(HalBtMixerLinkSetBtStreamingSettings(source->api,
- currentBtPluginData->currentHalData->ctlHalSpecificData->mixerApiName,
- currentBtPluginData->btStreamEnabled,
- currentBtPluginData->selectedBtDevice ? currentBtPluginData->selectedBtDevice->hci : NULL,
- currentBtPluginData->selectedBtDevice ? currentBtPluginData->selectedBtDevice->address : NULL)) {
- AFB_ApiError(source->api,
- "Couldn't set bluetooth streaming settings during call to verb '%s' of api '%s'",
- MIXER_SET_STREAMED_BT_DEVICE_VERB,
- currentBtPluginData->currentHalData->ctlHalSpecificData->mixerApiName);
- return -3;
- }
-
- return 0;
-} \ No newline at end of file