~ubuntu-branches/ubuntu/intrepid/bluez/intrepid

« back to all changes in this revision

Viewing changes to tools/bccmd.c

  • Committer: Bazaar Package Importer
  • Author(s): Mario Limonciello
  • Date: 2008-10-07 12:10:29 UTC
  • Revision ID: james.westby@ubuntu.com-20081007121029-4gup4fmmh2vfo5nh
Tags: upstream-4.12
ImportĀ upstreamĀ versionĀ 4.12

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *
 
3
 *  BlueZ - Bluetooth protocol stack for Linux
 
4
 *
 
5
 *  Copyright (C) 2004-2008  Marcel Holtmann <marcel@holtmann.org>
 
6
 *
 
7
 *
 
8
 *  This program is free software; you can redistribute it and/or modify
 
9
 *  it under the terms of the GNU General Public License as published by
 
10
 *  the Free Software Foundation; either version 2 of the License, or
 
11
 *  (at your option) any later version.
 
12
 *
 
13
 *  This program is distributed in the hope that it will be useful,
 
14
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
 *  GNU General Public License for more details.
 
17
 *
 
18
 *  You should have received a copy of the GNU General Public License
 
19
 *  along with this program; if not, write to the Free Software
 
20
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
21
 *
 
22
 */
 
23
 
 
24
#ifdef HAVE_CONFIG_H
 
25
#include <config.h>
 
26
#endif
 
27
 
 
28
#include <stdio.h>
 
29
#include <errno.h>
 
30
#include <stdlib.h>
 
31
#include <getopt.h>
 
32
#include <sys/socket.h>
 
33
 
 
34
#include <bluetooth/bluetooth.h>
 
35
#include <bluetooth/hci.h>
 
36
#include <bluetooth/hci_lib.h>
 
37
 
 
38
#include "csr.h"
 
39
 
 
40
#define CSR_TRANSPORT_UNKNOWN   0
 
41
#define CSR_TRANSPORT_HCI       1
 
42
#define CSR_TRANSPORT_USB       2
 
43
#define CSR_TRANSPORT_BCSP      3
 
44
#define CSR_TRANSPORT_H4        4
 
45
#define CSR_TRANSPORT_3WIRE     5
 
46
 
 
47
#define CSR_STORES_PSI          (0x0001)
 
48
#define CSR_STORES_PSF          (0x0002)
 
49
#define CSR_STORES_PSROM        (0x0004)
 
50
#define CSR_STORES_PSRAM        (0x0008)
 
51
#define CSR_STORES_DEFAULT      (CSR_STORES_PSI | CSR_STORES_PSF)
 
52
 
 
53
#define CSR_TYPE_NULL           0
 
54
#define CSR_TYPE_COMPLEX        1
 
55
#define CSR_TYPE_UINT8          2
 
56
#define CSR_TYPE_UINT16         3
 
57
#define CSR_TYPE_UINT32         4
 
58
 
 
59
#define CSR_TYPE_ARRAY          CSR_TYPE_COMPLEX
 
60
#define CSR_TYPE_BDADDR         CSR_TYPE_COMPLEX
 
61
 
 
62
static inline int transport_open(int transport, char *device)
 
63
{
 
64
        switch (transport) {
 
65
        case CSR_TRANSPORT_HCI:
 
66
                return csr_open_hci(device);
 
67
#ifdef HAVE_LIBUSB
 
68
        case CSR_TRANSPORT_USB:
 
69
                return csr_open_usb(device);
 
70
#endif
 
71
        case CSR_TRANSPORT_BCSP:
 
72
                return csr_open_bcsp(device);
 
73
        case CSR_TRANSPORT_H4:
 
74
                return csr_open_h4(device);
 
75
        case CSR_TRANSPORT_3WIRE:
 
76
                return csr_open_3wire(device);
 
77
        default:
 
78
                fprintf(stderr, "Unsupported transport\n");
 
79
                return -1;
 
80
        }
 
81
}
 
82
 
 
83
static inline int transport_read(int transport, uint16_t varid, uint8_t *value, uint16_t length)
 
84
{
 
85
        switch (transport) {
 
86
        case CSR_TRANSPORT_HCI:
 
87
                return csr_read_hci(varid, value, length);
 
88
#ifdef HAVE_LIBUSB
 
89
        case CSR_TRANSPORT_USB:
 
90
                return csr_read_usb(varid, value, length);
 
91
#endif
 
92
        case CSR_TRANSPORT_BCSP:
 
93
                return csr_read_bcsp(varid, value, length);
 
94
        case CSR_TRANSPORT_H4:
 
95
                return csr_read_h4(varid, value, length);
 
96
        case CSR_TRANSPORT_3WIRE:
 
97
                return csr_read_3wire(varid, value, length);
 
98
        default:
 
99
                errno = EOPNOTSUPP;
 
100
                return -1;
 
101
        }
 
102
}
 
103
 
 
104
static inline int transport_write(int transport, uint16_t varid, uint8_t *value, uint16_t length)
 
105
{
 
106
        switch (transport) {
 
107
        case CSR_TRANSPORT_HCI:
 
108
                return csr_write_hci(varid, value, length);
 
109
#ifdef HAVE_LIBUSB
 
110
        case CSR_TRANSPORT_USB:
 
111
                return csr_write_usb(varid, value, length);
 
112
#endif
 
113
        case CSR_TRANSPORT_BCSP:
 
114
                return csr_write_bcsp(varid, value, length);
 
115
        case CSR_TRANSPORT_H4:
 
116
                return csr_write_h4(varid, value, length);
 
117
        case CSR_TRANSPORT_3WIRE:
 
118
                return csr_write_3wire(varid, value, length);
 
119
        default:
 
120
                errno = EOPNOTSUPP;
 
121
                return -1;
 
122
        }
 
123
}
 
124
 
 
125
static inline void transport_close(int transport)
 
126
{
 
127
        switch (transport) {
 
128
        case CSR_TRANSPORT_HCI:
 
129
                csr_close_hci();
 
130
                break;
 
131
#ifdef HAVE_LIBUSB
 
132
        case CSR_TRANSPORT_USB:
 
133
                csr_close_usb();
 
134
                break;
 
135
#endif
 
136
        case CSR_TRANSPORT_BCSP:
 
137
                csr_close_bcsp();
 
138
                break;
 
139
        case CSR_TRANSPORT_H4:
 
140
                csr_close_h4();
 
141
                break;
 
142
        case CSR_TRANSPORT_3WIRE:
 
143
                csr_close_3wire();
 
144
                break;
 
145
        }
 
146
}
 
