open() returns with "No such device" error, but there is such a device (linux) - c

I'm trying to use a somewhat old DAQ, and had to jump through a few hoops to get an old (circa 2004) device driver for it to compile (DTI-DT340 Linux-DAQ-PCI).
I've gotten to the point where it compiles, I can load the kernel module, it finds the card, and I can create the character devices using mknod.
But I can't seem to open these devices and keep getting errno 19 (ENODEV) 'No such device' when I try to
open("/dev/dt340/0",O_RDWR);
but mknod had no complaints about making it, and it's there:
# ls -l /dev/dt340/
total 0
crw-rw-r-- 1 root staff 250, 0 2009-04-23 11:02 0
crw-rw-r-- 1 root staff 250, 1 2009-04-23 11:02 1
crw-rw-r-- 1 root staff 250, 2 2009-04-23 11:02 2
crw-rw-r-- 1 root staff 250, 3 2009-04-23 11:02 3
Is there something I'm neglecting to do? What might be a reason open fails?
Here's the script I use to load the driver and make the devices.
#!/bin/bash
module="dt340"
device="dt340"
mode="664"
# invoke modprobe with all arguments we were passed
#/sbin/modprobe -t misc -lroot -f -s $module.o $* || exit 1
insmod $module.ko
# remove stale nodes
rm -f /dev/${device}/[0-3]
major=`awk "\\$2==\"$module\" {print \\$1}" /proc/devices`
mkdir -p /dev/${device}
mknod /dev/${device}/0 c $major 0
mknod /dev/${device}/1 c $major 1
mknod /dev/${device}/2 c $major 2
mknod /dev/${device}/3 c $major 3
# give appropriate group/permissions, and change the group
# not all distributions have staff; some have "users" instead
group="staff"
grep '^staff:' /etc/group > /dev/null || group="users"
chgrp $group /dev/${device}/[0-3]
chmod $mode /dev/${device}/[0-3]
Some additional info:
#grep dt340 /proc/devices
250 dt340
# lsmod | grep dt340
dt340 21516 0
# tail /var/log/messages
Apr 23 11:59:26 ve kernel: [ 412.862139] dt340 0000:03:01.0: PCI INT A -> GSI 22 (level, low) -> IRQ 22
Apr 23 11:59:26 ve kernel: [ 412.862362] dt340: In function dt340_init_one:
Apr 23 11:59:26 ve kernel: [ 412.862363] Device DT340 Rev 0x0 detected at address 0xfebf0000
#lspci | grep 340
03:01.0 Multimedia controller: Data Translation DT340
ANSWER: A printk confirmed that the -ENODEV was thrown from inside open(). Following an oldstyle
while ((pdev = pci_find_device(PCI_VENDOR_ID_DTI, PCI_ANY_ID, pdev)))
(which is deprecated), if(!pdev) ends up true, and returns the -ENODEV.
I'm inching closer - I guess I have to work through and update the pci code to use more modern mechanisms...

If the device shows up in /proc/devices, and you're sure you've got the number right in mknod, then the driver itself is refusing the open. The driver can return any error code from open() - including "no such device", which it might if it discovered a problem initialising the hardware.

I'd guess it is a problem in the driver, check the open function.
It shows up in /proc/devices, so all the generic device stuff seems to be ok.

mknod doesn't care if there is an device corresponding to the given major/minor numbers. Are you sure insmod is installing your module? What does lsmod tell you?
I'm unfamiliar with having to add the ".ko" extension. Is that something specific to your device driver?

Check through lspci and make sure hardware is properly initialized. If your system supports hotplug, pci_find_device won't work. The problem with this is a refcnt. The best way to deal and learn is to dissect the API. BOL !!

Related

How to find the scsi_host_template functions for a block device?

I was looking into the IO path of the Linux kernel, and towards the bottom in the function scsi_dispatch_cmd(), the driver code is invoked
rtn = host->hostt->queuecommand(host, cmd);
So, for my block device like /dev/sda/, is there a way to find out which hostt or scsi_host_template it is using. I want to check which function queuecommand is pointing to..
Just as a sketch of reflection on this subject.
In my machine for USB drive I can see this:
$ ls -l /dev/sdg
brw-rw---- 1 root disk 8, 96 Apr 27 01:21 /dev/sdg
$ ll /sys/dev/block/8\:96/device/drive
lrwxrwxrwx 1 root root 0 Apr 27 01:32 /sys/dev/block/8:96/device/driver -> ../../../../../../../../../bus/scsi/drivers/sd
So normally such block devices are handled through the regular Linux scsi disk driver. Which is related with e.g. usb handling:
$ lsmod | grep sd
sd_mod 49152 13
scsi_mod 225280 5 sd_mod,usb_storage,libata,uas,sg
In this particular case we can see the relation between queuecommand and mentioned drive:
$ grep queuecommand /proc/kallsyms
ffffffffc052be60 t uas_queuecommand [uas]
ffffffffc0582ad0 t queuecommand [usb_storage]
Now, being in Linux source dir:
$ grep -rnI '\.queuecommand =' | grep usb
drivers/usb/storage/uas.c:846: .queuecommand = uas_queuecommand,
drivers/usb/storage/scsiglue.c:609: .queuecommand = queuecommand,
Hope this will help you.

NUC serial port fail to open

I have a NUC in Ubuntu. I would like to write a program in c for serial port send and receive message.
The device is /dev/ttyUSB0.
It is success to use Linux command echo "message" > /dev/ttyUSB0 and use minicom to get the result.
But the device is open fail when using c program, fd always return -1
int fd;
fd = open ("/dev/ttyUSB0", O_RDWR);
Then I try to use raspbian pi in debian, and run the same program. It can open the device.
Is there any setting is missing in Ubuntu platform in NUC? Thanks you very match.
Update:
I print out the error message: open() failed with error [Permission denied],
then I try to use sudo to run the exe file, then I can get the usb device
this is current file detial
-rwxrwxr-x 1 u u 9048 Aug 22 19:15 uart
-rw-rw-r-- 1 u u 1424 Aug 22 19:15 uart.c
Beside I use chown change the permission of file, is there any other method?
sudo usermod -a -G dialout <User>
/dev/ttyxy is owned by the user root and the group dialout , so I added myself to the dialout group. At least worked for me.
If your situation allow you to use sudo, then why any alternative !

setgid does not work on /tmp/

