Receiving 2 integers or bytes at same time HID

I’m using a library called USBController.h that basically allows me to read data being sent through the HID protocol. The problem is that I can’t figure out a way to read 2 values at the same time. There is no documentation of the library since it was created by a random guy a couple of years back.

I’m using this code to read the data but it seems like it can only read 1 of the bytes I’m sending.

void loop(){
  int recv = controller.read();
  if (recv != 0){
    Mouse.move(recv, 0, 0);
  }
}

I’m trying to have it read 2 bytes then it does

Mouse.move(recv[0], recv[1], 0);

Basically I’m trying to send data through python to where the mouse should move then use the mouse library to move the mouse, this can be moving the mouse up or down as well as to the sides but when im only able to read 1 byte then it’s impossible.

Can anyone who knows of this USBController library maybe tell me if there is a way to read multiple bytes or maybe can somebody who knows how to do this stuff modify the files so it’s able to read multiple bytes. I don’t know too much about arduino programming so I don’t really know what to do now I’m kinda stuck and can’t continue my project I’m working on.

Thanks in advance if anyone is able to help me :pray:.

This suggests that to get two values, you need to read() twice. But of course, those would not be nsynchronized with the sender, so you would have no idea which byte is which, or even if the two bytes are relevant.

For better informed help, post a link to the code you found.

1 Like

By the way I forgot to mention I’m unable to use serial communication and the files for USBController library are:

USBController.h


#ifndef USBController_h
#define USBController_h
#include "Arduino.h"

// make sure that it is a supported Architecture
#ifndef ARDUINO_ARCH_AVR
#error "Unsupported Architecture"
#endif

#include "PluggableUSB.h"
#include "HID.h"

#define USBController_D_HIDREPORT(length) { 9, 0x21, 0x11, 0x01, 0, 1, 0x22, lowByte(length), highByte(length) }
typedef struct {
	InterfaceDescriptor hid;
  HIDDescDescriptor desc;
  EndpointDescriptor in;
	EndpointDescriptor out;
} USBControllerHIDDescriptor;
typedef union {
	uint8_t dataInHeader[0];
	uint8_t dataInBlock[0];
	uint8_t dataOutHeader[0];
	uint8_t dataOutBlock[0];
	struct {
		uint8_t dataIn;
		uint8_t dataOut;
	};
} USBControllerDataPacket;

static const uint8_t USBControllerReportDescriptor[] PROGMEM = {
	0x06, 0x00, 0xff,              // USAGE_PAGE (vendor defined page 1)
	0x09, 0x00,                    // USAGE (Undefined)
	0xa1, 0x01,                    // COLLECTION (Application)
	0x85, 0x01,                    //   REPORT_ID (1)
	0x09, 0x00,                    //   USAGE (Undefined)
	0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
	0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM (255)
	0x75, 0x08,                    //   REPORT_SIZE (8)
	0x95, 0x01,                    //   REPORT_COUNT (1)
	0x81, 0x06,                    //   INPUT (Data,Var,Rel)
	0x85, 0x02,                    //   REPORT_ID (2)
	0x09, 0x00,                    //   USAGE (Undefined)
	0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
	0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM (255)
	0x75, 0x08,                    //   REPORT_SIZE (8)
	0x95, 0x01,                    //   REPORT_COUNT (1)
	0x91, 0x06,                    //   OUTPUT (Data,Var,Rel)
	0xc0                           // END_COLLECTION
};

#define USBControllerInterface pluggedInterface
#define USBControllerEndpointIn pluggedEndpoint
#define USBControllerEndpointOut (pluggedEndpoint + 1)
#define USBControllerTX USBControllerEndpointIn
#define USBControllerRX USBControllerEndpointOut

class USBController : public PluggableUSBModule {
public:
	USBController();
	int write(const uint8_t *buffer, size_t size);
	int read();
private:

protected:
	uint8_t endpointTypes[2];
	uint8_t protocol;
	uint8_t idle;

	int getInterface(uint8_t *interfaceNumber);
	int getDescriptor(USBSetup &setup);
	bool setup(USBSetup &setup);
};

#endif // USBController_h import guard

USBController.cpp


#include "USBController.h"
#include "Arduino.h"

USBController::USBController() : PluggableUSBModule(2, 1, endpointTypes) {
	endpointTypes[0] = EP_TYPE_BULK_IN;
	endpointTypes[1] = EP_TYPE_INTERRUPT_OUT;
	PluggableUSB().plug(this);
}

int USBController::getInterface(uint8_t *interfaceNumber) {
	interfaceNumber[0] += 1;
	USBControllerHIDDescriptor interfaceDescriptor = {
		D_INTERFACE(USBControllerInterface, 2, USB_DEVICE_CLASS_HUMAN_INTERFACE, 0, 0),
		USBController_D_HIDREPORT(sizeof(USBControllerReportDescriptor)),
		D_ENDPOINT(USB_ENDPOINT_IN(USBControllerEndpointIn), USB_ENDPOINT_TYPE_BULK, USB_EP_SIZE, 0),
		D_ENDPOINT(USB_ENDPOINT_OUT(USBControllerEndpointOut), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0),
	};
	return USB_SendControl(0, &interfaceDescriptor, sizeof(interfaceDescriptor));
}

int USBController::getDescriptor(USBSetup &setup) {
	// code copied and modified from NicoHood's HID-Project
	// check if it is a HID class Descriptor request
	if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { return 0; }
	if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { return 0; }

	// In a HID Class Descriptor wIndex cointains the interface number
	if (setup.wIndex != pluggedInterface) { return 0; }

	protocol = HID_REPORT_PROTOCOL;

	return USB_SendControl(TRANSFER_PGM, USBControllerReportDescriptor, sizeof(USBControllerReportDescriptor));
}

bool USBController::setup(USBSetup &setup) {
	// code copied from NicoHood's HID-Project
	if (pluggedInterface != setup.wIndex) {
		return false;
	}

	uint8_t request = setup.bRequest;
	uint8_t requestType = setup.bmRequestType;

	if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE)
	{
		if (request == HID_GET_REPORT) {
			// TODO: HID_GetReport();
			return true;
		}
		if (request == HID_GET_PROTOCOL) {
			// TODO: Send8(protocol);
			return true;
		}
	}

	if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE)
	{
		if (request == HID_SET_PROTOCOL) {
			protocol = setup.wValueL;
			return true;
		}
		if (request == HID_SET_IDLE) {
			idle = setup.wValueL;
			return true;
		}
		if (request == HID_SET_REPORT)
		{
		}
	}

	return false;
}

int USBController::write(const uint8_t *buffer, size_t size) {
	return USB_Send(USBControllerTX, buffer, size);
}

int USBController::read() {
	if (USB_Available(USBControllerRX)) {
		return USB_Recv(USBControllerRX);
	}
	else {
		return 0;
	}
}

Yes I understand that it’s a way I can do it but as you said it would be hard to know which byte is which and also it would be faster if it’s possible to read both at same time, thx for reply.

It would probably be informative to research the message format that the mouse uses to send data through the USB bus.

The message format used in the old serial port mouse is described in complete detail.

yep, only 1 byte as output in this descriptor

maybe you can change

0x75, 0x10,                    //   REPORT_SIZE (16)

and then

void loop(){
  int recv = controller.read();
byte X=recv & 0xff;
byte Y=(recv>>8) & 0xff;
  if (X != 0 && Y != 0){
    Mouse.move(recv, X, Y);
  }
}

Thx for trying to help. What do you mean change? I tried to change the 0x75, 0x08, to 0x75, 0x10, but that didnt work, I also tried to add another line after 0x75, 0x08, that was 0x75, 0x10, but that didnt work either. I did however see that when I changed to 0x75, 0x10, from 0x75, 0x08, that my buffer im sending the program needed to be 2 bytes instead of 3, I also tried changing the

0x95, 0x01,                    //   REPORT_COUNT (1)
//TO
0x95, 0x02,                    //   REPORT_COUNT (2)

and that made my program need 5 bytes in my buffer but I still couldnt read both of them. Maybe the problem is in here

  int recv = controller.read();
byte X=recv & 0xff;
byte Y=(recv>>8) & 0xff;

since im able to send more bytes but not read them. Again, thx for the reply.

Also I just saw that when im using this code

  int recv = controller.read();
byte X=recv & 0xff;
byte Y=(recv>>8) & 0xff;

it cant use either X or Y (both of them just move 0 pixels) to move but it can use recv still. Maybe it gets the bytes but sees them both as 0.

in many cases it helps to give an overview about the whole project.
Reading two bytes via HID-commands is not a self-purpose.

What is the final purpose of your project?
If all the details and circumstances are known usually a lot of more suggestions can be made.

