Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 315695
b: refs/heads/master
c: f674a05
h: refs/heads/master
i:
  315693: 2976ec4
  315691: 7868798
  315687: ebd8166
  315679: da70f77
v: v3
  • Loading branch information
Johan Hedberg authored and Gustavo Padovan committed Jul 17, 2012
1 parent c91f141 commit c3d259f
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 17 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 10122d07ced378ec9187f4b3110e110282beb192
refs/heads/master: f674a057c1f6b0fedf7d989c6dac0b482fef1b55
66 changes: 50 additions & 16 deletions trunk/drivers/bluetooth/hci_h5.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,18 +75,53 @@ struct h5 {
u8 tx_seq; /* Next seq number to send */
u8 tx_ack; /* Next ack number to send */

enum {
H5_UNINITIALIZED,
H5_INITIALIZED,
H5_ACTIVE,
} state;

bool sleeping;
};

static void h5_reset_rx(struct h5 *h5);

static void h5_link_control(struct hci_uart *hu, const void *data, size_t len)
{
struct h5 *h5 = hu->priv;
struct sk_buff *nskb;

nskb = alloc_skb(3, GFP_ATOMIC);
if (!nskb)
return;

bt_cb(nskb)->pkt_type = HCI_3WIRE_LINK_PKT;

memcpy(skb_put(nskb, len), data, len);

skb_queue_tail(&h5->unrel, nskb);
}

static void h5_timed_event(unsigned long arg)
{
const unsigned char sync_req[] = { 0x01, 0x7e };
const unsigned char conf_req[] = { 0x03, 0xfc, 0x01 };
struct hci_uart *hu = (struct hci_uart *) arg;
struct h5 *h5 = hu->priv;
struct sk_buff *skb;
unsigned long flags;

if (h5->state == H5_UNINITIALIZED)
h5_link_control(hu, sync_req, sizeof(sync_req));

if (h5->state == H5_INITIALIZED)
h5_link_control(hu, conf_req, sizeof(conf_req));

if (h5->state != H5_ACTIVE) {
mod_timer(&h5->timer, jiffies + H5_SYNC_TIMEOUT);
goto wakeup;
}

BT_DBG("hu %p retransmitting %u pkts", hu, h5->unack.qlen);

spin_lock_irqsave_nested(&h5->unack.lock, flags, SINGLE_DEPTH_NESTING);
Expand All @@ -98,25 +133,10 @@ static void h5_timed_event(unsigned long arg)

spin_unlock_irqrestore(&h5->unack.lock, flags);

wakeup:
hci_uart_tx_wakeup(hu);
}

static void h5_link_control(struct hci_uart *hu, const void *data, size_t len)
{
struct h5 *h5 = hu->priv;
struct sk_buff *nskb;

nskb = alloc_skb(3, GFP_ATOMIC);
if (!nskb)
return;

bt_cb(nskb)->pkt_type = HCI_3WIRE_LINK_PKT;

memcpy(skb_put(nskb, len), data, len);

skb_queue_tail(&h5->unrel, nskb);
}

static int h5_open(struct hci_uart *hu)
{
struct h5 *h5;
Expand Down Expand Up @@ -230,12 +250,14 @@ static void h5_handle_internal_rx(struct hci_uart *hu)
if (memcmp(data, sync_req, 2) == 0) {
h5_link_control(hu, sync_rsp, 2);
} else if (memcmp(data, sync_rsp, 2) == 0) {
h5->state = H5_INITIALIZED;
h5_link_control(hu, conf_req, 3);
} else if (memcmp(data, conf_req, 2) == 0) {
h5_link_control(hu, conf_rsp, 2);
h5_link_control(hu, conf_req, 3);
} else if (memcmp(data, conf_rsp, 2) == 0) {
BT_DBG("Three-wire init sequence complete");
h5->state = H5_ACTIVE;
hci_uart_init_ready(hu);
return;
} else if (memcmp(data, sleep_req, 2) == 0) {
Expand Down Expand Up @@ -340,6 +362,12 @@ static int h5_rx_3wire_hdr(struct hci_uart *hu, unsigned char c)
return 0;
}

if (h5->state != H5_ACTIVE &&
H5_HDR_PKT_TYPE(hdr) != HCI_3WIRE_LINK_PKT) {
BT_ERR("Non-link packet received in non-active state");
h5_reset_rx(h5);
}

h5->rx_func = h5_rx_payload;
h5->rx_pending = H5_HDR_LEN(hdr);

Expand Down Expand Up @@ -468,6 +496,12 @@ static int h5_enqueue(struct hci_uart *hu, struct sk_buff *skb)
return 0;
}

if (h5->state != H5_ACTIVE) {
BT_ERR("Ignoring HCI data in non-active state");
kfree_skb(skb);
return 0;
}

switch (bt_cb(skb)->pkt_type) {
case HCI_ACLDATA_PKT:
case HCI_COMMAND_PKT:
Expand Down

0 comments on commit c3d259f

Please sign in to comment.