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