Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom fw support #830

Merged
merged 20 commits into from
Jul 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
1eb0d0d
fix: made visible the version controls for devices with no github FW
alexpargon Jul 17, 2024
41ea2b6
feat: added folder functionality to load custom FW from folder if pre…
alexpargon Jul 17, 2024
ca6ad15
Chore: Added new animation keyframes and styles to the CustomModalFir…
thiagohernandez Jul 18, 2024
4560888
Chore: Change icon size and alignment on the files list in CustomFirm…
thiagohernandez Jul 18, 2024
f4179e7
fixed modal logic and implemented validator for custom fw loader
alexpargon Jul 18, 2024
8224300
chore: added comments for modal validator function
alexpargon Jul 18, 2024
c4481a4
fix: disable select custom fw button when files are not valid
alexpargon Jul 18, 2024
e6cf381
Fix: adjust styles to render properly in light mode the custom firmwa…
thiagohernandez Jul 18, 2024
c876704
fix: added more devices to fwFiles filter so that fw files are better…
alexpargon Jul 18, 2024
59501b0
Fix: add the selector to a custom firmware
thiagohernandez Jul 18, 2024
7a90bb8
fix: changed customFWcheck valeu storage to prevent false positives
alexpargon Jul 18, 2024
093d28d
Fix: Adjust text button color on light theme mode
thiagohernandez Jul 18, 2024
cd6f513
fix: now BT users can access flashing screen
alexpargon Jul 17, 2024
8a2fe4c
fix: added better error handling when passing connection errors to xs…
alexpargon Jul 17, 2024
a32b92a
fix: spread error handling feature to the rest of the xstate machines
alexpargon Jul 17, 2024
b507d15
feat: created message in place of button as bt disables the ability t…
alexpargon Jul 17, 2024
3287d45
feat: allow BT users to access Flashing screen
alexpargon Jul 17, 2024
4e542f5
Refactor: Added styles to custom firmware and alert when the device i…
thiagohernandez Jul 18, 2024
d1c5ec8
fix: changed fw loader functions from file to solve format issues
alexpargon Jul 18, 2024
72555fb
fix: flashing procedure now flashes properly from Bazecor for Raise2
alexpargon Jul 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions src/renderer/components/atoms/icons/IconDocumentWithLines.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React from "react";

interface IconProps {
size?: "md" | "sm";
}

