Blame view

drivers/bluetooth/hci_bcsp.c 18.2 KB
1a59d1b8e   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
  /*
0372a6627   Marcel Holtmann   [Bluetooth] Clean...
3
4
5
6
7
   *
   *  Bluetooth HCI UART driver
   *
   *  Copyright (C) 2002-2003  Fabrizio Gennari <fabrizio.gennari@philips.com>
   *  Copyright (C) 2004-2005  Marcel Holtmann <marcel@holtmann.org>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
8
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9
10
11
12
  #include <linux/module.h>
  
  #include <linux/kernel.h>
  #include <linux/init.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
13
14
15
16
17
18
19
20
21
22
23
24
25
  #include <linux/types.h>
  #include <linux/fcntl.h>
  #include <linux/interrupt.h>
  #include <linux/ptrace.h>
  #include <linux/poll.h>
  
  #include <linux/slab.h>
  #include <linux/tty.h>
  #include <linux/errno.h>
  #include <linux/string.h>
  #include <linux/signal.h>
  #include <linux/ioctl.h>
  #include <linux/skbuff.h>
c5ec51401   Harvey Harrison   bluetooth: hci_bc...
26
27
  #include <linux/bitrev.h>
  #include <asm/unaligned.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
29
30
  
  #include <net/bluetooth/bluetooth.h>
  #include <net/bluetooth/hci_core.h>
0372a6627   Marcel Holtmann   [Bluetooth] Clean...
31

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
  #include "hci_uart.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33

bff6b89f8   Shailendra Verma   Bluetooth: hci_ua...
34
35
  static bool txcrc = true;
  static bool hciextn = true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36

0372a6627   Marcel Holtmann   [Bluetooth] Clean...
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
  #define BCSP_TXWINSIZE	4
  
  #define BCSP_ACK_PKT	0x05
  #define BCSP_LE_PKT	0x06
  
  struct bcsp_struct {
  	struct sk_buff_head unack;	/* Unack'ed packets queue */
  	struct sk_buff_head rel;	/* Reliable packets queue */
  	struct sk_buff_head unrel;	/* Unreliable packets queue */
  
  	unsigned long rx_count;
  	struct	sk_buff *rx_skb;
  	u8	rxseq_txack;		/* rxseq == txack. */
  	u8	rxack;			/* Last packet sent by us that the peer ack'ed */
  	struct	timer_list tbcsp;
043560528   Kees Cook   Bluetooth: Conver...
52
  	struct	hci_uart *hu;
0372a6627   Marcel Holtmann   [Bluetooth] Clean...
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
  
  	enum {
  		BCSP_W4_PKT_DELIMITER,
  		BCSP_W4_PKT_START,
  		BCSP_W4_BCSP_HDR,
  		BCSP_W4_DATA,
  		BCSP_W4_CRC
  	} rx_state;
  
  	enum {
  		BCSP_ESCSTATE_NOESC,
  		BCSP_ESCSTATE_ESC
  	} rx_esc_state;
  
  	u8	use_crc;
  	u16	message_crc;
  	u8	txack_req;		/* Do we need to send ack's to the peer? */
  
  	/* Reliable packet sequence number - used to assign seq to each rel pkt. */
  	u8	msgq_txseq;
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74
75
76
  /* ---- BCSP CRC calculation ---- */
  
  /* Table for calculating CRC for polynomial 0x1021, LSB processed first,
8083ad1cf   Dean Jenkins   Bluetooth: Tidy-u...
77
78
   * initial value 0xffff, bits shifted in reverse order.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
79
80
81
82
83
84
85
86
87
88
  
  static const u16 crc_table[] = {
  	0x0000, 0x1081, 0x2102, 0x3183,
  	0x4204, 0x5285, 0x6306, 0x7387,
  	0x8408, 0x9489, 0xa50a, 0xb58b,
  	0xc60c, 0xd68d, 0xe70e, 0xf78f
  };
  
  /* Initialise the crc calculator */
  #define BCSP_CRC_INIT(x) x = 0xffff
8805eea24   Maxim Zhukov   Bluetooth: hci_bc...
89
90
91
92
93
94
  /* Update crc with next data byte
   *
   * Implementation note
   *     The data byte is treated as two nibbles.  The crc is generated
   *     in reverse, i.e., bits are fed into the register from the top.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95
96
97
98
99
100
101
102
103
  static void bcsp_crc_update(u16 *crc, u8 d)
  {
  	u16 reg = *crc;
  
  	reg = (reg >> 4) ^ crc_table[(reg ^ d) & 0x000f];
  	reg = (reg >> 4) ^ crc_table[(reg ^ (d >> 4)) & 0x000f];
  
  	*crc = reg;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
104
105
106
107
108
  /* ---- BCSP core ---- */
  
  static void bcsp_slip_msgdelim(struct sk_buff *skb)
  {
  	const char pkt_delim = 0xc0;
0372a6627   Marcel Holtmann   [Bluetooth] Clean...
109

59ae1d127   Johannes Berg   networking: intro...
110
  	skb_put_data(skb, &pkt_delim, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
112
113
114
115
116
117
118
119
  }
  
  static void bcsp_slip_one_byte(struct sk_buff *skb, u8 c)
  {
  	const char esc_c0[2] = { 0xdb, 0xdc };
  	const char esc_db[2] = { 0xdb, 0xdd };
  
  	switch (c) {
  	case 0xc0:
59ae1d127   Johannes Berg   networking: intro...
120
  		skb_put_data(skb, &esc_c0, 2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121
122
  		break;
  	case 0xdb:
59ae1d127   Johannes Berg   networking: intro...
123
  		skb_put_data(skb, &esc_db, 2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
124
125
  		break;
  	default:
59ae1d127   Johannes Berg   networking: intro...
126
  		skb_put_data(skb, &c, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
127
128
129
130
131
132
133
134
135
136
137
138
  	}
  }
  
  static int bcsp_enqueue(struct hci_uart *hu, struct sk_buff *skb)
  {
  	struct bcsp_struct *bcsp = hu->priv;
  
  	if (skb->len > 0xFFF) {
  		BT_ERR("Packet too long");
  		kfree_skb(skb);
  		return 0;
  	}
618e8bc22   Marcel Holtmann   Bluetooth: Use ne...
139
  	switch (hci_skb_pkt_type(skb)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
  	case HCI_ACLDATA_PKT:
  	case HCI_COMMAND_PKT:
  		skb_queue_tail(&bcsp->rel, skb);
  		break;
  
  	case HCI_SCODATA_PKT:
  		skb_queue_tail(&bcsp->unrel, skb);
  		break;
  
  	default:
  		BT_ERR("Unknown packet type");
  		kfree_skb(skb);
  		break;
  	}
  
  	return 0;
  }
  
  static struct sk_buff *bcsp_prepare_pkt(struct bcsp_struct *bcsp, u8 *data,
8083ad1cf   Dean Jenkins   Bluetooth: Tidy-u...
159
  					int len, int pkt_type)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
160
161
162
  {
  	struct sk_buff *nskb;
  	u8 hdr[4], chan;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163
  	u16 BCSP_CRC_INIT(bcsp_txmsg_crc);
20dd6f59d   Marcel Holtmann   [Bluetooth] Remov...
164
  	int rel, i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
  
  	switch (pkt_type) {
  	case HCI_ACLDATA_PKT:
  		chan = 6;	/* BCSP ACL channel */
  		rel = 1;	/* reliable channel */
  		break;
  	case HCI_COMMAND_PKT:
  		chan = 5;	/* BCSP cmd/evt channel */
  		rel = 1;	/* reliable channel */
  		break;
  	case HCI_SCODATA_PKT:
  		chan = 7;	/* BCSP SCO channel */
  		rel = 0;	/* unreliable channel */
  		break;
  	case BCSP_LE_PKT:
  		chan = 1;	/* BCSP LE channel */
  		rel = 0;	/* unreliable channel */
  		break;
  	case BCSP_ACK_PKT:
  		chan = 0;	/* BCSP internal channel */
  		rel = 0;	/* unreliable channel */
  		break;
  	default:
  		BT_ERR("Unknown packet type");
  		return NULL;
  	}
  
  	if (hciextn && chan == 5) {
c5ec51401   Harvey Harrison   bluetooth: hci_bc...
193
  		__le16 opcode = ((struct hci_command_hdr *)data)->opcode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
194

a9de92480   Marcel Holtmann   [Bluetooth] Switc...
195
  		/* Vendor specific commands */
c5ec51401   Harvey Harrison   bluetooth: hci_bc...
196
  		if (hci_opcode_ogf(__le16_to_cpu(opcode)) == 0x3f) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
197
  			u8 desc = *(data + HCI_COMMAND_HDR_SIZE);
8083ad1cf   Dean Jenkins   Bluetooth: Tidy-u...
198

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199
200
201
202
203
204
205
206
207
  			if ((desc & 0xf0) == 0xc0) {
  				data += HCI_COMMAND_HDR_SIZE + 1;
  				len  -= HCI_COMMAND_HDR_SIZE + 1;
  				chan = desc & 0x0f;
  			}
  		}
  	}
  
  	/* Max len of packet: (original len +4(bcsp hdr) +2(crc))*2
8805eea24   Maxim Zhukov   Bluetooth: hci_bc...
208
209
210
211
  	 * (because bytes 0xc0 and 0xdb are escaped, worst case is
  	 * when the packet is all made of 0xc0 and 0xdb :) )
  	 * + 2 (0xc0 delimiters at start and end).
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
212
213
214
215
  
  	nskb = alloc_skb((len + 6) * 2 + 2, GFP_ATOMIC);
  	if (!nskb)
  		return NULL;
618e8bc22   Marcel Holtmann   Bluetooth: Use ne...
216
  	hci_skb_pkt_type(nskb) = pkt_type;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
217
218
219
220
221
222
223
224
225
226
  
  	bcsp_slip_msgdelim(nskb);
  
  	hdr[0] = bcsp->rxseq_txack << 3;
  	bcsp->txack_req = 0;
  	BT_DBG("We request packet no %u to card", bcsp->rxseq_txack);
  
  	if (rel) {
  		hdr[0] |= 0x80 + bcsp->msgq_txseq;
  		BT_DBG("Sending packet with seqno %u", bcsp->msgq_txseq);
dd1589a43   David Howells   Bluetooth: Fix ab...
227
  		bcsp->msgq_txseq = (bcsp->msgq_txseq + 1) & 0x07;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
228
  	}
20dd6f59d   Marcel Holtmann   [Bluetooth] Remov...
229
230
231
  
  	if (bcsp->use_crc)
  		hdr[0] |= 0x40;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
232
233
234
235
236
237
238
239
  
  	hdr[1] = ((len << 4) & 0xff) | chan;
  	hdr[2] = len >> 4;
  	hdr[3] = ~(hdr[0] + hdr[1] + hdr[2]);
  
  	/* Put BCSP header */
  	for (i = 0; i < 4; i++) {
  		bcsp_slip_one_byte(nskb, hdr[i]);
20dd6f59d   Marcel Holtmann   [Bluetooth] Remov...
240
241
242
  
  		if (bcsp->use_crc)
  			bcsp_crc_update(&bcsp_txmsg_crc, hdr[i]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243
244
245
246
247
  	}
  
  	/* Put payload */
  	for (i = 0; i < len; i++) {
  		bcsp_slip_one_byte(nskb, data[i]);
20dd6f59d   Marcel Holtmann   [Bluetooth] Remov...
248
249
250
  
  		if (bcsp->use_crc)
  			bcsp_crc_update(&bcsp_txmsg_crc, data[i]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
251
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
252
  	/* Put CRC */
20dd6f59d   Marcel Holtmann   [Bluetooth] Remov...
253
  	if (bcsp->use_crc) {
c5ec51401   Harvey Harrison   bluetooth: hci_bc...
254
  		bcsp_txmsg_crc = bitrev16(bcsp_txmsg_crc);
8083ad1cf   Dean Jenkins   Bluetooth: Tidy-u...
255
256
  		bcsp_slip_one_byte(nskb, (u8)((bcsp_txmsg_crc >> 8) & 0x00ff));
  		bcsp_slip_one_byte(nskb, (u8)(bcsp_txmsg_crc & 0x00ff));
20dd6f59d   Marcel Holtmann   [Bluetooth] Remov...
257
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
258
259
260
261
262
263
264
265
266
267
268
  
  	bcsp_slip_msgdelim(nskb);
  	return nskb;
  }
  
  /* This is a rewrite of pkt_avail in ABCSP */
  static struct sk_buff *bcsp_dequeue(struct hci_uart *hu)
  {
  	struct bcsp_struct *bcsp = hu->priv;
  	unsigned long flags;
  	struct sk_buff *skb;
8805eea24   Maxim Zhukov   Bluetooth: hci_bc...
269

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
270
  	/* First of all, check for unreliable messages in the queue,
8083ad1cf   Dean Jenkins   Bluetooth: Tidy-u...
271
272
  	 * since they have priority
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
273

a08b15e66   Valentin Ilie   Bluetooth: Remove...
274
275
  	skb = skb_dequeue(&bcsp->unrel);
  	if (skb != NULL) {
618e8bc22   Marcel Holtmann   Bluetooth: Use ne...
276
277
278
279
  		struct sk_buff *nskb;
  
  		nskb = bcsp_prepare_pkt(bcsp, skb->data, skb->len,
  					hci_skb_pkt_type(skb));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
280
281
282
283
284
285
286
287
288
289
  		if (nskb) {
  			kfree_skb(skb);
  			return nskb;
  		} else {
  			skb_queue_head(&bcsp->unrel, skb);
  			BT_ERR("Could not dequeue pkt because alloc_skb failed");
  		}
  	}
  
  	/* Now, try to send a reliable pkt. We can only send a
8805eea24   Maxim Zhukov   Bluetooth: hci_bc...
290
291
292
  	 * reliable packet if the number of packets sent but not yet ack'ed
  	 * is < than the winsize
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
293

f89d75f22   Peter Zijlstra   [PATCH] lockdep: ...
294
  	spin_lock_irqsave_nested(&bcsp->unack.lock, flags, SINGLE_DEPTH_NESTING);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
295

a08b15e66   Valentin Ilie   Bluetooth: Remove...
296
297
298
  	if (bcsp->unack.qlen < BCSP_TXWINSIZE) {
  		skb = skb_dequeue(&bcsp->rel);
  		if (skb != NULL) {
618e8bc22   Marcel Holtmann   Bluetooth: Use ne...
299
300
301
302
  			struct sk_buff *nskb;
  
  			nskb = bcsp_prepare_pkt(bcsp, skb->data, skb->len,
  						hci_skb_pkt_type(skb));
a08b15e66   Valentin Ilie   Bluetooth: Remove...
303
304
305
306
307
308
309
310
311
  			if (nskb) {
  				__skb_queue_tail(&bcsp->unack, skb);
  				mod_timer(&bcsp->tbcsp, jiffies + HZ / 4);
  				spin_unlock_irqrestore(&bcsp->unack.lock, flags);
  				return nskb;
  			} else {
  				skb_queue_head(&bcsp->rel, skb);
  				BT_ERR("Could not dequeue pkt because alloc_skb failed");
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
312
313
314
315
  		}
  	}
  
  	spin_unlock_irqrestore(&bcsp->unack.lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
316
  	/* We could not send a reliable packet, either because there are
8805eea24   Maxim Zhukov   Bluetooth: hci_bc...
317
318
319
  	 * none or because there are too many unack'ed pkts. Did we receive
  	 * any packets we have not acknowledged yet ?
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
320
321
322
  
  	if (bcsp->txack_req) {
  		/* if so, craft an empty ACK pkt and send it on BCSP unreliable
8805eea24   Maxim Zhukov   Bluetooth: hci_bc...
323
324
  		 * channel 0
  		 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
  		struct sk_buff *nskb = bcsp_prepare_pkt(bcsp, NULL, 0, BCSP_ACK_PKT);
  		return nskb;
  	}
  
  	/* We have nothing to send */
  	return NULL;
  }
  
  static int bcsp_flush(struct hci_uart *hu)
  {
  	BT_DBG("hu %p", hu);
  	return 0;
  }
  
  /* Remove ack'ed packets */
  static void bcsp_pkt_cull(struct bcsp_struct *bcsp)
  {
8fc5387cb   David S. Miller   bluetooth: hci_bc...
342
  	struct sk_buff *skb, *tmp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
343
  	unsigned long flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
344
345
346
347
  	int i, pkts_to_be_removed;
  	u8 seqno;
  
  	spin_lock_irqsave(&bcsp->unack.lock, flags);
8fc5387cb   David S. Miller   bluetooth: hci_bc...
348
  	pkts_to_be_removed = skb_queue_len(&bcsp->unack);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
349
350
351
352
353
354
355
356
357
358
359
360
361
  	seqno = bcsp->msgq_txseq;
  
  	while (pkts_to_be_removed) {
  		if (bcsp->rxack == seqno)
  			break;
  		pkts_to_be_removed--;
  		seqno = (seqno - 1) & 0x07;
  	}
  
  	if (bcsp->rxack != seqno)
  		BT_ERR("Peer acked invalid packet");
  
  	BT_DBG("Removing %u pkts out of %u, up to seqno %u",
8fc5387cb   David S. Miller   bluetooth: hci_bc...
362
363
  	       pkts_to_be_removed, skb_queue_len(&bcsp->unack),
  	       (seqno - 1) & 0x07);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
364

8fc5387cb   David S. Miller   bluetooth: hci_bc...
365
366
  	i = 0;
  	skb_queue_walk_safe(&bcsp->unack, skb, tmp) {
d2e353f7c   Wending Weng   Bluetooth: Fix fa...
367
  		if (i >= pkts_to_be_removed)
8fc5387cb   David S. Miller   bluetooth: hci_bc...
368
  			break;
d2e353f7c   Wending Weng   Bluetooth: Fix fa...
369
  		i++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
370

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
371
372
  		__skb_unlink(skb, &bcsp->unack);
  		kfree_skb(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
373
  	}
0372a6627   Marcel Holtmann   [Bluetooth] Clean...
374

8fc5387cb   David S. Miller   bluetooth: hci_bc...
375
  	if (skb_queue_empty(&bcsp->unack))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
376
  		del_timer(&bcsp->tbcsp);
0372a6627   Marcel Holtmann   [Bluetooth] Clean...
377

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
378
379
380
381
382
383
384
  	spin_unlock_irqrestore(&bcsp->unack.lock, flags);
  
  	if (i != pkts_to_be_removed)
  		BT_ERR("Removed only %u out of %u pkts", i, pkts_to_be_removed);
  }
  
  /* Handle BCSP link-establishment packets. When we
8805eea24   Maxim Zhukov   Bluetooth: hci_bc...
385
386
387
   * detect a "sync" packet, symptom that the BT module has reset,
   * we do nothing :) (yet)
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
388
389
390
391
392
393
394
395
396
  static void bcsp_handle_le_pkt(struct hci_uart *hu)
  {
  	struct bcsp_struct *bcsp = hu->priv;
  	u8 conf_pkt[4]     = { 0xad, 0xef, 0xac, 0xed };
  	u8 conf_rsp_pkt[4] = { 0xde, 0xad, 0xd0, 0xd0 };
  	u8 sync_pkt[4]     = { 0xda, 0xdc, 0xed, 0xed };
  
  	/* spot "conf" pkts and reply with a "conf rsp" pkt */
  	if (bcsp->rx_skb->data[1] >> 4 == 4 && bcsp->rx_skb->data[2] == 0 &&
8083ad1cf   Dean Jenkins   Bluetooth: Tidy-u...
397
  	    !memcmp(&bcsp->rx_skb->data[4], conf_pkt, 4)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
398
399
400
401
402
  		struct sk_buff *nskb = alloc_skb(4, GFP_ATOMIC);
  
  		BT_DBG("Found a LE conf pkt");
  		if (!nskb)
  			return;
59ae1d127   Johannes Berg   networking: intro...
403
  		skb_put_data(nskb, conf_rsp_pkt, 4);
618e8bc22   Marcel Holtmann   Bluetooth: Use ne...
404
  		hci_skb_pkt_type(nskb) = BCSP_LE_PKT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
405
406
407
408
409
410
  
  		skb_queue_head(&bcsp->unrel, nskb);
  		hci_uart_tx_wakeup(hu);
  	}
  	/* Spot "sync" pkts. If we find one...disaster! */
  	else if (bcsp->rx_skb->data[1] >> 4 == 4 && bcsp->rx_skb->data[2] == 0 &&
8083ad1cf   Dean Jenkins   Bluetooth: Tidy-u...
411
  		 !memcmp(&bcsp->rx_skb->data[4], sync_pkt, 4)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
  		BT_ERR("Found a LE sync pkt, card has reset");
  	}
  }
  
  static inline void bcsp_unslip_one_byte(struct bcsp_struct *bcsp, unsigned char byte)
  {
  	const u8 c0 = 0xc0, db = 0xdb;
  
  	switch (bcsp->rx_esc_state) {
  	case BCSP_ESCSTATE_NOESC:
  		switch (byte) {
  		case 0xdb:
  			bcsp->rx_esc_state = BCSP_ESCSTATE_ESC;
  			break;
  		default:
59ae1d127   Johannes Berg   networking: intro...
427
  			skb_put_data(bcsp->rx_skb, &byte, 1);
fe8de008e   Prasanna Karthik   Bluetooth: hci_bc...
428
  			if ((bcsp->rx_skb->data[0] & 0x40) != 0 &&
8083ad1cf   Dean Jenkins   Bluetooth: Tidy-u...
429
  			    bcsp->rx_state != BCSP_W4_CRC)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
430
431
432
433
434
435
436
437
  				bcsp_crc_update(&bcsp->message_crc, byte);
  			bcsp->rx_count--;
  		}
  		break;
  
  	case BCSP_ESCSTATE_ESC:
  		switch (byte) {
  		case 0xdc:
59ae1d127   Johannes Berg   networking: intro...
438
  			skb_put_data(bcsp->rx_skb, &c0, 1);
fe8de008e   Prasanna Karthik   Bluetooth: hci_bc...
439
  			if ((bcsp->rx_skb->data[0] & 0x40) != 0 &&
8083ad1cf   Dean Jenkins   Bluetooth: Tidy-u...
440
  			    bcsp->rx_state != BCSP_W4_CRC)
fe8de008e   Prasanna Karthik   Bluetooth: hci_bc...
441
  				bcsp_crc_update(&bcsp->message_crc, 0xc0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
442
443
444
445
446
  			bcsp->rx_esc_state = BCSP_ESCSTATE_NOESC;
  			bcsp->rx_count--;
  			break;
  
  		case 0xdd:
59ae1d127   Johannes Berg   networking: intro...
447
  			skb_put_data(bcsp->rx_skb, &db, 1);
fe8de008e   Prasanna Karthik   Bluetooth: hci_bc...
448
  			if ((bcsp->rx_skb->data[0] & 0x40) != 0 &&
8083ad1cf   Dean Jenkins   Bluetooth: Tidy-u...
449
  			    bcsp->rx_state != BCSP_W4_CRC)
fe8de008e   Prasanna Karthik   Bluetooth: hci_bc...
450
  				bcsp_crc_update(&bcsp->message_crc, 0xdb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
451
452
453
454
455
  			bcsp->rx_esc_state = BCSP_ESCSTATE_NOESC;
  			bcsp->rx_count--;
  			break;
  
  		default:
fe8de008e   Prasanna Karthik   Bluetooth: hci_bc...
456
  			BT_ERR("Invalid byte %02x after esc byte", byte);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
457
458
459
460
461
462
463
  			kfree_skb(bcsp->rx_skb);
  			bcsp->rx_skb = NULL;
  			bcsp->rx_state = BCSP_W4_PKT_DELIMITER;
  			bcsp->rx_count = 0;
  		}
  	}
  }
858119e15   Arjan van de Ven   [PATCH] Unlinline...
464
  static void bcsp_complete_rx_pkt(struct hci_uart *hu)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
465
466
  {
  	struct bcsp_struct *bcsp = hu->priv;
37332ddc1   Dean Jenkins   Bluetooth: BCSP f...
467
  	int pass_up = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
468
469
470
  
  	if (bcsp->rx_skb->data[0] & 0x80) {	/* reliable pkt */
  		BT_DBG("Received seqno %u from card", bcsp->rxseq_txack);
37332ddc1   Dean Jenkins   Bluetooth: BCSP f...
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
  
  		/* check the rx sequence number is as expected */
  		if ((bcsp->rx_skb->data[0] & 0x07) == bcsp->rxseq_txack) {
  			bcsp->rxseq_txack++;
  			bcsp->rxseq_txack %= 0x8;
  		} else {
  			/* handle re-transmitted packet or
  			 * when packet was missed
  			 */
  			BT_ERR("Out-of-order packet arrived, got %u expected %u",
  			       bcsp->rx_skb->data[0] & 0x07, bcsp->rxseq_txack);
  
  			/* do not process out-of-order packet payload */
  			pass_up = 2;
  		}
  
  		/* send current txack value to all received reliable packets */
  		bcsp->txack_req = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
489
490
491
492
493
494
495
  
  		/* If needed, transmit an ack pkt */
  		hci_uart_tx_wakeup(hu);
  	}
  
  	bcsp->rxack = (bcsp->rx_skb->data[0] >> 3) & 0x07;
  	BT_DBG("Request for pkt %u from card", bcsp->rxack);
37332ddc1   Dean Jenkins   Bluetooth: BCSP f...
496
497
498
  	/* handle received ACK indications,
  	 * including those from out-of-order packets
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
499
  	bcsp_pkt_cull(bcsp);
37332ddc1   Dean Jenkins   Bluetooth: BCSP f...
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
  
  	if (pass_up != 2) {
  		if ((bcsp->rx_skb->data[1] & 0x0f) == 6 &&
  		    (bcsp->rx_skb->data[0] & 0x80)) {
  			hci_skb_pkt_type(bcsp->rx_skb) = HCI_ACLDATA_PKT;
  			pass_up = 1;
  		} else if ((bcsp->rx_skb->data[1] & 0x0f) == 5 &&
  			   (bcsp->rx_skb->data[0] & 0x80)) {
  			hci_skb_pkt_type(bcsp->rx_skb) = HCI_EVENT_PKT;
  			pass_up = 1;
  		} else if ((bcsp->rx_skb->data[1] & 0x0f) == 7) {
  			hci_skb_pkt_type(bcsp->rx_skb) = HCI_SCODATA_PKT;
  			pass_up = 1;
  		} else if ((bcsp->rx_skb->data[1] & 0x0f) == 1 &&
  			   !(bcsp->rx_skb->data[0] & 0x80)) {
  			bcsp_handle_le_pkt(hu);
  			pass_up = 0;
  		} else {
  			pass_up = 0;
  		}
  	}
  
  	if (pass_up == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
523
524
525
526
527
528
529
530
531
532
533
534
  		struct hci_event_hdr hdr;
  		u8 desc = (bcsp->rx_skb->data[1] & 0x0f);
  
  		if (desc != 0 && desc != 1) {
  			if (hciextn) {
  				desc |= 0xc0;
  				skb_pull(bcsp->rx_skb, 4);
  				memcpy(skb_push(bcsp->rx_skb, 1), &desc, 1);
  
  				hdr.evt = 0xff;
  				hdr.plen = bcsp->rx_skb->len;
  				memcpy(skb_push(bcsp->rx_skb, HCI_EVENT_HDR_SIZE), &hdr, HCI_EVENT_HDR_SIZE);
618e8bc22   Marcel Holtmann   Bluetooth: Use ne...
535
  				hci_skb_pkt_type(bcsp->rx_skb) = HCI_EVENT_PKT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
536

e1a261706   Marcel Holtmann   Bluetooth: Provid...
537
  				hci_recv_frame(hu->hdev, bcsp->rx_skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
538
  			} else {
fe8de008e   Prasanna Karthik   Bluetooth: hci_bc...
539
  				BT_ERR("Packet for unknown channel (%u %s)",
8083ad1cf   Dean Jenkins   Bluetooth: Tidy-u...
540
541
542
  				       bcsp->rx_skb->data[1] & 0x0f,
  				       bcsp->rx_skb->data[0] & 0x80 ?
  				       "reliable" : "unreliable");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
543
544
545
546
  				kfree_skb(bcsp->rx_skb);
  			}
  		} else
  			kfree_skb(bcsp->rx_skb);
37332ddc1   Dean Jenkins   Bluetooth: BCSP f...
547
  	} else if (pass_up == 1) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
548
549
  		/* Pull out BCSP hdr */
  		skb_pull(bcsp->rx_skb, 4);
e1a261706   Marcel Holtmann   Bluetooth: Provid...
550
  		hci_recv_frame(hu->hdev, bcsp->rx_skb);
37332ddc1   Dean Jenkins   Bluetooth: BCSP f...
551
552
553
554
555
  	} else {
  		/* ignore packet payload of already ACKed re-transmitted
  		 * packets or when a packet was missed in the BCSP window
  		 */
  		kfree_skb(bcsp->rx_skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
556
  	}
0372a6627   Marcel Holtmann   [Bluetooth] Clean...
557

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
558
559
560
  	bcsp->rx_state = BCSP_W4_PKT_DELIMITER;
  	bcsp->rx_skb = NULL;
  }
c5ec51401   Harvey Harrison   bluetooth: hci_bc...
561
562
563
564
  static u16 bscp_get_crc(struct bcsp_struct *bcsp)
  {
  	return get_unaligned_be16(&bcsp->rx_skb->data[bcsp->rx_skb->len - 2]);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
565
  /* Recv data */
9d1c40ebb   Marcel Holtmann   Bluetooth: hci_ua...
566
  static int bcsp_recv(struct hci_uart *hu, const void *data, int count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
567
568
  {
  	struct bcsp_struct *bcsp = hu->priv;
9d1c40ebb   Marcel Holtmann   Bluetooth: hci_ua...
569
  	const unsigned char *ptr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
570

8805eea24   Maxim Zhukov   Bluetooth: hci_bc...
571
  	BT_DBG("hu %p count %d rx_state %d rx_count %ld",
8083ad1cf   Dean Jenkins   Bluetooth: Tidy-u...
572
  	       hu, count, bcsp->rx_state, bcsp->rx_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
573
574
575
576
577
578
579
  
  	ptr = data;
  	while (count) {
  		if (bcsp->rx_count) {
  			if (*ptr == 0xc0) {
  				BT_ERR("Short BCSP packet");
  				kfree_skb(bcsp->rx_skb);
cf94da6f5   Tomas Bortoli   Bluetooth: Fix in...
580
  				bcsp->rx_skb = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
581
582
583
584
585
586
587
588
589
590
591
  				bcsp->rx_state = BCSP_W4_PKT_START;
  				bcsp->rx_count = 0;
  			} else
  				bcsp_unslip_one_byte(bcsp, *ptr);
  
  			ptr++; count--;
  			continue;
  		}
  
  		switch (bcsp->rx_state) {
  		case BCSP_W4_BCSP_HDR:
8083ad1cf   Dean Jenkins   Bluetooth: Tidy-u...
592
593
  			if ((0xff & (u8)~(bcsp->rx_skb->data[0] + bcsp->rx_skb->data[1] +
  			    bcsp->rx_skb->data[2])) != bcsp->rx_skb->data[3]) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
594
595
  				BT_ERR("Error in BCSP hdr checksum");
  				kfree_skb(bcsp->rx_skb);
cf94da6f5   Tomas Bortoli   Bluetooth: Fix in...
596
  				bcsp->rx_skb = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
597
598
599
600
  				bcsp->rx_state = BCSP_W4_PKT_DELIMITER;
  				bcsp->rx_count = 0;
  				continue;
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
601
  			bcsp->rx_state = BCSP_W4_DATA;
8805eea24   Maxim Zhukov   Bluetooth: hci_bc...
602
  			bcsp->rx_count = (bcsp->rx_skb->data[1] >> 4) +
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
603
604
605
606
607
608
609
610
611
612
613
614
  					(bcsp->rx_skb->data[2] << 4);	/* May be 0 */
  			continue;
  
  		case BCSP_W4_DATA:
  			if (bcsp->rx_skb->data[0] & 0x40) {	/* pkt with crc */
  				bcsp->rx_state = BCSP_W4_CRC;
  				bcsp->rx_count = 2;
  			} else
  				bcsp_complete_rx_pkt(hu);
  			continue;
  
  		case BCSP_W4_CRC:
c5ec51401   Harvey Harrison   bluetooth: hci_bc...
615
  			if (bitrev16(bcsp->message_crc) != bscp_get_crc(bcsp)) {
8805eea24   Maxim Zhukov   Bluetooth: hci_bc...
616
  				BT_ERR("Checksum failed: computed %04x received %04x",
8083ad1cf   Dean Jenkins   Bluetooth: Tidy-u...
617
618
  				       bitrev16(bcsp->message_crc),
  				       bscp_get_crc(bcsp));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
619
620
  
  				kfree_skb(bcsp->rx_skb);
cf94da6f5   Tomas Bortoli   Bluetooth: Fix in...
621
  				bcsp->rx_skb = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
  				bcsp->rx_state = BCSP_W4_PKT_DELIMITER;
  				bcsp->rx_count = 0;
  				continue;
  			}
  			skb_trim(bcsp->rx_skb, bcsp->rx_skb->len - 2);
  			bcsp_complete_rx_pkt(hu);
  			continue;
  
  		case BCSP_W4_PKT_DELIMITER:
  			switch (*ptr) {
  			case 0xc0:
  				bcsp->rx_state = BCSP_W4_PKT_START;
  				break;
  			default:
  				/*BT_ERR("Ignoring byte %02x", *ptr);*/
  				break;
  			}
  			ptr++; count--;
  			break;
  
  		case BCSP_W4_PKT_START:
  			switch (*ptr) {
  			case 0xc0:
  				ptr++; count--;
  				break;
  
  			default:
  				bcsp->rx_state = BCSP_W4_BCSP_HDR;
  				bcsp->rx_count = 4;
  				bcsp->rx_esc_state = BCSP_ESCSTATE_NOESC;
  				BCSP_CRC_INIT(bcsp->message_crc);
0372a6627   Marcel Holtmann   [Bluetooth] Clean...
653

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
654
  				/* Do not increment ptr or decrement count
8805eea24   Maxim Zhukov   Bluetooth: hci_bc...
655
656
657
  				 * Allocate packet. Max len of a BCSP pkt=
  				 * 0xFFF (payload) +4 (header) +2 (crc)
  				 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
658
659
660
661
662
663
664
665
  
  				bcsp->rx_skb = bt_skb_alloc(0x1005, GFP_ATOMIC);
  				if (!bcsp->rx_skb) {
  					BT_ERR("Can't allocate mem for new packet");
  					bcsp->rx_state = BCSP_W4_PKT_DELIMITER;
  					bcsp->rx_count = 0;
  					return 0;
  				}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
666
667
668
669
670
671
672
673
674
  				break;
  			}
  			break;
  		}
  	}
  	return count;
  }
  
  	/* Arrange to retransmit all messages in the relq. */
043560528   Kees Cook   Bluetooth: Conver...
675
  static void bcsp_timed_event(struct timer_list *t)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
676
  {
043560528   Kees Cook   Bluetooth: Conver...
677
678
  	struct bcsp_struct *bcsp = from_timer(bcsp, t, tbcsp);
  	struct hci_uart *hu = bcsp->hu;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
679
680
681
682
  	struct sk_buff *skb;
  	unsigned long flags;
  
  	BT_DBG("hu %p retransmitting %u pkts", hu, bcsp->unack.qlen);
f89d75f22   Peter Zijlstra   [PATCH] lockdep: ...
683
  	spin_lock_irqsave_nested(&bcsp->unack.lock, flags, SINGLE_DEPTH_NESTING);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
  
  	while ((skb = __skb_dequeue_tail(&bcsp->unack)) != NULL) {
  		bcsp->msgq_txseq = (bcsp->msgq_txseq - 1) & 0x07;
  		skb_queue_head(&bcsp->rel, skb);
  	}
  
  	spin_unlock_irqrestore(&bcsp->unack.lock, flags);
  
  	hci_uart_tx_wakeup(hu);
  }
  
  static int bcsp_open(struct hci_uart *hu)
  {
  	struct bcsp_struct *bcsp;
  
  	BT_DBG("hu %p", hu);
c063af346   David Herrmann   Bluetooth: hci-ua...
700
  	bcsp = kzalloc(sizeof(*bcsp), GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
701
702
  	if (!bcsp)
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
703
704
  
  	hu->priv = bcsp;
043560528   Kees Cook   Bluetooth: Conver...
705
  	bcsp->hu = hu;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
706
707
708
  	skb_queue_head_init(&bcsp->unack);
  	skb_queue_head_init(&bcsp->rel);
  	skb_queue_head_init(&bcsp->unrel);
043560528   Kees Cook   Bluetooth: Conver...
709
  	timer_setup(&bcsp->tbcsp, bcsp_timed_event, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
710
711
  
  	bcsp->rx_state = BCSP_W4_PKT_DELIMITER;
20dd6f59d   Marcel Holtmann   [Bluetooth] Remov...
712
713
  	if (txcrc)
  		bcsp->use_crc = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
714
715
716
717
718
719
  	return 0;
  }
  
  static int bcsp_close(struct hci_uart *hu)
  {
  	struct bcsp_struct *bcsp = hu->priv;
c327cddd1   Michael Knudsen   Bluetooth: Stop B...
720
721
  
  	del_timer_sync(&bcsp->tbcsp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
722
723
724
725
726
727
728
  	hu->priv = NULL;
  
  	BT_DBG("hu %p", hu);
  
  	skb_queue_purge(&bcsp->unack);
  	skb_queue_purge(&bcsp->rel);
  	skb_queue_purge(&bcsp->unrel);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
729

4ce9146e0   Tomas Bortoli   Bluetooth: hci_bc...
730
731
732
733
  	if (bcsp->rx_skb) {
  		kfree_skb(bcsp->rx_skb);
  		bcsp->rx_skb = NULL;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
734
735
736
  	kfree(bcsp);
  	return 0;
  }
4ee7ef198   Marcel Holtmann   Bluetooth: hci_ua...
737
  static const struct hci_uart_proto bcsp = {
0372a6627   Marcel Holtmann   [Bluetooth] Clean...
738
  	.id		= HCI_UART_BCSP,
7c40fb8db   Marcel Holtmann   Bluetooth: hci_ua...
739
  	.name		= "BCSP",
0372a6627   Marcel Holtmann   [Bluetooth] Clean...
740
741
742
743
744
745
  	.open		= bcsp_open,
  	.close		= bcsp_close,
  	.enqueue	= bcsp_enqueue,
  	.dequeue	= bcsp_dequeue,
  	.recv		= bcsp_recv,
  	.flush		= bcsp_flush
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
746
  };
f2b94bb9e   Gustavo F. Padovan   Bluetooth: Add __...
747
  int __init bcsp_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
748
  {
01009eec7   Marcel Holtmann   Bluetooth: hci_ua...
749
  	return hci_uart_register_proto(&bcsp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
750
  }
f2b94bb9e   Gustavo F. Padovan   Bluetooth: Add __...
751
  int __exit bcsp_deinit(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
752
753
754
  {
  	return hci_uart_unregister_proto(&bcsp);
  }
20dd6f59d   Marcel Holtmann   [Bluetooth] Remov...
755
756
  module_param(txcrc, bool, 0644);
  MODULE_PARM_DESC(txcrc, "Transmit CRC with every BCSP packet");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
757
758
  module_param(hciextn, bool, 0644);
  MODULE_PARM_DESC(hciextn, "Convert HCI Extensions into BCSP packets");