[solved] Unable to receive HID reports from computer using pluggableUSB

Hello!

I'm trying to receive HID reports from my computer to my arduino micro, I made my own library that was modeled off of the CDC (Serial), MIDI, and HID-Project libraries. But whenever I call USB_Available, it always returns 0.

I'm using the "SimpleHIDWrite" tool to write data, but when I press write, it says "WRITE ERROR: A device attached to the system is not functioning (1F)." But strangely enough, whenever I press it the RX light blinks, which makes me think that the endpoints are not configured correctly.

Any help is appreciated!

Arandom"dev"

USBController.cpp (2.38 KB)

USBController.h (2.41 KB)

SerialCommsv4.ino (232 Bytes)

I found the problem, apparently switching the out endpoint from type bulk to interrupt fixed it!

Here's the code with the fix.

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;
	}
}

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

sketch

#include <USBController.h>

USBController controller;
void setup(){
  Serial.begin(9600);
}

void loop(){
  int recv = controller.read();
  if (recv != 0) {
    Serial.println(recv);
  }
}