(see also message:
[patch 0/2] Change of libconcord API for IR codes learning - Build 20080628)
Patch installation:
===================
This patch should be applied to libconcord CVS release 0.20.
Install via:
cd <wherever>/libconcord
patch -p1 < libconcord-IRLearn-20080628.patch
TODO:
=====
While I managed to adapt the python bindings on my own, I would appreciate
any support to adapt the PERL bindings as well.
Any volunteers for testing on a Macintosh?
Detailed comments on changes:
=============================
Index: libconcord.h
===================================================================
+ * IR-stuff
-int learn_ir_commands(uint8_t *data, uint32_t size, int post);
+int get_key_names(uint8_t *data, uint32_t size,
+ char ***key_names, uint32_t *key_names_length);
+void delete_key_names(char **key_names, uint32_t key_names_length);
+int learn_from_remote(uint32_t *carrier_clock,
+ uint32_t **ir_signal, uint32_t *ir_signal_length);
+void delete_ir_signal(uint32_t *ir_signal);
+int encode_for_posting(uint32_t carrier_clock,
+ uint32_t *ir_signal, uint32_t ir_signal_length,
+ char **encoded_signal);
+void delete_encoded_signal(char *encoded_signal);
+int post_new_code(uint8_t *data, uint32_t size,
+ char *key_name, char *encoded_signal);
...
> redesign of IR learning API, see message [patch 0/2]...)
Index: libconcord.cpp
===================================================================
-#include <string.h>
+#include <string>
> fixed VC++ warning about deprecated include
- int u = 32;
+ uint32_t u = 32;
> fixed VC++ warning about comparing int to unsigned values
> this is always unsigned anyway
-int learn_ir_commands(uint8_t *data, uint32_t size, int post)
...
> redesign of IR learning API, see libconcord.h
Index: remote.h
===================================================================
-#define MAX_PULSE_COUNT 1000
+#define MAX_IR_SIGNAL_LENGTH 1000
> replaced 'pulse' by 'ir_signal', following Stephen's objection:
> pulse = mark+space, so allocated array would actually hold only 500
> pulses (=1000 mark/space durations).
- virtual int LearnIR(string *learn_string=NULL)=0;
+ virtual int LearnIR(uint32_t *freq, uint32_t **ir_signal,
+ uint32_t *ir_signal_length)=0;
> adapted to libconcord API change: return binary data instead of
> encoded string
- lc_callback cb=0, void *cb_arg=NULL);
+ lc_callback cb=NULL, void *cb_arg=NULL);
> make clear that default for callback is _NULL pointer_
Index: remote.cpp
===================================================================
-int handle_ir_response(uint8_t rsp[64], unsigned int &ir_word,
- unsigned int &t_on, unsigned int &t_off, unsigned int &pulse_count,
- unsigned int *&pulses, unsigned int &freq)
+int _handle_ir_response(uint8_t rsp[64], uint32_t &ir_word,
+ uint32_t &t_on, uint32_t &t_off, uint32_t &ir_signal_length,
+ uint32_t *&ir_signal, uint32_t &freq)
> 'unsigned int' replaced by 'uint32_t' for consistency
+ if ((len & 1) != 0) {
+ return 3; // Invalid length
+ }
> immediate return for bad length, saves one level of indent in the following
> (already deep indented) code; some linebreaks changed.
- const static uint8_t start_ir_learn[] = { COMMAND_START_IRCAP };
+ static const uint8_t start_ir_learn[] = { COMMAND_START_IRCAP };
+ static const uint8_t stop_ir_learn[] = { COMMAND_STOP_IRCAP };
+
> swapping 'const' and 'static' made kdevelop LSE happy (marked as error)
- err = 1;
+ err = LC_ERROR;
> use constant LC_ERROR
Index: web.h
===================================================================
+int encode_ir_signal(uint32_t carrier_clock,
+ uint32_t *ir_signal, uint32_t ir_signal_length,
+ string *learn_seq);
> adapted to libconcord API change: provide encoding of binary data to
> posting format
Index: web.cpp
===================================================================
- if (search - data >= data_size) {
+ if (search >= data + data_size) {
> fixed VC++ warning about comparing signed and unsigned - for the compiler,
> in theory (search - data) might become negative...
Index: bindings/python/libconcord.py
===================================================================
> adapted to libconcord API change
+# void delete_blob(uint8_t *ptr);
+ delete_blob = _create_func(
> fixed return type (int -> void) and typo (delete_block -> _blob)
Index: win/libconcord.def
===================================================================
> adapted to libconcord API change
Index: libconcord/libconcord.cpp
===================================================================
RCS file: /cvsroot/concordance/concordance/libconcord/libconcord.cpp,v
retrieving revision 1.35
diff -u -3 -p -u -p -r1.35 libconcord.cpp
--- libconcord/libconcord.cpp 14 Apr 2008 07:27:58 -0000 1.35
+++ libconcord/libconcord.cpp 28 Jun 2008 12:45:25 -0000
@@ -27,7 +27,7 @@
*/
#include <stdio.h>
-#include <string.h>
+#include <string>
#include <stdlib.h>
#include "libconcord.h"
#include "lc_internal.h"
@@ -39,6 +39,7 @@
#include "protocol.h"
#include "time.h"
#include <errno.h>
+#include <list>
#define ZWAVE_HID_PID_MIN 0xC112
#define ZWAVE_HID_PID_MAX 0xC115
@@ -1170,7 +1171,7 @@ int write_firmware_to_file(uint8_t *in,
do {
of.write("\t\t\t<DATA>");
char hex[16];
- int u = 32;
+ uint32_t u = 32;
if (u > size) {
u = size;
}
@@ -1224,41 +1225,196 @@ int extract_firmware_binary(uint8_t *xml
* IR stuff
*/
-int learn_ir_commands(uint8_t *data, uint32_t size, int post)
+/*
+ * List of key names to be learned is passed in section INPUTPARMS
+ * as e.g.:
+ * <PARAMETER><KEY>KeyName</KEY><VALUE>PowerToggle</VALUE></PARAMETER>
+ * First of these is repeated in section PARAMETERS, so we must
+ * concentrate on INPUTPARMS to avoid duplication.
+ */
+
+/*
+ * locate the INPUTPARMS section in *data:
+ */
+int _init_key_scan(uint8_t *data, uint32_t size,
+ uint8_t **inputparams_start, uint8_t **inputparams_end)
{
int err;
-
- if (data) {
- uint8_t *t = data;
- string keyname;
- do {
- err = GetTag("KEY", t, size - (t - data), t, &keyname);
- if (err != 0) {
- return err;
- }
- } while (keyname != "KeyName");
- uint8_t *n = 0;
- err = GetTag("VALUE", t, size, n, &keyname);
+
+ /* locating start tag "<INPUTPARMS>" */
+ err = GetTag("INPUTPARMS", data, size, *inputparams_start);
+ if (err == 0) {
+ /* locating end tag "</INPUTPARMS>" */
+ err = GetTag("/INPUTPARMS", *inputparams_start,
+ size - (*inputparams_start-data), *inputparams_end);
+ }
+ return err;
+}
+
+int _next_key_name(uint8_t **start, uint8_t *inputparams_end, string *keyname)
+{
+ int err;
+ /*
+ * to be really paranoid, we would have to narrow the search range
+ * further down to next <PARAMETER>...</PARAMETER>, but IMHO it
+ * should be safe to assume that Logitech always sends sane files:
+ */
+ do {
+ err = GetTag("KEY", *start, (inputparams_end - *start),
+ *start, keyname);
if (err != 0) {
return err;
}
- printf("Key Name: %s\n",keyname.c_str());
+ } while (*keyname != "KeyName");
- string ls;
- rmt->LearnIR(&ls);
- debug("Learned code: %s",ls.c_str());
-
- if (post) {
- Post(data, size, "POSTOPTIONS", ri, true, false, &ls,
- &keyname);
- }
- } else {
- rmt->LearnIR();
+ err = GetTag("VALUE", *start, (inputparams_end - *start),
+ *start, keyname);
+
+ if (err == 0) {
+ /* found next key name : */
+ debug("Key Name: %s\n", (*keyname).c_str());
}
+ return err;
+}
+
+int get_key_names(uint8_t *data, uint32_t size,
+ char ***key_names, uint32_t *key_names_length)
+{
+ uint8_t *cursor = data;
+ uint8_t *inputparams_end;
+ uint32_t key_index = 0;
+ std::list<string> key_list;
+ string key_name;
+
+ if ((data == NULL) || (size == 0) ||
+ (key_names == NULL) || (key_names_length == NULL)) {
+ return LC_ERROR;
+ }
+ /* setup data scanning, locating start and end of keynames section: */
+ if (_init_key_scan(data, size, &cursor, &inputparams_end) != 0) {
+ return LC_ERROR;
+ }
+
+ /* scan for key names and append found names to list: */
+ while (_next_key_name(&cursor, inputparams_end, &key_name) == 0) {
+ key_list.push_back(key_name);
+ }
+
+ if (key_list.size() == 0) {
+ return LC_ERROR;
+ }
+
+ *key_names_length = key_list.size();
+ *key_names = new char*[*key_names_length];
+
+ /* copy list of found names to allocated buffer: */
+ for (list<string>::const_iterator cursor = key_list.begin();
+ cursor != key_list.end(); ++cursor) {
+ (*key_names)[key_index++] = strdup((*cursor).c_str());
+ }
return 0;
+ /* C++ should take care of key_name and key_list */
+}
+
+/*
+ * Free memory allocated by get_key_names:
+ */
+void delete_key_names(char **key_names, uint32_t key_names_length)
+{
+ uint32_t key_count = 0;
+ if (key_names != NULL) {
+ for (key_count = 0; key_count < key_names_length; key_count++) {
+ free(key_names[key_count]);
+ /* allocated by strdup -> free() */
+ }
+ delete[](key_names); /* allocated by new[] -> delete[] */
+ }
+}
+
+/*
+ * Fill ir_data with IR code learned from other remote
+ * via Harmony IR receiver.
+ * Returns 0 for success, error code for failure.
+ */
+int learn_from_remote(uint32_t *carrier_clock,
+ uint32_t **ir_signal, uint32_t *ir_signal_length)
+{
+ if (rmt == NULL){
+ return LC_ERROR_CONNECT;
+ }
+ if ((carrier_clock == NULL) ||
+ (ir_signal == NULL) || (ir_signal_length == NULL)){
+ /* nothing to write to: */
+ return LC_ERROR;
+ }
+
+ /* try to learn code via Harmony from original remote: */
+ return rmt->LearnIR(carrier_clock, ir_signal, ir_signal_length);
+}
+
+/*
+ * Free memory allocated by learn_from_remote:
+ */
+void delete_ir_signal(uint32_t *ir_signal)
+{
+ delete [] ir_signal; /* allocated by new[] -> delete[] */
+}
+
+/*
+ * Fill encoded_signal with IR code encoded to Logitech
+ * posting string format.
+ * Returns 0 for success, error code in case of failure.
+ */
+int encode_for_posting(uint32_t carrier_clock,
+ uint32_t *ir_signal, uint32_t ir_signal_length,
+ char **encoded_signal)
+{
+ int err = 0;
+ string encoded;
+ if ((ir_signal == NULL) || (ir_signal_length == 0) ||
+ (encoded_signal == NULL)) {
+ return LC_ERROR; /* cannot do anything without */
+ }
+ err = encode_ir_signal(carrier_clock,
+ ir_signal, ir_signal_length, &encoded);
+ if (err == 0) {
+ debug("Learned code: %s",encoded.c_str());
+ *encoded_signal = strdup(encoded.c_str());
+ }
+ return err;
}
+/*
+ * Free memory allocated by encode_for_posting:
+ */
+void delete_encoded_signal(char *encoded_signal)
+{
+ free(encoded_signal); /* allocated by strdup -> free() */
+}
+
+/*
+ * Post encoded IR-code with key_name and additional
+ * information from XML data[size] to Logitech.
+ * Returns 0 for success, error code for failure.
+ */
+int post_new_code(uint8_t *data, uint32_t size,
+ char *key_name, char *encoded_signal)
+{
+ string learn_key;
+ string learn_seq;
+
+ if ((key_name == NULL) || (encoded_signal == NULL) ||
+ (data == NULL) || (size == 0)) {
+ return LC_ERROR_POST; /* cannot do anything without */
+ }
+
+ learn_key = key_name;
+ learn_seq = encoded_signal;
+
+ return Post(data, size, "POSTOPTIONS", ri, true, false,
+ &learn_seq, &learn_key);
+}
/*
* PRIVATE-SHARED INTERNAL FUNCTIONS
Index: libconcord/libconcord.h
===================================================================
RCS file: /cvsroot/concordance/concordance/libconcord/libconcord.h,v
retrieving revision 1.19
diff -u -3 -p -u -p -r1.19 libconcord.h
--- libconcord/libconcord.h 11 Apr 2008 05:05:26 -0000 1.19
+++ libconcord/libconcord.h 28 Jun 2008 12:45:25 -0000
@@ -382,10 +382,85 @@ int extract_firmware_binary(uint8_t *xml
uint32_t *size);
/*
- * IR-stuff. This stuff hasn't yet been cleaned up, you'll have to
- * dig in yourself.
+ * IR-stuff
+ * ===========================
+ * Data structure information:
+ *
+ * carrier_clock : in Hz, usually ~36000..40000
+ * ir_signal : IR mark/space durations (alternating) in microsconds
+ * ir_signal_length : total number of mark/space durations in ir_signal
+ * ir_signal will start with a mark and end with a space duration,
+ * hence ir_signal_length will always be an even number.
+ *
+ * They are usually filled in by calling learn_from_remote(...),
+ * to learn IR signals from an existing other remote, but may also
+ * be set by the application, e.g. be derived from Pilips Pronto Hex
+ * codes or RC5/NEC/... command codes (separate conversion library required).
+ *
+ * encoded posting format : IR code data converted to Logitech
+ * posting string format, returned by encode_for_posting.
+ * Having the encoding separate from the posting keeps the
+ * parameter list of post_new_code() tidy and allows the
+ * application to display the encoded signal when desired.
*/
-int learn_ir_commands(uint8_t *data, uint32_t size, int post);
+
+/*
+ * Scan the contents of the received LearnIR.EZTut file
+ * (read into *data[size]) for the key names to be learned.
+ *
+ * Fills key_names with the found names and key_names_length
+ * with the number of found key names.
+ * Returns 0 for success, or an error code in case of failure.
+ *
+ * Memory allocated for the strings must be freed by the caller
+ * via delete_key_names() when not needed any longer.
+ */
+int get_key_names(uint8_t *data, uint32_t size,
+ char ***key_names, uint32_t *key_names_length);
+
+void delete_key_names(char **key_names, uint32_t key_names_length);
+
+/*
+ * Fill ir_data with IR code learned from other remote
+ * via Harmony IR receiver.
+ *
+ * Returns 0 for success, error code for failure.
+ *
+ * Memory allocated for ir_signal must be freed by the caller
+ * via delete_ir_signal() when not needed any longer.
+ */
+int learn_from_remote(uint32_t *carrier_clock,
+ uint32_t **ir_signal, uint32_t *ir_signal_length);
+
+void delete_ir_signal(uint32_t *ir_signal);
+
+/*
+ * Fill encoded_signal with IR code encoded to Logitech
+ * posting string format.
+ *
+ * Returns 0 for success, error code in case of failure.
+ *
+ * Memory allocated for the string must be freed by the caller
+ * via delete_post_string() when not needed any longer.
+ */
+int encode_for_posting(uint32_t carrier_clock,
+ uint32_t *ir_signal, uint32_t ir_signal_length,
+ char **encoded_signal);
+
+void delete_encoded_signal(char *encoded_signal);
+
+/*
+ * Post encoded IR-code with key_name and additional
+ * information from XML data[size] to Logitech.
+ *
+ * Logitech will only accept keynames already present in the
+ * database or user-defined via 'Learn new Key' web page
+ * for the current device.
+ *
+ * Returns 0 for success, error code for failure.
+ */
+int post_new_code(uint8_t *data, uint32_t size,
+ char *key_name, char *encoded_signal);
#ifdef __cplusplus
}
Index: libconcord/remote.cpp
===================================================================
RCS file: /cvsroot/concordance/concordance/libconcord/remote.cpp,v
retrieving revision 1.34
diff -u -3 -p -u -p -r1.34 remote.cpp
--- libconcord/remote.cpp 14 Apr 2008 08:07:07 -0000 1.34
+++ libconcord/remote.cpp 28 Jun 2008 12:45:25 -0000
@@ -643,124 +643,116 @@ bool check_seq(int received_seq, uint8_t
}
}
-int handle_ir_response(uint8_t rsp[64], unsigned int &ir_word,
- unsigned int &t_on, unsigned int &t_off, unsigned int &pulse_count,
- unsigned int *&pulses, unsigned int &freq)
+int _handle_ir_response(uint8_t rsp[64], uint32_t &ir_word,
+ uint32_t &t_on, uint32_t &t_off, uint32_t &ir_signal_length,
+ uint32_t *&ir_signal, uint32_t &freq)
{
- const unsigned int len = rsp[63];
- if ((len & 1) == 0) {
- for (unsigned int u = 2; u < len; u += 2) {
- const unsigned int t = rsp[u] << 8 | rsp[1+u];
- if (ir_word > 2) {
- /*
- * For ODD words, t is the total time, we'll
- * update the total OFF time and be done.
- *
- * For EVEN words, t is just the ON time
- * -- IF we have any ON time, then we go ahead
- * and record the off and on times we should
- * have now gathered.
- *
- * Why do we differentiate between even/odd?
- * Perhaps just to make sure we've had two
- * cycles, and thus have off/on?
- */
- if (ir_word & 1) {
- // t == on + off time
- if (t_on)
- t_off = t-t_on;
- else
- t_off += t;
+ const uint32_t len = rsp[63];
+ if ((len & 1) != 0) {
+ return 3; // Invalid length
+ }
+
+ for (uint32_t u = 2; u < len; u += 2) {
+ const uint32_t t = rsp[u] << 8 | rsp[1+u];
+ if (ir_word > 2) {
+ /*
+ * For ODD words, t is the total time, we'll
+ * update the total OFF time and be done.
+ *
+ * For EVEN words, t is just the ON time
+ * -- IF we have any ON time, then we go ahead and record the
+ * off and on times we should have now gathered.
+ *
+ * Why do we differentiate between even/odd?
+ * Perhaps just to make sure we've had two
+ * cycles, and thus have off/on?
+ */
+ if (ir_word & 1) {
+ // t == on + off time
+ if (t_on) {
+ t_off = t-t_on;
} else {
- // t == on time
- t_on = t;
- if (t_on) {
- debug("-%i\n", t_off);
- if (pulse_count <
- MAX_PULSE_COUNT)
- pulses[pulse_count++] =
- t_off;
- debug("+%i\n", t_on);
- if (pulse_count <
- MAX_PULSE_COUNT)
- pulses[pulse_count++] =
- t_on;
- }
+ t_off += t;
}
} else {
- /*
- * For the first 3 words...
- * the first one, we ignore, apparently
- * the second one, we start keeping track
- * of ON time
- * the third one, we have enough data to
- * calculate the frequency and record
- * the on time we've calculated
- */
- switch (ir_word) {
- case 0:
- // ???
- break;
- case 1:
- // on time of
- // first burst
- t_on = t;
- break;
- case 2:
- // pulse count of
- // first burst
- if (t_on) {
- freq = static_cast<unsigned int>(static_cast<uint64_t>(t)*1000000/t_on);
- debug("%i Hz",freq);
- debug("+%i",t_on);
- pulses[pulse_count++] =
- t_on;
- }
- break;
+ // t == on time
+ t_on = t;
+ if (t_on) {
+ debug("-%i\n", t_off);
+ if (ir_signal_length < MAX_IR_SIGNAL_LENGTH) {
+ ir_signal[ir_signal_length++] = t_off;
+ }
+ debug("+%i\n", t_on);
+ if (ir_signal_length < MAX_IR_SIGNAL_LENGTH) {
+ ir_signal[ir_signal_length++] = t_on;
+ }
}
}
- ++ir_word;
+ } else {
+ /*
+ * For the first 3 words...
+ * the first one, we ignore, apparently
+ * the second one, we start keeping track of ON time
+ * the third one, we have enough data to calculate the
+ * frequency and record the on time we've calculated
+ */
+ switch (ir_word) {
+ case 0: // ???
+ break;
+ case 1: // on time of first burst
+ t_on = t;
+ break;
+ case 2: // carrier cycle count of first burst
+ if (t_on) {
+ freq = static_cast<uint32_t>(
+ static_cast<uint64_t>(t)*1000000/(t_on));
+ debug("%i Hz",freq);
+ debug("+%i",t_on);
+ ir_signal[ir_signal_length++] = t_on;
+ }
+ break;
+ }
}
- } else {
- // Invalid length
- return 3;
+ ++ir_word;
}
return 0;
}
-int CRemote::LearnIR(string *learn_string)
+
+int CRemote::LearnIR(uint32_t *freq, uint32_t **ir_signal, uint32_t *ir_signal_length)
{
int err = 0;
uint8_t rsp[68];
- const static uint8_t start_ir_learn[] = { COMMAND_START_IRCAP };
- if ((err = HID_WriteReport(start_ir_learn)))
- return err;
+ static const uint8_t start_ir_learn[] = { COMMAND_START_IRCAP };
+ static const uint8_t stop_ir_learn[] = { COMMAND_STOP_IRCAP };
+
+ err = HID_WriteReport(start_ir_learn);
+ if (err != 0) { return err; }
uint8_t seq = 0;
// Count of how man IR words we've received.
- unsigned int ir_word = 0;
+ uint32_t ir_word = 0;
// Time button is on and off
- unsigned int t_on = 0;
- unsigned int t_off = 0;
-
- // Frequency button emits
- unsigned int freq = 0;
- // Pulse map
- unsigned int *pulses = new unsigned int[MAX_PULSE_COUNT];
- unsigned int pulse_count = 0;
+ uint32_t t_on = 0;
+ uint32_t t_off = 0;
+ *ir_signal_length = 0;
+ *ir_signal = new uint32_t[MAX_IR_SIGNAL_LENGTH];
/*
+ * Caller is responsible for deallocation of *ir_signal after use.
+ *
* Loop while we have no error and we haven't had 500,000us of
- * any pulses
+ * any ir_signal
*/
while (err == 0 && t_off < 500000) {
- if ((err = HID_ReadReport(rsp, ir_word ? 500 : 4000)))
+ if ((err = HID_ReadReport(rsp, ir_word ? 500 : 4000))) {
break;
+ }
const uint8_t r = rsp[0] & COMMAND_MASK;
if (r == RESPONSE_IRCAP_DATA) {
if (!check_seq(rsp[1], seq)) {
- err = 1;
+ err = LC_ERROR;
break;
}
seq += 0x10;
@@ -769,8 +761,8 @@ int CRemote::LearnIR(string *learn_strin
* t_off so we can exit the loop if long enough time
* goes by without action.
*/
- err = handle_ir_response(rsp, ir_word, t_on, t_off,
- pulse_count, pulses, freq);
+ err = _handle_ir_response(rsp, ir_word, t_on, t_off,
+ *ir_signal_length, *ir_signal, *freq);
if (err != 0) {
break;
}
@@ -778,42 +770,29 @@ int CRemote::LearnIR(string *learn_strin
break;
} else {
debug("Invalid response [%02X]", rsp[1]);
- err = 1;
+ err = LC_ERROR;
}
}
- if (t_off)
- debug("-%i", t_off);
-
- /* make sure we record a final off? */
- if (pulse_count < MAX_PULSE_COUNT)
- pulses[pulse_count++] = t_off;
+ if ((err == 0) && (*ir_signal_length > 0)) {
+ /* we have actually got some signal */
+ if (t_off) {
+ debug("-%i", t_off);
+ }
+ /* make sure we record a final off */
+ if (*ir_signal_length < MAX_IR_SIGNAL_LENGTH) {
+ (*ir_signal)[(*ir_signal_length)++] = t_off;
+ }
+ }
- const static uint8_t stop_ir_learn[] = { COMMAND_STOP_IRCAP };
HID_WriteReport(stop_ir_learn);
/* read returned RESPONSE_DONE, otherwise next command wil fail! */
- err = HID_ReadReport(rsp);
- if (err == 0) {
+ if (HID_ReadReport(rsp) == 0) {
if ((rsp[0] & COMMAND_MASK) != RESPONSE_DONE) {
- err = 1;
+ err = LC_ERROR;
}
}
- /*
- * Encode our pulses into string
- */
- if (err == 0 && learn_string != NULL) {
- char s[32];
- sprintf(s, "F%04X", freq);
- *learn_string = s;
- for (unsigned int n = 0; n < pulse_count; ) {
- sprintf(s, "P%04X", pulses[n++]);
- *learn_string += s;
- sprintf(s, "S%04X", pulses[n++]);
- *learn_string += s;
- }
- }
-
return err;
}
Index: libconcord/remote.h
===================================================================
RCS file: /cvsroot/concordance/concordance/libconcord/remote.h,v
retrieving revision 1.17
diff -u -3 -p -u -p -r1.17 remote.h
--- libconcord/remote.h 11 Apr 2008 05:05:26 -0000 1.17
+++ libconcord/remote.h 28 Jun 2008 12:45:25 -0000
@@ -27,7 +27,7 @@
#define FLASH_EEPROM_ADDR 0x10
#define FLASH_SERIAL_ADDR 0x000110
#define FLASH_SIZE 48
-#define MAX_PULSE_COUNT 1000
+#define MAX_IR_SIGNAL_LENGTH 1000
/*
* WARNING: Do not change this!
@@ -147,7 +147,8 @@ public:
virtual int GetTime(const TRemoteInfo &ri, THarmonyTime &ht)=0;
virtual int SetTime(const TRemoteInfo &ri, const THarmonyTime &ht)=0;
- virtual int LearnIR(string *learn_string=NULL)=0;
+ virtual int LearnIR(uint32_t *freq, uint32_t **ir_signal,
+ uint32_t *ir_signal_length)=0;
};
class CRemote : public CRemoteBase // All non-Z-Wave remotes
@@ -171,7 +172,7 @@ public:
int ReadFlash(uint32_t addr, const uint32_t len, uint8_t *rd,
unsigned int protocol, bool verify=false,
- lc_callback cb=0, void *cb_arg=NULL);
+ lc_callback cb=NULL, void *cb_arg=NULL);
int InvalidateFlash(void);
int EraseFlash(uint32_t addr, uint32_t len, const TRemoteInfo &ri,
lc_callback cb=NULL, void *cb_arg=NULL);
@@ -185,7 +186,7 @@ public:
int GetTime(const TRemoteInfo &ri, THarmonyTime &ht);
int SetTime(const TRemoteInfo &ri, const THarmonyTime &ht);
- int LearnIR(string *learn_string=NULL);
+ int LearnIR(uint32_t *freq, uint32_t **ir_signal, uint32_t *ir_signal_length);
};
// Base class for all Z-Wave remotes
@@ -212,7 +213,7 @@ public:
int ReadFlash(uint32_t addr, const uint32_t len, uint8_t *rd,
unsigned int protocol, bool verify=false,
- lc_callback cb=0, void *cb_arg=NULL);
+ lc_callback cb=NULL, void *cb_arg=NULL);
int InvalidateFlash(void);
int EraseFlash(uint32_t addr, uint32_t len, const TRemoteInfo &ri,
lc_callback cb=NULL, void *cb_arg=NULL);
@@ -226,7 +227,7 @@ public:
int GetTime(const TRemoteInfo &ri, THarmonyTime &ht);
int SetTime(const TRemoteInfo &ri, const THarmonyTime &ht);
- int LearnIR(string *learn_string=NULL);
+ int LearnIR(uint32_t *freq, uint32_t **ir_signal, uint32_t *ir_signal_length);
};
// 890, 890Pro, AVL-300, RF Extender
Index: libconcord/remote_z.cpp
===================================================================
RCS file: /cvsroot/concordance/concordance/libconcord/remote_z.cpp,v
retrieving revision 1.18
diff -u -3 -p -u -p -r1.18 remote_z.cpp
--- libconcord/remote_z.cpp 11 Apr 2008 05:05:26 -0000 1.18
+++ libconcord/remote_z.cpp 28 Jun 2008 12:45:25 -0000
@@ -353,7 +353,8 @@ int CRemoteZ_Base::SetTime(const TRemote
return 1;
}
-int CRemoteZ_Base::LearnIR(string *learn_string)
+int CRemoteZ_Base::LearnIR(uint32_t *freq,
+ uint32_t **ir_signal, uint32_t *ir_signal_length)
{
return 0;
}
Index: libconcord/web.cpp
===================================================================
RCS file: /cvsroot/concordance/concordance/libconcord/web.cpp,v
retrieving revision 1.26
diff -u -3 -p -u -p -r1.26 web.cpp
--- libconcord/web.cpp 14 Apr 2008 02:32:00 -0000 1.26
+++ libconcord/web.cpp 28 Jun 2008 12:45:25 -0000
@@ -160,7 +160,7 @@ int GetTag(const char *find, uint8_t* da
if (*search == '<') {
break;
}
- if (search - data >= data_size) {
+ if (search >= data + data_size) {
return -1;
}
search++;
@@ -194,7 +194,7 @@ int GetTag(const char *find, uint8_t* da
while (*search && *search != '<') {
*s += *search;
search++;
- if (search - data >= data_size) {
+ if (search >= data + data_size) {
break;
}
}
@@ -207,7 +207,7 @@ int GetTag(const char *find, uint8_t* da
if (*search == '>') {
break;
}
- if (search - data >= data_size) {
+ if (search >= data + data_size) {
return -1;
}
search++;
@@ -215,6 +215,42 @@ int GetTag(const char *find, uint8_t* da
}
}
+int encode_ir_signal(uint32_t carrier_clock,
+ uint32_t *ir_signal, uint32_t ir_signal_length,
+ string *learn_seq)
+{ /*
+ * Encode ir_signal into string accepted by Logitech server
+ */
+ char s[32];
+
+ if ((learn_seq == NULL) ||
+ (ir_signal == NULL) || (ir_signal_length == 0)) {
+ return LC_ERROR;
+ }
+ if (carrier_clock > 0xFFFF) {
+ sprintf(s, "F%08X", carrier_clock);
+ } else {
+ sprintf(s, "F%04X", carrier_clock);
+ }
+ *learn_seq = s;
+ for (unsigned int n = 0; n < ir_signal_length; ) {
+ if (ir_signal[n] > 0xFFFF) {
+ sprintf(s, "P%08X", ir_signal[n++]);
+ } else {
+ sprintf(s, "P%04X", ir_signal[n++]);
+ }
+ *learn_seq += s;
+ if (ir_signal[n] > 0xFFFF) {
+ sprintf(s, "S%08X", ir_signal[n++]);
+ } else {
+ sprintf(s, "S%04X", ir_signal[n++]);
+ }
+ *learn_seq += s;
+ }
+ return 0;
+}
+
+
int Post(uint8_t *xml, uint32_t xml_size, const char *root, TRemoteInfo &ri,
bool has_userid, bool add_cookiekeyval = false,
string *learn_seq = NULL, string *learn_key = NULL)
Index: libconcord/web.h
===================================================================
RCS file: /cvsroot/concordance/concordance/libconcord/web.h,v
retrieving revision 1.10
diff -u -3 -p -u -p -r1.10 web.h
--- libconcord/web.h 14 Apr 2008 02:32:00 -0000 1.10
+++ libconcord/web.h 28 Jun 2008 12:45:25 -0000
@@ -25,6 +25,11 @@
int GetTag(const char *find, uint8_t* data, uint32_t data_size,
uint8_t *&found, string *s = NULL);
+
+int encode_ir_signal(uint32_t carrier_clock,
+ uint32_t *ir_signal, uint32_t ir_signal_length,
+ string *learn_seq);
+
int Post(uint8_t *xml, uint32_t xml_size, const char *root, TRemoteInfo &ri,
bool has_userid, bool add_cookiekeyval = false,
string *learn_seq=NULL, string *learn_key=NULL);
Index: libconcord/bindings/python/libconcord.py
===================================================================
RCS file: /cvsroot/concordance/concordance/libconcord/bindings/python/libconcord.py,v
retrieving revision 1.1
diff -u -3 -p -u -p -r1.1 libconcord.py
--- libconcord/bindings/python/libconcord.py 8 Apr 2008 09:50:29 -0000 1.1
+++ libconcord/bindings/python/libconcord.py 28 Jun 2008 12:45:26 -0000
@@ -55,7 +55,8 @@ class _CheckRetCode(object):
result = args[0]
if result != 0:
raise LibConcordException(self.func_name, result)
-
+ return result
+
# Internal ctypes function wrapper creation
def _create_func(
func_name,
@@ -321,11 +322,11 @@ get_time_timezone = _create_func(
c_char_p
)
-# int delete_blob(uint8_t *ptr);
+# void delete_blob(uint8_t *ptr);
delete_block = _create_func(
'delete_blob',
- _CheckRetCode,
- c_int,
+ None,
+ None,
POINTER(c_ubyte)
);
@@ -630,13 +631,85 @@ extract_firmware_binary = _create_func(
POINTER(c_uint)
)
-# int learn_ir_commands(uint8_t *data, uint32_t size, int post);
-learn_ir_commands = _create_func(
- 'learn_ir_commands',
+# IR-stuff
+# ===========================
+
+# int get_key_names(uint8_t *data, uint32_t size,
+# char ***key_names, uint32_t *key_names_length);
+
+get_key_names = _create_func(
+ 'get_key_names',
_CheckRetCode,
c_int,
POINTER(c_ubyte),
c_uint,
- c_int
+ POINTER(POINTER(c_char_p)),
+ POINTER(c_uint)
+)
+
+# void delete_key_names(char **key_names, uint32_t key_names_length);
+
+delete_key_names = _create_func(
+ 'delete_key_names',
+ None,
+ None,
+ POINTER(c_char_p),
+ c_uint
+)
+
+# int learn_from_remote(uint32_t *carrier_clock,
+# uint32_t **ir_signal, uint32_t *ir_signal_length);
+
+learn_from_remote = _create_func(
+ 'learn_from_remote',
+ _CheckRetCode,
+ c_int,
+ POINTER(c_uint),
+ POINTER(POINTER(c_uint)),
+ POINTER(c_uint)
+)
+
+# void delete_ir_signal(uint32_t *ir_signal);
+
+delete_ir_signal = _create_func(
+ 'delete_ir_signal',
+ None,
+ None,
+ POINTER(c_uint)
)
+# int encode_for_posting(uint32_t carrier_clock,
+# uint32_t *ir_signal, uint32_t ir_signal_length,
+# char **encoded_signal);
+
+encode_for_posting = _create_func(
+ 'encode_for_posting',
+ _CheckRetCode,
+ c_int,
+ c_uint,
+ POINTER(c_uint),
+ c_uint,
+ POINTER(c_char_p)
+)
+
+# void delete_encoded_signal(char *encoded_signal);
+
+delete_encoded_signal = _create_func(
+ 'delete_encoded_signal',
+ None,
+ None,
+ c_char_p
+)
+
+# int post_new_code(uint8_t *data, uint32_t size,
+# char *key_name, char *encoded_signal);
+
+post_new_code = _create_func(
+ 'post_new_code',
+ _CheckRetCode,
+ c_int,
+ POINTER(c_ubyte),
+ c_uint,
+ c_char_p,
+ c_char_p
+)
Index: libconcord/win/libconcord.def
===================================================================
RCS file: /cvsroot/concordance/concordance/libconcord/win/libconcord.def,v
retrieving revision 1.8
diff -u -3 -p -u -p -r1.8 libconcord.def
--- libconcord/win/libconcord.def 4 Apr 2008 05:21:03 -0000 1.8
+++ libconcord/win/libconcord.def 28 Jun 2008 12:45:26 -0000
@@ -92,5 +92,14 @@ write_firmware_to_file
extract_firmware_binary
; IR-stuff
-;
-learn_ir_commands
+get_key_names
+delete_key_names
+
+learn_from_remote
+delete_ir_signal
+
+encode_for_posting
+delete_encoded_signal
+
+post_new_code
+
-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
concordance-devel mailing list
concordance-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/concordance-devel