www.pudn.com > 蓝牙协议源代码.zip > rfcomm.h


/*
 * 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 
 *
 */

#ifndef __LWBT_RFCOMM_H__
#define __LWBT_RFCOMM_H__

#include "netif/lwbt/l2cap.h"


//struct rfcomm_pcb;

/* Functions for interfacing with RFCOMM: */

/* Lower layer interface to RFCOMM: */
void rfcomm_init(void); /* Must be called first to initialize RFCOMM */
void rfcomm_tmr(void); /* Must be called every 1s interval */

/* Application program's interface: */
struct rfcomm_pcb *rfcomm_new(struct l2cap_pcb *pcb);
void rfcomm_close(struct rfcomm_pcb *pcb);
void rfcomm_reset_all(void);
void rfcomm_arg(struct rfcomm_pcb *pcb, void *arg);
void rfcomm_recv(struct rfcomm_pcb *pcb, 
		 err_t (* recv)(void *arg, struct rfcomm_pcb *pcb, struct pbuf *p, err_t err));
void rfcomm_disc(struct rfcomm_pcb *pcb, 
		 err_t (* disc)(void *arg, struct rfcomm_pcb *pcb, err_t err));

#define rfcomm_cn(pcb) ((pcb)->cn)
#define rfcomm_cl(pcb) ((pcb)->cl)
#define rfcomm_local_credits(pcb) ((pcb)->k)
#define rfcomm_remote_credits(pcb) ((pcb)->rk)
#define rfcomm_fc(pcb) ((pcb)->fc)
#define rfcomm_mfs(pcb) ((pcb)->n)

err_t rfcomm_input(void *arg, struct l2cap_pcb *l2cappcb, struct pbuf *p, err_t err);

err_t rfcomm_connect(struct rfcomm_pcb *pcb, u8_t cn, 
		     err_t (* connected)(void *arg, struct rfcomm_pcb *tpcb, err_t err));
err_t rfcomm_disconnect(struct rfcomm_pcb *pcb);
err_t rfcomm_listen(struct rfcomm_pcb *npcb, u8_t cn, 
		    err_t (* accept)(void *arg, struct rfcomm_pcb *pcb, err_t err));
err_t rfcomm_pn(struct rfcomm_pcb *pcb,
		err_t (* pn_rsp)(void *arg, struct rfcomm_pcb *pcb, err_t err));
err_t rfcomm_test(struct rfcomm_pcb *pcb, 
		  err_t (* test_rsp)(void *arg, struct rfcomm_pcb *tpcb, err_t err));
err_t rfcomm_msc(struct rfcomm_pcb *pcb, u8_t fc, 
		 err_t (* msc_rsp)(void *arg, struct rfcomm_pcb *pcb, err_t err));
err_t rfcomm_rpn(struct rfcomm_pcb *pcb, u8_t br,
	   err_t (* rpn_rsp)(void *arg, struct rfcomm_pcb *pcb, err_t err));
err_t rfcomm_uih(struct rfcomm_pcb *pcb, u8_t cn, struct pbuf *q);
err_t rfcomm_uih_credits(struct rfcomm_pcb *pcb, u8_t credits, struct pbuf *q);

err_t rfcomm_lp_disconnected(struct l2cap_pcb *pcb);


/* Control field values */
#define RFCOMM_SABM 0x3F
#define RFCOMM_UA 0x73
#define RFCOMM_DM 0x0F
#define RFCOMM_DM_PF 0x1F
#define RFCOMM_DISC 0x53
#define RFCOMM_UIH 0xEF
#define RFCOMM_UIH_PF 0xFF 

/* Multiplexer message types */
#define RFCOMM_PN_CMD 0x83
#define RFCOMM_PN_RSP 0x81
#define RFCOMM_TEST_CMD 0x23
#define RFCOMM_TEST_RSP 0x21
#define RFCOMM_FCON_CMD 0xA3
#define RFCOMM_FCON_RSP 0xA1
#define RFCOMM_FCOFF_CMD 0x63
#define RFCOMM_FCOFF_RSP 0x61
#define RFCOMM_MSC_CMD 0xE3
#define RFCOMM_MSC_RSP 0xE1
#define RFCOMM_RPN_CMD 0x93
#define RFCOMM_RPN_RSP 0x91
#define RFCOMM_RLS_CMD 0x53
#define RFCOMM_RLS_RSP 0x51 
#define RFCOMM_NSC_RSP 0x11

/* Length of RFCOMM hdr with 1 or 2 byte lengh field excluding credit */
#define RFCOMM_HDR_LEN_1 3
#define RFCOMM_HDR_LEN_2 4

