Mouse connected with Arduino USB Host Shield is not working on my other PC

Mouse connected with Arduino USB Host Shield is not working on my other PC

Hello Arduino Community!

I've encountered issues with the Arduino USB Host Shield's communication with my PC. Here is some background on my current project.

Arduino IDE 1.8.13
Arduino Leonardo
USB Host Shield (w/ USB Host Shield Library 2.0 installed, 5V & 3V,5V GRD soldered)
Mouse with 2 side buttons (Razer Deathadder Essential to be specific)
Here is the setup:

I coded a sketch to draw a different pattern on the screen whenever I pressed the corresponding button with my mouse (Left & right click + mouse 4 & 5). With the USB Host Shield, the movement and click on the mouse can be sent to Leonardo directly. The functionality has no issue at all. The thing is I used to be able to move my mouse via USB Host Shield and perform the desired action on both my home laptop and desktop at work.

But all of a sudden the mouse couldn't respond on my home laptop. I didn't change my sketch at all, therefore I have no idea what could go wrong. And the Leonardo is still working normally as I can view the real-time response on the serial monitor with Serial.println(). It was just the mouse was not moving at all, and not responding to clicks.

Tried to re-install usbser.sys driver in Windows, and update the Arduino driver of Leonardo on Device Manager. Still couldn't fix it.

Suspected it could be a power supply issue, but I tried to connect it with a 12V-5A power supply, but still no effect.

Is there something wrong with my driver? Or protocol of USB communication? Is there anything recommended for me to try to solve the problem?

Does the Serial.begin(115200); need to match with my Leonardo's port setting in Device Manager (which is set to 9600)?

Here is my code for configuring the USB HID mouse and enabling the side button to be able to move and click my Razer mouse. All are in the same folder.

Main.ino

#include <SPI.h>
#include <usbhub.h>
#include "hidcustom.hpp"
#include "ImprovedMouse.h"
#include <hidboot.h>
USB Usb;
USBHub Hub(&Usb);
HIDBoot<USB_HID_PROTOCOL_MOUSE> HidMouse(&Usb);

MouseRptParser Prs;

void setup() {
  Serial.begin(115200);
  Serial.setTimeout(1);
  Usb.Init();
  HidMouse.SetReportParser(0, &Prs);
  Mouse.begin();
}

 void loop() {
  Usb.Task();
  drawSomething();
}

 void drawSomething() {
//draw something
}

ImprovedMouse.cpp

#include "ImprovedMouse.h"
 
static const uint8_t _hidMultiReportDescriptorMouse[] PROGMEM = {
    /*  Mouse relative */
    0x05, 0x01,               /* USAGE_PAGE (Generic Desktop)	  54 */
    0x09, 0x02,               /* USAGE (Mouse) */
    0xa1, 0x01,               /* COLLECTION (Application) */
    0x85, HID_REPORTID_MOUSE, /*     REPORT_ID */
 
    /* 8 Buttons */
    0x05, 0x09, /*     USAGE_PAGE (Button) */
    0x19, 0x01, /*     USAGE_MINIMUM (Button 1) */
    0x29, 0x08, /*     USAGE_MAXIMUM (Button 8) */
    0x15, 0x00, /*     LOGICAL_MINIMUM (0) */
    0x25, 0x01, /*     LOGICAL_MAXIMUM (1) */
    0x95, 0x08, /*     REPORT_COUNT (8) */
    0x75, 0x01, /*     REPORT_SIZE (1) */
    0x81, 0x02, /*     INPUT (Data,Var,Abs) */
 
    /* X, Y, Wheel */
    0x05, 0x01, /*     USAGE_PAGE (Generic Desktop) */
    0x09, 0x30, /*     USAGE (X) */
    0x09, 0x31, /*     USAGE (Y) */
    0x09, 0x38, /*     USAGE (Wheel) */
    0x15, 0x81, /*     LOGICAL_MINIMUM (-127) */
    0x25, 0x7f, /*     LOGICAL_MAXIMUM (127) */
    0x75, 0x08, /*     REPORT_SIZE (8) */
    0x95, 0x03, /*     REPORT_COUNT (3) */
    0x81, 0x06, /*     INPUT (Data,Var,Rel) */
 
    /* End */
    0xc0 /* END_COLLECTION */
};
 
