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

« back to all changes in this revision

Viewing changes to xpp/xtalk/xtalk.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) 2009, 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 <stdlib.h>
 
25
#include <string.h>
 
26
#include <assert.h>
 
27
#include <errno.h>
 
28
#include <arpa/inet.h>
 
29
#include <xtalk.h>
 
30
#include <debug.h>
 
31
 
 
32
static const char rcsid[] = "$Id: xtalk.c 9825 2011-03-10 18:48:11Z tzafrir $";
 
33
 
 
34
#define DBG_MASK        0x02
 
35
 
 
36
#define TIMEOUT         6000
 
37
 
 
38
/*
 
39
 * Base XTALK device. A pointer to this struct
 
40
 * should be included in the struct representing
 
41
 * the dialect.
 
42
 */
 
43
struct xtalk_device {
 
44
        void                    *transport_priv;        /* e.g: struct xusb */
 
45
        struct xtalk_ops        ops;
 
46
        struct xtalk_protocol   xproto;
 
47
        uint8_t                 xtalk_proto_version;
 
48
        uint8_t                 status;
 
49
        size_t                  packet_size;
 
50
        uint16_t                tx_sequenceno;
 
51
};
 
52
 
 
53
CMD_DEF(XTALK, ACK,
 
54
        uint8_t stat;
 
55
        );
 
56
 
 
57
CMD_DEF(XTALK, PROTO_GET,
 
58
        uint8_t proto_version;
 
59
        uint8_t reserved;
 
60
        );
 
61
 
 
62
CMD_DEF(XTALK, PROTO_GET_REPLY,
 
63
        uint8_t proto_version;
 
64
        uint8_t reserved;
 
65
        );
 
66
 
 
67
union XTALK_PDATA(XTALK) {
 
68
        MEMBER(XTALK, ACK);
 
69
        MEMBER(XTALK, PROTO_GET);
 
70
        MEMBER(XTALK, PROTO_GET_REPLY);
 
71
} PACKED members;
 
72
 
 
73
struct xtalk_protocol   xtalk_base = {
 
74
        .name   = "XTALK",
 
75
        .proto_version = 0,
 
76
        .commands = {
 
77
                CMD_RECV(XTALK, ACK, NULL),
 
78
                CMD_SEND(XTALK, PROTO_GET),
 
79
                CMD_RECV(XTALK, PROTO_GET_REPLY, NULL),
 
80
        },
 
81
        .ack_statuses = {
 
82
                ACK_STAT(OK, "Acknowledges previous command"),
 
83
                ACK_STAT(FAIL, "Last command failed"),
 
84
                ACK_STAT(RESET_FAIL, "reset failed"),
 
85
                ACK_STAT(NODEST, "No destination is selected"),
 
86
                ACK_STAT(MISMATCH, "Data mismatch"),
 
87
                ACK_STAT(NOACCESS, "No access"),
 
88
                ACK_STAT(BAD_CMD, "Bad command"),
 
89
                ACK_STAT(TOO_SHORT, "Packet is too short"),
 
90
                ACK_STAT(ERROFFS, "Offset error (not used)"),
 
91
                ACK_STAT(NO_LEEPROM, "Large EEPROM was not found"),
 
92
                ACK_STAT(NO_EEPROM, "No EEPROM was found"),
 
93
                ACK_STAT(WRITE_FAIL, "Writing to device failed"),
 
94
                ACK_STAT(NOPWR_ERR, "No power on USB connector"),
 
95
        }
 
96
};
 
97
 
 
98
void free_command(struct xtalk_command *cmd)
 
99
{
 
100
        if(!cmd)
 
101
                return;
 
102
        memset(cmd, 0, cmd->header.len);
 
103
        free(cmd);
 
104
}
 
105
 
 
106
static const struct xtalk_command_desc *get_command_desc(const struct xtalk_protocol *xproto, uint8_t op)
 
107
{
 
108
        const struct xtalk_command_desc *desc;
 
109
 
 
110
        if(!xproto)
 
111
                return NULL;
 
112
        desc = &xproto->commands[op];
 
113
        if(!desc->name)
 
114
                return NULL;
 
115
#if 0
 
116
        DBG("%s version=%d, op=0x%X (%s)\n",
 
117
                xproto->name, xproto->proto_version,
 
118
                op, desc->name);
 
119
#endif
 
120
        return desc;
 
121
}
 
122
 
 
123
static const char *ack_status_msg(const struct xtalk_protocol *xproto, uint8_t status)
 
124
{
 
125
        const char      *ack_status;
 
126
 
 
127
        if(!xproto)
 
128
                return NULL;
 
129
        ack_status = xproto->ack_statuses[status];
 
130
        DBG("%s status=0x%X (%s)\n", xproto->name, status, ack_status);
 
131
        return ack_status;
 
132
}
 
133
 
 
134
int xtalk_set_protocol(struct xtalk_device *xtalk_dev, const struct xtalk_protocol *xproto)
 
135
{
 
136
        const char      *protoname = (xproto) ? xproto->name : "GLOBAL";
 
137
        int             i;
 
138
 
 
139
        DBG("%s\n", protoname);
 
140
        memset(&xtalk_dev->xproto, 0, sizeof(xtalk_dev->xproto));
 
141
        for(i = 0; i < MAX_OPS; i++) {
 
142
                const struct xtalk_command_desc *desc;
 
143
 
 
144
                desc = get_command_desc(xproto, i);
 
145
                if(desc) {
 
146
                        if(!IS_PRIVATE_OP(i)) {
 
147
                                ERR("Bad op=0x%X (should be in the range [0x%X-0x%X]\n",
 
148
                                        i, PRIVATE_OP_FIRST, PRIVATE_OP_LAST);
 
149
                                return -EINVAL;
 
150
                        }
 
151
                        xtalk_dev->xproto.commands[i] = *desc;
 
152
                        DBG("private: op=0x%X (%s)\n", i, desc->name);
 
153
                } else {
 
154
                        if(!IS_PRIVATE_OP(i)) {
 
155
                                const char      *name;
 
156
 
 
157
                                xtalk_dev->xproto.commands[i] = xtalk_base.commands[i];
 
158
                                name = xtalk_dev->xproto.commands[i].name;
 
159
                                if(name)
 
160
                                        DBG("global: op=0x%X (%s)\n", i, name);
 
161
                        }
 
162
                }
 
163
        }
 
164
        for(i = 0; i < MAX_STATUS; i++) {
 
165
                const char      *stat_msg;
 
166
 
 
167
                stat_msg = (xproto) ? xproto->ack_statuses[i] : NULL;
 
168
                if(stat_msg) {
 
169
                        if(!IS_PRIVATE_OP(i)) {
 
170
                                ERR("Bad status=0x%X (should be in the range [0x%X-0x%X]\n",
 
171
                                        i, PRIVATE_OP_FIRST, PRIVATE_OP_LAST);
 
172
                                return -EINVAL;
 
173
                        }
 
174
                        xtalk_dev->xproto.ack_statuses[i] = stat_msg;
 
175
                        DBG("private: status=0x%X (%s)\n", i, stat_msg);
 
176
                } else {
 
177
                        if(!IS_PRIVATE_OP(i)) {
 
178
                                const char      *stat_msg;
 
179
 
 
180
                                xtalk_dev->xproto.ack_statuses[i] = xtalk_base.ack_statuses[i];
 
181
                                stat_msg = xtalk_dev->xproto.ack_statuses[i];
 
182
                                if(stat_msg)
 
183
                                        DBG("global: status=0x%X (%s)\n", i, stat_msg);
 
184
                        }
 
185
                }
 
186
        }
 
187
        xtalk_dev->xproto.name = protoname;
 
188
        xtalk_dev->xproto.proto_version = (xproto) ? xproto->proto_version : 0;
 
189
        return 0;
 
190
}
 
191
 
 
192
struct xtalk_command *new_command(
 
193
        const struct xtalk_device *xtalk_dev,
 
194
        uint8_t op, uint16_t extra_data)
 
195
{
 
196
        const struct xtalk_protocol     *xproto;
 
197
        struct xtalk_command            *cmd;
 
198
        const struct xtalk_command_desc *desc;
 
199
        uint16_t                        len;
 
200
 
 
201
        xproto = &xtalk_dev->xproto;
 
202
        desc = get_command_desc(xproto, op);
 
203
        if(!desc) {
 
204
                ERR("Unknown op=0x%X.\n", op);
 
205
                return NULL;
 
206
        }
 
207
        DBG("OP=0x%X [%s] (extra_data %d)\n", op, desc->name, extra_data);
 
208
        len = desc->len + extra_data;
 
209
        if((cmd = malloc(len)) == NULL) {
 
210
                ERR("Out of memory\n");
 
211
                return NULL;
 
212
        }
 
213
        if(extra_data) {
 
214
                uint8_t *ptr = (uint8_t *)cmd;
 
215
 
 
216
                DBG("clear extra_data (%d bytes)\n", extra_data);
 
217
                memset(ptr + desc->len, 0, extra_data);
 
218
        }
 
219
        cmd->header.op = op;
 
220
        cmd->header.len = len;
 
221
        cmd->header.seq = 0;    /* Overwritten in send_usb() */
 
222
        return cmd;
 
223
}
 
