aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/bluetooth
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/bluetooth')
-rw-r--r--drivers/bluetooth/Kconfig1
-rw-r--r--drivers/bluetooth/hci_bcsp.c44
2 files changed, 14 insertions, 31 deletions
diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
index 075598e1c502..a235ca787465 100644
--- a/drivers/bluetooth/Kconfig
+++ b/drivers/bluetooth/Kconfig
@@ -71,6 +71,7 @@ config BT_HCIUART_H4
71config BT_HCIUART_BCSP 71config BT_HCIUART_BCSP
72 bool "BCSP protocol support" 72 bool "BCSP protocol support"
73 depends on BT_HCIUART 73 depends on BT_HCIUART
74 select BITREVERSE
74 help 75 help
75 BCSP (BlueCore Serial Protocol) is serial protocol for communication 76 BCSP (BlueCore Serial Protocol) is serial protocol for communication
76 between Bluetooth device and host. This protocol is required for non 77 between Bluetooth device and host. This protocol is required for non
diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c
index 696f7528f022..4d37bb312ee3 100644
--- a/drivers/bluetooth/hci_bcsp.c
+++ b/drivers/bluetooth/hci_bcsp.c
@@ -39,6 +39,8 @@
39#include <linux/signal.h> 39#include <linux/signal.h>
40#include <linux/ioctl.h> 40#include <linux/ioctl.h>
41#include <linux/skbuff.h> 41#include <linux/skbuff.h>
42#include <linux/bitrev.h>
43#include <asm/unaligned.h>
42 44
43#include <net/bluetooth/bluetooth.h> 45#include <net/bluetooth/bluetooth.h>
44#include <net/bluetooth/hci_core.h> 46#include <net/bluetooth/hci_core.h>
@@ -124,27 +126,6 @@ static void bcsp_crc_update(u16 *crc, u8 d)
124 *crc = reg; 126 *crc = reg;
125} 127}
126 128
127/*
128 Get reverse of generated crc
129
130 Implementation note
131 The crc generator (bcsp_crc_init() and bcsp_crc_update())
132 creates a reversed crc, so it needs to be swapped back before
133 being passed on.
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/* ---- BCSP core ---- */ 129/* ---- BCSP core ---- */
149 130
150static void bcsp_slip_msgdelim(struct sk_buff *skb) 131static void bcsp_slip_msgdelim(struct sk_buff *skb)
@@ -235,10 +216,10 @@ static struct sk_buff *bcsp_prepare_pkt(struct bcsp_struct *bcsp, u8 *data,
235 } 216 }
236 217
237 if (hciextn && chan == 5) { 218 if (hciextn && chan == 5) {
238 struct hci_command_hdr *hdr = (struct hci_command_hdr *) data; 219 __le16 opcode = ((struct hci_command_hdr *)data)->opcode;
239 220
240 /* Vendor specific commands */ 221 /* Vendor specific commands */
241 if (hci_opcode_ogf(__le16_to_cpu(hdr->opcode)) == 0x3f) { 222 if (hci_opcode_ogf(__le16_to_cpu(opcode)) == 0x3f) {
242 u8 desc = *(data + HCI_COMMAND_HDR_SIZE); 223 u8 desc = *(data + HCI_COMMAND_HDR_SIZE);
243 if ((desc & 0xf0) == 0xc0) { 224 if ((desc & 0xf0) == 0xc0) {
244 data += HCI_COMMAND_HDR_SIZE + 1; 225 data += HCI_COMMAND_HDR_SIZE + 1;
@@ -296,7 +277,7 @@ static struct sk_buff *bcsp_prepare_pkt(struct bcsp_struct *bcsp, u8 *data,
296 277
297 /* Put CRC */ 278 /* Put CRC */
298 if (bcsp->use_crc) { 279 if (bcsp->use_crc) {
299 bcsp_txmsg_crc = bcsp_crc_reverse(bcsp_txmsg_crc); 280 bcsp_txmsg_crc = bitrev16(bcsp_txmsg_crc);
300 bcsp_slip_one_byte(nskb, (u8) ((bcsp_txmsg_crc >> 8) & 0x00ff)); 281 bcsp_slip_one_byte(nskb, (u8) ((bcsp_txmsg_crc >> 8) & 0x00ff));
301 bcsp_slip_one_byte(nskb, (u8) (bcsp_txmsg_crc & 0x00ff)); 282 bcsp_slip_one_byte(nskb, (u8) (bcsp_txmsg_crc & 0x00ff));
302 } 283 }
@@ -566,6 +547,11 @@ static void bcsp_complete_rx_pkt(struct hci_uart *hu)
566 bcsp->rx_skb = NULL; 547 bcsp->rx_skb = NULL;
567} 548}
568 549
550static u16 bscp_get_crc(struct bcsp_struct *bcsp)
551{
552 return get_unaligned_be16(&bcsp->rx_skb->data[bcsp->rx_skb->len - 2]);
553}
554
569/* Recv data */ 555/* Recv data */
570static int bcsp_recv(struct hci_uart *hu, void *data, int count) 556static int bcsp_recv(struct hci_uart *hu, void *data, int count)
571{ 557{
@@ -624,14 +610,10 @@ static int bcsp_recv(struct hci_uart *hu, void *data, int count)
624 continue; 610 continue;
625 611
626 case BCSP_W4_CRC: 612 case BCSP_W4_CRC:
627 if (bcsp_crc_reverse(bcsp->message_crc) != 613 if (bitrev16(bcsp->message_crc) != bscp_get_crc(bcsp)) {
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", 614 BT_ERR ("Checksum failed: computed %04x received %04x",
632 bcsp_crc_reverse(bcsp->message_crc), 615 bitrev16(bcsp->message_crc),
633 (bcsp->rx_skb-> data[bcsp->rx_skb->len - 2] << 8) + 616 bscp_get_crc(bcsp));
634 bcsp->rx_skb->data[bcsp->rx_skb->len - 1]);
635 617
636 kfree_skb(bcsp->rx_skb); 618 kfree_skb(bcsp->rx_skb);
637 bcsp->rx_state = BCSP_W4_PKT_DELIMITER; 619 bcsp->rx_state = BCSP_W4_PKT_DELIMITER;