xref: /openbmc/linux/drivers/bluetooth/hci_bcm.c (revision 4f3db074)
1 /*
2  *
3  *  Bluetooth HCI UART driver for Broadcom devices
4  *
5  *  Copyright (C) 2015  Intel Corporation
6  *
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  */
23 
24 #include <linux/kernel.h>
25 #include <linux/errno.h>
26 #include <linux/skbuff.h>
27 
28 #include <net/bluetooth/bluetooth.h>
29 #include <net/bluetooth/hci_core.h>
30 
31 #include "btbcm.h"
32 #include "hci_uart.h"
33 
34 struct bcm_data {
35 	struct sk_buff *rx_skb;
36 	struct sk_buff_head txq;
37 };
38 
39 static int bcm_open(struct hci_uart *hu)
40 {
41 	struct bcm_data *bcm;
42 
43 	BT_DBG("hu %p", hu);
44 
45 	bcm = kzalloc(sizeof(*bcm), GFP_KERNEL);
46 	if (!bcm)
47 		return -ENOMEM;
48 
49 	skb_queue_head_init(&bcm->txq);
50 
51 	hu->priv = bcm;
52 	return 0;
53 }
54 
55 static int bcm_close(struct hci_uart *hu)
56 {
57 	struct bcm_data *bcm = hu->priv;
58 
59 	BT_DBG("hu %p", hu);
60 
61 	skb_queue_purge(&bcm->txq);
62 	kfree_skb(bcm->rx_skb);
63 	kfree(bcm);
64 
65 	hu->priv = NULL;
66 	return 0;
67 }
68 
69 static int bcm_flush(struct hci_uart *hu)
70 {
71 	struct bcm_data *bcm = hu->priv;
72 
73 	BT_DBG("hu %p", hu);
74 
75 	skb_queue_purge(&bcm->txq);
76 
77 	return 0;
78 }
79 
80 static int bcm_setup(struct hci_uart *hu)
81 {
82 	BT_DBG("hu %p", hu);
83 
84 	hu->hdev->set_bdaddr = btbcm_set_bdaddr;
85 
86 	return btbcm_setup_patchram(hu->hdev);
87 }
88 
89 static const struct h4_recv_pkt bcm_recv_pkts[] = {
90 	{ H4_RECV_ACL,   .recv = hci_recv_frame },
91 	{ H4_RECV_SCO,   .recv = hci_recv_frame },
92 	{ H4_RECV_EVENT, .recv = hci_recv_frame },
93 };
94 
95 static int bcm_recv(struct hci_uart *hu, const void *data, int count)
96 {
97 	struct bcm_data *bcm = hu->priv;
98 
99 	if (!test_bit(HCI_UART_REGISTERED, &hu->flags))
100 		return -EUNATCH;
101 
102 	bcm->rx_skb = h4_recv_buf(hu->hdev, bcm->rx_skb, data, count,
103 				  bcm_recv_pkts, ARRAY_SIZE(bcm_recv_pkts));
104 	if (IS_ERR(bcm->rx_skb)) {
105 		int err = PTR_ERR(bcm->rx_skb);
106 		BT_ERR("%s: Frame reassembly failed (%d)", hu->hdev->name, err);
107 		return err;
108 	}
109 
110 	return count;
111 }
112 
113 static int bcm_enqueue(struct hci_uart *hu, struct sk_buff *skb)
114 {
115 	struct bcm_data *bcm = hu->priv;
116 
117 	BT_DBG("hu %p skb %p", hu, skb);
118 
119 	/* Prepend skb with frame type */
120 	memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
121 	skb_queue_tail(&bcm->txq, skb);
122 
123 	return 0;
124 }
125 
126 static struct sk_buff *bcm_dequeue(struct hci_uart *hu)
127 {
128 	struct bcm_data *bcm = hu->priv;
129 
130 	return skb_dequeue(&bcm->txq);
131 }
132 
133 static const struct hci_uart_proto bcm_proto = {
134 	.id		= HCI_UART_BCM,
135 	.name		= "BCM",
136 	.open		= bcm_open,
137 	.close		= bcm_close,
138 	.flush		= bcm_flush,
139 	.setup		= bcm_setup,
140 	.recv		= bcm_recv,
141 	.enqueue	= bcm_enqueue,
142 	.dequeue	= bcm_dequeue,
143 };
144 
145 int __init bcm_init(void)
146 {
147 	return hci_uart_register_proto(&bcm_proto);
148 }
149 
150 int __exit bcm_deinit(void)
151 {
152 	return hci_uart_unregister_proto(&bcm_proto);
153 }
154