224
 
 
225
void xtalk_dump_command(struct xtalk_command *cmd)
 
226
{
 
227
        uint16_t        len;
 
228
        int             i;
 
229
 
 
230
        len = cmd->header.len;
 
231
        if(len < sizeof(struct xtalk_header)) {
 
232
                ERR("Command too short (%d)\n", len);
 
233
                return;
 
234
        }
 
235
        INFO("DUMP: OP=0x%X len=%d seq=%d\n",
 
236
                cmd->header.op, cmd->header.len, cmd->header.seq);
 
237
        for(i = 0; i < len - sizeof(struct xtalk_header); i++) {
 
238
                INFO("  %2d. 0x%X\n", i, cmd->alt.raw_data[i]);
 
239
        }
 
240
}
 
241
 
 
242
static int send_command(struct xtalk_device *xtalk_dev, struct xtalk_command *cmd, int timeout)
 
243
{
 
244
        int             ret;
 
245
        int             len;
 
246
        char            *buf;
 
247
        void            *priv = xtalk_dev->transport_priv;
 
248
 
 
249
        len = cmd->header.len;
 
250
        cmd->header.seq = xtalk_dev->tx_sequenceno;
 
251
 
 
252
        buf = (char *)cmd;
 
253
        //printf("%s: len=%d\n", __FUNCTION__, len);
 
254
#if 0
 
255
        extern  FILE    *fp;
 
256
        if(fp) {
 
257
                int     i;
 
258
 
 
259
                fprintf(fp, "%05d:", cmd->header.seq);
 
260
                for(i = 0; i < len; i++)
 
261
                        fprintf(fp, " %02X", (uint8_t)buf[i]);
 
262
                fprintf(fp, "\n");
 
263
        }
 
264
#endif
 
265
        ret = xtalk_dev->ops.send_func(priv, (char *)cmd, len, timeout);
 
266
        if(ret < 0) {
 
267
                DBG("send_func failed ret=%d\n", ret);
 
268
        }
 
269
        xtalk_dev->tx_sequenceno++;
 
270
        return ret;
 
271
}
 
272
 
 
273
static struct xtalk_command *recv_command(struct xtalk_device *xtalk_dev, int timeout)
 
274
{
 
275
        struct xtalk_command    *reply;
 
276
        void                    *priv = xtalk_dev->transport_priv;
 
277
        int                     ret;
 
278
 
 
279
        if((reply = malloc(xtalk_dev->packet_size)) == NULL) {
 
280
                ERR("Out of memory\n");
 
281
                goto err;
 
282
        }
 
283
        reply->header.len = 0;
 
284
        ret = xtalk_dev->ops.recv_func(priv, (char *)reply, xtalk_dev->packet_size, timeout);
 
285
        if(ret < 0) {
 
286
                ERR("Receive from usb failed.\n");
 
287
                goto err;
 
288
        } else if(ret == 0) {
 
289
                goto err;       /* No reply */
 
290
        }
 
291
        if(ret != reply->header.len) {
 
292
                ERR("Wrong length received: got %d bytes, but length field says %d bytes%s\n",
 
293
                                ret, reply->header.len,
 
294
                                (ret == 1)? ". Old USB firmware?": "");
 
295
                goto err;
 
296
        }
 
297
        //dump_packet(LOG_DEBUG, DBG_MASK, __FUNCTION__, (char *)reply, ret);
 
298
        return reply;
 
299
err:
 
300
        if(reply) {
 
301
                memset(reply, 0, xtalk_dev->packet_size);
 
302
                free_command(reply);
 
303
        }
 
304
        return NULL;
 
305
}
 
306
 
 
307
 
 
308
__attribute__((warn_unused_result))
 
309
int process_command(
 
310
        struct xtalk_device *xtalk_dev,
 
311
        struct xtalk_command *cmd,
 
312
        struct xtalk_command **reply_ref)
 
313
{
 
314
        const struct xtalk_protocol     *xproto;
 
315
        struct xtalk_command            *reply = NULL;
 
316
        const struct xtalk_command_desc *reply_desc;
 
317
        const struct xtalk_command_desc *expected;
 
318
        const struct xtalk_command_desc *cmd_desc;
 
319
        uint8_t                         reply_op;
 
320
        const char                      *protoname;
 
321
        int                             ret;
 
322
 
 
323
        xproto = &xtalk_dev->xproto;
 
324
        protoname = (xproto) ? xproto->name : "GLOBAL";
 
325
        if(reply_ref)
 
326
                *reply_ref = NULL;      /* So the caller knows if a reply was received */
 
327
        reply_op = cmd->header.op | XTALK_REPLY_MASK;
 
328
        cmd_desc = get_command_desc(xproto, cmd->header.op);
 
329
        expected = get_command_desc(xproto, reply_op);
 
330
        //printf("%s: len=%d\n", __FUNCTION__, cmd->header.len);
 
331
        ret = send_command(xtalk_dev, cmd, TIMEOUT);
 
332
        if(!reply_ref) {
 
333
                DBG("No reply requested\n");
 
334
                goto out;
 
335
        }
 
336
        if(ret < 0) {
 
337
                ERR("send_command failed: %d\n", ret);
 
338
                goto out;
 
339
        }
 
340
        reply = recv_command(xtalk_dev, TIMEOUT);
 
341
        if(!reply) {
 
342
                ERR("recv_command failed\n");
 
343
                ret = -EPROTO;
 
344
                goto out;
 
345
        }
 
346
        *reply_ref = reply;
 
347
        if((reply->header.op & 0x80) != 0x80) {
 
348
                ERR("Unexpected reply op=0x%02X, should have MSB set.\n", reply->header.op);
 
349
                ret = -EPROTO;
 
350
                goto out;
 
351
        }
 
352
        DBG("REPLY OP: 0x%X\n", reply->header.op);
 
353
        reply_desc = get_command_desc(xproto, reply->header.op);
 
354
        if(!reply_desc) {
 
355
                ERR("Unknown reply (proto=%s) op=0x%02X\n", protoname, reply->header.op);
 
356
                ret = -EPROTO;
 
357
                goto out;
 
358
        }
 
359
        DBG("REPLY NAME: %s\n", reply_desc->name);
 
360
        if(reply->header.op == XTALK_ACK) {
 
361
                int     status = CMD_FIELD(reply, XTALK, ACK, stat);
 
362
 
 
363
                if(expected) {
 
364
                        ERR("Expected OP=0x%02X: Got ACK(%d): %s\n",
 
365
                                reply_op, status, ack_status_msg(xproto, status));
 
366
                        ret = -EPROTO;
 
367
                        goto out;
 
368
                } else if(status != STAT_OK) {
 
369
 
 
370
                        ERR("Got ACK (for OP=0x%X [%s]): %d %s\n",
 
371
                                cmd->header.op,
 
372
                                cmd_desc->name,
 
373
                                status, ack_status_msg(xproto, status));
 
374
#if 0
 
375
                        extern  FILE    *fp;
 
376
                        if(fp) {
 
377
                                fprintf(fp, "Got ACK(%d)\n", status);
 
378
                        }
 
379
#endif
 
380
                        ret = -EPROTO;
 
381
                        goto out;
 
382
                }
 
383
                /* Good expected ACK ... */
 
384
        } else if(reply->header.op != reply_op) {
 
385
                        ERR("Expected OP=0x%02X: Got OP=0x%02X\n",
 
386
                                reply_op, reply->header.op);
 
387
                        ret = -EPROTO;
 
388
                        goto out;
 
389
        }
 
390
        if(expected && expected->len > reply->header.len) {
 
391
                        ERR("Expected len=%d: Got len=%d\n",
 
392
                                expected->len, reply->header.len);
 
393
                        ret = -EPROTO;
 
394
                        goto out;
 
395
        }
 
396
        if(cmd->header.seq != reply->header.seq) {
 
397
                        ERR("Expected seq=%d: Got seq=%d\n",
 
398
                                cmd->header.seq, reply->header.seq);
 
399
                        ret = -EPROTO;
 
400
                        goto out;
 
401
        }
 
402
        ret = reply->header.len;        /* All good, return the length */
 
403
        DBG("returning reply op 0x%X (%d bytes)\n", reply->header.op, ret);
 
404
out:
 
405
        free_command(cmd);
 
406
        if(!reply_ref && reply)
 
407
                free_command(reply);
 
408
        return ret;
 
409
}
 
