[RFC] HFP support into oFono and BlueZ
by Gustavo F. Padovan
Hi,
These patches implement the new API for the Audio Gateway in BlueZ. It
follows the last version of the HandsfreeGateway and HandsfreeAgent
Intefaces API.
The first two patches is for BlueZ and the other for oFono. You can
test it with using enable-modem and test-voicecall scripts into the
test dir of oFono.
Feel free to test it and send me your comments. We have some bugs yet.
The audio part is not working yet. We are going to work on pulseaudio
this week to get this done soon.
Regards,
--
Gustavo F. Padovan
ProFUSION embedded systems - http://profusion.mobi
8 years, 7 months
CDMA SMS Handling
by Rajesh.Nagaiah@elektrobit.com
Hi,
There was a discussion about the CDMA SMS handling and CDMA PDUs in the
IRC channel couple of days before. I would like to highlight the
differences between CDMA and GSM PDU and how we should proceed with this
from my understanding. Let me know your opinion.
Even though oFono supports +CMT and +CMTI, if we feed the incoming CDMA
PDUs to the SMS core it wont get decoded correctly, as there is
substantial differences between the GSM and CDMA SMS PDUs as described
in 3GPP2 specification C.S0015-B Short Message Service (SMS) for
Wideband Spread Spectrum Systems
For eg, the incoming PDU example that was mentioned in the IRC
discussion
+CMT: , 40,
00000210020207028CE95DCC65800601FC08150003168D30010610241830608003061010
04044847
40 - Length of the PDU in bytes
00 - Message Type ( 00 - SMS Point-to-Point)
00 - TeleService Identifier Tag (SMS Parameter Indentifier)
02 - TeleService Identifier Length (SMS Parameter Length)
10 - TeleService Identifier Value - First 8 bits
02 - TeleService Identifier Value - Second 8 bits
TeleService Identifier - 0x1002 - CDMA Messaging Teleservice
(CMT-95)
02 - Originating Address Tag
07 - Originating Address Length
02 - Originating Address 1st 8 Bits
8C - Originating Address 2nd 8 Bits
E9 - Originating Address 3rd 8 Bits
5D - Originating Address 4th 8 Bits
CC - Originating Address 5th 8 Bits
65 - Originating Address 6th 8 Bits
80 - Originating Address 7th 8 Bits
Digit Mode - 1 Bit
Number Mode - 1 Bit
Number Type - 0 or 3 bits
Number Plan - 0 or 4 bits
Number Fields - 8 Bits
Number Field occurrence of CHARi
CHARi - 4 or 8 bits ( 4 - in case of DTMF encoding, 8 - incase
of ASCII encoding)
Reserved - 0-7 bits
Lets take the 1st and 2nd 8 bits
02 - 0000 0010 ( Digit Mode bit - 0, Number Mode bit - 0)
8C - 1000 1100
As Digit mode bit is set to 0, Number Plan and Number Type is void
(0 bits) in this case.
So the remaining 6 bits of 1st 8bits and the first 2 bits of 2nd
8bit is Number fields
Number fields - 00 0010 10 - 0000 1010 - 0x0A (10 digits)
As Digit mode bit is set to 0, each address digit here is
represented as 4bit DTMF digit
0x8C 0xE9 0x5D 0xCC 0x65 0X80
1000 1100 1110 1001 0101 1101 1100 1100 0110 0101 1000 0000
10 0011 0011 1010 0101 0111 0111 0011 0001 1001 0110 0000 00
3 3 0 5 7 7 3 1 9 6 Last 6 bits
are reserved bits
Originating Address - 3305773196
06 - Bearer Reply Option Tag
01 - Bearer Reply Option Length
FC - First 6 bits Reply Sequence number and last 2 bits reserved set to
0
1111 1100 - 111111 REPLY_SEQ
00 Reserved
08 - Bearer Data Tag
15 - Bearer Data Length
00 - Message Indentifier Tag ( Bearer Data Sub parameter )
03 - Message Indentifier Length
16 - Message Type 4 bits Message Id 4 Bits
8D - Message Id 8 Bits
30 - Message Id 4 Bits, UDH Header indicator 1 Bit, Reserved 3 Bits
How Message Identifier value 16 8D 30 was formed ?
Message type ( 4 bits ) - 1( 0001 - Deliver)
Message Identifier ( 16 bits ) - 26835( 0x68D3)
Header Indicator (1 bit) - 0 (UDH not present in User Data
Subparameter)
Reserved ( 3bits) - 0 (000)
01 - User Data Tag ( Bearer Data Sub parameter )
06 - User Data Length
10 - Message Encoding 5 bits ( 0001 0000 ( 00010 = 2 -> 7-bit ASCII )) &
Number Fields 3 bits ( 000)
24 - Number Fields 5 Bits + User char field 1's 3 bits ( 0010 0100 )
18 - User char field 1's remaining 5 bits + User char field 2's 3 bits
(0001 1000)
30 - User char field 2's remaining 5 bits + User char field 3's 3 bits
(0011 0000)
60 - User char field 3's remaining 5 bits + User char field 4's 3 bits
(0110 0000)
80 - User char field 4's remaining 5 bits + Reserved 3 Bits (1000 0000)
Number Fields: 000 00100 - 04 (4 Character fields)
User Char [1] - 100 00011 - 0x83
User Char [2] - 000 00110 - 0x06
User Char [3] - 000 01100 - 0x0C
User Char [4] - 000 10000 - 0x10
Hex 0x83 0x06 0x0C 0x10
Octets 1000 0011 0000 0110 0000 1100 0001 0000
Septets 1000 001 10000 01 100000 1 1000001
Character A(0x41) A(0x41) A(0x41) A(0x41)
Message content: AAAA
Message Encoding - 2 (00010 - 5 bits)
Number Fields - 4 (0000 0100 - 8 bits)
User characters - 0x83 0x06 0x0C 0x10 ( 8 bits each)
00010 0000 0100 1000 0011 0000 0110 0000 1100 0001 0000
0001 0000 - 0x10
0010 0100 - 0x24
0001 1000 - 0x18
0011 0000 - 0x30
0110 0000 - 0x60
1000 0000 - 0x80 (Last 3 bits set to 0's(reserved bit) to complete
the octets)
03 - Message Center Time Stamp Tag ( Bearer Data Sub parameter )
06 - Message Center Time Stamp Length
all date and time fields contain two 4-bit BCD numbers giving the
decimal value of the field.
10 - Year (2010)
10 - Month (10 - October)
04 - Day
04 - Hour
48 - Minutes
47 - Seconds
Time Stamp 04:48:47 04/10/2010
Decoded Information:
Message Type: Deliver (Incoming Message)
Teleservice: CMT-95
Message Identifier: 26835
Originating Address: 3305773196
Message content: AAAA
Message Center Time Stamp: 04:48:47 04/10/2010
As from the above decoding example we can see there is substantial
differences between the GSM and CDMA SMS specifications and so the SMS
atom needs many additions and needs to be heavily modified to support
also CDMA SMS handling. Currently the oFono sms file unit handles the
common and the GSM technology aspects of the SMS stack along with the
smsutils. The SMS atom has the GSM specific members, segmentation and
queuing logic. The smsutils mainly takes care of encoding/decoding of
the PDUs, which is GSM specific. As the segmentation and queuing logic
and the interface is common for both GSM and CDMA, we could reuse this
common code and add the CDMA handling into it and create a new
cdmasmsutils unit to support the CDMA SMS specifics, much like the
smsutils does already for GSM.
BR,
Rajesh
8 years, 10 months
[PATCH 1/2 v2] netreg: Add CPHS CSP implementation
by Aki Niemi
---
src/network.c | 122 ++++++++++++++++++++++++++++++++++++++++++++------------
1 files changed, 96 insertions(+), 26 deletions(-)
diff --git a/src/network.c b/src/network.c
index bf61472..07f9cdf 100644
--- a/src/network.c
+++ b/src/network.c
@@ -42,7 +42,8 @@
enum network_registration_mode {
NETWORK_REGISTRATION_MODE_AUTO = 0,
- NETWORK_REGISTRATION_MODE_MANUAL = 1,
+ NETWORK_REGISTRATION_MODE_AUTO_ONLY = 1,
+ NETWORK_REGISTRATION_MODE_MANUAL = 2,
};
#define SETTINGS_STORE "netreg"
@@ -98,6 +99,8 @@ static const char *registration_mode_to_string(int mode)
switch (mode) {
case NETWORK_REGISTRATION_MODE_AUTO:
return "auto";
+ case NETWORK_REGISTRATION_MODE_AUTO_ONLY:
+ return "auto-only";
case NETWORK_REGISTRATION_MODE_MANUAL:
return "manual";
}
@@ -143,6 +146,42 @@ static char **network_operator_technologies(struct network_operator_data *opd)
return techs;
}
+static void registration_status_callback(const struct ofono_error *error,
+ int status, int lac, int ci, int tech,
+ void *data)
+{
+ struct ofono_netreg *netreg = data;
+
+ if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
+ DBG("Error during registration status query");
+ return;
+ }
+
+ ofono_netreg_status_notify(netreg, status, lac, ci, tech);
+}
+
+static void init_register(const struct ofono_error *error, void *data)
+{
+ struct ofono_netreg *netreg = data;
+
+ if (netreg->driver->registration_status == NULL)
+ return;
+
+ netreg->driver->registration_status(netreg,
+ registration_status_callback, netreg);
+}
+
+static void enforce_auto_only(struct ofono_netreg *netreg)
+{
+ if (netreg->mode != NETWORK_REGISTRATION_MODE_MANUAL)
+ return;
+
+ if (netreg->driver->register_auto == NULL)
+ return;
+
+ netreg->driver->register_auto(netreg, init_register, netreg);
+}
+
static void set_registration_mode(struct ofono_netreg *netreg, int mode)
{
DBusConnection *conn;
@@ -152,6 +191,9 @@ static void set_registration_mode(struct ofono_netreg *netreg, int mode)
if (netreg->mode == mode)
return;
+ if (mode == NETWORK_REGISTRATION_MODE_AUTO_ONLY)
+ enforce_auto_only(netreg);
+
netreg->mode = mode;
if (netreg->settings) {
@@ -170,20 +212,6 @@ static void set_registration_mode(struct ofono_netreg *netreg, int mode)
"Mode", DBUS_TYPE_STRING, &strmode);
}
-static void registration_status_callback(const struct ofono_error *error,
- int status, int lac, int ci, int tech,
- void *data)
-{
- struct ofono_netreg *netreg = data;
-
- if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
- DBG("Error during registration status query");
- return;
- }
-
- ofono_netreg_status_notify(netreg, status, lac, ci, tech);
-}
-
static void register_callback(const struct ofono_error *error, void *data)
{
struct ofono_netreg *netreg = data;
@@ -211,15 +239,6 @@ out:
registration_status_callback, netreg);
}
-static void init_register(const struct ofono_error *error, void *data)
-{
- struct ofono_netreg *netreg = data;
-
- if (netreg->driver->registration_status)
- netreg->driver->registration_status(netreg,
- registration_status_callback, netreg);
-}
-
static struct network_operator_data *
network_operator_create(const struct ofono_network_operator *op)
{
@@ -586,6 +605,9 @@ static DBusMessage *network_operator_register(DBusConnection *conn,
struct network_operator_data *opd = data;
struct ofono_netreg *netreg = opd->netreg;
+ if (netreg->mode == NETWORK_REGISTRATION_MODE_AUTO_ONLY)
+ return __ofono_error_access_denied(msg);
+
if (netreg->pending)
return __ofono_error_busy(msg);
@@ -828,6 +850,9 @@ static DBusMessage *network_register(DBusConnection *conn,
{
struct ofono_netreg *netreg = data;
+ if (netreg->mode == NETWORK_REGISTRATION_MODE_AUTO_ONLY)
+ return __ofono_error_access_denied(msg);
+
if (netreg->pending)
return __ofono_error_busy(msg);
@@ -947,6 +972,9 @@ static DBusMessage *network_scan(DBusConnection *conn,
{
struct ofono_netreg *netreg = data;
+ if (netreg->mode == NETWORK_REGISTRATION_MODE_AUTO_ONLY)
+ return __ofono_error_access_denied(msg);
+
if (netreg->pending)
return __ofono_error_busy(msg);
@@ -1364,7 +1392,7 @@ static void init_registration_status(const struct ofono_error *error,
signal_strength_callback, netreg);
}
- if (netreg->mode == NETWORK_REGISTRATION_MODE_AUTO &&
+ if (netreg->mode != NETWORK_REGISTRATION_MODE_MANUAL &&
(status == NETWORK_REGISTRATION_STATUS_NOT_REGISTERED ||
status == NETWORK_REGISTRATION_STATUS_DENIED ||
status == NETWORK_REGISTRATION_STATUS_UNKNOWN)) {
@@ -1574,6 +1602,44 @@ static void sim_spn_read_cb(int ok, int length, int record,
}
}
+static void sim_csp_read_cb(int ok, int length, int record,
+ const unsigned char *data,
+ int record_length, void *user_data)
+{
+ struct ofono_netreg *netreg = user_data;
+ int i;
+
+ if (!ok)
+ return;
+
+ if (length < 18 || record_length < 18 || length < record_length)
+ return;
+
+ /*
+ * According to CPHS 4.2, EFcsp is an array of two-byte service
+ * entries, each consisting of a one byte service group
+ * identifier followed by 8 bits; each bit is indicating
+ * availability of a specific service or feature.
+ *
+ * The PLMN mode bit, if present, indicates whether manual
+ * operator selection should be disabled or enabled. When
+ * unset, the device is forced to automatic mode; when set,
+ * manual selection is to be enabled. The latter is also the
+ * default.
+ */
+ for (i = 0; i < record_length / 2; i++) {
+
+ if (data[i * 2] != SIM_CSP_ENTRY_VALUE_ADDED_SERVICES)
+ continue;
+
+ if ((data[i * 2 + 1] & 0x80) != 0)
+ return;
+
+ set_registration_mode(netreg,
+ NETWORK_REGISTRATION_MODE_AUTO_ONLY);
+ }
+}
+
int ofono_netreg_get_location(struct ofono_netreg *netreg)
{
if (netreg == NULL)
@@ -1769,7 +1835,8 @@ static void netreg_load_settings(struct ofono_netreg *netreg)
mode = g_key_file_get_integer(netreg->settings, SETTINGS_GROUP,
"Mode", NULL);
- if (mode >= 0 && mode <= 1)
+ if (mode == NETWORK_REGISTRATION_MODE_AUTO ||
+ mode == NETWORK_REGISTRATION_MODE_MANUAL)
netreg->mode = mode;
g_key_file_set_integer(netreg->settings, SETTINGS_GROUP,
@@ -1816,6 +1883,9 @@ void ofono_netreg_register(struct ofono_netreg *netreg)
ofono_sim_read(netreg->sim, SIM_EFSPN_FILEID,
OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
sim_spn_read_cb, netreg);
+ ofono_sim_read(netreg->sim, SIM_EF_CPHS_CSP_FILEID,
+ OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
+ sim_csp_read_cb, netreg);
}
__ofono_atom_register(netreg->atom, netreg_unregister);
--
1.7.1
9 years, 12 months
Enabling/disabling the GPS part of a Huawei EM770W
by Florian Mayer (Mayer Electronics)
Hello folks,
is it possible to enable / disable the GPS part of a Huawei EM770W 3G
modem through a DBUS command? It is done with the command AT^WPDGP and
AT^WPEND on the modem (tested it on PCUI port). Or is it possible to
send generic AT commands through DBUS?
Regards
Florian Mayer
10 years
[PATCH v2 0/8] sms: Cancel pending message
by Lucas De Marchi
In this version I fixed some issues pointed out by Andrzej and added another
patch, not so related, but that would conflict with these ones if applied to
current master branch. Difference from previous version:
Tested with phonesim, slightly changing its plugin in oFono in order to hold
messages for a certain period.
Lucas De Marchi (8):
history: add cancelled status
examples: handle cancelled history status
message: add cancelled state
sms: factor out 'remove entry' from tx_finished()
sms: allow message submission to be cancelled
doc: add CancelMessage to MessageManager
TODO: mark task 'cancel pending SMS' as done
sms: remove check for impossible NULL condition
TODO | 9 --
doc/messagemanager-api.txt | 12 +++
examples/history.c | 5 +
include/history.h | 1 +
src/message.c | 2 +
src/message.h | 3 +-
src/sms.c | 196 +++++++++++++++++++++++++++++++++----------
7 files changed, 172 insertions(+), 56 deletions(-)
--
1.7.4
10 years
[PATCH 0/7] Add CDMA Connection Manager support
by christian.lam@nokia.com
From: Christian Lam <christian.lam(a)nokia.com>
This series of patches provides the support for the CDMA Connection
Manager, cdma-connman, atom. This includes Mobile Originated connection
and disconnection features of Packet Data Service over CDMA
(1xRTT and 1xEV-DO) systems. This implementation do not yet handle the
CDMA Network Registration which is future work.
These patches have been tested against the Nokia 7705 CDMA device in a
tethered mode.
Limitations
-----------
The Nokia 7705 device does not support an AT interface for reporting request
responses, such as the remote/network disconnect reasons, so these are
currently untested.
Christian Lam (7):
dbus: add CDMA Connection Manager interface
cdma-connman: add CDMA Connection Manager support
src: add CDMA Connection Manager support
nokiacdma: add CDMA Connection Manager support
cdmamodem: add CDMA Connection Manager support
test: add CDMA Connection Manager support scripts
test: add Settings dict parsing for CDMA ConnMan
Makefile.am | 9 +-
drivers/cdmamodem/cdmamodem.c | 4 +-
drivers/cdmamodem/cdmamodem.h | 4 +-
drivers/cdmamodem/connman.c | 283 ++++++++++++++++++++
include/cdma-connman.h | 79 ++++++
include/dbus.h | 1 +
plugins/nokiacdma.c | 4 +
src/cdma-connman.c | 571 +++++++++++++++++++++++++++++++++++++++++
src/ofono.h | 2 +
test/disable-cdma-connman | 20 ++
test/enable-cdma-connman | 20 ++
test/list-modems | 10 +
12 files changed, 1002 insertions(+), 5 deletions(-)
create mode 100644 drivers/cdmamodem/connman.c
create mode 100644 include/cdma-connman.h
create mode 100644 src/cdma-connman.c
create mode 100755 test/disable-cdma-connman
create mode 100755 test/enable-cdma-connman
10 years
[PATCH 1/3] sim: Watch for changes to relevant SIM files.
by Andrzej Zaborowski
---
src/sim.c | 170 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 157 insertions(+), 13 deletions(-)
diff --git a/src/sim.c b/src/sim.c
index c39269d..c33fcd5 100644
--- a/src/sim.c
+++ b/src/sim.c
@@ -58,6 +58,7 @@ struct ofono_sim {
char **language_prefs;
unsigned char *efli;
unsigned char efli_length;
+ gboolean language_prefs_update;
enum ofono_sim_password_type pin_type;
gboolean locked_pins[OFONO_SIM_PASSWORD_SIM_PUK]; /* Number of PINs */
@@ -97,8 +98,10 @@ struct ofono_sim {
struct sim_fs *simfs;
struct ofono_sim_context *context;
+ struct ofono_sim_context *early_context;
unsigned char *iidf_image;
+ unsigned int *iidf_watch_ids;
DBusMessage *pending;
const struct ofono_sim_driver *driver;
@@ -928,6 +931,11 @@ static void sim_iidf_read_cb(int ok, int length, int record,
sim_iidf_read_clut_cb, sim);
}
+static void sim_image_data_changed(int id, void *userdata)
+{
+ /* TODO: notify D-bus clients */
+}
+
static void sim_get_image(struct ofono_sim *sim, unsigned char id,
gpointer user_data)
{
@@ -941,7 +949,7 @@ static void sim_get_image(struct ofono_sim *sim, unsigned char id,
if (image != NULL) {
sim_get_image_cb(sim, id, image, FALSE);
- return;
+ goto watch;
}
if (sim->efimg_length <= (id * 9)) {
@@ -958,6 +966,17 @@ static void sim_get_image(struct ofono_sim *sim, unsigned char id,
/* read the image data */
ofono_sim_read_bytes(sim->context, iidf_id, iidf_offset, iidf_len,
sim_iidf_read_cb, sim);
+
+watch:
+ if (sim->efimg_length <= id * 9)
+ return;
+
+ if (sim->iidf_watch_ids[id] > 0)
+ return;
+
+ sim->iidf_watch_ids[id] = ofono_sim_add_file_watch(sim->context,
+ iidf_id, sim_image_data_changed,
+ sim, NULL);
}
static DBusMessage *sim_get_icon(DBusConnection *conn,
@@ -1197,10 +1216,12 @@ out:
check:
/* All records retrieved */
if (sim->service_numbers) {
- char **service_numbers;
-
sim->service_numbers = g_slist_reverse(sim->service_numbers);
sim->sdn_ready = TRUE;
+ }
+
+ if (sim->sdn_ready) {
+ char **service_numbers;
service_numbers = get_service_numbers(sim->service_numbers);
@@ -1213,6 +1234,21 @@ check:
}
}
+static void sim_service_numbers_changed(int id, void *userdata)
+{
+ struct ofono_sim *sim = userdata;
+
+ if (sim->service_numbers) {
+ g_slist_foreach(sim->service_numbers,
+ (GFunc)service_number_free, NULL);
+ g_slist_free(sim->service_numbers);
+ sim->service_numbers = NULL;
+ }
+
+ ofono_sim_read(sim->context, SIM_EFSDN_FILEID,
+ OFONO_SIM_FILE_STRUCTURE_FIXED, sim_sdn_read_cb, sim);
+}
+
static void sim_own_numbers_update(struct ofono_sim *sim)
{
ofono_sim_read(sim->context, SIM_EFMSISDN_FILEID,
@@ -1220,6 +1256,13 @@ static void sim_own_numbers_update(struct ofono_sim *sim)
sim);
}
+static void sim_own_numbers_changed(int id, void *userdata)
+{
+ struct ofono_sim *sim = userdata;
+
+ sim_own_numbers_update(sim);
+}
+
static void sim_efimg_read_cb(int ok, int length, int record,
const unsigned char *data,
int record_length, void *userdata)
@@ -1247,6 +1290,11 @@ static void sim_efimg_read_cb(int ok, int length, int record,
if (sim->efimg == NULL)
return;
+ sim->iidf_watch_ids = g_try_new0(unsigned int, num_records);
+
+ if (sim->iidf_watch_ids == NULL)
+ return;
+
sim->efimg_length = num_records * 9;
}
@@ -1261,6 +1309,33 @@ static void sim_efimg_read_cb(int ok, int length, int record,
memcpy(efimg, &data[1], 9);
}
+static void sim_efimg_changed(int id, void *userdata)
+{
+ struct ofono_sim *sim = userdata;
+ int i, watch;
+
+ if (sim->efimg != NULL) {
+ for (i = sim->efimg_length / 9 - 1; i >= 0; i--) {
+ watch = sim->iidf_watch_ids[i];
+ if (watch == 0)
+ continue;
+
+ ofono_sim_remove_file_watch(sim->context, watch);
+ }
+
+ g_free(sim->efimg);
+ sim->efimg = NULL;
+ sim->efimg_length = 0;
+ g_free(sim->iidf_watch_ids);
+ sim->iidf_watch_ids = NULL;
+ }
+
+ ofono_sim_read(sim->context, SIM_EFIMG_FILEID,
+ OFONO_SIM_FILE_STRUCTURE_FIXED, sim_efimg_read_cb, sim);
+
+ /* TODO: notify D-bus clients */
+}
+
static void sim_ready(enum ofono_sim_state new_state, void *user)
{
struct ofono_sim *sim = user;
@@ -1269,11 +1344,18 @@ static void sim_ready(enum ofono_sim_state new_state, void *user)
return;
sim_own_numbers_update(sim);
+ ofono_sim_add_file_watch(sim->context, SIM_EFMSISDN_FILEID,
+ sim_own_numbers_changed, sim, NULL);
ofono_sim_read(sim->context, SIM_EFSDN_FILEID,
OFONO_SIM_FILE_STRUCTURE_FIXED, sim_sdn_read_cb, sim);
+ ofono_sim_add_file_watch(sim->context, SIM_EFSDN_FILEID,
+ sim_service_numbers_changed, sim, NULL);
+
ofono_sim_read(sim->context, SIM_EFIMG_FILEID,
OFONO_SIM_FILE_STRUCTURE_FIXED, sim_efimg_read_cb, sim);
+ ofono_sim_add_file_watch(sim->context, SIM_EFIMG_FILEID,
+ sim_efimg_changed, sim, NULL);
}
static void sim_set_ready(struct ofono_sim *sim)
@@ -1846,7 +1928,15 @@ skip_efpl:
DBUS_TYPE_STRING,
&sim->language_prefs);
- sim_pin_check(sim);
+ /* Proceed with sim initialization if we're not merely updating */
+ if (!sim->language_prefs_update) {
+ if (sim->context == NULL)
+ sim->context = ofono_sim_context_create(sim);
+
+ sim_pin_check(sim);
+ }
+
+ sim->language_prefs_update = FALSE;
}
static void sim_iccid_read_cb(int ok, int length, int record,
@@ -1872,6 +1962,43 @@ static void sim_iccid_read_cb(int ok, int length, int record,
&sim->iccid);
}
+static void sim_iccid_changed(int id, void *userdata)
+{
+ struct ofono_sim *sim = userdata;
+
+ if (sim->iccid) {
+ g_free(sim->iccid);
+ sim->iccid = NULL;
+ }
+
+ ofono_sim_read(sim->early_context, SIM_EF_ICCID_FILEID,
+ OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
+ sim_iccid_read_cb, sim);
+}
+
+static void sim_efli_efpl_changed(int id, void *userdata)
+{
+ struct ofono_sim *sim = userdata;
+
+ if (sim->efli != NULL) /* This shouldn't happen */
+ return;
+
+ if (sim->language_prefs) {
+ g_strfreev(sim->language_prefs);
+ sim->language_prefs = NULL;
+ }
+
+ sim->language_prefs_update = TRUE;
+
+ ofono_sim_read(sim->early_context, SIM_EFLI_FILEID,
+ OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
+ sim_efli_read_cb, sim);
+
+ ofono_sim_read(sim->early_context, SIM_EFPL_FILEID,
+ OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
+ sim_efpl_read_cb, sim);
+}
+
static void sim_initialize(struct ofono_sim *sim)
{
/*
@@ -1900,10 +2027,15 @@ static void sim_initialize(struct ofono_sim *sim)
* in the EFust
*/
+ if (sim->early_context == NULL)
+ sim->early_context = ofono_sim_context_create(sim);
+
/* Grab the EFiccid which is always available */
- ofono_sim_read(sim->context, SIM_EF_ICCID_FILEID,
+ ofono_sim_read(sim->early_context, SIM_EF_ICCID_FILEID,
OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
sim_iccid_read_cb, sim);
+ ofono_sim_add_file_watch(sim->early_context, SIM_EF_ICCID_FILEID,
+ sim_iccid_changed, sim, NULL);
/* EFecc is read by the voicecall atom */
@@ -1915,12 +2047,17 @@ static void sim_initialize(struct ofono_sim *sim)
* However we don't depend on the user interface and so
* need to read both files now.
*/
- ofono_sim_read(sim->context, SIM_EFLI_FILEID,
+ ofono_sim_read(sim->early_context, SIM_EFLI_FILEID,
OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
sim_efli_read_cb, sim);
- ofono_sim_read(sim->context, SIM_EFPL_FILEID,
+ ofono_sim_add_file_watch(sim->early_context, SIM_EFLI_FILEID,
+ sim_efli_efpl_changed, sim, NULL);
+
+ ofono_sim_read(sim->early_context, SIM_EFPL_FILEID,
OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
sim_efpl_read_cb, sim);
+ ofono_sim_add_file_watch(sim->early_context, SIM_EFPL_FILEID,
+ sim_efli_efpl_changed, sim, NULL);
}
struct ofono_sim_context *ofono_sim_context_create(struct ofono_sim *sim)
@@ -2069,6 +2206,11 @@ static void sim_free_early_state(struct ofono_sim *sim)
g_strfreev(sim->language_prefs);
sim->language_prefs = NULL;
}
+
+ if (sim->early_context) {
+ ofono_sim_context_free(sim->early_context);
+ sim->early_context = NULL;
+ }
}
static void sim_free_main_state(struct ofono_sim *sim)
@@ -2092,6 +2234,7 @@ static void sim_free_main_state(struct ofono_sim *sim)
(GFunc)service_number_free, NULL);
g_slist_free(sim->service_numbers);
sim->service_numbers = NULL;
+ sim->sdn_ready = FALSE;
}
if (sim->efust) {
@@ -2118,6 +2261,8 @@ static void sim_free_main_state(struct ofono_sim *sim)
g_free(sim->efimg);
sim->efimg = NULL;
sim->efimg_length = 0;
+ g_free(sim->iidf_watch_ids);
+ sim->iidf_watch_ids = NULL;
}
g_free(sim->iidf_image);
@@ -2125,6 +2270,11 @@ static void sim_free_main_state(struct ofono_sim *sim)
sim->fixed_dialing = FALSE;
sim->barred_dialing = FALSE;
+
+ if (sim->context) {
+ ofono_sim_context_free(sim->context);
+ sim->context = NULL;
+ }
}
static void sim_free_state(struct ofono_sim *sim)
@@ -2304,11 +2454,6 @@ static void sim_remove(struct ofono_atom *atom)
sim_free_state(sim);
- if (sim->context) {
- ofono_sim_context_free(sim->context);
- sim->context = NULL;
- }
-
sim_fs_free(sim->simfs);
sim->simfs = NULL;
@@ -2374,7 +2519,6 @@ void ofono_sim_register(struct ofono_sim *sim)
ofono_modem_add_interface(modem, OFONO_SIM_MANAGER_INTERFACE);
sim->state_watches = __ofono_watchlist_new(g_free);
sim->simfs = sim_fs_new(sim, sim->driver);
- sim->context = ofono_sim_context_create(sim);
__ofono_atom_register(sim->atom, sim_unregister);
--
1.7.1.86.g0e460.dirty
10 years
[PATCH] unit: Added unit test for STE
by Marit Henriksen
From: Marit Henriksen <marit.henriksen(a)stericsson.com>
---
Makefile.am | 17 +-
unit/test-ste.c | 1153 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 1169 insertions(+), 1 deletions(-)
create mode 100755 unit/test-ste.c
diff --git a/Makefile.am b/Makefile.am
index 42ad86f..0806e1e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -499,7 +499,7 @@ dist_man_MANS = doc/ofonod.8
noinst_PROGRAMS = unit/test-common unit/test-util unit/test-idmap \
unit/test-sms unit/test-simutil \
unit/test-mux unit/test-caif \
- unit/test-stkutil
+ unit/test-stkutil unit/test-ste
unit_objects =
@@ -540,6 +540,21 @@ unit_test_caif_SOURCES = unit/test-caif.c $(gatchat_sources) \
unit_test_caif_LDADD = @GLIB_LIBS@
unit_objects += $(unit_test_caif_OBJECTS)
+unit_test_ste_SOURCES = unit/test-ste.c $(gatchat_sources) \
+ $(gdbus_sources) $(local_headers) \
+ src/common.c src/util.c \
+ drivers/stemodem/stemodem.h \
+ drivers/atmodem/atutil.h \
+ drivers/atmodem/atutil.c \
+ drivers/stemodem/radio-settings.c \
+ drivers/stemodem/gprs-context.c \
+ drivers/stemodem/voicecall.c \
+ drivers/stemodem/caif_socket.h \
+ drivers/stemodem/if_caif.h
+
+unit_test_ste_LDADD = @GLIB_LIBS@ @DBUS_LIBS@
+unit_objects += $(unit_test_ste_OBJECTS)
+
if TOOLS
noinst_PROGRAMS += tools/huawei-audio tools/auto-enable
diff --git a/unit/test-ste.c b/unit/test-ste.c
new file mode 100755
index 0000000..b078aaf
--- /dev/null
+++ b/unit/test-ste.c
@@ -0,0 +1,1153 @@
+/*
+ *
+ * oFono - Open Source Telephony
+ *
+ * Copyright (C) 2010 ST-Ericsson AB.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <glib.h>
+#include <gatchat.h>
+#include <gatresult.h>
+#include <log.h>
+#include <ofono/modem.h>
+#include <ofono/voicecall.h>
+#include <ofono/radio-settings.h>
+#include <ofono/gprs-context.h>
+#include <drivers/stemodem/stemodem.h>
+#include <drivers/stemodem/caif_rtnl.h>
+#include "common.h"
+
+/* Generic test code decls */
+static GAtChat *chat;
+static GMainLoop *event_loop;
+static int phone_fd;
+
+#define ASSERT_AT(s) g_assert(assert_at(s));
+
+/* Send a simulated AT response */
+static void at_response(char *resp)
+{
+ int r;
+
+ /*
+ * Send AT response to g_at_chat and give main look a kick to run
+ * one iteration.
+ */
+ r = write(phone_fd, resp, strlen(resp));
+ g_assert(r > 0);
+ (void)g_main_context_iteration(NULL, TRUE);
+}
+
+static gboolean assert_at(char *match)
+{
+ char req[256];
+ int r;
+
+ if (g_main_context_iteration(NULL, TRUE) == TRUE) {
+
+ /* Read what g_at_chan has written to "modem" */
+ r = read(phone_fd, req, sizeof(req));
+
+ if (r > 1)
+ req[r-1] = 0;
+
+ if (strcmp(match, req) == 0)
+ return TRUE;
+ }
+
+ g_print("AT request did not match:%s != %s\n", match, req);
+ return FALSE;
+}
+
+
+/* Stubs from src/voicecall.c */
+struct ofono_voicecall;
+const struct ofono_voicecall_driver *voicecall_driver;
+void *voicecall_data;
+static unsigned int expected_id;
+static int expected_status;
+static char expected_number[OFONO_MAX_PHONE_NUMBER_LENGTH + 1];
+static int expected_reason;
+
+void ofono_voicecall_register(struct ofono_voicecall *vc)
+{
+}
+
+void ofono_voicecall_remove(struct ofono_voicecall *vc)
+{
+}
+
+int ofono_voicecall_driver_register(const struct ofono_voicecall_driver *d)
+{
+ voicecall_driver = d;
+ return 0;
+}
+
+void ofono_voicecall_driver_unregister(const struct ofono_voicecall_driver *d)
+{
+}
+
+void ofono_voicecall_set_data(struct ofono_voicecall *vc, void *data)
+{
+ voicecall_data = data;
+}
+
+void *ofono_voicecall_get_data(struct ofono_voicecall *vc)
+{
+ return voicecall_data;
+}
+
+void ofono_voicecall_notify(struct ofono_voicecall *vc,
+ const struct ofono_call *call)
+{
+ g_assert_cmpint(expected_id, ==, call->id);
+ g_assert_cmpint(expected_status, ==, call->status);
+ g_assert_cmpstr(expected_number, ==, call->phone_number.number);
+}
+
+void ofono_voicecall_disconnected(struct ofono_voicecall *vc, int id,
+ enum ofono_disconnect_reason reason,
+ const struct ofono_error *error)
+{
+ g_assert_cmpint(expected_id, ==, id);
+ g_assert_cmpint(expected_reason, ==, reason);
+ g_assert(error == NULL);
+}
+
+/* Stubs from src/radio-settings.c */
+struct ofono_radio_settings;
+const struct ofono_radio_settings_driver *radio_settings_driver;
+void *radio_settings_data;
+
+void ofono_radio_settings_register(struct ofono_radio_settings *rs)
+{
+}
+
+void ofono_radio_settings_remove(struct ofono_radio_settings *rs)
+{
+}
+
+void ofono_radio_settings_set_data(struct ofono_radio_settings *rs, void *data)
+{
+ radio_settings_data = data;
+}
+
+void *ofono_radio_settings_get_data(struct ofono_radio_settings *rs)
+{
+ return radio_settings_data;
+}
+
+int ofono_radio_settings_driver_register(
+ const struct ofono_radio_settings_driver *d)
+{
+ radio_settings_driver = d;
+ return 0;
+}
+
+void ofono_radio_settings_driver_unregister(
+ const struct ofono_radio_settings_driver *d)
+{
+}
+
+/* Stubs from src/gprs-context.c */
+struct ofono_gprs_context;
+const struct ofono_gprs_context_driver *gprs_context_driver;
+void *gprs_context_data;
+
+int caif_rtnl_create_interface(int type, int connid, int loop,
+ caif_rtnl_create_cb_t cb, void *user_data)
+{
+ cb(0, "caif0", user_data);
+ return 0;
+}
+
+int caif_rtnl_delete_interface(int ifid)
+{
+ return 0;
+}
+
+int caif_rtnl_init(void)
+{
+ return 0;
+}
+
+void caif_rtnl_exit(void)
+{
+}
+
+void ofono_gprs_context_remove(struct ofono_gprs_context *rs)
+{
+}
+
+void ofono_gprs_context_set_data(struct ofono_gprs_context *rs, void *data)
+{
+ gprs_context_data = data;
+}
+
+void *ofono_gprs_context_get_data(struct ofono_gprs_context *rs)
+{
+ return gprs_context_data;
+}
+
+int ofono_gprs_context_driver_register(
+ const struct ofono_gprs_context_driver *d)
+{
+ gprs_context_driver = d;
+ return 0;
+}
+
+void ofono_gprs_context_driver_unregister(
+ const struct ofono_gprs_context_driver *d)
+{
+}
+
+void ofono_gprs_context_deactivated(struct ofono_gprs_context *gc,
+ unsigned int cid)
+{
+}
+
+/* Test Fixture for context activation */
+static struct ofono_gprs_primary_context ctx = {
+ 5, 1, "apn", "user", "pwd", OFONO_GPRS_PROTO_IP
+};
+
+/*
+ * These vars are used to validate test case and are
+ * checked in callback functions.
+ */
+static enum ofono_error_type expected_errtype;
+static int expected_error;
+
+static void gprs_context_up_cb(const struct ofono_error *error,
+ const char *interface, ofono_bool_t static_ip,
+ const char *address, const char *netmask,
+ const char *gw, const char **dns, void *data)
+{
+ g_assert_cmpint(expected_errtype, ==, error->type);
+}
+
+static void ofono_generic_cb(const struct ofono_error *error, void *data)
+{
+ g_assert_cmpint(expected_errtype, ==, error->type);
+ g_assert_cmpint(expected_error, ==, error->error);
+
+}
+
+static void gprs_activate_helper(void)
+{
+ expected_errtype = OFONO_ERROR_TYPE_NO_ERROR;
+
+ gprs_context_driver->
+ activate_primary(0, &ctx,
+ (ofono_gprs_context_up_cb_t)
+ gprs_context_up_cb, 0);
+
+ ASSERT_AT("AT+CGDCONT=5,\"IP\",\"apn\"");
+ at_response("\r\nOK\r\n");
+
+ ASSERT_AT("AT*EIAAUW=5,1,\"user\",\"pwd\"");
+ at_response("\r\nOK\r\n");
+
+ ASSERT_AT("AT*EPPSD=1,1,5");
+ at_response(
+ "\r\n"
+ "<?xml version=\"1.0\"?>\r\n"
+ "<connection_parameters>\r\n"
+ "<ip_address>10.64.151.14</ip_address>\r\n"
+ "<subnet_mask>255.255.255.255</subnet_mask>\r\n"
+ "<mtu>1500</mtu>\r\n"
+ "<dns_server>10.64.148.4</dns_server>\r\n"
+ "<dns_server>10.64.148.5</dns_server>\r\n"
+ "</connection_parameters>\r\n"
+ "\r\nOK\r\n");
+}
+
+static void test_gprs_normal(void)
+{
+ ste_gprs_context_init();
+
+ gprs_context_driver->probe(NULL, 0, chat);
+ gprs_activate_helper();
+
+ gprs_context_driver->remove(gprs_context_data);
+ ste_gprs_context_exit();
+}
+
+static void test_gprs_deactivate(void)
+{
+ ste_gprs_context_init();
+
+ gprs_context_driver->probe(NULL, 0, chat);
+ gprs_activate_helper();
+
+ gprs_context_driver->
+ deactivate_primary(0, ctx.cid,
+ (ofono_gprs_context_cb_t)
+ ofono_generic_cb, 0);
+ ASSERT_AT("AT*EPPSD=0,1,5");
+ at_response("\r\nOK\r\n");
+
+ gprs_context_driver->remove(gprs_context_data);
+ ste_gprs_context_exit();
+}
+
+static void test_gprs_nw_deact(void)
+{
+ ste_gprs_context_init();
+
+ gprs_context_driver->probe(NULL, 0, chat);
+ gprs_activate_helper();
+
+ at_response("\r\n+CGEV: NW DEACT \r\n");
+ ASSERT_AT("AT+CGACT?");
+ at_response("\r\n+CGACT: 5,0\r\nOK\r\n");
+
+ gprs_context_driver->remove(gprs_context_data);
+ ste_gprs_context_exit();
+}
+
+static void test_gprs_deactivate_fail(void)
+{
+ ste_gprs_context_init();
+
+ gprs_context_driver->probe(NULL, 0, chat);
+ gprs_activate_helper();
+
+ gprs_context_driver->
+ deactivate_primary(0, ctx.cid,
+ (ofono_gprs_context_cb_t)
+ ofono_generic_cb, 0);
+ ASSERT_AT("AT*EPPSD=0,1,5");
+ expected_errtype = OFONO_ERROR_TYPE_CME;
+ expected_error = 100;
+ at_response("\r\n+CME ERROR:100\r\n");
+
+ gprs_context_driver->remove(gprs_context_data);
+ ste_gprs_context_exit();
+}
+
+static void test_gprs_deactivate_err(void)
+{
+ ste_gprs_context_init();
+
+ gprs_context_driver->probe(NULL, 0, chat);
+
+ expected_errtype = OFONO_ERROR_TYPE_FAILURE;
+ expected_error = 0;
+ gprs_context_driver->
+ deactivate_primary(0, ctx.cid,
+ (ofono_gprs_context_cb_t)
+ ofono_generic_cb, 0);
+
+ gprs_context_driver->remove(gprs_context_data);
+ ste_gprs_context_exit();
+}
+
+static void test_gprs_deact_fail_then_ok(void)
+{
+ ste_gprs_context_init();
+
+ gprs_context_driver->probe(NULL, 0, chat);
+ gprs_activate_helper();
+
+ gprs_context_driver->
+ deactivate_primary(0, ctx.cid,
+ (ofono_gprs_context_cb_t)
+ ofono_generic_cb, 0);
+ expected_errtype = OFONO_ERROR_TYPE_CME;
+ expected_error = 100;
+ at_response("\r\n+CME ERROR:100\r\n");
+
+ gprs_context_driver->
+ deactivate_primary(0, ctx.cid,
+ (ofono_gprs_context_cb_t)
+ ofono_generic_cb, 0);
+ ASSERT_AT("AT*EPPSD=0,1,5");
+ expected_errtype = OFONO_ERROR_TYPE_NO_ERROR;
+ expected_error = 0;
+ at_response("\r\nOK\r\n");
+
+ gprs_context_driver->remove(gprs_context_data);
+ ste_gprs_context_exit();
+}
+
+static void test_gprs_eppsd_err(void)
+{
+ ste_gprs_context_init();
+
+ gprs_context_driver->probe(NULL, 0, chat);
+
+ expected_errtype = OFONO_ERROR_TYPE_NO_ERROR;
+ gprs_context_driver->
+ activate_primary(0, &ctx,
+ (ofono_gprs_context_up_cb_t)
+ gprs_context_up_cb, 0);
+ ASSERT_AT("AT+CGDCONT=5,\"IP\",\"apn\"");
+ at_response("\r\nOK\r\n");
+ ASSERT_AT("AT*EIAAUW=5,1,\"user\",\"pwd\"");
+ at_response("\r\nOK\r\n");
+
+ ASSERT_AT("AT*EPPSD=1,1,5");
+ expected_errtype = OFONO_ERROR_TYPE_CME;
+ expected_error = 100;
+ at_response("\r\n+CME ERROR:100\r\n");
+
+ gprs_context_driver->remove(gprs_context_data);
+ ste_gprs_context_exit();
+}
+
+static void test_gprs_cgdcont_err(void)
+{
+ ste_gprs_context_init();
+
+ gprs_context_driver->probe(NULL, 0, chat);
+ expected_errtype = OFONO_ERROR_TYPE_NO_ERROR;
+ gprs_context_driver->
+ activate_primary(0, &ctx,
+ (ofono_gprs_context_up_cb_t)
+ gprs_context_up_cb, 0);
+ ASSERT_AT("AT+CGDCONT=5,\"IP\",\"apn\"");
+ expected_errtype = OFONO_ERROR_TYPE_CME;
+ expected_error = 100;
+ at_response("\r\n+CME ERROR:100\r\n");
+
+ gprs_context_driver->remove(gprs_context_data);
+ ste_gprs_context_exit();
+}
+
+static void test_gprs_xmlerr(void)
+{
+ ste_gprs_context_init();
+
+ gprs_context_driver->probe(NULL, 0, chat);
+
+ expected_errtype = OFONO_ERROR_TYPE_NO_ERROR;
+ gprs_context_driver->
+ activate_primary(0, &ctx,
+ (ofono_gprs_context_up_cb_t)
+ gprs_context_up_cb, 0);
+ ASSERT_AT("AT+CGDCONT=5,\"IP\",\"apn\"");
+ at_response("\r\nOK\r\n");
+
+ ASSERT_AT("AT*EIAAUW=5,1,\"user\",\"pwd\"");
+ at_response("\r\nOK\r\n");
+
+ ASSERT_AT("AT*EPPSD=1,1,5");
+ expected_errtype = OFONO_ERROR_TYPE_FAILURE;
+ expected_error = 0;
+ at_response(
+ "\r\n"
+ "<?xml version=\"1.0\"?>\r\n"
+ "<connection_parameters>\r\n"
+ "XML-ERROR"
+ "\r\nOK\r\n");
+
+ gprs_context_driver->remove(gprs_context_data);
+ ste_gprs_context_exit();
+}
+
+static enum ofono_radio_access_mode expected_mode;
+
+static void radio_rat_mode_query_callback(const struct ofono_error *error,
+ enum ofono_radio_access_mode mode,
+ void *data)
+{
+ g_assert_cmpint(expected_errtype, ==, error->type);
+ g_assert_cmpint(expected_mode, ==, mode);
+}
+
+
+#define QUERY_RAT() \
+ do { \
+ radio_settings_driver-> \
+ query_rat_mode(0, \
+ (ofono_radio_settings_rat_mode_query_cb_t) \
+ radio_rat_mode_query_callback, 0); \
+ ASSERT_AT("AT+CFUN?"); \
+ } while (0)
+
+static void test_radiosettings_all(void)
+{
+ ste_radio_settings_init();
+
+ radio_settings_driver->probe(NULL, 0, chat);
+
+ /* Normal Cases */
+ expected_errtype = OFONO_ERROR_TYPE_NO_ERROR;
+ expected_mode = OFONO_RADIO_ACCESS_MODE_ANY;
+ QUERY_RAT();
+ at_response("\r\n+CFUN: 1\r\n\r\nOK\r\n");
+
+ QUERY_RAT();
+ expected_mode = OFONO_RADIO_ACCESS_MODE_GSM;
+ at_response("\r\n+CFUN: 5\r\n\r\nOK\r\n");
+
+ QUERY_RAT();
+ expected_mode = OFONO_RADIO_ACCESS_MODE_UMTS;
+ at_response("\r\n+CFUN: 6\r\n\r\nOK\r\n");
+
+ /* Unexpected values */
+ expected_errtype = OFONO_ERROR_TYPE_FAILURE;
+ expected_mode = -1;
+ QUERY_RAT();
+ at_response("\r\n+CFUN: 0\r\n\r\nOK\r\n");
+
+ QUERY_RAT();
+ at_response("\r\n+CFUN: 4\r\n\r\nOK\r\n");
+
+ QUERY_RAT();
+ at_response("\r\n+CFUN: 11\r\n\r\nOK\r\n");
+
+ /* Error cases */
+ QUERY_RAT();
+ expected_errtype = OFONO_ERROR_TYPE_FAILURE;
+ expected_mode = -1;
+ at_response("\r\nERROR\r\n");
+
+ QUERY_RAT();
+ expected_errtype = OFONO_ERROR_TYPE_CME;
+ expected_error = 100;
+ at_response("\r\n+CME ERROR:100\r\n");
+
+ radio_settings_driver->remove(radio_settings_data);
+ ste_radio_settings_exit();
+}
+
+/* Test Phone number */
+static struct ofono_phone_number ph = {"4425993003739", 145 };
+
+static void voicecall_activate_helper(void)
+{
+ ste_voicecall_init();
+ voicecall_driver->probe(NULL, 0, chat);
+
+ ASSERT_AT("AT*ECAM=2");
+ at_response("\r\nOK\r\n");
+}
+
+static void test_voicecall_dial(void)
+{
+ /* Voice call initialisation */
+ voicecall_activate_helper();
+
+ voicecall_driver->dial(0, &ph, 0,
+ (ofono_voicecall_cb_t)ofono_generic_cb, 0);
+ ASSERT_AT("ATD+4425993003739;");
+ expected_errtype = OFONO_ERROR_TYPE_NO_ERROR;
+ expected_error = 0;
+ at_response("\r\nOK\r\n");
+
+ voicecall_driver->remove(voicecall_data);
+ ste_voicecall_exit();
+}
+
+static void test_voicecall_dial_colp(void)
+{
+ /* Voice call initialisation */
+ voicecall_activate_helper();
+
+ voicecall_driver->dial(0, &ph, 0,
+ (ofono_voicecall_cb_t)ofono_generic_cb, 0);
+ ASSERT_AT("ATD+4425993003739;");
+ expected_errtype = OFONO_ERROR_TYPE_NO_ERROR;
+ expected_error = 0;
+ expected_status = CALL_STATUS_DIALING;
+ sprintf(expected_number, "+4425993003739");
+ at_response("\r\n+COLP: \"+4425993003739\",129\r\nOK\r\n");
+
+ voicecall_driver->remove(voicecall_data);
+ ste_voicecall_exit();
+}
+
+static void test_voicecall_dial_erroneous_colp(void)
+{
+ /* Voice call initialisation */
+ voicecall_activate_helper();
+
+ voicecall_driver->dial(0, &ph, 0,
+ (ofono_voicecall_cb_t)ofono_generic_cb, 0);
+ ASSERT_AT("ATD+4425993003739;");
+ expected_errtype = OFONO_ERROR_TYPE_NO_ERROR;
+ expected_error = 0;
+ expected_status = CALL_STATUS_DIALING;
+ sprintf(expected_number, "+4425993003739");
+ at_response("\r\n+COLP:\r\nOK\r\n");
+
+ voicecall_driver->remove(voicecall_data);
+ ste_voicecall_exit();
+}
+
+static void test_voicecall_dial_fail(void)
+{
+ /* Voice call initialisation */
+ voicecall_activate_helper();
+
+ voicecall_driver->dial(0, &ph, 0,
+ (ofono_voicecall_cb_t)ofono_generic_cb, 0);
+ ASSERT_AT("ATD+4425993003739;");
+ expected_errtype = OFONO_ERROR_TYPE_CME;
+ expected_error = 423; /* Network problem */
+ at_response("\r\n+CME ERROR:423\r\n");
+
+ voicecall_driver->remove(voicecall_data);
+ ste_voicecall_exit();
+}
+
+static void test_voicecall_dial_busy(void)
+{
+ /* Voice call initialisation */
+ voicecall_activate_helper();
+
+ voicecall_driver->dial(0, &ph, 0,
+ (ofono_voicecall_cb_t)ofono_generic_cb, 0);
+ ASSERT_AT("ATD+4425993003739;");
+ expected_errtype = OFONO_ERROR_TYPE_FAILURE;
+ expected_error = 0;
+ at_response("\r\nBUSY\r\n");
+
+ voicecall_driver->remove(voicecall_data);
+ ste_voicecall_exit();
+}
+
+static void test_voicecall_dial_no_dialtone(void)
+{
+ /* Voice call initialisation */
+ voicecall_activate_helper();
+
+ voicecall_driver->dial(0, &ph, 0,
+ (ofono_voicecall_cb_t)ofono_generic_cb, 0);
+ ASSERT_AT("ATD+4425993003739;");
+ expected_errtype = OFONO_ERROR_TYPE_FAILURE;
+ expected_error = 0;
+ at_response("\r\nNO DIALTONE\r\n");
+
+ voicecall_driver->remove(voicecall_data);
+ ste_voicecall_exit();
+}
+
+static void test_voicecall_hangup(void)
+{
+ /* Voice call initialisation */
+ voicecall_activate_helper();
+
+ expected_errtype = OFONO_ERROR_TYPE_NO_ERROR;
+ expected_error = 0;
+
+ /* Hangup */
+ voicecall_driver->hangup_active(0,
+ (ofono_voicecall_cb_t)ofono_generic_cb, 0);
+ ASSERT_AT("AT+CHUP");
+ at_response("\r\nOK\r\n");
+
+ voicecall_driver->remove(voicecall_data);
+ ste_voicecall_exit();
+}
+
+static void test_voicecall_hangup_fail(void)
+{
+ /* Voice call initialisation */
+ voicecall_activate_helper();
+
+ /* Hangup */
+ voicecall_driver->hangup_active(0,
+ (ofono_voicecall_cb_t)ofono_generic_cb, 0);
+ ASSERT_AT("AT+CHUP");
+ expected_errtype = OFONO_ERROR_TYPE_CME;
+ expected_error = 100;
+ at_response("\r\n+CME ERROR:100\r\n");
+
+ voicecall_driver->remove(voicecall_data);
+ ste_voicecall_exit();
+}
+
+static void test_voicecall_hold(void)
+{
+ /* Voice call initialisation */
+ voicecall_activate_helper();
+
+ expected_errtype = OFONO_ERROR_TYPE_NO_ERROR;
+ expected_error = 0;
+
+ /* Hold Call */
+ voicecall_driver->hold_all_active(0,
+ (ofono_voicecall_cb_t)ofono_generic_cb, 0);
+ ASSERT_AT("AT+CHLD=2");
+ at_response("\r\nOK\r\n");
+
+ voicecall_driver->remove(voicecall_data);
+ ste_voicecall_exit();
+}
+
+static void test_voicecall_release_all_held(void)
+{
+ /* Voice call initialisation */
+ voicecall_activate_helper();
+
+ expected_errtype = OFONO_ERROR_TYPE_NO_ERROR;
+ expected_error = 0;
+
+ /* Release Call */
+ voicecall_driver->release_all_held(0,
+ (ofono_voicecall_cb_t)ofono_generic_cb, 0);
+ ASSERT_AT("AT+CHLD=0");
+ at_response("\r\nOK\r\n");
+
+ voicecall_driver->remove(voicecall_data);
+ ste_voicecall_exit();
+}
+
+static void test_voicecall_release_all_active(void)
+{
+ /* Voice call initialisation */
+ voicecall_activate_helper();
+
+ expected_errtype = OFONO_ERROR_TYPE_NO_ERROR;
+ expected_error = 0;
+
+ /* Release Call */
+ voicecall_driver->release_all_active(0,
+ (ofono_voicecall_cb_t)ofono_generic_cb, 0);
+ ASSERT_AT("AT+CHLD=1");
+ at_response("\r\nOK\r\n");
+
+ voicecall_driver->remove(voicecall_data);
+ ste_voicecall_exit();
+}
+
+static void test_voicecall_answer(void)
+{
+ /* Voice call initialisation */
+ voicecall_activate_helper();
+
+ /* Answer Call */
+ voicecall_driver->answer(0, (ofono_voicecall_cb_t)ofono_generic_cb, 0);
+ ASSERT_AT("ATA");
+ expected_errtype = OFONO_ERROR_TYPE_NO_ERROR;
+ expected_error = 0;
+ at_response("\r\nOK\r\n");
+
+ voicecall_driver->remove(voicecall_data);
+ ste_voicecall_exit();
+}
+
+static void test_voicecall_answer_error(void)
+{
+ /* Voice call initialisation */
+ voicecall_activate_helper();
+
+ /* Answer Call */
+ voicecall_driver->answer(0, (ofono_voicecall_cb_t)ofono_generic_cb, 0);
+ ASSERT_AT("ATA");
+ expected_errtype = OFONO_ERROR_TYPE_FAILURE;
+ expected_error = 0;
+ at_response("\r\nNO CARRIER\r\n");
+
+ voicecall_driver->remove(voicecall_data);
+ ste_voicecall_exit();
+}
+
+static void test_voicecall_multiparty(void)
+{
+ /* Voice call initialisation */
+ voicecall_activate_helper();
+
+ expected_errtype = OFONO_ERROR_TYPE_NO_ERROR;
+ expected_error = 0;
+
+ /* Multiparty */
+ voicecall_driver->create_multiparty(0,
+ (ofono_voicecall_cb_t)ofono_generic_cb, 0);
+ ASSERT_AT("AT+CHLD=3");
+ at_response("\r\nOK\r\n");
+
+ voicecall_driver->remove(voicecall_data);
+ ste_voicecall_exit();
+}
+
+static void test_voicecall_transfer(void)
+{
+ /* Voice call initialisation */
+ voicecall_activate_helper();
+
+ expected_errtype = OFONO_ERROR_TYPE_NO_ERROR;
+ expected_error = 0;
+
+ /* Transfer */
+ voicecall_driver->transfer(0,
+ (ofono_voicecall_cb_t)ofono_generic_cb, 0);
+ ASSERT_AT("AT+CHLD=4");
+ at_response("\r\nOK\r\n");
+
+ voicecall_driver->remove(voicecall_data);
+ ste_voicecall_exit();
+}
+
+static void test_voicecall_deflect(void)
+{
+ /* Voice call initialisation */
+ voicecall_activate_helper();
+
+ expected_errtype = OFONO_ERROR_TYPE_NO_ERROR;
+ expected_error = 0;
+
+ /* Transfer */
+ voicecall_driver->deflect(0, &ph,
+ (ofono_voicecall_cb_t)ofono_generic_cb, 0);
+ ASSERT_AT("AT+CTFR=\"4425993003739\",145");
+ at_response("\r\nOK\r\n");
+
+ voicecall_driver->remove(voicecall_data);
+ ste_voicecall_exit();
+}
+
+static void test_voicecall_send_tones(void)
+{
+ const char *test = "8,9";
+ /* Voice call initialisation */
+ voicecall_activate_helper();
+
+ expected_errtype = OFONO_ERROR_TYPE_NO_ERROR;
+ expected_error = 0;
+
+ /* Send DTMF tone */
+ voicecall_driver->send_tones(0, test,
+ (ofono_voicecall_cb_t)ofono_generic_cb, 0);
+ ASSERT_AT("AT+VTS=8,9");
+ at_response("\r\nOK\r\n");
+
+ voicecall_driver->remove(voicecall_data);
+ ste_voicecall_exit();
+}
+
+static void test_voicecall_release_specific(void)
+{
+ /* Voice call initialisation */
+ voicecall_activate_helper();
+
+ expected_errtype = OFONO_ERROR_TYPE_NO_ERROR;
+ expected_error = 0;
+
+ /* Release Call */
+ voicecall_driver->release_specific(0, 3,
+ (ofono_voicecall_cb_t)ofono_generic_cb, 0);
+ ASSERT_AT("AT+CHLD=13");
+ at_response("\r\nOK\r\n");
+
+ voicecall_driver->remove(voicecall_data);
+ ste_voicecall_exit();
+}
+
+
+static void test_voicecall_ecav_alerting(void)
+{
+ voicecall_activate_helper();
+
+ expected_id = 1;
+ expected_status = CALL_STATUS_INCOMING;
+ sprintf(expected_number, "+4425993005133");
+ at_response("\r\n*ECAV: 1,6,1,,,\"+4425993005133\",145\r\n");
+
+ voicecall_driver->remove(voicecall_data);
+ ste_voicecall_exit();
+}
+
+static void test_voicecall_ecav_alerting_number_withheld(void)
+{
+ voicecall_activate_helper();
+
+ expected_id = 1;
+ expected_status = CALL_STATUS_INCOMING;
+ strcpy(expected_number, "");
+ at_response("\r\n*ECAV: 1,6,1\r\n");
+
+ voicecall_driver->remove(voicecall_data);
+ ste_voicecall_exit();
+}
+
+static void test_voicecall_ecav_waiting(void)
+{
+ voicecall_activate_helper();
+
+ expected_id = 1;
+ expected_status = CALL_STATUS_WAITING;
+ sprintf(expected_number, "+4425993005133");
+ at_response("\r\n*ECAV: 1,5,1,,,\"+4425993005133\",145\r\n");
+
+ voicecall_driver->remove(voicecall_data);
+ ste_voicecall_exit();
+}
+
+static void test_voicecall_ecav_waiting_number_withheld(void)
+{
+ voicecall_activate_helper();
+
+ expected_id = 1;
+ expected_status = CALL_STATUS_WAITING;
+ strcpy(expected_number, "");
+ at_response("\r\n*ECAV: 1,5,1\r\n");
+
+ voicecall_driver->remove(voicecall_data);
+ ste_voicecall_exit();
+}
+
+static void test_voicecall_ecav_calling(void)
+{
+ voicecall_activate_helper();
+
+ expected_id = 1;
+ expected_status = CALL_STATUS_DIALING;
+ sprintf(expected_number, "+4425993005133");
+ at_response("\r\n*ECAV: 1,1,1,,,\"+4425993005133\",145\r\n");
+
+ voicecall_driver->remove(voicecall_data);
+ ste_voicecall_exit();
+}
+
+static void test_voicecall_ecav_idle(void)
+{
+ voicecall_activate_helper();
+
+ expected_id = 1;
+ expected_status = CALL_STATUS_DIALING;
+ sprintf(expected_number, "+4425993005133");
+ at_response("\r\n*ECAV: 1,1,1,,,\"+4425993005133\",145\r\n");
+
+ expected_reason = OFONO_DISCONNECT_REASON_REMOTE_HANGUP;
+ at_response("\r\n*ECAV: 1,0,1,08,016\r\n");
+
+ voicecall_driver->remove(voicecall_data);
+ ste_voicecall_exit();
+}
+
+static void test_voicecall_ecav_connecting(void)
+{
+ voicecall_activate_helper();
+
+ expected_id = 1;
+ expected_status = CALL_STATUS_DIALING;
+ sprintf(expected_number, "+4425993005133");
+ at_response("\r\n*ECAV: 1,1,1,,,\"+4425993005133\",145\r\n");
+
+ expected_status = CALL_STATUS_ALERTING;
+ at_response("\r\n*ECAV: 1,2,1\r\n");
+
+ voicecall_driver->remove(voicecall_data);
+ ste_voicecall_exit();
+}
+
+static void test_voicecall_ecav_active(void)
+{
+ voicecall_activate_helper();
+
+ expected_id = 1;
+ expected_status = CALL_STATUS_DIALING;
+ sprintf(expected_number, "+4425993005133");
+ at_response("\r\n*ECAV: 1,1,1,,,\"+4425993005133\",145\r\n");
+
+ expected_status = CALL_STATUS_ACTIVE;
+ at_response("\r\n*ECAV: 1,3,1\r\n");
+
+ voicecall_driver->remove(voicecall_data);
+ ste_voicecall_exit();
+}
+
+static void test_voicecall_ecav_held(void)
+{
+ voicecall_activate_helper();
+
+ expected_id = 1;
+ expected_status = CALL_STATUS_DIALING;
+ sprintf(expected_number, "+4425993005133");
+ at_response("\r\n*ECAV: 1,1,1,,,\"+4425993005133\",145\r\n");
+
+ expected_status = CALL_STATUS_HELD;
+ at_response("\r\n*ECAV: 1,4,1\r\n");
+
+ voicecall_driver->remove(voicecall_data);
+ ste_voicecall_exit();
+}
+
+static void test_voicecall_ecav_busy(void)
+{
+ voicecall_activate_helper();
+
+ expected_id = 1;
+ expected_status = CALL_STATUS_DIALING;
+ sprintf(expected_number, "+4425993005133");
+ at_response("\r\n*ECAV: 1,1,1,,,\"+4425993005133\",145\r\n");
+
+ expected_reason = OFONO_DISCONNECT_REASON_REMOTE_HANGUP;
+ at_response("\r\n*ECAV: 1,7,1\r\n");
+
+ voicecall_driver->remove(voicecall_data);
+ ste_voicecall_exit();
+}
+
+static void ste_test_add()
+{
+ g_test_add_func("/ste/gprs_nw_deact", test_gprs_nw_deact);
+ g_test_add_func("/ste/gprs_normal", test_gprs_normal);
+ g_test_add_func("/ste/gprs_cgdcont_err", test_gprs_cgdcont_err);
+ g_test_add_func("/ste/gprs_xmlerr", test_gprs_xmlerr);
+ g_test_add_func("/ste/gprs_deact", test_gprs_deactivate);
+ g_test_add_func("/ste/gprs_deact_err", test_gprs_deactivate_err);
+ g_test_add_func("/ste/gprs_deact_err_ok",
+ test_gprs_deact_fail_then_ok);
+ g_test_add_func("/ste/gprs_deact_fail", test_gprs_deactivate_fail);
+ g_test_add_func("/ste/gprs_eppsd_err", test_gprs_eppsd_err);
+ g_test_add_func("/ste/radiosettings_all", test_radiosettings_all);
+ g_test_add_func("/ste/test_voicecall_dial", test_voicecall_dial);
+ g_test_add_func("/ste/test_voicecall_dial_colp",
+ test_voicecall_dial_colp);
+ g_test_add_func("/ste/test_voicecall_dial_erroneous_colp",
+ test_voicecall_dial_erroneous_colp);
+ g_test_add_func("/ste/test_voicecall_dial_fail",
+ test_voicecall_dial_fail);
+ g_test_add_func("/ste/test_voicecall_dial_busy",
+ test_voicecall_dial_busy);
+ g_test_add_func("/ste/test_voicecall_hangup", test_voicecall_hangup);
+ g_test_add_func("/ste/test_voicecall_hangup_fail",
+ test_voicecall_hangup_fail);
+ g_test_add_func("/ste/test_voicecall_hold", test_voicecall_hold);
+ g_test_add_func("/ste/test_voicecall_release_all_held",
+ test_voicecall_release_all_held);
+ g_test_add_func("/ste/test_voicecall_release_all_active",
+ test_voicecall_release_all_active);
+ g_test_add_func("/ste/test_voicecall_answer", test_voicecall_answer);
+ g_test_add_func("/ste/test_voicecall_dial_no_dialtone",
+ test_voicecall_dial_no_dialtone);
+ g_test_add_func("/ste/test_voicecall_answer_error",
+ test_voicecall_answer_error);
+ g_test_add_func("/ste/test_voicecall_multiparty",
+ test_voicecall_multiparty);
+ g_test_add_func("/ste/test_voicecall_transfer",
+ test_voicecall_transfer);
+ g_test_add_func("/ste/test_voicecall_deflect", test_voicecall_deflect);
+ g_test_add_func("/ste/test_voicecall_send_tones",
+ test_voicecall_send_tones);
+ g_test_add_func("/ste/test_voicecall_release_specific",
+ test_voicecall_release_specific);
+ g_test_add_func("/ste/test_voicecall_ecav_alerting",
+ test_voicecall_ecav_alerting);
+ g_test_add_func("/ste/test_voicecall_ecav_alerting_number_withheld",
+ test_voicecall_ecav_alerting_number_withheld);
+ g_test_add_func("/ste/test_voicecall_ecav_waiting",
+ test_voicecall_ecav_waiting);
+ g_test_add_func("/ste/test_voicecall_ecav_waiting_number_withheld",
+ test_voicecall_ecav_waiting_number_withheld);
+ g_test_add_func("/ste/test_voicecall_ecav_calling",
+ test_voicecall_ecav_calling);
+ g_test_add_func("/ste/test_voicecall_ecav_held",
+ test_voicecall_ecav_held);
+ g_test_add_func("/ste/test_voicecall_ecav_busy",
+ test_voicecall_ecav_busy);
+ g_test_add_func("/ste/test_voicecall_ecav_idle",
+ test_voicecall_ecav_idle);
+ g_test_add_func("/ste/test_voicecall_ecav_connecting",
+ test_voicecall_ecav_connecting);
+ g_test_add_func("/ste/test_voicecall_ecav_active",
+ test_voicecall_ecav_active);
+ return;
+}
+
+void ofono_debug(const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ if (g_test_verbose())
+ vprintf(format, ap);
+ va_end(ap);
+}
+
+void ofono_error(const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ vprintf(format, ap);
+ va_end(ap);
+}
+
+static void ste_debug(const char *str, void *user_data)
+{
+ if (g_test_verbose())
+ g_print("%s\n", str);
+}
+
+int main(int argc, char **argv)
+{
+ GIOChannel *channel = NULL;
+ GAtSyntax *syntax = NULL;
+ int pair[2];
+
+ if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNIX, pair) < 0)
+ goto err;
+
+ /*
+ * Give one end of the socket pair, for simulating modem
+ * responses.
+ */
+ phone_fd = pair[1];
+
+
+ /* And the other end of the socket pair to at_chan */
+ channel = g_io_channel_unix_new(pair[0]);
+ if (channel == NULL)
+ goto err;
+
+ g_io_channel_set_close_on_unref(channel, TRUE);
+ syntax = g_at_syntax_new_gsm_permissive();
+ if (syntax == NULL)
+ goto err;
+
+ chat = g_at_chat_new_blocking(channel, syntax);
+ if (chat == NULL)
+ goto err;
+
+ g_at_syntax_unref(syntax);
+ g_io_channel_unref(channel);
+ g_at_chat_set_debug(chat, ste_debug, NULL);
+
+ event_loop = g_main_loop_new(NULL, FALSE);
+
+ g_test_init(&argc, &argv, NULL);
+ ste_test_add();
+ g_test_run();
+
+ g_main_loop_unref(event_loop);
+ g_at_chat_unref(chat);
+
+ return 0;
+
+err:
+ if (syntax != NULL)
+ g_at_syntax_unref(syntax);
+
+ if (channel != NULL)
+ g_io_channel_unref(channel);
+
+ g_print("error\n");
+ return 10;
+}
--
1.7.1
10 years
[PATCH 0/3] Voice call SS notifications (2nd version)
by Andras Domokos
Implementation proposal for handling some of the voice call
related Supplementary Services (SS) notifications.
Implementation details:
- removed SSN atom
- expanded the SS notify functions with call number info, useful
for modems capable of delivering it in the SS notifications
- expanded the SS callback functions with call number info and
service code, useful in demultiplexing when a common callback
function is defined for multiple service codes
- added +CSSU and +CSSI type SS notifications handling to the
voicecall code
Andras Domokos (3):
ssn: remove SSN atom
ssn: add code and call id to notifications
voicecall: add SSN notifications handling
drivers/atmodem/ssn.c | 6 +-
include/ssn.h | 12 ++--
include/types.h | 2 +
plugins/calypso.c | 1 -
plugins/g1.c | 1 -
plugins/huawei.c | 1 -
plugins/ifx.c | 1 -
plugins/isiusb.c | 1 -
plugins/linktop.c | 1 -
plugins/n900.c | 1 -
plugins/phonesim.c | 1 -
plugins/ste.c | 1 -
plugins/tc65.c | 1 -
plugins/u8500.c | 1 -
plugins/wavecom.c | 1 -
src/ofono.h | 5 +-
src/ssn.c | 66 +++++---------
src/voicecall.c | 240 ++++++++++++++++++++++++++++++++++++++++++++++++-
18 files changed, 272 insertions(+), 71 deletions(-)
10 years
[PATCH 0/5 v4] Neighbor Cell Info Atom
by Antti Paila
This series of patches implements an interface for client
applications to fetch the ECID information of neighboring
cells using DBUS. Since the 1st version the DBUS api has
been refactored to use new naming for method and to use
flat data format for the cell information. Also, the
internal datatypes have been optimized. Since the 2nd
version MNC and MCC are converted to strings and CPICH-RSCP
re-typed. Since 3rd version multiradio support is added and
interfaces are renamed.
Antti Paila (5):
cell-info: CellInfo DBUS interface definition
cell-info: Header files for neighbor cell info
cell-info: Atom for neighbor cell info
cell-info: New files included in compilation
cell-info: Documentation
Makefile.am | 9 +-
doc/cell-info.txt | 122 +++++++++++++
include/cell-info.h | 126 ++++++++++++++
include/dbus.h | 1 +
src/cell-info.c | 475 +++++++++++++++++++++++++++++++++++++++++++++++++++
src/ofono.h | 1 +
6 files changed, 731 insertions(+), 3 deletions(-)
create mode 100644 doc/cell-info.txt
create mode 100644 include/cell-info.h
create mode 100644 src/cell-info.c
10 years, 1 month