⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hci_bcsp.c

📁 Linux环境下的蓝牙模块驱动程序源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	if (skb_queue_empty(&bcsp->unack))		del_timer(&bcsp->tbcsp);	spin_unlock_irqrestore(&bcsp->unack.lock, flags);	if (i != pkts_to_be_removed)		BT_ERR("Removed only %u out of %u pkts", i, pkts_to_be_removed);}/* Handle BCSP link-establishment packets. When we   detect a "sync" packet, symptom that the BT module has reset,   we do nothing :) (yet) */static void bcsp_handle_le_pkt(struct hci_uart *hu){	struct bcsp_struct *bcsp = hu->priv;	u8 conf_pkt[4]     = { 0xad, 0xef, 0xac, 0xed };	u8 conf_rsp_pkt[4] = { 0xde, 0xad, 0xd0, 0xd0 };	u8 sync_pkt[4]     = { 0xda, 0xdc, 0xed, 0xed };	/* spot "conf" pkts and reply with a "conf rsp" pkt */	if (bcsp->rx_skb->data[1] >> 4 == 4 && bcsp->rx_skb->data[2] == 0 &&			!memcmp(&bcsp->rx_skb->data[4], conf_pkt, 4)) {		struct sk_buff *nskb = alloc_skb(4, GFP_ATOMIC);		BT_DBG("Found a LE conf pkt");		if (!nskb)			return;		memcpy(skb_put(nskb, 4), conf_rsp_pkt, 4);		bt_cb(nskb)->pkt_type = BCSP_LE_PKT;		skb_queue_head(&bcsp->unrel, nskb);		hci_uart_tx_wakeup(hu);	}	/* Spot "sync" pkts. If we find one...disaster! */	else if (bcsp->rx_skb->data[1] >> 4 == 4 && bcsp->rx_skb->data[2] == 0 &&			!memcmp(&bcsp->rx_skb->data[4], sync_pkt, 4)) {		BT_ERR("Found a LE sync pkt, card has reset");	}}static inline void bcsp_unslip_one_byte(struct bcsp_struct *bcsp, unsigned char byte){	const u8 c0 = 0xc0, db = 0xdb;	switch (bcsp->rx_esc_state) {	case BCSP_ESCSTATE_NOESC:		switch (byte) {		case 0xdb:			bcsp->rx_esc_state = BCSP_ESCSTATE_ESC;			break;		default:			memcpy(skb_put(bcsp->rx_skb, 1), &byte, 1);			if ((bcsp->rx_skb-> data[0] & 0x40) != 0 && 					bcsp->rx_state != BCSP_W4_CRC)				bcsp_crc_update(&bcsp->message_crc, byte);			bcsp->rx_count--;		}		break;	case BCSP_ESCSTATE_ESC:		switch (byte) {		case 0xdc:			memcpy(skb_put(bcsp->rx_skb, 1), &c0, 1);			if ((bcsp->rx_skb-> data[0] & 0x40) != 0 && 					bcsp->rx_state != BCSP_W4_CRC)				bcsp_crc_update(&bcsp-> message_crc, 0xc0);			bcsp->rx_esc_state = BCSP_ESCSTATE_NOESC;			bcsp->rx_count--;			break;		case 0xdd:			memcpy(skb_put(bcsp->rx_skb, 1), &db, 1);			if ((bcsp->rx_skb-> data[0] & 0x40) != 0 && 					bcsp->rx_state != BCSP_W4_CRC) 				bcsp_crc_update(&bcsp-> message_crc, 0xdb);			bcsp->rx_esc_state = BCSP_ESCSTATE_NOESC;			bcsp->rx_count--;			break;		default:			BT_ERR ("Invalid byte %02x after esc byte", byte);			kfree_skb(bcsp->rx_skb);			bcsp->rx_skb = NULL;			bcsp->rx_state = BCSP_W4_PKT_DELIMITER;			bcsp->rx_count = 0;		}	}}static void bcsp_complete_rx_pkt(struct hci_uart *hu){	struct bcsp_struct *bcsp = hu->priv;	int pass_up;	if (bcsp->rx_skb->data[0] & 0x80) {	/* reliable pkt */		BT_DBG("Received seqno %u from card", bcsp->rxseq_txack);		bcsp->rxseq_txack++;		bcsp->rxseq_txack %= 0x8;		bcsp->txack_req    = 1;		/* If needed, transmit an ack pkt */		hci_uart_tx_wakeup(hu);	}	bcsp->rxack = (bcsp->rx_skb->data[0] >> 3) & 0x07;	BT_DBG("Request for pkt %u from card", bcsp->rxack);	bcsp_pkt_cull(bcsp);	if ((bcsp->rx_skb->data[1] & 0x0f) == 6 &&			bcsp->rx_skb->data[0] & 0x80) {		bt_cb(bcsp->rx_skb)->pkt_type = HCI_ACLDATA_PKT;		pass_up = 1;	} else if ((bcsp->rx_skb->data[1] & 0x0f) == 5 &&			bcsp->rx_skb->data[0] & 0x80) {		bt_cb(bcsp->rx_skb)->pkt_type = HCI_EVENT_PKT;		pass_up = 1;	} else if ((bcsp->rx_skb->data[1] & 0x0f) == 7) {		bt_cb(bcsp->rx_skb)->pkt_type = HCI_SCODATA_PKT;		pass_up = 1;	} else if ((bcsp->rx_skb->data[1] & 0x0f) == 1 &&			!(bcsp->rx_skb->data[0] & 0x80)) {		bcsp_handle_le_pkt(hu);		pass_up = 0;	} else		pass_up = 0;	if (!pass_up) {		struct hci_event_hdr hdr;		u8 desc = (bcsp->rx_skb->data[1] & 0x0f);		if (desc != 0 && desc != 1) {			if (hciextn) {				desc |= 0xc0;				skb_pull(bcsp->rx_skb, 4);				memcpy(skb_push(bcsp->rx_skb, 1), &desc, 1);				hdr.evt = 0xff;				hdr.plen = bcsp->rx_skb->len;				memcpy(skb_push(bcsp->rx_skb, HCI_EVENT_HDR_SIZE), &hdr, HCI_EVENT_HDR_SIZE);				bt_cb(bcsp->rx_skb)->pkt_type = HCI_EVENT_PKT;				hci_recv_frame(bcsp->rx_skb);			} else {				BT_ERR ("Packet for unknown channel (%u %s)",					bcsp->rx_skb->data[1] & 0x0f,					bcsp->rx_skb->data[0] & 0x80 ? 					"reliable" : "unreliable");				kfree_skb(bcsp->rx_skb);			}		} else			kfree_skb(bcsp->rx_skb);	} else {		/* Pull out BCSP hdr */		skb_pull(bcsp->rx_skb, 4);		hci_recv_frame(bcsp->rx_skb);	}	bcsp->rx_state = BCSP_W4_PKT_DELIMITER;	bcsp->rx_skb = NULL;}static u16 bscp_get_crc(struct bcsp_struct *bcsp){	return get_unaligned_be16(&bcsp->rx_skb->data[bcsp->rx_skb->len - 2]);}/* Recv data */static int bcsp_recv(struct hci_uart *hu, void *data, int count){	struct bcsp_struct *bcsp = hu->priv;	register unsigned char *ptr;	BT_DBG("hu %p count %d rx_state %d rx_count %ld", 		hu, count, bcsp->rx_state, bcsp->rx_count);	ptr = data;	while (count) {		if (bcsp->rx_count) {			if (*ptr == 0xc0) {				BT_ERR("Short BCSP packet");				kfree_skb(bcsp->rx_skb);				bcsp->rx_state = BCSP_W4_PKT_START;				bcsp->rx_count = 0;			} else				bcsp_unslip_one_byte(bcsp, *ptr);			ptr++; count--;			continue;		}		switch (bcsp->rx_state) {		case BCSP_W4_BCSP_HDR:			if ((0xff & (u8) ~ (bcsp->rx_skb->data[0] + bcsp->rx_skb->data[1] +					bcsp->rx_skb->data[2])) != bcsp->rx_skb->data[3]) {				BT_ERR("Error in BCSP hdr checksum");				kfree_skb(bcsp->rx_skb);				bcsp->rx_state = BCSP_W4_PKT_DELIMITER;				bcsp->rx_count = 0;				continue;			}			if (bcsp->rx_skb->data[0] & 0x80	/* reliable pkt */			    		&& (bcsp->rx_skb->data[0] & 0x07) != bcsp->rxseq_txack) {				BT_ERR ("Out-of-order packet arrived, got %u expected %u",					bcsp->rx_skb->data[0] & 0x07, bcsp->rxseq_txack);				kfree_skb(bcsp->rx_skb);				bcsp->rx_state = BCSP_W4_PKT_DELIMITER;				bcsp->rx_count = 0;				continue;			}			bcsp->rx_state = BCSP_W4_DATA;			bcsp->rx_count = (bcsp->rx_skb->data[1] >> 4) + 					(bcsp->rx_skb->data[2] << 4);	/* May be 0 */			continue;		case BCSP_W4_DATA:			if (bcsp->rx_skb->data[0] & 0x40) {	/* pkt with crc */				bcsp->rx_state = BCSP_W4_CRC;				bcsp->rx_count = 2;			} else				bcsp_complete_rx_pkt(hu);			continue;		case BCSP_W4_CRC:			if (bitrev16(bcsp->message_crc) != bscp_get_crc(bcsp)) {				BT_ERR ("Checksum failed: computed %04x received %04x",					bitrev16(bcsp->message_crc),					bscp_get_crc(bcsp));				kfree_skb(bcsp->rx_skb);				bcsp->rx_state = BCSP_W4_PKT_DELIMITER;				bcsp->rx_count = 0;				continue;			}			skb_trim(bcsp->rx_skb, bcsp->rx_skb->len - 2);			bcsp_complete_rx_pkt(hu);			continue;		case BCSP_W4_PKT_DELIMITER:			switch (*ptr) {			case 0xc0:				bcsp->rx_state = BCSP_W4_PKT_START;				break;			default:				/*BT_ERR("Ignoring byte %02x", *ptr);*/				break;			}			ptr++; count--;			break;		case BCSP_W4_PKT_START:			switch (*ptr) {			case 0xc0:				ptr++; count--;				break;			default:				bcsp->rx_state = BCSP_W4_BCSP_HDR;				bcsp->rx_count = 4;				bcsp->rx_esc_state = BCSP_ESCSTATE_NOESC;				BCSP_CRC_INIT(bcsp->message_crc);				/* Do not increment ptr or decrement count				 * Allocate packet. Max len of a BCSP pkt= 				 * 0xFFF (payload) +4 (header) +2 (crc) */				bcsp->rx_skb = bt_skb_alloc(0x1005, GFP_ATOMIC);				if (!bcsp->rx_skb) {					BT_ERR("Can't allocate mem for new packet");					bcsp->rx_state = BCSP_W4_PKT_DELIMITER;					bcsp->rx_count = 0;					return 0;				}				bcsp->rx_skb->dev = (void *) hu->hdev;				break;			}			break;		}	}	return count;}	/* Arrange to retransmit all messages in the relq. */static void bcsp_timed_event(unsigned long arg){	struct hci_uart *hu = (struct hci_uart *) arg;	struct bcsp_struct *bcsp = hu->priv;	struct sk_buff *skb;	unsigned long flags;	BT_DBG("hu %p retransmitting %u pkts", hu, bcsp->unack.qlen);	spin_lock_irqsave_nested(&bcsp->unack.lock, flags, SINGLE_DEPTH_NESTING);	while ((skb = __skb_dequeue_tail(&bcsp->unack)) != NULL) {		bcsp->msgq_txseq = (bcsp->msgq_txseq - 1) & 0x07;		skb_queue_head(&bcsp->rel, skb);	}	spin_unlock_irqrestore(&bcsp->unack.lock, flags);	hci_uart_tx_wakeup(hu);}static int bcsp_open(struct hci_uart *hu){	struct bcsp_struct *bcsp;	BT_DBG("hu %p", hu);	bcsp = kzalloc(sizeof(*bcsp), GFP_ATOMIC);	if (!bcsp)		return -ENOMEM;	hu->priv = bcsp;	skb_queue_head_init(&bcsp->unack);	skb_queue_head_init(&bcsp->rel);	skb_queue_head_init(&bcsp->unrel);	init_timer(&bcsp->tbcsp);	bcsp->tbcsp.function = bcsp_timed_event;	bcsp->tbcsp.data     = (u_long) hu;	bcsp->rx_state = BCSP_W4_PKT_DELIMITER;	if (txcrc)		bcsp->use_crc = 1;	return 0;}static int bcsp_close(struct hci_uart *hu){	struct bcsp_struct *bcsp = hu->priv;	hu->priv = NULL;	BT_DBG("hu %p", hu);	skb_queue_purge(&bcsp->unack);	skb_queue_purge(&bcsp->rel);	skb_queue_purge(&bcsp->unrel);	del_timer(&bcsp->tbcsp);	kfree(bcsp);	return 0;}static struct hci_uart_proto bcsp = {	.id		= HCI_UART_BCSP,	.open		= bcsp_open,	.close		= bcsp_close,	.enqueue	= bcsp_enqueue,	.dequeue	= bcsp_dequeue,	.recv		= bcsp_recv,	.flush		= bcsp_flush};int bcsp_init(void){	int err = hci_uart_register_proto(&bcsp);	if (!err)		BT_INFO("HCI BCSP protocol initialized");	else		BT_ERR("HCI BCSP protocol registration failed");	return err;}int bcsp_deinit(void){	return hci_uart_unregister_proto(&bcsp);}module_param(txcrc, bool, 0644);MODULE_PARM_DESC(txcrc, "Transmit CRC with every BCSP packet");module_param(hciextn, bool, 0644);MODULE_PARM_DESC(hciextn, "Convert HCI Extensions into BCSP packets");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -