Пример #1
0
        static void Run(bool asGUI)
        {
            BasePath     = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
            DataBasePath = Path.Combine(BasePath, DataBasePath);
            UserDataPath = Path.Combine(BasePath, UserDataPath);

            if (!Localization.Load())
            {
                LogFatalError("Failed to load localization data");
                return;
            }
            if (!KeyValues.Load())
            {
                LogFatalError("Failed to load the key data");
                return;
            }
            if (!KeyboardState.Load())
            {
                LogFatalError("Failed to load keyboard data");
                return;
            }

#if COMMAND_LOGGER_ENABLED
            if (args.Length > 0 && args[0].ToLower() == "clog")
            {
                CommandLogger.Run();
                return;
            }
#endif

            KeyboardDeviceManager.Connected += (KeyboardDevice device) =>
            {
                Log("Connected to device '" + device.State.ModelName + "' model:" + device.State.ModelId +
                    " fw:" + device.State.FirmwareVersion);
                WebGUI.UpdateDeviceList();

                string file = GetUserDataFile(device);
                if (!string.IsNullOrEmpty(file))
                {
                    try
                    {
                        string dir = Path.GetDirectoryName(file);
                        if (!Directory.Exists(dir))
                        {
                            Directory.CreateDirectory(dir);
                        }
                        if (!File.Exists(file))
                        {
                            File.WriteAllText(file, string.Empty, Encoding.UTF8);
                        }
                    }
                    catch
                    {
                    }
                }
            };
            KeyboardDeviceManager.Disconnected += (KeyboardDevice device) =>
            {
                Log("Disconnected from device '" + device.State.ModelName + "'");
                WebGUI.UpdateDeviceList();
            };
            KeyboardDeviceManager.StartListener();

            if (asGUI)
            {
                Process   currentProc = Process.GetCurrentProcess();
                Process[] procs       = Process.GetProcessesByName(currentProc.ProcessName);
                try
                {
                    foreach (Process proc in procs)
                    {
                        try
                        {
                            if (proc != currentProc && proc.Id != currentProc.Id)
                            {
                                proc.Kill();
                            }
                        }
                        catch
                        {
                        }
                    }
                }
                finally
                {
                    foreach (Process proc in procs)
                    {
                        proc.Close();
                    }
                }
                currentProc.Close();

                WebGUI.Run();
                while (WebGUI.LastPing > DateTime.Now - WebGUI.PingTimeout)
                {
                    Thread.Sleep(1000);
                }
                return;
            }

            bool running      = true;
            bool hasNullInput = false;
            while (running)
            {
                string line = Console.ReadLine();
                if (line == null)
                {
                    // Handler for potential issue where ReadLine() returns null - see https://github.com/pixeltris/GK6X/issues/8
                    if (hasNullInput)
                    {
                        Console.WriteLine("Cannot read from command line. Exiting.");
                        break;
                    }
                    hasNullInput = true;
                    continue;
                }
                hasNullInput = false;
                string[] splitted = line.Split();
                switch (splitted[0].ToLower())
                {
                case "close":
                case "exit":
                case "quit":
                    running = false;
                    break;

                case "cls":
                case "clear":
                    Console.Clear();
                    break;

                case "update_data":
                    if (splitted.Length > 1)
                    {
                        string path      = line.TrimStart();
                        int    spaceChar = path.IndexOf(' ');
                        if (spaceChar > 0)
                        {
                            path = path.Substring(spaceChar).Trim();
                        }
                        bool isValidPath = false;
                        try
                        {
                            if (Directory.Exists(path))
                            {
                                isValidPath = true;
                            }
                        }
                        catch
                        {
                        }
                        if (isValidPath)
                        {
                            UpdateDataFiles(path);
                            Log("done");
                        }
                        else
                        {
                            Log("Couldn't find path '" + path + "'");
                        }
                    }
                    else
                    {
                        Log("Bad input. Expected folder name.");
                    }
                    break;

                case "gui":
                    WebGUI.Run();
                    break;

                case "gui_to_txt":
                {
                    if (string.IsNullOrEmpty(WebGUI.UserDataPath))
                    {
                        Log("Load GUI first");
                    }
                    else
                    {
                        string userDataPath = WebGUI.UserDataPath;
                        int    accountId    = 0;
                        string accountDir   = Path.Combine(userDataPath, "Account", accountId.ToString());
                        if (Directory.Exists(accountDir))
                        {
                            foreach (KeyboardDevice device in KeyboardDeviceManager.GetConnectedDevices())
                            {
                                string deviceDir = Path.Combine(userDataPath, "Account", accountId.ToString(), "Devices", device.State.ModelId.ToString());
                                if (Directory.Exists(deviceDir))
                                {
                                    Dictionary <int, UserDataFile.Macro> macrosById = new Dictionary <int, UserDataFile.Macro>();
                                    UserDataFile userDataFile = new UserDataFile();
                                    foreach (string file in Directory.GetFiles(deviceDir, "*.cmf"))
                                    {
                                        string config = Encoding.UTF8.GetString(CMFile.Load(file));
                                        Dictionary <string, object> data = MiniJSON.Json.Deserialize(config) as Dictionary <string, object>;
                                        int           modelIndex         = (int)Convert.ChangeType(data["ModeIndex"], typeof(int));
                                        KeyboardLayer layer = (KeyboardLayer)modelIndex;

                                        //////////////////////////////////////////
                                        // Keys / macros (NOTE: Macros on different layers might wipe each other. look into.)
                                        //////////////////////////////////////////
                                        for (int i = 0; i < 2; i++)
                                        {
                                            string setStr = i == 0 ? "KeySet" : "FnKeySet";
                                            if (data.ContainsKey(setStr))
                                            {
                                                List <object> keys = data[setStr] as List <object>;
                                                foreach (object keyObj in keys)
                                                {
                                                    Dictionary <string, object> key = keyObj as Dictionary <string, object>;
                                                    int    keyIndex       = (int)Convert.ChangeType(key["Index"], typeof(int));
                                                    uint   driverValue    = KeyValues.UnusedKeyValue;
                                                    string driverValueStr = (string)key["DriverValue"];
                                                    if (driverValueStr.StartsWith("0x"))
                                                    {
                                                        if (uint.TryParse(driverValueStr.Substring(2), System.Globalization.NumberStyles.HexNumber, null, out driverValue))
                                                        {
                                                            if (KeyValues.GetKeyType(driverValue) == DriverValueType.Macro && key.ContainsKey("Task"))
                                                            {
                                                                Dictionary <string, object> task = key["Task"] as Dictionary <string, object>;
                                                                if (task != null && (string)task["Type"] == "Macro")
                                                                {
                                                                    Dictionary <string, object> taskData = task["Data"] as Dictionary <string, object>;
                                                                    string macroGuid = (string)taskData["GUID"];
                                                                    string macroFile = Path.Combine(userDataPath, "Account", accountId.ToString(), "Macro", macroGuid + ".cms");
                                                                    if (File.Exists(macroFile))
                                                                    {
                                                                        UserDataFile.Macro macro = new UserDataFile.Macro(null);
                                                                        macro.LoadFile(macroFile);
                                                                        macro.RepeatCount              = (byte)Convert.ChangeType(taskData["Repeats"], typeof(byte));
                                                                        macro.RepeatType               = (MacroRepeatType)(byte)Convert.ChangeType(taskData["StopMode"], typeof(byte));
                                                                        macro.Id                       = KeyValues.GetKeyData2(driverValue);
                                                                        macrosById[macro.Id]           = macro;
                                                                        userDataFile.Macros[macroGuid] = macro;
                                                                    }
                                                                }
                                                            }
                                                        }
                                                        else
                                                        {
                                                            driverValue = KeyValues.UnusedKeyValue;
                                                        }
                                                    }
                                                    if (keyIndex >= 0 && keyIndex < device.State.MaxLogicCode && driverValue != KeyValues.UnusedKeyValue)
                                                    {
                                                        KeyboardState.Key keyInfo = device.State.GetKeyByLogicCode(keyIndex);
                                                        if (keyInfo != null)
                                                        {
                                                            Dictionary <string, uint> vals = userDataFile.FindOrAddLayer(layer, i > 0).Keys;
                                                            if (Enum.IsDefined(typeof(DriverValue), driverValue))
                                                            {
                                                                vals[keyInfo.DriverValueName.ToLower()] = driverValue;
                                                            }
                                                            else
                                                            {
                                                                Log("Failed to map index " + keyIndex + " to " + driverValue + " on layer " + layer +
                                                                    (i > 0 ? " fn" : string.Empty));
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }

                                        //////////////////////////////////////////
                                        // Lighting
                                        //////////////////////////////////////////
                                        Dictionary <string, UserDataFile.LightingEffect> effects = new Dictionary <string, UserDataFile.LightingEffect>();
                                        string[] leHeaders = { "ModeLE", "DriverLE" };
                                        foreach (string leHeader in leHeaders)
                                        {
                                            if (data.ContainsKey(leHeader))
                                            {
                                                List <object> leEntries = data[leHeader] as List <object>;
                                                if (leEntries == null)
                                                {
                                                    // There's only one ModeLE
                                                    leEntries = new List <object>();
                                                    leEntries.Add(data[leHeader]);
                                                }
                                                foreach (object entry in leEntries)
                                                {
                                                    Dictionary <string, object> modeLE = entry as Dictionary <string, object>;
                                                    string leGuid = (string)modeLE["GUID"];
                                                    if (!string.IsNullOrEmpty(leGuid))
                                                    {
                                                        string filePath = Path.Combine(userDataPath, "Account", accountId.ToString(), "LE", leGuid + ".le");
                                                        if (!effects.ContainsKey(leGuid) && File.Exists(filePath))
                                                        {
                                                            UserDataFile.LightingEffect le = new UserDataFile.LightingEffect(userDataFile, null);
                                                            le.Load(device.State, Encoding.UTF8.GetString(CMFile.Load(filePath)));
                                                            le.Layers.Add(layer);
                                                            userDataFile.LightingEffects[leGuid] = le;
                                                            effects[leGuid] = le;
                                                        }
                                                    }
                                                    else
                                                    {
                                                        object leDataObj;
                                                        if (modeLE.TryGetValue("LEData", out leDataObj))
                                                        {
                                                            Dictionary <string, object> leData = leDataObj as Dictionary <string, object>;
                                                            if (leData != null)
                                                            {
                                                                // This should be static lighting data only
                                                                UserDataFile.LightingEffect le = new UserDataFile.LightingEffect(userDataFile, null);
                                                                le.LoadStatic(device.State, leData);
                                                                le.Layers.Add(layer);
                                                                userDataFile.LightingEffects[Guid.NewGuid().ToString()] = le;
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                    userDataFile.SaveFromGUI(device.State, Path.Combine(UserDataPath, device.State.ModelId + "_exported.txt"));
                                    Log("Done");
                                    break;
                                }
                            }
                        }
                        else
                        {
                            Log("Account settings not found for account id " + accountId);
                        }
                    }
                }
                break;

                case "gui_le":
                {
                    string userDataPath = WebGUI.UserDataPath;
                    string leName       = line.Trim();
                    int    spaceIndex   = leName.IndexOf(' ');
                    if (spaceIndex > 0)
                    {
                        leName = leName.Substring(spaceIndex).Trim();
                    }
                    else
                    {
                        leName = null;
                    }
                    if (!string.IsNullOrEmpty(leName))
                    {
                        if (!string.IsNullOrEmpty(userDataPath) && Directory.Exists(userDataPath))
                        {
                            string leDir      = Path.Combine(userDataPath, "Account", "0", "LE");
                            string leListFile = Path.Combine(leDir, "lelist.json");
                            if (File.Exists(leListFile))
                            {
                                bool          foundFile = false;
                                List <object> leList    = MiniJSON.Json.Deserialize(File.ReadAllText(leListFile)) as List <object>;
                                if (leList != null)
                                {
                                    foreach (object item in leList)
                                    {
                                        Dictionary <string, object> guidName = item as Dictionary <string, object>;
                                        if (guidName["Name"].ToString() == leName)
                                        {
                                            string leFileName = Path.Combine(leDir, guidName["GUID"].ToString() + ".le");
                                            if (File.Exists(leFileName))
                                            {
                                                foreach (char c in System.IO.Path.GetInvalidFileNameChars())
                                                {
                                                    leName = leName.Replace(c, '_');
                                                }
                                                string effectString = Encoding.UTF8.GetString(CMFile.Load(leFileName));
                                                effectString = CMFile.FormatJson(effectString);
                                                File.WriteAllText(Path.Combine(DataBasePath, "lighting", leName + ".le"), effectString);
                                                Program.Log("Copied '" + leName + "'");
                                                foundFile = true;
                                            }
                                        }
                                    }
                                }
                                if (!foundFile)
                                {
                                    Program.Log("Failed to find lighting effect '" + leName + "' (it's case sensitive)");
                                }
                            }
                            else
                            {
                                Program.Log("Failed to find file '" + leListFile + "'");
                            }
                        }
                    }
                    else
                    {
                        Program.Log("Invalid input. Expected lighting effect name.");
                    }
                }
                break;

                case "findkeys":
                {
                    Log(string.Empty);
                    Log("This is used to identify keys. Press keys to see their values. Missing keys will generally show up as '(null)' and they need to be mapped in the data files Data/devuces/YOUR_MODEL_ID/");
                    Log("The 'S' values are what you want to use to map keys in your UserData file.");
                    Log(string.Empty);
                    Log("Entering 'driver' mode and mapping all keys to callbacks.");
                    Log(string.Empty);
                    KeyboardDevice[] devices;
                    if (TryGetDevices(out devices))
                    {
                        foreach (KeyboardDevice device in devices)
                        {
                            device.SetLayer(KeyboardLayer.Driver);
                            device.SetIdentifyDriverMacros();
                        }
                    }
                }
                break;

                case "map":
                case "unmap":
                {
                    bool             map = splitted[0].ToLower() == "map";
                    KeyboardDevice[] devices;
                    KeyboardLayer    targetLayer;
                    bool             targetLayerIsFn;
                    TryParseLayer(splitted, 1, out targetLayer, out targetLayerIsFn);
                    bool hasTargetLayer = targetLayer != KeyboardLayer.Invalid;
                    if (TryGetDevices(out devices))
                    {
                        foreach (KeyboardDevice device in devices)
                        {
                            UserDataFile userData = UserDataFile.Load(device.State, GetUserDataFile(device));
                            if (userData == null)
                            {
                                Log("Couldn't find user data file '" + GetUserDataFile(device) + "'");
                                continue;
                            }

                            foreach (KeyValuePair <KeyboardLayer, KeyboardStateLayer> layer in device.State.Layers)
                            {
                                if (layer.Key == KeyboardLayer.Driver)
                                {
                                    continue;
                                }

                                if (hasTargetLayer && layer.Key != targetLayer)
                                {
                                    continue;
                                }

                                device.SetLighting(layer.Key, userData);
                                device.SetMacros(layer.Key, userData);

                                for (int i = 0; i < 2; i++)
                                {
                                    bool fn = i == 1;
                                    if (targetLayer != KeyboardLayer.Invalid && fn != targetLayerIsFn)
                                    {
                                        continue;
                                    }

                                    // Setting keys to 0xFFFFFFFF is preferable compared to using what is defined in
                                    // files as this will use what is defined in the firmware.
                                    uint[] driverValues = new uint[device.State.MaxLogicCode];
                                    for (int j = 0; j < driverValues.Length; j++)
                                    {
                                        driverValues[j] = KeyValues.UnusedKeyValue;
                                    }

                                    if (map)
                                    {
                                        UserDataFile.Layer userDataLayer;
                                        if (fn)
                                        {
                                            userData.FnLayers.TryGetValue(layer.Key, out userDataLayer);
                                        }
                                        else
                                        {
                                            userData.Layers.TryGetValue(layer.Key, out userDataLayer);
                                        }
                                        if (userDataLayer != null)
                                        {
                                            for (int j = 0; j < driverValues.Length; j++)
                                            {
                                                KeyboardState.Key key = device.State.GetKeyByLogicCode(j);
                                                if (key != null)
                                                {
                                                    driverValues[j] = userDataLayer.GetKey(key);
                                                }
                                            }
                                        }
                                    }
                                    device.SetKeys(layer.Key, driverValues, fn);
                                }
                            }

                            // This is required to "refresh" the keyboard with the updated key info
                            if (hasTargetLayer)
                            {
                                device.SetLayer(targetLayer);
                            }
                            else
                            {
                                device.SetLayer(KeyboardLayer.Base);
                            }
                            Log("Done");
                        }
                    }
                }
                break;

                case "dumpkeys":
                {
                    int targetRow = -1;
                    if (splitted.Length > 1)
                    {
                        if (!int.TryParse(splitted[1], out targetRow))
                        {
                            targetRow = -1;
                        }
                    }
                    bool showLocationCodeInfo = false;
                    if (splitted.Length > 2)
                    {
                        showLocationCodeInfo = splitted[2] == "ex";
                    }

                    KeyboardDevice[] devices;
                    if (TryGetDevices(out devices))
                    {
                        foreach (KeyboardDevice device in devices)
                        {
                            Log("====== " + device.State.ModelId + " ======");
                            bool foundKey = false;
                            int  lastLeft = int.MinValue;
                            int  row      = 1;
                            foreach (KeyboardState.Key key in device.State.KeysByLocationCode.Values.OrderBy(
                                         x => x.Position.Top).ThenBy(x => x.Position.Left))
                            {
                                if (key.Position.Left >= 0)
                                {
                                    if (lastLeft > key.Position.Left && foundKey)
                                    {
                                        if (targetRow == -1)
                                        {
                                            Log("--------");
                                        }
                                        foundKey = false;
                                        row++;
                                    }
                                    lastLeft = key.Position.Left;
                                }

                                if (string.IsNullOrEmpty(key.KeyName) || !key.KeyName.StartsWith("LED-"))
                                {
                                    if (targetRow == -1 || row == targetRow)
                                    {
                                        Log(key.KeyName + " = " + key.DriverValueName +
                                            (showLocationCodeInfo ? " (" + key.LocationCode + ")" : string.Empty));
                                    }
                                    foundKey = true;
                                }
                            }
                        }
                    }
                }
                break;
                }
            }
        }
Пример #2
0
        public void SetLighting(KeyboardLayer layer, UserDataFile userData)
        {
            List <UserDataFile.LightingEffect> lightingEffects = userData.GetLightingEffects(layer);

            if (lightingEffects.Count > 0 || userData.NoLighting || userData.NoLightingLayers.Contains(layer))
            {
                WritePacketNoResponse(OpCodes.LayerResetDataType, (byte)layer, null, (byte)KeyboardLayerDataType.Lighting);
            }
            if (lightingEffects.Count > 0)
            {
                using (Packet packet = new Packet())
                {
                    const int maxEffects = UserDataFile.LightingEffect.MaxEffects;
                    packet.WriteBytes(new byte[maxEffects * (4 * 4)]);
                    List <Tuple <int, int, int, int> > dataOffsets = new List <Tuple <int, int, int, int> >();

                    for (int i = 0; i < Math.Min(maxEffects, lightingEffects.Count); i++)
                    {
                        UserDataFile.LightingEffect lightingEffect = lightingEffects[i];
                        if (lightingEffect != null)
                        {
                            int data1Offset = packet.Index;
                            int data1Count  = 0;
                            switch (lightingEffect.Type)
                            {
                            case LightingEffectType.Static:
                            {
                                data1Count = 1;
                                packet.WriteUInt16((ushort)lightingEffect.Type);
                                packet.WriteUInt16((ushort)(UserDataFile.LightingEffect.NumStaticLightingBytes));
                                uint[] keyColors = new uint[UserDataFile.LightingEffect.NumStaticLightingBytes / 4];
                                foreach (KeyValuePair <int, uint> keyColor in lightingEffect.KeyColors)
                                {
                                    keyColors[keyColor.Key] = keyColor.Value;
                                }
                                foreach (uint color in keyColors)
                                {
                                    packet.WriteUInt32(color);
                                }
                            }
                            break;

                            case LightingEffectType.Dynamic:
                            {
                                data1Count = lightingEffect.TotalFrames;
                                foreach (UserDataFile.LightingEffect.Frame frame in lightingEffect.Frames)
                                {
                                    for (int j = 0; j < frame.Count; j++)
                                    {
                                        packet.WriteUInt16((ushort)lightingEffect.Type);
                                        packet.WriteUInt16(22);        // 22 bytes of data (176 bits)
                                        byte[] byteBits = new byte[22];
                                        foreach (int keyCode in frame.KeyCodes)
                                        {
                                            int byteIndex = keyCode / 8;
                                            int bitIndex  = keyCode % 8;
                                            byteBits[byteIndex] |= (byte)(1 << bitIndex);
                                        }
                                        packet.WriteBytes(byteBits);
                                    }
                                }
                            }
                            break;
                            }

                            int data2Offset = packet.Index;
                            int data2Count  = 0;
                            switch (lightingEffect.Type)
                            {
                            case LightingEffectType.Static:
                                data2Offset = 0;
                                data2Count  = 0;
                                break;

                            case LightingEffectType.Dynamic:
                                data2Count = lightingEffect.Params.Count;
                                foreach (UserDataFile.LightingEffect.Param param in lightingEffect.Params)
                                {
                                    packet.WriteByte((byte)param.ColorType);
                                    packet.WriteByte(32);    // The size of the param buffer? (total size including self)

                                    // The keys impacted by the param (as a bit array)
                                    byte[] byteBits = new byte[22];
                                    foreach (int keyCode in param.Keys)
                                    {
                                        int byteIndex = keyCode / 8;
                                        int bitIndex  = keyCode % 8;
                                        byteBits[byteIndex] |= (byte)(1 << bitIndex);
                                    }
                                    packet.WriteBytes(byteBits);

                                    packet.WriteUInt32(param.Color);
                                    if (param.UseRawValues)
                                    {
                                        packet.WriteUInt16((ushort)param.Val1);
                                        packet.WriteUInt16((ushort)param.Val2);
                                    }
                                    else
                                    {
                                        switch (param.ColorType)
                                        {
                                        case LightingEffectColorType.Breathing:
                                            packet.WriteUInt16((ushort)(param.Val1 == 0 ? 0 : 100 / param.Val1));
                                            packet.WriteUInt16((ushort)param.Val2);        // "StayCount"
                                            break;

                                        default:
                                            // NOTE: RGB values seem to use 0x26 for the 2nd value? Is this just a random uninitialized variable?
                                            packet.WriteUInt16((ushort)(param.Val1 == 0 ? 0 : 360 / param.Val1));
                                            packet.WriteUInt16(0);
                                            break;
                                        }
                                    }
                                }
                                break;
                            }

                            dataOffsets.Add(new Tuple <int, int, int, int>(data1Offset, data1Count, data2Offset, data2Count));
                        }
                    }

                    int tempIndex = packet.Index;
                    packet.Index = 0;
                    for (int i = 0; i < maxEffects; i++)
                    {
                        Tuple <int, int, int, int> offsets = i < lightingEffects.Count ? dataOffsets[i] : null;
                        if (offsets != null)
                        {
                            packet.WriteInt32(offsets.Item1);
                            packet.WriteInt32(offsets.Item2);
                            packet.WriteInt32(offsets.Item3);
                            packet.WriteInt32(offsets.Item4);
                        }
                        else
                        {
                            packet.WriteInt32(-1);
                            packet.WriteInt32(-1);
                            packet.WriteInt32(-1);
                            packet.WriteInt32(-1);
                        }
                    }
                    packet.Index = tempIndex;
                    WritePacketNoResponse(OpCodes.LayerSetLightValues, (byte)layer, packet);
                }
            }
        }