Merge lp:~awe/phablet-extras/ofono-unittest-gprs-context into lp:phablet-extras/ofono

Proposed by Tony Espy on 2013-07-08
Status: Merged
Approved by: Ricardo Salveti on 2013-07-29
Approved revision: 67
Merged at revision: 48
Proposed branch: lp:~awe/phablet-extras/ofono-unittest-gprs-context
Merge into: lp:phablet-extras/ofono
Diff against target: 2756 lines (+1901/-394)
20 files modified
Makefile.am (+23/-2)
drivers/rilmodem/gprs-context.c (+187/-260)
drivers/rilmodem/rilutil.c (+2/-81)
drivers/rilmodem/rilutil.h (+0/-13)
gril/gril.c (+19/-6)
gril/gril.h (+10/-8)
gril/grilreply.c (+225/-0)
gril/grilreply.h (+57/-0)
gril/grilrequest.c (+213/-0)
gril/grilrequest.h (+63/-0)
gril/grilunsol.c (+158/-0)
gril/grilunsol.h (+62/-0)
gril/grilutil.c (+47/-0)
gril/grilutil.h (+9/-5)
gril/parcel.c (+15/-19)
gril/ril_constants.h (+12/-0)
include/types.h (+10/-0)
unit/test-grilreply.c (+339/-0)
unit/test-grilrequest.c (+312/-0)
unit/test-grilunsol.c (+138/-0)
To merge this branch: bzr merge lp:~awe/phablet-extras/ofono-unittest-gprs-context
Reviewer Review Type Date Requested Status
Ricardo Salveti Approve on 2013-07-29
PS Jenkins bot continuous-integration Approve on 2013-07-28
Sergio Schvezov 2013-07-08 Needs Fixing on 2013-07-12
Review via email: mp+173558@code.launchpad.net

Commit message

[gril/rilmodem] Re-factor gprs-context code to facilitate unit testing.

Description of the change

This branch re-factors rilmodem's gprs-context module such that all RIL message code has been moved into the lower gril base layer. This was done to allow unit testing of the RIL parcel code used by gprs-context.

Once this code has been merged, the plan is to re-factor the rest of the rilmodem code using this approach.

Tested on an un-flipped raring image running on maguro.

To post a comment you must log in.
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Tony Espy (awe) wrote :

Build failure is due to the fact that I didn't add the unit test source file... I'm working on restoring it, and should have this branch updated by end-of-day.

54. By Tony Espy on 2013-07-10

[gril] Re-work of gprsmessages based on unit testing.

55. By Tony Espy on 2013-07-10

[gril] Initial gprs-context unit tests for grilmessages.

56. By Tony Espy on 2013-07-10

[gril] Make changes for unit testing.

Sergio Schvezov (sergiusens) wrote :

I would split:
823 +static void test_invalid_setup_data_calls(void)
834 + /* Test invalid radio tech values */
847 + /* Test invalid data profile */
855 + /* Invalid APNs */
...
and so on for the other test functions into individual test cases.

Also consider the posibility of a test fixture for each of these test functions(at your discretion)
https://developer.gnome.org/glib/2.28/glib-Testing.html#g-test-add

Is it a good idea to make a free_reply (or with similar name) that would take care of freeing the complete struct and then just call that?
238 + g_strfreev(reply.dns_addresses);
239 + g_strfreev(reply.ip_addrs);
240 + g_strfreev(reply.gateways);
249 + g_free(reply.ifname);

review: Needs Fixing
Tony Espy (awe) wrote :

@Sergio

Thanks for the comments, and I agree that splitting the tests out probably makes sense.

Also per our discussion yesterday, I will split grilmessages.c into three separate files: grilrequests.c, grilreplies.c, and grilevents.c.

Finally, I also mentioned that I only added unit tests for the SETUP_DATA_CALL request. I will go ahead and add unit tests for the corresponding reply as well.

I should be able to wrap up all these changes today.

Sergio Schvezov (sergiusens) wrote :

On Fri, Jul 12, 2013 at 12:15 PM, Tony Espy <email address hidden> wrote:
> @Sergio
>
> Thanks for the comments, and I agree that splitting the tests out probably makes sense.
>
> Also per our discussion yesterday, I will split grilmessages.c into three separate files: grilrequests.c, grilreplies.c, and grilevents.c.
>
> Finally, I also mentioned that I only added unit tests for the SETUP_DATA_CALL request. I will go ahead and add unit tests for the corresponding reply as well.
>
> I should be able to wrap up all these changes today.

Sounds good to me :-)

57. By Tony Espy on 2013-07-17

[gril/rilmodem] Split grilmessages into grilrequest, grilreply, and grilunsol.

58. By Tony Espy on 2013-07-17

[rilmodem] Back out AudioSystem and Makefile.am changes made by mistake.

59. By Tony Espy on 2013-07-19

[gril] Re-factored low-level message support into type-specific modules.

60. By Tony Espy on 2013-07-19

[gril] Fixed the tracing logic, and cleaned up some minor warnings.

PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
61. By Tony Espy on 2013-07-19

Re-merge from trunk.

PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Tony Espy (awe) wrote :

Two last things need to be fixed.

First, the CI build fails due to a unit test failure. This is the test I mentioned earlier that was also failing in pbuild.

ERROR:unit/test-grilrequest.c:200:test_deactivate_data_call_valid: assertion failed: (!memcmp(rilp.data, test_data->parcel_data, test_data->parcel_size)\

Test test tries to compare wire-format parcel data ( stored in rilp.data ) to a static guchar of bytes that represent what the parcel wire format should look like.

The second issue is how the gprs-context code handles setup_data_call failures. I'm not sure if a failure callback triggers a disconnect from the core ofono code or not. If it does, then the code should be fine as is. If it doesn't, then this could potentially leave an active data call within RIL, and thus we should explicitly disconnect in this case.

Tony Espy (awe) wrote :

OK, so it appears the failure callback doesn't trigger a disconnect, so I'll modify the code to do that if the SETUP_DATA_CALL reply triggers a message validation error.

Tony Espy (awe) wrote :

I'll plan on landing the final bits over the weekend...

62. By Tony Espy on 2013-07-20

[gril/grilmodem] Ensure that data call is deactivated in invalid reply scenarios.

PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
63. By Tony Espy on 2013-07-22

[gril] Fix a bug in parcel_w_string() that can cause an invalid string terminator to be generated.

Tony Espy (awe) wrote :

OK, both problems are now fixed.

Data calls are properly disconnected if a reply is received from RIL that is deemed invalid by the gril code.

The unit test failure was due to a subtle bug in parcel_w_string() which could result in invalid string terminator bytes to be included due to an incorrect offset used to write the terminating utf16 0x00000.

64. By Tony Espy on 2013-07-26

[rilmodem] Implement gprs_context_detach_shutdown().

Ricardo Salveti (rsalveti) wrote :

127 - if (message->req != RIL_UNSOL_DATA_CALL_LIST_CHANGED) {
128 - ofono_error("ril_gprs_update_calls: invalid message received %d",
129 - message->req);
130 - return;
131 - }

Why did you remove the above? g_ril_unsol_parse_data_call_list is also not checking if the message is indeed UNSOL_DATA_CALL_LIST_CHANGED.

1017 + g_free(reply);
1611 + g_free(call);
1621 + g_free(unsol);

Not an issue, but as you're checking for call and unsol just before free, you could include the g_free call as part of the if scope.

901 +#define OFONO_EINVAL(error) do { \
902 + error->type = OFONO_ERROR_TYPE_FAILURE; \
903 + error->error = -EINVAL; \
904 +} while (0)
905 +
906 +#define OFONO_NO_ERROR(error) do { \
907 + error->type = OFONO_ERROR_TYPE_NO_ERROR; \
908 + error->error = 0; \
909 +} while (0)
910 +

These would be better if defined somewhere in a common ofono code, not just for ril.

