1 /****************************************************************************** 2 * 3 * Copyright (C) 2002-2012 Broadcom Corporation 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at: 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 ******************************************************************************/ 18 19 /****************************************************************************** 20 * 21 * Utility functions to help build and parse SBC Codec Information Element 22 * and Media Payload. 23 * 24 ******************************************************************************/ 25 26 #include "bt_target.h" 27 #include <string.h> 28 #include "a2d_api.h" 29 #include "a2d_int.h" 30 #include "a2d_sbc.h" 31 #include "bt_utils.h" 32 33 #if (A2D_SBC_INCLUDED == TRUE) 34 35 /************************************************************************************************* 36 * SBC descramble code 37 * Purpose: to tie the SBC code with BTE/mobile stack code, 38 * especially for the case when the SBC is ported into a third-party Multimedia chip 39 * 40 * Algorithm: 41 * init process: all counters reset to 0, 42 * calculate base_index: (6 + s16NumOfChannels*s16NumOfSubBands/2) 43 * scramble side: the init process happens every time SBC_Encoder_Init() is called. 44 * descramble side: it would be nice to know if he "init" process has happened. 45 * alter the SBC SYNC word 0x9C (1001 1100) to 0x8C (1000 1100). 46 * 47 * scramble process: 48 * The CRC byte: 49 * Every SBC frame has a frame header. 50 * The 1st byte is the sync word and the following 2 bytes are about the stream format. 51 * They are supposed to be "constant" within a "song" 52 * The 4th byte is the CRC byte. The CRC byte is bound to be random. 53 * Derive 2 items from the CRC byte; one is the "use" bit, the other is the "index". 54 * 55 * SBC keeps 2 sets of "use" & "index"; derived the current and the previous frame. 56 * 57 * The "use" bit is any bit in SBC_PRTC_USE_MASK is set. 58 * If set, SBC uses the "index" from the current frame. 59 * If not set, SBC uses the "index" from the previous frame or 0. 60 * 61 * index = (CRC & 0x3) + ((CRC & 0x30) >> 2) // 8 is the max index 62 * 63 * if(index > 0) 64 * { 65 * p = &u8frame[base_index]; 66 * if((index&1)&&(u16PacketLength > (base_index+index*2))) 67 * { 68 * // odd index: swap 2 bytes 69 * tmp = p[index]; 70 * p[index] = p[index*2]; 71 * p[index*2] = tmp; 72 * } 73 * else 74 * { 75 * // even index: shift by 3 76 * tmp = (p[index] >> 3) + (p[index] << 5); 77 * p[index] = tmp; 78 * } 79 * } 80 * //else index is 0. The frame stays unaltered 81 * 82 */ 83 #define A2D_SBC_SYNC_WORD 0x9C 84 #define A2D_SBC_CRC_IDX 3 85 #define A2D_SBC_USE_MASK 0x64 86 #define A2D_SBC_SYNC_MASK 0x10 87 #define A2D_SBC_CIDX 0 88 #define A2D_SBC_LIDX 1 89 #define A2D_SBC_CH_M_BITS 0xC /* channel mode bits: 0: mono; 1 ch */ 90 #define A2D_SBC_SUBBAND_BIT 0x1 /* num of subband bit: 0:4; 1: 8 */ 91 92 #define A2D_SBC_GET_IDX(sc) (((sc) & 0x3) + (((sc) & 0x30) >> 2)) 93 94 typedef struct 95 { 96 UINT8 use; 97 UINT8 idx; 98 } tA2D_SBC_FR_CB; 99 100 typedef struct 101 { 102 tA2D_SBC_FR_CB fr[2]; 103 UINT8 index; 104 UINT8 base; 105 } tA2D_SBC_DS_CB; 106 107 static tA2D_SBC_DS_CB a2d_sbc_ds_cb; 108 /*int a2d_count = 0;*/ 109 /****************************************************************************** 110 ** 111 ** Function A2D_SbcChkFrInit 112 ** 113 ** Description check if need to init the descramble control block. 114 ** 115 ** Returns nothing. 116 ******************************************************************************/ 117 void A2D_SbcChkFrInit(UINT8 *p_pkt) 118 { 119 UINT8 fmt; 120 UINT8 num_chnl = 1; 121 UINT8 num_subband = 4; 122 123 if((p_pkt[0] & A2D_SBC_SYNC_MASK) == 0) 124 { 125 a2d_cb.use_desc = TRUE; 126 fmt = p_pkt[1]; 127 p_pkt[0] |= A2D_SBC_SYNC_MASK; 128 memset(&a2d_sbc_ds_cb, 0, sizeof(tA2D_SBC_DS_CB)); 129 if(fmt & A2D_SBC_CH_M_BITS) 130 num_chnl = 2; 131 if(fmt & A2D_SBC_SUBBAND_BIT) 132 num_subband = 8; 133 a2d_sbc_ds_cb.base = 6 + num_chnl*num_subband/2; 134 /*printf("base: %d\n", a2d_sbc_ds_cb.base); 135 a2d_count = 0;*/ 136 } 137 } 138 139 /****************************************************************************** 140 ** 141 ** Function A2D_SbcDescramble 142 ** 143 ** Description descramble the packet. 144 ** 145 ** Returns nothing. 146 ******************************************************************************/ 147 void A2D_SbcDescramble(UINT8 *p_pkt, UINT16 len) 148 { 149 tA2D_SBC_FR_CB *p_cur, *p_last; 150 UINT32 idx, tmp, tmp2; 151 152 if(a2d_cb.use_desc) 153 { 154 /* c2l */ 155 p_last = &a2d_sbc_ds_cb.fr[A2D_SBC_LIDX]; 156 p_cur = &a2d_sbc_ds_cb.fr[A2D_SBC_CIDX]; 157 p_last->idx = p_cur->idx; 158 p_last->use = p_cur->use; 159 /* getc */ 160 p_cur->use = p_pkt[A2D_SBC_CRC_IDX] & A2D_SBC_USE_MASK; 161 p_cur->idx = A2D_SBC_GET_IDX(p_pkt[A2D_SBC_CRC_IDX]); 162 a2d_sbc_ds_cb.index = (p_cur->use)?A2D_SBC_CIDX:A2D_SBC_LIDX; 163 /* 164 printf("%05d: ar[%02d]: x%02x, msk: x%02x, use: %s, idx: %02d, ", 165 a2d_count++, 166 A2D_SBC_CRC_IDX, p_pkt[A2D_SBC_CRC_IDX], A2D_SBC_USE_MASK, 167 (p_cur->use)?"cur":"lst", p_cur->idx); 168 */ 169 /* descramble */ 170 idx = a2d_sbc_ds_cb.fr[a2d_sbc_ds_cb.index].idx; 171 if(idx > 0) 172 { 173 p_pkt = &p_pkt[a2d_sbc_ds_cb.base]; 174 if((idx&1) && (len > (a2d_sbc_ds_cb.base+(idx<<1)))) 175 { 176 tmp2 = (idx<<1); 177 tmp = p_pkt[idx]; 178 p_pkt[idx] = p_pkt[tmp2]; 179 p_pkt[tmp2] = tmp; 180 /* 181 printf("tmp2: %02d, len: %d, idx: %d\n", 182 tmp2, len, a2d_sbc_ds_cb.fr[a2d_sbc_ds_cb.index].idx); 183 */ 184 } 185 else 186 { 187 tmp2 = p_pkt[idx]; 188 tmp = (tmp2>>3)+(tmp2<<5); 189 p_pkt[idx] = (UINT8)tmp; 190 /* 191 printf("tmp: x%02x, len: %d, idx: %d(cmp:%d)\n", 192 (UINT8)tmp2, len, a2d_sbc_ds_cb.fr[a2d_sbc_ds_cb.index].idx, 193 (a2d_sbc_ds_cb.base+(idx<<1))); 194 */ 195 } 196 } 197 /* 198 else 199 { 200 printf("!!!!\n"); 201 } 202 */ 203 } 204 } 205 206 /****************************************************************************** 207 ** 208 ** Function A2D_BldSbcInfo 209 ** 210 ** Description This function is called by an application to build 211 ** the SBC Media Codec Capabilities byte sequence 212 ** beginning from the LOSC octet. 213 ** Input Parameters: 214 ** media_type: Indicates Audio, or Multimedia. 215 ** 216 ** p_ie: The SBC Codec Information Element information. 217 ** 218 ** Output Parameters: 219 ** p_result: the resulting codec info byte sequence. 220 ** 221 ** Returns A2D_SUCCESS if function execution succeeded. 222 ** Error status code, otherwise. 223 ******************************************************************************/ 224 tA2D_STATUS A2D_BldSbcInfo(UINT8 media_type, tA2D_SBC_CIE *p_ie, UINT8 *p_result) 225 { 226 tA2D_STATUS status; 227 228 if( p_ie == NULL || p_result == NULL || 229 (p_ie->samp_freq & ~A2D_SBC_IE_SAMP_FREQ_MSK) || 230 (p_ie->ch_mode & ~A2D_SBC_IE_CH_MD_MSK) || 231 (p_ie->block_len & ~A2D_SBC_IE_BLOCKS_MSK) || 232 (p_ie->num_subbands & ~A2D_SBC_IE_SUBBAND_MSK) || 233 (p_ie->alloc_mthd & ~A2D_SBC_IE_ALLOC_MD_MSK) || 234 (p_ie->max_bitpool < p_ie->min_bitpool) || 235 (p_ie->max_bitpool < A2D_SBC_IE_MIN_BITPOOL) || 236 (p_ie->max_bitpool > A2D_SBC_IE_MAX_BITPOOL) || 237 (p_ie->min_bitpool < A2D_SBC_IE_MIN_BITPOOL) || 238 (p_ie->min_bitpool > A2D_SBC_IE_MAX_BITPOOL) ) 239 { 240 /* if any unused bit is set */ 241 status = A2D_INVALID_PARAMS; 242 } 243 else 244 { 245 status = A2D_SUCCESS; 246 *p_result++ = A2D_SBC_INFO_LEN; 247 *p_result++ = media_type; 248 *p_result++ = A2D_MEDIA_CT_SBC; 249 250 /* Media Codec Specific Information Element */ 251 *p_result++ = p_ie->samp_freq | p_ie->ch_mode; 252 253 *p_result++ = p_ie->block_len | p_ie->num_subbands | p_ie->alloc_mthd; 254 255 *p_result++ = p_ie->min_bitpool; 256 *p_result = p_ie->max_bitpool; 257 } 258 return status; 259 } 260 261 /****************************************************************************** 262 ** 263 ** Function A2D_ParsSbcInfo 264 ** 265 ** Description This function is called by an application to parse 266 ** the SBC Media Codec Capabilities byte sequence 267 ** beginning from the LOSC octet. 268 ** Input Parameters: 269 ** p_info: the byte sequence to parse. 270 ** 271 ** for_caps: TRUE, if the byte sequence is for get capabilities response. 272 ** 273 ** Output Parameters: 274 ** p_ie: The SBC Codec Information Element information. 275 ** 276 ** Returns A2D_SUCCESS if function execution succeeded. 277 ** Error status code, otherwise. 278 ******************************************************************************/ 279 tA2D_STATUS A2D_ParsSbcInfo(tA2D_SBC_CIE *p_ie, UINT8 *p_info, BOOLEAN for_caps) 280 { 281 tA2D_STATUS status; 282 UINT8 losc; 283 UINT8 mt; 284 285 if( p_ie == NULL || p_info == NULL) 286 status = A2D_INVALID_PARAMS; 287 else 288 { 289 losc = *p_info++; 290 mt = *p_info++; 291 /* If the function is called for the wrong Media Type or Media Codec Type */ 292 if(losc != A2D_SBC_INFO_LEN || *p_info != A2D_MEDIA_CT_SBC) 293 status = A2D_WRONG_CODEC; 294 else 295 { 296 p_info++; 297 p_ie->samp_freq = *p_info & A2D_SBC_IE_SAMP_FREQ_MSK; 298 p_ie->ch_mode = *p_info & A2D_SBC_IE_CH_MD_MSK; 299 p_info++; 300 p_ie->block_len = *p_info & A2D_SBC_IE_BLOCKS_MSK; 301 p_ie->num_subbands = *p_info & A2D_SBC_IE_SUBBAND_MSK; 302 p_ie->alloc_mthd = *p_info & A2D_SBC_IE_ALLOC_MD_MSK; 303 p_info++; 304 p_ie->min_bitpool = *p_info++; 305 p_ie->max_bitpool = *p_info; 306 status = A2D_SUCCESS; 307 if(p_ie->min_bitpool < A2D_SBC_IE_MIN_BITPOOL || p_ie->min_bitpool > A2D_SBC_IE_MAX_BITPOOL ) 308 status = A2D_BAD_MIN_BITPOOL; 309 310 if(p_ie->max_bitpool < A2D_SBC_IE_MIN_BITPOOL || p_ie->max_bitpool > A2D_SBC_IE_MAX_BITPOOL || 311 p_ie->max_bitpool < p_ie->min_bitpool) 312 status = A2D_BAD_MAX_BITPOOL; 313 314 if(for_caps == FALSE) 315 { 316 if(A2D_BitsSet(p_ie->samp_freq) != A2D_SET_ONE_BIT) 317 status = A2D_BAD_SAMP_FREQ; 318 if(A2D_BitsSet(p_ie->ch_mode) != A2D_SET_ONE_BIT) 319 status = A2D_BAD_CH_MODE; 320 if(A2D_BitsSet(p_ie->block_len) != A2D_SET_ONE_BIT) 321 status = A2D_BAD_BLOCK_LEN; 322 if(A2D_BitsSet(p_ie->num_subbands) != A2D_SET_ONE_BIT) 323 status = A2D_BAD_SUBBANDS; 324 if(A2D_BitsSet(p_ie->alloc_mthd) != A2D_SET_ONE_BIT) 325 status = A2D_BAD_ALLOC_MTHD; 326 } 327 } 328 } 329 return status; 330 } 331 332 /****************************************************************************** 333 ** 334 ** Function A2D_BldSbcMplHdr 335 ** 336 ** Description This function is called by an application to parse 337 ** the SBC Media Payload header. 338 ** Input Parameters: 339 ** frag: 1, if fragmented. 0, otherwise. 340 ** 341 ** start: 1, if the starting packet of a fragmented frame. 342 ** 343 ** last: 1, if the last packet of a fragmented frame. 344 ** 345 ** num: If frag is 1, this is the number of remaining fragments 346 ** (including this fragment) of this frame. 347 ** If frag is 0, this is the number of frames in this packet. 348 ** 349 ** Output Parameters: 350 ** p_dst: the resulting media payload header byte sequence. 351 ** 352 ** Returns void. 353 ******************************************************************************/ 354 void A2D_BldSbcMplHdr(UINT8 *p_dst, BOOLEAN frag, BOOLEAN start, BOOLEAN last, UINT8 num) 355 { 356 if(p_dst) 357 { 358 *p_dst = 0; 359 if(frag) 360 *p_dst |= A2D_SBC_HDR_F_MSK; 361 if(start) 362 *p_dst |= A2D_SBC_HDR_S_MSK; 363 if(last) 364 *p_dst |= A2D_SBC_HDR_L_MSK; 365 *p_dst |= (A2D_SBC_HDR_NUM_MSK & num); 366 } 367 } 368 369 /****************************************************************************** 370 ** 371 ** Function A2D_ParsSbcMplHdr 372 ** 373 ** Description This function is called by an application to parse 374 ** the SBC Media Payload header. 375 ** Input Parameters: 376 ** p_src: the byte sequence to parse.. 377 ** 378 ** Output Parameters: 379 ** frag: 1, if fragmented. 0, otherwise. 380 ** 381 ** start: 1, if the starting packet of a fragmented frame. 382 ** 383 ** last: 1, if the last packet of a fragmented frame. 384 ** 385 ** num: If frag is 1, this is the number of remaining fragments 386 ** (including this fragment) of this frame. 387 ** If frag is 0, this is the number of frames in this packet. 388 ** 389 ** Returns void. 390 ******************************************************************************/ 391 void A2D_ParsSbcMplHdr(UINT8 *p_src, BOOLEAN *p_frag, BOOLEAN *p_start, BOOLEAN *p_last, UINT8 *p_num) 392 { 393 if(p_src && p_frag && p_start && p_last && p_num) 394 { 395 *p_frag = (*p_src & A2D_SBC_HDR_F_MSK) ? TRUE: FALSE; 396 *p_start= (*p_src & A2D_SBC_HDR_S_MSK) ? TRUE: FALSE; 397 *p_last = (*p_src & A2D_SBC_HDR_L_MSK) ? TRUE: FALSE; 398 *p_num = (*p_src & A2D_SBC_HDR_NUM_MSK); 399 } 400 } 401 402 #else /* A2D_SBC_INCLUDED == TRUE */ 403 404 void A2D_SbcChkFrInit(UINT8 *p_pkt) 405 { 406 UNUSED(p_pkt); 407 } 408 409 void A2D_SbcDescramble(UINT8 *p_pkt, UINT16 len) 410 { 411 UNUSED(p_pkt); 412 UNUSED(len); 413 } 414 415 tA2D_STATUS A2D_BldSbcInfo(UINT8 media_type, tA2D_SBC_CIE *p_ie, 416 UINT8 *p_result) 417 { 418 UNUSED(media_type); 419 UNUSED(p_ie); 420 UNUSED(p_result); 421 return A2D_FAIL; 422 } 423 424 tA2D_STATUS A2D_ParsSbcInfo(tA2D_SBC_CIE *p_ie, UINT8 *p_info, 425 BOOLEAN for_caps) 426 { 427 UNUSED(p_ie); 428 UNUSED(p_info); 429 UNUSED(for_caps); 430 return A2D_FAIL; 431 } 432 433 void A2D_BldSbcMplHdr(UINT8 *p_dst, BOOLEAN frag, BOOLEAN start, 434 BOOLEAN last, UINT8 num) 435 { 436 UNUSED(p_dst); 437 UNUSED(frag); 438 UNUSED(start); 439 UNUSED(last); 440 UNUSED(num); 441 } 442 443 void A2D_ParsSbcMplHdr(UINT8 *p_src, BOOLEAN *p_frag, 444 BOOLEAN *p_start, BOOLEAN *p_last, 445 UINT8 *p_num) 446 { 447 UNUSED(p_src); 448 UNUSED(p_frag); 449 UNUSED(p_start); 450 UNUSED(p_last); 451 UNUSED(p_num); 452 } 453 454 455 #endif /* A2D_SBC_INCLUDED == TRUE */ 456