From: Seungbae Shin Date: Mon, 15 Mar 2021 07:45:23 +0000 (+0900) Subject: support external bt-sco device for tv X-Git-Tag: submit/tizen/20210827.174915^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F07%2F255207%2F8;p=platform%2Fcore%2Fmultimedia%2Fpulseaudio-modules-tizen.git support external bt-sco device for tv [Version] 13.0.71 [Issue Type] Improvement Change-Id: Ic9d3d00c5a48e319203468550efa5fb40f6f243d --- diff --git a/packaging/pulseaudio-modules-tizen.spec b/packaging/pulseaudio-modules-tizen.spec index 9935f28..741064d 100644 --- a/packaging/pulseaudio-modules-tizen.spec +++ b/packaging/pulseaudio-modules-tizen.spec @@ -1,6 +1,6 @@ Name: pulseaudio-modules-tizen Summary: Pulseaudio modules for Tizen -Version: 13.0.70 +Version: 13.0.71 Release: 0 Group: Multimedia/Audio License: LGPL-2.1+ @@ -43,6 +43,8 @@ PulseAudio module-acm-sink for sending PCM data to ACM core. export CFLAGS="%{optflags} -fno-strict-aliasing -D__TIZEN__ -DSYSCONFDIR=\\\"%{_hal_sysconfdir}\\\" " %if "%{tizen_profile_name}" == "tv" export CFLAGS+=" -DTIZEN_TV"; +%else + export CFLAGS+=" -D__TIZEN_INTERNAL_BT_SCO__" %endif export LD_AS_NEEDED=0 diff --git a/src/device-manager-dbus.c b/src/device-manager-dbus.c index ccab821..359d4f4 100644 --- a/src/device-manager-dbus.c +++ b/src/device-manager-dbus.c @@ -219,7 +219,9 @@ static void handle_dump_device_list(DBusConnection *conn, DBusMessage *msg, void static void handle_test_device_status_change(DBusConnection *conn, DBusMessage *msg, void *userdata); static void handle_set_acm_mode(DBusConnection *conn, DBusMessage *msg, void *userdata); +#ifdef __TIZEN_INTERNAL_BT_SCO__ static int method_call_bt_get_name(DBusConnection *conn, const char *device_path, char **name); +#endif enum method_handler_index { METHOD_HANDLER_GET_CONNECTED_DEVICE_LIST, @@ -431,6 +433,7 @@ static int _translate_external_value(const char *type, int value, device_detecte return 0; } +#ifdef __TIZEN_INTERNAL_BT_SCO__ static int handle_bluez_headset_property_changed(DBusConnection *c, DBusMessage *s, pa_device_manager *dm) { DBusMessageIter msg_iter, variant_iter; char *property_name; @@ -504,6 +507,7 @@ static int handle_bluez_headset_property_changed(DBusConnection *c, DBusMessage return 0; } +#endif /* __TIZEN_INTERNAL_BT_SCO__ */ static DBusHandlerResult dbus_filter_device_detect_handler(DBusConnection *c, DBusMessage *s, void *userdata) { DBusError error; @@ -550,11 +554,11 @@ static DBusHandlerResult dbus_filter_device_detect_handler(DBusConnection *c, DB goto fail; } handle_device_status_changed(dm, DEVICE_TYPE_FORWARDING, NULL, NULL, detected); - +#ifdef __TIZEN_INTERNAL_BT_SCO__ } else if (dbus_message_is_signal(s, DBUS_INTERFACE_BLUEZ_HEADSET, "PropertyChanged")) { if (handle_bluez_headset_property_changed(c, s, dm) < 0) goto fail; - +#endif } else { pa_log_debug("Unknown message, not handle it"); dbus_error_free(&error); @@ -635,6 +639,7 @@ static bool device_is_match_with_mask(pa_tz_device *device, int mask) { device_is_match_type(device, mask & DEVICE_TYPE_FLAGS)); } +#ifdef __TIZEN_INTERNAL_BT_SCO__ static int method_call_bt_get_name(DBusConnection *conn, const char *device_path, char **name) { const char *intf = DBUS_INTERFACE_BLUEZ_DEVICE, *prop = "Alias"; DBusMessage *msg, *reply; @@ -682,6 +687,7 @@ static int method_call_bt_get_name(DBusConnection *conn, const char *device_path dbus_message_unref(reply); return 0; } +#endif /* __TIZEN_INTERNAL_BT_SCO__ */ static void handle_get_connected_device_list(DBusConnection *conn, DBusMessage *msg, void *userdata) { pa_device_manager *dm = (pa_device_manager *)userdata; diff --git a/src/device-manager.c b/src/device-manager.c index a1a717e..114f28f 100644 --- a/src/device-manager.c +++ b/src/device-manager.c @@ -87,6 +87,9 @@ #define DEVICE_API_RAOP "raop" #define DEVICE_API_TUNNEL "tunnel" #define DEVICE_API_RTSP "rtsp" +#ifndef __TIZEN_INTERNAL_BT_SCO__ +#define DEVICE_API_BTSCO "btsco" +#endif #define DEVICE_BUS_USB "usb" #define DEVICE_CLASS_SOUND "sound" #define DEVICE_CLASS_MONITOR "monitor" @@ -480,6 +483,17 @@ static bool pulse_device_is_rtsp(pa_object *pdevice) { return pa_safe_streq(pa_proplist_gets(prop, PA_PROP_DEVICE_API), DEVICE_API_RTSP); } +#ifndef __TIZEN_INTERNAL_BT_SCO__ +static bool pulse_device_is_btsco(pa_object *pdevice) { + pa_proplist *prop = pulse_device_get_proplist(pdevice); + + if (!prop) + return false; + + return pa_safe_streq(pa_proplist_gets(prop, PA_PROP_DEVICE_API), DEVICE_API_BTSCO); +} +#endif + static const char* pulse_device_get_device_string_removed_argument(pa_object *pdevice) { static char removed_param[DEVICE_PARAM_STRING_MAX] = {0,}; char *device_string_p = NULL; @@ -1156,6 +1170,10 @@ static const char* pulse_device_get_system_id(pa_object *pdevice) { return pa_proplist_gets(prop, PA_PROP_DEVICE_DESCRIPTION); else if (pulse_device_is_rtsp(pdevice)) return pa_proplist_gets(prop, PA_PROP_DEVICE_DESCRIPTION); +#ifndef __TIZEN_INTERNAL_BT_SCO__ + else if (pulse_device_is_btsco(pdevice)) + return pa_proplist_gets(prop, PA_PROP_DEVICE_DESCRIPTION); +#endif else return NULL; } @@ -1578,6 +1596,50 @@ static void handle_rtsp_pulse_device(pa_object *pdevice, bool is_loaded, pa_devi } } +#ifndef __TIZEN_INTERNAL_BT_SCO__ +static void handle_external_btsco_pulse_device(pa_object *pdevice, bool is_loaded, pa_device_manager *dm) { + const char *name, *system_id; + dm_device_direction_t direction; + pa_tz_device *device; + + pa_assert(pdevice); + pa_assert(dm); + + pa_log_info("Handle btsco pulse device"); + + system_id = pulse_device_get_system_id(pdevice); + direction = pulse_device_get_direction(pdevice); + + if (is_loaded) { + pa_tz_device_new_data data; + pa_proplist *prop; + + prop = pulse_device_get_proplist(pdevice); + name = pa_proplist_gets(prop, PA_PROP_DEVICE_DESCRIPTION); + + pa_tz_device_new_data_init(&data, dm->device_list, dm->comm, NULL); + pa_tz_device_new_data_set_type(&data, DEVICE_TYPE_BT_SCO); + pa_tz_device_new_data_set_name(&data, name); + pa_tz_device_new_data_set_direction(&data, direction); + pa_tz_device_new_data_set_system_id(&data, system_id); + pa_tz_device_new_data_set_use_internal_codec(&data, false); + if (direction == DM_DEVICE_DIRECTION_OUT) { + pa_tz_device_new_data_add_sink(&data, DEVICE_ROLE_NORMAL, PA_SINK(pdevice)); + } else { + pa_tz_device_new_data_add_source(&data, DEVICE_ROLE_NORMAL, PA_SOURCE(pdevice)); + } + + pa_tz_device_new(&data); + pa_tz_device_new_data_done(&data); + } else { + if (!(device = device_list_get_device(dm, DEVICE_TYPE_BT_SCO, NULL, system_id))) + pa_log_warn("Can't get btsco device for %s", system_id); + else + pa_tz_device_free(device); + } +} +#endif /* __TIZEN_INTERNAL_BT_SCO__ */ + static void handle_internal_pulse_device(pa_object *pdevice, bool is_loaded, pa_device_manager *dm) { pa_tz_device *device; struct composite_type *ctype; @@ -1661,6 +1723,12 @@ static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, pa_dev pulse_device_set_use_internal_codec(PA_OBJECT(sink), true); handle_internal_pulse_device(PA_OBJECT(sink), true, dm); return PA_HOOK_OK; +#ifndef __TIZEN_INTERNAL_BT_SCO__ + } else if (pulse_device_is_btsco(PA_OBJECT(sink))) { + pulse_device_set_use_internal_codec(PA_OBJECT(sink), false); + handle_external_btsco_pulse_device(PA_OBJECT(sink), true, dm); + return PA_HOOK_OK; +#endif } else { pa_log_debug("Don't care this sink"); } @@ -1705,6 +1773,11 @@ static pa_hook_result_t sink_unlink_hook_callback(pa_core *c, pa_sink *sink, pa_ } else if (pulse_device_is_alsa(PA_OBJECT(sink)) || pulse_device_is_tizenaudio(PA_OBJECT(sink))) { handle_internal_pulse_device(PA_OBJECT(sink), false, dm); return PA_HOOK_OK; +#ifndef __TIZEN_INTERNAL_BT_SCO__ + } else if (pulse_device_is_btsco(PA_OBJECT(sink))) { + handle_external_btsco_pulse_device(PA_OBJECT(sink), false, dm); + return PA_HOOK_OK; +#endif } else { pa_log_debug("Don't care this sink"); } @@ -1738,6 +1811,11 @@ static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source, pulse_device_set_use_internal_codec(PA_OBJECT(source), false); handle_rtsp_pulse_device(PA_OBJECT(source), true, dm); return PA_HOOK_OK; +#ifndef __TIZEN_INTERNAL_BT_SCO__ + } else if (pulse_device_is_btsco(PA_OBJECT(source))) { + pulse_device_set_use_internal_codec(PA_OBJECT(source), false); + handle_external_btsco_pulse_device(PA_OBJECT(source), true, dm); +#endif } else { pa_log_debug("Don't care this source"); } @@ -1778,7 +1856,11 @@ static pa_hook_result_t source_unlink_hook_callback(pa_core *c, pa_source *sourc return PA_HOOK_OK; } else if (pulse_device_is_rtsp(PA_OBJECT(source))) { handle_rtsp_pulse_device(PA_OBJECT(source), false, dm); +#ifndef __TIZEN_INTERNAL_BT_SCO__ + } else if (pulse_device_is_btsco(PA_OBJECT(source))) { + handle_external_btsco_pulse_device(PA_OBJECT(source), false, dm); return PA_HOOK_OK; +#endif } else { pa_log_debug("Don't care this source"); } diff --git a/src/module-tizenaudio-policy.c b/src/module-tizenaudio-policy.c index 2efbc89..44b1894 100644 --- a/src/module-tizenaudio-policy.c +++ b/src/module-tizenaudio-policy.c @@ -85,7 +85,9 @@ struct userdata; #define LOOPBACK_DEFAULT_LATENCY_MSEC 40 #define LOOPBACK_DEFAULT_ADJUST_SEC 3 +#ifdef __TIZEN_INTERNAL_BT_SCO__ #define TIMED_BT_SCO_CLOSE_USEC 3000000 +#endif /* Macros */ #define CONVERT_TO_HAL_DIRECTION(stream_type) \ @@ -183,7 +185,9 @@ struct userdata { int32_t latency_msec; int32_t adjust_sec; } loopback_args; +#ifdef __TIZEN_INTERNAL_BT_SCO__ pa_time_event *time_event_bt_sco_close; +#endif }; static void __load_dump_config(struct userdata *u) @@ -208,6 +212,7 @@ static void __load_dump_config(struct userdata *u) iniparser_freedict(dict); } +#ifdef __TIZEN_INTERNAL_BT_SCO__ /* threre is only one sco connected device */ static pa_tz_device* _get_sco_connected_device(pa_device_manager *dm) { pa_idxset *device_list; @@ -450,6 +455,7 @@ static void update_bt_sco_option(struct userdata *u, const char* role) { pa_log_warn("Failed to get property for wideband / nrec...."); } } +#endif static void update_loopback_module_args(struct userdata* u, int32_t parent_id, pa_sink *sink, pa_source *source) { @@ -690,6 +696,7 @@ static bool skip_device(const char *stream_role, const char *device_type) return false; } +#ifdef __TIZEN_INTERNAL_BT_SCO__ static bool skip_bt_sco_device(struct userdata *u, const char *stream_role, const char *device_type) { pa_assert(u); pa_assert(stream_role); @@ -719,6 +726,7 @@ static bool skip_bt_sco_device(struct userdata *u, const char *stream_role, cons return false; } +#endif static bool is_supported_stream_role_for_usb(const char *role) { pa_assert(role); @@ -819,8 +827,10 @@ static void select_device_by_auto_or_auto_all_routing(struct userdata *u, pa_str if (!pa_safe_streq(device_type, dm_device_type) || !IS_AVAILABLE_DIRECTION(data->stream_type, dm_device_direction)) continue; pa_log_info(" ** found a matched device: type[%-16s], direction[0x%x]", dm_device_type, dm_device_direction); +#ifdef __TIZEN_INTERNAL_BT_SCO__ if (skip_bt_sco_device(u, data->stream_role, dm_device_type)) continue; +#endif if (skip_usb_device(data->stream_role, device)) continue; @@ -891,8 +901,10 @@ static void select_device_by_auto_last_connected_routing(struct userdata *u, pa_ dm_device_type, dm_device_direction, dm_device_id, creation_time); if (!pa_safe_streq(device_type, dm_device_type) || !IS_AVAILABLE_DIRECTION(data->stream_type, dm_device_direction)) continue; +#ifdef __TIZEN_INTERNAL_BT_SCO__ if (skip_bt_sco_device(u, data->stream_role, dm_device_type)) continue; +#endif if (skip_usb_device(data->stream_role, device)) continue; @@ -1137,8 +1149,10 @@ static void reset_route(struct userdata *u, stream_type_t stream_type) { pa_assert(u); +#ifdef __TIZEN_INTERNAL_BT_SCO__ /* update BT SCO: close */ update_bt_sco_state(u, false, true, NULL); +#endif /* unload combine sink */ if (stream_type == STREAM_SINK_INPUT) { @@ -1291,9 +1305,15 @@ static void fill_device_info(hal_route_info *route_info, const char *type, uint3 route_info->num_of_devices -1, type, direction, id); } +#ifdef __TIZEN_INTERNAL_BT_SCO__ static pa_hook_result_t update_combine_sink_and_bt_sco(struct userdata *u, pa_stream_manager_hook_data_for_route *data, pa_tz_device *device, const char *stream_role, const char *dm_device_type, pa_sink **combine_sink_arg1, pa_sink **combine_sink_arg2) { +#else +static pa_hook_result_t update_combine_sink(struct userdata *u, pa_stream_manager_hook_data_for_route *data, + pa_tz_device *device, const char *stream_role, const char *dm_device_type, + pa_sink **combine_sink_arg1, pa_sink **combine_sink_arg2) { +#endif pa_sink *sink = NULL; pa_assert(u); @@ -1309,6 +1329,7 @@ static pa_hook_result_t update_combine_sink_and_bt_sco(struct userdata *u, pa_st else pa_log_error("[ROUTE][AUTO] could not get sink"); } +#ifdef __TIZEN_INTERNAL_BT_SCO__ if (pa_safe_streq(dm_device_type, DEVICE_TYPE_BT_SCO)) { if (IS_ROLE_AVAILABLE_BT_SCO_OPEN(stream_role)) { if (update_bt_sco_state(u, true, false, stream_role)) { @@ -1320,6 +1341,7 @@ static pa_hook_result_t update_combine_sink_and_bt_sco(struct userdata *u, pa_st return PA_HOOK_OK; } update_bt_sco_state(u, false, false, NULL); +#endif break; } case STREAM_ROUTE_TYPE_AUTO_ALL: { @@ -1328,7 +1350,9 @@ static pa_hook_result_t update_combine_sink_and_bt_sco(struct userdata *u, pa_st void *s = NULL; stream_route_type_t route_type; +#ifdef __TIZEN_INTERNAL_BT_SCO__ update_bt_sco_state(u, false, false, NULL); +#endif /* find the proper sink/source */ /* currently, we support two sinks for combining */ @@ -1412,8 +1436,10 @@ static int32_t update_route_by_preemptive_device(struct userdata *u, pa_stream_m /* if it needs to skip it, keep going to next device for proper UCM setting */ if (skip_device(data->stream_role, dm_device_type)) return -1; +#ifdef __TIZEN_INTERNAL_BT_SCO__ if (skip_bt_sco_device(u, data->stream_role, dm_device_type)) return -1; +#endif fill_device_info(route_info, dm_device_type, CONVERT_TO_HAL_DIRECTION(data->stream_type), dm_device_id); return 0; } @@ -1466,8 +1492,10 @@ static pa_hook_result_t handle_auto_or_auto_all_routing(struct userdata *u, pa_s /* if it needs to skip it, keep going to next device for proper UCM setting */ if (skip_device(data->stream_role, dm_device_type)) continue; +#ifdef __TIZEN_INTERNAL_BT_SCO__ if (skip_bt_sco_device(u, data->stream_role, dm_device_type)) continue; +#endif fill_device_info(route_info, dm_device_type, CONVERT_TO_HAL_DIRECTION(data->stream_type), dm_device_id); break; } @@ -1485,10 +1513,18 @@ update_auto_active_dev: else pa_proplist_sets(GET_STREAM_PROPLIST(data->stream, data->stream_type), PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV, dm_device_type); +#ifdef __TIZEN_INTERNAL_BT_SCO__ return update_combine_sink_and_bt_sco(u, data, *device, route_info->role, dm_device_type, NULL, NULL); +#else + return update_combine_sink(u, data, *device, route_info->role, dm_device_type, NULL, NULL); +#endif } else if (data->route_type == STREAM_ROUTE_TYPE_AUTO_ALL) { +#ifdef __TIZEN_INTERNAL_BT_SCO__ update_combine_sink_and_bt_sco(u, data, *device, NULL, NULL, &combine_sink_arg1, &combine_sink_arg2); +#else + update_combine_sink(u, data, *device, NULL, NULL, &combine_sink_arg1, &combine_sink_arg2); +#endif } } return PA_HOOK_OK; @@ -1539,8 +1575,12 @@ static pa_hook_result_t handle_auto_last_connected_routing(struct userdata *u, p continue; if ((use_internal_codec = pa_tz_device_is_use_internal_codec(*device))) { /* if it needs to skip it, keep going to next device for proper UCM setting */ +#ifdef __TIZEN_INTERNAL_BT_SCO__ if (skip_device(data->stream_role, dm_device_type) || skip_bt_sco_device(u, data->stream_role, dm_device_type)) +#else + if (skip_device(data->stream_role, dm_device_type)) +#endif continue; } if (!latest_device || (latest_creation_time <= creation_time)) { @@ -1582,6 +1622,7 @@ update_auto_active_dev: pa_log_error("[ROUTE][AUTO_LAST_CONN] could not get sink"); } +#ifdef __TIZEN_INTERNAL_BT_SCO__ if (pa_safe_streq(dm_device_type, DEVICE_TYPE_BT_SCO)) { if (IS_ROLE_AVAILABLE_BT_SCO_OPEN(route_info->role)) { if (update_bt_sco_state(u, true, false, route_info->role)) { @@ -1593,6 +1634,7 @@ update_auto_active_dev: } else { update_bt_sco_state(u, false, false, NULL); } +#endif /* Update device with latest_device to use be used later in this function */ *device = latest_device; @@ -1631,6 +1673,8 @@ static pa_hook_result_t handle_manual_routing(struct userdata *u, pa_stream_mana dm_device_direction = pa_tz_device_get_direction(*device); pa_log_debug(" ** found a matched device: type[%-16s], direction[0x%x]", dm_device_type, dm_device_direction); + +#ifdef __TIZEN_INTERNAL_BT_SCO__ /* Check for availability for opening Bluetooth SCO */ if (pa_safe_streq(dm_device_type, DEVICE_TYPE_BT_SCO) && IS_ROLE_AVAILABLE_BT_SCO_OPEN(route_info->role)) { /* update BT SCO: open */ @@ -1643,6 +1687,7 @@ static pa_hook_result_t handle_manual_routing(struct userdata *u, pa_stream_mana /* update BT SCO: close */ update_bt_sco_state(u, false, false, NULL); } +#endif if (IS_AVAILABLE_DIRECTION(data->stream_type, dm_device_direction)) { if ((use_internal_codec = pa_tz_device_is_use_internal_codec(*device))) @@ -1971,7 +2016,9 @@ void pa__done(pa_module *m) if (!(u = m->userdata)) return; +#ifdef __TIZEN_INTERNAL_BT_SCO__ bt_sco_close(u, false); +#endif if (u->loopback_modules) { pa_hashmap_remove_all(u->loopback_modules); diff --git a/src/tizen-device.c b/src/tizen-device.c index 996098a..cbeae10 100644 --- a/src/tizen-device.c +++ b/src/tizen-device.c @@ -145,8 +145,10 @@ static char* _device_get_info_str(pa_tz_device *device) { pa_strbuf_printf(buf, " Product ID : %04x\n", device->product_id); pa_strbuf_printf(buf, " Specified Stream role : %s\n", device->specified_stream_role); } +#ifdef __TIZEN_INTERNAL_BT_SCO__ if (device_type_is_equal(device->type, DEVICE_TYPE_BT_SCO)) pa_strbuf_printf(buf, " SCO opened : %s\n", pa_yes_no(device->sco_opened)); +#endif playback_str = get_playback_list_str(device->playback_devices); capture_str = get_capture_list_str(device->capture_devices); @@ -492,7 +494,9 @@ pa_tz_device* pa_tz_device_new(pa_tz_device_new_data *data) { device->state = DM_DEVICE_STATE_DEACTIVATED; device->creation_time = pa_rtclock_now(); device->use_internal_codec = data->use_internal_codec; +#ifdef __TIZEN_INTERNAL_BT_SCO__ device->sco_opened = false; +#endif device->is_running = false; device->specified_stream_role = pa_xstrdup("none"); @@ -832,6 +836,7 @@ pa_intset* pa_tz_device_get_stream_list(pa_tz_device *device) { return stream_id_set; } +#ifdef __TIZEN_INTERNAL_BT_SCO__ static int method_call_bt_sco_enable_pcm(pa_dbus_connection *conn, bool enable) { DBusMessage *msg, *reply; DBusError err; @@ -1081,4 +1086,5 @@ int pa_tz_device_sco_get_status(pa_tz_device *device, dm_device_bt_sco_status_t pa_log_info("BT SCO (%u) Get Status, %d", device->id, *status); return 0; } +#endif /* __TIZEN_INTERNAL_BT_SCO__ */ diff --git a/src/tizen-device.h b/src/tizen-device.h index 916a819..a7649ae 100644 --- a/src/tizen-device.h +++ b/src/tizen-device.h @@ -60,7 +60,9 @@ struct pa_tz_device { * false, if this device uses external card(bt-a2dp, usb */ bool use_internal_codec; /* If this is sco device, this can be used to */ +#ifdef __TIZEN_INTERNAL_BT_SCO__ bool sco_opened; +#endif /* Devices are contained in this list */ pa_idxset *list; @@ -153,12 +155,14 @@ bool pa_tz_device_is_use_internal_codec(pa_tz_device *device); bool pa_tz_device_is_all_suspended(pa_tz_device *device); pa_intset* pa_tz_device_get_stream_list(pa_tz_device *device); +#ifdef __TIZEN_INTERNAL_BT_SCO__ /* Only for BT SCO device */ int pa_tz_device_sco_enable_pcm(pa_tz_device *device, bool enable); int pa_tz_device_sco_open(pa_tz_device *device); int pa_tz_device_sco_close(pa_tz_device *device); int pa_tz_device_sco_get_property(pa_tz_device *device, bool *is_wide_band, bool *nrec); int pa_tz_device_sco_get_status(pa_tz_device *device, dm_device_bt_sco_status_t *status); +#endif /* Only for USB device */ int pa_tz_device_get_vendor_id(pa_tz_device *device);