OpenRetroPad/src/gamepad/USB-Gamepad/UsbGamepad.h

132 lines
3.3 KiB
C++

#ifndef USB_GAMEPAD_H
#define USB_GAMEPAD_H
#include <WString.h>
#include "../common.h"
#include "HID.h"
// ATT: 20 chars max (including NULL at the end) according to Arduino source code.
// Additionally serial number is used to differentiate arduino projects to have different button maps!
const char* gp_serial = "SF30 Pro";
class Gamepad_ : public PluggableUSBModule {
private:
uint8_t reportId;
protected:
uint8_t epType[1];
uint8_t protocol;
uint8_t idle;
/*
int getInterface(uint8_t* interfaceCount);
int getDescriptor(USBSetup& setup);
uint8_t getShortName(char *name);
bool setup(USBSetup& setup);
*/
int getInterface(uint8_t* interfaceCount) {
*interfaceCount += 1; // uses 1
HIDDescriptor hidInterface = {D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE),
D_HIDREPORT(sizeof(_hidReportDescriptor)),
D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01)};
return USB_SendControl(0, &hidInterface, sizeof(hidInterface));
}
int getDescriptor(USBSetup& setup) {
// Check if this 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;
}
// Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol
// due to the USB specs, but Windows and Linux just assumes its in report mode.
protocol = HID_REPORT_PROTOCOL;
return USB_SendControl(TRANSFER_PGM, _hidReportDescriptor, sizeof(_hidReportDescriptor));
}
bool setup(USBSetup& setup) {
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;
}
uint8_t getShortName(char* name) {
if (!next) {
strcpy(name, gp_serial);
return strlen(name);
}
return 0;
}
public:
Gamepad_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1) {
epType[0] = EP_TYPE_INTERRUPT_IN;
PluggableUSB().plug(this);
}
void send(const void* d, int len) {
USB_Send(pluggedEndpoint | TRANSFER_RELEASE, d, len);
}
};
class UsbGamepad : public AbstractGamepad {
public:
String deviceManufacturer;
String deviceName;
Gamepad_ gamepad[GAMEPAD_COUNT];
UsbGamepad(String deviceName = "8BitDo SN30 Pro+", String deviceManufacturer = "8Bitdo SF30 Pro") : AbstractGamepad() {
this->deviceName = deviceName;
this->deviceManufacturer = deviceManufacturer;
}
void sync(const uint8_t cIdx) {
gamepad[cIdx].send(&gamepadReport, GAMEPAD_REPORT_LEN);
}
};
typedef UsbGamepad Gamepad;
#endif // USB_GAMEPAD_H