This is an automated email from the ASF dual-hosted git repository.
xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new e09fb273468 drivers/usbhost: Fix HID mouse class to work with Logitech
mouse
e09fb273468 is described below
commit e09fb2734684b4ea39ae959b971b6e2f8b5bac7a
Author: Alan Carvalho de Assis <[email protected]>
AuthorDate: Thu Oct 22 15:52:18 2026 -0300
drivers/usbhost: Fix HID mouse class to work with Logitech mouse
HID mouse class:
- The whole configuration descriptor is passed to the class driver. In
a composite device (e.g. a keyboard + mouse receiver) only use the
endpoints of the HID mouse interface instead of the first interrupt
IN endpoint found.
- Select the boot protocol with SET_PROTOCOL: the reports are decoded
using the fixed boot format, but HID devices start in report protocol.
- Fix nxstyle issues reported in the touched file.
Signed-off-by: Alan C. Assis <[email protected]>
Assisted-by: Claude Code Opus 5.5
---
drivers/usbhost/usbhost_hidmouse.c | 46 ++++++++++++++++++++++++++++++++++----
1 file changed, 42 insertions(+), 4 deletions(-)
diff --git a/drivers/usbhost/usbhost_hidmouse.c
b/drivers/usbhost/usbhost_hidmouse.c
index 623cf23989a..64a7c1f0443 100644
--- a/drivers/usbhost/usbhost_hidmouse.c
+++ b/drivers/usbhost/usbhost_hidmouse.c
@@ -253,6 +253,7 @@ struct usbhost_state_s
volatile bool open; /* TRUE: The mouse device is open */
volatile bool valid; /* TRUE: New sample data is available
*/
uint8_t devno; /* Minor number in the /dev/mouse[n]
device */
+ uint8_t ifno; /* Mouse interface number */
uint8_t nwaiters; /* Number of threads waiting for mouse
data */
#ifdef CONFIG_HIDMOUSE_TSCIF
uint8_t id; /* Current "touch" point ID */
@@ -1359,6 +1360,7 @@ static inline int usbhost_cfgdesc(FAR struct
usbhost_state_s *priv,
FAR struct usbhost_epdesc_s epindesc;
int remaining;
uint8_t found = 0;
+ bool ifmatch = false;
bool done = false;
int ret;
@@ -1404,6 +1406,9 @@ static inline int usbhost_cfgdesc(FAR struct
usbhost_state_s *priv,
case USB_DESC_TYPE_INTERFACE:
{
+ FAR struct usb_ifdesc_s *ifdesc =
+ (FAR struct usb_ifdesc_s *)configdesc;
+
uinfo("Interface descriptor\n");
DEBUGASSERT(remaining >= USB_SIZEOF_IFDESC);
@@ -1421,9 +1426,16 @@ static inline int usbhost_cfgdesc(FAR struct
usbhost_state_s *priv,
}
else
{
- /* Otherwise, discard any endpoints previously found */
+ /* Otherwise, discard any endpoints previously found. The
+ * whole configuration is passed to us, so in a composite
+ * device (e.g. a keyboard + mouse receiver) only use the
+ * endpoints of the HID mouse interface.
+ */
- found = USBHOST_IFFOUND;
+ ifmatch = ifdesc->classid == USB_CLASS_HID &&
+ ifdesc->protocol == USBHID_PROTOCOL_MOUSE;
+ found = ifmatch ? USBHOST_IFFOUND : 0;
+ priv->ifno = ifdesc->ifno;
}
}
break;
@@ -1446,9 +1458,10 @@ static inline int usbhost_cfgdesc(FAR struct
usbhost_state_s *priv,
uinfo("Endpoint descriptor\n");
DEBUGASSERT(remaining >= USB_SIZEOF_EPDESC);
- /* Check for an interrupt endpoint. */
+ /* Check for an interrupt endpoint of the mouse interface */
- if ((epdesc->attr & USB_EP_ATTR_XFERTYPE_MASK) ==
+ if (ifmatch &&
+ (epdesc->attr & USB_EP_ATTR_XFERTYPE_MASK) ==
USB_EP_ATTR_XFER_INT)
{
/* Yes.. it is a interrupt endpoint. IN or OUT? */
@@ -1558,6 +1571,7 @@ static inline int usbhost_cfgdesc(FAR struct
usbhost_state_s *priv,
static inline int usbhost_devinit(FAR struct usbhost_state_s *priv)
{
+ FAR struct usb_ctrlreq_s *ctrlreq;
char devname[DEV_NAMELEN];
int ret;
@@ -1572,6 +1586,30 @@ static inline int usbhost_devinit(FAR struct
usbhost_state_s *priv)
return ret;
}
+ /* The reports are decoded using the fixed boot protocol format, but a HID
+ * device starts in report protocol after configuration. Select the boot
+ * protocol (the transfer buffer is not in use yet, so it holds the
+ * request).
+ */
+
+ ctrlreq = (FAR struct usb_ctrlreq_s *)priv->tbuffer;
+ ctrlreq->type = USB_REQ_DIR_OUT | USB_REQ_TYPE_CLASS |
+ USB_REQ_RECIPIENT_INTERFACE;
+ ctrlreq->req = USBHID_REQUEST_SETPROTOCOL;
+ ctrlreq->value[0] = 0; /* 0 = Boot protocol */
+ ctrlreq->value[1] = 0;
+ ctrlreq->index[0] = priv->ifno;
+ ctrlreq->index[1] = 0;
+ ctrlreq->len[0] = 0;
+ ctrlreq->len[1] = 0;
+
+ ret = DRVR_CTRLOUT(priv->usbclass.hport->drvr, priv->usbclass.hport->ep0,
+ ctrlreq, NULL);
+ if (ret < 0)
+ {
+ uwarn("WARNING: SET_PROTOCOL(boot) failed: %d\n", ret);
+ }
+
/* Increment the reference count. This will prevent usbhost_destroy() from
* being called asynchronously if the device is removed.
*/