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