/* Length of a multiplexer message */
#define RFCOMM_MSGHDR_LEN 2
#define RFCOMM_PNMSG_LEN 8
#define RFCOMM_MSCMSG_LEN 2
#define RFCOMM_RPNMSG_LEN 8
#define RFCOMM_NCMSG_LEN 1

/* Length of a frame */
#define RFCOMM_DM_LEN 4
#define RFCOMM_SABM_LEN 4
#define RFCOMM_DISC_LEN 4
#define RFCOMM_UA_LEN 4
#define RFCOMM_UIH_LEN 3
#define RFCOMM_UIHCRED_LEN 4

/* Default convergence layer */
#define RFCOMM_CL 0xF /* Credit based flow control */

/* Default port settings for a communication link */
#define RFCOMM_COM_BR 0x03 /* Baud rate (9600 bit/s)*/
#define RFCOMM_COM_CFG 0x03 /* Data bits (8 bits), stop bits (1), parity (no parity) 
			       and parity type */
#define RFCOMM_COM_FC 0x00 /* Flow control (no flow ctrl) */
#define RFCOMM_COM_XON 0x00 /* No flow control (default DC1) */ 
#define RFCOMM_COM_XOFF 0x00 /* No flow control (default DC3) */

/* FCS calc */
#define RFCOMM_CODE_WORD 0xE0 /* pol = x8+x2+x1+1 */
#define RFCOMM_CRC_CHECK_LEN 3
#define RFCOMM_UIHCRC_CHECK_LEN 2

/* RFCOMM configuration parameter masks */
#define RFCOMM_CFG_IR 0x01
#define RFCOMM_CFG_FC 0x02
#define RFCOMM_CFG_MSC_OUT 0x04
#define RFCOMM_CFG_MSC_IN 0x08

enum rfcomm_state {
  RFCOMM_CLOSED, RFCOMM_LISTEN, W4_RFCOMM_MULTIPLEXER, W4_RFCOMM_SABM_RSP, RFCOMM_CFG, RFCOMM_OPEN, 
  W4_RFCOMM_DISC_RSP
};

/* The RFCOMM frame header */
struct rfcomm_hdr {
  u8_t addr;
  u8_t ctrl;
  u16_t len;
  u8_t k;
};

struct rfcomm_msg_hdr {
  u8_t type;
  u8_t len;
};

struct rfcomm_pn_msg {
  u8_t dlci; /* Data link connection id */
  u8_t i_cl; /* Type frame for information and Convergece layer to use */
  u8_t p; /* Priority */
  u8_t t; /* Value of acknowledgement timer */
  u16_t n; /* Maximum frame size */
  u8_t na; /* Maximum number of retransmissions */
  u8_t k; /* Initial credit value */
};

struct rfcomm_msc_msg {
  u8_t dlci; /* Data link connection id */
  u8_t rs232; /* RS232 control signals */
};

struct rfcomm_rpn_msg {
  u8_t dlci; /* Data link connection id */
  u8_t br; /* Baud Rate */
  u8_t cfg; /* Data bits, Stop bits, Parity, Parity type */
  u8_t fc; /* Flow control */
  u8_t xon;
  u8_t xoff;
  u16_t mask;
};

/* The RFCOMM protocol control block */
struct rfcomm_pcb {
  struct rfcomm_pcb *next; /* For the linked list */

  enum rfcomm_state state; /* RFCOMM state */

  struct l2cap_pcb *l2cappcb; /* The L2CAP connection */

  u8_t cn; /* Channel number */
  
  u8_t cl; /* Convergence layer */
  u8_t p; /* Connection priority */
  u16_t n; /* Maximum frame size */
  u8_t k; /* No of local credits */

  u8_t rk; /* No of remote credits */

  u8_t rfcommcfg; /* Bit 1 indicates if we are the initiator of this connection
		   * Bit 2 indicates if the flow control bit is set so that we are allowed to send data
		   * Bit 3 indicates if modem status has been configured for the incoming direction
		   * Bit 4 indicates if modem status has been configured for the outgoing direction
		   */

  u16_t to; /* Frame and cmd timeout */
  
  u8_t uih_in_fcs; /* Frame check sequence for uih frames (P/F bit = 0) */
  u8_t uihpf_in_fcs; /* Frame check sequence for uih frames (P/F bit = 1) */
  u8_t uih_out_fcs; /* Frame check sequence for uih frames (P/F bit = 0) */
  u8_t uihpf_out_fcs; /* Frame check sequence for uih frames (P/F bit = 1) */

  u8_t uih0_in_fcs; /* Frame check sequence for uih frames on the control channel (P/F bit = 0) */
  u8_t uih0_out_fcs; /* Frame check sequence for uih frames on the control channel (P/F bit = 0) */

#if RFCOMM_FLOW_QUEUEING
  struct pbuf *buf;
#endif
  void *callback_arg;
  
