USB_Host_Shield_2.0/PS4USB.h
Kristian Sloth Lauszus e7a01565cd Use descriptor length in order to advance the buffer when parsing the descriptors
This caused an issue with the PS4 Slim controller, as the endpoint descriptor was two bytes longer on the PS4 slim controller when reading the audio interface

I suspect this is due to the fact that the audio interface (USB descriptor type 0x24) it is currently not supported by the library

This is similar to what is done in the example as well: cbea36f76f/examples/USB_desc/USB_desc.ino (L241)

Fixes issue #273
2017-01-31 00:07:13 +01:00

132 lines
4.8 KiB
C++

/* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved.
This software may be distributed and modified under the terms of the GNU
General Public License version 2 (GPL2) as published by the Free Software
Foundation and appearing in the file GPL2.TXT included in the packaging of
this file. Please note that GPL2 Section 2[b] requires that all works based
on this software must also be made publicly available under the terms of
the GPL2 ("Copyleft").
Contact information
-------------------
Kristian Lauszus, TKJ Electronics
Web : http://www.tkjelectronics.com
e-mail : kristianl@tkjelectronics.com
*/
#ifndef _ps4usb_h_
#define _ps4usb_h_
#include "hiduniversal.h"
#include "PS4Parser.h"
#define PS4_VID 0x054C // Sony Corporation
#define PS4_PID 0x05C4 // PS4 Controller
#define PS4_PID_SLIM 0x09CC // PS4 Slim Controller
/**
* This class implements support for the PS4 controller via USB.
* It uses the HIDUniversal class for all the USB communication.
*/
class PS4USB : public HIDUniversal, public PS4Parser {
public:
/**
* Constructor for the PS4USB class.
* @param p Pointer to the USB class instance.
*/
PS4USB(USB *p) :
HIDUniversal(p) {
PS4Parser::Reset();
};
/**
* Used to check if a PS4 controller is connected.
* @return Returns true if it is connected.
*/
bool connected() {
return HIDUniversal::isReady() && HIDUniversal::VID == PS4_VID && (HIDUniversal::PID == PS4_PID || HIDUniversal::PID == PS4_PID_SLIM);
};
/**
* Used to call your own function when the device is successfully initialized.
* @param funcOnInit Function to call.
*/
void attachOnInit(void (*funcOnInit)(void)) {
pFuncOnInit = funcOnInit;
};
protected:
/** @name HIDUniversal implementation */
/**
* Used to parse USB HID data.
* @param hid Pointer to the HID class.
* @param is_rpt_id Only used for Hubs.
* @param len The length of the incoming data.
* @param buf Pointer to the data buffer.
*/
virtual void ParseHIDData(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) {
if (HIDUniversal::VID == PS4_VID && (HIDUniversal::PID == PS4_PID || HIDUniversal::PID == PS4_PID_SLIM))
PS4Parser::Parse(len, buf);
};
/**
* Called when a device is successfully initialized.
* Use attachOnInit(void (*funcOnInit)(void)) to call your own function.
* This is useful for instance if you want to set the LEDs in a specific way.
*/
virtual uint8_t OnInitSuccessful() {
if (HIDUniversal::VID == PS4_VID && (HIDUniversal::PID == PS4_PID || HIDUniversal::PID == PS4_PID_SLIM)) {
PS4Parser::Reset();
if (pFuncOnInit)
pFuncOnInit(); // Call the user function
else
setLed(Blue);
};
return 0;
};
/**@}*/
/** @name PS4Parser implementation */
virtual void sendOutputReport(PS4Output *output) { // Source: https://github.com/chrippa/ds4drv
uint8_t buf[32];
memset(buf, 0, sizeof(buf));
buf[0] = 0x05; // Report ID
buf[1]= 0xFF;
buf[4] = output->smallRumble; // Small Rumble
buf[5] = output->bigRumble; // Big rumble
buf[6] = output->r; // Red
buf[7] = output->g; // Green
buf[8] = output->b; // Blue
buf[9] = output->flashOn; // Time to flash bright (255 = 2.5 seconds)
buf[10] = output->flashOff; // Time to flash dark (255 = 2.5 seconds)
output->reportChanged = false;
// The PS4 console actually set the four last bytes to a CRC32 checksum, but it seems like it is actually not needed
pUsb->outTransfer(bAddress, epInfo[ hidInterfaces[0].epIndex[epInterruptOutIndex] ].epAddr, sizeof(buf), buf);
};
/**@}*/
/** @name USBDeviceConfig implementation */
/**
* Used by the USB core to check what this driver support.
* @param vid The device's VID.
* @param pid The device's PID.
* @return Returns true if the device's VID and PID matches this driver.
*/
virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) {
return (vid == PS4_VID && (pid == PS4_PID || HIDUniversal::PID == PS4_PID_SLIM));
};
/**@}*/
private:
void (*pFuncOnInit)(void); // Pointer to function called in onInit()
};
#endif