Skip to content

Commit b509c02

Browse files
Loic PoulainJohan Hedberg
authored andcommitted
Bluetooth: HCI H5 peer reset detection
H5 Specification says: If a SYNC message is received while in the Active State, it is assumed that the peer device has reset. The local device should therefore perform a full reset of the upper stack, and start Link Establishment again at the Uninitialized State. Upon entering the Active State, the first packet sent shall have its SEQ and ACK numbers set to zero. This patch resets the HCI H5 driver data/state to unitialized and reports an HCI hardware error event to notify the upper stack that HCI synchronization has been lost. H5 will be re-synchronized and upper stack should generate an HCI Reset command. Signed-off-by: Loic Poulain <loic.poulain@intel.com> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
1 parent a4d5504 commit b509c02

File tree

1 file changed

+34
-0
lines changed

1 file changed

+34
-0
lines changed

drivers/bluetooth/hci_h5.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,36 @@ static void h5_timed_event(unsigned long arg)
168168
hci_uart_tx_wakeup(hu);
169169
}
170170

171+
static void h5_peer_reset(struct hci_uart *hu)
172+
{
173+
struct h5 *h5 = hu->priv;
174+
struct sk_buff *skb;
175+
const unsigned char hard_err[] = { 0x10, 0x01, 0x00 };
176+
177+
BT_ERR("Peer device has reset");
178+
179+
h5->state = H5_UNINITIALIZED;
180+
181+
del_timer(&h5->timer);
182+
183+
skb_queue_purge(&h5->rel);
184+
skb_queue_purge(&h5->unrel);
185+
skb_queue_purge(&h5->unack);
186+
187+
h5->tx_seq = 0;
188+
h5->tx_ack = 0;
189+
190+
skb = bt_skb_alloc(3, GFP_ATOMIC);
191+
if (!skb)
192+
return;
193+
194+
bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
195+
memcpy(skb_put(skb, 3), hard_err, 3);
196+
197+
/* Send Hardware Error to upper stack */
198+
hci_recv_frame(hu->hdev, skb);
199+
}
200+
171201
static int h5_open(struct hci_uart *hu)
172202
{
173203
struct h5 *h5;
@@ -283,8 +313,12 @@ static void h5_handle_internal_rx(struct hci_uart *hu)
283313
conf_req[2] = h5_cfg_field(h5);
284314

285315
if (memcmp(data, sync_req, 2) == 0) {
316+
if (h5->state == H5_ACTIVE)
317+
h5_peer_reset(hu);
286318
h5_link_control(hu, sync_rsp, 2);
287319
} else if (memcmp(data, sync_rsp, 2) == 0) {
320+
if (h5->state == H5_ACTIVE)
321+
h5_peer_reset(hu);
288322
h5->state = H5_INITIALIZED;
289323
h5_link_control(hu, conf_req, 3);
290324
} else if (memcmp(data, conf_req, 2) == 0) {

0 commit comments

Comments
 (0)