~ubuntu-branches/ubuntu/quantal/zaptel/quantal

« back to all changes in this revision

Viewing changes to kernel/xpp/utils/fpga_load.c

  • Committer: Bazaar Package Importer
  • Author(s): Tzafrir Cohen
  • Date: 2008-08-28 22:58:23 UTC
  • mfrom: (11.1.11 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080828225823-r8bdunirm8hmc76m
Tags: 1:1.4.11~dfsg-2
* Patch xpp_fxs_power: Fixed an issue with hook detection of the Astribank
  FXS module.
* Don't fail init.d script if fxotune fails. This may happen if running it
  when Asterisk is already running.
* Bump standards version to 3.8.0.0 .
* Ignore false lintian warning ("m-a a-i" has "a a").
* Patch xpp_fxo_cid_always: do always pass PCM if that's what the user
  asked.
* Patch vzaphfc_proc_root_dir: fix vzaphfc on 2.6.26.
* Patch wcte12xp_flags: Proper time for irq save flags.
* Patch headers_2627: Fix location of semaphore.h for 2.6.27 .
* Patch xpp_fxs_dtmf_leak: Don't play DTMFs to the wrong channel.
* Patch wctdm_fix_alarm: Fix sending channel alarms.
* Patch device_class_2626: Fix building 2.6.26 (Closes: #493397).
* Using dh_lintian for lintian overrides, hence requiring debhelper 6.0.7.
* Lintian: we know we have direct changes. Too bad we're half-upstream :-(
* Fix doc-base section names. 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <stdio.h>
 
2
#include <assert.h>
 
3
#include <string.h>
 
4
#include <stdint.h>
 
5
#include <errno.h>
 
6
#include <sys/types.h>
 
7
#include <sys/param.h>
 
8
#include <usb.h>
 
9
#include "hexfile.h"
 
10
 
 
11
static const char rcsid[] = "$Id: fpga_load.c 4266 2008-05-13 21:08:09Z tzafrir $";
 
12
 
 
13
#define ERR(fmt, arg...) do { \
 
14
                                if(verbose >= LOG_ERR) \
 
15
                                        fprintf(stderr, "%s: ERROR (%d): " fmt, \
 
16
                                                progname, __LINE__, ## arg); \
 
17
                        } while(0);
 
18
#define INFO(fmt, arg...) do { \
 
19
                                if(verbose >= LOG_INFO) \
 
20
                                        fprintf(stderr, "%s: " fmt, \
 
21
                                                progname, ## arg); \
 
22
                        } while(0);
 
23
#define DBG(fmt, arg...) do { \
 
24
                                if(verbose >= LOG_DEBUG) \
 
25
                                        fprintf(stderr, "%s: DBG: " fmt, \
 
26
                                                progname, ## arg); \
 
27
                        } while(0);
 
28
 
 
29
static int      verbose = LOG_WARNING;
 
30
static char     *progname;
 
31
static int      disconnected = 0;
 
32
 
 
33
#define MAX_HEX_LINES   10000
 
34
#define PACKET_SIZE     512
 
35
#define EEPROM_SIZE     16
 
36
#define LABEL_SIZE      8
 
37
#define TIMEOUT         5000
 
38
 
 
39
 
 
40
/* My device parameters */
 
41
#define MY_EP_OUT       0x04
 
42
#define MY_EP_IN        0x88
 
43
 
 
44
#define FPGA_EP_OUT     0x02
 
45
#define FPGA_EP_IN      0x86
 
46
 
 
47
/* USB firmware types */
 
48
#define USB_11xx        0
 
49
#define USB_FIRMWARE_II 1
 
50
 
 
51
#define TYPE_ENTRY(t,ni,n,ne,out,in,...)        \
 
52
        [t] = {                                 \
 
53
                .type_code = (t),               \
 
54
                .num_interfaces = (ni),         \
 
55
                .my_interface_num = (n),        \
 
56
                .num_endpoints = (ne),          \
 
57
                .my_ep_in = (in),               \
 
58
                .my_ep_out = (out),             \
 
59
                .name = #t,                     \
 
60
                .endpoints = { __VA_ARGS__ },   \
 
61
                }
 
62
 
 
63
static const struct astribank_type {
 
64
        int     type_code;
 
65
        int     num_interfaces;
 
66
        int     my_interface_num;
 
67
        int     num_endpoints;
 
68
        int     my_ep_out;
 
69
        int     my_ep_in;
 
70
        char    *name;
 
71
        int     endpoints[4];   /* for matching */
 
72
} astribank_types[] = {
 
73
        TYPE_ENTRY(USB_11xx,            1, 0, 4, MY_EP_OUT, MY_EP_IN,
 
74
                FPGA_EP_OUT,
 
75
                MY_EP_OUT,
 
76
                FPGA_EP_IN,
 
77
                MY_EP_IN),
 
78
        TYPE_ENTRY(USB_FIRMWARE_II,     2, 1, 2, MY_EP_OUT, MY_EP_IN,
 
79
                MY_EP_OUT,
 
80
                MY_EP_IN),
 
81
};
 
82
#undef TYPE_ENTRY
 
83
 
 
84
enum fpga_load_packet_types {
 
85
        PT_STATUS_REPLY = 0x01,
 
86
        PT_DATA_PACKET  = 0x01,
 
87
#ifdef  XORCOM_INTERNAL
 
88
        PT_EEPROM_SET   = 0x04,
 
89
#endif
 
90
        PT_EEPROM_GET   = 0x08,
 
91
        PT_RENUMERATE   = 0x10,
 
92
        PT_RESET        = 0x20,
 
93
        PT_BAD_COMMAND  = 0xAA
 
94
};
 
95
 
 
96
struct myeeprom {
 
97
        uint8_t         source;
 
98
        uint16_t        vendor;
 
99
        uint16_t        product;
 
100
        uint8_t         release_major;
 
101
        uint8_t         release_minor;
 
102
        uint8_t         reserved;
 
103
        uint8_t         label[LABEL_SIZE];
 
104
} PACKED;
 
105
 
 
106
struct fpga_packet_header {
 
107
        struct {
 
108
                uint8_t         op;
 
109
        } PACKED header;
 
110
        union {
 
111
                struct {
 
112
                        uint16_t        seq;
 
113
                        uint8_t         status;
 
114
                } PACKED status_reply;
 
115
                struct {
 
116
                        uint16_t        seq;
 
117
                        uint8_t         reserved;
 
118
                        uint8_t         data[ZERO_SIZE];
 
119
                } PACKED data_packet;
 
120
                struct {
 
121
                        struct myeeprom         data;
 
122
                } PACKED eeprom_set;
 
123
                struct {
 
124
                        struct myeeprom         data;
 
125
                } PACKED eeprom_get;
 
126
        } d;
 
127
} PACKED;
 
128
 
 
129
enum fpga_load_status {
 
130
        FW_FAIL_RESET   = 1,
 
131
        FW_FAIL_TRANS   = 2,
 
132
        FW_TRANS_OK     = 4,
 
133
        FW_CONFIG_DONE  = 8
 
134
};
 
135
 
 
136
struct my_usb_device {
 
137
        struct usb_device       *dev;
 
138
        usb_dev_handle          *handle;
 
139
        int                     my_interface_num;
 
140
        int                     my_ep_out;
 
141
        int                     my_ep_in;
 
142
        char                    iManufacturer[BUFSIZ];
 
143
        char                    iProduct[BUFSIZ];
 
144
        char                    iSerialNumber[BUFSIZ];
 
145
        char                    iInterface[BUFSIZ];
 
146
        int                     is_usb2;
 
147
        struct myeeprom         eeprom;
 
148
        const struct astribank_type     *abtype;
 
149
};
 
150
 
 
151
const char *load_status2str(enum fpga_load_status s)
 
152
{
 
153
        switch(s) {
 
154
                case FW_FAIL_RESET: return "FW_FAIL_RESET";
 
155
                case FW_FAIL_TRANS: return "FW_FAIL_TRANS";
 
156
                case FW_TRANS_OK: return "FW_TRANS_OK";
 
157
                case FW_CONFIG_DONE: return "FW_CONFIG_DONE";
 
158
                default: return "UNKNOWN";
 
159
        }
 
160
}
 
161
 
 
162
/* return 1 if:
 
163
 * - str has a number
 
164
 * - It is larger than 0
 
165
 * - It equals num
 
166
 */
 
167
int num_matches(int num, const char* str) {
 
168
        int str_val = atoi(str);
 
169
        if (str_val <= 0)
 
170
                return 0;
 
171
        return (str_val == num);
 
172
}
 
173
 
 
174
struct usb_device *dev_of_path(const char *path)
 
175
{
 
176
        struct usb_bus          *bus;
 
177
        struct usb_device       *dev;
 
178
        char                    dirname[PATH_MAX];
 
179
        char                    filename[PATH_MAX];
 
180
        const char              *p;
 
181
        int                     bnum;
 
182
        int                     dnum;
 
183
        int                     ret;
 
184
 
 
185
        assert(path != NULL);
 
186
        if(access(path, F_OK) < 0) {
 
187
                perror(path);
 
188
                return NULL;
 
189
        }
 
190
        /* Find last '/' */
 
191
        if((p = memrchr(path, '/', strlen(path))) == NULL) {
 
192
                ERR("Missing a '/' in %s\n", path);
 
193
                return NULL;
 
194
        }
 
195
        /* Get the device number */
 
196
        ret = sscanf(p + 1, "%d", &dnum);
 
197
        if(ret != 1) {
 
198
                ERR("Path tail is not a device number: '%s'\n", p);
 
199
                return NULL;
 
200
        }
 
201
        /* Search for a '/' before that */
 
202
        p = memrchr(path, '/', p - path);
 
203
        if(p == NULL)
 
204
                p = path;               /* Relative path */
 
205
        else
 
206
                p++;                    /* skip '/' */
 
207
        /* Get the bus number */
 
208
        ret = sscanf(p, "%d", &bnum);
 
209
        if(ret != 1) {
 
210
                ERR("Path tail is not a bus number: '%s'\n", p);
 
211
                return NULL;
 
212
        }
 
213
        sprintf(dirname, "%03d", bnum);
 
214
        sprintf(filename, "%03d", dnum);
 
215
        for (bus = usb_busses; bus; bus = bus->next) {
 
216
                if (! num_matches(bnum, bus->dirname))
 
217
                //if(strcmp(bus->dirname, dirname) != 0)
 
218
                        continue;
 
219
                for (dev = bus->devices; dev; dev = dev->next) {
 
220
                        //if(strcmp(dev->filename, filename) == 0)
 
221
                        if (num_matches(dnum, dev->filename))
 
222
                                return dev;
 
223
                }
 
224
        }
 
225
        ERR("no usb device match '%s'\n", path);
 
226
        return NULL;
 
227
}
 
228
 
 
229
int get_usb_string(char *buf, unsigned int len, uint16_t item, usb_dev_handle *handle)
 
230
{
 
231
        char    tmp[BUFSIZ];
 
232
        int     ret;
 
233
 
 
234
        if (!item)
 
235
                return 0;
 
236
        ret = usb_get_string_simple(handle, item, tmp, BUFSIZ);
 
237
        if (ret <= 0)
 
238
                return ret;
 
239
        return snprintf(buf, len, "%s", tmp);
 
240
}
 
241
 
 
242
void my_usb_device_cleanup(struct my_usb_device *mydev)
 
243
{
 
244
        assert(mydev != NULL);
 
245
        if(!mydev->handle) {
 
246
                return; /* Nothing to do */
 
247
        }
 
248
        if(!disconnected) {
 
249
                if(usb_release_interface(mydev->handle, mydev->abtype->my_interface_num) != 0) {
 
250
                        ERR("Releasing interface: usb: %s\n", usb_strerror());
 
251
                }
 
252
        }
 
253
        if(usb_close(mydev->handle) != 0) {
 
254
                ERR("Closing device: usb: %s\n", usb_strerror());
 
255
        }
 
256
        disconnected = 1;
 
257
        mydev->handle = NULL;
 
258
}
 
259
 
 
260
static void show_device_info(const struct my_usb_device *mydev)
 
261
{
 
262
        const struct myeeprom   *eeprom;
 
263
        uint8_t         data[LABEL_SIZE + 1];
 
264
 
 
265
        assert(mydev != NULL);
 
266
        eeprom = &mydev->eeprom;
 
267
        memset(data, 0, LABEL_SIZE + 1);
 
268
        memcpy(data, eeprom->label, LABEL_SIZE);
 
269
        printf("USB    Firmware Type: [%s]\n", mydev->abtype->name);
 
270
        printf("USB    iManufacturer: [%s]\n", mydev->iManufacturer);
 
271
        printf("USB    iProduct:      [%s]\n", mydev->iProduct);
 
272
        printf("USB    iSerialNumber: [%s]\n", mydev->iSerialNumber);
 
273
        printf("EEPROM Source:        0x%02X\n", eeprom->source);
 
274
        printf("EEPROM Vendor:        0x%04X\n", eeprom->vendor);
 
275
        printf("EEPROM Product:       0x%04X\n", eeprom->product);
 
276
        printf("EEPROM Release:       %d.%03d\n", eeprom->release_major, eeprom->release_minor);
 
277
        printf("EEPROM Label:        HEX(%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X) [%s]\n",
 
278
                        data[0], data[1], data[2], data[3],
 
279
                        data[4], data[5], data[6], data[7], data); 
 
280
}
 
281
 
 
282
void dump_packet(const char *msg, const char *buf, int len)
 
283
{
 
284
        int     i;
 
285
 
 
286
        for(i = 0; i < len; i++)
 
287
                INFO("%s: %2d> 0x%02X\n", msg, i, (uint8_t)buf[i]);
 
288
}
 
289
 
 
290
int send_usb(const char *msg, struct my_usb_device *mydev, struct fpga_packet_header *phead, int len, int timeout)
 
291
{
 
292
        char    *p = (char *)phead;
 
293
        int     ret;
 
294
 
 
295
        if(verbose >= LOG_DEBUG)
 
296
                dump_packet(msg, p, len);
 
297
        if(mydev->my_ep_out & USB_ENDPOINT_IN) {
 
298
                ERR("send_usb called with an input endpoint 0x%x\n", mydev->my_ep_out);
 
299
                return -EINVAL;
 
300
        }
 
301
        ret = usb_bulk_write(mydev->handle, mydev->my_ep_out, p, len, timeout);
 
302
        if(ret < 0) {
 
303
                /*
 
304
                 * If the device was gone, it may be the
 
305
                 * result of renumeration. Ignore it.
 
306
                 */
 
307
                if(ret != -ENODEV) {
 
308
                        ERR("bulk_write to endpoint 0x%x failed: %s\n", mydev->my_ep_out, usb_strerror());
 
309
                        dump_packet("send_usb[ERR]", p, len);
 
310
                } else {
 
311
                        disconnected = 1;
 
312
                        my_usb_device_cleanup(mydev);
 
313
                }
 
314
                return ret;
 
315
        } else if(ret != len) {
 
316
                ERR("bulk_write to endpoint 0x%x short write: %s\n", mydev->my_ep_out, usb_strerror());
 
317
                dump_packet("send_usb[ERR]", p, len);
 
318
                return -EFAULT;
 
319
        }
 
320
        return ret;
 
321
}
 
322
 
 
323
int recv_usb(const char *msg, struct my_usb_device *mydev, char *buf, size_t len, int timeout)
 
324
{
 
325
        int     ret;
 
326
 
 
327
        if(mydev->my_ep_in & USB_ENDPOINT_OUT) {
 
328
                ERR("recv_usb called with an output endpoint 0x%x\n", mydev->my_ep_in);
 
329
                return -EINVAL;
 
330
        }
 
331
        ret = usb_bulk_read(mydev->handle, mydev->my_ep_in, buf, len, timeout);
 
332
        if(ret < 0) {
 
333
                ERR("bulk_read from endpoint 0x%x failed: %s\n", mydev->my_ep_in, usb_strerror());
 
334
                return ret;
 
335
        }
 
336
        if(verbose >= LOG_DEBUG)
 
337
                dump_packet(msg, buf, ret);
 
338
        return ret;
 
339
}
 
340
 
 
341
#ifdef  XORCOM_INTERNAL
 
342
int eeprom_set(struct my_usb_device *mydev, const struct myeeprom *eeprom)
 
343
{
 
344
        int                             ret;
 
345
        int                             len;
 
346
        char                            buf[PACKET_SIZE];
 
347
        struct fpga_packet_header       *phead = (struct fpga_packet_header *)buf;
 
348
 
 
349
        DBG("%s Start...\n", __FUNCTION__);
 
350
        assert(mydev != NULL);
 
351
        phead->header.op = PT_EEPROM_SET;
 
352
        memcpy(&phead->d.eeprom_set.data, eeprom, EEPROM_SIZE);
 
353
        len = sizeof(phead->d.eeprom_set) + sizeof(phead->header.op);
 
354
        ret = send_usb("eeprom_set[W]", mydev, phead, len, TIMEOUT);
 
355
        if(ret < 0)
 
356
                return ret;
 
357
        ret = recv_usb("eeprom_set[R]", mydev, buf, sizeof(buf), TIMEOUT);
 
358
        if(ret <= 0)
 
359
                return ret;
 
360
        phead = (struct fpga_packet_header *)buf;
 
361
        if(phead->header.op == PT_BAD_COMMAND) {
 
362
                ERR("Firmware rejected PT_EEPROM_SET command\n");
 
363
                return -EINVAL;
 
364
        } else if(phead->header.op != PT_EEPROM_SET) {
 
365
                ERR("Got unexpected reply op=%d\n", phead->header.op);
 
366
                return -EINVAL;
 
367
        }
 
368
        return 0;
 
369
}
 
370
#endif
 
371
 
 
372
int eeprom_get(struct my_usb_device *mydev)
 
373
{
 
374
        int                             ret;
 
375
        int                             len;
 
376
        char                            buf[PACKET_SIZE];
 
377
        struct fpga_packet_header       *phead = (struct fpga_packet_header *)buf;
 
378
        struct myeeprom                 *eeprom;
 
379
 
 
380
        assert(mydev != NULL);
 
381
        eeprom = &mydev->eeprom;
 
382
        DBG("%s Start...\n", __FUNCTION__);
 
383
        phead->header.op = PT_EEPROM_GET;
 
384
        len = sizeof(phead->header.op);         /* warning: sending small packet */
 
385
        ret = send_usb("eeprom_get[W]", mydev, phead, len, TIMEOUT);
 
386
        if(ret < 0)
 
387
                return ret;
 
388
        ret = recv_usb("eeprom_get[R]", mydev, buf, sizeof(buf), TIMEOUT);
 
389
        if(ret <= 0)
 
390
                return ret;
 
391
        phead = (struct fpga_packet_header *)buf;
 
392
        if(phead->header.op == PT_BAD_COMMAND) {
 
393
                ERR("PT_BAD_COMMAND\n");
 
394
                return -EINVAL;
 
395
        } else if(phead->header.op != PT_EEPROM_GET) {
 
396
                ERR("Got unexpected reply op=%d\n", phead->header.op);
 
397
                return -EINVAL;
 
398
        }
 
399
        memcpy(eeprom, &phead->d.eeprom_get.data, EEPROM_SIZE);
 
400
        return 0;
 
401
}
 
402
 
 
403
int send_hexline(struct my_usb_device *mydev, struct hexline *hexline, int seq)
 
404
{
 
405
        int                             ret;
 
406
        int                             len;
 
407
        uint8_t                         *data;
 
408
        char                            buf[PACKET_SIZE];
 
409
        struct fpga_packet_header       *phead = (struct fpga_packet_header *)buf;
 
410
        enum fpga_load_status           status;
 
411
 
 
412
        assert(mydev != NULL);
 
413
        assert(hexline != NULL);
 
414
        if(hexline->d.content.header.tt != TT_DATA) {
 
415
                DBG("Non data record %d type = %d\n", seq, hexline->d.content.header.tt);
 
416
                return 0;
 
417
        }
 
418
        len = hexline->d.content.header.ll;     /* don't send checksum */
 
419
        data = hexline->d.content.tt_data.data;
 
420
        phead->header.op = PT_DATA_PACKET;
 
421
        phead->d.data_packet.seq = seq;
 
422
        phead->d.data_packet.reserved = 0x00;
 
423
        memcpy(phead->d.data_packet.data, data, len);
 
424
        len += sizeof(hexline->d.content.header);
 
425
        DBG("%04d+\r", seq);
 
426
        ret = send_usb("hexline[W]", mydev, phead, len, TIMEOUT);
 
427
        if(ret < 0)
 
428
                return ret;
 
429
        ret = recv_usb("hexline[R]", mydev, buf, sizeof(buf), TIMEOUT);
 
430
        if(ret <= 0)
 
431
                return ret;
 
432
        DBG("%04d-\r", seq);
 
433
        phead = (struct fpga_packet_header *)buf;
 
434
        if(phead->header.op != PT_STATUS_REPLY) {
 
435
                ERR("Got unexpected reply op=%d\n", phead->header.op);
 
436
                dump_packet("hexline[ERR]", buf, ret);
 
437
                return -EINVAL;
 
438
        }
 
439
        status = (enum fpga_load_status)phead->d.status_reply.status;
 
440
        switch(status) {
 
441
                case FW_TRANS_OK:
 
442
                case FW_CONFIG_DONE:
 
443
                        break;
 
444
                case FW_FAIL_RESET:
 
445
                case FW_FAIL_TRANS:
 
446
                        ERR("status reply %s (%d)\n", load_status2str(status), status);
 
447
                        dump_packet("hexline[ERR]", buf, ret);
 
448
                        return -EPROTO;
 
449
                default:
 
450
                        ERR("Unknown status reply %d\n", status);
 
451
                        dump_packet("hexline[ERR]", buf, ret);
 
452
                        return -EPROTO;
 
453
        }
 
454
        return 0;
 
455
}
 
456
 
 
457
//. returns > 0 - ok, the number of lines sent
 
458
//. returns < 0 - error number
 
459
int send_splited_hexline(struct my_usb_device *mydev, struct hexline *hexline, int seq, uint8_t maxwidth)
 
460
{
 
461
        struct hexline *extraline;
 
462
        int linessent = 0;
 
463
        int allocsize;
 
464
        int extra_offset = 0;
 
465
        unsigned int this_line = 0;
 
466
        uint8_t bytesleft = 0;
 
467
        
 
468
        assert(mydev != NULL);
 
469
        if(!hexline) {
 
470
                ERR("Bad record %d type = %d\n", seq, hexline->d.content.header.tt);
 
471
                return -EINVAL;
 
472
        }
 
473
        bytesleft = hexline->d.content.header.ll;
 
474
        // split the line into several lines
 
475
        while (bytesleft > 0) {
 
476
                int status;
 
477
                this_line = (bytesleft >= maxwidth) ? maxwidth : bytesleft;
 
478
                allocsize = sizeof(struct hexline) + this_line + 1;
 
479
                // generate the new line
 
480
                if((extraline = (struct hexline *)malloc(allocsize)) == NULL) {
 
481
                        ERR("Not enough memory for spliting the lines\n" );
 
482
                        return -EINVAL;
 
483
                }
 
484
                memset(extraline, 0, allocsize);
 
485
                extraline->d.content.header.ll          = this_line;
 
486
                extraline->d.content.header.offset      = hexline->d.content.header.offset + extra_offset;
 
487
                extraline->d.content.header.tt          = hexline->d.content.header.tt;
 
488
                memcpy( extraline->d.content.tt_data.data, hexline->d.content.tt_data.data+extra_offset, this_line);
 
489
                status = send_hexline(mydev, extraline, seq+linessent );
 
490
                // cleanups
 
491
                free(extraline);
 
492
                extra_offset += this_line;
 
493
                bytesleft -= this_line;
 
494
                if (status)
 
495
                        return status;
 
496
                linessent++;
 
497
        }
 
498
        return linessent;
 
499
}
 
500
 
 
501
int match_usb_device_identity(const struct usb_config_descriptor *config_desc,
 
502
        const struct astribank_type *ab)
 
503
{
 
504
        struct usb_interface            *interface;
 
505
        struct usb_interface_descriptor *iface_desc;
 
506
 
 
507
        if(config_desc->bNumInterfaces <= ab->my_interface_num)
 
508
                return 0;
 
509
        interface = &config_desc->interface[ab->my_interface_num];
 
510
        iface_desc = interface->altsetting;
 
511
        
 
512
        return  iface_desc->bInterfaceClass == 0xFF &&
 
513
                iface_desc->bInterfaceNumber == ab->my_interface_num &&
 
514
                iface_desc->bNumEndpoints == ab->num_endpoints;
 
515
}
 
516
 
 
517
const struct astribank_type *my_usb_device_identify(const char devpath[], struct my_usb_device *mydev)
 
518
{
 
519
        struct usb_device_descriptor    *dev_desc;
 
520
        struct usb_config_descriptor    *config_desc;
 
521
        int                             i;
 
522
 
 
523
        assert(mydev != NULL);
 
524
        usb_init();
 
525
        usb_find_busses();
 
526
        usb_find_devices();
 
527
        mydev->dev = dev_of_path(devpath);
 
528
        if(!mydev->dev) {
 
529
                ERR("Bailing out\n");
 
530
                return 0;
 
531
        }
 
532
        dev_desc = &mydev->dev->descriptor;
 
533
        config_desc = mydev->dev->config;
 
534
        for(i = 0; i < sizeof(astribank_types)/sizeof(astribank_types[0]); i++) {
 
535
                if(match_usb_device_identity(config_desc, &astribank_types[i])) {
 
536
                        DBG("Identified[%d]: interfaces=%d endpoints=%d: \"%s\"\n",
 
537
                                i,
 
538
                                astribank_types[i].num_interfaces,
 
539
                                astribank_types[i].num_endpoints,
 
540
                                astribank_types[i].name);
 
541
                        return &astribank_types[i];
 
542
                }
 
543
        }
 
544
        return NULL;
 
545
}
 
546
 
 
547
int my_usb_device_init(const char devpath[], struct my_usb_device *mydev, const struct astribank_type *abtype)
 
548
{
 
549
        struct usb_device_descriptor    *dev_desc;
 
550
        struct usb_config_descriptor    *config_desc;
 
551
        struct usb_interface            *interface;
 
552
        struct usb_interface_descriptor *iface_desc;
 
553
        struct usb_endpoint_descriptor  *endpoint;
 
554
        int                             ret;
 
555
        int                             i;
 
556
 
 
557
        assert(mydev != NULL);
 
558
        usb_init();
 
559
        usb_find_busses();
 
560
        usb_find_devices();
 
561
        mydev->dev = dev_of_path(devpath);
 
562
        if(!mydev->dev) {
 
563
                ERR("Bailing out\n");
 
564
                return 0;
 
565
        }
 
566
        mydev->handle = usb_open(mydev->dev);
 
567
        if(!mydev->handle) {
 
568
                ERR("Failed to open usb device '%s/%s': %s\n", mydev->dev->bus->dirname, mydev->dev->filename, usb_strerror());
 
569
                return 0;
 
570
        }
 
571
        if(usb_claim_interface(mydev->handle, abtype->my_interface_num) != 0) {
 
572
                ERR("usb_claim_interface: %s\n", usb_strerror());
 
573
                return 0;
 
574
        }
 
575
        dev_desc = &mydev->dev->descriptor;
 
576
        config_desc = mydev->dev->config;
 
577
        if (!config_desc) {
 
578
                ERR("usb interface without a configuration\n");
 
579
                return 0;
 
580
        }
 
581
        interface = &config_desc->interface[abtype->my_interface_num];
 
582
        iface_desc = interface->altsetting;
 
583
        endpoint = iface_desc->endpoint;
 
584
        mydev->is_usb2 = (endpoint->wMaxPacketSize == 512);
 
585
        for(i = 0; i < iface_desc->bNumEndpoints; i++, endpoint++) {
 
586
                if(endpoint->bEndpointAddress != abtype->endpoints[i]) {
 
587
                        ERR("Wrong endpoint 0x%X (at index %d)\n", endpoint->bEndpointAddress, i);
 
588
                        return 0;
 
589
                }
 
590
                if(endpoint->bEndpointAddress == MY_EP_OUT || endpoint->bEndpointAddress == MY_EP_IN) {
 
591
                        if(endpoint->wMaxPacketSize > PACKET_SIZE) {
 
592
                                ERR("Endpoint #%d wMaxPacketSize too large (%d)\n", i, endpoint->wMaxPacketSize);
 
593
                                return 0;
 
594
                        }
 
595
                }
 
596
        }
 
597
        mydev->abtype = abtype;
 
598
        mydev->my_ep_in = abtype->my_ep_in;
 
599
        mydev->my_ep_out = abtype->my_ep_out;
 
600
        ret = get_usb_string(mydev->iManufacturer, BUFSIZ, dev_desc->iManufacturer, mydev->handle);
 
601
        ret = get_usb_string(mydev->iProduct, BUFSIZ, dev_desc->iProduct, mydev->handle);
 
602
        ret = get_usb_string(mydev->iSerialNumber, BUFSIZ, dev_desc->iSerialNumber, mydev->handle);
 
603
        ret = get_usb_string(mydev->iInterface, BUFSIZ, iface_desc->iInterface, mydev->handle);
 
604
        INFO("ID=%04X:%04X Manufacturer=[%s] Product=[%s] SerialNumber=[%s] Interface=[%s]\n",
 
605
                dev_desc->idVendor,
 
606
                dev_desc->idProduct,
 
607
                mydev->iManufacturer,
 
608
                mydev->iProduct,
 
609
                mydev->iSerialNumber,
 
610
                mydev->iInterface);
 
611
        if(usb_clear_halt(mydev->handle, mydev->my_ep_out) != 0) {
 
612
                ERR("Clearing output endpoint: %s\n", usb_strerror());
 
613
                return 0;
 
614
        }
 
615
        if(usb_clear_halt(mydev->handle, mydev->my_ep_in) != 0) {
 
616
                ERR("Clearing input endpoint: %s\n", usb_strerror());
 
617
                return 0;
 
618
        }
 
619
        return 1;
 
620
}
 
621
 
 
622
int renumerate_device(struct my_usb_device *mydev, enum fpga_load_packet_types pt)
 
623
{
 
624
        char                            buf[PACKET_SIZE];
 
625
        struct fpga_packet_header       *phead = (struct fpga_packet_header *)buf;
 
626
        int                             ret;
 
627
 
 
628
        assert(mydev != NULL);
 
629
        DBG("Renumerating with 0x%X\n", pt);
 
630
        phead->header.op = pt;
 
631
        ret = send_usb("renumerate[W]", mydev, phead, 1, TIMEOUT);
 
632
        if(ret < 0 && ret != -ENODEV)
 
633
                        return ret;
 
634
#if 0
 
635
        /*
 
636
         * FIXME: we count on our USB firmware to reset the device... should we?
 
637
         */
 
638
        ret = usb_reset(mydev->handle);
 
639
        if(ret < 0) {
 
640
                ERR("usb_reset: %s\n", usb_strerror());
 
641
                return -ENODEV;
 
642
        }
 
643
#endif
 
644
        return 0;
 
645
}
 
646
 
 
647
/*
 
648
 * Returns: true on success, false on failure
 
649
 */
 
650
int fpga_load(struct my_usb_device *mydev, const struct hexdata *hexdata)
 
651
{
 
652
        unsigned int    i;
 
653
        unsigned int    j = 0;
 
654
        int             ret;
 
655
        int             finished = 0;
 
656
        const char      *v = hexdata->version_info;
 
657
        
 
658
        v = (v[0]) ? v : "Unknown";
 
659
        assert(mydev != NULL);
 
660
        INFO("FPGA_LOAD (version %s)\n", v);
 
661
        /*
 
662
         * i - is the line number
 
663
         * j - is the sequence number, on USB 2, i=j, but on
 
664
         *     USB 1 send_splited_hexline may increase the sequence
 
665
         *     number, as it needs 
 
666
         */
 
667
        for(i = 0; i < hexdata->maxlines; i++) {
 
668
                struct hexline  *hexline = hexdata->lines[i];
 
669
 
 
670
                if(!hexline)
 
671
                        break;
 
672
                if(finished) {
 
673
                        ERR("Extra data after End Of Data Record (line %d)\n", i);
 
674
                        return 0;
 
675
                }
 
676
                if(hexline->d.content.header.tt == TT_EOF) {
 
677
                        DBG("End of data\n");
 
678
                        finished = 1;
 
679
                        continue;
 
680
                }
 
681
                if(mydev->is_usb2) {
 
682
                        if((ret = send_hexline(mydev, hexline, i)) != 0) {
 
683
                                perror("Failed sending hexline");
 
684
                                return 0;
 
685
                        }
 
686
                } else {
 
687
                        if((ret = send_splited_hexline(mydev, hexline, j, 60)) < 0) {
 
688
                                perror("Failed sending hexline (splitting did not help)");
 
689
                                return 0;
 
690
                        }
 
691
                        j += ret;
 
692
                }
 
693
        }
 
694
        DBG("Finished...\n");
 
695
        return 1;
 
696
}
 
697
 
 
698
#include <getopt.h>
 
699
 
 
700
void usage()
 
701
{
 
702
        fprintf(stderr, "Usage: %s -D {/proc/bus/usb|/dev/bus/usb}/<bus>/<dev> [options...]\n", progname);
 
703
        fprintf(stderr, "\tOptions:\n");
 
704
        fprintf(stderr, "\t\t[-r]               # Reset the device\n");
 
705
        fprintf(stderr, "\t\t[-b <binfile>]     # Output to <binfile>\n");
 
706
        fprintf(stderr, "\t\t[-I <hexfile>]     # Input from <hexfile>\n");
 
707
        fprintf(stderr, "\t\t[-H <hexfile>]     # Output to <hexfile> ('-' is stdout)\n");
 
708
        fprintf(stderr, "\t\t[-i]               # Show hexfile information\n");
 
709
        fprintf(stderr, "\t\t[-g]               # Get eeprom from device\n");
 
710
        fprintf(stderr, "\t\t[-v]               # Increase verbosity\n");
 
711
#ifdef XORCOM_INTERNAL
 
712
        fprintf(stderr, "\t\t[-C srC byte]      # Set Address sourCe (default: C0)\n");
 
713
        fprintf(stderr, "\t\t[-V vendorid]      # Set Vendor id on device\n");
 
714
        fprintf(stderr, "\t\t[-P productid]     # Set Product id on device\n");
 
715
        fprintf(stderr, "\t\t[-R release]       # Set Release. 2 dot separated decimals\n");
 
716
        fprintf(stderr, "\t\t[-L label]         # Set label.\n");
 
717
#endif
 
718
        exit(1);
 
719
}
 
720
 
 
721
static void parse_report_func(int level, const char *msg, ...)
 
722
{
 
723
        va_list ap;
 
724
 
 
725
        va_start(ap, msg);
 
726
        if(level <= verbose)
 
727
                vfprintf(stderr, msg, ap);
 
728
        va_end(ap);
 
729
}
 
730
 
 
731
#ifdef  XORCOM_INTERNAL
 
732
static void eeprom_fill(struct myeeprom *myeeprom,
 
733
        const char vendor[],
 
734
        const char product[],
 
735
        const char release[],
 
736
        const char label[],
 
737
        const char source[])
 
738
{
 
739
        // FF: address source is from device. C0: from eeprom
 
740
        if (source)
 
741
                myeeprom->source = strtoul(source, NULL, 0);
 
742
        else
 
743
                myeeprom->source = 0xC0;
 
744
        if(vendor)
 
745
                myeeprom->vendor = strtoul(vendor, NULL, 0);
 
746
        if(product)
 
747
                myeeprom->product = strtoul(product, NULL, 0);
 
748
        if(release) {
 
749
                int     release_major = 0;
 
750
                int     release_minor = 0;
 
751
 
 
752
                sscanf(release, "%d.%d", &release_major, &release_minor);
 
753
                myeeprom->release_major = release_major;
 
754
                myeeprom->release_minor = release_minor;
 
755
        }
 
756
        if(label) {
 
757
                /* padding */
 
758
                memset(myeeprom->label, 0, LABEL_SIZE);
 
759
                memcpy(myeeprom->label, label, strlen(label));
 
760
        }
 
761
}
 
762
#endif
 
763
 
 
764
int main(int argc, char *argv[])
 
765
{
 
766
        const struct astribank_type     *abtype;
 
767
        struct my_usb_device    mydev;
 
768
        const char              *devpath = NULL;
 
769
        const char              *binfile = NULL;
 
770
        const char              *inhexfile = NULL;
 
771
        const char              *outhexfile = NULL;
 
772
        struct hexdata          *hexdata = NULL;
 
773
        int                     opt_reset = 0;
 
774
        int                     opt_info = 0;
 
775
        int                     opt_read_eeprom = 0;
 
776
        int                     opt_output_width = 0;
 
777
        int                     output_is_set = 0;
 
778
#ifdef  XORCOM_INTERNAL
 
779
        int                     opt_write_eeprom = 0;
 
780
        char                    *vendor = NULL;
 
781
        char                    *source = NULL;
 
782
        char                    *product = NULL;
 
783
        char                    *release = NULL;
 
784
        char                    *label = NULL;
 
785
        const char              options[] = "rib:D:ghH:I:vw:C:V:P:R:S:";
 
786
#else
 
787
        const char              options[] = "rib:D:ghH:I:vw:";
 
788
#endif
 
789
        int                     ret = 0;
 
790
 
 
791
        progname = argv[0];
 
792
        assert(sizeof(struct fpga_packet_header) <= PACKET_SIZE);
 
793
        assert(sizeof(struct myeeprom) == EEPROM_SIZE);
 
794
        while (1) {
 
795
                int     c;
 
796
 
 
797
                c = getopt (argc, argv, options);
 
798
                if (c == -1)
 
799
                        break;
 
800
 
 
801
                switch (c) {
 
802
                        case 'D':
 
803
                                devpath = optarg;
 
804
                                if(output_is_set++) {
 
805
                                        ERR("Cannot set -D. Another output option is already selected\n");
 
806
                                        return 1;
 
807
                                }
 
808
                                break;
 
809
                        case 'r':
 
810
                                opt_reset = 1;
 
811
                                break;
 
812
                        case 'i':
 
813
                                opt_info = 1;
 
814
                                break;
 
815
                        case 'b':
 
816
                                binfile = optarg;
 
817
                                if(output_is_set++) {
 
818
                                        ERR("Cannot set -b. Another output option is already selected\n");
 
819
                                        return 1;
 
820
                                }
 
821
                                break;
 
822
                        case 'g':
 
823
                                opt_read_eeprom = 1;
 
824
                                break;
 
825
                        case 'H':
 
826
                                outhexfile = optarg;
 
827
                                if(output_is_set++) {
 
828
                                        ERR("Cannot set -H. Another output option is already selected\n");
 
829
                                        return 1;
 
830
                                }
 
831
                                break;
 
832
                        case 'I':
 
833
                                inhexfile = optarg;
 
834
                                break;
 
835
#ifdef  XORCOM_INTERNAL
 
836
                        case 'V':
 
837
                                vendor = optarg;
 
838
                                break;
 
839
                        case 'C':
 
840
                                source = optarg;
 
841
                                break;
 
842
                        case 'P':
 
843
                                product = optarg;
 
844
                                break;
 
845
                        case 'R':
 
846
                                release = optarg;
 
847
                                break;
 
848
                        case 'S':
 
849
                                label = optarg;
 
850
                                {
 
851
                                        const char      GOOD_CHARS[] =
 
852
                                                "abcdefghijklmnopqrstuvwxyz"
 
853
                                                "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
 
854
                                                "0123456789"
 
855
                                                "-_.";
 
856
                                        int     len = strlen(label);
 
857
                                        int     goodlen = strspn(label, GOOD_CHARS);
 
858
 
 
859
                                        if(len > LABEL_SIZE) {
 
860
                                                ERR("Label too long (%d > %d)\n", len, LABEL_SIZE);
 
861
                                                usage();
 
862
                                        }
 
863
                                        if(goodlen != len) {
 
864
                                                ERR("Bad character in label number (pos=%d)\n", goodlen);
 
865
                                                usage();
 
866
                                        }
 
867
                                }
 
868
                                break;
 
869
#endif
 
870
                        case 'w':
 
871
                                opt_output_width = strtoul(optarg, NULL, 0);
 
872
                                break;
 
873
                        case 'v':
 
874
                                verbose++;
 
875
                                break;
 
876
                        case 'h':
 
877
                        default:
 
878
                                ERR("Unknown option '%c'\n", c);
 
879
                                usage();
 
880
                }
 
881
        }
 
882
 
 
883
        if (optind != argc) {
 
884
                usage();
 
885
        }
 
886
        if(inhexfile) {
 
887
#ifdef  XORCOM_INTERNAL
 
888
                if(vendor || product || release || label || source ) {
 
889
                        ERR("The -I option is exclusive of -[VPRSC]\n");
 
890
                        return 1;
 
891
                }
 
892
#endif
 
893
                parse_hexfile_set_reporting(parse_report_func);
 
894
                hexdata = parse_hexfile(inhexfile, MAX_HEX_LINES);
 
895
                if(!hexdata) {
 
896
                        ERR("Bailing out\n");
 
897
                        exit(1);
 
898
                }
 
899
                if(opt_info) {
 
900
                        printf("%s: Version=%s Checksum=%d\n",
 
901
                                        inhexfile, hexdata->version_info,
 
902
                                        bsd_checksum(hexdata));
 
903
                }
 
904
                if(binfile) {
 
905
                        dump_binary(hexdata, binfile);
 
906
                        return 0;
 
907
                }
 
908
                if(outhexfile) {
 
909
                        if(opt_output_width)
 
910
                                dump_hexfile2(hexdata, outhexfile, opt_output_width);
 
911
                        else
 
912
                                dump_hexfile(hexdata, outhexfile);
 
913
                        return 0;
 
914
                }
 
915
        }
 
916
#ifdef  XORCOM_INTERNAL
 
917
        else if(vendor || product || release || label || source ) {
 
918
                if(outhexfile) {
 
919
                        FILE    *fp;
 
920
 
 
921
                        if(strcmp(outhexfile, "-") == 0)
 
922
                                fp = stdout;
 
923
                        else if((fp = fopen(outhexfile, "w")) == NULL) {
 
924
                                perror(outhexfile);
 
925
                                return 1;
 
926
                        }
 
927
                        memset(&mydev.eeprom, 0, sizeof(struct myeeprom));
 
928
                        eeprom_fill(&mydev.eeprom, vendor, product, release, label, source);
 
929
                        gen_hexline((uint8_t *)&mydev.eeprom, 0, sizeof(mydev.eeprom), fp);
 
930
                        gen_hexline(NULL, 0, 0, fp);    /* EOF */
 
931
                        return 0;
 
932
                }
 
933
        }
 
934
#endif
 
935
        if(!devpath) {
 
936
                ERR("Missing device path\n");
 
937
                usage();
 
938
        }
 
939
        DBG("Startup %s\n", devpath);
 
940
        if((abtype = my_usb_device_identify(devpath, &mydev)) == NULL) {
 
941
                ERR("Bad device. Does not match our types.\n");
 
942
                usage();
 
943
        }
 
944
        INFO("FIRMWARE: %s (type=%d)\n", abtype->name, abtype->type_code);
 
945
        if(!my_usb_device_init(devpath, &mydev, abtype)) {
 
946
                ERR("Failed to initialize USB device '%s'\n", devpath);
 
947
                ret = -ENODEV;
 
948
                goto dev_err;
 
949
        }
 
950
        ret = eeprom_get(&mydev);
 
951
        if(ret < 0) {
 
952
                ERR("Failed reading eeprom\n");
 
953
                goto dev_err;
 
954
        }
 
955
#ifdef  XORCOM_INTERNAL
 
956
        if(vendor || product || release || label || source ) {
 
957
                eeprom_fill(&mydev.eeprom, vendor, product, release, label, source);
 
958
                opt_write_eeprom = 1;
 
959
                opt_read_eeprom = 1;
 
960
        }
 
961
#endif
 
962
        if(opt_read_eeprom) {
 
963
                show_device_info(&mydev);
 
964
        }
 
965
        if(hexdata) {
 
966
                if (!mydev.is_usb2)
 
967
                        INFO("Warning: working on a low end USB1 backend\n");
 
968
                if(!fpga_load(&mydev, hexdata)) {
 
969
                        ERR("FPGA loading failed\n");
 
970
                        ret = -ENODEV;
 
971
                        goto dev_err;
 
972
                }
 
973
                ret = renumerate_device(&mydev, PT_RENUMERATE);
 
974
                if(ret < 0) {
 
975
                        ERR("Renumeration failed: errno=%d\n", ret);
 
976
                        goto dev_err;
 
977
                }
 
978
        }
 
979
#ifdef XORCOM_INTERNAL
 
980
        else if(opt_write_eeprom) {
 
981
                if(abtype->type_code == USB_FIRMWARE_II) {
 
982
                        ERR("No EEPROM burning command in %s. Use fxload for that\n",
 
983
                                abtype->name);
 
984
                        goto dev_err;
 
985
                }
 
986
                ret = eeprom_set(&mydev, &mydev.eeprom);
 
987
                if(ret < 0) {
 
988
                        ERR("Failed writing eeprom: %s\n", strerror(-ret));
 
989
                        goto dev_err;
 
990
                }
 
991
                printf("------- RESULTS -------\n");
 
992
                show_device_info(&mydev);
 
993
        }
 
994
#endif
 
995
        if(opt_reset) {
 
996
                DBG("Reseting to default\n");
 
997
                ret = renumerate_device(&mydev, PT_RESET);
 
998
                if(ret < 0) {
 
999
                        ERR("Renumeration to default failed: errno=%d\n", ret);
 
1000
                        goto dev_err;
 
1001
                }
 
1002
        }
 
1003
        DBG("Exiting\n");
 
1004
dev_err:
 
1005
        my_usb_device_cleanup(&mydev);
 
1006
        return ret;
 
1007
}