|
From: John W. <jo...@fe...> - 2010-09-26 05:37:47
|
The enclosed lightly tested patch has been used on FreeBSD 8.1 to control
a Comcast Branded Motorola DTA100 using an usb-uirt.
Changes:
1) Add flavor to tag_uirt2_t and move the structure to hw_uirt2_common.h
so it's visible to other routines. Set flavor in uirt2_getversion
based on whether GETVERSION receives a 3 byte or 8 byte response.
It appears from the protocol specs and talking to the firmware
author that the uirt2 always returns 3 bytes and the usb-uirt
always returns returns 8 bytes.
2) Handle DTR in the common uirt2_init / uirt2_uninit routines based on
the device flavor. Only some revisions of the usb-uirt need DTR cleared
... unfortunately there's no way to progmatically tell the hardware
revision so we just always clear DTR if we detect it's a usb-uirt
which should be fine for any usb-uirt hardware revision acccording
to the firmware author.
3) Implement usb_uirt_send_mode2_raw in order to handle some DOTXRAW
differences.
4) Have uirt2_send used the correct send_mode2_raw routine based on
the device flavor.
5) Have uirt2_send wait for the sequence to complete in order to
avoid corrupting the transmission (depending on the usb-uirt
hardware revision) by disturbing DTR.
-- John
------------------------8<------------------------------8<---------------
--- ./daemons/hw_uirt2_common.c.ORIGINAL 2010-08-27 01:08:09.000000000 -0400
+++ ./daemons/hw_uirt2_common.c 2010-09-25 16:04:47.000000000 -0400
@@ -52,16 +52,6 @@ LOGPRINTF(1, "time: %s %li %li", #a, (a)
#define HEXDUMP(buf, len)
#endif
-struct tag_uirt2_t {
- int fd;
- int flags;
- int version;
-
- struct timeval pre_delay;
- struct timeval pre_time;
- int new_signal;
-};
-
const int unit = UIRT2_UNIT;
//static int debug = 3;
@@ -335,7 +325,7 @@ static unsigned long calc_struct1_length
uirt2_t *uirt2_init(int fd)
{
- uirt2_t *dev = (uirt2_t *)malloc(sizeof(uirt2_t));
+ uirt2_t *dev = (uirt2_t *)calloc(1, sizeof(uirt2_t));
if(dev == NULL)
{
@@ -343,8 +333,6 @@ uirt2_t *uirt2_init(int fd)
return NULL;
}
- memset(dev, 0, sizeof(uirt2_t));
-
timerclear(&dev->pre_time);
dev->new_signal = 1;
dev->flags = UIRT2_MODE_UIR;
@@ -364,12 +352,32 @@ uirt2_t *uirt2_init(int fd)
dev->version);
}
+ if(dev->flavor == usb_uirt_flavor)
+ {
+ /*
+ * Later versions of the USB-UIRT use DTR as part
+ * of out-of-band signalling to enable emitters.
+ *
+ * Clearing DTR enables the builtin emitter.
+ */
+ if(!tty_setdtr(hw.fd, 0))
+ {
+ logprintf(LOG_ERR, "uirt2_raw: could not set DTR");
+ free(dev);
+ return NULL;
+ }
+ }
+
return dev;
}
int uirt2_uninit(uirt2_t *dev)
{
+ if(dev->flavor == usb_uirt_flavor)
+ {
+ tty_setdtr(hw.fd, 1);
+ }
free(dev);
return 0;
}
@@ -454,6 +462,7 @@ int uirt2_getversion(uirt2_t *dev, int *
if (command_ext(dev, in, out) >= 0) {
*version = out[2] + (out[1] << 8);
+ dev->flavor = uirt2_flavor;
return 0;
}
@@ -470,6 +479,7 @@ int uirt2_getversion(uirt2_t *dev, int *
out[0] = 8;
if (command_ext(dev, in, out) >= 0) {
*version = out[2] + (out[1] << 8);
+ dev->flavor = usb_uirt_flavor;
return 0;
}
--- ./daemons/hw_uirt2_common.h.ORIGINAL 2006-11-22 16:28:39.000000000 -0500
+++ ./daemons/hw_uirt2_common.h 2010-09-25 12:59:45.000000000 -0400
@@ -101,6 +101,17 @@ typedef struct {
remstruct1_data_t data;
} __attribute__ ((packed)) remstruct1_ext_t;
+struct tag_uirt2_t {
+ int fd;
+ int flags;
+ int version;
+ enum { unknown_uirt_flavor, uirt2_flavor, usb_uirt_flavor } flavor;
+
+ struct timeval pre_delay;
+ struct timeval pre_time;
+ int new_signal;
+};
+
typedef struct tag_uirt2_t uirt2_t;
typedef byte_t uirt2_code_t[UIRT2_CODE_SIZE];
--- ./daemons/hw_uirt2_raw.c.ORIGINAL 2010-08-27 01:08:09.000000000 -0400
+++ ./daemons/hw_uirt2_raw.c 2010-09-26 00:41:21.000000000 -0400
@@ -77,6 +77,8 @@ static int uirt2_send_mode2_raw(uirt2_t
static int uirt2_send_mode2_struct1(uirt2_t *dev,
struct ir_remote *remote,
lirc_t *buf, int length);
+static int usb_uirt_send_mode2_raw(uirt2_t *dev, struct ir_remote *remote,
+ lirc_t *buf, int length);
struct hardware hw_uirt2_raw =
{
@@ -213,7 +215,6 @@ static lirc_t uirt2_raw_readdata(lirc_t
static int uirt2_raw_init(void)
{
- int version;
if(!tty_create_lock(hw.device))
{
@@ -280,21 +281,6 @@ static int uirt2_raw_init(void)
return(0);
}
- if(uirt2_getversion(dev, &version) < 0)
- {
- uirt2_raw_deinit();
- return(0);
- }
- if(version >= 0x0905)
- {
- if(!tty_setdtr(hw.fd, 0))
- {
- logprintf(LOG_ERR, "uirt2_raw: could not set DTR");
- uirt2_raw_deinit();
- return(0);
- }
- }
-
init_rec_buffer();
init_send_buffer();
@@ -307,12 +293,7 @@ static int uirt2_raw_init(void)
static int uirt2_raw_deinit(void)
{
- int version;
-
- if(uirt2_getversion(dev, &version) >= 0 && version >= 0x0905)
- {
- tty_setdtr(hw.fd, 1);
- }
+
uirt2_uninit(dev);
dev = NULL;
close(hw.fd);
@@ -349,9 +330,11 @@ static char *uirt2_raw_rec(struct ir_rem
static int uirt2_send(struct ir_remote *remote,struct ir_ncode *code)
{
+ int i;
int length;
lirc_t *signals;
int res = 0;
+ unsigned long delay;
if(!init_send(remote,code)) {
return 0;
@@ -370,8 +353,9 @@ static int uirt2_send(struct ir_remote *
signals, length);
if (!res && (length < 48)) {
LOGPRINTF(1, "Using RAW transission");
- res = uirt2_send_mode2_raw(dev, remote,
- signals, length);
+ res = (dev->flavor == uirt2_flavor)
+ ? uirt2_send_mode2_raw(dev, remote, signals, length)
+ : usb_uirt_send_mode2_raw(dev, remote, signals, length);
}
if (!res) {
@@ -381,6 +365,20 @@ static int uirt2_send(struct ir_remote *
LOGPRINTF(1, "uirt2_send: succeeded");
}
+ /*
+ * Some devices send the sequence in the background. Wait for
+ * the sequence to complete before returning in order to avoid
+ * disturbing DTR which is used by certain hardware revisions
+ * to enable the builtin emitter. We wait 1.1 times the expected
+ * time in order to handle any differences between the device and
+ * our clock.
+ */
+ delay = remote->min_remaining_gap;
+ for (i = 0; i < length; i++)
+ delay += signals[i];
+ delay = (delay * 11) / 10;
+ usleep (delay);
+
return res;
}
@@ -438,6 +436,86 @@ static int uirt2_send_mode2_raw(uirt2_t
}
+static int usb_uirt_send_mode2_raw(uirt2_t *dev, struct ir_remote *remote,
+ lirc_t *buf, int length)
+{
+ byte_t tmp[68];
+ byte_t *ptr;
+ int freq;
+ int i;
+ int res;
+ int repeats = 1;
+ int tUnitRaw;
+ lirc_t width;
+
+ /*
+ * The UIRT2_DOTXRAW command as implemented by the USB-UIRT uses
+ * a different RAWSTRUCT layout than that used by the UIRT2.
+ */
+
+ LOGPRINTF(1, "usb_uirt_send_mode2_raw %d %p",
+ length, buf);
+
+ freq = remote->freq;
+ if(freq == 0) freq = DEFAULT_FREQ;
+
+ tmp[0] = (2500000 / freq) & 0x7f;
+ tmp[1] = (repeats & 0x1f);
+
+ tmp[2] = remote->min_remaining_gap / UIRT2_UNIT / 256;
+ tmp[3] = (remote->min_remaining_gap / UIRT2_UNIT) & 255;
+
+ tUnitRaw = (tmp[0] & 0x7f) * 1000000 / 2500000;
+
+ ptr = &tmp[5];
+
+ for (i = 0; i < length; i++) {
+
+ /*
+ * Ensure space is available for worst case width.
+ *
+ * The USB-UIRT documentation says that up to 23
+ * unique pulse / space combinations can be defined,
+ * however it's not clear what that means in actual
+ * buffer space since the widths can be one or two
+ * bytes. A quick look at the firmware suggests
+ * the command buffer goes from location 0x20 to
+ * 0x67 ... 71 bytes. A DOTXRAW command has 2
+ * bytes for the command and a 1 byte checksum.
+ * The remaining 68 bytes should be available for
+ * the RAWSTRUCT.
+ */
+ if ((ptr - tmp + 2) > sizeof (tmp)) {
+ logprintf(LOG_ERR,
+ "uirt2_raw: too long RAW transmission");
+ return 0;
+ }
+
+ /*
+ * Store width.
+ */
+ width = buf[i] / tUnitRaw;
+ if (width < 0x80)
+ *ptr++ = (byte_t)width;
+ else {
+ *ptr++ = (byte_t)(width / 256) | 0x80;
+ *ptr++ = (byte_t)(width & 255);
+ }
+ }
+
+ tmp[4] = ptr - &tmp[5];
+
+ res = uirt2_send_raw(dev, tmp, 5 + tmp[4]);
+
+ if (!res) {
+ return 0;
+ }
+
+ LOGPRINTF(1, "usb_uirt_send_mode2_raw exit");
+ return 1;
+}
+
+
static void set_data_bit(byte_t *dest, int offset, int bit)
{
int i = offset / 8;
-------------------------------------------------------------------------
| Feith Systems | Voice: 1-215-646-8000 | Email: jo...@fe... |
| John Wehle | Fax: 1-215-540-5495 | |
-------------------------------------------------------------------------
|