~vibhavp/ubuntu/raring/dahdi-tools/merge-from-debian

« back to all changes in this revision

Viewing changes to xpp/mpptalk.c

  • Committer: Vibhav Pant
  • Date: 2012-12-26 17:23:16 UTC
  • mfrom: (2.1.6 sid)
  • Revision ID: vibhavp@gmail.com-20121226172316-o2jojsfcnr0aqrme
* Merge from Debian unstable. Remaining changes:
  - Bug Fix: If linux-headers are not installed, don't block, and print
    information for the user.
  - added debian/dahdi.postinst
  - added --error-handler=init_failed to debian/rules
  - debian/control: Added gawk as dependency for dkms build (LP: #493304)
  - Changes from Debian:
    - debian/control: Change Maintainer
    - debian/control: Removed Uploaders field.
    - debian/control: Removed Debian Vcs-Svn entry and replaced with
      ubuntu-voip Vcs-Bzr, to reflect divergence in packages.
    - debian/control: Package dahdi Depends on dahdi-dkms | dahdi-source 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Written by Oron Peled <oron@actcom.co.il>
 
3
 * Copyright (C) 2008, Xorcom
 
4
 *
 
5
 * All rights reserved.
 
6
 *
 
7
 * This program is free software; you can redistribute it and/or modify
 
8
 * it under the terms of the GNU General Public License as published by
 
9
 * the Free Software Foundation; either version 2 of the License, or
 
10
 * (at your option) any later version.
 
11
 *
 
12
 * This program is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
 * GNU General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU General Public License
 
18
 * along with this program; if not, write to the Free Software
 
19
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
20
 *
 
21
 */
 
22
 
 
23
#include <stdio.h>
 
24
#include <string.h>
 
25
#include <assert.h>
 
26
#include <errno.h>
 
27
#include <arpa/inet.h>
 
28
#include "hexfile.h"
 
29
#include "astribank_usb.h"
 
30
#include "mpp.h"
 
31
#include "mpptalk.h"
 
32
#include <debug.h>
 
33
#include <xusb.h>
 
34
#include <xtalk.h>
 
35
 
 
36
static const char rcsid[] = "$Id: mpptalk.c 9825 2011-03-10 18:48:11Z tzafrir $";
 
37
 
 
38
#define DBG_MASK        0x02
 
39
 
 
40
const char *ack_status_msg(uint8_t status)
 
41
{
 
42
        const static char       *msgs[] = {
 
43
                [STAT_OK] = "Acknowledges previous command",
 
44
                [STAT_FAIL] = "Last command failed",
 
45
                [STAT_RESET_FAIL] = "Reset failed",
 
46
                [STAT_NODEST] = "No destination is selected",
 
47
                [STAT_MISMATCH] = "Data mismatch",
 
48
                [STAT_NOACCESS] = "No access",
 
49
                [STAT_BAD_CMD] = "Bad command",
 
50
                [STAT_TOO_SHORT] = "Packet is too short",
 
51
                [STAT_ERROFFS] = "Offset error",
 
52
                [STAT_NOCODE] = "Source was not burned before",
 
53
                [STAT_NO_LEEPROM] = "Large EEPROM was not found",
 
54
                [STAT_NO_EEPROM] = "No EEPROM was found",
 
55
                [STAT_WRITE_FAIL] = "Writing to device failed",
 
56
                [STAT_FPGA_ERR] = "FPGA error",
 
57
                [STAT_KEY_ERR] = "Bad Capabilities Key",
 
58
                [STAT_NOCAPS_ERR]       = "No matching capability",
 
59
                [STAT_NOPWR_ERR]        = "No power on USB connector",
 
60
                [STAT_CAPS_FPGA_ERR]    = "Setting of the capabilities while FPGA is loaded",
 
61
        };
 
62
        if(status > sizeof(msgs)/sizeof(msgs[0]))
 
63
                return "ERROR CODE TOO LARGE";
 
64
        if(!msgs[status])
 
65
                return "MISSING ERROR CODE";
 
66
        return msgs[status];
 
67
}
 
68
 
 
69
const char *eeprom_type2str(int et)
 
70
{
 
71
        const static char       *msgs[] = {
 
72
                [EEPROM_TYPE_NONE]      = "NONE",
 
73
                [EEPROM_TYPE_SMALL]     = "SMALL",
 
74
                [EEPROM_TYPE_LARGE]     = "LARGE",
 
75
                [EEPROM_TYPE_UNUSED]    = "UNUSED",
 
76
        };
 
77
        if(et > sizeof(msgs)/sizeof(msgs[0]))
 
78
                return NULL;
 
79
        return msgs[et];
 
80
};
 
81
 
 
82
const char *dev_dest2str(int dest)
 
83
{
 
84
        const static char       *msgs[] = {
 
85
                [DEST_NONE]     = "NONE",
 
86
                [DEST_FPGA]     = "FPGA",
 
87
                [DEST_EEPROM]   = "EEPROM",
 
88
        };
 
89
        if(dest > sizeof(msgs)/sizeof(msgs[0]))
 
90
                return NULL;
 
91
        return msgs[dest];
 
92
};
 
93
 
 
94
union XTALK_PDATA(MPP) {
 
95
                MEMBER(MPP, STATUS_GET);
 
96
                MEMBER(MPP, STATUS_GET_REPLY);
 
97
                MEMBER(MPP, EEPROM_SET);
 
98
                MEMBER(MPP, CAPS_GET);
 
99
                MEMBER(MPP, CAPS_GET_REPLY);
 
100
                MEMBER(MPP, CAPS_SET);
 
101
                MEMBER(MPP, EXTRAINFO_GET);
 
102
                MEMBER(MPP, EXTRAINFO_GET_REPLY);
 
103
                MEMBER(MPP, EXTRAINFO_SET);
 
104
                MEMBER(MPP, RENUM);
 
105
                MEMBER(MPP, EEPROM_BLK_RD);
 
106
                MEMBER(MPP, EEPROM_BLK_RD_REPLY);
 
107
                MEMBER(MPP, DEV_SEND_SEG);
 
108
                MEMBER(MPP, DEV_SEND_START);
 
109
                MEMBER(MPP, DEV_SEND_END);
 
110
                MEMBER(MPP, RESET);
 
111
                MEMBER(MPP, HALF_RESET);
 
112
                MEMBER(MPP, SER_SEND);
 
113
                MEMBER(MPP, SER_RECV);
 
114
                /* Twinstar */
 
115
                MEMBER(MPP, TWS_WD_MODE_SET);
 
116
                MEMBER(MPP, TWS_WD_MODE_GET);
 
117
                MEMBER(MPP, TWS_WD_MODE_GET_REPLY);
 
118
                MEMBER(MPP, TWS_PORT_SET);
 
119
                MEMBER(MPP, TWS_PORT_GET);
 
120
                MEMBER(MPP, TWS_PORT_GET_REPLY);
 
121
                MEMBER(MPP, TWS_PWR_GET);
 
122
                MEMBER(MPP, TWS_PWR_GET_REPLY);
 
123
} PACKED members;
 
124
 
 
125
struct xtalk_protocol   astribank_proto = {
 
126
        .name   = "ABNK",
 
127
        .proto_version = 0x14,
 
128
        .commands = {
 
129
                CMD_SEND(MPP, STATUS_GET),
 
130
                CMD_RECV(MPP, STATUS_GET_REPLY, NULL),
 
131
                CMD_SEND(MPP, EEPROM_SET),
 
132
                CMD_SEND(MPP, CAPS_GET),
 
133
                CMD_RECV(MPP, CAPS_GET_REPLY, NULL),
 
134
                CMD_SEND(MPP, CAPS_SET),
 
135
                CMD_SEND(MPP, EXTRAINFO_GET),
 
136
                CMD_RECV(MPP, EXTRAINFO_GET_REPLY, NULL),
 
137
                CMD_SEND(MPP, EXTRAINFO_SET),
 
138
                CMD_SEND(MPP, RENUM),
 
139
                CMD_SEND(MPP, EEPROM_BLK_RD),
 
140
                CMD_RECV(MPP, EEPROM_BLK_RD_REPLY, NULL),
 
141
                CMD_SEND(MPP, DEV_SEND_SEG),
 
142
                CMD_SEND(MPP, DEV_SEND_START),
 
143
                CMD_SEND(MPP, DEV_SEND_END),
 
144
                CMD_SEND(MPP, RESET),
 
145
                CMD_SEND(MPP, HALF_RESET),
 
146
                CMD_SEND(MPP, SER_SEND),
 
147
                CMD_SEND(MPP, SER_RECV),
 
148
                /* Twinstar */
 
149
                CMD_SEND(MPP, TWS_WD_MODE_SET),
 
150
                CMD_SEND(MPP, TWS_WD_MODE_GET),
 
151
                CMD_RECV(MPP, TWS_WD_MODE_GET_REPLY, NULL),
 
152
                CMD_SEND(MPP, TWS_PORT_SET),
 
153
                CMD_SEND(MPP, TWS_PORT_GET),
 
154
                CMD_RECV(MPP, TWS_PORT_GET_REPLY, NULL),
 
155
                CMD_SEND(MPP, TWS_PWR_GET),
 
156
                CMD_RECV(MPP, TWS_PWR_GET_REPLY, NULL),
 
157
        },
 
158
        .ack_statuses = {
 
159
        }
 
160
};
 
161
 
 
162
struct cmd_queue {
 
163
        struct cmd_queue        *next;
 
164
        struct cmd_queue        *prev;
 
165
        struct xtalk_command    *cmd;
 
166
};
 
167
 
 
168
static struct cmd_queue output_queue = {
 
169
        .next = &output_queue,
 
170
        .prev = &output_queue,
 
171
        .cmd = NULL
 
172
        };
 
173
 
 
174
void dump_command(struct xtalk_command *cmd)
 
175
{
 
176
        uint16_t        len;
 
177
        int             i;
 
178
 
 
179
        len = cmd->header.len;
 
180
        if(len < sizeof(struct mpp_header)) {
 
181
                ERR("Command too short (%d)\n", len);
 
182
                return;
 
183
        }
 
184
        INFO("DUMP: OP=0x%X len=%d seq=%d\n",
 
185
                cmd->header.op, cmd->header.len, cmd->header.seq);
 
186
        for(i = 0; i < len - sizeof(struct mpp_header); i++) {
 
187
                INFO("  %2d. 0x%X\n", i, cmd->alt.raw_data[i]);
 
188
        }
 
189
}
 
190
 
 
191
 
 
192
static int set_ihex_version(char *dst, const char *src)
 
193
{
 
194
        memcpy(dst, src, VERSION_LEN);
 
195
        return 0;
 
196
}
 
197
 
 
198
/*
 
199
 * Protocol Commands
 
200
 */
 
201
 
 
202
int mpp_status_query(struct astribank_device *astribank)
 
203
{
 
204
        struct xtalk_command    *cmd;
 
205
        struct xtalk_command    *reply;
 
206
        struct xtalk_device     *xtalk_dev;
 
207
        int                     ret;
 
208
 
 
209
        DBG("\n");
 
210
        assert(astribank != NULL);
 
211
        xtalk_dev = astribank->xtalk_dev;
 
212
        if((cmd = new_command(xtalk_dev, MPP_STATUS_GET, 0)) == NULL) {
 
213
                ERR("new_command failed\n");
 
214
                return -ENOMEM;
 
215
        }
 
216
        ret = process_command(xtalk_dev, cmd, &reply);
 
217
        if(ret < 0) {
 
218
                ERR("process_command failed: %d\n", ret);
 
219
                return ret;
 
220
        }
 
221
        astribank->eeprom_type = 0x3 & (CMD_FIELD(reply, MPP, STATUS_GET_REPLY, i2cs_data) >> 3);
 
222
        astribank->status = CMD_FIELD(reply, MPP, STATUS_GET_REPLY, status);
 
223
        astribank->fw_versions = CMD_FIELD(reply, MPP, STATUS_GET_REPLY, fw_versions);
 
224
        DBG("EEPROM TYPE: %02x\n", astribank->eeprom_type);
 
225
        DBG("FPGA Firmware: %s\n", (astribank->status & 0x1) ? "Loaded" : "Empty");
 
226
        DBG("Firmware Versions: USB='%s' FPGA='%s' EEPROM='%s'\n",
 
227
                astribank->fw_versions.usb,
 
228
                astribank->fw_versions.fpga,
 
229
                astribank->fw_versions.eeprom);
 
230
        free_command(reply);
 
231
        return ret;
 
232
}
 
233
 
 
234
int mpp_eeprom_set(struct astribank_device *astribank, const struct eeprom_table *et)
 
235
{
 
236
        struct xtalk_command    *cmd;
 
237
        struct xtalk_command    *reply;
 
238
        struct xtalk_device     *xtalk_dev;
 
239
        int                     ret;
 
240
 
 
241
        DBG("\n");
 
242
        assert(astribank != NULL);
 
243
        xtalk_dev = astribank->xtalk_dev;
 
244
        if((cmd = new_command(xtalk_dev, MPP_EEPROM_SET, 0)) == NULL) {
 
245
                ERR("new_command failed\n");
 
246
                return -ENOMEM;
 
247
        }
 
248
        memcpy(&CMD_FIELD(cmd, MPP, EEPROM_SET, data), et, sizeof(*et));
 
249
        ret = process_command(xtalk_dev, cmd, &reply);
 
250
        if(ret < 0) {
 
251
                ERR("process_command failed: %d\n", ret);
 
252
                return ret;
 
253
        }
 
254
        free_command(reply);
 
255
        return 0;
 
256
}
 
257
 
 
258
int mpp_renumerate(struct astribank_device *astribank)
 
259
{
 
260
        struct xtalk_command    *cmd;
 
261
        struct xtalk_device     *xtalk_dev;
 
262
        int                     ret;
 
263
 
 
264
        DBG("\n");
 
265
        assert(astribank != NULL);
 
266
        xtalk_dev = astribank->xtalk_dev;
 
267
        if((cmd = new_command(xtalk_dev, MPP_RENUM, 0)) == NULL) {
 
268
                ERR("new_command failed\n");
 
269
                return -ENOMEM;
 
270
        }
 
271
        ret = process_command(xtalk_dev, cmd, NULL);
 
272
        if(ret < 0) {
 
273
                ERR("process_command failed: %d\n", ret);
 
274
                return ret;
 
275
        }
 
276
        return 0;
 
277
}
 
278
 
 
279
int mpp_caps_get(struct astribank_device *astribank,
 
280
        struct eeprom_table *eeprom_table,
 
281
        struct capabilities *capabilities,
 
282
        struct capkey *key)
 
283
{
 
284
        struct xtalk_command    *cmd;
 
285
        struct xtalk_command    *reply;
 
286
        struct xtalk_device     *xtalk_dev;
 
287
        int                     ret;
 
288
 
 
289
        DBG("\n");
 
290
        assert(astribank != NULL);
 
291
        xtalk_dev = astribank->xtalk_dev;
 
292
        if((cmd = new_command(xtalk_dev, MPP_CAPS_GET, 0)) == NULL) {
 
293
                ERR("new_command failed\n");
 
294
                return -ENOMEM;
 
295
        }
 
296
        ret = process_command(xtalk_dev, cmd, &reply);
 
297
        if(ret < 0) {
 
298
                ERR("process_command failed: %d\n", ret);
 
299
                return ret;
 
300
        }
 
301
        assert(reply->header.op == MPP_CAPS_GET_REPLY);
 
302
        if(eeprom_table) {
 
303
                memcpy(eeprom_table, (void *)&CMD_FIELD(reply, MPP, CAPS_GET_REPLY, data), sizeof(*eeprom_table));
 
304
        }
 
305
        if(capabilities) {
 
306
                const struct capabilities       *cap = &CMD_FIELD(reply, MPP, CAPS_GET_REPLY, capabilities);
 
307
 
 
308
                memcpy(capabilities, cap, sizeof(*capabilities));
 
309
        }
 
310
        if(key) {
 
311
                const struct capkey     *k = &CMD_FIELD(reply, MPP, CAPS_GET_REPLY, key);
 
312
 
 
313
                memcpy(key, k, sizeof(*key));
 
314
        }
 
315
        free_command(reply);
 
316
        return 0;
 
317
}
 
318
 
 
319
int mpp_caps_set(struct astribank_device *astribank,
 
320
        const struct eeprom_table *eeprom_table,
 
321
        const struct capabilities *capabilities,
 
322
        const struct capkey *key)
 
323
{
 
324
        struct xtalk_command    *cmd;
 
325
        struct xtalk_command    *reply;
 
326
        struct xtalk_device     *xtalk_dev;
 
327
        int                     ret;
 
328
 
 
329
        DBG("\n");
 
330
        assert(astribank != NULL);
 
331
        xtalk_dev = astribank->xtalk_dev;
 
332
        if((cmd = new_command(xtalk_dev, MPP_CAPS_SET, 0)) == NULL) {
 
333
                ERR("new_command failed\n");
 
334
                return -ENOMEM;
 
335
        }
 
336
        memcpy(&CMD_FIELD(cmd, MPP, CAPS_SET, data), eeprom_table, sizeof(*eeprom_table));
 
337
        memcpy(&CMD_FIELD(cmd, MPP, CAPS_SET, capabilities), capabilities, sizeof(*capabilities));
 
338
        memcpy(&CMD_FIELD(cmd, MPP, CAPS_SET, key), key, sizeof(*key));
 
339
        ret = process_command(xtalk_dev, cmd, &reply);
 
340
        if(ret < 0) {
 
341
                ERR("process_command failed: %d\n", ret);
 
342
                return ret;
 
343
        }
 
344
        free_command(reply);
 
345
        return 0;
 
346
}
 
347
 
 
348
int mpp_extrainfo_get(struct astribank_device *astribank, struct extrainfo *info)
 
349
{
 
350
        struct xtalk_command    *cmd;
 
351
        struct xtalk_command    *reply;
 
352
        struct xtalk_device     *xtalk_dev;
 
353
        int                     ret;
 
354
 
 
355
        DBG("\n");
 
356
        assert(astribank != NULL);
 
357
        xtalk_dev = astribank->xtalk_dev;
 
358
        if((cmd = new_command(xtalk_dev, MPP_EXTRAINFO_GET, 0)) == NULL) {
 
359
                ERR("new_command failed\n");
 
360
                return -ENOMEM;
 
361
        }
 
362
        ret = process_command(xtalk_dev, cmd, &reply);
 
363
        if(ret < 0) {
 
364
                ERR("process_command failed: %d\n", ret);
 
365
                return ret;
 
366
        }
 
367
        assert(reply->header.op == MPP_EXTRAINFO_GET_REPLY);
 
368
        if(info) {
 
369
                memcpy(info, (void *)&CMD_FIELD(reply, MPP, EXTRAINFO_GET_REPLY, info), sizeof(*info));
 
370
        }
 
371
        free_command(reply);
 
372
        return 0;
 
373
}
 
374
 
 
375
int mpp_extrainfo_set(struct astribank_device *astribank, const struct extrainfo *info)
 
376
{
 
377
        struct xtalk_command    *cmd;
 
378
        struct xtalk_command    *reply;
 
379
        struct xtalk_device     *xtalk_dev;
 
380
        int                     ret;
 
381
 
 
382
        DBG("\n");
 
383
        assert(astribank != NULL);
 
384
        xtalk_dev = astribank->xtalk_dev;
 
385
        if((cmd = new_command(xtalk_dev, MPP_EXTRAINFO_SET, 0)) == NULL) {
 
386
                ERR("new_command failed\n");
 
387
                return -ENOMEM;
 
388
        }
 
389
        memcpy(&CMD_FIELD(cmd, MPP, EXTRAINFO_SET, info), info, sizeof(*info));
 
390
        ret = process_command(xtalk_dev, cmd, &reply);
 
391
        if(ret < 0) {
 
392
                ERR("process_command failed: %d\n", ret);
 
393
                return ret;
 
394
        }
 
395
        free_command(reply);
 
396
        return 0;
 
397
}
 
398
 
 
399
int mpp_eeprom_blk_rd(struct astribank_device *astribank, uint8_t *buf, uint16_t offset, uint16_t len)
 
400
{
 
401
        struct xtalk_command    *cmd;
 
402
        struct xtalk_command    *reply;
 
403
        struct xtalk_device     *xtalk_dev;
 
404
        int                     ret;
 
405
        int                     size;
 
406
 
 
407
        DBG("len = %d, offset = %d\n", len, offset);
 
408
        assert(astribank != NULL);
 
409
        xtalk_dev = astribank->xtalk_dev;
 
410
        if((cmd = new_command(xtalk_dev, MPP_EEPROM_BLK_RD, 0)) == NULL) {
 
411
                ERR("new_command failed\n");
 
412
                return -ENOMEM;
 
413
        }
 
414
        CMD_FIELD(cmd, MPP, EEPROM_BLK_RD, len) = len;
 
415
        CMD_FIELD(cmd, MPP, EEPROM_BLK_RD, offset) = offset;
 
416
        ret = process_command(xtalk_dev, cmd, &reply);
 
417
        if(ret < 0) {
 
418
                ERR("process_command failed: %d\n", ret);
 
419
                size = ret;
 
420
                goto out;
 
421
        }
 
422
        size = reply->header.len - sizeof(struct mpp_header) - sizeof(XTALK_STRUCT(MPP, EEPROM_BLK_RD_REPLY));
 
423
        INFO("size=%d offset=0x%X\n", size, CMD_FIELD(reply, MPP, EEPROM_BLK_RD_REPLY, offset));
 
424
        dump_packet(LOG_DEBUG, DBG_MASK, "BLK_RD", (char *)reply, ret);
 
425
        if(size > len) {
 
426
                ERR("Truncating reply (was %d, now %d)\n", size, len);
 
427
                size = len;
 
428
        }
 
429
        memcpy(buf, CMD_FIELD(reply, MPP, EEPROM_BLK_RD_REPLY, data), size);
 
430
out:
 
431
        free_command(reply);
 
432
        return size;
 
433
}
 
434
 
 
435
int mpp_send_start(struct astribank_device *astribank, int dest, const char *ihex_version)
 
436
{
 
437
        struct xtalk_command    *cmd;
 
438
        struct xtalk_command    *reply = NULL;
 
439
        struct xtalk_device     *xtalk_dev;
 
440
        int                     ret = 0;
 
441
 
 
442
        DBG("dest = %s ihex_version = '%s'\n", dev_dest2str(dest), ihex_version);
 
443
        assert(astribank != NULL);
 
444
        xtalk_dev = astribank->xtalk_dev;
 
445
        if((cmd = new_command(xtalk_dev, MPP_DEV_SEND_START, 0)) == NULL) {
 
446
                ERR("new_command failed\n");
 
447
                ret = -ENOMEM;
 
448
                goto out;
 
449
        }
 
450
        CMD_FIELD(cmd, MPP, DEV_SEND_START, dest) = dest;
 
451
        set_ihex_version(CMD_FIELD(cmd, MPP, DEV_SEND_START, ihex_version), ihex_version);
 
452
        ret = process_command(xtalk_dev, cmd, &reply);
 
453
        if(ret < 0) {
 
454
                ERR("process_command failed: %d\n", ret);
 
455
                goto out;
 
456
        }
 
457
out:
 
458
        if(reply)
 
459
                free_command(reply);
 
460
        astribank->burn_state = (ret == 0)
 
461
                ? BURN_STATE_STARTED
 
462
                : BURN_STATE_FAILED;
 
463
        return ret;
 
464
}
 
465
 
 
466
int mpp_send_end(struct astribank_device *astribank)
 
467
{
 
468
        struct xtalk_command    *cmd;
 
469
        struct xtalk_command    *reply = NULL;
 
470
        struct xtalk_device     *xtalk_dev;
 
471
        int                     ret = 0;
 
472
 
 
473
        DBG("\n");
 
474
        assert(astribank != NULL);
 
475
        xtalk_dev = astribank->xtalk_dev;
 
476
        if((cmd = new_command(xtalk_dev, MPP_DEV_SEND_END, 0)) == NULL) {
 
477
                ERR("new_command failed\n");
 
478
                ret = -ENOMEM;
 
479
                goto out;
 
480
        }
 
481
        ret = process_command(xtalk_dev, cmd, &reply);
 
482
        if(ret < 0) {
 
483
                ERR("process_command failed: %d\n", ret);
 
484
                goto out;
 
485
        }
 
486
out:
 
487
        if(reply)
 
488
                free_command(reply);
 
489
        astribank->burn_state = (ret == 0)
 
490
                ? BURN_STATE_ENDED
 
491
                : BURN_STATE_FAILED;
 
492
        return ret;
 
493
}
 
494
 
 
495
int mpp_send_seg(struct astribank_device *astribank, const uint8_t *data, uint16_t offset, uint16_t len)
 
496
{
 
497
        struct xtalk_command    *cmd;
 
498
        struct xtalk_command    *reply;
 
499
        struct xtalk_device     *xtalk_dev;
 
500
        int                     ret;
 
501
 
 
502
        assert(astribank != NULL);
 
503
        xtalk_dev = astribank->xtalk_dev;
 
504
        if(!astribank->burn_state == BURN_STATE_STARTED) {
 
505
                ERR("Tried to send a segment while burn_state=%d\n",
 
506
                                astribank->burn_state);
 
507
                return -EINVAL;
 
508
        }
 
509
        DBG("len = %d, offset = %d (0x%02X, 0x%02X)\n", len, offset, *data, *(data + 1));
 
510
        if((cmd = new_command(xtalk_dev, MPP_DEV_SEND_SEG, len)) == NULL) {
 
511
                ERR("new_command failed\n");
 
512
                return -ENOMEM;
 
513
        }
 
514
        CMD_FIELD(cmd, MPP, DEV_SEND_SEG, offset) = offset;
 
515
        memcpy(CMD_FIELD(cmd, MPP, DEV_SEND_SEG, data), data, len);
 
516
#if 0
 
517
        {
 
518
                FILE                    *fp;
 
519
                if((fp = fopen("seg_data.bin", "a")) == NULL) {
 
520
                        perror("seg_data.bin");
 
521
                        exit(1);
 
522
                }
 
523
                if(fwrite(CMD_FIELD(cmd, MPP, DEV_SEND_SEG, data), len, 1, fp) != 1) {
 
524
                        perror("fwrite");
 
525
                        exit(1);
 
526
                }
 
527
                fclose(fp);
 
528
        }
 
529
#endif
 
530
        ret = process_command(xtalk_dev, cmd, &reply);
 
531
        if(ret < 0) {
 
532
                ERR("process_command failed: %d\n", ret);
 
533
                return ret;
 
534
        }
 
535
        free_command(reply);
 
536
        return 0;
 
537
}
 
538
 
 
539
int mpp_reset(struct astribank_device *astribank, int full_reset)
 
540
{
 
541
        struct xtalk_command    *cmd;
 
542
        struct xtalk_device     *xtalk_dev;
 
543
        int                     ret;
 
544
        int                     op = (full_reset) ? MPP_RESET: MPP_HALF_RESET;
 
545
 
 
546
        DBG("full = %s\n", (full_reset) ? "YES" : "NO");
 
547
        assert(astribank != NULL);
 
548
        xtalk_dev = astribank->xtalk_dev;
 
549
        if((cmd = new_command(xtalk_dev, op, 0)) == NULL) {
 
550
                ERR("new_command failed\n");
 
551
                return -ENOMEM;
 
552
        }
 
553
        ret = process_command(xtalk_dev, cmd, NULL);
 
554
        if(ret < 0) {
 
555
                ERR("process_command failed: %d\n", ret);
 
556
                return ret;
 
557
        }
 
558
        return 0;
 
559
}
 
560
 
 
561
int mpp_serial_cmd(struct astribank_device *astribank, const uint8_t *in, uint8_t *out, uint16_t len)
 
562
{
 
563
        struct xtalk_command    *cmd;
 
564
        struct xtalk_command    *reply;
 
565
        struct xtalk_device     *xtalk_dev;
 
566
        int                     ret;
 
567
        uint8_t                 *data;
 
568
 
 
569
        DBG("len=%d\n", len);
 
570
        assert(astribank != NULL);
 
571
        xtalk_dev = astribank->xtalk_dev;
 
572
        if((cmd = new_command(xtalk_dev, MPP_SER_SEND, len)) == NULL) {
 
573
                ERR("new_command failed\n");
 
574
                return -ENOMEM;
 
575
        }
 
576
        data = CMD_FIELD(cmd, MPP, SER_SEND, data);
 
577
        memcpy(data, in, len);
 
578
        ret = process_command(xtalk_dev, cmd, &reply);
 
579
        if(ret < 0) {
 
580
                ERR("process_command failed: %d\n", ret);
 
581
                return ret;
 
582
        }
 
583
        assert(reply->header.op == MPP_SER_RECV);
 
584
        data = CMD_FIELD(reply, MPP, SER_RECV, data);
 
585
        memcpy(out, data, len);
 
586
        free_command(reply);
 
587
        return 0;
 
588
}
 
589
 
 
590
int mpps_card_info(struct astribank_device *astribank, int unit, uint8_t *card_type, uint8_t *card_status)
 
591
{
 
592
        struct card_info_send {
 
593
                uint8_t ser_op;
 
594
                uint8_t addr;
 
595
        } *card_info_send;
 
596
        struct card_info_recv {
 
597
                uint8_t ser_op_undef;   /* invalid data */
 
598
                uint8_t addr;
 
599
                uint8_t card_full_type; /* (type << 4 | subtype) */
 
600
                uint8_t card_status;    /* BIT(0) - PIC burned */
 
601
        } *card_info_recv;
 
602
        uint8_t in[sizeof(struct card_info_recv)];
 
603
        uint8_t out[sizeof(struct card_info_recv)];
 
604
        int     len;
 
605
        int     ret;
 
606
 
 
607
        len = sizeof(struct card_info_recv);
 
608
        memset(in, 0, len);
 
609
        memset(out, 0, len);
 
610
        card_info_send = (struct card_info_send *)&in;
 
611
        card_info_recv = (struct card_info_recv *)&out;
 
612
        card_info_send->ser_op = SER_CARD_INFO_GET;
 
613
        card_info_send->addr = (unit << 4);     /* low nibble is subunit */
 
614
        ret = mpp_serial_cmd(astribank, in, out, len);
 
615
        if(ret < 0)
 
616
                return ret;
 
617
        *card_type = card_info_recv->card_full_type;
 
618
        *card_status = card_info_recv->card_status;
 
619
        return 0;
 
620
}
 
621
 
 
622
int mpp_tws_watchdog(struct astribank_device *astribank)
 
623
{
 
624
        struct xtalk_command    *cmd;
 
625
        struct xtalk_command    *reply;
 
626
        struct xtalk_device     *xtalk_dev;
 
627
        int                     ret;
 
628
 
 
629
        DBG("\n");
 
630
        assert(astribank != NULL);
 
631
        xtalk_dev = astribank->xtalk_dev;
 
632
        if((cmd = new_command(xtalk_dev, MPP_TWS_WD_MODE_GET, 0)) == NULL) {
 
633
                ERR("new_command failed\n");
 
634
                return -ENOMEM;
 
635
        }
 
636
        ret = process_command(xtalk_dev, cmd, &reply);
 
637
        if(ret < 0) {
 
638
                ERR("process_command failed: %d\n", ret);
 
639
                return ret;
 
640
        }
 
641
        ret = CMD_FIELD(reply, MPP, TWS_WD_MODE_GET_REPLY, wd_active);
 
642
        DBG("wd_active=0x%X\n", ret);
 
643
        free_command(reply);
 
644
        return ret == 1;
 
645
}
 
646
 
 
647
int mpp_tws_setwatchdog(struct astribank_device *astribank, int yes)
 
648
{
 
649
        struct xtalk_command    *cmd;
 
650
        struct xtalk_command    *reply;
 
651
        struct xtalk_device     *xtalk_dev;
 
652
        int                     ret;
 
653
 
 
654
        DBG("%s\n", (yes) ? "YES" : "NO");
 
655
        assert(astribank != NULL);
 
656
        xtalk_dev = astribank->xtalk_dev;
 
657
        if((cmd = new_command(xtalk_dev, MPP_TWS_WD_MODE_SET, 0)) == NULL) {
 
658
                ERR("new_command failed\n");
 
659
                return -ENOMEM;
 
660
        }
 
661
        CMD_FIELD(cmd, MPP, TWS_WD_MODE_SET, wd_active) = (yes) ? 1 : 0;
 
662
        ret = process_command(xtalk_dev, cmd, &reply);
 
663
        if(ret < 0) {
 
664
                ERR("process_command failed: %d\n", ret);
 
665
                return ret;
 
666
        }
 
667
        free_command(reply);
 
668
        return 0;
 
669
}
 
670
 
 
671
int mpp_tws_powerstate(struct astribank_device *astribank)
 
672
{
 
673
        struct xtalk_command    *cmd;
 
674
        struct xtalk_command    *reply;
 
675
        struct xtalk_device     *xtalk_dev;
 
676
        int                     ret;
 
677
 
 
678
        DBG("\n");
 
679
        assert(astribank != NULL);
 
680
        xtalk_dev = astribank->xtalk_dev;
 
681
        if((cmd = new_command(xtalk_dev, MPP_TWS_PWR_GET, 0)) == NULL) {
 
682
                ERR("new_command failed\n");
 
683
                return -ENOMEM;
 
684
        }
 
685
        ret = process_command(xtalk_dev, cmd, &reply);
 
686
        if(ret < 0) {
 
687
                ERR("process_command failed: %d\n", ret);
 
688
                return ret;
 
689
        }
 
690
        ret = CMD_FIELD(reply, MPP, TWS_PWR_GET_REPLY, power);
 
691
        DBG("power=0x%X\n", ret);
 
692
        free_command(reply);
 
693
        return ret;
 
694
}
 
695
 
 
696
int mpp_tws_portnum(struct astribank_device *astribank)
 
697
{
 
698
        struct xtalk_command    *cmd;
 
699
        struct xtalk_command    *reply;
 
700
        struct xtalk_device     *xtalk_dev;
 
701
        int                     ret;
 
702
 
 
703
        DBG("\n");
 
704
        assert(astribank != NULL);
 
705
        xtalk_dev = astribank->xtalk_dev;
 
706
        if((cmd = new_command(xtalk_dev, MPP_TWS_PORT_GET, 0)) == NULL) {
 
707
                ERR("new_command failed\n");
 
708
                return -ENOMEM;
 
709
        }
 
710
        ret = process_command(xtalk_dev, cmd, &reply);
 
711
        if(ret < 0) {
 
712
                ERR("process_command failed: %d\n", ret);
 
713
                return ret;
 
714
        }
 
715
        ret = CMD_FIELD(reply, MPP, TWS_PORT_GET_REPLY, portnum);
 
716
        DBG("portnum=0x%X\n", ret);
 
717
        free_command(reply);
 
718
        return ret;
 
719
}
 
720
 
 
721
int mpp_tws_setportnum(struct astribank_device *astribank, uint8_t portnum)
 
722
{
 
723
        struct xtalk_command    *cmd;
 
724
        struct xtalk_device     *xtalk_dev;
 
725
        int                     ret;
 
726
 
 
727
        DBG("\n");
 
728
        assert(astribank != NULL);
 
729
        xtalk_dev = astribank->xtalk_dev;
 
730
        if(portnum >= 2) {
 
731
                ERR("Invalid portnum (%d)\n", portnum);
 
732
                return -EINVAL;
 
733
        }
 
734
        if((cmd = new_command(xtalk_dev, MPP_TWS_PORT_SET, 0)) == NULL) {
 
735
                ERR("new_command failed\n");
 
736
                return -ENOMEM;
 
737
        }
 
738
        CMD_FIELD(cmd, MPP, TWS_PORT_SET, portnum) = portnum;
 
739
        ret = process_command(xtalk_dev, cmd, NULL);
 
740
        if(ret < 0) {
 
741
                ERR("process_command failed: %d\n", ret);
 
742
                return ret;
 
743
        }
 
744
        return 0;
 
745
}
 
746
 
 
747
/* Adapters for xusb ops */
 
748
static inline int xusb_close_func(void *priv)
 
749
{
 
750
        return xusb_close((struct xusb *)priv);
 
751
}
 
752
 
 
753
static inline int xusb_send_func(void *priv, void *data, size_t len, int timeout)
 
754
{
 
755
        return xusb_send((struct xusb *)priv, data, len, timeout);
 
756
}
 
757
 
 
758
static inline int xusb_recv_func(void *priv, void *data, size_t maxlen, int timeout)
 
759
{
 
760
        return xusb_recv((struct xusb *)priv, data, maxlen, timeout);
 
761
}
 
762
 
 
763
 
 
764
static struct xtalk_ops xusb_ops = {
 
765
        .send_func      = xusb_send_func,
 
766
        .recv_func      = xusb_recv_func,
 
767
        .close_func     = xusb_close_func,
 
768
};
 
769
 
 
770
/*
 
771
 * Wrappers
 
772
 */
 
773
 
 
774
struct astribank_device *mpp_init(const char devpath[], int iface_num)
 
775
{
 
776
        struct astribank_device *astribank = NULL;
 
777
        struct xtalk_device     *xtalk_dev = NULL;
 
778
        struct xusb             *xusb = NULL;
 
779
        int                     packet_size;
 
780
        int                     ret;
 
781
 
 
782
        DBG("devpath='%s' iface_num=%d\n", devpath, iface_num);
 
783
        if((astribank = astribank_open(devpath, iface_num)) == NULL) {
 
784
                ERR("Opening astribank failed\n");
 
785
                goto err;
 
786
        }
 
787
        xusb = astribank->xusb;
 
788
        packet_size = xusb_packet_size(xusb);
 
789
        if((xtalk_dev = xtalk_new(&xusb_ops, packet_size, xusb)) == NULL) {
 
790
                ERR("Allocating new XTALK device failed\n");
 
791
                goto err;
 
792
        }
 
793
        astribank->xtalk_dev = xtalk_dev;
 
794
        ret = xtalk_set_protocol(xtalk_dev, &astribank_proto);
 
795
        if(ret < 0) {
 
796
                ERR("MPP Protocol registration failed: %d\n", ret);
 
797
                goto err;
 
798
        }
 
799
        ret = xtalk_proto_query(xtalk_dev);
 
800
        if(ret < 0) {
 
801
                ERR("Protocol handshake failed: %d\n", ret);
 
802
                goto err;
 
803
        }
 
804
        ret = mpp_status_query(astribank);
 
805
        if(ret < 0) {
 
806
                ERR("Status query failed: %d\n", ret);
 
807
                goto err;
 
808
        }
 
809
        return astribank;
 
810
 
 
811
err:
 
812
        if (astribank) {
 
813
                astribank_close(astribank, 0);
 
814
                astribank = NULL;
 
815
        }
 
816
        if(xtalk_dev) {
 
817
                xtalk_delete(xtalk_dev);
 
818
                xtalk_dev = NULL;
 
819
        }
 
820
        return NULL;
 
821
}
 
822
 
 
823
void mpp_exit(struct astribank_device *astribank)
 
824
{
 
825
        DBG("\n");
 
826
        astribank_close(astribank, 0);
 
827
}
 
828
 
 
829
/*
 
830
 * data structures
 
831
 */
 
832
 
 
833
void show_eeprom(const struct eeprom_table *eprm, FILE *fp)
 
834
{
 
835
        int     rmajor = (eprm->release >> 8) & 0xFF;
 
836
        int     rminor = eprm->release & 0xFF;;
 
837
        char    buf[BUFSIZ];
 
838
 
 
839
        memset(buf, 0, LABEL_SIZE + 1);
 
840
        memcpy(buf, eprm->label, LABEL_SIZE);
 
841
        fprintf(fp, "EEPROM: %-15s: 0x%02X\n", "Source", eprm->source);
 
842
        fprintf(fp, "EEPROM: %-15s: 0x%04X\n", "Vendor", eprm->vendor);
 
843
        fprintf(fp, "EEPROM: %-15s: 0x%04X\n", "Product", eprm->product);
 
844
        fprintf(fp, "EEPROM: %-15s: %d.%d\n", "Release", rmajor, rminor);
 
845
        fprintf(fp, "EEPROM: %-15s: 0x%02X\n", "Config", eprm->config_byte);
 
846
        fprintf(fp, "EEPROM: %-15s: '%s'\n", "Label", buf);
 
847
}
 
848
 
 
849
void show_capabilities(const struct capabilities *capabilities, FILE *fp)
 
850
{
 
851
        fprintf(fp, "Capabilities: FXS ports: %2d\n", capabilities->ports_fxs);
 
852
        fprintf(fp, "Capabilities: FXO ports: %2d\n", capabilities->ports_fxo);
 
853
        fprintf(fp, "Capabilities: BRI ports: %2d\n", capabilities->ports_bri);
 
854
        fprintf(fp, "Capabilities: PRI ports: %2d\n", capabilities->ports_pri);
 
855
        fprintf(fp, "Capabilities: ECHO ports: %2d\n", capabilities->ports_echo);
 
856
        fprintf(fp, "Capabilities: TwinStar : %s\n",
 
857
                (CAP_EXTRA_TWINSTAR(capabilities)) ? "Yes" : "No");
 
858
}
 
859
 
 
860
void show_astribank_status(struct astribank_device *astribank, FILE *fp)
 
861
{
 
862
        char    version_buf[BUFSIZ];
 
863
        int     is_loaded = STATUS_FPGA_LOADED(astribank->status);
 
864
 
 
865
        fprintf(fp, "Astribank: EEPROM      : %s\n",
 
866
                eeprom_type2str(astribank->eeprom_type));
 
867
        fprintf(fp, "Astribank: FPGA status : %s\n",
 
868
                is_loaded ? "Loaded" : "Empty");
 
869
        if(is_loaded) {
 
870
                memset(version_buf, 0, sizeof(version_buf));
 
871
                memcpy(version_buf, astribank->fw_versions.fpga, VERSION_LEN);
 
872
                fprintf(fp, "Astribank: FPGA version: %s\n",
 
873
                        version_buf);
 
874
        }
 
875
}
 
876
 
 
877
void show_extrainfo(const struct extrainfo *extrainfo, FILE *fp)
 
878
{
 
879
        fprintf(fp, "Extrainfo:             : %s\n", (const char *)(extrainfo->text));
 
880
}
 
881
 
 
882
int twinstar_show(struct astribank_device *astribank, FILE *fp)
 
883
{
 
884
        int     watchdog;
 
885
        int     powerstate;
 
886
        int     portnum;
 
887
        int     i;
 
888
 
 
889
        if(!astribank_has_twinstar(astribank)) {
 
890
                fprintf(fp, "TwinStar: NO\n");
 
891
                return 0;
 
892
        }
 
893
        if((watchdog = mpp_tws_watchdog(astribank)) < 0) {
 
894
                ERR("Failed getting TwinStar information\n");
 
895
                return watchdog;
 
896
        }
 
897
        if((powerstate = mpp_tws_powerstate(astribank)) < 0) {
 
898
                ERR("Failed getting TwinStar powerstate\n");
 
899
                return powerstate;
 
900
        }
 
901
        if((portnum = mpp_tws_portnum(astribank)) < 0) {
 
902
                ERR("Failed getting TwinStar portnum\n");
 
903
                return portnum;
 
904
        }
 
905
        fprintf(fp, "TwinStar: Connected to : USB-%1d\n", portnum);
 
906
        fprintf(fp, "TwinStar: Watchdog     : %s\n",
 
907
                (watchdog) ? "on-guard" : "off-guard");
 
908
        for(i = 0; i < 2; i++) {
 
909
                int     pw = (1 << i) & powerstate;
 
910
 
 
911
                fprintf(fp, "TwinStar: USB-%1d POWER  : %s\n",
 
912
                        i, (pw) ? "ON" : "OFF");
 
913
        }
 
914
        return 0;
 
915
}