• udev example -- detect usb and write test file


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

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

     
    #include <unistd.h>  
    #include <stdio.h>  
    #include <stdlib.h>  
    #include <stddef.h>  
    #include <string.h>  
    #include <errno.h>  
    #include <getopt.h>  
    #include <fcntl.h>  
    #include <errno.h>  
    #include <signal.h>  
    #include <getopt.h>  
    #include <sys/time.h>  
    #include <sys/socket.h>  
    #include <sys/un.h>  
    #include <sys/select.h>  
    #include <linux/types.h>  
    #include <linux/netlink.h>  
    #include <sys/types.h>
    #include <libudev.h>
    #include <iostream>
    #include <pthread.h>
    #include <sys/mount.h>
    #include <sys/stat.h>
    #include <dirent.h>
    #include <time.h>
    using namespace std;
    static std::string record_path="";
    
    static bool FindRecord=false;
    void File_Opreation();
    void GetUsbFolderLocation(char *basePath);
    void MountTheSystem(char *basePath);
    static bool NeedToCheck=false;
    int ListDevice()
    {
        udev *udev;
        struct udev_enumerate *enumerate;
        struct udev_list_entry *devices, *dev_list_entry;
        struct udev_device *dev;
        
        /* Create the udev object */
        udev = udev_new();
        if (!udev) 
        {
            printf("Can't create udev
    ");
            exit(1);
        }
        
        /* Create a list of the devices in the 'hidraw' subsystem. */
        enumerate = udev_enumerate_new(udev);
        udev_enumerate_add_match_subsystem(enumerate, "block");
        udev_enumerate_scan_devices(enumerate);
        devices = udev_enumerate_get_list_entry(enumerate);
        /* For each item enumerated, print out its information.
           udev_list_entry_foreach is a macro which expands to
           a loop. The loop will be executed for each member in
           devices, setting dev_list_entry to a list entry
           which contains the device's path in /sys. */
        udev_list_entry_foreach(dev_list_entry, devices) 
        {
            const char *path;
            
            /* Get the filename of the /sys entry for the device
               and create a udev_device object (dev) representing it */
            path = udev_list_entry_get_name(dev_list_entry);
            dev = udev_device_new_from_syspath(udev, path);
    
            /* usb_device_get_devnode() returns the path to the device node
               itself in /dev. */
            printf("Device Node Path: %s
    ", udev_device_get_devnode(dev));
    
            /* The device pointed to by dev contains information about
               the hidraw device. In order to get information about the
               USB device, get the parent device with the
               subsystem/devtype pair of "usb"/"usb_device". This will
               be several levels up the tree, but the function will find
               it.*/
            dev = udev_device_get_parent_with_subsystem_devtype(
                   dev,
                   "usb",
                   "usb_device");
            if (!dev) 
            {
                cout<<"Unable to find parent usb device"<<endl;
                exit(1);
            }
        
            /* From here, we can call get_sysattr_value() for each file
               in the device's /sys entry. The strings passed into these
               functions (idProduct, idVendor, serial, etc.) correspond
               directly to the files in the directory which represents
               the USB device. Note that USB strings are Unicode, UCS2
               encoded, but the strings returned from
               udev_device_get_sysattr_value() are UTF-8 encoded. */
            printf("  VID/PID: %s %s
    ",
                    udev_device_get_sysattr_value(dev,"idVendor"),
                    udev_device_get_sysattr_value(dev, "idProduct"));
            printf("  %s
      %s
    ",
                    udev_device_get_sysattr_value(dev,"manufacturer"),
                    udev_device_get_sysattr_value(dev,"product"));
            printf("  serial: %s
    ",
                     udev_device_get_sysattr_value(dev, "serial"));
            udev_device_unref(dev);
        }
        /* Free the enumerator object */
        udev_enumerate_unref(enumerate);
    
        udev_unref(udev);
    
        return 0;       
    }
    
    void Udev_Enumrate()
    {
        struct udev* udev_ancestor=NULL;
        struct udev_enumerate* udev_enum=NULL;
        struct udev_list_entry* device_fistentry=NULL;
        struct udev_list_entry *dev_list_entry=NULL; //entry to store the current position
        struct udev_device *dev=NULL;
        udev_ancestor=udev_new();
        udev_enum=udev_enumerate_new(udev_ancestor);
        if(udev_enumerate_add_match_subsystem (udev_enum, "block")==0)
        {
            cout<<"add block device to match subsystem successful"<<endl;
        }
        
        if(udev_enumerate_add_match_subsystem (udev_enum, "usb")==0)
        {
            cout<<"add usb device to match subsystem successful"<<endl;
        }
    
        if(udev_enumerate_add_match_subsystem (udev_enum, "scsi")==0)
        {
            cout<<"add scsi device to match subsystem successful"<<endl;
        }
    
        //Scan the system under /sys/
        udev_enumerate_scan_devices(udev_enum);
        
        //get the first entry of the device list
        device_fistentry=udev_enumerate_get_list_entry(udev_enum);
        
        /* For each item enumerated, print out its information.
           udev_list_entry_foreach is a macro which expands to
           a loop. The loop will be executed for each member in
           devices, setting dev_list_entry to a list entry
           which contains the device's path in /sys. */
        udev_list_entry_foreach(dev_list_entry, device_fistentry)
        {
            const char *path;
            
            /* Get the filename of the /sys entry for the device
               and create a udev_device object (dev) representing it */
            path = udev_list_entry_get_name(dev_list_entry);
            dev = udev_device_new_from_syspath(udev_ancestor, path);
    
            /* usb_device_get_devnode() returns the path to the device node
               itself in /dev. */
            printf("Test Device Node Path: %s
    ", udev_device_get_devnode(dev));    
            
    
            /* The device pointed to by dev contains information about
            the hidraw device. In order to get information about the
            USB device, get the parent device with the
            subsystem/devtype pair of "usb"/"usb_device". This will
            be several levels up the tree, but the function will find
            it.*/
            dev = udev_device_get_parent_with_subsystem_devtype(
                                    dev,
                                    "usb",
                                    "usb_device");
            if (!dev) 
            {
                cout<<"Test Unable to find parent usb device"<<endl;
                //exit(1);
            }
            else
            {        
                printf("  VID/PID: %s %s
    ",udev_device_get_sysattr_value(dev,"idVendor"), udev_device_get_sysattr_value(dev, "idProduct"));
                printf("  %s
      %s
    ",udev_device_get_sysattr_value(dev,"manufacturer"), udev_device_get_sysattr_value(dev,"product"));
                printf("  serial: %s
    ",udev_device_get_sysattr_value(dev, "serial"));
            }
    
            udev_device_unref(dev);
        }
        udev_enumerate_unref(udev_enum);
        udev_unref(udev_ancestor);
    
    }
    
    void* udev_Monitor(void*)
    {
        struct udev* udev=NULL;
        struct udev_monitor * mon=NULL;
        struct udev_device *dev;
        int fd;
        fd_set fds;
        struct timeval tv;
        static int flag=0;
        
        udev=udev_new();
        mon=udev_monitor_new_from_netlink(udev,"udev");
        
        udev_monitor_filter_add_match_subsystem_devtype(mon, "sound", "usb_device");
        udev_monitor_filter_add_match_subsystem_devtype(mon, "usb", "usb_device");
        udev_monitor_filter_add_match_subsystem_devtype(mon, "block", "disk");
        udev_monitor_filter_add_match_subsystem_devtype(mon, "block", "partition");
        udev_monitor_filter_add_match_subsystem_devtype(mon, "usb", "usb_interface");
        udev_monitor_enable_receiving(mon);
        fd = udev_monitor_get_fd(mon);
        while(1)
        {
                    
            fd_set fds;
            struct timeval tv;
            int ret;
            
            FD_ZERO(&fds);
            FD_SET(fd, &fds);
            tv.tv_sec = 0;
            tv.tv_usec = 0;
            
            ret = select(fd+1, &fds, NULL, NULL, &tv);
            //ret means there's an event fd_isset means fd is readable
            if(ret>0 & FD_ISSET(fd,&fds))
            {
                //cout<<"There's a change with Num="<<flag<<endl;
                //flag++;
                /* Make the call to receive the device.
                   select() ensured that this will not block. */
                dev = udev_monitor_receive_device(mon);
                if (dev) 
                {                    
                    const char* sysPath        = udev_device_get_syspath(dev);
                    const char* action        = udev_device_get_action(dev);
                    const char* subsystem        = udev_device_get_subsystem(dev);
                    const char* devType        = udev_device_get_devtype(dev);
                    if (0 == strncmp(action, "add", strlen("add")))
                    {
                    
                        const char* devClass         = udev_device_get_sysattr_value(dev, "bDeviceClass");                            
                        const char* devInterfaceClass     = udev_device_get_sysattr_value(dev, "bInterfaceClass");
                        
                        cout<<"The  devClass: "<<devClass<<endl;
                        cout<<"The   devInterfaceClass:"<<devInterfaceClass<<endl;
    
                        NeedToCheck=true;
    
                    }
                    printf("Got Device
    ");
                    printf("   Node: %s
    ", udev_device_get_devnode(dev));
                    printf("   Subsystem: %s
    ", udev_device_get_subsystem(dev));
                    printf("   Devtype: %s
    ", udev_device_get_devtype(dev));
                    printf("   Action: %s
    ",udev_device_get_action(dev));
                    printf("   Path: %s
    ",udev_device_get_syspath(dev));
                    
                    udev_device_unref(dev);
                }
                else 
                {
                    printf("No Device from receive_device(). An error occured.
    ");
                }        
            }
        }
    }
    
    
    
    int LoopileList(char *basePath)
    {
        DIR *dir;
        struct dirent *ptr;
        char base[1000];
    
        if ((dir=opendir(basePath)) == NULL)
        {
            perror("Open dir error...");
            exit(1);
        }
    
        while ((ptr=readdir(dir)) != NULL)
        {
            if(strcmp(ptr->d_name,".")==0 || strcmp(ptr->d_name,"..")==0)    ///current dir OR parrent dir
            {            
                continue;
            }
            else if(ptr->d_type == 8)    ///file
            {
                printf("d_name:%s/%s
    ",basePath,ptr->d_name);
            }
            else if(ptr->d_type == 10)    ///link file
            {
                printf("d_name:%s/%s
    ",basePath,ptr->d_name);
        }
            else if(ptr->d_type == 4)    ///dir
            {
                memset(base,'',sizeof(base));
                strcpy(base,basePath);
                strcat(base,"/");
                strcat(base,ptr->d_name);
                LoopileList(base);
            }
        }
        closedir(dir);
        return 1;
    }
    
    static bool stopLoopflag=false;
    void GetUsbFolderLocation(char *basePath)
    {    
        bool ret=false;
        DIR *dir;
        struct dirent *ptr;
        char base[1000];
        MountTheSystem(basePath);
        //cout<<"Loop check  file "<<basePath<<endl;
        if ((dir=opendir(basePath)) == NULL)
        {
            //perror("Open dir error...");
            //exit(1);
        }
        else
        {
            while ((ptr=readdir(dir)) != NULL && !stopLoopflag)
                {
                    
                if(strcmp(ptr->d_name,".")==0 || strcmp(ptr->d_name,"..")==0)    ///current dir OR parrent dir
                {            
                    continue;
                }
                else if(ptr->d_type == 8)    ///file
                {            
                    if(strcmp(ptr->d_name,"Record_HFC")==0)
                    {
                        record_path=basePath;                    
                        printf("File :%s/%s
    ",basePath,ptr->d_name);
                        strcat(basePath,"/");
                        record_path=basePath;
                        cout<<"Record Path is="<<record_path<<endl;
                        FindRecord=true;
                        stopLoopflag=true;
                        break;
                    }
                
                }
                else if(ptr->d_type == 10)    ///link file
                {
                    printf("Link:%s/%s
    ",basePath,ptr->d_name);
                }
                else if(ptr->d_type == 4)    ///dir
                {
                    memset(base,'',sizeof(base));
                    strcpy(base,basePath);
                    strcat(base,"/");
                    strcat(base,ptr->d_name);
                    GetUsbFolderLocation(base);
                }
                }
               if(dir!=NULL)
               {
                   closedir(dir);
               }
        }
        
    }
    
    string GetLocalTime()
    {
        //string str="/usr/bin/sgm/Conn/tmp/out_";
        string str="";
        time_t rawtime;
        struct tm* timeinfo;
        char timE[25];
        time(&rawtime);
        timeinfo=localtime(&rawtime);
        strftime(timE,sizeof(timE),"%Y_%m_%d_%I_%M_%S",timeinfo);
        printf("%s",timE);
    
        str=str+timE;
        return str;
    }
    void MountTheSystem(char *basePath)
    {
        //cout<<"mount"<<record_path<<endl;
        //mount(NULL, record_path.c_str(), NULL, MS_REMOUNT, "-o, rw");
        //cout<<"mount"<<record_path<<endl;
        mount(NULL, basePath, NULL, MS_REMOUNT, "-o, rw");
    }
    void WriteFileToUSB()
    {
        record_path=record_path+"test.txt";
        FILE* fusb_Ubuntu=NULL;
        fusb_Ubuntu=fopen(record_path.c_str(),"w+");
        cout<<"path is="<<record_path<<endl;
        if(fusb_Ubuntu==NULL)
        {
            cout<<"cant't write"<<endl;
        }
        else
        {    
            cout<<"start write"<<endl;
            std::string str_Ubuntu="This is test";
            str_Ubuntu=str_Ubuntu+GetLocalTime();
            char* arr_Ubuntu=new char[str_Ubuntu.length()+1];
            for(int i=0;i<str_Ubuntu.length();i++)
            {
                arr_Ubuntu[i]=str_Ubuntu[i];
                
            }
            cout<<str_Ubuntu<<endl;
            fwrite(arr_Ubuntu,str_Ubuntu.length(),sizeof(char),fusb_Ubuntu);
            fclose(fusb_Ubuntu);
            record_path="";
            NeedToCheck=false;
            stopLoopflag=false;
            delete []arr_Ubuntu;
            arr_Ubuntu=NULL;
        }
        
            
            
        
    }
    void File_Opreation()
    {
        cout<<"start to do file operation"<<endl;
    }
    
    void* writeFile(void*)
    {
        while(1)
        {
            if(NeedToCheck)
            {    
                char* path="/media";
                GetUsbFolderLocation(path);
        
                if(FindRecord)
                {
                    WriteFileToUSB();
                }
            }
            else
            {
                cout<<"sleep for 5s"<<endl;
                usleep(5000*1000);
            }
        }
        
    }
    //int main(int argc, char *argv[])  
    int main()  
    {      
        #if 0                
        char* path="/media";
        GetUsbFolderLocation(path);
        
        if(FindRecord)
        {
            File_Opreation();
        }
        #endif
        pthread_t monitor_thread=0;
        pthread_t write_thread=0;
    
        int err=0;
        err=pthread_create(&monitor_thread, NULL,udev_Monitor, NULL);
        if(err!=0)
        {
            cout<<"create thread error"<<endl;
        }    
        else
        {
            cout<<"create thread monitor success "<<endl;
        }
        
        
    
        
        err=pthread_create(&write_thread, NULL,writeFile, NULL);
        if(err!=0)
        {
            cout<<"create thread error"<<endl;
        }
        else
        {
            cout<<"create thread writeFile success "<<endl;
        }
        
        
        if(monitor_thread!=0)
        {
            pthread_join(monitor_thread,NULL);
        }
        if(write_thread!=0)
        {
            pthread_join(write_thread,NULL);
        }    
    
        
        return 0;  
    }  

    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也没人会看,但是还是希望能帮到和我一样的菜鸟。

  • 相关阅读:
    【NX二次开发】修改dlx对话框标题的方法
    【NX二次开发】导入x_t,UF_PS_import_data
    设置NX欢迎界面
    [转]10个顶级的CSS UI开源框架
    [转] 多线程 《深入浅出 Java Concurrency》目录
    [转] JAVA多线程和并发基础面试问答
    [转]StuQ 技能图谱(全套13张)
    [转] MongoDB shell 操作 (查询)
    搜集好的java技术帖子,持续更新,java程序员的要求
    [转]JAVA程序员一定知道的优秀第三方库(2016版)
  • 原文地址:https://www.cnblogs.com/jlmgary/p/6742630.html
Copyright © 2020-2023  润新知