On 03/10/2012 06:01 PM, Scott Talbert wrote:
> This update predominantly adds comments to explain some of the changes 
> better.

I went to apply this patch to a fresh export to start testing other hardware
against it, but it won't come close to applying:

[phil@rider 900support]$ patch -p0  < /tmp/900.patch
patching file concordance/concordance.c
Hunk #1 FAILED at 922.
1 out of 1 hunk FAILED -- saving rejects to file concordance/concordance.c.rej
patching file libconcord/configure.ac
Hunk #1 succeeded at 11 with fuzz 1.
patching file libconcord/lc_internal.h
patching file libconcord/libconcord.cpp
Hunk #2 succeeded at 105 with fuzz 1.
Hunk #3 succeeded at 213 with fuzz 1.
Hunk #4 FAILED at 610.
Hunk #5 FAILED at 646.
Hunk #6 FAILED at 1085.
3 out of 6 hunks FAILED -- saving rejects to file libconcord/libconcord.cpp.rej
patching file libconcord/libconcord.h
patching file libconcord/operationfile.cpp
Hunk #1 FAILED at 113.
Hunk #2 FAILED at 159.
Hunk #3 FAILED at 186.
3 out of 3 hunks FAILED -- saving rejects to file 
libconcord/operationfile.cpp.rej
patching file libconcord/operationfile.h
Hunk #1 FAILED at 29.
1 out of 1 hunk FAILED -- saving rejects to file libconcord/operationfile.h.rej
patching file libconcord/remote.cpp
Hunk #1 FAILED at 52.
Hunk #2 FAILED at 112.
2 out of 2 hunks FAILED -- saving rejects to file libconcord/remote.cpp.rej
patching file libconcord/remote.h
Hunk #1 FAILED at 100.
Hunk #2 FAILED at 117.
Hunk #3 FAILED at 177.
Hunk #4 FAILED at 230.
Hunk #5 FAILED at 313.
Hunk #6 FAILED at 329.
6 out of 6 hunks FAILED -- saving rejects to file libconcord/remote.h.rej
patching file libconcord/remote_info.h
Hunk #1 FAILED at 92.
Hunk #2 FAILED at 416.
2 out of 2 hunks FAILED -- saving rejects to file libconcord/remote_info.h.rej
patching file libconcord/remote_z.cpp
Hunk #1 FAILED at 271.
Hunk #2 FAILED at 279.
Hunk #3 succeeded at 343 with fuzz 1.
Hunk #4 FAILED at 647.
Hunk #5 FAILED at 661.
Hunk #6 FAILED at 690.
Hunk #7 FAILED at 704.
Hunk #8 FAILED at 720.
7 out of 8 hunks FAILED -- saving rejects to file libconcord/remote_z.cpp.rej
patching file libconcord/usblan.cpp
Hunk #1 succeeded at 48 with fuzz 1.
Hunk #2 succeeded at 133 with fuzz 2.
patching file libconcord/usblan.h
patching file libconcord/web.cpp
Hunk #1 succeeded at 256 with fuzz 1.
Hunk #2 FAILED at 314.
Hunk #3 FAILED at 324.
2 out of 3 hunks FAILED -- saving rejects to file libconcord/web.cpp.rej
patching file libconcord/xml_headers.h
patching file libconcord/libusb/libusbhid.cpp
Hunk #1 FAILED at 135.
1 out of 1 hunk FAILED -- saving rejects to file
libconcord/libusb/libusbhid.cpp.rej

> 
> 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
> 


-- 
Phil Dibowitz                             p...@ipom.com
Open Source software and tech docs        Insanity Palace of Metallica
http://www.phildev.net/                   http://www.ipom.com/

"Be who you are and say what you feel, because those who mind don't matter
 and those who matter don't mind."
 - Dr. Seuss


Attachment: signature.asc
Description: OpenPGP digital signature

------------------------------------------------------------------------------
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

Reply via email to