I have this C program:
#include <sys/stat.h>
#include <stdlib.h>
int main(void) {
if (chmod("/tmp/foo", 0755 | S_ISGID) < 0) {
exit(1);
}
exit(0);
}
When I run it like this:
rm -f /tmp/foo &&
touch /tmp/foo &&
./a.out &&
ls -al /tmp/foo &&
a.out runs with exit code 0 but the output is:
-rwxr-xr-x 1 philipp wheel 0 Mar 16 06:58 /tmp/foo
Why is the groupid flag not set here? The permissions should be -rwxr-sr-x.
The following things would fix the issue (but I still wonder why I see this effect):
running the program as root
running it in a different directory
running it on Linux
setting the set-user-id (S_ISUID)
I can swear it worked in an earlier version of OSX
What I tried but didn't work:
chmod g+s /tmp/foo also doesn't work
disabling csrutil did not change anything
altering the permissions on /tmp/ to something different, e.g. 0777 or 4777
So the question remains: what does make /tmp/ different from the other directories if it's not the permissions? The only difference I could see is:
ls -al /
showed tmp as this:
lrwxr-xr-x# 1 root wheel 11 Dec 11 19:28 tmp -> private/tmp
The # sign at the end shows that there are some non-unix properties set on the directory. Querying those with ls -l# /tmp shows:
lrwxr-xr-x# 1 root wheel 11 Dec 11 19:28 /tmp -> private/tmp
com.apple.FinderInfo 32
com.apple.rootless 0
Update: According to comment feedbacks and a downvote I figured the question is confusing, so I totally revised the question and the title. During revision I found out that I wrongly compared the effects of my program against chmod u+s which was wrong, I need to compare against chmod g+s, I also corrected this in my question.
The chmod() system call sets the permissions on a file to only the value you provide. This means that setting permissions to S_IRUSR | S_ISGID clears all other permissions, including user write and execute.
What you probably want is:
chmod("/tmp/foo", 0755 | S_ISGID);
(0755 being the octal mode for user read+write+execute and group/other read+execute -- it's a lot less typing than the equivalent constants.)

Linux: Using module functions

Let's say I have a module which has this function my_open:
int my_open( struct inode *inode, struct file *filp ) {
filp->private_data = //allocate private data
if( filp->f_mode & FMODE_READ )
//handle read opening
if( filp->f_mode & FMODE_WRITE )
//handle write opening
if (MINOR( inode->i_rdev )==2){
filp->f_op = &my_fops2;
}
return 0;
}
how do I use this function from the shell/terminal?
This is either the open function for a device driver,
or it’s a sheep in wolf’s clothing [sic]. 
In the unlikely event that this is ordinary, vanilla user-level code,
compile it into an executable and use that.  But if it is a device driver’s open function,
First of all,
determine whether it is compiled/linked into the currently running kernel. 
If it isn’t, make it so (compile/link it into the kernel, and reboot).
Alternatively,
you may have the ability to load it into the kernel dynamically. 
Exactly how to do that depends on your particular operating system
and is out of scope for this question.
Find out whether it is a block device or a character device,
and what its major device number is. 
I can’t tell you specifically how to do that, either;
consult your local resources.
OK, let’s suppose that it is a character device with major number 42. 
Look through /dev (with ls -l) for entries that begin with c
(for “character”) and contain 42, something
where the size should be, like this:
drwxr-xr-x 1 root root 512 Feb 10 2015 .
drwxr-xr-x 1 root root 1024 Feb 10 2015 ..
crw-rw-rw- 1 root root 42, 0 Aug 15 18:31 foo
crw-rw-rw- 1 root root 42, 2 Aug 15 18:31 fu
crw-rw-rw- 1 root root 42, 17 Aug 15 18:31 fubar
If you can’t find any, create some.  See man mknod for details. 
You should probably create one with minor device number 2
and at least one with a different number
(because the code treats 2 as a special case).
Do to the /dev/whatever files whatever you want to,
based on the intended function of the driver. 
(Determining the intended function of the driver is out of scope.) 
For instance, you might try things like
od -cb /dev/foo
echo "Hello, world." > /dev/fu
Naturally, if it’s a block device,
replace c in the above instructions with b.

MinorFS: Installation

Hi i want to install MinorFS 0.3.5 to my computer. My Ubuntu version is 14.04 LTS. But i had some problems while installing the program.
Firstly i installed all fuse modules and gcc and run the script install.pl.
The program is designed for Ubuntu 8. As a result it wants to install fuse module to start the script install.pl.
But there is not a loadable fuse module for Ubuntu 14.04 LTS. I research about it and i see that, for the latest version of Ubuntu, the kernel is configured to include FUSE instead of compiling it as a module. So, i modified the perl code in install.pl and
install the script.(I install fuseiso with command apt-get install fuseiso just in case.)
Everyting is great for the moment. But for the next step, i run the command on terminal "/etc/init.d/minorfs start ".
And i get this error : " The path specified in /var/minorfs/viewfs.startcap is not a valid base dir for minorviewfs
"
This command runs the minorcapfs and minorviewfs i guess.Minorcapfs run succesfully but for minorviewfs i got this error.
The code which gives the Error writen below:(in minorviewfs file)
unless (-d $basepath) {
print STDERR "The path specified in $VARDIR/viewfs.startcap is not a valid base dir for minorviewfs\n";
exit 1;
}
Then for test, i print my " $basepath " and it's : /mnt/minorfs/cap/61ce0488ac06eba530e178a0d1716ec576b47f71
I couldn't solve this error.
Please help me to get rid of this problem.
Thank you!
I solved the problem with manually making a directory with the mkdir command. Now the script work. But now I have a different problem. The output is ;
Starting MinorFs filesystems minorcapfs going into background, consult syslog for information minorviewfs going into background, consult syslog for information.
Then when i run the command ls -la /mnt/minorfs/priv
i should get a links to the folders. But I have nothing.
dr-xr-xr-x 1 root root 0 Jan 1 1970 .
lrwxrwxrwx 1 root root 0 Jan 1 1970 home ->
lrwxrwxrwx 1 root root 0 Jan 1 1970 tmp ->
So i looked the system log file with gedit /var/log/syslog and i see that Error;
Sep 1 13:51:37 burak-UX31A minorcapfs[3581]: Problem in Fuse::main at /usr/local/bin/minorcapfs line 340
Sep 1 13:51:37 burak-UX31A minorcapfs[3581]: user: 0 1001 ; group 104 104 104 104 at /usr/local/bin/minorcapfs line 341
Sep 1 13:51:37 burak-UX31A minorcapfs[3581]: Probably a problem accesing /dev/fuse at /usr/local/bin/minorcapfs line 342
Sep 1 13:52:01 burak-UX31A minorviewfs[3584]: Use of uninitialized value in subroutine entry at /usr/lib/perl5/Fuse.pm line 147, line 26.
And this the MinorCapfs code ; http://codepad.org/nUUJ3b5m
How to get rid of this problems? Thank you.

Resources