Skip to content

Instantly share code, notes, and snippets.

@bullshit
Last active January 29, 2020 07:20
Show Gist options
  • Save bullshit/918d74db9473355d7181 to your computer and use it in GitHub Desktop.
Save bullshit/918d74db9473355d7181 to your computer and use it in GitHub Desktop.
LIRC patch instruction/how-to for USB Infrared Toy from Dangerous Prototypes

LIRC patch instruction/how-to for USB Infrared Toy from Dangerous Prototypes

This is a instruction to patch the usb infrared toy driver into lirc sources. Most of the work is done by Peter Kooiman

Requirements

Pre-requisites

Add deb-src to your sources.list Install the packaging-dev package to get a decent set of packages to do Debian packaging. It includes the quilt package.

$ sudo apt-get install packaging-dev

Load lirc sources

$ apt-get source lirc

Depending on the current lirc version number, the folder name may be different

$ ls
lirc-0.9.0~pre1  lirc_0.9.0~pre1-1.debian.tar.bz2  lirc_0.9.0~pre1-1.dsc  lirc_0.9.0~pre1.orig.tar.bz2

Download patch

$ wget https://gist.githubusercontent.com/bullshit/918d74db9473355d7181/raw/568b75813d51c8aaa793a83f448a6184b0d4d5aa/USB-Infrared-Toy-driver.patch

Apply patch to lirc sources

Switch to the source folder

$ cd lirc-0.9.0~pre1

Now import the patch with quilt and apply it

$ quilt import ../USB-Infrared-Toy-driver.patch
$ quilt push
$ quilt refresh

There is the output of the quilt commands on my raspberry pi

root@pi:~/test/lirc-0.9.0~pre1# quilt import ../USB-Infrared-Toy-driver.patch
Importing patch ../USB-Infrared-Toy-driver.patch (stored as USB-Infrared-Toy-driver.patch)
root@pi:~/test/lirc-0.9.0~pre1# quilt push
Applying patch USB-Infrared-Toy-driver.patch
patching file configure
patching file configure.ac
patching file daemons/hw-types.c
patching file daemons/hw_usbirtoy.c
patching file setup.data
patching file setup.sh

Now at patch USB-Infrared-Toy-driver.patch
root@pi:~/test/lirc-0.9.0~pre1# quilt refresh
Warning: trailing whitespace in lines 6,179,269 of daemons/hw_usbirtoy.c
Warning: trailing whitespace in lines 201,414 of setup.data
Refreshed patch USB-Infrared-Toy-driver.patch

Build your lirc package with USB Infrared Toy support

$ debuild -us -uc

When the build proccess is finished you have all the lirc packages outside the source folder

$ ls ../
liblircclient0_0.9.0~pre1-1_armhf.deb     lirc_0.9.0~pre1-1_armhf.build    lirc_0.9.0~pre1-1.debian.tar.bz2  lirc-x_0.9.0~pre1-1_armhf.deb
liblircclient-dev_0.9.0~pre1-1_armhf.deb  lirc_0.9.0~pre1-1_armhf.changes  lirc_0.9.0~pre1-1.dsc             USB-Infrared-Toy-driver.patch
lirc-0.9.0~pre1                           lirc_0.9.0~pre1-1_armhf.deb      lirc_0.9.0~pre1.orig.tar.bz2

Install your lirc packages

$ sudo dpkg -i ../liblircclient0_0.9.0~pre1-1_armhf.deb
$ sudo dpkg -i ../lirc_0.9.0~pre1-1_armhf.deb

Finished

And know you can use lirc with USB Infrared Toy. To prevent automatic updates from apt you can hold your package