147
 
 
148
static struct {
 
149
        uint16_t pskey;
 
150
        int type;
 
151
        int size;
 
152
        char *str;
 
153
} storage[] = {
 
154
        { CSR_PSKEY_BDADDR,                   CSR_TYPE_BDADDR,  8,  "bdaddr"   },
 
155
        { CSR_PSKEY_COUNTRYCODE,              CSR_TYPE_UINT16,  0,  "country"  },
 
156
        { CSR_PSKEY_CLASSOFDEVICE,            CSR_TYPE_UINT32,  0,  "devclass" },
 
157
        { CSR_PSKEY_ENC_KEY_LMIN,             CSR_TYPE_UINT16,  0,  "keymin"   },
 
158
        { CSR_PSKEY_ENC_KEY_LMAX,             CSR_TYPE_UINT16,  0,  "keymax"   },
 
159
        { CSR_PSKEY_LOCAL_SUPPORTED_FEATURES, CSR_TYPE_ARRAY,   8,  "features" },
 
160
        { CSR_PSKEY_LOCAL_SUPPORTED_COMMANDS, CSR_TYPE_ARRAY,   18, "commands" },
 
161
        { CSR_PSKEY_HCI_LMP_LOCAL_VERSION,    CSR_TYPE_UINT16,  0,  "version"  },
 
162
        { CSR_PSKEY_LMP_REMOTE_VERSION,       CSR_TYPE_UINT8,   0,  "remver"   },
 
163
        { CSR_PSKEY_HOSTIO_USE_HCI_EXTN,      CSR_TYPE_UINT16,  0,  "hciextn"  },
 
164
        { CSR_PSKEY_HOSTIO_MAP_SCO_PCM,       CSR_TYPE_UINT16,  0,  "mapsco"   },
 
165
        { CSR_PSKEY_UART_BAUDRATE,            CSR_TYPE_UINT16,  0,  "baudrate" },
 
166
        { CSR_PSKEY_HOST_INTERFACE,           CSR_TYPE_UINT16,  0,  "hostintf" },
 
167
        { CSR_PSKEY_ANA_FREQ,                 CSR_TYPE_UINT16,  0,  "anafreq"  },
 
168
        { CSR_PSKEY_ANA_FTRIM,                CSR_TYPE_UINT16,  0,  "anaftrim" },
 
169
        { CSR_PSKEY_USB_VENDOR_ID,            CSR_TYPE_UINT16,  0,  "usbvid"   },
 
170
        { CSR_PSKEY_USB_PRODUCT_ID,           CSR_TYPE_UINT16,  0,  "usbpid"   },
 
171
        { CSR_PSKEY_USB_DFU_PRODUCT_ID,       CSR_TYPE_UINT16,  0,  "dfupid"   },
 
172
        { CSR_PSKEY_INITIAL_BOOTMODE,         CSR_TYPE_UINT16,  0,  "bootmode" },
 
173
        { 0x0000 },
 
174
};
 
175
 
 
176
static char *storestostr(uint16_t stores)
 
177
{
 
178
        switch (stores) {
 
179
        case 0x0000:
 
180
                return "Default";
 
181
        case 0x0001:
 
182
                return "psi";
 
183
        case 0x0002:
 
184
                return "psf";
 
185
        case 0x0004:
 
186
                return "psrom";
 
187
        case 0x0008:
 
188
                return "psram";
 
189
        default:
 
190
                return "Unknown";
 
191
        }
 
192
}
 
193
 
 
194
static char *memorytostr(uint16_t type)
 
195
{
 
196
        switch (type) {
 
197
        case 0x0000:
 
198
                return "Flash memory";
 
199
        case 0x0001:
 
200
                return "EEPROM";
 
201
        case 0x0002:
 
202
                return "RAM (transient)";
 
203
        case 0x0003:
 
204
                return "ROM (or \"read-only\" flash memory)";
 
205
        default:
 
206
                return "Unknown";
 
207
        }
 
208
}
 
209
 
 
210
#define OPT_RANGE(min, max) \
 
211
                if (argc < (min)) { errno = EINVAL; return -1; } \
 
212
                if (argc > (max)) { errno = E2BIG; return -1; }
 
213
 
 
214
static struct option help_options[] = {
 
215
        { "help",       0, 0, 'h' },
 
216
        { 0, 0, 0, 0 }
 
217
};
 
218
 
 
219
static int opt_help(int argc, char *argv[], int *help)
 
220
{
 
221
        int opt;
 
222
 
 
223
        while ((opt=getopt_long(argc, argv, "+h", help_options, NULL)) != EOF) {
 
224
                switch (opt) {
 
225
                case 'h':
 
226
                        if (help)
 
227
                                *help = 1;
 
228
                        break;
 
229
                }
 
230
        }
 
231
 
 
232
        return optind;
 
233
}
 
234
 
 
235
#define OPT_HELP(range, help) \
 
236
                opt_help(argc, argv, (help)); \
 
237
                argc -= optind; argv += optind; optind = 0; \
 
238
                OPT_RANGE((range), (range))
 
239
 
 
240
static int cmd_builddef(int transport, int argc, char *argv[])
 
241
{
 
242
        uint8_t array[8];
 
243
        uint16_t def = 0x0000, nextdef = 0x0000;
 
244
        int err = 0;
 
245
 
 
246
        OPT_HELP(0, NULL);
 
247
 
 
248
        printf("Build definitions:\n");
 
249
 
 
250
        while (1) {
 
251
                memset(array, 0, sizeof(array));
 
252
                array[0] = def & 0xff;
 
253
                array[1] = def >> 8;
 
254
 
 
255
                err = transport_read(transport, CSR_VARID_GET_NEXT_BUILDDEF, array, 8);
 
256
                if (err < 0) {
 
257
                        errno = -err;
 
258
                        break;
 
259
                }
 
260
 
 
261
                nextdef = array[2] | (array[3] << 8);
 
262
 
 
263
                if (nextdef == 0x0000)
 
264
                        break;
 
265
 
 
266
                def = nextdef;
 
267
 
 
268
                printf("0x%04x - %s\n", def, csr_builddeftostr(def));
 
269
        }
 
270
 
 
271
        return err;
 
272
}
 
