Add battery indicator

This commit is contained in:
dualshock-tools 2024-08-14 12:28:58 +02:00
parent 225ba206bc
commit 3ad7b18516
2 changed files with 168 additions and 30 deletions

178
core.js
View File

@ -1,7 +1,10 @@
var device = null;
var devname = "";
var mode = 0;
var disable_btn = false;
// bitmask: 1: clone, 2: update ds5 firmware, 4: battery low, 8: ds-edge not supported
var disable_btn = 0;
var last_disable_btn = 0;
var lang_orig_text = {};
var lang_cur = {};
@ -94,11 +97,18 @@ function is_rare(hw_ver) {
async function ds4_info() {
try {
var ooc = l("unknown");
var is_clone = false;
const view = lf("ds4_info", await device.receiveFeatureReport(0xa3));
var cmd = view.getUint8(0, true);
if(cmd != 0xa3 || view.buffer.byteLength != 49) {
return false;
if(cmd != 0xa3 || view.buffer.byteLength < 49) {
if(view.buffer.byteLength != 49) {
ooc = l("clone");
is_clone = true;
}
}
var k1 = new TextDecoder().decode(view.buffer.slice(1, 0x10));
@ -110,19 +120,16 @@ async function ds4_info() {
var hw_ver_minor= view.getUint16(0x23, true)
var sw_ver_major= view.getUint32(0x25, true)
var sw_ver_minor= view.getUint16(0x25+4, true)
var ooc = l("unknown");
ooc = l("original");
var is_clone = false;
try {
const view = await device.receiveFeatureReport(0x81);
ooc = l("original");
if(!is_clone) {
const view = await device.receiveFeatureReport(0x81);
ooc = l("original");
}
} catch(e) {
la("clone");
is_clone = true;
ooc = "<font color='red'><b>" + l("clone") + "</b></font>";
disable_btn = true;
disable_btn |= 1;
}
clear_info();
@ -145,7 +152,7 @@ async function ds4_info() {
}
} catch(e) {
ooc = "<font color='red'><b>" + l("clone") + "</b></font>";
disable_btn = true;
disable_btn |= 1;
}
return true;
}
@ -516,7 +523,7 @@ async function ds5_info() {
old_controller = build_date.search(/ 2020| 2021/);
if(old_controller != -1) {
la("ds5_info_error", {"r": "old"})
disable_btn = true;
disable_btn |= 2;
return true;
}
@ -784,7 +791,7 @@ async function disconnect() {
mode = 0;
device.close();
device = null;
disable_btn = false;
disable_btn = 0;
reset_circularity();
$("#offlinebar").show();
$("#onlinebar").hide();
@ -1118,6 +1125,46 @@ function refresh_sticks() {
setTimeout(timeout_ok, 20);
}
var last_bat_txt = "";
var last_bat_disable = null;
function bat_percent_to_text(bat_charge, is_charging, is_error) {
var icon_txt = "";
if(bat_charge < 20) {
icon_txt = 'fa-battery-empty';
} else if(bat_charge < 40) {
icon_txt = 'fa-battery-quarter';
} else if(bat_charge < 60) {
icon_txt = 'fa-battery-half';
} else if(bat_charge < 80) {
icon_txt = 'fa-battery-three-quarters';
} else {
icon_txt = 'fa-battery-full';
}
var icon_full = '<i class="fa-solid ' + icon_txt + '"></i>';
var bolt_txt = '';
if(is_charging)
bolt_txt = '<i class="fa-solid fa-bolt"></i>';
bat_txt = bat_charge + "%" + ' ' + bolt_txt + ' ' + icon_full;
if(is_error) {
bat_txt = '<font color="red">' + l("error") + '</font>';
}
return bat_txt;
}
function update_battery_status(bat_capacity, cable_connected, is_charging, is_error) {
var bat_txt = bat_percent_to_text(bat_capacity, is_charging);
var can_use_tool = (bat_capacity >= 30 && cable_connected && !is_error);
if(bat_txt != last_bat_txt) {
$("#d-bat").html(bat_txt);
last_bat_txt = bat_txt;
}
}
function process_ds4_input(data) {
var lx = data.data.getUint8(0);
var ly = data.data.getUint8(1);
@ -1137,8 +1184,46 @@ function process_ds4_input(data) {
ll_updated = true;
refresh_sticks();
}
// Read battery
var bat = data.data.getUint8(29);
var bat_data = bat & 0x0f;
var bat_status = (bat >> 4) & 1;
var bat_capacity = 0;
var cable_connected = false;
var is_charging = false;
var is_error = false;
if(bat_status == 1) {
cable_connected = true;
if(bat_data < 10) {
bat_capacity = Math.min(bat_data * 10 + 5, 100);
is_charging = true;
} else if(bat_data == 10) {
bat_capacity = 100;
is_charging = true;
} else if(bat_data == 11) {
bat_capacity = 100;
// charged
} else {
// error
bat_capacity = 0;
is_error = true;
}
} else {
cable_connected = false;
if(bat_data < 10) {
bat_capacity = bat_data * 10 + 5;
} else {
bat_capacity = 100;
}
}
update_battery_status(bat_capacity, cable_connected, is_charging, is_error);
}
function process_ds_input(data) {
var lx = data.data.getUint8(0);
var ly = data.data.getUint8(1);
@ -1158,6 +1243,30 @@ function process_ds_input(data) {
ll_updated = true;
refresh_sticks();
}
var bat = data.data.getUint8(52);
var bat_charge = bat & 0x0f;
var bat_status = bat >> 4;
var bat_capacity = 0;
var cable_connected = false;
var is_charging = false;
var is_error = false;
if(bat_status == 0) {
bat_capacity = Math.min(bat_charge * 10 + 5, 100);
} else if(bat_status == 1) {
bat_capacity = Math.max(bat_charge * 10 + 5, 100);
is_charging = true;
cable_connected = true;
} else if(bat_status == 2) {
bat_capacity = 100;
cable_connected = true;
} else {
is_error = true;
}
update_battery_status(bat_capacity, cable_connected, is_charging, is_error);
}
async function continue_connection(report) {
@ -1202,7 +1311,7 @@ async function continue_connection(report) {
connected = true;
mode = 0;
devname = l("Sony DualSense Edge");
disable_btn = true;
disable_btn |= 8;
}
} else {
$("#btnconnect").prop("disabled", false);
@ -1228,17 +1337,8 @@ async function continue_connection(report) {
return;
}
if(disable_btn) {
if(device.productId == 0x0ce6) {
show_popup(l("This DualSense controller has outdated firmware.") + "<br>" + l("Please update the firmware and try again."), true);
} else if(device.productId == 0x0df2) {
show_popup(l("Calibration of the DualSense Edge is not currently supported."));
} else {
show_popup(l("The device appears to be a DS4 clone. All functionalities are disabled."));
}
}
$(".ds-btn").prop("disabled", disable_btn);
if(disable_btn != 0)
update_disable_btn();
$("#btnconnect").prop("disabled", false);
$("#connectspinner").hide();
@ -1250,10 +1350,36 @@ async function continue_connection(report) {
}
}
function update_disable_btn() {
if(disable_btn == last_disable_btn)
return;
if(disable_btn == 0) {
$(".ds-btn").prop("disabled", false);
last_disable_btn = 0;
return;
}
$(".ds-btn").prop("disabled", true);
// show only one popup
if(disable_btn & 1 && !(last_disable_btn & 1)) {
show_popup(l("The device appears to be a DS4 clone. All functionalities are disabled."));
} else if(disable_btn & 2 && !(last_disable_btn & 2)) {
show_popup(l("This DualSense controller has outdated firmware.") + "<br>" + l("Please update the firmware and try again."), true);
} else if(disable_btn & 8 && !(last_disable_btn & 8)) {
show_popup(l("Calibration of the DualSense Edge is not currently supported."));
} else if(disable_btn & 4 && !(last_disable_btn & 4)) {
show_popup(l("Please charge controller battery over 30% to use this tool."));
}
last_disable_btn = disable_btn;
}
async function connect() {
gj = crypto.randomUUID();
reset_circularity();
la("begin");
last_bat_txt = "";
try {
$("#btnconnect").prop("disabled", true);
$("#connectspinner").show();

View File

@ -10,9 +10,14 @@
integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH"
crossorigin="anonymous">
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.6.0/css/fontawesome.min.css"
integrity="sha384-NvKbDTEnL+A8F/AA5Tc5kmMLSJHUO868P+lDtTpJIeQdGYaUIuLr4lVGOEA1OcMy"
crossorigin="anonymous">
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.4.2/css/fontawesome.min.css"
integrity="sha384-BY+fdrpOd3gfeRvTSMT+VUZmA728cfF9Z2G42xpaRkUGu2i3DyzpTURDo5A6CaLK"
href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.6.0/css/all.min.css"
integrity="sha384-h/hnnw1Bi4nbpD6kE7nYfCXzovi622sY5WBxww8ARKwpdLj5kUWjRuyiXaD1U2JT"
crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.7.1.min.js"
@ -97,7 +102,14 @@
</div>
<div id="onlinebar" class="vstack p-2" style="display: none;">
<div class="hstack gap-2"><p><b class="ds-i18n">Connected to:</b></p><p id="devname"></p></div>
<div class="row">
<div class="col-sm-9 hstack">
<p><b class="ds-i18n">Connected to:</b></p>&nbsp;<p id="devname"></p>
</div>
<div class="col-sm-3">
<p id="d-bat" style="text-align: right;"></p>
</div>
</div>
<button type="button" class="btn btn-outline-secondary ds-i18n" onclick="disconnect()">Disconnect</button><br>
</div>
@ -508,7 +520,7 @@
<div class="container">
<footer>
<div class="d-flex flex-column flex-sm-row justify-content-between py-4 my-4 border-top" id="footbody">
<p><span class="ds-i18n">Version</span> 1.3 (2024-06-21) - <a href="#" class="ds-i18n" onclick="show_donate_modal();">Support this project</a>&nbsp;<span id="authorMsg"></span></p>
<p><span class="ds-i18n">Version</span> 1.4 (2024-08-14) - <a href="#" class="ds-i18n" onclick="show_donate_modal();">Support this project</a>&nbsp;<span id="authorMsg"></span></p>
<ul class="list-unstyled d-flex">
<li class="ms-3"><a class="link-body-emphasis" href="mailto:ds4@the.al" target="_blank"><svg class="bi" width="24" height="24"><use xlink:href="#mail"/></svg></a></li>