Browse Source

PS3 Move Motion controller

Turns out they are a lot different than other PS3 controllers.

When plugged into USB, it appears like these units do not send
any reports.  They do allow us to do pairing (which is differnt)
than other PS3, as well as set the Bulb LED color, which I now
have it alternating colors every few seconds and also it tries
to pair it with a BT dongle

When connected to Bluetooth, it now is setup to generate reports,
as well as again set the bulb color and rumble.

So far it maps the 3 button bytes into the buttons field and then
simply copies most all of the data down into Axis, starting where
the Trigger button is.

JoystickBT.ino was updated, to know about this controller and as
mentioned above in the USB case it tries to pair and plays with the
color of bulb.

In the BT case it tries to display data.  I did a quick and dirty
change of the Accel/Gyro like stuff which is probably totally wrong.

Pressing some of the buttons will set bulb color and pressing trigger
will set rumble.

PS3 Motion controller - very little mapping of axis
main
Kurt Eckhardt 5 years ago
parent
commit
d6e6c6a33e
9 changed files with 487 additions and 202 deletions
  1. +7
    -5
      USBHost_t36.h
  2. +4
    -1
      bluetooth.cpp
  3. +217
    -47
      examples/Bluetooth/JoystickBT/JoystickBT.ino
  4. +41
    -1
      examples/Bluetooth/JoystickBT/helperPS.ino
  5. +1
    -1
      examples/USBHost_viewer/USBHost_viewer.ino
  6. +1
    -1
      hid.cpp
  7. +214
    -145
      joystick.cpp
  8. +1
    -0
      keywords.txt
  9. +1
    -1
      mouse.cpp

+ 7
- 5
USBHost_t36.h View File

@@ -58,7 +58,7 @@


//#define USBHOST_PRINT_DEBUG
#define USBHDBGSerial Serial1
//#define USBHDBGSerial Serial1


#ifndef USBHDBGSerial
@@ -911,10 +911,11 @@ public:

// set functions functionality depends on underlying joystick.
bool setRumble(uint8_t lValue, uint8_t rValue, uint8_t timeout=0xff);
// setLEDs on PS4(RGB), PS3 simple LED setting (only uses lr)
bool setLEDs(uint8_t lr, uint8_t lg=0, uint8_t lb=0); // sets Leds,
// setLEDs on PS4(RGB), PS3 simple LED setting (only uses lb)
bool setLEDs(uint8_t lr, uint8_t lg, uint8_t lb); // sets Leds,
bool inline setLEDs(uint32_t leds) {return setLEDs((leds >> 16) & 0xff, (leds >> 8) & 0xff, leds & 0xff);} // sets Leds - passing one arg for all leds
enum { STANDARD_AXIS_COUNT = 10, ADDITIONAL_AXIS_COUNT = 54, TOTAL_AXIS_COUNT = (STANDARD_AXIS_COUNT+ADDITIONAL_AXIS_COUNT) };
typedef enum { UNKNOWN=0, PS3, PS4, XBOXONE, XBOX360} joytype_t;
typedef enum { UNKNOWN=0, PS3, PS4, XBOXONE, XBOX360, PS3_MOTION} joytype_t;
joytype_t joystickType() {return joystickType_;}

// PS3 pair function. hack, requires that it be connect4ed by USB and we have the address of the Bluetooth dongle...
@@ -954,6 +955,7 @@ private:
joytype_t mapVIDPIDtoJoystickType(uint16_t idVendor, uint16_t idProduct, bool exclude_hid_devices);
bool transmitPS4UserFeedbackMsg();
bool transmitPS3UserFeedbackMsg();
bool transmitPS3MotionUserFeedbackMsg();
bool mapNameToJoystickType(const uint8_t *remoteName);

bool anychange = false;
@@ -1685,7 +1687,7 @@ public:
const uint8_t* myBDAddr(void) {return my_bdaddr_;}

// BUGBUG version to allow some of the controlled objects to call?
enum {CONTROL_SCID=-1};
enum {CONTROL_SCID=-1, INTERRUPT_SCID=-2};
void sendL2CapCommand(uint8_t* data, uint8_t nbytes, int channel = (int)0x0001);

protected:

+ 4
- 1
bluetooth.cpp View File

@@ -31,7 +31,7 @@
#define println USBHost::println_//#define DEBUG_BT

//#define DEBUG_BT
#define DEBUG_BT_VERBOSE
//#define DEBUG_BT_VERBOSE

#ifndef DEBUG_BT
#undef DEBUG_BT_VERBOSE
@@ -1343,6 +1343,9 @@ void BluetoothController::sendL2CapCommand(uint8_t* data, uint8_t nbytes, int ch
case CONTROL_SCID:
channel_out = control_scid_;
break;
case INTERRUPT_SCID:
channel_out = interrupt_scid_;
break;
default:
channel_out = (uint16_t)channel;
}

+ 217
- 47
examples/Bluetooth/JoystickBT/JoystickBT.ino View File

@@ -37,6 +37,13 @@ USBHIDInput *hiddrivers[] = {&joystick1, &rawhid1, &rawhid2};
const char * hid_driver_names[CNT_DEVICES] = {"Joystick1", "RawHid1", "RawHid2"};

bool hid_driver_active[CNT_DEVICES] = {false, false, false};

BTHIDInput *bthiddrivers[] = {&joystick1};
#define CNT_BTHIDDEVICES (sizeof(bthiddrivers)/sizeof(bthiddrivers[0]))
const char * bthid_driver_names[CNT_HIDDEVICES] = {"joystick"};
bool bthid_driver_active[CNT_HIDDEVICES] = {false};


bool show_changed_only = false;
bool show_raw_data = false;
bool show_changed_data = false;
@@ -49,6 +56,15 @@ int psAxis[64];
bool first_joystick_message = true;
uint8_t last_bdaddr[6] = {0, 0, 0, 0, 0, 0};

// ps3 motion on USB does not do much, but see if we can pair it and maybe change
// color of bulb...
uint32_t PS3_MOTION_timer = 0;
uint8_t PS3_MOTION_tried_to_pair_state = 0;
#define PS3_MOTION_PERIOD 2500 // not sure yet what would be good period for this..

//=============================================================================
// Setup
//=============================================================================
void setup()
{

@@ -65,7 +81,9 @@ void setup()
rawhid2.attachReceive(OnReceiveHidData);
}


//=============================================================================
// Loop
//=============================================================================
void loop()
{
myusb.Task();
@@ -90,51 +108,9 @@ void loop()
}
}
}

for (uint8_t i = 0; i < CNT_DEVICES; i++) {
if (*drivers[i] != driver_active[i]) {
if (driver_active[i]) {
Serial.printf("*** Device %s - disconnected ***\n", driver_names[i]);
driver_active[i] = false;
} else {
Serial.printf("*** Device %s %x:%x - connected ***\n", driver_names[i], drivers[i]->idVendor(), drivers[i]->idProduct());
driver_active[i] = true;

const uint8_t *psz = drivers[i]->manufacturer();
if (psz && *psz) Serial.printf(" manufacturer: %s\n", psz);
psz = drivers[i]->product();
if (psz && *psz) Serial.printf(" product: %s\n", psz);
psz = drivers[i]->serialNumber();
if (psz && *psz) Serial.printf(" Serial: %s\n", psz);

if (drivers[i] == &bluet) {
const uint8_t *bdaddr = bluet.myBDAddr();
// remember it...
Serial.printf(" BDADDR: %x:%x:%x:%x:%x:%x\n", bdaddr[0], bdaddr[1], bdaddr[2], bdaddr[3], bdaddr[4], bdaddr[5]);
for (uint8_t i = 0; i < 6; i++) last_bdaddr[i] = bdaddr[i];
}
}
}
}

for (uint8_t i = 0; i < CNT_HIDDEVICES; i++) {
if (*hiddrivers[i] != hid_driver_active[i]) {
if (hid_driver_active[i]) {
Serial.printf("*** HID Device %s - disconnected ***\n", hid_driver_names[i]);
hid_driver_active[i] = false;
} else {
Serial.printf("*** HID Device %s %x:%x - connected ***\n", hid_driver_names[i], hiddrivers[i]->idVendor(), hiddrivers[i]->idProduct());
hid_driver_active[i] = true;

const uint8_t *psz = hiddrivers[i]->manufacturer();
if (psz && *psz) Serial.printf(" manufacturer: %s\n", psz);
psz = hiddrivers[i]->product();
if (psz && *psz) Serial.printf(" product: %s\n", psz);
psz = hiddrivers[i]->serialNumber();
if (psz && *psz) Serial.printf(" Serial: %s\n", psz);
}
}
}
// check to see if the device list has changed:
UpdateActiveDeviceInfo();
processPS3MotionTimer();

if (joystick1.available()) {
if (first_joystick_message) {
@@ -164,6 +140,9 @@ void loop()
case JoystickController::PS3:
displayPS3Data();
break;
case JoystickController::PS3_MOTION:
displayPS3MotionData();
break;
case JoystickController::XBOXONE:
case JoystickController::XBOX360:
displayXBoxData();
@@ -196,13 +175,96 @@ void loop()
}
}

//=============================================================================
// UpdateActiveDeviceInfo
//=============================================================================
void UpdateActiveDeviceInfo() {
for (uint8_t i = 0; i < CNT_DEVICES; i++) {
if (*drivers[i] != driver_active[i]) {
if (driver_active[i]) {
Serial.printf("*** Device %s - disconnected ***\n", driver_names[i]);
driver_active[i] = false;
} else {
Serial.printf("*** Device %s %x:%x - connected ***\n", driver_names[i], drivers[i]->idVendor(), drivers[i]->idProduct());
driver_active[i] = true;

const uint8_t *psz = drivers[i]->manufacturer();
if (psz && *psz) Serial.printf(" manufacturer: %s\n", psz);
psz = drivers[i]->product();
if (psz && *psz) Serial.printf(" product: %s\n", psz);
psz = drivers[i]->serialNumber();
if (psz && *psz) Serial.printf(" Serial: %s\n", psz);

if (drivers[i] == &bluet) {
const uint8_t *bdaddr = bluet.myBDAddr();
// remember it...
Serial.printf(" BDADDR: %x:%x:%x:%x:%x:%x\n", bdaddr[0], bdaddr[1], bdaddr[2], bdaddr[3], bdaddr[4], bdaddr[5]);
for (uint8_t i = 0; i < 6; i++) last_bdaddr[i] = bdaddr[i];
}
}
}
}

for (uint8_t i = 0; i < CNT_HIDDEVICES; i++) {
if (*hiddrivers[i] != hid_driver_active[i]) {
if (hid_driver_active[i]) {
Serial.printf("*** HID Device %s - disconnected ***\n", hid_driver_names[i]);
hid_driver_active[i] = false;
} else {
Serial.printf("*** HID Device %s %x:%x - connected ***\n", hid_driver_names[i], hiddrivers[i]->idVendor(), hiddrivers[i]->idProduct());
hid_driver_active[i] = true;

const uint8_t *psz = hiddrivers[i]->manufacturer();
if (psz && *psz) Serial.printf(" manufacturer: %s\n", psz);
psz = hiddrivers[i]->product();
if (psz && *psz) Serial.printf(" product: %s\n", psz);
psz = hiddrivers[i]->serialNumber();
if (psz && *psz) Serial.printf(" Serial: %s\n", psz);

// See if this is our joystick object...
if (hiddrivers[i] == &joystick1) {
Serial.printf(" Joystick type: %d\n", joystick1.joystickType());
if (joystick1.joystickType() == JoystickController::PS3_MOTION) {
Serial.println(" PS3 Motion detected");
PS3_MOTION_timer = millis(); // set time for last event
PS3_MOTION_tried_to_pair_state = 0;
}
}

}
}
}
// Then Bluetooth devices
for (uint8_t i = 0; i < CNT_BTHIDDEVICES; i++) {
if (*bthiddrivers[i] != bthid_driver_active[i]) {
if (bthid_driver_active[i]) {
Serial.printf("*** BTHID Device %s - disconnected ***\n", hid_driver_names[i]);
bthid_driver_active[i] = false;
} else {
Serial.printf("*** BTHID Device %s %x:%x - connected ***\n", hid_driver_names[i], hiddrivers[i]->idVendor(), hiddrivers[i]->idProduct());
bthid_driver_active[i] = true;

const uint8_t *psz = bthiddrivers[i]->manufacturer();
if (psz && *psz) Serial.printf(" manufacturer: %s\n", psz);
psz = bthiddrivers[i]->product();
if (psz && *psz) Serial.printf(" product: %s\n", psz);
psz = bthiddrivers[i]->serialNumber();
if (psz && *psz) Serial.printf(" Serial: %s\n", psz);
}
}
}
}

