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

📄 bluetooth.c

📁 blue tooth protocol stack source code
💻 C
📖 第 1 页 / 共 5 页
字号:
#ifdef BT_USELINEBUF		/* WINDOZE FIX */		BT_DATA(__FUNCTION__ ": (%d) line %d not active yet..., buffer it !\n", len, line);		/* FIXME -- only buffer first packet ? */		bt_linebuf_add(line, data, len);#else		BT_DATA(__FUNCTION__ ": (%d) line %d not active yet... silent discard!\n", len, line);#endif		return 0;	}	bt_stat.bytes_received += len;	upper_tty = GET_UPPERTTY(line);	if (upper_tty) {		upper_tty->ldisc.receive_buf(upper_tty, data, NULL, len);  	} else {//		D_ERR(__FUNCTION__ ": No upper tty registered !!!\n");		return -1;	}	return 0;}//#define IMPROVE_RFCOMM_FLOWvoid bt_feedstack(void){	struct tty_struct *upper_tty = NULL;	s32 check_line;	s32 nbr_checked = 0;	if (NBR_ACTIVE == 0) {		return;	}	/* If buffer usage is less than BTMEM_UNTHROTTLE_SIZE check if we 	   should wake up ldisc */	if (buf_byte_count(-1) >= BTMEM_UNTHROTTLE_SIZE) {		return;	}			/* Choose next line to check */	if (NBR_ACTIVE == 1) {		/* check same as last time */		check_line = bt_ctrl.tty_last_unthrottled;	} else if (bt_ctrl.tty_last_unthrottled == BT_NBR_DATAPORTS-1) {		/* wrap */		check_line = 0;	} else {		check_line = bt_ctrl.tty_last_unthrottled+1;		}		//	BT_DATA(__FUNCTION__ ": Start on line %d\n", check_line);			/* skip non-active and control port (last) */	while ((SESSIONSTATE(check_line) != BT_ACTIVE) && 	       (nbr_checked <= BT_NBR_DATAPORTS)) {		check_line++;		nbr_checked++;		if (check_line == BT_NBR_DATAPORTS) /* wrap */			check_line = 0;	}	/* check if we really found an active */	if (nbr_checked > BT_NBR_DATAPORTS)		return;//	BT_DATA(__FUNCTION__ ": Wakeup line %d !\n", check_line);	upper_tty = GET_UPPERTTY(check_line);	bt_ctrl.tty_last_unthrottled = check_line;			if (!upper_tty) {//		BT_DATA("No active line to feed from!\n");		return;	}#ifdef IMPROVE_RFCOMM_FLOW	/* FIXME: How should we know what serverchannel we are using ? */	if (rfcomm_flow_stop(check_line, 2)) {		BT_DATA(__FUNCTION__ ": Flow stopped in RFCOMM\n");		return;	}#endif	if ((upper_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&	    upper_tty->ldisc.write_wakeup) {//		BT_DATA("   |X|<<***     [%d]\n", check_line);				/* TTY_DO_WRITE_WAKEUP bit is cleared in 		   upper_tty->flags which means user mode process 		   will be able to write more data */		(upper_tty->ldisc.write_wakeup)(upper_tty);	} else if (!upper_tty->ldisc.write_wakeup) {     		/* if no wake_up function is defined (N_TTY ldisc)		   wake up wait queue *///		BT_DATA("   |X|<<***     [%d] (n_tty)\n", check_line);		wake_up_interruptible(&upper_tty->write_wait);	}}/* Used to wait for dma to finish transmission */void bt_wait_tx(s32 trim_delay){	while (sertty->driver.chars_in_buffer(sertty) > 0)		udelay(100);	udelay(trim_delay);}#ifdef CONFIG_BLUETOOTH_USE_INBUFFERstatic void bt_handle_indata(const __u8 *data, s32 count){	s32 free;	/* Check if there is data that hasn't been passed up to hci yet. 	   In that case there is a task scheduled for this and we shouldn't 	   add another one. */	if (hci_data.put == hci_data.get) {		bt_receive_task.routine = (void*)hci_receive_data_task;		bt_receive_task.data = NULL;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)		queue_task(&bt_receive_task, &tq_scheduler);#else		queue_task(&bt_receive_task, &tq_immediate);		mark_bh(IMMEDIATE_BH);#endif	}	if (hci_data.put >= hci_data.get) {		/* check for overruns... */		if (hci_data.put + count - BT_INBUFFER_SIZE >= hci_data.get) {			D_ERR(__FUNCTION__ ": Buffer overrun!\n");		} else {			/* Calculate how much space there is left at the end 			   of the buffer */			free = hci_data.tail - hci_data.put + 1;			/* normal case, data fits in buffer */			if (count < free) {				memcpy(hci_data.put, (u8*)data, count);			} else {				/* wrap buffer */				memcpy(hci_data.put, (u8*)data, free);				memcpy(hci_data.head, (u8*)(data + free), count - free);    			}		}	} else { 		/* hci_data.put < hci_data.get */		/* check for overruns ... */		if (hci_data.put + count >= hci_data.get) {			D_ERR(__FUNCTION__ ": Buffer overrun!\n");		} else {			/* Copy the data to the buffer */			memcpy(hci_data.put, (u8*)data, count);		}	}  	hci_data.put += count;	if (hci_data.put > hci_data.tail)		hci_data.put -= BT_INBUFFER_SIZE; }static voidhci_receive_data_task(void){	s32 size_end;	s32 size_start;	u8* getTemp;	cli();	if (hci_data.get == hci_data.put) {		sti();		return;	} else if (hci_data.get > hci_data.put) {		/* buffer is wrapped */		size_end = hci_data.tail - hci_data.get + 1;		size_start = hci_data.put - hci_data.head;		getTemp = hci_data.get;		/* Indicate that all data has been fetched (or soon will be) 		   by setting get == put. */		hci_data.get = hci_data.put;		sti();		bt_receive_data(getTemp, size_end);		bt_receive_data(hci_data.head, size_start);	}	else {		/* no wrapped buffer */		size_end = hci_data.put - hci_data.get;		getTemp = hci_data.get;		/* Indicate that all data has been fetched (or soon will be)		   by setting get == put. */		hci_data.get = hci_data.put;		sti();		bt_receive_data(getTemp, size_end);	}}#endif /* CONFIG_BLUETOOTH_USE_INBUFFER *//*  * Searches data buffer for number of completed packets (NCP)  * If only NCP data was found tell serial driver not to  * schedule a flip of DMA inbuffer. */int bt_catch_ncp(u8* data, u32 count){	int index = 0;	/* fixme -- do this for BCSP as well */#ifdef CONFIG_BLUETOOTH_SUPPORT_BCSP        if (bt_use_bcsp(-1))		return 0;#endif	/* || uart hdr | event code | par_len | nbr_handles | [data...] || */	while (index+2 < count &&	       data[index] == EVENT_PKT && 	       data[index+1] == NBR_OF_COMPLETED_PACKETS) {		/* we found a NCP */		index += (3 + data[index + 2]); /* event hdr + par len */	}	if (index == count) {		/* Contains _only_ NCP data, parse it ! */		/* The easy way would be to call bt_receive_data(data, count),		   but since it calls hci_receive_data() which is a state		   machine, we might mess up its state... */		index = 0;		while (index+2 < count) {			update_ncp(data[index+3], data+index+4);			index += (3 + data[index + 2]);		}		return 1;	}		/* Contains more than NCP data, tell serial 	   driver to queue it up as usual */	return 0;}static voidbt_receive_data(u8* data, u32 count){#ifdef CONFIG_BLUETOOTH_SUPPORT_BCSP        if (bt_use_bcsp(-1))                bcsp_receive_lower(data, count);        else#endif                hci_receive_data(data, count);}/* Opens a connection to the selected PSM, layer specific is the same as the * lowest part on the connection ID, in RFCOMM this is line | dlci, each one * is 8-bits  */s32bt_connect(u8 *bd_addr, u32 con_id){	u8 line = GET_LINE(con_id);					s32 retval = 0;	/* Check if we already got a connection on the line */	if ((SESSIONSTATE(line) == BT_LOWERCONNECTED)||	    (SESSIONSTATE(line) == BT_ACTIVE)) {		D_WARN(__FUNCTION__ ": Already got connection on line %d\n", 		       line); 		return -MSGCODE(MSG_BT_INTERFACE, BT_LINE_BUSY);	}		switch (GET_PSM(con_id)) {	case RFCOMM_LAYER:	{		u8 srv_ch;		s32 retval = 0;				CHECK_RFCOMM(con_id);		srv_ch = GET_RFCOMMSRVCH(con_id); 		bt_ctrl.session[line].connect_status = -1;		BT_DRIVER(__FUNCTION__ ": Connecting srv ch %d on line %d\n",			  srv_ch, line);		BT_DATADUMP("Remote BD: ", bd_addr, 6);		if ((retval = rfcomm_connect_req(bd_addr, srv_ch, line)) < 0) {			BT_DRIVER(__FUNCTION__ ": Failed\n");			return retval;		}                                /* sleep if not yet connected */                if (bt_ctrl.session[line].connect_status == -1) {			start_wq_timer(&bt_timer, BT_CON_TIMEOUT, 				       &bt_ctrl.connect_wq[line]);			interruptible_sleep_on(&bt_ctrl.connect_wq[line]);                }		return bt_ctrl.session[line].connect_status;	}	break;	case SDP_LAYER:	{		int sdp_connection_id = -1;		int return_value;		/* Initiate the connection */		BT_DRIVER(__FUNCTION__ ": Connecting SDP on line %d\n", line);		BT_DATADUMP("Remote BD: ", bd_addr, 6);		if ((sdp_connection_id = sdp_connect_req(bd_addr, line)) >= 0) {		  			/* 			 * If here, we have successfully created an SDP     			 * connection entry and are starting the sequence of 			 * opening an l2cap connection. Allow the bottom     			 * half to process the request and get back to us.   			 */						/* I seem to be having a lot of trouble with the L2CAP			   traffic just not appearing on this side of the link			   while I'm waiting for the SDP conneciton to finish			   up. So let's start a timer to wake us up if things			   don't appear to be working out.			   --gmcnutt			 */			/* fixme -- we probably need a lock on this timer since			   multiple processes could be trying to use it at the			   same time... or maybe use one timer per session.			 */			start_wq_timer(&bt_timer, BT_CON_TIMEOUT, 				       &bt_ctrl.connect_wq[line]);			/* The timeout routine doesn't have a hendle to our 			   session status, so set things up to reflect a 			   timeout error by default. If we really do get a 			   connection then this value _should_ be changed by			   the time we wake up to reflect a good connection.			   --gmcnutt			 */			bt_ctrl.session[line].connect_status = -ETIMEDOUT;			BT_DRIVER(__FUNCTION__ ": Sleep on line %d\n", line);			interruptible_sleep_on(&bt_ctrl.connect_wq[line]);			/* 			 * If the connect_status is >= 0, then the lower			 * stack did not have a problem handling the request.			 * Therefore return the sdp_connection_id            			 */						BT_DRIVER(__FUNCTION__ ": Wake up - line %d\n", line);			if (bt_ctrl.session[line].connect_status >= 0) {				return_value = sdp_connection_id;			} else {				return_value = bt_ctrl.session[line].connect_status;			}		} else {			return_value = sdp_connection_id;		}		return return_value;	}	break;	case L2CAP_TEST_LAYER:	case L2CAP_TEST2_LAYER:	case L2CAP_TEST3_LAYER:		BT_DRIVER(__FUNCTION__ ": Connecting TEST_LAYER (psm %02X) on line %d\n", GET_PSM(con_id), line);		if((retval = test_connect_psmreq(bd_addr, GET_PSM(con_id))) < 0) {			BT_DRIVER(__FUNCTION__ ": Failed\n");			return retval;		}    		return retval;	case TCS_LAYER:		return tcs_connect_req(bd_addr);	default:    		BT_DRIVER(__FUNCTION__ ": PSM %d not supported as client\n",			  GET_PSM(con_id));		break;	}	return -1;}static s32 bt_execute_sdp_request(bt_sdp_request *sdpRequest){	int line = GET_LINE(sdpRequest->conID);	int sdpIndex = GET_SDPINDEX(sdpRequest->conID);	if (SESSIONSTATE(line) != BT_ACTIVE) {		/* SDP connection not active!  Don't issue the request */		BT_DRIVER(__FUNCTION__ ": Line %d does not have an active connection!\n", line);		return -ENOTCONN;	}	BT_DRIVER(__FUNCTION__ ": Line %d SDP index %d\n",		  line, sdpIndex);	if (sdpStartRequest(sdpIndex,			    sdpRequest->sdpCommand,			    sdpRequest->pduPayload,			    sdpRequest->pduLength) < 0)		return -1; /* fixme -- EPERM probably not appropriate */	/* Sleep on this line while the response is going through */	printk(__FUNCTION__ ": Sleep on line %d\n", line);	interruptible_sleep_on(&bt_ctrl.connect_wq[line]);	/* If we're back, there may be data to send back.	   Copy into sdpRequest and return */		if (bt_ctrl.session[line].sdpRequestResponseData) {		BT_DRIVER(__FUNCTION__ ": sdpRequestResponseData 0x%x - copying\n", 			  (int)bt_ctrl.session[line].sdpRequestResponseData);		memcpy(sdpRequest->requestResponse,		       bt_ctrl.session[line].sdpRequestResponseData, 		       bt_ctrl.session[line].sdpRequestResponseDataLength);		sdpRequest->responseLength = 			bt_ctrl.session[line].sdpRequestResponseDataLength;	}	return 0;} voidbt_connect_ind(u32 con_id) {	if (GET_PSM(con_id) == RFCOMM_LAYER)		BT_DRIVER(__FUNCTION__ ": RFCOMM dlci : %d\n", 			  GET_RFCOMMDLCI(con_id));	else		BT_DRIVER(__FUNCTION__ ": PSM %d\n", GET_PSM(con_id));}voidbt_connect_cfm(u32 con_id, s32 status){	u16 psm;	s32 line = GET_LINE(con_id);	psm = GET_PSM(con_id);	if ((line < 0) || (line > BT_NBR_DATAPORTS)) {		D_ERR(__FUNCTION__ ": Invalid line (%d)\n", line);		return;	}		switch (psm) {	case RFCOMM_LAYER:		CHECK_RFCOMM(con_id);		bt_ctrl.session[line].connect_status = status;		BT_DRIVER(__FUNCTION__ ": Line %d [%s]\n",			  line, psmname(psm));		release_wq_timer(&bt_timer);		wake_up_interruptible(&bt_ctrl.connect_wq[line]);		wake_up_interruptible(&bt_ctrl.any_wq);		break;		case SDP_LAYER:                /* Record the connection status for bt_connect() to process. */		bt_ctrl.session[line].connect_status = status;		BT_DRIVER(__FUNCTION__ ": Line %d [%s]\n", line, psmname(psm));		BT_DRIVER(__FUNCTION__ ": Wake up line %d\n", line);		release_wq_timer(&bt_timer);		wake_up_interruptible(&bt_ctrl.connect_wq[line]);		wake_up_interruptible(&bt_ctrl.any_wq);		break;			case TCS_LAYER:		BT_DRIVER(__FUNCTION__ ": [%s]\n", psmname(psm));		break;	default:		D_ERR(__FUNCTION__ ": Unknown layer %d\n", psm);		break;	}}void bt_send_sdp_data_received(u8 line, u8 *data, int len){	/* Check the line for validity */	if (line > BT_NBR_DATAPORTS) {		D_ERR(__FUNCTION__ ": Invalid line (%d)\n", line);		return;	}	/* When data received for this line, we simply attach the	   data (& length) and wake up */		BT_DRIVER(__FUNCTION__ ": data 0x%x len %d\n", (int)data, len);	/* If previous data, deallocate it */	if (bt_ctrl.session[line].sdpRequestResponseData) {		D_WARN(__FUNCTION__ ": sdpRequestResponseData set - deallocate\n");		kfree(bt_ctrl.session[line].sdpRequestResponseData);		bt_ctrl.session[line].sdpRequestResponseData = NULL;		bt_ctrl.session[line].sdpRequestResponseDataLength = 0;	}	bt_ctrl.session[line].sdpRequestResponseData = data;	bt_ctrl.session[line].sdpRequestResponseDataLength = len;	wake_up_interruptible(&bt_ctrl.connect_wq[line]);	return;}

⌨️ 快捷键说明

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