Example #1
0
void
UdevSubsystem::enumerate_udev_devices()
{
  assert(m_process_match_cb);

  // Enumerate over all devices already connected to the computer
  struct udev_enumerate* enumerate = udev_enumerate_new(m_udev);
  assert(enumerate);

  udev_enumerate_add_match_subsystem(enumerate, "usb");
  // not available yet: udev_enumerate_add_match_is_initialized(enumerate);
  udev_enumerate_scan_devices(enumerate);

  struct udev_list_entry* devices;
  struct udev_list_entry* dev_list_entry;

  devices = udev_enumerate_get_list_entry(enumerate);
  udev_list_entry_foreach(dev_list_entry, devices)
  {
    // name is path, value is NULL
    const char* path = udev_list_entry_get_name(dev_list_entry);

    struct udev_device* device = udev_device_new_from_syspath(m_udev, path);

    // manually filter for devtype, as udev enumerate can't do it by itself
    const char* devtype = udev_device_get_devtype(device);
    if (devtype && strcmp(devtype, "usb_device") == 0)
    {
      m_process_match_cb(device);
    }
    udev_device_unref(device);
  }
  udev_enumerate_unref(enumerate);
}
Example #2
0
File: ldm.c Project: vodik/ldm
struct device_t *
device_new (struct udev_device *dev)
{
    struct device_t *device;

    const char *dev_type;
    const char *dev_idtype;
   
    device = malloc(sizeof(struct device_t));

    device->udev = dev;

    device->devnode = s_strdup(udev_device_get_devnode(dev));
    device->filesystem = s_strdup(udev_device_get_property_value(dev, "ID_FS_TYPE"));

    dev_type    = udev_device_get_devtype(dev);
    dev_idtype  = udev_device_get_property_value(dev, "ID_TYPE");

    device->type = DEVICE_UNK;

    if (!device->filesystem) {
        device_destroy(device);
        return NULL;
    }

    if (!strcmp(dev_type,   "partition")|| 
        !strcmp(dev_type,   "disk")     || 
        !strcmp(dev_idtype, "floppy"))  {
        device->type = DEVICE_VOLUME;
    } else if (!strcmp(dev_idtype, "cd")) {
        device->type = DEVICE_CD;
    }

    if (device->type == DEVICE_UNK) {
        device_destroy(device);
        return NULL;
    }

    device->has_media = device_has_media(device);
    device->fstab_entry = fstab_search(g_fstab, device);

    device->mountpoint = NULL;

    if (device->has_media) {
        if (device->fstab_entry) {
            device->mountpoint = s_strdup(device->fstab_entry->path);
        } else {
            device->mountpoint = device_create_mountpoint(device);
        }
    }

    device->mounted = device_is_mounted(device->devnode);

    if (!device_register(device)) {
        device_destroy(device);
        return NULL;
    }

    return device;
}
QString Device::devType() const
{
    if (!d)
        return QString();

    return QString::fromLatin1(udev_device_get_devtype(d->udev));
}
Example #4
0
void Storage::checkDevice(int fd) {
    PowerManagerLock* powerLock = PowerManager::getNewLock(this);
    powerLock->activate();
    qDebug() << Q_FUNC_INFO << "FD: "<< fd;

    struct udev_device *dev;
    dev = udev_monitor_receive_device(udev_monitor);
    if (dev)
    {
        QString device = udev_device_get_devnode(dev);
        QString path = udev_device_get_devpath(dev);
        QString action = udev_device_get_action(dev);
        QString devtype = udev_device_get_devtype(dev);
        QString sysname("/dev/");
        sysname += QString(udev_device_get_sysname(dev));
        QString parent = udev_device_get_devpath( udev_device_get_parent (dev));
        if (sysname.contains(QRegExp("mmcblk[0-9]\\d*"))  || sysname.contains(QRegExp("mmcblk[0-9]")))
        {
            qDebug() << "Got " << path << ":" << action;
            qDebug() << "    Got Device";
            qDebug() << "    Node: " <<  udev_device_get_devnode(dev);
            qDebug() << "    Subsystem: "<< udev_device_get_subsystem(dev);
            qDebug() << "    Devtype: " << devtype;
            qDebug() << "    Action: " << action;
            qDebug() << "    Sysname: " << sysname;
            qDebug() << "    sysnum: " << udev_device_get_sysnum (dev);
            qDebug() << "    parent: " << parent;

            processRemovableUdevEvents(devtype, path, sysname, action);
        }
        udev_device_unref(dev);
    }
    delete powerLock;
}
Example #5
0
QUdevDeviceList QUdevPrivate::getUDevDevicesForSubsystem(const QString &strSubSystem, const QString &strDeviceType, const QString &strParentSubSystem, const QString &strParentDeviceType)
{
    struct udev_enumerate *enumerate = udev_enumerate_new(m_pUdev);
    struct udev_list_entry *devices = 0;
    struct udev_list_entry *dev_list_entry = 0;
    struct udev_device *dev = 0;

    QList<QUdevDevice> lDevices;

    if(strSubSystem.isEmpty()) return lDevices;

    //get subsystem enumerator
    udev_enumerate_add_match_subsystem(enumerate, strSubSystem.toLatin1().constData());
    //perform sysfs scanning
    udev_enumerate_scan_devices(enumerate);
    devices = udev_enumerate_get_list_entry(enumerate);

    //iterate over all devices in the enumeration list
    udev_list_entry_foreach(dev_list_entry, devices)
    {
        QUdevDevice udDev;

        //create udev device for the sysfs path returned
        udDev.m_strSysfsPath = QString::fromLatin1(udev_list_entry_get_name(dev_list_entry));        
        dev = udev_device_new_from_syspath(m_pUdev, udDev.m_strSysfsPath.toLatin1().constData());

        //filter the correct device types, ignored if empty device type is specified
        if(strDeviceType.isEmpty() || (QString::fromLatin1(udev_device_get_devtype(dev)) == strDeviceType))
        {
            //get the path inside /dev
            udDev.m_strDevPath = QString::fromLatin1(udev_device_get_devnode(dev));
            udDev.m_strSubsystem = strSubSystem;
            udDev.m_strDeviceType = strDeviceType;

            //if the caller wants a specific parent subsystem/devtype query the sysfs tree here
            if(!strParentSubSystem.isEmpty() && !strParentDeviceType.isEmpty())
            {
                /*
                 * retrieve the parent device with the subsystem/devtype pair of m_strParentSubSystem/m_strParentDeviceType.
                 *
                 * udev_device_get_parent_with_subsystem_devtype() will walk up the complete tree if needed
                 */
                dev = udev_device_get_parent_with_subsystem_devtype(dev, strParentSubSystem.toLatin1().constData(), strParentDeviceType.toLatin1().constData());
            }

            if(dev)
            {
                //fill the device information
                udDev.m_strVendorID = QString::fromLatin1(udev_device_get_sysattr_value(dev,"idVendor"));
                udDev.m_strProductID = QString::fromLatin1(udev_device_get_sysattr_value(dev, "idProduct"));
                udDev.m_strManufacturer = QString::fromLatin1(udev_device_get_sysattr_value(dev,"manufacturer"));
                udDev.m_strProduct = QString::fromLatin1(udev_device_get_sysattr_value(dev,"product"));
                udDev.m_strSerial = QString::fromLatin1(udev_device_get_sysattr_value(dev, "serial"));
                lDevices.append(udDev);
            }

            udev_device_unref(dev);
        }
    }
Example #6
0
bool IsStorageDisk(udev_device* UdevDevice)
{
    const char* udevDeviceType = udev_device_get_devtype(UdevDevice);
    if (0 == strcmp(udevDeviceType, "disk"))
    {
        if (true == IsAtaDeviceBus(UdevDevice) || true == IsScsiDeviceBus(UdevDevice))
        {
            return true;
        }
    }
    return false;
}
Example #7
0
static void print_device(struct udev_device *device)
{
    const char *str;
    dev_t devnum;
    int count;
    struct udev_list_entry *list_entry;

    printf("*** device: %p ***\n", device);
    str = udev_device_get_action(device);
    if (str != NULL)
        printf("action:    '%s'\n", str);

    str = udev_device_get_syspath(device);
    printf("syspath:   '%s'\n", str);

    str = udev_device_get_sysname(device);
    printf("sysname:   '%s'\n", str);

    str = udev_device_get_sysnum(device);
    if (str != NULL)
        printf("sysnum:    '%s'\n", str);

    str = udev_device_get_devpath(device);
    printf("devpath:   '%s'\n", str);

    str = udev_device_get_subsystem(device);
    if (str != NULL)
        printf("subsystem: '%s'\n", str);

    str = udev_device_get_devtype(device);
    if (str != NULL)
        printf("devtype:   '%s'\n", str);

    str = udev_device_get_driver(device);
    if (str != NULL)
        printf("driver:    '%s'\n", str);

    str = udev_device_get_devnode(device);
    if (str != NULL)
        printf("devname:   '%s'\n", str);

    devnum = udev_device_get_devnum(device);
    if (major(devnum) > 0)
        printf("devnum:    %u:%u\n", major(devnum), minor(devnum));

    count = 0;
    udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(device)) {
        printf("link:      '%s'\n", udev_list_entry_get_name(list_entry));
        count++;
    }
Example #8
0
bool CUDevProvider::PumpDriveChangeEvents(IStorageEventsCallback *callback)
{
  bool changed = false;

  fd_set readfds;
  FD_ZERO(&readfds);
  FD_SET(udev_monitor_get_fd(m_udevMon), &readfds);

  // non-blocking, check the file descriptor for received data
  struct timeval tv = {0};
  int count = select(udev_monitor_get_fd(m_udevMon) + 1, &readfds, NULL, NULL, &tv);
  if (count < 0)
    return false;

  if (FD_ISSET(udev_monitor_get_fd(m_udevMon), &readfds))
  {
		struct udev_device *dev = udev_monitor_receive_device(m_udevMon);
    if (!dev)
      return false;

    const char *action  = udev_device_get_action(dev);
    const char *devtype = udev_device_get_devtype(dev);
    if (action)
    {
      const char *label = udev_device_get_property_value(dev, "ID_FS_LABEL");
      const char *mountpoint = get_mountpoint(udev_device_get_devnode(dev));
      if (!label)
        label = URIUtils::GetFileName(mountpoint);

      if (!strcmp(action, "add") && !strcmp(devtype, "partition"))
      {
        CLog::Log(LOGNOTICE, "UDev: Added %s", mountpoint);
        if (callback)
          callback->OnStorageAdded(label, mountpoint);
        changed = true;
      }
      if (!strcmp(action, "remove") && !strcmp(devtype, "partition"))
      {
        CLog::Log(LOGNOTICE, "UDev: Removed %s", mountpoint);
        if (callback)
          callback->OnStorageSafelyRemoved(label);
        changed = true;
      }
    }
    udev_device_unref(dev);
  }

  return changed;
}
Example #9
0
int Storage::enumerate_mmcblk_devices(struct udev *udev)
{
    struct udev_enumerate *udev_enumerate;

    qDebug() << Q_FUNC_INFO << ": enumerate 'block' devices";
    udev_enumerate = udev_enumerate_new(udev);
    if (udev_enumerate == NULL)
        return -1;
    udev_enumerate_add_match_subsystem(udev_enumerate,"block");
    udev_enumerate_scan_devices(udev_enumerate);
    struct udev_list_entry *list_entry;

    udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(udev_enumerate))
    {
        struct udev_device *device;

        device = udev_device_new_from_syspath(udev_enumerate_get_udev(udev_enumerate),
                                      udev_list_entry_get_name(list_entry));
        if (device != NULL) {
            QString sysname("/dev/");
            sysname += QString(udev_device_get_sysname(device));
            if (sysname.contains(QRegExp("mmcblk[1-9]\\d*"))  || sysname.contains(QRegExp("mmcblk[1-9]")))
            {
                QString path = udev_device_get_devpath(device);
                QString parent = udev_device_get_devpath( udev_device_get_parent (device));
                QString action = "add";
                QString devtype = udev_device_get_devtype(device);

                qDebug() << "Enumerate device " << path << ":" << action;
                qDebug() << "    Got Device";
                qDebug() << "    Node: " <<  udev_device_get_devnode(device);
                qDebug() << "    Subsystem: "<< udev_device_get_subsystem(device);
                qDebug() << "    Devtype: " << devtype;
                qDebug() << "    Action: " << action;
                qDebug() << "    Sysname: " << sysname;
                qDebug() << "    sysnum: " << udev_device_get_sysnum (device);
                qDebug() << "    parent: " << parent;

                processRemovableUdevEvents(devtype, path, sysname, action);
            }

            udev_device_unref(device);
        }
    }

    udev_enumerate_unref(udev_enumerate);
    return 0;
}
static int udev_builtin_hwdb_search(struct udev_device *dev, struct udev_device *srcdev,
                                    const char *subsystem, const char *prefix,
                                    const char *filter, bool test) {
        struct udev_device *d;
        char s[16];
        bool last = false;
        int r = 0;

        assert(dev);

        if (!srcdev)
                srcdev = dev;

        for (d = srcdev; d && !last; d = udev_device_get_parent(d)) {
                const char *dsubsys;
                const char *modalias = NULL;

                dsubsys = udev_device_get_subsystem(d);
                if (!dsubsys)
                        continue;

                /* look only at devices of a specific subsystem */
                if (subsystem && !streq(dsubsys, subsystem))
                        continue;

                modalias = udev_device_get_property_value(d, "MODALIAS");

                if (streq(dsubsys, "usb") && streq_ptr(udev_device_get_devtype(d), "usb_device")) {
                        /* if the usb_device does not have a modalias, compose one */
                        if (!modalias)
                                modalias = modalias_usb(d, s, sizeof(s));

                        /* avoid looking at any parent device, they are usually just a USB hub */
                        last = true;
                }

                if (!modalias)
                        continue;

                r = udev_builtin_hwdb_lookup(dev, prefix, modalias, filter, test);
                if (r > 0)
                        break;
        }

        return r;
}
Example #11
0
rw_status_t
rw_udev_recv_device(rw_udev_handle_t *handle)
{
  struct udev_device *dev;
  
  dev = udev_monitor_receive_device(handle->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("   Action: %s\n", udev_device_get_action(dev));
    udev_device_unref(dev);
  }
  
  return RW_STATUS_SUCCESS;
}
Example #12
0
static struct udev_device *handle_usb(struct udev_device *parent, char **path)
{
	const char *devtype;
	const char *str;
	const char *port;

	devtype = udev_device_get_devtype(parent);
	if (devtype == NULL || strcmp(devtype, "usb_interface") != 0)
		return parent;

	str = udev_device_get_sysname(parent);
	port = strchr(str, '-');
	if (port == NULL)
		return parent;
	port++;

	parent = skip_subsystem(parent, "usb");
	path_prepend(path, "usb-0:%s", port);
	return parent;
}
static int link_get_type_string(int iftype, struct udev_device *d, char **ret) {
        const char *t;
        char *p;

        if (iftype == ARPHRD_ETHER && d) {
                const char *devtype, *id = NULL;
                /* WLANs have iftype ARPHRD_ETHER, but we want
                 * to show a more useful type string for
                 * them */

                devtype = udev_device_get_devtype(d);
                if (streq_ptr(devtype, "wlan"))
                        id = "wlan";
                else if (streq_ptr(devtype, "wwan"))
                        id = "wwan";

                if (id) {
                        p = strdup(id);
                        if (!p)
                                return -ENOMEM;

                        *ret = p;
                        return 1;
                }
        }

        t = arphrd_to_name(iftype);
        if (!t) {
                *ret = NULL;
                return 0;
        }

        p = strdup(t);
        if (!p)
                return -ENOMEM;

        ascii_strlower(p);
        *ret = p;

        return 0;
}
Example #14
0
static struct udev_device *handle_scsi(struct udev_device *parent, char **path)
{
	const char *devtype;
	const char *name;
	const char *id;

	devtype = udev_device_get_devtype(parent);
	if (devtype == NULL || strcmp(devtype, "scsi_device") != 0)
		return parent;

	/* firewire */
	id = udev_device_get_sysattr_value(parent, "ieee1394_id");
	if (id != NULL) {
		parent = skip_subsystem(parent, "scsi");
		path_prepend(path, "ieee1394-0x%s", id);
		goto out;
	}

	/* lousy scsi sysfs does not have a "subsystem" for the transport */
	name = udev_device_get_syspath(parent);

	if (strstr(name, "/rport-") != NULL) {
		parent = handle_scsi_fibre_channel(parent, path);
		goto out;
	}

	if (strstr(name, "/end_device-") != NULL) {
		parent = handle_scsi_sas(parent, path);
		goto out;
	}

	if (strstr(name, "/session") != NULL) {
		parent = handle_scsi_iscsi(parent, path);
		goto out;
	}

	parent = handle_scsi_default(parent, path);
out:
	return parent;
}
Example #15
0
UdevEventContextRef UdevEventPublisher::createEventContextFrom(
    struct udev_device* device) {
  auto ec = createEventContext();
  ec->device = device;
  // Map the action string to the eventing enum.
  ec->action = UDEV_EVENT_ACTION_UNKNOWN;
  ec->action_string = std::string(udev_device_get_action(device));
  if (ec->action_string == "add") {
    ec->action = UDEV_EVENT_ACTION_ADD;
  } else if (ec->action_string == "remove") {
    ec->action = UDEV_EVENT_ACTION_REMOVE;
  } else if (ec->action_string == "change") {
    ec->action = UDEV_EVENT_ACTION_CHANGE;
  }

  // Set the subscription-aware variables for the event.
  auto value = udev_device_get_subsystem(device);
  if (value != nullptr) {
    ec->subsystem = std::string(value);
  }

  value = udev_device_get_devnode(device);
  if (value != nullptr) {
    ec->devnode = std::string(value);
  }

  value = udev_device_get_devtype(device);
  if (value != nullptr) {
    ec->devtype = std::string(value);
  }

  value = udev_device_get_driver(device);
  if (value != nullptr) {
    ec->driver = std::string(value);
  }

  return ec;
}
Example #16
0
int main (void)
{
	struct udev *udev;
	struct udev_enumerate *enumerate;
	struct udev_list_entry *devices, *dev_list_entry;
	struct udev_device *dev;

	struct udev_monitor *mon;
	int fd;

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

	/* This section sets up a monitor which will report events when
	   devices attached to the system change.  Events include "add",
	   "remove", "change", "online", and "offline".

	   This section sets up and starts the monitoring. Events are
	   polled for (and delivered) later in the file.

	   It is important that the monitor be set up before the call to
	   udev_enumerate_scan_devices() so that events (and devices) are
	   not missed.  For example, if enumeration happened first, there
	   would be no event generated for a device which was attached after
	   enumeration but before monitoring began.

	   Note that a filter is added so that we only get events for
	   "hidraw" devices. */

	/* Set up a monitor to monitor hidraw devices */
	mon = udev_monitor_new_from_netlink(udev, "udev");
//	udev_monitor_filter_add_match_subsystem_devtype(mon, "hidraw", NULL);
	udev_monitor_filter_add_match_subsystem_devtype(mon, "block", NULL);
	udev_monitor_enable_receiving(mon);
	/* Get the file descriptor (fd) for the monitor.
	   This fd will get passed to select() */
	fd = udev_monitor_get_fd(mon);


	/* Create a list of the devices in the 'hidraw' subsystem. */
	enumerate = udev_enumerate_new(udev);
//	udev_enumerate_add_match_subsystem(enumerate, "hidraw");
	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\n", udev_device_get_devnode(dev));

#if 0
		/* 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) {
			printf("Unable to find parent usb device.");
			exit(1);
		}
#endif
		/* 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 /sys 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\n",
		        udev_device_get_sysattr_value(dev,"idVendor"),
		        udev_device_get_sysattr_value(dev, "idProduct"));
		printf("  %s\n  %s\n",
		        udev_device_get_sysattr_value(dev,"manufacturer"),
		        udev_device_get_sysattr_value(dev,"product"));
		printf("  serial: %s\n",
		         udev_device_get_sysattr_value(dev, "serial"));
		udev_device_unref(dev);
	}
	/* Free the enumerator object */
	udev_enumerate_unref(enumerate);

	/* 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.

	   The monitor was set up earler in this file, and monitoring is
	   already underway.

	   This section will run continuously, calling usleep() at the end
	   of each pass. This is to demonstrate how to use a udev_monitor
	   in a non-blocking way. */
	while (1) {
		/* 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);
		FD_SET(fd, &fds);
		tv.tv_sec = 0;
		tv.tv_usec = 0;

		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("   Action: %s\n", udev_device_get_action(dev));
				udev_device_unref(dev);
			}
			else {
				printf("No Device from receive_device(). An error occured.\n");
			}
		}
		usleep(250*1000);
		printf(".");
		fflush(stdout);
	}


	udev_unref(udev);

	return 0;
}
Example #17
0
/* check for udev events for v4l2 devices*/
gboolean 
check_v4l2_udev_events(gpointer data)
{
    struct ALL_DATA * all_data = (struct ALL_DATA *) data;
    struct vdIn *videoIn = all_data->videoIn;
    struct GLOBAL *global = all_data->global;
    struct GWIDGET *gwidget = all_data->gwidget;
    
    fd_set fds;
    struct timeval tv;
    int ret;
    
    FD_ZERO(&fds);
    FD_SET(videoIn->udev_fd, &fds);
    tv.tv_sec = 0;
    tv.tv_usec = 0;
    
    ret = select(videoIn->udev_fd+1, &fds, NULL, NULL, &tv);
    
    /* Check if our file descriptor has received data. */
    if (ret > 0 && FD_ISSET(videoIn->udev_fd, &fds)) 
    {
        /* Make the call to receive the device.
            select() ensured that this will not block. */
        struct udev_device *dev = udev_monitor_receive_device(videoIn->udev_mon);
        if (dev) 
        {
            if (global->debug)
            {
                g_print("Got Device event\n");
                g_print("   Node: %s\n", udev_device_get_devnode(dev));
                g_print("   Subsystem: %s\n", udev_device_get_subsystem(dev));
                g_print("   Devtype: %s\n", udev_device_get_devtype(dev));

                g_print("   Action: %s\n",udev_device_get_action(dev));
            }
            
            /*update device list*/
            g_signal_handlers_block_by_func(GTK_COMBO_BOX_TEXT(gwidget->Devices), 
                G_CALLBACK (Devices_changed), all_data);
                
            /* clear out the old device list... */
            if(videoIn->listDevices != NULL) freeDevices(videoIn->listDevices);
            
            GtkListStore *store = GTK_LIST_STORE(gtk_combo_box_get_model (GTK_COMBO_BOX(gwidget->Devices)));
            gtk_list_store_clear(store);
            
            /*create new device list*/
            videoIn->listDevices = enum_devices( videoIn->videodevice, videoIn->udev, global->debug );
            
            if (videoIn->listDevices->num_devices < 1)
            {
                //use current
                gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(gwidget->Devices),
                    videoIn->videodevice);
                gtk_combo_box_set_active(GTK_COMBO_BOX(gwidget->Devices),0);
            }
            else
            {
                int i=0;
                for(i=0;i<(videoIn->listDevices->num_devices);i++)
                {
                    gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(gwidget->Devices),
                        videoIn->listDevices->listVidDevices[i].name);
                    if(videoIn->listDevices->listVidDevices[i].current)
                        gtk_combo_box_set_active(GTK_COMBO_BOX(gwidget->Devices),i);
                }
            }
            g_signal_handlers_unblock_by_func(GTK_COMBO_BOX_TEXT(gwidget->Devices), 
                G_CALLBACK (Devices_changed), all_data);
            
            udev_device_unref(dev);
        }
        else 
            g_printerr("No Device from receive_device(). An error occured.\n");

    }

    return(TRUE);
}
Example #18
0
void
UdevSubsystem::print_info(udev_device* device)
{
  log_debug("/---------------------------------------------");
  log_debug("devpath: " << udev_device_get_devpath(device));

  if (udev_device_get_action(device))
    log_debug("action: " << udev_device_get_action(device));
  //log_debug("init: " << udev_device_get_is_initialized(device));

  if (udev_device_get_subsystem(device))
    log_debug("subsystem: " << udev_device_get_subsystem(device));

  if (udev_device_get_devtype(device))
    log_debug("devtype:   " << udev_device_get_devtype(device));

  if (udev_device_get_syspath(device))
    log_debug("syspath:   " << udev_device_get_syspath(device));

  if (udev_device_get_sysname(device))
    log_debug("sysname:   " << udev_device_get_sysname(device));

  if (udev_device_get_sysnum(device))
    log_debug("sysnum:    " << udev_device_get_sysnum(device));

  if (udev_device_get_devnode(device))
    log_debug("devnode:   " << udev_device_get_devnode(device));

  if (udev_device_get_driver(device))
    log_debug("driver:    " << udev_device_get_driver(device));

  if (udev_device_get_action(device))
    log_debug("action:    " << udev_device_get_action(device));

  //udev_device_get_sysattr_value(device, "busnum");
  //udev_device_get_sysattr_value(device, "devnum");

#if 0
  // FIXME: only works with newer versions of libudev
  {
    log_debug("list: ");
    struct udev_list_entry* it = udev_device_get_tags_list_entry(device);
    while((it = udev_list_entry_get_next(it)) != 0)
    {
      log_debug("  "
                << udev_list_entry_get_name(it) << " = "
                << udev_list_entry_get_value(it)
        );
    }
  }

  {
    log_debug("properties: ");
    struct udev_list_entry* it = udev_device_get_properties_list_entry(device);
    while((it = udev_list_entry_get_next(it)) != 0)
    {
      log_debug("  "
                << udev_list_entry_get_name(it) << " = "
                << udev_list_entry_get_value(it)
        );
    }
  }

  {
    log_debug("devlist: ");
    struct udev_list_entry* it = udev_device_get_tags_list_entry(device);
    while((it = udev_list_entry_get_next(it)) != 0)
    {
      log_debug("  "
                << udev_list_entry_get_name(it) << " = "
                << udev_list_entry_get_value(it)
        );
    }
  }
#endif

  log_debug("\\----------------------------------------------");
}
Example #19
0
   static void *Listener(void *parm)
   {
      DeviceChangeListener *This = (DeviceChangeListener *) parm;

      // Instantiate the udev object
      struct udev *udev = udev_new();
      if (!udev)
      {
         pthread_exit(NULL);
      }
   
      // Instantiate the monitor object
      struct udev_monitor *mon = udev_monitor_new_from_netlink(udev, "udev");

      // Start receiving notifications
      udev_monitor_enable_receiving(mon);

      // Get the file descriptor we'll wait on
      int fd = udev_monitor_get_fd(mon);

      while (true)
      {
         fd_set set;
         
         FD_ZERO(&set);
         FD_SET(fd, &set);

         if (select(fd + 1, &set, NULL, NULL, NULL) < 0)
         {
            break;
         }
         
         if (FD_ISSET(fd, &set))
         {
            struct udev_device *dev = udev_monitor_receive_device(mon);
            if (dev)
            {
#if 0
               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("   Action: %s\n", udev_device_get_action(dev));
#endif
               if (This->mEnabled)
               {
                  This->mEnabled = false;
                  wxMutexGuiEnter();
                  wxCommandEvent e(EVT_DEVICE_CHANGE);
                  This->mHandler->AddPendingEvent(e);
                  wxMutexGuiLeave();
               }
         
               udev_device_unref(dev);
            }
         }
      }
   
      udev_unref(udev);

      pthread_exit(NULL);
   }
