Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package xone for openSUSE:Factory checked in 
at 2026-02-01 22:04:01
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/xone (Old)
 and      /work/SRC/openSUSE:Factory/.xone.new.1995 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "xone"

Sun Feb  1 22:04:01 2026 rev:2 rq:1330202 version:0.5.4

Changes:
--------
--- /work/SRC/openSUSE:Factory/xone/xone.changes        2025-11-18 
15:41:05.218606843 +0100
+++ /work/SRC/openSUSE:Factory/.xone.new.1995/xone.changes      2026-02-01 
22:04:46.366951150 +0100
@@ -1,0 +2,27 @@
+Sat Jan 31 16:42:35 UTC 2026 - Tobias Görgens <[email protected]>
+
+- Update to release 0.5.4
+  * Work around another sleeping issue
+- Update to release 0.5.3
+  * Work around sleeping issues
+
+-------------------------------------------------------------------
+Sun Jan 25 04:42:42 UTC 2026 - pallas wept <[email protected]>
+
+- Update to release 0.5.2
+  * Add fw override module parameter
+- Update to release 0.5.1
+  * Fix pairing through sysfs
+- Update to release 0.5.0
+  * This version breaks compatibility with kernels older than 6.5.0 
+    to lessen the maintainership burden.
+  * Increase the dongle pairing timout
+  * Support firmwares for all the defined dongles
+  * Merge mainline changes from medusalix
+- Update to release 0.4.12
+  * Fix leftover autosuspend handling
+  * Reduce the sleep before registering a GIP client
+  * Cleanup a warning
+  * Improve module unloading for testing
+
+-------------------------------------------------------------------

Old:
----
  v0.4.11.tar.gz

New:
----
  v0.5.4.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ xone.spec ++++++
--- /var/tmp/diff_new_pack.Z9r0B1/_old  2026-02-01 22:04:47.058980524 +0100
+++ /var/tmp/diff_new_pack.Z9r0B1/_new  2026-02-01 22:04:47.062980694 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package xone
 #
-# Copyright (c) 2025 SUSE LLC
+# Copyright (c) 2026 SUSE LLC and contributors
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -15,8 +15,9 @@
 # Please submit bugfixes or comments via https://bugs.opensuse.org/
 #
 
+
 Name:           xone
-Version:        0.4.11
+Version:        0.5.4
 Release:        0
 Summary:        Driver for Xbox One and Xbox Series X|S controllers
 License:        GPL-2.0-or-later
@@ -27,7 +28,7 @@
 BuildRequires:  %kernel_module_package_buildreqs
 BuildRequires:  systemd-rpm-macros
 BuildRequires:  xz
-Requires:       xone-dongle-firmware
+Requires:       xone-dongle-firmware >= 0+git20251208.d8be599
 Requires:       xone-kmp
 
 %kernel_module_package -n %name -p %_sourcedir/preamble

++++++ v0.4.11.tar.gz -> v0.5.4.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xone-0.4.11/README.md new/xone-0.5.4/README.md
--- old/xone-0.4.11/README.md   2025-11-11 17:49:18.000000000 +0100
+++ new/xone-0.5.4/README.md    2026-01-26 00:47:09.000000000 +0100
@@ -66,7 +66,7 @@
 
 ### Prerequisites
 
-- Linux 5.13+
+- Linux 6.5+
 - Linux headers
 
 ### Automagically
@@ -106,7 +106,7 @@
 - Linux (kernel 5.13+ and headers)
 - DKMS
 - curl (for firmware download)
-- cabextract (for firmware extraction)
+- bsdtar (for firmware extraction)
 - For SecureBoot-enabled systems see [SecureBoot dkms 
guide](https://github.com/dell/dkms#secure-boot)
 
 ### Guide
@@ -133,8 +133,11 @@
 ```
 sudo install/firmware.sh
 ```
+> [!NOTE]
+> The `--skip-disclaimer` flag might be useful for scripting purposes.
 
-**NOTE:** The `--skip-disclaimer` flag might be useful for scripting purposes.
+> [!TIP]
+> The `xone-dongle.fw_override=0x0000` module paramter can be used to load a 
different firmware file than the one selected automatically by the driver. The 
value is the USB PID contained in the fw file eg. `xone_dongle_02fe.bin`
 
 5. Plug in your Xbox devices.
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xone-0.4.11/auth/crypto.c 
new/xone-0.5.4/auth/crypto.c
--- old/xone-0.4.11/auth/crypto.c       2025-11-11 17:49:18.000000000 +0100
+++ new/xone-0.5.4/auth/crypto.c        2026-01-26 00:47:09.000000000 +0100
@@ -38,7 +38,6 @@
 
 int gip_auth_get_transcript(struct shash_desc *desc, void *transcript)
 {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)
        void *state = kzalloc(crypto_shash_descsize(desc->tfm), GFP_KERNEL);
        int err;
 
@@ -55,20 +54,6 @@
 get_transcript_error:
        kfree(state);
        return err;
-#else
-       struct sha256_state state;
-       int err;
-
-       err = crypto_shash_export(desc, &state);
-       if (err)
-               return err;
-
-       err = crypto_shash_final(desc, transcript);
-       if (err)
-               return err;
-
-       return crypto_shash_import(desc, &state);
-#endif
 }
 
 int gip_auth_compute_prf(struct shash_desc *desc, const char *label,
@@ -110,48 +95,20 @@
                         u8 *out, int out_len)
 {
        struct crypto_akcipher *tfm;
-       struct akcipher_request *req;
-       struct scatterlist src, dest;
-       DECLARE_CRYPTO_WAIT(wait);
-       u8 *buf;
        int err;
 
-       buf = kzalloc(out_len, GFP_KERNEL);
-       if (!buf)
-               return -ENOMEM;
-
        tfm = crypto_alloc_akcipher("pkcs1pad(rsa)", 0, 0);
-       if (IS_ERR(tfm)) {
-               err = PTR_ERR(tfm);
-               goto err_free_buf;
-       }
+       if (IS_ERR(tfm))
+               return PTR_ERR(tfm);
 
        err = crypto_akcipher_set_pub_key(tfm, key, key_len);
        if (err)
                goto err_free_tfm;
 
-       req = akcipher_request_alloc(tfm, GFP_KERNEL);
-       if (!req) {
-               err = -ENOMEM;
-               goto err_free_tfm;
-       }
-
-       sg_init_one(&src, in, in_len);
-       sg_init_one(&dest, buf, out_len);
-
-       akcipher_request_set_crypt(req, &src, &dest, in_len, out_len);
-       akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
-                                     crypto_req_done, &wait);
-       err = crypto_wait_req(crypto_akcipher_encrypt(req), &wait);
-       if (!err)
-               memcpy(out, buf, out_len);
-
-       akcipher_request_free(req);
+       err = crypto_akcipher_sync_encrypt(tfm, in, in_len, out, out_len);
 
 err_free_tfm:
        crypto_free_akcipher(tfm);
