Asterisk chan_mobile 代码阅读笔记

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

  1. 初始化mbl_tech.capabilities ,暂时不知道怎么用
  2. 检查蓝牙设备打开是否正常
  3. mbl_load_config 读取配置
  4. sdp_register 开启相关蓝牙sdp
  5. 创建 do_discovery 线程
  6. ast_channel_register(&mbl_tech) 注册channel 类型
  7. 其它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 ,只不过是方向反过来而已,处理流程是一摸一样的

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值