今天是14号 15号更新,说明,刚开始看程序有点复杂 没办法,必须看代码
建议首先先把ADK3.5.1中的例程tutorials看完,对学习很有帮助
typedef struct TaskData { void (*handler)(Task, MessageId, Message); } TaskData;
static void led_controller1( Task t, MessageId id, Message payload )
{
PioSet32( LED1, (PioGet32() ^ LED1) );
MessageSendLater( t, 0, 0, DELAY1 );
}
static void led_controller2( Task t, MessageId id, Message payload )
{
PioSet32( LED2, (PioGet32() ^ LED2) );
MessageSendLater( t, 0, 0, DELAY2 );
}
static TaskData led_controller1_task = { led_controller1 };//实例化了一个任务,并初始化了其参数,即回调函数
static TaskData led_controller2_task = { led_controller2 };
int main(void)
{
PioSetDir32(0xFF, 0xFF); /* Set all PIO to be output */
PioSet32(0xFF, 0); /* Set all PIO off (0) */
MessageSend( &led_controller1_task, 0 , 0 );//第一个参数为发送给哪个任务
MessageSend( &led_controller2_task, 0 , 0 );
MessageLoop();//开始任务调度
return 0;
}
csr中是以消息机制来进行任务的处理的,其中最大的任务为theSink,其结构体如下
/* Sink application data */
typedef struct
{
/* Main task */
TaskData task;//最重要的任务,指向最高层的回到函数,即main函数里边的app_handler
/* Config variables */
ButtonsTaskData *theButtonsTask;//按键的任务,这些是最高层任务之下的任务,之所以定义在最高层里面,应该是想让最高层具有知道所有事件运行情况的能力
LedTaskData *theLEDTask;//led显示的任务,同上
runtime_block1_t *rundata;//运行时的数据,目前还不了解
config_block1_t *conf1;//解下来的7个block以后会分析
config_block2_t *conf2;
config_block3_t *conf3;
config_block4_t *conf4;
config_block5_t *conf5;
config_block6_t *conf6;
config_block7_t *conf7;
ConfigTone_t gConfigTones;
volume_levels_t *volume_levels; /* current operating volume levels for a2dp/usb/wired modes */
power_table *user_power_table; /* pointer to user power table if available in ps */
hfp_common_plugin_params_t hfp_plugin_params;
HFP_features_type HFP_supp_features;
feature_config_type features;
bdaddr local_bd_addr; /* Local BD Address of the sink device available in ps */
/* Runtime variables */
/*下面这些运行时的变量都是在动态的生成或者释放的,每一个和button一样都是一个任务*/
Task codec_task ;
Sink routed_audio;
uint16 NoOfReconnectionAttempts;
profile_data_t profile_data[MAX_MULTIPOINT_CONNECTIONS];
a2dp_data *a2dp_link_data;
#ifdef ENABLE_AVRCP
avrcp_data *avrcp_link_data;
#endif
tp_bdaddr *confirmation_addr;
inquiry_data_t inquiry;
#ifdef ENABLE_PBAP
pbapc_data_t pbapc_data;
#endif
#ifdef ENABLE_USB
usb_info *usb;
#endif
#ifdef ENABLE_PEER
bdaddr remote_peer_ag_bd_addr;
#endif
user_eq_bank_t *PEQ;
/*! Runtime flags*/
/*word 1*/
unsigned PowerOffIsEnabled:1; /*自行百度结构体的用法,这样写应该是为了节省空间*/
unsigned SinkInitialising:1;
unsigned VolumeOrientationIsInverted:1; /*whether or not the vol buttons are inverted*/
unsigned NetworkIsPresent:1;
unsigned inquiry_scan_enabled:1;
unsigned page_scan_enabled:1 ;
unsigned csr_speech_recognition_is_active:1 ;
unsigned csr_speech_recognition_tuning_active:1 ;
unsigned panic_reconnect:1;
unsigned last_outgoing_ag:2 ; /* which AG made the last outgoing call */
unsigned audio_prompts_enabled:1;
unsigned confirmation:1;
unsigned debug_keys_enabled:1;
unsigned RepeatCallerIDFlag:1;
unsigned mute_all_outputs:1;
/*word 2*/
unsigned audio_prompt_language:4;
unsigned num_audio_prompt_languages:4;
unsigned MultipointEnable:1;
unsigned powerup_no_connection:1; /* bit to indicate device has powered and no connections yet */
unsigned paging_in_progress:1; /* bit to indicate that device is curretly paging whilst in connectable state */
unsigned audioAmpPowerPin:1; /* bit to indicate logic state of audio amplifier power pin */
unsigned battery_state:3;
unsigned gVolButtonsInverted:1; /*! whether or not the volume button operation is currently inverted*/
/*word 3*/
unsigned FailAudioNegotiation:1;
unsigned RenegotiateSco:1;
unsigned lbipmEnable:1; /* enable Low Battery Intelligent Power Management feature */
unsigned buttons_locked:1; /* Flag to indicate if button locking is enabled */
unsigned HeldCallIndex:4; /* which call to route in the case of multiple held calls */
unsigned inquiry_tx:8;
/*word 4*/
unsigned MissedCallIndicated:8;
unsigned gEventQueuedOnConnection:8 ;
/*word 5*/
unsigned mute_states:3;
unsigned pbap_access:1; /* Link Policy expedites PBAP access */
unsigned dfu_access:1; /* Link Policy expedites DFU data transfer */
unsigned hfp_profiles:3;
unsigned ssr_enabled:1;
unsigned VoiceRecognitionIsActive:2;
unsigned PartyModeEnabled:1;
#ifdef ENABLE_PEER
unsigned remote_peer_audio_conn_status:3; /* Flag to indicate which Audio sources are connected to the remote peer */
unsigned tws_qual_enable_peer_open:1; /* Flag to indicate App to trigger opening of Peer media channel */
#else
unsigned unused4:4;
#endif
/* word 6 */
unsigned gated_audio:8; /* Bitmask indicating which audio sources are prevented from being routed */
unsigned linkLossReminderTime:8;
/* word 7 */
peer_states_t peer;
#if defined(ENABLE_PEER) && defined( ENABLE_PEER_BATTERY_LEVEL)
uint16 peer_battery_level;
#endif
} hsTaskData;
/* Time critical initialisation */
#ifdef HOSTED_TEST_ENVIRONMENT
void _sink_init(void)
#else
void _init(void)
#endif
{
/* Set the application task */
theSink.task.handler = app_handler; /*这个就是上面提及的最重要的任务的回调函数,如果其他任务想让这个任务的事件触发,则向它发送消息,第一个参数为这个任务的TASK*/
/* set flag to indicate that configuration is being read, use to prevent use of variables
prior to completion of initialisation */
theSink.SinkInitialising = TRUE;/*将sink的正在初始化标志置位*/
/* Read in any PIOs required */
configManagerPioMap();/*根据配置文件获取PIO的设置和映射关系*/
/* Time critical USB setup */
usbTimeCriticalInit();/*目前没有用到*/
}
/* The Sink Application starts here...*/
#ifdef HOSTED_TEST_ENVIRONMENT
int sink_main(void)
#else
int main(void)
#endif
{
DEBUG (("Main [%s]\n",__TIME__));
/* Initialise the Upgrade lib */
sinkUpgradeInit(&theSink.task);/*这个和更新有关,暂不考虑*/
/* check and update as necessary the software version pskey, this is used for ensuring maximum
compatibility with the sinkg configuration tool */
configManagerSetVersionNo();/*版本相关*/
/* Initialise memory required early */
configManagerInitMemory();/*这个函数里面开辟了runtime_block1_t 这个结构体,初始化为0*/
/* initialise memory for the led manager */
LedManagerMemoryInit();/*开辟了LedTaskData结构体的空间,初始化为0*/
/* Initialise device state */
AuthResetConfirmationFlags();/*不懂?*/
/*the internal regs must be latched on (smps and LDO)*/
PioSetPowerPin ( TRUE ) ;/*不懂?*/
switch (BootGetMode() )/*配置工具可以设置系统的启动模式*/
{
#ifdef CVC_PRODTEST
case BOOTMODE_CVC_PRODTEST:
/*run the cvc prod test code and dont start the applicaiton */
cvcProductionTestEnter() ;
break ;
#endif
case BOOTMODE_DFU:
/*do nothing special for the DFU boot mode,
This mode expects to have the appropriate host interfface enabled
Don't start the application */
/* Initializing only the system components required for flashing the led pattern in the DFU mode*/
configManagerInit(FALSE);
LEDManagerIndicateEvent(EventUsrEnterDFUMode);
break ;
case BOOTMODE_DEFAULT:
case BOOTMODE_CUSTOM:
case BOOTMODE_USB_LOW_POWER:
case BOOTMODE_ALT_FSTAB:
default:
{
/* Initialise the Connection lib */
sinkConnectionInit();/*初始化连接库,从这里开始,可以把整个连接库从初始化调用到完成分析一下*/
#ifdef TEST_HARNESS
test_init();
#endif
}
break ;
}
/* Make sure the mute states are correctly set up */
VolumeSetInitialMuteState();/*静音模式初始化*/
/* Start the message scheduler loop */
MessageLoop();/*开始任务调度*/
/* Never get here...*/
return 0;
}
static void sinkConnectionInit(void)
{
/* read the lengths key into a temporary malloc to get pdl length */
/*给pdl分配空间*/
lengths_config_type * lengths_key = PanicUnlessMalloc(sizeof(lengths_config_type));
/* The number of paired devices can be restricted using pskey user 40, a number between 1 and 8 is allowed */
/*读取pdl*/
ConfigRetrieve(CONFIG_LENGTHS, lengths_key , sizeof(lengths_config_type) );
DEBUG (("PDLSize[%d]\n" , lengths_key->pdl_size ));
/* Initialise the Connection Library with the options */
/*具体的初始化函数,注意(0001)第一个参数为最上层的任务,第三个参数为pdl的个数*/
ConnectionInitEx2(&theSink.task , NULL, lengths_key->pdl_size );
/* free the malloc'd memory */
free(lengths_key);/*这里需要关注一下,这种malloc,free的模式在工程中很常见,都是先分配空间,使用之后再释放,在哪里看的目的好像是说减少栈内存的使用*/
}
void ConnectionInitEx3(Task theAppTask, const msg_filter *msgFilter , uint16 TdlNumberOfDevices , uint16 options)
{
/*注意这里面又有了一个theCm,自己可以分析一下,怎样和最重要的任务产生关系*/
theCm.msgFilter = (msgFilter == NULL) ? &defaultMsgFilter : msgFilter;
/* Initialise the Connection Library Task, all upstream messages sent by
Bluestack will be handled by this task */
/*这也是个任务,初始化其回调函数*/
theCm.task.handler = connectionBluestackHandler;
/* If a task is already registered to receive BlueStack prims then we panic! */
if (MessageBlueStackTask(connectionGetCmTask()))
{
CL_DEBUG(("ERROR - task already registered\n"));
}
/* Init the resource locks */
initLocks();
/* Init the sm_init_msg types.*/
theCm.smState.sm_init_msg = sm_init_set_none;
/* Store the application task */
/*在这一步,将最终要的任务,赋值给这个任务的结构体,这样这个任务就可以向最重要任务发消息*/
theCm.theAppTask = theAppTask;
/*set the number of devices to the requested value if in the range 1 to 8*/
theCm.smState.TdlNumberOfDevices = DEFAULT_NO_DEVICES_TO_MANAGE ;
if ((TdlNumberOfDevices >= MIN_NO_DEVICES_TO_MANAGE) &&
(TdlNumberOfDevices <= MAX_NO_DEVICES_TO_MANAGE))
{
theCm.smState.TdlNumberOfDevices = TdlNumberOfDevices ;
}
/* Process options */
/* Enable SC */
if (options & CONNLIB_OPTIONS_SC_ENABLE)
theCm.flags |= CONNECTION_FLAG_SC_ENABLE;
/* Enable SC only mode. It implies SC must be turned on as well */
if (options & CONNLIB_OPTIONS_SCOM_ENABLE)
theCm.flags |= (CONNECTION_FLAG_SCOM_ENABLE | CONNECTION_FLAG_SC_ENABLE);
/* Start the initialisation process */
MessageSend(connectionGetCmTask(), CL_INTERNAL_INIT_REQ, NO_PAYLOAD);/*这里发送消息给&theCm.task,也即上面赋值过的回调函数connectionBluestackHandler,第二个代表连接内部初始化请求此数值为1,第三个参数延时时间*/
}
/****************************************************************************
NAME
connectionBluestackHandler
DESCRIPTION
This is the main task handler for all messages sent to the Connection
Library task.
RETURNS
void
*/
void connectionBluestackHandler(Task task, MessageId id, Message message)
{
/* Get access to the Connection Library instance state */
/*获取这个传递过来的任务*/
connectionState *theCm = (connectionState *)task;
connectionStates state = theCm->state;
PRINT(("connectionBluestackHandler - Id = 0x%x\n",id));
/* Handle Bluestack primitives seperately */
switch (id)
{
case MESSAGE_BLUESTACK_DM_PRIM:/*8004*/
connectionBluestackHandlerDm(theCm, (DM_UPRIM_T *)message);
break;
#ifndef CL_EXCLUDE_RFCOMM
case MESSAGE_BLUESTACK_RFCOMM_PRIM:/*8006*/
connectionBluestackHandlerRfcomm(theCm, (RFCOMM_UPRIM_T *)message);
break;
#endif
#if !defined(CL_EXCLUDE_L2CAP) || !defined(DISABLE_BLE)
case MESSAGE_BLUESTACK_L2CAP_PRIM:/*8005*/
connectionBluestackHandlerL2cap(theCm, (L2CA_UPRIM_T *)message);
break;
#endif
#ifndef CL_EXCLUDE_SDP
case MESSAGE_BLUESTACK_SDP_PRIM:/*8007*/
connectionBluestackHandlerSdp(theCm, (SDS_UPRIM_T *)message);
break;
#endif
case MESSAGE_BLUESTACK_UDP_PRIM:/*8015*/
case MESSAGE_BLUESTACK_TCP_PRIM:/*8014*/
handleUnexpected(connectionUnhandledMessage, theCm->state, id);
break;
#ifndef CL_EXCLUDE_SDP
/* CL_SDP_CLOSE_SEARCH_CFM Primitive arrived as a result of an internal
call to close SDP search, can't avoid so ignore
Handled as a special case to allow the compiler to generate better
code for the previous switch statements. */
case CL_SDP_CLOSE_SEARCH_CFM:
break;
#endif
/* Everything else must be internal connection library primitives */
default:/*可知1会进入这里*/
{
switch (state)/*然会根据任务的状态判断,我们可以回过头去看看这个任务的状态在什么时间被赋值了,发现没有处理过所以为0,会进入connectionUninitialised这个值也为0*/
{
case connectionReady:
connectionBluestackHandlerReady(theCm, id, message);
break;
case connectionUninitialised:
connectionBluestackHandlerUninitialised(theCm, id, message);/*注意传递过去的参数*/
break;
case connectionInitialising:
connectionBluestackHandlerInitialising(theCm, id, message);
break;
case connectionTestMode:
connectionBluestackHandlerTestMode(theCm, id, message);
break;
}
}
}
}
static void connectionBluestackHandlerUninitialised(connectionState *theCm, MessageId id, Message message)
{
/* Depending upon the message id...*/
/*由前面可以知道此时相等*/
if (id == CL_INTERNAL_INIT_REQ)
{
PRINT(("CL_INTERNAL_INIT_REQ\n"));
connectionHandleInternalInit(connectionInit);/*执行这个函数,注意参数为0*/
}
else
{
/* Prims we are not handling - Not panicing the app in DEBUG Mode. Just Print this INFO and ignore it.*/
CL_DEBUG_INFO(("Ignored Unexpected Message - Code 0x%x State 0x%x MsgId 0x%x\n", connectionUnexpectedCmPrim, theCm->state, id))
}
}
void connectionHandleInternalInit(connectionInitState state)
{
/* If we're ready to run, change state */
if(state == connectionInitComplete)
{
theCm.state = connectionReady;
}
else if (theCm.state != connectionInitialising)/*这个成立,此时状态为未初始化*/
{
theCm.state = connectionInitialising;/*改变状态*/
/* Start a Timer to notify the Client if the initialisation fails */
/*等待一段时间发送CL_INTERNAL_INIT_TIMEOUT_IND这个消息此数值为0,还是向connectionBluestackHandler发送的,注意第三个参数,这个是个时间,很重要下面会分析到*/
MessageSendLater(&theCm.task, CL_INTERNAL_INIT_TIMEOUT_IND, NO_PAYLOAD, (uint32) INIT_TIMEOUT);
}
/* Check to see if all objects have been initialised */
if(state == connectionInitComplete)
{
/* Initialise auth requirements to unknown */
theCm.smState.authentication_requirements = AUTH_REQ_UNKNOWN;
/* Some DM stuff can be initialised only after the DM register has happened so do it here */
connectionDmInfoInit();
/* Let the application we're ready to go */
connectionSendInitCfm(theCm.theAppTask, success, theCm.infoState.version);
}
else
{
/* Depending upon the previous object initialised, initialise the next one */
switch(state)
{
case connectionInit:/*此时会调用这个函数*/
connectionDmInit(); /*这个是个初始化,做什么的不了解*/
break;
case connectionInitDm:
#ifndef CL_EXCLUDE_RFCOMM
connectionRfcInit();
#else
connectionL2capInit();
#endif
break;
#ifndef CL_EXCLUDE_RFCOMM
case connectionInitRfc:
connectionL2capInit();
break;
#endif
case connectionInitL2cap:
connectionUdpInit();
break;
case connectionInitUdp:
connectionTcpInit();
break;
case connectionInitTcp:
connectionSdpInit(&theCm.sdpState);
break;
case connectionInitSdp:
connectionVersionInit();
break;
case connectionInitVer:
connectionSmInit(theCm.infoState.version,
&theCm.smState,
theCm.flags);
break;
case connectionInitSm:
theCm.smState.noDevices = connectionAuthInit();
break;
case connectionInitComplete:
/* We're ready! */
default:
break;
}
}
}
case connectionInitialising:
connectionBluestackHandlerInitialising(theCm, id, message);
break;
static void connectionBluestackHandlerInitialising(connectionState *theCm, MessageId id, Message message)
{
/* Depending upon the message id...*/
switch (id)
{
case CL_INTERNAL_INIT_CFM:
PRINT(("CL_INTERNAL_INIT_CFM\n"));
connectionHandleInternalInit(((CL_INTERNAL_INIT_CFM_T*)message)->state);
break;
case CL_INTERNAL_INIT_TIMEOUT_IND:/*所以会执行下面的语句*/
PRINT(("CL_INTERNAL_INIT_TIMEOUT_IND\n"));
(void)MessageCancelFirst(&theCm->task, CL_INTERNAL_INIT_CFM);
SET_CM_STATE(connectionUninitialised);
connectionSendInitCfm(theCm->theAppTask, fail, bluetooth_unknown);/*这个函数是个重点,关注它的第一个参数为最重要的那个任务*/
break;
case CL_INTERNAL_SM_INIT_REQ:
PRINT(("CL_INTERNAL_SM_INIT_REQ\n"));
handleSecurityInitReq(&theCm->infoState, (CL_INTERNAL_SM_INIT_REQ_T *)message);
break;
case CL_INTERNAL_DM_READ_LOCAL_VERSION_REQ:
PRINT(("CL_INTERNAL_DM_READ_LOCAL_VERSION_REQ\n"));
connectionHandleReadLocalVersionRequest(&theCm->infoState, (CL_INTERNAL_DM_READ_LOCAL_VERSION_REQ_T *)message);
break;
case CL_INTERNAL_DM_SET_BT_VERSION_REQ:
PRINT(("CL_INTERNAL_DM_SET_BT_VERSION_REQ\n"));
connectionHandleSetBtVersionReq(&theCm->infoState, (CL_INTERNAL_DM_SET_BT_VERSION_REQ_T *)message);
break;
default:
/* Prims we are not handling - for now panic the app */
handleUnexpected(connectionUnhandledMessage, theCm->state, id);
break;
}
}
void connectionSendInitCfm(Task task, connection_lib_status status, cl_dm_bt_version version)
{
MAKE_CL_MESSAGE(CL_INIT_CFM);
message->status = status;//这里这个是fail
message->version = version;//版本的话没有bluetooth_unknown
/*这个函数是重点,这个task是最重要的任务,所以会往上面返回一个没有初始化成功的标志*/
MessageSend(task, CL_INIT_CFM, message);
/* Cancel initialisation timeout */
if(status == success)
(void) MessageCancelFirst(connectionGetCmTask(), CL_INTERNAL_INIT_TIMEOUT_IND);
}
汗啊,分析了一遍结果发现到头来初始化失败了啊!!
莫急,有没有注意到我上面说的那个时间很重要的参数,没错就是在这里,当这个时间到之后,确实会发送初始化失败,但是如果底层初始化成功的话这个消息将被取消,不会发往上面,其实程序看到这里的话,应该知道当状态变为初始化完成时,会向上面发送成功的标志,应该说流程大致有个印象,对于具体的其状态是怎样切换成初始化完成的,这个有待后面研究,目前我也不是很懂。