273
 
 
274
static int cmd_keylen(int transport, int argc, char *argv[])
 
275
{
 
276
        uint8_t array[8];
 
277
        uint16_t handle, keylen;
 
278
        int err;
 
279
 
 
280
        OPT_HELP(1, NULL);
 
281
 
 
282
        handle = atoi(argv[0]);
 
283
 
 
284
        memset(array, 0, sizeof(array));
 
285
        array[0] = handle & 0xff;
 
286
        array[1] = handle >> 8;
 
287
 
 
288
        err = transport_read(transport, CSR_VARID_CRYPT_KEY_LENGTH, array, 8);
 
289
        if (err < 0) {
 
290
                errno = -err;
 
291
                return -1;
 
292
        }
 
293
 
 
294
        handle = array[0] | (array[1] << 8);
 
295
        keylen = array[2] | (array[3] << 8);
 
296
 
 
297
        printf("Crypt key length: %d bit\n", keylen * 8);
 
298
 
 
299
        return 0;
 
300
}
 
301
 
 
302
static int cmd_clock(int transport, int argc, char *argv[])
 
303
{
 
304
        uint8_t array[8];
 
305
        uint32_t clock;
 
306
        int err;
 
307
 
 
308
        OPT_HELP(0, NULL);
 
309
 
 
310
        memset(array, 0, sizeof(array));
 
311
 
 
312
        err = transport_read(transport, CSR_VARID_BT_CLOCK, array, 8);
 
313
        if (err < 0) {
 
314
                errno = -err;
 
315
                return -1;
 
316
        }
 
317
 
 
318
        clock = array[2] | (array[3] << 8) | (array[0] << 16) | (array[1] << 24);
 
319
 
 
320
        printf("Bluetooth clock: 0x%04x (%d)\n", clock, clock);
 
321
 
 
322
        return 0;
 
323
}
 
324
 
 
325
static int cmd_rand(int transport, int argc, char *argv[])
 
326
{
 
327
        uint8_t array[8];
 
328
        uint16_t rand;
 
329
        int err;
 
330
 
 
331
        OPT_HELP(0, NULL);
 
332
 
 
333
        memset(array, 0, sizeof(array));
 
334
 
 
335
        err = transport_read(transport, CSR_VARID_RAND, array, 8);
 
336
        if (err < 0) {
 
337
                errno = -err;
 
338
                return -1;
 
339
        }
 
340
 
 
341
        rand = array[0] | (array[1] << 8);
 
342
 
 
343
        printf("Random number: 0x%02x (%d)\n", rand, rand);
 
344
 
 
345
        return 0;
 
346
}
 
347
 
 
348
static int cmd_chiprev(int transport, int argc, char *argv[])
 
349
{
 
350
        uint8_t array[8];
 
351
        uint16_t rev;
 
352
        char *str;
 
353
        int err;
 
354
 
 
355
        OPT_HELP(0, NULL);
 
356
 
 
357
        memset(array, 0, sizeof(array));
 
358
 
 
359
        err = transport_read(transport, CSR_VARID_CHIPREV, array, 8);
 
360
        if (err < 0) {
 
361
                errno = -err;
 
362
                return -1;
 
363
        }
 
364
 
 
365
        rev = array[0] | (array[1] << 8);
 
366
 
 
367
        switch (rev) {
 
368
        case 0x64:
 
369
                str = "BC1 ES";
 
370
                break;
 
371
        case 0x65:
 
372
                str = "BC1";
 
373
                break;
 
374
        case 0x89:
 
375
                str = "BC2-External A";
 
376
                break;
 
377
        case 0x8a:
 
378
                str = "BC2-External B";
 
379
                break;
 
380
        case 0x28:
 
381
                str = "BC2-ROM";
 
382
                break;
 
383
        case 0x43:
 
384
                str = "BC3-Multimedia";
 
385
                break;
 
386
        case 0x15:
 
387
                str = "BC3-ROM";
 
388
                break;
 
389
        case 0xe2:
 
390
                str = "BC3-Flash";
 
391
                break;
 
392
        case 0x26:
 
393
                str = "BC4-External";
 
394
                break;
 
395
        case 0x30:
 
396
                str = "BC4-ROM";
 
397
                break;
 
398
        default:
 
399
                str = "NA";
 
400
                break;
 
401
        }
 
402
 
 
403
        printf("Chip revision: 0x%04x (%s)\n", rev, str);
 
404
 
 
405
        return 0;
 
406
}
 
407
 
 
408
static int cmd_buildname(int transport, int argc, char *argv[])
 
409
{
 
410
        uint8_t array[130];
 
411
        char name[64];
 
412
        int i, err;
 
413
 
 
414
        OPT_HELP(0, NULL);
 
415
 
 
416
        memset(array, 0, sizeof(array));
 
417
 
 
418
        err = transport_read(transport, CSR_VARID_READ_BUILD_NAME, array, 128);
 
419
        if (err < 0) {
 
420
                errno = -err;
 
421
                return -1;
 
422
        }
 
423
 
 
424
        for (i = 0; i < sizeof(name); i++)
 
425
                name[i] = array[(i * 2) + 4];
 
426
 
 
427
        printf("Build name: %s\n", name);
 
428
 
 
429
        return 0;
 
430
}
 
431
 
 
432
static int cmd_panicarg(int transport, int argc, char *argv[])
 
433
{
 
434
        uint8_t array[8];
 
435
        uint16_t error;
 
436
        int err;
 
437
 
 
438
        OPT_HELP(0, NULL);
 
439
 
 
440
        memset(array, 0, sizeof(array));
 
441
 
 
442
        err = transport_read(transport, CSR_VARID_PANIC_ARG, array, 8);
 
443
        if (err < 0) {
 
444
                errno = -err;
 
445
                return -1;
 
446
        }
 
447
 
 
448
        error = array[0] | (array[1] << 8);
 
449
 
 
450
        printf("Panic code: 0x%02x (%s)\n", error,
 
451
                                        error < 0x100 ? "valid" : "invalid");
 
452
 
 
453
        return 0;
 
454
}
 
455
 
 
456
static int cmd_faultarg(int transport, int argc, char *argv[])
 
