aboutsummaryrefslogtreecommitdiffstats
path: root/sound/firewire/bebob/bebob_command.c
diff options
context:
space:
mode:
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>2014-04-25 09:45:15 -0400
committerTakashi Iwai <tiwai@suse.de>2014-05-26 08:29:29 -0400
commiteb7b3a056cd8130e45c4494fb27de54d53ce9f31 (patch)
tree13971a8c6d72473e1c53b1a092041a148db176ed /sound/firewire/bebob/bebob_command.c
parentfd6f4b0dc167c6329a153ceeeb95bc41307156f3 (diff)
ALSA: bebob: Add commands and connections/streams management
This commit adds management functionality for connections and streams. BeBoB uses CMP to manage connections and uses AMDTP for streams. This commit also adds some BridgeCo's AV/C extension commands. There are some BridgeCo's AV/C extension commands but this commit just uses below commands to get device's capability and status: 1.Extended Plug Info commands - Plug Channel Position Specific Data - Plug Type Specific Data - Cluster(Section) Info Specific Data - Plug Input Specific Data 2.Extended Stream Format Information commands - Extended Stream Format Information Command - List Request For Extended Plug Info commands for Cluster Info Specific Data, I pick up 'section' instead of 'cluster' from document to prevent from misunderstanding because 'cluster' is also used in IEC 61883-6. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/firewire/bebob/bebob_command.c')
-rw-r--r--sound/firewire/bebob/bebob_command.c205
1 files changed, 205 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..6a017951a888
--- /dev/null
+++ b/sound/firewire/bebob/bebob_command.c
@@ -0,0 +1,205 @@
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
11static inline void
12avc_bridgeco_fill_extension_addr(u8 *buf, u8 *addr)
13{
14 buf[1] = addr[0];
15 memcpy(buf + 4, addr + 1, 5);
16}
17
18static inline void
19avc_bridgeco_fill_plug_info_extension_command(u8 *buf, u8 *addr,
20 unsigned int itype)
21{
22 buf[0] = 0x01; /* AV/C STATUS */
23 buf[2] = 0x02; /* AV/C GENERAL PLUG INFO */
24 buf[3] = 0xc0; /* BridgeCo extension */
25 avc_bridgeco_fill_extension_addr(buf, addr);
26 buf[9] = itype; /* info type */
27}
28
29int avc_bridgeco_get_plug_type(struct fw_unit *unit,
30 u8 addr[AVC_BRIDGECO_ADDR_BYTES],
31 enum avc_bridgeco_plug_type *type)
32{
33 u8 *buf;
34 int err;
35
36 buf = kzalloc(12, GFP_KERNEL);
37 if (buf == NULL)
38 return -ENOMEM;
39
40 /* Info type is 'plug type'. */
41 avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x00);
42
43 err = fcp_avc_transaction(unit, buf, 12, buf, 12,
44 BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
45 BIT(6) | BIT(7) | BIT(9));
46 if ((err >= 0) && (err < 8))
47 err = -EIO;
48 else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
49 err = -ENOSYS;
50 else if (buf[0] == 0x0a) /* REJECTED */
51 err = -EINVAL;
52 else if (buf[0] == 0x0b) /* IN TRANSITION */
53 err = -EAGAIN;
54 if (err < 0)
55 goto end;
56
57 *type = buf[10];
58 err = 0;
59end:
60 kfree(buf);
61 return err;
62}
63
64int avc_bridgeco_get_plug_ch_pos(struct fw_unit *unit,
65 u8 addr[AVC_BRIDGECO_ADDR_BYTES],
66 u8 *buf, unsigned int len)
67{
68 int err;
69
70 /* Info type is 'channel position'. */
71 avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x03);
72
73 err = fcp_avc_transaction(unit, buf, 12, buf, 256,
74 BIT(1) | BIT(2) | BIT(3) | BIT(4) |
75 BIT(5) | BIT(6) | BIT(7) | BIT(9));
76 if ((err >= 0) && (err < 8))
77 err = -EIO;
78 else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
79 err = -ENOSYS;
80 else if (buf[0] == 0x0a) /* REJECTED */
81 err = -EINVAL;
82 else if (buf[0] == 0x0b) /* IN TRANSITION */
83 err = -EAGAIN;
84 if (err < 0)
85 goto end;
86
87 /* Pick up specific data. */
88 memmove(buf, buf + 10, err - 10);
89 err = 0;
90end:
91 return err;
92}
93
94int avc_bridgeco_get_plug_section_type(struct fw_unit *unit,
95 u8 addr[AVC_BRIDGECO_ADDR_BYTES],
96 unsigned int id, u8 *type)
97{
98 u8 *buf;
99 int err;
100
101 /* section info includes charactors but this module don't need it */
102 buf = kzalloc(12, GFP_KERNEL);
103 if (buf == NULL)
104 return -ENOMEM;
105
106 /* Info type is 'section info'. */
107 avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x07);
108 buf[10] = 0xff & ++id; /* section id */
109
110 err = fcp_avc_transaction(unit, buf, 12, buf, 12,
111 BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
112 BIT(6) | BIT(7) | BIT(9) | BIT(10));
113 if ((err >= 0) && (err < 8))
114 err = -EIO;
115 else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
116 err = -ENOSYS;
117 else if (buf[0] == 0x0a) /* REJECTED */
118 err = -EINVAL;
119 else if (buf[0] == 0x0b) /* IN TRANSITION */
120 err = -EAGAIN;
121 if (err < 0)
122 goto end;
123
124 *type = buf[11];
125 err = 0;
126end:
127 kfree(buf);
128 return err;
129}
130
131int avc_bridgeco_get_plug_input(struct fw_unit *unit,
132 u8 addr[AVC_BRIDGECO_ADDR_BYTES], u8 input[7])
133{
134 int err;
135 u8 *buf;
136
137 buf = kzalloc(18, GFP_KERNEL);
138 if (buf == NULL)
139 return -ENOMEM;
140
141 /* Info type is 'plug input'. */
142 avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x05);
143
144 err = fcp_avc_transaction(unit, buf, 16, buf, 16,
145 BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
146 BIT(6) | BIT(7));
147 if ((err >= 0) && (err < 8))
148 err = -EIO;
149 else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
150 err = -ENOSYS;
151 else if (buf[0] == 0x0a) /* REJECTED */
152 err = -EINVAL;
153 else if (buf[0] == 0x0b) /* IN TRANSITION */
154 err = -EAGAIN;
155 if (err < 0)
156 goto end;
157
158 memcpy(input, buf + 10, 5);
159 err = 0;
160end:
161 kfree(buf);
162 return err;
163}
164
165int avc_bridgeco_get_plug_strm_fmt(struct fw_unit *unit,
166 u8 addr[AVC_BRIDGECO_ADDR_BYTES], u8 *buf,
167 unsigned int *len, unsigned int eid)
168{
169 int err;
170
171 /* check given buffer */
172 if ((buf == NULL) || (*len < 12)) {
173 err = -EINVAL;
174 goto end;
175 }
176
177 buf[0] = 0x01; /* AV/C STATUS */
178 buf[2] = 0x2f; /* AV/C STREAM FORMAT SUPPORT */
179 buf[3] = 0xc1; /* Bridgeco extension - List Request */
180 avc_bridgeco_fill_extension_addr(buf, addr);
181 buf[10] = 0xff & eid; /* Entry ID */
182
183 err = fcp_avc_transaction(unit, buf, 12, buf, *len,
184 BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
185 BIT(6) | BIT(7) | BIT(10));
186 if ((err >= 0) && (err < 12))
187 err = -EIO;
188 else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
189 err = -ENOSYS;
190 else if (buf[0] == 0x0a) /* REJECTED */
191 err = -EINVAL;
192 else if (buf[0] == 0x0b) /* IN TRANSITION */
193 err = -EAGAIN;
194 else if (buf[10] != eid)
195 err = -EIO;
196 if (err < 0)
197 goto end;
198
199 /* Pick up 'stream format info'. */
200 memmove(buf, buf + 11, err - 11);
201 *len = err - 11;
202 err = 0;
203end:
204 return err;
205}