410
 
 
411
/*
 
412
 * Protocol Commands
 
413
 */
 
414
 
 
415
int xtalk_proto_query(struct xtalk_device *xtalk_dev)
 
416
{
 
417
        struct xtalk_command            *cmd;
 
418
        struct xtalk_command            *reply;
 
419
        uint8_t                         proto_version;
 
420
        int                             ret;
 
421
 
 
422
        DBG("\n");
 
423
        assert(xtalk_dev != NULL);
 
424
        proto_version = xtalk_dev->xproto.proto_version;
 
425
        if((cmd = new_command(xtalk_dev, XTALK_PROTO_GET, 0)) == NULL) {
 
426
                ERR("new_command failed\n");
 
427
                return -ENOMEM;
 
428
        }
 
429
        CMD_FIELD(cmd, XTALK, PROTO_GET, proto_version) = proto_version;        /* Protocol Version */
 
430
        ret = process_command(xtalk_dev, cmd, &reply);
 
431
        if(ret < 0) {
 
432
                ERR("process_command failed: %d\n", ret);
 
433
                goto out;
 
434
        }
 
435
        xtalk_dev->xtalk_proto_version = CMD_FIELD(reply, XTALK, PROTO_GET_REPLY, proto_version);
 
436
        if(xtalk_dev->xtalk_proto_version != proto_version) {
 
437
                ERR("Got %s protocol version: 0x%02x (expected 0x%02x)\n",
 
438
                        xtalk_dev->xproto.name,
 
439
                        xtalk_dev->xtalk_proto_version,
 
440
                        proto_version);
 
441
                ret = xtalk_dev->xtalk_proto_version;
 
442
                goto out;
 
443
        }
 
444
        DBG("Protocol version: %02x\n", xtalk_dev->xtalk_proto_version);
 
445
        ret = xtalk_dev->xtalk_proto_version;
 
446
out:
 
447
        free_command(reply);
 
448
        return ret;
 
449
}
 
450
 
 
451
/*
 
452
 * Wrappers
 
453
 */
 
454
 
 
455
struct xtalk_device *xtalk_new(const struct xtalk_ops *ops, size_t packet_size, void *priv)
 
456
{
 
457
        struct xtalk_device     *xtalk_dev;
 
458
        int                     ret;
 
459
 
 
460
        DBG("\n");
 
461
        assert(ops != NULL);
 
462
        if((xtalk_dev = malloc(sizeof(*xtalk_dev))) == NULL) {
 
463
                ERR("Allocating XTALK device memory failed\n");
 
464
                return NULL;
 
465
        }
 
466
        memset(xtalk_dev, 0, sizeof(*xtalk_dev));
 
467
        memcpy((void *)&xtalk_dev->ops, (const void *)ops, sizeof(xtalk_dev->ops));
 
468
        xtalk_dev->transport_priv = priv;
 
469
        xtalk_dev->packet_size = packet_size;
 
470
        xtalk_dev->tx_sequenceno = 1;
 
471
        ret = xtalk_set_protocol(xtalk_dev, NULL);
 
472
        if(ret < 0) {
 
473
                ERR("GLOBAL Protocol registration failed: %d\n", ret);
 
474
                goto err;
 
475
        }
 
476
        return xtalk_dev;
 
477
 
 
478
err:
 
479
        if (xtalk_dev)
 
480
                xtalk_delete(xtalk_dev);
 
481
        return NULL;
 
482
}
 
483
 
 
484
void xtalk_delete(struct xtalk_device *xtalk_dev)
 
485
{
 
486
        void    *priv;
 
487
 
 
488
        if(!xtalk_dev)
 
489
                return;
 
490
        DBG("\n");
 
491
        priv = xtalk_dev->transport_priv;
 
492
        assert(priv);
 
493
        xtalk_dev->tx_sequenceno = 0;
 
494
        assert(&xtalk_dev->ops != NULL);
 
495
        assert(&xtalk_dev->ops.close_func != NULL);
 
496
        xtalk_dev->ops.close_func(priv);
 
497
}