457
{
 
458
        uint8_t array[8];
 
459
        uint16_t error;
 
460
        int err;
 
461
 
 
462
        OPT_HELP(0, NULL);
 
463
 
 
464
        memset(array, 0, sizeof(array));
 
465
 
 
466
        err = transport_read(transport, CSR_VARID_FAULT_ARG, array, 8);
 
467
        if (err < 0) {
 
468
                errno = -err;
 
469
                return -1;
 
470
        }
 
471
 
 
472
        error = array[0] | (array[1] << 8);
 
473
 
 
474
        printf("Fault code: 0x%02x (%s)\n", error,
 
475
                                        error < 0x100 ? "valid" : "invalid");
 
476
 
 
477
        return 0;
 
478
}
 
479
 
 
480
static int cmd_coldreset(int transport, int argc, char *argv[])
 
481
{
 
482
        return transport_write(transport, CSR_VARID_COLD_RESET, NULL, 0);
 
483
}
 
484
 
 
485
static int cmd_warmreset(int transport, int argc, char *argv[])
 
486
{
 
487
        return transport_write(transport, CSR_VARID_WARM_RESET, NULL, 0);
 
488
}
 
489
 
 
490
static int cmd_disabletx(int transport, int argc, char *argv[])
 
491
{
 
492
        return transport_write(transport, CSR_VARID_DISABLE_TX, NULL, 0);
 
493
}
 
494
 
 
495
static int cmd_enabletx(int transport, int argc, char *argv[])
 
496
{
 
497
        return transport_write(transport, CSR_VARID_ENABLE_TX, NULL, 0);
 
498
}
 
499
 
 
500
static int cmd_singlechan(int transport, int argc, char *argv[])
 
501
{
 
502
        uint8_t array[8];
 
503
        uint16_t channel;
 
504
 
 
505
        OPT_HELP(1, NULL);
 
506
 
 
507
        channel = atoi(argv[0]);
 
508
 
 
509
        if (channel > 2401 && channel < 2481)
 
510
                channel -= 2402;
 
511
 
 
512
        if (channel > 78) {
 
513
                errno = EINVAL;
 
514
                return -1;
 
515
        }
 
516
 
 
517
        memset(array, 0, sizeof(array));
 
518
        array[0] = channel & 0xff;
 
519
        array[1] = channel >> 8;
 
520
 
 
521
        return transport_write(transport, CSR_VARID_SINGLE_CHAN, array, 8);
 
522
}
 
523
 
 
524
static int cmd_hoppingon(int transport, int argc, char *argv[])
 
525
{
 
526
        return transport_write(transport, CSR_VARID_HOPPING_ON, NULL, 0);
 
527
}
 
528
 
 
529
static int cmd_rttxdata1(int transport, int argc, char *argv[])
 
530
{
 
531
        uint8_t array[8];
 
532
        uint16_t freq, level;
 
533
 
 
534
        OPT_HELP(2, NULL);
 
535
 
 
536
        freq = atoi(argv[0]);
 
537
 
 
538
        if (!strncasecmp(argv[1], "0x", 2))
 
539
                level = strtol(argv[1], NULL, 16);
 
540
        else
 
541
                level = atoi(argv[1]);
 
542
 
 
543
        memset(array, 0, sizeof(array));
 
544
        array[0] = 0x04;
 
545
        array[1] = 0x00;
 
546
        array[2] = freq & 0xff;
 
547
        array[3] = freq >> 8;
 
548
        array[4] = level & 0xff;
 
549
        array[5] = level >> 8;
 
550
 
 
551
        return transport_write(transport, CSR_VARID_RADIOTEST, array, 8);
 
552
}
 
553
 
 
554
static int cmd_radiotest(int transport, int argc, char *argv[])
 
555
{
 
556
        uint8_t array[8];
 
557
        uint16_t freq, level, test;
 
558
 
 
559
        OPT_HELP(3, NULL);
 
560
 
 
561
        freq = atoi(argv[0]);
 
562
 
 
563
        if (!strncasecmp(argv[1], "0x", 2))
 
564
                level = strtol(argv[1], NULL, 16);
 
565
        else
 
566
                level = atoi(argv[1]);
 
567
 
 
568
        test = atoi(argv[2]);
 
569
 
 
570
        memset(array, 0, sizeof(array));
 
571
        array[0] = test & 0xff;
 
572
        array[1] = test >> 8;
 
573
        array[2] = freq & 0xff;
 
574
        array[3] = freq >> 8;
 
575
        array[4] = level & 0xff;
 
576
        array[5] = level >> 8;
 
577
 
 
578
        return transport_write(transport, CSR_VARID_RADIOTEST, array, 8);
 
579
}
 
580
 
 
581
static int cmd_memtypes(int transport, int argc, char *argv[])
 
582
{
 
583
        uint8_t array[8];
 
584
        uint16_t type, stores[4] = { 0x0001, 0x0002, 0x0004, 0x0008 };
 
585
        int i, err;
 
586
 
 
587
        OPT_HELP(0, NULL);
 
588
 
 
589
        for (i = 0; i < 4; i++) {
 
590
                memset(array, 0, sizeof(array));
 
591
                array[0] = stores[i] & 0xff;
 
592
                array[1] = stores[i] >> 8;
 
593
 
 
594
                err = transport_read(transport, CSR_VARID_PS_MEMORY_TYPE, array, 8);
 
595
                if (err < 0)
 
596
                        continue;
 
597
 
 
598
                type = array[2] + (array[3] << 8);
 
599
 
 
600
                printf("%s (0x%04x) = %s (%d)\n", storestostr(stores[i]),
 
601
                                        stores[i], memorytostr(type), type);
 
602
        }
 
603
 
 
604
        return 0;
 
605
}
 
606
 
 
607
static struct option pskey_options[] = {
 
608
        { "stores",     1, 0, 's' },
 
609
        { "reset",      0, 0, 'r' },
 
610
        { "help",       0, 0, 'h' },
 
611
        { 0, 0, 0, 0 }
 
612
};
 
613
 
 
614
static int opt_pskey(int argc, char *argv[], uint16_t *stores, int *reset, int *help)
 