-err_free_buf:
-       kfree(buf);
 
        return err;
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xone-0.4.11/bus/bus.c new/xone-0.5.4/bus/bus.c
--- old/xone-0.4.11/bus/bus.c   2025-11-11 17:49:18.000000000 +0100
+++ new/xone-0.5.4/bus/bus.c    2026-01-26 00:47:09.000000000 +0100
@@ -26,12 +26,8 @@
        .release = gip_adapter_release,
 };
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0)
-static int gip_client_uevent(struct device *dev, struct kobj_uevent_env *env)
-#else
 static int gip_client_uevent(const struct device *dev,
                             struct kobj_uevent_env *env)
-#endif
 {
        struct gip_client *client = to_gip_client(dev);
        struct gip_classes *classes = client->classes;
@@ -117,24 +113,11 @@
        up(&client->drv_lock);
 }
 
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(5, 13, 0)
-static int gip_bus_remove_compat(struct device *dev)
-{
-       gip_bus_remove(dev);
-
-       return 0;
-}
-#endif
-
 static struct bus_type gip_bus_type = {
        .name = "xone-gip",
        .match = gip_bus_match,
        .probe = gip_bus_probe,
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(5, 13, 0)
-       .remove = gip_bus_remove_compat,
-#else
        .remove = gip_bus_remove,
-#endif
 };
 
 struct gip_adapter *gip_create_adapter(struct device *parent,
@@ -148,12 +131,7 @@
        if (!adap)
                return ERR_PTR(-ENOMEM);
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 17, 0)
        adap->id = ida_alloc(&gip_adapter_ida, GFP_KERNEL);
-#else
-       adap->id = ida_simple_get(&gip_adapter_ida, 0, 0, GFP_KERNEL);
-#endif
-
        if (adap->id < 0) {
                err = adap->id;
                goto err_put_device;
@@ -185,11 +163,7 @@
        destroy_workqueue(adap->clients_wq);
 
 err_remove_ida:
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 17, 0)
        ida_free(&gip_adapter_ida, adap->id);
-#else
-       ida_simple_remove(&gip_adapter_ida, adap->id);
-#endif
 
 err_put_device:
        put_device(&adap->dev);
@@ -226,11 +200,7 @@
                device_unregister(&client->dev);
        }
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 17, 0)
        ida_free(&gip_adapter_ida, adap->id);
-#else
-       ida_simple_remove(&gip_adapter_ida, adap->id);
-#endif
        destroy_workqueue(adap->clients_wq);
 
        dev_dbg(&adap->dev, "%s: unregistered\n", __func__);
@@ -254,7 +224,7 @@
         * The unfortunate workaround, that at least works reliably is to add a
         * delay here. Since this is for human input device, one second is fine.
         */
-       msleep(1000);
+       msleep(700);
 
        client->dev.parent = &client->adapter->dev;
        client->dev.type = &gip_client_type;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xone-0.4.11/bus/protocol.c 
new/xone-0.5.4/bus/protocol.c
--- old/xone-0.4.11/bus/protocol.c      2025-11-11 17:49:18.000000000 +0100
+++ new/xone-0.5.4/bus/protocol.c       2026-01-26 00:47:09.000000000 +0100
@@ -70,6 +70,26 @@
        GIP_AUD_VOLUME_MIC_MUTED = 0x05,
 };
 
+static uint gip_audio_sample_rate[] = {
+       0,
+       8000,
+       8000,
+       12000,
+       12000,
+       16000,
+       16000,
+       20000,
+       20000,
+       24000,
+       24000,
+       32000,
+       32000,
+       40000,
+       40000,
+       48000,
+       48000,
+};
+
 enum gip_extended_command {
        GIP_EXT_GET_CAPABILITIES = 0x00,
        GIP_EXT_GET_TELEMETRY = 0x01,
@@ -182,7 +202,7 @@
 } __packed;
 
 struct gip_pkt_audio_samples {
-       __le16 length_out;
+       __le16 flow_rate;
        u8 samples[];
 } __packed;
 
@@ -482,7 +502,7 @@
 }
 
 static int gip_set_audio_format_chat(struct gip_client *client,
-                                    enum gip_audio_format_chat in_out)
+                                    enum gip_audio_format in_out)
 {
        struct gip_header hdr = {};
        struct gip_pkt_audio_format_chat pkt = {};
@@ -525,7 +545,7 @@
        /* special handling for the chat headset */
        if (chat)
                err = gip_set_audio_format_chat(client,
-                                               GIP_AUD_FORMAT_CHAT_24KHZ);
+                                               GIP_AUD_FORMAT_12KHZ_STEREO);
        else
                err = gip_set_audio_format(client, in, out);
 