//=============================================================================
// displayPS4Data
//=============================================================================
void displayPS4Data()
{
buttons = joystick1.getButtons();
Serial.printf("LX: %d, LY: %d, RX: %d, RY: %d \r\n", psAxis[0], psAxis[1], psAxis[2], psAxis[5]);
Serial.printf("L-Trig: %d, R-Trig: %d\r\n", psAxis[3], psAxis[4]);
Serial.printf("Buttons: %x\r\n", buttons);
Serial.printf("Battery Status: %d\n", ((psAxis[30] & (1 << 4) - 1)*10));
Serial.printf("Battery Status: %d\n", ((psAxis[30] & ((1 << 4) - 1))*10));
printAngles();
Serial.println();

@@ -244,6 +306,9 @@ void displayPS4Data()

}

//=============================================================================
// displayPS3Data
//=============================================================================
void displayPS3Data()

{
@@ -305,7 +370,61 @@ void displayPS3Data()
buttons_prev = buttons;
}
}
//=============================================================================
// displayPS3MotionData
//=============================================================================
void displayPS3MotionData()

{
buttons = joystick1.getButtons();

// Hard to know what is best here. for now just copy raw data over...
// will do this for now... Format of thought to be data.
// data[1-3] Buttons (mentioned 4 as well but appears to be counter
// axis[0-1] data[5] Trigger, Previous trigger value
// 2-5 Unknown probably place holders for Axis like data for other PS3
// 6 - Time stamp
// 7 - Battery
// 8-19 - Accel: XL, XH, YL, YH, ZL, ZH, XL2, XH2, YL2, YH2, ZL2, ZH2
// 20-31 - Gyro: Xl,Xh,Yl,Yh,Zl,Zh,Xl2,Xh2,Yl2,Yh2,Zl2,Zh2
// 32 - Temp High
// 33 - Temp Low (4 bits) Maybe Magneto x High on other??

// Use Select button to choose raw or not
if ((buttons & 0x01) && !(buttons_prev & 0x01)) show_raw_data = !show_raw_data;
if ((buttons & 0x04) && !(buttons_prev & 0x04)) show_changed_data = !show_changed_data;

if (show_raw_data) {
displayRawData();
} else {
uint64_t changed_mask = joystick1.axisChangedMask();
Serial.printf("Changed: %08x Buttons: %x: Trig: %d\r\n", (uint32_t)changed_mask, buttons, psAxis[0]);
Serial.printf("Battery Status: %d\n", psAxis[7]);
printPS3MotionAngles();
Serial.println();
}

uint8_t ltv = psAxis[0];

if ((ltv != joystick_left_trigger_value) ) {
joystick_left_trigger_value = ltv;
Serial.printf("Rumbling: %d\r\n", ltv);
joystick1.setRumble(ltv, 0);
}

if (buttons != buttons_prev) {
uint8_t ledsR = (buttons & 0x8000)? 0xff : 0; //Srq
uint8_t ledsG = (buttons & 0x2000)? 0xff : 0; //Cir
uint8_t ledsB = (buttons & 0x1000)? 0xff : 0; //Tri
Serial.printf("Set Leds %x %x %x\r\n", ledsR, ledsG, ledsB );
joystick1.setLEDs(ledsR, ledsG, ledsB);
buttons_prev = buttons;
}
}

//=============================================================================
// displayXBoxData
//=============================================================================
void displayXBoxData()
{
buttons = joystick1.getButtons();
@@ -345,6 +464,9 @@ void displayXBoxData()
}
}

