summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@nokia.com>2008-09-05 11:38:07 +0300
committerJohan Hedberg <johan.hedberg@nokia.com>2008-09-05 11:38:07 +0300
commit1b971b060ba37714d970089e978fa720a2c9326c (patch)
tree14b87bf835c41d3c6664d06259064c5c65769dc1
parenta3634219a1f00b7386c55f34d6707690ff73b605 (diff)
Implement last number dialed (AT+BLDN) support
-rw-r--r--audio/headset.c74
-rw-r--r--audio/telephony-dummy.c12
-rw-r--r--audio/telephony.h27
3 files changed, 111 insertions, 2 deletions
diff --git a/audio/headset.c b/audio/headset.c
index 1ce4d99b..0785df91 100644
--- a/audio/headset.c
+++ b/audio/headset.c
@@ -62,6 +62,9 @@
#define RING_INTERVAL 3000
+/* Number of indicator events that can be queued */
+#define EV_BUF_SIZE 4
+
#define BUF_SIZE 1024
#define HEADSET_GAIN_SPEAKER 'S'
@@ -74,12 +77,19 @@ static struct {
int er_mode; /* Event reporting mode */
int er_ind; /* Event reporting for indicators */
int rh; /* Response and Hold state */
+ gboolean ev_buf_active; /* Buffer indicator events */
+ struct {
+ int index; /* HFP indicator index */
+ int val; /* new indicator value */
+ } ev_buf[EV_BUF_SIZE]; /* Indicator event buffer */
} ag = {
.telephony_ready = FALSE,
.features = 0,
.er_mode = 3,
.er_ind = 0,
.rh = -1,
+ .ev_buf_active = FALSE,
+ .ev_buf = { { 0, 0 } },
};
static gboolean sco_hci = TRUE;
@@ -204,6 +214,49 @@ static int headset_send(struct headset *hs, char *format, ...)
return 0;
}
+static int buffer_event(int index)
+{
+ int i;
+
+ for (i = 0; i < EV_BUF_SIZE; i++) {
+ if (ag.ev_buf[i].index == 0) {
+ ag.ev_buf[i].index = index + 1;
+ ag.ev_buf[i].val = ag.indicators[index].val;
+ return 0;
+ }
+ }
+
+ error("No space in event buffer");
+ return -ENOSPC;
+}
+
+static int flush_events(void)
+{
+ int i;
+ struct headset *hs;
+
+ if (!active_telephony_device)
+ return -ENODEV;
+
+ hs = active_telephony_device->headset;
+
+ for (i = 0; i < EV_BUF_SIZE; i++) {
+ int ret;
+
+ if (ag.ev_buf[i].index == 0)
+ break;
+
+ ret = headset_send(hs, "\r\n+CIEV:%d,%d\r\n",
+ ag.ev_buf[i].index, ag.ev_buf[i].val);
+ if (ret < 0)
+ return ret;
+
+ ag.ev_buf[i].index = 0;
+ }
+
+ return 0;
+}
+
static int supported_features(struct audio_device *device, const char *buf)
{
struct headset *hs = device->headset;
@@ -622,6 +675,23 @@ static int response_and_hold(struct audio_device *device, const char *buf)
return headset_send(hs, "\r\nOK\n\r", ag.rh);
}
+static int last_dialed_number(struct audio_device *device, const char *buf)
+{
+ struct headset *hs = device->headset;
+
+ ag.ev_buf_active = TRUE;
+
+ if (telephony_last_dialed_number() < 0) {
+ headset_send(hs, "\r\nERROR\r\n");
+ return 0;
+ }
+
+ flush_events();
+ ag.ev_buf_active = FALSE;
+
+ return headset_send(hs, "\r\nOK\n\r", ag.rh);
+}
+
static int signal_gain_setting(struct audio_device *device, const char *buf)
{
struct headset *hs = device->headset;
@@ -678,6 +748,7 @@ static struct event event_callbacks[] = {
{ "AT+CKPD", answer_call },
{ "AT+CLIP", cli_notification },
{ "AT+BTRH", response_and_hold },
+ { "AT+BLDN", last_dialed_number },
{ 0 }
};
@@ -2013,6 +2084,9 @@ int telephony_event_ind(int index)
return -EINVAL;
}
+ if (ag.ev_buf_active)
+ return buffer_event(index);
+
return headset_send(hs, "\r\n+CIEV:%d,%d\r\n", index + 1,
ag.indicators[index].val);
}
diff --git a/audio/telephony-dummy.c b/audio/telephony-dummy.c
index 6c003066..46637b95 100644
--- a/audio/telephony-dummy.c
+++ b/audio/telephony-dummy.c
@@ -43,7 +43,7 @@ static gboolean events_enabled = FALSE;
*/
static int response_and_hold = -1;
-static struct indicator indicators[] =
+static struct indicator dummy_indicators[] =
{
{ "battchg", "0-5", 5 },
{ "signal", "0-5", 5 },
@@ -71,11 +71,19 @@ int telephony_response_and_hold_req(int rh)
return 0;
}
+int telephony_last_dialed_number(void)
+{
+ /* Notify outgoing call set-up successfully initiated */
+ telephony_update_indicator(dummy_indicators, "callsetup", 2);
+
+ return 0;
+}
+
int telephony_init(void)
{
uint32_t features = 0;
- telephony_ready(features, indicators, response_and_hold);
+ telephony_ready(features, dummy_indicators, response_and_hold);
return 0;
}
diff --git a/audio/telephony.h b/audio/telephony.h
index 4cc74ede..398f98df 100644
--- a/audio/telephony.h
+++ b/audio/telephony.h
@@ -23,6 +23,8 @@
*/
#include <stdint.h>
+#include <errno.h>
+#include <glib.h>
#define AG_FEATURE_THREE_WAY_CALLING 0x0001
#define AG_FEATURE_EC_ANDOR_NR 0x0002
@@ -48,7 +50,32 @@ int telephony_response_and_hold_req(int rh);
int telephony_response_and_hold_ind(int rh);
+int telephony_last_dialed_number(void);
+
int telephony_ready(uint32_t features, struct indicator *indicators, int rh);
+/* Helper function for quick indicator updates */
+static inline int telephony_update_indicator(struct indicator *indicators,
+ const char *desc,
+ int new_val)
+{
+ int i;
+ struct indicator *ind = NULL;
+
+ for (i = 0; indicators[i].desc != NULL; i++) {
+ if (g_str_equal(indicators[i].desc, desc)) {
+ ind = &indicators[i];
+ break;
+ }
+ }
+
+ if (!ind)
+ return -ENOENT;
+
+ ind->val = new_val;
+
+ return telephony_event_ind(i);
+}
+
int telephony_init(void);
void telephony_exit(void);