1 <!-- Copyright (C) 2003 Red Hat, Inc. -->
2 <!-- This material may be distributed only subject to the terms -->
3 <!-- and conditions set forth in the Open Publication License, v1.0 -->
4 <!-- or later (the latest version is presently available at -->
5 <!-- http://www.opencontent.org/openpub/). -->
6 <!-- Distribution of the work or derivative of the work in any -->
7 <!-- standard (paper) book form is prohibited unless prior -->
8 <!-- permission is obtained from the copyright holder. -->
12 >Writing New Devices - host</TITLE
13 ><meta name="MSSmartTagsPreventParsing" content="TRUE">
16 CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+
19 TITLE="eCos Reference Manual"
20 HREF="ecos-ref.html"><LINK
22 TITLE="eCos Synthetic Target"
23 HREF="hal-synth-arch.html"><LINK
25 TITLE="Writing New Devices - target"
26 HREF="synth-new-target.html"><LINK
29 HREF="synth-porting.html"></HEAD
40 SUMMARY="Header navigation table"
49 >eCos Reference Manual</TH
57 HREF="synth-new-target.html"
71 HREF="synth-porting.html"
82 NAME="SYNTH-NEW-HOST">Writing New Devices - host</H1
90 >Writing New Devices -- extending the synthetic target, host-side</DIV
94 NAME="SYNTH-NEW-HOST-DESCRIPTION"
99 >On the host-side adding a new device means writing a Tcl/Tk script
100 that will handle instantiation and subsequent requests from the
101 target-side. These scripts all run in the same full interpreter,
102 extended with various commands provided by the main I/O auxiliary
103 code, and running in an overall GUI framework. Some knowledge of
104 programming with Tcl/Tk is required to implement host-side device
108 >Some devices can be implemented entirely using a Tcl/Tk script. For
109 example, if the final system will have some buttons then those can be
110 emulated in the synthetic target using a few Tk widgets. A simple
111 emulation could just have the right number of buttons in a row. A more
112 advanced emulation could organize the buttons with the right layout,
113 perhaps even matching the colour scheme, the shapes, and the relative
114 sizes. With other devices it may be necessary for the Tcl script to
115 interact with an external program, because the required functionality
116 cannot easily be accessed from a Tcl script. For example interacting
117 with a raw ethernet device involves some <TT
121 calls, which is easier to do in a C program. Therefore the
125 > script which implements the
126 host-side ethernet support spawns a separate program
130 >, written in C, that performs the
131 low-level I/O. Raw ethernet access usually also requires root
132 privileges, and running a small program <TT
136 with such privileges is somewhat less of a security risk than the
137 whole eCos application, the I/O auxiliary, and various dynamically
141 >Because all scripts run in a single interpreter, some care has
142 to be taken to avoid accidental sharing of global variables. The best
143 way to avoid problems is to have each script create its own Tcl
144 namespace, so for example the <TT
148 creates a namespace <TT
152 and procedures reside in this namespace. Similarly the I/O auxiliary
153 itself makes use of a <TT
162 NAME="SYNTH-NEW-HOST-BUILD"
165 >Building and Installation</H2
167 >When an eCos device driver or application code instantiates a device,
168 the I/O auxiliary will attempt to load a matching Tcl script. The
169 third argument to <TT
171 >synth_auxiliary_instantiate</TT
173 specifies the type of device, for example <TT
177 and the I/O auxiliary will append a <TT
181 and look for a script <TT
187 >If the device being instantiated is application-specific rather than
188 part of an eCos package, the I/O auxiliary will look first in the
189 current directory, then in <TT
192 >. If it is part of an eCos
193 package then the auxiliary will expect to find the Tcl script and any
194 support files below <TT
197 > in the install tree - note
198 that the same install tree must be used for the I/O auxiliary itself
199 and for any device driver support. The directory hierarchy below
204 structure of the eCos repository, allowing multiple versions of a
205 package to be installed to allow for incompatible protocol changes.
208 >The preferred way to build host-side software is to use
216 this involves little more than copying the
227 > files from an existing package,
228 for example the synthetic target ethernet driver, and then making
232 > it may be necessary
233 to adjust the path to the root of the repository.
237 > may require a similar change, and
241 > macro invocation will have to be
242 changed to match one of the files in the new package. A critical macro
245 >ECOS_PACKAGE_DIRS</TT
247 up the correct install directory. <TT
251 require some more changes, for example to specify the data files that
252 should be installed (including the Tcl script). These files should
253 then be processed using <B
264 order. Actually building the software then just involves
275 >, as per the instructions in the
282 >To assist developers, if the environment variable
286 > is set then a slightly different
287 algorithm is used for locating device Tcl scripts. Instead of looking
288 only in the install tree the I/O auxiliary will also look in the
289 source tree, and if the script there is more recent than the installed
290 version it will be used in preference. This allows developers to
291 modify the master copy without having to run <B
298 >If a script needs to know where it has been installed it can examine
301 >synth::device_install_dir</TT
303 variable gets updated whenever a script is loaded, so if the
304 value may be needed later it should be saved away in a device-specific
311 NAME="SYNTH-NEW-HOST-INSTANTIATION"
316 >The I/O auxiliary will <B
319 > the device-specific
320 Tcl script when the eCos application first attempts to instantiate a
321 device of that type. The script should return a procedure that will be
322 invoked to instantiate a device.
331 CLASS="PROGRAMLISTING"
332 >namespace eval ethernet {
334 proc instantiate { id instance data } {
336 return ethernet::handle_request
339 return ethernet::instantiate</PRE
347 > argument is a unique identifier for this
348 device instance. It will also be supplied on subsequent calls to the
349 request handler, and will match the return value of
352 >synth_auxiliary_instantiate</TT
353 > on the target side. A
354 common use for this value is as an array index to support multiple
355 instances of this types of device. The <TT
362 > arguments match the corresponding arguments to
365 >synth_auxiliary_instantiate</TT
366 > on the target side, so
367 a typical value for <TT
378 arbitrary initialization parameters from target to host.
381 >The actual work done by the instantiation procedure is obviously
382 device-specific. It may involve allocating an <A
383 HREF="synth-new-host.html#SYNTH-NEW-HOST-INTERRUPTS"
386 device-specific subwindow to the display, opening a real Linux device,
387 establishing a socket connection to some server, spawning a separate
388 process to handle the actual I/O, or a combination of some or all of
392 >If the device is successfully instantiated then the return value
393 should be a handler for subsequent I/O requests. Otherwise the return
394 value should be an empty string, and on the target-side the
397 >synth_auxiliary_instantiate</TT
402 >. The script is responsible for providing
404 HREF="synth-new-host.html#SYNTH-NEW-HOST-OUTPUT"
407 why the device could not be instantiated.
413 NAME="SYNTH-NEW-HOST-REQUESTS"
416 >Handling Requests</H2
418 >When the target-side calls
421 >synth_auxiliary_xchgmsg</TT
422 >, the I/O auxiliary will
423 end up calling the request handler for the appropriate device instance
424 returned during instantiation:
433 CLASS="PROGRAMLISTING"
434 >namespace eval ethernet {
436 proc handle_request { id request arg1 arg2 txdata txlen max_rxlen } {
438 if { <some condition> } {
439 synth::send_reply <error code> 0 ""
443 synth::send_reply <reply code> $packet_len $packet
454 > argument is the same device id that was
455 passed to the instantiate function, and is typically used as an array
456 index to access per-device data. The <TT
470 > are the same values that were passed to
473 >synth_auxiliary_xchgmsg</TT
474 > on the target-side,
475 although since this is a Tcl script obviously the numbers have been
476 converted to strings. The <TT
480 as transmitted by the target, or an empty string if the I/O operation
481 does not involve any additional data. The Tcl procedures
492 > may be found especially useful when
493 manipulating this buffer. <TT
497 convenience, although <B
499 >string length $txdata</B
501 give the same information.
504 >The code for actually processing the request is of course device
505 specific. If the target does not expect a reply then the request
506 handler should just return when finished. If a reply is expected then
507 there should be a call to <B
509 >synth::send_reply</B
511 first argument is the reply code, and will be turned into a 32-bit
512 integer on the target side. The second argument specifies the length
513 of the reply data, and the third argument is the reply data itself.
514 For some devices the Tcl procedure <B
518 may prove useful. If the reply involves just a code and no additional
519 data, the second and third arguments should be <TT
523 and an empty string respectively.
526 >Attempts to send a reply when none is expected, fail to send a reply
527 when one is expected, or send a reply that is larger than the
528 target-side expects, will all be detected by the I/O auxiliary and
529 result in run-time error messages.
532 >It is not possible for the host-side code to send unsolicited messages
533 to the target. If host-side code needs attention from the target, for
534 example because some I/O operation has completed, then an interrupt
541 NAME="SYNTH-NEW-HOST-INTERRUPTS"
546 >The I/O auxiliary provides a number of procedures for interrupt
556 CLASS="PROGRAMLISTING"
557 >synth::interrupt_allocate <name>
558 synth::interrupt_get_max
559 synth::interrupt_get_devicename <vector>
560 synth::interrupt_raise <vector></PRE
567 >synth::interrupt_allocate</B
568 > is normally called during
569 device instantiation, and returns the next free interrupt vector. This
570 can be passed on to the target-side device driver in response to a
571 suitable request, and it can then install an interrupt handler on that
572 vector. Interrupt vector <TT
576 target-side code for the real-time clock, so the allocated vectors
580 >. The argument identifies the
581 device, for example <TT
584 >. This is not actually used
585 internally, but can be accessed by user-initialization scripts that
586 provide some sort of interrupt monitoring facility (typically via the
591 HREF="synth-new-host.html#SYNTH-NEW-HOST-HOOKS"
593 >). It is possible for a
594 single device to allocate multiple interrupt vectors, but the
595 synthetic target supports a maximum of 32 such vectors.
600 >synth::interrupt_get_max</B
601 > returns the highest
602 interrupt vector that has been allocated, or <TT
606 there have been no calls to
609 >synth::interrupt_allocate</B
613 >synth::interrupt_get_devicename</B
615 that was passed to <B
617 >synth::interrupt_allocate</B
619 the vector was allocated.
624 >synth::interrupt_raise</B
625 > can be called any time after
626 initialization. The argument should be the vector returned by
629 >synth::interrupt_allocate</B
630 > for this device. It will
631 activate the normal eCos interrupt handling mechanism so, subject to
632 interrupts being enabled and this particular interrupt not being
633 masked out, the appropriate ISR will run.
642 >At this time it is not possible for a device to allocate a specific
643 interrupt vector. The order in which interrupt vectors are assigned to
644 devices effectively depends on the order in which the eCos devices get
645 initialized, and that may change if the eCos application is rebuilt. A
646 future extension may allow devices to allocate specific vectors, thus
647 making things more deterministic. However that will introduce new
648 problems, in particular the code will have to start worrying about
649 requests for vectors that have already been allocated.
657 NAME="SYNTH-NEW-HOST-ARGS"
660 >Flags and Command Line Arguments</H2
662 >The generic I/O auxiliary code will process the standard command line
663 arguments, and will set various flag variables accordingly. Some of
664 these should be checked by device-specific scripts.
678 >This is set when the I/O auxiliary is operating in graphical mode
679 rather than text mode. Some functionality such as filters and the GUI
680 layout are only available in graphical mode.
689 CLASS="PROGRAMLISTING"
690 > if { $synth::flag_gui } {
700 >synth::flag_verbose</TT
704 >The user has requested additional information during startup. Each
705 device driver can decide how much additional information, if any,
712 >synth::flag_keep_going</TT
716 >The user has specified <TT
723 >, so even if an error occurs the I/O
724 auxiliary and the various device driver scripts should continue running
725 if at all possible. Diagnostics should still be generated.
731 >Some scripts may want to support additional command line arguments.
732 This facility should be used with care since there is no way to
733 prevent two different scripts from trying to use the same argument.
734 The following Tcl procedures are available:
743 CLASS="PROGRAMLISTING"
744 >synth::argv_defined <name>
745 synth::argv_get_value <name></PRE
752 >synth::argv_defined</B
753 > returns a boolean to indicate
754 whether or not a particular argument is present. If the argument is
755 the name part of a name/value pair, an <TT
759 should be appended. Typical uses might be:
768 CLASS="PROGRAMLISTING"
769 > if { [synth::argv_defined "-o13"] } {
773 if { [synth::argv_defined "-mark="] } {
780 >The first call checks for a flag <TT
787 > - the code treats options with single and
788 double hyphens interchangeably. The second call checks for an argument
791 >-mark=<value></TT
795 >-mark <value></TT
796 >. The value part of a
797 name/value pair can be obtained using
800 >synth::argv_get_value</B
810 CLASS="PROGRAMLISTING"
812 if { [synth::argv_defined "-mark="] } {
813 set mark [synth::argv_get_value "-mark="]
814 if { ![string is integer $mark] || ($mark < 1) || ($mark > 9) } {
815 <issue diagnostic>
826 >synth::argv_get_value</B
827 > should only be used after a
828 successful call to <B
830 >synth::argv_defined</B
832 At present there is no support for some advanced forms of command line
833 argument processing. For example it is not possible to repeat a
834 certain option such as <TT
841 >, with each occurrence increasing the level
845 >If a script is going to have its own set of command-line arguments
846 then it should give appropriate details if the user specifies
850 >. This involves a hook function:
859 CLASS="PROGRAMLISTING"
860 >namespace eval my_device {
862 puts " -o13 : activate the omega 13 device"
863 puts " -mark <speed> : set speed. Valid values are 1 to 9."
866 synth::hook_add "help" my_device::help_hook
875 NAME="SYNTH-NEW-HOST-TDF"
878 >The Target Definition File</H2
880 >Most device scripts will want to check entries in the target
881 definition file for run-time configuration information. The Tcl
882 procedures for this are as follows:
891 CLASS="PROGRAMLISTING"
892 >synth::tdf_has_device <name>
893 synth::tdf_get_devices
894 synth::tdf_has_option <devname> <option>
895 synth::tdf_get_option <devname> <option>
896 synth::tdf_get_options <devname> <option>
897 synth::tdf_get_all_options <devname></PRE
904 >synth::tdf_has_device</B
905 > can be used to check whether
906 or not the target definition file had an entry
909 >synth_device <name></TT
911 will match the type of device, so the
915 > script will look for a target
916 definition file entry <TT
922 >synth::tdf_get_devices</B
923 > returns a list of all
924 device entries in the target definition file.
927 >Once it is known that the target definition file has an entry for a
928 certain device, it is possible to check for options within the entry.
931 >synth::tdf_has_option</B
932 > just checks for the presence,
942 CLASS="PROGRAMLISTING"
943 > if { [synth::tdf_has_option "console" "appearance"] } {
952 >synth::tdf_get_option</B
953 > returns a list of all the
954 arguments for a given option. For example, if the target definition
955 file contains an entry:
964 CLASS="PROGRAMLISTING"
965 >synth_device console {
966 appearance -foreground white -background black
967 filter trace {^TRACE:.*} -foreground HotPink1 -hide 1
968 filter xyzzy {.*xyzzy.*} -foreground PapayaWhip
977 >synth::tdf_get_option console appearance</B
979 will return the list <TT
981 >{-foreground white -background
983 >. This list can be manipulated using standard Tcl routines
991 options can occur multiple times in one entry, for example
1001 >synth::tdf_get_options</B
1002 > returns a list of lists,
1003 with one entry for each option occurrence.
1006 >synth::tdf_get_all_options</B
1007 > returns a list of lists
1008 of all options. This time each entry will include the option name as
1012 >The I/O auxiliary will not issue warnings about entries in the target
1013 definition file for devices which were not loaded, unless the
1021 argument was used. This makes it easier to use a single target
1022 definition file for different applications. However the auxiliary will
1023 issue warnings about options within an entry that were ignored,
1024 because often these indicate a typing mistake of some sort. Hence a
1025 script should always call <B
1027 >synth::tdf_has_option</B
1031 >synth:;tdf_get_option</B
1035 >synth::tdf_get_options</B
1036 > for all valid options, even
1037 if some of the options preclude the use of others.
1043 NAME="SYNTH-NEW-HOST-HOOKS"
1048 >Some scripts may want to take action when particular events occur, for
1049 example when the eCos application has exited and there is no need for
1050 further I/O. This is supported using hooks:
1059 CLASS="PROGRAMLISTING"
1060 >namespace eval my_device {
1062 proc handle_ecos_exit { arg_list } {
1065 synth::hook_add "ecos_exit" my_device::handle_ecos_exit
1071 >It is possible for device scripts to add their own hooks and call all
1072 functions registered for those hooks. A typical use for this is by
1073 user initialization scripts that want to monitor some types of I/O.
1074 The available Tcl procedures for manipulating hooks are:
1083 CLASS="PROGRAMLISTING"
1084 >synth::hook_define <name>
1085 synth::hook_defined <name>
1086 synth::hook_add <name> <function>
1087 synth::hook_call <name> <args></PRE
1094 >synth::hook_define</B
1095 > creates a new hook with the
1096 specified name. This hook must not already exist.
1099 >synth::hook_defined</B
1100 > can be used to check for the
1101 existence of a hook. <B
1105 scripts to register a callback function for this hook, and
1108 >synth::hook_call</B
1109 > allows the owner script to invoke
1110 all such callback functions. A hook must already be defined before a
1111 callback can be attached. Therefore typically device scripts will only
1112 use standard hooks and their own hooks, not hooks created by some
1113 other device, because the order of device initialization is not
1114 sufficiently defined. User scripts run from
1118 > can use any hooks that have been
1124 >synth::hook_call</B
1125 > takes an arbitrary list of
1126 arguments, for example:
1135 CLASS="PROGRAMLISTING"
1136 > synth::hook_call "ethernet_rx" "eth0" $packet</PRE
1141 >The callback function will always be invoked with a single argument,
1142 a list of the arguments that were passed to
1145 >synth::hook_call</B
1155 CLASS="PROGRAMLISTING"
1156 > proc rx_callback { arg_list } {
1157 set device [lindex $arg_list 0]
1158 set packet [lindex $arg_list 1]
1164 >Although it might seem more appropriate to use Tcl's
1168 > procedure and have the callback functions
1169 invoked with the right number of arguments rather than a single list,
1170 that would cause serious problems if any of the data contained special
1171 characters such as <TT
1178 current implementation of hooks avoids such problems, at the cost of
1179 minor inconvenience when writing callbacks.
1182 >A number of hooks are defined as standard. Some devices will add
1183 additional hooks, and the device-specific documentation should be
1184 consulted for those. User scripts can add their own hooks if desired.
1189 CLASS="VARIABLELIST"
1198 >This hook is called just before the I/O auxiliary exits. Hence it
1199 provides much the same functionality as <TT
1203 C programs. The argument list passed to the callback function will be
1214 >This hook is called when the eCos application has exited. It is used
1215 mainly to shut down I/O operations: if the application is no longer
1216 running then there is no point in raising interrupts or storing
1217 incoming packets. The callback argument list will be empty.
1223 >ecos_initialized</TT
1227 >The synthetic target HAL will send a request to the I/O auxiliary once
1228 the static constructors have been run. All devices should now have been
1229 instantiated. A script could now check how many instances there are of
1230 a given type of device, for example ethernet devices, and create a
1231 little monitor window showing traffic on all the devices. The
1234 >ecos_initialized</TT
1235 > callbacks will be run just before
1239 > script. The callback
1240 argument list will be empty.
1250 >This hook is also invoked once static constructors have been run, but
1251 only if the user specified <TT
1258 >. Any scripts that add their own command line
1259 arguments should add a callback to this hook which outputs details of
1260 the additional arguments. The callback argument list will be empty.
1270 >Whenever a device calls <B
1272 >synth::interrupt_raise</B
1277 > hook will be called with a single
1278 argument, the interrupt vector. The main use for this is to allow
1279 user scripts to monitor interrupt traffic.
1288 NAME="SYNTH-NEW-HOST-OUTPUT"
1291 >Output and Filters</H2
1293 >Scripts can use conventional facilities for sending text output to the
1294 user, for example calling <B
1298 manipulating the central text widget
1301 >.main.centre.text</TT
1302 >. However in nearly all cases it
1303 is better to use output facilities provided by the I/O auxiliary
1313 CLASS="PROGRAMLISTING"
1314 >synth::report <msg>
1315 synth::report_warning <msg>
1316 synth::report_error <msg>
1317 synth::internal_error <msg>
1318 synth::output <msg> <filter></PRE
1326 > is intended for messages related to
1327 the operation of the I/O auxiliary itself, especially additional
1328 output resulting from <TT
1335 >. If running in text mode the output will go
1336 to standard output. If running in graphical mode the output will go to
1337 the central text window. In both modes, use of <TT
1344 > will modify the behaviour.
1349 >synth::report_warning</B
1353 >synth::report_error</B
1357 >synth::internal_error</B
1358 > have the obvious meaning,
1359 including prepending strings such as <TT
1366 >. When the eCos application informs the I/O
1367 auxiliary that all static constructors have run, if at that point
1368 there have been any calls to <B
1372 I/O auxiliary will exit. This can be suppressed with command line
1382 >synth::internal_error</B
1383 > will output some information
1384 about the current state of the I/O auxiliary and then exit
1385 immediately. Of course it should never be necessary to call this
1392 > is the main routine for outputting
1393 text. The second argument identifies a filter. If running in text mode
1394 the filter is ignored, but if running in graphical mode the filter can
1395 be used to control the appearance of this output. A typical use would
1405 CLASS="PROGRAMLISTING"
1406 > synth::output $line "console"</PRE
1411 >This outputs a single line of text using the
1415 > filter. If running in graphical mode the
1416 default appearance of this text can be modified with the
1423 >synth_device console</B
1424 > entry of the target
1425 definition file. The <SPAN
1427 >System filters</SPAN
1429 option can be used to change the appearance at run-time.
1432 >Filters should be created before they are used. The procedures
1433 available for this are:
1442 CLASS="PROGRAMLISTING"
1443 >synth::filter_exists <name>
1444 synth::filter_get_list
1445 synth::filter_add <name> [options]
1446 synth::filter_parse_options <options> <parsed_options> <message>
1447 synth::filter_add_parsed <name> <parsed_options></PRE
1454 >synth::filter_exists</B
1455 > can be used to check whether
1456 or not a particular filter already exists: creating two filters with
1457 the same name is not allowed.
1460 >synth::filter_get_list</B
1461 > returns a list of the
1462 current known filters. <B
1464 >synth::filter_add</B
1466 used to create a new filter. The first argument names the new filter,
1467 and the remaining arguments control the initial appearance. A typical
1477 CLASS="PROGRAMLISTING"
1478 > synth::filter_add "my_device_tx" -foreground yellow -hide 1</PRE
1483 >It is assumed that the supplied arguments are valid, which typically
1484 means that they are hard-wired in the script. If instead the data
1485 comes out of a configuration file and hence may be invalid, the
1486 I/O auxiliary provides a parsing utility. Typical usage would be:
1495 CLASS="PROGRAMLISTING"
1496 > array set parsed_options [list]
1498 if { ![synth::filter_parse_options $console_appearance parsed_options message] } {
1499 synth::report_error \
1500 "Invalid entry in target definition file $synth::target_definition\
1501 \n synth_device \"console\", entry \"appearance\"\n$message"
1503 synth::filter_add_parsed "console" parsed_options
1512 > will be updated with an
1513 internal representation of the desired appearance, which can then be
1514 used in a call to <B
1516 >synth::filter_add_parsed</B
1521 > will be updated with details of the
1522 parsing error that occurred.
1528 NAME="SYNTH-NEW-HOST-GUI"
1531 >The Graphical Interface</H2
1533 >When the I/O auxiliary is running in graphical mode, many scripts will
1534 want to update the user interface in some way. This may be as simple
1535 as adding another entry to the help menu for the device, or adding a
1536 new button to the toolbar. It may also involve adding new subwindows,
1537 or even creating entire new toplevel windows. These may be simple
1538 monitor windows, displaying additional information about what is going
1539 on in the system in a graphical format. Alternatively they may emulate
1540 actual I/O operations, for example button widgets could be used to
1541 emulate real physical buttons.
1544 >The I/O auxiliary does not provide many procedures related to the
1545 graphical interface. Instead it is expected that scripts will just
1546 update the widget hierarchy directly.
1549 CLASS="INFORMALFIGURE"
1564 >So adding a new item to the <SPAN
1570 >.menubar.help add</B
1571 > operation with suitable
1572 arguments. Adding a new button to the toolbar involves creating a
1577 appropriately. Scripts can create their own subwindows and then pack
1606 >. Normally the user should be allowed to
1608 HREF="synth-gui.html#SYNTH-GUI-LAYOUT"
1610 > this via the target
1611 definition file. The central window <TT
1615 should normally be left alone by other scripts since it gets used for
1619 >The following graphics-related utilities may be found useful:
1628 CLASS="PROGRAMLISTING"
1629 >synth::load_image <image name> <filename>
1630 synth::register_ballon_help <widget> <message>
1631 synth::handle_help <URL></PRE
1638 >synth::load_image</B
1639 > can be used to add a new image to
1640 the current interpreter. If the specified file has a
1644 > extension then the image will be a
1645 monochrome bitmap, otherwise it will be a colour image of some sort.
1646 A boolean will be returned to indicate success or failure, and
1647 suitable diagnostics will be generated if necessary.
1652 >synth::register_balloon_help</B
1653 > provides balloon help
1654 for a specific widget, usually a button on the toolbar.
1659 >synth::handle_help</B
1660 > is a utility routine that can be
1661 installed as the command for displaying online help, for example:
1670 CLASS="PROGRAMLISTING"
1671 > .menubar.help add command -label "my device" -command \
1672 [list synth::handle_help "file://$path"]</PRE
1682 SUMMARY="Footer navigation table"
1693 HREF="synth-new-target.html"
1702 HREF="ecos-ref.html"
1711 HREF="synth-porting.html"
1721 >Writing New Devices - target</TD
1727 HREF="hal-synth-arch.html"