| #include <sys/ioctl.h> | 
 | #include <sys/types.h> | 
 | #include <sys/stat.h> | 
 | #include <fcntl.h> | 
 | #include <stdio.h> | 
 | #include <errno.h> | 
 | #include <string.h> | 
 | #include <inttypes.h> | 
 | #include <unistd.h> | 
 |  | 
 | #include <linux/usbdevice_fs.h> | 
 |  | 
 | /* For building without an updated set of headers */ | 
 | #ifndef USBDEVFS_DROP_PRIVILEGES | 
 | #define USBDEVFS_DROP_PRIVILEGES		_IOW('U', 30, __u32) | 
 | #define USBDEVFS_CAP_DROP_PRIVILEGES		0x40 | 
 | #endif | 
 |  | 
 | void drop_privileges(int fd, uint32_t mask) | 
 | { | 
 | 	int res; | 
 |  | 
 | 	res = ioctl(fd, USBDEVFS_DROP_PRIVILEGES, &mask); | 
 | 	if (res) | 
 | 		printf("ERROR: USBDEVFS_DROP_PRIVILEGES returned %d\n", res); | 
 | 	else | 
 | 		printf("OK: privileges dropped!\n"); | 
 | } | 
 |  | 
 | void reset_device(int fd) | 
 | { | 
 | 	int res; | 
 |  | 
 | 	res = ioctl(fd, USBDEVFS_RESET); | 
 | 	if (!res) | 
 | 		printf("OK: USBDEVFS_RESET succeeded\n"); | 
 | 	else | 
 | 		printf("ERROR: reset failed! (%d - %s)\n", | 
 | 		       -res, strerror(-res)); | 
 | } | 
 |  | 
 | void claim_some_intf(int fd) | 
 | { | 
 | 	int i, res; | 
 |  | 
 | 	for (i = 0; i < 4; i++) { | 
 | 		res = ioctl(fd, USBDEVFS_CLAIMINTERFACE, &i); | 
 | 		if (!res) | 
 | 			printf("OK: claimed if %d\n", i); | 
 | 		else | 
 | 			printf("ERROR claiming if %d (%d - %s)\n", | 
 | 			       i, -res, strerror(-res)); | 
 | 	} | 
 | } | 
 |  | 
 | int main(int argc, char *argv[]) | 
 | { | 
 | 	uint32_t mask, caps; | 
 | 	int c, fd; | 
 |  | 
 | 	fd = open(argv[1], O_RDWR); | 
 | 	if (fd < 0) { | 
 | 		printf("Failed to open file\n"); | 
 | 		goto err_fd; | 
 | 	} | 
 |  | 
 | 	/* | 
 | 	 * check if dropping privileges is supported, | 
 | 	 * bail on systems where the capability is not present | 
 | 	 */ | 
 | 	ioctl(fd, USBDEVFS_GET_CAPABILITIES, &caps); | 
 | 	if (!(caps & USBDEVFS_CAP_DROP_PRIVILEGES)) { | 
 | 		printf("DROP_PRIVILEGES not supported\n"); | 
 | 		goto err; | 
 | 	} | 
 |  | 
 | 	/* | 
 | 	 * Drop privileges but keep the ability to claim all | 
 | 	 * free interfaces (i.e., those not used by kernel drivers) | 
 | 	 */ | 
 | 	drop_privileges(fd, -1U); | 
 |  | 
 | 	printf("Available options:\n" | 
 | 		"[0] Exit now\n" | 
 | 		"[1] Reset device. Should fail if device is in use\n" | 
 | 		"[2] Claim 4 interfaces. Should succeed where not in use\n" | 
 | 		"[3] Narrow interface permission mask\n" | 
 | 		"Which option shall I run?: "); | 
 |  | 
 | 	while (scanf("%d", &c) == 1) { | 
 | 		switch (c) { | 
 | 		case 0: | 
 | 			goto exit; | 
 | 		case 1: | 
 | 			reset_device(fd); | 
 | 			break; | 
 | 		case 2: | 
 | 			claim_some_intf(fd); | 
 | 			break; | 
 | 		case 3: | 
 | 			printf("Insert new mask: "); | 
 | 			scanf("%x", &mask); | 
 | 			drop_privileges(fd, mask); | 
 | 			break; | 
 | 		default: | 
 | 			printf("I don't recognize that\n"); | 
 | 		} | 
 |  | 
 | 		printf("Which test shall I run next?: "); | 
 | 	} | 
 |  | 
 | exit: | 
 | 	close(fd); | 
 | 	return 0; | 
 |  | 
 | err: | 
 | 	close(fd); | 
 | err_fd: | 
 | 	return 1; | 
 | } |