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 MATTHIAS 24 * RINGWALD 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 #include "btstack_chipset_csr.h" 53 54 static btstack_packet_callback_registration_t hci_event_callback_registration; 55 static bd_addr_t cmdline_addr = { }; 56 static btstack_timer_source_t warm_boot_timer; 57 static int cmdline_addr_found; 58 static const char * prog_name; 59 60 static uint8_t csr_set_bd_addr[] = { 61 // 0x0001: Set Bluetooth address 62 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, 63 }; 64 65 static uint8_t csr_warm_start[] = { 66 // WarmReset 67 0x00, 0xFC, 0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x03, 0x0e, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 68 }; 69 70 static void usage(void){ 71 fprintf(stderr, "\nUsage: %s aa:bb:cc:dd:ee:ff\n", prog_name); 72 exit(0); 73 } 74 /* @section Bluetooth Logic 75 * 76 * @text The Bluetooth logic is implemented as a state machine within the packet 77 * handler. In this example, the following states are passed sequentially: 78 * INIT, and ACTIVE. 79 */ 80 81 static void local_version_information_handler(uint8_t * packet){ 82 uint16_t hci_version = packet[6]; 83 uint16_t hci_revision = little_endian_read_16(packet, 7); 84 uint16_t lmp_version = packet[9]; 85 uint16_t manufacturer = little_endian_read_16(packet, 10); 86 uint16_t lmp_subversion = little_endian_read_16(packet, 12); 87 switch (manufacturer){ 88 case BLUETOOTH_COMPANY_ID_CAMBRIDGE_SILICON_RADIO: 89 printf("Cambridge Silicon Radio - CSR chipset.\n"); 90 break; 91 default: 92 printf("Local version information:\n"); 93 printf("- HCI Version 0x%04x\n", hci_version); 94 printf("- HCI Revision 0x%04x\n", hci_revision); 95 printf("- LMP Version 0x%04x\n", lmp_version); 96 printf("- LMP Subversion 0x%04x\n", lmp_subversion); 97 printf("- Manufacturer 0x%04x\n", manufacturer); 98 printf("Not a CSR chipset, exit\n"); 99 usage(); 100 break; 101 } 102 } 103 104 static int state = 0; 105 106 static void warm_boot_handler(struct btstack_timer_source *ts){ 107 UNUSED(ts); 108 109 if (state != 4) return; 110 printf("Done\n"); 111 exit(0); 112 } 113 114 static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 115 UNUSED(channel); 116 UNUSED(size); 117 118 if (packet_type != HCI_EVENT_PACKET) return; 119 120 switch(hci_event_packet_get_type(packet)){ 121 case BTSTACK_EVENT_STATE: 122 if (btstack_event_state_get_state(packet) == HCI_STATE_WORKING){ 123 if (!cmdline_addr_found){ 124 usage(); 125 break; 126 } 127 printf("Setting BD ADDR to %s\n", bd_addr_to_str(cmdline_addr)); 128 state = 1; 129 } 130 break; 131 case HCI_EVENT_COMMAND_COMPLETE: 132 if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_version_information)){ 133 local_version_information_handler(packet); 134 } 135 break; 136 case HCI_EVENT_VENDOR_SPECIFIC: 137 // Vendor event 138 state++; 139 break; 140 default: 141 break; 142 } 143 144 if (!hci_can_send_command_packet_now()) return; 145 switch (state){ 146 case 0: 147 case 2: 148 break; 149 case 1: 150 state++; 151 hci_send_cmd_packet(csr_set_bd_addr, sizeof(csr_set_bd_addr)); 152 break; 153 case 3: 154 state++; 155 hci_send_cmd_packet(csr_warm_start, sizeof(csr_warm_start)); 156 // set timer 157 warm_boot_timer.process = &warm_boot_handler; 158 btstack_run_loop_set_timer(&warm_boot_timer, 1000); 159 btstack_run_loop_add_timer(&warm_boot_timer); 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[]); 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