xref: /btstack/chipset/csr/btstack_chipset_csr.c (revision 2fca4dad957cd7b88f4657ed51e89c12615dda72)
1faa6c1f6SMatthias Ringwald /*
2faa6c1f6SMatthias Ringwald  * Copyright (C) 2014 BlueKitchen GmbH
3faa6c1f6SMatthias Ringwald  *
4faa6c1f6SMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
5faa6c1f6SMatthias Ringwald  * modification, are permitted provided that the following conditions
6faa6c1f6SMatthias Ringwald  * are met:
7faa6c1f6SMatthias Ringwald  *
8faa6c1f6SMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
9faa6c1f6SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
10faa6c1f6SMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
11faa6c1f6SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
12faa6c1f6SMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
13faa6c1f6SMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
14faa6c1f6SMatthias Ringwald  *    contributors may be used to endorse or promote products derived
15faa6c1f6SMatthias Ringwald  *    from this software without specific prior written permission.
16faa6c1f6SMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
17faa6c1f6SMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
18faa6c1f6SMatthias Ringwald  *    monetary gain.
19faa6c1f6SMatthias Ringwald  *
20faa6c1f6SMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21faa6c1f6SMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22faa6c1f6SMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23*2fca4dadSMilanka Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
24*2fca4dadSMilanka Ringwald  * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25faa6c1f6SMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26faa6c1f6SMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27faa6c1f6SMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28faa6c1f6SMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29faa6c1f6SMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30faa6c1f6SMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31faa6c1f6SMatthias Ringwald  * SUCH DAMAGE.
32faa6c1f6SMatthias Ringwald  *
33faa6c1f6SMatthias Ringwald  * Please inquire about commercial licensing options at
34faa6c1f6SMatthias Ringwald  * [email protected]
35faa6c1f6SMatthias Ringwald  *
36faa6c1f6SMatthias Ringwald  */
37faa6c1f6SMatthias Ringwald 
38e501bae0SMatthias Ringwald #define BTSTACK_FILE__ "btstack_chipset_csr.c"
39ab2c6ae4SMatthias Ringwald 
40faa6c1f6SMatthias Ringwald /*
41fb55bd0aSMatthias Ringwald  *  btstack_chipset_csr.c
42faa6c1f6SMatthias Ringwald  *
43faa6c1f6SMatthias Ringwald  *  Adapter to use CSR-based chipsets with BTstack
44fc62ef06SMatthias Ringwald  *  SCO over HCI doesn't work over H4 connection and BTM805 module from Microchip Bluetooth Audio Developer Kit (CSR8811)
45faa6c1f6SMatthias Ringwald  */
46faa6c1f6SMatthias Ringwald 
47fb55bd0aSMatthias Ringwald #include "btstack_chipset_csr.h"
48faa6c1f6SMatthias Ringwald 
49faa6c1f6SMatthias Ringwald #include <stddef.h>   /* NULL */
50faa6c1f6SMatthias Ringwald #include <stdio.h>
51faa6c1f6SMatthias Ringwald #include <string.h>   /* memcpy */
52faa6c1f6SMatthias Ringwald 
53faa6c1f6SMatthias Ringwald #include "btstack_control.h"
54faa6c1f6SMatthias Ringwald #include "btstack_debug.h"
55faa6c1f6SMatthias Ringwald #include "btstack_util.h"
56faa6c1f6SMatthias Ringwald #include "hci_transport.h"
57faa6c1f6SMatthias Ringwald 
5877b95b41SMatthias Ringwald enum update_result {
5977b95b41SMatthias Ringwald     OK,
6077b95b41SMatthias Ringwald     SKIP,
6177b95b41SMatthias Ringwald };
6277b95b41SMatthias Ringwald 
638c41f31fSMatthias Ringwald // minimal CSR init script to configure PSKEYs and activate them. It uses store 0x0008 = psram.
64faa6c1f6SMatthias Ringwald static const uint8_t init_script[] = {
65fc62ef06SMatthias Ringwald 
6677b95b41SMatthias Ringwald     // 0x01fe: Set ANA_Freq to 26MHz
678c41f31fSMatthias Ringwald     0x00, 0xFC, 0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x01, 0x00, 0x03, 0x70, 0x00, 0x00, 0xfe, 0x01, 0x01, 0x00, 0x08, 0x00, 0x90, 0x65,
68fc62ef06SMatthias Ringwald 
6977b95b41SMatthias Ringwald     // 0x00f2: Set HCI_NOP_DISABLE
708c41f31fSMatthias Ringwald     0x00, 0xFC, 0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x01, 0x00, 0x03, 0x70, 0x00, 0x00, 0xf2, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00,
71fc62ef06SMatthias Ringwald 
7271c4de7aSMatthias Ringwald #ifdef ENABLE_SCO_OVER_HCI
7377b95b41SMatthias Ringwald     // 0x01ab: Set HOSTIO_MAP_SCO_PCM to 0
748c41f31fSMatthias Ringwald     0x00, 0xFC, 0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x01, 0x00, 0x03, 0x70, 0x00, 0x00, 0xab, 0x01, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00,
7577b95b41SMatthias Ringwald     // 0x01b0: Set HOSTIO_MAP_SCO_CODEC to 0
768c41f31fSMatthias Ringwald     0x00, 0xFC, 0x13, 0xc2, 0x00, 0x00, 0x09, 0x00, 0x03, 0x00, 0x03, 0x70, 0x00, 0x00, 0xb0, 0x01, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00,
7777b95b41SMatthias Ringwald     // 0x22c9: Set ENABLE_SCO_STREAMS to 0
788c41f31fSMatthias Ringwald     0x00, 0xFC, 0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x01, 0x00, 0x03, 0x70, 0x00, 0x00, 0xc9, 0x22, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00,
79fc62ef06SMatthias Ringwald #endif
80fc62ef06SMatthias Ringwald 
8177b95b41SMatthias Ringwald     // 0x01bf: Enable RTS/CTS for BCSP (0806 -> 080e)
828c41f31fSMatthias Ringwald     0x00, 0xFC, 0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x01, 0x00, 0x03, 0x70, 0x00, 0x00, 0xbf, 0x01, 0x01, 0x00, 0x08, 0x00, 0x0e, 0x08,
8335dfa651SMatthias Ringwald 
8477b95b41SMatthias Ringwald     // 0x01ea: Set UART baudrate to 115200
858c41f31fSMatthias Ringwald     0x00, 0xFC, 0x15, 0xc2, 0x02, 0x00, 0x0a, 0x00, 0x02, 0x00, 0x03, 0x70, 0x00, 0x00, 0xea, 0x01, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0xc2,
8677b95b41SMatthias Ringwald 
8777b95b41SMatthias Ringwald     // 0x0001: Set Bluetooth address
888c41f31fSMatthias Ringwald     0x00, 0xFC, 0x19, 0xc2, 0x02, 0x00, 0x0A, 0x00, 0x03, 0x00, 0x03, 0x70, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x08, 0x00, 0xf3, 0x00, 0xf5, 0xf4, 0xf2, 0x00, 0xf2, 0xf1,
89fc62ef06SMatthias Ringwald 
90faa6c1f6SMatthias Ringwald     //  WarmReset
918c41f31fSMatthias Ringwald     0x00, 0xFC, 0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x03, 0x0e, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
92faa6c1f6SMatthias Ringwald };
93faa6c1f6SMatthias Ringwald static const uint16_t init_script_size = sizeof(init_script);
94faa6c1f6SMatthias Ringwald 
95faa6c1f6SMatthias Ringwald //
96faa6c1f6SMatthias Ringwald static uint32_t init_script_offset  = 0;
97faa6c1f6SMatthias Ringwald static hci_transport_config_uart_t * hci_transport_config_uart = NULL;
9877b95b41SMatthias Ringwald static int       set_bd_addr;
9977b95b41SMatthias Ringwald static bd_addr_t bd_addr;
100faa6c1f6SMatthias Ringwald 
chipset_init(const void * config)101fb55bd0aSMatthias Ringwald static void chipset_init(const void * config){
102faa6c1f6SMatthias Ringwald     init_script_offset = 0;
103faa6c1f6SMatthias Ringwald     hci_transport_config_uart = NULL;
104faa6c1f6SMatthias Ringwald     // check for hci_transport_config_uart_t
105faa6c1f6SMatthias Ringwald     if (!config) return;
106faa6c1f6SMatthias Ringwald     if (((hci_transport_config_t*)config)->type != HCI_TRANSPORT_CONFIG_UART) return;
107faa6c1f6SMatthias Ringwald     hci_transport_config_uart = (hci_transport_config_uart_t*) config;
108faa6c1f6SMatthias Ringwald }
109faa6c1f6SMatthias Ringwald 
110faa6c1f6SMatthias Ringwald // set requested baud rate
11177b95b41SMatthias Ringwald // @return 0 = OK, 1 = SKIP, 2 = ..
update_init_script_command(uint8_t * hci_cmd_buffer)11277b95b41SMatthias Ringwald static enum update_result update_init_script_command(uint8_t *hci_cmd_buffer){
113f8fbdce0SMatthias Ringwald     uint16_t varid = little_endian_read_16(hci_cmd_buffer, 10);
11477b95b41SMatthias Ringwald     if (varid != 0x7003) return OK;
115f8fbdce0SMatthias Ringwald     uint16_t key = little_endian_read_16(hci_cmd_buffer, 14);
116fc62ef06SMatthias Ringwald     log_info("csr: pskey 0x%04x", key);
11777b95b41SMatthias Ringwald     switch (key){
11877b95b41SMatthias Ringwald         case 0x001:
11977b95b41SMatthias Ringwald             // set bd addr command
12077b95b41SMatthias Ringwald             if (!set_bd_addr) return SKIP;
12177b95b41SMatthias Ringwald             hci_cmd_buffer[20] = bd_addr[3];
12277b95b41SMatthias Ringwald             hci_cmd_buffer[22] = bd_addr[5];
12377b95b41SMatthias Ringwald             hci_cmd_buffer[23] = bd_addr[4];
12477b95b41SMatthias Ringwald             hci_cmd_buffer[24] = bd_addr[2];
12577b95b41SMatthias Ringwald             hci_cmd_buffer[26] = bd_addr[1];
12677b95b41SMatthias Ringwald             hci_cmd_buffer[27] = bd_addr[0];
12777b95b41SMatthias Ringwald             return OK;
12877b95b41SMatthias Ringwald         case 0x01ea:
12977b95b41SMatthias Ringwald             // baud rate command
13077b95b41SMatthias Ringwald             if (!hci_transport_config_uart) return OK;
131faa6c1f6SMatthias Ringwald             uint32_t baudrate = hci_transport_config_uart->baudrate_main;
132faa6c1f6SMatthias Ringwald             if (baudrate == 0){
133faa6c1f6SMatthias Ringwald                 baudrate = hci_transport_config_uart->baudrate_init;
134faa6c1f6SMatthias Ringwald             }
135faa6c1f6SMatthias Ringwald             // uint32_t is stored as 2 x uint16_t with most important 16 bits first
136f8fbdce0SMatthias Ringwald             little_endian_store_16(hci_cmd_buffer, 20, baudrate >> 16);
137f8fbdce0SMatthias Ringwald             little_endian_store_16(hci_cmd_buffer, 22, baudrate &  0xffff);
13877b95b41SMatthias Ringwald             break;
13977b95b41SMatthias Ringwald         default:
14077b95b41SMatthias Ringwald             break;
14177b95b41SMatthias Ringwald     }
14277b95b41SMatthias Ringwald     return OK;
143faa6c1f6SMatthias Ringwald }
144faa6c1f6SMatthias Ringwald 
chipset_next_command(uint8_t * hci_cmd_buffer)145faa6c1f6SMatthias Ringwald static btstack_chipset_result_t chipset_next_command(uint8_t * hci_cmd_buffer){
146faa6c1f6SMatthias Ringwald 
147ff3cc4a5SMatthias Ringwald     while (true){
14877b95b41SMatthias Ringwald 
149faa6c1f6SMatthias Ringwald         if (init_script_offset >= init_script_size) {
150faa6c1f6SMatthias Ringwald             return BTSTACK_CHIPSET_DONE;
151faa6c1f6SMatthias Ringwald         }
152faa6c1f6SMatthias Ringwald 
153faa6c1f6SMatthias Ringwald         // copy command header
154faa6c1f6SMatthias Ringwald         memcpy(&hci_cmd_buffer[0], (uint8_t *) &init_script[init_script_offset], 3);
155faa6c1f6SMatthias Ringwald         init_script_offset += 3;
156faa6c1f6SMatthias Ringwald         int payload_len = hci_cmd_buffer[2];
157faa6c1f6SMatthias Ringwald         // copy command payload
158faa6c1f6SMatthias Ringwald         memcpy(&hci_cmd_buffer[3], (uint8_t *) &init_script[init_script_offset], payload_len);
159faa6c1f6SMatthias Ringwald 
160faa6c1f6SMatthias Ringwald         // support for on-the-fly configuration updates
16177b95b41SMatthias Ringwald         enum update_result res = update_init_script_command(hci_cmd_buffer);
162faa6c1f6SMatthias Ringwald         init_script_offset += payload_len;
163faa6c1f6SMatthias Ringwald 
16477b95b41SMatthias Ringwald         // support for skipping commands
16577b95b41SMatthias Ringwald         if (res == SKIP) continue;
16677b95b41SMatthias Ringwald 
167faa6c1f6SMatthias Ringwald         // support for warm boot command
168f8fbdce0SMatthias Ringwald         uint16_t varid = little_endian_read_16(hci_cmd_buffer, 10);
169faa6c1f6SMatthias Ringwald         if (varid == 0x4002){
170faa6c1f6SMatthias Ringwald             return BTSTACK_CHIPSET_WARMSTART_REQUIRED;
171faa6c1f6SMatthias Ringwald         }
172faa6c1f6SMatthias Ringwald 
173faa6c1f6SMatthias Ringwald         return BTSTACK_CHIPSET_VALID_COMMAND;
174faa6c1f6SMatthias Ringwald     }
17577b95b41SMatthias Ringwald }
176faa6c1f6SMatthias Ringwald 
177faa6c1f6SMatthias Ringwald 
178faa6c1f6SMatthias Ringwald static const btstack_chipset_t btstack_chipset_bcm = {
179593df0d9SMatthias Ringwald     "CSR",
180faa6c1f6SMatthias Ringwald     chipset_init,
181faa6c1f6SMatthias Ringwald     chipset_next_command,
182593df0d9SMatthias Ringwald     NULL, // chipset_set_baudrate_command,
183faa6c1f6SMatthias Ringwald     NULL, // chipset_set_bd_addr_command not supported or implemented
184faa6c1f6SMatthias Ringwald };
185faa6c1f6SMatthias Ringwald 
186faa6c1f6SMatthias Ringwald // MARK: public API
btstack_chipset_csr_instance(void)187faa6c1f6SMatthias Ringwald const btstack_chipset_t * btstack_chipset_csr_instance(void){
188faa6c1f6SMatthias Ringwald     return &btstack_chipset_bcm;
189faa6c1f6SMatthias Ringwald }
19077b95b41SMatthias Ringwald 
19177b95b41SMatthias Ringwald /**
19277b95b41SMatthias Ringwald  * Set BD ADDR before HCI POWER_ON
19377b95b41SMatthias Ringwald  * @param bd_addr
19477b95b41SMatthias Ringwald  */
btstack_chipset_csr_set_bd_addr(bd_addr_t new_bd_addr)19577b95b41SMatthias Ringwald void btstack_chipset_csr_set_bd_addr(bd_addr_t new_bd_addr){
19677b95b41SMatthias Ringwald     set_bd_addr = 1;
19777b95b41SMatthias Ringwald     memcpy(bd_addr, new_bd_addr, 6);
19877b95b41SMatthias Ringwald }
199