1// Copyright 2018 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <assert.h>
6#include <ddk/binding.h>
7#include <ddk/debug.h>
8#include <ddk/device.h>
9#include <ddk/driver.h>
10#include <ddk/protocol/bt-hci.h>
11#include <ddk/protocol/platform-defs.h>
12#include <ddk/protocol/serial.h>
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <threads.h>
17#include <zircon/device/bt-hci.h>
18#include <zircon/status.h>
19#include <zircon/threads.h>
20
21// TODO: how can we parameterize this?
22#define TARGET_BAUD_RATE    2000000
23
24#define FIRMWARE_PATH "/boot/lib/firmware/BCM4345C4.bin"
25
26#define FIRMWARE_DOWNLOAD_DELAY ZX_MSEC(50)
27
28// Hardcoded. Better to paramaterize on chipset.
29// Broadcom chips need a few hundred msec delay
30// after firmware load
31#define BAUD_RATE_SWITCH_DELAY ZX_MSEC(200)
32
33typedef struct {
34    uint16_t opcode;
35    uint8_t parameter_total_size;
36} __PACKED hci_command_header_t;
37
38typedef struct {
39    uint8_t event_code;
40    uint8_t parameter_total_size;
41} __PACKED hci_event_header_t;
42
43typedef struct {
44    hci_event_header_t header;
45    uint8_t num_hci_command_packets;
46    uint16_t command_opcode;
47    uint8_t return_code;
48} __PACKED hci_command_complete_t;
49
50// HCI reset command
51const hci_command_header_t RESET_CMD = {
52    .opcode =  0x0c03,
53    .parameter_total_size = 0,
54};
55
56// vendor command to begin firmware download
57const hci_command_header_t START_FIRMWARE_DOWNLOAD_CMD = {
58    .opcode =  0xfc2e,
59    .parameter_total_size = 0,
60};
61
62typedef struct {
63    hci_command_header_t header;
64    uint16_t unused;
65    uint32_t baud_rate;
66} __PACKED bcm_set_baud_rate_cmd_t;
67#define BCM_SET_BAUD_RATE_CMD   0xfc18
68
69#define HCI_EVT_COMMAND_COMPLETE    0x0e
70
71typedef struct {
72    zx_device_t* zxdev;
73    zx_device_t* transport_dev;
74    bt_hci_protocol_t hci;
75    serial_protocol_t serial;
76    zx_handle_t command_channel;
77    bool is_uart;   // true if underlying transport is UART
78} bcm_hci_t;
79
80static zx_status_t bcm_hci_get_protocol(void* ctx, uint32_t proto_id, void* out_proto) {
81    if (proto_id != ZX_PROTOCOL_BT_HCI) {
82        return ZX_ERR_NOT_SUPPORTED;
83    }
84
85    bcm_hci_t* hci = ctx;
86    bt_hci_protocol_t* hci_proto = out_proto;
87
88    // Forward the underlying bt-transport ops.
89    hci_proto->ops = hci->hci.ops;
90    hci_proto->ctx = hci->hci.ctx;
91
92    return ZX_OK;
93}
94
95static zx_status_t bcm_hci_ioctl(void* ctx, uint32_t op, const void* in_buf, size_t in_len,
96                                 void* out_buf, size_t out_len, size_t* out_actual) {
97    bcm_hci_t* hci = ctx;
98    if (out_len < sizeof(zx_handle_t)) {
99        return ZX_ERR_BUFFER_TOO_SMALL;
100    }
101
102    zx_handle_t* reply = out_buf;
103
104    zx_status_t status = ZX_ERR_NOT_SUPPORTED;
105    if (op == IOCTL_BT_HCI_GET_COMMAND_CHANNEL) {
106        status = bt_hci_open_command_channel(&hci->hci, reply);
107    } else if (op == IOCTL_BT_HCI_GET_ACL_DATA_CHANNEL) {
108        status = bt_hci_open_acl_data_channel(&hci->hci, reply);
109    } else if (op == IOCTL_BT_HCI_GET_SNOOP_CHANNEL) {
110        status = bt_hci_open_snoop_channel(&hci->hci, reply);
111    }
112
113    if (status != ZX_OK) {
114        return status;
115    }
116
117    *out_actual = sizeof(*reply);
118    return ZX_OK;
119}
120
121static void bcm_hci_unbind(void* ctx) {
122    bcm_hci_t* hci = ctx;
123
124    device_remove(hci->zxdev);
125}
126
127static void bcm_hci_release(void* ctx) {
128    bcm_hci_t* hci = ctx;
129
130    if (hci->command_channel != ZX_HANDLE_INVALID) {
131        zx_handle_close(hci->command_channel);
132    }
133
134    free(hci);
135}
136
137static zx_protocol_device_t bcm_hci_device_proto = {
138    .version = DEVICE_OPS_VERSION,
139    .get_protocol = bcm_hci_get_protocol,
140    .ioctl = bcm_hci_ioctl,
141    .unbind = bcm_hci_unbind,
142    .release = bcm_hci_release,
143};
144
145
146static zx_status_t bcm_hci_send_command(bcm_hci_t* hci, const hci_command_header_t* command,
147                                        size_t length) {
148    // send HCI command
149    zx_status_t status = zx_channel_write(hci->command_channel, 0, command, length, NULL, 0);
150    if (status != ZX_OK) {
151        zxlogf(ERROR, "bcm_hci_send_command zx_channel_write failed %s\n",
152               zx_status_get_string(status));
153        return status;
154    }
155
156    // wait for command complete
157    uint8_t event_buf[255 + 2];
158    uint32_t actual;
159
160    do {
161        status = zx_channel_read(hci->command_channel, 0, event_buf, NULL, sizeof(event_buf), 0,
162                                 &actual, NULL);
163        if (status == ZX_ERR_SHOULD_WAIT) {
164            zx_object_wait_one(hci->command_channel, ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED,
165                               zx_deadline_after(ZX_SEC(5)), NULL);
166        }
167    } while (status == ZX_ERR_SHOULD_WAIT);
168
169    if (status != ZX_OK) {
170        zxlogf(ERROR, "bcm_hci_send_command zx_channel_read failed %s\n",
171               zx_status_get_string(status));
172        return status;
173    }
174
175    hci_event_header_t* header = (hci_event_header_t *)event_buf;
176    if (header->event_code != HCI_EVT_COMMAND_COMPLETE || header->parameter_total_size
177            != sizeof(hci_command_complete_t)  - sizeof(hci_event_header_t)) {
178        zxlogf(ERROR, "bcm_hci_send_command did not receive command complete\n");
179        return ZX_ERR_INTERNAL;
180    }
181    hci_command_complete_t* event = (hci_command_complete_t *)event_buf;
182    if (event->return_code != 0) {
183        zxlogf(ERROR, "bcm_hci_send_command got command complete error %u\n", event->return_code);
184        return ZX_ERR_INTERNAL;
185    }
186
187    return ZX_OK;
188}
189
190static zx_status_t bcm_hci_set_baud_rate(bcm_hci_t* hci, uint32_t baud_rate) {
191    bcm_set_baud_rate_cmd_t command = {
192        .header = {
193            .opcode =  BCM_SET_BAUD_RATE_CMD,
194            .parameter_total_size = sizeof(bcm_set_baud_rate_cmd_t) - sizeof(hci_command_header_t),
195        },
196        .unused = 0,
197        .baud_rate = htole32(baud_rate),
198    };
199
200    zx_status_t status = bcm_hci_send_command(hci, &command.header, sizeof(command));
201    if (status != ZX_OK) {
202        return status;
203    }
204
205    return serial_config(&hci->serial, TARGET_BAUD_RATE, SERIAL_SET_BAUD_RATE_ONLY);
206}
207
208
209static int bcm_hci_start_thread(void* arg) {
210    bcm_hci_t* hci = arg;
211    zx_handle_t fw_vmo;
212
213    zx_status_t status = bt_hci_open_command_channel(&hci->hci, &hci->command_channel);
214    if (status != ZX_OK) {
215        goto fail;
216    }
217
218    // Send Reset command
219    status = bcm_hci_send_command(hci, &RESET_CMD, sizeof(RESET_CMD));
220    if (status != ZX_OK) {
221        goto fail;
222    }
223
224    if (hci->is_uart) {
225        // switch baud rate to TARGET_BAUD_RATE
226        status = bcm_hci_set_baud_rate(hci, TARGET_BAUD_RATE);
227        if (status != ZX_OK) {
228            goto fail;
229        }
230    }
231
232    size_t fw_size;
233    status = load_firmware(hci->zxdev, FIRMWARE_PATH, &fw_vmo, &fw_size);
234    if (status == ZX_OK) {
235        status = bcm_hci_send_command(hci, &START_FIRMWARE_DOWNLOAD_CMD,
236                                      sizeof(START_FIRMWARE_DOWNLOAD_CMD));
237        if (status != ZX_OK) {
238            goto fail;
239        }
240
241        // give time for placing firmware in download mode
242        zx_nanosleep(zx_deadline_after(FIRMWARE_DOWNLOAD_DELAY));
243
244        zx_off_t offset = 0;
245        while (offset < fw_size) {
246            uint8_t buffer[255 + 3];
247
248            size_t remaining = fw_size - offset;
249            size_t read_amount = (remaining > sizeof(buffer) ? sizeof(buffer) : remaining);
250
251            if (read_amount < 3) {
252                zxlogf(ERROR, "short HCI command in firmware download\n");
253                status = ZX_ERR_INTERNAL;
254                goto vmo_close_fail;
255            }
256
257            status = zx_vmo_read(fw_vmo, buffer, offset, read_amount);
258            if (status != ZX_OK) {
259                goto vmo_close_fail;
260            }
261
262            hci_command_header_t* header = (hci_command_header_t *)buffer;
263            size_t length = header->parameter_total_size + sizeof(*header);
264             if (read_amount < length) {
265                zxlogf(ERROR, "short HCI command in firmware download\n");
266                status = ZX_ERR_INTERNAL;
267                goto vmo_close_fail;
268            }
269            status = bcm_hci_send_command(hci, header, length);
270            if (status != ZX_OK) {
271                zxlogf(ERROR, "bcm_hci_send_command failed in firmware download: %s\n",
272                       zx_status_get_string(status));
273                goto vmo_close_fail;
274            }
275            offset += length;
276        }
277
278        zx_handle_close(fw_vmo);
279
280        if (hci->is_uart) {
281            // firmware switched us back to 115200. switch back to TARGET_BAUD_RATE
282            status = serial_config(&hci->serial, 115200, SERIAL_SET_BAUD_RATE_ONLY);
283            if (status != ZX_OK) {
284                goto fail;
285            }
286
287            // switch baud rate to TARGET_BAUD_RATE after DELAY
288            zx_nanosleep(zx_deadline_after(BAUD_RATE_SWITCH_DELAY));
289            status = bcm_hci_set_baud_rate(hci, TARGET_BAUD_RATE);
290            if (status != ZX_OK) {
291                goto fail;
292            }
293        }
294    } else {
295        zxlogf(INFO, "bcm-hci: no firmware file found\n");
296    }
297
298    // We're done with the command channel. Close it so that it can be opened by
299    // the host stack after the device becomes visible.
300    zx_handle_close(hci->command_channel);
301    hci->command_channel = ZX_HANDLE_INVALID;
302
303    device_make_visible(hci->zxdev);
304    return 0;
305
306vmo_close_fail:
307    zx_handle_close(fw_vmo);
308fail:
309    zxlogf(ERROR, "bcm_hci_start_thread: device initialization failed: %s\n",
310           zx_status_get_string(status));
311
312    device_remove(hci->zxdev);
313    return -1;
314}
315
316static zx_status_t bcm_hci_bind(void* ctx, zx_device_t* device) {
317    bcm_hci_t* hci = calloc(1, sizeof(bcm_hci_t));
318    if (!hci) {
319        return ZX_ERR_NO_MEMORY;
320    }
321
322    zx_status_t status = device_get_protocol(device, ZX_PROTOCOL_BT_HCI, &hci->hci);
323    if (status != ZX_OK) {
324        zxlogf(ERROR, "bcm_hci_bind: get protocol ZX_PROTOCOL_BT_HCI failed\n");
325        return status;
326    }
327    status = device_get_protocol(device, ZX_PROTOCOL_SERIAL, &hci->serial);
328    if (status == ZX_OK) {
329        hci->is_uart = true;
330    }
331
332    device_add_args_t args = {
333        .version = DEVICE_ADD_ARGS_VERSION,
334        .name = "bcm-hci",
335        .ctx = hci,
336        .ops = &bcm_hci_device_proto,
337        .proto_id = ZX_PROTOCOL_BT_HCI,
338        .flags = DEVICE_ADD_INVISIBLE,
339    };
340
341    hci->transport_dev = device;
342
343    status = device_add(device, &args, &hci->zxdev);
344    if (status != ZX_OK) {
345        bcm_hci_release(hci);
346        return status;
347    }
348
349    // create thread to continue initialization
350    thrd_t t;
351    int thrd_rc = thrd_create_with_name(&t, bcm_hci_start_thread, hci, "bcm_hci_start_thread");
352    if (thrd_rc != thrd_success) {
353        device_remove(hci->zxdev);
354        bcm_hci_release(hci);
355        return thrd_status_to_zx_status(thrd_rc);
356    }
357
358    return ZX_OK;
359}
360
361static zx_driver_ops_t bcm_hci_driver_ops = {
362    .version = DRIVER_OPS_VERSION,
363    .bind = bcm_hci_bind,
364};
365
366// clang-format off
367ZIRCON_DRIVER_BEGIN(bcm_hci, bcm_hci_driver_ops, "zircon", "0.1", 2)
368    BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_BT_TRANSPORT),
369    BI_MATCH_IF(EQ, BIND_SERIAL_VID, PDEV_VID_BROADCOM),
370ZIRCON_DRIVER_END(bcm_hci)
371