aboutsummaryrefslogtreecommitdiff
path: root/include/net/bluetooth/amp.h
blob: 15d1817fe978623a01dd80980875d1308093fbb9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
/*
   Copyright (c) 2010-2012 The Linux Foundation.  All rights reserved.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License version 2 and
   only version 2 as published by the Free Software Foundation.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
*/

#ifndef __AMP_H
#define __AMP_H

/* AMP defaults */

#define A2MP_RSP_TIMEOUT        (8000)  /*  8 seconds */

/* A2MP Protocol */

/* A2MP command codes */
#define A2MP_COMMAND_REJ         0x01
#define A2MP_DISCOVER_REQ        0x02
#define A2MP_DISCOVER_RSP        0x03
#define A2MP_CHANGE_NOTIFY       0x04
#define A2MP_CHANGE_RSP          0x05
#define A2MP_GETINFO_REQ         0x06
#define A2MP_GETINFO_RSP         0x07
#define A2MP_GETAMPASSOC_REQ     0x08
#define A2MP_GETAMPASSOC_RSP     0x09
#define A2MP_CREATEPHYSLINK_REQ  0x0A
#define A2MP_CREATEPHYSLINK_RSP  0x0B
#define A2MP_DISCONNPHYSLINK_REQ 0x0C
#define A2MP_DISCONNPHYSLINK_RSP 0x0D

struct a2mp_cmd_hdr {
	__u8       code;
	__u8       ident;
	__le16     len;
} __packed;

struct a2mp_cmd_rej {
	__le16     reason;
} __packed;

struct a2mp_discover_req {
	__le16     mtu;
	__le16     ext_feat;
} __packed;

struct a2mp_cl {
	__u8       id;
	__u8       type;
	__u8       status;
} __packed;

struct a2mp_discover_rsp {
	__le16     mtu;
	__le16     ext_feat;
	struct a2mp_cl cl[0];
} __packed;

struct a2mp_getinfo_req {
	__u8       id;
} __packed;

struct a2mp_getinfo_rsp {
	__u8       id;
	__u8       status;
	__le32     total_bw;
	__le32     max_bw;
	__le32     min_latency;
	__le16     pal_cap;
	__le16     assoc_size;
} __packed;

struct a2mp_getampassoc_req {
	__u8       id;
} __packed;

struct a2mp_getampassoc_rsp {
	__u8       id;
	__u8       status;
	__u8       amp_assoc[0];
} __packed;

struct a2mp_createphyslink_req {
	__u8       local_id;
	__u8       remote_id;
	__u8       amp_assoc[0];
} __packed;

struct a2mp_createphyslink_rsp {
	__u8       local_id;
	__u8       remote_id;
	__u8       status;
} __packed;

struct a2mp_disconnphyslink_req {
	__u8       local_id;
	__u8       remote_id;
} __packed;

struct a2mp_disconnphyslink_rsp {
	__u8       local_id;
	__u8       remote_id;
	__u8       status;
} __packed;


/* L2CAP-AMP module interface */
int amp_init(void);
void amp_exit(void);

/* L2CAP-AMP fixed channel interface */
void amp_conn_ind(struct hci_conn *hcon, struct sk_buff *skb);

/* L2CAP-AMP link interface */
void amp_create_physical(struct l2cap_conn *conn, struct sock *sk);
void amp_accept_physical(struct l2cap_conn *conn, u8 id, struct sock *sk);

/* AMP manager internals */
struct amp_ctrl {
	struct  amp_mgr *mgr;
	__u8    id;
	__u8    type;
	__u8    status;
	__u32   total_bw;
	__u32   max_bw;
	__u32   min_latency;
	__u16   pal_cap;
	__u16   max_assoc_size;
};

struct amp_mgr {
	struct list_head list;
	__u8    discovered;
	__u8    next_ident;
	struct l2cap_conn *l2cap_conn;
	struct socket *a2mp_sock;
	struct list_head  ctx_list;
	rwlock_t       ctx_list_lock;
	struct amp_ctrl *ctrls;          /* @@ TODO s.b. list of controllers */
	struct sk_buff *skb;
	__u8   connected;
};

