zoukankan      html  css  js  c++  java
  • udev example -- detect usb and write test file

    摘自:https://www.cnblogs.com/jlmgary/p/6742630.html

    之前学习了下Udev,就随便做了个测试小程序.....设计什么的也没考虑,就实现了一个基本功能,插入U盘,识别,循环检测到有特定文件后,就然后往U盘里面写数据,插拔多次,都能正常工作。

    里面的warning和不规范的写法请自己修改。

      1 #include <unistd.h>  
      2 #include <stdio.h>  
      3 #include <stdlib.h>  
      4 #include <stddef.h>  
      5 #include <string.h>  
      6 #include <errno.h>  
      7 #include <getopt.h>  
      8 #include <fcntl.h>  
      9 #include <errno.h>  
     10 #include <signal.h>  
     11 #include <getopt.h>  
     12 #include <sys/time.h>  
     13 #include <sys/socket.h>  
     14 #include <sys/un.h>  
     15 #include <sys/select.h>  
     16 #include <linux/types.h>  
     17 #include <linux/netlink.h>  
     18 #include <sys/types.h>
     19 #include <libudev.h>
     20 #include <iostream>
     21 #include <pthread.h>
     22 #include <sys/mount.h>
     23 #include <sys/stat.h>
     24 #include <dirent.h>
     25 #include <time.h>
     26 using namespace std;
     27 static std::string record_path="";
     28 
     29 static bool FindRecord=false;
     30 void File_Opreation();
     31 void GetUsbFolderLocation(char *basePath);
     32 void MountTheSystem(char *basePath);
     33 static bool NeedToCheck=false;
     34 int ListDevice()
     35 {
     36     udev *udev;
     37     struct udev_enumerate *enumerate;
     38     struct udev_list_entry *devices, *dev_list_entry;
     39     struct udev_device *dev;
     40     
     41     /* Create the udev object */
     42     udev = udev_new();
     43     if (!udev) 
     44     {
     45         printf("Can't create udev
    ");
     46         exit(1);
     47     }
     48     
     49     /* Create a list of the devices in the 'hidraw' subsystem. */
     50     enumerate = udev_enumerate_new(udev);
     51     udev_enumerate_add_match_subsystem(enumerate, "block");
     52     udev_enumerate_scan_devices(enumerate);
     53     devices = udev_enumerate_get_list_entry(enumerate);
     54     /* For each item enumerated, print out its information.
     55        udev_list_entry_foreach is a macro which expands to
     56        a loop. The loop will be executed for each member in
     57        devices, setting dev_list_entry to a list entry
     58        which contains the device's path in /sys. */
     59     udev_list_entry_foreach(dev_list_entry, devices) 
     60     {
     61         const char *path;
     62         
     63         /* Get the filename of the /sys entry for the device
     64            and create a udev_device object (dev) representing it */
     65         path = udev_list_entry_get_name(dev_list_entry);
     66         dev = udev_device_new_from_syspath(udev, path);
     67 
     68         /* usb_device_get_devnode() returns the path to the device node
     69            itself in /dev. */
     70         printf("Device Node Path: %s
    ", udev_device_get_devnode(dev));
     71 
     72         /* The device pointed to by dev contains information about
     73            the hidraw device. In order to get information about the
     74            USB device, get the parent device with the
     75            subsystem/devtype pair of "usb"/"usb_device". This will
     76            be several levels up the tree, but the function will find
     77            it.*/
     78         dev = udev_device_get_parent_with_subsystem_devtype(
     79                dev,
     80                "usb",
     81                "usb_device");
     82         if (!dev) 
     83         {
     84             cout<<"Unable to find parent usb device"<<endl;
     85             exit(1);
     86         }
     87     
     88         /* From here, we can call get_sysattr_value() for each file
     89            in the device's /sys entry. The strings passed into these
     90            functions (idProduct, idVendor, serial, etc.) correspond
     91            directly to the files in the directory which represents
     92            the USB device. Note that USB strings are Unicode, UCS2
     93            encoded, but the strings returned from
     94            udev_device_get_sysattr_value() are UTF-8 encoded. */
     95         printf("  VID/PID: %s %s
    ",
     96                 udev_device_get_sysattr_value(dev,"idVendor"),
     97                 udev_device_get_sysattr_value(dev, "idProduct"));
     98         printf("  %s
      %s
    ",
     99                 udev_device_get_sysattr_value(dev,"manufacturer"),
    100                 udev_device_get_sysattr_value(dev,"product"));
    101         printf("  serial: %s
    ",
    102                  udev_device_get_sysattr_value(dev, "serial"));
    103         udev_device_unref(dev);
    104     }
    105     /* Free the enumerator object */
    106     udev_enumerate_unref(enumerate);
    107 
    108     udev_unref(udev);
    109 
    110     return 0;       
    111 }
    112 
    113 void Udev_Enumrate()
    114 {
    115     struct udev* udev_ancestor=NULL;
    116     struct udev_enumerate* udev_enum=NULL;
    117     struct udev_list_entry* device_fistentry=NULL;
    118     struct udev_list_entry *dev_list_entry=NULL; //entry to store the current position
    119     struct udev_device *dev=NULL;
    120     udev_ancestor=udev_new();
    121     udev_enum=udev_enumerate_new(udev_ancestor);
    122     if(udev_enumerate_add_match_subsystem (udev_enum, "block")==0)
    123     {
    124         cout<<"add block device to match subsystem successful"<<endl;
    125     }
    126     
    127     if(udev_enumerate_add_match_subsystem (udev_enum, "usb")==0)
    128     {
    129         cout<<"add usb device to match subsystem successful"<<endl;
    130     }
    131 
    132     if(udev_enumerate_add_match_subsystem (udev_enum, "scsi")==0)
    133     {
    134         cout<<"add scsi device to match subsystem successful"<<endl;
    135     }
    136 
    137     //Scan the system under /sys/
    138     udev_enumerate_scan_devices(udev_enum);
    139     
    140     //get the first entry of the device list
    141     device_fistentry=udev_enumerate_get_list_entry(udev_enum);
    142     
    143     /* For each item enumerated, print out its information.
    144        udev_list_entry_foreach is a macro which expands to
    145        a loop. The loop will be executed for each member in
    146        devices, setting dev_list_entry to a list entry
    147        which contains the device's path in /sys. */
    148     udev_list_entry_foreach(dev_list_entry, device_fistentry)
    149     {
    150         const char *path;
    151         
    152         /* Get the filename of the /sys entry for the device
    153            and create a udev_device object (dev) representing it */
    154         path = udev_list_entry_get_name(dev_list_entry);
    155         dev = udev_device_new_from_syspath(udev_ancestor, path);
    156 
    157         /* usb_device_get_devnode() returns the path to the device node
    158            itself in /dev. */
    159         printf("Test Device Node Path: %s
    ", udev_device_get_devnode(dev));    
    160         
    161 
    162         /* The device pointed to by dev contains information about
    163         the hidraw device. In order to get information about the
    164         USB device, get the parent device with the
    165         subsystem/devtype pair of "usb"/"usb_device". This will
    166         be several levels up the tree, but the function will find
    167         it.*/
    168         dev = udev_device_get_parent_with_subsystem_devtype(
    169                                 dev,
    170                                 "usb",
    171                                 "usb_device");
    172         if (!dev) 
    173         {
    174             cout<<"Test Unable to find parent usb device"<<endl;
    175             //exit(1);
    176         }
    177         else
    178         {        
    179             printf("  VID/PID: %s %s
    ",udev_device_get_sysattr_value(dev,"idVendor"), udev_device_get_sysattr_value(dev, "idProduct"));
    180             printf("  %s
      %s
    ",udev_device_get_sysattr_value(dev,"manufacturer"), udev_device_get_sysattr_value(dev,"product"));
    181             printf("  serial: %s
    ",udev_device_get_sysattr_value(dev, "serial"));
    182         }
    183 
    184         udev_device_unref(dev);
    185     }
    186     udev_enumerate_unref(udev_enum);
    187     udev_unref(udev_ancestor);
    188 
    189 }
    190 
    191 void* udev_Monitor(void*)
    192 {
    193     struct udev* udev=NULL;
    194     struct udev_monitor * mon=NULL;
    195     struct udev_device *dev;
    196     int fd;
    197     fd_set fds;
    198     struct timeval tv;
    199     static int flag=0;
    200     
    201     udev=udev_new();
    202     mon=udev_monitor_new_from_netlink(udev,"udev");
    203     
    204     udev_monitor_filter_add_match_subsystem_devtype(mon, "sound", "usb_device");
    205     udev_monitor_filter_add_match_subsystem_devtype(mon, "usb", "usb_device");
    206     udev_monitor_filter_add_match_subsystem_devtype(mon, "block", "disk");
    207     udev_monitor_filter_add_match_subsystem_devtype(mon, "block", "partition");
    208     udev_monitor_filter_add_match_subsystem_devtype(mon, "usb", "usb_interface");
    209     udev_monitor_enable_receiving(mon);
    210     fd = udev_monitor_get_fd(mon);
    211     while(1)
    212     {
    213                 
    214         fd_set fds;
    215         struct timeval tv;
    216         int ret;
    217         
    218         FD_ZERO(&fds);
    219         FD_SET(fd, &fds);
    220         tv.tv_sec = 0;
    221         tv.tv_usec = 0;
    222         
    223         ret = select(fd+1, &fds, NULL, NULL, &tv);
    224         //ret means there's an event fd_isset means fd is readable
    225         if(ret>0 & FD_ISSET(fd,&fds))
    226         {
    227             //cout<<"There's a change with Num="<<flag<<endl;
    228             //flag++;
    229             /* Make the call to receive the device.
    230                select() ensured that this will not block. */
    231             dev = udev_monitor_receive_device(mon);
    232             if (dev) 
    233             {                    
    234                 const char* sysPath        = udev_device_get_syspath(dev);
    235                 const char* action        = udev_device_get_action(dev);
    236                 const char* subsystem        = udev_device_get_subsystem(dev);
    237                 const char* devType        = udev_device_get_devtype(dev);
    238                 if (0 == strncmp(action, "add", strlen("add")))
    239                 {
    240                 
    241                     const char* devClass         = udev_device_get_sysattr_value(dev, "bDeviceClass");                            
    242                     const char* devInterfaceClass     = udev_device_get_sysattr_value(dev, "bInterfaceClass");
    243                     
    244                     cout<<"The  devClass: "<<devClass<<endl;
    245                     cout<<"The   devInterfaceClass:"<<devInterfaceClass<<endl;
    246 
    247                     NeedToCheck=true;
    248 
    249                 }
    250                 printf("Got Device
    ");
    251                 printf("   Node: %s
    ", udev_device_get_devnode(dev));
    252                 printf("   Subsystem: %s
    ", udev_device_get_subsystem(dev));
    253                 printf("   Devtype: %s
    ", udev_device_get_devtype(dev));
    254                 printf("   Action: %s
    ",udev_device_get_action(dev));
    255                 printf("   Path: %s
    ",udev_device_get_syspath(dev));
    256                 
    257                 udev_device_unref(dev);
    258             }
    259             else 
    260             {
    261                 printf("No Device from receive_device(). An error occured.
    ");
    262             }        
    263         }
    264     }
    265 }
    266 
    267 
    268 
    269 int LoopileList(char *basePath)
    270 {
    271     DIR *dir;
    272     struct dirent *ptr;
    273     char base[1000];
    274 
    275     if ((dir=opendir(basePath)) == NULL)
    276     {
    277         perror("Open dir error...");
    278         exit(1);
    279     }
    280 
    281     while ((ptr=readdir(dir)) != NULL)
    282     {
    283         if(strcmp(ptr->d_name,".")==0 || strcmp(ptr->d_name,"..")==0)    ///current dir OR parrent dir
    284         {            
    285             continue;
    286         }
    287         else if(ptr->d_type == 8)    ///file
    288         {
    289             printf("d_name:%s/%s
    ",basePath,ptr->d_name);
    290         }
    291         else if(ptr->d_type == 10)    ///link file
    292         {
    293             printf("d_name:%s/%s
    ",basePath,ptr->d_name);
    294     }
    295         else if(ptr->d_type == 4)    ///dir
    296         {
    297             memset(base,'',sizeof(base));
    298             strcpy(base,basePath);
    299             strcat(base,"/");
    300             strcat(base,ptr->d_name);
    301             LoopileList(base);
    302         }
    303     }
    304     closedir(dir);
    305     return 1;
    306 }
    307 
    308 static bool stopLoopflag=false;
    309 void GetUsbFolderLocation(char *basePath)
    310 {    
    311     bool ret=false;
    312     DIR *dir;
    313     struct dirent *ptr;
    314     char base[1000];
    315     MountTheSystem(basePath);
    316     //cout<<"Loop check  file "<<basePath<<endl;
    317     if ((dir=opendir(basePath)) == NULL)
    318     {
    319         //perror("Open dir error...");
    320         //exit(1);
    321     }
    322     else
    323     {
    324         while ((ptr=readdir(dir)) != NULL && !stopLoopflag)
    325             {
    326                 
    327             if(strcmp(ptr->d_name,".")==0 || strcmp(ptr->d_name,"..")==0)    ///current dir OR parrent dir
    328             {            
    329                 continue;
    330             }
    331             else if(ptr->d_type == 8)    ///file
    332             {            
    333                 if(strcmp(ptr->d_name,"Record_HFC")==0)
    334                 {
    335                     record_path=basePath;                    
    336                     printf("File :%s/%s
    ",basePath,ptr->d_name);
    337                     strcat(basePath,"/");
    338                     record_path=basePath;
    339                     cout<<"Record Path is="<<record_path<<endl;
    340                     FindRecord=true;
    341                     stopLoopflag=true;
    342                     break;
    343                 }
    344             
    345             }
    346             else if(ptr->d_type == 10)    ///link file
    347             {
    348                 printf("Link:%s/%s
    ",basePath,ptr->d_name);
    349             }
    350             else if(ptr->d_type == 4)    ///dir
    351             {
    352                 memset(base,'',sizeof(base));
    353                 strcpy(base,basePath);
    354                 strcat(base,"/");
    355                 strcat(base,ptr->d_name);
    356                 GetUsbFolderLocation(base);
    357             }
    358             }
    359            if(dir!=NULL)
    360            {
    361                closedir(dir);
    362            }
    363     }
    364     
    365 }
    366 
    367 string GetLocalTime()
    368 {
    369     //string str="/usr/bin/sgm/Conn/tmp/out_";
    370     string str="";
    371     time_t rawtime;
    372     struct tm* timeinfo;
    373     char timE[25];
    374     time(&rawtime);
    375     timeinfo=localtime(&rawtime);
    376     strftime(timE,sizeof(timE),"%Y_%m_%d_%I_%M_%S",timeinfo);
    377     printf("%s",timE);
    378 
    379     str=str+timE;
    380     return str;
    381 }
    382 void MountTheSystem(char *basePath)
    383 {
    384     //cout<<"mount"<<record_path<<endl;
    385     //mount(NULL, record_path.c_str(), NULL, MS_REMOUNT, "-o, rw");
    386     //cout<<"mount"<<record_path<<endl;
    387     mount(NULL, basePath, NULL, MS_REMOUNT, "-o, rw");
    388 }
    389 void WriteFileToUSB()
    390 {
    391     record_path=record_path+"test.txt";
    392     FILE* fusb_Ubuntu=NULL;
    393     fusb_Ubuntu=fopen(record_path.c_str(),"w+");
    394     cout<<"path is="<<record_path<<endl;
    395     if(fusb_Ubuntu==NULL)
    396     {
    397         cout<<"cant't write"<<endl;
    398     }
    399     else
    400     {    
    401         cout<<"start write"<<endl;
    402         std::string str_Ubuntu="This is test";
    403         str_Ubuntu=str_Ubuntu+GetLocalTime();
    404         char* arr_Ubuntu=new char[str_Ubuntu.length()+1];
    405         for(int i=0;i<str_Ubuntu.length();i++)
    406         {
    407             arr_Ubuntu[i]=str_Ubuntu[i];
    408             
    409         }
    410         cout<<str_Ubuntu<<endl;
    411         fwrite(arr_Ubuntu,str_Ubuntu.length(),sizeof(char),fusb_Ubuntu);
    412         fclose(fusb_Ubuntu);
    413         record_path="";
    414         NeedToCheck=false;
    415         stopLoopflag=false;
    416         delete []arr_Ubuntu;
    417         arr_Ubuntu=NULL;
    418     }
    419     
    420         
    421         
    422     
    423 }
    424 void File_Opreation()
    425 {
    426     cout<<"start to do file operation"<<endl;
    427 }
    428 
    429 void* writeFile(void*)
    430 {
    431     while(1)
    432     {
    433         if(NeedToCheck)
    434         {    
    435             char* path="/media";
    436             GetUsbFolderLocation(path);
    437     
    438             if(FindRecord)
    439             {
    440                 WriteFileToUSB();
    441             }
    442         }
    443         else
    444         {
    445             cout<<"sleep for 5s"<<endl;
    446             usleep(5000*1000);
    447         }
    448     }
    449     
    450 }
    451 //int main(int argc, char *argv[])  
    452 int main()  
    453 {      
    454     #if 0                
    455     char* path="/media";
    456     GetUsbFolderLocation(path);
    457     
    458     if(FindRecord)
    459     {
    460         File_Opreation();
    461     }
    462     #endif
    463     pthread_t monitor_thread=0;
    464     pthread_t write_thread=0;
    465 
    466     int err=0;
    467     err=pthread_create(&monitor_thread, NULL,udev_Monitor, NULL);
    468     if(err!=0)
    469     {
    470         cout<<"create thread error"<<endl;
    471     }    
    472     else
    473     {
    474         cout<<"create thread monitor success "<<endl;
    475     }
    476     
    477     
    478 
    479     
    480     err=pthread_create(&write_thread, NULL,writeFile, NULL);
    481     if(err!=0)
    482     {
    483         cout<<"create thread error"<<endl;
    484     }
    485     else
    486     {
    487         cout<<"create thread writeFile success "<<endl;
    488     }
    489     
    490     
    491     if(monitor_thread!=0)
    492     {
    493         pthread_join(monitor_thread,NULL);
    494     }
    495     if(write_thread!=0)
    496     {
    497         pthread_join(write_thread,NULL);
    498     }    
    499 
    500     
    501     return 0;  
    502 }

    Linux 下运行,如果要在ARM下运行就编一个arm版本的。

    Makefile

    # specify the compiler
    CC=/usr/bin/g++
    
    # specify library
    
    INCFLAGS=-I ./ 
    
    
    # specify library
    LIBFLAGS=-l pthread -l udev
    
    # specify additional compile flags
    FLAGS= -lm -g -Wall -Wextra 
    
    # List of files specific 
    SRC:= Udev_Monitor.cpp              
     
    testapp:
        ${CC} -o Udev_Monitor ${SRC} ${LIBFLAGS} ${INCFLAGS}  ${FLAGS}
    
    clean:
        rm -f Udev_Monitor

    只是基本的识别插拔U盘,检测特定的文件,检测到后往U盘里面写数据,可以用来帮助cp或者记录log文件。

    虽然我的blog也没人会看,但是还是希望能帮到和我一样的菜鸟。

  • 相关阅读:
    day4
    day3
    day2
    day1
    spring-boot-note
    spring-boot-cli
    jquery ajax rest invoke
    spring-boot
    docker mysql
    jpa OneToMany
  • 原文地址:https://www.cnblogs.com/LiuYanYGZ/p/12419870.html
Copyright © 2011-2022 走看看