jobjectArray getusb_firmware_version(JNIEnv *env, jint usbvid_to_match, jint usbpid_to_match, jstring serial_number) {

	int x = 0;
	int vid = 0;
	int pid = 0;
	struct udev *udev_ctx;
	struct udev_enumerate *enumerator;
	struct udev_list_entry *devices, *dev_list_entry;
	const char *sysattr_val;
	const char *path;
	struct udev_device *udev_device;
	char *endptr;
	char buffer[128];
	const char* serial = NULL;
	const char *prop_val;
	struct jstrarray_list list = {0};
	jstring usb_dev_info;
	jclass strClass = NULL;
	jobjectArray usbDevicesFwVerFound = NULL;

	if(serial_number != NULL) {
		serial = (*env)->GetStringUTFChars(env, serial_number, NULL);
		if((serial == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
			throw_serialcom_exception(env, 3, 0, E_GETSTRUTFCHARSTR);
			return NULL;
		}
	}

	init_jstrarraylist(&list, 10);

	/* libudev is reference counted. Memory is freed when counts reach to zero. */
	udev_ctx = udev_new();
	enumerator = udev_enumerate_new(udev_ctx);
	udev_enumerate_add_match_subsystem(enumerator, "usb");
	udev_enumerate_scan_devices(enumerator);
	devices = udev_enumerate_get_list_entry(enumerator);

	udev_list_entry_foreach(dev_list_entry, devices) {
		path = udev_list_entry_get_name(dev_list_entry);
		udev_device = udev_device_new_from_syspath(udev_enumerate_get_udev(enumerator), path);
		if(udev_device == NULL) {
			continue;
		}

		if(strcmp("usb_device", udev_device_get_devtype(udev_device)) == 0) {

			/* match vid */
			sysattr_val = udev_device_get_sysattr_value(udev_device, "idVendor");
			if(sysattr_val != NULL) {
				vid = 0x0000FFFF & (int)strtol(sysattr_val, &endptr, 16);
				if(vid != usbvid_to_match) {
					udev_device_unref(udev_device);
					continue;
				}
			}else {
				udev_device_unref(udev_device);
				continue;
			}

			/* match pid */
			sysattr_val = udev_device_get_sysattr_value(udev_device, "idProduct");
			if(sysattr_val != NULL) {
				pid = 0x0000FFFF & (int)strtol(sysattr_val, &endptr, 16);
				if(pid != usbpid_to_match) {
					udev_device_unref(udev_device);
					continue;
				}
			}else {
				udev_device_unref(udev_device);
				continue;
			}

			/* match serial number if requested by application */
			if (serial != NULL) {
				sysattr_val = udev_device_get_sysattr_value(udev_device, "serial");
				if(sysattr_val != NULL) {
					if(strcasecmp(sysattr_val, serial) != 0) {
						udev_device_unref(udev_device);
						continue;
					}
				}else {
					udev_device_unref(udev_device);
					continue;
				}
			}

			/* reaching here means that this is the device whose firmware version application need to know. */
			prop_val = udev_device_get_property_value(udev_device, "ID_REVISION");
			memset(buffer, '\0', sizeof(buffer));
			snprintf(buffer, 128, "%d", (0x0000FFFF & (int)strtol(prop_val, &endptr, 16)));
			usb_dev_info = (*env)->NewStringUTF(env, buffer);
			if((usb_dev_info == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
				free_jstrarraylist(&list);
				udev_device_unref(udev_device);
				udev_enumerate_unref(enumerator);
				udev_unref(udev_ctx);
				throw_serialcom_exception(env, 3, 0, E_NEWSTRUTFSTR);
				return NULL;
			}
			insert_jstrarraylist(&list, usb_dev_info);
		}
		udev_device_unref(udev_device);
	}
Example #21
0
int main (void)
{
	struct udev *udev;
	struct udev_enumerate *enumerate;
	struct udev_list_entry *devices, *dev_list_entry;
	struct udev_device *dev;
	struct udev_device *parent_dev;
	
	/* Create the udev object */
	udev = udev_new();
	if (!udev) {
		printf("Can't create udev\n");
		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);
		
		parent_dev = udev_device_get_parent_with_subsystem_devtype(
		       dev,
		       "usb",
		       "usb_device");
		if (parent_dev) {
		/* usb_device_get_devnode() returns the path to the device node
		   itself in /dev. */
		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));
		/* 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");
	
		/* 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\n",
		        udev_device_get_sysattr_value(dev,"idVendor"),
		        udev_device_get_sysattr_value(dev, "idProduct"));
		printf("  %s\n  %s\n",
		        udev_device_get_sysattr_value(dev,"manufacturer"),
		        udev_device_get_sysattr_value(dev,"product"));
		printf("  serial: %s\n",
		         udev_device_get_sysattr_value(dev, "serial"));
		udev_device_unref(dev);
		udev_device_unref(parent_dev);
	}}
	/* Free the enumerator object */
	udev_enumerate_unref(enumerate);

	udev_unref(udev);

	return 0;       
}
Example #22
0
static int builtin_net_id(struct udev_device *dev, int argc, char *argv[], bool test) {
        const char *s;
        const char *p;
        unsigned int i;
        const char *devtype;
        const char *prefix = "en";
        struct netnames names = {};
        int err;

        /* handle only ARPHRD_ETHER devices */
        s = udev_device_get_sysattr_value(dev, "type");
        if (!s)
                return EXIT_FAILURE;
        i = strtoul(s, NULL, 0);
        if (i != 1)
                return 0;

        /* skip stacked devices, like VLANs, ... */
        s = udev_device_get_sysattr_value(dev, "ifindex");
        if (!s)
                return EXIT_FAILURE;
        p = udev_device_get_sysattr_value(dev, "iflink");
        if (!p)
                return EXIT_FAILURE;
        if (strcmp(s, p) != 0)
                return 0;

        devtype = udev_device_get_devtype(dev);
        if (devtype) {
                if (streq("wlan", devtype))
                        prefix = "wl";
                else if (streq("wwan", devtype))
                        prefix = "ww";
        }

        err = names_mac(dev, &names);
        if (err >= 0 && names.mac_valid) {
                char str[IFNAMSIZ];

                snprintf(str, sizeof(str), "%sx%02x%02x%02x%02x%02x%02x", prefix,
                         names.mac[0], names.mac[1], names.mac[2],
                         names.mac[3], names.mac[4], names.mac[5]);
                udev_builtin_add_property(dev, test, "ID_NET_NAME_MAC", str);

                ieee_oui(dev, &names, test);
        }

        /* get PCI based path names, we compose only PCI based paths */
        err = names_pci(dev, &names);
        if (err < 0)
                goto out;

        /* plain PCI device */
        if (names.type == NET_PCI) {
                char str[IFNAMSIZ];

                if (names.pci_onboard[0])
                        if (snprintf(str, sizeof(str), "%s%s", prefix, names.pci_onboard) < (int)sizeof(str))
                                udev_builtin_add_property(dev, test, "ID_NET_NAME_ONBOARD", str);

                if (names.pci_onboard_label)
                        if (snprintf(str, sizeof(str), "%s%s", prefix, names.pci_onboard_label) < (int)sizeof(str))
                                udev_builtin_add_property(dev, test, "ID_NET_LABEL_ONBOARD", str);

                if (names.pci_path[0])
                        if (snprintf(str, sizeof(str), "%s%s", prefix, names.pci_path) < (int)sizeof(str))
                                udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str);

                if (names.pci_slot[0])
                        if (snprintf(str, sizeof(str), "%s%s", prefix, names.pci_slot) < (int)sizeof(str))
                                udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str);
                goto out;
        }

        /* USB device */
        err = names_usb(dev, &names);
        if (err >= 0 && names.type == NET_USB) {
                char str[IFNAMSIZ];

                if (names.pci_path[0])
                        if (snprintf(str, sizeof(str), "%s%s%s", prefix, names.pci_path, names.usb_ports) < (int)sizeof(str))
                                udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str);

                if (names.pci_slot[0])
                        if (snprintf(str, sizeof(str), "%s%s%s", prefix, names.pci_slot, names.usb_ports) < (int)sizeof(str))
                                udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str);
                goto out;
        }

        /* Broadcom bus */
        err = names_bcma(dev, &names);
        if (err >= 0 && names.type == NET_BCMA) {
                char str[IFNAMSIZ];

                if (names.pci_path[0])
                        if (snprintf(str, sizeof(str), "%s%s%s", prefix, names.pci_path, names.bcma_core) < (int)sizeof(str))
                                udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str);

                if (names.pci_slot[0])
                        if (snprintf(str, sizeof(str), "%s%s%s", prefix, names.pci_slot, names.bcma_core) < (int)sizeof(str))
                                udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str);
                goto out;
        }

out:
        return EXIT_SUCCESS;
}
Example #23
0
int main(int argc, char **argv)
{
	struct udev *udev = udev_new();
	if (udev == NULL) {
		fprintf(stderr, "Unable to initialize udev context");
		return -1;
	}

#ifdef DEBUG
	struct udev_enumerate *enumerate = udev_enumerate_new(udev);
	if (enumerate == NULL) {
		fprintf(stderr, "Unable to enumerate devices");
		return -1;
	}

	udev_enumerate_add_match_subsystem(enumerate, "drm");
	udev_enumerate_scan_devices(enumerate);
	struct udev_list_entry *devices = udev_enumerate_get_list_entry(enumerate);
	if (devices == NULL) {
		fprintf(stderr, "Unable to enumerate devices");
		return -1;
	}

	// List devices
	struct udev_list_entry *dev_entry;
	udev_list_entry_foreach(dev_entry, devices) {
		const char *path = udev_list_entry_get_name(dev_entry);
		struct udev_device *dev = udev_device_new_from_syspath(udev, path);
		printf("%s [devtype=%s]\n", path, udev_device_get_devtype(dev));
	}
	udev_enumerate_unref(enumerate);
#endif

	// Setup monitor
	struct udev_monitor *monitor = udev_monitor_new_from_netlink(udev, "udev");
	if (monitor == NULL) {
		fprintf(stderr, "Unable to initialize udev monitor");
		return -1;
	}

	if (udev_monitor_filter_add_match_subsystem_devtype(monitor, "drm", "drm_minor") < 0) {
		fprintf(stderr, "Unable to setup udev monitor");
		return -1;
	}
	if (udev_monitor_filter_update(monitor) < 0) {
		fprintf(stderr, "Unable to setup udev monitor");
		return -1;
	}

	if (udev_monitor_enable_receiving(monitor) < 0) {
		fprintf(stderr, "Unable to listen in udev monitor");
		return -1;
	}

	// The same issue as in SO, receive_device does not block, use select
	// http://stackoverflow.com/questions/15687784/libudev-monitoring-returns-null-pointer-on-raspbian
	int fd = udev_monitor_get_fd(monitor);
	while(1) {
		fd_set fds;
		FD_ZERO(&fds);
		FD_SET(fd, &fds);
		int ret = select(fd+1, &fds, NULL, NULL, NULL);
		if (ret > 0 && FD_ISSET(fd, &fds)) {
			struct udev_device *dev = udev_monitor_receive_device(monitor);
			if (dev == NULL) {
				continue;
			}

			printf("%s\n", udev_device_get_syspath(dev));
			for (int i=1; i<argc; i++) {
				system(argv[i]);
			}
			udev_device_unref(dev);
		}
	}

	udev_monitor_unref(monitor);
	udev_unref(udev);
	return 0;
}
/*
 * Finds information about USB devices using operating system specific facilities and API.
 * The sequence of entries in array must match with what java layer expect (6 informations
 * per USB device). If a particular USB attribute is not set in descriptor or can not be
 * obtained "---" is placed in its place.
 *
 * Return array of USB device's information found, empty array if no USB device is found,
 * NULL if an error occurs (additionally throws exception).
 */
jobjectArray list_usb_devices(JNIEnv *env, jint vendor_to_match) {
	int x = 0;
	struct jstrarray_list list = {0};
	jstring usb_dev_info;
	jclass strClass = NULL;
	jobjectArray usbDevicesFound = NULL;

	struct udev *udev_ctx;
	struct udev_enumerate *enumerator;
	struct udev_list_entry *devices, *dev_list_entry;
	const char *sysattr_val;
	const char *path;
	struct udev_device *udev_device;
	char *endptr;

	init_jstrarraylist(&list, 100);

	/* libudev is reference counted. Memory is freed when counts reach to zero. */
	udev_ctx = udev_new();
	enumerator = udev_enumerate_new(udev_ctx);
	udev_enumerate_add_match_subsystem(enumerator, "usb");
	udev_enumerate_scan_devices(enumerator);
	devices = udev_enumerate_get_list_entry(enumerator);

	udev_list_entry_foreach(dev_list_entry, devices) {
		path = udev_list_entry_get_name(dev_list_entry);
		udev_device = udev_device_new_from_syspath(udev_enumerate_get_udev(enumerator), path);
		if(udev_device == NULL) {
			continue;
		}

		if(strcmp("usb_device", udev_device_get_devtype(udev_device)) == 0) {
			/* USB-IF vendor ID */
			sysattr_val = udev_device_get_sysattr_value(udev_device, "idVendor");
			if(sysattr_val != NULL) {
				if(vendor_to_match != 0) {
					/* we need to apply filter for identify specific vendor */
					if(vendor_to_match != (0x0000FFFF & (int)strtol(sysattr_val, &endptr, 16))) {
						udev_device_unref(udev_device);
						continue;
					}
				}
				usb_dev_info = (*env)->NewStringUTF(env, sysattr_val);
			}else {
				usb_dev_info = (*env)->NewStringUTF(env, "---");
			}
			if((usb_dev_info == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
				return linux_listusb_clean_throw_exp(env, 1, NULL, &list, udev_device, enumerator, udev_ctx);
			}
			insert_jstrarraylist(&list, usb_dev_info);

			/* USB product ID */
			sysattr_val = udev_device_get_sysattr_value(udev_device, "idProduct");
			if(sysattr_val != NULL) {
				usb_dev_info = (*env)->NewStringUTF(env, sysattr_val);
			}else {
				usb_dev_info = (*env)->NewStringUTF(env, "---");
			}
			if((usb_dev_info == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
				return linux_listusb_clean_throw_exp(env, 1, NULL, &list, udev_device, enumerator, udev_ctx);
			}
			insert_jstrarraylist(&list, usb_dev_info);

			/* SERIAL NUMBER */
			sysattr_val = udev_device_get_sysattr_value(udev_device, "serial");
			if(sysattr_val != NULL) {
				usb_dev_info = (*env)->NewStringUTF(env, sysattr_val);
			}else {
				usb_dev_info = (*env)->NewStringUTF(env, "---");
			}
			if((usb_dev_info == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
				return linux_listusb_clean_throw_exp(env, 1, NULL, &list, udev_device, enumerator, udev_ctx);
			}
			insert_jstrarraylist(&list, usb_dev_info);

			/* PRODUCT */
			sysattr_val = udev_device_get_sysattr_value(udev_device, "product");
			if(sysattr_val != NULL) {
				usb_dev_info = (*env)->NewStringUTF(env, sysattr_val);
			}else {
				usb_dev_info = (*env)->NewStringUTF(env, "---");
			}
			if((usb_dev_info == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
				return linux_listusb_clean_throw_exp(env, 1, NULL, &list, udev_device, enumerator, udev_ctx);
			}
			insert_jstrarraylist(&list, usb_dev_info);

			/* MANUFACTURER */
			sysattr_val = udev_device_get_sysattr_value(udev_device, "manufacturer");
			if(sysattr_val != NULL) {
				usb_dev_info = (*env)->NewStringUTF(env, sysattr_val);
			}else {
				usb_dev_info = (*env)->NewStringUTF(env, "---");
			}
			if((usb_dev_info == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
				return linux_listusb_clean_throw_exp(env, 1, NULL, &list, udev_device, enumerator, udev_ctx);
			}
			insert_jstrarraylist(&list, usb_dev_info);

			/* LOCATION (constructed) TODO*/
			sysattr_val = udev_device_get_sysattr_value(udev_device, "busnum");
			if(sysattr_val != NULL) {
				usb_dev_info = (*env)->NewStringUTF(env, sysattr_val);
			}else {
				usb_dev_info = (*env)->NewStringUTF(env, "---");
			}
			if((usb_dev_info == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
				return linux_listusb_clean_throw_exp(env, 1, NULL, &list, udev_device, enumerator, udev_ctx);
			}
			insert_jstrarraylist(&list, usb_dev_info);

		}
		udev_device_unref(udev_device);
	}
/*
 * A unique USB identification is generated like this:
 *
 * 1.) Get the USB device type from InterfaceClass and InterfaceSubClass
 * 2.) If the device type is 'Mass-Storage/SPC-2' or 'Mass-Storage/RBC',
 *     use the SCSI vendor and model as USB-Vendor and USB-model.
 * 3.) Otherwise, use the USB manufacturer and product as
 *     USB-Vendor and USB-model. Any non-printable characters
 *     in those strings will be skipped; a slash '/' will be converted
 *     into a full stop '.'.
 * 4.) If that fails, too, we will use idVendor and idProduct
 *     as USB-Vendor and USB-model.
 * 5.) The USB identification is the USB-vendor and USB-model
 *     string concatenated with an underscore '_'.
 * 6.) If the device supplies a serial number, this number
 *     is concatenated with the identification with an underscore '_'.
 */
static int builtin_usb_id(struct udev_device *dev, int argc, char *argv[], bool test) {
        char vendor_str[64];
        char vendor_str_enc[256];
        const char *vendor_id;
        char model_str[64];
        char model_str_enc[256];
        const char *product_id;
        char serial_str[UTIL_NAME_SIZE];
        char packed_if_str[UTIL_NAME_SIZE];
        char revision_str[64];
        char type_str[64];
        char instance_str[64];
        const char *ifnum = NULL;
        const char *driver = NULL;
        char serial[256];

        struct udev_device *dev_interface = NULL;
        struct udev_device *dev_usb = NULL;
        const char *if_class, *if_subclass;
        int if_class_num;
        int protocol = 0;
        size_t l;
        char *s;

        vendor_str[0] = '\0';
        model_str[0] = '\0';
        serial_str[0] = '\0';
        packed_if_str[0] = '\0';
        revision_str[0] = '\0';
        type_str[0] = '\0';
        instance_str[0] = '\0';

        /* shortcut, if we are called directly for a "usb_device" type */
        if (udev_device_get_devtype(dev) != NULL && streq(udev_device_get_devtype(dev), "usb_device")) {
                dev_if_packed_info(dev, packed_if_str, sizeof(packed_if_str));
                dev_usb = dev;
                goto fallback;
        }

        /* usb interface directory */
        dev_interface = udev_device_get_parent_with_subsystem_devtype(dev, "usb", "usb_interface");
        if (dev_interface == NULL) {
                log_debug("unable to access usb_interface device of '%s'",
                     udev_device_get_syspath(dev));
                return EXIT_FAILURE;
        }

        ifnum = udev_device_get_sysattr_value(dev_interface, "bInterfaceNumber");
        driver = udev_device_get_sysattr_value(dev_interface, "driver");

        if_class = udev_device_get_sysattr_value(dev_interface, "bInterfaceClass");
        if (!if_class) {
                log_debug("%s: cannot get bInterfaceClass attribute",
                     udev_device_get_sysname(dev));
                return EXIT_FAILURE;
        }

        if_class_num = strtoul(if_class, NULL, 16);
        if (if_class_num == 8) {
                /* mass storage */
                if_subclass = udev_device_get_sysattr_value(dev_interface, "bInterfaceSubClass");
                if (if_subclass != NULL)
                        protocol = set_usb_mass_storage_ifsubtype(type_str, if_subclass, sizeof(type_str)-1);
        } else {
                set_usb_iftype(type_str, if_class_num, sizeof(type_str)-1);
        }

        log_debug("%s: if_class %d protocol %d",
             udev_device_get_syspath(dev_interface), if_class_num, protocol);

        /* usb device directory */
        dev_usb = udev_device_get_parent_with_subsystem_devtype(dev_interface, "usb", "usb_device");
        if (!dev_usb) {
                log_debug("unable to find parent 'usb' device of '%s'",
                     udev_device_get_syspath(dev));
                return EXIT_FAILURE;
        }

        /* all interfaces of the device in a single string */
        dev_if_packed_info(dev_usb, packed_if_str, sizeof(packed_if_str));

        /* mass storage : SCSI or ATAPI */
        if ((protocol == 6 || protocol == 2)) {
                struct udev_device *dev_scsi;
                const char *scsi_model, *scsi_vendor, *scsi_type, *scsi_rev;
                int host, bus, target, lun;

                /* get scsi device */
                dev_scsi = udev_device_get_parent_with_subsystem_devtype(dev, "scsi", "scsi_device");
                if (dev_scsi == NULL) {
                        log_debug("unable to find parent 'scsi' device of '%s'",
                             udev_device_get_syspath(dev));
                        goto fallback;
                }
                if (sscanf(udev_device_get_sysname(dev_scsi), "%d:%d:%d:%d", &host, &bus, &target, &lun) != 4) {
                        log_debug("invalid scsi device '%s'", udev_device_get_sysname(dev_scsi));
                        goto fallback;
                }

                /* Generic SPC-2 device */
                scsi_vendor = udev_device_get_sysattr_value(dev_scsi, "vendor");
                if (!scsi_vendor) {
                        log_debug("%s: cannot get SCSI vendor attribute",
                             udev_device_get_sysname(dev_scsi));
                        goto fallback;
                }
                udev_util_encode_string(scsi_vendor, vendor_str_enc, sizeof(vendor_str_enc));
                util_replace_whitespace(scsi_vendor, vendor_str, sizeof(vendor_str)-1);
                util_replace_chars(vendor_str, NULL);

                scsi_model = udev_device_get_sysattr_value(dev_scsi, "model");
                if (!scsi_model) {
                        log_debug("%s: cannot get SCSI model attribute",
                             udev_device_get_sysname(dev_scsi));
                        goto fallback;
                }
                udev_util_encode_string(scsi_model, model_str_enc, sizeof(model_str_enc));
                util_replace_whitespace(scsi_model, model_str, sizeof(model_str)-1);
                util_replace_chars(model_str, NULL);

                scsi_type = udev_device_get_sysattr_value(dev_scsi, "type");
                if (!scsi_type) {
                        log_debug("%s: cannot get SCSI type attribute",
                             udev_device_get_sysname(dev_scsi));
                        goto fallback;
                }
                set_scsi_type(type_str, scsi_type, sizeof(type_str)-1);

                scsi_rev = udev_device_get_sysattr_value(dev_scsi, "rev");
                if (!scsi_rev) {
                        log_debug("%s: cannot get SCSI revision attribute",
                             udev_device_get_sysname(dev_scsi));
                        goto fallback;
                }
                util_replace_whitespace(scsi_rev, revision_str, sizeof(revision_str)-1);
                util_replace_chars(revision_str, NULL);

                /*
                 * some broken devices have the same identifiers
                 * for all luns, export the target:lun number
                 */
                sprintf(instance_str, "%d:%d", target, lun);
        }

fallback:
        vendor_id = udev_device_get_sysattr_value(dev_usb, "idVendor");
        product_id = udev_device_get_sysattr_value(dev_usb, "idProduct");

        /* fallback to USB vendor & device */
        if (vendor_str[0] == '\0') {
                const char *usb_vendor = NULL;

                usb_vendor = udev_device_get_sysattr_value(dev_usb, "manufacturer");
                if (!usb_vendor)
                        usb_vendor = vendor_id;
                if (!usb_vendor) {
                        log_debug("No USB vendor information available");
                        return EXIT_FAILURE;
                }
                udev_util_encode_string(usb_vendor, vendor_str_enc, sizeof(vendor_str_enc));
                util_replace_whitespace(usb_vendor, vendor_str, sizeof(vendor_str)-1);
                util_replace_chars(vendor_str, NULL);
        }

        if (model_str[0] == '\0') {
                const char *usb_model = NULL;

                usb_model = udev_device_get_sysattr_value(dev_usb, "product");
                if (!usb_model)
                        usb_model = product_id;
                if (!usb_model)
                        return EXIT_FAILURE;
                udev_util_encode_string(usb_model, model_str_enc, sizeof(model_str_enc));
                util_replace_whitespace(usb_model, model_str, sizeof(model_str)-1);
                util_replace_chars(model_str, NULL);
        }

        if (revision_str[0] == '\0') {
                const char *usb_rev;

                usb_rev = udev_device_get_sysattr_value(dev_usb, "bcdDevice");
                if (usb_rev) {
                        util_replace_whitespace(usb_rev, revision_str, sizeof(revision_str)-1);
                        util_replace_chars(revision_str, NULL);
                }
        }

        if (serial_str[0] == '\0') {
                const char *usb_serial;

                usb_serial = udev_device_get_sysattr_value(dev_usb, "serial");
                if (usb_serial) {
                        const unsigned char *p;

                        /* http://msdn.microsoft.com/en-us/library/windows/hardware/gg487321.aspx */
                        for (p = (unsigned char *)usb_serial; *p != '\0'; p++)
                                if (*p < 0x20 || *p > 0x7f || *p == ',') {
                                        usb_serial = NULL;
                                        break;
                                }
                }

                if (usb_serial) {
                        util_replace_whitespace(usb_serial, serial_str, sizeof(serial_str)-1);
                        util_replace_chars(serial_str, NULL);
                }
        }

        s = serial;
        l = strpcpyl(&s, sizeof(serial), vendor_str, "_", model_str, NULL);
        if (serial_str[0] != '\0')
                l = strpcpyl(&s, l, "_", serial_str, NULL);

        if (instance_str[0] != '\0')
                strpcpyl(&s, l, "-", instance_str, NULL);

        udev_builtin_add_property(dev, test, "ID_VENDOR", vendor_str);
        udev_builtin_add_property(dev, test, "ID_VENDOR_ENC", vendor_str_enc);
        udev_builtin_add_property(dev, test, "ID_VENDOR_ID", vendor_id);
        udev_builtin_add_property(dev, test, "ID_MODEL", model_str);
        udev_builtin_add_property(dev, test, "ID_MODEL_ENC", model_str_enc);
        udev_builtin_add_property(dev, test, "ID_MODEL_ID", product_id);
        udev_builtin_add_property(dev, test, "ID_REVISION", revision_str);
        udev_builtin_add_property(dev, test, "ID_SERIAL", serial);
        if (serial_str[0] != '\0')
                udev_builtin_add_property(dev, test, "ID_SERIAL_SHORT", serial_str);
        if (type_str[0] != '\0')
                udev_builtin_add_property(dev, test, "ID_TYPE", type_str);
        if (instance_str[0] != '\0')
                udev_builtin_add_property(dev, test, "ID_INSTANCE", instance_str);
        udev_builtin_add_property(dev, test, "ID_BUS", "usb");
        if (packed_if_str[0] != '\0')
                udev_builtin_add_property(dev, test, "ID_USB_INTERFACES", packed_if_str);
        if (ifnum != NULL)
                udev_builtin_add_property(dev, test, "ID_USB_INTERFACE_NUM", ifnum);
        if (driver != NULL)
                udev_builtin_add_property(dev, test, "ID_USB_DRIVER", driver);
        return EXIT_SUCCESS;
}
Example #26
0
File: usb.c Project: seec/TL866
void *notifier_function()
{

    struct udev *udev;
    struct udev_monitor *mon;
    struct udev_device *dev;
    cancel = FALSE;
    const GUID guid = {0x85980D83,0x32B9,0x4BA1,{0x8F,0xDF,0x12,0xA7,0x11,0xB9,0x9C,0xA2}};
    DEV_BROADCAST_DEVICEINTERFACE_W DevBi;
    DevBi.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE_W);
    DevBi.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
    DevBi.dbcc_classguid = guid;

    udev = udev_new();
    if (!udev) {
        printf("Can't create udev\n");
        return;
    }


    mon = udev_monitor_new_from_netlink(udev, "udev");
    if(!mon)
    {
        printf("NetLink not available!\n");
        return;
    }
    int count = get_device_count();
    if(count == -1)
    {
        printf("udev error.\n");
        return;
    }

    udev_monitor_filter_add_match_subsystem_devtype(mon, "usb", NULL);
    udev_monitor_enable_receiving(mon);
    int fd = udev_monitor_get_fd(mon);

    while (!cancel) {
        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);
        if (ret > 0 && FD_ISSET(fd, &fds)) {

            dev = udev_monitor_receive_device(mon);
            if(dev && !strcmp(udev_device_get_devtype(dev),"usb_device")){
                int count_new;
                if(!strcmp(udev_device_get_action(dev), "add"))
                {
                    count_new = get_device_count();
                    if(count != count_new)
                    {
                        count = count_new;
                        //printf("device added.\n");
                        close_devices();
                        usleep(100000);
                        SendMessageW(hWnd, WM_DEVICECHANGE, DBT_DEVICEARRIVAL, (LPARAM)&DevBi);
                        RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE);
                    }

                }
                else if(!strcmp(udev_device_get_action(dev), "remove"))
                {
                    count_new = get_device_count();
                    if(count != count_new)
                    {
                        count = count_new;
                        //printf("device removed.\n");
                        close_devices();
                        usleep(100000);
                        SendMessageW(hWnd, WM_DEVICECHANGE, DBT_DEVICEREMOVECOMPLETE, (LPARAM)&DevBi);
                        RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE);
                    }
                }
                udev_device_unref(dev);
            }
        }
        usleep(10000);
    }
}
Example #27
0
const char* UdevDevice::getType(void)
	{
	return udev_device_get_devtype(device);
	}
Example #28
0
int main (void) {
	struct udev *udev;
	struct udev_enumerate *enumerate;
	struct udev_list_entry *devices, *dev_list_entry;
	struct udev_device *dev;
	struct udev_device *dev2;
   	struct udev_monitor *mon;
	int fd;
	udev = udev_new();
	if (!udev) {
		printf("Can't create udev\n");
		exit(1);
	}
	mon = udev_monitor_new_from_netlink(udev, "udev");
	udev_monitor_filter_add_match_subsystem_devtype(mon, "tty", NULL);
	udev_monitor_enable_receiving(mon);
	fd = udev_monitor_get_fd(mon);
	enumerate = udev_enumerate_new(udev);
	udev_enumerate_add_match_subsystem(enumerate, "tty");
	udev_enumerate_scan_devices(enumerate);
	devices = udev_enumerate_get_list_entry(enumerate);
	udev_list_entry_foreach(dev_list_entry, devices) {
		const char *path;
		path = udev_list_entry_get_name(dev_list_entry);
		dev = udev_device_new_from_syspath(udev, path);
		dev2 = udev_device_get_parent_with_subsystem_devtype(dev, "usb", "usb_device");
		if (dev2) {
			printf("Device Node Path: %s\n", udev_device_get_devnode(dev));
			printf("  VID/PID: %s %s\n", udev_device_get_sysattr_value(dev2,"idVendor"), udev_device_get_sysattr_value(dev, "idProduct"));
			printf("  %s\n  %s\n", udev_device_get_sysattr_value(dev2,"manufacturer"), udev_device_get_sysattr_value(dev2,"product"));
			printf("  serial: %s\n", udev_device_get_sysattr_value(dev2, "serial"));
			udev_device_unref(dev2);
		}
	}
	udev_enumerate_unref(enumerate);
	

	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);
		
		/* 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("   Action: %s\n", udev_device_get_action(dev));
				udev_device_unref(dev);
			}
			else {
				printf("No Device from receive_device(). An error occured.\n");
			}					
		}
		usleep(250*1000);
		printf(".");
		fflush(stdout);
	}


	udev_unref(udev);

	return 0;       
}
Example #29
0
static int enumerate_partitions(dev_t devnum) {

        _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
        _cleanup_udev_device_unref_ struct udev_device *d = NULL;
        _cleanup_blkid_free_probe_ blkid_probe b = NULL;
        _cleanup_udev_unref_ struct udev *udev = NULL;
        _cleanup_free_ char *boot = NULL, *home = NULL, *srv = NULL;
        struct udev_list_entry *first, *item;
        struct udev_device *parent = NULL;
        const char *name, *node, *pttype, *devtype;
        int boot_nr = -1, home_nr = -1, srv_nr = -1;
        bool home_rw = true, srv_rw = true;
        blkid_partlist pl;
        int r, k;
        dev_t pn;

        udev = udev_new();
        if (!udev)
                return log_oom();

        d = udev_device_new_from_devnum(udev, 'b', devnum);
        if (!d)
                return log_oom();

        name = udev_device_get_devnode(d);
        if (!name)
                name = udev_device_get_syspath(d);
        if (!name) {
                log_debug("Device %u:%u does not have a name, ignoring.",
                          major(devnum), minor(devnum));
                return 0;
        }

        parent = udev_device_get_parent(d);
        if (!parent) {
                log_debug("%s: not a partitioned device, ignoring.", name);
                return 0;
        }

        /* Does it have a devtype? */
        devtype = udev_device_get_devtype(parent);
        if (!devtype) {
                log_debug("%s: parent doesn't have a device type, ignoring.", name);
                return 0;
        }

        /* Is this a disk or a partition? We only care for disks... */
        if (!streq(devtype, "disk")) {
                log_debug("%s: parent isn't a raw disk, ignoring.", name);
                return 0;
        }

        /* Does it have a device node? */
        node = udev_device_get_devnode(parent);
        if (!node) {
                log_debug("%s: parent device does not have device node, ignoring.", name);
                return 0;
        }

        log_debug("%s: root device %s.", name, node);

        pn = udev_device_get_devnum(parent);
        if (major(pn) == 0)
                return 0;

        errno = 0;
        b = blkid_new_probe_from_filename(node);
        if (!b) {
                if (errno == 0)
                        return log_oom();

                return log_error_errno(errno, "%s: failed to allocate prober: %m", node);
        }

        blkid_probe_enable_partitions(b, 1);
        blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS);

        errno = 0;
        r = blkid_do_safeprobe(b);
        if (r == 1)
                return 0; /* no results */
        else if (r == -2) {
                log_warning("%s: probe gave ambiguous results, ignoring", node);
                return 0;
        } else if (r != 0)
                return log_error_errno(errno ?: EIO, "%s: failed to probe: %m", node);

        errno = 0;
        r = blkid_probe_lookup_value(b, "PTTYPE", &pttype, NULL);
        if (r != 0)
                return log_error_errno(errno ?: EIO,
                                       "%s: failed to determine partition table type: %m", node);

        /* We only do this all for GPT... */
        if (!streq_ptr(pttype, "gpt")) {
                log_debug("%s: not a GPT partition table, ignoring.", node);
                return 0;
        }

        errno = 0;
        pl = blkid_probe_get_partitions(b);
        if (!pl) {
                if (errno == 0)
                        return log_oom();

                return log_error_errno(errno, "%s: failed to list partitions: %m", node);
        }

        e = udev_enumerate_new(udev);
        if (!e)
                return log_oom();

        r = udev_enumerate_add_match_parent(e, parent);
        if (r < 0)
                return log_oom();

        r = udev_enumerate_add_match_subsystem(e, "block");
        if (r < 0)
                return log_oom();

        r = udev_enumerate_scan_devices(e);
        if (r < 0)
                return log_error_errno(r, "%s: failed to enumerate partitions: %m", node);

        first = udev_enumerate_get_list_entry(e);
        udev_list_entry_foreach(item, first) {
                _cleanup_udev_device_unref_ struct udev_device *q;
                unsigned long long flags;
                const char *stype, *subnode;
                sd_id128_t type_id;
                blkid_partition pp;
                dev_t qn;
                int nr;

                q = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
                if (!q)
                        continue;

                qn = udev_device_get_devnum(q);
                if (major(qn) == 0)
                        continue;

                if (qn == devnum)
                        continue;

                if (qn == pn)
                        continue;

                subnode = udev_device_get_devnode(q);
                if (!subnode)
                        continue;

                pp = blkid_partlist_devno_to_partition(pl, qn);
                if (!pp)
                        continue;

                nr = blkid_partition_get_partno(pp);
                if (nr < 0)
                        continue;

                stype = blkid_partition_get_type_string(pp);
                if (!stype)
                        continue;

                if (sd_id128_from_string(stype, &type_id) < 0)
                        continue;

                flags = blkid_partition_get_flags(pp);

                if (sd_id128_equal(type_id, GPT_SWAP)) {

                        if (flags & GPT_FLAG_NO_AUTO)
                                continue;

                        if (flags & GPT_FLAG_READ_ONLY) {
                                log_debug("%s marked as read-only swap partition, which is bogus. Ignoring.", subnode);
                                continue;
                        }

                        k = add_swap(subnode);
                        if (k < 0)
                                r = k;

                } else if (sd_id128_equal(type_id, GPT_ESP)) {

                        /* We only care for the first /boot partition */
                        if (boot && nr >= boot_nr)
                                continue;

                        /* Note that we do not honour the "no-auto"
                         * flag for the ESP, as it is often unset, to
                         * hide it from Windows. */

                        boot_nr = nr;

                        r = free_and_strdup(&boot, subnode);
                        if (r < 0)
                                return log_oom();

                } else if (sd_id128_equal(type_id, GPT_HOME)) {

                        if (flags & GPT_FLAG_NO_AUTO)
                                continue;

                        /* We only care for the first /home partition */
                        if (home && nr >= home_nr)
                                continue;

                        home_nr = nr;
                        home_rw = !(flags & GPT_FLAG_READ_ONLY),

                        r = free_and_strdup(&home, subnode);
                        if (r < 0)
                                return log_oom();

                } else if (sd_id128_equal(type_id, GPT_SRV)) {

                        if (flags & GPT_FLAG_NO_AUTO)
                                continue;

                        /* We only care for the first /srv partition */
                        if (srv && nr >= srv_nr)
                                continue;

                        srv_nr = nr;
                        srv_rw = !(flags & GPT_FLAG_READ_ONLY),

                        r = free_and_strdup(&srv, subnode);
                        if (r < 0)
                                return log_oom();
                }
        }
Example #30
0
int main(int argc, char *argv[])
{
	static const struct option options[] = {
		{ "help", no_argument, NULL, 'h' },
		{ "mode", required_argument, NULL, 'm' },
		{ "devpath", required_argument, NULL, 'p' },
		{ "method", required_argument, NULL, 'M' },
		{ }
	};
	enum method {
		METHOD_UNDEF,
		METHOD_CSR,
		METHOD_LOGITECH_HID,
		METHOD_DELL,
	} method = METHOD_UNDEF;
	struct udev *udev;
	struct udev_device *udev_dev = NULL;
	char syspath[PATH_MAX];
	int (*usb_switch)(int fd, enum mode mode) = NULL;
	enum mode mode = HCI;
	const char *devpath = NULL;
	int err = -1;
	int rc = 1;

	for (;;) {
		int option;

		option = getopt_long(argc, argv, "m:p:M:h", options, NULL);
		if (option == -1)
			break;

		switch (option) {
		case 'm':
			if (!strcmp(optarg, "hid")) {
				mode = HID;
			} else if (!strcmp(optarg, "hci")) {
				mode = HCI;
			} else {
				usage("error: undefined radio mode\n");
				exit(1);
			}
			break;
		case 'p':
			devpath = optarg;
			break;
		case 'M':
			if (!strcmp(optarg, "csr")) {
				method = METHOD_CSR;
				usb_switch = usb_switch_csr;
			} else if (!strcmp(optarg, "logitech-hid")) {
				method = METHOD_LOGITECH_HID;
			} else if (!strcmp(optarg, "dell")) {
				method = METHOD_DELL;
				usb_switch = usb_switch_dell;
			} else {
				usage("error: undefined switching method\n");
				exit(1);
			}
			break;
		case 'h':
			usage(NULL);
		}
	}

	if (!devpath || method == METHOD_UNDEF) {
		usage("error: --devpath= and --method= must be defined\n");
		exit(1);
	}

	udev = udev_new();
	if (udev == NULL)
		goto exit;

	snprintf(syspath, sizeof(syspath), "/sys/%s", devpath);
	udev_dev = udev_device_new_from_syspath(udev, syspath);
	if (udev_dev == NULL) {
		fprintf(stderr, "error: could not find '%s'\n", devpath);
		goto exit;
	}

	switch (method) {
	case METHOD_CSR:
	case METHOD_DELL: {
		struct udev_device *dev;
		int handle;
		const char *type;

		/* get the parent usb_device if needed */
		dev = udev_dev;
		type = udev_device_get_devtype(dev);
		if (type == NULL || strcmp(type, "usb_device") != 0) {
			dev = udev_device_get_parent_with_subsystem_devtype(dev,
							"usb", "usb_device");
			if (dev == NULL) {
				fprintf(stderr, "error: could not find usb_device for '%s'\n", devpath);
				goto exit;
			}
		}

		handle = find_device(dev);
		if (handle < 0) {
			fprintf(stderr, "error: unable to handle '%s'\n",
				udev_device_get_syspath(dev));
			goto exit;
		}
		err = usb_switch(handle, mode);
		close(handle);
		break;
	}
	case METHOD_LOGITECH_HID: {
		const char *device;

		device = udev_device_get_devnode(udev_dev);
		if (device == NULL) {
			fprintf(stderr, "error: could not find hiddev device node\n");
			goto exit;
		}
		err = hid_switch_logitech(device);
		break;
	}
	default:
		break;
	}

	if (err < 0)
		fprintf(stderr, "error: switching device '%s' failed.\n",
			udev_device_get_syspath(udev_dev));
exit:
	udev_device_unref(udev_dev);
	udev_unref(udev);
	return rc;
}