@@ -624,10 +644,10 @@
                dest = buf + i * cfg->packet_size;
 
                /* sequence number is always greater than zero */
-               do {
-                       hdr.sequence = client->adapter->audio_sequence++;
-               } while (!hdr.sequence);
+               if (!++client->adapter->audio_sequence)
+                       ++client->adapter->audio_sequence;
 
+               hdr.sequence = client->adapter->audio_sequence;
                gip_encode_header(&hdr, dest);
                memcpy(dest + hdr_len, src, cfg->fragment_size);
        }
@@ -785,25 +805,16 @@
 {
        struct gip_header hdr = {};
 
-       switch (cfg->format) {
-       case GIP_AUD_FORMAT_16KHZ_MONO:
-               cfg->channels = 1;
-               cfg->sample_rate = 16000;
-               break;
-       case GIP_AUD_FORMAT_24KHZ_MONO:
-               cfg->channels = 1;
-               cfg->sample_rate = 24000;
-               break;
-       case GIP_AUD_FORMAT_48KHZ_STEREO:
-               cfg->channels = 2;
-               cfg->sample_rate = 48000;
-               break;
-       default:
-               gip_err(client, "%s: unknown format: 0x%02x\n",
-                       __func__, cfg->format);
+       if (cfg->format <= 0 || cfg->format > GIP_AUD_FORMAT_48KHZ_STEREO) {
+               gip_err(client, "%s: unknown format: 0x%02x\n", __func__,
+                       cfg->format);
                return -ENOTSUPP;
        }
 
+       /* even-indexed formats are stereo, uneven are mono */
+       cfg->channels = 2 - (cfg->format & 1);
+       cfg->sample_rate = gip_audio_sample_rate[cfg->format];
+
        cfg->buffer_size = cfg->sample_rate * cfg->channels *
                           sizeof(s16) * GIP_AUDIO_INTERVAL / MSEC_PER_SEC;
        cfg->fragment_size = cfg->buffer_size /
@@ -813,6 +824,9 @@
        hdr.packet_length = cfg->fragment_size;
        cfg->packet_size = gip_get_header_length(&hdr) + cfg->fragment_size;
 
+       /* set initial flow rate value */
+       cfg->flow_rate = cfg->buffer_size;
+
        gip_dbg(client, "%s: rate=%d/%d, buffer=%d\n", __func__,
                cfg->sample_rate, cfg->channels, cfg->buffer_size);
 
@@ -842,7 +856,7 @@
        if (len < off + total)
                return ERR_PTR(-EINVAL);
 
-       elem = kzalloc(sizeof(*elem) + total, GFP_ATOMIC);
+       elem = kzalloc(struct_size(elem, data, total), GFP_ATOMIC);
        if (!elem)
                return ERR_PTR(-ENOMEM);
 
@@ -983,8 +997,7 @@
        if (!count)
                return -EINVAL;
 
-       classes = kzalloc(sizeof(*classes) + sizeof(char *) * count,
-                         GFP_ATOMIC);
+       classes = kzalloc(struct_size(classes, strings, count), GFP_ATOMIC);
        if (!classes)
                return -ENOMEM;
 
@@ -1342,7 +1355,7 @@
                return -EINVAL;
 
        /* chat headsets apparently default to 24 kHz */
-       if (pkt->in_out != GIP_AUD_FORMAT_CHAT_24KHZ ||
+       if (pkt->in_out != GIP_AUD_FORMAT_12KHZ_STEREO ||
            in->buffer_size || out->buffer_size)
                return -EPROTO;
 
@@ -1508,6 +1521,7 @@
                                        void *data, u32 len)
 {
        struct gip_pkt_audio_samples *pkt = data;
+       struct gip_audio_config *out = &client->audio_config_out;
        int err = 0;
 
        if (len < sizeof(*pkt))
@@ -1516,6 +1530,10 @@
        if (down_trylock(&client->drv_lock))
                return -EBUSY;
 
+       out->flow_rate = le16_to_cpu(pkt->flow_rate);
+       if (out->flow_rate != out->buffer_size)
+               gip_dbg(client, "%s: Unusual flow rate control -> %u", 
__func__, out->flow_rate);
+
        if (client->drv && client->drv->ops.audio_samples)
                err = client->drv->ops.audio_samples(client, pkt->samples,
                                                     len - sizeof(*pkt));
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xone-0.4.11/bus/protocol.h 
new/xone-0.5.4/bus/protocol.h
--- old/xone-0.4.11/bus/protocol.h      2025-11-11 17:49:18.000000000 +0100
+++ new/xone-0.5.4/bus/protocol.h       2026-01-26 00:47:09.000000000 +0100
@@ -37,14 +37,23 @@
 };
 
 enum gip_audio_format {
-       GIP_AUD_FORMAT_16KHZ_MONO = 0x05,
-       GIP_AUD_FORMAT_24KHZ_MONO = 0x09,
-       GIP_AUD_FORMAT_48KHZ_STEREO = 0x10,
-};
-
-enum gip_audio_format_chat {
-       GIP_AUD_FORMAT_CHAT_24KHZ = 0x04,
-       GIP_AUD_FORMAT_CHAT_16KHZ = 0x05,
+       GIP_AUD_FORMAT_NONE,
+       GIP_AUD_FORMAT_8KHZ_MONO,
+       GIP_AUD_FORMAT_8KHZ_STEREO,
+       GIP_AUD_FORMAT_12KHZ_MONO,
+       GIP_AUD_FORMAT_12KHZ_STEREO,
+       GIP_AUD_FORMAT_16KHZ_MONO,
+       GIP_AUD_FORMAT_16KHZ_STEREO,
+       GIP_AUD_FORMAT_20KHZ_MONO,
+       GIP_AUD_FORMAT_20KHZ_STEREO,
+       GIP_AUD_FORMAT_24KHZ_MONO,
+       GIP_AUD_FORMAT_24KHZ_STEREO,
+       GIP_AUD_FORMAT_32KHZ_MONO,
+       GIP_AUD_FORMAT_32KHZ_STEREO,
+       GIP_AUD_FORMAT_40KHZ_MONO,
+       GIP_AUD_FORMAT_40KHZ_STEREO,
+       GIP_AUD_FORMAT_48KHZ_MONO,
+       GIP_AUD_FORMAT_48KHZ_STEREO,
 };
 
 enum gip_led_mode {
@@ -96,6 +105,9 @@
        int buffer_size;
        int fragment_size;
        int packet_size;
+
+       /* only used for rendered audio (out) */
+       u16 flow_rate;
 };
 
 struct gip_classes {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xone-0.4.11/driver/common.c 
new/xone-0.5.4/driver/common.c
--- old/xone-0.4.11/driver/common.c     2025-11-11 17:49:18.000000000 +0100
+++ new/xone-0.5.4/driver/common.c      2026-01-26 00:47:09.000000000 +0100
@@ -122,7 +122,7 @@
        struct led_classdev *cdev = dev_get_drvdata(dev);
        struct gip_led *led = container_of(cdev, typeof(*led), dev);
 
-       return sprintf(buf, "%u\n", led->mode);
+       return sysfs_emit(buf, "%u\n", led->mode);
 }
 
 static ssize_t gip_led_mode_store(struct device *dev,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xone-0.4.11/driver/gamepad.c 
new/xone-0.5.4/driver/gamepad.c
--- old/xone-0.4.11/driver/gamepad.c    2025-11-11 17:49:18.000000000 +0100
+++ new/xone-0.5.4/driver/gamepad.c     2026-01-26 00:47:09.000000000 +0100
@@ -124,6 +124,16 @@
        PADDLE_ELITE2_511, // Different packet entirely.
 } PaddleCapability;
 
+struct gip_gamepad_rumble {
+       /* serializes access to rumble packet */
+       spinlock_t lock;
+       unsigned long last;
+       struct timer_list timer;
+       struct gip_gamepad_pkt_rumble pkt;
+
+       struct gip_gamepad *parent;
+};
+
 struct gip_gamepad {
        struct gip_client *client;
        struct gip_battery battery;
@@ -135,27 +145,20 @@
        bool supports_dli;
        PaddleCapability paddle_support;
 
-       struct gip_gamepad_rumble {
-               /* serializes access to rumble packet */
-               spinlock_t lock;
-               unsigned long last;
-               struct timer_list timer;
-               struct gip_gamepad_pkt_rumble pkt;
-       } rumble;
+       struct gip_gamepad_rumble rumble;
 };
 
 static void gip_gamepad_send_rumble(struct timer_list *timer)
 {
        // from_timer() has been renamed to timer_container_of() in linux 6.16
        struct gip_gamepad_rumble *rumble =
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,16,0)
-               timer_container_of(rumble, timer, timer);
-#else
+#if LINUX_VERSION_CODE < KERNEL_VERSION(6,16,0)
                from_timer(rumble, timer, timer);
+#else
+               timer_container_of(rumble, timer, timer);
 #endif
 
-       struct gip_gamepad *gamepad = container_of(rumble, typeof(*gamepad),
-                                                  rumble);
+       struct gip_gamepad *gamepad = rumble->parent;
        unsigned long flags;
 
        spin_lock_irqsave(&rumble->lock, flags);
@@ -204,6 +207,7 @@
                             GIP_GP_MOTOR_RT | GIP_GP_MOTOR_LT;
        rumble->pkt.duration = 0xff;
        rumble->pkt.repeat = 0xeb;
+       rumble->parent = gamepad;
        gip_gamepad_send_rumble(&rumble->timer);
 
        input_set_capability(dev, EV_FF, FF_RUMBLE);
@@ -309,10 +313,10 @@
        return 0;
 
 err_delete_timer:
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,15,0)
-       timer_delete_sync(&gamepad->rumble.timer);
-#else
+#if LINUX_VERSION_CODE < KERNEL_VERSION(6,15,0)
        del_timer_sync(&gamepad->rumble.timer);
+#else
+       timer_delete_sync(&gamepad->rumble.timer);
 #endif
        return err;
 }
