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\n");
 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\n", 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\n",
 96                 udev_device_get_sysattr_value(dev,"idVendor"),
 97                 udev_device_get_sysattr_value(dev, "idProduct"));
 98         printf("  %s\n  %s\n",
 99                 udev_device_get_sysattr_value(dev,"manufacturer"),
100                 udev_device_get_sysattr_value(dev,"product"));
101         printf("  serial: %s\n",
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\n", 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\n",udev_device_get_sysattr_value(dev,"idVendor"), udev_device_get_sysattr_value(dev, "idProduct"));
180             printf("  %s\n  %s\n",udev_device_get_sysattr_value(dev,"manufacturer"), udev_device_get_sysattr_value(dev,"product"));
181             printf("  serial: %s\n",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\n");
251                 printf("   Node: %s\n", udev_device_get_devnode(dev));
252                 printf("   Subsystem: %s\n", udev_device_get_subsystem(dev));
253                 printf("   Devtype: %s\n", udev_device_get_devtype(dev));
254                 printf("   Action: %s\n",udev_device_get_action(dev));
255                 printf("   Path: %s\n",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.\n");
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\n",basePath,ptr->d_name);
290         }
291         else if(ptr->d_type == 10)    ///link file
292         {
293             printf("d_name:%s/%s\n",basePath,ptr->d_name);
294     }
295         else if(ptr->d_type == 4)    ///dir
296         {
297             memset(base,'\0',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\n",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\n",basePath,ptr->d_name);
349             }
350             else if(ptr->d_type == 4)    ///dir
351             {
352                 memset(base,'\0',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也没人会看,但是还是希望能帮到和我一样的菜鸟。

posted @ 2020-03-05 13:53  LiuYanYGZ  阅读(430)  评论(0编辑  收藏  举报