/proc/devices still shows unregistered device - linux

I am learning to write my first Linux char driver, but can't seem to make it work as expected.
The code for the driver module's init and exit functions are below:
static int __init one_init(void)
{
int result;
printk(KERN_DEBUG "In ones init call");
result = alloc_chrdev_region(&onedev, 0, 4, "one");
printk("Allocated device major: %d, first minor: %d",MAJOR(onedev),MINOR(onedev));
return 0;
}
static void __exit one_exit(void)
{
unregister_chrdev_region(onedev,4);
printk(KERN_DEBUG "In ones exit call");
}
My device still shows in /proc/devices after I unload my driver, whose exit function calls unregister_chrdev_region.
The dmesg command prints shows that my driver's init and exit calls were made.
I saw a few related questions, but the answers did not solve my seemingly simple problem.
What am I doing or expecting wrong?

Use 'rmmod modulename' in the terminal. This should unload the module and remove the associations.

Related

Linux kernel insmod failed with error Invalid parameters

I have a simple kernel module and want to define an IRQ. If I call in the code the following function, the module can not be inserted:
result = request_irq(12,
test_irq,
0,
"testgpio",
NULL);
This is the error from insmod:
insmod: ERROR: could not insert module gpioc.ko: Invalid parameters
The hardware is a RPI 4 with 2 GB and Ubuntu 64Bit.
static irqreturn_t test_irq(int irq, void *data)
{
/*interrupt-handling*/
return IRQ_HANDLED;
}
#I tried this to get the irq number but without success:
struct gpio_desc *gpio = NULL;
gpio = gpiod_get(NULL, "SPI_CE0_N", GPIOD_OUT_HIGH);
if (NULL == gpio){
printk(KERN_INFO "GPIO_TEST: invalid GPIO16\n");
return -ENODEV;
}
int n = gpiod_to_irq(gpio);
if (n <= 0){
printk(KERN_INFO "GPIO_TEST: invalid IRQ\n");
return -ENODEV;
}
It is not clear to use the function "gpiod_get". Here especially the first parameter!
Does anyone know where a working example exists?
Apparently you get EINVAL error from request_irq() according to the comments. The requested IRQ may not be correct. For GPIO, you may need to use gpio_to_irq() function to get the IRQ associated to a given GPIO.
The GPIO documentation documentation provides the pin to GPIO number. The latter is passed to gpio_to_irq() to get the IRQ.

Invoke execvp from linux driver

Currently, i want to call execvp from kernel side.
My program is programmed to go to halt mode.
So i have tried to setup below code:
char *argv[] = { "/sbin/halt", "-f", NULL };
char * envp[] = {
"SHELL=/bin/sh",
"HOME=/",
"PATH=.:/sbin:/usr/sbin:/bin:/usr/bin",
"PWD=/",
NULL };
rc = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
It seems that the code can execute halt command well.
But it does not meet the requirement about the electric signal.
I have checked, when i call execvp from the user space:
execvp ("halt", argv);
It worked well as expected.
I know that execvp will replace the current running programming by the new one specified in passing argument. When i use call_usermodehelper, that does not happen, i think it could be the difference.
Anyone know how can i solved this problem? How to make execvp work in driver similar to user space.
Thanks!

insmod: ERROR: could not insert module : No child processes

