Commit 81b13d72 authored by Dimitris Lampridis's avatar Dimitris Lampridis

Merge branch '2-provide-a-mechanism-to-program-an-empty-eeprom' into 'master'

Resolve "Provide a mechanism to program an empty EEPROM"

Closes #2

See merge request be-cem-edl/fec/hardware-modules/rf-att-4cha!1
parents 2cd2e784 345bd7cf
all clean:
make -C lib $@
make -C test $@
......@@ -7,7 +7,7 @@ GIT_VERSION = $(shell git describe --dirty --tags --long)
NAME = oattnusb
LIBNAME = lib$(NAME)
all: lib testprog serial_mod_oau doc
all: lib doc
lib: $(LIBNAME).a $(LIBNAME).so
$(LIBNAME).a: $(OBJS)
......@@ -20,15 +20,8 @@ $(OBJS): $(LIBNAME).h $(LIBNAME)-i.h usb-enum.h
doc:
doxygen oattn.doxy
testprog: LDLIBS += -ludev
testprog: test.o $(LIBNAME).a
$(CC) $(CFLAGS) $^ -o $@ $(LDLIBS) $(LDFLAGS)
serial_mod_oau: LDFLAGS += -lusb-1.0
serial_mod_oau: eeprom.o serial_mod_oau.o
clean:
rm -f *.a *.o *.so testprog usb-enum serial_mod_oau
rm -f *.a *.o *.so
rm -rf html
-include Makefile.install
VERSION = $(shell git describe --dirty --tags --long)
OATTN_ROOT = /acc/local/L867/drv/$(NAME)
DOCROOT = /nfs/cs-ccr-nfsop/nfs1/vol30/local/doc/html/private/coht/doxy/$(NAME)
INSTALL_ROOT = $(OATTN_ROOT)/$(VERSION)
install: doc
install: $(LIBNAME).a $(LIBNAME).so $(NAME)test
install: $(LIBNAME).h usb-enum.h
install:
mkdir -p $(INSTALL_ROOT)/lib
mkdir -p $(INSTALL_ROOT)/include
mkdir -p $(INSTALL_ROOT)/bin
mkdir -p $(INSTALL_ROOT)/doc
ln -s ../pyenv $(INSTALL_ROOT)/pyenv
ln -sf . $(INSTALL_ROOT)/include/$(NAME)
install -m 0775 $(LIBNAME).a $(LIBNAME).so $(INSTALL_ROOT)/lib
install -m 0775 $(NAME)test serial_mod_oau $(INSTALL_ROOT)/bin
install -m 0775 $(NAME)test $(INSTALL_ROOT)/bin
install -m 0775 $(LIBNAME).h usb-enum.h $(INSTALL_ROOT)/include
rsync -rtq html/ $(DOCROOT)/
......@@ -45,13 +45,7 @@ int oau_factory_program_eeprom(unsigned int bus, unsigned int dev, char *serial)
static char ser[64];
char *ptr;
struct ftdi_context *ctx;
long serno;
serno = strtol(serial, &ptr, 10);
if (*ptr != 0 || *serial == 0) {
fprintf(stderr, "invalid serial %s\n", serial);
return -EINVAL;
}
if ((ctx = ftdi_new()) == NULL) {
fprintf(stderr, "cannot init libftdi, exiting\n");
return -ENOMEM;
......@@ -61,40 +55,56 @@ int oau_factory_program_eeprom(unsigned int bus, unsigned int dev, char *serial)
ret = ftdi_usb_open_string(ctx, devbus);
if (ret != 0) {
fprintf(stderr, "cannot open usb device %s\n", devbus);
return -EINVAL;
return -ENODEV;
}
b = libusb_get_bus_number(libusb_get_device(ctx->usb_dev));
d = libusb_get_port_number(libusb_get_device(ctx->usb_dev));
// Read and backup any existing contents
ret = ftdi_read_eeprom(ctx);
if (ret != 0) {
fprintf(stderr, "could not read eeprom of %03x:%03x\n", b, d);
return -ENOENT;
}
ret = ftdi_eeprom_decode(ctx, 1);
if (ret != 0) {
fprintf(stderr, "error %d decoding eeprom of %03x:%03x\n", b, d);
return -ENOENT;
}
ret = ftdi_get_eeprom_buf(ctx, eeprom_raw, sizeof(eeprom_raw));
if (ret != 0) {
fprintf(stderr, "could not read raw eeprom of %03x:%03x\n", b, d);
return -EINVAL;
return -ENOENT;
}
eeprom_backup(eeprom_raw, sizeof(eeprom_raw));
snprintf(ser, sizeof(ser), "HCCAIAD000-CR%06d", serno);
// Ignore all existing data and start from scratch, setting all necessary fields.
// Erasing is also necessary to properly detect the size of the attached EEPROM.
ret = ftdi_eeprom_initdefaults(ctx, NULL, NULL, NULL);
if (ret != 0) {
fprintf(stderr, "could not init eeprom of %03x:%03x\n", b, d);
return -EINVAL;
}
ret = ftdi_erase_eeprom(ctx);
if (ret != 0) {
fprintf(stderr, "could not erase eeprom of %03x:%03x\n", b, d);
return -EIO;
}
snprintf(ser, sizeof(ser), serial);
ret = 0;
ret = ret || ftdi_eeprom_set_strings(ctx, OATTNUSB_MANUFACTURER, OATTNUSB_PRODUCT, ser);
ret = ret || ftdi_set_eeprom_value(ctx, VENDOR_ID, OATTNUSB_VENDOR_ID);
ret = ret || ftdi_set_eeprom_value(ctx, PRODUCT_ID, OATTNUSB_DEVICE_ID);
ret = ret || ftdi_set_eeprom_value(ctx, CHANNEL_A_TYPE, CHANNEL_IS_FIFO);
ret = ret || ftdi_set_eeprom_value(ctx, CHANNEL_B_TYPE, CHANNEL_IS_FIFO);
ret = ret || ftdi_set_eeprom_value(ctx, CHANNEL_A_DRIVER, DRIVER_VCP);
ret = ret || ftdi_set_eeprom_value(ctx, CHANNEL_B_DRIVER, DRIVER_VCP);
// Try to rebuild the binary buffer, back it up and check that it is valid
ret = ret || (ftdi_eeprom_build(ctx) < 0);
eeprom_backup(eeprom_raw, sizeof(eeprom_raw));
ret = ret || ftdi_eeprom_decode(ctx, 1);
if (ret != 0) {
fprintf(stderr, "error building new EEPROM, cowardly refusing to write it\n");
return -EINVAL;
}
ret = ftdi_write_eeprom(ctx);
if (ret == 0) {
fprintf(stderr, "successful EEPROM write, resetting USB device\n");
......@@ -103,6 +113,7 @@ int oau_factory_program_eeprom(unsigned int bus, unsigned int dev, char *serial)
fprintf(stderr, "EEPROM write error, ftdi_write_eeprom returned %d\n", ret);
return -EIO;
}
ftdi_free(ctx);
return 0;
......
......@@ -28,6 +28,12 @@ class DevArray(Structure):
class OattnUsbTest(cmd.Cmd):
VENDOR_ID = 0x1556 # CERN USB Vendor ID
DEVICE_ID = 0x0443 # oau USB Device ID
FTDI_VENDOR_ID = 0x403 # FTDI Vendor ID
FTDI_DEVICE_ID = 0x6010 # FTDI Product ID
attn_values = {
'-40dB' : 0,
'-20dB' : 1,
......@@ -50,7 +56,7 @@ class OattnUsbTest(cmd.Cmd):
self.nchannels = None
self.load_solib()
self.fill_devarray()
self.devices = self.fill_devarray(self.VENDOR_ID, self.DEVICE_ID)
def load_solib(self):
"""try to load attn dyn library from script dir or ../lib."""
......@@ -71,15 +77,15 @@ class OattnUsbTest(cmd.Cmd):
exit()
def fill_devarray(self):
def fill_devarray(self, vid, pid):
self.api.oattnusb_get_devarray.restype = POINTER(DevArray)
self.devarray = self.api.oattnusb_get_devarray(0x1556, 0x0443)
self.devarray = self.api.oattnusb_get_devarray(vid, pid)
ndevs = self.devarray.contents.ndevs
devs = self.devarray.contents.devs
self.devices = []
devices = []
for i in range(ndevs):
dev = devs[i]
self.devices.append({
devices.append({
'lun' : dev.lun,
'busnum' : str(dev.busnum, 'utf8'),
'devnum' : str(dev.devnum, 'utf8'),
......@@ -88,10 +94,10 @@ class OattnUsbTest(cmd.Cmd):
'devno' : str(dev.devno, 'utf8'),
'serial' : str(dev.serial, 'utf8'),
'path' : str(dev.path , 'utf8')})
return devices
def do_list(self, arg):
"""list devices and their access methods."""
self.fill_devarray()
for i, dev in enumerate(self.devices):
print('{}:\tl:{}\tserial:{}\tbusdev:{}/{}\tbusport:{}'.format(i,
dev['lun'], dev['serial'], dev['busnum'], dev['devnum'],
......@@ -182,32 +188,42 @@ class OattnUsbTest(cmd.Cmd):
print('error resetting attenuation in channel {}'.format(ch))
return
def do_serial(self, args):
"""EXPERT: change serial number of board."""
def do_eeprom_program(self, args):
"""EXPERT: program the EEPROM (you will be asked to provide a serial number)."""
try:
bus, dev, serial = [int(arg) for arg in args.split()]
bus, dev = [int(arg) for arg in args.split()]
except ValueError as e:
print('usage: serial bus dev serialno')
print('usage: eeprom_program bus dev')
return
except Exception as e:
raise
for device in self.devices:
if (bus, dev) == (int(device['busnum']), int(device['devnum'])):
print('breaking')
break
else:
print('device bus:{} dev:{} not found'.format(bus, dev))
return
print('WARNING: about to record new serial number {:02d}'
' into dev with old serial: {} at busdev:{}/{}, busport:{}'.format(
# Also check if there could be any unprogrammed devices which
# still have the default FTDI VID/PID
ftdi_devices = self.fill_devarray(self.FTDI_VENDOR_ID, self.FTDI_DEVICE_ID)
for device in ftdi_devices:
if (bus, dev) == (int(device['busnum']), int(device['devnum'])):
break
else:
print('device bus:{} dev:{} not found'.format(bus, dev))
return
serial = input('Please provide the serial number to program: ')
print('WARNING: about to erase and program the EEPROM with new serial number [{}]'
' into dev with old serial: [{}] at busdev: {}/{}, busport: {}'.format(
serial, device['serial'],
device['busnum'], device['devnum'], device['busport']))
if input('are you sure? (yes/N) ') != 'yes':
print('ok, giving up.')
return
self.api.oau_factory_program_eeprom.argtypes = [c_int, c_int, c_char_p]
self.api.oau_factory_program_eeprom(bus, dev, bytes(str(serial), 'ascii'))
print('new serial recorded!')
ret = self.api.oau_factory_program_eeprom(bus, dev, bytes(str(serial), 'ascii'))
if (ret != 0):
print('EEPROM programming error detected')
else:
print('new serial recorded!')
print('quitting, please restart the test program')
return True
......
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern int (* oau_factory_program_eeprom)(unsigned int bus, unsigned int dev, char *serial);
int main(int argc, char *argv[])
{
int ret;
unsigned int bus, dev;
char serial[3] = { 'F', 'F', 0 };
if (argc != 4) {
fprintf(stderr, "usage: %s bus dev serialno\n", argv[0]);
exit(1);
}
bus = strtol(argv[1], NULL, 0);
dev = strtol(argv[2], NULL, 0);
strncpy(serial, argv[3], sizeof(serial));
ret = oau_factory_program_eeprom(bus, dev, serial);
return ret;
}
#include <stdio.h>
#include <unistd.h>
#include "liboattnusb.h"
int main()
{
int fd = oattnusb_open(0);
for(;;)
{
fprintf(stderr,".");
oattnusb_set_relay ( fd, 4, ATT_MINUS_20dB );
sleep(1);
fprintf(stderr,".");
oattnusb_set_relay ( fd, 4, ATT_ZERO_dB );
sleep(1);
fprintf(stderr,".");
oattnusb_set_relay ( fd, 4, ATT_MINUS_40dB );
sleep(1);
}
oattnusb_close(fd);
return 0;
}
......@@ -27,7 +27,7 @@ struct oattnusb_devarray *oattnusb_get_devarray(unsigned int vendor_id, unsigned
{
struct udev *udev = udev_new();
struct udev_enumerate *enumerate = udev_enumerate_new(udev);
struct udev_list_entry *devs, *ptr, *ptr2;
struct udev_list_entry *devs, *ptr;
int found_devs = 0;
char vid[6], did[6];
......@@ -36,22 +36,34 @@ struct oattnusb_devarray *oattnusb_get_devarray(unsigned int vendor_id, unsigned
udev_enumerate_add_match_property(enumerate, "ID_VENDOR_ID", vid);
udev_enumerate_add_match_property(enumerate, "ID_MODEL_ID", did);
udev_enumerate_scan_devices(enumerate);
devs = udev_enumerate_get_list_entry(enumerate);
udev_list_entry_foreach(ptr, devs) {
if (found_devs >= MAX_OUA)
goto out;
const char *path = udev_list_entry_get_name(ptr);
struct udev_device *dev = udev_device_new_from_syspath(udev, path);
struct oattnusb_usb_dev *entry = &usb_dev[found_devs];
strcpy(entry->path, path);
strcpy(entry->busnum, udev_device_get_sysattr_value(dev, "busnum"));
strcpy(entry->devnum, udev_device_get_sysattr_value(dev, "devnum"));
strcpy(entry->devno, udev_device_get_sysattr_value(dev, "dev"));
strcpy(entry->serial, udev_device_get_sysattr_value(dev, "serial"));
strcpy(entry->busport, rindex(entry->path, '/') + 1);
found_devs += 1;
const char *busnum = udev_device_get_sysattr_value(dev, "busnum");
const char *devnum = udev_device_get_sysattr_value(dev, "devnum");
if (busnum && devnum) {
const char *devno = udev_device_get_sysattr_value(dev, "dev");
const char *serial = udev_device_get_sysattr_value(dev, "serial");
struct oattnusb_usb_dev *entry = &usb_dev[found_devs];
strcpy(entry->path, path);
strcpy(entry->busnum, busnum);
strcpy(entry->devnum, devnum);
strcpy(entry->devno, devno);
if (serial) {
strcpy(entry->serial, serial);
}
else {
strcpy(entry->serial, "EMPTY");
}
strcpy(entry->busport, rindex(entry->path, '/') + 1);
found_devs += 1;
}
udev_device_unref(dev);
}
out:
......
-include ../lib/Makefile.ftdi
OBJS = oasis-usb-att-test.o
GIT_VERSION = $(shell git describe --dirty --tags --all --long)
CFLAGS += -I../lib -DGIT_VERSION=\"$(GIT_VERSION)\"
LDFLAGS += -L ../lib
LDLIBS += -loasis-usb-att
all: testprog
testprog: $(OBJS)
gcc -o oasis-usb-att-test $(OBJS) $(LDFLAGS) $(LDLIBS)
clean:
rm -f *.o oasis-usb-att-test
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <math.h>
#include <stdlib.h>
#include "liboasis-usb-att.h"
static char git_version[] = "git_version: " GIT_VERSION;
int device;
int selected_channel;
int relay_register;
int num_channels;
char relay_bit_string[20];
void uint16_to_bit_string(char *s, uint16_t r)
{
uint16_t bitmask;
int i;
bitmask = (1 << 15);
for (i = 0; i < 19; i++) {
s[i] = ' ';
if (i % 5 == 4)
continue;
s[i] = r & bitmask ? '1' : '0';
bitmask >>= 1;
}
s[i] = 0;
}
int get_dB_at_channel (int chan)
{
int chan_db;
chan_db = 3 << ((chan -1) * 4);
chan_db = (chan_db & relay_register) >> ((chan -1) * 4);
if (chan_db == 1)
chan_db = 20;
else if (chan_db == 3)
chan_db = 40;
return chan_db;
}
void print_menu ()
{
int i;
uint16_to_bit_string(relay_bit_string, relay_register);
// printf("\033[2J"); /* clear the screen */
// printf("\033[H"); /* position cursor at top-left corner */
printf("\n--------------------------------------\n");
printf("| OASIS USB Attenuator |\n");
printf("| Test program |\n");
printf("--------------------------------------\n");
printf("\n----> Selected channel is %d\n", selected_channel);
printf("\n----> Relays command register: %08x = [%s]\n",
relay_register, relay_bit_string);
for (i=1; i<=num_channels;i++) {
printf("\n\tChannel %d: %2d dB ", i, get_dB_at_channel(i));
if (i == selected_channel)
printf("[*]");
}
printf("\n\n [0] - Re-read attenuation values\n");
printf("\n [1] - Change current channel\n");
printf("\n [2] - Set attenuation to 20dB\n");
printf("\n [3] - Set attenuation to 40dB\n");
printf("\n [4] - Unset attenuation\n");
printf("\n [q] - Quit test\n");
printf("\n Choose an option: ");
}
int get_register_value (int fd)
{
int value = 0;
int tmp;
int i;
for (i=1; i<=num_channels; i++) {
tmp = oau_att_get_relay(fd, i);
tmp = tmp << 4 * (i-1);
value |= tmp;
}
return value;
}
void change_channel ()
{
char option;
char ch;
/* Manual flush ?? */
while( (ch = fgetc(stdin)) != EOF && ch != '\n' ){}
printf("\nEnter new channel [1-4]: ");
scanf("%c",&option);
if ((option >= '1') && (option <= '4')) {
selected_channel = atoi(&option);
} else {
printf("Invalid channel\n");
}
}
static void print_version(char *pname)
{
printf("%s %s\n", pname, git_version);
printf("%s\n", liboau_att_version_s);
}
int main (int argc, char *argv[])
{
int fd;
char option;
selected_channel = 1;
if (argc != 2)
{
printf("Insufficient number of arguments\n");
printf("\nPlease use: %s <lun_of_the_device>\n", argv[0]);
printf("or: %s -v for version info\n", argv[0]);
exit(-1);
}
if(!strcmp("-v", argv[1])) {
print_version(argv[0]);
exit(0);
}
else
{
device = atoi(argv[1]);
}
if ((fd = oau_att_open(device)) < 0) {
perror ("open failed\n");
return -1;
}
/* Check for channel count*/
num_channels = oau_att_get_nchannels(fd);
if (num_channels < 0) {
printf("Can not get channel count. Exiting...\n");
return -1;
}
do {
relay_register = get_register_value(fd);
print_menu();
scanf("%c", &option);
switch (option) {
case '0':
break;
case '1':
change_channel();
break;
case '2':
oau_att_set_relay(fd, selected_channel, ATT_1);
break;
case '3':
oau_att_set_relay(fd, selected_channel, ATT_2);
break;
case '4':
oau_att_set_relay(fd, selected_channel, ATT_NONE);
break;
default:
if ((option != 'q') && (option != 'Q'))
printf("Unknown option\n");
break;
}
} while ((option != 'q') && (option != 'Q'));
/* That's all folks! */
oau_att_close(fd);
return 1;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment