-1

I want to detect a usb connection and mount its corresponding partition. I tried using udev.I was able to find device in /dev/bus/usb/001 or/002.But from this I cannot find which partition it uses. So using udev I searched for block partitions and mount if a partition is added..eg/dev/sda1.But this is a temporary solution. What I want is to detect a usb connection using udev or something and find which partition it is having and mount it.

My Code:

#include <libudev.h>
#include <stdio.h>
#include "dmutil.h"
#include <pthread.h>

#include <unistd.h>

/*
 Thread which detects devices.
 */
void *  udev_listener(void * i)
{

    struct udev *udev;
    udev = udev_new();
    if (!udev) {
        printf("Can't create udev\n");
        exit(1);
    }

    std::string mount_path_for_udev_listner = DEFAULT_MOUNT_PATH;
    printf("\n\n **********\nUdev_listner is asked to mount usb to %s ....",mount_path_for_udev_listner.c_str());

    struct udev_device *dev;
    struct udev_monitor *mon;   
    mon = udev_monitor_new_from_netlink(udev, "udev");
    assert(mon != NULL);
    /*  int udev_monitor_filter_add_match_subsystem_devtype(struct udev_monitor *udev_monitor,const char *subsystem, const char *devtype);
        filters to select messages that get delivered to a listener.
        On Success it returns an integer greater than, or equal to, 0. On failure, a negative error code is returned.
    */
    assert(udev_monitor_filter_add_match_subsystem_devtype(mon, "block", NULL) >=0);
    udev_monitor_enable_receiving(mon);
    /* Get the file descriptor (fd) for the monitor.
       This fd will get passed to select() */

    int fd = udev_monitor_get_fd(mon);
    /* Begin polling for udev events. Events occur when devices attached to the system are added, removed, or change state. 
       udev_monitor_receive_device() will return a device object representing the device which changed and what type of change occured.

       The select() system call is used to ensure that the call to udev_monitor_receive_device() will not block.

       This section will run continuously, calling usleep() at the end of each pass. This is to  use  udev_monitor in a non-blocking way. */
    while (1) 
    {
        /*
            int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);

            select()  allows  a  program  to  monitor  multiple  file descriptors,  waiting  until one or more of the file descriptors 
            become "ready" for some class of I/O operation.

            Set up the call to select(). In this case, select() will only operate on a single file descriptor, the one associated 
            with our udev_monitor. Note that the timeval object is set to 0, which will cause select() to not block. */
        fd_set fds;
        struct timeval tv;
        int ret;

        FD_ZERO(&fds); //clear fds
        FD_SET(fd, &fds);// Add fd to fds
        /*
            The timeout argument specifies the interval that select() should block waiting for a file descriptor to become ready. 
            This interval will be rounded up to the system  clock  granularity, and kernel scheduling delays mean that the 
            blocking interval may overrun by a small amount.  If both fields of the timeval structure are zero, then select() 
            returns immediately. (This is useful for polling.)If timeout is NULL (no timeout), select() can block indefinitely.
        */  
        tv.tv_sec = 0;
        tv.tv_usec = 0;
        /*
          nfds specifies how big the list of file descriptors is because the total number can be vast.
          So, if you want to monitor file descriptors 24-31, you'd set nfds to 32. 
          man - nfds is the highest-numbered file descriptor in any of the three sets, plus 1.
        */
        ret = select(fd+1, &fds, NULL, NULL, &tv);

        /* Check if our file descriptor has received data. */
        if (ret > 0 && FD_ISSET(fd, &fds)) {
            printf("\nselect() says there should be data\n");

            /* Make the call to receive the device.
               select() ensured that this will not block. */
            dev = udev_monitor_receive_device(mon);
            if (dev) {
                printf("Got Device\n");
                printf("   Node: %s\n", udev_device_get_devnode(dev));
                printf("   Subsystem: %s\n", udev_device_get_subsystem(dev));
                printf("   Devtype: %s\n", udev_device_get_devtype(dev));
                printf("   syspath:%s\n",udev_device_get_syspath(dev));
                printf("   sysname:%s\n",udev_device_get_sysname(dev));
                printf("   devpath:%s\n",udev_device_get_devpath(dev));
                printf("   subsystem:%s\n",udev_device_get_subsystem(dev));
                printf("   Action: %s\n", udev_device_get_action(dev));
                std::string devtype=udev_device_get_devtype(dev);
                std::string action=udev_device_get_action(dev);
                std::string devnode=udev_device_get_devnode(dev);
                if(devtype.compare("partition")==0 && action.compare("add") == 0)
                {
                    printf("A new partition detected at %s\nTrying to mount to %s",devnode.c_str(),mount_path_for_udev_listner.c_str());
                    int ret = mount_disk(devnode,mount_path_for_udev_listner);
                    if(ret == 0)
                    {
                        printf("\nSystem returns %d, Mounting success\n",ret);
                    }
                    else{
                            printf("\n*****Error no %d\n",errno);
                    }
                }
                if(devtype.compare("partition")==0 && action.compare("remove") == 0)
                {
                    printf("Partition removal detected, trying to unmount...\n");
                    int ret=umount_disk();
                    if(ret==0){
                        printf("\nSystem returns %d\n",ret);
                        printf("unmount successfull\n");
                    }
                    else{
                        printf("\nThe partition unmounting FAILED:\n ");
                    }
                }
                udev_device_unref(dev);
            }
            else {
                printf("No Device from receive_device(). An error occured.\n");
            }                   
        }
        usleep(250*1000);
        printf(".");
        fflush(stdout);
    }
    pthread_exit(NULL);
}
rjmrohit
  • 11
  • 4