Mouse_::Mouse_(void)
{
  static HIDSubDescriptor node(_hidMultiReportDescriptorMouse, sizeof(_hidMultiReportDescriptorMouse));
  HID().AppendDescriptor(&node);
}
 
void Mouse_::begin(void)
{
  end();
}
 
void Mouse_::end(void)
{
  _buttons = 0;
  move(0, 0, 0);
}
 
void Mouse_::click(uint8_t b)
{
  _buttons = b;
  move(0, 0, 0);
  _buttons = 0;
  move(0, 0, 0);
}
 
void Mouse_::move(signed char x, signed char y, signed char wheel)
{
  HID_MouseReport_Data_t report;
  report.buttons = _buttons;
  report.xAxis = x;
  report.yAxis = y;
  report.wheel = wheel;
  SendReport(&report, sizeof(report));
}
 
void Mouse_::buttons(uint8_t b)
{
  if (b != _buttons)
  {
    _buttons = b;
    move(0, 0, 0);
  }
}
 
void Mouse_::press(uint8_t b)
{
  buttons(_buttons | b);
}
 
void Mouse_::release(uint8_t b)
{
  buttons(_buttons & ~b);
}
 
void Mouse_::releaseAll(void)
{
  _buttons = 0;
  move(0, 0, 0);
}
 
bool Mouse_::isPressed(uint8_t b)
{
  if ((b & _buttons) > 0)
    return true;
  return false;
}
 
void Mouse_::SendReport(void *data, int length)
{
  HID().SendReport(HID_REPORTID_MOUSE, data, length);
}

Mouse_ Mouse;

ImprovedMouse.h

#pragma once

#define HID_REPORTID_NONE 0

#ifndef HID_REPORTID_MOUSE
#define HID_REPORTID_MOUSE 1
#endif

#ifndef HID_REPORTID_KEYBOARD
#define HID_REPORTID_KEYBOARD 2
#endif

#ifndef HID_REPORTID_RAWHID

#endif

#ifndef HID_REPORTID_CONSUMERCONTROL
#define HID_REPORTID_CONSUMERCONTROL 4
#endif

#ifndef HID_REPORTID_SYSTEMCONTROL
#define HID_REPORTID_SYSTEMCONTROL 5
#endif

#ifndef HID_REPORTID_GAMEPAD
#define HID_REPORTID_GAMEPAD 6
#endif

#ifndef HID_REPORTID_MOUSE_ABSOLUTE
#define HID_REPORTID_MOUSE_ABSOLUTE 7
#endif

#ifndef HID_REPORTID_NKRO_KEYBOARD
#define HID_REPORTID_NKRO_KEYBOARD 8
#endif

#ifndef HID_REPORTID_TEENSY_KEYBOARD
#define HID_REPORTID_TEENSY_KEYBOARD 9
#endif

#ifndef HID_REPORTID_SURFACEDIAL
#define HID_REPORTID_SURFACEDIAL 10
#endif

#if defined(ARDUINO_ARCH_AVR)

#define ATTRIBUTE_PACKED

#include "PluggableUSB.h"

#define EPTYPE_DESCRIPTOR_SIZE uint8_t

#elif defined(ARDUINO_ARCH_SAM)

#define ATTRIBUTE_PACKED __attribute__((packed, aligned(1)))

#include "USB/PluggableUSB.h"

#define EPTYPE_DESCRIPTOR_SIZE uint32_t
#define EP_TYPE_INTERRUPT_IN (UOTGHS_DEVEPTCFG_EPSIZE_512_BYTE | UOTGHS_DEVEPTCFG_EPDIR_IN | UOTGHS_DEVEPTCFG_EPTYPE_BLK | UOTGHS_DEVEPTCFG_EPBK_1_BANK | UOTGHS_DEVEPTCFG_NBTRANS_1_TRANS | UOTGHS_DEVEPTCFG_ALLOC)
#define EP_TYPE_INTERRUPT_OUT (UOTGHS_DEVEPTCFG_EPSIZE_512_BYTE | UOTGHS_DEVEPTCFG_EPTYPE_BLK | UOTGHS_DEVEPTCFG_EPBK_1_BANK | UOTGHS_DEVEPTCFG_NBTRANS_1_TRANS | UOTGHS_DEVEPTCFG_ALLOC)
#define USB_EP_SIZE EPX_SIZE
#define USB_SendControl USBD_SendControl
#define USB_Available USBD_Available
#define USB_Recv USBD_Recv
#define USB_Send USBD_Send
#define USB_Flush USBD_Flush

