~ubuntu-branches/ubuntu/saucy/nut/saucy

« back to all changes in this revision

Viewing changes to drivers/mge-shut.h

  • Committer: Bazaar Package Importer
  • Author(s): Arnaud Quette
  • Date: 2004-05-28 13:10:01 UTC
  • mto: (16.1.1 squeeze)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20040528131001-yj2m9qcez4ya2w14
Tags: upstream-1.4.2
ImportĀ upstreamĀ versionĀ 1.4.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*  mge-shut.h - monitor MGE UPS for NUT with SHUT protocol
 
2
 * 
 
3
 *  Copyright (C) 2002-2004
 
4
 *     Arnaud Quette <arnaud.quette@free.fr> & <arnaud.quette@mgeups.com>
 
5
 *     Philippe Marzouk <philm@users.sourceforge.net>
 
6
 *     Russell Kroll <rkroll@exploits.org>
 
7
 *  
 
8
 *  Sponsored by MGE UPS SYSTEMS <http://opensource.mgeups.com/>
 
9
 *
 
10
 *  This program is free software; you can redistribute it and/or modify
 
11
 *  it under the terms of the GNU General Public License as published by
 
12
 *  the Free Software Foundation; either version 2 of the License, or
 
13
 *  (at your option) any later version.
 
14
 *
 
15
 *  This program is distributed in the hope that it will be useful,
 
16
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
18
 *  GNU General Public License for more details.
 
19
 *
 
20
 *  You should have received a copy of the GNU General Public License
 
21
 *  along with this program; if not, write to the Free Software
 
22
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
23
 *
 
24
 */
 
25
 
 
26
#include "hidparser.h"
 
27
#include "hidtypes.h"
 
28
 
 
29
#define DRIVER_VERSION "0.59"
 
30
 
 
31
#define DEFAULT_TIMEOUT         3000
 
32
#define MAX_STRING              64
 
33
 
 
34
#define DEFAULT_LOWBATT         30      /* low battery level, in %          */
 
35
#define DEFAULT_ONDELAY         3       /* delay between return of utility power
 
36
                                           and powering up of load, 10 seconds units */
 
37
#define DEFAULT_OFFDELAY        20      /* delay befor power off, in SECONDS*/ 
 
38
#define OFF_NOTIFICATION        1       /* notification off */
 
39
 
 
40
#define LIGHT_NOTIFICATION      2       /* light notification */
 
41
#define COMPLETE_NOTIFICATION   3       /* complete notification for UPSs which do
 
42
                                         * not support disabling it like some early
 
43
                                         * Ellipse models */
 
44
#define DEFAULT_NOTIFICATION COMPLETE_NOTIFICATION
 
45
 
 
46
/* HID definitions */
 
47
 
 
48
#define HID_REPORT_TYPE_INPUT   0x01
 
49
#define HID_REPORT_TYPE_OUTPUT  0x02
 
50
#define HID_REPORT_TYPE_FEATURE 0x03
 
51
 
 
52
#define REQUEST_TYPE_USB        0x80
 
53
#define REQUEST_TYPE_HID        0x81
 
54
#define REQUEST_TYPE_GET_REPORT 0xa1
 
55
#define REQUEST_TYPE_SET_REPORT 0x21
 
56
 
 
57
#define DEVICE_DESCRIPTOR       0x0001
 
58
#define CONFIG_DESCRIPTOR       0x0002
 
59
#define STRING_DESCRIPTOR       0x0003
 
60
#define INTERFACE_DESCRIPTOR    0x0004
 
61
#define ENDPOINT_DESCRIPTOR     0x0005
 
62
#define HID_DESCRIPTOR          0x0021
 
63
#define REPORT_DESCRIPTOR       0x0022
 
64
 
 
65
#define MAX_REPORT_SIZE         0x1800
 
66
 
 
67
/* SHUT definitions - From Simplified SHUT spec */
 
68
 
 
69
#define SHUT_TYPE_REQUEST       0x01
 
70
#define SHUT_TYPE_RESPONSE      0x04
 
71
#define SHUT_TYPE_NOTIFY        0x05
 
72
#define SHUT_OK                 0x06
 
73
#define SHUT_NOK                0x15
 
74
#define SHUT_SYNC               0x16 /* complete notifications - not yet managed
 
75
                                      but needed for some early Ellipse models */
 
76
#define SHUT_SYNC_LIGHT         0x17 /* partial notifications */
 
