device-manager : Fix source bugs
[platform/core/multimedia/pulseaudio-modules-tizen.git] / src / tizen-device.c
1 #ifdef HAVE_CONFIG_H
2 #include <config.h>
3 #endif
4
5 #include <ctype.h>
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>
12
13 #include "tizen-device.h"
14
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"
18
19 #define BT_CVSD_CODEC_ID 1 // narrow-band
20 #define BT_MSBC_CODEC_ID 2 // wide-band
21
22 #define COMPOUND_STATE(d) (((pa_tz_profile*)d)->playback_state | ((pa_tz_profile*)d)->capture_state)
23
24 int device_id_max_g = 1;
25 uint32_t event_id_max_g = 1;
26
27 static uint32_t _new_event_id() {
28     return event_id_max_g++;
29 }
30
31 static char* get_playback_list_str(pa_hashmap *playback_devices) {
32     pa_sink *sink = NULL;
33     void *state = NULL;
34     const char *role;
35     pa_strbuf *buf;
36
37     if (!playback_devices || !pa_hashmap_size(playback_devices))
38         return NULL;
39
40     buf = pa_strbuf_new();
41     pa_strbuf_printf(buf, "    Playback device list\n");
42     PA_HASHMAP_FOREACH_KEY(sink, playback_devices, state, role)
43         pa_strbuf_printf(buf, "        %-13s -> %s\n", role, sink->name);
44
45     return pa_strbuf_tostring_free(buf);
46 }
47
48 static char* get_capture_list_str(pa_hashmap *capture_devices) {
49     pa_source *source = NULL;
50     void *state = NULL;
51     const char *role;
52     pa_strbuf *buf;
53
54     if (!capture_devices || !pa_hashmap_size(capture_devices))
55         return NULL;
56
57     buf = pa_strbuf_new();
58     pa_strbuf_printf(buf, "    Capture device list\n");
59     PA_HASHMAP_FOREACH_KEY(source, capture_devices, state, role)
60         pa_strbuf_printf(buf, "        %-13s -> %s\n", role, source->name);
61
62     return pa_strbuf_tostring_free(buf);
63 }
64
65 /* Returned string must be freed */
66 static char* get_device_profile_info_str(pa_tz_profile *profile) {
67     pa_strbuf *buf;
68     char *playback_str, *capture_str;
69     if (!profile)
70         return NULL;
71
72     buf = pa_strbuf_new();
73     pa_strbuf_printf(buf, "    Profile      : %s\n", pa_strna(profile->profile));
74     pa_strbuf_printf(buf, "    Direction    : %s\n", device_direction_to_string(profile->direction));
75     pa_strbuf_printf(buf, "    Is activated : %s\n", pa_yes_no(COMPOUND_STATE(profile) == DM_DEVICE_STATE_ACTIVATED));
76     pa_strbuf_printf(buf, "    Internal     : %s\n", pa_yes_no(profile->use_internal_codec));
77     if (profile->profile && pa_streq(profile->profile, DEVICE_PROFILE_BT_SCO))
78         pa_strbuf_printf(buf, "    SCO opened   : %s\n", pa_yes_no(profile->sco_opened));
79     playback_str = get_playback_list_str(profile->playback_devices);
80     capture_str = get_capture_list_str(profile->capture_devices);
81
82     if (playback_str)
83         pa_strbuf_puts(buf, playback_str);
84     if (capture_str)
85         pa_strbuf_puts(buf, capture_str);
86
87     pa_xfree(playback_str);
88     pa_xfree(capture_str);
89
90     return pa_strbuf_tostring_free(buf);
91 }
92
93 static char* _device_get_info_str(pa_tz_device *device) {
94     pa_strbuf *buf;
95     char *profile_info;
96     pa_tz_profile *profile;
97     uint32_t profile_idx;
98
99     if (!device)
100         return NULL;
101
102     buf = pa_strbuf_new();
103     pa_strbuf_printf(buf, "[Device #%u]\n", device->id);
104     pa_strbuf_printf(buf, "  ID             : %u\n", device->id);
105     pa_strbuf_printf(buf, "  Type           : %s\n", device->type);
106     pa_strbuf_printf(buf, "  Name           : %s\n", device->name);
107     if (device_type_is_multi_profile(device->type))
108         pa_strbuf_printf(buf, "  System ID      : %s\n", device->system_id);
109     pa_strbuf_printf(buf, "  Active Profile : %u\n", device->active_profile);
110
111     PA_IDXSET_FOREACH(profile, device->profiles, profile_idx) {
112         pa_strbuf_printf(buf, "  (Profile #%d)\n", profile_idx);
113         profile_info = get_device_profile_info_str(profile);
114         if (profile_info)
115             pa_strbuf_puts(buf, profile_info);
116         pa_xfree(profile_info);
117     }
118
119     return pa_strbuf_tostring_free(buf);
120 }
121
122
123 void pa_tz_device_dump_info(pa_tz_device *device, pa_log_level_t log_level) {
124     char *info;
125
126     if (!device)
127         return;
128
129     if ((info = _device_get_info_str(device))) {
130         pa_logl(log_level, "%s", info);
131         pa_xfree(info);
132     }
133 }
134
135 static void notify_device_connection_changed(pa_tz_device *device, bool connected) {
136     pa_device_manager_hook_data_for_conn_changed hook_data;
137     uint32_t event_id;
138
139     event_id = _new_event_id();
140
141     hook_data.event_id = event_id;
142     hook_data.is_connected = connected;
143     hook_data.device = device;
144
145     pa_log_info("Fire hook for device connection changed, device(%u) %s",
146             device->id, connected ? "connected" : "disconnected");
147     pa_hook_fire(pa_communicator_hook(device->comm, PA_COMMUNICATOR_HOOK_DEVICE_CONNECTION_CHANGED), &hook_data);
148 }
149
150 static void notify_device_info_changed(pa_tz_device *device, dm_device_changed_info_t changed_type) {
151     pa_device_manager_hook_data_for_info_changed hook_data;
152     uint32_t event_id;
153
154     event_id = _new_event_id();
155
156     hook_data.event_id = event_id;
157     hook_data.changed_info = changed_type;
158     hook_data.device = device;
159
160     pa_log_info("Fire hook for device info changed, device(%u) %s changed",
161             device->id, changed_type == DM_DEVICE_CHANGED_INFO_STATE ? "state" : "direction");
162     pa_hook_fire(pa_communicator_hook(device->comm, PA_COMMUNICATOR_HOOK_DEVICE_INFORMATION_CHANGED), &hook_data);
163 }
164
165 /* pa_tz_device_new_data */
166 void pa_tz_device_new_data_init(pa_tz_device_new_data *data, pa_idxset *list,
167         pa_communicator *comm, pa_dbus_connection *conn) {
168     pa_assert(data);
169     pa_assert(list);
170     pa_assert(comm);
171
172     data->list = list;
173     data->comm = comm;
174     data->dbus_conn = conn;
175
176     data->type = NULL;
177     data->name = NULL;
178     data->system_id = NULL;
179     data->direction = DM_DEVICE_DIRECTION_NONE;
180
181     data->playback_pcms= pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
182     data->capture_pcms = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
183
184     data->n_profile = 0;
185 }
186
187 void pa_tz_device_new_data_set_type(pa_tz_device_new_data *data, const char *type) {
188     pa_assert(data);
189
190     data->type = pa_xstrdup(type);
191 }
192
193 void pa_tz_device_new_data_set_name(pa_tz_device_new_data *data, const char *name) {
194     pa_assert(data);
195
196     data->name = pa_xstrdup(name);
197 }
198
199 void pa_tz_device_new_data_set_direction(pa_tz_device_new_data *data, dm_device_direction_t direction) {
200     pa_assert(data);
201
202     data->direction = direction;
203 }
204 /* only for external? */
205 void pa_tz_device_new_data_set_system_id(pa_tz_device_new_data *data, const char *system_id) {
206     pa_assert(data);
207
208     data->system_id = pa_xstrdup(system_id);
209 }
210
211 void pa_tz_device_new_data_set_use_internal_codec(pa_tz_device_new_data *data, bool use_internal_codec) {
212     pa_assert(data);
213
214     data->use_internal_codec = use_internal_codec;
215 }
216
217 void pa_tz_device_new_data_add_sink(pa_tz_device_new_data *data, const char *role, pa_sink *sink) {
218     pa_assert(data);
219
220     pa_hashmap_put(data->playback_pcms, (void*)role, sink);
221 }
222
223 void pa_tz_device_new_data_add_source(pa_tz_device_new_data *data, const char *role, pa_source *source) {
224     pa_assert(data);
225
226     pa_hashmap_put(data->capture_pcms, (void*)role, source);
227 }
228 /* after set_type, only for multi profile type, and check direction, profile */
229 void pa_tz_device_new_data_add_profile(pa_tz_device_new_data *data, pa_tz_profile_new_data *profile_data, bool as_active) {
230     uint32_t profile_idx;
231     pa_assert(data);
232
233     profile_idx = data->n_profile;
234     data->profile_data[profile_idx] = profile_data;
235     if (as_active)
236         data->active_profile = profile_idx;
237
238     data->n_profile++;
239 }
240
241 void pa_tz_device_new_data_done(pa_tz_device_new_data *data) {
242     pa_assert(data);
243
244     pa_xfree(data->type);
245     pa_xfree(data->name);
246 }
247
248 static int _check_valid_device_new_data(pa_tz_device_new_data *data) {
249     bool is_multi_profile;
250     pa_assert(data);
251
252     if (data->type == NULL) {
253         pa_log_error("new data type is null");
254         return -1;
255     }
256
257     is_multi_profile = device_type_is_multi_profile(data->type);
258
259     if (is_multi_profile == false && data->direction == DM_DEVICE_DIRECTION_NONE) {
260         pa_log_error("new data direction is none");
261         return -1;
262     }
263
264     if (is_multi_profile == true && data->n_profile == 0) {
265         pa_log_error("multi profile type, but there is no profile");
266         return -1;
267     }
268     if (is_multi_profile == false && data->n_profile > 0) {
269         pa_log_error("not multi profile type, but there are profile");
270         return -1;
271     }
272
273     return 0;
274 }
275
276 static pa_tz_profile* profile_new(char *profile_str, dm_device_direction_t direction,
277         pa_hashmap *playbacks, pa_hashmap *captures, bool use_internal_codec, pa_tz_device *device) {
278     pa_tz_profile *profile;
279
280     pa_log_info("New profile(%s) direction(%s), for device(%u)",
281             pa_strempty(profile_str), device_direction_to_string(direction), device->id);
282
283     profile = pa_xmalloc(sizeof(pa_tz_profile));
284
285     profile->profile = pa_xstrdup(profile_str);
286     profile->playback_devices = playbacks;
287     profile->capture_devices = captures;
288     profile->direction = direction;
289     profile->playback_state = DM_DEVICE_STATE_DEACTIVATED;
290     profile->capture_state = DM_DEVICE_STATE_DEACTIVATED;
291     profile->device = device;
292     profile->creation_time = pa_rtclock_now();
293     profile->use_internal_codec = use_internal_codec;
294     profile->sco_opened = false;
295
296     return profile;
297 }
298
299 static void profile_free(pa_tz_profile *profile) {
300     if (!profile)
301         return;
302
303     pa_log_info("Free profile(%s) for device(%u)",
304             pa_strempty(profile->profile), profile->device->id);
305
306     pa_xfree(profile->profile);
307
308     if (profile->playback_devices)
309         pa_hashmap_free(profile->playback_devices);
310     if (profile->capture_devices)
311         pa_hashmap_free(profile->capture_devices);
312
313     pa_xfree(profile);
314 }
315
316 static int profile_add_sink(pa_tz_profile *profile, const char *role, pa_sink *sink) {
317     pa_assert(profile);
318
319     if (pa_hashmap_put(profile->playback_devices, (void*)role, sink) < 0) {
320         pa_log_error("Failed to add sink : put sink failed");
321         return -1;
322     }
323     return 0;
324 }
325
326 static int profile_add_source(pa_tz_profile *profile, const char *role, pa_source *source) {
327     pa_assert(profile);
328
329     if (pa_hashmap_put(profile->capture_devices, (void*)role, source) < 0) {
330         pa_log_error("Failed to add source : put source failed");
331         return -1;
332     }
333     return 0;
334 }
335
336 static pa_sink* profile_get_sink(pa_tz_profile *profile, const char *role) {
337     pa_sink *sink;
338     pa_assert(profile);
339
340     if ((sink = pa_hashmap_get(profile->playback_devices, role)) == NULL) {
341         pa_log_warn("Failed to get sink for %s", role);
342         return NULL;
343     }
344
345     return sink;
346 }
347
348 static pa_source* profile_get_source(pa_tz_profile *profile, const char *role) {
349     pa_source *source;
350     pa_assert(profile);
351
352     if ((source = pa_hashmap_get(profile->capture_devices, role)) == NULL) {
353         pa_log_warn("Failed to get source for %s", role);
354         return NULL;
355     }
356
357     return source;
358 }
359
360 static void profile_set_state(pa_tz_profile *profile, dm_device_direction_t direction, dm_device_state_t state) {
361     dm_device_state_t prev_state, new_state;
362     pa_assert(profile);
363
364     prev_state = COMPOUND_STATE(profile);
365     pa_log_debug("previous playback_state : %d, capture_state : %d => state %d", profile->playback_state, profile->capture_state, prev_state);
366     if (direction & DM_DEVICE_DIRECTION_IN)
367         profile->capture_state = state;
368     if (direction & DM_DEVICE_DIRECTION_OUT)
369         profile->playback_state = state;
370     new_state = COMPOUND_STATE(profile);
371     pa_log_debug("new playback_state : %d, capture_state : %d => state %d", profile->playback_state, profile->capture_state, new_state);
372
373     if (prev_state != new_state) {
374         notify_device_info_changed(profile->device, DM_DEVICE_CHANGED_INFO_STATE);
375         pa_tz_device_dump_info(profile->device, PA_LOG_DEBUG);
376     }
377 }
378
379 static dm_device_state_t profile_get_state(pa_tz_profile *profile, dm_device_direction_t direction) {
380     pa_assert(profile);
381
382     if (direction == DM_DEVICE_DIRECTION_BOTH)
383         return COMPOUND_STATE(profile);
384     else if (direction == DM_DEVICE_DIRECTION_OUT)
385         return profile->playback_state;
386     else if (direction == DM_DEVICE_DIRECTION_IN)
387         return profile->capture_state;
388     else
389         return DM_DEVICE_STATE_DEACTIVATED;
390 }
391
392 static int profile_remove_sink_with_role(pa_tz_profile *profile, const char *role) {
393     pa_sink *sink;
394     pa_assert(profile);
395
396     sink = pa_hashmap_remove(profile->playback_devices, role);
397     return sink ? 0 : -1;
398 }
399
400 static int profile_remove_source_with_role(pa_tz_profile *profile, const char *role) {
401     pa_source *source;
402     pa_assert(profile);
403
404     source = pa_hashmap_remove(profile->capture_devices, role);
405     return source ? 0 : -1;
406 }
407
408 static int profile_remove_sink(pa_tz_profile *profile, pa_sink *sink) {
409     pa_sink *_sink;
410     void *state;
411     char *role;
412
413     pa_assert(profile);
414
415     PA_HASHMAP_FOREACH_KEY(_sink, profile->playback_devices, state, role) {
416         if (sink == _sink)
417             return profile_remove_sink_with_role(profile, role);
418     }
419
420     return -1;
421 }
422
423 static int profile_remove_source(pa_tz_profile *profile, pa_source *source) {
424     pa_source *_source;
425     void *state;
426     char *role;
427
428     pa_assert(profile);
429
430     PA_HASHMAP_FOREACH_KEY(_source, profile->capture_devices, state, role) {
431         if (source == _source)
432             return profile_remove_source_with_role(profile, role);
433     }
434
435     return -1;
436 }
437
438 /* pa_tz_device */
439 pa_tz_device* pa_tz_device_new(pa_tz_device_new_data *data) {
440     pa_tz_device *device;
441     pa_sink *sink;
442     pa_source *source;
443     pa_tz_profile *profile;
444     uint32_t profile_idx;
445
446     pa_assert(data);
447
448     if (_check_valid_device_new_data(data) < 0) {
449         pa_log_error("Invalid device_new_data");
450         return NULL;
451     }
452
453     device = pa_xmalloc(sizeof(pa_tz_device));
454     device->list = data->list;
455     device->comm = data->comm;
456     device->dbus_conn = data->dbus_conn;
457
458     device->id = device_id_max_g++;
459     device->type = pa_xstrdup(data->type);
460     if (data->name)
461         device->name = pa_xstrdup(data->name);
462     else
463         device->name = pa_xstrdup(data->type);
464     device->system_id = pa_xstrdup(data->system_id);
465     device->active_profile = 0;
466
467     pa_log_info("New device type(%s) id(%u) name(%s) system_id(%s)",
468             device->type, device->id, device->name, pa_strempty(device->system_id));
469
470     device->profiles = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
471
472     /* If multi profile type, get from data->profile_data */
473     if (device_type_is_multi_profile(data->type)) {
474         pa_tz_profile_new_data *pdata;
475         for (int i = 0; i < data->n_profile; i++) {
476             pdata = data->profile_data[i];
477             profile = profile_new(pdata->profile, pdata->direction,
478                     pdata->playback_pcms, pdata->capture_pcms, pdata->use_internal_codec, device);
479             pa_idxset_put(device->profiles, profile, NULL);
480         }
481         device->active_profile = data->active_profile;
482     } else {
483         profile = profile_new(NULL, data->direction,
484                 data->playback_pcms, data->capture_pcms, data->use_internal_codec, device);
485         pa_idxset_put(device->profiles, profile, NULL);
486     }
487
488     PA_IDXSET_FOREACH(profile, device->profiles, profile_idx) {
489         if (device_type_is_use_external_card(device->type, profile->profile)) {
490             if ((sink = profile_get_sink(profile, DEVICE_ROLE_NORMAL)))
491                 sink->device_item = device;
492             if ((source = profile_get_source(profile, DEVICE_ROLE_NORMAL)))
493                 source->device_item = device;
494         }
495     }
496
497     pa_idxset_put(device->list, device, NULL);
498     notify_device_connection_changed(device, true);
499
500     pa_tz_device_dump_info(device, PA_LOG_INFO);
501
502     return device;
503 }
504
505 static uint32_t _get_profile_idx(pa_tz_device *device, const char *profile_str) {
506     pa_tz_profile *profile;
507     uint32_t profile_idx;
508
509     pa_assert(device);
510     pa_assert(device->profiles);
511
512     if (profile_str == NULL || pa_streq(profile_str, "")) {
513         pa_idxset_first(device->profiles, &profile_idx);
514         return profile_idx;
515     }
516
517     PA_IDXSET_FOREACH(profile, device->profiles, profile_idx) {
518         if (device_profile_is_equal(profile->profile, profile_str))
519             return profile_idx;
520     }
521
522     return PA_INVALID_INDEX;
523 }
524
525 static pa_tz_profile* _get_profile(pa_tz_device *device, const char *profile_str) {
526     pa_tz_profile *profile;
527     uint32_t profile_idx;
528
529     pa_assert(device);
530     pa_assert(device->profiles);
531
532     PA_IDXSET_FOREACH(profile, device->profiles, profile_idx) {
533         if (device_profile_is_equal(profile->profile, profile_str))
534             return profile;
535     }
536
537     return NULL;
538 }
539
540 static pa_tz_profile* _get_profile_by_idx(pa_tz_device *device, uint32_t profile_idx) {
541     pa_tz_profile *profile;
542
543     pa_assert(device);
544
545     profile = pa_idxset_get_by_index(device->profiles, profile_idx);
546     if (profile == NULL)
547         pa_log_error("No profile(%u) in device(%u)", profile_idx, device->id);
548
549     return profile;
550 }
551
552
553 static pa_tz_profile* _get_active_profile(pa_tz_device *device) {
554     pa_tz_profile *profile;
555
556     pa_assert(device);
557
558     profile = _get_profile_by_idx(device, device->active_profile);
559     if (profile == NULL)
560         pa_log_error("Failed to find active profile(%u)", device->active_profile);
561
562     return profile;
563 }
564
565 /* if noti_always is true, always noti this change without checking index
566  * if profile is null, set first profile as active */
567 int _set_active_profile(pa_tz_device *device, const char *profile, bool noti_always) {
568     uint32_t profile_idx, prev_active_idx;
569
570     pa_assert(device);
571
572     pa_log_info("Set active profile, device(%u) profile(%s)",
573             device->id, pa_strempty(profile));
574
575     prev_active_idx = device->active_profile;
576     profile_idx = _get_profile_idx(device, profile);
577     if (profile_idx == PA_INVALID_INDEX) {
578         pa_log_error("index for profile(%s) is invalid", pa_strempty(profile));
579         return -1;
580     }
581     device->active_profile = profile_idx;
582     pa_log_info("new active profile index %u", profile_idx);
583
584     /* Compare index only when check_idx is true */
585     if (noti_always || prev_active_idx != device->active_profile)
586         notify_device_info_changed(device, DM_DEVICE_CHANGED_INFO_IO_DIRECTION);
587
588     return 0;
589 }
590
591 /* only for multi profile type */
592 int pa_tz_device_add_profile(pa_tz_device *device, pa_tz_profile_new_data *pdata, bool as_active) {
593     pa_tz_profile *profile;
594
595     pa_assert(device);
596     pa_assert(device->profiles);
597
598     pa_log_info("device add profile, device(%u) profile(%s) as_active(%s)",
599             device->id, pa_strempty(pdata->profile), pa_yes_no(as_active));
600
601     if (device_type_is_multi_profile(device->type) == false) {
602         pa_log_error("Failed to add profile : not multi profile type");
603         return -1;
604     }
605     if (pa_idxset_size(device->profiles) >= PROFILE_NUM_MAX) {
606         pa_log_error("Failed to add profile : Too many profiles");
607         return -1;
608     }
609
610     profile = profile_new(pdata->profile, pdata->direction,
611             pdata->playback_pcms, pdata->capture_pcms, pdata->use_internal_codec, device);
612     pa_idxset_put(device->profiles, profile, NULL);
613
614     if (as_active)
615         _set_active_profile(device, pdata->profile, true);
616     pa_tz_device_dump_info(device, PA_LOG_INFO);
617
618     return 0;
619 }
620
621 int pa_tz_device_remove_profile(pa_tz_device *device, const char *profile_str) {
622     pa_tz_profile *profile;
623     uint32_t profile_idx, remove_idx;
624     bool found = false;
625     unsigned profile_num;
626
627     pa_assert(device);
628     pa_assert(device->profiles);
629
630     pa_log_info("device remove profile, device(%u) profile(%s)",
631             device->id, pa_strempty(profile_str));
632
633     if (device_type_is_multi_profile(device->type) == false) {
634         pa_log_error("Failed to add profile : not multi profile type");
635         return -1;
636     }
637
638     if ((profile_num = pa_tz_device_get_profile_num(device)) <= 1) {
639         pa_log_error("This device have too small profiles %u, Should be freed", profile_num);
640         return -1;
641     }
642
643     PA_IDXSET_FOREACH(profile, device->profiles, profile_idx) {
644         if (pa_safe_streq(profile->profile, profile_str)) {
645             pa_log_info("found matching profile to remove");
646             found = true;
647             remove_idx = profile_idx;
648         }
649     }
650
651     if (found) {
652         pa_idxset_remove_by_index(device->profiles, remove_idx);
653         /* change active profile if removed one was active */
654         if (device->active_profile == remove_idx)
655             _set_active_profile(device, NULL, true);
656         pa_tz_device_dump_info(device, PA_LOG_INFO);
657         return 0;
658     } else {
659         pa_log_warn("no matching profile to remove");
660         return -1;
661     }
662 }
663
664 /* only for single profile type */
665 int pa_tz_device_add_sink(pa_tz_device *device, const char *role, pa_sink *sink) {
666     pa_tz_profile *profile;
667
668     pa_assert(device);
669     pa_assert(device_role_is_valid(role));
670     pa_assert(sink);
671
672     pa_log_info("device add sink, device(%u) role(%s) sink(%s)",
673             device->id, role, sink->name);
674
675     if (pa_tz_device_get_profile_num(device) > 1) {
676         pa_log_error("Failed to add sink : Too many profiles");
677         return -1;
678     }
679
680     profile = pa_idxset_first(device->profiles, NULL);
681
682     if (profile_add_sink(profile, role, sink) < 0) {
683         pa_log_error("Failed to add sink : Can't add to profile");
684         return -1;
685     }
686
687     return 0;
688 }
689
690 int pa_tz_device_add_source(pa_tz_device *device, const char *role, pa_source *source) {
691     pa_tz_profile *profile;
692
693     pa_assert(device);
694     pa_assert(device_role_is_valid(role));
695     pa_assert(source);
696
697     pa_log_info("device add source, device(%u) role(%s) source(%s)",
698             device->id, role, source->name);
699
700     if (pa_tz_device_get_profile_num(device) > 1) {
701         pa_log_warn("Failed to add source : Too many profiles");
702         return -1;
703     }
704
705     profile = pa_idxset_first(device->profiles, NULL);
706
707     if (profile_add_source(profile, role, source) < 0) {
708         pa_log_error("Failed to add source : Can't add to profile");
709         return -1;
710     }
711
712     return 0;
713 }
714
715 int pa_tz_device_remove_sink(pa_tz_device *device, pa_sink *sink) {
716     pa_tz_profile *profile;
717     int removed = 0;
718     uint32_t profile_idx;
719
720     pa_assert(device);
721     pa_assert(sink);
722
723     pa_log_info("device remove sink, device(%u) sink(%s)",
724             device->id, sink->name);
725
726     PA_IDXSET_FOREACH(profile, device->profiles, profile_idx)
727         removed &= profile_remove_sink(profile, sink);
728
729     return removed;
730 }
731
732 int pa_tz_device_remove_source(pa_tz_device *device, pa_source *source) {
733     pa_tz_profile *profile;
734     uint32_t profile_idx;
735     int removed = 0;
736
737     pa_assert(device);
738     pa_assert(source);
739
740     pa_log_info("device remove source, device(%u) source(%s)",
741             device->id, source->name);
742
743     PA_IDXSET_FOREACH(profile, device->profiles, profile_idx)
744         removed &= profile_remove_source(profile, source);
745
746     return removed;
747 }
748
749 int pa_tz_device_remove_sink_with_role(pa_tz_device *device, const char *role) {
750     pa_tz_profile *profile;
751     uint32_t profile_idx;
752     int removed = 0;
753
754     pa_assert(device);
755     pa_assert(device_role_is_valid(role));
756
757     pa_log_info("device remove sink with role, device(%u) role(%s)",
758             device->id, role);
759
760     PA_IDXSET_FOREACH(profile, device->profiles, profile_idx)
761         removed &= profile_remove_sink_with_role(profile, role);
762
763     return removed;
764 }
765
766 int pa_tz_device_remove_source_with_role(pa_tz_device *device, const char *role) {
767     pa_tz_profile *profile;
768     uint32_t profile_idx;
769     int removed = 0;
770
771     pa_assert(device);
772     pa_assert(device_role_is_valid(role));
773
774     pa_log_info("device remove source with role, device(%u) role(%s)",
775             device->id, role);
776
777     PA_IDXSET_FOREACH(profile, device->profiles, profile_idx)
778         removed &= profile_remove_source_with_role(profile, role);
779
780     return removed;
781 }
782
783 /* only for multi profile */
784 int pa_tz_device_profile_add_sink(pa_tz_device *device, const char *profile_str, const char *role, pa_sink *sink) {
785     pa_tz_profile *profile;
786
787     pa_assert(device);
788
789     pa_log_info("device profile add sink, device(%u) profile(%s) role(%s) sink(%s)",
790             device->id, pa_strempty(profile_str), role, sink->name);
791
792     if ((profile = _get_profile(device, profile_str)) == NULL) {
793         pa_log_error("Can't get profile %s", profile_str);
794         return -1;
795     }
796
797     if (profile_add_sink(profile, role, sink) < 0) {
798         pa_log_error("Can't add to profile");
799         return -1;
800     }
801
802     return 0;
803 }
804
805 int pa_tz_device_profile_add_source(pa_tz_device *device, const char *profile_str, const char *role, pa_source *source) {
806     pa_tz_profile *profile;
807
808     pa_assert(device);
809
810     pa_log_info("device profile add source, device(%u) profile(%s) role(%s) source(%s)",
811             device->id, pa_strempty(profile_str), role, source->name);
812
813     if ((profile = _get_profile(device, profile_str)) == NULL) {
814         pa_log_error("Can't get profile %s", profile_str);
815         return -1;
816     }
817
818     if (profile_add_source(profile, role, source) < 0) {
819         pa_log_error("Can't add to profile");
820         return -1;
821     }
822
823     return 0;
824 }
825
826 int pa_tz_device_profile_remove_sink(pa_tz_device *device, const char *profile_str, pa_sink *sink) {
827     pa_tz_profile *profile;
828
829     pa_assert(device);
830
831     pa_log_info("device profile remove sink, device(%u) profile(%s) sink(%s)",
832             device->id, pa_strempty(profile_str), sink->name);
833
834     if ((profile = _get_profile(device, profile_str)) == NULL) {
835         pa_log_error("Can't get profile %s", profile_str);
836         return -1;
837     }
838
839     if (profile_remove_sink(profile, sink) < 0) {
840         pa_log_error("Can't remove from profile");
841         return -1;
842     }
843
844     return 0;
845 }
846
847 int pa_tz_device_profile_remove_source(pa_tz_device *device, const char *profile_str, pa_source *source) {
848     pa_tz_profile *profile;
849
850     pa_assert(device);
851
852     pa_log_info("device profile remove source, device(%u) profile(%s) source(%s)",
853             device->id, pa_strempty(profile_str), source->name);
854
855     if ((profile = _get_profile(device, profile_str)) == NULL) {
856         pa_log_error("Can't get profile %s", profile_str);
857         return -1;
858     }
859
860     if (profile_remove_source(profile, source) < 0) {
861         pa_log_error("Can't remove from profile");
862         return -1;
863     }
864
865     return 0;
866 }
867
868 int pa_tz_device_profile_remove_sink_with_role(pa_tz_device *device, const char *profile_str, const char *role) {
869     pa_tz_profile *profile;
870
871     pa_assert(device);
872     pa_assert(device_role_is_valid(role));
873
874     pa_log_info("device profile remove sink with role, device(%u) profile(%s) role(%s)",
875             device->id, pa_strempty(profile_str), role);
876
877     if ((profile = _get_profile(device, profile_str)) == NULL) {
878         pa_log_error("Can't get profile %s", profile_str);
879         return -1;
880     }
881
882     if (profile_remove_sink_with_role(profile, role) < 0) {
883         pa_log_error("Can't remove from profile");
884         return -1;
885     }
886
887     return 0;
888 }
889
890 int pa_tz_device_profile_remove_source_with_role(pa_tz_device *device, const char *profile_str, const char *role) {
891     pa_tz_profile *profile;
892
893     pa_assert(device);
894     pa_assert(device_role_is_valid(role));
895
896     pa_log_info("device profile remove source with role, device(%u) profile(%s) role(%s)",
897             device->id, pa_strempty(profile_str), role);
898
899     if ((profile = _get_profile(device, profile_str)) == NULL) {
900         pa_log_error("Can't get profile %s", profile_str);
901         return -1;
902     }
903
904     if (profile_remove_source_with_role(profile, role) < 0) {
905         pa_log_error("Can't remove from profile");
906         return -1;
907     }
908
909     return 0;
910 }
911
912 pa_sink* pa_tz_device_profile_get_sink(pa_tz_device *device, const char *profile_str, const char *role) {
913     pa_sink *sink;
914     pa_tz_profile *profile;
915
916     pa_assert(device);
917
918     pa_log_info("device profile get sink, device(%u) profile(%s) role(%s)",
919             device->id, pa_strempty(profile_str), role);
920
921     if ((profile = _get_profile(device, profile_str)) == NULL) {
922         pa_log_error("Can't get profile %s", profile_str);
923         return NULL;
924     }
925
926     if ((sink = profile_get_sink(profile, role)) == NULL) {
927         pa_log_error("Can't get sink from profile");
928         return NULL;
929     }
930
931     return sink;
932 }
933
934 pa_source* pa_tz_device_profile_get_source(pa_tz_device *device, const char *profile_str, const char *role) {
935     pa_source *source;
936     pa_tz_profile *profile;
937
938     pa_assert(device);
939
940     pa_log_info("device profile get source, device(%u) profile(%s) role(%s)",
941             device->id, pa_strempty(profile_str), role);
942
943     if ((profile = _get_profile(device, profile_str)) == NULL) {
944         pa_log_error("Can't get profile %s", profile_str);
945         return NULL;
946     }
947
948     if ((source = profile_get_source(profile, role)) == NULL) {
949         pa_log_error("Can't get source from profile");
950         return NULL;
951     }
952
953     return source;
954 }
955
956 void pa_tz_device_free(pa_tz_device *device) {
957     pa_assert(device);
958
959     pa_log_info("Free device type(%s) id(%u) name(%s) system_id(%s)",
960             device->type, device->id, device->name, device->system_id);
961
962     pa_tz_device_dump_info(device, PA_LOG_INFO);
963
964     pa_idxset_remove_by_data(device->list, device, NULL);
965     notify_device_connection_changed(device, false);
966
967     pa_xfree(device->type);
968     pa_xfree(device->name);
969     pa_xfree(device->system_id);
970
971     pa_idxset_free(device->profiles, (pa_free_cb_t)profile_free);
972
973     pa_xfree(device);
974 }
975
976 /* pa_tz_profile_new_data */
977 void pa_tz_profile_new_data_init(pa_tz_profile_new_data *profile_data) {
978     pa_assert(profile_data);
979
980     profile_data->profile = NULL;
981     profile_data->direction = DM_DEVICE_DIRECTION_NONE;
982
983     profile_data->playback_pcms= pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
984     profile_data->capture_pcms = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
985 }
986
987 void pa_tz_profile_new_data_set_direction(pa_tz_profile_new_data *profile_data, dm_device_direction_t direction) {
988     pa_assert(profile_data);
989
990     profile_data->direction = direction;
991 }
992
993 void pa_tz_profile_new_data_set_profile(pa_tz_profile_new_data *profile_data, const char *profile) {
994     pa_assert(profile_data);
995
996     profile_data->profile = pa_xstrdup(profile);
997 }
998
999 void pa_tz_profile_new_data_set_use_internal_codec(pa_tz_profile_new_data *profile_data, bool use_internal_codec) {
1000     pa_assert(profile_data);
1001     profile_data->use_internal_codec = use_internal_codec;
1002 }
1003
1004 void pa_tz_profile_new_data_add_sink(pa_tz_profile_new_data *profile_data, const char *role, pa_sink *sink) {
1005     pa_assert(profile_data);
1006
1007     pa_hashmap_put(profile_data->playback_pcms, (void*)role, sink);
1008 }
1009
1010 void pa_tz_profile_new_data_add_source(pa_tz_profile_new_data *profile_data, const char *role, pa_source *source) {
1011     pa_assert(profile_data);
1012
1013     pa_hashmap_put(profile_data->capture_pcms, (void*)role, source);
1014 }
1015
1016 void pa_tz_profile_new_data_done(pa_tz_profile_new_data *profile_data) {
1017     pa_assert(profile_data);
1018
1019     pa_xfree(profile_data->profile);
1020 }
1021
1022 /* exported api */
1023 pa_sink* pa_tz_device_get_sink(pa_tz_device *device, const char *role) {
1024     pa_tz_profile *profile;
1025     pa_sink *sink;
1026
1027     pa_assert(device);
1028     pa_assert(profile = _get_active_profile(device));
1029
1030     pa_log_info("device get sink, device(%u) role(%s), active-profile(%s)",
1031             device->id, role, pa_strempty(profile->profile));
1032
1033     if ((sink = profile_get_sink(profile, role)) == NULL) {
1034         pa_log_error("Failed to get sink from profile");
1035         return NULL;
1036     }
1037
1038     return sink;
1039 }
1040
1041 pa_source* pa_tz_device_get_source(pa_tz_device *device, const char *role) {
1042     pa_tz_profile *profile;
1043     pa_source *source;
1044
1045     pa_assert(device);
1046     pa_assert(profile = _get_active_profile(device));
1047
1048     pa_log_info("device get source, device(%u) role(%s), active-profile(%s)",
1049             device->id, role, pa_strempty(profile->profile));
1050
1051     if ((source = profile_get_source(profile, role)) == NULL) {
1052         pa_log_error("Failed to get source from profile");
1053         return NULL;
1054     }
1055
1056     return source;
1057 }
1058
1059 void pa_tz_device_set_state(pa_tz_device *device, dm_device_direction_t direction, dm_device_state_t state) {
1060     pa_tz_profile *profile;
1061
1062     pa_assert(device);
1063     pa_assert(profile = _get_active_profile(device));
1064
1065     pa_log_info("device set state, device(%u) type(%s) active-profile(%s) direction(%s) -> %d",
1066             device->id, device->type, pa_strempty(profile->profile), device_direction_to_string(direction), state);
1067     profile_set_state(profile, direction, state);
1068 }
1069
1070 dm_device_state_t pa_tz_device_get_state(pa_tz_device *device, dm_device_direction_t direction) {
1071     pa_tz_profile *profile;
1072
1073     pa_assert(device);
1074     pa_assert(profile = _get_active_profile(device));
1075
1076     return profile_get_state(profile, direction);
1077 }
1078
1079 uint32_t pa_tz_device_get_id(pa_tz_device *device) {
1080     pa_assert(device);
1081
1082     return device->id;
1083 }
1084
1085 char* pa_tz_device_get_type(pa_tz_device *device) {
1086     pa_assert(device);
1087
1088     return device->type;
1089 }
1090
1091 char* pa_tz_device_get_name(pa_tz_device *device) {
1092     pa_assert(device);
1093
1094     return device->name;
1095 }
1096
1097 char* pa_tz_device_get_system_id(pa_tz_device *device) {
1098     pa_assert(device);
1099
1100     return device->system_id;
1101 }
1102
1103 char* pa_tz_device_get_profile(pa_tz_device *device) {
1104     pa_tz_profile *profile;
1105
1106     pa_assert(device);
1107     pa_assert(profile = _get_active_profile(device));
1108
1109     return profile->profile;
1110 }
1111
1112 dm_device_direction_t pa_tz_device_get_direction(pa_tz_device *device) {
1113     pa_tz_profile *profile;
1114
1115     pa_assert(device);
1116     pa_assert(profile = _get_active_profile(device));
1117
1118     return profile->direction;
1119 }
1120
1121 pa_usec_t pa_tz_device_get_creation_time(pa_tz_device *device) {
1122     pa_tz_profile *profile;
1123
1124     pa_assert(device);
1125     pa_assert(profile = _get_active_profile(device));
1126
1127     return profile->creation_time;
1128 }
1129
1130 bool pa_tz_device_is_use_internal_codec(pa_tz_device *device) {
1131     pa_tz_profile *profile;
1132
1133     pa_assert(device);
1134     pa_assert(profile = _get_active_profile(device));
1135
1136     return profile->use_internal_codec;
1137 }
1138
1139 unsigned pa_tz_device_get_profile_num(pa_tz_device *device) {
1140     pa_assert(device);
1141     pa_assert(device->profiles);
1142
1143     return pa_idxset_size(device->profiles);
1144 }
1145
1146 bool pa_tz_device_have_profile(pa_tz_device *device, const char *profile) {
1147     pa_assert(device);
1148
1149     if (_get_profile(device, profile) == NULL)
1150         return false;
1151     else
1152         return true;
1153 }
1154
1155 static int method_call_bt_sco(pa_dbus_connection *conn, bool onoff) {
1156     DBusMessage *msg, *reply;
1157     DBusError err;
1158     const char *method;
1159
1160     pa_assert(conn);
1161
1162     method = onoff ? "Play" : "Stop";
1163     if (!(msg = dbus_message_new_method_call(DBUS_SERVICE_HFP_AGENT, DBUS_OBJECT_HFP_AGENT, DBUS_INTERFACE_HFP_AGENT, method))) {
1164         pa_log_error("dbus method call failed");
1165         return -1;
1166     }
1167
1168     dbus_error_init(&err);
1169     if (!(reply = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(conn), msg, -1, &err))) {
1170         pa_log_error("Failed to method call %s.%s, %s", DBUS_INTERFACE_HFP_AGENT, method, err.message);
1171         dbus_error_free(&err);
1172         return -1;
1173     }
1174
1175     dbus_message_unref(reply);
1176     return 0;
1177 }
1178
1179 static int method_call_bt_sco_get_property(pa_dbus_connection *conn, bool *is_wide_band, bool *nrec) {
1180     DBusMessage *msg, *reply;
1181     DBusMessageIter reply_iter, reply_iter_entry;
1182     DBusError err;
1183     unsigned int codec;
1184     const char *property;
1185
1186     pa_assert(conn);
1187
1188     if (!is_wide_band && !nrec) {
1189         return -1;
1190     }
1191
1192     if (!(msg = dbus_message_new_method_call(DBUS_SERVICE_HFP_AGENT, DBUS_OBJECT_HFP_AGENT, DBUS_INTERFACE_HFP_AGENT, "GetProperties"))) {
1193         pa_log_error("dbus method call failed");
1194         return -1;
1195     }
1196
1197     dbus_error_init(&err);
1198     if (!(reply = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(conn), msg, -1, &err))) {
1199         pa_log_error("Failed to method call %s.%s, %s", DBUS_INTERFACE_HFP_AGENT, "GetProperties", err.message);
1200         dbus_error_free(&err);
1201         return -1;
1202     }
1203
1204     dbus_message_iter_init(reply,  &reply_iter);
1205
1206     if (dbus_message_iter_get_arg_type(&reply_iter) != DBUS_TYPE_ARRAY) {
1207         pa_log_error("Cannot get reply argument");
1208         return -1;
1209     }
1210
1211     dbus_message_iter_recurse(&reply_iter,  &reply_iter_entry);
1212
1213     while (dbus_message_iter_get_arg_type(&reply_iter_entry) == DBUS_TYPE_DICT_ENTRY) {
1214         DBusMessageIter dict_entry, dict_entry_val;
1215         dbus_message_iter_recurse(&reply_iter_entry, &dict_entry);
1216         dbus_message_iter_get_basic(&dict_entry, &property);
1217         pa_log_debug("String received = %s", property);
1218         if (property) {
1219             if (pa_streq("codec", property) && is_wide_band) {
1220                 dbus_message_iter_next(&dict_entry);
1221                 dbus_message_iter_recurse(&dict_entry, &dict_entry_val);
1222                 if (dbus_message_iter_get_arg_type(&dict_entry_val) != DBUS_TYPE_UINT32)
1223                     continue;
1224                 dbus_message_iter_get_basic(&dict_entry_val, &codec);
1225                 pa_log_debug("Codec = [%d]", codec);
1226                 *is_wide_band = (codec == BT_MSBC_CODEC_ID) ? true : false;
1227             } else if (pa_streq("nrec", property) && nrec) {
1228                 dbus_message_iter_next(&dict_entry);
1229                 dbus_message_iter_recurse(&dict_entry, &dict_entry_val);
1230                 if (dbus_message_iter_get_arg_type(&dict_entry_val) != DBUS_TYPE_BOOLEAN)
1231                     continue;
1232                 dbus_message_iter_get_basic(&dict_entry_val, nrec);
1233                 pa_log_debug("nrec= [%d]", *nrec);
1234             }
1235         }
1236         dbus_message_iter_next(&reply_iter_entry);
1237     }
1238
1239
1240     dbus_message_unref(reply);
1241     return 0;
1242 }
1243
1244 /* only for bt device, which have sco profile */
1245 int pa_tz_device_sco_open(pa_tz_device *device) {
1246     pa_tz_profile *profile;
1247
1248     pa_assert(device);
1249     pa_assert(device->dbus_conn);
1250
1251     pa_log_info("BT SCO Open for device(%u)", device->id);
1252     if (pa_streq(device->type, DEVICE_TYPE_BT) == false) {
1253         pa_log_error("Not BT device");
1254         return -1;
1255     }
1256     if ((profile = _get_profile(device, DEVICE_PROFILE_BT_SCO)) == NULL) {
1257         pa_log_error("No BT SCO profile");
1258         return -1;
1259     }
1260
1261     if (profile->sco_opened) {
1262         pa_log_warn("SCO already opened");
1263         return -1;
1264     }
1265
1266     if (method_call_bt_sco(device->dbus_conn, true) < 0) {
1267         pa_log_error("Failed to bt sco on");
1268         return -1;
1269     }
1270
1271     profile->sco_opened = true;
1272     _set_active_profile(device, DEVICE_PROFILE_BT_SCO, false);
1273     pa_tz_device_dump_info(profile->device, PA_LOG_DEBUG);
1274     pa_log_info("BT SCO Open - SUCCESS");
1275
1276     return 0;
1277 }
1278
1279 /* only for bt device, which have sco profile */
1280 int pa_tz_device_sco_close(pa_tz_device *device) {
1281     pa_tz_profile *profile;
1282     pa_assert(device);
1283
1284     pa_log_info("BT SCO Close for device(%u)", device->id);
1285
1286     if (pa_streq(device->type, DEVICE_TYPE_BT) == false) {
1287         pa_log_error("Not BT device");
1288         return -1;
1289     }
1290     if ((profile = _get_profile(device, DEVICE_PROFILE_BT_SCO)) == NULL) {
1291         pa_log_error("No BT SCO profile");
1292         return -1;
1293     }
1294
1295     if (profile->sco_opened == false) {
1296         pa_log_warn("SCO not opened");
1297         return -1;
1298     }
1299
1300     if (method_call_bt_sco(device->dbus_conn, false) < 0) {
1301         pa_log_error("Failed to bt sco on");
1302         return -1;
1303     }
1304
1305     profile->sco_opened = false;
1306     if (pa_tz_device_have_profile(device, DEVICE_PROFILE_BT_A2DP))
1307         _set_active_profile(device, DEVICE_PROFILE_BT_A2DP, false);
1308     pa_tz_device_dump_info(profile->device, PA_LOG_DEBUG);
1309     pa_log_info("BT SCO Close - Success");
1310
1311     return 0;
1312 }
1313
1314 /* only for bt device, which have sco profile */
1315 int pa_tz_device_sco_get_property(pa_tz_device *device, bool *is_wide_band, bool *nrec) {
1316     pa_assert(device);
1317
1318     pa_log_info("BT SCO get property for device(%u)", device->id);
1319     if (pa_streq(device->type, DEVICE_TYPE_BT) == false) {
1320         pa_log_error("Not BT device");
1321         return -1;
1322     }
1323     if ((_get_profile(device, DEVICE_PROFILE_BT_SCO)) == NULL) {
1324         pa_log_error("No BT SCO profile");
1325         return -1;
1326     }
1327
1328     if (method_call_bt_sco_get_property(device->dbus_conn, is_wide_band, nrec) < 0) {
1329         pa_log_error("Failed to get BT SCO Property");
1330         return -1;
1331     }
1332
1333     pa_log_info("BT SCO Get Property - Success, is wide band : %s, nrec : %s", pa_yes_no(is_wide_band), pa_yes_no(nrec));
1334
1335     return 0;
1336 }
1337
1338 /* only for bt device */
1339 int pa_tz_device_sco_get_status(pa_tz_device *device, dm_device_bt_sco_status_t *status) {
1340     pa_tz_profile *profile;
1341     pa_assert(device);
1342
1343     pa_log_info("BT SCO get status for device(%u)", device->id);
1344     if (pa_streq(device->type, DEVICE_TYPE_BT) == false) {
1345         pa_log_error("Not BT device");
1346         return -1;
1347     }
1348     if (status == NULL) {
1349         pa_log_error("invalid parameter");
1350         return -1;
1351     }
1352
1353     if ((profile = _get_profile(device, DEVICE_PROFILE_BT_SCO))) {
1354         if (profile->sco_opened == false)
1355             *status = DM_DEVICE_BT_SCO_STATUS_CONNECTED;
1356         else
1357             *status = DM_DEVICE_BT_SCO_STATUS_OPENED;
1358     } else {
1359         *status = DM_DEVICE_BT_SCO_STATUS_DISCONNECTED;
1360     }
1361
1362     pa_log_debug("BT SCO Get Status, %d", *status);
1363     return 0;
1364 }
1365