xpp: migrate everything to libxtalk

* Build new libxtalk as local convenience library
 * Have new mpptalk.[ch] and astribank.[ch] wrap the new API
 * Modify all tools to use the new API

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
This commit is contained in:
Oron Peled 2014-12-21 14:58:03 -05:00 committed by Tzafrir Cohen
parent 9c61e40187
commit 0e6b068e89
26 changed files with 1007 additions and 3017 deletions

View File

@ -8,7 +8,7 @@ man_MANS =
# FIXME: try to improve code, so we can use $(PEDANTIC)
#PEDANTIC = -ansi -pedantic -std=c99
GLOBAL_CFLAGS = -I$(srcdir) -I$(srcdir)/xtalk $(PEDANTIC)
GLOBAL_CFLAGS = -I$(srcdir) -I$(srcdir)/xtalk/include $(PEDANTIC) -Wall
if DAHDI_DEVMODE
GLOBAL_CFLAGS += \
@ -81,24 +81,14 @@ endif
noinst_LTLIBRARIES = libastribank.la libecholoader.la libhexfile.la
libastribank_la_SOURCES = \
astribank_usb.c \
astribank_usb.h \
astribank.c \
astribank.h \
mpptalk.c \
mpptalk.h \
mpp.h \
mpptalk_defs.h \
xtalk/debug.c \
xtalk/debug.h \
xtalk/xlist.c \
xtalk/xlist.h \
xtalk/xtalk.c \
xtalk/xtalk.h \
xtalk/xtalk_defs.h \
xtalk/xusb.c \
xtalk/xusb.h \
#
libastribank_la_CFLAGS = $(GLOBAL_CFLAGS)
libastribank_la_LIBADD = xtalk/libxtalk.la
if USE_OCTASIC
libecholoader_la_SOURCES = \

177
xpp/astribank.c Normal file
View File

@ -0,0 +1,177 @@
#include <assert.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <xtalk/debug.h>
#include <xtalk/xusb.h>
#include "mpptalk.h"
#include "astribank.h"
#define DBG_MASK 0x08
struct astribank {
struct xusb_device *xusb_device;
struct xusb_iface *xpp_iface;
struct xusb_iface *mpp_iface;
struct mpp_device *mpp;
char *path;
};
struct astribank *astribank_new(const char *path)
{
struct astribank *ab;
ab = calloc(sizeof(*ab), 1);
if (!ab) {
ERR("%s: Failed allocating Astribank device\n", path);
goto err;
}
ab->xusb_device = xusb_find_bypath(path);
if (!ab->xusb_device) {
ERR("%s: Cannot find Astribank\n", path);
goto err;
}
ab->path = strdup(path);
if (!ab->path) {
ERR("%s: Failed allocating Astribank path\n", path);
goto err;
}
return ab;
err:
astribank_destroy(ab);
return NULL;
}
void astribank_destroy(struct astribank *ab)
{
if (ab) {
if (ab->path)
free(ab->path);
if (ab->xpp_iface)
xusb_release(ab->xpp_iface);
if (ab->mpp) {
mpp_delete(ab->mpp); /* this also closes the underlying xusb */
ab->mpp = NULL;
}
if (ab->xusb_device) {
xusb_destroy(ab->xusb_device);
ab->xusb_device = NULL;
}
free(ab);
ab = NULL;
}
}
struct xusb_iface *astribank_xpp_open(struct astribank *ab)
{
int ret;
ret = xusb_claim(ab->xusb_device, 0, &ab->xpp_iface);
if (ret < 0) {
ERR("%s: Cannot claim XPP interface\n", ab->path);
goto err;
}
DBG("%s: Claimed Astribank XPP interface\n", ab->path);
return ab->xpp_iface;
err:
if (ab->xpp_iface)
xusb_release(ab->xpp_iface);
return NULL;
}
struct mpp_device *astribank_mpp_open(struct astribank *ab)
{
int ret;
ret = xusb_claim(ab->xusb_device, 1, &ab->mpp_iface);
if (ret < 0) {
ERR("%s: Cannot claim MPP interface\n", ab->path);
goto err;
}
DBG("%s: Claimed Astribank MPP interface\n", ab->path);
ab->mpp = mpp_new(ab->mpp_iface);
if (!ab->mpp) {
ERR("Failed initializing MPP protocol\n");
goto err;
}
ret = mpp_status_query(ab->mpp);
if (ret < 0) {
ERR("status query failed (ret=%d)\n", ret);
goto err;
}
return ab->mpp;
err:
if (ab->mpp) {
mpp_delete(ab->mpp); /* this also closes the underlying xusb */
ab->mpp = NULL;
}
return NULL;
}
struct xusb_device *xusb_dev_of_astribank(const struct astribank *ab)
{
assert(ab->xusb_device);
return ab->xusb_device;
}
const char *astribank_devpath(const struct astribank *ab)
{
return xusb_devpath(ab->xusb_device);
}
const char *astribank_serial(const struct astribank *ab)
{
return xusb_serial(ab->xusb_device);
}
void show_astribank_info(const struct astribank *ab)
{
struct xusb_device *xusb_device;
assert(ab != NULL);
xusb_device = ab->xusb_device;
assert(xusb_device != NULL);
if(verbose <= LOG_INFO) {
xusb_showinfo(xusb_device);
} else {
const struct xusb_spec *spec;
spec = xusb_spec(xusb_device);
printf("USB Bus/Device: [%s]\n", xusb_devpath(xusb_device));
printf("USB Firmware Type: [%s]\n", spec->name);
printf("USB iSerialNumber: [%s]\n", xusb_serial(xusb_device));
printf("USB iManufacturer: [%s]\n", xusb_manufacturer(xusb_device));
printf("USB iProduct: [%s]\n", xusb_product(xusb_device));
}
}
int astribank_send(struct astribank *ab, int interface_num, const char *buf, int len, int timeout)
{
struct xusb_iface *iface;
if (interface_num == 0)
iface = ab->xpp_iface;
else if (interface_num == 1)
iface = ab->mpp_iface;
else {
ERR("Unknown interface number (%d)\n", interface_num);
return -EINVAL;
}
return xusb_send(iface, buf, len, timeout);
}
int astribank_recv(struct astribank *ab, int interface_num, char *buf, size_t len, int timeout)
{
struct xusb_iface *iface;
if (interface_num == 0)
iface = ab->xpp_iface;
else if (interface_num == 1)
iface = ab->mpp_iface;
else {
ERR("Unknown interface number (%d)\n", interface_num);
return -EINVAL;
}
return xusb_recv(iface, buf, len, timeout);
}

33
xpp/astribank.h Normal file
View File

