示例#1
0
文件: libhid.c 项目: ThomasKurz/nut
/* refresh the report with the given id in the report buffer rbuf.  If
   the report is not yet in the buffer, or if it is older than "age"
   seconds, then the report is freshly read from the USB
   device. Otherwise, it is unchanged.
   Return 0 on success, -1 on error with errno set. */
static int refresh_report_buffer(reportbuf_t *rbuf, hid_dev_handle_t udev, HIDData_t *pData, int age)
{
	int	id = pData->ReportID;
	int	r;

	if (rbuf->ts[id] + age > time(NULL)) {
		/* buffered report is still good; nothing to do */
		upsdebug_hex(3, "Report[buf]", rbuf->data[id], rbuf->len[id]);
		return 0;
	}

	r = comm_driver->get_report(udev, id, rbuf->data[id], rbuf->len[id]);
	if (r <= 0) {
		return -1;
	}

	if (rbuf->len[id] != r) {
		upsdebugx(2, "%s: expected %d bytes, but got %d instead", __func__, rbuf->len[id], r);
		upsdebug_hex(3, "Report[err]", rbuf->data[id], r);
	} else {
		upsdebug_hex(3, "Report[get]", rbuf->data[id], rbuf->len[id]);
	}

	/* have (valid) report */
	time(&rbuf->ts[id]);

	return 0;
}
示例#2
0
static int do_command(const unsigned char *command, char *reply, int cmd_len)
{
	int	ret;

	ret = ser_send_buf(upsfd, command, cmd_len);
	if (ret < 0) {
		upsdebug_with_errno(2, "send");
		return -1;
	} else if (ret < cmd_len) {
		upsdebug_hex(2, "send: truncated", command, ret);
		return -1;
	}

	upsdebug_hex(2, "send", command, ret);

	ret = ser_get_buf_len(upsfd, reply, 8, 1, 0); /* it needs that this driver works with USB to Serial cable */
	if (ret < 0) {
		upsdebug_with_errno(2, "read");
		return -1;
	} else if (ret < 6) {
		upsdebug_hex(2, "read: truncated", reply, ret);
		return -1;
	} else if (reply[7] != cksum(reply, 7)) {
		upsdebug_hex(2, "read: checksum error", reply, ret);
		return -1;
	}

	upsdebug_hex(2, "read", reply, ret);
	return ret;
}
示例#3
0
static void send_command(unsigned char *command, int command_length)
{
	int		retry = 0, sent;
	unsigned char	sbuf[128];

	/* Prepare the send buffer */
	sbuf[0] = PW_COMMAND_START_BYTE;
	sbuf[1] = (unsigned char)(command_length);
	memcpy(sbuf+2, command, command_length);
	command_length += 2;

	/* Add checksum */
	sbuf[command_length] = calc_checksum(sbuf);
	command_length += 1;

	upsdebug_hex (3, "send_command", sbuf, command_length);

	while (retry++ < PW_MAX_TRY) {

		if (retry == PW_MAX_TRY) {
			ser_send_char(upsfd, 0x1d);	/* last retry is preceded by a ESC.*/
			usleep(250000);
		}

		sent = ser_send_buf(upsfd, sbuf, command_length);

		if (sent == command_length) {
			return;
		}
	}
}
示例#4
0
文件: libhid.c 项目: ThomasKurz/nut
/* file a given report in the report buffer. This is used when the
   report has been obtained without having been explicitly requested,
   e.g., it arrived through an interrupt transfer. Returns 0 on
   success, -1 on error with errno set. */
