Can now set the rumble and light on the PS4 controller

Still need to test it via USB
This commit is contained in:
Kristian Lauszus 2014-02-17 00:21:21 +01:00
parent ac5d134f73
commit 6373ebe6ce
10 changed files with 200 additions and 39 deletions

View file

@ -110,28 +110,6 @@ const uint8_t PS3_ANALOG_BUTTONS[] PROGMEM = {
15, // T_ANALOG - Both at byte 14 (last reading) and byte 15 (current reading) 15, // T_ANALOG - Both at byte 14 (last reading) and byte 15 (current reading)
}; };
/** Used to set the colors of the move controller. */
enum ColorsEnum {
/** r = 255, g = 0, b = 0 */
Red = 0xFF0000,
/** r = 0, g = 255, b = 0 */
Green = 0xFF00,
/** r = 0, g = 0, b = 255 */
Blue = 0xFF,
/** r = 255, g = 235, b = 4 */
Yellow = 0xFFEB04,
/** r = 0, g = 255, b = 255 */
Lightblue = 0xFFFF,
/** r = 255, g = 0, b = 255 */
Purble = 0xFF00FF,
/** r = 255, g = 255, b = 255 */
White = 0xFFFFFF,
/** r = 0, g = 0, b = 0 */
Off = 0x00,
};
enum StatusEnum { enum StatusEnum {
// Note that the location is shifted 9 when it's connected via USB // Note that the location is shifted 9 when it's connected via USB
// Byte location | bit location // Byte location | bit location
@ -160,9 +138,4 @@ enum StatusEnum {
Bluetooth = (40 << 8) | 0x16, // Operating by Bluetooth and rumble is turned off Bluetooth = (40 << 8) | 0x16, // Operating by Bluetooth and rumble is turned off
}; };
enum RumbleEnum {
RumbleHigh = 0x10,
RumbleLow = 0x20,
};
#endif #endif

43
PS4BT.h
View file

@ -46,6 +46,14 @@ public:
return BTHID::connected; return BTHID::connected;
}; };
/**
* 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: protected:
/** @name BTHID implementation */ /** @name BTHID implementation */
/** /**
@ -64,7 +72,12 @@ protected:
* This is useful for instance if you want to set the LEDs in a specific way. * This is useful for instance if you want to set the LEDs in a specific way.
*/ */
virtual void OnInitBTHID() { virtual void OnInitBTHID() {
PS4Parser::Reset();
enable_sixaxis(); // Make the controller send out the entire output report enable_sixaxis(); // Make the controller send out the entire output report
if (pFuncOnInit)
pFuncOnInit(); // Call the user function
else
setLed(Blue);
}; };
/** Used to reset the different buffers to there default values */ /** Used to reset the different buffers to there default values */
@ -74,6 +87,34 @@ protected:
/**@}*/ /**@}*/
private: private:
/** @name PS4Parser implementation */
virtual void sendOutputReport(PS4Output *output) { // Source: https://github.com/chrippa/ds4drv
uint8_t buf[79];
memset(buf, 0, sizeof(buf));
buf[0] = 0x52; // HID BT Set_report (0x50) | Report Type (Output 0x02)
buf[1] = 0x11; // Report ID
buf[2] = 0x80;
buf[4]= 0xFF;
buf[7] = output->bigRumble; // Big Rumble
buf[8] = output->smallRumble; // Small rumble
buf[9] = output->r; // Red
buf[10] = output->g; // Green
buf[11] = output->b; // Blue
buf[12] = output->flashOn; // Time to flash bright (255 = 2.5 seconds)
buf[13] = 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
HID_Command(buf, sizeof(buf));
};
/**@}*/
void HID_Command(uint8_t *data, uint8_t nbytes) { void HID_Command(uint8_t *data, uint8_t nbytes) {
pBtd->L2CAP_Command(hci_handle, data, nbytes, control_scid[0], control_scid[1]); pBtd->L2CAP_Command(hci_handle, data, nbytes, control_scid[0], control_scid[1]);
}; };
@ -85,5 +126,7 @@ private:
HID_Command(buf, 2); HID_Command(buf, 2);
}; };
void (*pFuncOnInit)(void); // Pointer to function called in onInit()
}; };
#endif #endif

View file

@ -118,4 +118,7 @@ void PS4Parser::Parse(uint8_t len, uint8_t *buf) {
} }
} }
} }
if (ps4Output.reportChanged)
sendOutputReport(&ps4Output); // Send output report
} }

View file

