1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25#include <linux/module.h>
26
27#include <linux/kernel.h>
28#include <linux/init.h>
29#include <linux/types.h>
30#include <linux/fcntl.h>
31#include <linux/interrupt.h>
32#include <linux/ptrace.h>
33#include <linux/poll.h>
34
35#include <linux/slab.h>
36#include <linux/tty.h>
37#include <linux/errno.h>
38#include <linux/string.h>
39#include <linux/signal.h>
40#include <linux/ioctl.h>
41#include <linux/skbuff.h>
42
43#include <net/bluetooth/bluetooth.h>
44#include <net/bluetooth/hci_core.h>
45
46#include "hci_uart.h"
47
48#ifndef CONFIG_BT_HCIUART_DEBUG
49#undef BT_DBG
50#define BT_DBG( A... )
51#endif
52
53#define VERSION "0.3"
54
55static int txcrc = 1;
56static int hciextn = 1;
57
58#define BCSP_TXWINSIZE 4
59
60#define BCSP_ACK_PKT 0x05
61#define BCSP_LE_PKT 0x06
62
63struct bcsp_struct {
64 struct sk_buff_head unack;
65 struct sk_buff_head rel;
66 struct sk_buff_head unrel;
67
68 unsigned long rx_count;
69 struct sk_buff *rx_skb;
70 u8 rxseq_txack;
71 u8 rxack;
72 struct timer_list tbcsp;
73
74 enum {
75 BCSP_W4_PKT_DELIMITER,
76 BCSP_W4_PKT_START,
77 BCSP_W4_BCSP_HDR,
78 BCSP_W4_DATA,
79 BCSP_W4_CRC
80 } rx_state;
81
82 enum {
83 BCSP_ESCSTATE_NOESC,
84 BCSP_ESCSTATE_ESC
85 } rx_esc_state;
86
87 u8 use_crc;
88 u16 message_crc;
89 u8 txack_req;
90
91
92 u8 msgq_txseq;
93};
94
95
96
97
98
99
100static const u16 crc_table[] = {
101 0x0000, 0x1081, 0x2102, 0x3183,
102 0x4204, 0x5285, 0x6306, 0x7387,
103 0x8408, 0x9489, 0xa50a, 0xb58b,
104 0xc60c, 0xd68d, 0xe70e, 0xf78f
105};
106
107
108#define BCSP_CRC_INIT(x) x = 0xffff
109
110
111
112
113
114
115
116
117static void bcsp_crc_update(u16 *crc, u8 d)
118{
119 u16 reg = *crc;
120
121 reg = (reg >> 4) ^ crc_table[(reg ^ d) & 0x000f];
122 reg = (reg >> 4) ^ crc_table[(reg ^ (d >> 4)) & 0x000f];
123
124 *crc = reg;
125}
126
127
128
129
130
131
132
133
134
135static u16 bcsp_crc_reverse(u16 crc)
136{
137 u16 b, rev;
138
139 for (b = 0, rev = 0; b < 16; b++) {
140 rev = rev << 1;
141 rev |= (crc & 1);
142 crc = crc >> 1;
143 }
144
145 return (rev);
146}
147
148
149
150static void bcsp_slip_msgdelim(struct sk_buff *skb)
151{
152 const char pkt_delim = 0xc0;
153
154 memcpy(skb_put(skb, 1), &pkt_delim, 1);
155}
156
157static void bcsp_slip_one_byte(struct sk_buff *skb, u8 c)
158{
159 const char esc_c0[2] = { 0xdb, 0xdc };
160 const char esc_db[2] = { 0xdb, 0xdd };
161
162 switch (c) {
163 case 0xc0:
164 memcpy(skb_put(skb, 2), &esc_c0, 2);
165 break;
166 case 0xdb:
167 memcpy(skb_put(skb, 2), &esc_db, 2);
168 break;
169 default:
170 memcpy(skb_put(skb, 1), &c, 1);
171 }
172}
173
174static int bcsp_enqueue(struct hci_uart *hu, struct sk_buff *skb)
175{
176 struct bcsp_struct *bcsp = hu->priv;
177
178 if (skb->len > 0xFFF) {
179 BT_ERR("Packet too long");
180 kfree_skb(skb);
181 return 0;
182 }
183
184 switch (bt_cb(skb)->pkt_type) {
185 case HCI_ACLDATA_PKT:
186 case HCI_COMMAND_PKT:
187 skb_queue_tail(&bcsp->rel, skb);
188 break;
189
190 case HCI_SCODATA_PKT:
191 skb_queue_tail(&bcsp->unrel, skb);
192 break;
193
194 default:
195 BT_ERR("Unknown packet type");
196 kfree_skb(skb);
197 break;
198 }
199
200 return 0;
201}
202
203static struct sk_buff *bcsp_prepare_pkt(struct bcsp_struct *bcsp, u8 *data,
204 int len, int pkt_type)
205{
206 struct sk_buff *nskb;
207 u8 hdr[4], chan;
208 u16 BCSP_CRC_INIT(bcsp_txmsg_crc);
209 int rel, i;
210
211 switch (pkt_type) {
212 case HCI_ACLDATA_PKT:
213 chan = 6;
214 rel = 1;
215 break;
216 case HCI_COMMAND_PKT:
217 chan = 5;
218 rel = 1;
219 break;
220 case HCI_SCODATA_PKT:
221 chan = 7;
222 rel = 0;
223 break;
224 case BCSP_LE_PKT:
225 chan = 1;
226 rel = 0;
227 break;
228 case BCSP_ACK_PKT:
229 chan = 0;
230 rel = 0;
231 break;
232 default:
233 BT_ERR("Unknown packet type");
234 return NULL;
235 }
236
237 if (hciextn && chan == 5) {
238 struct hci_command_hdr *hdr = (struct hci_command_hdr *) data;
239
240
241 if (hci_opcode_ogf(__le16_to_cpu(hdr->opcode)) == 0x3f) {
242 u8 desc = *(data + HCI_COMMAND_HDR_SIZE);
243 if ((desc & 0xf0) == 0xc0) {
244 data += HCI_COMMAND_HDR_SIZE + 1;
245 len -= HCI_COMMAND_HDR_SIZE + 1;
246 chan = desc & 0x0f;
247 }
248 }
249 }
250
251
252
253
254
255
256 nskb = alloc_skb((len + 6) * 2 + 2, GFP_ATOMIC);
257 if (!nskb)
258 return NULL;
259
260 bt_cb(nskb)->pkt_type = pkt_type;
261
262 bcsp_slip_msgdelim(nskb);
263
264 hdr[0] = bcsp->rxseq_txack << 3;
265 bcsp->txack_req = 0;
266 BT_DBG("We request packet no %u to card", bcsp->rxseq_txack);
267
268 if (rel) {
269 hdr[0] |= 0x80 + bcsp->msgq_txseq;
270 BT_DBG("Sending packet with seqno %u", bcsp->msgq_txseq);
271 bcsp->msgq_txseq = ++(bcsp->msgq_txseq) & 0x07;
272 }
273
274 if (bcsp->use_crc)
275 hdr[0] |= 0x40;
276
277 hdr[1] = ((len << 4) & 0xff) | chan;
278 hdr[2] = len >> 4;
279 hdr[3] = ~(hdr[0] + hdr[1] + hdr[2]);
280
281
282 for (i = 0; i < 4; i++) {
283 bcsp_slip_one_byte(nskb, hdr[i]);
284
285 if (bcsp->use_crc)
286 bcsp_crc_update(&bcsp_txmsg_crc, hdr[i]);
287 }
288
289
290 for (i = 0; i < len; i++) {
291 bcsp_slip_one_byte(nskb, data[i]);
292
293 if (bcsp->use_crc)
294 bcsp_crc_update(&bcsp_txmsg_crc, data[i]);
295 }
296
297
298 if (bcsp->use_crc) {
299 bcsp_txmsg_crc = bcsp_crc_reverse(bcsp_txmsg_crc);
300 bcsp_slip_one_byte(nskb, (u8) ((bcsp_txmsg_crc >> 8) & 0x00ff));
301 bcsp_slip_one_byte(nskb, (u8) (bcsp_txmsg_crc & 0x00ff));
302 }
303
304 bcsp_slip_msgdelim(nskb);
305 return nskb;
306}
307
308
309static struct sk_buff *bcsp_dequeue(struct hci_uart *hu)
310{
311 struct bcsp_struct *bcsp = hu->priv;
312 unsigned long flags;
313 struct sk_buff *skb;
314
315
316
317
318 if ((skb = skb_dequeue(&bcsp->unrel)) != NULL) {
319 struct sk_buff *nskb = bcsp_prepare_pkt(bcsp, skb->data, skb->len, bt_cb(skb)->pkt_type);
320 if (nskb) {
321 kfree_skb(skb);
322 return nskb;
323 } else {
324 skb_queue_head(&bcsp->unrel, skb);
325 BT_ERR("Could not dequeue pkt because alloc_skb failed");
326 }
327 }
328
329
330
331
332
333 spin_lock_irqsave_nested(&bcsp->unack.lock, flags, SINGLE_DEPTH_NESTING);
334
335 if (bcsp->unack.qlen < BCSP_TXWINSIZE && (skb = skb_dequeue(&bcsp->rel)) != NULL) {
336 struct sk_buff *nskb = bcsp_prepare_pkt(bcsp, skb->data, skb->len, bt_cb(skb)->pkt_type);
337 if (nskb) {
338 __skb_queue_tail(&bcsp->unack, skb);
339 mod_timer(&bcsp->tbcsp, jiffies + HZ / 4);
340 spin_unlock_irqrestore(&bcsp->unack.lock, flags);
341 return nskb;
342 } else {
343 skb_queue_head(&bcsp->rel, skb);
344 BT_ERR("Could not dequeue pkt because alloc_skb failed");
345 }
346 }
347
348 spin_unlock_irqrestore(&bcsp->unack.lock, flags);
349
350
351
352
353
354 if (bcsp->txack_req) {
355
356
357 struct sk_buff *nskb = bcsp_prepare_pkt(bcsp, NULL, 0, BCSP_ACK_PKT);
358 return nskb;
359 }
360
361
362 return NULL;
363}
364
365static int bcsp_flush(struct hci_uart *hu)
366{
367 BT_DBG("hu %p", hu);
368 return 0;
369}
370
371
372static void bcsp_pkt_cull(struct bcsp_struct *bcsp)
373{
374 unsigned long flags;
375 struct sk_buff *skb;
376 int i, pkts_to_be_removed;
377 u8 seqno;
378
379 spin_lock_irqsave(&bcsp->unack.lock, flags);
380
381 pkts_to_be_removed = bcsp->unack.qlen;
382 seqno = bcsp->msgq_txseq;
383
384 while (pkts_to_be_removed) {
385 if (bcsp->rxack == seqno)
386 break;
387 pkts_to_be_removed--;
388 seqno = (seqno - 1) & 0x07;
389 }
390
391 if (bcsp->rxack != seqno)
392 BT_ERR("Peer acked invalid packet");
393
394 BT_DBG("Removing %u pkts out of %u, up to seqno %u",
395 pkts_to_be_removed, bcsp->unack.qlen, (seqno - 1) & 0x07);
396
397 for (i = 0, skb = ((struct sk_buff *) &bcsp->unack)->next; i < pkts_to_be_removed
398 && skb != (struct sk_buff *) &bcsp->unack; i++) {
399 struct sk_buff *nskb;
400
401 nskb = skb->next;
402 __skb_unlink(skb, &bcsp->unack);
403 kfree_skb(skb);
404 skb = nskb;
405 }
406
407 if (bcsp->unack.qlen == 0)
408 del_timer(&bcsp->tbcsp);
409
410 spin_unlock_irqrestore(&bcsp->unack.lock, flags);
411
412 if (i != pkts_to_be_removed)
413 BT_ERR("Removed only %u out of %u pkts", i, pkts_to_be_removed);
414}
415
416
417
418
419static void bcsp_handle_le_pkt(struct hci_uart *hu)
420{
421 struct bcsp_struct *bcsp = hu->priv;
422 u8 conf_pkt[4] = { 0xad, 0xef, 0xac, 0xed };
423 u8 conf_rsp_pkt[4] = { 0xde, 0xad, 0xd0, 0xd0 };
424 u8 sync_pkt[4] = { 0xda, 0xdc, 0xed, 0xed };
425
426
427 if (bcsp->rx_skb->data[1] >> 4 == 4 && bcsp->rx_skb->data[2] == 0 &&
428 !memcmp(&bcsp->rx_skb->data[4], conf_pkt, 4)) {
429 struct sk_buff *nskb = alloc_skb(4, GFP_ATOMIC);
430
431 BT_DBG("Found a LE conf pkt");
432 if (!nskb)
433 return;
434 memcpy(skb_put(nskb, 4), conf_rsp_pkt, 4);
435 bt_cb(nskb)->pkt_type = BCSP_LE_PKT;
436
437 skb_queue_head(&bcsp->unrel, nskb);
438 hci_uart_tx_wakeup(hu);
439 }
440
441 else if (bcsp->rx_skb->data[1] >> 4 == 4 && bcsp->rx_skb->data[2] == 0 &&
442 !memcmp(&bcsp->rx_skb->data[4], sync_pkt, 4)) {
443 BT_ERR("Found a LE sync pkt, card has reset");
444 }
445}
446
447static inline void bcsp_unslip_one_byte(struct bcsp_struct *bcsp, unsigned char byte)
448{
449 const u8 c0 = 0xc0, db = 0xdb;
450
451 switch (bcsp->rx_esc_state) {
452 case BCSP_ESCSTATE_NOESC:
453 switch (byte) {
454 case 0xdb:
455 bcsp->rx_esc_state = BCSP_ESCSTATE_ESC;
456 break;
457 default:
458 memcpy(skb_put(bcsp->rx_skb, 1), &byte, 1);
459 if ((bcsp->rx_skb-> data[0] & 0x40) != 0 &&
460 bcsp->rx_state != BCSP_W4_CRC)
461 bcsp_crc_update(&bcsp->message_crc, byte);
462 bcsp->rx_count--;
463 }
464 break;
465
466 case BCSP_ESCSTATE_ESC:
467 switch (byte) {
468 case 0xdc:
469 memcpy(skb_put(bcsp->rx_skb, 1), &c0, 1);
470 if ((bcsp->rx_skb-> data[0] & 0x40) != 0 &&
471 bcsp->rx_state != BCSP_W4_CRC)
472 bcsp_crc_update(&bcsp-> message_crc, 0xc0);
473 bcsp->rx_esc_state = BCSP_ESCSTATE_NOESC;
474 bcsp->rx_count--;
475 break;
476
477 case 0xdd:
478 memcpy(skb_put(bcsp->rx_skb, 1), &db, 1);
479 if ((bcsp->rx_skb-> data[0] & 0x40) != 0 &&
480 bcsp->rx_state != BCSP_W4_CRC)
481 bcsp_crc_update(&bcsp-> message_crc, 0xdb);
482 bcsp->rx_esc_state = BCSP_ESCSTATE_NOESC;
483 bcsp->rx_count--;
484 break;
485
486 default:
487 BT_ERR ("Invalid byte %02x after esc byte", byte);
488 kfree_skb(bcsp->rx_skb);
489 bcsp->rx_skb = NULL;
490 bcsp->rx_state = BCSP_W4_PKT_DELIMITER;
491 bcsp->rx_count = 0;
492 }
493 }
494}
495
496static void bcsp_complete_rx_pkt(struct hci_uart *hu)
497{
498 struct bcsp_struct *bcsp = hu->priv;
499 int pass_up;
500
501 if (bcsp->rx_skb->data[0] & 0x80) {
502 BT_DBG("Received seqno %u from card", bcsp->rxseq_txack);
503 bcsp->rxseq_txack++;
504 bcsp->rxseq_txack %= 0x8;
505 bcsp->txack_req = 1;
506
507
508 hci_uart_tx_wakeup(hu);
509 }
510
511 bcsp->rxack = (bcsp->rx_skb->data[0] >> 3) & 0x07;
512 BT_DBG("Request for pkt %u from card", bcsp->rxack);
513
514 bcsp_pkt_cull(bcsp);
515 if ((bcsp->rx_skb->data[1] & 0x0f) == 6 &&
516 bcsp->rx_skb->data[0] & 0x80) {
517 bt_cb(bcsp->rx_skb)->pkt_type = HCI_ACLDATA_PKT;
518 pass_up = 1;
519 } else if ((bcsp->rx_skb->data[1] & 0x0f) == 5 &&
520 bcsp->rx_skb->data[0] & 0x80) {
521 bt_cb(bcsp->rx_skb)->pkt_type = HCI_EVENT_PKT;
522 pass_up = 1;
523 } else if ((bcsp->rx_skb->data[1] & 0x0f) == 7) {
524 bt_cb(bcsp->rx_skb)->pkt_type = HCI_SCODATA_PKT;
525 pass_up = 1;
526 } else if ((bcsp->rx_skb->data[1] & 0x0f) == 1 &&
527 !(bcsp->rx_skb->data[0] & 0x80)) {
528 bcsp_handle_le_pkt(hu);
529 pass_up = 0;
530 } else
531 pass_up = 0;
532
533 if (!pass_up) {
534 struct hci_event_hdr hdr;
535 u8 desc = (bcsp->rx_skb->data[1] & 0x0f);
536
537 if (desc != 0 && desc != 1) {
538 if (hciextn) {
539 desc |= 0xc0;
540 skb_pull(bcsp->rx_skb, 4);
541 memcpy(skb_push(bcsp->rx_skb, 1), &desc, 1);
542
543 hdr.evt = 0xff;
544 hdr.plen = bcsp->rx_skb->len;
545 memcpy(skb_push(bcsp->rx_skb, HCI_EVENT_HDR_SIZE), &hdr, HCI_EVENT_HDR_SIZE);
546 bt_cb(bcsp->rx_skb)->pkt_type = HCI_EVENT_PKT;
547
548 hci_recv_frame(bcsp->rx_skb);
549 } else {
550 BT_ERR ("Packet for unknown channel (%u %s)",
551 bcsp->rx_skb->data[1] & 0x0f,
552 bcsp->rx_skb->data[0] & 0x80 ?
553 "reliable" : "unreliable");
554 kfree_skb(bcsp->rx_skb);
555 }
556 } else
557 kfree_skb(bcsp->rx_skb);
558 } else {
559
560 skb_pull(bcsp->rx_skb, 4);
561
562 hci_recv_frame(bcsp->rx_skb);
563 }
564
565 bcsp->rx_state = BCSP_W4_PKT_DELIMITER;
566 bcsp->rx_skb = NULL;
567}
568
569
570static int bcsp_recv(struct hci_uart *hu, void *data, int count)
571{
572 struct bcsp_struct *bcsp = hu->priv;
573 register unsigned char *ptr;
574
575 BT_DBG("hu %p count %d rx_state %d rx_count %ld",
576 hu, count, bcsp->rx_state, bcsp->rx_count);
577
578 ptr = data;
579 while (count) {
580 if (bcsp->rx_count) {
581 if (*ptr == 0xc0) {
582 BT_ERR("Short BCSP packet");
583 kfree_skb(bcsp->rx_skb);
584 bcsp->rx_state = BCSP_W4_PKT_START;
585 bcsp->rx_count = 0;
586 } else
587 bcsp_unslip_one_byte(bcsp, *ptr);
588
589 ptr++; count--;
590 continue;
591 }
592
593 switch (bcsp->rx_state) {
594 case BCSP_W4_BCSP_HDR:
595 if ((0xff & (u8) ~ (bcsp->rx_skb->data[0] + bcsp->rx_skb->data[1] +
596 bcsp->rx_skb->data[2])) != bcsp->rx_skb->data[3]) {
597 BT_ERR("Error in BCSP hdr checksum");
598 kfree_skb(bcsp->rx_skb);
599 bcsp->rx_state = BCSP_W4_PKT_DELIMITER;
600 bcsp->rx_count = 0;
601 continue;
602 }
603 if (bcsp->rx_skb->data[0] & 0x80
604 && (bcsp->rx_skb->data[0] & 0x07) != bcsp->rxseq_txack) {
605 BT_ERR ("Out-of-order packet arrived, got %u expected %u",
606 bcsp->rx_skb->data[0] & 0x07, bcsp->rxseq_txack);
607
608 kfree_skb(bcsp->rx_skb);
609 bcsp->rx_state = BCSP_W4_PKT_DELIMITER;
610 bcsp->rx_count = 0;
611 continue;
612 }
613 bcsp->rx_state = BCSP_W4_DATA;
614 bcsp->rx_count = (bcsp->rx_skb->data[1] >> 4) +
615 (bcsp->rx_skb->data[2] << 4);
616 continue;
617
618 case BCSP_W4_DATA:
619 if (bcsp->rx_skb->data[0] & 0x40) {
620 bcsp->rx_state = BCSP_W4_CRC;
621 bcsp->rx_count = 2;
622 } else
623 bcsp_complete_rx_pkt(hu);
624 continue;
625
626 case BCSP_W4_CRC:
627 if (bcsp_crc_reverse(bcsp->message_crc) !=
628 (bcsp->rx_skb->data[bcsp->rx_skb->len - 2] << 8) +
629 bcsp->rx_skb->data[bcsp->rx_skb->len - 1]) {
630
631 BT_ERR ("Checksum failed: computed %04x received %04x",
632 bcsp_crc_reverse(bcsp->message_crc),
633 (bcsp->rx_skb-> data[bcsp->rx_skb->len - 2] << 8) +
634 bcsp->rx_skb->data[bcsp->rx_skb->len - 1]);
635
636 kfree_skb(bcsp->rx_skb);
637 bcsp->rx_state = BCSP_W4_PKT_DELIMITER;
638 bcsp->rx_count = 0;
639 continue;
640 }
641 skb_trim(bcsp->rx_skb, bcsp->rx_skb->len - 2);
642 bcsp_complete_rx_pkt(hu);
643 continue;
644
645 case BCSP_W4_PKT_DELIMITER:
646 switch (*ptr) {
647 case 0xc0:
648 bcsp->rx_state = BCSP_W4_PKT_START;
649 break;
650 default:
651
652 break;
653 }
654 ptr++; count--;
655 break;
656
657 case BCSP_W4_PKT_START:
658 switch (*ptr) {
659 case 0xc0:
660 ptr++; count--;
661 break;
662
663 default:
664 bcsp->rx_state = BCSP_W4_BCSP_HDR;
665 bcsp->rx_count = 4;
666 bcsp->rx_esc_state = BCSP_ESCSTATE_NOESC;
667 BCSP_CRC_INIT(bcsp->message_crc);
668
669
670
671
672
673 bcsp->rx_skb = bt_skb_alloc(0x1005, GFP_ATOMIC);
674 if (!bcsp->rx_skb) {
675 BT_ERR("Can't allocate mem for new packet");
676 bcsp->rx_state = BCSP_W4_PKT_DELIMITER;
677 bcsp->rx_count = 0;
678 return 0;
679 }
680 bcsp->rx_skb->dev = (void *) hu->hdev;
681 break;
682 }
683 break;
684 }
685 }
686 return count;
687}
688
689
690static void bcsp_timed_event(unsigned long arg)
691{
692 struct hci_uart *hu = (struct hci_uart *) arg;
693 struct bcsp_struct *bcsp = hu->priv;
694 struct sk_buff *skb;
695 unsigned long flags;
696
697 BT_DBG("hu %p retransmitting %u pkts", hu, bcsp->unack.qlen);
698
699 spin_lock_irqsave_nested(&bcsp->unack.lock, flags, SINGLE_DEPTH_NESTING);
700
701 while ((skb = __skb_dequeue_tail(&bcsp->unack)) != NULL) {
702 bcsp->msgq_txseq = (bcsp->msgq_txseq - 1) & 0x07;
703 skb_queue_head(&bcsp->rel, skb);
704 }
705
706 spin_unlock_irqrestore(&bcsp->unack.lock, flags);
707
708 hci_uart_tx_wakeup(hu);
709}
710
711static int bcsp_open(struct hci_uart *hu)
712{
713 struct bcsp_struct *bcsp;
714
715 BT_DBG("hu %p", hu);
716
717 bcsp = kzalloc(sizeof(*bcsp), GFP_ATOMIC);
718 if (!bcsp)
719 return -ENOMEM;
720
721 hu->priv = bcsp;
722 skb_queue_head_init(&bcsp->unack);
723 skb_queue_head_init(&bcsp->rel);
724 skb_queue_head_init(&bcsp->unrel);
725
726 init_timer(&bcsp->tbcsp);
727 bcsp->tbcsp.function = bcsp_timed_event;
728 bcsp->tbcsp.data = (u_long) hu;
729
730 bcsp->rx_state = BCSP_W4_PKT_DELIMITER;
731
732 if (txcrc)
733 bcsp->use_crc = 1;
734
735 return 0;
736}
737
738static int bcsp_close(struct hci_uart *hu)
739{
740 struct bcsp_struct *bcsp = hu->priv;
741 hu->priv = NULL;
742
743 BT_DBG("hu %p", hu);
744
745 skb_queue_purge(&bcsp->unack);
746 skb_queue_purge(&bcsp->rel);
747 skb_queue_purge(&bcsp->unrel);
748 del_timer(&bcsp->tbcsp);
749
750 kfree(bcsp);
751 return 0;
752}
753
754static struct hci_uart_proto bcsp = {
755 .id = HCI_UART_BCSP,
756 .open = bcsp_open,
757 .close = bcsp_close,
758 .enqueue = bcsp_enqueue,
759 .dequeue = bcsp_dequeue,
760 .recv = bcsp_recv,
761 .flush = bcsp_flush
762};
763
764int bcsp_init(void)
765{
766 int err = hci_uart_register_proto(&bcsp);
767
768 if (!err)
769 BT_INFO("HCI BCSP protocol initialized");
770 else
771 BT_ERR("HCI BCSP protocol registration failed");
772
773 return err;
774}
775
776int bcsp_deinit(void)
777{
778 return hci_uart_unregister_proto(&bcsp);
779}
780
781module_param(txcrc, bool, 0644);
782MODULE_PARM_DESC(txcrc, "Transmit CRC with every BCSP packet");
783
784module_param(hciextn, bool, 0644);
785MODULE_PARM_DESC(hciextn, "Convert HCI Extensions into BCSP packets");
786