static int file_report_buffer(reportbuf_t *rbuf, unsigned char *buf, int buflen)
{
	int id = buf[0];

	/* broken report descriptors are common, so store whatever we can */
	memcpy(rbuf->data[id], buf, (buflen < rbuf->len[id]) ? buflen : rbuf->len[id]);

	if (rbuf->len[id] != buflen) {
		upsdebugx(2, "%s: expected %d bytes, but got %d instead", __func__, rbuf->len[id], buflen);
		upsdebug_hex(3, "Report[err]", buf, buflen);
	} else {
		upsdebug_hex(3, "Report[int]", rbuf->data[id], rbuf->len[id]);
	}

	/* have (valid) report */
	time(&rbuf->ts[id]);

	return 0;
}
示例#5
0
static int execute_and_retrieve_query(char *query, char *reply)
{
	int	ret;

	ret = usb_control_msg(udev, STATUS_REQUESTTYPE, REQUEST_VALUE,
		MESSAGE_VALUE, INDEX_VALUE, query, QUERY_PACKETSIZE, 1000);

	if (ret <= 0) {
		upsdebugx(3, "send: %s", ret ? usb_strerror() : "timeout");
		return ret;
	}

	upsdebug_hex(3, "send", query, ret);

	ret = usb_interrupt_read(udev, REPLY_REQUESTTYPE, reply, REPLY_PACKETSIZE, 1000);

	if (ret <= 0) {
		upsdebugx(3, "read: %s", ret ? usb_strerror() : "timeout");
		return ret;
	}

	upsdebug_hex(3, "read", reply, ret);
	return ret;
}
示例#6
0
文件: libhid.c 项目: ThomasKurz/nut
/* set the logical value for the given pData. No physical to logical
   conversion is performed. On success, return 0, and failure, return
   -1 and set errno. The updated value is sent to the device. */
static int set_item_buffered(reportbuf_t *rbuf, hid_dev_handle_t udev, HIDData_t *pData, long Value)
{
	int id = pData->ReportID;
	int r;

	SetValue(pData, rbuf->data[id], Value);

	r = comm_driver->set_report(udev, id, rbuf->data[id], rbuf->len[id]);
	if (r <= 0) {
		return -1;
	}

	upsdebug_hex(3, "Report[set]", rbuf->data[id], rbuf->len[id]);

	/* expire report */
	rbuf->ts[id] = 0;

	return 0;
}
示例#7
0
文件: microdowell.c 项目: AlexLov/nut
void SendCmdToSerial(unsigned char *Buff, int Len)
{
	int i;
	unsigned char Tmp[20], Xor ;

	Tmp[0] = STX_CHAR ;
	Xor = Tmp[1] = (unsigned char) (Len & 0x1f) ;
	for (i=0 ; i < Tmp[1] ; i++)
	{
		Tmp[i+2] = Buff[i] ;
		Xor ^= Buff[i] ;
	}
	Tmp[Len+2] = Xor ;

	upsdebug_hex(4, "->UPS", Tmp, Len+3) ;

	/* flush serial port */
	ser_flush_in(upsfd, "", 0) ; /* empty input buffer */
	ser_send_buf(upsfd, Tmp, Len+3) ; /* send data to the UPS */
}
示例#8
0
文件: libusb.c 项目: alfh/nut
/* On success, fill in the curDevice structure and return the report
 * descriptor length. On failure, return -1.
 * Note: When callback is not NULL, the report descriptor will be
 * passed to this function together with the udev and USBDevice_t
 * information. This callback should return a value > 0 if the device
 * is accepted, or < 1 if not. If it isn't accepted, the next device
 * (if any) will be tried, until there are no more devices left.
 */