@@ -529,10 +533,10 @@
 {
        struct gip_gamepad *gamepad = dev_get_drvdata(&client->dev);
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,15,0)
-       timer_delete_sync(&gamepad->rumble.timer);
-#else
+#if LINUX_VERSION_CODE < KERNEL_VERSION(6,15,0)
        del_timer_sync(&gamepad->rumble.timer);
+#else
+       timer_delete_sync(&gamepad->rumble.timer);
 #endif
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xone-0.4.11/driver/headset.c 
new/xone-0.5.4/driver/headset.c
--- old/xone-0.4.11/driver/headset.c    2025-11-11 17:49:18.000000000 +0100
+++ new/xone-0.5.4/driver/headset.c     2026-01-26 00:47:09.000000000 +0100
@@ -5,7 +5,6 @@
 
 #include <linux/module.h>
 #include <linux/hrtimer.h>
-#include <linux/vmalloc.h>
 #include <linux/version.h>
 #include <sound/core.h>
 #include <sound/initval.h>
@@ -68,8 +67,6 @@
                snd_pcm_uframes_t pointer;
                snd_pcm_uframes_t period;
        } playback, capture;
-
-       struct snd_card *card;
 };
 
 static int gip_headset_pcm_open(struct snd_pcm_substream *sub)
@@ -89,7 +86,9 @@
        hw.channels_max = cfg->channels;
        hw.buffer_bytes_max = cfg->buffer_size * GIP_HS_NUM_BUFFERS;
        hw.period_bytes_min = cfg->buffer_size;
