forked from MCMrARM/mbp2018-bridge-drv
-
Notifications
You must be signed in to change notification settings - Fork 26
/
Copy pathprotocol.c
347 lines (318 loc) · 12.5 KB
/
protocol.c
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
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
#include "protocol.h"
#include "protocol_bce.h"
#include "audio.h"
int aaudio_msg_read_base(struct aaudio_msg *msg, struct aaudio_msg_base *base)
{
if (msg->size < sizeof(struct aaudio_msg_header) + sizeof(struct aaudio_msg_base) * 2)
return -EINVAL;
*base = *((struct aaudio_msg_base *) ((struct aaudio_msg_header *) msg->data + 1));
return 0;
}
#define READ_START(type) \
size_t offset = sizeof(struct aaudio_msg_header) + sizeof(struct aaudio_msg_base); (void)offset; \
if (((struct aaudio_msg_base *) ((struct aaudio_msg_header *) msg->data + 1))->msg != type) \
return -EINVAL;
#define READ_DEVID_VAR(devid) *devid = ((struct aaudio_msg_header *) msg->data)->device_id
#define READ_VAL(type) ({ offset += sizeof(type); *((type *) ((u8 *) msg->data + offset - sizeof(type))); })
#define READ_VAR(type, var) *var = READ_VAL(type)
int aaudio_msg_read_start_io_response(struct aaudio_msg *msg)
{
READ_START(AAUDIO_MSG_START_IO_RESPONSE);
return 0;
}
int aaudio_msg_read_stop_io_response(struct aaudio_msg *msg)
{
READ_START(AAUDIO_MSG_STOP_IO_RESPONSE);
return 0;
}
int aaudio_msg_read_update_timestamp(struct aaudio_msg *msg, aaudio_device_id_t *devid,
u64 *timestamp, u64 *update_seed)
{
READ_START(AAUDIO_MSG_UPDATE_TIMESTAMP);
READ_DEVID_VAR(devid);
READ_VAR(u64, timestamp);
READ_VAR(u64, update_seed);
return 0;
}
int aaudio_msg_read_get_property_response(struct aaudio_msg *msg, aaudio_object_id_t *obj,
struct aaudio_prop_addr *prop, void **data, u64 *data_size)
{
READ_START(AAUDIO_MSG_GET_PROPERTY_RESPONSE);
READ_VAR(aaudio_object_id_t, obj);
READ_VAR(u32, &prop->element);
READ_VAR(u32, &prop->scope);
READ_VAR(u32, &prop->selector);
READ_VAR(u64, data_size);
*data = ((u8 *) msg->data + offset);
/* offset += data_size; */
return 0;
}
int aaudio_msg_read_set_property_response(struct aaudio_msg *msg, aaudio_object_id_t *obj)
{
READ_START(AAUDIO_MSG_SET_PROPERTY_RESPONSE);
READ_VAR(aaudio_object_id_t, obj);
return 0;
}
int aaudio_msg_read_property_listener_response(struct aaudio_msg *msg, aaudio_object_id_t *obj,
struct aaudio_prop_addr *prop)
{
READ_START(AAUDIO_MSG_PROPERTY_LISTENER_RESPONSE);
READ_VAR(aaudio_object_id_t, obj);
READ_VAR(u32, &prop->element);
READ_VAR(u32, &prop->scope);
READ_VAR(u32, &prop->selector);
return 0;
}
int aaudio_msg_read_property_changed(struct aaudio_msg *msg, aaudio_device_id_t *devid, aaudio_object_id_t *obj,
struct aaudio_prop_addr *prop)
{
READ_START(AAUDIO_MSG_PROPERTY_CHANGED);
READ_DEVID_VAR(devid);
READ_VAR(aaudio_object_id_t, obj);
READ_VAR(u32, &prop->element);
READ_VAR(u32, &prop->scope);
READ_VAR(u32, &prop->selector);
return 0;
}
int aaudio_msg_read_set_input_stream_address_ranges_response(struct aaudio_msg *msg)
{
READ_START(AAUDIO_MSG_SET_INPUT_STREAM_ADDRESS_RANGES_RESPONSE);
return 0;
}
int aaudio_msg_read_get_input_stream_list_response(struct aaudio_msg *msg, aaudio_object_id_t **str_l, u64 *str_cnt)
{
READ_START(AAUDIO_MSG_GET_INPUT_STREAM_LIST_RESPONSE);
READ_VAR(u64, str_cnt);
*str_l = (aaudio_device_id_t *) ((u8 *) msg->data + offset);
/* offset += str_cnt * sizeof(aaudio_object_id_t); */
return 0;
}
int aaudio_msg_read_get_output_stream_list_response(struct aaudio_msg *msg, aaudio_object_id_t **str_l, u64 *str_cnt)
{
READ_START(AAUDIO_MSG_GET_OUTPUT_STREAM_LIST_RESPONSE);
READ_VAR(u64, str_cnt);
*str_l = (aaudio_device_id_t *) ((u8 *) msg->data + offset);
/* offset += str_cnt * sizeof(aaudio_object_id_t); */
return 0;
}
int aaudio_msg_read_set_remote_access_response(struct aaudio_msg *msg)
{
READ_START(AAUDIO_MSG_SET_REMOTE_ACCESS_RESPONSE);
return 0;
}
int aaudio_msg_read_get_device_list_response(struct aaudio_msg *msg, aaudio_device_id_t **dev_l, u64 *dev_cnt)
{
READ_START(AAUDIO_MSG_GET_DEVICE_LIST_RESPONSE);
READ_VAR(u64, dev_cnt);
*dev_l = (aaudio_device_id_t *) ((u8 *) msg->data + offset);
/* offset += dev_cnt * sizeof(aaudio_device_id_t); */
return 0;
}
#define WRITE_START_OF_TYPE(typev, devid) \
size_t offset = sizeof(struct aaudio_msg_header); (void) offset; \
((struct aaudio_msg_header *) msg->data)->type = (typev); \
((struct aaudio_msg_header *) msg->data)->device_id = (devid);
#define WRITE_START_COMMAND(devid) WRITE_START_OF_TYPE(AAUDIO_MSG_TYPE_COMMAND, devid)
#define WRITE_START_RESPONSE() WRITE_START_OF_TYPE(AAUDIO_MSG_TYPE_RESPONSE, 0)
#define WRITE_START_NOTIFICATION() WRITE_START_OF_TYPE(AAUDIO_MSG_TYPE_NOTIFICATION, 0)
#define WRITE_VAL(type, value) { *((type *) ((u8 *) msg->data + offset)) = value; offset += sizeof(value); }
#define WRITE_BIN(value, size) { memcpy((u8 *) msg->data + offset, value, size); offset += size; }
#define WRITE_BASE(type) WRITE_VAL(u32, type) WRITE_VAL(u32, 0)
#define WRITE_END() { msg->size = offset; }
void aaudio_msg_write_start_io(struct aaudio_msg *msg, aaudio_device_id_t dev)
{
WRITE_START_COMMAND(dev);
WRITE_BASE(AAUDIO_MSG_START_IO);
WRITE_END();
}
void aaudio_msg_write_stop_io(struct aaudio_msg *msg, aaudio_device_id_t dev)
{
WRITE_START_COMMAND(dev);
WRITE_BASE(AAUDIO_MSG_STOP_IO);
WRITE_END();
}
void aaudio_msg_write_get_property(struct aaudio_msg *msg, aaudio_device_id_t dev, aaudio_object_id_t obj,
struct aaudio_prop_addr prop, void *qualifier, u64 qualifier_size)
{
WRITE_START_COMMAND(dev);
WRITE_BASE(AAUDIO_MSG_GET_PROPERTY);
WRITE_VAL(aaudio_object_id_t, obj);
WRITE_VAL(u32, prop.element);
WRITE_VAL(u32, prop.scope);
WRITE_VAL(u32, prop.selector);
WRITE_VAL(u64, qualifier_size);
WRITE_BIN(qualifier, qualifier_size);
WRITE_END();
}
void aaudio_msg_write_set_property(struct aaudio_msg *msg, aaudio_device_id_t dev, aaudio_object_id_t obj,
struct aaudio_prop_addr prop, void *data, u64 data_size, void *qualifier, u64 qualifier_size)
{
WRITE_START_COMMAND(dev);
WRITE_BASE(AAUDIO_MSG_SET_PROPERTY);
WRITE_VAL(aaudio_object_id_t, obj);
WRITE_VAL(u32, prop.element);
WRITE_VAL(u32, prop.scope);
WRITE_VAL(u32, prop.selector);
WRITE_VAL(u64, data_size);
WRITE_BIN(data, data_size);
WRITE_VAL(u64, qualifier_size);
WRITE_BIN(qualifier, qualifier_size);
WRITE_END();
}
void aaudio_msg_write_property_listener(struct aaudio_msg *msg, aaudio_device_id_t dev, aaudio_object_id_t obj,
struct aaudio_prop_addr prop)
{
WRITE_START_COMMAND(dev);
WRITE_BASE(AAUDIO_MSG_PROPERTY_LISTENER);
WRITE_VAL(aaudio_object_id_t, obj);
WRITE_VAL(u32, prop.element);
WRITE_VAL(u32, prop.scope);
WRITE_VAL(u32, prop.selector);
WRITE_END();
}
void aaudio_msg_write_set_input_stream_address_ranges(struct aaudio_msg *msg, aaudio_device_id_t devid)
{
WRITE_START_COMMAND(devid);
WRITE_BASE(AAUDIO_MSG_SET_INPUT_STREAM_ADDRESS_RANGES);
WRITE_END();
}
void aaudio_msg_write_get_input_stream_list(struct aaudio_msg *msg, aaudio_device_id_t devid)
{
WRITE_START_COMMAND(devid);
WRITE_BASE(AAUDIO_MSG_GET_INPUT_STREAM_LIST);
WRITE_END();
}
void aaudio_msg_write_get_output_stream_list(struct aaudio_msg *msg, aaudio_device_id_t devid)
{
WRITE_START_COMMAND(devid);
WRITE_BASE(AAUDIO_MSG_GET_OUTPUT_STREAM_LIST);
WRITE_END();
}
void aaudio_msg_write_set_remote_access(struct aaudio_msg *msg, u64 mode)
{
WRITE_START_COMMAND(0);
WRITE_BASE(AAUDIO_MSG_SET_REMOTE_ACCESS);
WRITE_VAL(u64, mode);
WRITE_END();
}
void aaudio_msg_write_alive_notification(struct aaudio_msg *msg, u32 proto_ver, u32 msg_ver)
{
WRITE_START_NOTIFICATION();
WRITE_BASE(AAUDIO_MSG_NOTIFICATION_ALIVE);
WRITE_VAL(u32, proto_ver);
WRITE_VAL(u32, msg_ver);
WRITE_END();
}
void aaudio_msg_write_update_timestamp_response(struct aaudio_msg *msg)
{
WRITE_START_RESPONSE();
WRITE_BASE(AAUDIO_MSG_UPDATE_TIMESTAMP_RESPONSE);
WRITE_END();
}
void aaudio_msg_write_get_device_list(struct aaudio_msg *msg)
{
WRITE_START_COMMAND(0);
WRITE_BASE(AAUDIO_MSG_GET_DEVICE_LIST);
WRITE_END();
}
#define CMD_SHARED_VARS_NO_REPLY \
int status = 0; \
struct aaudio_send_ctx sctx;
#define CMD_SHARED_VARS \
CMD_SHARED_VARS_NO_REPLY \
struct aaudio_msg reply = aaudio_reply_alloc(); \
struct aaudio_msg *buf = &reply;
#define CMD_SEND_REQUEST(fn, ...) \
if ((status = aaudio_send_cmd_sync(a, &sctx, buf, 500, fn, ##__VA_ARGS__))) \
return status;
#define CMD_DEF_SHARED_AND_SEND(fn, ...) \
CMD_SHARED_VARS \
CMD_SEND_REQUEST(fn, ##__VA_ARGS__);
#define CMD_DEF_SHARED_NO_REPLY_AND_SEND(fn, ...) \
CMD_SHARED_VARS_NO_REPLY \
CMD_SEND_REQUEST(fn, ##__VA_ARGS__);
#define CMD_HNDL_REPLY_NO_FREE(fn, ...) \
status = fn(buf, ##__VA_ARGS__); \
return status;
#define CMD_HNDL_REPLY_AND_FREE(fn, ...) \
status = fn(buf, ##__VA_ARGS__); \
aaudio_reply_free(&reply); \
return status;
int aaudio_cmd_start_io(struct aaudio_device *a, aaudio_device_id_t devid)
{
CMD_DEF_SHARED_AND_SEND(aaudio_msg_write_start_io, devid);
CMD_HNDL_REPLY_AND_FREE(aaudio_msg_read_start_io_response);
}
int aaudio_cmd_stop_io(struct aaudio_device *a, aaudio_device_id_t devid)
{
CMD_DEF_SHARED_AND_SEND(aaudio_msg_write_stop_io, devid);
CMD_HNDL_REPLY_AND_FREE(aaudio_msg_read_stop_io_response);
}
int aaudio_cmd_get_property(struct aaudio_device *a, struct aaudio_msg *buf,
aaudio_device_id_t devid, aaudio_object_id_t obj,
struct aaudio_prop_addr prop, void *qualifier, u64 qualifier_size, void **data, u64 *data_size)
{
CMD_DEF_SHARED_NO_REPLY_AND_SEND(aaudio_msg_write_get_property, devid, obj, prop, qualifier, qualifier_size);
CMD_HNDL_REPLY_NO_FREE(aaudio_msg_read_get_property_response, &obj, &prop, data, data_size);
}
int aaudio_cmd_get_primitive_property(struct aaudio_device *a,
aaudio_device_id_t devid, aaudio_object_id_t obj,
struct aaudio_prop_addr prop, void *qualifier, u64 qualifier_size, void *data, u64 data_size)
{
int status;
struct aaudio_msg reply = aaudio_reply_alloc();
void *r_data;
u64 r_data_size;
if ((status = aaudio_cmd_get_property(a, &reply, devid, obj, prop, qualifier, qualifier_size,
&r_data, &r_data_size)))
goto finish;
if (r_data_size != data_size) {
status = -EINVAL;
goto finish;
}
memcpy(data, r_data, data_size);
finish:
aaudio_reply_free(&reply);
return status;
}
int aaudio_cmd_set_property(struct aaudio_device *a, aaudio_device_id_t devid, aaudio_object_id_t obj,
struct aaudio_prop_addr prop, void *qualifier, u64 qualifier_size, void *data, u64 data_size)
{
CMD_DEF_SHARED_AND_SEND(aaudio_msg_write_set_property, devid, obj, prop, data, data_size,
qualifier, qualifier_size);
CMD_HNDL_REPLY_AND_FREE(aaudio_msg_read_set_property_response, &obj);
}
int aaudio_cmd_property_listener(struct aaudio_device *a, aaudio_device_id_t devid, aaudio_object_id_t obj,
struct aaudio_prop_addr prop)
{
CMD_DEF_SHARED_AND_SEND(aaudio_msg_write_property_listener, devid, obj, prop);
CMD_HNDL_REPLY_AND_FREE(aaudio_msg_read_property_listener_response, &obj, &prop);
}
int aaudio_cmd_set_input_stream_address_ranges(struct aaudio_device *a, aaudio_device_id_t devid)
{
CMD_DEF_SHARED_AND_SEND(aaudio_msg_write_set_input_stream_address_ranges, devid);
CMD_HNDL_REPLY_AND_FREE(aaudio_msg_read_set_input_stream_address_ranges_response);
}
int aaudio_cmd_get_input_stream_list(struct aaudio_device *a, struct aaudio_msg *buf, aaudio_device_id_t devid,
aaudio_object_id_t **str_l, u64 *str_cnt)
{
CMD_DEF_SHARED_NO_REPLY_AND_SEND(aaudio_msg_write_get_input_stream_list, devid);
CMD_HNDL_REPLY_NO_FREE(aaudio_msg_read_get_input_stream_list_response, str_l, str_cnt);
}
int aaudio_cmd_get_output_stream_list(struct aaudio_device *a, struct aaudio_msg *buf, aaudio_device_id_t devid,
aaudio_object_id_t **str_l, u64 *str_cnt)
{
CMD_DEF_SHARED_NO_REPLY_AND_SEND(aaudio_msg_write_get_output_stream_list, devid);
CMD_HNDL_REPLY_NO_FREE(aaudio_msg_read_get_output_stream_list_response, str_l, str_cnt);
}
int aaudio_cmd_set_remote_access(struct aaudio_device *a, u64 mode)
{
CMD_DEF_SHARED_AND_SEND(aaudio_msg_write_set_remote_access, mode);
CMD_HNDL_REPLY_AND_FREE(aaudio_msg_read_set_remote_access_response);
}
int aaudio_cmd_get_device_list(struct aaudio_device *a, struct aaudio_msg *buf,
aaudio_device_id_t **dev_l, u64 *dev_cnt)
{
CMD_DEF_SHARED_NO_REPLY_AND_SEND(aaudio_msg_write_get_device_list);
CMD_HNDL_REPLY_NO_FREE(aaudio_msg_read_get_device_list_response, dev_l, dev_cnt);
}