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 && 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 47 int 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; 83 end: 84 kfree(buf); 85 return err; 86 } 87 88 static inline void 89 avc_bridgeco_fill_extension_addr(u8 *buf, u8 *addr) 90 { 91 buf[1] = addr[0]; 92 memcpy(buf + 4, addr + 1, 5); 93 } 94 95 static inline void 96 avc_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 106 int 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; 136 end: 137 kfree(buf); 138 return err; 139 } 140 141 int 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; 167 end: 168 return err; 169 } 170 171 int 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; 203 end: 204 kfree(buf); 205 return err; 206 } 207 208 int 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; 237 end: 238 kfree(buf); 239 return err; 240 } 241 242 int 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; 280 end: 281 return err; 282 } 283