$ sudo apt-mark hold lirc
Description: USB Infrared Toy driver
Author: Oskar Holowaty <[email protected]>
Origin: other, http://sourceforge.net/p/lirc/mailman/message/28032156/
Last-Update: 2014-11-21
---
This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
Index: lirc-0.9.0~pre1/configure
===================================================================
--- lirc-0.9.0~pre1.orig/configure 2010-10-26 19:39:24.000000000 +0200
+++ lirc-0.9.0~pre1/configure 2014-11-22 00:55:42.193077231 +0100
@@ -1666,7 +1666,7 @@
srm7500libusb, streamzap, tekram,
tekram_bt829, tira, tira_raw, ttusbir,
tuxbox, tvbox, udp, uirt2, uirt2_raw,
- usb_uirt_raw, usbx, wpc8769l
+ usb_uirt_raw, usb_irtoy, usbx, wpc8769l
--with-devdir=DIR Install device files in DIR (/dev)
--with-moduledir=DIR kernel modules in DIR (/lib/modules/`uname -r`/misc)
--with-major=value specify the device major for the driver (61)
@@ -15474,6 +15474,7 @@
(uirt2) \
(uirt2_raw) \
(usb_uirt_raw) \
+ (usb_irtoy) \
(usbx) \
(udp)"
@@ -17786,6 +17787,9 @@
uirt2_raw|usb_uirt_raw)
hw_module="${hw_module} hw_uirt2_raw.o hw_uirt2_common.o serial.o receive.o transmit.o"
;;
+ usb_irtoy)
+ hw_module="${hw_module} hw_usbirtoy.o serial.o receive.o transmit.o"
+ ;;
usbx)
hw_module="${hw_module} hw_usbx.o serial.o"
;;
@@ -18560,6 +18564,11 @@
hw_module="hw_uirt2_raw.o hw_uirt2_common.o serial.o receive.o transmit.o"
HW_DEFAULT="hw_usb_uirt_raw"
fi
+if test "$driver" = "usb_irtoy"; then
+ lirc_driver="none"
+ hw_module="hw_usbirtoy.o serial.o receive.o transmit.o"
+ HW_DEFAULT="hw_usbirtoy"
+fi
if test "$driver" = "usbx"; then
lirc_driver="none"
hw_module="hw_usbx.o serial.o"
Index: lirc-0.9.0~pre1/configure.ac
===================================================================
--- lirc-0.9.0~pre1.orig/configure.ac 2010-10-26 19:32:18.000000000 +0200
+++ lirc-0.9.0~pre1/configure.ac 2014-11-22 01:05:42.242819852 +0100
@@ -154,6 +154,7 @@
(uirt2) \
(uirt2_raw) \
(usb_uirt_raw) \
+ (usb_irtoy) \
(usbx) \
(udp)"
@@ -454,7 +455,7 @@
srm7500libusb, streamzap, tekram,
tekram_bt829, tira, tira_raw, ttusbir,
tuxbox, tvbox, udp, uirt2, uirt2_raw,
- usb_uirt_raw, usbx, wpc8769l],
+ usb_uirt_raw, usb_irtoy, usbx, wpc8769l],
driver=${withval},
driver="unset"
)
@@ -698,6 +699,9 @@
uirt2_raw|usb_uirt_raw)
hw_module="${hw_module} hw_uirt2_raw.o hw_uirt2_common.o serial.o receive.o transmit.o"
;;
+ usb_irtoy)
+ hw_module="${hw_module} hw_usbirtoy.o serial.o receive.o transmit.o"
+ ;;
usbx)
hw_module="${hw_module} hw_usbx.o serial.o"
;;
@@ -1442,6 +1446,11 @@
hw_module="hw_uirt2_raw.o hw_uirt2_common.o serial.o receive.o transmit.o"
HW_DEFAULT="hw_usb_uirt_raw"
fi
+if test "$driver" = "usb_irtoy"; then
+ lirc_driver="none"
+ hw_module="hw_usbirtoy.o serial.o receive.o transmit.o"
+ HW_DEFAULT="hw_usbirtoy"
+fi
if test "$driver" = "usbx"; then
lirc_driver="none"
hw_module="hw_usbx.o serial.o"
Index: lirc-0.9.0~pre1/daemons/hw-types.c
===================================================================
--- lirc-0.9.0~pre1.orig/daemons/hw-types.c 2010-10-26 19:31:24.000000000 +0200
+++ lirc-0.9.0~pre1/daemons/hw-types.c 2014-11-22 00:56:29.747612207 +0100
@@ -58,6 +58,7 @@
extern struct hardware hw_uirt2;
extern struct hardware hw_uirt2_raw;
extern struct hardware hw_usb_uirt_raw;
+extern struct hardware hw_usbirtoy;
extern struct hardware hw_usbx;
#ifndef HW_DEFAULT
@@ -172,6 +173,7 @@
&hw_uirt2,
&hw_uirt2_raw,
&hw_usb_uirt_raw,
+ &hw_usbirtoy,
&hw_usbx,
#else
&HW_DEFAULT,
Index: lirc-0.9.0~pre1/daemons/hw_usbirtoy.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ lirc-0.9.0~pre1/daemons/hw_usbirtoy.c 2014-11-22 01:00:04.277080637 +0100
@@ -0,0 +1,434 @@
+/****************************************************************************
+ ** hw_usbirtoy.c **********************************************************
+ ****************************************************************************
+ *
+ * Routines for USB Infrared Toy receiver/transmitter in sampling mode
+ *
+ * Copyright (C) 2011 Peter Kooiman <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+ #ifdef HAVE_CONFIG_H
+ #include <config.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <limits.h>
+#include <signal.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include "hardware.h"
+#include "serial.h"
+#include "ir_remote.h"
+#include "lircd.h"
+#include "receive.h"
+#include "transmit.h"
+#define IRTOY_MINFWVERSION 20
+#define IRTOY_UNIT 21.3333
+#define IRTOY_LONGSPACE 1000000
+const unsigned char IRTOY_COMMAND_TXSTART[] = {0x24, 0x25, 0x26, 0x03};
+#define IRTOY_COMMAND_RESET 0
+#define IRTOY_COMMAND_SMODE_ENTER 's'
+#define IRTOY_COMMAND_VERSION 'v'
+#define IRTOY_REPLY_XMITCOUNT 't'
+#define IRTOY_REPLY_XMITSUCCESS 'C'
+#define IRTOY_REPLY_VERSION 'V'
+#define IRTOY_REPLY_SAMPLEMODEPROTO 'S'
+#define IRTOY_LEN_XMITRES 4
+#define IRTOY_LEN_VERSION 4
+#define IRTOY_LEN_SAMPLEMODEPROTO 3
+#define IRTOY_TIMEOUT_READYFORDATA 1000000
+#define IRTOY_TIMEOUT_FLUSH 20000
+#define IRTOY_TIMEOUT_SMODE_ENTER 500000
+#define IRTOY_TIMEOUT_VERSION 500000
+struct tag_irtoy_t {
+ int hwVersion;
+ int swVersion;
+ int protoVersion;
+ int fd;
+ int awaitingNewSig;
+ int pulse;
+};
+typedef struct tag_irtoy_t irtoy_t;
+static irtoy_t *dev;
+unsigned char rawSB[WBUF_SIZE * 2 + 2];
+/* exported functions */
+static int irtoy_init(void);
+static int irtoy_deinit(void);
+static int irtoy_send(struct ir_remote *remote, struct ir_ncode *code);
+static char *irtoy_rec(struct ir_remote *remotes);
+static int irtoy_decode(struct ir_remote *remote, ir_code * prep, ir_code * codep, ir_code * postp,
+ int *repeat_flagp, lirc_t * min_remaining_gapp, lirc_t * max_remaining_gapp);
+static lirc_t irtoy_readdata(lirc_t timeout);
+struct hardware hw_usbirtoy = {
+ #ifndef LIRC_IRTTY
+ "/dev/ttyACM0",
+ #else
+ LIRC_IRTTY, /* default device */
+ #endif
+ -1, /* fd */
+ LIRC_CAN_REC_MODE2 | LIRC_CAN_SEND_PULSE, /* features */
+ LIRC_MODE_PULSE, /* send_mode */
+ LIRC_MODE_MODE2, /* rec_mode */
+ 0, /* code_length */
+ irtoy_init, /* init_func */
+ irtoy_deinit, /* deinit_func */
+ irtoy_send, /* send_func */
+ irtoy_rec, /* rec_func */
+ irtoy_decode, /* decode_func */
+ NULL, /* ioctl_func */
+ irtoy_readdata, /* readdata */
+ "usb_irtoy"
+};
+static int irtoy_decode(struct ir_remote *remote, ir_code * prep, ir_code * codep, ir_code * postp,
+ int *repeat_flagp, lirc_t * min_remaining_gapp, lirc_t * max_remaining_gapp)
+{
+ int res;
+ LOGPRINTF(1, "irtoy_decode: enter");
+ res = receive_decode(remote, prep, codep, postp, repeat_flagp, min_remaining_gapp, max_remaining_gapp);
+ LOGPRINTF(1, "irtoy_decode: %d", res);
+ return res;
+}
+static ssize_t read_with_timeout(int fd, void *buf, size_t count, long to_usec)
+{
+ ssize_t rc;
+ size_t numread = 0;
+ struct timeval timeout;
+ fd_set fds;
+ timeout.tv_sec = 0;
+ timeout.tv_usec = to_usec;
+ rc = read(fd, (char *) buf, count);
+ if (rc > 0) {
+ numread += rc;
+ }
+ while ((rc == -1 && errno == EAGAIN) || (rc >= 0 && numread < count)) {
+ FD_ZERO(&fds);
+ FD_SET(fd, &fds);
+ rc = select(fd + 1, &fds, NULL, NULL, &timeout);
+ if (rc == 0) {
+ /* timeout */
+ break;
+ } else if (rc == -1) {
+ /* continue for EAGAIN case */
+ continue;
+ }
+ rc = read(fd, ((char *)buf) + numread, count - numread);
+ if (rc > 0) {
+ numread += rc;
+ }
+ }
+ return(numread == 0) ? -1 : numread;
+}
+static int irtoy_readflush(irtoy_t * dev, long timeout)
+{
+ int res;
+ char c;
+ while ((res = read_with_timeout(dev->fd, &c, 1, timeout)) == 1)
+ ;
+ if (res != 0)
+ return -1;
+ else
+ return 0;
+ }
+static lirc_t irtoy_read(irtoy_t * dev, lirc_t timeout)
+{
+ lirc_t data;
+ int res;
+ unsigned char dur[2];
+ if (!waitfordata(timeout))
+ return 0;
+ // lircd expects a space as start of the next transmission, not just at the end of the last one
+ // irrecord however likes to see a space at the end of the signal
+ // We remember if we saw the 0xFFFF timeout from the usbtoy and send a long space both after last signal and at start of next signal
+ // From usb irtoy: <signal...><lastpulse> [usbtoy timeout duration] 0xFFFF [however long it takes before next signal] <firstpulse><signal..>
+ // We return: <signal><lastpulse> [usbtoy timeout duration] LONGSPACE [however long it takes before next signal] LONGSPACE <firstpulse><signal>
+ if (dev->awaitingNewSig) {
+ LOGPRINTF(1, "new signal after large space");
+ dev->pulse = 1;
+ dev->awaitingNewSig = 0;
+ return IRTOY_LONGSPACE;
+ }
+ res = read_with_timeout(dev->fd, dur, 2, 0);
+ if (res != 2) {
+ logprintf(LOG_ERR, "irtoy_read: could not get 2 bytes");
+ return 0;
+ }
+ LOGPRINTF(3, "read_raw %02x%02x", dur[0], dur[1]);
+ if (dur[0] == 0xff && dur[1] == 0xff) {
+ dev->awaitingNewSig = 1;
+ return IRTOY_LONGSPACE;
+ }
+ data = (lirc_t) (IRTOY_UNIT * (double) (256 * dur[0] + dur[1]));
+ LOGPRINTF(3, "read_raw %d", data);
+ if (dev->pulse) {
+ data = data | PULSE_BIT;
+ }
+ dev->pulse = ! (dev->pulse);
+ return data;
+}
+static lirc_t irtoy_readdata(lirc_t timeout)
+{
+ lirc_t data = irtoy_read(dev, timeout);
+ if (data) {
+ LOGPRINTF(1, "irtoy_readdata %d %d", !!(data & PULSE_BIT), data & PULSE_MASK);
+ }
+ return(data);
+}
+static int irtoy_getversion(irtoy_t *dev)
+{
+ int res;
+ unsigned char buf[16];
+ int vNum;
+ irtoy_readflush(dev, IRTOY_TIMEOUT_FLUSH);
+ buf[0] = IRTOY_COMMAND_VERSION;
+ res = write(dev->fd, buf, 1);
+ if (res != 1) {
+ logprintf(LOG_ERR, "irtoy_getversion: couldn't write command");
+ return 0;
+ }
+ res = read_with_timeout(dev->fd, buf, IRTOY_LEN_VERSION, IRTOY_TIMEOUT_VERSION);
+ if (res != IRTOY_LEN_VERSION) {
+ logprintf(LOG_ERR, "irtoy_getversion: couldn't read version");
+ logprintf(LOG_ERR, "please make sure you are using firmware v20 or higher");
+ return 0;
+ }
+ buf[IRTOY_LEN_VERSION] = 0;
+ LOGPRINTF(1, "irtoy_getversion: Got version %s", buf);
+ if (buf[0] != IRTOY_REPLY_VERSION) {
+ logprintf(LOG_ERR, "irtoy_getversion: invalid response %02X", buf[0]);
+ logprintf(LOG_ERR, "please make sure you are using firmware v20 or higher");
+ return 0;
+ }
+ vNum = atoi(buf + 1);
+ dev->hwVersion = vNum / 100;
+ dev->swVersion = vNum % 100;
+ return 1;
+}
+static int irtoy_reset(irtoy_t *dev)
+{
+ int res;
+ unsigned char buf[16];
+ buf[0] = IRTOY_COMMAND_RESET;
+ res = write(dev->fd, buf, 1);
+ if (res != 1) {
+ logprintf(LOG_ERR, "irtoy_reset: couldn't write command");
+ return 0;
+ }
+ irtoy_readflush(dev, IRTOY_TIMEOUT_FLUSH);
+ return 1;
+}
+static int irtoy_enter_samplemode(irtoy_t *dev)
+{
+ int res;
+ unsigned char buf[16];
+ buf[0] = IRTOY_COMMAND_SMODE_ENTER;
+ res = write(dev->fd, buf, 1);
+ if (res != 1) {
+ logprintf(LOG_ERR, "irtoy_enter_samplemode: couldn't write command");
+ return 0;
+ }
+ res = read_with_timeout(dev->fd, buf, IRTOY_LEN_SAMPLEMODEPROTO, IRTOY_TIMEOUT_SMODE_ENTER);
+ if (res != IRTOY_LEN_SAMPLEMODEPROTO) {
+ logprintf(LOG_ERR, "irtoy_enter_samplemode: couldn't read command result");
+ return 0;
+ }
+ buf[IRTOY_LEN_SAMPLEMODEPROTO] = 0;
+ if (buf[0] != IRTOY_REPLY_SAMPLEMODEPROTO) {
+ logprintf(LOG_ERR, "irtoy_enter_samplemode: invalid response %02X", buf[0]);
+ return 0;
+ }
+ LOGPRINTF(1, "irtoy_reset: Got protocol %s", buf);
+ dev->protoVersion = atoi(buf + 1);
+ return 1;
+}
+static irtoy_t *irtoy_hw_init(int fd)
+{
+ irtoy_t *dev = (irtoy_t *) malloc(sizeof(irtoy_t));
+ if (dev == NULL) {
+ logprintf(LOG_ERR, "irtoy_init: out of memory");
+ return NULL;
+ }
+ memset(dev, 0, sizeof(irtoy_t));
+ dev->awaitingNewSig = 1;
+ dev->fd = fd;
+ dev->pulse = 1;
+ irtoy_readflush(dev, IRTOY_TIMEOUT_FLUSH);
+ if (!irtoy_reset(dev) || !irtoy_getversion(dev) || !irtoy_enter_samplemode(dev)) {
+ free(dev);
+ dev = NULL;
+ return NULL;
+ }
+ return dev;
+}
+static int irtoy_init(void)
+{
+ if (!tty_create_lock(hw.device)) {
+ logprintf(LOG_ERR, "usb_irtoy: could not create lock files");
+ return(0);
+ }
+ if ((hw.fd = open(hw.device, O_RDWR | O_NONBLOCK | O_NOCTTY)) < 0) {
+ logprintf(LOG_ERR, "usb_irtoy: could not open %s", hw.device);
+ tty_delete_lock();
+ return(0);
+ }
+ if (!tty_reset(hw.fd)) {
+ logprintf(LOG_ERR, "usb_irtoy: could not reset tty");
+ close(hw.fd);
+ tty_delete_lock();
+ return(0);
+ }
+ if (!tty_setbaud(hw.fd, 115200)) {
+ logprintf(LOG_ERR, "usb_irtoy: could not set baud rate");
+ close(hw.fd);
+ tty_delete_lock();
+ return(0);
+ }
+ if (!tty_setcsize(hw.fd, 8)) {
+ logprintf(LOG_ERR, "usb_irtoy: could not set csize");
+ close(hw.fd);
+ tty_delete_lock();
+ return(0);
+ }
+ if (!tty_setrtscts(hw.fd, 1)) {
+ logprintf(LOG_ERR, "usb_irtoy: could not enable hardware flow");
+ close(hw.fd);
+ tty_delete_lock();
+ return(0);
+ }
+ if ((dev = irtoy_hw_init(hw.fd)) == NULL) {
+ logprintf(LOG_ERR, "usb_irtoy: No USB Irtoy device found at %s", hw.device);
+ close(hw.fd);
+ tty_delete_lock();
+ return(0);
+ }
+ LOGPRINTF(1, "Version hw %d, sw %d, protocol %d\n", dev->hwVersion, dev->swVersion, dev->protoVersion);
+ if (dev->swVersion < IRTOY_MINFWVERSION) {
+ logprintf(LOG_ERR, "usb_irtoy: Need firmware V%02d or higher, this firmware: %02d", IRTOY_MINFWVERSION, dev->swVersion);
+ free(dev);
+ return 0;
+ }
+ init_rec_buffer();
+ init_send_buffer();
+ return(1);
+}
+static int irtoy_deinit(void)
+{
+ // IMPORTANT do not remove this reset. it is vital to return the irtoy to IRMAN mode.
+ // If we leave the irtoy in sample mode while no-one has the tty open, the linux cdc_acm driver will fail on the next open.
+ // This is apparently due to data being sent while the tty is not open and fairly well known (google for "tty_port_close_start: tty->count = 1 port count = 0")
+ // IRMAN mode will wait until a signal is actually read before sending the next one, while sample mode will keep streaming (and under fluorescent light it WILL stream..)
+ // triggering the problem
+ irtoy_reset(dev);
+ free(dev);
+ dev = NULL;
+ close(hw.fd);
+ hw.fd = -1;
+ tty_delete_lock();
+ return 1;
+}
+static char *irtoy_rec(struct ir_remote *remotes)
+{
+ LOGPRINTF(1, "irtoy_raw_rec");
+ if (!clear_rec_buffer())
+ return(NULL);
+ return decode_all(remotes);
+}
+static int irtoy_send_double_buffered(unsigned char * signals, int length)
+{
+ int numToXmit = length;
+ int numThisTime;
+ int res;
+ unsigned char irToyBufLen;
+ unsigned char *txPtr;
+ unsigned char reply[16];
+ int irtoyXmit;
+ res = write(dev->fd, IRTOY_COMMAND_TXSTART, sizeof(IRTOY_COMMAND_TXSTART));
+ if (res != sizeof(IRTOY_COMMAND_TXSTART)) {
+ logprintf(LOG_ERR, "irtoy_send: couldn't write command");
+ return 0;
+ }
+ res = read_with_timeout(dev->fd, &irToyBufLen, 1, IRTOY_TIMEOUT_READYFORDATA);
+ if (res != 1) {
+ logprintf(LOG_ERR, "irtoy_send: couldn't read command result");
+ return -1;
+ }
+ LOGPRINTF(1, "irtoy ready for %d bytes\n", irToyBufLen);
+ txPtr = signals;
+ while (numToXmit) {
+ numThisTime = (numToXmit < irToyBufLen) ? numToXmit : irToyBufLen;
+ res = write(dev->fd, txPtr, numThisTime);
+ if (res != numThisTime) {
+ logprintf(LOG_ERR, "irtoy_send: couldn't write command");
+ return 0;
+ }
+ txPtr += numThisTime;
+ numToXmit -= numThisTime;
+ res = read_with_timeout(dev->fd, &irToyBufLen, 1, IRTOY_TIMEOUT_READYFORDATA);
+ if (res != 1) {
+ logprintf(LOG_ERR, "irtoy_send: couldn't read command result");
+ return -1;
+ }
+ LOGPRINTF(1, "irtoy ready for %d bytes\n", irToyBufLen);
+ }
+ res = read_with_timeout(dev->fd, reply, IRTOY_LEN_XMITRES, IRTOY_TIMEOUT_READYFORDATA);
+ if (res != IRTOY_LEN_XMITRES) {
+ logprintf(LOG_ERR, "irtoy_send: couldn't read command result");
+ return -1;
+ }
+ LOGPRINTF(1, "%c %02X %02X %c\n", reply[0], reply[1], reply[2], reply[3]);
+ if (reply[0] != IRTOY_REPLY_XMITCOUNT) {
+ logprintf(LOG_ERR, "irtoy_send: invalid byte count indicator received: %02X", reply[0]);
+ return 0;
+ }
+ irtoyXmit = (reply[1] << 8) | reply[2];
+ if (length != irtoyXmit) {
+ logprintf(LOG_ERR, "irtoy_send: incorrect byte count received: %d expected: %d", irtoyXmit, length);
+ return 0;
+ }
+ if (reply[3] != IRTOY_REPLY_XMITSUCCESS) {
+ logprintf(LOG_ERR, "irtoy_send: received error status %02X", reply[3]);
+ return 0;
+ }
+ return 1;
+}
+static int irtoy_send(struct ir_remote *remote, struct ir_ncode *code)
+{
+ int length;
+ lirc_t *signals;
+ int res = 0;
+ int numToXmit;
+ int i;
+ lirc_t val;
+ if (!init_send(remote, code)) {
+ return 0;
+ }
+ length = send_buffer.wptr;
+ signals = send_buffer.data;
+ for (i = 0; i < length; i++) {
+ val = (lirc_t)(((double) signals[i]) / IRTOY_UNIT);
+ rawSB[2*i] = val >> 8;
+ rawSB[2*i + 1] = val & 0xFF;
+ }
+ rawSB[2 * length] = 0xFF;
+ rawSB[2 * length + 1] = 0xFF;
+ numToXmit = 2 * length + 2;
+ return irtoy_send_double_buffered(rawSB, numToXmit);
+}
+
Index: lirc-0.9.0~pre1/setup.data
===================================================================
--- lirc-0.9.0~pre1.orig/setup.data 2010-10-26 19:31:24.000000000 +0200
+++ lirc-0.9.0~pre1/setup.data 2014-11-22 01:00:28.244352363 +0100
@@ -123,6 +123,7 @@
awlibusb: "Awox RF/IR Remote (userspace)"
sb0540: "Creative USB IR Receiver (SB0540)"
commandir: "CommandIR Multi-IR Transceiver (userspace)"
+ usb_irtoy: "Dangerous Prototypes USB Infrared Toy"
dfclibusb: "DFC USB InfraRed Remote Control (userspace)"
sasem: "Dign HV5 HTPC IR/VFD Module"
dvico: "DViCO USB Remote"
@@ -153,6 +154,7 @@
mplay: "VLSystem MPlay Mini"
mceusb: "Windows Media Center Transceivers/Remotes (all)"
+
param_type: \
act200l \
act220l \
@@ -196,6 +198,9 @@
usbx
ttyUSB:
+param_type: usb_irtoy
+ ttyACM:
+
param_type: \
adaptec \
alsa_usb \
@@ -406,6 +411,10 @@
usbx
ttyUSB1:
+default_param: usb_irtoy
+ ttyACM1:
+
+
remote: \
hauppauge \
hauppauge_dvb \
@@ -445,6 +454,7 @@
ttusbir \
uirt2_raw \
udp \
+ usb_irtoy \
usb_uirt_raw \
wpc8769l
any:
Index: lirc-0.9.0~pre1/setup.sh
===================================================================
--- lirc-0.9.0~pre1.orig/setup.sh 2010-10-26 19:32:18.000000000 +0200
+++ lirc-0.9.0~pre1/setup.sh 2014-11-22 01:00:28.252352120 +0100
@@ -65,6 +65,10 @@
elif test "$DRIVER_PARAMETER" = "ttyUSB2"; then COM2="on"; IRTTY="/dev/ttyUSB1"; LIRC_PORT="none"; LIRC_IRQ="none"
elif test "$DRIVER_PARAMETER" = "ttyUSB3"; then COM3="on"; IRTTY="/dev/ttyUSB2"; LIRC_PORT="none"; LIRC_IRQ="none"
elif test "$DRIVER_PARAMETER" = "ttyUSB4"; then COM4="on"; IRTTY="/dev/ttyUSB3"; LIRC_PORT="none"; LIRC_IRQ="none"
+ elif test "$DRIVER_PARAMETER" = "ttyACM1"; then COM1="on"; IRTTY="/dev/ttyACM0"; LIRC_PORT="none"; LIRC_IRQ="none"
+ elif test "$DRIVER_PARAMETER" = "ttyACM2"; then COM2="on"; IRTTY="/dev/ttyACM1"; LIRC_PORT="none"; LIRC_IRQ="none"
+ elif test "$DRIVER_PARAMETER" = "ttyACM3"; then COM3="on"; IRTTY="/dev/ttyACM2"; LIRC_PORT="none"; LIRC_IRQ="none"
+ elif test "$DRIVER_PARAMETER" = "ttyACM4"; then COM4="on"; IRTTY="/dev/ttyACM3"; LIRC_PORT="none"; LIRC_IRQ="none"
elif test "$DRIVER_PARAMETER" = "com1"; then COM1="on"; LIRC_PORT=$COM1_PORT; LIRC_IRQ=$COM1_IRQ
elif test "$DRIVER_PARAMETER" = "com2"; then COM2="on"; LIRC_PORT=$COM2_PORT; LIRC_IRQ=$COM2_IRQ
elif test "$DRIVER_PARAMETER" = "com3"; then COM3="on"; LIRC_PORT=$COM3_PORT; LIRC_IRQ=$COM3_IRQ
@@ -207,6 +211,30 @@
else
return 1;
fi
+ elif test "$DRIVER_PARAM_TYPE" = "ttyACM"; then
+ {
+ dialog --clear --backtitle "$BACKTITLE" \
+ --title "Select tty to use" \
+ --radiolist "$SET_TTY_TEXT" 13 74 6 \
+ 1 "/dev/ttyACM0" $COM1 \
+ 2 "/dev/ttyACM1" $COM2 \
+ 3 "/dev/ttyACM2" $COM3 \
+ 4 "/dev/ttyACM3" $COM4 \
+ 2> $TEMP
+ }
+ if test "$?" = "0"; then
+ {
+ set `cat $TEMP`
+ if test "$1" = "1"; then DRIVER_PARAMETER="ttyACM1"
+ elif test "$1" = "2"; then DRIVER_PARAMETER="ttyACM2"
+ elif test "$1" = "3"; then DRIVER_PARAMETER="ttyACM3"
+ elif test "$1" = "4"; then DRIVER_PARAMETER="ttyACM4"
+ fi
+ GetSelectedDriver
+ }
+ else
+ return 1;
+ fi
fi
return 0;
}
@@ -347,7 +375,7 @@
else echo "--without-timer \\" >>$START;
fi
}
- elif test "$DRIVER_PARAM_TYPE" = "tty" -o "$DRIVER_PARAM_TYPE" = "ttyUSB" -o "$LIRC_DRIVER" = "bte"; then
+ elif test "$DRIVER_PARAM_TYPE" = "tty" -o "$DRIVER_PARAM_TYPE" = "ttyUSB" -o "$DRIVER_PARAM_TYPE" = "ttyACM" -o "$LIRC_DRIVER" = "bte"; then
{
echo "--with-tty=$IRTTY \\" >>$START
}
@andrec0
Copy link

andrec0 commented Jul 1, 2016

Hi! Thanks for the how-to
It didn't work for me at first on my Raspberry pi 3 with Raspbian jessie
I got this error on almost every IR send:

irtoy_getversion: couldn't read version
please make sure you are using firmware v20 or higher

And then lirc crashes.

Then I raised the timeouts on the patch to:
+#define IRTOY_TIMEOUT_READYFORDATA 2000000
+#define IRTOY_TIMEOUT_FLUSH 20000
+#define IRTOY_TIMEOUT_SMODE_ENTER 1000000
+#define IRTOY_TIMEOUT_VERSION 1500000

Now it´s working beautifully :)

@eugenet8k
Copy link

eugenet8k commented Mar 27, 2017

While working with recent lirc 0.9.4d or even one built on master, I still had issues with USB IR-DROID device (based on IR Toys) failing in Raspberry Pi 3, but it seems @andrec0 suggestion totally helped. After rebuilding with increasing timeouts and rebuilding lirc from sources the connection to usb device is stable and doesn't fall after sending IR signals.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment