Discussion:
How to use properly IOCTL on a driver?
(too old to reply)
jfloresmu92@yahoo.com [nuttx]
2018-02-15 10:00:23 UTC
Permalink
Hi!

After solve my problem with I2C bus, I felt secure enough to develop a driver for NuttX. So I'm developing the driver for the HIH-6130 humidity/sensor which it's a I2C sensor, but it's pretty simple to use it.
At the moment it's working perfectly all the functions (I can open, close and read the device data) except the IOCTL.

And here comes my questions.
I would like to have the possibility to configure with IOCTL which measure I want to show (If you want to choose the humidity measure or the temperature measure).
To implement this functions I've done the next things:
- This is my function IOCTL function:

static int hih6130_ioctl(FAR struct file *filep,int cmd,unsigned long arg){
FAR struct hih6130_dev_s *priv;
switch (cmd)
{
//You can choose between temperature measure or humidity measure
case SNIOC_TEMPERATURE:
{
sninfo("Set temperature measure\n");
priv->opt=true;
sninfo("priv value %i\n",priv->opt);
}
break;
case SNIOC_HUMIDITY:
{
sninfo("Set humidity measure\n");
priv->opt=false;
sninfo("priv value %i\n",priv->opt);
}
break;
}
}

As you can see it's pretty simple, depending the argument you change the value of opt and then in the read function, you check the value of "opt" and it call to the humidity measure function or temperature measure function.
Also I initialize the function in register function giving a true value.

But the problem comes in the read function. And it doesn't matter if I change or not that it always the initialization value.
I check the value like this:
if(priv->opt){
*data=temperature();
}
else{
*data=humidity();
}

Everything compile correctly, initialization fine and also when I use the ioctl function in my example, the debug info returns me the correct value, but it looks like it only save the data in the function.
Any idea?

Thank you for the help!!
jfloresmu92@yahoo.com [nuttx]
2018-02-15 10:24:00 UTC
Permalink
Hi!

Finally I saw that the problem it was that I forgot to add:
FAR struct inode *inode = filep->f_inode;

Now it's working! And the function looks like this:
static int hih6130_ioctl(FAR struct file *filep,int cmd,unsigned long arg){
FAR struct inode *inode = filep->f_inode;
FAR struct hih6130_dev_s *priv = inode->i_private;
switch (cmd)
{
//You can choose between temperature measure or humidity measure
case SNIOC_TEMPERATURE:
{
sninfo("Set temperature measure\n");
priv->opt=true;
sninfo("priv value %i\n",priv->opt);
}
break;
case SNIOC_HUMIDITY:
{
sninfo("Set humidity measure\n");
priv->opt=false;
sninfo("priv value %i\n",priv->opt);
}
break;
}
}

Also I have another question if you let me.
I'm testing the driver to see if everything is correct and if it works properly. So it's possible to share this driver uploading to the repository? And if so, I need to check something?
Sebastien Lorquet sebastien@lorquet.fr [nuttx]
2018-02-15 10:59:49 UTC
Permalink
Ah ok, so as I guessed, you had something uninitialized :)

My other mail still raises interesting design issues.

Sebastien
 
Hi!
FAR struct inode      *inode = filep->f_inode;
static int hih6130_ioctl(FAR struct file *filep,int cmd,unsigned long arg){
  FAR struct inode      *inode = filep->f_inode;
  FAR struct hih6130_dev_s *priv   = inode->i_private;
  switch (cmd)
    {
      //You can choose between temperature measure or humidity measure
      {
        sninfo("Set temperature measure\n");
        priv->opt=true;
        sninfo("priv value %i\n",priv->opt);
      }
      break;
      {
        sninfo("Set humidity measure\n");
        priv->opt=false;
        sninfo("priv value %i\n",priv->opt);
      }
      break;
    }
}
Also I have another question if you let me.
I'm testing the driver to see if everything is correct and if it works
properly. So it's possible to share this driver uploading to the repository?
And if so, I need to check something?
jfloresmu92@yahoo.com [nuttx]
2018-02-15 14:05:37 UTC
Permalink
Hi Sebastien.

I've made your suggestion about the threatening of the data, because you get both data(temperature and humidity) at the same time.

To be sure that I'm doing right, I've checked other drivers and I found that the INA219 driver have some similarities with the HIH6130 (I mean, in both case you measure two different data at the same time).
So I followed how it returns the data with the structure.

Thank you!

Sebastien Lorquet sebastien@lorquet.fr [nuttx]
2018-02-15 10:49:43 UTC
Permalink
Hello

Do you really want to do this in the first place?

Most sensors in nuttx return info via read, where read() must be called with a
pointer to a struct that contain fields for all measurements. You can check in
your read function that the passed length is correct. The struct has to be
declared in the header that gets included by the user app.

This way, the read function can read BOTH temp and humidity without having to
choose with an ioctl.

It is probably useful to read both parameters at the same time, performances are
better and you are sure that both measurements were made at the same time! Seems
a better design.


That said, you are not telling us everything: where does priv come from? If the
snipped you posted is complete, then priv is not initialized. If you want to
remember parameters over the open/read/write/close sequence, you have to use the
priv pointer from the struct file structure, not from the struct inode structure.

This means that, if you allow the user to open your device multiple times, you
have to provide (and alloc!) a private file struct each time the device is
opened (and free() it at close()). If the device can only be opened once
simultaneously, a global storage can be used.

Sebastien
Post by ***@yahoo.com [nuttx]
 
Hi!
After solve my problem with I2C bus, I felt secure enough to develop a driver
for NuttX. So I'm developing the driver for the HIH-6130 humidity/sensor which
it's a I2C sensor, but it's pretty simple to use it.
At the moment it's working perfectly all the functions (I can open, close and
read the device data) except the IOCTL.
And here comes my questions.
I would like to have the possibility to configure with IOCTL which measure I
want to show (If you want to choose the humidity measure or the temperature
measure).
static int hih6130_ioctl(FAR struct file *filep,int cmd,unsigned long arg){
  FAR struct hih6130_dev_s *priv;
  switch (cmd)
    {
      //You can choose between temperature measure or humidity measure
      {
        sninfo("Set temperature measure\n");
        priv->opt=true;
        sninfo("priv value %i\n",priv->opt);
      }
      break;
      {
        sninfo("Set humidity measure\n");
        priv->opt=false;
        sninfo("priv value %i\n",priv->opt);
      }
      break;
    }
}
As you can see it's pretty simple, depending the argument you change the value
of opt and then in the read function, you check the value of "opt" and it call
to the humidity measure function or temperature measure function.
Also I initialize the function in register function giving a true value.
But the problem comes in the read function. And it doesn't matter if I change
or not that it always the initialization value.
if(priv->opt){
      *data=temperature();
}
else{
      *data=humidity();
}
Everything compile correctly, initialization fine and also when I use the
ioctl function in my example, the debug info returns me the correct value, but
it looks like it only save the data in the function.
Any idea?
Thank you for the help!!
Loading...