- provides way to implement control commands
- deprecated but widely used
- basically a (command) number is sent to driver
API example:
#define DIGIO_IOC_MAGIC 'C'
/* parameter for DIGIO_SET_VAL ioctl */
struct digio_par {
unsigned int pinnr;
unsigned int val;
};
/*
* ioctl definitions
*/
#define DIGIO_GET_VAL _IOR(DIGIO_IOC_MAGIC, 0, struct digio_par *)
#define DIGIO_SET_VAL _IOW(DIGIO_IOC_MAGIC, 1, struct digio_par *)
#define DIGIO_RESET_ALL _IO(SCULL_IOC_MAGIC, 2)
#define DIGIO_IOC_MAXNR 2
static int digio_ioctl (struct inode *inode, struct file *file, uint cmd, unsigned long arg)
{
int err;
struct digio_par par;
/* sanity checks */
if(_IOC_TYPE(cmd) != DIGIO_IOC_MAGIC) return -ENOTTY;
if(_IOC_NR(cmd) > DIGIO_IOC_MAXNR) return -ENOTTY;
switch(cmd) {
case DIGIO_GET_VAL:
if((err = digio_get_pin(par.pinnr, &par.val)) < 0)
goto out;
if(copy_to_user((unsigned int *)arg, &par, sizeof(struct digio_par)) != 0) {
printk(KERN_CRIT "%s: copy_to_user failed", __FUNCTION__);
err = -EFAULT;
goto out;
}
break;
case DIGIO_SET_VAL:
if(copy_from_user(&par, (unsigned int *)arg, sizeof(struct digio_par))) {
err = -EFAULT;
printk(KERN_CRIT "%s: copy_from_user failed", __FUNCTION__);
goto out;
}
digio_set_pin(par.pinnr, par.val);
break;
case DIGIO_RESET_ALL:
digio_reset_all();
break;
default:
/* this is defined by POSIX */
return -ENOTTY;
}
/* all ok */
err = 0;
out:
return err;
}