@ -0,0 +1,33 @@
#ifndef ASTRIBANK_H
#define ASTRIBANK_H
#include <mpptalk.h>
struct astribank *astribank_new(const char *path);
void astribank_destroy(struct astribank *ab);
void show_astribank_info(const struct astribank *ab);
struct xusb_iface *astribank_xpp_open(struct astribank *ab);
struct mpp_device *astribank_mpp_open(struct astribank *ab);
struct xusb_device *xusb_dev_of_astribank(const struct astribank *ab);
const char *astribank_devpath(const struct astribank *ab);
const char *astribank_serial(const struct astribank *ab);
int astribank_send(struct astribank *ab, int interface_num, const char *buf, int len, int timeout);
int astribank_recv(struct astribank *ab, int interface_num, char *buf, size_t len, int timeout);
#define AB_REPORT(report_type, astribank, fmt, ...) \
report_type("%s [%s]: " fmt, \
astribank_devpath(astribank), \
astribank_serial(astribank), \
## __VA_ARGS__)
#define AB_INFO(astribank, fmt, ...) \
AB_REPORT(INFO, astribank, fmt, ## __VA_ARGS__)
#define AB_ERR(astribank, fmt, ...) \
AB_REPORT(ERR, astribank, fmt, ## __VA_ARGS__)
#endif /* ASTRIBANK_H */

View File

@ -31,9 +31,9 @@
#include <sys/types.h>
#include <arpa/inet.h>
#include <ctype.h>
#include "mpp.h"
#include <xtalk/debug.h>
#include "mpptalk.h"
#include <debug.h>
#include "astribank.h"
#include "astribank_license.h"
static const char rcsid[] = "$Id$";
@ -55,28 +55,11 @@ static void usage()
exit(1);
}
static int capabilities_burn(
struct astribank_device *astribank,
struct eeprom_table *eeprom_table,
struct capabilities *capabilities,
struct capkey *key)
{
int ret;
INFO("Burning capabilities\n");
ret = mpp_caps_set(astribank, eeprom_table, capabilities, key);
if(ret < 0) {
ERR("Capabilities burning failed: %d\n", ret);
return ret;
}
INFO("Done\n");
return 0;
}
int main(int argc, char *argv[])
{
char *devpath = NULL;
struct astribank_device *astribank;
struct astribank *astribank;
struct mpp_device *mpp;
struct eeprom_table eeprom_table;
struct capabilities caps;
struct capkey key;
@ -127,16 +110,19 @@ int main(int argc, char *argv[])
usage();
}
DBG("Startup %s\n", devpath);
if((astribank = mpp_init(devpath, 1)) == NULL) {
ERR("Failed initializing MPP\n");
astribank = astribank_new(devpath);
if(!astribank) {
ERR("Failed initializing Astribank\n");
return 1;
}
if(astribank->eeprom_type != EEPROM_TYPE_LARGE) {
mpp = astribank_mpp_open(astribank);
ret = mpp_eeprom_type(mpp);
if(ret != EEPROM_TYPE_LARGE) {
ERR("Cannot use this program with astribank EEPROM type %d (need %d)\n",
astribank->eeprom_type, EEPROM_TYPE_LARGE);
ret, EEPROM_TYPE_LARGE);
return 1;
}
ret = mpp_caps_get(astribank, &eeprom_table, &caps, &key);
ret = mpp_caps_get(mpp, &eeprom_table, &caps, &key);
if(ret < 0) {
ERR("Failed to get original capabilities: %d\n", ret);
return 1;
@ -158,8 +144,13 @@ int main(int argc, char *argv[])
return 1;
}
show_capabilities(&caps, stderr);
if (capabilities_burn(astribank, &eeprom_table, &caps, &key) < 0)
INFO("Burning capabilities\n");
ret = mpp_caps_set(mpp, &eeprom_table, &caps, &key);
if(ret < 0) {
ERR("Capabilities burning failed: %d\n", ret);
return 1;
}
INFO("Done\n");
if (file != stdin)
fclose(file);
} else {
@ -180,6 +171,6 @@ int main(int argc, char *argv[])
if (file != stdout)
fclose(file);
}
mpp_exit(astribank);
astribank_destroy(astribank);
return 0;
}

View File

@ -28,13 +28,14 @@
#include <errno.h>
#include <assert.h>
#include <arpa/inet.h>
#include <debug.h>
#include <autoconfig.h>
#include <xtalk/debug.h>
#include <xtalk/xusb.h>
#include "hexfile.h"
#include "mpptalk.h"
#include "astribank.h"
#include "pic_loader.h"
#include "echo_loader.h"
#include "astribank_usb.h"
#include "../autoconfig.h"
#define DBG_MASK 0x80
#define MAX_HEX_LINES 64000
@ -61,7 +62,7 @@ static void usage()
exit(1);
}
int handle_hexline(struct astribank_device *astribank, struct hexline *hexline)
int handle_hexline(struct mpp_device *mpp, struct hexline *hexline)
{
uint16_t len;
uint16_t offset_dummy;
@ -69,7 +70,7 @@ int handle_hexline(struct astribank_device *astribank, struct hexline *hexline)
int ret;
assert(hexline);
assert(astribank);
assert(mpp);
if(hexline->d.content.header.tt != TT_DATA) {
DBG("Non data record type = %d\n", hexline->d.content.header.tt);
return 0;
@ -77,7 +78,7 @@ int handle_hexline(struct astribank_device *astribank, struct hexline *hexline)
len = hexline->d.content.header.ll;
offset_dummy = hexline->d.content.header.offset;
data = hexline->d.content.tt_data.data;
if((ret = mpp_send_seg(astribank, data, offset_dummy, len)) < 0) {
if((ret = mpp_send_seg(mpp, data, offset_dummy, len)) < 0) {
ERR("Failed hexfile send line: %d\n", ret);
return -EINVAL;
}
@ -100,7 +101,7 @@ static void print_parse_errors(int level, const char *msg, ...)
}
}
static int load_hexfile(struct astribank_device *astribank, const char *hexfile, enum dev_dest dest)
static int load_hexfile(struct mpp_device *mpp, const char *hexfile, enum dev_dest dest)
{
struct hexdata *hexdata = NULL;
int finished = 0;
@ -108,19 +109,24 @@ static int load_hexfile(struct astribank_device *astribank, const char *hexfile,
unsigned i;
char star[] = "+\\+|+/+-";
const char *devstr;
struct xusb_device *xusb_device;
struct xusb_iface *xusb_iface;
parse_hexfile_set_reporting(print_parse_errors);
if((hexdata = parse_hexfile(hexfile, MAX_HEX_LINES)) == NULL) {
perror(hexfile);
return -errno;
}
devstr = xusb_devpath(astribank->xusb);
xusb_iface = xubs_iface_of_mpp(mpp);
xusb_device = xusb_deviceof(xusb_iface);
devstr = xusb_devpath(xusb_device);
INFO("%s [%s]: Loading %s Firmware: %s (version %s)\n",
devstr,
xusb_serial(astribank->xusb),
xusb_serial(xusb_device),
dev_dest2str(dest),
hexdata->fname, hexdata->version_info);
if((ret = mpp_send_start(astribank, dest, hexdata->version_info)) < 0) {
if((ret = mpp_send_start(mpp, dest, hexdata->version_info)) < 0) {
ERR("%s: Failed hexfile send start: %d\n", devstr, ret);
return ret;
}
@ -142,7 +148,7 @@ static int load_hexfile(struct astribank_device *astribank, const char *hexfile,
finished = 1;
continue;
}
if((ret = handle_hexline(astribank, hexline)) < 0) {
if((ret = handle_hexline(mpp, hexline)) < 0) {
ERR("%s: Failed hexfile sending in lineno %d (ret=%d)\n", devstr, i, ret);;
return ret;
}
@ -151,7 +157,7 @@ static int load_hexfile(struct astribank_device *astribank, const char *hexfile,
putchar('\n');
fflush(stdout);
}
if((ret = mpp_send_end(astribank)) < 0) {
if((ret = mpp_send_end(mpp)) < 0) {
ERR("%s: Failed hexfile send end: %d\n", devstr, ret);
return ret;
}
@ -178,7 +184,6 @@ int main(int argc, char *argv[])
int opt_sum = 0;
enum dev_dest dest = DEST_NONE;
const char options[] = "vd:D:EFOopAS:";
int iface_num;
int ret;
progname = argv[0];
@ -247,7 +252,6 @@ int main(int argc, char *argv[])
" and -p options are mutually exclusive, if neither is used then -o should present\n");
usage();
}
iface_num = (opt_dest) ? 1 : 0;
if(!opt_pic && !opt_ecver) {
if(optind != argc - 1) {
ERR("Got %d hexfile names (Need exactly one hexfile)\n",
@ -270,29 +274,43 @@ int main(int argc, char *argv[])
/*
* MPP Interface
*/
struct astribank_device *astribank;
struct astribank *astribank;
struct mpp_device *mpp;
if((astribank = mpp_init(devpath, iface_num)) == NULL) {
astribank = astribank_new(devpath);
if(!astribank) {
ERR("%s: Opening astribank failed\n", devpath);
return 1;
}
//show_astribank_info(astribank);
if(load_hexfile(astribank, argv[optind], dest) < 0) {
mpp = astribank_mpp_open(astribank);
if(!mpp) {
ERR("%s: Opening astribank XPP interface failed\n", devpath);
return 1;
}
show_astribank_info(astribank);
if(load_hexfile(mpp, argv[optind], dest) < 0) {
ERR("%s: Loading firmware to %s failed\n", devpath, dev_dest2str(dest));
return 1;
}
astribank_close(astribank, 0);
astribank_destroy(astribank);
} else if(opt_pic || opt_echo || opt_ecver) {
/*
* XPP Interface
*/
struct astribank_device *astribank;
struct astribank *astribank;
struct xusb_iface *xpp_iface;
if((astribank = astribank_open(devpath, iface_num)) == NULL) {
astribank = astribank_new(devpath);
if (!astribank) {
ERR("%s: Opening astribank failed\n", devpath);
return 1;
}
//show_astribank_info(astribank);
xpp_iface = astribank_xpp_open(astribank);
if(!xpp_iface) {
ERR("%s: Opening astribank XPP interface failed\n", devpath);
return 1;
}
show_astribank_info(astribank);
#if HAVE_OCTASIC
if (opt_ecver) {
if((ret = echo_ver(astribank)) < 0) {
@ -315,7 +333,7 @@ int main(int argc, char *argv[])
}
#endif
}
astribank_close(astribank, 0);
astribank_destroy(astribank);
}
return 0;
}

View File

@ -24,7 +24,7 @@
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <debug.h>
#include <xtalk/debug.h>
#include "astribank_license.h"
#define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))

View File

@ -1,7 +1,7 @@
#ifndef ASTRIBANK_ALLOW_H
#define ASTRIBANK_ALLOW_H
#include "mpp.h"
#include "mpptalk.h"
enum license_markers {
LICENSE_MARKER_NONE = 0,

View File

@ -28,10 +28,10 @@
#include <getopt.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include "astribank_usb.h"
#include <xtalk/debug.h>
#include <xtalk/xusb.h>
#include "mpptalk.h"
#include <debug.h>
#include <xusb.h>
#include "astribank.h"
#define DBG_MASK 0x80
/* if enabled, adds support for resetting pre-MPP USB firmware - if we
@ -76,90 +76,11 @@ static int reset_kind(const char *arg)
return -1;
}
static int show_hardware(struct astribank_device *astribank)
{
int ret;
struct eeprom_table eeprom_table;
struct capabilities capabilities;
struct extrainfo extrainfo;
ret = mpp_caps_get(astribank, &eeprom_table, &capabilities, NULL);
if(ret < 0)
return ret;
show_eeprom(&eeprom_table, stdout);
show_astribank_status(astribank, stdout);
if(astribank->eeprom_type == EEPROM_TYPE_LARGE) {
show_capabilities(&capabilities, stdout);
if(STATUS_FPGA_LOADED(astribank->status)) {
uint8_t unit;
uint8_t card_status;
uint8_t card_type;
uint8_t fpga_configuration;
uint8_t status;
for(unit = 0; unit < 5; unit++) {
ret = mpps_card_info(astribank, unit, &card_type, &card_status);
if(ret < 0)
return ret;
printf("CARD %d: type=%x.%x %s\n", unit,
((card_type >> 4) & 0xF), (card_type & 0xF),
((card_status & 0x1) ? "PIC" : "NOPIC"));
}
ret = mpps_stat(astribank, unit, &fpga_configuration, &status);
if (ret < 0)
return ret;
printf("FPGA: %-17s: %d\n", "Configuration num", fpga_configuration);
printf("FPGA: %-17s: %s\n", "Watchdog Timer",
(SER_STAT_WATCHDOG_READY(status)) ? "ready" : "expired");
printf("FPGA: %-17s: %s\n", "XPD Alive",
(SER_STAT_XPD_ALIVE(status)) ? "yes" : "no");
}
ret = mpp_extrainfo_get(astribank, &extrainfo);
if(ret < 0)
return ret;
show_extrainfo(&extrainfo, stdout);
if(CAP_EXTRA_TWINSTAR(&capabilities)) {
twinstar_show(astribank, stdout);
}
}
return 0;
}
#ifdef SUPPORT_OLD_RESET
/* Try to reset a device using USB_FW.hex, up to Xorcom rev. 6885 */
int old_reset(const char* devpath)
{
struct astribank_device *astribank;
int ret;
struct {
uint8_t op;
} PACKED header = {0x20}; /* PT_RESET */
char *buf = (char*) &header;
/* Note that the function re-opens the connection to the Astribank
* as any reference to the previous connection was lost when mpp_open
* returned NULL as the astribank reference. */
astribank = astribank_open(devpath, 1);
if (!astribank) {
DBG("Failed re-opening astribank device for old_reset\n");
return -ENODEV;
}
ret = xusb_send(astribank->xusb, buf, 1, 5000);
/* If we just had a reenumeration, we may get -ENODEV */
if(ret < 0 && ret != -ENODEV)
return ret;
/* We don't astribank_close(), as it has likely been
* reenumerated by now. */
return 0;
}
#endif /* SUPPORT_OLD_RESET */
int main(int argc, char *argv[])
{
char *devpath = NULL;
struct astribank_device *astribank;
struct astribank *astribank;
struct mpp_device *mpp;
const char options[] = "vd:D:nr:p:w:Q";
int opt_renumerate = 0;
char *opt_port = NULL;
@ -218,20 +139,12 @@ int main(int argc, char *argv[])
usage();
}
DBG("Startup %s\n", devpath);
if((astribank = mpp_init(devpath, 1)) == NULL) {
ERR("Failed initializing MPP\n");
#ifdef SUPPORT_OLD_RESET
DBG("opt_reset = %s\n", opt_reset);
if (opt_reset) {
DBG("Trying old reset method\n");
if ((ret = old_reset(devpath)) != 0) {
ERR("Old reset method failed as well: %d\n", ret);
}
}
#endif /* SUPPORT_OLD_RESET */
astribank = astribank_new(devpath);
if(!astribank) {
ERR("Failed initializing Astribank\n");
return 1;
}
mpp = astribank_mpp_open(astribank);
/*
* First process reset options. We want to be able
* to reset minimal USB firmwares even if they don't
@ -245,7 +158,7 @@ int main(int argc, char *argv[])
return 1;
}
DBG("Reseting (%s)\n", opt_reset);
if((ret = mpp_reset(astribank, full_reset)) < 0) {
if((ret = mpp_reset(mpp, full_reset)) < 0) {
ERR("%s Reseting astribank failed: %d\n",
(full_reset) ? "Full" : "Half", ret);
}
@ -253,10 +166,10 @@ int main(int argc, char *argv[])
}
show_astribank_info(astribank);
if(opt_query) {
show_hardware(astribank);
show_hardware(mpp);
} else if(opt_renumerate) {
DBG("Renumerate\n");
if((ret = mpp_renumerate(astribank)) < 0) {
if((ret = mpp_renumerate(mpp)) < 0) {
ERR("Renumerating astribank failed: %d\n", ret);
}
} else if(opt_watchdog) {
@ -264,24 +177,24 @@ int main(int argc, char *argv[])
DBG("TWINSTAR: Setting watchdog %s-guard\n",
(watchdogstate) ? "on" : "off");
if((ret = mpp_tws_setwatchdog(astribank, watchdogstate)) < 0) {
if((ret = mpp_tws_setwatchdog(mpp, watchdogstate)) < 0) {
ERR("Failed to set watchdog to %d\n", watchdogstate);
return 1;
}
} else if(opt_port) {
int new_portnum = strtoul(opt_port, NULL, 0);
int tws_portnum = mpp_tws_portnum(astribank);
int tws_portnum = mpp_tws_portnum(mpp);
char *msg = (new_portnum == tws_portnum)
? " Same same, never mind..."
: "";
DBG("TWINSTAR: Setting portnum to %d.%s\n", new_portnum, msg);
if((ret = mpp_tws_setportnum(astribank, new_portnum)) < 0) {
if((ret = mpp_tws_setportnum(mpp, new_portnum)) < 0) {
ERR("Failed to set USB portnum to %d\n", new_portnum);
return 1;
}
}
out:
mpp_exit(astribank);
astribank_destroy(astribank);
return 0;
}

View File

@ -1,276 +0,0 @@
/*
* Written by Oron Peled <oron@actcom.co.il>
* Copyright (C) 2008, Xorcom
*
* 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.
*
*/
#define _GNU_SOURCE /* for memrchr() */
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <stdarg.h>
#include <syslog.h>
#include <arpa/inet.h>
#include <xusb.h>
#include "astribank_usb.h"
#include <debug.h>
static const char rcsid[] = "$Id$";
#define DBG_MASK 0x01
#define TIMEOUT 500
#define TYPE_ENTRY(t,p,ni,n,ne,out,in,...) \
{ \
.my_vendor_id = 0xe4e4, \
.my_product_id = (p), \
.name = #t, \
.num_interfaces = (ni), \
.my_interface_num = (n), \
.num_endpoints = (ne), \
.my_ep_in = (in), \
.my_ep_out = (out), \
}
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
static const struct xusb_spec astribank_specs[] = {
/* OLD Firmwares */
TYPE_ENTRY("USB-OLDFXS", 0x1131, 2, 1, 2, MP_EP_OUT, MP_EP_IN),
TYPE_ENTRY("FPGA-OLDFXS", 0x1132, 2, 1, 2, MP_EP_OUT, MP_EP_IN),
TYPE_ENTRY("USB-BRI", 0x1141, 2, 1, 2, MP_EP_OUT, MP_EP_IN),
TYPE_ENTRY("FPGA-BRI", 0x1142, 2, 1, 2, MP_EP_OUT, MP_EP_IN),
TYPE_ENTRY("USB-OLD", 0x1151, 2, 1, 2, MP_EP_OUT, MP_EP_IN),
TYPE_ENTRY("FPGA-OLD", 0x1152, 2, 1, 2, MP_EP_OUT, MP_EP_IN),
TYPE_ENTRY("USB-MULTI", 0x1161, 2, 1, 2, MP_EP_OUT, MP_EP_IN),
TYPE_ENTRY("FPGA-MULTI", 0x1162, 2, 1, 2, MP_EP_OUT, MP_EP_IN),
TYPE_ENTRY("BURNED-MULTI", 0x1164, 2, 1, 2, MP_EP_OUT, MP_EP_IN),
TYPE_ENTRY("USB-BURN", 0x1112, 2, 1, 2, MP_EP_OUT, MP_EP_IN),
};
static const struct xusb_spec astribank_pic_specs[] = {
TYPE_ENTRY("USB_PIC", 0x1161, 2, 0, 2, XPP_EP_OUT, XPP_EP_IN),
};
#undef TYPE_ENTRY
//static int verbose = LOG_DEBUG;
/*
* USB handling
*/
struct astribank_device *astribank_open(const char devpath[], int iface_num)
{
struct astribank_device *astribank = NULL;
struct xusb *xusb;
DBG("devpath='%s' iface_num=%d\n", devpath, iface_num);
if((astribank = malloc(sizeof(struct astribank_device))) == NULL) {
ERR("Out of memory\n");
goto fail;
}
memset(astribank, 0, sizeof(*astribank));
if (iface_num) {
xusb = xusb_find_bypath(astribank_specs, ARRAY_SIZE(astribank_specs), devpath);
} else {
xusb = xusb_find_bypath(astribank_pic_specs, ARRAY_SIZE(astribank_pic_specs), devpath);
}
if (!xusb) {
ERR("%s: No device found\n", __func__);
goto fail;
}
astribank->xusb = xusb;
astribank->is_usb2 = (xusb_packet_size(xusb) == 512);
astribank->my_interface_num = iface_num;
if (xusb_claim_interface(astribank->xusb) < 0) {
ERR("xusb_claim_interface failed\n");
goto fail;
}
astribank->tx_sequenceno = 1;
return astribank;
fail:
if (astribank) {
free(astribank);
astribank = NULL;
}
return NULL;
}
/*
* MP device handling
*/
void show_astribank_info(const struct astribank_device *astribank)
{
struct xusb *xusb;
assert(astribank != NULL);
xusb = astribank->xusb;
assert(xusb != NULL);
if(verbose <= LOG_INFO) {
xusb_showinfo(xusb);
} else {
const struct xusb_spec *spec;
spec = xusb_spec(xusb);
printf("USB Bus/Device: [%s]\n", xusb_devpath(xusb));
printf("USB Firmware Type: [%s]\n", spec->name);
printf("USB iSerialNumber: [%s]\n", xusb_serial(xusb));
printf("USB iManufacturer: [%s]\n", xusb_manufacturer(xusb));
printf("USB iProduct: [%s]\n", xusb_product(xusb));
}
}
void astribank_close(struct astribank_device *astribank, int disconnected)
{
assert(astribank != NULL);
if (astribank->xusb) {
xusb_close(astribank->xusb);
astribank->xusb = NULL;
}
astribank->tx_sequenceno = 0;
}
#if 0
int flush_read(struct astribank_device *astribank)
{
char tmpbuf[BUFSIZ];
int ret;
DBG("starting...\n");
memset(tmpbuf, 0, BUFSIZ);
ret = recv_usb(astribank, tmpbuf, BUFSIZ, 1);
if(ret < 0 && ret != -ETIMEDOUT) {
ERR("ret=%d\n", ret);
return ret;
} else if(ret > 0) {
DBG("Got %d bytes:\n", ret);
dump_packet(LOG_DEBUG, DBG_MASK, __FUNCTION__, tmpbuf, ret);
}
return 0;
}
#endif
int release_isvalid(uint16_t release)
{
uint8_t rmajor = (release >> 8) & 0xFF;
uint8_t rminor = release & 0xFF;
return (rmajor > 0) &&
(rmajor < 10) &&
(rminor > 0) &&
(rminor < 10);
}
int label_isvalid(const char *label)
{
int len;
int goodlen;
const char GOOD_CHARS[] =
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789"
"-_.";
len = strlen(label);
goodlen = strspn(label, GOOD_CHARS);
if(len > LABEL_SIZE) {
ERR("Label too long (%d > %d)\n", len, LABEL_SIZE);
return 0;
}
if(goodlen != len) {
ERR("Bad character in label (pos=%d)\n", goodlen);
return 0;
}
return 1;
}
int eeprom_fill(struct eeprom_table *eprm,
const char *vendor,
const char *product,
const char *release,
const char *label)
{
uint16_t val;
eprm->source = 0xC0;
eprm->config_byte = 0;
if(vendor) {
val = strtoul(vendor, NULL, 0);
if(!val) {
ERR("Invalid vendor '%s'\n",
vendor);
return -EINVAL;
}
eprm->vendor = val;
}
if(product) {
val = strtoul(product, NULL, 0);
if(!val) {
ERR("Invalid product '%s'\n",
product);
return -EINVAL;
}
eprm->product = val;
}
if(release) {
int release_major = 0;
int release_minor = 0;
uint16_t value;
if(sscanf(release, "%d.%d", &release_major, &release_minor) != 2) {
ERR("Failed to parse release number '%s'\n", release);
return -EINVAL;
}
value = (release_major << 8) | release_minor;
DBG("Parsed release(%d): major=%d, minor=%d\n",
value, release_major, release_minor);
if(!release_isvalid(value)) {
ERR("Invalid release number 0x%X\n", value);
return -EINVAL;
}
eprm->release = value;
}
if(label) {
/* padding */
if(!label_isvalid(label)) {
ERR("Invalid label '%s'\n", label);
return -EINVAL;
}
memset(eprm->label, 0, LABEL_SIZE);
memcpy(eprm->label, label, strlen(label));
}
return 0;
}
int astribank_has_twinstar(struct astribank_device *astribank)
{
uint16_t product_series;
assert(astribank != NULL);
product_series = xusb_product_id(astribank->xusb);
product_series &= 0xFFF0;
if(product_series == 0x1160) /* New boards */
return 1;
return 0;
}

View File

@ -1,113 +0,0 @@
#ifndef ASTRIBANK_USB_H
#define ASTRIBANK_USB_H
/*
* Written by Oron Peled <oron@actcom.co.il>
* Copyright (C) 2008, Xorcom
*
* 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 <xusb.h>
#include <xtalk.h>
#include "mpp.h"
/*
* Astribank handling
*/
#define PACKET_SIZE 512
/* USB Endpoints */
#define MP_EP_OUT 0x04 /* Managment processor */
#define MP_EP_IN 0x88 /* Managment processor */
#define XPP_EP_OUT 0x02 /* XPP */
#define XPP_EP_IN 0x86 /* XPP */
/* USB firmware types */
#define USB_11xx 0
#define USB_FIRMWARE_II 1
#define USB_PIC 2
struct interface_type {
int type_code;
int num_interfaces;
int my_interface_num;
int num_endpoints;
int my_ep_out;
int my_ep_in;
char *name;
int endpoints[4]; /* for matching */
};
enum eeprom_burn_state {
BURN_STATE_NONE = 0,
BURN_STATE_STARTED = 1,
BURN_STATE_ENDED = 2,
BURN_STATE_FAILED = 3,
};
struct astribank_device {
struct xusb *xusb;
struct xtalk_device *xtalk_dev;
usb_dev_handle *handle;
int my_interface_num;
int my_ep_out;
int my_ep_in;
char iInterface[BUFSIZ];
int is_usb2;
enum eeprom_type eeprom_type;
enum eeprom_burn_state burn_state;
uint8_t status;
uint8_t mpp_proto_version;
struct eeprom_table *eeprom;
struct firmware_versions fw_versions;
uint16_t tx_sequenceno;
};
/*
* Prototypes
*/
struct astribank_device *astribank_open(const char devpath[], int iface_num);
void astribank_close(struct astribank_device *astribank, int disconnected);
void show_astribank_info(const struct astribank_device *astribank);
int send_usb(struct astribank_device *astribank, char *buf, int len, int timeout);
int recv_usb(struct astribank_device *astribank, char *buf, size_t len, int timeout);
int flush_read(struct astribank_device *astribank);
int eeprom_fill(struct eeprom_table *eprm,
const char *vendor,
const char *product,
const char *release,
const char *label);
int astribank_has_twinstar(struct astribank_device *astribank);
int label_isvalid(const char *label);
#define AB_REPORT(report_type, astribank, fmt, ...) \
report_type("%s [%s]: " fmt, \
xusb_devpath((astribank)->xusb), \
xusb_serial((astribank)->xusb), \
## __VA_ARGS__)
#define AB_INFO(astribank, fmt, ...) \
AB_REPORT(INFO, astribank, fmt, ## __VA_ARGS__)
#define AB_ERR(astribank, fmt, ...) \
AB_REPORT(ERR, astribank, fmt, ## __VA_ARGS__)
#endif /* ASTRIBANK_USB_H */

View File

@ -28,12 +28,21 @@
#include <limits.h>
#include <regex.h>
#include <sys/time.h>
#include "echo_loader.h"
#include "debug.h"
#include <unistd.h>
#include <oct6100api/oct6100_api.h>
#include <xtalk/debug.h>
#include <xtalk/xusb.h>
#include <astribank.h>
#include "echo_loader.h"
#include "parse_span_specs.h"
#define DBG_MASK 0x03
#ifdef __GNUC__
#define PACKED __attribute__((packed))
#else
#define PACKED
#endif
#define DBG_MASK 0x10
#define TIMEOUT 1000
#define ECHO_MAX_CHANS 128
#define ECHO_RIN_STREAM 0
@ -53,7 +62,7 @@ static float oct_fw_load_timeout = 2.0;
struct echo_mod {
tPOCT6100_INSTANCE_API pApiInstance;
UINT32 ulEchoChanHndl[256];
struct astribank_device *astribank;
struct astribank *astribank;
int maxchans;
};
@ -100,9 +109,9 @@ static struct usb_buffer {
} usb_buffer;
static void usb_buffer_init(struct astribank_device *astribank, struct usb_buffer *ub)
static void usb_buffer_init(struct astribank *astribank, struct usb_buffer *ub)
{
ub->max_len = xusb_packet_size(astribank->xusb);
ub->max_len = xusb_packet_size(xusb_dev_of_astribank(astribank));
ub->curr = 0;
ub->min_send = INT_MAX;
ub->max_send = 0;
@ -120,7 +129,7 @@ static long usb_buffer_usec(struct usb_buffer *ub)
(now.tv_usec - ub->start.tv_usec);
}
static void usb_buffer_showstatistics(struct astribank_device *astribank, struct usb_buffer *ub)
static void usb_buffer_showstatistics(struct astribank *astribank, struct usb_buffer *ub)
{
long usec;
@ -133,7 +142,7 @@ static void usb_buffer_showstatistics(struct astribank_device *astribank, struct
usec / 1000, usec / ub->num_sends);
}
static int usb_buffer_flush(struct astribank_device *astribank, struct usb_buffer *ub)
static int usb_buffer_flush(struct astribank *astribank, struct usb_buffer *ub)
{
int ret;
long t;
@ -142,7 +151,7 @@ static int usb_buffer_flush(struct astribank_device *astribank, struct usb_buffe
if (ub->curr == 0)
return 0;
ret = xusb_send(astribank->xusb, ub->data, ub->curr, TIMEOUT);
ret = astribank_send(astribank, 0, ub->data, ub->curr, TIMEOUT);
if (ret < 0) {
AB_ERR(astribank, "xusb_send failed: %d\n", ret);
return ret;
@ -175,7 +184,7 @@ static int usb_buffer_flush(struct astribank_device *astribank, struct usb_buffe
return ret;
}
static int usb_buffer_append(struct astribank_device *astribank, struct usb_buffer *ub,
static int usb_buffer_append(struct astribank *astribank, struct usb_buffer *ub,
char *buf, int len)
{
if (ub->curr + len >= ub->max_len) {
@ -188,7 +197,7 @@ static int usb_buffer_append(struct astribank_device *astribank, struct usb_buff
return len;
}
static int usb_buffer_send(struct astribank_device *astribank, struct usb_buffer *ub,
static int usb_buffer_send(struct astribank *astribank, struct usb_buffer *ub,
char *buf, int len, int timeout, int recv_answer)
{
int ret = 0;
@ -209,7 +218,7 @@ static int usb_buffer_send(struct astribank_device *astribank, struct usb_buffer
ret = usb_buffer_flush(astribank, ub);
if (ret < 0)
return ret;
ret = xusb_recv(astribank->xusb, buf, PACKET_SIZE, TIMEOUT);
ret = astribank_recv(astribank, 0, buf, PACKET_SIZE, TIMEOUT);
if (ret <= 0) {
AB_ERR(astribank, "No USB packs to read: %s\n", strerror(-ret));
return -EINVAL;
@ -239,7 +248,7 @@ static int usb_buffer_send(struct astribank_device *astribank, struct usb_buffer
return ret;
}
int spi_send(struct astribank_device *astribank, uint16_t addr, uint16_t data, int recv_answer, int ver)
int spi_send(struct astribank *astribank, uint16_t addr, uint16_t data, int recv_answer, int ver)
{
int ret;
char buf[PACKET_SIZE];
@ -272,7 +281,7 @@ int spi_send(struct astribank_device *astribank, uint16_t addr, uint16_t data, i
return ret;
}
int test_send(struct astribank_device *astribank)
int test_send(struct astribank *astribank)
{
int ret;
char buf[PACKET_SIZE];
@ -300,7 +309,7 @@ int test_send(struct astribank_device *astribank)
return ret;
}
int echo_send_data(struct astribank_device *astribank, const unsigned int addr, const unsigned int data)
int echo_send_data(struct astribank *astribank, const unsigned int addr, const unsigned int data)
{
int ret;
/* DBG("SEND: %04X -> [%04X]\n", data, addr);
@ -330,7 +339,7 @@ failed:
return ret;
}
int echo_recv_data(struct astribank_device *astribank, const unsigned int addr)
int echo_recv_data(struct astribank *astribank, const unsigned int addr)
{
unsigned int data = 0x00;
int ret;
@ -452,7 +461,7 @@ UINT32 Oct6100UserDriverWriteApi(tPOCT6100_WRITE_PARAMS f_pWriteParams)
const unsigned int addr = f_pWriteParams->ulWriteAddress;
const unsigned int data = f_pWriteParams->usWriteData;
const struct echo_mod *echo_mod = (struct echo_mod *)(f_pWriteParams->pProcessContext);
struct astribank_device *astribank = echo_mod->astribank;
struct astribank *astribank = echo_mod->astribank;
int ret;
ret = echo_send_data(astribank, addr, data);
@ -469,7 +478,7 @@ UINT32 Oct6100UserDriverWriteSmearApi(tPOCT6100_WRITE_SMEAR_PARAMS f_pSmearParam
unsigned int data;
unsigned int len;
const struct echo_mod *echo_mod;
struct astribank_device *astribank;
struct astribank *astribank;
unsigned int i;
len = f_pSmearParams->ulWriteLength;
@ -495,7 +504,7 @@ UINT32 Oct6100UserDriverWriteBurstApi(tPOCT6100_WRITE_BURST_PARAMS f_pBurstParam
unsigned int data;
unsigned int len = f_pBurstParams->ulWriteLength;
const struct echo_mod *echo_mod = (struct echo_mod *)f_pBurstParams->pProcessContext;
struct astribank_device *astribank = echo_mod->astribank;
struct astribank *astribank = echo_mod->astribank;
unsigned int i;
for (i = 0; i < len; i++) {
@ -516,7 +525,7 @@ UINT32 Oct6100UserDriverReadApi(tPOCT6100_READ_PARAMS f_pReadParams)
{
const unsigned int addr = f_pReadParams->ulReadAddress;
const struct echo_mod *echo_mod;
struct astribank_device *astribank;
struct astribank *astribank;
int ret;
echo_mod = (struct echo_mod *)f_pReadParams->pProcessContext;
@ -535,7 +544,7 @@ UINT32 Oct6100UserDriverReadBurstApi(tPOCT6100_READ_BURST_PARAMS f_pBurstParams)
unsigned int addr;
unsigned int len;
const struct echo_mod *echo_mod;
struct astribank_device *astribank;
struct astribank *astribank;
unsigned int i;
len = f_pBurstParams->ulReadLength;
@ -555,13 +564,13 @@ UINT32 Oct6100UserDriverReadBurstApi(tPOCT6100_READ_BURST_PARAMS f_pBurstParams)
return cOCT6100_ERR_OK;
}
inline int get_ver(struct astribank_device *astribank)
inline int get_ver(struct astribank *astribank)
{
return spi_send(astribank, 0, 0, 1, 1);
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
UINT32 init_octasic(char *filename, struct astribank_device *astribank, struct span_specs *span_specs)
UINT32 init_octasic(char *filename, struct astribank *astribank, struct span_specs *span_specs)
{
int cpld_ver;
struct echo_mod *echo_mod;
@ -838,7 +847,7 @@ UINT32 init_octasic(char *filename, struct astribank_device *astribank, struct s
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
int load_echo(struct astribank_device *astribank, char *filename, int default_is_alaw, const char *span_spec)
int load_echo(struct astribank *astribank, char *filename, int default_is_alaw, const char *span_spec)
{
int ret;
UINT32 octasic_status;
@ -868,7 +877,7 @@ int load_echo(struct astribank_device *astribank, char *filename, int default_is
return 0;
}
int echo_ver(struct astribank_device *astribank)
int echo_ver(struct astribank *astribank)
{
usb_buffer_init(astribank, &usb_buffer);
return get_ver(astribank);

View File

@ -23,10 +23,10 @@
*/
#include <stdint.h>
#include "astribank_usb.h"
#include "astribank.h"
int spi_send(struct astribank_device *astribank, uint16_t addr, uint16_t data, int recv_answer, int ver);
int load_echo(struct astribank_device *astribank, char *filename, int is_alaw, const char *span_spec);
int echo_ver(struct astribank_device *astribank);
int spi_send(struct astribank *astribank, uint16_t addr, uint16_t data, int recv_answer, int ver);
int load_echo(struct astribank *astribank, char *filename, int is_alaw, const char *span_spec);
int echo_ver(struct astribank *astribank);
#endif /* ECHO_LOADER_H */

202
xpp/mpp.h
View File

@ -1,202 +0,0 @@
#ifndef MPP_H
#define MPP_H
/*
* Written by Oron Peled <oron@actcom.co.il>
* Copyright (C) 2008, Xorcom
*
* 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.
*
*/
/*
* MPP - Managment Processor Protocol definitions
*/
#include <mpptalk_defs.h>
#include <stdint.h>
#include <xtalk.h>
#ifdef __GNUC__
#define PACKED __attribute__((packed))
#else
#error "We do not know how your compiler packs structures"
#endif
#define MK_PROTO_VERSION(major, minor) (((major) << 4) | (0x0F & (minor)))
#define MPP_PROTOCOL_VERSION MK_PROTO_VERSION(1,4)
#define MPP_SUPPORTED_VERSION(x) ((x) == MK_PROTO_VERSION(1,3) || (x) == MK_PROTO_VERSION(1,4))
/*
* The eeprom_table is common to all eeprom types.
*/
#define LABEL_SIZE 8
struct eeprom_table {
uint8_t source; /* C0 - small eeprom, C2 - large eeprom */
uint16_t vendor;
uint16_t product;
uint16_t release; /* BCD encoded release */
uint8_t config_byte; /* Must be 0 */
uint8_t label[LABEL_SIZE];
} PACKED;
#define VERSION_LEN 6
struct firmware_versions {
char usb[VERSION_LEN];
char fpga[VERSION_LEN];
char eeprom[VERSION_LEN];
} PACKED;
struct capabilities {
uint8_t ports_fxs;
uint8_t ports_fxo;
uint8_t ports_bri;
uint8_t ports_pri;
uint8_t extra_features; /* BIT(0) - TwinStar */
uint8_t ports_echo;
uint8_t reserved[2];
uint32_t timestamp;
} PACKED;
#define CAP_EXTRA_TWINSTAR(c) ((c)->extra_features & 0x01)
#define CAP_EXTRA_TWINSTAR_SET(c) do {(c)->extra_features |= 0x01;} while (0)
#define CAP_EXTRA_TWINSTAR_CLR(c) do {(c)->extra_features &= ~0x01;} while (0)
#define KEYSIZE 16
struct capkey {
uint8_t k[KEYSIZE];
} PACKED;
struct extrainfo {
char text[EXTRAINFO_SIZE];
} PACKED;
struct mpp_header {
uint16_t len;
uint16_t seq;
uint8_t op; /* MSB: 0 - to device, 1 - from device */
} PACKED;
enum mpp_ser_op {
SER_CARD_INFO_GET = 0x1,
SER_STAT_GET = 0x3,
/* Status bits */
#define SER_STAT_WATCHDOG_READY(s) ((s) & 0x01)
#define SER_STAT_XPD_ALIVE(s) ((s) & 0x02)
};
/* Individual commands structure */
CMD_DEF(MPP, STATUS_GET);
CMD_DEF(MPP, STATUS_GET_REPLY,
uint8_t i2cs_data;
#define STATUS_FPGA_LOADED(x) ((x) & 0x01)
uint8_t status; /* BIT(0) - FPGA is loaded */
struct firmware_versions fw_versions;
);
CMD_DEF(MPP, EEPROM_SET,
struct eeprom_table data;
);
CMD_DEF(MPP, CAPS_GET);
CMD_DEF(MPP, CAPS_GET_REPLY,
struct eeprom_table data;
struct capabilities capabilities;
struct capkey key;
);
CMD_DEF(MPP, CAPS_SET,
struct eeprom_table data;
struct capabilities capabilities;
struct capkey key;
);
CMD_DEF(MPP, EXTRAINFO_GET);
CMD_DEF(MPP, EXTRAINFO_GET_REPLY,
struct extrainfo info;
);
CMD_DEF(MPP, EXTRAINFO_SET,
struct extrainfo info;
);
CMD_DEF(MPP, RENUM);
CMD_DEF(MPP, EEPROM_BLK_RD,
uint16_t offset;
uint16_t len;
);
CMD_DEF(MPP, EEPROM_BLK_RD_REPLY,
uint16_t offset;
uint8_t data[0];
);
CMD_DEF(MPP, DEV_SEND_START,
uint8_t dest;
char ihex_version[VERSION_LEN];
);
CMD_DEF(MPP, DEV_SEND_END);
CMD_DEF(MPP, DEV_SEND_SEG,
uint16_t offset;
uint8_t data[0];
);
CMD_DEF(MPP, RESET);
CMD_DEF(MPP, HALF_RESET);
CMD_DEF(MPP, SER_SEND,
uint8_t data[0];
);
CMD_DEF(MPP, SER_RECV,
uint8_t data[0];
);
CMD_DEF(MPP, TWS_WD_MODE_SET,
uint8_t wd_active;
);
CMD_DEF(MPP, TWS_WD_MODE_GET);
CMD_DEF(MPP, TWS_WD_MODE_GET_REPLY,
uint8_t wd_active;
);
CMD_DEF(MPP, TWS_PORT_SET,
uint8_t portnum;
);
CMD_DEF(MPP, TWS_PORT_GET);
CMD_DEF(MPP, TWS_PORT_GET_REPLY,
uint8_t portnum;
);
CMD_DEF(MPP, TWS_PWR_GET);
CMD_DEF(MPP, TWS_PWR_GET_REPLY,
uint8_t power;
);
#endif /* MPP_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
#ifndef MPP_FUNCS_H
#define MPP_FUNCS_H
#ifndef MPPTALK_H
#define MPPTALK_H
/*
* Written by Oron Peled <oron@actcom.co.il>
* Copyright (C) 2008, Xorcom
@ -22,64 +22,152 @@
*
*/
#include <stdint.h>
#include <stdio.h>
#include "mpp.h"
#include "astribank_usb.h"
struct astribank_device;
struct eeprom_table;
struct extrainfo;
struct capabilities;
struct capkey;
#define TIMEOUT 6000
/* high-level */
struct astribank_device *mpp_init(const char devpath[], int iface_num);
void mpp_exit(struct astribank_device *astribank);
int mpp_proto_query(struct astribank_device *astribank);
int mpp_status_query(struct astribank_device *astribank);
int mpp_eeprom_set(struct astribank_device *astribank, const struct eeprom_table *et);
int mpp_renumerate(struct astribank_device *astribank);
int mpp_caps_get(struct astribank_device *astribank,
struct eeprom_table *et,
struct capabilities *cap,
struct capkey *key);
int mpp_caps_set(struct astribank_device *astribank,
const struct eeprom_table *eeprom_table,
const struct capabilities *capabilities,
const struct capkey *key);
int mpp_extrainfo_get(struct astribank_device *astribank, struct extrainfo *info);
int mpp_extrainfo_set(struct astribank_device *astribank, const struct extrainfo *info);
int mpp_eeprom_blk_rd(struct astribank_device *astribank, uint8_t *buf, uint16_t offset, uint16_t len);
int mpp_send_start(struct astribank_device *astribank, int dest, const char *ihex_version);
int mpp_send_end(struct astribank_device *astribank);
int mpp_send_seg(struct astribank_device *astribank, const uint8_t *data, uint16_t offset, uint16_t len);
int mpp_reset(struct astribank_device *astribank, int full_reset);
int mpp_serial_cmd(struct astribank_device *astribank, const uint8_t *in, uint8_t *out, uint16_t len);
void show_eeprom(const struct eeprom_table *eprm, FILE *fp);
void show_capabilities(const struct capabilities *capabilities, FILE *fp);
void show_astribank_status(struct astribank_device *astribank, FILE *fp);
void show_extrainfo(const struct extrainfo *extrainfo, FILE *fp);
int twinstar_show(struct astribank_device *astribank, FILE *fp);
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
/*
* Serial commands to FPGA
* MPPTALK - Example XTALK dialect
*/
int mpps_card_info(struct astribank_device *astribank, int unit, uint8_t *card_type, uint8_t *card_status);
int mpps_stat(struct astribank_device *astribank, int unit, uint8_t *maincard_version, uint8_t *status);
#include <xtalk/proto.h>
#include <xtalk/proto_sync.h>
#ifdef __GNUC__
#define PACKED __attribute__((packed))
#else
#define PACKED
#endif
/*---------------- Common types --------------------*/
/*
* The eeprom_table is common to all eeprom types.
*/
#define LABEL_SIZE 8
struct eeprom_table {
uint8_t source; /* C0 - small eeprom, C2 - large eeprom */
uint16_t vendor;
uint16_t product;
uint16_t release; /* BCD encoded release */
uint8_t config_byte; /* Must be 0 */
uint8_t label[LABEL_SIZE];
} PACKED;
#define VERSION_LEN 6
struct firmware_versions {
char usb[VERSION_LEN];
char fpga[VERSION_LEN];
char eeprom[VERSION_LEN];
} PACKED;
struct capabilities {
uint8_t ports_fxs;
uint8_t ports_fxo;
uint8_t ports_bri;
uint8_t ports_pri;
uint8_t extra_features; /* BIT(0) - TwinStar */
uint8_t ports_echo;
uint8_t reserved[2];
uint32_t timestamp;
} PACKED;
#define CAP_EXTRA_TWINSTAR(c) ((c)->extra_features & 0x01)
#define CAP_EXTRA_TWINSTAR_SET(c) do {(c)->extra_features |= 0x01;} while (0)
#define CAP_EXTRA_TWINSTAR_CLR(c) do {(c)->extra_features &= ~0x01;} while (0)
#define KEYSIZE 16
struct capkey {
uint8_t k[KEYSIZE];
} PACKED;
#define EXTRAINFO_SIZE 24
struct extrainfo {
char text[EXTRAINFO_SIZE];
} PACKED;
struct mpp_header {
uint16_t len;
uint16_t seq;
uint8_t op; /* MSB: 0 - to device, 1 - from device */
} PACKED;
enum mpp_ser_op {
SER_CARD_INFO_GET = 0x1,
SER_STAT_GET = 0x3,
/* Status bits */
#define SER_STAT_WATCHDOG_READY(s) ((s) & 0x01)
#define SER_STAT_XPD_ALIVE(s) ((s) & 0x02)
};
/* EEPROM_QUERY: i2cs(ID1, ID0) */
enum eeprom_type {
EEPROM_TYPE_NONE = 0,
EEPROM_TYPE_SMALL = 1,
EEPROM_TYPE_LARGE = 2,
EEPROM_TYPE_UNUSED = 3,
};
enum dev_dest {
DEST_NONE = 0x00,
DEST_FPGA = 0x01,
DEST_EEPROM = 0x02,
};
/*---------------- PROTOCOL ------------------------*/
/* API */
struct mpp_device;
struct mpp_device *mpp_new(struct xusb_iface *iface);
void mpp_delete(struct mpp_device *dev);
struct xusb_iface *xubs_iface_of_mpp(struct mpp_device *mpp);
int mpp_status_query(struct mpp_device *mpp_dev);
enum eeprom_type mpp_eeprom_type(struct mpp_device *mpp_dev);
void show_eeprom(const struct eeprom_table *eprm, FILE *fp);
void show_capabilities(const struct capabilities *capabilities, FILE *fp);
void show_astribank_status(struct mpp_device *mpp_dev, FILE *fp);
void show_extrainfo(const struct extrainfo *extrainfo, FILE *fp);
int twinstar_show(struct mpp_device *mpp, FILE *fp);
int show_hardware(struct mpp_device *mpp_dev);
int mpp_renumerate(struct mpp_device *mpp_dev);
int mpp_send_start(struct mpp_device *mpp_dev, int dest, const char *ihex_version);
int mpp_send_end(struct mpp_device *mpp_dev);
int mpp_send_seg(struct mpp_device *mpp_dev, const uint8_t *data, uint16_t offset, uint16_t len);
int mpp_reset(struct mpp_device *mpp_dev, int full_reset);
int mpp_caps_get(struct mpp_device *mpp_dev,
struct eeprom_table *eeprom_table,
struct capabilities *capabilities,
struct capkey *key);
int mpp_caps_set(struct mpp_device *mpp_dev,
const struct eeprom_table *eeprom_table,
const struct capabilities *capabilities,
const struct capkey *key);
/*
* serial sub-protocol to FPGA
*/
int mpps_card_info(struct mpp_device *mpp, int unit, uint8_t *card_type, uint8_t *card_status);
int mpps_stat(struct mpp_device *mpp, int unit, uint8_t *maincard_version, uint8_t *status);
/*
* Twinstar
*/
int mpp_tws_watchdog(struct astribank_device *astribank);
int mpp_tws_setwatchdog(struct astribank_device *astribank, int yes);
int mpp_tws_powerstate(struct astribank_device *astribank);
int mpp_tws_portnum(struct astribank_device *astribank);
int mpp_tws_setportnum(struct astribank_device *astribank, uint8_t portnum);
int mpp_tws_watchdog(struct mpp_device *mpp);
int mpp_tws_setwatchdog(struct mpp_device *mpp, int yes);
int mpp_tws_powerstate(struct mpp_device *mpp);
int mpp_tws_portnum(struct mpp_device *mpp);
int mpp_tws_setportnum(struct mpp_device *mpp, uint8_t portnum);
const char *dev_dest2str(int dest);
#endif /* MPP_FUNCS_H */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* MPPTALK_H */

View File

@ -1,113 +0,0 @@
#ifndef MPPTALK_DEFS_H
#define MPPTALK_DEFS_H
/*
* Written by Oron Peled <oron@actcom.co.il>
* Copyright (C) 2008,2009,2010 Xorcom
*
* 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 <xtalk_defs.h>
/*
* MPP - Managment Processor Protocol definitions
*/
/*
* OP Codes:
* MSB of op signifies a reply from device
*/
#define MPP_RENUM 0x0B /* Trigger USB renumeration */
#define MPP_EEPROM_SET 0x0D
/* AB capabilities */
#define MPP_CAPS_GET 0x0E
#define MPP_CAPS_GET_REPLY 0x8E
#define MPP_CAPS_SET 0x0F
#define MPP_DEV_SEND_START 0x05
#define MPP_DEV_SEND_SEG 0x07
#define MPP_DEV_SEND_END 0x09
/* Astribank Status */
#define MPP_STATUS_GET 0x11
#define MPP_STATUS_GET_REPLY 0x91
#define MPP_STATUS_GET_REPLY_V13 0x91 /* backward compat */
/* Get extra vendor information */
#define MPP_EXTRAINFO_GET 0x13
#define MPP_EXTRAINFO_GET_REPLY 0x93
#define MPP_EXTRAINFO_SET 0x15 /* Set extra vendor information */
#define MPP_EEPROM_BLK_RD 0x27
#define MPP_EEPROM_BLK_RD_REPLY 0xA7
#define MPP_SER_SEND 0x37
#define MPP_SER_RECV 0xB7
#define MPP_RESET 0x45 /* Reset both FPGA and USB firmwares */
#define MPP_HALF_RESET 0x47 /* Reset only FPGA firmware */
/* Twinstar */
#define MPP_TWS_WD_MODE_SET 0x31 /* Set watchdog off/on guard */
#define MPP_TWS_WD_MODE_GET 0x32 /* Current watchdog mode */
#define MPP_TWS_WD_MODE_GET_REPLY 0xB2 /* Current watchdog mode */
#define MPP_TWS_PORT_SET 0x34 /* USB-[0/1] */
#define MPP_TWS_PORT_GET 0x35 /* USB-[0/1] */
#define MPP_TWS_PORT_GET_REPLY 0xB5 /* USB-[0/1] */
#define MPP_TWS_PWR_GET 0x36 /* Power: bits -> USB ports */
#define MPP_TWS_PWR_GET_REPLY 0xB6 /* Power: bits -> USB ports */
/*
* Statuses
*/
#define STAT_OK 0x00 /* acknowledges previous command */
#define STAT_FAIL 0x01 /* Last command failed */
#define STAT_RESET_FAIL 0x02 /* reset failed */
#define STAT_NODEST 0x03 /* No destination is selected */
#define STAT_MISMATCH 0x04 /* Data mismatch */
#define STAT_NOACCESS 0x05 /* No access */
#define STAT_BAD_CMD 0x06 /* Bad command */
#define STAT_TOO_SHORT 0x07 /* Packet is too short */
#define STAT_ERROFFS 0x08 /* Offset error */
#define STAT_NOCODE 0x09 /* Source was not burned before */
#define STAT_NO_LEEPROM 0x0A /* Large EEPROM was not found */
#define STAT_NO_EEPROM 0x0B /* No EEPROM was found */
#define STAT_WRITE_FAIL 0x0C /* Writing to device failed */
#define STAT_FPGA_ERR 0x0D /* FPGA error */
#define STAT_KEY_ERR 0x0E /* Bad Capabilities Key */
#define STAT_NOCAPS_ERR 0x0F /* No matching capability */
#define STAT_NOPWR_ERR 0x10 /* No power on USB connector */
#define STAT_CAPS_FPGA_ERR 0x11 /* Setting of the capabilities while FPGA is loaded */
/* EEPROM_QUERY: i2cs(ID1, ID0) */
enum eeprom_type {
EEPROM_TYPE_NONE = 0,
EEPROM_TYPE_SMALL = 1,
EEPROM_TYPE_LARGE = 2,
EEPROM_TYPE_UNUSED = 3,
};
enum dev_dest {
DEST_NONE = 0x00,
DEST_FPGA = 0x01,
DEST_EEPROM = 0x02,
};
#define EXTRAINFO_SIZE 24
#endif /* MPPTALK_DEFS_H */

View File

@ -25,12 +25,12 @@
#include <stdlib.h>
#include <errno.h>
#include <regex.h>
#include <xtalk/debug.h>
#include <xtalk/xusb.h>
#include "hexfile.h"
#include "pic_loader.h"
#include <debug.h>
#include <xusb.h>
#define DBG_MASK 0x03
#define DBG_MASK 0x20
#define MAX_HEX_LINES 10000
#define TIMEOUT 500
@ -57,7 +57,7 @@ struct xpp_packet_header {
} d;
} PACKED;
int send_picline(struct astribank_device *astribank, uint8_t card_type, enum pic_command pcmd, int offs, uint8_t *data, int data_len)
int send_picline(struct astribank *ab, uint8_t card_type, enum pic_command pcmd, int offs, uint8_t *data, int data_len)
{
int recv_answer = 0;
char buf[PACKET_SIZE];
@ -65,7 +65,7 @@ int send_picline(struct astribank_device *astribank, uint8_t card_type, enum pic
int pack_len;
int ret;
assert(astribank != NULL);
assert(ab != NULL);
pack_len = data_len + sizeof(phead->header) + sizeof(phead->d.pic_packet.pic_header);
phead->header.len = pack_len;
phead->header.op = PIC_REQ_XOP;
@ -90,14 +90,14 @@ int send_picline(struct astribank_device *astribank, uint8_t card_type, enum pic
DBG("PICLINE: pack_len=%d pcmd=%d\n", pack_len, pcmd);
dump_packet(LOG_DEBUG, DBG_MASK, "dump:picline[W]", (char *)phead, pack_len);
ret = xusb_send(astribank->xusb, buf, pack_len, TIMEOUT);
ret = astribank_send(ab, 0, buf, pack_len, TIMEOUT);
if(ret < 0) {
ERR("xusb_send failed: %d\n", ret);
ERR("astribank_send failed: %d\n", ret);
return ret;
}
DBG("xusb_send: Written %d bytes\n", ret);
DBG("astribank_send: Written %d bytes\n", ret);
if (recv_answer) {
ret = xusb_recv(astribank->xusb, buf, sizeof(buf), TIMEOUT);
ret = astribank_recv(ab, 0, buf, sizeof(buf), TIMEOUT);
if(ret <= 0) {
ERR("No USB packs to read\n");
return ret;
@ -172,7 +172,7 @@ static const char *pic_basename(const char *fname, uint8_t *card_type)
/*
* Returns: true on success, false on failure
*/
static int pic_burn(struct astribank_device *astribank, const struct hexdata *hexdata)
static int pic_burn(struct astribank *ab, const struct hexdata *hexdata)
{
const char *v = hexdata->version_info;
const char *basename;
@ -182,18 +182,21 @@ static int pic_burn(struct astribank_device *astribank, const struct hexdata *he
int ret;
unsigned int i;
const char *devstr;
const struct xusb_device *xusb;
v = (v[0]) ? v : "Unknown";
assert(astribank != NULL);
assert(ab != NULL);
assert(hexdata != NULL);
devstr = xusb_devpath(astribank->xusb);
if(!astribank->is_usb2) {
xusb = xusb_dev_of_astribank(ab);
devstr = xusb_devpath(xusb);
i = xusb_packet_size(xusb);
if(i != 512) {
ERR("%s: Skip PIC burning (not USB2)\n", devstr);
return 0;
}
INFO("%s [%s]: Loading PIC Firmware: %s (version %s)\n",
devstr,
xusb_serial(astribank->xusb),
xusb_serial(xusb),
hexdata->fname,
hexdata->version_info);
basename = pic_basename(hexdata->fname, &card_type);
@ -209,10 +212,10 @@ static int pic_burn(struct astribank_device *astribank, const struct hexdata *he
for(i = 2; i; i--) {
char buf[PACKET_SIZE];
if(xusb_recv(astribank->xusb, buf, sizeof(buf), 1) <= 0)
if (astribank_recv(ab, 0, buf, sizeof(buf), TIMEOUT) <= 0)
break;
}
if((ret = send_picline(astribank, card_type, PIC_START_FLAG, 0, NULL, 0)) != 0) {
if((ret = send_picline(ab, card_type, PIC_START_FLAG, 0, NULL, 0)) != 0) {
perror("Failed sending start hexline");
return 0;
}
@ -233,7 +236,7 @@ static int pic_burn(struct astribank_device *astribank, const struct hexdata *he
}
data = hexline->d.content.tt_data.data;
check_sum ^= data[0] ^ data[1] ^ data[2];
ret = send_picline(astribank, card_type, PIC_DATA_FLAG,
ret = send_picline(ab, card_type, PIC_DATA_FLAG,
hexline->d.content.header.offset, data, len);
if(ret) {
perror("Failed sending data hexline");
@ -247,7 +250,7 @@ static int pic_burn(struct astribank_device *astribank, const struct hexdata *he
return 0;
}
}
if((ret = send_picline(astribank, card_type, PIC_END_FLAG, 0, &check_sum, 1)) != 0) {
if((ret = send_picline(ab, card_type, PIC_END_FLAG, 0, &check_sum, 1)) != 0) {
perror("Failed sending end hexline");
return 0;
}
@ -255,12 +258,12 @@ static int pic_burn(struct astribank_device *astribank, const struct hexdata *he
return 1;
}
int load_pic(struct astribank_device *astribank, int numfiles, char *filelist[])
int load_pic(struct astribank *ab, int numfiles, char *filelist[])
{
int i;
const char *devstr;
devstr = xusb_devpath(astribank->xusb);
devstr = xusb_devpath(xusb_dev_of_astribank(ab));
DBG("%s: Loading %d PIC files...\n", devstr, numfiles);
for(i = 0; i < numfiles; i++) {
struct hexdata *picdata;
@ -271,13 +274,13 @@ int load_pic(struct astribank_device *astribank, int numfiles, char *filelist[])
perror(curr);
return -errno;
}
if(!pic_burn(astribank, picdata)) {
if(!pic_burn(ab, picdata)) {
ERR("%s: PIC %s burning failed\n", devstr, curr);
return -ENODEV;
}
free_hexdata(picdata);
}
if((i = send_picline(astribank, 0, PIC_ENDS_FLAG, 0, NULL, 0)) != 0) {
if((i = send_picline(ab, 0, PIC_ENDS_FLAG, 0, NULL, 0)) != 0) {
ERR("%s: PIC end burning failed\n", devstr);
return -ENODEV;
}

View File

@ -23,7 +23,7 @@
*/
#include <stdint.h>
#include "astribank_usb.h"
#include "astribank.h"
/*
* Astribank PIC loading
@ -39,8 +39,8 @@ enum pic_command {
#define PIC_PACK_LEN 0x0B
#define PIC_LINE_LEN 0x03
int send_picline(struct astribank_device *astribank, uint8_t card_type,
int send_picline(struct astribank *astribank, uint8_t card_type,
enum pic_command pcmd, int offs, uint8_t *data, int data_len);
int load_pic(struct astribank_device *astribank, int numfiles, char *filelist[]);
int load_pic(struct astribank *astribank, int numfiles, char *filelist[]);
#endif /* PIC_LOADER_H */

View File

@ -19,12 +19,7 @@ noinst_PROGRAMS = xlist_test xusb_test xusb_test_bypath xtalk_test xtalk_raw_te
sbin_PROGRAMS = xtalk_send
noinst_LTLIBRARIES = libxtalk.la
dist_noinst_HEADERS = \
debug.h \
xlist.h \
xtalk.h \
xtalk_base.h \
xtalk_defs.h \
xusb.h \
xusb_common.h \
include/xtalk/proto_raw.h \
include/xtalk/api_defs.h \

View File

@ -1,497 +0,0 @@
/*
* Written by Oron Peled <oron@actcom.co.il>
* Copyright (C) 2009, Xorcom
*
* 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 <stdlib.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <arpa/inet.h>
#include <xtalk.h>
#include <debug.h>
#define DBG_MASK 0x02
#define TIMEOUT 6000
/*
* Base XTALK device. A pointer to this struct
* should be included in the struct representing
* the dialect.
*/
struct xtalk_device {
void *transport_priv; /* e.g: struct xusb */
struct xtalk_ops ops;
struct xtalk_protocol xproto;
uint8_t xtalk_proto_version;
uint8_t status;
size_t packet_size;
uint16_t tx_sequenceno;
};
CMD_DEF(XTALK, ACK,
uint8_t stat;
);
CMD_DEF(XTALK, PROTO_GET,
uint8_t proto_version;
uint8_t reserved;
);
CMD_DEF(XTALK, PROTO_GET_REPLY,
uint8_t proto_version;
uint8_t reserved;
);
union XTALK_PDATA(XTALK) {
MEMBER(XTALK, ACK);
MEMBER(XTALK, PROTO_GET);
MEMBER(XTALK, PROTO_GET_REPLY);
} PACKED members;
struct xtalk_protocol xtalk_base = {
.name = "XTALK",
.proto_version = 0,
.commands = {
CMD_RECV(XTALK, ACK, NULL),
CMD_SEND(XTALK, PROTO_GET),
CMD_RECV(XTALK, PROTO_GET_REPLY, NULL),
},
.ack_statuses = {
ACK_STAT(OK, "Acknowledges previous command"),
ACK_STAT(FAIL, "Last command failed"),
ACK_STAT(RESET_FAIL, "reset failed"),
ACK_STAT(NODEST, "No destination is selected"),
ACK_STAT(MISMATCH, "Data mismatch"),
ACK_STAT(NOACCESS, "No access"),
ACK_STAT(BAD_CMD, "Bad command"),
ACK_STAT(TOO_SHORT, "Packet is too short"),
ACK_STAT(ERROFFS, "Offset error (not used)"),
ACK_STAT(NO_LEEPROM, "Large EEPROM was not found"),
ACK_STAT(NO_EEPROM, "No EEPROM was found"),
ACK_STAT(WRITE_FAIL, "Writing to device failed"),
ACK_STAT(NOPWR_ERR, "No power on USB connector"),
}
};
void free_command(struct xtalk_command *cmd)
{
if (!cmd)
return;
memset(cmd, 0, cmd->header.len);
free(cmd);
}
static const struct xtalk_command_desc *get_command_desc(
const struct xtalk_protocol *xproto, uint8_t op)
{
const struct xtalk_command_desc *desc;
if (!xproto)
return NULL;
desc = &xproto->commands[op];
if (!desc->name)
return NULL;
#if 0
DBG("%s version=%d, op=0x%X (%s)\n",
xproto->name, xproto->proto_version,
op, desc->name);
#endif
return desc;
}
static const char *ack_status_msg(const struct xtalk_protocol *xproto,
uint8_t status)
{
const char *ack_status;
if (!xproto)
return NULL;
ack_status = xproto->ack_statuses[status];
DBG("%s status=0x%X (%s)\n", xproto->name, status, ack_status);
return ack_status;
}
int xtalk_set_protocol(struct xtalk_device *xtalk_dev,
const struct xtalk_protocol *xproto)
{
const char *protoname = (xproto) ? xproto->name : "GLOBAL";
int i;
DBG("%s\n", protoname);
memset(&xtalk_dev->xproto, 0, sizeof(xtalk_dev->xproto));
for (i = 0; i < MAX_OPS; i++) {
const struct xtalk_command_desc *desc;
desc = get_command_desc(xproto, i);
if (desc) {
if (!IS_PRIVATE_OP(i)) {
ERR("Bad op=0x%X "
"(should be in the range [0x%X-0x%X]\n",
i, PRIVATE_OP_FIRST, PRIVATE_OP_LAST);
return -EINVAL;
}
xtalk_dev->xproto.commands[i] = *desc;
DBG("private: op=0x%X (%s)\n", i, desc->name);
} else {
if (!IS_PRIVATE_OP(i)) {
const char *name;
xtalk_dev->xproto.commands[i] =
xtalk_base.commands[i];
name = xtalk_dev->xproto.commands[i].name;
if (name)
DBG("global: op=0x%X (%s)\n", i, name);
}
}
}
for (i = 0; i < MAX_STATUS; i++) {
const char *stat_msg;
stat_msg = (xproto) ? xproto->ack_statuses[i] : NULL;
if (stat_msg) {
if (!IS_PRIVATE_OP(i)) {
ERR("Bad status=0x%X "
"(should be in the range [0x%X-0x%X]\n",
i, PRIVATE_OP_FIRST, PRIVATE_OP_LAST);
return -EINVAL;
}
xtalk_dev->xproto.ack_statuses[i] = stat_msg;
DBG("private: status=0x%X (%s)\n", i, stat_msg);
} else {
if (!IS_PRIVATE_OP(i)) {
const char *stat_msg;
xtalk_dev->xproto.ack_statuses[i] =
xtalk_base.ack_statuses[i];
stat_msg = xtalk_dev->xproto.ack_statuses[i];
if (stat_msg)
DBG("global: status=0x%X (%s)\n",
i, stat_msg);
}
}
}
xtalk_dev->xproto.name = protoname;
xtalk_dev->xproto.proto_version = (xproto) ? xproto->proto_version : 0;
return 0;
}
struct xtalk_command *new_command(
const struct xtalk_device *xtalk_dev,
uint8_t op, uint16_t extra_data)
{
const struct xtalk_protocol *xproto;
struct xtalk_command *cmd;
const struct xtalk_command_desc *desc;
uint16_t len;
xproto = &xtalk_dev->xproto;
desc = get_command_desc(xproto, op);
if (!desc) {
ERR("Unknown op=0x%X.\n", op);
return NULL;
}
DBG("OP=0x%X [%s] (extra_data %d)\n", op, desc->name, extra_data);
len = desc->len + extra_data;
cmd = malloc(len);
if (!cmd) {
ERR("Out of memory\n");
return NULL;
}
if (extra_data) {
uint8_t *ptr = (uint8_t *)cmd;
DBG("clear extra_data (%d bytes)\n", extra_data);
memset(ptr + desc->len, 0, extra_data);
}
cmd->header.op = op;
cmd->header.len = len;
cmd->header.seq = 0; /* Overwritten in send_usb() */
return cmd;
}
void xtalk_dump_command(struct xtalk_command *cmd)
{
uint16_t len;
int i;
len = cmd->header.len;
if (len < sizeof(struct xtalk_header)) {
ERR("Command too short (%d)\n", len);
return;
}
INFO("DUMP: OP=0x%X len=%d seq=%d\n",
cmd->header.op, cmd->header.len, cmd->header.seq);
for (i = 0; i < len - sizeof(struct xtalk_header); i++)
INFO(" %2d. 0x%X\n", i, cmd->alt.raw_data[i]);
}
static int send_command(struct xtalk_device *xtalk_dev,
struct xtalk_command *cmd, int timeout)
{
int ret;
int len;
void *priv = xtalk_dev->transport_priv;
len = cmd->header.len;
cmd->header.seq = xtalk_dev->tx_sequenceno;
ret = xtalk_dev->ops.send_func(priv, (char *)cmd, len, timeout);
if (ret < 0)
DBG("send_func failed ret=%d\n", ret);
xtalk_dev->tx_sequenceno++;
return ret;
}
static struct xtalk_command *recv_command(struct xtalk_device *xtalk_dev,
int timeout)
{
struct xtalk_command *reply;
void *priv = xtalk_dev->transport_priv;
size_t psize = xtalk_dev->packet_size;
int ret;
reply = malloc(psize);
if (!reply) {
ERR("Out of memory\n");
goto err;
}
reply->header.len = 0;
ret = xtalk_dev->ops.recv_func(priv, (char *)reply, psize, timeout);
if (ret < 0) {
ERR("Receive from usb failed.\n");
goto err;
} else if (ret == 0) {
goto err; /* No reply */
}
if (ret != reply->header.len) {
ERR("Wrong length received: got %d bytes, "
"but length field says %d bytes%s\n",
ret, reply->header.len,
(ret == 1) ? ". Old USB firmware?" : "");
goto err;
}
/* dump_packet(LOG_DEBUG, DBG_MASK, __func__, (char *)reply, ret); */
return reply;
err:
if (reply) {
memset(reply, 0, psize);
free_command(reply);
}
return NULL;
}
__attribute__((warn_unused_result))
int process_command(
struct xtalk_device *xtalk_dev,
struct xtalk_command *cmd,
struct xtalk_command **reply_ref)
{
const struct xtalk_protocol *xproto;
struct xtalk_command *reply = NULL;
const struct xtalk_command_desc *reply_desc;
const struct xtalk_command_desc *expected;
const struct xtalk_command_desc *cmd_desc;
uint8_t reply_op;
const char *protoname;
int ret;
xproto = &xtalk_dev->xproto;
protoname = (xproto) ? xproto->name : "GLOBAL";
/* So the caller knows if a reply was received */
if (reply_ref)
*reply_ref = NULL;
reply_op = cmd->header.op | XTALK_REPLY_MASK;
cmd_desc = get_command_desc(xproto, cmd->header.op);
expected = get_command_desc(xproto, reply_op);
ret = send_command(xtalk_dev, cmd, TIMEOUT);
if (!reply_ref) {
DBG("No reply requested\n");
goto out;
}
if (ret < 0) {
ERR("send_command failed: %d\n", ret);
goto out;
}
reply = recv_command(xtalk_dev, TIMEOUT);
if (!reply) {
ERR("recv_command failed\n");
ret = -EPROTO;
goto out;
}
*reply_ref = reply;
if ((reply->header.op & 0x80) != 0x80) {
ERR("Unexpected reply op=0x%02X, should have MSB set.\n",
reply->header.op);
ret = -EPROTO;
goto out;
}
DBG("REPLY OP: 0x%X\n", reply->header.op);
reply_desc = get_command_desc(xproto, reply->header.op);
if (!reply_desc) {
ERR("Unknown reply (proto=%s) op=0x%02X\n",
protoname, reply->header.op);
ret = -EPROTO;
goto out;
}
DBG("REPLY NAME: %s\n", reply_desc->name);
if (reply->header.op == XTALK_ACK) {
int status = CMD_FIELD(reply, XTALK, ACK, stat);
if (expected) {
ERR("Expected OP=0x%02X: Got ACK(%d): %s\n",
reply_op,
status,
ack_status_msg(xproto, status));
ret = -EPROTO;
goto out;
} else if (status != STAT_OK) {
ERR("Got ACK (for OP=0x%X [%s]): %d %s\n",
cmd->header.op,
cmd_desc->name,
status, ack_status_msg(xproto, status));
ret = -EPROTO;
goto out;
}
/* Good expected ACK ... */
} else if (reply->header.op != reply_op) {
ERR("Expected OP=0x%02X: Got OP=0x%02X\n",
reply_op, reply->header.op);
ret = -EPROTO;
goto out;
}
if (expected && expected->len > reply->header.len) {
ERR("Expected len=%d: Got len=%d\n",
expected->len, reply->header.len);
ret = -EPROTO;
goto out;
}
if (cmd->header.seq != reply->header.seq) {
ERR("Expected seq=%d: Got seq=%d\n",
cmd->header.seq, reply->header.seq);
ret = -EPROTO;
goto out;
}
ret = reply->header.len; /* All good, return the length */
DBG("returning reply op 0x%X (%d bytes)\n", reply->header.op, ret);
out:
free_command(cmd);
if (!reply_ref && reply)
free_command(reply);
return ret;
}
/*
* Protocol Commands
*/
int xtalk_proto_query(struct xtalk_device *xtalk_dev)
{
struct xtalk_command *cmd;
struct xtalk_command *reply;
uint8_t proto_version;
int ret;
DBG("\n");
assert(xtalk_dev != NULL);
proto_version = xtalk_dev->xproto.proto_version;
cmd = new_command(xtalk_dev, XTALK_PROTO_GET, 0);
if (!cmd) {
ERR("new_command failed\n");
return -ENOMEM;
}
/* Protocol Version */
CMD_FIELD(cmd, XTALK, PROTO_GET, proto_version) = proto_version;
ret = process_command(xtalk_dev, cmd, &reply);
if (ret < 0) {
ERR("process_command failed: %d\n", ret);
goto out;
}
xtalk_dev->xtalk_proto_version =
CMD_FIELD(reply, XTALK, PROTO_GET_REPLY, proto_version);
if (xtalk_dev->xtalk_proto_version != proto_version) {
DBG("Got %s protocol version: 0x%02x (expected 0x%02x)\n",
xtalk_dev->xproto.name,
xtalk_dev->xtalk_proto_version,
proto_version);
ret = xtalk_dev->xtalk_proto_version;
goto out;
}
DBG("Protocol version: %02x\n", xtalk_dev->xtalk_proto_version);
ret = xtalk_dev->xtalk_proto_version;
out:
free_command(reply);
return ret;
}
/*
* Wrappers
*/
struct xtalk_device *xtalk_new(const struct xtalk_ops *ops,
size_t packet_size, void *priv)
{
struct xtalk_device *xtalk_dev;
int ret;
DBG("\n");
assert(ops != NULL);
xtalk_dev = malloc(sizeof(*xtalk_dev));
if (!xtalk_dev) {
ERR("Allocating XTALK device memory failed\n");
return NULL;
}
memset(xtalk_dev, 0, sizeof(*xtalk_dev));
memcpy((void *)&xtalk_dev->ops, (const void *)ops,
sizeof(xtalk_dev->ops));
xtalk_dev->transport_priv = priv;
xtalk_dev->packet_size = packet_size;
xtalk_dev->tx_sequenceno = 1;
ret = xtalk_set_protocol(xtalk_dev, NULL);
if (ret < 0) {
ERR("GLOBAL Protocol registration failed: %d\n", ret);
goto err;
}
return xtalk_dev;
err:
if (xtalk_dev)
xtalk_delete(xtalk_dev);
return NULL;
}
void xtalk_delete(struct xtalk_device *xtalk_dev)
{
void *priv;
if (!xtalk_dev)
return;
DBG("\n");
priv = xtalk_dev->transport_priv;
assert(priv);
xtalk_dev->tx_sequenceno = 0;
assert(&xtalk_dev->ops != NULL);
assert(&xtalk_dev->ops.close_func != NULL);
xtalk_dev->ops.close_func(priv);
}

View File

@ -1,178 +0,0 @@
#ifndef XTALK_H
#define XTALK_H
/*
* Written by Oron Peled <oron@actcom.co.il>
* Copyright (C) 2009, Xorcom
*
* 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.
*
*/
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
/*
* XTALK - Base protocol for our USB devices
* It is meant to provide a common base for layered
* protocols (dialects)
*/
#include <stdint.h>
#include <stdlib.h>
/* Definitions common to the firmware (in include/ directory) */
#include <xtalk_defs.h>
#ifdef __GNUC__
#define PACKED __attribute__((packed))
#else
#error "We do not know how your compiler packs structures"
#endif
struct xtalk_device;
struct xtalk_command_desc;
typedef int (*xtalk_cmd_callback_t)(
struct xtalk_device *xtalk_dev,
struct xtalk_command_desc *xtalk_cmd);
/* Describe a single xtalk command */
struct xtalk_command_desc {
uint8_t op;
const char *name;
xtalk_cmd_callback_t callback;
uint16_t len; /* Minimal length */
};
/* Define a complete protocol */
struct xtalk_protocol {
const char *name;
uint8_t proto_version;
struct xtalk_command_desc commands[MAX_OPS];
const char *ack_statuses[MAX_STATUS];
};
/*
* The common header of every xtalk command
* in every xtalk dialect.
*/
struct xtalk_header {
uint16_t len;
uint16_t seq;
uint8_t op; /* MSB: 0 - to device, 1 - from device */
} PACKED;
struct xtalk_command {
/* Common part */
struct xtalk_header header;
/* Each dialect has its own data members */
union private_data {
uint8_t raw_data[0];
} PACKED alt;
} PACKED;
/*
* Macros to unify access to protocol packets and fields:
* p - signify the dialect prefix (XTALK for base protocol)
* o - signify command op (e.g: ACK)
* cmd - A pointer to struct xtalk_command
* field - field name (e.g: raw_data)
*/
#define XTALK_STRUCT(p, o) p ## _struct_ ## o
#define XTALK_PDATA(o) xtalk_privdata_ ## o
#define XTALK_CMD_PTR(cmd, p) ((union XTALK_PDATA(p)*)&((cmd)->alt))
#define CMD_FIELD(cmd, p, o, field) \
(XTALK_CMD_PTR(cmd, p)->XTALK_STRUCT(p, o).field)
#define CMD_DEF(p, o, ...) struct XTALK_STRUCT(p, o) { \
__VA_ARGS__ \
} PACKED XTALK_STRUCT(p, o)
#define MEMBER(p, o) struct XTALK_STRUCT(p, o) XTALK_STRUCT(p, o)
/* Wrappers for transport (xusb) functions */
struct xtalk_ops {
int (*send_func)(void *transport_priv, void *data, size_t len,
int timeout);
int (*recv_func)(void *transport_priv, void *data, size_t maxlen,
int timeout);
int (*close_func)(void *transport_priv);
};
/*
* Base XTALK device. A pointer to this struct
* should be included in the struct representing
* the dialect.
*/
struct xtalk_device;
/* high-level */
struct xtalk_device *xtalk_new(const struct xtalk_ops *ops,
size_t packet_size, void *transport_priv);
void xtalk_delete(struct xtalk_device *dev);
int xtalk_set_protocol(struct xtalk_device *xtalk_dev,
const struct xtalk_protocol *xproto);
int xtalk_proto_query(struct xtalk_device *dev);
void xtalk_dump_command(struct xtalk_command *cmd);
/* low-level */
int process_command(
struct xtalk_device *dev,
struct xtalk_command *cmd,
struct xtalk_command **reply_ref);
struct xtalk_command *new_command(
const struct xtalk_device *xtalk_dev,
uint8_t op, uint16_t extra_data);
void free_command(struct xtalk_command *cmd);
/*
* Convenience macros to define entries in a protocol command table:
* p - signify the dialect prefix (XTALK for base protocol)
* o - signify command op (e.g: ACK)
* cb - A callback function (type xtalk_cmd_callback_t)
*/
#define CMD_RECV(p, o, cb) \
[p ## _ ## o | XTALK_REPLY_MASK] = { \
.op = (p ## _ ## o) | XTALK_REPLY_MASK, \
.name = (#o "_reply"), \
.callback = (cb), \
.len = \
sizeof(struct xtalk_header) + \
sizeof(struct XTALK_STRUCT(p, o)), \
}
#define CMD_SEND(p, o) \
[p ## _ ## o] = { \
.op = (p ## _ ## o), \
.name = (#o), \
.callback = NULL, \
.len = \
sizeof(struct xtalk_header) + \
sizeof(struct XTALK_STRUCT(p, o)), \
}
/*
* Convenience macro to define statuses:
* x - status code (e.g: OK)
* m - status message (const char *)
*/
#define ACK_STAT(x, m) [STAT_ ## x] = (m)
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* XTALK_H */

View File

@ -351,3 +351,8 @@ void xtalk_base_delete(struct xtalk_base *xtalk_base)
memset(xtalk_base, 0, sizeof(*xtalk_base));
free(xtalk_base);
}
struct xusb_iface *xusb_iface_of_xtalk_base(const struct xtalk_base *xtalk_base)
{
return xtalk_base->transport_priv;
}

View File

@ -1,41 +0,0 @@
#ifndef XTALK_DEFS_H
#define XTALK_DEFS_H
#define MAX_OPS 256 /* single byte */
#define MAX_STATUS 256 /* single byte */
#define XTALK_REPLY_MASK 0x80 /* Every reply has this bit */
#define PRIVATE_OP_FIRST 0x05
#define PRIVATE_OP_LAST 0x7F
#define IS_PRIVATE_OP(x) ( \
(((x) & ~(XTALK_REPLY_MASK)) >= PRIVATE_OP_FIRST) && \
(((x) & ~(XTALK_REPLY_MASK)) <= PRIVATE_OP_LAST) \
)
#define XTALK_ACK 0x80
#define XTALK_PROTO_GET 0x01
#define XTALK_PROTO_GET_REPLY (XTALK_PROTO_GET | XTALK_REPLY_MASK)
#define XTALK_FWVERS_GET 0x11
#define XTALK_FWVERS_GET_REPLY (XTALK_FWVERS_GET | XTALK_REPLY_MASK)
/* Get EEPROM table contents Product/Vendor Id ... */
#define XTALK_CAPS_GET 0x0E
#define XTALK_CAPS_GET_REPLY (XTALK_CAPS_GET | XTALK_REPLY_MASK)
/*------------- XTALK: statuses in ACK ---------------------------------------*/
#define STAT_OK 0x00 /* OK */
#define STAT_FAIL 0x01 /* last command failed */
#define STAT_RESET_FAIL 0x02 /* reset failed */
#define STAT_NODEST 0x03 /* No destination is selected */
#define STAT_MISMATCH 0x04 /* Data mismatch */
#define STAT_NOACCESS 0x05 /* No access */
#define STAT_BAD_CMD 0x06 /* Bad command */
#define STAT_TOO_SHORT 0x07 /* Packet is too short */
#define STAT_ERROFFS 0x08 /* Offset error (not used) */
#define STAT_NO_LEEPROM 0x0A /* Large EEPROM was not found */
#define STAT_NO_EEPROM 0x0B /* No EEPROM was found */
#define STAT_WRITE_FAIL 0x0C /* Writing to device failed */
#define STAT_NOPWR_ERR 0x10 /* No power on USB connector */
#endif /* XTALK_DEFS_H */

View File

@ -1,943 +0,0 @@
/*
* Written by Oron Peled <oron@actcom.co.il>
* Copyright (C) 2008, Xorcom
*
* 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.
*
*/
#define _GNU_SOURCE /* for memrchr() */
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <stdarg.h>
#include <syslog.h>
#include <arpa/inet.h>
#include <debug.h>
#include <xusb.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#define DBG_MASK 0x01
#define TIMEOUT 500
#define MAX_RETRIES 10
struct xusb {
struct usb_device *dev;
usb_dev_handle *handle;
const struct xusb_spec *spec;
char iManufacturer[BUFSIZ];
char iProduct[BUFSIZ];
char iSerialNumber[BUFSIZ];
char iInterface[BUFSIZ];
char devpath_tail[PATH_MAX + 1];
int bus_num;
int device_num;
int interface_num;
int ep_out;
int ep_in;
int is_usb2;
int is_claimed;
int is_open;
size_t packet_size;
};
static void xusb_init();
/*
* XTALK_OPTIONS:
* A white-space separated list of options, read from the environment
* variable of that name. Existing options:
*
* - "use-clear-halt" -- force USB "clear_halt" operation during
* device initialization (this is the default)
* - "no-use-clear-halt" -- force no USB "clear_halt" operation during
* device initialization
* - "no-lock" -- prevent using global sempahore to serialize libusb
* initialization. Previously done via "XUSB_NOLOCK"
* environment variable.
*/
int xtalk_parse_options(void);
int xtalk_option_use_clear_halt(void);
int xtalk_option_no_lock(void);
void xusb_init_spec(struct xusb_spec *spec, char *name,
uint16_t vendor_id, uint16_t product_id,
int nifaces, int iface, int nep, int ep_out, int ep_in)
{
DBG("Initialize %s: interfaces=%d using interface num=%d endpoints=%d "
"(OUT=0x%02X, IN=0x%02X)\n",
name, nifaces, iface, nep, ep_out, ep_in);
memset(spec, 0, sizeof(*spec));
spec->name = name;
spec->num_interfaces = nifaces;
spec->my_interface_num = iface;
spec->num_endpoints = nep;
spec->my_vendor_id = vendor_id;
spec->my_product_id = product_id;
spec->my_ep_in = ep_in;
spec->my_ep_out = ep_out;
}
#define EP_OUT(xusb) ((xusb)->spec->my_ep_out)
#define EP_IN(xusb) ((xusb)->spec->my_ep_in)
/*
* USB handling
*/
static int get_usb_string(struct xusb *xusb, uint8_t item, char *buf)
{
char tmp[BUFSIZ];
int ret;
assert(xusb->handle);
if (!item)
return 0;
ret = usb_get_string_simple(xusb->handle, item, tmp, BUFSIZ);
if (ret <= 0)
return ret;
return snprintf(buf, BUFSIZ, "%s", tmp);
}
static const struct usb_interface_descriptor *get_interface(
const struct usb_device *dev,
int my_interface_num,
int num_interfaces)
{
const struct usb_interface *interface;
const struct usb_interface_descriptor *iface_desc;
const struct usb_config_descriptor *config_desc;
int num_altsetting;
config_desc = dev->config;
if (!config_desc) {
ERR("No configuration descriptor: strange USB1 controller?\n");
return NULL;
}
if (num_interfaces && config_desc->bNumInterfaces != num_interfaces) {
DBG("Wrong number of interfaces: have %d need %d\n",
config_desc->bNumInterfaces, num_interfaces);
return NULL;
}
interface = &config_desc->interface[my_interface_num];
assert(interface != NULL);
iface_desc = interface->altsetting;
num_altsetting = interface->num_altsetting;
assert(num_altsetting != 0);
assert(iface_desc != NULL);
return iface_desc;
}
static int match_interface(const struct usb_device *dev,
const struct xusb_spec *spec)
{
const struct usb_device_descriptor *dev_desc;
const struct usb_interface_descriptor *iface_desc;
dev_desc = &dev->descriptor;
assert(dev_desc);
DBG("Checking: %04X:%04X interfaces=%d interface num=%d endpoints=%d: "
"\"%s\"\n",
spec->my_vendor_id,
spec->my_product_id,
spec->num_interfaces,
spec->my_interface_num,
spec->num_endpoints,
spec->name);
if (dev_desc->idVendor != spec->my_vendor_id) {
DBG("Wrong vendor id 0x%X\n", dev_desc->idVendor);
return 0;
}
if (dev_desc->idProduct != spec->my_product_id) {
DBG("Wrong product id 0x%X\n", dev_desc->idProduct);
return 0;
}
iface_desc = get_interface(dev, spec->my_interface_num,
spec->num_interfaces);
if (!iface_desc) {
ERR("Could not get interface descriptor of device: %s\n",
usb_strerror());
return 0;
}
if (iface_desc->bInterfaceClass != 0xFF) {
DBG("Wrong interface class 0x%X\n",
iface_desc->bInterfaceClass);
return 0;
}
if (iface_desc->bInterfaceNumber != spec->my_interface_num) {
DBG("Wrong interface number %d (expected %d)\n",
iface_desc->bInterfaceNumber, spec->my_interface_num);
return 0;
}
if (iface_desc->bNumEndpoints != spec->num_endpoints) {
DBG("Wrong number of endpoints %d\n",
iface_desc->bNumEndpoints);
return 0;
}
return 1;
}
#define GET_USB_STRING(xusb, from, item) \
get_usb_string((xusb), (from)->item, xusb->item)
static int xusb_fill_strings(struct xusb *xusb)
{
const struct usb_device_descriptor *dev_desc;
const struct usb_interface_descriptor *iface_desc;
dev_desc = &xusb->dev->descriptor;
assert(dev_desc);
if (GET_USB_STRING(xusb, dev_desc, iManufacturer) < 0) {
ERR("Failed reading iManufacturer string: %s\n",
usb_strerror());
return 0;
}
if (GET_USB_STRING(xusb, dev_desc, iProduct) < 0) {
ERR("Failed reading iProduct string: %s\n",
usb_strerror());
return 0;
}
if (GET_USB_STRING(xusb, dev_desc, iSerialNumber) < 0) {
ERR("Failed reading iSerialNumber string: %s\n",
usb_strerror());
return 0;
}
iface_desc = get_interface(xusb->dev, xusb->interface_num, 0);
if (!iface_desc) {
ERR("Could not get interface descriptor of device: %s\n",
usb_strerror());
return 0;
}
if (GET_USB_STRING(xusb, iface_desc, iInterface) < 0) {
ERR("Failed reading iInterface string: %s\n", usb_strerror());
return 0;
}
return 1;
}
static int xusb_open(struct xusb *xusb)
{
assert(xusb);
if (xusb->is_open)
return 1;
xusb->handle = usb_open(xusb->dev);
if (!xusb->handle) {
ERR("Failed to open usb device '%s': %s\n",
xusb->devpath_tail, usb_strerror());
return 0;
}
xusb->is_open = 1;
return 1;
}
int xusb_claim_interface(struct xusb *xusb)
{
const struct usb_device_descriptor *dev_desc;
int ret;
assert(xusb);
xusb_open(xusb); /* If it's not open yet... */
if (usb_claim_interface(xusb->handle, xusb->interface_num) != 0) {
ERR("usb_claim_interface %d in '%s': %s\n",
xusb->interface_num,
xusb->devpath_tail,
usb_strerror());
return 0;
}
xusb->is_claimed = 1;
xusb_fill_strings(xusb);
dev_desc = &xusb->dev->descriptor;
DBG("ID=%04X:%04X Manufacturer=[%s] Product=[%s] "
"SerialNumber=[%s] Interface=[%s]\n",
dev_desc->idVendor,
dev_desc->idProduct,
xusb->iManufacturer,
xusb->iProduct,
xusb->iSerialNumber,
xusb->iInterface);
if (xtalk_option_use_clear_halt()) {
DBG("Using clear_halt()\n");
if (usb_clear_halt(xusb->handle, EP_OUT(xusb)) != 0) {
ERR("Clearing output endpoint: %s\n", usb_strerror());
return 0;
}
if (usb_clear_halt(xusb->handle, EP_IN(xusb)) != 0) {
ERR("Clearing input endpoint: %s\n", usb_strerror());
return 0;
}
}
ret = xusb_flushread(xusb);
if (ret < 0) {
ERR("xusb_flushread failed: %d\n", ret);
return 0;
}
return 1;
}
static void xusb_list_dump(struct xlist_node *xusb_list)
{
struct xlist_node *curr;
struct xusb *xusb;
for (curr = xusb_list->next; curr != xusb_list; curr = curr->next) {
struct usb_device *dev;
struct usb_bus *bus;
struct usb_device_descriptor *dev_desc;
xusb = curr->data;
assert(xusb);
dev = xusb->dev;
assert(dev);
bus = dev->bus;
assert(bus);
dev_desc = &dev->descriptor;
assert(dev_desc);
DBG("usb:ID=%04X:%04X [%s / %s / %s], (%s/%s)\n",
dev_desc->idVendor,
dev_desc->idProduct,
xusb->iManufacturer,
xusb->iProduct,
xusb->iSerialNumber,
bus->dirname,
dev->filename
);
}
}
void xusb_destroy(struct xusb *xusb)
{
if (xusb) {
xusb_close(xusb);
memset(xusb, 0, sizeof(*xusb));
free(xusb);
}
}
static struct xusb *xusb_new(struct usb_device *dev,
const struct xusb_spec *spec)
{
struct usb_device_descriptor *dev_desc;
struct usb_config_descriptor *config_desc;
struct usb_interface *interface;
struct usb_interface_descriptor *iface_desc;
struct usb_endpoint_descriptor *endpoint;
size_t max_packet_size;
int i;
struct xusb *xusb = NULL;
/*
* Get information from the usb_device
*/
dev_desc = &dev->descriptor;
if (!dev_desc) {
ERR("usb device without a device descriptor\n");
goto fail;
}
config_desc = dev->config;
if (!config_desc) {
ERR("usb device without a configuration descriptor\n");
goto fail;
}
interface = &config_desc->interface[spec->my_interface_num];
iface_desc = interface->altsetting;
endpoint = iface_desc->endpoint;
/* Calculate max packet size */
max_packet_size = PACKET_SIZE;
for (i = 0; i < iface_desc->bNumEndpoints; i++, endpoint++) {
DBG("Validating endpoint @ %d (interface %d)\n",
i, spec->my_interface_num);
if (endpoint->bEndpointAddress == spec->my_ep_out ||
endpoint->bEndpointAddress == spec->my_ep_in) {
if (endpoint->wMaxPacketSize > PACKET_SIZE) {
ERR("EP #%d wMaxPacketSize too large (%d)\n",
i, endpoint->wMaxPacketSize);
goto fail;
}
if (endpoint->wMaxPacketSize < max_packet_size)
max_packet_size = endpoint->wMaxPacketSize;
}
}
/* Fill xusb */
xusb = malloc(sizeof(*xusb));
if (!xusb) {
ERR("Out of memory");
goto fail;
}
memset(xusb, 0, sizeof(*xusb));
xusb->dev = dev;
xusb->spec = spec;
sscanf(dev->bus->dirname, "%d", &xusb->bus_num);
sscanf(dev->filename, "%d", &xusb->device_num);
snprintf(xusb->devpath_tail, PATH_MAX, "%03d/%03d",
xusb->bus_num, xusb->device_num);
xusb->interface_num = spec->my_interface_num;
xusb->ep_out = spec->my_ep_out;
xusb->ep_in = spec->my_ep_in;
xusb->packet_size = max_packet_size;
xusb->is_usb2 = (max_packet_size == 512);
if (!xusb_open(xusb)) {
ERR("Failed opening device: %04X:%04X - %s\n",
dev_desc->idVendor,
dev_desc->idProduct,
xusb->devpath_tail);
goto fail;
}
DBG("%04X:%04X - %s\n",
dev_desc->idVendor,
dev_desc->idProduct,
xusb->devpath_tail);
return xusb;
fail:
xusb_destroy(xusb);
return NULL;
}
struct xusb *xusb_find_iface(const char *devpath,
int iface_num,
int ep_out,
int ep_in,
struct xusb_spec *dummy_spec)
{
struct usb_bus *bus;
DBG("\n");
xusb_init();
for (bus = usb_get_busses(); bus; bus = bus->next) {
int bus_num;
char tmppath[PATH_MAX + 1];
struct usb_device *dev;
tmppath[0] = '\0';
sscanf(bus->dirname, "%d", &bus_num);
snprintf(tmppath, sizeof(tmppath), "%03d", bus_num);
DBG("Check bus %d: %s ? %s\n", bus_num, tmppath, devpath);
if (strncmp(tmppath, devpath, strlen(tmppath)) != 0)
continue;
DBG("Matched bus %d\n", bus_num);
for (dev = bus->devices; dev; dev = dev->next) {
struct usb_device_descriptor *dev_desc;
struct usb_config_descriptor *config_desc;
struct usb_interface *interface;
struct xusb *xusb;
int device_num;
sscanf(dev->filename, "%d", &device_num);
DBG("Check device %d\n", device_num);
snprintf(tmppath, sizeof(tmppath), "%03d/%03d",
bus_num, device_num);
if (strncmp(tmppath, devpath, strlen(tmppath)) != 0)
continue;
dev_desc = &dev->descriptor;
assert(dev_desc);
config_desc = dev->config;
assert(config_desc);
interface = config_desc->interface;
assert(interface);
DBG("Matched device %s: %X:%X\n", tmppath,
dev_desc->idVendor, dev_desc->idProduct);
assert(dummy_spec);
xusb_init_spec(dummy_spec, "<none>",
dev_desc->idVendor, dev_desc->idProduct,
config_desc->bNumInterfaces,
iface_num,
interface->altsetting->bNumEndpoints,
ep_out, ep_in);
xusb = xusb_new(dev, dummy_spec);
if (!xusb)
ERR("xusb allocation failed\n");
return xusb;
}
}
return NULL;
}
static const char *path_tail(const char *path)
{
const char *p;
assert(path != NULL);
/* Find last '/' */
p = memrchr(path, '/', strlen(path));
if (!p) {
ERR("Missing a '/' in %s\n", path);
return NULL;
}
/* Search for a '/' before that */
p = memrchr(path, '/', p - path);
if (!p)
p = path; /* No more '/' */
else
p++; /* skip '/' */
return p;
}
int xusb_filter_bypath(const struct xusb *xusb, void *data)
{
const char *p;
const char *path = data;
DBG("%s\n", path);
assert(path != NULL);
p = path_tail(path);
if (strcmp(xusb->devpath_tail, p) != 0) {
DBG("device path missmatch: '%s' != '%s'\n",
xusb->devpath_tail, p);
return 0;
}
return 1;
}
struct xusb *xusb_find_bypath(const struct xusb_spec *specs, int numspecs,
const char *path)
{
struct xlist_node *xlist;
struct xlist_node *head;
struct xusb *xusb;
xlist = xusb_find_byproduct(specs, numspecs,
xusb_filter_bypath, (void *)path);
head = xlist_shift(xlist);
if (!head)
return NULL;
if (!xlist_empty(xlist)) {
ERR("Too many matches (extra %zd) to '%s'\n",
xlist_length(xlist), path);
return NULL;
}
xusb = head->data;
xlist_destroy(xlist, NULL);
return xusb;
}
struct xlist_node *xusb_find_byproduct(const struct xusb_spec *specs,
int numspecs, xusb_filter_t filterfunc, void *data)
{
struct xlist_node *xlist;
struct usb_bus *bus;
struct usb_device *dev;
DBG("specs(%d)\n", numspecs);
xlist = xlist_new(NULL);
if (!xlist) {
ERR("Failed allocation new xlist");
goto fail_xlist;
}
xusb_init();
for (bus = usb_get_busses(); bus; bus = bus->next) {
for (dev = bus->devices; dev; dev = dev->next) {
struct usb_device_descriptor *dev_desc;
struct xlist_node *item;
int i;
dev_desc = &dev->descriptor;
assert(dev_desc);
DBG("usb:%s/%s: ID=%04X:%04X\n",
dev->bus->dirname,
dev->filename,
dev_desc->idVendor,
dev_desc->idProduct);
for (i = 0; i < numspecs; i++) {
struct xusb *xusb;
const struct xusb_spec *sp = &specs[i];
if (!match_interface(dev, sp))
continue;
xusb = xusb_new(dev, sp);
if (!xusb) {
ERR("xusb allocation failed\n");
goto fail_malloc;
}
if (filterfunc && !filterfunc(xusb, data)) {
xusb_destroy(xusb);
continue;
}
item = xlist_new(xusb);
xlist_append_item(xlist, item);
break;
}
}
}
xusb_list_dump(xlist);
return xlist;
fail_malloc:
xlist_destroy(xlist, NULL);
fail_xlist:
return NULL;
}
struct xusb *xusb_open_one(const struct xusb_spec *specs, int numspecs,
xusb_filter_t filterfunc, void *data)
{
struct xlist_node *xusb_list;
struct xlist_node *curr;
int num;
struct xusb *xusb = NULL;
xusb_list = xusb_find_byproduct(specs, numspecs, filterfunc, data);
num = xlist_length(xusb_list);
DBG("total %d devices\n", num);
switch (num) {
case 0:
ERR("No matching device.\n");
break;
case 1:
curr = xlist_shift(xusb_list);
xusb = curr->data;
xlist_destroy(curr, NULL);
xlist_destroy(xusb_list, NULL);
if (!xusb_claim_interface(xusb)) {
xusb_destroy(xusb);
return NULL;
}
xusb_showinfo(xusb);
break;
default:
ERR("Too many devices (%d). Aborting.\n", num);
break;
}
return xusb;
}
int xusb_interface(struct xusb *xusb)
{
return xusb->interface_num;
}
size_t xusb_packet_size(const struct xusb *xusb)
{
return xusb->packet_size;
}
/*
* MP device handling
*/
void xusb_showinfo(const struct xusb *xusb)
{
struct usb_device_descriptor *dev_desc;
struct usb_device *dev;
assert(xusb != NULL);
dev = xusb->dev;
dev_desc = &dev->descriptor;
if (verbose <= LOG_INFO) {
INFO("usb:%s/%s: ID=%04X:%04X [%s / %s / %s]\n",
dev->bus->dirname,
dev->filename,
dev_desc->idVendor,
dev_desc->idProduct,
xusb->iManufacturer,
xusb->iProduct,
xusb->iSerialNumber);
} else {
printf("USB Bus/Device: [%s/%s] (%s,%s)\n",
dev->bus->dirname,
dev->filename,
(xusb->is_open) ? "open" : "closed",
(xusb->is_claimed) ? "claimed" : "unused");
printf("USB Spec name: [%s]\n", xusb->spec->name);
printf("USB iManufacturer: [%s]\n", xusb->iManufacturer);
printf("USB iProduct: [%s]\n", xusb->iProduct);
printf("USB iSerialNumber: [%s]\n", xusb->iSerialNumber);
}
}
const char *xusb_serial(const struct xusb *xusb)
{
return xusb->iSerialNumber;
}
const char *xusb_devpath(const struct xusb *xusb)
{
return xusb->devpath_tail;
}
const char *xusb_manufacturer(const struct xusb *xusb)
{
return xusb->iManufacturer;
}
const char *xusb_product(const struct xusb *xusb)
{
return xusb->iProduct;
}
uint16_t xusb_vendor_id(const struct xusb *xusb)
{
return xusb->dev->descriptor.idVendor;
}
uint16_t xusb_product_id(const struct xusb *xusb)
{
return xusb->dev->descriptor.idProduct;
}
const struct xusb_spec *xusb_spec(const struct xusb *xusb)
{
return xusb->spec;
}
int xusb_close(struct xusb *xusb)
{
if (xusb) {
if (xusb->handle) {
assert(xusb->spec);
assert(xusb->spec->name);
DBG("Closing interface \"%s\"\n", xusb->spec->name);
if (xusb->is_claimed) {
if (usb_release_interface(xusb->handle,
xusb->spec->my_interface_num) != 0)
ERR("Releasing interface: usb: %s\n",
usb_strerror());
xusb->is_claimed = 0;
}
if (xusb->is_open) {
if (usb_close(xusb->handle) != 0) {
ERR("Closing device: usb: %s\n",
usb_strerror());
}
xusb->is_open = 0;
}
xusb->handle = NULL;
}
xusb = NULL;
}
return 0;
}
int xusb_send(struct xusb *xusb, char *buf, int len, int timeout)
{
int ret;
int retries = 0;
dump_packet(LOG_DEBUG, DBG_MASK, __func__, buf, len);
if (EP_OUT(xusb) & USB_ENDPOINT_IN) {
ERR("%s called with an input endpoint 0x%x\n",
__func__, EP_OUT(xusb));
return -EINVAL;
}
retry_write:
ret = usb_bulk_write(xusb->handle, EP_OUT(xusb), buf, len, timeout);
if (ret < 0) {
/*
* If the device was gone, it may be the
* result of renumeration. Ignore it.
*/
if (ret != -ENODEV) {
ERR("bulk_write to endpoint 0x%x failed: (%d) %s\n",
EP_OUT(xusb), ret, usb_strerror());
dump_packet(LOG_ERR, DBG_MASK, "xusb_send[ERR]",
buf, len);
/*exit(2);*/
} else {
DBG("bulk_write to endpoint 0x%x got ENODEV\n",
EP_OUT(xusb));
xusb_close(xusb);
}
return ret;
}
if (!ret) {
ERR("bulk_write to endpoint 0x%x short write[%d]: (%d)\n",
EP_OUT(xusb), retries, ret);
if (retries++ > MAX_RETRIES)
return -EFAULT;
usleep(100);
goto retry_write;
}
if (ret != len) {
ERR("bulk_write to endpoint 0x%x short write: (%d) %s\n",
EP_OUT(xusb), ret, usb_strerror());
dump_packet(LOG_ERR, DBG_MASK, "xusb_send[ERR]", buf, len);
return -EFAULT;
}
return ret;
}
int xusb_recv(struct xusb *xusb, char *buf, size_t len, int timeout)
{
int ret;
int retries = 0;
if (EP_IN(xusb) & USB_ENDPOINT_OUT) {
ERR("%s called with an output endpoint 0x%x\n",
__func__, EP_IN(xusb));
return -EINVAL;
}
retry_read:
ret = usb_bulk_read(xusb->handle, EP_IN(xusb), buf, len, timeout);
if (ret < 0) {
DBG("bulk_read from endpoint 0x%x failed: (%d) %s\n",
EP_IN(xusb), ret, usb_strerror());
memset(buf, 0, len);
return ret;
}
if (!ret) {
ERR("bulk_read to endpoint 0x%x short read[%d]: (%d)\n",
EP_IN(xusb), retries, ret);
if (retries++ > MAX_RETRIES)
return -EFAULT;
usleep(100);
goto retry_read;
}
dump_packet(LOG_DEBUG, DBG_MASK, __func__, buf, ret);
return ret;
}
int xusb_flushread(struct xusb *xusb)
{
char tmpbuf[BUFSIZ];
int ret;
DBG("starting...\n");
memset(tmpbuf, 0, BUFSIZ);
ret = xusb_recv(xusb, tmpbuf, BUFSIZ, 1);
if (ret < 0 && ret != -ETIMEDOUT) {
ERR("ret=%d\n", ret);
return ret;
} else if (ret > 0) {
DBG("Got %d bytes:\n", ret);
dump_packet(LOG_DEBUG, DBG_MASK, __func__, tmpbuf, ret);
}
return 0;
}
/*
* Serialize calls to usb_find_busses()/usb_find_devices()
*/
static const key_t SEM_KEY = 0x1a2b3c4d;
static int semid = -1; /* Failure */
static void xusb_lock_usb()
{
struct sembuf sembuf;
while (semid < 0) {
/* Maybe it was already created? */
semid = semget(SEM_KEY, 1, 0);
if (semid < 0) {
/* No, let's create ourselves */
semid = semget(SEM_KEY, 1, IPC_CREAT | IPC_EXCL | 0644);
if (semid < 0) {
/* Someone else won the race to create it */
if (errno != ENOENT)
ERR("%s: semget() failed: %s\n",
__func__, strerror(errno));
/* Retry */
continue;
}
/* Initialize */
if (semctl(semid, 0, SETVAL, 1) < 0)
ERR("%s: SETVAL() failed: %s\n",
__func__, strerror(errno));
}
}
DBG("%d: LOCKING\n", getpid());
sembuf.sem_num = 0;
sembuf.sem_op = -1;
sembuf.sem_flg = SEM_UNDO;
if (semop(semid, &sembuf, 1) < 0)
ERR("%s: semop() failed: %s\n", __func__, strerror(errno));
DBG("%d: LOCKED\n", getpid());
}
static void xusb_unlock_usb()
{
struct sembuf sembuf;
DBG("%d: UNLOCKING\n", getpid());
sembuf.sem_num = 0;
sembuf.sem_op = 1;
sembuf.sem_flg = SEM_UNDO;
if (semop(semid, &sembuf, 1) < 0)
ERR("%s: semop() failed: %s\n", __func__, strerror(errno));
DBG("%d: UNLOCKED\n", getpid());
}
static int initizalized;
static void xusb_init()
{
if (!initizalized) {
xtalk_parse_options();
if (!xtalk_option_no_lock())
xusb_lock_usb();
usb_init();
usb_find_busses();
usb_find_devices();
initizalized = 1;
if (!xtalk_option_no_lock())
xusb_unlock_usb();
}
}
/* XTALK option handling */
static int use_clear_halt = 1;
static int libusb_no_lock = 0;
static int xtalk_one_option(const char *option_string)
{
if (strcmp(option_string, "use-clear-halt") == 0) {
use_clear_halt = 1;
return 0;
}
if (strcmp(option_string, "no-use-clear-halt") == 0) {
use_clear_halt = 0;
return 0;
}
if (strcmp(option_string, "no-lock") == 0) {
libusb_no_lock = 1;
return 0;
}
ERR("Unknown XTALK_OPTIONS content: '%s'\n", option_string);
return -EINVAL;
}
int xtalk_option_use_clear_halt(void)
{
return use_clear_halt;
}
int xtalk_option_no_lock(void)
{
return libusb_no_lock;
}
int xtalk_parse_options(void)
{
char *xtalk_options;
char *saveptr;
char *token;
int ret;
xtalk_options = getenv("XTALK_OPTIONS");
if (!xtalk_options)
return 0;
token = strtok_r(xtalk_options, " \t", &saveptr);
while (token) {
ret = xtalk_one_option(token);
if (ret < 0)
return ret;
token = strtok_r(NULL, " \t", &saveptr);
}
return 0;
}

View File

@ -1,102 +0,0 @@
#ifndef XUSB_H
#define XUSB_H
/*
* Written by Oron Peled <oron@actcom.co.il>
* Copyright (C) 2008, Xorcom
*
* 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 <stdint.h>
#include <usb.h>
#include <xlist.h>
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
/*
* Xorcom usb handling
*/
#define PACKET_SIZE 512
/*
* Specify the wanted interface
*/
struct xusb_spec {
/* Sanity checks so we know it is our device indeed */
int num_interfaces;
int num_endpoints;
char *name; /* For debug/output purpose */
/* What we will actually use */
uint16_t my_vendor_id;
uint16_t my_product_id;
int my_interface_num;
int my_ep_out;
int my_ep_in;
};
void xusb_init_spec(struct xusb_spec *xusb_spec, char *name,
uint16_t vendor_id, uint16_t product_id,
int nifaces, int iface, int nep, int ep_out, int ep_in);
struct xusb;
/*
* Prototypes
*/
typedef int (*xusb_filter_t)(const struct xusb *xusb, void *data);
struct xlist_node *xusb_find_byproduct(const struct xusb_spec *specs,
int numspecs, xusb_filter_t filterfunc, void *data);
struct xusb *xusb_find_bypath(const struct xusb_spec *specs, int numspecs,
const char *path);
struct xusb *xusb_open_one(const struct xusb_spec *specs, int numspecs,
xusb_filter_t filterfunc, void *data);
struct xusb *xusb_find_iface(const char *devpath, int iface_num,
int ep_out, int ep_in, struct xusb_spec *dummy);
/*
* A convenience filter
*/
int xusb_filter_bypath(const struct xusb *xusb, void *data);
int xusb_interface(struct xusb *xusb);
int xusb_claim_interface(struct xusb *xusb);
void xusb_destroy(struct xusb *xusb);
int xusb_close(struct xusb *xusb);
size_t xusb_packet_size(const struct xusb *xusb);
void xusb_showinfo(const struct xusb *xusb);
const char *xusb_serial(const struct xusb *xusb);
const char *xusb_manufacturer(const struct xusb *xusb);
const char *xusb_product(const struct xusb *xusb);
uint16_t xusb_vendor_id(const struct xusb *xusb);
uint16_t xusb_product_id(const struct xusb *xusb);
const char *xusb_devpath(const struct xusb *xusb);
const struct xusb_spec *xusb_spec(const struct xusb *xusb);
int xusb_send(struct xusb *xusb, char *buf, int len, int timeout);
int xusb_recv(struct xusb *xusb, char *buf, size_t len, int timeout);
int xusb_flushread(struct xusb *xusb);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* XUSB_H */

View File

@ -566,7 +566,7 @@ struct xusb_device *xusb_find_bypath(const char *path)
ERR("usb device without a device descriptor\n");
continue;
}
INFO("Found: %04x:%04x %s\n",
DBG("Found: %04x:%04x %s\n",
dev_desc.idVendor, dev_desc.idProduct, devpath_tail);
xusb_init_spec(spec, "<BYPATH>",
dev_desc.idVendor, dev_desc.idProduct);