-       hw.period_bytes_max = cfg->buffer_size;
+       hw.period_bytes_max = cfg->buffer_size * 2;
+       hw.periods_min = 1;
+       hw.periods_max = 8;
 
        sub->runtime->hw = hw;
 
@@ -101,39 +100,6 @@
        return 0;
 }
 
-static int gip_headset_pcm_hw_params(struct snd_pcm_substream *sub,
-                                    struct snd_pcm_hw_params *params)
-{
-       struct snd_pcm_runtime *runtime = sub->runtime;
-       size_t size = params_buffer_bytes(params);
-
-       if (runtime->dma_area) {
-               if (runtime->dma_bytes >= size)
-                       return 0; /* Already large enough */
-               vfree(runtime->dma_area);
-       }
-       runtime->dma_area = vzalloc(size);
-       if (!runtime->dma_area)
-               return -ENOMEM;
-       runtime->dma_bytes = size;
-       return 1;
-}
-
-static int gip_headset_pcm_hw_free(struct snd_pcm_substream *sub)
-{
-       struct snd_pcm_runtime *runtime = sub->runtime;
-
-       vfree(runtime->dma_area);
-       runtime->dma_area = NULL;
-       return 0;
-}
-
-static struct page *gip_headset_pcm_get_page(struct snd_pcm_substream *sub,
-                                            unsigned long offset)
-{
-       return vmalloc_to_page(sub->runtime->dma_area + offset);
-}
-
 static int gip_headset_pcm_prepare(struct snd_pcm_substream *sub)
 {
        return 0;
@@ -186,13 +152,9 @@
 static const struct snd_pcm_ops gip_headset_pcm_ops = {
        .open = gip_headset_pcm_open,
        .close = gip_headset_pcm_close,
-       .ioctl = snd_pcm_lib_ioctl,
-       .hw_params = gip_headset_pcm_hw_params,
-       .hw_free = gip_headset_pcm_hw_free,
        .prepare = gip_headset_pcm_prepare,
        .trigger = gip_headset_pcm_trigger,
        .pointer = gip_headset_pcm_pointer,
-       .page = gip_headset_pcm_get_page,
 };
 
 static bool gip_headset_advance_pointer(struct gip_headset_stream *stream,
@@ -334,8 +296,8 @@
        struct snd_pcm *pcm;
        int err;
 
-       err = snd_card_new(&headset->client->dev, SNDRV_DEFAULT_IDX1,
-                          SNDRV_DEFAULT_STR1, THIS_MODULE, 0, &card);
+       err = snd_devm_card_new(&headset->client->dev, SNDRV_DEFAULT_IDX1,
+                               SNDRV_DEFAULT_STR1, THIS_MODULE, 0, &card);
        if (err)
                return err;
 
@@ -344,8 +306,6 @@
        snprintf(card->longname, sizeof(card->longname), "%s at %s",
                 GIP_HS_NAME, dev_name(&headset->client->dev));
 
-       headset->card = card;
-
        err = snd_pcm_new(card, GIP_HS_NAME, 0, 1, 1, &pcm);
        if (err)
                return err;
@@ -355,6 +315,7 @@
 
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &gip_headset_pcm_ops);
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &gip_headset_pcm_ops);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0);
 
        return snd_card_register(card);
 }
@@ -440,7 +401,7 @@
                return;
 
        dev_dbg(&client->dev, "%s: init pcm device.\n", __func__);
-       err = gip_headset_init_pcm(headset);
+       err = snd_card_free_on_error(&client->dev, 
gip_headset_init_pcm(headset));
        if (err) {
                dev_err(&client->dev, "%s: init PCM failed: %d\n",
                        __func__, err);
@@ -466,6 +427,14 @@
                return;
        }
 
+       dev_dbg(&client->dev, "%s: init audio in.\n", __func__);
+       err = gip_init_audio_in(client);
+       if (err) {
+               dev_err(&client->dev, "%s: init audio in failed: %d\n",
+                       __func__, err);
+               return;
+       }
+
        /* start audio timer */
        hrtimer_start(&headset->timer, 0, HRTIMER_MODE_REL);
 }
