hci_h4.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:6k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* 
  2.    BlueZ - Bluetooth protocol stack for Linux
  3.    Copyright (C) 2000-2001 Qualcomm Incorporated
  4.    Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
  5.    This program is free software; you can redistribute it and/or modify
  6.    it under the terms of the GNU General Public License version 2 as
  7.    published by the Free Software Foundation;
  8.    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  9.    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  10.    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
  11.    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
  12.    CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
  13.    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
  14.    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
  15.    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  16.    ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
  17.    COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
  18.    SOFTWARE IS DISCLAIMED.
  19. */
  20. /*
  21.  * BlueZ HCI UART(H4) protocol.
  22.  *
  23.  * $Id: hci_h4.c,v 1.2 2002/04/17 17:37:20 maxk Exp $    
  24.  */
  25. #define VERSION "1.1"
  26. #include <linux/config.h>
  27. #include <linux/module.h>
  28. #include <linux/version.h>
  29. #include <linux/config.h>
  30. #include <linux/kernel.h>
  31. #include <linux/init.h>
  32. #include <linux/sched.h>
  33. #include <linux/types.h>
  34. #include <linux/fcntl.h>
  35. #include <linux/interrupt.h>
  36. #include <linux/ptrace.h>
  37. #include <linux/poll.h>
  38. #include <linux/slab.h>
  39. #include <linux/tty.h>
  40. #include <linux/errno.h>
  41. #include <linux/string.h>
  42. #include <linux/signal.h>
  43. #include <linux/ioctl.h>
  44. #include <linux/skbuff.h>
  45. #include <net/bluetooth/bluetooth.h>
  46. #include <net/bluetooth/hci_core.h>
  47. #include "hci_uart.h"
  48. #include "hci_h4.h"
  49. #ifndef HCI_UART_DEBUG
  50. #undef  BT_DBG
  51. #define BT_DBG( A... )
  52. #undef  BT_DMP
  53. #define BT_DMP( A... )
  54. #endif
  55. /* Initialize protocol */
  56. static int h4_open(struct n_hci *n_hci)
  57. {
  58. struct h4_struct *h4;
  59. BT_DBG("n_hci %p", n_hci);
  60. h4 = kmalloc(sizeof(*h4), GFP_ATOMIC);
  61. if (!h4)
  62. return -ENOMEM;
  63. memset(h4, 0, sizeof(*h4));
  64. n_hci->priv = h4;
  65. return 0;
  66. }
  67. /* Flush protocol data */
  68. static int h4_flush(struct n_hci *n_hci)
  69. {
  70. BT_DBG("n_hci %p", n_hci);
  71. return 0;
  72. }
  73. /* Close protocol */
  74. static int h4_close(struct n_hci *n_hci)
  75. {
  76. struct h4_struct *h4 = n_hci->priv;
  77. n_hci->priv = NULL;
  78. BT_DBG("n_hci %p", n_hci);
  79. if (h4->rx_skb)
  80. kfree_skb(h4->rx_skb);
  81. kfree(h4);
  82. return 0;
  83. }
  84. /* Send data */
  85. static int h4_send(struct n_hci *n_hci, void *data, int len)
  86. {
  87. struct tty_struct *tty = n_hci->tty;
  88. BT_DBG("n_hci %p len %d", n_hci, len);
  89. /* Send frame to TTY driver */
  90. tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
  91. return tty->driver.write(tty, 0, data, len);
  92. }
  93. /* Init frame before queueing (padding, crc, etc) */
  94. static struct sk_buff* h4_preq(struct n_hci *n_hci, struct sk_buff *skb)
  95. {
  96. BT_DBG("n_hci %p skb %p", n_hci, skb);
  97. /* Prepend skb with frame type */
  98. memcpy(skb_push(skb, 1), &skb->pkt_type, 1);
  99. return skb;
  100. }
  101. static inline int h4_check_data_len(struct h4_struct *h4, int len)
  102. {
  103. register int room = skb_tailroom(h4->rx_skb);
  104. BT_DBG("len %d room %d", len, room);
  105. if (!len) {
  106. BT_DMP(h4->rx_skb->data, h4->rx_skb->len);
  107. hci_recv_frame(h4->rx_skb);
  108. } else if (len > room) {
  109. BT_ERR("Data length is to large");
  110. kfree_skb(h4->rx_skb);
  111. } else {
  112. h4->rx_state = H4_W4_DATA;
  113. h4->rx_count = len;
  114. return len;
  115. }
  116. h4->rx_state = H4_W4_PACKET_TYPE;
  117. h4->rx_skb   = NULL;
  118. h4->rx_count = 0;
  119. return 0;
  120. }
  121. /* Recv data */
  122. static int h4_recv(struct n_hci *n_hci, void *data, int count)
  123. {
  124. struct h4_struct *h4 = n_hci->priv;
  125. register char *ptr;
  126. hci_event_hdr *eh;
  127. hci_acl_hdr   *ah;
  128. hci_sco_hdr   *sh;
  129. register int len, type, dlen;
  130. BT_DBG("n_hci %p count %d rx_state %ld rx_count %ld", n_hci, count, h4->rx_state, h4->rx_count);
  131. ptr = data;
  132. while (count) {
  133. if (h4->rx_count) {
  134. len = MIN(h4->rx_count, count);
  135. memcpy(skb_put(h4->rx_skb, len), ptr, len);
  136. h4->rx_count -= len; count -= len; ptr += len;
  137. if (h4->rx_count)
  138. continue;
  139. switch (h4->rx_state) {
  140. case H4_W4_DATA:
  141. BT_DBG("Complete data");
  142. BT_DMP(h4->rx_skb->data, h4->rx_skb->len);
  143. hci_recv_frame(h4->rx_skb);
  144. h4->rx_state = H4_W4_PACKET_TYPE;
  145. h4->rx_skb = NULL;
  146. continue;
  147. case H4_W4_EVENT_HDR:
  148. eh = (hci_event_hdr *) h4->rx_skb->data;
  149. BT_DBG("Event header: evt 0x%2.2x plen %d", eh->evt, eh->plen);
  150. h4_check_data_len(h4, eh->plen);
  151. continue;
  152. case H4_W4_ACL_HDR:
  153. ah = (hci_acl_hdr *) h4->rx_skb->data;
  154. dlen = __le16_to_cpu(ah->dlen);
  155. BT_DBG("ACL header: dlen %d", dlen);
  156. h4_check_data_len(h4, dlen);
  157. continue;
  158. case H4_W4_SCO_HDR:
  159. sh = (hci_sco_hdr *) h4->rx_skb->data;
  160. BT_DBG("SCO header: dlen %d", sh->dlen);
  161. h4_check_data_len(h4, sh->dlen);
  162. continue;
  163. };
  164. }
  165. /* H4_W4_PACKET_TYPE */
  166. switch (*ptr) {
  167. case HCI_EVENT_PKT:
  168. BT_DBG("Event packet");
  169. h4->rx_state = H4_W4_EVENT_HDR;
  170. h4->rx_count = HCI_EVENT_HDR_SIZE;
  171. type = HCI_EVENT_PKT;
  172. break;
  173. case HCI_ACLDATA_PKT:
  174. BT_DBG("ACL packet");
  175. h4->rx_state = H4_W4_ACL_HDR;
  176. h4->rx_count = HCI_ACL_HDR_SIZE;
  177. type = HCI_ACLDATA_PKT;
  178. break;
  179. case HCI_SCODATA_PKT:
  180. BT_DBG("SCO packet");
  181. h4->rx_state = H4_W4_SCO_HDR;
  182. h4->rx_count = HCI_SCO_HDR_SIZE;
  183. type = HCI_SCODATA_PKT;
  184. break;
  185. default:
  186. BT_ERR("Unknown HCI packet type %2.2x", (__u8)*ptr);
  187. n_hci->hdev.stat.err_rx++;
  188. ptr++; count--;
  189. continue;
  190. };
  191. ptr++; count--;
  192. /* Allocate packet */
  193. h4->rx_skb = bluez_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
  194. if (!h4->rx_skb) {
  195. BT_ERR("Can't allocate mem for new packet");
  196. h4->rx_state = H4_W4_PACKET_TYPE;
  197. h4->rx_count = 0;
  198. return 0;
  199. }
  200. h4->rx_skb->dev = (void *) &n_hci->hdev;
  201. h4->rx_skb->pkt_type = type;
  202. }
  203. return count;
  204. }
  205. static struct hci_uart_proto h4p = {
  206. id:    HCI_UART_H4,
  207. open:  h4_open,
  208. close: h4_close,
  209. send:  h4_send,
  210. recv:  h4_recv,
  211. preq:  h4_preq,
  212. flush: h4_flush,
  213. };
  214.       
  215. int h4_init(void)
  216. {
  217. return hci_uart_register_proto(&h4p);
  218. }
  219. int h4_deinit(void)
  220. {
  221. return hci_uart_unregister_proto(&h4p);
  222. }