Does this mean that the python code runs on a windows computer?
Do you want to move the mouse on a windows computer?
If yes there are a lot of more options to achieve this.

That is the reason why you should give an overview about your project and the final purpose of moving the mouse.

best regards Stefan

Hi Stefan. Basically im using python to detect objects on the screen using AI, then im calculating the x and y coordinates of where the mouse would be needed to move to get to those objects. Then im sending those cordiantes to the arduino leonardo with HID so it can move the mouse for me (using the Mouse.h library). I understand that its possible to use other ways like serial communication or even simple python modules, but im really trying to get it to work with HID and arduino, mostly for learning.

I don't believe that the x and y values you pass in move() correspond to pixel values. Mouse sensitivity and acceleration changes from computer to computer.

If you want to go ahead using this library, I imagine that you might need to repeatedly call move(), checking (with python) how far the cursor has moved. If this is the case, there is no reason to worry about sending a 2 byte value: just send multiple 1 byte values.

Alternatively, you may be interested in the absmouse library.
AbsMouse.move(500, 500) should move your cursor to x: 500, y: 500 on screen.
Disclaimer: I haven't tested this.

Im having a screen capture running and letting my python script constantly analyze where it should move to frame by frame. Then im sending only x and y values consisting of only 1, 2 and 3 (depending on how fast I want the arduino to move cursor) to the arduino Mouse.move function. Im trying to make it move smoothly almost like a human would not just instantly move to the correct place on the screen. Also, if I send only one byte at a time I cant really make the arduino "mouse" move smoothly and be able to make move on both the x and y axis.

Oh, so if I understand correctly, you are having difficulty sending 1 byte of x and 1 byte of y, simultaneously?

The issue is not with the official Mouse library you are using for output, it is with the USBController class, from unknowncheats.me.

As jremmington was getting at earlier, the data coming from controller.read() is not correctly formatted for Mouse.move().

The original version of the USBController class prints the data over serial. Someone on this other website was asking, last week, about how to swap out the Serial.print(recv) for Mouse.move().

Maybe you are making the same mistake as them?

I got it from my friend who helped me a little with this project. I just asked him and yes that seems to be the site he got the USBController library from. Although I think its the same as the "original". This is the real original of this HID USBController library: [solved] Unable to receive HID reports from computer using pluggableUSB. Do you know if there is any way though to make it receive 2 bytes to then use with Mouse.move();? I think the issue is on the controller.read(); though, I am able to read 1 byte and easily use that with Mouse.move(); but it seems like the original creator of the library didnt make it able to receive 2 bytes. Do you know if there is any bypass to this, maybe simply changing the USBController code like someone else suggested?

Maybe start out with using 'Serial.print()', like in the unmodified code, and look at it with the Serial monitor, to figure out how the data is formatted.

I disabled my arduino COM port so im unable to even open serial monitor right now.

Well maybe re-enable it for debugging.

I think I did something wrong while disabling it or something, I simply commented out a few lines of code from usbcore.cpp and I uncommented them now and uploaded new sketch but it still doesnt get back its com port, I remember also that when I first tested USBController and used Serial.print it just did as I thought it would, It printed the integer but with a 2 first (example: if I sent 88 through my program it would print 288). Dont know why it did that but it didnt affect anything when I tried using what I sent in a Mouse.move.

You should always keep original code as a copy for rolling back by picking the original file instead of re-re-modifying an existing file.

So try again with the original file new downloaded.

post your complete sketch for analysis

I downloaded this and replaced it with the modified one but I still dont get my COM port back when uploading sketches, maybe I just have to reinstall the IDE I guess.

Also this is the code sketch im trying to work with

#include <Mouse.h>
#include <USBController.h>

char command = '0';
int value = 0;

USBController controller;
void setup() {
  delay(3000); 
  Mouse.begin(); 
}

void loop() {
  int recv = controller.read();
  byte X = recv & 0xff;
  byte Y = (recv>>8) & 0xff;
  if (X != 0 && Y != 0){
    Mouse.move(X, Y, 0);
  }
}

This one is working

#include <Mouse.h>
#include <USBController.h>

char command = '0';
int value = 0;

USBController controller;
void setup() {
  delay(3000); 
  Mouse.begin(); 
}

void loop() {
  int recv = controller.read();
  if ((recv != 0)){
    Mouse.move(recv, 0, 0);
  }
}

but it only works for 1 byte so I can only move the mouse on either the x or y axis.

which one? descriptor have 2 places with it.