brintos

brintos / linux-shallow public Read only

0
0
Text · 2.8 KiB · 66a44d4 Raw
130 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>4 *               2005-2007 Takahiro Hirofuchi5 */6 7#include <libudev.h>8 9#include <errno.h>10#include <stdio.h>11#include <string.h>12 13#include <getopt.h>14 15#include "usbip_common.h"16#include "utils.h"17#include "usbip.h"18#include "sysfs_utils.h"19 20static const char usbip_unbind_usage_string[] =21	"usbip unbind <args>\n"22	"    -b, --busid=<busid>    Unbind " USBIP_HOST_DRV_NAME ".ko from "23	"device on <busid>\n";24 25void usbip_unbind_usage(void)26{27	printf("usage: %s", usbip_unbind_usage_string);28}29 30static int unbind_device(char *busid)31{32	char bus_type[] = "usb";33	int rc, ret = -1;34 35	char unbind_attr_name[] = "unbind";36	char unbind_attr_path[SYSFS_PATH_MAX];37	char rebind_attr_name[] = "rebind";38	char rebind_attr_path[SYSFS_PATH_MAX];39 40	struct udev *udev;41	struct udev_device *dev;42	const char *driver;43 44	/* Create libudev context. */45	udev = udev_new();46 47	/* Check whether the device with this bus ID exists. */48	dev = udev_device_new_from_subsystem_sysname(udev, "usb", busid);49	if (!dev) {50		err("device with the specified bus ID does not exist");51		goto err_close_udev;52	}53 54	/* Check whether the device is using usbip-host driver. */55	driver = udev_device_get_driver(dev);56	if (!driver || strcmp(driver, "usbip-host")) {57		err("device is not bound to usbip-host driver");58		goto err_close_udev;59	}60 61	/* Unbind device from driver. */62	snprintf(unbind_attr_path, sizeof(unbind_attr_path), "%s/%s/%s/%s/%s/%s",63		 SYSFS_MNT_PATH, SYSFS_BUS_NAME, bus_type, SYSFS_DRIVERS_NAME,64		 USBIP_HOST_DRV_NAME, unbind_attr_name);65 66	rc = write_sysfs_attribute(unbind_attr_path, busid, strlen(busid));67	if (rc < 0) {68		err("error unbinding device %s from driver", busid);69		goto err_close_udev;70	}71 72	/* Notify driver of unbind. */73	rc = modify_match_busid(busid, 0);74	if (rc < 0) {75		err("unable to unbind device on %s", busid);76		goto err_close_udev;77	}78 79	/* Trigger new probing. */80	snprintf(rebind_attr_path, sizeof(unbind_attr_path), "%s/%s/%s/%s/%s/%s",81			SYSFS_MNT_PATH, SYSFS_BUS_NAME, bus_type, SYSFS_DRIVERS_NAME,82			USBIP_HOST_DRV_NAME, rebind_attr_name);83 84	rc = write_sysfs_attribute(rebind_attr_path, busid, strlen(busid));85	if (rc < 0) {86		err("error rebinding");87		goto err_close_udev;88	}89 90	ret = 0;91	info("unbind device on busid %s: complete", busid);92 93err_close_udev:94	udev_device_unref(dev);95	udev_unref(udev);96 97	return ret;98}99 100int usbip_unbind(int argc, char *argv[])101{102	static const struct option opts[] = {103		{ "busid", required_argument, NULL, 'b' },104		{ NULL,    0,                 NULL,  0  }105	};106 107	int opt;108	int ret = -1;109 110	for (;;) {111		opt = getopt_long(argc, argv, "b:", opts, NULL);112 113		if (opt == -1)114			break;115 116		switch (opt) {117		case 'b':118			ret = unbind_device(optarg);119			goto out;120		default:121			goto err_out;122		}123	}124 125err_out:126	usbip_unbind_usage();127out:128	return ret;129}130