mtk8127 bt sco 路径


标签: bluetoothandroid
  958人阅读  评论(0)  收藏  举报
  分类:
 
audio(2)    android linux bluetooth(5) 

目录(?)[+]

1 mtk8127做蓝牙耳机时的系统框图

下面是bt sco的音频通道、音频codec、ap、modem等模块的连接框图。
mtk8127 bt sco 路径_第1张图片

下图是当mtk8127做handfree client时,bt sco的音频数据流走向(红色的中空箭头表示down link的语音数据流,紫色的中空箭头表示up link的语音数据流,)

\ mtk8127 bt sco 路径_第2张图片
bt sco音频设备在内核空间对应的设备节点为:/dev/ebc.通过misc_register系统函数来注册struct miscdevice设备。

代码路径:
mtk8127 bt sco 路径_第3张图片

2 数据结构

接收循环buffer对应的数据结构,其中蓝牙mcu子系统往这个循环buffer队列中写,对应的写下标为:iPacket_w;而驱动上层read接口,则是从这个循环buffer队列中读,对应的读下标为:iPacket_r,并且这个读写下标都不是反卷的,都是线性增长,当需要使用反卷的效果时,只需要执行如下操作即可:btsco.pRX->iPacket_w/iPacket_r & SCO_RX_PACKET_MASK
[cpp]  view plain  copy
 
  1. typedef struct  
  2. {  
  3.     kal_uint8     PacketBuf[SCO_RX_PACKER_BUF_NUM][SCO_RX_PLC_SIZE + BTSCO_CVSD_PACKET_VALID_SIZE];  
  4.     kal_bool        PacketValid[SCO_RX_PACKER_BUF_NUM];  
  5.     kal_int32    iPacket_w;  
  6.     kal_int32    iPacket_r;  
  7.     kal_uint8     TempPacketBuf[BT_SCO_PACKET_180];  
  8.     kal_bool      fOverflow;  
  9.     kal_uint32      u4BufferSize;   //RX packetbuf size  
  10. } BT_SCO_RX_T;  
由于驱动read是在应用所在的线程,而蓝牙mcu子系统往这个循环buffer队列中写(对应函数:AudDrv_BTCVSD_ReadFromBT)则是在中断线程中,所以他们存在同步和竞争的关系。驱动通过如下成员来控制
  • 自旋锁:auddrv_BTCVSDRX_lock
  • 等待队列:BTCVSD_Read_Wait_Queue/BTCVSD_read_wait_queue_flag
由于是在中断中,所以必须使用spin_lock_irqsave、spin_unlock_irqrestore形式来锁住和释放该自旋锁。

类似的发送循环buffer对应的数据结构为:
[cpp]  view plain  copy
 
  1. typedef struct  
  2. {  
  3.     kal_uint8     PacketBuf[SCO_TX_PACKER_BUF_NUM][SCO_TX_ENCODE_SIZE];  
  4.     kal_int32    iPacket_w;  
  5.     kal_int32    iPacket_r;  
  6.     kal_uint8     TempPacketBuf[BT_SCO_PACKET_180];  
  7.     kal_bool      fUnderflow;  
  8.     kal_uint32      u4BufferSize; //TX packetbuf size  
  9. } BT_SCO_TX_T;  
其中蓝牙的mcu子系统往这个循环buffer队列中读,对应的读下标为:iPacket_r;而驱动上层的write接口,则是从这个循环buffer队列中写,对应的写下表为:iPacket_w,同样这个读写下标都是线性增长的。当需要使用反卷的效果时,只需要执行如下操作即可:btsco.pTX->iPacket_w/iPacket_r & & SCO_TX_PACKET_MASK

由于驱动write是在应用所在的线程,而蓝牙mcu子系统从这个循环buffer队列中读(对应函数:AudDrv_BTCVSD_WriteToBT)则是在中断线程中,所以他们也存在同步和竞争的关系。驱动通过如下成员来控制
  • 自旋锁:auddrv_BTCVSDTX_lock
  • 等待队列:BTCVSD_Write_Wait_Queue/BTCVSD_write_wait_queue_flag
同样由于是在中断中,所以必须使用spin_lock_irqsave、spin_unlock_irqrestore形式来锁住和释放该自旋锁。


3 sco的接收流程

如下为read系统调用涉及的模块的数据流图,注意从receive package address register读出的地址只是一个偏移量,需要加上物理内存的开始地址对应的虚拟地址。
mtk8127 bt sco 路径_第4张图片
read的调用流程如下:
[cpp]  view plain  copy
 
  1. AudDrv_btcvsd_read  
  2. |------>read_size:(btsco.pRX->iPacket_w - btsco.pRX->iPacket_r) * (SCO_RX_PLC_SIZE + BTSCO_CVSD_PACKET_VALID_SIZE);  
  3. |------>BTSCORX_ReadIdx_tmp:(btsco.pRX->iPacket_r & SCO_RX_PACKET_MASK) * (SCO_RX_PLC_SIZE + BTSCO_CVSD_PACKET_VALID_SIZE);  
  4. |------>copy_to_user((void __user *)Read_Data_Ptr, (void *)((kal_uint8 *)btsco.pRX->PacketBuf + BTSCORX_ReadIdx_tmp), read_size)  
  5. |--->wait_event_interruptible_timeout(BTCVSD_Read_Wait_Queue, BTCVSD_read_wait_queue_flag...) // if have not enough data available to read,then sleep on wait queue  
