]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - doc/html/ref/synth-new-host.html
RedBoot TX53 Release 2012-02-15
[karo-tx-redboot.git] / doc / html / ref / synth-new-host.html
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.               -->
9 <HTML
10 ><HEAD
11 ><TITLE
12 >Writing New Devices - host</TITLE
13 ><meta name="MSSmartTagsPreventParsing" content="TRUE">
14 <META
15 NAME="GENERATOR"
16 CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+
17 "><LINK
18 REL="HOME"
19 TITLE="eCos Reference Manual"
20 HREF="ecos-ref.html"><LINK
21 REL="UP"
22 TITLE="eCos Synthetic Target"
23 HREF="hal-synth-arch.html"><LINK
24 REL="PREVIOUS"
25 TITLE="Writing New Devices - target"
26 HREF="synth-new-target.html"><LINK
27 REL="NEXT"
28 TITLE="Porting"
29 HREF="synth-porting.html"></HEAD
30 ><BODY
31 CLASS="REFENTRY"
32 BGCOLOR="#FFFFFF"
33 TEXT="#000000"
34 LINK="#0000FF"
35 VLINK="#840084"
36 ALINK="#0000FF"
37 ><DIV
38 CLASS="NAVHEADER"
39 ><TABLE
40 SUMMARY="Header navigation table"
41 WIDTH="100%"
42 BORDER="0"
43 CELLPADDING="0"
44 CELLSPACING="0"
45 ><TR
46 ><TH
47 COLSPAN="3"
48 ALIGN="center"
49 >eCos Reference Manual</TH
50 ></TR
51 ><TR
52 ><TD
53 WIDTH="10%"
54 ALIGN="left"
55 VALIGN="bottom"
56 ><A
57 HREF="synth-new-target.html"
58 ACCESSKEY="P"
59 >Prev</A
60 ></TD
61 ><TD
62 WIDTH="80%"
63 ALIGN="center"
64 VALIGN="bottom"
65 ></TD
66 ><TD
67 WIDTH="10%"
68 ALIGN="right"
69 VALIGN="bottom"
70 ><A
71 HREF="synth-porting.html"
72 ACCESSKEY="N"
73 >Next</A
74 ></TD
75 ></TR
76 ></TABLE
77 ><HR
78 ALIGN="LEFT"
79 WIDTH="100%"></DIV
80 ><H1
81 ><A
82 NAME="SYNTH-NEW-HOST">Writing New Devices - host</H1
83 ><DIV
84 CLASS="REFNAMEDIV"
85 ><A
86 NAME="AEN18382"
87 ></A
88 ><H2
89 >Name</H2
90 >Writing New Devices&nbsp;--&nbsp;extending the synthetic target, host-side</DIV
91 ><DIV
92 CLASS="REFSECT1"
93 ><A
94 NAME="SYNTH-NEW-HOST-DESCRIPTION"
95 ></A
96 ><H2
97 >Description</H2
98 ><P
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
105 support.
106     </P
107 ><P
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
118 CLASS="FUNCTION"
119 >ioctl</TT
120 >
121 calls, which is easier to do in a C program. Therefore the
122 <TT
123 CLASS="FILENAME"
124 >ethernet.tcl</TT
125 > script which implements the
126 host-side ethernet support spawns a separate program
127 <TT
128 CLASS="FILENAME"
129 >rawether</TT
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
133 CLASS="FILENAME"
134 >rawether</TT
135 >
136 with such privileges is somewhat less of a security risk than the
137 whole eCos application, the I/O auxiliary, and various dynamically
138 loaded Tcl scripts.
139     </P
140 ><P
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
145 CLASS="FILENAME"
146 >ethernet.tcl</TT
147 > script
148 creates a namespace <TT
149 CLASS="VARNAME"
150 >ethernet::</TT
151 > and all variables
152 and procedures reside in this namespace. Similarly the I/O auxiliary
153 itself makes use of a <TT
154 CLASS="VARNAME"
155 >synth::</TT
156 > namespace.
157     </P
158 ></DIV
159 ><DIV
160 CLASS="REFSECT1"
161 ><A
162 NAME="SYNTH-NEW-HOST-BUILD"
163 ></A
164 ><H2
165 >Building and Installation</H2
166 ><P
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
170 CLASS="FUNCTION"
171 >synth_auxiliary_instantiate</TT
172 >
173 specifies the type of device, for example <TT
174 CLASS="LITERAL"
175 >ethernet</TT
176 >,
177 and the I/O auxiliary will append a <TT
178 CLASS="FILENAME"
179 >.tcl</TT
180 > suffix
181 and look for a script <TT
182 CLASS="FILENAME"
183 >ethernet.tcl</TT
184 >.
185     </P
186 ><P
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
190 CLASS="FILENAME"
191 >~/.ecos/synth</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
195 CLASS="FILENAME"
196 >libexec/ecos</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
200 <TT
201 CLASS="FILENAME"
202 >libexec/ecos</TT
203 > matches the
204 structure of the eCos repository, allowing multiple versions of a
205 package to be installed to allow for incompatible protocol changes.
206     </P
207 ><P
208 >The preferred way to build host-side software is to use
209 <B
210 CLASS="COMMAND"
211 >autoconf</B
212 > and <B
213 CLASS="COMMAND"
214 >automake</B
215 >. Usually
216 this involves little more than copying the
217 <TT
218 CLASS="FILENAME"
219 >acinclude.m4</TT
220 >, <TT
221 CLASS="FILENAME"
222 >configure.in</TT
223 >
224 and <TT
225 CLASS="FILENAME"
226 >Makefile.am</TT
227 > files from an existing package,
228 for example the synthetic target ethernet driver, and then making
229 minor edits. In <TT
230 CLASS="FILENAME"
231 >acinclude.m4</TT
232 > it may be necessary
233 to adjust the path to the root of the repository.
234 <TT
235 CLASS="FILENAME"
236 >configure.in</TT
237 > may require a similar change, and
238 the <TT
239 CLASS="FUNCTION"
240 >AC_INIT</TT
241 > macro invocation will have to be
242 changed to match one of the files in the new package. A critical macro
243 in this file is <TT
244 CLASS="FILENAME"
245 >ECOS_PACKAGE_DIRS</TT
246 > which will set
247 up the correct install directory. <TT
248 CLASS="FILENAME"
249 >Makefile.am</TT
250 > may
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
254 CLASS="COMMAND"
255 >aclocal</B
256 >,
257 <B
258 CLASS="COMMAND"
259 >autoconf</B
260 > and <B
261 CLASS="COMMAND"
262 >automake</B
263 > in that
264 order. Actually building the software then just involves
265 <B
266 CLASS="COMMAND"
267 >configure</B
268 >, <B
269 CLASS="COMMAND"
270 >make</B
271 > and
272 <B
273 CLASS="COMMAND"
274 >make install</B
275 >, as per the instructions in the
276 toplevel <TT
277 CLASS="FILENAME"
278 >README.host</TT
279 > file.
280     </P
281 ><P
282 >To assist developers, if the environment variable
283 <TT
284 CLASS="ENVAR"
285 >ECOSYNTH_DEVEL</TT
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
292 CLASS="COMMAND"
293 >make
294 install</B
295 > all the time.
296     </P
297 ><P
298 >If a script needs to know where it has been installed it can examine
299 the Tcl variable <TT
300 CLASS="VARNAME"
301 >synth::device_install_dir</TT
302 > . This
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
305 variable. 
306     </P
307 ></DIV
308 ><DIV
309 CLASS="REFSECT1"
310 ><A
311 NAME="SYNTH-NEW-HOST-INSTANTIATION"
312 ></A
313 ><H2
314 >Instantiation</H2
315 ><P
316 >The I/O auxiliary will <B
317 CLASS="COMMAND"
318 >source</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.
323     </P
324 ><TABLE
325 BORDER="5"
326 BGCOLOR="#E0E0F0"
327 WIDTH="70%"
328 ><TR
329 ><TD
330 ><PRE
331 CLASS="PROGRAMLISTING"
332 >namespace eval ethernet {
333     &#8230;
334     proc instantiate { id instance data } {
335         &#8230;
336         return ethernet::handle_request
337     }
338 }
339 return ethernet::instantiate</PRE
340 ></TD
341 ></TR
342 ></TABLE
343 ><P
344 >The <TT
345 CLASS="VARNAME"
346 >id</TT
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
350 <TT
351 CLASS="FUNCTION"
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
356 CLASS="VARNAME"
357 >instance</TT
358 > and
359 <TT
360 CLASS="VARNAME"
361 >data</TT
362 > arguments match the corresponding arguments to
363 <TT
364 CLASS="FUNCTION"
365 >synth_auxiliary_instantiate</TT
366 > on the target side, so
367 a typical value for <TT
368 CLASS="VARNAME"
369 >instance</TT
370 > would be
371 <TT
372 CLASS="LITERAL"
373 >eth0</TT
374 >, and <TT
375 CLASS="VARNAME"
376 >data</TT
377 > is used to pass
378 arbitrary initialization parameters from target to host.
379     </P
380 ><P
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"
384 >interrupt vector</A
385 >, adding a
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
389 the above.
390     </P
391 ><P
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
395 <TT
396 CLASS="FUNCTION"
397 >synth_auxiliary_instantiate</TT
398 > call will return
399 <TT
400 CLASS="LITERAL"
401 >-1</TT
402 >. The script is responsible for providing
403 <A
404 HREF="synth-new-host.html#SYNTH-NEW-HOST-OUTPUT"
405 >diagnostics</A
406 > explaining
407 why the device could not be instantiated.
408     </P
409 ></DIV
410 ><DIV
411 CLASS="REFSECT1"
412 ><A
413 NAME="SYNTH-NEW-HOST-REQUESTS"
414 ></A
415 ><H2
416 >Handling Requests</H2
417 ><P
418 >When the target-side calls
419 <TT
420 CLASS="FUNCTION"
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:
425     </P
426 ><TABLE
427 BORDER="5"
428 BGCOLOR="#E0E0F0"
429 WIDTH="70%"
430 ><TR
431 ><TD
432 ><PRE
433 CLASS="PROGRAMLISTING"
434 >namespace eval ethernet {
435     &#8230;
436     proc handle_request { id request arg1 arg2 txdata txlen max_rxlen } {
437         &#8230;
438         if { &lt;some condition&gt; } {
439             synth::send_reply &lt;error code&gt; 0 ""
440             return
441         }
442         &#8230;
443         synth::send_reply &lt;reply code&gt; $packet_len $packet
444     }
445     &#8230;
446 }</PRE
447 ></TD
448 ></TR
449 ></TABLE
450 ><P
451 >The <TT
452 CLASS="VARNAME"
453 >id</TT
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
457 CLASS="VARNAME"
458 >request</TT
459 >,
460 <TT
461 CLASS="VARNAME"
462 >arg1</TT
463 >, <TT
464 CLASS="VARNAME"
465 >arg2</TT
466 >, and
467 <TT
468 CLASS="VARNAME"
469 >max_rxlen</TT
470 > are the same values that were passed to
471 <TT
472 CLASS="FUNCTION"
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
477 CLASS="VARNAME"
478 >txdata</TT
479 > buffer is raw data
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
482 <B
483 CLASS="COMMAND"
484 >binary scan</B
485 >, <B
486 CLASS="COMMAND"
487 >string index</B
488 > and
489 <B
490 CLASS="COMMAND"
491 >string range</B
492 > may be found especially useful when
493 manipulating this buffer. <TT
494 CLASS="VARNAME"
495 >txlen</TT
496 > is provided for
497 convenience, although <B
498 CLASS="COMMAND"
499 >string length $txdata</B
500 > would
501 give the same information.
502     </P
503 ><P
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
508 CLASS="COMMAND"
509 >synth::send_reply</B
510 >. The
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
515 CLASS="COMMAND"
516 >binary format</B
517 >
518 may prove useful. If the reply involves just a code and no additional
519 data, the second and third arguments should be <TT
520 CLASS="LITERAL"
521 >0</TT
522 >
523 and an empty string respectively.
524     </P
525 ><P
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.
530     </P
531 ><P
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
535 should be raised.
536     </P
537 ></DIV
538 ><DIV
539 CLASS="REFSECT1"
540 ><A
541 NAME="SYNTH-NEW-HOST-INTERRUPTS"
542 ></A
543 ><H2
544 >Interrupts</H2
545 ><P
546 >The I/O auxiliary provides a number of procedures for interrupt
547 handling. 
548     </P
549 ><TABLE
550 BORDER="5"
551 BGCOLOR="#E0E0F0"
552 WIDTH="70%"
553 ><TR
554 ><TD
555 ><PRE
556 CLASS="PROGRAMLISTING"
557 >synth::interrupt_allocate &lt;name&gt;
558 synth::interrupt_get_max
559 synth::interrupt_get_devicename &lt;vector&gt;
560 synth::interrupt_raise &lt;vector&gt;</PRE
561 ></TD
562 ></TR
563 ></TABLE
564 ><P
565 ><B
566 CLASS="COMMAND"
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
573 CLASS="LITERAL"
574 >0</TT
575 > is used within the
576 target-side code for the real-time clock, so the allocated vectors
577 will start at <TT
578 CLASS="LITERAL"
579 >1</TT
580 >. The argument identifies the
581 device, for example <TT
582 CLASS="LITERAL"
583 >eth0</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
587 <TT
588 CLASS="LITERAL"
589 >interrupt</TT
590 > <A
591 HREF="synth-new-host.html#SYNTH-NEW-HOST-HOOKS"
592 >hook</A
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.
596     </P
597 ><P
598 ><B
599 CLASS="COMMAND"
600 >synth::interrupt_get_max</B
601 > returns the highest
602 interrupt vector that has been allocated, or <TT
603 CLASS="LITERAL"
604 >0</TT
605 > if
606 there have been no calls to
607 <B
608 CLASS="COMMAND"
609 >synth::interrupt_allocate</B
610 >.
611 <B
612 CLASS="COMMAND"
613 >synth::interrupt_get_devicename</B
614 > returns the string
615 that was passed to <B
616 CLASS="COMMAND"
617 >synth::interrupt_allocate</B
618 > when
619 the vector was allocated.
620     </P
621 ><P
622 ><B
623 CLASS="COMMAND"
624 >synth::interrupt_raise</B
625 > can be called any time after
626 initialization. The argument should be the vector returned by
627 <B
628 CLASS="COMMAND"
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.
634     </P
635 ><DIV
636 CLASS="NOTE"
637 ><BLOCKQUOTE
638 CLASS="NOTE"
639 ><P
640 ><B
641 >Note: </B
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.
650     </P
651 ></BLOCKQUOTE
652 ></DIV
653 ></DIV
654 ><DIV
655 CLASS="REFSECT1"
656 ><A
657 NAME="SYNTH-NEW-HOST-ARGS"
658 ></A
659 ><H2
660 >Flags and Command Line Arguments</H2
661 ><P
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.
665     </P
666 ><P
667 ></P
668 ><DIV
669 CLASS="VARIABLELIST"
670 ><DL
671 ><DT
672 ><TT
673 CLASS="VARNAME"
674 >synth::flag_gui</TT
675 ></DT
676 ><DD
677 ><P
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.
681         </P
682 ><TABLE
683 BORDER="5"
684 BGCOLOR="#E0E0F0"
685 WIDTH="70%"
686 ><TR
687 ><TD
688 ><PRE
689 CLASS="PROGRAMLISTING"
690 >    if { $synth::flag_gui } {
691         &#8230;
692     }</PRE
693 ></TD
694 ></TR
695 ></TABLE
696 ></DD
697 ><DT
698 ><TT
699 CLASS="VARNAME"
700 >synth::flag_verbose</TT
701 ></DT
702 ><DD
703 ><P
704 >The user has requested additional information during startup. Each
705 device driver can decide how much additional information, if any,
706 should be produced.
707          </P
708 ></DD
709 ><DT
710 ><TT
711 CLASS="VARNAME"
712 >synth::flag_keep_going</TT
713 ></DT
714 ><DD
715 ><P
716 >The user has specified <TT
717 CLASS="OPTION"
718 >-k</TT
719 > or
720 <TT
721 CLASS="OPTION"
722 >--keep-going</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.
726         </P
727 ></DD
728 ></DL
729 ></DIV
730 ><P
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:
735     </P
736 ><TABLE
737 BORDER="5"
738 BGCOLOR="#E0E0F0"
739 WIDTH="70%"
740 ><TR
741 ><TD
742 ><PRE
743 CLASS="PROGRAMLISTING"
744 >synth::argv_defined &lt;name&gt;
745 synth::argv_get_value &lt;name&gt;</PRE
746 ></TD
747 ></TR
748 ></TABLE
749 ><P
750 ><B
751 CLASS="COMMAND"
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
756 CLASS="LITERAL"
757 >=</TT
758 > character
759 should be appended. Typical uses might be:
760     </P
761 ><TABLE
762 BORDER="5"
763 BGCOLOR="#E0E0F0"
764 WIDTH="70%"
765 ><TR
766 ><TD
767 ><PRE
768 CLASS="PROGRAMLISTING"
769 >    if { [synth::argv_defined "-o13"] } {
770         &#8230;
771     }
772
773     if { [synth::argv_defined "-mark="] } {
774         &#8230;
775     }</PRE
776 ></TD
777 ></TR
778 ></TABLE
779 ><P
780 >The first call checks for a flag <TT
781 CLASS="LITERAL"
782 >-o13</TT
783 > or
784 <TT
785 CLASS="LITERAL"
786 >--o13</TT
787 > - the code treats options with single and
788 double hyphens interchangeably. The second call checks for an argument
789 of the form <TT
790 CLASS="LITERAL"
791 >-mark=&lt;value&gt;</TT
792 > or a pair of
793 arguments <TT
794 CLASS="LITERAL"
795 >-mark &lt;value&gt;</TT
796 >. The value part of a
797 name/value pair can be obtained using
798 <B
799 CLASS="COMMAND"
800 >synth::argv_get_value</B
801 >;
802     </P
803 ><TABLE
804 BORDER="5"
805 BGCOLOR="#E0E0F0"
806 WIDTH="70%"
807 ><TR
808 ><TD
809 ><PRE
810 CLASS="PROGRAMLISTING"
811 >    variable speed 1
812     if { [synth::argv_defined "-mark="] } {
813         set mark [synth::argv_get_value "-mark="]
814         if { ![string is integer $mark] || ($mark &#60; 1) || ($mark &#62; 9) } {
815             &lt;issue diagnostic&gt;
816         } else {
817             set speed $mark
818         }
819     }</PRE
820 ></TD
821 ></TR
822 ></TABLE
823 ><P
824 ><B
825 CLASS="COMMAND"
826 >synth::argv_get_value</B
827 > should only be used after a
828 successful call to <B
829 CLASS="COMMAND"
830 >synth::argv_defined</B
831 >.
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
835 CLASS="OPTION"
836 >-v</TT
837 > or
838 <TT
839 CLASS="OPTION"
840 >--verbose</TT
841 >, with each occurrence increasing the level
842 of verbosity. 
843     </P
844 ><P
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
847 <TT
848 CLASS="OPTION"
849 >--help</TT
850 >. This involves a hook function:
851     </P
852 ><TABLE
853 BORDER="5"
854 BGCOLOR="#E0E0F0"
855 WIDTH="70%"
856 ><TR
857 ><TD
858 ><PRE
859 CLASS="PROGRAMLISTING"
860 >namespace eval my_device {
861     proc help_hook { } {
862         puts " -o13          : activate the omega 13 device"
863         puts " -mark &lt;speed&gt; : set speed. Valid values are 1 to 9."
864     }
865
866     synth::hook_add "help" my_device::help_hook
867 }</PRE
868 ></TD
869 ></TR
870 ></TABLE
871 ></DIV
872 ><DIV
873 CLASS="REFSECT1"
874 ><A
875 NAME="SYNTH-NEW-HOST-TDF"
876 ></A
877 ><H2
878 >The Target Definition File</H2
879 ><P
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:
883     </P
884 ><TABLE
885 BORDER="5"
886 BGCOLOR="#E0E0F0"
887 WIDTH="70%"
888 ><TR
889 ><TD
890 ><PRE
891 CLASS="PROGRAMLISTING"
892 >synth::tdf_has_device &lt;name&gt;
893 synth::tdf_get_devices
894 synth::tdf_has_option &lt;devname&gt; &lt;option&gt;
895 synth::tdf_get_option &lt;devname&gt; &lt;option&gt;
896 synth::tdf_get_options &lt;devname&gt; &lt;option&gt;
897 synth::tdf_get_all_options &lt;devname&gt;</PRE
898 ></TD
899 ></TR
900 ></TABLE
901 ><P
902 ><B
903 CLASS="COMMAND"
904 >synth::tdf_has_device</B
905 > can be used to check whether
906 or not the target definition file had an entry
907 <TT
908 CLASS="LITERAL"
909 >synth_device&nbsp;&lt;name&gt;</TT
910 >. Usually the name
911 will match the type of device, so the
912 <TT
913 CLASS="FILENAME"
914 >console.tcl</TT
915 > script will look for a target
916 definition file entry <TT
917 CLASS="LITERAL"
918 >console</TT
919 >.
920 <B
921 CLASS="COMMAND"
922 >synth::tdf_get_devices</B
923 > returns a list of all
924 device entries in the target definition file.
925     </P
926 ><P
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.
929 <B
930 CLASS="COMMAND"
931 >synth::tdf_has_option</B
932 > just checks for the presence,
933 returning a boolean:
934     </P
935 ><TABLE
936 BORDER="5"
937 BGCOLOR="#E0E0F0"
938 WIDTH="70%"
939 ><TR
940 ><TD
941 ><PRE
942 CLASS="PROGRAMLISTING"
943 >    if { [synth::tdf_has_option "console" "appearance"] } {
944         &#8230;
945     }</PRE
946 ></TD
947 ></TR
948 ></TABLE
949 ><P
950 ><B
951 CLASS="COMMAND"
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:
956     </P
957 ><TABLE
958 BORDER="5"
959 BGCOLOR="#E0E0F0"
960 WIDTH="70%"
961 ><TR
962 ><TD
963 ><PRE
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
969 }</PRE
970 ></TD
971 ></TR
972 ></TABLE
973 ><P
974 >A call
975 <B
976 CLASS="COMMAND"
977 >synth::tdf_get_option&nbsp;console&nbsp;appearance</B
978 >
979 will return the list <TT
980 CLASS="LITERAL"
981 >{-foreground white -background
982 black}</TT
983 >. This list can be manipulated using standard Tcl routines
984 such as <B
985 CLASS="COMMAND"
986 >llength</B
987 > and <B
988 CLASS="COMMAND"
989 >lindex</B
990 >. Some
991 options can occur multiple times in one entry, for example
992 <TT
993 CLASS="OPTION"
994 >filter</TT
995 > in the <TT
996 CLASS="LITERAL"
997 >console</TT
998 > entry.
999 <B
1000 CLASS="COMMAND"
1001 >synth::tdf_get_options</B
1002 > returns a list of lists,
1003 with one entry for each option occurrence.
1004 <B
1005 CLASS="COMMAND"
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
1009 well.
1010     </P
1011 ><P
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
1014 <TT
1015 CLASS="OPTION"
1016 >-v</TT
1017 > or <TT
1018 CLASS="OPTION"
1019 >--verbose</TT
1020 > command line
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
1026 CLASS="COMMAND"
1027 >synth::tdf_has_option</B
1028 >,
1029 <B
1030 CLASS="COMMAND"
1031 >synth:;tdf_get_option</B
1032 > or
1033 <B
1034 CLASS="COMMAND"
1035 >synth::tdf_get_options</B
1036 > for all valid options, even
1037 if some of the options preclude the use of others.
1038     </P
1039 ></DIV
1040 ><DIV
1041 CLASS="REFSECT1"
1042 ><A
1043 NAME="SYNTH-NEW-HOST-HOOKS"
1044 ></A
1045 ><H2
1046 >Hooks</H2
1047 ><P
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:
1051     </P
1052 ><TABLE
1053 BORDER="5"
1054 BGCOLOR="#E0E0F0"
1055 WIDTH="70%"
1056 ><TR
1057 ><TD
1058 ><PRE
1059 CLASS="PROGRAMLISTING"
1060 >namespace eval my_device {
1061     &#8230;
1062     proc handle_ecos_exit { arg_list } {
1063         &#8230;
1064     }
1065     synth::hook_add "ecos_exit" my_device::handle_ecos_exit
1066 }</PRE
1067 ></TD
1068 ></TR
1069 ></TABLE
1070 ><P
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:
1075     </P
1076 ><TABLE
1077 BORDER="5"
1078 BGCOLOR="#E0E0F0"
1079 WIDTH="70%"
1080 ><TR
1081 ><TD
1082 ><PRE
1083 CLASS="PROGRAMLISTING"
1084 >synth::hook_define &lt;name&gt;
1085 synth::hook_defined &lt;name&gt;
1086 synth::hook_add &lt;name&gt; &lt;function&gt;
1087 synth::hook_call &lt;name&gt; &lt;args&gt;</PRE
1088 ></TD
1089 ></TR
1090 ></TABLE
1091 ><P
1092 ><B
1093 CLASS="COMMAND"
1094 >synth::hook_define</B
1095 > creates a new hook with the
1096 specified name. This hook must not already exist.
1097 <B
1098 CLASS="COMMAND"
1099 >synth::hook_defined</B
1100 > can be used to check for the
1101 existence of a hook. <B
1102 CLASS="COMMAND"
1103 >synth::hook_add</B
1104 > allows other
1105 scripts to register a callback function for this hook, and
1106 <B
1107 CLASS="COMMAND"
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
1115 <TT
1116 CLASS="FILENAME"
1117 >mainrc.tcl</TT
1118 > can use any hooks that have been
1119 defined.
1120     </P
1121 ><P
1122 ><B
1123 CLASS="COMMAND"
1124 >synth::hook_call</B
1125 > takes an arbitrary list of
1126 arguments, for example:
1127     </P
1128 ><TABLE
1129 BORDER="5"
1130 BGCOLOR="#E0E0F0"
1131 WIDTH="70%"
1132 ><TR
1133 ><TD
1134 ><PRE
1135 CLASS="PROGRAMLISTING"
1136 >    synth::hook_call "ethernet_rx" "eth0" $packet</PRE
1137 ></TD
1138 ></TR
1139 ></TABLE
1140 ><P
1141 >The callback function will always be invoked with a single argument,
1142 a list of the arguments that were passed to
1143 <B
1144 CLASS="COMMAND"
1145 >synth::hook_call</B
1146 >: 
1147     </P
1148 ><TABLE
1149 BORDER="5"
1150 BGCOLOR="#E0E0F0"
1151 WIDTH="70%"
1152 ><TR
1153 ><TD
1154 ><PRE
1155 CLASS="PROGRAMLISTING"
1156 >    proc rx_callback { arg_list } {
1157         set device [lindex $arg_list 0]
1158         set packet [lindex $arg_list 1]
1159     }</PRE
1160 ></TD
1161 ></TR
1162 ></TABLE
1163 ><P
1164 >Although it might seem more appropriate to use Tcl's
1165 <B
1166 CLASS="COMMAND"
1167 >eval</B
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
1172 CLASS="LITERAL"
1173 >[</TT
1174 > or <TT
1175 CLASS="LITERAL"
1176 >$</TT
1177 >. The
1178 current implementation of hooks avoids such problems, at the cost of
1179 minor inconvenience when writing callbacks.
1180     </P
1181 ><P
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.
1185     </P
1186 ><P
1187 ></P
1188 ><DIV
1189 CLASS="VARIABLELIST"
1190 ><DL
1191 ><DT
1192 ><TT
1193 CLASS="LITERAL"
1194 >exit</TT
1195 ></DT
1196 ><DD
1197 ><P
1198 >This hook is called just before the I/O auxiliary exits. Hence it
1199 provides much the same functionality as <TT
1200 CLASS="FUNCTION"
1201 >atexit</TT
1202 > in
1203 C programs. The argument list passed to the callback function will be
1204 empty. 
1205         </P
1206 ></DD
1207 ><DT
1208 ><TT
1209 CLASS="LITERAL"
1210 >ecos_exit</TT
1211 ></DT
1212 ><DD
1213 ><P
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.
1218         </P
1219 ></DD
1220 ><DT
1221 ><TT
1222 CLASS="LITERAL"
1223 >ecos_initialized</TT
1224 ></DT
1225 ><DD
1226 ><P
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
1232 <TT
1233 CLASS="LITERAL"
1234 >ecos_initialized</TT
1235 > callbacks will be run just before
1236 the user's <TT
1237 CLASS="FILENAME"
1238 >mainrc.tcl</TT
1239 > script. The callback
1240 argument list will be empty.
1241         </P
1242 ></DD
1243 ><DT
1244 ><TT
1245 CLASS="LITERAL"
1246 >help</TT
1247 ></DT
1248 ><DD
1249 ><P
1250 >This hook is also invoked once static constructors have been run, but
1251 only if the user specified <TT
1252 CLASS="OPTION"
1253 >-h</TT
1254 > or
1255 <TT
1256 CLASS="OPTION"
1257 >--help</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.
1261         </P
1262 ></DD
1263 ><DT
1264 ><TT
1265 CLASS="LITERAL"
1266 >interrupt</TT
1267 ></DT
1268 ><DD
1269 ><P
1270 >Whenever a device calls <B
1271 CLASS="COMMAND"
1272 >synth::interrupt_raise</B
1273 > the
1274 <TT
1275 CLASS="LITERAL"
1276 >interrupt</TT
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.
1280         </P
1281 ></DD
1282 ></DL
1283 ></DIV
1284 ></DIV
1285 ><DIV
1286 CLASS="REFSECT1"
1287 ><A
1288 NAME="SYNTH-NEW-HOST-OUTPUT"
1289 ></A
1290 ><H2
1291 >Output and Filters</H2
1292 ><P
1293 >Scripts can use conventional facilities for sending text output to the
1294 user, for example calling <B
1295 CLASS="COMMAND"
1296 >puts</B
1297 > or directly
1298 manipulating the central text widget
1299 <TT
1300 CLASS="VARNAME"
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
1304 itself: 
1305     </P
1306 ><TABLE
1307 BORDER="5"
1308 BGCOLOR="#E0E0F0"
1309 WIDTH="70%"
1310 ><TR
1311 ><TD
1312 ><PRE
1313 CLASS="PROGRAMLISTING"
1314 >synth::report &lt;msg&gt;
1315 synth::report_warning &lt;msg&gt;
1316 synth::report_error &lt;msg&gt;
1317 synth::internal_error &lt;msg&gt;
1318 synth::output &lt;msg&gt; &lt;filter&gt;</PRE
1319 ></TD
1320 ></TR
1321 ></TABLE
1322 ><P
1323 ><B
1324 CLASS="COMMAND"
1325 >synth::report</B
1326 > is intended for messages related to
1327 the operation of the I/O auxiliary itself, especially additional
1328 output resulting from <TT
1329 CLASS="OPTION"
1330 >-v</TT
1331 > or
1332 <TT
1333 CLASS="OPTION"
1334 >--verbose</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
1338 CLASS="OPTION"
1339 >-l</TT
1340 > or
1341 <TT
1342 CLASS="OPTION"
1343 >--logfile</TT
1344 > will modify the behaviour.
1345     </P
1346 ><P
1347 ><B
1348 CLASS="COMMAND"
1349 >synth::report_warning</B
1350 >,
1351 <B
1352 CLASS="COMMAND"
1353 >synth::report_error</B
1354 > and
1355 <B
1356 CLASS="COMMAND"
1357 >synth::internal_error</B
1358 > have the obvious meaning,
1359 including prepending strings such as <TT
1360 CLASS="LITERAL"
1361 >Warning:</TT
1362 > and
1363 <TT
1364 CLASS="LITERAL"
1365 >Error:</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
1369 CLASS="COMMAND"
1370 >synth::error</B
1371 > then the
1372 I/O auxiliary will exit. This can be suppressed with command line
1373 arguments <TT
1374 CLASS="OPTION"
1375 >-k</TT
1376 > or <TT
1377 CLASS="OPTION"
1378 >--keep-going</TT
1379 >.
1380 <B
1381 CLASS="COMMAND"
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
1386 function. 
1387     </P
1388 ><P
1389 ><B
1390 CLASS="COMMAND"
1391 >synth::output</B
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
1396 be:
1397     </P
1398 ><TABLE
1399 BORDER="5"
1400 BGCOLOR="#E0E0F0"
1401 WIDTH="70%"
1402 ><TR
1403 ><TD
1404 ><PRE
1405 CLASS="PROGRAMLISTING"
1406 >    synth::output $line "console"</PRE
1407 ></TD
1408 ></TR
1409 ></TABLE
1410 ><P
1411 >This outputs a single line of text using the
1412 <TT
1413 CLASS="LITERAL"
1414 >console</TT
1415 > filter. If running in graphical mode the
1416 default appearance of this text can be modified with the
1417 <TT
1418 CLASS="OPTION"
1419 >appearance</TT
1420 > option in the
1421 <B
1422 CLASS="COMMAND"
1423 >synth_device&nbsp;console</B
1424 > entry of the target
1425 definition file. The <SPAN
1426 CLASS="GUIMENUITEM"
1427 >System filters</SPAN
1428 > menu
1429 option can be used to change the appearance at run-time.
1430     </P
1431 ><P
1432 >Filters should be created before they are used. The procedures
1433 available for this are:
1434     </P
1435 ><TABLE
1436 BORDER="5"
1437 BGCOLOR="#E0E0F0"
1438 WIDTH="70%"
1439 ><TR
1440 ><TD
1441 ><PRE
1442 CLASS="PROGRAMLISTING"
1443 >synth::filter_exists &lt;name&gt;
1444 synth::filter_get_list
1445 synth::filter_add &lt;name&gt; [options]
1446 synth::filter_parse_options &lt;options&gt; &lt;parsed_options&gt; &lt;message&gt;
1447 synth::filter_add_parsed &lt;name&gt; &lt;parsed_options&gt;</PRE
1448 ></TD
1449 ></TR
1450 ></TABLE
1451 ><P
1452 ><B
1453 CLASS="COMMAND"
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.
1458 <B
1459 CLASS="COMMAND"
1460 >synth::filter_get_list</B
1461 > returns a list of the
1462 current known filters. <B
1463 CLASS="COMMAND"
1464 >synth::filter_add</B
1465 > can be
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
1468 use might be:
1469     </P
1470 ><TABLE
1471 BORDER="5"
1472 BGCOLOR="#E0E0F0"
1473 WIDTH="70%"
1474 ><TR
1475 ><TD
1476 ><PRE
1477 CLASS="PROGRAMLISTING"
1478 >    synth::filter_add "my_device_tx" -foreground yellow -hide 1</PRE
1479 ></TD
1480 ></TR
1481 ></TABLE
1482 ><P
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:
1487     </P
1488 ><TABLE
1489 BORDER="5"
1490 BGCOLOR="#E0E0F0"
1491 WIDTH="70%"
1492 ><TR
1493 ><TD
1494 ><PRE
1495 CLASS="PROGRAMLISTING"
1496 >    array set parsed_options [list]
1497     set message ""
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"
1502     } else {
1503         synth::filter_add_parsed "console" parsed_options
1504     }</PRE
1505 ></TD
1506 ></TR
1507 ></TABLE
1508 ><P
1509 >On success <TT
1510 CLASS="VARNAME"
1511 >parsed_options</TT
1512 > will be updated with an
1513 internal representation of the desired appearance, which can then be
1514 used in a call to <B
1515 CLASS="COMMAND"
1516 >synth::filter_add_parsed</B
1517 >. On
1518 failure <TT
1519 CLASS="VARNAME"
1520 >message</TT
1521 > will be updated with details of the
1522 parsing error that occurred.
1523     </P
1524 ></DIV
1525 ><DIV
1526 CLASS="REFSECT1"
1527 ><A
1528 NAME="SYNTH-NEW-HOST-GUI"
1529 ></A
1530 ><H2
1531 >The Graphical Interface</H2
1532 ><P
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.
1542     </P
1543 ><P
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.
1547     </P
1548 ><DIV
1549 CLASS="INFORMALFIGURE"
1550 ><A
1551 NAME="AEN18674"><P
1552 ></P
1553 ><DIV
1554 CLASS="MEDIAOBJECT"
1555 ><P
1556 ><IMG
1557 SRC="layout.png"
1558 ALIGN="CENTER"></P
1559 ></DIV
1560 ><P
1561 ></P
1562 ></DIV
1563 ><P
1564 >So adding a new item to the <SPAN
1565 CLASS="GUIMENU"
1566 >Help</SPAN
1567 > menu involves a
1568 <B
1569 CLASS="COMMAND"
1570 >.menubar.help&nbsp;add</B
1571 > operation with suitable
1572 arguments. Adding a new button to the toolbar involves creating a
1573 child window in <TT
1574 CLASS="VARNAME"
1575 >.toolbar</TT
1576 > and packing it
1577 appropriately. Scripts can create their own subwindows and then pack
1578 it into one of <TT
1579 CLASS="VARNAME"
1580 >.main.nw</TT
1581 >,
1582 <TT
1583 CLASS="VARNAME"
1584 >.main.n</TT
1585 >, <TT
1586 CLASS="VARNAME"
1587 >.main.ne</TT
1588 >,
1589 <TT
1590 CLASS="VARNAME"
1591 >.main.w</TT
1592 >, <TT
1593 CLASS="VARNAME"
1594 >.main.e</TT
1595 >,
1596 <TT
1597 CLASS="VARNAME"
1598 >.main.sw</TT
1599 >, <TT
1600 CLASS="VARNAME"
1601 >.main.s</TT
1602 > or
1603 <TT
1604 CLASS="VARNAME"
1605 >.main.se</TT
1606 >. Normally the user should be allowed to
1607 <A
1608 HREF="synth-gui.html#SYNTH-GUI-LAYOUT"
1609 >control</A
1610 > this via the target
1611 definition file. The central window <TT
1612 CLASS="VARNAME"
1613 >.main.centre</TT
1614 >
1615 should normally be left alone by other scripts since it gets used for
1616 text output.
1617     </P
1618 ><P
1619 >The following graphics-related utilities may be found useful:
1620     </P
1621 ><TABLE
1622 BORDER="5"
1623 BGCOLOR="#E0E0F0"
1624 WIDTH="70%"
1625 ><TR
1626 ><TD
1627 ><PRE
1628 CLASS="PROGRAMLISTING"
1629 >synth::load_image &lt;image name&gt; &lt;filename&gt;
1630 synth::register_ballon_help &lt;widget&gt; &lt;message&gt;
1631 synth::handle_help &lt;URL&gt;</PRE
1632 ></TD
1633 ></TR
1634 ></TABLE
1635 ><P
1636 ><B
1637 CLASS="COMMAND"
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
1641 <TT
1642 CLASS="FILENAME"
1643 >.xbm</TT
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.
1648     </P
1649 ><P
1650 ><B
1651 CLASS="COMMAND"
1652 >synth::register_balloon_help</B
1653 > provides balloon help
1654 for a specific widget, usually a button on the toolbar.
1655     </P
1656 ><P
1657 ><B
1658 CLASS="COMMAND"
1659 >synth::handle_help</B
1660 > is a utility routine that can be
1661 installed as the command for displaying online help, for example:
1662     </P
1663 ><TABLE
1664 BORDER="5"
1665 BGCOLOR="#E0E0F0"
1666 WIDTH="70%"
1667 ><TR
1668 ><TD
1669 ><PRE
1670 CLASS="PROGRAMLISTING"
1671 >    .menubar.help add command -label "my device" -command \
1672         [list synth::handle_help "file://$path"]</PRE
1673 ></TD
1674 ></TR
1675 ></TABLE
1676 ></DIV
1677 ><DIV
1678 CLASS="NAVFOOTER"
1679 ><HR
1680 ALIGN="LEFT"
1681 WIDTH="100%"><TABLE
1682 SUMMARY="Footer navigation table"
1683 WIDTH="100%"
1684 BORDER="0"
1685 CELLPADDING="0"
1686 CELLSPACING="0"
1687 ><TR
1688 ><TD
1689 WIDTH="33%"
1690 ALIGN="left"
1691 VALIGN="top"
1692 ><A
1693 HREF="synth-new-target.html"
1694 ACCESSKEY="P"
1695 >Prev</A
1696 ></TD
1697 ><TD
1698 WIDTH="34%"
1699 ALIGN="center"
1700 VALIGN="top"
1701 ><A
1702 HREF="ecos-ref.html"
1703 ACCESSKEY="H"
1704 >Home</A
1705 ></TD
1706 ><TD
1707 WIDTH="33%"
1708 ALIGN="right"
1709 VALIGN="top"
1710 ><A
1711 HREF="synth-porting.html"
1712 ACCESSKEY="N"
1713 >Next</A
1714 ></TD
1715 ></TR
1716 ><TR
1717 ><TD
1718 WIDTH="33%"
1719 ALIGN="left"
1720 VALIGN="top"
1721 >Writing New Devices - target</TD
1722 ><TD
1723 WIDTH="34%"
1724 ALIGN="center"
1725 VALIGN="top"
1726 ><A
1727 HREF="hal-synth-arch.html"
1728 ACCESSKEY="U"
1729 >Up</A
1730 ></TD
1731 ><TD
1732 WIDTH="33%"
1733 ALIGN="right"
1734 VALIGN="top"
1735 >Porting</TD
1736 ></TR
1737 ></TABLE
1738 ></DIV
1739 ></BODY
1740 ></HTML
1741 >