mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	bluez5: backend-native: Add AT+VTS support
This allows to send a DTMF key on an active call.
This commit is contained in:
		
							parent
							
								
									7c05574072
								
							
						
					
					
						commit
						a37aeac273
					
				
					 3 changed files with 83 additions and 0 deletions
				
			
		| 
						 | 
					@ -1119,6 +1119,21 @@ next_indicator:
 | 
				
			||||||
			rfcomm_send_error(rfcomm, error);
 | 
								rfcomm_send_error(rfcomm, error);
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						} else if (spa_strstartswith(buf, "AT+VTS=")) {
 | 
				
			||||||
 | 
							char *dtmf;
 | 
				
			||||||
 | 
							enum cmee_error error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							dtmf = calloc(1, 2);
 | 
				
			||||||
 | 
							if (sscanf(buf, "AT+VTS=%1s", dtmf) != 1) {
 | 
				
			||||||
 | 
								spa_log_debug(backend->log, "Failed to parse AT+VTS: \"%s\"", buf);
 | 
				
			||||||
 | 
								rfcomm_send_error(rfcomm, CMEE_AG_FAILURE);
 | 
				
			||||||
 | 
								return true;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!mm_send_dtmf(backend->modemmanager, dtmf, rfcomm, &error)) {
 | 
				
			||||||
 | 
								rfcomm_send_error(rfcomm, error);
 | 
				
			||||||
 | 
								return true;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1040,6 +1040,66 @@ bool mm_do_call(void *modemmanager, const char* number, void *user_data, enum cm
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool mm_send_dtmf(void *modemmanager, const char *dtmf, void *user_data, enum cmee_error *error)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct impl *this = modemmanager;
 | 
				
			||||||
 | 
						struct call *call_object, *call_tmp;
 | 
				
			||||||
 | 
						struct dbus_cmd_data *data;
 | 
				
			||||||
 | 
						DBusMessage *m;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						call_object = NULL;
 | 
				
			||||||
 | 
						spa_list_for_each(call_tmp, &this->call_list, link) {
 | 
				
			||||||
 | 
							if (call_tmp->state == CLCC_ACTIVE) {
 | 
				
			||||||
 | 
								call_object = call_tmp;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (!call_object) {
 | 
				
			||||||
 | 
							spa_log_debug(this->log, "No active call");
 | 
				
			||||||
 | 
							if (error)
 | 
				
			||||||
 | 
								*error = CMEE_OPERATION_NOT_ALLOWED;
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Allowed dtmf characters: 0-9, *, #, A-D */
 | 
				
			||||||
 | 
						if (!((dtmf[0] >= '0' && dtmf[0] <= '9')
 | 
				
			||||||
 | 
						    || (dtmf[0] == '*')
 | 
				
			||||||
 | 
						    || (dtmf[0] == '#')
 | 
				
			||||||
 | 
						    || (dtmf[0] >= 'A' && dtmf[0] <= 'D'))) {
 | 
				
			||||||
 | 
							spa_log_debug(this->log, "Invalid DTMF character: %s", dtmf);
 | 
				
			||||||
 | 
							if (error)
 | 
				
			||||||
 | 
								*error = CMEE_INVALID_CHARACTERS_TEXT_STRING;
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						data = malloc(sizeof(struct dbus_cmd_data));
 | 
				
			||||||
 | 
						if (!data) {
 | 
				
			||||||
 | 
							if (error)
 | 
				
			||||||
 | 
								*error = CMEE_AG_FAILURE;
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						data->this = this;
 | 
				
			||||||
 | 
						data->call = call_object;
 | 
				
			||||||
 | 
						data->user_data = user_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						m = dbus_message_new_method_call(MM_DBUS_SERVICE, call_object->path, MM_DBUS_INTERFACE_CALL, MM_CALL_METHOD_SENDDTMF);
 | 
				
			||||||
 | 
						if (m == NULL) {
 | 
				
			||||||
 | 
							if (error)
 | 
				
			||||||
 | 
								*error = CMEE_AG_FAILURE;
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						dbus_message_append_args(m, DBUS_TYPE_STRING, &dtmf, DBUS_TYPE_INVALID);
 | 
				
			||||||
 | 
						if (!mm_dbus_connection_send_with_reply(this, m, &call_object->pending, mm_get_call_simple_reply, data)) {
 | 
				
			||||||
 | 
							spa_log_error(this->log, "dbus call failure");
 | 
				
			||||||
 | 
							dbus_message_unref(m);
 | 
				
			||||||
 | 
							if (error)
 | 
				
			||||||
 | 
								*error = CMEE_AG_FAILURE;
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const char *mm_get_incoming_call_number(void *modemmanager)
 | 
					const char *mm_get_incoming_call_number(void *modemmanager)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct impl *this = modemmanager;
 | 
						struct impl *this = modemmanager;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -94,6 +94,7 @@ unsigned int mm_supported_features();
 | 
				
			||||||
bool mm_answer_call(void *modemmanager, void *user_data, enum cmee_error *error);
 | 
					bool mm_answer_call(void *modemmanager, void *user_data, enum cmee_error *error);
 | 
				
			||||||
bool mm_hangup_call(void *modemmanager, void *user_data, enum cmee_error *error);
 | 
					bool mm_hangup_call(void *modemmanager, void *user_data, enum cmee_error *error);
 | 
				
			||||||
bool mm_do_call(void *modemmanager, const char* number, void *user_data, enum cmee_error *error);
 | 
					bool mm_do_call(void *modemmanager, const char* number, void *user_data, enum cmee_error *error);
 | 
				
			||||||
 | 
					bool mm_send_dtmf(void *modemmanager, const char *dtmf, void *user_data, enum cmee_error *error);
 | 
				
			||||||
const char *mm_get_incoming_call_number(void *modemmanager);
 | 
					const char *mm_get_incoming_call_number(void *modemmanager);
 | 
				
			||||||
struct spa_list *mm_get_calls(void *modemmanager);
 | 
					struct spa_list *mm_get_calls(void *modemmanager);
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
| 
						 | 
					@ -137,6 +138,13 @@ bool mm_do_call(void *modemmanager, const char* number, void *user_data, enum cm
 | 
				
			||||||
	return false;
 | 
						return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool mm_send_dtmf(void *modemmanager, const char *dtmf, void *user_data, enum cmee_error *error)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (error)
 | 
				
			||||||
 | 
							*error = CMEE_OPERATION_NOT_SUPPORTED;
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const char *mm_get_incoming_call_number(void *modemmanager)
 | 
					const char *mm_get_incoming_call_number(void *modemmanager)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue