162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Bluetooth HCI UART driver 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright (C) 2002-2003 Fabrizio Gennari <fabrizio.gennari@philips.com> 762306a36Sopenharmony_ci * Copyright (C) 2004-2005 Marcel Holtmann <marcel@holtmann.org> 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/module.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <linux/kernel.h> 1362306a36Sopenharmony_ci#include <linux/init.h> 1462306a36Sopenharmony_ci#include <linux/types.h> 1562306a36Sopenharmony_ci#include <linux/fcntl.h> 1662306a36Sopenharmony_ci#include <linux/interrupt.h> 1762306a36Sopenharmony_ci#include <linux/ptrace.h> 1862306a36Sopenharmony_ci#include <linux/poll.h> 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#include <linux/slab.h> 2162306a36Sopenharmony_ci#include <linux/tty.h> 2262306a36Sopenharmony_ci#include <linux/errno.h> 2362306a36Sopenharmony_ci#include <linux/string.h> 2462306a36Sopenharmony_ci#include <linux/signal.h> 2562306a36Sopenharmony_ci#include <linux/ioctl.h> 2662306a36Sopenharmony_ci#include <linux/skbuff.h> 2762306a36Sopenharmony_ci#include <linux/bitrev.h> 2862306a36Sopenharmony_ci#include <asm/unaligned.h> 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#include <net/bluetooth/bluetooth.h> 3162306a36Sopenharmony_ci#include <net/bluetooth/hci_core.h> 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci#include "hci_uart.h" 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_cistatic bool txcrc = true; 3662306a36Sopenharmony_cistatic bool hciextn = true; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci#define BCSP_TXWINSIZE 4 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci#define BCSP_ACK_PKT 0x05 4162306a36Sopenharmony_ci#define BCSP_LE_PKT 0x06 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_cistruct bcsp_struct { 4462306a36Sopenharmony_ci struct sk_buff_head unack; /* Unack'ed packets queue */ 4562306a36Sopenharmony_ci struct sk_buff_head rel; /* Reliable packets queue */ 4662306a36Sopenharmony_ci struct sk_buff_head unrel; /* Unreliable packets queue */ 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci unsigned long rx_count; 4962306a36Sopenharmony_ci struct sk_buff *rx_skb; 5062306a36Sopenharmony_ci u8 rxseq_txack; /* rxseq == txack. */ 5162306a36Sopenharmony_ci u8 rxack; /* Last packet sent by us that the peer ack'ed */ 5262306a36Sopenharmony_ci struct timer_list tbcsp; 5362306a36Sopenharmony_ci struct hci_uart *hu; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci enum { 5662306a36Sopenharmony_ci BCSP_W4_PKT_DELIMITER, 5762306a36Sopenharmony_ci BCSP_W4_PKT_START, 5862306a36Sopenharmony_ci BCSP_W4_BCSP_HDR, 5962306a36Sopenharmony_ci BCSP_W4_DATA, 6062306a36Sopenharmony_ci BCSP_W4_CRC 6162306a36Sopenharmony_ci } rx_state; 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci enum { 6462306a36Sopenharmony_ci BCSP_ESCSTATE_NOESC, 6562306a36Sopenharmony_ci BCSP_ESCSTATE_ESC 6662306a36Sopenharmony_ci } rx_esc_state; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci u8 use_crc; 6962306a36Sopenharmony_ci u16 message_crc; 7062306a36Sopenharmony_ci u8 txack_req; /* Do we need to send ack's to the peer? */ 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci /* Reliable packet sequence number - used to assign seq to each rel pkt. */ 7362306a36Sopenharmony_ci u8 msgq_txseq; 7462306a36Sopenharmony_ci}; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci/* ---- BCSP CRC calculation ---- */ 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci/* Table for calculating CRC for polynomial 0x1021, LSB processed first, 7962306a36Sopenharmony_ci * initial value 0xffff, bits shifted in reverse order. 8062306a36Sopenharmony_ci */ 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_cistatic const u16 crc_table[] = { 8362306a36Sopenharmony_ci 0x0000, 0x1081, 0x2102, 0x3183, 8462306a36Sopenharmony_ci 0x4204, 0x5285, 0x6306, 0x7387, 8562306a36Sopenharmony_ci 0x8408, 0x9489, 0xa50a, 0xb58b, 8662306a36Sopenharmony_ci 0xc60c, 0xd68d, 0xe70e, 0xf78f 8762306a36Sopenharmony_ci}; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci/* Initialise the crc calculator */ 9062306a36Sopenharmony_ci#define BCSP_CRC_INIT(x) x = 0xffff 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci/* Update crc with next data byte 9362306a36Sopenharmony_ci * 9462306a36Sopenharmony_ci * Implementation note 9562306a36Sopenharmony_ci * The data byte is treated as two nibbles. The crc is generated 9662306a36Sopenharmony_ci * in reverse, i.e., bits are fed into the register from the top. 9762306a36Sopenharmony_ci */ 9862306a36Sopenharmony_cistatic void bcsp_crc_update(u16 *crc, u8 d) 9962306a36Sopenharmony_ci{ 10062306a36Sopenharmony_ci u16 reg = *crc; 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci reg = (reg >> 4) ^ crc_table[(reg ^ d) & 0x000f]; 10362306a36Sopenharmony_ci reg = (reg >> 4) ^ crc_table[(reg ^ (d >> 4)) & 0x000f]; 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci *crc = reg; 10662306a36Sopenharmony_ci} 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci/* ---- BCSP core ---- */ 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_cistatic void bcsp_slip_msgdelim(struct sk_buff *skb) 11162306a36Sopenharmony_ci{ 11262306a36Sopenharmony_ci const char pkt_delim = 0xc0; 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci skb_put_data(skb, &pkt_delim, 1); 11562306a36Sopenharmony_ci} 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_cistatic void bcsp_slip_one_byte(struct sk_buff *skb, u8 c) 11862306a36Sopenharmony_ci{ 11962306a36Sopenharmony_ci const char esc_c0[2] = { 0xdb, 0xdc }; 12062306a36Sopenharmony_ci const char esc_db[2] = { 0xdb, 0xdd }; 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci switch (c) { 12362306a36Sopenharmony_ci case 0xc0: 12462306a36Sopenharmony_ci skb_put_data(skb, &esc_c0, 2); 12562306a36Sopenharmony_ci break; 12662306a36Sopenharmony_ci case 0xdb: 12762306a36Sopenharmony_ci skb_put_data(skb, &esc_db, 2); 12862306a36Sopenharmony_ci break; 12962306a36Sopenharmony_ci default: 13062306a36Sopenharmony_ci skb_put_data(skb, &c, 1); 13162306a36Sopenharmony_ci } 13262306a36Sopenharmony_ci} 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_cistatic int bcsp_enqueue(struct hci_uart *hu, struct sk_buff *skb) 13562306a36Sopenharmony_ci{ 13662306a36Sopenharmony_ci struct bcsp_struct *bcsp = hu->priv; 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci if (skb->len > 0xFFF) { 13962306a36Sopenharmony_ci BT_ERR("Packet too long"); 14062306a36Sopenharmony_ci kfree_skb(skb); 14162306a36Sopenharmony_ci return 0; 14262306a36Sopenharmony_ci } 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci switch (hci_skb_pkt_type(skb)) { 14562306a36Sopenharmony_ci case HCI_ACLDATA_PKT: 14662306a36Sopenharmony_ci case HCI_COMMAND_PKT: 14762306a36Sopenharmony_ci skb_queue_tail(&bcsp->rel, skb); 14862306a36Sopenharmony_ci break; 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci case HCI_SCODATA_PKT: 15162306a36Sopenharmony_ci skb_queue_tail(&bcsp->unrel, skb); 15262306a36Sopenharmony_ci break; 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci default: 15562306a36Sopenharmony_ci BT_ERR("Unknown packet type"); 15662306a36Sopenharmony_ci kfree_skb(skb); 15762306a36Sopenharmony_ci break; 15862306a36Sopenharmony_ci } 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci return 0; 16162306a36Sopenharmony_ci} 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_cistatic struct sk_buff *bcsp_prepare_pkt(struct bcsp_struct *bcsp, u8 *data, 16462306a36Sopenharmony_ci int len, int pkt_type) 16562306a36Sopenharmony_ci{ 16662306a36Sopenharmony_ci struct sk_buff *nskb; 16762306a36Sopenharmony_ci u8 hdr[4], chan; 16862306a36Sopenharmony_ci u16 BCSP_CRC_INIT(bcsp_txmsg_crc); 16962306a36Sopenharmony_ci int rel, i; 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci switch (pkt_type) { 17262306a36Sopenharmony_ci case HCI_ACLDATA_PKT: 17362306a36Sopenharmony_ci chan = 6; /* BCSP ACL channel */ 17462306a36Sopenharmony_ci rel = 1; /* reliable channel */ 17562306a36Sopenharmony_ci break; 17662306a36Sopenharmony_ci case HCI_COMMAND_PKT: 17762306a36Sopenharmony_ci chan = 5; /* BCSP cmd/evt channel */ 17862306a36Sopenharmony_ci rel = 1; /* reliable channel */ 17962306a36Sopenharmony_ci break; 18062306a36Sopenharmony_ci case HCI_SCODATA_PKT: 18162306a36Sopenharmony_ci chan = 7; /* BCSP SCO channel */ 18262306a36Sopenharmony_ci rel = 0; /* unreliable channel */ 18362306a36Sopenharmony_ci break; 18462306a36Sopenharmony_ci case BCSP_LE_PKT: 18562306a36Sopenharmony_ci chan = 1; /* BCSP LE channel */ 18662306a36Sopenharmony_ci rel = 0; /* unreliable channel */ 18762306a36Sopenharmony_ci break; 18862306a36Sopenharmony_ci case BCSP_ACK_PKT: 18962306a36Sopenharmony_ci chan = 0; /* BCSP internal channel */ 19062306a36Sopenharmony_ci rel = 0; /* unreliable channel */ 19162306a36Sopenharmony_ci break; 19262306a36Sopenharmony_ci default: 19362306a36Sopenharmony_ci BT_ERR("Unknown packet type"); 19462306a36Sopenharmony_ci return NULL; 19562306a36Sopenharmony_ci } 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci if (hciextn && chan == 5) { 19862306a36Sopenharmony_ci __le16 opcode = ((struct hci_command_hdr *)data)->opcode; 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci /* Vendor specific commands */ 20162306a36Sopenharmony_ci if (hci_opcode_ogf(__le16_to_cpu(opcode)) == 0x3f) { 20262306a36Sopenharmony_ci u8 desc = *(data + HCI_COMMAND_HDR_SIZE); 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci if ((desc & 0xf0) == 0xc0) { 20562306a36Sopenharmony_ci data += HCI_COMMAND_HDR_SIZE + 1; 20662306a36Sopenharmony_ci len -= HCI_COMMAND_HDR_SIZE + 1; 20762306a36Sopenharmony_ci chan = desc & 0x0f; 20862306a36Sopenharmony_ci } 20962306a36Sopenharmony_ci } 21062306a36Sopenharmony_ci } 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci /* Max len of packet: (original len +4(bcsp hdr) +2(crc))*2 21362306a36Sopenharmony_ci * (because bytes 0xc0 and 0xdb are escaped, worst case is 21462306a36Sopenharmony_ci * when the packet is all made of 0xc0 and 0xdb :) ) 21562306a36Sopenharmony_ci * + 2 (0xc0 delimiters at start and end). 21662306a36Sopenharmony_ci */ 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci nskb = alloc_skb((len + 6) * 2 + 2, GFP_ATOMIC); 21962306a36Sopenharmony_ci if (!nskb) 22062306a36Sopenharmony_ci return NULL; 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci hci_skb_pkt_type(nskb) = pkt_type; 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci bcsp_slip_msgdelim(nskb); 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci hdr[0] = bcsp->rxseq_txack << 3; 22762306a36Sopenharmony_ci bcsp->txack_req = 0; 22862306a36Sopenharmony_ci BT_DBG("We request packet no %u to card", bcsp->rxseq_txack); 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci if (rel) { 23162306a36Sopenharmony_ci hdr[0] |= 0x80 + bcsp->msgq_txseq; 23262306a36Sopenharmony_ci BT_DBG("Sending packet with seqno %u", bcsp->msgq_txseq); 23362306a36Sopenharmony_ci bcsp->msgq_txseq = (bcsp->msgq_txseq + 1) & 0x07; 23462306a36Sopenharmony_ci } 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci if (bcsp->use_crc) 23762306a36Sopenharmony_ci hdr[0] |= 0x40; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci hdr[1] = ((len << 4) & 0xff) | chan; 24062306a36Sopenharmony_ci hdr[2] = len >> 4; 24162306a36Sopenharmony_ci hdr[3] = ~(hdr[0] + hdr[1] + hdr[2]); 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci /* Put BCSP header */ 24462306a36Sopenharmony_ci for (i = 0; i < 4; i++) { 24562306a36Sopenharmony_ci bcsp_slip_one_byte(nskb, hdr[i]); 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci if (bcsp->use_crc) 24862306a36Sopenharmony_ci bcsp_crc_update(&bcsp_txmsg_crc, hdr[i]); 24962306a36Sopenharmony_ci } 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci /* Put payload */ 25262306a36Sopenharmony_ci for (i = 0; i < len; i++) { 25362306a36Sopenharmony_ci bcsp_slip_one_byte(nskb, data[i]); 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci if (bcsp->use_crc) 25662306a36Sopenharmony_ci bcsp_crc_update(&bcsp_txmsg_crc, data[i]); 25762306a36Sopenharmony_ci } 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci /* Put CRC */ 26062306a36Sopenharmony_ci if (bcsp->use_crc) { 26162306a36Sopenharmony_ci bcsp_txmsg_crc = bitrev16(bcsp_txmsg_crc); 26262306a36Sopenharmony_ci bcsp_slip_one_byte(nskb, (u8)((bcsp_txmsg_crc >> 8) & 0x00ff)); 26362306a36Sopenharmony_ci bcsp_slip_one_byte(nskb, (u8)(bcsp_txmsg_crc & 0x00ff)); 26462306a36Sopenharmony_ci } 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci bcsp_slip_msgdelim(nskb); 26762306a36Sopenharmony_ci return nskb; 26862306a36Sopenharmony_ci} 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci/* This is a rewrite of pkt_avail in ABCSP */ 27162306a36Sopenharmony_cistatic struct sk_buff *bcsp_dequeue(struct hci_uart *hu) 27262306a36Sopenharmony_ci{ 27362306a36Sopenharmony_ci struct bcsp_struct *bcsp = hu->priv; 27462306a36Sopenharmony_ci unsigned long flags; 27562306a36Sopenharmony_ci struct sk_buff *skb; 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci /* First of all, check for unreliable messages in the queue, 27862306a36Sopenharmony_ci * since they have priority 27962306a36Sopenharmony_ci */ 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci skb = skb_dequeue(&bcsp->unrel); 28262306a36Sopenharmony_ci if (skb != NULL) { 28362306a36Sopenharmony_ci struct sk_buff *nskb; 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci nskb = bcsp_prepare_pkt(bcsp, skb->data, skb->len, 28662306a36Sopenharmony_ci hci_skb_pkt_type(skb)); 28762306a36Sopenharmony_ci if (nskb) { 28862306a36Sopenharmony_ci kfree_skb(skb); 28962306a36Sopenharmony_ci return nskb; 29062306a36Sopenharmony_ci } else { 29162306a36Sopenharmony_ci skb_queue_head(&bcsp->unrel, skb); 29262306a36Sopenharmony_ci BT_ERR("Could not dequeue pkt because alloc_skb failed"); 29362306a36Sopenharmony_ci } 29462306a36Sopenharmony_ci } 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci /* Now, try to send a reliable pkt. We can only send a 29762306a36Sopenharmony_ci * reliable packet if the number of packets sent but not yet ack'ed 29862306a36Sopenharmony_ci * is < than the winsize 29962306a36Sopenharmony_ci */ 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci spin_lock_irqsave_nested(&bcsp->unack.lock, flags, SINGLE_DEPTH_NESTING); 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci if (bcsp->unack.qlen < BCSP_TXWINSIZE) { 30462306a36Sopenharmony_ci skb = skb_dequeue(&bcsp->rel); 30562306a36Sopenharmony_ci if (skb != NULL) { 30662306a36Sopenharmony_ci struct sk_buff *nskb; 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci nskb = bcsp_prepare_pkt(bcsp, skb->data, skb->len, 30962306a36Sopenharmony_ci hci_skb_pkt_type(skb)); 31062306a36Sopenharmony_ci if (nskb) { 31162306a36Sopenharmony_ci __skb_queue_tail(&bcsp->unack, skb); 31262306a36Sopenharmony_ci mod_timer(&bcsp->tbcsp, jiffies + HZ / 4); 31362306a36Sopenharmony_ci spin_unlock_irqrestore(&bcsp->unack.lock, flags); 31462306a36Sopenharmony_ci return nskb; 31562306a36Sopenharmony_ci } else { 31662306a36Sopenharmony_ci skb_queue_head(&bcsp->rel, skb); 31762306a36Sopenharmony_ci BT_ERR("Could not dequeue pkt because alloc_skb failed"); 31862306a36Sopenharmony_ci } 31962306a36Sopenharmony_ci } 32062306a36Sopenharmony_ci } 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci spin_unlock_irqrestore(&bcsp->unack.lock, flags); 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci /* We could not send a reliable packet, either because there are 32562306a36Sopenharmony_ci * none or because there are too many unack'ed pkts. Did we receive 32662306a36Sopenharmony_ci * any packets we have not acknowledged yet ? 32762306a36Sopenharmony_ci */ 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci if (bcsp->txack_req) { 33062306a36Sopenharmony_ci /* if so, craft an empty ACK pkt and send it on BCSP unreliable 33162306a36Sopenharmony_ci * channel 0 33262306a36Sopenharmony_ci */ 33362306a36Sopenharmony_ci struct sk_buff *nskb = bcsp_prepare_pkt(bcsp, NULL, 0, BCSP_ACK_PKT); 33462306a36Sopenharmony_ci return nskb; 33562306a36Sopenharmony_ci } 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci /* We have nothing to send */ 33862306a36Sopenharmony_ci return NULL; 33962306a36Sopenharmony_ci} 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_cistatic int bcsp_flush(struct hci_uart *hu) 34262306a36Sopenharmony_ci{ 34362306a36Sopenharmony_ci BT_DBG("hu %p", hu); 34462306a36Sopenharmony_ci return 0; 34562306a36Sopenharmony_ci} 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci/* Remove ack'ed packets */ 34862306a36Sopenharmony_cistatic void bcsp_pkt_cull(struct bcsp_struct *bcsp) 34962306a36Sopenharmony_ci{ 35062306a36Sopenharmony_ci struct sk_buff *skb, *tmp; 35162306a36Sopenharmony_ci unsigned long flags; 35262306a36Sopenharmony_ci int i, pkts_to_be_removed; 35362306a36Sopenharmony_ci u8 seqno; 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci spin_lock_irqsave(&bcsp->unack.lock, flags); 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci pkts_to_be_removed = skb_queue_len(&bcsp->unack); 35862306a36Sopenharmony_ci seqno = bcsp->msgq_txseq; 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci while (pkts_to_be_removed) { 36162306a36Sopenharmony_ci if (bcsp->rxack == seqno) 36262306a36Sopenharmony_ci break; 36362306a36Sopenharmony_ci pkts_to_be_removed--; 36462306a36Sopenharmony_ci seqno = (seqno - 1) & 0x07; 36562306a36Sopenharmony_ci } 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci if (bcsp->rxack != seqno) 36862306a36Sopenharmony_ci BT_ERR("Peer acked invalid packet"); 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci BT_DBG("Removing %u pkts out of %u, up to seqno %u", 37162306a36Sopenharmony_ci pkts_to_be_removed, skb_queue_len(&bcsp->unack), 37262306a36Sopenharmony_ci (seqno - 1) & 0x07); 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci i = 0; 37562306a36Sopenharmony_ci skb_queue_walk_safe(&bcsp->unack, skb, tmp) { 37662306a36Sopenharmony_ci if (i >= pkts_to_be_removed) 37762306a36Sopenharmony_ci break; 37862306a36Sopenharmony_ci i++; 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci __skb_unlink(skb, &bcsp->unack); 38162306a36Sopenharmony_ci dev_kfree_skb_irq(skb); 38262306a36Sopenharmony_ci } 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci if (skb_queue_empty(&bcsp->unack)) 38562306a36Sopenharmony_ci del_timer(&bcsp->tbcsp); 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci spin_unlock_irqrestore(&bcsp->unack.lock, flags); 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci if (i != pkts_to_be_removed) 39062306a36Sopenharmony_ci BT_ERR("Removed only %u out of %u pkts", i, pkts_to_be_removed); 39162306a36Sopenharmony_ci} 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci/* Handle BCSP link-establishment packets. When we 39462306a36Sopenharmony_ci * detect a "sync" packet, symptom that the BT module has reset, 39562306a36Sopenharmony_ci * we do nothing :) (yet) 39662306a36Sopenharmony_ci */ 39762306a36Sopenharmony_cistatic void bcsp_handle_le_pkt(struct hci_uart *hu) 39862306a36Sopenharmony_ci{ 39962306a36Sopenharmony_ci struct bcsp_struct *bcsp = hu->priv; 40062306a36Sopenharmony_ci u8 conf_pkt[4] = { 0xad, 0xef, 0xac, 0xed }; 40162306a36Sopenharmony_ci u8 conf_rsp_pkt[4] = { 0xde, 0xad, 0xd0, 0xd0 }; 40262306a36Sopenharmony_ci u8 sync_pkt[4] = { 0xda, 0xdc, 0xed, 0xed }; 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci /* spot "conf" pkts and reply with a "conf rsp" pkt */ 40562306a36Sopenharmony_ci if (bcsp->rx_skb->data[1] >> 4 == 4 && bcsp->rx_skb->data[2] == 0 && 40662306a36Sopenharmony_ci !memcmp(&bcsp->rx_skb->data[4], conf_pkt, 4)) { 40762306a36Sopenharmony_ci struct sk_buff *nskb = alloc_skb(4, GFP_ATOMIC); 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci BT_DBG("Found a LE conf pkt"); 41062306a36Sopenharmony_ci if (!nskb) 41162306a36Sopenharmony_ci return; 41262306a36Sopenharmony_ci skb_put_data(nskb, conf_rsp_pkt, 4); 41362306a36Sopenharmony_ci hci_skb_pkt_type(nskb) = BCSP_LE_PKT; 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci skb_queue_head(&bcsp->unrel, nskb); 41662306a36Sopenharmony_ci hci_uart_tx_wakeup(hu); 41762306a36Sopenharmony_ci } 41862306a36Sopenharmony_ci /* Spot "sync" pkts. If we find one...disaster! */ 41962306a36Sopenharmony_ci else if (bcsp->rx_skb->data[1] >> 4 == 4 && bcsp->rx_skb->data[2] == 0 && 42062306a36Sopenharmony_ci !memcmp(&bcsp->rx_skb->data[4], sync_pkt, 4)) { 42162306a36Sopenharmony_ci BT_ERR("Found a LE sync pkt, card has reset"); 42262306a36Sopenharmony_ci } 42362306a36Sopenharmony_ci} 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_cistatic inline void bcsp_unslip_one_byte(struct bcsp_struct *bcsp, unsigned char byte) 42662306a36Sopenharmony_ci{ 42762306a36Sopenharmony_ci const u8 c0 = 0xc0, db = 0xdb; 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci switch (bcsp->rx_esc_state) { 43062306a36Sopenharmony_ci case BCSP_ESCSTATE_NOESC: 43162306a36Sopenharmony_ci switch (byte) { 43262306a36Sopenharmony_ci case 0xdb: 43362306a36Sopenharmony_ci bcsp->rx_esc_state = BCSP_ESCSTATE_ESC; 43462306a36Sopenharmony_ci break; 43562306a36Sopenharmony_ci default: 43662306a36Sopenharmony_ci skb_put_data(bcsp->rx_skb, &byte, 1); 43762306a36Sopenharmony_ci if ((bcsp->rx_skb->data[0] & 0x40) != 0 && 43862306a36Sopenharmony_ci bcsp->rx_state != BCSP_W4_CRC) 43962306a36Sopenharmony_ci bcsp_crc_update(&bcsp->message_crc, byte); 44062306a36Sopenharmony_ci bcsp->rx_count--; 44162306a36Sopenharmony_ci } 44262306a36Sopenharmony_ci break; 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci case BCSP_ESCSTATE_ESC: 44562306a36Sopenharmony_ci switch (byte) { 44662306a36Sopenharmony_ci case 0xdc: 44762306a36Sopenharmony_ci skb_put_data(bcsp->rx_skb, &c0, 1); 44862306a36Sopenharmony_ci if ((bcsp->rx_skb->data[0] & 0x40) != 0 && 44962306a36Sopenharmony_ci bcsp->rx_state != BCSP_W4_CRC) 45062306a36Sopenharmony_ci bcsp_crc_update(&bcsp->message_crc, 0xc0); 45162306a36Sopenharmony_ci bcsp->rx_esc_state = BCSP_ESCSTATE_NOESC; 45262306a36Sopenharmony_ci bcsp->rx_count--; 45362306a36Sopenharmony_ci break; 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci case 0xdd: 45662306a36Sopenharmony_ci skb_put_data(bcsp->rx_skb, &db, 1); 45762306a36Sopenharmony_ci if ((bcsp->rx_skb->data[0] & 0x40) != 0 && 45862306a36Sopenharmony_ci bcsp->rx_state != BCSP_W4_CRC) 45962306a36Sopenharmony_ci bcsp_crc_update(&bcsp->message_crc, 0xdb); 46062306a36Sopenharmony_ci bcsp->rx_esc_state = BCSP_ESCSTATE_NOESC; 46162306a36Sopenharmony_ci bcsp->rx_count--; 46262306a36Sopenharmony_ci break; 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci default: 46562306a36Sopenharmony_ci BT_ERR("Invalid byte %02x after esc byte", byte); 46662306a36Sopenharmony_ci kfree_skb(bcsp->rx_skb); 46762306a36Sopenharmony_ci bcsp->rx_skb = NULL; 46862306a36Sopenharmony_ci bcsp->rx_state = BCSP_W4_PKT_DELIMITER; 46962306a36Sopenharmony_ci bcsp->rx_count = 0; 47062306a36Sopenharmony_ci } 47162306a36Sopenharmony_ci } 47262306a36Sopenharmony_ci} 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_cistatic void bcsp_complete_rx_pkt(struct hci_uart *hu) 47562306a36Sopenharmony_ci{ 47662306a36Sopenharmony_ci struct bcsp_struct *bcsp = hu->priv; 47762306a36Sopenharmony_ci int pass_up = 0; 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci if (bcsp->rx_skb->data[0] & 0x80) { /* reliable pkt */ 48062306a36Sopenharmony_ci BT_DBG("Received seqno %u from card", bcsp->rxseq_txack); 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci /* check the rx sequence number is as expected */ 48362306a36Sopenharmony_ci if ((bcsp->rx_skb->data[0] & 0x07) == bcsp->rxseq_txack) { 48462306a36Sopenharmony_ci bcsp->rxseq_txack++; 48562306a36Sopenharmony_ci bcsp->rxseq_txack %= 0x8; 48662306a36Sopenharmony_ci } else { 48762306a36Sopenharmony_ci /* handle re-transmitted packet or 48862306a36Sopenharmony_ci * when packet was missed 48962306a36Sopenharmony_ci */ 49062306a36Sopenharmony_ci BT_ERR("Out-of-order packet arrived, got %u expected %u", 49162306a36Sopenharmony_ci bcsp->rx_skb->data[0] & 0x07, bcsp->rxseq_txack); 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci /* do not process out-of-order packet payload */ 49462306a36Sopenharmony_ci pass_up = 2; 49562306a36Sopenharmony_ci } 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci /* send current txack value to all received reliable packets */ 49862306a36Sopenharmony_ci bcsp->txack_req = 1; 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_ci /* If needed, transmit an ack pkt */ 50162306a36Sopenharmony_ci hci_uart_tx_wakeup(hu); 50262306a36Sopenharmony_ci } 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci bcsp->rxack = (bcsp->rx_skb->data[0] >> 3) & 0x07; 50562306a36Sopenharmony_ci BT_DBG("Request for pkt %u from card", bcsp->rxack); 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci /* handle received ACK indications, 50862306a36Sopenharmony_ci * including those from out-of-order packets 50962306a36Sopenharmony_ci */ 51062306a36Sopenharmony_ci bcsp_pkt_cull(bcsp); 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci if (pass_up != 2) { 51362306a36Sopenharmony_ci if ((bcsp->rx_skb->data[1] & 0x0f) == 6 && 51462306a36Sopenharmony_ci (bcsp->rx_skb->data[0] & 0x80)) { 51562306a36Sopenharmony_ci hci_skb_pkt_type(bcsp->rx_skb) = HCI_ACLDATA_PKT; 51662306a36Sopenharmony_ci pass_up = 1; 51762306a36Sopenharmony_ci } else if ((bcsp->rx_skb->data[1] & 0x0f) == 5 && 51862306a36Sopenharmony_ci (bcsp->rx_skb->data[0] & 0x80)) { 51962306a36Sopenharmony_ci hci_skb_pkt_type(bcsp->rx_skb) = HCI_EVENT_PKT; 52062306a36Sopenharmony_ci pass_up = 1; 52162306a36Sopenharmony_ci } else if ((bcsp->rx_skb->data[1] & 0x0f) == 7) { 52262306a36Sopenharmony_ci hci_skb_pkt_type(bcsp->rx_skb) = HCI_SCODATA_PKT; 52362306a36Sopenharmony_ci pass_up = 1; 52462306a36Sopenharmony_ci } else if ((bcsp->rx_skb->data[1] & 0x0f) == 1 && 52562306a36Sopenharmony_ci !(bcsp->rx_skb->data[0] & 0x80)) { 52662306a36Sopenharmony_ci bcsp_handle_le_pkt(hu); 52762306a36Sopenharmony_ci pass_up = 0; 52862306a36Sopenharmony_ci } else { 52962306a36Sopenharmony_ci pass_up = 0; 53062306a36Sopenharmony_ci } 53162306a36Sopenharmony_ci } 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci if (pass_up == 0) { 53462306a36Sopenharmony_ci struct hci_event_hdr hdr; 53562306a36Sopenharmony_ci u8 desc = (bcsp->rx_skb->data[1] & 0x0f); 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci if (desc != 0 && desc != 1) { 53862306a36Sopenharmony_ci if (hciextn) { 53962306a36Sopenharmony_ci desc |= 0xc0; 54062306a36Sopenharmony_ci skb_pull(bcsp->rx_skb, 4); 54162306a36Sopenharmony_ci memcpy(skb_push(bcsp->rx_skb, 1), &desc, 1); 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ci hdr.evt = 0xff; 54462306a36Sopenharmony_ci hdr.plen = bcsp->rx_skb->len; 54562306a36Sopenharmony_ci memcpy(skb_push(bcsp->rx_skb, HCI_EVENT_HDR_SIZE), &hdr, HCI_EVENT_HDR_SIZE); 54662306a36Sopenharmony_ci hci_skb_pkt_type(bcsp->rx_skb) = HCI_EVENT_PKT; 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci hci_recv_frame(hu->hdev, bcsp->rx_skb); 54962306a36Sopenharmony_ci } else { 55062306a36Sopenharmony_ci BT_ERR("Packet for unknown channel (%u %s)", 55162306a36Sopenharmony_ci bcsp->rx_skb->data[1] & 0x0f, 55262306a36Sopenharmony_ci bcsp->rx_skb->data[0] & 0x80 ? 55362306a36Sopenharmony_ci "reliable" : "unreliable"); 55462306a36Sopenharmony_ci kfree_skb(bcsp->rx_skb); 55562306a36Sopenharmony_ci } 55662306a36Sopenharmony_ci } else 55762306a36Sopenharmony_ci kfree_skb(bcsp->rx_skb); 55862306a36Sopenharmony_ci } else if (pass_up == 1) { 55962306a36Sopenharmony_ci /* Pull out BCSP hdr */ 56062306a36Sopenharmony_ci skb_pull(bcsp->rx_skb, 4); 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci hci_recv_frame(hu->hdev, bcsp->rx_skb); 56362306a36Sopenharmony_ci } else { 56462306a36Sopenharmony_ci /* ignore packet payload of already ACKed re-transmitted 56562306a36Sopenharmony_ci * packets or when a packet was missed in the BCSP window 56662306a36Sopenharmony_ci */ 56762306a36Sopenharmony_ci kfree_skb(bcsp->rx_skb); 56862306a36Sopenharmony_ci } 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci bcsp->rx_state = BCSP_W4_PKT_DELIMITER; 57162306a36Sopenharmony_ci bcsp->rx_skb = NULL; 57262306a36Sopenharmony_ci} 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_cistatic u16 bscp_get_crc(struct bcsp_struct *bcsp) 57562306a36Sopenharmony_ci{ 57662306a36Sopenharmony_ci return get_unaligned_be16(&bcsp->rx_skb->data[bcsp->rx_skb->len - 2]); 57762306a36Sopenharmony_ci} 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci/* Recv data */ 58062306a36Sopenharmony_cistatic int bcsp_recv(struct hci_uart *hu, const void *data, int count) 58162306a36Sopenharmony_ci{ 58262306a36Sopenharmony_ci struct bcsp_struct *bcsp = hu->priv; 58362306a36Sopenharmony_ci const unsigned char *ptr; 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci BT_DBG("hu %p count %d rx_state %d rx_count %ld", 58662306a36Sopenharmony_ci hu, count, bcsp->rx_state, bcsp->rx_count); 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci ptr = data; 58962306a36Sopenharmony_ci while (count) { 59062306a36Sopenharmony_ci if (bcsp->rx_count) { 59162306a36Sopenharmony_ci if (*ptr == 0xc0) { 59262306a36Sopenharmony_ci BT_ERR("Short BCSP packet"); 59362306a36Sopenharmony_ci kfree_skb(bcsp->rx_skb); 59462306a36Sopenharmony_ci bcsp->rx_skb = NULL; 59562306a36Sopenharmony_ci bcsp->rx_state = BCSP_W4_PKT_START; 59662306a36Sopenharmony_ci bcsp->rx_count = 0; 59762306a36Sopenharmony_ci } else 59862306a36Sopenharmony_ci bcsp_unslip_one_byte(bcsp, *ptr); 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci ptr++; count--; 60162306a36Sopenharmony_ci continue; 60262306a36Sopenharmony_ci } 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci switch (bcsp->rx_state) { 60562306a36Sopenharmony_ci case BCSP_W4_BCSP_HDR: 60662306a36Sopenharmony_ci if ((0xff & (u8)~(bcsp->rx_skb->data[0] + bcsp->rx_skb->data[1] + 60762306a36Sopenharmony_ci bcsp->rx_skb->data[2])) != bcsp->rx_skb->data[3]) { 60862306a36Sopenharmony_ci BT_ERR("Error in BCSP hdr checksum"); 60962306a36Sopenharmony_ci kfree_skb(bcsp->rx_skb); 61062306a36Sopenharmony_ci bcsp->rx_skb = NULL; 61162306a36Sopenharmony_ci bcsp->rx_state = BCSP_W4_PKT_DELIMITER; 61262306a36Sopenharmony_ci bcsp->rx_count = 0; 61362306a36Sopenharmony_ci continue; 61462306a36Sopenharmony_ci } 61562306a36Sopenharmony_ci bcsp->rx_state = BCSP_W4_DATA; 61662306a36Sopenharmony_ci bcsp->rx_count = (bcsp->rx_skb->data[1] >> 4) + 61762306a36Sopenharmony_ci (bcsp->rx_skb->data[2] << 4); /* May be 0 */ 61862306a36Sopenharmony_ci continue; 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_ci case BCSP_W4_DATA: 62162306a36Sopenharmony_ci if (bcsp->rx_skb->data[0] & 0x40) { /* pkt with crc */ 62262306a36Sopenharmony_ci bcsp->rx_state = BCSP_W4_CRC; 62362306a36Sopenharmony_ci bcsp->rx_count = 2; 62462306a36Sopenharmony_ci } else 62562306a36Sopenharmony_ci bcsp_complete_rx_pkt(hu); 62662306a36Sopenharmony_ci continue; 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci case BCSP_W4_CRC: 62962306a36Sopenharmony_ci if (bitrev16(bcsp->message_crc) != bscp_get_crc(bcsp)) { 63062306a36Sopenharmony_ci BT_ERR("Checksum failed: computed %04x received %04x", 63162306a36Sopenharmony_ci bitrev16(bcsp->message_crc), 63262306a36Sopenharmony_ci bscp_get_crc(bcsp)); 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci kfree_skb(bcsp->rx_skb); 63562306a36Sopenharmony_ci bcsp->rx_skb = NULL; 63662306a36Sopenharmony_ci bcsp->rx_state = BCSP_W4_PKT_DELIMITER; 63762306a36Sopenharmony_ci bcsp->rx_count = 0; 63862306a36Sopenharmony_ci continue; 63962306a36Sopenharmony_ci } 64062306a36Sopenharmony_ci skb_trim(bcsp->rx_skb, bcsp->rx_skb->len - 2); 64162306a36Sopenharmony_ci bcsp_complete_rx_pkt(hu); 64262306a36Sopenharmony_ci continue; 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_ci case BCSP_W4_PKT_DELIMITER: 64562306a36Sopenharmony_ci switch (*ptr) { 64662306a36Sopenharmony_ci case 0xc0: 64762306a36Sopenharmony_ci bcsp->rx_state = BCSP_W4_PKT_START; 64862306a36Sopenharmony_ci break; 64962306a36Sopenharmony_ci default: 65062306a36Sopenharmony_ci /*BT_ERR("Ignoring byte %02x", *ptr);*/ 65162306a36Sopenharmony_ci break; 65262306a36Sopenharmony_ci } 65362306a36Sopenharmony_ci ptr++; count--; 65462306a36Sopenharmony_ci break; 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci case BCSP_W4_PKT_START: 65762306a36Sopenharmony_ci switch (*ptr) { 65862306a36Sopenharmony_ci case 0xc0: 65962306a36Sopenharmony_ci ptr++; count--; 66062306a36Sopenharmony_ci break; 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_ci default: 66362306a36Sopenharmony_ci bcsp->rx_state = BCSP_W4_BCSP_HDR; 66462306a36Sopenharmony_ci bcsp->rx_count = 4; 66562306a36Sopenharmony_ci bcsp->rx_esc_state = BCSP_ESCSTATE_NOESC; 66662306a36Sopenharmony_ci BCSP_CRC_INIT(bcsp->message_crc); 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_ci /* Do not increment ptr or decrement count 66962306a36Sopenharmony_ci * Allocate packet. Max len of a BCSP pkt= 67062306a36Sopenharmony_ci * 0xFFF (payload) +4 (header) +2 (crc) 67162306a36Sopenharmony_ci */ 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_ci bcsp->rx_skb = bt_skb_alloc(0x1005, GFP_ATOMIC); 67462306a36Sopenharmony_ci if (!bcsp->rx_skb) { 67562306a36Sopenharmony_ci BT_ERR("Can't allocate mem for new packet"); 67662306a36Sopenharmony_ci bcsp->rx_state = BCSP_W4_PKT_DELIMITER; 67762306a36Sopenharmony_ci bcsp->rx_count = 0; 67862306a36Sopenharmony_ci return 0; 67962306a36Sopenharmony_ci } 68062306a36Sopenharmony_ci break; 68162306a36Sopenharmony_ci } 68262306a36Sopenharmony_ci break; 68362306a36Sopenharmony_ci } 68462306a36Sopenharmony_ci } 68562306a36Sopenharmony_ci return count; 68662306a36Sopenharmony_ci} 68762306a36Sopenharmony_ci 68862306a36Sopenharmony_ci /* Arrange to retransmit all messages in the relq. */ 68962306a36Sopenharmony_cistatic void bcsp_timed_event(struct timer_list *t) 69062306a36Sopenharmony_ci{ 69162306a36Sopenharmony_ci struct bcsp_struct *bcsp = from_timer(bcsp, t, tbcsp); 69262306a36Sopenharmony_ci struct hci_uart *hu = bcsp->hu; 69362306a36Sopenharmony_ci struct sk_buff *skb; 69462306a36Sopenharmony_ci unsigned long flags; 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_ci BT_DBG("hu %p retransmitting %u pkts", hu, bcsp->unack.qlen); 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci spin_lock_irqsave_nested(&bcsp->unack.lock, flags, SINGLE_DEPTH_NESTING); 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci while ((skb = __skb_dequeue_tail(&bcsp->unack)) != NULL) { 70162306a36Sopenharmony_ci bcsp->msgq_txseq = (bcsp->msgq_txseq - 1) & 0x07; 70262306a36Sopenharmony_ci skb_queue_head(&bcsp->rel, skb); 70362306a36Sopenharmony_ci } 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ci spin_unlock_irqrestore(&bcsp->unack.lock, flags); 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_ci hci_uart_tx_wakeup(hu); 70862306a36Sopenharmony_ci} 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_cistatic int bcsp_open(struct hci_uart *hu) 71162306a36Sopenharmony_ci{ 71262306a36Sopenharmony_ci struct bcsp_struct *bcsp; 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci BT_DBG("hu %p", hu); 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_ci bcsp = kzalloc(sizeof(*bcsp), GFP_KERNEL); 71762306a36Sopenharmony_ci if (!bcsp) 71862306a36Sopenharmony_ci return -ENOMEM; 71962306a36Sopenharmony_ci 72062306a36Sopenharmony_ci hu->priv = bcsp; 72162306a36Sopenharmony_ci bcsp->hu = hu; 72262306a36Sopenharmony_ci skb_queue_head_init(&bcsp->unack); 72362306a36Sopenharmony_ci skb_queue_head_init(&bcsp->rel); 72462306a36Sopenharmony_ci skb_queue_head_init(&bcsp->unrel); 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci timer_setup(&bcsp->tbcsp, bcsp_timed_event, 0); 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ci bcsp->rx_state = BCSP_W4_PKT_DELIMITER; 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_ci if (txcrc) 73162306a36Sopenharmony_ci bcsp->use_crc = 1; 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_ci return 0; 73462306a36Sopenharmony_ci} 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_cistatic int bcsp_close(struct hci_uart *hu) 73762306a36Sopenharmony_ci{ 73862306a36Sopenharmony_ci struct bcsp_struct *bcsp = hu->priv; 73962306a36Sopenharmony_ci 74062306a36Sopenharmony_ci timer_shutdown_sync(&bcsp->tbcsp); 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ci hu->priv = NULL; 74362306a36Sopenharmony_ci 74462306a36Sopenharmony_ci BT_DBG("hu %p", hu); 74562306a36Sopenharmony_ci 74662306a36Sopenharmony_ci skb_queue_purge(&bcsp->unack); 74762306a36Sopenharmony_ci skb_queue_purge(&bcsp->rel); 74862306a36Sopenharmony_ci skb_queue_purge(&bcsp->unrel); 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_ci if (bcsp->rx_skb) { 75162306a36Sopenharmony_ci kfree_skb(bcsp->rx_skb); 75262306a36Sopenharmony_ci bcsp->rx_skb = NULL; 75362306a36Sopenharmony_ci } 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_ci kfree(bcsp); 75662306a36Sopenharmony_ci return 0; 75762306a36Sopenharmony_ci} 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_cistatic const struct hci_uart_proto bcsp = { 76062306a36Sopenharmony_ci .id = HCI_UART_BCSP, 76162306a36Sopenharmony_ci .name = "BCSP", 76262306a36Sopenharmony_ci .open = bcsp_open, 76362306a36Sopenharmony_ci .close = bcsp_close, 76462306a36Sopenharmony_ci .enqueue = bcsp_enqueue, 76562306a36Sopenharmony_ci .dequeue = bcsp_dequeue, 76662306a36Sopenharmony_ci .recv = bcsp_recv, 76762306a36Sopenharmony_ci .flush = bcsp_flush 76862306a36Sopenharmony_ci}; 76962306a36Sopenharmony_ci 77062306a36Sopenharmony_ciint __init bcsp_init(void) 77162306a36Sopenharmony_ci{ 77262306a36Sopenharmony_ci return hci_uart_register_proto(&bcsp); 77362306a36Sopenharmony_ci} 77462306a36Sopenharmony_ci 77562306a36Sopenharmony_ciint __exit bcsp_deinit(void) 77662306a36Sopenharmony_ci{ 77762306a36Sopenharmony_ci return hci_uart_unregister_proto(&bcsp); 77862306a36Sopenharmony_ci} 77962306a36Sopenharmony_ci 78062306a36Sopenharmony_cimodule_param(txcrc, bool, 0644); 78162306a36Sopenharmony_ciMODULE_PARM_DESC(txcrc, "Transmit CRC with every BCSP packet"); 78262306a36Sopenharmony_ci 78362306a36Sopenharmony_cimodule_param(hciextn, bool, 0644); 78462306a36Sopenharmony_ciMODULE_PARM_DESC(hciextn, "Convert HCI Extensions into BCSP packets"); 785