952bf131d6a53d847bb0e2a0abb745360843c4c7
[framework/connectivity/bluez.git] / tools / bccmd.c
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2004-2010  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, speed_t bcsp_rate)
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, bcsp_rate);
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                         break;
258
259                 nextdef = array[2] | (array[3] << 8);
260
261                 if (nextdef == 0x0000)
262                         break;
263
264                 def = nextdef;
265
266                 printf("0x%04x - %s\n", def, csr_builddeftostr(def));
267         }
268
269         return err;
270 }
271
272 static int cmd_keylen(int transport, int argc, char *argv[])
273 {
274         uint8_t array[8];
275         uint16_t handle, keylen;
276         int err;
277
278         OPT_HELP(1, NULL);
279
280         handle = atoi(argv[0]);
281
282         memset(array, 0, sizeof(array));
283         array[0] = handle & 0xff;
284         array[1] = handle >> 8;
285
286         err = transport_read(transport, CSR_VARID_CRYPT_KEY_LENGTH, array, 8);
287         if (err < 0)
288                 return -1;
289
290         handle = array[0] | (array[1] << 8);
291         keylen = array[2] | (array[3] << 8);
292
293         printf("Crypt key length: %d bit\n", keylen * 8);
294
295         return 0;
296 }
297
298 static int cmd_clock(int transport, int argc, char *argv[])
299 {
300         uint8_t array[8];
301         uint32_t clock;
302         int err;
303
304         OPT_HELP(0, NULL);
305
306         memset(array, 0, sizeof(array));
307
308         err = transport_read(transport, CSR_VARID_BT_CLOCK, array, 8);
309         if (err < 0)
310                 return -1;
311
312         clock = array[2] | (array[3] << 8) | (array[0] << 16) | (array[1] << 24);
313
314         printf("Bluetooth clock: 0x%04x (%d)\n", clock, clock);
315
316         return 0;
317 }
318
319 static int cmd_rand(int transport, int argc, char *argv[])
320 {
321         uint8_t array[8];
322         uint16_t rand;
323         int err;
324
325         OPT_HELP(0, NULL);
326
327         memset(array, 0, sizeof(array));
328
329         err = transport_read(transport, CSR_VARID_RAND, array, 8);
330         if (err < 0)
331                 return -1;
332
333         rand = array[0] | (array[1] << 8);
334
335         printf("Random number: 0x%02x (%d)\n", rand, rand);
336
337         return 0;
338 }
339
340 static int cmd_chiprev(int transport, int argc, char *argv[])
341 {
342         uint8_t array[8];
343         uint16_t rev;
344         char *str;
345         int err;
346
347         OPT_HELP(0, NULL);
348
349         memset(array, 0, sizeof(array));
350
351         err = transport_read(transport, CSR_VARID_CHIPREV, array, 8);
352         if (err < 0)
353                 return -1;
354
355         rev = array[0] | (array[1] << 8);
356
357         switch (rev) {
358         case 0x64:
359                 str = "BC1 ES";
360                 break;
361         case 0x65:
362                 str = "BC1";
363                 break;
364         case 0x89:
365                 str = "BC2-External A";
366                 break;
367         case 0x8a:
368                 str = "BC2-External B";
369                 break;
370         case 0x28:
371                 str = "BC2-ROM";
372                 break;
373         case 0x43:
374                 str = "BC3-Multimedia";
375                 break;
376         case 0x15:
377                 str = "BC3-ROM";
378                 break;
379         case 0xe2:
380                 str = "BC3-Flash";
381                 break;
382         case 0x26:
383                 str = "BC4-External";
384                 break;
385         case 0x30:
386                 str = "BC4-ROM";
387                 break;
388         default:
389                 str = "NA";
390                 break;
391         }
392
393         printf("Chip revision: 0x%04x (%s)\n", rev, str);
394
395         return 0;
396 }
397
398 static int cmd_buildname(int transport, int argc, char *argv[])
399 {
400         uint8_t array[130];
401         char name[64];
402         unsigned int i;
403         int err;
404
405         OPT_HELP(0, NULL);
406
407         memset(array, 0, sizeof(array));
408
409         err = transport_read(transport, CSR_VARID_READ_BUILD_NAME, array, 128);
410         if (err < 0)
411                 return -1;
412
413         for (i = 0; i < sizeof(name); i++)
414                 name[i] = array[(i * 2) + 4];
415
416         printf("Build name: %s\n", name);
417
418         return 0;
419 }
420
421 static int cmd_panicarg(int transport, int argc, char *argv[])
422 {
423         uint8_t array[8];
424         uint16_t error;
425         int err;
426
427         OPT_HELP(0, NULL);
428
429         memset(array, 0, sizeof(array));
430
431         err = transport_read(transport, CSR_VARID_PANIC_ARG, array, 8);
432         if (err < 0)
433                 return -1;
434
435         error = array[0] | (array[1] << 8);
436
437         printf("Panic code: 0x%02x (%s)\n", error,
438                                         error < 0x100 ? "valid" : "invalid");
439
440         return 0;
441 }
442
443 static int cmd_faultarg(int transport, int argc, char *argv[])
444 {
445         uint8_t array[8];
446         uint16_t error;
447         int err;
448
449         OPT_HELP(0, NULL);
450
451         memset(array, 0, sizeof(array));
452
453         err = transport_read(transport, CSR_VARID_FAULT_ARG, array, 8);
454         if (err < 0)
455                 return -1;
456
457         error = array[0] | (array[1] << 8);
458
459         printf("Fault code: 0x%02x (%s)\n", error,
460                                         error < 0x100 ? "valid" : "invalid");
461
462         return 0;
463 }
464
465 static int cmd_coldreset(int transport, int argc, char *argv[])
466 {
467         return transport_write(transport, CSR_VARID_COLD_RESET, NULL, 0);
468 }
469
470 static int cmd_warmreset(int transport, int argc, char *argv[])
471 {
472         return transport_write(transport, CSR_VARID_WARM_RESET, NULL, 0);
473 }
474
475 static int cmd_disabletx(int transport, int argc, char *argv[])
476 {
477         return transport_write(transport, CSR_VARID_DISABLE_TX, NULL, 0);
478 }
479
480 static int cmd_enabletx(int transport, int argc, char *argv[])
481 {
482         return transport_write(transport, CSR_VARID_ENABLE_TX, NULL, 0);
483 }
484
485 static int cmd_singlechan(int transport, int argc, char *argv[])
486 {
487         uint8_t array[8];
488         uint16_t channel;
489
490         OPT_HELP(1, NULL);
491
492         channel = atoi(argv[0]);
493
494         if (channel > 2401 && channel < 2481)
495                 channel -= 2402;
496
497         if (channel > 78) {
498                 errno = EINVAL;
499                 return -1;
500         }
501
502         memset(array, 0, sizeof(array));
503         array[0] = channel & 0xff;
504         array[1] = channel >> 8;
505
506         return transport_write(transport, CSR_VARID_SINGLE_CHAN, array, 8);
507 }
508
509 static int cmd_hoppingon(int transport, int argc, char *argv[])
510 {
511         return transport_write(transport, CSR_VARID_HOPPING_ON, NULL, 0);
512 }
513
514 static int cmd_rttxdata1(int transport, int argc, char *argv[])
515 {
516         uint8_t array[8];
517         uint16_t freq, level;
518
519         OPT_HELP(2, NULL);
520
521         freq = atoi(argv[0]);
522
523         if (!strncasecmp(argv[1], "0x", 2))
524                 level = strtol(argv[1], NULL, 16);
525         else
526                 level = atoi(argv[1]);
527
528         memset(array, 0, sizeof(array));
529         array[0] = 0x04;
530         array[1] = 0x00;
531         array[2] = freq & 0xff;
532         array[3] = freq >> 8;
533         array[4] = level & 0xff;
534         array[5] = level >> 8;
535
536         return transport_write(transport, CSR_VARID_RADIOTEST, array, 8);
537 }
538
539 static int cmd_radiotest(int transport, int argc, char *argv[])
540 {
541         uint8_t array[8];
542         uint16_t freq, level, test;
543
544         OPT_HELP(3, NULL);
545
546         freq = atoi(argv[0]);
547
548         if (!strncasecmp(argv[1], "0x", 2))
549                 level = strtol(argv[1], NULL, 16);
550         else
551                 level = atoi(argv[1]);
552
553         test = atoi(argv[2]);
554
555         memset(array, 0, sizeof(array));
556         array[0] = test & 0xff;
557         array[1] = test >> 8;
558         array[2] = freq & 0xff;
559         array[3] = freq >> 8;
560         array[4] = level & 0xff;
561         array[5] = level >> 8;
562
563         return transport_write(transport, CSR_VARID_RADIOTEST, array, 8);
564 }
565
566 static int cmd_memtypes(int transport, int argc, char *argv[])
567 {
568         uint8_t array[8];
569         uint16_t type, stores[4] = { 0x0001, 0x0002, 0x0004, 0x0008 };
570         int i, err;
571
572         OPT_HELP(0, NULL);
573
574         for (i = 0; i < 4; i++) {
575                 memset(array, 0, sizeof(array));
576                 array[0] = stores[i] & 0xff;
577                 array[1] = stores[i] >> 8;
578
579                 err = transport_read(transport, CSR_VARID_PS_MEMORY_TYPE, array, 8);
580                 if (err < 0)
581                         continue;
582
583                 type = array[2] + (array[3] << 8);
584
585                 printf("%s (0x%04x) = %s (%d)\n", storestostr(stores[i]),
586                                         stores[i], memorytostr(type), type);
587         }
588
589         return 0;
590 }
591
592 static struct option pskey_options[] = {
593         { "stores",     1, 0, 's' },
594         { "reset",      0, 0, 'r' },
595         { "help",       0, 0, 'h' },
596         { 0, 0, 0, 0 }
597 };
598
599 static int opt_pskey(int argc, char *argv[], uint16_t *stores, int *reset, int *help)
600 {
601         int opt;
602
603         while ((opt=getopt_long(argc, argv, "+s:rh", pskey_options, NULL)) != EOF) {
604                 switch (opt) {
605                 case 's':
606                         if (!stores)
607                                 break;
608                         if (!strcasecmp(optarg, "default"))
609                                 *stores = 0x0000;
610                         else if (!strcasecmp(optarg, "implementation"))
611                                 *stores = 0x0001;
612                         else if (!strcasecmp(optarg, "factory"))
613                                 *stores = 0x0002;
614                         else if (!strcasecmp(optarg, "rom"))
615                                 *stores = 0x0004;
616                         else if (!strcasecmp(optarg, "ram"))
617                                 *stores = 0x0008;
618                         else if (!strcasecmp(optarg, "psi"))
619                                 *stores = 0x0001;
620                         else if (!strcasecmp(optarg, "psf"))
621                                 *stores = 0x0002;
622                         else if (!strcasecmp(optarg, "psrom"))
623                                 *stores = 0x0004;
624                         else if (!strcasecmp(optarg, "psram"))
625                                 *stores = 0x0008;
626                         else if (!strncasecmp(optarg, "0x", 2))
627                                 *stores = strtol(optarg, NULL, 16);
628                         else
629                                 *stores = atoi(optarg);
630                         break;
631
632                 case 'r':
633                         if (reset)
634                                 *reset = 1;
635                         break;
636
637                 case 'h':
638                         if (help)
639                                 *help = 1;
640                         break;
641                 }
642         }
643
644         return optind;
645 }
646
647 #define OPT_PSKEY(min, max, stores, reset, help) \
648                 opt_pskey(argc, argv, (stores), (reset), (help)); \
649                 argc -= optind; argv += optind; optind = 0; \
650                 OPT_RANGE((min), (max))
651
652 static int cmd_psget(int transport, int argc, char *argv[])
653 {
654         uint8_t array[128];
655         uint16_t pskey, length, value, stores = CSR_STORES_DEFAULT;
656         uint32_t val32;
657         int i, err, reset = 0;
658
659         memset(array, 0, sizeof(array));
660
661         OPT_PSKEY(1, 1, &stores, &reset, NULL);
662
663         if (strncasecmp(argv[0], "0x", 2)) {
664                 pskey = atoi(argv[0]);
665
666                 for (i = 0; storage[i].pskey; i++) {
667                         if (strcasecmp(storage[i].str, argv[0]))
668                                 continue;
669
670                         pskey = storage[i].pskey;
671                         break;
672                 }
673         } else
674                 pskey = strtol(argv[0] + 2, NULL, 16);
675
676         memset(array, 0, sizeof(array));
677         array[0] = pskey & 0xff;
678         array[1] = pskey >> 8;
679         array[2] = stores & 0xff;
680         array[3] = stores >> 8;
681
682         err = transport_read(transport, CSR_VARID_PS_SIZE, array, 8);
683         if (err < 0)
684                 return err;
685
686         length = array[2] + (array[3] << 8);
687         if (length + 6 > (int) sizeof(array) / 2)
688                 return -EIO;
689
690         memset(array, 0, sizeof(array));
691         array[0] = pskey & 0xff;
692         array[1] = pskey >> 8;
693         array[2] = length & 0xff;
694         array[3] = length >> 8;
695         array[4] = stores & 0xff;
696         array[5] = stores >> 8;
697
698         err = transport_read(transport, CSR_VARID_PS, array, (length + 3) * 2);
699         if (err < 0)
700                 return err;
701
702         switch (length) {
703         case 1:
704                 value = array[6] | (array[7] << 8);
705                 printf("%s: 0x%04x (%d)\n", csr_pskeytostr(pskey), value, value);
706                 break;
707
708         case 2:
709                 val32 = array[8] | (array[9] << 8) | (array[6] << 16) | (array[7] << 24);
710                 printf("%s: 0x%08x (%d)\n", csr_pskeytostr(pskey), val32, val32);
711                 break;
712
713         default:
714                 printf("%s:", csr_pskeytostr(pskey));
715                 for (i = 0; i < length; i++)
716                         printf(" 0x%02x%02x", array[(i * 2) + 6], array[(i * 2) + 7]);
717                 printf("\n");
718                 break;
719         }
720
721         if (reset)
722                 transport_write(transport, CSR_VARID_WARM_RESET, NULL, 0);
723
724         return err;
725 }
726
727 static int cmd_psset(int transport, int argc, char *argv[])
728 {
729         uint8_t array[128];
730         uint16_t pskey, length, value, stores = CSR_STORES_PSRAM;
731         uint32_t val32;
732         int i, err, reset = 0;
733
734         memset(array, 0, sizeof(array));
735
736         OPT_PSKEY(2, 81, &stores, &reset, NULL);
737
738         if (strncasecmp(argv[0], "0x", 2)) {
739                 pskey = atoi(argv[0]);
740
741                 for (i = 0; storage[i].pskey; i++) {
742                         if (strcasecmp(storage[i].str, argv[0]))
743                                 continue;
744
745                         pskey = storage[i].pskey;
746                         break;
747                 }
748         } else
749                 pskey = strtol(argv[0] + 2, NULL, 16);
750
751         memset(array, 0, sizeof(array));
752         array[0] = pskey & 0xff;
753         array[1] = pskey >> 8;
754         array[2] = stores & 0xff;
755         array[3] = stores >> 8;
756
757         err = transport_read(transport, CSR_VARID_PS_SIZE, array, 8);
758         if (err < 0)
759                 return err;
760
761         length = array[2] + (array[3] << 8);
762         if (length + 6 > (int) sizeof(array) / 2)
763                 return -EIO;
764
765         memset(array, 0, sizeof(array));
766         array[0] = pskey & 0xff;
767         array[1] = pskey >> 8;
768         array[2] = length & 0xff;
769         array[3] = length >> 8;
770         array[4] = stores & 0xff;
771         array[5] = stores >> 8;
772
773         argc--;
774         argv++;
775
776         switch (length) {
777         case 1:
778                 if (argc != 1) {
779                         errno = E2BIG;
780                         return -1;
781                 }
782
783                 if (!strncasecmp(argv[0], "0x", 2))
784                         value = strtol(argv[0] + 2, NULL, 16);
785                 else
786                         value = atoi(argv[0]);
787
788                 array[6] = value & 0xff;
789                 array[7] = value >> 8;
790                 break;
791
792         case 2:
793                 if (argc != 1) {
794                         errno = E2BIG;
795                         return -1;
796                 }
797
798                 if (!strncasecmp(argv[0], "0x", 2))
799                         val32 = strtol(argv[0] + 2, NULL, 16);
800                 else
801                         val32 = atoi(argv[0]);
802
803                 array[6] = (val32 & 0xff0000) >> 16;
804                 array[7] = val32 >> 24;
805                 array[8] = val32 & 0xff;
806                 array[9] = (val32 & 0xff00) >> 8;
807                 break;
808
809         default:
810                 if (argc != length * 2) {
811                         errno = EINVAL;
812                         return -1;
813                 }
814
815                 for (i = 0; i < length * 2; i++)
816                         if (!strncasecmp(argv[0], "0x", 2))
817                                 array[i + 6] = strtol(argv[i] + 2, NULL, 16);
818                         else
819                                 array[i + 6] = atoi(argv[i]);
820                 break;
821         }
822
823         err = transport_write(transport, CSR_VARID_PS, array, (length + 3) * 2);
824         if (err < 0)
825                 return err;
826
827         if (reset)
828                 transport_write(transport, CSR_VARID_WARM_RESET, NULL, 0);
829
830         return err;
831 }
832
833 static int cmd_psclr(int transport, int argc, char *argv[])
834 {
835         uint8_t array[8];
836         uint16_t pskey, stores = CSR_STORES_PSRAM;
837         int i, err, reset = 0;
838
839         OPT_PSKEY(1, 1, &stores, &reset, NULL);
840
841         if (strncasecmp(argv[0], "0x", 2)) {
842                 pskey = atoi(argv[0]);
843
844                 for (i = 0; storage[i].pskey; i++) {
845                         if (strcasecmp(storage[i].str, argv[0]))
846                                 continue;
847
848                         pskey = storage[i].pskey;
849                         break;
850                 }
851         } else
852                 pskey = strtol(argv[0] + 2, NULL, 16);
853
854         memset(array, 0, sizeof(array));
855         array[0] = pskey & 0xff;
856         array[1] = pskey >> 8;
857         array[2] = stores & 0xff;
858         array[3] = stores >> 8;
859
860         err = transport_write(transport, CSR_VARID_PS_CLR_STORES, array, 8);
861         if (err < 0)
862                 return err;
863
864         if (reset)
865                 transport_write(transport, CSR_VARID_WARM_RESET, NULL, 0);
866
867         return err;
868 }
869
870 static int cmd_pslist(int transport, int argc, char *argv[])
871 {
872         uint8_t array[8];
873         uint16_t pskey = 0x0000, length, stores = CSR_STORES_DEFAULT;
874         int err, reset = 0;
875
876         OPT_PSKEY(0, 0, &stores, &reset, NULL);
877
878         while (1) {
879                 memset(array, 0, sizeof(array));
880                 array[0] = pskey & 0xff;
881                 array[1] = pskey >> 8;
882                 array[2] = stores & 0xff;
883                 array[3] = stores >> 8;
884
885                 err = transport_read(transport, CSR_VARID_PS_NEXT, array, 8);
886                 if (err < 0)
887                         break;
888
889                 pskey = array[4] + (array[5] << 8);
890                 if (pskey == 0x0000)
891                         break;
892
893                 memset(array, 0, sizeof(array));
894                 array[0] = pskey & 0xff;
895                 array[1] = pskey >> 8;
896                 array[2] = stores & 0xff;
897                 array[3] = stores >> 8;
898
899                 err = transport_read(transport, CSR_VARID_PS_SIZE, array, 8);
900                 if (err < 0)
901                         continue;
902
903                 length = array[2] + (array[3] << 8);
904
905                 printf("0x%04x - %s (%d bytes)\n", pskey,
906                                         csr_pskeytostr(pskey), length * 2);
907         }
908
909         if (reset)
910                 transport_write(transport, CSR_VARID_WARM_RESET, NULL, 0);
911
912         return 0;
913 }
914
915 static int cmd_psread(int transport, int argc, char *argv[])
916 {
917         uint8_t array[256];
918         uint16_t pskey = 0x0000, length, stores = CSR_STORES_DEFAULT;
919         char *str, val[7];
920         int i, err, reset = 0;
921
922         OPT_PSKEY(0, 0, &stores, &reset, NULL);
923
924         while (1) {
925                 memset(array, 0, sizeof(array));
926                 array[0] = pskey & 0xff;
927                 array[1] = pskey >> 8;
928                 array[2] = stores & 0xff;
929                 array[3] = stores >> 8;
930
931                 err = transport_read(transport, CSR_VARID_PS_NEXT, array, 8);
932                 if (err < 0)
933                         break;
934
935                 pskey = array[4] + (array[5] << 8);
936                 if (pskey == 0x0000)
937                         break;
938
939                 memset(array, 0, sizeof(array));
940                 array[0] = pskey & 0xff;
941                 array[1] = pskey >> 8;
942                 array[2] = stores & 0xff;
943                 array[3] = stores >> 8;
944
945                 err = transport_read(transport, CSR_VARID_PS_SIZE, array, 8);
946                 if (err < 0)
947                         continue;
948
949                 length = array[2] + (array[3] << 8);
950                 if (length + 6 > (int) sizeof(array) / 2)
951                         continue;
952
953                 memset(array, 0, sizeof(array));
954                 array[0] = pskey & 0xff;
955                 array[1] = pskey >> 8;
956                 array[2] = length & 0xff;
957                 array[3] = length >> 8;
958                 array[4] = stores & 0xff;
959                 array[5] = stores >> 8;
960
961                 err = transport_read(transport, CSR_VARID_PS, array, (length + 3) * 2);
962                 if (err < 0)
963                         continue;
964
965                 str = csr_pskeytoval(pskey);
966                 if (!strcasecmp(str, "UNKNOWN")) {
967                         sprintf(val, "0x%04x", pskey);
968                         str = NULL;
969                 }
970
971                 printf("// %s%s\n&%04x =", str ? "PSKEY_" : "",
972                                                 str ? str : val, pskey);
973                 for (i = 0; i < length; i++)
974                         printf(" %02x%02x", array[(i * 2) + 7], array[(i * 2) + 6]);
975                 printf("\n");
976         }
977
978         if (reset)
979                 transport_write(transport, CSR_VARID_WARM_RESET, NULL, 0);
980
981         return 0;
982 }
983
984 static int cmd_psload(int transport, int argc, char *argv[])
985 {
986         uint8_t array[256];
987         uint16_t pskey, length, size, stores = CSR_STORES_PSRAM;
988         char *str, val[7];
989         int err, reset = 0;
990
991         OPT_PSKEY(1, 1, &stores, &reset, NULL);
992
993         psr_read(argv[0]);
994
995         memset(array, 0, sizeof(array));
996         size = sizeof(array) - 6;
997
998         while (psr_get(&pskey, array + 6, &size) == 0) {
999                 str = csr_pskeytoval(pskey);
1000                 if (!strcasecmp(str, "UNKNOWN")) {
1001                         sprintf(val, "0x%04x", pskey);
1002                         str = NULL;
1003                 }
1004
1005                 printf("Loading %s%s ... ", str ? "PSKEY_" : "",
1006                                                         str ? str : val);
1007                 fflush(stdout);
1008
1009                 length = size / 2;
1010
1011                 array[0] = pskey & 0xff;
1012                 array[1] = pskey >> 8;
1013                 array[2] = length & 0xff;
1014                 array[3] = length >> 8;
1015                 array[4] = stores & 0xff;
1016                 array[5] = stores >> 8;
1017
1018                 err = transport_write(transport, CSR_VARID_PS, array, size + 6);
1019
1020                 printf("%s\n", err < 0 ? "failed" : "done");
1021
1022                 memset(array, 0, sizeof(array));
1023                 size = sizeof(array) - 6;
1024         }
1025
1026         if (reset)
1027                 transport_write(transport, CSR_VARID_WARM_RESET, NULL, 0);
1028
1029         return 0;
1030 }
1031
1032 static int cmd_pscheck(int transport, int argc, char *argv[])
1033 {
1034         uint8_t array[256];
1035         uint16_t pskey, size;
1036         int i;
1037
1038         OPT_HELP(1, NULL);
1039
1040         psr_read(argv[0]);
1041
1042         while (psr_get(&pskey, array, &size) == 0) {
1043                 printf("0x%04x =", pskey);
1044                 for (i = 0; i < size; i++)
1045                         printf(" 0x%02x", array[i]);
1046                 printf("\n");
1047         }
1048
1049         return 0;
1050 }
1051
1052 static struct {
1053         char *str;
1054         int (*func)(int transport, int argc, char *argv[]);
1055         char *arg;
1056         char *doc;
1057 } commands[] = {
1058         { "builddef",  cmd_builddef,  "",                    "Get build definitions"          },
1059         { "keylen",    cmd_keylen,    "<handle>",            "Get current crypt key length"   },
1060         { "clock",     cmd_clock,     "",                    "Get local Bluetooth clock"      },
1061         { "rand",      cmd_rand,      "",                    "Get random number"              },
1062         { "chiprev",   cmd_chiprev,   "",                    "Get chip revision"              },
1063         { "buildname", cmd_buildname, "",                    "Get the full build name"        },
1064         { "panicarg",  cmd_panicarg,  "",                    "Get panic code argument"        },
1065         { "faultarg",  cmd_faultarg,  "",                    "Get fault code argument"        },
1066         { "coldreset", cmd_coldreset, "",                    "Perform cold reset"             },
1067         { "warmreset", cmd_warmreset, "",                    "Perform warm reset"             },
1068         { "disabletx", cmd_disabletx, "",                    "Disable TX on the device"       },
1069         { "enabletx",  cmd_enabletx,  "",                    "Enable TX on the device"        },
1070         { "singlechan",cmd_singlechan,"<channel>",           "Lock radio on specific channel" },
1071         { "hoppingon", cmd_hoppingon, "",                    "Revert to channel hopping"      },
1072         { "rttxdata1", cmd_rttxdata1, "<freq> <level>",      "TXData1 radio test"             },
1073         { "radiotest", cmd_radiotest, "<freq> <level> <id>", "Run radio tests"                },
1074         { "memtypes",  cmd_memtypes,  NULL,                  "Get memory types"               },
1075         { "psget",     cmd_psget,     "<key>",               "Get value for PS key"           },
1076         { "psset",     cmd_psset,     "<key> <value>",       "Set value for PS key"           },
1077         { "psclr",     cmd_psclr,     "<key>",               "Clear value for PS key"         },
1078         { "pslist",    cmd_pslist,    NULL,                  "List all PS keys"               },
1079         { "psread",    cmd_psread,    NULL,                  "Read all PS keys"               },
1080         { "psload",    cmd_psload,    "<file>",              "Load all PS keys from PSR file" },
1081         { "pscheck",   cmd_pscheck,   "<file>",              "Check PSR file"                 },
1082         { NULL }
1083 };
1084
1085 static void usage(void)
1086 {
1087         int i, pos = 0;
1088
1089         printf("bccmd - Utility for the CSR BCCMD interface\n\n");
1090         printf("Usage:\n"
1091                 "\tbccmd [options] <command>\n\n");
1092
1093         printf("Options:\n"
1094                 "\t-t <transport>     Select the transport\n"
1095                 "\t-d <device>        Select the device\n"
1096                 "\t-b <bcsp rate>     Select the bcsp transfer rate\n"
1097                 "\t-h, --help         Display help\n"
1098                 "\n");
1099
1100         printf("Transports:\n"
1101                 "\tHCI USB BCSP H4 3WIRE\n\n");
1102
1103         printf("Commands:\n");
1104         for (i = 0; commands[i].str; i++)
1105                 printf("\t%-10s %-20s\t%s\n", commands[i].str,
1106                 commands[i].arg ? commands[i].arg : " ",
1107                 commands[i].doc);
1108         printf("\n");
1109
1110         printf("Keys:\n\t");
1111         for (i = 0; storage[i].pskey; i++) {
1112                 printf("%s ", storage[i].str);
1113                 pos += strlen(storage[i].str) + 1;
1114                 if (pos > 60) {
1115                         printf("\n\t");
1116                         pos = 0;
1117                 }
1118         }
1119         printf("\n");
1120 }
1121
1122 static struct option main_options[] = {
1123         { "transport",  1, 0, 't' },
1124         { "device",     1, 0, 'd' },
1125         { "bcsprate", 1, 0, 'b'},
1126         { "help",       0, 0, 'h' },
1127         { 0, 0, 0, 0 }
1128 };
1129
1130 int main(int argc, char *argv[])
1131 {
1132         char *device = NULL;
1133         int i, err, opt, transport = CSR_TRANSPORT_HCI;
1134         speed_t bcsp_rate = B38400;
1135
1136         while ((opt=getopt_long(argc, argv, "+t:d:i:b:h", main_options, NULL)) != EOF) {
1137                 switch (opt) {
1138                 case 't':
1139                         if (!strcasecmp(optarg, "hci"))
1140                                 transport = CSR_TRANSPORT_HCI;
1141                         else if (!strcasecmp(optarg, "usb"))
1142                                 transport = CSR_TRANSPORT_USB;
1143                         else if (!strcasecmp(optarg, "bcsp"))
1144                                 transport = CSR_TRANSPORT_BCSP;
1145                         else if (!strcasecmp(optarg, "h4"))
1146                                 transport = CSR_TRANSPORT_H4;
1147                         else if (!strcasecmp(optarg, "h5"))
1148                                 transport = CSR_TRANSPORT_3WIRE;
1149                         else if (!strcasecmp(optarg, "3wire"))
1150                                 transport = CSR_TRANSPORT_3WIRE;
1151                         else if (!strcasecmp(optarg, "twutl"))
1152                                 transport = CSR_TRANSPORT_3WIRE;
1153                         else
1154                                 transport = CSR_TRANSPORT_UNKNOWN;
1155                         break;
1156
1157                 case 'd':
1158                 case 'i':
1159                         device = strdup(optarg);
1160                         break;
1161                 case 'b':
1162                         switch (atoi(optarg)) {
1163                         case 9600: bcsp_rate = B9600; break;
1164                         case 19200: bcsp_rate = B19200; break;
1165                         case 38400: bcsp_rate = B38400; break;
1166                         case 57600: bcsp_rate = B57600; break;
1167                         case 115200: bcsp_rate = B115200; break;
1168                         case 230400: bcsp_rate = B230400; break;
1169                         case 460800: bcsp_rate = B460800; break;
1170                         case 500000: bcsp_rate = B500000; break;
1171                         case 576000: bcsp_rate = B576000; break;
1172                         case 921600: bcsp_rate = B921600; break;
1173                         case 1000000: bcsp_rate = B1000000; break;
1174                         case 1152000: bcsp_rate = B1152000; break;
1175                         case 1500000: bcsp_rate = B1500000; break;
1176                         case 2000000: bcsp_rate = B2000000; break;
1177 #ifdef B2500000
1178                         case 2500000: bcsp_rate = B2500000; break;
1179 #endif
1180 #ifdef B3000000
1181                         case 3000000: bcsp_rate = B3000000; break;
1182 #endif
1183 #ifdef B3500000
1184                         case 3500000: bcsp_rate = B3500000; break;
1185 #endif
1186 #ifdef B4000000
1187                         case 4000000: bcsp_rate = B4000000; break;
1188 #endif
1189                         default:
1190                                 printf("Unknown BCSP baud rate specified, defaulting to 38400bps\n");
1191                                 bcsp_rate = B38400;
1192                         }
1193                         break;
1194                 case 'h':
1195                 default:
1196                         usage();
1197                         exit(0);
1198                 }
1199         }
1200
1201         argc -= optind;
1202         argv += optind;
1203         optind = 0;
1204
1205         if (argc < 1) {
1206                 usage();
1207                 exit(1);
1208         }
1209
1210         if (transport_open(transport, device, bcsp_rate) < 0)
1211                 exit(1);
1212
1213         free(device);
1214
1215         for (i = 0; commands[i].str; i++) {
1216                 if (strcasecmp(commands[i].str, argv[0]))
1217                         continue;
1218
1219                 err = commands[i].func(transport, argc, argv);
1220
1221                 transport_close(transport);
1222
1223                 if (err < 0) {
1224                         fprintf(stderr, "Can't execute command: %s (%d)\n",
1225                                                         strerror(errno), errno);
1226                         exit(1);
1227                 }
1228
1229                 exit(0);
1230         }
1231
1232         fprintf(stderr, "Unsupported command\n");
1233
1234         transport_close(transport);
1235
1236         exit(1);
1237 }