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

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

 



Hi Egor,

On Tue, Jun 3, 2025 at 6:05 AM Egor Vorontsov <sdoregor@xxxxxxxx> 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.
>
> 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).
> ---
>  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. */

Not quite following, what key are you talking about? I thought the
link keys are still generated over Bluetooth, or are you talking about
passkeys 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;
> +
> +       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)
>                 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);
> -
>                 server_set_cable_pairing(adapter_bdaddr, true);
>         }
>
> @@ -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;
>         }
> --
> 2.49.0
>
>


-- 
Luiz Augusto von Dentz





[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