WIP: TITAN TestPort for accessing USB devices from a USB host
This commit is contained in:
commit
cdd33ebe7e
|
@ -0,0 +1,4 @@
|
||||||
|
*.d
|
||||||
|
*.o
|
||||||
|
*.so
|
||||||
|
compile
|
|
@ -0,0 +1,219 @@
|
||||||
|
# This Makefile was generated by the Makefile Generator
|
||||||
|
# of the TTCN-3 Test Executor version CRL 113 200/6 R5A
|
||||||
|
# for Harald Welte (laforge@nataraja) on Sun Jan 6 20:29:51 2019
|
||||||
|
|
||||||
|
# Copyright (c) 2000-2018 Ericsson Telecom AB
|
||||||
|
|
||||||
|
# The following make commands are available:
|
||||||
|
# - make, make all Builds the executable test suite.
|
||||||
|
# - make archive Archives all source files.
|
||||||
|
# - make check Checks the semantics of TTCN-3 and ASN.1modules.
|
||||||
|
# - make port Generates port skeletons.
|
||||||
|
# - make clean Removes all generated files.
|
||||||
|
# - make compile Translates TTCN-3 and ASN.1 modules to C++.
|
||||||
|
# - make dep Creates/updates dependency list.
|
||||||
|
# - make executable Builds the executable test suite.
|
||||||
|
# - make library Builds the library archive.
|
||||||
|
# - make objects Builds the object files without linking the executable.
|
||||||
|
# - make shared_objects Builds the shared object files without linking the executable.
|
||||||
|
# WARNING! This Makefile can be used with GNU make only.
|
||||||
|
# Other versions of make may report syntax errors in it.
|
||||||
|
|
||||||
|
#
|
||||||
|
# Do NOT touch this line...
|
||||||
|
#
|
||||||
|
.PHONY: all shared_objects executable library objects check port clean dep archive
|
||||||
|
|
||||||
|
.SUFFIXES: .d
|
||||||
|
|
||||||
|
#
|
||||||
|
# Set these variables...
|
||||||
|
#
|
||||||
|
|
||||||
|
ifndef TTCN3_DIR
|
||||||
|
ifneq (,$(wildcard /usr/include/titan/))
|
||||||
|
TTCN3_DIR = /usr
|
||||||
|
TTCN3_SUBDIR = /titan
|
||||||
|
else
|
||||||
|
TTCN3_DIR =
|
||||||
|
TTCN3_SUBDIR =
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Your platform: (SOLARIS, SOLARIS8, LINUX, FREEBSD or WIN32)
|
||||||
|
PLATFORM = LINUX
|
||||||
|
|
||||||
|
# Your C++ compiler:
|
||||||
|
# (if you change the platform, you may need to change the compiler)
|
||||||
|
CXX = g++
|
||||||
|
|
||||||
|
# Flags for the C++ preprocessor (and makedepend as well):
|
||||||
|
CPPFLAGS = -D$(PLATFORM) -I$(TTCN3_DIR)/include$(TTCN3_SUBDIR) $(shell pkg-config --cflags libusb-1.0)
|
||||||
|
|
||||||
|
# Flags for dependency generation
|
||||||
|
CXXDEPFLAGS = -MM
|
||||||
|
|
||||||
|
# Flags for the C++ compiler:
|
||||||
|
CXXFLAGS = -Wall -fPIC
|
||||||
|
|
||||||
|
# Flags for the linker:
|
||||||
|
LDFLAGS = -fPIC $(shell pkg-config --libs libusb-1.0)
|
||||||
|
|
||||||
|
ifeq ($(PLATFORM), WIN32)
|
||||||
|
# Silence linker warnings.
|
||||||
|
LDFLAGS += -Wl,--enable-auto-import,--enable-runtime-pseudo-reloc
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Utility to create library files
|
||||||
|
AR = ar
|
||||||
|
ARFLAGS =
|
||||||
|
|
||||||
|
# Flags for the TTCN-3 and ASN.1 compiler:
|
||||||
|
COMPILER_FLAGS = -L
|
||||||
|
|
||||||
|
# Execution mode: (either ttcn3 or ttcn3-parallel)
|
||||||
|
TTCN3_LIB = ttcn3-parallel-dynamic
|
||||||
|
|
||||||
|
# The path of your libxml2 installation:
|
||||||
|
# If you do not have your own one, leave it unchanged.
|
||||||
|
XMLDIR = $(TTCN3_DIR)
|
||||||
|
|
||||||
|
# Directory to store the archived source files:
|
||||||
|
ARCHIVE_DIR = backup
|
||||||
|
|
||||||
|
#
|
||||||
|
# You may change these variables. Add your files if necessary...
|
||||||
|
#
|
||||||
|
|
||||||
|
# TTCN-3 modules of this project:
|
||||||
|
TTCN3_MODULES = USB_PortType.ttcn USB_PortTypes.ttcn
|
||||||
|
|
||||||
|
# ASN.1 modules of this project:
|
||||||
|
ASN1_MODULES =
|
||||||
|
|
||||||
|
# C++ source & header files generated from the TTCN-3 & ASN.1 modules of
|
||||||
|
# this project:
|
||||||
|
GENERATED_SOURCES = $(TTCN3_MODULES:.ttcn=.cc) $(ASN1_MODULES:.asn=.cc)
|
||||||
|
GENERATED_HEADERS = $(GENERATED_SOURCES:.cc=.hh)
|
||||||
|
|
||||||
|
# C/C++ Source & header files of Test Ports, external functions and
|
||||||
|
# other modules:
|
||||||
|
USER_SOURCES = USB_PT.cc
|
||||||
|
USER_HEADERS = $(USER_SOURCES:.cc=.hh)
|
||||||
|
|
||||||
|
# Shared object files of this project:
|
||||||
|
SHARED_OBJECTS = $(GENERATED_SOURCES:.cc=.so) $(USER_SOURCES:.cc=.so)
|
||||||
|
|
||||||
|
# Object files of this project that are needed for the executable test suite:
|
||||||
|
OBJECTS = $(GENERATED_OBJECTS) $(USER_OBJECTS)
|
||||||
|
|
||||||
|
GENERATED_OBJECTS = $(GENERATED_SOURCES:.cc=.o)
|
||||||
|
|
||||||
|
USER_OBJECTS = $(USER_SOURCES:.cc=.o)
|
||||||
|
|
||||||
|
DEPFILES = $(USER_OBJECTS:.o=.d) $(GENERATED_OBJECTS:.o=.d)
|
||||||
|
|
||||||
|
# Other files of the project (Makefile, configuration files, etc.)
|
||||||
|
# that will be added to the archived source files:
|
||||||
|
OTHER_FILES = Makefile
|
||||||
|
|
||||||
|
# The name of the executable test suite:
|
||||||
|
EXECUTABLE = USB_PortType
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
LIBRARY = lib$(EXECUTABLE).so
|
||||||
|
|
||||||
|
TARGET = $(EXECUTABLE)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Do not modify these unless you know what you are doing...
|
||||||
|
# Platform specific additional libraries:
|
||||||
|
#
|
||||||
|
SOLARIS_LIBS = -lsocket -lnsl -lxml2
|
||||||
|
SOLARIS8_LIBS = -lsocket -lnsl -lxml2
|
||||||
|
LINUX_LIBS = -lxml2
|
||||||
|
FREEBSD_LIBS = -lxml2
|
||||||
|
WIN32_LIBS = -lxml2
|
||||||
|
|
||||||
|
#
|
||||||
|
# Rules for building the executable...
|
||||||
|
#
|
||||||
|
|
||||||
|
all: $(TARGET) ;
|
||||||
|
|
||||||
|
shared_objects: $(SHARED_OBJECTS) ;
|
||||||
|
|
||||||
|
executable: $(EXECUTABLE) ;
|
||||||
|
|
||||||
|
library: $(LIBRARY) ;
|
||||||
|
|
||||||
|
objects: $(OBJECTS) compile;
|
||||||
|
|
||||||
|
$(EXECUTABLE): $(SHARED_OBJECTS)
|
||||||
|
if $(CXX) $(LDFLAGS) -o $@ -Wl,--no-as-needed $^ \
|
||||||
|
-L$(TTCN3_DIR)/lib$(TTCN3_SUBDIR) -l$(TTCN3_LIB) \
|
||||||
|
-L$(OPENSSL_DIR)/lib -lcrypto \
|
||||||
|
-L$(XMLDIR)/lib $($(PLATFORM)_LIBS); \
|
||||||
|
then : ; else $(TTCN3_DIR)/bin/titanver $(OBJECTS); exit 1; fi
|
||||||
|
|
||||||
|
$(LIBRARY): $(OBJECTS)
|
||||||
|
$(CXX) -shared -o $@ $(OBJECTS)
|
||||||
|
|
||||||
|
.cc.o .c.o:
|
||||||
|
$(CXX) -c $(CPPFLAGS) $(CXXFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
.cc.d .c.d:
|
||||||
|
@echo Creating dependency file for '$<'; set -e; \
|
||||||
|
$(CXX) $(CXXDEPFLAGS) $(CPPFLAGS) $(CXXFLAGS) $< \
|
||||||
|
| sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \
|
||||||
|
[ -s $@ ] || rm -f $@
|
||||||
|
|
||||||
|
%.so: %.o
|
||||||
|
$(CXX) -shared -o $@ $<
|
||||||
|
|
||||||
|
$(GENERATED_SOURCES) $(GENERATED_HEADERS): compile
|
||||||
|
@if [ ! -f $@ ]; then $(RM) compile; $(MAKE) compile; fi
|
||||||
|
|
||||||
|
check: $(TTCN3_MODULES) $(ASN1_MODULES)
|
||||||
|
$(TTCN3_DIR)/bin/compiler -s $(COMPILER_FLAGS) $^
|
||||||
|
|
||||||
|
port: $(TTCN3_MODULES) $(ASN1_MODULES)
|
||||||
|
$(TTCN3_DIR)/bin/compiler -t $(COMPILER_FLAGS) $^
|
||||||
|
|
||||||
|
compile: $(TTCN3_MODULES) $(ASN1_MODULES)
|
||||||
|
$(TTCN3_DIR)/bin/compiler $(COMPILER_FLAGS) $^ - $?
|
||||||
|
touch $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
-$(RM) $(EXECUTABLE) $(LIBRARY) $(OBJECTS) $(GENERATED_HEADERS) \
|
||||||
|
$(GENERATED_SOURCES) $(SHARED_OBJECTS) compile $(DEPFILES) \
|
||||||
|
tags *.log
|
||||||
|
|
||||||
|
dep: $(GENERATED_SOURCES) $(USER_SOURCES) ;
|
||||||
|
|
||||||
|
ifeq ($(findstring n,$(MAKEFLAGS)),)
|
||||||
|
ifeq ($(filter clean check port compile archive diag,$(MAKECMDGOALS)),)
|
||||||
|
-include $(DEPFILES)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
archive:
|
||||||
|
mkdir -p $(ARCHIVE_DIR)
|
||||||
|
tar -cvhf - $(TTCN3_MODULES) $(ASN1_MODULES) \
|
||||||
|
$(USER_HEADERS) $(USER_SOURCES) $(OTHER_FILES) \
|
||||||
|
| gzip >$(ARCHIVE_DIR)/`basename $(TARGET) .exe`-`date '+%y%m%d-%H%M'`.tgz
|
||||||
|
|
||||||
|
diag:
|
||||||
|
$(TTCN3_DIR)/bin/compiler -v 2>&1
|
||||||
|
$(TTCN3_DIR)/bin/mctr_cli -v 2>&1
|
||||||
|
$(CXX) -v 2>&1
|
||||||
|
@echo TTCN3_DIR=$(TTCN3_DIR)
|
||||||
|
@echo OPENSSL_DIR=$(OPENSSL_DIR)
|
||||||
|
@echo XMLDIR=$(XMLDIR)
|
||||||
|
@echo PLATFORM=$(PLATFORM)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Add your rules here if necessary...
|
||||||
|
#
|
||||||
|
|
|
@ -0,0 +1,495 @@
|
||||||
|
/* Copyright (c) 2018 Harald Welte <laforge@gnumonks.org> */
|
||||||
|
|
||||||
|
#include "USB_PT.hh"
|
||||||
|
#include "USB_PortType.hh"
|
||||||
|
|
||||||
|
#include <poll.h>
|
||||||
|
#include <libusb.h>
|
||||||
|
|
||||||
|
using namespace USB__PortTypes;
|
||||||
|
|
||||||
|
namespace USB__PortType {
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* libusb callbacks / helpers
|
||||||
|
***********************************************************************/
|
||||||
|
|
||||||
|
static enum libusb_transfer_type ttype_titan2usb(const USB__transfer__type &in)
|
||||||
|
{
|
||||||
|
switch (in) {
|
||||||
|
case USB__transfer__type::USB__TRANSFER__TYPE__CONTROL:
|
||||||
|
return LIBUSB_TRANSFER_TYPE_CONTROL;
|
||||||
|
case USB__transfer__type::USB__TRANSFER__TYPE__ISOCHRONOUS:
|
||||||
|
return LIBUSB_TRANSFER_TYPE_ISOCHRONOUS;
|
||||||
|
case USB__transfer__type::USB__TRANSFER__TYPE__BULK:
|
||||||
|
return LIBUSB_TRANSFER_TYPE_BULK;
|
||||||
|
case USB__transfer__type::USB__TRANSFER__TYPE__INTERRUPT:
|
||||||
|
return LIBUSB_TRANSFER_TYPE_INTERRUPT;
|
||||||
|
case USB__transfer__type::USB__TRANSFER__TYPE__BULK__STREAM:
|
||||||
|
return LIBUSB_TRANSFER_TYPE_BULK_STREAM;
|
||||||
|
default:
|
||||||
|
TTCN_error("Unknown USB transfer type %d", (int)in);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static USB__transfer__type ttype_usb2titan(enum libusb_transfer_type in)
|
||||||
|
{
|
||||||
|
switch (in) {
|
||||||
|
case LIBUSB_TRANSFER_TYPE_CONTROL:
|
||||||
|
return USB__transfer__type::USB__TRANSFER__TYPE__CONTROL;
|
||||||
|
case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
|
||||||
|
return USB__transfer__type::USB__TRANSFER__TYPE__ISOCHRONOUS;
|
||||||
|
case LIBUSB_TRANSFER_TYPE_BULK:
|
||||||
|
return USB__transfer__type::USB__TRANSFER__TYPE__BULK;
|
||||||
|
case LIBUSB_TRANSFER_TYPE_INTERRUPT:
|
||||||
|
return USB__transfer__type::USB__TRANSFER__TYPE__INTERRUPT;
|
||||||
|
case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
|
||||||
|
return USB__transfer__type::USB__TRANSFER__TYPE__BULK__STREAM;
|
||||||
|
default:
|
||||||
|
TTCN_error("Unknown USB transfer type %d", (int)in);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* call-back by libusb telling us to monitor a given fd */
|
||||||
|
void libusb_pollfd_added(int fd, short events, void *user_data)
|
||||||
|
{
|
||||||
|
TTCN_warning("pollfd_added(%d, %d)", fd, events);
|
||||||
|
USB__PT_PROVIDER *pt = (USB__PT_PROVIDER *)user_data;
|
||||||
|
if (events & POLLIN)
|
||||||
|
pt->Handler_Add_Fd_Read(fd);
|
||||||
|
if (events & POLLOUT)
|
||||||
|
pt->Handler_Add_Fd_Write(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* call-back by libusb telling us to stop monitoring a given fd */
|
||||||
|
void libusb_pollfd_removed(int fd, void *user_data)
|
||||||
|
{
|
||||||
|
TTCN_warning("pollfd_removed(%d)", fd);
|
||||||
|
USB__PT_PROVIDER *pt = (USB__PT_PROVIDER *)user_data;
|
||||||
|
pt->Handler_Remove_Fd(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void libusb_transfer_cb(struct libusb_transfer *xfer)
|
||||||
|
{
|
||||||
|
USB_Transfer *t = (USB_Transfer *) xfer->user_data;
|
||||||
|
t->complete();
|
||||||
|
delete t;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* USB_Interface
|
||||||
|
***********************************************************************/
|
||||||
|
|
||||||
|
USB_Interface::USB_Interface(USB_Device &dev, unsigned int number)
|
||||||
|
: mDev(dev), mNum(number)
|
||||||
|
{
|
||||||
|
mDev.log(TTCN_WARNING, "creating USB interface %u\n", mNum);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
USB_Interface::~USB_Interface()
|
||||||
|
{
|
||||||
|
mDev.log(TTCN_WARNING, "releasing USB interface %u\n", mNum);
|
||||||
|
int rc = libusb_release_interface(mDev.mHandle, mNum);
|
||||||
|
if (rc != 0)
|
||||||
|
mDev.log(TTCN_WARNING, "cannot release interface");
|
||||||
|
}
|
||||||
|
/***********************************************************************
|
||||||
|
* USB_Device
|
||||||
|
***********************************************************************/
|
||||||
|
|
||||||
|
USB_Device::USB_Device(USB__PT_PROVIDER *port, libusb_device_handle *handle, unsigned int id)
|
||||||
|
: mPort(port), mHandle(handle), mID(id)
|
||||||
|
{
|
||||||
|
log(TTCN_WARNING, "creating");
|
||||||
|
}
|
||||||
|
|
||||||
|
USB_Device::USB_Device(const USB_Device &in)
|
||||||
|
{
|
||||||
|
this->mPort = in.mPort;
|
||||||
|
this->mHandle = in.mHandle;
|
||||||
|
this->mID = in.mID;
|
||||||
|
log(TTCN_WARNING, "copying from %p", &in);
|
||||||
|
}
|
||||||
|
|
||||||
|
USB_Device::~USB_Device()
|
||||||
|
{
|
||||||
|
log(TTCN_WARNING, "destroying");
|
||||||
|
|
||||||
|
/* iterate over map of interfaces: destroy the USB_Interface objects in it; clear map */
|
||||||
|
std::map<unsigned int,USB_Interface *>::iterator it;
|
||||||
|
for (it = mInterfaces.begin(); it != mInterfaces.end(); it++) {
|
||||||
|
delete it->second;
|
||||||
|
}
|
||||||
|
mInterfaces.clear();
|
||||||
|
|
||||||
|
libusb_close(mHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
USB_Interface *USB_Device::interface(unsigned int number)
|
||||||
|
{
|
||||||
|
std::map<unsigned int,USB_Interface *>::iterator it = mInterfaces.find(number);
|
||||||
|
if (it == mInterfaces.end())
|
||||||
|
TTCN_error("Cannot find USB interface %u", number);
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
void USB_Device::log(TTCN_Logger::Severity msg_severity, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
TTCN_Logger::begin_event(msg_severity);
|
||||||
|
TTCN_Logger::log_event("USB Test port (%s): Device %p(%p,%d) ", mPort->get_name(), this, mHandle, mID);
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
TTCN_Logger::log_event_va_list(fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
TTCN_Logger::end_event();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* USB_Transfer
|
||||||
|
***********************************************************************/
|
||||||
|
|
||||||
|
USB_Transfer::USB_Transfer(const USB_Device *dev, unsigned int id, struct libusb_transfer *lx)
|
||||||
|
{
|
||||||
|
init(dev, id, lx);
|
||||||
|
}
|
||||||
|
|
||||||
|
USB_Transfer::USB_Transfer(USB__PT_PROVIDER *pt, const USB__transfer& send_par)
|
||||||
|
{
|
||||||
|
USB_Device *dev = pt->usbdev_by_hdl(send_par.device__hdl());
|
||||||
|
|
||||||
|
struct libusb_transfer *xfer = libusb_alloc_transfer(0);
|
||||||
|
xfer->dev_handle = dev->mHandle;
|
||||||
|
xfer->flags = 0;
|
||||||
|
xfer->type = ttype_titan2usb(send_par.ttype());
|
||||||
|
xfer->endpoint = send_par.endpoint();
|
||||||
|
xfer->timeout = send_par.timeout__msec();
|
||||||
|
xfer->user_data = this;
|
||||||
|
xfer->length = send_par.data().lengthof();
|
||||||
|
xfer->buffer = libusb_dev_mem_alloc(xfer->dev_handle, xfer->length);
|
||||||
|
memcpy(xfer->buffer, send_par.data(), xfer->length);
|
||||||
|
xfer->callback = &libusb_transfer_cb;
|
||||||
|
init(dev, send_par.transfer__hdl(), xfer);
|
||||||
|
};
|
||||||
|
|
||||||
|
void USB_Transfer::init(const USB_Device *dev, unsigned int id, struct libusb_transfer *lx)
|
||||||
|
{
|
||||||
|
mDev = dev;
|
||||||
|
mID = id;
|
||||||
|
mXfer = lx;
|
||||||
|
log("transfer created\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void USB_Transfer::submit()
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = libusb_submit_transfer(mXfer);
|
||||||
|
if (rc != 0) {
|
||||||
|
TTCN_error("Error during libusb_submit_transfer(): %s",
|
||||||
|
libusb_strerror((libusb_error) rc));
|
||||||
|
}
|
||||||
|
log("transfer submitted\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void USB_Transfer::complete()
|
||||||
|
{
|
||||||
|
log("transfer completed\n");
|
||||||
|
/* report back to TTCN-3 port user */
|
||||||
|
mDev->mPort->transfer_completed(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void USB_Transfer::log(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
TTCN_Logger::begin_event(TTCN_WARNING);
|
||||||
|
TTCN_Logger::log_event("USB Test port (%s): T %p ", mDev->mPort->get_name(), this);
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
TTCN_Logger::log_event_va_list(fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
TTCN_Logger::end_event();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
USB_Transfer::~USB_Transfer()
|
||||||
|
{
|
||||||
|
/* last, but not least: release the buffer used */
|
||||||
|
if (mXfer->buffer) {
|
||||||
|
libusb_dev_mem_free(mDev->mHandle, mXfer->buffer, mXfer->length);
|
||||||
|
mXfer->buffer = NULL;
|
||||||
|
}
|
||||||
|
libusb_free_transfer(mXfer);
|
||||||
|
log("transfer destroyed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* USB__PT_PROVIDER
|
||||||
|
***********************************************************************/
|
||||||
|
|
||||||
|
USB__PT_PROVIDER::USB__PT_PROVIDER(const char *par_port_name)
|
||||||
|
: PORT(par_port_name)
|
||||||
|
{
|
||||||
|
libusb_init(&mCtx);
|
||||||
|
libusb_set_pollfd_notifiers(mCtx, libusb_pollfd_added, libusb_pollfd_removed, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
USB__PT_PROVIDER::~USB__PT_PROVIDER()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void USB__PT_PROVIDER::log(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
TTCN_Logger::begin_event(TTCN_WARNING);
|
||||||
|
TTCN_Logger::log_event("USB Test port (%s): ", get_name());
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
TTCN_Logger::log_event_va_list(fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
TTCN_Logger::end_event();
|
||||||
|
}
|
||||||
|
|
||||||
|
void USB__PT_PROVIDER::set_parameter(const char *parameter_name, const char *parameter_value)
|
||||||
|
{
|
||||||
|
if (0) {
|
||||||
|
/* handle known/supported parameters here */
|
||||||
|
} else
|
||||||
|
TTCN_error("Unsupported test port parameter `%s'.", parameter_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void USB__PT_PROVIDER::Handle_Fd_Event(int fd, boolean is_readable,
|
||||||
|
boolean is_writable, boolean is_error)
|
||||||
|
{
|
||||||
|
/* we assume that we're running Linux v2.6.27 with timerfd support here
|
||||||
|
* and hence don't have to perform manual timeout handling. See
|
||||||
|
* "Notes on time-based events" at
|
||||||
|
* http://libusb.sourceforge.net/api-1.0/group__libusb__poll.html */
|
||||||
|
struct timeval zero_tv = { 0, 0 };
|
||||||
|
libusb_handle_events_timeout(mCtx, &zero_tv);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*void USB__PT_PROVIDER::Handle_Timeout(double time_since_last_call) {}*/
|
||||||
|
|
||||||
|
void USB__PT_PROVIDER::user_map(const char * /*system_port*/)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void USB__PT_PROVIDER::user_unmap(const char * /*system_port*/)
|
||||||
|
{
|
||||||
|
/* iterate over map of devices: destroy the USB_Device objects in it; clear map */
|
||||||
|
std::map<unsigned int,USB_Device *>::iterator it;
|
||||||
|
for (it = mDevices.begin(); it != mDevices.end(); it++) {
|
||||||
|
delete it->second;
|
||||||
|
}
|
||||||
|
mDevices.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void USB__PT_PROVIDER::user_start()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void USB__PT_PROVIDER::user_stop()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
USB_Device *USB__PT_PROVIDER::usbdev_by_hdl(unsigned int hdl)
|
||||||
|
{
|
||||||
|
std::map<unsigned int,USB_Device *>::iterator search = mDevices.find(hdl);
|
||||||
|
if (search == mDevices.end()) {
|
||||||
|
TTCN_error("Cannot find USB device for handle %u\n", hdl);
|
||||||
|
}
|
||||||
|
return search->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int USB__PT_PROVIDER::usbhdl_by_dev(libusb_device_handle *dh)
|
||||||
|
{
|
||||||
|
std::map<unsigned int,USB_Device *>::iterator it = mDevices.begin();
|
||||||
|
while (it != mDevices.end()) {
|
||||||
|
if (it->second->mHandle == dh)
|
||||||
|
return it->first;
|
||||||
|
}
|
||||||
|
|
||||||
|
TTCN_error("Cannot find USB handle for lubusb_dev %p\n", dh);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void USB__PT_PROVIDER::outgoing_send(const USB__open__vid__pid& send_par)
|
||||||
|
{
|
||||||
|
unsigned int device_hdl = send_par.device__hdl();
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
libusb_device_handle *dh;
|
||||||
|
dh = libusb_open_device_with_vid_pid(mCtx, send_par.vendor__id(), send_par.product__id());
|
||||||
|
if (!dh) {
|
||||||
|
log("Error opening VID/PID %04x:%04x", send_par.vendor__id(), send_par.product__id());
|
||||||
|
rc = -1;
|
||||||
|
} else {
|
||||||
|
USB_Device *dev = new USB_Device(this, dh, device_hdl);
|
||||||
|
mDevices.insert(std::make_pair(device_hdl, dev));
|
||||||
|
rc = 0;
|
||||||
|
}
|
||||||
|
incoming_message(USB__result(send_par.req__hdl(), send_par.device__hdl(), rc));
|
||||||
|
}
|
||||||
|
|
||||||
|
void USB__PT_PROVIDER::outgoing_send(const USB__set__configuration& send_par)
|
||||||
|
{
|
||||||
|
USB_Device *dev = usbdev_by_hdl(send_par.device__hdl());
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = libusb_set_configuration(dev->mHandle, send_par.configuration());
|
||||||
|
if (rc != 0)
|
||||||
|
log("Cannot set configuration %d", (int)send_par.configuration());
|
||||||
|
incoming_message(USB__result(send_par.req__hdl(), send_par.device__hdl(), rc));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void USB__PT_PROVIDER::outgoing_send(const USB__claim__interface& send_par)
|
||||||
|
{
|
||||||
|
USB_Device *dev = usbdev_by_hdl(send_par.device__hdl());
|
||||||
|
unsigned int interface_nr = send_par.interface();
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = libusb_claim_interface(dev->mHandle, interface_nr);
|
||||||
|
if (rc != 0)
|
||||||
|
log("Cannot claim USB interface %d\n", interface_nr);
|
||||||
|
else {
|
||||||
|
USB_Interface *intf = new USB_Interface(*dev, interface_nr);
|
||||||
|
dev->mInterfaces.insert(std::make_pair(interface_nr, intf));
|
||||||
|
}
|
||||||
|
incoming_message(USB__result(send_par.req__hdl(), send_par.device__hdl(), rc));
|
||||||
|
}
|
||||||
|
|
||||||
|
void USB__PT_PROVIDER::outgoing_send(const USB__release__interface& send_par)
|
||||||
|
{
|
||||||
|
USB_Device *dev = usbdev_by_hdl(send_par.device__hdl());
|
||||||
|
unsigned int interface_nr = send_par.interface();
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = libusb_release_interface(dev->mHandle, interface_nr);
|
||||||
|
if (rc != 0)
|
||||||
|
log("Cannot release USB interface %d\n", interface_nr);
|
||||||
|
else
|
||||||
|
dev->mInterfaces.erase(interface_nr);
|
||||||
|
incoming_message(USB__result(send_par.req__hdl(), send_par.device__hdl(), rc));
|
||||||
|
}
|
||||||
|
|
||||||
|
void USB__PT_PROVIDER::outgoing_send(const USB__get__device__descriptor& send_par)
|
||||||
|
{
|
||||||
|
USB_Device *dev = usbdev_by_hdl(send_par.device__hdl());
|
||||||
|
struct libusb_device_descriptor udesc;
|
||||||
|
struct USB__descriptor resp;
|
||||||
|
OCTETSTRING data;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
struct libusb_device *d = libusb_get_device(dev->mHandle);
|
||||||
|
rc = libusb_get_device_descriptor(d, &udesc);
|
||||||
|
if (rc != 0)
|
||||||
|
data = OCTETSTRING();
|
||||||
|
else
|
||||||
|
data = OCTETSTRING(sizeof(udesc), (const unsigned char *) &udesc);
|
||||||
|
incoming_message(USB__descriptor(send_par.req__hdl(), send_par.device__hdl(), rc, data));
|
||||||
|
}
|
||||||
|
|
||||||
|
void USB__PT_PROVIDER::outgoing_send(const USB__get__config__descriptor& send_par)
|
||||||
|
{
|
||||||
|
USB_Device *dev = usbdev_by_hdl(send_par.device__hdl());
|
||||||
|
struct libusb_config_descriptor *udesc;
|
||||||
|
struct USB__descriptor resp;
|
||||||
|
OCTETSTRING data;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
struct libusb_device *d = libusb_get_device(dev->mHandle);
|
||||||
|
rc = libusb_get_config_descriptor(d, send_par.config__index(), &udesc);
|
||||||
|
if (rc != 0)
|
||||||
|
data = OCTETSTRING();
|
||||||
|
else {
|
||||||
|
data = OCTETSTRING(udesc->wTotalLength, (const unsigned char *) udesc);
|
||||||
|
libusb_free_config_descriptor(udesc);
|
||||||
|
}
|
||||||
|
incoming_message(USB__descriptor(send_par.req__hdl(), send_par.device__hdl(), rc, data));
|
||||||
|
}
|
||||||
|
|
||||||
|
void USB__PT_PROVIDER::outgoing_send(const USB__get__config__descriptor__by__value& send_par)
|
||||||
|
{
|
||||||
|
USB_Device *dev = usbdev_by_hdl(send_par.device__hdl());
|
||||||
|
struct libusb_config_descriptor *udesc;
|
||||||
|
struct USB__descriptor resp;
|
||||||
|
OCTETSTRING data;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
struct libusb_device *d = libusb_get_device(dev->mHandle);
|
||||||
|
rc = libusb_get_config_descriptor_by_value(d, send_par.config__value(), &udesc);
|
||||||
|
if (rc != 0)
|
||||||
|
data = OCTETSTRING();
|
||||||
|
else {
|
||||||
|
data = OCTETSTRING(udesc->wTotalLength, (const unsigned char *) udesc);
|
||||||
|
libusb_free_config_descriptor(udesc);
|
||||||
|
}
|
||||||
|
incoming_message(USB__descriptor(send_par.req__hdl(), send_par.device__hdl(), rc, data));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void USB__PT_PROVIDER::outgoing_send(const USB__get__active__config__descriptor& send_par)
|
||||||
|
{
|
||||||
|
USB_Device *dev = usbdev_by_hdl(send_par.device__hdl());
|
||||||
|
struct libusb_config_descriptor *udesc;
|
||||||
|
struct USB__descriptor resp;
|
||||||
|
OCTETSTRING data;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
struct libusb_device *d = libusb_get_device(dev->mHandle);
|
||||||
|
rc = libusb_get_active_config_descriptor(d, &udesc);
|
||||||
|
if (rc != 0)
|
||||||
|
data = OCTETSTRING();
|
||||||
|
else {
|
||||||
|
data = OCTETSTRING(udesc->wTotalLength, (const unsigned char *) udesc);
|
||||||
|
libusb_free_config_descriptor(udesc);
|
||||||
|
}
|
||||||
|
incoming_message(USB__descriptor(send_par.req__hdl(), send_par.device__hdl(), rc, data));
|
||||||
|
}
|
||||||
|
|
||||||
|
void USB__PT_PROVIDER::outgoing_send(const USB__get__string__descriptor& send_par)
|
||||||
|
{
|
||||||
|
USB_Device *dev = usbdev_by_hdl(send_par.device__hdl());
|
||||||
|
struct USB__descriptor resp;
|
||||||
|
unsigned char buf[256];
|
||||||
|
OCTETSTRING data;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = libusb_get_string_descriptor(dev->mHandle, send_par.index(), send_par.language__id(),
|
||||||
|
buf, sizeof(buf));
|
||||||
|
if (rc < 0)
|
||||||
|
data = OCTETSTRING();
|
||||||
|
else
|
||||||
|
data = OCTETSTRING(rc, buf);
|
||||||
|
incoming_message(USB__descriptor(send_par.req__hdl(), send_par.device__hdl(), rc, data));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void USB__PT_PROVIDER::outgoing_send(const USB__transfer& send_par)
|
||||||
|
{
|
||||||
|
USB_Transfer *t = new USB_Transfer(this, send_par);
|
||||||
|
t->submit();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void USB__PT_PROVIDER::transfer_completed(USB_Transfer *t)
|
||||||
|
{
|
||||||
|
USB__transfer__compl xfc;
|
||||||
|
xfc.device__hdl() = t->mDev->mID;
|
||||||
|
xfc.ttype() = ttype_usb2titan((enum libusb_transfer_type) t->mXfer->type);
|
||||||
|
xfc.endpoint() = t->mXfer->endpoint;
|
||||||
|
xfc.data() = OCTETSTRING(t->mXfer->length, t->mXfer->buffer);
|
||||||
|
xfc.actual__length() = t->mXfer->actual_length;
|
||||||
|
incoming_message(xfc);
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* end of namespace */
|
||||||
|
|
|
@ -0,0 +1,129 @@
|
||||||
|
// This Test Port skeleton header file was generated by the
|
||||||
|
// TTCN-3 Compiler of the TTCN-3 Test Executor version CRL 113 200/6 R5A
|
||||||
|
// for Harald Welte (laforge@nataraja) on Sun Jan 6 18:08:12 2019
|
||||||
|
|
||||||
|
// Copyright (c) 2000-2018 Ericsson Telecom AB
|
||||||
|
|
||||||
|
// You may modify this file. Add your attributes and prototypes of your
|
||||||
|
// member functions here.
|
||||||
|
|
||||||
|
#ifndef USB__PT_HH
|
||||||
|
#define USB__PT_HH
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
|
#include <TTCN3.hh>
|
||||||
|
#include <libusb.h>
|
||||||
|
#include "USB_PortTypes.hh"
|
||||||
|
|
||||||
|
// Note: Header file USB_PortType.hh must not be included into this file!
|
||||||
|
// (because it includes this file)
|
||||||
|
// Please add the declarations of message types manually.
|
||||||
|
|
||||||
|
namespace USB__PortType {
|
||||||
|
|
||||||
|
using namespace USB__PortTypes;
|
||||||
|
|
||||||
|
class USB_Device;
|
||||||
|
|
||||||
|
class USB_Interface {
|
||||||
|
public:
|
||||||
|
USB_Interface(USB_Device &dev, unsigned int number);
|
||||||
|
~USB_Interface();
|
||||||
|
USB_Device &mDev;
|
||||||
|
unsigned int mNum;
|
||||||
|
};
|
||||||
|
|
||||||
|
class USB__PT_PROVIDER;
|
||||||
|
|
||||||
|
class USB_Device {
|
||||||
|
public:
|
||||||
|
USB_Device(USB__PT_PROVIDER *pt, libusb_device_handle *handle, unsigned int id);
|
||||||
|
USB_Device(const USB_Device &in);
|
||||||
|
~USB_Device();
|
||||||
|
USB_Interface *interface(unsigned int number);
|
||||||
|
void log(TTCN_Logger::Severity msg_severity, const char *fmt, ...);
|
||||||
|
|
||||||
|
/* the TTCN-3 port through which this device was opened */
|
||||||
|
USB__PT_PROVIDER *mPort;
|
||||||
|
/* the actaul libusb data structure */
|
||||||
|
libusb_device_handle *mHandle;
|
||||||
|
/* ID the user gave the transfer, returned back to user on completion */
|
||||||
|
unsigned int mID;
|
||||||
|
/* interfaces we have claimed for this device */
|
||||||
|
std::map<unsigned int, USB_Interface *> mInterfaces;
|
||||||
|
};
|
||||||
|
|
||||||
|
class USB_Transfer {
|
||||||
|
public:
|
||||||
|
USB_Transfer(const USB_Device *dev, unsigned int id, struct libusb_transfer *lx);
|
||||||
|
USB_Transfer(USB__PT_PROVIDER *pt, const USB__transfer& send_par);
|
||||||
|
~USB_Transfer();
|
||||||
|
void submit();
|
||||||
|
void complete();
|
||||||
|
void log(const char *fmt, ...);
|
||||||
|
|
||||||
|
/* the USB device through which the transfer is sent */
|
||||||
|
const USB_Device *mDev;
|
||||||
|
/* ID the user gave the transfer, returned back to user on completion */
|
||||||
|
unsigned int mID;
|
||||||
|
/* the actaul libusb data structure */
|
||||||
|
struct libusb_transfer *mXfer;
|
||||||
|
private:
|
||||||
|
void init(const USB_Device *dev, unsigned int id, struct libusb_transfer *lx);
|
||||||
|
};
|
||||||
|
|
||||||
|
class USB__PT_PROVIDER : public PORT {
|
||||||
|
public:
|
||||||
|
USB__PT_PROVIDER(const char *par_port_name);
|
||||||
|
~USB__PT_PROVIDER();
|
||||||
|
|
||||||
|
void set_parameter(const char *parameter_name,
|
||||||
|
const char *parameter_value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void Handle_Fd_Event(int fd, boolean is_readable, boolean is_writable, boolean is_error);
|
||||||
|
/* void Handle_Timeout(double time_since_last_call); */
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void user_map(const char *system_port);
|
||||||
|
void user_unmap(const char *system_port);
|
||||||
|
|
||||||
|
void user_start();
|
||||||
|
void user_stop();
|
||||||
|
|
||||||
|
void outgoing_send(const USB__open__vid__pid& send_par);
|
||||||
|
void outgoing_send(const USB__transfer& send_par);
|
||||||
|
void outgoing_send(const USB__set__configuration& send_par);
|
||||||
|
void outgoing_send(const USB__claim__interface& send_par);
|
||||||
|
void outgoing_send(const USB__release__interface& send_par);
|
||||||
|
void outgoing_send(const USB__get__device__descriptor& send_par);
|
||||||
|
void outgoing_send(const USB__get__config__descriptor& send_par);
|
||||||
|
void outgoing_send(const USB__get__config__descriptor__by__value& send_par);
|
||||||
|
void outgoing_send(const USB__get__active__config__descriptor& send_par);
|
||||||
|
void outgoing_send(const USB__get__string__descriptor& send_par);
|
||||||
|
|
||||||
|
virtual void incoming_message(const USB__transfer__compl& incoming_par) = 0;
|
||||||
|
virtual void incoming_message(const USB__result& incoming_par) = 0;
|
||||||
|
virtual void incoming_message(const USB__descriptor& incoming_par) = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void log(const char *fmt, ...);
|
||||||
|
USB_Device *usbdev_by_hdl(unsigned int hdl);
|
||||||
|
void transfer_completed(USB_Transfer *t);
|
||||||
|
private:
|
||||||
|
libusb_context *mCtx;
|
||||||
|
std::map<unsigned int, USB_Device *> mDevices;
|
||||||
|
|
||||||
|
unsigned int usbhdl_by_dev(libusb_device_handle *dh);
|
||||||
|
|
||||||
|
/* to make them access protected Handler_{Add,Remove}_Fd methods */
|
||||||
|
friend void libusb_pollfd_added(int fd, short events, void *user_data);
|
||||||
|
friend void libusb_pollfd_removed(int fd, void *user_data);
|
||||||
|
friend void libusb_transfer_cb(struct libusb_transfer *xfer);
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* end of namespace */
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,22 @@
|
||||||
|
module USB_PortType {
|
||||||
|
import from USB_PortTypes all;
|
||||||
|
|
||||||
|
type port USB_PT message {
|
||||||
|
out USB_open_vid_pid;
|
||||||
|
out USB_set_configuration;
|
||||||
|
out USB_claim_interface;
|
||||||
|
out USB_release_interface;
|
||||||
|
in USB_result;
|
||||||
|
|
||||||
|
out USB_get_device_descriptor;
|
||||||
|
out USB_get_config_descriptor;
|
||||||
|
out USB_get_active_config_descriptor;
|
||||||
|
out USB_get_config_descriptor_by_value;
|
||||||
|
out USB_get_string_descriptor;
|
||||||
|
in USB_descriptor;
|
||||||
|
|
||||||
|
out USB_transfer;
|
||||||
|
in USB_transfer_compl;
|
||||||
|
} with { extension "provider" };
|
||||||
|
|
||||||
|
};
|
|
@ -0,0 +1,125 @@
|
||||||
|
module USB_PortTypes {
|
||||||
|
|
||||||
|
type enumerated USB_transfer_status {
|
||||||
|
USB_TRANSFER_COMPLETED,
|
||||||
|
USB_TRANSFER_ERROR,
|
||||||
|
USB_TRANSFER_TIMED_OUT,
|
||||||
|
USB_TRANSFER_CANCELLED,
|
||||||
|
USB_TRANSFER_STALL,
|
||||||
|
USB_TRANSFER_NO_DEVIC,
|
||||||
|
USB_TRANSFER_OVERFLOW
|
||||||
|
};
|
||||||
|
|
||||||
|
type integer USB_endpoint (0..255);
|
||||||
|
type integer USB_vendor_id (0..65535);
|
||||||
|
type integer USB_product_id (0..65535);
|
||||||
|
|
||||||
|
type enumerated USB_transfer_type {
|
||||||
|
USB_TRANSFER_TYPE_CONTROL,
|
||||||
|
USB_TRANSFER_TYPE_ISOCHRONOUS,
|
||||||
|
USB_TRANSFER_TYPE_BULK,
|
||||||
|
USB_TRANSFER_TYPE_INTERRUPT,
|
||||||
|
USB_TRANSFER_TYPE_BULK_STREAM
|
||||||
|
};
|
||||||
|
|
||||||
|
/* submit a USB transfer to the specified device / endpoint */
|
||||||
|
type record USB_transfer {
|
||||||
|
/* refers to a previously opened device */
|
||||||
|
integer device_hdl,
|
||||||
|
/* opaque value passed back in call-back */
|
||||||
|
integer transfer_hdl,
|
||||||
|
USB_endpoint endpoint,
|
||||||
|
USB_transfer_type ttype,
|
||||||
|
octetstring data,
|
||||||
|
integer timeout_msec
|
||||||
|
};
|
||||||
|
/* Response: USB_transfer_compl */
|
||||||
|
|
||||||
|
type record USB_transfer_compl {
|
||||||
|
/* refers to a previously opened device */
|
||||||
|
integer device_hdl,
|
||||||
|
/* opaque value passed back in call-back */
|
||||||
|
integer transfer_hdl,
|
||||||
|
USB_endpoint endpoint,
|
||||||
|
USB_transfer_type ttype,
|
||||||
|
octetstring data,
|
||||||
|
integer actual_length,
|
||||||
|
USB_transfer_status status
|
||||||
|
};
|
||||||
|
|
||||||
|
type record USB_result {
|
||||||
|
integer req_hdl,
|
||||||
|
integer device_hdl,
|
||||||
|
integer result_code
|
||||||
|
};
|
||||||
|
|
||||||
|
type record USB_open_vid_pid {
|
||||||
|
integer req_hdl,
|
||||||
|
integer device_hdl,
|
||||||
|
USB_vendor_id vendor_id,
|
||||||
|
USB_product_id product_id
|
||||||
|
};
|
||||||
|
/* Response: USB_result */
|
||||||
|
|
||||||
|
type record USB_set_configuration {
|
||||||
|
integer req_hdl,
|
||||||
|
integer device_hdl,
|
||||||
|
integer configuration
|
||||||
|
};
|
||||||
|
/* Response: USB_result */
|
||||||
|
|
||||||
|
type record USB_claim_interface {
|
||||||
|
integer req_hdl,
|
||||||
|
integer device_hdl,
|
||||||
|
integer interface
|
||||||
|
};
|
||||||
|
/* Response: USB_result */
|
||||||
|
|
||||||
|
type record USB_release_interface {
|
||||||
|
integer req_hdl,
|
||||||
|
integer device_hdl,
|
||||||
|
integer interface
|
||||||
|
};
|
||||||
|
/* Response: USB_result */
|
||||||
|
|
||||||
|
type record USB_get_device_descriptor {
|
||||||
|
integer req_hdl,
|
||||||
|
integer device_hdl
|
||||||
|
};
|
||||||
|
/* Response: USB_descriptor */
|
||||||
|
|
||||||
|
type record USB_get_config_descriptor {
|
||||||
|
integer req_hdl,
|
||||||
|
integer device_hdl,
|
||||||
|
integer config_index
|
||||||
|
};
|
||||||
|
/* Response: USB_descriptor */
|
||||||
|
|
||||||
|
type record USB_get_active_config_descriptor {
|
||||||
|
integer req_hdl,
|
||||||
|
integer device_hdl
|
||||||
|
};
|
||||||
|
/* Response: USB_descriptor */
|
||||||
|
|
||||||
|
type record USB_get_config_descriptor_by_value {
|
||||||
|
integer req_hdl,
|
||||||
|
integer device_hdl,
|
||||||
|
integer config_value
|
||||||
|
};
|
||||||
|
/* Response: USB_descriptor */
|
||||||
|
|
||||||
|
type record USB_get_string_descriptor {
|
||||||
|
integer req_hdl,
|
||||||
|
integer device_hdl,
|
||||||
|
integer index,
|
||||||
|
integer language_id
|
||||||
|
};
|
||||||
|
/* Response: USB_descriptor */
|
||||||
|
|
||||||
|
type record USB_descriptor {
|
||||||
|
integer req_hdl,
|
||||||
|
integer device_hdl,
|
||||||
|
integer result_code,
|
||||||
|
octetstring data
|
||||||
|
};
|
||||||
|
};
|
Loading…
Reference in New Issue