First commit
This commit is contained in:
parent
aa1712eb20
commit
534f477219
939
core.js
Normal file
939
core.js
Normal file
@ -0,0 +1,939 @@
|
|||||||
|
var device = null;
|
||||||
|
var devname = "";
|
||||||
|
var mode = 0;
|
||||||
|
var disable_btn = false;
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function ds4_info() {
|
||||||
|
const view = await device.receiveFeatureReport(0xa3);
|
||||||
|
|
||||||
|
var cmd = view.getUint8(0, true);
|
||||||
|
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));
|
||||||
|
k1=k1.replace(/\0/g, '');
|
||||||
|
k2=k2.replace(/\0/g, '');
|
||||||
|
|
||||||
|
var hw_ver_major= view.getUint16(0x21, true)
|
||||||
|
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 = "unknown";
|
||||||
|
|
||||||
|
try {
|
||||||
|
const view = await device.receiveFeatureReport(0x81);
|
||||||
|
ooc = "original";
|
||||||
|
} catch(e) {
|
||||||
|
ooc = "<font color='red'><b>clone</b></font>";
|
||||||
|
disable_btn = true;
|
||||||
|
}
|
||||||
|
clear_info();
|
||||||
|
append_info("Firmware Date: ", k1 + " " + k2);
|
||||||
|
append_info("HW Version:", "" + dec2hex(hw_ver_major) + ":" + dec2hex(hw_ver_minor));
|
||||||
|
append_info("SW Version:", dec2hex32(sw_ver_major) + ":" + dec2hex(sw_ver_minor));
|
||||||
|
append_info("Device Type:", ooc);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function ds4_reset() {
|
||||||
|
try {
|
||||||
|
await device.sendFeatureReport(0xa0, alloc_req(0x80, [4,1,0]))
|
||||||
|
} catch(error) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function ds5_reset() {
|
||||||
|
try {
|
||||||
|
await device.sendFeatureReport(0x80, alloc_req(0x80, [1,1,0]))
|
||||||
|
} catch(error) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function ds4_calibrate_range_begin(perm_ch) {
|
||||||
|
try {
|
||||||
|
if(perm_ch) {
|
||||||
|
await ds4_nvunlock();
|
||||||
|
if(await ds4_nvstatus() != 0) {
|
||||||
|
close_calibrate_window();
|
||||||
|
return show_popup("Range calibration failed: cannot unlock NV.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Begin
|
||||||
|
await device.sendFeatureReport(0x90, alloc_req(0x90, [1,1,2]))
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
data = await device.receiveFeatureReport(0x91)
|
||||||
|
data2 = await device.receiveFeatureReport(0x92)
|
||||||
|
if(data.getUint32(0, false) != 0x91010201 || data2.getUint32(0, false) != 0x920102ff) {
|
||||||
|
close_calibrate_window();
|
||||||
|
return show_popup("Range calibration failed: error 1.");
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
await new Promise(r => setTimeout(r, 500));
|
||||||
|
close_calibrate_window();
|
||||||
|
return show_popup("Calibration failed: " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function ds4_calibrate_range_end(perm_ch) {
|
||||||
|
try {
|
||||||
|
// Write
|
||||||
|
await device.sendFeatureReport(0x90, alloc_req(0x90, [2,1,2]))
|
||||||
|
|
||||||
|
data = await device.receiveFeatureReport(0x91)
|
||||||
|
data2 = await device.receiveFeatureReport(0x92)
|
||||||
|
if(data.getUint32(0, false) != 0x91010202 || data2.getUint32(0, false) != 0x92010201) {
|
||||||
|
close_calibrate_window();
|
||||||
|
return show_popup("Range calibration failed: error 3.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(perm_ch) {
|
||||||
|
await ds4_nvlock();
|
||||||
|
if(await ds4_nvstatus() != 1) {
|
||||||
|
close_calibrate_window();
|
||||||
|
return show_popup("Range calibration failed: cannot relock NV.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
close_calibrate_window();
|
||||||
|
show_popup("Range calibration completed");
|
||||||
|
} catch(e) {
|
||||||
|
await new Promise(r => setTimeout(r, 500));
|
||||||
|
close_calibrate_window();
|
||||||
|
return show_popup("Calibration failed: " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function ds4_calibrate_sticks_begin(has_perm_changes) {
|
||||||
|
try {
|
||||||
|
if(has_perm_changes) {
|
||||||
|
await ds4_nvunlock();
|
||||||
|
if(await ds4_nvstatus() != 0) {
|
||||||
|
show_popup("Calibration failed: cannot unlock NV.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Begin
|
||||||
|
await device.sendFeatureReport(0x90, alloc_req(0x90, [1,1,1]))
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
data = await device.receiveFeatureReport(0x91)
|
||||||
|
data2 = await device.receiveFeatureReport(0x92)
|
||||||
|
if(data.getUint32(0, false) != 0x91010101 || data2.getUint32(0, false) != 0x920101ff) {
|
||||||
|
show_popup("Calibration failed: error 1.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch(e) {
|
||||||
|
await new Promise(r => setTimeout(r, 500));
|
||||||
|
show_popup("Calibration failed: " + e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function ds4_calibrate_sticks_sample() {
|
||||||
|
try {
|
||||||
|
// Sample
|
||||||
|
await device.sendFeatureReport(0x90, alloc_req(0x90, [3,1,1]))
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
data = await device.receiveFeatureReport(0x91);
|
||||||
|
data2 = await device.receiveFeatureReport(0x92);
|
||||||
|
if(data.getUint32(0, false) != 0x91010101 || data2.getUint32(0, false) != 0x920101ff) {
|
||||||
|
close_calibrate_window();
|
||||||
|
d1 = dec2hex32(data.getUint32(0, false));
|
||||||
|
d2 = dec2hex32(data2.getUint32(0, false));
|
||||||
|
show_popup("Calibration failed: error 2 (got " + d1 + ", " + d2 + " at i=" + i + ")");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} catch(e) {
|
||||||
|
await new Promise(r => setTimeout(r, 500));
|
||||||
|
show_popup("Calibration failed: " + e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function ds4_calibrate_sticks_end(has_perm_changes) {
|
||||||
|
try {
|
||||||
|
// Write
|
||||||
|
await device.sendFeatureReport(0x90, alloc_req(0x90, [2,1,1]))
|
||||||
|
if(data.getUint32(0, false) != 0x91010101 || data2.getUint32(0, false) != 0x920101FF) {
|
||||||
|
d1 = dec2hex32(data.getUint32(0, false));
|
||||||
|
d2 = dec2hex32(data2.getUint32(0, false));
|
||||||
|
show_popup("Calibration failed: error 3 (got " + d1 + ", " + d2 + " at i=" + i + ")");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(has_perm_changes) {
|
||||||
|
await ds4_nvlock();
|
||||||
|
if(await ds4_nvstatus() != 1) {
|
||||||
|
show_popup("Calibration failed: cannot relock NV.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch(e) {
|
||||||
|
await new Promise(r => setTimeout(r, 500));
|
||||||
|
show_popup("Calibration failed: " + e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function ds4_calibrate_sticks() {
|
||||||
|
try {
|
||||||
|
set_progress(0);
|
||||||
|
|
||||||
|
// Begin
|
||||||
|
await device.sendFeatureReport(0x90, alloc_req(0x90, [1,1,1]))
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
data = await device.receiveFeatureReport(0x91)
|
||||||
|
data2 = await device.receiveFeatureReport(0x92)
|
||||||
|
if(data.getUint32(0, false) != 0x91010101 || data2.getUint32(0, false) != 0x920101ff) {
|
||||||
|
close_calibrate_window();
|
||||||
|
return show_popup("Calibration failed: error 1.");
|
||||||
|
}
|
||||||
|
|
||||||
|
set_progress(10);
|
||||||
|
await new Promise(r => setTimeout(r, 100));
|
||||||
|
|
||||||
|
for(var i=0;i<3;i++) {
|
||||||
|
// Sample
|
||||||
|
await device.sendFeatureReport(0x90, alloc_req(0x90, [3,1,1]))
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
data = await device.receiveFeatureReport(0x91);
|
||||||
|
data2 = await device.receiveFeatureReport(0x92);
|
||||||
|
if(data.getUint32(0, false) != 0x91010101 || data2.getUint32(0, false) != 0x920101ff) {
|
||||||
|
close_calibrate_window();
|
||||||
|
d1 = dec2hex32(data.getUint32(0, false));
|
||||||
|
d2 = dec2hex32(data2.getUint32(0, false));
|
||||||
|
return show_popup("Calibration failed: error 2 (got " + d1 + ", " + d2 + " at i=" + i + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
await new Promise(r => setTimeout(r, 500));
|
||||||
|
set_progress(20 + i * 30);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write
|
||||||
|
await device.sendFeatureReport(0x90, alloc_req(0x90, [2,1,1]))
|
||||||
|
if(data.getUint32(0, false) != 0x91010101 || data2.getUint32(0, false) != 0x920101FF) {
|
||||||
|
d1 = dec2hex32(data.getUint32(0, false));
|
||||||
|
d2 = dec2hex32(data2.getUint32(0, false));
|
||||||
|
close_calibrate_window();
|
||||||
|
return show_popup("Calibration failed: error 3 (got " + d1 + ", " + d2 + " at i=" + i + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
set_progress(100);
|
||||||
|
await new Promise(r => setTimeout(r, 500));
|
||||||
|
close_calibrate_window()
|
||||||
|
show_popup("Calibration completed successfully");
|
||||||
|
} catch(e) {
|
||||||
|
await new Promise(r => setTimeout(r, 500));
|
||||||
|
close_calibrate_window();
|
||||||
|
return show_popup("Calibration failed: " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function ds4_nvstatus() {
|
||||||
|
await device.sendFeatureReport(0x08, alloc_req(0x08, [0xff,0, 12]))
|
||||||
|
data = await device.receiveFeatureReport(0x11)
|
||||||
|
// 1: temporary, 0: permanent
|
||||||
|
ret = data.getUint8(1, false);
|
||||||
|
if(ret == 1) {
|
||||||
|
$("#d-nvstatus").html("<font color='green'>locked</font>");
|
||||||
|
} else if(ret == 0) {
|
||||||
|
$("#d-nvstatus").html("<font color='red'>unlocked</font>");
|
||||||
|
} else {
|
||||||
|
$("#d-nvstatus").html("<font color='purple'>unk " + ret + "</font>");
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function ds5_nvstatus() {
|
||||||
|
try {
|
||||||
|
await device.sendFeatureReport(0x80, alloc_req(0x80, [3,3]))
|
||||||
|
data = await device.receiveFeatureReport(0x81)
|
||||||
|
ret = data.getUint32(1, false);
|
||||||
|
if(ret == 0x03030201) {
|
||||||
|
$("#d-nvstatus").html("<font color='green'>locked</font>");
|
||||||
|
return 1; // temporary
|
||||||
|
} else if(ret == 0x03030200) {
|
||||||
|
$("#d-nvstatus").html("<font color='red'>unlocked</font>");
|
||||||
|
return 0; // permanent
|
||||||
|
} else {
|
||||||
|
$("#d-nvstatus").html("<font color='purple'>unk " + dec2hex32(ret) + "</font>");
|
||||||
|
return ret; // unknown
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
$("#d-nvstatus").html("<font color='red'>error</font>");
|
||||||
|
return 2; // error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function ds4_getbdaddr() {
|
||||||
|
return "not implemented";
|
||||||
|
}
|
||||||
|
|
||||||
|
async function ds5_getbdaddr() {
|
||||||
|
try {
|
||||||
|
await device.sendFeatureReport(0x80, alloc_req(0x80, [9,2]))
|
||||||
|
data = await device.receiveFeatureReport(0x81)
|
||||||
|
out = ""
|
||||||
|
for(i=0;i<6;i++) {
|
||||||
|
if(i >= 1) out += ":";
|
||||||
|
out += dec2hex8(data.getUint8(4 + i, false));
|
||||||
|
}
|
||||||
|
$("#d-bdaddr").text(out);
|
||||||
|
return out;
|
||||||
|
} catch(e) {
|
||||||
|
$("#d-bdaddr").html("<font color='red'>error</font>");
|
||||||
|
return "error";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function ds4_nvlock() {
|
||||||
|
await device.sendFeatureReport(0xa0, alloc_req(0xa0, [10,1,0]))
|
||||||
|
}
|
||||||
|
|
||||||
|
async function 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);
|
||||||
|
|
||||||
|
var cmd = view.getUint8(0, true);
|
||||||
|
if(cmd != 0x20 || view.buffer.byteLength != 64)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var build_date = new TextDecoder().decode(view.buffer.slice(1, 1+11));
|
||||||
|
var build_time = new TextDecoder().decode(view.buffer.slice(12, 20));
|
||||||
|
|
||||||
|
var fwtype = view.getUint16(20, true);
|
||||||
|
var swseries = view.getUint16(22, true);
|
||||||
|
var hwinfo = view.getUint32(24, true);
|
||||||
|
var fwversion = view.getUint32(28, true);
|
||||||
|
|
||||||
|
var deviceinfo = new TextDecoder().decode(view.buffer.slice(32, 32+12));
|
||||||
|
var updversion = view.getUint16(44, true);
|
||||||
|
var unk = view.getUint16(46, true);
|
||||||
|
|
||||||
|
var fwversion1 = view.getUint32(50, true);
|
||||||
|
var fwversion2 = view.getUint32(54, true);
|
||||||
|
var fwversion3 = view.getUint32(58, true);
|
||||||
|
|
||||||
|
clear_info();
|
||||||
|
|
||||||
|
append_info("Build Time: ", build_date + " " + build_time);
|
||||||
|
append_info("Firmware Type:", "0x" + dec2hex(fwtype));
|
||||||
|
append_info("SW Series:", "0x" + dec2hex(swseries));
|
||||||
|
append_info("HW Info:", "0x" + dec2hex32(hwinfo));
|
||||||
|
append_info("FW Version:", "0x" + dec2hex32(fwversion));
|
||||||
|
//append_info("deviceinfo:", deviceinfo);
|
||||||
|
append_info("UPD Version:", "0x" + dec2hex(updversion));
|
||||||
|
//append_info("Unknown:", "0x" + dec2hex(unk));
|
||||||
|
append_info("FW Version1:", "0x" + dec2hex32(fwversion1));
|
||||||
|
append_info("FW Version2:", "0x" + dec2hex32(fwversion2));
|
||||||
|
append_info("FW Version3:", "0x" + dec2hex32(fwversion3));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function ds5_calibrate_sticks_begin(has_perm_changes) {
|
||||||
|
console.log("::ds5_calibrate_sticks_begin(" + has_perm_changes + ")");
|
||||||
|
try {
|
||||||
|
if(has_perm_changes) {
|
||||||
|
await ds5_nvunlock();
|
||||||
|
if(await ds5_nvstatus() != 0) {
|
||||||
|
show_popup("Range calibration failed: cannot unlock NVS.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Begin
|
||||||
|
await device.sendFeatureReport(0x82, alloc_req(0x82, [1,1,1]))
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
data = await device.receiveFeatureReport(0x83)
|
||||||
|
if(data.getUint32(0, false) != 0x83010101) {
|
||||||
|
d1 = dec2hex32(data.getUint32(0, false));
|
||||||
|
show_popup("Calibration failed: error 1 (got " + d1 + ").");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} catch(e) {
|
||||||
|
await new Promise(r => setTimeout(r, 500));
|
||||||
|
show_popup("Calibration failed: " + e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function ds5_calibrate_sticks_sample() {
|
||||||
|
console.log("::ds5_calibrate_sticks_sample()");
|
||||||
|
try {
|
||||||
|
// Sample
|
||||||
|
await device.sendFeatureReport(0x82, alloc_req(0x82, [3,1,1]))
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
data = await device.receiveFeatureReport(0x83)
|
||||||
|
if(data.getUint32(0, false) != 0x83010101) {
|
||||||
|
d1 = dec2hex32(data.getUint32(0, false));
|
||||||
|
show_popup("Calibration failed: error 2 (got " + d1 + ").");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} catch(e) {
|
||||||
|
await new Promise(r => setTimeout(r, 500));
|
||||||
|
show_popup("Calibration failed: " + e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function ds5_calibrate_sticks_end(has_perm_changes) {
|
||||||
|
console.log("::ds5_calibrate_sticks_end(" + has_perm_changes + ")");
|
||||||
|
try {
|
||||||
|
// Write
|
||||||
|
await device.sendFeatureReport(0x82, alloc_req(0x82, [2,1,1]))
|
||||||
|
|
||||||
|
data = await device.receiveFeatureReport(0x83)
|
||||||
|
if(data.getUint32(0, false) != 0x83010102) {
|
||||||
|
d1 = dec2hex32(data.getUint32(0, false));
|
||||||
|
show_popup("Calibration failed: error 3 (got " + d1 + ").");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(has_perm_changes) {
|
||||||
|
await ds5_nvlock();
|
||||||
|
if(await ds5_nvstatus() != 1) {
|
||||||
|
show_popup("Range calibration failed: cannot relock NVS.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} catch(e) {
|
||||||
|
await new Promise(r => setTimeout(r, 500));
|
||||||
|
show_popup("Calibration failed: " + e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function ds5_calibrate_sticks() {
|
||||||
|
try {
|
||||||
|
set_progress(0);
|
||||||
|
|
||||||
|
// Begin
|
||||||
|
await device.sendFeatureReport(0x82, alloc_req(0x82, [1,1,1]))
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
data = await device.receiveFeatureReport(0x83)
|
||||||
|
if(data.getUint32(0, false) != 0x83010101) {
|
||||||
|
d1 = dec2hex32(data.getUint32(0, false));
|
||||||
|
close_calibrate_window();
|
||||||
|
return show_popup("Calibration failed: error 1 (got " + d1 + ").");
|
||||||
|
}
|
||||||
|
|
||||||
|
set_progress(10);
|
||||||
|
|
||||||
|
await new Promise(r => setTimeout(r, 100));
|
||||||
|
|
||||||
|
for(var i=0;i<3;i++) {
|
||||||
|
// Sample
|
||||||
|
await device.sendFeatureReport(0x82, alloc_req(0x82, [3,1,1]))
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
data = await device.receiveFeatureReport(0x83)
|
||||||
|
if(data.getUint32(0, false) != 0x83010101) {
|
||||||
|
d1 = dec2hex32(data.getUint32(0, false));
|
||||||
|
close_calibrate_window();
|
||||||
|
return show_popup("Calibration failed: error 2 (got " + d1 + ").");
|
||||||
|
}
|
||||||
|
|
||||||
|
await new Promise(r => setTimeout(r, 500));
|
||||||
|
set_progress(20 + i * 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
await new Promise(r => setTimeout(r, 200));
|
||||||
|
set_progress(80);
|
||||||
|
|
||||||
|
// Write
|
||||||
|
await device.sendFeatureReport(0x82, alloc_req(0x82, [2,1,1]))
|
||||||
|
|
||||||
|
data = await device.receiveFeatureReport(0x83)
|
||||||
|
if(data.getUint32(0, false) != 0x83010102) {
|
||||||
|
d1 = dec2hex32(data.getUint32(0, false));
|
||||||
|
close_calibrate_window();
|
||||||
|
return show_popup("Calibration failed: error 3 (got " + d1 + ").");
|
||||||
|
}
|
||||||
|
|
||||||
|
set_progress(100);
|
||||||
|
|
||||||
|
await new Promise(r => setTimeout(r, 500));
|
||||||
|
close_calibrate_window()
|
||||||
|
|
||||||
|
show_popup("Calibration completed successfully");
|
||||||
|
} catch(e) {
|
||||||
|
await new Promise(r => setTimeout(r, 500));
|
||||||
|
close_calibrate_window();
|
||||||
|
return show_popup("Calibration failed: " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function ds5_calibrate_range_begin(perm_ch) {
|
||||||
|
try {
|
||||||
|
if(perm_ch) {
|
||||||
|
await ds5_nvunlock();
|
||||||
|
if(await ds5_nvstatus() != 0) {
|
||||||
|
close_calibrate_window();
|
||||||
|
return show_popup("Range calibration failed: cannot unlock NVS.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Begin
|
||||||
|
await device.sendFeatureReport(0x82, alloc_req(0x82, [1,1,2]))
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
data = await device.receiveFeatureReport(0x83)
|
||||||
|
if(data.getUint32(0, false) != 0x83010201) {
|
||||||
|
d1 = dec2hex32(data.getUint32(0, false));
|
||||||
|
close_calibrate_window();
|
||||||
|
return show_popup("Calibration failed: error 1 (got " + d1 + ").");
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
await new Promise(r => setTimeout(r, 500));
|
||||||
|
close_calibrate_window();
|
||||||
|
return show_popup("Calibration failed: " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function ds5_calibrate_range_end(perm_ch) {
|
||||||
|
try {
|
||||||
|
// Write
|
||||||
|
await device.sendFeatureReport(0x82, alloc_req(0x82, [2,1,2]))
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
data = await device.receiveFeatureReport(0x83)
|
||||||
|
if(data.getUint32(0, false) != 0x83010202) {
|
||||||
|
d1 = dec2hex32(data.getUint32(0, false));
|
||||||
|
close_calibrate_window();
|
||||||
|
return show_popup("Calibration failed: error 1 (got " + d1 + ").");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(perm_ch) {
|
||||||
|
await ds5_nvlock();
|
||||||
|
if(await ds5_nvstatus() != 1) {
|
||||||
|
close_calibrate_window();
|
||||||
|
return show_popup("Range calibration failed: cannot relock NVS.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
close_calibrate_window();
|
||||||
|
show_popup("Range calibration completed");
|
||||||
|
} catch(e) {
|
||||||
|
await new Promise(r => setTimeout(r, 500));
|
||||||
|
close_calibrate_window();
|
||||||
|
return show_popup("Calibration failed: " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function ds5_nvlock() {
|
||||||
|
try {
|
||||||
|
await device.sendFeatureReport(0x80, alloc_req(0x80, [3,1]))
|
||||||
|
data = await device.receiveFeatureReport(0x83)
|
||||||
|
} catch(e) {
|
||||||
|
await new Promise(r => setTimeout(r, 500));
|
||||||
|
close_calibrate_window();
|
||||||
|
return show_popup("NVSLock failed: " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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("NVSUnlock failed: " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function disconnect() {
|
||||||
|
if(device == null)
|
||||||
|
return;
|
||||||
|
mode = 0;
|
||||||
|
device.close();
|
||||||
|
device = null;
|
||||||
|
disable_btn = false;
|
||||||
|
|
||||||
|
$("#offlinebar").show();
|
||||||
|
$("#onlinebar").hide();
|
||||||
|
$("#mainmenu").hide();
|
||||||
|
close_calibrate_window();
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleDisconnectedDevice(e) {
|
||||||
|
console.log("Disconnected: " + e.device.productName)
|
||||||
|
disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
function gboot() {
|
||||||
|
if (!("hid" in navigator)) {
|
||||||
|
$("#offlinebar").hide();
|
||||||
|
$("#onlinebar").hide();
|
||||||
|
$("#missinghid").show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$("#offlinebar").show();
|
||||||
|
navigator.hid.addEventListener("disconnect", handleDisconnectedDevice);
|
||||||
|
}
|
||||||
|
|
||||||
|
function alloc_req(id, data=[]) {
|
||||||
|
len = data.length;
|
||||||
|
try {
|
||||||
|
fr = device.collections[0].featureReports;
|
||||||
|
fr.forEach((e) => { if(e.reportId == id) { len = e.items[0].reportCount; }});
|
||||||
|
} catch(e) {
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
out = new Uint8Array(len);
|
||||||
|
for(i=0;i<data.length && i < len;i++) {
|
||||||
|
out[i] = data[i];
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function connect() {
|
||||||
|
try {
|
||||||
|
$("#btnconnect").prop("disabled", true);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (devices.length == 0) {
|
||||||
|
$("#btnconnect").prop("disabled", false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (devices.length > 1) {
|
||||||
|
$("#btnconnect").prop("disabled", false);
|
||||||
|
show_popup("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 = "Sony DualShock 4 V1";
|
||||||
|
}
|
||||||
|
} else if(device.productId == 0x09cc) {
|
||||||
|
if(await ds4_info()) {
|
||||||
|
connected = true
|
||||||
|
mode = 1;
|
||||||
|
devname = "Sony DualShock 4 V2";
|
||||||
|
}
|
||||||
|
} else if(device.productId == 0x0ce6) {
|
||||||
|
if(await ds5_info()) {
|
||||||
|
connected = true
|
||||||
|
mode = 2;
|
||||||
|
devname = "Sony DualSense";
|
||||||
|
}
|
||||||
|
} else if(device.productId == 0x0df2) {
|
||||||
|
if(await ds5_info()) {
|
||||||
|
connected = true
|
||||||
|
mode = 0;
|
||||||
|
devname = "Sony DualSense Edge";
|
||||||
|
disable_btn = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$("#btnconnect").prop("disabled", false);
|
||||||
|
show_popup("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 = "Unknown";
|
||||||
|
$("#d-bdaddr").text = "Unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
if(disable_btn) {
|
||||||
|
if(device.productId == 0x0df2) {
|
||||||
|
show_popup("Calibration of the DualSense Edge is not currently supported.");
|
||||||
|
} else {
|
||||||
|
show_popup("The device appears to be a DS4 clone. All functionalities are disabled.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$(".ds-btn").prop("disabled", disable_btn);
|
||||||
|
|
||||||
|
$("#btnconnect").prop("disabled", false);
|
||||||
|
} catch(error) {
|
||||||
|
$("#btnconnect").prop("disabled", false);
|
||||||
|
show_popup("Error: " + error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var curModal = null
|
||||||
|
|
||||||
|
async function multi_reset() {
|
||||||
|
if(mode == 1)
|
||||||
|
ds4_reset();
|
||||||
|
else
|
||||||
|
ds5_reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function multi_getbdaddr() {
|
||||||
|
if(mode == 1)
|
||||||
|
ds4_getbdaddr();
|
||||||
|
else
|
||||||
|
ds5_getbdaddr();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function multi_nvstatus() {
|
||||||
|
if(mode == 1)
|
||||||
|
ds4_nvstatus();
|
||||||
|
else
|
||||||
|
ds5_nvstatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function multi_nvsunlock() {
|
||||||
|
if(mode == 1) {
|
||||||
|
await ds4_nvunlock();
|
||||||
|
await ds4_nvstatus();
|
||||||
|
} else {
|
||||||
|
await ds5_nvunlock();
|
||||||
|
await ds5_nvstatus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function multi_nvslock() {
|
||||||
|
if(mode == 1) {
|
||||||
|
await ds4_nvlock();
|
||||||
|
await ds4_nvstatus();
|
||||||
|
} else {
|
||||||
|
await ds5_nvlock();
|
||||||
|
await ds5_nvstatus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function multi_calib_sticks_begin(pc) {
|
||||||
|
if(mode == 1)
|
||||||
|
return ds4_calibrate_sticks_begin(pc);
|
||||||
|
else
|
||||||
|
return ds5_calibrate_sticks_begin(pc);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function multi_calib_sticks_end(pc) {
|
||||||
|
if(mode == 1)
|
||||||
|
return ds4_calibrate_sticks_end(pc);
|
||||||
|
else
|
||||||
|
return ds5_calibrate_sticks_end(pc);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function multi_calib_sticks_sample() {
|
||||||
|
if(mode == 1)
|
||||||
|
return ds4_calibrate_sticks_sample();
|
||||||
|
else
|
||||||
|
return ds5_calibrate_sticks_sample();
|
||||||
|
}
|
||||||
|
|
||||||
|
var last_perm_ch = 0
|
||||||
|
async function multi_calibrate_range(perm_ch) {
|
||||||
|
if(mode == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
set_progress(0);
|
||||||
|
curModal = new bootstrap.Modal(document.getElementById('rangeModal'), {})
|
||||||
|
curModal.show();
|
||||||
|
|
||||||
|
last_perm_ch = perm_ch
|
||||||
|
|
||||||
|
await new Promise(r => setTimeout(r, 1000));
|
||||||
|
|
||||||
|
if(mode == 1)
|
||||||
|
ds4_calibrate_range_begin(perm_ch);
|
||||||
|
else
|
||||||
|
ds5_calibrate_range_begin(perm_ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function multi_calibrate_range_on_close() {
|
||||||
|
if(mode == 1)
|
||||||
|
ds4_calibrate_range_end(last_perm_ch);
|
||||||
|
else
|
||||||
|
ds5_calibrate_range_end(last_perm_ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function multi_calibrate_sticks() {
|
||||||
|
if(mode == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
set_progress(0);
|
||||||
|
curModal = new bootstrap.Modal(document.getElementById('calibrateModal'), {})
|
||||||
|
curModal.show();
|
||||||
|
|
||||||
|
await new Promise(r => setTimeout(r, 1000));
|
||||||
|
|
||||||
|
if(mode == 1)
|
||||||
|
ds4_calibrate_sticks();
|
||||||
|
else
|
||||||
|
ds5_calibrate_sticks();
|
||||||
|
}
|
||||||
|
|
||||||
|
function close_calibrate_window() {
|
||||||
|
if (curModal != null) {
|
||||||
|
curModal.hide();
|
||||||
|
curModal = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$("#calibCenterModal").modal("hide");
|
||||||
|
cur_calib = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
function set_progress(i) {
|
||||||
|
$(".progress-bar").css('width', '' + i + '%')
|
||||||
|
}
|
||||||
|
|
||||||
|
function clear_info() {
|
||||||
|
$("#fwinfo").html("");
|
||||||
|
}
|
||||||
|
|
||||||
|
function append_info(key, value) {
|
||||||
|
// TODO escape html
|
||||||
|
var s = '<div class="hstack"><p>' + key + '</p><p class="ms-auto">' + value + '</p></div>';
|
||||||
|
$("#fwinfo").html($("#fwinfo").html() + s);
|
||||||
|
}
|
||||||
|
|
||||||
|
function show_popup(text) {
|
||||||
|
$("#popupBody").text(text);
|
||||||
|
new bootstrap.Modal(document.getElementById('popupModal'), {}).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
function calib_perm_changes() { return $("#calibPermanentChanges").is(':checked') }
|
||||||
|
|
||||||
|
function reset_calib_perm_changes() {
|
||||||
|
$("#calibPermanentChanges").prop("checked", false).parent().removeClass('active');
|
||||||
|
}
|
||||||
|
|
||||||
|
function close_new_calib() {
|
||||||
|
$("#calibCenterModal").modal("hide");
|
||||||
|
cur_calib = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function calib_step(i) {
|
||||||
|
if(i < 1 || i > 7) return;
|
||||||
|
|
||||||
|
var pc = calib_perm_changes();
|
||||||
|
var ret = true;
|
||||||
|
if(i >= 2 && i <= 6) {
|
||||||
|
$("#btnSpinner").show();
|
||||||
|
$("#calibNext").prop("disabled", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(i == 2) {
|
||||||
|
$("#calibNextText").text("Initializing...");
|
||||||
|
await new Promise(r => setTimeout(r, 100));
|
||||||
|
ret = await multi_calib_sticks_begin(pc);
|
||||||
|
} else if(i == 6) {
|
||||||
|
$("#calibNextText").text("Storing calibration...");
|
||||||
|
await new Promise(r => setTimeout(r, 100));
|
||||||
|
ret = await multi_calib_sticks_end(pc);
|
||||||
|
} else if(i > 2 && i < 6){
|
||||||
|
$("#calibNextText").text("Sampling...");
|
||||||
|
await new Promise(r => setTimeout(r, 100));
|
||||||
|
ret = await multi_calib_sticks_sample();
|
||||||
|
}
|
||||||
|
if(i >= 2 && i <= 6) {
|
||||||
|
await new Promise(r => setTimeout(r, 200));
|
||||||
|
$("#calibNext").prop("disabled", false);
|
||||||
|
$("#btnSpinner").hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ret == false) {
|
||||||
|
close_new_calib();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(j=1;j<7;j++) {
|
||||||
|
$("#list-" + j).hide();
|
||||||
|
$("#list-" + j + "-calib").removeClass("active");
|
||||||
|
}
|
||||||
|
|
||||||
|
$("#list-" + i).show();
|
||||||
|
$("#list-" + i + "-calib").addClass("active");
|
||||||
|
|
||||||
|
if(i == 1) {
|
||||||
|
$("#calibTitle").text("Stick center calibration");
|
||||||
|
$("#calibNextText").text("Start");
|
||||||
|
}
|
||||||
|
else if(i == 6) {
|
||||||
|
$("#calibTitle").text("Stick center calibration");
|
||||||
|
$("#calibNextText").text("Done");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$("#calibTitle").html("Calibration in progress");
|
||||||
|
$("#calibNextText").text("Continue");
|
||||||
|
}
|
||||||
|
if(i == 1 || i == 6)
|
||||||
|
$("#calibCross").show();
|
||||||
|
else
|
||||||
|
$("#calibCross").hide();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var cur_calib = 0;
|
||||||
|
async function calib_open() {
|
||||||
|
cur_calib = 0;
|
||||||
|
reset_calib_perm_changes();
|
||||||
|
await calib_next();
|
||||||
|
new bootstrap.Modal(document.getElementById('calibCenterModal'), {}).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
async function calib_next() {
|
||||||
|
console.log(cur_calib);
|
||||||
|
if(cur_calib == 6) {
|
||||||
|
close_new_calib()
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(cur_calib < 6) {
|
||||||
|
cur_calib += 1;
|
||||||
|
await calib_step(cur_calib);
|
||||||
|
}
|
||||||
|
}
|
9
fa.min.css
vendored
Normal file
9
fa.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
260
index.html
Normal file
260
index.html
Normal file
@ -0,0 +1,260 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>DualShock Calibration GUI</title>
|
||||||
|
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" 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" crossorigin="anonymous">
|
||||||
|
|
||||||
|
<script src="https://code.jquery.com/jquery-3.7.1.slim.min.js"
|
||||||
|
integrity="sha256-kmHvs0B+OpCW5GVHUNjv9rOmY0IvSIRcf7zGUDTDQM8="
|
||||||
|
crossorigin="anonymous"></script>
|
||||||
|
|
||||||
|
<script src="core.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="d-none">
|
||||||
|
<symbol id="mail" viewBox="0 0 512 512">
|
||||||
|
<path d="M48 64C21.5 64 0 85.5 0 112c0 15.1 7.1 29.3 19.2 38.4L236.8 313.6c11.4 8.5 27 8.5 38.4 0L492.8 150.4c12.1-9.1 19.2-23.3 19.2-38.4c0-26.5-21.5-48-48-48H48zM0 176V384c0 35.3 28.7 64 64 64H448c35.3 0 64-28.7 64-64V176L294.4 339.2c-22.8 17.1-54 17.1-76.8 0L0 176z"/>
|
||||||
|
</symbol>
|
||||||
|
<symbol id="github" viewBox="0 0 496 512">
|
||||||
|
<path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/>
|
||||||
|
</symbol>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
|
||||||
|
|
||||||
|
<div class="container p-2">
|
||||||
|
<h1>DualShock Calibration GUI</h1>
|
||||||
|
|
||||||
|
<div id="missinghid" style="display: none;">
|
||||||
|
<p>Unsupported browser. Please use a web browser with WebHID support (e.g. Chrome).</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="offlinebar" class="vstack p-2" style="display: none;">
|
||||||
|
<p>Connect a DualShock 4 or a DualSense to your computer and press Connect.</p>
|
||||||
|
<button id="btnconnect" type="button" class="btn btn-outline-primary" onclick="connect()">Connect</button><br>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="onlinebar" class="vstack p-2" style="display: none;">
|
||||||
|
<div class="hstack gap-2"><p><b>Connected to:</b></p><p id="devname"></p></div>
|
||||||
|
<button type="button" class="btn btn-outline-secondary" onclick="disconnect()">Disconnect</button><br>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="mainmenu" class="container" style="display: none;">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6 col-sm-12">
|
||||||
|
<div class="card text-bg-light" >
|
||||||
|
<div class="card-header">Firmware Info</div>
|
||||||
|
|
||||||
|
<div class="vstack p-2" id="fwinfo"> </div>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6 col-sm-12">
|
||||||
|
<div class="vstack gap-2 p-2">
|
||||||
|
<button id="btnmcs2" type="button" class="btn btn-primary ds-btn" onclick="calib_open()">Calibrate stick center</button>
|
||||||
|
<div class="hstack gap-2">
|
||||||
|
<button type="button" class="btn btn-primary ds-btn" onclick="multi_calibrate_range(true)">Calibrate stick range (permanent)</button>
|
||||||
|
<button type="button" class="btn btn-primary ds-btn" onclick="multi_calibrate_range(false)">Calibrate stick range (temporary)</button>
|
||||||
|
</div>
|
||||||
|
<button type="button" class="btn btn-danger ds-btn" onclick="multi_reset()" id="resetBtn">Reset controller</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<p> Sections below are not useful, just some debug infos or manual commands</p>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6 col-sm-12">
|
||||||
|
<div class="card text-bg-light" >
|
||||||
|
<div class="card-header">Debug info</div>
|
||||||
|
<div class="vstack p-2">
|
||||||
|
<div class="hstack"><p>NVS Status</p><p class="ms-auto" id="d-nvstatus">Unknown</p></div>
|
||||||
|
<div class="hstack"><p>BD Addr</p><p class="ms-auto" id="d-bdaddr">Unknown</p></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6 col-sm-12">
|
||||||
|
<div class="card text-bg-light" >
|
||||||
|
<div class="card-header">Debug buttons</div>
|
||||||
|
<div class="vstack gap-2 p-2">
|
||||||
|
<div class="hstack gap-2">
|
||||||
|
<button type="button" class="btn btn-success ds-btn" onclick="multi_nvstatus()">Query NVS status</button>
|
||||||
|
<button type="button" class="btn btn-primary ds-btn" onclick="multi_nvsunlock()">NVS unlock</button>
|
||||||
|
<button type="button" class="btn btn-primary ds-btn" onclick="multi_nvslock()">NVS lock</button>
|
||||||
|
</div>
|
||||||
|
<button type="button" class="btn btn-primary ds-btn" onclick="multi_getbdaddr()">Get BDAddr</button>
|
||||||
|
<button id="btnmcs" type="button" class="btn btn-primary ds-btn" onclick="multi_calibrate_sticks()">Fast calibrate stick center (OLD)</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- New calibrate modal -->
|
||||||
|
<div class="modal fade" id="calibCenterModal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="calibTitle" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-lg">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h1 class="modal-title fs-5" id="calibTitle">Stick Center calibration</h1>
|
||||||
|
<button type="button" id="calibCross" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-4">
|
||||||
|
<div class="list-group" id="list-tab">
|
||||||
|
<a class="list-group-item list-group-item-action active" id="list-1-calib">Welcome</a>
|
||||||
|
<a class="list-group-item list-group-item-action" id="list-2-calib">Step 1</a>
|
||||||
|
<a class="list-group-item list-group-item-action" id="list-3-calib">Step 2</a>
|
||||||
|
<a class="list-group-item list-group-item-action" id="list-4-calib">Step 3</a>
|
||||||
|
<a class="list-group-item list-group-item-action" id="list-5-calib">Step 4</a>
|
||||||
|
<a class="list-group-item list-group-item-action" id="list-6-calib">Completed</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-8">
|
||||||
|
<div class="container" id="list-1">
|
||||||
|
<h4>Welcome to the stick center-calibration wizard!</h4>
|
||||||
|
|
||||||
|
<p>This tool will guide you in re-centering the analog sticks of your controller.
|
||||||
|
It consists in four steps: you will be asked to move both
|
||||||
|
sticks in a direction and release them.</p>
|
||||||
|
|
||||||
|
<p>Please be aware that, <i>once the calibration is running,
|
||||||
|
it cannot be canceled</i>. Do not close this page or
|
||||||
|
disconnect your controller until is completed.</p>
|
||||||
|
|
||||||
|
<h5>Calibration storage</h5>
|
||||||
|
|
||||||
|
<p>By default the calibration is only saved in a volatile
|
||||||
|
storage, so that if you (or this tool) mess something up, a
|
||||||
|
reset of the controller is enough to make it work again. </p>
|
||||||
|
|
||||||
|
<p>If you wish to store the calibration permanently in the controller, tick the checkbox below:</p>
|
||||||
|
|
||||||
|
<input class="form-check-input" type="checkbox" value="" id="calibPermanentChanges">
|
||||||
|
<label class="form-check-label" for="calibPermanentChanges">
|
||||||
|
Write changes permanently in the controller
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<br><br>
|
||||||
|
|
||||||
|
<p>Press <b>Start</b> to begin calibration.</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="container" style="display: none;" id="list-2">
|
||||||
|
<p>Please move both sticks to the <b>top-left corner</b> and release them.</p>
|
||||||
|
<p>When the sticks are back in the center, press <b>Continue</b>.</p>
|
||||||
|
</div>
|
||||||
|
<div class="container" style="display: none;" id="list-3">
|
||||||
|
<p>Please move both sticks to the <b>top-right corner</b> and release them.</p>
|
||||||
|
<p>When the sticks are back in the center, press <b>Continue</b>.</p>
|
||||||
|
</div>
|
||||||
|
<div class="container" style="display: none;" id="list-4">
|
||||||
|
<p>Please move both sticks to the <b>bottom-left corner</b> and release them.</p>
|
||||||
|
<p>When the sticks are back in the center, press <b>Continue</b>.</p>
|
||||||
|
</div>
|
||||||
|
<div class="container" style="display: none;" id="list-5">
|
||||||
|
<p>Please move both sticks to the <b>bottom-right corner</b> and release them.</p>
|
||||||
|
<p>When the sticks are back in the center, press <b>Continue</b>.</p>
|
||||||
|
</div>
|
||||||
|
<div class="container" style="display: none;" id="list-6">
|
||||||
|
Calibration completed successfully!<br><br>
|
||||||
|
|
||||||
|
You can check the calibration with the <a href="https://hardwaretester.com/gamepad" target="_blank">gamepad tester</a>.
|
||||||
|
<br><br>
|
||||||
|
Have a nice day :)
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-primary" id="calibNext" onclick="calib_next()">
|
||||||
|
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true" id="btnSpinner" style="display: none;"></span>
|
||||||
|
<span id="calibNextText">Next</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Modal -->
|
||||||
|
<div class="modal fade" id="calibrateModal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="staticBackdropLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h1 class="modal-title fs-5" id="staticBackdropLabel">Calibrating center</h1>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
Recentering the controller sticks. <br>
|
||||||
|
Please do not close this window and do not disconnect your controller.<br>
|
||||||
|
<div class="progress" role="progressbar" aria-label="Centering" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">
|
||||||
|
<div class="progress-bar" style="width: 0%"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Modal -->
|
||||||
|
<div class="modal fade" id="rangeModal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="staticBackdropLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h1 class="modal-title fs-5" id="staticBackdropLabel">Range calibration</h1>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<b>The controller is now sampling data!</b> <br>
|
||||||
|
Rotate the sticks slowly to cover the whole range. Press "Done" when completed.
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-primary" onclick="multi_calibrate_range_on_close()">Done</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Popup -->
|
||||||
|
<div class="modal fade" id="popupModal" tabindex="-1" aria-labelledby="popupTitle" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-dialog-centered">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-body" id="popupBody"></div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-primary" data-bs-dismiss="modal">OK</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<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>Version 0.3<small class="text-muted">beta</small> (2024-04-06)</p>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
<!-- Google tag (gtag.js) -->
|
||||||
|
<script async src="https://www.googletagmanager.com/gtag/js?id=G-FSXPMDXLLS"></script>
|
||||||
|
<script>
|
||||||
|
window.dataLayer = window.dataLayer || [];
|
||||||
|
function gtag(){dataLayer.push(arguments);}
|
||||||
|
gtag('js', new Date());
|
||||||
|
gtag('config', 'G-FSXPMDXLLS');
|
||||||
|
gboot();
|
||||||
|
</script>
|
||||||
|
</html>
|
Loading…
x
Reference in New Issue
Block a user