Howto receive data using HID

I successfully managed to send custom data from my Leonardo to a PC using the RAWHID part in the "HID.cpp". This way I don't have to install any drivers on the target computer at all.

Unfortunately I am running out of ideas how to get data back from my PC to the Arduino via HID. Does anyone have experience with this?

Maybe this will help.

Thank you. I know the LUFA library, but for my project I need to stick to most parts of the Arduino library AND use HID communication in both directions. Maybe I will just rewrite the entire USB part of the library using LUFA. :frowning:

hi,any progress?

I'm currently working on same thing.
from what I've gathered arduino hid decriptor is in place for both sending and receiving but deep inside
there are no hid endpoints for receiving data, only for sending.

look at USBCore.h

typedef struct 
{
	InterfaceDescriptor			hid;
	HIDDescDescriptor			desc;
	EndpointDescriptor			in;
} HIDDescriptor;

& USBDesc.h

#define HID_ENDPOINT_INT
...
#ifdef HID_ENABLED
#define HID_TX HID_ENDPOINT_INT
#endif

i will post if i manage to modify this to work as of now in arduino 1.6.0,
but will check what's up with 1.6.1 first.

nothing has changed in 1.6.1

I DID IT!!

atm i have arduino working as usb gamepad
and RAWHID

im sending 64 bytes via SimpleHIDWrite.exe
on arduino im sending same data back and setting X,Y,Z axis with data from bytes 0,1,2.

and its working.

i will post details tomorrow.
it's pretty late i'm tired.

1 Like

ok where do i start. 8)

Legend
//** modifided line
//++ added line

Arduino\hardware\arduino\avr\cores\arduino\USBCore.h ~~line 273++ near end

...
typedef struct 
{
	InterfaceDescriptor			hid;
	HIDDescDescriptor			desc;
	EndpointDescriptor			in;
	EndpointDescriptor			out;		//++
} HIDDescriptor;

...
#define D_HIDREPORT(_descriptorLength) \
	{ 9, 0x21, 0x11, 0x1, 0, 1, 0x22, _descriptorLength, 0 }   //**  3rd byte from 0x1 to 0x11  for hid 1.11

Arduino\hardware\arduino\avr\cores\arduino\USBCore.cpp

line 82:
//	DEVICE DESCRIPTOR
const DeviceDescriptor USB_DeviceDescriptor =
	D_DEVICE(0xEF,DEVICE_SUBCLASS,DEVICE_PROTO,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1);  //** D_DEVICE (bDeviceClass  EFh Miscellaneous ;bDeviceSubClass 02h Common Class , DEVICE_PROTO

const DeviceDescriptor USB_DeviceDescriptorA =
	D_DEVICE(DEVICE_CLASS,DEVICE_SUBCLASS,DEVICE_PROTO,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1); //**
