215 lines
4.7 KiB
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;
|
|
}
|