/* * foxtel.c: A foxtel (Aussie cable TV) IR control client * * By: Alan Yates */ #include #include #include #include #include #include #include /* note: all times are in mirco seconds */ #define BUFSIZE 2048 /* buffer size */ #define IR_DEV "irctrl" /* device file */ #define ir_carrier 21 /* IR carrier period */ #define bit_t 600 /* IR TX time */ #define one_t 7000 /* delay that codes '1' */ #define zero_t 4400 /* delay that codes '0' */ #define sync_t 3200 /* sync pulse spacing */ #define cmd_delay 100000 /* min delay between consective cmds */ #define tailspace 1 /* last 'space' time given to kernel */ /* code table */ struct code_t { char *name; char *code; }; struct code_t codes[] = { {"pwr", "x100010000"}, {"0", "x100000000"}, {"1", "x100000001"}, {"2", "x100000010"}, {"3", "x100000011"}, {"4", "x100000100"}, {"5", "x100000101"}, {"6", "x100000110"}, {"7", "x100000111"}, {"8", "x100001000"}, {"9", "x100001001"}, {"up", "x100011010"}, {"rcl", "x100011010"}, {"f", "x100011001"}, {"-", "x100010110"}, {"left", "x100010110"}, {"menu", "x100010111"}, {"+", "x100010001"}, {"right", "x100010001"}, {"i", "x100011111"}, {"down", "x100001011"}, {"fav", "x100001011"}, {"store", "x100010011"}, {"norm", "x100010101"}, {"mute", "x100011110"}, {0, 0} }; char press = 0; /* toggle flag, each new press has toggled value */ char *PROG = 0; /* set to argv[0] */ int DEV = 0; /* set to open(IR_DEV, O_WRONLY) */ struct timeval rxbuf[BUFSIZE]; /* rx timing buffer */ int rxwcursor = 0; /* rx write cursor */ int rxrcursor = 0; /* rx read cursor */ void dump_table() { int i = 0, p = 0; char buf[2048]; fprintf(stderr, "%s: code table:\n", PROG); while(codes[i].name) { p += sprintf(&buf[p], "%-16s %s\n", codes[i].name, codes[i].code); i++; } p += sprintf(&buf[p], "\n"); buf[p] = 0; fprintf(stderr, buf); } void dump_cmds() { int i = 0, p = 0; char buf[10240]; p += sprintf(&buf[p], "%s: known codes:\n", PROG); while(codes[i].name) p += sprintf(&buf[p], "%s ", codes[i++].name); p += sprintf(&buf[p], "\n. for a delay, = for table, ? for codes\n\n"); buf[p] = 0; fprintf(stderr, buf); } void tx(char *data) { int i = 0, p = 0; char bit = 0; struct stat sb; char buf[10240]; /* open the device file */ if(stat(IR_DEV, &sb) < 0) { perror(IR_DEV); return; } DEV = open(IR_DEV, O_WRONLY); /* x bit toggle per press */ (press == '0') ? (press = '1') : (press = '0'); /* irctrl carrier period and compensate values */ p += sprintf(&buf[p], "%d\n", ir_carrier); /* IR data sync header */ p += sprintf(&buf[p], "%d %d\n", bit_t, sync_t); p += sprintf(&buf[p], "%d %d\n", bit_t, sync_t); /* IR data packet */ for(i = 0; i < strlen(data); i++) { bit = data[i]; if(bit == 'x') bit = press; if(bit == '1') p += sprintf(&buf[p], "%d %d\n", bit_t, one_t); else p += sprintf(&buf[p], "%d %d\n", bit_t, zero_t); } /* Stop bit */ p += sprintf(&buf[p], "%d %d\n", bit_t, tailspace); buf[p] = 0; /* write and release device */ write(DEV, buf, p); close(DEV); } void send(char *cmd) { int i = 0; struct timeval tv; /* check to see if its a delay element or table dump */ if(!strcmp(cmd, ".")) { /* wait */ /* do nothing */ } else if(!strcmp(cmd, "?")) { /* cmd listing */ dump_cmds(); } else if(!strcmp(cmd, "=")) { /* table dump */ dump_table(); } else if(cmd[0] == '/') { /* raw send */ tx(&cmd[1]); } else { /* cmd in table */ while(codes[i].name) { if(!strcmp(codes[i].name, cmd)) break; else i++; } if(!codes[i].name) { fprintf(stderr, "%s: unknown command: '%s'\n", PROG, cmd); return; } tx(codes[i].code); } /* delay */ tv.tv_sec = 0; tv.tv_usec = cmd_delay; select(0, 0, 0, 0, &tv); } void interactive() { char buf[2048]; struct timeval tv; char *p1, *p2; fd_set fds; fprintf(stdout, "%s> ", PROG); fflush(stdout); while(fgets(buf, 2048, stdin)) { buf[strlen(buf)-1] = 0; p1 = buf; p2 = buf; while((p2 = strsep(&p1, " "))) { send(p2); } fprintf(stdout, "%s> ", PROG); fflush(stdout); } } int main(int argc, char **argv) { int i; struct timeval tv; PROG = argv[0]; if(argc < 2) { dump_cmds(); interactive(); } else { for(i = 1; i < argc; i++) { send(argv[i]); tv.tv_sec = 0; tv.tv_usec = cmd_delay; select(0, 0, 0, 0, &tv); } } return 0; }