1/*
2 *
3 *  BlueZ - Bluetooth protocol stack for Linux
4 *
5 *  Copyright (C) 2006-2010  Nokia Corporation
6 *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
7 *
8 *
9 *  This program is free software; you can redistribute it and/or modify
10 *  it under the terms of the GNU General Public License as published by
11 *  the Free Software Foundation; either version 2 of the License, or
12 *  (at your option) any later version.
13 *
14 *  This program is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this program; if not, write to the Free Software
21 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
22 *
23 */
24
25#include <stdint.h>
26#include <errno.h>
27#include <glib.h>
28
29/* Response and hold values */
30#define BTRH_NOT_SUPPORTED	-2
31#define BTRH_NONE		-1
32#define BTRH_HOLD		0
33#define BTRH_ACCEPT		1
34#define BTRH_REJECT		2
35
36/* HFP feature bits */
37#define AG_FEATURE_THREE_WAY_CALLING		0x0001
38#define AG_FEATURE_EC_ANDOR_NR			0x0002
39#define AG_FEATURE_VOICE_RECOGNITION		0x0004
40#define AG_FEATURE_INBAND_RINGTONE		0x0008
41#define AG_FEATURE_ATTACH_NUMBER_TO_VOICETAG	0x0010
42#define AG_FEATURE_REJECT_A_CALL		0x0020
43#define AG_FEATURE_ENHANCED_CALL_STATUS		0x0040
44#define AG_FEATURE_ENHANCED_CALL_CONTROL	0x0080
45#define AG_FEATURE_EXTENDED_ERROR_RESULT_CODES	0x0100
46
47#define HF_FEATURE_EC_ANDOR_NR			0x0001
48#define HF_FEATURE_CALL_WAITING_AND_3WAY	0x0002
49#define HF_FEATURE_CLI_PRESENTATION		0x0004
50#define HF_FEATURE_VOICE_RECOGNITION		0x0008
51#define HF_FEATURE_REMOTE_VOLUME_CONTROL	0x0010
52#define HF_FEATURE_ENHANCED_CALL_STATUS		0x0020
53#define HF_FEATURE_ENHANCED_CALL_CONTROL	0x0040
54
55/* Indicator event values */
56#define EV_SERVICE_NONE			0
57#define EV_SERVICE_PRESENT		1
58
59#define EV_CALL_INACTIVE		0
60#define EV_CALL_ACTIVE			1
61
62#define EV_CALLSETUP_INACTIVE		0
63#define EV_CALLSETUP_INCOMING		1
64#define EV_CALLSETUP_OUTGOING		2
65#define EV_CALLSETUP_ALERTING		3
66
67#define EV_CALLHELD_NONE		0
68#define EV_CALLHELD_MULTIPLE		1
69#define EV_CALLHELD_ON_HOLD		2
70
71#define EV_ROAM_INACTIVE		0
72#define EV_ROAM_ACTIVE			1
73
74/* Call parameters */
75#define CALL_DIR_OUTGOING		0
76#define CALL_DIR_INCOMING		1
77
78#define CALL_STATUS_ACTIVE		0
79#define CALL_STATUS_HELD		1
80#define CALL_STATUS_DIALING		2
81#define CALL_STATUS_ALERTING		3
82#define CALL_STATUS_INCOMING		4
83#define CALL_STATUS_WAITING		5
84
85#define CALL_MODE_VOICE			0
86#define CALL_MODE_DATA			1
87#define CALL_MODE_FAX			2
88
89#define CALL_MULTIPARTY_NO		0
90#define CALL_MULTIPARTY_YES		1
91
92/* Subscriber number parameters */
93#define SUBSCRIBER_SERVICE_VOICE	4
94#define SUBSCRIBER_SERVICE_FAX		5
95
96/* Operator selection mode values */
97#define OPERATOR_MODE_AUTO		0
98#define OPERATOR_MODE_MANUAL		1
99#define OPERATOR_MODE_DEREGISTER	2
100#define OPERATOR_MODE_MANUAL_AUTO	4
101
102/* Some common number types */
103#define NUMBER_TYPE_UNKNOWN		128
104#define NUMBER_TYPE_TELEPHONY		129
105#define NUMBER_TYPE_INTERNATIONAL	145
106#define NUMBER_TYPE_NATIONAL		161
107#define NUMBER_TYPE_VOIP		255
108
109/* Extended Audio Gateway Error Result Codes */
110typedef enum {
111	CME_ERROR_NONE			= -1,
112	CME_ERROR_AG_FAILURE		= 0,
113	CME_ERROR_NO_PHONE_CONNECTION	= 1,
114	CME_ERROR_NOT_ALLOWED		= 3,
115	CME_ERROR_NOT_SUPPORTED		= 4,
116	CME_ERROR_PH_SIM_PIN_REQUIRED	= 5,
117	CME_ERROR_SIM_NOT_INSERTED	= 10,
118	CME_ERROR_SIM_PIN_REQUIRED	= 11,
119	CME_ERROR_SIM_PUK_REQUIRED	= 12,
120	CME_ERROR_SIM_FAILURE		= 13,
121	CME_ERROR_SIM_BUSY		= 14,
122	CME_ERROR_INCORRECT_PASSWORD	= 16,
123	CME_ERROR_SIM_PIN2_REQUIRED	= 17,
124	CME_ERROR_SIM_PUK2_REQUIRED	= 18,
125	CME_ERROR_MEMORY_FULL		= 20,
126	CME_ERROR_INVALID_INDEX		= 21,
127	CME_ERROR_MEMORY_FAILURE	= 23,
128	CME_ERROR_TEXT_STRING_TOO_LONG	= 24,
129	CME_ERROR_INVALID_TEXT_STRING	= 25,
130	CME_ERROR_DIAL_STRING_TOO_LONG	= 26,
131	CME_ERROR_INVALID_DIAL_STRING	= 27,
132	CME_ERROR_NO_NETWORK_SERVICE	= 30,
133	CME_ERROR_NETWORK_TIMEOUT	= 31,
134	CME_ERROR_NETWORK_NOT_ALLOWED	= 32,
135} cme_error_t;
136
137struct indicator {
138	const char *desc;
139	const char *range;
140	int val;
141	gboolean ignore_redundant;
142};
143
144/* Notify telephony-*.c of connected/disconnected devices. Implemented by
145 * telephony-*.c
146 */
147void telephony_device_connected(void *telephony_device);
148void telephony_device_disconnected(void *telephony_device);
149
150/* HF requests (sent by the handsfree device). These are implemented by
151 * telephony-*.c
152 */
153void telephony_event_reporting_req(void *telephony_device, int ind);
154void telephony_response_and_hold_req(void *telephony_device, int rh);
155void telephony_last_dialed_number_req(void *telephony_device);
156void telephony_terminate_call_req(void *telephony_device);
157void telephony_answer_call_req(void *telephony_device);
158void telephony_dial_number_req(void *telephony_device, const char *number);
159void telephony_transmit_dtmf_req(void *telephony_device, char tone);
160void telephony_subscriber_number_req(void *telephony_device);
161void telephony_list_current_calls_req(void *telephony_device);
162void telephony_operator_selection_req(void *telephony_device);
163void telephony_call_hold_req(void *telephony_device, const char *cmd);
164void telephony_nr_and_ec_req(void *telephony_device, gboolean enable);
165void telephony_voice_dial_req(void *telephony_device, gboolean enable);
166void telephony_key_press_req(void *telephony_device, const char *keys);
167
168/* AG responses to HF requests. These are implemented by headset.c */
169int telephony_event_reporting_rsp(void *telephony_device, cme_error_t err);
170int telephony_response_and_hold_rsp(void *telephony_device, cme_error_t err);
171int telephony_last_dialed_number_rsp(void *telephony_device, cme_error_t err);
172int telephony_terminate_call_rsp(void *telephony_device, cme_error_t err);
173int telephony_answer_call_rsp(void *telephony_device, cme_error_t err);
174int telephony_dial_number_rsp(void *telephony_device, cme_error_t err);
175int telephony_transmit_dtmf_rsp(void *telephony_device, cme_error_t err);
176int telephony_subscriber_number_rsp(void *telephony_device, cme_error_t err);
177int telephony_list_current_calls_rsp(void *telephony_device, cme_error_t err);
178int telephony_operator_selection_rsp(void *telephony_device, cme_error_t err);
179int telephony_call_hold_rsp(void *telephony_device, cme_error_t err);
180int telephony_nr_and_ec_rsp(void *telephony_device, cme_error_t err);
181int telephony_voice_dial_rsp(void *telephony_device, cme_error_t err);
182int telephony_key_press_rsp(void *telephony_device, cme_error_t err);
183
184/* Event indications by AG. These are implemented by headset.c */
185int telephony_event_ind(int index);
186int telephony_response_and_hold_ind(int rh);
187int telephony_incoming_call_ind(const char *number, int type);
188int telephony_calling_stopped_ind(void);
189int telephony_ready_ind(uint32_t features, const struct indicator *indicators,
190			int rh, const char *chld);
191int telephony_deinit(void);
192int telephony_list_current_call_ind(int idx, int dir, int status, int mode,
193					int mprty, const char *number,
194					int type);
195int telephony_subscriber_number_ind(const char *number, int type,
196					int service);
197int telephony_call_waiting_ind(const char *number, int type);
198int telephony_operator_selection_ind(int mode, const char *oper);
199
200/* Helper function for quick indicator updates */
201static inline int telephony_update_indicator(struct indicator *indicators,
202						const char *desc,
203						int new_val)
204{
205	int i;
206	struct indicator *ind = NULL;
207
208	for (i = 0; indicators[i].desc != NULL; i++) {
209		if (g_str_equal(indicators[i].desc, desc)) {
210			ind = &indicators[i];
211			break;
212		}
213	}
214
215	if (!ind)
216		return -ENOENT;
217
218	DBG("Telephony indicator \"%s\" %d->%d", desc, ind->val, new_val);
219
220	if (ind->ignore_redundant && ind->val == new_val) {
221		DBG("Ignoring no-change indication");
222		return 0;
223	}
224
225	ind->val = new_val;
226
227	return telephony_event_ind(i);
228}
229
230static inline int telephony_get_indicator(const struct indicator *indicators,
231						const char *desc)
232{
233	int i;
234
235	for (i = 0; indicators[i].desc != NULL; i++) {
236		if (g_str_equal(indicators[i].desc, desc))
237			return indicators[i].val;
238	}
239
240	return -ENOENT;
241}
242
243int telephony_init(void);
244void telephony_exit(void);
245