23#define LIRCD_EXACT_GAP_THRESHOLD 10000
25#ifdef HAVE_KERNEL_LIRC_H
26#include <linux/lirc.h>
28#include "media/lirc.h"
31#include "lirc/lirc_log.h"
32#include "lirc/transmit.h"
42 lirc_t _data[WBUF_SIZE];
52static void send_signals(lirc_t* signals,
int n);
53static int init_send_or_sim(
struct ir_remote* remote,
struct ir_ncode* code,
int sim,
int repeat_preset);
64 memset(&send_buffer, 0,
sizeof(send_buffer));
67static void clear_send_buffer(
void)
71 send_buffer.too_long = 0;
72 send_buffer.is_biphase = 0;
73 send_buffer.pendingp = 0;
74 send_buffer.pendings = 0;
78static void add_send_buffer(lirc_t data)
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;
86 send_buffer.too_long = 1;
90static void send_pulse(lirc_t data)
92 if (send_buffer.pendingp > 0) {
93 send_buffer.pendingp += data;
95 if (send_buffer.pendings > 0) {
96 add_send_buffer(send_buffer.pendings);
97 send_buffer.pendings = 0;
99 send_buffer.pendingp = data;
103static void send_space(lirc_t data)
105 if (send_buffer.wptr == 0 && send_buffer.pendingp == 0) {
109 if (send_buffer.pendings > 0) {
110 send_buffer.pendings += data;
112 if (send_buffer.pendingp > 0) {
113 add_send_buffer(send_buffer.pendingp);
114 send_buffer.pendingp = 0;
116 send_buffer.pendings = data;
120static int bad_send_buffer(
void)
122 if (send_buffer.too_long != 0)
124 if (send_buffer.wptr == WBUF_SIZE && send_buffer.pendingp > 0)
129static int check_send_buffer(
void)
133 if (send_buffer.wptr == 0) {
137 for (i = 0; i < send_buffer.wptr; i++) {
138 if (send_buffer.data[i] == 0) {
151static void flush_send_buffer(
void)
153 if (send_buffer.pendingp > 0) {
154 add_send_buffer(send_buffer.pendingp);
155 send_buffer.pendingp = 0;
157 if (send_buffer.pendings > 0) {
158 add_send_buffer(send_buffer.pendings);
159 send_buffer.pendings = 0;
163static void sync_send_buffer(
void)
165 if (send_buffer.pendingp > 0) {
166 add_send_buffer(send_buffer.pendingp);
167 send_buffer.pendingp = 0;
169 if (send_buffer.wptr > 0 && send_buffer.wptr % 2 == 0)
173static void send_header(
struct ir_remote* remote)
175 if (has_header(remote)) {
176 send_pulse(remote->phead);
177 send_space(remote->shead);
181static void send_foot(
struct ir_remote* remote)
183 if (has_foot(remote)) {
184 send_space(remote->sfoot);
185 send_pulse(remote->pfoot);
189static void send_lead(
struct ir_remote* remote)
191 if (remote->plead != 0)
192 send_pulse(remote->plead);
195static void send_trail(
struct ir_remote* remote)
197 if (remote->ptrail != 0)
198 send_pulse(remote->ptrail);
201static void send_data(
struct ir_remote* remote,
ir_code data,
int bits,
int done)
204 int all_bits = bit_count(remote);
205 int toggle_bit_mask_bits = bits_set(remote->toggle_bit_mask);
208 data = reverse(data, bits);
209 if (is_rcmm(remote)) {
210 mask = 1 << (all_bits - 1 - done);
211 if (bits % 2 || done % 2) {
215 for (i = 0; i < bits; i += 2, mask >>= 2) {
218 send_pulse(remote->pzero);
219 send_space(remote->szero);
223 send_pulse(remote->pone);
224 send_space(remote->sone);
227 send_pulse(remote->ptwo);
228 send_space(remote->stwo);
231 send_pulse(remote->pthree);
232 send_space(remote->sthree);
238 }
else if (is_xmp(remote)) {
239 if (bits % 4 || done % 4) {
243 for (i = 0; i < bits; i += 4) {
246 nibble = reverse(data & 0xf, 4);
247 send_pulse(remote->pzero);
248 send_space(remote->szero + nibble * remote->sone);
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) {
260 if (remote->toggle_bit_mask_state & mask)
263 if (remote->toggle_bit_mask_state & mask)
267 if (has_toggle_mask(remote) && mask & remote->toggle_mask && remote->toggle_mask_state % 2)
270 if (is_biphase(remote)) {
271 if (mask & remote->rc6_mask) {
272 send_space(2 * remote->sone);
273 send_pulse(2 * remote->pone);
275 send_space(remote->sone);
276 send_pulse(remote->pone);
278 }
else if (is_space_first(remote)) {
279 send_space(remote->sone);
280 send_pulse(remote->pone);
282 send_pulse(remote->pone);
283 send_space(remote->sone);
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);
293 send_pulse(remote->pzero);
294 send_space(remote->szero);
301static void send_pre(
struct ir_remote* remote)
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);
312static void send_post(
struct ir_remote* remote)
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);
319 send_data(remote, remote->post_data, remote->post_data_bits, remote->pre_data_bits + remote->bits);
323static void send_repeat(
struct ir_remote* remote)
326 send_pulse(remote->prepeat);
327 send_space(remote->srepeat);
337 send_data(remote, code, remote->bits, remote->pre_data_bits);
344 send_buffer.sum -= remote->phead + remote->shead;
347static void send_signals(lirc_t* signals,
int n)
351 for (i = 0; i < n; i++)
352 add_send_buffer(signals[i]);
357 return init_send_or_sim(remote, code, 0, 0);
366 return init_send_or_sim(remote, code, 1, repeat_preset);
375 return send_buffer.wptr;
381 return send_buffer.data;
386 return send_buffer.sum;
389static int init_send_or_sim(
struct ir_remote* remote,
struct ir_ncode* code,
int sim,
int repeat_preset)
391 int i, repeat = repeat_preset;
393 if (is_grundig(remote) || is_goldstar(remote) || is_serial(remote) || is_bo(remote)) {
395 log_error(
"sorry, can't send this protocol yet");
399 if (strcmp(remote->name,
"lirc") == 0) {
400 send_buffer.data[send_buffer.wptr] =
LIRC_EOF | 1;
401 send_buffer.wptr += 1;
405 if (is_biphase(remote))
406 send_buffer.is_biphase = 1;
409 remote->repeat_countdown = remote->min_repeat;
415 if (repeat && has_repeat(remote)) {
420 if (!is_raw(remote)) {
423 if (sim || code->transmit_state == NULL)
424 next_code = code->code;
426 next_code = code->transmit_state->code;
428 if (repeat && has_repeat_mask(remote))
429 next_code ^= remote->repeat_mask;
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;
437 send_buffer.data = send_buffer._data;
439 if (code->signals == NULL) {
444 if (send_buffer.wptr > 0) {
445 send_signals(code->signals, code->length);
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];
455 if (bad_send_buffer()) {
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;
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);
477 remote->min_remaining_gap = min_gap(remote);
478 remote->max_remaining_gap = max_gap(remote);
481 if (code->next != NULL) {
482 if (code->transmit_state == NULL) {
483 code->transmit_state = code->next;
485 code->transmit_state = code->transmit_state->next;
486 if (is_xmp(remote) && code->transmit_state == NULL)
487 code->transmit_state = code->next;
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) {
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;
502 send_signals(signals, n);
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);
517 if (!check_send_buffer()) {
520 log_error(
"this remote configuration cannot be used to transmit");
int send_buffer_put(struct ir_remote *remote, struct ir_ncode *code)
Initializes the global send buffer for transmitting the code in the second argument,...
lirc_t send_buffer_sum(void)
struct ir_remote * repeat_remote
Global pointer to the remote that contains the code currently repeating.
void send_buffer_init(void)
Initializes the global sending buffer.
const lirc_t * send_buffer_data(void)
int send_buffer_length(void)
Do not document this function.
#define REPEAT_HEADER
header is also sent before repeat code
uint64_t ir_code
Denotes an internal coded representation for an IR transmission.
#define NO_FOOT_REP
no foot for key repeats
#define NO_HEAD_REP
no header for key repeats
#define CONST_LENGTH
signal length+gap is always constant
#define LIRC_EOF
Bit manipulator in lirc_t, see lirc.h .
#define log_trace(fmt,...)
Log a trace message.
#define log_trace2(fmt,...)
Log a trace2 message.
#define log_error(fmt,...)
Log an error message.
logchannel_t
Log channels used to filter messages.
IR Command, corresponding to one (command defining) line of the configuration file.
One remote as represented in the configuration file.