Linux: device appears in /dev but cannot be accessed - linux

I have created a Linux device driver and can add it to the system (insmod, mknod). When I look in /dev I see it listed as camerax:
ls -l /dev/camerax
crw-r--r-- 1 root root 245, 0 Jun 27 17:19
Even so, I cannot access it. Whatever I do, I get an error.
For example:
int fd = open("/dev/camerax", O_RDONLY);
printf("%d [%s]\n", fd, strerror(errno));
Generates:
-1 [No such device or address]
I'm running as a super user. Any suggestions?

Your Module is not linked to the special file which you have mentioned so it is giving error.
If your module is successfully inserted verify in /proc/devices using cat command
cat /proc/devices.
file created using mknod in the path /dev/____ is just a refrence to your driver
The major and minor number should match with your inserted device.

I have solved the problem.
Instead of creating the major device number dynamically, as described in the documentation, I now set it explicitly to 61. Everything now works.
The only difference I can see between the working and non-working versions is the major number (and yes, I change anything that uses the device number so I am always using the appropriate one).
This adds one more bizarre feature of the system to my growing list.

Related

PWM without sysfs

I am pretty new to linux kernel.I am trying to generate PWM through linux. The API man talks about a sysfs interface. I want to implement a userspace program in C. But using PWM forces me to use a command line. Furthermore, using read, write is a problem in C as when I am using cd, it is changing path directory.
Thus the path is variable. Is there any way I can pass values to pwm_config() without using sysfs? Perhaps through ioctl? If yes, then what would be the procedure?
Application C code:
void main(){
int export = open("/sys/class/pwm/pmwchip0/export",O_WRONLY);
int period,duty_cycle,enable;
if(export == -1)
{
perror("Export:");
}
and so on for other files like period and duty cycle.
When I try to run my application I get the following error.
Export:: No such file or directory
Export_write: Bad file descriptor
Period_write:: Bad file descriptor
Duty_cycle_write:: Bad file descriptor
Enable_write:: Bad file descriptor
As far as I know, the sysfs is the only standard userspace interface to PWM. But anything you can do from the command line can be done in C (the shell is written in C, after all).
The problem you are having with cd is not actually a problem. Inside sysfs the directories in /sys/class/pwd/* are actually symbolic links to the proper devices. In your case /sys/class/pwm/pwmchip0 is a symlink to /sys/devices/soc0/amba/f8001000.timer/pwm/pwmchip0.
The funny thing is that some shells, when you cd a symbolic link will resolve to the real directory, but other shells will actually keep the symlink name as the current directory.
But that issue with the directory symlinks should not be an issue for you. A C program willing to manage PWM devices should not change the working directory. Instead open the files with the full path:
open("/sys/class/pwm/pwmchip0/npwm", O_RDONLY);
and so on.

Open file by inode

Is it possible to open a file knowing its inode?
ls -i /tmp/test/test.txt
529965 /tmp/test/test.txt
I can provide path, inode (above 529965) and I am looking to get in return a file descriptor.
This is not possible because it would open a loophole in the access control rules. Whether you can open a file depends not only on its own access permission bits, but on the permission bits of every containing directory. (For instance, in your example, if test.txt were mode 644 but the containing directory test were mode 700, then only root and the owner of test could open test.txt.) Inode numbers only identify the file, not the containing directories (it's possible for a file to be in more than one directory; read up on "hard links") so the kernel cannot perform a complete set of access control checks with only an inode number.
(Some Unix implementations have offered nonstandard root-only APIs to open a file by inode number, bypassing some of the access-control rules, but if current Linux has such an API, I don't know about it.)
Not exactly what you are asking, but (as hinted by zwol) both Linux and NetBSD/FreeBSD provide the ability to open files using previously created “handles”: These are inode-like persistent names that identify a file on a file system.
On *BSD (getfh and fhopen) using this is as simple as:
#include <sys/param.h>
#include <sys/mount.h>
fhandle_t file_handle;
getfh("<file_path>", &file_handle); // Or `getfhat` for the *at-style API
// … possibly save handle as bytes somewhere and recreate it some time later …
int fd = fhopen(&file_handle, O_RDWR);
The last call requiring the caller to be root however.
The Linux name_to_handle_at and open_by_handle_at system calls are similar, but a lot more explicit and require the caller to keep track of the relevant file system mount IDs/UUIDs themselves, so I'll humbly link to the detailed example in the manpage instead. Beware, that the example is not complete if you are looking to persist the handles across reboots; one has to convert the received mount ID to a persistent filesystem identifier, such as a filesystem UUID, and convert that back to a mount ID later on. In essence they do the same however. And just like on *BSD using the later system call requires elevated privileges (CAP_DAC_READ_SEARCH to be exact).

Linux Module file missing

Actually I'm a beginner and I'm trying to learn the concept of low-level driver and high level driver. I want to know how a module depends on other modules for their operation.
I've done lsmod command. I found these lines in the output.
parport_pc 25962 1
lp 7028 0
parport 32635 3 ppdev,parport_pc,lp
From the above lines, I understood that there exist modules like,
parport_pc
lp
parport
I've found source code parport_pc.c, lp.c, in the directory /usr/src/drivers/parport. But I can't find the source code for parport in my entire file system. Even though I found parpot.ko inside /lib/modules/linux2.6.32-37-generic/kernel/parport.
Also in the directory /usr/src/drivers/parport, I've seen a line in the Makefile like,
obj-$(CONFIG_PARPORT) += parport.o
So where can I find the parport.c file ? I've searched the entire file system using the command
find / -name parport.c
but no result. Why is the file parport.c missing?
The parport.o file is compiled from multiple .c files, including share.c, ieee1284.c, ieee1284_ops.c, and procfs.c, and possibly including daisy.c and probe.c, all under the drivers/parport/ directory of the Linux sources. (This information was taken from Linux 3.5-rc3-00203-g8874e81, which is a bit newer than the kernel you are looking at, but the parallel port drivers don't change much any more).
To find this information, I looked at the same Makefile and noted that the parport-objs variable was initially set to share.o ieee1284.o ieee1284_ops.o procfs.o and daisy.o probe.o was added if CONFIG_PARPORT_1284 was set to y.

Weird URI string displayed on mounting iPod

I have written a small program to detect whenever a device is mounted on a desktop running Linux. I have used GIO for this. I am extracting the URI of the mounted resource and displaying it to the user. When I put in a CD I get a URI string which looks like file:///media/cdrom0/ which I can understand. But when I mount an iPod the URI I see is something like gphoto2://[usb:002,028]. What does this mean? I have observed that the second number (028) keeps increasing every time I take the device out and plug it back in. Can some one interpret this URI for me?
Update: As shodanex answered, the two numbers are the bus number and device number respectively. gphoto2:// indicates the protocol (PTP/MTP).
gphoto2://[usb:002,028]
I guess 002 is the bus number, and 28 is the adress of the device on that bus.
It maps to the second and fourth field of the lsusb util output. Here is an example
on my system :
Bus 001 Device 015: ID 05e3:0715 Genesys Logic, Inc. USB 2.0 microSD Reader
I guess it would translate to :
usb:001,015
I have these kinds of URL's in Nautilus too, but the other response doesn't explain how that relates to a mount location on disk. I can navigate through the files on an SD card via the Nautilus file browser, but I don't see any of these files in /mnt/ or /media/ or anywhere else I would typically look for automatically mounted file systems.
Eventually I tried right-clicking the folder, selecting "Open with other application," choosing a text editor, and then I could see that the folder was actually mounted at:
'~/.gvfs/gphoto2 mount on usb%3A001,010'
I wish Nautilus and other tools in ubuntu would provide some more obvious way to find these files... this seems pretty un-intuitive.

Problem with chardev.c example from The Linux Kernel Module Programmers Guide

I compiled and ran the chardev.c example from the lkmpg and when writing to the device received an unexpected error:
anon#anon:~/lkmpg$ sudo echo "hi" > /dev/chardev
bash: /dev/chardev: Permission denied
The module write function looks like this:
/*
* Called when a process writes to dev file: echo "hi" > /dev/chardev
*/
static ssize_t
device_write(struct file *filp, const char *buff, size_t len, loff_t * off)
{
printk(KERN_ALERT "Sorry, this operation isn't supported.\n");
return -EINVAL;
}
I'm not getting the expected error of invalid operation and the error printed to /var/log/messages.
I can read from the device with no problem, receiving the expected results:
anon#anon:~/lkmpg$ cat /dev/chardev
I already told you 6 times Hello world!
The device /dev/chardev is created manually using:
sudo mknod /dev/chardev c 252 0
What's the deal?
--Edit--
Apparently when I mknod to create the device it ends up with the following permissions:
crw-r--r-- 1 root root 252, 0 2009-10-30 09:27 /dev/chardev.
Once I did sudo chmod a+w /dev/chardev the driver worked as expected.
However, people have said it is not correct to do this.
What is the correct course of action and why?
A really, really, really straight forward and simple example of how to implement character drivers can be found in drivers/watchdog/softdog.c
You can compare your code to this example, which shows you how to do the following:
Read from the device
Write to the device
Present an ioctl interface via the device
While softdog is a very useful tool, its as much a tutorial as anything else. Alan Cox threw it together, so its a good example of more 'proper' implementation.
If you can post the whole source to your module, we can help you find out why your function is not being entered as expected.
Update:
It is perfectly acceptable to allow under privileged users to write to character devices! I repeat, it is perfectly acceptable to allow under privileged users to write to character devices! If this was not the case, stuff like FUSE, Modems, USB Gadgets, CD ROMS and other things would require root access to use.
What you can do is take advantage of group memberships. I.e., on Ubuntu, users permitted to use FUSE (file system in user space) should belong to the 'fuse' group, which permits granular access on who can and can not use that feature. Similarly, on some of my systems, a QRNG (quantum random number generator) is in use .. and is (you guessed it) a character device. I need to allow PHP to access that device , so I:
Create a QRNG group
Make sure PHP runs as the user (not anonymous system users)
Add users owning apps that need access to the device to the QRNG group
I hope that clears it up :)
I think, actual problem is the command which you issued to write is incorrect. Try
#sudo sh -c "echo "hi" > /dev/chardev"
If you want to run multiple commands with sudo then you should use command as shown above. With this, you dont need to do chmod and change its permissions as well. Hope this helps.

Resources