README-DemoApp.txt Driver File Contents (dm6437_1day_1_21.zip)

Texas Instruments DM6437EVM Host-side Demo Application (v0.5)
======================================================

This program runs on a host machine (typically a PC running Windows or Linux) 
and connects over the network to a DM6437EVM board, running the target-side 
demo application, in order to let the user control the target behavior and to 
stream audio and video files to and from the target.

The program is written in ECMAScript -- popularly known as JavaScript -- and 
requires no development tools other than a text editor. You run the program by 
running the .bat file located in this directory. (To learn how to run the 
program in a graphical debugger, please look at the .bat file itself and 
comment out the appropriate line.)

We should note that the core JavaScript language, used for this program, has 
nothing to do with Web pages; it is a general purpose scripting language like 
Perl or Python.

JavaScript is not Java, but it lets a developer use existing body of Java 
libraries without requiring the developer to be a Java programmer. Three such 
libraries are used by this script:
   1) Networking library
   2) File I/O library
   3) GUI library

These libraries are part of the XDC toolset, used primarily for development of 
target software, and are included in the DM6437EVM tools installation.

(An alternative scripting language, Perl, while more widely used, is considered 
less coder-friendly and would require a separate Perl tools installation. 
Another alternative -- not a script, but an executable developed in MS Visual 
C++ -- is less suitable for rapid development of applications like this one, 
and would require installation of licensed MS tools.)


Structure of the application
----------------------------

