| LIRC libraries LinuxInfraredRemoteControl

transmit.c
Go to the documentation of this file.
1 /******************************************************************
2 ** transmit.c **************************************************************
3 ****************************************************************************
4 *
5 * functions that prepare IR codes for transmitting
6 *
7 * Copyright (C) 1999-2004 Christoph Bartelmus <lirc@bartelmus.de>
8 *
9 */
10
17 #ifdef HAVE_CONFIG_H
18 # include <config.h>
19 #endif
20
21 /* if the gap is lower than this value, we will concatenate the
22 * signals and send the signal chain at a single blow */
23 #define LIRCD_EXACT_GAP_THRESHOLD 10000
24
25 #ifdef HAVE_KERNEL_LIRC_H
26 #include <linux/lirc.h>
27 #else
28 #include "include/media/lirc.h"
29 #endif
30
31 #include "lirc/lirc_log.h"
32 #include "lirc/transmit.h"
33
34 static const logchannel_t logchannel = LOG_LIB;
35
39 static struct sbuf {
40 lirc_t* data;
41
42 lirc_t _data[WBUF_SIZE];
43 int wptr;
44 int too_long;
45 int is_biphase;
46 lirc_t pendingp;
47 lirc_t pendings;
48 lirc_t sum;
49 } send_buffer;
50
51
52 static void send_signals(lirc_t* signals, int n);
53 static int init_send_or_sim(struct ir_remote* remote, struct ir_ncode* code, int sim, int repeat_preset);
54
55 /*
56 * sending stuff
57 */
58
62 void send_buffer_init(void)
63 {
64 memset(&send_buffer, 0, sizeof(send_buffer));
65 }
66
67 static void clear_send_buffer(void)
68 {
69 log_trace2("clearing transmit buffer");
70 send_buffer.wptr = 0;
71 send_buffer.too_long = 0;
72 send_buffer.is_biphase = 0;
73 send_buffer.pendingp = 0;
74 send_buffer.pendings = 0;
75 send_buffer.sum = 0;
76 }
77
78 static void add_send_buffer(lirc_t data)
79 {
80 if (send_buffer.wptr < WBUF_SIZE) {
81 log_trace2("adding to transmit buffer: %u", data);
82 send_buffer.sum += data;
83 send_buffer._data[send_buffer.wptr] = data;
84 send_buffer.wptr++;
85 } else {
86 send_buffer.too_long = 1;
87 }
88 }
89
90 static void send_pulse(lirc_t data)
91 {
92 if (send_buffer.pendingp > 0) {
93 send_buffer.pendingp += data;
94 } else {
95 if (send_buffer.pendings > 0) {
96 add_send_buffer(send_buffer.pendings);
97 send_buffer.pendings = 0;
98 }
99 send_buffer.pendingp = data;
100 }
101 }
102
103 static void send_space(lirc_t data)
104 {
105 if (send_buffer.wptr == 0 && send_buffer.pendingp == 0) {
106 log_trace("first signal is a space!");
107 return;
108 }
109 if (send_buffer.pendings > 0) {
110 send_buffer.pendings += data;
111 } else {
112 if (send_buffer.pendingp > 0) {
113 add_send_buffer(send_buffer.pendingp);
114 send_buffer.pendingp = 0;
115 }
116 send_buffer.pendings = data;
117 }
118 }
119
120 static int bad_send_buffer(void)
121 {
122 if (send_buffer.too_long != 0)
123 return 1;
124 if (send_buffer.wptr == WBUF_SIZE && send_buffer.pendingp > 0)
125 return 1;
126 return 0;
127 }
128
129 static int check_send_buffer(void)
130 {
131 int i;
132
133 if (send_buffer.wptr == 0) {
134 log_trace("nothing to send");
135 return 0;
136 }
137 for (i = 0; i < send_buffer.wptr; i++) {
138 if (send_buffer.data[i] == 0) {
139 if (i % 2) {
140 log_trace("invalid space: %d", i);
141 } else {
142 log_trace("invalid pulse: %d", i);
143 }
144 return 0;
145 }
146 }
147
148 return 1;
149 }
150
151 static void flush_send_buffer(void)
152 {
153 if (send_buffer.pendingp > 0) {
154 add_send_buffer(send_buffer.pendingp);
155 send_buffer.pendingp = 0;
156 }
157 if (send_buffer.pendings > 0) {
158 add_send_buffer(send_buffer.pendings);
159 send_buffer.pendings = 0;
160 }
161 }
162
163 static void sync_send_buffer(void)
164 {
165 if (send_buffer.pendingp > 0) {
166 add_send_buffer(send_buffer.pendingp);
167 send_buffer.pendingp = 0;
168 }
169 if (send_buffer.wptr > 0 && send_buffer.wptr % 2 == 0)
170 send_buffer.wptr--;
171 }
172
173 static void send_header(struct ir_remote* remote)
174 {
175 if (has_header(remote)) {
176 send_pulse(remote->phead);
177 send_space(remote->shead);
178 }
179 }
180
181 static void send_foot(struct ir_remote* remote)
182 {
183 if (has_foot(remote)) {
184 send_space(remote->sfoot);
185 send_pulse(remote->pfoot);
186 }
187 }
188
189 static void send_lead(struct ir_remote* remote)
190 {
191 if (remote->plead != 0)
192 send_pulse(remote->plead);
193 }
194
195 static void send_trail(struct ir_remote* remote)
196 {
197 if (remote->ptrail != 0)
198 send_pulse(remote->ptrail);
199 }
200
201 static void send_data(struct ir_remote* remote, ir_code data, int bits, int done)
202 {
203 int i;
204 int all_bits = bit_count(remote);
205 int toggle_bit_mask_bits = bits_set(remote->toggle_bit_mask);
206 ir_code mask;
207
208 data = reverse(data, bits);
209 if (is_rcmm(remote)) {
210 mask = 1 << (all_bits - 1 - done);
211 if (bits % 2 || done % 2) {
212 log_error("invalid bit number.");
213 return;
214 }
215 for (i = 0; i < bits; i += 2, mask >>= 2) {
216 switch (data & 3) {
217 case 0:
218 send_pulse(remote->pzero);
219 send_space(remote->szero);
220 break;
221 /* 2 and 1 swapped due to reverse() */
222 case 2:
223 send_pulse(remote->pone);
224 send_space(remote->sone);
225 break;
226 case 1:
227 send_pulse(remote->ptwo);
228 send_space(remote->stwo);
229 break;
230 case 3:
231 send_pulse(remote->pthree);
232 send_space(remote->sthree);
233 break;
234 }
235 data = data >> 2;
236 }
237 return;
238 } else if (is_xmp(remote)) {
239 if (bits % 4 || done % 4) {
240 log_error("invalid bit number.");
241 return;
242 }
243 for (i = 0; i < bits; i += 4) {
244 ir_code nibble;
245
246 nibble = reverse(data & 0xf, 4);
247 send_pulse(remote->pzero);
248 send_space(remote->szero + nibble * remote->sone);
249 data >>= 4;
250 }
251 return;
252 }
253
254 mask = ((ir_code)1) << (all_bits - 1 - done);
255 for (i = 0; i < bits; i++, mask >>= 1) {
256 if (has_toggle_bit_mask(remote) && mask & remote->toggle_bit_mask) {
257 if (toggle_bit_mask_bits == 1) {
258 /* backwards compatibility */
259 data &= ~((ir_code)1);
260 if (remote->toggle_bit_mask_state & mask)
261 data |= (ir_code)1;
262 } else {
263 if (remote->toggle_bit_mask_state & mask)
264 data ^= (ir_code)1;
265 }
266 }
267 if (has_toggle_mask(remote) && mask & remote->toggle_mask && remote->toggle_mask_state % 2)
268 data ^= 1;
269 if (data & 1) {
270 if (is_biphase(remote)) {
271 if (mask & remote->rc6_mask) {
272 send_space(2 * remote->sone);
273 send_pulse(2 * remote->pone);
274 } else {
275 send_space(remote->sone);
276 send_pulse(remote->pone);
277 }
278 } else if (is_space_first(remote)) {
279 send_space(remote->sone);
280 send_pulse(remote->pone);
281 } else {
282 send_pulse(remote->pone);
283 send_space(remote->sone);
284 }
285 } else {
286 if (mask & remote->rc6_mask) {
287 send_pulse(2 * remote->pzero);
288 send_space(2 * remote->szero);
289 } else if (is_space_first(remote)) {
290 send_space(remote->szero);
291 send_pulse(remote->pzero);
292 } else {
293 send_pulse(remote->pzero);
294 send_space(remote->szero);
295 }
296 }
297 data = data >> 1;
298 }
299 }
300
301 static void send_pre(struct ir_remote* remote)
302 {
303 if (has_pre(remote)) {
304 send_data(remote, remote->pre_data, remote->pre_data_bits, 0);
305 if (remote->pre_p > 0 && remote->pre_s > 0) {
306 send_pulse(remote->pre_p);
307 send_space(remote->pre_s);
308 }
309 }
310 }
311
312 static void send_post(struct ir_remote* remote)
313 {
314 if (has_post(remote)) {
315 if (remote->post_p > 0 && remote->post_s > 0) {
316 send_pulse(remote->post_p);
317 send_space(remote->post_s);
318 }
319 send_data(remote, remote->post_data, remote->post_data_bits, remote->pre_data_bits + remote->bits);
320 }
321 }
322
323 static void send_repeat(struct ir_remote* remote)
324 {
325 send_lead(remote);
326 send_pulse(remote->prepeat);
327 send_space(remote->srepeat);
328 send_trail(remote);
329 }
330
331 static void send_code(struct ir_remote* remote, ir_code code, int repeat)
332 {
333 if (!repeat || !(remote->flags & NO_HEAD_REP))
334 send_header(remote);
335 send_lead(remote);
336 send_pre(remote);
337 send_data(remote, code, remote->bits, remote->pre_data_bits);
338 send_post(remote);
339 send_trail(remote);
340 if (!repeat || !(remote->flags & NO_FOOT_REP))
341 send_foot(remote);
342
343 if (!repeat && remote->flags & NO_HEAD_REP && remote->flags & CONST_LENGTH)
344 send_buffer.sum -= remote->phead + remote->shead;
345 }
346
347 static void send_signals(lirc_t* signals, int n)
348 {
349 int i;
350
351 for (i = 0; i < n; i++)
352 add_send_buffer(signals[i]);
353 }
354
355 int send_buffer_put(struct ir_remote* remote, struct ir_ncode* code)
356 {
357 return init_send_or_sim(remote, code, 0, 0);
358 }
359
364 int init_sim(struct ir_remote* remote, struct ir_ncode* code, int repeat_preset)
365 {
366 return init_send_or_sim(remote, code, 1, repeat_preset);
367 }
373 int send_buffer_length(void)
374 {
375 return send_buffer.wptr;
376 }
377
378
379 const lirc_t* send_buffer_data(void)
380 {
381 return send_buffer.data;
382 }
383
384 lirc_t send_buffer_sum(void)
385 {
386 return send_buffer.sum;
387 }
388
389 static int init_send_or_sim(struct ir_remote* remote, struct ir_ncode* code, int sim, int repeat_preset)
390 {
391 int i, repeat = repeat_preset;
392
393 if (is_grundig(remote) || is_goldstar(remote) || is_serial(remote) || is_bo(remote)) {
394 if (!sim)
395 log_error("sorry, can't send this protocol yet");
396 return 0;
397 }
398 clear_send_buffer();
399 if (strcmp(remote->name, "lirc") == 0) {
400 send_buffer.data[send_buffer.wptr] = LIRC_EOF | 1;
401 send_buffer.wptr += 1;
402 goto final_check;
403 }
404
405 if (is_biphase(remote))
406 send_buffer.is_biphase = 1;
407 if (!sim) {
408 if (repeat_remote == NULL)
409 remote->repeat_countdown = remote->min_repeat;
410 else
411 repeat = 1;
412 }
413
414 init_send_loop:
415 if (repeat && has_repeat(remote)) {
416 if (remote->flags & REPEAT_HEADER && has_header(remote))
417 send_header(remote);
418 send_repeat(remote);
419 } else {
420 if (!is_raw(remote)) {
421 ir_code next_code;
422
423 if (sim || code->transmit_state == NULL)
424 next_code = code->code;
425 else
426 next_code = code->transmit_state->code;
427
428 if (repeat && has_repeat_mask(remote))
429 next_code ^= remote->repeat_mask;
430
431 send_code(remote, next_code, repeat);
432 if (!sim && has_toggle_mask(remote)) {
433 remote->toggle_mask_state++;
434 if (remote->toggle_mask_state == 4)
435 remote->toggle_mask_state = 2;
436 }
437 send_buffer.data = send_buffer._data;
438 } else {
439 if (code->signals == NULL) {
440 if (!sim)
441 log_error("no signals for raw send");
442 return 0;
443 }
444 if (send_buffer.wptr > 0) {
445 send_signals(code->signals, code->length);
446 } else {
447 send_buffer.data = code->signals;
448 send_buffer.wptr = code->length;
449 for (i = 0; i < code->length; i++)
450 send_buffer.sum += code->signals[i];
451 }
452 }
453 }
454 sync_send_buffer();
455 if (bad_send_buffer()) {
456 if (!sim)
457 log_error("buffer too small");
458 return 0;
459 }
460 if (sim)
461 goto final_check;
462
463 if (has_repeat_gap(remote) && repeat && has_repeat(remote)) {
464 remote->min_remaining_gap = remote->repeat_gap;
465 remote->max_remaining_gap = remote->repeat_gap;
466 } else if (is_const(remote)) {
467 if (min_gap(remote) > send_buffer.sum) {
468 remote->min_remaining_gap = min_gap(remote) - send_buffer.sum;
469 remote->max_remaining_gap = max_gap(remote) - send_buffer.sum;
470 } else {
471 log_error("too short gap: %u", remote->gap);
472 remote->min_remaining_gap = min_gap(remote);
473 remote->max_remaining_gap = max_gap(remote);
474 return 0;
475 }
476 } else {
477 remote->min_remaining_gap = min_gap(remote);
478 remote->max_remaining_gap = max_gap(remote);
479 }
480 /* update transmit state */
481 if (code->next != NULL) {
482 if (code->transmit_state == NULL) {
483 code->transmit_state = code->next;
484 } else {
485 code->transmit_state = code->transmit_state->next;
486 if (is_xmp(remote) && code->transmit_state == NULL)
487 code->transmit_state = code->next;
488 }
489 }
490 if ((remote->repeat_countdown > 0 || code->transmit_state != NULL)
491 && remote->min_remaining_gap < LIRCD_EXACT_GAP_THRESHOLD) {
492 if (send_buffer.data != send_buffer._data) {
493 lirc_t* signals;
494 int n;
495
496 log_trace("unrolling raw signal optimisation");
497 signals = send_buffer.data;
498 n = send_buffer.wptr;
499 send_buffer.data = send_buffer._data;
500 send_buffer.wptr = 0;
501
502 send_signals(signals, n);
503 }
504 log_trace("concatenating low gap signals");
505 if (code->next == NULL || code->transmit_state == NULL)
506 remote->repeat_countdown--;
507 send_space(remote->min_remaining_gap);
508 flush_send_buffer();
509 send_buffer.sum = 0;
510
511 repeat = 1;
512 goto init_send_loop;
513 }
514 log_trace2("transmit buffer ready");
515
516 final_check:
517 if (!check_send_buffer()) {
518 if (!sim) {
519 log_error("invalid send buffer");
520 log_error("this remote configuration cannot be used to transmit");
521 }
522 return 0;
523 }
524 return 1;
525 }
ir_remote::min_remaining_gap
lirc_t min_remaining_gap
Definition: ir_remote_types.h:244
ir_remote
Definition: ir_remote_types.h:167
ir_remote::bits
int bits
Definition: ir_remote_types.h:171
send_buffer_data
const lirc_t * send_buffer_data(void)
Definition: transmit.c:379
NO_FOOT_REP
#define NO_FOOT_REP
Definition: ir_remote_types.h:136
ir_remote::post_data
ir_code post_data
Definition: ir_remote_types.h:199
ir_remote::post_s
lirc_t post_s
Definition: ir_remote_types.h:201
ir_remote::plead
lirc_t plead
Definition: ir_remote_types.h:191
ir_remote::repeat_mask
ir_code repeat_mask
Definition: ir_remote_types.h:234
ir_ncode::next
struct ir_code_node * next
Definition: ir_remote_types.h:91
ir_remote::name
const char * name
Definition: ir_remote_types.h:168
ir_ncode::signals
lirc_t * signals
Definition: ir_remote_types.h:87
LIRC_EOF
#define LIRC_EOF
Definition: lirc_config.h:104
ir_code
__u64 ir_code
Definition: ir_remote_types.h:59
ir_remote::sfoot
lirc_t sfoot
Definition: ir_remote_types.h:193
ir_remote::ptrail
lirc_t ptrail
Definition: ir_remote_types.h:192
ir_remote::pre_data_bits
int pre_data_bits
Definition: ir_remote_types.h:196
logchannel_t
logchannel_t
Definition: lirc_log.h:53
log_trace2
#define log_trace2(fmt,...)
Definition: lirc_log.h:139
ir_remote::post_data_bits
int post_data_bits
Definition: ir_remote_types.h:198
ir_remote::sthree
lirc_t sthree
Definition: ir_remote_types.h:187
ir_remote::toggle_mask
ir_code toggle_mask
Definition: ir_remote_types.h:222
log_error
#define log_error(fmt,...)
Definition: lirc_log.h:104
ir_remote::pre_data
ir_code pre_data
Definition: ir_remote_types.h:197
send_buffer_sum
lirc_t send_buffer_sum(void)
Definition: transmit.c:384
log_trace
#define log_trace(fmt,...)
Definition: lirc_log.h:129
ir_remote::sone
lirc_t sone
Definition: ir_remote_types.h:189
send_buffer_init
void send_buffer_init(void)
Definition: transmit.c:62
ir_remote::shead
lirc_t shead
Definition: ir_remote_types.h:186
REPEAT_HEADER
#define REPEAT_HEADER
Definition: ir_remote_types.h:138
send_buffer_put
int send_buffer_put(struct ir_remote *remote, struct ir_ncode *code)
Definition: transmit.c:355
ir_remote::repeat_gap
__u32 repeat_gap
Definition: ir_remote_types.h:205
ir_remote::gap
__u32 gap
Definition: ir_remote_types.h:203
CONST_LENGTH
#define CONST_LENGTH
Definition: ir_remote_types.h:137
NO_HEAD_REP
#define NO_HEAD_REP
Definition: ir_remote_types.h:135
ir_remote::pre_s
lirc_t pre_s
Definition: ir_remote_types.h:200
ir_remote::szero
lirc_t szero
Definition: ir_remote_types.h:190
ir_ncode
Definition: ir_remote_types.h:76
ir_remote::stwo
lirc_t stwo
Definition: ir_remote_types.h:188
ir_remote::flags
int flags
Definition: ir_remote_types.h:172
ir_remote::srepeat
lirc_t srepeat
Definition: ir_remote_types.h:194
ir_ncode::transmit_state
struct ir_code_node * transmit_state
Definition: ir_remote_types.h:98
ir_remote::max_remaining_gap
lirc_t max_remaining_gap
Definition: ir_remote_types.h:245
ir_ncode::code
ir_code code
Definition: ir_remote_types.h:81
ir_remote::rc6_mask
ir_code rc6_mask
Definition: ir_remote_types.h:223
send_buffer_length
int send_buffer_length(void)
Definition: transmit.c:373
repeat_remote
struct ir_remote * repeat_remote
Definition: ir_remote.c:60
ir_remote::toggle_bit_mask
ir_code toggle_bit_mask
Definition: ir_remote_types.h:207
ir_remote::min_repeat
int min_repeat
Definition: ir_remote_types.h:211
ir_ncode::length
int length
Definition: ir_remote_types.h:84