aboutsummaryrefslogtreecommitdiffstats
path: root/sound/firewire/bebob/bebob_command.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/firewire/bebob/bebob_command.c')
-rw-r--r--sound/firewire/bebob/bebob_command.c282
1 files changed, 282 insertions, 0 deletions
diff --git a/sound/firewire/bebob/bebob_command.c b/sound/firewire/bebob/bebob_command.c
new file mode 100644
index 000000000000..9402cc15dbc1
--- /dev/null
+++ b/sound/firewire/bebob/bebob_command.c
@@ -0,0 +1,282 @@
1/*
2 * bebob_command.c - driver for BeBoB based devices
3 *
4 * Copyright (c) 2013-2014 Takashi Sakamoto
5 *
6 * Licensed under the terms of the GNU General Public License, version 2.
7 */
8
9#include "./bebob.h"
10
11int avc_audio_set_selector(struct fw_unit *unit, unsigned int subunit_id,
12 unsigned int fb_id, unsigned int num)
13{
14 u8 *buf;
15 int err;
16
17 buf = kzalloc(12, GFP_KERNEL);
18 if (buf == NULL)
19 return -ENOMEM;
20
21 buf[0] = 0x00; /* AV/C CONTROL */
22 buf[1] = 0x08 | (0x07 & subunit_id); /* AUDIO SUBUNIT ID */
23 buf[2] = 0xb8; /* FUNCTION BLOCK */
24 buf[3] = 0x80; /* type is 'selector'*/
25 buf[4] = 0xff & fb_id; /* function block id */
26 buf[5] = 0x10; /* control attribute is CURRENT */
27 buf[6] = 0x02; /* selector length is 2 */
28 buf[7] = 0xff & num; /* input function block plug number */
29 buf[8] = 0x01; /* control selector is SELECTOR_CONTROL */
30
31 err = fcp_avc_transaction(unit, buf, 12, buf, 12,
32 BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
33 BIT(6) | BIT(7) | BIT(8));
34 if (err > 0 && err < 9)
35 err = -EIO;
36 else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
37 err = -ENOSYS;
38 else if (buf[0] == 0x0a) /* REJECTED */
39 err = -EINVAL;
40 else if (err > 0)
41 err = 0;
42
43 kfree(buf);
44 return err;
45}
46
47int avc_audio_get_selector(struct fw_unit *unit, unsigned int subunit_id,
48 unsigned int fb_id, unsigned int *num)
49{
50 u8 *buf;
51 int err;
52
53 buf = kzalloc(12, GFP_KERNEL);
54 if (buf == NULL)
55 return -ENOMEM;
56
57 buf[0] = 0x01; /* AV/C STATUS */
58 buf[1] = 0x08 | (0x07 & subunit_id); /* AUDIO SUBUNIT ID */
59 buf[2] = 0xb8; /* FUNCTION BLOCK */
60 buf[3] = 0x80; /* type is 'selector'*/
61 buf[4] = 0xff & fb_id; /* function block id */
62 buf[5] = 0x10; /* control attribute is CURRENT */
63 buf[6] = 0x02; /* selector length is 2 */
64 buf[7] = 0xff; /* input function block plug number */
65 buf[8] = 0x01; /* control selector is SELECTOR_CONTROL */
66
67 err = fcp_avc_transaction(unit, buf, 12, buf, 12,
68 BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
69 BIT(6) | BIT(8));
70 if (err > 0 && err < 9)
71 err = -EIO;
72 else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
73 err = -ENOSYS;
74 else if (buf[0] == 0x0a) /* REJECTED */
75 err = -EINVAL;
76 else if (buf[0] == 0x0b) /* IN TRANSITION */
77 err = -EAGAIN;
78 if (err < 0)
79 goto end;
80
81 *num = buf[7];
82 err = 0;
83end:
84 kfree(buf);
85 return err;
86}
87
88static inline void
89avc_bridgeco_fill_extension_addr(u8 *buf, u8 *addr)
90{
91 buf[1] = addr[0];
92 memcpy(buf + 4, addr + 1, 5);
93}
94
95static inline void
96avc_bridgeco_fill_plug_info_extension_command(u8 *buf, u8 *addr,
97 unsigned int itype)
98{
99 buf[0] = 0x01; /* AV/C STATUS */
100 buf[2] = 0x02; /* AV/C GENERAL PLUG INFO */
101 buf[3] = 0xc0; /* BridgeCo extension */
102 avc_bridgeco_fill_extension_addr(buf, addr);
103 buf[9] = itype; /* info type */
104}
105
106int avc_bridgeco_get_plug_type(struct fw_unit *unit,
107 u8 addr[AVC_BRIDGECO_ADDR_BYTES],
108 enum avc_bridgeco_plug_type *type)
109{
110 u8 *buf;
111 int err;
112
113 buf = kzalloc(12, GFP_KERNEL);
114 if (buf == NULL)
115 return -ENOMEM;
116
117 /* Info type is 'plug type'. */
118 avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x00);
119
120 err = fcp_avc_transaction(unit, buf, 12, buf, 12,
121 BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
122 BIT(6) | BIT(7) | BIT(9));
123 if ((err >= 0) && (err < 8))
124 err = -EIO;
125 else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
126 err = -ENOSYS;
127 else if (buf[0] == 0x0a) /* REJECTED */
128 err = -EINVAL;
129 else if (buf[0] == 0x0b) /* IN TRANSITION */
130 err = -EAGAIN;
131 if (err < 0)
132 goto end;
133
134 *type = buf[10];
135 err = 0;
136end:
137 kfree(buf);
138 return err;
139}
140
141int avc_bridgeco_get_plug_ch_pos(struct fw_unit *unit,
142 u8 addr[AVC_BRIDGECO_ADDR_BYTES],
143 u8 *buf, unsigned int len)
144{
145 int err;
146
147 /* Info type is 'channel position'. */
148 avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x03);
149
150 err = fcp_avc_transaction(unit, buf, 12, buf, 256,
151 BIT(1) | BIT(2) | BIT(3) | BIT(4) |
152 BIT(5) | BIT(6) | BIT(7) | BIT(9));
153 if ((err >= 0) && (err < 8))
154 err = -EIO;
155 else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
156 err = -ENOSYS;
157 else if (buf[0] == 0x0a) /* REJECTED */
158 err = -EINVAL;
159 else if (buf[0] == 0x0b) /* IN TRANSITION */
160 err = -EAGAIN;
161 if (err < 0)
162 goto end;
163
164 /* Pick up specific data. */
165 memmove(buf, buf + 10, err - 10);
166 err = 0;
167end:
168 return err;
169}
170
171int avc_bridgeco_get_plug_section_type(struct fw_unit *unit,
172 u8 addr[AVC_BRIDGECO_ADDR_BYTES],
173 unsigned int id, u8 *type)
174{
175 u8 *buf;
176 int err;
177
178 /* section info includes charactors but this module don't need it */
179 buf = kzalloc(12, GFP_KERNEL);
180 if (buf == NULL)
181 return -ENOMEM;
182
183 /* Info type is 'section info'. */
184 avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x07);
185 buf[10] = 0xff & ++id; /* section id */
186
187 err = fcp_avc_transaction(unit, buf, 12, buf, 12,
188 BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
189 BIT(6) | BIT(7) | BIT(9) | BIT(10));
190 if ((err >= 0) && (err < 8))
191 err = -EIO;
192 else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
193 err = -ENOSYS;
194 else if (buf[0] == 0x0a) /* REJECTED */
195 err = -EINVAL;
196 else if (buf[0] == 0x0b) /* IN TRANSITION */
197 err = -EAGAIN;
198 if (err < 0)
199 goto end;
200
201 *type = buf[11];
202 err = 0;
203end:
204 kfree(buf);
205 return err;
206}
207
208int avc_bridgeco_get_plug_input(struct fw_unit *unit,
209 u8 addr[AVC_BRIDGECO_ADDR_BYTES], u8 input[7])
210{
211 int err;
212 u8 *buf;
213
214 buf = kzalloc(18, GFP_KERNEL);
215 if (buf == NULL)
216 return -ENOMEM;
217
218 /* Info type is 'plug input'. */
219 avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x05);
220
221 err = fcp_avc_transaction(unit, buf, 16, buf, 16,
222 BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
223 BIT(6) | BIT(7));
224 if ((err >= 0) && (err < 8))
225 err = -EIO;
226 else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
227 err = -ENOSYS;
228 else if (buf[0] == 0x0a) /* REJECTED */
229 err = -EINVAL;
230 else if (buf[0] == 0x0b) /* IN TRANSITION */
231 err = -EAGAIN;
232 if (err < 0)
233 goto end;
234
235 memcpy(input, buf + 10, 5);
236 err = 0;
237end:
238 kfree(buf);
239 return err;
240}
241
242int avc_bridgeco_get_plug_strm_fmt(struct fw_unit *unit,
243 u8 addr[AVC_BRIDGECO_ADDR_BYTES], u8 *buf,
244 unsigned int *len, unsigned int eid)
245{
246 int err;
247
248 /* check given buffer */
249 if ((buf == NULL) || (*len < 12)) {
250 err = -EINVAL;
251 goto end;
252 }
253
254 buf[0] = 0x01; /* AV/C STATUS */
255 buf[2] = 0x2f; /* AV/C STREAM FORMAT SUPPORT */
256 buf[3] = 0xc1; /* Bridgeco extension - List Request */
257 avc_bridgeco_fill_extension_addr(buf, addr);
258 buf[10] = 0xff & eid; /* Entry ID */
259
260 err = fcp_avc_transaction(unit, buf, 12, buf, *len,
261 BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
262 BIT(6) | BIT(7) | BIT(10));
263 if ((err >= 0) && (err < 12))
264 err = -EIO;
265 else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
266 err = -ENOSYS;
267 else if (buf[0] == 0x0a) /* REJECTED */
268 err = -EINVAL;
269 else if (buf[0] == 0x0b) /* IN TRANSITION */
270 err = -EAGAIN;
271 else if (buf[10] != eid)
272 err = -EIO;
273 if (err < 0)
274 goto end;
275
276 /* Pick up 'stream format info'. */
277 memmove(buf, buf + 11, err - 11);
278 *len = err - 11;
279 err = 0;
280end:
281 return err;
282}