I'm trying to implement a program to access memory on an embedded system. I need to access some control register so I think that ioctl is the best way to do it. I have added the ioctl to the fops:
struct file_operations aes_fops = {
read: aes_read,
write: aes_write,
unlocked_ioctl: aes_ioctl,
open: aes_open,
release: aes_release
};
And have set up the function:
int aes_ioctl(struct inode *inode,
struct file *file,
unsigned int ioctl_num,
unsigned long ioctl_param){
printk(KERN_INFO "in ioctl\n");
....
}
But I am not getting inside of this function. Here is my user space code. Please help me understand if I am doing this totally wrong.
int main(int argc, char* argv[]){
int fd = fopen("/dev/aes", "r+");
ioctl(fd, 0, 1);
fclose(fd);
}
Some of the code is apparently for older kernels, because I am compiling for an embedded system where an older version of Linux has been modified.
The problem with your code is the request number you are using - 0. The kernel has some request number reserved for internal use. The kernel regards the request number as a struct, separates it to fields and calls the right subsystem for it.
See Documentation/ioctl/ioctl-number.txt (from Linux 3.4.6):
Code Seq#(hex) Include File Comments
========================================================
0x00 00-1F linux/fs.h conflict!
0x00 00-1F scsi/scsi_ioctl.h conflict!
0x00 00-1F linux/fb.h conflict!
0x00 00-1F linux/wavefront.h conflict!
0x02 all linux/fd.h
0x03 all linux/hdreg.h
...
Depending on what you are during, you'd have to follow the kernel guidelines for adding new ioctls():
If you are adding new ioctl's to the kernel, you should use the _IO
macros defined in <linux/ioctl.h>:
_IO an ioctl with no parameters
_IOW an ioctl with write parameters (copy_from_user)
_IOR an ioctl with read parameters (copy_to_user)
_IOWR an ioctl with both write and read parameters.
See the kernel's own Documentation/ioctl/ioctl-decoding.txt document for further details on how those numbers are structured.
In practice, if you pick Code 1, which means starting from 0x100 up until 0x1ff, you'd be fine.
Is your setup of the aes_fops structure correct? I've never seen it done that way. All the code I have is:
.unlocked_ioctl = aes_ioctl,
rather than:
unlocked_ioctl: aes_ioctl,
Colons within a structure (as you have in your setup) fields are used for bit fields as far as I'm aware (and during definition), not initialising the individual fields.
In other words, try:
struct file_operations aes_fops = {
.read = aes_read,
.write = aes_write,
.unlocked_ioctl = aes_ioctl,
.open = aes_open,
.release = aes_release
};
Note: It appears that gcc once did allow that variant of structure field initialisation but it's been obsolete since gcc 2.5 (see here, straight from the GCC documentation). You really should be using the proper method (ie, the one blessed by the ISO standard) to do this.
Without knowing the error returned, it's hard to say... My first though is your permissions on your file descriptor. I've seen similar issues before. First, you can get some more information about the failure if you take a look at the return of the ioctl:
#include <errno.h>
int main(int argc, char* argv[])
{
long ret;
int fd = fopen("/dev/aes", "r+");
ret = ioctl(fd, 0, 1);
if (ret < 0)
printf("ioctl failed. Return code: %d, meaning: %s\n", ret, strerror(errno));
fclose(fd);
}
Check the return values and this should help give you something to search on. Why check? See the bottom of the post...
Next in order to check if it is permissions issue, run the command:
ls -l /dev/aes
if you see something like:
crw------- 1 root root 10, 57 Aug 21 10:24 /dev/aes
Then just issue a:
sudo chmod 777 /dev/aes
And give it a try again. I bet it will work for you. (Note I ran that with root permissions since root is the owner of my version of your mod)
If the permissions are already OK, then I have a few more suggestions:
1) To me, the use of fopen/fclose is strange. You really only need to do:
int fd = open("/dev/aes");
close(fd);
My system doesn't even let your code compile as is.
2) Your IOCTL parameter list is old, I don't know what kernel version your compiling on, but recent kernels use this format:
long aes_ioctl(struct file *file, unsigned int ioctl_num, unsigned long ioctl_param){
Note the removal of the inode and the change of the return type. When I ran your code on my system, I made these changes.
Best of luck!
Note: Why should we check the return when we're "not getting into the ioctl"? Let me give you an example:
//Kernel Code:
//assume include files, other fops, exit, miscdev struct, etc. are present
long hello_ioctl(struct file *file, unsigned long ioctl_num, unsigned long ioctl_param) {
long ret = 0;
printk("in ioctl");
return ret;
}
static const struct file_operations hello_fops = {
owner: THIS_MODULE,
read: hello_read,
unlocked_ioctl: hello_ioctl,
};
static int __init hello_init(void) {
int ret;
printk("hello!\n");
ret = misc_register(&hello_dev); //assume it worked...
return ret;
}
User space code:
//assume includes
void main() {
int fd;
long ret;
fd = open("/dev/hello");
if(fd) {
c = ioctl(fd, 0, 1);
if (c < 0)
printf("error: %d, errno: %d, meaning: %s\n", c, errno, strerror(errno));
close(fd);
}
return;
}
So what's the output? Lets assume bad file permissions on /dev/hello (meaning our user space program can't access /dev/hello).
The dmesg | tail shows:
[ 2388.051660] Hello!
So it looks like we didn't "get in to" the ioctl. What's the output from the program?
error: -1, errno: 9, meaning: Bad file descriptor
Lots of useful output. Clearly the ioctl call did something, just not what we wanted. Now changing the permissions and re-running we can see the new dmesg:
[ 2388.051660] Hello!
[ 2625.025339] in ioctl
Related
Recently, I've been fixing the timestep for the sake of a library that I am writing. Following some research, suppose that I ended up with this prototype, precise and easy to combine with the generic event system of my library:
#include <stdio.h>
#include <unistd.h>
#include <sys/timerfd.h>
#include <poll.h>
struct pollfd fds[1];
struct itimerspec its;
int main(void) {
fds[0] = (struct pollfd) {timerfd_create(CLOCK_MONOTONIC, 0), POLLIN, 0}; //long live clarity
its.it_interval = (struct timespec) {0, 16666667};
its.it_value = (struct timespec) {0, 16666667};
timerfd_settime(fds[0].fd, 0, &its, NULL);
while(1) {
poll(fds, 1, -1);
if(fds[0].revents == POLLIN) {
long long buffer;
read(fds[0].fd, &buffer, 8);
printf("ROFL\n");
} else {
printf("BOOM\n");
break;
}
}
close(fds[0].fd);
return 0;
}
However, it severely hurt me that I've had to pollute my CPU caches with a whole precious 8 bytes of data in order to make the timer's file descriptor reusable. Because of that, I've tried to replace the read() call with lseek(), as follows:
lseek(fds[0].fd, 0, SEEK_END);
Unfortunately, both that and even lseek(fds[0].fd, 8, SEEK_CUR); gave me ESPIPE errors and would not work. But then, I found out that the following actually did its job, despite of giving EFAULTs:
read(fds[0].fd, NULL, 8);
Is it legal, defined behavior to offset the file descriptor like this? If it is not (as the EFAULTs suggested to me, strongly enough to refrain from using that piece of genius), does there exist a function that would discard the read data, without ever writing it down, or otherwise offset my timer's file descriptor?
The POSIX specification of read(2) does not specify the consequences of passing a null pointer as the buffer argument. No specific error code is given, nor does it say whether any data will be read from the descriptor.
The Linux man page has this error, though:
EFAULT buf is outside your accessible address space.
It doesn't say that it will read the 8 bytes and discard them when this happens, though.
So I don't think you can depend on this working as you desire.
I have developed a simple line discipline using v4.0.5 of the Linux Kernel, running under Mint Linux.
The tty_ldisc_ops structure looks as follows:
static struct tty_ldisc_ops my_ldisc = {
.owner = THIS_MODULE,
.magic = TTY_LDISC_MAGIC,
.name = "my_ldisc",
.open = my_open,
.close = my_close,
.read = my_read,
.write = my_write,
.ioctl = my_ioctl,
.poll = my_poll,
.receive_buf = my_receive,
.write_wakeup = my_wakeup,
};
The module gets added via insmod my_lkm.ko. I know it's getting added correct as I've used printk to indicate it and can see the message via dmesg. Also, at startup, my userspace application uses ioctl and I have also verified that works via printk.
The problem is, in my_write, copy_from_user always returns a non-zero value indicating that it has failed somehow.
Here is my_write():
static ssize_t my_write(struct tty_struct *tty,
struct file *file,
const unsigned char *buf,
size_t nr)
{
int error = 0;
unsigned char data[MAX]; //MAX is 256
if(!my_tty) {
return -EIO;
}
if(nr > MAX) { //too big
return -ENOMEM;
}
error = copy_from_user(data,buf,nr);
printk("copy_from_user returned %d\n",error);
//here, error is always equal to nr
//(which is 12 in my example application)
if(error==0) {
printk("success\n"); //never get here
return nr;
}
return error;
}
From what I've researched, copy_from_user eventually calls pa_memcpy which does validation of the pointers being used. That validation is failing, but I can't tell why. I don't know see how *buf and data overlap or would cause a fault.
Output from uname -a: Linux mint-linux 4.0.5-040005-generic #201506061639 SMP Sat Jun 6 16:40:45 UTC 2015 UTC x86_64 x86_64 x86_64 GNU/Linux
A snippet of the userspace application is:
#define OPEN_FLAGS (O_RDWR|O_NONBLOCK)
int main(int argc, char **argv)
{
int fd=-1;
int bytes_written= 0;
char device="/dev/ttyUSB0";
unsigned char outbuffer[128]={0};
fd=open(device,OPEN_FLAGS);
//set baud rate, etc., switch to my_ldisc (using N_MOUSE)
outbuffer[0]=0x01;
outbuffer[1]=0x02;
outbuffer[2]=0x03;
outbuffer[3]=0x04;
outbuffer[4]=0x05;
outbuffer[5]=0x06;
outbuffer[6]=0x07;
outbuffer[7]=0x08;
outbuffer[8]=0x09;
outbuffer[9]=0x0A;
outbuffer[10]=0x0B;
outbuffer[11]=0x0C;
bytes_written=write(fd,outbuffer,12);
while(true) {
//...
sleep(1);
}
}
In addition, any access of buf in my_write causes instability in the VM. Even following the tty driver example in the o'reilly linux drivers book like this:
printk(KERN_DEBUG "%s - ", __FUNCTION__);
for(i=0;i<nr;i++)
{
printk("%02x ",buf[i]);
}
printk("\n");
Following Tsyvarev's advice, I printed the pointer in the user space application and the kernel module. They were different which meant I should access the incoming buffer directly. I used printf("%p\n",outbuffer); to do that in user space and the equivalent printk in kernel space.
So, slowing down and testing the module line by line helped me to fix the original problem, which it turns out was a bug in the user space application.
FWIW, the compiler never did give me a warning about the use of __user in the original code. Had it worked the way Tsyvarev suggested it would at compile time, it would have made this a lot easier to track down.
Unlike to .write method of struct file_operations, which accepts pointer to user data, .write method for struct tty_operations accepts pointer to kernel data, and these data shold be accessed via usual methods such as memcpy or even directly.
Modern kernel uses __user attribute for mark user-space data, and this attribute is checked (at compile time) when data is accessed. So having compiler warnings enabled will reveal usage of the data with incorrect origin.
I've been following a tutorial for opening files from userspace from a Linux kernel module at http://www.howtoforge.com/reading-files-from-the-linux-kernel-space-module-driver-fedora-14
The code is the following:
#include <linux/module.h> // Needed by all modules
#include <linux/kernel.h> // Needed for KERN_INFO
#include <linux/fs.h> // Needed by filp
#include <asm/uaccess.h> // Needed by segment descriptors
int init_module(void)
{
// Create variables
struct file *f;
char buf[128];
mm_segment_t fs;
int i;
// Init the buffer with 0
for(i=0;i<128;i++)
buf[i] = 0;
// To see in /var/log/messages that the module is operating
printk(KERN_INFO "My module is loaded\n");
// I am using Fedora and for the test I have chosen following file
// Obviously it is much smaller than the 128 bytes, but hell with it =)
f = filp_open("/etc/fedora-release", O_RDONLY, 0);
if(f == NULL)
printk(KERN_ALERT "filp_open error!!.\n");
else{
// Get current segment descriptor
fs = get_fs();
// Set segment descriptor associated to kernel space
set_fs(get_ds());
// Read the file
f->f_op->read(f, buf, 128, &f->f_pos);
// Restore segment descriptor
set_fs(fs);
// See what we read from file
printk(KERN_INFO "buf:%s\n",buf);
}
filp_close(f,NULL);
return 0;
}
void cleanup_module(void)
{
printk(KERN_INFO "My module is unloaded\n");
}
The code is copy-pasted from the link above. On my machine, running Fedora 19 with 3.11.10-200 kernel, it seems that filp_open isn't run, providing the buf variable with null values.
What could be wrong? I am still learning the ropes of Linux kernel module development.
First thing you should do is to check if any errors are returned from filp_open (in fact, checking for NULL is probably an outright mistake when modern kernels are concerned). The proper sequence should be:
f = filp_open("/etc/fedora-release", O_RDONLY, 0);
if (IS_ERR(f)) {
// inspect the value of PTR_ERR(f), get the necessary clues
// negative values represent various errors
// as defined in asm-generic/errno-base.h
}
Only then you can move on to diagnosing the read.
977 struct file *filp_open(const char *filename, int flags, umode_t mode)
978 {
979 struct filename *name = getname_kernel(filename);
980 struct file *file = ERR_CAST(name);
981
982 if (!IS_ERR(name)) {
983 file = file_open_name(name, flags, mode);
984 putname(name);
985 }
986 return file;
987 }
Probably the error is in how you put the parameters, the flags parameter is in mode parameter position and vice versa, mode in falgs position.
source: http://lxr.free-electrons.com/source/fs/open.c#L977
I'm working on a new project where I want to make a connection with an FTDI which is connected to my debian machine. I am intending to write the code with C, not C++. Here lies my problem. All the examples I find are incomplete or are made for a c++ compiler in stead of the GCC compiler.
The goal is to talk to my microcontroller which is connected to the FTDI. For debugging i want to start building a linux application which is able to:
initialize a serial connection on startup with ttyUSB1
send a character string
display character strings when they are received by the pc
save the communication to a .txt file
Is there any example code or tutorial to make this?
If I succeed I will defenetly place the code here so that new viewers can use it to!
Edit:
Like I said I would post the code if I had it, and this is what worked for me:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#define MODEM "/dev/ttyUSB0"
#define BAUDRATE B115200
int main(int argc,char** argv)
{
struct termios tio;
struct termios stdio;
struct termios old_stdio;
int tty_fd, flags;
unsigned char c='D';
tcgetattr(STDOUT_FILENO,&old_stdio);
printf("Please start with %s /dev/ttyS1 (for example)\n",argv[0]);
memset(&stdio,0,sizeof(stdio));
stdio.c_iflag=0;
stdio.c_oflag=0;
stdio.c_cflag=0;
stdio.c_lflag=0;
stdio.c_cc[VMIN]=1;
stdio.c_cc[VTIME]=0;
tcsetattr(STDOUT_FILENO,TCSANOW,&stdio);
tcsetattr(STDOUT_FILENO,TCSAFLUSH,&stdio);
fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK); // make the reads non-blocking
memset(&tio,0,sizeof(tio));
tio.c_iflag=0;
tio.c_oflag=0;
tio.c_cflag=CS8|CREAD|CLOCAL; // 8n1, see termios.h for more information
tio.c_lflag=0;
tio.c_cc[VMIN]=1;
tio.c_cc[VTIME]=5;
if((tty_fd = open(MODEM , O_RDWR | O_NONBLOCK)) == -1){
printf("Error while opening\n"); // Just if you want user interface error control
return -1;
}
cfsetospeed(&tio,BAUDRATE);
cfsetispeed(&tio,BAUDRATE); // baudrate is declarated above
tcsetattr(tty_fd,TCSANOW,&tio);
while (c!='q'){
if (read(tty_fd,&c,1)>0){
write(STDOUT_FILENO,&c,1); // if new data is available on the serial port, print it out
printf("\n");
}
if (read(STDIN_FILENO,&c,1)>0){
write(tty_fd,&c,1);//if new data is available on the console, send it to serial port
printf("\n");
}
}
close(tty_fd);
tcsetattr(STDOUT_FILENO,TCSANOW,&old_stdio);
return EXIT_SUCCESS;
}
Most of the code came from http://en.wikibooks.org/wiki/Serial_Programming/Serial_Linux but i also used a bit from the code posted below.
Handling with serial ports ( for linux OS ) :
- To open communication, you will need a descriptor which will be the handle for your serial port.
- Set the flags to control how the comunication will be.
- Write the command to this Handle ( make sure you're formatting the input correctly ).
- Get the answer. (make sure you're to read the amount of information you want )
- Close the handle.
It will seem like this:
int fd; // file descriptor
int flags; // communication flags
int rsl_len; // result size
char message[128]; // message to send, you can even dinamically alocate.
char result[128]; // result to read, same from above, thanks to #Lu
flags = O_RDWR | O_NOCTTY; // Read and write, and make the job control for portability
if ((fd = open("/dev/ttyUSB1", flags)) == -1 ) {
printf("Error while opening\n"); // Just if you want user interface error control
return -1;
}
// In this point your communication is already estabilished, lets send out something
strcpy(message, "Hello");
if (rsl_len = write(fd, message, strlen(message)) < 0 ) {
printf("Error while sending message\n"); // Again just in case
return -2;
}
if (rsl_len = read(fd, &result, sizeof(result)) < 0 ) {
printf("Error while reading return\n");
return -3;
}
close(fd);
Note that you have to care about what to write and what to read.
Some more flags can be used in case of parity control, stop bits, baud rate and more.
Since gcc is a C/C++ compiler, you don't need to limit yourself to pure C.
Sticking to pure C is OK if you enjoy writing lots of boilerplate code, and if you really know what you're doing. Many people use Unix APIs incorrectly, and a lot of example code out there is much too simplistic. Writing correct Unix C code is somewhat annoying, to say the least.
Personally, I'd suggest using not only C++, but also a higher-level application development framework like Qt. Qt 5 comes bundled with a QtSerialPort module that makes it easy to enumerate the serial ports, configure them, and get data into and out of them. Qt does not force you to use the gui modules, it can be a command line application, or a non-interactive server/daemon.
QtSerialPort is also usable from Qt 4, but it doesn't come bundled with Qt 4, you have to add it to your project. I suggest starting out with Qt 5, it's nicer to use with its C++11 support.
The code using Qt can be pretty simple, not much longer than your plain-English description. The below is a Qt console application using Qt 5 and C++11. It uses the core and serialport modules. It also handles the SIGINT signal so that the output file gets flushed before the process would terminate due to a ^C. I'm using QLocalSocket in place of raw Unix API to communicate from the Unix signal handler, the functionality is the same.
Only the code within main is strictly required, the rest is just to make it properly wrap things up when you hit ^C.
#include <QCoreApplication>
#include <QSerialPort>
#include <QFile>
#include <QTextStream>
#include <QLocalServer>
#include <QLocalSocket>
#include <cstdio>
#include <csignal>
QLocalSocket * xmit;
static void signalHandler(int)
{
xmit->write(" ");
xmit->flush();
}
static bool setupSignalHandler()
{
QLocalServer srv;
srv.listen("foobarbaz");
xmit = new QLocalSocket(qApp);
xmit->connectToServer(srv.serverName(), QIODevice::WriteOnly);
srv.waitForNewConnection();
QLocalSocket * receive = srv.nextPendingConnection();
receive->setParent(qApp);
qApp->connect(receive, &QLocalSocket::readyRead, &QCoreApplication::quit);
struct sigaction sig;
sig.sa_handler = signalHandler;
sigemptyset(&sig.sa_mask);
sig.sa_flags = SA_RESTART;
return ! sigaction(SIGINT, &sig, NULL);
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
setupSignalHandler();
QSerialPort port("ttyUSB1");
QFile file("file.txt");
QTextStream err(stderr, QIODevice::WriteOnly);
QTextStream out(stdout, QIODevice::WriteOnly);
if (!file.open(QIODevice::WriteOnly)) {
err << "Couldn't open the output file" << endl;
return 1;
}
if (!port.open(QIODevice::ReadWrite)) {
err << "Couldn't open the port" << endl;
return 2;
}
port.setBaudRate(9600);
QObject::connect(&port, &QSerialPort::readyRead, [&](){
QByteArray data = port.readAll();
out << data;
file.write(data);
});
out << "Use ^C to quit" << endl;
return a.exec();
}
For example I opened up 2 devices in an array of devices..
NODES are /dev/ttyUSB0, /dev/ttyUSB1 etc..
#define MAXDEV 4
devlist[MAXDEV];
const char *devices[] = {"/dev/ttyUSB0","/dev/ttyUSB1");
for(loop =0; loop<sizeof(devices); loop++){
fd= open(devices[loop]);
}
Now I add them to the list of fds;
for(i=0; i<MAXDEV; i++){
if(devlist[i] != 0){
devlist[i] = fd;
fd = -1;
}
}
Now I read on the devices for data.
for(iter=0; iter<MAXDEV; iter++){
if(FD_ISSET(devlist[iter],&fds)){
if ((nbytes = read(devlist[iter], buf, sizeof(buf)-1)) > 0 && nbytes != 0)
{
buf[nbytes] = '\0';
printf("Data Received on Node ???");
}
if(nbytes < 0){
printf("connection reset\n");
FD_CLR(devlist[iter], &fds);
close(devlist[iter]);
devlist[iter] = 0;
}
if(nbytes ==0){
printf("Device Removed on Node ???\n");
FD_CLR(devlist[iter], &fds);
close(devlist[iter]);
devlist[iter] = 0;
}
}
}
Now how do I get the device node using its fd?.. Thanks.
The proper way to do this is to do your own book-keeping. That would allow you to log the device node name exactly as supplied by the user, rather than provide an equivalent, yet confusingly different one.
For example you could use a hash table, to associate file descriptor numbers to char arrays with the device name used for the corresponding open() call.
A simpler, but far more fragile and definitely not recommended, solution might involve using a simple array of pointers to char with an inordinately large size, in the hopes that any file descriptor value that you may encounter can be used as an index to the appropriate string without going beyond the array bounds. This is slightly easier to code than a hash table, but it will cause your program to die horribly if a file descriptor value exceeds the maximum allowed index in your string array.
If your program is bound to the Linux platform anyway, you might be able to, uh, cheat by using the /dev/fd directory or the /proc filesystem (more specifically the /proc/self/fd directory to which /dev/fd is usually a symbolic link). Both contain symbolic links that associate file descriptor values to canonical versions of the paths that where used to open the corresponding files. For example consider the following transcript:
$ ls -l /proc/self/fd
total 0
lrwx------ 1 user user 64 Nov 9 23:21 0 -> /dev/pts/10
l-wx------ 1 user user 64 Nov 9 23:21 1 -> /dev/pts/10
lrwx------ 1 user user 64 Nov 9 23:21 2 -> /dev/pts/10
lr-x------ 1 user user 64 Nov 9 23:21 3 -> /proc/16437/fd/
You can use the readlink() system call to retrieve the target of the link that corresponds to a file descriptor of interest.
You need the fstat(2) syscall, perhaps also fstatfs(2). Check that it succeeded.
struct stat st;
memset (&st, 0, sizeof(st));
if (fstat (fd, &st))
perror("fstat");
else {
// use st, notably st.st_rdev
}
Remember that you could have a device outside of /dev. If you are sure that your device is in it, you could stat(2) every entry in it, and compare their st_rdev
Read also Advanced Linux Programming (it is online under a free license, but you may want to buy the book).
Well I can see this question is about 1 year old. But right now I was looking for a way of doing this. And I found it. For getting the device node using the file descritor you can combine stat and libudev here is an example:
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <libudev.h>
#include <iostream>
#include <fcntl.h>
int main(int argc, char *argv[])
{
struct stat sb;
// Get a file descriptor to the file.
int fd = open(argv[1], O_RDWR);
// Get stats for that file descriptor.
if (fstat(fd, &sb) == -1) {
perror("stat");
exit(EXIT_FAILURE);
}
// Create the udev context.
struct udev *udev;
udev = udev_new();
// Create de udev_device from the dev_t obtained from stat.
struct udev_device *dev;
dev = udev_device_new_from_devnum(udev, 'b', sb.st_dev);
// Finally obtain the node.
const char* node = udev_device_get_devnode(dev);
udev_unref(udev);
std::cout << "The file is in: " << node << std::endl;
return 0;
}