/*
....
line ~320:

extern const u8 _initEndpoints[] PROGMEM;
const u8 _initEndpoints[] = 
{
	0,
	
#ifdef CDC_ENABLED
	EP_TYPE_INTERRUPT_IN,		// CDC_ENDPOINT_ACM
	EP_TYPE_BULK_OUT,			// CDC_ENDPOINT_OUT
	EP_TYPE_BULK_IN,			// CDC_ENDPOINT_IN
#endif

#ifdef HID_ENABLED
	EP_TYPE_INTERRUPT_IN,		// HID_ENDPOINT_INT
	EP_TYPE_INTERRUPT_OUT		// HID_ENDPOINT_INT  //++ HID_RX endpoint interrupt
#endif
};

Arduino\hardware\arduino\avr\cores\arduino\USBDesc.h

#define CDC_ENABLED
#define HID_ENABLED


#ifdef CDC_ENABLED
#define CDC_INTERFACE_COUNT	2
#define CDC_ENPOINT_COUNT	3
#else
#define CDC_INTERFACE_COUNT	0
#define CDC_ENPOINT_COUNT	0
#endif

#ifdef HID_ENABLED
#define HID_INTERFACE_COUNT	1
#define HID_ENPOINT_COUNT	2      //**  modified was 1
#else
#define HID_INTERFACE_COUNT	0
#define HID_ENPOINT_COUNT	0
#endif

#define CDC_ACM_INTERFACE	0	// CDC ACM
#define CDC_DATA_INTERFACE	1	// CDC Data
#define CDC_FIRST_ENDPOINT	1
#define CDC_ENDPOINT_ACM	(CDC_FIRST_ENDPOINT)							// CDC First
#define CDC_ENDPOINT_OUT	(CDC_FIRST_ENDPOINT+1)
#define CDC_ENDPOINT_IN		(CDC_FIRST_ENDPOINT+2)

#define HID_INTERFACE		(CDC_ACM_INTERFACE + CDC_INTERFACE_COUNT)		// HID Interface
#define HID_FIRST_ENDPOINT	(CDC_FIRST_ENDPOINT + CDC_ENPOINT_COUNT)
#define HID_ENDPOINT_INT	(HID_FIRST_ENDPOINT)
#define HID_ENDPOINT_OUT	(HID_FIRST_ENDPOINT+1)   //++  new endpoint 

#define INTERFACE_COUNT		(MSC_INTERFACE + MSC_INTERFACE_COUNT)

#ifdef CDC_ENABLED
#define CDC_RX CDC_ENDPOINT_OUT
#define CDC_TX CDC_ENDPOINT_IN
#endif

#ifdef HID_ENABLED
#define HID_TX HID_ENDPOINT_INT
#define HID_RX HID_ENDPOINT_OUT     //++ EP  HID_RX for ease of use with USB_Available & USB_Recv
#endif

#define IMANUFACTURER	1
#define IPRODUCT		2

Arduino\hardware\arduino\avr\cores\arduino\HID.h

...

#define RAWHID_ENABLED //++  added after #ifdef HID_ENABLED
..
#define RAWHID_TX_SIZE 63 //** normally 64 but i changed that to 63 because raportID is the 1st byte of transmision, max packet size is 64 and i wanted it to stay in 1 packet
#define RAWHID_RX_SIZE 63
//

mine rawhid portion of descryptor, i don't know if it changed much, after playing around with it, i chose raportID 9 for it

#ifdef RAWHID_ENABLED
	//	RAW HID

	
 	0x06, LSB(RAWHID_USAGE_PAGE), MSB(RAWHID_USAGE_PAGE),	// 30
	0x0A, LSB(RAWHID_USAGE), MSB(RAWHID_USAGE),
	
	0xA1, 0x01,				// Collection 0x01
		0x85, 0x09,				// report id
		0x75, 0x08,				// report size = 8 bits
		0x15, 0x00,				// logical minimum = 0
		0x26, 0xFF, 0x00,			// logical maximum = 255
		0x95, RAWHID_TX_SIZE,			// report count
		0x09, 0x01,				// usage
		0x81, 0x02,				// Input (array)
		0x95, RAWHID_RX_SIZE,			// report count
		0x09, 0x02,				// usage
		0x91, 0x02,				// Output (array)
	0xC0					// end collection
#endif

shortly after this is :

extern const HIDDescriptor _hidInterface PROGMEM;
const HIDDescriptor _hidInterface =
{
	D_INTERFACE(HID_INTERFACE,2,3,0,0), //** 2 corresponds to #of endpoints was 1
	D_HIDREPORT(sizeof(_hidReportDescriptor)),
	D_ENDPOINT(USB_ENDPOINT_IN (HID_TX),USB_ENDPOINT_TYPE_INTERRUPT,0x40,0x02),
	D_ENDPOINT(USB_ENDPOINT_OUT(HID_RX),USB_ENDPOINT_TYPE_INTERRUPT,0x40,0x08), //++ filling up with receiving endpoint
};

and now the sketch portion

void loop() {

	 uint8_t raw[63]={0};
	 if (USB_Available(HID_RX))         //anything out there???
	 {
		 Serial.print("USB_Available\t"); Serial.println(USB_Available(HID_RX));

		 uint8_t raportID=0;
		 USB_Recv(HID_RX,&raportID,1); // get that raportID of the Recv buff
		 USB_Recv(HID_RX,&raw,63);     //now we have our data

		 raw[3]=random(0xff);          //do whatever to data or not 
		 HID_SendReport(9,&raw,63); // send back report or not, do whatever // 9 is raportID must correspond with hid descriptor
	 }
	delay(50);
}

i was using SimpleHIDWrite.exe for testing

1 Like

Thanks for this -- working on getting this going. In the meantime, the file you identified as Arduino\hardware\arduino\avr\cores\arduino\HID.h is actually HID.cpp.

Also, I'm not sure about DEVICE_CLASS, DEVICE_SUBCLASS and DEVICE_PROTO - what should they be defined as? They don't seem to be defined anywhere.

Assuming the idea was to define USB_DeviceDescriptorA as the RAW HID device, I've started with this, just before declaring the device descriptors:

#ifdef RAWHID_ENABLED
#define DEVICE_CLASS 0x02
#define DEVICE_SUBCLASS 0x00
#define DEVICE_PROTO 0x00
#elif defined(CDC_ENABLED)
#define DEVICE_CLASS 0x03
#define DEVICE_SUBCLASS 0x00
#define DEVICE_PROTO 0x00
#else
#define DEVICE_CLASS 0x00
#define DEVICE_SUBCLASS 0x00
#define DEVICE_PROTO 0x00
#endif

which disables CDC mode, so I can't upload with out a hard reset of the micro controller, or look at the serial output...so I think I missed something here.

Thanks!

Matt