static int libusb_open(usb_dev_handle **udevp, USBDevice_t *curDevice, USBDeviceMatcher_t *matcher,
	int (*callback)(usb_dev_handle *udev, USBDevice_t *hd, unsigned char *rdbuf, int rdlen))
{
#ifdef HAVE_USB_DETACH_KERNEL_DRIVER_NP
	int retries;
#endif
	int rdlen1, rdlen2; /* report descriptor length, method 1+2 */
	USBDeviceMatcher_t *m;
	struct usb_device *dev;
	struct usb_bus *bus;
	usb_dev_handle *udev;
	struct usb_interface_descriptor *iface;

	int ret, res;
	unsigned char buf[20];
	unsigned char *p;
	char string[256];
	int i;

	/* report descriptor */
	unsigned char	rdbuf[MAX_REPORT_SIZE];
	int		rdlen;

	/* libusb base init */
	usb_init();
	usb_find_busses();
	usb_find_devices();

#ifndef __linux__ /* SUN_LIBUSB (confirmed to work on Solaris and FreeBSD) */
	/* Causes a double free corruption in linux if device is detached! */
	libusb_close(*udevp);
#endif

	for (bus = usb_busses; bus; bus = bus->next) {
		for (dev = bus->devices; dev; dev = dev->next) {
			upsdebugx(2, "Checking device (%04X/%04X) (%s/%s)", dev->descriptor.idVendor,
				dev->descriptor.idProduct, bus->dirname, dev->filename);

			/* supported vendors are now checked by the
			   supplied matcher */

			/* open the device */
			*udevp = udev = usb_open(dev);
			if (!udev) {
				upsdebugx(2, "Failed to open device, skipping. (%s)", usb_strerror());
				continue;
			}

			/* collect the identifying information of this
			   device. Note that this is safe, because
			   there's no need to claim an interface for
			   this (and therefore we do not yet need to
			   detach any kernel drivers). */

			free(curDevice->Vendor);
			free(curDevice->Product);
			free(curDevice->Serial);
			free(curDevice->Bus);
			memset(curDevice, '\0', sizeof(*curDevice));

			curDevice->VendorID = dev->descriptor.idVendor;
			curDevice->ProductID = dev->descriptor.idProduct;
			curDevice->Bus = strdup(bus->dirname);

			if (dev->descriptor.iManufacturer) {
				ret = usb_get_string_simple(udev, dev->descriptor.iManufacturer,
					string, sizeof(string));
				if (ret > 0) {
					curDevice->Vendor = strdup(string);
				}
			}

			if (dev->descriptor.iProduct) {
				ret = usb_get_string_simple(udev, dev->descriptor.iProduct,
					string, sizeof(string));
				if (ret > 0) {
					curDevice->Product = strdup(string);
				}
			}

			if (dev->descriptor.iSerialNumber) {
				ret = usb_get_string_simple(udev, dev->descriptor.iSerialNumber,
					string, sizeof(string));
				if (ret > 0) {
					curDevice->Serial = strdup(string);
				}
			}

			upsdebugx(2, "- VendorID: %04x", curDevice->VendorID);
			upsdebugx(2, "- ProductID: %04x", curDevice->ProductID);
			upsdebugx(2, "- Manufacturer: %s", curDevice->Vendor ? curDevice->Vendor : "unknown");
			upsdebugx(2, "- Product: %s", curDevice->Product ? curDevice->Product : "unknown");
			upsdebugx(2, "- Serial Number: %s", curDevice->Serial ? curDevice->Serial : "unknown");
			upsdebugx(2, "- Bus: %s", curDevice->Bus ? curDevice->Bus : "unknown");

			upsdebugx(2, "Trying to match device");
			for (m = matcher; m; m=m->next) {
				ret = matches(m, curDevice);
				if (ret==0) {
					upsdebugx(2, "Device does not match - skipping");
					goto next_device;
				} else if (ret==-1) {
					fatal_with_errno(EXIT_FAILURE, "matcher");
					goto next_device;
				} else if (ret==-2) {
					upsdebugx(2, "matcher: unspecified error");
					goto next_device;
				}
			}
			upsdebugx(2, "Device matches");

			/* Now we have matched the device we wanted. Claim it. */

#ifdef HAVE_USB_DETACH_KERNEL_DRIVER_NP
			/* this method requires at least libusb 0.1.8:
			 * it force device claiming by unbinding
			 * attached driver... From libhid */
			retries = 3;
			while (usb_claim_interface(udev, 0) < 0) {

				upsdebugx(2, "failed to claim USB device: %s", usb_strerror());

				if (usb_detach_kernel_driver_np(udev, 0) < 0) {
					upsdebugx(2, "failed to detach kernel driver from USB device: %s", usb_strerror());
				} else {
					upsdebugx(2, "detached kernel driver from USB device...");
				}

				if (retries-- > 0) {
					continue;
				}

				fatalx(EXIT_FAILURE, "Can't claim USB device [%04x:%04x]: %s", curDevice->VendorID, curDevice->ProductID, usb_strerror());
			}
#else
			if (usb_claim_interface(udev, 0) < 0) {
				fatalx(EXIT_FAILURE, "Can't claim USB device [%04x:%04x]: %s", curDevice->VendorID, curDevice->ProductID, usb_strerror());
			}
#endif

			/* set default interface */
			usb_set_altinterface(udev, 0);

			if (!callback) {
				return 1;
			}

			if (!dev->config) { /* ?? this should never happen */
				upsdebugx(2, "  Couldn't retrieve descriptors");
				goto next_device;
			}

			rdlen1 = -1;
			rdlen2 = -1;

			/* Get HID descriptor */

			/* FIRST METHOD: ask for HID descriptor directly. */
			/* res = usb_get_descriptor(udev, USB_DT_HID, 0, buf, 0x9); */
			res = usb_control_msg(udev, USB_ENDPOINT_IN+1, USB_REQ_GET_DESCRIPTOR,
					      (USB_DT_HID << 8) + 0, 0, buf, 0x9, USB_TIMEOUT);

			if (res < 0) {
				upsdebugx(2, "Unable to get HID descriptor (%s)", usb_strerror());
			} else if (res < 9) {
				upsdebugx(2, "HID descriptor too short (expected %d, got %d)", 8, res);
			} else {

				upsdebug_hex(3, "HID descriptor, method 1", buf, 9);

				rdlen1 = buf[7] | (buf[8] << 8);
			}

			if (rdlen1 < -1) {
				upsdebugx(2, "Warning: HID descriptor, method 1 failed");
			}

			/* SECOND METHOD: find HID descriptor among "extra" bytes of
			   interface descriptor, i.e., bytes tucked onto the end of
			   descriptor 2. */

			/* Note: on some broken UPS's (e.g. Tripp Lite Smart1000LCD),
				only this second method gives the correct result */

			/* for now, we always assume configuration 0, interface 0,
			   altsetting 0, as above. */
			iface = &dev->config[0].interface[0].altsetting[0];
			for (i=0; i<iface->extralen; i+=iface->extra[i]) {
				upsdebugx(4, "i=%d, extra[i]=%02x, extra[i+1]=%02x", i,
					iface->extra[i], iface->extra[i+1]);
				if (i+9 <= iface->extralen && iface->extra[i] >= 9 && iface->extra[i+1] == 0x21) {
					p = &iface->extra[i];
					upsdebug_hex(3, "HID descriptor, method 2", p, 9);
					rdlen2 = p[7] | (p[8] << 8);
					break;
				}
			}

			if (rdlen2 < -1) {
				upsdebugx(2, "Warning: HID descriptor, method 2 failed");
			}

			/* when available, always choose the second value, as it
				seems to be more reliable (it is the one reported e.g. by
				lsusb). Note: if the need arises, can change this to use
				the maximum of the two values instead. */
			rdlen = rdlen2 >= 0 ? rdlen2 : rdlen1;

			if (rdlen < 0) {
				upsdebugx(2, "Unable to retrieve any HID descriptor");
				goto next_device;
			}
			if (rdlen1 >= 0 && rdlen2 >= 0 && rdlen1 != rdlen2) {
				upsdebugx(2, "Warning: two different HID descriptors retrieved (Reportlen = %d vs. %d)", rdlen1, rdlen2);
			}

			upsdebugx(2, "HID descriptor length %d", rdlen);

			if (rdlen > (int)sizeof(rdbuf)) {
				upsdebugx(2, "HID descriptor too long %d (max %d)", rdlen, (int)sizeof(rdbuf));
				goto next_device;
			}

			/* res = usb_get_descriptor(udev, USB_DT_REPORT, 0, bigbuf, rdlen); */
			res = usb_control_msg(udev, USB_ENDPOINT_IN+1, USB_REQ_GET_DESCRIPTOR,
				(USB_DT_REPORT << 8) + 0, 0, rdbuf, rdlen, USB_TIMEOUT);

			if (res < 0)
			{
				upsdebug_with_errno(2, "Unable to get Report descriptor");
				goto next_device;
			}

			if (res < rdlen)
			{
				upsdebugx(2, "Warning: report descriptor too short (expected %d, got %d)", rdlen, res);
				rdlen = res; /* correct rdlen if necessary */
			}

			res = callback(udev, curDevice, rdbuf, rdlen);
			if (res < 1) {
				upsdebugx(2, "Caller doesn't like this device");
				goto next_device;
			}

			upsdebugx(2, "Report descriptor retrieved (Reportlen = %d)", rdlen);
			upsdebugx(2, "Found HID device");
			fflush(stdout);

			return rdlen;

		next_device:
			usb_close(udev);
		}
	}

	*udevp = NULL;
	upsdebugx(2, "No appropriate HID device found");
	fflush(stdout);

	return -1;
}
示例#9
0
void upsdrv_initinfo(void)
{
	struct {
		const char	*var;
		unsigned char	len;
	} vartab[] = {
		{ "ups.model",15 },
		{ "ups.firmware",8 },
		{ "ups.serial",10 },
		{ "ups.mfr.date",4 },
		{ NULL }
	};

	char	buf[LARGEBUF];
	int	i,bitn,vari,ret=0,offset=4,readok=0;
	char	command[6], reply[8];
	unsigned int	value;

	dstate_setinfo("ups.mfr", "%s", "Liebert");

	for (vari = 0; vartab[vari].var; vari++) {
		upsdebugx(1, "reading: %s", vartab[vari].var);

		for (i = 0; i < vartab[vari].len; i++) {
			snprintf(command, sizeof(command), "\x01\x88\x02\x01%c", i+offset);
		command[5] = cksum(command, 5);

		ret = do_command((unsigned char *)command, reply, 6);
			if (ret < 8) {
				upsdebug_hex(2, "send: truncated", command, ret);
				break;
			}

			buf[i<<1] = reply[6];
			buf[(i<<1)+1] = reply[5];
	}

	buf[i<<1] = 0;
		upsdebugx(1, "return: %d (8=success)", ret);

		if (ret == 8) { /* last command successful */
			dstate_setinfo(vartab[vari].var,"%s",buf);
			readok++;
		}
		offset+=vartab[vari].len;
	} /* for */
	if (!readok) {
		fatalx(EXIT_FAILURE, "ESP-II capable UPS not detected");
	}

	/* determine number of input & output phases and ups type */
	memcpy(command,cmd_upstype,6);
	ret = do_command((unsigned char *)command, reply, 6);
	if (ret < 8) {
		upsdebug_hex(2, "send: phase detection: truncated", command, ret);
	}
	else {
		/* input: from bit 0 to bit 1 (2 bits) */
		for (value=0,bitn=0;bitn<2;bitn++) {
			if (IsBitSet(reply[6],(unsigned short int)bitn)) /* bit range measurement on LSByte*/
				value+=(1<<(unsigned short int)(bitn - 0));
		}
		num_inphases=value;
		dstate_setinfo("input.phases", "%d", value);

		/* output: from bit 4 to bit 5  (2 bits)*/
		for (value=0,bitn=4;bitn<6;bitn++) {
			if (IsBitSet(reply[6],(unsigned short int)bitn)) /* bit range measurement on LSByte*/
				value+=(1<<(unsigned short int)(bitn - 4));
		}
		num_outphases=value;
		dstate_setinfo("output.phases", "%d", value);

		if (reply[5] & (1<<4)) {	/* ISOFFLINE */
			dstate_setinfo("ups.type", "offline") ;
		}
		else if (reply[5] & (1<<5)) { /* ISINTERACTIVE */
			dstate_setinfo("ups.type", "line-interactive") ;
		}
		else {
			dstate_setinfo("ups.type", "online") ;
		}
	}

	/* determine scaling */
	/* full scaling output not defined yet, but we can differentiate sets of 
	 * multipliers based on a sample scaling reading */
	memcpy(command,cmd_scaling1,6);
	ret = do_command((unsigned char *)command, reply, 6);
	if (ret < 8) {
		upsdebug_hex(2, "send: scaling detection: truncated", command, ret);
	}
	else { /* add here multipliers that differentiate between models */
		switch (reply[6]) {
		case 1: /* GXT-2 */
			multi[M_FREQUENCY]=0.1;
			multi[M_VOLT_DC]=1.0;
			multi[M_POWER]=1.0;
			multi[M_NOMPOWER]=1.0;
			break;
		case 2: /* NXe */
			multi[M_FREQUENCY]=0.01;
			multi[M_VOLT_DC]=0.1;
			multi[M_POWER]=100.0;
			multi[M_NOMPOWER]=100.0;
			break;
		default: /* the default values from definition of multi will be used */
			break;
		}
	}

	upsh.instcmd = instcmd;
	upsh.setvar = setvar;
}
示例#10
0
/* get the answer of a command from the ups. And check that the answer is for this command */
int get_answer(unsigned char *data, unsigned char command)
{
	unsigned char	my_buf[128];	/* packet has a maximum length of 121+5 bytes */
	int		length, end_length = 0, res, endblock = 0, start = 0;
	unsigned char	block_number, sequence, pre_sequence = 0;

	while (endblock != 1){

		do {
			/* Read PW_COMMAND_START_BYTE byte */
			res = ser_get_char(upsfd, my_buf, 1, 0);

			if (res != 1) {
				upsdebugx(1,"Receive error (PW_COMMAND_START_BYTE): %d, cmd=%x!!!\n", res, command);
				return -1;
			}

			start++;

		} while ((my_buf[0] != PW_COMMAND_START_BYTE) && (start < 128));
		
		if (start == 128) {
			ser_comm_fail("Receive error (PW_COMMAND_START_BYTE): packet not on start!!%x\n", my_buf[0]);
			return -1;
		}

		/* Read block number byte */
		res = ser_get_char(upsfd, my_buf+1, 1, 0);

		if (res != 1) {
			ser_comm_fail("Receive error (Block number): %d!!!\n", res);
			return -1;
		}

		block_number = (unsigned char)my_buf[1];

		if (command <= 0x43) {
			if ((command - 0x30) != block_number){
				ser_comm_fail("Receive error (Request command): %x!!!\n", block_number);
				return -1;
			}
		}

		if (command >= 0x89) {
			if ((command == 0xA0) && (block_number != 0x01)){
				ser_comm_fail("Receive error (Requested only mode command): %x!!!\n", block_number);
				return -1;
			}

			if ((command != 0xA0) && (block_number != 0x09)){
				ser_comm_fail("Receive error (Control command): %x!!!\n", block_number);
				return -1;
			}
		}

		/* Read data length byte */
		res = ser_get_char(upsfd, my_buf+2, 1, 0);

		if (res != 1) {
			ser_comm_fail("Receive error (length): %d!!!\n", res);
			return -1;
		}

		length = (unsigned char)my_buf[2];

		if (length < 1) {
			ser_comm_fail("Receive error (length): packet length %x!!!\n", length);
			return -1;
		}

		/* Read sequence byte */
		res = ser_get_char(upsfd, my_buf+3, 1, 0);

		if (res != 1) {
			ser_comm_fail("Receive error (sequence): %d!!!\n", res);
			return -1;
		}

		sequence = (unsigned char)my_buf[3];

		if ((sequence & 0x80) == 0x80) {
			endblock = 1;
		}

		if ((sequence & 0x07) != (pre_sequence + 1)) {
			ser_comm_fail("Not the right sequence received %x!!!\n", sequence);
			return -1;
		}

		pre_sequence = sequence;

		/* Try to read all the remainig bytes */
		res = ser_get_buf_len(upsfd, my_buf+4, length, 1, 0);

		if (res != length) {
			ser_comm_fail("Receive error (data): got %d bytes instead of %d!!!\n", res, length);
			return -1;
		}

		/* Get the checksum byte */
		res = ser_get_char(upsfd, my_buf+(4+length), 1, 0);

		if (res != 1) {
			ser_comm_fail("Receive error (checksum): %x!!!\n", res);
			return -1;
		}

		/* now we have the whole answer from the ups, we can checksum it */
		if (!checksum_test(my_buf)) {
			ser_comm_fail("checksum error! ");
			return -1;
		}

		memcpy(data+end_length, my_buf+4, length);
		end_length += length;

	}

	upsdebug_hex (5, "get_answer", data, end_length);
	ser_comm_good();

	return end_length;
}
示例#11
0
static int phoenix_command(const char *cmd, char *buf, size_t buflen)
{
	char	tmp[SMALLBUF];
	int	ret;
	size_t	i;

	for (i = 0; i < 8; i++) {

		/* Read data in 8-byte chunks */
		/* ret = usb->get_interrupt(udev, (unsigned char *)tmp, 8, 1000); */
		ret = usb_interrupt_read(udev, 0x81, tmp, 8, 1000);

		/*
		 * This USB to serial implementation is crappy. In order to read correct
		 * replies we need to flush the output buffers of the converter until we
		 * get no more data (ie, it times out).
		 */
		switch (ret)
		{
		case -EPIPE:		/* Broken pipe */
			usb_clear_halt(udev, 0x81);
		case -ETIMEDOUT:	/* Connection timed out */
			break;
		}

		if (ret < 0) {
			upsdebugx(3, "flush: %s", usb_strerror());
			break;
		}

		upsdebug_hex(4, "dump", tmp, ret);
	}

	memset(tmp, 0, sizeof(tmp));
	snprintf(tmp, sizeof(tmp), "%s", cmd);

	for (i = 0; i < strlen(tmp); i += ret) {

		/* Write data in 8-byte chunks */
		/* ret = usb->set_report(udev, 0, (unsigned char *)&tmp[i], 8); */
		ret = usb_control_msg(udev, USB_ENDPOINT_OUT + USB_TYPE_CLASS + USB_RECIP_INTERFACE,
			0x09, 0x200, 0, &tmp[i], 8, 1000);

		if (ret <= 0) {
			upsdebugx(3, "send: %s", ret ? usb_strerror() : "timeout");
			return ret;
		}
	}

	upsdebugx(3, "send: %.*s", (int)strcspn(tmp, "\r"), tmp);

	memset(buf, 0, buflen);

	for (i = 0; (i <= buflen-8) && (strchr(buf, '\r') == NULL); i += ret) {

		/* Read data in 8-byte chunks */
		/* ret = usb->get_interrupt(udev, (unsigned char *)&buf[i], 8, 1000); */
		ret = usb_interrupt_read(udev, 0x81, &buf[i], 8, 1000);

		/*
		 * Any errors here mean that we are unable to read a reply (which
		 * will happen after successfully writing a command to the UPS)
		 */
		if (ret <= 0) {
			upsdebugx(3, "read: %s", ret ? usb_strerror() : "timeout");
			return ret;
		}
	}

	upsdebugx(3, "read: %.*s", (int)strcspn(buf, "\r"), buf);
	return i;
}
示例#12
0
文件: microdowell.c 项目: AlexLov/nut
unsigned char * CmdSerial(unsigned char *OutBuffer, int Len, unsigned char *RetBuffer)
{
	#define TMP_BUFF_LEN	1024
   unsigned char InpBuff[TMP_BUFF_LEN+1] ;
	unsigned char TmpBuff[3] ;
   int i, ErrCode ;
   unsigned char *p ;
	int BuffLen ;

	/* The default error code (no received character) */
	ErrCode = ERR_COM_NO_CHARS ;

   SendCmdToSerial(OutBuffer, Len) ;
	usleep(10000) ; /* small delay (1/100 s) */

	/* get chars until timeout */
	BuffLen = 0 ;
	while (ser_get_char(upsfd, TmpBuff, 0, 10000) == 1)
		{
		InpBuff[BuffLen++] = TmpBuff[0] ;
		if (BuffLen > TMP_BUFF_LEN)
			break ;
		}

	upsdebug_hex(4, "UPS->", InpBuff, BuffLen) ;

	if (BuffLen > 0)
		{
		ErrCode = CheckDataChecksum(InpBuff, BuffLen) ;
		/* upsdebugx(4, "ErrCode = %d / Len = %d", ErrCode, BuffLen); */

		if (!ErrCode)
			{
			/* FramePointer to valid data! */
			p = InpBuff + ups.FramePointer ;
			/* p now point to valid data.
			 check if it is a error code. */
			ErrCode = CheckErrCode(p) ;
			if (!ErrCode)
				{
				/* I copy the data read in the buffer */
				for(i=0 ; i<(int) (p[1])+3  ; i++)
					RetBuffer[i] = p[i] ;
				ups.ErrCode = ups.ErrCount = ups.CommStatus = 0 ;
				return(RetBuffer) ;
				}
			}
		}

	/* if they have arrived here, wants to say that I have found an error.... */
	ups.ErrCode = ErrCode ;
	ups.ErrCount++ ;
	if (ups.ErrCount > 3)
		{
		ups.CommStatus &= 0x80 ;
		ups.CommStatus |= (unsigned char) (ups.ErrCount & 0x7F)  ;
			if (ups.ErrCount > 100)
			ups.ErrCount = 100 ;
		}
	return(NULL) ;	/* There have been errors in the reading of the data */
}
/* Preprocess the answer we got back from the UPS when queried with 'QS\r' */
static int	voltronic_qs_hex_preprocess_qs_answer(item_t *item, const int len)
{
	int	i, token;
	char	refined[SMALLBUF] = "";

	if (len <= 0)
		return len;

	if (item->answer[0] != '#') {
		upsdebugx(4, "%s: wrong leading character [%s: 0x%0x]", __func__, item->info_type, item->answer[0]);
		return -1;
	}

	snprintf(refined, sizeof(refined), "%s", "#");

	/* e.g.: item->answer = "#\x6C\x01 \x35 \x6C\x01 \x35 \x03 \x51\x9A \x28\x02\x12\xD0 \xE6 \x1E \x09\r" */
	upsdebug_hex(4, "read", item->answer, len);

	for (i = 1, token = 1; i < len; i++) {

		/* New token */
		if (item->answer[i] == 0x20) {
			snprintfcat(refined, sizeof(refined), "%s", " ");
			token++;
			continue;
		}

		/* 'Unescape' raw data */
		if (item->answer[i] == 0x28 && i < len) {

			switch (item->answer[i + 1])
			{
			case 0x00:	/* Escaped because: CR */
				snprintfcat(refined, sizeof(refined), "%02x", 0x0D);
				break;
			case 0x01:	/* Escaped because: XON */
				snprintfcat(refined, sizeof(refined), "%02x", 0x11);
				break;
			case 0x02:	/* Escaped because: XOFF */
				snprintfcat(refined, sizeof(refined), "%02x", 0x13);
				break;
			case 0x03:	/* Escaped because: LF */
				snprintfcat(refined, sizeof(refined), "%02x", 0x0A);
				break;
			case 0x04:	/* Escaped because: space */
				snprintfcat(refined, sizeof(refined), "%02x", 0x20);
				break;
			default:
				if (token != 10)
					snprintfcat(refined, sizeof(refined), "%02x", ((unsigned char *)item->answer)[i]);
				else
					snprintfcat(refined, sizeof(refined), "%08d", voltronic_qs_hex_status_char_to_binary(((unsigned char *)item->answer)[i]));
				continue;
			}

			i++;
			continue;

		}

		/* Trailing CR */
		if (item->answer[i] == 0x0D)
			break;

		if (token != 10)
			snprintfcat(refined, sizeof(refined), "%02x", ((unsigned char *)item->answer)[i]);
		else
			snprintfcat(refined, sizeof(refined), "%08d", voltronic_qs_hex_status_char_to_binary(((unsigned char *)item->answer)[i]));

	}

	if (token != 10 || strlen(refined) != 46) {
		upsdebugx(2, "noncompliant reply: %s", refined);
		return -1;
	}

	upsdebugx(4, "read: %s", refined);

	/* e.g.: item->answer = "#6C01 35 6C01 35 03 519A 1312D0 E6 1E 00001001" */
	return snprintf(item->answer, sizeof(item->answer), "%s\r", refined);
}
示例#14
0
文件: ivtscd.c 项目: sbutler/nut
static int ivt_status(void)
{
	char	reply[SMALLBUF];
	int	ret, i, j = 0;

	ser_flush_io(upsfd);

	/*
	 * send: F\n
	 */
	ret = ser_send(upsfd, "F");

	if (ret < 0) {
		upsdebug_with_errno(3, "send");
		return -1;
	}

	if (ret == 0) {
		upsdebug_with_errno(3, "send: timeout");
		return -1;
	}

	upsdebugx(3, "send: F");
	sleep(1);	/* allow controller some time to digest this */
	
	/*
	 * read: R:12,57;- 1,1;20;12,57;13,18;- 2,1; 1,5;\n
	 */
	ret = ser_get_buf(upsfd, reply, sizeof(reply), 1, 0);

	if (ret < 0) {
		upsdebug_with_errno(3, "read");
		return -1;
	}

	if (ret == 0) {
		upsdebugx(3, "read: timeout");
		return -1;
	}

	upsdebugx(3, "read: %.*s", (int)strcspn(reply, "\r\n"), reply);
	upsdebug_hex(4, "  \\_", reply, ret);

	for (i = 0; i < ret; i++) {
		switch(reply[i])
		{
		case ',':	/* convert ',' to '.' */
			reply[j++] = '.';
			break;
		case ' ':	/* skip over white space */
		case '\0':	/* skip over null characters */
			break;
		default:	/* leave the rest as is */
			reply[j++] = reply[i];
			break;
		}
	}

	reply[j++] = '\0';

	ret = sscanf(reply, "R:%f;%f;%f;%f;%f;%f;%f;", &battery.voltage.act, &battery.current.act, &battery.temperature,
					&battery.voltage.min, &battery.voltage.max, &battery.current.min, &battery.current.max);

	upsdebugx(3, "Parsed %d parameters from reply", ret);
	return ret;
}