diff --git a/src/commands/getDeviceInfo.js b/src/commands/getDeviceInfo.js index 767f27f9..67c585fd 100644 --- a/src/commands/getDeviceInfo.js +++ b/src/commands/getDeviceInfo.js @@ -5,19 +5,13 @@ import { fromPromise } from 'rxjs/observable/fromPromise' import { withDevice } from 'helpers/deviceAccess' import getDeviceInfo from 'helpers/devices/getDeviceInfo' +import type { DeviceInfo } from 'helpers/devices/getDeviceInfo' type Input = { devicePath: string, } -type Result = { - targetId: number | string, - version: string, - final: boolean, - mcu: boolean, -} - -const cmd: Command = createCommand('getDeviceInfo', ({ devicePath }) => +const cmd: Command = createCommand('getDeviceInfo', ({ devicePath }) => fromPromise(withDevice(devicePath)(transport => getDeviceInfo(transport))), ) diff --git a/src/components/ManagerPage/FlashMcu.js b/src/components/ManagerPage/FlashMcu.js index 5edeacd4..0cb9905d 100644 --- a/src/components/ManagerPage/FlashMcu.js +++ b/src/components/ManagerPage/FlashMcu.js @@ -4,12 +4,7 @@ import React, { PureComponent } from 'react' import type { Device } from 'types/common' import installMcu from 'commands/installMcu' -type DeviceInfo = { - targetId: number | string, - version: string, - final: boolean, - mcu: boolean, -} +import type { DeviceInfo } from 'helpers/devices/getDeviceInfo' type Props = { device: Device, @@ -35,7 +30,7 @@ class FlashMcu extends PureComponent { .send({ devicePath: device.path, targetId: deviceInfo.targetId, - version: deviceInfo.version, + version: deviceInfo.seVersion, }) .toPromise() this.setState({ flashing: false }) diff --git a/src/components/ManagerPage/index.js b/src/components/ManagerPage/index.js index d7399013..49a7312b 100644 --- a/src/components/ManagerPage/index.js +++ b/src/components/ManagerPage/index.js @@ -4,19 +4,13 @@ import React, { PureComponent } from 'react' import type { Device } from 'types/common' +import type { DeviceInfo } from 'helpers/devices/getDeviceInfo' import Workflow from 'components/Workflow' import WorkflowWithIcon from 'components/Workflow/WorkflowWithIcon' import Dashboard from './Dashboard' import FlashMcu from './FlashMcu' -type DeviceInfo = { - targetId: number | string, - version: string, - final: boolean, - mcu: boolean, -} - type Error = { message: string, stack: string, @@ -27,7 +21,7 @@ class ManagerPage extends PureComponent<*, *> { return ( ( -

UPDATE FINAL FIRMARE (TEMPLATE + ACTION WIP) {deviceInfo.final}

+

UPDATE FINAL FIRMARE (TEMPLATE + ACTION WIP) {deviceInfo.isOSU}

)} renderMcuUpdate={(device: Device, deviceInfo: DeviceInfo) => ( diff --git a/src/components/Workflow/EnsureDashboard.js b/src/components/Workflow/EnsureDashboard.js index e7b86416..bc762558 100644 --- a/src/components/Workflow/EnsureDashboard.js +++ b/src/components/Workflow/EnsureDashboard.js @@ -7,12 +7,7 @@ import type { Device } from 'types/common' import getDeviceInfo from 'commands/getDeviceInfo' -type DeviceInfo = { - targetId: number | string, - version: string, - final: boolean, - mcu: boolean, -} +import type { DeviceInfo } from 'helpers/devices/getDeviceInfo' type Error = { message: string, diff --git a/src/components/Workflow/EnsureGenuine.js b/src/components/Workflow/EnsureGenuine.js index a1890480..2ebc5729 100644 --- a/src/components/Workflow/EnsureGenuine.js +++ b/src/components/Workflow/EnsureGenuine.js @@ -15,7 +15,8 @@ type Error = { type DeviceInfos = { targetId: number | string, - version: string, + seVersion: string, + providerName: string, } type Props = { @@ -60,8 +61,15 @@ class EnsureGenuine extends PureComponent { if (device && infos && !this._checking) { this._checking = true try { + const versionName = `${infos.seVersion}${ + infos.providerName ? `-${infos.providerName}` : '' + }` const res = await getIsGenuine - .send({ devicePath: device.path, targetId: infos.targetId, version: infos.version }) + .send({ + devicePath: device.path, + targetId: infos.targetId, + version: versionName, + }) .pipe(timeout(GENUINE_TIMEOUT)) .toPromise() if (this._unmounting) return diff --git a/src/components/Workflow/index.js b/src/components/Workflow/index.js index e3db974f..7c778f63 100644 --- a/src/components/Workflow/index.js +++ b/src/components/Workflow/index.js @@ -1,6 +1,7 @@ // @flow import React, { PureComponent } from 'react' +import type { DeviceInfo } from 'helpers/devices/getDeviceInfo' import type { Node } from 'react' import type { Device } from 'types/common' @@ -9,13 +10,6 @@ import EnsureDevice from './EnsureDevice' import EnsureDashboard from './EnsureDashboard' import EnsureGenuine from './EnsureGenuine' -type DeviceInfo = { - targetId: number | string, - version: string, - final: boolean, - mcu: boolean, -} - type Error = { message: string, stack: string, @@ -55,11 +49,11 @@ class Workflow extends PureComponent { {(device: Device) => ( {(deviceInfo: ?DeviceInfo, dashboardError: ?Error) => { - if (deviceInfo && deviceInfo.mcu && renderMcuUpdate) { + if (deviceInfo && deviceInfo.isBootloader && renderMcuUpdate) { return renderMcuUpdate(device, deviceInfo) } - if (deviceInfo && deviceInfo.final && renderFinalUpdate) { + if (deviceInfo && deviceInfo.isOSU && renderFinalUpdate) { return renderFinalUpdate(device, deviceInfo) } diff --git a/src/helpers/common.js b/src/helpers/common.js index 3d5a9c30..a8e4bb13 100644 --- a/src/helpers/common.js +++ b/src/helpers/common.js @@ -32,9 +32,20 @@ export async function getFirmwareInfo(transport: Transport<*>) { const data = byteArray.slice(0, byteArray.length - 2) const targetIdStr = Buffer.from(data.slice(0, 4)) const targetId = targetIdStr.readUIntBE(0, 4) - const versionLength = data[4] - const version = Buffer.from(data.slice(5, 5 + versionLength)).toString() - return { targetId, version } + const seVersionLength = data[4] + const seVersion = Buffer.from(data.slice(5, 5 + seVersionLength)).toString() + const flagsLength = data[5 + seVersionLength] + const flags = Buffer.from( + data.slice(5 + seVersionLength + 1, 5 + seVersionLength + 1 + flagsLength), + ).toString() + const mcuVersionLength = data[5 + seVersionLength + 1 + flagsLength] + const mcuVersion = Buffer.from( + data.slice( + 7 + seVersionLength + flagsLength, + 7 + seVersionLength + flagsLength + mcuVersionLength, + ), + ).toString() + return { targetId, seVersion, flags, mcuVersion } } catch (err) { const error = new Error(err.message) error.stack = err.stack diff --git a/src/helpers/devices/getDeviceInfo.js b/src/helpers/devices/getDeviceInfo.js index 06a1e2be..34bf6fe6 100644 --- a/src/helpers/devices/getDeviceInfo.js +++ b/src/helpers/devices/getDeviceInfo.js @@ -4,23 +4,193 @@ import type Transport from '@ledgerhq/hw-transport' import { getFirmwareInfo } from 'helpers/common' -type Result = { +export type DeviceInfo = { targetId: string | number, - version: string, - mcu: boolean, - final: boolean, + seVersion: string, + isBootloader: boolean, + flags: string, + mcuVersion: string, + isOSU: boolean, + providerName: string, } -export default async (transport: Transport<*>): Promise => { - try { - const { targetId, version } = await getFirmwareInfo(transport) - const finalReady = version.endsWith('-osu') - const mcuReady = targetId === 0x01000001 +const DETECT_CLUBCOIN = [ + [0xe0, 0x04, 0x00, 0x00, 0x04, 0x31, 0x10, 0x00, 0x02], + [0xe0, 0x50, 0x00, 0x00, 0x08, 0xe4, 0x6c, 0x4c, 0x71, 0x8b, 0xc8, 0x7f, 0xb7], + [ + 0xe0, + 0x51, + 0x80, + 0x00, + 0x8a, + 0x41, + 0x04, + 0xc9, + 0x8c, + 0xa0, + 0x99, + 0x53, + 0x47, + 0x2b, + 0x36, + 0x06, + 0x1e, + 0x0e, + 0x40, + 0xc9, + 0x3d, + 0x50, + 0x52, + 0x34, + 0x09, + 0x0e, + 0xfd, + 0x74, + 0xf1, + 0xd7, + 0xa2, + 0x93, + 0xe8, + 0x28, + 0x15, + 0x9a, + 0x97, + 0x71, + 0x1b, + 0x33, + 0xd1, + 0x8a, + 0xfc, + 0x17, + 0xad, + 0x15, + 0x6e, + 0xae, + 0xd9, + 0x9c, + 0xf4, + 0x3b, + 0x20, + 0xe1, + 0x5d, + 0x64, + 0xaf, + 0x39, + 0xa5, + 0x51, + 0x3b, + 0x4e, + 0x3c, + 0x5f, + 0x43, + 0x17, + 0xe6, + 0x42, + 0x70, + 0x2f, + 0x05, + 0x47, + 0x30, + 0x45, + 0x02, + 0x21, + 0x00, + 0xf1, + 0xd2, + 0xb8, + 0x34, + 0x99, + 0x4a, + 0x0c, + 0x1f, + 0x25, + 0xea, + 0x20, + 0xcf, + 0x33, + 0xe3, + 0x2b, + 0xd0, + 0x6b, + 0xcf, + 0x7c, + 0x42, + 0x4a, + 0x02, + 0xee, + 0xe8, + 0xf6, + 0x96, + 0x99, + 0x20, + 0xe1, + 0xe8, + 0xc2, + 0xb3, + 0x02, + 0x20, + 0x63, + 0x2d, + 0x19, + 0xbd, + 0x30, + 0xab, + 0x20, + 0x76, + 0x18, + 0x78, + 0x78, + 0xae, + 0xaa, + 0x0f, + 0x4d, + 0x48, + 0x04, + 0x01, + 0x32, + 0x79, + 0xd0, + 0x16, + 0xde, + 0xca, + 0x66, + 0x93, + 0xf3, + 0x7b, + 0x4e, + 0x50, + 0x7f, + 0x43, + ], +] - return { targetId, version, final: finalReady, mcu: mcuReady } - } catch (err) { - const error = Error(err.message) - error.stack = err.stack - throw error +export default async (transport: Transport<*>): Promise => { + const res = await getFirmwareInfo(transport) + let { seVersion } = res + const { targetId, mcuVersion, flags } = res + if (seVersion === '1.2') { + try { + DETECT_CLUBCOIN.forEach(async apdus => { + await transport.send(...apdus) + }) + seVersion = '1.2.0-club' + } catch (e) { + seVersion = '1.2.0' + } + } + const parsedVersion = seVersion.match(/[0-9]+.[0-9]+(.[0-9]+)?(-[a-z]+)?(-osu)?/) || [] + const isOSU = typeof parsedVersion[5] !== 'undefined' + const providerName = parsedVersion[4] || '' + const isBootloader = targetId === 0x01000001 + const majMin = parsedVersion[1] + const patch = parsedVersion[2] || '.0' + return { + targetId, + seVersion: majMin + patch, + isOSU, + mcuVersion, + isBootloader, + providerName, + flags, } }