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

📄 hci.c

📁 blue tooth protocol stack source code
💻 C
📖 第 1 页 / 共 5 页
字号:
				   the HCI header and the HCI data */				tmp_pos = 0;				state = WAIT_FOR_ACL_DATA;			} else if (tmp_pos < ACL_HDR_LEN) {				D_REC(__FUNCTION__ ": Didn't got whole header length, waiting for more\n");			} else {				D_ERR(__FUNCTION__ ": incorredt ACL header length\n");			}			break;			/* Finally we process the data, i.e we wait for the			   whole data packet and then we send it to a higher			   protocol layer, in this case the L2CAP-layer */		case WAIT_FOR_ACL_DATA:			D_STATE(__FUNCTION__ ": WAIT_FOR_ACL_DATA\n");			/* Find out how much data we can copy, don't copy more			   than one HCI packet at time */			c = MIN(count, data_len - tmp_pos);			if (in_buf) {				memcpy(in_buf->buf_ptr, buf, c);				in_buf->buf_ptr += c;				in_buf->count += c;				D_REC(__FUNCTION__ ": in_buf->count = %d\n",in_buf->count);			}      			/* Increase the data_index and decrease the amount of			   data */			tmp_pos += c;			count -= c;      			D_REC(__FUNCTION__ ": Copied %d bytes into inbuffer\n",c);			if (tmp_pos == data_len) {				if (in_buf) {					process_acl_data(in_buf, pb_flag);				} else {					D_ERR("invalid inbuffer\n");				}				state = WAIT_FOR_PACKET_TYPE;			}			buf += c;			break;      			/* wait for the SCO header, three bytes */		case WAIT_FOR_SCO_HDR:			D_STATE(__FUNCTION__ ": WAIT_FOR_SCO_HDR\n");			if (tmp_pos < SCO_HDR_LEN) {				c = MIN(count,SCO_HDR_LEN - tmp_pos);				memcpy(hdr + tmp_pos, buf, c);				tmp_pos += c;				buf += c;				count -= c;				if (tmp_pos == SCO_HDR_LEN) {					hci_hdl = hci_handle(hdr);					data_len = hdr[2];					tmp_pos = 0;					state = WAIT_FOR_SCO_DATA;				}			}			break;			/* Wait for the rest of the SCO packet and send it to			   the tty */		case WAIT_FOR_SCO_DATA:			D_STATE(__FUNCTION__ ": WAIT_FOR_SCO_DATA\n");			c = MIN(count, data_len - tmp_pos);			process_sco_packet(buf, hci_hdl, c);			tmp_pos += c;			buf += c;			count -= c;			if (tmp_pos == data_len) {				state = WAIT_FOR_PACKET_TYPE;        				/* FIXME - Send the data to the audio tty */			}			break;		default:			D_ERR(__FUNCTION__ ": Oops shouldn't be possible...\n");			break;		}	}}#ifdef CONFIG_BLUETOOTH_SUPPORT_BCSPvoidhci_receive_event(u8 *data, s32 count){	u8 event_type, event_len;	u8 *tmp_buf;	tmp_buf = data;		while (count > 0) {		event_type = tmp_buf[0];		event_len = tmp_buf[1];		tmp_buf += EVENT_HDR_LEN;		count -= EVENT_HDR_LEN;		D_REC(__FUNCTION__ ": Received event 0x%02x with len:%d\n", event_type, event_len);				process_event(tmp_buf, event_len, event_type);		tmp_buf += event_len;		count -= event_len;	}}voidhci_receive_acl(u8 *data, s32 count){	u8 *tmp_buf;	u16 hci_hdl;	u8 pb_flag;	u8 bc_flag;	u16 data_len;	hci_in_buffer *in_buf;	tmp_buf = data;	while (count > 0) {		u32 tmp_hdr = le32_to_cpuu(tmp_buf);		/* Parse the ACL header */		hci_hdl = GET_BITS(tmp_hdr, 0, 12);		pb_flag = GET_BITS(tmp_hdr, 12, 2);		bc_flag = GET_BITS(tmp_hdr, 14, 2);		data_len = GET_BITS(tmp_hdr, 16, 16);		tmp_buf += ACL_HDR_LEN;		count -= ACL_HDR_LEN;				/* Check the length to make sure we won't 		   overrun in_buf->buf_ptr in a memcpy later.		   --gmcnutt		*/		if (data_len > HCI_IN_SIZE) {			D_ERR(__FUNCTION__ ": %d is too big "\			      "for our HCI input buffers -- "\			      "discarding buffer\n",			      data_len);			return;		}				if (pb_flag == L2CAP_FRAME_START) {			D_REC(__FUNCTION__ ": New L2CAP frame\n");			in_buf = get_free_inbuffer();			if (in_buf) {				in_buf->nbr_of_hci_pkt = 1;				in_buf->hci_hdl = hci_hdl;			}			} else {			D_REC(__FUNCTION__ ": Cont L2CAP frame\n");			in_buf = get_inbuffer(hci_hdl);			if (in_buf) {				in_buf->nbr_of_hci_pkt++;			}		}				if (in_buf) {			memcpy(in_buf->buf_ptr, tmp_buf, data_len);			D_REC(__FUNCTION__ ": Copied %d bytes into inbuffer\n",			      data_len);			in_buf->buf_ptr += data_len;			in_buf->count += data_len;			D_REC(__FUNCTION__ ": in_buf->count: %d\n", in_buf->count);		} else {			D_ERR(__FUNCTION__ ": No inbuffer was found, "\			      "discarding data\n");			return;		}				/* Decrease the amount of remaining data */		count -= data_len;				process_acl_data(in_buf, pb_flag);		tmp_buf += data_len;	}}#endifs32hci_trig_send(void){#ifdef __KERNEL__	if (buf_count() && (hci_ctrl.hc_buf.acl_num > 0)) {#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)		queue_task(&send_data_task, &tq_scheduler);#else		queue_task(&send_data_task, &tq_immediate);		mark_bh(IMMEDIATE_BH);#endif		return TRUE;	} else {		return FALSE;	}#else        /* FIXME? */        return FALSE;#endif}s32hci_acl_num_cnt(void){	return hci_ctrl.hc_buf.acl_num;}voidupdate_ncp(u8 nbr_of_hdl, u8 *pkt){	s32 i;#ifdef __KERNEL__	unsigned long flags;	save_flags(flags);	cli();#endif	D_REC(__FUNCTION__ ": acl_num before: %d\n", hci_ctrl.hc_buf.acl_num);		/* FIXME */	/* Check if we have to register which connection handlers that	   have been sent, or if we just need to know how many packets	   that have been sent */	for (i = 0; i < 4 * nbr_of_hdl; i += 4) {		hci_ctrl.hc_buf.acl_num += le16_to_cpuu(&pkt[i+2]);	}		D_QUEUE("<NCP:%d>\n", hci_ctrl.hc_buf.acl_num);	D_REC(__FUNCTION__ ": acl_num after: %d\n", hci_ctrl.hc_buf.acl_num);	/* We've just been notified that the hardware has free buffers.	   If we have any outstanding packets, send_acl_data_task will try	   to send as many packets as possible. */#ifdef __KERNEL__	if (buf_count()) {	     #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)		queue_task(&send_data_task, &tq_scheduler);#else		queue_task(&send_data_task, &tq_immediate);		mark_bh(IMMEDIATE_BH);#endif	}#ifdef USE_NCPTIMER	hw.acl_num_count += hci_ctrl.hc_buf.acl_num;#endif	bt_feedstack();	restore_flags(flags);#else	if (buf_count())		send_acl_data_task();#endif	}/* * Parses an eventpacket, buf is the event parameters, length the event length * and event_code is the event's opcode */voidprocess_event(u8 *buf, u32 len, u32 event_code){	u16 hci_hdl;	s32 i;	PRINTPKT(__FUNCTION__, buf, len);        switch (event_code) {	case INQUIRY_COMPLETE:		D_CMD("INQUIRY_COMPLETE\n");                hci_inq_pending = 0;#if USE_INQTIMER		release_inq_timer();#endif		wake_up_interruptible(&inq_wq);#ifndef __KERNEL__		for (i = 0; i < inq_res->nbr_of_units; i++) {			D_CMD(__FUNCTION__ ": BD %d: %02x:%02x:%02x:%02x:%02x:%02x\n",i,			      inq_res->bd_addr[0+6*i],inq_res->bd_addr[1+6*i],			      inq_res->bd_addr[2+6*i],inq_res->bd_addr[3+6*i],			      inq_res->bd_addr[4+6*i],inq_res->bd_addr[5+6*i]);		}#endif		break;	case INQUIRY_RESULT:	{		s32 j;		u8 tmp_bd[6];		D_CMD(__FUNCTION__ ": INQUIRY_RESULT\n");		for(i = 1; i < (buf[0] * 14) + 1; i += 14) {					printk("BD addr %d\n", i % 14);						for (j = 0; j < 6; j++) {				tmp_bd[5-j] = buf[i + j];			}			print_data("BD", tmp_bd, 6);			for (j = 0; j < inq_res->nbr_of_units; j++) {				if (!memcmp(inq_res->bd_addr + j * 6, tmp_bd, 6)) {					break;				}			}			if (j >= inq_res->nbr_of_units) {				memcpy(inq_res->bd_addr + 				       inq_res->nbr_of_units * 6, tmp_bd, 6);				inq_res->nbr_of_units++;			}		}		break;	}	case CONNECTION_COMPLETE:	{		u8 link_type;		D_CMD(__FUNCTION__ ": CONNECTION_COMPLETE: %s\n",		      get_err_msg(buf[0]));		link_type = buf[9];		hci_hdl = hci_handle(&buf[1]);		test_hci_hdl = hci_hdl;  		if (link_type == ACL_LINK) {			if (lp_connect_cfm(buf + 3, (u32) buf[0], hci_hdl)) {				hci_ctrl.nbr_of_connections++;				hci_update_load_factor();			}#ifndef HCI_EMULATION			if (buf[0]) {				/* remove hci handle if connection failed */				DSYS(__FUNCTION__ ": CONNECTION_COMPLETE %s\n",				     get_err_msg(buf[0]));				reset_hci_con_bd(hci_hdl);			} else {				DSYS(__FUNCTION__ ": ACL link is up\n");#ifdef CONFIG_BLUETOOTH_ERICSSON				change_connection_packet_type(hci_hdl, 							      DM3|DH3|DM5|DH5);#else				change_connection_packet_type(hci_hdl, 							      DM1|DH1|DM3|DH3|DM5|DH5);#endif				set_hci_con(buf + 3, hci_hdl);				remote_name_request(buf + 3);				/* enable m/s switch */ 				write_link_policy_settings(hci_hdl, 0x01);				/* we demand role switch as server */				if (force_msswitch && !i_am_initiator) {					/* FIXME -- check return code */#ifndef CONFIG_BLUETOOTH_EARLY_MSSWITCH					hci_switch_role(buf + 3, 0);#endif				}				/* reset variable again */				i_am_initiator = 0;			}#endif /* HCI_EMULATION */			if (test_wq_active) {				test_wq_active = 0;				wake_up_interruptible(&test_wq);			}  		} else {			hci_ctrl.nbr_of_connections++;			hci_update_load_factor();  			tcs_add_sco_link(buf[0], hci_hdl);  		}				break;	}	case CONNECTION_REQUEST:		D_CMD(__FUNCTION__ ": CONNECTION_REQUEST\n");		if (buf[9] == ACL_LINK) {			lp_connect_ind(buf); /* BD_ADDRESS */		} else {			printk(__FUNCTION__ ": CONNECTION_REQUEST for SCO LINK");			accept_connection_request(buf, 0x01); /* role ignored for SCO */		}		break;	case DISCONNECTION_COMPLETE:		DSYS(__FUNCTION__ ": DISCONNECTION_COMPLETE %s\n", get_err_msg(buf[3]));		release_cmd_timer();		wake_up_interruptible(&hci_wq);		if (lp_disconnect_ind(hci_handle(&buf[1])))			if (hci_ctrl.nbr_of_connections > 0) {				hci_ctrl.nbr_of_connections--;				hci_update_load_factor();			}		/* FIXME: No more NBR_OF_COMPLETE_PACKETS will arrive for this		   connection handle, if we only support point-to-point		   connections we can acl_num by reading the buffersizes again,		   but this will not work in a multipoint connection. */		reset_hci_con_bd(hci_handle(&buf[1]));				if (hci_ctrl.nbr_of_connections <= 0) {			hci_read_buffer_size(HCI_NON_BLOCK);		}		break;	case AUTHENTICATION_COMPLETE:		DSYS(__FUNCTION__ ": AUTHENTICATION_COMPLETE\n");		release_cmd_timer();		#ifdef CONFIG_BLUETOOTH_USE_SECURITY_MANAGER		if (buf[0]) {			D_ERR(__FUNCTION__ ": AUTHENTICATION_COMPLETE: %s\n", get_err_msg(buf[0]));					}				sec_man_event(HCI, get_bd(hci_handle(&buf[1])), AUTHENTICATION_COMPLETE, buf, 1);#endif		wake_up_interruptible(&hci_wq);		break;	case REMOTE_NAME_REQUEST_COMPLETE:		D_CMD(__FUNCTION__ ": REMOTE_NAME_REQUEST_COMPLETE %s\n", buf + 7);		if (buf[0]) {			D_ERR(__FUNCTION__ ": REMOTE_NAME_REQUEST_COMPLETE: %s\n",			      get_err_msg(buf[0]));		} else {			if (strlen(buf + 7) > 248) {				D_ERR(__FUNCTION__ ": REMOTE_NAME_REQUEST_COMPLETE: too long name length %d\n", (int)strlen(buf + 7));				break;			}			set_hci_con_name(buf + 1, buf + 7);		}		break;	case ENCRYPTION_CHANGE:		DSYS(__FUNCTION__ ": ENCRYPTION_CHANGE\n");		release_cmd_timer();#ifdef CONFIG_BLUETOOTH_USE_SECURITY_MANAGER		if (buf[0]) {			D_ERR(__FUNCTION__ ": ENCRYPTION_CHANGE: %s\n", get_err_msg(buf[0]));		}                {                        u8 tmp[2];                        tmp[0] = buf[0];                        tmp[1] = buf[3];		                        sec_man_event(HCI, get_bd(hci_handle(&buf[1])), ENCRYPTION_CHANGE, tmp, 2);                }#endif		wake_up_interruptible(&hci_wq);		break;		case CHANGE_CONNECTION_LINK_KEY_COMPLETE:		DSYS(__FUNCTION__ ": CHANGE_CONNECTION_LINK_KEY_COMPLETE Not implemented!\n");		break;	case MASTER_LINK_KEY_COMPLETE:		DSYS(__FUNCTION__ ": MASTER_LINK_KEY_COMPLETE Not implemented!\n");		break;	case READ_REMOTE_SUPPORTED_FEATURES_COMPLETE:		DSYS(__FUNCTION__ ": READ_REMOTE_SUPPORTED_FEATURES_COMPLETE Not implemented!\n");		break;	case READ_REMOTE_VERSION_INFORMATION_COMPLETE:		DSYS(__FUNCTION__ ": READ_REMOTE_VERSION_INFORMATION_COMPLETE Not implemented!\n");		break;	case QOS_SETUP_COMPLETE:		DSYS(__FUNCTION__ ": QOS_SETUP_COMPLETE\n");		break;	case COMMAND_COMPLETE:		D_CMD(__FUNCTION__ ": COMMAND_COMPLETE\n");		/* FIXME - stop any outstanding send timers if cmd_num is > 0*/		D_QUEUE("<CC>\n");		process_return_param(buf);		update_nhcp(buf[0]);		break;		/* used to prevent host from waiting on reply when a 		   command has been received in HW and is currently 		   performing the task for this command */			case COMMAND_STATUS:		release_cmd_timer();

⌨️ 快捷键说明

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