Initial commit
This commit is contained in:
commit
97616b9600
|
@ -0,0 +1,57 @@
|
||||||
|
cmake_minimum_required (VERSION 2.8.5)
|
||||||
|
project (razer-bw-te-ctl C)
|
||||||
|
set (project_VERSION "1.0")
|
||||||
|
|
||||||
|
find_package (PkgConfig REQUIRED)
|
||||||
|
pkg_check_modules (dependencies REQUIRED libusb-1.0)
|
||||||
|
include_directories (${dependencies_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
include (GNUInstallDirs)
|
||||||
|
configure_file (${PROJECT_SOURCE_DIR}/config.h.in
|
||||||
|
${PROJECT_BINARY_DIR}/config.h)
|
||||||
|
include_directories (${PROJECT_BINARY_DIR})
|
||||||
|
|
||||||
|
add_executable (${PROJECT_NAME} ${PROJECT_NAME}.c)
|
||||||
|
target_link_libraries (${PROJECT_NAME} ${dependencies_LIBRARIES})
|
||||||
|
install (TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||||
|
|
||||||
|
find_program (HELP2MAN_EXECUTABLE help2man)
|
||||||
|
if (NOT HELP2MAN_EXECUTABLE)
|
||||||
|
message (FATAL_ERROR "help2man not found")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
foreach (page ${PROJECT_NAME})
|
||||||
|
set (page_output "${PROJECT_BINARY_DIR}/${page}.1")
|
||||||
|
list (APPEND project_MAN_PAGES "${page_output}")
|
||||||
|
add_custom_command (OUTPUT ${page_output}
|
||||||
|
COMMAND ${HELP2MAN_EXECUTABLE} -N
|
||||||
|
"${PROJECT_BINARY_DIR}/${page}" -o ${page_output}
|
||||||
|
DEPENDS ${PROJECT_NAME}
|
||||||
|
COMMENT "Generating man page for ${page}" VERBATIM)
|
||||||
|
endforeach ()
|
||||||
|
|
||||||
|
add_custom_target (docs ALL DEPENDS ${project_MAN_PAGES})
|
||||||
|
|
||||||
|
foreach (page ${project_MAN_PAGES})
|
||||||
|
string (REGEX MATCH "\\.([0-9])" manpage_suffix "${page}")
|
||||||
|
install (FILES "${page}"
|
||||||
|
DESTINATION "${CMAKE_INSTALL_MANDIR}/man${CMAKE_MATCH_1}")
|
||||||
|
endforeach ()
|
||||||
|
|
||||||
|
set (CPACK_PACKAGE_DESCRIPTION_SUMMARY
|
||||||
|
"Razer BlackWidow Tournament Edition control utility")
|
||||||
|
set (CPACK_PACKAGE_VERSION ${project_VERSION})
|
||||||
|
set (CPACK_PACKAGE_VENDOR "Premysl Janouch")
|
||||||
|
set (CPACK_PACKAGE_CONTACT "Přemysl Janouch <p.janouch@gmail.com>")
|
||||||
|
set (CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE")
|
||||||
|
|
||||||
|
set (CPACK_GENERATOR "TGZ;ZIP")
|
||||||
|
set (CPACK_PACKAGE_FILE_NAME
|
||||||
|
"${PROJECT_NAME}-${project_VERSION}-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}")
|
||||||
|
|
||||||
|
set (CPACK_SOURCE_GENERATOR "TGZ;ZIP")
|
||||||
|
set (CPACK_SOURCE_IGNORE_FILES "/\\\\.git;/build;/CMakeLists.txt.user")
|
||||||
|
set (CPACK_SOURCE_PACKAGE_FILE_NAME "${PROJECT_NAME}-${project_VERSION}")
|
||||||
|
|
||||||
|
set (CPACK_SET_DESTDIR TRUE)
|
||||||
|
include (CPack)
|
|
@ -0,0 +1,15 @@
|
||||||
|
Copyright (c) 2013, Přemysl Janouch <p.janouch@gmail.com>
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||||
|
SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||||
|
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
razer-bw-te-ctl
|
||||||
|
|
||||||
|
This program makes it possible to change the configuration of your Razer
|
||||||
|
BlackWidow Tournament Edition keybooard from within Linux, *BSD or any other
|
||||||
|
POSIX-compatible system supported by libusb.
|
||||||
|
|
||||||
|
Make sure to let the Windows Razer Synapse tool upgrade the firmware to the
|
||||||
|
newest version before running the program. There might be some issues otherwise
|
||||||
|
due to protocol changes, although I don't really deem it very probable.
|
||||||
|
|
||||||
|
Run `razer-bw-te-ctl --help' or `man razer-bw-te-ctl' for usage information.
|
||||||
|
|
||||||
|
Installation
|
||||||
|
============
|
||||||
|
Build dependencies: cmake >= 2.8.5, help2man, libusb >= 1.0
|
||||||
|
|
||||||
|
$ git clone git://github.com/pjanouch/razer-bw-te-ctl.git
|
||||||
|
$ cd razer-bw-te-ctl
|
||||||
|
$ mkdir build
|
||||||
|
$ cd build
|
||||||
|
$ cmake .. -DCMAKE_INSTALL_PREFIX=/usr
|
||||||
|
# make install
|
||||||
|
|
||||||
|
Note that there's no "make uninstall".
|
||||||
|
|
||||||
|
For Debian-based distros, you can do the following instead of the last step:
|
||||||
|
$ cpack -G DEB
|
||||||
|
# dpkg -i razer-bw-te-ctl-*.deb
|
|
@ -0,0 +1,7 @@
|
||||||
|
#ifndef CONFIG_H
|
||||||
|
#define CONFIG_H
|
||||||
|
|
||||||
|
#define PROJECT_NAME "${CMAKE_PROJECT_NAME}"
|
||||||
|
#define PROJECT_VERSION "${project_VERSION}"
|
||||||
|
|
||||||
|
#endif // ! CONFIG_H
|
|
@ -0,0 +1,427 @@
|
||||||
|
/*
|
||||||
|
* razer-bw-te-ctl.c: Razer BlackWidow Tournament Edition control utility
|
||||||
|
*
|
||||||
|
* Everything has been reverse-engineered via Wireshark/usbmon and VirtualBox.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Přemysl Janouch <p.janouch@gmail.com>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||||
|
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <libusb.h>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
// --- Utilities ---------------------------------------------------------------
|
||||||
|
|
||||||
|
/** Search for a device with given vendor and product ID. */
|
||||||
|
static libusb_device_handle *
|
||||||
|
find_device (int vendor, int product, int *error)
|
||||||
|
{
|
||||||
|
libusb_device **list;
|
||||||
|
libusb_device *found = NULL;
|
||||||
|
libusb_device_handle *handle = NULL;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
ssize_t cnt = libusb_get_device_list (NULL, &list);
|
||||||
|
if (cnt < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ssize_t i = 0;
|
||||||
|
for (i = 0; i < cnt; i++)
|
||||||
|
{
|
||||||
|
libusb_device *device = list[i];
|
||||||
|
|
||||||
|
struct libusb_device_descriptor desc;
|
||||||
|
if (libusb_get_device_descriptor (device, &desc))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (desc.idVendor == vendor && desc.idProduct == product)
|
||||||
|
{
|
||||||
|
found = device;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found)
|
||||||
|
{
|
||||||
|
err = libusb_open (found, &handle);
|
||||||
|
if (err)
|
||||||
|
goto out_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
out_free:
|
||||||
|
libusb_free_device_list(list, 1);
|
||||||
|
out:
|
||||||
|
if (error != NULL && err != 0)
|
||||||
|
*error = err;
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Device configuration ----------------------------------------------------
|
||||||
|
|
||||||
|
#define USB_VENDOR_RAZER 0x1532
|
||||||
|
#define USB_PRODUCT_RAZER_BW_TE 0x011c
|
||||||
|
|
||||||
|
#define USB_GET_REPORT 0x01
|
||||||
|
#define USB_SET_REPORT 0x09
|
||||||
|
|
||||||
|
#define BW_CTL_IFACE 0
|
||||||
|
|
||||||
|
/** Razer logo backlight mode. */
|
||||||
|
enum bw_led_mode
|
||||||
|
{
|
||||||
|
LED_BRIGHTNESS = 0,
|
||||||
|
LED_BLINK,
|
||||||
|
LED_PULSATE
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Overall device configuration. */
|
||||||
|
struct bw_config
|
||||||
|
{
|
||||||
|
enum bw_led_mode led_mode;
|
||||||
|
unsigned led_brightness;
|
||||||
|
unsigned macro_led_on : 1;
|
||||||
|
unsigned macro_led_blinking : 1;
|
||||||
|
unsigned gaming_mode : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Send a command to the mouse via SET_REPORT. */
|
||||||
|
static int
|
||||||
|
bw_send_command (libusb_device_handle *device,
|
||||||
|
unsigned char *data, uint16_t length)
|
||||||
|
{
|
||||||
|
unsigned char packet[90] = { 0x00 };
|
||||||
|
assert (length <= sizeof packet - 5);
|
||||||
|
memcpy (packet + 5, data, length);
|
||||||
|
|
||||||
|
unsigned char checksum = 0;
|
||||||
|
while (length--)
|
||||||
|
checksum ^= data[length];
|
||||||
|
packet[sizeof packet - 2] = checksum;
|
||||||
|
|
||||||
|
// XXX wIndex should actually be 0x0002 but that doesn't work
|
||||||
|
int result = libusb_control_transfer (device, LIBUSB_ENDPOINT_OUT
|
||||||
|
| LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE,
|
||||||
|
USB_SET_REPORT, 0x0300, 0x0000, packet, sizeof packet, 0);
|
||||||
|
return result < 0 ? result : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set Razer logo backlight mode. */
|
||||||
|
static int
|
||||||
|
bw_set_led_mode (libusb_device_handle *device, enum bw_led_mode mode)
|
||||||
|
{
|
||||||
|
unsigned char cmd[] = { 0x03, 0x03, 0x02, 0x01, 0x04, mode };
|
||||||
|
return bw_send_command (device, cmd, sizeof cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set Razer logo backlight brightness. */
|
||||||
|
static int
|
||||||
|
bw_set_led_brightness (libusb_device_handle *device, unsigned char brightness)
|
||||||
|
{
|
||||||
|
unsigned char cmd[] = { 0x03, 0x03, 0x03, 0x01, 0x04, brightness };
|
||||||
|
return bw_send_command (device, cmd, sizeof cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set the on/off state of the macro LED. */
|
||||||
|
static int
|
||||||
|
bw_set_macro_led (libusb_device_handle *device, bool on)
|
||||||
|
{
|
||||||
|
unsigned char cmd[] = { 0x03, 0x03, 0x00, 0x00, 0x07, on };
|
||||||
|
return bw_send_command (device, cmd, sizeof cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set whether the macro LED should blink. */
|
||||||
|
static int
|
||||||
|
bw_set_macro_led_blinking (libusb_device_handle *device, bool blinking)
|
||||||
|
{
|
||||||
|
unsigned char cmd[] = { 0x03, 0x03, 0x02, 0x00, 0x07, blinking };
|
||||||
|
return bw_send_command (device, cmd, sizeof cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set the gaming mode (whether the Windows key should be ignored). */
|
||||||
|
static int
|
||||||
|
bw_set_gaming_mode (libusb_device_handle *device, bool on)
|
||||||
|
{
|
||||||
|
unsigned char cmd[] = { 0x03, 0x03, 0x00, 0x01, 0x08, on };
|
||||||
|
return bw_send_command (device, cmd, sizeof cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Control utility ---------------------------------------------------------
|
||||||
|
|
||||||
|
struct options
|
||||||
|
{
|
||||||
|
unsigned set_led_mode : 1;
|
||||||
|
unsigned set_led_brightness : 1;
|
||||||
|
unsigned set_macro_led_on : 1;
|
||||||
|
unsigned set_macro_led_blinking : 1;
|
||||||
|
unsigned set_gaming_mode : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
show_usage (const char *program_name)
|
||||||
|
{
|
||||||
|
printf ("Usage: %s [OPTION]...\n", program_name);
|
||||||
|
printf ("Configure Razer BlackWidow Tournament Edition devices.\n\n");
|
||||||
|
printf (" -h, --help Show this help\n");
|
||||||
|
printf (" --version Show program version and exit\n");
|
||||||
|
printf (" --led-mode X Set the mode of the Razer logo LED"
|
||||||
|
" (can be 'normal', 'blink' or 'pulsate')\n");
|
||||||
|
printf (" --led-brightness X Set Razer logo LED brightness"
|
||||||
|
" (from 0 to 255)\n");
|
||||||
|
printf (" --macro-led X Set the macro LED mode"
|
||||||
|
" ('off', 'on' or 'blink')\n");
|
||||||
|
printf (" --gaming-mode BOOL Set whether the Windows key is ignored\n");
|
||||||
|
printf ("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
parse_options (int argc, char *argv[],
|
||||||
|
struct options *options, struct bw_config *new_config)
|
||||||
|
{
|
||||||
|
static struct option long_opts[] =
|
||||||
|
{
|
||||||
|
{ "help", no_argument, 0, 'h' },
|
||||||
|
{ "version", no_argument, 0, 'V' },
|
||||||
|
{ "led-mode", required_argument, 0, 'l' },
|
||||||
|
{ "led-brightness", required_argument, 0, 'L' },
|
||||||
|
{ "macro-led", required_argument, 0, 'm' },
|
||||||
|
{ "gaming-mode", required_argument, 0, 'g' },
|
||||||
|
{ 0, 0, 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
if (argc == 1)
|
||||||
|
{
|
||||||
|
show_usage (argv[0]);
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
int c;
|
||||||
|
while ((c = getopt_long (argc, argv, "h", long_opts, NULL)) != -1)
|
||||||
|
{
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case 'h':
|
||||||
|
show_usage (argv[0]);
|
||||||
|
exit (EXIT_SUCCESS);
|
||||||
|
case 'V':
|
||||||
|
printf (PROJECT_NAME " " PROJECT_VERSION "\n");
|
||||||
|
exit (EXIT_SUCCESS);
|
||||||
|
case 'l':
|
||||||
|
if (!strcasecmp (optarg, "normal"))
|
||||||
|
new_config->led_mode = LED_BRIGHTNESS;
|
||||||
|
else if (!strcasecmp (optarg, "blink"))
|
||||||
|
new_config->led_mode = LED_BLINK;
|
||||||
|
else if (!strcasecmp (optarg, "pulsate"))
|
||||||
|
new_config->led_mode = LED_PULSATE;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf (stderr, "Error: invalid LED mode: %s\n", optarg);
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
options->set_led_mode = true;
|
||||||
|
break;
|
||||||
|
case 'L':
|
||||||
|
{
|
||||||
|
char *end;
|
||||||
|
long bri = strtol (optarg, &end, 10);
|
||||||
|
if (!*optarg || *end || bri < 0 || bri > 255)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "Error: invalid LED brightness value\n");
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
options->set_led_brightness = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'm':
|
||||||
|
if (!strcasecmp (optarg, "off"))
|
||||||
|
{
|
||||||
|
new_config->macro_led_on = false;
|
||||||
|
new_config->macro_led_blinking = false;
|
||||||
|
}
|
||||||
|
else if (!strcasecmp (optarg, "blink"))
|
||||||
|
{
|
||||||
|
new_config->macro_led_on = true;
|
||||||
|
new_config->macro_led_blinking = true;
|
||||||
|
}
|
||||||
|
else if (!strcasecmp (optarg, "on"))
|
||||||
|
{
|
||||||
|
new_config->macro_led_on = true;
|
||||||
|
new_config->macro_led_blinking = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf (stderr, "Error: invalid macro LED mode: %s\n", optarg);
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
options->set_macro_led_blinking = true;
|
||||||
|
options->set_macro_led_on = true;
|
||||||
|
break;
|
||||||
|
case 'g':
|
||||||
|
if (!strcasecmp (optarg, "true")
|
||||||
|
|| !strcasecmp (optarg, "on")
|
||||||
|
|| !strcasecmp (optarg, "yes"))
|
||||||
|
new_config->gaming_mode = true;
|
||||||
|
else if (!strcasecmp (optarg, "false")
|
||||||
|
|| !strcasecmp (optarg, "off")
|
||||||
|
|| !strcasecmp (optarg, "no"))
|
||||||
|
new_config->gaming_mode = false;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf (stderr, "Error: invalid gaming mode"
|
||||||
|
" setting: %s\n", optarg);
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
options->set_gaming_mode = true;
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optind < argc)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "Error: extra parameters\n");
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
apply_options (libusb_device_handle *device,
|
||||||
|
struct options *options, struct bw_config *new_config)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if (options->set_led_mode)
|
||||||
|
if ((result = bw_set_led_mode
|
||||||
|
(device, new_config->led_mode)))
|
||||||
|
return result;
|
||||||
|
if (options->set_led_brightness)
|
||||||
|
if ((result = bw_set_led_brightness
|
||||||
|
(device, new_config->led_brightness)))
|
||||||
|
return result;
|
||||||
|
|
||||||
|
if (options->set_macro_led_on)
|
||||||
|
if ((result = bw_set_macro_led
|
||||||
|
(device, new_config->macro_led_on)))
|
||||||
|
return result;
|
||||||
|
if (options->set_macro_led_blinking)
|
||||||
|
if ((result = bw_set_macro_led_blinking
|
||||||
|
(device, new_config->macro_led_blinking)))
|
||||||
|
return result;
|
||||||
|
|
||||||
|
if (options->set_gaming_mode)
|
||||||
|
if ((result = bw_set_gaming_mode
|
||||||
|
(device, new_config->gaming_mode)))
|
||||||
|
return result;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ERROR(label, ...) \
|
||||||
|
do { \
|
||||||
|
fprintf (stderr, "Error: " __VA_ARGS__); \
|
||||||
|
status = 1; \
|
||||||
|
goto label; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
struct options options = { 0 };
|
||||||
|
struct bw_config new_config = { 0 };
|
||||||
|
|
||||||
|
parse_options (argc, argv, &options, &new_config);
|
||||||
|
|
||||||
|
int result, status = 0;
|
||||||
|
|
||||||
|
result = libusb_init (NULL);
|
||||||
|
if (result)
|
||||||
|
ERROR (error_0, "libusb initialisation failed: %s\n",
|
||||||
|
libusb_error_name (result));
|
||||||
|
|
||||||
|
result = 0;
|
||||||
|
libusb_device_handle *device = find_device
|
||||||
|
(USB_VENDOR_RAZER, USB_PRODUCT_RAZER_BW_TE, &result);
|
||||||
|
if (!device)
|
||||||
|
{
|
||||||
|
if (result)
|
||||||
|
ERROR (error_1, "couldn't open device: %s\n",
|
||||||
|
libusb_error_name (result));
|
||||||
|
else
|
||||||
|
ERROR (error_1, "no suitable device found\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool reattach_driver = false;
|
||||||
|
|
||||||
|
result = libusb_kernel_driver_active (device, BW_CTL_IFACE);
|
||||||
|
switch (result)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
case LIBUSB_ERROR_NOT_SUPPORTED:
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
reattach_driver = true;
|
||||||
|
result = libusb_detach_kernel_driver (device, BW_CTL_IFACE);
|
||||||
|
if (result)
|
||||||
|
ERROR (error_2, "couldn't detach kernel driver: %s\n",
|
||||||
|
libusb_error_name (result));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ERROR (error_2, "coudn't detect kernel driver presence: %s\n",
|
||||||
|
libusb_error_name (result));
|
||||||
|
}
|
||||||
|
|
||||||
|
result = libusb_claim_interface (device, BW_CTL_IFACE);
|
||||||
|
if (result)
|
||||||
|
ERROR (error_3, "couldn't claim interface: %s\n",
|
||||||
|
libusb_error_name (result));
|
||||||
|
|
||||||
|
result = apply_options (device, &options, &new_config);
|
||||||
|
if (result)
|
||||||
|
ERROR (error_4, "operation failed: %s\n",
|
||||||
|
libusb_error_name (result));
|
||||||
|
|
||||||
|
error_4:
|
||||||
|
result = libusb_release_interface (device, BW_CTL_IFACE);
|
||||||
|
if (result)
|
||||||
|
ERROR (error_3, "couldn't release interface: %s\n",
|
||||||
|
libusb_error_name (result));
|
||||||
|
|
||||||
|
error_3:
|
||||||
|
if (reattach_driver)
|
||||||
|
{
|
||||||
|
result = libusb_attach_kernel_driver (device, BW_CTL_IFACE);
|
||||||
|
if (result)
|
||||||
|
ERROR (error_2, "couldn't reattach kernel driver: %s\n",
|
||||||
|
libusb_error_name (result));
|
||||||
|
}
|
||||||
|
|
||||||
|
error_2:
|
||||||
|
libusb_close (device);
|
||||||
|
error_1:
|
||||||
|
libusb_exit (NULL);
|
||||||
|
error_0:
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue