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

📄 l2cap.c

📁 linux系统下的关于蓝牙模块的源代码!十分的经典的程序!
💻 C
📖 第 1 页 / 共 5 页
字号:
	s32 i, retval = 0;	u8 rev_bd[6];	D_RCV(__FUNCTION__ "\n");	PRINTPKT(__FUNCTION__ ": sent to bd ",bd, 6);	/* Check bd_addr */	if (!bd[0] && !bd[1] && !bd[2] && !bd[3] && !bd[4] && !bd[5]) {		D_ERR(__FUNCTION__ ": No BD-addr\n");		return -EINVAL;	}	/* Check PSM */	if ((psm % 2) == 0) {		D_ERR(__FUNCTION__ ": incorrect PSM value\n");		return -EINVAL;	}	if ((psm > MAX_PSM) && (psm < MIN_DYNAMIC_PSM)) {		D_ERR(__FUNCTION__ ": value of PSM preserved\n");		return -EINVAL;	}	if (psm > MAX_DYNAMIC_PSM) {		D_ERR(__FUNCTION__ ": PSM value not valid\n");		return -EINVAL;	}		/* bd is big endian, reverse byte order to little endian */	for (i = 0; i < 6; i++) {		rev_bd[5-i] = bd[i];	}	tmpcon = get_con(rev_bd, ANY_STATE);  	/* Create connection object, hci_handle is set from lp_connect_cfm */	con = create_con(0/* not yet set */, get_cid(), 0/* not yet set */);	/* Check connection */        if (con == NULL) {		D_ERR(__FUNCTION__ ": no connection created\n");		return -ENOMEM;        }	memcpy(con->remote_bd, rev_bd, 6);	print_data("bd", con->remote_bd, 6);	/* we are client */	con->initiator = 1; 	/* we must send and receive a configure req */	con->conf_req_ready=0;	con->conf_rsp_ready=0;	con->psm = psm;	con->flush_timeout = FLUSHTIMEOUT_DEFAULT;	/* is set when receiving a pos lp_connect_cfm */	con->link_up = 0;   	insert_con(con);	/* if this physical bd link exist for another l2cap con, use that! */	if (tmpcon) {		D_STATE(__FUNCTION__ ": hci handle already exist.\n");		con->hci_hdl = tmpcon->hci_hdl;		con->link_up = 1;		ENTERSTATE(con, W4_L2CAP_CONNECT_RSP);		PRINTSTATE(con);	} else {		D_STATE(__FUNCTION__ ": create new baseband link\n");		retval = lp_connect_req(con->remote_bd);		if(retval < 0) {			D_ERR(__FUNCTION__ ": failed (status %d)\n", retval);			return retval;		}		/* wait here until we received a lp_connect_cfm */		l2ca_wait(__FUNCTION__ ": wait baseband", con);				if (con->c_status != RES_SUCCESS) {			D_ERR(__FUNCTION__ ": lp_connect_req failed, no connection (status %d)\n", con->c_status);			retval = -MSGCODE(MSG_LAYER_HCI, con->c_status);			delete_con(con);			return retval;		}	}		/* Now send connect req */	con->c_status = CSTATUS_RTX_TIMEOUT;	/* Leave loop when either status failed or success */	while (con->c_status == CSTATUS_RTX_TIMEOUT) {		/* baseband is up, now initiate send connect req */		retval = l2cap_connect_req(con, con->psm);		if(retval < 0) {			D_ERR(__FUNCTION__ ": failed (status %d)\n", retval);		}		/* wait until we received a response or after timeout */		l2ca_wait(__FUNCTION__ ": wait rsp", con);	}	if (con->c_status == CSTATUS_MAX_NO_RTX && !retval) {		retval = -MSGCODE(MSG_LAYER_L2CAP, L2CAP_RTX_TIMEOUT);	}	return retval;}/* params determines how we would like to receive data */s32 l2ca_config_req(l2cap_con *con, u16 in_mtu, flow *outflow,                 u16 flush_timeout, u16 link_to){  	if (PARANOIA_CHECKCON(con)) {		D_ERR(__FUNCTION__ ": Paranoia check failed\n");		return -EINVAL;	}	D_STATE("l2ca_config_req remote cid %d, in_mtu %d\n", 		con->remote_cid, in_mtu);	/* should already be in CONFIG state */	if (con->current_state == CONFIG) {  		/* local mtu is set in l2cap_config_req */                		con->conf_req_sent = 1;		return l2cap_config_req(con, in_mtu, outflow, 					flush_timeout, link_to);  	} else if (con->current_state == CLOSED) {		l2ca_config_cfm(con, CONF_REJ);		return -MSGCODE(MSG_LAYER_L2CAP, L2CAP_NO_CONNECTION);	} else if (con->current_state == OPEN) {		DSYS("l2ca_config_req: state OPEN, reconfiguration !\n");		/* FIXME - 		   Is data automatically suspended while reconfiguring  ?		*/		ENTERSTATE(con, CONFIG);		PRINTSTATE(con);				/* local mtu is set in l2cap_config_req */		con->conf_req_ready = FALSE;		con->conf_rsp_ready = FALSE;		return l2cap_config_req(con, in_mtu, outflow, 					flush_timeout, link_to);  	} else {		D_ERR(__FUNCTION__ ": invalid state\n");		PRINTSTATE(con);		return -MSGCODE(MSG_LAYER_L2CAP, L2CAP_INVALID_STATE);	}}s32 l2ca_disconnect_req(l2cap_con *con){	s32 retval = 0;	u16 tmp_hdl = con->hci_hdl;	if (PARANOIA_CHECKCON(con)) {		D_ERR(__FUNCTION__ ": Paranoia check failed\n");		return -EINVAL;	}	D_STATE(__FUNCTION__ ": remote cid : %d\n", con->remote_cid);	if (con->current_state == OPEN || con->current_state == CONFIG) {		ENTERSTATE(con, W4_L2CAP_DISCONNECT_RSP);		PRINTSTATE(con);		do {			retval = l2cap_disconnect_req(con);			if(retval < 0) {				/* This will result in a timeout and we need to try again				   as the error is a result of insufficent space in our				   memorypool and we try again after a timeout */				D_ERR(__FUNCTION__ ": Failed (status %d)\n", retval);			}						l2ca_wait(__FUNCTION__, con);			PRINTSTATE(con);					} while (con->c_status == CSTATUS_RTX_TIMEOUT);	} else {		D_ERR(__FUNCTION__ ": Invalid state!\n");		PRINTSTATE(con);		return -MSGCODE(MSG_LAYER_L2CAP, L2CAP_INVALID_STATE);    	}		if(con->c_status != CSTATUS_MAX_NO_RTX) {		if (con->current_state == CLOSED) {				/* remove l2cap connection */			delete_con(con);		} else {			/* FIXME: If we reach here, should we delete the connection? */			D_ERR(__FUNCTION__ ": Failed (Connection not closed)");			PRINTSTATE(con);			retval = -MSGCODE(MSG_LAYER_L2CAP, L2CAP_FAILED);		}	}			/* fixme -- if we want to keep baseband connection we must 	   leave the l2cap connection which holds the hci handle 	   simply just clear l2cap params but keep hci handle ! */		if (count_con(tmp_hdl) == 0) {		DSYS("l2ca_disconnect_req : (C) no more l2cap cons\n");		DSYS("Shutdown baseband\n");		lp_disconnect(tmp_hdl);	}	return retval;}/* Response from upper layer to the indication of a channel to a remote    device */s32 l2ca_connect_rsp(l2cap_con* con, u16 response, u16 status){	s32 result;	D_STATE(__FUNCTION__ "\n");	if (PARANOIA_CHECKCON(con)) {		D_ERR(__FUNCTION__ ": Paranoia check failed\n");		return -EINVAL;	}	/* optionally send l2cap_connect_rsp_pnd() */  	if (con->current_state != W4_L2CA_CONNECT_RSP) {		D_ERR(__FUNCTION__ ": invalid state \n");		PRINTSTATE(con);		return -1;	}  	result = l2cap_connect_rsp(con, response, status);		if (response == RES_SUCCESS) {  		ENTERSTATE(con, CONFIG);		PRINTSTATE(con);	} else if (response == RES_PENDING) {		/* remain in same state */	} else if (response >= RES_PSMNEG) {		/* 'l2ca_connect_rsp_neg()' */		ENTERSTATE(con, CLOSED);		PRINTSTATE(con);		/* remove connection */		delete_con(con);	}  	return result;}s32 l2ca_config_rsp(l2cap_con* con, u32 out_mtu, flow *in_flow, s32 result){	s32 ret_val = -1;	if (PARANOIA_CHECKCON(con)) {		D_ERR(__FUNCTION__ ": Paranoia check failed\n");		return -EINVAL;	}	D_STATE(__FUNCTION__ ": remote cid %d remote mtu %d\n", 		con->remote_cid, con->remote_mtu);	if (con->current_state != CONFIG) {		D_ERR(__FUNCTION__": invalid state\n");		PRINTSTATE(con);		return -1;	}	if (result == CONF_SUCCESS) {		/* upper layers responded OK */		con->conf_rsp_ready = TRUE;		ret_val = l2cap_config_rsp(con, out_mtu, in_flow, result);		/* check if we have sent a configure request yet */		if (con->conf_req_ready && !con->remote_flags) {			/* all done, proceed to OPEN */			ENTERSTATE(con, OPEN);			PRINTSTATE(con);			DSYS("l2cap channel (%d,%d) [%s] connected\n", 			     con->local_cid, con->remote_cid, 			     psm2str(con->psm));			/* reset variable */			con->conf_req_sent = 0;			/* notify upper layers that we are opened */			l2ca_config_cfm(con, RES_SUCCESS);		} else {			D_STATE(__FUNCTION__ ": Conf not done or flags set\n");		}	} else {		D_STATE("We don't accepted remote options\n");		ret_val = l2cap_config_rsp(con, out_mtu, in_flow, result);	}	return ret_val;}s32 l2ca_disconnect_rsp(l2cap_con* con){	s32 result = -1;	D_STATE(__FUNCTION__ "\n");	if (PARANOIA_CHECKCON(con)) {		D_ERR(__FUNCTION__ ": Paranoia check failed\n");		return -EINVAL;	}	SHOW_CON("disconnecting : ", con);	if (con->current_state == W4_L2CA_DISCONNECT_RSP) {		/* if we got a link down unexpectedly we cannot send 		   back a response, send nothing... */		if (con->link_up)			result = l2cap_disconnect_rsp(con);		else {			/* tell upper layers that disconnection was 			   'successful' */			result=0;			D_STATE("baseband link down, cannot send rsp\n");		}				ENTERSTATE(con, CLOSED);				PRINTSTATE(con); 		DSYS("l2cap channel (%d,%d) [%s] disconnected\n", 		     con->local_cid, con->remote_cid, psm2str(con->psm));		if (count_con(con->hci_hdl) > 1) {			delete_con(con);     		}	} else {		D_ERR(__FUNCTION__ ": invalid state !\n\n");		PRINTSTATE(con);	}	return result;}/* only supports one call at a time */voidl2ca_wait(const char *str, l2cap_con *con){	if (!(con->c_flags & FLAG_WAKEMEUP)) {		if (con->c_flags & FLAG_DONTSLEEP) {			printk("l2ca_wait : don't sleep flag set\n");			return;		}		con->c_flags |= FLAG_WAKEMEUP;		printk("%s, sleep on wq 0x%x\n", str, (int)&con->wq);		interruptible_sleep_on(&con->wq);		printk("%s, woke up !\n", str);	} else {		printk("%s, wq already in use\n", str);	}}void l2ca_wakeup(const char *str, l2cap_con *con){	if (con->c_flags & FLAG_WAKEMEUP) {		if (con->c_flags & FLAG_DONTSLEEP) {			printk("l2ca_wakeup : don't sleep flag set\n");			con->c_flags &= ~FLAG_DONTSLEEP;			return;		}		con->c_flags &= ~FLAG_WAKEMEUP;		printk("%s, wake up wq 0x%x\n", str,(int)&con->wq);		wake_up_interruptible(&con->wq);	} else {		printk("%s, wake up flag not set\n", str);	}}/*******************************************************************//* (E5) Timer events *//********************/#ifdef CONFIG_BLUETOOTH_L2CAP_USE_TIMERSvoid l2ca_timeoutind(l2cap_con *con){	DSYS("l2ca_timeoutind\n");	con->c_status = CSTATUS_RTX_TIMEOUT;		l2ca_wakeup("l2ca_timeoutind ", con);}#ifdef __KERNEL__voidl2cap_rtx_timeout(unsigned long ptr){	l2cap_con *con = (l2cap_con*)ptr;#else /* usermode timer */voidl2cap_rtx_timeout(void){	l2cap_con *con = timeout_con;	if (timer_cancelled) {		D_TIM("RTX timer already cancelled\n");		return;	}#endif	/* do some paranoia checks */	if (PARANOIA_CHECKCON(con)) {		D_ERR(__FUNCTION__ ": Paranoia check failed\n");		return;	}	D_TIM(__FUNCTION__ ": current no rtx : %d\n", con->timer.rtx_no);	con->timer.rtx_inuse = 0;	if (con->timer.rtx_no == MAX_NO_RTX) {		con->c_status = CSTATUS_MAX_NO_RTX;		D_TIM("Connection unresponsive\n");		show_con("Connection unresponsive\n", con);		con->c_result = MSGCODE(MSG_LAYER_L2CAP, 					L2CAP_CON_UNRESPONSIVE);		l2ca_wakeup("rtx_timeout", con);		/* reset rtx counter */		con->timer.rtx_no = 0;		if (con->timer.rtx_action == RTX_ACTION_START_ERTX) {			/* start ertx timer */			D_TIM("Starting ERTX\n");			start_ertx(con, ERTX_TIMEOUT);		} else if (con->timer.rtx_action == RTX_ACTION_TERMINATE) {			D_TIM("Removing connection\n");			l2ca_disconnect_ind(con);			ENTERSTATE(con, CLOSED);			delete_con(con);		}	} else {		con->timer.rtx_no++;		l2ca_timeoutind(con);		}#ifndef __KERNEL__	timeout_con = NULL;#endif}voidl2cap_ertx_timeout(unsigned long ptr){	l2cap_con *con;	D_TIM(__FUNCTION__ "\n");	con = (l2cap_con*)ptr;	/* do paranoia check */	if (PARANOIA_CHECKCON(con)) {		D_ERR(__FUNCTION__ ": Paranoia check failed\n");		return;	}	if (con->timer.ertx_action == ERTX_ACTION_TERMINATE) {		D_TIM("Removing connection\n");		l2ca_disconnect_ind(con);		ENTERSTATE(con, CLOSED);		delete_con(con);	} else if (con->timer.ertx_action == ERTX_ACTION_DISCONNECT) {				D_TIM("Disconnect connection\n");		/* set dont sleep flag so that we wont do sleep 		   when not running in usermode context */		con->c_flags |= FLAG_DONTSLEEP;		ENTERSTATE(con, CONFIG); /* CERT HACK ! */		l2ca_disconnect_req(con);	}}#endif /* CONFIG_BLUETOOTH_L2CAP_USE_TIMERS *//*******************************************************************//*-------------------------- ACTIONS ------------------------------*//*******************************************************************//*    Actions are partitioned into five categories:    1. l2cap to lower layers    2. l2cap to l2cap signalling    3. l2cap to l2cap data transmission    4. l2cap to upper layers    5. setting timers     *//*******************************************************************//* (A1) l2cap to lower layers *//*****************************//* FIXME - lp_qos_req() */

⌨️ 快捷键说明

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