0

Please help with a question.
I'm trying to resolve programm example for parport loopback wtire/read.
While reading program skip first 6 symbols due to select timeout and I can't understand what to do in that situation.
How to trace what is hold function and how to fix it.
Thanks.

Some profile data:

Kernel: Linux pc-Cantiga-ICH9M-Chipset 5.4.0-33-generic  
Ubuntu: bullseye/sid  
Compiler: gcc (Ubuntu 9.3.0-10ubuntu2) 9.3.0

Write to port

# write.c
#include "testlpt.h"
#include <sys/types.h>

/* example how to write data */
void  *write_data() {
unsigned char status='\0';

  for(int i=0;i<SIZE_BUF;i++)  {


    int mode=0xFF;
int     res=ioctl(fd, PPDATADIR, &mode);

      fprintf(stdout,"Data= %c\n",data);
#if 1
#endif

counter=counter+0;
  res=ioctl(fd, PPWDATA, &data);

      if (res < 0)   {
       fprintf(stdout,"Error write (%d)(%s)\n",errno,strerror(errno));
       break;
    }
  data++;
  usleep(USLEEP);
   }
 int res=ioctl(fd, PPRELEASE);
 if (res < 0 ){
fprintf(stdout,"Release error \n"); 
 }
pthread_exit(0);
}

/* example how to read the status lines. */
int status_pins(int fd)
{
    unsigned char val;

    int res=ioctl(fd, PPRSTATUS, &val);
    if (res <0){
        fprintf(stdout,"PPRSTATUS ERROR res = %d\n",res);
        return -1;
    }
// val ^= PARPORT_STATUS_BUSY; /* /BUSY needs to get inverted */
fprintf(stdout,"ERROR  = 0x%02x \n", (val & (PARPORT_STATUS_ERROR | PARPORT_STATUS_BUSY))); //==PARPORT_STATUS_ERROR)?"HI":"LO",val ^= PARPORT_STATUS_BUSY);
fprintf(stdout,"BUSY = 0x%02x \n", (val & PARPORT_STATUS_BUSY)); //==PARPORT_STATUS_ERROR)?"HI":"LO",val ^= PARPORT_STATUS_BUSY);
fprintf(stdout,"SELECT  = 0x%02x \n", (val & PARPORT_STATUS_SELECT)); //==PARPORT_STATUS_ERROR)?"HI":"LO",val ^= PARPORT_STATUS_BUSY);
fprintf(stdout,"ACK  = 0x%02x \n", (val & PARPORT_STATUS_ACK)); //==PARPORT_STATUS_ERROR)?"HI":"LO",val ^= PARPORT_STATUS_BUSY);
}

Header

# testlpt.h

#ifndef _TESTLPT_H
#define _TESTLPT_H

#include <stdio.h>
#include <fcntl.h>      
#include <sys/types.h>      
#include <sys/stat.h>       
#include <sys/ioctl.h>
#include <linux/parport.h>
#include <linux/ppdev.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
#include <sys/io.h>
#include <errno.h>
#include <error.h>
#include <string.h> 

#define DEVICE "/dev/parport0"
#define SIZE_BUF 26
#define USLEEP 1000
#define TIMEOUT 1

#include <poll.h>

#include <sys/epoll.h>

void *reads_data();
void *write_data();

int claim_port ();
int port_select(int fd);

extern int fd;
extern unsigned char data;
extern int counter;

static pthread_mutex_t lock;

#endif /* testlpt.h */

Read from port

/* read.c */

#include <sys/select.h>
#include "testlpt.h"



