summaryrefslogtreecommitdiffstats
path: root/meta-facebook/meta-wedge/recipes-wedge/rackmon
diff options
context:
space:
mode:
Diffstat (limited to 'meta-facebook/meta-wedge/recipes-wedge/rackmon')
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/Makefile40
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/gpiowatch.c93
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/hexfile.py174
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbus.c352
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbus.h85
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbuscmd.c131
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbussim.c181
-rwxr-xr-xmeta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/psu-update-delta.py319
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/rackmon-config.py220
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/rackmond.c637
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/rackmond.h46
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/rackmond.py26
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/rackmondata.c58
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/setup-rackmond.sh20
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon_0.1.bb81
15 files changed, 0 insertions, 2463 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."
diff --git a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon_0.1.bb b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon_0.1.bb
deleted file mode 100644
index c7e78c9..0000000
--- a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon_0.1.bb
+++ /dev/null
@@ -1,81 +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
-SUMMARY = "Rackmon Functionality"
-DESCRIPTION = "Rackmon Functionality"
-SECTION = "base"
-PR = "r1"
-LICENSE = "GPLv2"
-LIC_FILES_CHKSUM = "file://modbus.c;beginline=4;endline=16;md5=da35978751a9d71b73679307c4d296ec"
-
-DEPENDS_append = " update-rc.d-native"
-
-SRC_URI = "file://Makefile \
- file://modbuscmd.c \
- file://modbussim.c \
- file://modbus.c \
- file://modbus.h \
- file://gpiowatch.c \
- file://rackmond.c \
- file://rackmond.h \
- file://rackmondata.c \
- file://setup-rackmond.sh \
- file://rackmon-config.py \
- file://rackmond.py \
- file://psu-update-delta.py \
- file://hexfile.py \
- "
-
-S = "${WORKDIR}"
-
-binfiles = "modbuscmd \
- modbussim \
- gpiowatch \
- rackmond \
- rackmondata \
- psu-update-delta.py \
- hexfile.py \
- "
-
-#otherfiles = "README"
-
-pkgdir = "rackmon"
-
-do_install() {
- dst="${D}/usr/local/fbpackages/${pkgdir}"
- bin="${D}/usr/local/bin"
- install -d $dst
- install -d $bin
- for f in ${binfiles}; do
- install -m 755 $f ${dst}/$f
- ln -snf ../fbpackages/${pkgdir}/$f ${bin}/$f
- done
- install -d ${D}${sysconfdir}/init.d
- install -d ${D}${sysconfdir}/rcS.d
- install -m 755 setup-rackmond.sh ${D}${sysconfdir}/init.d/setup-rackmond.sh
- install -m 755 rackmon-config.py ${D}${sysconfdir}/rackmon-config.py
- install -m 755 rackmond.py ${D}${sysconfdir}/rackmond.py
- update-rc.d -r ${D} setup-rackmond.sh start 95 2 3 4 5 .
-}
-
-FBPACKAGEDIR = "${prefix}/local/fbpackages"
-
-FILES_${PN} = "${FBPACKAGEDIR}/rackmon ${prefix}/local/bin ${sysconfdir} "
-
-# Inhibit complaints about .debug directories for the rackmon binaries:
-
-INHIBIT_PACKAGE_DEBUG_SPLIT = "1"
-INHIBIT_PACKAGE_STRIP = "1"
OpenPOWER on IntegriCloud