mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	bluez: native-backend: Handle AT commands replies for HFP HF
This commit is contained in:
		
							parent
							
								
									18c447b0a4
								
							
						
					
					
						commit
						613021137c
					
				
					 1 changed files with 148 additions and 14 deletions
				
			
		| 
						 | 
					@ -5,6 +5,8 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <errno.h>
 | 
					#include <errno.h>
 | 
				
			||||||
#include <stdbool.h>
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <sys/poll.h>
 | 
				
			||||||
#include <unistd.h>
 | 
					#include <unistd.h>
 | 
				
			||||||
#include <stdarg.h>
 | 
					#include <stdarg.h>
 | 
				
			||||||
#include <sys/types.h>
 | 
					#include <sys/types.h>
 | 
				
			||||||
| 
						 | 
					@ -1239,29 +1241,115 @@ next_indicator:
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool rfcomm_hfp_hf(struct rfcomm *rfcomm, char* token);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool hfp_hf_wait_for_reply(struct rfcomm *rfcomm, char *buf, size_t len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct impl *backend = rfcomm->backend;
 | 
				
			||||||
 | 
						struct pollfd fds[1];
 | 
				
			||||||
 | 
						bool reply_found = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fds[0].fd = rfcomm->source.fd;
 | 
				
			||||||
 | 
						fds[0].events = POLLIN;
 | 
				
			||||||
 | 
						while (!reply_found) {
 | 
				
			||||||
 | 
							int ret;
 | 
				
			||||||
 | 
							char tmp_buf[512];
 | 
				
			||||||
 | 
							ssize_t tmp_len;
 | 
				
			||||||
 | 
							char *ptr, *token;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ret = poll(fds, 1, 2000);
 | 
				
			||||||
 | 
							if (ret < 0) {
 | 
				
			||||||
 | 
								spa_log_error(backend->log, "RFCOMM poll error: %s", strerror(errno));
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							} else if (ret == 0) {
 | 
				
			||||||
 | 
								spa_log_error(backend->log, "RFCOMM poll timeout");
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (fds[0].revents & (POLLHUP | POLLERR)) {
 | 
				
			||||||
 | 
								spa_log_info(backend->log, "lost RFCOMM connection.");
 | 
				
			||||||
 | 
								rfcomm_free(rfcomm);
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (fds[0].revents & POLLIN) {
 | 
				
			||||||
 | 
								tmp_len = read(rfcomm->source.fd, tmp_buf, sizeof(tmp_buf) - 1);
 | 
				
			||||||
 | 
								if (tmp_len < 0) {
 | 
				
			||||||
 | 
									spa_log_error(backend->log, "RFCOMM read error: %s", strerror(errno));
 | 
				
			||||||
 | 
									return false;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								tmp_buf[tmp_len] = '\0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								/* Relaxed parsing of \r\n<REPLY>\r\n */
 | 
				
			||||||
 | 
								ptr = tmp_buf;
 | 
				
			||||||
 | 
								while ((token = strsep(&ptr, "\r"))) {
 | 
				
			||||||
 | 
									size_t ptr_len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									/* Skip leading and trailing \n */
 | 
				
			||||||
 | 
									while (*token == '\n')
 | 
				
			||||||
 | 
										++token;
 | 
				
			||||||
 | 
									for (ptr_len = strlen(token); ptr_len > 0 && token[ptr_len - 1] == '\n'; --ptr_len)
 | 
				
			||||||
 | 
										token[ptr_len - 1] = '\0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									/* Skip empty */
 | 
				
			||||||
 | 
									if (*token == '\0' /*&& buf == NULL*/)
 | 
				
			||||||
 | 
										continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									spa_log_debug(backend->log, "RFCOMM event: %s", token);
 | 
				
			||||||
 | 
									if (spa_strstartswith(token, "OK") || spa_strstartswith(token, "ERROR")) {
 | 
				
			||||||
 | 
										spa_log_debug(backend->log, "RFCOMM reply found: %s", token);
 | 
				
			||||||
 | 
										reply_found = true;
 | 
				
			||||||
 | 
										strncpy(buf, token, len);
 | 
				
			||||||
 | 
										buf[len-1] = '\0';
 | 
				
			||||||
 | 
									} else if (!rfcomm_hfp_hf(rfcomm, token)) {
 | 
				
			||||||
 | 
										spa_log_debug(backend->log, "RFCOMM received unsupported event: %s", token);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return reply_found;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int hfp_hf_answer(void *data) {
 | 
					static int hfp_hf_answer(void *data) {
 | 
				
			||||||
	struct rfcomm_call_data *call_data = telephony_call_get_user_data(data);
 | 
						struct rfcomm_call_data *call_data = telephony_call_get_user_data(data);
 | 
				
			||||||
 | 
						struct rfcomm *rfcomm = call_data->rfcomm;
 | 
				
			||||||
 | 
						struct impl *backend = rfcomm->backend;
 | 
				
			||||||
 | 
						char reply[20];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (call_data->call->state != CALL_STATE_INCOMING)
 | 
						if (call_data->call->state != CALL_STATE_INCOMING)
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rfcomm_send_cmd(call_data->rfcomm, "ATA");
 | 
						rfcomm_send_cmd(rfcomm, "ATA");
 | 
				
			||||||
 | 
						if (!hfp_hf_wait_for_reply(rfcomm, reply, sizeof(reply)) || !spa_strstartswith(reply, "OK")) {
 | 
				
			||||||
 | 
							spa_log_info(backend->log, "Failed to answer call");
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int hfp_hf_hangup(void *data) {
 | 
					static int hfp_hf_hangup(void *data) {
 | 
				
			||||||
	struct rfcomm_call_data *call_data = telephony_call_get_user_data(data);
 | 
						struct rfcomm_call_data *call_data = telephony_call_get_user_data(data);
 | 
				
			||||||
 | 
						struct rfcomm *rfcomm = call_data->rfcomm;
 | 
				
			||||||
 | 
						struct impl *backend = rfcomm->backend;
 | 
				
			||||||
 | 
						char reply[20];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (call_data->call->state == CALL_STATE_INCOMING || call_data->call->state == CALL_STATE_ACTIVE) {
 | 
						if (call_data->call->state == CALL_STATE_INCOMING || call_data->call->state == CALL_STATE_ACTIVE) {
 | 
				
			||||||
		rfcomm_send_cmd(call_data->rfcomm, "AT+CHUP");
 | 
							rfcomm_send_cmd(rfcomm, "AT+CHUP");
 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
	} else if (call_data->call->state == CALL_STATE_WAITING) {
 | 
						} else if (call_data->call->state == CALL_STATE_WAITING) {
 | 
				
			||||||
		rfcomm_send_cmd(call_data->rfcomm, "AT+CHLD=0");
 | 
							rfcomm_send_cmd(rfcomm, "AT+CHLD=0");
 | 
				
			||||||
		return 0;
 | 
						} else {
 | 
				
			||||||
 | 
							spa_log_info(backend->log, "Call not incoming, waiting or active: skip hangup");
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return -1;
 | 
						if (!hfp_hf_wait_for_reply(rfcomm, reply, sizeof(reply)) || !spa_strstartswith(reply, "OK")) {
 | 
				
			||||||
 | 
							spa_log_info(backend->log, "Failed to hangup call");
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const struct spa_bt_telephony_call_events telephony_call_events = {
 | 
					static const struct spa_bt_telephony_call_events telephony_call_events = {
 | 
				
			||||||
| 
						 | 
					@ -1293,15 +1381,19 @@ static int hfp_hf_dial(void *data, const char *number)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct rfcomm *rfcomm = data;
 | 
						struct rfcomm *rfcomm = data;
 | 
				
			||||||
	struct impl *backend = rfcomm->backend;
 | 
						struct impl *backend = rfcomm->backend;
 | 
				
			||||||
	struct spa_bt_telephony_call *call;
 | 
						char reply[20];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_log_info(backend->log, "Dialing: \"%s\"", number);
 | 
						spa_log_info(backend->log, "Dialing: \"%s\"", number);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	call = hfp_hf_add_call(rfcomm, rfcomm->telephony_ag, CALL_STATE_DIALING, number);
 | 
					 | 
				
			||||||
	if (!call)
 | 
					 | 
				
			||||||
		return -1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	rfcomm_send_cmd(rfcomm, "ATD%s;", number);
 | 
						rfcomm_send_cmd(rfcomm, "ATD%s;", number);
 | 
				
			||||||
 | 
						if (hfp_hf_wait_for_reply(rfcomm, reply, sizeof(reply)) && spa_strstartswith(reply, "OK")) {
 | 
				
			||||||
 | 
							struct spa_bt_telephony_call *call;
 | 
				
			||||||
 | 
							call = hfp_hf_add_call(rfcomm, rfcomm->telephony_ag, CALL_STATE_DIALING, number);
 | 
				
			||||||
 | 
							if (!call)
 | 
				
			||||||
 | 
								return -1;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							spa_log_info(backend->log, "Failed to dial: \"%s\"", number);
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1313,6 +1405,7 @@ static int hfp_hf_swap_calls(void *data)
 | 
				
			||||||
	struct spa_bt_telephony_call *call;
 | 
						struct spa_bt_telephony_call *call;
 | 
				
			||||||
	bool found_active = false;
 | 
						bool found_active = false;
 | 
				
			||||||
	bool found_held = false;
 | 
						bool found_held = false;
 | 
				
			||||||
 | 
						char reply[20];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!rfcomm->chld_supported)
 | 
						if (!rfcomm->chld_supported)
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
| 
						 | 
					@ -1333,6 +1426,10 @@ static int hfp_hf_swap_calls(void *data)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rfcomm_send_cmd(rfcomm, "AT+CHLD=2");
 | 
						rfcomm_send_cmd(rfcomm, "AT+CHLD=2");
 | 
				
			||||||
 | 
						if (!hfp_hf_wait_for_reply(rfcomm, reply, sizeof(reply)) || !spa_strstartswith(reply, "OK")) {
 | 
				
			||||||
 | 
							spa_log_info(backend->log, "Failed to swap calls");
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_list_for_each(call, &rfcomm->telephony_ag->call_list, link) {
 | 
						spa_list_for_each(call, &rfcomm->telephony_ag->call_list, link) {
 | 
				
			||||||
		bool changed = false;
 | 
							bool changed = false;
 | 
				
			||||||
| 
						 | 
					@ -1358,6 +1455,7 @@ static int hfp_hf_release_and_answer(void *data)
 | 
				
			||||||
	struct spa_bt_telephony_call *call, *tcall;
 | 
						struct spa_bt_telephony_call *call, *tcall;
 | 
				
			||||||
	bool found_active = false;
 | 
						bool found_active = false;
 | 
				
			||||||
	bool found_waiting = false;
 | 
						bool found_waiting = false;
 | 
				
			||||||
 | 
						char reply[20];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!rfcomm->chld_supported)
 | 
						if (!rfcomm->chld_supported)
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
| 
						 | 
					@ -1375,6 +1473,10 @@ static int hfp_hf_release_and_answer(void *data)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rfcomm_send_cmd(rfcomm, "AT+CHLD=1");
 | 
						rfcomm_send_cmd(rfcomm, "AT+CHLD=1");
 | 
				
			||||||
 | 
						if (!hfp_hf_wait_for_reply(rfcomm, reply, sizeof(reply)) || !spa_strstartswith(reply, "OK")) {
 | 
				
			||||||
 | 
							spa_log_info(backend->log, "Failed to release and answer calls");
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_list_for_each_safe(call, tcall, &rfcomm->telephony_ag->call_list, link) {
 | 
						spa_list_for_each_safe(call, tcall, &rfcomm->telephony_ag->call_list, link) {
 | 
				
			||||||
		if (call->state == CALL_STATE_ACTIVE) {
 | 
							if (call->state == CALL_STATE_ACTIVE) {
 | 
				
			||||||
| 
						 | 
					@ -1397,6 +1499,7 @@ static int hfp_hf_release_and_swap(void *data)
 | 
				
			||||||
	struct spa_bt_telephony_call *call, *tcall;
 | 
						struct spa_bt_telephony_call *call, *tcall;
 | 
				
			||||||
	bool found_active = false;
 | 
						bool found_active = false;
 | 
				
			||||||
	bool found_held = false;
 | 
						bool found_held = false;
 | 
				
			||||||
 | 
						char reply[20];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!rfcomm->chld_supported)
 | 
						if (!rfcomm->chld_supported)
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
| 
						 | 
					@ -1417,6 +1520,10 @@ static int hfp_hf_release_and_swap(void *data)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rfcomm_send_cmd(rfcomm, "AT+CHLD=1");
 | 
						rfcomm_send_cmd(rfcomm, "AT+CHLD=1");
 | 
				
			||||||
 | 
						if (!hfp_hf_wait_for_reply(rfcomm, reply, sizeof(reply)) || !spa_strstartswith(reply, "OK")) {
 | 
				
			||||||
 | 
							spa_log_info(backend->log, "Failed to release and swap calls");
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_list_for_each_safe(call, tcall, &rfcomm->telephony_ag->call_list, link) {
 | 
						spa_list_for_each_safe(call, tcall, &rfcomm->telephony_ag->call_list, link) {
 | 
				
			||||||
		if (call->state == CALL_STATE_ACTIVE) {
 | 
							if (call->state == CALL_STATE_ACTIVE) {
 | 
				
			||||||
| 
						 | 
					@ -1439,6 +1546,7 @@ static int hfp_hf_hold_and_answer(void *data)
 | 
				
			||||||
	struct spa_bt_telephony_call *call;
 | 
						struct spa_bt_telephony_call *call;
 | 
				
			||||||
	bool found_active = false;
 | 
						bool found_active = false;
 | 
				
			||||||
	bool found_waiting = false;
 | 
						bool found_waiting = false;
 | 
				
			||||||
 | 
						char reply[20];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!rfcomm->chld_supported)
 | 
						if (!rfcomm->chld_supported)
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
| 
						 | 
					@ -1456,6 +1564,10 @@ static int hfp_hf_hold_and_answer(void *data)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rfcomm_send_cmd(rfcomm, "AT+CHLD=2");
 | 
						rfcomm_send_cmd(rfcomm, "AT+CHLD=2");
 | 
				
			||||||
 | 
						if (!hfp_hf_wait_for_reply(rfcomm, reply, sizeof(reply)) || !spa_strstartswith(reply, "OK")) {
 | 
				
			||||||
 | 
							spa_log_info(backend->log, "Failed to hold and answer calls");
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_list_for_each(call, &rfcomm->telephony_ag->call_list, link) {
 | 
						spa_list_for_each(call, &rfcomm->telephony_ag->call_list, link) {
 | 
				
			||||||
		bool changed = false;
 | 
							bool changed = false;
 | 
				
			||||||
| 
						 | 
					@ -1477,15 +1589,27 @@ static int hfp_hf_hold_and_answer(void *data)
 | 
				
			||||||
static int hfp_hf_hangup_all(void *data)
 | 
					static int hfp_hf_hangup_all(void *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct rfcomm *rfcomm = data;
 | 
						struct rfcomm *rfcomm = data;
 | 
				
			||||||
 | 
						struct impl *backend = rfcomm->backend;
 | 
				
			||||||
 | 
						char reply[20];
 | 
				
			||||||
 | 
						int ret = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Hangup held calls */
 | 
						/* Hangup held calls */
 | 
				
			||||||
	if (rfcomm->chld_supported)
 | 
						if (rfcomm->chld_supported) {
 | 
				
			||||||
		rfcomm_send_cmd(rfcomm, "AT+CHLD=0");
 | 
							rfcomm_send_cmd(rfcomm, "AT+CHLD=0");
 | 
				
			||||||
 | 
							if (!hfp_hf_wait_for_reply(rfcomm, reply, sizeof(reply)) || !spa_strstartswith(reply, "OK")) {
 | 
				
			||||||
 | 
								spa_log_info(backend->log, "Failed to hangup held calls");
 | 
				
			||||||
 | 
								ret = -1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Hangup active calls */
 | 
						/* Hangup active calls */
 | 
				
			||||||
	rfcomm_send_cmd(rfcomm, "AT+CHUP");
 | 
						rfcomm_send_cmd(rfcomm, "AT+CHUP");
 | 
				
			||||||
 | 
						if (!hfp_hf_wait_for_reply(rfcomm, reply, sizeof(reply)) || !spa_strstartswith(reply, "OK")) {
 | 
				
			||||||
 | 
							spa_log_info(backend->log, "Failed to hangup active calls");
 | 
				
			||||||
 | 
							ret = -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int hfp_hf_create_multiparty(void *data)
 | 
					static int hfp_hf_create_multiparty(void *data)
 | 
				
			||||||
| 
						 | 
					@ -1495,6 +1619,7 @@ static int hfp_hf_create_multiparty(void *data)
 | 
				
			||||||
	struct spa_bt_telephony_call *call;
 | 
						struct spa_bt_telephony_call *call;
 | 
				
			||||||
	bool found_active = false;
 | 
						bool found_active = false;
 | 
				
			||||||
	bool found_held = false;
 | 
						bool found_held = false;
 | 
				
			||||||
 | 
						char reply[20];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_list_for_each(call, &rfcomm->telephony_ag->call_list, link) {
 | 
						spa_list_for_each(call, &rfcomm->telephony_ag->call_list, link) {
 | 
				
			||||||
		if (call->state == CALL_STATE_WAITING) {
 | 
							if (call->state == CALL_STATE_WAITING) {
 | 
				
			||||||
| 
						 | 
					@ -1512,6 +1637,10 @@ static int hfp_hf_create_multiparty(void *data)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rfcomm_send_cmd(rfcomm, "AT+CHLD=3");
 | 
						rfcomm_send_cmd(rfcomm, "AT+CHLD=3");
 | 
				
			||||||
 | 
						if (!hfp_hf_wait_for_reply(rfcomm, reply, sizeof(reply)) || !spa_strstartswith(reply, "OK")) {
 | 
				
			||||||
 | 
							spa_log_info(backend->log, "Failed to create multiparty");
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_list_for_each(call, &rfcomm->telephony_ag->call_list, link) {
 | 
						spa_list_for_each(call, &rfcomm->telephony_ag->call_list, link) {
 | 
				
			||||||
		bool changed = false;
 | 
							bool changed = false;
 | 
				
			||||||
| 
						 | 
					@ -1537,6 +1666,7 @@ static int hfp_hf_send_tones(void *data, const char *tones)
 | 
				
			||||||
	struct impl *backend = rfcomm->backend;
 | 
						struct impl *backend = rfcomm->backend;
 | 
				
			||||||
	struct spa_bt_telephony_call *call;
 | 
						struct spa_bt_telephony_call *call;
 | 
				
			||||||
	bool found = false;
 | 
						bool found = false;
 | 
				
			||||||
 | 
						char reply[20];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_list_for_each(call, &rfcomm->telephony_ag->call_list, link) {
 | 
						spa_list_for_each(call, &rfcomm->telephony_ag->call_list, link) {
 | 
				
			||||||
		if (call->state == CALL_STATE_ACTIVE) {
 | 
							if (call->state == CALL_STATE_ACTIVE) {
 | 
				
			||||||
| 
						 | 
					@ -1551,6 +1681,10 @@ static int hfp_hf_send_tones(void *data, const char *tones)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rfcomm_send_cmd(rfcomm, "AT+VTS=%s", tones);
 | 
						rfcomm_send_cmd(rfcomm, "AT+VTS=%s", tones);
 | 
				
			||||||
 | 
						if (!hfp_hf_wait_for_reply(rfcomm, reply, sizeof(reply)) || !spa_strstartswith(reply, "OK")) {
 | 
				
			||||||
 | 
							spa_log_info(backend->log, "Failed to send tones: %s", tones);
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue