@ledgerhq/live-common
Version:
Common ground for the Ledger Live apps
122 lines (109 loc) • 3.27 kB
text/typescript
/* eslint-disable no-bitwise */
import { DeviceOnDashboardExpected, TransportStatusError } from "@ledgerhq/errors";
import { LocalTracer, log } from "@ledgerhq/logs";
import Transport from "@ledgerhq/hw-transport";
import { getVersion } from "../device/use-cases/getVersionUseCase";
import isDevFirmware from "./isDevFirmware";
import getAppAndVersion from "./getAppAndVersion";
import { PROVIDERS } from "../manager/provider";
import { isDashboardName } from "./isDashboardName";
import { DeviceNotOnboarded } from "../errors";
import type { DeviceInfo } from "@ledgerhq/types-live";
const ManagerAllowedFlag = 0x08;
const PinValidatedFlag = 0x80;
export default async function (transport: Transport): Promise<DeviceInfo> {
const tracer = new LocalTracer("hw", {
...transport.getTraceContext(),
function: "getDeviceInfo",
});
tracer.trace("Starting get device info");
const probablyOnDashboard = await getAppAndVersion(transport)
.then(({ name }) => isDashboardName(name))
.catch(e => {
tracer.trace(`Error from getAppAndVersion: ${e}`, { error: e });
if (e instanceof TransportStatusError) {
if (e.statusCode === 0x6e00 || e.statusCode === 0x6e01) {
return true;
}
if (e.statusCode === 0x6d00) {
return false;
}
}
throw e;
});
if (!probablyOnDashboard) {
tracer.trace(`Device not on dashboard`);
throw new DeviceOnDashboardExpected();
}
const res = await getVersion(transport).catch(e => {
tracer.trace(`Error from getVersion: ${e}`, { error: e });
if (e instanceof TransportStatusError) {
if (e.statusCode === 0x6d06 || e.statusCode === 0x6d07) {
throw new DeviceNotOnboarded();
}
}
throw e;
});
const {
isBootloader,
rawVersion,
targetId,
seVersion,
seTargetId,
mcuBlVersion,
mcuVersion,
mcuTargetId,
bootloaderVersion,
hardwareVersion,
languageId,
charonState,
flags,
} = res;
const isOSU = rawVersion.includes("-osu");
const version = rawVersion.replace("-osu", "");
const m = rawVersion.match(/([0-9]+.[0-9]+(.[0-9]+){0,1})?(-(.*))?/);
const [, majMin, , , postDash] = m || [];
const providerName = PROVIDERS[postDash] ? postDash : null;
const flag = flags.length > 0 ? flags[0] : 0;
const managerAllowed = !!(flag & ManagerAllowedFlag);
const pinValidated = !!(flag & PinValidatedFlag);
let isRecoveryMode = false;
let onboarded = true;
if (flags.length === 4) {
// Nb Since LNS+ unseeded devices are visible + extra flags
isRecoveryMode = !!(flags[0] & 0x01);
onboarded = !!(flags[0] & 0x04);
}
log(
"hw",
"deviceInfo: se@" +
version +
" mcu@" +
mcuVersion +
(isOSU ? " (osu)" : isBootloader ? " (bootloader)" : ""),
);
const hasDevFirmware = isDevFirmware(seVersion);
return {
version,
mcuVersion,
seVersion,
mcuBlVersion,
majMin,
providerName: providerName || null,
targetId,
hasDevFirmware,
seTargetId,
mcuTargetId,
isOSU,
isBootloader,
isRecoveryMode,
managerAllowed,
pinValidated,
onboarded,
bootloaderVersion,
hardwareVersion,
languageId,
charonState,
seFlags: flags,
};
}