Commit 030d754c authored by Juan David Gonzalez Cobas's avatar Juan David Gonzalez Cobas

Merge branch 'david-cleanups'

This merges into master the 'mise en forme' of the library
so that it is usable by FESA developers, documented and sporting a
python test program.
parents 2f042d1b a4a31a77
test
*.o
*.a
\ No newline at end of file
*.a
*.so
html/
testprog
all clean:
make -C lib $@
make -C test $@
OBJS = liboasis-usb-att.o
-include Makefile.ftdi
CFLAGS = -I. -DGIT_VERSION="dummy"
OBJS = $(LIBNAME).o usb-enum.o eeprom.o
CFLAGS += -fPIC -g
CFLAGS += -DGIT_VERSION=\"$(GIT_VERSION)\"
GIT_VERSION = $(shell git describe --dirty --tags --long)
NAME = oattnusb
LIBNAME = lib$(NAME)
all: lib testprog
all: lib testprog serial_mod_oau doc
lib: $(LIBNAME).a $(LIBNAME).so
lib: $(OBJS)
ar rc liboasis-usb-att.a $(OBJS)
$(LIBNAME).a: $(OBJS)
ar rc $(LIBNAME).a $(OBJS)
$(LIBNAME).so: LDLIBS += -ludev
$(LIBNAME).so: $(OBJS)
$(CC) $(CFLAGS) -shared -o $@ $^ $(LDFLAGS) $(LDLIBS)
$(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 -rf html
-include Makefile.install
#
# intra2net does not seem to settle into any side of this
# dilemma, so we have to decide for them, see
# http://developer.intra2net.com/mailarchive/html/libftdi/2013/msg00372.html
#
CONFIG = $(shell which libftdi1-config)
ifeq ($(CONFIG),)
CONFIG = $(shell which libftdi-config)
endif
LIBFTDI_INC := $(shell $(CONFIG) --cflags)
LIBFTDI_LIBS := $(shell $(CONFIG) --libs)
CFLAGS += $(LIBFTDI_INC)
LDLIBS += $(LIBFTDI_LIBS)
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 $(LIBNAME).h usb-enum.h $(INSTALL_ROOT)/include
rsync -rtq html/ $(DOCROOT)/
/**
* @file eeprom.c
* @brief Library part that takes care of EEPROM serial number
* @author Tomasz Włostowski
* @author Juan David Gonzalez Cobas
* @date October 17th 2018
*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/time.h>
#include <libusb-1.0/libusb.h>
#include <ftdi.h>
#include "liboattnusb.h"
#include "liboattnusb-i.h"
static void eeprom_backup(unsigned char *eeprom_raw, int sz)
{
static char fname[64];
FILE *f;
struct timeval tv;
gettimeofday(&tv, NULL);
snprintf(fname, sizeof(fname),
"/tmp/eeprom_dump-%10d%06d.bin", tv.tv_sec, tv.tv_usec);
if ((f = fopen(fname, "wb")) != NULL) {
fprintf(stderr, "backing up EEPROM into %s\n", fname);
fwrite(eeprom_raw, sz, 1, f);
fclose(f);
}
}
int oau_factory_program_eeprom(unsigned int bus, unsigned int dev, char *serial)
{
int i;
int ret;
int b, d;
char devbus[16];
static uint8_t eeprom_raw[128];
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;
}
snprintf(devbus, sizeof(devbus), "d:%03d/%03d", bus, dev);
ret = ftdi_usb_open_string(ctx, devbus);
if (ret != 0) {
fprintf(stderr, "cannot open usb device %s\n", devbus);
return -EINVAL;
}
b = libusb_get_bus_number(libusb_get_device(ctx->usb_dev));
d = libusb_get_port_number(libusb_get_device(ctx->usb_dev));
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;
}
eeprom_backup(eeprom_raw, sizeof(eeprom_raw));
snprintf(ser, sizeof(ser), "HCCAIAD000-CR%06d", serno);
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_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");
libusb_reset_device(ctx->usb_dev);
} else {
fprintf(stderr, "EEPROM write error, ftdi_write_eeprom returned %d\n", ret);
return -EIO;
}
ftdi_free(ctx);
return 0;
}
/**
* @file liboattnusb-i.h
*
* @brief OASIS USB Attenuator driver library internal definitions
*
* Copyright (c) 2018 CERN
* @author Tomasz Włostowski <tomasz.wlostowski@cern.ch>
* @author Juan David Gonzalez Cobas <dcobas@cern.ch>
*
* @section license_sec License
* Released under the GPL v2. (and only v2, not any later version)
*/
#ifndef __LIBOATTNUSB_I_H
#define __LIBOATTNUSB_I_H
#define OATTNUSB_VENDOR_ID 0x1556 /* CERN USB Vendor ID */
#define OATTNUSB_DEVICE_ID 0x0443 /* oau USB Device ID */
#define OATTNUSB_FTDI_VENDOR_ID 0x403 /* FTDI Vendor ID */
#define OATTNUSB_FTDI_DEVICE_ID 0x6010 /* FTDI Product ID */
#define OATTNUSB_MANUFACTURER "CERN"
#define OATTNUSB_PRODUCT "OASIS RF Attenuator"
#define OATTNUSB_MAX_HANDLES 16
#define OATTNUSB_NUM_CHANNELS 4
#endif /* __LIBOATTNUSB_I_H */
/**
* @file liboasis-usb-att.c
* @file liboattnusb.c
* @brief Library file for the msatt driver
* @author Tomasz Włostowski
* @date October 17th 2018
......@@ -8,73 +8,81 @@
#include <stdio.h>
#include <errno.h>
#include "liboasis-usb-att.h"
#include <libusb-1.0/libusb.h>
#include <ftdi.h>
#define OAU_VENDOR_ID 0x0403
#define OAU_DEVICE_ID 0x6010
#include "liboattnusb.h"
#include "liboattnusb-i.h"
#include "usb-enum.h"
#define OAU_MAX_HANDLES 16
const char * const liboattnusb_version_s =
"liboattnusb version: " GIT_VERSION;
#define OAU_NUM_CHANNELS 4
const char * const liboau_att_version_s = "liboasis-usb-att version: ";// GIT_VERSION;
struct oau_context {
struct oattnusb_context {
struct ftdi_context *ftdi;
uint8_t relay_state;
};
static int oau_current_handle = 0;
static struct oau_context oau_contexts[OAU_MAX_HANDLES];
static int oattnusb_current_handle = 1;
static struct oattnusb_context oattnusb_contexts[OATTNUSB_MAX_HANDLES];
static struct {
int r1, r2;
} oau_relay_mapping[OAU_NUM_CHANNELS] = {
{ 0, 1 },
{ 2, 3 },
{ 4, 5 },
{ 6, 7 }
} oattnusb_relay_mapping[OATTNUSB_NUM_CHANNELS] = {
{ 0, 1 },
{ 2, 3 },
{ 4, 5 },
{ 6, 7 }
};
int oau_att_open(int lun)
int oattnusb_open(int lun)
{
/* not implemented: ignore lun by the moment */
return -ENOSYS;
}
int oattnusb_open_by_serial(const char *serial)
{
int ret;
if( oau_current_handle >= OAU_MAX_HANDLES )
if( oattnusb_current_handle >= OATTNUSB_MAX_HANDLES )
return -ENOMEM;
struct oau_context *ctx = &oau_contexts[ oau_current_handle ];
int fd = oau_current_handle;
oau_current_handle++;
if ((ctx->ftdi = ftdi_new()) == 0)
{
return -ENOMEM;
}
if ((ret = ftdi_usb_open(ctx->ftdi, OAU_VENDOR_ID, OAU_DEVICE_ID)) < 0)
{
ftdi_free(ctx->ftdi);
return ret;
}
if( (ret = ftdi_set_bitmode(ctx->ftdi, 0xff, BITMODE_BITBANG)) < 0 )
{
struct oattnusb_context *ctx = &oattnusb_contexts[ oattnusb_current_handle ];
int fd = oattnusb_current_handle;
oattnusb_current_handle++;
if ((ctx->ftdi = ftdi_new()) == 0) {
return -ENOMEM;
}
if (serial) {
ret = ftdi_usb_open_desc(ctx->ftdi,
OATTNUSB_VENDOR_ID, OATTNUSB_DEVICE_ID, NULL, serial);
if (ret < 0) {
ftdi_free(ctx->ftdi);
return ret;
}
} else { /* open first, and maybe only, device at hand */
ret = ftdi_usb_open(ctx->ftdi, OATTNUSB_VENDOR_ID, OATTNUSB_DEVICE_ID);
if (ret < 0) {
ftdi_free(ctx->ftdi);
return ret;
}
}
if( (ret = ftdi_set_bitmode(ctx->ftdi, 0xff, BITMODE_BITBANG)) < 0 ) {
ftdi_usb_close( ctx->ftdi );
ftdi_free(ctx->ftdi);
return ret;
return ret;
}
uint8_t pins;
if( (ret = ftdi_read_pins(ctx->ftdi, &pins) ) < 0 )
{
if( (ret = ftdi_read_pins(ctx->ftdi, &pins) ) < 0 ) {
ftdi_usb_close( ctx->ftdi );
ftdi_free(ctx->ftdi);
return ret;
return ret;
}
ctx->relay_state = pins;
......@@ -82,9 +90,9 @@ int oau_att_open(int lun)
return fd;
}
int oau_att_close (int fd)
int oattnusb_close (int fd)
{
struct oau_context *ctx = &oau_contexts[ fd ];
struct oattnusb_context *ctx = &oattnusb_contexts[ fd ];
int ret;
if( (ret = ftdi_usb_close( ctx->ftdi )) < 0 )
......@@ -96,52 +104,50 @@ int oau_att_close (int fd)
return 0;
}
enum oau_att_value_enum oau_att_get_relay (int fd, int channel)
enum oattnusb_value_enum oattnusb_get_relay (int fd, int channel)
{
struct oau_context *ctx = &oau_contexts[ fd ];
struct oattnusb_context *ctx = &oattnusb_contexts[ fd ];
if(channel < 1 || channel > OAU_NUM_CHANNELS)
if(channel < 1 || channel > OATTNUSB_NUM_CHANNELS)
return -EINVAL;
uint8_t r1_mask = 1 << oau_relay_mapping[channel-1].r1;
uint8_t r2_mask = 1 << oau_relay_mapping[channel-1].r2;
uint8_t r1_mask = 1 << oattnusb_relay_mapping[channel-1].r1;
uint8_t r2_mask = 1 << oattnusb_relay_mapping[channel-1].r2;
int r1 = ( ctx->relay_state & r1_mask );
int r2 = ( ctx->relay_state & r2_mask );
if( r1 && !r2 )
return ATT_1;
return ATT_MINUS_20dB;
else if ( r1 && r2 )
return ATT_2;
return ATT_ZERO_dB;
else if ( !r1 && !r2 )
return ATT_NONE;
return ATT_MINUS_40dB;
return ATT_ERR;
}
int oau_att_set_relay (int fd, int channel, enum oau_att_value_enum val)
int oattnusb_set_relay (int fd, int channel, enum oattnusb_value_enum val)
{
struct oau_context *ctx = &oau_contexts[ fd ];
struct oattnusb_context *ctx = &oattnusb_contexts[ fd ];
fprintf(stderr, "att_set_delay fd %d chan %d val %d\n", fd, channel, val);
if(channel < 1 || channel > OAU_NUM_CHANNELS)
if(channel < 1 || channel > OATTNUSB_NUM_CHANNELS)
return -EINVAL;
uint8_t r1_mask = 1 << oau_relay_mapping[channel-1].r1;
uint8_t r2_mask = 1 << oau_relay_mapping[channel-1].r2;
uint8_t r1_mask = 1 << oattnusb_relay_mapping[channel-1].r1;
uint8_t r2_mask = 1 << oattnusb_relay_mapping[channel-1].r2;
switch(val)
{
case ATT_NONE:
case ATT_MINUS_40dB:
ctx->relay_state &= ~(r1_mask | r2_mask);
break;
case ATT_1:
case ATT_MINUS_20dB:
ctx->relay_state &= ~r2_mask;
ctx->relay_state |= r1_mask;
break;
case ATT_2:
case ATT_ZERO_dB:
ctx->relay_state |= r1_mask;
ctx->relay_state |= r2_mask;
break;
......@@ -149,24 +155,29 @@ int oau_att_set_relay (int fd, int channel, enum oau_att_value_enum val)
return -EINVAL;
}
printf("RState %x\n", ctx->relay_state );
int ret = ftdi_write_data(ctx->ftdi, &ctx->relay_state, 1);
if(ret < 0)
return -EIO;
uint8_t pins;
ftdi_read_pins(ctx->ftdi, &pins);
printf("RState2 %x\n", pins );
return 0;
}
int oau_att_get_nchannels(int fd)
int oattnusb_get_nchannels(int fd)
{
return OAU_NUM_CHANNELS;
return OATTNUSB_NUM_CHANNELS;
}
int oattnusb_list_devices(void)
{
int i, devs;
struct oattnusb_devarray *list;
list = oattnusb_get_devarray(OATTNUSB_VENDOR_ID, OATTNUSB_DEVICE_ID);
oattnusb_display_devarray(list);
return 0;
}
/**
* @file liboasis-usb-att.h
* @file liboattnusb.h
*
* @brief OASIS USB Attenuator driver library interface
*
......@@ -15,69 +15,112 @@
*/
#ifndef __LIBOASIS_USB_ATT_H
#define __LIBOASIS_USB_ATT_H
#ifndef __LIBOATTNUSB_H
#define __LIBOATTNUSB_H
#ifdef __cplusplus
extern "C" {
#endif
/** \mainpage OASIS USB attenuator library
*
* \section intro_sec Introduction
*
* To be able to use the library API, you just need to include the
* .liboattnusb.h header file. Linkage requires the flag
* `-loattnusb` and, in addition, `-lftdi1 -ludev`, as these are
* used by the basic library. To wit:
*
* gcc -o test test.c \
* -L /acc/local/L867/drv/oattn/1.0/lib \
* -I/acc/local/L867/drv/oattn/1.0/include \
* -loattnusb -lftdi1 -ludev
*
* In case the static version of the library is preferred, a more
* contorted incantation than the above may be required to
* the static library version in a foolproof manner:
*
* gcc -o test test.c \
* -L /acc/local/L867/drv/oattn/1.0/lib \
* -I/acc/local/L867/drv/oattn/1.0/include \
* -lftdi1 -ludev \
* -Wl,--push-state,-static \
* -loattnusb \
* -Wl,--pop-state
*
* \section api_sec API
*
* The library API is documented in liboattnusb.h
*/
/**
* @enum oau_att_value_enum
* @enum oattnusb_value_enum
* @brief Valid relay values
*
*/
enum oau_att_value_enum {
enum oattnusb_value_enum {
ATT_ERR = -1, /**< Error */
ATT_NONE = 0x0, /**< No attenuation */
ATT_1 = 0x01, /**< Attenuator 1: 20dB */
ATT_2 = 0x03, /**< Attenuator 1+2: 40dB */
ATT_MINUS_40dB = 0x0, /**< -40dB attn (power-on default) */
ATT_MINUS_20dB = 0x01, /**< -20dB attn */
ATT_ZERO_dB = 0x03, /**< 0dB attn */
};
/**
* @brief Open a msatt device
* @brief Open a msatt device by LUN (not implemented)
*
* A board is selected by lun, and a handle is returned for further
* reference to it.
*
* @param lun - LUN of msatt card
* @param lun - logical unit number of USB attenuator
*
* @return >0 - on success, device file descriptor number
*/
int oattnusb_open(int lun);
/**
* @brief Open a msatt device
*
* Open OASIS USB attenuator with given serial number.
*
* @param serial - serial number of USB attenuator
*
* @return >0 - on success, device file descriptor number
*/
int oau_att_open(int lun);
int oattnusb_open_by_serial(const char *serial);
/**
* @brief close a channel handle
*
* @param fd Handle to close
*/
int oau_att_close(int fd);
int oattnusb_close(int fd);
/**
* @brief Get attenuation value for a given channel
*
* Each channel can be on one of these states:
* - No attenuation active (Relay value = 0x0)
* - 20dB attenuation (Relay value = 0x1)
* - 40dB attenuation (Relay value = 0x3)
* Each channel can be in one of these states:
*
* - attenuation -40dB (power-on default) (Relay value = 0x0)
* - attenuation -20dB (Relay value = 0x1)
* - attenuation 0dB (Relay value = 0x3)
*
* @param fd Device handle identifying board
* @param channel Channel [1,2,3,4] on the board to read from
*
* @return ATT_ERR on failure, another oau_att_value_enum value on success
* @return ATT_ERR on failure, another oattnusb_value_enum value on success
*/
enum oau_att_value_enum oau_att_get_relay(int fd, int channel);
enum oattnusb_value_enum oattnusb_get_relay(int fd, int channel);
/**
* @brief Set attenuation value for a given channel
*
* @param fd Device handle identifying board
* @param channel Channel on the board [1,2,3,4]
* @param val Valid oau_att_value_enum relay value
* @param val Valid oattnusb_value_enum relay value
*
* @return Upon successful completion, returns a value other than -1. On failure it returns -1
*/
int oau_att_set_relay(int fd, int channel, enum oau_att_value_enum val);
int oattnusb_set_relay(int fd, int channel, enum oattnusb_value_enum val);
/**
* @brief Gets the number of channels (2 or 4)
......@@ -86,13 +129,12 @@ int oau_att_set_relay(int fd, int channel, enum oau_att_value_enum val);
*
* @return -1 on fail, 2 for MSATTN2 and 4 for MSATTN4
*/
int oau_att_get_nchannels(int fd);
int oattnusb_get_nchannels(int fd);
/* libmsatt version string */
extern const char * const liboau_att_version_s;
extern const char * const liboattnusb_version_s;
#ifdef __cplusplus
}
#endif
#endif /* __LIBOASIS_USB_ATT_H */
#endif /* __LIBOATTNUSB_H */
QUIET = YES
WARN_IF_UNDOCUMENTED = NO
GENERATE_LATEX = NO
PROJECT_NAME = "OASIS USB Attenuator Library"
#!/usr/bin/env python3
# vim: et ts=8 sw=4 sts=4 ai
import cmd
import readline
import os.path
import pdb
from ctypes import *
class Dev(Structure):
_fields_ = [
( 'lun', c_int ),
( 'busnum', c_char * 6 ),
( 'devnum', c_char * 6 ),
( 'portnum', c_char * 6 ),
( 'busport', c_char * 16 ),
( 'devno', c_char * 10 ),
( 'serial', c_char * 48 ),
( 'path', c_char * 256 ),
( 'unused', c_int * 4 ),
]
class DevArray(Structure):
_fields_ = [
( 'ndevs', c_int ),
( 'devs', POINTER(Dev) ),
]
class OattnUsbTest(cmd.Cmd):
attn_values = {
'-40dB' : 0,
'-20dB' : 1,
'0dB' : 3,
}
attn_labels = {
0 : '-40dB',
1 : '-20dB',
3 : '0dB',
}
intro = 'Oasis USB Attenuator CLI. Type "help" or "?" to list commands\n'
prompt = 'oatt> '
def __init__(self):
cmd.Cmd.__init__(self)
self.lun = None
self.fd = None
self.nchannels = None
self.load_solib()
self.fill_devarray()
def load_solib(self):
"""try to load attn dyn library from script dir or ../lib."""
self.solib = './liboattnusb.so'
scriptdir = os.path.dirname(os.path.realpath(__file__))
rootdir = os.path.dirname(scriptdir)
libdir = os.path.join(rootdir, 'lib', self.solib)
self.history = os.path.expanduser('~/.oattnusb_history')
try:
self.api = CDLL(self.solib)
except OSError as e:
pass
try:
self.api = CDLL(libdir)
except OSError as e:
print('cannot load oattn solib, exiting')
exit()
def fill_devarray(self):
self.api.oattnusb_get_devarray.restype = POINTER(DevArray)
self.devarray = self.api.oattnusb_get_devarray(0x1556, 0x0443)
ndevs = self.devarray.contents.ndevs
devs = self.devarray.contents.devs
self.devices = []
for i in range(ndevs):
dev = devs[i]
self.devices.append({
'lun' : dev.lun,
'busnum' : str(dev.busnum, 'utf8'),
'devnum' : str(dev.devnum, 'utf8'),
'portnum' : str(dev.portnum, 'utf8'),
'busport' : str(dev.busport, 'utf8'),
'devno' : str(dev.devno, 'utf8'),
'serial' : str(dev.serial, 'utf8'),
'path' : str(dev.path , 'utf8')})
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'],
dev['busport']))
def do_open(self, arg):
"""open device by serial number."""
try:
serial = self.devices[0]['serial'] if not arg else arg
except IndexError as e:
print('no devices found, cannot open')
return
fd = self.api.oattnusb_open_by_serial(bytes(serial, 'utf8'))
if fd < 0:
print('cannot open device {}'.format(serial))
return
self.fd = fd
self.nchannels = self.read_nchannels()
print('current device: serial {}, fd {}, {} channels'.format(
serial, fd, self.nchannels))
def do_close(self, arg):
"""close connection to current device."""
if self.fd is None:
print('no active connection')
return
err = self.api.oattnusb_close(self.fd)
if err < 0:
print('could not close fd {}'.format(self.fd))
return
self.fd = None
self.nchannels = None
def read_nchannels(self):
err = self.api.oattnusb_get_nchannels(self.fd)
if err < 0:
print('error {} getting number of channels'.format(err))
return
return err
def do_nchannels(self, arg):
"""number of channels of current device."""
if self.nchannels is None:
print('no active connection')
return
print('{} channels'.format(self.nchannels))
def do_get_attn(self, arg):
"""display attenuation value of each channel."""
if self.fd is None:
print('no active connection')
return
for i in range(1, self.nchannels+1):
attn = self.api.oattnusb_get_relay(self.fd, i)
print('ch {}: attn {}'.format(i, self.attn_labels[attn]))
def do_set_attn(self, args):
"""set attenuation value of channel."""
try:
ch, attn = args.strip().split()
ch = int(ch)
attn = self.attn_values[attn]
except ValueError as e:
print('usage: set_attn ch {-40dB|-20dB|0dB}')
print(' ch = 1..{}'.format(self.nchannels))
return
except KeyError as e:
print('invalid attenuation value')
print('usage: set_attn ch {-40dB|-20dB|0dB}')
print(' NB: attenuation labels MUST be literally correct')
return
if self.fd is None:
print('no active connection')
return
err = self.api.oattnusb_set_relay(self.fd, ch, attn);
if err < 0:
print('error setting attenuation {} for channel {}'.format(attn, ch))
return
def do_reset(self, args):
"""reset all channel attns to the default (-40dB)."""
if self.fd is None or self.nchannels is None:
print('no active connection')
return
for ch in range(1, self.nchannels+1):
err = self.api.oattnusb_set_relay(self.fd, ch, self.attn_values['-40dB'])
if err < 0:
print('error resetting attenuation in channel {}'.format(ch))
return
def do_serial(self, args):
"""EXPERT: change serial number of board."""
try:
bus, dev, serial = [int(arg) for arg in args.split()]
except ValueError as e:
print('usage: serial bus dev serialno')
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(
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!')
print('quitting, please restart the test program')
return True
def do_version(self, arg):
"""display software version."""
version = c_char_p.in_dll(self.api, "liboattnusb_version_s")
version = str(version.value, 'utf8')
print(version)
def do_EOF(self, arg):
return True
def my_preloop(self):
try:
readline.read_history_file(self.history)
except FileNotFoundError:
readline.write_history_file(self.history)
def my_postloop(self):
readline.write_history_file(self.history)
# catch Ctrl-C and drop me back into cli
def cmdloop_intr(self, intro=None):
self.my_preloop()
while True:
try:
self.cmdloop()
break
except KeyboardInterrupt as e:
self.intro = None
print('^C')
self.my_postloop()
do_q = do_EOF
do_h = cmd.Cmd.do_help
do_ls = do_list
if __name__ == '__main__':
cli = OattnUsbTest()
cli.cmdloop_intr()
#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 "liboasis-usb-att.h"
#include "liboattnusb.h"
int main()
{
int fd = oau_att_open(0);
int fd = oattnusb_open(0);
for(;;)
{
fprintf(stderr,".");
oau_att_set_relay ( fd, 4, ATT_1 );
oattnusb_set_relay ( fd, 4, ATT_MINUS_20dB );
sleep(1);
fprintf(stderr,".");
oau_att_set_relay ( fd, 4, ATT_2 );
oattnusb_set_relay ( fd, 4, ATT_ZERO_dB );
sleep(1);
fprintf(stderr,".");
oau_att_set_relay ( fd, 4, ATT_NONE );
oattnusb_set_relay ( fd, 4, ATT_MINUS_40dB );
sleep(1);
}
oau_att_close(fd);
oattnusb_close(fd);
return 0;
}
\ No newline at end of file
}
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libudev.h>
#include "usb-enum.h"
#define MAX_OUA 16
void oattnusb_display_devarray(struct oattnusb_devarray *ls)
{
int i;
for (i = 0; i < ls->ndevs; i++) {
struct oattnusb_usb_dev *entry = &ls->devs[i];
printf("%d: busdev:%s:%s bus-port:%s devno:%s serial:%s devpath:%s\n",
i, entry->busnum, entry->devnum,
entry->busport, entry->devno, entry->serial, entry->path);
}
}
static struct oattnusb_usb_dev usb_dev[MAX_OUA];
static struct oattnusb_devarray devarray = { -1, usb_dev, };
struct oattnusb_devarray *oattnusb_get_devarray(unsigned int vendor_id, unsigned int device_id)
{
struct udev *udev = udev_new();
struct udev_enumerate *enumerate = udev_enumerate_new(udev);
struct udev_list_entry *devs, *ptr, *ptr2;
int found_devs = 0;
char vid[6], did[6];
sprintf(vid, "%04x", vendor_id);
sprintf(did, "%04x", device_id);
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;
udev_device_unref(dev);
}
out:
udev_enumerate_unref(enumerate);
devarray.ndevs = found_devs;
return &devarray;
}
/**
* @file usb-enum.h
*
* @brief OASIS USB Attenuator driver library interface
*
* This file describes the external interface to the OASIS USB Attenuator
* driver and provides the definitios for proper communication
* with the device
*
* Copyright (c) 2021 CERN
* @author David Cobas <dcobas AT cern.ch>
*
* Released under the GPL v2. (and only v2, not any later version)
*/
/**
* \brief oattnusb_usb_dev - representation of an oattn device in all
* concevable forms
*/
struct oattnusb_usb_dev {
int lun; /**< logical unit number (not implemented) */
char busnum[6]; /**< USB bus number (decimal) */
char devnum[6]; /**< USB dev number (decimal) */
char portnum[6]; /**< USB port number (decimal) */
char busport[16]; /**< USB bus-port string (decimal bbb-ppp) */
char devno[10]; /**< Linux kernel devno (decimal major:minor) */
char serial[48]; /**< Serial number (e.g. HCCAIAD000-CR000003) */
char path[256]; /**< Linux sysfs device path */
int unused[4];
};
/**
* \struct oattnusb_devarray
* \brief array of oattn devices detected in the system
*/
struct oattnusb_devarray {
int ndevs; /**< number of devices (i.e. array length) */
struct oattnusb_usb_dev *devs; /**< pointer to array of devices */
};
/** oattnusb_display_devarray - auxiliary function to display the
* detected device array table
*/
void oattnusb_display_devarray(struct oattnusb_devarray *ls);
/** oattnusb_get_devarray - populate library's static table of detected devices
*/
struct oattnusb_devarray *oattnusb_get_devarray(unsigned int vendor_id, unsigned int device_id);
-include ../lib/Makefile.ftdi
OBJS = oasis-usb-att-test.o
CFLAGS = -I../lib -DGIT_VERSION="dummy"
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) -L../lib -loasis-usb-att -lftdi
\ No newline at end of file
gcc -o oasis-usb-att-test $(OBJS) $(LDFLAGS) $(LDLIBS)
clean:
rm -f *.o oasis-usb-att-test
......@@ -13,7 +13,7 @@
#include "liboasis-usb-att.h"
static char git_version[] = "git_version: "; // GIT_VERSION;
static char git_version[] = "git_version: " GIT_VERSION;
int device;
int selected_channel;
......
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