Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/firewire/bebob/bebob_command.c
26439 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* bebob_command.c - driver for BeBoB based devices
4
*
5
* Copyright (c) 2013-2014 Takashi Sakamoto
6
*/
7
8
#include "./bebob.h"
9
10
int avc_audio_set_selector(struct fw_unit *unit, unsigned int subunit_id,
11
unsigned int fb_id, unsigned int num)
12
{
13
u8 *buf;
14
int err;
15
16
buf = kzalloc(12, GFP_KERNEL);
17
if (buf == NULL)
18
return -ENOMEM;
19
20
buf[0] = 0x00; /* AV/C CONTROL */
21
buf[1] = 0x08 | (0x07 & subunit_id); /* AUDIO SUBUNIT ID */
22
buf[2] = 0xb8; /* FUNCTION BLOCK */
23
buf[3] = 0x80; /* type is 'selector'*/
24
buf[4] = 0xff & fb_id; /* function block id */
25
buf[5] = 0x10; /* control attribute is CURRENT */
26
buf[6] = 0x02; /* selector length is 2 */
27
buf[7] = 0xff & num; /* input function block plug number */
28
buf[8] = 0x01; /* control selector is SELECTOR_CONTROL */
29
30
err = fcp_avc_transaction(unit, buf, 12, buf, 12,
31
BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
32
BIT(6) | BIT(7) | BIT(8));
33
if (err < 0)
34
;
35
else if (err < 9)
36
err = -EIO;
37
else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
38
err = -ENOSYS;
39
else if (buf[0] == 0x0a) /* REJECTED */
40
err = -EINVAL;
41
else
42
err = 0;
43
44
kfree(buf);
45
return err;
46
}
47
48
int avc_audio_get_selector(struct fw_unit *unit, unsigned int subunit_id,
49
unsigned int fb_id, unsigned int *num)
50
{
51
u8 *buf;
52
int err;
53
54
buf = kzalloc(12, GFP_KERNEL);
55
if (buf == NULL)
56
return -ENOMEM;
57
58
buf[0] = 0x01; /* AV/C STATUS */
59
buf[1] = 0x08 | (0x07 & subunit_id); /* AUDIO SUBUNIT ID */
60
buf[2] = 0xb8; /* FUNCTION BLOCK */
61
buf[3] = 0x80; /* type is 'selector'*/
62
buf[4] = 0xff & fb_id; /* function block id */
63
buf[5] = 0x10; /* control attribute is CURRENT */
64
buf[6] = 0x02; /* selector length is 2 */
65
buf[7] = 0xff; /* input function block plug number */
66
buf[8] = 0x01; /* control selector is SELECTOR_CONTROL */
67
68
err = fcp_avc_transaction(unit, buf, 12, buf, 12,
69
BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
70
BIT(6) | BIT(8));
71
if (err < 0)
72
;
73
else if (err < 9)
74
err = -EIO;
75
else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
76
err = -ENOSYS;
77
else if (buf[0] == 0x0a) /* REJECTED */
78
err = -EINVAL;
79
else if (buf[0] == 0x0b) /* IN TRANSITION */
80
err = -EAGAIN;
81
if (err < 0)
82
goto end;
83
84
*num = buf[7];
85
err = 0;
86
end:
87
kfree(buf);
88
return err;
89
}
90
91
static inline void
92
avc_bridgeco_fill_extension_addr(u8 *buf, u8 *addr)
93
{
94
buf[1] = addr[0];
95
memcpy(buf + 4, addr + 1, 5);
96
}
97
98
static inline void
99
avc_bridgeco_fill_plug_info_extension_command(u8 *buf, u8 *addr,
100
unsigned int itype)
101
{
102
buf[0] = 0x01; /* AV/C STATUS */
103
buf[2] = 0x02; /* AV/C GENERAL PLUG INFO */
104
buf[3] = 0xc0; /* BridgeCo extension */
105
avc_bridgeco_fill_extension_addr(buf, addr);
106
buf[9] = itype; /* info type */
107
}
108
109
int avc_bridgeco_get_plug_type(struct fw_unit *unit,
110
u8 addr[AVC_BRIDGECO_ADDR_BYTES],
111
enum avc_bridgeco_plug_type *type)
112
{
113
u8 *buf;
114
int err;
115
116
buf = kzalloc(12, GFP_KERNEL);
117
if (buf == NULL)
118
return -ENOMEM;
119
120
/* Info type is 'plug type'. */
121
avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x00);
122
123
err = fcp_avc_transaction(unit, buf, 12, buf, 12,
124
BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
125
BIT(6) | BIT(7) | BIT(9));
126
if (err < 0)
127
;
128
else if (err < 11)
129
err = -EIO;
130
else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
131
err = -ENOSYS;
132
else if (buf[0] == 0x0a) /* REJECTED */
133
err = -EINVAL;
134
else if (buf[0] == 0x0b) /* IN TRANSITION */
135
err = -EAGAIN;
136
if (err < 0)
137
goto end;
138
139
*type = buf[10];
140
err = 0;
141
end:
142
kfree(buf);
143
return err;
144
}
145
146
int avc_bridgeco_get_plug_ch_count(struct fw_unit *unit, u8 addr[AVC_BRIDGECO_ADDR_BYTES],
147
unsigned int *ch_count)
148
{
149
u8 *buf;
150
int err;
151
152
buf = kzalloc(12, GFP_KERNEL);
153
if (buf == NULL)
154
return -ENOMEM;
155
156
// Info type is 'plug type'.
157
avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x02);
158
159
err = fcp_avc_transaction(unit, buf, 12, buf, 12,
160
BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
161
BIT(6) | BIT(7) | BIT(9));
162
if (err < 0)
163
;
164
else if (err < 11)
165
err = -EIO;
166
else if (buf[0] == 0x08) // NOT IMPLEMENTED
167
err = -ENOSYS;
168
else if (buf[0] == 0x0a) // REJECTED
169
err = -EINVAL;
170
else if (buf[0] == 0x0b) // IN TRANSITION
171
err = -EAGAIN;
172
if (err < 0)
173
goto end;
174
175
*ch_count = buf[10];
176
err = 0;
177
end:
178
kfree(buf);
179
return err;
180
}
181
182
int avc_bridgeco_get_plug_ch_pos(struct fw_unit *unit,
183
u8 addr[AVC_BRIDGECO_ADDR_BYTES],
184
u8 *buf, unsigned int len)
185
{
186
int err;
187
188
/* Info type is 'channel position'. */
189
avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x03);
190
191
err = fcp_avc_transaction(unit, buf, 12, buf, 256,
192
BIT(1) | BIT(2) | BIT(3) | BIT(4) |
193
BIT(5) | BIT(6) | BIT(7) | BIT(9));
194
if (err < 0)
195
;
196
else if (err < 11)
197
err = -EIO;
198
else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
199
err = -ENOSYS;
200
else if (buf[0] == 0x0a) /* REJECTED */
201
err = -EINVAL;
202
else if (buf[0] == 0x0b) /* IN TRANSITION */
203
err = -EAGAIN;
204
if (err < 0)
205
goto end;
206
207
/* Pick up specific data. */
208
memmove(buf, buf + 10, err - 10);
209
err = 0;
210
end:
211
return err;
212
}
213
214
int avc_bridgeco_get_plug_section_type(struct fw_unit *unit,
215
u8 addr[AVC_BRIDGECO_ADDR_BYTES],
216
unsigned int id, u8 *type)
217
{
218
u8 *buf;
219
int err;
220
221
/* section info includes charactors but this module don't need it */
222
buf = kzalloc(12, GFP_KERNEL);
223
if (buf == NULL)
224
return -ENOMEM;
225
226
/* Info type is 'section info'. */
227
avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x07);
228
buf[10] = 0xff & ++id; /* section id */
229
230
err = fcp_avc_transaction(unit, buf, 12, buf, 12,
231
BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
232
BIT(6) | BIT(7) | BIT(9) | BIT(10));
233
if (err < 0)
234
;
235
else if (err < 12)
236
err = -EIO;
237
else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
238
err = -ENOSYS;
239
else if (buf[0] == 0x0a) /* REJECTED */
240
err = -EINVAL;
241
else if (buf[0] == 0x0b) /* IN TRANSITION */
242
err = -EAGAIN;
243
if (err < 0)
244
goto end;
245
246
*type = buf[11];
247
err = 0;
248
end:
249
kfree(buf);
250
return err;
251
}
252
253
int avc_bridgeco_get_plug_input(struct fw_unit *unit,
254
u8 addr[AVC_BRIDGECO_ADDR_BYTES], u8 input[7])
255
{
256
int err;
257
u8 *buf;
258
259
buf = kzalloc(18, GFP_KERNEL);
260
if (buf == NULL)
261
return -ENOMEM;
262
263
/* Info type is 'plug input'. */
264
avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x05);
265
266
err = fcp_avc_transaction(unit, buf, 16, buf, 16,
267
BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
268
BIT(6) | BIT(7));
269
if (err < 0)
270
;
271
else if (err < 16)
272
err = -EIO;
273
else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
274
err = -ENOSYS;
275
else if (buf[0] == 0x0a) /* REJECTED */
276
err = -EINVAL;
277
else if (buf[0] == 0x0b) /* IN TRANSITION */
278
err = -EAGAIN;
279
if (err < 0)
280
goto end;
281
282
memcpy(input, buf + 10, 5);
283
err = 0;
284
end:
285
kfree(buf);
286
return err;
287
}
288
289
int avc_bridgeco_get_plug_strm_fmt(struct fw_unit *unit,
290
u8 addr[AVC_BRIDGECO_ADDR_BYTES], u8 *buf,
291
unsigned int *len, unsigned int eid)
292
{
293
int err;
294
295
/* check given buffer */
296
if ((buf == NULL) || (*len < 12)) {
297
err = -EINVAL;
298
goto end;
299
}
300
301
buf[0] = 0x01; /* AV/C STATUS */
302
buf[2] = 0x2f; /* AV/C STREAM FORMAT SUPPORT */
303
buf[3] = 0xc1; /* Bridgeco extension - List Request */
304
avc_bridgeco_fill_extension_addr(buf, addr);
305
buf[10] = 0xff & eid; /* Entry ID */
306
307
err = fcp_avc_transaction(unit, buf, 12, buf, *len,
308
BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
309
BIT(6) | BIT(7) | BIT(10));
310
if (err < 0)
311
;
312
else if (err < 12)
313
err = -EIO;
314
else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
315
err = -ENOSYS;
316
else if (buf[0] == 0x0a) /* REJECTED */
317
err = -EINVAL;
318
else if (buf[0] == 0x0b) /* IN TRANSITION */
319
err = -EAGAIN;
320
else if (buf[10] != eid)
321
err = -EIO;
322
if (err < 0)
323
goto end;
324
325
/* Pick up 'stream format info'. */
326
memmove(buf, buf + 11, err - 11);
327
*len = err - 11;
328
err = 0;
329
end:
330
return err;
331
}
332
333