inline int get_repeat(struct ir_remote *remote)
{
	if (!get_lead(remote))
		return (0);
	if (is_biphase(remote)) {
		if (!expectspace(remote, remote->srepeat))
			return (0);
		if (!expectpulse(remote, remote->prepeat))
			return (0);
	} else {
		if (!expectpulse(remote, remote->prepeat))
			return (0);
		set_pending_space(remote->srepeat);
	}
	if (!get_trail(remote))
		return (0);
	if (!get_gap
	    (remote,
	     is_const(remote) ? (min_gap(remote) >
				 rec_buffer.sum ? min_gap(remote) -
				 rec_buffer.sum : 0) : (has_repeat_gap(remote) ? remote->repeat_gap : min_gap(remote))
	    ))
		return (0);
	return (1);
}
Beispiel #2
0
static int sanityChecks(struct ir_remote *rem)
{
	struct ir_ncode *codes;
	struct ir_code_node *node;

	if (!rem->name)
	{
		logprintf(LOG_ERR,"you must specify a remote name");
		return 0;
	}
	if(rem->gap == 0)
	{
		logprintf(LOG_WARNING, "you should specify a valid gap value");
	}
	if(has_repeat_gap(rem) && is_const(rem))
	{
		logprintf(LOG_WARNING, "repeat_gap will be ignored if "
			  "CONST_LENGTH flag is set");
	}

	if(is_raw(rem)) return 1;

	if((rem->pre_data&gen_mask(rem->pre_data_bits)) != rem->pre_data)
	{
		logprintf(LOG_WARNING, "invalid pre_data found for %s",
			  rem->name);
		rem->pre_data &= gen_mask(rem->pre_data_bits);
	}
	if((rem->post_data&gen_mask(rem->post_data_bits)) != rem->post_data)
	{
		logprintf(LOG_WARNING, "invalid post_data found for %s",
			  rem->name);
		rem->post_data &= gen_mask(rem->post_data_bits);
	}
	for(codes = rem->codes; codes->name != NULL; codes++)
	{
		if((codes->code&gen_mask(rem->bits)) != codes->code)
		{
			logprintf(LOG_WARNING, "invalid code found for %s: %s",
				  rem->name, codes->name);
			codes->code &= gen_mask(rem->bits);
		}
		for(node = codes->next; node != NULL; node = node->next)
		{
			if((node->code&gen_mask(rem->bits)) != node->code)
			{
				logprintf(LOG_WARNING, "invalid code found "
					 "for %s: %s",
					  rem->name, codes->name);
				node->code &= gen_mask(rem->bits);
			}
		}
	}

	return 1;
}
Beispiel #3
0
void fprint_remote_head(FILE *f, struct ir_remote *rem)
{
	fprintf(f, "begin remote\n\n");
	if(!is_raw(rem)){
		fprintf(f, "  name  %s\n",rem->name);
		fprintf(f, "  bits        %5d\n",rem->bits);
		fprint_flags(f,rem->flags);
		fprintf(f, "  eps         %5d\n",rem->eps);
		fprintf(f, "  aeps        %5d\n\n",rem->aeps);
		if(has_header(rem))
		{
			fprintf(f, "  header      %5lu %5lu\n",
				(unsigned long) rem->phead,
				(unsigned long) rem->shead);
		}
		if(rem->pthree!=0 || rem->sthree!=0)
			fprintf(f, "  three       %5lu %5lu\n",
				(unsigned long) rem->pthree,
				(unsigned long) rem->sthree);
		if(rem->ptwo!=0 || rem->stwo!=0)
			fprintf(f, "  two         %5lu %5lu\n",
				(unsigned long) rem->ptwo,
				(unsigned long)  rem->stwo);
		fprintf(f, "  one         %5lu %5lu\n",
			(unsigned long) rem->pone,
			(unsigned long) rem->sone);
		fprintf(f, "  zero        %5lu %5lu\n",
			(unsigned long) rem->pzero,
			(unsigned long)  rem->szero);
		if(rem->ptrail!=0)
		{
			fprintf(f, "  ptrail      %5lu\n",
				(unsigned long) rem->ptrail);
		}
		if(rem->plead!=0)
		{
			fprintf(f, "  plead       %5lu\n",
				(unsigned long) rem->plead);
		}
		if(has_foot(rem))
		{
			fprintf(f, "  foot        %5lu %5lu\n",
				(unsigned long) rem->pfoot,
				(unsigned long) rem->sfoot);
		}
		if(has_repeat(rem))
		{
			fprintf(f, "  repeat      %5lu %5lu\n",
				(unsigned long) rem->prepeat,
				(unsigned long) rem->srepeat);
		}
		if(rem->pre_data_bits>0)
		{
			fprintf(f, "  pre_data_bits   %d\n",rem->pre_data_bits);
#                       ifdef LONG_IR_CODE
			fprintf(f, "  pre_data       0x%llX\n",rem->pre_data);
#                       else
			fprintf(f, "  pre_data       0x%lX\n",rem->pre_data);
#                       endif
		}
		if(rem->post_data_bits>0)
		{
			fprintf(f, "  post_data_bits  %d\n",rem->post_data_bits);
#                       ifdef LONG_IR_CODE
			fprintf(f, "  post_data      0x%llX\n",rem->post_data);
#                       else
			fprintf(f, "  post_data      0x%lX\n",rem->post_data);
#                       endif
		}
		if(rem->pre_p!=0 && rem->pre_s!=0)
		{
			fprintf(f, "  pre         %5lu %5lu\n",
				(unsigned long) rem->pre_p,
				(unsigned long) rem->pre_s);
		}
		if(rem->post_p!=0 && rem->post_s!=0)
		{
			fprintf(f, "  post        %5lu %5lu\n",
				(unsigned long) rem->post_p,
				(unsigned long) rem->post_s);
		}
		fprintf(f, "  gap          %lu\n",
			(unsigned long) rem->gap);
		if(has_repeat_gap(rem))
		{
			fprintf(f, "  repeat_gap   %lu\n",
				(unsigned long) rem->repeat_gap);
		}
		if(rem->min_repeat>0)
		{
			fprintf(f, "  min_repeat      %d\n",rem->min_repeat);
		}
		if(rem->min_code_repeat>0)
		{
			fprintf(f, "  min_code_repeat %d\n",
				rem->min_code_repeat);
		}
#               ifdef LONG_IR_CODE
		fprintf(f, "  toggle_bit_mask 0x%llX\n",
			rem->toggle_bit_mask);
#               else
		fprintf(f, "  toggle_bit_mask 0x%lX\n",
			rem->toggle_bit_mask);
#               endif
		if(has_toggle_mask(rem))
		{
#                       ifdef LONG_IR_CODE
			fprintf(f, "  toggle_mask    0x%llX\n",
				rem->toggle_mask);
#                       else
			fprintf(f, "  toggle_mask    0x%lX\n",
				rem->toggle_mask);
#                       endif
		}
		if(rem->rc6_mask!=0)
		{
#                       ifdef LONG_IR_CODE
			fprintf(f, "  rc6_mask    0x%llX\n",
				rem->rc6_mask);
#                       else
			fprintf(f, "  rc6_mask    0x%lX\n",
				rem->rc6_mask);
#                       endif
		}
		if(is_serial(rem))
		{
			fprintf(f, "  baud            %d\n",rem->baud);
			fprintf(f, "  serial_mode     %dN%d%s\n",
				rem->bits_in_byte,
				rem->stop_bits/2,
				rem->stop_bits%2 ? ".5":"");
		}
	}
	else
	{
		fprintf(f, "  name   %s\n",rem->name);
		fprint_flags(f,rem->flags);
		fprintf(f, "  eps         %5d\n",rem->eps);
		fprintf(f, "  aeps        %5d\n\n",rem->aeps);
		fprintf(f, "  ptrail      %5lu\n",(unsigned long) rem->ptrail);
		fprintf(f, "  repeat %5lu %5lu\n",
			(unsigned long) rem->prepeat,
			(unsigned long) rem->srepeat);
		fprintf(f, "  gap    %lu\n",(unsigned long) rem->gap);
	}
	if(rem->freq!=0)
	{
		fprintf(f, "  frequency    %u\n",rem->freq);
	}
	if(rem->duty_cycle!=0)
	{
		fprintf(f, "  duty_cycle   %u\n",rem->duty_cycle);
	}
	fprintf(f,"\n");
}
Beispiel #4
0
int receive_decode(struct ir_remote *remote,
		   ir_code *prep,ir_code *codep,ir_code *postp,
		   int *repeat_flagp,lirc_t *remaining_gapp)
{
	ir_code pre,code,post,code_mask=0,post_mask=0;
	lirc_t sync;
	int header;
	struct timeval current;

	sync=0; /* make compiler happy */
	code=pre=post=0;
	header=0;

	if(hw.rec_mode==LIRC_MODE_MODE2 ||
	   hw.rec_mode==LIRC_MODE_PULSE ||
	   hw.rec_mode==LIRC_MODE_RAW)
	{
		rewind_rec_buffer();
		rec_buffer.is_biphase=is_biphase(remote) ? 1:0;
		
		/* we should get a long space first */
		if(!(sync=sync_rec_buffer(remote)))
		{
			LOGPRINTF(1,"failed on sync");
			return(0);
		}

		LOGPRINTF(1,"sync");

		if(has_repeat(remote) && last_remote==remote)
		{
			if(remote->flags&REPEAT_HEADER && has_header(remote))
			{
				if(!get_header(remote))
				{
					LOGPRINTF(1,"failed on repeat "
						  "header");
					return(0);
				}
				LOGPRINTF(1,"repeat header");
			}
			if(get_repeat(remote))
			{
				if(remote->last_code==NULL)
				{
					logprintf(LOG_NOTICE,"repeat code "
						  "without last_code "
						  "received");
					return(0);
				}

				*prep=remote->pre_data;
				*codep=remote->last_code->code;
				*postp=remote->post_data;
				*repeat_flagp=1;

				*remaining_gapp=
				is_const(remote) ? 
				(remote->gap>rec_buffer.sum ?
				 remote->gap-rec_buffer.sum:0):
				(has_repeat_gap(remote) ?
				 remote->repeat_gap:remote->gap);
				return(1);
			}
			else
			{
				LOGPRINTF(1,"no repeat");
				rewind_rec_buffer();
				sync_rec_buffer(remote);
			}

		}

		if(has_header(remote))
		{
			header=1;
			if(!get_header(remote))
			{
				header=0;
				if(!(remote->flags&NO_HEAD_REP && 
				     (sync<=remote->gap+remote->gap*remote->eps/100
				      || sync<=remote->gap+remote->aeps)))
				{
					LOGPRINTF(1,"failed on header");
					return(0);
				}
			}
			LOGPRINTF(1,"header");
		}
	}

	if(is_raw(remote))
	{
		struct ir_ncode *codes,*found;
		int i;

		if(hw.rec_mode==LIRC_MODE_CODE ||
		   hw.rec_mode==LIRC_MODE_LIRCCODE)
			return(0);

		codes=remote->codes;
		found=NULL;
		while(codes->name!=NULL && found==NULL)
		{
			found=codes;
			for(i=0;i<codes->length;)
			{
				if(!expectpulse(remote,codes->signals[i++]))
				{
					found=NULL;
					rewind_rec_buffer();
					sync_rec_buffer(remote);
					break;
				}
				if(i<codes->length &&
				   !expectspace(remote,codes->signals[i++]))
				{
					found=NULL;
					rewind_rec_buffer();
					sync_rec_buffer(remote);
					break;
				}
			}
			codes++;
		}
		if(found!=NULL)
		{
			if(!get_gap(remote,
				    is_const(remote) ? 
				    remote->gap-rec_buffer.sum:
				    remote->gap)) 
				found=NULL;
		}
		if(found==NULL) return(0);
		code=found->code;
	}
	else
	{
		if(hw.rec_mode==LIRC_MODE_CODE ||
		   hw.rec_mode==LIRC_MODE_LIRCCODE)
		{
			int i;
 			lirc_t sum;

#                       ifdef LONG_IR_CODE
			LOGPRINTF(1,"decoded: %llx",rec_buffer.decoded);
#                       else
			LOGPRINTF(1,"decoded: %lx",rec_buffer.decoded);
#                       endif
			if((hw.rec_mode==LIRC_MODE_CODE &&
			    hw.code_length<remote->pre_data_bits
			    +remote->bits+remote->post_data_bits)
			   ||
			   (hw.rec_mode==LIRC_MODE_LIRCCODE && 
			    hw.code_length!=remote->pre_data_bits
			    +remote->bits+remote->post_data_bits))
			{
				return(0);
			}
			
			for(i=0;i<remote->post_data_bits;i++)
			{
				post_mask=(post_mask<<1)+1;
			}
			post=rec_buffer.decoded&post_mask;
			post_mask=0;
			rec_buffer.decoded=
			rec_buffer.decoded>>remote->post_data_bits;
			for(i=0;i<remote->bits;i++)
			{
				code_mask=(code_mask<<1)+1;
			}
			code=rec_buffer.decoded&code_mask;
			code_mask=0;
			pre=rec_buffer.decoded>>remote->bits;
			gettimeofday(&current,NULL);
			sum=remote->phead+remote->shead+
				lirc_t_max(remote->pone+remote->sone,
					   remote->pzero+remote->szero)*
				(remote->bits+
				 remote->pre_data_bits+
				 remote->post_data_bits)+
				remote->plead+
				remote->ptrail+
				remote->pfoot+remote->sfoot+
				remote->pre_p+remote->pre_s+
				remote->post_p+remote->post_s;
			
			rec_buffer.sum=sum>=remote->gap ? remote->gap-1:sum;
			sync=time_elapsed(&remote->last_send,&current)-
 				rec_buffer.sum;
		}
		else
		{
			if(!get_lead(remote))
Beispiel #5
0
void fprint_remote_head(FILE* f, const struct ir_remote* rem)
{
	fprintf(f, "begin remote\n\n");
	fprintf(f, "  name  %s\n", rem->name);
	if (rem->manual_sort)
		fprintf(f, "  manual_sort  %d\n", rem->manual_sort);
	if (rem->driver)
		fprintf(f, "  driver %s\n", rem->driver);
	if (!is_raw(rem))
		fprintf(f, "  bits        %5d\n", rem->bits);
	fprint_flags(f, rem->flags);
	fprintf(f, "  eps         %5d\n", rem->eps);
	fprintf(f, "  aeps        %5d\n\n", rem->aeps);
	if (!is_raw(rem)) {
		if (has_header(rem))
			fprintf(f, "  header      %5u %5u\n", (__u32)rem->phead, (__u32)rem->shead);
		if (rem->pthree != 0 || rem->sthree != 0)
			fprintf(f, "  three       %5u %5u\n", (__u32)rem->pthree, (__u32)rem->sthree);
		if (rem->ptwo != 0 || rem->stwo != 0)
			fprintf(f, "  two         %5u %5u\n", (__u32)rem->ptwo, (__u32)rem->stwo);
		fprintf(f, "  one         %5u %5u\n", (__u32)rem->pone, (__u32)rem->sone);
		fprintf(f, "  zero        %5u %5u\n", (__u32)rem->pzero, (__u32)rem->szero);
	}
	if (rem->ptrail != 0)
		fprintf(f, "  ptrail      %5u\n", (__u32)rem->ptrail);
	if (!is_raw(rem)) {
		if (rem->plead != 0)
			fprintf(f, "  plead       %5u\n", (__u32)rem->plead);
		if (has_foot(rem))
			fprintf(f, "  foot        %5u %5u\n", (__u32)rem->pfoot, (__u32)rem->sfoot);
	}
	if (has_repeat(rem))
		fprintf(f, "  repeat      %5u %5u\n", (__u32)rem->prepeat, (__u32)rem->srepeat);
	if (!is_raw(rem)) {
		if (rem->pre_data_bits > 0) {
			fprintf(f, "  pre_data_bits   %d\n", rem->pre_data_bits);
			fprintf(f, "  pre_data       0x%llX\n", (unsigned long long)rem->pre_data);
		}
		if (rem->post_data_bits > 0) {
			fprintf(f, "  post_data_bits  %d\n", rem->post_data_bits);
			fprintf(f, "  post_data      0x%llX\n", (unsigned long long)rem->post_data);
		}
		if (rem->pre_p != 0 && rem->pre_s != 0)
			fprintf(f, "  pre         %5u %5u\n", (__u32)rem->pre_p, (__u32)rem->pre_s);
		if (rem->post_p != 0 && rem->post_s != 0)
			fprintf(f, "  post        %5u %5u\n", (__u32)rem->post_p, (__u32)rem->post_s);
	}
	fprint_remote_gap(f, rem);
	if (has_repeat_gap(rem))
		fprintf(f, "  repeat_gap   %u\n", (__u32)rem->repeat_gap);
	if (rem->suppress_repeat > 0)
		fprintf(f, "  suppress_repeat %d\n", rem->suppress_repeat);
	if (rem->min_repeat > 0) {
		fprintf(f, "  min_repeat      %d\n", rem->min_repeat);
		if (rem->suppress_repeat == 0) {
			fprintf(f, "#  suppress_repeat %d\n", rem->min_repeat);
			fprintf(f, "#  uncomment to suppress unwanted repeats\n");
		}
	}
	if (!is_raw(rem)) {
		if (rem->min_code_repeat > 0)
			fprintf(f, "  min_code_repeat %d\n", rem->min_code_repeat);
		fprintf(f, "  toggle_bit_mask 0x%llX\n", (unsigned long long)rem->toggle_bit_mask);
		if (has_toggle_mask(rem))
			fprintf(f, "  toggle_mask    0x%llX\n", (unsigned long long)rem->toggle_mask);
		if (rem->repeat_mask != 0)
			fprintf(f, "  repeat_mask    0x%llX\n", (unsigned long long)rem->repeat_mask);
		if (rem->rc6_mask != 0)
			fprintf(f, "  rc6_mask    0x%llX\n", (unsigned long long)rem->rc6_mask);
		if (has_ignore_mask(rem))
			fprintf(f, "  ignore_mask 0x%llX\n", (unsigned long long)rem->ignore_mask);
		if (is_serial(rem)) {
			fprintf(f, "  baud            %d\n", rem->baud);
			fprintf(f, "  serial_mode     %dN%d%s\n", rem->bits_in_byte, rem->stop_bits / 2,
				rem->stop_bits % 2 ? ".5" : "");
		}
	}
	if (rem->freq != 0)
		fprintf(f, "  frequency    %u\n", rem->freq);
	if (rem->duty_cycle != 0)
		fprintf(f, "  duty_cycle   %u\n", rem->duty_cycle);
	fprintf(f, "\n");
}
Beispiel #6
0
int init_send(struct ir_remote *remote,struct ir_ncode *code)
{
	int i, repeat=0;
	
	if(is_grundig(remote) || 
	   is_goldstar(remote) || is_serial(remote) || is_bo(remote))
	{
		logprintf(LOG_ERR,"sorry, can't send this protocol yet");
		return(0);
	}
	clear_send_buffer();
	if(is_biphase(remote))
	{
		send_buffer.is_biphase=1;
	}
	if(repeat_remote==NULL)
	{
		remote->repeat_countdown=remote->min_repeat;
	}
	else
	{
		repeat = 1;
	}
	
 init_send_loop:
	if(repeat && has_repeat(remote))
	{
		if(remote->flags&REPEAT_HEADER && has_header(remote))
		{
			send_header(remote);
		}
		send_repeat(remote);
	}
	else
	{
		if(!is_raw(remote))
		{
			ir_code next_code;
			
			if(code->transmit_state == NULL)
			{
				next_code = code->code;
			}
			else
			{
				next_code = code->transmit_state->code;
			}
			send_code(remote, next_code, repeat);
			if(has_toggle_mask(remote))
			{
				remote->toggle_mask_state++;
				if(remote->toggle_mask_state==4)
				{
					remote->toggle_mask_state=2;
				}
			}
			send_buffer.data=send_buffer._data;
		}
		else
		{
			if(code->signals==NULL)
			{
				logprintf(LOG_ERR, "no signals for raw send");
				return 0;
			}
			if(send_buffer.wptr>0)
			{
				send_signals(code->signals, code->length);
			}
			else
			{
				send_buffer.data=code->signals;
				send_buffer.wptr=code->length;
				for(i=0; i<code->length; i++)
				{
					send_buffer.sum+=code->signals[i];
				}
			}
		}
	}
	sync_send_buffer();
	if(bad_send_buffer())
	{
		logprintf(LOG_ERR,"buffer too small");
		return(0);
	}
	if(has_repeat_gap(remote) && repeat && has_repeat(remote))
	{
		remote->min_remaining_gap=remote->repeat_gap;
		remote->max_remaining_gap=remote->repeat_gap;
	}
	else if(is_const(remote))
	{
		if(min_gap(remote)>send_buffer.sum)
		{
			remote->min_remaining_gap=min_gap(remote)-send_buffer.sum;
			remote->max_remaining_gap=max_gap(remote)-send_buffer.sum;
		}
		else
		{
			logprintf(LOG_ERR,"too short gap: %u",remote->gap);
			remote->min_remaining_gap=min_gap(remote);
			remote->max_remaining_gap=max_gap(remote);
			return(0);
		}
	}
	else
	{
		remote->min_remaining_gap=min_gap(remote);
		remote->max_remaining_gap=max_gap(remote);
	}
	/* update transmit state */
	if(code->next != NULL)
	{
		if(code->transmit_state == NULL)
		{
			code->transmit_state = code->next;
		}
		else
		{
			code->transmit_state = code->transmit_state->next;
		}
	}
	if((remote->repeat_countdown>0 || code->transmit_state != NULL) &&
	   remote->min_remaining_gap<LIRCD_EXACT_GAP_THRESHOLD)
	{
		if(send_buffer.data!=send_buffer._data)
		{
			lirc_t *signals;
			int n;
			
			LOGPRINTF(1, "unrolling raw signal optimisation");
			signals=send_buffer.data;
			n=send_buffer.wptr;
			send_buffer.data=send_buffer._data;
			send_buffer.wptr=0;
			
			send_signals(signals, n);
		}
		LOGPRINTF(1, "concatenating low gap signals");
		if(code->next == NULL || code->transmit_state == NULL)
		{
			remote->repeat_countdown--;
		}
		send_space(remote->min_remaining_gap);
		flush_send_buffer();
		send_buffer.sum=0;
		
		repeat = 1;
		goto init_send_loop;
	}
	LOGPRINTF(3, "transmit buffer ready");
	return(1);
}
struct ir_remote * read_config(FILE *f)
{
	char buf[LINE_LEN+1], *key, *val, *val2;
        int len,argc;
	struct ir_remote *top_rem=NULL,*rem=NULL;
        struct void_array codes_list,raw_codes,signals;
	struct ir_ncode raw_code={NULL,0,0,NULL};
	struct ir_ncode name_code={NULL,0,0,NULL};
	int mode=ID_none;

	line=0;
	parse_error=0;

	while(fgets(buf,LINE_LEN,f)!=NULL)
	{
		line++;
		len=strlen(buf);
		if(len==LINE_LEN && buf[len-1]!='\n')
		{
			logprintf(LOG_ERR,"line %d too long in config file",
				  line);
			parse_error=1;
			break;
		}

                /* ignore comments */
		len--;
		if(buf[len]=='\n') buf[len]=0;
                if(buf[0]=='#'){
			continue;
                }
		key=strtok(buf," \t");
		/* ignore empty lines */
		if(key==NULL) continue;
		val=strtok(NULL, " \t");
		if(val!=NULL){
			val2=strtok(NULL, " \t");
			LOGPRINTF(3,"\"%s\" \"%s\"",key,val);
                        if (strcasecmp("begin",key)==0){
				if (strcasecmp("codes", val)==0){
                                        /* init codes mode */
					LOGPRINTF(2,"    begin codes");
					if (!checkMode(mode, ID_remote,
						       "begin codes")) break;
					if (rem->codes){
						logprintf(LOG_ERR,"error in configfile line %d:",line);
						logprintf(LOG_ERR,"codes are already defined");
						parse_error=1;
						break;
					}
					
                                        init_void_array(&codes_list,30, sizeof(struct ir_ncode));
                                        mode=ID_codes;
                                }else if(strcasecmp("raw_codes",val)==0){
                                        /* init raw_codes mode */
					LOGPRINTF(2,"    begin raw_codes");
					if(!checkMode(mode, ID_remote,
						  "begin raw_codes")) break;
					if (rem->codes){
						logprintf(LOG_ERR,"error in configfile line %d:",line);
						logprintf(LOG_ERR,"codes are already defined");
						parse_error=1;
						break;
					}
					rem->flags|=RAW_CODES;
					raw_code.code=0;
                                        init_void_array(&raw_codes,30, sizeof(struct ir_ncode));
                                        mode=ID_raw_codes;
                                }else if(strcasecmp("remote",val)==0){
					/* create new remote */
					LOGPRINTF(1,"parsing remote");
					if(!checkMode(mode, ID_none,
						  "begin remote")) break;
                                        mode=ID_remote;
                                        if (!top_rem){
                                                /* create first remote */
						LOGPRINTF(2,"creating first remote");
                                                rem=top_rem=s_malloc(sizeof(struct ir_remote));
                                        }else{
                                                /* create new remote */
						LOGPRINTF(2,"creating next remote");
                                                rem->next=s_malloc(sizeof(struct ir_remote));;
                                                rem=rem->next;
                                        }
                                }else{
                                        logprintf(LOG_ERR,"error in configfile line %d:",line);
					logprintf(LOG_ERR,"unknown section \"%s\"",val);
                                        parse_error=1;
                                }
				if(!parse_error && val2!=NULL)
				{
					logprintf(LOG_WARNING,"garbage after "
						  "'%s' token in line %d ignored",
						  val,line);
				}
                        }else if (strcasecmp("end",key)==0){

				if (strcasecmp("codes", val)==0){
					/* end Codes mode */
					LOGPRINTF(2,"    end codes");
                                        if (!checkMode(mode, ID_codes,
						       "end codes")) break;
                                        rem->codes=get_void_array(&codes_list);
                                        mode=ID_remote;     /* switch back */

                                }else if(strcasecmp("raw_codes",val)==0){
                                        /* end raw codes mode */
					LOGPRINTF(2,"    end raw_codes");
					
					if(mode==ID_raw_name){
						raw_code.signals=get_void_array(&signals);
						raw_code.length=signals.nr_items;
						if(raw_code.length%2==0)
						{
							logprintf(LOG_ERR,"error in configfile line %d:",line);
							logprintf(LOG_ERR,"bad signal length",val);
							parse_error=1;
						}
						if(!add_void_array(&raw_codes, &raw_code))
							break;
						mode=ID_raw_codes;
					}
                                        if(!checkMode(mode,ID_raw_codes,
						      "end raw_codes")) break;
					rem->codes=get_void_array(&raw_codes);
					mode=ID_remote;     /* switch back */
                                }else if(strcasecmp("remote",val)==0){
                                        /* end remote mode */
					LOGPRINTF(2,"end remote");
					/* print_remote(rem); */
                                        if (!checkMode(mode,ID_remote,
                                                  "end remote")) break;
                                        if (!rem->name){
                                                logprintf(LOG_ERR,"you must specify a remote name");
                                                parse_error=1;
                                                break;
                                        }

					/* not really necessary because we
					   clear the alloced memory */
                                        rem->next=NULL;
					rem->last_code=NULL;
                                        mode=ID_none;     /* switch back */
					if(has_repeat_gap(rem) && 
					   is_const(rem))
					{
						logprintf(LOG_WARNING,"repeat_gap will be ignored if CONST_LENGTH flag is set");
					}
                                }else{
                                        logprintf(LOG_ERR,"error in configfile line %d:",line);
					logprintf(LOG_ERR,"unknown section %s",val);
                                        parse_error=1;
                                }
				if(!parse_error && val2!=NULL)
				{
					logprintf(LOG_WARNING,"garbage after '%s'"
						  " token in line %d ignored",
						  val,line);
				}
                        } else {
				switch (mode){
				case ID_remote:
					argc=defineRemote(key, val, val2, rem);
					if(!parse_error && ((argc==1 && val2!=NULL) || 
					   (argc==2 && val2!=NULL && strtok(NULL," \t")!=NULL)))
					{
						logprintf(LOG_WARNING,"garbage after '%s'"
							  " token in line %d ignored",
							  key,line);
					}
					break;
				case ID_codes:
					add_void_array(&codes_list, defineCode(key, val, &name_code));
					if(!parse_error && val2!=NULL)
					{
						logprintf(LOG_WARNING,"garbage after '%s'"
							  " code in line %d ignored",
							  key,line);
					}
					break;
				case ID_raw_codes:
				case ID_raw_name:
					if(strcasecmp("name",key)==0){
						LOGPRINTF(3,"Button: \"%s\"",val);
						if(mode==ID_raw_name)
						{
                                                        raw_code.signals=get_void_array(&signals);
							raw_code.length=signals.nr_items;
							if(raw_code.length%2==0)
							{
								logprintf(LOG_ERR,"error in configfile line %d:",line);
								logprintf(LOG_ERR,"bad signal length",val);
								parse_error=1;
							}
							if(!add_void_array(&raw_codes, &raw_code))
								break;
						}
						if(!(raw_code.name=s_strdup(val))){
							break;
						}
						raw_code.code++;
						init_void_array(&signals,50,sizeof(lirc_t));
						mode=ID_raw_name;
						if(!parse_error && val2!=NULL)
						{
							logprintf(LOG_WARNING,"garbage after '%s'"
								  " token in line %d ignored",
								  key,line);
						}
					}else{
						if(mode==ID_raw_codes)
						{
							logprintf(LOG_ERR,"no name for signal defined at line %d",line);
							parse_error=1;
							break;
						}
						if(!addSignal(&signals, key)) break;
						if(!addSignal(&signals, val)) break;
						if (val2){
							if (!addSignal(&signals, val2)){
								break;
							}
						}
						while ((val=strtok(NULL," \t"))){
							if (!addSignal(&signals, val)) break;
						}
					}
					break;
				}
			}
		}else if(mode==ID_raw_name){
                        if(!addSignal(&signals, key)){
				break;
			}
		}else{
                        logprintf(LOG_ERR,"error in configfile line %d", line);
			parse_error=1;
			break;
                }
                if (parse_error){
                        break;
                }
        }
	if(mode!=ID_none)
	{
		switch(mode)
		{
		case ID_raw_name:
			if(raw_code.name!=NULL)
			{
				free(raw_code.name);
				if(get_void_array(&signals)!=NULL)
					free(get_void_array(&signals));
			}
		case ID_raw_codes:
			rem->codes=get_void_array(&raw_codes);
			break;
		case ID_codes:
			rem->codes=get_void_array(&codes_list);
			break;
		}
		if(!parse_error)
		{
			logprintf(LOG_ERR,"unexpected end of file");
			parse_error=1;
		}
	}
        if (parse_error){
		free_config(top_rem);
                return((void *) -1);
        }
	/* kick reverse flag */
	rem=top_rem;
	while(rem!=NULL)
	{
		if((!is_raw(rem)) && rem->flags&REVERSE)
		{
			struct ir_ncode *codes;
			
			if(has_pre(rem))
			{
				rem->pre_data=reverse(rem->pre_data,
						      rem->pre_data_bits);
			}
			if(has_post(rem))
			{
				rem->post_data=reverse(rem->post_data,
						       rem->post_data_bits);
			}
			codes=rem->codes;
			while(codes->name!=NULL)
			{
				codes->code=reverse(codes->code,rem->bits);
				codes++;
			}
			/* rem->flags=rem->flags&(~REVERSE); */
			/* don't delete the flag because we still need
			   it to remain compatible with older versions
			*/
		}
		rem=rem->next;
	}

#       if defined(DEBUG) && !defined(DAEMONIZE)
        /*fprint_remotes(stderr, top_rem);*/
#       endif
        return (top_rem);
}