void *reads_data() {

unsigned char data;
data='\0';


int res=0;

fd_set rfds;

counter =0;

for(;;) {
struct timeval tv;  
tv.tv_sec = 0;
tv.tv_usec = 100;
errno =0;



FD_ZERO(&rfds);
FD_SET(fd, &rfds);

#if 1
    int mode=0x00;
    res=ioctl(fd, PPDATADIR, &mode);
  res=select (fd + 1, &rfds, (fd_set *)NULL, (fd_set *)NULL, &tv);
    fprintf(stdout,"res select = %d counter = %d \n",res,counter);
  if( res== -1 ) {
    fprintf(stdout,"End Read by select \n");
       continue;

    } else if (res == 0){
    fprintf(stdout,"Select timeout\n");
    } else {
    counter++;
    if ( FD_ISSET(fd , &rfds ) ) {
    res=ioctl(fd, PPRDATA, &data);  /* now fetch the data! */


    if (res < 0) {
    fprintf(stdout,"End Read by end of array\n");
    break;
        }
    }
   }
#endif  


    fflush(stdout);
    usleep(USLEEP);

 if (( data > 0x40 ) && ( data < 0x5B)) {
    fprintf(stdout,"counter = %d data = %c\n",counter,data);
    }
counter++;
}

FD_ZERO(&rfds);
    fprintf(stdout,"End Read\n");
pthread_exit(0);
}

Main function

#include <testlpt.h>

int fd;
unsigned char data=0x41;
int counter=0;

int main(int argc, char **argv)
{
    pthread_t id[1]; 
    pthread_attr_t attr;        

    if ((fd=open(DEVICE, O_RDWR | O_NOCTTY )) < 0) {
        fprintf(stderr, "can not open %s\n", DEVICE);
        return 5;
    }
    int  mode = IEEE1284_MODE_COMPAT;
     int res=ioctl(fd, PPSETMODE, &mode);

     if( res== -1 ) {
    fprintf(stdout,"PPSETMODE ERROR\n");
  }
unsigned int modes;
     res=ioctl(fd, PPGETMODE, &modes);  
  if( res ==0 ) {
    fprintf(stdout,"MODES= 0x%02x\n", modes);
  }

#if 1
  while (claim_port() <0 ){
fprintf (stdout,"Claimt port error = %d\n",0);
sleep(1);
continue;
}
#endif

pthread_attr_init(&attr);
pthread_mutex_init(&lock, NULL);

#if 1
    if (pthread_create(&id[0],0,&write_data,NULL)){
perror("pthread create error!");
    }
    if (pthread_create(&id[1],0,&reads_data,NULL)){
perror("pthread create error!");
    }

if (pthread_join(id[0],NULL)) {
        perror("pthread exit error!");
        }
if (pthread_join(id[1],NULL)) {
        perror("pthread exit error!");
        }

    ioctl(fd, PPRELEASE);
    close(fd);
    exit(EXIT_SUCCESS);
#endif
}

int claim_port() {
  if (ioctl(fd, PPCLAIM) < 0) {
//  if (ioctl(fd, PPEXCL) < 0) {
  int errsv = errno;
  fprintf(stdout,"CLAIM errno %s \n",strerror(errsv));
        close(fd);
        return -1;
    }
        return 0;
}

Program output

