My userspace program is like this(this is only part of code):
char path[SIZE];
printf( "Enter the path of the block device to add or remove: ");
fgets(path, SIZE, stdin);
path[strcspn(path, "\n")] = '\0';
int fd = open( path, O_RDWR );
if( fd < 0 )
{
perror( "Failed to open device" );
exit( EXIT_FAILURE );
}
while( 1 )
{
int input;
printf( "Enter a number [ 0 for add and 1 for remove ]: " );
scanf( "%d", &input );
switch( input )
{
case 0:
if( ioctl( fd, MY_BLOCK_DEVICE_ADD, &path ) < 0 )
{
perror( "Failed to add device" );
exit( EXIT_FAILURE );
}
break;
case 1:
if( ioctl( fd, MY_BLOCK_DEVICE_REMOVE, &path ) < 0 )
{
perror( "Failed to remove device" );
exit( EXIT_FAILURE );
}
break;
case 2:
close(fd);
return 0;
}
in '.h' file I have defined custom IOCTL commands -
#define MY_BLOCK_DEVICE_ADD _IOWR('M', 1, char*)
#define MY_BLOCK_DEVICE_REMOVE _IOWR('M', 2, char*)
in driver/module code -
static int device_ioctl( struct block_device *dev, fmode_t mode, unsigned int cmd, unsigned long arg )
{
printk(KERN_INFO "in ioctl");
int ret;
char path[SIZE];
switch( cmd )
{
case MY_BLOCK_DEVICE_ADD:
if( copy_from_user( path, (char *)arg, SIZE ) )
{
return -EFAULT;
}
path[strcspn(path, "\n")] = '\0';
register_block_device(path);
printk( KERN_INFO "Device added\n" );
break;
case MY_BLOCK_DEVICE_REMOVE:
if( copy_from_user( path, (char *)arg, SIZE ) )
{
return -EFAULT;
}
unregister_block_device();
printk( KERN_INFO "Device removed\n" );
break;
default:
return -ENOTTY;
}
return 0;
}
But every time when I call IOCTL from userspace, I am getting invalid argument error. I verified changing magic numbers but didn't succeed. Can you plz help me with this?
EDIT Note that these aren't full code snippets.
The problem is that you try to do your own device-IOCTL calls on a totally different device.
If, as you claim in a comment, that you open
the /dev/sdb
device, then you can't do the IOCTL calls on it. You must open your own device, then call the IOCTL on that device:
// Error checking omitted
int mydevice = open("/dev/myowndevicefile", O_RDWR);
ioctl(mydevice, MY_BLOCK_DEVICE_ADD, path);