中断处理中对应的read 系统调用对应的循环buffer的处理
[cpp]  view plain  copy
 
  1. AudDrv_BTCVSD_IRQ_handler  
  2. |---->uControl = *bt_hw_REG_CONTROL;  
  3. |----> uPacketType = (uControl >> 18) & 0x7;  
  4. |----> uPacketLength = (kal_uint32)btsco_PacketInfo[uPacketType][0];  
  5. |---->uPacketNumber = (kal_uint32)btsco_PacketInfo[uPacketType][1];  
  6. |---->uBufferCount_TX = (kal_uint32)btsco_PacketInfo[uPacketType][2];  
  7. |---->uBufferCount_RX = (kal_uint32)btsco_PacketInfo[uPacketType][3];  
  8. |---->AudDrv_BTCVSD_ReadFromBT(uPacketType, uPacketLength, uPacketNumber, uBufferCount_RX, uControl);  
  9.        |------>connsys_addr_rx = *bt_hw_REG_PACKET_R;  
  10.        |------>ap_addr_rx = (kal_uint32)BTSYS_SRAM_BANK2_BASE_ADDRESS + (connsys_addr_rx & 0xFFFF);  
  11.        |------>AudDrv_BTCVSD_DataTransfer(BT_SCO_DIRECT_BT2ARM, pSrc, btsco.pRX->TempPacketBuf, uPacketLength, uPacketNumber, btsco.uRXState);  
  12.        |------>memcpy(btsco.pRX->PacketBuf[btsco.pRX->iPacket_w & SCO_RX_PACKET_MASK], btsco.pRX->TempPacketBuf + (SCO_RX_PLC_SIZE * i), SCO_RX_PLC_SIZE);  
  13.        |------>btsco.pRX->iPacket_w++;  
  14. |---->*bt_hw_REG_CONTROL &= ~BT_CVSD_CLEAR;  
  15. |---->BTCVSD_read_wait_queue_flag = 1;  
  16. |---->wake_up_interruptible(&BTCVSD_Read_Wait_Queue);//alread received data from BT chip, so wake up read system call function to fetch data  

4 sco的发送流程

write的调用流程如下:
[cpp]  view plain  copy
 
  1. AudDrv_btcvsd_write  
  2. |------>copy_size = btsco.pTX->u4BufferSize - (btsco.pTX->iPacket_w - btsco.pTX->iPacket_r) * SCO_TX_ENCODE_SIZE; //  free space of TX packet buffer  
  3. |------>BTSCOTX_WriteIdx = (btsco.pTX->iPacket_w & SCO_TX_PACKET_MASK) * SCO_TX_ENCODE_SIZE;  
  4. |------>copy_from_user((void *)((kal_uint8 *)btsco.pTX->PacketBuf + BTSCOTX_WriteIdx), (const void __user *)data_w_ptr, copy_size)  
  5. |------>btsco.pTX->iPacket_w += copy_size / SCO_TX_ENCODE_SIZE;  
  6. |------>BTCVSD_write_wait_queue_flag = 0;  
  7. |------>wait_event_interruptible_timeout(BTCVSD_Write_Wait_Queue, BTCVSD_write_wait_queue_flag, ...)//if have not enough space available to write,then sleep on wait queue  
中断处理中对应的write系统调用对应的循环buffer的处理
[cpp]  view plain  copy
 
  1. AudDrv_BTCVSD_IRQ_handler  
  2. |---->uControl = *bt_hw_REG_CONTROL;  
  3. |---->uPacketType = (uControl >> 18) & 0x7;  
  4. |---->uPacketLength = (kal_uint32)btsco_PacketInfo[uPacketType][0];  
  5. |---->uPacketNumber = (kal_uint32)btsco_PacketInfo[uPacketType][1];  
  6. |---->uBufferCount_TX = (kal_uint32)btsco_PacketInfo[uPacketType][2];  
  7. |---->uBufferCount_RX = (kal_uint32)btsco_PacketInfo[uPacketType][3];  
  8. |---->AudDrv_BTCVSD_WriteToBT  
  9.          |--->memcpy((void *)(btsco.pTX->TempPacketBuf + (SCO_TX_ENCODE_SIZE * i)), (void *)(btsco.pTX->PacketBuf[btsco.pTX->iPacket_r & SCO_TX_PACKET_MASK]), SCO_TX_ENCODE_SIZE);  
  10.          |--->btsco.pTX->iPacket_r++;  
  11.          |--->connsys_addr_tx = *bt_hw_REG_PACKET_W;  
  12.          |--->pDst= (kal_uint32)BTSYS_SRAM_BANK2_BASE_ADDRESS + (connsys_addr_tx & 0xFFFF);  
  13.          |--->AudDrv_BTCVSD_DataTransfer(BT_SCO_DIRECT_ARM2BT, btsco.pTX->TempPacketBuf, pDst, uPacketLength, uPacketNumber, btsco.uTXState);  
  14. |----> *bt_hw_REG_CONTROL &= ~BT_CVSD_CLEAR;  
  15. |---->BTCVSD_write_wait_queue_flag = 1;  
  16. |---->wake_up_interruptible(&BTCVSD_Write_Wait_Queue);//already have free space for write syscall, so wake up write system call to fill data  

你可能感兴趣的:(android,BlueTooth)