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 ,只不过是方向反过来而已,处理流程是一摸一样的