77
#define SHUT_SYNC_OFF           0x18 /* disable notifications - only do polling */
 
78
#define SHUT_PKT_LAST           0x80
 
79
 
 
80
/* From SHUT specifications */
 
81
 
 
82
typedef struct hid_packet {
 
83
  unsigned char  bmRequestType;
 
84
  unsigned char  bRequest;
 
85
  unsigned short wValue;
 
86
  unsigned short wIndex;
 
87
  unsigned short wLength;
 
88
/*   unsigned char  padding[8]; for use with shut_set_report */
 
89
} hid_packet_t;
 
90
 
 
91
typedef union hid_data {
 
92
  hid_packet_t  hid_pkt;
 
93
  unsigned char raw_pkt[8]; /* max report lengh, was 8 */
 
94
} hid_data_u;
 
95
 
 
96
typedef struct shut_packet {
 
97
  unsigned char bType;
 
98
  unsigned char bLength;
 
99
  hid_data_u    data;
 
100
  unsigned char bChecksum;
 
101
} shut_packet_t;
 
102
 
 
103
typedef union shut_data {
 
104
  shut_packet_t shut_pkt;
 
105
  unsigned char raw_pkt[11];
 
106
} shut_data_u;
 
107
 
 
108
/* From USB/HID specifications */
 
109
 
 
110
typedef struct hid_descriptor {
 
111
  unsigned char  bLength;
 
112
  unsigned char  bDescriptorType;
 
113
  unsigned short bcdHID;
 
114
  unsigned char  bCountryCode;
 
115
  unsigned char  bNumDescriptors;
 
116
  unsigned char  bReportDescriptorType;
 
117
  unsigned short wDescriptorLength;
 
118
} hid_descriptor_t;
 
119
 
 
120
typedef union hid_desc_data {
 
121
  hid_descriptor_t hid_desc;
 
122
  unsigned char    raw_desc[9]; /* max report lengh, aws 9 */
 
123
} hid_desc_data_u;
 
124
 
 
125
typedef struct device_descriptor {
 
126
  unsigned char  bLength;
 
127
  unsigned char  bDescriptorType;
 
128
  unsigned short bcdUSB;
 
129
  unsigned char  bDeviceClass;
 
130
  unsigned char  bDeviceSubClass;
 
131
  unsigned char  bDeviceProtocol;
 
132
  unsigned char  bMaxPacketSize0;
 
133
  unsigned short idVendor;
 
134
  unsigned short idProduct;
 
135
  unsigned short bcdDevice;
 
136
  unsigned char  iManufacturer;
 
137
  unsigned char  iProduct;
 
138
  unsigned char  iSerialNumber;
 
139
  unsigned char  bNumConfigurations;
 
140
} device_descriptor_t;
 
141
 
 
142
typedef union device_desc_data {
 
143
  device_descriptor_t dev_desc;
 
144
  unsigned char       raw_desc[18];
 
145
} device_desc_data_u;
 
146
 
 
147
/* --------------------------------------------------------------- */
 
148
/*                       Explicit Booleans                         */
 
149
/* --------------------------------------------------------------- */
 
150
 
 
151
#define SHUT_FLAG_OK     (1 << 0)       /* show element to upsd. */
 
152
#define SHUT_FLAG_STATIC (1 << 1)       /* retrieve info only once. */
 
153
#define SHUT_FLAG_ABSENT (1 << 2)       /* data is absent in the device,
 
154
                                           use default value. */
 
155
#define SHUT_FLAG_STALE  (1 << 3)       /* data stale, don't try too often. */
 
156
#define SHUT_FLAG_DELAY  (1 << 4)       /* delay type value: formated differently. */
 
157
 
 
158
/* --------------------------------------------------------------- */
 
159
/*      Query Commands and their Mapping to INFO_ Variables        */
 
160
/* --------------------------------------------------------------- */
 
161
 
 
162
/* Structure defining how to query UPS for a variable and write
 
163
   information to INFO structure.
 
164
*/
 
165
typedef struct {
 
166
  char  *type;                  /* INFO_* element                        */
 
167
  int   flags;                  /* INFO-element flags to set in addinfo  */
 
168
  int   length;                 /* INFO-element length of strings        */  
 
169
  char  item_path[MAX_STRING];  /* HID object (fully qualified string path) */
 
170
  char  fmt[6];                 /* printf format string for INFO entry   */
 
171
  char  *dfl;                   /* default value */
 
172
  unsigned long shut_flags;     /* specific SHUT flags */
 
173
} mge_info_item;
 
