serial.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. // SPDX-License-Identifier: LGPL-2.1-or-later
  2. /*
  3. *
  4. * BlueZ - Bluetooth protocol stack for Linux
  5. *
  6. * Copyright (C) 2011-2014 Intel Corporation
  7. * Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
  8. *
  9. *
  10. */
  11. #ifdef HAVE_CONFIG_H
  12. #include <config.h>
  13. #endif
  14. #define _GNU_SOURCE
  15. #include <stdio.h>
  16. #include <errno.h>
  17. #include <ctype.h>
  18. #include <unistd.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <fcntl.h>
  22. #include <sys/param.h>
  23. #include <sys/epoll.h>
  24. #include <sys/uio.h>
  25. #include "lib/bluetooth.h"
  26. #include "lib/hci.h"
  27. #include "src/shared/mainloop.h"
  28. #include "btdev.h"
  29. #include "serial.h"
  30. #define uninitialized_var(x) x = x
  31. struct serial {
  32. enum serial_type type;
  33. uint16_t id;
  34. int fd;
  35. char path[PATH_MAX];
  36. struct btdev *btdev;
  37. uint8_t *pkt_data;
  38. uint8_t pkt_type;
  39. uint16_t pkt_expect;
  40. uint16_t pkt_len;
  41. uint16_t pkt_offset;
  42. };
  43. static void open_pty(struct serial *serial);
  44. static void serial_destroy(void *user_data)
  45. {
  46. struct serial *serial = user_data;
  47. btdev_destroy(serial->btdev);
  48. serial->btdev = NULL;
  49. close(serial->fd);
  50. serial->fd = -1;
  51. }
  52. static void serial_write_callback(const struct iovec *iov, int iovlen,
  53. void *user_data)
  54. {
  55. struct serial *serial = user_data;
  56. ssize_t written;
  57. written = writev(serial->fd, iov, iovlen);
  58. if (written < 0)
  59. return;
  60. }
  61. static void serial_read_callback(int fd, uint32_t events, void *user_data)
  62. {
  63. struct serial *serial = user_data;
  64. static uint8_t buf[4096];
  65. uint8_t *ptr = buf;
  66. ssize_t len;
  67. uint16_t count;
  68. if (events & (EPOLLERR | EPOLLHUP)) {
  69. mainloop_remove_fd(serial->fd);
  70. open_pty(serial);
  71. return;
  72. }
  73. again:
  74. len = read(serial->fd, buf + serial->pkt_offset,
  75. sizeof(buf) - serial->pkt_offset);
  76. if (len < 0) {
  77. if (errno == EAGAIN)
  78. goto again;
  79. return;
  80. }
  81. if (!serial->btdev)
  82. return;
  83. count = serial->pkt_offset + len;
  84. while (count > 0) {
  85. hci_command_hdr *cmd_hdr;
  86. if (!serial->pkt_data) {
  87. serial->pkt_type = ptr[0];
  88. switch (serial->pkt_type) {
  89. case HCI_COMMAND_PKT:
  90. if (count < HCI_COMMAND_HDR_SIZE + 1) {
  91. serial->pkt_offset += len;
  92. return;
  93. }
  94. cmd_hdr = (hci_command_hdr *) (ptr + 1);
  95. serial->pkt_expect = HCI_COMMAND_HDR_SIZE +
  96. cmd_hdr->plen + 1;
  97. serial->pkt_data = malloc(serial->pkt_expect);
  98. serial->pkt_len = 0;
  99. break;
  100. default:
  101. printf("packet error\n");
  102. return;
  103. }
  104. serial->pkt_offset = 0;
  105. }
  106. if (count >= serial->pkt_expect) {
  107. memcpy(serial->pkt_data + serial->pkt_len,
  108. ptr, serial->pkt_expect);
  109. ptr += serial->pkt_expect;
  110. count -= serial->pkt_expect;
  111. btdev_receive_h4(serial->btdev, serial->pkt_data,
  112. serial->pkt_len + serial->pkt_expect);
  113. free(serial->pkt_data);
  114. serial->pkt_data = NULL;
  115. } else {
  116. memcpy(serial->pkt_data + serial->pkt_len, ptr, count);
  117. serial->pkt_len += count;
  118. serial->pkt_expect -= count;
  119. count = 0;
  120. }
  121. }
  122. }
  123. static void open_pty(struct serial *serial)
  124. {
  125. enum btdev_type uninitialized_var(type);
  126. serial->fd = posix_openpt(O_RDWR | O_NOCTTY);
  127. if (serial->fd < 0) {
  128. perror("Failed to get central pseudo terminal");
  129. return;
  130. }
  131. if (grantpt(serial->fd) < 0) {
  132. perror("Failed to grant peripheral pseudo terminal");
  133. close(serial->fd);
  134. serial->fd = -1;
  135. return;
  136. }
  137. if (unlockpt(serial->fd) < 0) {
  138. perror("Failed to unlock peripheral pseudo terminal");
  139. close(serial->fd);
  140. serial->fd = -1;
  141. return;
  142. }
  143. ptsname_r(serial->fd, serial->path, sizeof(serial->path));
  144. printf("Pseudo terminal at %s\n", serial->path);
  145. switch (serial->type) {
  146. case SERIAL_TYPE_BREDRLE:
  147. type = BTDEV_TYPE_BREDRLE;
  148. break;
  149. case SERIAL_TYPE_BREDR:
  150. type = BTDEV_TYPE_BREDR;
  151. break;
  152. case SERIAL_TYPE_LE:
  153. type = BTDEV_TYPE_LE;
  154. break;
  155. case SERIAL_TYPE_AMP:
  156. type = BTDEV_TYPE_AMP;
  157. break;
  158. }
  159. serial->btdev = btdev_create(type, serial->id);
  160. if (!serial->btdev) {
  161. close(serial->fd);
  162. serial->fd = -1;
  163. return;
  164. }
  165. btdev_set_send_handler(serial->btdev, serial_write_callback, serial);
  166. if (mainloop_add_fd(serial->fd, EPOLLIN, serial_read_callback,
  167. serial, serial_destroy) < 0) {
  168. btdev_destroy(serial->btdev);
  169. serial->btdev = NULL;
  170. close(serial->fd);
  171. serial->fd = -1;
  172. return;
  173. }
  174. }
  175. struct serial *serial_open(enum serial_type type)
  176. {
  177. struct serial *serial;
  178. enum btdev_type uninitialized_var(dev_type);
  179. serial = malloc(sizeof(*serial));
  180. if (!serial)
  181. return NULL;
  182. memset(serial, 0, sizeof(*serial));
  183. serial->type = type;
  184. serial->id = 0x42;
  185. open_pty(serial);
  186. return serial;
  187. }
  188. void serial_close(struct serial *serial)
  189. {
  190. if (!serial)
  191. return;
  192. mainloop_remove_fd(serial->fd);
  193. free(serial);
  194. }