i am trying to run the linux kernel module in linux kernel.
But what is happening, sometimes it succeeds and run, sometimes insertion of module fails with error :
insmod: ERROR: could not insert module netlinkKernel.ko: No child processes
and kernel logs shows it is failing at print
Error creating socket nl_sk
I think its a common error , and i do not think it has to do anything with module.
I am just creating two netlink sockets in module. when i comment the second socket creation line, With one netlink sockets, the module is working fine, but with two as pasted in code below, it alywas gives this error, then again, when i try the module with one netlink socket, then it also fails and i have to reboot the system.
static int __init hello_init(void) {
printk("Entering: %s\n",__FUNCTION__);
// This is for 3.6 kernels and above.
struct netlink_kernel_cfg cfg = {
.input = hello_nl_recv_msg,
};
struct netlink_kernel_cfg cfg1 = {
.input = hello_nl_recv_msg1,
};
nl_sk = netlink_kernel_create(&init_net, NETLINK_USER, &cfg);
nl_sk1 = netlink_kernel_create(&init_net, NETLINK_USER1, &cfg1);
//nl_sk = netlink_kernel_create(&init_net, NETLINK_USER, 0, hello_nl_recv_msg,NULL,THIS_MODULE);
if(!nl_sk)
{
printk(KERN_ALERT "Error creating socket nl_sk.\n");
return -10;
}
if(!nl_sk1)
{
printk(KERN_ALERT "Error creating socket nl_sk1.\n");
return -10;
}
return 0;
}
Can anyone please shed a light on this ?
NB: I am not (yet) a kernel coding master.
If I understand your query correctly, this module will insert properly so long as the 3rd netlink_kernel_create line is commented out. If this is the case, it is likely because once a Netlink socket is created for a specific unit (NETLINK_USER), it needs to be freed using netlink_kernel_release before it can be recreated again with another netlink_kernel_create. This is also why you cannot load the module after it has already failed to load; you are never releasing the allocated netlink sockets. Also, the 3rd invocation of netlink_kernel_create is incorrect for kernels after 3.7.
My recommendation would be to restructure your code to be something like this:
nl_sk = netlink_kernel_create(&init_net, NETLINK_USER, &cfg);
if(!nl_sk)
{
printk(KERN_ALERT "Error creating socket nl_sk.\n");
return -10;
}
nl_sk1 = netlink_kernel_create(&init_net, NETLINK_USER1, &cfg1);
if(!nl_sk1)
{
printk(KERN_ALERT "Error creating socket nl_sk1.\n");
netlink_kernel_release(nl_sk);
return -10;
}
Also, you should include matching netlink_kernel_release calls in your module_exit function
Ok, i changed the value for #define NETLINK_USER1 32 from 32 to 30 and it worked fine. Both sockets created. Need to see fn prototype
netlink_kernel_create(&init_net, NETLINK_USER1, &cfg1);
to check what possible values it expects as the middle argument.

Linux kernel module to read out GPS device via USB

