#include #include #include #include #include #include #include #include #include #define LOGFILE "/var/log/pve-hubhotplug.log" void errExit(const char *err) { fprintf(stderr, "%s\n", err); exit(1); } char *addDevice(const char *bus, const char *dev, const char *vmid, const char *parentHub, FILE *debug) { DIR *dirfd = opendir("/sys/bus/usb/devices/"); if (dirfd) { struct dirent *dirEntry; char *devaddr = NULL; char *hubMatch = NULL; if (parentHub) { const int len = strlen(parentHub) +1; hubMatch = malloc(sizeof(*hubMatch) * len); snprintf(hubMatch, len, "%s.", parentHub); } else { hubMatch = malloc(sizeof(*hubMatch) * 32); snprintf(hubMatch, 31, "%s-", bus); } while (dirEntry = readdir(dirfd)) { if (strncmp(hubMatch, dirEntry->d_name, strlen(hubMatch))) 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; if (!strcmp(devnum, dev)) { fprintf(debug, "Found device %s\n", dirEntry->d_name); devaddr = strdup(dirEntry->d_name +strlen(bus) +1); break; } } } closedir(dirfd); free(hubMatch); if (devaddr) { char *res = malloc(sizeof(*res) * 1024); snprintf(res, 1024, "echo device_add usb-host,bus=xhci.0,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 *parentHub = av[1] ? av[2] : NULL; 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 [parentBus-parentPort]\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(LOGFILE, "a"); if (!strcmp(actionStr, "add")) action = addDevice(busNumStr, devNumStr, vmid, parentHub, f); 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); }