  /* RFCOMM Frame commands and responses */
  err_t (* connected)(void *arg, struct rfcomm_pcb *pcb, err_t err);
  err_t (* accept)(void *arg, struct rfcomm_pcb *pcb, err_t err);
  err_t (* disconnected)(void *arg, struct rfcomm_pcb *pcb, err_t err);

  /* RFCOMM Multiplexer responses */
  err_t (* pn_rsp)(void *arg, struct rfcomm_pcb *pcb, err_t err);
  err_t (* test_rsp)(void *arg, struct rfcomm_pcb *pcb, err_t err);
  err_t (* msc_rsp)(void *arg, struct rfcomm_pcb *pcb, err_t err);
  err_t (* rpn_rsp)(void *arg, struct rfcomm_pcb *pcb, err_t err);

  err_t (* recv)(void *arg, struct rfcomm_pcb *pcb, struct pbuf *p, err_t err);
};

/* The server channel */
struct rfcomm_pcb_listen {
  struct rfcomm_pcb_listen *next; /* For the linked list */

  enum rfcomm_state state; /* RFCOMM state */

  u8_t cn; /* Channel number */

  void *callback_arg;

  err_t (* accept)(void *arg, struct rfcomm_pcb *pcb, err_t err);
};

#define RFCOMM_EVENT_CONNECTED(pcb,err,ret) \
                              if((pcb)->connected != NULL) \
                              (ret = (pcb)->connected((pcb)->callback_arg,(pcb),(err)))
#define RFCOMM_EVENT_ACCEPT(pcb,err,ret) \
                              if((pcb)->accept != NULL) \
                              (ret = (pcb)->accept((pcb)->callback_arg,(pcb),(err)))
#define RFCOMM_EVENT_DISCONNECTED(pcb,err,ret) \
                                 if((pcb)->disconnected != NULL) { \
                                   (ret = (pcb)->disconnected((pcb)->callback_arg,(pcb),(err))); \
                                 } else { \
                                   rfcomm_close(pcb); \
				 }
#define RFCOMM_EVENT_PN_RSP(pcb,err,ret) \
                       if((pcb)->pn_rsp != NULL) \
                       (ret = (pcb)->pn_rsp((pcb)->callback_arg,(pcb),(err)))
#define RFCOMM_EVENT_TEST(pcb,err,ret) \
                       if((pcb)->test_rsp != NULL) \
                       (ret = (pcb)->test_rsp((pcb)->callback_arg,(pcb),(err)))
#define RFCOMM_EVENT_MSC(pcb,err,ret) \
                        if((pcb)->msc_rsp != NULL) \
                        (ret = (pcb)->msc_rsp((pcb)->callback_arg,(pcb),(err)))
#define RFCOMM_EVENT_RPN(pcb,err,ret) \
                        if((pcb)->rpn_rsp != NULL) \
                        (ret = (pcb)->rpn_rsp((pcb)->callback_arg,(pcb),(err)))
#define RFCOMM_EVENT_RECV(pcb,err,p,ret) \
                          if((pcb)->recv != NULL) { \
                            (ret = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err))); \
                          } else { \
                            pbuf_free(p); \
                          }


/* The RFCOMM PCB lists. */
extern struct rfcomm_pcb_listen *rfcomm_listen_pcbs; /* List of all RFCOMM PCBs listening for 
							 an incomming connection on a specific
							 server channel */
extern struct rfcomm_pcb *rfcomm_active_pcbs; /* List of all active RFCOMM PCBs */

extern struct rfcomm_pcb *rfcomm_tmp_pcb;      /* Only used for temporary storage. */

/* Define two macros, RFCOMM_REG and RFCOMM_RMV that registers a RFCOMM PCB
   with a PCB list or removes a PCB from a list, respectively. */

#define RFCOMM_REG(pcbs, npcb) do { \
                            npcb->next = *pcbs; \
                            *pcbs = npcb; \
                            } while(0)
#define RFCOMM_RMV(pcbs, npcb) do { \
                            if(*pcbs == npcb) { \
                               *pcbs = (*pcbs)->next; \
                            } else for(rfcomm_tmp_pcb = *pcbs; rfcomm_tmp_pcb != NULL; rfcomm_tmp_pcb = rfcomm_tmp_pcb->next) { \
                               if(rfcomm_tmp_pcb->next != NULL && rfcomm_tmp_pcb->next == npcb) { \
                                  rfcomm_tmp_pcb->next = npcb->next; \
                                  break; \
                               } \
                            } \
                            npcb->next = NULL; \
                            } while(0)

#endif /* __RFCOMM_H__ */