}
}
+static void update_hal_route_option(pa_hal_interface *hal_intf, const char *role, const char* name, int value)
+{
+ hal_route_option route_option;
+
+ memset(&route_option, 0, sizeof(hal_route_option));
+ route_option.role = role;
+ route_option.name = name;
+ route_option.value = value;
+
+ pa_hal_interface_update_route_option(hal_intf, &route_option);
+}
+
/* threre is only one sco connected device */
static pa_tz_device* _get_sco_connected_device(pa_device_manager *dm) {
pa_idxset *device_list;
}
-static int bt_sco_open(struct userdata *u) {
+static int bt_sco_open(struct userdata *u, const char *role) {
dm_device_bt_sco_status_t sco_status;
pa_tz_device *bt_device;
pa_assert(u);
+ pa_assert(role);
if (u->time_event_bt_sco_close) {
u->core->mainloop->time_free(u->time_event_bt_sco_close);
pa_log_warn("BT SCO is already opened for this BT device");
return 0;
}
+
+ if (pa_streq(role, STREAM_ROLE_VOICE_RECOGNITION) ||
+ pa_streq(role, STREAM_ROLE_VOICE_RECOGNITION_SERVICE))
+ pa_tz_device_sco_enable_pcm(bt_device, true);
+
if (pa_tz_device_sco_open(bt_device) < 0) {
pa_log_error("failed to open BT SCO");
return -1;
pa_log_warn("BT SCO is already closed for this BT device");
return 0;
}
+
+ pa_tz_device_sco_enable_pcm(bt_device, false);
+
if (delayed_close) {
/* request to close SCO after 3 sec. */
if (!u->time_event_bt_sco_close) {
}
/* Open/Close BT SCO if it is possible */
-static int update_bt_sco_state(struct userdata *u, bool open, bool delayed_close) {
+static int update_bt_sco_state(struct userdata *u, bool open, bool delayed_close, const char *role) {
pa_assert(u);
if (open)
- return bt_sco_open(u);
+ return bt_sco_open(u, role);
else
return bt_sco_close(u, delayed_close);
}
return pa_tz_device_sco_get_property(bt_device, is_wb, is_nrec);
}
+static void update_bt_sco_option(struct userdata *u, const char* role) {
+ bool is_wb = false;
+ bool is_nrec = false;
+
+ pa_assert(u);
+ pa_assert(role);
+
+ if (get_bt_property(u->device_manager, &is_wb, &is_nrec) == 0) {
+ pa_log_info("bt property : wideband(%d), nrec(%d)", is_wb, is_nrec);
+ update_hal_route_option(u->hal_interface, role, "bt-wideband", (int)is_wb);
+ update_hal_route_option(u->hal_interface, role, "bt-nrec", (int)is_nrec);
+ } else
+ pa_log_warn("Failed to get property for wideband / nrec....");
+}
+
/* Load/Unload module-loopback */
static void update_loopback_module(struct userdata *u, bool load) {
char *args = NULL;
return PA_HOOK_OK;
}
-static void update_bt_route_option(pa_hal_interface *hal_intf, const char *role, const char* name, int value)
-{
- hal_route_option route_option;
-
- memset(&route_option, 0, sizeof(hal_route_option));
- route_option.role = role;
- route_option.name = name;
- route_option.value = value;
-
- pa_hal_interface_update_route_option(hal_intf, &route_option);
-}
-
static void reset_route(struct userdata *u, stream_type_t stream_type) {
hal_route_info route_info = {NULL, NULL, 0};
pa_sink *null_sink = NULL;
}
/* update BT SCO: close */
- update_bt_sco_state(u, false, true);
+ update_bt_sco_state(u, false, true, NULL);
/* unload combine sink */
if (stream_type == STREAM_SINK_INPUT) {
}
if (pa_streq(dm_device_type, DEVICE_TYPE_BT_SCO)) {
- if (IS_ROLE_AVAILABLE_BT_SCO_OPEN(route_info.role))
- update_bt_sco_state(u, true, false);
+ if (IS_ROLE_AVAILABLE_BT_SCO_OPEN(route_info.role)) {
+ if (update_bt_sco_state(u, true, false, route_info.role)) {
+ pa_log_error(" ** could not open BT SCO");
+ return PA_HOOK_CANCEL;
+ }
+ update_bt_sco_option(u, route_info.role);
+ }
} else {
- update_bt_sco_state(u, false, false);
+ update_bt_sco_state(u, false, false, NULL);
}
break;
uint32_t s_idx = 0;
void *s = NULL;
- update_bt_sco_state(u, false, false);
+ update_bt_sco_state(u, false, false, NULL);
/* find the proper sink/source */
/* currently, we support two sinks for combining */
}
if (pa_streq(dm_device_type, DEVICE_TYPE_BT_SCO)) {
- if (IS_ROLE_AVAILABLE_BT_SCO_OPEN(route_info.role))
- update_bt_sco_state(u, true, false);
+ if (IS_ROLE_AVAILABLE_BT_SCO_OPEN(route_info.role)) {
+ if (update_bt_sco_state(u, true, false, route_info.role)) {
+ pa_log_error(" ** could not open BT SCO");
+ return PA_HOOK_CANCEL;
+ }
+ update_bt_sco_option(u, route_info.role);
+ }
} else {
- update_bt_sco_state(u, false, false);
+ update_bt_sco_state(u, false, false, NULL);
}
/* Update device with latest_device to use be used later in this function */
dm_device_type, dm_device_direction);
/* Check for availability for opening Bluetooth SCO */
if (pa_streq(dm_device_type, DEVICE_TYPE_BT_SCO) && IS_ROLE_AVAILABLE_BT_SCO_OPEN(route_info.role)) {
- bool is_wb = false;
- bool is_nrec = false;
-
/* update BT SCO: open */
- if (update_bt_sco_state(u, true, false)) {
+ if (update_bt_sco_state(u, true, false, route_info.role)) {
pa_log_error(" ** could not open BT SCO");
return PA_HOOK_CANCEL;
}
-
- if (get_bt_property(u->device_manager, &is_wb, &is_nrec) == 0) {
- pa_log_info("bt property : wideband(%d), nrec(%d)", is_wb, is_nrec);
- update_bt_route_option(u->hal_interface, route_info.role, "bt-wideband", (int)is_wb);
- update_bt_route_option(u->hal_interface, route_info.role, "bt-nrec", (int)is_nrec);
- } else
- pa_log_warn("Failed to get property for wideband / nrec....");
+ update_bt_sco_option(u, route_info.role);
} else {
/* update BT SCO: close */
- update_bt_sco_state(u, false, false);
+ update_bt_sco_state(u, false, false, NULL);
}
/* Check for in/out devices in case of loopback */
if (pa_streq(data->stream_role, STREAM_ROLE_LOOPBACK)) {
#define IS_ROLE_AVAILABLE_BT_SCO_OPEN(stream_role) \
(stream_role && (pa_streq(stream_role, STREAM_ROLE_CALL_VOICE) || pa_streq(stream_role, STREAM_ROLE_CALL_VIDEO) || \
pa_streq(stream_role, STREAM_ROLE_VOIP) || pa_streq(stream_role, STREAM_ROLE_RINGBACKTONE_CALL) || \
- pa_streq(stream_role, STREAM_ROLE_VOICE_RECOGNITION)))
+ pa_streq(stream_role, STREAM_ROLE_VOICE_RECOGNITION) || pa_streq(stream_role, STREAM_ROLE_VOICE_RECOGNITION_SERVICE)))
#define CONVERT_TO_DEVICE_ROLE(x_stream_role, x_device_role) \
do { \
#define GET_STREAM_PROPLIST(stream, type) \
(type == STREAM_SINK_INPUT ? ((pa_sink_input*)stream)->proplist : ((pa_source_output*)stream)->proplist)
-#define STREAM_ROLE_MEDIA "media"
-#define STREAM_ROLE_RINGTONE_CALL "ringtone-call"
-#define STREAM_ROLE_RINGBACKTONE_CALL "ringbacktone-call"
-#define STREAM_ROLE_RINGTONE_VOIP "ringtone-voip"
-#define STREAM_ROLE_CALL_VOICE "call-voice"
-#define STREAM_ROLE_CALL_VIDEO "call-video"
-#define STREAM_ROLE_VOIP "voip"
-#define STREAM_ROLE_LOOPBACK "loopback"
-#define STREAM_ROLE_LOOPBACK_MIRRORING "loopback-mirroring"
-#define STREAM_ROLE_RADIO "radio"
-#define STREAM_ROLE_SOLO "solo"
-#define STREAM_ROLE_VOICE_RECOGNITION "voice-recognition"
-#define STREAM_ROLE_VOICE_INFORMATION "voice-information"
+#define STREAM_ROLE_MEDIA "media"
+#define STREAM_ROLE_RINGTONE_CALL "ringtone-call"
+#define STREAM_ROLE_RINGBACKTONE_CALL "ringbacktone-call"
+#define STREAM_ROLE_RINGTONE_VOIP "ringtone-voip"
+#define STREAM_ROLE_CALL_VOICE "call-voice"
+#define STREAM_ROLE_CALL_VIDEO "call-video"
+#define STREAM_ROLE_VOIP "voip"
+#define STREAM_ROLE_LOOPBACK "loopback"
+#define STREAM_ROLE_LOOPBACK_MIRRORING "loopback-mirroring"
+#define STREAM_ROLE_RADIO "radio"
+#define STREAM_ROLE_SOLO "solo"
+#define STREAM_ROLE_VOICE_RECOGNITION "voice-recognition"
+#define STREAM_ROLE_VOICE_RECOGNITION_SERVICE "voice-recognition-service"
+#define STREAM_ROLE_VOICE_INFORMATION "voice-information"
#define SINK_NAME_COMBINED "sink_combined"
#define SINK_NAME_NULL "sink_null"
return stream_id_set;
}
+static int method_call_bt_sco_enable_pcm(pa_dbus_connection *conn, bool enable) {
+ DBusMessage *msg, *reply;
+ DBusError err;
+ const char *method = "SetVoiceDial";
+
+ pa_assert(conn);
+
+ if (!(msg = dbus_message_new_method_call(DBUS_SERVICE_HFP_AGENT, DBUS_OBJECT_HFP_AGENT, DBUS_INTERFACE_HFP_AGENT, method))) {
+ pa_log_error("dbus method call failed");
+ return -1;
+ }
+
+ dbus_error_init(&err);
+ dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &enable, DBUS_TYPE_INVALID);
+ if (!(reply = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(conn), msg, -1, &err))) {
+ pa_log_error("Failed to method call %s.%s, %s", DBUS_INTERFACE_HFP_AGENT, method, err.message);
+ dbus_error_free(&err);
+ return -1;
+ }
+
+ dbus_message_unref(reply);
+ return 0;
+}
+
static int method_call_bt_sco(pa_dbus_connection *conn, bool onoff) {
DBusMessage *msg, *reply;
DBusError err;
return 0;
}
+/* only for bt sco device */
+int pa_tz_device_sco_enable_pcm(pa_tz_device *device, bool enable) {
+ pa_assert(device);
+ pa_assert(device->dbus_conn);
+
+ pa_log_info("BT SCO PCM[device id:%u, enable: %d]", device->id, enable);
+ if (device_type_is_equal(device->type, DEVICE_TYPE_BT_SCO) == false) {
+ pa_log_error("Not BT SCO device");
+ return -1;
+ }
+
+ if (enable && device->sco_opened) {
+ pa_log_info("BT SCO is already opened, skip enable pcm");
+ return 0;
+ }
+
+ if (method_call_bt_sco_enable_pcm(device->dbus_conn, enable) < 0) {
+ pa_log_error("Failed to bt sco enable pcm");
+ return -1;
+ }
+
+ pa_log_info("BT SCO PCM enable[%d]- SUCCESS", enable);
+
+ return 0;
+}
+
/* only for bt sco device */
int pa_tz_device_sco_open(pa_tz_device *device) {
pa_assert(device);