Fixed standalone locking bugs in HID host idle get/set - #264

Merged
fdesbiens merged 1 commit into
devfrom
fix-hid-standalone-idle-locking
Jun 4, 2026
Merged

Fixed standalone locking bugs in HID host idle get/set#264
fdesbiens merged 1 commit into
devfrom
fix-hid-standalone-idle-locking

Conversation

@fdesbiens

Copy link
Copy Markdown
Contributor

Summary

Two bugs discovered while reviewing and fixing thread-safety issues in the new ux_host_class_hid_protocol_get/set functions (PR #244).

Changes

1. idle_get.c: wrong operator acquires no lock in standalone mode

Line 104 used &= ~UX_HOST_CLASS_HID_FLAG_LOCK (the release/clear operation) instead of |= UX_HOST_CLASS_HID_FLAG_LOCK (acquire/set). The preceding check correctly returns UX_BUSY when the flag is set, but the follow-on line then immediately clears it instead of setting it. The net effect is that the HID instance is never actually locked in UX_HOST_STANDALONE mode, making the mutual-exclusion check a no-op and leaving idle_get unprotected against concurrent calls.

2. idle_set.c: standalone path used a blocking spin-loop

The standalone branch called _ux_host_class_hid_idle_set_run() in a do/while loop, blocking the caller until the transfer completed. This is inconsistent with every other inline HID control-transfer function (idle_get, report_get, report_set, protocol_get, protocol_set) which all use the direct UX_DISABLE/UX_RESTORE atomic flag pattern and return UX_BUSY if the instance or device endpoint is already locked.

Replaced with the same inline standalone locking pattern used by the other functions: atomic HID_FLAG_LOCK acquire, atomic DEVICE_FLAG_LOCK acquire with AUTO_DEVICE_UNLOCK + UX_TRANSFER_STATE_RESET, and an AUTO_WAIT check at completion consistent with idle_get behavior.

Two issues discovered while reviewing and fixing thread-safety issues in
the new ux_host_class_hid_protocol_get/set functions (PR #244).
1. idle_get.c: wrong operator acquires no lock in standalone mode
Line 104 used '&= ~UX_HOST_CLASS_HID_FLAG_LOCK' (the release/clear
operation) instead of '|= UX_HOST_CLASS_HID_FLAG_LOCK' (acquire/set).
The preceding check correctly returns UX_BUSY when the flag is set,
but the follow-on line then immediately clears it instead of setting it.
The net effect is that the HID instance is never actually locked in
UX_HOST_STANDALONE mode, making the mutual-exclusion check a no-op.
2. idle_set.c: standalone path used a blocking spin-loop
The standalone branch called _ux_host_class_hid_idle_set_run() in a
do/while loop, blocking the caller until the transfer completed. This
is inconsistent with every other inline HID control-transfer function
(idle_get, report_get, report_set, protocol_get, protocol_set) which
all use the direct UX_DISABLE/UX_RESTORE atomic flag pattern and
return UX_BUSY if the instance or device endpoint is already locked.
Replaced with the same inline standalone locking pattern used by the
other functions: atomic HID FLAG_LOCK acquire, atomic DEVICE_FLAG_LOCK
acquire with AUTO_DEVICE_UNLOCK + UX_TRANSFER_STATE_RESET, and an
AUTO_WAIT check at completion consistent with idle_get behavior.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@fdesbiensfdesbiens changed the title Fix standalone locking bugs in HID host idle get/setFixed standalone locking bugs in HID host idle get/setJun 4, 2026
@fdesbiens
fdesbiens merged commit 94cdd1e into devJun 4, 2026
1 check passed
@fdesbiens
fdesbiens deleted the fix-hid-standalone-idle-locking branch June 4, 2026 19:45
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@fdesbiens
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Fixed standalone locking bugs in HID host idle get/set - #264

Merged
fdesbiens merged 1 commit into
devfrom
fix-hid-standalone-idle-locking
Jun 4, 2026
Merged

Fixed standalone locking bugs in HID host idle get/set#264
fdesbiens merged 1 commit into
devfrom
fix-hid-standalone-idle-locking

Conversation

@fdesbiens

Copy link
Copy Markdown
Contributor

Summary

Two bugs discovered while reviewing and fixing thread-safety issues in the new ux_host_class_hid_protocol_get/set functions (PR #244).

Changes

1. idle_get.c: wrong operator acquires no lock in standalone mode

Line 104 used &= ~UX_HOST_CLASS_HID_FLAG_LOCK (the release/clear operation) instead of |= UX_HOST_CLASS_HID_FLAG_LOCK (acquire/set). The preceding check correctly returns UX_BUSY when the flag is set, but the follow-on line then immediately clears it instead of setting it. The net effect is that the HID instance is never actually locked in UX_HOST_STANDALONE mode, making the mutual-exclusion check a no-op and leaving idle_get unprotected against concurrent calls.

2. idle_set.c: standalone path used a blocking spin-loop

The standalone branch called _ux_host_class_hid_idle_set_run() in a do/while loop, blocking the caller until the transfer completed. This is inconsistent with every other inline HID control-transfer function (idle_get, report_get, report_set, protocol_get, protocol_set) which all use the direct UX_DISABLE/UX_RESTORE atomic flag pattern and return UX_BUSY if the instance or device endpoint is already locked.

Replaced with the same inline standalone locking pattern used by the other functions: atomic HID_FLAG_LOCK acquire, atomic DEVICE_FLAG_LOCK acquire with AUTO_DEVICE_UNLOCK + UX_TRANSFER_STATE_RESET, and an AUTO_WAIT check at completion consistent with idle_get behavior.

Two issues discovered while reviewing and fixing thread-safety issues in
the new ux_host_class_hid_protocol_get/set functions (PR #244).
1. idle_get.c: wrong operator acquires no lock in standalone mode
Line 104 used '&= ~UX_HOST_CLASS_HID_FLAG_LOCK' (the release/clear
operation) instead of '|= UX_HOST_CLASS_HID_FLAG_LOCK' (acquire/set).
The preceding check correctly returns UX_BUSY when the flag is set,
but the follow-on line then immediately clears it instead of setting it.
The net effect is that the HID instance is never actually locked in
UX_HOST_STANDALONE mode, making the mutual-exclusion check a no-op.
2. idle_set.c: standalone path used a blocking spin-loop
The standalone branch called _ux_host_class_hid_idle_set_run() in a
do/while loop, blocking the caller until the transfer completed. This
is inconsistent with every other inline HID control-transfer function
(idle_get, report_get, report_set, protocol_get, protocol_set) which
all use the direct UX_DISABLE/UX_RESTORE atomic flag pattern and
return UX_BUSY if the instance or device endpoint is already locked.
Replaced with the same inline standalone locking pattern used by the
other functions: atomic HID FLAG_LOCK acquire, atomic DEVICE_FLAG_LOCK
acquire with AUTO_DEVICE_UNLOCK + UX_TRANSFER_STATE_RESET, and an
AUTO_WAIT check at completion consistent with idle_get behavior.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@fdesbiensfdesbiens changed the title Fix standalone locking bugs in HID host idle get/setFixed standalone locking bugs in HID host idle get/setJun 4, 2026
@fdesbiens
fdesbiens merged commit 94cdd1e into devJun 4, 2026
1 check passed
@fdesbiens
fdesbiens deleted the fix-hid-standalone-idle-locking branch June 4, 2026 19:45
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@fdesbiens
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fixed standalone locking bugs in HID host idle get/set - #264

Merged
fdesbiens merged 1 commit into
devfrom
fix-hid-standalone-idle-locking
Jun 4, 2026
Merged

Fixed standalone locking bugs in HID host idle get/set#264
fdesbiens merged 1 commit into
devfrom
fix-hid-standalone-idle-locking

Conversation

@fdesbiens

Copy link
Copy Markdown
Contributor

Summary

Two bugs discovered while reviewing and fixing thread-safety issues in the new ux_host_class_hid_protocol_get/set functions (PR #244).

Changes

1. idle_get.c: wrong operator acquires no lock in standalone mode

Line 104 used &= ~UX_HOST_CLASS_HID_FLAG_LOCK (the release/clear operation) instead of |= UX_HOST_CLASS_HID_FLAG_LOCK (acquire/set). The preceding check correctly returns UX_BUSY when the flag is set, but the follow-on line then immediately clears it instead of setting it. The net effect is that the HID instance is never actually locked in UX_HOST_STANDALONE mode, making the mutual-exclusion check a no-op and leaving idle_get unprotected against concurrent calls.

2. idle_set.c: standalone path used a blocking spin-loop

The standalone branch called _ux_host_class_hid_idle_set_run() in a do/while loop, blocking the caller until the transfer completed. This is inconsistent with every other inline HID control-transfer function (idle_get, report_get, report_set, protocol_get, protocol_set) which all use the direct UX_DISABLE/UX_RESTORE atomic flag pattern and return UX_BUSY if the instance or device endpoint is already locked.

Replaced with the same inline standalone locking pattern used by the other functions: atomic HID_FLAG_LOCK acquire, atomic DEVICE_FLAG_LOCK acquire with AUTO_DEVICE_UNLOCK + UX_TRANSFER_STATE_RESET, and an AUTO_WAIT check at completion consistent with idle_get behavior.

Two issues discovered while reviewing and fixing thread-safety issues in
the new ux_host_class_hid_protocol_get/set functions (PR #244).
1. idle_get.c: wrong operator acquires no lock in standalone mode
Line 104 used '&= ~UX_HOST_CLASS_HID_FLAG_LOCK' (the release/clear
operation) instead of '|= UX_HOST_CLASS_HID_FLAG_LOCK' (acquire/set).
The preceding check correctly returns UX_BUSY when the flag is set,
but the follow-on line then immediately clears it instead of setting it.
The net effect is that the HID instance is never actually locked in
UX_HOST_STANDALONE mode, making the mutual-exclusion check a no-op.
2. idle_set.c: standalone path used a blocking spin-loop
The standalone branch called _ux_host_class_hid_idle_set_run() in a
do/while loop, blocking the caller until the transfer completed. This
is inconsistent with every other inline HID control-transfer function
(idle_get, report_get, report_set, protocol_get, protocol_set) which
all use the direct UX_DISABLE/UX_RESTORE atomic flag pattern and
return UX_BUSY if the instance or device endpoint is already locked.
Replaced with the same inline standalone locking pattern used by the
other functions: atomic HID FLAG_LOCK acquire, atomic DEVICE_FLAG_LOCK
acquire with AUTO_DEVICE_UNLOCK + UX_TRANSFER_STATE_RESET, and an
AUTO_WAIT check at completion consistent with idle_get behavior.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@fdesbiensfdesbiens changed the title Fix standalone locking bugs in HID host idle get/setFixed standalone locking bugs in HID host idle get/setJun 4, 2026
@fdesbiens
fdesbiens merged commit 94cdd1e into devJun 4, 2026
1 check passed
@fdesbiens
fdesbiens deleted the fix-hid-standalone-idle-locking branch June 4, 2026 19:45
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@fdesbiens
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fixed standalone locking bugs in HID host idle get/set - #264

Merged
fdesbiens merged 1 commit into
devfrom
fix-hid-standalone-idle-locking
Jun 4, 2026
Merged

Fixed standalone locking bugs in HID host idle get/set#264
fdesbiens merged 1 commit into
devfrom
fix-hid-standalone-idle-locking

Conversation

@fdesbiens

Copy link
Copy Markdown
Contributor

Summary

Two bugs discovered while reviewing and fixing thread-safety issues in the new ux_host_class_hid_protocol_get/set functions (PR #244).

Changes

1. idle_get.c: wrong operator acquires no lock in standalone mode

Line 104 used &= ~UX_HOST_CLASS_HID_FLAG_LOCK (the release/clear operation) instead of |= UX_HOST_CLASS_HID_FLAG_LOCK (acquire/set). The preceding check correctly returns UX_BUSY when the flag is set, but the follow-on line then immediately clears it instead of setting it. The net effect is that the HID instance is never actually locked in UX_HOST_STANDALONE mode, making the mutual-exclusion check a no-op and leaving idle_get unprotected against concurrent calls.

2. idle_set.c: standalone path used a blocking spin-loop

The standalone branch called _ux_host_class_hid_idle_set_run() in a do/while loop, blocking the caller until the transfer completed. This is inconsistent with every other inline HID control-transfer function (idle_get, report_get, report_set, protocol_get, protocol_set) which all use the direct UX_DISABLE/UX_RESTORE atomic flag pattern and return UX_BUSY if the instance or device endpoint is already locked.

Replaced with the same inline standalone locking pattern used by the other functions: atomic HID_FLAG_LOCK acquire, atomic DEVICE_FLAG_LOCK acquire with AUTO_DEVICE_UNLOCK + UX_TRANSFER_STATE_RESET, and an AUTO_WAIT check at completion consistent with idle_get behavior.

Two issues discovered while reviewing and fixing thread-safety issues in
the new ux_host_class_hid_protocol_get/set functions (PR #244).
1. idle_get.c: wrong operator acquires no lock in standalone mode
Line 104 used '&= ~UX_HOST_CLASS_HID_FLAG_LOCK' (the release/clear
operation) instead of '|= UX_HOST_CLASS_HID_FLAG_LOCK' (acquire/set).
The preceding check correctly returns UX_BUSY when the flag is set,
but the follow-on line then immediately clears it instead of setting it.
The net effect is that the HID instance is never actually locked in
UX_HOST_STANDALONE mode, making the mutual-exclusion check a no-op.
2. idle_set.c: standalone path used a blocking spin-loop
The standalone branch called _ux_host_class_hid_idle_set_run() in a
do/while loop, blocking the caller until the transfer completed. This
is inconsistent with every other inline HID control-transfer function
(idle_get, report_get, report_set, protocol_get, protocol_set) which
all use the direct UX_DISABLE/UX_RESTORE atomic flag pattern and
return UX_BUSY if the instance or device endpoint is already locked.
Replaced with the same inline standalone locking pattern used by the
other functions: atomic HID FLAG_LOCK acquire, atomic DEVICE_FLAG_LOCK
acquire with AUTO_DEVICE_UNLOCK + UX_TRANSFER_STATE_RESET, and an
AUTO_WAIT check at completion consistent with idle_get behavior.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@fdesbiensfdesbiens changed the title Fix standalone locking bugs in HID host idle get/setFixed standalone locking bugs in HID host idle get/setJun 4, 2026
@fdesbiens
fdesbiens merged commit 94cdd1e into devJun 4, 2026
1 check passed
@fdesbiens
fdesbiens deleted the fix-hid-standalone-idle-locking branch June 4, 2026 19:45
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@fdesbiens
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Fixed standalone locking bugs in HID host idle get/set - #264

Merged
fdesbiens merged 1 commit into
devfrom
fix-hid-standalone-idle-locking
Jun 4, 2026
Merged

Fixed standalone locking bugs in HID host idle get/set#264
fdesbiens merged 1 commit into
devfrom
fix-hid-standalone-idle-locking

Conversation

@fdesbiens

Copy link
Copy Markdown
Contributor

Summary

Two bugs discovered while reviewing and fixing thread-safety issues in the new ux_host_class_hid_protocol_get/set functions (PR #244).

Changes

1. idle_get.c: wrong operator acquires no lock in standalone mode

Line 104 used &= ~UX_HOST_CLASS_HID_FLAG_LOCK (the release/clear operation) instead of |= UX_HOST_CLASS_HID_FLAG_LOCK (acquire/set). The preceding check correctly returns UX_BUSY when the flag is set, but the follow-on line then immediately clears it instead of setting it. The net effect is that the HID instance is never actually locked in UX_HOST_STANDALONE mode, making the mutual-exclusion check a no-op and leaving idle_get unprotected against concurrent calls.

2. idle_set.c: standalone path used a blocking spin-loop

The standalone branch called _ux_host_class_hid_idle_set_run() in a do/while loop, blocking the caller until the transfer completed. This is inconsistent with every other inline HID control-transfer function (idle_get, report_get, report_set, protocol_get, protocol_set) which all use the direct UX_DISABLE/UX_RESTORE atomic flag pattern and return UX_BUSY if the instance or device endpoint is already locked.

Replaced with the same inline standalone locking pattern used by the other functions: atomic HID_FLAG_LOCK acquire, atomic DEVICE_FLAG_LOCK acquire with AUTO_DEVICE_UNLOCK + UX_TRANSFER_STATE_RESET, and an AUTO_WAIT check at completion consistent with idle_get behavior.

Two issues discovered while reviewing and fixing thread-safety issues in
the new ux_host_class_hid_protocol_get/set functions (PR #244).
1. idle_get.c: wrong operator acquires no lock in standalone mode
Line 104 used '&= ~UX_HOST_CLASS_HID_FLAG_LOCK' (the release/clear
operation) instead of '|= UX_HOST_CLASS_HID_FLAG_LOCK' (acquire/set).
The preceding check correctly returns UX_BUSY when the flag is set,
but the follow-on line then immediately clears it instead of setting it.
The net effect is that the HID instance is never actually locked in
UX_HOST_STANDALONE mode, making the mutual-exclusion check a no-op.
2. idle_set.c: standalone path used a blocking spin-loop
The standalone branch called _ux_host_class_hid_idle_set_run() in a
do/while loop, blocking the caller until the transfer completed. This
is inconsistent with every other inline HID control-transfer function
(idle_get, report_get, report_set, protocol_get, protocol_set) which
all use the direct UX_DISABLE/UX_RESTORE atomic flag pattern and
return UX_BUSY if the instance or device endpoint is already locked.
Replaced with the same inline standalone locking pattern used by the
other functions: atomic HID FLAG_LOCK acquire, atomic DEVICE_FLAG_LOCK
acquire with AUTO_DEVICE_UNLOCK + UX_TRANSFER_STATE_RESET, and an
AUTO_WAIT check at completion consistent with idle_get behavior.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@fdesbiensfdesbiens changed the title Fix standalone locking bugs in HID host idle get/setFixed standalone locking bugs in HID host idle get/setJun 4, 2026
@fdesbiens
fdesbiens merged commit 94cdd1e into devJun 4, 2026
1 check passed
@fdesbiens
fdesbiens deleted the fix-hid-standalone-idle-locking branch June 4, 2026 19:45
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@fdesbiens
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fixed standalone locking bugs in HID host idle get/set - #264

Merged
fdesbiens merged 1 commit into
devfrom
fix-hid-standalone-idle-locking
Jun 4, 2026
Merged

Fixed standalone locking bugs in HID host idle get/set#264
fdesbiens merged 1 commit into
devfrom
fix-hid-standalone-idle-locking

Conversation

@fdesbiens

Copy link
Copy Markdown
Contributor

Summary

Two bugs discovered while reviewing and fixing thread-safety issues in the new ux_host_class_hid_protocol_get/set functions (PR #244).

Changes

1. idle_get.c: wrong operator acquires no lock in standalone mode

Line 104 used &= ~UX_HOST_CLASS_HID_FLAG_LOCK (the release/clear operation) instead of |= UX_HOST_CLASS_HID_FLAG_LOCK (acquire/set). The preceding check correctly returns UX_BUSY when the flag is set, but the follow-on line then immediately clears it instead of setting it. The net effect is that the HID instance is never actually locked in UX_HOST_STANDALONE mode, making the mutual-exclusion check a no-op and leaving idle_get unprotected against concurrent calls.

2. idle_set.c: standalone path used a blocking spin-loop

The standalone branch called _ux_host_class_hid_idle_set_run() in a do/while loop, blocking the caller until the transfer completed. This is inconsistent with every other inline HID control-transfer function (idle_get, report_get, report_set, protocol_get, protocol_set) which all use the direct UX_DISABLE/UX_RESTORE atomic flag pattern and return UX_BUSY if the instance or device endpoint is already locked.

Replaced with the same inline standalone locking pattern used by the other functions: atomic HID_FLAG_LOCK acquire, atomic DEVICE_FLAG_LOCK acquire with AUTO_DEVICE_UNLOCK + UX_TRANSFER_STATE_RESET, and an AUTO_WAIT check at completion consistent with idle_get behavior.

Two issues discovered while reviewing and fixing thread-safety issues in
the new ux_host_class_hid_protocol_get/set functions (PR #244).
1. idle_get.c: wrong operator acquires no lock in standalone mode
Line 104 used '&= ~UX_HOST_CLASS_HID_FLAG_LOCK' (the release/clear
operation) instead of '|= UX_HOST_CLASS_HID_FLAG_LOCK' (acquire/set).
The preceding check correctly returns UX_BUSY when the flag is set,
but the follow-on line then immediately clears it instead of setting it.
The net effect is that the HID instance is never actually locked in
UX_HOST_STANDALONE mode, making the mutual-exclusion check a no-op.
2. idle_set.c: standalone path used a blocking spin-loop
The standalone branch called _ux_host_class_hid_idle_set_run() in a
do/while loop, blocking the caller until the transfer completed. This
is inconsistent with every other inline HID control-transfer function
(idle_get, report_get, report_set, protocol_get, protocol_set) which
all use the direct UX_DISABLE/UX_RESTORE atomic flag pattern and
return UX_BUSY if the instance or device endpoint is already locked.
Replaced with the same inline standalone locking pattern used by the
other functions: atomic HID FLAG_LOCK acquire, atomic DEVICE_FLAG_LOCK
acquire with AUTO_DEVICE_UNLOCK + UX_TRANSFER_STATE_RESET, and an
AUTO_WAIT check at completion consistent with idle_get behavior.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@fdesbiensfdesbiens changed the title Fix standalone locking bugs in HID host idle get/setFixed standalone locking bugs in HID host idle get/setJun 4, 2026
@fdesbiens
fdesbiens merged commit 94cdd1e into devJun 4, 2026
1 check passed
@fdesbiens
fdesbiens deleted the fix-hid-standalone-idle-locking branch June 4, 2026 19:45
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@fdesbiens
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fixed standalone locking bugs in HID host idle get/set - #264

Merged
fdesbiens merged 1 commit into
devfrom
fix-hid-standalone-idle-locking
Jun 4, 2026
Merged

Fixed standalone locking bugs in HID host idle get/set#264
fdesbiens merged 1 commit into
devfrom
fix-hid-standalone-idle-locking

Conversation

@fdesbiens

Copy link
Copy Markdown
Contributor

Summary

Two bugs discovered while reviewing and fixing thread-safety issues in the new ux_host_class_hid_protocol_get/set functions (PR #244).

Changes

1. idle_get.c: wrong operator acquires no lock in standalone mode

Line 104 used &= ~UX_HOST_CLASS_HID_FLAG_LOCK (the release/clear operation) instead of |= UX_HOST_CLASS_HID_FLAG_LOCK (acquire/set). The preceding check correctly returns UX_BUSY when the flag is set, but the follow-on line then immediately clears it instead of setting it. The net effect is that the HID instance is never actually locked in UX_HOST_STANDALONE mode, making the mutual-exclusion check a no-op and leaving idle_get unprotected against concurrent calls.

2. idle_set.c: standalone path used a blocking spin-loop

The standalone branch called _ux_host_class_hid_idle_set_run() in a do/while loop, blocking the caller until the transfer completed. This is inconsistent with every other inline HID control-transfer function (idle_get, report_get, report_set, protocol_get, protocol_set) which all use the direct UX_DISABLE/UX_RESTORE atomic flag pattern and return UX_BUSY if the instance or device endpoint is already locked.

Replaced with the same inline standalone locking pattern used by the other functions: atomic HID_FLAG_LOCK acquire, atomic DEVICE_FLAG_LOCK acquire with AUTO_DEVICE_UNLOCK + UX_TRANSFER_STATE_RESET, and an AUTO_WAIT check at completion consistent with idle_get behavior.

Two issues discovered while reviewing and fixing thread-safety issues in
the new ux_host_class_hid_protocol_get/set functions (PR #244).
1. idle_get.c: wrong operator acquires no lock in standalone mode
Line 104 used '&= ~UX_HOST_CLASS_HID_FLAG_LOCK' (the release/clear
operation) instead of '|= UX_HOST_CLASS_HID_FLAG_LOCK' (acquire/set).
The preceding check correctly returns UX_BUSY when the flag is set,
but the follow-on line then immediately clears it instead of setting it.
The net effect is that the HID instance is never actually locked in
UX_HOST_STANDALONE mode, making the mutual-exclusion check a no-op.
2. idle_set.c: standalone path used a blocking spin-loop
The standalone branch called _ux_host_class_hid_idle_set_run() in a
do/while loop, blocking the caller until the transfer completed. This
is inconsistent with every other inline HID control-transfer function
(idle_get, report_get, report_set, protocol_get, protocol_set) which
all use the direct UX_DISABLE/UX_RESTORE atomic flag pattern and
return UX_BUSY if the instance or device endpoint is already locked.
Replaced with the same inline standalone locking pattern used by the
other functions: atomic HID FLAG_LOCK acquire, atomic DEVICE_FLAG_LOCK
acquire with AUTO_DEVICE_UNLOCK + UX_TRANSFER_STATE_RESET, and an
AUTO_WAIT check at completion consistent with idle_get behavior.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@fdesbiensfdesbiens changed the title Fix standalone locking bugs in HID host idle get/setFixed standalone locking bugs in HID host idle get/setJun 4, 2026
@fdesbiens
fdesbiens merged commit 94cdd1e into devJun 4, 2026
1 check passed
@fdesbiens
fdesbiens deleted the fix-hid-standalone-idle-locking branch June 4, 2026 19:45
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@fdesbiens
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Fixed standalone locking bugs in HID host idle get/set - #264

Merged
fdesbiens merged 1 commit into
devfrom
fix-hid-standalone-idle-locking
Jun 4, 2026
Merged

Fixed standalone locking bugs in HID host idle get/set#264
fdesbiens merged 1 commit into
devfrom
fix-hid-standalone-idle-locking

Conversation

@fdesbiens

Copy link
Copy Markdown
Contributor

Summary

Two bugs discovered while reviewing and fixing thread-safety issues in the new ux_host_class_hid_protocol_get/set functions (PR #244).

Changes

1. idle_get.c: wrong operator acquires no lock in standalone mode

Line 104 used &= ~UX_HOST_CLASS_HID_FLAG_LOCK (the release/clear operation) instead of |= UX_HOST_CLASS_HID_FLAG_LOCK (acquire/set). The preceding check correctly returns UX_BUSY when the flag is set, but the follow-on line then immediately clears it instead of setting it. The net effect is that the HID instance is never actually locked in UX_HOST_STANDALONE mode, making the mutual-exclusion check a no-op and leaving idle_get unprotected against concurrent calls.

2. idle_set.c: standalone path used a blocking spin-loop

The standalone branch called _ux_host_class_hid_idle_set_run() in a do/while loop, blocking the caller until the transfer completed. This is inconsistent with every other inline HID control-transfer function (idle_get, report_get, report_set, protocol_get, protocol_set) which all use the direct UX_DISABLE/UX_RESTORE atomic flag pattern and return UX_BUSY if the instance or device endpoint is already locked.

Replaced with the same inline standalone locking pattern used by the other functions: atomic HID_FLAG_LOCK acquire, atomic DEVICE_FLAG_LOCK acquire with AUTO_DEVICE_UNLOCK + UX_TRANSFER_STATE_RESET, and an AUTO_WAIT check at completion consistent with idle_get behavior.

Two issues discovered while reviewing and fixing thread-safety issues in
the new ux_host_class_hid_protocol_get/set functions (PR #244).
1. idle_get.c: wrong operator acquires no lock in standalone mode
Line 104 used '&= ~UX_HOST_CLASS_HID_FLAG_LOCK' (the release/clear
operation) instead of '|= UX_HOST_CLASS_HID_FLAG_LOCK' (acquire/set).
The preceding check correctly returns UX_BUSY when the flag is set,
but the follow-on line then immediately clears it instead of setting it.
The net effect is that the HID instance is never actually locked in
UX_HOST_STANDALONE mode, making the mutual-exclusion check a no-op.
2. idle_set.c: standalone path used a blocking spin-loop
The standalone branch called _ux_host_class_hid_idle_set_run() in a
do/while loop, blocking the caller until the transfer completed. This
is inconsistent with every other inline HID control-transfer function
(idle_get, report_get, report_set, protocol_get, protocol_set) which
all use the direct UX_DISABLE/UX_RESTORE atomic flag pattern and
return UX_BUSY if the instance or device endpoint is already locked.
Replaced with the same inline standalone locking pattern used by the
other functions: atomic HID FLAG_LOCK acquire, atomic DEVICE_FLAG_LOCK
acquire with AUTO_DEVICE_UNLOCK + UX_TRANSFER_STATE_RESET, and an
AUTO_WAIT check at completion consistent with idle_get behavior.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@fdesbiensfdesbiens changed the title Fix standalone locking bugs in HID host idle get/setFixed standalone locking bugs in HID host idle get/setJun 4, 2026
@fdesbiens
fdesbiens merged commit 94cdd1e into devJun 4, 2026
1 check passed
@fdesbiens
fdesbiens deleted the fix-hid-standalone-idle-locking branch June 4, 2026 19:45
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@fdesbiens