diff --git a/PS3Enums.h b/PS3Enums.h
index 7ee84293..77801945 100644
--- a/PS3Enums.h
+++ b/PS3Enums.h
@@ -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)
};
-/** 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 {
// Note that the location is shifted 9 when it's connected via USB
// Byte location | bit location
@@ -160,9 +138,4 @@ enum StatusEnum {
Bluetooth = (40 << 8) | 0x16, // Operating by Bluetooth and rumble is turned off
};
-enum RumbleEnum {
- RumbleHigh = 0x10,
- RumbleLow = 0x20,
-};
-
#endif
diff --git a/PS4BT.h b/PS4BT.h
index bd42786a..129df6b1 100644
--- a/PS4BT.h
+++ b/PS4BT.h
@@ -46,6 +46,14 @@ public:
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:
/** @name BTHID implementation */
/**
@@ -64,7 +72,12 @@ protected:
* This is useful for instance if you want to set the LEDs in a specific way.
*/
virtual void OnInitBTHID() {
+ PS4Parser::Reset();
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 */
@@ -74,6 +87,34 @@ protected:
/**@}*/
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) {
pBtd->L2CAP_Command(hci_handle, data, nbytes, control_scid[0], control_scid[1]);
};
@@ -85,5 +126,7 @@ private:
HID_Command(buf, 2);
};
+
+ void (*pFuncOnInit)(void); // Pointer to function called in onInit()
};
#endif
\ No newline at end of file
diff --git a/PS4Parser.cpp b/PS4Parser.cpp
index f22784cd..1a449adb 100644
--- a/PS4Parser.cpp
+++ b/PS4Parser.cpp
@@ -118,4 +118,7 @@ void PS4Parser::Parse(uint8_t len, uint8_t *buf) {
}
}
}
+
+ if (ps4Output.reportChanged)
+ sendOutputReport(&ps4Output); // Send output report
}
\ No newline at end of file
diff --git a/PS4Parser.h b/PS4Parser.h
index 1fe8ab2a..680edc83 100644
--- a/PS4Parser.h
+++ b/PS4Parser.h
@@ -102,6 +102,13 @@ struct PS4Data {
// The last three bytes are always: 0x00, 0x80, 0x00
} __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 {
DPAD_UP = 0x0,
DPAD_UP_RIGHT = 0x1,
@@ -237,6 +244,74 @@ public:
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:
@@ -267,13 +342,21 @@ protected:
oldButtonState.dpad = DPAD_OFF;
buttonClickState.dpad = 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:
bool checkDpad(ButtonEnum b); // Used to check PS4 DPAD buttons
PS4Data ps4Data;
PS4Buttons oldButtonState, buttonClickState;
+ PS4Output ps4Output;
uint8_t oldDpad;
};
#endif
\ No newline at end of file
diff --git a/PS4USB.h b/PS4USB.h
index fcb514c3..d377b60d 100644
--- a/PS4USB.h
+++ b/PS4USB.h
@@ -75,14 +75,44 @@ protected:
* This is useful for instance if you want to set the LEDs in a specific way.
*/
virtual uint8_t OnInitSuccessful() {
- PS4Parser::Reset();
- if (HIDUniversal::VID == PS4_VID && HIDUniversal::PID == PS4_PID && pFuncOnInit)
- pFuncOnInit(); // Call the user function
+ if (HIDUniversal::VID == PS4_VID && HIDUniversal::PID == PS4_PID) {
+ PS4Parser::Reset();
+ if (pFuncOnInit)
+ pFuncOnInit(); // Call the user function
+ else
+ setLed(Blue);
+ };
return 0;
};
/**@}*/
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()
};
#endif
\ No newline at end of file
diff --git a/README.md b/README.md
index b2a7dcc4..56152496 100644
--- a/README.md
+++ b/README.md
@@ -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.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.
-
-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.
+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.
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: .
-Also check out this excellent Wiki by Frank Zhao about the PS4 controller: .
+Also check out this excellent Wiki by Frank Zhao about the PS4 controller: and this Linux driver: .
### PS3 Library
diff --git a/controllerEnums.h b/controllerEnums.h
index 0eae781d..295b6ae4 100644
--- a/controllerEnums.h
+++ b/controllerEnums.h
@@ -41,6 +41,33 @@ enum LEDEnum {
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 */
enum ButtonEnum {
/**@{*/
diff --git a/examples/PS4USB/PS4USB.ino b/examples/PS4USB/PS4USB.ino
index 95a0e586..c8dc5069 100644
--- a/examples/PS4USB/PS4USB.ino
+++ b/examples/PS4USB/PS4USB.ino
@@ -6,6 +6,11 @@
#include
+// Satisfy IDE, which only needs to see the include statment in the ino.
+#ifdef dobogusinclude
+#include
+#endif
+
USB Usb;
PS4USB PS4(&Usb);
diff --git a/hiduniversal.h b/hiduniversal.h
index bfd1173b..d97f4b8c 100644
--- a/hiduniversal.h
+++ b/hiduniversal.h
@@ -17,10 +17,7 @@ class HIDUniversal : public HID {
// Returns HID class specific descriptor length by its type and order number
uint16_t GetHidClassDescrLen(uint8_t type, uint8_t num);
- EpInfo epInfo[totalEndpoints];
-
struct HIDInterface {
-
struct {
uint8_t bmInterface : 3;
uint8_t bmAltSet : 3;
@@ -29,8 +26,6 @@ class HIDUniversal : public HID {
uint8_t epIndex[maxEpPerInterface];
};
- HIDInterface hidInterfaces[maxHidInterfaces];
-
uint8_t bConfNum; // configuration number
uint8_t bNumIface; // number of interfaces 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);
protected:
+ EpInfo epInfo[totalEndpoints];
+ HIDInterface hidInterfaces[maxHidInterfaces];
+
bool bHasReportId;
uint16_t PID, VID; // PID and VID of connected device
diff --git a/keywords.txt b/keywords.txt
index 786d4fa2..a13ff34d 100644
--- a/keywords.txt
+++ b/keywords.txt
@@ -64,6 +64,7 @@ setRumbleOn KEYWORD2
setLedOff KEYWORD2
setLedOn KEYWORD2
setLedToggle KEYWORD2
+setLedFlash KEYWORD2
moveSetBulb KEYWORD2
moveSetRumble KEYWORD2