615
{
 
616
        int opt;
 
617
 
 
618
        while ((opt=getopt_long(argc, argv, "+s:rh", pskey_options, NULL)) != EOF) {
 
619
                switch (opt) {
 
620
                case 's':
 
621
                        if (!stores)
 
622
                                break;
 
623
                        if (!strcasecmp(optarg, "default"))
 
624
                                *stores = 0x0000;
 
625
                        else if (!strcasecmp(optarg, "implementation"))
 
626
                                *stores = 0x0001;
 
627
                        else if (!strcasecmp(optarg, "factory"))
 
628
                                *stores = 0x0002;
 
629
                        else if (!strcasecmp(optarg, "rom"))
 
630
                                *stores = 0x0004;
 
631
                        else if (!strcasecmp(optarg, "ram"))
 
632
                                *stores = 0x0008;
 
633
                        else if (!strcasecmp(optarg, "psi"))
 
634
                                *stores = 0x0001;
 
635
                        else if (!strcasecmp(optarg, "psf"))
 
636
                                *stores = 0x0002;
 
637
                        else if (!strcasecmp(optarg, "psrom"))
 
638
                                *stores = 0x0004;
 
639
                        else if (!strcasecmp(optarg, "psram"))
 
640
                                *stores = 0x0008;
 
641
                        else if (!strncasecmp(optarg, "0x", 2))
 
642
                                *stores = strtol(optarg, NULL, 16);
 
643
                        else
 
644
                                *stores = atoi(optarg);
 
645
                        break;
 
646
 
 
647
                case 'r':
 
648
                        if (reset)
 
649
                                *reset = 1;
 
650
                        break;
 
651
 
 
652
                case 'h':
 
653
                        if (help)
 
654
                                *help = 1;
 
655
                        break;
 
656
                }
 
657
        }
 
658
 
 
659
        return optind;
 
660
}
 
661
 
 
662
#define OPT_PSKEY(min, max, stores, reset, help) \
 
663
                opt_pskey(argc, argv, (stores), (reset), (help)); \
 
664
                argc -= optind; argv += optind; optind = 0; \
 
665
                OPT_RANGE((min), (max))
 
666
 
 
667
static int cmd_psget(int transport, int argc, char *argv[])
 
668
{
 
669
        uint8_t array[128];
 
670
        uint16_t pskey, length, value, stores = CSR_STORES_DEFAULT;
 
671
        uint32_t val32;
 
672
        int i, err, reset = 0;
 
673
 
 
674
        memset(array, 0, sizeof(array));
 
675
 
 
676
        OPT_PSKEY(1, 1, &stores, &reset, NULL);
 
677
 
 
678
        if (strncasecmp(argv[0], "0x", 2)) {
 
679
                pskey = atoi(argv[0]);
 
680
 
 
681
                for (i = 0; storage[i].pskey; i++) {
 
682
                        if (strcasecmp(storage[i].str, argv[0]))
 
683
                                continue;
 
684
 
 
685
                        pskey = storage[i].pskey;
 
686
                        break;
 
687
                }
 
688
        } else
 
689
                pskey = strtol(argv[0] + 2, NULL, 16);
 
690
 
 
691
        memset(array, 0, sizeof(array));
 
692
        array[0] = pskey & 0xff;
 
693
        array[1] = pskey >> 8;
 
694
        array[2] = stores & 0xff;
 
695
        array[3] = stores >> 8;
 
696
 
 
697
        err = transport_read(transport, CSR_VARID_PS_SIZE, array, 8);
 
698
        if (err < 0)
 
699
                return err;
 
700
 
 
701
        length = array[2] + (array[3] << 8);
 
702
        if (length + 6 > sizeof(array) / 2)
 
703
                return -EIO;
 
704
 
 
705
        memset(array, 0, sizeof(array));
 
706
        array[0] = pskey & 0xff;
 
707
        array[1] = pskey >> 8;
 
708
        array[2] = length & 0xff;
 
709
        array[3] = length >> 8;
 
710
        array[4] = stores & 0xff;
 
711
        array[5] = stores >> 8;
 
712
 
 
713
        err = transport_read(transport, CSR_VARID_PS, array, (length + 3) * 2);
 
714
        if (err < 0)
 
715
                return err;
 
716
 
 
717
        switch (length) {
 
718
        case 1:
 
719
                value = array[6] | (array[7] << 8);
 
720
                printf("%s: 0x%04x (%d)\n", csr_pskeytostr(pskey), value, value);
 
721
                break;
 
722
 
 
723
        case 2:
 
724
                val32 = array[8] | (array[9] << 8) | (array[6] << 16) | (array[7] << 24);
 
725
                printf("%s: 0x%08x (%d)\n", csr_pskeytostr(pskey), val32, val32);
 
726
                break;
 
727
 
 
728
        default:
 
729
                printf("%s:", csr_pskeytostr(pskey));
 
730
                for (i = 0; i < length; i++)
 
731
                        printf(" 0x%02x%02x", array[(i * 2) + 6], array[(i * 2) + 7]);
 
732
                printf("\n");
 
733
                break;
 
734
        }
 
735
 
 
736
        if (reset)
 
737
                transport_write(transport, CSR_VARID_WARM_RESET, NULL, 0);
 
738
 
 
739
        return err;
 
740
}
 
741
 
 
742
static int cmd_psset(int transport, int argc, char *argv[])
 
743
{
 
744
        uint8_t array[128];
 
745
        uint16_t pskey, length, value, stores = CSR_STORES_PSRAM;
 
746
        uint32_t val32;
 
747
        int i, err, reset = 0;
 
748
 
 
749
        memset(array, 0, sizeof(array));
 
750
 
 
751
        OPT_PSKEY(2, 81, &stores, &reset, NULL);
 
752
 
 
753
        if (strncasecmp(argv[0], "0x", 2)) {
 
754
                pskey = atoi(argv[0]);
 
755
 
 
756
                for (i = 0; storage[i].pskey; i++) {
 
757
                        if (strcasecmp(storage[i].str, argv[0]))
 
758
                                continue;
 
759
 
 
760
                        pskey = storage[i].pskey;
 
761
                        break;
 
762
                }
 
763
        } else
 
764
                pskey = strtol(argv[0] + 2, NULL, 16);
 
765
 
 
766
        memset(array, 0, sizeof(array));
 
767
        array[0] = pskey & 0xff;
 
768
        array[1] = pskey >> 8;
 
769
        array[2] = stores & 0xff;
 
770
        array[3] = stores >> 8;
 
771
 
 
772
        err = transport_read(transport, CSR_VARID_PS_SIZE, array, 8);
 
773
        if (err < 0)
 
774
                return err;
 
775
 
 
776
        length = array[2] + (array[3] << 8);
 
777
        if (length + 6 > sizeof(array) / 2)
 
778
                return -EIO;
 
779
 
 
780
        memset(array, 0, sizeof(array));
 
781
        array[0] = pskey & 0xff;
 
782
        array[1] = pskey >> 8;
 
783
        array[2] = length & 0xff;
 
784
        array[3] = length >> 8;
 
785
        array[4] = stores & 0xff;
 
786
        array[5] = stores >> 8;
 
787
 
 
788
        argc--;
 
789
        argv++;
 
790
 
 
791
        switch (length) {
 
792
        case 1:
 
793
                if (argc != 1) {
 
794
                        errno = E2BIG;
 
795
                        return -1;
 
796
                }
 
797
 
 
798
                if (!strncasecmp(argv[0], "0x", 2))
 
799
                        value = strtol(argv[0] + 2, NULL, 16);
 
800
                else
 
801
                        value = atoi(argv[0]);
 
802
 
 
803
                array[6] = value & 0xff;
 
804
                array[7] = value >> 8;
 
805
                break;
 
806
 
 
807
        case 2:
 
808
                if (argc != 1) {
 
809
                        errno = E2BIG;
 
810
                        return -1;
 
811
                }
 
812
 
 
813
                if (!strncasecmp(argv[0], "0x", 2))
 
814
                        val32 = strtol(argv[0] + 2, NULL, 16);
 
815
                else
 
816
                        val32 = atoi(argv[0]);
 
817
 
 
818
                array[6] = (val32 & 0xff0000) >> 16;
 
819
                array[7] = val32 >> 24;
 
820
                array[8] = val32 & 0xff;
 
821
                array[9] = (val32 & 0xff00) >> 8;
 
822
                break;
 
823
 
 
824
        default:
 
825
                if (argc != length * 2) {
 
826
                        errno = EINVAL;
 
827
                        return -1;
 
828
                }
 
829
 
 
830
                for (i = 0; i < length * 2; i++)
 
831
                        if (!strncasecmp(argv[0], "0x", 2))
 
832
                                array[i + 6] = strtol(argv[i] + 2, NULL, 16);
 
833
                        else
 
834
                                array[i + 6] = atoi(argv[i]);
 
835
                break;
 
836
        }
 
837
 
 
838
        err = transport_write(transport, CSR_VARID_PS, array, (length + 3) * 2);
 
839
        if (err < 0)
 
840
                return err;
 
841
 
 
842
        if (reset)
 
843
                transport_write(transport, CSR_VARID_WARM_RESET, NULL, 0);
 
844
 
 
845
        return err;
 
846
}
 
847
 
 
848
static int cmd_psclr(int transport, int argc, char *argv[])
 
849
{
 
850
        uint8_t array[8];
 
851
        uint16_t pskey, stores = CSR_STORES_PSRAM;
 
852
        int i, err, reset = 0;
 
853
 
 
854
        OPT_PSKEY(1, 1, &stores, &reset, NULL);
 
855
 
 
856
        if (strncasecmp(argv[0], "0x", 2)) {
 
857
                pskey = atoi(argv[0]);
 
858
 
 
859
                for (i = 0; storage[i].pskey; i++) {
 
860
                        if (strcasecmp(storage[i].str, argv[0]))
 
861
                                continue;
 
862
 
 
863
                        pskey = storage[i].pskey;
 
864
                        break;
 
865
                }
 
866
        } else
 
867
                pskey = strtol(argv[0] + 2, NULL, 16);
 
868
 
 
869
        memset(array, 0, sizeof(array));
 
870
        array[0] = pskey & 0xff;
 
871
        array[1] = pskey >> 8;
 
872
        array[2] = stores & 0xff;
 
873
        array[3] = stores >> 8;
 
874
 
 
875
        err = transport_write(transport, CSR_VARID_PS_CLR_STORES, array, 8);
 
876
        if (err < 0)
 
877
                return err;
 
878
 
 
879
        if (reset)
 
880
                transport_write(transport, CSR_VARID_WARM_RESET, NULL, 0);
 
881
 
 
882
        return err;
 
883
}
 
884
 
 
885
static int cmd_pslist(int transport, int argc, char *argv[])
 
886
{
 
887
        uint8_t array[8];
 
888
        uint16_t pskey = 0x0000, length, stores = CSR_STORES_DEFAULT;
 
889
        int err, reset = 0;
 
890
 
 
891
        OPT_PSKEY(0, 0, &stores, &reset, NULL);
 
892
 
 
893
        while (1) {
 
894
                memset(array, 0, sizeof(array));
 
895
                array[0] = pskey & 0xff;
 
896
                array[1] = pskey >> 8;
 
897
                array[2] = stores & 0xff;
 
898
                array[3] = stores >> 8;
 
899
 
 
900
                err = transport_read(transport, CSR_VARID_PS_NEXT, array, 8);
 
901
                if (err < 0)
 
902
                        break;
 
903
 
 
904
                pskey = array[4] + (array[5] << 8);
 
905
                if (pskey == 0x0000)
 
906
                        break;
 
907
 
 
908
                memset(array, 0, sizeof(array));
 
909
                array[0] = pskey & 0xff;
 
910
                array[1] = pskey >> 8;
 
911
                array[2] = stores & 0xff;
 
912
                array[3] = stores >> 8;
 
913
 
 
914
                err = transport_read(transport, CSR_VARID_PS_SIZE, array, 8);
 
915
                if (err < 0)
 
916
                        continue;
 
917
 
 
918
                length = array[2] + (array[3] << 8);
 
919
 
 
920
                printf("0x%04x - %s (%d bytes)\n", pskey,
 
921
                                        csr_pskeytostr(pskey), length * 2);
 
922
        }
 
923
 
 
924
        if (reset)
 
925
                transport_write(transport, CSR_VARID_WARM_RESET, NULL, 0);
 
926
 
 
927
        return 0;
 
928
}
 
929
 
 
930
static int cmd_psread(int transport, int argc, char *argv[])
 