//=============================================================================
// displayRawData
//=============================================================================
void displayRawData() {
uint64_t axis_mask = joystick1.axisMask();
uint64_t changed_mask = joystick1.axisChangedMask();
@@ -380,6 +502,9 @@ void displayRawData() {
}


//=============================================================================
// OnReceiveHidData
//=============================================================================
bool OnReceiveHidData(uint32_t usage, const uint8_t *data, uint32_t len) {
// Called for maybe both HIDS for rawhid basic test. One is for the Teensy
// to output to Serial. while still having Raw Hid...
@@ -413,4 +538,49 @@ bool OnReceiveHidData(uint32_t usage, const uint8_t *data, uint32_t len) {
}

return true;
}

//=============================================================================
// processPS3MotionTimer
//=============================================================================
static const uint32_t PS3_MOTION_colors[] = {0, 0xff, 0xff00, 0xff0000, 0xffff, 0xff00ff, 0xffff00, 0xffffff};

uint8_t PS3_MOTION_colors_index = 0;

void processPS3MotionTimer() {
// See if we have a PS3_MOTION connected and we have run for a certain amount of time

if (PS3_MOTION_timer && ((millis()-PS3_MOTION_timer) >= PS3_MOTION_PERIOD)) {
Serial.println("PS3 Motion Timer"); Serial.flush();
if (joystick1) {
PS3_MOTION_timer = millis(); // joystick not there any more...

// We will first try to set feedback color for the PS3, maybe alternate colors
if (++PS3_MOTION_colors_index >= sizeof(PS3_MOTION_colors)/sizeof(PS3_MOTION_colors[0])) PS3_MOTION_colors_index = 0;
joystick1.setLEDs(PS3_MOTION_colors[PS3_MOTION_colors_index]);

// Next see if we can try to pair.
if (PS3_MOTION_tried_to_pair_state == 0) {
Serial.println("PS3_MOTION Connected");
if (!last_bdaddr[0] && !last_bdaddr[1] && !last_bdaddr[2] && !last_bdaddr[3] && !last_bdaddr[4] && !last_bdaddr[5]) {
Serial.println(" - No Bluetooth adapter has been plugged in - so will not try to pair");
PS3_MOTION_tried_to_pair_state = 1;
}
}
if ((PS3_MOTION_tried_to_pair_state < 2) &&
(last_bdaddr[0] || last_bdaddr[1] || last_bdaddr[2] || last_bdaddr[3] || last_bdaddr[4] || last_bdaddr[5])) {
Serial.println(" - Bluetooth device detected, will try to pair");
// Lets try to pair
if (! joystick1.PS3Pair(last_bdaddr)) {
Serial.println(" - Pairing call Failed");
} else {
Serial.println(" - Pairing complete (I hope), make sure Bluetooth adapter is plugged in and try PS3 without USB");
}
PS3_MOTION_tried_to_pair_state = 2; // don't try again...
}
} else {
Serial.println("PS3 Motion Joystick no longer detected");
PS3_MOTION_timer = 0; // joystick not there any more...
}
}
}

+ 41
- 1
examples/Bluetooth/JoystickBT/helperPS.ino View File

@@ -22,7 +22,6 @@ void printAngles(){
void getCoords(uint16_t &xc, uint16_t &yc, uint8_t &isTouch){

//uint8_t finger = 0; //only getting finger 1
uint8_t Id = 0;


// Trackpad touch 1: id, active, x, y
@@ -62,4 +61,45 @@ void getGyro(float &gx, float &gy, float &gz){
gy = (float) gyroy * RAD_TO_DEG/1024;
gz = (float) gyroz * RAD_TO_DEG/1024;
}


void printPS3MotionAngles(){
//test function calls
float gx, gy, gz;
getPS3MotionAccel(ax, ay, az);
Serial.printf("Accel-g's: %f, %f, %f\n", ax, ay, az);
getPS3MotionGyro(gx, gy, gz);
Serial.printf("Gyro-deg/sec: %f, %f, %f\n", gx, gy, gz);

getPS3MotionAngles(pitch, roll);
Serial.printf("Pitch/Roll: %f, %f\n", pitch, roll);
}


void getPS3MotionAccel( float &ax, float &ay, float &az){
int accelx = (int16_t)(psAxis[9]<<8) | psAxis[8];
int accely = (int16_t)(psAxis[11]<<8) | psAxis[10];
int accelz = (int16_t)(psAxis[13]<<8) | psAxis[12];

ax = (float) accelx/8192;
ay = (float) accely/8192;
az = (float) accelz/8192;
}

void getPS3MotionAngles(float &p, float &r){
getAccel( ax, ay, az);
p = (atan2f(ay, az) + PI) * RAD_TO_DEG;
r = (atan2f(ax, az) + PI) * RAD_TO_DEG;
}

void getPS3MotionGyro(float &gx, float &gy, float &gz){
int gyrox = (int16_t)(psAxis[21]<<8) | psAxis[20];
int gyroy = (int16_t)(psAxis[23]<<8) | psAxis[22];
int gyroz = (int16_t)(psAxis[25]<<8) | psAxis[24];

gx = (float) gyrox * RAD_TO_DEG/1024;
gy = (float) gyroy * RAD_TO_DEG/1024;
gz = (float) gyroz * RAD_TO_DEG/1024;
}

+ 1
- 1
examples/USBHost_viewer/USBHost_viewer.ino View File

@@ -251,7 +251,7 @@ void UpdateActiveDeviceInfo() {
if (*bthiddrivers[i] != bthid_driver_active[i]) {
if (bthid_driver_active[i]) {
Serial.printf("*** BTHID Device %s - disconnected ***\n", hid_driver_names[i]);
hid_driver_active[i] = false;
bthid_driver_active[i] = false;
} else {
new_device_detected = true;
Serial.printf("*** BTHID Device %s %x:%x - connected ***\n", hid_driver_names[i], hiddrivers[i]->idVendor(), hiddrivers[i]->idProduct());

+ 1
- 1
hid.cpp View File

@@ -166,7 +166,7 @@ void USBHIDParser::control(const Transfer_t *transfer)
parse();
queue_Data_Transfer(in_pipe, report, in_size, this);
if (device->idVendor == 0x054C &&
((device->idProduct == 0x0268) || (device->idProduct == 0x042F) || (device->idProduct == 0x03D5))) {
((device->idProduct == 0x0268) || (device->idProduct == 0x042F)/* || (device->idProduct == 0x03D5)*/)) {
println("send special PS3 feature command");
mk_setup(setup, 0x21, 9, 0x03F4, 0, 4); // ps3 tell to send report 1?
static uint8_t ps3_feature_F4_report[] = {0x42, 0x0c, 0x00, 0x00};

+ 214
- 145
joystick.cpp View File

@@ -42,7 +42,7 @@ JoystickController::product_vendor_mapping_t JoystickController::pid_vid_mapping
{ 0x045e, 0x0719, XBOX360, false},
{ 0x054C, 0x0268, PS3, true},
{ 0x054C, 0x042F, PS3, true}, // PS3 Navigation controller
{ 0x054C, 0x03D5, PS3, true}, // PS3 Motion controller
{ 0x054C, 0x03D5, PS3_MOTION, true}, // PS3 Motion controller
{ 0x054C, 0x05C4, PS4, true}, {0x054C, 0x09CC, PS4, true }
};

@@ -127,6 +127,8 @@ bool JoystickController::setRumble(uint8_t lValue, uint8_t rValue, uint8_t timeo
break;
case PS3:
return transmitPS3UserFeedbackMsg();
case PS3_MOTION:
return transmitPS3MotionUserFeedbackMsg();
case PS4:
return transmitPS4UserFeedbackMsg();
case XBOXONE:
@@ -169,6 +171,7 @@ bool JoystickController::setRumble(uint8_t lValue, uint8_t rValue, uint8_t timeo
return false;
}


bool JoystickController::setLEDs(uint8_t lr, uint8_t lg, uint8_t lb)
{
// Need to know which joystick we are on. Start off with XBox support - maybe need to add some enum value for the known
@@ -181,6 +184,8 @@ bool JoystickController::setLEDs(uint8_t lr, uint8_t lg, uint8_t lb)
switch (joystickType_) {
case PS3:
return transmitPS3UserFeedbackMsg();
case PS3_MOTION:
return transmitPS3MotionUserFeedbackMsg();
case PS4:
return transmitPS4UserFeedbackMsg();
case XBOX360:
@@ -272,7 +277,7 @@ bool JoystickController::transmitPS3UserFeedbackMsg() {
txbuf_[2] = rumble_lValue_; // Small Rumble
txbuf_[3] = rumble_rValue_? rumble_timeout_ : 0;
txbuf_[4] = rumble_rValue_; // Big rumble
txbuf_[9] = leds_[0] << 1; // RGB value
txbuf_[9] = leds_[2] << 1; // RGB value // using third led now...
//DBGPrintf("\nJoystick update Rumble/LEDs %d %d %d %d %d\n", txbuf_[1], txbuf_[2], txbuf_[3], txbuf_[4], txbuf_[9]);
return driver_->sendControlPacket(0x21, 9, 0x201, 0, 48, txbuf_);
} else if (btdriver_) {
@@ -284,7 +289,7 @@ bool JoystickController::transmitPS3UserFeedbackMsg() {
txbuf_[4] = rumble_lValue_; // Small Rumble
txbuf_[5] = rumble_rValue_? rumble_timeout_ : 0;
txbuf_[6] = rumble_rValue_; // Big rumble
txbuf_[11] = leds_[0] << 1; // RGB value
txbuf_[11] = leds_[2] << 1; // RGB value
DBGPrintf("\nJoystick update Rumble/LEDs %d %d %d %d %d\n", txbuf_[3], txbuf_[4], txbuf_[5], txbuf_[6], txbuf_[11]);
btdriver_->sendL2CapCommand(txbuf_, 50, BluetoothController::CONTROL_SCID);
return true;
@@ -292,6 +297,33 @@ bool JoystickController::transmitPS3UserFeedbackMsg() {
return false;
}

#define MOVE_REPORT_BUFFER_SIZE 7
#define MOVE_HID_BUFFERSIZE 50 // Size of the buffer for the Playstation Motion Controller

bool JoystickController::transmitPS3MotionUserFeedbackMsg() {
if (driver_) {
txbuf_[0] = 0x02; // Set report ID, this is needed for Move commands to work
txbuf_[2] = leds_[0];
txbuf_[3] = leds_[1];
txbuf_[4] = leds_[2];
txbuf_[6] = rumble_lValue_; // Set the rumble value into the write buffer

//return driver_->sendControlPacket(0x21, 9, 0x201, 0, MOVE_REPORT_BUFFER_SIZE, txbuf_);
return driver_->sendPacket(txbuf_, MOVE_REPORT_BUFFER_SIZE);

} else if (btdriver_) {
txbuf_[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)
txbuf_[1] = 0x02; // Report ID
txbuf_[3] = leds_[0];
txbuf_[4] = leds_[1];
txbuf_[5] = leds_[2];
txbuf_[7] = rumble_lValue_;
btdriver_->sendL2CapCommand(txbuf_, MOVE_HID_BUFFERSIZE, BluetoothController::INTERRUPT_SCID);
return true;
}
return false;
}

//*****************************************************************************
// Support for Joysticks that Use HID data.
//*****************************************************************************
@@ -318,6 +350,7 @@ hidclaim_t JoystickController::claim_collection(USBHIDParser *driver, Device_t *
DBGPrintf("JoystickController::claim_collection joystickType_=%d\n", joystickType_);
switch (joystickType_) {
case PS3:
case PS3_MOTION: // not sure yet
additional_axis_usage_page_ = 0x1;
additional_axis_usage_start_ = 0x100;
additional_axis_usage_count_ = 39;
@@ -711,7 +744,7 @@ bool JoystickController::claim_bluetooth(BluetoothController *driver, uint32_t b
}

if (remoteName && mapNameToJoystickType(remoteName)) {
if (joystickType_ == PS3) {
if ((joystickType_ == PS3) || (joystickType_ == PS3_MOTION)) {
DBGPrintf("JoystickController::claim_bluetooth TRUE PS3 hack...\n");
btdriver_ = driver;
btdevice = (Device_t*)driver; // remember this way
@@ -728,13 +761,15 @@ bool JoystickController::process_bluetooth_HID_data(const uint8_t *data, uint16_
// Example data from PS4 controller
//01 7e 7f 82 84 08 00 00 00 00
// LX LY RX RY BT BT PS LT RT
//DBGPrintf("JoystickController::process_bluetooth_HID_data\n");
DBGPrintf("JoystickController::process_bluetooth_HID_data: data[0]=%x\n", data[0]);
// May have to look at this one with other controllers...
if (data[0] == 1) {
//print(" Joystick Data: ");
//print_hexbytes(data, length);
// DBGPrintf(" Joystick Data: ");
// print_hexbytes(data, length);
if (length > TOTAL_AXIS_COUNT) length = TOTAL_AXIS_COUNT; // don't overflow arrays...
DBGPrintf(" Joystick Data: ");
for(uint16_t i =0; i < length; i++) DBGPrintf("%02x ", data[i]);
DBGPrintf("\r\n");
if (joystickType_ == PS3) {
// Quick and dirty hack to match PS3 HID data
uint32_t cur_buttons = data[2] | ((uint16_t)data[3] << 8) | ((uint32_t)data[4] << 16);
@@ -777,6 +812,37 @@ bool JoystickController::process_bluetooth_HID_data(const uint8_t *data, uint16_
}
mask <<= 1; // shift down the mask.
}
} else if (joystickType_ == PS3_MOTION) {
// Quick and dirty PS3_Motion data.
uint32_t cur_buttons = data[1] | ((uint16_t)data[2] << 8) | ((uint32_t)data[3] << 16);
if (cur_buttons != buttons) {
buttons = cur_buttons;
joystickEvent = true; // something changed.
}

// Hard to know what is best here. for now just copy raw data over...
// will do this for now... Format of thought to be data.
// data[1-3] Buttons (mentioned 4 as well but appears to be counter
// axis[0-1] data[5] Trigger, Previous trigger value
// 2-5 Unknown probably place holders for Axis like data for other PS3
// 6 - Time stamp
// 7 - Battery
// 8-19 - Accel: XL, XH, YL, YH, ZL, ZH, XL2, XH2, YL2, YH2, ZL2, ZH2
// 20-31 - Gyro: Xl,Xh,Yl,Yh,Zl,Zh,Xl2,Xh2,Yl2,Yh2,Zl2,Zh2
// 32 - Temp High
// 33 - Temp Low (4 bits) Maybe Magneto x High on other??
uint64_t mask = 0x1;
axis_mask_ = 0; // assume bits 0, 1, 2, 5
// Then rest of data
mask = 0x1 << 10; // setup for other bits
for (uint16_t i = 5; i < length; i++ ) {
axis_mask_ |= mask;
if(data[i] != axis[i-5]) {
axis_changed_mask_ |= mask;
axis[i-5] = data[i];
}
mask <<= 1; // shift down the mask.
}

} else {
uint64_t mask = 0x1;
@@ -800,116 +866,92 @@ bool JoystickController::process_bluetooth_HID_data(const uint8_t *data, uint16_
return true;

} else if(data[0] == 0x11){
if (data[0] == 1) {
//print(" Joystick Data: ");
//print_hexbytes(data, length);
// DBGPrintf(" Joystick Data: ");
uint64_t mask = 0x1;
axis_mask_ = 0;
axis_changed_mask_ = 0;

if (length > TOTAL_AXIS_COUNT) length = TOTAL_AXIS_COUNT; // don't overflow arrays...
for (uint16_t i = 0; i < length; i++ ) {
axis_mask_ |= mask;
if(data[i] != axis[i]) {
axis_changed_mask_ |= mask;
axis[i] = data[i];
}
mask <<= 1; // shift down the mask.
// DBGPrintf("%02x ", axis[i]);
}
// DBGPrintf("\n");
joystickEvent = true;
connected_ = true;
return true;
} else if(data[0] == 0x11){
DBGPrintf("\n Joystick Data: ");
uint64_t mask = 0x1;
axis_mask_ = 0;
axis_changed_mask_ = 0;
//This moves data to be equivalent to what we see for
//data[0] = 0x01
uint8_t tmp_data[length-2];
for (uint16_t i = 0; i < (length-2); i++ ) {
tmp_data[i] = 0;
tmp_data[i] = data[i+2];
}
/*
* [1] LX, [2] = LY, [3] = RX, [4] = RY
* [5] combo, tri, cir, x, sqr, D-PAD (4bits, 0-3
* [6] R3,L3, opt, share, R2, L2, R1, L1
* [7] Counter (bit7-2), T-PAD, PS
* [8] Left Trigger, [9] Right Trigger
* [10-11] Timestamp
* [12] Battery (0 to 0xff)
* [13-14] acceleration x
* [15-16] acceleration y
* [17-18] acceleration z
* [19-20] gyro x
* [21-22] gyro y
* [23-24] gyro z
* [25-29] unknown
* [30] 0x00,phone,mic, usb, battery level (4bits)
* rest is trackpad? to do implement?
*/
//PS Bit
tmp_data[7] = (tmp_data[7] >> 0) & 1;
//set arrow buttons to axis[0]
tmp_data[10] = tmp_data[5] & ((1 << 4) - 1);
//set buttons for last 4bits in the axis[5]
tmp_data[5] = tmp_data[5] >> 4;
DBGPrintf("\n Joystick Data: ");
uint64_t mask = 0x1;
axis_mask_ = 0;
axis_changed_mask_ = 0;
// Quick and dirty hack to match PS4 HID data
uint32_t cur_buttons = tmp_data[7] | (tmp_data[10]) | ((tmp_data[6]*10)) | ((uint16_t)tmp_data[5] << 16) ;
if (cur_buttons != buttons) {
buttons = cur_buttons;
joystickEvent = true; // something changed.
}
mask = 0x1;
axis_mask_ = 0x27; // assume bits 0, 1, 2, 5
for (uint16_t i = 0; i < 3; i++) {
if (axis[i] != tmp_data[i+1]) {
axis_changed_mask_ |= mask;
axis[i] = tmp_data[i+1];
}
mask <<= 1; // shift down the mask.
}
if (axis[5] != tmp_data[4]) {
axis_changed_mask_ |= (1<<5);
axis[5] = tmp_data[4];
}
if (axis[3] != tmp_data[8]) {
axis_changed_mask_ |= (1<<3);
axis[3] = tmp_data[8];
}
if (axis[4] != tmp_data[9]) {
axis_changed_mask_ |= (1<<4);
axis[4] = tmp_data[9];
//This moves data to be equivalent to what we see for
//data[0] = 0x01
uint8_t tmp_data[length-2];
for (uint16_t i = 0; i < (length-2); i++ ) {
tmp_data[i] = 0;
tmp_data[i] = data[i+2];
}
/*
* [1] LX, [2] = LY, [3] = RX, [4] = RY
* [5] combo, tri, cir, x, sqr, D-PAD (4bits, 0-3
* [6] R3,L3, opt, share, R2, L2, R1, L1
* [7] Counter (bit7-2), T-PAD, PS
* [8] Left Trigger, [9] Right Trigger
* [10-11] Timestamp
* [12] Battery (0 to 0xff)
* [13-14] acceleration x
* [15-16] acceleration y
* [17-18] acceleration z
* [19-20] gyro x
* [21-22] gyro y
* [23-24] gyro z
* [25-29] unknown
* [30] 0x00,phone,mic, usb, battery level (4bits)
* rest is trackpad? to do implement?
*/
//PS Bit
tmp_data[7] = (tmp_data[7] >> 0) & 1;
//set arrow buttons to axis[0]
tmp_data[10] = tmp_data[5] & ((1 << 4) - 1);
//set buttons for last 4bits in the axis[5]
tmp_data[5] = tmp_data[5] >> 4;
// Quick and dirty hack to match PS4 HID data
uint32_t cur_buttons = tmp_data[7] | (tmp_data[10]) | ((tmp_data[6]*10)) | ((uint16_t)tmp_data[5] << 16) ;
if (cur_buttons != buttons) {
buttons = cur_buttons;
joystickEvent = true; // something changed.
}
mask = 0x1;
axis_mask_ = 0x27; // assume bits 0, 1, 2, 5
for (uint16_t i = 0; i < 3; i++) {
if (axis[i] != tmp_data[i+1]) {
axis_changed_mask_ |= mask;
axis[i] = tmp_data[i+1];
}
//limit for masking
mask = 0x1;
for (uint16_t i = 6; i < (64); i++ ) {
axis_mask_ |= mask;
if(tmp_data[i] != axis[i]) {
axis_changed_mask_ |= mask;
axis[i] = tmp_data[i];
}
mask <<= 1; // shift down the mask.
DBGPrintf("%02x ", axis[i]);
mask <<= 1; // shift down the mask.
}
if (axis[5] != tmp_data[4]) {
axis_changed_mask_ |= (1<<5);
axis[5] = tmp_data[4];
}
if (axis[3] != tmp_data[8]) {
axis_changed_mask_ |= (1<<3);
axis[3] = tmp_data[8];
}
if (axis[4] != tmp_data[9]) {
axis_changed_mask_ |= (1<<4);
axis[4] = tmp_data[9];
}
//limit for masking
mask = 0x1;
for (uint16_t i = 6; i < (64); i++ ) {
axis_mask_ |= mask;
if(tmp_data[i] != axis[i]) {
axis_changed_mask_ |= mask;
axis[i] = tmp_data[i];
}
DBGPrintf("\n");
//DBGPrintf("Axis Mask (axis_mask_, axis_changed_mask_; %d, %d\n", axis_mask_,axis_changed_mask_);
joystickEvent = true;
connected_ = true;
mask <<= 1; // shift down the mask.
DBGPrintf("%02x ", axis[i]);
}
DBGPrintf("\n");
//DBGPrintf("Axis Mask (axis_mask_, axis_changed_mask_; %d, %d\n", axis_mask_,axis_changed_mask_);
joystickEvent = true;
connected_ = true;
}
return false;
}
@@ -926,6 +968,9 @@ bool JoystickController::mapNameToJoystickType(const uint8_t *remoteName)
} else if (strncmp((const char *)remoteName, "Navigation Controller", 21) == 0) {
DBGPrintf(" JoystickController::mapNameToJoystickType %x %s - set to PS3\n", (uint32_t)this, remoteName);
joystickType_ = PS3;
} else if (strncmp((const char *)remoteName, "Motion Controller", 17) == 0) {
DBGPrintf(" JoystickController::mapNameToJoystickType %x %s - set to PS3 Motion\n", (uint32_t)this, remoteName);
joystickType_ = PS3_MOTION;
} else if (strncmp((const char *)remoteName, "Xbox Wireless", 13) == 0) {
DBGPrintf(" JoystickController::mapNameToJoystickType %x %s - set to XBOXONE\n", (uint32_t)this, remoteName);
joystickType_ = XBOXONE;
@@ -944,6 +989,7 @@ bool JoystickController::remoteNameComplete(const uint8_t *remoteName)
switch (joystickType_) {
case PS4: special_process_required = SP_NEED_CONNECT; break;
case PS3: special_process_required = SP_PS3_IDS; break;
case PS3_MOTION: special_process_required = SP_PS3_IDS; break;
default:
break;
}
@@ -954,28 +1000,37 @@ bool JoystickController::remoteNameComplete(const uint8_t *remoteName)
void JoystickController::connectionComplete()
{
DBGPrintf(" JoystickController::connectionComplete %x joystick type %d\n", (uint32_t)this, joystickType_);
if (joystickType_ == PS4) {
uint8_t packet[2];
packet[0] = 0x43; // HID BT Get_report (0x40) | Report Type (Feature 0x03)
packet[1] = 0x02; // Report ID
DBGPrintf("Set PS4 report\n");
delay(1);
btdriver_->sendL2CapCommand(packet, sizeof(packet), 0x40);

} else if (joystickType_ == PS3) {
uint8_t packet[6];
packet[0] = 0x53; // HID BT Set_report (0x50) | Report Type (Feature 0x03)
packet[1] = 0xF4; // Report ID
packet[2] = 0x42; // Special PS3 Controller enable commands
packet[3] = 0x03;
packet[4] = 0x00;
packet[5] = 0x00;

DBGPrintf("enable six axis\n");
delay(1);
btdriver_->sendL2CapCommand(packet, sizeof(packet), BluetoothController::CONTROL_SCID);
switch (joystickType_) {
case PS4:
{
uint8_t packet[2];
packet[0] = 0x43; // HID BT Get_report (0x40) | Report Type (Feature 0x03)
packet[1] = 0x02; // Report ID
DBGPrintf("Set PS4 report\n");
delay(1);
btdriver_->sendL2CapCommand(packet, sizeof(packet), 0x40);
}
break;
case PS3:
{
uint8_t packet[6];
packet[0] = 0x53; // HID BT Set_report (0x50) | Report Type (Feature 0x03)
packet[1] = 0xF4; // Report ID
packet[2] = 0x42; // Special PS3 Controller enable commands
packet[3] = 0x03;
packet[4] = 0x00;
packet[5] = 0x00;

DBGPrintf("enable six axis\n");
delay(1);
btdriver_->sendL2CapCommand(packet, sizeof(packet), BluetoothController::CONTROL_SCID);
}
break;
case PS3_MOTION:
setLEDs(0, 0xff, 0); // Maybe try setting to green?
default:
break;
}

}

void JoystickController::release_bluetooth()
@@ -989,15 +1044,29 @@ void JoystickController::release_bluetooth()


bool JoystickController::PS3Pair(uint8_t* bdaddr) {
if ((joystickType_ != PS3) || !driver_) return false; // not a PS2 nor plugged into USB...

/* Set the internal Bluetooth address */
txbuf_[0] = 0x01;
txbuf_[1] = 0x00;

for(uint8_t i = 0; i < 6; i++)
txbuf_[i + 2] = bdaddr[5 - i]; // Copy into buffer, has to be written reversed, so it is MSB first

// bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0xF5), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data
return driver_->sendControlPacket(0x21, 9, 0x3f5, 0, 8, txbuf_);
if (!driver_) return false;
if (joystickType_ == PS3) {
/* Set the internal Bluetooth address */
txbuf_[0] = 0x01;
txbuf_[1] = 0x00;

for(uint8_t i = 0; i < 6; i++)
txbuf_[i + 2] = bdaddr[5 - i]; // Copy into buffer, has to be written reversed, so it is MSB first

// bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0xF5), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data
return driver_->sendControlPacket(0x21, 9, 0x3f5, 0, 8, txbuf_);
} else if (joystickType_ == PS3_MOTION) {
// Slightly different than other PS3 units...
txbuf_[0] = 0x05;
for(uint8_t i = 0; i < 6; i++)
txbuf_[i + 1] = bdaddr[i]; // Order different looks like LSB First?

txbuf_[7] = 0x10;
txbuf_[8] = 0x01;
txbuf_[9] = 0x02;
txbuf_[10] = 0x12;
// bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0xF5), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data
return driver_->sendControlPacket(0x21, 9, 0x305, 0, 11, txbuf_);
}
return false;
}

+ 1
- 0
keywords.txt View File

@@ -90,6 +90,7 @@ setRumbleOn KEYWORD2
setLEDs KEYWORD2
joystickType KEYWORD2
PS3 LITERAL1
PS3_MOTION LITERAL1
PS4 LITERAL1
XBOXONE LITERAL1
XBOX360 LITERAL1

+ 1
- 1
mouse.cpp View File

@@ -35,7 +35,7 @@ void MouseController::init()
hidclaim_t MouseController::claim_collection(USBHIDParser *driver, Device_t *dev, uint32_t topusage)
{
// only claim Desktop/Mouse
if (topusage != 0x10002) return CLAIM_NO;
if ((topusage != 0x10002) && (topusage != 0x10001)) return CLAIM_NO;
// only claim from one physical device
if (mydevice != NULL && dev != mydevice) return CLAIM_NO;
mydevice = dev;

Loading…
Cancel
Save