@ -102,6 +102,13 @@ struct PS4Data {
// The last three bytes are always: 0x00, 0x80, 0x00 // The last three bytes are always: 0x00, 0x80, 0x00
} __attribute__((packed)); } __attribute__((packed));
struct PS4Output {
uint8_t bigRumble, smallRumble; // Rumble
uint8_t r, g, b; // RGB
uint8_t flashOn, flashOff; // Time to flash bright/dark (255 = 2.5 seconds)
bool reportChanged; // The data is send when data is received from the controller
} __attribute__((packed));
enum DPADEnum { enum DPADEnum {
DPAD_UP = 0x0, DPAD_UP = 0x0,
DPAD_UP_RIGHT = 0x1, DPAD_UP_RIGHT = 0x1,
@ -237,6 +244,74 @@ public:
return 0; return 0;
} }
}; };
/** Turn both rumble and the LEDs off. */
void setAllOff() {
setRumbleOff();
setLedOff();
};
/** Set rumble off. */
void setRumbleOff() {
setRumbleOn(0, 0);
};
/**
* Turn on rumble.
* @param mode Either ::RumbleHigh or ::RumbleLow.
*/
void setRumbleOn(RumbleEnum mode) {
if (mode == RumbleLow)
setRumbleOn(0xFF, 0x00);
else
setRumbleOn(0x00, 0xFF);
};
/**
* Turn on rumble.
* @param bigRumble Value for big motor.
* @param smallRumble Value for small motor.
*/
void setRumbleOn(uint8_t bigRumble, uint8_t smallRumble) {
ps4Output.bigRumble = bigRumble;
ps4Output.smallRumble = smallRumble;
ps4Output.reportChanged = true;
};
/** Turn all LEDs off. */
void setLedOff() {
setLed(0, 0, 0);
};
/**
* Use this to set the color using RGB values.
* @param r,g,b RGB value.
*/
void setLed(uint8_t r, uint8_t g, uint8_t b) {
ps4Output.r = r;
ps4Output.g = g;
ps4Output.b = b;
ps4Output.reportChanged = true;
};
/**
* Use this to set the color using the predefined colors in ::ColorsEnum.
* @param color The desired color.
*/
void setLed(ColorsEnum color) {
setLed((uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color));
};
/**
* Set the LEDs flash time.
* @param flashOn Time to flash bright (255 = 2.5 seconds).
* @param flashOff Time to flash dark (255 = 2.5 seconds).
*/
void setLedFlash(uint8_t flashOn, uint8_t flashOff) {
ps4Output.flashOn = flashOn;
ps4Output.flashOff = flashOff;
ps4Output.reportChanged = true;
};
/**@}*/ /**@}*/
protected: protected:
@ -267,13 +342,21 @@ protected:
oldButtonState.dpad = DPAD_OFF; oldButtonState.dpad = DPAD_OFF;
buttonClickState.dpad = 0; buttonClickState.dpad = 0;
oldDpad = 0; oldDpad = 0;
ps4Output.bigRumble = ps4Output.smallRumble = 0;
ps4Output.r = ps4Output.g = ps4Output.b = 0;
ps4Output.flashOn = ps4Output.flashOff = 0;
ps4Output.reportChanged = false;
}; };
virtual void sendOutputReport(PS4Output *output) = 0; // This is overridden in PS4BT and PS4USB
private: private:
bool checkDpad(ButtonEnum b); // Used to check PS4 DPAD buttons bool checkDpad(ButtonEnum b); // Used to check PS4 DPAD buttons
PS4Data ps4Data; PS4Data ps4Data;
PS4Buttons oldButtonState, buttonClickState; PS4Buttons oldButtonState, buttonClickState;
PS4Output ps4Output;
uint8_t oldDpad; uint8_t oldDpad;
}; };
#endif #endif

View file

@ -75,14 +75,44 @@ protected:
* This is useful for instance if you want to set the LEDs in a specific way. * This is useful for instance if you want to set the LEDs in a specific way.
*/ */
virtual uint8_t OnInitSuccessful() { virtual uint8_t OnInitSuccessful() {
if (HIDUniversal::VID == PS4_VID && HIDUniversal::PID == PS4_PID) {
PS4Parser::Reset(); PS4Parser::Reset();
if (HIDUniversal::VID == PS4_VID && HIDUniversal::PID == PS4_PID && pFuncOnInit) if (pFuncOnInit)
pFuncOnInit(); // Call the user function pFuncOnInit(); // Call the user function
else
setLed(Blue);
};
return 0; return 0;
}; };
/**@}*/ /**@}*/
private: private:
/** @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->bigRumble; // Big Rumble
buf[5] = output->smallRumble; // Small 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);
};
/**@}*/
void (*pFuncOnInit)(void); // Pointer to function called in onInit() void (*pFuncOnInit)(void); // Pointer to function called in onInit()
}; };
#endif #endif

View file

