aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/bluetooth/hci_bcsp.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/bluetooth/hci_bcsp.c')
-rw-r--r--drivers/bluetooth/hci_bcsp.c44
1 files changed, 13 insertions, 31 deletions
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;