2024-06-01 22:48:42 +02:00
|
|
|
export function Name() { return "Corsair Virtuoso XT Headset"; }
|
2024-06-01 22:10:56 +02:00
|
|
|
export function VendorId() { return 0x1b1c; }
|
|
|
|
export function ProductId() { return 0x0A64; }
|
|
|
|
export function Publisher() { return "WhirlwindFX"; }
|
|
|
|
export function Documentation(){ return "troubleshooting/corsair"; }
|
|
|
|
export function Size() { return [1, 1]; }
|
|
|
|
export function DefaultPosition(){return [145, 85];}
|
|
|
|
export function DefaultScale(){return 10.0;}
|
|
|
|
|
|
|
|
|
|
|
|
/* global
|
|
|
|
LightingMode:readonly
|
|
|
|
forcedColor:readonly
|
|
|
|
micLedMode:readonly
|
|
|
|
micLedDefState:readonly
|
|
|
|
micColorOn:readonly
|
|
|
|
micColorOff:readonly
|
|
|
|
*/
|
|
|
|
export function ControllableParameters() {
|
|
|
|
return [
|
|
|
|
{"property":"LightingMode", "group":"lighting", "label":"Lighting Mode", "type":"combobox", "values":["Canvas", "Forced"], "default":"Canvas"},
|
|
|
|
{"property":"forcedColor", "group":"lighting", "label":"Forced Color", "min":"0", "max":"360", "type":"color", "default":"#009bde"},
|
|
|
|
{"property":"micLedMode", "group":"lighting", "label":"Microphone LED Mode", "type":"combobox", "values":["Effect", "MicState"], "default":"Effect"},
|
|
|
|
{"property":"micLedDefState", "group":"lighting", "label":"Microphone Default State", "type":"combobox", "values":["OFF", "ON"], "default":"OFF"},
|
|
|
|
{"property":"micColorOn", "group":"lighting", "label":"Microphone Color ON", "min":"0", "max":"360", "type":"color", "default":"#33cc33"},
|
|
|
|
{"property":"micColorOff", "group":"lighting", "label":"Microphone Color OFF", "min":"0", "max":"360", "type":"color", "default":"#cc0000"},
|
|
|
|
];
|
|
|
|
}
|
|
|
|
export function Documentation(){ return "troubleshooting/corsair"; }
|
|
|
|
|
|
|
|
let headsetMode;
|
|
|
|
let micState;
|
|
|
|
|
|
|
|
const vLedNames = ["Logo", "Mic"];
|
|
|
|
|
|
|
|
const vLedPositions = [ [0, 0], [0, 1] ];
|
|
|
|
|
|
|
|
export function LedNames() {
|
|
|
|
return vLedNames;
|
|
|
|
}
|
|
|
|
|
|
|
|
export function LedPositions() {
|
|
|
|
return vLedPositions;
|
|
|
|
}
|
|
|
|
|
|
|
|
function sendColor(shutdown = false) {
|
|
|
|
let mxPxColor;
|
|
|
|
const packet = new Array(64).fill(0x00);
|
|
|
|
|
|
|
|
packet[0] = 0x02;
|
|
|
|
packet[1] = headsetMode;
|
|
|
|
packet[2] = 0x06;
|
|
|
|
packet[4] = 0x09;
|
|
|
|
|
|
|
|
if(shutdown) {
|
|
|
|
packet[2] = 0x01;
|
|
|
|
packet[3] = 0x02;
|
|
|
|
packet[4] = 0x00;
|
|
|
|
device.write(packet, 64);
|
|
|
|
} else {
|
|
|
|
for(let iIdx = 0; iIdx < vLedPositions.length; iIdx++) {
|
|
|
|
if(iIdx == 1 && micLedMode == "MicState") {
|
|
|
|
mxPxColor = hexToRgb(micState == 0 ? micColorOff : micColorOn);
|
|
|
|
} else {
|
|
|
|
const iPxX = vLedPositions[iIdx][0];
|
|
|
|
const iPxY = vLedPositions[iIdx][1];
|
|
|
|
|
|
|
|
if (LightingMode === "Forced") {
|
|
|
|
mxPxColor = hexToRgb(forcedColor);
|
|
|
|
} else {
|
|
|
|
mxPxColor = device.color(iPxX, iPxY);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
packet[(iIdx*2)+8] = mxPxColor[0];
|
|
|
|
packet[(iIdx*2)+11] = mxPxColor[1];
|
|
|
|
packet[(iIdx*2)+14] = mxPxColor[2];
|
|
|
|
}
|
|
|
|
|
|
|
|
device.write(packet, 64);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function Initialize() {
|
2024-06-01 22:30:04 +02:00
|
|
|
headsetMode = (ProductId() == 0x0a6b || ProductId() == 0x0a64) ? 0x09 : 0x08;
|
2024-06-01 22:10:56 +02:00
|
|
|
device.set_endpoint(3, 0x0001, 0xFF42);
|
|
|
|
SetSoftwareMode();
|
|
|
|
}
|
|
|
|
|
|
|
|
function SetSoftwareMode() {
|
|
|
|
micState = micLedDefState == "ON" ? 1 : 0;
|
|
|
|
|
|
|
|
const packet = new Array(64).fill(0x00);
|
|
|
|
packet[0] = 0x02;
|
|
|
|
packet[1] = headsetMode;
|
|
|
|
packet[2] = 0x01;
|
|
|
|
packet[3] = 0x03;
|
|
|
|
packet[5] = 0x02;
|
|
|
|
device.write(packet, 64);
|
|
|
|
|
|
|
|
packet[2] = 0x0D;
|
|
|
|
packet[3] = 0x00;
|
|
|
|
packet[4] = 0x01;
|
|
|
|
packet[5] = 0x00;
|
|
|
|
device.write(packet, 64);
|
|
|
|
|
|
|
|
packet[2] = 0x01;
|
|
|
|
packet[3] = 0x02;
|
|
|
|
packet[4] = 0x00;
|
|
|
|
packet[5] = 0xE8;
|
|
|
|
packet[6] = 0x03;
|
|
|
|
device.write(packet, 64);
|
|
|
|
}
|
|
|
|
|
|
|
|
export function Render() {
|
|
|
|
readDevice();
|
|
|
|
device.pause(1);
|
|
|
|
sendColor();
|
|
|
|
}
|
|
|
|
|
|
|
|
function readDevice() {
|
|
|
|
device.set_endpoint(3, 0x0002, 0xFF42);
|
|
|
|
|
|
|
|
const packet = device.read([0x00], 64, 3);
|
|
|
|
device.set_endpoint(3, 0x0001, 0xFF42);
|
|
|
|
|
|
|
|
if(packet[0] == 0x03 && packet[1] == 0x01 && packet[2] == 0x01 && packet[3] == 0x10 && packet[4] == 0x00 && packet[5] == 0x02) {
|
|
|
|
SetSoftwareMode();
|
|
|
|
}
|
|
|
|
|
2024-06-01 22:40:33 +02:00
|
|
|
if(packet[0] == 0x03 && packet[2] == 0x01 && packet[3] == 0x46 && packet[4] == 0x00 && packet[5] == 0x00) {
|
2024-06-01 22:10:56 +02:00
|
|
|
micState = 1;
|
|
|
|
}
|
|
|
|
|
2024-06-01 22:40:33 +02:00
|
|
|
if(packet[0] == 0x03 && packet[2] == 0x01 && packet[3] == 0x46 && packet[4] == 0x00 && packet[5] == 0x01) {
|
2024-06-01 22:10:56 +02:00
|
|
|
micState = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function Shutdown() {
|
|
|
|
sendColor(true);
|
|
|
|
|
|
|
|
const packet = new Array(64).fill(0x00);
|
|
|
|
packet[0] = 0x02;
|
|
|
|
packet[1] = headsetMode;
|
|
|
|
packet[2] = 0x01;
|
|
|
|
packet[3] = 0x03;
|
|
|
|
packet[5] = 0x01;
|
|
|
|
device.write(packet, 64);
|
|
|
|
}
|
|
|
|
|
|
|
|
export function Validate(endpoint) {
|
2024-06-01 22:22:18 +02:00
|
|
|
return endpoint.interface === 3 && (endpoint.usage === 0x0001 || endpoint.usage === 0x0002) && endpoint.usage_page === 0xFF42;
|
2024-06-01 22:10:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
function hexToRgb(hex) {
|
|
|
|
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
|
|
|
const colors = [];
|
|
|
|
colors[0] = parseInt(result[1], 16);
|
|
|
|
colors[1] = parseInt(result[2], 16);
|
|
|
|
colors[2] = parseInt(result[3], 16);
|
|
|
|
|
|
|
|
return colors;
|
|
|
|
}
|
|
|
|
|
|
|
|
export function Image() {
|
2024-06-01 22:43:32 +02:00
|
|
|
return "iVBORw0KGgoAAAANSUhEUgAAA+gAAAH0CAYAAAHZLze7AAAACXBIWXMAAAsTAAALEwEAmpwYAAAGfmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNi4wLWMwMDUgNzkuMTY0NTkwLCAyMDIwLzEyLzA5LTExOjU3OjQ0ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdEV2dD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlRXZlbnQjIiB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgMjIuMSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIxLTAxLTI4VDE1OjIxOjI5LTA4OjAwIiB4bXA6TWV0YWRhdGFEYXRlPSIyMDIxLTAxLTI4VDE1OjIxOjI5LTA4OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyMS0wMS0yOFQxNToyMToyOS0wODowMCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo2MWZmZjZmMC0zYjE5LWU1NDUtYTQzZS1hMGU1ZDI3NDU0MzUiIHhtcE1NOkRvY3VtZW50SUQ9ImFkb2JlOmRvY2lkOnBob3Rvc2hvcDowYzFmYmViMy05MDZkLWJkNDEtYTUwYS1jNmI0MDlkYTVhYjIiIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpkYTJiN2VhNy0wYzBjLWM3NDUtOGZhOC04MmU0MTI2ZmQ4YjMiIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiIGRjOmZvcm1hdD0iaW1hZ2UvcG5nIj4gPHhtcE1NOkhpc3Rvcnk+IDxyZGY6U2VxPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0iY3JlYXRlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDpkYTJiN2VhNy0wYzBjLWM3NDUtOGZhOC04MmU0MTI2ZmQ4YjMiIHN0RXZ0OndoZW49IjIwMjEtMDEtMjhUMTU6MjE6MjktMDg6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCAyMi4xIChXaW5kb3dzKSIvPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0ic2F2ZWQiIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6NjFmZmY2ZjAtM2IxOS1lNTQ1LWE0M2UtYTBlNWQyNzQ1NDM1IiBzdEV2dDp3aGVuPSIyMDIxLTAxLTI4VDE1OjIxOjI5LTA4OjAwIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgMjIuMSAoV2luZG93cykiIHN0RXZ0OmNoYW5nZWQ9Ii8iLz4gPC9yZGY6U2VxPiA8L3htcE1NOkhpc3Rvcnk+IDxwaG90b3Nob3A6RG9jdW1lbnRBbmNlc3RvcnM+IDxyZGY6QmFnPiA8cmRmOmxpPkJCQkUyMDBENEJEMjcxNUZBNUE2MTYzMzIxRTZEMDVEPC9yZGY6bGk+IDxyZGY6bGk+RUQ0NzIwN0Y0NUU4NzdBOTI2NEY0RDgzNDUwRDZDRTU8L3JkZjpsaT4gPC9yZGY6QmFnPiA8L3Bob3Rvc2hvcDpEb2N1bWVudEFuY2VzdG9ycz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4nKmdGAAOfpUlEQVR4nOydd5wkVdX3v7dC5+7pyXFnNufIEpZlCUsOAmIiKQZEFAyIOWeUxwdQFBFRUUkiIjnnnGFzzjs7OXXuivf9o7p3egOwsPgw+9K/z6e2Z3p7qm/Vqd895557gpBSUsb7C8p7PYAy/u9RFvr7EGWhvw9RFvr7EGWhvw+hvdcD2B2EEP+1UxcOpfAKIHdz7DVG8qpoRAr9XURRwBrgBwKFw8fwtUvABkwgXzhMwOJdfAhGEv5/FbrAu7YAEAXiQGXhqADCeIIXgIMn5AyQBAaAwcKRBozCZ/6/Ef6IF7qUklwux2V/uuNNP7dy7TJuuuoSAah4wq4EGoAWYBTQNGb8nJMr6usndfV3qjJpYGsCXSjowSihkG5oQryy/NWnngS2AVuAdqAbSAD5X//5frdr6zomTp3+huM4//SFe3/R/2WMeKHvKW666hIFj70VQBMwDpjYOHryOVL1T9J1ga4FkaZFQ3UDolJBUcG1LVzp4trSbxjGIc0T5x6iSEVqGE9sXLvkXmAVsB7o+sZnT0gDzjW3PL5Ps/7/C6H/4KKzFCAE1ALjgemt46Z/Ou8yI15Vjc/vQ5Eaig5OLkeyN0XezgMKAVXF59OwhUo46CMaDuJKRSRz6YU1zdMWSmvw7/09HU8By4BNwND5py+09mXB7/NC/8FFZ6l4OroZmA7MrR8z/ZuOrouoHkBXFLKZLEGfj472TlxHoGkCIcCRkLUlmayDlJCQkurqOgwjS0W8Cl9TiFwq/MmahrHHr17yzK+BILAW6D//9IXmvir4fVroJQwfBcyZeeARnx0aTByuB4OEw2GwHHRd0N0xSFJTiUYqiFdEUANhgv4gUgUcyBh5nFyKTCZPKpfCtCzimovMuMSiYbLpbP3oSfv9atPq136Md89WAn14BuA+h31G6NXV1Si6gubzoQqVT5+2QOAZbE3ArAlT9rswkzHmhaqiRBQfHR1dCE3BMU2qaqqorKknoFsbHn/o3kek6yaBLN6yTAC+UDgcP/q4U09JJszW7v4++rf1YWgu/pxOZWUdDrY2esL+P9209pUfFP7OOv/0hYPX3PK4/Z7dlHcIMRKdCKXOmWtueZxPnHwQL6zu3uEzR84Z48OzzvebMnPu6ZYMnBH062hCQ/H52LZ1I6FAhLET2tynHr77r6ZprAE6gH52XIoB6HgzRjXQNmnKjGOjVU3HDvR0kzZsAn6NcGUlPiFwbNdY9uoT3wSexjPw0g8+s9IFF4Hg2AVTgbJz5l2BW7JMPnrOWAVv/T0amJO2xBk1FUEUqWO5Gbq2bqa2upFgSF/zyL3//ivedLwFbw2eZde1t4In+DCwfvXKpZth6cuHHv+Rb3Zs2qKnkoPUNTXh5CRSGP7RE2d/btOaRb3AEGAgXANA7iNL+X1C6Nff/SKatoNr1g/UAVPGzTzkm+F4JYrlEAyqdGwapHnUBNYuf/5viaHBp/Gs7q14a20DcO97apG0cllUv4o0bay8TTjs47ijDk7hCXIAGHz6gX+nDj321G/2dipVWzauo21UKzg6wheYhmc0dgCJ4w6ZZj3+6lr3/+6O7B32CaED7HeA5xCZ01qjABFgVNu48QdE/Xogn0rSN9CPVCTNDU28/sKDf3Ac52lgCZ6jJQM4jz29SBr5zO4ZqcKfrrve+dynP5EFuii4Yp9+6M5LDz/6Q9+zbRnr6OrC79OpjtdRd8gJX33x2fvX4wk+UxmNGfuK026fEbquKgjvnupAFTBGC9R+WgZDVAqV5GA/1TVV9HRtuM
|
2024-06-01 22:10:56 +02:00
|
|
|
}
|