change PAD_ScanPads()s behaviour. the return value now contains a bitmask of the...
[libogc.git] / lwbt / l2cap.h
blob6ba450d7f1b5bb121e4f52ed3c00bf326291c004
1 #ifndef __L2CAP_H__
2 #define __L2CAP_H__
4 #include "bt.h"
5 #include "bd_addr.h"
7 /* Protocol and service multiplexor */
8 #define HIDP_PSM 0x0011
9 #define INTR_PSM 0x0013
11 /* Packet header lengths */
12 #define L2CAP_HDR_LEN 4
13 #define L2CAP_SIGHDR_LEN 4
14 #define L2CAP_CFGOPTHDR_LEN 2
16 /* Signals sizes */
17 #define L2CAP_CONN_REQ_SIZE 4
18 #define L2CAP_CONN_RSP_SIZE 8
19 #define L2CAP_CFG_RSP_SIZE 6
20 #define L2CAP_DISCONN_RSP_SIZE 4
22 #define L2CAP_CFG_REQ_SIZE 4
24 #define L2CAP_DISCONN_REQ_SIZE 4
25 #define L2CAP_CMD_REJ_SIZE 2
27 /* Signal codes */
28 #define L2CAP_CMD_REJ 0x01
29 #define L2CAP_CONN_REQ 0x02
30 #define L2CAP_CONN_RSP 0x03
31 #define L2CAP_CFG_REQ 0x04
32 #define L2CAP_CFG_RSP 0x05
33 #define L2CAP_DISCONN_REQ 0x06
34 #define L2CAP_DISCONN_RSP 0x07
35 #define L2CAP_ECHO_REQ 0x08
36 #define L2CAP_ECHO_RSP 0x09
37 #define L2CAP_INFO_REQ 0x0A
38 #define L2CAP_INFO_RSP 0x0B
40 /* Permanent channel identifiers */
41 #define L2CAP_NULL_CID 0x0000
42 #define L2CAP_SIG_CID 0x0001
43 #define L2CAP_CONNLESS_CID 0x0002
45 /* Channel identifiers values */
46 #define L2CAP_MIN_CID 0x0040
47 #define L2CAP_MAX_CID 0xFFFF
49 /* Configuration types */
50 #define L2CAP_CFG_MTU 0x01
51 #define L2CAP_FLUSHTO 0x02
52 #define L2CAP_QOS 0x03
54 /* Configuration types length */
55 #define L2CAP_MTU_LEN 2
56 #define L2CAP_FLUSHTO_LEN 2
57 #define L2CAP_QOS_LEN 22
59 /* Configuration response types */
60 #define L2CAP_CFG_SUCCESS 0x0000
61 #define L2CAP_CFG_UNACCEPT 0x0001
62 #define L2CAP_CFG_REJ 0x0002
63 #define L2CAP_CFG_UNKNOWN 0x0003
64 #define L2CAP_CFG_TIMEOUT 0xEEEE
66 /* QoS types */
67 #define L2CAP_QOS_NO_TRAFFIC 0x00
68 #define L2CAP_QOS_BEST_EFFORT 0x01
69 #define L2CAP_QOS_GUARANTEED 0x02
71 /* Command reject reasons */
72 #define L2CAP_CMD_NOT_UNDERSTOOD 0x0000
73 #define L2CAP_MTU_EXCEEDED 0x0001
74 #define L2CAP_INVALID_CID 0x0002
76 /* Connection response results */
77 #define L2CAP_CONN_SUCCESS 0x0000
78 #define L2CAP_CONN_PND 0x0001
79 #define L2CAP_CONN_REF_PSM 0x0002
80 #define L2CAP_CONN_REF_SEC 0x0003
81 #define L2CAP_CONN_REF_RES 0x0004
82 #define L2CAP_CONN_CFG_TO 0x0005 /* Implementation specific result */
84 /* Echo response results */
85 #define L2CAP_ECHO_RCVD 0x00
86 #define L2CAP_ECHO_TO 0x01
88 /* L2CAP segmentation */
89 #define L2CAP_ACL_START 0x02
90 #define L2CAP_ACL_CONT 0x01
92 /* L2CAP config default parameters */
93 #define L2CAP_CFG_DEFAULT_INMTU 672 /* Two Baseband DH5 packets (2*341=682) minus the Baseband ACL
94 headers (2*2=4) and L2CAP header (6) */
95 #define L2CAP_CFG_DEFAULT_OUTFLUSHTO 0xFFFF
97 /* L2CAP configuration parameter masks */
98 #define L2CAP_CFG_IR 0x01
99 #define L2CAP_CFG_IN_SUCCESS 0x02
100 #define L2CAP_CFG_OUT_SUCCESS 0x04
101 #define L2CAP_CFG_OUT_REQ 0x08
103 enum l2cap_state {
104 L2CAP_CLOSED, L2CAP_LISTEN, W4_L2CAP_CONNECT_RSP, W4_L2CA_CONNECT_RSP, L2CAP_CONFIG,
105 L2CAP_OPEN, W4_L2CAP_DISCONNECT_RSP, W4_L2CA_DISCONNECT_RSP
108 struct l2cap_hdr
110 u16_t len;
111 u16_t cid;
112 } ATTRIBUTE_PACKED;
114 struct l2cap_sig_hdr
116 u8_t code;
117 u8_t id;
118 u16_t len;
119 } ATTRIBUTE_PACKED;
121 struct l2cap_cfgopt_hdr
123 u8_t type;
124 u8_t len;
125 } ATTRIBUTE_PACKED;
127 /* This structure is used to represent L2CAP signals. */
128 struct l2cap_sig {
129 struct l2cap_sig *next; /* for the linked list, used when putting signals
130 on a queue */
131 struct pbuf *p; /* buffer containing data + L2CAP header */
132 u16_t sigid; /* Identification */
133 u16_t ertx; /* extended response timeout expired */
134 u8_t rtx; /* response timeout expired */
135 u8_t nrtx; /* number of retransmissions */
138 struct l2cap_cfg
140 u16_t inmtu;
141 u16_t outmtu;
142 u16_t influshto;
143 u16_t outflushto;
145 struct pbuf *opt;
147 u8_t cfgto;
148 u8_t l2capcfg;
151 struct l2cap_seg
153 struct l2cap_seg *next;
154 struct bd_addr bdaddr;
155 struct pbuf *p;
156 u16_t len;
157 struct l2cap_hdr *l2caphdr;
158 struct l2cap_pcb *pcb; /* The L2CAP Protocol Control Block */
161 struct l2cap_pcb {
162 struct l2cap_pcb *next; /* For the linked list */
164 enum l2cap_state state; /* L2CAP state */
166 void *callback_arg;
168 u16_t scid; /* Source CID */
169 u16_t dcid; /* Destination CID */
171 u16_t psm; /* Protocol/Service Multiplexer */
173 u16_t ursp_id; /* Signal id to respond to */
174 u8_t encrypt; /* encryption mode */
176 struct l2cap_sig *unrsp_sigs; /* List of sent but unresponded signals */
178 struct bd_addr remote_bdaddr;
180 struct l2cap_cfg cfg; /* Configuration parameters */
182 /* Upper layer to L2CAP confirmation functions */
184 /* Function to be called when a connection has been set up */
185 err_t (* l2ca_connect_cfm)(void *arg, struct l2cap_pcb *pcb, u16_t result, u16_t status);
186 /* Function to be called when a connection has been closed */
187 err_t (* l2ca_disconnect_cfm)(void *arg, struct l2cap_pcb *pcb);
188 /* Function to be called when a echo reply has been received */
189 err_t (* l2ca_pong)(void *arg, struct l2cap_pcb *pcb, u8_t result);
191 /* L2CAP to upper layer indication functions */
193 /* Function to be called when a connection indication event occurs */
194 err_t (* l2ca_connect_ind)(void *arg, struct l2cap_pcb *pcb, err_t err);
195 /* Function to be called when a disconnection indication event occurs */
196 err_t (* l2ca_disconnect_ind)(void *arg, struct l2cap_pcb *pcb, err_t err);
197 /* Function to be called when a timeout indication event occurs */
198 err_t (* l2ca_timeout_ind)(void *arg, struct l2cap_pcb *newpcb, err_t err);
199 /* Function to be called when a L2CAP connection receives data */
200 err_t (* l2ca_recv)(void *arg, struct l2cap_pcb *pcb, struct pbuf *p, err_t err);
203 struct l2cap_pcb_listen {
204 struct l2cap_pcb_listen *next; /* for the linked list */
206 enum l2cap_state state; /* L2CAP state */
208 void *callback_arg;
210 u16_t psm; /* Protocol/Service Multiplexer */
211 struct bd_addr bdaddr; /* Device Address */
213 /* Function to call when a connection request has been received
214 from a remote device. */
215 err_t (* l2ca_connect_ind)(void *arg, struct l2cap_pcb *pcb, err_t err);
218 #define l2cap_psm(pcb) ((pcb)->psm)
220 void l2cap_init();
221 struct l2cap_pcb* l2cap_new(void);
223 void lp_connect_ind(struct bd_addr *bdaddr);
224 void lp_connect_cfm(struct bd_addr *bdaddr, u8_t encrypt_mode, err_t err);
225 void lp_disconnect_ind(struct bd_addr *bdaddr,u8_t reason);
227 err_t l2ca_config_req(struct l2cap_pcb *pcb);
228 err_t l2ca_disconnect_req(struct l2cap_pcb *pcb, err_t (* l2ca_disconnect_cfm)(void *arg, struct l2cap_pcb *pcb));
229 err_t l2ca_datawrite(struct l2cap_pcb *pcb, struct pbuf *p);
230 err_t l2ca_ping(struct bd_addr *bdaddr, struct l2cap_pcb *tpcb,err_t (* l2ca_pong)(void *arg, struct l2cap_pcb *pcb, u8_t result));
231 err_t l2ca_connect_req(struct l2cap_pcb *pcb, struct bd_addr *bdaddr, u16_t psm, u8_t role_switch, err_t (* l2ca_connect_cfm)(void *arg, struct l2cap_pcb *lpcb,u16_t result, u16_t status));
233 void l2cap_tmr();
234 void l2cap_input(struct pbuf *p, struct bd_addr *bdaddr);
235 err_t l2cap_close(struct l2cap_pcb *pcb);
236 void l2cap_reset_all(void);
237 u8_t l2cap_next_sigid(void);
238 err_t l2cap_write(struct bd_addr *bdaddr, struct pbuf *p, u16_t len);
239 void l2cap_arg(struct l2cap_pcb *pcb, void *arg);
240 void l2cap_disconnect_ind(struct l2cap_pcb *pcb, err_t (* l2ca_disconnect_ind)(void *arg, struct l2cap_pcb *newpcb, err_t err));
241 void l2cap_timeout_ind(struct l2cap_pcb *pcb,err_t (* l2ca_timeout_ind)(void *arg, struct l2cap_pcb *newpcb, err_t err));
242 void l2cap_recv(struct l2cap_pcb *pcb, err_t (* l2ca_recv)(void *arg, struct l2cap_pcb *pcb, struct pbuf *p, err_t err));
243 err_t l2cap_signal(struct l2cap_pcb *pcb, u8_t code, u16_t ursp_id, struct bd_addr *remote_bdaddr, struct pbuf *data);
244 void l2cap_process_sig(struct pbuf *q, struct l2cap_hdr *l2caphdr, struct bd_addr *bdaddr);
246 err_t l2cap_rexmit_signal(struct l2cap_pcb *pcb, struct l2cap_sig *sig);
247 err_t l2cap_connect_ind(struct l2cap_pcb *npcb, struct bd_addr *bdaddr, u16_t psm,err_t (* l2ca_connect_ind)(void *arg, struct l2cap_pcb *pcb, err_t err));
249 void (*l2cap_disconnect_bb(void (*l2ca_disconnect_bb)(struct bd_addr *bdaddr,u8_t reason)))(struct bd_addr *bdaddr,u8_t reason);
251 /* Internal functions and global variables */
252 #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)))
253 #define L2CA_ACTION_DISCONN_CFM(pcb,ret) if((pcb)->l2ca_disconnect_cfm != NULL) (ret = (pcb)->l2ca_disconnect_cfm((pcb)->callback_arg,(pcb)))
254 #define L2CA_ACTION_PING_CFM(pcb,result,ret) if((pcb)->l2ca_pong != NULL) (ret = (pcb)->l2ca_pong((pcb)->callback_arg,(pcb),(result)))
256 #define L2CA_ACTION_CONN_IND(pcb,err,ret) if((pcb)->l2ca_connect_ind != NULL) (ret = (pcb)->l2ca_connect_ind((pcb)->callback_arg,(pcb),(err)))
257 #define L2CA_ACTION_DISCONN_IND(pcb,err,ret) \
258 if((pcb)->l2ca_disconnect_ind != NULL) { \
259 LOG("l2cap_disconnect_ind called\n"); \
260 (ret = (pcb)->l2ca_disconnect_ind((pcb)->callback_arg,(pcb),(err))); \
261 } else { \
262 l2cap_close(pcb); \
264 #define L2CA_ACTION_TO_IND(pcb,err,ret) if((pcb)->l2ca_timeout_ind != NULL) (ret = (pcb)->l2ca_timeout_ind((pcb)->callback_arg,(pcb),(err)))
265 #define L2CA_ACTION_RECV(pcb,p,err,ret) \
266 if((pcb)->l2ca_recv != NULL) { \
267 (ret = (pcb)->l2ca_recv((pcb)->callback_arg,(pcb),(p),(err))); \
268 } else { \
269 btpbuf_free(p); \
272 #define L2CAP_OPTH_TYPE(hdr) (((hdr)->type) & 0x7f)
273 #define L2CAP_OPTH_TOA(hdr) (((hdr)->type) >> 7)
275 /* The L2CAP PCB lists. */
276 extern struct l2cap_pcb_listen *l2cap_listen_pcbs; /* List of all L2CAP PCBs in CLOSED state
277 but awaing an incoming conn req. */
278 extern struct l2cap_pcb *l2cap_active_pcbs; /* List of all L2CAP PCBs that has
279 established or is about to establish
280 an ACL link */
282 extern struct l2cap_pcb *l2cap_tmp_pcb; /* Only used for temporary storage. */
284 #define L2CAP_REG(pcbs, npcb) do { \
285 u32 level; \
286 _CPU_ISR_Disable(level); \
287 npcb->next = *pcbs; \
288 *pcbs = npcb; \
289 _CPU_ISR_Restore(level); \
290 } while(0)
291 #define L2CAP_RMV(pcbs, npcb) do { \
292 u32 level; \
293 _CPU_ISR_Disable(level); \
294 if(*pcbs == npcb) { \
295 *pcbs = (*pcbs)->next; \
296 } else for(l2cap_tmp_pcb = *pcbs; l2cap_tmp_pcb != NULL; l2cap_tmp_pcb = l2cap_tmp_pcb->next) { \
297 if(l2cap_tmp_pcb->next != NULL && l2cap_tmp_pcb->next == npcb) { \
298 l2cap_tmp_pcb->next = npcb->next; \
299 break; \
302 npcb->next = NULL; \
303 _CPU_ISR_Restore(level); \
304 } while(0)
306 /* The L2CAP SIG list macros */
307 extern struct l2cap_sig *l2cap_tmp_sig; /* Only used for temporary storage. */
309 #define L2CAP_SIG_REG(ursp_sigs, nsig) do { \
310 u32 level; \
311 _CPU_ISR_Disable(level); \
312 nsig->next = *ursp_sigs; \
313 *ursp_sigs = nsig; \
314 _CPU_ISR_Restore(level); \
315 } while(0)
316 #define L2CAP_SIG_RMV(ursp_sigs, nsig) do { \
317 u32 level; \
318 _CPU_ISR_Disable(level); \
319 if(*ursp_sigs == nsig) { \
320 *ursp_sigs = (*ursp_sigs)->next; \
321 } else for(l2cap_tmp_sig = *ursp_sigs; l2cap_tmp_sig != NULL; l2cap_tmp_sig = l2cap_tmp_sig->next) { \
322 if(l2cap_tmp_sig->next != NULL && l2cap_tmp_sig->next == nsig) { \
323 l2cap_tmp_sig->next = nsig->next; \
324 break; \
327 nsig->next = NULL; \
328 _CPU_ISR_Restore(level); \
329 } while(0)
331 /* The L2CAP incoming segments list macros */
332 extern struct l2cap_seg *l2cap_tmp_inseg; /* Only used for temporary storage. */
334 #define L2CAP_SEG_REG(segs, nseg) do { \
335 u32 level; \
336 _CPU_ISR_Disable(level); \
337 nseg->next = *segs; \
338 *segs = nseg; \
339 _CPU_ISR_Restore(level); \
340 } while(0)
341 #define L2CAP_SEG_RMV(segs, nseg) do { \
342 u32 level; \
343 _CPU_ISR_Disable(level); \
344 if(*segs == nseg) { \
345 *segs = (*segs)->next; \
346 } else for(l2cap_tmp_inseg = *segs; l2cap_tmp_inseg != NULL; l2cap_tmp_inseg = l2cap_tmp_inseg->next) { \
347 if(l2cap_tmp_inseg->next != NULL && l2cap_tmp_inseg->next == nseg) { \
348 l2cap_tmp_inseg->next = nseg->next; \
349 break; \
352 nseg->next = NULL; \
353 _CPU_ISR_Restore(level); \
354 } while(0)
356 #endif