From: Vibhav Pant vibhavp@gmail.com
--- dlls/winebth.sys/dbus.c | 142 +++++++++++++++++++++++++++++++ dlls/winebth.sys/unixlib.c | 20 +++++ dlls/winebth.sys/unixlib.h | 14 +++ dlls/winebth.sys/unixlib_priv.h | 3 + dlls/winebth.sys/winebluetooth.c | 21 +++++ dlls/winebth.sys/winebluetooth.h | 4 + dlls/winebth.sys/winebth.c | 31 ++++++- include/bthioctl.h | 12 +++ 8 files changed, 246 insertions(+), 1 deletion(-)
diff --git a/dlls/winebth.sys/dbus.c b/dlls/winebth.sys/dbus.c index de083925513..1fb2414aa9b 100644 --- a/dlls/winebth.sys/dbus.c +++ b/dlls/winebth.sys/dbus.c @@ -196,6 +196,22 @@ static const char *bluez_next_dict_entry( DBusMessageIter *iter, DBusMessageIter return name; }
+/* Adds an entry to a dict iterator of type {sv} */ +static void bluez_variant_dict_add_entry( DBusMessageIter *dict, const char *key, int value_type, + const char *value_type_str, const void *value ) +{ + DBusMessageIter entry, variant; + + p_dbus_message_iter_open_container( dict, DBUS_TYPE_DICT_ENTRY, NULL, &entry ); + p_dbus_message_iter_append_basic( &entry, DBUS_TYPE_STRING, &key ); + + p_dbus_message_iter_open_container( &entry, DBUS_TYPE_VARIANT, value_type_str, &variant ); + p_dbus_message_iter_append_basic( &variant, value_type, value ); + p_dbus_message_iter_close_container( &entry, &variant ); + + p_dbus_message_iter_close_container( dict, &entry ); +} + static const char *dbgstr_dbus_message( DBusMessage *message ) { const char *interface; @@ -289,6 +305,132 @@ static void parse_mac_address( const char *addr_str, BYTE dest[6] ) dest[i] = addr[i]; }
+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; + + 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 ); + p_dbus_message_iter_open_container( &iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter ); + bluez_variant_dict_add_entry( &dict_iter, "Transport", DBUS_TYPE_STRING, + DBUS_TYPE_STRING_AS_STRING, &transport_str ); + p_dbus_message_iter_close_container( &iter, &dict_iter ); + + p_dbus_error_init ( &error ); + + TRACE( "Setting discovery filter on %s to use transport %s\n", debugstr_a( adapter_path ), + debugstr_a( transport_str ) ); + reply = + p_dbus_connection_send_with_reply_and_block( connection, request, bluez_timeout, &error ); + p_dbus_message_unref( request ); + if (!reply) + { + NTSTATUS status; + 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, + enum winebluetooth_discovery_transport transport ) +{ + DBusMessage *request, *reply; + DBusError error; + + TRACE( "(%p, %s, %d)\n", connection, debugstr_a( adapter_path ), transport ); + + if (transport != WINEBLUETOOTH_DISCOVERY_TRANSPORT_DEFAULT) + { + const char *transport_str; + NTSTATUS status; + + switch ( transport ) + { + case WINEBLUETOOTH_DISCOVERY_TRANSPORT_AUTO: + transport_str = "auto"; + break; + case WINEBLUETOOTH_DISCOVERY_TRANSPORT_BR_EDR: + transport_str = "bredr"; + break; + case WINEBLUETOOTH_DISCOVERY_TRANSPORT_LE: + transport_str = "le"; + break; + default: + return STATUS_INVALID_PARAMETER; + } + + status = bluez_adapter_set_discovery_filter( connection, adapter_path, transport_str ); + 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 ); + reply = + p_dbus_connection_send_with_reply_and_block( connection, request, bluez_timeout, &error ); + p_dbus_message_unref( request ); + if (!reply) + { + NTSTATUS status; + 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_stop_discovery( void *connection, const char *adapter_path ) +{ + DBusMessage *request, *reply; + DBusError error; + + TRACE( "(%p, %s)\n", connection, debugstr_a( adapter_path ) ); + + request = p_dbus_message_new_method_call( BLUEZ_DEST, adapter_path, BLUEZ_INTERFACE_ADAPTER, + "StopDiscovery" ); + if (!request) return STATUS_NO_MEMORY; + + p_dbus_error_init( &error ); + reply = + p_dbus_connection_send_with_reply_and_block( connection, request, bluez_timeout, &error ); + p_dbus_message_unref( request ); + if (!reply) + { + NTSTATUS status; + ERR( "Failed to stop 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; +} + static void bluez_radio_prop_from_dict_entry( const char *prop_name, DBusMessageIter *variant, struct winebluetooth_radio_properties *props, winebluetooth_radio_props_mask_t *props_mask, diff --git a/dlls/winebth.sys/unixlib.c b/dlls/winebth.sys/unixlib.c index 79fdb101648..df8af51afe2 100644 --- a/dlls/winebth.sys/unixlib.c +++ b/dlls/winebth.sys/unixlib.c @@ -153,6 +153,23 @@ static NTSTATUS bluetooth_adapter_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, + params->transport ); +} + +static NTSTATUS bluetooth_adapter_stop_discovery( void *args ) +{ + struct bluetooth_adapter_stop_discovery_params *params = args; + + if (!dbus_connection) return STATUS_NOT_SUPPORTED; + return bluez_adapter_stop_discovery( dbus_connection, params->adapter->str ); +} + static NTSTATUS bluetooth_watcher_init( void *args ) { struct bluetooth_watcher_init_params *params = args; @@ -201,6 +218,9 @@ const unixlib_entry_t __wine_unix_call_funcs[] = { bluetooth_adapter_get_unique_name, bluetooth_adapter_free,
+ bluetooth_adapter_start_discovery, + bluetooth_adapter_stop_discovery, + bluetooth_device_free,
bluetooth_watcher_init, diff --git a/dlls/winebth.sys/unixlib.h b/dlls/winebth.sys/unixlib.h index 15fd76c1366..953d916d6b5 100644 --- a/dlls/winebth.sys/unixlib.h +++ b/dlls/winebth.sys/unixlib.h @@ -70,6 +70,17 @@ struct bluetooth_adapter_get_unique_name_params SIZE_T buf_size; };
+struct bluetooth_adapter_start_discovery_params +{ + unix_name_t adapter; + enum winebluetooth_discovery_transport transport; +}; + +struct bluetooth_adapter_stop_discovery_params +{ + unix_name_t adapter; +}; + struct bluetooth_get_device_props_by_path_params { unix_name_t device_path; @@ -124,6 +135,9 @@ enum bluetoothapis_funcs unix_bluetooth_adapter_get_unique_name, unix_bluetooth_adapter_free,
+ unix_bluetooth_adapter_start_discovery, + unix_bluetooth_adapter_stop_discovery, + unix_bluetooth_device_free,
unix_bluetooth_watcher_init, diff --git a/dlls/winebth.sys/unixlib_priv.h b/dlls/winebth.sys/unixlib_priv.h index 0690e86f99b..593c16c743a 100644 --- a/dlls/winebth.sys/unixlib_priv.h +++ b/dlls/winebth.sys/unixlib_priv.h @@ -49,6 +49,9 @@ extern void *bluez_dbus_init( void ); extern void bluez_dbus_close( void *connection ); extern void bluez_dbus_free( void *connection ); extern NTSTATUS bluez_dbus_loop( void *connection, void *watcher_ctx, struct winebluetooth_event_loop_result *result ); +extern NTSTATUS bluez_adapter_start_discovery( void *connection, const char *adapter_path, + enum winebluetooth_discovery_transport transport ); +extern NTSTATUS bluez_adapter_stop_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 /* SONAME_LIBDBUS_1 */ diff --git a/dlls/winebth.sys/winebluetooth.c b/dlls/winebth.sys/winebluetooth.c index 0cc499d7acb..f3d907cb850 100644 --- a/dlls/winebth.sys/winebluetooth.c +++ b/dlls/winebth.sys/winebluetooth.c @@ -55,6 +55,27 @@ NTSTATUS winebluetooth_radio_get_unique_name( winebluetooth_radio_t radio, char return status; }
+NTSTATUS winebluetooth_radio_start_discovery( + winebluetooth_radio_t radio, enum winebluetooth_discovery_transport transport ) +{ + struct bluetooth_adapter_start_discovery_params params = {0}; + + TRACE( "(%p, %d)\n", radio, transport ); + + params.adapter = radio.handle; + params.transport = transport; + return UNIX_BLUETOOTH_CALL( bluetooth_adapter_start_discovery, ¶ms ); +} + +NTSTATUS winebluetooth_radio_stop_discovery( winebluetooth_radio_t radio ) +{ + struct bluetooth_adapter_stop_discovery_params params = {0}; + + TRACE( "(%p)\n", radio.handle ); + params.adapter = radio.handle; + return UNIX_BLUETOOTH_CALL(bluetooth_adapter_stop_discovery, ¶ms); +} + void winebluetooth_radio_free( winebluetooth_radio_t radio ) { struct bluetooth_adapter_free_params args = { 0 }; diff --git a/dlls/winebth.sys/winebluetooth.h b/dlls/winebth.sys/winebluetooth.h index b043fb760bd..1d7bc4a6733 100644 --- a/dlls/winebth.sys/winebluetooth.h +++ b/dlls/winebth.sys/winebluetooth.h @@ -118,6 +118,7 @@ struct winebluetooth_device_properties
enum winebluetooth_discovery_transport { + WINEBLUETOOTH_DISCOVERY_TRANSPORT_DEFAULT, WINEBLUETOOTH_DISCOVERY_TRANSPORT_AUTO, WINEBLUETOOTH_DISCOVERY_TRANSPORT_BR_EDR, WINEBLUETOOTH_DISCOVERY_TRANSPORT_LE @@ -140,6 +141,9 @@ static inline BOOL winebluetooth_radio_equal( winebluetooth_radio_t r1, wineblue { return r1.handle == r2.handle; } +NTSTATUS winebluetooth_radio_start_discovery( + winebluetooth_radio_t radio, enum winebluetooth_discovery_transport transport ); +NTSTATUS winebluetooth_radio_stop_discovery( winebluetooth_radio_t radio );
void winebluetooth_device_free( winebluetooth_device_t device ); static inline BOOL winebluetooth_device_equal( winebluetooth_device_t d1, diff --git a/dlls/winebth.sys/winebth.c b/dlls/winebth.sys/winebth.c index f80336cec91..915ac4a62cf 100644 --- a/dlls/winebth.sys/winebth.c +++ b/dlls/winebth.sys/winebth.c @@ -85,6 +85,7 @@ struct bluetooth_radio
static NTSTATUS WINAPI dispatch_bluetooth(DEVICE_OBJECT *device, IRP *irp ) { + struct bluetooth_radio *ext = (struct bluetooth_radio *)device->DeviceExtension; IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation( irp ); ULONG code = stack->Parameters.DeviceIoControl.IoControlCode; ULONG insize = stack->Parameters.DeviceIoControl.InputBufferLength; @@ -151,10 +152,38 @@ static NTSTATUS WINAPI dispatch_bluetooth(DEVICE_OBJECT *device, IRP *irp ) status = STATUS_SUCCESS; irp->IoStatus.Information = sizeof( *info ); } + case IOCTL_WINEBTH_RADIO_START_DISCOVERY: + { + struct winebth_discovery_filter *filter = + (struct winebth_discovery_filter *)irp->AssociatedIrp.SystemBuffer; + enum winebluetooth_discovery_transport transport; + if (filter == NULL) + { + status = STATUS_INVALID_PARAMETER; + break; + } + if (insize < sizeof(*filter)) + { + status = STATUS_BUFFER_TOO_SMALL; + break; + } + + if (filter->le && filter->bredr) + transport = WINEBLUETOOTH_DISCOVERY_TRANSPORT_AUTO; + else if (filter->le) + transport = WINEBLUETOOTH_DISCOVERY_TRANSPORT_LE; + else if (filter->bredr) + transport = WINEBLUETOOTH_DISCOVERY_TRANSPORT_BR_EDR; + else + transport = WINEBLUETOOTH_DISCOVERY_TRANSPORT_DEFAULT; + status = winebluetooth_radio_start_discovery( ext->radio, transport ); + } + case IOCTL_WINEBTH_RADIO_STOP_DISCOVERY: + status = winebluetooth_radio_stop_discovery( ext->radio ); default: break; } - +
irp->IoStatus.Status = status; IoCompleteRequest( irp, IO_NO_INCREMENT ); diff --git a/include/bthioctl.h b/include/bthioctl.h index 773ea54f154..5b697f47382 100644 --- a/include/bthioctl.h +++ b/include/bthioctl.h @@ -41,6 +41,11 @@ #define IOCTL_INTERNAL_BTHENUM_GET_ENUMINFO CTL_CODE(FILE_DEVICE_BLUETOOTH, 0x01, METHOD_NEITHER, FILE_ANY_ACCESS) #define IOCTL_INTERNAL_BTHENUM_GET_DEVINFO CTL_CODE(FILE_DEVICE_BLUETOOTH, 0x02, METHOD_NEITHER, FILE_ANY_ACCESS)
+#ifdef WINE_BTH_EXTENSIONS +#define IOCTL_WINEBTH_RADIO_START_DISCOVERY CTL_CODE(FILE_DEVICE_BLUETOOTH, 0xa6, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_WINEBTH_RADIO_STOP_DISCOVERY CTL_CODE(FILE_DEVICE_BLUETOOTH, 0xa7, METHOD_BUFFERED, FILE_ANY_ACCESS) +#endif + #define LOCAL_RADIO_DISCOVERABLE (0x0001) #define LOCAL_RADIO_CONNECTABLE (0x0002)
@@ -67,5 +72,12 @@ typedef struct _BTH_DEVICE_INFO_LIST BTH_DEVICE_INFO deviceList[1]; } BTH_DEVICE_INFO_LIST, *PBTH_DEVICE_INFO_LIST;
+#ifdef WINE_BTH_EXTENSIONS +struct winebth_discovery_filter +{ + unsigned int bredr : 1; + unsigned int le : 1; +}; +#endif #endif /* __WINE_BTHIOCTL_H_ */