const IconDocumentWithLines = ({ size = "md" }: IconProps) => (
<>
{size === "md" && (
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M19 8L19.6 8C19.6 7.84087 19.5368 7.68826 19.4243 7.57574L19 8ZM14 3L14.4243 2.57574C14.3117 2.46321 14.1591 2.4 14 2.4L14 3ZM14 8L13.4 8L13.4 8.6L14 8.6L14 8ZM19 20L19.6 20L19 20ZM6 21.6L18 21.6L18 20.4L6 20.4L6 21.6ZM4.4 4L4.4 20L5.6 20L5.6 4L4.4 4ZM19.6 20L19.6 8L18.4 8L18.4 20L19.6 20ZM14 2.4L6 2.4L6 3.6L14 3.6L14 2.4ZM19.4243 7.57574L14.4243 2.57574L13.5757 3.42426L18.5757 8.42426L19.4243 7.57574ZM13.4 3L13.4 8L14.6 8L14.6 3L13.4 3ZM14 8.6L19 8.6L19 7.4L14 7.4L14 8.6ZM8 12.6L16 12.6L16 11.4L8 11.4L8 12.6ZM8 16.6L16 16.6L16 15.4L8 15.4L8 16.6ZM18 21.6C18.8837 21.6 19.6 20.8837 19.6 20L18.4 20C18.4 20.2209 18.2209 20.4 18 20.4L18 21.6ZM6 20.4C5.77909 20.4 5.6 20.2209 5.6 20L4.4 20C4.4 20.8837 5.11634 21.6 6 21.6L6 20.4ZM5.6 4C5.6 3.77909 5.77909 3.6 6 3.6L6 2.4C5.11634 2.4 4.4 3.11634 4.4 4L5.6 4Z"
fill="currentColor"
/>
</svg>
)}
{size === "sm" && (
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M12.6667 5.33333L13.0667 5.33333C13.0667 5.22725 13.0245 5.12551 12.9495 5.05049L12.6667 5.33333ZM9.33335 2L9.6162 1.71716C9.54118 1.64214 9.43944 1.6 9.33335 1.6L9.33335 2ZM9.33335 5.33333L8.93335 5.33333L8.93335 5.73333L9.33335 5.73333L9.33335 5.33333ZM12.6667 13.3333L13.0667 13.3333L12.6667 13.3333ZM4.00002 14.4L12 14.4L12 13.6L4.00002 13.6L4.00002 14.4ZM2.93335 2.66667L2.93335 13.3333L3.73335 13.3333L3.73335 2.66667L2.93335 2.66667ZM13.0667 13.3333L13.0667 5.33333L12.2667 5.33333L12.2667 13.3333L13.0667 13.3333ZM9.33335 1.6L4.00002 1.6L4.00002 2.4L9.33335 2.4L9.33335 1.6ZM12.9495 5.05049L9.6162 1.71716L9.05051 2.28284L12.3838 5.61618L12.9495 5.05049ZM8.93335 2L8.93335 5.33333L9.73335 5.33333L9.73335 2L8.93335 2ZM9.33335 5.73333L12.6667 5.73333L12.6667 4.93333L9.33335 4.93333L9.33335 5.73333ZM5.33335 8.4L10.6667 8.4L10.6667 7.6L5.33335 7.6L5.33335 8.4ZM5.33335 11.0667L10.6667 11.0667L10.6667 10.2667L5.33335 10.2667L5.33335 11.0667ZM12 14.4C12.5891 14.4 13.0667 13.9224 13.0667 13.3333L12.2667 13.3333C12.2667 13.4806 12.1473 13.6 12 13.6L12 14.4ZM4.00002 13.6C3.85274 13.6 3.73335 13.4806 3.73335 13.3333L2.93335 13.3333C2.93335 13.9224 3.41092 14.4 4.00002 14.4L4.00002 13.6ZM3.73335 2.66667C3.73335 2.51939 3.85274 2.4 4.00002 2.4L4.00002 1.6C3.41092 1.6 2.93335 2.07756 2.93335 2.66667L3.73335 2.66667Z"
fill="currentColor"
/>
</svg>
)}
</>
);

export default IconDocumentWithLines;
18 changes: 18 additions & 0 deletions src/renderer/components/atoms/icons/IconMemoryUpload.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import React from "react";

const IconMemoryUpload = () => (
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M10 3V6M10 6H7C6.44772 6 6 6.44772 6 7V10M10 6H14M14 3V6M14 6H17C17.5523 6 18 6.44772 18 7V10M21 10H18M18 10V14M21 14H18M18 14V17C18 17.5523 17.5523 18 17 18H14M14 21V18M14 18H10M10 21V18M10 18H7C6.44772 18 6 17.5523 6 17V14M3 14H6M6 14V10M3 10H6"
stroke="currentColor"
strokeWidth="1.2"
/>
<path
d="M12 17.8125L12 10.0625M12 10.0625L8.77084 13.2917M12 10.0625L15.2292 13.2917"
stroke="currentColor"
strokeWidth="1.2"
/>
</svg>
);