2 Answers2

1

I got the answer. I just had to add one more filter for usb-device. if I get a device as both usb and block I can use the partition and mount it.

 assert(udev_monitor_filter_add_match_subsystem_devtype(mon, "block", NULL)>=0);
 assert(udev_monitor_filter_add_match_subsystem_devtype(mon, "usb","usb-device") >=0);
rjmrohit
  • 11
  • 4
-1

i copied this from https://askubuntu.com/questions/285539/detect-and-mount-devices

sudo lsusb will tell you what USB devices Linux detects. Whether a USB storage device mounts, or is detected, are separate issues. sudo lsusb -v will give verbose output, possibly more information than you want if the OS truly doesn't recognize the device.

Alternatively, you could compare the lists of devices in /dev before and after plugging in the USB device. There are many ways to do it; I would probably just use:

ls -l /dev/* | wc -l

This will give you a number of recognized devices. Doing it before and after plugging in a device will tell you if the OS assigned the device in /dev/.

Another option would be to look at what is happening in dmesg when you plug in the USB device. dmesg may tell you things like how a device failed.

If the USB device you are having trouble mounting, is on the lsusb list, then you can try mounting the device. At this point it would be good to know the filesystem type. sudo fdisk -l will tell you the filesystem type, in the form of an ID. You may have to look up the ID number. There are lots of references online for that. Once you know the device listing, that is, /dev/hda1 and the filesystem type you can try to mount the device manualy with the mount command.

sudo mount /dev/hda1 /home/user/Desktop/whereEver

You may have to make sure the location you want to mount the device on exists. If the OS recognizes the file system, then mount might just work if the file system is not a native file system type; you may have to specify flags for mounting.

Post back your output from dmesg (not all of it, only from around when the USB device is plugged in), and sudo lsusb.

You may find Linux / UNIX: Device files helpful if trying to determine device type.

I am writing this assuming all your unrecognized devices are block type devices. There are many ways to approach this type of problem and many possible solutions. More specific information is needed to provide a solution.

There are also many GUI applications that can do the same thing. You might try looking for the plugged-in hardware in the "Disk Utility".

An alternative way to detect attached USB devices is DBus or HAL (however Hal is considered to be deprecated), see this How to detect inserted USB and linux hotplugging

Community
  • 1
  • 1
ralf htp
  • 9,149
  • 4
  • 22
  • 34