steelseries-led/steelseries-led.c

278 lines
7.3 KiB
C

/*
* steelseries-led.c
* Copyright 2015 L. Bradley LaBoon
*
* This program 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 3 of the License, or
* (at your option) any later version.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <hidapi/hidapi.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#define BUFFER_SIZE 8
#define COLOR_OFF 0
#define COLOR_RED 1
#define COLOR_ORANGE 2
#define COLOR_YELLOW 3
#define COLOR_GREEN 4
#define COLOR_SKY 5
#define COLOR_BLUE 6
#define COLOR_PURPLE 7
#define COLOR_WHITE 8
#define LEVEL_LIGHT 3
#define LEVEL_LOW 2
#define LEVEL_MED 1
#define LEVEL_HIGH 0
#define MODE_NORMAL 1
#define MODE_GAMING 2
#define MODE_BREATHE 3
#define MODE_DEMO 4
#define MODE_WAVE 5
#define REGION_LEFT 1
#define REGION_MIDDLE 2
#define REGION_RIGHT 3
#define COMMAND_MODE 0
#define COMMAND_SET 1
#define COMMAND_HELP 2
void printHelp()
{
printf("Usage: steelseries-led mode MODE\n");
printf(" or: steelseries-led set REGION COLOR LEVEL\n");
printf("Configure the lighting of a SteelSeries laptop keyboard.\n\n");
printf("MODE can be one of the following:\n");
printf("\tnormal\t\tSolid lighting for each of the three regions\n");
printf("\tgaming\t\tOnly the left region is lit\n");
printf("\tbreathe\t\tLighting fades in and out\n");
printf("\tdemo\t\tCycles between various colors and modes\n");
printf("\twave\t\tColors flow from left to right\n\n");
printf("REGION can be one of the following:\n");
printf("\tleft\n");
printf("\tright\n");
printf("\tmiddle\n\n");
printf("COLOR can be one of the following:\n");
printf("\toff\n");
printf("\tred\n");
printf("\torange\n");
printf("\tyellow\n");
printf("\tgreen\n");
printf("\tsky\n");
printf("\tblue\n");
printf("\tpurple\n");
printf("\twhite\n\n");
printf("LEVEL can be one of the following:\n");
printf("\tlight\n");
printf("\tlow\n");
printf("\tmed\n");
printf("\thigh\n\n");
printf("Examples:\n");
printf("\tsteelseries-led mode normal\n");
printf("\t\tPuts the keyboard in normal mode.\n\n");
printf("\tsteelseries-led set left blue high\n");
printf("\t\tSets the left side of the keyboard to bright blue.\n\n");
printf("\tsteelseries-led set middle off light\n");
printf("\t\tTurns off the LEDs in the middle of the keyboard.\n");
printf("\t\tThe last argument is irrelevant in this case.\n\n");
printf("Report bugs to me@bradleylaboon.com\n");
printf("Home page: <http://www.bradleylaboon.com/projects/steelseries-led/>\n");
}
int main(int argc, char** argv)
{
if (argc < 2) {
fprintf(stderr, "Missing command.\n");
fprintf(stderr, "Run 'steelseries-led help' for more information.\n");
return 1;
}
// Get mode from arguments
int command = -1;
if (strcmp(argv[1], "mode") == 0)
command = COMMAND_MODE;
else if (strcmp(argv[1], "set") == 0)
command = COMMAND_SET;
else if (strcmp(argv[1], "help") == 0)
command = COMMAND_HELP;
if (command == -1) {
fprintf(stderr, "Invalid command -- '%s'\n", argv[1]);
fprintf(stderr, "Run 'steelseries-led help' for more information.\n");
return 2;
}
unsigned char buffer[BUFFER_SIZE];
for (int i = 0; i < BUFFER_SIZE; i++)
buffer[i] = 0;
// Populate buffer
switch (command) {
case COMMAND_MODE:
if (argc < 3) {
fprintf(stderr, "No mode specified.\n");
fprintf(stderr, "Run 'steelseries-led help' for more information.\n");
return 1;
}
// Get the mode argument
int mode = -1;
if (strcmp(argv[2], "normal") == 0)
mode = MODE_NORMAL;
else if (strcmp(argv[2], "gaming") == 0)
mode = MODE_GAMING;
else if (strcmp(argv[2], "breathe") == 0)
mode = MODE_BREATHE;
else if (strcmp(argv[2], "demo") == 0)
mode = MODE_DEMO;
else if (strcmp(argv[2], "wave") == 0)
mode = MODE_WAVE;
if (mode == -1) {
fprintf(stderr, "Invalid mode -- '%s'\n", argv[2]);
fprintf(stderr, "Run 'steelseries-led help' for more information.\n");
return 2;
}
// Bytes for setting mode
buffer[0] = 1;
buffer[1] = 2;
buffer[2] = 65; // Set mode
buffer[3] = (unsigned char) mode;
buffer[7] = 236; // End of request
break;
case COMMAND_SET:
if (argc < 5) {
fprintf(stderr, "Missing arguments for command 'set'.\n");
fprintf(stderr, "Run 'steelseries-led help' for more information.\n");
return 1;
}
// Get the region argument
int region = -1;
if (strcmp(argv[2], "left") == 0)
region = REGION_LEFT;
else if (strcmp(argv[2], "right") == 0)
region = REGION_RIGHT;
else if (strcmp(argv[2], "middle") == 0)
region = REGION_MIDDLE;
if (region == -1) {
fprintf(stderr, "Invalid region -- '%s'\n", argv[2]);
fprintf(stderr, "Run 'steelseries-led help' for more information.\n");
return 2;
}
// Get the color argument
int color = -1;
if (strcmp(argv[3], "off") == 0)
color = COLOR_OFF;
else if (strcmp(argv[3], "red") == 0)
color = COLOR_RED;
else if (strcmp(argv[3], "orange") == 0)
color = COLOR_ORANGE;
else if (strcmp(argv[3], "yellow") == 0)
color = COLOR_YELLOW;
else if (strcmp(argv[3], "green") == 0)
color = COLOR_GREEN;
else if (strcmp(argv[3], "sky") == 0)
color = COLOR_SKY;
else if (strcmp(argv[3], "blue") == 0)
color = COLOR_BLUE;
else if (strcmp(argv[3], "purple") == 0)
color = COLOR_PURPLE;
else if (strcmp(argv[3], "white") == 0)
color = COLOR_WHITE;
if (color == -1) {
fprintf(stderr, "Invalid color -- '%s'\n", argv[3]);
fprintf(stderr, "Run 'steelseries-led help' for more information.\n");
return 2;
}
// Get the level argument
int level = -1;
if (strcmp(argv[4], "light") == 0)
level = LEVEL_LIGHT;
else if (strcmp(argv[4], "low") == 0)
level = LEVEL_LOW;
else if (strcmp(argv[4], "med") == 0)
level = LEVEL_MED;
else if (strcmp(argv[4], "high") == 0)
level = LEVEL_HIGH;
if (level == -1) {
fprintf(stderr, "Invalid level -- '%s'\n", argv[4]);
fprintf(stderr, "Run 'steelseries-led help' for more information.\n");
return 2;
}
// Bytes for setting the backlight
buffer[0] = 1;
buffer[1] = 2;
buffer[2] = 66; // Set backlight
buffer[3] = (unsigned char) region;
buffer[4] = (unsigned char) color;
buffer[5] = (unsigned char) level;
buffer[7] = 236; // End of request
break;
case COMMAND_HELP:
default:
printHelp();
return 0;
}
// Initialize HIDAPI library
if (hid_init() == -1) {
fprintf(stderr, "hid_init(): Couldn't initialize HIDAPI.\n");
return 3;
}
// Open device
hid_device *device = hid_open(0x1770, 0xff00, NULL);
if (device == NULL) {
fprintf(stderr, "hid_open(): Couldn't open device.\n");
hid_exit();
return 3;
}
// Send the data
int retVal = 0;
if (hid_send_feature_report(device, buffer, BUFFER_SIZE) == -1) {
wchar_t *err = hid_error(device);
if (err == NULL)
err = L"Couldn't send data.";
fprintf(stderr, "hid_send_feature_report(): %ls\n", err);
retVal = 3;
}
// Close the device and finalize HIDAPI
hid_close(device);
hid_exit();
return retVal;
}