29
#define POWERWARE 0x0592
31
/* Phoenixtec Power Co., Ltd */
32
#define PHOENIXTEC 0x06da
35
#define HP_VENDORID 0x03f0
38
usb_dev_handle *nutusb_open(const char *port);
39
int nutusb_close(usb_dev_handle *dev_h, const char *port);
40
/* unified failure reporting: call these often */
41
void nutusb_comm_fail(const char *fmt, ...)
42
__attribute__ ((__format__ (__printf__, 1, 2)));
43
void nutusb_comm_good(void);
44
/* function pointer, set depending on which device is used */
45
int (*usb_set_descriptor)(usb_dev_handle *udev, unsigned char type,
46
unsigned char index, void *buf, int size);
48
/* usb_set_descriptor() for Powerware devices */
49
static int usb_set_powerware(usb_dev_handle *udev, unsigned char type, unsigned char index, void *buf, int size)
51
return usb_control_msg(udev, USB_ENDPOINT_OUT, USB_REQ_SET_DESCRIPTOR, (type << 8) + index, 0, buf, size, 1000);
54
static void *powerware_ups(void) {
55
usb_set_descriptor = &usb_set_powerware;
59
/* usb_set_descriptor() for Phoenixtec devices */
60
static int usb_set_phoenixtec(usb_dev_handle *udev, unsigned char type, unsigned char index, void *buf, int size)
62
return usb_control_msg(udev, 0x42, 0x0d, (0x00 << 8) + 0x0, 0, buf, size, 1000);
65
static void *phoenixtec_ups(void) {
66
usb_set_descriptor = &usb_set_phoenixtec;
70
/* USB IDs device table */
71
static usb_device_id_t pw_usb_device_table[] = {
73
{ USB_DEVICE(POWERWARE, 0x0002), &powerware_ups },
76
{ USB_DEVICE(PHOENIXTEC, 0x0002), &phoenixtec_ups },
79
{ USB_DEVICE(HP_VENDORID, 0x1f01), &phoenixtec_ups },
81
{ USB_DEVICE(HP_VENDORID, 0x1f02), &phoenixtec_ups },
83
/* Terminating entry */
87
/* limit the amount of spew that goes in the syslog when we lose the UPS */
88
#define USB_ERR_LIMIT 10 /* start limiting after 10 in a row */
89
#define USB_ERR_RATE 10 /* then only print every 10th error */
90
#define XCP_USB_TIMEOUT 5000
92
/* global variables */
93
usb_dev_handle *upsdev = NULL;
95
static unsigned int comm_failures = 0;
97
/* Functions implementations */
20
98
void send_read_command(unsigned char command)
100
unsigned char buf[4];
24
buf[0]=PW_COMMAND_START_BYTE;
25
buf[1]=0x01; /* data length */
26
buf[2]=command; /* command to send */
27
buf[3]=calc_checksum(buf); /* checksum */
28
usb_set_descriptor(upsdev, USB_DT_STRING, 4, buf, 4); /* Ignore error */
103
buf[0] = PW_COMMAND_START_BYTE;
104
buf[1] = 0x01; /* data length */
105
buf[2] = command; /* command to send */
106
buf[3] = calc_checksum(buf); /* checksum */
107
upsdebug_hex (3, "send_read_command", buf, 4);
108
usb_set_descriptor(upsdev, USB_DT_STRING, 4, buf, 4); /* FIXME: Ignore error */
31
112
void send_write_command(unsigned char *command, int command_length)
33
114
unsigned char sbuf[128];
35
/* Prepare the send buffer */
36
sbuf[0] = PW_COMMAND_START_BYTE;
37
sbuf[1] = (unsigned char)(command_length);
38
memcpy(sbuf+2, command, command_length);
117
/* Prepare the send buffer */
118
sbuf[0] = PW_COMMAND_START_BYTE;
119
sbuf[1] = (unsigned char)(command_length);
120
memcpy(sbuf+2, command, command_length);
42
sbuf[command_length] = calc_checksum(sbuf);
44
usb_set_descriptor(upsdev, USB_DT_STRING, 4, sbuf, command_length); /* Ignore error */
124
sbuf[command_length] = calc_checksum(sbuf);
126
upsdebug_hex (3, "send_write_command", sbuf, command_length);
127
usb_set_descriptor(upsdev, USB_DT_STRING, 4, sbuf, command_length); /* FIXME: Ignore error */
47
131
/* get the answer of a command from the ups. And check that the answer is for this command */
48
132
int get_answer(unsigned char *data, unsigned char command)
50
134
unsigned char buf[1024], *my_buf = buf;
51
int length, end_length, res, endblock, start;
52
unsigned char block_number, sequence, pre_sequence;
59
res = usb_interrupt_read(upsdev, 1, (char *)buf, sizeof(buf), 1000);
61
nutusb_comm_fail("Receive error (Request command): COMMAND: %x\n", command);
135
int length, end_length, res, endblock, bytes_read, ellapsed_time;
136
unsigned char block_number, sequence, seq_num;
137
struct timeval start_time, now;
67
while (endblock != 1 && my_buf < buf+sizeof(buf) && res > 0){
142
length = 1; /* non zero to enter the read loop */
143
end_length = 0; /* total length of sequence(s), not counting header(s) */
144
endblock = 0; /* signal the last sequence in the block */
145
bytes_read = 0; /* total length of data read, including XCP header */
148
seq_num = 1; /* current theoric sequence */
150
upsdebugx(1, "entering get_answer(%x)", command);
152
/* Store current time */
153
gettimeofday(&start_time, NULL);
155
while ( (!endblock) && ((XCP_USB_TIMEOUT - ellapsed_time) > 0) ) {
157
/* Get (more) data if needed */
158
if ((length - bytes_read) > 0) {
159
res = usb_interrupt_read(upsdev, 0x81,
160
(char *)&buf[bytes_read],
161
(PW_ANSWER_MAX_SIZE - bytes_read),
162
(XCP_USB_TIMEOUT - ellapsed_time));
165
gettimeofday(&now, NULL);
166
ellapsed_time = (now.tv_sec - start_time.tv_sec)*1000 +
167
(now.tv_usec - start_time.tv_usec)/1000;
169
/* Check libusb return value */
172
/* Clear any possible endpoint stalls */
173
usb_clear_halt(upsdev, 0x81);
174
/* continue; */ /* FIXME: seems a break would be better! */
178
/* this seems to occur on XSlot USB card */
185
/* Else, we got some input bytes */
187
upsdebug_hex(1, "get_answer", buf, bytes_read);
190
/* Now validate XCP frame */
192
if ( my_buf[0] != 0xAB ) {
193
upsdebugx(2, "get_answer: wrong header");
197
/* These validations seem not needed! */
68
198
/* Read block number byte */
69
block_number = (unsigned char)my_buf[1];
199
block_number = my_buf[1];
200
upsdebugx(1, "get_answer: block_number = %x", block_number);
71
202
if (command <= 0x43) {
72
203
if ((command - 0x30) != block_number){
73
nutusb_comm_fail("Receive error (Request command): BLOCK: %x, COMMAND: %x!\n", block_number, command);
204
nutusb_comm_fail("Receive error (Request command): BLOCK: %x (instead of %x), COMMAND: %x!\n",
205
block_number, (command - 0x30), command);
78
210
if (command >= 0x89) {
79
211
if ((command == 0xA0) && (block_number != 0x01)){
80
nutusb_comm_fail("Receive error (Request command): BLOCK: %x, COMMAND: %x!\n", block_number, command);
212
nutusb_comm_fail("Receive error (Request command): BLOCK: %x (instead of 0x01), COMMAND: %x!\n", block_number, command);
83
215
else if ((command != 0xA0) && (block_number != 0x09)){
84
nutusb_comm_fail("Receive error (Request command): BLOCK: %x, COMMAND: %x!\n", block_number, command);
216
nutusb_comm_fail("Receive error (Request command): BLOCK: %x (instead of 0x09), COMMAND: %x!\n", block_number, command);
89
/* Read data length byte */
90
length = (unsigned char)my_buf[2];
93
nutusb_comm_fail("Receive error (length): packet length %x!!!\n", length);
97
/* Read sequence byte */
98
sequence = (unsigned char)my_buf[3];
99
if ((sequence & 0x80) == 0x80) {
222
/* Check data length byte (remove the header length) */
224
upsdebugx(3, "get_answer: data length = %d", length);
225
if ((bytes_read - 5) < length) {
226
upsdebugx(2, "get_answer: need to read %d more data", length - (bytes_read - 5));
229
/* Check if Length conforms to XCP (121 for normal, 140 for Test mode) */
230
/* Use the more generous length for testing */
232
upsdebugx(2, "get_answer: bad length");
236
/* Test the Sequence # */
237
sequence = my_buf[3];
238
if ((sequence & PW_SEQ_MASK) != seq_num) {
239
nutusb_comm_fail("get_answer: not the right sequence received %x!!!\n", (sequence & PW_SEQ_MASK));
243
upsdebugx(2, "get_answer: sequence number (%x) is ok", (sequence & PW_SEQ_MASK));
246
/* Validate checksum */
247
if (!checksum_test(my_buf)) {
248
nutusb_comm_fail("get_answer: checksum error! ");
252
upsdebugx(2, "get_answer: checksum is ok");
255
/* Check if it's the last sequence */
256
if (sequence & PW_LAST_SEQ) {
257
/* we're done receiving data */
258
upsdebugx(2, "get_answer: all data received");
103
if ((sequence & 0x07) != (pre_sequence + 1)) {
104
nutusb_comm_fail("Not the right sequence received %x!!!\n", sequence);
108
pre_sequence = sequence;
110
/* Try to read all the remainig bytes */
111
if (res-5 < length) {
112
nutusb_comm_fail("Receive error (data): got %d bytes instead of %d!!!\n", res-5, length);
116
/* now we have the whole answer from the ups, we can checksum it */
117
if (!checksum_test(my_buf)) {
118
nutusb_comm_fail("checksum error! ");
265
/* copy the current valid XCP frame back */
122
266
memcpy(data+end_length, my_buf+4, length);
267
/* increment pointers to process the next sequence */
123
268
end_length += length;
125
269
my_buf += length + 5;
272
upsdebug_hex (5, "get_answer", data, end_length);
128
273
return end_length;
190
336
void upsdrv_reconnect(void)
193
338
upslogx(LOG_WARNING, "RECONNECT USB DEVICE\n");
194
339
nutusb_close(upsdev, "USB");
345
static void nutusb_open_error(const char *port)
347
printf("Unable to find POWERWARE UPS device on USB bus (%s)\n\n", port);
349
printf("Things to try:\n\n");
350
printf(" - Connect UPS device to USB bus\n\n");
351
printf(" - Run this driver as another user (upsdrvctl -u or 'user=...' in ups.conf).\n");
352
printf(" See upsdrvctl(8) and ups.conf(5).\n\n");
354
fatalx(EXIT_FAILURE, "Fatal error: unusable configuration");
357
/* FIXME: this part of the opening can go into common... */
358
static usb_dev_handle *open_powerware_usb(void)
360
struct usb_bus *busses = usb_get_busses();
363
for (bus = busses; bus; bus = bus->next)
365
struct usb_device *dev;
367
for (dev = bus->devices; dev; dev = dev->next)
369
if (dev->descriptor.bDeviceClass != USB_CLASS_PER_INTERFACE) {
373
if (is_usb_device_supported(pw_usb_device_table,
374
dev->descriptor.idVendor, dev->descriptor.idProduct) == SUPPORTED) {
375
return usb_open(dev);
382
usb_dev_handle *nutusb_open(const char *port)
385
usb_dev_handle *dev_h = NULL;
386
int retry, errout = 0;
388
upsdebugx(1, "entering nutusb_open()");
390
/* Initialize Libusb */
395
for (retry = 0; retry < MAX_TRY ; retry++)
397
dev_h = open_powerware_usb();
399
upsdebugx(1, "Can't open POWERWARE USB device");
403
upsdebugx(1, "device %s opened successfully", usb_device(dev_h)->filename);
406
if (usb_claim_interface(dev_h, 0) < 0)
408
upsdebugx(1, "Can't claim POWERWARE USB interface: %s", usb_strerror());
415
/* FIXME: the above part of the opening can go into common... up to here at least */
417
if (usb_clear_halt(dev_h, 0x81) < 0)
419
upsdebugx(1, "Can't reset POWERWARE USB endpoint: %s", usb_strerror());
426
/* Test if we succeeded */
427
if ( (dev_h != NULL) && dev_claimed && (errout == 0) )
430
/* Clear errors, and try again */
435
if (!dev_h && !dev_claimed && retry == MAX_TRY)
440
if (dev_h && dev_claimed)
441
usb_release_interface(dev_h, 0);
447
nutusb_open_error(port);
452
/* FIXME: this part can go into common... */
453
int nutusb_close(usb_dev_handle *dev_h, const char *port)
457
usb_release_interface(dev_h, 0);
458
return usb_close(dev_h);
464
void nutusb_comm_fail(const char *fmt, ...)
470
/* this means we're probably here because select was interrupted */
472
return; /* ignored, since we're about to exit anyway */
476
if ((comm_failures == USB_ERR_LIMIT) ||
477
((comm_failures % USB_ERR_RATE) == 0))
479
upslogx(LOG_WARNING, "Warning: excessive comm failures, "
480
"limiting error reporting");
483
/* once it's past the limit, only log once every USB_ERR_LIMIT calls */
484
if ((comm_failures > USB_ERR_LIMIT) &&
485
((comm_failures % USB_ERR_LIMIT) != 0)) {
486
/* Try reconnection */
491
/* generic message if the caller hasn't elaborated */
494
upslogx(LOG_WARNING, "Communications with UPS lost - check cabling");
499
ret = vsnprintf(why, sizeof(why), fmt, ap);
502
if ((ret < 1) || (ret >= (int) sizeof(why)))
503
upslogx(LOG_WARNING, "usb_comm_fail: vsnprintf needed "
504
"more than %d bytes", (int)sizeof(why));
506
upslogx(LOG_WARNING, "Communications with UPS lost: %s", why);
509
void nutusb_comm_good(void)
511
if (comm_failures == 0)
514
upslogx(LOG_NOTICE, "Communications with UPS re-established");