📄 irrecord.c
字号:
/* $Id: irrecord.c,v 5.42 2002/07/13 09:30:17 ranty Exp $ *//**************************************************************************** ** irrecord.c ************************************************************** **************************************************************************** * * irrecord - application for recording IR-codes for usage with lircd * * Copyright (C) 1998,99 Christoph Bartelmus <lirc@bartelmus.de> * */#ifdef HAVE_CONFIG_H# include <config.h>#endif#include <stdio.h>#include <stdlib.h>#include <stdarg.h>#ifdef TIME_WITH_SYS_TIME# include <sys/time.h># include <time.h>#else# ifdef HAVE_SYS_TIME_H# include <sys/time.h># else# include <time.h># endif#endif#include <sys/types.h>#include <unistd.h>#include <string.h>#include <unistd.h>#include <fcntl.h>#include <getopt.h>#include <sys/socket.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/un.h>#include <errno.h>#include <limits.h>#include <signal.h>#include <syslog.h>#include "drivers/lirc.h"#include "hardware.h"#include "hw-types.h"#include "dump_config.h"#include "ir_remote.h"#include "config_file.h"void flushhw(void);int resethw(void);int waitfordata(unsigned long maxusec);int availabledata(void);int get_toggle_bit(struct ir_remote *remote);void set_toggle_bit(struct ir_remote *remote,ir_code xor);void get_pre_data(struct ir_remote *remote);void get_post_data(struct ir_remote *remote);#ifdef DEBUGvoid remove_pre_data(struct ir_remote *remote);void remove_post_data(struct ir_remote *remote);#endifint get_lengths(struct ir_remote *remote,int force);struct lengths *new_length(lirc_t length);int add_length(struct lengths **first,lirc_t length);void free_lengths(struct lengths *first);void merge_lengths(struct lengths *first);void get_scheme(struct ir_remote *remote);struct lengths *get_max_length(struct lengths *first,unsigned int *sump);void unlink_length(struct lengths **first,struct lengths *remove);int get_trail_length(struct ir_remote *remote);int get_lead_length(struct ir_remote *remote);int get_repeat_length(struct ir_remote *remote);int get_header_length(struct ir_remote *remote);int get_data_length(struct ir_remote *remote);int get_gap_length(struct ir_remote *remote);void fprint_copyright(FILE *fout);extern struct hardware hw;extern struct ir_remote *last_remote;char *progname;const char *usage="Usage: %s [options] file\n";struct ir_remote remote;struct ir_ncode ncode;#define IRRECORD_VERSION "0.5"#define BUTTON 80+1#define RETRIES 10#define min(a,b) (a>b ? b:a)#define max(a,b) (a>b ? a:b)/* the longest signal I've seen up to now was 48-bit signal with header */#define MAX_SIGNALS 200lirc_t signals[MAX_SIGNALS];#define AEPS 100#define EPS 30/* some threshold values */#define TH_SPACE_ENC 80 /* I want less than 20% mismatches */#define TH_HEADER 90#define TH_REPEAT 90#define TH_TRAIL 90#define TH_LEAD 90#define TH_IS_BIT 15#define MIN_GAP 20000#define MAX_GAP 100000#define SAMPLES 80#ifdef DEBUGint debug=10;#elseint debug=0;#endifFILE *lf=NULL;char *hostname="";int daemonized=0;void logprintf(int prio,char *format_str, ...){ time_t current; char *currents; va_list ap; current=time(¤t); currents=ctime(¤t); if(lf) fprintf(lf,"%15.15s %s %s: ",currents+4,hostname,progname); if(!daemonized) fprintf(stderr,"%s: ",progname); va_start(ap,format_str); if(lf) { if(prio==LOG_WARNING) fprintf(lf,"WARNING: "); vfprintf(lf,format_str,ap); fputc('\n',lf);fflush(lf); } if(!daemonized) { if(prio==LOG_WARNING) fprintf(stderr,"WARNING: "); vfprintf(stderr,format_str,ap); fputc('\n',stderr);fflush(stderr); } va_end(ap);}void logperror(int prio,const char *s){ if(s!=NULL) { logprintf(prio,"%s: %s",s,strerror(errno)); } else { logprintf(prio,"%s",strerror(errno)); }}void dosigterm(int sig){ raise(SIGTERM);}int main(int argc,char **argv){ char *filename; FILE *fout,*fin; int flags; int retval=EXIT_SUCCESS; ir_code pre,code,post; int repeat_flag; lirc_t remaining_gap; int force; int retries; struct ir_remote *remotes=NULL;#ifdef DEBUG int get_pre=0,get_post=0;#endif progname=argv[0]; force=0; hw_choose_driver(NULL); while(1) { int c; static struct option long_options[] = { {"help",no_argument,NULL,'h'}, {"version",no_argument,NULL,'v'}, {"device",required_argument,NULL,'d'}, {"driver",required_argument,NULL,'H'}, {"force",no_argument,NULL,'f'},#ifdef DEBUG {"pre",no_argument,NULL,'p'}, {"post",no_argument,NULL,'P'},#endif {0, 0, 0, 0} };#ifdef DEBUG c = getopt_long(argc,argv,"hvd:H:fpP",long_options,NULL);#else c = getopt_long(argc,argv,"hvd:H:f",long_options,NULL);#endif if(c==-1) break; switch (c) { case 'h': printf(usage,progname); printf("\t -h --help\t\tdisplay this message\n"); printf("\t -v --version\t\tdisplay version\n"); printf("\t -f --force\t\tforce raw mode\n"); printf("\t -H --driver=driver\tuse given driver\n"); printf("\t -d --device=device\tread from given device\n"); exit(EXIT_SUCCESS); case 'v': printf("irrecord %s\n",IRRECORD_VERSION); exit(EXIT_SUCCESS); case 'H': if(hw_choose_driver(optarg) != 0){ fprintf(stderr, "Driver `%s' not supported.\n", optarg); hw_print_drivers(stderr); exit (EXIT_FAILURE); } case 'd': hw.device=optarg; break; case 'f': force=1; break;#ifdef DEBUG case 'p': get_pre=1; break; case 'P': get_post=1; break;#endif default: printf("Try %s -h for help!\n",progname); exit(EXIT_FAILURE); } } if(argc==1) { printf(usage,progname); } if(optind+1!=argc) { fprintf(stderr,"%s: invalid argument count\n",progname); exit(EXIT_FAILURE); } if(strcmp(hw.name, "null")==0) { fprintf(stderr, "%s: irrecord does not make sense without hardware\n", progname); exit(EXIT_FAILURE); } filename=argv[optind]; fin=fopen(filename,"r"); if(fin!=NULL) { char *filename_new; remotes=read_config(fin); fclose(fin); if(remotes==(void *) -1 || remotes==NULL) { fprintf(stderr, "%s: file \"%s\" does not contain valid " "data\n",progname,filename); exit(EXIT_FAILURE); }#ifdef DEBUG remove_pre_data(remotes); remove_post_data(remotes); if(get_pre) get_pre_data(remotes); if(get_post) get_post_data(remotes); fprint_remotes(stdout,remotes); free_config(remotes); return(EXIT_SUCCESS);#endif remote=*remotes; remote.name=NULL; remote.codes=NULL; remote.last_code=NULL; remote.next=NULL; remote.toggle_bit=0; remote.bits=remote.pre_data_bits+ remote.bits+ remote.post_data_bits; remote.pre_data_bits=0; remote.post_data_bits=0; if(remotes->next!=NULL) { fprintf(stderr, "%s: only first remote definition " "in file \"%s\" used\n", progname,filename); } filename_new=malloc(strlen(filename)+10); if(filename_new==NULL) { fprintf(stderr,"%s: out of memory\n", progname); exit(EXIT_FAILURE); } strcpy(filename_new,filename); strcat(filename,".conf"); } fout=fopen(filename,"w"); if(fout==NULL) { fprintf(stderr,"%s: could not open file %s\n",progname, filename); perror(progname); exit(EXIT_FAILURE); } printf("\nirrecord - application for recording IR-codes" " for usage with lirc\n" "\n" "Copyright (C) 1998,1999 Christoph Bartelmus" "(lirc@bartelmus.de)\n"); printf("\n"); if(hw.init_func) { if(!hw.init_func()) { fprintf(stderr,"%s: could not init hardware" " (lircd running ? --> close it, " "check permissions)\n",progname); fclose(fout); unlink(filename); exit(EXIT_FAILURE); } } if(hw.rec_mode==LIRC_MODE_STRING) { fprintf(stderr,"%s: no config file necessary\n",progname); fclose(fout); unlink(filename); if(hw.deinit_func) hw.deinit_func(); exit(EXIT_SUCCESS); } if(hw.rec_mode!=LIRC_MODE_MODE2 && hw.rec_mode!=LIRC_MODE_CODE && hw.rec_mode!=LIRC_MODE_LIRCCODE) { fprintf(stderr,"%s: mode not supported\n",progname); fclose(fout); unlink(filename); if(hw.deinit_func) hw.deinit_func(); exit(EXIT_FAILURE); } flags=fcntl(hw.fd,F_GETFL,0); if(flags==-1 || fcntl(hw.fd,F_SETFL,flags|O_NONBLOCK)==-1) { fprintf(stderr,"%s: could not set O_NONBLOCK flag\n", progname); fclose(fout); unlink(filename); if(hw.deinit_func) hw.deinit_func(); exit(EXIT_FAILURE); } printf("This program will record the signals from your remote control\n""and create a config file for lircd.\n\n""\n""A proper config file for lircd is maybe the most vital part of this\n""package, so you should invest some time to create a working config\n""file. Although I put a good deal of effort in this program it is often\n""not possible to automatically recognize all features of a remote\n""control. Often short-comings of the receiver hardware make it nearly\n""impossible. If you have problems to create a config file READ THE\n""DOCUMENTATION of this package, especially section \"Adding new remote\n""controls\" for how to get help.\n""\n""If there already is a remote control of the same brand available at\n""http://www.lirc.org/remotes/ you might also want to try using such a\n""remote as a template. The config files already contain all\n""parameters of the protocol used by remotes of a certain brand and\n""knowing these parameters makes the job of this program much\n""easier. There are also template files for the most common protocols\n""available in the remotes/generic/ directory of the source\n""distribution of this package. You can use a template files by\n""providing the path of the file as command line parameter.\n""\n""Please send the finished config files to <lirc@bartelmus.de> so that I\n""can make them available to others. Don't forget to put all information\n""that you can get about the remote control in the header of the file.\n""\n""Press RETURN to continue.\n\n"); getchar(); remote.name=filename; switch(hw.rec_mode) { case LIRC_MODE_MODE2: if(remotes==NULL && !get_lengths(&remote,force)) { if(remote.gap==0) { fprintf(stderr,"%s: gap not found," " can't continue\n",progname); fclose(fout); unlink(filename); if(hw.deinit_func) hw.deinit_func(); exit(EXIT_FAILURE); } printf("Creating config file in raw mode.\n"); remote.flags&=~(RC5|RC6|RCMM|SPACE_ENC); remote.flags|=RAW_CODES; remote.eps=EPS; remote.aeps=AEPS; break; } # ifdef DEBUG printf("%d %lu %lu %lu %lu %lu %d %d %d %lu\n", remote.bits, (unsigned long) remote.pone, (unsigned long) remote.sone, (unsigned long) remote.pzero, (unsigned long) remote.szero, (unsigned long) remote.ptrail, remote.flags,remote.eps,remote.aeps, (unsigned long) remote.gap);# endif break; case LIRC_MODE_CODE: case LIRC_MODE_LIRCCODE: if(hw.rec_mode==LIRC_MODE_CODE) remote.bits=CHAR_BIT; else remote.bits=hw.code_length; if(!get_gap_length(&remote)) { fprintf(stderr,"%s: gap not found," " can't continue\n",progname); fclose(fout); unlink(filename); if(hw.deinit_func) hw.deinit_func(); exit(EXIT_FAILURE); } break; } if(is_rc6(&remote)) { sleep(1); while(availabledata()) { hw.rec_func(NULL); } if(!get_toggle_bit(&remote)) { printf("But I know for sure that RC6 has a toggle bit!\n"); fclose(fout); unlink(filename); if(hw.deinit_func) hw.deinit_func(); exit(EXIT_FAILURE); } } printf("Now enter the names for the buttons.\n"); fprint_copyright(fout); fprint_comment(fout,&remote); fprint_remote_head(fout,&remote); fprint_remote_signal_head(fout,&remote); while(1) { char buffer[BUTTON]; char *string; printf("\nPlease enter the name for the next button (press <ENTER> to finish recording)\n"); string=fgets(buffer,BUTTON,stdin); if(string!=buffer) { fprintf(stderr,"%s: fgets() failed\n",progname); retval=EXIT_FAILURE; break; } buffer[strlen(buffer)-1]=0; if(strchr(buffer,' ') || strchr(buffer,'\t')) { printf("The name must not contain any whitespace.\n"); printf("Please try again.\n"); continue; } if(strcasecmp(buffer,"begin")==0 || strcasecmp(buffer,"end")==0) { printf("'%s' is not allowed as button name\n",buffer); printf("Please try again.\n"); continue; } if(strlen(buffer)==0) { break; } if(remote.flags&RAW_CODES) { flushhw(); } else { while(availabledata()) { hw.rec_func(NULL); } } printf("\nNow hold down button \"%s\".\n",buffer); fflush(stdout); if(remote.flags&RAW_CODES) { lirc_t data,sum; unsigned int count; count=0;sum=0; while(count<MAX_SIGNALS) { unsigned long timeout; if(count==0) timeout=10000000; else timeout=remote.gap*5; data=hw.readdata(timeout); if(!data) { if(count==0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -