diff options
Diffstat (limited to 'meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon')
14 files changed, 0 insertions, 2382 deletions
diff --git a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/Makefile b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/Makefile deleted file mode 100644 index fa1e932..0000000 --- a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/Makefile +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright 2014-present Facebook. All Rights Reserved. -# -# This program file 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; version 2 of the License. -# -# 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 in a file named COPYING; if not, write to the -# Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, -# Boston, MA 02110-1301 USA - -override CFLAGS+=-D_GNU_SOURCE -D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=199309 -Wall -Werror -std=c99 -override LDFLAGS+=-pthread -all: modbuscmd gpiowatch modbussim rackmond rackmondata - -rackmondata: rackmondata.c modbus.c - $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) - -rackmond: rackmond.c modbus.c - $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) - -modbuscmd: modbuscmd.c modbus.c - $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) - -modbussim: modbussim.c modbus.c - $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) - -gpiowatch: gpiowatch.c - $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) - -.PHONY: clean - -clean: - rm -rf *.o modbuscmd gpiowatch modbussim rackmond rackmondata diff --git a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/gpiowatch.c b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/gpiowatch.c deleted file mode 100644 index 11b5471..0000000 --- a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/gpiowatch.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2014-present Facebook. All Rights Reserved. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <stdlib.h> -#include <errno.h> -#include <fcntl.h> - -#define CHECK(x) { if((x) < 0) { \ - error = x; \ - goto cleanup; \ -} } - -#define CHECKNULL(x) { if((x) == NULL) { \ - error = -1; \ - goto cleanup; \ -} } - -typedef struct { - int fd; - int gpio; - char value; -} wgpio; - -int main(int argc, char **argv) { - int error = 0; - int nfds = argc - 1; - int i = 0; - int polliv = 10000; - wgpio* wgpios = NULL; - - if(argc < 2) { - fprintf(stderr, "Usage: %s <gpio num> [gpio num] [gpio num...]\n", argv[0]); - exit(1); - } - if(getenv("POLL_US")) { - polliv = atoi(getenv("POLL_US")); - } - - wgpios = calloc(nfds, sizeof(wgpio)); - CHECKNULL(wgpios) - - fprintf(stderr, "Watching %d gpios:", nfds); - for(i = 1; i < argc; i++) { - char filename[255]; - int gpio_num = atoi(argv[i]); - wgpios[i - 1].gpio = gpio_num; - snprintf(filename, 255, "/sys/class/gpio/gpio%d/value", gpio_num); - wgpios[i - 1].fd = open(filename, O_RDONLY); - CHECK(wgpios[i - 1].fd); - CHECK(read(wgpios[i - 1].fd, &(wgpios[i - 1].value), 1)); - fprintf(stderr, " %d (currently: %c)", gpio_num, wgpios[i - 1].value); - } - fprintf(stderr, "\n"); - - do { - usleep(polliv); - for(i = 0; i < nfds; i++) { - wgpio* w = &wgpios[i]; - char value; - lseek(w->fd, 0, SEEK_SET); - CHECK(read(w->fd, &value, 1)); - if(value != w->value) { - printf("GPIO%d: %c -> %c\n", w->gpio, w->value, value); - w->value = value; - } - } - } while (1); - -cleanup: - if(error != 0) { - fprintf(stderr, "Error %d: %s\n", errno, strerror(errno)); - error = 1; - } - return error; -} diff --git a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/hexfile.py b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/hexfile.py deleted file mode 100644 index c484fdf..0000000 --- a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/hexfile.py +++ /dev/null @@ -1,174 +0,0 @@ -# The MIT License (MIT) -# ===================== -# -# Copyright (c) 2014 Ryan Sturmer -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -# https://github.com/ryansturmer/hexfile/blob/master/hexfile/core.py - -import itertools - -def short(msb,lsb): - return (msb<<8) | lsb - -class HexFile(object): - def __init__(self, segments): - self.segments = segments - - def __getitem__(self, val): - if isinstance(val, slice): - address = val.start - else: - address = val - - for segment in self.segments: - if address in segment: - return segment[val] - - raise IndexError('No segment contains address 0x%x' % address) - - def __len__(self): - return sum(map(len, self.segments)) - - @property - def size(self): - return len(self) - - def __iter__(self): - return itertools.chain(*self.segments) - - @staticmethod - def load(filename): - segments = [Segment(0)] - - with open(filename) as fp: - lines = fp.readlines() - - extended_linear_address = 0 - current_address = 0 - end_of_file = False - - lineno = 0 - for line in lines: - lineno += 1 - line = line.strip(); - if not line.startswith(':'): - continue - - if end_of_file: - raise Exception("Record found after end of file on line %d" % lineno) - - bytes = [int(line[i:i+2], 16) for i in range(1,len(line), 2)] - byte_count = bytes[0] - address = short(*bytes[1:3]) - record_type = bytes[3] - checksum = bytes[-1] - data = bytes[4:-1] - computed_checksum = ((1 << 8)-(sum(bytes[:-1]) & 0xff)) & 0xff - - if(computed_checksum != checksum): - raise Exception("Record checksum doesn't match on line %d" % lineno) - - if record_type == 0: - if byte_count == len(data): - current_address = (address | extended_linear_address) - have_segment = False - for segment in segments: - if segment.end_address == current_address: - segment.data.extend(data) - have_segment = True - break - if not have_segment: - segments.append(Segment(current_address, data)) - else: - raise Exception("Data record reported size does not match actual size on line %d" % lineno) - elif record_type == 1: - end_of_file = True - elif record_type == 4: - if byte_count != 2 or len(data) != 2: - raise Exception("Byte count misreported in extended linear address record on line %d" % lineno) - extended_linear_address = short(*data) << 16 - - else: - raise Exception("Unknown record type: %s" % record_type) - return HexFile(segments) - - def pretty_string(self, stride=16): - retval = [] - for segment in self.segments: - retval.append('Segment @ 0x%08x (%d bytes)' % (segment.start_address, segment.size)) - retval.append(segment.pretty_string(stride=stride)) - retval.append('') - return '\n'.join(retval) - -def load(filename): - return HexFile.load(filename) - -class Segment(object): - def __init__(self, start_address, data = None): - self.start_address = start_address - self.data = data or [] - - def pretty_string(self, stride=16): - retval = [] - addresses = self.addresses - ranges = [addresses[i:i+stride] for i in range(0, self.size, stride)] - for r in ranges: - retval.append('%08x ' % r[0] + ' '.join(['%02x' % self[addr] for addr in r])) - return '\n'.join(retval) - - def __str__(self): - return '<%d byte segment @ 0x%08x>' % (self.size, self.start_address) - def __repr__(self): - return str(self) - - @property - def end_address(self): - return self.start_address + len(self.data) - - @property - def size(self): - return len(self.data) - - def __contains__(self, address): - return address >= self.start_address and address < self.end_address - - def __getitem__(self, address): - if isinstance(address, slice): - if address.start not in self or address.stop-1 not in self: - raise IndexError('Address out of range for this segment') - else: - d = self.data[address.start-self.start_address:address.stop-self.start_address:address.step] - start_address = address.start + self.start_address - return Segment(start_address, d) - else: - if not address in self: - raise IndexError("Address 0x%x is not in this segment" % address) - return self.data[address-self.start_address] - - @property - def addresses(self): - return range(self.start_address, self.end_address) - - def __len__(self): - return len(self.data) - - def __iter__(self): - return iter(self.data) diff --git a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbus.c b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbus.c deleted file mode 100644 index 8fb0835..0000000 --- a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbus.c +++ /dev/null @@ -1,352 +0,0 @@ -/* - * Copyright 2014-present Facebook. All Rights Reserved. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <time.h> -#include "modbus.h" -#include <termios.h> -#include <unistd.h> -#include <fcntl.h> -#include <stdlib.h> -#include <stdint.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> -#include <sys/ioctl.h> -#include <sched.h> -#include <pthread.h> - -int verbose = 0; - -#define TIOCSERWAITTEMT 0x5499 -int waitfd(int fd) { - int loops = 0; - ioctl(fd, TIOCSERWAITTEMT, DEFAULT_GPIO); - while(1) { - int lsr; - int ret = ioctl(fd, TIOCSERGETLSR, &lsr); - if(ret == -1) { - fprintf(stderr, "Error checking ioctl: %s\n", strerror(errno)); - break; - } - if(lsr & TIOCSER_TEMT) break; - // never should hit this with new ioctl - loops++; - } - return loops; -} - -void gpio_on(int fd) { - lseek(fd, 0, SEEK_SET); - write(fd, "1", 1); -} - -void gpio_off(int fd) { - lseek(fd, 0, SEEK_SET); - write(fd, "0", 1); -} - -void decode_hex_in_place(char* buf, size_t* len) { - for(int i = 0; i < *len; i+=2) { - sscanf(buf + i, "%2hhx", buf + (i / 2)); - } - *len = *len / 2; -} - -void append_modbus_crc16(char* buf, size_t* len) { - uint16_t crc = modbus_crc16(buf, *len); - dbg("[*] Append Modbus CRC16 %04x\n", crc); - buf[(*len)++] = crc >> 8; - buf[(*len)++] = crc & 0x00FF; -} - -void print_hex(FILE* f, char* buf, size_t len) { - for(int i = 0; i < len; i++) - fprintf(f, "%02x ", buf[i]); -} - -size_t read_wait(int fd, char* dst, size_t maxlen, int mdelay_us) { - fd_set fdset; - struct timeval timeout; - char read_buf[16]; - size_t read_size = 0; - size_t pos = 0; - memset(dst, 0, maxlen); - while(pos < maxlen) { - FD_ZERO(&fdset); - FD_SET(fd, &fdset); - timeout.tv_sec = 0; - timeout.tv_usec = mdelay_us; - int rv = select(fd + 1, &fdset, NULL, NULL, &timeout); - if(rv == -1) { - perror("select()"); - } else if (rv == 0) { - break; - } - read_size = read(fd, read_buf, 16); - if(read_size < 0) { - if(errno == EAGAIN) continue; - fprintf(stderr, "read error: %s\n", strerror(errno)); - exit(1); - } - if((pos + read_size) <= maxlen) { - memcpy(dst + pos, read_buf, read_size); - pos += read_size; - } else { - return pos; - fprintf(stderr, "Response buffer overflowed!\n"); - } - } - return pos; -} - -/* From libmodbus, https://github.com/stephane/libmodbus - * Under LGPL. */ -/* Table of CRC values for high-order byte */ -static const uint8_t table_crc_hi[] = { - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, - 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, - 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, - 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, - 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, - 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, - 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, - 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, - 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, - 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, - 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, - 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, - 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, - 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, - 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, - 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, - 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, - 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, - 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, - 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 -}; - -/* Table of CRC values for low-order byte */ -static const uint8_t table_crc_lo[] = { - 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, - 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, - 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, - 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, - 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4, - 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, - 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, - 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, - 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, - 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, - 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, - 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, - 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, - 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, - 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, - 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, - 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, - 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, - 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, - 0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, - 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, - 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, - 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, - 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, - 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, - 0x43, 0x83, 0x41, 0x81, 0x80, 0x40 -}; - -uint16_t modbus_crc16(char* buffer, size_t buffer_length) { - uint8_t crc_hi = 0xFF; /* high CRC byte initialized */ - uint8_t crc_lo = 0xFF; /* low CRC byte initialized */ - unsigned int i; /* will index into CRC lookup */ - - /* pass through message buffer */ - while (buffer_length--) { - i = crc_hi ^ *((uint8_t*)(buffer++)); /* calculate the CRC */ - crc_hi = crc_lo ^ table_crc_hi[i]; - crc_lo = table_crc_lo[i]; - } - - return (crc_hi << 8 | crc_lo); -} - - -double ts_diff (struct timespec* begin, struct timespec* end) { - return 1000.0 * (end->tv_sec) + (1e-6 * end->tv_nsec) - - (1000.0 * (begin->tv_sec) + (1e-6 * begin->tv_nsec)); -} - -static long success = 0; -static long crcfail = 0; -static long timeout = 0; -static long stat_wait = 0; - -int modbuscmd(modbus_req *req) { - int error = 0; - struct termios tio; - char modbus_cmd[req->cmd_len + 2]; - size_t cmd_len = req->cmd_len; - - if (verbose) - fprintf(stderr, "[*] Setting TTY flags!\n"); - memset(&tio, 0, sizeof(tio)); - // CREAD should be left *off* until we've confirmed THRE - // to avoid catching false character starts - cfsetspeed(&tio,B19200); - tio.c_cflag |= PARENB; - tio.c_cflag |= CLOCAL; - tio.c_cflag |= CS8; - tio.c_iflag |= INPCK; - tio.c_cc[VMIN] = 1; - tio.c_cc[VTIME] = 0; - CHECK(tcsetattr(req->tty_fd,TCSANOW,&tio)); - - memcpy(modbus_cmd, req->modbus_cmd, cmd_len); - append_modbus_crc16(modbus_cmd, &cmd_len); - - // print command as sent - if (verbose) { - fprintf(stderr, "Will send: "); - print_hex(stderr, modbus_cmd, cmd_len); - fprintf(stderr, "\n"); - } - - dbg("[*] Writing!\n"); - - // hoped adding the ioctl to do the switching would have alleviated the - // need to do SCHED_FIFO, but we still get preempted between the write and - // ioctl syscalls w/o it often enough to break f/w updates. - struct sched_param sp; - sp.sched_priority = 50; - int policy = SCHED_FIFO; - CHECKP(sched, pthread_setschedparam(pthread_self(), policy, &sp)); - // gpio on, write, wait, gpio off - gpio_on(req->gpio_fd); - struct timespec write_begin; - struct timespec wait_begin; - struct timespec wait_end; - struct timespec read_end; - clock_gettime(CLOCK_MONOTONIC_RAW, &write_begin); - write(req->tty_fd, modbus_cmd, cmd_len); - clock_gettime(CLOCK_MONOTONIC_RAW, &wait_begin); - int waitloops = waitfd(req->tty_fd); - clock_gettime(CLOCK_MONOTONIC_RAW, &wait_end); - gpio_off(req->gpio_fd); - sp.sched_priority = 0; - // Enable UART read - tio.c_cflag |= CREAD; - CHECK(tcsetattr(req->tty_fd,TCSANOW,&tio)); - policy = SCHED_OTHER; - CHECKP(sched, pthread_setschedparam(pthread_self(), policy, &sp)); - - dbg("[*] waitfd loops: %d\n", waitloops); - dbg("[*] reading any response...\n"); - // Read back response - size_t mb_pos = 0; - memset(req->dest_buf, 0, req->dest_limit); - if(req->expected_len == 0) { - req->expected_len = req->dest_limit; - } - if(req->expected_len > req->dest_limit) { - return -1; - } - mb_pos = read_wait(req->tty_fd, req->dest_buf, req->expected_len, req->timeout); - clock_gettime(CLOCK_MONOTONIC_RAW, &read_end); - req->dest_len = mb_pos; - if(mb_pos >= 4) { - uint16_t crc = modbus_crc16(req->dest_buf, mb_pos - 2); - dbg("Modbus response CRC: %04X\n ", crc); - if((req->dest_buf[mb_pos - 2] == (crc >> 8)) && - (req->dest_buf[mb_pos - 1] == (crc & 0x00FF))) { - dbg("CRC OK!\n"); - } else { - dbg("BAD CRC :(\n"); - fprintf(stderr, "bad crc timings:"); - fprintf(stderr, " write: %.2f ms", ts_diff(&write_begin, &wait_begin)); - fprintf(stderr, " wait: %.2f ms", ts_diff(&wait_begin, &wait_end)); - fprintf(stderr, " read: %.2f ms\n", ts_diff(&wait_end, &read_end)); - if(!req->scan) { - crcfail++; - } - if(verbose) { - print_hex(stderr, req->dest_buf, mb_pos); - } - return MODBUS_BAD_CRC; - } - } else { - fprintf(stderr, "timeout timings:"); - fprintf(stderr, " write: %.2f ms", ts_diff(&write_begin, &wait_begin)); - fprintf(stderr, " wait: %.2f ms", ts_diff(&wait_begin, &wait_end)); - fprintf(stderr, " wait: %d iters", waitloops); - fprintf(stderr, " read: %.2f ms\n", ts_diff(&wait_end, &read_end)); - dbg("No response :(\n"); - if(!req->scan) { - timeout++; - } - return MODBUS_RESPONSE_TIMEOUT; - } - -cleanup: - if(error != 0) { - error = -1; - fprintf(stderr, "%s\n", strerror(errno)); - } else { - //fprintf(stderr, "success, timings:"); - //fprintf(stderr, " write: %.2f ms", ts_diff(&write_begin, &wait_begin)); - //fprintf(stderr, " wait: %.2f ms", ts_diff(&wait_begin, &wait_end)); - //fprintf(stderr, " read: %.2f ms -- ", ts_diff(&wait_end, &read_end)); - if(stat_wait == 0 && !req->scan) { - fprintf(stderr, "success: %.2f%% crcfail %.2f%%, timeout %.2f%%\n", - ((double) 100.0 * success / (success + crcfail + timeout)), - ((double) 100.0 * crcfail / (success + crcfail + timeout)), - ((double) 100.0 * timeout / (success + crcfail + timeout))); - stat_wait = 1000; - fprintf(stderr, "success timings:"); - fprintf(stderr, " write: %.2f ms", ts_diff(&write_begin, &wait_begin)); - fprintf(stderr, " wait: %.2f ms", ts_diff(&wait_begin, &wait_end)); - fprintf(stderr, " wait: %d iters", waitloops); - fprintf(stderr, " read: %.2f ms\n", ts_diff(&wait_end, &read_end)); - } else if (!req->scan) { - stat_wait--; - } - if(!req->scan) { - success++; - } - } - return 0; -} - -const char* modbus_strerror(int mb_err) { - if (mb_err < 0) { - mb_err = -mb_err; - } - switch(mb_err) { - case 4: - return "timed out"; - case 5: - return "crc check failed"; - default: - return "unknown"; - } -} diff --git a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbus.h b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbus.h deleted file mode 100644 index 1354feb..0000000 --- a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbus.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2014-present Facebook. All Rights Reserved. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef MODBUS_H_ -#define MODBUS_H_ -#include <stddef.h> -#include <stdint.h> -#include <stdio.h> -uint16_t modbus_crc16(char* buffer, size_t length); - -#define DEFAULT_TTY "/dev/ttyS3" -#define DEFAULT_GPIO 45 - -extern int verbose; -#define dbg(...) if(verbose) { fprintf(stderr, __VA_ARGS__); } -#define log(...) { fprintf(stderr, __VA_ARGS__); } - -#define CHECK(expr) { int _check = expr; if((_check) < 0) { \ - error = _check; \ - goto cleanup; \ -} } -#define CHECKP(name, expr) { int _check = expr; if((_check) < 0) { \ - error = _check; \ - perror(#name); \ - goto cleanup; \ -} } -#define BAIL(...) { \ - fprintf(stderr, __VA_ARGS__); \ - fflush(stderr); \ - error = -1; \ - goto cleanup; \ -} - -int waitfd(int fd); -void gpio_on(int fd); -void gpio_off(int fd); -void decode_hex_in_place(char* buf, size_t* len); -void append_modbus_crc16(char* buf, size_t* len); -void print_hex(FILE* f, char* buf, size_t len); - -// Read until maxlen bytes or no bytes in mdelay_us microseconds -size_t read_wait(int fd, char* dst, size_t maxlen, int mdelay_us); - - -typedef struct _modbus_req { - int tty_fd; - int gpio_fd; - const char *modbus_cmd; - size_t cmd_len; - int timeout; - size_t expected_len; - char *dest_buf; - size_t dest_limit; - size_t dest_len; - int scan; -} modbus_req; - -int modbuscmd(modbus_req *req); -// Modbus errors - -#define MODBUS_RESPONSE_TIMEOUT -4 -#define MODBUS_BAD_CRC -5 - -const char* modbus_strerror(int mb_err); - -// Modbus constants -#define MODBUS_READ_HOLDING_REGISTERS 3 - - -#endif diff --git a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbuscmd.c b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbuscmd.c deleted file mode 100644 index 78f62a1..0000000 --- a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbuscmd.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright 2014-present Facebook. All Rights Reserved. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <errno.h> -#include <fcntl.h> -#include <getopt.h> -#include <sched.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <sys/ioctl.h> -#include <sys/socket.h> -#include <sys/types.h> -#include <sys/un.h> -#include "modbus.h" -#include "rackmond.h" - -void usage() { - fprintf(stderr, - "modbuscmd [-v] [-t <timeout in ms>] [-x <expected response length>] modbus_command\n" - "\tmodbus command should be specified in hex\n" - "\teg:\ta40300000008\n" - "\tif an expected response length is provided, modbuscmd will stop receving and check crc immediately " - "after receiving that many bytes\n"); - exit(1); -} - - -int main(int argc, char **argv) { - int error = 0; - char *modbus_cmd = NULL; - size_t cmd_len = 0; - int expected = 0; - uint32_t timeout = 0; - verbose = 0; - rackmond_command *cmd = NULL; - char *response = NULL; - int clisock; - uint16_t response_len_actual; - struct sockaddr_un rackmond_addr; - - int opt; - while((opt = getopt(argc, argv, "w:x:t:g:v")) != -1) { - switch (opt) { - case 'x': - expected = atoi(optarg); - break; - case 't': - timeout = atol(optarg); - break; - case 'v': - verbose = 1; - break; - default: - usage(); - break; - } - } - if(optind < argc) { - modbus_cmd = argv[optind]; - } - if(modbus_cmd == NULL) { - usage(); - } - - //convert hex to bytes - cmd_len = strlen(modbus_cmd); - if(cmd_len < 4) { - fprintf(stderr, "Modbus command too short!\n"); - exit(1); - } - decode_hex_in_place(modbus_cmd, &cmd_len); - cmd = malloc(sizeof(rackmond_command) + cmd_len); - cmd->type = COMMAND_TYPE_RAW_MODBUS; - cmd->raw_modbus.length = cmd_len; - cmd->raw_modbus.custom_timeout = timeout; - memcpy(cmd->raw_modbus.data, modbus_cmd, cmd_len); - cmd->raw_modbus.expected_response_length = expected; - response = malloc(expected ? expected : 1024); - uint16_t wire_cmd_len = sizeof(rackmond_command) + cmd_len; - - clisock = socket(AF_UNIX, SOCK_STREAM, 0); - CHECKP(socket, clisock); - rackmond_addr.sun_family = AF_UNIX; - strcpy(rackmond_addr.sun_path, "/var/run/rackmond.sock"); - int addr_len = strlen(rackmond_addr.sun_path) + sizeof(rackmond_addr.sun_family); - CHECKP(connect, connect(clisock, (struct sockaddr*) &rackmond_addr, addr_len)); - CHECKP(send, send(clisock, &wire_cmd_len, sizeof(wire_cmd_len), 0)); - CHECKP(send, send(clisock, cmd, wire_cmd_len, 0)); - CHECKP(recv, recv(clisock, &response_len_actual, sizeof(response_len_actual), 0)); - if(response_len_actual == 0) { - uint16_t errcode = 0; - CHECKP(recv, recv(clisock, &errcode, sizeof(errcode), 0)); - fprintf(stderr, "modbus error: %d (%s)\n", errcode, modbus_strerror(errcode)); - error = 1; - goto cleanup; - } - CHECKP(recv, recv(clisock, response, response_len_actual, 0)); - if(error == 0) { - printf("Response: "); - print_hex(stdout, response, response_len_actual); - printf("\n"); - } -cleanup: - free(cmd); - free(response); - if(error != 0) { - if(errno != 0) { - fprintf(stderr, "errno err: %s\n", strerror(errno)); - } - error = 1; - } - return error; -} diff --git a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbussim.c b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbussim.c deleted file mode 100644 index e276501..0000000 --- a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbussim.c +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright 2014-present Facebook. All Rights Reserved. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <termios.h> -#include <unistd.h> -#include <fcntl.h> -#include <stdlib.h> -#include <stdint.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> -#include <sys/ioctl.h> -#include <getopt.h> -#include "modbus.h" - -void usage() { - fprintf(stderr, - "modbussim [-v] [-t <tty>] [-g <gpio>] modbus_request modbus_reply\n" - "\ttty defaults to %s\n" - "\tgpio defaults to %d\n" - "\tmodbus request/reply should be specified in hex\n" - "\teg:\ta40300000008\n", - DEFAULT_TTY, DEFAULT_GPIO); - exit(1); -} - -int main(int argc, char **argv) { - int error = 0; - int fd; - struct termios tio; - char gpio_filename[255]; - int gpio_fd = 0; - int gpio_n = DEFAULT_GPIO; - char *tty = DEFAULT_TTY; - char *modbus_cmd = NULL; - char *modbus_reply = NULL; - size_t cmd_len = 0; - size_t reply_len = 0; - verbose = 0; - - int opt; - while((opt = getopt(argc, argv, "t:g:v"))) { - if (opt == -1) break; - switch (opt) { - case 't': - tty = optarg; - break; - case 'g': - gpio_n = atoi(optarg); - break; - case 'v': - verbose = 1; - break; - default: - usage(); - break; - } - } - if(optind < argc) { - modbus_cmd = argv[optind++]; - modbus_reply = argv[optind++]; - } - if(modbus_cmd == NULL || modbus_reply == NULL) { - usage(); - } - - if (verbose) - fprintf(stderr, "[*] Opening TTY\n"); - fd = open(tty, O_RDWR | O_NOCTTY); - CHECK(fd); - - if (verbose) - fprintf(stderr, "[*] Opening GPIO %d\n", gpio_n); - snprintf(gpio_filename, 255, "/sys/class/gpio/gpio%d/value", gpio_n); - gpio_fd = open(gpio_filename, O_WRONLY | O_SYNC); - CHECK(gpio_fd); - - if (verbose) - fprintf(stderr, "[*] Setting TTY flags!\n"); - memset(&tio, 0, sizeof(tio)); - cfsetspeed(&tio,B19200); - tio.c_cflag |= PARENB; - tio.c_cflag |= CLOCAL; - tio.c_cflag |= CS8; - tio.c_iflag |= INPCK; - tio.c_cc[VMIN] = 1; - tio.c_cc[VTIME] = 0; - CHECK(tcsetattr(fd,TCSANOW,&tio)); - - //convert hex to bytes - cmd_len = strlen(modbus_cmd); - if(cmd_len < 2) { - fprintf(stderr, "Command too short!\n"); - exit(1); - } - decode_hex_in_place(modbus_cmd, &cmd_len); - append_modbus_crc16(modbus_cmd, &cmd_len); - if (verbose) { - fprintf(stderr, "expect: "); - print_hex(stderr, modbus_cmd, cmd_len); - fprintf(stderr, "\n"); - } - reply_len = strlen(modbus_reply); - decode_hex_in_place(modbus_reply, &reply_len); - append_modbus_crc16(modbus_reply, &reply_len); - // print full expected reply - if (verbose) { - fprintf(stderr, "reply: "); - print_hex(stderr, modbus_reply, reply_len); - fprintf(stderr, "\n"); - } - - // Enable UART read - tio.c_cflag |= CREAD; - CHECK(tcsetattr(fd,TCSANOW,&tio)); - gpio_off(gpio_fd); - - if(verbose) - fprintf(stderr, "[*] Wait for matching command...\n"); - - char modbus_buf[255]; - size_t mb_pos; -wait_for_command: - mb_pos = read_wait(fd, modbus_buf, sizeof(modbus_buf), 30000); - if(mb_pos >= 4) { - printf("Received: "); - print_hex(stdout, modbus_buf, mb_pos); - uint16_t crc = modbus_crc16(modbus_buf, mb_pos - 2); - if((modbus_buf[mb_pos - 2] == (crc >> 8)) && - (modbus_buf[mb_pos - 1] == (crc & 0x00FF))) { - if(verbose) - fprintf(stderr, "CRC OK!\n"); - if(memcmp(modbus_buf, modbus_cmd, cmd_len) == 0) { - fprintf(stderr, "Command matched!\n"); - } else { - fprintf(stderr, "Got modbus cmd that didn't match.\n"); - goto wait_for_command; - } - } else { - fprintf(stderr, "Got data that failed modbus CRC.\n"); - goto wait_for_command; - } - } else { - goto wait_for_command; - } - - - if (verbose) - fprintf(stderr, "[*] Writing reply!\n"); - - // Disable UART read - tio.c_cflag &= ~CREAD; - CHECK(tcsetattr(fd,TCSANOW,&tio)); - // gpio on, write, wait, gpio off - gpio_on(gpio_fd); - write(fd, modbus_reply, reply_len); - waitfd(fd); - gpio_off(gpio_fd); - -cleanup: - if(error != 0) { - error = 1; - fprintf(stderr, "%s\n", strerror(errno)); - } - return error; -} diff --git a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/psu-update-delta.py b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/psu-update-delta.py deleted file mode 100755 index 34a64f8..0000000 --- a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/psu-update-delta.py +++ /dev/null @@ -1,319 +0,0 @@ -#!/usr/bin/env python -from __future__ import print_function - -import os.path -import os -import fcntl -import socket -import struct -import sys -import argparse -import traceback -import json -from tempfile import mkstemp - -import hexfile - - -def auto_int(x): - return int(x, 0) - - -parser = argparse.ArgumentParser() -parser.add_argument('--addr', type=auto_int, required=True, - help="PSU Modbus Address") -parser.add_argument('--statusfile', default=None, - help="Write status to JSON file during process") -parser.add_argument('--rmfwfile', action='store_true', - help="Delete FW file after update completes") -parser.add_argument('file', help="firmware file") - -status = { - 'pid': os.getpid(), - 'state': 'started' -} - -statuspath = None - -def write_status(): - global status - if statuspath is None: - return - tmppath = statuspath + '~' - with open(tmppath, 'wb') as tfh: - tfh.write(json.dumps(status)) - os.rename(tmppath, statuspath) - -def status_state(state): - global status - status['state'] = state - write_status() - -class ModbusTimeout(Exception): - pass - - -class ModbusCRCFail(Exception): - pass - - -class ModbusUnknownError(Exception): - pass - - -class BadMEIResponse(Exception): - pass - - -def rackmon_command(cmd): - srvpath = "/var/run/rackmond.sock" - replydata = [] - if os.path.exists(srvpath): - client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) - client.connect(srvpath) - cmdlen = struct.pack("@H", len(cmd)) - client.send(cmdlen) - client.send(cmd) - while True: - data = client.recv(1024) - if not data: - break - replydata.append(data) - client.close() - return ''.join(replydata) - - -def pause_monitoring(): - COMMAND_TYPE_PAUSE_MONITORING = 0x04 - command = struct.pack("@Hxx", COMMAND_TYPE_PAUSE_MONITORING) - result = rackmon_command(command) - (res_n, ) = struct.unpack("@B", result) - if res_n == 1: - print("Monitoring was already paused when tried to pause") - elif res_n == 0: - print("Monitoring paused") - else: - print("Unknown response pausing monitoring: %d" % res_n) - - -def resume_monitoring(): - COMMAND_TYPE_START_MONITORING = 0x05 - command = struct.pack("@Hxx", COMMAND_TYPE_START_MONITORING) - result = rackmon_command(command) - (res_n, ) = struct.unpack("@B", result) - if res_n == 1: - print("Monitoring was already running when tried to resume") - elif res_n == 0: - print("Monitoring resumed") - else: - print("Unknown response resuming monitoring: %d" % res_n) - - -def modbuscmd(raw_cmd, expected=0, timeout=0): - COMMAND_TYPE_RAW_MODBUS = 1 - send_command = struct.pack("@HxxHHL", - COMMAND_TYPE_RAW_MODBUS, - len(raw_cmd), - expected, - timeout) + raw_cmd - result = rackmon_command(send_command) - if len(result) == 0: - raise ModbusUnknownError() - (resp_len,) = struct.unpack("@H", result[:2]) - if resp_len == 0: - (error, ) = struct.unpack("@H", result[2:4]) - if error == 4: - raise ModbusTimeout() - if error == 5: - raise ModbusCRCFail() - print("Unknown modbus error: " + str(error)) - raise ModbusUnknownError() - return result[2:resp_len] - - -def mei_command(addr, func_code, mei_type=0x64, data=None, timeout=0): - i_data = data - if i_data is None: - i_data = ("\xFF" * 7) - if len(i_data) < 7: - i_data = i_data + ("\xFF" * (7 - len(i_data))) - assert len(i_data) == 7 - command = struct.pack("BBBB", addr, 0x2b, mei_type, func_code) + i_data - return modbuscmd(command, expected=13, timeout=timeout) - - -def enter_bootloader(addr): - try: - print("Entering bootloader...") - mei_command(addr, 0xFB, timeout=4000) - except ModbusTimeout: - print("Enter bootloader timed out (expected.)") - pass - - -def mei_expect(response, addr, data_pfx, error, success_mei_type=0x71): - expected = struct.pack("BBB", addr, 0x2B, success_mei_type) + \ - data_pfx + ("\xFF" * (8 - len(data_pfx))) - if response != expected: - print(error + ", response: " + response.encode('hex')) - raise BadMEIResponse() - - -def start_programming(addr): - print("Send start programming...") - response = mei_command(addr, 0x70, timeout=10000) - mei_expect(response, addr, "\xB0", "Start programming failed") - print("Start programming succeeded.") - - -def get_challenge(addr): - print("Send get seed") - response = mei_command(addr, 0x27, timeout=3000) - expected = struct.pack("BBBB", addr, 0x2B, 0x71, 0x67) - if response[:len(expected)] != expected: - print("Bad response to get seed: " + response.encode('hex')) - raise BadMEIResponse() - challenge = response[len(expected):len(expected) + 4] - print("Got seed: " + challenge.encode('hex')) - return challenge - - -def send_key(addr, key): - print("Send key") - response = mei_command(addr, 0x28, data=key, timeout=3000) - mei_expect(response, addr, "\x68", "Start programming failed") - print("Send key successful.") - - -def delta_seccalckey(challenge): - (seed, ) = struct.unpack(">L", challenge) - for i in range(32): - if seed & 1 != 0: - seed = seed ^ 0xc758a5b6 - seed = (seed >> 1) & 0x7fffffff - seed = seed ^ 0x06854137 - return struct.pack(">L", seed) - - -def verify_flash(addr): - print("Verifying program...") - response = mei_command(addr, 0x76, timeout=60000) - mei_expect(response, addr, "\xB6", "Program verification failed") - - -def set_write_address(psu_addr, flash_addr): - # print("Set write address to " + hex(flash_addr)) - data = struct.pack(">LB", flash_addr, 0xEA) - response = mei_command(psu_addr, 0x61, data=data, timeout=3000) - mei_expect(response, psu_addr, "\xA1\xEA", "Set address failed") - - -def write_data(addr, data): - assert(len(data) == 8) - command = struct.pack(">BBB", addr, 0x2b, 0x65) + data - response = modbuscmd(command, expected=13, timeout=3000) - expected = struct.pack(">B", addr) +\ - "\x2b\x73\xf0\xaa\xff\xff\xff\xff\xff\xff" - if response != expected: - print("Bad response to writing data: " + - response.encode('hex')) - raise BadMEIResponse() - - -def send_image(addr, fwimg): - global statuspath - total_chunks = sum([len(s) for s in fwimg.segments]) / 8 - sent_chunks = 0 - for s in fwimg.segments: - if len(s) == 0: - continue - print("Sending " + str(s)) - set_write_address(addr, s.start_address) - for i in xrange(0, len(s), 8): - chunk = s.data[i:i+8] - if len(chunk) < 8: - chunk = chunk + ("\xFF" * (8 - len(chunk))) - sent_chunks += 1 - # dont fill the restapi log with junk - if statuspath is None: - print("\r[%.2f%%] Sending chunk %d of %d..." % - (sent_chunks * 100.0 / total_chunks, - sent_chunks, total_chunks), end="") - sys.stdout.flush() - write_data(addr, str(bytearray(chunk))) - status['flash_progress_percent'] = sent_chunks * 100.0 / total_chunks - write_status() - print("") - - -def reset_psu(addr): - print("Resetting PSU...") - try: - response = mei_command(addr, 0x72, timeout=10000) - except ModbusTimeout: - print("No reply from PSU reset (expected.)") - return - expected = struct.pack(">BBBB", addr, 0x2b, 0x71, 0xb2) +\ - ("\xFF" * 7) - if response != expected: - print("Bad response to unit reset request: " + - response.encode('hex')) - raise BadMEIResponse() - - -def erase_flash(addr): - print("Erasing flash... ") - sys.stdout.flush() - response = mei_command(addr, 0x65, timeout=30000) - expected = struct.pack(">BBBB", addr, 0x2b, 0x71, 0xa5) +\ - ("\xFF" * 7) - if response != expected: - print("Bad response to erasing flash: " + - response.encode('hex')) - raise BadMEIResponse() - - -def update_psu(addr, filename): - status_state('pausing_monitoring') - pause_monitoring() - status_state('parsing_fw_file') - fwimg = hexfile.load(filename) - status_state('bootloader_handshake') - enter_bootloader(addr) - start_programming(addr) - challenge = get_challenge(addr) - send_key(addr, delta_seccalckey(challenge)) - status_state('erase_flash') - erase_flash(addr) - status_state('flashing') - send_image(addr, fwimg) - status_state('verifying') - verify_flash(addr) - status_state('resetting') - reset_psu(addr) - status_state('done') - - -def main(): - args = parser.parse_args() - global statuspath - statuspath = args.statusfile - print("statusfile %s" % statuspath) - try: - update_psu(args.addr, args.file) - except Exception, e: - print("Firmware update failed") - global status - status['exception'] = traceback.format_exc() - status_state('failed') - resume_monitoring() - if args.rmfwfile: - os.remove(args.file) - sys.exit(1) - resume_monitoring() - if args.rmfwfile: - os.remove(args.file) - sys.exit(0) - -if __name__ == "__main__": - main() diff --git a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/rackmon-config.py b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/rackmon-config.py deleted file mode 100644 index 130f26f..0000000 --- a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/rackmon-config.py +++ /dev/null @@ -1,220 +0,0 @@ -from rackmond import configure_rackmond - -reglist = [ - {"begin": 0x0, #MFR_MODEL - "length": 8}, - {"begin": 0x10, #MFR_DATE - "length": 8}, - {"begin": 0x20, #FB Part # - "length": 8}, - {"begin": 0x30, #HW Revision - "length": 4}, - {"begin": 0x38, #FW Revision - "length": 4}, - {"begin": 0x40, #MFR Serial # - "length": 16}, - {"begin": 0x60, #Workorder # - "length": 4}, - {"begin": 0x68, #PSU Status - "length": 1, - "keep": 10, # 10-sample ring buffer - "flags": 1}, - {"begin": 0x69, #Battery Status - "length": 1, - "keep": 10, # 10-sample ring buffer - "flags": 1}, - {"begin": 0x6B, #BBU Battery Mode - "length": 1, - "keep": 10, # 10-sample ring buffer - "flags": 1}, - {"begin": 0x6C, #BBU Battery Status - "length": 1, - "keep": 10, # 10-sample ring buffer - "flags": 1}, - {"begin": 0x6D, #BBU Cell Voltage 1 - "length": 1, - "keep": 10}, - {"begin": 0x6E, #BBU Cell Voltage 2 - "length": 1, - "keep": 10}, - {"begin": 0x6F, #BBU Cell Voltage 3 - "length": 1, - "keep": 10}, - {"begin": 0x70, #BBU Cell Voltage 4 - "length": 1, - "keep": 10}, - {"begin": 0x71, #BBU Cell Voltage 5 - "length": 1, - "keep": 10}, - {"begin": 0x72, #BBU Cell Voltage 6 - "length": 1, - "keep": 10}, - {"begin": 0x73, #BBU Cell Voltage 7 - "length": 1, - "keep": 10}, - {"begin": 0x74, #BBU Cell Voltage 8 - "length": 1, - "keep": 10}, - {"begin": 0x75, #BBU Cell Voltage 9 - "length": 1, - "keep": 10}, - {"begin": 0x76, #BBU Cell Voltage 10 - "length": 1, - "keep": 10}, - {"begin": 0x77, #BBU Cell Voltage 11 - "length": 1, - "keep": 10}, - {"begin": 0x78, #BBU Cell Voltage 12 - "length": 1, - "keep": 10}, - {"begin": 0x79, #BBU Cell Voltage 13 - "length": 1, - "keep": 10}, - {"begin": 0x7A, #BBU Temp 1 - "length": 1, - "keep": 10}, - {"begin": 0x7B, #BBU Temp 2 - "length": 1, - "keep": 10}, - {"begin": 0x7C, #BBU Temp 3 - "length": 1, - "keep": 10}, - {"begin": 0x7D, #BBU Temp 4 - "length": 1, - "keep": 10}, - {"begin": 0x7E, #BBU Relative State of Charge - "length": 1, - "keep": 10}, - {"begin": 0x7F, #BBU Absolute State of Charge - "length": 1, - "keep": 10}, - {"begin": 0x80, #Input VAC - "length": 1, - "keep": 10}, - {"begin": 0x81, #BBU Battery Voltage - "length": 1, - "keep": 10}, - {"begin": 0x82, #Input Current AC - "length": 1, - "keep": 10}, - {"begin": 0x83, #BBU Battery Current - "length": 1, - "keep": 10}, - {"begin": 0x84, #Battery Voltage - "length": 1, - "keep": 10}, - {"begin": 0x85, #BBU Average Current - "length": 1, - "keep": 10}, - {"begin": 0x86, #Battery Current Output - "length": 1}, - {"begin": 0x87, #BBU Remaining Capacity - "length": 1, - "keep": 10}, - {"begin": 0x88, #Battery Current Input - "length": 1}, - {"begin": 0x89, #BBU Full Charge Capacity - "length": 1, - "keep": 10}, - {"begin": 0x8A, #Output Voltage (main converter) - "length": 1, - "keep": 10}, - {"begin": 0x8B, #BBU Run Time to Empty - "length": 1, - "keep": 10}, - {"begin": 0x8C, #Output Current (main converter) - "length": 1, - "keep": 10}, - {"begin": 0x8D, #BBU Average Time to Empty - "length": 1, - "keep": 10}, - {"begin": 0x8E, #IT Load Voltage Output - "length": 1}, - {"begin": 0x8F, #BBU Charging Current - "length": 1}, - {"begin": 0x90, #IT Load Current Output - "length": 1}, - {"begin": 0x91, #BBU Charging Voltage - "length": 1, - "keep": 10}, - {"begin": 0x92, #Bulk Cap Voltage - "length": 1}, - {"begin": 0x93, #BBU Cycle Count - "length": 1, - "keep": 10}, - {"begin": 0x94, #Input Power - "length": 1, - "keep": 10}, - {"begin": 0x95, #BBU Design Capacity - "length": 1}, - {"begin": 0x96, #Output Power - "length": 1, - "keep": 10}, - {"begin": 0x97, #BBU Design Voltage - "length": 1}, - {"begin": 0x98, #RPM Fan 0 - "length": 1}, - {"begin": 0x99, #BBU At Rate - "length": 1}, - {"begin": 0x9A, #RPM Fan 1 - "length": 1}, - {"begin": 0x9B, #BBU At Rate Time to Full - "length": 1, - "keep": 10}, - {"begin": 0x9C, #BBU At Rate Time to Empty - "length": 1, - "keep": 10}, - {"begin": 0x9D, #BBU At Rate OK - "length": 1, - "keep": 10}, - {"begin": 0x9E, #Temp 0 - "length": 1}, - {"begin": 0x9F, #BBU Temp - "length": 1}, - {"begin": 0xA0, #Temp 1 - "length": 1}, - {"begin": 0xA1, #BBU Max Error - "length": 1}, - {"begin": 0xD0, #General Alarm Status Register - "length": 1}, - {"begin": 0xD1, #PFC Alarm Status Register - "length": 1}, - {"begin": 0xD2, #LLC Alarm Status Register - "length": 1}, - {"begin": 0xD3, #Current Feed Alarm Status Register - "length": 1}, - {"begin": 0xD4, #Auxiliary Alarm Status Register - "length": 1}, - {"begin": 0xD5, #Battery Charger Alarm Status Register - "length": 1}, - {"begin": 0xD7, #Temperature Alarm Status Register - "length": 1}, - {"begin": 0xD8, #Fan Alarm Status Register - "length": 1}, - {"begin": 0xD9, #Communication Alarm Status Register - "length": 1}, - {"begin": 0x106, #BBU Specification Info - "length": 1}, - {"begin": 0x107, #BBU Manufacturer Date - "length": 1}, - {"begin": 0x108, #BBU Serial Number - "length": 1}, - {"begin": 0x109, #BBU Device Chemistry - "length": 2}, - {"begin": 0x10B, #BBU Manufacturer Data - "length": 2}, - {"begin": 0x10D, #BBU Manufacturer Name - "length": 8}, - {"begin": 0x115, #BBU Device Name - "length": 8}, - {"begin": 0x11D, #FB Battery Status - "length": 4}, - {"begin": 0x121, #SoH results - "length": 1}, -] - -def main(): - configure_rackmond(reglist) - -if __name__ == "__main__": - main() diff --git a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/rackmond.c b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/rackmond.c deleted file mode 100644 index cce3ba4..0000000 --- a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/rackmond.c +++ /dev/null @@ -1,637 +0,0 @@ -#include "modbus.h" -#include "rackmond.h" -#include <string.h> -#include <pthread.h> -#include <stdio.h> -#include <fcntl.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <errno.h> -#include <stdlib.h> -#include <unistd.h> -#include <poll.h> -#include <time.h> -#include <stdarg.h> -#include <syslog.h> -#include <signal.h> - -#define MAX_ACTIVE_ADDRS 12 -#define REGISTER_PSU_STATUS 0x68 - -struct _lock_holder { - pthread_mutex_t *lock; - int held; -}; - -#define lock_holder(holder_name, lock_expr) \ - struct _lock_holder holder_name; \ - holder_name.lock = lock_expr; \ - holder_name.held = 0; - -#define lock_take(holder_name) { \ - pthread_mutex_lock(holder_name.lock); \ - holder_name.held = 1; \ -} - -#define lock_release(holder_name) { \ - if(holder_name.held) { \ - pthread_mutex_unlock(holder_name.lock); \ - holder_name.held = 0; \ - } \ -} - -int scanning = 0; - -typedef struct _rs485_dev { - // hold this for the duration of a command - pthread_mutex_t lock; - int tty_fd; - int gpio_fd; -} rs485_dev; - -typedef struct _register_req { - uint16_t begin; - int num; -} register_req; - -typedef struct register_range_data { - monitor_interval* i; - void* mem_begin; - size_t mem_pos; -} register_range_data; - -typedef struct monitoring_data { - uint8_t addr; - register_range_data range_data[1]; -} monitoring_data; - -typedef struct _rackmond_data { - // global rackmond lock - pthread_mutex_t lock; - // number of register read commands to send to each PSU - int num_reqs; - // register read commands (begin+length) - register_req *reqs; - monitoring_config *config; - - uint8_t num_active_addrs; - uint8_t active_addrs[MAX_ACTIVE_ADDRS]; - monitoring_data* stored_data[MAX_ACTIVE_ADDRS]; - FILE *status_log; - - // timeout in nanosecs - int modbus_timeout; - - int paused; - - rs485_dev rs485; -} rackmond_data; - -rackmond_data world; - -char psu_address(int rack, int shelf, int psu) { - int rack_a = ((rack & 3) << 3); - int shelf_a = ((shelf & 1) << 2); - int psu_a = (psu & 3); - return 0xA0 | rack_a | shelf_a | psu_a; -} - -int modbus_command(rs485_dev* dev, int timeout, char* command, size_t len, char* destbuf, size_t dest_limit, size_t expect) { - int error = 0; - lock_holder(devlock, &dev->lock); - modbus_req req; - req.tty_fd = dev->tty_fd; - req.gpio_fd = dev->gpio_fd; - req.modbus_cmd = command; - req.cmd_len = len; - req.dest_buf = destbuf; - req.dest_limit = dest_limit; - req.timeout = timeout; - req.expected_len = expect != 0 ? expect : dest_limit; - req.scan = scanning; - lock_take(devlock); - int cmd_error = modbuscmd(&req); - CHECK(cmd_error); -cleanup: - lock_release(devlock); - if (error >= 0) { - return req.dest_len; - } - - return error; -} - -int read_registers(rs485_dev *dev, int timeout, uint8_t addr, uint16_t begin, uint16_t num, uint16_t* out) { - int error = 0; - // address, function, begin, length in # of regs - char command[sizeof(addr) + 1 + sizeof(begin) + sizeof(num)]; - // address, function, length (1 byte), data (2 bytes per register), crc - // (VLA) - char response[sizeof(addr) + 1 + 1 + (2 * num) + 2]; - command[0] = addr; - command[1] = MODBUS_READ_HOLDING_REGISTERS; - command[2] = begin << 8; - command[3] = begin & 0xFF; - command[4] = num << 8; - command[5] = num & 0xFF; - - int dest_len = - modbus_command( - dev, timeout, - command, sizeof(addr) + 1 + sizeof(begin) + sizeof(num), - response, sizeof(addr) + 1 + 1 + (2 * num) + 2, 0); - CHECK(dest_len); - - if (dest_len >= 5) { - memcpy(out, response + 3, num * 2); - } else { - log("Unexpected short but CRC correct response!\n"); - error = -1; - goto cleanup; - } - if (response[0] != addr) { - log("Got response for addr %02x when expected %02x\n", response[0], addr); - error = -1; - goto cleanup; - } - if (response[2] != (num * 2)) { - log("Got %d register data bytes when expecting %d\n", response[2], (num * 2)); - error = -1; - goto cleanup; - } -cleanup: - return error; -} - -int sub_uint8s(const void* a, const void* b) { - return (*(uint8_t*)a) - (*(uint8_t*)b); -} - -int check_active_psus() { - int error = 0; - lock_holder(worldlock, &world.lock); - lock_take(worldlock); - if (world.paused == 1) { - usleep(1000); - goto cleanup; - } - if (world.config == NULL) { - lock_release(worldlock); - usleep(5000); - goto cleanup; - } - world.num_active_addrs = 0; - - scanning = 1; - //fprintf(stderr, "Begin presence check: "); - for(int rack = 0; rack < 3; rack++) { - for(int shelf = 0; shelf < 2; shelf++) { - for(int psu = 0; psu < 3; psu++) { - char addr = psu_address(rack, shelf, psu); - uint16_t status = 0; - int err = read_registers(&world.rs485, world.modbus_timeout, addr, REGISTER_PSU_STATUS, 1, &status); - if (err == 0) { - world.active_addrs[world.num_active_addrs] = addr; - world.num_active_addrs++; - //fprintf(stderr, "%02x - active (%04x) ", addr, status); - } else { - dbg("%02x - %d; ", addr, err); - } - } - } - } - //its the only stdlib sort - qsort(world.active_addrs, world.num_active_addrs, - sizeof(uint8_t), sub_uint8s); -cleanup: - scanning = 0; - lock_release(worldlock); - return error; -} - -monitoring_data* alloc_monitoring_data(uint8_t addr) { - size_t size = sizeof(monitoring_data) + - sizeof(register_range_data) * world.config->num_intervals; - for(int i = 0; i < world.config->num_intervals; i++) { - monitor_interval *iv = &world.config->intervals[i]; - int pitch = sizeof(uint32_t) + (sizeof(uint16_t) * iv->len); - int data_size = pitch * iv->keep; - size += data_size; - } - monitoring_data* d = calloc(1, size); - if (d == NULL) { - log("Failed to allocate memory for sensor data.\n"); - return NULL; - } - d->addr = addr; - void* mem = d; - mem = mem + (sizeof(monitoring_data) + - sizeof(register_range_data) * world.config->num_intervals); - for(int i = 0; i < world.config->num_intervals; i++) { - monitor_interval *iv = &world.config->intervals[i]; - int pitch = sizeof(uint32_t) + (sizeof(uint16_t) * iv->len); - int data_size = pitch * iv->keep; - d->range_data[i].i = iv; - d->range_data[i].mem_begin = mem; - d->range_data[i].mem_pos = 0; - mem = mem + data_size; - } - return d; -} - -int sub_storeptrs(const void* va, const void *vb) { - //more *s than i like :/ - monitoring_data* a = *(monitoring_data**)va; - monitoring_data* b = *(monitoring_data**)vb; - //nulls to the end - if (b == NULL && a == NULL) { - return 0; - } - if (b == NULL) { - return -1; - } - if (a == NULL) { - return 1; - } - return a->addr - b->addr; -} - -int alloc_monitoring_datas() { - int error = 0; - if (world.config == NULL) { - goto cleanup; - } - qsort(world.stored_data, MAX_ACTIVE_ADDRS, - sizeof(monitoring_data*), sub_storeptrs); - int data_pos = 0; - for(int i = 0; i < world.num_active_addrs; i++) { - uint8_t addr = world.active_addrs[i]; - while(world.stored_data[data_pos] != NULL && - world.stored_data[data_pos]->addr != addr) { - data_pos++; - } - if (world.stored_data[data_pos] == NULL) { - log("Detected PSU at address 0x%02x\n", addr); - //syslog(LOG_INFO, "Detected PSU at address 0x%02x", addr); - world.stored_data[data_pos] = alloc_monitoring_data(addr); - if (world.stored_data[data_pos] == NULL) { - BAIL("allocation failed\n"); - } - //reset search pos after alloc (post-sorted addrs may already be alloc'd, need to check again) - data_pos = 0; - continue; - } - if (world.stored_data[data_pos]->addr == addr) { - continue; - } - BAIL("shouldn't get here!\n"); - } -cleanup: - return error; -} - -void record_data(register_range_data* rd, uint32_t time, uint16_t* regs) { - int n_regs = (rd->i->len); - int pitch = sizeof(time) + (sizeof(uint16_t) * n_regs); - int mem_size = pitch * rd->i->keep; - - memcpy(rd->mem_begin + rd->mem_pos, &time, sizeof(time)); - rd->mem_pos += sizeof(time); - memcpy(rd->mem_begin + rd->mem_pos, regs, n_regs * sizeof(uint16_t)); - rd->mem_pos += n_regs * sizeof(uint16_t); - rd->mem_pos = rd->mem_pos % mem_size; -} - -int fetch_monitored_data() { - int error = 0; - int data_pos = 0; - lock_holder(worldlock, &world.lock); - lock_take(worldlock); - if (world.paused == 1) { - usleep(1000); - goto cleanup; - } - if (world.config == NULL) { - goto cleanup; - } - lock_release(worldlock); - - usleep(1000); // wait a sec btween PSUs to not overload RT scheduling - // threshold - while(world.stored_data[data_pos] != NULL && data_pos < MAX_ACTIVE_ADDRS) { - uint8_t addr = world.stored_data[data_pos]->addr; - //log("readpsu %02x\n", addr); - for(int r = 0; r < world.config->num_intervals; r++) { - register_range_data* rd = &world.stored_data[data_pos]->range_data[r]; - monitor_interval* i = rd->i; - uint16_t regs[i->len]; - int err = read_registers(&world.rs485, - world.modbus_timeout, addr, i->begin, i->len, regs); - if (err) { - log("Error %d reading %02x registers at %02x from %02x\n", - err, i->len, i->begin, addr); - continue; - } - struct timespec ts; - clock_gettime(CLOCK_REALTIME, &ts); - uint32_t timestamp = ts.tv_sec; - if (rd->i->flags & MONITOR_FLAG_ONLY_CHANGES) { - int pitch = sizeof(timestamp) + (sizeof(uint16_t) * i->len); - int lastpos = rd->mem_pos - pitch; - if (lastpos < 0) { - lastpos = (pitch * rd->i->keep) - pitch; - } - if (!memcmp(rd->mem_begin + lastpos + sizeof(timestamp), - regs, sizeof(uint16_t) * i->len) && - memcmp(rd->mem_begin, "\x00\x00\x00\x00", 4)) { - continue; - } - - if (world.status_log) { - time_t rawt; - struct tm* ti; - time(&rawt); - ti = localtime(&rawt); - char timestr[80]; - strftime(timestr, sizeof(timestr), "%b %e %T", ti); - fprintf(world.status_log, - "%s: Change to status register %02x on address %02x. New value: %02x\n", - timestr, i->begin, addr, regs[0]); - fflush(world.status_log); - } - - } - lock_take(worldlock); - record_data(rd, timestamp, regs); - lock_release(worldlock); - } - data_pos++; - } -cleanup: - lock_release(worldlock); - return error; -} - -// check for new psus every N rounds of sensor reads -#define SEARCH_PSUS_EVERY 200 -void* monitoring_loop(void* arg) { - (void) arg; - int until_search = 0; - world.status_log = fopen("/var/log/psu-status.log", "a+"); - while(1) { - if (until_search == 0) { - check_active_psus(); - alloc_monitoring_datas(); - until_search = SEARCH_PSUS_EVERY; - } else { - until_search--; - } - fetch_monitored_data(); - } - return NULL; -} - -int open_rs485_dev(const char* tty_filename, int gpio_num, rs485_dev *dev) { - int error = 0; - int tty_fd, gpio_fd; - char gpio_filename[128]; - dbg("[*] Opening TTY\n"); - tty_fd = open(tty_filename, O_RDWR | O_NOCTTY); - CHECK(tty_fd); - - dbg("[*] Opening GPIO %d\n", gpio_num); - snprintf(gpio_filename, sizeof(gpio_filename), "/sys/class/gpio/gpio%d/value", gpio_num); - gpio_fd = open(gpio_filename, O_WRONLY | O_SYNC); - CHECK(gpio_fd); - - dev->tty_fd = tty_fd; - dev->gpio_fd = gpio_fd; - pthread_mutex_init(&dev->lock, NULL); -cleanup: - return error; -} - -int do_command(int sock, rackmond_command* cmd) { - int error = 0; - lock_holder(worldlock, &world.lock); - switch(cmd->type) { - case COMMAND_TYPE_RAW_MODBUS: - { - uint16_t expected = cmd->raw_modbus.expected_response_length; - int timeout = world.modbus_timeout; - if (cmd->raw_modbus.custom_timeout) { - //ms to us - timeout = cmd->raw_modbus.custom_timeout * 1000; - } - if (expected == 0) { - expected = 1024; - } - char response[expected]; - int response_len = modbus_command( - &world.rs485, timeout, - cmd->raw_modbus.data, cmd->raw_modbus.length, - response, expected, expected); - uint16_t response_len_wire = response_len; - if(response_len < 0) { - uint16_t error = -response_len; - response_len_wire = 0; - send(sock, &response_len_wire, sizeof(uint16_t), 0); - send(sock, &error, sizeof(uint16_t), 0); - break; - } - send(sock, &response_len_wire, sizeof(uint16_t), 0); - send(sock, response, response_len, 0); - break; - } - case COMMAND_TYPE_SET_CONFIG: - { - lock_take(worldlock); - if (world.config != NULL) { - BAIL("rackmond already configured\n"); - } - size_t config_size = sizeof(monitoring_config) + - (sizeof(monitor_interval) * cmd->set_config.config.num_intervals); - world.config = calloc(1, config_size); - memcpy(world.config, &cmd->set_config.config, config_size); - syslog(LOG_INFO, "got configuration"); - lock_release(worldlock); - break; - } - case COMMAND_TYPE_DUMP_DATA_JSON: - { - lock_take(worldlock); - if (world.config == NULL) { - send(sock, "[]", 2, 0); - } else { - struct timespec ts; - clock_gettime(CLOCK_REALTIME, &ts); - uint32_t now = ts.tv_sec; - send(sock, "[", 1, 0); - int data_pos = 0; - while(world.stored_data[data_pos] != NULL && data_pos < MAX_ACTIVE_ADDRS) { - dprintf(sock, "{\"addr\":%d,\"now\":%d,\"ranges\":[", - world.stored_data[data_pos]->addr, now); - for(int i = 0; i < world.config->num_intervals; i++) { - uint32_t time; - register_range_data *rd = &world.stored_data[data_pos]->range_data[i]; - char* mem_pos = rd->mem_begin; - dprintf(sock,"{\"begin\":%d,\"readings\":[", rd->i->begin); - // want to cut the list off early just before - // the first entry with time == 0 - memcpy(&time, mem_pos, sizeof(time)); - for(int j = 0; j < rd->i->keep && time != 0; j++) { - mem_pos += sizeof(time); - dprintf(sock, "{\"time\":%d,\"data\":\"", time); - for(int c = 0; c < rd->i->len * 2; c++) { - dprintf(sock, "%02x", *mem_pos); - mem_pos++; - } - send(sock, "\"}", 2, 0); - memcpy(&time, mem_pos, sizeof(time)); - if (time == 0) { - break; - } - if ((j+1) < rd->i->keep) { - send(sock, ",", 1, 0); - } - } - send(sock, "]}", 2, 0); - if ((i+1) < world.config->num_intervals) { - send(sock, ",", 1, 0); - } - } - data_pos++; - if (data_pos < MAX_ACTIVE_ADDRS && world.stored_data[data_pos] != NULL) { - send(sock, "]},", 3, 0); - } else { - send(sock, "]}", 2, 0); - } - } - send(sock, "]", 1, 0); - } - lock_release(worldlock); - break; - } - case COMMAND_TYPE_PAUSE_MONITORING: - { - lock_take(worldlock); - uint8_t was_paused = world.paused; - world.paused = 1; - send(sock, &was_paused, sizeof(was_paused), 0); - lock_release(worldlock); - break; - } - case COMMAND_TYPE_START_MONITORING: - { - lock_take(worldlock); - uint8_t was_started = !world.paused; - world.paused = 0; - send(sock, &was_started, sizeof(was_started), 0); - lock_release(worldlock); - break; - } - default: - CHECK(-1); - } -cleanup: - lock_release(worldlock); - return error; -} - -typedef enum { - CONN_WAITING_LENGTH, - CONN_WAITING_BODY -} rackmond_connection_state; - -// receive the command as a length prefixed block -// (uint16_t, followed by data) -// this is all over a local socket, won't be doing -// endian flipping, clients should only be local procs -// compiled for the same arch -int handle_connection(int sock) { - int error = 0; - rackmond_connection_state state = CONN_WAITING_LENGTH; - char bodybuf[1024]; - uint16_t expected_len = 0; - struct pollfd pfd; - int recvret = 0; - pfd.fd = sock; - pfd.events = POLLIN | POLLERR | POLLHUP; - // if you don't do anything for a whole second we bail -next: - CHECKP(poll, poll(&pfd, 1, 1000)); - if (pfd.revents & (POLLERR | POLLHUP)) { - goto cleanup; - } - switch(state) { - case CONN_WAITING_LENGTH: - recvret = recv(sock, &expected_len, 2, MSG_DONTWAIT); - if (recvret == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) { - goto next; - } - if (expected_len == 0 || expected_len > sizeof(bodybuf)) { - // bad length; bail - goto cleanup; - } - state = CONN_WAITING_BODY; - goto next; - break; - case CONN_WAITING_BODY: - recvret = recv(sock, &bodybuf, expected_len, MSG_DONTWAIT); - if (recvret == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) { - goto next; - } - CHECK(do_command(sock, (rackmond_command*) bodybuf)); - } -cleanup: - close(sock); - if (error != 0) { - fprintf(stderr, "Warning: possible error handling user connection (%d)\n", error); - } - return 0; -} - -int main(int argc, char** argv) { - if (getenv("RACKMOND_FOREGROUND") == NULL) { - daemon(0, 0); - } - signal(SIGPIPE, SIG_IGN); - int error = 0; - world.paused = 0; - world.modbus_timeout = 300000; - if (getenv("RACKMOND_TIMEOUT") != NULL) { - world.modbus_timeout = atoll(getenv("RACKMOND_TIMEOUT")); - fprintf(stderr, "Timeout from env: %dms\n", - (world.modbus_timeout / 1000)); - } - world.config = NULL; - pthread_mutex_init(&world.lock, NULL); - verbose = getenv("RACKMOND_VERBOSE") != NULL ? 1 : 0; - openlog("rackmond", 0, LOG_USER); - syslog(LOG_INFO, "rackmon/modbus service starting"); - CHECK(open_rs485_dev(DEFAULT_TTY, DEFAULT_GPIO, &world.rs485)); - pthread_t monitoring_thread; - pthread_create(&monitoring_thread, NULL, monitoring_loop, NULL); - struct sockaddr_un local, client; - int sock = socket(AF_UNIX, SOCK_STREAM, 0); - strcpy(local.sun_path, "/var/run/rackmond.sock"); - local.sun_family = AF_UNIX; - int socknamelen = sizeof(local.sun_family) + strlen(local.sun_path); - unlink(local.sun_path); - CHECKP(bind, bind(sock, (struct sockaddr *)&local, socknamelen)); - CHECKP(listen, listen(sock, 5)); - syslog(LOG_INFO, "rackmon/modbus service listening"); - while(1) { - socklen_t clisocklen = sizeof(struct sockaddr_un); - int clisock = accept(sock, (struct sockaddr*) &client, &clisocklen); - CHECKP(accept, clisock); - CHECK(handle_connection(clisock)); - } - -cleanup: - if (error != 0) { - error = 1; - } - return error; -} diff --git a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/rackmond.h b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/rackmond.h deleted file mode 100644 index 2c0e8a0..0000000 --- a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/rackmond.h +++ /dev/null @@ -1,46 +0,0 @@ -#include <stdint.h> - -//would've been nice to have thrift - -// Raw modbus command -// Response is just the raw response data -typedef struct raw_modbus_command { - uint16_t length; - uint16_t expected_response_length; - uint32_t custom_timeout; // 0 for default - char data[1]; -} raw_modbus_command; - -// only store new value if different from most recent -// (for watching changes to status flags registers) -#define MONITOR_FLAG_ONLY_CHANGES 0x1 - -typedef struct monitor_interval { - uint16_t begin; - uint16_t len; - uint16_t keep; // How long of a history to keep? - uint16_t flags; -} monitor_interval; - -typedef struct monitoring_config { - uint16_t num_intervals; - monitor_interval intervals[1]; -} monitoring_config; - -typedef struct set_config_command { - monitoring_config config; -} set_config_command; - -#define COMMAND_TYPE_RAW_MODBUS 0x01 -#define COMMAND_TYPE_SET_CONFIG 0x02 -#define COMMAND_TYPE_DUMP_DATA_JSON 0x03 -#define COMMAND_TYPE_PAUSE_MONITORING 0x04 -#define COMMAND_TYPE_START_MONITORING 0x05 - -typedef struct rackmond_command { - uint16_t type; - union { - raw_modbus_command raw_modbus; - set_config_command set_config; - }; -} rackmond_command; diff --git a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/rackmond.py b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/rackmond.py deleted file mode 100644 index 35dbaa5..0000000 --- a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/rackmond.py +++ /dev/null @@ -1,26 +0,0 @@ -import struct -import socket -import os, os.path - -def configure_rackmond(reglist): - COMMAND_TYPE_SET_CONFIG = 2 - config_command = struct.pack("@HxxH", - COMMAND_TYPE_SET_CONFIG, - len(reglist)) - for r in reglist: - keep = 1 - if "keep" in r: - keep = r["keep"] - flags = 0 - if "flags" in r: - flags = r["flags"] - monitor_interval = struct.pack("@HHHH", r["begin"], r["length"], keep, flags) - config_command += monitor_interval - - config_packet = struct.pack("H", len(config_command)) + config_command - srvpath = "/var/run/rackmond.sock" - if os.path.exists(srvpath): - client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) - client.connect(srvpath) - client.send(config_packet) - diff --git a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/rackmondata.c b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/rackmondata.c deleted file mode 100644 index 391b5be..0000000 --- a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/rackmondata.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2014-present Facebook. All Rights Reserved. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <unistd.h> -#include <sys/socket.h> -#include <sys/types.h> -#include <sys/un.h> -#include "modbus.h" -#include "rackmond.h" - -int main(int argc, char **argv) { - int error = 0; - rackmond_command cmd; - int clisock; - uint16_t wire_cmd_len = sizeof(cmd); - struct sockaddr_un rackmond_addr; - cmd.type = COMMAND_TYPE_DUMP_DATA_JSON; - clisock = socket(AF_UNIX, SOCK_STREAM, 0); - CHECKP(socket, clisock); - rackmond_addr.sun_family = AF_UNIX; - strcpy(rackmond_addr.sun_path, "/var/run/rackmond.sock"); - int addr_len = strlen(rackmond_addr.sun_path) + sizeof(rackmond_addr.sun_family); - CHECKP(connect, connect(clisock, (struct sockaddr*) &rackmond_addr, addr_len)); - CHECKP(send, send(clisock, &wire_cmd_len, sizeof(wire_cmd_len), 0)); - CHECKP(send, send(clisock, &cmd, wire_cmd_len, 0)); - char readbuf[256]; - ssize_t n_read; - while((n_read = read(clisock, readbuf, sizeof(readbuf))) > 0) { - write(1, readbuf, n_read); - } -cleanup: - if(error != 0) { - if(errno != 0) { - fprintf(stderr, "%s\n", strerror(errno)); - } - error = 1; - } - return error; -} diff --git a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/setup-rackmond.sh b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/setup-rackmond.sh deleted file mode 100644 index b592a35..0000000 --- a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/setup-rackmond.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash -# -# Copyright 2014-present Facebook. All Rights Reserved. -# -### BEGIN INIT INFO -# Provides: setup-rackmond -# Required-Start: -# Required-Stop: -# Default-Start: S -# Default-Stop: -# Short-Description: Start Rackmon service -### END INIT INFO - -echo -n "Starting rackmon background service..." -/usr/local/bin/rackmond -echo "done." - -echo -n "Configuring rackmon service..." -PYTHONPATH=/etc python /etc/rackmon-config.py -echo "done." |