6 #include <pulse/proplist.h>
7 #include <pulse/util.h>
8 #include <pulse/rtclock.h>
9 #include <pulsecore/log.h>
10 #include <pulsecore/core-util.h>
11 #include <pulsecore/strbuf.h>
13 #include "tizen-device.h"
15 #define DBUS_SERVICE_HFP_AGENT "org.bluez.ag_agent"
16 #define DBUS_OBJECT_HFP_AGENT "/org/bluez/hfp_agent"
17 #define DBUS_INTERFACE_HFP_AGENT "Org.Hfp.App.Interface"
19 #define BT_CVSD_CODEC_ID 1 // narrow-band
20 #define BT_MSBC_CODEC_ID 2 // wide-band
23 int values[MAX_INTSET_NUM];
28 int device_id_max_g = 1;
29 uint32_t event_id_max_g = 1;
31 static uint32_t _new_event_id() {
32 return event_id_max_g++;
35 int pa_intset_put(pa_intset *s, int val) {
40 if (s->write_index >= MAX_INTSET_NUM)
43 for(i = 0; i < s->write_index; i++) {
44 if (s->values[i] == val)
48 s->values[s->write_index++] = val;
53 pa_intset* pa_intset_new() {
56 s = pa_xmalloc0(sizeof(pa_intset));
63 void pa_intset_free(pa_intset *s) {
68 int pa_intset_first(pa_intset *s, int *val) {
72 if (s->write_index == 0)
76 *val = s->values[s->read_index++];
81 int pa_intset_next(pa_intset *s, int *val) {
85 if (s->read_index >= s->write_index)
88 *val = s->values[s->read_index++];
93 static char* get_playback_list_str(pa_hashmap *playback_devices) {
99 if (!playback_devices || !pa_hashmap_size(playback_devices))
102 buf = pa_strbuf_new();
103 pa_strbuf_printf(buf, " Playback device list\n");
104 PA_HASHMAP_FOREACH_KV(role, sink, playback_devices, state)
105 pa_strbuf_printf(buf, " %-13s -> %s\n", role, sink->name);
107 return pa_strbuf_to_string_free(buf);
110 static char* get_capture_list_str(pa_hashmap *capture_devices) {
111 pa_source *source = NULL;
116 if (!capture_devices || !pa_hashmap_size(capture_devices))
119 buf = pa_strbuf_new();
120 pa_strbuf_printf(buf, " Capture device list\n");
121 PA_HASHMAP_FOREACH_KV(role, source, capture_devices, state)
122 pa_strbuf_printf(buf, " %-13s -> %s\n", role, source->name);
124 return pa_strbuf_to_string_free(buf);
127 static char* _device_get_info_str(pa_tz_device *device) {
129 char *playback_str, *capture_str;
134 buf = pa_strbuf_new();
135 pa_strbuf_printf(buf, "[Device #%u]\n", device->id);
136 pa_strbuf_printf(buf, " ID : %u\n", device->id);
137 pa_strbuf_printf(buf, " Type : %s\n", device->type);
138 pa_strbuf_printf(buf, " Name : %s\n", device->name);
139 pa_strbuf_printf(buf, " System ID : %s\n", device->system_id);
140 pa_strbuf_printf(buf, " Direction : %s\n", device_direction_to_string(device->direction));
141 pa_strbuf_printf(buf, " Is activated : %s\n", pa_yes_no(device->state == DM_DEVICE_STATE_ACTIVATED));
142 pa_strbuf_printf(buf, " Internal : %s\n", pa_yes_no(device->use_internal_codec));
143 if (device_type_is_equal(device->type, DEVICE_TYPE_USB_AUDIO)) {
144 pa_strbuf_printf(buf, " Vendor ID : %04x\n", device->vendor_id);
145 pa_strbuf_printf(buf, " Product ID : %04x\n", device->product_id);
147 if (device_type_is_equal(device->type, DEVICE_TYPE_BT_SCO))
148 pa_strbuf_printf(buf, " SCO opened : %s\n", pa_yes_no(device->sco_opened));
149 playback_str = get_playback_list_str(device->playback_devices);
150 capture_str = get_capture_list_str(device->capture_devices);
153 pa_strbuf_puts(buf, playback_str);
155 pa_strbuf_puts(buf, capture_str);
157 pa_xfree(playback_str);
158 pa_xfree(capture_str);
160 return pa_strbuf_to_string_free(buf);
164 void pa_tz_device_dump_info(pa_tz_device *device, pa_log_level_t log_level) {
170 if ((info = _device_get_info_str(device))) {
171 pa_logl(log_level, "%s", info);
176 static void notify_device_connection_changed(pa_tz_device *device, bool connected) {
177 pa_tz_device_hook_data_for_conn_changed hook_data;
179 hook_data.event_id = _new_event_id();
180 hook_data.is_connected = connected;
181 hook_data.device = device;
183 pa_log_info("Fire hook for device connection changed, device(%s/%u) %s",
184 device->type, device->id, connected ? "connected" : "disconnected");
185 pa_hook_fire(pa_communicator_hook(device->comm, PA_COMMUNICATOR_HOOK_DEVICE_CONNECTION_CHANGED), &hook_data);
188 static void notify_device_state_changed(pa_tz_device *device, dm_device_state_t state) {
189 pa_tz_device_hook_data_for_state_changed hook_data;
191 hook_data.event_id = _new_event_id();
192 hook_data.activated = (state == DM_DEVICE_STATE_ACTIVATED) ? true : false;
193 hook_data.device = device;
195 pa_log_info("Fire hook for device state changed, device(%s/%u) %s",
196 device->type, device->id, hook_data.activated ? "Activated" : "De-activated");
197 pa_hook_fire(pa_communicator_hook(device->comm, PA_COMMUNICATOR_HOOK_DEVICE_STATE_CHANGED), &hook_data);
200 static void notify_device_running_changed(pa_tz_device *device, bool running) {
201 pa_tz_device_hook_data_for_running_changed hook_data;
203 hook_data.event_id = _new_event_id();
204 hook_data.is_running = running;
205 hook_data.device = device;
207 pa_log_info("Fire hook for device running changed, device(%s/%u) %s",
208 device->type, device->id, hook_data.is_running ? "Running" : "Not running");
209 pa_hook_fire(pa_communicator_hook(device->comm, PA_COMMUNICATOR_HOOK_DEVICE_RUNNING_CHANGED), &hook_data);
212 /* pa_tz_device_new_data */
213 void pa_tz_device_new_data_init(pa_tz_device_new_data *data, pa_idxset *list,
214 pa_communicator *comm, pa_dbus_connection *conn) {
221 data->dbus_conn = conn;
225 data->system_id = NULL;
226 data->vendor_id = -1;
227 data->product_id = -1;
228 data->direction = DM_DEVICE_DIRECTION_NONE;
230 data->playback_pcms= pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
231 data->capture_pcms = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
234 void pa_tz_device_new_data_set_type(pa_tz_device_new_data *data, const char *type) {
237 data->type = pa_xstrdup(type);
240 void pa_tz_device_new_data_set_name(pa_tz_device_new_data *data, const char *name) {
243 data->name = pa_xstrdup(name);
246 void pa_tz_device_new_data_set_direction(pa_tz_device_new_data *data, dm_device_direction_t direction) {
249 data->direction = direction;
251 /* only for external? */
252 void pa_tz_device_new_data_set_system_id(pa_tz_device_new_data *data, const char *system_id) {
255 data->system_id = pa_xstrdup(system_id);
258 void pa_tz_device_new_data_set_vendor_id(pa_tz_device_new_data *data, int vendor_id) {
261 data->vendor_id = vendor_id;
264 void pa_tz_device_new_data_set_product_id(pa_tz_device_new_data *data, int product_id) {
267 data->product_id = product_id;
270 void pa_tz_device_new_data_set_use_internal_codec(pa_tz_device_new_data *data, bool use_internal_codec) {
273 data->use_internal_codec = use_internal_codec;
276 void pa_tz_device_new_data_add_sink(pa_tz_device_new_data *data, const char *role, pa_sink *sink) {
279 pa_hashmap_put(data->playback_pcms, (void*)role, sink);
282 void pa_tz_device_new_data_add_source(pa_tz_device_new_data *data, const char *role, pa_source *source) {
285 pa_hashmap_put(data->capture_pcms, (void*)role, source);
288 void pa_tz_device_new_data_done(pa_tz_device_new_data *data) {
291 pa_xfree(data->type);
292 pa_xfree(data->name);
295 static int _check_valid_device_new_data(pa_tz_device_new_data *data) {
298 if (data->type == NULL) {
299 pa_log_error("new data type is null");
303 if (data->direction == DM_DEVICE_DIRECTION_NONE) {
304 pa_log_error("new data direction is none");
311 static int device_add_sink(pa_tz_device *device, const char *role, pa_sink *sink) {
313 pa_assert(device->playback_devices);
315 if (pa_hashmap_put(device->playback_devices, (void*)role, sink) < 0) {
316 pa_log_error("Failed to add sink : put sink failed");
322 static int device_add_source(pa_tz_device *device, const char *role, pa_source *source) {
324 pa_assert(device->capture_devices);
326 if (pa_hashmap_put(device->capture_devices, (void*)role, source) < 0) {
327 pa_log_error("Failed to add source : put source failed");
333 static pa_sink* device_get_sink(pa_tz_device *device, const char *role) {
336 pa_assert(device->playback_devices);
338 if ((sink = pa_hashmap_get(device->playback_devices, role)) == NULL) {
339 pa_log_warn("Failed to get sink for %s", role);
346 static pa_source* device_get_source(pa_tz_device *device, const char *role) {
349 pa_assert(device->capture_devices);
351 if ((source = pa_hashmap_get(device->capture_devices, role)) == NULL) {
352 pa_log_warn("Failed to get source for %s", role);
359 static void device_set_state(pa_tz_device *device, dm_device_state_t new_state) {
362 if (device->state != new_state) {
363 pa_log_debug("change state %d -> %d", device->state, new_state);
364 device->state = new_state;
365 notify_device_state_changed(device, new_state);
366 pa_tz_device_dump_info(device, PA_LOG_DEBUG);
368 pa_log_debug("same state, not change it");
372 static dm_device_state_t device_get_state(pa_tz_device *device) {
374 return device->state;
377 static void device_set_running_and_notify(pa_tz_device *device, bool running) {
380 if (device->is_running != running) {
381 pa_log_debug("change running state %d -> %d", device->is_running, running);
382 device->is_running = running;
383 notify_device_running_changed(device, running);
384 pa_tz_device_dump_info(device, PA_LOG_DEBUG);
386 pa_log_debug("same running state, not change it");
390 static int device_remove_sink_with_role(pa_tz_device *device, const char *role) {
394 sink = pa_hashmap_remove(device->playback_devices, role);
395 return sink ? 0 : -1;
398 static int device_remove_source_with_role(pa_tz_device *device, const char *role) {
402 source = pa_hashmap_remove(device->capture_devices, role);
403 return source ? 0 : -1;
406 static int device_remove_sink(pa_tz_device *device, pa_sink *sink) {
413 PA_HASHMAP_FOREACH_KV(role, _sink, device->playback_devices, state) {
415 return device_remove_sink_with_role(device, role);
421 static int device_remove_source(pa_tz_device *device, pa_source *source) {
428 PA_HASHMAP_FOREACH_KV(role, _source, device->capture_devices, state) {
429 if (source == _source)
430 return device_remove_source_with_role(device, role);
437 pa_tz_device* pa_tz_device_new(pa_tz_device_new_data *data) {
438 pa_tz_device *device;
444 if (_check_valid_device_new_data(data) < 0) {
445 pa_log_error("Invalid device_new_data");
449 device = pa_xmalloc(sizeof(pa_tz_device));
450 device->list = data->list;
451 device->comm = data->comm;
452 device->dbus_conn = data->dbus_conn;
454 device->id = device_id_max_g++;
455 device->type = pa_xstrdup(data->type);
457 device->name = pa_xstrdup(data->name);
459 device->name = pa_xstrdup(data->type);
460 device->system_id = pa_xstrdup(data->system_id);
461 device->vendor_id = data->vendor_id;
462 device->product_id = data->product_id;
464 pa_log_info("New device type(%s) id(%u) name(%s) system_id(%s) vendor_id(%04x) product_id(%04x)",
465 device->type, device->id, device->name, pa_strempty(device->system_id),
466 device->vendor_id, device->product_id);
468 device->playback_devices = data->playback_pcms;
469 device->capture_devices = data->capture_pcms;
470 device->direction = data->direction;
471 device->state = DM_DEVICE_STATE_DEACTIVATED;
472 device->creation_time = pa_rtclock_now();
473 device->use_internal_codec = data->use_internal_codec;
474 device->sco_opened = false;
475 device->is_running = false;
477 if (device_type_is_use_external_card(device->type)) {
478 if ((sink = device_get_sink(device, DEVICE_ROLE_NORMAL)))
479 sink->device_item = device;
480 if ((source = device_get_source(device, DEVICE_ROLE_NORMAL)))
481 source->device_item = device;
484 pa_idxset_put(device->list, device, NULL);
485 notify_device_connection_changed(device, true);
487 pa_tz_device_dump_info(device, PA_LOG_INFO);
492 int pa_tz_device_add_sink(pa_tz_device *device, const char *role, pa_sink *sink) {
494 pa_assert(device_role_is_valid(role));
497 pa_log_info("device add sink, device(%u) role(%s) sink(%s)",
498 device->id, role, sink->name);
500 if (device_add_sink(device, role, sink) < 0) {
501 pa_log_error("Failed to add sink : Can't add to device");
508 int pa_tz_device_add_source(pa_tz_device *device, const char *role, pa_source *source) {
510 pa_assert(device_role_is_valid(role));
513 pa_log_info("device add source, device(%u) role(%s) source(%s)",
514 device->id, role, source->name);
516 if (device_add_source(device, role, source) < 0) {
517 pa_log_error("Failed to add source : Can't add to device");
524 int pa_tz_device_remove_sink(pa_tz_device *device, pa_sink *sink) {
528 pa_log_info("device remove sink, device(%u) sink(%s)",
529 device->id, sink->name);
531 return device_remove_sink(device, sink);
534 int pa_tz_device_remove_source(pa_tz_device *device, pa_source *source) {
538 pa_log_info("device remove source, device(%u) source(%s)",
539 device->id, source->name);
541 return device_remove_source(device, source);
544 int pa_tz_device_remove_sink_with_role(pa_tz_device *device, const char *role) {
546 pa_assert(device_role_is_valid(role));
548 pa_log_info("device remove sink with role, device(%u) role(%s)",
551 return device_remove_sink_with_role(device, role);
554 int pa_tz_device_remove_source_with_role(pa_tz_device *device, const char *role) {
556 pa_assert(device_role_is_valid(role));
558 pa_log_info("device remove source with role, device(%u) role(%s)",
561 return device_remove_source_with_role(device, role);
564 void pa_tz_device_free(pa_tz_device *device) {
571 pa_log_info("Free device type(%s) id(%u) name(%s) system_id(%s)",
572 device->type, device->id, device->name, device->system_id);
574 pa_tz_device_dump_info(device, PA_LOG_INFO);
576 pa_idxset_remove_by_data(device->list, device, NULL);
578 if (device->playback_devices)
579 PA_HASHMAP_FOREACH(sink, device->playback_devices, state)
580 sink->device_item = NULL;
582 if (device->capture_devices)
583 PA_HASHMAP_FOREACH(source, device->capture_devices, state)
584 source->device_item = NULL;
586 notify_device_connection_changed(device, false);
588 pa_xfree(device->type);
589 pa_xfree(device->name);
590 pa_xfree(device->system_id);
596 pa_sink* pa_tz_device_get_sink(pa_tz_device *device, const char *role) {
601 pa_log_info("device get sink, device(%u) role(%s)", device->id, role);
603 if ((sink = device_get_sink(device, role)) == NULL) {
604 pa_log_error("Failed to get sink from device");
611 pa_source* pa_tz_device_get_source(pa_tz_device *device, const char *role) {
616 pa_log_info("device get source, device(%u) role(%s)",
619 if ((source = device_get_source(device, role)) == NULL) {
620 pa_log_error("Failed to get source from device");
627 /* TODO : Change param dm_device_state_t to bool or pa_tz_device_state_t,
628 * Because this state represent pa_tz_device's own state */
629 void pa_tz_device_set_state(pa_tz_device *device, dm_device_state_t state) {
632 pa_log_info("device set state, device(%u) type(%s) -> %d",
633 device->id, device->type, state);
634 device_set_state(device, state);
637 dm_device_state_t pa_tz_device_get_state(pa_tz_device *device) {
640 return device_get_state(device);
643 void pa_tz_device_set_running_and_notify(pa_tz_device *device, bool running) {
646 pa_log_info("device set running, device(%u) type(%s) -> %d (0:not running, 1:running)",
647 device->id, device->type, running);
648 device_set_running_and_notify(device, running);
651 bool pa_tz_device_is_running(pa_tz_device *device) {
654 return device->is_running;
657 uint32_t pa_tz_device_get_id(pa_tz_device *device) {
663 char* pa_tz_device_get_type(pa_tz_device *device) {
669 char* pa_tz_device_get_name(pa_tz_device *device) {
675 char* pa_tz_device_get_system_id(pa_tz_device *device) {
678 return device->system_id;
681 int pa_tz_device_get_vendor_id(pa_tz_device *device) {
684 return device->vendor_id;
687 int pa_tz_device_get_product_id(pa_tz_device *device) {
690 return device->product_id;
693 dm_device_direction_t pa_tz_device_get_direction(pa_tz_device *device) {
696 return device->direction;
699 pa_usec_t pa_tz_device_get_creation_time(pa_tz_device *device) {
702 return device->creation_time;
705 bool pa_tz_device_is_use_internal_codec(pa_tz_device *device) {
708 return device->use_internal_codec;
711 bool pa_tz_device_is_all_suspended(pa_tz_device *device) {
716 PA_HASHMAP_FOREACH(sink, device->playback_devices, state) {
717 if (pa_sink_get_state(sink) != PA_SINK_SUSPENDED)
721 PA_HASHMAP_FOREACH(source, device->capture_devices, state) {
722 if (pa_source_get_state(source) != PA_SOURCE_SUSPENDED)
729 pa_intset* pa_tz_device_get_stream_list(pa_tz_device *device) {
732 pa_sink_input *input;
733 pa_source_output *output;
735 const char *p_id_str;
738 pa_intset *stream_id_set;
742 stream_id_set = pa_intset_new();
743 PA_HASHMAP_FOREACH(sink, device->playback_devices, state) {
744 PA_IDXSET_FOREACH(input, sink->inputs, idx) {
745 p_id_str = pa_proplist_gets(input->proplist, PA_PROP_MEDIA_PARENT_ID);
746 if (p_id_str && !pa_atoi(p_id_str, &p_id)) {
747 pa_intset_put(stream_id_set, p_id);
749 pa_log_warn("Invalid Parent ID : '%s'", pa_strnull(p_id_str));
753 PA_HASHMAP_FOREACH(source, device->capture_devices, state) {
754 PA_IDXSET_FOREACH(output, source->outputs, idx) {
755 p_id_str = pa_proplist_gets(output->proplist, PA_PROP_MEDIA_PARENT_ID);
756 if (p_id_str && !pa_atoi(p_id_str, &p_id)) {
757 pa_intset_put(stream_id_set, p_id);
759 pa_log_warn("Invalid Parent ID : '%s'", pa_strnull(p_id_str));
764 return stream_id_set;
767 static int method_call_bt_sco_enable_pcm(pa_dbus_connection *conn, bool enable) {
768 DBusMessage *msg, *reply;
770 const char *method = "SetVoiceDial";
774 if (!(msg = dbus_message_new_method_call(DBUS_SERVICE_HFP_AGENT, DBUS_OBJECT_HFP_AGENT, DBUS_INTERFACE_HFP_AGENT, method))) {
775 pa_log_error("dbus method call failed");
779 dbus_error_init(&err);
780 dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &enable, DBUS_TYPE_INVALID);
781 if (!(reply = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(conn), msg, -1, &err))) {
782 pa_log_error("Failed to method call %s.%s, %s", DBUS_INTERFACE_HFP_AGENT, method, err.message);
783 dbus_error_free(&err);
787 dbus_message_unref(reply);
791 static int method_call_bt_sco(pa_dbus_connection *conn, bool onoff) {
792 DBusMessage *msg, *reply;
798 method = onoff ? "Play" : "Stop";
799 if (!(msg = dbus_message_new_method_call(DBUS_SERVICE_HFP_AGENT, DBUS_OBJECT_HFP_AGENT, DBUS_INTERFACE_HFP_AGENT, method))) {
800 pa_log_error("dbus method call failed");
804 dbus_error_init(&err);
805 if (!(reply = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(conn), msg, -1, &err))) {
806 pa_log_error("Failed to method call %s.%s, %s", DBUS_INTERFACE_HFP_AGENT, method, err.message);
807 dbus_error_free(&err);
811 dbus_message_unref(reply);
815 static int method_call_bt_sco_get_property(pa_dbus_connection *conn, bool *is_wide_band, bool *is_nrec) {
816 DBusMessage *msg, *reply;
817 DBusMessageIter reply_iter, reply_iter_entry;
821 const char *property;
825 if (!is_wide_band && !is_nrec) {
829 if (!(msg = dbus_message_new_method_call(DBUS_SERVICE_HFP_AGENT, DBUS_OBJECT_HFP_AGENT, DBUS_INTERFACE_HFP_AGENT, "GetProperties"))) {
830 pa_log_error("dbus method call failed");
834 dbus_error_init(&err);
835 if (!(reply = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(conn), msg, -1, &err))) {
836 pa_log_error("Failed to method call %s.%s, %s", DBUS_INTERFACE_HFP_AGENT, "GetProperties", err.message);
837 dbus_error_free(&err);
841 dbus_message_iter_init(reply, &reply_iter);
843 if (dbus_message_iter_get_arg_type(&reply_iter) != DBUS_TYPE_ARRAY) {
844 pa_log_error("Cannot get reply argument");
848 dbus_message_iter_recurse(&reply_iter, &reply_iter_entry);
850 while (dbus_message_iter_get_arg_type(&reply_iter_entry) == DBUS_TYPE_DICT_ENTRY) {
851 DBusMessageIter dict_entry, dict_entry_val;
852 dbus_message_iter_recurse(&reply_iter_entry, &dict_entry);
853 dbus_message_iter_get_basic(&dict_entry, &property);
854 pa_log_debug("String received = %s", property);
856 if (pa_streq("codec", property) && is_wide_band) {
857 dbus_message_iter_next(&dict_entry);
858 dbus_message_iter_recurse(&dict_entry, &dict_entry_val);
859 if (dbus_message_iter_get_arg_type(&dict_entry_val) != DBUS_TYPE_UINT32)
861 dbus_message_iter_get_basic(&dict_entry_val, &codec);
862 pa_log_debug("Codec = [%d]", codec);
863 *is_wide_band = (codec == BT_MSBC_CODEC_ID) ? true : false;
864 } else if (pa_streq("nrec", property) && is_nrec) {
865 dbus_message_iter_next(&dict_entry);
866 dbus_message_iter_recurse(&dict_entry, &dict_entry_val);
867 if (dbus_message_iter_get_arg_type(&dict_entry_val) != DBUS_TYPE_BOOLEAN)
869 dbus_message_iter_get_basic(&dict_entry_val, &nrec);
870 pa_log_debug("nrec= [%d]", nrec);
874 dbus_message_iter_next(&reply_iter_entry);
878 dbus_message_unref(reply);
882 /* only for bt sco device */
883 int pa_tz_device_sco_enable_pcm(pa_tz_device *device, bool enable) {
885 pa_assert(device->dbus_conn);
887 pa_log_info("BT SCO PCM[device id:%u, enable: %d]", device->id, enable);
888 if (device_type_is_equal(device->type, DEVICE_TYPE_BT_SCO) == false) {
889 pa_log_error("Not BT SCO device");
893 if (enable && device->sco_opened) {
894 pa_log_info("BT SCO is already opened, skip enable pcm");
898 if (method_call_bt_sco_enable_pcm(device->dbus_conn, enable) < 0) {
899 pa_log_error("Failed to bt sco enable pcm");
903 pa_log_info("BT SCO PCM enable[%d]- SUCCESS", enable);
908 /* only for bt sco device */
909 int pa_tz_device_sco_open(pa_tz_device *device) {
911 pa_assert(device->dbus_conn);
913 pa_log_info("BT SCO Open for device(%u)", device->id);
914 if (device_type_is_equal(device->type, DEVICE_TYPE_BT_SCO) == false) {
915 pa_log_error("Not BT SCO device");
919 if (device->sco_opened) {
920 pa_log_warn("SCO already opened");
924 if (method_call_bt_sco(device->dbus_conn, true) < 0) {
925 pa_log_error("Failed to bt sco on");
929 device->sco_opened = true;
930 device->creation_time = pa_rtclock_now();
931 pa_tz_device_dump_info(device, PA_LOG_DEBUG);
932 pa_log_info("BT SCO Open - SUCCESS");
937 /* only for bt sco device */
938 int pa_tz_device_sco_close(pa_tz_device *device) {
941 pa_log_info("BT SCO Close for device(%u)", device->id);
943 if (device_type_is_equal(device->type, DEVICE_TYPE_BT_SCO) == false) {
944 pa_log_error("Not BT SCO device");
948 if (device->sco_opened == false) {
949 pa_log_warn("SCO not opened");
953 if (method_call_bt_sco(device->dbus_conn, false) < 0) {
954 pa_log_error("Failed to bt sco on");
958 device->sco_opened = false;
959 pa_tz_device_dump_info(device, PA_LOG_DEBUG);
960 pa_log_info("BT SCO Close - Success");
965 /* only for bt sco device */
966 int pa_tz_device_sco_get_property(pa_tz_device *device, bool *is_wide_band, bool *nrec) {
969 pa_log_info("BT SCO get property for device(%u)", device->id);
970 if (device_type_is_equal(device->type, DEVICE_TYPE_BT_SCO) == false) {
971 pa_log_error("Not BT device");
975 if (method_call_bt_sco_get_property(device->dbus_conn, is_wide_band, nrec) < 0) {
976 pa_log_error("Failed to get BT SCO Property");
980 pa_log_info("BT SCO Get Property - Success, is wide band : %s, nrec : %s", pa_yes_no(*is_wide_band), pa_yes_no(*nrec));
985 /* only for bt sco device */
986 int pa_tz_device_sco_get_status(pa_tz_device *device, dm_device_bt_sco_status_t *status) {
989 pa_log_debug("BT SCO get status for device(%u)", device->id);
990 if (device_type_is_equal(device->type, DEVICE_TYPE_BT_SCO) == false) {
991 pa_log_error("Not BT device");
994 if (status == NULL) {
995 pa_log_error("invalid parameter");
999 if (device->sco_opened == false)
1000 *status = DM_DEVICE_BT_SCO_STATUS_CONNECTED;
1002 *status = DM_DEVICE_BT_SCO_STATUS_OPENED;
1004 pa_log_info("BT SCO (%u) Get Status, %d", device->id, *status);