The application is split into four modules: GUI control, Target control, File 
I/O, and networking (communication):
   
  Main.js <-----+------ Dm6437evm/Rpc.js  <------+-- Dm6437evm/Ipc.js
   (GUI)        |       (target control)         |   (networked comm w/target)
                |                                |
                `------ Dm6437evm/Fileio.js  <---'
                        (File I/O)

The main script, Main.js, is in charge only of the GUI: it draws buttons and 
input fields and listens for user's actions to send an appropriate command to 
the target (start playing, stop playing, switch mode etc.). It also starts a 
separate thread to run Fileio functions and thus serve the target with input 
and output audio/video files.

The Rpc -- "Remote Procedure Call" -- module provides the GUI script with 
several functions, of which the important ones are:

    rpc.connect( ipAddr )     -- connects to the target at ipAddr
    rpc.paramGet( paramName ) -- gets a target state parameter, e.g. "mode"
    rpc.paramSet( paramName ) -- changes state, i.e. sets "mode" to "decode"
    rpc.controlPlay/Stop()    -- starts/stops target's audio/video processing

    (paramGet() and paramSet() read and write target's state variables -- like
     I/O registers -- and what those are is defined by the target. The demo app
     accesses a few like "runFlag" -- is the demo running or stopped,
     "audioEnableFlag" -- is audio enabled, "mode" -- what mode it is running
     in, etc.)

The Fileio module has an even simpler API:

    fileio.connect( ipAddr, port ) -- connects to the target's fileio port
    fileio.recvCmd()               -- receive File I/O command from target
    fileio.dispatchCmd()           -- run received File server cmd, eg. "read"

    (The target sends commands like "open file such and such", "read so and
     so many bytes from the file" to the host but the GUI script does not
     care what those are. Its only duty is to run them from a separate
     thread.)

The Ipc module takes Rpc's and Fileio's data structures, serializes them and 
sends or receives them to or from the target over the network. The API -- not 
directly used by the GUI script -- looks like this:

    ipc.connect( ipAddr, port )   -- connects to the port at the given address
    ipc.writeWord( word )         -- writes a 32-bit word to the target
    ipc.readWord()                -- reads a 32-bit word from the target
    ipc.writeString( string )     -- passes on a text string to the target
    ipc.readString()              -- reads a text string from the target.

For details about how Rpc, Fileio, and Ipc (Inter-Process Communication) 
modules work, please refer to their scripts directly. They follow a certain 
protocol for exchanging information between the host and the target. It is 
unlikely you will have to change any of those modules: if you want to modify 
the host and the target demo application for your own needs, on the host side 
you likely need to change only the GUI script -- add or remove some buttons and 
drop-down lists, and read and write some old and some new target state 
parameters, as defined by your target application.


A note about ECMAScript (JavaScript)
------------------------------------

JavaScript's syntax allows C programmers to understand, and to a degree modify, 
programs written in this language even if they have never seen this language 
before. To learn how to make nontrivial modifications, or to write new 
JavaScript programs, please refer to this Web page:

    http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Guide

We believe it is not necessary to read it in order to understand the rest of 
this document. C programmers typically "get" patterns of JavaScript scripts 
quickly and can replicate them without formally learning the language.

Also note that part of our JavaScript script is using Java library classes. 
This requires knowing the APIs of libraries in question, however using Java 
classes from JavaScript is much easier than writing Java programs in Java. (We 
do not do that here.)


The main application script, Main.js
------------------------------------

The flow of the main script can be described in short as: initialize target 
communication modules, draw buttons and other widgets on the screen, assign a 
function to each button, and loop, waiting for the user to close the window; 
meanwhile, whenever the user clicks on a button, the function we assigned to 
the button runs -- typically sending some message to the target, e.g. "connect" 
or "start playback".

In more details (and you can look at the code in parallel), Main.js flows like 
this:

    .---- global ---------------------.
    | - load target comm. scripts     |
    | - define global variables       |
    | - call main()                   |
    `---------------------------------'
        |
        |   .---- main() ---------------------.
        `-->| - create target comm. objects   |
            | - create GUI objects            |
            | - call layoutWidgets()          |
            | - call setEventListeners()      |
            | - loop till the user closes app |
            `---------------------------------'
               |
               |    .---- layoutWidgets() --------------.
               +--->| - place all controls (buttons,    |
               |    |   text boxes, groups of controls) |
               |    |   on screen                       |
               |    `-----------------------------------'
               |   
               |    .---- setEventListeners() ----------.
               `--->| - specify functions to be called  |
                    |   for each button and other       |
                    |   controls                        |
                    `-----------------------------------'
                        |  
                        |   .---- eventFxnBtnConnect() -----.
                        +-->| - connect to the target       |
                        |   | - read target state variables |
                        |   | - set state of widgets based  |
                        |   |   on target state             |
                        |   | - start the FileIo thread     |
                        |   `-------------------------------'
                        |
                        |   .---- eventFxnBtnDisconnect() --.
                        +-->| - disconnect from the target  |
                        |   `-------------------------------'
                        |
                        :   ... etc.
                       
1. First we load the two scripts, Rpc.js and Fileio.js, that implement 
communication with the target, i.e. sending messages to it over the network. 
They let us create target communication objects later on in main().


2. We define global variables used in this script (Main.js). Some of them are 
references to library objects, others we define as null and initialize later on.

First we create aliases for the GUI Java libraries ("classes") we use. We do 
not use the standard Java GUI library but something called "SWT" (Standard 
Windowing Toolkit), made by IBM for its development environment Eclipse. SWT 
works much faster and looks "normal" -- it's impossible to say that this 
application wasn't written in MSVC++ or Visual Basic just by looking at its 
screen.

Next we define the "debugFxn" variable, to turn debugging on or off. This 
variable is really a function, but in JavaScript a variable can be of any type, 
including a function! So if a script line 'debugFxn( "Debug: File I/O thread 
started" );' somewhere down the road executes, what it will do depends on how 
we defined "debugFxn". If we defined "var debugFxn = print;" -- and print() is 
a built-in function -- the message will appear. If we defined "var debugFxn = 
function() {}", all calls to debugFxn() will be silent.

Global variables "rpc" and "fileio" for target communication, and "display" and 
"shell" that refer to the system screen and our application's window are set to 
null and will be initialized in main().

Variable "myWidgets" is a hash-table -- an array whose elements are accessed by 
name instead of by index -- and initially empty, but will later be filled with 
references to various screen controls. For example, we will when appropriate 
read what the user has typed in the "txtIP1" box -- the box with the first part 
of the target IP address -- by calling 'myWidgets["txtIP1"].getText();' or, 
qw;ll check if he selected the "Encode" video mode with 'if 
(myWidgets["radioEncode"].getSelection() == true)'.


3. The final outside-of-any-function statement executed in this script is 
main(), which calls our function main() defined below. In JavaScript, a 
variable/function is in the scope if it is defined anywhere in the scope -- 
does not have to be defined before it is referenced.

The main() function first creates an Rpc object, from the Rpc.js module. After 
the "rpc" variable is initialized, any function in the script can connect or 
send a message to the target, like rpc.connect( "168.132.141.15" ) or 
rpc.controlPlay(). Similarly with fileio and Fileio.js -- for details of Rpc 
and Fileio APIs refer to their scripts.

After that, the main() function creates "display" and a "shell", initializing 
these global variables; "display" is the whole screen, "shell" is where buttons 
and other widgets are drawn. Then it calls the function that draws -- lays out 
-- the widgets, and another that assigns "event listener" functions that are 
called when a button is pressed. After that main() calls a function that grays 
out everything except the "connect" button's area, because the application has 
just started and allowing the user to press "play" without even connecting 
first would be wrong.

The last part of the main() function is the standard loop for SWT GUI programs 
that refreshes the screen and calls event functions when a button click (or 
some other widget event) occurs, leaving the loop when the user has closed the 
main window.


Drawing screen controls ("laying out widgets")
----------------------------------------------

Since we don't use a graphical editor to draw widgets on the screen, we have to 
lay them out within the script in a recipe-like fashion. That means that for 
our application window (the "shell") we say which groups of widgets are drawn 
next to each other and which are under others. Then in each group of widgets we 
specify how widgets inside it are laid out -- next to each other or some under 
others, and whether there are any further subgroups contained within the group.

This will become obvious in a moment. Meanwhile let's clarify some terms -- a 
"widget" is a common name for any singular element like a button, a text field, 
label, drop-down box, etc., or a container for other elements, i.e. a "group" 
of widgets.

These containers are special because they can contain other widgets -- simple 
elements and other containers. It is worth noting that we use two kinds of 
containers: "Groups" and "Composites", the only difference between them being 
that Groups have visible frames around widgets contained in it, while 
Composites are not visible.

One final thing to know about containers is that we use so called "grid" 
layouts to specify how widgets inside them are laid out. Grids are matrices -- 
which can and often have only one row or only one column -- where each grid 
cell contains a widget (which, remember, can be another container with its own 
grid), and each grid cell can be aligned left or right or centered.

An example to explain it all soon follows. A grid's column or row width or 
height can be controlled, but we usually don't have to: we can set the size of, 
say, a button inside it in pixels and the grid's column adapts automatically, 
expanding to match the widest element in the column. And often we don't have to 
do even that: when we put some text on the button, say " Connect ", the system 
calculates how wide the button should be for the text to show, and everything 
automatically fits.

We can also control minor properties of containers like "margin width" or 
"vertical spacing" or "make all columns equal width" to create 
professional-looking applications.

Let us now take a look at an example. Run the demo app and look at the 
"Connection" frame. It has several buttons and text fields, one drop-down list 
(called a "combo box"), and a few labels, looking on the screen like this:

    .-- Connection ----------------------.
    |                                    |
    | Status     [____NOT CONNECTED____] |
    |                                    |
    | IP Addr    [146].[252].[191].[38 ] |
    |                                    |
    | (Discover) [____________________v] |       Legend:                    
    |                                    |       [____] - text field
    | (Connect)  (Disconnect)            |       (____) - push button
    |                                    |       [___v] - drop-down combo box
    `------------------------------------'

