home *** CD-ROM | disk | FTP | other *** search
/ World of A1200 / World_Of_A1200.iso / datafiles / text / c_manual / devices / serialdevice / serialdevice.doc < prev    next >
Text File  |  1995-02-27  |  64KB  |  1,839 lines

  1. 7    SERIAL DEVICE
  2.  
  3. 7.1  INTRODUCTION
  4.  
  5. All Amiga models have a serial port to which you can connect
  6. external devices like a modem, scanner or a printer with a
  7. serial interface. Data can be sent in both directions, in
  8. several different formats, like seven or eight bits, with
  9. or without error checking etc.
  10.  
  11. On the Amiga the serial port consists of a 25 pin connector,
  12. and can communicate with baud rate up to 32250. It is the
  13. custom chip called "Paula" which contains a Universal
  14. Asynchronous Receiver/Transmitter (UART) that takes care of
  15. all serial data transmissions. The chip itself can manage
  16. up to one million bits per second, but at that speed the data
  17. buffer would be filled before the system had time to react,
  18. and normal cables can not manage to transmit more than
  19. 100,000 - 200,000 bits per second.
  20.  
  21. Baud rates between 1200 and 9600 are in most cases more than
  22. sufficient, and at that speed the computer will still be able
  23. to multitask properly.
  24.  
  25.  
  26.  
  27. 7.2  THE SERIAL PORT
  28.  
  29. The serial port sends and receives data in streams of bits.
  30. In theory only one physical wire would therefore be required,
  31. but there have been several extra cables added to send and
  32. receive special information as well as to supply external
  33. devices with power (+12V) and so on.
  34.  
  35. Since all data is sent bit by bit, and not as with the parallel
  36. port which sends one byte (8 bits) each time, it is rather
  37. slow. (Well at least not as fast as the parallel port, which
  38. is fully documented in the next chapter.) However, since
  39. some applications only works with one line, for example
  40. the modems which are connected to the telephone system,
  41. serial communication is easier to handle. Serial cables are
  42. also much cheaper.
  43.  
  44. Although only one line is required there is a whole 25-pin
  45. connector on the Amiga. Normal applications like a modem, or
  46. a scanner only needs some of the lines, but since there are
  47. so many possible lines to use, a lot of special equipment can
  48. be connected to the serial port. (See illustration "RS-232".)
  49.  
  50.  
  51.  
  52. 7.2.1  BYTE TO BITS AND VICE VERSA
  53.  
  54. Since the serial device only sends a stream of bits, a special
  55. chip has to convert the data (bytes) to bits (8). The character
  56. "A" would for example be transformed to 01000001 and "B" to
  57. 01000010 and so on. Of course the chip must also be able to
  58. do the opposite, to convert an incoming stream of bits to
  59. bytes.
  60.  
  61.             --------
  62.   A (64) <- |      | <- 01000001  (Receiving data)
  63.             | UART |
  64.   D (68) -> |      | -> 01000100  (Transmitting data)
  65.             --------
  66.  
  67.  
  68. The special chip that takes care of this is the "Universal
  69. Asynchronous Receiver/Transmitter" usually referred to as
  70. "UART". (See illustration "UART") Luckily we do not need to
  71. bother too much about this. However, it is good to know what
  72. is actually happening.
  73.  
  74.  
  75.  
  76. 7.2.2  PIN ASSIGNMENT
  77.  
  78. The Amiga's serial port is a 25-pin D-female-type connector.
  79. Below is an almost complete list of the pin assignment,
  80. together with a short description. (See illustration "RS-232".)
  81.  
  82. Pin  Amiga   RS232  HAYES  Direction  Type      Description
  83. -------------------------------------------------------------------
  84.   1  SHIELD  GND    GND    -          Standard  Ground  
  85.   2  TXD     TXD    TXD    Out        Standard  Transmit data
  86.   3  RXD     RXD    RXD    In         Standard  Receive data
  87.   4  RTS     RTS x  -      Out        Standard  Request to send
  88.   5  CTS     CTS x  CTS    In         Standard  Clear to send
  89.   6  DSR     DSR x  DSR    In         Standard  Data set ready
  90.   7  GND     GND    GND    -          Standard  Signal ground
  91.   8  DCD     DCD    DCD    In         Standard  Carrier detect
  92.   9  +12V    -      -      -          Amiga     +12 Volt
  93.  10  -12V    -      -      -          Amiga     -12 Volt
  94.  11  AUDO    -      -      Out        Amiga     Audio output
  95.  12  -       S.DS   SI     +          -         Speed indicate
  96.  13          S.CTS  -      +          -         RS232 code
  97.  14  -       S.TXD  -      +          -         RS232 code
  98.  15  -       TXC    -      +          -         RS232 code
  99.  16  -       S.RXD  -      +          -         RS232 code
  100.  17  -       RXC    -      +          -         RS232 code
  101.  18  AUDI    -      -      In         Amiga     Audio in (not used)
  102.  19  -       S.RTS  -      +          -         RS
  103.  20  DTR     DTR x  DTR    Out        Standard  Data terminal ready
  104.  21  -       SQD    -      -          *         (A1000 +5V)
  105.  22  RI      RI     RI     In         Standard  Ring indicator
  106.  23  -       SS     -      -          *         (A1000 +12V)
  107.  24  -       TXC1   -      -          -         3.58 MHz clock
  108.  25  -       -      -      -          Amiga     Reset (A1000)
  109.  
  110. (x) Used only if you have set the "seven-wire flag". Se below
  111.     for more information.
  112.  
  113. WARNING! Pin 21 and 23 are connected to the power supply on
  114. the old Amiga 1000s (+5V and +12V). On all other models the
  115. power is sent through pin 9 and 10. Be careful with this if
  116. you intend to make serial cables! We do not want to burn the
  117. user's external devices, do we?
  118.  
  119.  
  120.  
  121. 7.2.3  THE DATA STREAM
  122.  
  123. Since all data is sent and received in a stream of bits, the
  124. UART chip needs to know when each new byte (set of 8 bits) is
  125. coming in. To make this possible, following rules have been
  126. stated: (See illustration "Serial Bits".)
  127.  
  128.   1. When no data is sent, a mark bit (1) is sent over and over.
  129.  
  130.   2. Just before a byte is sent, a start bit (0) is transmitted.
  131.      The receiver will now know that seven or eight bits (depends
  132.      on what type of device it is) of data will be received.
  133.  
  134.   3. An optional "parity" bit will come directly after the
  135.      data bits. The parity bit is used for error checking. The
  136.      receiver may use "even", "odd" or no parity at all. If
  137.      the receiver is using even parity, the sender should set
  138.      the parity bit to 1 if the remainder of all data bits
  139.      divided by two is 0, else the parity bit should be set to
  140.      0. If the receiver is using odd parity, the sender should
  141.      set the parity bit to 0 if the remainder of all data bits
  142.      divided by two is 0, else the parity bit should be set to
  143.      1. If the receiver does not use parity checking, either
  144.      set the parity bit to 0 or do not send any parity bit at
  145.      all.
  146.  
  147.   4. Finally we need to send one (or two) stop bit(s) to tell
  148.      the receiver that the last data bit has been sent.
  149.  
  150.  
  151.   ...1 0 0 0 1 0 0 0 1 0 1 0 0 0 1... -> -> ->
  152.   ..._       _       _   _       _...
  153.       \_____/ \_____/ \_/ \_____/             
  154.      ^                           ^
  155.      | ^ ^ ^ 8 7 6 5 4 3 2 1 0 ^ |
  156.      | | | | <-- Data bits --> | Mark bit(s)
  157.      | | | |   (7 or 8 bits)   | 
  158.      | | | |                   Start bit
  159.      | | | |                        
  160.      | \ / Parity bit (We use even parity, hence 0)                 
  161.      |  | 
  162.      |  One or two stop bits
  163.      |
  164.      Mark bit(s)
  165.  
  166.  
  167.   Even parity: The sum of the data bits is divided by two, and
  168.                if the remainder is 0, the parity bit should be
  169.                set to 1. If the remainder is 1, the parity bit
  170.                should be set to 0. 
  171.  
  172.     10100110 = 4 bits are set. 4/2  remainder = 0 -> parity = 1
  173.     01110110 = 5 bits are set. 5/2  remainder = 1 -> parity = 0
  174.  
  175.  
  176.   Odd parity: The sum of the data bits is divided by two, and
  177.               if the remainder is 0, the parity bit should be
  178.               set to 0. If the remainder is 1, the parity bit
  179.               should be set to 1. 
  180.  
  181.     10100110 = 4 bits are set. 4/2  remainder = 0 -> parity = 0
  182.     01110110 = 5 bits are set. 5/2  remainder = 1 -> parity = 1
  183.  
  184.  
  185. The nice thing about the serial device is that we do not need
  186. to bother about this. (So why did I write it?) You only have
  187. to tell the device if you want to use parity, and if so if it
  188. should use even (default) or odd parity. You should also tell
  189. the serial device if you want to send seven or eight data bits,
  190. and one or two stop bits. Once you have told the device what
  191. you want, you do not need to think about it any more.
  192.  
  193.  
  194.  
  195. 7.3  THE SERIAL DEVICE
  196.  
  197. The Serial Port is a limited resource it that sense that there
  198. exist (normally) only one port. There may however be several
  199. programs running at the same time which all want to use the
  200. serial port. To make this possible they all have to coordinate
  201. their work with the port. That is the serial device's main
  202. task.
  203.  
  204. You can tell the device that you want a shared access, which
  205. means that other programs may also use the serial port, or if
  206. you want exclusive access, no other programs may use the
  207. device. It is then up to the device if it will accept your
  208. demands or else deny you the right to use the serial port.
  209. (Another task may have exclusive access.)
  210.  
  211. Once you have been allowed to use the serial port, you should
  212. send all your demands to the serial device, and it will take
  213. care of everything. You only have to give it some information
  214. like how it should work (eight or seven bits data, parity?
  215. one or two stop bits, baud rate etc...) and where data should
  216. be fetched/stored.
  217.  
  218.  
  219.  
  220. 7.3.1  PREPARE THE SERIAL DEVICE
  221.  
  222. Before you should open the serial device you need to decide if
  223. you want exclusive or shared access, and if you want to use the
  224. special RTS/CTR, DTR/DSR ("seven-wire-mode").
  225.  
  226.   1. If you want shared access, other programs may also use the
  227.      serial port, set the flag SERF_SHARED. (Se below.) If you
  228.      want exclusive access you do not need to set any flags,
  229.      since it is the default mode.
  230.  
  231.   2. If you want to use the RTS/CTR, DTR/DSR handshaking
  232.      protocol ("seven-wire-mode") set the flag SERF_7WIRE.
  233.     
  234.  
  235.  
  236.  
  237. 7.3.2  OPEN THE SERIAL DEVICE
  238.  
  239. As with all devices you have to open a message port through
  240. which the serial device can talk to you, and allocate a
  241. request block (a IOExtSer structure), before you may open
  242. the device itself.
  243.  
  244.   1. Open a message port: (Since it is only our task and the
  245.      device that will use the message port, we do not need
  246.      to make it "public", hence no name. Priority should as
  247.      usual be set to 0, normal priority.)
  248.  
  249.      struct MsgPort *replymp;
  250.  
  251.      replymp = (struct MsgPort *)
  252.        CreatePort( NULL, 0 );
  253.  
  254.      if( !replymp )
  255.        clean_up( "Could not create the reply port!" );
  256.  
  257.  
  258.   2. Allocate a request block of type IOExtSer structure.
  259.      (The IOExtSer structure is an extended version of the
  260.      normal request block, and should therefore be allocated
  261.      with help of the CreateExtIO() function with the size
  262.      set to sizeof( struct IOExtSer ).
  263.  
  264.      struct IOExtSer *serial_req;
  265.  
  266.      serial_req = (struct IOExtSer *)
  267.        CreateExtIO( replymp, sizeof( struct IOExtSer ) );
  268.  
  269.      if( !serial_req )
  270.        clean_up( "Not enough memory!" );
  271.  
  272.  
  273. Once the message port and the request block have successfully
  274. been created, you should set the desired flags which were
  275. explained above, and then open the serial device.
  276.  
  277.   3. Set desired flags (only SERF_SHARED and SERF_7WIRE are
  278.      accepted), and open the device.
  279.  
  280.      UBYTE error;
  281.  
  282.      serial_req->io_SerFlags = SERF_SHARED|SERF_7WIRE;
  283.  
  284.      error = OpenDevice( SERIALNAME, 0, serial_req, 0 );
  285.  
  286.      if( error )
  287.        clean_up( "Could not open the Serial Device!" );
  288.  
  289.  
  290.  
  291. 7.3.3  SET SERIAL PARAMETERS
  292.  
  293. Once the serial device has successfully been opened you should
  294. set desired parameters like baud rate, seven or eight data bits
  295. and so on. To set these parameters you initialize the request
  296. block as described below, set the flag SDCMD_SETPARMS and
  297. tells EXEC to execute your request with a DoIO() command.
  298.  
  299. Here is a list of parameters that should be initialized: (We
  300. assume you have already opened the device as described above,
  301. and have also created an IOExtSer structure with a pointer
  302. named "ioreq" to it.
  303.  
  304.   1. The serial device collects data and stores it in a
  305.      temporary buffer. Because of this it can read a lot of
  306.      data without any interruption, and once there is a break
  307.      the data in this temporary buffer is moved to the real
  308.      data buffer. The temporary buffer should be at least
  309.      512 bytes, but more is recommended, especially if you
  310.      want to collect a lot of data at high speed.
  311.      
  312.      This temporary buffer is automatically created by the
  313.      serial device, and also automatically deallocated when
  314.      you close the device. If you have set one buffer size,
  315.      and later on changes the size, the old buffer will be
  316.      removed and a new buffer allocated. All data will then
  317.      be lost, so do not change the size of the buffer while
  318.      you are still collecting data.
  319.      
  320.      The size is set in the io_RBufLen field of the request
  321.      structure. The size must be at least 512, but other
  322.      recommended sizes are 1024, 2048, 4096, 8192 or 16384.
  323.      To set the internal input buffer size to 8192 bytes do
  324.      like this:
  325.  
  326.        ioreq->io_RBufLen = 8192;
  327.  
  328.  
  329.   2. You must tell the serial device at what speed it should
  330.      communicate (how many bits per second). It is important
  331.      that both the sender and receiver are using the same
  332.      speed.
  333.      
  334.      You set the desired speed by initializing the io_Baud
  335.      field to one of the following baud rates (you may use
  336.      other speeds, but most applications expect you to use
  337.      on of the recommended speeds, and if it is to fast data
  338.      can be lost or corrupted): 110, 300, 1200, 2400, 4800,
  339.      9600, 19200 or 31250. To set the baud rate to 9600 do
  340.      like this:
  341.   
  342.        ioreq->io_Baud = 9600;
  343.   
  344.  
  345.   3. Your program or the external device you are communicating
  346.      with can send a "break message", which will pause the
  347.      transmission for a specified time. This is useful if you
  348.      have received to many messages and you can not answer all
  349.      of them before more are arriving. A small break would in
  350.      this case be appreciated. A break signal simply stops the
  351.      communication for a specified number of microseconds.
  352.      
  353.      You can set the number of microseconds the communication
  354.      should be down after a break signal by initializing the
  355.      io_BrkTime field. To set the break time to half a second
  356.      do like this:
  357.      
  358.        ioreq->io_BrkTime = 500000;
  359.   
  360.  
  361.   4. If you want to read normal ASCII characters you only need
  362.      the first seven bits, and should therefore only try to
  363.      collect seven data bits instead of eight. However,
  364.      sometimes you want to receive whole bytes, and should then
  365.      collect all eight data bits.
  366.      
  367.      To set the number of bits you want to read each time you
  368.      initialize the io_ReadLen field accordingly. To read eight
  369.      data bits do like this: 
  370.   
  371.        ioreq->io_ReadLen = 8;
  372.  
  373.  
  374.   5. Since you sometimes only want to send 7 data bits, but
  375.      other times want send all 8 data bits, you should
  376.      initialize the io_WriteLen field accordingly. To write
  377.      eight bits do like this:
  378.      
  379.        ioreq->io_WriteLen = 8;
  380.   
  381.  
  382.   6. After each character you need to send one or two stop
  383.      bit(s), depending on what the other device expect.
  384.      Normally you only use one stop bit, but if you are using
  385.      seven data bits it happens that you should use two stop
  386.      bits. To tell the serial device to use one stop bit to
  387.      like this:
  388.      
  389.        ioreq->io_StopBits = 1;
  390.  
  391.  
  392.   7. There exist some special modes that are selected by
  393.      setting some serial flags. Here is a complete list of
  394.      possible flags together with a short description:
  395.      
  396.        SERF_XDISABLED  Set this flag if you want to turn off
  397.                        the XON-XOFF feature. Default is on.
  398.  
  399.        SERF_EOFMODE    Set this flag if you want the Serial
  400.                        Device to send/collect data until it
  401.                        finds one of the eight specified
  402.                        "end-of-file" characters. (See below
  403.                        for more information.)
  404.                        
  405.        SERF_SHARED     Set this flag if you want to share the
  406.                        serial port with other programs. Note
  407.                        that this flag should only be used
  408.                        BEFORE you have opened the device, and
  409.                        should NOT be changed later on. If you
  410.                        want to change status you should close
  411.                        the serial device, alter the status and
  412.                        then try to open it again.
  413.                        
  414.        SERF_RAD_BOOGIE Set this flag if you want to use the
  415.                        serial port at high speed. When this
  416.                        flag is set no parity is used, xON/xOFF
  417.                        handling is turned off, no break signals
  418.                        are allowed, and finally only eight-bit
  419.                        characters are used. When you need fast
  420.                        communication set this flag, but
  421.                        remember that the data will then not be
  422.                        error checked, and break signals are
  423.                        ignored.
  424.  
  425.  
  426.        SERF_QUEUEDBRK  Set this flag if you want break commands
  427.                        to be queued along with all other
  428.                        signals. The default is that a break
  429.                        command interrupts the process
  430.                        immediately.
  431.  
  432.        SERF_7WIRE      If the flag is set, the seven-wire
  433.                        "handshaking" mode will be used.
  434.                        (Default is three-wire.) With this flag
  435.                        set you can use the RS232 RTS/CTS,
  436.                        DTR/DSR commands. This flag should only
  437.                        be used BEFORE when you have opened the
  438.                        serial device, and should NOT be changed
  439.                        after that. To change this mode, you
  440.                        must close the device, set the desired
  441.                        mode and then try to open it again.
  442.  
  443.        SERF_PARTY_ODD  Set this flag if you want to use odd
  444.                        parity. (The default setting is even
  445.                        parity.)
  446.  
  447.        SERF_PARTY_ON   Parity checking/writing is turned on.
  448.                        (The sum of all data bits are divided by
  449.                        two, and the remainder is the parity
  450.                        bit. If even parity is used the bit will
  451.                        be set to 1 if the remainder is even. If
  452.                        odd parity is used the parity bit will
  453.                        be set to 0 if the remainder is even.
  454.  
  455.      You set desired flags in the io_SerFlags filed of the
  456.      request structure. If you want to set several flags, put
  457.      a "|" ("binary-OR") between. To set the parity on, and
  458.      use the end of character mode, do like this:
  459.      
  460.        ioreq->io_SerFlags = SERF_PARTY_ON | SERF_EOFMODE;
  461.  
  462.      Note! If you do not want to set any flags, remember to set
  463.      the field to 0. If you do not make sure it is empty, some
  464.      flags might accidentally be set.
  465.  
  466.  
  467.   8. There exist a special field where more serial flags can
  468.      be used in the future. For the moment there exist only two
  469.      flags for this field.
  470.      
  471.        SEXTF_MSPON Set this flag if you want to use mark-space
  472.                    parity rather than odd-even parity.
  473.  
  474.        SEXTF_MARK  If this and the SEXTF_MSPON flag is set, it
  475.                    will Mark.
  476.      
  477.      If you want to use the mark-space method, with mark, do
  478.      like this:
  479.  
  480.        ioreq->io_ExtFlags = SEXTF_MSPON | SEXTF_MARK;
  481.  
  482.      Note! If you do not want to set any of these flags, remember
  483.      to set the field to 0!
  484.   
  485.   
  486.   9. If you have set the flag "SERF_EOFMODE", the serial device
  487.      will send/collect data until it finds one of eight
  488.      specified "end-of-file" characters. These eight characters
  489.      are stored in a IOTArray structure which look like this:
  490.      
  491.        struct IOTArray
  492.        {
  493.          ULONG TermArray0;
  494.          ULONG TermArray1;
  495.        };
  496.  
  497.      Each ULONG data consists of four bytes, and in total you
  498.      can store eight bytes (end-of-file characters) in the
  499.      array. To make the checking routine efficient you must
  500.      store the characters in descending order! To copy the
  501.      desired characters into the array do like this:
  502.      
  503.        /* Here is an array with all EOF characters: */
  504.        /* NOTE! They MUST be in descending order!   */
  505.        UBYTE eof_char[8]={ 0x54, 0x32, 0x16, 0x15,
  506.                            0x12, 0x03, 0x00, 0x00 };
  507.  
  508.        /* Declare a unsigned byte pointer: */
  509.        UBYTE *ptr;
  510.  
  511.        /* Simple loop variable: */
  512.        int loop;
  513.  
  514.        ...
  515.  
  516.        /* Get the address of the IOTArray: */
  517.        ptr = (UBYTE *) &(ioreq->io_TermArray);
  518.  
  519.        /* Set all eight end of file characters: */
  520.        for( loop=0; loop < 8; loop++ )
  521.        {
  522.          /* Copy character after character: */
  523.          *ptr = eof_chars[ loop ];
  524.  
  525.          /* Step one byte foreward: */
  526.          ptr++;
  527.        }
  528.  
  529.  
  530. Once you have set all desired parameters in the request block
  531. (IOExtSer structure) you set the IO command to SDCMD_SETPARAMS
  532. and tell the serial device to do your request by calling the
  533. DoIO() function. If something went wrong DoIO() will return
  534. with an error number, else 0 is returned which means that your
  535. request have successfully been executed. (See below for a
  536. complete list of error messages.)
  537.  
  538.   ioreq->IOSer.io_Command = SDCMD_SETPARAMS;
  539.  
  540.   error = DoIO( ioreq );
  541.  
  542.  
  543.  
  544. 7.3.4  READ DATA
  545.  
  546. When you want to read data from the serial port, you have to do
  547. four things. First you have to give the serial device a pointer
  548. to a buffer where all data which you read will be stored.
  549. (This memory buffer is not the same as the serial device's own
  550. temporary input buffer that was explained above.)
  551.  
  552. Secondly you have to tell the device how many bytes/characters
  553. you want to read. You do it by either telling the device
  554. exactly how many characters you want to read, or set the
  555. length to -1 which means you want to read continuously and stop
  556. first when an end-of-file characters have been found. (Remember
  557. to set the flag "SERF_EOFMODE", or the serial device will not
  558. check for termination characters.)
  559.  
  560. Thirdly you have to set the command flag "CMD_READ", which
  561. tells the serial device that you want to read data from the
  562. serial port.
  563.  
  564. Finally you tell the serial device to do your request. You can
  565. either put your program to sleep while the serial device is
  566. reading data with a DoIO() call, or you use the SendIO()
  567. function and continue to do something while all data is
  568. collected. There exist even a special "quick" mode which
  569. should be used if very fast communication is needed.
  570.  
  571. Here is an example on how to read data: (Your program will be
  572. put to sleep while the data is collected.)
  573.  
  574.   error: (UBYTE) is a simple unsigned byte variable.
  575.  
  576.   ioreq: (struct IOExtSer *) is a pointer to an IOExtSer
  577.          structure.
  578.  
  579.   data:  (BYTE) is a pointer to a block of memory where all
  580.          data which is collected will be stored. Note that the
  581.          serial device will not check if it sends more data
  582.          than actually can be stored in the buffer. Innocent
  583.          memory can be corrupted if you do not make the buffer
  584.          big enough!
  585.  
  586.  
  587.   /* We want to read some data: */
  588.   ioreq->IOSer.io_Command = CMD_READ;
  589.  
  590.   /* Give the start address of our data buffer: */
  591.   ioreq->IOSer.io_Data = data;
  592.  
  593.   /* We want to read 400 bytes/characters: (The buffer must */
  594.   /* then be at least 400 bytes.)                           */ 
  595.   ioreq->IOSer.io_Length = 400;
  596.  
  597.   /* Do our request: */
  598.   error = DoIO( ioreq );
  599.  
  600.   /* Everything OK? */
  601.   if( error )
  602.     printf( "Problems while reading!\n" );
  603.  
  604.  
  605. The program above will go to sleep while the data is collected
  606. from the serial port. However, sometimes you may want to do
  607. something while the data is fetched and not go to sleep.
  608. Instead of using the function DoIO() you should then use the
  609. asynchronous SendIO(). As explained in chapter 17 DEVICES, the
  610. SendIO() will not wait for the request to be completed.
  611.  
  612. To check if the request have been completed or not you can
  613. either use the function CheckIO(), or wait for a message to
  614. arrive at the request block's reply port.
  615.  
  616. Once the request have been completed you can look at the
  617. io_Error field of the request block to check if everything
  618. was OK. If the field is zero everything was executed without
  619. any problems, but if it is non zero the request failed.
  620.  
  621. Here is an example:
  622.  
  623.   /* Declare a pointer and set it to NULL: */
  624.   struct IOExtSer *ptr = NULL;
  625.  
  626.   ...
  627.   
  628.  
  629.   /* We want to read some data: */
  630.   ioreq->IOSer.io_Command = CMD_READ;
  631.  
  632.   /* Give the start address of our data buffer: */
  633.   ioreq->IOSer.io_Data = data;
  634.  
  635.   /* We want to read 400 bytes/characters: (The buffer must */
  636.   /* then be at least 400 bytes.)                           */
  637.   ioreq->IOSer.io_Length = 400;
  638.  
  639.   /* Do our request and return immediately: */
  640.   SendIO( ioreq );
  641.  
  642.  
  643.   /* As long as the pointer is not pointing to */
  644.   /* the request we should stay in the loop:   */
  645.   while( ptr == NULL )
  646.   {
  647.     ... do something ...
  648.  
  649.   
  650.     /* Check if the request has been completed: (If the  */
  651.     /* request has been completed CheckIO() will return  */
  652.     /* a pointer to the request, else NULL is returned.) */
  653.     ptr = CheckIO( ioreq );
  654.   }
  655.  
  656.   /* Remove the request block's message. (The ptr and ioreq */
  657.   /* are in this example identical, so it does not matter   */
  658.   /* whichever you will use. The parenthesis around the     */
  659.   /* expression is actually unnecessary, but this looks     */
  660.   /* better.)                                               */
  661.   Remove( &(ptr->IOSer.io_Message.mn_Node) );
  662.  
  663.   /* Everything OK? Check the io_Error filed: */
  664.   if( ioreq->IOSer.io_Error )
  665.     printf( "Problems while reading!\n" );
  666.  
  667.  
  668. Finally their exist a special "quick" mode. It can only
  669. sometimes be used and only for reading. This special mode
  670. can be used when a lot of data at a very (!) high speed
  671. should be collected. The "quick" mode is not the same as the
  672. "SERF_RAD_BOOGIE" mode explained above. The quick mode can
  673. only be used for reading, and there are some special
  674. restrictions, while the high speed rad boogie mode can be
  675. used both for reading and writing.
  676.  
  677. To use the quick mode you set the IOF_QUICK flag, before
  678. you send the request. You should then not use the normal DoIO()
  679. or SendIO() functions, but instead the low level BeginIO()
  680. function. The BiginIO() is synchronous (like DoIO()) if we
  681. were allowed to use quick mode, else the request is
  682. asynchronous (like SendIO()).
  683.  
  684. Although you want to use the quick mode, it is not sure you
  685. are allowed to do it. For some requests it is OK, others
  686. will automatically remove the IOF_QUICK flag. You must
  687. therefore check the request after you have posted it to
  688. see if the IOF_QUICK flag is still on or not. If the flag was
  689. removed, the quick mode was turned off and the request should
  690. now be treated as those started with a SendIO() call (remember
  691. to remove the message). However, it the flag is still there
  692. the quick mode was used and we do not need (nor should) remove
  693. any message at the reply port.
  694.  
  695.   /* Initialize the request block as normal. */
  696.   /* ...                                     */
  697.  
  698.   /* Try to use the "quick" mode: */
  699.   ioreq->IOSer.io_Flags = IOF_QUICK;
  700.  
  701.   /* Do the request: */
  702.   BeginIO( ioreq );
  703.  
  704.   if( (ioreq->IOSer.io_Flags & IOFQUICK) )
  705.   {
  706.     /* OK! The request was using quick mode, which means  */
  707.     /* that our task was put to sleep while the data was  */
  708.     /* fetched, and the request have now been completed.  */
  709.     /* Since we are using quick mode there are no message */
  710.     /* that should be removed.                            */
  711.   }
  712.   else
  713.   {
  714.     /* Too bad, we were not allowed to use the quick mode. */
  715.     /* The request should now be treated as if it was      */
  716.     /* started with a SendIO() function call. This request */
  717.     /* is asynchronous - request returns immediately.      */
  718.   
  719.     /* We can either use the routine above with CheckIO()  */
  720.     /* or put our task to sleep while we are waiting, by   */
  721.     /* calling the WaitIO() function. The WaitIO()         */
  722.     /* function will automatically remove the message, so  */
  723.     /* we do not need to do anything more. However, if we  */
  724.     /* used the function Wait(), we have to remove the     */
  725.     /* messages ourself.                                   */
  726.     WaitIO( ioreq );
  727.   }
  728.  
  729.  
  730. The "quick" mode can only sometimes be used:
  731.  
  732.   1. You may only read data. The "quick" mode is not allowed for
  733.      writing.
  734.  
  735.   2. There is enough data in the internal input buffer so the
  736.      request will immediately be satisfied.
  737.  
  738.   3. No other requests is using/waiting for the serial port.
  739.  
  740.  
  741.  
  742. 7.3.5  WRITE DATA
  743.  
  744. When you want to write data to the serial port it is almost the
  745. same procedure as when reading. The only difference is that you
  746. set the command flag "CMD_WRITE".
  747.  
  748. Here is an example on how to write data to the serial port:
  749. (Your program will be put to sleep while the data is moved to
  750. the serial port.)
  751.  
  752.   error: (UBYTE) is a simple unsigned byte variable.
  753.  
  754.   ioreq: (struct IOExtSer *) is a pointer to an IOExtSer
  755.          structure.
  756.  
  757.   data:  (BYTE) is a pointer to a block of memory where all
  758.          data you want to send is stored.
  759.  
  760.  
  761.   /* We want to send (write) some data: */
  762.   ioreq->IOSer.io_Command = CMD_WRITE;
  763.  
  764.   /* Give the start address of our data buffer: */
  765.   ioreq->IOSer.io_Data = data;
  766.  
  767.   /* We want to send 150 bytes/characters: */
  768.   ioreq->IOSer.io_Length = 150;
  769.  
  770.   /* Do our request: */
  771.   error = DoIO( ioreq );
  772.  
  773.   /* Everything OK? */
  774.   if( error )
  775.     printf( "Problems while writing!\n" );
  776.  
  777.  
  778. The program above will go to sleep while the data is copied to
  779. the serial port. If you do not want the program to wait for the
  780. request to be completed you should use SendIO(). The procedure
  781. is very similar with reading.
  782.  
  783. To check if the request have been completed or not you can
  784. either use the function CheckIO(), or wait for a message to
  785. arrive at the request block's reply port.
  786.  
  787. Once the request have been completed you can look at the
  788. io_Error field of the request block to check if everything
  789. was OK. If the field is zero everything was executed without
  790. any problems, but if it is non zero the request failed.
  791.  
  792. Here is an example:
  793.  
  794.   /* Declare a pointer and set it to NULL: */
  795.   struct IOExtSer *ptr = NULL;
  796.  
  797.   ...
  798.   
  799.  
  800.   /* We want to send (write) some data: */
  801.   ioreq->IOSer.io_Command = CMD_WRITE;
  802.  
  803.   /* Give the start address of our data buffer: */
  804.   ioreq->IOSer.io_Data = data;
  805.  
  806.   /* We want to send 280 bytes/characters: */
  807.   ioreq->IOSer.io_Length = 280;
  808.  
  809.   /* Do our request and return immediately: */
  810.   SendIO( ioreq );
  811.  
  812.  
  813.   /* As long as the pointer is not pointing to */
  814.   /* the request we should stay in the loop:   */
  815.   while( ptr == NULL )
  816.   {
  817.     ... do something ...
  818.  
  819.   
  820.     /* Check if the request has been completed: (If the  */
  821.     /* request has been completed CheckIO() will return  */
  822.     /* a pointer to the request, else NULL is returned.) */
  823.     ptr = CheckIO( ioreq );
  824.   }
  825.  
  826.   /* Remove the requst block's message. (The ptr and ioreq */
  827.   /* are in this example identical, so it does not matter  */
  828.   /* whichever you will use. The parenthesis around the    */
  829.   /* expression is actually unnecessary, but this looks    */
  830.   /* better.)                                              */
  831.   Remove( &(ptr->IOSer.io_Message.mn_Node) );
  832.  
  833.   /* Everything OK? Check the io_Error filed: */
  834.   if( ioreq->IOSer.io_Error )
  835.     printf( "Problems while writing!\n" );
  836.  
  837.  
  838. You can not use the quick mode while you are sending data. If
  839. you need fast communication you should set the serial flag
  840. "SERB_RAD_BOOGIE". Note the restrictions mentioned above. (Only
  841. eight-bit characters, and no parity checking etc...)
  842.  
  843.  
  844. Since you usually will want to read and write data at the same
  845. time, you have to use two separate request blocks. If you are
  846. using shared access mode you simply create two request blocks
  847. and open the serial device twice. (Do not forget to close both
  848. requests later on.) Here is an example:
  849.  
  850.   struct MsgPort *replymp;
  851.   struct IOExtSer *serial_req_read;
  852.   struct IOExtSer *serial_req_write;
  853.   UBYTE error;
  854.  
  855.      
  856.   /* We use only one reply message port: */
  857.   replymp = (struct MsgPort *)
  858.     CreatePort( NULL, 0 );
  859.   if( !replymp )
  860.     clean_up( "Could not create the reply port!" );
  861.  
  862.  
  863.   /* Create the request block "read": */
  864.   serial_req_read = (struct IOExtSer *)
  865.     CreateExtIO( replymp, sizeof( struct IOExtSer ) );
  866.   if( !serial_req_read )
  867.     clean_up( "Not enough memory!" );
  868.   serial_req_read->io_SerFlags = SERF_SHARED|SERF_7WIRE;
  869.  
  870.   /* Create the request block "write": */
  871.   serial_req_write = (struct IOExtSer *)
  872.     CreateExtIO( replymp, sizeof( struct IOExtSer ) );
  873.   if( !serial_req_write )
  874.     clean_up( "Not enough memory!" );
  875.   serial_req_write->io_SerFlags = SERF_SHARED|SERF_7WIRE;
  876.  
  877.  
  878.   /* Open the serial device for the read request: */
  879.   error = OpenDevice( SERIALNAME, 0, serial_req_read, 0 );
  880.   if( error )
  881.     clean_up( "Could not open the serial device (Read)!" );
  882.  
  883.   /* Open the serial device for the write request: */
  884.   error = OpenDevice( SERIALNAME, 0, serial_req_write, 0 );
  885.   if( error )
  886.     clean_up( "Could not open the serial device (Write)!" );
  887.  
  888.  
  889. If you are using exclusive access mode you can of course not
  890. open the serial device twice. Instead we have to copy the
  891. first request block to the other request block, byte for byte.
  892. Here is an example:
  893.  
  894.   struct MsgPort *replymp;
  895.   struct IOExtSer *serial_req_read;
  896.   struct IOExtSer *serial_req_write;
  897.   BYTE *r_ptr;
  898.   BYTE *w_ptr;
  899.   UBYTE error;
  900.   int loop;
  901.  
  902.      
  903.   /* We use only one reply message port: */
  904.   replymp = (struct MsgPort *)
  905.     CreatePort( NULL, 0 );
  906.   if( !replymp )
  907.     clean_up( "Could not create the reply port!" );
  908.  
  909.  
  910.   /* Create the request block "read": */
  911.   serial_req_read = (struct IOExtSer *)
  912.     CreateExtIO( replymp, sizeof( struct IOExtSer ) );
  913.   if( !serial_req_read )
  914.     clean_up( "Not enough memory!" );
  915.   serial_req_read->io_SerFlags = SERF_SHARED|SERF_7WIRE;
  916.  
  917.   /* Create the requestblock "write": */
  918.   serial_req_write = (struct IOExtSer *)
  919.     CreateExtIO( replymp, sizeof( struct IOExtSer ) );
  920.   if( !serial_req_write )
  921.     clean_up( "Not enough memory!" );
  922.   serial_req_write->io_SerFlags = SERF_SHARED|SERF_7WIRE;
  923.  
  924.  
  925.   /* Open the serial device for the read request: */
  926.   error = OpenDevice( SERIALNAME, 0, serial_req_read, 0 );
  927.   if( error )
  928.     clean_up( "Could not open the Serial Device (Read)!" );
  929.  
  930.  
  931.   /* Since we can not open the serial device once again */
  932.   /* for the write request, we have to copy the whole   */
  933.   /* read request block into the write request block.   */
  934.  
  935.   /* Get the start address of both request blocks: */
  936.   r_ptr = (BYTE *) serial_req_read;
  937.   w_ptr = (BYTE *) serial_req_write;
  938.  
  939.   /* Copy the request block, byte by byte: */
  940.   for( loop=0; loop < sizeof( struct IOExtSer ); loop++ )
  941.   {
  942.     /* Copy one byte: */
  943.     *w_ptr = *r_ptr;
  944.     
  945.     /* Step one byte forward: */
  946.     w_ptr++;
  947.     r_ptr++;
  948.   }
  949.  
  950.  
  951. Now we have two request blocks, and can therefore use both
  952. read and write requests at the same time. If you also want to
  953. use the special extra functions described further down, you
  954. may want to create even one more request block (or maybe
  955. even more...). The procedure is the same as described above.
  956.  
  957.  
  958.  
  959. 7.3.6  ERRORS
  960.  
  961. While you are using the serial device several errors may
  962. occur. The most common problem is that some other program is
  963. already using the serial port, but it can happen that data has
  964. been corrupted while reading/writing (the parity checking is
  965. a simple way to find these errors).
  966.  
  967. There exit for the moment nine different types of serial port
  968. errors, all defined in the header file "devices/serial.h".
  969. You will receive the error message from the function you
  970. just called, or you can check a request block to see if there
  971. were any problems. (The io_Error filed of the request block
  972. either contains 0, which means everything is OK, or an error
  973. number.)
  974.  
  975. Here is a complete list of the serial error messages:
  976.  
  977.   SerErr_DevBusy        Some other task/request is already
  978.                         using the serial device.
  979.  
  980.   SerErr_BufErr:        The serial device could not allocate
  981.                         enough memory for the internal input
  982.                         buffer.
  983.  
  984.   SerErr_InvParam:      The request block's parameters were not
  985.                         properly initialized.
  986.  
  987.   SerErr_LineErr:       The serial cable is faulty or the other
  988.                         device is not properly initialized or
  989.                         not connected. Tell the user to check the
  990.                         cables!
  991.  
  992.   SerErr_ParityErr:     The data you just sent/received contained
  993.                         at least one byte which was corrupted.
  994.                         Note that the serial flag "SERF_PARITY_ON"
  995.                         must be set, else the device will not
  996.                         check for errors.
  997.  
  998.   SerErr_TimerErr:      There was some problem with the timer.
  999.  
  1000.   SerErr_BufOverflow:   The serial input buffer has been filled.
  1001.                         You should empty it as fast as possible
  1002.                         so you do not lose valuable information.
  1003.                       
  1004.   SerErr_NoDSR:         No DSR.
  1005.  
  1006.   SerErr_DetectedBreak: A break was detected.
  1007.  
  1008.  
  1009. While you are using the serial device it may happen that you
  1010. receive other error messages than described above. It is
  1011. then usually the Exec which sent them: (defined in the header
  1012. file "exec/errors.h")
  1013.  
  1014. IOERR_OPENFAIL  The device (unit) could not be opened. (If you
  1015.                 are denied access to the serial device you
  1016.                 should receive the SerErr_DevBusy flag instead
  1017.                 of this exec message, but internally this flag
  1018.                 is used.) 
  1019.  
  1020. IOERR_ABORTED   When you abort a previously started request by
  1021.                 calling the AbortIO() function, the io_Error
  1022.                 filed of that request is set to IOERR_ABORTED.
  1023.                 If you find a request block with this flag set,
  1024.                 you know that it has been aborted.
  1025.  
  1026. IOERR_NOCMD     You tried to use a command that is not
  1027.                 supported by the serial device.
  1028.  
  1029. IOERR_BADLENGTH The length of the request was not valid.
  1030.  
  1031.  
  1032.  
  1033. 7.3.7  CLEAN UP
  1034.  
  1035. As usual on the Amiga you must remember to close and return
  1036. everything you have opened or allocated. If you do not close
  1037. the serial device after you, other programs will then not
  1038. be able to use the serial port. PLEASE be very careful about
  1039. this!
  1040.  
  1041. Here is a list of what you have to do:
  1042.  
  1043.   1. All requests you have started with SendIO() or BeginIO()
  1044.      (asynchronous commands) must either have been completed
  1045.      or aborted before you may close the device. It is a very
  1046.      common error to forget this, and it can be hard to find
  1047.      this bug. Usually the program will work fine (the command
  1048.      was completed in time), but now and then your program will
  1049.      crash (the command was completed after the device have
  1050.      been closed).
  1051.  
  1052.      A simple way is to abort all commands that have not
  1053.      reported that they have been completed, but this is not
  1054.      always good way to do it. (The last commands may be
  1055.      important and should therefore not be aborted.)
  1056.      
  1057.      If you do not want to abort the command, you should
  1058.      instead wait for it to be completed. The WaitIO()
  1059.      function is simple to use, and will put your program
  1060.      to sleep while waiting, so no computer time is wasted.
  1061.      If the request has already been completed, the function
  1062.      will return immediately. WaitIO() will also remove the
  1063.      message from the reply port. It is a very useful and
  1064.      simple function to use, but do NOT try to wait for
  1065.      a request that has not been started! (It will then be
  1066.      a very long wait, probably some million years before
  1067.      the user realizes that he/she has to hit the reset keys.)
  1068.  
  1069.      Here is an example on how to wait for a request to be
  1070.      completed: (If the request already has been completed
  1071.      it does not matter, WaitIO() will then simply return
  1072.      immediately. Note that we do not have to remove any
  1073.      messages from the reply port if we use WaitIO().)
  1074.  
  1075.        /* Store possible error numbers here: */
  1076.        UBYTE error;
  1077.      
  1078.        /* ... */
  1079.      
  1080.        /* Wait for the request to be completed: */
  1081.        error = WaitIO( ioreq );
  1082.      
  1083.        /* Everything OK? */
  1084.        if( error )
  1085.          printf( "Something went wrong!" );
  1086.  
  1087.        /* Well, successful or not, we may now */
  1088.        /* close the device!                   */
  1089.  
  1090.  
  1091.      To abort a request, simply use the AbortIO() function:
  1092.  
  1093.        /* Try to abort a previously started request:  */
  1094.        /* (Do not try to abort a request that has not */
  1095.        /* been started.)                              */
  1096.        AbortIO( ioreq );
  1097.  
  1098.  
  1099.   2. When all requests have been completed or aborted you may
  1100.      close the serial device. (Requests that have been executed
  1101.      by calling the DoIO() function have already been completed
  1102.      before your program wakes up, and thus you do not need to
  1103.      wait for these.)
  1104.      
  1105.      The serial device is closed as all other devices, by
  1106.      calling the CloseDevice() function. Here is an example:
  1107.  
  1108.        /* Close the Serial Device: */
  1109.        if( !serial_dever )
  1110.          CloseDevice( ioreq );
  1111.  
  1112.  
  1113.   3. You should now return all request blocks you have
  1114.      allocated. If you allocated a standard sized request block
  1115.      by calling the CreateStdIO() function, you should free
  1116.      it by calling the DeleteStdIO() function. However, if
  1117.      you have allocated an extended request block (like the
  1118.      serial device's request blocks) by calling the
  1119.      CreateExtIO() function, you MUST call the DeleteExtIO(),
  1120.      and of course remove the same amount of data as you
  1121.      allocated.
  1122.      
  1123.      How to delete a standard request block: (Since it is of
  1124.      the standard size, you do not need to specify any size.)
  1125.      
  1126.        /* Deallocate a standard sized request block: */
  1127.        DeleteStdIO( ioreq );
  1128.  
  1129.      With extended request block you have to specify the size
  1130.      as you did when you allocated it:
  1131.  
  1132.        /* Deallocate an extended request block: */
  1133.        /* (The size may vary depending on what  */
  1134.        /* device it was used for.)              */
  1135.        DeleteExtIO( ioreq, sizeof( struct IOExtSer ) );
  1136.  
  1137.      Note that ALL request blocks that have been allocated,
  1138.      must be removed!
  1139.  
  1140.  
  1141.   4. Finally you should close all message ports you have
  1142.      previously opened. Simply use the DeletePort() function
  1143.      as this example demonstrates:
  1144.  
  1145.        /* Remove the replyport: */
  1146.        DeletePort( replymp);
  1147.  
  1148.  
  1149. It can not be said to often. Please be careful with how your
  1150. program terminates! Your program should not only run fine,
  1151. but it should also allow other programs to run after and
  1152. simultaneously. Remember that your program must also be able
  1153. to quit nice and neatly even if it had to terminate too
  1154. early because of some fatale error. The cleaning up should
  1155. only be done where it is needed, and if you have not allocated
  1156. the memory or opened the device before your program quits, you
  1157. should of course NOT try to free these resources! If you do the
  1158. Amiga will most certainly crash! Too many programs contain this
  1159. very annoying error.
  1160.  
  1161. The best way to manage this cleaning up routine is to write a
  1162. separate function which checks each thing before it frees it.
  1163. The idea is that you may call this routine at any time, and it
  1164. will still manage to clear everything properly. Here is an
  1165. example: (Note how we check each thing to see if it should be
  1166. removed!)
  1167.  
  1168.   /* Close and return everything that has been */
  1169.   /* opened and allocated before we quit:      */
  1170.   void clean_up()
  1171.   {
  1172.     /* 1. Close the Serial Device: */ 
  1173.     if( !serial_dever )
  1174.       CloseDevice( serial_req );
  1175.   
  1176.     /* 2. Deallocate the serial request block: */
  1177.     if( serial_req )
  1178.       DeleteExtIO( serial_req, sizeof( struct IOExtSer ) );
  1179.   
  1180.     /* 3. Remove the replyport: */
  1181.     if( replymp )
  1182.       DeletePort( replymp);
  1183.   
  1184.     /* 4. Quit: */
  1185.     exit( 0 );
  1186.   }
  1187.  
  1188. Comments: 1. The serial_dever is a variable that we have
  1189.              declared ourself, and is used only to determine
  1190.              if the device has been opened or not. (The
  1191.              variable is set to TRUE before the program
  1192.              starts, and is only changed to FALSE after
  1193.              a successful opening of the device. See the
  1194.              included examples for more information.) We
  1195.              should of course only close the device if
  1196.              the serial_dever is FALSE. ("serial_dever"
  1197.              stands for "serial device error".)
  1198.  
  1199.           2. The serial_req is a pointer which is either
  1200.              pointing to a request block, or NULL if no
  1201.              request block has been allocated. We should
  1202.              of course only free the request block if there
  1203.              exist one.
  1204.  
  1205.           3. The replymp is a pointer which is either
  1206.              pointing to a message port, or NULL if no message
  1207.              port has been opened. And of course, we should
  1208.              only close the message port if it has been
  1209.              opened.
  1210.  
  1211.           4. Finally our program may terminate. The exit()
  1212.              function is placed here so we are sure the 
  1213.              program will quit. (If we did not have this
  1214.              exit(), our function would then return the
  1215.              control to our program again, and then we would
  1216.              have serial (sorry, serious) problems.
  1217.  
  1218.  
  1219.  
  1220. 7.4  A COMPLETE EXAMPLE
  1221.  
  1222. Here is a complete example that opens the serial device, sets
  1223. all necessary parameters, sends some data, collects some data
  1224. and finally cleans up and quits. Since we send the read and
  1225. write requests after each other (the first is completed before
  1226. the other is started) we only need to use one request block.
  1227.  
  1228.  
  1229. #include <exec/types.h>
  1230. #include <devices/serial.h>
  1231.  
  1232.  
  1233. /* Declare a pointer to our reply port: */
  1234. struct MsgPort *replymp = NULL;
  1235.  
  1236. /* Declare a pointer to our serial request block: */
  1237. struct IOExtSer *serial_req = NULL;
  1238.  
  1239. /* Store the serial device error here: */
  1240. UWORD serial_dever = TRUE;
  1241.  
  1242. /* Declare our own data buffer: (Big enough to hold 300 bytes.) */
  1243. BYTE buffer[ 300 ];
  1244.  
  1245.  
  1246. /* Declare our functions: */
  1247. void main();
  1248. void clean_up( STRPTR text );
  1249.  
  1250. void main()
  1251. {
  1252.   int loop;
  1253.   UBYTE *ptr;
  1254.   UBYTE error;
  1255.  
  1256.   /* The eight end-of-file characters: */
  1257.   UBYTE eof_char[8]={ 0x06, 0x05, 0x04, 0x03,
  1258.                       0x02, 0x01, 0x00, 0x00 };
  1259.  
  1260.  
  1261.   
  1262.   /* OPEN THE SERIAL DEVICE: */
  1263.  
  1264.   /* Get a reply port: (No name, priority 0) */
  1265.   replymp = (struct MsgPort *)
  1266.     CreatePort( NULL, 0 );
  1267.   if( !replymp )
  1268.     clean_up( "Could not create the reply port!" );
  1269.  
  1270.   /* Create a serial request block: */
  1271.   serial_req = (struct IOExtSer *)
  1272.     CreateExtIO( replymp, sizeof( struct IOExtSer ) );
  1273.   if( !serial_req )
  1274.     clean_up( "Not enough memory for the serial request block!" );
  1275.  
  1276.   /* Open the Serial Device: */
  1277.   serial_dever = OpenDevice( SERIALNAME, 0, serial_req, 0 );
  1278.   if( serial_dever )
  1279.     clean_up( "Could not open the Serial Device!" );
  1280.  
  1281.  
  1282.  
  1283.   
  1284.   /* SET THE SERIAL PARAMETERS: */
  1285.   
  1286.   /* Set the Serial Device's own input buffer to 512 bytes: */
  1287.   serial_req->io_RBufLen = 512;
  1288.   
  1289.   /* Set baud rate to 9600 baud: */
  1290.   serial_req->io_Baud = 9600;
  1291.   
  1292.   /* Set break time to half a second: */
  1293.   serial_req->io_BrkTime = 500000;
  1294.   
  1295.   /* Read 8 bits per character: */
  1296.   serial_req->io_ReadLen = 8;
  1297.  
  1298.   /* Write 8 bits per character: */
  1299.   serial_req->io_WriteLen = 8;
  1300.   
  1301.   /* Use 1 stop bit: */
  1302.   serial_req->io_StopBits = 1;
  1303.  
  1304.   /* Use parity and end-of-file characters: */
  1305.   serial_req->io_SerFlags = SERF_PARTY_ON | SERF_EOFMODE;
  1306.  
  1307.   /* No additional flags: */
  1308.   serial_req->io_ExtFlags = NULL;
  1309.   
  1310.   /* Set all eight end of file characters: */
  1311.   ptr = (UBYTE *) &(serial_req->io_TermArray);
  1312.   for( loop=0; loop < 8; loop++ )
  1313.   {
  1314.     /* Copy character after character: */
  1315.     *ptr = eof_char[ loop ];
  1316.     /* Step one byte forward: */
  1317.     ptr++;
  1318.   }
  1319.   
  1320.   /* All values have now been set, lets do a SDCMD_SETPARAMS request: */
  1321.   serial_req->IOSer.io_Command = SDCMD_SETPARAMS;
  1322.   
  1323.   /* Do our request: */
  1324.   error = DoIO( serial_req );
  1325.   if( error )
  1326.     clean_up( "Could not set the serial parameters!" );
  1327.  
  1328.  
  1329.  
  1330.   /* SEND DATA TO THE SERIAL PORT: */
  1331.  
  1332.   /* Put the data we want to send to the serial port into */
  1333.   /* our own data buffer: (Well in this example we only   */
  1334.   /* send two bytes.)                                     */
  1335.   buffer[ 0 ] = 0x4C;
  1336.   buffer[ 1 ] = 0x31;
  1337.   
  1338.   /* We want to send (write) some data: */
  1339.   serial_req->IOSer.io_Command = CMD_WRITE;
  1340.  
  1341.   /* Give the start address of our data: */
  1342.   serial_req->IOSer.io_Data = (APTR) buffer;
  1343.  
  1344.   /* We want to send two bytes: */
  1345.   serial_req->IOSer.io_Length = 2;
  1346.  
  1347.   /* Do our request: */
  1348.   error = DoIO( serial_req );
  1349.   if( error )
  1350.     clean_up( "Could not send data to the serial port!" );
  1351.  
  1352.  
  1353.  
  1354.   /* READ DATA FROM THE SERIAL DEVICE: */
  1355.   
  1356.   /* We want to read some data: */
  1357.   serial_req->IOSer.io_Command = CMD_READ;
  1358.  
  1359.   /* Give the start address of our buffer: */
  1360.   serial_req->IOSer.io_Data = (APTR) buffer;
  1361.  
  1362.   /* We want to read 0 bytes: */
  1363.   /* (If you do not have anything connected to your serial */
  1364.   /* port, we better not wait for any signals, thus read   */
  1365.   /* only 0 bytes.)                                        */
  1366.   serial_req->IOSer.io_Length = 0;
  1367.  
  1368.   /* Do our request: */
  1369.   error = DoIO( serial_req );
  1370.   if( error )
  1371.     clean_up( "Could not read data from the serial port!" );
  1372.  
  1373.  
  1374.  
  1375.   /* THE END: */
  1376.   clean_up( "The End" );
  1377. }
  1378.  
  1379.  
  1380. /* Close and return everything that has been */
  1381. /* opened and allocated before we quit:      */
  1382. void clean_up( STRPTR text )
  1383. {
  1384.   /* Close the Parallel Device: */ 
  1385.   if( !serial_dever )
  1386.     CloseDevice( serial_req );
  1387.  
  1388.   /* Deallocate the serial request block: */
  1389.   if( serial_req )
  1390.     DeleteExtIO( serial_req, sizeof( struct IOExtSer ) );
  1391.  
  1392.   /* Remove the replyport: */
  1393.   if( replymp )
  1394.     DeletePort( replymp);
  1395.  
  1396.   /* Print the message: */
  1397.   printf( "\n%s\n", text );
  1398.  
  1399.   /* Quit: */
  1400.   exit( 0 );
  1401. }
  1402.  
  1403.  
  1404.  
  1405. 7.5  OTHER USEFUL COMMANDS
  1406.  
  1407. You can not only read and write from/to the serial port. There
  1408. exist several other functions that can sometimes be needed.
  1409. Here is a complete list:
  1410.  
  1411.   1. Break, stop the serial device for a short time.
  1412.   2. Clear, clear the input buffer.
  1413.   3. Flush, removes all queued requests.
  1414.   4. Query, get some information from the serial device.
  1415.   5. Reset, reinitializes the serial device.
  1416.   6. Start, restarts the serial communication.
  1417.   7. Stop, temporary stops the serial communication.
  1418.  
  1419.  
  1420.  
  1421. 7.5.1  BREAK
  1422.  
  1423. While you are sending or reading data you sometimes have to
  1424. take a small pause. Your program may for example need to empty
  1425. the data buffer, or coordinate its action with some other task.
  1426. To pause the serial device you simply send a break request,
  1427. and all communications is halted for a specified time.
  1428.  
  1429. You send a break signal by setting the io_Command field to
  1430. "SDCMD_BREAK". The default is that all serial requests are
  1431. immediately halted, but if the serial flag "SERF_QUEUEDBRK"
  1432. is set, the break command will be queued as all other requests
  1433. and the device will first take a break when all previous
  1434. requests have been completed.
  1435.  
  1436. The serial device will normally take a 250000 microseconds
  1437. (1/4 seconds) long break, but you may change this break time
  1438. by altering the serial device's "io_BrkTime" parameter.
  1439.  
  1440. Here is an example on how you can send a break command:
  1441.  
  1442.   /* We want to take a pause: */
  1443.   ioreq->IOSer.io_Command = SDCMD_BREAK;
  1444.  
  1445.   /* Do our request: */
  1446.   error = DoIO( ioreq );
  1447.  
  1448.   /* OK? */
  1449.   if( error )
  1450.     printf( "Problems with the break!\n" );
  1451.  
  1452.  
  1453.  
  1454. 7.5.2  CLEAR
  1455.  
  1456. While you are reading data from the serial device, it is
  1457. actually first stored in the internal input buffer, and then
  1458. moved to your own buffer when requested. If you want to clear
  1459. the buffer before you start to read you should set the
  1460. io_Command field to "CMD_CLEAR". Here is an example:
  1461.  
  1462.   /* We want to clear the input buffer: */
  1463.   ioreq->IOSer.io_Command = CMD_CLEAR;
  1464.  
  1465.   /* Do our request: */
  1466.   error = DoIO( ioreq );
  1467.  
  1468.   /* OK? */
  1469.   if( error )
  1470.     printf( "Could not clear the input buffer!\n" );
  1471.  
  1472.  
  1473.  
  1474. 7.5.3  FLUSH
  1475.  
  1476. If several requests are sent to the device they are all queued
  1477. on a FIFO (First In First Out) basis. The command "CMD_FLUSH"
  1478. can then be used to remove all these queued commands. Here
  1479. is an example:
  1480.  
  1481.   /* We want to remove all queued requests: */
  1482.   ioreq->IOSer.io_Command = CMD_FLUSH;
  1483.  
  1484.   /* Do our request: */
  1485.   error = DoIO( ioreq );
  1486.  
  1487.   /* OK? */
  1488.   if( error )
  1489.     printf( "Could not remove the queued requests!\n" );
  1490.  
  1491.  
  1492.  
  1493. 7.5.4  QUERY
  1494.  
  1495. The command "SDCMD_QUERY" can be used to get some information
  1496. from the serial device. It is useful if you want to see the
  1497. serial status and/or how many bytes there are already in the
  1498. internal input buffer. The "io_Status" field of the request
  1499. structure will be set as following table shows:
  1500.  
  1501. Bit  Hex     Active  Description
  1502. ---------------------------------------------------------------
  1503.   0  0x0001  -       Reserved
  1504.   1  0x0002  -       Reserved
  1505.   2  0x0004  High    Connected to par. "select" and ser. "ring"
  1506.   3  0x0008  Low     DSR - Data Set Ready
  1507.   4  0x0010  Low     CTS - Clear To Send
  1508.   5  0x0020  Low     DCD - Carrier Detect
  1509.   6  0x0040  Low     RTS - Ready To Send
  1510.   7  0x0080  Low     DTR - Data Terminal Ready
  1511.   8  0x0100  High    Read overrun
  1512.   9  0x0200  High    Break sent
  1513.  10  0x0400  High    Break received
  1514.  11  0x0800  High    Transmit X-OFF
  1515.  12  0x1000  High    Receive X-OFF
  1516.  13  0x2000  -       Reserved
  1517.  14  0x4000  -       Reserved
  1518.  15  0x8000  -       Reserved
  1519. ---------------------------------------------------------------
  1520.  
  1521. The field "io_Actual" of the request structure contains the
  1522. number of bytes still left in the internal input buffer. Here
  1523. is an example:
  1524.  
  1525.   /* Check the serial device: */
  1526.   ioreq->IOSer.io_Command = SDCMD_QUERY;
  1527.  
  1528.   /* Do our request: */
  1529.   error = DoIO( ioreq );
  1530.  
  1531.   /* OK? */
  1532.   if( error )
  1533.     printf( "Could not get any information from the device!\n" );
  1534.   else
  1535.   {
  1536.     /* Check the "io_Status" field: */
  1537.     if( ioreq->io_Status & 0x0200 )
  1538.       printf( "A break request have just been sent!\n" );    
  1539.  
  1540.     /* Check number of characters left in the input buffer: */
  1541.     printf( "Characters left: %ld\n", ioreq->IOSer.io_Actual );
  1542.   }
  1543.  
  1544.  
  1545.  
  1546. 7.5.5  RESET
  1547.  
  1548. Send the command "CMD_RESET" to reset the serial device. All
  1549. commands that are queued to the device will be removed, commands
  1550. that are currently executed will be aborted, the internal input
  1551. buffer will be cleared and reallocated to the default size and
  1552. finally all serial flags are resetted. Here is an example:
  1553.  
  1554.   /* We want to reset the serial device: */
  1555.   ioreq->IOSer.io_Command = CMD_RESET;
  1556.  
  1557.   /* Do our request: */
  1558.   error = DoIO( ioreq );
  1559.  
  1560.   /* OK? */
  1561.   if( error )
  1562.     printf( "Could not reset the serial device!\n" );
  1563.  
  1564.  
  1565.  
  1566. 7.5.6  START
  1567.  
  1568. After you have stopped the serial communication by sending an
  1569. X-OFF message to the other device, you may want to start the
  1570. communication again. It is done by sending an X-ON message,
  1571. and the external device will then know that it may start to
  1572. send/receive data. X-ON messages are sent to the other device
  1573. (as well to our self) by issuing a "CMD_START" command. Here
  1574. is an example:
  1575.  
  1576.   /* We want to start serial communication again: */
  1577.   ioreq->IOSer.io_Command = CMD_START;
  1578.  
  1579.   /* Do our request: */
  1580.   error = DoIO( ioreq );
  1581.  
  1582.   /* OK? */
  1583.   if( error )
  1584.     printf( "Could not start the serial communication!\n" );
  1585.  
  1586.  
  1587.  
  1588. 7.5.7  STOP
  1589.  
  1590. To temporary stop all serial communication you send a
  1591. "CMD_STOP" command. If you try to stop the communication an
  1592. X-OFF message will be sent to the external device (as well as
  1593. to all other programs currently using the serial device). When
  1594. a X-OFF message has been received, communication will first
  1595. start again when an X-ON message is sent. (See CMD_START.) Here
  1596. is an example:
  1597.  
  1598.   /* We want to temporary stop all serial communication: */
  1599.   ioreq->IOSer.io_Command = CMD_STOP;
  1600.  
  1601.   /* Do our request: */
  1602.   error = DoIO( ioreq );
  1603.  
  1604.   /* OK? */
  1605.   if( error )
  1606.     printf( "Could not stop the serial communication!\n" );
  1607.  
  1608.  
  1609.  
  1610. 7.6  FUNCTIONS
  1611.  
  1612. DoIO()
  1613.  
  1614.   DoIO() is used to send requests to a device, and waits for it
  1615.   to be completed. While the program is waiting it is put to
  1616.   sleep so it will not waste any computer time. DoIO() will
  1617.   return first when the request have been completed or failed,
  1618.   and no message is therefore sent to the reply port.
  1619.  
  1620.   Synopsis: error = DoIO( req );
  1621.  
  1622.   error:    (long) DoIO() will return first when the request has
  1623.             been completed or something has failed. If the
  1624.             request was successfully completed zero is returned,
  1625.             else an error number is returned. What error number
  1626.             depends on which device was used.
  1627.  
  1628.   req:      (struct IORequest *) Pointer to the request you
  1629.             want to have executed.
  1630.  
  1631.  
  1632. SendIO()
  1633.  
  1634.   SendIO() is used to send requests to a device, but will
  1635.   return immediately without any delay. To check if the request
  1636.   have been completed use the CheckIO() function, or look
  1637.   at the request's reply port for any messages. Once the
  1638.   request has been completed you must remove the message at
  1639.   the reply port. (CheckIO() will not do it.) To remove a
  1640.   message use the function Remove(). Note that you may NOT
  1641.   close the serial device before all requests have been
  1642.   completed or aborted!
  1643.  
  1644.   Synopsis: SendIO( req )
  1645.  
  1646.   req:      (struct IORequest *) Pointer to the request you
  1647.             want to have executed.
  1648.  
  1649.  
  1650. CheckIO()
  1651.  
  1652.   CheckIO() is used to check if a previously started request
  1653.   has been completed. Note that this function will not remove
  1654.   the message at the reply port. This must be done with the
  1655.   Remove() function.
  1656.  
  1657.   Synopsis: ptr = CheckIO( req );
  1658.  
  1659.   ptr:      (long) CheckIO() will either return NULL if the
  1660.             request have not been completed or it will return a
  1661.             pointer to the request block.
  1662.  
  1663.   req:      (struct IORequest *) Pointer to the request you
  1664.             want to check.
  1665.  
  1666.  
  1667. WaitIO()
  1668.  
  1669.   WaitIO() will wait for the request to be completed, and while
  1670.   the program is waiting it is put to sleep so no computer time
  1671.   is wasted.
  1672.  
  1673.   Synopsis: error = WaitIO( req );
  1674.  
  1675.   error:    (long) WaitIO() will return first when the request,
  1676.             that has previously been sent, has been completed or
  1677.             something has failed. If the request was successfully
  1678.             completed zero is returned, else an error number is
  1679.             returned. What error number depends on which device
  1680.             was used.
  1681.  
  1682.   req:      (struct IORequest *) Pointer to the request you
  1683.             want to wait for to be completed. Note that the
  1684.             request must have already been sent to the device
  1685.             by either a SendIO() or BeginIO() function call.
  1686.  
  1687.  
  1688. BeginIO()
  1689.  
  1690.   BeginIO() is a low level form of the SendIO() function. The
  1691.   advantage with BeginIO() is that no fields of the request
  1692.   block will be altered as which is the case with SendIO(). If
  1693.   you are for example using the "quick mode" you should not
  1694.   use SendIO() since it will alter some of the data blocks.
  1695.   
  1696.   BeginIO() is synchronous command if you use the quick mode,
  1697.   but if you are not, the command will be asynchronous. Note
  1698.   that you may NOT close the serial device before all requests
  1699.   have been completed or aborted, so be careful with
  1700.   asynchronous commands.
  1701.  
  1702.   Synopsis: BeginIO( req )
  1703.  
  1704.   req:      (struct IORequest *) Pointer to the request you
  1705.             want to have executed. BeginIO() will not alter any
  1706.             values in this request structure as which is the case
  1707.             with SendIO() and DoIO(). Normally this is not any
  1708.             problem, and thus the SendIO() and DoIO() functions
  1709.             should be used. However, with the Audio Device for
  1710.             example some of these fields which are altered should
  1711.             not be changed, and you should therefore use this
  1712.             low level function BeginIO().  
  1713.  
  1714.  
  1715. AbortIO()
  1716.  
  1717.   AbortIO() will try to abort a previously started request. This
  1718.   function should be used sparsely since it does not look so
  1719.   good if you start a request and the try to stop it. (Better
  1720.   not start it at all.) However, it is easy, and can sometimes
  1721.   be very useful.
  1722.  
  1723.   A request that is aborted will have its io_Error field set
  1724.   to IOERR_ABORTED (defined in header file "exec/errors.h").
  1725.  
  1726.   Synopsis: AbortIO( req )
  1727.  
  1728.   req:      (struct IORequest *) Pointer to the request you
  1729.             want to abort.
  1730.  
  1731.  
  1732. CloseDevice()
  1733.  
  1734.   CloseDevice() will (surprise!) close a device. If you close
  1735.   the serial device the internal input buffer will
  1736.   automatically be deallocated. Note that you should NOT close
  1737.   the device before all started asynchronous requests have been
  1738.   either completed or aborted.
  1739.   
  1740.   Synopsis: CloseDevice( ioreq );
  1741.  
  1742.   ioreg:    (struct IORequest *) Pointer to the device's
  1743.             request block.
  1744.  
  1745.  
  1746. OpenDevice()
  1747.  
  1748.   OpenDevice() will try to open the specified device.
  1749.   
  1750.   Synopsis: error = OpenDevice( name, unit, req, flags );
  1751.  
  1752.   error:    (long) If OpenDevice() managed to open the device
  1753.             it returns 0, else an error number is returned.
  1754.             If you try to open the serial device, and there is
  1755.             already a program that is using it, the error
  1756.             message "SerErr_DevBusy" is returned.
  1757.  
  1758.   name:     (char *) Name of the device you want to open.
  1759.             The name of the serial device is defined as
  1760.             SERIALNAME in header file "devices/serial.h".
  1761.  
  1762.   unit:     (long) Which unit you want to open. Since there
  1763.             exist only one serial port, this field is ignored.
  1764.  
  1765.   req:      (struct IORequest *) Pointer to a request block.
  1766.             For the serial device it must be a pointer to an
  1767.             extender serial request block (struct IOExtSer).
  1768.  
  1769.   flags:    (long) Any special mode is set here. Ignored by
  1770.             the serial device.
  1771.  
  1772.  
  1773.  
  1774. 7.7  COMMANDS
  1775.  
  1776. Here is a complete list of commands you may send to the serial
  1777. device. For full documentation se examples above.
  1778.  
  1779. The special serial device commands: (Defined in header file
  1780. "devices/serial.h")
  1781.  
  1782.   SDCMD_BREAK      Sends a break signal.
  1783.   SDCMD_QUERY      Check the status of the serial device.
  1784.   SDCMD_SETPARAMS  Set the parameters of the serial device.
  1785.  
  1786.  
  1787. The rest of the commands you may use are normal exec commands,
  1788. and are defined in header file "exec/io.h".
  1789.  
  1790.   CMD_RESET  Resets all parameters of the serial device.
  1791.   CMD_READ   Read data from the serial port.
  1792.   CMD_WRITE  Write data to the serial port.
  1793.   CMD_CLEAR  Clears the internal input buffer.
  1794.   CMD_STOP   Temporary stops all serial communication. (X-OFF)
  1795.   CMD_START  Restarts serial communication. (X-ON)
  1796.   CMD_FLUSH  Removes all queued requests.
  1797.  
  1798.  
  1799.  
  1800. 7.8  EXAMPLES
  1801.  
  1802. The included examples demonstrates how you can use the Serial
  1803. Device. It demonstrates most of the features described in this
  1804. chapter. Since I do not know what you have connected to your
  1805. serial port the examples will not do very much. However, the
  1806. examples are easy modify, so it should not be hard for you to
  1807. change them as desired.
  1808.  
  1809. Example 1
  1810.   If you have a Sharp JX-100 scanner you can run this program
  1811.   since it will try to turn the lamp on and then off again.
  1812.   Very useful! (hmmm...) The program does not check if there
  1813.   is any contact with the scanner, nor if the lamp really was
  1814.   turned on or not. It simply demonstrates how to send data.
  1815.  
  1816. Example 2
  1817.   This example is rather similar to Example 1, but this time
  1818.   we do not wait for the serial port to complete our request.
  1819.   Instead we do somethings (well not very much) and now and
  1820.   then checks if the request has been completed. Using a busy
  1821.   wait.
  1822.  
  1823. Example 3
  1824.   This example is also rather similar to Example 1, but this
  1825.   time we try to read and write at the same time. To be able
  1826.   to do several requests simultaneously we need one request
  1827.   block for each command. In this example we use three
  1828.   separate request blocks. Using asynchronous commands but
  1829.   puts the task to sleep just before we clear and return 
  1830.   everything.
  1831.  
  1832. Example 4
  1833.   This example does not do anything, but it consists of
  1834.   several useful functions that you can use yourself after
  1835.   small modifications. The functions demonstrates all
  1836.   commands there exist for the serial device, so if you
  1837.   had problems in understanding how a command was used you
  1838.   can look here.
  1839.