user340
user340

Reputation: 383

Passing struct to device driver through IOCTL

I am trying to pass a struct from user space to kernel space. I had been trying for many hours and it isn't working. Here is what I have done so far..

int device_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg){

int ret, SIZE;


switch(cmd){

    case PASS_STRUCT_ARRAY_SIZE:

        SIZE = (int *)arg;
        if(ret < 0){
            printk("Error in PASS_STRUCT_ARRAY_SIZE\n");
            return -1;  
        }
        printk("Struct Array Size : %d\n",SIZE);
        break;

    case PASS_STRUCT:


        struct mesg{
            int pIDs[SIZE];
            int niceVal;
        };

        struct mesg data;

        ret = copy_from_user(&data, arg, sizeof(*data));
        if(ret < 0){
            printk("PASS_STRUCT\n");
            return -1;  
        }

        printk("Message PASS_STRUCT : %d\n",data.niceVal);
        break;

    default :
        return -ENOTTY;
}

return 0;
  }

I have trouble defining the struct. What is the correct way to define it? I want to have int pIDs[SIZE]. Will int *pIDs do it(in user space it is defined like pIDs[SIZE])?

EDIT:

With the above change I get this error? error: expected expression before 'struct' any ideas?

Upvotes: 2

Views: 8591

Answers (1)

osgx
osgx

Reputation: 94345

There are two variants of the structure in your question.

 struct mesg1{
  int *pIDs;
  int niceVal;
 };

 struct mesg2{
  int pIDs[SIZE];
  int niceVal;
 };

They are different; in case of mesg1 you has pointer to int array (which is outside the struct). In other case (mesg2) there is int array inside the struct.

If your SIZE is fixed (in API of your module; the same value used in user- and kernel- space), you can use second variant (mesg2).

To use first variant of structure (mesg1) you may add field size to the structure itself, like:

 struct mesg1{
  int pIDs_size;
  int *pIDs;
  int niceVal;
 };

and fill it with count of ints, pointed by *pIDs.

PS: And please, never use structures with variable-sized arrays in the middle of the struct (aka VLAIS). This is proprietary, wierd, buggy and non-documented extension to C language by GCC compiler. Only last field of struct can be array with variable size (VLA) according to international C standard. Some examples here: 1 2

PPS:

You can declare you struct with VLA (if there is only single array with variable size):

 struct mesg2{
  int niceVal;
  int pIDs[];
 };

but you should be careful when allocating memory for such struct with VLA

Upvotes: 1

Related Questions