Skip to content

Commit

Permalink
WIP very quick and dirty DualSense support
Browse files Browse the repository at this point in the history
  • Loading branch information
JibbSmart committed Nov 17, 2020
1 parent 9784995 commit ec58a58
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 25 deletions.
9 changes: 8 additions & 1 deletion JoyShockLibrary/InputHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ bool handle_input(JoyShock *jc, uint8_t *packet, int len, bool &hasIMU) {
jc->delta_time = (float)(std::chrono::duration_cast<std::chrono::microseconds>(time_now - jc->last_polled).count() / 1000000.0);
jc->last_polled = time_now;
// ds4
if (jc->is_ds4) {
if (jc->controller_type == ControllerType::s_ds4) {
int indexOffset = 0;
bool isValid = true;
if (!jc->is_usb) {
Expand Down Expand Up @@ -140,6 +140,13 @@ bool handle_input(JoyShock *jc, uint8_t *packet, int len, bool &hasIMU) {
return true;
}

if (jc->controller_type == ControllerType::s_ds) {
printf("%d: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
packet[0], packet[1], packet[2], packet[3], packet[4], packet[5], packet[6], packet[7], packet[8], packet[9],
packet[10], packet[11], packet[12], packet[13], packet[14], packet[15], packet[16], packet[17], packet[18], packet[19], packet[20]);
return true;
}

// most of this JoyCon and Pro Controller stuff is adapted from MFosse's Joycon driver.

// bluetooth button pressed packet:
Expand Down
56 changes: 50 additions & 6 deletions JoyShockLibrary/JoyShock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@
#define _wcsdup wcsdup
#endif

enum ControllerType { n_switch, s_ds4, s_ds };

// PS5 stuff
#define DS_VENDOR 0x054C
#define DS_USB 0x0CE6

// PS4 stuff
// http://www.psdevwiki.com/ps4/DS4-USB
// http://www.psdevwiki.com/ps4/DS4-BT
Expand Down Expand Up @@ -100,8 +106,8 @@ class JoyShock {
bool has_user_cal_stick_r = false;
bool has_user_cal_sensor = false;

bool is_ds4 = false;
bool is_usb = false; // it's ds4_bt because joycons aren't using that distinction (yet?)
ControllerType controller_type = ControllerType::n_switch;
bool is_usb = false;

unsigned char small_rumble = 0;
unsigned char big_rumble = 0;
Expand Down Expand Up @@ -310,17 +316,24 @@ class JoyShock {
dev->product_id == DS4_USB_V2) {
this->name = std::string("DualShock 4");
this->left_right = 3; // left and right?
this->is_ds4 = true;
this->controller_type = ControllerType::s_ds4;
this->is_usb = (dev->product_id != DS4_BT);
}

if (dev->product_id == DS_USB) {
this->name = std::string("DualSense");
this->left_right = 3; // left and right?
this->controller_type = ControllerType::s_ds;
this->is_usb = true; // for now, only usb
}

this->serial = _wcsdup(dev->serial_number);
this->intHandle = uniqueHandle;

//printf("Found device %c: %ls %s\n", L_OR_R(this->left_right), this->serial, dev->path);
this->handle = hid_open_path(dev->path);

if (this->is_ds4) {
if (this->controller_type == ControllerType::s_ds4) {
unsigned char buf[64];
memset(buf, 0, 64);

Expand Down Expand Up @@ -349,7 +362,7 @@ class JoyShock {
}

int get_gyro_average_window_total_samples_for_device() {
if (this->is_ds4) {
if (this->controller_type == ControllerType::s_ds4) {
// 250 samples per second
return 250 * this->gyro_average_window_seconds;
}
Expand Down Expand Up @@ -728,7 +741,7 @@ class JoyShock {

// Enable IMU data
printf("Enabling IMU data...\n");
if (is_ds4)
if (controller_type == ControllerType::s_ds4)
{
if (is_usb)
{
Expand Down Expand Up @@ -1015,6 +1028,37 @@ class JoyShock {
enable_gyro_ds4_bt(buf, 78);
}

// placeholder to get things working quickly. overdue for a refactor
void init_ds_usb() {
// initialise stuff
memset(factory_stick_cal, 0, 0x12);
memset(device_colours, 0, 0xC);
memset(user_stick_cal, 0, 0x16);
memset(sensor_model, 0, 0x6);
memset(stick_model, 0, 0x12);
memset(factory_sensor_cal, 0, 0x18);
memset(user_sensor_cal, 0, 0x1A);
memset(factory_sensor_cal_calm, 0, 0xC);
memset(user_sensor_cal_calm, 0, 0xC);
memset(sensor_cal, 0, sizeof(sensor_cal));
memset(stick_cal_x_l, 0, sizeof(stick_cal_x_l));
memset(stick_cal_y_l, 0, sizeof(stick_cal_y_l));
memset(stick_cal_x_r, 0, sizeof(stick_cal_x_r));
memset(stick_cal_y_r, 0, sizeof(stick_cal_y_r));
stick_cal_x_l[0] =
stick_cal_y_l[0] =
stick_cal_x_r[0] =
stick_cal_y_r[0] = 0;
stick_cal_x_l[1] =
stick_cal_y_l[1] =
stick_cal_x_r[1] =
stick_cal_y_r[1] = 127;
stick_cal_x_l[2] =
stick_cal_y_l[2] =
stick_cal_x_r[2] =
stick_cal_y_r[2] = 255;
}

// this is mostly copied from init_usb() below, but modified to speak DS4
void init_ds4_usb() {
unsigned char buf[31];
Expand Down
75 changes: 57 additions & 18 deletions JoyShockLibrary/JoyShockLibrary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,19 @@ void pollIndividualLoop(JoyShock *jc) {
int numTimeOuts = 0;
int numNoIMU = 0;
bool hasIMU = false;
int noIMULimit = jc->is_ds4 ? 250 : 67;
int noIMULimit;
switch (jc->controller_type)
{
case ControllerType::s_ds4:
noIMULimit = 250;
break;
case ControllerType::s_ds:
noIMULimit = 250;
break;
case ControllerType::n_switch:
default:
noIMULimit = 67;
}
float wakeupTimer = 0.0f;

while (!jc->cancel_thread) {
Expand All @@ -67,7 +79,7 @@ void pollIndividualLoop(JoyShock *jc) {
else
{
// try wake up the controller with the appropriate message
if (jc->is_ds4)
if (jc->controller_type != ControllerType::n_switch)
{
// TODO
}
Expand Down Expand Up @@ -127,7 +139,8 @@ void pollIndividualLoop(JoyShock *jc) {
_pollCallback(jc->intHandle, jc->simple_state, jc->last_simple_state, jc->imu_state, jc->last_imu_state, jc->delta_time);
}
// touchpad will have its own callback so that it doesn't change the existing api
if (jc->is_ds4 && _pollTouchCallback != nullptr) {
// todo: s_ds (DualSense) should be able to do this, too
if (jc->controller_type == ControllerType::s_ds4 && _pollTouchCallback != nullptr) {
_pollTouchCallback(jc->intHandle, jc->touch_state, jc->last_touch_state, jc->delta_time);
}
_callbackLock.unlock_shared();
Expand All @@ -149,7 +162,7 @@ void pollIndividualLoop(JoyShock *jc) {
}

// dualshock 4 bluetooth might need waking up
if (jc->is_ds4 && !jc->is_usb)
if (jc->controller_type == ControllerType::s_ds4 && !jc->is_usb)
{
wakeupTimer += jc->delta_time;
if (wakeupTimer > 30.0f)
Expand All @@ -166,7 +179,7 @@ void pollIndividualLoop(JoyShock *jc) {
int JslConnectDevices()
{
// for writing to console:
//freopen("CONOUT$", "w", stdout);
freopen("CONOUT$", "w", stdout);
if (_joyshocks.size() > 0) {
// already connected? clean up old stuff!
JslDisconnectAndDisposeAll();
Expand Down Expand Up @@ -238,17 +251,38 @@ int JslConnectDevices()
}
hid_free_enumeration(devs);

// find dualsenses
devs = hid_enumerate(DS_VENDOR, 0x0);
cur_dev = devs;
while (cur_dev) {
// do we need to confirm vendor id if this is what we asked for?
if (cur_dev->vendor_id == DS_VENDOR) {
// usb or bluetooth ds4:
printf("DS\n");
if (cur_dev->product_id == DS_USB) {
JoyShock* jc = new JoyShock(cur_dev, GetUniqueHandle());
_joyshocks.emplace(jc->intHandle, jc);
}
}

cur_dev = cur_dev->next;
}
hid_free_enumeration(devs);

// init joyshocks:
for (std::pair<int, JoyShock*> pair : _joyshocks)
{
JoyShock* jc = pair.second;
if (jc->is_ds4) {
if (jc->controller_type == ControllerType::s_ds4) {
if (!jc->is_usb) {
jc->init_ds4_bt();
}
else {
jc->init_ds4_usb();
}
} // dualsense
else if (jc->controller_type == ControllerType::s_ds)
{
} // charging grip
else if (jc->is_usb) {
//printf("USB\n");
Expand All @@ -273,7 +307,7 @@ int JslConnectDevices()
for (std::pair<int, JoyShock*> pair : _joyshocks)
{
JoyShock *jc = pair.second;
if (jc->is_ds4) {
if (jc->controller_type != ControllerType::n_switch) {
// don't do joycon LED stuff with DS4
continue;
}
Expand Down Expand Up @@ -321,13 +355,16 @@ void JslDisconnectAndDisposeAll()
// threads for polling
jc->cancel_thread = true;
jc->thread->join();
if (jc->is_ds4) {
if (jc->controller_type == ControllerType::s_ds4) {
if (jc->is_usb) {
jc->deinit_ds4_usb();
}
else {
jc->deinit_ds4_bt();
}
}
else if (jc->controller_type == ControllerType::s_ds) {

} // TODO: Charging grip? bluetooth?
else if (jc->is_usb) {
jc->deinit_usb();
Expand Down Expand Up @@ -570,7 +607,7 @@ float JslGetStickStep(int deviceId)
{
JoyShock* jc = GetJoyShockFromHandle(deviceId);
if (jc != nullptr) {
if (jc->is_ds4) {
if (jc->controller_type != ControllerType::n_switch) {
return 1.0 / 128.0;
}
else {
Expand All @@ -589,15 +626,15 @@ float JslGetTriggerStep(int deviceId)
{
JoyShock* jc = GetJoyShockFromHandle(deviceId);
if (jc != nullptr) {
return jc->is_ds4 ? 1 / 256.0 : 1.0;
return jc->controller_type != ControllerType::n_switch ? 1 / 256.0 : 1.0;
}
return 1.0f;
}
float JslGetPollRate(int deviceId)
{
JoyShock* jc = GetJoyShockFromHandle(deviceId);
if (jc != nullptr) {
return jc->is_ds4 ? 250.0 : 66.6667;
return jc->controller_type != ControllerType::n_switch ? 250.0 : 66.6667;
}
return 0.0f;
}
Expand Down Expand Up @@ -661,12 +698,14 @@ int JslGetControllerType(int deviceId)
{
JoyShock* jc = GetJoyShockFromHandle(deviceId);
if (jc != nullptr) {
if (jc->is_ds4)
switch (jc->controller_type)
{
case ControllerType::s_ds4:
return JS_TYPE_DS4;
}
else
{
case ControllerType::s_ds:
return JS_TYPE_DS;
default:
case ControllerType::n_switch:
return jc->left_right;
}
}
Expand Down Expand Up @@ -695,7 +734,7 @@ int JslGetControllerColour(int deviceId)
void JslSetLightColour(int deviceId, int colour)
{
JoyShock* jc = GetJoyShockFromHandle(deviceId);
if (jc != nullptr && jc->is_ds4) {
if (jc != nullptr && jc->controller_type == ControllerType::s_ds4) {
jc->led_r = (colour >> 16) & 0xff;
jc->led_g = (colour >> 8) & 0xff;
jc->led_b = colour & 0xff;
Expand All @@ -711,7 +750,7 @@ void JslSetLightColour(int deviceId, int colour)
void JslSetRumble(int deviceId, int smallRumble, int bigRumble)
{
JoyShock* jc = GetJoyShockFromHandle(deviceId);
if (jc != nullptr && jc->is_ds4) {
if (jc != nullptr && jc->controller_type == ControllerType::s_ds4) {
jc->small_rumble = smallRumble;
jc->big_rumble = bigRumble;
jc->set_ds4_rumble_light(
Expand All @@ -726,7 +765,7 @@ void JslSetRumble(int deviceId, int smallRumble, int bigRumble)
void JslSetPlayerNumber(int deviceId, int number)
{
JoyShock* jc = GetJoyShockFromHandle(deviceId);
if (jc != nullptr && !jc->is_ds4) {
if (jc != nullptr && jc->controller_type == ControllerType::n_switch) {
jc->player_number = number;
unsigned char buf[64];
memset(buf, 0x00, 0x40);
Expand Down
1 change: 1 addition & 0 deletions JoyShockLibrary/JoyShockLibrary.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#define JS_TYPE_JOYCON_RIGHT 2
#define JS_TYPE_PRO_CONTROLLER 3
#define JS_TYPE_DS4 4
#define JS_TYPE_DS 5

#define JS_SPLIT_TYPE_LEFT 1
#define JS_SPLIT_TYPE_RIGHT 2
Expand Down

0 comments on commit ec58a58

Please sign in to comment.