|
| 1 | +# usb_oc-dkms |
| 2 | + |
| 3 | +Kernel module for overclocking USB devices (controllers, mice, keyboards, etc.). Equivalent of the `hidusbf` driver on Windows. |
| 4 | + |
| 5 | +This allows you to change their poll rates by loading this out-of-tree module, instead of having to patch and re-compile the whole kernel. |
| 6 | + |
| 7 | +## Installation and setup |
| 8 | + |
| 9 | +Firstly find the `VID:PID` of your USB device with `lsusb`, such as `054c:0ce6`. |
| 10 | + |
| 11 | +### 0. Pick your bInterval value |
| 12 | + |
| 13 | +Check the speed of your USB device with (replace with your device's `VID:PID`): |
| 14 | + |
| 15 | +```console |
| 16 | +$ lsusb -d 054c:0ce6 -v | grep '^Negotiated speed:' |
| 17 | + |
| 18 | +Negotiated speed: Full Speed (12Mbps) |
| 19 | +``` |
| 20 | + |
| 21 | +#### Low Speed (USB 1.1) (1.5 Mbps) |
| 22 | + |
| 23 | +Extremely rare, rather forget about overclocking those too much. Note that "0" itself might not be a valid value. |
| 24 | + |
| 25 | +| Value of bInterval | Polling Period | Frequency | |
| 26 | +| ------------------ | -------------- | --------- | |
| 27 | +| 0 to 15 | 8 ms | 125 Hz | |
| 28 | +| 16 to 35 | 16 ms | 62.5 Hz | |
| 29 | +| 36 to 255 | 32 ms | 31.25 Hz | |
| 30 | + |
| 31 | +#### Full Speed (USB 1.1) (12 Mbps) |
| 32 | + |
| 33 | +This is most of the devices. |
| 34 | + |
| 35 | +| Value of bInterval | Polling Period | Frequency | |
| 36 | +| ------------------ | -------------- | --------- | |
| 37 | +| 1 | 1 ms | 1000 Hz | |
| 38 | +| 2 (*to 3*) | 2 ms | 500 Hz | |
| 39 | +| 4 (*to 7*) | 4 ms | 250 Hz | |
| 40 | +| 8 (*to 15*) | 8 ms | 125 Hz | |
| 41 | +| 16 (*to 31*) | 16 ms | 62.5 Hz | |
| 42 | +| 32 (*to 255*) | 32 ms | 31.25 Hz | |
| 43 | + |
| 44 | +#### High Speed (USB 2.0) (480 Mbps) |
| 45 | + |
| 46 | +Still has a maximum of 1000 Hz, but the values of `bInterval` differ (`Period = 2^(bInterval - 1)`). |
| 47 | + |
| 48 | +| Value of bInterval | Polling Period | Frequency | |
| 49 | +| ------------------ | -------------- | --------- | |
| 50 | +| 1 | 1 ms | 1000 Hz | |
| 51 | +| 2 | 2 ms | 500 Hz | |
| 52 | +| 3 | 4 ms | 250 Hz | |
| 53 | +| 4 | 8 ms | 125 Hz | |
| 54 | +| 5 | 16 ms | 62.5 Hz | |
| 55 | +| 6 | 32 ms | 31.25 Hz | |
| 56 | +| 7 to 255 | 32 ms | 31.25 Hz | |
| 57 | + |
| 58 | +#### Higher than that |
| 59 | + |
| 60 | +Don't quote me on this, I pulled the table below out of my ass and didn't test it yet :3 The formula seems to be `Period = 2^(bInterval - 1) * 0.125`. |
| 61 | + |
| 62 | +| Value of bInterval | Polling Period | Frequency | |
| 63 | +| ------------------ | -------------- | --------- | |
| 64 | +| 1 | 0.125 ms | 8000 Hz | |
| 65 | +| 2 | 0.250 ms | 4000 Hz | |
| 66 | +| 3 | 0.500 ms | 2000 Hz | |
| 67 | +| 4 | 1 ms | 1000 Hz | |
| 68 | +| 5 | 2 ms | 500 Hz | |
| 69 | +| 6 | 4 ms | 250 Hz | |
| 70 | + |
| 71 | +### 1. Install |
| 72 | + |
| 73 | +You can go to [Releases](https://github.com/p0358/usb_oc-dkms/releases) section and download the latest `.deb`, `.rpm` or `.pkg.tar.zst`. |
| 74 | + |
| 75 | +#### Debian/Ubuntu/Mint/Pop_OS (.deb) |
| 76 | + |
| 77 | +```console |
| 78 | +# curl -Lo /tmp/usb-oc-dkms.deb https://github.com/p0358/usb_oc-dkms/releases/download/v1.0/usb-oc-dkms_1.0_amd64.deb |
| 79 | +# apt install /tmp/usb-oc-dkms.deb |
| 80 | +``` |
| 81 | + |
| 82 | +#### Arch Linux/CachyOS/EndevourOS/Manjaro (.pkg.tar.zst) |
| 83 | + |
| 84 | +AUR: [usb_oc-dkms](https://aur.archlinux.org/packages/usb_oc-dkms) or: |
| 85 | + |
| 86 | +```console |
| 87 | +# curl -Lo /tmp/usb_oc-dkms.pkg.tar.zst https://github.com/p0358/usb_oc-dkms/releases/download/v1.0/usb_oc-dkms-1.0-1-any.pkg.tar.zst |
| 88 | +# pacman -U /tmp/usb_oc-dkms.pkg.tar.zst |
| 89 | +``` |
| 90 | + |
| 91 | +#### Fedora (.rpm) |
| 92 | + |
| 93 | +```console |
| 94 | +# curl -Lo /tmp/usb_oc-dkms.rpm https://github.com/p0358/usb_oc-dkms/releases/download/v1.0/usb_oc-dkms-1.0-1.fc45.noarch.rpm |
| 95 | +# dnf install /tmp/usb_oc-dkms.rpm |
| 96 | +``` |
| 97 | + |
| 98 | +#### openSUSE (.rpm) |
| 99 | + |
| 100 | +```console |
| 101 | +# curl -Lo /tmp/usb_oc-dkms.rpm https://github.com/p0358/usb_oc-dkms/releases/download/v1.0/usb_oc-dkms-1.0-1.fc45.noarch.rpm |
| 102 | +# zypper install --allow-unsigned-rpm /tmp/usb_oc-dkms.rpm |
| 103 | +``` |
| 104 | + |
| 105 | +#### Nobara |
| 106 | + |
| 107 | +Use this instead: https://github.com/GloriousEggroll/Linux-Pollrate-Patch |
| 108 | + |
| 109 | +#### Yet another distro |
| 110 | + |
| 111 | +I guess you're on your own. |
| 112 | + |
| 113 | +### 2. Test it out |
| 114 | + |
| 115 | +Load the kernel module and confirm that it's been loaded: |
| 116 | + |
| 117 | +```console |
| 118 | +# modprobe usb_oc |
| 119 | +# lsmod | grep usb_oc |
| 120 | +usb_oc 16384 0 |
| 121 | +``` |
| 122 | + |
| 123 | +You can change the module configuration on-the-fly without unloading the module. The changes will be applied immediately. Assuming you want, for the device with `VID:PID` of `054c:0ce6`, to set bInterval to `1`, run: |
| 124 | + |
| 125 | +```console |
| 126 | +# echo -n '054c:0ce6:1' > /sys/module/usb_oc/parameters/interrupt_interval_override |
| 127 | +``` |
| 128 | + |
| 129 | +If you want to overclock multiple devices, you'd do: |
| 130 | + |
| 131 | +```console |
| 132 | +# echo -n '054c:0ce6:1,1234:5678:1' > /sys/module/usb_oc/parameters/interrupt_interval_override |
| 133 | +``` |
| 134 | + |
| 135 | +Do monitor the output of `dmesg` command to diagnose the module and see any warnings. |
| 136 | + |
| 137 | +See the FAQ section for how to benchmark your device to confirm the actual overclocked rate is working. Some devices might just be impossible to overclock and will not send more data than they were designed for, when polled more frequently. Some will, for which this module is made. And some will already be set to their maximum polling rate of given USB version. |
| 138 | + |
| 139 | +Once you're done with testing, you may unload the module with `rmmod usb_oc`. Reconnect any USB devices if you want to restore their bIntervals to default. |
| 140 | + |
| 141 | +### 3. Configure the module to auto-load on system startup |
| 142 | + |
| 143 | +If you found a working configuration, you will probably want to persist it, so that it always overclocks your device when you boot up your computer. |
| 144 | + |
| 145 | +Firstly, set the module to load on system startup: |
| 146 | + |
| 147 | +```console |
| 148 | +# echo 'usb_oc' > /etc/modules-load.d/usb_oc.conf |
| 149 | +``` |
| 150 | + |
| 151 | +Secondly, set the module configuration (again, assuming you want, for the device with `VID:PID` of `054c:0ce6`, to set bInterval to `1`): |
| 152 | + |
| 153 | +```console |
| 154 | +# echo 'options usb_oc interrupt_interval_override=054c:0ce6:1' > /etc/modules-load.d/usb_oc.conf |
| 155 | +``` |
| 156 | + |
| 157 | +After rebooting the machine, verify the module was loaded and working with: |
| 158 | + |
| 159 | +```console |
| 160 | +# dmesg | grep usb_oc |
| 161 | +``` |
| 162 | + |
| 163 | +### 4. Success |
| 164 | + |
| 165 | +Share you overclock success stories at [#1](https://github.com/p0358/usb_oc-dkms/discussions/1) and failure stories at [#2](https://github.com/p0358/usb_oc-dkms/discussions/2)! |
| 166 | + |
| 167 | +## Notes |
| 168 | + |
| 169 | +### Secure Boot |
| 170 | + |
| 171 | +If you have Secure Boot enabled (check with `mokutil --sb-state`) and you get `modprobe: ERROR: could not insert 'usb_oc': Key was rejected by service` when trying to modprobe, you need to enroll DKMS's MOK key to your machine in order for the module to be possible to load. |
| 172 | + |
| 173 | +Just run: |
| 174 | + |
| 175 | +```bash |
| 176 | +mokutil --timeout -1 |
| 177 | +mokutil --import /var/lib/dkms/mok.pub |
| 178 | +``` |
| 179 | + |
| 180 | +You'll be prompted to create a password. Enter it twice. |
| 181 | + |
| 182 | +Reboot the computer. At boot you'll see the MOK Manager EFI interface. Press any key to enter it. |
| 183 | + |
| 184 | +- "Enroll MOK" |
| 185 | +- "Continue" |
| 186 | +- "Yes" |
| 187 | +- Enter the password you set up just now. |
| 188 | +- Select "OK" and the computer will reboot again. |
| 189 | + |
| 190 | +Now the module should be possible to load. |
| 191 | + |
| 192 | +### USB 1.1 and bandwidth limitations |
| 193 | + |
| 194 | +If your device is USB 1.1 ("Full Speed" 12 Mbps, or, heavens forbid, "Low Speed" 1.5 Mbps) and you overclock it too high (1000 Hz), you may run into bandwidth issues and sometimes experience some lagged input in games. At least I think that's why it happens and goes away with higher bInterval. |
| 195 | + |
| 196 | +I did the maths and with 12 Mbps and 1000 Hz, it should be roughly ~1572 bytes per poll though, which doesn't seem that little. I don't know how chatty XInput protocol is. Perhaps it's just the particular device that can't keep up. In any case, at some point you might have diminishing results with overclocking the device *too much*. |
| 197 | + |
| 198 | +### Little quirk: the device is reset after the bInterval descriptor change is made |
| 199 | + |
| 200 | +This is so that the change is picked up. But be careful with this, and not only for this reason, but in general: |
| 201 | + |
| 202 | +> [!WARNING] |
| 203 | +> Unload this module if you're trying to do something "sensitive"/"risky" with the overclocked device, such as trying to flash its firmware. I am not responsible for any problems if you do dumb things, please use common sense here. |
| 204 | +
|
| 205 | +## FAQ |
| 206 | + |
| 207 | +### Why does Fedora RPM package use DKMS instead of AKMODS? |
| 208 | + |
| 209 | +Because I couldn't figure out the kmod counterpart and didn't care enough to spend more time on it, if the DKMS one works (and then it works on more distros like openSUSE too). But if you care, then contributions are welcome to add it, including the CI workflow to build the appropriate RPM files (as far as I understand, we'd want to publish SRPM in Releases, but still would want to at least check the binary modules are indeed building from those for current kernel...). |
| 210 | + |
| 211 | +### How to benchmark the device to confirm it was overclocked? |
| 212 | + |
| 213 | +For controllers you can use **[Gamepadla Polling](https://github.com/cakama3a/Polling)** ([gamepadla-polling<sup>AUR</sup>](https://aur.archlinux.org/packages/gamepadla-polling)) and for mouse you can use **[evhz](https://git.sr.ht/~iank/evhz)** ([evhz-git<sup>AUR</sup>](https://aur.archlinux.org/packages/evhz-git)). |
| 214 | + |
| 215 | +### Why is USB overclocking not part of upstream kernel? |
| 216 | + |
| 217 | +What do I know? A you can see in "Alternatives" section below, some means of overclocking some devices exist, and yet the patchset to overclock any device didn't seem to get accepted. And some distros outside of Nobara seem to be [allergic](https://github.com/CachyOS/linux-cachyos/issues/240#issuecomment-2430116447) to it for some reason too. But who cares, this module allows you to overclock your devices anyway, without care about what your distro thinks about it or recompiling the whole kernel! |
| 218 | + |
| 219 | +## Alternatives |
| 220 | + |
| 221 | +The `usbhid` driver has options for [`mousepoll`](https://wiki.archlinux.org/title/Mouse_polling_rate#Set_polling_interval), but it [reportedly doesn't work with USB 3 devices](https://wiki.archlinux.org/title/Mouse_polling_rate#Polling_rate_not_changing). The option `kbpoll` also exists for keyboards, but likely suffers from the same problem. It also has an option `jspoll` for joysticks, but it doesn't work with gamepads using other drivers like `xpad`. |
| 222 | + |
| 223 | +[Linux-Kernel_MiSTer] has a downstream patch for [`xpad` driver adding `cpoll` option](https://github.com/MiSTer-devel/Linux-Kernel_MiSTer/blob/master/drivers/input/joystick/xpad.c). Unfortunately it is not upstreamed. |
| 224 | + |
| 225 | +Nobara comes with [this patch](https://github.com/GloriousEggroll/Linux-Pollrate-Patch) applied to its kernel. |
| 226 | + |
| 227 | +Some devices have settings apps that allow changing on-device configuration used by the device's firmware and its processor. Sometimes this configuration include the poll rate that will be advertised by the device, without needing a kernel module for it (for example Solaar for select Logitech mice). |
| 228 | + |
| 229 | +## Thanks to |
| 230 | + |
| 231 | +Some inspiration (parts of code/scripts) taken from: |
| 232 | + |
| 233 | +- https://github.com/hannesmann/gcadapter-oc-kmod (skeleton for a simple DKMS USB overclock module) |
| 234 | +- https://github.com/GloriousEggroll/Linux-Pollrate-Patch (kernel patchset with a configurable USB overclocking parameter) |
| 235 | +- https://github.com/strongtz/i915-sriov-dkms (CI and Makefiles) |
| 236 | +- https://github.com/KyleGospo/openrgb-dkms (Fedora dkms rpm spec file) |
| 237 | + |
| 238 | +## Dev notes |
| 239 | + |
| 240 | +For updating, remember to update the version in: |
| 241 | + |
| 242 | +- `dkms.conf` |
| 243 | +- `src/usb_oc.c` |
| 244 | +- `packaging/arch/PKGBUILD` |
| 245 | +- `packaging/rpm/usb_oc-dkms.spec` |
| 246 | +- (in this README in the Install section in package URLs) |
0 commit comments