diff --git a/include/logic/options.h b/include/logic/options.h index 9aca2af..e5f940a 100644 --- a/include/logic/options.h +++ b/include/logic/options.h @@ -24,45 +24,8 @@ #include #include -struct color { - uint8_t red; - uint8_t green; - uint8_t blue; -}; - -struct led_temperatures { - uint8_t temp1; - uint8_t temp2; - uint8_t temp3; -}; - -enum led_modes { - STATIC = 0, - BLINK = 1, - PULSE = 2, - SHIFT = 3, - RAINBOW = 4, - TEMPERATURE = 5, -}; - -struct temp_speed_pair { - /** temperature */ - int8_t temperature; - - /** fan speed PWM */ - int8_t speed; -}; - -enum motor_modes { - PWM = 0, - RPM = 1, - DEFAULT = 2, - QUIET = 3, - BALANCED = 4, - PERFORMANCE = 5, - CUSTOM = 6, - UNDEFINED = 7, -}; +#include "logic/support.h" +#include "logic/suboptions.h" struct option_flags { // flags @@ -73,47 +36,6 @@ struct option_flags { unsigned int set_pump : 1; }; -struct led_control { - uint8_t channel; - enum led_modes mode; - struct color led_colors[7]; - uint16_t temperatures[3]; - uint8_t speed; - uint8_t count; - uint8_t led_type; // commanderpro - uint8_t direction; // commanderpro - uint8_t change_style; // commanderpro -}; - -struct fan_control { - uint8_t channel; - enum motor_modes mode; - struct temp_speed_pair table[7]; - - // data returns - uint8_t fan_count; - uint8_t fan_type; - uint8_t temp_sensor_id; - uint16_t data; - uint16_t speed; - uint8_t speed_pwm; - uint16_t speed_rpm; - uint16_t max_speed; - char mode_string[64]; -}; - -struct pump_control { - uint8_t channel; - enum motor_modes mode; - struct temp_speed_pair table[6]; - - // data returns - uint16_t speed; - uint8_t speed_pwm; - uint16_t speed_rpm; - uint16_t max_speed; -}; - struct option_parse_return { struct led_control led_ctrl; struct fan_control fan_ctrl; @@ -177,66 +99,6 @@ static struct option long_options[] = { xx[6].green = 0x00; \ xx[6].blue = 0xff; -enum { - SUBOPTION_FAN_CHANNEL = 0, - SUBOPTION_FAN_MODE, - SUBOPTION_FAN_PWM, - SUBOPTION_FAN_RPM, - SUBOPTION_FAN_TEMPERATURES, - SUBOPTION_FAN_SPEEDS, - SUBOPTION_FAN_LIST_END, -}; - -enum { - SUBOPTION_LED_CHANNEL = 0, - SUBOPTION_LED_MODE, - SUBOPTION_LED_SPEED, - SUBOPTION_LED_COLORS, - SUBOPTION_LED_WARN, - SUBOPTION_LED_TEMPERATURES, - SUBOPTION_LED_LIST_END, -}; - -enum { - SUBOPTION_PUMP_MODE = 0, - SUBOPTION_PUMP_PWM, - SUBOPTION_PUMP_RPM, - SUBOPTION_PUMP_TEMPERATURES, - SUBOPTION_PUMP_SPEEDS, - SUBOPTION_PUMP_LIST_END, -}; - -static char *fan_options[] = {[SUBOPTION_FAN_CHANNEL] = "channel", - [SUBOPTION_FAN_MODE] = "mode", - [SUBOPTION_FAN_PWM] = "pwm", - [SUBOPTION_FAN_RPM] = "rpm", - [SUBOPTION_FAN_TEMPERATURES] = "temps", - [SUBOPTION_FAN_SPEEDS] = "speeds", - [SUBOPTION_FAN_LIST_END] = 0}; - -static char *led_options[] = {[SUBOPTION_LED_CHANNEL] = "channel", - [SUBOPTION_LED_MODE] = "mode", - [SUBOPTION_LED_SPEED] = "speed", - [SUBOPTION_LED_COLORS] = "colors", - [SUBOPTION_LED_WARN] = "warning_color", - [SUBOPTION_LED_TEMPERATURES] = "temps", - [SUBOPTION_LED_LIST_END] = 0}; - -static char *pump_options[] = {[SUBOPTION_PUMP_MODE] = "mode", - [SUBOPTION_PUMP_PWM] = "pwm", - [SUBOPTION_PUMP_RPM] = "rpm", - [SUBOPTION_PUMP_TEMPERATURES] = "temps", - [SUBOPTION_PUMP_SPEEDS] = "speeds", - [SUBOPTION_PUMP_LIST_END] = 0}; - -void fan_suboptions_parse(char *subopts, struct fan_control *settings); -void led_suboptions_parse(char *subopts, struct led_control *settings); -void pump_suboptions_parse(char *subopts, struct pump_control *settings); - -void fan_control_init(struct fan_control *settings); -void led_control_init(struct led_control *settings); -void pump_control_init(struct pump_control *settings); - void options_print(void); int options_parse(int argc, char **argv, struct option_flags *flags, diff --git a/include/logic/suboptions.h b/include/logic/suboptions.h new file mode 100644 index 0000000..42a1490 --- /dev/null +++ b/include/logic/suboptions.h @@ -0,0 +1,120 @@ +/* + * This file is part of OpenCorsairLink. + * Copyright (C) 2017-2019 Sean Nelson + + * OpenCorsairLink is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * any later version. + + * OpenCorsairLink is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with OpenCorsairLink. If not, see . + */ + +#ifndef _SUBOPTIONS_H +#define _SUBOPTIONS_H + +enum { + SUBOPTION_FAN_CHANNEL = 0, + SUBOPTION_FAN_MODE, + SUBOPTION_FAN_PWM, + SUBOPTION_FAN_RPM, + SUBOPTION_FAN_TEMPERATURES, + SUBOPTION_FAN_SPEEDS, + SUBOPTION_FAN_LIST_END, +}; + +enum { + SUBOPTION_LED_CHANNEL = 0, + SUBOPTION_LED_MODE, + SUBOPTION_LED_SPEED, + SUBOPTION_LED_COLORS, + SUBOPTION_LED_WARN, + SUBOPTION_LED_TEMPERATURES, + SUBOPTION_LED_LIST_END, +}; + +enum { + SUBOPTION_PUMP_MODE = 0, + SUBOPTION_PUMP_PWM, + SUBOPTION_PUMP_RPM, + SUBOPTION_PUMP_TEMPERATURES, + SUBOPTION_PUMP_SPEEDS, + SUBOPTION_PUMP_LIST_END, +}; + +struct led_control { + uint8_t channel; + enum led_modes mode; + struct color led_colors[7]; + uint16_t temperatures[3]; + uint8_t speed; + uint8_t count; +}; + +struct fan_control { + uint8_t channel; + enum motor_modes mode; + struct temp_speed_pair table[7]; + + // data returns + uint8_t fan_count; + uint8_t fan_type; + uint8_t temp_sensor_id; + uint16_t data; + uint16_t speed; + uint8_t speed_pwm; + uint16_t speed_rpm; + uint16_t max_speed; + char mode_string[64]; +}; + +struct pump_control { + uint8_t channel; + enum motor_modes mode; + struct temp_speed_pair table[6]; + + // data returns + uint16_t speed; + uint8_t speed_pwm; + uint16_t speed_rpm; + uint16_t max_speed; +}; + +static char *fan_options[] = {[SUBOPTION_FAN_CHANNEL] = "channel", + [SUBOPTION_FAN_MODE] = "mode", + [SUBOPTION_FAN_PWM] = "pwm", + [SUBOPTION_FAN_RPM] = "rpm", + [SUBOPTION_FAN_TEMPERATURES] = "temps", + [SUBOPTION_FAN_SPEEDS] = "speeds", + [SUBOPTION_FAN_LIST_END] = 0}; + +static char *led_options[] = {[SUBOPTION_LED_CHANNEL] = "channel", + [SUBOPTION_LED_MODE] = "mode", + [SUBOPTION_LED_SPEED] = "speed", + [SUBOPTION_LED_COLORS] = "colors", + [SUBOPTION_LED_WARN] = "warning_color", + [SUBOPTION_LED_TEMPERATURES] = "temps", + [SUBOPTION_LED_LIST_END] = 0}; + +static char *pump_options[] = {[SUBOPTION_PUMP_MODE] = "mode", + [SUBOPTION_PUMP_PWM] = "pwm", + [SUBOPTION_PUMP_RPM] = "rpm", + [SUBOPTION_PUMP_TEMPERATURES] = "temps", + [SUBOPTION_PUMP_SPEEDS] = "speeds", + [SUBOPTION_PUMP_LIST_END] = 0}; + +void fan_suboptions_parse(char *subopts, struct fan_control *settings); +void led_suboptions_parse(char *subopts, struct led_control *settings); +void pump_suboptions_parse(char *subopts, struct pump_control *settings); + +void fan_control_init(struct fan_control *settings); +void led_control_init(struct led_control *settings); +void pump_control_init(struct pump_control *settings); + +#endif diff --git a/include/logic/support.h b/include/logic/support.h new file mode 100644 index 0000000..c1ad558 --- /dev/null +++ b/include/logic/support.h @@ -0,0 +1,95 @@ +/* + * This file is part of OpenCorsairLink. + * Copyright (C) 2017-2019 Sean Nelson + + * OpenCorsairLink is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * any later version. + + * OpenCorsairLink is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with OpenCorsairLink. If not, see . + */ + +#ifndef _SUPPORT_H +#define _SUPPORT_H + +struct color { + uint8_t red; + uint8_t green; + uint8_t blue; +}; + +struct led_temperatures { + uint8_t temp1; + uint8_t temp2; + uint8_t temp3; +}; + +enum led_modes { + STATIC = 0, + BLINK = 1, + PULSE = 2, + SHIFT = 3, + RAINBOW = 4, + TEMPERATURE = 5, +}; + +struct temp_speed_pair { + /** temperature */ + int8_t temperature; + + /** fan speed PWM */ + int8_t speed; +}; + +enum motor_modes { + PWM = 0, + RPM = 1, + DEFAULT = 2, + QUIET = 3, + BALANCED = 4, + PERFORMANCE = 5, + CUSTOM = 6, + UNDEFINED = 7, +}; + +#define INIT_WARNING_LED(xx) \ + xx.red = 0xFF; \ + xx.green = 0x00; \ + xx.blue = 0x00; + +#define INIT_DEFAULT_LED(xx) \ + xx.red = 0xFF; \ + xx.green = 0xFF; \ + xx.blue = 0x00; + +#define INIT_RAINBOW_LED(xx) \ + xx[0].red = 0xff; \ + xx[0].green = 0x00; \ + xx[0].blue = 0x00; \ + xx[1].red = 0xff; \ + xx[1].green = 0x80; \ + xx[1].blue = 0x00; \ + xx[2].red = 0xff; \ + xx[2].green = 0xff; \ + xx[2].blue = 0x00; \ + xx[3].red = 0x00; \ + xx[3].green = 0xff; \ + xx[3].blue = 0x00; \ + xx[4].red = 0x00; \ + xx[4].green = 0x00; \ + xx[4].blue = 0xff; \ + xx[5].red = 0x4b; \ + xx[5].green = 0x00; \ + xx[5].blue = 0x82; \ + xx[6].red = 0x7f; \ + xx[6].green = 0x00; \ + xx[6].blue = 0xff; + +#endif diff --git a/logic/options.c b/logic/options.c index 6f3ad0c..10c05a7 100644 --- a/logic/options.c +++ b/logic/options.c @@ -16,7 +16,8 @@ * along with OpenCorsairLink. If not, see . */ -#include "common.h" +// #include "logic/support.h" +// #include "logic/suboptions.h" #include "logic/options.h" #include "logic/print.h" diff --git a/logic/scan.c b/logic/scan.c index 8fe494e..686408e 100644 --- a/logic/scan.c +++ b/logic/scan.c @@ -42,7 +42,13 @@ corsairlink_handle_close( struct libusb_device_handle* handle ) rr = libusb_release_interface( handle, 0 ); if ( rr < 0 ) { - msg_err("Unable to release USB interface\n"); + msg_err( "Encountered LibUSB Error: %s!\n", libusb_strerror( rr ) ); + } + + rr = libusb_attach_kernel_driver( handle, 0 ); + if ( rr < 0 ) + { + msg_err( "Encountered LibUSB Error: %s!\n", libusb_strerror( rr ) ); } libusb_close( handle ); @@ -53,17 +59,162 @@ corsairlink_handle_close( struct libusb_device_handle* handle ) int corsairlink_close( libusb_context* context ) { + int rr; int ii; for ( ii = 0; ii < scanlist_count; ii++ ) { - corsairlink_handle_close( scanlist[ii].handle ); + rr = corsairlink_handle_close( scanlist[ii].handle ); } libusb_exit( context ); return 0; } +int +corsairlink_check_device_id( struct corsair_device_info* cl_device ) +{ + int rr; + + /* get device_id if we have a proper device handle */ + uint16_t device_id = 0x00; + cl_device->driver->device_id( cl_device, scanlist[scanlist_count].handle, &device_id ); + + /* check to see if the device_id is the right one */ + if ( cl_device->device_id == device_id ) + { + /* if we have the right device id we can setup the rest + * of the device connections + */ + scanlist[scanlist_count].device = cl_device; + msg_info( "Dev=%d, CorsairLink Device Found: %s!\n", scanlist_count, cl_device->name ); + scanlist_count++; + return 1; // break; + + } + else + { + msg_debug( "No (device_id 0x%02X)\n", device_id ); + rr = corsairlink_handle_close( scanlist[scanlist_count].handle ); + return 2; // continue; + } +} + +int +corsairlink_device_setup( + libusb_device* device, + struct corsair_device_info* cl_device, + struct libusb_device_descriptor desc ) +{ + int rr; // This could be safely ignored. It is just a success flag for + // libusb functions. + + if ( ( cl_device->vendor_id == desc.idVendor ) + && ( cl_device->product_id == desc.idProduct ) ) + { + msg_debug( "Corsair product detected. Checking if device is %s... ", cl_device->name ); + rr = libusb_open( device, &scanlist[scanlist_count].handle ); + if ( rr < 0 ) + { + msg_err( "Encountered LibUSB Error: %s!\n", libusb_strerror( rr ) ); + return rr; + } + + rr = libusb_kernel_driver_active( scanlist[scanlist_count].handle, 0 ); + if (rr == 1) + { + msg_debug("Corsair Device has kernel driver attached\n"); + + rr = libusb_detach_kernel_driver( scanlist[scanlist_count].handle, 0 ); + if ( rr < 0 ) + { + msg_debug("Encountered LibUSB Error: %s!\n", libusb_strerror( rr ) ); + return rr; + } + else + { + msg_debug("Detached kernel driver from Corsair Device\n"); + } + + } + else if ( rr == 0 ) + { + msg_debug("Corsair Device has no kernel driver attached\n"); + } + else + { + msg_debug("Encountered LibUSB Error: %s!\n", libusb_strerror( rr ) ); + return rr; + } + + // libusb_reset_device() + // libusb_get_device() + // libusb_set_configuration() + + rr = libusb_claim_interface( scanlist[scanlist_count].handle, 0 ); + if ( rr < 0 ) + { + msg_debug("Encountered LibUSB Error: %s!\n", libusb_strerror( rr ) ); + return rr; + } + else + { + msg_debug("Claimed Interface on Corsair Device\n"); + } + + // libusb_set_interface_alt_setting + // libusb_get_device_descriptor + // libusb_get_bus_number + // libusb_get_device_address + // libusb_get_string_descriptor_ascii + + return corsairlink_check_device_id( cl_device ); + } + + return 0; +} + +int +corsairlink_device_enumerate( libusb_device* devices ) +{ + int rr; // This could be safely ignored. It is just a success flag for + // libusb functions. + int jj; // Loops through known CorsairLink Devices. + + if ( scanlist_count >= 10 ) + { + msg_debug( "Limited to 10 CorsairLink devices\n" ); + return 1; // break; + } + + struct libusb_device_descriptor desc; + rr = libusb_get_device_descriptor( devices, &desc ); + if ( rr < 0 ) + { + msg_err( "Encountered LibUSB Error: %s!\n", libusb_strerror( rr ) ); + return rr; + } + + // msg_debug( "Checking USB device %d (%04x:%04x)...\n", ii, desc.idVendor, desc.idProduct ); + msg_debug( "Checking USB device (%04x:%04x)...\n", desc.idVendor, desc.idProduct ); + + for ( jj = 0; jj < corsairlink_device_list_count; jj++ ) + { + rr = corsairlink_device_setup( devices, &corsairlink_devices[jj], desc ); + if ( rr == 1 ) + { + break; + } + else if (rr == 2 ) + { + continue; + } + // return rr; + } + + return 0; +} + int corsairlink_device_scanner( libusb_context* context, int* _scanlist_count ) { @@ -72,80 +223,17 @@ corsairlink_device_scanner( libusb_context* context, int* _scanlist_count ) /* Start: scan code */ int ii; // Loops through USB devices. - int jj; // Loops through known CorsairLink Devices. ssize_t cnt; - struct corsair_device_info* device; libusb_device** devices; - uint16_t device_id = 0x00; - // uint16_t firmware_id = 0x0000; cnt = libusb_get_device_list( context, &devices ); for ( ii = 0; ii < cnt; ii++ ) { - if ( scanlist_count >= 10 ) + rr = corsairlink_device_enumerate( devices[ii] ); + if ( rr == 1 ) { - msg_debug( "Limited to 10 CorsairLink devices\n" ); break; } - - struct libusb_device_descriptor desc; - rr = libusb_get_device_descriptor( devices[ii], &desc ); - msg_debug( "Checking USB device %d (%04x:%04x)...\n", ii, desc.idVendor, desc.idProduct ); - - for ( jj = 0; jj < corsairlink_device_list_count; jj++ ) - { - device = &corsairlink_devices[jj]; - - if ( ( device->vendor_id == desc.idVendor ) - && ( device->product_id == desc.idProduct ) ) - { - msg_debug( "Corsair product detected. Checking if device is %s... ", device->name ); - rr = libusb_open( devices[ii], &scanlist[scanlist_count].handle ); - if ( scanlist[scanlist_count].handle != NULL ) - { // Maybe try 'if (rr == 0)' - rr = libusb_set_auto_detach_kernel_driver( scanlist[scanlist_count].handle, 1 ); - if ( rr != LIBUSB_SUCCESS ) - { - msg_err("Platform does not support kernel detachment\n"); - } - - rr = libusb_claim_interface( scanlist[scanlist_count].handle, 0 ); - if ( rr < 0 ) - { - msg_err("Unable to claim USB device interface\n"); - return rr; - } - - /* get device_id if we have a proper device handle */ - device->driver->device_id( - device, scanlist[scanlist_count].handle, &device_id ); - /* check to see if the device_id is the right one */ - if ( device->device_id == device_id ) - { - /* if we have the right device id we can setup the rest - * of the device connections - */ - scanlist[scanlist_count].device = device; - msg_info( - "Dev=%d, CorsairLink Device Found: %s!\n", scanlist_count, - device->name ); - scanlist_count++; - break; - } - else - { - msg_debug( "No (device_id 0x%02X)\n", device_id ); - - corsairlink_handle_close( scanlist[scanlist_count].handle ); - continue; - } - } - else - { - msg_debug( "Could not open device %d:%d.", desc.idVendor, desc.idProduct ); - } - } - } } msg_info( "\n" ); *_scanlist_count = scanlist_count;