static gboolean l2cap_listen_cb(GIOChannel *io, GIOCondition cond,
							gpointer user_data)
{
	struct test_data *data = tester_get_data();
	const struct l2cap_data *l2data = data->test_data;
	int sk, new_sk;

	data->io_id = 0;

	sk = g_io_channel_unix_get_fd(io);

	new_sk = accept(sk, NULL, NULL);
	if (new_sk < 0) {
		tester_warn("accept failed: %s (%u)", strerror(errno), errno);
		tester_test_failed();
		return FALSE;
	}

	if (l2data->read_data) {
		struct bthost *bthost;
		GIOChannel *new_io;

		new_io = g_io_channel_unix_new(new_sk);
		g_io_channel_set_close_on_unref(new_io, TRUE);

		bthost = hciemu_client_get_host(data->hciemu);
		g_io_add_watch(new_io, G_IO_IN, server_received_data, NULL);
		bthost_send_cid(bthost, data->handle, data->dcid,
					l2data->read_data, l2data->data_len);

		g_io_channel_unref(new_io);

		return FALSE;
	} else if (l2data->write_data) {
		struct bthost *bthost;
		ssize_t ret;

		bthost = hciemu_client_get_host(data->hciemu);
		bthost_add_cid_hook(bthost, data->handle, data->scid,
					server_bthost_received_data, NULL);

		ret = write(new_sk, l2data->write_data, l2data->data_len);
		close(new_sk);

		if (ret != l2data->data_len) {
			tester_warn("Unable to write all data");
			tester_test_failed();
		}

		return FALSE;
	}

	tester_print("Successfully connected");

	close(new_sk);

	tester_test_passed();

	return FALSE;
}
static gboolean l2cap_connect_cb(GIOChannel *io, GIOCondition cond,
							gpointer user_data)
{
	struct test_data *data = tester_get_data();
	const struct l2cap_data *l2data = data->test_data;
	int err, sk_err, sk;
	socklen_t len = sizeof(sk_err);

	data->io_id = 0;

	sk = g_io_channel_unix_get_fd(io);

	if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &sk_err, &len) < 0)
		err = -errno;
	else
		err = -sk_err;

	if (err < 0)
		tester_warn("Connect failed: %s (%d)", strerror(-err), -err);
	else
		tester_print("Successfully connected");

	if (l2data->read_data) {
		struct bthost *bthost;

		bthost = hciemu_client_get_host(data->hciemu);
		g_io_add_watch(io, G_IO_IN, client_received_data, NULL);

		bthost_send_cid(bthost, data->handle, data->dcid,
					l2data->read_data, l2data->data_len);

		return FALSE;
	} else if (l2data->write_data) {
		struct bthost *bthost;
		ssize_t ret;

		bthost = hciemu_client_get_host(data->hciemu);
		bthost_add_cid_hook(bthost, data->handle, data->dcid,
					bthost_received_data, NULL);

		ret = write(sk, l2data->write_data, l2data->data_len);
		if (ret != l2data->data_len) {
			tester_warn("Unable to write all data");
			tester_test_failed();
		}

		return FALSE;
	}

	if (-err != l2data->expect_err)
		tester_test_failed();
	else
		tester_test_passed();

	return FALSE;
}
예제 #3
0
static void test_connect(const void *test_data)
{
	struct test_data *data = tester_get_data();
	const struct l2cap_client_data *l2data = data->test_data;
	GIOChannel *io;
	int sk;

	if (l2data->server_psm) {
		struct bthost *bthost = hciemu_client_get_host(data->hciemu);
		bthost_set_server_psm(bthost, l2data->server_psm);
	}

	sk = create_l2cap_sock(data, 0);
	if (sk < 0) {
		tester_test_failed();
		return;
	}

	if (connect_l2cap_sock(data, sk, l2data->client_psm) < 0) {
		close(sk);
		tester_test_failed();
		return;
	}

	io = g_io_channel_unix_new(sk);
	g_io_channel_set_close_on_unref(io, TRUE);

	data->io_id = g_io_add_watch(io, G_IO_OUT, l2cap_connect_cb, NULL);

	g_io_channel_unref(io);

	tester_print("Connect in progress");
}
예제 #4
0
static void test_connect_two_sockets(const void *test_data)
{
	struct test_data *data = tester_get_data();
	const struct l2cap_data *l2data = data->test_data;
	const uint8_t *client_bdaddr;

	test_two_sockets_connect_cb_cnt = 0;
	test_scan_enable_counter = 0;

	hciemu_add_master_post_command_hook(data->hciemu,
				test_connect_two_sockets_router, data);

	if (l2data->server_psm) {
		struct bthost *bthost = hciemu_client_get_host(data->hciemu);

		if (!l2data->data_len)
			bthost_add_l2cap_server(bthost, l2data->server_psm,
						NULL, NULL);
	}

	client_bdaddr = hciemu_get_client_bdaddr(data->hciemu);
	if (l2data->close_one_socket)
		connect_socket(client_bdaddr, &data->sk, NULL);
	else
		connect_socket(client_bdaddr, &data->sk,
						test_two_sockets_connect_cb);
}
예제 #5
0
static void test_client(const void *test_data)
{
	struct test_data *data = tester_get_data();
	const struct smp_data *smp = data->test_data;
	struct mgmt_cp_pair_device cp;
	struct bthost *bthost;

	init_bdaddr(data);

	bthost = hciemu_client_get_host(data->hciemu);
	bthost_set_connect_cb(bthost, smp_new_conn, data);
	test_add_condition(data);

	if (smp->expect_hci_command) {
		tester_print("Registering HCI command callback");
		hciemu_add_master_post_command_hook(data->hciemu,
						command_hci_callback, data);
		test_add_condition(data);
	}

	memcpy(&cp.addr.bdaddr, data->ra, sizeof(data->ra));
	cp.addr.type = BDADDR_LE_PUBLIC;
	if (smp->mitm)
		cp.io_cap = 0x04; /* KeyboardDisplay */
	else
		cp.io_cap = 0x03; /* NoInputNoOutput */

	mgmt_send(data->mgmt, MGMT_OP_PAIR_DEVICE, data->mgmt_index,
			sizeof(cp), &cp, pair_device_complete, NULL, NULL);

	tester_print("Pairing in progress");
}
예제 #6
0
static void setup_powered_client_callback(uint8_t status, uint16_t length,
					const void *param, void *user_data)
{
	struct test_data *data = tester_get_data();
	const struct l2cap_data *l2data = data->test_data;
	struct bthost *bthost;

	if (status != MGMT_STATUS_SUCCESS) {
		tester_setup_failed();
		return;
	}

	tester_print("Controller powered on");

	bthost = hciemu_client_get_host(data->hciemu);
	bthost_set_cmd_complete_cb(bthost, client_cmd_complete, user_data);

	if (data->hciemu_type == HCIEMU_TYPE_LE) {
		if (!l2data || !l2data->server_not_advertising)
			bthost_set_adv_enable(bthost, 0x01);
		else
			tester_setup_complete();
	} else {
		bthost_write_scan_enable(bthost, 0x03);
	}
}
예제 #7
0
static void client_l2cap_rsp(uint8_t code, const void *data, uint16_t len,
							void *user_data)
{
	struct test_data *t_data = tester_get_data();
	struct bthost *bthost = hciemu_client_get_host(t_data->hciemu);
	struct emu_l2cap_cid_data *cid_data = user_data;
	const uint16_t *psm = data;
	const struct iovec con_req = raw_pdu(0x13, 0x00,	/* PSM */
						0x41, 0x00);	/* Source CID */

	if (len < sizeof(*psm)) {
		tester_warn("Invalid l2cap response.");
		return;
	}

	switch (*psm) {
	case 0x40:
		bthost_add_cid_hook(bthost, cid_data->handle, 0x40,
						hid_ctrl_cid_hook_cb, cid_data);

		bthost_l2cap_req(bthost, cid_data->handle, 0x02,
					con_req.iov_base, con_req.iov_len,
					client_l2cap_rsp, cid_data);
		break;
	case 0x41:
		bthost_add_cid_hook(bthost, cid_data->handle, 0x41,
						hid_intr_cid_hook_cb, cid_data);
		break;
	default:
		break;
	}
}
예제 #8
0
static void setup_powered_common(void)
{
	struct test_data *data = tester_get_data();
	const struct l2cap_data *test = data->test_data;
	struct bthost *bthost = hciemu_client_get_host(data->hciemu);
	unsigned char param[] = { 0x01 };

	mgmt_register(data->mgmt, MGMT_EV_USER_CONFIRM_REQUEST,
			data->mgmt_index, user_confirm_request_callback,
			NULL, NULL);

	if (test && (test->pin || test->expect_pin))
		mgmt_register(data->mgmt, MGMT_EV_PIN_CODE_REQUEST,
				data->mgmt_index, pin_code_request_callback,
				data, NULL);

	if (test && test->client_pin)
		bthost_set_pin_code(bthost, test->client_pin,
							test->client_pin_len);
	if (test && test->reject_ssp)
		bthost_set_reject_user_confirm(bthost, true);

	if (data->hciemu_type == HCIEMU_TYPE_LE)
		mgmt_send(data->mgmt, MGMT_OP_SET_LE, data->mgmt_index,
				sizeof(param), param, NULL, NULL, NULL);

	if (test && test->enable_ssp)
		mgmt_send(data->mgmt, MGMT_OP_SET_SSP, data->mgmt_index,
				sizeof(param), param, NULL, NULL, NULL);

	mgmt_send(data->mgmt, MGMT_OP_SET_PAIRABLE, data->mgmt_index,
				sizeof(param), param, NULL, NULL, NULL);
}
예제 #9
0
static void client_cmd_complete(uint16_t opcode, uint8_t status,
					const void *param, uint8_t len,
					void *user_data)
{
	struct test_data *data = tester_get_data();
	const struct l2cap_data *test = data->test_data;
	struct bthost *bthost;

	bthost = hciemu_client_get_host(data->hciemu);

	switch (opcode) {
	case BT_HCI_CMD_WRITE_SCAN_ENABLE:
	case BT_HCI_CMD_LE_SET_ADV_ENABLE:
		tester_print("Client set connectable status 0x%02x", status);
		if (!status && test && test->enable_ssp) {
			bthost_write_ssp_mode(bthost, 0x01);
			return;
		}
		break;
	case BT_HCI_CMD_WRITE_SIMPLE_PAIRING_MODE:
		tester_print("Client enable SSP status 0x%02x", status);
		break;
	default:
		return;
	}


	if (status)
		tester_setup_failed();
	else
		tester_setup_complete();
}
예제 #10
0
static bool verify_random(const uint8_t rnd[16])
{
	struct test_data *data = tester_get_data();
	uint8_t confirm[16];

	if (!bt_crypto_c1(data->crypto, data->tk, data->rrnd, data->prsp,
					data->preq, data->ia_type, data->ia,
					data->ra_type, data->ra, confirm))
		return false;

	if (memcmp(data->pcnf, confirm, sizeof(data->pcnf) != 0)) {
		tester_warn("Confirmation values don't match");
		return false;
	}

	if (data->out) {
		struct bthost *bthost = hciemu_client_get_host(data->hciemu);
		bt_crypto_s1(data->crypto, data->tk, data->rrnd, data->prnd,
								data->ltk);
		bthost_le_start_encrypt(bthost, data->handle, data->ltk);
	} else {
		bt_crypto_s1(data->crypto, data->tk, data->prnd, data->rrnd,
								data->ltk);
	}

	return true;
}
예제 #11
0
static void test_connect(const void *test_data)
{
	struct test_data *data = tester_get_data();
	struct bthost *bthost = hciemu_client_get_host(data->hciemu);
	const struct rfcomm_client_data *client_data = data->test_data;
	const uint8_t *client_addr, *master_addr;
	GIOChannel *io;
	int sk;

	bthost_add_l2cap_server(bthost, 0x0003, NULL, NULL);
	bthost_add_rfcomm_server(bthost, client_data->server_channel,
						rfcomm_connect_cb, NULL);

	master_addr = hciemu_get_master_bdaddr(data->hciemu);
	client_addr = hciemu_get_client_bdaddr(data->hciemu);

	sk = create_rfcomm_sock((bdaddr_t *) master_addr, 0);

	if (connect_rfcomm_sock(sk, (const bdaddr_t *) client_addr,
					client_data->client_channel) < 0) {
		close(sk);
		tester_test_failed();
		return;
	}

	io = g_io_channel_unix_new(sk);
	g_io_channel_set_close_on_unref(io, TRUE);

	data->io_id = g_io_add_watch(io, G_IO_OUT, rc_connect_cb, NULL);

	g_io_channel_unref(io);

	tester_print("Connect in progress %d", sk);
}
예제 #12
0
static void smp_new_conn(uint16_t handle, void *user_data)
{
	struct test_data *data = user_data;
	const struct smp_data *smp = data->test_data;
	struct bthost *bthost = hciemu_client_get_host(data->hciemu);
	const struct smp_req_rsp *req;
	const void *pdu;

	tester_print("New SMP client connection with handle 0x%04x", handle);

	data->handle = handle;

	bthost_add_cid_hook(bthost, handle, SMP_CID, smp_server, data);

	if (smp->req_count == data->counter)
		return;

	req = &smp->req[data->counter];

	if (!req->send)
		return;

	tester_print("Sending SMP PDU");

	pdu = get_pdu(req->send);
	bthost_send_cid(bthost, handle, SMP_CID, pdu, req->send_len);

	if (!req->expect)
		test_condition_complete(data);
}
예제 #13
0
static void send_req_new_conn(uint16_t handle, void *user_data)
{
	struct test_data *data = user_data;
	const struct l2cap_data *l2data = data->test_data;
	struct bthost *bthost;

	tester_print("New client connection with handle 0x%04x", handle);

	data->handle = handle;

	if (l2data->send_cmd) {
		bthost_l2cap_rsp_cb cb;

		if (l2data->expect_cmd_code)
			cb = client_l2cap_rsp;
		else
			cb = NULL;

		tester_print("Sending L2CAP Request from client");

		bthost = hciemu_client_get_host(data->hciemu);
		bthost_l2cap_req(bthost, handle, l2data->send_cmd_code,
					l2data->send_cmd, l2data->send_cmd_len,
					cb, data);
	}
}
예제 #14
0
static gboolean enable_advertising(gpointer args)
{
	struct test_data *data = tester_get_data();
	struct bthost *bthost = hciemu_client_get_host(data->hciemu);

	bthost_set_adv_enable(bthost, 0x01);
	return FALSE;
}
예제 #15
0
static void hid_prepare_reply_report(struct emu_l2cap_cid_data *cid_data)
{
	struct test_data *t_data = tester_get_data();
	struct bthost *bthost = hciemu_client_get_host(t_data->hciemu);
	const struct iovec pdu = raw_pdu(0xa2, 0x01, 0x00);

	bthost_send_cid_v(bthost, cid_data->handle, cid_data->cid, &pdu, 1);
}
예제 #16
0
static void conn_cb(uint16_t handle, void *user_data)
{
	struct test_data *data = tester_get_data();
	struct bthost *bthost = hciemu_client_get_host(data->hciemu);

	tester_print("New connection with handle 0x%04x", handle);

	test_conn_handle = handle;

	bthost_request_auth(bthost, handle);
}
예제 #17
0
static void avrcp_get_element_attributes_req(void)
{
	struct test_data *data = tester_get_data();
	struct bthost *bthost = hciemu_client_get_host(data->hciemu);
	const struct iovec pdu = raw_pdu(req_ele_attr);
	struct step *step = g_new0(struct step, 1);

	bthost_send_cid_v(bthost, avrcp_data.handle, avrcp_data.cid, &pdu, 1);
	step->action_status = BT_STATUS_SUCCESS;
	schedule_action_verification(step);
}
예제 #18
0
static void avrcp_connect_request_cb(uint16_t handle, uint16_t cid,
							void *user_data)
{
	struct test_data *data = tester_get_data();
	struct bthost *bthost = hciemu_client_get_host(data->hciemu);
	struct emu_l2cap_cid_data *cid_data = user_data;

	cid_data->handle = handle;
	cid_data->cid = cid;

	bthost_add_cid_hook(bthost, handle, cid, avrcp_cid_hook_cb, cid_data);
}
예제 #19
0
static void test_server(const void *test_data)
{
	struct test_data *data = tester_get_data();
	const struct l2cap_data *l2data = data->test_data;
	const uint8_t *master_bdaddr;
	uint8_t addr_type;
	struct bthost *bthost;
	GIOChannel *io;
	int sk;

	if (l2data->server_psm || l2data->cid) {
		sk = create_l2cap_sock(data, l2data->server_psm,
					l2data->cid, l2data->sec_level);
		if (sk < 0) {
			tester_test_failed();
			return;
		}

		if (listen(sk, 5) < 0) {
			tester_warn("listening on socket failed: %s (%u)",
					strerror(errno), errno);
			tester_test_failed();
			close(sk);
			return;
		}

		io = g_io_channel_unix_new(sk);
		g_io_channel_set_close_on_unref(io, TRUE);

		data->io_id = g_io_add_watch(io, G_IO_IN, l2cap_listen_cb,
									NULL);
		g_io_channel_unref(io);

		tester_print("Listening for connections");
	}

	master_bdaddr = hciemu_get_master_bdaddr(data->hciemu);
	if (!master_bdaddr) {
		tester_warn("No master bdaddr");
		tester_test_failed();
		return;
	}

	bthost = hciemu_client_get_host(data->hciemu);
	bthost_set_connect_cb(bthost, send_req_new_conn, data);

	if (data->hciemu_type == HCIEMU_TYPE_BREDR)
		addr_type = BDADDR_BREDR;
	else
		addr_type = BDADDR_LE_PUBLIC;

	bthost_hci_connect(bthost, master_bdaddr, addr_type);
}
예제 #20
0
static void client_new_conn(uint16_t handle, void *user_data)
{
	struct test_data *data = tester_get_data();
	const struct rfcomm_server_data *server_data = data->test_data;
	struct bthost *bthost;

	bthost = hciemu_client_get_host(data->hciemu);
	bthost_add_rfcomm_chan_hook(bthost, handle,
						server_data->client_channel,
						server_hook_func, NULL);
	bthost_connect_rfcomm(bthost, handle, server_data->client_channel,
						connection_cb, NULL);
}
예제 #21
0
static void rfcomm_connect_cb(uint16_t handle, uint16_t cid,
						void *user_data, bool status)
{
	struct test_data *data = tester_get_data();
	const struct rfcomm_client_data *client_data = data->test_data;
	struct bthost *bthost = hciemu_client_get_host(data->hciemu);

	if (client_data->send_data)
		bthost_add_rfcomm_chan_hook(bthost, handle,
						client_data->client_channel,
						client_hook_func, NULL);
	else if (client_data->read_data)
		data->conn_handle = handle;
}
예제 #22
0
static void test_server(const void *test_data)
{
	struct test_data *data = tester_get_data();
	struct bthost *bthost;

	data->out = true;

	init_bdaddr(data);

	bthost = hciemu_client_get_host(data->hciemu);
	bthost_set_connect_cb(bthost, smp_new_conn, data);

	bthost_hci_connect(bthost, data->ra, BDADDR_LE_PUBLIC);
}
예제 #23
0
static gboolean rc_connect_cb(GIOChannel *io, GIOCondition cond,
		gpointer user_data)
{
	struct test_data *data = tester_get_data();
	const struct rfcomm_client_data *client_data = data->test_data;
	socklen_t len = sizeof(int);
	int sk, err, sk_err;

	data->io_id = 0;

	sk = g_io_channel_unix_get_fd(io);

	if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &sk_err, &len) < 0)
		err = -errno;
	else
		err = -sk_err;

	if (client_data->expected_connect_err &&
				err == client_data->expected_connect_err) {
		tester_test_passed();
		return false;
	}

	if (client_data->send_data) {
		ssize_t ret;

		ret = write(sk, client_data->send_data, client_data->data_len);
		if (client_data->data_len != ret)
			tester_test_failed();

		return false;
	} else if (client_data->read_data) {
		g_io_add_watch(io, G_IO_IN, client_received_data, NULL);
		bthost_send_rfcomm_data(hciemu_client_get_host(data->hciemu),
						data->conn_handle,
						client_data->client_channel,
						client_data->read_data,
						client_data->data_len);
		return false;
	}

	if (err < 0)
		tester_test_failed();
	else
		tester_test_passed();

	return false;
}
예제 #24
0
static void setup_powered_client_callback(uint8_t status, uint16_t length,
					const void *param, void *user_data)
{
	struct test_data *data = tester_get_data();
	struct bthost *bthost;

	if (status != MGMT_STATUS_SUCCESS) {
		tester_setup_failed();
		return;
	}

	tester_print("Controller powered on");

	bthost = hciemu_client_get_host(data->hciemu);
	bthost_set_cmd_complete_cb(bthost, client_connectable_complete, data);
	bthost_set_adv_enable(bthost, 0x01, 0x00);
}
예제 #25
0
static void map_client_conn_cb(uint16_t handle, void *user_data)
{
	struct test_data *data = tester_get_data();
	struct bthost *bthost = hciemu_client_get_host(data->hciemu);

	tester_print("New connection with handle 0x%04x", handle);

	if (data->hciemu_type == HCIEMU_TYPE_BREDR) {
		tester_warn("Not handled device type.");
		return;
	}

	cid_data.cid = 0x0040;
	cid_data.handle = handle;

	bthost_add_cid_hook(bthost, handle, cid_data.cid,
					map_client_cid_hook_cb, &cid_data);
}
예제 #26
0
static void send_rsp_new_conn(uint16_t handle, void *user_data)
{
	struct test_data *data = user_data;
	struct bthost *bthost;

	tester_print("New connection with handle 0x%04x", handle);

	data->handle = handle;

	if (data->hciemu_type == HCIEMU_TYPE_LE)
		data->dcid = 0x0005;
	else
		data->dcid = 0x0001;

	bthost = hciemu_client_get_host(data->hciemu);
	bthost_add_cid_hook(bthost, data->handle, data->dcid,
						bthost_send_rsp, NULL);
}
예제 #27
0
static gboolean test_close_socket_2_part_2(gpointer arg)
{
	struct test_data *data = tester_get_data();
	struct bthost *bthost = hciemu_client_get_host(data->hciemu);

	/* Make sure CMD_LE_CREATE_CONN will not immediately result in
	 * BT_HCI_EVT_CONN_COMPLETE.
	 */
	hciemu_add_hook(data->hciemu, HCIEMU_HOOK_PRE_EVT,
		BT_HCI_CMD_LE_CREATE_CONN, test_close_socket_cc_hook, NULL);

	/* Advertise once. After that, kernel should stop scanning, and trigger
	 * BT_HCI_CMD_LE_CREATE_CONN_CANCEL.
	 */
	bthost_set_adv_enable(bthost, 0x01);
	bthost_set_adv_enable(bthost, 0x00);
	return FALSE;
}
예제 #28
0
static void test_connect(const void *test_data)
{
	struct test_data *data = tester_get_data();
	const struct l2cap_data *l2data = data->test_data;
	GIOChannel *io;
	int sk;

	if (l2data->server_psm) {
		struct bthost *bthost = hciemu_client_get_host(data->hciemu);

		if (!l2data->data_len)
			bthost_add_l2cap_server(bthost, l2data->server_psm,
						NULL, NULL);
		else
			bthost_add_l2cap_server(bthost, l2data->server_psm,
						client_l2cap_connect_cb, data);
	}

	if (l2data->direct_advertising)
		hciemu_add_master_post_command_hook(data->hciemu,
						direct_adv_cmd_complete, NULL);

	sk = create_l2cap_sock(data, 0, l2data->cid, l2data->sec_level);
	if (sk < 0) {
		tester_test_failed();
		return;
	}

	if (connect_l2cap_sock(data, sk, l2data->client_psm,
							l2data->cid) < 0) {
		close(sk);
		tester_test_failed();
		return;
	}

	io = g_io_channel_unix_new(sk);
	g_io_channel_set_close_on_unref(io, TRUE);

	data->io_id = g_io_add_watch(io, G_IO_OUT, l2cap_connect_cb, NULL);

	g_io_channel_unref(io);

	tester_print("Connect in progress");
}
예제 #29
0
static void setup_powered_client(const void *test_data)
{
	struct test_data *data = tester_get_data();
	const struct l2cap_data *test = data->test_data;
	unsigned char param[] = { 0x01 };

	setup_powered_common();

	tester_print("Powering on controller");

	if (test && (test->expect_cmd || test->send_cmd)) {
		struct bthost *bthost = hciemu_client_get_host(data->hciemu);
		bthost_set_connect_cb(bthost, send_rsp_new_conn, data);
	}

	mgmt_send(data->mgmt, MGMT_OP_SET_POWERED, data->mgmt_index,
			sizeof(param), param, setup_powered_client_callback,
			NULL, NULL);
}
예제 #30
0
static void test_server(const void *test_data)
{
	struct test_data *data = tester_get_data();
	const struct rfcomm_server_data *server_data = data->test_data;
	const uint8_t *master_addr;
	struct bthost *bthost;
	GIOChannel *io;
	int sk;

	master_addr = hciemu_get_master_bdaddr(data->hciemu);

	sk = create_rfcomm_sock((bdaddr_t *) master_addr,
						server_data->server_channel);
	if (sk < 0) {
		tester_test_failed();
		return;
	}

	if (listen(sk, 5) < 0) {
		tester_warn("listening on socket failed: %s (%u)",
				strerror(errno), errno);
		tester_test_failed();
		close(sk);
		return;
	}

	io = g_io_channel_unix_new(sk);
	g_io_channel_set_close_on_unref(io, TRUE);

	data->io_id = g_io_add_watch(io, G_IO_IN, rfcomm_listen_cb, NULL);
	g_io_channel_unref(io);

	tester_print("Listening for connections");

	bthost = hciemu_client_get_host(data->hciemu);
	bthost_set_connect_cb(bthost, client_new_conn, data);

	bthost_hci_connect(bthost, master_addr, BDADDR_BREDR);
}