2018 +static const struct ril_msg reply_data_call_invalid_2 = {
2019 + .buf = (gchar *) &reply_data_call_invalid_parcel1,

2052 +static const struct ril_msg reply_data_call_invalid_3 = {
2053 + .buf = (gchar *) &reply_data_call_invalid_parcel2,

2084 +static const struct ril_msg reply_data_call_invalid_4 = {
2085 + .buf = (gchar *) &reply_data_call_invalid_parcel3,

2115 +static const struct ril_msg reply_data_call_invalid_5 = {
2116 + .buf = (gchar *) &reply_data_call_invalid_parcel4,

2147 +static const struct ril_msg reply_data_call_invalid_6 = {
2148 + .buf = (gchar *) &reply_data_call_invalid_parcel5,

2176 +static const struct ril_msg reply_data_call_invalid_7 = {
2177 + .buf = (gchar *) &reply_data_call_invalid_parcel6,

Would you mind changing the test id to match the same number used by both structs? Otherwise it gets quite confusing when reading the code, as data_call_invalid_2 is part of invalid_parcel_1, instead of invalid_parcel_2 (which is a natural reading by our brain).

Other than those minor comments, code looks good (although it could technically be separated in more MRs, as we discussed).

Will now test in both mako and maguro.

review: Needs Fixing
Ricardo Salveti (rsalveti) wrote :

Tested with both mako and maguro and it seems to be all good :-)

Just minor issue I got with my maguro is that the modem can't attach anymore it seems, but don't think it's related with this MR (might be that intermittent issue we had this week).

Will test a bit more with maguro...

Would be nice if you could double check with it as well.

Ricardo Salveti (rsalveti) wrote :

Yeah, can't get my mako to attach anymore, with/without NM, and even after a clean install.

We might be having another issue somewhere in this code, which is not related with this MR.

Ricardo Salveti (rsalveti) wrote :

Argh, *maguro*.

Ricardo Salveti (rsalveti) wrote :

Ok, the issue with maguro is that it cannot attach at first, but it works after restarting ofono =\

First run, not attached:
http://paste.ubuntu.com/5917341/

Second run, attached:
http://paste.ubuntu.com/5917346/

Wonder if this is a side effect of that roaming bug you fixed (will follow up this in a bug).

Tony Espy (awe) wrote :

Question, were you testing with just this MR, or the combined MRs? As we discussed, the attach fix was split between the two MRs due to the heavy re-factoring of gprs-context.c in this MR.

I will look at your comments above, which all seem reasonable and try and update the MR later today.

I will also do some more testing to see if I can reproduce any of the issues you ran into while testing.

Note, my fix assumes that NetworkManager always sets the ConnectionManager's 'Powered' on start-up. Perhaps there's a race condition and this isn't always happening?

Ricardo Salveti (rsalveti) wrote :

Just with this MR, and without NetworkManager involved. Was just tracking the ofono state after it was properly initialized.

Tony Espy (awe) wrote :

OK, I'll plan on giving both a shake-down tomorrow after I clean up the couple of things based on your previous comment.

This code really shouldn't have effected whether GPRS attaches or not, as it only touches the gprs-context driver.

65. By Tony Espy on 2013-07-28

[gril] Moved ofono error helper #defines into <ofono/types.h>

66. By Tony Espy on 2013-07-28

[gril] Re-numbered parcel unit test data variables to match test cases.

67. By Tony Espy on 2013-07-28

[gril] Minor re-factoring in helper functions.

Tony Espy (awe) wrote :

> 127 - if (message->req != RIL_UNSOL_DATA_CALL_LIST_CHANGED) {
> 128 - ofono_error("ril_gprs_update_calls: invalid message received %d",
> 129 - message->req);
> 130 - return;
> 131 - }
>
> Why did you remove the above? g_ril_unsol_parse_data_call_list is also not
> checking if the message is indeed UNSOL_DATA_CALL_LIST_CHANGED.

I removed it because it wasn't needed. If you look at the code in gril.c that handles unsolicited messages, it's not really possible for the wrong message to be passed to a registered listener, as that's the whole purpose of registering for a particular message.

> 1017 + g_free(reply);
> 1611 + g_free(call);
> 1621 + g_free(unsol);
>
> Not an issue, but as you're checking for call and unsol just before free, you
> could include the g_free call as part of the if scope.

Done.

> 901 +#define OFONO_EINVAL(error) do { \
> 902 + error->type = OFONO_ERROR_TYPE_FAILURE; \
> 903 + error->error = -EINVAL; \
> 904 +} while (0)
> 905 +
> 906 +#define OFONO_NO_ERROR(error) do { \
> 907 + error->type = OFONO_ERROR_TYPE_NO_ERROR; \
> 908 + error->error = 0; \
> 909 +} while (0)
> 910 +
>
> These would be better if defined somewhere in a common ofono code, not just
> for ril.

Done, moved these to <ofono/type.h>.
>
> 2018 +static const struct ril_msg reply_data_call_invalid_2 = {
> 2019 + .buf = (gchar *) &reply_data_call_invalid_parcel1,
>
> 2052 +static const struct ril_msg reply_data_call_invalid_3 = {
> 2053 + .buf = (gchar *) &reply_data_call_invalid_parcel2,
>
> 2084 +static const struct ril_msg reply_data_call_invalid_4 = {
> 2085 + .buf = (gchar *) &reply_data_call_invalid_parcel3,
>
> 2115 +static const struct ril_msg reply_data_call_invalid_5 = {
> 2116 + .buf = (gchar *) &reply_data_call_invalid_parcel4,
>
> 2147 +static const struct ril_msg reply_data_call_invalid_6 = {
> 2148 + .buf = (gchar *) &reply_data_call_invalid_parcel5,
>
> 2176 +static const struct ril_msg reply_data_call_invalid_7 = {
> 2177 + .buf = (gchar *) &reply_data_call_invalid_parcel6,
>
> Would you mind changing the test id to match the same number used by both
> structs? Otherwise it gets quite confusing when reading the code, as
> data_call_invalid_2 is part of invalid_parcel_1, instead of invalid_parcel_2
> (which is a natural reading by our brain).

Yea, I thought about this an since the first test case didn't actually have parcel_data, I thought it would be weird having the first parcel data variable start with "2". Oh well, not a big deal. Re-number per your suggestion.

> Other than those minor comments, code looks good (although it could
> technically be separated in more MRs, as we discussed).
>
> Will now test in both mako and maguro.

Ricardo Salveti (rsalveti) wrote :

Good, thanks!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Makefile.am'
2--- Makefile.am 2013-06-18 00:13:38 +0000
3+++ Makefile.am 2013-07-28 19:18:23 +0000
4@@ -93,7 +93,10 @@
5 gril/grilio.c gril/grilutil.h \
6 gril/grilutil.c gril/ringbuffer.h \
7 gril/gfunc.h gril/ril.h \
8- gril/parcel.c gril/parcel.h
9+ gril/parcel.c gril/parcel.h \
10+ gril/grilreply.c gril/grilreply.h \
11+ gril/grilrequest.c gril/grilrequest.h \
12+ gril/grilunsol.c gril/grilunsol.h
13
14 btio_sources = btio/btio.h btio/btio.c
15
16@@ -684,7 +687,10 @@
17
18 unit_tests = unit/test-common unit/test-util unit/test-idmap \
19 unit/test-simutil unit/test-stkutil \
20- unit/test-sms unit/test-cdmasms
21+ unit/test-sms unit/test-cdmasms \
22+ unit/test-grilrequest \
23+ unit/test-grilreply \
24+ unit/test-grilunsol
25
26 noinst_PROGRAMS = $(unit_tests) \
27 unit/test-sms-root unit/test-mux unit/test-caif
28@@ -736,6 +742,21 @@
29 unit_test_caif_LDADD = @GLIB_LIBS@
30 unit_objects += $(unit_test_caif_OBJECTS)
31
32+unit_test_grilrequest_SOURCES = unit/test-grilrequest.c $(gril_sources) \
33+ src/log.c gatchat/ringbuffer.c
34+unit_test_grilrequest_LDADD = @GLIB_LIBS@
35+unit_objects += $(unit_test_grilrequest_OBJECTS)
36+
37+unit_test_grilreply_SOURCES = unit/test-grilreply.c $(gril_sources) \
38+ src/log.c gatchat/ringbuffer.c
39+unit_test_grilreply_LDADD = @GLIB_LIBS@
40+unit_objects += $(unit_test_grilreply_OBJECTS)
41+
42+unit_test_grilunsol_SOURCES = unit/test-grilunsol.c $(gril_sources) \
43+ src/log.c gatchat/ringbuffer.c
44+unit_test_grilunsol_LDADD = @GLIB_LIBS@
45+unit_objects += $(unit_test_grilunsol_OBJECTS)
46+
47 TESTS = $(unit_tests)
48
49 if TOOLS
50
51=== modified file 'drivers/rilmodem/gprs-context.c'
52--- drivers/rilmodem/gprs-context.c 2013-06-13 14:59:09 +0000
53+++ drivers/rilmodem/gprs-context.c 2013-07-28 19:18:23 +0000
54@@ -38,23 +38,12 @@
55 #include <ofono/gprs-context.h>
56 #include <ofono/types.h>
57
58-#include "gril.h"
59-#include "grilutil.h"
60+#include "grilreply.h"
61+#include "grilrequest.h"
62+#include "grilunsol.h"
63
64 #include "rilmodem.h"
65
66-/* REQUEST_DEACTIVATE_DATA_CALL parameter values */
67-#define DEACTIVATE_DATA_CALL_NUM_PARAMS 2
68-#define DEACTIVATE_DATA_CALL_NO_REASON "0"
69-
70-/* REQUEST_SETUP_DATA_CALL parameter values */
71-#define SETUP_DATA_CALL_PARAMS 7
72-#define CHAP_PAP_OK "3"
73-#define DATA_PROFILE_DEFAULT "0"
74-#define PROTO_IP "IP"
75-#define PROTO_IPV6 "IPV6"
76-#define PROTO_IPV4V6 "IPV4V6"
77-
78 enum state {
79 STATE_IDLE,
80 STATE_ENABLING,
81@@ -64,36 +53,51 @@
82
83 struct gprs_context_data {
84 GRil *ril;
85- unsigned int active_ctx_cid;
86- unsigned int active_rild_cid;
87- char username[OFONO_GPRS_MAX_USERNAME_LENGTH + 1];
88- char password[OFONO_GPRS_MAX_PASSWORD_LENGTH + 1];
89+ guint active_ctx_cid;
90+ gint active_rild_cid;
91 enum state state;
92 };
93
94+static void ril_gprs_context_deactivate_primary(struct ofono_gprs_context *gc,
95+ unsigned int id,
96+ ofono_gprs_context_cb_t cb, void *data);
97+
98+static void set_context_disconnected(struct gprs_context_data *gcd)
99+{
100+ DBG("");
101+
102+ gcd->active_ctx_cid = -1;
103+ gcd->active_rild_cid = -1;
104+ gcd->state = STATE_IDLE;
105+}
106+
107+static void disconnect_context(struct ofono_gprs_context *gc)
108+{
109+ ril_gprs_context_deactivate_primary(gc, 0, NULL, NULL);
110+}
111+
112 static void ril_gprs_context_call_list_changed(struct ril_msg *message,
113 gpointer user_data)
114 {
115 struct ofono_gprs_context *gc = user_data;
116 struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
117 struct data_call *call = NULL;
118+ struct unsol_data_call_list *unsol;
119 gboolean active_cid_found = FALSE;
120 gboolean disconnect = FALSE;
121- GSList *calls = NULL, *iterator = NULL;
122+ GSList *iterator = NULL;
123+ struct ofono_error error;
124
125 DBG("");
126
127- if (message->req != RIL_UNSOL_DATA_CALL_LIST_CHANGED) {
128- ofono_error("ril_gprs_update_calls: invalid message received %d",
129- message->req);
130- return;
131- }
132-
133- calls = ril_util_parse_data_call_list(gcd->ril, message);
134-
135- DBG("number of call in call_list_changed is: %d", g_slist_length(calls));
136-
137- for (iterator = calls; iterator; iterator = iterator->next) {
138+ unsol = g_ril_unsol_parse_data_call_list(gcd->ril, message, &error);
139+
140+ if (error.type != OFONO_ERROR_TYPE_NO_ERROR)
141+ goto error;
142+
143+ DBG("number of call in call_list_changed is: %d", unsol->num);
144+
145+ for (iterator = unsol->call_list; iterator; iterator = iterator->next) {
146 call = (struct data_call *) iterator->data;
147
148 if (call->cid == gcd->active_rild_cid) {
149@@ -113,13 +117,11 @@
150 if (disconnect || active_cid_found == FALSE) {
151 DBG("Clearing active context");
152
153- gcd->active_ctx_cid = -1;
154- gcd->active_rild_cid = -1;
155- gcd->state = STATE_IDLE;
156+ set_context_disconnected(gcd);
157 }
158
159- g_slist_foreach(calls, (GFunc) g_free, NULL);
160- g_slist_free(calls);
161+error:
162+ g_ril_unsol_free_data_call_list(unsol);
163 }
164
165 static void ril_setup_data_call_cb(struct ril_msg *message, gpointer user_data)
166@@ -129,87 +131,67 @@
167 struct ofono_gprs_context *gc = cbd->user;
168 struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
169 struct ofono_error error;
170- struct parcel rilp;
171- int status, retry_time, cid, active, num, version;
172- char *dnses = NULL, *ifname = NULL;
173- char *raw_ip_addrs = NULL, *raw_gws = NULL, *type = NULL;
174- char **dns_addresses = NULL, **gateways = NULL;
175- char **ip_addrs = NULL, **split_ip_addr = NULL;
176-
177- /* TODO:
178- * Cleanup duplicate code between this function and
179- * ril_util_parse_data_call_list().
180- */
181-
182- /* valid size: 36 (34 if HCRADIO defined) */
183- if (message->buf_len < 36) {
184- DBG("Parcel is less then minimum DataCallResponseV6 size!");
185- decode_ril_error(&error, "FAIL");
186- goto error;
187- }
188+ struct reply_setup_data_call *reply;
189+ char **split_ip_addr = NULL;
190
191 if (message->error != RIL_E_SUCCESS) {
192 DBG("Reply failure: %s", ril_error_to_string(message->error));
193- decode_ril_error(&error, "FAIL");
194+
195+ error.type = OFONO_ERROR_TYPE_FAILURE;
196 error.error = message->error;
197- goto error;
198- }
199-
200- ril_util_init_parcel(message, &rilp);
201+
202+ set_context_disconnected(gcd);
203+ goto error;
204+ }
205+
206+ reply = g_ril_reply_parse_data_call(gcd->ril, message, &error);
207+
208+ gcd->active_rild_cid = reply->cid;
209+
210+ if (error.type != OFONO_ERROR_TYPE_NO_ERROR) {
211+ if (gcd->active_rild_cid != -1)
212+ disconnect_context(gc);
213+
214+ goto error;
215+ }
216+
217+ if (reply->status != 0) {
218+ ofono_error("%s: reply->status is non-zero: %d",
219+ __func__,
220+ reply->status);
221+
222+ error.type = OFONO_ERROR_TYPE_FAILURE;
223+ error.error = reply->status;
224+
225+ set_context_disconnected(gcd);
226+ goto error;
227+ }
228
229 /*
230- * ril.h documents the reply to a RIL_REQUEST_SETUP_DATA_CALL
231- * as being a RIL_Data_Call_Response_v6 struct, however in
232- * reality, the response actually includes the version of the
233- * struct, followed by an array of calls, so the array size
234- * also has to be read after the version.
235+ * TODO: consier moving this into parse_data_reply
236 *
237- * TODO: What if there's more than 1 call in the list??
238+ * Note - the address may optionally include a prefix size
239+ * ( Eg. "/30" ). As this confuses NetworkManager, we
240+ * explicitly strip any prefix after calculating the netmask.
241 */
242- version = parcel_r_int32(&rilp);
243- num = parcel_r_int32(&rilp);
244-
245- status = parcel_r_int32(&rilp);
246- retry_time = parcel_r_int32(&rilp);
247- cid = parcel_r_int32(&rilp);
248- active = parcel_r_int32(&rilp);
249-
250- type = parcel_r_string(&rilp);
251- ifname = parcel_r_string(&rilp);
252- raw_ip_addrs = parcel_r_string(&rilp);
253- dnses = parcel_r_string(&rilp);
254- raw_gws = parcel_r_string(&rilp);
255-
256- g_ril_append_print_buf(gcd->ril,
257- "{version=%d,num=%d [status=%d,retry=%d,cid=%d,active=%d,type=%s,ifname=%s,address=%s,dns=%s,gateways=%s]}",
258- version,
259- num,
260- status,
261- retry_time,
262- cid,
263- active,
264- type,
265- ifname,
266- raw_ip_addrs,
267- dnses,
268- raw_gws);
269- g_ril_print_response(gcd->ril, message);
270-
271- if (status != 0) {
272- DBG("Reply failure; status %d", status);
273- gcd->state = STATE_IDLE;
274+ split_ip_addr = g_strsplit(reply->ip_addrs[0], "/", 2);
275+
276+ /* TODO: see note above re: invalid messages... */
277+ if (split_ip_addr[0] == NULL) {
278+ ofono_error("%s: invalid IP address field returned: %s",
279+ __func__,
280+ reply->ip_addrs[0]);
281+
282+ error.type = OFONO_ERROR_TYPE_FAILURE;
283+ error.error = EINVAL;
284+
285+ set_context_disconnected(gcd);
286 goto error;
287 }
288
289 gcd->state = STATE_ACTIVE;
290- gcd->active_rild_cid = cid;
291-
292- ofono_gprs_context_set_interface(gc, ifname);
293-
294- /*
295- * TODO: re-factor the following code into a
296- * ril_util function that can be unit-tested.
297- */
298+
299+ ofono_gprs_context_set_interface(gc, reply->ifname);
300
301 /* TODO:
302 * RILD can return multiple addresses; oFono only supports
303@@ -218,65 +200,19 @@
304 * just specify the end-points of the point-to-point
305 * connection, in which case this code will need to
306 * changed to handle such a device.
307- *
308- * For now split into a maximum of three, and only use
309- * the first address for the remaining operations.
310 */
311- ip_addrs = g_strsplit(raw_ip_addrs, " ", 3);
312- if (ip_addrs[0] == NULL) {
313- DBG("No IP address specified: %s", raw_ip_addrs);
314- decode_ril_error(&error, "FAIL");
315- goto error;
316- }
317-
318 ofono_gprs_context_set_ipv4_netmask(gc,
319- ril_util_get_netmask(ip_addrs[0]));
320-
321- /*
322- * Note - the address may optionally include a prefix size
323- * ( Eg. "/30" ). As this confuses NetworkManager, we
324- * explicitly strip any prefix after calculating the netmask.
325- */
326- split_ip_addr = g_strsplit(ip_addrs[0], "/", 2);
327- if (split_ip_addr[0] == NULL) {
328- DBG("Invalid IP address field returned: %s", raw_ip_addrs);
329- decode_ril_error(&error, "FAIL");
330- goto error;
331- }
332+ ril_util_get_netmask(reply->ip_addrs[0]));
333
334 ofono_gprs_context_set_ipv4_address(gc, split_ip_addr[0], TRUE);
335-
336- /*
337- * RILD can return multiple addresses; oFono only supports
338- * setting a single IPv4 gateway.
339- */
340- gateways = g_strsplit(raw_gws, " ", 3);
341- if (gateways[0] == NULL) {
342- DBG("Invalid gateways field returned: %s", raw_gws);
343- decode_ril_error(&error, "FAIL");
344- goto error;
345- }
346-
347- ofono_gprs_context_set_ipv4_gateway(gc, gateways[0]);
348-
349- /* Split DNS addresses */
350- dns_addresses = g_strsplit(dnses, " ", 3);
351+ ofono_gprs_context_set_ipv4_gateway(gc, reply->gateways[0]);
352+
353 ofono_gprs_context_set_ipv4_dns_servers(gc,
354- (const char **) dns_addresses);
355-
356- decode_ril_error(&error, "OK");
357+ (const char **) reply->dns_addresses);
358
359 error:
360- g_strfreev(dns_addresses);
361- g_strfreev(ip_addrs);
362+ g_ril_reply_free_setup_data_call(reply);
363 g_strfreev(split_ip_addr);
364- g_strfreev(gateways);
365-
366- g_free(type);
367- g_free(ifname);
368- g_free(raw_ip_addrs);
369- g_free(dnses);
370- g_free(raw_gws);
371
372 cb(&error, cbd->data);
373 }
374@@ -287,91 +223,61 @@
375 {
376 struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
377 struct cb_data *cbd = cb_data_new(cb, data);
378+ struct req_setup_data_call request;
379 struct parcel rilp;
380- gchar *protocol = PROTO_IP;
381- gchar tech[3];
382- int request = RIL_REQUEST_SETUP_DATA_CALL;
383- int ret;
384+ struct ofono_error error;
385+ int reqid = RIL_REQUEST_SETUP_DATA_CALL;
386+ int ret = 0;
387+
388+ DBG("Activating contex: %d", ctx->cid);
389
390 cbd->user = gc;
391+
392+ /* TODO: implement radio technology selection. */
393+ request.tech = RADIO_TECH_HSPA;
394+
395+ /* TODO: add comments about tethering, other non-public
396+ * profiles...
397+ */
398+ request.data_profile = RIL_DATA_PROFILE_DEFAULT;
399+ request.apn = g_strdup(ctx->apn);
400+ request.username = g_strdup(ctx->username);
401+ request.password = g_strdup(ctx->password);
402+ request.auth_type = RIL_AUTH_BOTH;
403+ request.protocol = ctx->proto;
404+
405+ if (g_ril_request_setup_data_call(gcd->ril,
406+ &request,
407+ &rilp,
408+ &error) == FALSE) {
409+ ofono_error("Couldn't build SETUP_DATA_CALL request.");
410+ goto error;
411+ }
412+
413 gcd->active_ctx_cid = ctx->cid;
414 gcd->state = STATE_ENABLING;
415
416- memcpy(gcd->username, ctx->username, sizeof(ctx->username));
417- memcpy(gcd->password, ctx->password, sizeof(ctx->password));
418-
419- parcel_init(&rilp);
420- parcel_w_int32(&rilp, SETUP_DATA_CALL_PARAMS);
421-
422- /* RadioTech: hardcoded to HSPA for now... */
423- sprintf((char *) tech, "%d", (int) RADIO_TECH_HSPA);
424- DBG("setting tech to: %s", tech);
425- parcel_w_string(&rilp, (char *) tech);
426-
427- /*
428- * TODO ( OEM/Tethering ): DataProfile:
429- *
430- * Other options are TETHERING (1) or OEM_BASE (1000).
431- */
432- parcel_w_string(&rilp, DATA_PROFILE_DEFAULT);
433-
434- /* APN */
435- parcel_w_string(&rilp, (char *) (ctx->apn));
436-
437- if (ctx->username && strlen(ctx->username)) {
438- parcel_w_string(&rilp, (char *) (ctx->username));
439- } else {
440- parcel_w_string(&rilp, NULL);
441- }
442-
443- if (ctx->password && strlen(ctx->password)) {
444- parcel_w_string(&rilp, (char *) (ctx->password));
445- } else {
446- parcel_w_string(&rilp, NULL);
447- }
448-
449- /*
450- * TODO: review with operators...
451- * Auth type: PAP/CHAP may be performed
452- */
453- parcel_w_string(&rilp, CHAP_PAP_OK);
454-
455- switch (ctx->proto) {
456- case OFONO_GPRS_PROTO_IPV6:
457- protocol = PROTO_IPV6;
458- break;
459- case OFONO_GPRS_PROTO_IPV4V6:
460- protocol = PROTO_IPV4V6;
461- break;
462- case OFONO_GPRS_PROTO_IP:
463- break;
464- default:
465- DBG("Invalid protocol: %d", ctx->proto);
466- }
467-
468- parcel_w_string(&rilp, protocol);
469-
470 ret = g_ril_send(gcd->ril,
471- request,
472+ reqid,
473 rilp.data,
474 rilp.size,
475 ril_setup_data_call_cb, cbd, g_free);
476
477- g_ril_append_print_buf(gcd->ril,
478- "(%s,%s,%s,%s,%s,%s,%s)",
479- tech,
480- DATA_PROFILE_DEFAULT,
481- ctx->apn,
482- ctx->username,
483- ctx->password,
484- CHAP_PAP_OK,
485- protocol);
486- g_ril_print_request(gcd->ril, ret, request);
487+ /* NOTE - we could make the following function part of g_ril_send? */
488+ g_ril_print_request(gcd->ril, ret, reqid);
489
490 parcel_free(&rilp);
491+
492+error:
493+ g_free(request.apn);
494+ g_free(request.username);
495+ g_free(request.password);
496+
497 if (ret <= 0) {
498 ofono_error("Send RIL_REQUEST_SETUP_DATA_CALL failed.");
499
500+ set_context_disconnected(gcd);
501+
502 g_free(cbd);
503 CALLBACK_WITH_FAILURE(cb, data);
504 }
505@@ -383,7 +289,6 @@
506 ofono_gprs_context_cb_t cb = cbd->cb;
507 struct ofono_gprs_context *gc = cbd->user;
508 struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
509- struct ofono_error error;
510
511 DBG("");
512
513@@ -392,16 +297,24 @@
514
515 g_ril_print_response_no_args(gcd->ril, message);
516
517- gcd->state = STATE_IDLE;
518- CALLBACK_WITH_SUCCESS(cb, cbd->data);
519+ set_context_disconnected(gcd);
520+
521+ /* If the deactivate was a result of a shutdown,
522+ * there won't be call back, so _deactivated()
523+ * needs to be called directly.
524+ */
525+ if (cb)
526+ CALLBACK_WITH_SUCCESS(cb, cbd->data);
527+ else
528+ ofono_gprs_context_deactivated(gc, gcd->active_ctx_cid);
529
530 } else {
531- DBG("Reply failure: %s", ril_error_to_string(message->error));
532-
533- decode_ril_error(&error, "FAIL");
534- error.error = message->error;
535-
536- cb(&error, cbd->data);
537+ ofono_error("%s: replay failure: %s",
538+ __func__,
539+ ril_error_to_string(message->error));
540+
541+ if (cb)
542+ CALLBACK_WITH_FAILURE(cb, cbd->data);
543 }
544 }
545
546@@ -410,51 +323,67 @@
547 ofono_gprs_context_cb_t cb, void *data)
548 {
549 struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
550- struct cb_data *cbd = cb_data_new(cb, data);
551+ struct cb_data *cbd = NULL;
552 struct parcel rilp;
553- gchar *cid = NULL;
554- int request = RIL_REQUEST_DEACTIVATE_DATA_CALL;
555- int ret;
556-
557+ struct req_deactivate_data_call request;
558+ struct ofono_error error;
559+ int reqid = RIL_REQUEST_DEACTIVATE_DATA_CALL;
560+ int ret = 0;
561+
562+ DBG("");
563+
564+ if (gcd->active_rild_cid == -1) {
565+ set_context_disconnected(gcd);
566+
567+ if (cb) {
568+ CALLBACK_WITH_SUCCESS(cb, data);
569+ g_free(cbd);
570+ }
571+
572+ return;
573+ }
574+
575+
576+ cbd = cb_data_new(cb, data);
577 cbd->user = gc;
578
579 gcd->state = STATE_DISABLING;
580
581- parcel_init(&rilp);
582- parcel_w_int32(&rilp, DEACTIVATE_DATA_CALL_NUM_PARAMS);
583-
584- cid = g_strdup_printf("%d", gcd->active_rild_cid);
585- parcel_w_string(&rilp, cid);
586-
587- /*
588- * TODO: airplane-mode; change reason to '1',
589- * which means "radio power off".
590- */
591- parcel_w_string(&rilp, DEACTIVATE_DATA_CALL_NO_REASON);
592+ request.cid = gcd->active_rild_cid;
593+ request.reason = RIL_DEACTIVATE_DATA_CALL_NO_REASON;
594+
595+ if (g_ril_request_deactivate_data_call(gcd->ril, &request,
596+ &rilp, &error) == FALSE) {
597+ ofono_error("Couldn't build DEACTIVATE_DATA_CALL request.");
598+ goto error;
599+ }
600
601 ret = g_ril_send(gcd->ril,
602- request,
603+ reqid,
604 rilp.data,
605 rilp.size,
606 ril_deactivate_data_call_cb, cbd, g_free);
607
608- g_ril_append_print_buf(gcd->ril, "(%s,0)", cid);
609- g_ril_print_request(gcd->ril, ret, request);
610+ g_ril_append_print_buf(gcd->ril, "(%d,0)", request.cid);
611+ g_ril_print_request(gcd->ril, ret, reqid);
612
613 parcel_free(&rilp);
614- g_free(cid);
615
616+error:
617 if (ret <= 0) {
618 ofono_error("Send RIL_REQUEST_DEACTIVATE_DATA_CALL failed.");
619 g_free(cbd);
620- CALLBACK_WITH_FAILURE(cb, data);
621+ if (cb)
622+ CALLBACK_WITH_FAILURE(cb, data);
623 }
624 }
625
626 static void ril_gprs_context_detach_shutdown(struct ofono_gprs_context *gc,
627- unsigned int id)
628+ unsigned int id)
629 {
630- DBG("");
631+ DBG("cid: %d", id);
632+
633+ ril_gprs_context_deactivate_primary(gc, 0, NULL, NULL);
634 }
635
636 static int ril_gprs_context_probe(struct ofono_gprs_context *gc,
637@@ -468,9 +397,7 @@
638 return -ENOMEM;
639
640 gcd->ril = g_ril_clone(ril);
641- gcd->active_ctx_cid = -1;
642- gcd->active_rild_cid = -1;
643- gcd->state = STATE_IDLE;
644+ set_context_disconnected(gcd);
645
646 ofono_gprs_context_set_data(gc, gcd);
647
648@@ -486,7 +413,7 @@
649 DBG("");
650
651 if (gcd->state != STATE_IDLE) {
652- /* TODO: call detach_shutdown */
653+ ril_gprs_context_detach_shutdown(gc, 0);
654 }
655
656 ofono_gprs_context_set_data(gc, NULL);
657
658=== modified file 'drivers/rilmodem/rilutil.c'
659--- drivers/rilmodem/rilutil.c 2013-07-08 18:02:27 +0000
660+++ drivers/rilmodem/rilutil.c 2013-07-28 19:18:23 +0000
661@@ -97,20 +97,6 @@
662 return 0;
663 }
664
665-gint ril_util_data_call_compare(gconstpointer a, gconstpointer b)
666-{
667- const struct data_call *ca = a;
668- const struct data_call *cb = b;
669-
670- if (ca->cid < cb->cid)
671- return -1;
672-
673- if (ca->cid > cb->cid)
674- return 1;
675-
676- return 0;
677-}
678-
679 gint ril_util_call_compare(gconstpointer a, gconstpointer b)
680 {
681 const struct ofono_call *ca = a;
682@@ -171,6 +157,8 @@
683 return result;
684 }
685
686+/* TODO: this function can go away, once all the code has been
687+ * re-factored to use grilreply.c */
688 void ril_util_init_parcel(struct ril_msg *message, struct parcel *rilp)
689 {
690 /* Set up Parcel struct for proper parsing */
691@@ -283,73 +271,6 @@
692 return l;
693 }
694
695-GSList *ril_util_parse_data_call_list(GRil *gril, struct ril_msg *message)
696-{
697- struct data_call *call;
698- struct parcel rilp;
699- GSList *l = NULL;
700- int num, i, version;
701- gchar *number, *name;
702-
703- ril_util_init_parcel(message, &rilp);
704-
705- /*
706- * ril.h documents the reply to a RIL_REQUEST_DATA_CALL_LIST
707- * as being an array of RIL_Data_Call_Response_v6 structs,
708- * however in reality, the response also includes a version
709- * to start.
710- */
711- version = parcel_r_int32(&rilp);
712-
713- /* Number of calls */
714- num = parcel_r_int32(&rilp);
715-
716- g_ril_append_print_buf(gril,
717- "(version=%d,num=%d",
718- version,
719- num);
720-
721- for (i = 0; i < num; i++) {
722- call = g_try_new(struct data_call, 1);
723- if (call == NULL)
724- break;
725-
726- call->status = parcel_r_int32(&rilp);
727- call->retry = parcel_r_int32(&rilp);
728- call->cid = parcel_r_int32(&rilp);
729- call->active = parcel_r_int32(&rilp);
730-
731- call->type = parcel_r_string(&rilp);
732- call->ifname = parcel_r_string(&rilp);
733- call->addresses = parcel_r_string(&rilp);
734- call->dnses = parcel_r_string(&rilp);
735- call->gateways = parcel_r_string(&rilp);
736-
737- /* TODO: figure out how to line-wrap properly
738- * without introducing spaces in string.
739- */
740- g_ril_append_print_buf(gril,
741- "%s [status=%d,retry=%d,cid=%d,active=%d,type=%s,ifname=%s,address=%s,dns=%s,gateways=%s]",
742- print_buf,
743- call->status,
744- call->retry,
745- call->cid,
746- call->active,
747- call->type,
748- call->ifname,
749- call->addresses,
750- call->dnses,
751- call->gateways);
752-
753- l = g_slist_insert_sorted(l, call, ril_util_data_call_compare);
754- }
755-
756- g_ril_append_print_buf(gril, "%s}", print_buf);
757- g_ril_print_response(gril, message);
758-
759- return l;
760-}
761-
762 char *ril_util_parse_sim_io_rsp(GRil *gril,
763 struct ril_msg *message,
764 int *sw1, int *sw2,
765
766=== modified file 'drivers/rilmodem/rilutil.h'
767--- drivers/rilmodem/rilutil.h 2013-07-08 17:17:54 +0000
768+++ drivers/rilmodem/rilutil.h 2013-07-28 19:18:23 +0000
769@@ -72,18 +72,6 @@
770 APPSTATE_READY,
771 };
772
773-struct data_call {
774- int status;
775- int retry;
776- int cid;
777- int active;
778- char *type;
779- char *ifname;
780- char *addresses;
781- char *dnses;
782- char *gateways;
783-};
784-
785 #define MAX_UICC_APPS 16
786
787 struct sim_status {
788@@ -124,7 +112,6 @@
789 void ril_util_sim_state_query_free(struct ril_util_sim_state_query *req);
790
791 GSList *ril_util_parse_clcc(GRil *gril, struct ril_msg *message);
792-GSList *ril_util_parse_data_call_list(GRil *gril, struct ril_msg *message);
793 char *ril_util_parse_sim_io_rsp(GRil *gril, struct ril_msg *message,
794 int *sw1, int *sw2,
795 int *hex_len);
796
797=== modified file 'gril/gril.c'
798--- gril/gril.c 2013-06-25 16:15:35 +0000
799+++ gril/gril.c 2013-07-28 19:18:23 +0000
800@@ -40,6 +40,7 @@
801 #include "log.h"
802 #include "ringbuffer.h"
803 #include "gril.h"
804+#include "grilutil.h"
805
806 #define RIL_TRACE(ril, fmt, arg...) do { \
807 if (ril->trace == TRUE) \
808@@ -119,6 +120,9 @@
809 guint32 error_code; /* LE: */
810 };
811
812+#define RIL_PRINT_BUF_SIZE 8096
813+char print_buf[RIL_PRINT_BUF_SIZE] __attribute__((used));
814+
815 static void ril_wakeup_writer(struct ril_s *ril);
816
817 static void ril_notify_node_destroy(gpointer data, gpointer user_data)
818@@ -240,7 +244,7 @@
819
820
821 DBG("req: %s, id: %d, data_len: %d",
822- ril_request_id_to_string(req), id, data_len);
823+ ril_request_id_to_string(req), id, (int) data_len);
824
825 /* RIL request: 8 byte header + data */
826 len = 8 + data_len;
827@@ -634,7 +638,9 @@
828
829 len = req->data_len;
830
831- DBG("len: %d, req_bytes_written: %d", len, ril->req_bytes_written);
832+ DBG("len: %d, req_bytes_written: %d",
833+ (int) len,
834+ ril->req_bytes_written);
835
836 /* For some reason write watcher fired, but we've already
837 * written the entire command out to the io channel,
838@@ -810,8 +816,6 @@
839 return NULL;
840 }
841
842- g_io_channel_set_buffered(io, FALSE);
843- g_io_channel_set_encoding(io, NULL, NULL);
844 g_io_channel_set_close_on_unref(io, TRUE);
845 g_io_channel_set_flags(io, G_IO_FLAG_NONBLOCK, NULL);
846
847@@ -956,6 +960,15 @@
848 return FALSE;
849 }
850
851+void g_ril_init_parcel(struct ril_msg *message, struct parcel *rilp)
852+{
853+ /* Set up Parcel struct for proper parsing */
854+ rilp->data = message->buf;
855+ rilp->size = message->buf_len;
856+ rilp->capacity = message->buf_len;
857+ rilp->offset = 0;
858+}
859+
860 GRil *g_ril_new()
861 {
862 GRil *ril;
863@@ -1022,7 +1035,7 @@
864 return ril;
865 }
866
867-guint g_ril_send(GRil *ril, const guint req, const char *data,
868+guint g_ril_send(GRil *ril, const guint reqid, const char *data,
869 const gsize data_len, GRilResponseFunc func,
870 gpointer user_data, GDestroyNotify notify)
871 {
872@@ -1034,7 +1047,7 @@
873
874 p = ril->parent;
875
876- r = ril_request_create(p, ril->group, req, p->next_cmd_id,
877+ r = ril_request_create(p, ril->group, reqid, p->next_cmd_id,
878 data, data_len, func,
879 user_data, notify, FALSE);
880 if (r == NULL)
881
882=== modified file 'gril/gril.h'
883--- gril/gril.h 2013-06-14 16:11:01 +0000
884+++ gril/gril.h 2013-07-28 19:18:23 +0000
885@@ -27,9 +27,9 @@
886 extern "C" {
887 #endif
888
889-#include "grilresponse.h"
890+#include "grilio.h"
891 #include "grilutil.h"
892-#include "grilio.h"
893+#include "parcel.h"
894 #include "ril_constants.h"
895
896 struct _GRil;
897@@ -63,12 +63,11 @@
898 * name it is called in.
899 */
900 #define G_RIL_TRACE(gril, fmt, arg...) do { \
901- if (g_ril_get_trace(gril)) \
902+ if (gril && g_ril_get_trace(gril)) \
903 ofono_debug(fmt, ## arg); \
904 } while (0)
905
906-#define RIL_PRINT_BUF_SIZE 8096
907-static char print_buf[RIL_PRINT_BUF_SIZE] __attribute__((used));
908+extern char print_buf[];
909
910 #define g_ril_print_request(gril, token, req) \
911 G_RIL_TRACE(gril, "[%04d]> %s %s", token, ril_request_id_to_string(req), print_buf)
912@@ -82,7 +81,7 @@
913 ril_request_id_to_string(message->req))
914
915 #define g_ril_append_print_buf(gril, x...) do { \
916- if (g_ril_get_trace(gril)) \
917+ if (gril && g_ril_get_trace(gril)) \
918 sprintf(print_buf, x); \
919 } while (0)
920
921@@ -92,6 +91,8 @@
922 #define g_ril_print_unsol_no_args(gril, message) \
923 G_RIL_TRACE(gril, "[UNSOL]< %s", ril_unsol_request_to_string(message->req))
924
925+void g_ril_init_parcel(struct ril_msg *message, struct parcel *rilp);
926+
927 GRil *g_ril_new();
928
929 GIOChannel *g_ril_get_channel(GRil *ril);
930@@ -127,8 +128,9 @@
931 * g_ril_cancel. If an error occurred, an id of 0 is returned.
932 *
933 */
934-guint g_ril_send(GRil *ril, const guint req, const char *data, const gsize data_len,
935- GRilResponseFunc func, gpointer user_data, GDestroyNotify notify);
936+guint g_ril_send(GRil *ril, const guint reqid, const char *data,
937+ const gsize data_len, GRilResponseFunc func,
938+ gpointer user_data, GDestroyNotify notify);
939
940 guint g_ril_register(GRil *ril, const int req,
941 GRilNotifyFunc func, gpointer user_data);
942
943=== added file 'gril/grilreply.c'
944--- gril/grilreply.c 1970-01-01 00:00:00 +0000
945+++ gril/grilreply.c 2013-07-28 19:18:23 +0000
946@@ -0,0 +1,225 @@
947+/*
948+ *
949+ * RIL library with GLib integration
950+ *
951+ * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
952+ * Copyright (C) 2012-2013 Canonical Ltd.
953+ *
954+ * This program is free software; you can redistribute it and/or modify
955+ * it under the terms of the GNU General Public License version 2 as
956+ * published by the Free Software Foundation.
957+ *
958+ * This program is distributed in the hope that it will be useful,
959+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
960+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
961+ * GNU General Public License for more details.
962+ *
963+ * You should have received a copy of the GNU General Public License
964+ * along with this program; if not, write to the Free Software
965+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
966+ *
967+ */
968+
969+#ifdef HAVE_CONFIG_H
970+#include <config.h>
971+#endif
972+
973+#include <stdio.h>
974+#include <ctype.h>
975+#include <errno.h>
976+#include <string.h>
977+
978+#include <glib.h>
979+
980+#include <ofono/log.h>
981+#include <ofono/modem.h>
982+#include <ofono/gprs-context.h>
983+
984+#include "grilreply.h"
985+#include "grilutil.h"
986+
987+/* SETUP_DATA_CALL_PARAMS reply params */
988+#define MIN_DATA_CALL_REPLY_SIZE 36
989+
990+/* TODO: move this to grilutil.c */
991+void g_ril_reply_free_setup_data_call(struct reply_setup_data_call *reply)
992+{
993+ if (reply) {
994+ g_free(reply->ifname);
995+ g_strfreev(reply->dns_addresses);
996+ g_strfreev(reply->gateways);
997+ g_strfreev(reply->ip_addrs);
998+ g_free(reply);
999+ }
1000+}
1001+
1002+struct reply_setup_data_call *g_ril_reply_parse_data_call(GRil *gril,
1003+ struct ril_msg *message,
1004+ struct ofono_error *error)
1005+{
1006+ struct parcel rilp;
1007+ int num = 0;
1008+ int protocol;
1009+ char *type = NULL, *raw_ip_addrs = NULL;
1010+ char *dnses = NULL, *raw_gws = NULL;
1011+
1012+ struct reply_setup_data_call *reply =
1013+ g_new0(struct reply_setup_data_call, 1);
1014+
1015+ OFONO_NO_ERROR(error);
1016+
1017+ reply->cid = -1;
1018+
1019+ /* TODO:
1020+ * Cleanup duplicate code between this function and
1021+ * ril_util_parse_data_call_list().
1022+ */
1023+
1024+ /* valid size: 36 (34 if HCRADIO defined) */
1025+ if (message->buf_len < MIN_DATA_CALL_REPLY_SIZE) {
1026+ /* TODO: make a macro for error logging */
1027+ ofono_error("%s: reply too small: %d",
1028+ __func__,
1029+ (int) message->buf_len);
1030+ OFONO_EINVAL(error);
1031+ goto error;
1032+ }
1033+
1034+ g_ril_init_parcel(message, &rilp);
1035+
1036+ /*
1037+ * ril.h documents the reply to a RIL_REQUEST_SETUP_DATA_CALL
1038+ * as being a RIL_Data_Call_Response_v6 struct, however in
1039+ * reality, the response actually includes the version of the
1040+ * struct, followed by an array of calls, so the array size
1041+ * also has to be read after the version.
1042+ *
1043+ * TODO: What if there's more than 1 call in the list??
1044+ */
1045+
1046+ /*
1047+ * TODO: consider using 'unused' variable; however if we
1048+ * do this, the alternative is a few more append_print_buf
1049+ * calls ( which become no-ops if tracing isn't enabled.
1050+ */
1051+ reply->version = parcel_r_int32(&rilp);
1052+ num = parcel_r_int32(&rilp);
1053+ if (num != 1) {
1054+ ofono_error("%s: too many calls: %d", __func__, num);
1055+ OFONO_EINVAL(error);
1056+ goto error;
1057+ }
1058+
1059+ reply->status = parcel_r_int32(&rilp);
1060+ reply->retry_time = parcel_r_int32(&rilp);
1061+ reply->cid = parcel_r_int32(&rilp);
1062+ reply->active = parcel_r_int32(&rilp);
1063+ type = parcel_r_string(&rilp);
1064+ reply->ifname = parcel_r_string(&rilp);
1065+ raw_ip_addrs = parcel_r_string(&rilp);
1066+ dnses = parcel_r_string(&rilp);
1067+ raw_gws = parcel_r_string(&rilp);
1068+
1069+ g_ril_append_print_buf(gril,
1070+ "{version=%d,num=%d [status=%d,retry=%d,"
1071+ "cid=%d,active=%d,type=%s,ifname=%s,address=%s"
1072+ ",dns=%s,gateways=%s]}",
1073+ reply->version,
1074+ num,
1075+ reply->status,
1076+ reply->retry_time,
1077+ reply->cid,
1078+ reply->active,
1079+ type,
1080+ reply->ifname,
1081+ raw_ip_addrs,
1082+ dnses,
1083+ raw_gws);
1084+
1085+ g_ril_print_response(gril, message);
1086+
1087+ protocol = ril_protocol_string_to_ofono_protocol(type);
1088+ if (protocol < 0) {
1089+ ofono_error("%s: Invalid type(protocol) specified: %s",
1090+ __func__,
1091+ type);
1092+ OFONO_EINVAL(error);
1093+ goto error;
1094+ }
1095+
1096+ reply->protocol = (guint) protocol;
1097+
1098+ if (reply->ifname == NULL || strlen(reply->ifname) == 0) {
1099+ ofono_error("%s: No interface specified: %s",
1100+ __func__,
1101+ reply->ifname);
1102+
1103+ OFONO_EINVAL(error);
1104+ goto error;
1105+
1106+ }
1107+
1108+ /* TODO:
1109+ * RILD can return multiple addresses; oFono only supports
1110+ * setting a single IPv4 address. At this time, we only
1111+ * use the first address. It's possible that a RIL may
1112+ * just specify the end-points of the point-to-point
1113+ * connection, in which case this code will need to
1114+ * changed to handle such a device.
1115+ *
1116+ * For now split into a maximum of three, and only use
1117+ * the first address for the remaining operations.
1118+ */
1119+ if (raw_ip_addrs)
1120+ reply->ip_addrs = g_strsplit(raw_ip_addrs, " ", 3);
1121+ else
1122+ reply->ip_addrs = NULL;
1123+
1124+ /* TODO: I'm not sure it's possible to specify a zero-length
1125+ * in a parcel in a parcel. If *not*, then this can be
1126+ * simplified.
1127+ */
1128+ if (reply->ip_addrs == NULL || (sizeof(reply->ip_addrs) == 0)) {
1129+ ofono_error("%s no IP address: %s", __func__, raw_ip_addrs);
1130+
1131+ OFONO_EINVAL(error);
1132+ goto error;
1133+ }
1134+
1135+ /*
1136+ * RILD can return multiple addresses; oFono only supports
1137+ * setting a single IPv4 gateway.
1138+ */
1139+ if (raw_gws)
1140+ reply->gateways = g_strsplit(raw_gws, " ", 3);
1141+ else
1142+ reply->gateways = NULL;
1143+
1144+ if (reply->gateways == NULL || (sizeof(reply->gateways) == 0)) {
1145+ ofono_error("%s: no gateways: %s", __func__, raw_gws);
1146+ OFONO_EINVAL(error);
1147+ goto error;
1148+ }
1149+
1150+ /* Split DNS addresses */
1151+ if (dnses)
1152+ reply->dns_addresses = g_strsplit(dnses, " ", 3);
1153+ else
1154+ reply->dns_addresses = NULL;
1155+
1156+ if (reply->dns_addresses == NULL ||
1157+ (sizeof(reply->dns_addresses) == 0)) {
1158+ ofono_error("%s: no DNS: %s", __func__, dnses);
1159+
1160+ OFONO_EINVAL(error);
1161+ goto error;
1162+ }
1163+
1164+error:
1165+ g_free(type);
1166+ g_free(raw_ip_addrs);
1167+ g_free(dnses);
1168+ g_free(raw_gws);
1169+
1170+ return reply;
1171+}
1172
1173=== added file 'gril/grilreply.h'
1174--- gril/grilreply.h 1970-01-01 00:00:00 +0000
1175+++ gril/grilreply.h 2013-07-28 19:18:23 +0000
1176@@ -0,0 +1,57 @@
1177+/*
1178+ *
1179+ * RIL library with GLib integration
1180+ *
1181+ * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
1182+ * Copyright (C) 2012-2013 Canonical Ltd.
1183+ *
1184+ * This program is free software; you can redistribute it and/or modify
1185+ * it under the terms of the GNU General Public License version 2 as
1186+ * published by the Free Software Foundation.
1187+ *
1188+ * This program is distributed in the hope that it will be useful,
1189+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1190+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1191+ * GNU General Public License for more details.
1192+ *
1193+ * You should have received a copy of the GNU General Public License
1194+ * along with this program; if not, write to the Free Software
1195+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1196+ *
1197+ */
1198+
1199+#ifndef __GRILREPLY_H
1200+#define __GRILREPLY_H
1201+
1202+#include <ofono/types.h>
1203+
1204+#include "gril.h"
1205+
1206+#ifdef __cplusplus
1207+extern "C" {
1208+#endif
1209+
1210+struct reply_setup_data_call {
1211+ guint version;
1212+ guint status;
1213+ gint cid;
1214+ guint retry_time;
1215+ guint active;
1216+ guint protocol;
1217+ gchar *ifname;
1218+ gchar **dns_addresses;
1219+ gchar **gateways;
1220+ gchar **ip_addrs;
1221+};
1222+
1223+void g_ril_reply_free_setup_data_call(struct reply_setup_data_call *reply);
1224+
1225+struct reply_setup_data_call *g_ril_reply_parse_data_call(GRil *gril,
1226+ struct ril_msg *message,
1227+ struct ofono_error *error);
1228+
1229+#ifdef __cplusplus
1230+}
1231+#endif
1232+
1233+#endif /* __GRILREPLY_H */
1234
1235=== added file 'gril/grilrequest.c'
1236--- gril/grilrequest.c 1970-01-01 00:00:00 +0000
1237+++ gril/grilrequest.c 2013-07-28 19:18:23 +0000
1238@@ -0,0 +1,213 @@
1239+/*
1240+ *
1241+ * RIL library with GLib integration
1242+ *
1243+ * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
1244+ * Copyright (C) 2012-2013 Canonical Ltd.
1245+ *
1246+ * This program is free software; you can redistribute it and/or modify
1247+ * it under the terms of the GNU General Public License version 2 as
1248+ * published by the Free Software Foundation.
1249+ *
1250+ * This program is distributed in the hope that it will be useful,
1251+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1252+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1253+ * GNU General Public License for more details.
1254+ *
1255+ * You should have received a copy of the GNU General Public License
1256+ * along with this program; if not, write to the Free Software
1257+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1258+ *
1259+ */
1260+
1261+#ifdef HAVE_CONFIG_H
1262+#include <config.h>
1263+#endif
1264+
1265+#include <stdio.h>
1266+#include <ctype.h>
1267+#include <errno.h>
1268+#include <string.h>
1269+
1270+#include <glib.h>
1271+
1272+#include <ofono/log.h>
1273+#include <ofono/modem.h>
1274+#include <ofono/gprs-context.h>
1275+
1276+#include "grilrequest.h"
1277+
1278+/* DEACTIVATE_DATA_CALL request parameters */
1279+#define DEACTIVATE_DATA_CALL_NUM_PARAMS 2
1280+
1281+/* SETUP_DATA_CALL_PARAMS request parameters */
1282+#define SETUP_DATA_CALL_PARAMS 7
1283+#define DATA_PROFILE_DEFAULT_STR "0"
1284+#define DATA_PROFILE_TETHERED_STR "1"
1285+#define DATA_PROFILE_IMS_STR "2"
1286+#define DATA_PROFILE_FOTA_STR "3"
1287+#define DATA_PROFILE_CBS_STR "4"
1288+#define DATA_PROFILE_OEM_BASE_STR "1000"
1289+
1290+/* SETUP_DATA_CALL_PARAMS reply parameters */
1291+#define MIN_DATA_CALL_REPLY_SIZE 36
1292+
1293+/*
1294+ * TODO:
1295+ *
1296+ * A potential future change here is to create a driver
1297+ * abstraction for each request/reply/event method, and a
1298+ * corresponding method to allow new per-message implementations
1299+ * to be registered. This would allow PES to easily add code
1300+ * to quirk a particular RIL implementation.
1301+ *
1302+ * struct g_ril_messages_driver {
1303+ * const char *name;
1304+ * };
1305+ *
1306+ */
1307+
1308+gboolean g_ril_request_deactivate_data_call(GRil *gril,
1309+ const struct req_deactivate_data_call *req,
1310+ struct parcel *rilp,
1311+ struct ofono_error *error)
1312+{
1313+ gchar *cid_str = NULL;
1314+ gchar *reason_str = NULL;
1315+
1316+ if (req->reason != RIL_DEACTIVATE_DATA_CALL_NO_REASON &&
1317+ req->reason != RIL_DEACTIVATE_DATA_CALL_RADIO_SHUTDOWN) {
1318+ goto error;
1319+ }
1320+
1321+ parcel_init(rilp);
1322+ parcel_w_int32(rilp, DEACTIVATE_DATA_CALL_NUM_PARAMS);
1323+
1324+ cid_str = g_strdup_printf("%d", req->cid);
1325+ parcel_w_string(rilp, cid_str);
1326+
1327+ /*
1328+ * TODO: airplane-mode; change reason to '1',
1329+ * which means "radio power off".
1330+ */
1331+ reason_str = g_strdup_printf("%d", req->reason);
1332+ parcel_w_string(rilp, reason_str);
1333+
1334+ g_free(cid_str);
1335+ g_free(reason_str);
1336+
1337+ OFONO_NO_ERROR(error);
1338+ return TRUE;
1339+
1340+error:
1341+ OFONO_EINVAL(error);
1342+ return FALSE;
1343+}
1344+
1345+gboolean g_ril_request_setup_data_call(GRil *gril,
1346+ const struct req_setup_data_call *req,
1347+ struct parcel *rilp,
1348+ struct ofono_error *error)
1349+{
1350+ const gchar *protocol_str;
1351+ gchar *tech_str;
1352+ gchar *auth_str;
1353+ gchar *profile_str;
1354+ size_t apn_len;
1355+
1356+ DBG("");
1357+
1358+ if (req->tech < RADIO_TECH_GPRS || req->tech > RADIO_TECH_GSM) {
1359+ ofono_error("%s: Invalid tech value: %d", __func__, req->tech);
1360+ goto error;
1361+ }
1362+
1363+ /*
1364+ * TODO(OEM): This code doesn't currently support
1365+ * OEM data profiles. If a use case exist, then
1366+ * this code will need to be modified.
1367+ */
1368+ switch (req->data_profile) {
1369+ case RIL_DATA_PROFILE_DEFAULT:
1370+ profile_str = DATA_PROFILE_DEFAULT_STR;
1371+ break;
1372+ case RIL_DATA_PROFILE_TETHERED:
1373+ profile_str = DATA_PROFILE_TETHERED_STR;
1374+ break;
1375+ case RIL_DATA_PROFILE_IMS:
1376+ profile_str = DATA_PROFILE_IMS_STR;
1377+ break;
1378+ case RIL_DATA_PROFILE_FOTA:
1379+ profile_str = DATA_PROFILE_FOTA_STR;
1380+ break;
1381+ case RIL_DATA_PROFILE_CBS:
1382+ profile_str = DATA_PROFILE_CBS_STR;
1383+ break;
1384+ default:
1385+ ofono_error("%s, invalid data_profile value: %d",
1386+ __func__,
1387+ req->data_profile);
1388+ goto error;
1389+ }
1390+
1391+ if (req->apn == NULL)
1392+ goto error;
1393+
1394+ apn_len = strlen(req->apn);
1395+ if (apn_len == 0 || apn_len > 100) {
1396+ ofono_error("%s: invalid apn length: %d",
1397+ __func__,
1398+ (int) apn_len);
1399+ goto error;
1400+ }
1401+
1402+ if (req->auth_type > RIL_AUTH_BOTH) {
1403+ ofono_error("%s: Invalid auth type: %d",
1404+ __func__,
1405+ req->auth_type);
1406+ goto error;
1407+ }
1408+
1409+ protocol_str = ril_ofono_protocol_to_ril_string(req->protocol);
1410+ if (protocol_str == NULL) {
1411+ ofono_error("%s: Invalid protocol: %d",
1412+ __func__,
1413+ req->protocol);
1414+ goto error;
1415+ }
1416+
1417+ parcel_init(rilp);
1418+
1419+ parcel_w_int32(rilp, SETUP_DATA_CALL_PARAMS);
1420+
1421+ tech_str = g_strdup_printf("%d", req->tech);
1422+ parcel_w_string(rilp, (char *) tech_str);
1423+ parcel_w_string(rilp, (char *) profile_str);
1424+ parcel_w_string(rilp, (char *) req->apn);
1425+ parcel_w_string(rilp, (char *) req->username);
1426+ parcel_w_string(rilp, (char *) req->password);
1427+
1428+ auth_str = g_strdup_printf("%d", req->auth_type);
1429+ parcel_w_string(rilp, (char *) auth_str);
1430+ parcel_w_string(rilp, (char *) protocol_str);
1431+
1432+ g_ril_append_print_buf(gril,
1433+ "(%s,%s,%s,%s,%s,%s,%s)",
1434+ tech_str,
1435+ profile_str,
1436+ req->apn,
1437+ req->username,
1438+ req->password,
1439+ auth_str,
1440+ protocol_str);
1441+
1442+ g_free(tech_str);
1443+ g_free(auth_str);
1444+
1445+ OFONO_NO_ERROR(error);
1446+ return TRUE;
1447+
1448+error:
1449+ OFONO_EINVAL(error);
1450+ return FALSE;
1451+}
1452
1453=== added file 'gril/grilrequest.h'
1454--- gril/grilrequest.h 1970-01-01 00:00:00 +0000
1455+++ gril/grilrequest.h 2013-07-28 19:18:23 +0000
1456@@ -0,0 +1,63 @@
1457+/*
1458+ *
1459+ * RIL library with GLib integration
1460+ *
1461+ * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
1462+ * Copyright (C) 2012-2013 Canonical Ltd.
1463+ *
1464+ * This program is free software; you can redistribute it and/or modify
1465+ * it under the terms of the GNU General Public License version 2 as
1466+ * published by the Free Software Foundation.
1467+ *
1468+ * This program is distributed in the hope that it will be useful,
1469+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1470+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1471+ * GNU General Public License for more details.
1472+ *
1473+ * You should have received a copy of the GNU General Public License
1474+ * along with this program; if not, write to the Free Software
1475+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1476+ *
1477+ */
1478+
1479+#ifndef __GRILREQUEST_H
1480+#define __GRILREQUEST_H
1481+
1482+#include <ofono/types.h>
1483+
1484+#include "gril.h"
1485+
1486+#ifdef __cplusplus
1487+extern "C" {
1488+#endif
1489+
1490+struct req_deactivate_data_call {
1491+ guint cid;
1492+ guint reason;
1493+};
1494+
1495+struct req_setup_data_call {
1496+ guint tech;
1497+ guint data_profile;
1498+ gchar *apn;
1499+ gchar *username;
1500+ gchar *password;
1501+ guint auth_type;
1502+ guint protocol;
1503+};
1504+
1505+gboolean g_ril_request_deactivate_data_call(GRil *gril,
1506+ const struct req_deactivate_data_call *req,
1507+ struct parcel *rilp,
1508+ struct ofono_error *error);
1509+
1510+gboolean g_ril_request_setup_data_call(GRil *gril,
1511+ const struct req_setup_data_call *req,
1512+ struct parcel *rilp,
1513+ struct ofono_error *error);
1514+
1515+#ifdef __cplusplus
1516+}
1517+#endif
1518+
1519+#endif /* __GRILREQUEST_H */
1520
1521=== added file 'gril/grilunsol.c'
1522--- gril/grilunsol.c 1970-01-01 00:00:00 +0000
1523+++ gril/grilunsol.c 2013-07-28 19:18:23 +0000
1524@@ -0,0 +1,158 @@
1525+/*
1526+ *
1527+ * RIL library with GLib integration
1528+ *
1529+ * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
1530+ * Copyright (C) 2012-2013 Canonical Ltd.
1531+ *
1532+ * This program is free software; you can redistribute it and/or modify
1533+ * it under the terms of the GNU General Public License version 2 as
1534+ * published by the Free Software Foundation.
1535+ *
1536+ * This program is distributed in the hope that it will be useful,
1537+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1538+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1539+ * GNU General Public License for more details.
1540+ *
1541+ * You should have received a copy of the GNU General Public License
1542+ * along with this program; if not, write to the Free Software
1543+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1544+ *
1545+ */
1546+
1547+#ifdef HAVE_CONFIG_H
1548+#include <config.h>
1549+#endif
1550+
1551+#include <stdio.h>
1552+#include <ctype.h>
1553+#include <errno.h>
1554+#include <string.h>
1555+
1556+#include <glib.h>
1557+
1558+#include <ofono/log.h>
1559+#include <ofono/modem.h>
1560+#include <ofono/gprs-context.h>
1561+
1562+#include "grilunsol.h"
1563+
1564+/* Minimum size is two int32s version/number of calls */
1565+#define MIN_DATA_CALL_LIST_SIZE 8
1566+
1567+static gint data_call_compare(gconstpointer a, gconstpointer b)
1568+{
1569+ const struct data_call *ca = a;
1570+ const struct data_call *cb = b;
1571+
1572+ if (ca->cid < cb->cid)
1573+ return -1;
1574+
1575+ if (ca->cid > cb->cid)
1576+ return 1;
1577+
1578+ return 0;
1579+}
1580+
1581+static void free_data_call(gpointer data, gpointer user_data)
1582+{
1583+ struct data_call *call = data;
1584+
1585+ if (call) {
1586+ g_free(call->type);
1587+ g_free(call->ifname);
1588+ g_free(call->addresses);
1589+ g_free(call->dnses);
1590+ g_free(call->gateways);
1591+ g_free(call);
1592+ }
1593+}
1594+
1595+void g_ril_unsol_free_data_call_list(struct unsol_data_call_list *unsol)
1596+{
1597+ if (unsol) {
1598+ g_slist_foreach(unsol->call_list, (GFunc) free_data_call, NULL);
1599+ g_slist_free(unsol->call_list);
1600+ g_free(unsol);
1601+ }
1602+}
1603+
1604+struct unsol_data_call_list *g_ril_unsol_parse_data_call_list(GRil *gril,
1605+ struct ril_msg *message,
1606+ struct ofono_error *error)
1607+{
1608+ struct data_call *call;
1609+ struct parcel rilp;
1610+ struct unsol_data_call_list *reply =
1611+ g_new0(struct unsol_data_call_list, 1);
1612+ int i;
1613+
1614+ DBG("");
1615+
1616+ OFONO_NO_ERROR(error);
1617+
1618+ if (message->buf_len < MIN_DATA_CALL_LIST_SIZE) {
1619+ ofono_error("%s: message too small: %d",
1620+ __func__,
1621+ (int) message->buf_len);
1622+ OFONO_EINVAL(error);
1623+ goto error;
1624+ }
1625+
1626+ g_ril_init_parcel(message, &rilp);
1627+
1628+ /*
1629+ * ril.h documents the reply to a RIL_REQUEST_DATA_CALL_LIST
1630+ * as being an array of RIL_Data_Call_Response_v6 structs,
1631+ * however in reality, the response also includes a version
1632+ * to start.
1633+ */
1634+ reply->version = parcel_r_int32(&rilp);
1635+ reply->num = parcel_r_int32(&rilp);
1636+
1637+ g_ril_append_print_buf(gril,
1638+ "(version=%d,num=%d",
1639+ reply->version,
1640+ reply->num);
1641+
1642+ for (i = 0; i < reply->num; i++) {
1643+ call = g_new0(struct data_call, 1);
1644+
1645+ call->status = parcel_r_int32(&rilp);
1646+ call->retry = parcel_r_int32(&rilp);
1647+ call->cid = parcel_r_int32(&rilp);
1648+ call->active = parcel_r_int32(&rilp);
1649+
1650+ call->type = parcel_r_string(&rilp);
1651+ call->ifname = parcel_r_string(&rilp);
1652+ call->addresses = parcel_r_string(&rilp);
1653+ call->dnses = parcel_r_string(&rilp);
1654+ call->gateways = parcel_r_string(&rilp);
1655+
1656+ g_ril_append_print_buf(gril,
1657+ "%s [status=%d,retry=%d,cid=%d,"
1658+ "active=%d,type=%s,ifname=%s,"
1659+ "address=%s,dns=%s,gateways=%s]",
1660+ print_buf,
1661+ call->status,
1662+ call->retry,
1663+ call->cid,
1664+ call->active,
1665+ call->type,
1666+ call->ifname,
1667+ call->addresses,
1668+ call->dnses,
1669+ call->gateways);
1670+
1671+ reply->call_list =
1672+ g_slist_insert_sorted(reply->call_list,
1673+ call,
1674+ data_call_compare);
1675+ }
1676+
1677+ g_ril_append_print_buf(gril, "%s}", print_buf);
1678+ g_ril_print_unsol(gril, message);
1679+
1680+error:
1681+ return reply;
1682+}
1683
1684=== added file 'gril/grilunsol.h'
1685--- gril/grilunsol.h 1970-01-01 00:00:00 +0000
1686+++ gril/grilunsol.h 2013-07-28 19:18:23 +0000
1687@@ -0,0 +1,62 @@
1688+/*
1689+ *
1690+ * RIL library with GLib integration
1691+ *
1692+ * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
1693+ * Copyright (C) 2012-2013 Canonical Ltd.
1694+ *
1695+ * This program is free software; you can redistribute it and/or modify
1696+ * it under the terms of the GNU General Public License version 2 as
1697+ * published by the Free Software Foundation.
1698+ *
1699+ * This program is distributed in the hope that it will be useful,
1700+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1701+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1702+ * GNU General Public License for more details.
1703+ *
1704+ * You should have received a copy of the GNU General Public License
1705+ * along with this program; if not, write to the Free Software
1706+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1707+ *
1708+ */
1709+
1710+#ifndef __GRILUNSOL_H
1711+#define __GRILUNSOL_H
1712+
1713+#include <ofono/types.h>
1714+
1715+#include "gril.h"
1716+
1717+#ifdef __cplusplus
1718+extern "C" {
1719+#endif
1720+
1721+struct unsol_data_call_list {
1722+ guint version;
1723+ guint num;
1724+ GSList *call_list;
1725+};
1726+
1727+struct data_call {
1728+ guint status;
1729+ guint retry;
1730+ guint cid;
1731+ guint active;
1732+ char *type;
1733+ char *ifname;
1734+ char *addresses;
1735+ char *dnses;
1736+ char *gateways;
1737+};
1738+
1739+void g_ril_unsol_free_data_call_list(struct unsol_data_call_list *unsol);
1740+
1741+struct unsol_data_call_list *g_ril_unsol_parse_data_call_list(GRil *gril,
1742+ struct ril_msg *message,
1743+ struct ofono_error *error);
1744+
1745+#ifdef __cplusplus
1746+}
1747+#endif
1748+
1749+#endif /* __GRILUNSOL_H */
1750
1751=== modified file 'gril/grilutil.c'
1752--- gril/grilutil.c 2013-05-25 03:31:48 +0000
1753+++ gril/grilutil.c 2013-07-28 19:18:23 +0000
1754@@ -30,9 +30,56 @@
1755
1756 #include <glib.h>
1757
1758+#include <ofono/modem.h>
1759+#include <ofono/gprs-context.h>
1760+#include <ofono/types.h>
1761+
1762 #include "grilutil.h"
1763+#include "parcel.h"
1764 #include "ril_constants.h"
1765
1766+/* Constants used by CALL_LIST, and SETUP_DATA_CALL RIL requests */
1767+#define PROTO_IP_STR "IP"
1768+#define PROTO_IPV6_STR "IPV6"
1769+#define PROTO_IPV4V6_STR "IPV4V6"
1770+
1771+const char *ril_ofono_protocol_to_ril_string(guint protocol)
1772+{
1773+ char *result;
1774+
1775+ switch (protocol) {
1776+ case OFONO_GPRS_PROTO_IPV6:
1777+ result = PROTO_IPV6_STR;
1778+ break;
1779+ case OFONO_GPRS_PROTO_IPV4V6:
1780+ result = PROTO_IPV4V6_STR;
1781+ break;
1782+ case OFONO_GPRS_PROTO_IP:
1783+ result = PROTO_IP_STR;
1784+ break;
1785+ default:
1786+ result = NULL;
1787+ }
1788+
1789+ return result;
1790+}
1791+
1792+int ril_protocol_string_to_ofono_protocol(gchar *protocol_str)
1793+{
1794+ int result;
1795+
1796+ if (g_strcmp0(protocol_str, PROTO_IPV6_STR) == 0)
1797+ result = OFONO_GPRS_PROTO_IPV6;
1798+ else if (g_strcmp0(protocol_str, PROTO_IPV4V6_STR) == 0)
1799+ result = OFONO_GPRS_PROTO_IPV4V6;
1800+ else if (g_strcmp0(protocol_str, PROTO_IP_STR) == 0)
1801+ result = OFONO_GPRS_PROTO_IP;
1802+ else
1803+ result = -1;
1804+
1805+ return result;
1806+}
1807+
1808 const char *ril_appstate_to_string(int app_state)
1809 {
1810 switch (app_state) {
1811
1812=== modified file 'gril/grilutil.h'
1813--- gril/grilutil.h 2013-05-25 03:31:48 +0000
1814+++ gril/grilutil.h 2013-07-28 19:18:23 +0000
1815@@ -23,12 +23,16 @@
1816 #ifndef __GRILUTIL_H
1817 #define __GRILUTIL_H
1818
1819+#ifdef __cplusplus
1820+extern "C" {
1821+#endif
1822+
1823 #include "gfunc.h"
1824-
1825-#ifdef __cplusplus
1826-extern "C" {
1827-#endif
1828-
1829+#include "parcel.h"
1830+#include "gril.h"
1831+
1832+const char *ril_ofono_protocol_to_ril_string(guint protocol);
1833+int ril_protocol_string_to_ofono_protocol(gchar *protocol_str);
1834 const char *ril_appstate_to_string(int app_state);
1835 const char *ril_apptype_to_string(int app_type);
1836 const char *ril_cardstate_to_string(int card_state);
1837
1838=== modified file 'gril/parcel.c'
1839--- gril/parcel.c 2013-05-24 22:02:28 +0000
1840+++ gril/parcel.c 2013-07-28 19:18:23 +0000
1841@@ -82,11 +82,9 @@
1842 {
1843 for (;;) {
1844
1845- /*
1846- * TODO: make conditional:
1847- * DBG("parcel_w_int32(%d): offset = %d, cap = %d, size = %d",
1848- * val, p->offset, p->capacity, p->size);
1849- */
1850+ DBG("parcel_w_int32(%d): offset = %d, cap = %d, size = %d\n",
1851+ val, p->offset, p->capacity, p->size);
1852+
1853 if (p->offset + sizeof(int32_t) < p->capacity) {
1854 /* There's enough space */
1855 *((int32_t *) (p->data + p->offset)) = val;
1856@@ -106,6 +104,7 @@
1857 gunichar2 *gs16;
1858 glong gs16_len;
1859 size_t len;
1860+ size_t gs16_size;
1861
1862 if (str == NULL) {
1863 parcel_w_int32(p, -1);
1864@@ -118,27 +117,24 @@
1865 return -1;
1866 }
1867
1868- len = (gs16_len + 1) * sizeof(char16_t);
1869+ gs16_size = gs16_len * sizeof(char16_t);
1870+ len = gs16_size + sizeof(char16_t);
1871 for (;;) {
1872 size_t padded = PAD_SIZE(len);
1873- /*
1874- * TODO: make conditional:
1875- * DBG("parcel_w_string(\"%s\"): offset %d, cap %d, size %d",
1876- * str, p->offset, p->capacity, p->size);
1877- */
1878+
1879+ DBG("parcel_w_string(\"%s\"): len %d offset %d, cap %d, size %d",
1880+ str, p->offset, p->capacity, p->size);
1881 if (p->offset + len < p->capacity) {
1882 /* There's enough space */
1883- memcpy(p->data + p->offset, gs16,
1884- gs16_len * sizeof(char16_t));
1885- *((char16_t *) (p->data + p->offset + len)) = 0;
1886+ memcpy(p->data + p->offset, gs16, gs16_size);
1887+ *((char16_t *) (p->data + p->offset + gs16_size)) = 0;
1888 p->offset += padded;
1889 p->size += padded;
1890 if (padded != len) {
1891- /*
1892- * TODO: make conditional:
1893- * DBG("Writing %d bytes, padded to %d",
1894- * len, padded);
1895- */
1896+
1897+ DBG("Writing %d bytes, padded to %d\n",
1898+ len, padded);
1899+
1900 #if BYTE_ORDER == BIG_ENDIAN
1901 static const uint32_t mask[4] = {
1902 0x00000000, 0xffffff00,
1903
1904=== modified file 'gril/ril_constants.h'
1905--- gril/ril_constants.h 2013-05-24 22:03:27 +0000
1906+++ gril/ril_constants.h 2013-07-28 19:18:23 +0000
1907@@ -76,12 +76,24 @@
1908 #define RADIO_TECH_HSPAP 15
1909 #define RADIO_TECH_GSM 16
1910
1911+/* see RIL_REQUEST_DEACTIVATE_DATA_CALL parameter*/
1912+#define RIL_DEACTIVATE_DATA_CALL_NO_REASON 0
1913+#define RIL_DEACTIVATE_DATA_CALL_RADIO_SHUTDOWN 1
1914+
1915 /* See RIL_REQUEST_SETUP_DATA_CALL */
1916
1917 #define RIL_DATA_PROFILE_DEFAULT 0
1918 #define RIL_DATA_PROFILE_TETHERED 1
1919+#define RIL_DATA_PROFILE_IMS 2
1920+#define RIL_DATA_PROFILE_FOTA 3 /* FOTA = Firmware Over the Air */
1921+#define RIL_DATA_PROFILE_CBS 4
1922 #define RIL_DATA_PROFILE_OEM_BASE 1000 /* Start of OEM-specific profiles */
1923
1924+#define RIL_AUTH_NONE 0
1925+#define RIL_AUTH_PAP 1
1926+#define RIL_AUTH_CHAP 2
1927+#define RIL_AUTH_BOTH 3
1928+
1929 /* SIM card states */
1930 #define RIL_CARDSTATE_ABSENT 0
1931 #define RIL_CARDSTATE_PRESENT 1
1932
1933=== modified file 'include/types.h'
1934--- include/types.h 2012-08-22 19:59:08 +0000
1935+++ include/types.h 2013-07-28 19:18:23 +0000
1936@@ -70,6 +70,16 @@
1937 int error;
1938 };
1939
1940+#define OFONO_EINVAL(error) do { \
1941+ error->type = OFONO_ERROR_TYPE_FAILURE; \
1942+ error->error = -EINVAL; \
1943+} while (0)
1944+
1945+#define OFONO_NO_ERROR(error) do { \
1946+ error->type = OFONO_ERROR_TYPE_NO_ERROR; \
1947+ error->error = 0; \
1948+} while (0)
1949+
1950 #define OFONO_MAX_PHONE_NUMBER_LENGTH 80
1951 #define OFONO_MAX_CALLER_NAME_LENGTH 80
1952
1953
1954=== added file 'unit/test-grilreply.c'
1955--- unit/test-grilreply.c 1970-01-01 00:00:00 +0000
1956+++ unit/test-grilreply.c 2013-07-28 19:18:23 +0000
1957@@ -0,0 +1,339 @@
1958+/*
1959+ *
1960+ * oFono - Open Source Telephony
1961+ *
1962+ * Copyright (C) 2013 Canonical Ltd.
1963+ *
1964+ * This program is free software; you can redistribute it and/or modify
1965+ * it under the terms of the GNU General Public License version 2 as
1966+ * published by the Free Software Foundation.
1967+ *
1968+ * This program is distributed in the hope that it will be useful,
1969+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1970+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1971+ * GNU General Public License for more details.
1972+ *
1973+ * You should have received a copy of the GNU General Public License
1974+ * along with this program; if not, write to the Free Software
1975+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1976+ *
1977+ */
1978+
1979+#ifdef HAVE_CONFIG_H
1980+#include <config.h>
1981+#endif
1982+
1983+#include <string.h>
1984+#include <stdio.h>
1985+#include <assert.h>
1986+#include <glib.h>
1987+#include <errno.h>
1988+
1989+#include <ofono/modem.h>
1990+#include <ofono/gprs-context.h>
1991+#include <ofono/types.h>
1992+
1993+#include "grilreply.h"
1994+
1995+/*
1996+ * TODO: It may make sense to split this file into
1997+ * domain-specific files ( eg. test-grilreply-gprs-context.c )
1998+ * once more tests are added.
1999+ */
2000+
2001+static const struct ril_msg reply_data_call_invalid_1 = {
2002+ .buf = "",
2003+ .buf_len = 0,
2004+};
2005+
2006+/*
2007+ * The following hexadecimal data equates te the following
2008+ * RIL_REQUEST_SETUP_DATA_CALL reply parameters:
2009+ *
2010+ * {version=2,num=2 [status=0,retry=-1,cid=0,active=2,type=IP}
2011+ * Parcel is truncated, as num=2 should trigger a failure.
2012+ */
2013+static const guchar reply_data_call_invalid_parcel2[36] = {
2014+ 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2015+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
2016+ 0x02, 0x00, 0x00, 0x00, 0x49, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00
2017+};
2018+
2019+static const struct ril_msg reply_data_call_invalid_2 = {
2020+ .buf = (gchar *) &reply_data_call_invalid_parcel2,
2021+ .buf_len = 36,
2022+};
2023+
2024+/*
2025+ * The following hexadecimal data is a binary representation of
2026+ * a parcel containing an invalid RIL_REQUEST_SETUP_DATA_CALL reply
2027+ * with a NULL string specified cfor 'type':
2028+ *
2029+ * {version=7,num=1 [status=0,retry=-1,cid=0,active=2,type=NULL
2030+ * ifname=rmnet_usb0,address=10.181.235.154/30,
2031+ * dns=172.16.145.103 172.16.145.103,gateways=10.181.235.153]}
2032+ */
2033+static const guchar reply_data_call_invalid_parcel3[196] = {
2034+ 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2035+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
2036+ 0xff, 0xff, 0xff, 0xff,
2037+ 0x0a, 0x00, 0x00, 0x00, 0x72, 0x00, 0x6d, 0x00, 0x6e, 0x00, 0x65, 0x00,
2038+ 0x74, 0x00, 0x5f, 0x00, 0x75, 0x00, 0x73, 0x00, 0x62, 0x00, 0x30, 0x00,
2039+ 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x31, 0x00, 0x30, 0x00,
2040+ 0x2e, 0x00, 0x31, 0x00, 0x38, 0x00, 0x31, 0x00, 0x2e, 0x00, 0x32, 0x00,
2041+ 0x33, 0x00, 0x35, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x35, 0x00, 0x34, 0x00,
2042+ 0x2f, 0x00, 0x33, 0x00, 0x30, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
2043+ 0x31, 0x00, 0x37, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x36, 0x00,
2044+ 0x2e, 0x00, 0x31, 0x00, 0x34, 0x00, 0x35, 0x00, 0x2e, 0x00, 0x31, 0x00,
2045+ 0x30, 0x00, 0x33, 0x00, 0x20, 0x00, 0x31, 0x00, 0x37, 0x00, 0x32, 0x00,
2046+ 0x2e, 0x00, 0x31, 0x00, 0x36, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x34, 0x00,
2047+ 0x35, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x30, 0x00, 0x33, 0x00, 0x00, 0x00,
2048+ 0x0e, 0x00, 0x00, 0x00, 0x31, 0x00, 0x30, 0x00, 0x2e, 0x00, 0x31, 0x00,
2049+ 0x38, 0x00, 0x31, 0x00, 0x2e, 0x00, 0x32, 0x00, 0x33, 0x00, 0x35, 0x00,
2050+ 0x2e, 0x00, 0x31, 0x00, 0x35, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00
2051+};
2052+
2053+static const struct ril_msg reply_data_call_invalid_3 = {
2054+ .buf = (gchar *) &reply_data_call_invalid_parcel3,
2055+ .buf_len = 196,
2056+};
2057+
2058+/*
2059+ * The following hexadecimal data is a binary representation of
2060+ * a parcel containing an invalid RIL_REQUEST_SETUP_DATA_CALL reply
2061+ * with a NULL string specified for 'ifname':
2062+ *
2063+ * {version=7,num=1 [status=0,retry=-1,cid=0,active=2,type=IP
2064+ * ifname=NULL,address=10.181.235.154/30,
2065+ * dns=172.16.145.103 172.16.145.103,gateways=10.181.235.153]}
2066+ */
2067+static const guchar reply_data_call_invalid_parcel4[190] = {
2068+ 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2069+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
2070+ 0x02, 0x00, 0x00, 0x00, 0x49, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00,
2071+ 0xff, 0xff, 0xff, 0xff, 0x11, 0x00, 0x00, 0x00, 0x31, 0x00, 0x30, 0x00,
2072+ 0x2e, 0x00, 0x31, 0x00, 0x38, 0x00, 0x31, 0x00, 0x2e, 0x00, 0x32, 0x00,
2073+ 0x33, 0x00, 0x35, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x35, 0x00, 0x34, 0x00,
2074+ 0x2f, 0x00, 0x33, 0x00, 0x30, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
2075+ 0x31, 0x00, 0x37, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x36, 0x00,
2076+ 0x2e, 0x00, 0x31, 0x00, 0x34, 0x00, 0x35, 0x00, 0x2e, 0x00, 0x31, 0x00,
2077+ 0x30, 0x00, 0x33, 0x00, 0x20, 0x00, 0x31, 0x00, 0x37, 0x00, 0x32, 0x00,
2078+ 0x2e, 0x00, 0x31, 0x00, 0x36, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x34, 0x00,
2079+ 0x35, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x30, 0x00, 0x33, 0x00, 0x00, 0x00,
2080+ 0x0e, 0x00, 0x00, 0x00, 0x31, 0x00, 0x30, 0x00, 0x2e, 0x00, 0x31, 0x00,
2081+ 0x38, 0x00, 0x31, 0x00, 0x2e, 0x00, 0x32, 0x00, 0x33, 0x00, 0x35, 0x00,
2082+ 0x2e, 0x00, 0x31, 0x00, 0x35, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00
2083+};
2084+
2085+static const struct ril_msg reply_data_call_invalid_4 = {
2086+ .buf = (gchar *) &reply_data_call_invalid_parcel4,
2087+ .buf_len = 190,
2088+};
2089+
2090+/*
2091+ * The following hexadecimal data is a binary representation of
2092+ * a parcel containing an invalid RIL_REQUEST_SETUP_DATA_CALL reply
2093+ * with a NULL string specified for 'address':
2094+ *
2095+ * {version=7,num=1 [status=0,retry=-1,cid=0,active=2,type=IP
2096+ * ifname=rmnet_usb0,address=NULL,
2097+ * dns=172.16.145.103 172.16.145.103,gateways=10.181.235.153]}
2098+ */
2099+static const guchar reply_data_call_invalid_parcel5[168] = {
2100+ 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2101+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
2102+ 0x02, 0x00, 0x00, 0x00, 0x49, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00,
2103+ 0x0a, 0x00, 0x00, 0x00, 0x72, 0x00, 0x6d, 0x00, 0x6e, 0x00, 0x65, 0x00,
2104+ 0x74, 0x00, 0x5f, 0x00, 0x75, 0x00, 0x73, 0x00, 0x62, 0x00, 0x30, 0x00,
2105+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x1d, 0x00, 0x00, 0x00,
2106+ 0x31, 0x00, 0x37, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x36, 0x00,
2107+ 0x2e, 0x00, 0x31, 0x00, 0x34, 0x00, 0x35, 0x00, 0x2e, 0x00, 0x31, 0x00,
2108+ 0x30, 0x00, 0x33, 0x00, 0x20, 0x00, 0x31, 0x00, 0x37, 0x00, 0x32, 0x00,
2109+ 0x2e, 0x00, 0x31, 0x00, 0x36, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x34, 0x00,
2110+ 0x35, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x30, 0x00, 0x33, 0x00, 0x00, 0x00,
2111+ 0x0e, 0x00, 0x00, 0x00, 0x31, 0x00, 0x30, 0x00, 0x2e, 0x00, 0x31, 0x00,
2112+ 0x38, 0x00, 0x31, 0x00, 0x2e, 0x00, 0x32, 0x00, 0x33, 0x00, 0x35, 0x00,
2113+ 0x2e, 0x00, 0x31, 0x00, 0x35, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00
2114+};
2115+
2116+static const struct ril_msg reply_data_call_invalid_5 = {
2117+ .buf = (gchar *) &reply_data_call_invalid_parcel5,
2118+ .buf_len = 168,
2119+};
2120+
2121+/*
2122+ * The following hexadecimal data represents a serialized Binder parcel
2123+ * instance containing an invalid RIL_REQUEST_SETUP_DATA_CALL reply
2124+ * with a NULL string specified for 'gateways':
2125+ *
2126+ * {version=7,num=1 [status=0,retry=-1,cid=0,active=2,type=IP
2127+ * ifname=rmnet_usb0,address=10.181.235.154/30,
2128+ * dns=172.16.145.103 172.16.145.103,gateways=NULL]}
2129+ */
2130+static const guchar reply_data_call_invalid_parcel6[180] = {
2131+ 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2132+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
2133+ 0x02, 0x00, 0x00, 0x00, 0x49, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00,
2134+ 0x0a, 0x00, 0x00, 0x00, 0x72, 0x00, 0x6d, 0x00, 0x6e, 0x00, 0x65, 0x00,
2135+ 0x74, 0x00, 0x5f, 0x00, 0x75, 0x00, 0x73, 0x00, 0x62, 0x00, 0x30, 0x00,
2136+ 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x31, 0x00, 0x30, 0x00,
2137+ 0x2e, 0x00, 0x31, 0x00, 0x38, 0x00, 0x31, 0x00, 0x2e, 0x00, 0x32, 0x00,
2138+ 0x33, 0x00, 0x35, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x35, 0x00, 0x34, 0x00,
2139+ 0x2f, 0x00, 0x33, 0x00, 0x30, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
2140+ 0x31, 0x00, 0x37, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x36, 0x00,
2141+ 0x2e, 0x00, 0x31, 0x00, 0x34, 0x00, 0x35, 0x00, 0x2e, 0x00, 0x31, 0x00,
2142+ 0x30, 0x00, 0x33, 0x00, 0x20, 0x00, 0x31, 0x00, 0x37, 0x00, 0x32, 0x00,
2143+ 0x2e, 0x00, 0x31, 0x00, 0x36, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x34, 0x00,
2144+ 0x35, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x30, 0x00, 0x33, 0x00, 0x00, 0x00,
2145+ 0xff, 0xff, 0xff, 0xff
2146+};
2147+
2148+static const struct ril_msg reply_data_call_invalid_6 = {
2149+ .buf = (gchar *) &reply_data_call_invalid_parcel6,
2150+ .buf_len = 180,
2151+};
2152+
2153+/*
2154+ * The following hexadecimal data represents a serialized Binder parcel
2155+ * instance containing an invalid RIL_REQUEST_SETUP_DATA_CALL reply with
2156+ * with a NULL string specified for 'dns':
2157+ *
2158+ * {version=7,num=1 [status=0,retry=-1,cid=0,active=2,type=IP
2159+ * ifname=rmnet_usb0,address=10.181.235.154/30,
2160+ * dns=NULL,gateways=10.181.235.153]}
2161+ */
2162+static const guchar reply_data_call_invalid_parcel7[144] = {
2163+ 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2164+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
2165+ 0x02, 0x00, 0x00, 0x00, 0x49, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00,
2166+ 0x0a, 0x00, 0x00, 0x00, 0x72, 0x00, 0x6d, 0x00, 0x6e, 0x00, 0x65, 0x00,
2167+ 0x74, 0x00, 0x5f, 0x00, 0x75, 0x00, 0x73, 0x00, 0x62, 0x00, 0x30, 0x00,
2168+ 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x31, 0x00, 0x30, 0x00,
2169+ 0x2e, 0x00, 0x31, 0x00, 0x38, 0x00, 0x31, 0x00, 0x2e, 0x00, 0x32, 0x00,
2170+ 0x33, 0x00, 0x35, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x35, 0x00, 0x34, 0x00,
2171+ 0x2f, 0x00, 0x33, 0x00, 0x30, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
2172+ 0x0e, 0x00, 0x00, 0x00, 0x31, 0x00, 0x30, 0x00, 0x2e, 0x00, 0x31, 0x00,
2173+ 0x38, 0x00, 0x31, 0x00, 0x2e, 0x00, 0x32, 0x00, 0x33, 0x00, 0x35, 0x00,
2174+ 0x2e, 0x00, 0x31, 0x00, 0x35, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00
2175+};
2176+
2177+static const struct ril_msg reply_data_call_invalid_7 = {
2178+ .buf = (gchar *) &reply_data_call_invalid_parcel7,
2179+ .buf_len = 144,
2180+};
2181+
2182+/*
2183+ * The following hexadecimal data represents a serialized Binder parcel
2184+ * instance containing a valid RIL_REQUEST_SETUP_DATA_CALL reply with the
2185+ * following parameters:
2186+ *
2187+ * {version=7,num=1 [status=0,retry=-1,cid=0,active=2,type=IP,
2188+ * ifname=rmnet_usb0,address=10.181.235.154/30,
2189+ * dns=172.16.145.103 172.16.145.103,gateways=10.181.235.153]}
2190+ */
2191+static const guchar reply_data_call_valid_parcel1[204] = {
2192+ 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2193+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
2194+ 0x02, 0x00, 0x00, 0x00, 0x49, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00,
2195+ 0x0a, 0x00, 0x00, 0x00, 0x72, 0x00, 0x6d, 0x00, 0x6e, 0x00, 0x65, 0x00,
2196+ 0x74, 0x00, 0x5f, 0x00, 0x75, 0x00, 0x73, 0x00, 0x62, 0x00, 0x30, 0x00,
2197+ 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x31, 0x00, 0x30, 0x00,
2198+ 0x2e, 0x00, 0x31, 0x00, 0x38, 0x00, 0x31, 0x00, 0x2e, 0x00, 0x32, 0x00,
2199+ 0x33, 0x00, 0x35, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x35, 0x00, 0x34, 0x00,
2200+ 0x2f, 0x00, 0x33, 0x00, 0x30, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
2201+ 0x31, 0x00, 0x37, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x36, 0x00,
2202+ 0x2e, 0x00, 0x31, 0x00, 0x34, 0x00, 0x35, 0x00, 0x2e, 0x00, 0x31, 0x00,
2203+ 0x30, 0x00, 0x33, 0x00, 0x20, 0x00, 0x31, 0x00, 0x37, 0x00, 0x32, 0x00,
2204+ 0x2e, 0x00, 0x31, 0x00, 0x36, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x34, 0x00,
2205+ 0x35, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x30, 0x00, 0x33, 0x00, 0x00, 0x00,
2206+ 0x0e, 0x00, 0x00, 0x00, 0x31, 0x00, 0x30, 0x00, 0x2e, 0x00, 0x31, 0x00,
2207+ 0x38, 0x00, 0x31, 0x00, 0x2e, 0x00, 0x32, 0x00, 0x33, 0x00, 0x35, 0x00,
2208+ 0x2e, 0x00, 0x31, 0x00, 0x35, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00
2209+};
2210+
2211+static const struct ril_msg reply_data_call_valid_1 = {
2212+ .buf = (gchar *) &reply_data_call_valid_parcel1,
2213+ .buf_len = 204,
2214+ .unsolicited = FALSE,
2215+ .req = RIL_REQUEST_SETUP_DATA_CALL,
2216+ .serial_no = 0,
2217+ .error = 0,
2218+};
2219+
2220+static void test_reply_data_call_invalid(gconstpointer data)
2221+{
2222+ /* TODO: fix de-const cast... */
2223+ struct ril_msg *message = (struct ril_msg *) data;
2224+ struct ofono_error error;
2225+ struct reply_setup_data_call *reply;
2226+
2227+ reply = g_ril_reply_parse_data_call(NULL, message, &error);
2228+ g_assert(reply != NULL);
2229+ g_ril_reply_free_setup_data_call(reply);
2230+
2231+ g_assert(error.type == OFONO_ERROR_TYPE_FAILURE &&
2232+ error.error == -EINVAL);
2233+}
2234+
2235+static void test_reply_data_call_valid(gconstpointer data)
2236+{
2237+ /* TODO: fix de-const cast... */
2238+ struct ril_msg *message = (struct ril_msg *) data;
2239+ struct ofono_error error;
2240+ struct reply_setup_data_call *reply;
2241+
2242+ reply = g_ril_reply_parse_data_call(NULL, message, &error);
2243+ g_assert(reply != NULL);
2244+ g_ril_reply_free_setup_data_call(reply);
2245+
2246+ g_assert(error.type == OFONO_ERROR_TYPE_NO_ERROR &&
2247+ error.error == 0);
2248+}
2249+
2250+int main(int argc, char **argv)
2251+{
2252+ g_test_init(&argc, &argv, NULL);
2253+
2254+ g_test_add_data_func("/testgrilreply/gprs-context: "
2255+ "invalid SETUP_DATA_CALL Test 1",
2256+ &reply_data_call_invalid_1,
2257+ test_reply_data_call_invalid);
2258+
2259+ g_test_add_data_func("/testgrilreply/gprs-context: "
2260+ "invalid SETUP_DATA_CALL Test 2",
2261+ &reply_data_call_invalid_2,
2262+ test_reply_data_call_invalid);
2263+
2264+ g_test_add_data_func("/testgrilreply/gprs-context: "
2265+ "invalid SETUP_DATA_CALL Test 3",
2266+ &reply_data_call_invalid_3,
2267+ test_reply_data_call_invalid);
2268+
2269+ g_test_add_data_func("/testgrilreply/gprs-context: "
2270+ "invalid SETUP_DATA_CALL Test 4",
2271+ &reply_data_call_invalid_4,
2272+ test_reply_data_call_invalid);
2273+
2274+ g_test_add_data_func("/testgrilreply/gprs-context: "
2275+ "invalid SETUP_DATA_CALL Test 5",
2276+ &reply_data_call_invalid_5,
2277+ test_reply_data_call_invalid);
2278+
2279+ g_test_add_data_func("/testgrilreply/gprs-context: "
2280+ "invalid SETUP_DATA_CALL Test 6",
2281+ &reply_data_call_invalid_6,
2282+ test_reply_data_call_invalid);
2283+
2284+ g_test_add_data_func("/testgrilreply/gprs-context: "
2285+ "invalid SETUP_DATA_CALL Test 7",
2286+ &reply_data_call_invalid_7,
2287+ test_reply_data_call_invalid);
2288+
2289+ g_test_add_data_func("/testgrilreply/gprs-context: "
2290+ "valid SETUP_DATA_CALL Test 1",
2291+ &reply_data_call_valid_1,
2292+ test_reply_data_call_valid);
2293+
2294+
2295+ return g_test_run();
2296+}
2297
2298=== added file 'unit/test-grilrequest.c'
2299--- unit/test-grilrequest.c 1970-01-01 00:00:00 +0000
2300+++ unit/test-grilrequest.c 2013-07-28 19:18:23 +0000
2301@@ -0,0 +1,312 @@
2302+/*
2303+ *
2304+ * oFono - Open Source Telephony
2305+ *
2306+ * Copyright (C) 2013 Canonical Ltd.
2307+ *
2308+ * This program is free software; you can redistribute it and/or modify
2309+ * it under the terms of the GNU General Public License version 2 as
2310+ * published by the Free Software Foundation.
2311+ *
2312+ * This program is distributed in the hope that it will be useful,
2313+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2314+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2315+ * GNU General Public License for more details.
2316+ *
2317+ * You should have received a copy of the GNU General Public License
2318+ * along with this program; if not, write to the Free Software
2319+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2320+ *
2321+ */
2322+
2323+#ifdef HAVE_CONFIG_H
2324+#include <config.h>
2325+#endif
2326+
2327+#include <string.h>
2328+#include <stdio.h>
2329+#include <assert.h>
2330+#include <glib.h>
2331+#include <errno.h>
2332+
2333+#include <ofono/modem.h>
2334+#include <ofono/gprs-context.h>
2335+#include <ofono/types.h>
2336+
2337+#include "grilrequest.h"
2338+
2339+struct request_test_data {
2340+ gconstpointer request;
2341+ guchar *parcel_data;
2342+ gsize parcel_size;
2343+};
2344+
2345+/*
2346+ * TODO: It may make sense to split this file into
2347+ * domain-specific files ( eg. test-grilrequest-gprs-context.c )
2348+ * once more tests are added.
2349+ */
2350+
2351+static const struct req_deactivate_data_call req_deact_data_call_invalid_1 = {
2352+ .cid = 1,
2353+ .reason = 10,
2354+};
2355+
2356+/*
2357+ * The following hexadecimal data represents a serialized Binder parcel
2358+ * instance containing a valid RIL_REQUEST_DEACTIVATE_DATA_CALL message
2359+ * with the following parameters:
2360+ *
2361+ * (cid=1,reason=0)
2362+ */
2363+static const guchar req_deact_data_call_valid_parcel1[20] = {
2364+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00,
2365+ 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00
2366+};
2367+
2368+static const struct req_deactivate_data_call req_deact_data_call_valid_1 = {
2369+ .cid = 1,
2370+ .reason = RIL_DEACTIVATE_DATA_CALL_NO_REASON,
2371+};
2372+
2373+static const struct request_test_data deact_data_call_valid_test_1 = {
2374+ .request = &req_deact_data_call_valid_1,
2375+ .parcel_data = (guchar *) &req_deact_data_call_valid_parcel1,
2376+ .parcel_size = 20,
2377+};
2378+
2379+
2380+static const struct req_setup_data_call req_setup_data_call_invalid_1 = {
2381+ .tech = RADIO_TECH_UNKNOWN,
2382+};
2383+
2384+static const struct req_setup_data_call req_setup_data_call_invalid_2 = {
2385+ .tech = 2112,
2386+};
2387+
2388+static const struct req_setup_data_call req_setup_data_call_invalid_3 = {
2389+ .tech = RADIO_TECH_GPRS,
2390+ .data_profile = 5,
2391+};
2392+
2393+static const struct req_setup_data_call req_setup_data_call_invalid_4 = {
2394+ .tech = RADIO_TECH_GPRS,
2395+ .data_profile = RIL_DATA_PROFILE_DEFAULT,
2396+ .apn = NULL,
2397+};
2398+
2399+static const struct req_setup_data_call req_setup_data_call_invalid_5 = {
2400+ .tech = RADIO_TECH_GPRS,
2401+ .data_profile = RIL_DATA_PROFILE_DEFAULT,
2402+ .apn = "",
2403+};
2404+
2405+static const struct req_setup_data_call req_setup_data_call_invalid_6 = {
2406+ .tech = RADIO_TECH_GPRS,
2407+ .data_profile = RIL_DATA_PROFILE_DEFAULT,
2408+ .apn = "",
2409+ .apn = "12345678901234567890123456789012345678901234567890"
2410+ "123456789012345678901234567890123456789012345678901",
2411+};
2412+
2413+static const struct req_setup_data_call req_setup_data_call_invalid_7 = {
2414+ .tech = RADIO_TECH_GPRS,
2415+ .data_profile = RIL_DATA_PROFILE_DEFAULT,
2416+ .apn = "test.apn",
2417+ .auth_type = 4,
2418+};
2419+
2420+static const struct req_setup_data_call req_setup_data_call_invalid_8 = {
2421+ .tech = RADIO_TECH_GPRS,
2422+ .data_profile = RIL_DATA_PROFILE_DEFAULT,
2423+ .apn = "test.apn",
2424+ .auth_type = RIL_AUTH_BOTH,
2425+ .protocol = 3,
2426+};
2427+
2428+static const struct req_setup_data_call req_setup_data_call_valid_1 = {
2429+ .tech = RADIO_TECH_GPRS,
2430+ .data_profile = RIL_DATA_PROFILE_DEFAULT,
2431+ .apn = "test.apn",
2432+ .username = NULL,
2433+ .password = NULL,
2434+ .auth_type = RIL_AUTH_BOTH,
2435+ .protocol = OFONO_GPRS_PROTO_IP,
2436+
2437+};
2438+
2439+static const struct req_setup_data_call req_setup_data_call_valid_2 = {
2440+ .tech = RADIO_TECH_GPRS,
2441+ .data_profile = RIL_DATA_PROFILE_DEFAULT,
2442+ .apn = "test.apn",
2443+ .username = "",
2444+ .password = "",
2445+ .auth_type = RIL_AUTH_NONE,
2446+ .protocol = OFONO_GPRS_PROTO_IP,
2447+};
2448+
2449+static const struct req_setup_data_call req_setup_data_call_valid_3 = {
2450+ .tech = RADIO_TECH_GPRS,
2451+ .data_profile = RIL_DATA_PROFILE_DEFAULT,
2452+ .apn = "test.apn",
2453+ .username = "phablet",
2454+ .password = "phablet",
2455+ .auth_type = RIL_AUTH_BOTH,
2456+ .protocol = OFONO_GPRS_PROTO_IPV4V6,
2457+};
2458+
2459+static const struct req_setup_data_call req_setup_data_call_valid_4 = {
2460+ .tech = RADIO_TECH_GPRS,
2461+ .data_profile = RIL_DATA_PROFILE_DEFAULT,
2462+ .apn = "test.apn",
2463+ .username = "phablet",
2464+ .password = "phablet",
2465+ .auth_type = RIL_AUTH_BOTH,
2466+ .protocol = OFONO_GPRS_PROTO_IPV6,
2467+};
2468+
2469+static void test_deactivate_data_call_invalid(gconstpointer data)
2470+{
2471+ const struct req_deactivate_data_call *request = data;
2472+ gboolean result;
2473+ struct parcel rilp;
2474+ struct ofono_error error;
2475+
2476+ /*
2477+ * No parcel_init needed, as these tests all fail during
2478+ * param validation
2479+ */
2480+ result = g_ril_request_deactivate_data_call(NULL, request, &rilp, &error);
2481+ g_assert(result == FALSE);
2482+ g_assert(error.type == OFONO_ERROR_TYPE_FAILURE &&
2483+ error.error == -EINVAL);
2484+}
2485+
2486+static void test_deactivate_data_call_valid(gconstpointer data)
2487+{
2488+ const struct request_test_data *test_data = data;
2489+ const struct req_deactivate_data_call *request = test_data->request;
2490+ gboolean result;
2491+ struct parcel rilp;
2492+ struct ofono_error error;
2493+
2494+ result = g_ril_request_deactivate_data_call(NULL, request, &rilp, &error);
2495+ g_assert(result == TRUE);
2496+ g_assert(error.type == OFONO_ERROR_TYPE_NO_ERROR &&
2497+ error.error == 0);
2498+
2499+ g_assert(!memcmp(rilp.data, test_data->parcel_data, test_data->parcel_size));
2500+
2501+ parcel_free(&rilp);
2502+}
2503+
2504+static void test_request_setup_data_call_invalid(gconstpointer data)
2505+{
2506+ const struct req_setup_data_call *request = data;
2507+ gboolean result;
2508+ struct parcel rilp;
2509+ struct ofono_error error;
2510+
2511+ /*
2512+ * No parcel_init needed, as these tests all fail during
2513+ * param validation
2514+ */
2515+ result = g_ril_request_setup_data_call(NULL, request, &rilp, &error);
2516+ g_assert(result == FALSE);
2517+ g_assert(error.type == OFONO_ERROR_TYPE_FAILURE &&
2518+ error.error == -EINVAL);
2519+}
2520+
2521+static void test_request_setup_data_call_valid(gconstpointer data)
2522+{
2523+ const struct req_setup_data_call *request = data;
2524+ gboolean result;
2525+ struct parcel rilp;
2526+ struct ofono_error error;
2527+
2528+ result = g_ril_request_setup_data_call(NULL, request, &rilp, &error);
2529+ g_assert(result == TRUE);
2530+ g_assert(error.type == OFONO_ERROR_TYPE_NO_ERROR &&
2531+ error.error == 0);
2532+
2533+ parcel_free(&rilp);
2534+
2535+ /* TODO: add unit 3 tests to validate binary parcel result */
2536+}
2537+
2538+int main(int argc, char **argv)
2539+{
2540+ g_test_init(&argc, &argv, NULL);
2541+
2542+ g_test_add_data_func("/testgrilrequest/gprs-context: "
2543+ "invalid DEACTIVATE_DATA_CALL Test 1",
2544+ &req_deact_data_call_invalid_1,
2545+ test_deactivate_data_call_invalid);
2546+
2547+ g_test_add_data_func("/testgrilrequest/gprs-context: "
2548+ "valid DEACTIVATE_DATA_CALL Test 1",
2549+ &deact_data_call_valid_test_1,
2550+ test_deactivate_data_call_valid);
2551+
2552+ g_test_add_data_func("/testgrilrequest/gprs-context: "
2553+ "invalid SETUP_DATA_CALL Test 1",
2554+ &req_setup_data_call_invalid_1,
2555+ test_request_setup_data_call_invalid);
2556+
2557+ g_test_add_data_func("/testgrilrequest/gprs-context: "
2558+ "invalid SETUP_DATA_CALL Test 2",
2559+ &req_setup_data_call_invalid_2,
2560+ test_request_setup_data_call_invalid);
2561+
2562+ g_test_add_data_func("/testgrilrequest/gprs-context: "
2563+ "invalid SETUP_DATA_CALL Test 3",
2564+ &req_setup_data_call_invalid_3,
2565+ test_request_setup_data_call_invalid);
2566+
2567+ g_test_add_data_func("/testgrilrequest/gprs-context: "
2568+ "invalid SETUP_DATA_CALL Test 4",
2569+ &req_setup_data_call_invalid_4,
2570+ test_request_setup_data_call_invalid);
2571+
2572+ g_test_add_data_func("/testgrilrequest/gprs-context: "
2573+ "invalid SETUP_DATA_CALL Test 5",
2574+ &req_setup_data_call_invalid_5,
2575+ test_request_setup_data_call_invalid);
2576+
2577+ g_test_add_data_func("/testgrilrequest/gprs-context: "
2578+ "invalid SETUP_DATA_CALL Test 6",
2579+ &req_setup_data_call_invalid_6,
2580+ test_request_setup_data_call_invalid);
2581+
2582+ g_test_add_data_func("/testgrilrequest/gprs-context: "
2583+ "invalid SETUP_DATA_CALL Test 7",
2584+ &req_setup_data_call_invalid_7,
2585+ test_request_setup_data_call_invalid);
2586+
2587+ g_test_add_data_func("/testgrilrequest/gprs-context: "
2588+ "invalid SETUP_DATA_CALL Test 8",
2589+ &req_setup_data_call_invalid_8,
2590+ test_request_setup_data_call_invalid);
2591+
2592+ g_test_add_data_func("/testgrilrequest/gprs-context: "
2593+ "valid SETUP_DATA_CALL Test 1",
2594+ &req_setup_data_call_valid_1,
2595+ test_request_setup_data_call_valid);
2596+
2597+ g_test_add_data_func("/testgrilrequest/gprs-context: "
2598+ "valid SETUP_DATA_CALL Test 2",
2599+ &req_setup_data_call_valid_2,
2600+ test_request_setup_data_call_valid);
2601+
2602+ g_test_add_data_func("/testgrilrequest/gprs-context: "
2603+ "valid SETUP_DATA_CALL Test 3",
2604+ &req_setup_data_call_valid_3,
2605+ test_request_setup_data_call_valid);
2606+
2607+ g_test_add_data_func("/testgrilrequest/gprs-context: "
2608+ "valid SETUP_DATA_CALL Test 4",
2609+ &req_setup_data_call_valid_4,
2610+ test_request_setup_data_call_valid);
2611+
2612+ return g_test_run();
2613+}
2614
2615=== added file 'unit/test-grilunsol.c'
2616--- unit/test-grilunsol.c 1970-01-01 00:00:00 +0000
2617+++ unit/test-grilunsol.c 2013-07-28 19:18:23 +0000
2618@@ -0,0 +1,138 @@
2619+/*
2620+ *
2621+ * oFono - Open Source Telephony
2622+ *
2623+ * Copyright (C) 2013 Canonical Ltd.
2624+ *
2625+ * This program is free software; you can redistribute it and/or modify
2626+ * it under the terms of the GNU General Public License version 2 as
2627+ * published by the Free Software Foundation.
2628+ *
2629+ * This program is distributed in the hope that it will be useful,
2630+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2631+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2632+ * GNU General Public License for more details.
2633+ *
2634+ * You should have received a copy of the GNU General Public License
2635+ * along with this program; if not, write to the Free Software
2636+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2637+ *
2638+ */
2639+
2640+#ifdef HAVE_CONFIG_H
2641+#include <config.h>
2642+#endif
2643+
2644+#include <string.h>
2645+#include <stdio.h>
2646+#include <assert.h>
2647+#include <glib.h>
2648+#include <errno.h>
2649+
2650+#include <ofono/modem.h>
2651+#include <ofono/gprs-context.h>
2652+#include <ofono/types.h>
2653+
2654+#include "gril.h"
2655+#include "grilunsol.h"
2656+
2657+/*
2658+ * TODO: It may make sense to split this file into
2659+ * domain-specific files ( eg. test-grilrequest-gprs-context.c )
2660+ * once more tests are added.
2661+ */
2662+
2663+static const struct ril_msg unsol_data_call_list_changed_invalid_1 = {
2664+ .buf = "",
2665+ .buf_len = 0,
2666+ .unsolicited = TRUE,
2667+ .req = RIL_UNSOL_DATA_CALL_LIST_CHANGED,
2668+ .serial_no = 0,
2669+ .error = 0,
2670+};
2671+
2672+/*
2673+ * The following hexadecimal data represents a serialized Binder parcel
2674+ * instance containing a valid RIL_UNSOL_DATA_CALL_LIST_CHANGED message
2675+ * with the following parameters:
2676+ *
2677+ * (version=7,num=1 [status=0,retry=-1,cid=0,active=1,type=IP,
2678+ * ifname=rmnet_usb0,address=10.209.114.102/30,
2679+ * dns=172.16.145.103 172.16.145.103,gateways=10.209.114.101]}
2680+ */
2681+static const guchar unsol_data_call_list_changed_parcel1[216] = {
2682+ 0x00, 0x00, 0x00, 0xd4, 0x01, 0x00, 0x00, 0x00, 0xf2, 0x03, 0x00, 0x00,
2683+ 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2684+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2685+ 0x02, 0x00, 0x00, 0x00, 0x49, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00,
2686+ 0x0a, 0x00, 0x00, 0x00, 0x72, 0x00, 0x6d, 0x00, 0x6e, 0x00, 0x65, 0x00,
2687+ 0x74, 0x00, 0x5f, 0x00, 0x75, 0x00, 0x73, 0x00, 0x62, 0x00, 0x30, 0x00,
2688+ 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x31, 0x00, 0x30, 0x00,
2689+ 0x2e, 0x00, 0x32, 0x00, 0x30, 0x00, 0x39, 0x00, 0x2e, 0x00, 0x31, 0x00,
2690+ 0x31, 0x00, 0x34, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x30, 0x00, 0x32, 0x00,
2691+ 0x2f, 0x00, 0x33, 0x00, 0x30, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
2692+ 0x31, 0x00, 0x37, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x36, 0x00,
2693+ 0x2e, 0x00, 0x31, 0x00, 0x34, 0x00, 0x35, 0x00, 0x2e, 0x00, 0x31, 0x00,
2694+ 0x30, 0x00, 0x33, 0x00, 0x20, 0x00, 0x31, 0x00, 0x37, 0x00, 0x32, 0x00,
2695+ 0x2e, 0x00, 0x31, 0x00, 0x36, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x34, 0x00,
2696+ 0x35, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x30, 0x00, 0x33, 0x00, 0x00, 0x00,
2697+ 0x0e, 0x00, 0x00, 0x00, 0x31, 0x00, 0x30, 0x00, 0x2e, 0x00, 0x32, 0x00,
2698+ 0x30, 0x00, 0x39, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x31, 0x00, 0x34, 0x00,
2699+ 0x2e, 0x00, 0x31, 0x00, 0x30, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00
2700+};
2701+
2702+static const struct ril_msg unsol_data_call_list_changed_valid_1 = {
2703+ .buf = (gchar *) &unsol_data_call_list_changed_parcel1,
2704+ .buf_len = 216,
2705+ .unsolicited = TRUE,
2706+ .req = RIL_UNSOL_DATA_CALL_LIST_CHANGED,
2707+ .serial_no = 0,
2708+ .error = 0,
2709+};
2710+
2711+static void test_unsol_data_call_list_changed_invalid(gconstpointer data)
2712+{
2713+ /* TODO: fix de-const cast... */
2714+ const struct ril_msg *message = (struct ril_msg *) data;
2715+ struct ofono_error error;
2716+ struct unsol_data_call_list *unsol;
2717+
2718+ unsol = g_ril_unsol_parse_data_call_list(NULL, message, &error);
2719+ g_assert(unsol != NULL);
2720+ g_ril_unsol_free_data_call_list(unsol);
2721+
2722+ g_assert(error.type == OFONO_ERROR_TYPE_FAILURE &&
2723+ error.error == -EINVAL);
2724+}
2725+
2726+static void test_unsol_data_call_list_changed_valid(gconstpointer data)
2727+{
2728+ /* TODO: fix de-const cast... */
2729+ const struct ril_msg *message = (struct ril_msg *) data;
2730+ struct ofono_error error;
2731+ struct unsol_data_call_list *unsol;
2732+
2733+ unsol = g_ril_unsol_parse_data_call_list(NULL, message, &error);
2734+ g_assert(unsol != NULL);
2735+ g_ril_unsol_free_data_call_list(unsol);
2736+
2737+ g_assert(error.type == OFONO_ERROR_TYPE_NO_ERROR &&
2738+ error.error == 0);
2739+}
2740+
2741+int main(int argc, char **argv)
2742+{
2743+ g_test_init(&argc, &argv, NULL);
2744+
2745+ g_test_add_data_func("/testgrilrequest/gprs-context: "
2746+ "invalid DATA_CALL_LIST_CHANGED Test 1",
2747+ &unsol_data_call_list_changed_invalid_1,
2748+ test_unsol_data_call_list_changed_invalid);
2749+
2750+ g_test_add_data_func("/testgrilrequest/gprs-context: "
2751+ "valid DATA_CALL_LIST_CHANGED Test 1",
2752+ &unsol_data_call_list_changed_valid_1,
2753+ test_unsol_data_call_list_changed_valid);
2754+
2755+ return g_test_run();
2756+}

Subscribers

People subscribed via source and target branches