Data= A
Data= B
Select timeout
Data= C
Select timeout
Data= D
Select timeout
Data= E
Select timeout
Data= F
Select timeout
Data= G
Select timeout
Data= H
Data= I
Data= J
counter = 7 data = I
Data= K
counter = 9 data = J
Data= L
counter = 11 data = K
Data= M
counter = 13 data = L
Data= N
counter = 15 data = M
counter = 17 data = N
Data= O
counter = 19 data = N
Data= P
counter = 21 data = O
Data= Q
counter = 23 data = P
Data= R
Data= S
counter = 25 data = Q
Data= T
counter = 27 data = S
Data= U
counter = 29 data = T
Data= V
counter = 31 data = U
Data= W
counter = 33 data = V
Data= X
counter = 35 data = W
counter = 37 data = X
Data= Y
Data= Z
counter = 39 data = X
counter = 41 data = Z
Cvl
  • 1
  • 2
  • regarding: `void *reads_data()` this is not a valid signature for a thread function. Suggest: `void *reads_data( void *dummy ) { (void)dummy; ... – user3629249 Jun 06 '20 at 17:43
  • for ease of readability and understanding: 1) please consistently indent the code: Indent after every opening brace '{'. Unindent before every closing brace '}'. Suggest each indent level be 4 spaces – user3629249 Jun 06 '20 at 17:45
  • regarding function: `int status_pins(int fd)` the end of that function contains several calls to `fprintf()` but fails to return a value. This causes the compiler to output: *untitled1.c:102:1: warning: control reaches end of non-void function [-Wreturn-type]* AND the function is not even called in the posted code. – user3629249 Jun 06 '20 at 17:48
  • regarding: `int claim_port ();` This prototype is for a function that takes no parameters, so, to produce the correct code, the prototype should be: `int claim_port ( void );` – user3629249 Jun 06 '20 at 17:59
  • regarding the header file: `testlpt.h` Header files can contain 'extern' references to data instances, but they must not contain actual data instances. Because a new instance of the data is created everywhere that header file is included. – user3629249 Jun 06 '20 at 18:02
  • regarding: `static pthread_mutex_t lock;` This creates an instance of the mutex in every file, (I.E. several instances), but only the `main()` function even bothers to initialize it. BTW: there are several valid ways to initialize a mutex, setting it to `NULL` is NOT one of them. Suggest: `(if you don't just remove that mutex from your code, to use: `pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;` Note: there are several other valid initialization values – user3629249 Jun 06 '20 at 18:09
  • regarding: `pthread_t id[1];` This creates an array with only one entry however: `if (pthread_create(&id[0],0,&write_data,NULL))` and `if (pthread_create(&id[1],0,&reads_data,NULL))` are expecting 2 entries. (remember that array indexes in C have the range: 0...(number of entries in array-1) Suggest: `pthread_t id[2];` otherwise the code is accessing beyond the end of the array, which is undefined behavior and can lead to a seg fault event – user3629249 Jun 06 '20 at 18:18
  • regarding: `pthread_attr_t attr; ` and `pthread_attr_init(&attr);` This `attr` is never used, suggest removing both those statements. – user3629249 Jun 06 '20 at 18:20
  • regarding statements like: `int res=ioctl(fd, PPSETMODE, &mode);` what are you trying to perform with such statements and the `mode` variable? – user3629249 Jun 06 '20 at 18:23
  • when some function, like: `pthread_create()` fails, do not be executing code like it was successful. Rather, cleanup and exit – user3629249 Jun 06 '20 at 18:28
  • regarding: `int main(int argc, char **argv)` When these two parameters are not used, the compiler will output a warning message for each unused parameter. Much better to avoid the compiler messages by using the other valid `main()` signature: `int main( void )` – user3629249 Jun 06 '20 at 18:32
  • Make plain fork version, but not positive result: https://www.pastebin.in/ohpJsKCI3Y – Cvl Jun 08 '20 at 06:49
  • regarding the 'pastbin' link: 1) copy/select/paste the code directly as an edit to your question. 2) apply this comment: *for ease of readability and understanding: 1) please consistently indent the code: Indent after every opening brace '{'. Unindent before every closing brace '}'. Suggest each indent level be 4 spaces* to your code – user3629249 Jun 08 '20 at 19:18
  • the code in 'pastebin' does not compile! amongst MANY other problems, this statement: `fds = (struct pollfd) memset(&fds,0,sizeof(fds))` is missing the trailing semicolon `;` – user3629249 Jun 08 '20 at 19:41
  • regarding: `fds = (struct pollfd) memset(&fds,0,sizeof(fds));` the function: `memset` returns a pointer to the first parameter, A POINTER. However, `struct pollfd` is NOT a pointer. – user3629249 Jun 08 '20 at 19:44
  • When compiling, always enable the warnings, then fix those warnings. ( for `gcc`, at a minimum use: `-Wall -Wextra -Wconversion -pedantic -std=gnu11` ) Note: other compilers use different options to produce the same results. – user3629249 Jun 08 '20 at 19:45

1 Answers1

0

It's magic, but I added

int intrpt=0x09;  
ioctl(fd,PPWDATA,&intrpt);

before writing and program start work correctly

Cvl
  • 1
  • 2