hciattach_bcm43xx.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. *
  4. * BlueZ - Bluetooth protocol stack for Linux
  5. *
  6. * Copyright (C) 2014 Intel Corporation. All rights reserved.
  7. *
  8. *
  9. */
  10. #ifdef HAVE_CONFIG_H
  11. #include <config.h>
  12. #endif
  13. #define _GNU_SOURCE
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <unistd.h>
  17. #include <termios.h>
  18. #include <fcntl.h>
  19. #include <unistd.h>
  20. #include <errno.h>
  21. #include <dirent.h>
  22. #include <time.h>
  23. #include <limits.h>
  24. #include "lib/bluetooth.h"
  25. #include "lib/hci.h"
  26. #include "lib/hci_lib.h"
  27. #include "hciattach.h"
  28. #ifndef FIRMWARE_DIR
  29. #define FIRMWARE_DIR "/etc/firmware"
  30. #endif
  31. #define FW_EXT ".hcd"
  32. #define BCM43XX_CLOCK_48 1
  33. #define BCM43XX_CLOCK_24 2
  34. #define CMD_SUCCESS 0x00
  35. #define CC_MIN_SIZE 7
  36. #define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
  37. static int bcm43xx_read_local_name(int fd, char *name, size_t size)
  38. {
  39. unsigned char cmd[] = { HCI_COMMAND_PKT, 0x14, 0x0C, 0x00 };
  40. unsigned char *resp;
  41. unsigned int name_len;
  42. resp = malloc(size + CC_MIN_SIZE);
  43. if (!resp)
  44. return -1;
  45. tcflush(fd, TCIOFLUSH);
  46. if (write(fd, cmd, sizeof(cmd)) != sizeof(cmd)) {
  47. fprintf(stderr, "Failed to write read local name command\n");
  48. goto fail;
  49. }
  50. if (read_hci_event(fd, resp, size) < CC_MIN_SIZE) {
  51. fprintf(stderr, "Failed to read local name, invalid HCI event\n");
  52. goto fail;
  53. }
  54. if (resp[4] != cmd[1] || resp[5] != cmd[2] || resp[6] != CMD_SUCCESS) {
  55. fprintf(stderr, "Failed to read local name, command failure\n");
  56. goto fail;
  57. }
  58. name_len = resp[2] - 1;
  59. strncpy(name, (char *) &resp[7], MIN(name_len, size));
  60. name[size - 1] = 0;
  61. free(resp);
  62. return 0;
  63. fail:
  64. free(resp);
  65. return -1;
  66. }
  67. static int bcm43xx_reset(int fd)
  68. {
  69. unsigned char cmd[] = { HCI_COMMAND_PKT, 0x03, 0x0C, 0x00 };
  70. unsigned char resp[CC_MIN_SIZE];
  71. if (write(fd, cmd, sizeof(cmd)) != sizeof(cmd)) {
  72. fprintf(stderr, "Failed to write reset command\n");
  73. return -1;
  74. }
  75. if (read_hci_event(fd, resp, sizeof(resp)) < CC_MIN_SIZE) {
  76. fprintf(stderr, "Failed to reset chip, invalid HCI event\n");
  77. return -1;
  78. }
  79. if (resp[4] != cmd[1] || resp[5] != cmd[2] || resp[6] != CMD_SUCCESS) {
  80. fprintf(stderr, "Failed to reset chip, command failure\n");
  81. return -1;
  82. }
  83. return 0;
  84. }
  85. static int bcm43xx_set_bdaddr(int fd, const char *bdaddr)
  86. {
  87. unsigned char cmd[] =
  88. { HCI_COMMAND_PKT, 0x01, 0xfc, 0x06, 0x00, 0x00,
  89. 0x00, 0x00, 0x00, 0x00 };
  90. unsigned char resp[CC_MIN_SIZE];
  91. printf("Set BDADDR UART: %s\n", bdaddr);
  92. if (str2ba(bdaddr, (bdaddr_t *) (&cmd[4])) < 0) {
  93. fprintf(stderr, "Incorrect bdaddr\n");
  94. return -1;
  95. }
  96. tcflush(fd, TCIOFLUSH);
  97. if (write(fd, cmd, sizeof(cmd)) != sizeof(cmd)) {
  98. fprintf(stderr, "Failed to write set bdaddr command\n");
  99. return -1;
  100. }
  101. if (read_hci_event(fd, resp, sizeof(resp)) < CC_MIN_SIZE) {
  102. fprintf(stderr, "Failed to set bdaddr, invalid HCI event\n");
  103. return -1;
  104. }
  105. if (resp[4] != cmd[1] || resp[5] != cmd[2] || resp[6] != CMD_SUCCESS) {
  106. fprintf(stderr, "Failed to set bdaddr, command failure\n");
  107. return -1;
  108. }
  109. return 0;
  110. }
  111. static int bcm43xx_set_clock(int fd, unsigned char clock)
  112. {
  113. unsigned char cmd[] = { HCI_COMMAND_PKT, 0x45, 0xfc, 0x01, 0x00 };
  114. unsigned char resp[CC_MIN_SIZE];
  115. printf("Set Controller clock (%d)\n", clock);
  116. cmd[4] = clock;
  117. tcflush(fd, TCIOFLUSH);
  118. if (write(fd, cmd, sizeof(cmd)) != sizeof(cmd)) {
  119. fprintf(stderr, "Failed to write update clock command\n");
  120. return -1;
  121. }
  122. if (read_hci_event(fd, resp, sizeof(resp)) < CC_MIN_SIZE) {
  123. fprintf(stderr, "Failed to update clock, invalid HCI event\n");
  124. return -1;
  125. }
  126. if (resp[4] != cmd[1] || resp[5] != cmd[2] || resp[6] != CMD_SUCCESS) {
  127. fprintf(stderr, "Failed to update clock, command failure\n");
  128. return -1;
  129. }
  130. return 0;
  131. }
  132. static int bcm43xx_set_speed(int fd, struct termios *ti, uint32_t speed)
  133. {
  134. unsigned char cmd[] =
  135. { HCI_COMMAND_PKT, 0x18, 0xfc, 0x06, 0x00, 0x00,
  136. 0x00, 0x00, 0x00, 0x00 };
  137. unsigned char resp[CC_MIN_SIZE];
  138. if (speed > 3000000 && bcm43xx_set_clock(fd, BCM43XX_CLOCK_48))
  139. return -1;
  140. printf("Set Controller UART speed to %d bit/s\n", speed);
  141. cmd[6] = (uint8_t) (speed);
  142. cmd[7] = (uint8_t) (speed >> 8);
  143. cmd[8] = (uint8_t) (speed >> 16);
  144. cmd[9] = (uint8_t) (speed >> 24);
  145. tcflush(fd, TCIOFLUSH);
  146. if (write(fd, cmd, sizeof(cmd)) != sizeof(cmd)) {
  147. fprintf(stderr, "Failed to write update baudrate command\n");
  148. return -1;
  149. }
  150. if (read_hci_event(fd, resp, sizeof(resp)) < CC_MIN_SIZE) {
  151. fprintf(stderr, "Failed to update baudrate, invalid HCI event\n");
  152. return -1;
  153. }
  154. if (resp[4] != cmd[1] || resp[5] != cmd[2] || resp[6] != CMD_SUCCESS) {
  155. fprintf(stderr, "Failed to update baudrate, command failure\n");
  156. return -1;
  157. }
  158. if (set_speed(fd, ti, speed) < 0) {
  159. perror("Can't set host baud rate");
  160. return -1;
  161. }
  162. return 0;
  163. }
  164. static int bcm43xx_load_firmware(int fd, const char *fw)
  165. {
  166. unsigned char cmd[] = { HCI_COMMAND_PKT, 0x2e, 0xfc, 0x00 };
  167. struct timespec tm_mode = { 0, 50000000 };
  168. struct timespec tm_ready = { 0, 200000000 };
  169. unsigned char resp[CC_MIN_SIZE];
  170. unsigned char tx_buf[1024];
  171. int len, fd_fw, n;
  172. printf("Flash firmware %s\n", fw);
  173. fd_fw = open(fw, O_RDONLY);
  174. if (fd_fw < 0) {
  175. fprintf(stderr, "Unable to open firmware (%s)\n", fw);
  176. return -1;
  177. }
  178. tcflush(fd, TCIOFLUSH);
  179. if (write(fd, cmd, sizeof(cmd)) != sizeof(cmd)) {
  180. fprintf(stderr, "Failed to write download mode command\n");
  181. goto fail;
  182. }
  183. if (read_hci_event(fd, resp, sizeof(resp)) < CC_MIN_SIZE) {
  184. fprintf(stderr, "Failed to load firmware, invalid HCI event\n");
  185. goto fail;
  186. }
  187. if (resp[4] != cmd[1] || resp[5] != cmd[2] || resp[6] != CMD_SUCCESS) {
  188. fprintf(stderr, "Failed to load firmware, command failure\n");
  189. goto fail;
  190. }
  191. /* Wait 50ms to let the firmware placed in download mode */
  192. nanosleep(&tm_mode, NULL);
  193. tcflush(fd, TCIOFLUSH);
  194. while ((n = read(fd_fw, &tx_buf[1], 3))) {
  195. if (n < 0) {
  196. fprintf(stderr, "Failed to read firmware\n");
  197. goto fail;
  198. }
  199. tx_buf[0] = HCI_COMMAND_PKT;
  200. len = tx_buf[3];
  201. if (read(fd_fw, &tx_buf[4], len) < 0) {
  202. fprintf(stderr, "Failed to read firmware\n");
  203. goto fail;
  204. }
  205. if (write(fd, tx_buf, len + 4) != (len + 4)) {
  206. fprintf(stderr, "Failed to write firmware\n");
  207. goto fail;
  208. }
  209. read_hci_event(fd, resp, sizeof(resp));
  210. tcflush(fd, TCIOFLUSH);
  211. }
  212. /* Wait for firmware ready */
  213. nanosleep(&tm_ready, NULL);
  214. close(fd_fw);
  215. return 0;
  216. fail:
  217. close(fd_fw);
  218. return -1;
  219. }
  220. static int bcm43xx_locate_patch(const char *dir_name,
  221. const char *chip_name, char *location)
  222. {
  223. DIR *dir;
  224. int ret = -1;
  225. dir = opendir(dir_name);
  226. if (!dir) {
  227. fprintf(stderr, "Cannot open directory '%s': %s\n",
  228. dir_name, strerror(errno));
  229. return -1;
  230. }
  231. /* Recursively look for a BCM43XX*.hcd */
  232. while (1) {
  233. struct dirent *entry = readdir(dir);
  234. if (!entry)
  235. break;
  236. if (entry->d_type & DT_DIR) {
  237. char path[PATH_MAX];
  238. if (!strcmp(entry->d_name, "..") || !strcmp(entry->d_name, "."))
  239. continue;
  240. snprintf(path, PATH_MAX, "%s/%s", dir_name, entry->d_name);
  241. ret = bcm43xx_locate_patch(path, chip_name, location);
  242. if (!ret)
  243. break;
  244. } else if (!strncmp(chip_name, entry->d_name, strlen(chip_name))) {
  245. unsigned int name_len = strlen(entry->d_name);
  246. size_t curs_ext = name_len - sizeof(FW_EXT) + 1;
  247. if (curs_ext > name_len)
  248. break;
  249. if (strncmp(FW_EXT, &entry->d_name[curs_ext], sizeof(FW_EXT)))
  250. break;
  251. /* found */
  252. snprintf(location, PATH_MAX, "%s/%s", dir_name, entry->d_name);
  253. ret = 0;
  254. break;
  255. }
  256. }
  257. closedir(dir);
  258. return ret;
  259. }
  260. int bcm43xx_init(int fd, int def_speed, int speed, struct termios *ti,
  261. const char *bdaddr)
  262. {
  263. char chip_name[20];
  264. char fw_path[PATH_MAX];
  265. printf("bcm43xx_init\n");
  266. if (bcm43xx_reset(fd))
  267. return -1;
  268. if (bcm43xx_read_local_name(fd, chip_name, sizeof(chip_name)))
  269. return -1;
  270. if (bcm43xx_locate_patch(FIRMWARE_DIR, chip_name, fw_path)) {
  271. fprintf(stderr, "Patch not found, continue anyway\n");
  272. } else {
  273. if (bcm43xx_set_speed(fd, ti, speed))
  274. return -1;
  275. if (bcm43xx_load_firmware(fd, fw_path))
  276. return -1;
  277. /* Controller speed has been reset to def speed */
  278. if (set_speed(fd, ti, def_speed) < 0) {
  279. perror("Can't set host baud rate");
  280. return -1;
  281. }
  282. if (bcm43xx_reset(fd))
  283. return -1;
  284. }
  285. if (bdaddr)
  286. bcm43xx_set_bdaddr(fd, bdaddr);
  287. if (bcm43xx_set_speed(fd, ti, speed))
  288. return -1;
  289. return 0;
  290. }