xref: /btstack/chipset/csr/csr_set_bd_addr.c (revision ae46c388c2098a3d94131818a757b2f27eae5705)
1 /*
2  * Copyright (C) 2018 BlueKitchen GmbH
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the copyright holders nor the names of
14  *    contributors may be used to endorse or promote products derived
15  *    from this software without specific prior written permission.
16  * 4. Any redistribution, use, or modification is done solely for
17  *    personal benefit and not for any commercial purpose or for
18  *    monetary gain.
19  *
20  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
24  * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * Please inquire about commercial licensing options at
34  * [email protected]
35  *
36  */
37 
38 #define BTSTACK_FILE__ "csr_set_bd_addr.c"
39 
40 // *****************************************************************************
41 /* EXAMPLE_START(csr_set_bd_addr): Set BD ADDR on USB CSR modules
42  *
43  */
44 // *****************************************************************************
45 
46 #include <stdint.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50 
51 #include "btstack.h"
52 
53 static btstack_packet_callback_registration_t hci_event_callback_registration;
54 static bd_addr_t cmdline_addr;
55 static btstack_timer_source_t warm_boot_timer;
56 static int cmdline_addr_found;
57 static const char * prog_name;
58 
59 static uint8_t csr_set_bd_addr[] = {
60     // 0x0001: Set Bluetooth address
61     0x00, 0xFC, 0x19, 0xc2, 0x02, 0x00, 0x0A, 0x00, 0x03, 0x00, 0x03, 0x70, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0xf3, 0x00, 0xf5, 0xf4, 0xf2, 0x00, 0xf2, 0xf1,
62 };
63 
64 static uint8_t csr_warm_start[] = {
65     //  WarmReset
66     0x00, 0xFC, 0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x03, 0x0e, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
67 };
68 
usage(void)69 static void usage(void){
70     fprintf(stderr, "\nUsage: %s aa:bb:cc:dd:ee:ff\n", prog_name);
71     exit(0);
72 }
73 /* @section Bluetooth Logic
74  *
75  * @text The Bluetooth logic is implemented as a state machine within the packet
76  * handler. In this example, the following states are passed sequentially:
77  * INIT, and ACTIVE.
78  */
79 
local_version_information_handler(uint8_t * packet)80 static void local_version_information_handler(uint8_t * packet){
81     uint16_t hci_version    = packet[6];
82     uint16_t hci_revision   = little_endian_read_16(packet, 7);
83     uint16_t lmp_version    = packet[9];
84     uint16_t manufacturer   = little_endian_read_16(packet, 10);
85     uint16_t lmp_subversion = little_endian_read_16(packet, 12);
86     switch (manufacturer){
87         case BLUETOOTH_COMPANY_ID_CAMBRIDGE_SILICON_RADIO:
88             printf("Cambridge Silicon Radio - CSR chipset.\n");
89             break;
90         default:
91             printf("Local version information:\n");
92             printf("- HCI Version    0x%04x\n", hci_version);
93             printf("- HCI Revision   0x%04x\n", hci_revision);
94             printf("- LMP Version    0x%04x\n", lmp_version);
95             printf("- LMP Subversion 0x%04x\n", lmp_subversion);
96             printf("- Manufacturer   0x%04x\n", manufacturer);
97             printf("Not a CSR chipset, exit\n");
98             usage();
99             break;
100     }
101 }
102 
103 static int state = 0;
104 
warm_boot_handler(struct btstack_timer_source * ts)105 static void warm_boot_handler(struct btstack_timer_source *ts){
106     UNUSED(ts);
107 
108     if (state != 4) return;
109     printf("Done\n");
110     exit(0);
111 }
112 
packet_handler(uint8_t packet_type,uint16_t channel,uint8_t * packet,uint16_t size)113 static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
114     UNUSED(channel);
115     UNUSED(size);
116 
117     if (packet_type != HCI_EVENT_PACKET) return;
118 
119     switch(hci_event_packet_get_type(packet)){
120         case BTSTACK_EVENT_STATE:
121             if (btstack_event_state_get_state(packet) == HCI_STATE_WORKING){
122                 if (!cmdline_addr_found){
123                     usage();
124                     break;
125                 }
126                 printf("Setting BD ADDR to %s\n", bd_addr_to_str(cmdline_addr));
127                 state = 1;
128             }
129             break;
130             if (hci_event_command_complete_get_command_opcode(packet) == HCI_OPCODE_HCI_READ_LOCAL_VERSION_INFORMATION){
131                 local_version_information_handler(packet);
132             }
133             break;
134         case HCI_EVENT_VENDOR_SPECIFIC:
135             // Vendor event
136             state++;
137             break;
138         default:
139             break;
140     }
141 
142     if (!hci_can_send_command_packet_now()) return;
143     switch (state){
144         case 0:
145         case 2:
146             break;
147         case 1:
148             state++;
149             hci_send_cmd_packet(csr_set_bd_addr, sizeof(csr_set_bd_addr));
150             break;
151         case 3:
152             state++;
153             hci_send_cmd_packet(csr_warm_start, sizeof(csr_warm_start));
154             // set timer
155             warm_boot_timer.process = &warm_boot_handler;
156             btstack_run_loop_set_timer(&warm_boot_timer, 1000);
157             btstack_run_loop_add_timer(&warm_boot_timer);
158             break;
159         default:
160             break;
161     }
162 }
163 
164 
165 /* @section Main Application Setup
166  *
167  * @text Listing MainConfiguration shows main application code.
168  * It registers the HCI packet handler and starts the Bluetooth stack.
169  */
170 
171 /* LISTING_START(MainConfiguration): Setup packet handler for GAP inquiry */
172 int btstack_main(int argc, const char * argv[]);
btstack_main(int argc,const char * argv[])173 int btstack_main(int argc, const char * argv[]) {
174 
175     prog_name = argv[0];
176     if (argc > 1) {
177         cmdline_addr_found = sscanf_bd_addr(argv[1], cmdline_addr);
178     }
179 
180     if (cmdline_addr_found){
181         // prepare set bd addr command
182         csr_set_bd_addr[20] = cmdline_addr[3];
183         csr_set_bd_addr[22] = cmdline_addr[5];
184         csr_set_bd_addr[23] = cmdline_addr[4];
185         csr_set_bd_addr[24] = cmdline_addr[2];
186         csr_set_bd_addr[26] = cmdline_addr[1];
187         csr_set_bd_addr[27] = cmdline_addr[0];
188     }
189 
190     hci_event_callback_registration.callback = &packet_handler;
191     hci_add_event_handler(&hci_event_callback_registration);
192 
193     // turn on!
194     hci_power_control(HCI_POWER_ON);
195     return 0;
196 }
197 /* LISTING_END */
198 /* EXAMPLE_END */
199