Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.15.
  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}