The "Connection" frame is a cell in a larger grid, but it could be the only 
thing on the screen -- we'd draw it all the same. We need one container, 
"Group" because we want a visible frame, whose text will be "Connection", and 
before we lay out labels, text fields etc. inside it, we say that the group 
uses a grid with 2 columns in each row.

The challenge, however, is that we have two widgets per row in all rows except 
the second -- the IP address takes 7 widgets: four text fields and three labels 
(each containing just the "." as its text).

(A row is filled by adding an element to the container. When the newly added 
element exceeds the number of columns in the current row, it spills over into 
the next row.)

So we need to treat the IP address set of fields differently: we need to lump 
up all of its widgets into an invisible container -- a "Composite", and put 
that composite in the second cell of the second row. Then, as far as the 
"Connection" group is concerned, it sees only two elements in each row. The 
Composite for the IP address we'll declare to have 7 columns per row, and then 
we'll alternate the for text fields and three "." labels to fill in its single 
row.

That gives us the following layout:

    +- - -  Connection - - - - - - - - - - - - - - - - - - - - - - - +
    :  Status      :  [ NOT CONNECTED                             ]  :
    +- - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - +
    :              :  +- - - -+- -+- - - -+- -+- - - -+- -+- - - -+  :
    :  IP Address  :  : [146] : . : [252] : . : [191] : . : [38 ] :  :
    :              :  +- - - -+- -+- - - -+- -+- - - -+- -+- - - -+  :
    +- - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - +
    : ( Discover ) :  [                                          v]  :
    +- - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - +
    : ( Connect )  :  (Disconnect )                                  :
    +- - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - +

Dotted lines indicate invisible grids. The outer grid has rows with 2 columns 
each, and the inner grid in the second row has one row with 7 columns.

Now let's look at the script code that does this layout. We define two handy 
functions, WID() and END() (almost like macros) that make the code look more 
readable. WID(<new widget>) adds the new widget to the current widget, 
referenced with variable $w, and makes the new widget current until a matching 
END() is called. WID() also returns the reference to the newly created widget 
object, so that we can store it in myWidgets[] hash table. We only need 
references to a few widgets that we later want to somehow control; usually we 
keep only the references for the input fields and buttons.

The following code creates the "Connection" frame inside the current widget 
(which happens to be the larger grid containing all other big frames in the 
screen, but that's irrelevant), and adds the first two elements, i.e. completes 
the first row:

                         WID( widgets.Group( $w, SWT.NONE ) );
                             $w.setText( "Connection" ); // $w = current widget
                             var gl = layout.GridLayout( 2, false );
                             $w.setLayout( gl );
          
                             WID( widgets.Label( $w, SWT.NONE ) );
                                 $w.setText( "   Status" );
                             END();
               
    w["txtStatus"] =         WID( widgets.Text( $w, SWT.BORDER | SWT.CENTER |
                                  SWT.READ_ONLY ) );
                                 $w.setLayoutData( GD( 164, SWT.DEFAULT ) );
                             END();

So we create the "Connection" group, set its label text appropriately, and make 
it have a Grid Layout of 2 columns per row. The function ("constructor") that 
creates a new layout has signature, GridLayout( <number of columns>, <make 
columns equal width> ).

All widgets, when created, as a first argument take the reference of the 
containing widget. With our macro-like functions it is always "$w". The second 
argument to a widget is usually some attributes, e.g. whether it has a border, 
how is its text justified, etc.

We then add a label, "Status", and create a text box to contain connection 
status. The connection status text could be placed in another label like 
"Status", because we can change the text of any widget dynamically, but we use 
a text box for an aesthetic effect. We make the textbox have a border, have its 
text center-aligned, and be read only; we also record its reference in 
myWidgets["txtStatus"], where "w" is a short alias for "myWidgets". In the next 
line, we say that the grid cell where the text box is should be 164 pixels wide 
and have the default height (determined by the textbox's font and font size).

So how do we know which widgets are available, and which properties they have? 
The answer lies at this page:
    http://www.eclipse.org/swt/widgets.
It has a screenshot of each widget, its API reference, and example code snippet.

The rest of the code lays out the "IP address" label, the invisible 7-column 
"Composite" with its IP address fields and labels, the "Discover" button and 
combo box, and the "Connect" and "Disconnect" buttons. Note how the END() 
function closes the definition of a widget:

                             WID( widgets.Composite( $w, SWT.NONE ) );
                                 var gl = new layout.GridLayout( 7, false );
                                 gl.marginWidth = 0;
                                 $w.setLayout( gl );
    w["txtIP1"] =                WID( widgets.Text($w,SWT.BORDER|SWT.CENTER ));
                                     $w.setLayoutData( GD( 20, SWT.DEFAULT ) );
                                 END();
                                 WID( widgets.Label( $w, SWT.NONE ) );
                                     $w.setText( "." );
                                 END();
    w["txtIP2"] =                WID( widgets.Text($w,SWT.BORDER|SWT.CENTER));
                                     $w.setLayoutData( GD( 20, SWT.DEFAULT ) );
                                 END();
                                 WID( widgets.Label( $w, SWT.NONE ) );
                                     $w.setText( "." );
                                 END();
                                 ... etc, for IP3 and IP4
                             END();
                
    w["btnDiscover"]   =     WID( widgets.Button( $w, SWT.PUSH ) );
                                 $w.setText( "   Discove&r   " );
                             END();
                           
    w["cmbDiscover"]   =     WID( widgets.Combo( $w, SWT.READ_ONLY ) );
                                 $w.setLayoutData( GD( 158, SWT.DEFAULT ) );
                             END(); 
                           
    w["btnConnect"]    =     WID( widgets.Button( $w, SWT.PUSH ) );
                                 $w.setText( "   &Connect   " );
                             END();
                           
    w["btnDisconnect"] =     WID( widgets.Button( $w, SWT.PUSH ) );
                                 $w.setText( " Disc&onnect " );
                             END();
                         END();

The indentation before WID() and END() functions lets us better see who 
contains whom. Note again that it is not necessary to use WID() and END(), we 
use them because they improve readability of the code. (If you place a widget 
in the wrong container, you'll often get drastically different screens.)


Reacting to button clicks ("setting widget event functions")
-----------------------------------------------------------

The setEventListeners() function assigns a function to every widget that the 
user can click on. The first such assignment you will see -- remembering that 
"w" is an alias for the "myWidgets" hash table -- is

    w["btnDiscover"].addListener( SWT.Selection, eventFxnBtnDiscover );

That means, when the user presses ("selects") the "Discover" button, our 
eventFxnBtnDiscover() function is to be called. If you look at the body of that 
function further below, you'll see the expected: it calls the rpc.discover() 
function which returns zero or more IP addresses of targets who run the demo 
(determined by their response to a specific broadcast message, see Rpc.js for 
details), and then fills in the w["cmbDiscover"] drop down list with those 
addresses and copies the first in the list into the "IP address" input fields. 
If at least one is found, the user can click on the "Connect" button afterwards 
for the first found target, or select a different one from the drop down list.

However, in the setEventListeners() you will see that events for which we have 
simpler actions can be defined right on the spot. Take this one for example:

    w["btnInVideoBrowse"].addListener( SWT.Selection, function( event ) {
        var dialog = new widgets.FileDialog( shell );
        var fileName = dialog.open();
        if (fileName != null) {
            w["cmbInVideo"].add( fileName, 0 );
            w["cmbInVideo"].select( 0 );
            w["txtInVideoSizeKB"].setText( Math.floor( new java.io.File(
                fileName ).length() / 1024 ) );
        }
    } );

This is an event function for the "Browse for Input Video file" button. It 
opens a new file dialog, and, if the user has selected a file, it adds the file 
to the top of the "input video file" drop-down list and makes it the first 
choice. Then, while we're at it, we read the file's size and show it in the 
"txtInVideoSizeKB" read-only input video file size textbox. (The function call 
java.io.File(fileName).length() returns the file size in bytes or 0 if the file 
doesn't exist.) It is these versatile Java library functions like this that 
make scripts short.


Exceptions
----------

(C++ and OOP developers can skip this section) If you look at the APIs provided 
by target communication modules Rpc.js and Fileio.js (and the one they use, 
Ipc.js), you will see that no function returns success or failure. Instead, if 
en error occurs, an /exception/ is trown, either by a system module that the 
function uses, or the function itself if it detects some irregularity. That 
exception travels up the call stack until someone catches it -- or, if no 
function catches it, the application exits in an error with its call stack 
listed.

That frees us from having to check return status on every other line of code. 
Instead, we simply catch the exceptions -- by enclosing function(s) whose 
execution can result in an exception -- in what is called a "try-catch" block:

    try {
        function(s) called here
    } catch (e) {
        // we're here only if an error occurred
        print ("error occurred, reason: " + e)
    }

You will see code like this in the Main script only and rarely elsewhere.


Threading
---------

Our application is a multi-threading one. The main thread runs the main() 
function, looping to see if display should be refreshed, dispatching any 
events, and exiting when the window is closed. Each of our widget event 
functions, called by the SWT GUI system, runs in the context of that main 
thread. So the main application thread is in charge of all the GUI.

Another thread we run is the FileIO thread. When the main thread connects to 
the target, it soon after fires up a separate thread that also connects to the 
target but on a different port, and the new thread becomes the target's file 
server. The new thread reads input files from the disk and sends audio/video 
data to the target, and receives data from the target and writes output files.

We also use an occasional timer thread, to update a counter or periodically 
check for target status.

Creating a new thread in JavaScript is simple. For example, in code like this,

    print( "Hello" );
    new java.lang.Thread( new java.lang.Runnable() {
        run: function() {
            print( "cruel" );
        }
    } ).start();
    print( "world" );

the main thread prints "Hello", then creates a secondary thread which will 
print "cruel" when runs and starts it, and finally prints "world". The new 
thread may print its message in between the two main thread's messages or 
after. The new thread also could have a loop, perhaps sleeping every now and 
then by calling java.lang.Thread.sleep(<milliseconds>) or yielding the CPU with 
java.lang.Thread.yield(). All of this is standard for any threading system; the 
difference is only in ease of thread creation.

All threads can read and write all the script's global variables; for example, 
the thread running Fileio function loops while "stopFileIoThreadFlag" global 
variable is false; this variable is set to true by the main() function at its 
exit. Moreover, threads whose "run" functions are defined inline -- as in the 
example above -- have access to all the variables in the scope of the function 
which defined them. That lets us define quick, short thread functions right on 
the spot, without having to define separate functions and pass on piles of 
variables.

The only exception to this idyllic picture comes when different threads need to 
access GUI objects: "shell" and "myWidgets[]" in our case. They cannot be 
accessed directly from a thread other than the main thread, i.e. this would 
fail:

    // main thread
    w["myText"].setText( "lovely" );
    new java.lang.Thread( new java.lang.Runnable() {
        run: function() {
            // new thread
            print( "Hello " + w["myText"].getText() + " world" );
        }
    } ).start();
  
The main thread sets the text of the "myText" text widget and creates the new 
thread. But the new thread is not allowed to call the "getText()" method of the 
w["myText"] object. It must goe around this limitation by calling a method 
"display.syncExec()" or "display.asyncExec()" and specify a thread-like code 
within it to access the widget:

    w["myText"].setText( "lovely" );
    new java.lang.Thread( new java.lang.Runnable() {
        run: function() {
            var myTextContents;
            display.syncExec(
                new java.lang.Runnable() {
                    run: function() {
                        myTextContents = w["myText"].getText();
                    }
                 }
            );
            print( "Hello " + myTextContents + " world" );
        }
    } ).start();

The new thread now makes a blocking call to the display.syncExec() method that 
creates yet another thread, but now one that is allowed to read the widget. The 
newest thread reads the contents of the text widget, stores it in the second 
thread's local variable, "myTextContents", and exits. Then the second thread  
continues and goes on to print the contents of its local variable, 
"myTextContents", knowing that it has been set to reflect the contents of the 
widgets that it couldn't access directly.

You will notice that we use display.asyncExec() in a couple places in Main.js. 
One such example is the Fileio thread: the main thread in Main.js spawns a new 
thread to be a Fileio server upon connection to the target. The new thread 
calls fileio.recvCmd() and fileio.dispatchCmd( cmd ) methods in a loop. The 
later one can be (and often is) a write request from the target -- the target 
wants to write data to a file or text on the console. If you look at Fileio.js, 
you will see that the function that implements write also calls a method 
"showWriteInfo( filename, newFileSize )". This method is by default a dummy 
function -- but the fileio thread in Main.js sets this method to update the 
file size textboxes on the screen. And this is where display.asyncExec() comes 
to play:

Fileio's showWriteInfo is effectively a callback, called from another thread, 
and set to update some widgets on the screen. We now know that is not allowed, 
so in Main.js' fileio thread we set the callback not to be a simple update of 
the text, but we wrap it around display.asyncExec() and it all works.

Why didn't we use display.syncExec(), i.e. the blocking version? The answer is, 
we don't want the fileio thread to be blocked on what's a less important task 
-- updating the widgets -- and be less responsive to the data the target sends. 
This problem would get compounded if the main thread happened to be doing a 
blocking call itself, like rpc.controlStop() which exchanges some messages with 
the target. Then the Fileio thread would unnecessarily wait for that blocking 
call to complete just so it can finish updating some not-so-important widget. 
This is why display.asyncExec() is the right method to use.


Final note
----------

One of the biggest powers of JavaScript comes from the fact that functions can 
be defined (and even generated!) on the fly. Any syntactically valid text can be 
turned into a function.

Another is that variables can be of any type, and fields in a structure like 
hash-table can be added on the fly and be of any type.

Both these features carry a danger with them: wrong functions can be 
constructed and we won't know until they run, and typos can happen and a wrong 
field or value will be set in a hash-table object without anyone complaining. 
With traditional languages, the compiler prevents some of these errors, but 
often also we cannot know if the value the compiler accepted is OK until we run 
the program.

A third powerful feature is integration with Java classes and ability to use 
them easily. And since Java classes can be made that access native code like 
driver DLLs, it would not be difficult to create such wrapper Java classes that 
would let you call low-level driver functions from a JavaScript script.


Information resources for ECMAScript (JavaScript) and libraries
---------------------------------------------------------------

JavaScript programs can readily use Java libraries just by knowing their APIs. 
Here are the resources for the libraries used in this application:

    - JavaScript language: 
      http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Guide

    - Java Networking:
        - overview:
          http://java.sun.com/docs/books/tutorial/networking/index.html
        - sockets: 
          http://java.sun.com/j2se/1.4.2/docs/api/java/net/Socket.html

    - Java File I/O: 
      http://java.sun.com/docs/books/tutorial/essential/io/
    - GUI:
        - widgets snapshots and APIs: 
          http://www.eclipse.org/swt/widgets/
        - programming SWT: 
          http://www.developer.com/java/other/article.php/3330861
Download Driver Pack

How To Update Drivers Manually

After your driver has been downloaded, follow these simple steps to install it.

  • Expand the archive file (if the download file is in zip or rar format).

  • If the expanded file has an .exe extension, double click it and follow the installation instructions.

  • Otherwise, open Device Manager by right-clicking the Start menu and selecting Device Manager.

  • Find the device and model you want to update in the device list.

  • Double-click on it to open the Properties dialog box.

  • From the Properties dialog box, select the Driver tab.

  • Click the Update Driver button, then follow the instructions.

Very important: You must reboot your system to ensure that any driver updates have taken effect.

For more help, visit our Driver Support section for step-by-step videos on how to install drivers for every file type.

server: web4, load: 1.03