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
|
/****************************************************************************
** hw_pinsys.c *************************************************************
****************************************************************************
*
* adapted routines for Pinnacle Systems PCTV (pro) receiver
*
* Original routines from hw_pixelview.c :
* Copyright (C) 1999 Christoph Bartelmus <lirc@bartelmus.de>
*
* Adapted by Bart Alewijnse (scarfboy@yahoo.com)
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifndef LIRC_IRTTY
#define LIRC_IRTTY "/dev/ttyS0"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <limits.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include "hardware.h"
#include "serial.h"
#include "ir_remote.h"
#include "lircd.h"
#include "hw_pinsys.h"
#include <termios.h>
extern struct ir_remote *repeat_remote, *last_remote;
/* Technically, the code is three bytes long, however, only five bits
in the last byte are needed to identify a button. If you don't
define the following, the ir_cide code will only be the last
byte. I don't know why I left it in.. well, who knows.
#define PINSYS_THREEBYTE
*/
#define PINSYS_THREEBYTE
#ifdef PINSYS_THREEBYTE
#define BITS_COUNT 24
#else
#define BITS_COUNT 8
#endif
#define REPEAT_FLAG ((ir_code) 0x000040)
#define REPEAT_MASK ((ir_code) 0x00e840)
static unsigned char b[3];
static struct timeval start, end, last;
static lirc_t signal_length;
static ir_code code;
struct hardware hw_pinsys = {
LIRC_IRTTY, /* default device */
-1, /* fd */
LIRC_CAN_REC_LIRCCODE, /* features */
0, /* send_mode */
LIRC_MODE_LIRCCODE, /* rec_mode */
/* remember to change signal_length if you correct this one */
BITS_COUNT, /* code_length */
pinsys_init, /* init_func */
pinsys_deinit, /* deinit_func */
NULL, /* send_func */
pinsys_rec, /* rec_func */
pinsys_decode, /* decode_func */
NULL, /* ioctl_func */
NULL, /* readdata */
"pinsys"
};
/**** start of autodetect code ***************************/
int is_it_is_it_huh(int port)
{
int j;
tty_clear(port, 1, 0);
ioctl(port, TIOCMGET, &j);
if ((j & TIOCM_CTS) || (j & TIOCM_DSR)) {
return 0;
}
tty_set(port, 1, 0);
ioctl(port, TIOCMGET, &j);
if ((!(j & TIOCM_CTS)) || (j & TIOCM_DSR)) {
return 0;
}
return 1;
}
/* returns 0-3, the port, or -1 if it can't find the device */
int autodetect(void)
{
int port, i;
long backup;
char device[20];
/* hardcoded the device names.. it's easy enough to change
that, but it's unlikely to be on something else. */
for (i = 0; i < 4; i++) {
sprintf(device, "/dev/ttyS%d", i);
if (!tty_create_lock(device)) {
continue;
}
port = open("/dev/ttyS0", O_RDONLY | O_NOCTTY);
if (port < 0) {
logprintf(LOG_WARNING, "couldn't open %s", device);
tty_delete_lock();
continue;
} else {
ioctl(port, TIOCMGET, &backup);
if (is_it_is_it_huh(port)) {
ioctl(port, TIOCMSET, &backup);
close(port);
tty_delete_lock();
return i;
}
ioctl(port, TIOCMSET, &backup);
close(port);
}
tty_delete_lock();
}
return -1;
}
/************** end of autodetect code *************/
int pinsys_decode(struct ir_remote *remote, ir_code * prep, ir_code * codep, ir_code * postp, int *repeat_flagp,
lirc_t * min_remaining_gapp, lirc_t * max_remaining_gapp)
{
if (!map_code
(remote, prep, codep, postp, 0, 0, BITS_COUNT, code & REPEAT_FLAG ? code ^ REPEAT_MASK : code, 0, 0)) {
return (0);
}
map_gap(remote, &start, &last, signal_length, repeat_flagp, min_remaining_gapp, max_remaining_gapp);
if (start.tv_sec - last.tv_sec < 2) {
/* let's believe the remote */
if (code & REPEAT_FLAG) {
*repeat_flagp = 1;
LOGPRINTF(1, "repeat_flag: %d\n", *repeat_flagp);
}
}
return (1);
}
int pinsys_init(void)
{
signal_length = (hw.code_length + (hw.code_length / BITS_COUNT) * 2) * 1000000 / 1200;
if (!tty_create_lock(hw.device)) {
logprintf(LOG_ERR, "could not create lock files");
return (0);
}
if ((hw.fd = open(hw.device, O_RDWR | O_NONBLOCK | O_NOCTTY)) < 0) {
int detected;
/* last character gets overwritten */
char auto_lirc_device[] = "/dev/ttyS_";
tty_delete_lock();
logprintf(LOG_WARNING, "could not open %s, autodetecting on /dev/ttyS[0-3]", hw.device);
logperror(LOG_WARNING, "pinsys_init()");
/* it can also mean you compiled serial support as a
module and it isn't inserted, but that's unlikely
unless you're me. */
detected = autodetect();
if (detected == -1) {
logprintf(LOG_ERR, "no device found on /dev/ttyS[0-3]");
tty_delete_lock();
return (0);
} else { /* detected */
auto_lirc_device[9] = '0' + detected;
hw.device = auto_lirc_device;
if ((hw.fd = open(hw.device, O_RDWR | O_NONBLOCK | O_NOCTTY)) < 0) {
/* unlikely, but hey. */
logprintf(LOG_ERR, "couldn't open autodetected device \"%s\"", hw.device);
logperror(LOG_ERR, "pinsys_init()");
tty_delete_lock();
return (0);
}
}
}
if (!tty_reset(hw.fd)) {
logprintf(LOG_ERR, "could not reset tty");
pinsys_deinit();
return (0);
}
if (!tty_setbaud(hw.fd, 1200)) {
logprintf(LOG_ERR, "could not set baud rate");
pinsys_deinit();
return (0);
}
/* set RTS, clear DTR */
if (!tty_set(hw.fd, 1, 0) || !tty_clear(hw.fd, 0, 1)) {
logprintf(LOG_ERR, "could not set modem lines (DTR/RTS)");
pinsys_deinit();
return (0);
}
/* I dunno, but when lircd starts may log `reading of byte 1
failed' I know that happened when testing, it's a zero
byte. Problem is, flushing doesn't fix it. It's not fatal,
it's an indication that it gets fixed. still... */
if (tcflush(hw.fd, TCIFLUSH) < 0) {
logprintf(LOG_ERR, "could not flush input buffer");
pinsys_deinit();
return (0);
}
return (1);
}
int pinsys_deinit(void)
{
close(hw.fd);
tty_delete_lock();
return (1);
}
/* The first byte is always 0xFE, the second one, is a kind of checksum
and the third one is the code itself (6 bits). The 7th bit (0x40) is the
repeat flag.
*/
#if 0
static char pinsys_codes[8] = { 0xD1, 0x73, 0xE6, 0x1D, 0x3A, 0x74, 0xE8, 0x00 };
static int pinsys_check_code(char key, char crc)
{
int b;
for (b = 0; b < 8; b++) {
if (key & (1 << b))
crc ^= pinsys_codes[b];
}
return crc == 0;
}
#endif
char *pinsys_rec(struct ir_remote *remotes)
{
char *m;
int i;
last = end;
gettimeofday(&start, NULL);
for (i = 0; i < 3; i++) {
if (i > 0) {
if (!waitfordata(20000)) {
LOGPRINTF(0, "timeout reading byte %d", i);
/* likely to be !=3 bytes, so flush. */
tcflush(hw.fd, TCIFLUSH);
return (NULL);
}
}
if (read(hw.fd, &b[i], 1) != 1) {
logprintf(LOG_ERR, "reading of byte %d failed", i);
logperror(LOG_ERR, NULL);
return (NULL);
}
LOGPRINTF(1, "byte %d: %02x", i, b[i]);
}
gettimeofday(&end, NULL);
#ifdef PINSYS_THREEBYTE
code = (b[2]) | (b[1] << 8) | (b[0] << 16);
#else
code = b[2];
#endif
LOGPRINTF(1, " -> %016lx", (__u32) code);
m = decode_all(remotes);
return (m);
}
|