From 3ad7b18516bce9f37fe4933be2732b29f2d6552b Mon Sep 17 00:00:00 2001 From: dualshock-tools Date: Wed, 14 Aug 2024 12:28:58 +0200 Subject: [PATCH] Add battery indicator --- core.js | 178 +++++++++++++++++++++++++++++++++++++++++++++-------- index.html | 20 ++++-- 2 files changed, 168 insertions(+), 30 deletions(-) diff --git a/core.js b/core.js index c8e428a..f919d6c 100644 --- a/core.js +++ b/core.js @@ -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 = "" + l("clone") + ""; - disable_btn = true; + disable_btn |= 1; } clear_info(); @@ -145,7 +152,7 @@ async function ds4_info() { } } catch(e) { ooc = "" + l("clone") + ""; - 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 = ''; + var bolt_txt = ''; + if(is_charging) + bolt_txt = ''; + bat_txt = bat_charge + "%" + ' ' + bolt_txt + ' ' + icon_full; + + if(is_error) { + bat_txt = '' + l("error") + ''; + } + 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.") + "
" + 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.") + "
" + 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(); diff --git a/index.html b/index.html index 2873c5e..d5ef6e6 100644 --- a/index.html +++ b/index.html @@ -10,9 +10,14 @@ integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous"> + +