Re: [PATCH BlueZ 2/2] plugins/sixaxis: Implement cable pairing for DualSense

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, 2025-06-03 at 12:56 +0300, Egor Vorontsov wrote:
> The code is very similar to that for DS4, but I found it's better
> to separate the matters instead of generalizing it via constants.

I don't think there was a need to mention it that way, the code is
already setup in such a way that it has separate code paths for each
supported type of hardware. Maybe:
"The protocol used by the DualSense cable pairing is similar to that
used by the DualShock4 controllers, but different enough that using
separate code paths is more legible."

> Also added a request to enable Bluetooth on the controller to initiate
> pairing without the need to disconnect it and power on again wirelessly,
> basically emulating what PS itself does. Only for DualSense family now,
> but can be expanded to DS4 too (I don't have one at hand to test this).

The fact that you wrote "also" in this commit message is a good
indicator that this should probably have been a separate commit.

> ---
>  plugins/sixaxis.c | 107
> ++++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 104 insertions(+), 3 deletions(-)
> 
> diff --git a/plugins/sixaxis.c b/plugins/sixaxis.c
> index 1fab8ae59..a583c8b82 100644
> --- a/plugins/sixaxis.c
> +++ b/plugins/sixaxis.c
> @@ -131,12 +131,36 @@ static int ds4_get_device_bdaddr(int fd,
> bdaddr_t *bdaddr)
>  	return 0;
>  }
>  
> +static int dualsense_get_device_bdaddr(int fd, bdaddr_t *bdaddr)
> +{
> +	uint8_t buf[20];
> +	int ret;
> +
> +	memset(buf, 0, sizeof(buf));
> +
> +	buf[0] = 0x09;
> +
> +	ret = ioctl(fd, HIDIOCGFEATURE(sizeof(buf)), buf);
> +	if (ret < 0) {
> +		error("sixaxis: failed to read DualSense device
> address (%s)",
> +		      strerror(errno));
> +		return ret;
> +	}
> +
> +	/* address is little-endian on DualSense */
> +	bacpy(bdaddr, (bdaddr_t*) (buf + 1));
> +
> +	return 0;
> +}
> +
>  static int get_device_bdaddr(int fd, bdaddr_t *bdaddr,
> CablePairingType type)
>  {
>  	if (type == CABLE_PAIRING_SIXAXIS)
>  		return sixaxis_get_device_bdaddr(fd, bdaddr);
>  	else if (type == CABLE_PAIRING_DS4)
>  		return ds4_get_device_bdaddr(fd, bdaddr);
> +	else if (type == CABLE_PAIRING_DUALSENSE)
> +		return dualsense_get_device_bdaddr(fd, bdaddr);
>  	return -1;
>  }
>  
> @@ -183,12 +207,36 @@ static int ds4_get_central_bdaddr(int fd,
> bdaddr_t *bdaddr)
>  	return 0;
>  }
>  
> +static int dualsense_get_central_bdaddr(int fd, bdaddr_t *bdaddr)
> +{
> +	uint8_t buf[20];
> +	int ret;
> +
> +	memset(buf, 0, sizeof(buf));
> +
> +	buf[0] = 0x09;
> +
> +	ret = ioctl(fd, HIDIOCGFEATURE(sizeof(buf)), buf);
> +	if (ret < 0) {
> +		error("sixaxis: failed to read DualSense central
> address (%s)",
> +		      strerror(errno));
> +		return ret;
> +	}
> +
> +	/* address is little-endian on DualSense */
> +	bacpy(bdaddr, (bdaddr_t*) (buf + 10));
> +
> +	return 0;
> +}
> +
>  static int get_central_bdaddr(int fd, bdaddr_t *bdaddr,
> CablePairingType type)
>  {
>  	if (type == CABLE_PAIRING_SIXAXIS)
>  		return sixaxis_get_central_bdaddr(fd, bdaddr);
>  	else if (type == CABLE_PAIRING_DS4)
>  		return ds4_get_central_bdaddr(fd, bdaddr);
> +	else if (type == CABLE_PAIRING_DUALSENSE)
> +		return dualsense_get_central_bdaddr(fd, bdaddr);
>  	return -1;
>  }
>  
> @@ -230,6 +278,26 @@ static int ds4_set_central_bdaddr(int fd, const
> bdaddr_t *bdaddr)
>  	return ret;
>  }
>  
> +static int dualsense_set_central_bdaddr(int fd, const bdaddr_t
> *bdaddr)
> +{
> +	uint8_t buf[27];
> +	int ret;
> +
> +	buf[0] = 0x0A;
> +	bacpy((bdaddr_t*) (buf + 1), bdaddr);
> +	/* TODO: we could put the key here but
> +	   there is no way to force a re-loading
> +	   of link keys to the kernel from here. */
> +	memset(buf + 7, 0, 16);
> +
> +	ret = ioctl(fd, HIDIOCSFEATURE(sizeof(buf)), buf);
> +	if (ret < 0)
> +		error("sixaxis: failed to write DualSense central
> address (%s)",
> +		      strerror(errno));
> +
> +	return ret;
> +}
> +
>  static int set_central_bdaddr(int fd, const bdaddr_t *bdaddr,
>  					CablePairingType type)
>  {
> @@ -237,6 +305,32 @@ static int set_central_bdaddr(int fd, const
> bdaddr_t *bdaddr,
>  		return sixaxis_set_central_bdaddr(fd, bdaddr);
>  	else if (type == CABLE_PAIRING_DS4)
>  		return ds4_set_central_bdaddr(fd, bdaddr);
> +	else if (type == CABLE_PAIRING_DUALSENSE)
> +		return dualsense_set_central_bdaddr(fd, bdaddr);
> +	return -1;
> +}
> +
> +static int dualsense_set_bluetooth_state(int fd, bool state)
> +{
> +	uint8_t buf[48];
> +	int ret;
> +
> +	buf[0] = 0x08;
> +	buf[1] = state?1:2;

buf[1] = state ? 0x1 : 0x2;

> +
> +	ret = ioctl(fd, HIDIOCSFEATURE(sizeof(buf)), buf);
> +	if (ret < 0)
> +		error("sixaxis: failed to set DualSense Bluetooth
> state (%s)",
> +		      strerror(errno));
> +
> +	return ret;
> +}
> +
> +static int set_bluetooth_state(int fd, CablePairingType type,
> +					bool state)
> +{
> +	if (type == CABLE_PAIRING_DUALSENSE)
> +		return dualsense_set_bluetooth_state(fd, state);
>  	return -1;
>  }
>  
> @@ -297,12 +391,13 @@ static void agent_auth_cb(DBusError *derr, void
> *user_data)
>  	remove_device = false;
>  	btd_device_set_temporary(closure->device, false);
>  
> -	if (closure->type == CABLE_PAIRING_SIXAXIS) {
> +	if (closure->type == CABLE_PAIRING_SIXAXIS)

It's a multi-line conditional, we still want the braces.

>  		btd_device_set_record(closure->device, HID_UUID,
>  						
> SIXAXIS_HID_SDP_RECORD);
>  
> +	if (closure->type == CABLE_PAIRING_SIXAXIS ||
> +				closure->type ==
> CABLE_PAIRING_DUALSENSE) {
>  		device_set_cable_pairing(closure->device, true);
> -

No white space changes please.

>  		server_set_cable_pairing(adapter_bdaddr, true);
>  	}

device_set_cable_pairing() and server_set_cable_pairing() are supposed
to be called for DS4 as well. I've fixed that in another patchset,
which you'll probably need to rebase on top of.

>  
> @@ -312,6 +407,11 @@ static void agent_auth_cb(DBusError *derr, void
> *user_data)
>  	DBG("remote %s old_central %s new_central %s",
>  				device_addr, central_addr,
> adapter_addr);
>  
> +	if (closure->type == CABLE_PAIRING_DUALSENSE) {
> +		DBG("Enabling Bluetooth connection on the device");
> +		set_bluetooth_state(closure->fd, closure->type,
> true);
> +	}
> +
>  out:
>  	g_hash_table_steal(pending_auths, closure->sysfs_path);
>  
> @@ -432,7 +532,8 @@ static void device_added(struct udev_device
> *udevice)
>  
>  	cp = get_pairing_type_for_device(udevice, &bus,
> &sysfs_path);
>  	if (!cp || (cp->type != CABLE_PAIRING_SIXAXIS &&
> -				cp->type != CABLE_PAIRING_DS4)) {
> +				cp->type != CABLE_PAIRING_DS4 &&
> +				cp->type !=
> CABLE_PAIRING_DUALSENSE)) {
>  		g_free(sysfs_path);
>  		return;
>  	}





[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux