0

I am trying to control a LED on a custom board. I have written the device driver and successfully loaded it. I have created a device file in /dev directory with the correct major number. Then I wrote a program in user plane to control the LED on the board, but my ioctl is failing with error number as 2 (No such File or Directory), the file descriptor returned is 3. Below is the application in user space.

int main(int argc, char **argv)
{
    struct  s_LEDControl sLedControlParam;  
    int     ledNumber;
    int     command;
    int     fDDevice;
    int     ioctlReturn;

    ledNumber   = atoi(argv[1]);
    command     = atoi(argv[2]);

    /* Prepare the message to be sent to Kernel Space */
    sLedControlParam.led = ledNumber;
    sLedControlParam.cmd = command;

    /* Open the device */
    fDDevice = open("/dev/newdevice_drv", O_RDWR);

    if(fDDevice == -1)
    {
         printf("ERROR: Cannot open the device /dev/newdevice_drv\n");
         exit(0);
    }

    ioctlReturn = ioctl(fDDevice, c_controlLED1, &sLedControlParam);

    if(ioctlReturn != 0)
    {
         printf("ERROR: ioctl failed Reason:%s FD:%d\n", strerror(errno), fDDevice);
    }

    close(fDDevice);
    return 0;
}

Just to check if something was wrong with the file descriptor, I passed a dummy file descriptor to ioctl and I got the correct error number. I am new to linux and device drivers, any help would be appreciated.

The above C program is cross compiled to PPC environment.

Below is some part of the driver code

MODULE_LICENSE("XXX");
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_SUPPORTED_DEVICE("XXXX");

/** Assign device functions to file_operation structure */
struct file_operations fops= {
        .owner=THIS_MODULE,
        .open=device_open,
        .release=device_release,
        .read=device_read,
        .write=device_write,
        .unlocked_ioctl=device_ioctl,
        .llseek=NULL,
};

static int device_ioctl( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
        enum e_FPGACommand e_cmd;
        e_cmd = (enum e_FPGACommand)cmd;

        printk("DEBUG: device_ioctl entered\n");

        switch(e_cmd)
        {
            case c_controlLED1: controlLED1_ioctl(arg);
            break;

            default: printk("ERROR: Invalid command %d\n", e_cmd);
                     return INVALID_IOCTL;
            break;
        }

        printk("DEBUG: device_ioctl exited\n");

        return OK;
}

static int controlLED1_ioctl(unsigned int arg)
{
    struct s_LEDControl *sLedControlParam;
    int result;

    sLedControlParam = (struct s_LEDControl *)kmalloc(sizeof(struct s_LEDControl), GFP_KERNEL);

    if(sLedControlParam == GLO_NULL)
    {
        printk("ERROR: Memory allocation failed in controlLED1_ioctl\n");
        return FAILURE_MEMORY_ALLOCATION;
    }

    result = copy_from_user(sLedControlParam, (struct s_LEDControl *)arg, sizeof(struct s_LEDControl));

    if(result > 0) 
    {
        printk("ERROR: copy_from_user in controlLED1_ioctl returned unfinished bytes\n");
        kfree(sLedControlParam);
        return FAILURE_COPY_FROM_USER;
    }

    if(sLedControlParam->cmd == On)
    {
        /* On - Do something */
    }

    return OK;
}

I can't see any error messages, when the device driver is loaded I get all the prints. When I try to run my application I can see that the device was opened and immediately closed but can't see any prints from my ioctl function.

Neo
  • 141
  • 5
  • 16
  • You're probably going to have to show the source code for the driver to get any help. Unless there's someone here who wants to write a checklist of what you should be doing in your driver. – sawdust Jan 30 '13 at 03:42
  • I have added the device driver code now, hope it helps to debug the issue – Neo Jan 30 '13 at 04:38
  • Your driver calls `register_chrdev()` to get a *dynamic* major number. I've never done that. I hardcode the major & minor numbers in the driver. What major & minor numbers did you use to create the device nodes? How did you ensure that the device node(s) and driver use the same major number? What kernel version is this for? Here's a driver w/hard device numbers: http://lxr.free-electrons.com/source/drivers/char/dsp56k.c – sawdust Jan 30 '13 at 09:12
  • @sawdust: I am using kernel **3.0.0-14.1-build3+**. When register_chrdev returns I print the major number, so once the driver is loaded into the kernel I have the major number used. Then I create the device file in /dev directory with the correct major number. – Neo Jan 30 '13 at 17:30
  • @sawdust: My problem was solved, I followed the steps mentioned by Ottavio, check it out. Thanks a lot for your help. – Neo Jan 30 '13 at 18:21

1 Answers1

2

Check this answer.

You have

static int device_ioctl( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)

but he says it has to be

static long device_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)

I haven't verified it, but maybe it helps. I was just curious because it never saw unlocked_ioctl before.

Community
  • 1
  • 1
Ottavio Campana
  • 4,088
  • 5
  • 31
  • 58
  • My problem is solved, I changed the declaration of the function. The posted which you showed also mentioned to use lock_kernel and unlock_kernel, I couldn't get the definition of these functions. Should I implement them myself ? I am new to linux, can you help ? I also read that BIG LOCKS should be avoided in new implementations, then what is the alternative to BIG LOCKS ? I am accepting your answer. – Neo Jan 30 '13 at 18:22
  • instead of BIG LOCKS, use mutexes. Moreover Big locks are deprecated. – MSharq Sep 12 '19 at 13:26