174
 
 
175
/* Array containing information to translate between UTalk and NUT info
 
176
 * NOTE: 
 
177
 *      - Array is terminated by element with type NULL.
 
178
 *      - Essential INFO items (ups.{mfr, model, firmware, status}) are
 
179
 *              handled separately.
 
180
 *      - Array is NOT const, since "shut_flags" can be changed.
 
181
 */
 
182
 
 
183
static mge_info_item mge_info[] = {
 
184
        { "driver.version.internal", FLAG_STRING, 5, "", "%s", DRIVER_VERSION, SHUT_FLAG_ABSENT | SHUT_FLAG_OK },
 
185
        /* Battery page */
 
186
        { "battery.charge", 0, 0, "UPS.PowerSummary.RemainingCapacity", "%i", NULL, SHUT_FLAG_OK },
 
187
        { "battery.charge.low", FLAG_RW |ST_FLAG_STRING, 5, "UPS.PowerSummary.RemainingCapacityLimitSetting", "%ld", NULL, SHUT_FLAG_OK }, /* RW, to be caught first if exists... */
 
188
        { "battery.charge.low",ST_FLAG_STRING, 5, "UPS.PowerSummary.RemainingCapacityLimit", "%ld", NULL, SHUT_FLAG_OK }, /* ... or Read only */
 
189
        { "battery.runtime", 0, 0, "UPS.PowerSummary.RunTimeToEmpty", "%05d", NULL, SHUT_FLAG_OK },
 
190
        /* UPS page */
 
191
        { "ups.mfr",ST_FLAG_STRING, 20, "", "%s", "MGE UPS SYSTEMS", SHUT_FLAG_ABSENT | SHUT_FLAG_OK },
 
192
        { "ups.load", 0, 0, "UPS.PowerSummary.PercentLoad", "%i", NULL, SHUT_FLAG_OK },
 
193
        { "ups.delay.shutdown",ST_FLAG_RW |ST_FLAG_STRING, 5, "UPS.PowerSummary.DelayBeforeShutdown", "%ld", NULL, SHUT_FLAG_OK | SHUT_FLAG_DELAY},
 
194
        { "ups.delay.reboot",ST_FLAG_RW |ST_FLAG_STRING, 5, "UPS.PowerSummary.DelayBeforeReboot", "%ld", NULL, SHUT_FLAG_OK | SHUT_FLAG_DELAY},
 
195
        { "ups.delay.start",ST_FLAG_RW |ST_FLAG_STRING, 5, "UPS.PowerSummary.DelayBeforeStartup", "%ld", NULL, SHUT_FLAG_OK | SHUT_FLAG_DELAY},
 
196
        { "ups.test.interval",ST_FLAG_RW |ST_FLAG_STRING, 5, "UPS.BatterySystem.Battery.TestPeriod", "%i", NULL, SHUT_FLAG_OK },
 
197
        { "ups.test.result",ST_FLAG_RW |ST_FLAG_STRING, 5, "UPS.BatterySystem.Battery.Test", "%i", NULL, SHUT_FLAG_OK },
 
198
 
 
199
        /* Output page */
 
200
        { "output.voltage", 0, 0, "UPS.PowerConverter.Output.Voltage", "%i", NULL, SHUT_FLAG_OK },
 
201
        { "output.voltage.target.line", 0, 0, "UPS.PowerSummary.ConfigVoltage", "%i", NULL, SHUT_FLAG_OK },
 
202
        { "output.voltage.target.battery", 0, 0, "UPS.PowerSummary.ConfigVoltage", "%i", NULL, SHUT_FLAG_OK },
 
203
        { "output.current", 0, 0, "UPS.PowerSummary.Output.Current", "%i", NULL, SHUT_FLAG_OK },
 
204
        { "output.frequency", 0, 0, "UPS.PowerConverter.Output.Frequency", "%i", NULL, SHUT_FLAG_OK },
 
205
 
 
206
        /* Outlet page (using MGE UPS SYSTEMS - PowerShare technology) */
 
207
        /* TODO: add an iterative semantic [%x] to factorise outlets */
 
208
        { "outlet.0.id", 0, 0, "UPS.OutletSystem.Outlet.[1].OutletID", "%i", NULL, SHUT_FLAG_OK },
 
209
        { "outlet.0.desc",ST_FLAG_RW |ST_FLAG_STRING, 20, "", "s", "Main Outlet", SHUT_FLAG_ABSENT | SHUT_FLAG_OK },
 
210
        { "outlet.0.switchable", 0, 0, "UPS.OutletSystem.Outlet.[1].PresentStatus.Switchable", "%i", NULL, SHUT_FLAG_OK },
 
211
        { "outlet.1.id", 0, 0, "UPS.OutletSystem.Outlet.[2].OutletID", "%i", NULL, SHUT_FLAG_OK },      
 
212
        { "outlet.1.desc",ST_FLAG_RW |ST_FLAG_STRING, 20, "", "s", "PowerShare Outlet 1", SHUT_FLAG_ABSENT | SHUT_FLAG_OK },
 
213
        { "outlet.1.switchable", 0, 0, "UPS.OutletSystem.Outlet.[2].PresentStatus.Switchable", "%i", NULL, SHUT_FLAG_OK },
 
214
        { "outlet.1.switch",ST_FLAG_RW |ST_FLAG_STRING, 2, "UPS.OutletSystem.Outlet.[2].PresentStatus.SwitchOn/Off", "%i", NULL, SHUT_FLAG_OK },
 
215
        { "outlet.1.autoswitch.charge.low",ST_FLAG_RW |ST_FLAG_STRING, 3, "UPS.OutletSystem.Outlet.[2].RemainingCapacityLimit", "%i", NULL, SHUT_FLAG_OK },
 
216
        { "outlet.1.delay.shutdown",ST_FLAG_RW |ST_FLAG_STRING, 5, "UPS.OutletSystem.Outlet.[2].DelayBeforeShutdown", "%i", NULL, SHUT_FLAG_OK },
 
217
        { "outlet.1.delay.start",ST_FLAG_RW |ST_FLAG_STRING, 5, "UPS.OutletSystem.Outlet.[2].DelayBeforeStartup", "%i", NULL, SHUT_FLAG_OK },
 
218
        { "outlet.2.id", 0, 0, "UPS.OutletSystem.Outlet.[3].OutletID", "%i", NULL, SHUT_FLAG_OK },      
 
219
        { "outlet.2.desc",ST_FLAG_RW |ST_FLAG_STRING, 20, "", "s", "PowerShare Outlet 2", SHUT_FLAG_ABSENT | SHUT_FLAG_OK },
 
220
        { "outlet.2.switchable", 0, 0, "UPS.OutletSystem.Outlet.[3].PresentStatus.Switchable", "%i", NULL, SHUT_FLAG_OK },
 
221
        { "outlet.2.switch",ST_FLAG_RW |ST_FLAG_STRING, 2, "UPS.OutletSystem.Outlet.[3].PresentStatus.SwitchOn/Off", "%i", NULL, SHUT_FLAG_OK },
 
222
        { "outlet.2.autoswitch.charge.low",ST_FLAG_RW |ST_FLAG_STRING, 3, "UPS.OutletSystem.Outlet.[3].RemainingCapacityLimit", "%i", NULL, SHUT_FLAG_OK },
 
223
        { "outlet.2.delay.shutdown",ST_FLAG_RW |ST_FLAG_STRING, 5, "UPS.OutletSystem.Outlet.[3].DelayBeforeShutdown", "%i", NULL, SHUT_FLAG_OK },
 
224
        { "outlet.2.delay.start",ST_FLAG_RW |ST_FLAG_STRING, 5, "UPS.OutletSystem.Outlet.[3].DelayBeforeStartup", "%i", NULL, SHUT_FLAG_OK },
 
225
 
 
226
        /* Input page */
 
227
        { "input.voltage", 0, 0, "UPS.PowerConverter.Input.[1].Voltage", "%i", NULL, SHUT_FLAG_OK },
 
228
        { "input.frequency", 0, 0, "UPS.PowerConverter.Input.[1].Frequency", "%i", NULL, SHUT_FLAG_OK },
 
229
 
 
230
        /* terminating element */
 
231
        { NULL, 0, 0, "\0", "\0", NULL, 0 } 
 
232
};
 
233
 
 
234
/* temporary usage code lookup */
 
235
typedef struct {
 
236
        char *usage_name;
 
237
        int usage_code;
 
238
} usage_lkp_t;
 
239
 
 
240
static usage_lkp_t usage_lkp[] = {
 
241
        /* Power Device Page */
 
242
        {  "PresentStatus", 0x00840002 },
 
243
        {  "UPS", 0x00840004 },
 
244
        {  "BatterySystem", 0x00840010 },
 
245
        {  "Battery", 0x00840012 },
 
246
        {  "BatteryID", 0x00840013 },   
 
247
        {  "PowerConverter", 0x00840016 },
 
248
        {  "OutletSystem", 0x00840018 },
 
249
        {  "Input", 0x0084001a },
 
250
        {  "Output", 0x0084001c },
 
251
        {  "Outlet", 0x00840020 },
 
252
        {  "OutletID", 0x00840021 },
 
253
        {  "PowerSummary", 0x00840024 },
 
254
        {  "Voltage", 0x00840030 },
 
255
        {  "Current", 0x00840031 },
 
256
        {  "Frequency", 0x00840032 },
 
257
        {  "PercentLoad", 0x00840035 },
 
258
        {  "ConfigVoltage", 0x00840040 },
 
259
        {  "ConfigCurrent", 0x00840041 },
 
260
        {  "ConfigFrequency", 0x00840042 },
 
261
        {  "ConfigApparentPower", 0x00840043 },
 
262
        {  "LowVoltageTransfer", 0x00840053 },
 
263
        {  "HighVoltageTransfer", 0x00840054 }, 
 
264
        {  "DelayBeforeReboot", 0x00840055 },   
 
265
        {  "DelayBeforeStartup", 0x00840056 },
 
266
        {  "DelayBeforeShutdown", 0x00840057 },
 
267
        {  "Test", 0x00840058 },
 
268
        {  "OverLoad", 0x00840065 }, /* mispelled in usb.ids */
 
269
        {  "SwitchOn/Off", 0x0084006b },        
 
270
        {  "Switchable", 0x0084006c },  
 
271
        {  "Flow", 0x0084001e },
 
272
        /* Battery System Page */
 
273
        {  "RemainingCapacityLimit", 0x00850029 },
 
274
        {  "BelowRemainingCapacityLimit", 0x00850042 },
 
275
        {  "RemainingCapacity", 0x00850066 },
 
276
        {  "RunTimeToEmpty", 0x00850068 },
 
277
        {  "ACPresent", 0x008500d0 },
 
278
        {  "Charging", 0x00850044 },
 
279
        {  "Discharging", 0x00850045 },
 
280
        {  "NeedReplacement", 0x0085004b },
 
281
        /* MGE UPS SYSTEMS Page */
 
282
        {  "iModel", 0xffff00f0 },
 
283
        {  "RemainingCapacityLimitSetting", 0xffff004d },
 
284
        {  "TestPeriod", 0xffff0001 },
 
285
        
 
286
        {  "\0", 0x0 }
 
287
};
 
