home *** CD-ROM | disk | FTP | other *** search
/ World of A1200 / World_Of_A1200.iso / datafiles / text / c_manual / devices / paralleldevice / example3.c < prev    next >
C/C++ Source or Header  |  1995-02-27  |  20KB  |  504 lines

  1. /***********************************************************/
  2. /*                                                         */
  3. /* Amiga C Encyclopedia (ACE) V3.0      Amiga C Club (ACC) */
  4. /* -------------------------------      ------------------ */
  5. /*                                                         */
  6. /* Book:    ACM Devices                 Amiga C Club       */
  7. /* Chapter: Parallel Device             Tulevagen 22       */
  8. /* File:    Example3.c                  181 41  LIDINGO    */
  9. /* Author:  Anders Bjerin               SWEDEN             */
  10. /* Date:    92-04-26                                       */
  11. /* Version: 1.00                                           */
  12. /*                                                         */
  13. /*   Copyright 1992, Anders Bjerin - Amiga C Club (ACC)    */
  14. /*                                                         */
  15. /* Registered members may use this program freely in their */
  16. /*     own commercial/noncommercial programs/articles.     */
  17. /*                                                         */
  18. /***********************************************************/
  19.  
  20.  
  21.  
  22. /* This example is rather similar to Example 1, but this time     */
  23. /* we do not wait for the parallel port to complete our request.  */
  24. /* We are also trying to read and write at the same time. To be   */
  25. /* able to do several requests simultaneously we need one request */
  26. /* block for each command. In this example we use three separate  */
  27. /* request blocks.                                                */
  28.  
  29.  
  30.  
  31. #include <exec/types.h>       /* STRPTR           */
  32. #include <devices/parallel.h> /* Parallel Device  */
  33.  
  34.  
  35.  
  36. /* Size of our data buffer: */
  37. #define MY_BUFFER_SIZE 200
  38.  
  39. /* Parallel flags: (Check for end-of-file characters.) */
  40. #define PARALLEL_FLAGS PARF_EOFMODE
  41.  
  42. /* Additional flags: (Nothing) */
  43. #define ADDITIONAL_FLAGS 0
  44.  
  45.  
  46.  
  47. /* Declare a pointer to our reply port: */
  48. struct MsgPort *replymp = NULL;
  49.  
  50. /* Declare pointers to our parallel request blocks:      */
  51. /* One is used for reading, the other for writing, and   */
  52. /* finally the last one is used for other commands.      */
  53. struct IOExtPar *parallel_req_read = NULL;    /* Read    */
  54. struct IOExtPar *parallel_req_write = NULL;   /* Write   */
  55. struct IOExtPar *parallel_req_command = NULL; /* Command */
  56.  
  57. /* Store the parallel device error here: */
  58. UWORD parallel_dever = TRUE;
  59.  
  60. /* Declare two data buffers. The first one will contain the  */
  61. /* information we want to send, and the other will be filled */
  62. /* with all data we have collected:                          */
  63. BYTE read_buffer[ MY_BUFFER_SIZE ];
  64. BYTE write_buffer[ MY_BUFFER_SIZE ];
  65.  
  66.  
  67.  
  68. /* Declare our functions: */
  69.  
  70. /* Our main function: */
  71. void main();
  72.  
  73. /* Clears and removes everything nice and neatly: */
  74. void clean_up( UBYTE error, STRPTR text );
  75.  
  76. /* Sets the parallel parameters: */
  77. UBYTE SetParParams(
  78.   struct IOExtPar *ioreq,
  79.   UBYTE parallel_flags,
  80.   ULONG extended_flags,
  81.   UBYTE *eof_chars
  82. );
  83.  
  84. /* Explains error messages: */
  85. void ParError( UBYTE error );
  86.  
  87. /* Sends data to the parallel device without waiting: */
  88. void ParWriteNoWait(
  89.   struct IOExtPar *ioreq,
  90.   BYTE *data,
  91.   ULONG length
  92. );
  93.  
  94. /* Collects data from the parallel device without waiting: */
  95. void ParReadNoWait(
  96.   struct IOExtPar *ioreq,
  97.   BYTE *data,
  98.   ULONG length
  99. );
  100.  
  101.  
  102.  
  103. void main()
  104. {
  105.   /* Error number: */
  106.   UBYTE error;
  107.   
  108.   /* Byte pointers, used to copy the request blocks: */
  109.   BYTE *r_ptr;
  110.   BYTE *w_ptr;
  111.   BYTE *c_ptr;
  112.  
  113.   /* Loop variable: */
  114.   int loop;
  115.  
  116.   /* The eight end-of-file characters: */
  117.   /* They MUST be in descending order! */
  118.   UBYTE eof_char[8]={ 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00 };
  119.  
  120.   
  121.   
  122.   /* Get a reply port: (No name, priority 0) */
  123.   replymp = (struct MsgPort *)
  124.     CreatePort( NULL, 0 );
  125.   if( !replymp )
  126.     clean_up( 0, "Could not create the reply port!" );
  127.  
  128.  
  129.  
  130.   /* Create request block "Read": */
  131.   parallel_req_read = (struct IOExtPar *)
  132.     CreateExtIO( replymp, sizeof( struct IOExtPar ) );
  133.   if( !parallel_req_read )
  134.     clean_up( 0, "Not enough memory for the request block Read!" );
  135.  
  136.   /* Create request block "Write": */
  137.   parallel_req_write = (struct IOExtPar *)
  138.     CreateExtIO( replymp, sizeof( struct IOExtPar ) );
  139.   if( !parallel_req_write )
  140.     clean_up( 0, "Not enough memory for the request block Write!" );
  141.  
  142.   /* Create request block "Command": */
  143.   parallel_req_command = (struct IOExtPar *)
  144.     CreateExtIO( replymp, sizeof( struct IOExtPar ) );
  145.   if( !parallel_req_command )
  146.     clean_up( 0, "Not enough memory for the request block Command!" );
  147.  
  148.  
  149.  
  150.  
  151.   /* Open the parallel device for the read request: */
  152.   parallel_dever = OpenDevice( PARALLELNAME, 0, parallel_req_read, 0 );
  153.   if( parallel_dever )
  154.     clean_up( parallel_dever, "Could not open the Parallel Device!" );
  155.  
  156.   /* Since we can not open the parallel device any more  */
  157.   /* for the other request (we use exclusive access), we */
  158.   /* have to copy the whole read request block into the  */
  159.   /* write and command request blocks.                   */
  160.  
  161.   /* Get the start address of all request blocks: */
  162.   r_ptr = (BYTE *) parallel_req_read;
  163.   w_ptr = (BYTE *) parallel_req_write;
  164.   c_ptr = (BYTE *) parallel_req_command;
  165.  
  166.   /* Copy the request block, byte by byte: */
  167.   for( loop=0; loop < sizeof( struct IOExtPar ); loop++ )
  168.   {
  169.     /* Copy one byte: */
  170.     *w_ptr = *r_ptr; /* Write   */
  171.     *c_ptr = *r_ptr; /* Command */
  172.     
  173.     /* Step one byte foreward: */
  174.     w_ptr++;
  175.     r_ptr++;
  176.     c_ptr++;
  177.   }
  178.  
  179.  
  180.  
  181.   /* Set the parallel device's parameters: */
  182.   error = (UBYTE) SetParParams(
  183.     parallel_req_write, /* Pointer to our parallel request block.        */
  184.     PARALLEL_FLAGS,     /* Parallel flags.                               */
  185.     ADDITIONAL_FLAGS,   /* Additional flags.                             */
  186.     eof_char            /* Pointer to an array of eight end-of-file chr. */
  187.   );
  188.  
  189.   /* OK? */
  190.   if( error )
  191.     clean_up( error, "Could not set the parallel parameters!" );
  192.  
  193.  
  194.  
  195.  
  196.   /* Send 0 bytes to the parallel port and return immediately: */
  197.   /* (Since I do not know what you have connected to your      */
  198.   /* parallel port, it is best not to do anything.)            */
  199.   ParWriteNoWait( parallel_req_write, write_buffer, 0 ); 
  200.  
  201.   /* Collect 0 bytes from the parallel port and return immediately: */
  202.   ParReadNoWait( parallel_req_read, read_buffer, 0 ); 
  203.  
  204.  
  205.  
  206.   /* Do whatever you want... */
  207.  
  208.  
  209.  
  210.   /* When you are using asynchronious commands you have to be  */
  211.   /* careful with cleaning up. All requests you have started   */
  212.   /* MUST have been completed or aborted before you may close  */
  213.   /* the device. All reply massages must also be removed from  */
  214.   /* the reply port.                                           */
  215.   /*                                                           */
  216.   /* There exist several different ways on how to wait for     */
  217.   /* requests to be completed. In example 2 we used the        */
  218.   /* function CheckIO(), and Remove(). In this example will    */
  219.   /* we use the WaitIO() which puts our program to sleep and   */
  220.   /* will first wake up when the request have been completed.  */
  221.   /* WaitIO() will automatically remove the reply messages,    */
  222.   /* and if the request have already been competed it will     */
  223.   /*  immediately return.                                      */
  224.   /*                                                           */
  225.   /* The difference between a busy wait and a task sleep is    */
  226.   /* that your program can do other things while waiting if    */
  227.   /* you are using the busy wait. The task sleep should be     */
  228.   /* used if you do not want to do anything while waiting.     */
  229.   /*                                                           */
  230.   /* NOTE! Do NOT use a busy wait if you can manage with a     */
  231.   /* task sleep! Computer time should always be used with      */
  232.   /* care.                                                     */
  233.   /*                                                           */
  234.   /* We have three request blocks that has to be looked after. */
  235.   /* The "Command" block was only used by the SetParParams()   */
  236.   /* function and was used as a synchronous request. [DoIO()]  */
  237.   /* We will therefore (nor should we) wait for it to be       */
  238.   /* completed or try to remove any reply message. The two     */
  239.   /* other request blocks were on the other hand asynchronous, */
  240.   /* and we must therefore both wait for them to be completed  */
  241.   /* and make sure that the reply messages are removed. The    */
  242.   /* WaitIO() function will do both of these things.           */
  243.   /*                                                           */
  244.   /* NOTE! Do NOT try to wait for a reuest that has not been   */
  245.   /* started [either by a SendIO() or BeginIO()].              */
  246.  
  247.   /* Task sleep... (It does not matter in which order we wait.) */
  248.   WaitIO( parallel_req_read );
  249.   WaitIO( parallel_req_write );
  250.  
  251.  
  252.  
  253.   /* Clean up and quit: */
  254.   clean_up( 0, "The End!" );
  255. }
  256.  
  257.  
  258.  
  259. /* Close and return everything that has been */
  260. /* opened and allocated before we quit:      */
  261.  
  262. void clean_up( UBYTE error, STRPTR text )
  263. {
  264.   /* Print some information about the problem: */
  265.   if( error )
  266.     ParError( error );
  267.  
  268.   /* Close the Parallel Device: */ 
  269.   if( !parallel_dever )
  270.     CloseDevice( parallel_req_read );
  271.  
  272.   /* Deallocate the parallel "read" request block: */
  273.   if( parallel_req_read )
  274.     DeleteExtIO( parallel_req_read, sizeof( struct IOExtPar ) );
  275.  
  276.   /* Deallocate the parallel "write" request block: */
  277.   if( parallel_req_write )
  278.     DeleteExtIO( parallel_req_write, sizeof( struct IOExtPar ) );
  279.  
  280.   /* Deallocate the parallel "command" request block: */
  281.   if( parallel_req_command )
  282.     DeleteExtIO( parallel_req_command, sizeof( struct IOExtPar ) );
  283.  
  284.   /* Remove the replyport: */
  285.   if( replymp )
  286.     DeletePort( replymp);
  287.  
  288.   /* Print the message: */
  289.   printf( "\n%s\n", text );
  290.  
  291.   /* Quit: */
  292.   exit( 0 );
  293. }
  294.  
  295.  
  296.  
  297. /* SetParParams() sets the parallel parameters. It initializes a IOExtPar  */
  298. /* structure, and does a PDCMD_SETPARAMS commad. If everything is OK it    */
  299. /* returns NULL, else an error number is returned.                         */
  300. /*                                                                         */
  301. /* Synopsis: er = SetParParams( io, bl, br, bt, rl, wl, sl, sf, ef, chr ); */
  302. /*                                                                         */
  303. /* er:       (UBYTE) SetParParams() returns 0 if everything was OK, else   */
  304. /*           an error value is returned. See function ParError() for more  */
  305. /*           information.                                                  */
  306. /*                                                                         */ 
  307. /* io:       (struct IOExtPar *) Pointer to the parallel request block you */
  308. /*           want to initialize.                                           */
  309. /*                                                                         */
  310. /*           PARF_RAD_BOOGIE Not supported by the parallel device for the  */
  311. /*                           moment.                                       */
  312. /*                                                                         */
  313. /*           PARF_SHARED     Set this flag if you want to allow other      */
  314. /*                           tasks running at the same time to use the     */
  315. /*                           parallel device. The default is exclusive-    */
  316. /*                           access. (If some other task is using the      */
  317. /*                           parallel device with the shared bit set, and  */
  318. /*                           you call this function with exclusive access, */
  319. /*                           your request will fail.)                      */
  320. /*                                                                         */
  321. /*           PARF_EOFMODE    Set this flag if you want to check for end of */
  322. /*                           file characters. (You may use up to eight end */
  323. /*                           of file characters, which are specified       */
  324. /*                           below.)                                       */
  325. /*                                                                         */
  326. /* ef:       (ULONG) Not supported by the parallel device for the moment.  */
  327. /*                                                                         */
  328. /* chr:      (UBYTE *) Pointer to an array containing eight end-of-file    */
  329. /*           characters. If the parallel flag "PARF_EOFMODE" is set, the   */
  330. /*           parallel device will check each character which is sent or    */
  331. /*           received, and if it matches one of the end-of-file characters */
  332. /*           the read/wite request is terminated.                          */
  333.  
  334. UBYTE SetParParams(
  335.   struct IOExtPar *ioreq, /* Pointer to our parallel request block.        */
  336.   UBYTE parallel_flags,   /* Parallel flags.                               */
  337.   ULONG extended_flags,   /* Additional parallel flags.                    */
  338.   UBYTE *eof_chars        /* Pointer to an array containing eight end-of-  */
  339.                           /* file characters.                              */
  340. )
  341. {
  342.   int loop;           /* Used in the loop.      */
  343.   UBYTE *ptr;         /* Unsigned byte pointer. */
  344.   
  345.   
  346.   /* Set parallel flags: */
  347.   ioreq->io_ParFlags = parallel_flags;
  348.  
  349.   /* Set additional flags: */
  350.   ioreq->io_PExtFlags = extended_flags;
  351.   
  352.   
  353.   /* Get the address of the IOTArray: */
  354.   ptr = (UBYTE *) &(ioreq->io_PTermArray);
  355.  
  356.   /* Set all eight end of file characters: */
  357.   for( loop=0; loop < 8; loop++ )
  358.   {
  359.     /* Copy character after character: */
  360.     *ptr = eof_chars[ loop ];
  361.  
  362.     /* Step one byte foreward: */
  363.     ptr++;
  364.   }
  365.   
  366.   /* All values have now been set, lets do a PDCMD_SETPARAMS request: */
  367.   ioreq->IOPar.io_Command = PDCMD_SETPARAMS;
  368.   
  369.   /* Do our request, and when complete return 0 if */
  370.   /* OK, else an error value:                      */
  371.   return( (UBYTE) DoIO( ioreq ) );
  372. }
  373.  
  374.  
  375.  
  376. /* ParError() tells the user what went wrong. You give it the error code */
  377. /* you received, and ParError() will print a short description of the    */
  378. /* problem. Useful when debugging.                                       */
  379. /*                                                                       */
  380. /* Synopsis: ParError( error );                                          */
  381. /*                                                                       */
  382. /* error:    (UBYTE) The error value you want to have explained.         */
  383.  
  384. void ParError( UBYTE error )
  385. {
  386.   switch( error )
  387.   {
  388.     case ParErr_DevBusy:
  389.       printf( "Some other task is already using the parallel Device!\n" );
  390.       break;
  391.     case ParErr_BufTooBig:
  392.       printf( "The parallel buffer is too big! (?)\n" );
  393.       break;
  394.     case ParErr_InvParam:
  395.       printf( "Invalid parameters!\n" );
  396.       break;
  397.     case ParErr_LineErr:
  398.       printf( "Line error, check all cables!\n" );
  399.       break;
  400.     case ParErr_NotOpen:
  401.       printf( "The Parallel Device is not open!\n" );
  402.       break;
  403.     case ParErr_PortReset:
  404.       printf( "Someone has resetted the Parallel Device!\n" );
  405.       break;
  406.     case ParErr_InitErr:
  407.       printf( "Could not initialize the Parallel Device!\n" );
  408.       break;
  409.  
  410.     default:
  411.       printf( "An unknown error was reported! Error nr: %d\n", error );
  412.   }
  413. }
  414.  
  415.  
  416.  
  417.  
  418.  
  419. /* ParWriteNoWait() sends some data to the Parallel Port, but returns */
  420. /* immediately. You only have to give it a pointer to the data you    */
  421. /* want to write and tell it how many bytes you want to transfer.     */
  422. /* Since it does not wait for the request to be completed, you have   */
  423. /* to take care of removing the message yourself. Note that all       */
  424. /* requests that have been started must be completed or aborted       */
  425. /* before your program may close the parallel device.                 */
  426. /*                                                                    */
  427. /* Synopsis: error = ParWriteNoWait( io, data, length );              */
  428. /*                                                                    */
  429. /* io:       (struct IOExtPar *) Pointer to an initialized parallel   */
  430. /*           request block.                                           */
  431. /*                                                                    */
  432. /* data:     (BYTE *) Pointer to the first byte of the data you want  */
  433. /*           to send (write).                                         */
  434. /*                                                                    */
  435. /* length:   (ULONG) How many bytes you want to transfer. If you want */
  436. /*           to continue to send data until we have received an end-  */
  437. /*           of-file character, set the length to -1. (Note that the  */
  438. /*           parallel device will then ONLY stop when it receives one */
  439. /*           of the specified end-of-file characters.)                */
  440.  
  441. void ParWriteNoWait(
  442.   struct IOExtPar *ioreq, /* Pointer to our parallel request block.   */
  443.   BYTE *data,             /* Pointer to the data you want to send.    */
  444.   ULONG length            /* The length of the data you want to send. */
  445. )
  446. {
  447.   /* We want to send (write) some data: */
  448.   ioreq->IOPar.io_Command = CMD_WRITE;
  449.  
  450.   /* Give the start address of our data: */
  451.   ioreq->IOPar.io_Data = (APTR) data;
  452.  
  453.   /* Set the length of the message: */
  454.   ioreq->IOPar.io_Length = length;
  455.  
  456.   /* Do our request and return immediately: */
  457.   SendIO( ioreq );
  458. }
  459.  
  460.  
  461.  
  462. /* ParReadNoWait() reads some data from the Parallel Port, but returns */
  463. /* immediately. You only have to give it a pointer to some memory      */
  464. /* where the data should be stored, and tell it how many bytes you     */
  465. /* want to read. Since it does not wait for the request to be          */
  466. /* completed, you have to take care of removing the message yourself.  */
  467. /* Note that all requests that have been started must be completed or  */
  468. /* aborted before your program may close the parallel device.          */
  469. /*                                                                     */
  470. /*                                                                     */
  471. /* Synopsis: error = ParReadNoWait( io, data, length );                */
  472. /*                                                                     */
  473. /* io:       (struct IOExtPar *) Pointer to an initialized parallel    */
  474. /*           request block.                                            */
  475. /*                                                                     */
  476. /* data:     (BYTE *) Pointer to the memory buffer where you want to   */
  477. /*           store all data.                                           */
  478. /*                                                                     */
  479. /* length:   (ULONG) How many bytes you want to read. If you want to   */
  480. /*           continue to send data until we have received an end-of-   */
  481. /*           file character, set the length to -1. (Note that the      */
  482. /*           parallel device will then ONLY stop when it receives one  */
  483. /*           of the end-of-file characters.)                           */
  484.  
  485. void ParReadNoWait(
  486.   struct IOExtPar *ioreq, /* Pointer to our parallel request block. */
  487.   BYTE *data,             /* Where the data should be placed.     */
  488.   ULONG length            /* How many bytes you want to read.     */
  489. )
  490. {
  491.   /* We want to read some data: */
  492.   ioreq->IOPar.io_Command = CMD_READ;
  493.  
  494.   /* Give the start address of our data: */
  495.   ioreq->IOPar.io_Data = (APTR) data;
  496.  
  497.   /* Set how many bytes you want to read: */
  498.   ioreq->IOPar.io_Length = length;
  499.  
  500.   /* Do our request and return immediately: */
  501.   DoIO( ioreq );
  502. }
  503.  
  504.