@@ -437,6 +437,24 @@ <h3 id="import-preview-title">Import preview</h3>
437437 const commandsSection = document . getElementById ( 'commands-section' ) ;
438438 commandsSection . innerHTML = '' ;
439439
440+ function getKnownPortOptions ( ) {
441+ const options = [ { label : 'all ports' , value : 0 } ] ;
442+ const ports = settingsData && settingsData . ports ? settingsData . ports : null ;
443+ if ( ports ) {
444+ Object . entries ( ports )
445+ . filter ( ( [ _ , portNum ] ) => Number . isFinite ( portNum ) )
446+ . map ( ( [ portName , portNum ] ) => ( {
447+ label : portName . replace ( / ^ p o r t _ / , '' ) ,
448+ value : portNum
449+ } ) )
450+ . sort ( ( a , b ) => a . value - b . value )
451+ . forEach ( option => options . push ( option ) ) ;
452+ }
453+ return options
454+ . map ( option => `<option value="${ option . value } ">${ option . label } (port ${ option . value } )</option>` )
455+ . join ( '' ) ;
456+ }
457+
440458 for ( const [ key , command ] of Object . entries ( settingsData . commands ) ) {
441459 if ( dangerousCommands . some ( rx => rx . test ( key ) ) ) {
442460 continue ;
@@ -468,6 +486,32 @@ <h3 id="import-preview-title">Import preview</h3>
468486 ${ settingOptions . map ( option => `<option value="${ option . id } ">${ option . name } (${ option . id } )</option>` ) . join ( '' ) }
469487 </select>
470488 ` ;
489+ } else if ( key === 'cmd_flash_get_from_head' ) {
490+ helperHtml = `
491+ <label class="command-helper-label" for="command-select-${ command . id } -port">Port</label>
492+ <select id="command-select-${ command . id } -port" class="command-helper-input">
493+ ${ getKnownPortOptions ( ) }
494+ </select>
495+ <label class="command-helper-label" for="command-input-${ command . id } -start">Start</label>
496+ <input id="command-input-${ command . id } -start" class="command-helper-input" type="text" placeholder="50" data-format="uint32" />
497+ <label class="command-helper-label" for="command-input-${ command . id } -count">How many</label>
498+ <input id="command-input-${ command . id } -count" class="command-helper-input" type="text" placeholder="10" data-format="uint32" />
499+ ` ;
500+ } else if ( commandInputMeta && commandInputMeta . options ) {
501+ helperHtml = `
502+ <label class="command-helper-label" for="command-select-${ command . id } ">Value</label>
503+ <select id="command-select-${ command . id } " class="command-helper-input">
504+ ${ commandInputMeta . options . map ( option => `<option value="${ option . value } ">${ option . label } </option>` ) . join ( '' ) }
505+ </select>
506+ ` ;
507+ } else if ( commandInputMeta && commandInputMeta . input ) {
508+ const placeholder = commandInputMeta . input . placeholder || '' ;
509+ const labelText = commandInputMeta . input . label || 'Value' ;
510+ const dataFormat = commandInputMeta . input . format || 'uint8' ;
511+ helperHtml = `
512+ <label class="command-helper-label" for="command-input-${ command . id } ">${ labelText } </label>
513+ <input id="command-input-${ command . id } " class="command-helper-input" type="text" placeholder="${ placeholder } " data-format="${ dataFormat } " />
514+ ` ;
471515 }
472516 row . innerHTML = `
473517 <div class="checkbox-container">
@@ -610,13 +654,61 @@ <h3 id="import-preview-title">Import preview</h3>
610654 try {
611655 if ( settingObj . type === 'command' && settingObj . length === 1 ) {
612656 const selectEl = document . getElementById ( `command-select-${ settingObj . id } ` ) ;
657+ const inputEl = document . getElementById ( `command-input-${ settingObj . id } ` ) ;
658+ let value = 0 ;
613659 if ( selectEl ) {
614660 const selected = selectEl . value ;
615- const parsed = selected && selected . startsWith ( '0x' ) ? parseInt ( selected , 16 ) : parseInt ( selected , 10 ) ;
616- valueBytes = settingToBytes ( settingKey , settingObj , parsed . toString ( ) ) ;
617- } else {
618- valueBytes = settingToBytes ( settingKey , settingObj , getInputValue ( settingObj . id ) ) ;
661+ value = selected && selected . startsWith ( '0x' ) ? parseInt ( selected , 16 ) : parseInt ( selected , 10 ) ;
662+ } else if ( inputEl ) {
663+ const rawValue = inputEl . value . trim ( ) ;
664+ const format = inputEl . getAttribute ( 'data-format' ) || 'uint8' ;
665+ if ( rawValue . length === 0 ) {
666+ value = 0 ;
667+ } else if ( format === 'hex8' ) {
668+ const cleaned = rawValue . replace ( / ^ 0 x / i, '' ) ;
669+ const parsed = parseInt ( cleaned , 16 ) ;
670+ if ( Number . isNaN ( parsed ) ) {
671+ throw new Error ( 'Invalid hex value' ) ;
672+ }
673+ value = parsed ;
674+ } else {
675+ const parsed = parseInt ( rawValue , 10 ) ;
676+ if ( Number . isNaN ( parsed ) ) {
677+ throw new Error ( 'Invalid numeric value' ) ;
678+ }
679+ value = parsed ;
680+ }
681+ } else if ( settingObj . value !== undefined ) {
682+ value = settingObj . value ;
619683 }
684+ valueBytes = settingToBytes ( settingKey , settingObj , value . toString ( ) ) ;
685+ } else if ( settingObj . type === 'command' && settingKey === 'cmd_flash_get_from_head' ) {
686+ const portEl = document . getElementById ( `command-select-${ settingObj . id } -port` ) ;
687+ const startEl = document . getElementById ( `command-input-${ settingObj . id } -start` ) ;
688+ const countEl = document . getElementById ( `command-input-${ settingObj . id } -count` ) ;
689+ const parseUint32 = ( el , label ) => {
690+ if ( ! el ) {
691+ return 0 ;
692+ }
693+ const rawValue = el . value . trim ( ) ;
694+ if ( ! rawValue ) {
695+ return 0 ;
696+ }
697+ const parsed = rawValue . startsWith ( '0x' ) ? parseInt ( rawValue , 16 ) : parseInt ( rawValue , 10 ) ;
698+ if ( ! Number . isFinite ( parsed ) || parsed < 0 || parsed > 0xFFFFFFFF ) {
699+ throw new Error ( `Invalid ${ label } (uint32)` ) ;
700+ }
701+ return parsed >>> 0 ;
702+ } ;
703+ const port = parseUint32 ( portEl , 'port' ) ;
704+ const start = parseUint32 ( startEl , 'start index' ) ;
705+ const count = parseUint32 ( countEl , 'count' ) ;
706+ const payload = new Uint8Array ( 12 ) ;
707+ const view = new DataView ( payload . buffer ) ;
708+ view . setUint32 ( 0 , port , true ) ;
709+ view . setUint32 ( 4 , start , true ) ;
710+ view . setUint32 ( 8 , count , true ) ;
711+ valueBytes = payload ;
620712 } else {
621713 valueBytes = settingToBytes ( settingKey , settingObj , getInputValue ( settingObj . id ) ) ;
622714 }
0 commit comments