xref: /btstack/chipset/csr/btstack_chipset_csr.c (revision ab2c6ae4b737d5e801d3defe4117331eb244ebb7)
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
23faa6c1f6SMatthias Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
24faa6c1f6SMatthias Ringwald  * RINGWALD 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 
38*ab2c6ae4SMatthias Ringwald #define __BTSTACK_FILE__ "btstack_chipset_csr.c"
39*ab2c6ae4SMatthias 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 
58faa6c1f6SMatthias Ringwald // minimal CSR init script to configure PSKEYs and activate them
59faa6c1f6SMatthias Ringwald static const uint8_t init_script[] = {
60fc62ef06SMatthias Ringwald 
61fc62ef06SMatthias Ringwald     //  Set ANA_Freq to 26MHz
62faa6c1f6SMatthias Ringwald     0x01, 0x00, 0xFC, 0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x01, 0x00, 0x03, 0x70, 0x00, 0x00, 0xfe, 0x01, 0x01, 0x00, 0x00, 0x00, 0x90, 0x65,
63fc62ef06SMatthias Ringwald 
64faa6c1f6SMatthias Ringwald     //  Set HCI_NOP_DISABLE
65faa6c1f6SMatthias Ringwald     0x01, 0x00, 0xFC, 0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x01, 0x00, 0x03, 0x70, 0x00, 0x00, 0xf2, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,
66fc62ef06SMatthias Ringwald 
6771c4de7aSMatthias Ringwald #ifdef ENABLE_SCO_OVER_HCI
68fc62ef06SMatthias Ringwald     // Set HOSTIO_MAP_SCO_PCM to 0
69fc62ef06SMatthias Ringwald     0x01, 0x00, 0xFC, 0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x01, 0x00, 0x03, 0x70, 0x00, 0x00, 0xab, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
7026a5de6fSMatthias Ringwald     // Set HOSTIO_MAP_SCO_CODEC to 0
7126a5de6fSMatthias Ringwald     0x01, 0x00, 0xFC, 0x13, 0xc2, 0x00, 0x00, 0x09, 0x00, 0x03, 0x00, 0x03, 0x70, 0x00, 0x00, 0xb0, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
72fc62ef06SMatthias Ringwald     // Set ENABLE_SCO_STREAMS to 0
73fc62ef06SMatthias Ringwald     0x01, 0x00, 0xFC, 0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x01, 0x00, 0x03, 0x70, 0x00, 0x00, 0xc9, 0x22, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
74fc62ef06SMatthias Ringwald #endif
75fc62ef06SMatthias Ringwald 
7635dfa651SMatthias Ringwald     // Enable RTS/CTS for BCSP (0806 -> 080e)
7735dfa651SMatthias Ringwald     0x01, 0x00, 0xFC, 0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x01, 0x00, 0x03, 0x70, 0x00, 0x00, 0xbf, 0x01, 0x01, 0x00, 0x00, 0x00, 0x0e, 0x08,
7835dfa651SMatthias Ringwald 
7935dfa651SMatthias Ringwald     // Enable RTS/CTS for H5 (1806 -> 180e, even parity still on)
8005b338c5SMatthias Ringwald     0x01, 0x00, 0xFC, 0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x01, 0x00, 0x03, 0x70, 0x00, 0x00, 0xc1, 0x01, 0x01, 0x00, 0x00, 0x00, 0x0e, 0x18,
8135dfa651SMatthias Ringwald 
82faa6c1f6SMatthias Ringwald     //  Set UART baudrate to 115200
83faa6c1f6SMatthias Ringwald     0x01, 0x00, 0xFC, 0x15, 0xc2, 0x02, 0x00, 0x0a, 0x00, 0x02, 0x00, 0x03, 0x70, 0x00, 0x00, 0xea, 0x01, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xc2,
84fc62ef06SMatthias Ringwald 
85faa6c1f6SMatthias Ringwald     //  WarmReset
86faa6c1f6SMatthias Ringwald     0x01, 0x00, 0xFC, 0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x03, 0x0e, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
87faa6c1f6SMatthias Ringwald };
88faa6c1f6SMatthias Ringwald static const uint16_t init_script_size = sizeof(init_script);
89faa6c1f6SMatthias Ringwald 
90faa6c1f6SMatthias Ringwald //
91faa6c1f6SMatthias Ringwald static uint32_t init_script_offset  = 0;
92faa6c1f6SMatthias Ringwald static hci_transport_config_uart_t * hci_transport_config_uart = NULL;
93faa6c1f6SMatthias Ringwald 
94fb55bd0aSMatthias Ringwald static void chipset_init(const void * config){
95faa6c1f6SMatthias Ringwald     init_script_offset = 0;
96faa6c1f6SMatthias Ringwald     hci_transport_config_uart = NULL;
97faa6c1f6SMatthias Ringwald     // check for hci_transport_config_uart_t
98faa6c1f6SMatthias Ringwald     if (!config) return;
99faa6c1f6SMatthias Ringwald     if (((hci_transport_config_t*)config)->type != HCI_TRANSPORT_CONFIG_UART) return;
100faa6c1f6SMatthias Ringwald     hci_transport_config_uart = (hci_transport_config_uart_t*) config;
101faa6c1f6SMatthias Ringwald }
102faa6c1f6SMatthias Ringwald 
103faa6c1f6SMatthias Ringwald // set requested baud rate
104faa6c1f6SMatthias Ringwald static void update_init_script_command(uint8_t *hci_cmd_buffer){
105f8fbdce0SMatthias Ringwald     uint16_t varid = little_endian_read_16(hci_cmd_buffer, 10);
106faa6c1f6SMatthias Ringwald     if (varid != 0x7003) return;
107f8fbdce0SMatthias Ringwald     uint16_t key = little_endian_read_16(hci_cmd_buffer, 14);
108fc62ef06SMatthias Ringwald     log_info("csr: pskey 0x%04x", key);
109faa6c1f6SMatthias Ringwald     if (key != 0x01ea) return;
110faa6c1f6SMatthias Ringwald 
111faa6c1f6SMatthias Ringwald     // check for baud rate
112faa6c1f6SMatthias Ringwald     if (!hci_transport_config_uart) return;
113faa6c1f6SMatthias Ringwald     uint32_t baudrate = hci_transport_config_uart->baudrate_main;
114faa6c1f6SMatthias Ringwald     if (baudrate == 0){
115faa6c1f6SMatthias Ringwald         baudrate = hci_transport_config_uart->baudrate_init;
116faa6c1f6SMatthias Ringwald     }
117faa6c1f6SMatthias Ringwald     // uint32_t is stored as 2 x uint16_t with most important 16 bits first
118f8fbdce0SMatthias Ringwald     little_endian_store_16(hci_cmd_buffer, 20, baudrate >> 16);
119f8fbdce0SMatthias Ringwald     little_endian_store_16(hci_cmd_buffer, 22, baudrate &  0xffff);
120faa6c1f6SMatthias Ringwald }
121faa6c1f6SMatthias Ringwald 
122faa6c1f6SMatthias Ringwald static btstack_chipset_result_t chipset_next_command(uint8_t * hci_cmd_buffer){
123faa6c1f6SMatthias Ringwald 
124faa6c1f6SMatthias Ringwald     if (init_script_offset >= init_script_size) {
125faa6c1f6SMatthias Ringwald         return BTSTACK_CHIPSET_DONE;
126faa6c1f6SMatthias Ringwald     }
127faa6c1f6SMatthias Ringwald 
128faa6c1f6SMatthias Ringwald     // init script is stored with the HCI Command Packet Type
129faa6c1f6SMatthias Ringwald     init_script_offset++;
130faa6c1f6SMatthias Ringwald     // copy command header
131faa6c1f6SMatthias Ringwald     memcpy(&hci_cmd_buffer[0], (uint8_t *) &init_script[init_script_offset], 3);
132faa6c1f6SMatthias Ringwald     init_script_offset += 3;
133faa6c1f6SMatthias Ringwald     int payload_len = hci_cmd_buffer[2];
134faa6c1f6SMatthias Ringwald     // copy command payload
135faa6c1f6SMatthias Ringwald     memcpy(&hci_cmd_buffer[3], (uint8_t *) &init_script[init_script_offset], payload_len);
136faa6c1f6SMatthias Ringwald 
137faa6c1f6SMatthias Ringwald     // support for on-the-fly configuration updates
138faa6c1f6SMatthias Ringwald     update_init_script_command(hci_cmd_buffer);
139faa6c1f6SMatthias Ringwald 
140faa6c1f6SMatthias Ringwald     init_script_offset += payload_len;
141faa6c1f6SMatthias Ringwald 
142faa6c1f6SMatthias Ringwald     // support for warm boot command
143f8fbdce0SMatthias Ringwald     uint16_t varid = little_endian_read_16(hci_cmd_buffer, 10);
144faa6c1f6SMatthias Ringwald     if (varid == 0x4002){
145faa6c1f6SMatthias Ringwald         return BTSTACK_CHIPSET_WARMSTART_REQUIRED;
146faa6c1f6SMatthias Ringwald     }
147faa6c1f6SMatthias Ringwald 
148faa6c1f6SMatthias Ringwald     return BTSTACK_CHIPSET_VALID_COMMAND;
149faa6c1f6SMatthias Ringwald }
150faa6c1f6SMatthias Ringwald 
151faa6c1f6SMatthias Ringwald 
152faa6c1f6SMatthias Ringwald static const btstack_chipset_t btstack_chipset_bcm = {
153593df0d9SMatthias Ringwald     "CSR",
154faa6c1f6SMatthias Ringwald     chipset_init,
155faa6c1f6SMatthias Ringwald     chipset_next_command,
156593df0d9SMatthias Ringwald     NULL, // chipset_set_baudrate_command,
157faa6c1f6SMatthias Ringwald     NULL, // chipset_set_bd_addr_command not supported or implemented
158faa6c1f6SMatthias Ringwald };
159faa6c1f6SMatthias Ringwald 
160faa6c1f6SMatthias Ringwald // MARK: public API
161faa6c1f6SMatthias Ringwald const btstack_chipset_t * btstack_chipset_csr_instance(void){
162faa6c1f6SMatthias Ringwald     return &btstack_chipset_bcm;
163faa6c1f6SMatthias Ringwald }
164