288
 
 
289
/* SHUT / HID functions Prototypes */
 
290
 
 
291
int   shut_ups_start(void);
 
292
uchar shut_checksum(const unsigned char *buf, int bufsize);
 
293
int   shut_token_send(unsigned char token);
 
294
int   shut_packet_send (hid_data_u *hdata, int datalen, unsigned char token);
 
295
int   shut_packet_recv (unsigned char *Buf, int datalen);
 
296
 
 
297
int   shut_get_descriptor(int desctype, unsigned char *pkt, int reportlen);
 
298
int   shut_get_string(int index, char *string, int strlen);
 
299
int   shut_get_report(int id, unsigned char *pkt, int reportlen);
 
300
int   shut_set_report(int id, unsigned char *pkt, int reportlen);
 
301
int   shut_identify_ups (void);
 
302
int   shut_wait_ack (void);
 
303
void  shut_ups_status(void);
 
304
 
 
305
int    hid_init_device(void);
 
306
int        hid_lookup_usage(char *name);
 
307
int    hid_get_value(char *item_path);
 
308
int    hid_set_value(const char *varname, const char *val);
 
309
ushort lookup_path(char *HIDpath, HIDData *data);
 
310
 
 
311
int    instcmd(const char *cmdname, const char *extra);
 
312
void   setline(int set);
 
313
int    serial_read (int read_timeout, unsigned char *read);
 
314
int    serial_send(unsigned char *buf, int len);
 
315
 
 
316
void   dump_hex(const char *msg, const unsigned char *buf, int len);
 
317
void   make_string(unsigned char *buf, int datalen, char *string);
 
318
 
 
319
 
 
320
mge_info_item *shut_find_info(const char *varname);