From: Vibhav Pant vibhavp@gmail.com
--- dlls/winebth.sys/dbus.c | 130 +++++++++++++++++++++++++++++++ dlls/winebth.sys/unixlib.c | 9 +++ dlls/winebth.sys/unixlib.h | 6 ++ dlls/winebth.sys/unixlib_priv.h | 1 + dlls/winebth.sys/winebluetooth.c | 10 +++ dlls/winebth.sys/winebth.c | 3 + dlls/winebth.sys/winebth_priv.h | 1 + include/wine/winebth.h | 2 + 8 files changed, 162 insertions(+)
diff --git a/dlls/winebth.sys/dbus.c b/dlls/winebth.sys/dbus.c index 153c4e60ad1..6bd90008735 100644 --- a/dlls/winebth.sys/dbus.c +++ b/dlls/winebth.sys/dbus.c @@ -183,6 +183,39 @@ static const char *bluez_next_dict_entry( DBusMessageIter *iter, DBusMessageIter return name; }
+/* Adds an entry to a dict iterator of type {sv} */ +static BOOL bluez_variant_dict_add_entry( DBusMessageIter *dict, const char *key, int value_type, + const char *value_type_str, const void *value ) +{ + DBusMessageIter entry, variant; + + if (!p_dbus_message_iter_open_container( dict, DBUS_TYPE_DICT_ENTRY, NULL, &entry )) return FALSE; + if (!p_dbus_message_iter_append_basic( &entry, DBUS_TYPE_STRING, &key )) + { + p_dbus_message_iter_abandon_container( dict, &entry ); + return FALSE; + } + + if (!p_dbus_message_iter_open_container( &entry, DBUS_TYPE_VARIANT, value_type_str, &variant )) + { + p_dbus_message_iter_abandon_container( dict, &entry ); + return FALSE; + } + if (!p_dbus_message_iter_append_basic( &variant, value_type, value )) + { + p_dbus_message_iter_abandon_container( &entry, &variant ); + p_dbus_message_iter_abandon_container( dict, &entry ); + return FALSE; + } + if (!p_dbus_message_iter_close_container( &entry, &variant )) + { + p_dbus_message_iter_abandon_container( dict, &entry ); + return FALSE; + } + + return !!p_dbus_message_iter_close_container( dict, &entry ); +} + static const char *dbgstr_dbus_message( DBusMessage *message ) { const char *interface; @@ -329,6 +362,99 @@ static NTSTATUS bluez_dbus_send_and_wait_for_reply( DBusConnection *connection, return bluez_dbus_pending_call_wait( pending_call, reply, error ); }
+static NTSTATUS bluez_adapter_set_discovery_filter( void *connection, const char *adapter_path, + const char *transport_str ) +{ + DBusMessage *request, *reply; + DBusMessageIter iter, dict_iter; + DBusError error; + NTSTATUS status; + + TRACE( "(%p, %s, %s)\n", connection, debugstr_a( adapter_path ), debugstr_a( transport_str ) ); + + request = p_dbus_message_new_method_call( BLUEZ_DEST, adapter_path, BLUEZ_INTERFACE_ADAPTER, + "SetDiscoveryFilter" ); + if (!request) return STATUS_NO_MEMORY; + + p_dbus_message_iter_init_append( request, &iter ); + if (!p_dbus_message_iter_open_container( &iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter )) + { + p_dbus_message_unref( request ); + return STATUS_NO_MEMORY; + } + if (!bluez_variant_dict_add_entry( &dict_iter, "Transport", DBUS_TYPE_STRING, + DBUS_TYPE_STRING_AS_STRING, &transport_str )) + { + p_dbus_message_iter_abandon_container( &iter, &dict_iter ); + p_dbus_message_unref( request ); + return STATUS_NO_MEMORY; + } + if (!p_dbus_message_iter_close_container( &iter, &dict_iter )) + { + p_dbus_message_unref( request ); + return STATUS_NO_MEMORY; + } + + p_dbus_error_init ( &error ); + + TRACE( "Setting discovery filter on %s to use transport %s\n", debugstr_a( adapter_path ), + debugstr_a( transport_str ) ); + status = bluez_dbus_send_and_wait_for_reply( connection, request, &reply, &error ); + if (status) + { + p_dbus_error_free( &error ); + return status; + } + if (!reply) + { + WARN( "Failed to set discovery filter: %s: %s\n", debugstr_a( error.name ), debugstr_a( error.message ) ); + status = bluez_dbus_error_to_ntstatus( &error ); + p_dbus_error_free( &error ); + return status; + } + p_dbus_message_unref( reply ); + p_dbus_error_free( &error ); + + return STATUS_SUCCESS; + +} + +NTSTATUS bluez_adapter_start_discovery( void *connection, const char *adapter_path ) +{ + DBusMessage *request, *reply; + DBusError error; + NTSTATUS status; + + TRACE( "(%p, %s)\n", connection, debugstr_a( adapter_path ) ); + + status = bluez_adapter_set_discovery_filter( connection, adapter_path, "bredr" ); + if (status != STATUS_SUCCESS) return status; + + request = p_dbus_message_new_method_call( BLUEZ_DEST, adapter_path, BLUEZ_INTERFACE_ADAPTER, + "StartDiscovery" ); + if (!request) return STATUS_NO_MEMORY; + + TRACE( "Starting discovery on %s\n", debugstr_a( adapter_path ) ); + p_dbus_error_init( &error ); + status = bluez_dbus_send_and_wait_for_reply( connection, request, &reply, &error ); + if (status) + { + p_dbus_error_free( &error ); + return status; + } + if (!reply) + { + ERR( "Failed to start discovery on adapter %s: %s: %s", debugstr_a( adapter_path ), + debugstr_a( error.message ), debugstr_a( error.name ) ); + status = bluez_dbus_error_to_ntstatus( &error ); + p_dbus_error_free( &error ); + return status; + } + p_dbus_error_free( &error ); + p_dbus_message_unref( reply ); + return STATUS_SUCCESS; +} + NTSTATUS bluez_adapter_set_prop( void *connection, struct bluetooth_adapter_set_prop_params *params ) { DBusMessage *request, *reply; @@ -1560,5 +1686,9 @@ NTSTATUS bluez_adapter_set_prop( void *connection, struct bluetooth_adapter_set_ { return STATUS_NOT_SUPPORTED; } +NTSTATUS bluez_adapter_start_discovery( void *connection, const char *adapter_path ) +{ + return STATUS_NOT_SUPPORTED; +}
#endif /* SONAME_LIBDBUS_1 */ diff --git a/dlls/winebth.sys/unixlib.c b/dlls/winebth.sys/unixlib.c index a80a51d9cf1..9ae1bf4022b 100644 --- a/dlls/winebth.sys/unixlib.c +++ b/dlls/winebth.sys/unixlib.c @@ -171,6 +171,14 @@ static NTSTATUS bluetooth_device_free( void *args ) return STATUS_SUCCESS; }
+static NTSTATUS bluetooth_adapter_start_discovery( void *args ) +{ + struct bluetooth_adapter_start_discovery_params *params = args; + + if (!dbus_connection) return STATUS_NOT_SUPPORTED; + return bluez_adapter_start_discovery( dbus_connection, params->adapter->str ); +} + static NTSTATUS bluetooth_get_event( void *args ) { struct bluetooth_get_event_params *params = args; @@ -186,6 +194,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] = {
bluetooth_adapter_set_prop, bluetooth_adapter_get_unique_name, + bluetooth_adapter_start_discovery, bluetooth_adapter_free,
bluetooth_device_free, diff --git a/dlls/winebth.sys/unixlib.h b/dlls/winebth.sys/unixlib.h index 002cc2cc3aa..7de32fd38f0 100644 --- a/dlls/winebth.sys/unixlib.h +++ b/dlls/winebth.sys/unixlib.h @@ -70,6 +70,11 @@ struct bluetooth_adapter_set_prop_params union winebluetooth_property *prop; };
+struct bluetooth_adapter_start_discovery_params +{ + unix_name_t adapter; +}; + struct bluetooth_get_event_params { struct winebluetooth_event result; @@ -82,6 +87,7 @@ enum bluetoothapis_funcs
unix_bluetooth_adapter_set_prop, unix_bluetooth_adapter_get_unique_name, + unix_bluetooth_adapter_start_discovery, unix_bluetooth_adapter_free,
unix_bluetooth_device_free, diff --git a/dlls/winebth.sys/unixlib_priv.h b/dlls/winebth.sys/unixlib_priv.h index 5146799e705..3dc7b956293 100644 --- a/dlls/winebth.sys/unixlib_priv.h +++ b/dlls/winebth.sys/unixlib_priv.h @@ -50,6 +50,7 @@ extern void bluez_dbus_free( void *connection ); extern NTSTATUS bluez_dbus_loop( void *connection, void *watcher_ctx, struct winebluetooth_event *result ); extern NTSTATUS bluez_adapter_set_prop( void *connection, struct bluetooth_adapter_set_prop_params *params ); +extern NTSTATUS bluez_adapter_start_discovery( void *connection, const char *adapter_path ); extern NTSTATUS bluez_watcher_init( void *connection, void **ctx ); extern void bluez_watcher_close( void *connection, void *ctx ); #endif /* __WINE_WINEBTH_UNIXLIB_PRIV_H */ diff --git a/dlls/winebth.sys/winebluetooth.c b/dlls/winebth.sys/winebluetooth.c index 6ebfe55ac28..62ae685f55d 100644 --- a/dlls/winebth.sys/winebluetooth.c +++ b/dlls/winebth.sys/winebluetooth.c @@ -68,6 +68,16 @@ NTSTATUS winebluetooth_radio_set_property( winebluetooth_radio_t radio, return UNIX_BLUETOOTH_CALL( bluetooth_adapter_set_prop, ¶ms ); }
+NTSTATUS winebluetooth_radio_start_discovery( winebluetooth_radio_t radio ) +{ + struct bluetooth_adapter_start_discovery_params params = {0}; + + TRACE( "(%p)\n", (void *)radio.handle ); + + params.adapter = radio.handle; + return UNIX_BLUETOOTH_CALL( bluetooth_adapter_start_discovery, ¶ms ); +} + void winebluetooth_radio_free( winebluetooth_radio_t radio ) { struct bluetooth_adapter_free_params args = { 0 }; diff --git a/dlls/winebth.sys/winebth.c b/dlls/winebth.sys/winebth.c index c3af6f9b95f..2dab1614644 100644 --- a/dlls/winebth.sys/winebth.c +++ b/dlls/winebth.sys/winebth.c @@ -251,6 +251,9 @@ static NTSTATUS WINAPI dispatch_bluetooth( DEVICE_OBJECT *device, IRP *irp ) status = winebluetooth_radio_set_property( ext->radio, params->flag, &prop_value ); break; } + case IOCTL_WINEBTH_RADIO_START_DISCOVERY: + status = winebluetooth_radio_start_discovery( ext->radio ); + break; default: FIXME( "Unimplemented IOCTL code: %#lx\n", code ); break; diff --git a/dlls/winebth.sys/winebth_priv.h b/dlls/winebth.sys/winebth_priv.h index b50935c091c..a0d4e689e90 100644 --- a/dlls/winebth.sys/winebth_priv.h +++ b/dlls/winebth.sys/winebth_priv.h @@ -196,6 +196,7 @@ static inline BOOL winebluetooth_radio_equal( winebluetooth_radio_t r1, wineblue NTSTATUS winebluetooth_radio_set_property( winebluetooth_radio_t radio, ULONG prop_flag, union winebluetooth_property *property ); +NTSTATUS winebluetooth_radio_start_discovery( winebluetooth_radio_t radio );
void winebluetooth_device_free( winebluetooth_device_t device ); static inline BOOL winebluetooth_device_equal( winebluetooth_device_t d1, winebluetooth_device_t d2 ) diff --git a/include/wine/winebth.h b/include/wine/winebth.h index c26a2100fb9..222d780e10d 100644 --- a/include/wine/winebth.h +++ b/include/wine/winebth.h @@ -25,6 +25,8 @@ /* Set the discoverability or connectable flag for a local radio. Enabling discoverability will also enable incoming * connections, while disabling incoming connections disables discoverability as well. */ #define IOCTL_WINEBTH_RADIO_SET_FLAG CTL_CODE(FILE_DEVICE_BLUETOOTH, 0xa3, METHOD_BUFFERED, FILE_ANY_ACCESS) +/* Start device inquiry for a local radio. */ +#define IOCTL_WINEBTH_RADIO_START_DISCOVERY CTL_CODE(FILE_DEVICE_BLUETOOTH, 0xa6, METHOD_BUFFERED, FILE_ANY_ACCESS)
#include <pshpack1.h>