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

📄 rfcomm.c

📁 blue tooth protocol stack source code
💻 C
📖 第 1 页 / 共 5 页
字号:
					      mcc_short_pkt->h.length.len,					      MCC_RSP);			}		}		break;    	case FCON:  /* Flow control on command */		D_CTRL(FNC"Received Flow control on command\n");		if (mcc_short_pkt->h.type.cr == MCC_CMD) {			rfcomm->dlci[0].state = CONNECTED;			rfcomm_fcon_msg(rfcomm, MCC_RSP);		}		break;    	case FCOFF:  /* Flow control off command */		D_CTRL(FNC"Received Flow control off command\n");		if (mcc_short_pkt->h.type.cr == MCC_CMD) {			rfcomm->dlci[0].state = FLOW_STOPPED;			rfcomm_fcoff_msg(rfcomm, MCC_RSP);		}		break;    	case MSC:  /* Modem status command */	{		u8 dlci;		u8 v24_sigs;				dlci = (mcc_short_pkt->value[0]) >> 2;		v24_sigs = mcc_short_pkt->value[1];		if (rfcomm->dlci[dlci].state == DISCONNECTED) {			send_dm(rfcomm, dlci);			break;		}		if (mcc_short_pkt->h.type.cr == MCC_CMD) {			D_CTRL(FNC"Received Modem status command\n");			if (v24_sigs & 2) {				D_CTRL(FNC"Device unable to accept frames\n");				rfcomm->dlci[dlci].state = FLOW_STOPPED;			} else {				rfcomm->dlci[dlci].state = CONNECTED;				D_CTRL(FNC"Flow ON, dlci %d\n", dlci);  			}			rfcomm_msc_msg(rfcomm, v24_sigs, MCC_RSP, dlci);						if (!(rfcomm->dlci[dlci].initiated) && !(rfcomm->dlci[dlci].initiator)) {				rfcomm_msc_msg(rfcomm, EA | RTR | RTC | DV,					       MCC_CMD, dlci);				rfcomm->dlci[dlci].initiated = TRUE;			}		} else {			D_CTRL(FNC"Received Modem status response\n");			if (v24_sigs & 2) {				D_CTRL(FNC"Flow stop accepted\n");			}		}		break;	}    	case RPN:  /* Remote port negotiation command */	{		u8 tmp_dlci;		tmp_dlci = (mcc_short_pkt->value[0]) >> 2;				if (mcc_short_pkt->h.type.cr == MCC_CMD) {			if (mcc_short_pkt->h.length.len == 1) {				D_CTRL(FNC"Received Remote port negotiation command\n");				rfcomm_rpn_msg(rfcomm, MCC_RSP, tmp_dlci, 0);			} else {				/* Accept the other sides settings (accept all				   for now) */				D_CTRL(FNC"Received Remote port negotiation respons\n");				memcpy(&rpn_val, &mcc_short_pkt->value[1], 8);				rfcomm_rpn_msg(rfcomm, MCC_RSP, tmp_dlci, 0);				/* Zero the parametermask after respons */				memset(&rpn_val.pm, 0, 2);			}		}			break;	}	case RLS: /* Remote line status */	{		u8 tmp_dlci;		u8 err_code;					D_CTRL(FNC"Received Remote line status\n");		if (mcc_short_pkt->h.type.cr == MCC_CMD) {			tmp_dlci = mcc_short_pkt->value[0] >> 2;			err_code = mcc_short_pkt->value[1];					rfcomm_rls_msg(rfcomm, MCC_RSP, tmp_dlci, err_code);		}		break;	}	case PN:  /* DLC parameter negotiation */	{		pn_msg *pn_pkt;		D_CTRL(FNC"Received DLC parameter negotiation, PN\n");		if (longpkt) {			/* If a long length field is used, then move the			   payload pointer one byte ahead */			data++;		}  		pn_pkt = (pn_msg*) data;		if (pn_pkt->mcc_s_head.type.cr == MCC_CMD) {			u8 tmp_dlci;			u16 frame_size;			u8 credit, nbrof_credits;						/* If the incoming messages is a command we send			   back a response */			tmp_dlci = pn_pkt->dlci;			frame_size = le16_to_cpuu(&pn_pkt->frame_size);			frame_size = MIN(frame_size, rfcomm->l2cap->local_mtu - RFCOMM_MAX_HDR_SIZE);			credit = pn_pkt->credit_flow;			nbrof_credits = pn_pkt->credits;			if (credit) {				DSYS(FNC"Using credit flow control, initiating credits are %d on dlci %d\n", nbrof_credits, tmp_dlci);				rfcomm->credit_flow = TRUE;				rfcomm->dlci[tmp_dlci].local_credits = nbrof_credits;				D_CTRL(FNC"Local credits:%d\n", rfcomm->dlci[tmp_dlci].local_credits); 				rfcomm->dlci[tmp_dlci].remote_credits = START_CREDITS;				D_CTRL(FNC"Remote credits: %d\n",rfcomm->dlci[tmp_dlci].remote_credits);				send_pn_msg(rfcomm, pn_pkt->prior, frame_size,					    credit ^ 1, START_CREDITS, 					    tmp_dlci, MCC_RSP);			} else {				send_pn_msg(rfcomm, pn_pkt->prior, frame_size,					    0, 0, tmp_dlci, MCC_RSP);			}			rfcomm->dlci[tmp_dlci].mtu = frame_size;			D_CTRL(FNC"process_mcc : mtu set to %d\n", 			      rfcomm->dlci[tmp_dlci].mtu);		} else {			u8 tmp_dlci;			tmp_dlci = pn_pkt->dlci;			D_CTRL(FNC"received PN response with:\n");			D_CTRL(FNC"Frame size:%d\n", le16_to_cpuu(&pn_pkt->frame_size));			D_CTRL(FNC"credit_flow:%d\n", pn_pkt->credit_flow);			D_CTRL(FNC"credits:%d\n", pn_pkt->credits);						rfcomm->dlci[tmp_dlci].mtu  = le16_to_cpuu(&pn_pkt->frame_size);						if (pn_pkt->credit_flow == 0xe) {				DSYS(FNC"Credit flow control used\n");				rfcomm->credit_flow = TRUE;				rfcomm->dlci[tmp_dlci].local_credits = pn_pkt->credits;				D_CTRL(FNC"Local credits:%d\n", rfcomm->dlci[tmp_dlci].local_credits); 			}			D_CTRL(FNC"process_mcc : mtu set on dlci:%d to %d\n", 			       tmp_dlci, rfcomm->dlci[tmp_dlci].mtu);			if (rfcomm->dlci[tmp_dlci].state == NEGOTIATING) {				send_sabm(rfcomm, tmp_dlci);			}		}		break;	}    	case NSC: /* Non supported command resonse */		D_CTRL(FNC"Received Non supported command response\n");		break;    	default:  /* Non supported command received */		D_REC(FNC"Received a non supported command\n");    		send_nsc_msg(rfcomm, mcc_short_pkt->h.type, MCC_RSP);    		break;	}}/* Sending packet functions *//* Creates a UA packet and puts it at the beginning of the pkt pointer */                         s32 send_ua(rfcomm_con *rfcomm, u8 dlci){	bt_tx_buf *tx_buf;	short_frame *ua_pkt;	u32 rfcomm_frame_size;  	D_CTRL("send_ua: Creating UA packet to DLCI %d\n",dlci);	rfcomm_frame_size = sizeof(short_frame) + FCS_SIZE;	tx_buf = subscribe_bt_buf(sizeof(rfcomm_tx_buf) + rfcomm_frame_size);		if (!tx_buf) {		D_ERR("send_ua : didn't get a valid tx_buf\n");		return -ENOMEM;	}		tx_buf->cur_len = rfcomm_frame_size;  	ua_pkt = (short_frame*) (tx_buf->data + sizeof(rfcomm_tx_buf));  	/* Always one in the address field */	ua_pkt->h.addr.ea = 1;	/* If we are the responder the cr bit should be set in a response */	ua_pkt->h.addr.cr = ((~(rfcomm->initiator)) & 0x1);	/* The control channel is on DLCI 0, i.e. d-bit should not be set */	ua_pkt->h.addr.d = (dlci) & 0x1;	ua_pkt->h.addr.server_chn = (dlci) >> 0x1;	/* In RFCOMM the F-bit should always be set when sending UA packets */	ua_pkt->h.control = SET_PF(UA);	/* The UA packet has length zero, and then the ea bit in the length	   field should  be set */	ua_pkt->h.length.ea = 1;	ua_pkt->h.length.len = 0;	ua_pkt->data[0] = crc_calc((u8*) ua_pkt, LONG_CRC_CHECK);  	return l2cap_send_data(tx_buf,rfcomm->l2cap);}/* Creates a DM packet and puts it at the beginning of the pkt pointer */s32 send_dm(rfcomm_con *rfcomm, u8 dlci){	bt_tx_buf *tx_buf;	short_frame *dm_pkt;	u32 rfcomm_frame_size;  	D_CTRL("send_dm: Creating DM packet to DLCI %d\n",dlci);  	rfcomm_frame_size = sizeof(short_frame) + FCS_SIZE;	tx_buf = subscribe_bt_buf(sizeof(rfcomm_tx_buf) + rfcomm_frame_size);	if (!tx_buf) {		D_ERR("send_dm : didn't get a valid tx_buf\n");		return -ENOMEM;	}	tx_buf->cur_len = rfcomm_frame_size;  	dm_pkt = (short_frame*) (tx_buf->data + sizeof(rfcomm_tx_buf));	/* Always one in the address field */	dm_pkt->h.addr.ea = 1;	/* If we are the responder the cr bit should be set in a response */	dm_pkt->h.addr.cr =  ((~(rfcomm->initiator)) & 0x1);	/* The control channel is on DLCI 0, i.e. d-bit should not be set */	dm_pkt->h.addr.d = dlci & 0x1;	dm_pkt->h.addr.server_chn = dlci >> 0x1;	/* In RFCOMM the F-bit should always be set when sending DM packets */	dm_pkt->h.control = SET_PF(DM);	/* The DM packet has length zero, and then the ea bit in the length	   field should  be set */	dm_pkt->h.length.ea = 1;	dm_pkt->h.length.len = 0;	dm_pkt->data[0] = crc_calc((u8*) dm_pkt, LONG_CRC_CHECK);	return l2cap_send_data(tx_buf,rfcomm->l2cap);}s32 send_sabm(rfcomm_con *rfcomm, u8 dlci){	bt_tx_buf *tx_buf;	short_frame *sabm_pkt;	u32 rfcomm_frame_size;	D_CTRL("send_sabm: Creating SABM packet to DLCI %d\n",dlci);	rfcomm_frame_size = sizeof(short_frame) + FCS_SIZE;	tx_buf = subscribe_bt_buf(sizeof(rfcomm_tx_buf) + rfcomm_frame_size);		if (!tx_buf) {		D_ERR("send_sabm : didn't get a valid tx_buf\n");		return -ENOMEM;	}	tx_buf->cur_len = rfcomm_frame_size;  	sabm_pkt = (short_frame*) (tx_buf->data + sizeof(rfcomm_tx_buf));  	/* Always one in the address field */	sabm_pkt->h.addr.ea = 1;	/* If we are the responder the cr bit should be set in a response */	sabm_pkt->h.addr.cr = ((rfcomm->initiator) & 0x1);	sabm_pkt->h.addr.d = dlci & 0x1;	sabm_pkt->h.addr.server_chn = dlci >> 0x1;	/* In RFCOMM the F-bit should always be set when sending SABM packets	 */	sabm_pkt->h.control = SET_PF(SABM);	/* The SABM packet has length zero, and then the ea bit in the length	   field should  be set */	sabm_pkt->h.length.ea = 1;	sabm_pkt->h.length.len = 0;	sabm_pkt->data[0] = crc_calc((u8*) sabm_pkt, LONG_CRC_CHECK);  	return l2cap_send_data(tx_buf,rfcomm->l2cap);}s32 send_disc(rfcomm_con *rfcomm, u8 dlci){	bt_tx_buf *tx_buf;	short_frame *disc_pkt;	u32 rfcomm_frame_size;	D_CTRL("send_disc: Creating DISC packet to DLCI %d\n",dlci);	rfcomm_frame_size = sizeof(short_frame) + FCS_SIZE;	tx_buf = subscribe_bt_buf(sizeof(rfcomm_tx_buf) + rfcomm_frame_size);	if (!tx_buf) {		D_ERR("send_disc : didn't get a valid tx_buf\n");		return -ENOMEM;	}	tx_buf->cur_len = rfcomm_frame_size;  	disc_pkt = (short_frame*) (tx_buf->data + sizeof(rfcomm_tx_buf));  	/* Always one in the address field */	disc_pkt->h.addr.ea = 1;	/* If we are the responder the cr bit should be set in a response */	disc_pkt->h.addr.cr = ((rfcomm->initiator) & 0x1);	disc_pkt->h.addr.d = dlci & 0x1;	disc_pkt->h.addr.server_chn = dlci >> 0x1;	/* In RFCOMM the F-bit should always be set when sending DISC packets	 */	disc_pkt->h.control = SET_PF(DISC);	/* The DISC packet has length zero, and then the ea bit in the length	   field should  be set */	disc_pkt->h.length.ea = 1;	disc_pkt->h.length.len = 0;	disc_pkt->data[0] = crc_calc((u8*) disc_pkt, LONG_CRC_CHECK);  	return l2cap_send_data(tx_buf,rfcomm->l2cap);} /* Creates a UIH packet and puts it at the beginning of the pkt pointer   The funtion returns how many bytes the UIH packet consist of */s32 send_uih(u8 *data, u32 len, rfcomm_con *rfcomm, u8 dlci){	bt_tx_buf *tx_buf;	u32 rfcomm_frame_size;	u8  send_credit = 0;	s32 retval = 0;			D_CTRL(FNC"Creating UIH packet with %d bytes data to DLCI %d\n",	       len, dlci);	if (!rfcomm->l2cap->link_up) {		D_ERR(FNC"could not send data, baseband down\n");#ifdef __KERNEL__		return 0;#else		return -1; /* FIXME - see comment in rfcomm_send_data */#endif	}	if (rfcomm->credit_flow &&(rfcomm->dlci[dlci].remote_credits < MIN_CREDITS)) {			D_SND(FNC"Sending more credits to remote port\n");			send_credit = 1;		}		if (len > SHORT_PAYLOAD_SIZE) {		long_frame *l_pkt;    		rfcomm_frame_size = sizeof(long_frame) + len + FCS_SIZE + send_credit;		/* Check for space in buffer, don't forget the size of the		   L2CAP and HCI headers */		if (buf_write_room() < (rfcomm_frame_size					+ sizeof(rfcomm_tx_buf))) {			return 0;		}		tx_buf = subscribe_bt_buf(sizeof(rfcomm_tx_buf)					  + rfcomm_frame_size);    		if (!tx_buf) {			D_ERR(FNC"didn't get a valid tx_buf\n");			return -ENOMEM;		}		tx_buf->cur_len = rfcomm_frame_size;    		l_pkt = (long_frame*) (tx_buf->data + sizeof(rfcomm_tx_buf));		set_uih_hdr((void*) l_pkt, dlci, len, rfcomm->initiator);		if (send_credit) {			u8 newcredits = MAX_CREDITS - rfcomm->dlci[dlci].remote_credits;			l_pkt->h.control = SET_PF(UIH);			l_pkt->data[0] = (newcredits);			rfcomm->dlci[dlci].remote_credits += newcredits;			D_SND(FNC": Remote credits: %d\n",rfcomm->dlci[dlci].remote_credits);			memcpy(l_pkt->data + 1, data, len);		} else {			memcpy(l_pkt->data, data, len);		}		l_pkt->data[len + send_credit] = crc_calc((u8*) l_pkt, SHORT_CRC_CHECK);		swap_long_frame(l_pkt);	} else {		short_frame *s_pkt;		rfcomm_frame_size = sizeof(short_frame) + len + FCS_SIZE + send_credit;		/* Check for space in buffer, don't forget the size of the		   L2CAP and HCI headers */		if (buf_write_room() < (rfcomm_frame_size					+ sizeof(rfcomm_tx_buf))) {			return 0;		}		tx_buf = subscribe_bt_buf(sizeof(rfcomm_tx_buf)					  + rfcomm_frame_size);		if (!tx_buf) {			D_ERR(FNC"didn't get a valid tx_buf\n");			return -ENOMEM;		}		tx_buf->cur_len = rfcomm_frame_size;    		s_pkt = (short_frame*) (tx_buf->data + sizeof(rfcomm_tx_buf));		/* Always one */		set_uih_hdr((void*) s_pkt, dlci, len, rfcomm->initiator);		if (send_credit) {			u8 newcredits = MAX_CREDITS - rfcomm->dlci[dlci].remote_credits;						s_pkt->h.control = SET_PF(UIH);			s_pkt->data[0] = (newcredits);			rfcomm->dlci[dlci].remote_credits += newcredits;			D_SND(FNC": Remote credits: %d\n",rfcomm->dlci[dlci].remote_credits);			memcpy(s_pkt->data + 1, data, len);		} else {			memcpy(s_pkt->data, data, len);		}		s_pkt->data[len + send_credit] = crc_calc((u8*) s_pkt, SHORT_CRC_CHECK);	}	/* FIXME - How should we propagate result up to higher layers ?	   through len or success/no success? */	tx_buf->line = rfcomm->line;	if((retval = l2cap_send_data(tx_buf, rfcomm->l2cap)) < 0) {		return retval;	}		return len;}s32rfcomm_send_credits(rfcomm_con *rfcomm, u8 dlci, u8 credits){	bt_tx_buf *tx_buf;	short_frame *uih_pkt;	u32 rfcomm_frame_size;  	D_CTRL(FNC"give %d credits to dlci %d\n", credits, dlci);	rfcomm_frame_size = (sizeof(short_frame) + 1 + FCS_SIZE);	tx_buf = subscribe_bt_buf(sizeof(rfcomm_tx_buf) + rfcomm_frame_size);	if (!tx_buf) {		D_ERR("rfcomm_fcon_msg : didn't get a valid tx_buf\n");		return -ENOMEM;	}	tx_buf->cur_len = rfcomm_frame_size;  	uih_pkt = (short_frame*) (tx_buf->data + sizeof(rfcomm_tx_buf));	set_uih_hdr(uih_pkt, dlci, 0, (~rfcomm->initiator)^1);	uih_pkt->h.control = SET_PF(UIH);	uih_pkt->data[0] = credits;	uih_pkt->data[1] = crc_calc((u8*) uih_pkt, SHORT_CRC_CHECK);		return l2cap_send_data(tx_buf, rfcomm->l2cap);}/* Sends Multiplexer command packets funktions *//* Sends a test messages with a specific test pattern. */s32 rfcomm_test_msg(rfcomm_con *rfcomm, u8 *test_pattern, u32 len, u8 cr){	bt_tx_buf *tx_buf;

⌨️ 快捷键说明

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