This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

problem with add_device function calls

Hi,
I am trying to add functions through add_device as shown below.
add_device("mydevice", _MSA, my_open, my_close, my_read, my_write, my_lseek, my_unlink, my_rename);

With this, the functions my_open etc are getting called when I call fopen etc.,

The problem is when I call fscanf and fprintf functions, the address the of the buffer is getting changed when the call goes to my_read and my_write functions.

When I do following,
  char str[20];
  fscanf(fp,"%s",str);
fscanf calls my_read. But the buf value in my_read(int fd, char *buf, unsigned int count) is different. So the copied data in my_read does not come to str.

Can somebody point me the problem here.
Also is there any document that gives the flow from fscanf function to my_read function and also how the buffer address changes.

thanks, Durga

//~~~~~~~~~~~ Code sample ~~~~~~~~~~~~~~~~
typedef struct
{
  unsigned char inuse;
  int fpos;
  char fname[24];
} my_file_type;

my_file_type file[10];

int my_open(const char *path, unsigned int flags, int mode)
{
  int file_num;
  file_num = get_unused_file();
  file[file_num].inuse = TRUE;
  strcpy(file[file_num].fname,path);
  file[file_num].fpos = 0;
  return(file_num);
}

int my_close(int fd)
{
  file[fd].inuse = FALSE;
  file[fd].fpos = 0;

  return 0;
}

my_read(int fd, char *buf, unsigned int count)
{
  FILE *fp;

  printf("my_read:: 0x%x\n",buf);

  fp = fopen (file[fd].fname,"r");
  fscanf(fp,"%s",buf);
  fclose(fp);
}

my_write(int fd, const char *buf, unsigned int count)
{
  FILE *fp;
  fp = fopen (file[fd].fname,"r");
  fprintf(fp,"%s",buf);
  fclose(fp);
}

int my_lseek(int dev_fd, off_t offset, int origin)
{
  return -1;
}

int my_rename(const char *old_name, const char *new_name)
{
  return -1;
}

int my_unlink(const char *path)
{

  return -1;
}

main()
{
  FILE *fp;
  char str_write[] = "Hello World!";
  char str_read[24];

  printf("main:: 0x%x\n",str_read);

  add_device("mydevice", _MSA,
      my_open,
      my_close,
      my_read,
      my_write,
      my_lseek,
      my_unlink,
      my_rename);

  fp = fopen("mydevice:testRead.txt","r");
  fscanf(fp,"%s",str_read);
  fclose(fp);

  printf("main:: %s\n",str_read);

}

  • It is not an error that the buf argument to my_read is different than the pointer you are trying to write to with fscanf. The buf argument to my_read points into the CIO buffer allocated for that file, not to any argument.

    Your problem is that my_read and my_write absolutely must return a value indicating the number of bytes successfully read, and yours fails to return any value. It's not immediately obvious, but you must also keep track of fpos for this file.

    A first try, which won't work properly:

    int my_read(int fd, char *buf, unsigned int count)
    {
      FILE *fp;
    
      printf("my_read:: 0x%x\n",buf);
    
      fp = fopen (file[fd].fname,"r");
      fscanf(fp,"%s",buf);
      if (file[fd].fpos >= strlen(buf)) return 0;
      fclose(fp);
      return file[fd].fpos = strlen(buf);
    }

    So why doesn't this work properly? fscanf is the wrong thing to use here - it won't get past the space after Hello.  In the low-level function read, you really should handle the input character-by-character:

    int my_read(int fd, char *buf, unsigned int count)
    {
        FILE *fp;
        int cur_pos = file[fd].fpos;
        int num_read;
    
        printf("my_read2:: 0x%x\n",buf);
    
        fp = fopen (file[fd].fname,"r");
        
        while (cur_pos--) fread(buf, 1, 1, fp);
    
        num_read = fread(buf, 1, count, fp);
    
        fclose(fp);
    
        file[fd].fpos += num_read;
    
        return num_read;
    }
    int main() {
        [..]
        fp = fopen("mydevice:testRead.txt","r");
        fscanf(fp,"%s",str_read);
        printf("main:: %s\n",str_read);
        fscanf(fp,"%s",str_read);
        printf("main:: %s\n",str_read);
        fclose(fp);
    }
    

    Of course, you really should not use the high-level functions; you should make calls to whatever device driver you'll be using.  However, I assume this is a practice exercise.

    Also, in my_write, it should be "w", not "r".

    [Edit: tweaked second call to fread to use count for efficiency -- Archaeologist]

  • Thanks for your reply.

    To summarize,

    1. The functions in my_read and my_write will have separare CIO buffer.

    2. Before calling my_write, data is copied to CIO buffer and my_write can use the CIO buffer to do actual writing.

    3. fread(buf,1,25,fd);
       int my_read(int fd, char *buf, unsigned int count)
      
       fread calls my_read; my_read reads 256 bytes of data to CIO buffer.
       my_read should return no of bytes

       data from CIO buffer is copied to buf of size = return value from my_read.
      
       Calling my_read is repeated in a loop until (sum of return values from my_read) = count.

    4. fread(buf, 1, 300, fd)
       Here fread calls my_read with count as 256, and then calls again with count as 144.

  • There are several buffers involved.  Each FILE object has its own buffer, and in addition there is a global CIOBUF shared between the HOST device (part of CIO) and the debugger.

    The "buf" argument to my_read and my_write will point into the FILE-specific buffer for your file.

    CIOBUF is only used by the "HOST" device, which communicates with the debugger through a breakpoint.  Your device should not refer to it.

    Regarding points 3 and 4, I'm not sure what you're trying to say.  Are you having a problem with fread?

  • I don't have problem with fread. I was trying to interpret data copy from fread buffer to my_read buffer.

    Thanks again.