@ -120,9 +120,7 @@ It enables me to see the Bluetooth communication between my Mac and any device.
The PS4BT library is split up into the [PS4BT](PS4BT.h) and the [PS4USB](PS4USB.h) library. These allow you to use the Sony PS4 controller via Bluetooth and USB. The PS4BT library is split up into the [PS4BT](PS4BT.h) and the [PS4USB](PS4USB.h) library. These allow you to use the Sony PS4 controller via Bluetooth and USB.
The [PS4BT.ino](examples/Bluetooth/PS4BT/PS4BT.ino) and [PS4USB.ino](examples/PS4USB/PS4USB.ino) examples shows how to easily read the buttons and joysticks on the controller via Bluetooth and USB respectively. The [PS4BT.ino](examples/Bluetooth/PS4BT/PS4BT.ino) and [PS4USB.ino](examples/PS4USB/PS4USB.ino) examples shows how to easily read the buttons, joysticks, touchpad and IMU on the controller via Bluetooth and USB respectively. It is also possible to control the rumble and light on the controller.
I still have not figured out how to turn rumble on and off and set the color of the light, but hopefully I will figure that out soon.
Before you can use the PS4 controller via Bluetooth you will need to pair with it. Before you can use the PS4 controller via Bluetooth you will need to pair with it.
@ -132,7 +130,7 @@ It should then automatically pair the dongle with your controller. This only hav
For information see the following blog post: <http://blog.tkjelectronics.dk/2014/01/ps4-controller-now-supported-by-the-usb-host-library/>. For information see the following blog post: <http://blog.tkjelectronics.dk/2014/01/ps4-controller-now-supported-by-the-usb-host-library/>.
Also check out this excellent Wiki by Frank Zhao about the PS4 controller: <http://eleccelerator.com/wiki/index.php?title=DualShock_4>. Also check out this excellent Wiki by Frank Zhao about the PS4 controller: <http://eleccelerator.com/wiki/index.php?title=DualShock_4> and this Linux driver: <https://github.com/chrippa/ds4drv>.
### PS3 Library ### PS3 Library

View file

@ -41,6 +41,33 @@ enum LEDEnum {
ALL = 5, ALL = 5,
}; };
/** Used to set the colors of the Move and PS4 controller. */
enum ColorsEnum {
/** r = 255, g = 0, b = 0 */
Red = 0xFF0000,
/** r = 0, g = 255, b = 0 */
Green = 0xFF00,
/** r = 0, g = 0, b = 255 */
Blue = 0xFF,
/** r = 255, g = 235, b = 4 */
Yellow = 0xFFEB04,
/** r = 0, g = 255, b = 255 */
Lightblue = 0xFFFF,
/** r = 255, g = 0, b = 255 */
Purble = 0xFF00FF,
/** r = 255, g = 255, b = 255 */
White = 0xFFFFFF,
/** r = 0, g = 0, b = 0 */
Off = 0x00,
};
enum RumbleEnum {
RumbleHigh = 0x10,
RumbleLow = 0x20,
};
/** This enum is used to read all the different buttons on the different controllers */ /** This enum is used to read all the different buttons on the different controllers */
enum ButtonEnum { enum ButtonEnum {
/**@{*/ /**@{*/

View file

@ -6,6 +6,11 @@
#include <PS4USB.h> #include <PS4USB.h>
// Satisfy IDE, which only needs to see the include statment in the ino.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#endif
USB Usb; USB Usb;
PS4USB PS4(&Usb); PS4USB PS4(&Usb);

View file

@ -17,10 +17,7 @@ class HIDUniversal : public HID {
// Returns HID class specific descriptor length by its type and order number // Returns HID class specific descriptor length by its type and order number
uint16_t GetHidClassDescrLen(uint8_t type, uint8_t num); uint16_t GetHidClassDescrLen(uint8_t type, uint8_t num);
EpInfo epInfo[totalEndpoints];
struct HIDInterface { struct HIDInterface {
struct { struct {
uint8_t bmInterface : 3; uint8_t bmInterface : 3;
uint8_t bmAltSet : 3; uint8_t bmAltSet : 3;
@ -29,8 +26,6 @@ class HIDUniversal : public HID {
uint8_t epIndex[maxEpPerInterface]; uint8_t epIndex[maxEpPerInterface];
}; };
HIDInterface hidInterfaces[maxHidInterfaces];
uint8_t bConfNum; // configuration number uint8_t bConfNum; // configuration number
uint8_t bNumIface; // number of interfaces in the configuration uint8_t bNumIface; // number of interfaces in the configuration
uint8_t bNumEP; // total number of EP in the configuration uint8_t bNumEP; // total number of EP in the configuration
@ -49,6 +44,9 @@ class HIDUniversal : public HID {
void SaveBuffer(uint8_t len, uint8_t *src, uint8_t *dest); void SaveBuffer(uint8_t len, uint8_t *src, uint8_t *dest);
protected: protected:
EpInfo epInfo[totalEndpoints];
HIDInterface hidInterfaces[maxHidInterfaces];
bool bHasReportId; bool bHasReportId;
uint16_t PID, VID; // PID and VID of connected device uint16_t PID, VID; // PID and VID of connected device

View file

@ -64,6 +64,7 @@ setRumbleOn KEYWORD2
setLedOff KEYWORD2 setLedOff KEYWORD2
setLedOn KEYWORD2 setLedOn KEYWORD2
setLedToggle KEYWORD2 setLedToggle KEYWORD2
setLedFlash KEYWORD2
moveSetBulb KEYWORD2 moveSetBulb KEYWORD2
moveSetRumble KEYWORD2 moveSetRumble KEYWORD2