summaryrefslogtreecommitdiff
path: root/irdev.c
diff options
context:
space:
mode:
authorchatty1999-01-12 12:58:18 +0000
committerchatty1999-01-12 12:58:18 +0000
commit0118246b32fe0ccc5f289cc350f32fb935305959 (patch)
tree8525f9bc6213b6046d3ce6121398029d76a63bc2 /irdev.c
parent23abb4b87c7e40ed259dd02f653516f60e55ade4 (diff)
downloadirbox-0118246b32fe0ccc5f289cc350f32fb935305959.zip
irbox-0118246b32fe0ccc5f289cc350f32fb935305959.tar.gz
irbox-0118246b32fe0ccc5f289cc350f32fb935305959.tar.bz2
irbox-0118246b32fe0ccc5f289cc350f32fb935305959.tar.xz
Initial revision
Diffstat (limited to 'irdev.c')
-rw-r--r--irdev.c299
1 files changed, 299 insertions, 0 deletions
diff --git a/irdev.c b/irdev.c
new file mode 100644
index 0000000..96e2feb
--- /dev/null
+++ b/irdev.c
@@ -0,0 +1,299 @@
+/*
+ *
+ * IRBOX, an Ivy driver for infra-red remote controls
+ *
+ * Copyright 1998-1999
+ * Centre d'Etudes de la Navigation Aerienne
+ *
+ * Device driver
+ *
+ * $Id$
+ *
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/errno.h>
+#include <sys/param.h>
+#include <termio.h>
+#include <sys/ioctl.h>
+
+#include "irdev.h"
+
+
+#define CHECKEDWRITE(fd , buff , len ) \
+ if (write( fd, buff, len) != len) { perror("IR write"); return -1; }
+
+#define NBITS 8
+#define SET(n, p) ((p)[(n)/NBITS] |= ((unsigned)1 << ((n) % NBITS)))
+#define CLR(n, p) ((p)[(n)/NBITS] &= ~((unsigned)1 << ((n) % NBITS)))
+#define ISSET(n, p) ((p)[(n)/NBITS] & ((unsigned)1 << ((n) % NBITS)))
+
+char BTVUP[] = { 0xf2, 0xf0, 0xd0, 0xfc, 0xbc, 0x34 };
+
+struct ir_state {
+ int fd;
+ IrEvtCallback callback;
+ IrTimerSetter set_timeout;
+ IrTimerCanceller cancel_timeout;
+
+ /* state machine stuff */
+ char state;
+ char value[6];
+
+ void *checkinit_id;
+
+ /* misc. std. driver stuff */
+ unsigned char initialized;/* true if data structures are set */
+ /* and init sequence has been sent to */
+ /* device */
+ unsigned char ready; /* true if we've received confirmation */
+ /* of the init sequence from the device */
+ unsigned char errorCount;/* count of bad messages for recovery */
+};
+
+static void
+IrDefaultCallback (IrState *ir, IrEvent event, const char *value)
+{
+ switch (event ) {
+ case EVENT_BTN_PRESS:
+ fprintf (stderr, "IR default callback EVENT_BTN_PRESS %s\n", value );
+ break;
+ case EVENT_BTN_RELEASE:
+ fprintf (stderr, "IR default callback EVENT_BTN_PRESS %s\n", value );
+ break;
+ case EVENT_BTN_PRESS_TV_VOL_UP:
+ fprintf (stderr, "IR default callback EVENT_BTN_PRESS_TV_VOL_UP %s\n", value );
+ break;
+ }
+
+}
+
+static int IrInitDevice (IrState*);
+
+
+int
+IrInit (IrState *ir, IrEvtCallback cb, IrTimerSetter st, IrTimerCanceller ct)
+{
+ ir->callback = cb;
+ ir->set_timeout = st;
+ ir->cancel_timeout = ct;
+ return IrInitDevice (ir);
+}
+
+
+
+static void
+IrCheckInit (void * id, IrState *ir, int delta)
+{
+ if ((!ir->ready) && (ir->checkinit_id)) {
+ if (ir->errorCount++<5) {
+ IrInitDevice (ir);
+ return;
+ } else {
+ fprintf(stderr,"Ir box not responding.\n");
+ }
+ }
+ ir->checkinit_id= 0;
+ return;
+}
+
+
+#define SPEED B9600
+
+/* ARGSUSED */
+static int
+IrInitDevice (IrState *ir)
+{
+ unsigned char dcmd[2];
+ struct termios terms;
+
+ /*initialisation du port serie */
+ if (tcgetattr (ir->fd, &terms) == -1) {
+ perror ( "Cant get device configuration for IR box");
+ return 0;
+ }
+
+ /* change the modes */
+ cfmakeraw (&terms);
+ terms.c_lflag = 0;
+
+ if (cfsetospeed (&terms, SPEED) < 0 ) {
+ perror ("Can't set ouput speed for IR box");
+ return 0;
+ }
+
+ if (cfsetispeed (&terms, SPEED) < 0 ) {
+ perror ("Can't set input speed for IR box");
+ return 0;
+ }
+
+ if (tcsetattr (ir->fd, TCSANOW, &terms) < 0)
+ {
+ perror ("Can't change device configuration for IR box");
+ return 0;
+ }
+
+ /* discard all unread or unwritten data */
+ tcflush (ir->fd, TCIOFLUSH );
+
+ fprintf (stderr, "IR box initialization in progress.....\n");
+
+ dcmd[0] = 'I';
+ dcmd[1] = 'R';
+ CHECKEDWRITE(ir->fd, dcmd, sizeof(dcmd));
+
+ ir->initialized= 1;
+ if (ir->set_timeout)
+ ir->checkinit_id = (*ir->set_timeout)(IrCheckInit, 1000, ir);
+ return 1;
+}
+
+
+
+
+static void
+IrSetup (IrState *ir)
+{
+ ir->ready=1;
+ if (ir->cancel_timeout)
+ (*ir->cancel_timeout)(ir->checkinit_id);
+
+ ir->errorCount= 0;
+ return;
+}
+
+
+static void
+IrDecodeInit (IrState *ir, char ch)
+{
+ /* on doit attendre les caracteres "OK" */
+ switch (ir->state) {
+ case 0:
+ if ( ch == 'O' )
+ ir->state++;
+ break;
+ case 1:
+ if ( ch == 'K' ) {
+ ir->state = 0;
+ fprintf (stderr,"IR box initialized OK.\n");
+ IrSetup (ir);
+ ir->errorCount = 0;
+ } else {
+ fprintf (stderr, "unexpected char %d from IR box\n", ch);
+ if (ir->errorCount++ > 5) {
+ /* try to reinitialize */
+ fprintf (stderr,"Reinitializing IR box\n");
+ IrInitDevice (ir);
+ }
+ }
+ break;
+ default:
+ fprintf (stderr,"Impossible state %d in ir_intr.\n", ir->state);
+ ir->state = 0;
+ break;
+ }
+}
+
+
+static void
+IrDecodeFrame (IrState *ir, char ch)
+{
+ /* trame normale de 6 carateres */
+ if (ir->state == 5) {
+ /* fin de trame */
+#ifdef DEBUG_RECEIVE
+ fprintf (stdout, "Valeur BTVUP: %s\n",BTVUP);
+ fprintf (stdout, "Valeur recue: %s\n",ir->value);
+#endif
+ if (strcmp (ir->value,BTVUP) == 0)
+ (*ir->callback)(ir, EVENT_BTN_PRESS_TV_VOL_UP, ir->value );
+ else
+ (*ir->callback)(ir, EVENT_BTN_PRESS, ir->value );
+ ir->state = 0;
+ } else {
+ /* un caractere de la trame */
+ ir->value[(int)(ir->state++)] = ch;
+ }
+}
+
+void
+IrIntr (IrState *ir)
+{
+ unsigned char buf[128];
+ unsigned char *str;
+ int len;
+ register unsigned char ch;
+#ifdef DEBUG_RECEIVE
+ int i;
+#endif
+ if ((len = read(ir->fd, buf, sizeof(buf))) < 0)
+ return;
+#ifdef DEBUG_RECEIVE
+ fprintf(stderr, "receive %d bytes from device \n",len);
+ for ( i = 0; i < len ; i ++ )
+ fprintf(stderr, "0x%02x ",buf[i]);
+ fprintf(stderr, "\n");
+#endif
+ str = buf;
+ while (len > 0) {
+ ch = *str++;
+ if (!ir->ready) /* on doit attendre les caracteres OK */
+ IrDecodeInit (ir,ch);
+ else /* on doit attendre la fin de la trame ( 6 car ) */
+ IrDecodeFrame (ir, ch);
+ len--;
+ }
+ return;
+}
+
+/* ARGSUSED */
+IrState*
+IrOpen (const char *name )
+{
+ register IrState *ir;
+
+ if ( !(ir = (IrState *)malloc(sizeof *ir)))
+ return NULL;
+ /* Set defaults -- totally arbitrary, my choice */
+ memset( ir, 0, sizeof *ir ) ;
+
+ if ((ir->fd = open(name, O_RDWR/*|O_NONBLOCK*/)) < 0) {
+ fprintf(stderr, "Couldn't open %s\n", name);
+ free( ir );
+ return NULL;
+
+ }
+
+
+ ir->initialized = 1;
+ ir->errorCount = 0;
+ ir->state = 0;
+
+
+ ir->callback = IrDefaultCallback;
+ return ir;
+}
+
+/* ARGSUSED */
+void
+IrClose (IrState *ir)
+{
+ if (ir->checkinit_id) {
+ if (ir->cancel_timeout )
+ (*ir->cancel_timeout)( ir->checkinit_id );
+ ir->checkinit_id= 0;
+ }
+ free (ir);
+}
+
+int
+IrGetFd (IrState *ir)
+{
+ return ir->fd;
+}