From 0c812c6a4f58a3d8201b30ba3bfd7dae3ac2be36 Mon Sep 17 00:00:00 2001 From: dualshock-tools Date: Mon, 22 Apr 2024 16:07:45 +0200 Subject: [PATCH] Add analytics support --- core.js | 272 ++++++++++++++++++++++++++++++++--------------------- index.html | 3 +- 2 files changed, 167 insertions(+), 108 deletions(-) diff --git a/core.js b/core.js index c40cffb..3caab1e 100644 --- a/core.js +++ b/core.js @@ -6,6 +6,8 @@ var disable_btn = false; var lang_orig_text = {}; var lang_cur = {}; var lang_disabled = true; +var gj = 0; +var gu = 0; var available_langs = { "zh_cn": { "name": "中文", "file": "zh_cn.json"}, @@ -18,12 +20,18 @@ var available_langs = { "tr_tr": { "name": "Türkçe", "file": "tr_tr.json"}, }; +function buf2hex(buffer) { + return [...new Uint8Array(buffer)] .map(x => x.toString(16).padStart(2, '0')) .join(''); +} + function dec2hex(i) { return (i+0x10000).toString(16).substr(-4).toUpperCase(); } + function dec2hex32(i) { return (i+0x100000000).toString(16).substr(-8).toUpperCase(); } + function dec2hex8(i) { return (i+0x100).toString(16).substr(-2).toUpperCase(); } @@ -49,11 +57,12 @@ function ds4_hw_to_bm(hw_ver) { async function ds4_info() { try { - const view = await device.receiveFeatureReport(0xa3); + const view = lf("ds4_info", await device.receiveFeatureReport(0xa3)); var cmd = view.getUint8(0, true); - if(cmd != 0xa3 || view.buffer.byteLength != 49) + if(cmd != 0xa3 || view.buffer.byteLength != 49) { return false; + } var k1 = new TextDecoder().decode(view.buffer.slice(1, 0x10)); var k2 = new TextDecoder().decode(view.buffer.slice(0x10, 0x20)); @@ -73,6 +82,7 @@ async function ds4_info() { const view = await device.receiveFeatureReport(0x81); ooc = l("original"); } catch(e) { + la("clone"); is_clone = true; ooc = "" + l("clone") + ""; disable_btn = true; @@ -100,6 +110,7 @@ async function ds4_info() { } async function ds4_reset() { + la("ds4_reset"); try { await device.sendFeatureReport(0xa0, alloc_req(0x80, [4,1,0])) } catch(error) { @@ -107,6 +118,7 @@ async function ds4_reset() { } async function ds5_reset() { + la("ds5_reset"); try { await device.sendFeatureReport(0x80, alloc_req(0x80, [1,1,0])) } catch(error) { @@ -114,6 +126,7 @@ async function ds5_reset() { } async function ds4_calibrate_range_begin(perm_ch) { + la("ds4_calibrate_range_begin", {"p": perm_ch}); var err = l("Range calibration failed: "); try { if(perm_ch) { @@ -142,6 +155,7 @@ async function ds4_calibrate_range_begin(perm_ch) { } async function ds4_calibrate_range_end(perm_ch) { + la("ds4_calibrate_range_end", {"p": perm_ch}); var err = l("Range calibration failed: "); try { // Write @@ -172,6 +186,7 @@ async function ds4_calibrate_range_end(perm_ch) { } async function ds4_calibrate_sticks_begin(has_perm_changes) { + la("ds4_calibrate_sticks_begin", {"p": has_perm_changes}); var err = l("Stick calibration failed: "); try { if(has_perm_changes) { @@ -202,6 +217,7 @@ async function ds4_calibrate_sticks_begin(has_perm_changes) { } async function ds4_calibrate_sticks_sample() { + la("ds4_calibrate_sticks_sample"); var err = l("Stick calibration failed: "); try { // Sample @@ -226,6 +242,7 @@ async function ds4_calibrate_sticks_sample() { } async function ds4_calibrate_sticks_end(has_perm_changes) { + la("ds4_calibrate_sticks_end", {"p": has_perm_changes}); var err = l("Stick calibration failed: "); try { // Write @@ -254,6 +271,7 @@ async function ds4_calibrate_sticks_end(has_perm_changes) { } async function ds4_calibrate_sticks() { + la("ds4_calibrate_sticks"); var err = l("Stick calibration failed: "); try { set_progress(0); @@ -312,7 +330,7 @@ async function ds4_calibrate_sticks() { async function ds4_nvstatus() { await device.sendFeatureReport(0x08, alloc_req(0x08, [0xff,0, 12])) - data = await device.receiveFeatureReport(0x11) + data = lf("ds4_nvstatus", await device.receiveFeatureReport(0x11)) // 1: temporary, 0: permanent ret = data.getUint8(1, false); if(ret == 1) { @@ -328,7 +346,7 @@ async function ds4_nvstatus() { async function ds5_nvstatus() { try { await device.sendFeatureReport(0x80, alloc_req(0x80, [3,3])) - data = await device.receiveFeatureReport(0x81) + data = lf("ds5_nvstatus", await device.receiveFeatureReport(0x81)) ret = data.getUint32(1, false); if(ret == 0x03030201) { $("#d-nvstatus").html("" + l("locked") + ""); @@ -347,8 +365,9 @@ async function ds5_nvstatus() { } async function ds4_getbdaddr() { + la("ds4_getbdaddr"); try { - data = await device.receiveFeatureReport(0x12) + data = await device.receiveFeatureReport(0x12); out = "" for(i=0;i<6;i++) { if(i >= 1) out += ":"; @@ -363,9 +382,10 @@ async function ds4_getbdaddr() { } async function ds5_getbdaddr() { + la("ds5_getbdaddr"); try { await device.sendFeatureReport(0x80, alloc_req(0x80, [9,2])) - data = await device.receiveFeatureReport(0x81) + data = await device.receiveFeatureReport(0x81); out = "" for(i=0;i<6;i++) { if(i >= 1) out += ":"; @@ -380,15 +400,17 @@ async function ds5_getbdaddr() { } async function ds4_nvlock() { + la("ds4_nvlock"); await device.sendFeatureReport(0xa0, alloc_req(0xa0, [10,1,0])) } async function ds4_nvunlock() { + la("ds4_nvunlock"); await device.sendFeatureReport(0xa0, alloc_req(0xa0, [10,2,0x3e,0x71,0x7f,0x89])) } async function ds5_info() { - const view = await device.receiveFeatureReport(0x20); + const view = lf("ds5_info", await device.receiveFeatureReport(0x20)); var cmd = view.getUint8(0, true); if(cmd != 0x20 || view.buffer.byteLength != 64) @@ -425,8 +447,8 @@ async function ds5_info() { } async function ds5_calibrate_sticks_begin(has_perm_changes) { + la("ds5_calibrate_sticks_begin", {"p": has_perm_changes}); var err = l("Range calibration failed: "); - console.log("::ds5_calibrate_sticks_begin(" + has_perm_changes + ")"); try { if(has_perm_changes) { await ds5_nvunlock(); @@ -454,8 +476,8 @@ async function ds5_calibrate_sticks_begin(has_perm_changes) { } async function ds5_calibrate_sticks_sample() { + la("ds5_calibrate_sticks_sample"); var err = l("Stick calibration failed: "); - console.log("::ds5_calibrate_sticks_sample()"); try { // Sample await device.sendFeatureReport(0x82, alloc_req(0x82, [3,1,1])) @@ -476,8 +498,8 @@ async function ds5_calibrate_sticks_sample() { } async function ds5_calibrate_sticks_end(has_perm_changes) { + la("ds5_calibrate_sticks_end", {"p": has_perm_changes}); var err = l("Stick calibration failed: "); - console.log("::ds5_calibrate_sticks_end(" + has_perm_changes + ")"); try { // Write await device.sendFeatureReport(0x82, alloc_req(0x82, [2,1,1])) @@ -505,6 +527,7 @@ async function ds5_calibrate_sticks_end(has_perm_changes) { } async function ds5_calibrate_sticks() { + la("ds5_fast_calibrate_sticks"); var err = l("Stick calibration failed: "); try { set_progress(0); @@ -567,6 +590,7 @@ async function ds5_calibrate_sticks() { } async function ds5_calibrate_range_begin(perm_ch) { + la("ds5_calibrate_range_begin", {"p": perm_ch}); var err = l("Range calibration failed: "); try { if(perm_ch) { @@ -595,6 +619,7 @@ async function ds5_calibrate_range_begin(perm_ch) { } async function ds5_calibrate_range_end(perm_ch) { + la("ds5_calibrate_range_end", {"p": perm_ch}); var err = l("Range calibration failed: "); try { // Write @@ -626,6 +651,7 @@ async function ds5_calibrate_range_end(perm_ch) { } async function ds5_nvlock() { + la("ds5_nvlock"); try { await device.sendFeatureReport(0x80, alloc_req(0x80, [3,1])) data = await device.receiveFeatureReport(0x83) @@ -637,19 +663,22 @@ async function ds5_nvlock() { } async function ds5_nvunlock() { -try { - await device.sendFeatureReport(0x80, alloc_req(0x80, [3,2, 101, 50, 64, 12])) - data = await device.receiveFeatureReport(0x83) -} catch(e) { - await new Promise(r => setTimeout(r, 500)); - close_calibrate_window(); - return show_popup(l("NVS Unlock failed: ") + e); -} + la("ds5_nvunlock"); + try { + await device.sendFeatureReport(0x80, alloc_req(0x80, [3,2, 101, 50, 64, 12])) + data = await device.receiveFeatureReport(0x83) + } catch(e) { + await new Promise(r => setTimeout(r, 500)); + close_calibrate_window(); + return show_popup(l("NVS Unlock failed: ") + e); + } } async function disconnect() { + la("disconnect"); if(device == null) return; + gj = 0; mode = 0; device.close(); device = null; @@ -662,6 +691,7 @@ async function disconnect() { } function handleDisconnectedDevice(e) { + la("disconnected"); console.log("Disconnected: " + e.device.productName) disconnect(); } @@ -706,11 +736,13 @@ function welcome_modal() { } function welcome_accepted() { + la("welcome_accepted"); createCookie("welcome_accepted", "1"); $("#welcomeModal").modal("hide"); } function gboot() { + gu = crypto.randomUUID(); window.addEventListener('DOMContentLoaded', function() { lang_init(); welcome_modal(); @@ -743,101 +775,104 @@ function alloc_req(id, data=[]) { } async function connect() { -try { - $("#btnconnect").prop("disabled", true); - $("#connectspinner").show(); - await new Promise(r => setTimeout(r, 100)); - - let ds4v1 = { vendorId: 0x054c, productId: 0x05c4 }; - let ds4v2 = { vendorId: 0x054c, productId: 0x09cc }; - let ds5 = { vendorId: 0x054c, productId: 0x0ce6 }; - let ds5edge = { vendorId: 0x054c, productId: 0x0df2 }; - let requestParams = { filters: [ds4v1,ds4v2,ds5,ds5edge] }; - - var devices = await navigator.hid.getDevices(); - if (devices.length == 0) { - devices = await navigator.hid.requestDevice(requestParams); - } + gj = crypto.randomUUID(); + la("begin"); + try { + $("#btnconnect").prop("disabled", true); + $("#connectspinner").show(); + await new Promise(r => setTimeout(r, 100)); - if (devices.length == 0) { - $("#btnconnect").prop("disabled", false); - $("#connectspinner").hide(); - return; - } - - if (devices.length > 1) { - $("#btnconnect").prop("disabled", false); - $("#connectspinner").hide(); - show_popup(l("Please connect only one controller at time.")); - return; - } - - await devices[0].open(); - - device = devices[0] - - var connected = false - if(device.productId == 0x05c4) { - if(await ds4_info()) { - connected = true - mode = 1; - devname = l("Sony DualShock 4 V1"); + let ds4v1 = { vendorId: 0x054c, productId: 0x05c4 }; + let ds4v2 = { vendorId: 0x054c, productId: 0x09cc }; + let ds5 = { vendorId: 0x054c, productId: 0x0ce6 }; + let ds5edge = { vendorId: 0x054c, productId: 0x0df2 }; + let requestParams = { filters: [ds4v1,ds4v2,ds5,ds5edge] }; + + var devices = await navigator.hid.getDevices(); + if (devices.length == 0) { + devices = await navigator.hid.requestDevice(requestParams); } - } else if(device.productId == 0x09cc) { - if(await ds4_info()) { - connected = true - mode = 1; - devname = l("Sony DualShock 4 V2"); + + if (devices.length == 0) { + $("#btnconnect").prop("disabled", false); + $("#connectspinner").hide(); + return; } - } else if(device.productId == 0x0ce6) { - if(await ds5_info()) { - connected = true - mode = 2; - devname = l("Sony DualSense"); + + if (devices.length > 1) { + $("#btnconnect").prop("disabled", false); + $("#connectspinner").hide(); + show_popup(l("Please connect only one controller at time.")); + return; } - } else if(device.productId == 0x0df2) { - if(await ds5_info()) { - connected = true - mode = 0; - devname = l("Sony DualSense Edge"); - disable_btn = true; - } - } else { - $("#btnconnect").prop("disabled", false); - $("#connectspinner").hide(); - show_popup(l("Connected invalid device: ") + dec2hex(device.vendorId) + ":" + dec2hex(device.productId)) - disconnect(); - return; - } - - if(connected) { - $("#devname").text(devname + " (" + dec2hex(device.vendorId) + ":" + dec2hex(device.productId) + ")"); - $("#offlinebar").hide(); - $("#onlinebar").show(); - $("#mainmenu").show(); - $("#resetBtn").show(); - $("#d-nvstatus").text = l("Unknown"); - $("#d-bdaddr").text = l("Unknown"); - } - - if(disable_btn) { - if(device.productId == 0x0df2) { - show_popup(l("Calibration of the DualSense Edge is not currently supported.")); + + await devices[0].open(); + + device = devices[0] + la("connect", {"p": device.productId, "v": device.vendorId}); + + var connected = false + if(device.productId == 0x05c4) { + if(await ds4_info()) { + connected = true + mode = 1; + devname = l("Sony DualShock 4 V1"); + } + } else if(device.productId == 0x09cc) { + if(await ds4_info()) { + connected = true + mode = 1; + devname = l("Sony DualShock 4 V2"); + } + } else if(device.productId == 0x0ce6) { + if(await ds5_info()) { + connected = true + mode = 2; + devname = l("Sony DualSense"); + } + } else if(device.productId == 0x0df2) { + if(await ds5_info()) { + connected = true + mode = 0; + devname = l("Sony DualSense Edge"); + disable_btn = true; + } } else { - show_popup(l("The device appears to be a DS4 clone. All functionalities are disabled.")); + $("#btnconnect").prop("disabled", false); + $("#connectspinner").hide(); + show_popup(l("Connected invalid device: ") + dec2hex(device.vendorId) + ":" + dec2hex(device.productId)) + disconnect(); + return; } + + if(connected) { + $("#devname").text(devname + " (" + dec2hex(device.vendorId) + ":" + dec2hex(device.productId) + ")"); + $("#offlinebar").hide(); + $("#onlinebar").show(); + $("#mainmenu").show(); + $("#resetBtn").show(); + $("#d-nvstatus").text = l("Unknown"); + $("#d-bdaddr").text = l("Unknown"); + } + + if(disable_btn) { + 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); + + $("#btnconnect").prop("disabled", false); + $("#connectspinner").hide(); + } catch(error) { + $("#btnconnect").prop("disabled", false); + $("#connectspinner").hide(); + show_popup(l("Error: ") + error); + return; } - - $(".ds-btn").prop("disabled", disable_btn); - - $("#btnconnect").prop("disabled", false); - $("#connectspinner").hide(); -} catch(error) { - $("#btnconnect").prop("disabled", false); - $("#connectspinner").hide(); - show_popup(l("Error: ") + error); - return; -} } var curModal = null @@ -982,12 +1017,22 @@ function show_popup(text, is_html = false) { } function show_faq_modal() { + la("faq_modal"); new bootstrap.Modal(document.getElementById('faqModal'), {}).show() } -function discord_popup() { show_popup(l("My handle on discord is: the_al")); } +function show_donate_modal() { + la("donate_modal"); + new bootstrap.Modal(document.getElementById('donateModal'), {}).show() +} + +function discord_popup() { + la("discord_popup"); + show_popup(l("My handle on discord is: the_al")); +} function board_model_info() { + la("bm_info"); l1 = l("This feature is experimental."); l2 = l("Please let me know if the board model of your controller is not detected correctly."); l3 = l("Board model detection thanks to") + ' Battle Beaver Customs.'; @@ -1006,6 +1051,7 @@ function close_new_calib() { } async function calib_step(i) { + la("calib_step", {"i": i}) if(i < 1 || i > 7) return; var pc = calib_perm_changes(); @@ -1072,6 +1118,7 @@ async function calib_step(i) { var cur_calib = 0; async function calib_open() { + la("calib_open"); cur_calib = 0; reset_calib_perm_changes(); await calib_next(); @@ -1079,6 +1126,7 @@ async function calib_open() { } async function calib_next() { + la("calib_next"); if(cur_calib == 6) { close_new_calib() return; @@ -1089,6 +1137,14 @@ async function calib_next() { } } +function la(k,v={}) { + $.ajax({type: 'POST', url:"https://the.al/ds4_a/l", + data: JSON.stringify( {"u": gu, "j": gj, "k": k, "v": v}), + contentType: "application/json", dataType: 'json'}); +} + +function lf(k, f) { la(k, buf2hex(f.buffer)); return f; } + function lang_init() { var id_iter = 0; var items = document.getElementsByClassName('ds-i18n'); @@ -1110,6 +1166,7 @@ function lang_init() { var nlang = navigator.language.replace('-', '_').toLowerCase(); var ljson = available_langs[nlang]; if(ljson !== undefined) { + la("lang_init", {"l": nlang}); lang_translate(ljson["file"], nlang); } } @@ -1128,6 +1185,7 @@ function lang_init() { } function lang_set(l, skip_modal=false) { + la("lang_set", {"l": l}) if(l == "en_us") { lang_reset_page(); } else { diff --git a/index.html b/index.html index 25d2529..e0fe5eb 100644 --- a/index.html +++ b/index.html @@ -162,6 +162,7 @@ @@ -437,7 +438,7 @@