bluetooth handfree client test on console

1 测试环境

  • 硬件环境: wmt8880行车记录仪+mtk6622 bt + iphone手机
  • 软件环境: android4.4.2+ bluedroid5.0 + kernel3.4.5
  • 系统组件的连接框图:
bluetooth handfree client test on console_第1张图片

2 测试代码编码

  • step1:通过hw_get_module接口来获取蓝牙HAL层提供的蓝牙接口:bt_interface,并调用他的初始化函数:bt_interface->init(callbacks) 来设置对应的应用层回调函数:callbacks
bool hal_open(bt_callbacks_t *callbacks) {
  hw_module_t *module;
  if (hw_get_module(BT_STACK_MODULE_ID, (hw_module_t const **)&module)) {
    return false;
  }

  hw_device_t *device;
  if (module->methods->open(module, BT_STACK_MODULE_ID, &device)) {
    return false;
  }

  bt_device = (bluetooth_device_t *)device;
  bt_interface = bt_device->get_bluetooth_interface();
  if (!bt_interface) {
    bt_device->common.close((hw_device_t *)&bt_device->common);
    bt_device = NULL;
    return false;
  }

  bool success = (bt_interface->init(callbacks) == BT_STATUS_SUCCESS);
  success = success && (bt_interface->set_os_callouts(&callouts) == BT_STATUS_SUCCESS);
  return success;

step2:使能蓝牙:bt_interface->enable()
step3:修改蓝牙的名字

bt_property_t *property_new_name(const char *name) {
  bt_bdname_t *bdname = calloc(sizeof(bt_bdname_t), 1);
  bt_property_t *property = calloc(sizeof(bt_property_t), 1);

  property->type = BT_PROPERTY_BDNAME;
  property->val = bdname;
  property->len = sizeof(bt_bdname_t);

  strlcpy((char *)bdname->name, name, sizeof(bdname->name));

  return property;
}
bool modify_adapter_name() {
  int error;
  bt_property_t *name = property_new_name("handfree_sink");

  CALL_AND_WAIT(bt_interface->set_adapter_property(name), adapter_properties);
  CALL_AND_WAIT(error = bt_interface->get_adapter_property(BT_PROPERTY_BDNAME), adapter_properties);
  TASSERT(error == BT_STATUS_SUCCESS, "Error getting device name.");
  TASSERT(adapter_get_property_count() == 1, "Expected 1 adapter property change, found %d instead.", adapter_get_property_count());
  TASSERT(adapter_get_property(BT_PROPERTY_BDNAME), "The Bluetooth name property did not change.");
  TASSERT(property_equals(adapter_get_property(BT_PROPERTY_BDNAME), name), "Bluetooth name '%s' does not match test value", property_extract_name(adapter_get_property(BT_PROPERTY_BDNAME)));
  property_free(name);
  return true;
}

step4: 是蓝牙adapter对其他设备可见:


int  discoverable()
{
	int ret;
	 bt_property_t prop;
	 int val = 120;
	 prop.type = (bt_property_type_t) BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT;
        prop.len = sizeof(int);
        prop.val = &val;
	ret = bt_interface->set_adapter_property(&prop);
	printf("set discoverable,ret:%d\n",ret);
	return ret;
}

step5: 设定蓝牙的scan模式
int  set_scan_mode(int scan_mode)
{
	int ret;
	 bt_property_t prop;
	 int val = scan_mode;//BT_SCAN_MODE_CONNECTABLE;
	 prop.type = (bt_property_type_t) BT_PROPERTY_ADAPTER_SCAN_MODE;
        prop.len = sizeof(int);
        prop.val = &val;
	ret = bt_interface->set_adapter_property(&prop);
	printf("set scan mod,ret:%d\n",ret);
	return ret;
}

step6: 跟远端设备进行配对
int request_pair()
{
	int ret;
	ret = bt_interface->create_bond(&bt_remote_bdaddr,0);
	printf("enter %s, ret:%d\n",__func__,ret);
	return ret;
}
void  ssp_request(bt_bdaddr_t *remote_bd_addr,
                                        bt_bdname_t *bd_name,
                                        uint32_t cod,
                                        bt_ssp_variant_t pairing_variant,
                                     uint32_t pass_key)
  {
    	printf("enter %s,bd_name:%s,cod:%d,pairing_variant:%d,pass_key:%d\n",__func__,bd_name->name,cod,pairing_variant,pass_key);
	bt_interface->ssp_reply(remote_bd_addr,pairing_variant,true,pass_key);
    	CALLBACK_RET();
	//return 0;
  }


配对的时序图如下:
bluetooth handfree client test on console_第2张图片
  • step7: 获取handfree client对应的接口:handfree_interface,并且调用它的init函数设置对应的回调函数:
bool handfree_init() {
  handfree_interface = (bthf_client_interface_t *)bt_interface->get_profile_interface(BT_PROFILE_HANDSFREE_CLIENT_ID);
  return handfree_interface->init(callbacks_get_bthf_struct()) == BT_STATUS_SUCCESS;
}
  • step8:跟远端建立rfcomm链路,然后再建立sco链路,前者用于传输at指令,后者用于传输语音数据,如果使用pcm接口传输语音数据,也需要建立sco链路
bool handfree_connect() {
  int error;

  // PAN is enabled by default, wait for the first control state change
  // with default parameters set. We don't want to verify the result since
  // the implementation could have set any parameters.
 // WAIT(pan_control_state_changed);

  // Call enable explicitly and verify that the parameters match what we just set.
  CALL_AND_WAIT(error = handfree_interface->connect(&bt_remote_bdaddr), bthf_client_connection_state);
  TASSERT(error == BT_STATUS_SUCCESS, "Error handfree connect: %d", error);
  //TASSERT(pan_get_control_state() == BTPAN_STATE_ENABLED, "Control state is disabled.");
  //TASSERT(pan_get_local_role() == local_role, "Unexpected local role: %d", pan_get_local_role());
  //TASSERT(pan_get_error() == BT_STATUS_SUCCESS, "Error in control callback: %d", pan_get_error());

  return true;
}
  • step9: 开始拨打电话:10086:
bt_status_t dialNum(const char * number)
{
	int ret;
	ret = handfree_interface->dial(number);
	printf("dial,ret:%d\n",ret);
	return ret;
}
  • step10: 建立sco音频通道:
bool handfree_connect_audio() {
  int error;

  CALL_AND_WAIT(error = handfree_interface->connect_audio(&bt_remote_bdaddr), bthf_client_audio_state);
  TASSERT(error == BT_STATUS_SUCCESS, "Error handfree connect audio: %d", error);
  printf("error = %d\n",error);
  //TASSERT(pan_get_error() == BT_STATUS_SUCCESS, "Error connecting to BT device: %d", pan_get_error());
  //TASSERT(pan_get_connection_state() == BTPAN_STATE_CONNECTING, "Invalid PAN state after connect: %d", pan_get_connection_state());
  //TASSERT(pan_get_local_role() == local_role, "Incorrect local role: %d", pan_get_local_role());
  //TASSERT(pan_get_remote_role() == remote_role, "Incorrect remote role: %d", pan_get_remote_role());

//  WAIT(pan_connection_state_changed);
 // TASSERT(pan_get_error() == BT_STATUS_SUCCESS, "Error connecting to BT device: %d", pan_get_error());
 // TASSERT(pan_get_connection_state() == BTPAN_STATE_CONNECTED, "Invalid PAN state after connect: %d", pan_get_connection_state());
 // TASSERT(pan_get_local_role() == local_role, "Incorrect local role: %d", pan_get_local_role());
 // TASSERT(pan_get_remote_role() == remote_role, "Incorrect remote role: %d", pan_get_remote_role());

  return true;
}

完整的测试代码如下:
int main(int argc, char **argv) {
  if (argc < 2 || !parse_bdaddr(argv[1], &bt_remote_bdaddr)) {
    printf("Usage: %s \n", argv[0]);
    return -1;
  }

  if (!hal_open(callbacks_get_adapter_struct())) {
    printf("Unable to open Bluetooth HAL.\n");
    return 1;
  }
  printf("begin callbacks_init\n");
   callbacks_init();
   //enable bt
   printf("begin enable bt...\n");
   CALL_AND_WAIT(bt_interface->enable(), adapter_state_changed);
   //set bt device name
   printf("modify bt name to :handfree test\n");
   modify_adapter_name();
   //set bt discovable
   printf("set bt device discoverable\n");
  //CALL_AND_WAIT(discoverable(), discovery_state_changed);
  CALL_AND_WAIT(discoverable(), adapter_properties);
  //set scan mode
  printf("set bt device scan mode\n");
  CALL_AND_WAIT(set_scan_mode(BT_SCAN_MODE_CONNECTABLE), adapter_properties);
  // paire with remote device
  printf("begin to pair with iphone\n");
  //request_pair();
  CALL_AND_WAIT(request_pair(), ssp_request);

   WAIT(bond_state_chang);
   WAIT(bond_state_chang);

   //test handfree client profile
   printf("begint to handfree client profile test...\n");
   handfree_init();
   printf("begin to rfcomm connect\n");
   handfree_connect();
   WAIT(bthf_client_connection_state);

  // dialNum("10086");
  //CALL_AND_WAIT(dialNum("10086"),cmd_complete_cb);
  CALL_AND_WAIT(dialNum("13424419597"),cmd_complete_cb);

   audio_config();
   
   printf("begin to audio connect\n");
   handfree_connect_audio();
   WAIT(bthf_client_audio_state);
   WAIT(bthf_client_audio_state);
   WAIT(bthf_client_audio_state);
   WAIT(bthf_client_audio_state);
   
  callbacks_cleanup();
}
编译输出:bdtest
以上代码是基于android5.0中的bluedroid中的test/suite中的代码框架进行的扩展。

3 控制台的测试步骤

前提条件:需要wmt8880支持pcm驱动,使用支持handfree client和a2dp sink的bluedroid,uart driver可以正常工作。
  1. bdtest 1c:1a:c0:39:e8:d2 &(iphone手机的蓝牙mac地址)
  2. tinycap bt.wav -d 1 -c 1 -r 8000 (录下行downlink 语音)
  3. tinyplay bt.wav -d 1 -r 8000(播放上行uplink语音)

你可能感兴趣的:(android,linux,bluetooth)