#elif defined(ARDUINO_ARCH_SAMD)

#define ATTRIBUTE_PACKED __attribute__((packed, aligned(1)))

#define USB_EP_SIZE EPX_SIZE
#define EP_TYPE_INTERRUPT_IN USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_IN(0);
#define EP_TYPE_INTERRUPT_OUT USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_OUT(0);

#if defined(ARDUINO_API_VERSION)
#include "api/PluggableUSB.h"
#define EPTYPE_DESCRIPTOR_SIZE unsigned int
#else
#include "USB/PluggableUSB.h"

#define EPTYPE_DESCRIPTOR_SIZE uint32_t

#define USB_Available USBDevice.available
#define USB_Recv USBDevice.recv
#define USB_RecvControl USBDevice.recvControl
#define USB_Send USBDevice.send
#define USB_Flush USBDevice.flush

int USB_SendControl(void *y, uint8_t z);
int USB_SendControl(uint8_t x, const void *y, uint8_t z);
#endif

#define TRANSFER_PGM 0
#define TRANSFER_RELEASE 0

#define HID_REPORT_TYPE_INPUT 1
#define HID_REPORT_TYPE_OUTPUT 2
#define HID_REPORT_TYPE_FEATURE 3

#else

#error "Unsupported architecture"

#endif

#include <HID.h>

#define MOUSE_LEFT (1 << 0)
#define MOUSE_RIGHT (1 << 1)
#define MOUSE_MIDDLE (1 << 2)
#define MOUSE_PREV (1 << 3)
#define MOUSE_NEXT (1 << 4)

#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE | MOUSE_PREV | MOUSE_NEXT)

typedef union ATTRIBUTE_PACKED {
  // Mouse report: 8 buttons, position, wheel
  uint8_t whole8[0];
  uint16_t whole16[0];
  uint32_t whole32[0];
  struct ATTRIBUTE_PACKED {
    uint8_t buttons;
    int8_t xAxis;
    int8_t yAxis;
    int8_t wheel;
  };
} HID_MouseReport_Data_t;

typedef union ATTRIBUTE_PACKED {
  // BootMouse report: 3 buttons, position
  // Wheel is not supported by boot protocol
  uint8_t whole8[0];
  uint16_t whole16[0];
  uint32_t whole32[0];
  struct ATTRIBUTE_PACKED {
    uint8_t buttons;
    int8_t xAxis;
    int8_t yAxis;
  };
} HID_BootMouseReport_Data_t;

class Mouse_ {
public:
  Mouse_(void);
  void begin(void);
  void end(void);
  void click(uint8_t b = MOUSE_LEFT);
  void move(signed char x, signed char y, signed char wheel = 0);
  void press(uint8_t b = MOUSE_LEFT);
  void release(uint8_t b = MOUSE_LEFT);
  void releaseAll(void);
  bool isPressed(uint8_t b = MOUSE_LEFT);
  void buttons(uint8_t b);
  void SendReport(void *data, int length);

protected:
  uint8_t _buttons;
};
extern Mouse_ Mouse;

hidcustom.hpp

#include <hidboot.h>
#include "ImprovedMouse.h"
 
class MouseRptParser : public MouseReportParser
{
protected:
  void Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf)
  {
    Mouse.buttons(buf[0]);
    Mouse.move(buf[1], buf[2], buf[3]);
  }
};

Appreciate all the help Arduino community! Cheers.


My setup

I used the USB Host Shield to capture the input (mouse click) from my mouse and the Arduino Leonardo can react to the action and send out the output towards the PC (mouse move) automatically. It functions normally without an issue with my desktop, but when I try to plug it into my laptop, it no longer works. Couldn't move the mouse at all. The mouse is being powered as I can see it lights up normally when I plug it in.

Is it because of the USB port difference? (laptop: SS, desktop: SS-5) Can I solve it by using micro-to-type C and connecting it using the type C port of my laptop? (it is SS-10).

Or the driver issue so the laptop is not working the same way the desktop does?

I am sure that the HID descriptor is correctly constructed.

Thanks in advance.

I've merged your two topics on the same subject. Please do not cross-post.

If people don't reply, it basically means that nobody knows the answer or is able to get you on the right track.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.