/* AMP Manager signalling contexts */
#define AMP_GETAMPASSOC       1
#define AMP_CREATEPHYSLINK    2
#define AMP_ACCEPTPHYSLINK    3
#define AMP_CREATELOGLINK     4
#define AMP_ACCEPTLOGLINK     5

/* Get AMP Assoc sequence */
#define AMP_GAA_INIT           0
#define AMP_GAA_RLAA_COMPLETE  1
struct amp_gaa_state {
	__u8       req_ident;
	__u16      len_so_far;
	__u8      *assoc;
};

/* Create Physical Link sequence */
#define AMP_CPL_INIT           0
#define AMP_CPL_DISC_RSP       1
#define AMP_CPL_GETINFO_RSP    2
#define AMP_CPL_GAA_RSP        3
#define AMP_CPL_CPL_STATUS     4
#define AMP_CPL_WRA_COMPLETE   5
#define AMP_CPL_CHANNEL_SELECT 6
#define AMP_CPL_RLA_COMPLETE   7
#define AMP_CPL_PL_COMPLETE    8
#define AMP_CPL_PL_CANCEL      9
struct amp_cpl_state {
	__u8       remote_id;
	__u16      max_len;
	__u8      *remote_assoc;
	__u8      *local_assoc;
	__u16      len_so_far;
	__u16      rem_len;
	__u8       phy_handle;
};

/* Accept Physical Link sequence */
#define AMP_APL_INIT           0
#define AMP_APL_APL_STATUS     1
#define AMP_APL_WRA_COMPLETE   2
#define AMP_APL_PL_COMPLETE    3
struct amp_apl_state {
	__u8       remote_id;
	__u8       req_ident;
	__u8      *remote_assoc;
	__u16      len_so_far;
	__u16      rem_len;
	__u8       phy_handle;
};

/* Create/Accept Logical Link sequence */
#define AMP_LOG_INIT         0
#define AMP_LOG_LL_STATUS    1
#define AMP_LOG_LL_COMPLETE  2
struct amp_log_state {
	__u8       remote_id;
};

/* Possible event types a context may wait for */
#define AMP_INIT            0x01
#define AMP_HCI_EVENT       0x02
#define AMP_HCI_CMD_CMPLT   0x04
#define AMP_HCI_CMD_STATUS  0x08
#define AMP_A2MP_RSP        0x10
#define AMP_KILLED          0x20
#define AMP_CANCEL          0x40
struct amp_ctx {
	struct list_head list;
	struct amp_mgr *mgr;
	struct hci_dev *hdev;
	__u8       type;
	__u8       state;
	union {
		struct amp_gaa_state gaa;
		struct amp_cpl_state cpl;
		struct amp_apl_state apl;
	} d;
	__u8 evt_type;
	__u8 evt_code;
	__u16 opcode;
	__u8 id;
	__u8 rsp_ident;

	struct sock *sk;
	struct amp_ctx *deferred;
	struct timer_list timer;
};

/* AMP work */
struct amp_work_pl_timeout {
	struct work_struct work;
	struct amp_ctrl *ctrl;
};
struct amp_work_ctx_timeout {
	struct work_struct work;
	struct amp_ctx *ctx;
};
struct amp_work_data_ready {
	struct work_struct work;
	struct sock *sk;
	int bytes;
};
struct amp_work_state_change {
	struct work_struct work;
	struct sock *sk;
};
struct amp_work_conn_ind {
	struct work_struct work;
	struct hci_conn *hcon;
	struct sk_buff *skb;
};
struct amp_work_create_physical {
	struct work_struct work;
	struct l2cap_conn *conn;
	u8 id;
	struct sock *sk;
};
struct amp_work_accept_physical {
	struct work_struct work;
	struct l2cap_conn *conn;
	u8 id;
	struct sock *sk;
};
struct amp_work_cmd_cmplt {
	struct work_struct work;
	struct hci_dev *hdev;
	u16 opcode;
	struct sk_buff *skb;
};
struct amp_work_cmd_status {
	struct work_struct work;
	struct hci_dev *hdev;
	u16 opcode;
	u8 status;
};
struct amp_work_event {
	struct work_struct work;
	struct hci_dev *hdev;
	u8 event;
	struct sk_buff *skb;
};

#endif /* __AMP_H */