From: Vibhav Pant vibhavp@gmail.com
--- dlls/winebth.sys/dbus.c | 67 ++++++++++++++++++++++++++++++++ dlls/winebth.sys/unixlib.c | 9 +++++ dlls/winebth.sys/unixlib.h | 9 +++++ dlls/winebth.sys/unixlib_priv.h | 2 + dlls/winebth.sys/winebluetooth.c | 30 +++++++++++++- dlls/winebth.sys/winebluetooth.h | 3 ++ dlls/winebth.sys/winebth.c | 33 ++++++++++++++++ include/bthioctl.h | 2 + 8 files changed, 154 insertions(+), 1 deletion(-)
diff --git a/dlls/winebth.sys/dbus.c b/dlls/winebth.sys/dbus.c index 1fb2414aa9b..5f5f5d4c2d3 100644 --- a/dlls/winebth.sys/dbus.c +++ b/dlls/winebth.sys/dbus.c @@ -305,6 +305,73 @@ static void parse_mac_address( const char *addr_str, BYTE dest[6] ) dest[i] = addr[i]; }
+NTSTATUS bluez_adapter_set_prop( void *connection, struct bluetooth_adapter_set_prop_params *params ) +{ + DBusMessage *request, *reply; + DBusMessageIter iter, sub_iter; + DBusError error; + DBusBasicValue val; + int val_type; + static const char *adapter_iface = BLUEZ_INTERFACE_ADAPTER; + const char *prop_name; + + TRACE( "(%p, %p)\n", connection, params ); + + switch (params->prop_flag) + { + case WINEBLUETOOTH_RADIO_PROPERTY_DISCOVERABLE: + prop_name = "Discoverable"; + val.bool_val = params->prop->bool; + val_type = DBUS_TYPE_BOOLEAN; + break; + case WINEBLUETOOTH_RADIO_PROPERTY_CONNECTABLE: + prop_name = "Connectable"; + val.bool_val = params->prop->bool; + val_type = DBUS_TYPE_BOOLEAN; + break; + case WINEBLUETOOTH_RADIO_PROPERTY_PAIRABLE: + prop_name = "Pairable"; + val.bool_val = params->prop->bool; + val_type = DBUS_TYPE_BOOLEAN; + break; + default: + return STATUS_INVALID_PARAMETER; + } + + TRACE( "Setting property %s for adapter %s\n", debugstr_a( prop_name ), + debugstr_a( params->adapter->str ) ); + request = p_dbus_message_new_method_call( BLUEZ_DEST, params->adapter->str, + DBUS_INTERFACE_PROPERTIES, "Set" ); + if (!request) return STATUS_NO_MEMORY; + + p_dbus_message_iter_init_append( request, &iter ); + p_dbus_message_iter_append_basic( &iter, DBUS_TYPE_STRING, &adapter_iface ); + p_dbus_message_iter_append_basic( &iter, DBUS_TYPE_STRING, &prop_name ); + p_dbus_message_iter_open_container( &iter, DBUS_TYPE_VARIANT, DBUS_TYPE_BOOLEAN_AS_STRING, + &sub_iter ); + p_dbus_message_iter_append_basic( &sub_iter, val_type, &val ); + p_dbus_message_iter_close_container( &iter, &sub_iter ); + + 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 set property %s for adapter %s: %s: %s\n", debugstr_a( prop_name ), + debugstr_a( params->adapter->str ), debugstr_a( error.name ), + debugstr_a( error.message ) ); + 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 NTSTATUS bluez_adapter_set_discovery_filter( void *connection, const char *adapter_path, const char *transport_str ) { diff --git a/dlls/winebth.sys/unixlib.c b/dlls/winebth.sys/unixlib.c index df8af51afe2..017e073207e 100644 --- a/dlls/winebth.sys/unixlib.c +++ b/dlls/winebth.sys/unixlib.c @@ -153,6 +153,14 @@ static NTSTATUS bluetooth_adapter_free( void *args ) return STATUS_SUCCESS; }
+static NTSTATUS bluetooth_adapter_set_prop( void *arg ) +{ + struct bluetooth_adapter_set_prop_params *params = arg; + + if (!dbus_connection) return STATUS_NOT_SUPPORTED; + return bluez_adapter_set_prop( dbus_connection, params ); +} + static NTSTATUS bluetooth_adapter_start_discovery( void *args ) { struct bluetooth_adapter_start_discovery_params *params = args; @@ -215,6 +223,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] = { bluetooth_init, bluetooth_shutdown,
+ bluetooth_adapter_set_prop, bluetooth_adapter_get_unique_name, bluetooth_adapter_free,
diff --git a/dlls/winebth.sys/unixlib.h b/dlls/winebth.sys/unixlib.h index 953d916d6b5..ba468e54b19 100644 --- a/dlls/winebth.sys/unixlib.h +++ b/dlls/winebth.sys/unixlib.h @@ -70,6 +70,14 @@ struct bluetooth_adapter_get_unique_name_params SIZE_T buf_size; };
+struct bluetooth_adapter_set_prop_params +{ + unix_name_t adapter; + winebluetooth_radio_props_mask_t prop_flag; + + union winebluetooth_property *prop; +}; + struct bluetooth_adapter_start_discovery_params { unix_name_t adapter; @@ -132,6 +140,7 @@ enum bluetoothapis_funcs unix_bluetooth_init, unix_bluetooth_shutdown,
+ unix_bluetooth_adapter_set_prop, unix_bluetooth_adapter_get_unique_name, unix_bluetooth_adapter_free,
diff --git a/dlls/winebth.sys/unixlib_priv.h b/dlls/winebth.sys/unixlib_priv.h index 593c16c743a..2375aee531f 100644 --- a/dlls/winebth.sys/unixlib_priv.h +++ b/dlls/winebth.sys/unixlib_priv.h @@ -49,6 +49,8 @@ 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_set_prop( void *connection, + struct bluetooth_adapter_set_prop_params *params ); 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 ); diff --git a/dlls/winebth.sys/winebluetooth.c b/dlls/winebth.sys/winebluetooth.c index 19a7d7ea421..07d4e6a022d 100644 --- a/dlls/winebth.sys/winebluetooth.c +++ b/dlls/winebth.sys/winebluetooth.c @@ -55,6 +55,34 @@ NTSTATUS winebluetooth_radio_get_unique_name( winebluetooth_radio_t radio, char return status; }
+NTSTATUS winebluetooth_radio_set_property( winebluetooth_radio_t radio, + winebluetooth_radio_props_mask_t prop, + union winebluetooth_property *property ) +{ + struct bluetooth_adapter_set_prop_params params = { 0 }; + NTSTATUS status; + + TRACE( "(%p, %#x, %p)\n", (void *)radio.handle, prop, property ); + + params.adapter = radio.handle; + + switch (prop) + { + case WINEBLUETOOTH_RADIO_PROPERTY_CONNECTABLE: + case WINEBLUETOOTH_RADIO_PROPERTY_DISCOVERABLE: + case WINEBLUETOOTH_RADIO_PROPERTY_PAIRABLE: + break; + default: + return STATUS_INVALID_PARAMETER; + } + + status = UNIX_BLUETOOTH_CALL( bluetooth_adapter_set_prop, ¶ms ); + + if (status != STATUS_SUCCESS) return status; + + return STATUS_SUCCESS; +} + NTSTATUS winebluetooth_radio_start_discovery( winebluetooth_radio_t radio, enum winebluetooth_discovery_transport transport ) { @@ -111,7 +139,7 @@ NTSTATUS winebluetooth_guid_array_free( UINT_PTR src )
TRACE( "(%p)\n", (void *)src ); params.arr = src; - return UNIX_BLUETOOTH_CALL( bluetooth_guid_array_free, ¶ms ); + return UNIX_BLUETOOTH_CALL( bluetooth_guid_array_free, ¶ms ); }
NTSTATUS winebluetooth_watcher_init( winebluetooth_watcher_t *watcher ) diff --git a/dlls/winebth.sys/winebluetooth.h b/dlls/winebth.sys/winebluetooth.h index 1d7bc4a6733..f3cf220ae31 100644 --- a/dlls/winebth.sys/winebluetooth.h +++ b/dlls/winebth.sys/winebluetooth.h @@ -141,6 +141,9 @@ static inline BOOL winebluetooth_radio_equal( winebluetooth_radio_t r1, wineblue { return r1.handle == r2.handle; } +NTSTATUS winebluetooth_radio_set_property( winebluetooth_radio_t radio, + winebluetooth_radio_props_mask_t prop, + union winebluetooth_property *property ); NTSTATUS winebluetooth_radio_start_discovery( winebluetooth_radio_t radio, enum winebluetooth_discovery_transport transport ); NTSTATUS winebluetooth_radio_stop_discovery( winebluetooth_radio_t radio ); diff --git a/dlls/winebth.sys/winebth.c b/dlls/winebth.sys/winebth.c index 08938ca95cd..c2361979919 100644 --- a/dlls/winebth.sys/winebth.c +++ b/dlls/winebth.sys/winebth.c @@ -152,6 +152,39 @@ static NTSTATUS WINAPI dispatch_bluetooth(DEVICE_OBJECT *device, IRP *irp ) status = STATUS_SUCCESS; irp->IoStatus.Information = sizeof( *info ); } + case IOCTL_WINEBTH_RADIO_SET_FLAG: + case IOCTL_WINEBTH_RADIO_UNSET_FLAG: + { + UINT32 *flags = (UINT32 *)irp->AssociatedIrp.SystemBuffer; + union winebluetooth_property prop_value = {.bool = code == IOCTL_WINEBTH_RADIO_SET_FLAG}; + + if (flags == NULL) + { + status = STATUS_INVALID_PARAMETER; + break; + } + if (insize < sizeof(UINT32)) + { + status = STATUS_BUFFER_TOO_SMALL; + break; + } + + TRACE( "flags=%s\n", debugstr_radio_flags( *flags ) ); + switch (*flags) + { + case LOCAL_RADIO_CONNECTABLE: + status = winebluetooth_radio_set_property( + ext->radio, WINEBLUETOOTH_RADIO_PROPERTY_CONNECTABLE, &prop_value ); + break; + case LOCAL_RADIO_DISCOVERABLE: + status = winebluetooth_radio_set_property( + ext->radio, WINEBLUETOOTH_RADIO_PROPERTY_DISCOVERABLE, &prop_value ); + break; + default: + status = STATUS_INVALID_PARAMETER; + } + break; + } case IOCTL_WINEBTH_RADIO_START_DISCOVERY: { struct winebth_discovery_filter *filter = diff --git a/include/bthioctl.h b/include/bthioctl.h index 5b697f47382..0b9cc6164a4 100644 --- a/include/bthioctl.h +++ b/include/bthioctl.h @@ -42,6 +42,8 @@ #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_SET_FLAG CTL_CODE(FILE_DEVICE_BLUETOOTH, 0xa3, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_WINEBTH_RADIO_UNSET_FLAG CTL_CODE(FILE_DEVICE_BLUETOOTH, 0xa4, METHOD_BUFFERED, FILE_ANY_ACCESS) #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