I'm writing a Linux kernel module to read out a GPS device (a u-blox NEO-7) via USB by using the book Linux Device Drivers.
I already can probe and read out data from the device successfully. But, there is a problem when reading the device with multiple applications simultaneously (I used "cat /dev/ublox" to read indefinitely). When the active/reading applications is cancelled via "Ctrl + C", the next reading attempt from the other application fails (exactly method call usb_submit_urb(...) returns -EINVAL).
I use following ideas for my implementation:
The kernel module methods should be re-entrant. Therefore, I use a mutex to protect critical sections. E.g. allowing only one reader simultaneously.
To safe ressources, I reuse the struct urb for different reading requests (see an explanation)
Device-specific data like USB endpoint address and so on is held in a device-specific struct called ublox_device.
After submitting the USB read request, the calling process is sent to sleep until the asynchronous complete handler is called.
I verified that the ideas are implemented correctly: I have run two instances of "cat /dev/ublox" simultaneously and I got the correct output (only one instance accessed the critical read section at a time). And also reusing the "struct urb" is working. Both instances read out data alternatively.
The problem only occurs if the currently active instance is cancelled via "Ctrl + C". I can solve the problem by not reusing the "struct urb" but I would like to avoid that. I.e. by allocating a new "struct urb" for each read request via usb_alloc_urb(...) (usually it is allocated once when probing the USB device).
My code follows the USB skeleton driver from Greg Kroah-Hartman who also reuse the "struct urb" for different reading requests.
Maybe someone has a clue what's going wrong here.
The complete code can be found on pastebin. Here is a small excerpt of the read method and the USB request complete handler.
static ssize_t ublox_read(struct file *file, char *buffer, size_t count, loff_t *pos)
{
struct ublox_device *ublox_device = file->private_data;
...
return_value = mutex_lock_interruptible(&ublox_device->bulk_in_mutex);
if (return_value < 0)
return -EINTR;
...
retry:
usb_fill_bulk_urb(...);
ublox_device->read_in_progress = 1;
/* Next call fails if active application is cancelled via "Ctrl + C" */
return_value = usb_submit_urb(ublox_device->bulk_in_urb, GFP_KERNEL);
if (return_value) {
printk(KERN_ERR "usb_submit_urb(...) failed!\n");
ublox_device->read_in_progress = 0;
goto exit;
}
/* Go to sleep until read operation has finished */
return_value = wait_event_interruptible(ublox_device->bulk_in_wait_queue, (!ublox_device->read_in_progress));
if (return_value < 0)
goto exit;
...
exit:
mutex_unlock(&ublox_device->bulk_in_mutex);
return return_value;
}
static void ublox_read_bulk_callback(struct urb *urb)
{
struct ublox_device *ublox_device = urb->context;
int status = urb->status;
/* Evaluate status... */
...
ublox_device->transferred_bytes = urb->actual_length;
ublox_device->read_in_progress = 0;
wake_up_interruptible(&ublox_device->bulk_in_wait_queue);
}
Now, I allocate a new struct urb for each read request. This avoids the problem with the messed up struct urb after an active read request is cancelled by the calling application. The allocated struct is freed in the complete handler.
I will come back to LKML when I optimize my code. For now, it is okay to allocate a new struct urb for each single read request. The complete code of the kernel module is on pastebin.
static ssize_t ublox_read(struct file *file, char *buffer, size_t count, loff_t *pos)
{
struct ublox_device *ublox_device = file->private_data;
...
retry:
ublox_device->bulk_in_urb = usb_alloc_urb(0, GFP_KERNEL);
...
usb_fill_bulk_urb(...);
...
return_value = usb_submit_urb(ublox_device->bulk_in_urb, GFP_KERNEL);
...
}
static void ublox_read_bulk_callback(struct urb *urb)
{
struct ublox_device *ublox_device = urb->context;
...
usb_free_urb(ublox_device->bulk_in_urb);
...
}

Linux (Ubuntu) ioctl KDGETLED/KDGKBLED always 0

Code snippet below; basically, I am grabbing the active vt and issuing an ioctl KDGETLED against that terminal for the current state of the capslock/numlock/scrolllock keys and I always get result=0, regardless of the state of the lock keys.
I've tried this on multiple Linux boxes, all running variants of Ubuntu (e.g. Mint). I've tried other fds for the KDGETLED command such as "/dev/tty", "/dev/console", 0, etc. I'm running into the same problem with KDGKBLED. Are others experiencing the same issue, am I doing something silly, am I running into poorly written drivers, or something else?
int fd;
vt_stat stat;
fd = open("/dev/tty0", O_RDONLY);
if (ioctl(fd, VT_GETSTATE, &stat) == -1) {
fprintf(stderr, "Error on VT_GETSTATE\n");
exit(1);
}
close(fd);
char tty[128];
sprintf(tty, "/dev/tty%d", stat.v_active);
printf("Query tty: %s\n", tty);
char result;
fd = open(tty, O_RDWR | O_NDELAY, 0);
if (ioctl(fd, KDGETLED, &result) == -1) {
fprintf(stderr, "Error on KDGETLED\n");
exit(1);
}
close(fd);
printf("LED flag state: %d\n", result);
Thanks, in advance, to all who review my question.
Checkout the driver code, especially the struct file_operations instance for that driver, and check the function assigned to the .ioctl member - if that is poorly coded (I've seen a lot of shitty stuff happening in ioctls) then that is definitely your issue.
In this case I am pretty sure it is the drivers fault. As long the ioctl command shows no compile error, everything - especially error handling and input checking - is the task of the driver.

Resources