/* Demo Hidprobe Script Applications bl, version 0.4, 29 November 2008, Psuedo polling of an event notiifer that puts thread to sleep Customisable bootloader script for embedded devices using Hidprobe, http://www.zgus.com/hid. Code uploaded may be secure firmware. This script does not need to know Rename file from bl_js.txt to bl.js for ease of editing and ease of loading to Hidprobe. For the file to be passed through to an embedded device, all lines must be in multiples of 16 characters Please see zgus_hidprobe_manual.pdf for general usage of scripting with Hidprobe (http://www.zgus.com/hid) Author: John Heenan, Auscyber Pty Ltd Copyright 2008 Auscyber Pty Ltd. All rights reserved. ZGUS is a trading name of Auscyber Pty Ltd No Warranty: No warranty of any kind, such as no warranty of fitness for any purpose, including no warranty of fitness for merchantability. No Liability: Auscyber Pty Ltd shall not be liable for any damage or harm the software may cause by its use, whether from faults or not, - including direct, indirect, incidental, consequential, loss of business profits or special damages Should you have any questions regarding your right to use this Software, contact Auscyber Pty Ltd T/A ZGUS at www.zgus.com. */ var file_log="bl_log.txt"; var file_secure="zgus_fw_secure.txt"; var TIMEOUT_INFINITE =-1; var HIDSCRIPT_EVENT_SHUTDOWN =0x00; var HIDSCRIPT_EVENT_TIMEOUT =0x01; var HIDSCRIPT_EVENT_TIMER =0x02; var HIDSCRIPT_EVENT_GETREPORT =0x03; var HIDSCRIPT_EVENT_SIGNAL =0x04; var HIDSCRIPT_EVENT_TIMEOUT_OUTOFRANGE =0x0800; var HIDSCRIPT_EVENT_WAITING =0x0801; //only applicable if a script makes a multithreaded call var HIDSCRIPT_EVENT_ERROR =0x0802; var priorBAUD=0; var fso, tf_log, tf_secure; var er=null; if(host_is_hidprobe()) { if(null!=connection.match(/No connection/i)) { alert("No connection: please open a connection then click on Load/Run again"); } else { try { transfer_open(); try { eventLoop_BootLoad();//for bootloader. For simplicity there are no calls or callbacks as a result of events log("Returned from eventLoop_BootLoad()"); } catch(e) { log("event loop error"); throw e; } } catch(e) { alert("error: " + e.description); er=e; }//finally only appears to work with a rethrow if a javascript throw that was used to generate the error in the first place, not a windows runtime error?? try { transfer_close(); } catch(e) { } if(er!=null) throw er; } } function host_is_hidprobe() { var host_ok; try { WScript.Echo("Must be run hosted by Hidprobe http//www.zgus.com/hid"); host_ok=false; } catch(e) { try { if(null!=Version.match(/Hidprobe/i)) host_ok=true; else host_ok=false; } catch(e) { host_ok=false; } } return host_ok; } function transfer_open() { var signal=GetSignal(); alert("version is '"+Version+"'"); alert("signal is '"+signal+"'"); alert("connection is '"+Connection+"'"); fso = new ActiveXObject("Scripting.FileSystemObject"); tf_log = fso.CreateTextFile(file_log, true); try { tf_secure = fso.OpenTextFile(file_secure, 1, false); } catch(e) { throw new Error(0,"file_secure not found: '" + file_secure + "'"); } if(BAUD!=2400) { priorBAUD=BAUD; BAUD=2400;//the default start speed, can be changed later log("baud temporarily changed to 2400 baud for start up"); } } function transfer_close() { if(priorBAUD) { BAUD=priorBAUD; log("prior BAUD restored"); } tf_secure.Close(); tf_log.Close(); } function _sleep(timeMs) { var resSleep; switch(resSleep=Sleep(timeMs)) { case HIDSCRIPT_EVENT_TIMEOUT: //OK return; case HIDSCRIPT_EVENT_TIMEOUT_OUTOFRANGE: //out of range (10 to 1000 000 000 milliseconds is the accepted range throw new Error("Sleep value '"+timerM+"' out of ms range"); default: //error or shutdown throw new Error("Sleep received error or shutdown response: "+resSleep); } } function matchReadUniqueEnd(str_expected)//a simple but effective parse routine that relies on last chracter sent being unique and the last character sent {//does not keep spinning! GetNextEvent sends thread to sleep until an event has been posted to the thread var str_received, char_last if(!str_expected.length) return true; str_received=""; char_last=str_expected.charAt(str_expected.length-1); while(1) {//this is NOT POLLING! var event=GetNextEvent(TIMEOUT_INFINITE);//goes to sleep if no event notification is waiting to be collected if(HIDSCRIPT_EVENT_GETREPORT==event) { str_received+=GetReport(); if(str_received.charAt(str_received.length-1)==char_last) {//don't need to search entre string because last character sent is always unique for a required match if(str_received==str_expected) return true; else return false; } } else throw new Error("unexpected event " + event + " in matchReadUniqueEnd"); } } function log2file(msg) { tf_log.WriteLine(msg); } function log(msg) { log2file(msg); alert(msg); } function eventLoop_BootLoad() {//normally event loops call functions or make callbacks. For simplicity this is not done here var str_reply=""; var str_hex; while(!matchReadUniqueEnd("ZGBL\r\n"));//hidprobe inserts an extra \r SetReport("ZGBL S5\n");//change baud to 38400 _sleep(100); BAUD=38400 log("speed changed to 38400") if(!matchReadUniqueEnd("ZGBL S5\r\n"))//hidprobe inserts an extra \r { log("Error: ZGBL S5\\n expected to confirm baud change"); return; } SetReport("ZGBL L\n");//do load of new firmwware while(!tf_secure.AtEndOfStream) { var chars_to_send; var chars_sent=0; str_hex=tf_secure.ReadLine();//read in the first line, end of stream not checked for here log2file("Read in Line: " + str_hex + " of length " + str_hex.length); chars_to_send=str_hex.length; if(chars_to_send%16) throw new Error("Error: chars_to_send must be a multiple of 16"); while(1) {//this is NOT POLLING! var event=GetNextEvent(TIMEOUT_INFINITE);//goes to sleep if no event notification is waiting to be collected if(HIDSCRIPT_EVENT_GETREPORT==event) { str_reply=GetReport(); if(str_reply!="C")//should only be character at a time throw new Error("Unexpected response " + str_reply); SetReport(str_hex.substring(chars_sent, chars_sent+16));//currently ONLY 100 characters allowed to be sent at a time!!!!! chars_sent+=16; if(chars_to_send==chars_sent)//also caters for a blank line being read in with zero characters break; } else throw new Error("unexpected event " + event + " in eventLoop_BootLoad"); } } _sleep(200); log("Bootloader finished"); }