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

📄 hci_bcsp.c

📁 linux蓝牙USB HCI层驱动,简单明了非常适合蓝牙开发人员学习
💻 C
📖 第 1 页 / 共 2 页
字号:
	for (i = 0, skb = ((struct sk_buff *) &bcsp->unack)->next; i < pkts_to_be_removed			&& skb != (struct sk_buff *) &bcsp->unack; i++) {		struct sk_buff *nskb;		nskb = skb->next;		__skb_unlink(skb, &bcsp->unack);		kfree_skb(skb);		skb = nskb;	}	if (bcsp->unack.qlen == 0)		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);		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 inline 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) {		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) {		bcsp->rx_skb->pkt_type = HCI_EVENT_PKT;		pass_up = 1;	} else if ((bcsp->rx_skb->data[1] & 0x0f) == 7) {		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) {		if ((bcsp->rx_skb->data[1] & 0x0f) != 0 &&	    		(bcsp->rx_skb->data[1] & 0x0f) != 1) {			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 {		/* 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;}/* 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 %ld 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 (bcsp_crc_reverse(bcsp->message_crc) !=					(bcsp->rx_skb->data[bcsp->rx_skb->len - 2] << 8) +					bcsp->rx_skb->data[bcsp->rx_skb->len - 1]) {				BT_ERR ("Checksum failed: computed %04x received %04x",					bcsp_crc_reverse(bcsp->message_crc),				     	(bcsp->rx_skb-> data[bcsp->rx_skb->len - 2] << 8) +				     	bcsp->rx_skb->data[bcsp->rx_skb->len - 1]);				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 = bluez_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 = (struct bcsp_struct *) hu->priv;	struct sk_buff *skb;	unsigned long flags;	BT_ERR("Timeout, retransmitting %u pkts", bcsp->unack.qlen);	spin_lock_irqsave(&bcsp->unack.lock, flags);	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 = kmalloc(sizeof(*bcsp), GFP_ATOMIC);	if (!bcsp)		return -ENOMEM;	memset(bcsp, 0, sizeof(*bcsp));	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;	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){	return hci_uart_register_proto(&bcsp);}int bcsp_deinit(void){	return hci_uart_unregister_proto(&bcsp);}

⌨️ 快捷键说明

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