931
{
 
932
        uint8_t array[256];
 
933
        uint16_t pskey = 0x0000, length, stores = CSR_STORES_DEFAULT;
 
934
        char *str, val[7];
 
935
        int i, err, reset = 0;
 
936
 
 
937
        OPT_PSKEY(0, 0, &stores, &reset, NULL);
 
938
 
 
939
        while (1) {
 
940
                memset(array, 0, sizeof(array));
 
941
                array[0] = pskey & 0xff;
 
942
                array[1] = pskey >> 8;
 
943
                array[2] = stores & 0xff;
 
944
                array[3] = stores >> 8;
 
945
 
 
946
                err = transport_read(transport, CSR_VARID_PS_NEXT, array, 8);
 
947
                if (err < 0)
 
948
                        break;
 
949
 
 
950
                pskey = array[4] + (array[5] << 8);
 
951
                if (pskey == 0x0000)
 
952
                        break;
 
953
 
 
954
                memset(array, 0, sizeof(array));
 
955
                array[0] = pskey & 0xff;
 
956
                array[1] = pskey >> 8;
 
957
                array[2] = stores & 0xff;
 
958
                array[3] = stores >> 8;
 
959
 
 
960
                err = transport_read(transport, CSR_VARID_PS_SIZE, array, 8);
 
961
                if (err < 0)
 
962
                        continue;
 
963
 
 
964
                length = array[2] + (array[3] << 8);
 
965
                if (length + 6 > sizeof(array) / 2)
 
966
                        continue;
 
967
 
 
968
                memset(array, 0, sizeof(array));
 
969
                array[0] = pskey & 0xff;
 
970
                array[1] = pskey >> 8;
 
971
                array[2] = length & 0xff;
 
972
                array[3] = length >> 8;
 
973
                array[4] = stores & 0xff;
 
974
                array[5] = stores >> 8;
 
975
 
 
976
                err = transport_read(transport, CSR_VARID_PS, array, (length + 3) * 2);
 
977
                if (err < 0)
 
978
                        continue;
 
979
 
 
980
                str = csr_pskeytoval(pskey);
 
981
                if (!strcasecmp(str, "UNKNOWN")) {
 
982
                        sprintf(val, "0x%04x", pskey);
 
983
                        str = NULL;
 
984
                }
 
985
 
 
986
                printf("// %s%s\n&%04x =", str ? "PSKEY_" : "", 
 
987
                                                str ? str : val, pskey);
 
988
                for (i = 0; i < length; i++)
 
989
                        printf(" %02x%02x", array[(i * 2) + 7], array[(i * 2) + 6]);
 
990
                printf("\n");
 
991
        }
 
992
 
 
993
        if (reset)
 
994
                transport_write(transport, CSR_VARID_WARM_RESET, NULL, 0);
 
995
 
 
996
        return 0;
 
997
}
 
998
 
 
999
static int cmd_psload(int transport, int argc, char *argv[])
 
1000
{
 
1001
        uint8_t array[256];
 
1002
        uint16_t pskey, length, size, stores = CSR_STORES_PSRAM;
 
1003
        char *str, val[7];
 
1004
        int err, reset = 0;
 
1005
 
 
1006
        OPT_PSKEY(1, 1, &stores, &reset, NULL);
 
1007
 
 
1008
        psr_read(argv[0]);
 
1009
 
 
1010
        memset(array, 0, sizeof(array));
 
1011
        size = sizeof(array) - 6;
 
1012
 
 
1013
        while (psr_get(&pskey, array + 6, &size) == 0) {
 
1014
                str = csr_pskeytoval(pskey);
 
1015
                if (!strcasecmp(str, "UNKNOWN")) {
 
1016
                        sprintf(val, "0x%04x", pskey);
 
1017
                        str = NULL;
 
1018
                }
 
1019
 
 
1020
                printf("Loading %s%s ... ", str ? "PSKEY_" : "",
 
1021
                                                        str ? str : val);
 
1022
                fflush(stdout);
 
1023
 
 
1024
                length = size / 2;
 
1025
 
 
1026
                array[0] = pskey & 0xff;
 
1027
                array[1] = pskey >> 8;
 
1028
                array[2] = length & 0xff;
 
1029
                array[3] = length >> 8;
 
1030
                array[4] = stores & 0xff;
 
1031
                array[5] = stores >> 8;
 
1032
 
 
1033
                err = transport_write(transport, CSR_VARID_PS, array, size + 6);
 
1034
 
 
1035
                printf("%s\n", err < 0 ? "failed" : "done");
 
1036
 
 
1037
                memset(array, 0, sizeof(array));
 
1038
                size = sizeof(array) - 6;
 
1039
        }
 
1040
 
 
1041
        if (reset)
 
1042
                transport_write(transport, CSR_VARID_WARM_RESET, NULL, 0);
 
1043
 
 
1044
        return 0;
 
1045
}
 
1046
 
 
1047
static int cmd_pscheck(int transport, int argc, char *argv[])
 
1048
{
 
1049
        uint8_t array[256];
 
1050
        uint16_t pskey, size;
 
1051
        int i;
 
1052
 
 
1053
        OPT_HELP(1, NULL);
 
1054
 
 
1055
        psr_read(argv[0]);
 
1056
 
 
1057
        while (psr_get(&pskey, array, &size) == 0) {
 
1058
                printf("0x%04x =", pskey);
 
1059
                for (i = 0; i < size; i++)
 
1060
                        printf(" 0x%02x", array[i]);
 
1061
                printf("\n");
 
1062
        }
 
1063
 
 
1064
        return 0;
 
1065
}
 
