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

📄 rfcomm.c

📁 蓝牙协议源代码 bluetooth stack for lwip
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * Copyright (c) 2003 EISLAB, Lulea University of Technology. * All rights reserved.  *  * Redistribution and use in source and binary forms, with or without modification,  * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, *    this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, *    this list of conditions and the following disclaimer in the documentation *    and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products *    derived from this software without specific prior written permission.  * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY  * OF SUCH DAMAGE. * * This file is part of the lwBT Bluetooth stack. *  * Author: Conny Ohult <conny@sm.luth.se> * *//*-----------------------------------------------------------------------------------*//* rfcomm.c * * Implementation of the RFCOMM protocol. A subset of the ETSI TS 07.10 standard with  * some Bluetooth-specific adaptations. *//*-----------------------------------------------------------------------------------*/#include "netif/lwbt/l2cap.h"#include "netif/lwbt/rfcomm.h"#include "netif/lwbt/lwbt_memp.h"#include "netif/lwbt/fcs.h"#include "lwbtopts.h"#include "lwip/debug.h"struct rfcomm_pcb_listen *rfcomm_listen_pcbs; /* List of all RFCOMM PCBs listening for 					      an incomming connection on a specific					      server channel */struct rfcomm_pcb *rfcomm_active_pcbs;  /* List of all active RFCOMM PCBs */struct rfcomm_pcb *rfcomm_tmp_pcb;/* Forward declarations */struct rfcomm_pcb *rfcomm_get_active_pcb(u8_t cn, struct bd_addr *bdaddr);/*-----------------------------------------------------------------------------------*//*  * rfcomm_init(): *  * Initializes the rfcomm layer. *//*-----------------------------------------------------------------------------------*/voidrfcomm_init(void){  /* Clear globals */  rfcomm_listen_pcbs = NULL;  rfcomm_active_pcbs = NULL;  rfcomm_tmp_pcb = NULL;}/*-----------------------------------------------------------------------------------*//* * rfcomm_tmr(): * * Called every 1s and implements the command timer that * removes a DLC if it has been waiting for a response enough * time. *//*-----------------------------------------------------------------------------------*/voidrfcomm_tmr(void){  struct rfcomm_pcb *pcb, *tpcb;  err_t ret;    /* Step through all of the active pcbs */  for(pcb = rfcomm_active_pcbs; pcb != NULL; pcb = pcb->next) {    if(pcb->to != 0) {      --pcb->to;      LWIP_DEBUGF(RFCOMM_DEBUG, ("rfcomm_tmr: %d\n", pcb->to));      if(pcb->to == 0) {	/* Timeout */	if(pcb->cn == 0) {	  /* If DLC 0 timed out, disconnect all other DLCs on this multiplexer session first */	  for(tpcb = rfcomm_active_pcbs; tpcb != NULL; tpcb = tpcb->next) {	    if(tpcb->cn != 0 && bd_addr_cmp(&(tpcb->l2cappcb->remote_bdaddr), &(pcb->l2cappcb->remote_bdaddr))) {	      //RFCOMM_RMV(&rfcomm_active_pcbs, tpcb); /* Remove pcb from active list */	      tpcb->state = RFCOMM_CLOSED;	      RFCOMM_EVENT_DISCONNECTED(tpcb,ERR_OK,ret); /* Notify upper layer */	    }	  }	}	/* Disconnect this DLC */	LWIP_DEBUGF(RFCOMM_DEBUG, ("rfcomm_tmr: Timeout! Disconnect this DLC. State = %d\n", pcb->state));	//RFCOMM_RMV(&rfcomm_active_pcbs, pcb); /* Remove pcb from active list */	pcb->state = RFCOMM_CLOSED;	RFCOMM_EVENT_DISCONNECTED(pcb,ERR_OK,ret); /* Notify upper layer */      }    }  }}/*-----------------------------------------------------------------------------------*//* * rfcomm_lp_disconnected(): * * Called by the application to indicate that the lower protocol disconnected. Closes * any active PCBs in the lists *//*-----------------------------------------------------------------------------------*/err_trfcomm_lp_disconnected(struct l2cap_pcb *l2cappcb){  struct rfcomm_pcb *pcb, *tpcb;  err_t ret = ERR_OK;  pcb = rfcomm_active_pcbs;  while(pcb != NULL) {    tpcb = pcb->next;    if(bd_addr_cmp(&(l2cappcb->remote_bdaddr), &(pcb->l2cappcb->remote_bdaddr))) {      pcb->state = RFCOMM_CLOSED;      RFCOMM_EVENT_DISCONNECTED(pcb,ERR_OK,ret); /* Notify upper layer */    }    pcb = tpcb;  }  return ret;}/*-----------------------------------------------------------------------------------*//*  * rfcomm_new(): * * Creates a new RFCOMM protocol control block but doesn't place it on * any of the RFCOMM PCB lists. *//*-----------------------------------------------------------------------------------*/struct rfcomm_pcb *rfcomm_new(struct l2cap_pcb *l2cappcb) {  struct rfcomm_pcb *pcb;  pcb = lwbt_memp_malloc(MEMP_RFCOMM_PCB);  if(pcb != NULL) {    memset(pcb, 0, sizeof(struct rfcomm_pcb));    pcb->l2cappcb = l2cappcb;        pcb->cl = RFCOMM_CL; /* Default convergence layer */    pcb->n = RFCOMM_N; /* Default maximum frame size */         pcb->state = RFCOMM_CLOSED;    return pcb;  }  LWIP_DEBUGF(RFCOMM_DEBUG, ("rfcomm_new: Could not allocate a new pcb\n"));  return NULL;}/*-----------------------------------------------------------------------------------*//*  * rfcomm_close(): * * Closes the RFCOMM protocol control block. *//*-----------------------------------------------------------------------------------*/voidrfcomm_close(struct rfcomm_pcb *pcb) {#if RFCOMM_FLOW_QUEUEING  if(pcb->buf != NULL) {    pbuf_free(pcb->buf);  }#endif  if(pcb->state == RFCOMM_LISTEN) {    RFCOMM_RMV((struct rfcomm_pcb **)&rfcomm_listen_pcbs, pcb);    lwbt_memp_free(MEMP_RFCOMM_PCB_LISTEN, pcb);  } else {    RFCOMM_RMV(&rfcomm_active_pcbs, pcb);    lwbt_memp_free(MEMP_RFCOMM_PCB, pcb);  }  pcb = NULL;}/*-----------------------------------------------------------------------------------*//*  * rfcomm_reset_all(): * * Closes all active and listening RFCOMM protocol control blocks. *//*-----------------------------------------------------------------------------------*/voidrfcomm_reset_all(void) {  struct rfcomm_pcb *pcb, *tpcb;  struct rfcomm_pcb_listen *lpcb, *tlpcb;  for(pcb = rfcomm_active_pcbs; pcb != NULL;) {    tpcb = pcb->next;    rfcomm_close(pcb);    pcb = tpcb;  }  for(lpcb = rfcomm_listen_pcbs; lpcb != NULL;) {    tlpcb = lpcb->next;    rfcomm_close((struct rfcomm_pcb *)lpcb);    lpcb = tlpcb;  }    rfcomm_init();}/*-----------------------------------------------------------------------------------*//*  * rfcomm_get_multiplexer(): * * Return the active PCB with the matching Bluetooth address and channel number. *//*-----------------------------------------------------------------------------------*/struct rfcomm_pcb *rfcomm_get_active_pcb(u8_t cn, struct bd_addr *bdaddr) {  struct rfcomm_pcb *pcb;  for(pcb = rfcomm_active_pcbs; pcb != NULL; pcb = pcb->next) {    if(pcb->cn == cn && bd_addr_cmp(&(pcb->l2cappcb->remote_bdaddr), 				    bdaddr)) {      break;    }  }  return pcb;}/*-----------------------------------------------------------------------------------*//*  * rfcomm_dm(): * * Sends a RFCOMM disconnected mode frame in response to a command when disconnected. *//*-----------------------------------------------------------------------------------*/static err_trfcomm_dm(struct l2cap_pcb *pcb, struct rfcomm_hdr *hdr) {  struct pbuf *p;  struct rfcomm_hdr *rfcommhdr;  err_t ret;  LWIP_DEBUGF(RFCOMM_DEBUG, ("rfcomm_dm\n"));  if((p = pbuf_alloc(PBUF_RAW, RFCOMM_DM_LEN, PBUF_RAM)) == NULL) {    /* Could not allocate memory for pbuf */    LWIP_DEBUGF(RFCOMM_DEBUG, ("rfcomm_dm: Could not allocate memory for pbuf\n"));    return ERR_MEM;  }  rfcommhdr = p->payload;  rfcommhdr->addr = hdr->addr & 0xFB; /* Set direction bit to 0 for the response */  rfcommhdr->ctrl = RFCOMM_DM;  rfcommhdr->len = 1; /* EA bit set to 1 to indicate a 7 bit length field */  ((u8_t *)p->payload)[RFCOMM_HDR_LEN_1] = fcs8_crc_calc(p, RFCOMM_CRC_CHECK_LEN);    ret = l2ca_datawrite(pcb, p);  pbuf_free(p);  return ret;}/*-----------------------------------------------------------------------------------*//*  * rfcomm_connect(): * * Sends a RFCOMM start asynchronous balanced mode frame to startup the channel. Also * specify the function to be called when the channel has been connected. *//*-----------------------------------------------------------------------------------*/err_trfcomm_connect(struct rfcomm_pcb *pcb, u8_t cn, err_t (* connected)(void *arg,								    struct rfcomm_pcb *tpcb,								    err_t err)){  struct rfcomm_hdr *hdr;  struct pbuf *p;  err_t ret;  struct rfcomm_pcb *tpcb;  LWIP_DEBUGF(RFCOMM_DEBUG, ("rfcomm_connect\n"));  pcb->connected = connected;  pcb->cn = cn;  pcb->rfcommcfg |= RFCOMM_CFG_IR; /* Set role to initiator */   /* Create multiplexer session if one does not already exist */  if(cn != 0) {    tpcb = rfcomm_get_active_pcb(0, &pcb->l2cappcb->remote_bdaddr);        if(tpcb == NULL) {      pcb->state = W4_RFCOMM_MULTIPLEXER;      RFCOMM_REG(&rfcomm_active_pcbs, pcb);      pcb = rfcomm_new(pcb->l2cappcb);      pcb->rfcommcfg |= RFCOMM_CFG_IR; /* Set role to initiator */    }   }   if((p = pbuf_alloc(PBUF_RAW, RFCOMM_SABM_LEN, PBUF_RAM)) == NULL) {    /* Could not allocate memory for pbuf */    LWIP_DEBUGF(RFCOMM_DEBUG, ("rfcomm_connect: Could not allocate memory for pbuf\n"));    return ERR_MEM;  }  hdr = p->payload;  hdr->addr = (1 << 0) | ((pcb->rfcommcfg & RFCOMM_CFG_IR) << 1) | (((pcb->rfcommcfg & RFCOMM_CFG_IR) ^ 1) << 2) | (pcb->cn << 3);  hdr->ctrl = RFCOMM_SABM;  hdr->len = (1 << 0) | (0 << 1);  ((u8_t *)p->payload)[RFCOMM_HDR_LEN_1] = fcs8_crc_calc(p, RFCOMM_CRC_CHECK_LEN);  if((ret = l2ca_datawrite(pcb->l2cappcb, p)) == ERR_OK) {    pcb->state = W4_RFCOMM_SABM_RSP;    pcb->to = 5*RFCOMM_TO; /* Set acknowledgement timer, 50-300s (5*10-60s) */  }  if((tpcb = rfcomm_get_active_pcb(pcb->cn, &pcb->l2cappcb->remote_bdaddr)) == NULL) {    RFCOMM_REG(&rfcomm_active_pcbs, pcb);  }  pbuf_free(p);  return ret;}/*-----------------------------------------------------------------------------------*//*  * rfcomm_disconnect(): * * Sends a RFCOMM disconnect frame to close the channel. *//*-----------------------------------------------------------------------------------*/err_trfcomm_disconnect(struct rfcomm_pcb *pcb){  struct rfcomm_hdr *hdr;  struct pbuf *p;  err_t ret;  LWIP_DEBUGF(RFCOMM_DEBUG, ("rfcomm_disconnect\n"));  if((p = pbuf_alloc(PBUF_RAW, RFCOMM_DISC_LEN, PBUF_RAM)) == NULL) {    /* Could not allocate memory for pbuf */    LWIP_DEBUGF(RFCOMM_DEBUG, ("rfcomm_disconnect: Could not allocate memory for pbuf\n"));    return ERR_MEM;  }    p = pbuf_alloc(PBUF_RAW, RFCOMM_DISC_LEN, PBUF_RAM);  hdr = p->payload;  hdr->addr = (1 << 0) | ((pcb->rfcommcfg & RFCOMM_CFG_IR) << 1) | (((pcb->rfcommcfg & RFCOMM_CFG_IR) ^ 1) << 2) | (pcb->cn << 3);  hdr->ctrl = RFCOMM_DISC;  hdr->len = (1 << 0) | (0 << 1);  ((u8_t *)p->payload)[RFCOMM_HDR_LEN_1] = fcs8_crc_calc(p, RFCOMM_CRC_CHECK_LEN);  pcb->state = W4_RFCOMM_DISC_RSP;  if((ret = l2ca_datawrite(pcb->l2cappcb, p)) == ERR_OK) {    pcb->to = RFCOMM_TO; /* Set acknowledgement timer, 10-60s */  }  pbuf_free(p);  return ret;}/*-----------------------------------------------------------------------------------*//*  * rfcomm_ua(): * * Sends a RFCOMM unnumbered acknowledgement to respond to a connection request. *//*-----------------------------------------------------------------------------------*/static err_t //RESPONDERrfcomm_ua(struct l2cap_pcb *pcb, struct rfcomm_hdr *hdr) 

⌨️ 快捷键说明

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