Reputation: 1
So im trying to change the polling rate of my mouse. it has a web based driver that probably runs some kind of javascript to send control transfer requests to the mouse firmware (i know nothing about web drivers).
When I dump the requests sent by the driver with WireShark, we can see that the driver sends 3 control transfer requests upon changing the polling rate in the web software, two SET_REPORT requests and one GET_REPORT request. here are the dumps:
first request from driver
Frame 1617: 100 bytes on wire (800 bits), 100 bytes captured (800 bits)
USB URB
[Source: host]
[Destination: 2.4.0]
USBPcap pseudoheader length: 28
IRP ID: 0xffffd08bf1d322d0
IRP USBD_STATUS: USBD_STATUS_SUCCESS (0x00000000)
URB Function: URB_FUNCTION_CLASS_INTERFACE (0x001b)
IRP information: 0x00, Direction: FDO -> PDO
URB bus id: 2
Device address: 4
Endpoint: 0x00, Direction: OUT
URB transfer type: URB_CONTROL (0x02)
Packet Data Length: 72
[Response in: 1618]
Control transfer stage: Setup (0)
[bInterfaceClass: HID (0x03)]
Setup Data
bmRequestType: 0x21
0... .... = Direction: Host-to-device
.01. .... = Type: Class (0x1)
...0 0001 = Recipient: Interface (0x01)
bRequest: SET_REPORT (0x09)
wValue: 0x0300
ReportID: 0
ReportType: Feature (3)
wIndex: 2
wLength: 64
Data Fragment: f7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
second request from driver
Frame 1619: 36 bytes on wire (288 bits), 36 bytes captured (288 bits)
USB URB
[Source: host]
[Destination: 2.4.0]
USBPcap pseudoheader length: 28
IRP ID: 0xffffd08bf9527810
IRP USBD_STATUS: USBD_STATUS_SUCCESS (0x00000000)
URB Function: URB_FUNCTION_CLASS_INTERFACE (0x001b)
IRP information: 0x00, Direction: FDO -> PDO
URB bus id: 2
Device address: 4
Endpoint: 0x80, Direction: IN
URB transfer type: URB_CONTROL (0x02)
Packet Data Length: 8
[Response in: 1620]
Control transfer stage: Setup (0)
[bInterfaceClass: HID (0x03)]
Setup Data
bmRequestType: 0xa1
1... .... = Direction: Device-to-host
.01. .... = Type: Class (0x1)
...0 0001 = Recipient: Interface (0x01)
bRequest: GET_REPORT (0x01)
wValue: 0x0300
ReportID: 0
ReportType: Feature (3)
wIndex: 2
wLength: 64
third request from driver (this is the request that actually changes the polling rate, bit 10 changes depending on chosen polling rate in the web software for the mouse)
Frame 1621: 100 bytes on wire (800 bits), 100 bytes captured (800 bits)
USB URB
[Source: host]
[Destination: 2.4.0]
USBPcap pseudoheader length: 28
IRP ID: 0xffffd08bf1d322d0
IRP USBD_STATUS: USBD_STATUS_SUCCESS (0x00000000)
URB Function: URB_FUNCTION_CLASS_INTERFACE (0x001b)
IRP information: 0x00, Direction: FDO -> PDO
URB bus id: 2
Device address: 4
Endpoint: 0x00, Direction: OUT
URB transfer type: URB_CONTROL (0x02)
Packet Data Length: 72
[Response in: 1622]
Control transfer stage: Setup (0)
[bInterfaceClass: HID (0x03)]
Setup Data
bmRequestType: 0x21
0... .... = Direction: Host-to-device
.01. .... = Type: Class (0x1)
...0 0001 = Recipient: Interface (0x01)
bRequest: SET_REPORT (0x09)
wValue: 0x0300
ReportID: 0
ReportType: Feature (3)
wIndex: 2
wLength: 64
Data Fragment:
53000000000000ac0082010000000101010000000000000003030407000000000000000000000000000000000000000000006464010000000000000000000000
I made it easy for myself and choose to use libusb for sending the control requests. My current code looks like this:
...........
libusb_context* ctx = nullptr;
libusb_device_handle* handle = nullptr;
int r;
// Initialize the libusb context
r = libusb_init(&ctx);
if (r < 0) {
std::cerr << "Failed to initialize libusb: " << libusb_error_name(r) << std::endl;
return EXIT_FAILURE;
}
// Open the USB device with specified Vendor ID and Product ID
handle = libusb_open_device_with_vid_pid(ctx, VENDOR_ID, PRODUCT_ID);
if (!handle) {
std::cerr << "Error finding USB device" << std::endl;
libusb_exit(ctx);
return EXIT_FAILURE;
}
// Claim the interface (assuming the interface number is 2)
r = libusb_claim_interface(handle, 2); // Change to your device's interface number
if (r < 0) {
std::cerr << "Error claiming interface: " << libusb_error_name(r) << std::endl;
libusb_close(handle);
libusb_exit(ctx);
return EXIT_FAILURE;
}
unsigned char pre_data[64] = {
0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
//change polling rate data
unsigned char data[64] = {
0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0xac, 0x00,
0x82, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
0x03, 0x04, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x64, 0x64, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
unsigned char read_data[64];
// Perform the control transfer
r = libusb_control_transfer(handle,
0x21, // bmRequestType: Host-to-device, Class, Interface
0x09, // bRequest: SET_REPORT
0x0300, // wValue: Report Type (Feature) | Report ID (0)
2, // wIndex: Target Interface (2)
pre_data, // Data buffer
sizeof(pre_data), // wLength: Size of the data buffer (64)
TIMEOUT); // Timeout
if (r < 0) {
std::cerr << "Error sending control request: " << libusb_error_name(r) << std::endl;
}
else {
std::cout << "Control transfer sent successfully (" << r << " bytes)" << std::endl;
}
r = libusb_control_transfer(handle,
0xa1, // bmRequestType: Device-to-host, Class, Interface
0x01, // bRequest: GET_REPORT
0x0300, // wValue: Report Type (Feature) | Report ID (0)
2, // wIndex: Target Interface (2)
read_data, // Data buffer to receive data
sizeof(read_data), // wLength: Size of the data buffer (64)
TIMEOUT); // Timeout
if (r < 0) {
std::cerr << "Error sending control request: " << libusb_error_name(r) << std::endl;
}
else {
std::cout << "Control transfer sent successfully (" << r << " bytes)" << std::endl;
}
// Display the received data
for (int i = 0; i < r; i++) {
printf("%02x ", read_data[i]);
}
printf("\n");
// Send the SET_REPORT control transfer
r = libusb_control_transfer(handle,
0x21, // bmRequestType: Host-to-device, Class, Interface
0x09, // bRequest: SET_REPORT
0x0300, // wValue: Report Type (Feature) | Report ID (0)
2, // wIndex: Target Interface (2)
data, // Data buffer
sizeof(data), // wLength: Size of the data buffer
TIMEOUT); // Timeout
if (r < 0) {
std::cerr << "Error sending control request: " << libusb_error_name(r) << std::endl;
}
else {
std::cout << "Control transfer sent successfully (" << r << " bytes)" << std::endl;
}
// Release the interface and close the device
libusb_release_interface(handle, 2); // Change to your device's interface number
libusb_close(handle);
libusb_exit(ctx);
...........
The transfers get sent successfully but bricks my mouse(mouse clicks does not work but movement/sensor does).
Is it the report data that is wrong? converted the hex-string data fragment from the WireShark dumps. Any ideas?
Upvotes: 0
Views: 8