1066
 
 
1067
static struct {
 
1068
        char *str;
 
1069
        int (*func)(int transport, int argc, char *argv[]);
 
1070
        char *arg;
 
1071
        char *doc;
 
1072
} commands[] = {
 
1073
        { "builddef",  cmd_builddef,  "",                    "Get build definitions"          },
 
1074
        { "keylen",    cmd_keylen,    "<handle>",            "Get current crypt key length"   },
 
1075
        { "clock",     cmd_clock,     "",                    "Get local Bluetooth clock"      },
 
1076
        { "rand",      cmd_rand,      "",                    "Get random number"              },
 
1077
        { "chiprev",   cmd_chiprev,   "",                    "Get chip revision"              },
 
1078
        { "buildname", cmd_buildname, "",                    "Get the full build name"        },
 
1079
        { "panicarg",  cmd_panicarg,  "",                    "Get panic code argument"        },
 
1080
        { "faultarg",  cmd_faultarg,  "",                    "Get fault code argument"        },
 
1081
        { "coldreset", cmd_coldreset, "",                    "Perform cold reset"             },
 
1082
        { "warmreset", cmd_warmreset, "",                    "Perform warm reset"             },
 
1083
        { "disabletx", cmd_disabletx, "",                    "Disable TX on the device"       },
 
1084
        { "enabletx",  cmd_enabletx,  "",                    "Enable TX on the device"        },
 
1085
        { "singlechan",cmd_singlechan,"<channel>",           "Lock radio on specific channel" },
 
1086
        { "hoppingon", cmd_hoppingon, "",                    "Revert to channel hopping"      },
 
1087
        { "rttxdata1", cmd_rttxdata1, "<freq> <level>",      "TXData1 radio test"             },
 
1088
        { "radiotest", cmd_radiotest, "<freq> <level> <id>", "Run radio tests"                },
 
1089
        { "memtypes",  cmd_memtypes,  NULL,                  "Get memory types"               },
 
1090
        { "psget",     cmd_psget,     "<key>",               "Get value for PS key"           },
 
1091
        { "psset",     cmd_psset,     "<key> <value>",       "Set value for PS key"           },
 
1092
        { "psclr",     cmd_psclr,     "<key>",               "Clear value for PS key"         },
 
1093
        { "pslist",    cmd_pslist,    NULL,                  "List all PS keys"               },
 
1094
        { "psread",    cmd_psread,    NULL,                  "Read all PS keys"               },
 
1095
        { "psload",    cmd_psload,    "<file>",              "Load all PS keys from PSR file" },
 
1096
        { "pscheck",   cmd_pscheck,   "<file>",              "Check PSR file"                 },
 
1097
        { NULL }
 
1098
};
 
1099
 
 
1100
static void usage(void)
 
1101
{
 
1102
        int i, pos = 0;
 
1103
 
 
1104
        printf("bccmd - Utility for the CSR BCCMD interface\n\n");
 
1105
        printf("Usage:\n"
 
1106
                "\tbccmd [options] <command>\n\n");
 
1107
 
 
1108
        printf("Options:\n"
 
1109
                "\t-t <transport>     Select the transport\n"
 
1110
                "\t-d <device>        Select the device\n"
 
1111
                "\t-h, --help         Display help\n"
 
1112
                "\n");
 
1113
 
 
1114
        printf("Transports:\n"
 
1115
                "\tHCI USB BCSP H4 3WIRE\n\n");
 
1116
 
 
1117
        printf("Commands:\n");
 
1118
        for (i = 0; commands[i].str; i++)
 
1119
                printf("\t%-10s %-20s\t%s\n", commands[i].str,
 
1120
                commands[i].arg ? commands[i].arg : " ",
 
1121
                commands[i].doc);
 
1122
        printf("\n");
 
1123
 
 
1124
        printf("Keys:\n\t");
 
1125
        for (i = 0; storage[i].pskey; i++) {
 
1126
                printf("%s ", storage[i].str);
 
1127
                pos += strlen(storage[i].str) + 1;
 
1128
                if (pos > 60) {
 
1129
                        printf("\n\t");
 
1130
                        pos = 0;
 
1131
                }
 
1132
        }
 
1133
        printf("\n");
 
1134
}
 
1135
 
 
1136
static struct option main_options[] = {
 
1137
        { "transport",  1, 0, 't' },
 
1138
        { "device",     1, 0, 'd' },
 
1139
        { "help",       0, 0, 'h' },
 
1140
        { 0, 0, 0, 0 }
 
1141
};
 
1142
 
 
1143
int main(int argc, char *argv[])
 
1144
{
 
1145
        char *device = NULL;
 
1146
        int i, err, opt, transport = CSR_TRANSPORT_HCI;
 
1147
 
 
1148
        while ((opt=getopt_long(argc, argv, "+t:d:i:h", main_options, NULL)) != EOF) {
 
1149
                switch (opt) {
 
1150
                case 't':
 
1151
                        if (!strcasecmp(optarg, "hci"))
 
1152
                                transport = CSR_TRANSPORT_HCI;
 
1153
                        else if (!strcasecmp(optarg, "usb"))
 
1154
                                transport = CSR_TRANSPORT_USB;
 
1155
                        else if (!strcasecmp(optarg, "bcsp"))
 
1156
                                transport = CSR_TRANSPORT_BCSP;
 
1157
                        else if (!strcasecmp(optarg, "h4"))
 
1158
                                transport = CSR_TRANSPORT_H4;
 
1159
                        else if (!strcasecmp(optarg, "h5"))
 
1160
                                transport = CSR_TRANSPORT_3WIRE;
 
1161
                        else if (!strcasecmp(optarg, "3wire"))
 
1162
                                transport = CSR_TRANSPORT_3WIRE;
 
1163
                        else if (!strcasecmp(optarg, "twutl"))
 
1164
                                transport = CSR_TRANSPORT_3WIRE;
 
1165
                        else
 
1166
                                transport = CSR_TRANSPORT_UNKNOWN;
 
1167
                        break;
 
1168
 
 
1169
                case 'd':
 
1170
                case 'i':
 
1171
                        device = strdup(optarg);
 
1172
                        break;
 
1173
 
 
1174
                case 'h':
 
1175
                default:
 
1176
                        usage();
 
1177
                        exit(0);
 
1178
                }
 
1179
        }
 
1180
 
 
1181
        argc -= optind;
 
1182
        argv += optind;
 
1183
        optind = 0;
 
1184
 
 
1185
        if (argc < 1) {
 
1186
                usage();
 
1187
                exit(1);
 
1188
        }
 
1189
 
 
1190
        if (transport_open(transport, device) < 0)
 
1191
                exit(1);
 
1192
 
 
1193
        if (device)
 
1194
                free(device);
 
1195
 
 
1196
        for (i = 0; commands[i].str; i++) {
 
1197
                if (strcasecmp(commands[i].str, argv[0]))
 
1198
                        continue;
 
1199
 
 
1200
                err = commands[i].func(transport, argc, argv);
 
1201
 
 
1202
                transport_close(transport);
 
1203
 
 
1204
                if (err < 0) {
 
1205
                        fprintf(stderr, "Can't execute command: %s (%d)\n",
 
1206
                                                        strerror(errno), errno);
 
1207
                        exit(1);
 
1208
                }
 
1209
 
 
1210
                exit(0);
 
1211
        }
 
1212
 
 
1213
        fprintf(stderr, "Unsupported command\n");
 
1214
 
 
1215
        transport_close(transport);
 
1216
 
 
1217
        exit(1);
 
1218
}