[Nut-upsdev] Re: [Nut-upsuser] Ablerex 625L USB version

Peter Selinger selinger at mathstat.dal.ca
Thu Feb 1 20:41:29 CET 2007


Hi Jon,

your patches are malformed because (presumably) your email client
wrapped this lines. Could you please send these as a unified diff
("diff -u"), and send them in attachments, rather than as a
copy-and-paste? 

Thanks, -- Peter

Jon Gough wrote:
> 
> Peter,
>     Here are the files I have worked on. I hope I have diff'd them 
> correctly. I have not touched the megatec_ser.c file so I have not 
> included it. I have now got knutclient talking to the driver and it 
> seems to be displaying what it should. So as a first pass this will 
> work with the Upsonic CS1500 UPS that reports itself as Ablerex.
> 
> Regards
>     Jon
> 
> *** megatec.c.orig      2007-01-29 08:12:19.000000000 +1100
> --- megatec.c   2007-01-31 18:28:33.000000000 +1100
> ***************
> *** 243,251 ****
>          char buffer[RECV_BUFFER_LEN];
>          int ret;
> 
> !       upsdebugx(2, "Sending \"Q1\" command...");
> !       comm->send("Q1%c", ENDCHAR);
>          ret = comm->recv(buffer, RECV_BUFFER_LEN, ENDCHAR, IGNCHARS);
>          if (ret < Q1_CMD_REPLY_LEN) {
>                  upsdebugx(2, "Wrong answer to \"Q1\" command.");
> 
> --- 243,253 ----
>          char buffer[RECV_BUFFER_LEN];
>          int ret;
> 
> !       upsdebugx(2, "check_ups: Sending \"Q1\" command...");
> !       ret = comm->send("Q1%c", ENDCHAR);
> !       upsdebugx(4, "check_ups: getting receive stuff, ignchars: %s, 
> ret: %i", IGNCHARS, ret);
>          ret = comm->recv(buffer, RECV_BUFFER_LEN, ENDCHAR, IGNCHARS);
> +       upsdebugx(4, "got receive stuff: rc = %i, buffer: %s", ret, buffer);
>          if (ret < Q1_CMD_REPLY_LEN) {
>                  upsdebugx(2, "Wrong answer to \"Q1\" command.");
> 
> ***************
> *** 265,270 ****
> --- 267,273 ----
> 
>          upsdebugx(1, "Asking for UPS information (\"I\" command)...");
>          comm->send("I%c", ENDCHAR);
> +       upsdebugx(4, "get_ups_info: getting receive stuff, ignchars: 
> %s", IGNCHARS);
>          ret = comm->recv(buffer, RECV_BUFFER_LEN, ENDCHAR, IGNCHARS);
>          if (ret < I_CMD_REPLY_LEN) {
>                  upsdebugx(1, "UPS doesn't return any information 
> about itself.");
> ***************
> *** 295,300 ****
> --- 298,304 ----
> 
>          upsdebugx(1, "Asking for UPS power ratings (\"F\" command)...");
>          comm->send("F%c", ENDCHAR);
> +       upsdebugx(4, "get_firmware_values: getting receive stuff, 
> ignchars: %s", IGNCHARS);
>          ret = comm->recv(buffer, RECV_BUFFER_LEN, ENDCHAR, IGNCHARS);
>          if (ret < F_CMD_REPLY_LEN) {
>                  upsdebugx(1, "UPS doesn't return any information 
> about its power ratings.");
> ***************
> *** 318,323 ****
> --- 322,328 ----
> 
>          upsdebugx(1, "Asking for UPS status (\"Q1\" command)...");
>          comm->send("Q1%c", ENDCHAR);
> +       upsdebugx(4, "run_query: getting receive stuff, ignchars: 
> %s", IGNCHARS);
>          ret = comm->recv(buffer, RECV_BUFFER_LEN, ENDCHAR, IGNCHARS);
>          if (ret < Q1_CMD_REPLY_LEN) {
>                  upsdebugx(1, "UPS doesn't return any information 
> about its status.");
> ***************
> *** 564,571 ****
>    {
>          upslogx(LOG_INFO, "Shutting down UPS immediately.");
> 
> !       ser_send_pace(upsfd, SEND_PACE, "C%c", ENDCHAR);
> !       ser_send_pace(upsfd, SEND_PACE, "S%02dR%04d%c", 
> shutdown_delay, start_delay, ENDCHAR);
>    }
> 
> 
> --- 569,576 ----
>    {
>          upslogx(LOG_INFO, "Shutting down UPS immediately.");
> 
> !       comm->send("C%c", ENDCHAR);
> !       comm->send("S%02dR%04d%c%c", shutdown_delay, start_delay, ENDCHAR);
>    }
> 
> 
> ***************
> *** 581,589 ****
>          */
> 
>          if (strcasecmp(cmdname, "test.battery.start.deep") == 0) {
> !               ser_send_pace(upsfd, SEND_PACE, "TL%c", ENDCHAR);
> 
> !               if (ser_get_line(upsfd, buffer, RECV_BUFFER_LEN, 
> ENDCHAR, IGNCHARS, READ_TIMEOUT, 0) > 0) {
>                          upslogx(LOG_NOTICE, "test.battery.start.deep 
> not supported by UPS.");
>                  } else {
>                          upslogx(LOG_INFO, "Deep battery test started.");
> --- 586,595 ----
>          */
> 
>          if (strcasecmp(cmdname, "test.battery.start.deep") == 0) {
> !               comm->send("TL%c", ENDCHAR);
> 
> !       upsdebugx(4, "instcmd1: getting receive stuff, ignchars: %s", 
> IGNCHARS);
> !               if (comm->recv(buffer, RECV_BUFFER_LEN, ENDCHAR, 
> IGNCHARS) > 0) {
>                          upslogx(LOG_NOTICE, "test.battery.start.deep 
> not supported by UPS.");
>                  } else {
>                          upslogx(LOG_INFO, "Deep battery test started.");
> ***************
> *** 593,601 ****
>          }
> 
>          if (strcasecmp(cmdname, "test.battery.start") == 0) {
> !               ser_send_pace(upsfd, SEND_PACE, "T%c", ENDCHAR);
> 
> !               if (ser_get_line(upsfd, buffer, RECV_BUFFER_LEN, 
> ENDCHAR, IGNCHARS, READ_TIMEOUT, 0) > 0) {
>                          upslogx(LOG_NOTICE, "test.battery.start not 
> supported by UPS.");
>                  } else {
>                          upslogx(LOG_INFO, "Battery test started.");
> --- 599,608 ----
>          }
> 
>          if (strcasecmp(cmdname, "test.battery.start") == 0) {
> !               comm->send("T%c", ENDCHAR);
> 
> !       upsdebugx(4, "instcmd2: getting receive stuff, ignchars: %s", 
> IGNCHARS);
> !               if (comm->recv(buffer, RECV_BUFFER_LEN, ENDCHAR, 
> IGNCHARS) > 0) {
>                          upslogx(LOG_NOTICE, "test.battery.start not 
> supported by UPS.");
>                  } else {
>                          upslogx(LOG_INFO, "Battery test started.");
> ***************
> *** 605,613 ****
>          }
> 
>          if (strcasecmp(cmdname, "test.battery.stop") == 0) {
> !               ser_send_pace(upsfd, SEND_PACE, "CT%c", ENDCHAR);
> 
> !               if (ser_get_line(upsfd, buffer, RECV_BUFFER_LEN, 
> ENDCHAR, IGNCHARS, READ_TIMEOUT, 0) > 0) {
>                          upslogx(LOG_NOTICE, "test.battery.stop not 
> supported by UPS.");
>                  } else {
>                          upslogx(LOG_INFO, "Battery test stopped.");
> --- 612,621 ----
>          }
> 
>          if (strcasecmp(cmdname, "test.battery.stop") == 0) {
> !               comm->send("CT%c", ENDCHAR);
> 
> !       upsdebugx(4, "instcmd3: getting receive stuff, ignchars: %s", 
> IGNCHARS);
> !               if (comm->recv(buffer, RECV_BUFFER_LEN, ENDCHAR, 
> IGNCHARS) > 0) {
>                          upslogx(LOG_NOTICE, "test.battery.stop not 
> supported by UPS.");
>                  } else {
>                          upslogx(LOG_INFO, "Battery test stopped.");
> ***************
> *** 617,626 ****
>          }
> 
>          if (strcasecmp(cmdname, "shutdown.return") == 0) {
> !               ser_send_pace(upsfd, SEND_PACE, "C%c", ENDCHAR);
>                  watchdog_enabled = 0;
> 
> !               ser_send_pace(upsfd, SEND_PACE, "S%02dR%04d%c", 
> shutdown_delay, start_delay, ENDCHAR);
> 
>                  upslogx(LOG_INFO, "Shutdown (return) initiated.");
> 
> --- 625,634 ----
>          }
> 
>          if (strcasecmp(cmdname, "shutdown.return") == 0) {
> !               comm->send("C%c", ENDCHAR);
>                  watchdog_enabled = 0;
> 
> !               comm->send("S%02dR%04d%c", shutdown_delay, 
> start_delay, ENDCHAR);
> 
>                  upslogx(LOG_INFO, "Shutdown (return) initiated.");
> 
> ***************
> *** 628,637 ****
>          }
> 
>          if (strcasecmp(cmdname, "shutdown.stayoff") == 0) {
> !               ser_send_pace(upsfd, SEND_PACE, "C%c", ENDCHAR);
>                  watchdog_enabled = 0;
> 
> !               ser_send_pace(upsfd, SEND_PACE, "S%02dR0000%c", 
> shutdown_delay, ENDCHAR);
> 
>                  upslogx(LOG_INFO, "Shutdown (stayoff) initiated.");
> 
> --- 636,645 ----
>          }
> 
>          if (strcasecmp(cmdname, "shutdown.stayoff") == 0) {
> !               comm->send("C%c", ENDCHAR);
>                  watchdog_enabled = 0;
> 
> !               comm->send("S%02dR0000%c%c", shutdown_delay, ENDCHAR);
> 
>                  upslogx(LOG_INFO, "Shutdown (stayoff) initiated.");
> 
> ***************
> *** 639,645 ****
>          }
> 
>          if (strcasecmp(cmdname, "shutdown.stop") == 0) {
> !               ser_send_pace(upsfd, SEND_PACE, "C%c", ENDCHAR);
>                  watchdog_enabled = 0;
> 
>                  upslogx(LOG_INFO, "Shutdown canceled.");
> --- 647,653 ----
>          }
> 
>          if (strcasecmp(cmdname, "shutdown.stop") == 0) {
> !               comm->send("C%c", ENDCHAR);
>                  watchdog_enabled = 0;
> 
>                  upslogx(LOG_INFO, "Shutdown canceled.");
> ***************
> *** 648,654 ****
>          }
> 
>          if (strcasecmp(cmdname, "load.on") == 0) {
> !               ser_send_pace(upsfd, SEND_PACE, "C%c", ENDCHAR);
>                  watchdog_enabled = 0;
> 
>                  upslogx(LOG_INFO, "Turning load on.");
> --- 656,662 ----
>          }
> 
>          if (strcasecmp(cmdname, "load.on") == 0) {
> !               comm->send("C%c", ENDCHAR);
>                  watchdog_enabled = 0;
> 
>                  upslogx(LOG_INFO, "Turning load on.");
> ***************
> *** 657,666 ****
>          }
> 
>          if (strcasecmp(cmdname, "load.off") == 0) {
> !               ser_send_pace(upsfd, SEND_PACE, "C%c", ENDCHAR);
>                  watchdog_enabled = 0;
> 
> !               ser_send_pace(upsfd, SEND_PACE, "S00R0000%c", ENDCHAR);
> 
>                  upslogx(LOG_INFO, "Turning load off.");
> 
> --- 665,674 ----
>          }
> 
>          if (strcasecmp(cmdname, "load.off") == 0) {
> !               comm->send("C%c", ENDCHAR);
>                  watchdog_enabled = 0;
> 
> !               comm->send("S00R0000%c%c", ENDCHAR);
> 
>                  upslogx(LOG_INFO, "Turning load off.");
> 
> ***************
> *** 680,687 ****
>          }
> 
>          if (strcasecmp(cmdname, "reset.watchdog") == 0) {
> !               ser_send_pace(upsfd, SEND_PACE, "C%c", ENDCHAR);
> !               ser_send_pace(upsfd, SEND_PACE, "S%02dR0001%c", 
> watchdog_timeout, ENDCHAR);
> 
>                  if (watchdog_enabled) {
>                          upsdebugx(2, "Resetting the UPS watchdog.");
> --- 688,695 ----
>          }
> 
>          if (strcasecmp(cmdname, "reset.watchdog") == 0) {
> !               comm->send("C%c", ENDCHAR);
> !               comm->send("S%02dR0001%c", watchdog_timeout, ENDCHAR);
> 
>                  if (watchdog_enabled) {
>                          upsdebugx(2, "Resetting the UPS watchdog.");
> ***************
> *** 694,700 ****
>          }
> 
>          if (strcasecmp(cmdname, "beeper.toggle") == 0) {
> !               ser_send_pace(upsfd, SEND_PACE, "Q%c", ENDCHAR);
> 
>                  upslogx(LOG_INFO, "Toggling UPS beeper.");
> 
> --- 702,708 ----
>          }
> 
>          if (strcasecmp(cmdname, "beeper.toggle") == 0) {
> !               comm->send("Q%c", ENDCHAR);
> 
>                  upslogx(LOG_INFO, "Toggling UPS beeper.");
> 
> ***************
> *** 758,778 ****
> 
>    void upsdrv_banner(void)
>    {
> !       printf("Network UPS Tools %s - Megatec protocol driver %s 
> [%s]\n", UPS_VERSION, DRV_VERSION, progname);
>          printf("Carlos Rodrigues (c) 2003-2007\n\n");
>    }
> 
> 
>    void upsdrv_initups(void)
>    {
> !       upsfd = ser_open(device_path);
> !       ser_set_speed(upsfd, device_path, B2400);
>    }
> 
> 
>    void upsdrv_cleanup(void)
>    {
> !       ser_close(upsfd, device_path);
>    }
> 
> 
> --- 766,785 ----
> 
>    void upsdrv_banner(void)
>    {
> !       printf("Network UPS Tools - Megatec protocol driver %s[%s] 
> (%s)\n", DRV_VERSION, comm->name, UPS_VERSION);
>          printf("Carlos Rodrigues (c) 2003-2007\n\n");
>    }
> 
> 
>    void upsdrv_initups(void)
>    {
> !       comm->open(device_path);
>    }
> 
> 
>    void upsdrv_cleanup(void)
>    {
> !       comm->close(device_path);
>    }
> 
> *** megatec.h.orig      2007-01-29 08:12:19.000000000 +1100
> --- megatec.h   2007-01-29 12:55:31.000000000 +1100
> ***************
> *** 1,5 ****
>    /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: t; -*-
> !  *
>     * megatec.h: support for Megatec protocol based UPSes
>     *
>     * Copyright (C) Carlos Rodrigues <carlos.efr at mail.telepac.pt>
> --- 1,5 ----
>    /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: t; -*-
> !  *
>     * megatec.h: support for Megatec protocol based UPSes
>     *
>     * Copyright (C) Carlos Rodrigues <carlos.efr at mail.telepac.pt>
> ***************
> *** 22,24 ****
> --- 22,36 ----
>     */
> 
>    #define DRV_VERSION "1.5"
> +
> + /* comm driver */
> + typedef struct {
> +     const char  *name;
> +     int         (*open)(const char*param);
> +     void        (*close)();
> +     int         (*send)(const char *fmt,...);
> +     int         (*recv)(char *buffer,size_t buffer_len,char 
> endchar,const char *ignchars);
> + }     megatec_comm_t;
> +
> + extern megatec_comm_t* comm;
> +
> 
> *** megatec_usb.c.orig  2007-02-01 19:01:06.000000000 +1100
> --- megatec_usb.c       2007-02-01 15:06:56.000000000 +1100
> ***************
> *** 0 ****
> --- 1,422 ----
> + /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: t; -*-
> +  *
> +  * megatec_usb.c: usb communication layer for Megatec protocol based UPSes
> +  *
> +  * Copyright (C) Andrey Lelikov <nut-driver at lelik.org>
> +  *
> +  * megatec_usb.c created on 3-Oct-2006
> +  *
> +  * This program is free software; you can redistribute it and/or modify
> +  * it under the terms of the GNU General Public License as published by
> +  * the Free Software Foundation; either version 2 of the License, or
> +  * (at your option) any later version.
> +  *
> +  * This program is distributed in the hope that it will be useful,
> +  * but WITHOUT ANY WARRANTY; without even the implied warranty of
> +  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +  * GNU General Public License for more details.
> +  *
> +  * You should have received a copy of the GNU General Public License
> +  * along with this program; if not, write to the Free Software
> +  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
> +  */
> +
> + #include "main.h"
> + #include "megatec.h"
> + #include "libusb.h"
> +
> + #include <stdio.h>
> + #include <limits.h>
> + #include <string.h>
> +
> + /*
> +     This is a communication driver for "USB HID" UPS-es which use proprietary
> + usb-to-serial converter and speak megatec protocol. Usually these are cheap
> + models and usb-to-serial converter is a huge oem hack - HID tables are bogus,
> + device has no UPS reports, etc.
> +     This driver has a table of all known devices which has pointers 
> to device-
> + specific communication functions (namely send a string to UPS and 
> read a string
> + from it). Driver takes care of detection, opening a usb device, string
> + formatting etc. So in order to add support for another 
> usb-to-serial device one
> + only needs to implement device-specific get/set functions and add 
> an entry into
> + KnownDevices table.
> +
> + */
> +
> + static communication_subdriver_t    *usb = &usb_subdriver;
> + static usb_dev_handle               *udev=NULL;
> + static HIDDevice                    hiddevice;
> +
> + static int comm_usb_recv(char *buffer,size_t buffer_len,char 
> endchar,const char *ignchars);
> +
> + typedef struct
> + {
> +     uint16_t        vid;
> +     uint16_t        pid;
> +     int (*get_data)(char *buffer,int buffer_size);
> +     int (*set_data)(const char *str);
> + } usb_ups_t;
> +
> + usb_ups_t   *usb_ups_device = NULL;
> +
> + /*
> +     All devices known to this driver go here
> +     along with their set/get routines
> + */
> +
> + static int get_data_agiler(char *buffer,int buffer_size);
> + static int set_data_agiler(const char *str);
> + static int get_data_ablerex(char *buffer,int buffer_size);
> + static int set_data_ablerex(const char *str);
> +
> + static usb_ups_t KnownDevices[]={
> +     { 0x05b8, 0x0000, get_data_agiler, set_data_agiler },
> +     { 0xffff, 0x0000, get_data_ablerex, set_data_ablerex },
> +     { .vid=0 }     /* end of list */
> + };
> +
> + static int comm_usb_match(HIDDevice *d, void *privdata)
> + {
> +     usb_ups_t   *p;
> + upsdebugx(4, "comm_usb_match");
> +     for (p=KnownDevices;p->vid!=0;p++)
> +     {
> +         if ( (p->vid==d->VendorID) && (p->pid==d->ProductID) )
> +         {
> +             usb_ups_device = p;
> +             return 1;
> +         }
> +     }
> +
> +     p = (usb_ups_t*)privdata;
> +
> +     if (NULL!=p)
> +     {
> +         if ( (p->vid==d->VendorID) && (p->pid==d->ProductID) )
> +         {
> +             usb_ups_device = p;
> +             return 1;
> +         }
> +     }
> +
> +     return 0;
> + }
> +
> + static int comm_usb_open(const char *param)
> + {
> +     HIDDeviceMatcher_t  match;
> +     static usb_ups_t    param_arg;
> +     const char*         p;
> +     int                 ret,i;
> +     union  _u {
> +         unsigned char   report_desc[4096];
> +         char            flush_buf[256];
> +     } u;
> + upsdebugx(4, "comm_usb_open");
> +     memset(&match,0,sizeof(match));
> +     match.match_function = &comm_usb_match;
> +
> +     if (0!=strcmp(param,"auto"))
> +     {
> +         param_arg.vid = (uint16_t) strtoul(param,NULL,16);
> +         p = strchr(param,':');
> +         if (NULL!=p)
> +         {
> +             param_arg.pid = (uint16_t) strtoul(p+1,NULL,16);
> +         } else {
> +             param_arg.vid = 0;
> +         }
> +
> +         // pure heuristics - assume this unknown device speaks 
> agiler protocol
> +         param_arg.get_data = usb_ups_device->get_data;
> +         param_arg.set_data = usb_ups_device->set_data;
> +
> +         if (0!=param_arg.vid)
> +         {
> +             match.privdata = &param_arg;
> +         } else {
> +             upslogx(LOG_ERR,
> +                 "comm_usb_open: invalid usb device specified, must 
> be \"auto\" or \"vid:pid\"");
> +             return -1;
> +         }
> +     }
> +
> +     ret = usb->open(&udev,&hiddevice,&match,u.report_desc,MODE_OPEN);
> +     if (ret<0)
> +         return ret;
> +
> +     // flush input buffers
> +     for (i=0;i<10;i++)
> +     {
> +        upsdebugx(4, "comm_usb_open: Flush buffers");
> +         if (comm_usb_recv(u.flush_buf,sizeof(u.flush_buf),0,NULL)<1) break;
> +     }
> +     return 0;
> + }
> +
> + static void comm_usb_close(const char *param)
> + {
> + upsdebugx(4, "comm_usb_close");
> +     usb->close(udev);
> + }
> +
> + static int comm_usb_send(const char *fmt,...)
> + {
> +     char    buf[128];
> +     size_t  len;
> +     va_list   ap;
> + upsdebugx(4, "comm_usb_send: Starting");
> +     if (NULL==udev)
> +         return -1;
> +     va_start(ap, fmt);
> +     len = vsnprintf(buf, sizeof(buf), fmt, ap);
> +     va_end(ap);
> +     if ((len < 1) || (len >= (int) sizeof(buf)))
> +     {
> +        upsdebugx(4, "in if test");
> +         upslogx(LOG_WARNING, "comm_usb_send: vsnprintf needed more "
> +             "than %d bytes", (int)sizeof(buf));
> +         buf[sizeof(buf)-1]=0;
> +     }
> + upsdebugx(4, "comm_usb_send: About to return");
> +     return usb_ups_device->set_data(buf);
> + }
> +
> + static int comm_usb_recv(char *buffer,size_t buffer_len,char 
> endchar,const char *ignchars)
> + {
> +     int len;
> +     char *src,*dst,c;
> +
> + upsdebugx(4, "comm_usb_recv: Starting");
> +     if (NULL==udev)
> +         return -1;
> +
> +     len = usb_ups_device->get_data(buffer,buffer_len);
> + upsdebugx(4, "comm_usb_recv: len: %i", len);
> +     if (len<0)
> +         return len;
> +
> +     dst = buffer;
> +
> +     for (src=buffer;src!=(buffer+len);src++)
> +     {
> +         c = *src;
> +         if ( (c==endchar) || (c==0) ) {
> +             break;
> +         }
> +         if (ignchars == NULL) break;
> +         if (NULL!=strchr(ignchars,c)) continue;
> +         *(dst++) = c;
> +     }
> +
> +     // terminate string if we have space
> +     if (dst!=(buffer+len))
> +     {
> +         *dst = 0;
> +     }
> +
> +     return (dst-buffer);
> + }
> +
> + static megatec_comm_t comm_usb =
> + {
> +     .name = "usb",
> +     .open = &comm_usb_open,
> +     .close = &comm_usb_close,
> +     .send = &comm_usb_send,
> +     .recv = &comm_usb_recv
> + };
> +
> + megatec_comm_t *comm = & comm_usb;
> +
> +
> + /************** minidrivers go after this point **************************/
> +
> +
> + /*
> +     Agiler seraial-to-usb device.
> +
> +     Protocol was reverse-engineered from Windows driver
> +     HID tables are complitely bogus
> +     Data is transferred out as one 8-byte packet with report ID 0
> +     Data comes in as 6 8-byte reports per line , padded with zeroes
> +     All constants are hardcoded in windows driver
> + */
> +
> + #define AGILER_REPORT_SIZE      8
> + #define AGILER_REPORT_COUNT     6
> + #define AGILER_TIMEOUT          5000
> +
> + static int set_data_agiler(const char *str)
> + {
> +     unsigned char report_buf[AGILER_REPORT_SIZE];
> +
> +     if (strlen(str)>AGILER_REPORT_SIZE)
> +     {
> +         upslogx(LOG_ERR,
> +             "set_data_agiler: output string too large");
> +         return -1;
> +     }
> +
> +     memset(report_buf,0,sizeof(report_buf));
> +     memcpy(report_buf,str,strlen(str));
> +
> +     return usb->set_report(udev,0,report_buf,sizeof(report_buf));
> + }
> +
> + static int get_data_agiler(char *buffer,int buffer_size)
> + {
> +     int i,len;
> +     char    buf[AGILER_REPORT_SIZE*AGILER_REPORT_COUNT+1];
> +
> +     memset(buf,0,sizeof(buf));
> +
> +     for (i=0;i<AGILER_REPORT_COUNT;i++)
> +     {
> +         len = usb->get_interrupt(udev,(unsigned char 
> *)buf+i*AGILER_REPORT_SIZE,AGILER_REPORT_SIZE,AGILER_TIMEOUT);
> +         if (len!=AGILER_REPORT_SIZE) {
> +             if (len<0) len=0;
> +             buf[i*AGILER_REPORT_SIZE+len]=0;
> +             break;
> +         }
> +     }
> +
> +     len = strlen(buf);
> +
> +     if (len > buffer_size)
> +     {
> +         upslogx(LOG_ERR,
> +             "get_data_agiler: input buffer too small");
> +         len = buffer_size;
> +     }
> +
> +     memcpy(buffer,buf,len);
> +     return len;
> + }
> +
> + /*
> +     Ablerex seraial-to-usb device.
> +
> +     Protocol was reverse-engineered from Windows driver
> +     HID tables are complitely bogus
> +     Data is transferred out as one 8-byte packet with report ID 0
> +     Data comes in as 1 47-byte report per line , padded with zeroes
> +     All constants are hardcoded in windows driver
> + */
> +
> + #define ABLEREX_REPORT_SIZE      47
> + #define ABLEREX_REPORT_COUNT     1
> + #define ABLEREX_TIMEOUT          5000
> + #define ABLEREX_RESPONSE_SIZE     11
> +
> + static char ablerex_response[ABLEREX_REPORT_SIZE];
> + static bool get_done;
> +
> + static int set_data_ablerex(const char *str)
> + {
> +     char report_buf[ABLEREX_REPORT_SIZE];
> +     int rc;
> + upsdebugx(4, "set_data_ablerex: Starting");
> +     if (strlen(str)>ABLEREX_REPORT_SIZE)
> +     {
> +         upslogx(LOG_ERR,
> +             "set_data_ablerex: output string too large");
> +         return -1;
> +     }
> +
> +     memset(report_buf,0,sizeof(report_buf));
> +     memcpy(report_buf,str,strlen(str));
> +
> +    if (strcmp(str, "Q1\r") == 0)
> +    {
> +       upsdebugx(4, "set_data_ablerex: Doing Q1 stuff");
> +       rc = usb_get_string_simple(udev, 3, report_buf, sizeof(report_buf));
> +       get_done = TRUE;
> +    }
> +    else if (strcmp(str, "Q\r") == 0)
> +    {
> +       upsdebugx(4, "set_data_ablerex: Doing Q stuff");
> +       rc = usb_get_string_simple(udev, 7, report_buf, sizeof(report_buf));
> +       get_done = TRUE;
> +    }
> +    else if (strcmp(str, "C\r") == 0)
> +    {
> +       upsdebugx(4, "set_data_ablerex: Doing C stuff");
> +       rc = usb_get_string_simple(udev, 11, report_buf, sizeof(report_buf));
> +       get_done = TRUE;
> +    }
> +    else if (strcmp(str, "T\r") == 0)
> +    {
> +       upsdebugx(4, "set_data_ablerex: Doing T stuff");
> +       rc = usb_get_string_simple(udev, 4, report_buf, sizeof(report_buf));
> +       get_done = TRUE;
> +    }
> +    else if (strcmp(str, "I\r") == 0)
> +    {
> +       char rep1[sizeof(report_buf)], rep2[sizeof(report_buf)];
> +       int rc1, rc2;
> +       upsdebugx(4, "set_data_ablerex: Doing I stuff");
> +       rc1 = usb_get_string_simple(udev, 1, rep1, sizeof(report_buf));
> +       rc2 = usb_get_string_simple(udev, 2, rep2, sizeof(report_buf));
> +       rc = rc1 + rc2;
> +       strcpy(report_buf, rep1);
> +       strcat(report_buf, rep2);
> +       get_done = TRUE;
> +    }
> +    else if (strcmp(str, "F\r") == 0)
> +    {
> +       upsdebugx(4, "set_data_ablerex: Doing F stuff");
> +       rc = usb_get_string_simple(udev, 13, report_buf, sizeof(report_buf));
> +       get_done = TRUE;
> +    }
> +
> +    else
> +    {
> +       upsdebugx(4, "set_data_ablerex: doing set-report stuff");
> +       rc = usb->set_report(udev,0, (unsigned char *)report_buf, 
> strlen(report_buf));
> +       get_done = FALSE;
> +    }
> +    strcpy(ablerex_response, report_buf);
> +     upsdebugx(4, "set_data_ablerex: rc: %i, report_buf: %s", rc, report_buf);
> +     return rc;
> + }
> +
> + static int get_data_ablerex(char *buffer,int buffer_size)
> + {
> +    int  i,len, rc;
> +    char buf[ABLEREX_REPORT_SIZE*ABLEREX_REPORT_COUNT+1];
> +
> +    upsdebugx(4, "get_data_ablerex: Starting");
> +    // code to handle having issued and received response in set_data_ablerex
> +    memset(buffer,0, buffer_size);
> +    if (get_done == TRUE)
> +    {
> +       memcpy(buffer, ablerex_response, strlen(ablerex_response));
> +       return strlen(ablerex_response);
> +    }
> +
> +     for (i=0;i<ABLEREX_REPORT_COUNT;i++)
> +     {
> +         len = usb->get_interrupt(udev, (unsigned char *) 
> buf+i*ABLEREX_REPORT_SIZE,ABLEREX_REPORT_SIZE,ABLEREX_TIMEOUT);
> +         upsdebugx(4, "get_data_ablerex: len: %i, error: %i, %s: 
> buf: %s", len, errno, strerror(errno), buf);
> +         if (len!=ABLEREX_REPORT_SIZE) {
> +             if (len<0) len=0;
> +             buf[i*ABLEREX_REPORT_SIZE+len]=0;
> +             break;
> +         }
> +     }
> +     len = strlen(buf);
> +
> +     if (len > buffer_size)
> +     {
> +         upslogx(LOG_ERR,
> +             "get_data_ablerex: input buffer too small");
> +         len = buffer_size;
> +     }
> +
> + upsdebugx(4, "get_data_ablerex: Leaving get_data_ablerex: len: %i", len);
> +     memcpy(buffer,buf,len);
> +     return len;
> + }
> +
> + /* EOF - megatec_usb.c */



More information about the Nut-upsdev mailing list