156 lines
4 KiB
Diff
156 lines
4 KiB
Diff
Description: Patches for compatibility with on-board Bluetooth on RPi 3
|
|
Author: Simon Long <simon@raspberrypi.org>
|
|
Last-Update: 2017-04-05
|
|
|
|
--- a/tools/hciattach.c
|
|
+++ b/tools/hciattach.c
|
|
@@ -1091,6 +1091,9 @@
|
|
{ "bcm43xx", 0x0000, 0x0000, HCI_UART_H4, 115200, 3000000,
|
|
FLOW_CTL, DISABLE_PM, NULL, bcm43xx, NULL },
|
|
|
|
+ { "bcm43xx-3wire", 0x0000, 0x0000, HCI_UART_3WIRE, 115200, 3000000,
|
|
+ 0, DISABLE_PM, NULL, bcm43xx, NULL },
|
|
+
|
|
{ "ath3k", 0x0000, 0x0000, HCI_UART_ATH3K, 115200, 115200,
|
|
FLOW_CTL, DISABLE_PM, NULL, ath3k_ps, ath3k_pm },
|
|
|
|
@@ -1237,7 +1240,7 @@
|
|
{
|
|
struct uart_t *u = NULL;
|
|
int detach, printpid, raw, opt, i, n, ld, err;
|
|
- int to = 10;
|
|
+ int to = 30;
|
|
int init_speed = 0;
|
|
int send_break = 0;
|
|
pid_t pid;
|
|
--- a/tools/hciattach.h
|
|
+++ b/tools/hciattach.h
|
|
@@ -44,7 +45,7 @@
|
|
#define HCI_UART_VND_DETECT 5
|
|
|
|
#ifndef FIRMWARE_DIR
|
|
-#define FIRMWARE_DIR "/etc/firmware"
|
|
+#define FIRMWARE_DIR "/lib/firmware"
|
|
#endif
|
|
|
|
int read_hci_event(int fd, unsigned char *buf, int size);
|
|
--- a/tools/hciattach_bcm43xx.c
|
|
+++ b/tools/hciattach_bcm43xx.c
|
|
@@ -36,6 +36,7 @@
|
|
#include <dirent.h>
|
|
#include <time.h>
|
|
#include <limits.h>
|
|
+#include <sys/stat.h>
|
|
|
|
#include "lib/bluetooth.h"
|
|
#include "lib/hci.h"
|
|
@@ -303,9 +304,23 @@
|
|
static int bcm43xx_locate_patch(const char *dir_name,
|
|
const char *chip_name, char *location)
|
|
{
|
|
+ struct stat statbuf;
|
|
+ char path[PATH_MAX];
|
|
DIR *dir;
|
|
int ret = -1;
|
|
|
|
+ /* Try an exact match before scanning, otherwise a board without a specific
|
|
+ * firmware/link may end up loading a specific firmware for another board
|
|
+ * just because it is encountered first.
|
|
+ */
|
|
+ if (snprintf(path, PATH_MAX, "%s/%s%s", dir_name, chip_name, FW_EXT) < 0)
|
|
+ return -1;
|
|
+ if ((stat(path, &statbuf) == 0) && S_ISREG(statbuf.st_mode)) {
|
|
+ strcpy(location, path);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ /* Now search subdirectories and files with suffixes */
|
|
dir = opendir(dir_name);
|
|
if (!dir) {
|
|
fprintf(stderr, "Cannot open directory '%s': %s\n",
|
|
@@ -320,8 +335,6 @@
|
|
break;
|
|
|
|
if (entry->d_type & DT_DIR) {
|
|
- char path[PATH_MAX];
|
|
-
|
|
if (!strcmp(entry->d_name, "..") || !strcmp(entry->d_name, "."))
|
|
continue;
|
|
|
|
@@ -341,8 +354,10 @@
|
|
break;
|
|
|
|
/* found */
|
|
- snprintf(location, PATH_MAX, "%s/%s", dir_name, entry->d_name);
|
|
- ret = 0;
|
|
+ if (snprintf(location, PATH_MAX, "%s/%s", dir_name, entry->d_name) < 0)
|
|
+ ret = -1;
|
|
+ else
|
|
+ ret = 0;
|
|
break;
|
|
}
|
|
}
|
|
@@ -352,11 +367,32 @@
|
|
return ret;
|
|
}
|
|
|
|
+static int get_board_type(char *buf, int buf_size)
|
|
+{
|
|
+ int bytes_read;
|
|
+ int len;
|
|
+ int fd;
|
|
+
|
|
+ fd = open("/sys/firmware/devicetree/base/compatible", O_RDONLY);
|
|
+ if (fd < 0)
|
|
+ return -1;
|
|
+
|
|
+ bytes_read = read(fd, buf, buf_size);
|
|
+ close(fd);
|
|
+ if (bytes_read < 0)
|
|
+ return -1;
|
|
+
|
|
+ len = strnlen(buf, buf_size);
|
|
+ return (len < buf_size) ? len : -1;
|
|
+}
|
|
+
|
|
int bcm43xx_init(int fd, int def_speed, int speed, struct termios *ti,
|
|
const char *bdaddr)
|
|
{
|
|
char chip_name[20];
|
|
+ char board_specific_name[sizeof(chip_name) + 64];
|
|
char fw_path[PATH_MAX];
|
|
+ int chip_name_len;
|
|
|
|
printf("bcm43xx_init\n");
|
|
|
|
@@ -366,12 +402,17 @@
|
|
if (bcm43xx_read_local_name(fd, chip_name, sizeof(chip_name)))
|
|
return -1;
|
|
|
|
- if (bcm43xx_locate_patch(FIRMWARE_DIR, chip_name, fw_path)) {
|
|
- fprintf(stderr, "Patch not found, continue anyway\n");
|
|
+ /* Grab the board compatible string from Device Tree */
|
|
+ chip_name_len = strlen(chip_name);
|
|
+ memcpy(board_specific_name, chip_name, chip_name_len);
|
|
+ board_specific_name[chip_name_len++] = '.';
|
|
+
|
|
+ if (((get_board_type(board_specific_name + chip_name_len,
|
|
+ sizeof(board_specific_name) - chip_name_len) < 0) ||
|
|
+ bcm43xx_locate_patch(FIRMWARE_DIR, board_specific_name, fw_path)) &&
|
|
+ bcm43xx_locate_patch(FIRMWARE_DIR, chip_name, fw_path)) {
|
|
+ fprintf(stderr, "Patch not found for %s, continue anyway\n", chip_name);
|
|
} else {
|
|
- if (bcm43xx_set_speed(fd, ti, speed))
|
|
- return -1;
|
|
-
|
|
if (bcm43xx_load_firmware(fd, fw_path))
|
|
return -1;
|
|
|
|
@@ -381,6 +422,7 @@
|
|
return -1;
|
|
}
|
|
|
|
+ sleep(1);
|
|
if (bcm43xx_reset(fd))
|
|
return -1;
|
|
}
|