xref: /btstack/chipset/csr/btstack_chipset_csr.c (revision faa6c1f625806f77d213afda856e452e3e27fee8)
1*faa6c1f6SMatthias Ringwald /*
2*faa6c1f6SMatthias Ringwald  * Copyright (C) 2014 BlueKitchen GmbH
3*faa6c1f6SMatthias Ringwald  *
4*faa6c1f6SMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
5*faa6c1f6SMatthias Ringwald  * modification, are permitted provided that the following conditions
6*faa6c1f6SMatthias Ringwald  * are met:
7*faa6c1f6SMatthias Ringwald  *
8*faa6c1f6SMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
9*faa6c1f6SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
10*faa6c1f6SMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
11*faa6c1f6SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
12*faa6c1f6SMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
13*faa6c1f6SMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
14*faa6c1f6SMatthias Ringwald  *    contributors may be used to endorse or promote products derived
15*faa6c1f6SMatthias Ringwald  *    from this software without specific prior written permission.
16*faa6c1f6SMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
17*faa6c1f6SMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
18*faa6c1f6SMatthias Ringwald  *    monetary gain.
19*faa6c1f6SMatthias Ringwald  *
20*faa6c1f6SMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21*faa6c1f6SMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22*faa6c1f6SMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23*faa6c1f6SMatthias Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
24*faa6c1f6SMatthias Ringwald  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25*faa6c1f6SMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26*faa6c1f6SMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27*faa6c1f6SMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28*faa6c1f6SMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29*faa6c1f6SMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30*faa6c1f6SMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31*faa6c1f6SMatthias Ringwald  * SUCH DAMAGE.
32*faa6c1f6SMatthias Ringwald  *
33*faa6c1f6SMatthias Ringwald  * Please inquire about commercial licensing options at
34*faa6c1f6SMatthias Ringwald  * [email protected]
35*faa6c1f6SMatthias Ringwald  *
36*faa6c1f6SMatthias Ringwald  */
37*faa6c1f6SMatthias Ringwald 
38*faa6c1f6SMatthias Ringwald /*
39*faa6c1f6SMatthias Ringwald  *  bt_control_csr.c
40*faa6c1f6SMatthias Ringwald  *
41*faa6c1f6SMatthias Ringwald  *  Adapter to use CSR-based chipsets with BTstack
42*faa6c1f6SMatthias Ringwald  *
43*faa6c1f6SMatthias Ringwald  */
44*faa6c1f6SMatthias Ringwald 
45*faa6c1f6SMatthias Ringwald #include "bt_control_csr.h"
46*faa6c1f6SMatthias Ringwald 
47*faa6c1f6SMatthias Ringwald #include <stddef.h>   /* NULL */
48*faa6c1f6SMatthias Ringwald #include <stdio.h>
49*faa6c1f6SMatthias Ringwald #include <string.h>   /* memcpy */
50*faa6c1f6SMatthias Ringwald 
51*faa6c1f6SMatthias Ringwald #include "btstack_control.h"
52*faa6c1f6SMatthias Ringwald #include "btstack_debug.h"
53*faa6c1f6SMatthias Ringwald #include "btstack_util.h"
54*faa6c1f6SMatthias Ringwald #include "hci_transport.h"
55*faa6c1f6SMatthias Ringwald 
56*faa6c1f6SMatthias Ringwald // minimal CSR init script to configure PSKEYs and activate them
57*faa6c1f6SMatthias Ringwald static const uint8_t init_script[] = {
58*faa6c1f6SMatthias Ringwald     //  Set ANA_Freq PSKEY to 26MHz
59*faa6c1f6SMatthias Ringwald     0x01, 0x00, 0xFC, 0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x01, 0x00, 0x03, 0x70, 0x00, 0x00, 0xfe, 0x01, 0x01, 0x00, 0x00, 0x00, 0x90, 0x65,
60*faa6c1f6SMatthias Ringwald     //  Set HCI_NOP_DISABLE
61*faa6c1f6SMatthias Ringwald     0x01, 0x00, 0xFC, 0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x01, 0x00, 0x03, 0x70, 0x00, 0x00, 0xf2, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,
62*faa6c1f6SMatthias Ringwald     //  Set UART baudrate to 115200
63*faa6c1f6SMatthias 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,
64*faa6c1f6SMatthias Ringwald     //  WarmReset
65*faa6c1f6SMatthias Ringwald     0x01, 0x00, 0xFC, 0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x03, 0x0e, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
66*faa6c1f6SMatthias Ringwald };
67*faa6c1f6SMatthias Ringwald static const uint16_t init_script_size = sizeof(init_script);
68*faa6c1f6SMatthias Ringwald 
69*faa6c1f6SMatthias Ringwald //
70*faa6c1f6SMatthias Ringwald static uint32_t init_script_offset  = 0;
71*faa6c1f6SMatthias Ringwald static hci_transport_config_uart_t * hci_transport_config_uart = NULL;
72*faa6c1f6SMatthias Ringwald 
73*faa6c1f6SMatthias Ringwald static void chipset_init(void * config){
74*faa6c1f6SMatthias Ringwald     init_script_offset = 0;
75*faa6c1f6SMatthias Ringwald     hci_transport_config_uart = NULL;
76*faa6c1f6SMatthias Ringwald     // check for hci_transport_config_uart_t
77*faa6c1f6SMatthias Ringwald     if (!config) return;
78*faa6c1f6SMatthias Ringwald     if (((hci_transport_config_t*)config)->type != HCI_TRANSPORT_CONFIG_UART) return;
79*faa6c1f6SMatthias Ringwald     hci_transport_config_uart = (hci_transport_config_uart_t*) config;
80*faa6c1f6SMatthias Ringwald }
81*faa6c1f6SMatthias Ringwald 
82*faa6c1f6SMatthias Ringwald static void chipset_set_baudrate_command(uint32_t baudrate, uint8_t *hci_cmd_buffer){
83*faa6c1f6SMatthias Ringwald }
84*faa6c1f6SMatthias Ringwald 
85*faa6c1f6SMatthias Ringwald // set requested baud rate
86*faa6c1f6SMatthias Ringwald static void update_init_script_command(uint8_t *hci_cmd_buffer){
87*faa6c1f6SMatthias Ringwald     uint16_t varid = READ_BT_16(hci_cmd_buffer, 10);
88*faa6c1f6SMatthias Ringwald     if (varid != 0x7003) return;
89*faa6c1f6SMatthias Ringwald     uint16_t key = READ_BT_16(hci_cmd_buffer, 14);
90*faa6c1f6SMatthias Ringwald     if (key != 0x01ea) return;
91*faa6c1f6SMatthias Ringwald 
92*faa6c1f6SMatthias Ringwald     // check for baud rate
93*faa6c1f6SMatthias Ringwald     if (!hci_transport_config_uart) return;
94*faa6c1f6SMatthias Ringwald     uint32_t baudrate = hci_transport_config_uart->baudrate_main;
95*faa6c1f6SMatthias Ringwald     if (baudrate == 0){
96*faa6c1f6SMatthias Ringwald         baudrate = hci_transport_config_uart->baudrate_init;
97*faa6c1f6SMatthias Ringwald     }
98*faa6c1f6SMatthias Ringwald     // uint32_t is stored as 2 x uint16_t with most important 16 bits first
99*faa6c1f6SMatthias Ringwald     bt_store_16(hci_cmd_buffer, 20, baudrate >> 16);
100*faa6c1f6SMatthias Ringwald     bt_store_16(hci_cmd_buffer, 22, baudrate &  0xffff);
101*faa6c1f6SMatthias Ringwald }
102*faa6c1f6SMatthias Ringwald 
103*faa6c1f6SMatthias Ringwald static btstack_chipset_result_t chipset_next_command(uint8_t * hci_cmd_buffer){
104*faa6c1f6SMatthias Ringwald 
105*faa6c1f6SMatthias Ringwald     if (init_script_offset >= init_script_size) {
106*faa6c1f6SMatthias Ringwald         return BTSTACK_CHIPSET_DONE;
107*faa6c1f6SMatthias Ringwald     }
108*faa6c1f6SMatthias Ringwald 
109*faa6c1f6SMatthias Ringwald     // init script is stored with the HCI Command Packet Type
110*faa6c1f6SMatthias Ringwald     init_script_offset++;
111*faa6c1f6SMatthias Ringwald     // copy command header
112*faa6c1f6SMatthias Ringwald     memcpy(&hci_cmd_buffer[0], (uint8_t *) &init_script[init_script_offset], 3);
113*faa6c1f6SMatthias Ringwald     init_script_offset += 3;
114*faa6c1f6SMatthias Ringwald     int payload_len = hci_cmd_buffer[2];
115*faa6c1f6SMatthias Ringwald     // copy command payload
116*faa6c1f6SMatthias Ringwald     memcpy(&hci_cmd_buffer[3], (uint8_t *) &init_script[init_script_offset], payload_len);
117*faa6c1f6SMatthias Ringwald 
118*faa6c1f6SMatthias Ringwald     // support for on-the-fly configuration updates
119*faa6c1f6SMatthias Ringwald     update_init_script_command(hci_cmd_buffer);
120*faa6c1f6SMatthias Ringwald 
121*faa6c1f6SMatthias Ringwald     init_script_offset += payload_len;
122*faa6c1f6SMatthias Ringwald 
123*faa6c1f6SMatthias Ringwald     // support for warm boot command
124*faa6c1f6SMatthias Ringwald     uint16_t varid = READ_BT_16(hci_cmd_buffer, 10);
125*faa6c1f6SMatthias Ringwald     log_info("csr: varid 0x%04x", varid);
126*faa6c1f6SMatthias Ringwald     if (varid == 0x4002){
127*faa6c1f6SMatthias Ringwald         return BTSTACK_CHIPSET_WARMSTART_REQUIRED;
128*faa6c1f6SMatthias Ringwald     }
129*faa6c1f6SMatthias Ringwald 
130*faa6c1f6SMatthias Ringwald     return BTSTACK_CHIPSET_VALID_COMMAND;
131*faa6c1f6SMatthias Ringwald }
132*faa6c1f6SMatthias Ringwald 
133*faa6c1f6SMatthias Ringwald 
134*faa6c1f6SMatthias Ringwald static const btstack_chipset_t btstack_chipset_bcm = {
135*faa6c1f6SMatthias Ringwald     "BCM",
136*faa6c1f6SMatthias Ringwald     chipset_init,
137*faa6c1f6SMatthias Ringwald     chipset_next_command,
138*faa6c1f6SMatthias Ringwald     chipset_set_baudrate_command,
139*faa6c1f6SMatthias Ringwald     NULL, // chipset_set_bd_addr_command not supported or implemented
140*faa6c1f6SMatthias Ringwald };
141*faa6c1f6SMatthias Ringwald 
142*faa6c1f6SMatthias Ringwald // MARK: public API
143*faa6c1f6SMatthias Ringwald const btstack_chipset_t * btstack_chipset_csr_instance(void){
144*faa6c1f6SMatthias Ringwald     return &btstack_chipset_bcm;
145*faa6c1f6SMatthias Ringwald }
146