@@ -574,28 +543,22 @@
        INIT_DELAYED_WORK(&headset->work_power_on, gip_headset_power_on);
        INIT_WORK(&headset->work_register, gip_headset_register);
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,15,0)
-       hrtimer_setup(&headset->timer, gip_headset_send_samples,
-                     CLOCK_MONOTONIC, HRTIMER_MODE_REL);
-       hrtimer_setup(&headset->start_audio_timer, gip_headset_start_audio,
-                     CLOCK_MONOTONIC, HRTIMER_MODE_REL);
-#else
+#if LINUX_VERSION_CODE < KERNEL_VERSION(6,15,0)
        hrtimer_init(&headset->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
        headset->timer.function = gip_headset_send_samples;
        hrtimer_init(&headset->start_audio_timer, CLOCK_MONOTONIC, 
HRTIMER_MODE_REL);
        headset->start_audio_timer.function = gip_headset_start_audio;
+#else
+       hrtimer_setup(&headset->timer, gip_headset_send_samples,
+                     CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+       hrtimer_setup(&headset->start_audio_timer, gip_headset_start_audio,
+                     CLOCK_MONOTONIC, HRTIMER_MODE_REL);
 #endif
 
        err = gip_enable_audio(client);
        if (err)
                return err;
 
-       err = gip_init_audio_in(client);
-       if (err) {
-               gip_disable_audio(client);
-               return err;
-       }
-
        dev_set_drvdata(&client->dev, headset);
 
        /* start audio configuration */
@@ -614,11 +577,6 @@
        hrtimer_cancel(&headset->timer);
        hrtimer_cancel(&headset->start_audio_timer);
        gip_disable_audio(client);
-
-       if (headset->card) {
-               snd_card_disconnect(headset->card);
-               snd_card_free_when_closed(headset->card);
-       }
 }
 
 static struct gip_driver gip_headset_driver = {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xone-0.4.11/install/firmware.sh 
new/xone-0.5.4/install/firmware.sh
--- old/xone-0.4.11/install/firmware.sh 2025-11-11 17:49:18.000000000 +0100
+++ new/xone-0.5.4/install/firmware.sh  2026-01-26 00:47:09.000000000 +0100
@@ -12,8 +12,8 @@
     exit 1
 fi
 
-if ! [ -x "$(command -v cabextract)" ]; then
-    echo 'This script requires cabextract!' >&2
+if ! [ -x "$(command -v bsdtar)" ]; then
+    echo 'This script requires bsdtar!' >&2
     exit 1
 fi
 
@@ -25,34 +25,47 @@
     read -r _
 fi
 
-echo -e "dongle firmware installation...\n"
+echo -e "Dongle firmware installation\n"
 
-driver_url='https://catalog.s.download.windowsupdate.com/c/msdownload/update/driver/drvs/2017/07/1cd6a87c-623f-4407-a52d-c31be49e925c_e19f60808bdcbfbd3c3df6be3e71ffc52e43261e.cab'
-firmware_hash='48084d9fa53b9bb04358f3bb127b7495dc8f7bb0b3ca1437bd24ef2b6eabdf66'
-dest_file="/lib/firmware/xow_dongle.bin"
-
-if [[ ! -f $dest_file ]]; then
-    curl -L -o driver.cab "$driver_url"
-    cabextract -F FW_ACC_00U.bin driver.cab
-    echo "$firmware_hash" FW_ACC_00U.bin | sha256sum -c
-    mv FW_ACC_00U.bin $dest_file
+urls=(
+    
'https://catalog.s.download.windowsupdate.com/d/msdownload/update/driver/drvs/2017/03/2ea9591b-f751-442c-80ce-8f4692cdc67b_6b555a3a288153cf04aec6e03cba360afe2fce34.cab'
+    
'https://catalog.s.download.windowsupdate.com/c/msdownload/update/driver/drvs/2017/07/1cd6a87c-623f-4407-a52d-c31be49e925c_e19f60808bdcbfbd3c3df6be3e71ffc52e43261e.cab'
+    
'https://catalog.s.download.windowsupdate.com/c/msdownload/update/driver/drvs/2017/06/1dbd7cb4-53bc-4857-a5b0-5955c8acaf71_9081931e7d664429a93ffda0db41b7545b7ac257.cab'
+    
'https://catalog.s.download.windowsupdate.com/d/msdownload/update/driver/drvs/2017/08/aeff215c-3bc4-4d36-a3ea-e14bfa8fa9d2_e58550c4f74a27e51e5cb6868b10ff633fa77164.cab'
+)
+hashes=(
+    '080ce4091e53a4ef3e5fe29939f51fd91f46d6a88be6d67eb6e99a5723b3a223'
+    '48084d9fa53b9bb04358f3bb127b7495dc8f7bb0b3ca1437bd24ef2b6eabdf66'
+    '0023a7bae02974834500c665a281e25b1ba52c9226c84989f9084fa5ce591d9b'
+    'e2710daf81e7b36d35985348f68a81d18bc537a2b0c508ffdfde6ac3eae1bad7'
+)
+filenames=('FW_ACC_00U.bin' 'FW_ACC_00U.bin' 'FW_ACC_CL.bin' 'FW_ACC_BR.bin')
+pids=('02e6' '02fe' '02f9' '091e')
+
+function download_firmware() {
+    local firmware_name="xone_dongle_${1}.bin"
+    local dest_file="/lib/firmware/$firmware_name"
+
+    if [[ -f $dest_file ]]; then
+        echo -e "$firmware_name found. Skipping download"
+        return 0
+    fi
+
+    echo -n "Downloading $firmware_name..."
+    curl -s -L -o driver.cab "$2"
+    bsdtar -xf driver.cab "$3" > /dev/null 2>&1
+
+    echo -n " Checking sha256..."
+    echo "$4" "$3" | sha256sum -c --quiet
+    mv "$3" $dest_file
     rm driver.cab
-else
-    echo -e "xow_dongle.bin found. Skipping download\n"
-fi
 
-driver_url='https://catalog.s.download.windowsupdate.com/d/msdownload/update/driver/drvs/2015/12/20810869_8ce2975a7fbaa06bcfb0d8762a6275a1cf7c1dd3.cab'
-firmware_hash='080ce4091e53a4ef3e5fe29939f51fd91f46d6a88be6d67eb6e99a5723b3a223'
-dest_file="/lib/firmware/xow_dongle_045e_02e6.bin"
-
-if [[ ! -f $dest_file ]]; then
-    curl -L -o driver.cab "$driver_url"
-    cabextract -F FW_ACC_00U.bin driver.cab
-    echo "$firmware_hash" FW_ACC_00U.bin | sha256sum -c
-    mv FW_ACC_00U.bin $dest_file
-    rm driver.cab
-else
-    echo -e "xow_dongle_045e_02e6.bin found. Skipping download\n"
-fi
+    echo -e " Done!"
+}
+
+for ((i = 0 ; i < "${#urls[@]}" ; i++)); do
+    download_firmware "${pids[$i]}" "${urls[$i]}" "${filenames[$i]}" 
"${hashes[$i]}"
+done
+
+echo -e "\nDongle firmwares installed!"
 
-echo -e "dongle firmware installed\n"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xone-0.4.11/install/steam-deck-install.sh 
new/xone-0.5.4/install/steam-deck-install.sh
--- old/xone-0.4.11/install/steam-deck-install.sh       2025-11-11 
17:49:18.000000000 +0100
+++ new/xone-0.5.4/install/steam-deck-install.sh        2026-01-26 
00:47:09.000000000 +0100
@@ -67,8 +67,8 @@
 sudo -u deck makepkg -Ccf -p PKGBUILD_XONE
 sudo -u deck makepkg -Ccf -p PKGBUILD_FIRMWARE
 
-pacman -U --noconfirm xone-dkms-*.tar.zst
 pacman -U --noconfirm --asdeps xone-dongle-firmware-*.tar.zst
+pacman -U --noconfirm xone-dkms-*.tar.zst
 
 # Remove unneeded build dependencies
 pacman -Rcns --noconfirm w3m html-xml-utils
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xone-0.4.11/modules_load.sh 
new/xone-0.5.4/modules_load.sh
--- old/xone-0.4.11/modules_load.sh     2025-11-11 17:49:18.000000000 +0100
+++ new/xone-0.5.4/modules_load.sh      2026-01-26 00:47:09.000000000 +0100
@@ -6,8 +6,7 @@
 
 mapfile -t MODULES_TMP < modules.order
 MODULES=("${MODULES_TMP[@]}")
-
-LOADED_MODULES=$(lsmod)
+LOADED_MODULES=$(lsmod | cut -d " " -f 1)
 
 if [[ $1 == "unload" ]]; then
     OPERATION="rmmod -f"
@@ -32,6 +31,9 @@
 for module in "${MODULES[@]}"; do
     module="${module%.o}$SUFFIX"
 
+    # remove path and leave only base name
+    [[ $1 == "unload" ]] && module=${module##*/}
+
     # skip rmmod if module is not loaded
     [[ $1 == "unload" && ! "$LOADED_MODULES" =~ "$module" ]] && continue
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xone-0.4.11/transport/dongle.c 
new/xone-0.5.4/transport/dongle.c
--- old/xone-0.4.11/transport/dongle.c  2025-11-11 17:49:18.000000000 +0100
+++ new/xone-0.5.4/transport/dongle.c   2026-01-26 00:47:09.000000000 +0100
@@ -18,6 +18,10 @@
 #include "mt76.h"
 #include "../bus/bus.h"
 
+ushort fw_override_pid = 0;
+MODULE_PARM_DESC(fw_override, "Use firmware for the provided product ID 
instead of the one detected automatically");
+module_param_named(fw_override, fw_override_pid, ushort, 0600);
+
 #define XONE_DONGLE_NUM_IN_URBS 12
 #define XONE_DONGLE_NUM_OUT_URBS 12
 
@@ -26,16 +30,12 @@
 
 #define XONE_DONGLE_MAX_CLIENTS 16
 
-#define XONE_DONGLE_PAIRING_TIMEOUT msecs_to_jiffies(30000)
+#define XONE_DONGLE_PAIRING_TIMEOUT msecs_to_jiffies(60000)
 #define XONE_DONGLE_PWR_OFF_TIMEOUT msecs_to_jiffies(5000)
 #define XONE_DONGLE_FW_REQ_TIMEOUT_MS 3000
 #define XONE_DONGLE_FW_REQ_RETRIES 11 // 30 seconds
 #define XONE_DONGLE_FW_LOAD_RETRIES 3
 
-#define XONE_DONGLE_OFFICIAL_VENDOR 0x045e
-#define XONE_DONGLE_OFFICIAL_PRODUCT 0x02fe
-#define XONE_DONGLE_KNOCKOFF_PRODUCT1 0x02e6
-
 enum xone_dongle_queue {
        XONE_DONGLE_QUEUE_DATA = 0x00,
        XONE_DONGLE_QUEUE_AUDIO = 0x02,
@@ -62,14 +62,16 @@
        struct gip_adapter *adapter;
 };
 
+enum xone_dongle_event_type {
+       XONE_DONGLE_EVT_ADD_CLIENT,
+       XONE_DONGLE_EVT_REMOVE_CLIENT,
+       XONE_DONGLE_EVT_PAIR_CLIENT,
+       XONE_DONGLE_EVT_ENABLE_PAIRING,
+       XONE_DONGLE_EVT_ENABLE_ENCRYPTION,
+};
+
 struct xone_dongle_event {
-       enum xone_dongle_event_type {
-               XONE_DONGLE_EVT_ADD_CLIENT,
-               XONE_DONGLE_EVT_REMOVE_CLIENT,
-               XONE_DONGLE_EVT_PAIR_CLIENT,
-               XONE_DONGLE_EVT_ENABLE_PAIRING,
-               XONE_DONGLE_EVT_ENABLE_ENCRYPTION,
-       } type;
+       enum xone_dongle_event_type type;
 
        struct xone_dongle *dongle;
        u8 address[ETH_ALEN];
@@ -230,7 +232,6 @@
 
 static int xone_dongle_toggle_pairing(struct xone_dongle *dongle, bool enable)
 {
-       struct usb_interface *intf = to_usb_interface(dongle->mt.dev);
        enum xone_mt76_led_mode led;
        int err = 0;
 
@@ -255,11 +256,6 @@
        if (err)
                goto err_unlock;
 
-       if (enable)
-               usb_autopm_get_interface(intf);
-       else
-               usb_autopm_put_interface(intf);
-
        dev_dbg(dongle->mt.dev, "%s: enabled=%d\n", __func__, enable);
        dongle->pairing = enable;
 
@@ -296,7 +292,7 @@
        struct usb_interface *intf = to_usb_interface(dev);
        struct xone_dongle *dongle = usb_get_intfdata(intf);
 
-       return sprintf(buf, "%d\n", dongle->pairing);
+       return sysfs_emit(buf, "%d\n", dongle->pairing);
 }
 
 static ssize_t xone_dongle_pairing_store(struct device *dev,
@@ -312,16 +308,10 @@
        if (err)
                return err;
 
-       err = pm_runtime_resume_and_get(dev);
-       if (err)
-               return err;
-
        err = xone_dongle_toggle_pairing(dongle, enable);
        if (err)
                return err;
 
-       pm_runtime_put(dev);
-
        return count;
 }
 
@@ -778,8 +768,8 @@
        if (err) {
                dev_err(dongle->mt.dev, "%s: process failed: %d\n",
                        __func__, err);
-               print_hex_dump_debug("xone-dongle packet: ", DUMP_PREFIX_NONE,
-                                    16, 1, data, len, false);
+               print_hex_dump_bytes("xone-dongle packet: ", DUMP_PREFIX_NONE,
+                                    data, len);
        }
 
        dev_kfree_skb(skb);
@@ -918,20 +908,16 @@
 
        struct xone_mt76 *mt = &dongle->mt;
        const struct firmware *fw;
-       char fwname[25];
+       char fwname[21];
        int err;
+       u16 fw_product = dongle->product;
 
-       switch (dongle->product) {
-       case XONE_DONGLE_KNOCKOFF_PRODUCT1:
-               snprintf(fwname, 25, "xow_dongle_%04x_%04x.bin", dongle->vendor,
-                        dongle->product);
-               break;
-
-       case XONE_DONGLE_OFFICIAL_PRODUCT:
-       default:
-               snprintf(fwname, 15, "xow_dongle.bin");
+       if (fw_override_pid) {
+               dev_info(mt->dev, "Firmware overriden with PID=0x%04x", 
fw_override_pid);
+               fw_product = fw_override_pid;
        }
 
+       sprintf(fwname, "xone_dongle_%04x.bin", fw_product);
        err = xone_dongle_fw_requester(&fw, dongle, fwname);
        if (dongle->fw_state == XONE_DONGLE_FW_STATE_STOP_LOADING) {
                dongle->fw_state = XONE_DONGLE_FW_STATE_ERROR;
@@ -947,7 +933,12 @@
        dev_dbg(mt->dev, "%s: firmware requested successfully\n", __func__);
 
 
-       err = xone_mt76_load_firmware(mt, fw);
+       for (int i = 0; i < 5; ++i) {
+               err = xone_mt76_load_firmware(mt, fw);
+               if (!err)
+                       break;
+               ssleep(1);
+       }
        release_firmware(fw);
        if (err) {
                dongle->fw_state = XONE_DONGLE_FW_STATE_ERROR;
@@ -1177,6 +1168,8 @@
                return 0;
        }
 
+       msleep(1500);
+
        while ((urb = usb_get_from_anchor(&dongle->urbs_in_idle))) {
                usb_anchor_urb(urb, &dongle->urbs_in_busy);
                usb_free_urb(urb);
@@ -1185,6 +1178,10 @@
                if (err)
                        return err;
        }
+
+       msleep(1000);
+       return xone_mt76_resume_radio(&dongle->mt);
+       msleep(500);
        return xone_mt76_resume_radio(&dongle->mt);
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xone-0.4.11/transport/mt76.c 
new/xone-0.5.4/transport/mt76.c
--- old/xone-0.4.11/transport/mt76.c    2025-11-11 17:49:18.000000000 +0100
+++ new/xone-0.5.4/transport/mt76.c     2026-01-26 00:47:09.000000000 +0100
@@ -640,7 +640,7 @@
                err = xone_mt76_switch_channel(mt, chan);
                if (err)
                        return err;
-               
+
                /* pick the highest power channel seen first */
                /* the last channel might not be the best one */
                if (chan->power > pow) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xone-0.4.11/transport/wired.c 
new/xone-0.5.4/transport/wired.c
--- old/xone-0.4.11/transport/wired.c   2025-11-11 17:49:18.000000000 +0100
+++ new/xone-0.5.4/transport/wired.c    2026-01-26 00:47:09.000000000 +0100
@@ -71,10 +71,8 @@
                                 urb->actual_length);
        if (err) {
                dev_err(dev, "%s: process failed: %d\n", __func__, err);
-               print_hex_dump_debug("xone-wired packet: ",
-                                    DUMP_PREFIX_NONE, 16, 1,
-                                    urb->transfer_buffer, urb->actual_length,
-                                    false);
+               print_hex_dump_bytes("xone-wired packet: ", DUMP_PREFIX_NONE,
+                                    urb->transfer_buffer, urb->actual_length);
        }
 
 resubmit:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xone-0.4.11/uninstall.sh new/xone-0.5.4/uninstall.sh
--- old/xone-0.4.11/uninstall.sh        2025-11-11 17:49:18.000000000 +0100
+++ new/xone-0.5.4/uninstall.sh 2026-01-26 00:47:09.000000000 +0100
@@ -32,5 +32,6 @@
 echo -e "All xone versions removed\n"
 
 [[ ${1:-} == "--no-firmware" ]] && exit 0
-rm -rf /lib/firmware/xow_dongle*
+rm -rf /lib/firmware/xow_dongle* || true
+rm -rf /lib/firmware/xone_dongle* || true
 echo -e "All dongle firmwares removed\n"

Reply via email to