This update predominantly adds comments to explain some of the changes better.
Index: concordance/concordance.c =================================================================== RCS file: /cvsroot/concordance/concordance/concordance/concordance.c,v retrieving revision 1.41.2.20 diff -u -p -r1.41.2.20 concordance.c --- concordance/concordance.c 20 Feb 2011 00:57:18 -0000 1.41.2.20 +++ concordance/concordance.c 11 Mar 2012 01:54:59 -0000 @@ -922,8 +922,8 @@ int print_version_info(struct options_t if ((*options).verbose) printf(" Firmware Type: %i\n", get_fw_type()); - printf(" Hardware Version: %i.%i\n", get_hw_ver_maj(), - get_hw_ver_min()); + printf(" Hardware Version: %i.%i.%i\n", get_hw_ver_maj(), + get_hw_ver_min(), get_hw_ver_mic()); if ((*options).verbose) { int size = get_flash_size(); Index: libconcord/configure.ac =================================================================== RCS file: /cvsroot/concordance/concordance/libconcord/configure.ac,v retrieving revision 1.7.2.2 diff -u -p -r1.7.2.2 configure.ac --- libconcord/configure.ac 11 Aug 2011 05:46:45 -0000 1.7.2.2 +++ libconcord/configure.ac 11 Mar 2012 01:54:59 -0000 @@ -11,7 +11,7 @@ then AC_MSG_ERROR([Error, libusb is missing!]) fi AC_CHECK_HEADER(zzip/lib.h, [], [a=0]) -AC_CHECK_LIB(zzip, zzip_dir_open, [] [a=0]) +AC_CHECK_LIB(zzip, zzip_dir_open, [], [a=0]) if test $a == 0 then AC_MSG_ERROR([Error, libzzip is missing!]) Index: libconcord/lc_internal.h =================================================================== RCS file: /cvsroot/concordance/concordance/libconcord/lc_internal.h,v retrieving revision 1.2.2.1 diff -u -p -r1.2.2.1 lc_internal.h --- libconcord/lc_internal.h 19 Sep 2010 16:06:25 -0000 1.2.2.1 +++ libconcord/lc_internal.h 11 Mar 2012 01:54:59 -0000 @@ -59,5 +59,6 @@ using namespace std; void report_net_error(const char *msg); /* NOTE: 1 for yes, 0 for no, unlike some other functions. */ int is_z_remote(); +int is_usbnet_remote(); #endif // ifndef LC_INTERNAL_H Index: libconcord/libconcord.cpp =================================================================== RCS file: /cvsroot/concordance/concordance/libconcord/libconcord.cpp,v retrieving revision 1.42.2.18 diff -u -p -r1.42.2.18 libconcord.cpp --- libconcord/libconcord.cpp 11 Aug 2011 05:46:45 -0000 1.42.2.18 +++ libconcord/libconcord.cpp 11 Mar 2012 01:54:59 -0000 @@ -47,7 +47,8 @@ #define ZWAVE_HID_PID_MIN 0xC112 #define ZWAVE_HID_PID_MAX 0xC115 -#define MAX_WAIT_FOR_BOOT 5 +// Certain remotes (e.g., 900) take longer to reboot, so extend wait time. +#define MAX_WAIT_FOR_BOOT 10 #define WAIT_FOR_BOOT_SLEEP 5 static class CRemoteBase *rmt; @@ -104,6 +105,11 @@ int get_hw_ver_min() return ri.hw_ver_minor; } +int get_hw_ver_mic() +{ + return ri.hw_ver_micro; +} + int get_flash_size() { return ri.flash->size; @@ -207,6 +213,11 @@ int is_z_remote() return rmt->IsZRemote() ? 1 : 0; } +int is_usbnet_remote() +{ + return rmt->IsUSBNet() ? 1 : 0; +} + int get_time_second() { return rtime.second; @@ -599,15 +610,11 @@ int init_concord() if ((err = FindRemote(hid_info))) { hid_info.pid = 0; -#ifdef WIN32 if ((err = FindUsbLanRemote())) { return LC_ERROR_CONNECT; } rmt = new CRemoteZ_TCP; -#else - return LC_ERROR_CONNECT; -#endif } /* @@ -635,8 +642,11 @@ int init_concord() int deinit_concord() { ShutdownUSB(); - if (of) - delete of; + // Do not delete the OperationFile here. It is used again in + // concordance after deinit_concord() is called. Deleting it causes + // the final website check to fail in update config operations. + //if (of) + //delete of; if (rmt) delete rmt; return 0; @@ -1074,7 +1084,7 @@ int update_configuration(lc_callback cb, if (err != 0) return err; - if (noreset || is_z_remote()) + if (noreset || (is_z_remote() && !is_usbnet_remote())) return 0; if ((err = reset_remote(cb, cb_arg))) Index: libconcord/libconcord.h =================================================================== RCS file: /cvsroot/concordance/concordance/libconcord/libconcord.h,v retrieving revision 1.22.2.14 diff -u -p -r1.22.2.14 libconcord.h --- libconcord/libconcord.h 20 Feb 2011 00:27:19 -0000 1.22.2.14 +++ libconcord/libconcord.h 11 Mar 2012 01:54:59 -0000 @@ -132,6 +132,7 @@ int get_fw_ver_min(); int get_fw_type(); int get_hw_ver_maj(); int get_hw_ver_min(); +int get_hw_ver_mic(); int get_flash_size(); int get_flash_mfg(); int get_flash_id(); Index: libconcord/operationfile.cpp =================================================================== RCS file: /cvsroot/concordance/concordance/libconcord/Attic/operationfile.cpp,v retrieving revision 1.1.2.1 diff -u -p -r1.1.2.1 operationfile.cpp --- libconcord/operationfile.cpp 19 Sep 2010 16:09:29 -0000 1.1.2.1 +++ libconcord/operationfile.cpp 11 Mar 2012 01:54:59 -0000 @@ -113,6 +113,7 @@ int OperationFile::ReadZipFile(char *fil } else { data_size = dirent.st_size; data = new uint8_t[data_size]; + data_alloc = true; zzip_size_t len = zzip_file_read(fh, data, data_size); } @@ -159,11 +160,12 @@ OperationFile::OperationFile() { data_size = xml_size = 0; data = xml = NULL; + data_alloc = false; } OperationFile::~OperationFile() { - if (data) + if (data && data_alloc) delete data; if (xml) delete xml; @@ -186,6 +188,7 @@ int OperationFile::_ExtractFirmwareBinar debug("extracting firmware binary"); uint32_t o_size = FIRMWARE_MAX_SIZE; data = new uint8_t[o_size]; + data_alloc = true; uint8_t *o = data; uint8_t *x = xml; Index: libconcord/operationfile.h =================================================================== RCS file: /cvsroot/concordance/concordance/libconcord/Attic/operationfile.h,v retrieving revision 1.1.2.1 diff -u -p -r1.1.2.1 operationfile.h --- libconcord/operationfile.h 19 Sep 2010 16:09:29 -0000 1.1.2.1 +++ libconcord/operationfile.h 11 Mar 2012 01:54:59 -0000 @@ -29,6 +29,7 @@ class OperationFile { private: uint8_t *data; uint32_t data_size; + bool data_alloc; uint8_t *xml; uint32_t xml_size; int ReadPlainFile(char *file_name); Index: libconcord/remote.cpp =================================================================== RCS file: /cvsroot/concordance/concordance/libconcord/remote.cpp,v retrieving revision 1.40.2.7 diff -u -p -r1.40.2.7 remote.cpp --- libconcord/remote.cpp 20 Feb 2011 00:27:19 -0000 1.40.2.7 +++ libconcord/remote.cpp 11 Mar 2012 01:54:59 -0000 @@ -52,10 +52,19 @@ void setup_ri_pointers(TRemoteInfo &ri) void make_guid(const uint8_t * const in, char*&out) { char x[48]; - sprintf(x, - "{%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X}", - in[3], in[2], in[1], in[0], in[5], in[4], in[7], in[6], - in[8], in[9], in[10], in[11], in[12], in[13], in[14], in[15]); + // usbnet remotes seem to use a more normal byte ordering for serial #'s + if (is_usbnet_remote()) { + sprintf(x, + "{%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X}", + in[0], in[1], in[2], in[3], in[4], in[5], in[6], in[7], + in[8], in[9], in[10], in[11], in[12], in[13], in[14], in[15]); + } + else { + sprintf(x, + "{%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X}", + in[3], in[2], in[1], in[0], in[5], in[4], in[7], in[6], + in[8], in[9], in[10], in[11], in[12], in[13], in[14], in[15]); + } out = strdup(x); } @@ -112,6 +121,7 @@ int CRemote::GetIdentity(TRemoteInfo &ri ri.fw_ver_minor = rsp[1] & 0x0F; ri.hw_ver_major = rsp[2] >> 4; ri.hw_ver_minor = rsp[2] & 0x0F; + ri.hw_ver_micro = 0; /* usbnet remotes have a non-zero micro version */ ri.flash_id = rsp[3]; ri.flash_mfg = rsp[4]; ri.architecture = rx_len < 6 ? 2 : rsp[5] >> 4; Index: libconcord/remote.h =================================================================== RCS file: /cvsroot/concordance/concordance/libconcord/remote.h,v retrieving revision 1.20.2.8 diff -u -p -r1.20.2.8 remote.h --- libconcord/remote.h 19 Sep 2010 16:06:25 -0000 1.20.2.8 +++ libconcord/remote.h 11 Mar 2012 01:54:59 -0000 @@ -100,6 +100,7 @@ struct TArchInfo { struct TRemoteInfo { uint16_t hw_ver_major; uint16_t hw_ver_minor; + uint16_t hw_ver_micro; uint16_t fw_ver_major; uint16_t fw_ver_minor; uint8_t fw_type; @@ -117,6 +118,13 @@ struct TRemoteInfo { bool valid_config; uint32_t config_bytes_used; uint32_t max_config_size; + uint8_t num_regions; /* usbnet only from here down */ + uint8_t *region_ids; + char **region_versions; + uint32_t home_id; + uint8_t node_id; + char *tid; + char *xml_user_rf_setting; }; struct THarmonyTime { @@ -177,6 +185,7 @@ public: uint32_t *ir_signal_length, lc_callback cb=NULL, void *cb_arg=NULL, uint32_t cb_stage=NULL)=0; virtual int IsZRemote()=0; + virtual int IsUSBNet()=0; }; class CRemote : public CRemoteBase // All non-Z-Wave remotes @@ -230,6 +239,7 @@ public: uint32_t *ir_signal_length, lc_callback cb=NULL, void *cb_arg=NULL, uint32_t cb_stage=NULL); int IsZRemote() {return false;} + int IsUSBNet() {return false;} }; // Base class for all Z-Wave remotes @@ -313,12 +323,14 @@ public: virtual ~CRemoteZ_HID() {}; int UpdateConfig(const uint32_t len, const uint8_t *wr, lc_callback cb, void *cb_arg, uint32_t cb_stage); + int IsUSBNet() {return false;} }; // 1000, 1000i class CRemoteZ_TCP : public CRemoteZ_Base { protected: + int TCPSendAndCheck(uint8_t cmd, uint32_t len=0, uint8_t *data=NULL); virtual int Write(uint8_t typ, uint8_t cmd, uint32_t len=0, uint8_t *data=NULL); virtual int Read(uint8_t &status, uint32_t &len, uint8_t *data); @@ -329,6 +341,12 @@ protected: public: CRemoteZ_TCP() {}; virtual ~CRemoteZ_TCP() {}; + int UpdateConfig(const uint32_t len, const uint8_t *wr, + lc_callback cb, void *cb_arg, uint32_t cb_stage); + int GetTime(const TRemoteInfo &ri, THarmonyTime &ht); + int SetTime(const TRemoteInfo &ri, const THarmonyTime &ht, + lc_callback cb=NULL, void *cb_arg=NULL, uint32_t cb_stage=NULL); + int IsUSBNet() {return true;} }; #endif //REMOTE_H Index: libconcord/remote_info.h =================================================================== RCS file: /cvsroot/concordance/concordance/libconcord/remote_info.h,v retrieving revision 1.12.2.1 diff -u -p -r1.12.2.1 remote_info.h --- libconcord/remote_info.h 13 Mar 2011 09:40:50 -0000 1.12.2.1 +++ libconcord/remote_info.h 11 Mar 2012 01:54:59 -0000 @@ -92,7 +92,7 @@ static const TModel ModelList[]={ { MFG_UNK, "Unknown", NULL }, { MFG_UNK, "Unknown", NULL }, { MFG_UNK, "Unknown", NULL }, // 60 - { MFG_UNK, "Unknown", NULL }, + { MFG_HAR, "Harmony 900", NULL }, { MFG_UNK, "Unknown", NULL }, { MFG_UNK, "Unknown", NULL }, { MFG_UNK, "Unknown", NULL }, @@ -416,6 +416,24 @@ static const TArchInfo ArchList[]={ 0, // ram_size 0, // eeprom_size "Internal", // usb + }, + /* arch 15 - usbnet (e.g., 900) */ + { + 0, // serial_location + 0, // serial_address + 0, // flash_base + 0, // firmware_base + 0, // config_base + 0, // firmware_update_base + 0, // firmware_4847_offset + 0x1, /* hack to make config test pass */ // cookie + 0, // cookie_size + 0, // end_vector + "", // micro + 0, // flash_size + 0, // ram_size + 0, // eeprom_size + "", // usb } }; Index: libconcord/remote_z.cpp =================================================================== RCS file: /cvsroot/concordance/concordance/libconcord/remote_z.cpp,v retrieving revision 1.25.2.14 diff -u -p -r1.25.2.14 remote_z.cpp --- libconcord/remote_z.cpp 19 Sep 2010 16:06:25 -0000 1.25.2.14 +++ libconcord/remote_z.cpp 11 Mar 2012 01:54:59 -0000 @@ -271,7 +271,10 @@ int CRemoteZ_HID::ParseParams(uint32_t l int CRemoteZ_TCP::Write(uint8_t typ, uint8_t cmd, uint32_t len, uint8_t *data) { - if (len > 60) { + /* Largest packet size for usbnet is the COMMAND_WRITE_UPDATE_DATA + which is 1 (num params) + 3 (3 parameter size bytes) + 1 (param 1) + + 1024 (param 2) + 4 (param 3) = 1033. */ + if (len > 1033) { return LC_ERROR; } @@ -279,7 +282,7 @@ int CRemoteZ_TCP::Write(uint8_t typ, uin const bool request = (typ == TYPE_REQUEST); const uint8_t status = STATUS_OK; - uint8_t pkt[68]; + uint8_t pkt[1036]; /* largest packet (1033) + standard 3-byte header */ pkt[0] = service_type << 4 | (cmd >> 8) & 0x0F; pkt[1] = cmd & 0xFF; pkt[2] = request ? 0x80 : (status & 0x7F); @@ -343,6 +346,239 @@ int CRemoteZ_TCP::ParseParams(uint32_t l return 0; } +int CRemoteZ_TCP::TCPSendAndCheck(uint8_t cmd, uint32_t len, uint8_t *data) +{ + int err = 0; + uint8_t status; + unsigned int rlen; + uint8_t rsp[60]; + + if ((err = Write(TYPE_REQUEST, cmd, len, data))) { + debug("Failed to send request %02X", cmd); + return LC_ERROR_WRITE; + } + + if ((err = Read(status, rlen, rsp))) { + debug("Failed to read from remote"); + return LC_ERROR_READ; + } + + if (rsp[2] != TYPE_RESPONSE) { + debug("Packet didn't have response bit!"); + return LC_ERROR; + } + + if (rsp[1] != cmd) { + debug("The cmd bit didn't match our request packet"); + return LC_ERROR; + } + + return 0; +} + +int CRemoteZ_TCP::UpdateConfig(const uint32_t len, const uint8_t *wr, + lc_callback cb, void *arg, uint32_t cb_stage) +{ + int err = 0; + int cb_count = 0; + uint8_t rsp[60]; + unsigned int rlen; + uint8_t status; + + cb(LC_CB_STAGE_INITIALIZE_UPDATE, cb_count++, 0, 2, + LC_CB_COUNTER_TYPE_STEPS, arg); + + /* ACK it with a command to start an update */ + debug("START_UPDATE"); + // 2 parameters, each 1 byte. + // 1st parameter "flags" seems to always be 0. + uint8_t cmd[60] = { 0x02, 0x01, 0x00, 0x01, REGION_USER_CONFIG }; + if ((err = TCPSendAndCheck(COMMAND_START_UPDATE, 5, cmd))) { + return err; + } + + cb(LC_CB_STAGE_INITIALIZE_UPDATE, cb_count++, 1, 2, + LC_CB_COUNTER_TYPE_STEPS, arg); + + /* write update-header */ + debug("UPDATE_HEADER"); + cmd[0] = 0x02; // 2 parameters + cmd[1] = 0x04; // 1st parameter 4 bytes (size) + cmd[2] = (len & 0xFF000000) >> 24; + cmd[3] = (len & 0x00FF0000) >> 16; + cmd[4] = (len & 0x0000FF00) >> 8; + cmd[5] = (len & 0x000000FF); + cmd[6] = 0x01; // 2nd parameter 1 byte (region id) + cmd[7] = REGION_USER_CONFIG; + if ((err = TCPSendAndCheck(COMMAND_WRITE_UPDATE_HEADER, 8, cmd))) { + return err; + } + + cb(LC_CB_STAGE_INITIALIZE_UPDATE, cb_count++, 2, 2, + LC_CB_COUNTER_TYPE_STEPS, arg); + cb_count = 0; + + /* write data */ + debug("UPDATE_DATA"); + uint32_t pkt_len; + int tlen = len; + int bytes_written = 0; + uint8_t *wr_ptr = const_cast<uint8_t*>(wr); + uint8_t tmp_pkt[1033]; + tmp_pkt[0] = 0x03; // 3 parameters + tmp_pkt[1] = 0x01; // 1st parameter, 1 byte (region id) + tmp_pkt[2] = REGION_USER_CONFIG; + tmp_pkt[3] = 0xC2; // 2nd parameter, 1024 bytes (data) + tmp_pkt[1028] = 0x04; // 3rd parameter, 4 bytes (length) + while (tlen) { + pkt_len = 1024; // max packet length seems to be 1024 + if (tlen < pkt_len) { + pkt_len = tlen; + } + tlen -= pkt_len; + + memcpy(&tmp_pkt[4], wr_ptr, pkt_len); + tmp_pkt[1029] = (pkt_len & 0xFF000000) >> 24; + tmp_pkt[1030] = (pkt_len & 0x00FF0000) >> 16; + tmp_pkt[1031] = (pkt_len & 0x0000FF00) >> 8; + tmp_pkt[1032] = (pkt_len & 0x000000FF); + + debug("DATA %d, sending %d bytes, %d bytes left", cb_count, + pkt_len, tlen); + + if ((err = TCPSendAndCheck(COMMAND_WRITE_UPDATE_DATA, 1033, + tmp_pkt))) { + return err; + } + wr_ptr += pkt_len; + + if (cb) { + cb(LC_CB_STAGE_WRITE_CONFIG, cb_count++, + (int)(wr_ptr - wr), len, + LC_CB_COUNTER_TYPE_BYTES, arg); + } + } + + /* write update-done */ + cb_count = 0; + cb(LC_CB_STAGE_FINALIZE_UPDATE, cb_count++, 0, 3, + LC_CB_COUNTER_TYPE_STEPS, arg); + + debug("UPDATE_DATA_DONE"); + cmd[0] = 0x01; // 1 parameter + cmd[1] = 0x01; // 1st parameter 1 byte (region id) + cmd[2] = REGION_USER_CONFIG; + if ((err = TCPSendAndCheck(COMMAND_WRITE_UPDATE_DATA_DONE, 3, cmd))) { + return err; + } + + cb(LC_CB_STAGE_FINALIZE_UPDATE, cb_count++, 1, 3, + LC_CB_COUNTER_TYPE_STEPS, arg); + + /* send get-cheksum */ + debug("GET_CHECKSUM"); + cmd[0] = 0x02; // 2 parameters + cmd[1] = 0x02; // 1st parameter 2 bytes (seed) + cmd[2] = 0xFF; // seed seems to always be FF + cmd[3] = 0xFF; // seed seems to always be FF + cmd[4] = 0x01; // 2nd parameter 1 byte (region id) + cmd[5] = REGION_USER_CONFIG; + if ((err = TCPSendAndCheck(COMMAND_GET_UPDATE_CHECKSUM, 6, cmd))) { + return err; + } + + cb(LC_CB_STAGE_FINALIZE_UPDATE, cb_count++, 2, 3, + LC_CB_COUNTER_TYPE_STEPS, arg); + + /* send finish-update */ + debug("FINISH_UPDATE"); + cmd[0] = 0x02; // 2 parameters + cmd[1] = 0x01; // 1st parameter 1 byte (validate) + cmd[2] = 0x01; // validate? + cmd[3] = 0x01; // 2nd parameter 1 byte (region id) + cmd[4] = REGION_USER_CONFIG; + if ((err = TCPSendAndCheck(COMMAND_FINISH_UPDATE, 5, cmd))) { + return err; + } + + cb(LC_CB_STAGE_FINALIZE_UPDATE, cb_count++, 3, 3, + LC_CB_COUNTER_TYPE_STEPS, arg); + + return 0; +} + +int CRemoteZ_TCP::GetTime(const TRemoteInfo &ri, THarmonyTime &ht) +{ + int err = 0; + if ((err = Write(TYPE_REQUEST, COMMAND_GET_CURRENT_TIME))) { + debug("Failed to write to remote"); + return LC_ERROR_WRITE; + } + uint8_t time[60]; + unsigned int len; + uint8_t status; + if ((err = Read(status, len, time))) { + debug("Failed to read to remote"); + return LC_ERROR_READ; + } + + if (time[2] != TYPE_RESPONSE || time[1] != COMMAND_GET_CURRENT_TIME) { + debug("Incorrect response type from Get Time"); + return LC_ERROR_INVALID_DATA_FROM_REMOTE; + } + + CRemoteZ_Base::TParamList pl; + ParseParams(len, time, pl); + + ht.year = GetWord(pl.p[0]); + ht.month = *pl.p[1]; + ht.day = *pl.p[2]; + ht.hour = *pl.p[3]; + ht.minute = *pl.p[4]; + ht.second = *pl.p[5]; + ht.dow = *pl.p[6]&7; + ht.utc_offset = static_cast<int16_t>(GetWord(pl.p[7])); + if (pl.count > 11) { + ht.timezone = reinterpret_cast<char*>(pl.p[11]); + ht.timezone[3] = '\0'; + } else { + ht.timezone = ""; + } + + return 0; +} + +int CRemoteZ_TCP::SetTime(const TRemoteInfo &ri, const THarmonyTime &ht, + lc_callback cb, void *cb_arg, uint32_t cb_stage) +{ + debug("SetTime"); + int err = 0; + + uint8_t tsv[32] = { + 0x0C, // 12 parameters + 0x02, ht.year >> 8, ht.year, // 2 bytes + 0x01, ht.month, + 0x01, ht.day, + 0x01, ht.hour, + 0x01, ht.minute, + 0x01, ht.second, + 0x01, ht.dow, + // utcOffset + 0x02, 0, 0, // 2 bytes - 900 doesn't seem to accept this + // 0s + 0x02, 0, 0, // 2 bytes + 0x02, 0, 0, // 2 bytes + 0x02, 0, 0, // 2 bytes + 0x83, 0, 0, 0 // 900 doesn't seem to accept this, don't bother + }; + + if ((err = TCPSendAndCheck(COMMAND_UPDATE_TIME, 32, tsv))) { + debug("Failed to write to remote"); + return err; + } + + return 0; +} int CRemoteZ_Base::Reset(uint8_t kind) { @@ -414,8 +650,8 @@ int CRemoteZ_Base::GetIdentity(TRemoteIn hid.frl = 0; hid.mfg = "Logitech"; hid.prod = "Harmony 1000"; - ri.flash_mfg = 0; // todo - ri.flash_id = 0; // todo + ri.flash_mfg = 0x01; // Seems to be the same as regular zwave + ri.flash_id = 0x49; // Seems to be the same as regular zwave } else { // Not 1000 ri.flash_mfg = 0x01;// todo ri.flash_id = 0x49; // todo @@ -428,10 +664,10 @@ int CRemoteZ_Base::GetIdentity(TRemoteIn const unsigned int hw = GetWord(pl.p[7]); ri.hw_ver_major = hw >> 8; // ??? ri.hw_ver_minor = (hw >> 4) & 0x0F; // ??? - // hw_ver_micro = hw & 0x0F // ??? + ri.hw_ver_micro = hw & 0x0F; // 900 has this and is non-zero //ri.hw_ver_major = hw >> 4; //ri.hw_ver_minor = hw & 0x0F; - ri.protocol = 0; + ri.protocol = GetWord(pl.p[2]); // Seems to be the same as arch? setup_ri_pointers(ri); @@ -457,7 +693,12 @@ int CRemoteZ_Base::GetIdentity(TRemoteIn ri.max_config_size = 1; ri.valid_config = 1; -#if 0 // Get region info - 1000 only! + if (!IsUSBNet()) { + return 0; + } + + // Get region info - everything below is extra stuff that only the + // usbnet remotes seem to use. uint8_t rr[] = { 1, 1, 1 }; // AddByteParam(1); if ((err = Write(TYPE_REQUEST, COMMAND_GET_REGION_IDS, 3, rr))) { debug("Failed to write to remote"); @@ -471,9 +712,33 @@ int CRemoteZ_Base::GetIdentity(TRemoteIn ParseParams(len, rgn, pl); if (pl.count == 1) { const unsigned int rc = *(pl.p[0]-1) & 0x3F; + ri.num_regions = rc + 1; + ri.region_ids = new uint8_t[ri.num_regions]; + ri.region_versions = new char*[ri.num_regions]; + + // There seems to be an implied Region 0 that the Windows + // software requests but it is not listed in the Region IDs. + uint8_t rz[] = { 1, 1, 0 }; // 1 parameter, 1 byte, value = 0 + if ((err = Write(TYPE_REQUEST, + COMMAND_GET_REGION_VERSION, 3, rz))) { + debug("Failed to write to remote"); + return LC_ERROR; + } + uint8_t rgz[64]; + if ((err = Read(status, len, rgz))) { + debug("Failed to read from remote"); + return LC_ERROR; + } + CRemoteZ_Base::TParamList rzp; + ParseParams(len, rgz, rzp); + ri.region_ids[0] = 0x00; // Store region 0. + ri.region_versions[0] = new char[4]; + snprintf(ri.region_versions[0], 4, "%d.%d", *(rzp.p[0]+1), + *rzp.p[0]); + for(unsigned int r = 0; r < rc; ++r) { const uint8_t rn = *(pl.p[0]+r); - printf("Region %i\n", rn); + debug("Region %i", rn); uint8_t rv[] = { 1, 1, rn }; // AddByteParam(rn); if ((err = Write(TYPE_REQUEST, COMMAND_GET_REGION_VERSION, 3, rv))) { @@ -487,10 +752,61 @@ int CRemoteZ_Base::GetIdentity(TRemoteIn } CRemoteZ_Base::TParamList rp; ParseParams(len, rgv, rp); + ri.region_ids[r+1] = rn; + ri.region_versions[r+1] = new char[4]; + snprintf(ri.region_versions[r+1], 4, "%d.%d", + *(rp.p[0]+1), *rp.p[0]); } } -#endif + // Get HOMEID, NODEID, TID + if ((err = Write(TYPE_REQUEST, COMMAND_GET_HOME_ID))) { + debug("Failed to write to remote"); + return LC_ERROR; + } + if ((err = Read(status, len, rsp))) { + debug("Failed to read from remote"); + return LC_ERROR; + } + ParseParams(len, rsp, pl); + ri.home_id = (*pl.p[0] << 24) + (*(pl.p[0]+1) << 16) + + (*(pl.p[0]+2) << 8) + *(pl.p[0]+3); + if ((err = Write(TYPE_REQUEST, COMMAND_GET_NODE_ID))) { + debug("Failed to write to remote"); + return LC_ERROR; + } + if ((err = Read(status, len, rsp))) { + debug("Failed to read from remote"); + return LC_ERROR; + } + ParseParams(len, rsp, pl); + ri.node_id = *pl.p[0]; + // Get the "TID" - not entirely sure what this is, but it appears to be + // contained in the INTERFACE_LIST. + if ((err = Write(TYPE_REQUEST, COMMAND_GET_INTERFACE_LIST))) { + debug("Failed to write to remote"); + return LC_ERROR; + } + if ((err = Read(status, len, rsp))) { + debug("Failed to read from remote"); + return LC_ERROR; + } + ParseParams(len, rsp, pl); + ri.tid = new char[21]; + ri.tid[0] = '0'; + ri.tid[1] = 'x'; + // "TID" appears to be contained in the middle of the INTERFACE_LIST. + for (int i=0; i<9; i++) + snprintf(&ri.tid[(i*2)+2], 3, "%02X", *(pl.p[1]+i+2)); + ri.tid[20] = '\0'; + + // Get the "XMLUserRFSetting" - the usbnet remote appears to have a web + // server running where the Windows driver grabs this data. + if (err = GetXMLUserRFSetting(&ri.xml_user_rf_setting)) { + debug("Failed to read XML User RF Settings"); + return LC_ERROR; + } + return 0; } Index: libconcord/usblan.cpp =================================================================== RCS file: /cvsroot/concordance/concordance/libconcord/usblan.cpp,v retrieving revision 1.13.2.1 diff -u -p -r1.13.2.1 usblan.cpp --- libconcord/usblan.cpp 19 Sep 2010 16:06:25 -0000 1.13.2.1 +++ libconcord/usblan.cpp 11 Mar 2012 01:54:59 -0000 @@ -48,6 +48,12 @@ static SOCKET sock = SOCKET_ERROR; const char * const remote_ip_address = "169.254.1.2"; const u_short remote_port = 3074; +const char * const http_get_cmd = "\ +GET /xmluserrfsetting HTTP/1.1\r\n\ +User-Agent: Jakarta Commons-HttpClient/3.1\r\n\ +Host: 169.254.1.2\r\n\ +\r\n"; + int InitializeUsbLan(void) { return 0; @@ -127,3 +133,63 @@ int UsbLan_Read(unsigned int &len, uint8 return 0; } + +int GetXMLUserRFSetting(char **data) +{ + int err; + int web_sock; + char buf[4096]; + + hostent* addr = gethostbyname(remote_ip_address); + + if (!addr) { + report_net_error("gethostbyname()"); + return LC_ERROR_OS_NET; + } + + sockaddr_in sa; + memcpy(&(sa.sin_addr), addr->h_addr, addr->h_length); + sa.sin_family = AF_INET; // TCP/IP + sa.sin_port = htons(80); // Web Server port + + web_sock = socket(sa.sin_family, SOCK_STREAM, 0); // TCP + + if ((err = connect(web_sock,(struct sockaddr*)&sa,sizeof(sa)))) { + report_net_error("connect()"); + return LC_ERROR_OS_NET; + } + debug("Connected to USB LAN web server!"); + + err = send(web_sock, http_get_cmd, strlen(http_get_cmd), 0); + if (err == SOCKET_ERROR) { + report_net_error("send()"); + return LC_ERROR_OS_NET; + } + debug("%i bytes sent", err); + + unsigned int len = 0; + char* buf_ptr = buf; + do { + err = recv(web_sock, buf_ptr, sizeof(buf)-len, 0); + if (err == SOCKET_ERROR) { + report_net_error("recv()"); + len = 0; + return LC_ERROR_OS_NET; + } + len += err; + buf_ptr += err; + debug("%i bytes received", err); + } while (err > 0); // recv will return 0 when the message is done. + buf[len] = '\0'; + + buf_ptr = strstr(buf, "\r\n\r\n"); // search for end of the http header + if (buf_ptr == NULL) { + report_net_error("strstr()"); + return LC_ERROR_OS_NET; + } + buf_ptr += 4; + *data = new char[strlen(buf_ptr)+1]; + strncpy(*data, buf_ptr, strlen(buf_ptr)+1); + + return 0; +} Index: libconcord/usblan.h =================================================================== RCS file: /cvsroot/concordance/concordance/libconcord/usblan.h,v retrieving revision 1.5.2.1 diff -u -p -r1.5.2.1 usblan.h --- libconcord/usblan.h 19 Sep 2010 16:06:25 -0000 1.5.2.1 +++ libconcord/usblan.h 11 Mar 2012 01:54:59 -0000 @@ -30,5 +30,6 @@ int ShutdownUsbLan(void); int FindUsbLanRemote(void); int UsbLan_Write(unsigned int len, uint8_t *data); int UsbLan_Read(unsigned int &len, uint8_t *data); +int GetXMLUserRFSetting(char **data); #endif Index: libconcord/web.cpp =================================================================== RCS file: /cvsroot/concordance/concordance/libconcord/web.cpp,v retrieving revision 1.27.2.2 diff -u -p -r1.27.2.2 web.cpp --- libconcord/web.cpp 18 Sep 2010 14:14:54 -0000 1.27.2.2 +++ libconcord/web.cpp 11 Mar 2012 01:54:59 -0000 @@ -256,6 +256,19 @@ int encode_ir_signal(uint32_t carrier_cl return 0; } +int add_usbnet_headers(char *post_data, TRemoteInfo &ri) +{ + sprintf(post_data+strlen(post_data), post_xml_usbnet1, ri.home_id, + ri.node_id, ri.tid); + for (int i=0; i<ri.num_regions; i++) { + sprintf(post_data+strlen(post_data), + post_xml_usbnet_region, ri.region_ids[i], + ri.region_versions[i]); + } + sprintf(post_data+strlen(post_data), "%s", post_xml_usbnet2); + sprintf(post_data+strlen(post_data), "%s", ri.xml_user_rf_setting); + sprintf(post_data+strlen(post_data), "%s", post_xml_usbnet3); +} int Post(uint8_t *xml, uint32_t xml_size, const char *root, TRemoteInfo &ri, bool has_userid, bool add_cookiekeyval, bool z_post, @@ -301,7 +314,7 @@ int Post(uint8_t *xml, uint32_t xml_size if (learn_seq == NULL) { char serial[144]; sprintf(serial, "%s%s%s", ri.serial1, ri.serial2, ri.serial3); - char post_data[2000]; + char post_data[4000]; // large enough for extra usbnet headers if (z_post) { sprintf(post_data, z_post_xml, ri.hw_ver_major, ri.hw_ver_minor, @@ -311,8 +324,14 @@ int Post(uint8_t *xml, uint32_t xml_size sprintf(post_data, post_xml, ri.fw_ver_major, ri.fw_ver_minor, ri.fw_type, serial, ri.hw_ver_major, ri.hw_ver_minor, - ri.flash_mfg, ri.flash_id, ri.protocol, - ri.architecture, ri.skin); + ri.hw_ver_micro, ri.flash_mfg, ri.flash_id, + ri.protocol, ri.architecture, ri.skin); + if (is_usbnet_remote()) { + add_usbnet_headers(post_data, ri); + } else { + sprintf(post_data+strlen(post_data), "%s", + post_xml_trailer); + } } debug("post data: %s",post_data); Index: libconcord/xml_headers.h =================================================================== RCS file: /cvsroot/concordance/concordance/libconcord/xml_headers.h,v retrieving revision 1.7.2.1 diff -u -p -r1.7.2.1 xml_headers.h --- libconcord/xml_headers.h 25 Aug 2010 22:27:22 -0000 1.7.2.1 +++ libconcord/xml_headers.h 11 Mar 2012 01:54:59 -0000 @@ -153,16 +153,36 @@ const char *post_xml="\ <SOFTWARE>%i.%i</SOFTWARE>\ <SOFTWARETYPE>%i</SOFTWARETYPE>\ <ID>%s</ID>\ -<BOARD>%i.%i.0</BOARD>\ +<BOARD>%i.%i.%i</BOARD>\ <FLASH>0x%02X:0x%02X</FLASH>\ <PROTOCOL>%i</PROTOCOL>\ <ARCHITECTURE>%i</ARCHITECTURE>\ -<SKIN>%i</SKIN>\ +<SKIN>%i</SKIN>"; + +const char *post_xml_trailer="\ <REGIONS/>\ </VERSION>\ </VERSIONINFORMATION>\ </EASYZAPPERDATA>\r\n"; +const char *post_xml_usbnet1="\ +<HOMEID>0x%08X</HOMEID>\ +<NODEID>%i</NODEID>\ +<TID>%s</TID>\ +<FIRMWARE>"; + +const char *post_xml_usbnet_region="\ +<REGION ID=\"%i\">%s</REGION>"; + +const char *post_xml_usbnet2="\ +</FIRMWARE>\ +<REGIONS/>\ +</VERSION>\ +</VERSIONINFORMATION>"; + +const char *post_xml_usbnet3="\ +</EASYZAPPERDATA>"; + const char *z_post_xml="\ <DATA>\ <STATUS>Success</STATUS>\ Index: libconcord/libusb/libusbhid.cpp =================================================================== RCS file: /cvsroot/concordance/concordance/libconcord/libusb/libusbhid.cpp,v retrieving revision 1.19 diff -u -p -r1.19 libusbhid.cpp --- libconcord/libusb/libusbhid.cpp 17 Jul 2010 22:17:37 -0000 1.19 +++ libconcord/libusb/libusbhid.cpp 11 Mar 2012 01:54:59 -0000 @@ -135,6 +135,11 @@ int FindRemote(THIDINFO &hid_info) } #ifdef linux + /* If this is a usbnet remote, abort before trying to detach drivers */ + if (h_dev && (h_dev->descriptor.idProduct == 0xC11F)) { + return LC_ERROR_CONNECT; + } + /* * Before we attempt to claim the interface, lets go ahead and get * the kernel off of it, in case it claimed it already. ------------------------------------------------------------------------------ Virtualization & Cloud Management Using Capacity Planning Cloud computing makes use of virtualization - but cloud computing also focuses on allowing computing to be delivered as a service. http://www.accelacomm.com/jaw/sfnl/114/51521223/ _______________________________________________ concordance-devel mailing list concordance-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/concordance-devel