summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTzafrir Cohen <tzafrir.cohen@xorcom.com>2009-11-22 11:48:40 +0000
committerTzafrir Cohen <tzafrir.cohen@xorcom.com>2009-11-22 11:48:40 +0000
commita55fc0054985fe01558a440fda80549fbe17e01a (patch)
treef6a72b209413f67c36c891d6e356eaa7d759e81e
parentd61645339b4515d0873288d908fbdb920b5b43d5 (diff)
xpp: MPP protocol v.1.4
* New firmware loading protocol - Older one (1.3) is still supported for now * Support loading firmwares from Astribanks with a minimal firmware (1163) * astribank_tool -Q: always query, regardless of verbosity level xpp rev: up to 7559 Merged revisions 7609 via svnmerge from https://origsvn.digium.com/svn/dahdi/tools/trunk git-svn-id: http://svn.asterisk.org/svn/dahdi/tools/branches/2.2@7621 a0bf4364-ded3-4de4-8d8a-66a801d63aff
-rw-r--r--xpp/astribank_hexload.c67
-rw-r--r--xpp/astribank_tool.89
-rw-r--r--xpp/astribank_tool.c31
-rw-r--r--xpp/astribank_usb.h1
-rw-r--r--xpp/mpp.h22
-rw-r--r--xpp/mpp_funcs.c204
-rw-r--r--xpp/mpp_funcs.h6
-rw-r--r--xpp/perl_modules/Dahdi/Hardware/USB.pm1
-rw-r--r--xpp/perl_modules/Dahdi/Xpp/Mpp.pm15
9 files changed, 253 insertions, 103 deletions
diff --git a/xpp/astribank_hexload.c b/xpp/astribank_hexload.c
index 411bab2..28463e0 100644
--- a/xpp/astribank_hexload.c
+++ b/xpp/astribank_hexload.c
@@ -41,6 +41,7 @@ static void usage()
{
fprintf(stderr, "Usage: %s [options...] -D {/proc/bus/usb|/dev/bus/usb}/<bus>/<dev> hexfile...\n", progname);
fprintf(stderr, "\tOptions: {-F|-p}\n");
+ fprintf(stderr, "\t\t[-E] # Burn to EEPROM\n");
fprintf(stderr, "\t\t[-F] # Load FPGA firmware\n");
fprintf(stderr, "\t\t[-p] # Load PIC firmware\n");
fprintf(stderr, "\t\t[-v] # Increase verbosity\n");
@@ -65,24 +66,27 @@ int handle_hexline(struct astribank_device *astribank, struct hexline *hexline)
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) {
- ERR("Failed FPGA send line: %d\n", ret);
+ ERR("Failed hexfile send line: %d\n", ret);
return -EINVAL;
}
return 0;
}
-static int load_fpga(struct astribank_device *astribank, const char *hexfile)
+static int load_hexfile(struct astribank_device *astribank, const char *hexfile, enum dev_dest dest)
{
struct hexdata *hexdata = NULL;
int finished = 0;
int ret;
int i;
+ char star[] = "+\\+|+/+-";
if((hexdata = parse_hexfile(hexfile, MAX_HEX_LINES)) == NULL) {
perror(hexfile);
return -errno;
}
- INFO("Loading FPGA: %s (version %s)\n", hexdata->fname, hexdata->version_info);
+ INFO("Loading hexfile to %s: %s (version %s)\n",
+ dev_dest2str(dest),
+ hexdata->fname, hexdata->version_info);
#if 0
FILE *fp;
if((fp = fopen("fpga_dump_new.txt", "w")) == NULL) {
@@ -90,8 +94,8 @@ static int load_fpga(struct astribank_device *astribank, const char *hexfile)
exit(1);
}
#endif
- if((ret = mpp_send_start(astribank, DEST_FPGA)) < 0) {
- ERR("Failed FPGA send start: %d\n", ret);
+ if((ret = mpp_send_start(astribank, dest, hexdata->version_info)) < 0) {
+ ERR("Failed hexfile send start: %d\n", ret);
return ret;
}
for(i = 0; i < hexdata->maxlines; i++) {
@@ -99,6 +103,10 @@ static int load_fpga(struct astribank_device *astribank, const char *hexfile)
if(!hexline)
break;
+ if(verbose > LOG_INFO) {
+ printf("Sending: %4d%% %c\r", (100 * i) / hexdata->last_line, star[i % sizeof(star)]);
+ fflush(stdout);
+ }
if(finished) {
ERR("Extra data after End Of Data Record (line %d)\n", i);
return 0;
@@ -109,19 +117,23 @@ static int load_fpga(struct astribank_device *astribank, const char *hexfile)
continue;
}
if((ret = handle_hexline(astribank, hexline)) < 0) {
- ERR("Failed FPGA sending in lineno %d (ret=%d)\n", i, ret);;
+ ERR("Failed hexfile sending in lineno %d (ret=%d)\n", i, ret);;
return ret;
}
}
+ if(verbose > LOG_INFO) {
+ putchar('\n');
+ fflush(stdout);
+ }
if((ret = mpp_send_end(astribank)) < 0) {
- ERR("Failed FPGA send end: %d\n", ret);
+ ERR("Failed hexfile send end: %d\n", ret);
return ret;
}
#if 0
fclose(fp);
#endif
free_hexdata(hexdata);
- DBG("FPGA firmware loaded successfully\n");
+ DBG("hexfile loaded successfully\n");
return 0;
}
@@ -129,9 +141,10 @@ int main(int argc, char *argv[])
{
char *devpath = NULL;
struct astribank_device *astribank;
- int opt_fpga = 0;
int opt_pic = 0;
- const char options[] = "vd:D:Fp";
+ int opt_dest = 0;
+ enum dev_dest dest = DEST_NONE;
+ const char options[] = "vd:D:EFp";
int iface_num;
int ret;
@@ -147,8 +160,21 @@ int main(int argc, char *argv[])
case 'D':
devpath = optarg;
break;
+ case 'E':
+ if(dest != DEST_NONE) {
+ ERR("The -F and -E options are mutually exclusive.\n");
+ usage();
+ }
+ opt_dest = 1;
+ dest = DEST_EEPROM;
+ break;
case 'F':
- opt_fpga = 1;
+ if(dest != DEST_NONE) {
+ ERR("The -F and -E options are mutually exclusive.\n");
+ usage();
+ }
+ opt_dest = 1;
+ dest = DEST_FPGA;
break;
case 'p':
opt_pic = 1;
@@ -162,17 +188,18 @@ int main(int argc, char *argv[])
case 'h':
default:
ERR("Unknown option '%c'\n", c);
- return 1;
+ usage();
}
}
- if((opt_fpga ^ opt_pic) == 0) {
- ERR("The -F and -p options are mutually exclusive.\n");
+ if((opt_dest ^ opt_pic) == 0) {
+ ERR("The -F, -E and -p options are mutually exclusive.\n");
usage();
}
- iface_num = (opt_fpga) ? 1 : 0;
- if(opt_fpga) {
+ iface_num = (opt_dest) ? 1 : 0;
+ if(!opt_pic) {
if(optind != argc - 1) {
- ERR("The -F option requires exacly one hexfile argument\n");
+ ERR("Got %d hexfile names (Need exactly one hexfile)\n",
+ argc - 1 - optind);
usage();
}
}
@@ -185,9 +212,9 @@ int main(int argc, char *argv[])
return 1;
}
show_astribank_info(astribank);
- if(opt_fpga) {
- if(load_fpga(astribank, argv[optind]) < 0) {
- ERR("Loading FPGA firmware failed\n");
+ if(opt_dest) {
+ if(load_hexfile(astribank, argv[optind], dest) < 0) {
+ ERR("Loading firmware to %s failed\n", dev_dest2str(dest));
return 1;
}
} else if(opt_pic) {
diff --git a/xpp/astribank_tool.8 b/xpp/astribank_tool.8
index 57ad2a4..65a5e2e 100644
--- a/xpp/astribank_tool.8
+++ b/xpp/astribank_tool.8
@@ -3,13 +3,15 @@
.SH NAME
astribank_tool \- Xorcom Astribank (xpp) control tool
.SH SYNOPSIS
-.B astribank_tool -D \fIdevice-path\fR [ options ]
+.B astribank_tool [ options ] [ operation... ] -D \fIdevice-path\fR
.B astribank_tool [-h]
.SH DESCRIPTION
.B astribank_tool
is a tool to control the USB-level functionality of an Astribank.
+The tool operates on a single Astribank at a time (given as parameter
+to the -D command line option).
.SH OPTIONS
.B -D
@@ -46,6 +48,11 @@ Astribank will jump to the second port if this system is "not working"
and the system on the second port is available.
.RE
+.B -Q
+.RS
+Query astribank properties via MPP protocol.
+.RE
+
.B -n
.RS
Renumerate the Astribank product number (e.g: from 1161 to 1162).
diff --git a/xpp/astribank_tool.c b/xpp/astribank_tool.c
index db0b7a3..699a2e0 100644
--- a/xpp/astribank_tool.c
+++ b/xpp/astribank_tool.c
@@ -41,14 +41,16 @@ static char *progname;
static void usage()
{
- fprintf(stderr, "Usage: %s [options...] -D {/proc/bus/usb|/dev/bus/usb}/<bus>/<dev>\n", progname);
- fprintf(stderr, "\tOptions: {-n|-r kind}\n");
+ fprintf(stderr, "Usage: %s [options] -D {/proc/bus/usb|/dev/bus/usb}/<bus>/<dev> [operation...]\n", progname);
+ fprintf(stderr, "\tOptions:\n");
+ fprintf(stderr, "\t\t[-v] # Increase verbosity\n");
+ fprintf(stderr, "\t\t[-d mask] # Debug mask (0xFF for everything)\n");
+ fprintf(stderr, "\tOperations:\n");
fprintf(stderr, "\t\t[-n] # Renumerate device\n");
fprintf(stderr, "\t\t[-r kind] # Reset: kind = {half|full}\n");
fprintf(stderr, "\t\t[-p port] # TwinStar: USB port number [0, 1]\n");
fprintf(stderr, "\t\t[-w (0|1)] # TwinStar: Watchdog off or on guard\n");
- fprintf(stderr, "\t\t[-v] # Increase verbosity\n");
- fprintf(stderr, "\t\t[-d mask] # Debug mask (0xFF for everything)\n");
+ fprintf(stderr, "\t\t[-Q] # Query device properties\n");
exit(1);
}
@@ -82,9 +84,6 @@ static int show_hardware(struct astribank_device *astribank)
struct capabilities capabilities;
struct extrainfo extrainfo;
- show_astribank_info(astribank);
- if(verbose <= LOG_INFO)
- return 0;
ret = mpp_caps_get(astribank, &eeprom_table, &capabilities, NULL);
if(ret < 0)
return ret;
@@ -147,11 +146,12 @@ int main(int argc, char *argv[])
{
char *devpath = NULL;
struct astribank_device *astribank;
- const char options[] = "vd:D:nr:p:w:";
+ const char options[] = "vd:D:nr:p:w:Q";
int opt_renumerate = 0;
char *opt_port = NULL;
char *opt_watchdog = NULL;
char *opt_reset = NULL;
+ int opt_query = 0;
int ret;
progname = argv[0];
@@ -184,6 +184,9 @@ int main(int argc, char *argv[])
if(reset_kind(opt_reset) < 0)
usage();
break;
+ case 'Q':
+ opt_query = 1;
+ break;
case 'v':
verbose++;
break;
@@ -215,7 +218,11 @@ int main(int argc, char *argv[])
return 1;
}
- show_hardware(astribank);
+ /*
+ * First process reset options. We want to be able
+ * to reset minimal USB firmwares even if they don't
+ * implement the full MPP protocol (e.g: EEPROM_BURN)
+ */
if(opt_reset) {
int full_reset;
@@ -228,6 +235,11 @@ int main(int argc, char *argv[])
ERR("%s Reseting astribank failed: %d\n",
(full_reset) ? "Full" : "Half", ret);
}
+ goto out;
+ }
+ show_astribank_info(astribank);
+ if(opt_query) {
+ show_hardware(astribank);
} else if(opt_renumerate) {
DBG("Renumerate\n");
if((ret = mpp_renumerate(astribank)) < 0) {
@@ -255,6 +267,7 @@ int main(int argc, char *argv[])
return 1;
}
}
+out:
mpp_exit(astribank);
return 0;
}
diff --git a/xpp/astribank_usb.h b/xpp/astribank_usb.h
index 6f9a429..b3b4d79 100644
--- a/xpp/astribank_usb.h
+++ b/xpp/astribank_usb.h
@@ -78,6 +78,7 @@ struct astribank_device {
uint8_t status;
uint8_t mpp_proto_version;
struct eeprom_table *eeprom;
+ struct firmware_versions fw_versions;
const struct interface_type *fwtype;
uint16_t tx_sequenceno;
};
diff --git a/xpp/mpp.h b/xpp/mpp.h
index b71eb30..45654b7 100644
--- a/xpp/mpp.h
+++ b/xpp/mpp.h
@@ -34,7 +34,8 @@
#define MK_PROTO_VERSION(major, minor) (((major) << 4) | (0x0F & (minor)))
-#define MPP_PROTOCOL_VERSION MK_PROTO_VERSION(1,3)
+#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.
@@ -49,6 +50,13 @@ struct eeprom_table {
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;
@@ -94,6 +102,7 @@ enum mpp_command_ops {
MPP_STATUS_GET = 0x11, /* Get Astribank Status */
MPP_STATUS_GET_REPLY = 0x91,
+ MPP_STATUS_GET_REPLY_V13 = 0x91, /* backward compat */
MPP_EXTRAINFO_GET = 0x13, /* Get extra vendor information */
MPP_EXTRAINFO_GET_REPLY = 0x93,
@@ -150,11 +159,20 @@ CMD_DEF(PROTO_REPLY,
CMD_DEF(STATUS_GET);
+CMD_DEF(STATUS_GET_REPLY_V13,
+ uint8_t i2cs_data;
+
+#define STATUS_FPGA_LOADED(x) ((x) & 0x01)
+ uint8_t status; /* BIT(0) - FPGA is loaded */
+ );
+
+
CMD_DEF(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(EEPROM_SET,
@@ -199,6 +217,7 @@ CMD_DEF(EEPROM_BLK_RD_REPLY,
CMD_DEF(DEV_SEND_START,
uint8_t dest;
+ char ihex_version[VERSION_LEN];
);
CMD_DEF(DEV_SEND_END);
@@ -253,6 +272,7 @@ struct mpp_command {
MEMBER(PROTO_QUERY);
MEMBER(PROTO_REPLY);
MEMBER(STATUS_GET);
+ MEMBER(STATUS_GET_REPLY_V13);
MEMBER(STATUS_GET_REPLY);
MEMBER(EEPROM_SET);
MEMBER(CAPS_GET);
diff --git a/xpp/mpp_funcs.c b/xpp/mpp_funcs.c
index 04b93d6..8f13da2 100644
--- a/xpp/mpp_funcs.c
+++ b/xpp/mpp_funcs.c
@@ -76,6 +76,18 @@ const char *eeprom_type2str(enum eeprom_type et)
return msgs[et];
};
+const char *dev_dest2str(enum dev_dest dest)
+{
+ const static char *msgs[] = {
+ [DEST_NONE] = "NONE",
+ [DEST_FPGA] = "FPGA",
+ [DEST_EEPROM] = "EEPROM",
+ };
+ if(dest > sizeof(msgs)/sizeof(msgs[0]))
+ return NULL;
+ return msgs[dest];
+};
+
struct command_desc {
uint8_t op;
const char *name;
@@ -98,13 +110,13 @@ static const struct command_desc command_table[] = {
CMD_RECV(ACK),
CMD_SEND(PROTO_QUERY),
CMD_SEND(STATUS_GET),
- CMD_SEND(STATUS_GET_REPLY),
+ CMD_RECV(STATUS_GET_REPLY),
CMD_SEND(EEPROM_SET),
CMD_SEND(CAPS_GET),
CMD_RECV(CAPS_GET_REPLY),
CMD_SEND(CAPS_SET),
CMD_SEND(EXTRAINFO_GET),
- CMD_SEND(EXTRAINFO_GET_REPLY),
+ CMD_RECV(EXTRAINFO_GET_REPLY),
CMD_SEND(EXTRAINFO_SET),
CMD_RECV(PROTO_REPLY),
CMD_SEND(RENUM),
@@ -127,6 +139,41 @@ static const struct command_desc command_table[] = {
CMD_SEND(TWS_PWR_GET),
CMD_RECV(TWS_PWR_GET_REPLY),
};
+
+static const struct command_desc command_table_V13[] = {
+ CMD_RECV(ACK),
+ CMD_SEND(PROTO_QUERY),
+ CMD_SEND(STATUS_GET),
+ CMD_RECV(STATUS_GET_REPLY_V13),
+ CMD_SEND(EEPROM_SET),
+ CMD_SEND(CAPS_GET),
+ CMD_RECV(CAPS_GET_REPLY),
+ CMD_SEND(CAPS_SET),
+ CMD_SEND(EXTRAINFO_GET),
+ CMD_RECV(EXTRAINFO_GET_REPLY),
+ CMD_SEND(EXTRAINFO_SET),
+ CMD_RECV(PROTO_REPLY),
+ CMD_SEND(RENUM),
+ CMD_SEND(EEPROM_BLK_RD),
+ CMD_RECV(EEPROM_BLK_RD_REPLY),
+ CMD_SEND(DEV_SEND_SEG),
+ CMD_SEND(DEV_SEND_START),
+ CMD_SEND(DEV_SEND_END),
+ CMD_SEND(RESET),
+ CMD_SEND(HALF_RESET),
+ CMD_SEND(SER_SEND),
+ CMD_SEND(SER_RECV),
+ /* Twinstar */
+ CMD_SEND(TWS_WD_MODE_SET),
+ CMD_SEND(TWS_WD_MODE_GET),
+ CMD_RECV(TWS_WD_MODE_GET_REPLY),
+ CMD_SEND(TWS_PORT_SET),
+ CMD_SEND(TWS_PORT_GET),
+ CMD_RECV(TWS_PORT_GET_REPLY),
+ CMD_SEND(TWS_PWR_GET),
+ CMD_RECV(TWS_PWR_GET_REPLY),
+};
+
#undef CMD_SEND
#undef CMD_RECV
@@ -148,22 +195,45 @@ void free_command(struct mpp_command *cmd)
free(cmd);
}
-struct mpp_command *new_command(uint8_t op, uint16_t extra_data)
+const struct command_desc *get_command_desc(uint8_t protocol_version, uint8_t op)
+{
+ const struct command_desc *desc;
+
+ switch(protocol_version) {
+ case MK_PROTO_VERSION(1,3):
+ if(op > sizeof(command_table_V13)/sizeof(command_table_V13[0])) {
+ //ERR("Invalid op=0x%X. Bigger than max valid op\n", op);
+ return NULL;
+ }
+ desc = &command_table_V13[op];
+ if(!desc->name)
+ return NULL;
+ break;
+ default:
+ if(op > sizeof(command_table)/sizeof(command_table[0])) {
+ //ERR("Invalid op=0x%X. Bigger than max valid op\n", op);
+ return NULL;
+ }
+ desc = &command_table[op];
+ if(!desc->name)
+ return NULL;
+ break;
+ }
+ return desc;
+}
+
+struct mpp_command *new_command(uint8_t protocol_version, uint8_t op, uint16_t extra_data)
{
struct mpp_command *cmd;
const struct command_desc *desc;
uint16_t len;
- DBG("OP=0x%X (extra_data %d)\n", op, extra_data);
- if(op > sizeof(command_table)/sizeof(command_table[0])) {
- ERR("Invalid op=0x%X. Bigger than max valid op\n", op);
- return NULL;
- }
- desc = &command_table[op];
- if(!desc->name) {
+ desc = get_command_desc(protocol_version, 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;
if((cmd = malloc(len)) == NULL) {
ERR("Out of memory\n");
@@ -175,29 +245,6 @@ struct mpp_command *new_command(uint8_t op, uint16_t extra_data)
return cmd;
}
-const struct command_desc *get_command_desc(uint8_t op)
-{
- const struct command_desc *desc;
-
- if(op > sizeof(command_table)/sizeof(command_table[0])) {
- //ERR("Invalid op=0x%X. Bigger than max valid op\n", op);
- return NULL;
- }
- desc = &command_table[op];
- if(!desc->name)
- return NULL;
- return desc;
-}
-
-const char *get_command_name(uint8_t op)
-{
- const struct command_desc *desc;
-
- if((desc = get_command_desc(op)) == NULL)
- return NULL;
- return desc->name;
-}
-
void dump_command(struct mpp_command *cmd)
{
uint16_t len;
@@ -259,6 +306,8 @@ struct mpp_command *recv_command(struct astribank_device *astribank, int 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",
@@ -283,13 +332,17 @@ int process_command(struct astribank_device *astribank, struct mpp_command *cmd,
struct mpp_command *reply = NULL;
const struct command_desc *reply_desc;
const struct command_desc *expected;
+ const struct command_desc *cmd_desc;
uint8_t reply_op;
int ret;
if(reply_ref)
*reply_ref = NULL; /* So the caller knows if a reply was received */
reply_op = cmd->header.op | 0x80;
- expected = get_command_desc(reply_op);
+ if(cmd->header.op == MPP_PROTO_QUERY)
+ astribank->mpp_proto_version = MPP_PROTOCOL_VERSION; /* bootstrap */
+ cmd_desc = get_command_desc(astribank->mpp_proto_version, cmd->header.op);
+ expected = get_command_desc(astribank->mpp_proto_version, reply_op);
//printf("%s: len=%d\n", __FUNCTION__, cmd->header.len);
ret = send_command(astribank, cmd, TIMEOUT);
if(!reply_ref) {
@@ -313,7 +366,7 @@ int process_command(struct astribank_device *astribank, struct mpp_command *cmd,
goto out;
}
DBG("REPLY OP: 0x%X\n", reply->header.op);
- reply_desc = get_command_desc(reply->header.op);
+ reply_desc = get_command_desc(astribank->mpp_proto_version, reply->header.op);
if(!reply_desc) {
ERR("Unknown reply op=0x%02X\n", reply->header.op);
ret = -EPROTO;
@@ -330,8 +383,9 @@ int process_command(struct astribank_device *astribank, struct mpp_command *cmd,
goto out;
} else if(status != STAT_OK) {
- ERR("Got ACK (for OP=0x%X): %d - %s\n",
+ ERR("Got ACK (for OP=0x%X [%s]): %d - %s\n",
cmd->header.op,
+ cmd_desc->name,
status,
ack_status_msg(status));
#if 0
@@ -371,6 +425,12 @@ out:
return ret;
}
+static int set_ihex_version(char *dst, const char *src)
+{
+ memcpy(dst, src, VERSION_LEN);
+ return 0;
+}
+
/*
* Protocol Commands
*/
@@ -383,7 +443,7 @@ int mpp_proto_query(struct astribank_device *astribank)
DBG("\n");
assert(astribank != NULL);
- if((cmd = new_command(MPP_PROTO_QUERY, 0)) == NULL) {
+ if((cmd = new_command(astribank->mpp_proto_version, MPP_PROTO_QUERY, 0)) == NULL) {
ERR("new_command failed\n");
return -ENOMEM;
}
@@ -394,13 +454,17 @@ int mpp_proto_query(struct astribank_device *astribank)
return ret;
}
astribank->mpp_proto_version = CMD_FIELD(reply, PROTO_REPLY, proto_version);
- if(astribank->mpp_proto_version != MPP_PROTOCOL_VERSION) {
+ if(! MPP_SUPPORTED_VERSION(astribank->mpp_proto_version)) {
ERR("Got mpp protocol version: %02x (expected %02x)\n",
astribank->mpp_proto_version,
MPP_PROTOCOL_VERSION);
ret = -EPROTO;
goto out;
}
+ if(astribank->mpp_proto_version != MPP_PROTOCOL_VERSION) {
+ ERR("Deprecated (but working) MPP protocol version [%X]. Please upgrade to [%X] ASAP\n",
+ astribank->mpp_proto_version, MPP_PROTOCOL_VERSION);
+ }
DBG("Protocol version: %02x\n", astribank->mpp_proto_version);
ret = astribank->mpp_proto_version;
free_command(reply);
@@ -416,7 +480,7 @@ int mpp_status_query(struct astribank_device *astribank)
DBG("\n");
assert(astribank != NULL);
- if((cmd = new_command(MPP_STATUS_GET, 0)) == NULL) {
+ if((cmd = new_command(astribank->mpp_proto_version, MPP_STATUS_GET, 0)) == NULL) {
ERR("new_command failed\n");
return -ENOMEM;
}
@@ -427,8 +491,13 @@ int mpp_status_query(struct astribank_device *astribank)
}
astribank->eeprom_type = 0x3 & (CMD_FIELD(reply, STATUS_GET_REPLY, i2cs_data) >> 3);
astribank->status = CMD_FIELD(reply, STATUS_GET_REPLY, status);
+ astribank->fw_versions = CMD_FIELD(reply, STATUS_GET_REPLY, fw_versions);
DBG("EEPROM TYPE: %02x\n", astribank->eeprom_type);
DBG("FPGA Firmware: %s\n", (astribank->status & 0x1) ? "Loaded" : "Empty");
+ DBG("Firmware Versions: USB='%s' FPGA='%s' EEPROM='%s'\n",
+ astribank->fw_versions.usb,
+ astribank->fw_versions.fpga,
+ astribank->fw_versions.eeprom);
free_command(reply);
return ret;
}
@@ -441,7 +510,7 @@ int mpp_eeprom_set(struct astribank_device *astribank, const struct eeprom_table
DBG("\n");
assert(astribank != NULL);
- if((cmd = new_command(MPP_EEPROM_SET, 0)) == NULL) {
+ if((cmd = new_command(astribank->mpp_proto_version, MPP_EEPROM_SET, 0)) == NULL) {
ERR("new_command failed\n");
return -ENOMEM;
}
@@ -462,7 +531,7 @@ int mpp_renumerate(struct astribank_device *astribank)
DBG("\n");
assert(astribank != NULL);
- if((cmd = new_command(MPP_RENUM, 0)) == NULL) {
+ if((cmd = new_command(astribank->mpp_proto_version, MPP_RENUM, 0)) == NULL) {
ERR("new_command failed\n");
return -ENOMEM;
}
@@ -485,7 +554,7 @@ int mpp_caps_get(struct astribank_device *astribank,
DBG("\n");
assert(astribank != NULL);
- if((cmd = new_command(MPP_CAPS_GET, 0)) == NULL) {
+ if((cmd = new_command(astribank->mpp_proto_version, MPP_CAPS_GET, 0)) == NULL) {
ERR("new_command failed\n");
return -ENOMEM;
}
@@ -523,7 +592,7 @@ int mpp_caps_set(struct astribank_device *astribank,
DBG("\n");
assert(astribank != NULL);
- if((cmd = new_command(MPP_CAPS_SET, 0)) == NULL) {
+ if((cmd = new_command(astribank->mpp_proto_version, MPP_CAPS_SET, 0)) == NULL) {
ERR("new_command failed\n");
return -ENOMEM;
}
@@ -547,7 +616,7 @@ int mpp_extrainfo_get(struct astribank_device *astribank, struct extrainfo *info
DBG("\n");
assert(astribank != NULL);
- if((cmd = new_command(MPP_EXTRAINFO_GET, 0)) == NULL) {
+ if((cmd = new_command(astribank->mpp_proto_version, MPP_EXTRAINFO_GET, 0)) == NULL) {
ERR("new_command failed\n");
return -ENOMEM;
}
@@ -572,7 +641,7 @@ int mpp_extrainfo_set(struct astribank_device *astribank, const struct extrainfo
DBG("\n");
assert(astribank != NULL);
- if((cmd = new_command(MPP_EXTRAINFO_SET, 0)) == NULL) {
+ if((cmd = new_command(astribank->mpp_proto_version, MPP_EXTRAINFO_SET, 0)) == NULL) {
ERR("new_command failed\n");
return -ENOMEM;
}
@@ -595,7 +664,7 @@ int mpp_eeprom_blk_rd(struct astribank_device *astribank, uint8_t *buf, uint16_t
DBG("len = %d, offset = %d\n", len, offset);
assert(astribank != NULL);
- if((cmd = new_command(MPP_EEPROM_BLK_RD, 0)) == NULL) {
+ if((cmd = new_command(astribank->mpp_proto_version, MPP_EEPROM_BLK_RD, 0)) == NULL) {
ERR("new_command failed\n");
return -ENOMEM;
}
@@ -620,20 +689,21 @@ out:
return size;
}
-int mpp_send_start(struct astribank_device *astribank, enum dev_dest dest)
+int mpp_send_start(struct astribank_device *astribank, enum dev_dest dest, const char *ihex_version)
{
struct mpp_command *cmd;
struct mpp_command *reply = NULL;
int ret = 0;
- DBG("dest = %d\n", dest);
+ DBG("dest = %s ihex_version = '%s'\n", dev_dest2str(dest), ihex_version);
assert(astribank != NULL);
- if((cmd = new_command(MPP_DEV_SEND_START, 0)) == NULL) {
+ if((cmd = new_command(astribank->mpp_proto_version, MPP_DEV_SEND_START, 0)) == NULL) {
ERR("new_command failed\n");
ret = -ENOMEM;
goto out;
}
CMD_FIELD(cmd, DEV_SEND_START, dest) = dest;
+ set_ihex_version(CMD_FIELD(cmd, DEV_SEND_START, ihex_version), ihex_version);
ret = process_command(astribank, cmd, &reply);
if(ret < 0) {
ERR("process_command failed: %d\n", ret);
@@ -656,7 +726,7 @@ int mpp_send_end(struct astribank_device *astribank)
DBG("\n");
assert(astribank != NULL);
- if((cmd = new_command(MPP_DEV_SEND_END, 0)) == NULL) {
+ if((cmd = new_command(astribank->mpp_proto_version, MPP_DEV_SEND_END, 0)) == NULL) {
ERR("new_command failed\n");
ret = -ENOMEM;
goto out;
@@ -688,7 +758,7 @@ int mpp_send_seg(struct astribank_device *astribank, const uint8_t *data, uint16
}
DBG("len = %d, offset = %d (0x%02X, 0x%02X)\n", len, offset, *data, *(data + 1));
assert(astribank != NULL);
- if((cmd = new_command(MPP_DEV_SEND_SEG, len)) == NULL) {
+ if((cmd = new_command(astribank->mpp_proto_version, MPP_DEV_SEND_SEG, len)) == NULL) {
ERR("new_command failed\n");
return -ENOMEM;
}
@@ -725,7 +795,7 @@ int mpp_reset(struct astribank_device *astribank, int full_reset)
DBG("full = %s\n", (full_reset) ? "YES" : "NO");
assert(astribank != NULL);
- if((cmd = new_command(op, 0)) == NULL) {
+ if((cmd = new_command(astribank->mpp_proto_version, op, 0)) == NULL) {
ERR("new_command failed\n");
return -ENOMEM;
}
@@ -746,7 +816,7 @@ int mpp_serial_cmd(struct astribank_device *astribank, const uint8_t *in, uint8_
DBG("len=%d\n", len);
assert(astribank != NULL);
- if((cmd = new_command(MPP_SER_SEND, len)) == NULL) {
+ if((cmd = new_command(astribank->mpp_proto_version, MPP_SER_SEND, len)) == NULL) {
ERR("new_command failed\n");
return -ENOMEM;
}
@@ -804,7 +874,7 @@ int mpp_tws_watchdog(struct astribank_device *astribank)
DBG("\n");
assert(astribank != NULL);
- if((cmd = new_command(MPP_TWS_WD_MODE_GET, 0)) == NULL) {
+ if((cmd = new_command(astribank->mpp_proto_version, MPP_TWS_WD_MODE_GET, 0)) == NULL) {
ERR("new_command failed\n");
return -ENOMEM;
}
@@ -827,7 +897,7 @@ int mpp_tws_setwatchdog(struct astribank_device *astribank, int yes)
DBG("%s\n", (yes) ? "YES" : "NO");
assert(astribank != NULL);
- if((cmd = new_command(MPP_TWS_WD_MODE_SET, 0)) == NULL) {
+ if((cmd = new_command(astribank->mpp_proto_version, MPP_TWS_WD_MODE_SET, 0)) == NULL) {
ERR("new_command failed\n");
return -ENOMEM;
}
@@ -849,7 +919,7 @@ int mpp_tws_powerstate(struct astribank_device *astribank)
DBG("\n");
assert(astribank != NULL);
- if((cmd = new_command(MPP_TWS_PWR_GET, 0)) == NULL) {
+ if((cmd = new_command(astribank->mpp_proto_version, MPP_TWS_PWR_GET, 0)) == NULL) {
ERR("new_command failed\n");
return -ENOMEM;
}
@@ -872,7 +942,7 @@ int mpp_tws_portnum(struct astribank_device *astribank)
DBG("\n");
assert(astribank != NULL);
- if((cmd = new_command(MPP_TWS_PORT_GET, 0)) == NULL) {
+ if((cmd = new_command(astribank->mpp_proto_version, MPP_TWS_PORT_GET, 0)) == NULL) {
ERR("new_command failed\n");
return -ENOMEM;
}
@@ -891,7 +961,6 @@ int mpp_tws_setportnum(struct astribank_device *astribank, uint8_t portnum)
{
struct mpp_command *cmd;
int ret;
- struct mpp_command *reply;
DBG("\n");
assert(astribank != NULL);
@@ -899,17 +968,16 @@ int mpp_tws_setportnum(struct astribank_device *astribank, uint8_t portnum)
ERR("Invalid portnum (%d)\n", portnum);
return -EINVAL;
}
- if((cmd = new_command(MPP_TWS_PORT_SET, 0)) == NULL) {
+ if((cmd = new_command(astribank->mpp_proto_version, MPP_TWS_PORT_SET, 0)) == NULL) {
ERR("new_command failed\n");
return -ENOMEM;
}
CMD_FIELD(cmd, TWS_PORT_SET, portnum) = portnum;
- ret = process_command(astribank, cmd, &reply);
+ ret = process_command(astribank, cmd, NULL);
if(ret < 0) {
ERR("process_command failed: %d\n", ret);
return ret;
}
- free_command(reply);
return 0;
}
@@ -983,9 +1051,19 @@ void show_capabilities(const struct capabilities *capabilities, FILE *fp)
void show_astribank_status(struct astribank_device *astribank, FILE *fp)
{
- fprintf(fp, "Astribank: EEPROM : %s\n", eeprom_type2str(astribank->eeprom_type));
+ char version_buf[BUFSIZ];
+ int is_loaded = STATUS_FPGA_LOADED(astribank->status);
+
+ fprintf(fp, "Astribank: EEPROM : %s\n",
+ eeprom_type2str(astribank->eeprom_type));
fprintf(fp, "Astribank: FPGA status : %s\n",
- STATUS_FPGA_LOADED(astribank->status) ? "Loaded" : "Empty");
+ is_loaded ? "Loaded" : "Empty");
+ if(is_loaded) {
+ memset(version_buf, 0, sizeof(version_buf));
+ memcpy(version_buf, astribank->fw_versions.fpga, VERSION_LEN);
+ fprintf(fp, "Astribank: FPGA version: %s\n",
+ version_buf);
+ }
}
void show_extrainfo(const struct extrainfo *extrainfo, FILE *fp)
diff --git a/xpp/mpp_funcs.h b/xpp/mpp_funcs.h
index 8ab4b3a..59bbc7d 100644
--- a/xpp/mpp_funcs.h
+++ b/xpp/mpp_funcs.h
@@ -45,7 +45,7 @@ int mpp_caps_set(struct astribank_device *astribank,
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, enum dev_dest dest);
+int mpp_send_start(struct astribank_device *astribank, enum dev_dest 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);
@@ -72,7 +72,9 @@ int mpp_tws_setportnum(struct astribank_device *astribank, uint8_t portnum);
/* low-level */
int process_command(struct astribank_device *astribank, struct mpp_command *cmd, struct mpp_command **reply_ref);
-struct mpp_command *new_command(uint8_t op, uint16_t extra_data);
+struct mpp_command *new_command(uint8_t protocol_version, uint8_t op, uint16_t extra_data);
void free_command(struct mpp_command *cmd);
+const char *dev_dest2str(enum dev_dest dest);
+
#endif /* MPP_FUNCS_H */
diff --git a/xpp/perl_modules/Dahdi/Hardware/USB.pm b/xpp/perl_modules/Dahdi/Hardware/USB.pm
index 722b87b..ae1bf93 100644
--- a/xpp/perl_modules/Dahdi/Hardware/USB.pm
+++ b/xpp/perl_modules/Dahdi/Hardware/USB.pm
@@ -33,6 +33,7 @@ my %usb_ids = (
'e4e4:1160' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-modular no-firmware' },
'e4e4:1161' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-modular USB-firmware' },
'e4e4:1162' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-modular FPGA-firmware' },
+ 'e4e4:1163' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-TwinStar monitor' },
# Sangoma USB FXO:
'10c4:8461' => { DRIVER => 'wanpipe', DESCRIPTION => 'Sangoma WANPIPE USB-FXO Device' },
diff --git a/xpp/perl_modules/Dahdi/Xpp/Mpp.pm b/xpp/perl_modules/Dahdi/Xpp/Mpp.pm
index c95b13a..2c11a94 100644
--- a/xpp/perl_modules/Dahdi/Xpp/Mpp.pm
+++ b/xpp/perl_modules/Dahdi/Xpp/Mpp.pm
@@ -102,8 +102,9 @@ sub showinfo($$) {
}
}
-sub astribank_tool_cmd($) {
+sub astribank_tool_cmd($@) {
my $dev = shift || die;
+ my @args = @_;
my $usb_top;
# Find USB bus toplevel
@@ -113,7 +114,7 @@ sub astribank_tool_cmd($) {
my $name = $dev->priv_device_name();
die "$0: Unkown private device name" unless defined $name;
my $path = "$usb_top/$name";
- return ($astribank_tool, '-D', "$path");
+ return ($astribank_tool, '-D', "$path", @args);
}
sub new($$$) {
@@ -136,7 +137,7 @@ sub new($$$) {
}
return $mppinfo unless $product =~ /116[12]/;
$mppinfo->{'MPP_TALK'} = 1;
- my @cmd = astribank_tool_cmd($dev);
+ my @cmd = astribank_tool_cmd($dev, '-Q');
my $name = $dev->priv_device_name();
my $dbg_file = "$name";
$dbg_file =~ s/\W/_/g;
@@ -191,9 +192,9 @@ sub mpp_setwatchdog($$) {
my $dev = $mppinfo->dev || die;
return undef unless defined $mppinfo->mpp_talk;
my $old = $mppinfo->tws_watchdog;
- my @cmd = astribank_tool_cmd($dev);
+ my @cmd = astribank_tool_cmd($dev, '-w', $on);
print STDERR "DEBUG($on): '@cmd'\n";
- system(@cmd, '-w', $on);
+ system(@cmd);
die "Running $astribank_tool failed: $?" if $?;
}
@@ -204,8 +205,8 @@ sub mpp_jump($) {
my $port = $mppinfo->twinstar_port;
$port = ($port == 1) ? 0 : 1;
die "Unknown TwinStar port" unless defined $port;
- my @cmd = astribank_tool_cmd($dev);
- system(@cmd, '-p', $port);
+ my @cmd = astribank_tool_cmd($dev, '-p', $port);
+ system(@cmd);
die "Running $astribank_tool failed: $?" if $?;
}