bluetooth_input.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. /****************************************************************************
  2. * net/bluetooth/bluetooth_input.c
  3. * Handle incoming Bluetooth frame input
  4. *
  5. * Copyright (C) 2018 Gregory Nutt. All rights reserved.
  6. * Author: Gregory Nutt <gnutt@nuttx.org>
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in the
  16. * documentation and/or other materials provided with the distribution.
  17. * 3. The name of the author may not be used to endorse or promote
  18. * products derived from this software without specific prior
  19. * written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
  22. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  23. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  25. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  27. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  28. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  29. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  30. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  31. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. *
  33. ****************************************************************************/
  34. /****************************************************************************
  35. * Included Files
  36. ****************************************************************************/
  37. #include <nuttx/config.h>
  38. #include <string.h>
  39. #include <assert.h>
  40. #include <debug.h>
  41. #include <nuttx/mm/iob.h>
  42. #include <nuttx/net/radiodev.h>
  43. #include <nuttx/net/bluetooth.h>
  44. #include <nuttx/wireless/bluetooth/bt_hci.h>
  45. #include "devif/devif.h"
  46. #include "bluetooth/bluetooth.h"
  47. #ifdef CONFIG_NET_BLUETOOTH
  48. /****************************************************************************
  49. * Public Functions
  50. ****************************************************************************/
  51. /****************************************************************************
  52. * Name: bluetooth_count_frames
  53. *
  54. * Description:
  55. * Return the number of frames in the RX queue.
  56. *
  57. * Input Parameters:
  58. * conn - The socket connection structure.
  59. *
  60. * Returned Value:
  61. * The number of frames in the queue.
  62. *
  63. ****************************************************************************/
  64. #if defined(CONFIG_DEBUG_ASSERTIONS) && CONFIG_NET_BLUETOOTH_BACKLOG > 0
  65. static int bluetooth_count_frames(FAR struct bluetooth_conn_s *conn)
  66. {
  67. FAR struct bluetooth_container_s *container;
  68. int count;
  69. for (count = 0, container = conn->bc_rxhead;
  70. container != NULL;
  71. count++, container = container->bn_flink)
  72. {
  73. }
  74. return count;
  75. }
  76. #endif
  77. /****************************************************************************
  78. * Name: bluetooth_queue_frame
  79. *
  80. * Description:
  81. * Add one frame to the connection's RX queue.
  82. *
  83. * Input Parameters:
  84. * conn - The socket connection structure.
  85. * framel - A single frame to add to the RX queue.
  86. * meta - Meta data characterizing the received frane.
  87. *
  88. * Returned Value:
  89. * Zero (OK) is returned on success; A negated errno value is returned on
  90. * any failure.
  91. *
  92. ****************************************************************************/
  93. static int bluetooth_queue_frame(FAR struct bluetooth_conn_s *conn,
  94. FAR struct iob_s *frame,
  95. FAR struct bluetooth_frame_meta_s *meta)
  96. {
  97. FAR struct bluetooth_container_s *container;
  98. /* Allocate a container for the frame */
  99. container = bluetooth_container_allocate();
  100. if (container == NULL)
  101. {
  102. nerr("ERROR: Failed to allocate a container\n");
  103. return -ENOMEM;
  104. }
  105. /* Initialize the container */
  106. memset(&container->bn_raddr, 0, sizeof(bt_addr_t));
  107. container->bn_channel = meta->bm_channel;
  108. BLUETOOTH_ADDRCOPY(&container->bn_raddr, &meta->bm_raddr);
  109. DEBUGASSERT(frame != NULL);
  110. container->bn_iob = frame;
  111. /* Add the container to the tail of the list of incoming frames */
  112. container->bn_flink = NULL;
  113. if (conn->bc_rxtail == NULL)
  114. {
  115. conn->bc_rxhead = container;
  116. }
  117. else
  118. {
  119. conn->bc_rxtail->bn_flink = container;
  120. }
  121. #if CONFIG_NET_BLUETOOTH_BACKLOG > 0
  122. /* If incrementing the count would exceed the maximum bc_backlog value, then
  123. * delete the oldest frame from the head of the RX queue.
  124. */
  125. if (conn->bc_backlog >= CONFIG_NET_BLUETOOTH_BACKLOG)
  126. {
  127. DEBUGASSERT(conn->bc_backlog == CONFIG_NET_BLUETOOTH_BACKLOG);
  128. /* Remove the container from the tail RX input queue. */
  129. container = conn->bc_rxhead;
  130. DEBUGASSERT(container != NULL);
  131. conn->bc_rxhead = container->bn_flink;
  132. container->bn_flink = NULL;
  133. /* Did the RX queue become empty? */
  134. if (conn->bc_rxhead == NULL)
  135. {
  136. conn->bc_rxtail = NULL;
  137. }
  138. DEBUGASSERT(container != NULL && container->bn_iob != NULL);
  139. /* Free both the IOB and the container */
  140. iob_free(container->bn_iob, IOBUSER_NET_SOCK_BLUETOOTH);
  141. bluetooth_container_free(container);
  142. }
  143. else
  144. {
  145. /* Increment the count of frames in the queue. */
  146. conn->bc_backlog++;
  147. }
  148. DEBUGASSERT((int)conn->bc_backlog == bluetooth_count_frames(conn));
  149. #endif
  150. return OK;
  151. }
  152. /****************************************************************************
  153. * Public Functions
  154. ****************************************************************************/
  155. /****************************************************************************
  156. * Name: bluetooth_input
  157. *
  158. * Description:
  159. * Handle incoming Bluetooth input
  160. *
  161. * This function is called when the radio device driver has received an
  162. * frame from the network. The frame from the device driver must be
  163. * provided in by the IOB frame argument of the function call:
  164. *
  165. * - The frame data is in the IOB io_data[] buffer,
  166. * - The length of the frame is in the IOB io_len field, and
  167. * - The offset past and radio MAC header is provided in the io_offset
  168. * field.
  169. *
  170. * The frame argument may refer to a single frame (a list of length one)
  171. * or may it be the head of a list of multiple frames.
  172. *
  173. * - The io_flink field points to the next frame in the list (if enable)
  174. * - The last frame in the list will have io_flink == NULL.
  175. *
  176. * Input Parameters:
  177. * radio The radio network driver interface.
  178. * framelist - The head of an incoming list of frames. Normally this
  179. * would be a single frame. A list may be provided if
  180. * appropriate, however.
  181. * meta - Meta data characterizing the received frame.
  182. *
  183. * If there are multiple frames in the list, this metadata
  184. * must apply to all of the frames in the list.
  185. *
  186. * Returned Value:
  187. * OK The Bluetooth has been processed and can be deleted
  188. * ERROR Hold the Bluetooth and try again later. There is a listening
  189. * socket but no recv in place to catch the Bluetooth yet.
  190. * Useful when a packet arrives before a recv call is in place.
  191. *
  192. * Assumptions:
  193. * Called from the network diver with the network locked.
  194. *
  195. ****************************************************************************/
  196. int bluetooth_input(FAR struct radio_driver_s *radio,
  197. FAR struct iob_s *framelist,
  198. FAR struct bluetooth_frame_meta_s *meta)
  199. {
  200. FAR struct bluetooth_conn_s *conn;
  201. FAR struct iob_s *frame;
  202. FAR struct iob_s *next;
  203. int ret = OK;
  204. /* Check if there is a connection that will accept this packet */
  205. conn = bluetooth_conn_active(meta);
  206. if (conn != NULL)
  207. {
  208. /* Setup for the application callback (NOTE: These should not be
  209. * used by PF_BLUETOOTH sockets).
  210. */
  211. radio->r_dev.d_appdata = radio->r_dev.d_buf;
  212. radio->r_dev.d_len = 0;
  213. radio->r_dev.d_sndlen = 0;
  214. /* The framelist probably contains only a single frame, but we will
  215. * process it as a list of frames.
  216. */
  217. for (frame = framelist; frame != NULL; frame = next)
  218. {
  219. /* Remove the frame from the list */
  220. next = frame->io_flink;
  221. frame->io_flink = NULL;
  222. /* Add the frame to the RX queue */
  223. ret = bluetooth_queue_frame(conn, frame, meta);
  224. if (ret < 0)
  225. {
  226. nerr("ERROR: Failed to queue frame: %d\n", ret);
  227. iob_free(frame, IOBUSER_NET_SOCK_BLUETOOTH);
  228. }
  229. }
  230. /* Perform the application callback. The frame may be processed now
  231. * if there is a user wait for an incoming frame. Or it may pend in
  232. * the RX queue until some user process reads the frame. NOTE: The
  233. * return value from bluetooth_callback would distinguish these
  234. * cases: BLUETOOTH_NEWDATA will still be processed if the frame
  235. * was not consumed.
  236. */
  237. (void)bluetooth_callback(radio, conn, BLUETOOTH_NEWDATA);
  238. }
  239. else
  240. {
  241. nwarn("WARNING: No listener\n");
  242. }
  243. return ret;
  244. }
  245. #endif /* CONFIG_NET_BLUETOOTH */