/ src / tools / knxtool.c
knxtool.c
   1  /*
   2      knxtool - multi function eibd client
   3      Copyright (C) 2005-2011 Martin Koegler <mkoegler@auto.tuwien.ac.at>
   4  
   5      First version by Jean-Francois Meessen <jef2000@ouaye.net>
   6      More applets ported by Marc Leeman
   7  
   8      This program is free software; you can redistribute it and/or modify
   9      it under the terms of the GNU General Public License as published by
  10      the Free Software Foundation; either version 2 of the License, or
  11      (at your option) any later version.
  12  
  13      This program is distributed in the hope that it will be useful,
  14      but WITHOUT ANY WARRANTY; without even the implied warranty of
  15      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16      GNU General Public License for more details.
  17  
  18      You should have received a copy of the GNU General Public License
  19      along with this program; if not, write to the Free Software
  20      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  21  */
  22  
  23  #include "common.h"
  24  #include "path.h"
  25  #include <time.h>
  26  #include <fcntl.h>
  27  #include <string.h>
  28  #ifdef HAVE_SYS_TIME_H
  29  #include <sys/time.h>
  30  #endif
  31  
  32  static char *prog;
  33  
  34  static EIBConnection *
  35  open_con (const char *uri)
  36  {
  37    EIBConnection *con;
  38    if (!uri || !*uri)
  39      die ("usage: %s url [args]", prog);
  40  
  41    /* Open the Socket */
  42    con = EIBSocketURL (uri);
  43    if (!con)
  44      die ("Open failed");
  45  
  46    return con;
  47  }
  48  
  49  int
  50  main (int ac, char *ag[])
  51  {
  52    uint8_t buf[255];
  53    int len;
  54    EIBConnection *con;
  55    eibaddr_t dest;
  56    eibaddr_t src;
  57  
  58    /* check if the application is called by its original name
  59     * (and an applet name afterwards), or with a symbolic link */
  60    prog = strrchr (ag[0], '/');
  61    if (prog)
  62      prog += 1;
  63    else
  64      prog = ag[0];
  65    if (strcmp(prog, "knxtool") == 0 || strcmp(prog, "lt-knxtool") == 0)
  66      {
  67        if (ac < 2)
  68          die ("usage: %s applet [args] -- say '%s list' to get a list of applets", prog,prog);
  69        ac--;
  70        ag++;
  71        prog = ag[0];
  72      }
  73    if (strncmp (prog, "knx", 3) == 0)
  74      prog += 3;
  75    if (strcmp (prog , "list") == 0)
  76      {
  77        printf("on off write swrite read if readtemp dimup log \n\
  78  busmonitor1 busmonitor2 readindividual progmodeon progmodeoff progmodetoggle progmodestatus maskver \n\
  79  writeaddress vbusmonitor1 vbusmonitor2 mprogmodeon mprogmodeoff mprogmodetoggle mprogmodestatus mmaskver \n\
  80  mpeitype madcread mread mwrite mpropread mpropwrite mpropdesc mpropscan groupread groupswrite groupwrite \n\
  81  msetkey grouplisten groupresponse groupsresponse groupsocketlisten groupsocketread mpropscanpoll \n\
  82  vbusmonitor1poll groupreadresponse groupcacheenable groupcachedisable groupcacheclear groupcacheremove \n\
  83  groupcachereadsync groupcacheread mwriteplain mrestart groupsocketwrite groupsocketswrite \n\
  84  xpropread xpropwrite groupcachelastupdates busmonitor3 vbusmonitor3 eibread-cgi eibwrite-cgi \n\
  85  vbusmonitor1time\n");
  86        return 0;
  87      }
  88  
  89    /* Buffering stdout is almost never what we want */
  90    setvbuf(stdout, NULL, _IOLBF, 0);
  91  
  92    if (strcmp (prog, "on") == 0)
  93      {
  94        if (ac != 3)
  95          die ("usage: %s url eibaddr", prog);
  96        con = open_con(ag[1]);
  97        dest = readgaddr (ag[2]);
  98        buf[0] = 0;
  99        buf[1] = 0x81;
 100  
 101        if (EIBOpenT_Group (con, dest, 1) == -1)
 102          die ("Connect failed");
 103  
 104        len = EIBSendAPDU (con, 2, buf);
 105        if (len == -1)
 106          die ("Request failed");
 107        printf ("Send request\n");
 108      }
 109    else if (strcmp (prog, "off") == 0)
 110      {
 111        if (ac != 3)
 112          die ("usage: %s url eibaddr", prog);
 113        con = open_con(ag[1]);
 114        dest = readgaddr (ag[2]);
 115        buf[0] = 0;
 116        buf[1] = 0x80;
 117  
 118        if (EIBOpenT_Group (con, dest, 1) == -1)
 119          die ("Connect failed");
 120  
 121        len = EIBSendAPDU (con, 2, buf);
 122        if (len == -1)
 123          die ("Request failed");
 124        printf ("Send request\n");
 125      }
 126    else if (strcmp (prog, "write") == 0)
 127      {
 128        if (ac != 4)
 129          die ("usage: %s url eibaddr val", prog);
 130        con = open_con(ag[1]);
 131        dest = readgaddr (ag[2]);
 132        buf[0] = 0;
 133        buf[1] = 0x80;
 134        buf[2] = readHex (ag[3]);
 135  
 136        if (EIBOpenT_Group (con, dest, 1) == -1)
 137          die ("Connect failed");
 138  
 139        len = EIBSendAPDU (con, 3, buf);
 140        if (len == -1)
 141          die ("Request failed");
 142        printf ("Send request\n");
 143      }
 144    else if (strcmp (prog, "swrite") == 0)
 145      {
 146        if (ac != 4)
 147          die ("usage: %s url eibaddr val", prog);
 148        con = open_con(ag[1]);
 149        dest = readgaddr (ag[2]);
 150        buf[0] = 0;
 151        buf[1] = 0x80 | (readHex (ag[3]) & 0x3f);
 152  
 153        if (EIBOpenT_Group (con, dest, 1) == -1)
 154          die ("Connect failed");
 155  
 156        len = EIBSendAPDU (con, 2, buf);
 157        if (len == -1)
 158          die ("Request failed");
 159        printf ("Send request\n");
 160      }
 161    else if (strcmp (prog, "read") == 0)
 162      {
 163  
 164        if (ac != 3)
 165          die ("usage: %s url eibaddr", prog);
 166        con = open_con(ag[1]);
 167        dest = readgaddr (ag[2]);
 168  
 169        if (EIBOpenT_Group (con, dest, 0) == -1)
 170          die ("Connect failed");
 171  
 172        buf[0] = 0;
 173        buf[1] = 0;
 174        len = EIBSendAPDU (con, 2, buf);
 175        if (len == -1)
 176          die ("Request failed");
 177  
 178        while (1)
 179          {
 180            len = EIBGetAPDU_Src (con, sizeof (buf), buf, &src);
 181            if (len == -1)
 182              die ("Read failed");
 183            if (len < 2)
 184              die ("Invalid Packet");
 185            if (buf[0] & 0x3 || (buf[1] & 0xC0) == 0xC0)
 186              {
 187                printf ("Error: Unknown APDU: ");
 188                printHex (len, buf);
 189                printf ("\n");
 190              }
 191            else if ((buf[1] & 0xC0) == 0x40)
 192              {
 193                if (len == 2)
 194                  printf ("%02X", buf[1] & 0x3F);
 195                else
 196                  printHex (len - 2, buf + 2);
 197                printf ("\n");
 198                fflush (stdout);
 199                break;
 200              }
 201          }
 202  
 203      }
 204    else if (strcmp (prog, "if") == 0)
 205      {
 206        if (ac != 4 && ac != 5)
 207          die ("usage: %s url eibaddr text1 [text2]", prog);
 208        con = open_con(ag[1]);
 209        dest = readgaddr (ag[2]);
 210  
 211        if (EIBOpenT_Group (con, dest, 0) == -1)
 212          die ("Connect failed");
 213  
 214        buf[0] = 0;
 215        buf[1] = 0;
 216        len = EIBSendAPDU (con, 2, buf);
 217        if (len == -1)
 218          die ("Request failed");
 219  
 220        while (1)
 221          {
 222            len = EIBGetAPDU_Src (con, sizeof (buf), buf, &src);
 223            if (len < 2 || buf[0] & 0x3 || (buf[1] & 0xC0) == 0xC0)
 224              {
 225                printf ("ERR");
 226                break;
 227              }
 228            else if ((buf[1] & 0xC0) == 0x40)
 229              {
 230                if (len == 2)
 231                  {
 232                    if (buf[1] & 0x3F)
 233                      printf ("%s", ag[3]);
 234                    else if (ac == 5)
 235                      printf ("%s", ag[4]);
 236                    printf ("\n");
 237                    fflush (stdout);
 238                  }
 239                else
 240                  printf ("ERR\n");
 241                break;
 242              }
 243          }
 244  
 245      }
 246    else if (strcmp (prog, "readtemp") == 0)
 247      {
 248        if (ac != 3)
 249          die ("usage: %s url eibaddr", prog);
 250        con = open_con(ag[1]);
 251        dest = readgaddr (ag[2]);
 252  
 253        if (EIBOpenT_Group (con, dest, 0) == -1)
 254          die ("Connect failed");
 255  
 256        buf[0] = 0;
 257        buf[1] = 0;
 258        len = EIBSendAPDU (con, 2, buf);
 259        if (len == -1)
 260          die ("Request failed");
 261  
 262        while (1)
 263          {
 264            len = EIBGetAPDU_Src (con, sizeof (buf), buf, &src);
 265            if (len == -1)
 266              die ("Read failed");
 267            if (len < 2)
 268              die ("Invalid Packet");
 269            if (buf[0] & 0x3 || (buf[1] & 0xC0) == 0xC0)
 270              {
 271                printf ("Error: Unknown APDU: ");
 272                printHex (len, buf);
 273                printf ("\n");
 274              }
 275            else if ((buf[1] & 0xC0) == 0x40)
 276              {
 277                if (len == 2)
 278                  printf ("%02X", buf[1] & 0x3F);
 279                else
 280                  {
 281  
 282                    if (len == 4)
 283                      {
 284                        int d1 =
 285                          ((unsigned char) buf[2]) * 256 +
 286                          (unsigned char) buf[3];
 287                        int m = d1 & 0x7ff;
 288                        int ex = (d1 & 0x7800) >> 11;
 289                        float temp = ((float) m * (1 << ex) / 100);
 290                        /* printf ("d1=%d;m=%d;ex=%d;temp=%f\n", d1, m, ex, temp); */
 291                        printf ("%2.1f", temp);
 292                      }
 293                    else
 294                      printHex (len - 2, buf + 2);
 295                  }
 296                printf ("\n");
 297                break;
 298              }
 299          }
 300      }
 301    else if (strcmp (prog, "dimup") == 0)
 302      {
 303        if (ac != 4)
 304          die ("usage: %s url eibaddr time", prog);
 305        con = open_con(ag[1]);
 306  
 307        dest = readgaddr (ag[2]);
 308  
 309        if (EIBOpenT_Group (con, dest, 0) == -1)
 310          die ("Connect failed");
 311  
 312        buf[0] = 0;
 313        buf[1] = 0x80;
 314        int time = atoi(ag[3]);
 315        if (time <= 0)
 316          die ("Invalid param: time");
 317  
 318        unsigned long step = time * 8333;
 319        int idx;
 320        int fd = EIB_Poll_FD (con);
 321        struct timeval tv;
 322        fd_set fds;
 323        tv.tv_sec = 0;
 324        tv.tv_usec = 0;
 325        for (idx = 0; idx < 120; idx++)
 326          {
 327            buf[2] = idx * 2;
 328            len = EIBSendAPDU (con, 3, buf);
 329            if (len == -1)
 330              die ("Request failed");
 331            usleep (step);
 332            FD_ZERO (&fds);
 333            FD_SET (fd, &fds);
 334            while (select (fd + 1, &fds, NULL, NULL, &tv) > 0)
 335              {
 336                if (EIB_Poll_Complete (con) == 1)
 337                  {
 338                    len = EIBGetAPDU_Src (con, sizeof (buf), buf, &src);
 339                    if (len == 3 && (buf[1] & 0xC0) == 0x80)
 340                      {
 341                        printf ("Read value %02X\n", buf[2]);
 342                        if (buf[2] < idx * 2)
 343                          {
 344                            printf ("Abort dim\n");
 345                            goto out;
 346                          }
 347                      }
 348  
 349                  }
 350  
 351              }
 352          }
 353        printf ("Dimmed up\n");
 354      }
 355    else if (strcmp (prog, "log") == 0)
 356      {
 357        int prev_day = -1;
 358        FILE *log_fd = stderr;
 359  
 360        if (ac != 2)
 361          die ("usage: %s url", prog);
 362        con = open_con(ag[1]);
 363  
 364        if (EIBOpenVBusmonitorText (con) == -1)
 365          die ("Open Busmonitor failed");
 366  
 367        while (1)
 368          {
 369            time_t clock;
 370            struct tm *loctim;
 371            len = EIBGetBusmonitorPacket (con, sizeof (buf), buf);
 372            if (len == -1)
 373              die ("Read failed");
 374            clock = time (NULL);
 375            loctim = localtime (&clock);
 376  
 377            if (prev_day != loctim->tm_yday)
 378              {
 379                char logfile[32];
 380                FILE *new_fd;
 381                prev_day = loctim->tm_yday;
 382                snprintf (logfile, 31, "knx-%hd-%02hd-%02hd.log",
 383                          loctim->tm_year + 1900,
 384                          loctim->tm_mon + 1, loctim->tm_mday);
 385  
 386                if (NULL == (new_fd = fopen (logfile, "a")))
 387                  {
 388                    fprintf (log_fd, "Unable to create logfile: %s\n", logfile);
 389                  }
 390                else
 391                  {
 392                    if (log_fd != stderr)
 393                      {
 394                        fprintf (log_fd, "Logfile closed\n");
 395                        fclose (log_fd);
 396                      }
 397                    log_fd = new_fd;
 398                    fprintf (log_fd, "Logfile opened\n");
 399                  }
 400              }
 401            fprintf (log_fd, "%d-%02d-%02d %02d:%02d:%02d : %s\n",
 402                     loctim->tm_year + 1900,
 403                     loctim->tm_mon + 1,
 404                     loctim->tm_mday,
 405                     loctim->tm_hour, loctim->tm_min, loctim->tm_sec, buf);
 406            fflush (log_fd);
 407          }
 408        if (log_fd != stderr)
 409          {
 410            fprintf (log_fd, "Logfile closed\n");
 411            fclose (log_fd);
 412          }
 413      }
 414    else if (strcmp (prog, "busmonitor1") == 0)
 415      {
 416        if (ac != 2)
 417          die ("usage: %s url", prog);
 418        con = open_con(ag[1]);
 419  
 420        if (EIBOpenBusmonitorText (con) == -1)
 421          die ("Open Busmonitor failed");
 422        while (1)
 423          {
 424            len = EIBGetBusmonitorPacket (con, sizeof (buf), buf);
 425            if (len == -1)
 426              die ("Read failed");
 427            buf[len] = 0;
 428            printf ("%s\n", buf);
 429            fflush (stdout);
 430          }
 431      }
 432    else if (strcmp (prog, "busmonitor2") == 0)
 433      {
 434        if (ac != 2)
 435          die ("usage: %s url", prog);
 436        con = open_con(ag[1]);
 437  
 438        if (EIBOpenBusmonitor (con) == -1)
 439          die ("Open Busmonitor failed");
 440        while (1)
 441          {
 442            len = EIBGetBusmonitorPacket (con, sizeof (buf), buf);
 443            if (len == -1)
 444              die ("Read failed");
 445            printHex (len, buf);
 446            printf ("\n");
 447            fflush (stdout);
 448          }
 449      }
 450    else if (strcmp (prog, "busmonitor3") == 0)
 451      {
 452        uint32_t ts;
 453        uint8_t status;
 454        if (ac != 2)
 455          die ("usage: %s url", prog);
 456        con = open_con(ag[1]);
 457  
 458        if (EIBOpenBusmonitorTS (con, &ts) == -1)
 459          die ("Open Busmonitor failed");
 460  
 461        printf ("TS-Base: %08x\n", ts);
 462  
 463        while (1)
 464          {
 465            len = EIBGetBusmonitorPacketTS (con, &status, &ts, sizeof (buf), buf);
 466            if (len == -1)
 467              die ("Read failed");
 468            printf ("(%d, %08x) ", status, ts);
 469            printHex (len, buf);
 470            printf ("\n");
 471            fflush (stdout);
 472          }
 473      }
 474  
 475    else if (strcmp (prog, "groupcacheclear") == 0)
 476      {
 477        if (ac != 2)
 478          die ("usage: %s url", prog);
 479        con = open_con(ag[1]);
 480  
 481        len = EIB_Cache_Clear (con);
 482        if (len == -1)
 483          die ("Clear failed");
 484      }
 485    else if (strcmp (prog, "groupcachedisable") == 0)
 486      {
 487        if (ac != 2)
 488          die ("usage: %s url", prog);
 489        con = open_con(ag[1]);
 490  
 491        len = EIB_Cache_Disable (con);
 492        if (len == -1)
 493          die ("Disable failed");
 494      }
 495    else if (strcmp (prog, "groupcacheenable") == 0)
 496      {
 497        if (ac != 2)
 498          die ("usage: %s url", prog);
 499        con = open_con(ag[1]);
 500        len = EIB_Cache_Enable (con);
 501        if (len == -1)
 502          die ("Enable failed");
 503  
 504      }
 505    else if (strcmp (prog, "groupcachelastupdates") == 0)
 506      {
 507        int i;
 508        int start;
 509        int timeout;
 510        uint32_t end;
 511  
 512        if (ac != 4)
 513          die ("usage: %s url start-position timeout", prog);
 514        con = open_con(ag[1]);
 515        start = atoi (ag[2]);
 516        timeout = atoi (ag[3]);
 517  
 518        len = EIB_Cache_LastUpdates2 (con, start, timeout, sizeof (buf), buf, &end);
 519        if (len == -1)
 520          die ("Read failed");
 521  
 522        printf ("new position: %d\n", end);
 523        for (i = 0; i < len; i += 2)
 524          {
 525            eibaddr_t a = (buf[i] << 8) | buf[i + 1];
 526            printGroup (a);
 527            printf ("\n");
 528          }
 529        printf ("\n");
 530      }
 531    else if (strcmp (prog, "groupcacheread") == 0)
 532      {
 533        if (ac != 3)
 534          die ("usage: %s url groupaddr", prog);
 535        con = open_con(ag[1]);
 536        dest = readgaddr (ag[2]);
 537  
 538        len = EIB_Cache_Read (con, dest, &src, sizeof (buf), buf);
 539        if (len == -1)
 540          die ("Read failed");
 541  
 542        switch (buf[1] & 0xC0)
 543          {
 544          case 0x40:
 545            printf ("Response");
 546            break;
 547          case 0x80:
 548            printf ("Write");
 549            break;
 550          }
 551        printf (" from ");
 552        printIndividual (src);
 553        if (buf[1] & 0xC0)
 554          {
 555            printf (": ");
 556            if (len == 2)
 557              printf ("%02X", buf[1] & 0x3F);
 558            else
 559              printHex (len - 2, buf + 2);
 560          }
 561        printf ("\n");
 562      }
 563    else if (strcmp (prog, "groupcachereadsync") == 0)
 564      {
 565        uint16_t age = 0;
 566  
 567        if (ac != 3 && ac != 4)
 568          die ("usage: %s url eibaddr [age]", prog);
 569        con = open_con(ag[1]);
 570        dest = readgaddr (ag[2]);
 571        if (ac == 4)
 572          age = atoi (ag[3]);
 573  
 574        len = EIB_Cache_Read_Sync (con, dest, &src, sizeof (buf), buf, age);
 575        if (len == -1)
 576          die ("Read failed");
 577  
 578        switch (buf[1] & 0xC0)
 579          {
 580          case 0x40:
 581            printf ("Response");
 582            break;
 583          case 0x80:
 584            printf ("Write");
 585            break;
 586          }
 587        printf (" from ");
 588        printIndividual (src);
 589        if (buf[1] & 0xC0)
 590          {
 591            printf (": ");
 592            if (len == 2)
 593              printf ("%02X", buf[1] & 0x3F);
 594            else
 595              printHex (len - 2, buf + 2);
 596          }
 597        printf ("\n");
 598      }
 599    else if (strcmp (prog, "groupcacheremove") == 0)
 600      {
 601        if (ac != 3)
 602          die ("usage: %s url eibaddr", prog);
 603        con = open_con(ag[1]);
 604        dest = readgaddr (ag[2]);
 605  
 606        len = EIB_Cache_Remove (con, dest);
 607        if (len == -1)
 608          die ("Remove failed");
 609      }
 610    else if (strcmp (prog, "grouplisten") == 0)
 611      {
 612        if (ac != 3)
 613          die ("usage: %s url eibaddr", prog);
 614        con = open_con(ag[1]);
 615        dest = readgaddr (ag[2]);
 616  
 617        if (EIBOpenT_Group (con, dest, 0) == -1)
 618          die ("Connect failed");
 619  
 620        while (1)
 621          {
 622            len = EIBGetAPDU_Src (con, sizeof (buf), buf, &src);
 623            if (len == -1)
 624              die ("Read failed");
 625            if (len < 2)
 626              die ("Invalid Packet");
 627            if (buf[0] & 0x3 || (buf[1] & 0xC0) == 0xC0)
 628              {
 629                printf ("Unknown APDU from ");
 630                printIndividual (src);
 631                printf (": ");
 632                printHex (len, buf);
 633                printf ("\n");
 634              }
 635            else
 636              {
 637                switch (buf[1] & 0xC0)
 638                  {
 639                  case 0x00:
 640                    printf ("Read");
 641                    break;
 642                  case 0x40:
 643                    printf ("Response");
 644                    break;
 645                  case 0x80:
 646                    printf ("Write");
 647                    break;
 648                  }
 649                printf (" from ");
 650                printIndividual (src);
 651                if (buf[1] & 0xC0)
 652                  {
 653                    printf (": ");
 654                    if (len == 2)
 655                      printf ("%02X", buf[1] & 0x3F);
 656                    else
 657                      printHex (len - 2, buf + 2);
 658                  }
 659                printf ("\n");
 660              }
 661          }
 662      }
 663    else if (strcmp (prog, "groupread") == 0)
 664      {
 665        buf[0] = 0x0;
 666        buf[1] = 0x0;
 667  
 668        if (ac != 3)
 669          die ("usage: %s url eibaddr", prog);
 670        con = open_con(ag[1]);
 671        dest = readgaddr (ag[2]);
 672  
 673        if (EIBOpenT_Group (con, dest, 1) == -1)
 674          die ("Connect failed");
 675  
 676        len = EIBSendAPDU (con, 2, buf);
 677        if (len == -1)
 678          die ("Request failed");
 679        printf ("Send request\n");
 680      }
 681    else if (strcmp (prog, "groupreadresponse") == 0)
 682      {
 683        uint8_t req_buf[2] = { 0, 0 };
 684        fd_set read;
 685        struct timeval tv;
 686  
 687        if (ac != 3)
 688          die ("usage: %s url eibaddr", prog);
 689        con = open_con(ag[1]);
 690        dest = readgaddr (ag[2]);
 691  
 692        if (EIBOpenT_Group (con, dest, 0) == -1)
 693          die ("Connect failed");
 694  
 695        len = EIBSendAPDU (con, 2, req_buf);
 696        if (len == -1)
 697          die ("Request failed");
 698        printf ("Send request\n");
 699  
 700        while (1)
 701          {
 702            tv.tv_usec = 0;
 703            tv.tv_sec = 10;
 704  lp:
 705            FD_ZERO (&read);
 706            FD_SET (EIB_Poll_FD (con), &read);
 707  
 708            if (select (EIB_Poll_FD (con) + 1, &read, 0, 0, &tv) == -1)
 709              die ("select failed");
 710  
 711            len = EIB_Poll_Complete (con);
 712            if (len == -1)
 713              die ("Read failed");
 714            if (len == 0)
 715              {
 716                if (tv.tv_sec == 0 && tv.tv_usec == 0)
 717                  goto end;
 718                goto lp;
 719              }
 720  
 721            len = EIBGetAPDU_Src (con, sizeof (buf), buf, &src);
 722            if (len == -1)
 723              die ("Read failed");
 724            if (len < 2)
 725              die ("Invalid Packet");
 726            if (buf[0] & 0x3 || (buf[1] & 0xC0) == 0xC0)
 727              {
 728                printf ("Unknown APDU from ");
 729                printIndividual (src);
 730                printf (": ");
 731                printHex (len, buf);
 732                printf ("\n");
 733              }
 734            else
 735              {
 736                switch (buf[1] & 0xC0)
 737                  {
 738                  case 0x00:
 739                    printf ("Read");
 740                    break;
 741                  case 0x40:
 742                    printf ("Response");
 743                    break;
 744                  case 0x80:
 745                    printf ("Write");
 746                    break;
 747                  }
 748                printf (" from ");
 749                printIndividual (src);
 750                if (buf[1] & 0xC0)
 751                  {
 752                    printf (": ");
 753                    if (len == 2)
 754                      printf ("%02X", buf[1] & 0x3F);
 755                    else
 756                      printHex (len - 2, buf + 2);
 757                  }
 758                printf ("\n");
 759                switch (buf[1] & 0xC0)
 760                  {
 761                  case 0x80:
 762                  case 0x40:
 763                    goto end;
 764                  }
 765              }
 766          }
 767  end:
 768        fprintf (stderr, "Ending %s.\n", prog);
 769      }
 770    else if (strcmp (prog, "groupresponse") == 0)
 771      {
 772        uint8_t lbuf[255] = { 0, 0x40 };
 773  
 774        if (ac < 4)
 775          die ("usage: %s url eibaddr val val ...", prog);
 776        con = open_con(ag[1]);
 777        die ("Open failed");
 778        dest = readgaddr (ag[2]);
 779        len = readBlock (lbuf + 2, sizeof (lbuf) - 2, ac - 3, ag + 3);
 780        if (len < 0)
 781          die ("Invalid hex bytes");
 782  
 783        if (EIBOpenT_Group (con, dest, 1) == -1)
 784          die ("Connect failed");
 785  
 786        len = EIBSendAPDU (con, 2 + len, lbuf);
 787        if (len == -1)
 788          die ("Request failed");
 789        printf ("Send request\n");
 790      }
 791    else if (strcmp (prog, "groupsocketlisten") == 0)
 792      {
 793        if (ac != 2)
 794          die ("usage: %s url", prog);
 795        con = open_con(ag[1]);
 796  
 797        if (EIBOpen_GroupSocket (con, 0) == -1)
 798          die ("Connect failed");
 799  
 800        while (1)
 801          {
 802            len = EIBGetGroup_Src (con, sizeof (buf), buf, &src, &dest);
 803            if (len == -1)
 804              die ("Read failed");
 805            if (len < 2)
 806              die ("Invalid Packet");
 807            if (buf[0] & 0x3 || (buf[1] & 0xC0) == 0xC0)
 808              {
 809                printf ("Unknown APDU from ");
 810                printIndividual (src);
 811                printf (" to ");
 812                printGroup (dest);
 813                printf (": ");
 814                printHex (len, buf);
 815                printf ("\n");
 816              }
 817            else
 818              {
 819                switch (buf[1] & 0xC0)
 820                  {
 821                  case 0x00:
 822                    printf ("Read");
 823                    break;
 824                  case 0x40:
 825                    printf ("Response");
 826                    break;
 827                  case 0x80:
 828                    printf ("Write");
 829                    break;
 830                  }
 831                printf (" from ");
 832                printIndividual (src);
 833                printf (" to ");
 834                printGroup (dest);
 835                if (buf[1] & 0xC0)
 836                  {
 837                    printf (": ");
 838                    if (len == 2)
 839                      printf ("%02X", buf[1] & 0x3F);
 840                    else
 841                      printHex (len - 2, buf + 2);
 842                  }
 843                printf ("\n");
 844              }
 845          }
 846      }
 847    else if (strcmp (prog, "groupsocketread") == 0)
 848      {
 849        buf[0] = 0x0;
 850        buf[1] = 0x0;
 851  
 852        if (ac != 3)
 853          die ("usage: %s url eibaddr", prog);
 854        con = open_con(ag[1]);
 855        dest = readgaddr (ag[2]);
 856  
 857        if (EIBOpen_GroupSocket (con, 1) == -1)
 858          die ("Connect failed");
 859  
 860        len = EIBSendGroup (con, dest, 2, buf);
 861        if (len == -1)
 862          die ("Request failed");
 863        printf ("Send request\n");
 864      }
 865    else if (strcmp (prog, "groupsocketwrite") == 0)
 866      {
 867        buf[0] = 0x0;
 868        buf[1] = 0x80;
 869  
 870        if (ac < 4)
 871          die ("usage: %s url eibaddr val val ...", prog);
 872        con = open_con(ag[1]);
 873        dest = readgaddr (ag[2]);
 874        len = readBlock (buf + 2, sizeof (buf) - 2, ac - 3, ag + 3);
 875  
 876        if (EIBOpen_GroupSocket (con, 1) == -1)
 877          die ("Connect failed");
 878  
 879        len = EIBSendGroup (con, dest, 2 + len, buf);
 880        if (len == -1)
 881          die ("Request failed");
 882        printf ("Send request\n");
 883      }
 884    else if (strcmp (prog, "groupsocketswrite") == 0)
 885      {
 886        uint8_t lbuf[3] = { 0x0, 0x80 };
 887  
 888        if (ac != 4)
 889          die ("usage: %s url eibaddr val", prog);
 890        con = open_con(ag[1]);
 891        dest = readgaddr (ag[2]);
 892        lbuf[1] |= readHex (ag[3]) & 0x3f;
 893  
 894        if (EIBOpen_GroupSocket (con, 1) == -1)
 895          die ("Connect failed");
 896  
 897        len = EIBSendGroup (con, dest, 2, lbuf);
 898        if (len == -1)
 899          die ("Request failed");
 900        printf ("Send request\n");
 901      }
 902    else if (strcmp (prog, "groupsresponse") == 0)
 903      {
 904        uint8_t lbuf[3] = { 0x0, 0x40 };
 905  
 906        if (ac != 4)
 907          die ("usage: %s url eibaddr val", prog);
 908        con = open_con(ag[1]);
 909        dest = readgaddr (ag[2]);
 910        lbuf[1] |= readHex (ag[3]) & 0x3f;
 911  
 912        if (EIBOpenT_Group (con, dest, 1) == -1)
 913          die ("Connect failed");
 914  
 915        len = EIBSendAPDU (con, 2, lbuf);
 916        if (len == -1)
 917          die ("Request failed");
 918        printf ("Send request\n");
 919      }
 920    else if (strcmp (prog, "groupswrite") == 0)
 921      {
 922        uint8_t lbuf[3] = { 0x0, 0x80 };
 923  
 924        if (ac != 4)
 925          die ("usage: %s url eibaddr val", prog);
 926        con = open_con(ag[1]);
 927        dest = readgaddr (ag[2]);
 928        lbuf[1] |= readHex (ag[3]) & 0x3f;
 929  
 930        if (EIBOpenT_Group (con, dest, 1) == -1)
 931          die ("Connect failed");
 932  
 933        len = EIBSendAPDU (con, 2, lbuf);
 934        if (len == -1)
 935          die ("Request failed");
 936        printf ("Send request\n");
 937      }
 938    else if (strcmp (prog, "groupwrite") == 0)
 939      {
 940        uint8_t lbuf[255] = { 0x0, 0x80 };
 941  
 942        if (ac < 4)
 943          die ("usage: %s url eibaddr val val ...", prog);
 944        con = open_con(ag[1]);
 945        dest = readgaddr (ag[2]);
 946        len = readBlock (lbuf + 2, sizeof (lbuf) - 2, ac - 3, ag + 3);
 947        if (len < 0)
 948          die ("Invalid hex bytes");
 949  
 950        if (EIBOpenT_Group (con, dest, 1) == -1)
 951          die ("Connect failed");
 952  
 953        len = EIBSendAPDU (con, 2 + len, lbuf);
 954        if (len == -1)
 955          die ("Request failed");
 956        printf ("Send request\n");
 957  
 958      }
 959    else if (strcmp (prog, "madcread") == 0)
 960      {
 961        int channel;
 962        int16_t val;
 963  
 964        parseKey (&ac, &ag);
 965        if (ac != 5)
 966          die ("usage: %s [-k key] url eibaddr channel count", prog);
 967        con = open_con(ag[1]);
 968        dest = readaddr (ag[2]);
 969        channel = atoi (ag[3]);
 970        len = atoi (ag[4]);
 971  
 972        if (EIB_MC_Connect (con, dest) == -1)
 973          die ("Connect failed");
 974        auth (con);
 975  
 976        len = EIB_MC_ReadADC (con, channel, len, &val);
 977        if (len == -1)
 978          die ("Read failed");
 979        printf ("Value: %d\n", val);
 980      }
 981    else if (strcmp (prog, "maskver") == 0)
 982      {
 983        if (ac != 3)
 984          die ("usage: %s url eibaddr", prog);
 985        con = open_con(ag[1]);
 986        dest = readaddr (ag[2]);
 987  
 988        len = EIB_M_GetMaskVersion (con, dest);
 989        if (len == -1)
 990          die ("Read failed");
 991        printf ("Mask: %04X\n", len);
 992      }
 993    else if (strcmp (prog, "mmaskver") == 0)
 994      {
 995        parseKey (&ac, &ag);
 996        if (ac != 3)
 997          die ("usage: %s [-k key] url eibaddr", prog);
 998        con = open_con(ag[1]);
 999        dest = readaddr (ag[2]);
1000  
1001        if (EIB_MC_Connect (con, dest) == -1)
1002          die ("Connect failed");
1003        auth (con);
1004  
1005        len = EIB_MC_GetMaskVersion (con);
1006        if (len == -1)
1007          die ("Read failed");
1008        printf ("Mask: %04X\n", len);
1009      }
1010    else if (strcmp (prog, "mpeitype") == 0)
1011      {
1012        parseKey (&ac, &ag);
1013        if (ac != 3)
1014          die ("usage: %s [-k key] url eibaddr", prog);
1015        con = open_con(ag[1]);
1016        dest = readaddr (ag[2]);
1017  
1018        if (EIB_MC_Connect (con, dest) == -1)
1019          die ("Connect failed");
1020        auth (con);
1021  
1022        len = EIB_MC_GetPEIType (con);
1023        if (len == -1)
1024          die ("Read failed");
1025        printf ("PEI: %d\n", len);
1026      }
1027    else if (strcmp (prog, "mprogmodeoff") == 0)
1028      {
1029        parseKey (&ac, &ag);
1030        if (ac != 3)
1031          die ("usage: %s [-k key] url eibaddr", prog);
1032        con = open_con(ag[1]);
1033        dest = readaddr (ag[2]);
1034  
1035        if (EIB_MC_Connect (con, dest) == -1)
1036          die ("Connect failed");
1037        auth (con);
1038  
1039        len = EIB_MC_Progmode_Off (con);
1040        if (len == -1)
1041          die ("Set failed");
1042      }
1043    else if (strcmp (prog, "mprogmodeon") == 0)
1044      {
1045        parseKey (&ac, &ag);
1046        if (ac != 3)
1047          die ("usage: %s [-k key] url eibaddr", prog);
1048        con = open_con(ag[1]);
1049        dest = readaddr (ag[2]);
1050  
1051        if (EIB_MC_Connect (con, dest) == -1)
1052          die ("Connect failed");
1053        auth (con);
1054  
1055        len = EIB_MC_Progmode_On (con);
1056        if (len == -1)
1057          die ("Set failed");
1058      }
1059    else if (strcmp (prog, "mprogmodestatus") == 0)
1060      {
1061        parseKey (&ac, &ag);
1062        if (ac != 3)
1063          die ("usage: %s [-k key] url eibaddr", prog);
1064        con = open_con(ag[1]);
1065        dest = readaddr (ag[2]);
1066  
1067        if (EIB_MC_Connect (con, dest) == -1)
1068          die ("Connect failed");
1069        auth (con);
1070  
1071        len = EIB_MC_Progmode_Status (con);
1072        if (len == -1)
1073          die ("Set failed");
1074        if (len)
1075          printf ("in programming mode\n");
1076        else
1077          printf ("not in programming mode\n");
1078  
1079      }
1080    else if (strcmp (prog, "mprogmodetoggle") == 0)
1081      {
1082        parseKey (&ac, &ag);
1083        if (ac != 3)
1084          die ("usage: %s [-k key] url eibaddr", prog);
1085        con = open_con(ag[1]);
1086        dest = readaddr (ag[2]);
1087  
1088        if (EIB_MC_Connect (con, dest) == -1)
1089          die ("Connect failed");
1090        auth (con);
1091  
1092        len = EIB_MC_Progmode_Toggle (con);
1093        if (len == -1)
1094          die ("Set failed");
1095      }
1096    else if (strcmp (prog, "mpropdesc") == 0)
1097      {
1098        int obj, prop;
1099        uint8_t type, access;
1100        uint16_t count;
1101  
1102        parseKey (&ac, &ag);
1103        if (ac != 5)
1104          die ("usage: %s [-k key] url eibaddr obj prop", prog);
1105        con = open_con(ag[1]);
1106        dest = readaddr (ag[2]);
1107        obj = atoi (ag[3]);
1108        prop = atoi (ag[4]);
1109  
1110        if (EIB_MC_Connect (con, dest) == -1)
1111          die ("Connect failed");
1112        auth (con);
1113  
1114        len = EIB_MC_PropertyDesc (con, obj, prop, &type, &count, &access);
1115        if (len == -1)
1116          die ("Read failed");
1117        printf ("Property: type:%d count:%d access:%02X\n", type, count,
1118                access);
1119      }
1120    else if (strcmp (prog, "mpropread") == 0)
1121      {
1122        int obj, prop, start, nr_of_elem;
1123  
1124        parseKey (&ac, &ag);
1125        if (ac != 7)
1126          die ("usage: %s [-k key] url eibaddr obj prop start nr_of_elem",
1127               prog);
1128        con = open_con(ag[1]);
1129        dest = readaddr (ag[2]);
1130        obj = atoi (ag[3]);
1131        prop = atoi (ag[4]);
1132        start = atoi (ag[5]);
1133        nr_of_elem = atoi (ag[6]);
1134  
1135        if (EIB_MC_Connect (con, dest) == -1)
1136          die ("Connect failed");
1137        auth (con);
1138  
1139        len =
1140          EIB_MC_PropertyRead (con, obj, prop, start, nr_of_elem, sizeof (buf),
1141                               buf);
1142        if (len == -1)
1143          die ("Read failed");
1144        printHex (len, buf);
1145  
1146      }
1147    else if (strcmp (prog, "mpropscan") == 0)
1148      {
1149        int i;
1150  
1151        parseKey (&ac, &ag);
1152        if (ac != 3)
1153          die ("usage: %s [-k key] url eibaddr", prog);
1154        con = open_con(ag[1]);
1155        dest = readaddr (ag[2]);
1156  
1157        if (EIB_MC_Connect (con, dest) == -1)
1158          die ("Connect failed");
1159        auth (con);
1160  
1161        len = EIB_MC_PropertyScan (con, sizeof (buf), buf);
1162        if (len == -1)
1163          die ("Read failed");
1164        for (i = 0; i < len; i += 6)
1165          if (buf[i + 1] == 1 && buf[i + 2] == 4)
1166            printf ("Obj: %d Property: %d Type: %d Objtype:%d Access:%02X\n",
1167                    buf[i + 0], buf[i + 1], buf[i + 2],
1168                    (buf[i + 3] << 8) | buf[i + 4], buf[i + 5]);
1169          else
1170            printf ("Obj: %d Property: %d Type: %d Count:%d Access:%02X\n",
1171                    buf[i + 0], buf[i + 1], buf[i + 2],
1172                    (buf[i + 3] << 8) | buf[i + 4], buf[i + 5]);
1173  
1174      }
1175    else if (strcmp (prog, "mpropscanpoll") == 0)
1176      {
1177        fd_set read;
1178        int i;
1179  
1180        parseKey (&ac, &ag);
1181        if (ac != 3)
1182          die ("usage: %s [-k key] url eibaddr", prog);
1183        con = open_con(ag[1]);
1184        dest = readaddr (ag[2]);
1185  
1186        if (EIB_MC_Connect (con, dest) == -1)
1187          die ("Connect failed");
1188        auth (con);
1189  
1190        len = EIB_MC_PropertyScan_async (con, sizeof (buf), buf);
1191        if (len == -1)
1192          die ("Read failed");
1193  
1194  lp0:
1195        FD_ZERO (&read);
1196        FD_SET (EIB_Poll_FD (con), &read);
1197        printf ("Waiting\n");
1198        if (select (EIB_Poll_FD (con) + 1, &read, 0, 0, 0) == -1)
1199          die ("select failed");
1200        printf ("Data available\n");
1201        len = EIB_Poll_Complete (con);
1202        if (len == -1)
1203          die ("Read failed");
1204        if (len == 0)
1205          goto lp0;
1206        printf ("Completed\n");
1207  
1208        len = EIBComplete (con);
1209  
1210        for (i = 0; i < len; i += 6)
1211          if (buf[i + 1] == 1 && buf[i + 2] == 4)
1212            printf ("Obj: %d Property: %d Type: %d Objtype:%d Access:%02X\n",
1213                    buf[i + 0], buf[i + 1], buf[i + 2],
1214                    (buf[i + 3] << 8) | buf[i + 4], buf[i + 5]);
1215          else
1216            printf ("Obj: %d Property: %d Type: %d Count:%d Access:%02X\n",
1217                    buf[i + 0], buf[i + 1], buf[i + 2],
1218                    (buf[i + 3] << 8) | buf[i + 4], buf[i + 5]);
1219  
1220      }
1221    else if (strcmp (prog, "mpropwrite") == 0)
1222      {
1223        int obj, prop, start, nr_of_elem;
1224        uint8_t res[255];
1225  
1226        parseKey (&ac, &ag);
1227        if (ac < 7)
1228          {
1229            die("usage: %s [-k key] url eibaddr obj prop start nr_of_elem "
1230                "[xx xx ..]", prog);
1231          }
1232        con = open_con(ag[1]);
1233        dest = readaddr (ag[2]);
1234        obj = atoi (ag[3]);
1235        prop = atoi (ag[4]);
1236        start = atoi (ag[5]);
1237        nr_of_elem = atoi (ag[6]);
1238        len = readBlock (buf, sizeof (buf), ac - 7, ag + 7);
1239        if (len < 0)
1240          die ("Invalid hex bytes");
1241  
1242        if (EIB_MC_Connect (con, dest) == -1)
1243          die ("Connect failed");
1244        auth (con);
1245  
1246        printf ("Write: ");
1247        printHex (len, buf);
1248        printf ("\n");
1249        len =
1250          EIB_MC_PropertyWrite (con, obj, prop, start, nr_of_elem, len, buf,
1251                                sizeof (res), res);
1252        if (len == -1)
1253          die ("Write failed");
1254        printHex (len, res);
1255      }
1256    else if (strcmp (prog, "mread") == 0)
1257      {
1258        int addr;
1259  
1260        parseKey (&ac, &ag);
1261        if (ac != 5)
1262          die ("usage: %s url [-k key] eibaddr addr count", prog);
1263        con = open_con(ag[1]);
1264        dest = readaddr (ag[2]);
1265        addr = readHex (ag[3]);
1266        len = atoi (ag[4]);
1267  
1268        if (EIB_MC_Connect (con, dest) == -1)
1269          die ("Connect failed");
1270        auth (con);
1271  
1272        len = EIB_MC_Read (con, addr, len, buf);
1273        if (len == -1)
1274          die ("Read failed");
1275        printHex (len, buf);
1276      }
1277    else if (strcmp (prog, "mrestart") == 0)
1278      {
1279        parseKey (&ac, &ag);
1280        if (ac != 3)
1281          die ("usage: %s [-k key] url eibaddr", prog);
1282        con = open_con(ag[1]);
1283        dest = readaddr (ag[2]);
1284  
1285        if (EIB_MC_Connect (con, dest) == -1)
1286          die ("Connect failed");
1287        auth (con);
1288  
1289        len = EIB_MC_Restart (con);
1290        if (len == -1)
1291          die ("Restart failed");
1292  
1293      }
1294    else if (strcmp (prog, "msetkey") == 0)
1295      {
1296        int level, k;
1297        uint8_t key[4];
1298  
1299        parseKey (&ac, &ag);
1300        if (ac != 5)
1301          die ("usage: %s [-k key] url eibaddr level key", prog);
1302        con = open_con(ag[1]);
1303        dest = readaddr (ag[2]);
1304        level = atoi (ag[3]);
1305        sscanf (ag[4], "%x", &k);
1306        key[0] = (k >> 24) & 0xff;
1307        key[1] = (k >> 16) & 0xff;
1308        key[2] = (k >> 8) & 0xff;
1309        key[3] = (k >> 0) & 0xff;
1310  
1311        if (EIB_MC_Connect (con, dest) == -1)
1312          die ("Connect failed");
1313        auth (con);
1314  
1315        k = EIB_MC_SetKey (con, key, level);
1316        if (k == -1)
1317          die ("SetKey failed");
1318  
1319      }
1320    else if (strcmp (prog, "mwrite") == 0)
1321      {
1322        int addr;
1323  
1324        parseKey (&ac, &ag);
1325        if (ac < 4)
1326          die ("usage: %s [-k key] url eibaddr addr [xx xx xx ..]", prog);
1327        con = open_con(ag[1]);
1328        dest = readaddr (ag[2]);
1329        addr = readHex (ag[3]);
1330        len = readBlock (buf, sizeof (buf), ac - 4, ag + 4);
1331        if (len < 0)
1332          die ("Invalid hex bytes");
1333  
1334        if (EIB_MC_Connect (con, dest) == -1)
1335          die ("Connect failed");
1336        auth (con);
1337  
1338        printf ("Write: ");
1339        printHex (len, buf);
1340        printf ("\n");
1341        len = EIB_MC_Write (con, addr, len, buf);
1342        if (len == -1)
1343          die ("Write failed");
1344  
1345      }
1346    else if (strcmp (prog, "mwriteplain") == 0)
1347      {
1348        int addr;
1349  
1350        parseKey (&ac, &ag);
1351        if (ac < 4)
1352          die ("usage: %s [-k key] url eibaddr addr [xx xx xx ..]", prog);
1353        con = open_con(ag[1]);
1354  
1355        dest = readaddr (ag[2]);
1356        addr = readHex (ag[3]);
1357        len = readBlock (buf, sizeof (buf), ac - 4, ag + 4);
1358        if (len < 0)
1359          die ("Invalid hex bytes");
1360  
1361        if (EIB_MC_Connect (con, dest) == -1)
1362          die ("Connect failed");
1363        auth (con);
1364  
1365        printf ("Write: ");
1366        printHex (len, buf);
1367        printf ("\n");
1368        len = EIB_MC_Write_Plain (con, addr, len, buf);
1369        if (len == -1)
1370          die ("Write failed");
1371      }
1372    else if (strcmp (prog, "progmodeoff") == 0)
1373      {
1374        if (ac != 3)
1375          die ("usage: %s url eibaddr", prog);
1376        con = open_con(ag[1]);
1377        dest = readaddr (ag[2]);
1378  
1379        len = EIB_M_Progmode_Off (con, dest);
1380        if (len == -1)
1381          die ("Set failed");
1382      }
1383    else if (strcmp (prog, "progmodeon") == 0)
1384      {
1385        if (ac != 3)
1386          die ("usage: %s url eibaddr", prog);
1387        con = open_con(ag[1]);
1388        dest = readaddr (ag[2]);
1389  
1390        len = EIB_M_Progmode_On (con, dest);
1391        if (len == -1)
1392          die ("Set failed");
1393  
1394      }
1395    else if (strcmp (prog, "progmodestatus") == 0)
1396      {
1397        if (ac != 3)
1398          die ("usage: %s url eibaddr", prog);
1399        con = open_con(ag[1]);
1400        dest = readaddr (ag[2]);
1401  
1402        len = EIB_M_Progmode_Status (con, dest);
1403        if (len == -1)
1404          die ("Set failed");
1405        if (len)
1406          printf ("in programming mode\n");
1407        else
1408          printf ("not in programming mode\n");
1409      }
1410    else if (strcmp (prog, "progmodetoggle") == 0)
1411      {
1412        if (ac != 3)
1413          die ("usage: %s url eibaddr", prog);
1414        con = open_con(ag[1]);
1415        dest = readaddr (ag[2]);
1416  
1417        len = EIB_M_Progmode_Toggle (con, dest);
1418        if (len == -1)
1419          die ("Set failed");
1420      }
1421    else if (strcmp (prog, "readindividual") == 0)
1422      {
1423        int i;
1424  
1425        if (ac != 2)
1426          die ("usage: %s url", prog);
1427        con = open_con(ag[1]);
1428  
1429        len = EIB_M_ReadIndividualAddresses (con, sizeof (buf), buf);
1430        if (len == -1)
1431          die ("Read failed");
1432        for (i = 0; i < len; i += 2)
1433          {
1434            printf ("Addr: ");
1435            printIndividual ((buf[i] << 8) | buf[i + 1]);
1436            printf ("\n");
1437          }
1438      }
1439    else if (strcmp (prog, "vbusmonitor1") == 0)
1440      {
1441        if (ac != 2)
1442          die ("usage: %s url", prog);
1443        con = open_con(ag[1]);
1444  
1445        if (EIBOpenVBusmonitorText (con) == -1)
1446          die ("Open Busmonitor failed");
1447  
1448        while (1)
1449          {
1450            len = EIBGetBusmonitorPacket (con, sizeof (buf), buf);
1451            if (len == -1)
1452              die ("Read failed");
1453            buf[len] = 0;
1454            printf ("%s\n", buf);
1455          }
1456      }
1457    else if (strcmp (prog, "vbusmonitor1poll") == 0)
1458      {
1459        fd_set read;
1460  
1461        if (ac != 2)
1462          die ("usage: %s url", prog);
1463        con = open_con(ag[1]);
1464  
1465        if (EIBOpenVBusmonitorText (con) == -1)
1466          die ("Open Busmonitor failed");
1467  
1468        while (1)
1469          {
1470  lp1:
1471            FD_ZERO (&read);
1472            FD_SET (EIB_Poll_FD (con), &read);
1473            printf ("Waiting\n");
1474            if (select (EIB_Poll_FD (con) + 1, &read, 0, 0, 0) == -1)
1475              die ("select failed");
1476            printf ("Data available\n");
1477            len = EIB_Poll_Complete (con);
1478            if (len == -1)
1479              die ("Read failed");
1480            if (len == 0)
1481              goto lp1;
1482            printf ("Completed\n");
1483  
1484            len = EIBGetBusmonitorPacket (con, sizeof (buf), buf);
1485            if (len == -1)
1486              die ("Read failed");
1487            printf ("%s\n", buf);
1488          }
1489  
1490      }
1491    else if (strcmp (prog, "vbusmonitor1time") == 0)
1492      {
1493        /* hires-time */
1494        struct timeval tv;
1495        struct tm* ptm;
1496        char time_string[40];
1497        long milliseconds;
1498        /* Obtain the time of day, and convert it to a tm struct. */
1499        gettimeofday (&tv, NULL);
1500        ptm = localtime (&tv.tv_sec);
1501        /* Format the date and time, down to a single second. */
1502        strftime (time_string, sizeof (time_string), "%Y-%m-%d %H:%M:%S", ptm);
1503        /* Compute milliseconds from microseconds. */
1504        milliseconds = tv.tv_usec / 1000;
1505        /* Print the formatted time, in seconds, followed by a decimal point and the milliseconds. */
1506        printf ("%s.%03ld\n", time_string, milliseconds);
1507  
1508        if (ac != 2)
1509          die ("usage: %s url", prog);
1510        con = open_con(ag[1]);
1511  
1512        if (EIBOpenVBusmonitorText (con) == -1)
1513          die ("Open Busmonitor failed");
1514  
1515        while (1)
1516          {
1517            len = EIBGetBusmonitorPacket (con, sizeof (buf), buf);
1518            if (len == -1)
1519              die ("Read failed");
1520            buf[len] = 0;
1521            gettimeofday (&tv, NULL);
1522            ptm = localtime (&tv.tv_sec);
1523            strftime (time_string, sizeof (time_string), "%H:%M:%S", ptm);
1524            milliseconds = tv.tv_usec / 1000;
1525            printf ("%s.%03ld %s\n", time_string, milliseconds, buf);
1526            fflush (stdout);
1527          }
1528  
1529      }
1530    else if (strcmp (prog, "vbusmonitor2") == 0)
1531      {
1532        if (ac != 2)
1533          die ("usage: %s url", prog);
1534        con = open_con(ag[1]);
1535  
1536        if (EIBOpenVBusmonitor (con) == -1)
1537          die ("Open Busmonitor failed");
1538  
1539        while (1)
1540          {
1541            len = EIBGetBusmonitorPacket (con, sizeof (buf), buf);
1542            if (len == -1)
1543              die ("Read failed");
1544            printHex (len, buf);
1545            printf ("\n");
1546          }
1547      }
1548    else if (strcmp (prog, "vbusmonitor3") == 0)
1549      {
1550        uint32_t ts;
1551        uint8_t status;
1552        if (ac != 2)
1553          die ("usage: %s url", prog);
1554        con = open_con(ag[1]);
1555  
1556        if (EIBOpenVBusmonitorTS (con, &ts) == -1)
1557          die ("Open Busmonitor failed");
1558  
1559        printf ("TS-Base: %08x\n", ts);
1560  
1561        while (1)
1562          {
1563            len = EIBGetBusmonitorPacketTS (con, &status, &ts, sizeof (buf), buf);
1564            if (len == -1)
1565              die ("Read failed");
1566            printf ("(%d, %08x) ", status, ts);
1567            printHex (len, buf);
1568            printf ("\n");
1569            fflush (stdout);
1570          }
1571  
1572      }
1573    else if (strcmp (prog, "writeaddress") == 0)
1574      {
1575        if (ac != 3)
1576          die ("usage: %s url eibaddr", prog);
1577        con = open_con(ag[1]);
1578        dest = readaddr (ag[2]);
1579  
1580        len = EIB_M_WriteIndividualAddress (con, dest);
1581        if (len == -1)
1582          die ("Set failed");
1583  
1584      }
1585    else if (strcmp (prog, "xpropread") == 0)
1586      {
1587        int len, obj, prop, start, nr_of_elem;
1588  
1589        if (ac != 7)
1590          die ("usage: %s url eibaddr obj prop start nr_of_elem", prog);
1591        con = open_con(ag[1]);
1592        dest = readaddr (ag[2]);
1593        obj = atoi (ag[3]);
1594        prop = atoi (ag[4]);
1595        start = atoi (ag[5]);
1596        nr_of_elem = atoi (ag[6]);
1597  
1598        if (EIB_MC_Individual_Open (con, dest) == -1)
1599          die ("Connect failed");
1600  
1601        len =
1602          EIB_MC_PropertyRead (con, obj, prop, start, nr_of_elem, sizeof (buf),
1603                               buf);
1604        if (len == -1)
1605          die ("Read failed");
1606        printHex (len, buf);
1607      }
1608    else if (strcmp (prog, "xpropwrite") == 0)
1609      {
1610        int len, obj, prop, start, nr_of_elem;
1611        uint8_t res[255];
1612  
1613        if (ac < 7)
1614          die ("usage: %s url eibaddr obj prop start nr_of_elem [xx xx ..]", prog);
1615        con = open_con(ag[1]);
1616        dest = readaddr (ag[2]);
1617        obj = atoi (ag[3]);
1618        prop = atoi (ag[4]);
1619        start = atoi (ag[5]);
1620        nr_of_elem = atoi (ag[6]);
1621        len = readBlock (buf, sizeof (buf), ac - 7, ag + 7);
1622        if (len < 0)
1623          die ("Invalid hex bytes");
1624  
1625        if (EIB_MC_Individual_Open (con, dest) == -1)
1626          die ("Connect failed");
1627  
1628        printf ("Write: ");
1629        printHex (len, buf);
1630        printf ("\n");
1631        len =
1632          EIB_MC_PropertyWrite (con, obj, prop, start, nr_of_elem, len, buf,
1633                                sizeof (res), res);
1634        if (len == -1)
1635          die ("Write failed");
1636        printHex (len, res);
1637      }
1638    else
1639      {
1640        char *path = malloc (strlen (PKGLIBDIR) + strlen (prog) + 2);
1641        sprintf (path,"%s/%s", PKGLIBDIR, prog);
1642        execv (path, ag);
1643        die ("No such applet: %s", prog);
1644      }
1645  
1646  out:
1647    EIBClose (con);
1648    return 0;
1649  }