82 lines
2.3 KiB
C
82 lines
2.3 KiB
C
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/ioctl.h>
|
|
#include <fcntl.h>
|
|
#include <linux/ioctl.h>
|
|
#include <linux/usbdevice_fs.h>
|
|
#include <libusb-1.0/libusb.h>
|
|
|
|
// Template for control messages, obtained through packet capture
|
|
unsigned char *CMD = "\xfd\x00\x16M\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
|
|
|
|
|
|
int main(int argc, char **argv) {
|
|
uint8_t cmd[64];
|
|
memcpy(cmd, CMD, 64);
|
|
struct usbdevfs_ioctl command;
|
|
libusb_context *ctx = NULL;
|
|
|
|
//
|
|
// Find and open the device
|
|
//
|
|
libusb_init(&ctx);
|
|
if (!ctx) {
|
|
perror("failed to initialize libusb");
|
|
return 1;
|
|
}
|
|
|
|
libusb_device_handle *devh = libusb_open_device_with_vid_pid(ctx, 0x0c2e, 0x0b07);
|
|
if (!devh) {
|
|
devh = libusb_open_device_with_vid_pid(ctx, 0x0c2e, 0x0b01);
|
|
if (!devh) {
|
|
perror("failed to open device");
|
|
return 1;
|
|
}
|
|
}
|
|
libusb_device *dev = libusb_get_device(devh);
|
|
if (!dev) {
|
|
perror("failed to get device info");
|
|
return 1;
|
|
}
|
|
|
|
//
|
|
// Disconnect usbhid driver from both device interfaces
|
|
//
|
|
char usbdevfs[32];
|
|
snprintf(usbdevfs, 32, "/dev/bus/usb/%03d/%03d", libusb_get_bus_number(dev), libusb_get_device_address(dev));
|
|
// usbdevfs/ioctl inspired from
|
|
// https://www.linuxquestions.org/questions/linux-hardware-18/how-to-unclaim-usb-device-558138/#post3406986
|
|
int fd = open(usbdevfs,O_RDWR);
|
|
if (fd < 1) {
|
|
perror("failed to open usbdevfs file");
|
|
return 1;
|
|
}
|
|
for (uint8_t i = 0; i < 2; ++i) {
|
|
command.ifno = i;
|
|
command.ioctl_code = USBDEVFS_DISCONNECT;
|
|
command.data = NULL;
|
|
int ret = ioctl(fd, USBDEVFS_IOCTL, &command);
|
|
if (ret < 0) {
|
|
perror("failed to unclaim USB interface from usbhid");
|
|
}
|
|
}
|
|
|
|
//
|
|
// Prepare and send a message on the control channel for each config argument
|
|
//
|
|
for (int i = 1; i < argc; ++i) {
|
|
memset(cmd+5, 0, 59);
|
|
cmd[1] = strlen(argv[i])+3;
|
|
memcpy(cmd+5, argv[i], strlen(argv[i]));
|
|
libusb_control_transfer(devh, 0x21, 0x09, 0x02fd, 1, cmd, 64, 0);
|
|
}
|
|
|
|
//
|
|
// Cleanup
|
|
//
|
|
libusb_release_interface(devh, 1);
|
|
libusb_close(devh);
|
|
libusb_exit(ctx);
|
|
}
|