import { debug } from 'debug' ; import { pack } from 'byte-data' ; import { Peripheral } from './peripheral' ; import { Commands , MemoryIds , Properties , ResponseCodes , ResponseTags } from './enums' ; import { BootloaderVersion , CommandOption , CommandResponse , DataOption } from './models' ; const logger = debug ( 'kboot' ) ; const RESET_IGNORED_ERRORS = [ 'could not read data from device' , 'could not read from HID device' , 'Cannot write to HID device' , 'Cannot write to hid device' ] ; export class KBoot { constructor ( private peripheral ) { } open ( ) { logger ( 'Open peripheral' ) ; this . peripheral . open ( ) ; } close ( ) { logger ( 'Close peripheral' ) ; this . peripheral . close ( ) ; } async getProperty ( property , memoryId = MemoryIds . Internal ) { logger ( 'Start read memory %o' , { property , memoryId } ) ; const command = { command : Commands . GetProperty , params : [ ... pack ( property , { bits : 32 } ) , ... pack ( memoryId , { bits : 32 } ) ] } ; const response = await this . peripheral . sendCommand ( command ) ; if ( response . tag !== ResponseTags . Property ) { logger ( 'Response tag is not property response: %d' , property ) ; throw new Error ( 'Response tag is not property response' ) ; } if ( response . code === ResponseCodes . UnknownProperty ) { logger ( 'Unknown property %d' , response . code ) ; throw new Error ( 'Unknown property!' ) ; } if ( response . code !== ResponseCodes . Success ) { logger ( 'Unknown error %d' , response . code ) ; throw new Error ( `Unknown error. Error code:${ response . code }` ) ; } return response ; } async getBootloaderVersion ( ) { logger ( 'Start to read Bootloader Version' ) ; const response = await this . getProperty ( Properties . BootloaderVersion ) ; const version = { bugfix : response . raw [ 12 ] , minor : response . raw [ 13 ] , major : response . raw [ 14 ] , protocolName : String . fromCharCode ( response . raw [ 15 ] ) } ; logger ( 'bootloader version %o' ) ; return version ; } async flashSecurityDisable ( key ) { logger ( 'Start flash security disable %o' , { key } ) ; if ( key . length !== 8 ) { logger ( 'Error: Flash security key must be 8 byte. %o' , key ) ; throw new Error ( 'Flash security key must be 8 byte' ) ; } const command = { command : Commands . FlashSecurityDisable , params : [ ... key ] } ; const response = await this . peripheral . sendCommand ( command ) ; if ( response . tag !== ResponseTags . Generic ) { logger ( 'Response tag is not generic response: %d' , response . tag ) ; throw new Error ( 'Response tag is not generic response' ) ; } if ( response . code !== ResponseCodes . Success ) { logger ( 'Can not disable flash security: %d' , response . code ) ; throw new Error ( `Can not disable flash security` ) ; } } async flashEraseRegion ( startAddress , count ) { logger ( 'Start flash erase region' ) ; const command = { command : Commands . FlashEraseRegion , params : [ ... pack ( startAddress , { bits : 32 } ) , ... pack ( count , { bits : 32 } ) ] } ; const response = await this . peripheral . sendCommand ( command ) ; if ( response . tag !== ResponseTags . Generic ) { logger ( 'Response tag is not generic response: %d' , response . tag ) ; throw new Error ( 'Response tag is not generic response' ) ; } if ( response . code !== ResponseCodes . Success ) { logger ( 'Can not flash erase region: %d' , response . code ) ; throw new Error ( `Can not flash erase region` ) ; } } async flashEraseAllUnsecure ( ) { logger ( 'Start flash erase all unsecure' ) ; const command = { command : Commands . FlashEraseAllUnsecure , params : [ ] } ; const response = await this . peripheral . sendCommand ( command ) ; if ( response . tag !== ResponseTags . Generic ) { logger ( 'Response tag is not generic response: %d' , response . tag ) ; throw new Error ( 'Response tag is not generic response' ) ; } if ( response . code !== ResponseCodes . Success ) { logger ( 'Can not flash erase all unsecure: %d' , response . code ) ; throw new Error ( `Can not flash erase all unsecure` ) ; } } async readMemory ( startAddress , count ) { logger ( 'Start read memory %o' , { startAddress , count } ) ; return this . peripheral . readMemory ( startAddress , count ) ; } async writeMemory ( options ) { logger ( 'Start write memory %o' , { options } ) ; return this . peripheral . writeMemory ( options ) ; } /**
     * Reset the bootloader
     */ async reset ( ) { logger ( 'Start reset the bootloader' ) ; const command = { command : Commands . Reset , params : [ ] } ; let response ; try { response = await this . peripheral . sendCommand ( command ) ; } catch ( error ) { logger ( `Reset command error message: "${ error . message }"` ) ; if ( RESET_IGNORED_ERRORS . includes ( error . message ) ) { logger ( 'Ignoring missing response from reset command.' ) ; this . close ( ) ; return ; } throw error ; } if ( response . tag !== ResponseTags . Generic ) { logger ( 'Response tag is not generic response: %d' , response . tag ) ; throw new Error ( 'Response tag is not generic response' ) ; } if ( response . code !== ResponseCodes . Success ) { logger ( 'Unknown error %d' , response . code ) ; throw new Error ( `Unknown error. Error code:${ response . code }` ) ; } } param address param speed async configureI2c ( address , speed = 64 ) { logger ( 'Start configure I2C' , { address , speed } ) ; if ( address > 127 ) { logger ( 'Only 7-bit i2c address is supported' ) ; throw new Error ( 'Only 7-bit i2c address is supported' ) ; } const command = { command : Commands . ConfigureI2c , params : [ ... pack ( address , { bits : 32 } ) , ... pack ( speed , { bits : 32 } ) ] } ; const response = await this . peripheral . sendCommand ( command ) ; if ( response . tag !== ResponseTags . Generic ) { logger ( 'Response tag is not generic response: %d' , response . tag ) ; throw new Error ( 'Response tag is not generic response' ) ; } if ( response . code !== ResponseCodes . Success ) { logger ( 'Unknown error %d' , response . code ) ; throw new Error ( `Unknown error. Error code:${ response . code }` ) ; } } }