blink1-tool/blink1raw/blink1raw.c

215 lines
4.7 KiB
C

/*
* blinkraw.c
*
* fgmr 2012-09-22
*
* playing with the hidraw interface to blink(1)
*
* Thank you Alan Ott for
* http://lxr.free-electrons.com/source/samples/hidraw/hid-example.c
*/
#include <linux/types.h>
#include <linux/input.h>
#include <linux/hidraw.h>
#ifndef HIDIOCSFEATURE
#define HIDIOCSFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x06, len)
#define HIDIOCGFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x07, len)
#endif /* HIDIOCSFEATURE */
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <stdarg.h>
#include <ctype.h>
static void
usage(const char* hunh) {
if (NULL != hunh) {
fprintf(stderr, "Can't understand %s\n", hunh);
}
fprintf(stderr,
"Usage: blinkraw {arg, ...}\n"
" /dev/whatever -- open device\n"
" ./whatever -- open device\n"
" =R,G,B,t -- fade to color\n"
" :R,G,B -- set color (now)\n"
" @step:R,G,B,t -- set step\n"
" +step -- start playing at step\n"
" -[step] -- stop playing at step (default zero)\n"
" %% -- clear all steps\n"
" _ -- turn off\n"
" _t -- fade off\n"
"\n"
" step is on [0,15]\n",
" R, G, B are on [0, 255]\n"
" t is time in centiseconds\n"
"\n"
" Arguments are applied in order. A new device, which is\n"
" a valid blink(1) device, will become the new target.\n"
"\n"
" Example:\n"
" # blinkraw /dev/hidraw* % =255,0,0,100\n"
);
exit(1);
}
static void
color(int fd, char action, int R, int G, int B, int T, int step) {
char buf[16];
int rc;
if (-1 == fd) return;
memset(buf, 0, sizeof(buf));
if (R<0) R=0;
if (G<0) G=0;
if (B<0) B=0;
if (T<0) T=0;
if (step<0) step=0;
if (R>255) R=255;
if (G>255) G=255;
if (B>255) B=255;
if (T>65535) T=65535;
if (step>15) step=15;
buf[0] = 1;
buf[1] = action;
buf[2] = R; /* R */
buf[3] = G; /* G */
buf[4] = B; /* B */
buf[5] = (T >>8); /* time/cs high */
buf[6] = (T & 0xff); /* time/cs low */
buf[7] = step;
buf[8] = 0;
rc = ioctl(fd, HIDIOCSFEATURE(9), buf);
if (rc < 0) perror("HIDIOCSFEATURE");
}
static void
play(int fd, char action, int play, int step) {
char buf[16];
int rc;
if (-1 == fd) return;
memset(buf, 0, sizeof(buf));
buf[0] = 1;
buf[1] = action;
buf[2] = play;
buf[3] = step;
rc = ioctl(fd, HIDIOCSFEATURE(9), buf);
if (rc < 0) perror("HIDIOCSFEATURE");
}
static int
isblink1(int fd) {
int rc;
struct hidraw_devinfo info;
memset(&info, 0, sizeof(info));
rc = ioctl(fd, HIDIOCGRAWINFO, &info);
if (rc < 0) {
perror("HIDIOCGRAWINFO");
return 0;
}
if ((info.vendor == 0x27b8) && (info.product == 0x01ed)) {
return 1;
} else {
return 0;
}
}
int
main(int argc, char *argv[]) {
int fd = -1;
if (argc < 2) usage(NULL);
while(++argv, --argc) {
int rc = -1;
int step = 0;
int R = 0;
int G = 0;
int B = 0;
int T = 0;
char buf[16];
memset(buf, 0, sizeof(buf));
switch(**argv) {
case '/': case '.':
rc = open(*argv, O_RDWR|O_NONBLOCK);
if (rc < 0) {
perror(*argv);
continue;
}
if (isblink1(rc)) {
if (fd >= 0) close(fd);
fd = rc;
}
break;
case '=':
rc = sscanf(*argv, "=%d,%d,%d,%d", &R, &G, &B, &T);
if (rc != 4) usage(*argv);
color(fd, 'c', R, G, B, T, 0);
break;
case ':':
rc = sscanf(*argv, ":%d,%d,%d", &R, &G, &B);
if (rc != 3) usage(*argv);
color(fd, 'n', R, G, B, 0, 0);
break;
case '@':
rc = sscanf(*argv, "@%d:%d,%d,%d,%d", &step, &R, &G, &B, &T);
if (rc != 5) usage(*argv);
if ((step < 0) || step > 15) usage(*argv);
color(fd, 'P', R, G, B, T, step);
break;
case '_':
rc = sscanf(*argv, "_%d", &T);
if (rc == 1) color(fd, 'c', 0, 0, 0, T, 0);
else color(fd, 'n', 0, 0, 0, 0, 0);
break;
case '+':
rc = sscanf(*argv, "+%d", &step);
if (rc != 1) usage(*argv);
if ((step < 0) || step > 15) usage(*argv);
play(fd, 'p', 1, step);
break;
case '-':
rc = sscanf(*argv, "-%d", &step);
if (rc != 1) step = 0;
if ((step < 0) || step > 15) step = 0;
play(fd, 'p', 0, step);
break;
case '%':
for(step = 0; step < 16; ++step) {
color(fd, 'P', 0, 0, 0, 0, step);
}
break;
default:
usage(*argv);
}
}
close(fd);
return 0;
}