|
|
@@ -0,0 +1,119 @@
|
|
|
+
|
|
|
+#include <sys/types.h>
|
|
|
+#include <sys/stat.h>
|
|
|
+#include <fcntl.h>
|
|
|
+#include <unistd.h>
|
|
|
+#include <stdlib.h>
|
|
|
+#include <string.h>
|
|
|
+#include <stdio.h>
|
|
|
+#include <sys/types.h>
|
|
|
+#include <dirent.h>
|
|
|
+
|
|
|
+void errExit(const char *err)
|
|
|
+{
|
|
|
+ fprintf(stderr, "%s\n", err);
|
|
|
+ exit(1);
|
|
|
+}
|
|
|
+
|
|
|
+char *addDevice(const char *bus, const char *dev, const char *vmid)
|
|
|
+{
|
|
|
+ DIR *dirfd = opendir("/sys/bus/usb/devices/");
|
|
|
+
|
|
|
+ if (dirfd)
|
|
|
+ {
|
|
|
+ struct dirent *dirEntry;
|
|
|
+ char *devaddr = NULL;
|
|
|
+ char dirStartWith[32];
|
|
|
+ snprintf(dirStartWith, 32, "%s-", bus);
|
|
|
+
|
|
|
+ while (dirEntry = readdir(dirfd))
|
|
|
+ {
|
|
|
+ if (strncmp(dirStartWith, dirEntry->d_name, strlen(dirStartWith)))
|
|
|
+ continue;
|
|
|
+ char path[1024];
|
|
|
+ snprintf(path, 1024, "/sys/bus/usb/devices/%s/devnum", dirEntry->d_name);
|
|
|
+ int fic = open(path, O_RDONLY);
|
|
|
+ if (fic >= 0)
|
|
|
+ {
|
|
|
+ char devnum[32];
|
|
|
+ int rd = read(fic, devnum, 32);
|
|
|
+ close(fic);
|
|
|
+ if (rd)
|
|
|
+ devnum[rd -1] = 0;
|
|
|
+ printf("{cmp %s vs %s at %s}\n", devnum, dev, dirEntry->d_name);
|
|
|
+ if (!strcmp(devnum, dev))
|
|
|
+ {
|
|
|
+ devaddr = strdup(dirEntry->d_name +strlen(dirStartWith));
|
|
|
+ printf("Found device %s\n", dirEntry->d_name);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ closedir(dirfd);
|
|
|
+ if (devaddr)
|
|
|
+ {
|
|
|
+ char *res = malloc(sizeof(*res) * 1024);
|
|
|
+ snprintf(res, 1024, "echo device_add usb-host,hostbus=%s,hostport=%s,id=hubhotplug-%s-%s | qm monitor %s\n", bus, devaddr, bus, dev, vmid);
|
|
|
+ free(devaddr);
|
|
|
+ return res;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
+char *delDevice(const char *bus, const char *dev, const char *vmid)
|
|
|
+{
|
|
|
+ char *res = malloc(sizeof(*res) * 1024);
|
|
|
+ snprintf(res, 1024, "echo device_del hubhotplug-%s-%s | qm monitor %s\n", bus, dev, vmid);
|
|
|
+ return res;
|
|
|
+}
|
|
|
+
|
|
|
+int main(int ac, char **av)
|
|
|
+{
|
|
|
+ const char *vmid = av[1];
|
|
|
+ const char *devtypeStr = getenv("DEVTYPE");
|
|
|
+ const char *actionStr = getenv("ACTION");
|
|
|
+ const char *busNumStr = getenv("BUSNUM");
|
|
|
+ const char *devNumStr = getenv("DEVNUM");
|
|
|
+
|
|
|
+ if (!vmid)
|
|
|
+ {
|
|
|
+ fprintf(stderr, "Usage: %s VM-id\n", *av);
|
|
|
+ exit(1);
|
|
|
+ }
|
|
|
+ if (!devtypeStr)
|
|
|
+ errExit("Missing udev DEVTYPE");
|
|
|
+ if (!actionStr)
|
|
|
+ errExit("Missing udev ACTION");
|
|
|
+ if (!busNumStr)
|
|
|
+ errExit("Missing udev BUSNUM");
|
|
|
+ if (!devNumStr)
|
|
|
+ errExit("Missing udev DEVNUM");
|
|
|
+
|
|
|
+ if (strcmp(devtypeStr, "usb_device"))
|
|
|
+ errExit("Ignoring, devtype not matched");
|
|
|
+
|
|
|
+ while (*busNumStr == '0')
|
|
|
+ ++busNumStr;
|
|
|
+ while (*devNumStr == '0')
|
|
|
+ ++devNumStr;
|
|
|
+
|
|
|
+ char *action;
|
|
|
+ FILE *f = fopen("/tmp/log", "w+");
|
|
|
+ fprintf(f, "%s:%s\n", busNumStr, devNumStr);
|
|
|
+ if (!strcmp(actionStr, "add"))
|
|
|
+ action = addDevice(busNumStr, devNumStr, vmid);
|
|
|
+ else if (!strcmp(actionStr, "remove"))
|
|
|
+ action = delDevice(busNumStr, devNumStr, vmid);
|
|
|
+ else
|
|
|
+ errExit("Invalid ACTION");
|
|
|
+
|
|
|
+ if (action)
|
|
|
+ {
|
|
|
+ fprintf(f, ">>> %s\n", action);
|
|
|
+ system(action);
|
|
|
+ free(action);
|
|
|
+ }
|
|
|
+ fclose(f);
|
|
|
+}
|
|
|
+
|