Added lirc.
[irreco.git] / lirc-0.8.4a / daemons / hw_irlink.c
blobc7e541259c3f7562352e68aca5b83023f774dc4b
1 /*****************************************************************************
2 ** hw_irlink.c **************************************************************
3 *****************************************************************************
4 * Routines for the IRLink VS Infrared receiver
6 * Copyright (C) 2007 Maxim Muratov <mumg at mail.ru>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Library General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <fcntl.h>
31 #include <unistd.h>
32 #include <limits.h>
33 #include <signal.h>
34 #include <sys/stat.h>
35 #include <sys/types.h>
36 #include <sys/ioctl.h>
37 #include <sys/wait.h>
38 #include <errno.h>
39 #include <termios.h>
41 #include "hardware.h"
42 #include "receive.h"
43 #include "serial.h"
44 #include "ir_remote.h"
45 #include "lircd.h"
46 #include "hw_irlink.h"
48 struct hardware hw_irlink = {
49 LIRC_DRIVER_DEVICE, /* Default device */
50 -1, /* fd */
51 LIRC_CAN_REC_MODE2, /* Features */
52 0, /* send_mode */
53 LIRC_MODE_MODE2, /* rec_mode */
54 0, /* code_length */
55 irlink_init, /* init_func */
56 NULL, /* config_func */
57 irlink_deinit, /* deinit_func */
58 NULL, /* send_func */
59 irlink_rec, /* rec_func */
60 receive_decode, /* decode_func */
61 NULL, /* ioctl_func */
62 irlink_readdata, /* readdata */
63 "irlink"
67 typedef enum
69 BLOCK,
70 NON_BLOCK
71 }IRLINK_READ_MODE_T;
73 #define IS_IRLINK_LONG_PULSE(code) (code == 0xFF)
74 #define IS_IRLINK_LONG_PAUSE(code) (code == 0xFE)
76 #define IS_IRLINK_PULSE(code) (code & 0x01)
78 #define IS_IRLINK_TIMESCALE_3600(code) ((code & 0x80) > 0)
79 #define IS_IRLINK_TIMESCALE_14400(code) ((code & 0x80) == 0)
81 #define IRLINK_DETECT_CMD 0x81
83 #define IRLINK_PERIOD(value,timescale) \
84 (((1000000 * ((unsigned int)value))/timescale)&PULSE_MASK)
86 static int is_long_pause = 0;
87 static int is_long_pulse = 0;
88 static struct timeval last_time = {0};
89 static unsigned char pulse = 1;
90 static lirc_t last_code = 0;
92 static int irlink_close(const int port)
94 if ( port != -1 )
96 tty_delete_lock();
97 close(port);
98 return 0;
100 return -1;
104 static int irlink_open(const char * portName)
106 int port = -1;
107 if(!tty_create_lock((char*)portName))
109 logprintf(LOG_ERR,"could not create lock files");
110 return -1;
112 if((port=open(portName,O_RDWR | O_NOCTTY | O_NDELAY))<0)
114 logprintf(LOG_ERR,"could not open %s",hw.device);
115 tty_delete_lock();
116 return -1;
118 if(tty_reset(port) < 0 ||
119 tty_setbaud(port , 115200) < 0 ||
120 tty_setcsize(port , 8) < 0 ||
121 tty_setrtscts(port , 0) < 0 )
123 irlink_close(port);
124 port = -1;
126 return port;
129 static int irlink_read(const int port,
130 unsigned char * buffer,
131 int bufferSize )
133 if ( port == -1 )
135 return -1;
137 return read(port , buffer , bufferSize);
141 static int irlink_write(const int port,
142 unsigned char * buffer,
143 int bufferSize)
145 if ( port == -1 )
147 return -1;
149 return write(port , buffer , bufferSize );
152 static void irlink_read_flush(const int port)
154 for(;;)
156 fd_set fds;
157 struct timeval tm;
158 lirc_t data = 0;
159 FD_ZERO(&fds);
160 FD_SET(port, &fds);
161 tm.tv_sec = 0;
162 tm.tv_usec = 0;
163 if(select(port + 1 , &fds , 0 , 0 , &tm) > 0)
165 if (read(port , &data , sizeof(data)) <= 0)
167 break;
170 else
172 break;
178 static int irlink_detect(const int port)
180 unsigned char detect_cmd [] = { IRLINK_DETECT_CMD };
181 if ( port == -1 )
183 return -1;
185 irlink_read_flush(port);
186 if ( irlink_write(port,
187 detect_cmd,
188 sizeof(detect_cmd)) == sizeof(detect_cmd))
190 unsigned char detect_response = 0;
191 if ( waitfordata(500000) &&
192 irlink_read(port,
193 &detect_response,
194 sizeof(detect_response) ) == sizeof(detect_response))
196 if (detect_response == IRLINK_DETECT_CMD )
198 return 0;
202 return -1;
207 char *irlink_rec(struct ir_remote *remotes)
209 if(!clear_rec_buffer()) return(NULL);
210 return(decode_all(remotes));
213 lirc_t irlink_readdata(lirc_t timeout)
215 lirc_t data = 0;
216 unsigned char rd_value = 0;
217 struct timeval start_time = {0};
218 gettimeofday(&start_time, NULL);
219 lirc_t time_delta = 0;
220 for(;;)
222 if (last_code != 0)
224 data = last_code;
225 last_code = 0;
226 break;
228 if (timeout < time_delta )
230 logprintf (LOG_ERR, "timeout < time_delta");
231 break;
233 if (!waitfordata(timeout - time_delta))
235 break;
237 if ( irlink_read(hw.fd,
238 &rd_value,
239 sizeof(rd_value)) == sizeof(rd_value) )
241 if ( IS_IRLINK_LONG_PULSE(rd_value)||
242 IS_IRLINK_LONG_PAUSE(rd_value))
244 struct timeval diff_time = {0};
245 is_long_pulse = IS_IRLINK_LONG_PULSE(rd_value);
246 is_long_pause = IS_IRLINK_LONG_PAUSE(rd_value);
247 gettimeofday(&last_time, NULL);
248 timersub(&last_time,
249 &start_time,
250 &diff_time);
251 time_delta = diff_time.tv_sec * 1000000 +
252 diff_time.tv_usec;
253 continue;
255 else
257 lirc_t * code_ptr = &data;
258 if ( is_long_pulse != 0 ||
259 is_long_pause != 0 )
261 struct timeval curr_time;
262 struct timeval diff_time;
263 gettimeofday(&curr_time, NULL);
264 timersub(&curr_time,
265 &last_time,
266 &diff_time);
268 if (diff_time.tv_sec >= 16)
270 data = PULSE_MASK;
272 else
274 data = diff_time.tv_sec *
275 1000000 +
276 diff_time.tv_usec;
278 if (is_long_pause)
280 is_long_pause = 0;
281 pulse = 1;
282 data &= ~PULSE_BIT;
284 if (is_long_pulse)
286 pulse = 0;
287 is_long_pulse = 0;
288 data |= PULSE_BIT;
290 code_ptr = &last_code;
292 if(IS_IRLINK_TIMESCALE_3600(rd_value))
294 rd_value = (rd_value & 0x7F) >> 1;
295 *code_ptr = IRLINK_PERIOD(rd_value,3600);
297 else if (IS_IRLINK_TIMESCALE_14400(rd_value))
299 rd_value = (rd_value & 0x7F) >> 1;
300 *code_ptr = IRLINK_PERIOD(rd_value,14400);
302 if ( pulse == 0 )
304 *code_ptr &= ~PULSE_BIT;
306 else
308 *code_ptr |= PULSE_BIT;
310 pulse = !pulse;
311 break;
314 else
316 logprintf(LOG_ERR, "error reading from %s", hw.device);
317 logperror(LOG_ERR, NULL);
318 irlink_deinit();
321 return data;
324 int irlink_init(void)
326 hw.fd = irlink_open(hw.device);
327 if ( hw.fd < 0)
329 logprintf (LOG_ERR, "Could not open the '%s' device",
330 hw.device);
332 else
334 if ( irlink_detect(hw.fd) == 0 )
336 return 1;
338 else
340 logprintf (LOG_ERR, "Failed to detect IRLink "
341 "on '%s' device",
342 hw.device);
343 irlink_deinit();
346 return 0;
349 int irlink_deinit (void)
351 if ( hw.fd != - 1)
353 irlink_close(hw.fd);
355 hw.fd = -1;
356 return 1;