export default IconMemoryUpload;
4 changes: 4 additions & 0 deletions src/renderer/components/atoms/icons/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import IconColorPalette from "./IconColorPalette";
import IconColorPicker from "./IconColorPicker";
import IconConnected from "./IconConnected";
import IconDelete from "./IconDelete";
import IconDocumentWithLines from "./IconDocumentWithLines";
import IconDragAndDrop from "./IconDragAndDrop";
import IconDragDots from "./IconDragDots";
import IconEditModeSingleView from "./IconEditModeSingleView";
Expand Down Expand Up @@ -84,6 +85,7 @@ import IconMediaSoundMore from "./IconMediaSoundMore";
import IconMediaSoundMute from "./IconMediaSoundMute";
import IconMediaStop from "./IconMediaStop";
import IconMemory from "./IconMemory";
import IconMemoryUpload from "./IconMemoryUpload";
import IconMoon from "./IconMoon";
import IconMoreVertical from "./IconMoreVertical";
import IconMouse from "./IconMouse";
Expand Down Expand Up @@ -158,6 +160,7 @@ export {
IconColorPicker,
IconConnected,
IconDelete,
IconDocumentWithLines,
IconDragAndDrop,
IconDragDots,
IconEditModeSingleView,
Expand Down Expand Up @@ -202,6 +205,7 @@ export {
IconMediaSoundMute,
IconMediaStop,
IconMemory,
IconMemoryUpload,
IconMoon,
IconMoreVertical,
IconMouse,
Expand Down
6 changes: 4 additions & 2 deletions src/renderer/controller/DeviceChecks/machine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ const DeviceChecks = setup({
},
onError: {
target: "failure",
actions: assign({ error: ({ event }) => event.error }),
actions: [assign({ error: event => event as any })],
},
},
on: {
Expand Down Expand Up @@ -125,6 +125,7 @@ const DeviceChecks = setup({
],
},
onError: "failure",
actions: [assign({ error: event => event as any })],
},
},
RSideCheck: {
Expand Down Expand Up @@ -152,6 +153,7 @@ const DeviceChecks = setup({
],
},
onError: "failure",
actions: [assign({ error: event => event as any })],
},
},
validateStatus: {
Expand Down Expand Up @@ -182,7 +184,7 @@ const DeviceChecks = setup({
},
onError: {
target: "failure",
actions: assign({ error: ({ event }) => event.error }),
actions: [assign({ error: event => event as any })],
},
},
on: {
Expand Down
83 changes: 58 additions & 25 deletions src/renderer/controller/FirmwareSelection/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import { Octokit } from "@octokit/core";
import axios from "axios";
import SemVer from "semver";
import log from "electron-log/renderer";
import { ReleaseType } from "@Renderer/types/releases";
import path from "path";
import fs from "fs";

import { ReleaseType } from "@Renderer/types/releases";
import * as Context from "./context";

const FWMAJORVERSION = "1.x";
Expand Down Expand Up @@ -84,7 +86,7 @@ export const GitHubRead = async (context: Context.ContextType): Promise<Context.
finalReleases = fwReleases.filter(
release =>
release.name === context.device.info.product &&
(context.device.info.product === "Defy"
(context.device.info.product !== "Raise"
? SemVer.satisfies(release.version ? release.version : "", FWMAJORVERSION, { includePrerelease: true })
: true),
);
Expand All @@ -103,8 +105,7 @@ export const GitHubRead = async (context: Context.ContextType): Promise<Context.
isBeta = false;
}
} catch (error) {
log.warn("error when filtering data from GitHub");
log.error(error);
log.warn("error when filtering data from GitHub", error);
throw new Error(error);
}
log.info("GitHub data acquired!", finalReleases);
Expand Down Expand Up @@ -172,39 +173,71 @@ const obtainFWFiles = async (type: string, url: string) => {
return firmware;
};

const obtainLocalFWFiles = (customFWPath: string) => {
const fromHexString = (hexString: any) => Uint8Array.from(hexString.match(/.{1,2}/g).map((byte: string) => parseInt(byte, 16)));

let result;
if (customFWPath.includes(".hex")) {
let fileData = fs.readFileSync(customFWPath, { encoding: "utf8" });
fileData = fileData.replace(/(?:\r\n|\r|\n)/g, "");
const lines = fileData.split(":");
lines.splice(0, 1);
result = lines;
}
if (customFWPath.includes(".bin")) {
const filedata = fs.readFileSync(customFWPath, { encoding: "hex" });
result = fromHexString(filedata);
}
if (customFWPath.includes(".uf2")) {
result = fs.readFileSync(customFWPath, { encoding: "binary" });
}
return result;
};

export const downloadFirmware = async (
typeSelected: string,
info: { product: string; keyboardType: string },
firmwareList: ReleaseType[],
selectedFirmware: number,
customFirmwareFolder: string,
) => {
let filename: Array<string>;
let filenameSides: Uint8Array;
log.info("Data to download FW: ", typeSelected, info, firmwareList, selectedFirmware);
try {
if (typeSelected === "default") {
if (info.product === "Raise") {
filename = (await obtainFWFiles(
"firmware.hex",
firmwareList[selectedFirmware].assets.find((asset: { name: string }) => asset.name === "firmware.hex").url,
)) as Array<string>;
if (info.product === "Raise") {
filename =
typeSelected === "default"
? ((await obtainFWFiles(
"firmware.hex",
firmwareList[selectedFirmware].assets.find((asset: { name: string }) => asset.name === "firmware.hex").url,
)) as Array<string>)
: (obtainLocalFWFiles(path.join(customFirmwareFolder, "firmware.hex")) as Array<string>);
} else {
if (info.keyboardType === "wireless" || info.product === "Raise2") {
filename =
typeSelected === "default"
? ((await obtainFWFiles(
"Wireless_neuron.hex",
firmwareList[selectedFirmware].assets.find((asset: { name: string }) => asset.name === "Wireless_neuron.hex").url,
)) as Array<string>)
: (obtainLocalFWFiles(path.join(customFirmwareFolder, "Wireless_neuron.hex")) as Array<string>);
} else {
if (info.keyboardType === "wireless") {
filename = (await obtainFWFiles(
"Wireless_neuron.hex",
firmwareList[selectedFirmware].assets.find((asset: { name: string }) => asset.name === "Wireless_neuron.hex").url,
)) as Array<string>;
} else {
filename = (await obtainFWFiles(
"Wired_neuron.uf2",
firmwareList[selectedFirmware].assets.find((asset: { name: string }) => asset.name === "Wired_neuron.uf2").url,
)) as Array<string>;
}
filenameSides = (await obtainFWFiles(
"keyscanner.bin",
firmwareList[selectedFirmware].assets.find((asset: { name: string }) => asset.name === "keyscanner.bin").url,
)) as Uint8Array;
filename =
typeSelected === "default"
? ((await obtainFWFiles(
"Wired_neuron.uf2",
firmwareList[selectedFirmware].assets.find((asset: { name: string }) => asset.name === "Wired_neuron.uf2").url,
)) as Array<string>)
: (obtainLocalFWFiles(path.join(customFirmwareFolder, "Wired_neuron.uf2")) as Array<string>);
}
filenameSides =
typeSelected === "default"
? ((await obtainFWFiles(
"keyscanner.bin",
firmwareList[selectedFirmware].assets.find((asset: { name: string }) => asset.name === "keyscanner.bin").url,
)) as Uint8Array)
: new Uint8Array(obtainLocalFWFiles(path.join(customFirmwareFolder, "keyscanner.bin")) as any);
}
} catch (error) {
log.warn("error when asking for FW files");
Expand Down
5 changes: 4 additions & 1 deletion src/renderer/controller/FirmwareSelection/context.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ReleaseType } from "@Renderer/types/releases";
import { State } from "src/api/comms/Device";
import { ErrorActorEvent } from "xstate";

export interface ContextType {
stateblock: number;
Expand All @@ -21,11 +22,12 @@ export interface ContextType {
};
typeSelected: string;
selectedFirmware: number;
customFirmwareFolder: string;
isUpdated: boolean;
isBeta: boolean;
allowBeta: boolean;
deviceState: State | undefined;
error: unknown;
error: ErrorActorEvent;
}

export const Context: ContextType = {
Expand All @@ -47,6 +49,7 @@ export const Context: ContextType = {
fwSides: undefined,
},
typeSelected: "default",
customFirmwareFolder: undefined,
selectedFirmware: 0,
isUpdated: false,
isBeta: false,
Expand Down
7 changes: 6 additions & 1 deletion src/renderer/controller/FirmwareSelection/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,9 @@ export interface CHANGEFW {
readonly selected: number;
}

export type Events = AutoInit | NEXT | RETRY | CHANGEFW;
export interface CUSTOMFW {
readonly type: "customFW-event";
readonly selected: string;
}

export type Events = AutoInit | NEXT | RETRY | CHANGEFW | CUSTOMFW;
1 change: 1 addition & 0 deletions src/renderer/controller/FirmwareSelection/input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export const Input = async (input: InputType): Promise<Context.ContextType> => {
isUpdated: false,
isBeta: false,
typeSelected: "default",
customFirmwareFolder: undefined,
selectedFirmware: 0,
allowBeta: input.allowBeta,
};
Expand Down
29 changes: 24 additions & 5 deletions src/renderer/controller/FirmwareSelection/machine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,13 @@ const FirmwareSelection = setup({
FocusAPIRead: fromPromise<Context.ContextType, Context.ContextType>(({ input }) => Actions.FocusAPIRead(input)),
GitHubRead: fromPromise<Context.ContextType, Context.ContextType>(({ input }) => Actions.GitHubRead(input)),
downloadFirmware: fromPromise<{ fw: Array<string>; fwSides: Uint8Array }, Context.ContextType>(({ input }) =>
Actions.downloadFirmware(input.typeSelected, input.device.info, input.firmwareList, input.selectedFirmware),
Actions.downloadFirmware(
input.typeSelected,
input.device.info,
input.firmwareList,
input.selectedFirmware,
input.customFirmwareFolder,
),
),
},
actions: {
Expand Down Expand Up @@ -76,7 +82,7 @@ const FirmwareSelection = setup({
() => {
log.warn("error");
},
assign({ error: (_context, event) => event }),
assign({ error: event => event as any }),
],
},
},
Expand Down Expand Up @@ -106,7 +112,7 @@ const FirmwareSelection = setup({
},
onError: {
target: "failure",
actions: assign({ error: (context, event) => event }),
actions: [assign({ error: event => event as any })],
},
},
},
Expand All @@ -123,7 +129,20 @@ const FirmwareSelection = setup({
on: {
"next-event": ["loadingFWFiles"],
"changeFW-event": {
actions: [assign({ selectedFirmware: ({ event }) => event.selected })],
actions: [
assign(({ event }) => ({
selectedFirmware: event.selected,
typeSelected: "default",
})),
],
},
"customFW-event": {
actions: [
assign(({ event }) => ({
customFirmwareFolder: event.selected,
typeSelected: "custom",
})),
],
},
},
},
Expand All @@ -146,7 +165,7 @@ const FirmwareSelection = setup({
},
onError: {
target: "failure",
actions: [assign({ error: event => event })],
actions: [assign({ error: event => event as any })],
},
},
},
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/controller/FlashManager/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export interface ContextType {
Block: number;
deviceState: State | undefined;
backup?: any;
error: unknown;
error: any;
firmwareList: ReleaseType[];
firmwares: any;
device: any;
Expand Down
4 changes: 3 additions & 1 deletion src/renderer/controller/FlashManager/machine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,13 +140,15 @@ const FlashManager = setup({
},
error: {
id: "error",
type: "final",
entry: [
() => {
log.info("Error Card entry");
},
assign({ Block: () => -1 }),
],
on: {
"retry-event": ["retry"],
},
},
success: { type: "final" },
},
Expand Down
Loading
Loading