📄 l2cap.h
字号:
on a queue */
struct pbuf *p; /* buffer containing data + L2CAP header */
u16_t sigid; /* Identification */
u16_t ertx; /* extended response timeout expired */
u8_t rtx; /* response timeout expired */
u8_t nrtx; /* number of retransmissions */
};
struct l2cap_cfg {
u16_t inmtu; /* Maximum transmission unit this channel can accept */
u16_t outmtu; /* Maximum transmission unit that can be sent on this channel */
u16_t influshto; /* In flush timeout */
u16_t outflushto; /* Out flush timeout */
struct pbuf *opt; /* Any received non-hint unknown option(s) or option(s) with unacceptable parameters
will be temporarily stored here */
u8_t cfgto; /* Configuration timeout */
u8_t l2capcfg; /* Bit 1 indicates if we are the initiator of this connection
* Bit 2 indicates if a successful configuration response has been received
* Bit 3 indicates if a successful configuration response has been sent
* Bit 4 indicates if an initial configuration request has been sent
*/
};
struct l2cap_seg {
struct l2cap_seg *next; /* For the linked list */
struct bd_addr bdaddr;
struct pbuf *p; /* Buffer containing data + L2CAP header */
u16_t len; /* The L2CAP length of this segment */
struct l2cap_hdr *l2caphdr; /* The L2CAP header */
struct l2cap_pcb *pcb; /* The L2CAP Protocol Control Block */
};
struct l2cap_pcb {
struct l2cap_pcb *next; /* For the linked list */
enum l2cap_state state; /* L2CAP state */
void *callback_arg;
u16_t scid; /* Source CID */
u16_t dcid; /* Destination CID */
u16_t psm; /* Protocol/Service Multiplexer */
u16_t ursp_id; /* Signal id to respond to */
u8_t encrypt; /* encryption mode */
struct l2cap_sig *unrsp_sigs; /* List of sent but unresponded signals */
struct bd_addr remote_bdaddr;
struct l2cap_cfg cfg; /* Configuration parameters */
/* Upper layer to L2CAP confirmation functions */
/* Function to be called when a connection has been set up */
err_t (* l2ca_connect_cfm)(void *arg, struct l2cap_pcb *pcb, u16_t result, u16_t status);
/* Function to be called when a connection has been closed */
err_t (* l2ca_disconnect_cfm)(void *arg, struct l2cap_pcb *pcb);
/* Function to be called when a echo reply has been received */
err_t (* l2ca_pong)(void *arg, struct l2cap_pcb *pcb, u8_t result);
/* L2CAP to upper layer indication functions */
/* Function to be called when a connection indication event occurs */
err_t (* l2ca_connect_ind)(void *arg, struct l2cap_pcb *pcb, err_t err);
/* Function to be called when a disconnection indication event occurs */
err_t (* l2ca_disconnect_ind)(void *arg, struct l2cap_pcb *pcb, err_t err);
/* Function to be called when a timeout indication event occurs */
err_t (* l2ca_timeout_ind)(void *arg, struct l2cap_pcb *newpcb, err_t err);
/* Function to be called when a L2CAP connection receives data */
err_t (* l2ca_recv)(void *arg, struct l2cap_pcb *pcb, struct pbuf *p, err_t err);
};
struct l2cap_pcb_listen {
struct l2cap_pcb_listen *next; /* for the linked list */
enum l2cap_state state; /* L2CAP state */
void *callback_arg;
u16_t psm; /* Protocol/Service Multiplexer */
/* Function to call when a connection request has been received
from a remote device. */
err_t (* l2ca_connect_ind)(void *arg, struct l2cap_pcb *pcb, err_t err);
};
/* Internal functions and global variables */
#define L2CA_ACTION_CONN_CFM(pcb,result,status,ret) if((pcb)->l2ca_connect_cfm != NULL) (ret = (pcb)->l2ca_connect_cfm((pcb)->callback_arg,(pcb),(result),(status)))
#define L2CA_ACTION_DISCONN_CFM(pcb,ret) if((pcb)->l2ca_disconnect_cfm != NULL) (ret = (pcb)->l2ca_disconnect_cfm((pcb)->callback_arg,(pcb)))
#define L2CA_ACTION_PING_CFM(pcb,result,ret) if((pcb)->l2ca_pong != NULL) (ret = (pcb)->l2ca_pong((pcb)->callback_arg,(pcb),(result)))
#define L2CA_ACTION_CONN_IND(pcb,err,ret) if((pcb)->l2ca_connect_ind != NULL) (ret = (pcb)->l2ca_connect_ind((pcb)->callback_arg,(pcb),(err)))
#define L2CA_ACTION_DISCONN_IND(pcb,err,ret) \
if((pcb)->l2ca_disconnect_ind != NULL) { \
LWIP_DEBUGF(L2CAP_DEBUG, ("l2cap_disconnect_ind called\n")); \
(ret = (pcb)->l2ca_disconnect_ind((pcb)->callback_arg,(pcb),(err))); \
} else { \
l2cap_close(pcb); \
}
#define L2CA_ACTION_TO_IND(pcb,err,ret) if((pcb)->l2ca_timeout_ind != NULL) (ret = (pcb)->l2ca_timeout_ind((pcb)->callback_arg,(pcb),(err)))
#define L2CA_ACTION_RECV(pcb,p,err,ret) \
if((pcb)->l2ca_recv != NULL) { \
(ret = (pcb)->l2ca_recv((pcb)->callback_arg,(pcb),(p),(err))); \
} else { \
pbuf_free(p); \
}
#define L2CAP_OPTH_TYPE(hdr) (((hdr)->type) & 0x7f)
#define L2CAP_OPTH_TOA(hdr) (((hdr)->type) >> 7)
/* The L2CAP PCB lists. */
extern struct l2cap_pcb_listen *l2cap_listen_pcbs; /* List of all L2CAP PCBs in CLOSED state
but awaing an incoming conn req. */
extern struct l2cap_pcb *l2cap_active_pcbs; /* List of all L2CAP PCBs that has
established or is about to establish
an ACL link */
extern struct l2cap_pcb *l2cap_tmp_pcb; /* Only used for temporary storage. */
/* Axoims about the above list:
1) A PCB is only in one of the lists.
2) All PCBs in the l2cap_active_pcbs list has established or is about to
establish an ACL link.
*/
/* Define two macros, L2CAP_REG and L2CAP_RMV that registers a L2CAP PCB
with a PCB list or removes a PCB from a list, respectively. */
#ifdef LWBT_DEBUG
#define L2CAP_REG(pcbs, npcb) do { \
for(l2cap_tmp_pcb = *pcbs; \
l2cap_tmp_pcb != NULL; \
l2cap_tmp_pcb = l2cap_tmp_pcb->next) { \
LWIP_ASSERT("L2CAP_REG: already registered\n", l2cap_tmp_pcb != npcb); \
} \
npcb->next = *pcbs; \
LWIP_ASSERT("L2CAP_REG: npcb->next != npcb", npcb->next != npcb); \
*pcbs = npcb; \
} while(0)
#define L2CAP_RMV(pcbs, npcb) do { \
LWIP_ASSERT("L2CAP_RMV: pcbs != NULL", *pcbs != NULL); \
LWIP_DEBUGF(L2CAP_DEBUG, ("L2CAP_RMV: removing %p from %p\n", npcb, *pcbs)); \
if(*pcbs == npcb) { \
*pcbs = (*pcbs)->next; \
} else for(l2cap_tmp_pcb = *pcbs; l2cap_tmp_pcb != NULL; l2cap_tmp_pcb = l2cap_tmp_pcb->next) { \
if(l2cap_tmp_pcb->next != NULL && l2cap_tmp_pcb->next == npcb) { \
l2cap_tmp_pcb->next = npcb->next; \
break; \
} \
} \
npcb->next = NULL; \
LWIP_DEBUGF(L2CAP_DEBUG, ("L2CAP_RMV: removed %p from %p\n", npcb, *pcbs)); \
} while(0)
#else /* LWBT_DEBUG */
#define L2CAP_REG(pcbs, npcb) do { \
npcb->next = *pcbs; \
*pcbs = npcb; \
} while(0)
#define L2CAP_RMV(pcbs, npcb) do { \
if(*pcbs == npcb) { \
*pcbs = (*pcbs)->next; \
} else for(l2cap_tmp_pcb = *pcbs; l2cap_tmp_pcb != NULL; l2cap_tmp_pcb = l2cap_tmp_pcb->next) { \
if(l2cap_tmp_pcb->next != NULL && l2cap_tmp_pcb->next == npcb) { \
l2cap_tmp_pcb->next = npcb->next; \
break; \
} \
} \
npcb->next = NULL; \
} while(0)
#endif /* LWBT_DEBUG */
/* The L2CAP SIG list macros */
extern struct l2cap_sig *l2cap_tmp_sig; /* Only used for temporary storage. */
#define L2CAP_SIG_REG(ursp_sigs, nsig) do { \
nsig->next = *ursp_sigs; \
*ursp_sigs = nsig; \
} while(0)
#define L2CAP_SIG_RMV(ursp_sigs, nsig) do { \
if(*ursp_sigs == nsig) { \
*ursp_sigs = (*ursp_sigs)->next; \
} else for(l2cap_tmp_sig = *ursp_sigs; l2cap_tmp_sig != NULL; l2cap_tmp_sig = l2cap_tmp_sig->next) { \
if(l2cap_tmp_sig->next != NULL && l2cap_tmp_sig->next == nsig) { \
l2cap_tmp_sig->next = nsig->next; \
break; \
} \
} \
nsig->next = NULL; \
} while(0)
/* The L2CAP incoming segments list macros */
extern struct l2cap_seg *l2cap_tmp_inseg; /* Only used for temporary storage. */
#define L2CAP_SEG_REG(segs, nseg) do { \
nseg->next = *segs; \
*segs = nseg; \
} while(0)
#define L2CAP_SEG_RMV(segs, nseg) do { \
if(*segs == nseg) { \
*segs = (*segs)->next; \
} else for(l2cap_tmp_inseg = *segs; l2cap_tmp_inseg != NULL; l2cap_tmp_inseg = l2cap_tmp_inseg->next) { \
if(l2cap_tmp_inseg->next != NULL && l2cap_tmp_inseg->next == nseg) { \
l2cap_tmp_inseg->next = nseg->next; \
break; \
} \
} \
nseg->next = NULL; \
} while(0)
#endif /* __LWBT_L2CAP_H__ */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -