Hotplug: device->next must be NULL in callback #791

Open
opened 2026-04-24 09:16:39 -05:00 by Youw · 0 comments
Youw commented 2026-04-24 09:16:39 -05:00 (Migrated from github.com)

Tracking from #790 / #674.

Contract (documented in #790)

The device->next pointer is always NULL. Each callback invocation describes exactly one device; compound or composite devices that expose multiple interfaces produce multiple callback invocations (typically delivered in quick succession).

Current state

Backends invoke the user callback with a hid_device_info* whose next field still points into the backend-internal enumeration list. Example: libusb/hid.c:1123 already carries a `TODO` for this:

```c
/* TODO: possibly make the `next` field NULL to match the behavior on other systems */
```

The other backends are similarly inconsistent.

Proposed fix

Before dispatching the callback, copy the `hid_device_info` into a local struct on the dispatcher's stack with `.next = NULL`, then pass a pointer to that local struct into the callback. Do not deep-copy the string fields — they are still owned by HIDAPI and remain valid for the duration of the callback.

This avoids exposing the internal list layout to user code and gives one consistent cross-backend contract.

Backends to touch

  • `libusb/hid.c` — `hid_internal_invoke_callbacks`
  • `linux/hid.c`
  • `mac/hid.c`
  • `windows/hid.c`
  • #674 (hotplug implementation)
  • #784 (original doc patch, superseded)
  • #790 (documentation of the target contract)
Tracking from #790 / #674. ### Contract (documented in #790) > The `device->next` pointer is always NULL. Each callback invocation describes exactly one device; compound or composite devices that expose multiple interfaces produce multiple callback invocations (typically delivered in quick succession). ### Current state Backends invoke the user callback with a `hid_device_info*` whose `next` field still points into the backend-internal enumeration list. Example: [libusb/hid.c:1123](https://github.com/libusb/hidapi/blob/connection-callback/libusb/hid.c#L1123) already carries a \`TODO\` for this: \`\`\`c /* TODO: possibly make the \`next\` field NULL to match the behavior on other systems */ \`\`\` The other backends are similarly inconsistent. ### Proposed fix Before dispatching the callback, copy the \`hid_device_info\` into a local struct on the dispatcher's stack with \`.next = NULL\`, then pass a pointer to that local struct into the callback. Do not deep-copy the string fields — they are still owned by HIDAPI and remain valid for the duration of the callback. This avoids exposing the internal list layout to user code and gives one consistent cross-backend contract. ### Backends to touch - [ ] \`libusb/hid.c\` — \`hid_internal_invoke_callbacks\` - [ ] \`linux/hid.c\` - [ ] \`mac/hid.c\` - [ ] \`windows/hid.c\` ### Related - #674 (hotplug implementation) - #784 (original doc patch, superseded) - #790 (documentation of the target contract)
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
gh-libusb/hidapi#791
No description provided.