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

📄 l2cap.c

📁 blue tooth 核心协议栈在linux上的实现
💻 C
📖 第 1 页 / 共 5 页
字号:
	return hci_send_data(tx);}/* only specify inparam if it differs from default value */s32 l2cap_config_req(l2cap_con *con, u16 in_mtu, flow *outflow,		 u16 flush_timeout, u16 link_timeout){	bt_tx_buf *tx; 	l2cap_tx_buf *l2cap_buf;  /* Entire l2cap frame + lower layer hdrs */	sig_cmd *cmd;	sig_confreq *req;	u16 payload_len;	s32 opt_len = 0;	struct l2cap_option *opt;	D_XMIT(__FUNCTION__ ": rcid :%d\n", con->remote_cid);	/******************************************************************/	/* | len2 | CID2 || code1 | id1 || destcid2 | flags1 | options? | */	/* -------------------------------------------------------------- */	/* | l2cap hdr   || sig cmd hdr ||             data             | */	/******************************************************************/	D_STATE(__FUNCTION__ ": inmtu : %d, local mtu : %d\n",		in_mtu, con->local_mtu);	if (in_mtu != 0) {		DSYS("Setting local mtu to %d\n", in_mtu);		con->local_mtu = in_mtu;		opt_len += 4;	}	if (flush_timeout != 0) {		/* We inform peer about our flush timeout */				/* FIXME -- who controls this ? Upper layer ? */		opt_len +=4;	}		if (outflow != NULL) {		/* We inform peer about our QOS settings */		opt_len += sizeof *outflow + 2; /* include type/len */	}		payload_len = SIGCMD_HDRSIZE + CONF_REQSIZE + opt_len;   	tx = subscribe_bt_buf(sizeof(l2cap_tx_buf) + L2CAP_HDRSIZE+payload_len);	if (!tx) {		D_ERR(__FUNCTION__ ": didn't get a valid tx buf\n");		return -ENOMEM;	}	l2cap_buf = (l2cap_tx_buf *)(tx->data);  	cmd = (sig_cmd*)(l2cap_buf->frame + L2CAP_HDRSIZE);	req = (sig_confreq*)(l2cap_buf->frame + L2CAP_HDRSIZE + SIGCMD_HDRSIZE);		if (opt_len > 0) {		/* if the negotiated mtu differs from the current, send it */          		opt = (struct l2cap_option*)(l2cap_buf->frame+L2CAP_HDRSIZE + 			SIGCMD_HDRSIZE + CONF_REQSIZE); 		if (in_mtu != 0) {			DSYS("Sending in_mtu %d\n", in_mtu);			opt->type = OPT_MTU;			opt->len = 2;			*(opt->option_data) = (u8)(in_mtu & 0x00ff);			*(opt->option_data+1) = (u8)(in_mtu >> 8) & 0x00ff;				/* forward pointer for other options */			opt = (struct l2cap_option*)((char *)opt + 4);		}				if (flush_timeout != 0) {			DSYS("Sending flush_timeout %d\n", flush_timeout);			opt->type = OPT_FLUSH;			opt->len = 2;			*(opt->option_data) = (u8)(flush_timeout & 0x00ff);			*(opt->option_data+1) = (u8)(flush_timeout >> 8) &0x00ff;			/* forward pointer for other options */			opt = (struct l2cap_option*)((char *)opt + 4);		}				if (outflow != NULL) { 			DSYS("Sending conf req outflow\n");			print_flow(outflow);			opt->type = OPT_QOS;			opt->len = sizeof *outflow;			memcpy((char*)opt+2, outflow, sizeof *outflow);		}	}	/* Request header */	req->dst_cid = cpu_to_le16(con->remote_cid); /* Sending end */	req->flags = 0; /* Negotiate same as remote */	/* Signalling header */	cmd->code = SIG_CONFREQ;        /* Don't increment ID if retransmission */        if (con->timer.rtx_no == 0)                cmd->id = set_id(con); /* Sets sig_id_sent in l2cap_con */        else                DSYS("RTX, use same ID\n");	/* fixme -- wrong len field should be 2 more */	cmd->len = cpu_to_le16(CONF_REQSIZE + opt_len);	SET_L2CAP_HDR(l2cap_buf->frame, payload_len, CIDSIG);	/* pb_flag is set from hci_send_data */	tx->hci_hdl = con->hci_hdl;	tx->bc_flag = NO_BROADCAST;	tx->cur_len = L2CAP_HDRSIZE + payload_len; /* Increased when lower						      layers add header data */	opt = (struct l2cap_option*)(l2cap_buf->frame+L2CAP_HDRSIZE + 				     SIGCMD_HDRSIZE + CONF_REQSIZE);		print_data("l2cap options: ", (char*)opt , opt_len);#ifdef CONFIG_BLUETOOTH_L2CAP_USE_TIMERS	/* start retransmission timer */	start_rtx(con, RTX_TIMEOUT, RTX_ACTION_START_ERTX);#endif	return hci_send_data(tx);}s32 l2cap_disconnect_req(l2cap_con *con){	bt_tx_buf *tx; 	l2cap_tx_buf *l2cap_buf;  /* Entire l2cap frame + lower layer hdrs */	sig_cmd *cmd;	sig_discreq *req;	u16 payload_len; 	D_XMIT(__FUNCTION__ ": rcid %d\n", con->remote_cid);	payload_len = SIGCMD_HDRSIZE + DISC_REQSIZE;  	tx = subscribe_bt_buf(sizeof(l2cap_tx_buf) + L2CAP_HDRSIZE+payload_len);	if (!tx) {		D_ERR(__FUNCTION__ ": didn't get a valid tx buf\n");		return -ENOMEM;	}	l2cap_buf = (l2cap_tx_buf *)(tx->data);	cmd = (sig_cmd*)(l2cap_buf->frame + L2CAP_HDRSIZE);	req = (sig_discreq*)(l2cap_buf->frame + L2CAP_HDRSIZE + SIGCMD_HDRSIZE);	/* Now fill in header fields */  	req->dst_cid = cpu_to_le16(con->remote_cid);	req->src_cid = cpu_to_le16(con->local_cid);	cmd->code = SIG_DISCREQ;                /* Don't increment ID if retransmission */        if (con->timer.rtx_no == 0)                cmd->id = set_id(con); /* Sets sig_id_sent in l2cap_con */        else                DSYS("RTX, use same ID\n");        	cmd->len = cpu_to_le16(DISC_REQSIZE);	SET_L2CAP_HDR(l2cap_buf->frame, payload_len, CIDSIG);	tx->hci_hdl = con->hci_hdl;	tx->bc_flag = NO_BROADCAST;	tx->cur_len = L2CAP_HDRSIZE + payload_len;#ifdef CONFIG_BLUETOOTH_L2CAP_USE_TIMERS	/* start retransmission timer */	start_rtx(con, RTX_TIMEOUT, RTX_ACTION_TERMINATE);#endif	return hci_send_data(tx);}s32 l2cap_echo_req(l2cap_con *con, u8 *opt_data, u16 opt_len){	bt_tx_buf *tx; 	l2cap_tx_buf *l2cap_buf;  /* Entire l2cap frame + lower layer hdrs */	sig_cmd *cmd;	sig_echo_pkt *req;	u16 payload_len;	u16 hci_hdl = con->hci_hdl;	payload_len = SIGCMD_HDRSIZE + sizeof(sig_echo_pkt) + opt_len;	D_XMIT(__FUNCTION__ "\n");	tx = subscribe_bt_buf(sizeof(l2cap_tx_buf) + L2CAP_HDRSIZE+payload_len);	if (!tx) {		D_ERR(__FUNCTION__ ": didn't get a valid tx buf\n");		return -ENOMEM;	}	l2cap_buf = (l2cap_tx_buf *)(tx->data);  	cmd = (sig_cmd*)(l2cap_buf->frame + L2CAP_HDRSIZE);	req = (sig_echo_pkt*)(l2cap_buf->frame + L2CAP_HDRSIZE +SIGCMD_HDRSIZE);    	/* Now fill in header fields */	if (opt_len)		memcpy(req->data, opt_data, opt_len);  	cmd->code = SIG_ECHOREQ;	cmd->id = get_id();  	cmd->len = cpu_to_le16(opt_len);	SET_L2CAP_HDR(l2cap_buf->frame, payload_len, CIDSIG);	/* pb_flag is set from hci_send_data */	tx->hci_hdl = hci_hdl;	tx->bc_flag = NO_BROADCAST;        /* Increased when lower layers add header data */	tx->cur_len = L2CAP_HDRSIZE + payload_len;#ifdef CONFIG_BLUETOOTH_L2CAP_USE_TIMERS	start_rtx(con, RTX_TIMEOUT, RTX_ACTION_DISCONNECT);#endif        return hci_send_data(tx);}s32 l2cap_echo_rsp(s32 hci_hdl, s32 id, u8 *opt_data, u16 opt_len){	bt_tx_buf *tx; 	l2cap_tx_buf *l2cap_buf;  /* Entire l2cap frame + lower layer hdrs */	sig_cmd *cmd;	sig_echo_pkt *rsp;	u16 payload_len;	D_XMIT(__FUNCTION__ "\n");	payload_len = SIGCMD_HDRSIZE + opt_len;	tx = subscribe_bt_buf(sizeof(l2cap_tx_buf) + L2CAP_HDRSIZE+payload_len);	if (!tx) {		D_ERR(__FUNCTION__ ": didn't get a valid tx buf\n");		return -ENOMEM;	} 	l2cap_buf = (l2cap_tx_buf *)(tx->data);	cmd = (sig_cmd*)(l2cap_buf->frame + L2CAP_HDRSIZE);	rsp = (sig_echo_pkt*)(l2cap_buf->frame + L2CAP_HDRSIZE +SIGCMD_HDRSIZE);    	/* Now fill in header fields */	if (opt_len)		memcpy(rsp->data, opt_data, opt_len);  	cmd->code = SIG_ECHORSP;	cmd->id = id;	cmd->len = cpu_to_le16(opt_len);	SET_L2CAP_HDR(l2cap_buf->frame, payload_len, CIDSIG);	/* pb_flag is set from hci_send_data */	tx->hci_hdl = hci_hdl;	tx->bc_flag = NO_BROADCAST;	tx->cur_len = L2CAP_HDRSIZE + payload_len; /* Increased as lower layers						      add header data */  	return hci_send_data(tx);}s32l2cap_info_req(l2cap_con *con, u16 info_type){	bt_tx_buf *tx; 	l2cap_tx_buf *l2cap_buf;  /* Entire l2cap frame + lower layer hdrs */	sig_cmd *cmd;	sig_info_req *req;	s32 payload_len;	u16 hci_hdl = con->hci_hdl;	payload_len = SIGCMD_HDRSIZE + sizeof(sig_info_req);	D_XMIT(__FUNCTION__ "\n");	tx = subscribe_bt_buf(sizeof(l2cap_tx_buf) + L2CAP_HDRSIZE+payload_len);	if (!tx) {		D_ERR(__FUNCTION__ ": didn't get a valid tx buf\n");		return -ENOMEM;	}	l2cap_buf = (l2cap_tx_buf *)(tx->data);  	cmd = (sig_cmd*)(l2cap_buf->frame + L2CAP_HDRSIZE);	req = (sig_info_req*)(l2cap_buf->frame + L2CAP_HDRSIZE +SIGCMD_HDRSIZE);	req->type = cpu_to_le16(info_type);    	cmd->code = SIG_INFOREQ;	cmd->id = get_id();	cmd->len = cpu_to_le16(sizeof(sig_info_req));	SET_L2CAP_HDR(l2cap_buf->frame, payload_len, CIDSIG);	/* pb_flag is set from hci_send_data */	tx->hci_hdl = hci_hdl;	tx->bc_flag = NO_BROADCAST;	tx->cur_len = L2CAP_HDRSIZE + payload_len; /* Increased when lower						      layers add header data */#ifdef CONFIG_BLUETOOTH_L2CAP_USE_TIMERS	start_rtx(con, RTX_TIMEOUT, RTX_ACTION_TERMINATE);#endif	return hci_send_data(tx);} s32 l2cap_info_rsp(s32 hci_hdl, s32 id, u16 info_type, u8 *info_data, 	       s32 info_len, s32 result){	bt_tx_buf *tx; 	l2cap_tx_buf *l2cap_buf;  /* Entire l2cap frame + lower layer hdrs */	sig_cmd *cmd;	sig_info_rsp *rsp;	s32 payload_len;	D_XMIT(__FUNCTION__ "\n");	payload_len = SIGCMD_HDRSIZE + sizeof(sig_info_rsp) + info_len;	tx = subscribe_bt_buf(sizeof(l2cap_tx_buf) + L2CAP_HDRSIZE + payload_len);	if (!tx) {		D_ERR(__FUNCTION__ ": didn't get a valid tx buf\n");		return -ENOMEM;	} 	l2cap_buf = (l2cap_tx_buf *)(tx->data);	cmd = (sig_cmd*)(l2cap_buf->frame + L2CAP_HDRSIZE);	rsp = (sig_info_rsp*)(l2cap_buf->frame + L2CAP_HDRSIZE +SIGCMD_HDRSIZE);	rsp->type = cpu_to_le16(info_type);	rsp->result = cpu_to_le16(result);		/* Now fill in header fields */	if (info_len) {		memcpy(rsp->infodata, info_data, info_len);	}	cmd->code = SIG_INFORSP;	cmd->id = id;	cmd->len = cpu_to_le16(sizeof(sig_info_rsp) + info_len);	SET_L2CAP_HDR(l2cap_buf->frame, payload_len, CIDSIG);	/* pb_flag is set from hci_send_data */	tx->hci_hdl = hci_hdl;	tx->bc_flag = NO_BROADCAST;	tx->cur_len = L2CAP_HDRSIZE + payload_len; /* Increased as lower layers						      add header data */  	return hci_send_data(tx);}s32 l2cap_cmdrej(s32 hci_hdl, u8 reason, u8 *opt_data, s32 opt_len){	bt_tx_buf *tx; 	l2cap_tx_buf *l2cap_buf;  /* Entire l2cap frame + lower layer hdrs */	sig_cmd *cmd;	sig_cmdreject *cmdrej;	u16 payload_len;	payload_len = SIGCMD_HDRSIZE + sizeof(sig_cmdreject) + opt_len;	D_XMIT(__FUNCTION__ ": %s\n", cmdrej_reason[reason]);	tx = subscribe_bt_buf(sizeof(l2cap_tx_buf) + L2CAP_HDRSIZE+payload_len);	if (!tx) {		D_ERR(__FUNCTION__ ": didn't get a valid tx buf\n");		return -ENOMEM;	}  	l2cap_buf = (l2cap_tx_buf *)(tx->data);	cmd = (sig_cmd*)(l2cap_buf->frame + L2CAP_HDRSIZE);	cmdrej = (sig_cmdreject*)(l2cap_buf->frame				  + L2CAP_HDRSIZE + SIGCMD_HDRSIZE);    	/* Now fill in header fields */	if (opt_len)		memcpy(cmdrej->data, opt_data, opt_len);  	cmd->code = SIG_CMDREJECT;	cmd->id = get_id();	cmd->len = cpu_to_le16(sizeof(sig_cmdreject) + opt_len);	/* FIXME: set the reason parameter */	/* Ok. Does this work? (gjm) */	cmdrej->reason = cpu_to_le16((u16)reason);	SET_L2CAP_HDR(l2cap_buf->frame, payload_len, CIDSIG);	/* pb_flag is set from hci_send_data */	tx->hci_hdl = hci_hdl;	tx->bc_flag = NO_BROADCAST;	tx->cur_len = L2CAP_HDRSIZE + payload_len; /* Increased when lower						      layers add header data */	return hci_send_data(tx);}/****************************//* l2cap response functions *//****************************/s32 l2cap_connect_rsp(l2cap_con* con, u16 response, u16 status){	bt_tx_buf *tx; 	l2cap_tx_buf *l2cap_buf;  /* Entire l2cap frame + lower layer hdrs */	sig_cmd *cmd;	sig_conrsp *rsp;	u16 payload_len;  	D_XMIT(__FUNCTION__ ": rcid:%d lcid:%d result:%d status:%d \n",	       con->remote_cid, con->local_cid, response, status);	payload_len = SIGCMD_HDRSIZE + CON_RSPSIZE;  	tx = subscribe_bt_buf(sizeof(l2cap_tx_buf) + L2CAP_HDRSIZE+payload_len);	if (!tx) {		D_ERR(__FUNCTION__ ": didn't get a valid tx buf\n");		return -ENOMEM;	}	l2cap_buf = (l2cap_tx_buf *)(tx->data);	cmd = (sig_cmd*)(l2cap_buf->frame + L2CAP_HDRSIZE);	rsp = (sig_conrsp*)(l2cap_buf->frame + L2CAP_HDRSIZE + SIGCMD_HDRSIZE);  	/* Now fill in header fields */	rsp->dst_cid = cpu_to_le16(con->local_cid); /* sending end */	rsp->src_cid = cpu_to_le16(con->remote_cid); /* receiving end */	if ((rsp->result = cpu_to_le16(response)) == RES_PENDING)		rsp->status = cpu_to_le16(status);	else {		rsp->status = cpu_to_le16(STAT_NOINFO);	}		cmd->code = SIG_CONRSP;	cmd->id = con->sig_id_rcv; /* Send back same id as received on req */	cmd->len = cpu_to_le16(CON_RSPSIZE);	SET_L2CAP_HDR(l2cap_buf->frame, payload_len, CIDSIG);	/* pb_flag is set from hci_send_data */	tx->hci_hdl = con->hci_hdl;	tx->bc_flag = NO_BROADCAST;	tx->cur_len = L2CAP_HDRSIZE + payload_len; /* Increased when lower						      layers add header data */	return hci_send_data(tx);  } s32 l2cap_config_rsp(l2cap_con* con, u32 out_mtu, flow *in_flow, s32 result){	bt_tx_buf *tx; 	l2cap_tx_buf *l2cap_buf;  /* Entire l2cap frame + lower layer hdrs */	sig_cmd *cmd;	sig_confrsp *rsp;	u16 payload_len;	int opt_len = 0;	struct l2cap_option *opt;	D_XMIT(__FUNCTION__ ": rcid : %d, out_mtu: %d \n", 	       con->remote_cid, out_mtu);	/* If negative, the accepted options are sent back */	if (result != RES_SUCCESS) {		DSYS("Neg config rsp !\n");		if (out_mtu != 0) {			con->remote_mtu = out_mtu;			opt_len += 4;		}		if (in_flow != NULL) {			/* The accepted settings for incoming traffic */			opt_len += sizeof *in_flow;		}	}	payload_len = SIGCMD_HDRSIZE + CONF_RSPSIZE + opt_len;	tx = subscribe_bt_buf(sizeof(l2cap_tx_buf) + 			      L2CAP_HDRSIZE + payload_len);	if (!tx) {		D_ERR(__FUNCTION__ ": didn't get a valid tx buf\n");		return -ENOMEM;	}	l2cap_buf = (l2cap_tx_buf *)(tx->data);	cmd = (sig_cmd*)(l2cap_buf->frame + L2CAP_HDRSIZE);	rsp = (sig_confrsp*)(l2cap_buf->frame + L2CAP_HDRSIZE + 			     SIGCMD_HDRSIZE);	/* Now fill in header fields */  	rsp->src_cid = cpu_to_le16(con->remote_cid);	rsp->flags = con->remote_flags;	rsp->result = cpu_to_le16((u16)result);	/* Include unaccepted options if any */	if (opt_len) {		opt = (struct l2cap_option*)((u8*)rsp + CONF_RSPSIZE);		if (out_mtu != 0) {			DSYS("Sending out_mtu %d\n", out_mtu);			opt->type = OPT_MTU;			opt->len = 2;			opt->option_data[0] = (u8)(out_

⌨️ 快捷键说明

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