PageRenderTime 39ms CodeModel.GetById 22ms app.highlight 14ms RepoModel.GetById 1ms app.codeStats 0ms

/drivers/bluetooth/btsdio.c

https://bitbucket.org/cresqo/cm7-p500-kernel
C | 400 lines | 267 code | 104 blank | 29 comment | 24 complexity | fb4f72e5277f237a3e965f7eb2cdb0b1 MD5 | raw file
Possible License(s): LGPL-2.0, AGPL-1.0, GPL-2.0
  1/*
  2 *
  3 *  Generic Bluetooth SDIO driver
  4 *
  5 *  Copyright (C) 2007  Cambridge Silicon Radio Ltd.
  6 *  Copyright (C) 2007  Marcel Holtmann <marcel@holtmann.org>
  7 *
  8 *
  9 *  This program is free software; you can redistribute it and/or modify
 10 *  it under the terms of the GNU General Public License as published by
 11 *  the Free Software Foundation; either version 2 of the License, or
 12 *  (at your option) any later version.
 13 *
 14 *  This program is distributed in the hope that it will be useful,
 15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 17 *  GNU General Public License for more details.
 18 *
 19 *  You should have received a copy of the GNU General Public License
 20 *  along with this program; if not, write to the Free Software
 21 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 22 *
 23 */
 24
 25#include <linux/kernel.h>
 26#include <linux/module.h>
 27#include <linux/init.h>
 28#include <linux/slab.h>
 29#include <linux/types.h>
 30#include <linux/sched.h>
 31#include <linux/errno.h>
 32#include <linux/skbuff.h>
 33
 34#include <linux/mmc/sdio_ids.h>
 35#include <linux/mmc/sdio_func.h>
 36
 37#include <net/bluetooth/bluetooth.h>
 38#include <net/bluetooth/hci_core.h>
 39
 40#define VERSION "0.1"
 41
 42static const struct sdio_device_id btsdio_table[] = {
 43	/* Generic Bluetooth Type-A SDIO device */
 44	{ SDIO_DEVICE_CLASS(SDIO_CLASS_BT_A) },
 45
 46	/* Generic Bluetooth Type-B SDIO device */
 47	{ SDIO_DEVICE_CLASS(SDIO_CLASS_BT_B) },
 48
 49	{ }	/* Terminating entry */
 50};
 51
 52MODULE_DEVICE_TABLE(sdio, btsdio_table);
 53
 54struct btsdio_data {
 55	struct hci_dev   *hdev;
 56	struct sdio_func *func;
 57
 58	struct work_struct work;
 59
 60	struct sk_buff_head txq;
 61};
 62
 63#define REG_RDAT     0x00	/* Receiver Data */
 64#define REG_TDAT     0x00	/* Transmitter Data */
 65#define REG_PC_RRT   0x10	/* Read Packet Control */
 66#define REG_PC_WRT   0x11	/* Write Packet Control */
 67#define REG_RTC_STAT 0x12	/* Retry Control Status */
 68#define REG_RTC_SET  0x12	/* Retry Control Set */
 69#define REG_INTRD    0x13	/* Interrupt Indication */
 70#define REG_CL_INTRD 0x13	/* Interrupt Clear */
 71#define REG_EN_INTRD 0x14	/* Interrupt Enable */
 72#define REG_MD_STAT  0x20	/* Bluetooth Mode Status */
 73
 74static int btsdio_tx_packet(struct btsdio_data *data, struct sk_buff *skb)
 75{
 76	int err;
 77
 78	BT_DBG("%s", data->hdev->name);
 79
 80	/* Prepend Type-A header */
 81	skb_push(skb, 4);
 82	skb->data[0] = (skb->len & 0x0000ff);
 83	skb->data[1] = (skb->len & 0x00ff00) >> 8;
 84	skb->data[2] = (skb->len & 0xff0000) >> 16;
 85	skb->data[3] = bt_cb(skb)->pkt_type;
 86
 87	err = sdio_writesb(data->func, REG_TDAT, skb->data, skb->len);
 88	if (err < 0) {
 89		skb_pull(skb, 4);
 90		sdio_writeb(data->func, 0x01, REG_PC_WRT, NULL);
 91		return err;
 92	}
 93
 94	data->hdev->stat.byte_tx += skb->len;
 95
 96	kfree_skb(skb);
 97
 98	return 0;
 99}
100
101static void btsdio_work(struct work_struct *work)
102{
103	struct btsdio_data *data = container_of(work, struct btsdio_data, work);
104	struct sk_buff *skb;
105	int err;
106
107	BT_DBG("%s", data->hdev->name);
108
109	sdio_claim_host(data->func);
110
111	while ((skb = skb_dequeue(&data->txq))) {
112		err = btsdio_tx_packet(data, skb);
113		if (err < 0) {
114			data->hdev->stat.err_tx++;
115			skb_queue_head(&data->txq, skb);
116			break;
117		}
118	}
119
120	sdio_release_host(data->func);
121}
122
123static int btsdio_rx_packet(struct btsdio_data *data)
124{
125	u8 hdr[4] __attribute__ ((aligned(4)));
126	struct sk_buff *skb;
127	int err, len;
128
129	BT_DBG("%s", data->hdev->name);
130
131	err = sdio_readsb(data->func, hdr, REG_RDAT, 4);
132	if (err < 0)
133		return err;
134
135	len = hdr[0] | (hdr[1] << 8) | (hdr[2] << 16);
136	if (len < 4 || len > 65543)
137		return -EILSEQ;
138
139	skb = bt_skb_alloc(len - 4, GFP_KERNEL);
140	if (!skb) {
141		/* Out of memory. Prepare a read retry and just
142		 * return with the expectation that the next time
143		 * we're called we'll have more memory. */
144		return -ENOMEM;
145	}
146
147	skb_put(skb, len - 4);
148
149	err = sdio_readsb(data->func, skb->data, REG_RDAT, len - 4);
150	if (err < 0) {
151		kfree_skb(skb);
152		return err;
153	}
154
155	data->hdev->stat.byte_rx += len;
156
157	skb->dev = (void *) data->hdev;
158	bt_cb(skb)->pkt_type = hdr[3];
159
160	err = hci_recv_frame(skb);
161	if (err < 0)
162		return err;
163
164	sdio_writeb(data->func, 0x00, REG_PC_RRT, NULL);
165
166	return 0;
167}
168
169static void btsdio_interrupt(struct sdio_func *func)
170{
171	struct btsdio_data *data = sdio_get_drvdata(func);
172	int intrd;
173
174	BT_DBG("%s", data->hdev->name);
175
176	intrd = sdio_readb(func, REG_INTRD, NULL);
177	if (intrd & 0x01) {
178		sdio_writeb(func, 0x01, REG_CL_INTRD, NULL);
179
180		if (btsdio_rx_packet(data) < 0) {
181			data->hdev->stat.err_rx++;
182			sdio_writeb(data->func, 0x01, REG_PC_RRT, NULL);
183		}
184	}
185}
186
187static int btsdio_open(struct hci_dev *hdev)
188{
189	struct btsdio_data *data = hdev->driver_data;
190	int err;
191
192	BT_DBG("%s", hdev->name);
193
194	if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
195		return 0;
196
197	sdio_claim_host(data->func);
198
199	err = sdio_enable_func(data->func);
200	if (err < 0) {
201		clear_bit(HCI_RUNNING, &hdev->flags);
202		goto release;
203	}
204
205	err = sdio_claim_irq(data->func, btsdio_interrupt);
206	if (err < 0) {
207		sdio_disable_func(data->func);
208		clear_bit(HCI_RUNNING, &hdev->flags);
209		goto release;
210	}
211
212	if (data->func->class == SDIO_CLASS_BT_B)
213		sdio_writeb(data->func, 0x00, REG_MD_STAT, NULL);
214
215	sdio_writeb(data->func, 0x01, REG_EN_INTRD, NULL);
216
217release:
218	sdio_release_host(data->func);
219
220	return err;
221}
222
223static int btsdio_close(struct hci_dev *hdev)
224{
225	struct btsdio_data *data = hdev->driver_data;
226
227	BT_DBG("%s", hdev->name);
228
229	if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
230		return 0;
231
232	sdio_claim_host(data->func);
233
234	sdio_writeb(data->func, 0x00, REG_EN_INTRD, NULL);
235
236	sdio_release_irq(data->func);
237	sdio_disable_func(data->func);
238
239	sdio_release_host(data->func);
240
241	return 0;
242}
243
244static int btsdio_flush(struct hci_dev *hdev)
245{
246	struct btsdio_data *data = hdev->driver_data;
247
248	BT_DBG("%s", hdev->name);
249
250	skb_queue_purge(&data->txq);
251
252	return 0;
253}
254
255static int btsdio_send_frame(struct sk_buff *skb)
256{
257	struct hci_dev *hdev = (struct hci_dev *) skb->dev;
258	struct btsdio_data *data = hdev->driver_data;
259
260	BT_DBG("%s", hdev->name);
261
262	if (!test_bit(HCI_RUNNING, &hdev->flags))
263		return -EBUSY;
264
265	switch (bt_cb(skb)->pkt_type) {
266	case HCI_COMMAND_PKT:
267		hdev->stat.cmd_tx++;
268		break;
269
270	case HCI_ACLDATA_PKT:
271		hdev->stat.acl_tx++;
272		break;
273
274	case HCI_SCODATA_PKT:
275		hdev->stat.sco_tx++;
276		break;
277
278	default:
279		return -EILSEQ;
280	}
281
282	skb_queue_tail(&data->txq, skb);
283
284	schedule_work(&data->work);
285
286	return 0;
287}
288
289static void btsdio_destruct(struct hci_dev *hdev)
290{
291	struct btsdio_data *data = hdev->driver_data;
292
293	BT_DBG("%s", hdev->name);
294
295	kfree(data);
296}
297
298static int btsdio_probe(struct sdio_func *func,
299				const struct sdio_device_id *id)
300{
301	struct btsdio_data *data;
302	struct hci_dev *hdev;
303	struct sdio_func_tuple *tuple = func->tuples;
304	int err;
305
306	BT_DBG("func %p id %p class 0x%04x", func, id, func->class);
307
308	while (tuple) {
309		BT_DBG("code 0x%x size %d", tuple->code, tuple->size);
310		tuple = tuple->next;
311	}
312
313	data = kzalloc(sizeof(*data), GFP_KERNEL);
314	if (!data)
315		return -ENOMEM;
316
317	data->func = func;
318
319	INIT_WORK(&data->work, btsdio_work);
320
321	skb_queue_head_init(&data->txq);
322
323	hdev = hci_alloc_dev();
324	if (!hdev) {
325		kfree(data);
326		return -ENOMEM;
327	}
328
329	hdev->bus = HCI_SDIO;
330	hdev->driver_data = data;
331
332	data->hdev = hdev;
333
334	SET_HCIDEV_DEV(hdev, &func->dev);
335
336	hdev->open     = btsdio_open;
337	hdev->close    = btsdio_close;
338	hdev->flush    = btsdio_flush;
339	hdev->send     = btsdio_send_frame;
340	hdev->destruct = btsdio_destruct;
341
342	hdev->owner = THIS_MODULE;
343
344	err = hci_register_dev(hdev);
345	if (err < 0) {
346		hci_free_dev(hdev);
347		kfree(data);
348		return err;
349	}
350
351	sdio_set_drvdata(func, data);
352
353	return 0;
354}
355
356static void btsdio_remove(struct sdio_func *func)
357{
358	struct btsdio_data *data = sdio_get_drvdata(func);
359	struct hci_dev *hdev;
360
361	BT_DBG("func %p", func);
362
363	if (!data)
364		return;
365
366	hdev = data->hdev;
367
368	sdio_set_drvdata(func, NULL);
369
370	hci_unregister_dev(hdev);
371
372	hci_free_dev(hdev);
373}
374
375static struct sdio_driver btsdio_driver = {
376	.name		= "btsdio",
377	.probe		= btsdio_probe,
378	.remove		= btsdio_remove,
379	.id_table	= btsdio_table,
380};
381
382static int __init btsdio_init(void)
383{
384	BT_INFO("Generic Bluetooth SDIO driver ver %s", VERSION);
385
386	return sdio_register_driver(&btsdio_driver);
387}
388
389static void __exit btsdio_exit(void)
390{
391	sdio_unregister_driver(&btsdio_driver);
392}
393
394module_init(btsdio_init);
395module_exit(btsdio_exit);
396
397MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
398MODULE_DESCRIPTION("Generic Bluetooth SDIO driver ver " VERSION);
399MODULE_VERSION(VERSION);
400MODULE_LICENSE("GPL");