static struct ast_channel_tech mbl_tech = {
.type = "Mobile",
.description = "Bluetooth Mobile Device Channel Driver",
.requester = mbl_request,
.call = mbl_call,
.hangup = mbl_hangup,
.answer = mbl_answer,
.send_digit_end = mbl_digit_end,
.read = mbl_read,
.write = mbl_write,
.fixup = mbl_fixup,
.devicestate = mbl_devicestate
};
mbl_call 調用 hfp_send_atd 發送 “ATDxxxx” 指令,xxxx是被叫號碼。
static int hfp_send_atd(struct hfp_pvt *hfp, const char *number)
{
char cmd[64];
snprintf(cmd, sizeof(cmd), "ATD%s;\r", number);
return rfcomm_write(hfp->rsock, cmd);
}
mbl_hangup 調用 hfp_send_chup 發送"AT+CHUP\r"
static int hfp_send_chup(struct hfp_pvt *hfp)
{
return rfcomm_write(hfp->rsock, "AT+CHUP\r");
}
mbl_answer 調用 hfp_send_chup 發送"ATA\r"
static int hfp_send_ata(struct hfp_pvt *hfp)
{
return rfcomm_write(hfp->rsock, "ATA\r");
}
mbl_digit_end 調用 hfp_send_dtmf 發送 “AT+VTS=%c\r”
static int hfp_send_dtmf(struct hfp_pvt *hfp, char digit)
{
char cmd[10];
switch(digit) {
case '0':
...
case '#':
snprintf(cmd, sizeof(cmd), "AT+VTS=%c\r", digit);
return rfcomm_write(hfp->rsock, cmd);
default:
return -1;
}
}
mbl_read 、 mbl_write 讀寫藍牙的SCO 音頻數據
mbl_fixup :替換新值,暫時不理解用途
mbl_request :to set up call data structures (pvt’s) 被channel.c request_channel 調用
再從load_module 函數看起
load_module
- 初始化mbl_tech.capabilities ,暫時不知道怎麼用
- 檢查藍牙設備打開是否正常
- mbl_load_config 讀取配置
- sdp_register 開啓相關藍牙sdp
- 創建 do_discovery 線程
- ast_channel_register(&mbl_tech) 註冊channel 類型
- 其它cli 命令等
static int load_module(void)
{
int dev_id, s;
if (!(mbl_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return AST_MODULE_LOAD_DECLINE;
}
ast_format_cap_append(mbl_tech.capabilities, DEVICE_FRAME_FORMAT, 0);
/* Check if we have Bluetooth, no point loading otherwise... */
dev_id = hci_get_route(NULL);
//2. 檢查藍牙設備打開是否正常
s = hci_open_dev(dev_id);
if (dev_id < 0 || s < 0) {
ast_log(LOG_ERROR, "No Bluetooth devices found. Not loading module.\n");
ao2_ref(mbl_tech.capabilities, -1);
mbl_tech.capabilities = NULL;
hci_close_dev(s);
return AST_MODULE_LOAD_DECLINE;
}
hci_close_dev(s);
//mbl_load_config 讀取配置
if (mbl_load_config()) {
ast_log(LOG_ERROR, "Errors reading config file %s. Not loading module.\n", MBL_CONFIG);
ao2_ref(mbl_tech.capabilities, -1);
mbl_tech.capabilities = NULL;
return AST_MODULE_LOAD_DECLINE;
}
//sdp_register 開啓相關藍牙sdp
sdp_session = sdp_register();
/* Spin the discovery thread */
//創建 do_discovery 線程
if (ast_pthread_create_background(&discovery_thread, NULL, do_discovery, NULL) < 0) {
ast_log(LOG_ERROR, "Unable to create discovery thread.\n");
goto e_cleanup;
}
/* register our channel type */
//註冊channel 類型
if (ast_channel_register(&mbl_tech)) {
ast_log(LOG_ERROR, "Unable to register channel class %s\n", "Mobile");
goto e_cleanup;
}
//其它cli 命令等
ast_cli_register_multiple(mbl_cli, sizeof(mbl_cli) / sizeof(mbl_cli[0]));
ast_register_application(app_mblstatus, mbl_status_exec, mblstatus_synopsis, mblstatus_desc);
ast_register_application(app_mblsendsms, mbl_sendsms_exec, mblsendsms_synopsis, mblsendsms_desc);
return AST_MODULE_LOAD_SUCCESS;
e_cleanup:
unload_module();
return AST_MODULE_LOAD_DECLINE;
}
do_discovery 做些什麼?
啓用 do_monitor_phone 線程
do_discovery
start_monitor
do_monitor_phone
do_monitor_phone 做些什麼?
讀取 rfcomm 消息,判斷是否來電等
static void *do_monitor_phone(void *data)
{
...
//讀取 rfcomm 消息
if ((at_msg = at_read_full(hfp->rsock, buf, sizeof(buf))) < 0) {
ast_debug(1, "[%s] error reading from device: %s (%d)\n", pvt->id, strerror(errno), errno);
break;
}
ast_debug(1, "[%s] read %s\n", pvt->id, buf);
//處理 rfcomm 消息
switch (at_msg) {
case AT_BRSF:
.....
}
}
來電處理過程:
AT_RING
handle_response_ring
AT_CLIP
handle_response_clip
ast_pbx_start
pbx_thread
__ast_pbx_run
/*查找對應的context和exten*/
ast_exists_extension
pbx_extension_helper
pbx_findapp //找到對應的 application
pbx_exec //運行 application 如:Dial sip分機
Dial
Dial 調用過程
app_dial.c
static int load_module(void)
{
int res;
res = ast_register_application_xml(app, dial_exec);
res |= ast_register_application_xml(rapp, retrydial_exec);
return res;
}
dial_exec
dial_exec_full
ast_request
ast_call
chan->tech->call // 如: call sip
可以看出在asterisk 中,接聽一個來電最終是要發起對另一個channel 的呼叫。
A呼叫B : A -> PBX->B
B呼叫A : A -< PBX<-B
B呼叫A ,只不過是方向反過來而已,處理流程是一摸一樣的