diff options
author | Tzafrir Cohen <tzafrir.cohen@xorcom.com> | 2009-11-22 11:48:40 +0000 |
---|---|---|
committer | Tzafrir Cohen <tzafrir.cohen@xorcom.com> | 2009-11-22 11:48:40 +0000 |
commit | a55fc0054985fe01558a440fda80549fbe17e01a (patch) | |
tree | f6a72b209413f67c36c891d6e356eaa7d759e81e | |
parent | d61645339b4515d0873288d908fbdb920b5b43d5 (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.c | 67 | ||||
-rw-r--r-- | xpp/astribank_tool.8 | 9 | ||||
-rw-r--r-- | xpp/astribank_tool.c | 31 | ||||
-rw-r--r-- | xpp/astribank_usb.h | 1 | ||||
-rw-r--r-- | xpp/mpp.h | 22 | ||||
-rw-r--r-- | xpp/mpp_funcs.c | 204 | ||||
-rw-r--r-- | xpp/mpp_funcs.h | 6 | ||||
-rw-r--r-- | xpp/perl_modules/Dahdi/Hardware/USB.pm | 1 | ||||
-rw-r--r-- | xpp/perl_modules/Dahdi/Xpp/Mpp.pm | 15 |
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; }; @@ -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 $?; } |