1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306
|
/* irfunc.c v0.4.2 (c) 1998-99 Tom Wheeley <tomw@tsys.demon.co.uk> */
/* this code is placed under the LGPL, see www.gnu.org for info */
/*
* irfunc.c, infrared functions (Irman specific)
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <termios.h>
#include <unistd.h>
#include "irman.h"
/* generic function for ir_get_code() and ir_poll_code() */
static unsigned char *ir_read_code(unsigned long timeout);
/* converts a single hex character to an integer */
static int ir_hex_to_int(unsigned char hex);
/* flag to enable use of higher level functions */
static int ir_enabled=0;
/* output hex digits */
static char ir_hexdigit[16] = {
'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'
};
int ir_init(char *filename)
{
#ifndef IR_SOFTWARE_TEST /* normal only */
int rdchar;
#endif /* both */
int fd;
if (ir_enabled) {
errno = IR_EENABLED; /* we already have a high level ir setup */
return -1;
}
#ifndef IR_SOFTWARE_TEST /* normal only */
if ( (fd = ir_open_port(filename)) < 0) {
return -1;
}
ir_clear_buffer();
if (ir_write_char('I') < 0)
return -1;
tcdrain(fd);
ir_usleep(IR_HANDSHAKE_GAP);
if (ir_write_char('R') < 0)
return -1;
/* we'll be nice and give the box a good chance to send an 'O' */
while ((rdchar = ir_read_char(IR_HANDSHAKE_TIMEOUT)) != 'O') {
if (rdchar < 0) { /* error or timeout */
return -1;
}
}
/* as regards the 'K', however, that really must be the next character */
rdchar = ir_read_char(IR_HANDSHAKE_TIMEOUT);
if (rdchar < 0) {
return -1;
}
/* ENOEXEC is the closest error I could find, that would also not be
* generated by ir_read_char(). Anyway, ENOEXEC does more or less mean
* "I don't understand this data I've been given"
*/
if (rdchar != 'K') {
errno = IR_EHANDSHAKE;
return -1;
}
#else /* software test only */
fd = 1;
#endif /* IR_SOFTWARE_TEST */ /* both */
/* we are now ready to roll */
ir_enabled = 1;
return fd;
}
/* simply a wrapper for ir_close_port() */
int ir_finish(void)
{
if (!ir_enabled) {
errno = IR_EDISABLED;
return -1;
}
ir_enabled = 0;
#ifndef IR_SOFTWARE_TEST
return ir_close_port();
#else
return 0;
#endif
}
/* this function is used by both ir_get_code() and ir_poll_code(),
* the difference being in the timeout for the first piece of data.
* we also have a short timeout whatever for the remaining five bytes,
* in case computer and Irman get out of sync we can just raise an error
* and get back to normal life.
*
* note esp. that these functions return a pointer to statically defined
* data. In the forseeable usage of LIBIRMAN this seems the easiest way.
*/
#ifndef IR_SOFTWARE_TEST /* normal behaviour */
static unsigned char *ir_read_code(unsigned long timeout)
{
static char codebuf[2][IR_CODE_LEN];
static struct timeval lasttv = {0, 0};
static int curbuf = 0;
struct timeval tv;
int i, datum;
datum = ir_read_char(timeout);
if (datum < 0)
return NULL;
codebuf[curbuf][0] = datum;
gettimeofday(&tv, NULL);
for (i=1; i<IR_CODE_LEN; i++) {
datum = ir_read_char(IR_POLL_TIMEOUT);
if (datum < 0) {
return NULL;
} else {
codebuf[curbuf][i] = datum;
}
}
/* check for another code */
if (lasttv.tv_sec || lasttv.tv_usec) {
if ( ((long) (tv.tv_sec - lasttv.tv_sec)) * 1000000 +
(tv.tv_usec - lasttv.tv_usec) < IR_DOUBLE_TIMEOUT) {
/* within timeout */
if (!strcmp(codebuf[0], codebuf[1])) {
/* codes match */
lasttv.tv_sec = 0;
lasttv.tv_usec = 0;
errno = IR_EDUPCODE;
return NULL;
}
}
}
lasttv = tv;
curbuf = curbuf ? 0 : 1;
return (unsigned char *) codebuf[1-curbuf];
}
#else /* following is with IR_SOFTWARE_TEST defined */
static unsigned char *ir_read_code(unsigned long timeout)
{
static char buf[999];
/* we ignore the timeout... please don't poll! */
printf(" ------------\n");
printf("please enter 12 hex digits: ");fflush(stdout);
fgets(buf, 998, stdin);
return ir_text_to_code(buf);
}
#endif /* IR_SOFTWARE_TEST */
unsigned char *ir_get_code(void)
{
/* well dodgy choice of error here...! */
if (!ir_enabled) {
errno = IR_EDISABLED;
return NULL;
}
return ir_read_code(IR_BLOCKING);
}
unsigned char *ir_poll_code(void)
{
if (!ir_enabled) {
errno = IR_EDISABLED;
return NULL;
}
return ir_read_code(0);
}
/* checks to see if a piece of text is a valid ir code (1 = yes) */
int ir_valid_code(char *text)
{
char *c;
if (strlen(text) != IR_CODE_LEN * 2)
return 0;
for(c = text; *c; c++)
if (!isxdigit(*c))
return 0;
return 1;
}
char *ir_code_to_text(unsigned char *code)
{
static char text[2 * IR_CODE_LEN + 1];
int i;
char *j;
j = text;
for (i=0; i < IR_CODE_LEN; i++) {
*j++ = ir_hexdigit[(code[i] >> 4) & 0x0f];
*j++ = ir_hexdigit[ code[i] & 0x0f];
}
*j = '\0';
return text;
}
static int ir_hex_to_int(unsigned char hex)
{
if (hex >= '0' && hex <= '9')
return hex - '0';
hex = tolower(hex);
if (hex >= 'a' && hex <= 'f')
return hex - 'a' + 10;
/* error! */
return 0;
}
unsigned char *ir_text_to_code(char *text)
{
static char code[IR_CODE_LEN];
int i;
char *j;
j = text;
for (i=0; i<IR_CODE_LEN; i++) {
if (!j[0] || !j[1]) {
break;
}
code[i] = (ir_hex_to_int(*j++) << 4) & 0xf0;
code[i] += (ir_hex_to_int(*j++) ) & 0x0f;
}
/* if string isn't long enough, pad with zeros. This is (marginally)
* better than the leaving in the remains of the last conversion
*/
for ( ; i<IR_CODE_LEN; i++)
code[i] = '\0';
return (unsigned char *)code;
}
/* this function should never be called, but maybe someone wants to manually
* open the ir channel, then use the higher level functions. If you use this
* then you deserve any problems you get! It is only here because I don't
* believe in unneccesary restrictions.
*/
void ir_set_enabled(int val)
{
ir_enabled = val;
}
/* end of irfunc.c */
|