From db4012df9a277b42b1e138a402560c89fae36eb1 Mon Sep 17 00:00:00 2001 From: Greg Lehey Date: Mon, 5 Mar 2007 05:04:45 +0000 Subject: [PATCH] Add support for DVICO USB remote control. Submitted by: grog Approved by: Daniel O'Connor (maintainer) --- comms/lirc/Makefile | 4 +- comms/lirc/files/patch-daemons::hw_hiddev.c | 160 ++++++++++++++++++++ comms/lirc/files/patch-daemons::lircd.c | 18 +++ 3 files changed, 180 insertions(+), 2 deletions(-) create mode 100644 comms/lirc/files/patch-daemons::hw_hiddev.c create mode 100644 comms/lirc/files/patch-daemons::lircd.c diff --git a/comms/lirc/Makefile b/comms/lirc/Makefile index d5c5d7af568e..3a20213fdbb7 100644 --- a/comms/lirc/Makefile +++ b/comms/lirc/Makefile @@ -40,9 +40,9 @@ PLIST_SUB+= SMODE2="@comment " .if defined(WITH_IRMAN) BUILD_DEPENDS+= ${LOCALBASE}/lib/libirman.a:${PORTSDIR}/comms/libirman -CONFIGURE_ARGS+= --with-driver=irman +CONFIGURE_ARGS+= --with-driver=irman --with-driver=dvico .else -CONFIGURE_ARGS+= --with-driver=any +CONFIGURE_ARGS+= --with-driver=any --with-driver=dvico .endif .if ${OSVERSION} >= 500041 diff --git a/comms/lirc/files/patch-daemons::hw_hiddev.c b/comms/lirc/files/patch-daemons::hw_hiddev.c new file mode 100644 index 000000000000..741f4f55138e --- /dev/null +++ b/comms/lirc/files/patch-daemons::hw_hiddev.c @@ -0,0 +1,160 @@ +--- daemons/hw_hiddev.c.orig Sun Jul 10 18:04:11 2005 ++++ daemons/hw_hiddev.c Thu Nov 23 14:41:52 2006 +@@ -19,14 +19,19 @@ + #include + #include + ++#ifdef __FreeBSD__ ++#include ++#else /* assume Linux */ + #include + #include ++#endif + + #include "hardware.h" + #include "ir_remote.h" + #include "lircd.h" + #include "receive.h" +- ++#include ++#include + + static int hiddev_init(); + static int hiddev_deinit(void); +@@ -103,7 +108,11 @@ + logprintf(LOG_INFO, "initializing '%s'", hw.device); + + if ((hw.fd = open(hw.device, O_RDONLY)) < 0) { +- logprintf(LOG_ERR, "unable to open '%s'", hw.device); ++ logprintf(LOG_ERR, ++ "unable to open '%s': %s (%d)", ++ hw.device, ++ strerror (errno), ++ errno ); + return 0; + } + +@@ -143,38 +152,117 @@ + } + + ++/* ++ * Read a record from the remote control, decode it and return a ++ * string of the form ++ * ++ * 00010046000042fe 00 start DVICO_MCE ++ * ++ * The first field is the complete event. The second appears to tbe ++ * the repeat flag, the third the name of the the key, and the fourth ++ * some kind of identification. I have no idea how much of this is ++ * used. ++ * ++ * The code below works around the extremely fast repeat holdoff on ++ * the DVICO control. It's difficult to press a key without it ++ * repeating. We work around this by ignoring the first 3 repeats. ++ * ++ * For FreeBSD, we have the problem of a different HID interface. ++ * Linux returns a struct hiddev_event, while FreeBSD returns data ++ * with no specific structure. Part of the Linux structure is the ++ * hid, which FreeBSD doesn't seem to supply. Work around these ++ * issues by reading the FreeBSD data and packing it into a Linux ++ * struct hiddev_event. This requires lying about the hid. ++ */ ++ + char *hiddev_rec(struct ir_remote *remotes) + { ++#ifdef __FreeBSD__ ++#define HIDRECLEN 3 /* get this from hid_init() */ ++ char inbuf [HIDRECLEN]; ++ struct hiddev_event ++ { ++ unsigned hid; ++ int16_t value; ++ }; ++#endif + struct hiddev_event event; + int rd; + /* Remotec Mediamaster specific */ + static int wheel_count = 0; + static int x_movement = 0; ++ static int repeat_count = 0; + int y_movement=0; + int x_direction=0; + int y_direction=0; + + LOGPRINTF(1, "hiddev_rec"); + ++#ifdef __FreeBSD__ ++ rd = read(hw.fd, inbuf, sizeof inbuf); ++ if (rd != sizeof inbuf) { ++ logprintf(LOG_ERR, ++ "Really read %d bytes from '%s', expected %d", ++ rd, ++ hw.device, ++ sizeof inbuf ); ++ return 0; ++ } ++ event.hid = 0x10046; /* XXX not in FreeBSD */ ++ event.value = * (int16_t *) (&inbuf [1]); ++ rd = sizeof event; /* to make code happy */ ++#else + rd = read(hw.fd, &event, sizeof event); ++#endif + if (rd != sizeof event) { +- logprintf(LOG_ERR, "error reading '%s'", hw.device); ++ logprintf(LOG_ERR, ++ "Read %d bytes from '%s', expected %d", ++ rd, ++ hw.device, ++ sizeof event ); + return 0; + } + + LOGPRINTF(1, "hid 0x%X value 0x%X", event.hid, event.value); + + pre_code = event.hid; +- main_code = event.value; +- ++ main_code = event.value & 0xffff; /* only 16 bits */ + /* + * This stuff is probably dvico specific. + * I don't have any other hid devices to test... + */ +- if (event.hid == 0x10046) { +- repeat_flag = (main_code & dvico_repeat_mask); ++ if (pre_code == 0x10046) { ++ if (main_code & dvico_repeat_mask) /* repeated press */ ++ repeat_count++; /* count them */ ++ else ++ repeat_count = 0; /* reset */ ++ repeat_flag = repeat_count > 2; /* real repeat flag */ + main_code = (main_code & ~dvico_repeat_mask); +- return decode_all(remotes); ++ /* ++ * Skip this if we're working around the premature ++ * repeat. ++ */ ++ if (repeat_flag || (repeat_count == 0)) ++ { ++ char *foo; ++ ++ foo = decode_all(remotes); ++ /* ++ * XXX Experimental code. Chop off the first 12 ++ * bytes of the hex code, which FreeBSD does not ++ * provide, and which I suspect nobody cares ++ * about. ++ * ++ * For some reason, we can get NULL back here, ++ * so we need to check for that before returning ++ * address 0xc. ++ */ ++ if (foo) ++ foo = &foo [12]; /* chop off the leading chars. */ ++ return foo; ++ } ++ else ++ return 0; /* no data */ + } + /* Remotec Mediamaster specific code */ + /* Y-Coordinate, diff --git a/comms/lirc/files/patch-daemons::lircd.c b/comms/lirc/files/patch-daemons::lircd.c new file mode 100644 index 000000000000..14774ba706d5 --- /dev/null +++ b/comms/lirc/files/patch-daemons::lircd.c @@ -0,0 +1,18 @@ +--- daemons/lircd.c.orig Sun Jul 10 18:04:12 2005 ++++ daemons/lircd.c Fri Nov 24 14:21:10 2006 +@@ -755,9 +755,12 @@ + strcpy(serv_addr.sun_path,lircdfile); + if(bind(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr))==-1) + { +- fprintf(stderr,"%s: could not assign address to socket\n", +- progname); +- perror(progname); ++ fprintf(stderr, ++ "%s: could not assign address to socket %s: %s (%d)\n", ++ progname, ++ lircdfile, ++ strerror (errno), ++ errno ); + goto start_server_failed1; + } +