From: Vibhav Pant vibhavp@gmail.com
--- dlls/winebth.sys/dbus.c | 37 ++++++++++++++++++++++++++++++++ dlls/winebth.sys/unixlib.c | 9 ++++++++ dlls/winebth.sys/unixlib.h | 6 ++++++ dlls/winebth.sys/unixlib_priv.h | 1 + dlls/winebth.sys/winebluetooth.c | 9 ++++++++ dlls/winebth.sys/winebth.c | 33 ++++++++++++++++++++++++++++ dlls/winebth.sys/winebth_priv.h | 1 + include/bthioctl.h | 5 +++-- 8 files changed, 99 insertions(+), 2 deletions(-)
diff --git a/dlls/winebth.sys/dbus.c b/dlls/winebth.sys/dbus.c index b390828d231..f0b97401a94 100644 --- a/dlls/winebth.sys/dbus.c +++ b/dlls/winebth.sys/dbus.c @@ -1194,6 +1194,39 @@ done: return ret; }
+NTSTATUS bluez_device_disconnect( void *connection, const char *device_path ) +{ + DBusMessage *request, *reply = NULL; + NTSTATUS status; + DBusError error; + + TRACE( "(%p, %s)\n", connection, debugstr_a( device_path ) ); + + request = p_dbus_message_new_method_call( BLUEZ_DEST, device_path, BLUEZ_INTERFACE_DEVICE, "Disconnect" ); + if (!request) + return STATUS_NO_MEMORY; + + 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 disconnect device %s: %s: %s\n", debugstr_a( device_path ), 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; +} + struct bluez_watcher_event { struct list entry; @@ -2115,5 +2148,9 @@ NTSTATUS bluez_auth_agent_send_response( void *auth_agent, struct unix_name *dev { return STATUS_NOT_SUPPORTED; } +NTSTATUS bluez_device_disconnect( void *connection, const char *device_path ) +{ + return STATUS_NOT_SUPPORTED; +}
#endif /* SONAME_LIBDBUS_1 */ diff --git a/dlls/winebth.sys/unixlib.c b/dlls/winebth.sys/unixlib.c index e9c4010b047..7a9b80487c2 100644 --- a/dlls/winebth.sys/unixlib.c +++ b/dlls/winebth.sys/unixlib.c @@ -223,6 +223,14 @@ static NTSTATUS bluetooth_auth_send_response( void *args ) params->numeric_or_passkey, params->negative, params->authenticated ); }
+static NTSTATUS bluetooth_device_disconnect( void *args ) +{ + struct bluetooth_device_disconnect_params *params = args; + + if (!dbus_connection) return STATUS_NOT_SUPPORTED; + return bluez_device_disconnect( dbus_connection, params->device->str ); +} + static NTSTATUS bluetooth_get_event( void *args ) { struct bluetooth_get_event_params *params = args; @@ -243,6 +251,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] = { bluetooth_adapter_free,
bluetooth_device_free, + bluetooth_device_disconnect,
bluetooth_auth_agent_enable_incoming, bluetooth_auth_send_response, diff --git a/dlls/winebth.sys/unixlib.h b/dlls/winebth.sys/unixlib.h index bc963f48c98..c10964b5bc7 100644 --- a/dlls/winebth.sys/unixlib.h +++ b/dlls/winebth.sys/unixlib.h @@ -54,6 +54,11 @@ struct bluetooth_device_free_params unix_name_t device; };
+struct bluetooth_device_disconnect_params +{ + unix_name_t device; +}; + struct bluetooth_adapter_get_unique_name_params { unix_name_t adapter; @@ -106,6 +111,7 @@ enum bluetoothapis_funcs unix_bluetooth_adapter_free,
unix_bluetooth_device_free, + unix_bluetooth_device_disconnect,
unix_bluetooth_auth_agent_enable_incoming, unix_bluetooth_auth_send_response, diff --git a/dlls/winebth.sys/unixlib_priv.h b/dlls/winebth.sys/unixlib_priv.h index 7aff1386986..8853adec1a3 100644 --- a/dlls/winebth.sys/unixlib_priv.h +++ b/dlls/winebth.sys/unixlib_priv.h @@ -60,6 +60,7 @@ extern NTSTATUS bluez_auth_agent_stop( void *connection, void *ctx ); extern NTSTATUS bluez_auth_agent_send_response( void *auth_agent, struct unix_name *device, BLUETOOTH_AUTHENTICATION_METHOD method, UINT32 numeric_or_passkey, BOOL negative, BOOL *authenticated ); +extern NTSTATUS bluez_device_disconnect( void *connection, const char *device_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 f9ec589e0de..f3a16adf951 100644 --- a/dlls/winebth.sys/winebluetooth.c +++ b/dlls/winebth.sys/winebluetooth.c @@ -110,6 +110,15 @@ void winebluetooth_device_free( winebluetooth_device_t device ) UNIX_BLUETOOTH_CALL( bluetooth_device_free, &args ); }
+NTSTATUS winebluetooth_device_disconnect( winebluetooth_device_t device ) +{ + struct bluetooth_device_disconnect_params args = {0}; + TRACE( "(%p)\n", (void *)device.handle ); + + args.device = device.handle; + return UNIX_BLUETOOTH_CALL( bluetooth_device_disconnect, &args ); +} + void winebluetooth_device_properties_to_info( winebluetooth_device_props_mask_t props_mask, const struct winebluetooth_device_properties *props, BTH_DEVICE_INFO *info ) diff --git a/dlls/winebth.sys/winebth.c b/dlls/winebth.sys/winebth.c index 4293f0d4610..8bace437a18 100644 --- a/dlls/winebth.sys/winebth.c +++ b/dlls/winebth.sys/winebth.c @@ -225,6 +225,39 @@ static NTSTATUS WINAPI dispatch_bluetooth( DEVICE_OBJECT *device, IRP *irp ) status = STATUS_INVALID_BUFFER_SIZE; break; } + case IOCTL_BTH_DISCONNECT_DEVICE: + { + const BTH_ADDR *param = irp->AssociatedIrp.SystemBuffer; + BTH_ADDR device_addr; + struct bluetooth_remote_device *device; + + if (!param || insize < sizeof( *param )) + { + status = STATUS_INVALID_USER_BUFFER; + break; + } + + device_addr = RtlUlonglongByteSwap( *param ) >> 16; + status = STATUS_DEVICE_NOT_CONNECTED; + + EnterCriticalSection( &ext->remote_devices_cs ); + LIST_FOR_EACH_ENTRY( device, &ext->remote_devices, struct bluetooth_remote_device, entry ) + { + BOOL matches; + + EnterCriticalSection( &device->props_cs ); + matches = device->props_mask & WINEBLUETOOTH_DEVICE_PROPERTY_ADDRESS && + device_addr == device->props.address.ullLong; + LeaveCriticalSection( &device->props_cs ); + if (matches) + { + status = winebluetooth_device_disconnect( device->device ); + break; + } + } + LeaveCriticalSection( &ext->remote_devices_cs ); + break; + } case IOCTL_WINEBTH_RADIO_SET_FLAG: { const struct winebth_radio_set_flag_params *params = irp->AssociatedIrp.SystemBuffer; diff --git a/dlls/winebth.sys/winebth_priv.h b/dlls/winebth.sys/winebth_priv.h index e47491b6956..e37ac20f140 100644 --- a/dlls/winebth.sys/winebth_priv.h +++ b/dlls/winebth.sys/winebth_priv.h @@ -209,6 +209,7 @@ static inline BOOL winebluetooth_device_equal( winebluetooth_device_t d1, winebl void winebluetooth_device_properties_to_info( winebluetooth_device_props_mask_t props_mask, const struct winebluetooth_device_properties *props, BTH_DEVICE_INFO *info ); +NTSTATUS winebluetooth_device_disconnect( winebluetooth_device_t device );
NTSTATUS winebluetooth_auth_send_response( winebluetooth_device_t device, BLUETOOTH_AUTHENTICATION_METHOD method, UINT32 numeric_or_passkey, BOOL negative, BOOL *authenticated ); diff --git a/include/bthioctl.h b/include/bthioctl.h index 56a665e9f41..d08d002aaaa 100644 --- a/include/bthioctl.h +++ b/include/bthioctl.h @@ -22,8 +22,9 @@ #ifndef __BTHIOCTL_H__ #define __BTHIOCTL_H__
-#define IOCTL_BTH_GET_LOCAL_INFO CTL_CODE(FILE_DEVICE_BLUETOOTH, 0x00, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_BTH_GET_DEVICE_INFO CTL_CODE(FILE_DEVICE_BLUETOOTH, 0x02, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_BTH_GET_LOCAL_INFO CTL_CODE(FILE_DEVICE_BLUETOOTH, 0x00, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_BTH_GET_DEVICE_INFO CTL_CODE(FILE_DEVICE_BLUETOOTH, 0x02, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_BTH_DISCONNECT_DEVICE CTL_CODE(FILE_DEVICE_BLUETOOTH, 0x03, METHOD_BUFFERED, FILE_ANY_ACCESS)
#include <pshpack1.h>