Bluedroid From A2DP|source code reading note

转自http://yongbingchen.github.io/
 
//A2DP Client Side

1. static int adev_open_output_stream(struct audio_hw_device *dev,
	1.1 out->ctrl_fd = skt_connect(out, "/data/misc/bluedroid/.a2dp_ctrl")
		skt_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
		connect(fd, (struct sockaddr *) &addr, alen)
		setsockopt(skt_fd, SOL_SOCKET, SO_SNDBUF, (char*)&len, (int)sizeof(len));
	1.2 check_a2dp_ready(out)
		a2dp_command(out, A2DP_CTRL_CMD_CHECK_READY)
			//send command
			send(out->ctrl_fd, &cmd, 1, MSG_NOSIGNAL)
			//wait for response
			recv(out->ctrl_fd, &ack, 1, MSG_NOSIGNAL)
			if (ack != A2DP_CTRL_ACK_SUCCESS)
				return -1;


2. static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
	2.1 start_audio_datapath(out);
		a2dp_command(out, A2DP_CTRL_CMD_START);
		out->audio_fd = skt_connect(out, "/data/misc/bluedroid/.a2dp_data");
	2.2 sent = skt_write(out->audio_fd, buffer,  bytes);
		pfd.events = POLLOUT;
		poll(&pfd, 1, 500);//send timeout 500ms
		sent = send(fd, p, len, MSG_NOSIGNAL);
		
3. static int suspend_audio_datapath(struct a2dp_stream_out *out, bool standby)
	3.1 a2dp_command(out, A2DP_CTRL_CMD_SUSPEND)
	3.2 skt_disconnect(out->audio_fd);


	
//Init BT Adatper in Android system init:
3. In Bluedroid implementation,
		3.1 return implementation of bt_interface_t
			external/bluetooth/bluedroid/btif/src/bluetooth.c
			404 struct hw_module_t HAL_MODULE_INFO_SYM = {
			408     .id = BT_HARDWARE_MODULE_ID,

			400 static struct hw_module_methods_t bt_stack_module_methods = {
			401     .open = open_bluetooth_stack,

			385 static int open_bluetooth_stack (const struct hw_module_t* module, char const* name, struct hw_device_t** abstraction)
			387 {
			394     stack->get_bluetooth_interface = bluetooth__get_bluetooth_interface;

			//Android bt_interface_t API in <hardware/bluetooth.h>,here's Bluedroid implementation
			372 const bt_interface_t* bluetooth__get_bluetooth_interface ()
			376     return &bluetoothInterface;
	
			346 static const bt_interface_t bluetoothInterface = {
			347     sizeof(bt_interface_t),
			348     init,//must called before enable
						bt_utils_init();
						btif_init_bluetooth();
							external/bluetooth/bluedroid/btif/src/btif_core.c
							btif_config_init();
								load_cfg(); //CFG_PATH "/data/misc/bluedroid/" CFG_FILE_NAME "bt_config" CFG_FILE_EXT ".xml"
									btif_config_get_int("Local", "Adapter", "BluezMigrationDone", &bluez_migration_done);
						bte_main_boot_entry();//Entry point for BTE chip/stack initialization
							GKI_init();/* initialize OS */
							bte_main_in_hw_init();
								bt_hc_if = (bt_hc_interface_t *) bt_hc_get_interface()//BLUETOOTH HOST/CONTROLLER INTERFACE LIBRARY FUNCTIONS
									return &bluetoothHCLibInterface;
							bte_load_conf(BTE_STACK_CONF_FILE);//"/etc/bluetooth/bt_stack.conf"
						btif_fetch_local_bdaddr(&btif_local_bd_addr);
						//BTIF task handler managing all messages being passed Bluetooth HAL and BTA.
						GKI_create_task(btif_task, BTIF_TASK, BTIF_TASK_STR,(UINT16 *) ((UINT8 *)btif_task_stack + BTIF_TASK_STACK_SIZE),sizeof(btif_task_stack));
							
			349     enable,
						 bt_status_t btif_enable_bluetooth(void)//Performs chip power on and kickstarts OS scheduler
							bte_main_enable(btif_local_bd_addr.address);//Creates all the BTE tasks. 
								BTE_Init();
								int result = bt_hc_if->init(&hc_callbacks, local_addr);
									init_vnd_if(local_bdaddr);//Init BT hw module vendor specific API bt_vendor_interface_t, talk to bt hw module through this API.
									GLOBAL tHCI_IF *p_hci_if = &hci_h4_func_table;
									p_hci_if->init();
									userial_init();
									lpm_init();
									pthread_create(&hc_cb.worker_thread, &thread_attr, bt_hc_worker_thread, NULL) != 0)//create HCI TX/RX main thread. All HCI traffic come through here.
								bt_hc_if->set_power(BT_HC_CHIP_PWR_ON);
								//btu_task:This is the main task of the Bluetooth Upper Layers unit.It sits in a loop waiting for messages, and dispatches them to the appropiate handlers.
								GKI_create_task((TASKPTR)btu_task, BTU_TASK, BTE_BTU_TASK_STR,
					
			350     disable,
			351     cleanup,
			352     get_adapter_properties,
			353     get_adapter_property,
			354     set_adapter_property,
			355     get_remote_device_properties,
			356     get_remote_device_property,
			357     set_remote_device_property,
			358     get_remote_service_record,
			359     get_remote_services,
			360     start_discovery,
			361     cancel_discovery,
			362     create_bond,
			363     remove_bond,
			364     cancel_bond,
			365     pin_reply,
			366     ssp_reply,
			367     get_profile_interface,

			

155 ** Description      This is the main task of the Bluetooth Upper Layers unit.
156 **                  It sits in a loop waiting for messages, and dispatches them
157 **                  to the appropiate handlers.
162 BTU_API UINT32 btu_task (UINT32 param)
174     /* Initialize the mandatory core stack control blocks
175        (BTU, BTM, L2CAP, and SDP)
176      */
177     btu_init_core();
179     /* Initialize any optional stack components */
180     BTE_InitStack();
193     /* Send a startup evt message to BTIF_TASK to kickstart the init procedure */
194     GKI_send_event(BTIF_TASK, BT_EVT_TRIGGER_STACK_INIT);
227                     case BT_EVT_TO_BTU_HCI_EVT:
228                         btu_hcif_process_event ((UINT8)(p_msg->event & BT_SUB_EVT_MASK), p_msg);
229                         GKI_freebuf(p_msg);
236                         break;
237
238                     case BT_EVT_TO_BTU_HCI_CMD:
239                         btu_hcif_send_cmd ((UINT8)(p_msg->event & BT_SUB_EVT_MASK), p_msg);
240                         break;
211                     case BT_EVT_TO_BTU_HCI_ACL:
212                         /* All Acl Data goes to L2CAP */
213                         l2c_rcv_acl_data (p_msg);
214                         break;
	
		



//How Android initiate Bluetooth Adapter API:
	D/AdapterServiceConfig( 2161): Adding A2dpService
	D/AdapterServiceConfig( 2161): Adding HidService
	packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp
	static void classInitNative(JNIEnv* env, jclass clazz)
		err = hw_get_module(BT_STACK_MODULE_ID, (hw_module_t const**)&module);
		err = module->methods->open(module, id, &abstraction);
		const bt_interface_t* sBluetoothInterface = ((bluetooth_module_t*)abstraction)->get_bluetooth_interface();//bt_interface_t API defined in <hardware/bluetooth.h>

	static void initNative(JNIEnv *env, jobject object) {
		int ret = sBluetoothInterface->init(&sBluetoothCallbacks);
		const btsock_interface_t *sBluetoothSocketInterface = (btsock_interface_t *)sBluetoothInterface->get_profile_interface(BT_PROFILE_SOCKETS_ID);
		//btsock_interface_t API defined in <hardware/bt_sock.h>, Represents the standard BT SOCKET interface
		//listen(): listen to a rfcomm uuid or channel.
		//connect():connect to a rfcomm uuid channel of remote device



//Incoming data path
0. Init vendor (BT chip vendor, like MRVL/TI) implement of bt_vendor_interface_t interface.
	187 void init_vnd_if(unsigned char *local_bdaddr)
			dlhandle = dlopen("libbt-vendor.so", RTLD_NOW);				
			GLOBAL bt_vendor_interface_t *bt_vnd_if = (bt_vendor_interface_t *) dlsym(dlhandle, "BLUETOOTH_VENDOR_LIB_INTERFACE");
			bt_vnd_if->init(&vnd_callbacks, local_bdaddr);
			
	306 uint8_t userial_open(uint8_t port)
			result = bt_vendor_interface_t * bt_vnd_if->op(BT_VND_OP_USERIAL_OPEN, &fd_array);
				int bt_vnd_mrvl_if_op(bt_vendor_opcode_t opcode, void *param)
					mchar_fd = open("/dev/mbtchar0", O_RDWR);
	363     pthread_create(&(userial_cb.read_thread), &thread_attr, userial_read_thread, NULL) != 0 );

1. Got a packet from hardware device driver, in HCI layer.
bluedroid/hci/src/userial.c:210 static void *userial_read_thread(void *arg)
	rx_length = select_read(userial_cb.fd, p, READ_LIMIT);
		ret = read(fd, pbuf, (size_t)len);
	utils_enqueue(&(userial_cb.rx_q), p_buf);
	//bluedroid/hci/src/bt_hci_bdroid.c
	bthc_signal_event(HC_EVENT_RX);

2. Transfer this to L2CAP layer.
bluedroid/hci/src/bt_hci_bdroid.c	
339 static void *bt_hc_worker_thread(void *arg)
	if (events & HC_EVENT_RX)
		 p_hci_if->rcv();
			uint16_t hci_h4_receive_msg(void)//Construct HCI EVENT/ACL packets and send them to stack
 957             if (p_cb->p_rcv_msg->event != MSG_HC_TO_STACK_HCI_ACL)
 958                 btsnoop_capture(p_cb->p_rcv_msg, TRUE);
 959
 960             if (p_cb->p_rcv_msg->event == MSG_HC_TO_STACK_HCI_EVT)
 961                 intercepted = internal_event_intercept();//intercept the event if it is the result of an early issued internal command.
						p_cb->int_cmd[p_cb->int_cmd_rd_idx].cback(p_cb->p_rcv_msg);//deactive timer here? NO
 965                 bt_hc_cbacks->data_ind((TRANSAC) p_cb->p_rcv_msg, (char *) (p_cb->p_rcv_msg + 1), p_cb->p_rcv_msg->len + BT_HC_HDR_SIZE);
							bluedroid/main/bte_main.c:504 static int data_ind(TRANSAC transac, char *p_buf, int len)
								GKI_send_msg (BTU_TASK, BTU_HCI_RCV_MBOX, transac);


3. Process this in L2CAP layer							
162 BTU_API UINT32 btu_task (UINT32 param)
206             while ((p_msg = (BT_HDR *) GKI_read_mbox (BTU_HCI_RCV_MBOX)) != NULL)
207             {
208                 /* Determine the input message type. */
209                 switch (p_msg->event & BT_EVT_MASK)
210                 {
211                     case BT_EVT_TO_BTU_HCI_ACL:
212                         /* All Acl Data goes to L2CAP */
213                         l2c_rcv_acl_data (p_msg);//bluedroid/stack/l2cap/l2c_main.c

			
//Init A2DP server
04-25 01:56:30.530 I/BluetoothA2dpServiceJni( 2093): classInitNative: succeeds
packages/apps/Bluetooth/jni/com_android_bluetooth_a2dp.cpp
137 static void initNative(JNIEnv *env, jobject object)
	GLOBAL const btav_interface_t *sBluetoothA2dpInterface = (btav_interface_t *)btInf->get_profile_interface(BT_PROFILE_ADVANCED_AUDIO_ID);
	sBluetoothA2dpInterface->init(&sBluetoothA2dpCallbacks);
		external/bluetooth/bluedroid/btif/src/btif_av.c
		725 static bt_status_t init(btav_callbacks_t* callbacks )
			686 int btif_a2dp_start_media_task(void)
				GKI_create_task((TASKPTR)btif_media_task, A2DP_MEDIA_TASK,
			btif_enable_service(BTA_A2DP_SERVICE_ID);//Upon BT enable, BTIF core shall invoke the BTA APIs to enable the profiles
			
			
external/bluetooth/bluedroid/btif/src/btif_media_task.c
//Task for SBC encoder.  This task receives an event when the waveIn interface has a pcm data buffer ready.  On receiving the event, handle all ready pcm data buffers.  If stream is started, run the SBC encoder on each chunk of pcm samples and build an output packet consisting of one or more encoded SBC frames.
1066 int btif_media_task(void *p)
1073     btif_media_task_init();
1044     UIPC_Init(NULL);
			606 UDRV_API void UIPC_Init(void *p_data)
				569 int uipc_start_main_server_thread(void)
					pthread_create(&uipc_main.tid, (const pthread_attr_t *) NULL, (void*)uipc_read_task, NULL)
1047     UIPC_Open(UIPC_CH_ID_AV_CTRL , btif_a2dp_ctrl_cb);
			uipc_setup_server_locked(ch_id, A2DP_CTRL_PATH, p_cback);//This is the control socket that listen on A2DP client.
1079     while (1)//A2DP event loop 
1080     {
1085         if (event & BTIF_MEDIA_TASK_CMD)
1090                 btif_media_task_handle_cmd(p_msg);
1093
1094         if (event & BTIF_MEDIA_TASK_DATA)
1099                 btif_media_task_handle_media(p_msg);
1102
1103         if (event & BTIF_MEDIA_AA_TASK_TIMER)
1105             /* advance audio timer expiration */
1106             btif_media_task_aa_handle_timer();


//Connect a A2DP remote device
1. Android system will try to reconnect paired A2DP device automatically after BT enable.
04-25 01:56:31.080 D/BluetoothAdapterService( 2093): Auto Connecting A2DP Profile with device 50:C9:71:0D:D2:D9
	packages/apps/Bluetooth/jni/com_android_bluetooth_a2dp.cpp	
	static jboolean connectA2dpNative(JNIEnv *env, jobject object, jbyteArray address)
		const bt_interface_t* btInf= getBluetoothInterface();
		const btav_interface_t *sBluetoothA2dpInterface = (btav_interface_t *)btInf->get_profile_interface(BT_PROFILE_ADVANCED_AUDIO_ID);
		status = sBluetoothA2dpInterface->connect((bt_bdaddr_t *)addr)
			//external/bluetooth/bluedroid/btif/src/btif_av.c
			btif_queue_connect(UUID_SERVCLASS_AUDIO_SOURCE, bd_addr, connect_int);//This will trigger an event in btu_task, now the caller thread returned.
				GKI_send_msg(BTIF_TASK, BTU_BTIF_MBOX, p_msg);

2. This will later trigger a A2DP server event API_CONNECT_REQ_EVT in state CCB_IDLE_ST:
05-02 01:54:33.342 I/bt-avp  ( 2093): CCB ccb=0 event=API_CONNECT_REQ_EVT state=CCB_IDLE_ST

3. A2DP server handle this event in bellow two actions:
external/bluetooth/bluedroid/stack/avdt/avdt_ccb.c
129 const UINT8 avdt_ccb_st_idle[][AVDT_CCB_NUM_COLS] = {
130 /* Event                      Action 1                    Action 2                    Next state */
139 /* API_CONNECT_REQ_EVT */    {AVDT_CCB_SET_CONN,          AVDT_CCB_CHAN_OPEN,         AVDT_CCB_OPENING_ST},

3.1 Set CCB variables associated with AVDT_ConnectReq().
996 void avdt_ccb_set_conn(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
	BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_AVDTP, p_data->connect.sec_mask,AVDT_PSM, BTM_SEC_PROTO_AVDT, AVDT_CHAN_SIG);

3.2 initiate a signaling channel connection.
87 void avdt_ccb_chan_open(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
					BTM_SetOutService(p_ccb->peer_addr, BTM_SEC_SERVICE_AVDTP, AVDT_CHAN_SIG);
					avdt_ad_open_req(AVDT_CHAN_SIG, p_ccb, NULL, AVDT_INT);
						lcid = L2CA_ConnectReq(AVDT_PSM, p_ccb->peer_addr)//Note that the connection is not established at this time, but connection establishment gets started. The callback function will be invoked when connection establishes or fails.

4 How L2CAP handle this channel connection:
external/bluetooth/bluedroid/stack/l2cap/l2c_api.c						
229 UINT16 L2CA_ErtmConnectReq (UINT16 psm, BD_ADDR p_bd_addr, tL2CAP_ERTM_INFO *p_ertm_info)						
	p_lcb = l2cu_allocate_lcb (p_bd_addr, FALSE);
	l2cu_create_conn(p_lcb);//This function initiates an acl connection via HCI
		2180 BOOLEAN l2cu_create_conn_after_switch (tL2C_LCB *p_lcb)
			//external/bluetooth/bluedroid/stack/hcic/hcicmds.c
			btsnd_hcic_create_conn (p_lcb->remote_bd_addr,HCI_PKT_TYPES_MASK_DM1 + HCI_PKT_TYPES_MASK_DH1,page_scan_rep_mode,page_scan_mode,clock_offset,allow_switch));
				HCI_CMD_TO_LOWER(p_buf);
					//external/bluetooth/bluedroid/main/bte_main.c
					bt_hc_if->transmit_buf((TRANSAC)p_msg, \ (char *) (p_msg + 1), \p_msg->len);
						utils_enqueue(&tx_q, (void *) transac);
						 bthc_signal_event(HC_EVENT_TX);
			btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK,L2CAP_LINK_CONNECT_TOUT);
	if (p_lcb->link_state == LST_CONNECTED)
		l2c_csm_execute (p_ccb, L2CEVT_L2CA_CONNECT_REQ, NULL);


//Data transfer from A2DP client to remote device.
1. A2DP client write to A2DP data socket will trigger API_WRITE_REQ_EVT in SCB_STREAM_ST state:
05-02 01:14:03.134 I/bt-avp  ( 2139): SCB hdl=1 event=1/API_WRITE_REQ_EVT state=SCB_STREAM_ST
394 /* state table for streaming state */
395 const UINT8 avdt_scb_st_stream[][AVDT_SCB_NUM_COLS] = {
396 /* Event                     Action 1                       Action 2                    Next state */
398 /* API_WRITE_REQ_EVT */     {AVDT_SCB_HDL_WRITE_REQ,        AVDT_SCB_CHK_SND_PKT,       AVDT_SCB_STREAM_ST},

2. A2DP server handle this in bellow two action:
2.1 builds a new media packet and stores it in the SCB.
external/bluetooth/bluedroid/stack/avdt/avdt_scb_act.c
1320 void avdt_scb_hdl_write_req(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data) 

2.2 sends this stored media packet to L2CAP layer.
1921 void avdt_scb_chk_snd_pkt(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
	avdt_ad_write_req(AVDT_CHAN_MEDIA, p_scb->p_ccb, p_scb, p_pkt);
		L2CA_DataWrite(avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid, p_buf);
		
		
3. L2CAP to HCI layer
	bluedroid/stack/l2cap/l2c_api.c
1633 UINT8 L2CA_DataWrite (UINT16 cid, BT_HDR *p_data)
1634 {
1636     return l2c_data_write (cid, p_data, L2CAP_FLUSHABLE_CH_BASED);
					p_ccb = l2cu_find_ccb_by_cid (NULL, cid);
					l2c_csm_execute (p_ccb, L2CEVT_L2CA_DATA_WRITE, p_data);
						935 static void l2c_csm_open (tL2C_CCB *p_ccb, UINT16 event, void *p_data)//Just consider channel connected state
						1050     case L2CEVT_L2CA_DATA_WRITE:                    /* Upper layer data to send */
						1051         l2c_enqueue_peer_data (p_ccb, (BT_HDR *)p_data);
						1052         l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, NULL);
						1053         break;
								l2c_link_check_send_pkts (p_lcb, NULL, NULL);
									l2c_link_send_to_lower (p_lcb, p_buf);
									1341 #if BLE_INCLUDED == TRUE
									1342         if (p_lcb->is_ble_link)
									1344             L2C_LINK_SEND_BLE_ACL_DATA(p_buf);
									1346         else
									1349             L2C_LINK_SEND_ACL_DATA (p_buf);
														bte_main_hci_send((BT_HDR *)(p), BT_EVT_TO_LM_HCI_ACL);
															bt_hc_if->transmit_buf((TRANSAC)p_msg, \(char *) (p_msg + 1),p_msg->len);
																bluedroid/hci/src/bt_hci_bdroid.c:249 static int transmit_buf(TRANSAC transac, char *p_buf, int len)
																	utils_enqueue(&tx_q, (void *) transac);
																	bthc_signal_event(HC_EVENT_TX);
									1350         }
219                         break;

4 HCI content write to hardware device driver 
339 static void *bt_hc_worker_thread(void *arg)
		if (events & HC_EVENT_TX)
			p_hci_if->send(sending_msg_que[i]);
			593 void hci_h4_send_msg(HC_BT_HDR *p_msg)
				bytes_sent = userial_write(event,(uint8_t *) p,bytes_to_send);
					 ret = write(userial_cb.fd, p_data+total, len);
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值