Merge lp:~awe/phablet-extras/ofono-raring into lp:phablet-extras/ofono

Proposed by Tony Espy
Status: Merged
Approved by: Ricardo Salveti
Approved revision: 35
Merged at revision: 30
Proposed branch: lp:~awe/phablet-extras/ofono-raring
Merge into: lp:phablet-extras/ofono
Prerequisite: lp:~awe/phablet-extras/ofono-flatten
Diff against target: 6188 lines (+5905/-14)
31 files modified
Makefile.am (+37/-9)
configure.ac (+5/-0)
debian/changelog (+56/-0)
debian/control (+3/-0)
debian/ofono.install (+0/-2)
debian/ofono.upstart (+6/-1)
debian/rules (+2/-2)
drivers/rilmodem/call-volume.c (+186/-0)
drivers/rilmodem/devinfo.c (+171/-0)
drivers/rilmodem/network-registration.c (+595/-0)
drivers/rilmodem/rilmodem.c (+61/-0)
drivers/rilmodem/rilmodem.h (+38/-0)
drivers/rilmodem/rilutil.c (+372/-0)
drivers/rilmodem/rilutil.h (+125/-0)
drivers/rilmodem/sms.c (+357/-0)
drivers/rilmodem/voicecall.c (+537/-0)
gril/gfunc.h (+42/-0)
gril/gril.c (+1160/-0)
gril/gril.h (+102/-0)
gril/grilio.c (+396/-0)
gril/grilio.h (+69/-0)
gril/grilresponse.h (+46/-0)
gril/grilutil.c (+499/-0)
gril/grilutil.h (+53/-0)
gril/parcel.c (+181/-0)
gril/parcel.h (+43/-0)
gril/ril_constants.h (+244/-0)
gril/ringbuffer.h (+107/-0)
include/modem.h (+1/-0)
plugins/ril.c (+395/-0)
src/modem.c (+16/-0)
To merge this branch: bzr merge lp:~awe/phablet-extras/ofono-raring
Reviewer Review Type Date Requested Status
Ricardo Salveti (community) Approve
PS Jenkins bot continuous-integration Approve
Review via email: mp+156908@code.launchpad.net

Commit message

Re-based ofono/RILD code on new upstream version ofono-1.12-0ubuntu2b1 from Raring.

Description of the change

This MR represents a re-base of the oFono RILD code from the quantal version (ofono-1.9) to the raring version (ofono-1.12).

Basic functional testing was run on a Galaxy Nexus using a recent daily build. Phone calls and SMSs were both tested.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Ricardo Salveti (rsalveti) wrote :

There are quite a few things missing here:
* Not running autoreconf during configure (as we change configure.ac and makefile.am)
* makefile.am not covering all changes we had (missing -lwaudio for example)
* build fails when building the plugins:
plugins/phonesim.o: In function `localhfp_enable':
/home/phablet/ofono/ofono-raring/plugins/phonesim.c:883: undefined reference to `hfp_slc_info_init'
/home/phablet/ofono/ofono-raring/plugins/phonesim.c:885: undefined reference to `hfp_slc_establish'
plugins/hfp_hf.o: In function `hfp_agent_new_connection':
/home/phablet/ofono/ofono-raring/plugins/hfp_hf.c:173: undefined reference to `hfp_slc_info_init'
plugins/hfp_hf.o: In function `service_level_connection':
/home/phablet/ofono/ofono-raring/plugins/hfp_hf.c:156: undefined reference to `hfp_slc_establish'
collect2: error: ld returned 1 exit status
make[2]: *** [src/ofonod] Error 1
make[1]: *** [all] Error 2
make[1]: Leaving directory `/home/phablet/ofono/ofono-raring'
make: *** [debian/stamp-makefile-build] Error 2
dpkg-buildpackage: error: debian/rules build gave error exit status 2

Trying to build the package with dpkg-buildpackage -uc -us.

review: Needs Fixing
Revision history for this message
Ricardo Salveti (rsalveti) wrote :

Needed changes just to make it get to the failed point pointed above:
$ bzr diff
=== modified file 'Makefile.am'
--- Makefile.am 2013-03-28 12:50:26 +0000
+++ Makefile.am 2013-04-09 02:28:20 +0000
@@ -526,7 +526,7 @@
    src/cdma-sms.c src/private-network.c src/cdma-netreg.c \
    src/cdma-provision.c src/handsfree.c

-src_ofonod_LDADD = $(builtin_libadd) @GLIB_LIBS@ @DBUS_LIBS@ -ldl
+src_ofonod_LDADD = $(builtin_libadd) @GLIB_LIBS@ @DBUS_LIBS@ -ldl -lwaudio

 src_ofonod_LDFLAGS = -Wl,--export-dynamic \
     -Wl,--version-script=$(srcdir)/src/ofono.ver

=== modified file 'debian/control'
--- debian/control 2013-03-28 12:50:26 +0000
+++ debian/control 2013-04-09 02:14:30 +0000
@@ -6,10 +6,12 @@
 Uploaders: Jonny Lamb <email address hidden>, Hector Oron <email address hidden>, Konstantinos Margaritis <email address hidden>
 Build-Depends: debhelper (>= 7.0.50~),
                cdbs,
+ dh-autoreconf,
                libtool,
                libglib2.0-dev (>= 2.22),
                libdbus-glib-1-dev,
                libudev-dev,
+ libwaudio1-dev (>= 1.4~quantal1),
                udev,
                libbluetooth-dev (>= 4.30),
                mobile-broadband-provider-info

=== modified file 'debian/rules'
--- debian/rules 2012-08-22 19:59:08 +0000
+++ debian/rules 2013-04-09 02:05:25 +0000
@@ -2,6 +2,7 @@
 DEB_AUTO_CLEANUP_RCS := yes

 include /usr/share/cdbs/1/class/autotools.mk
+include /usr/share/cdbs/1/rules/autoreconf.mk
 include /usr/share/cdbs/1/rules/debhelper.mk
 #include /usr/share/cdbs/1/rules/simple-patchsys.mk
 include /usr/share/cdbs/1/rules/utils.mk

lp:~awe/phablet-extras/ofono-raring updated
32. By Tony Espy

Fix build problems by enabled autoreconf, disabling Bluetooth, and fixing
the android audio system dependency.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
lp:~awe/phablet-extras/ofono-raring updated
33. By Tony Espy

Remove dundee reference in debian/ofono.install.

34. By Tony Espy

Removed udev references from debian/ofono.install.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
lp:~awe/phablet-extras/ofono-raring updated
35. By Tony Espy

Disable udev in debian/rules.

Revision history for this message
Tony Espy (awe) wrote :

Should be all set.

I verified the latest branch builds, installs and runs on a quantal touch daily ( today's ). I verified that incoming/outgoing sms and voice calls worked.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Ricardo Salveti (rsalveti) wrote :

Good, worked fine at both quantal and raring, with phone calls and sms.

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-01-28 16:25:32 +0000
3+++ Makefile.am 2013-04-09 20:01:20 +0000
4@@ -89,6 +89,12 @@
5 gisi/server.c gisi/server.h \
6 gisi/socket.c gisi/socket.h
7
8+gril_sources = gril/gril.h gril/gril.c gril/grilio.h \
9+ gril/grilio.c gril/grilutil.h \
10+ gril/grilutil.c gril/ringbuffer.h \
11+ gril/gfunc.h gril/ril.h \
12+ gril/parcel.c gril/parcel.h
13+
14 btio_sources = btio/btio.h btio/btio.c
15
16 if UDEV
17@@ -101,6 +107,25 @@
18 builtin_sources += plugins/udevng.c
19 endif
20
21+if RILMODEM
22+builtin_sources += $(gril_sources)
23+
24+builtin_modules += ril
25+builtin_sources += plugins/ril.c
26+
27+builtin_modules += rilmodem
28+builtin_sources += drivers/rilmodem/rilmodem.h \
29+ drivers/rilmodem/rilmodem.c \
30+ drivers/rilmodem/devinfo.c \
31+ drivers/rilmodem/network-registration.c \
32+ drivers/rilmodem/voicecall.c \
33+ drivers/rilmodem/call-volume.c \
34+ drivers/rilmodem/sms.c \
35+ drivers/rilmodem/rilutil.c \
36+ drivers/rilmodem/rilutil.h
37+
38+endif
39+
40 if ISIMODEM
41 builtin_modules += isimodem
42 builtin_sources += $(gisi_sources) \
43@@ -210,7 +235,7 @@
44 drivers/atmodem/gprs-context.c \
45 drivers/atmodem/sim-auth.c \
46 drivers/atmodem/gnss.c
47-
48+if !RILMODEM
49 builtin_modules += nwmodem
50 builtin_sources += drivers/atmodem/atutil.h \
51 drivers/nwmodem/nwmodem.h \
52@@ -299,6 +324,13 @@
53 drivers/dunmodem/network-registration.c \
54 drivers/dunmodem/gprs.c
55
56+builtin_modules += speedupmodem
57+builtin_sources += drivers/atmodem/atutil.h \
58+ drivers/speedupmodem/speedupmodem.h \
59+ drivers/speedupmodem/speedupmodem.c \
60+ drivers/speedupmodem/ussd.c
61+endif
62+
63 builtin_modules += hfpmodem
64 builtin_sources += drivers/atmodem/atutil.h \
65 drivers/hfpmodem/hfpmodem.h \
66@@ -311,12 +343,6 @@
67 drivers/hfpmodem/devinfo.c \
68 drivers/hfpmodem/handsfree.c
69
70-builtin_modules += speedupmodem
71-builtin_sources += drivers/atmodem/atutil.h \
72- drivers/speedupmodem/speedupmodem.h \
73- drivers/speedupmodem/speedupmodem.c \
74- drivers/speedupmodem/ussd.c
75-
76 if PHONESIM
77 builtin_modules += phonesim
78 builtin_sources += plugins/phonesim.c
79@@ -335,6 +361,7 @@
80 drivers/cdmamodem/connman.c
81 endif
82
83+if !RILMODEM
84 builtin_modules += g1
85 builtin_sources += plugins/g1.c
86
87@@ -406,6 +433,7 @@
88
89 builtin_modules += sim900
90 builtin_sources += plugins/sim900.c
91+endif
92
93 if BLUETOOTH
94 builtin_modules += bluetooth
95@@ -498,7 +526,7 @@
96 src/cdma-sms.c src/private-network.c src/cdma-netreg.c \
97 src/cdma-provision.c src/handsfree.c
98
99-src_ofonod_LDADD = $(builtin_libadd) @GLIB_LIBS@ @DBUS_LIBS@ -ldl
100+src_ofonod_LDADD = $(builtin_libadd) @GLIB_LIBS@ @DBUS_LIBS@ -ldl -lwaudio
101
102 src_ofonod_LDFLAGS = -Wl,--export-dynamic \
103 -Wl,--version-script=$(srcdir)/src/ofono.ver
104@@ -522,7 +550,7 @@
105
106 INCLUDES = -I$(builddir)/include -I$(builddir)/src -I$(srcdir)/src \
107 -I$(srcdir)/gdbus -I$(srcdir)/gisi -I$(srcdir)/gatchat \
108- -I$(srcdir)/btio
109+ -I$(srcdir)/btio -I$(srcdir)/gril
110
111 doc_files = doc/overview.txt doc/ofono-paper.txt doc/release-faq.txt \
112 doc/manager-api.txt doc/modem-api.txt doc/network-api.txt \
113
114=== modified file 'configure.ac'
115--- configure.ac 2013-01-28 16:25:32 +0000
116+++ configure.ac 2013-04-09 20:01:20 +0000
117@@ -167,6 +167,11 @@
118 [enable_isimodem=${enableval}])
119 AM_CONDITIONAL(ISIMODEM, test "${enable_isimodem}" != "no")
120
121+AC_ARG_ENABLE(rilmodem, AC_HELP_STRING([--disable-rilmodem],
122+ [disable RIL modem support]),
123+ [enable_rilmodem=${enableval}])
124+AM_CONDITIONAL(RILMODEM, test "${enable_rilmodem}" != "no")
125+
126 AC_ARG_ENABLE(qmimodem, AC_HELP_STRING([--disable-qmimodem],
127 [disable Qualcomm QMI modem support]),
128 [enable_qmimodem=${enableval}])
129
130=== modified file 'debian/changelog'
131--- debian/changelog 2013-04-03 16:11:02 +0000
132+++ debian/changelog 2013-04-09 20:01:20 +0000
133@@ -1,5 +1,61 @@
134 ofono (1.12phablet1) UNRELEASED; urgency=low
135
136+ [ Ricardo Salveti de Araujo ]
137+ * ofono.upstart: not starting with debug by default, not needed anymore
138+ * drivers/rilmodem/devinfo.c: fake data should just use Fake instead of
139+ Galaxy Nexus
140+
141+ [ Tony Espy ]
142+ * gril/*, plugins/ril.c, drivers/rilmodem/*: fixed copyright headers,
143+ sanitized comments.
144+
145+ [ Ricardo Salveti de Araujo ]
146+ * Fixing audio states during and after a call, previously broken with
147+ JellyBean (LP: #1101339)
148+
149+ [ Tony Espy ]
150+ * Re-named the galaxynexus plugin to ril.
151+ * [galaxynexus] Add SIM checking to modem initialization.
152+ * [gril] Add ril_request_id_to_string function.
153+ * [core] Modify ofono_modem_set_online() to call modem_change_state(),
154+ which triggers our new modem initialization logic in galaxynexus'
155+ post_online function.
156+
157+ [ Ricardo Salveti de Araujo ]
158+ * parcel.c: fixing data padding boundary for parcel_w_string (LP: #1088559)
159+ * Only setting audio mode in call when actually dialing or answering (to
160+ allow ringtones at the ubuntu side)
161+
162+ [ Tony Espy ]
163+ * Disable atmodem plugin on starup.
164+
165+ [ Ricardo Salveti de Araujo ]
166+ * Adding proper support for network registration and network state changes
167+ * Support registering for network time update reports
168+ * Extending network registration to support current operator, list of
169+ operators and auto/manual registration
170+ * Enabling support to retrieve the signal strength
171+ * Enabling initial support for DTMF
172+ * Adding support for answering a call
173+ * Tuning start sleep for 8 and running with debug messages enabled
174+ * Sync ril_delayed_register timeout to 2 for all services in rilmodem
175+ * Setting up voice state and enabling voice call support at AudioFlinger
176+
177+ [ Tony Espy ]
178+ * Initial version of notification framework for RIL
179+ unsolicited events ( signal strength, new sms, ... ).
180+ * Support for incoming SMS messages (LP: #1085896).
181+
182+ [ Ricardo Salveti de Araujo ]
183+ * Adding support for voice call (LP: #1085893)
184+ * Adding utils files for parcel and string handling
185+ * Enable basic support for voice volume (mute/unmute)
186+
187+ [ Michael Frey ]
188+ * debian/ofono.upstart: Fix for hang on shutdown.
189+
190+ [ Tony Espy ]
191+ * First hard-coded support for RIL modem on Galaxy Nexus.
192 * Initial phablet version, converted to native for
193 easier development of new RIL driver/plugin code.
194 - debian/source/format: changed to 3.0 (native)
195
196=== modified file 'debian/control'
197--- debian/control 2012-08-22 19:59:08 +0000
198+++ debian/control 2013-04-09 20:01:20 +0000
199@@ -6,9 +6,12 @@
200 Uploaders: Jonny Lamb <jonny@debian.org>, Hector Oron <zumbi@debian.org>, Konstantinos Margaritis <markos@debian.org>
201 Build-Depends: debhelper (>= 7.0.50~),
202 cdbs,
203+ dh-autoreconf,
204+ libtool,
205 libglib2.0-dev (>= 2.22),
206 libdbus-glib-1-dev,
207 libudev-dev,
208+ libwaudio1-dev,
209 udev,
210 libbluetooth-dev (>= 4.30),
211 mobile-broadband-provider-info
212
213=== modified file 'debian/ofono.install'
214--- debian/ofono.install 2012-08-22 19:59:08 +0000
215+++ debian/ofono.install 2013-04-09 20:01:20 +0000
216@@ -1,6 +1,4 @@
217 debian/tmp/etc/dbus-1/system.d/*
218 debian/tmp/usr/sbin/ofonod
219-debian/tmp/usr/sbin/dundee
220 debian/tmp/etc/ofono
221-debian/tmp/lib/udev/rules.d/*
222 debian/tmp/usr/share/man
223
224=== modified file 'debian/ofono.upstart'
225--- debian/ofono.upstart 2010-09-02 18:21:57 +0000
226+++ debian/ofono.upstart 2013-04-09 20:01:20 +0000
227@@ -6,4 +6,9 @@
228 expect fork
229 respawn
230
231-exec ofonod
232+exec ofonod --noplugin=atmodem
233+
234+pre-start script
235+ sleep 8
236+end script
237+
238
239=== modified file 'debian/rules'
240--- debian/rules 2012-08-22 19:59:08 +0000
241+++ debian/rules 2013-04-09 20:01:20 +0000
242@@ -2,14 +2,14 @@
243 DEB_AUTO_CLEANUP_RCS := yes
244
245 include /usr/share/cdbs/1/class/autotools.mk
246+include /usr/share/cdbs/1/rules/autoreconf.mk
247 include /usr/share/cdbs/1/rules/debhelper.mk
248-#include /usr/share/cdbs/1/rules/simple-patchsys.mk
249 include /usr/share/cdbs/1/rules/utils.mk
250
251 DEB_DH_INSTALLINIT_ARGS := --no-restart-on-upgrade
252
253 common-binary-post-install-arch:: list-missing
254
255-DEB_CONFIGURE_EXTRA_FLAGS := --enable-bluetooth --enable-dundee
256+DEB_CONFIGURE_EXTRA_FLAGS := --disable-bluetooth --disable-dundee --disable-udev
257
258 include $(CURDIR)/debian/update-patches.mk
259
260=== added directory 'drivers/rilmodem'
261=== added file 'drivers/rilmodem/call-volume.c'
262--- drivers/rilmodem/call-volume.c 1970-01-01 00:00:00 +0000
263+++ drivers/rilmodem/call-volume.c 2013-04-09 20:01:20 +0000
264@@ -0,0 +1,186 @@
265+/*
266+ *
267+ * oFono - Open Source Telephony
268+ *
269+ * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
270+ * Copyright (C) 2012 Canonical Ltd.
271+ *
272+ * This program is free software; you can redistribute it and/or modify
273+ * it under the terms of the GNU General Public License version 2 as
274+ * published by the Free Software Foundation.
275+ *
276+ * This program is distributed in the hope that it will be useful,
277+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
278+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
279+ * GNU General Public License for more details.
280+ *
281+ * You should have received a copy of the GNU General Public License
282+ * along with this program; if not, write to the Free Software
283+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
284+ *
285+ */
286+
287+#ifdef HAVE_CONFIG_H
288+#include <config.h>
289+#endif
290+
291+#define _GNU_SOURCE
292+#include <string.h>
293+#include <stdio.h>
294+#include <errno.h>
295+
296+#include <glib.h>
297+
298+#include <ofono/log.h>
299+#include <ofono/modem.h>
300+#include <ofono/call-volume.h>
301+
302+#include "gril.h"
303+#include "grilutil.h"
304+
305+#include "common.h"
306+
307+#include "rilmodem.h"
308+#include "parcel.h"
309+
310+struct cv_data {
311+ GRil *ril;
312+ unsigned int vendor;
313+};
314+
315+static void volume_mute_cb(struct ril_msg *message, gpointer user_data)
316+{
317+ struct cb_data *cbd = user_data;
318+ ofono_call_volume_cb_t cb = cbd->cb;
319+ struct ofono_error error;
320+
321+ DBG("");
322+
323+ if (message->error == RIL_E_SUCCESS) {
324+ decode_ril_error(&error, "OK");
325+ } else {
326+ ofono_error("Could not set the ril mute state");
327+ decode_ril_error(&error, "FAIL");
328+ }
329+
330+ cb(&error, cbd->data);
331+}
332+
333+static void ril_call_volume_mute(struct ofono_call_volume *cv, int muted,
334+ ofono_call_volume_cb_t cb, void *data)
335+{
336+ struct cv_data *cvd = ofono_call_volume_get_data(cv);
337+ struct cb_data *cbd = cb_data_new(cb, data);
338+ struct parcel rilp;
339+
340+ DBG("");
341+
342+ parcel_init(&rilp);
343+ parcel_w_int32(&rilp, 1);
344+ parcel_w_int32(&rilp, muted);
345+ g_ril_send(cvd->ril, RIL_REQUEST_SET_MUTE, rilp.data,
346+ rilp.size, volume_mute_cb, cbd, g_free);
347+ parcel_free(&rilp);
348+
349+ return;
350+}
351+
352+static void probe_mute_cb(struct ril_msg *message, gpointer user_data)
353+{
354+ struct ofono_call_volume *cv = user_data;
355+ struct parcel rilp;
356+ int muted;
357+
358+ DBG("");
359+
360+ if (message->error != RIL_E_SUCCESS) {
361+ ofono_error("Could not retrive the ril mute state");
362+ return;
363+ }
364+
365+ /* Set up Parcel struct for proper parsing */
366+ rilp.data = message->buf;
367+ rilp.size = message->buf_len;
368+ rilp.capacity = message->buf_len;
369+ rilp.offset = 0;
370+
371+ muted = parcel_r_int32(&rilp);
372+ DBG("Initial ril muted state: %d", muted);
373+
374+ ofono_call_volume_set_muted(cv, muted);
375+}
376+
377+static void call_probe_mute(gpointer user_data)
378+{
379+ struct ofono_call_volume *cv = user_data;
380+ struct cv_data *cvd = ofono_call_volume_get_data(cv);
381+
382+ DBG("Requesting mute from RIL");
383+
384+ g_ril_send(cvd->ril, RIL_REQUEST_GET_MUTE, NULL, 0,
385+ probe_mute_cb, cv, NULL);
386+
387+ return;
388+}
389+
390+static gboolean ril_delayed_register(gpointer user_data)
391+{
392+ struct ofono_call_volume *cv = user_data;
393+ DBG("");
394+ ofono_call_volume_register(cv);
395+
396+ /* Probe the mute state */
397+ call_probe_mute(user_data);
398+
399+ /* This makes the timeout a single-shot */
400+ return FALSE;
401+}
402+
403+static int ril_call_volume_probe(struct ofono_call_volume *cv,
404+ unsigned int vendor, void *data)
405+{
406+ GRil *ril = data;
407+ struct cv_data *cvd;
408+
409+ DBG("");
410+
411+ cvd = g_new0(struct cv_data, 1);
412+ if (cvd == NULL)
413+ return -ENOMEM;
414+
415+ cvd->ril = g_ril_clone(ril);
416+ cvd->vendor = vendor;
417+
418+ ofono_call_volume_set_data(cv, cvd);
419+
420+ g_timeout_add_seconds(2, ril_delayed_register, cv);
421+
422+ return 0;
423+}
424+
425+static void ril_call_volume_remove(struct ofono_call_volume *cv)
426+{
427+ struct cv_data *cvd = ofono_call_volume_get_data(cv);
428+
429+ ofono_call_volume_set_data(cv, NULL);
430+
431+ g_ril_unref(cvd->ril);
432+ g_free(cvd);
433+}
434+
435+static struct ofono_call_volume_driver driver = {
436+ .name = "rilmodem",
437+ .probe = ril_call_volume_probe,
438+ .remove = ril_call_volume_remove,
439+ .mute = ril_call_volume_mute,
440+};
441+
442+void ril_call_volume_init(void)
443+{
444+ ofono_call_volume_driver_register(&driver);
445+}
446+
447+void ril_call_volume_exit(void)
448+{
449+ ofono_call_volume_driver_unregister(&driver);
450+}
451
452=== added file 'drivers/rilmodem/devinfo.c'
453--- drivers/rilmodem/devinfo.c 1970-01-01 00:00:00 +0000
454+++ drivers/rilmodem/devinfo.c 2013-04-09 20:01:20 +0000
455@@ -0,0 +1,171 @@
456+/*
457+ *
458+ * oFono - Open Source Telephony - RIL Modem Support
459+ *
460+ * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
461+ * Copyright (C) 2012 Canonical Ltd.
462+ *
463+ * This program is free software; you can redistribute it and/or modify
464+ * it under the terms of the GNU General Public License version 2 as
465+ * published by the Free Software Foundation.
466+ *
467+ * This program is distributed in the hope that it will be useful,
468+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
469+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
470+ * GNU General Public License for more details.
471+ *
472+ * You should have received a copy of the GNU General Public License
473+ * along with this program; if not, write to the Free Software
474+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
475+ *
476+ */
477+
478+#ifdef HAVE_CONFIG_H
479+#include <config.h>
480+#endif
481+
482+#define _GNU_SOURCE
483+#include <stdio.h>
484+#include <stdlib.h>
485+#include <string.h>
486+#include <errno.h>
487+
488+#include <glib.h>
489+
490+#include <ofono/log.h>
491+#include <ofono/modem.h>
492+#include <ofono/devinfo.h>
493+
494+#include "gril.h"
495+
496+#include "rilmodem.h"
497+
498+/*
499+ * TODO: The functions in this file are stubbed out, and
500+ * will need to be re-worked to talk to the /gril layer
501+ * in order to get real values from RILD.
502+ */
503+
504+static void ril_query_manufacturer(struct ofono_devinfo *info,
505+ ofono_devinfo_query_cb_t cb,
506+ void *data)
507+{
508+ const char *attr = "Fake Manufacturer";
509+ struct cb_data *cbd = cb_data_new(cb, data);
510+ struct ofono_error error;
511+ decode_ril_error(&error, "OK");
512+
513+ cb(&error, attr, cbd->data);
514+
515+ /* Note: this will need to change if cbd passed to gril layer */
516+ g_free(cbd);
517+}
518+
519+static void ril_query_model(struct ofono_devinfo *info,
520+ ofono_devinfo_query_cb_t cb,
521+ void *data)
522+{
523+ const char *attr = "Fake Modem Model";
524+ struct cb_data *cbd = cb_data_new(cb, data);
525+ struct ofono_error error;
526+ decode_ril_error(&error, "OK");
527+
528+ cb(&error, attr, cbd->data);
529+
530+ /* Note: this will need to change if cbd passed to gril layer */
531+ g_free(cbd);
532+}
533+
534+static void ril_query_revision(struct ofono_devinfo *info,
535+ ofono_devinfo_query_cb_t cb,
536+ void *data)
537+{
538+ const char *attr = "Fake Revision";
539+ struct cb_data *cbd = cb_data_new(cb, data);
540+ struct ofono_error error;
541+ decode_ril_error(&error, "OK");
542+
543+ cb(&error, attr, cbd->data);
544+
545+ /* Note: this will need to change if cbd passed to gril layer */
546+ g_free(cbd);
547+}
548+
549+static void ril_query_serial(struct ofono_devinfo *info,
550+ ofono_devinfo_query_cb_t cb,
551+ void *data)
552+{
553+ const char *attr = "THIS-IS-A-FAKE-SERIAL-NO";
554+ struct cb_data *cbd = cb_data_new(cb, data);
555+ struct ofono_error error;
556+ decode_ril_error(&error, "OK");
557+
558+ cb(&error, attr, cbd->data);
559+
560+ /* Note: this will need to change if cbd passed to gril layer */
561+ g_free(cbd);
562+}
563+
564+static gboolean ril_delayed_register(gpointer user_data)
565+{
566+ struct ofono_devinfo *info = user_data;
567+ DBG("");
568+ ofono_devinfo_register(info);
569+
570+ /* This makes the timeout a single-shot */
571+ return FALSE;
572+}
573+
574+static int ril_devinfo_probe(struct ofono_devinfo *info, unsigned int vendor,
575+ void *data)
576+{
577+ GRil *ril = NULL;
578+
579+ if (data != NULL)
580+ ril = g_ril_clone(data);
581+
582+ ofono_devinfo_set_data(info, ril);
583+
584+ DBG("");
585+
586+ /* Nothing to send...
587+ *
588+ * ofono_devinfo_register() needs to be called after
589+ * the driver has been set in devinfo_create() which
590+ * calls this function. Most other drivers use a
591+ * callback after getting some return from the modem
592+ * itself...
593+ */
594+ g_timeout_add_seconds(1, ril_delayed_register, info);
595+
596+ return 0;
597+}
598+
599+static void ril_devinfo_remove(struct ofono_devinfo *info)
600+{
601+ GRil *ril = ofono_devinfo_get_data(info);
602+
603+ ofono_devinfo_set_data(info, NULL);
604+
605+ g_ril_unref(ril);
606+}
607+
608+static struct ofono_devinfo_driver driver = {
609+ .name = "rilmodem",
610+ .probe = ril_devinfo_probe,
611+ .remove = ril_devinfo_remove,
612+ .query_manufacturer = ril_query_manufacturer,
613+ .query_model = ril_query_model,
614+ .query_revision = ril_query_revision,
615+ .query_serial = ril_query_serial
616+};
617+
618+void ril_devinfo_init(void)
619+{
620+ ofono_devinfo_driver_register(&driver);
621+}
622+
623+void ril_devinfo_exit(void)
624+{
625+ ofono_devinfo_driver_unregister(&driver);
626+}
627
628=== added file 'drivers/rilmodem/network-registration.c'
629--- drivers/rilmodem/network-registration.c 1970-01-01 00:00:00 +0000
630+++ drivers/rilmodem/network-registration.c 2013-04-09 20:01:20 +0000
631@@ -0,0 +1,595 @@
632+/*
633+ *
634+ * oFono - Open Source Telephony - RIL Modem Support
635+ *
636+ * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
637+ * Copyright (C) 2010 ST-Ericsson AB.
638+ * Copyright (C) 2012 Canonical Ltd.
639+ *
640+ * This program is free software; you can redistribute it and/or modify
641+ * it under the terms of the GNU General Public License version 2 as
642+ * published by the Free Software Foundation.
643+ *
644+ * This program is distributed in the hope that it will be useful,
645+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
646+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
647+ * GNU General Public License for more details.
648+ *
649+ * You should have received a copy of the GNU General Public License
650+ * along with this program; if not, write to the Free Software
651+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
652+ *
653+ */
654+
655+#ifdef HAVE_CONFIG_H
656+#include <config.h>
657+#endif
658+
659+#define _GNU_SOURCE
660+#include <string.h>
661+#include <stdlib.h>
662+#include <stdio.h>
663+
664+#include <glib.h>
665+
666+#include <ofono/log.h>
667+#include <ofono/modem.h>
668+#include <ofono/netreg.h>
669+
670+#include "gril.h"
671+
672+#include "rilmodem.h"
673+#include "parcel.h"
674+#include "common.h"
675+#include "parcel.h"
676+
677+struct netreg_data {
678+ GRil *ril;
679+ char mcc[OFONO_MAX_MCC_LENGTH + 1];
680+ char mnc[OFONO_MAX_MNC_LENGTH + 1];
681+ int signal_index; /* If strength is reported via CIND */
682+ int signal_min; /* min strength reported via CIND */
683+ int signal_max; /* max strength reported via CIND */
684+ int signal_invalid; /* invalid strength reported via CIND */
685+ int tech;
686+ struct ofono_network_time time;
687+ guint nitz_timeout;
688+ unsigned int vendor;
689+};
690+
691+/* 27.007 Section 7.3 <stat> */
692+enum operator_status {
693+ OPERATOR_STATUS_UNKNOWN = 0,
694+ OPERATOR_STATUS_AVAILABLE = 1,
695+ OPERATOR_STATUS_CURRENT = 2,
696+ OPERATOR_STATUS_FORBIDDEN = 3,
697+};
698+
699+static void extract_mcc_mnc(const char *str, char *mcc, char *mnc)
700+{
701+ /* Three digit country code */
702+ strncpy(mcc, str, OFONO_MAX_MCC_LENGTH);
703+ mcc[OFONO_MAX_MCC_LENGTH] = '\0';
704+
705+ /* Usually a 2 but sometimes 3 digit network code */
706+ strncpy(mnc, str + OFONO_MAX_MCC_LENGTH, OFONO_MAX_MNC_LENGTH);
707+ mnc[OFONO_MAX_MNC_LENGTH] = '\0';
708+}
709+
710+/*
711+ * TODO: The functions in this file are stubbed out, and
712+ * will need to be re-worked to talk to the /gril layer
713+ * in order to get real values from RILD.
714+ */
715+
716+static void ril_creg_cb(struct ril_msg *message, gpointer user_data)
717+{
718+ struct cb_data *cbd = user_data;
719+ ofono_netreg_status_cb_t cb = cbd->cb;
720+ struct netreg_data *nd = cbd->user;
721+ struct ofono_error error;
722+ int status, lac, ci, tech;
723+
724+ DBG("");
725+
726+ if (message->error != RIL_E_SUCCESS) {
727+ decode_ril_error(&error, "FAIL");
728+ ofono_error("Failed to pull registration state");
729+ cb(&error, -1, -1, -1, -1, cbd->data);
730+ return;
731+ }
732+
733+ decode_ril_error(&error, "OK");
734+
735+ if (ril_util_parse_reg(message, &status,
736+ &lac, &ci, &tech) == FALSE) {
737+ CALLBACK_WITH_FAILURE(cb, -1, -1, -1, -1, cbd->data);
738+ return;
739+ }
740+
741+ DBG("oFono reg - status: %s, lac: %x, ci: %x, tech: %s",
742+ registration_status_to_string(status),
743+ lac, ci,
744+ registration_tech_to_string(tech));
745+
746+ nd->tech = tech;
747+ cb(&error, status, lac, ci, tech, cbd->data);
748+}
749+
750+static void ril_creg_notify(struct ofono_error *error, int status, int lac,
751+ int ci, int tech, gpointer user_data)
752+{
753+ struct ofono_netreg *netreg = user_data;
754+
755+ DBG("");
756+
757+ if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
758+ DBG("Error during status notification");
759+ return;
760+ }
761+
762+ ofono_netreg_status_notify(netreg, status, lac, ci, tech);
763+}
764+
765+static void ril_network_state_change(struct ril_msg *message, gpointer user_data)
766+{
767+ struct ofono_netreg *netreg = user_data;
768+ struct netreg_data *nd = ofono_netreg_get_data(netreg);
769+ struct cb_data *cbd = cb_data_new(ril_creg_notify, netreg);
770+
771+ DBG("");
772+
773+ cbd->user = nd;
774+
775+ if (message->req != RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED)
776+ goto error;
777+
778+ if (g_ril_send(nd->ril, RIL_REQUEST_VOICE_REGISTRATION_STATE, NULL,
779+ 0, ril_creg_cb, cbd, g_free) > 0)
780+ return;
781+
782+ /* For operator update ofono will use the current_operator cb
783+ * so we don't need to probe ril here */
784+
785+error:
786+ g_free(cbd);
787+
788+ ofono_error("Unable to request network state changed");
789+}
790+
791+static void ril_registration_status(struct ofono_netreg *netreg,
792+ ofono_netreg_status_cb_t cb,
793+ void *data)
794+{
795+ struct netreg_data *nd = ofono_netreg_get_data(netreg);
796+ struct cb_data *cbd = cb_data_new(cb, data);
797+
798+ cbd->user = nd;
799+
800+ if (g_ril_send(nd->ril, RIL_REQUEST_VOICE_REGISTRATION_STATE, NULL,
801+ 0, ril_creg_cb, cbd, g_free) > 0)
802+ return;
803+
804+ g_free(cbd);
805+
806+ CALLBACK_WITH_FAILURE(cb, -1, -1, -1, -1, data);
807+}
808+
809+static void ril_cops_cb(struct ril_msg *message, gpointer user_data)
810+{
811+ struct cb_data *cbd = user_data;
812+ ofono_netreg_operator_cb_t cb = cbd->cb;
813+ struct netreg_data *nd = cbd->user;
814+ struct ofono_error error;
815+ struct parcel rilp;
816+ struct ofono_network_operator op;
817+ gchar *lalpha, *salpha, *numeric;
818+
819+ if (message->error == RIL_E_SUCCESS) {
820+ decode_ril_error(&error, "OK");
821+ } else {
822+ ofono_error("Failed to retrive the current operator");
823+ goto error;
824+ }
825+
826+ /* Set up Parcel struct for proper parsing */
827+ rilp.data = message->buf;
828+ rilp.size = message->buf_len;
829+ rilp.capacity = message->buf_len;
830+ rilp.offset = 0;
831+
832+ /* Size of char ** */
833+ if (parcel_r_int32(&rilp) == 0)
834+ goto error;
835+
836+ lalpha = parcel_r_string(&rilp);
837+ salpha = parcel_r_string(&rilp);
838+ numeric = parcel_r_string(&rilp);
839+
840+ DBG("RIL cops - lalpha: %s, salpha: %s, numeric: %s",
841+ lalpha, salpha, numeric);
842+
843+ /* Try to use long by default */
844+ if (lalpha)
845+ strncpy(op.name, lalpha, OFONO_MAX_OPERATOR_NAME_LENGTH);
846+ else
847+ strncpy(op.name, salpha, OFONO_MAX_OPERATOR_NAME_LENGTH);
848+
849+ extract_mcc_mnc(numeric, op.mcc, op.mnc);
850+
851+ /* Set to current */
852+ op.status = OPERATOR_STATUS_CURRENT;
853+ op.tech = nd->tech;
854+
855+ DBG("ril_cops_cb: %s, %s, %s, %s", op.name, op.mcc, op.mnc,
856+ registration_tech_to_string(op.tech));
857+
858+ g_free(lalpha);
859+ g_free(salpha);
860+ g_free(numeric);
861+
862+ cb(&error, &op, cbd->data);
863+
864+ return;
865+
866+error:
867+ CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
868+}
869+
870+static void ril_current_operator(struct ofono_netreg *netreg,
871+ ofono_netreg_operator_cb_t cb, void *data)
872+{
873+ struct netreg_data *nd = ofono_netreg_get_data(netreg);
874+ struct cb_data *cbd = cb_data_new(cb, data);
875+
876+ cbd->user = nd;
877+
878+ if (g_ril_send(nd->ril, RIL_REQUEST_OPERATOR, NULL,
879+ 0, ril_cops_cb, cbd, g_free) > 0)
880+ return;
881+
882+ g_free(cbd);
883+
884+ CALLBACK_WITH_FAILURE(cb, NULL, data);
885+}
886+
887+static void ril_cops_list_cb(struct ril_msg *message, gpointer user_data)
888+{
889+ struct cb_data *cbd = user_data;
890+ ofono_netreg_operator_list_cb_t cb = cbd->cb;
891+ struct ofono_network_operator *list;
892+ struct ofono_error error;
893+ struct parcel rilp;
894+ int noperators, i;
895+ gchar *lalpha, *salpha, *numeric, *status;
896+
897+ if (message->error == RIL_E_SUCCESS) {
898+ decode_ril_error(&error, "OK");
899+ } else {
900+ ofono_error("Failed to retrive the list of operators");
901+ goto error;
902+ }
903+
904+ /* Set up Parcel struct for proper parsing */
905+ rilp.data = message->buf;
906+ rilp.size = message->buf_len;
907+ rilp.capacity = message->buf_len;
908+ rilp.offset = 0;
909+
910+ /* Number of operators at the list (4 strings for every operator) */
911+ noperators = parcel_r_int32(&rilp) / 4;
912+ DBG("noperators = %d", noperators);
913+
914+ list = g_try_new0(struct ofono_network_operator, noperators);
915+ if (list == NULL)
916+ goto error;
917+
918+ for (i = 0; i < noperators; i++) {
919+ lalpha = parcel_r_string(&rilp);
920+ salpha = parcel_r_string(&rilp);
921+ numeric = parcel_r_string(&rilp);
922+ status = parcel_r_string(&rilp);
923+
924+ /* Try to use long by default */
925+ if (lalpha) {
926+ strncpy(list[i].name, lalpha,
927+ OFONO_MAX_OPERATOR_NAME_LENGTH);
928+ } else {
929+ strncpy(list[i].name, salpha,
930+ OFONO_MAX_OPERATOR_NAME_LENGTH);
931+ }
932+
933+ extract_mcc_mnc(numeric, list[i].mcc, list[i].mnc);
934+
935+ /* Use GSM as default, as RIL doesn't pass that info to us */
936+ list[i].tech = ACCESS_TECHNOLOGY_GSM;
937+
938+ /* Set the proper status */
939+ if (!strcmp(status, "unknown"))
940+ list[i].status = OPERATOR_STATUS_UNKNOWN;
941+ else if (!strcmp(status, "available"))
942+ list[i].status = OPERATOR_STATUS_AVAILABLE;
943+ else if (!strcmp(status, "current"))
944+ list[i].status = OPERATOR_STATUS_CURRENT;
945+ else if (!strcmp(status, "forbidden"))
946+ list[i].status = OPERATOR_STATUS_FORBIDDEN;
947+
948+ DBG("Operator: %s, %s, %s, status: %s",
949+ list[i].name, list[i].mcc,
950+ list[i].mnc, status);
951+
952+ g_free(lalpha);
953+ g_free(salpha);
954+ g_free(numeric);
955+ g_free(status);
956+ }
957+
958+ cb(&error, noperators, list, cbd->data);
959+
960+ return;
961+
962+error:
963+ CALLBACK_WITH_FAILURE(cb, 0, NULL, cbd->data);
964+}
965+
966+static void ril_list_operators(struct ofono_netreg *netreg,
967+ ofono_netreg_operator_list_cb_t cb, void *data)
968+{
969+ struct netreg_data *nd = ofono_netreg_get_data(netreg);
970+ struct cb_data *cbd = cb_data_new(cb, data);
971+
972+ cbd->user = nd;
973+
974+ if (g_ril_send(nd->ril, RIL_REQUEST_QUERY_AVAILABLE_NETWORKS, NULL,
975+ 0, ril_cops_list_cb, cbd, g_free) > 0)
976+ return;
977+
978+ g_free(cbd);
979+
980+ CALLBACK_WITH_FAILURE(cb, 0, NULL, data);
981+}
982+
983+static void ril_register_cb(struct ril_msg *message, gpointer user_data)
984+{
985+ struct cb_data *cbd = user_data;
986+ ofono_netreg_register_cb_t cb = cbd->cb;
987+ struct ofono_error error;
988+
989+ if (message->error == RIL_E_SUCCESS) {
990+ decode_ril_error(&error, "OK");
991+ } else {
992+ decode_ril_error(&error, "FAIL");
993+ }
994+
995+ cb(&error, cbd->data);
996+}
997+
998+static void ril_register_auto(struct ofono_netreg *netreg,
999+ ofono_netreg_register_cb_t cb, void *data)
1000+{
1001+ struct netreg_data *nd = ofono_netreg_get_data(netreg);
1002+ struct cb_data *cbd = cb_data_new(cb, data);
1003+
1004+ if (g_ril_send(nd->ril, RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC,
1005+ NULL, 0, ril_register_cb, cbd, g_free) > 0)
1006+ return;
1007+
1008+ g_free(cbd);
1009+
1010+ CALLBACK_WITH_FAILURE(cb, data);
1011+}
1012+
1013+static void ril_register_manual(struct ofono_netreg *netreg,
1014+ const char *mcc, const char *mnc,
1015+ ofono_netreg_register_cb_t cb, void *data)
1016+{
1017+ struct netreg_data *nd = ofono_netreg_get_data(netreg);
1018+ struct cb_data *cbd = cb_data_new(cb, data);
1019+ char buf[OFONO_MAX_MCC_LENGTH + OFONO_MAX_MNC_LENGTH + 1];
1020+ struct parcel rilp;
1021+ int ret;
1022+
1023+ parcel_init(&rilp);
1024+
1025+ /* RIL expects a char * specifying MCCMNC of network to select */
1026+ snprintf(buf, sizeof(buf), "%s%s", mcc, mnc);
1027+ parcel_w_string(&rilp, buf);
1028+
1029+ ret = g_ril_send(nd->ril, RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL,
1030+ rilp.data, rilp.size, ril_register_cb,
1031+ cbd, g_free);
1032+ parcel_free(&rilp);
1033+
1034+ /* In case of error free cbd and return the cb with failure */
1035+ if (ret <= 0) {
1036+ g_free(cbd);
1037+ CALLBACK_WITH_FAILURE(cb, data);
1038+ }
1039+}
1040+
1041+static void ril_strength_notify(struct ril_msg *message, gpointer user_data)
1042+{
1043+ struct ofono_netreg *netreg = user_data;
1044+ int strength;
1045+
1046+ g_assert(message->req == RIL_UNSOL_SIGNAL_STRENGTH);
1047+
1048+ strength = ril_util_get_signal(message);
1049+ ofono_netreg_strength_notify(netreg, strength);
1050+
1051+ return;
1052+}
1053+
1054+static void ril_strength_cb(struct ril_msg *message, gpointer user_data)
1055+{
1056+ struct cb_data *cbd = user_data;
1057+ ofono_netreg_strength_cb_t cb = cbd->cb;
1058+ struct ofono_error error;
1059+ int strength;
1060+
1061+ if (message->error == RIL_E_SUCCESS) {
1062+ decode_ril_error(&error, "OK");
1063+ } else {
1064+ ofono_error("Failed to retrive the signal strength");
1065+ goto error;
1066+ }
1067+
1068+ strength = ril_util_get_signal(message);
1069+ cb(&error, strength, cbd->data);
1070+
1071+ return;
1072+
1073+error:
1074+ CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
1075+}
1076+
1077+static void ril_signal_strength(struct ofono_netreg *netreg,
1078+ ofono_netreg_strength_cb_t cb, void *data)
1079+{
1080+ struct netreg_data *nd = ofono_netreg_get_data(netreg);
1081+ struct cb_data *cbd = cb_data_new(cb, data);
1082+
1083+ cbd->user = nd;
1084+
1085+ if (g_ril_send(nd->ril, RIL_REQUEST_SIGNAL_STRENGTH,
1086+ NULL, 0, ril_strength_cb, cbd, g_free) > 0)
1087+ return;
1088+
1089+ g_free(cbd);
1090+
1091+ CALLBACK_WITH_FAILURE(cb, -1, data);
1092+}
1093+
1094+static void ril_nitz_notify(struct ril_msg *message, gpointer user_data)
1095+{
1096+ struct ofono_netreg *netreg = user_data;
1097+ struct netreg_data *nd = ofono_netreg_get_data(netreg);
1098+ struct parcel rilp;
1099+ int year, mon, mday, hour, min, sec, dst, tzi;
1100+ char tzs, tz[4];
1101+ gchar *nitz;
1102+
1103+ if (message->req != RIL_UNSOL_NITZ_TIME_RECEIVED)
1104+ goto error;
1105+
1106+ /* Set up Parcel struct for proper parsing */
1107+ rilp.data = message->buf;
1108+ rilp.size = message->buf_len;
1109+ rilp.capacity = message->buf_len;
1110+ rilp.offset = 0;
1111+
1112+ nitz = parcel_r_string(&rilp);
1113+
1114+ DBG("RIL NITZ: %s", nitz);
1115+
1116+ sscanf(nitz, "%u/%u/%u,%u:%u:%u%c%u,%u", &year, &mon, &mday,
1117+ &hour, &min, &sec, &tzs, &tzi, &dst);
1118+ sprintf(tz, "%c%d", tzs, tzi);
1119+
1120+ nd->time.utcoff = atoi(tz) * 15 * 60;
1121+ nd->time.dst = dst;
1122+ nd->time.sec = sec;
1123+ nd->time.min = min;
1124+ nd->time.hour = hour;
1125+ nd->time.mday = mday;
1126+ nd->time.mon = mon;
1127+ nd->time.year = 2000 + year;
1128+
1129+ ofono_netreg_time_notify(netreg, &nd->time);
1130+
1131+ g_free(nitz);
1132+
1133+ return;
1134+
1135+error:
1136+ ofono_error("Unable to notify ofono about nitz");
1137+}
1138+
1139+static gboolean ril_delayed_register(gpointer user_data)
1140+{
1141+ struct ofono_netreg *netreg = user_data;
1142+ struct netreg_data *nd = ofono_netreg_get_data(netreg);
1143+ ofono_netreg_register(netreg);
1144+
1145+ /* Register for network state changes */
1146+ g_ril_register(nd->ril, RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED,
1147+ ril_network_state_change, netreg);
1148+
1149+ /* Register for network time update reports */
1150+ g_ril_register(nd->ril, RIL_UNSOL_NITZ_TIME_RECEIVED,
1151+ ril_nitz_notify, netreg);
1152+
1153+ /* Register for signal strength changes */
1154+ g_ril_register(nd->ril, RIL_UNSOL_SIGNAL_STRENGTH,
1155+ ril_strength_notify, netreg);
1156+
1157+ /* This makes the timeout a single-shot */
1158+ return FALSE;
1159+}
1160+
1161+static int ril_netreg_probe(struct ofono_netreg *netreg, unsigned int vendor,
1162+ void *data)
1163+{
1164+ GRil *ril = data;
1165+ struct netreg_data *nd;
1166+
1167+ nd = g_new0(struct netreg_data, 1);
1168+
1169+ nd->ril = g_ril_clone(ril);
1170+ nd->vendor = vendor;
1171+ nd->tech = -1;
1172+ nd->time.sec = -1;
1173+ nd->time.min = -1;
1174+ nd->time.hour = -1;
1175+ nd->time.mday = -1;
1176+ nd->time.mon = -1;
1177+ nd->time.year = -1;
1178+ nd->time.dst = 0;
1179+ nd->time.utcoff = 0;
1180+ ofono_netreg_set_data(netreg, nd);
1181+
1182+ /* ofono_netreg_register() needs to be called after
1183+ * the driver has been set in devinfo_create() which
1184+ * calls this function. Most other drivers use a
1185+ * callback after getting some return from the modem
1186+ * itself...
1187+ */
1188+ g_timeout_add_seconds(1, ril_delayed_register, netreg);
1189+
1190+ return 0;
1191+}
1192+
1193+static void ril_netreg_remove(struct ofono_netreg *netreg)
1194+{
1195+ struct netreg_data *nd = ofono_netreg_get_data(netreg);
1196+
1197+ if (nd->nitz_timeout)
1198+ g_source_remove(nd->nitz_timeout);
1199+
1200+ ofono_netreg_set_data(netreg, NULL);
1201+
1202+ g_ril_unref(nd->ril);
1203+ g_free(nd);
1204+}
1205+
1206+static struct ofono_netreg_driver driver = {
1207+ .name = "rilmodem",
1208+ .probe = ril_netreg_probe,
1209+ .remove = ril_netreg_remove,
1210+ .registration_status = ril_registration_status,
1211+ .current_operator = ril_current_operator,
1212+ .list_operators = ril_list_operators,
1213+ .register_auto = ril_register_auto,
1214+ .register_manual = ril_register_manual,
1215+ .strength = ril_signal_strength,
1216+};
1217+
1218+void ril_netreg_init(void)
1219+{
1220+ ofono_netreg_driver_register(&driver);
1221+}
1222+
1223+void ril_netreg_exit(void)
1224+{
1225+ ofono_netreg_driver_unregister(&driver);
1226+}
1227
1228=== added file 'drivers/rilmodem/rilmodem.c'
1229--- drivers/rilmodem/rilmodem.c 1970-01-01 00:00:00 +0000
1230+++ drivers/rilmodem/rilmodem.c 2013-04-09 20:01:20 +0000
1231@@ -0,0 +1,61 @@
1232+/*
1233+ *
1234+ * oFono - Open Source Telephony - RIL Modem Support
1235+ *
1236+ * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
1237+ * Copyright (C) 2012 Canonical Ltd.
1238+ *
1239+ * This program is free software; you can redistribute it and/or modify
1240+ * it under the terms of the GNU General Public License version 2 as
1241+ * published by the Free Software Foundation.
1242+ *
1243+ * This program is distributed in the hope that it will be useful,
1244+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1245+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1246+ * GNU General Public License for more details.
1247+ *
1248+ * You should have received a copy of the GNU General Public License
1249+ * along with this program; if not, write to the Free Software
1250+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1251+ *
1252+ */
1253+
1254+#ifdef HAVE_CONFIG_H
1255+#include <config.h>
1256+#endif
1257+
1258+#include <glib.h>
1259+#include <gril.h>
1260+
1261+#define OFONO_API_SUBJECT_TO_CHANGE
1262+#include <ofono/plugin.h>
1263+#include <ofono/log.h>
1264+
1265+#include "rilmodem.h"
1266+
1267+static int rilmodem_init(void)
1268+{
1269+ DBG("");
1270+
1271+ ril_devinfo_init();
1272+ ril_voicecall_init();
1273+ ril_sms_init();
1274+ ril_netreg_init();
1275+ ril_call_volume_init();
1276+
1277+ return 0;
1278+}
1279+
1280+static void rilmodem_exit(void)
1281+{
1282+ DBG("");
1283+
1284+ ril_devinfo_exit();
1285+ ril_voicecall_exit();
1286+ ril_sms_exit();
1287+ ril_netreg_exit();
1288+ ril_call_volume_exit();
1289+}
1290+
1291+OFONO_PLUGIN_DEFINE(rilmodem, "RIL modem driver", VERSION,
1292+ OFONO_PLUGIN_PRIORITY_DEFAULT, rilmodem_init, rilmodem_exit)
1293
1294=== added file 'drivers/rilmodem/rilmodem.h'
1295--- drivers/rilmodem/rilmodem.h 1970-01-01 00:00:00 +0000
1296+++ drivers/rilmodem/rilmodem.h 2013-04-09 20:01:20 +0000
1297@@ -0,0 +1,38 @@
1298+/*
1299+ *
1300+ * oFono - Open Source Telephony - RIL Modem Support
1301+ *
1302+ * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
1303+ * Copyright (C) 2012 Canonical Ltd.
1304+ *
1305+ * This program is free software; you can redistribute it and/or modify
1306+ * it under the terms of the GNU General Public License version 2 as
1307+ * published by the Free Software Foundation.
1308+ *
1309+ * This program is distributed in the hope that it will be useful,
1310+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1311+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1312+ * GNU General Public License for more details.
1313+ *
1314+ * You should have received a copy of the GNU General Public License
1315+ * along with this program; if not, write to the Free Software
1316+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1317+ *
1318+ */
1319+
1320+#include "rilutil.h"
1321+
1322+extern void ril_devinfo_init(void);
1323+extern void ril_devinfo_exit(void);
1324+
1325+extern void ril_call_volume_init(void);
1326+extern void ril_call_volume_exit(void);
1327+
1328+extern void ril_voicecall_init(void);
1329+extern void ril_voicecall_exit(void);
1330+
1331+extern void ril_sms_init(void);
1332+extern void ril_sms_exit(void);
1333+
1334+extern void ril_netreg_init(void);
1335+extern void ril_netreg_exit(void);
1336
1337=== added file 'drivers/rilmodem/rilutil.c'
1338--- drivers/rilmodem/rilutil.c 1970-01-01 00:00:00 +0000
1339+++ drivers/rilmodem/rilutil.c 2013-04-09 20:01:20 +0000
1340@@ -0,0 +1,372 @@
1341+/*
1342+ *
1343+ * oFono - Open Source Telephony
1344+ *
1345+ * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
1346+ * Copyright (C) 2012 Canonical Ltd.
1347+ *
1348+ * This program is free software; you can redistribute it and/or modify
1349+ * it under the terms of the GNU General Public License version 2 as
1350+ * published by the Free Software Foundation.
1351+ *
1352+ * This program is distributed in the hope that it will be useful,
1353+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1354+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1355+ * GNU General Public License for more details.
1356+ *
1357+ * You should have received a copy of the GNU General Public License
1358+ * along with this program; if not, write to the Free Software
1359+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1360+ *
1361+ */
1362+
1363+#ifdef HAVE_CONFIG_H
1364+#include <config.h>
1365+#endif
1366+
1367+#include <glib.h>
1368+#include <gril.h>
1369+#include <string.h>
1370+#include <stdlib.h>
1371+
1372+#define OFONO_API_SUBJECT_TO_CHANGE
1373+#include <ofono/log.h>
1374+#include <ofono/types.h>
1375+
1376+#include "common.h"
1377+#include "rilutil.h"
1378+#include "parcel.h"
1379+
1380+struct ril_util_sim_state_query {
1381+ GRil *ril;
1382+ guint cpin_poll_source;
1383+ guint cpin_poll_count;
1384+ guint interval;
1385+ guint num_times;
1386+ ril_util_sim_inserted_cb_t cb;
1387+ void *userdata;
1388+ GDestroyNotify destroy;
1389+};
1390+
1391+static gboolean cpin_check(gpointer userdata);
1392+
1393+void decode_ril_error(struct ofono_error *error, const char *final)
1394+{
1395+ if (!strcmp(final, "OK")) {
1396+ error->type = OFONO_ERROR_TYPE_NO_ERROR;
1397+ error->error = 0;
1398+ } else {
1399+ error->type = OFONO_ERROR_TYPE_FAILURE;
1400+ error->error = 0;
1401+ }
1402+}
1403+
1404+gint ril_util_call_compare_by_status(gconstpointer a, gconstpointer b)
1405+{
1406+ const struct ofono_call *call = a;
1407+ int status = GPOINTER_TO_INT(b);
1408+
1409+ if (status != call->status)
1410+ return 1;
1411+
1412+ return 0;
1413+}
1414+
1415+gint ril_util_call_compare_by_phone_number(gconstpointer a, gconstpointer b)
1416+{
1417+ const struct ofono_call *call = a;
1418+ const struct ofono_phone_number *pb = b;
1419+
1420+ return memcmp(&call->phone_number, pb,
1421+ sizeof(struct ofono_phone_number));
1422+}
1423+
1424+gint ril_util_call_compare_by_id(gconstpointer a, gconstpointer b)
1425+{
1426+ const struct ofono_call *call = a;
1427+ unsigned int id = GPOINTER_TO_UINT(b);
1428+
1429+ if (id < call->id)
1430+ return -1;
1431+
1432+ if (id > call->id)
1433+ return 1;
1434+
1435+ return 0;
1436+}
1437+
1438+gint ril_util_call_compare(gconstpointer a, gconstpointer b)
1439+{
1440+ const struct ofono_call *ca = a;
1441+ const struct ofono_call *cb = b;
1442+
1443+ if (ca->id < cb->id)
1444+ return -1;
1445+
1446+ if (ca->id > cb->id)
1447+ return 1;
1448+
1449+ return 0;
1450+}
1451+
1452+static gboolean cpin_check(gpointer userdata)
1453+{
1454+ struct ril_util_sim_state_query *req = userdata;
1455+
1456+ req->cpin_poll_source = 0;
1457+
1458+ return FALSE;
1459+}
1460+
1461+struct ril_util_sim_state_query *ril_util_sim_state_query_new(GRil *ril,
1462+ guint interval, guint num_times,
1463+ ril_util_sim_inserted_cb_t cb,
1464+ void *userdata,
1465+ GDestroyNotify destroy)
1466+{
1467+ struct ril_util_sim_state_query *req;
1468+
1469+ req = g_new0(struct ril_util_sim_state_query, 1);
1470+
1471+ req->ril = ril;
1472+ req->interval = interval;
1473+ req->num_times = num_times;
1474+ req->cb = cb;
1475+ req->userdata = userdata;
1476+ req->destroy = destroy;
1477+
1478+ cpin_check(req);
1479+
1480+ return req;
1481+}
1482+
1483+void ril_util_sim_state_query_free(struct ril_util_sim_state_query *req)
1484+{
1485+ if (req == NULL)
1486+ return;
1487+
1488+ if (req->cpin_poll_source > 0)
1489+ g_source_remove(req->cpin_poll_source);
1490+
1491+ if (req->destroy)
1492+ req->destroy(req->userdata);
1493+
1494+ g_free(req);
1495+}
1496+
1497+GSList *ril_util_parse_clcc(struct ril_msg *message)
1498+{
1499+ struct ofono_call *call;
1500+ struct parcel rilp;
1501+ GSList *l = NULL;
1502+ int num, i;
1503+ gchar *number, *name;
1504+
1505+ /* Set up Parcel struct for proper parsing */
1506+ rilp.data = message->buf;
1507+ rilp.size = message->buf_len;
1508+ rilp.capacity = message->buf_len;
1509+ rilp.offset = 0;
1510+
1511+ /* Number of RIL_Call structs */
1512+ num = parcel_r_int32(&rilp);
1513+ for (i = 0; i < num; i++) {
1514+ call = g_try_new(struct ofono_call, 1);
1515+ if (call == NULL)
1516+ break;
1517+
1518+ ofono_call_init(call);
1519+ call->status = parcel_r_int32(&rilp);
1520+ call->id = parcel_r_int32(&rilp);
1521+ call->phone_number.type = parcel_r_int32(&rilp);
1522+ parcel_r_int32(&rilp); /* isMpty */
1523+ parcel_r_int32(&rilp); /* isMT */
1524+ parcel_r_int32(&rilp); /* als */
1525+ call->type = parcel_r_int32(&rilp); /* isVoice */
1526+ parcel_r_int32(&rilp); /* isVoicePrivacy */
1527+ number = parcel_r_string(&rilp);
1528+ if (number) {
1529+ strncpy(call->phone_number.number, number,
1530+ OFONO_MAX_PHONE_NUMBER_LENGTH);
1531+ g_free(number);
1532+ }
1533+ parcel_r_int32(&rilp); /* numberPresentation */
1534+ name = parcel_r_string(&rilp);
1535+ if (name) {
1536+ strncpy(call->name, name,
1537+ OFONO_MAX_CALLER_NAME_LENGTH);
1538+ g_free(name);
1539+ }
1540+ parcel_r_int32(&rilp); /* namePresentation */
1541+ parcel_r_int32(&rilp); /* uusInfo */
1542+
1543+ if (strlen(call->phone_number.number) > 0)
1544+ call->clip_validity = 0;
1545+ else
1546+ call->clip_validity = 2;
1547+
1548+ DBG("Adding call - id: %d, status: %d, type: %d, number: %s, name: %s",
1549+ call->id, call->status, call->type,
1550+ call->phone_number.number, call->name);
1551+
1552+ l = g_slist_insert_sorted(l, call, ril_util_call_compare);
1553+ }
1554+
1555+ return l;
1556+}
1557+
1558+gboolean ril_util_parse_reg(struct ril_msg *message, int *status,
1559+ int *lac, int *ci, int *tech)
1560+{
1561+ struct parcel rilp;
1562+ gchar *sstatus, *slac, *sci, *stech;
1563+
1564+ /* Set up Parcel struct for proper parsing */
1565+ rilp.data = message->buf;
1566+ rilp.size = message->buf_len;
1567+ rilp.capacity = message->buf_len;
1568+ rilp.offset = 0;
1569+
1570+ /* Size of char ** */
1571+ if (parcel_r_int32(&rilp) == 0)
1572+ return FALSE;
1573+
1574+ sstatus = parcel_r_string(&rilp);
1575+ slac = parcel_r_string(&rilp);
1576+ sci = parcel_r_string(&rilp);
1577+ stech = parcel_r_string(&rilp);
1578+
1579+ DBG("RIL reg - status: %s, lac: %s, ci: %s, radio tech: %s",
1580+ sstatus, slac, sci, stech);
1581+
1582+ if (status)
1583+ *status = atoi(sstatus);
1584+ if (lac) {
1585+ if (slac)
1586+ *lac = strtol(slac, NULL, 16);
1587+ else
1588+ *lac = -1;
1589+ }
1590+ if (ci) {
1591+ if (sci)
1592+ *ci = strtol(sci, NULL, 16);
1593+ else
1594+ *ci = -1;
1595+ }
1596+ if (tech) {
1597+ switch(atoi(stech)) {
1598+ case RADIO_TECH_UNKNOWN:
1599+ *tech = -1;
1600+ break;
1601+ case RADIO_TECH_GPRS:
1602+ *tech = ACCESS_TECHNOLOGY_GSM;
1603+ break;
1604+ case RADIO_TECH_EDGE:
1605+ *tech = ACCESS_TECHNOLOGY_GSM_EGPRS;
1606+ break;
1607+ case RADIO_TECH_UMTS:
1608+ *tech = ACCESS_TECHNOLOGY_UTRAN;
1609+ break;
1610+ case RADIO_TECH_HSDPA:
1611+ *tech = ACCESS_TECHNOLOGY_UTRAN_HSDPA;
1612+ break;
1613+ case RADIO_TECH_HSUPA:
1614+ *tech = ACCESS_TECHNOLOGY_UTRAN_HSUPA;
1615+ break;
1616+ case RADIO_TECH_HSPA:
1617+ *tech = ACCESS_TECHNOLOGY_UTRAN_HSDPA_HSUPA;
1618+ break;
1619+ default:
1620+ *tech = -1;
1621+ }
1622+ }
1623+
1624+ /* Free our parcel handlers */
1625+ g_free(sstatus);
1626+ g_free(slac);
1627+ g_free(sci);
1628+ g_free(stech);
1629+
1630+ return TRUE;
1631+}
1632+
1633+gint ril_util_parse_sms_response(struct ril_msg *message)
1634+{
1635+ struct parcel rilp;
1636+ int error, mr;
1637+ char *ack_pdu;
1638+
1639+ /* Set up Parcel struct for proper parsing */
1640+ rilp.data = message->buf;
1641+ rilp.size = message->buf_len;
1642+ rilp.capacity = message->buf_len;
1643+ rilp.offset = 0;
1644+
1645+ /* TP-Message-Reference for GSM/
1646+ * BearerData MessageId for CDMA
1647+ */
1648+ mr = parcel_r_int32(&rilp);
1649+ ack_pdu = parcel_r_int32(&rilp);
1650+ error = parcel_r_int32(&rilp);
1651+
1652+ DBG("SMS_Response mr: %d, ackPDU: %d, error: %d",
1653+ mr, ack_pdu, error);
1654+
1655+ return mr;
1656+}
1657+
1658+gint ril_util_get_signal(struct ril_msg *message)
1659+{
1660+ struct parcel rilp;
1661+ int gw_signal, cdma_dbm, evdo_dbm, lte_signal;
1662+
1663+ /* Set up Parcel struct for proper parsing */
1664+ rilp.data = message->buf;
1665+ rilp.size = message->buf_len;
1666+ rilp.capacity = message->buf_len;
1667+ rilp.offset = 0;
1668+
1669+ /* RIL_SignalStrength_v6 */
1670+ /* GW_SignalStrength */
1671+ gw_signal = parcel_r_int32(&rilp);
1672+ parcel_r_int32(&rilp); /* bitErrorRate */
1673+
1674+ /* CDMA_SignalStrength */
1675+ cdma_dbm = parcel_r_int32(&rilp);
1676+ parcel_r_int32(&rilp); /* ecio */
1677+
1678+ /* EVDO_SignalStrength */
1679+ evdo_dbm = parcel_r_int32(&rilp);
1680+ parcel_r_int32(&rilp); /* ecio */
1681+ parcel_r_int32(&rilp); /* signalNoiseRatio */
1682+
1683+ /* LTE_SignalStrength */
1684+ lte_signal = parcel_r_int32(&rilp);
1685+ parcel_r_int32(&rilp); /* rsrp */
1686+ parcel_r_int32(&rilp); /* rsrq */
1687+ parcel_r_int32(&rilp); /* rssnr */
1688+ parcel_r_int32(&rilp); /* cqi */
1689+
1690+ DBG("RIL SignalStrength - gw: %d, cdma: %d, evdo: %d, lte: %d",
1691+ gw_signal, cdma_dbm, evdo_dbm, lte_signal);
1692+
1693+ /* Return the first valid one */
1694+ if ((gw_signal != 99) && (gw_signal != -1))
1695+ return (gw_signal * 100) / 31;
1696+ if ((lte_signal != 99) && (lte_signal != -1))
1697+ return (lte_signal * 100) / 31;
1698+
1699+ /* In case of dbm, return the value directly */
1700+ if (cdma_dbm != -1) {
1701+ if (cdma_dbm > 100)
1702+ cdma_dbm = 100;
1703+ return cdma_dbm;
1704+ }
1705+ if (evdo_dbm != -1) {
1706+ if (evdo_dbm > 100)
1707+ evdo_dbm = 100;
1708+ return evdo_dbm;
1709+ }
1710+
1711+ return -1;
1712+}
1713
1714=== added file 'drivers/rilmodem/rilutil.h'
1715--- drivers/rilmodem/rilutil.h 1970-01-01 00:00:00 +0000
1716+++ drivers/rilmodem/rilutil.h 2013-04-09 20:01:20 +0000
1717@@ -0,0 +1,125 @@
1718+/*
1719+ *
1720+ * oFono - Open Source Telephony
1721+ *
1722+ * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
1723+ * Copyright (C) 2012 Canonical Ltd.
1724+ *
1725+ * This program is free software; you can redistribute it and/or modify
1726+ * it under the terms of the GNU General Public License version 2 as
1727+ * published by the Free Software Foundation.
1728+ *
1729+ * This program is distributed in the hope that it will be useful,
1730+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1731+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1732+ * GNU General Public License for more details.
1733+ *
1734+ * You should have received a copy of the GNU General Public License
1735+ * along with this program; if not, write to the Free Software
1736+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1737+ *
1738+ */
1739+
1740+enum ril_util_sms_store {
1741+ RIL_UTIL_SMS_STORE_SM = 0,
1742+ RIL_UTIL_SMS_STORE_ME = 1,
1743+ RIL_UTIL_SMS_STORE_MT = 2,
1744+ RIL_UTIL_SMS_STORE_SR = 3,
1745+ RIL_UTIL_SMS_STORE_BM = 4,
1746+};
1747+
1748+/* 3GPP TS 27.007 Release 8 Section 5.5 */
1749+enum at_util_charset {
1750+ RIL_UTIL_CHARSET_GSM = 0x1,
1751+ RIL_UTIL_CHARSET_HEX = 0x2,
1752+ RIL_UTIL_CHARSET_IRA = 0x4,
1753+ RIL_UTIL_CHARSET_PCCP437 = 0x8,
1754+ RIL_UTIL_CHARSET_PCDN = 0x10,
1755+ RIL_UTIL_CHARSET_UCS2 = 0x20,
1756+ RIL_UTIL_CHARSET_UTF8 = 0x40,
1757+ RIL_UTIL_CHARSET_8859_1 = 0x80,
1758+ RIL_UTIL_CHARSET_8859_2 = 0x100,
1759+ RIL_UTIL_CHARSET_8859_3 = 0x200,
1760+ RIL_UTIL_CHARSET_8859_4 = 0x400,
1761+ RIL_UTIL_CHARSET_8859_5 = 0x800,
1762+ RIL_UTIL_CHARSET_8859_6 = 0x1000,
1763+ RIL_UTIL_CHARSET_8859_C = 0x2000,
1764+ RIL_UTIL_CHARSET_8859_A = 0x4000,
1765+ RIL_UTIL_CHARSET_8859_G = 0x8000,
1766+ RIL_UTIL_CHARSET_8859_H = 0x10000,
1767+};
1768+
1769+typedef void (*ril_util_sim_inserted_cb_t)(gboolean present, void *userdata);
1770+
1771+void decode_ril_error(struct ofono_error *error, const char *final);
1772+gint ril_util_call_compare_by_status(gconstpointer a, gconstpointer b);
1773+gint ril_util_call_compare_by_phone_number(gconstpointer a, gconstpointer b);
1774+gint ril_util_call_compare_by_id(gconstpointer a, gconstpointer b);
1775+gint ril_util_call_compare(gconstpointer a, gconstpointer b);
1776+
1777+struct ril_util_sim_state_query *ril_util_sim_state_query_new(GRil *ril,
1778+ guint interval, guint num_times,
1779+ ril_util_sim_inserted_cb_t cb,
1780+ void *userdata,
1781+ GDestroyNotify destroy);
1782+void ril_util_sim_state_query_free(struct ril_util_sim_state_query *req);
1783+
1784+GSList *ril_util_parse_clcc(struct ril_msg *message);
1785+
1786+gboolean ril_util_parse_reg(struct ril_msg *message, int *status,
1787+ int *lac, int *ci, int *tech);
1788+
1789+gint ril_util_parse_sms_response(struct ril_msg *message);
1790+
1791+gint ril_util_get_signal(struct ril_msg *message);
1792+
1793+struct cb_data {
1794+ void *cb;
1795+ void *data;
1796+ void *user;
1797+};
1798+
1799+static inline struct cb_data *cb_data_new(void *cb, void *data)
1800+{
1801+ struct cb_data *ret;
1802+
1803+ ret = g_new0(struct cb_data, 1);
1804+ ret->cb = cb;
1805+ ret->data = data;
1806+
1807+ return ret;
1808+}
1809+
1810+static inline int ril_util_convert_signal_strength(int strength)
1811+{
1812+ int result;
1813+
1814+ if (strength == 99)
1815+ result = -1;
1816+ else
1817+ result = (strength * 100) / 31;
1818+
1819+ return result;
1820+}
1821+
1822+#define DECLARE_FAILURE(e) \
1823+ struct ofono_error e; \
1824+ e.type = OFONO_ERROR_TYPE_FAILURE; \
1825+ e.error = 0 \
1826+
1827+#define CALLBACK_WITH_FAILURE(cb, args...) \
1828+ do { \
1829+ struct ofono_error cb_e; \
1830+ cb_e.type = OFONO_ERROR_TYPE_FAILURE; \
1831+ cb_e.error = 0; \
1832+ \
1833+ cb(&cb_e, ##args); \
1834+ } while (0) \
1835+
1836+#define CALLBACK_WITH_SUCCESS(f, args...) \
1837+ do { \
1838+ struct ofono_error e; \
1839+ e.type = OFONO_ERROR_TYPE_NO_ERROR; \
1840+ e.error = 0; \
1841+ f(&e, ##args); \
1842+ } while (0)
1843
1844=== added file 'drivers/rilmodem/sms.c'
1845--- drivers/rilmodem/sms.c 1970-01-01 00:00:00 +0000
1846+++ drivers/rilmodem/sms.c 2013-04-09 20:01:20 +0000
1847@@ -0,0 +1,357 @@
1848+/*
1849+ *
1850+ * oFono - Open Source Telephony - RIL Modem Support
1851+ *
1852+ * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
1853+ * Copyright (C) 2012 Canonical Ltd.
1854+ *
1855+ * This program is free software; you can redistribute it and/or modify
1856+ * it under the terms of the GNU General Public License version 2 as
1857+ * published by the Free Software Foundation.
1858+ *
1859+ * This program is distributed in the hope that it will be useful,
1860+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1861+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1862+ * GNU General Public License for more details.
1863+ *
1864+ * You should have received a copy of the GNU General Public License
1865+ * along with this program; if not, write to the Free Software
1866+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1867+ *
1868+ */
1869+
1870+#ifdef HAVE_CONFIG_H
1871+#include <config.h>
1872+#endif
1873+
1874+#define _GNU_SOURCE
1875+#include <ctype.h>
1876+#include <string.h>
1877+#include <stdlib.h>
1878+#include <stdio.h>
1879+
1880+#include <glib.h>
1881+#include <gril.h>
1882+#include <parcel.h>
1883+
1884+#include <ofono/log.h>
1885+#include <ofono/modem.h>
1886+#include <ofono/sms.h>
1887+#include "smsutil.h"
1888+#include "util.h"
1889+
1890+#include "rilmodem.h"
1891+
1892+struct sms_data {
1893+ GRil *ril;
1894+ unsigned int vendor;
1895+};
1896+
1897+static void sms_debug(const gchar *str, gpointer user_data)
1898+{
1899+ const char *prefix = user_data;
1900+
1901+ ofono_info("%s%s", prefix, str);
1902+}
1903+
1904+static void ril_csca_set(struct ofono_sms *sms,
1905+ const struct ofono_phone_number *sca,
1906+ ofono_sms_sca_set_cb_t cb, void *user_data)
1907+{
1908+ /* TODO:
1909+ *
1910+ * (1) Need to determine if RIL supports setting the
1911+ * SMSC number.
1912+ *
1913+ * (2) In the short term, this function should return
1914+ * a 'not-supported' error.
1915+ */
1916+
1917+ DBG("");
1918+
1919+ CALLBACK_WITH_FAILURE(cb, user_data);
1920+}
1921+
1922+static void ril_csca_query_cb(gboolean ok, gpointer user_data)
1923+{
1924+ struct cb_data *cbd = user_data;
1925+ ofono_sms_sca_query_cb_t cb = cbd->cb;
1926+ struct ofono_error error;
1927+ struct ofono_phone_number sca;
1928+
1929+ /* For now setup dummy number */
1930+ const char *number = "6176666666";
1931+
1932+ if (number[0] == '+') {
1933+ number = number + 1;
1934+ sca.type = 145;
1935+ } else {
1936+ sca.type = 129;
1937+ }
1938+
1939+ strncpy(sca.number, number, OFONO_MAX_PHONE_NUMBER_LENGTH);
1940+ sca.number[OFONO_MAX_PHONE_NUMBER_LENGTH] = '\0';
1941+
1942+ DBG("csca_query_cb: %s, %d", sca.number, sca.type);
1943+
1944+ cb(&error, &sca, cbd->data);
1945+
1946+ return;
1947+}
1948+
1949+static void ril_csca_query(struct ofono_sms *sms, ofono_sms_sca_query_cb_t cb,
1950+ void *user_data)
1951+{
1952+ /* TODO:
1953+ *
1954+ * (1) Need to determine if RIL supports querying the
1955+ * SMSC number.
1956+ *
1957+ * (2) In the short term, this function should return
1958+ * a 'not-supported' error.
1959+ */
1960+
1961+ CALLBACK_WITH_FAILURE(cb, NULL, user_data);
1962+}
1963+
1964+static void submit_sms_cb(struct ril_msg *message, gpointer user_data)
1965+{
1966+ struct cb_data *cbd = user_data;
1967+ struct ofono_error error;
1968+ ofono_sms_submit_cb_t cb = cbd->cb;
1969+ int mr;
1970+
1971+ if (message->error == RIL_E_SUCCESS) {
1972+ decode_ril_error(&error, "OK");
1973+ } else {
1974+ decode_ril_error(&error, "FAIL");
1975+ }
1976+
1977+ mr = ril_util_parse_sms_response(message);
1978+
1979+ cb(&error, mr, cbd->data);
1980+}
1981+
1982+static void ril_cmgs(struct ofono_sms *sms, const unsigned char *pdu,
1983+ int pdu_len, int tpdu_len, int mms,
1984+ ofono_sms_submit_cb_t cb, void *user_data)
1985+{
1986+ struct sms_data *data = ofono_sms_get_data(sms);
1987+ struct cb_data *cbd = cb_data_new(cb, user_data);
1988+ struct parcel rilp;
1989+ char *tpdu;
1990+ int ret, smsc_len;
1991+
1992+ DBG("pdu_len: %d, tpdu_len: %d mms: %d", pdu_len, tpdu_len, mms);
1993+ g_ril_util_debug_hexdump(FALSE, pdu, pdu_len, sms_debug, "sms-pdu: ");
1994+
1995+ /* TODO: if (mms) { ... } */
1996+
1997+ parcel_init(&rilp);
1998+ parcel_w_int32(&rilp, 2); /* Number of strings */
1999+
2000+ /* SMSC address:
2001+ *
2002+ * smsc_len == 1, then zero-length SMSC was spec'd
2003+ * RILD expects a NULL string in this case instead
2004+ * of a zero-length string.
2005+ */
2006+ smsc_len = pdu_len - tpdu_len;
2007+ if (smsc_len > 1) {
2008+ /* TODO: encode SMSC & write to parcel */
2009+ DBG("SMSC address specified (smsc_len %d); NOT-IMPLEMENTED", smsc_len);
2010+ }
2011+
2012+ parcel_w_string(&rilp, NULL); /* SMSC address; NULL == default */
2013+
2014+ /* TPDU:
2015+ *
2016+ * 'pdu' is a raw hexadecimal string
2017+ * encode_hex() turns it into an ASCII/hex UTF8 buffer
2018+ * parcel_w_string() encodes utf8 -> utf16
2019+ */
2020+ tpdu = encode_hex(pdu + smsc_len, tpdu_len, 0);
2021+ g_ril_util_debug_hexdump(FALSE, (guchar *) tpdu, (tpdu_len * 2),
2022+ sms_debug, "tpdu: ");
2023+
2024+ parcel_w_string(&rilp, tpdu);
2025+
2026+ /* Dump the entire parcel */
2027+ g_ril_util_debug_hexdump(FALSE, (guchar *) rilp.data, rilp.size,
2028+ sms_debug, "sms-encoded-buf: ");
2029+ ret = g_ril_send(data->ril,
2030+ RIL_REQUEST_SEND_SMS,
2031+ rilp.data,
2032+ rilp.size,
2033+ submit_sms_cb, cbd, g_free);
2034+
2035+ parcel_free(&rilp);
2036+
2037+ if (ret <= 0) {
2038+ g_free(cbd);
2039+ CALLBACK_WITH_FAILURE(cb, -1, data);
2040+ }
2041+}
2042+
2043+static void ril_cgsms_set(struct ofono_sms *sms, int bearer,
2044+ ofono_sms_bearer_set_cb_t cb, void *user_data)
2045+{
2046+ /* TODO: same as csca_set */
2047+ DBG("");
2048+
2049+ CALLBACK_WITH_FAILURE(cb, user_data);
2050+}
2051+
2052+static void ril_cgsms_query(struct ofono_sms *sms,
2053+ ofono_sms_bearer_query_cb_t cb, void *user_data)
2054+{
2055+ /* TODO: same as csca_query */
2056+ DBG("");
2057+
2058+ CALLBACK_WITH_FAILURE(cb, -1, user_data);
2059+}
2060+
2061+static void ril_sms_notify(struct ril_msg *message, gpointer user_data)
2062+{
2063+ struct ofono_sms *sms = user_data;
2064+ struct sms_data *data = ofono_sms_get_data(sms);
2065+ struct parcel rilp;
2066+ char *ril_pdu;
2067+ int ril_pdu_len;
2068+ long ril_buf_len;
2069+ guchar *ril_data;
2070+
2071+ DBG("req: %d; data_len: %d", message->req, message->buf_len);
2072+
2073+ if (message->req != RIL_UNSOL_RESPONSE_NEW_SMS)
2074+ goto error;
2075+
2076+ /* Set up Parcel struct for proper parsing */
2077+ rilp.data = message->buf;
2078+ rilp.size = message->buf_len;
2079+ rilp.capacity = message->buf_len;
2080+ rilp.offset = 0;
2081+
2082+ g_ril_util_debug_hexdump(FALSE, (guchar *) message->buf,
2083+ message->buf_len, sms_debug, "sms-notify: ");
2084+
2085+ ril_pdu = parcel_r_string(&rilp);
2086+ if (ril_pdu == NULL)
2087+ goto error;
2088+
2089+ ril_pdu_len = strlen(ril_pdu);
2090+
2091+ DBG("ril_pdu_len is %d", ril_pdu_len);
2092+ ril_data = decode_hex(ril_pdu, ril_pdu_len, &ril_buf_len, -1);
2093+ if (ril_data == NULL)
2094+ goto error;
2095+
2096+ g_ril_util_debug_hexdump(FALSE, ril_data,
2097+ ril_buf_len,
2098+ sms_debug,
2099+ "sms-notify-decoded: ");
2100+
2101+ /* Last parameter is 'tpdu_len' ( substract SMSC length ) */
2102+ ofono_sms_deliver_notify(sms, ril_data,
2103+ ril_buf_len,
2104+ ril_buf_len - 8);
2105+
2106+ /* Re-use rilp, so initilize */
2107+ parcel_init(&rilp);
2108+ parcel_w_int32(&rilp, 2); /* Number of int32 values in array */
2109+ parcel_w_int32(&rilp, 1); /* Successful receipt */
2110+ parcel_w_int32(&rilp, 0); /* error code */
2111+
2112+ /* TODO: should ACK be sent for either of the error cases? */
2113+
2114+ /* ACK the incoming NEW_SMS; ignore response so no cb needed */
2115+ g_ril_send(data->ril, RIL_REQUEST_SMS_ACKNOWLEDGE,
2116+ rilp.data,
2117+ rilp.size,
2118+ NULL, NULL, NULL);
2119+
2120+ parcel_free(&rilp);
2121+ return;
2122+
2123+error:
2124+ ofono_error("Unable to parse NEW_SMS notification");
2125+}
2126+
2127+static gboolean ril_delayed_register(gpointer user_data)
2128+{
2129+ struct ofono_sms *sms = user_data;
2130+ struct sms_data *data = ofono_sms_get_data(sms);
2131+
2132+ DBG("");
2133+ ofono_sms_register(sms);
2134+
2135+ /* register to receive INCOMING_SMS */
2136+ g_ril_register(data->ril, RIL_UNSOL_RESPONSE_NEW_SMS,
2137+ ril_sms_notify, sms);
2138+
2139+ DBG("registered NEW_SMS callback");
2140+
2141+ /* This makes the timeout a single-shot */
2142+ return FALSE;
2143+}
2144+
2145+static int ril_sms_probe(struct ofono_sms *sms, unsigned int vendor,
2146+ void *user)
2147+{
2148+ GRil *ril = user;
2149+ struct sms_data *data;
2150+
2151+ DBG("");
2152+
2153+ data = g_new0(struct sms_data, 1);
2154+ data->ril = g_ril_clone(ril);
2155+ data->vendor = vendor;
2156+
2157+ ofono_sms_set_data(sms, data);
2158+
2159+ /* ofono_devinfo_register() needs to be called after
2160+ * the driver has been set in devinfo_create() which
2161+ * calls this function. Most other drivers use a
2162+ * callback after getting some return from the modem
2163+ * itself...
2164+ */
2165+ g_timeout_add_seconds(2, ril_delayed_register, sms);
2166+
2167+ return 0;
2168+}
2169+
2170+static void ril_sms_remove(struct ofono_sms *sms)
2171+{
2172+ struct sms_data *data = ofono_sms_get_data(sms);
2173+
2174+ DBG("");
2175+
2176+ g_ril_unref(data->ril);
2177+ g_free(data);
2178+
2179+ ofono_sms_set_data(sms, NULL);
2180+}
2181+
2182+static struct ofono_sms_driver driver = {
2183+ .name = "rilmodem",
2184+ .probe = ril_sms_probe,
2185+ .remove = ril_sms_remove,
2186+ .sca_query = ril_csca_query,
2187+ .sca_set = ril_csca_set,
2188+ .submit = ril_cmgs,
2189+ .bearer_query = NULL, /* FIXME: needs investigation. */
2190+ .bearer_set = NULL,
2191+};
2192+
2193+void ril_sms_init(void)
2194+{
2195+ DBG("");
2196+ if (ofono_sms_driver_register(&driver))
2197+ DBG("ofono_sms_driver_register failed!");
2198+}
2199+
2200+void ril_sms_exit(void)
2201+{
2202+ DBG("");
2203+ ofono_sms_driver_unregister(&driver);
2204+}
2205
2206=== added file 'drivers/rilmodem/voicecall.c'
2207--- drivers/rilmodem/voicecall.c 1970-01-01 00:00:00 +0000
2208+++ drivers/rilmodem/voicecall.c 2013-04-09 20:01:20 +0000
2209@@ -0,0 +1,537 @@
2210+/*
2211+ *
2212+ * oFono - Open Source Telephony
2213+ *
2214+ * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
2215+ * Copyright (C) 2012 Canonical Ltd.
2216+ *
2217+ * This program is free software; you can redistribute it and/or modify
2218+ * it under the terms of the GNU General Public License version 2 as
2219+ * published by the Free Software Foundation.
2220+ *
2221+ * This program is distributed in the hope that it will be useful,
2222+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2223+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2224+ * GNU General Public License for more details.
2225+ *
2226+ * You should have received a copy of the GNU General Public License
2227+ * along with this program; if not, write to the Free Software
2228+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2229+ *
2230+ */
2231+
2232+#ifdef HAVE_CONFIG_H
2233+#include <config.h>
2234+#endif
2235+
2236+#define _GNU_SOURCE
2237+#include <string.h>
2238+#include <stdlib.h>
2239+#include <stdio.h>
2240+#include <errno.h>
2241+
2242+#include <glib.h>
2243+
2244+/* For AudioFlinger settings */
2245+#include <waudio.h>
2246+
2247+#include <ofono/log.h>
2248+#include <ofono/modem.h>
2249+#include <ofono/voicecall.h>
2250+
2251+#include "gril.h"
2252+#include "grilutil.h"
2253+
2254+#include "common.h"
2255+
2256+#include "rilmodem.h"
2257+#include "parcel.h"
2258+
2259+/* Amount of ms we wait between CLCC calls */
2260+#define POLL_CLCC_INTERVAL 300
2261+
2262+/* When +VTD returns 0, an unspecified manufacturer-specific delay is used */
2263+#define TONE_DURATION 1000
2264+
2265+#define FLAG_NEED_CLIP 1
2266+
2267+struct voicecall_data {
2268+ GSList *calls;
2269+ unsigned int local_release;
2270+ unsigned int clcc_source;
2271+ GRil *ril;
2272+ unsigned int vendor;
2273+ unsigned int tone_duration;
2274+ guint vts_source;
2275+ unsigned int vts_delay;
2276+ unsigned char flags;
2277+};
2278+
2279+struct release_id_req {
2280+ struct ofono_voicecall *vc;
2281+ ofono_voicecall_cb_t cb;
2282+ void *data;
2283+ int id;
2284+};
2285+
2286+struct change_state_req {
2287+ struct ofono_voicecall *vc;
2288+ ofono_voicecall_cb_t cb;
2289+ void *data;
2290+ int affected_types;
2291+};
2292+
2293+static void audioflinger_set_call_mode()
2294+{
2295+ char parameter[20];
2296+ int i;
2297+
2298+ /* Set the call mode in AudioFlinger */
2299+ DBG("Setting AudioFlinger to call state");
2300+ AudioSystem_setMode(AUDIO_MODE_IN_CALL);
2301+
2302+ DBG("Setting sound route to earpiece");
2303+ sprintf(parameter, "routing=%d", AUDIO_DEVICE_OUT_EARPIECE);
2304+
2305+ /* Try the first 3 threads, as this is not fixed and there's no easy
2306+ * way to retrieve the default thread/output from Android */
2307+ for (i = 1; i <= 3; i++) {
2308+ if (AudioSystem_setParameters(i, parameter) >= 0)
2309+ break;
2310+ }
2311+}
2312+
2313+static void audioflinger_set_normal_mode()
2314+{
2315+ char parameter[20];
2316+ int i;
2317+
2318+ DBG("Setting AudioFlinger to normal mode");
2319+ AudioSystem_setMode(AUDIO_MODE_NORMAL);
2320+
2321+ DBG("Setting sound route back to speaker");
2322+
2323+ /* Get device back to speaker mode, as by default in_call
2324+ * mode sets up device out to earpiece */
2325+ sprintf(parameter, "routing=%d", AUDIO_DEVICE_OUT_SPEAKER);
2326+
2327+ /* Try the first 3 threads, as this is not fixed and there's no easy
2328+ * way to retrieve the default thread/output from Android */
2329+ for (i = 1; i <= 3; i++) {
2330+ if (AudioSystem_setParameters(i, parameter) >= 0)
2331+ break;
2332+ }
2333+}
2334+
2335+static void clcc_poll_cb(struct ril_msg *message, gpointer user_data)
2336+{
2337+ struct ofono_voicecall *vc = user_data;
2338+ struct voicecall_data *vd = ofono_voicecall_get_data(vc);
2339+ GSList *calls;
2340+ GSList *n, *o;
2341+ struct ofono_call *nc, *oc;
2342+
2343+ if (message->error != RIL_E_SUCCESS) {
2344+ ofono_error("We are polling CLCC and received an error");
2345+ ofono_error("All bets are off for call management");
2346+ return;
2347+ }
2348+
2349+ calls = ril_util_parse_clcc(message);
2350+
2351+ n = calls;
2352+ o = vd->calls;
2353+
2354+ while (n || o) {
2355+ nc = n ? n->data : NULL;
2356+ oc = o ? o->data : NULL;
2357+
2358+ if (oc && (nc == NULL || (nc->id > oc->id))) {
2359+ enum ofono_disconnect_reason reason;
2360+
2361+ if (vd->local_release & (1 << oc->id))
2362+ reason = OFONO_DISCONNECT_REASON_LOCAL_HANGUP;
2363+ else
2364+ reason = OFONO_DISCONNECT_REASON_REMOTE_HANGUP;
2365+
2366+ if (oc->type)
2367+ ofono_voicecall_disconnected(vc, oc->id,
2368+ reason, NULL);
2369+
2370+ o = o->next;
2371+ } else if (nc && (oc == NULL || (nc->id < oc->id))) {
2372+ /* new call, signal it */
2373+ if (nc->type)
2374+ ofono_voicecall_notify(vc, nc);
2375+
2376+ n = n->next;
2377+ } else {
2378+ /*
2379+ * Always use the clip_validity from old call
2380+ * the only place this is truly told to us is
2381+ * in the CLIP notify, the rest are fudged
2382+ * anyway. Useful when RING, CLIP is used,
2383+ * and we're forced to use CLCC and clip_validity
2384+ * is 1
2385+ */
2386+ if (oc->clip_validity == 1)
2387+ nc->clip_validity = oc->clip_validity;
2388+
2389+ nc->cnap_validity = oc->cnap_validity;
2390+
2391+ /*
2392+ * CDIP doesn't arrive as part of CLCC, always
2393+ * re-use from the old call
2394+ */
2395+ memcpy(&nc->called_number, &oc->called_number,
2396+ sizeof(oc->called_number));
2397+
2398+ /*
2399+ * If the CLIP is not provided and the CLIP never
2400+ * arrives, or RING is used, then signal the call
2401+ * here
2402+ */
2403+ if (nc->status == CALL_STATUS_INCOMING &&
2404+ (vd->flags & FLAG_NEED_CLIP)) {
2405+ if (nc->type)
2406+ ofono_voicecall_notify(vc, nc);
2407+
2408+ vd->flags &= ~FLAG_NEED_CLIP;
2409+ } else if (memcmp(nc, oc, sizeof(*nc)) && nc->type)
2410+ ofono_voicecall_notify(vc, nc);
2411+
2412+ n = n->next;
2413+ o = o->next;
2414+ }
2415+ }
2416+
2417+ /* No other calls, get audioflinger into normal state */
2418+ if (vd->calls && !calls) {
2419+ audioflinger_set_normal_mode();
2420+ }
2421+
2422+ g_slist_foreach(vd->calls, (GFunc) g_free, NULL);
2423+ g_slist_free(vd->calls);
2424+
2425+ vd->calls = calls;
2426+ vd->local_release = 0;
2427+}
2428+
2429+static gboolean poll_clcc(gpointer user_data)
2430+{
2431+ struct ofono_voicecall *vc = user_data;
2432+ struct voicecall_data *vd = ofono_voicecall_get_data(vc);
2433+
2434+ g_ril_send(vd->ril, RIL_REQUEST_GET_CURRENT_CALLS, NULL,
2435+ 0, clcc_poll_cb, vc, NULL);
2436+
2437+ vd->clcc_source = 0;
2438+
2439+ return FALSE;
2440+}
2441+
2442+static void generic_cb(struct ril_msg *message, gpointer user_data)
2443+{
2444+ struct change_state_req *req = user_data;
2445+ struct voicecall_data *vd = ofono_voicecall_get_data(req->vc);
2446+ struct ofono_error error;
2447+
2448+ if (message->error == RIL_E_SUCCESS) {
2449+ decode_ril_error(&error, "OK");
2450+ } else {
2451+ decode_ril_error(&error, "FAIL");
2452+ goto out;
2453+ }
2454+
2455+ if (req->affected_types) {
2456+ GSList *l;
2457+ struct ofono_call *call;
2458+
2459+ for (l = vd->calls; l; l = l->next) {
2460+ call = l->data;
2461+
2462+ if (req->affected_types & (1 << call->status))
2463+ vd->local_release |= (1 << call->id);
2464+ }
2465+ }
2466+
2467+out:
2468+ g_ril_send(vd->ril, RIL_REQUEST_GET_CURRENT_CALLS, NULL,
2469+ 0, clcc_poll_cb, req->vc, NULL);
2470+
2471+ /* We have to callback after we schedule a poll if required */
2472+ if (req->cb)
2473+ req->cb(&error, req->data);
2474+}
2475+
2476+static void ril_template(const guint rreq, struct ofono_voicecall *vc,
2477+ GRilResponseFunc func, unsigned int affected_types,
2478+ gpointer pdata, const gsize psize,
2479+ ofono_voicecall_cb_t cb, void *data)
2480+{
2481+ struct voicecall_data *vd = ofono_voicecall_get_data(vc);
2482+ struct change_state_req *req = g_try_new0(struct change_state_req, 1);
2483+
2484+ if (req == NULL)
2485+ goto error;
2486+
2487+ req->vc = vc;
2488+ req->cb = cb;
2489+ req->data = data;
2490+ req->affected_types = affected_types;
2491+
2492+ if (g_ril_send(vd->ril, rreq, pdata, psize, func, req, g_free) > 0)
2493+ return;
2494+
2495+error:
2496+ g_free(req);
2497+
2498+ if (cb)
2499+ CALLBACK_WITH_FAILURE(cb, data);
2500+}
2501+
2502+static void rild_cb(struct ril_msg *message, gpointer user_data)
2503+{
2504+ struct cb_data *cbd = user_data;
2505+ struct ofono_voicecall *vc = cbd->user;
2506+ struct voicecall_data *vd = ofono_voicecall_get_data(vc);
2507+ ofono_voicecall_cb_t cb = cbd->cb;
2508+ struct ofono_error error;
2509+ struct ofono_call *call;
2510+ GSList *l;
2511+
2512+ if (message->error == RIL_E_SUCCESS) {
2513+ decode_ril_error(&error, "OK");
2514+ } else {
2515+ decode_ril_error(&error, "FAIL");
2516+ goto out;
2517+ }
2518+
2519+ /* On a success, make sure to put all active calls on hold */
2520+ for (l = vd->calls; l; l = l->next) {
2521+ call = l->data;
2522+
2523+ if (call->status != CALL_STATUS_ACTIVE)
2524+ continue;
2525+
2526+ call->status = CALL_STATUS_HELD;
2527+ ofono_voicecall_notify(vc, call);
2528+ }
2529+
2530+ /* CLCC will update the oFono call list with proper ids */
2531+ if (!vd->clcc_source)
2532+ vd->clcc_source = g_timeout_add(POLL_CLCC_INTERVAL,
2533+ poll_clcc, vc);
2534+
2535+ audioflinger_set_call_mode();
2536+
2537+out:
2538+ cb(&error, cbd->data);
2539+}
2540+
2541+static void ril_dial(struct ofono_voicecall *vc,
2542+ const struct ofono_phone_number *ph,
2543+ enum ofono_clir_option clir, ofono_voicecall_cb_t cb,
2544+ void *data)
2545+{
2546+ struct voicecall_data *vd = ofono_voicecall_get_data(vc);
2547+ struct cb_data *cbd = cb_data_new(cb, data);
2548+ struct parcel rilp;
2549+ int ret;
2550+
2551+ cbd->user = vc;
2552+
2553+ parcel_init(&rilp);
2554+
2555+ /* Number to dial */
2556+ parcel_w_string(&rilp, phone_number_to_string(ph));
2557+ /* CLIR mode */
2558+ parcel_w_int32(&rilp, clir);
2559+ /* USS, need it twice for absent */
2560+ /* TODO: Deal with USS properly */
2561+ parcel_w_int32(&rilp, 0);
2562+ parcel_w_int32(&rilp, 0);
2563+
2564+ /* Send request to RIL */
2565+ ret = g_ril_send(vd->ril, RIL_REQUEST_DIAL, rilp.data,
2566+ rilp.size, rild_cb, cbd, g_free);
2567+ parcel_free(&rilp);
2568+
2569+ /* In case of error free cbd and return the cb with failure */
2570+ if (ret <= 0) {
2571+ g_free(cbd);
2572+ CALLBACK_WITH_FAILURE(cb, data);
2573+ }
2574+}
2575+
2576+static void ril_hangup_all(struct ofono_voicecall *vc,
2577+ ofono_voicecall_cb_t cb, void *data)
2578+{
2579+ struct voicecall_data *vd = ofono_voicecall_get_data(vc);
2580+ struct parcel rilp;
2581+ struct ofono_error error;
2582+ struct ofono_call *call;
2583+ GSList *l;
2584+
2585+ for (l = vd->calls; l; l = l->next) {
2586+ call = l->data;
2587+ /* TODO: Hangup just the active ones once we have call
2588+ * state tracking (otherwise it can't handle ringing) */
2589+ DBG("Hanging up call with id %d", call->id);
2590+ parcel_init(&rilp);
2591+ parcel_w_int32(&rilp, 1); /* Always 1 - AT+CHLD=1x */
2592+ parcel_w_int32(&rilp, call->id);
2593+
2594+ /* Send request to RIL */
2595+ ril_template(RIL_REQUEST_HANGUP, vc, generic_cb, 0x3f,
2596+ rilp.data, rilp.size, NULL, NULL);
2597+ parcel_free(&rilp);
2598+ }
2599+
2600+ /* TODO: Deal in case of an error at hungup */
2601+ decode_ril_error(&error, "OK");
2602+ cb(&error, data);
2603+}
2604+
2605+static void ril_call_state_notify(struct ril_msg *message, gpointer user_data)
2606+{
2607+ struct ofono_voicecall *vc = user_data;
2608+
2609+ if (message->req != RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED)
2610+ goto error;
2611+
2612+ /* Just need to request the call list again */
2613+ poll_clcc(vc);
2614+
2615+ return;
2616+
2617+error:
2618+ ofono_error("Unable to notify about call state changes");
2619+}
2620+
2621+static void ril_answer(struct ofono_voicecall *vc,
2622+ ofono_voicecall_cb_t cb, void *data)
2623+{
2624+ DBG("Answering current call");
2625+
2626+ /* Send request to RIL */
2627+ ril_template(RIL_REQUEST_ANSWER, vc, generic_cb, 0,
2628+ NULL, 0, cb, data);
2629+
2630+ audioflinger_set_call_mode();
2631+}
2632+
2633+static void ril_send_dtmf(struct ofono_voicecall *vc, const char *dtmf,
2634+ ofono_voicecall_cb_t cb, void *data)
2635+{
2636+ struct voicecall_data *vd = ofono_voicecall_get_data(vc);
2637+ int len = strlen(dtmf);
2638+ struct parcel rilp;
2639+ struct ofono_error error;
2640+ char *ril_dtmf = g_try_malloc(sizeof(char) * 2);
2641+ int i;
2642+
2643+ DBG("");
2644+
2645+ /* Ril wants just one character, but we need to send as string */
2646+ ril_dtmf[1] = '\0';
2647+
2648+ for (i = 0; i < len; i++) {
2649+ parcel_init(&rilp);
2650+ ril_dtmf[0] = dtmf[i];
2651+ parcel_w_string(&rilp, ril_dtmf);
2652+ DBG("DTMF: Sending %s", ril_dtmf);
2653+ g_ril_send(vd->ril, RIL_REQUEST_DTMF, rilp.data,
2654+ rilp.size, NULL, NULL, NULL);
2655+ parcel_free(&rilp);
2656+ }
2657+
2658+ free(ril_dtmf);
2659+
2660+ /* We don't really care about errors here */
2661+ decode_ril_error(&error, "OK");
2662+ cb(&error, data);
2663+}
2664+
2665+static gboolean ril_delayed_register(gpointer user_data)
2666+{
2667+ struct ofono_voicecall *vc = user_data;
2668+ struct voicecall_data *vd = ofono_voicecall_get_data(vc);
2669+ ofono_voicecall_register(vc);
2670+
2671+ /* Initialize call list */
2672+ poll_clcc(vc);
2673+
2674+ /* Unsol when call state changes */
2675+ g_ril_register(vd->ril, RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED,
2676+ ril_call_state_notify, vc);
2677+
2678+ /* This makes the timeout a single-shot */
2679+ return FALSE;
2680+}
2681+
2682+static int ril_voicecall_probe(struct ofono_voicecall *vc, unsigned int vendor,
2683+ void *data)
2684+{
2685+ GRil *ril = data;
2686+ struct voicecall_data *vd;
2687+
2688+ vd = g_try_new0(struct voicecall_data, 1);
2689+ if (vd == NULL)
2690+ return -ENOMEM;
2691+
2692+ vd->ril = g_ril_clone(ril);
2693+ vd->vendor = vendor;
2694+ vd->tone_duration = TONE_DURATION;
2695+
2696+ ofono_voicecall_set_data(vc, vd);
2697+
2698+ /* ofono_devinfo_register() needs to be called after
2699+ * the driver has been set in devinfo_create() which
2700+ * calls this function. Most other drivers use a
2701+ * callback after getting some return from the modem
2702+ * itself...
2703+ */
2704+ g_timeout_add_seconds(2, ril_delayed_register, vc);
2705+
2706+ return 0;
2707+}
2708+
2709+static void ril_voicecall_remove(struct ofono_voicecall *vc)
2710+{
2711+ struct voicecall_data *vd = ofono_voicecall_get_data(vc);
2712+
2713+ if (vd->clcc_source)
2714+ g_source_remove(vd->clcc_source);
2715+
2716+ if (vd->vts_source)
2717+ g_source_remove(vd->vts_source);
2718+
2719+ g_slist_foreach(vd->calls, (GFunc) g_free, NULL);
2720+ g_slist_free(vd->calls);
2721+
2722+ ofono_voicecall_set_data(vc, NULL);
2723+
2724+ g_ril_unref(vd->ril);
2725+ g_free(vd);
2726+}
2727+
2728+static struct ofono_voicecall_driver driver = {
2729+ .name = "rilmodem",
2730+ .probe = ril_voicecall_probe,
2731+ .remove = ril_voicecall_remove,
2732+ .dial = ril_dial,
2733+ .answer = ril_answer,
2734+ .hangup_all = ril_hangup_all,
2735+ .send_tones = ril_send_dtmf
2736+};
2737+
2738+void ril_voicecall_init(void)
2739+{
2740+ ofono_voicecall_driver_register(&driver);
2741+}
2742+
2743+void ril_voicecall_exit(void)
2744+{
2745+ ofono_voicecall_driver_unregister(&driver);
2746+}
2747
2748=== added directory 'gril'
2749=== added file 'gril/gfunc.h'
2750--- gril/gfunc.h 1970-01-01 00:00:00 +0000
2751+++ gril/gfunc.h 2013-04-09 20:01:20 +0000
2752@@ -0,0 +1,42 @@
2753+/*
2754+ *
2755+ * RIL library with GLib integration
2756+ *
2757+ * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
2758+ * Copyright (C) 2012 Canonical Ltd.
2759+ *
2760+ * This program is free software; you can redistribute it and/or modify
2761+ * it under the terms of the GNU General Public License version 2 as
2762+ * published by the Free Software Foundation.
2763+ *
2764+ * This program is distributed in the hope that it will be useful,
2765+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2766+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2767+ * GNU General Public License for more details.
2768+ *
2769+ * You should have received a copy of the GNU General Public License
2770+ * along with this program; if not, write to the Free Software
2771+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2772+ *
2773+ */
2774+
2775+#ifndef __GFUNC_H
2776+#define __GFUNC_H
2777+
2778+#include <glib.h>
2779+
2780+#ifdef __cplusplus
2781+extern "C" {
2782+#endif
2783+
2784+typedef void (*GRilDisconnectFunc)(gpointer user_data);
2785+typedef void (*GRilReceiveFunc)(const unsigned char *data, gsize size,
2786+ gpointer user_data);
2787+typedef void (*GRilDebugFunc)(const char *str, gpointer user_data);
2788+typedef void (*GRilSuspendFunc)(gpointer user_data);
2789+
2790+#ifdef __cplusplus
2791+}
2792+#endif
2793+
2794+#endif /* __GFUNC_H */
2795
2796=== added file 'gril/gril.c'
2797--- gril/gril.c 1970-01-01 00:00:00 +0000
2798+++ gril/gril.c 2013-04-09 20:01:20 +0000
2799@@ -0,0 +1,1160 @@
2800+/*
2801+ *
2802+ * RIL library with GLib integration
2803+ *
2804+ * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
2805+ * Copyright (C) 2012 Canonical Ltd.
2806+ *
2807+ * This program is free software; you can redistribute it and/or modify
2808+ * it under the terms of the GNU General Public License version 2 as
2809+ * published by the Free Software Foundation.
2810+ *
2811+ * This program is distributed in the hope that it will be useful,
2812+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2813+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2814+ * GNU General Public License for more details.
2815+ *
2816+ * You should have received a copy of the GNU General Public License
2817+ * along with this program; if not, write to the Free Software
2818+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2819+ *
2820+ */
2821+
2822+#ifdef HAVE_CONFIG_H
2823+#include <config.h>
2824+#endif
2825+
2826+#include <stdio.h>
2827+#include <unistd.h>
2828+#include <string.h>
2829+#include <assert.h>
2830+#include <ctype.h>
2831+#include <errno.h>
2832+#include <sys/socket.h>
2833+#include <sys/un.h>
2834+#include <netinet/in.h>
2835+
2836+#include <glib.h>
2837+
2838+#include "log.h"
2839+#include "ringbuffer.h"
2840+#include "gril.h"
2841+
2842+#define COMMAND_FLAG_EXPECT_PDU 0x1
2843+#define COMMAND_FLAG_EXPECT_SHORT_PROMPT 0x2
2844+
2845+#define RILD_CMD_SOCKET "/dev/socket/rild"
2846+#define RILD_DBG_SOCKET "/dev/socket/rild-debug"
2847+
2848+struct ril_request {
2849+ gchar *req;
2850+ guint req_len;
2851+ guint id;
2852+ guint gid;
2853+ GRilResponseFunc callback;
2854+ gpointer user_data;
2855+ GDestroyNotify notify;
2856+};
2857+
2858+struct ril_notify_node {
2859+ guint id;
2860+ guint gid;
2861+ GRilNotifyFunc callback;
2862+ gpointer user_data;
2863+ gboolean destroyed;
2864+};
2865+
2866+typedef gboolean (*node_remove_func)(struct ril_notify_node *node,
2867+ gpointer user_data);
2868+
2869+struct ril_notify {
2870+ GSList *nodes;
2871+};
2872+
2873+struct ril_s {
2874+ gint ref_count; /* Ref count */
2875+ guint next_cmd_id; /* Next command id */
2876+ guint next_notify_id; /* Next notify id */
2877+ guint next_gid; /* Next group id */
2878+ GRilIO *io; /* GRil IO */
2879+ GQueue *command_queue; /* Command queue */
2880+ guint req_bytes_written; /* bytes written from req */
2881+ GHashTable *notify_list; /* List of notification reg */
2882+ GRilDisconnectFunc user_disconnect; /* user disconnect func */
2883+ gpointer user_disconnect_data; /* user disconnect data */
2884+ guint read_so_far; /* Number of bytes processed */
2885+ gboolean suspended; /* Are we suspended? */
2886+ GRilDebugFunc debugf; /* debugging output function */
2887+ gpointer debug_data; /* Data to pass to debug func */
2888+ GSList *response_lines; /* char * lines of the response */
2889+ gint timeout_source;
2890+ gboolean destroyed; /* Re-entrancy guard */
2891+ gboolean in_read_handler; /* Re-entrancy guard */
2892+ gboolean in_notify;
2893+};
2894+
2895+struct _GRil {
2896+ gint ref_count;
2897+ struct ril_s *parent;
2898+ guint group;
2899+};
2900+
2901+/*
2902+ * This struct represents the header of a RIL reply.
2903+ * It does not include the Big Endian UINT32 length prefix.
2904+ */
2905+struct ril_reply {
2906+ guint32 reply; /* LE: should be 0 */
2907+ guint32 serial_no; /* LE: used to match requests */
2908+ guint32 error_code; /* LE: */
2909+};
2910+
2911+static void ril_wakeup_writer(struct ril_s *ril);
2912+
2913+static void ril_notify_node_destroy(gpointer data, gpointer user_data)
2914+{
2915+ struct ril_notify_node *node = data;
2916+ g_free(node);
2917+}
2918+
2919+static void ril_notify_destroy(gpointer user_data)
2920+{
2921+ struct ril_notify *notify = user_data;
2922+
2923+ g_slist_foreach(notify->nodes, ril_notify_node_destroy, NULL);
2924+ g_slist_free(notify->nodes);
2925+ g_free(notify);
2926+}
2927+
2928+static gint ril_notify_node_compare_by_id(gconstpointer a, gconstpointer b)
2929+{
2930+ const struct ril_notify_node *node = a;
2931+ guint id = GPOINTER_TO_UINT(b);
2932+
2933+ if (node->id < id)
2934+ return -1;
2935+
2936+ if (node->id > id)
2937+ return 1;
2938+
2939+ return 0;
2940+}
2941+
2942+static gboolean ril_unregister_all(struct ril_s *ril,
2943+ gboolean mark_only,
2944+ node_remove_func func,
2945+ gpointer userdata)
2946+{
2947+ GHashTableIter iter;
2948+ struct ril_notify *notify;
2949+ struct ril_notify_node *node;
2950+ gpointer key, value;
2951+ GSList *p;
2952+ GSList *c;
2953+ GSList *t;
2954+
2955+ if (ril->notify_list == NULL)
2956+ return FALSE;
2957+
2958+ g_hash_table_iter_init(&iter, ril->notify_list);
2959+
2960+ while (g_hash_table_iter_next(&iter, &key, &value)) {
2961+ notify = value;
2962+
2963+ p = NULL;
2964+ c = notify->nodes;
2965+
2966+ while (c) {
2967+ node = c->data;
2968+
2969+ if (func(node, userdata) != TRUE) {
2970+ p = c;
2971+ c = c->next;
2972+ continue;
2973+ }
2974+
2975+ if (mark_only) {
2976+ node->destroyed = TRUE;
2977+ p = c;
2978+ c = c->next;
2979+ continue;
2980+ }
2981+
2982+ if (p)
2983+ p->next = c->next;
2984+ else
2985+ notify->nodes = c->next;
2986+
2987+ ril_notify_node_destroy(node, NULL);
2988+
2989+ t = c;
2990+ c = c->next;
2991+ g_slist_free_1(t);
2992+ }
2993+
2994+ if (notify->nodes == NULL)
2995+ g_hash_table_iter_remove(&iter);
2996+ }
2997+
2998+ return TRUE;
2999+}
3000+
3001+/* TODO: move to grilutil.h */
3002+static const char *err_name(int error)
3003+{
3004+ switch(error) {
3005+ case RIL_E_SUCCESS: return "SUCCESS";
3006+ case RIL_E_RADIO_NOT_AVAILABLE: return "RADIO_NOT_AVAILABLE";
3007+ case RIL_E_GENERIC_FAILURE: return "GENERIC_FAILURE";
3008+ case RIL_E_PASSWORD_INCORRECT: return "PASSWORD_INCORRECT";
3009+ case RIL_E_SIM_PIN2: return "SIM_PIN2";
3010+ case RIL_E_SIM_PUK2: return "SIM_PUK2";
3011+ case RIL_E_REQUEST_NOT_SUPPORTED: return "REQUEST_NOT_SUPPORTED";
3012+ case RIL_E_CANCELLED: return "CANCELLED";
3013+ case RIL_E_OP_NOT_ALLOWED_DURING_VOICE_CALL: return "OP_NOT_ALLOWED_DURING_VOICE_CALL";
3014+ case RIL_E_OP_NOT_ALLOWED_BEFORE_REG_TO_NW: return "OP_NOT_ALLOWED_BEFORE_REG_TO_NW";
3015+ case RIL_E_SMS_SEND_FAIL_RETRY: return "SMS_SEND_FAIL_RETRY";
3016+ case RIL_E_SIM_ABSENT: return "SIM_ABSENT";
3017+ case RIL_E_SUBSCRIPTION_NOT_AVAILABLE: return "SUBSCRIPTION_NOT_AVAILABLE";
3018+ case RIL_E_MODE_NOT_SUPPORTED: return "MODE_NOT_SUPPORTED";
3019+ case RIL_E_FDN_CHECK_FAILURE: return "FDN_CHECK_FAILURE";
3020+ case RIL_E_ILLEGAL_SIM_OR_ME: return "ILLEGAL_SIM_OR_ME";
3021+ default: return "<unknown errno>";
3022+ }
3023+}
3024+
3025+/* TODO: move to grilutil.h */
3026+static const char *unsol_request_name(int request)
3027+{
3028+ switch(request) {
3029+ case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED: return "UNSOL_RESPONSE_RADIO_STATE_CHANGED";
3030+ case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED: return "UNSOL_RESPONSE_CALL_STATE_CHANGED";
3031+ case RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED: return "UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED";
3032+ case RIL_UNSOL_RESPONSE_NEW_SMS: return "UNSOL_RESPONSE_NEW_SMS";
3033+ case RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT: return "UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT";
3034+ case RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM: return "UNSOL_RESPONSE_NEW_SMS_ON_SIM";
3035+ case RIL_UNSOL_ON_USSD: return "UNSOL_ON_USSD";
3036+ case RIL_UNSOL_ON_USSD_REQUEST: return "UNSOL_ON_USSD_REQUEST(obsolete)";
3037+ case RIL_UNSOL_NITZ_TIME_RECEIVED: return "UNSOL_NITZ_TIME_RECEIVED";
3038+ case RIL_UNSOL_SIGNAL_STRENGTH: return "UNSOL_SIGNAL_STRENGTH";
3039+ case RIL_UNSOL_STK_SESSION_END: return "UNSOL_STK_SESSION_END";
3040+ case RIL_UNSOL_STK_PROACTIVE_COMMAND: return "UNSOL_STK_PROACTIVE_COMMAND";
3041+ case RIL_UNSOL_STK_EVENT_NOTIFY: return "UNSOL_STK_EVENT_NOTIFY";
3042+ case RIL_UNSOL_STK_CALL_SETUP: return "UNSOL_STK_CALL_SETUP";
3043+ case RIL_UNSOL_SIM_SMS_STORAGE_FULL: return "UNSOL_SIM_SMS_STORAGE_FUL";
3044+ case RIL_UNSOL_SIM_REFRESH: return "UNSOL_SIM_REFRESH";
3045+ case RIL_UNSOL_DATA_CALL_LIST_CHANGED: return "UNSOL_DATA_CALL_LIST_CHANGED";
3046+ case RIL_UNSOL_CALL_RING: return "UNSOL_CALL_RING";
3047+ case RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED: return "UNSOL_RESPONSE_SIM_STATUS_CHANGED";
3048+ case RIL_UNSOL_RESPONSE_CDMA_NEW_SMS: return "UNSOL_NEW_CDMA_SMS";
3049+ case RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS: return "UNSOL_NEW_BROADCAST_SMS";
3050+ case RIL_UNSOL_CDMA_RUIM_SMS_STORAGE_FULL: return "UNSOL_CDMA_RUIM_SMS_STORAGE_FULL";
3051+ case RIL_UNSOL_RESTRICTED_STATE_CHANGED: return "UNSOL_RESTRICTED_STATE_CHANGED";
3052+ case RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE: return "UNSOL_ENTER_EMERGENCY_CALLBACK_MODE";
3053+ case RIL_UNSOL_CDMA_CALL_WAITING: return "UNSOL_CDMA_CALL_WAITING";
3054+ case RIL_UNSOL_CDMA_OTA_PROVISION_STATUS: return "UNSOL_CDMA_OTA_PROVISION_STATUS";
3055+ case RIL_UNSOL_CDMA_INFO_REC: return "UNSOL_CDMA_INFO_REC";
3056+ case RIL_UNSOL_OEM_HOOK_RAW: return "UNSOL_OEM_HOOK_RAW";
3057+ case RIL_UNSOL_RINGBACK_TONE: return "UNSOL_RINGBACK_TONE";
3058+ case RIL_UNSOL_RESEND_INCALL_MUTE: return "UNSOL_RESEND_INCALL_MUTE";
3059+ case RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED: return "UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED";
3060+ case RIL_UNSOL_CDMA_PRL_CHANGED: return "UNSOL_CDMA_PRL_CHANGED";
3061+ case RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE: return "UNSOL_EXIT_EMERGENCY_CALLBACK_MODE";
3062+ case RIL_UNSOL_RIL_CONNECTED: return "UNSOL_RIL_CONNECTED";
3063+ default:
3064+ DBG("Got unknown request number %d", request);
3065+ return "<unknown request>";
3066+ }
3067+}
3068+
3069+/*
3070+ * This function creates a RIL request. For a good reference on
3071+ * the layout of RIL requests, responses, and unsolicited requests
3072+ * see:
3073+ *
3074+ * https://wiki.mozilla.org/B2G/RIL
3075+ *
3076+ */
3077+static struct ril_request *ril_request_create(struct ril_s *ril,
3078+ guint gid,
3079+ const guint req,
3080+ const guint id,
3081+ const char *data,
3082+ const gsize data_len,
3083+ GRilResponseFunc func,
3084+ gpointer user_data,
3085+ GDestroyNotify notify,
3086+ gboolean wakeup)
3087+{
3088+ struct ril_request *r;
3089+ gsize len;
3090+ gchar *cur_bufp;
3091+ guint32 *net_length, *request, *serial_no;
3092+
3093+ r = g_try_new0(struct ril_request, 1);
3094+ if (r == NULL)
3095+ return 0;
3096+
3097+ DBG("req: %s, id: %d, data_len: %d",
3098+ ril_request_id_to_string(req), id, data_len);
3099+
3100+ /* RIL request: 8 byte header + data */
3101+ len = 8 + data_len;
3102+
3103+ /* Add 4 bytes to buffer length to include length prefix */
3104+ r->req_len = len + 4;
3105+
3106+ r->req = g_try_new(char, r->req_len);
3107+ if (r->req == NULL) {
3108+ ofono_error("ril_request: can't allocate new request.");
3109+ g_free(r);
3110+ return 0;
3111+ }
3112+
3113+ /* convert length to network byte order (Big Endian) */
3114+ net_length = (guint32 *) r->req;
3115+ *net_length = htonl(len);
3116+
3117+ /* advance past initial length */
3118+ cur_bufp = r->req + 4;
3119+
3120+ /* write request code */
3121+ request = (guint32 *) cur_bufp;
3122+ *request = req;
3123+ cur_bufp += 4;
3124+
3125+ /* write serial number */
3126+ serial_no = (guint32 *) cur_bufp;
3127+ *serial_no = id;
3128+ cur_bufp += 4;
3129+
3130+ /* copy request data */
3131+ memcpy(cur_bufp, (const void *) data, data_len);
3132+
3133+ r->gid = gid;
3134+ r->id = id;
3135+ r->callback = func;
3136+ r->user_data = user_data;
3137+ r->notify = notify;
3138+
3139+ return r;
3140+}
3141+
3142+static void ril_request_destroy(struct ril_request *req)
3143+{
3144+ if (req->notify)
3145+ req->notify(req->user_data);
3146+
3147+ g_free(req->req);
3148+ g_free(req);
3149+}
3150+
3151+static void ril_cleanup(struct ril_s *p)
3152+{
3153+ /* Cleanup pending commands */
3154+
3155+ g_queue_free(p->command_queue);
3156+ p->command_queue = NULL;
3157+
3158+ /* Cleanup any response lines we have pending */
3159+ g_slist_foreach(p->response_lines, (GFunc)g_free, NULL);
3160+ g_slist_free(p->response_lines);
3161+ p->response_lines = NULL;
3162+
3163+ /* Cleanup registered notifications */
3164+
3165+ if (p->notify_list)
3166+ g_hash_table_destroy(p->notify_list);
3167+
3168+ p->notify_list = NULL;
3169+
3170+ if (p->timeout_source) {
3171+ g_source_remove(p->timeout_source);
3172+ p->timeout_source = 0;
3173+ }
3174+}
3175+
3176+static void io_disconnect(gpointer user_data)
3177+{
3178+ struct ril_s *ril = user_data;
3179+
3180+ ril_cleanup(ril);
3181+ g_ril_io_unref(ril->io);
3182+ ril->io = NULL;
3183+
3184+ if (ril->user_disconnect)
3185+ ril->user_disconnect(ril->user_disconnect_data);
3186+}
3187+
3188+static void handle_response(struct ril_s *p, struct ril_msg *message)
3189+{
3190+ gsize count = g_queue_get_length(p->command_queue);
3191+ struct ril_request *req;
3192+ int i;
3193+
3194+ g_assert(count > 0);
3195+
3196+ for (i = 0; i < count; i++) {
3197+ req = g_queue_peek_nth(p->command_queue, i);
3198+ DBG("comparing req->id: %d to message->serial_no: %d",
3199+ req->id, message->serial_no);
3200+
3201+ if (req->id == message->serial_no) {
3202+ req = g_queue_pop_nth(p->command_queue, i);
3203+
3204+ if (req->callback)
3205+ req->callback(message, req->user_data);
3206+
3207+ ril_request_destroy(req);
3208+
3209+ if (g_queue_peek_head(p->command_queue))
3210+ ril_wakeup_writer(p);
3211+ /*
3212+ * TODO: there's a flaw in the current logic.
3213+ * If a matching response isn't received,
3214+ * req_bytes_written doesn't get reset.
3215+ * gatchat has the concept of modem wakeup,
3216+ * which is a failsafe way of making sure
3217+ * cmd_bytes_written gets reset, however if
3218+ * the modem isn't configured for wakeup,
3219+ * it may have the same problem. Perhaps
3220+ * we should consider adding a timer?
3221+ */
3222+ p->req_bytes_written = 0;
3223+
3224+ /* Found our matching one */
3225+ break;
3226+ }
3227+ }
3228+}
3229+
3230+static void handle_unsol_req(struct ril_s *p, struct ril_msg *message)
3231+{
3232+ GHashTableIter iter;
3233+ struct ril_notify *notify;
3234+ int req_key;
3235+ gpointer key, value;
3236+ GList *list_item;
3237+ struct ril_notify_node *node;
3238+
3239+ if (p->notify_list == NULL)
3240+ return;
3241+
3242+ p->in_notify = TRUE;
3243+
3244+ g_hash_table_iter_init(&iter, p->notify_list);
3245+
3246+ while (g_hash_table_iter_next(&iter, &key, &value)) {
3247+ req_key = *((int *)key);
3248+ notify = value;
3249+
3250+ DBG("checking req_key: %d to req: %d", req_key, message->req);
3251+
3252+ if (req_key != message->req)
3253+ continue;
3254+
3255+ list_item = notify->nodes;
3256+
3257+ while (list_item != NULL) {
3258+ node = list_item->data;
3259+
3260+ DBG("about to callback: notify: %x, node: %x, notify->nodes: %x, callback: %x",
3261+ notify, node, notify->nodes, node->callback);
3262+
3263+ node->callback(message, node->user_data);
3264+
3265+ list_item = g_slist_next(list_item);
3266+ }
3267+ }
3268+
3269+ p->in_notify = FALSE;
3270+}
3271+
3272+static void dispatch(struct ril_s *p, struct ril_msg *message)
3273+{
3274+ guint32 *unsolicited_field, *id_num_field;
3275+ gchar *bufp = message->buf;
3276+ gchar *datap;
3277+ gsize data_len;
3278+
3279+ /* This could be done with a struct/union... */
3280+ unsolicited_field = (guint32 *) bufp;
3281+ if (*unsolicited_field)
3282+ message->unsolicited = TRUE;
3283+ else
3284+ message->unsolicited = FALSE;
3285+
3286+ bufp += 4;
3287+
3288+ id_num_field = (guint32 *) bufp;
3289+ if (message->unsolicited) {
3290+ message->req = (int) *id_num_field;
3291+
3292+ /*
3293+ * A RIL Unsolicited Event is two UINT32 fields ( unsolicited, and req/ev ),
3294+ * so subtract the length of the header from the overall length to calculate
3295+ * the length of the Event Data.
3296+ */
3297+ data_len = message->buf_len - 8;
3298+ } else {
3299+ message->serial_no = (int) *id_num_field;
3300+
3301+ bufp += 4;
3302+ message->error = *((guint32 *) bufp);
3303+
3304+ /*
3305+ * A RIL Solicited Response is three UINT32 fields ( unsolicied, serial_no
3306+ * and error ), so subtract the length of the header from the overall length
3307+ * to calculate the length of the Event Data.
3308+ */
3309+ data_len = message->buf_len - 12;
3310+ }
3311+
3312+ /* advance to start of data.. */
3313+ bufp += 4;
3314+
3315+ /* Now, allocate new buffer for data only, copy from
3316+ * original, and free the original...
3317+ */
3318+ if (data_len) {
3319+ datap = g_try_malloc(data_len);
3320+ if (datap == NULL)
3321+ goto error;
3322+
3323+ /* Copy bytes into new buffer */
3324+ memmove(datap, (const void *) bufp, data_len);
3325+
3326+ /* Free old buffer */
3327+ g_free(message->buf);
3328+
3329+ /* ...and replace with new buffer */
3330+ message->buf = datap;
3331+ message->buf_len = data_len;
3332+ }
3333+
3334+ if (message->unsolicited == TRUE) {
3335+ DBG("RIL Event: %s\n", unsol_request_name(message->req));
3336+
3337+ handle_unsol_req(p, message);
3338+ } else {
3339+ DBG("RIL Reply: serial-no: %d errno: %s\n",
3340+ message->serial_no,
3341+ err_name(message->error));
3342+
3343+ handle_response(p, message);
3344+ }
3345+error:
3346+ g_free(message->buf);
3347+ g_free(message);
3348+}
3349+
3350+static struct ril_msg *read_fixed_record(struct ril_s *p,
3351+ const guchar *bytes, gsize *len)
3352+{
3353+ struct ril_msg *message;
3354+ int message_len, plen;
3355+
3356+ /* First four bytes are length in TCP byte order (Big Endian) */
3357+ plen = ntohl(*((uint32_t *) bytes));
3358+ bytes += 4;
3359+
3360+ /* TODO: Verify that 4k is the max message size from rild.
3361+ *
3362+ * These conditions shouldn't happen. If it does
3363+ * there are three options:
3364+ *
3365+ * 1) ASSERT; ofono will restart via DBus
3366+ * 2) Consume the bytes & continue
3367+ * 3) force a disconnect
3368+ */
3369+ g_assert(plen >= 8 && plen <= 4092);
3370+
3371+ /* If we don't have the whole fixed record in the ringbuffer
3372+ * then return NULL & leave ringbuffer as is.
3373+ */
3374+
3375+ message_len = *len - 4;
3376+ if (message_len < plen) {
3377+ return NULL;
3378+ }
3379+
3380+ /* FIXME: add check for message_len = 0? */
3381+
3382+ message = g_try_malloc(sizeof(struct ril_msg));
3383+ g_assert(message != NULL);
3384+
3385+ /* allocate ril_msg->buffer */
3386+ message->buf_len = plen;
3387+ message->buf = g_try_malloc(plen);
3388+ g_assert(message->buf != NULL);
3389+
3390+ /* Copy bytes into message buffer */
3391+ memmove(message->buf, (const void *) bytes, plen);
3392+
3393+ /* Indicate to caller size of record we extracted */
3394+ *len = plen + 4;
3395+ return message;
3396+}
3397+
3398+static void new_bytes(struct ring_buffer *rbuf, gpointer user_data)
3399+{
3400+ struct ril_msg *message;
3401+ struct ril_s *p = user_data;
3402+ unsigned int len = ring_buffer_len(rbuf);
3403+ unsigned int wrap = ring_buffer_len_no_wrap(rbuf);
3404+ guchar *buf = ring_buffer_read_ptr(rbuf, p->read_so_far);
3405+
3406+ p->in_read_handler = TRUE;
3407+
3408+ DBG("len: %d, wrap: %d", len, wrap);
3409+
3410+ while (p->suspended == FALSE && (p->read_so_far < len)) {
3411+ gsize rbytes = MIN(len - p->read_so_far, wrap - p->read_so_far);
3412+
3413+ if (rbytes < 4) {
3414+ DBG("Not enough bytes for header length: len: %d", len);
3415+ return;
3416+ }
3417+
3418+ /* this function attempts to read the next full length
3419+ * fixed message from the stream. if not all bytes are
3420+ * available, it returns NULL. otherwise it allocates
3421+ * and returns a ril_message with the copied bytes, and
3422+ * drains those bytes from the ring_buffer
3423+ */
3424+ message = read_fixed_record(p, buf, &rbytes);
3425+
3426+ /* wait for the rest of the record... */
3427+ if (message == NULL) {
3428+ DBG("Not enough bytes for fixed record");
3429+ break;
3430+ }
3431+
3432+ buf += rbytes;
3433+ p->read_so_far += rbytes;
3434+
3435+ /* TODO: need to better understand how wrap works! */
3436+ if (p->read_so_far == wrap) {
3437+ buf = ring_buffer_read_ptr(rbuf, p->read_so_far);
3438+ wrap = len;
3439+ }
3440+
3441+ dispatch(p, message);
3442+
3443+ ring_buffer_drain(rbuf, p->read_so_far);
3444+
3445+ len -= p->read_so_far;
3446+ wrap -= p->read_so_far;
3447+ p->read_so_far = 0;
3448+ }
3449+
3450+ p->in_read_handler = FALSE;
3451+
3452+ if (p->destroyed)
3453+ g_free(p);
3454+}
3455+
3456+static gboolean can_write_data(gpointer data)
3457+{
3458+ struct ril_s *ril = data;
3459+ struct ril_request *req;
3460+ gsize bytes_written;
3461+ gsize towrite;
3462+ gsize len;
3463+
3464+ /* Grab the first command off the queue and write as
3465+ * much of it as we can
3466+ */
3467+ req = g_queue_peek_head(ril->command_queue);
3468+
3469+ /* For some reason command queue is empty, cancel write watcher */
3470+ if (req == NULL)
3471+ return FALSE;
3472+
3473+ len = req->req_len;
3474+ DBG("len: %d, req_bytes_written: %d", len, ril->req_bytes_written);
3475+
3476+ /* For some reason write watcher fired, but we've already
3477+ * written the entire command out to the io channel,
3478+ * cancel write watcher
3479+ */
3480+ if (ril->req_bytes_written >= len)
3481+ return FALSE;
3482+
3483+ /*
3484+ * AT modems need to be woken up via a command set by the
3485+ * upper layers. RIL has no such concept, hence wakeup needed
3486+ * NOTE - I'm keeping the if statement here commented out, just
3487+ * in case this concept needs to be added back in...
3488+ *
3489+ * if (ril->req_bytes_written == 0 && wakeup_first == TRUE) {
3490+ * cmd = at_command_create(0, chat->wakeup, none_prefix, 0,
3491+ * NULL, wakeup_cb, chat, NULL, TRUE);
3492+ * g_queue_push_head(chat->command_queue, cmd);
3493+ * len = strlen(chat->wakeup);
3494+ * chat->timeout_source = g_timeout_add(chat->wakeup_timeout,
3495+ * wakeup_no_response, chat);
3496+ * }
3497+ */
3498+
3499+ towrite = len - ril->req_bytes_written;
3500+
3501+#ifdef WRITE_SCHEDULER_DEBUG
3502+ if (towrite > 5)
3503+ towrite = 5;
3504+#endif
3505+
3506+ bytes_written = g_ril_io_write(ril->io,
3507+ req->req + ril->req_bytes_written,
3508+ towrite);
3509+
3510+ DBG("bytes_written: %d", bytes_written);
3511+
3512+ if (bytes_written == 0)
3513+ return FALSE;
3514+
3515+ ril->req_bytes_written += bytes_written;
3516+ if (bytes_written < towrite)
3517+ return TRUE;
3518+
3519+ return FALSE;
3520+}
3521+
3522+static void ril_wakeup_writer(struct ril_s *ril)
3523+{
3524+ g_ril_io_set_write_handler(ril->io, can_write_data, ril);
3525+}
3526+
3527+static void ril_suspend(struct ril_s *ril)
3528+{
3529+ ril->suspended = TRUE;
3530+
3531+ g_ril_io_set_write_handler(ril->io, NULL, NULL);
3532+ g_ril_io_set_read_handler(ril->io, NULL, NULL);
3533+ g_ril_io_set_debug(ril->io, NULL, NULL);
3534+}
3535+
3536+/*
3537+ * TODO: need to determine when ril_resume/suspend are called.
3538+ *
3539+ * Most likely, this is in response to DBUS messages sent to
3540+ * oFono to tell it the system is suspending/resuming.
3541+ */
3542+static void ril_resume(struct ril_s *ril)
3543+{
3544+ ril->suspended = FALSE;
3545+
3546+ if (g_ril_io_get_channel(ril->io) == NULL) {
3547+ io_disconnect(ril);
3548+ return;
3549+ }
3550+
3551+ g_ril_io_set_disconnect_function(ril->io, io_disconnect, ril);
3552+
3553+ g_ril_io_set_debug(ril->io, ril->debugf, ril->debug_data);
3554+
3555+ g_ril_io_set_read_handler(ril->io, new_bytes, ril);
3556+
3557+ if (g_queue_get_length(ril->command_queue) > 0)
3558+ ril_wakeup_writer(ril);
3559+}
3560+
3561+static gboolean ril_set_debug(struct ril_s *ril,
3562+ GRilDebugFunc func, gpointer user_data)
3563+{
3564+
3565+ ril->debugf = func;
3566+ ril->debug_data = user_data;
3567+
3568+ if (ril->io)
3569+ g_ril_io_set_debug(ril->io, func, user_data);
3570+
3571+ return TRUE;
3572+}
3573+
3574+static void ril_unref(struct ril_s *ril)
3575+{
3576+ gboolean is_zero;
3577+
3578+ is_zero = g_atomic_int_dec_and_test(&ril->ref_count);
3579+
3580+ if (is_zero == FALSE)
3581+ return;
3582+
3583+ if (ril->io) {
3584+ ril_suspend(ril);
3585+ g_ril_io_unref(ril->io);
3586+ ril->io = NULL;
3587+ ril_cleanup(ril);
3588+ }
3589+
3590+ if (ril->in_read_handler)
3591+ ril->destroyed = TRUE;
3592+ else
3593+ g_free(ril);
3594+}
3595+
3596+static gboolean node_compare_by_group(struct ril_notify_node *node,
3597+ gpointer userdata)
3598+{
3599+ guint group = GPOINTER_TO_UINT(userdata);
3600+
3601+ if (node->gid == group)
3602+ return TRUE;
3603+
3604+ return FALSE;
3605+}
3606+
3607+static struct ril_s *create_ril()
3608+
3609+{
3610+ struct ril_s *ril;
3611+ struct sockaddr_un addr;
3612+ int sk;
3613+ GIOChannel *io;
3614+
3615+ ril = g_try_new0(struct ril_s, 1);
3616+ if (ril == NULL)
3617+ return ril;
3618+
3619+ ril->ref_count = 1;
3620+ ril->next_cmd_id = 1;
3621+ ril->next_notify_id = 1;
3622+ ril->next_gid = 0;
3623+ ril->debugf = NULL;
3624+ ril->req_bytes_written = 0;
3625+
3626+ sk = socket(AF_UNIX, SOCK_STREAM, 0);
3627+ if (sk < 0) {
3628+ ofono_error("create_ril: can't create unix socket: %s (%d)\n",
3629+ strerror(errno), errno);
3630+ goto error;
3631+ }
3632+
3633+ memset(&addr, 0, sizeof(addr));
3634+ addr.sun_family = AF_UNIX;
3635+ strncpy(addr.sun_path, RILD_CMD_SOCKET, sizeof(addr.sun_path) - 1);
3636+
3637+ if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
3638+ ofono_error("create_ril: can't connect to RILD: %s (%d)\n",
3639+ strerror(errno), errno);
3640+ goto error;
3641+ }
3642+
3643+ io = g_io_channel_unix_new(sk);
3644+ if (io == NULL) {
3645+ ofono_error("create_ril: can't connect to RILD: %s (%d)\n",
3646+ strerror(errno), errno);
3647+ return NULL;
3648+ }
3649+
3650+ g_io_channel_set_buffered(io, FALSE);
3651+ g_io_channel_set_encoding(io, NULL, NULL);
3652+ g_io_channel_set_close_on_unref(io, TRUE);
3653+ g_io_channel_set_flags(io, G_IO_FLAG_NONBLOCK, NULL);
3654+
3655+ ril->io = g_ril_io_new(io);
3656+ if (ril->io == NULL) {
3657+ ofono_error("create_ril: can't create ril->io");
3658+ goto error;
3659+ }
3660+
3661+ g_ril_io_set_disconnect_function(ril->io, io_disconnect, ril);
3662+
3663+ ril->command_queue = g_queue_new();
3664+ if (ril->command_queue == NULL) {
3665+ ofono_error("create_ril: Couldn't create command_queue.");
3666+ goto error;
3667+ }
3668+
3669+ ril->notify_list = g_hash_table_new_full(g_int_hash, g_int_equal,
3670+ g_free, ril_notify_destroy);
3671+
3672+ g_ril_io_set_read_handler(ril->io, new_bytes, ril);
3673+
3674+ return ril;
3675+
3676+error:
3677+ g_ril_io_unref(ril->io);
3678+
3679+ if (ril->command_queue)
3680+ g_queue_free(ril->command_queue);
3681+
3682+ if (ril->notify_list)
3683+ g_hash_table_destroy(ril->notify_list);
3684+
3685+ g_free(ril);
3686+ return NULL;
3687+}
3688+
3689+static struct ril_notify *ril_notify_create(struct ril_s *ril,
3690+ const int req)
3691+{
3692+ struct ril_notify *notify;
3693+ int *key;
3694+
3695+ notify = g_try_new0(struct ril_notify, 1);
3696+ if (notify == NULL)
3697+ return 0;
3698+
3699+ key = g_try_new0(int, 1);
3700+ if (key == NULL)
3701+ return 0;
3702+
3703+ *key = req;
3704+
3705+ g_hash_table_insert(ril->notify_list, key, notify);
3706+
3707+ return notify;
3708+}
3709+
3710+static guint ril_register(struct ril_s *ril, guint group,
3711+ const int req, GRilNotifyFunc func,
3712+ gpointer user_data)
3713+{
3714+ struct ril_notify *notify;
3715+ struct ril_notify_node *node;
3716+
3717+ if (ril->notify_list == NULL)
3718+ return 0;
3719+
3720+ if (func == NULL)
3721+ return 0;
3722+
3723+ notify = g_hash_table_lookup(ril->notify_list, &req);
3724+
3725+ if (notify == NULL)
3726+ notify = ril_notify_create(ril, req);
3727+
3728+ if (notify == NULL)
3729+ return 0;
3730+
3731+ node = g_try_new0(struct ril_notify_node, 1);
3732+ if (node == NULL)
3733+ return 0;
3734+
3735+ node->id = ril->next_notify_id++;
3736+ node->gid = group;
3737+ node->callback = func;
3738+ node->user_data = user_data;
3739+
3740+ notify->nodes = g_slist_prepend(notify->nodes, node);
3741+ DBG("after pre-pend; notify: %x, node %x, notify->nodes: %x, callback: %x",
3742+ notify, node, notify->nodes, node->callback);
3743+
3744+ return node->id;
3745+}
3746+
3747+static gboolean ril_unregister(struct ril_s *ril, gboolean mark_only,
3748+ guint group, guint id)
3749+{
3750+ GHashTableIter iter;
3751+ struct ril_notify *notify;
3752+ struct ril_notify_node *node;
3753+ gpointer key, value;
3754+ GSList *l;
3755+
3756+ if (ril->notify_list == NULL)
3757+ return FALSE;
3758+
3759+ g_hash_table_iter_init(&iter, ril->notify_list);
3760+
3761+ while (g_hash_table_iter_next(&iter, &key, &value)) {
3762+ notify = value;
3763+
3764+ l = g_slist_find_custom(notify->nodes, GUINT_TO_POINTER(id),
3765+ ril_notify_node_compare_by_id);
3766+
3767+ if (l == NULL)
3768+ continue;
3769+
3770+ node = l->data;
3771+
3772+ if (node->gid != group)
3773+ return FALSE;
3774+
3775+ if (mark_only) {
3776+ node->destroyed = TRUE;
3777+ return TRUE;
3778+ }
3779+
3780+ ril_notify_node_destroy(node, NULL);
3781+ notify->nodes = g_slist_remove(notify->nodes, node);
3782+
3783+ if (notify->nodes == NULL)
3784+ g_hash_table_iter_remove(&iter);
3785+
3786+ return TRUE;
3787+ }
3788+
3789+ return FALSE;
3790+}
3791+
3792+GRil *g_ril_new()
3793+{
3794+ GRil *ril;
3795+
3796+ ril = g_try_new0(GRil, 1);
3797+ if (ril == NULL)
3798+ return NULL;
3799+
3800+ ril->parent = create_ril();
3801+ if (ril->parent == NULL) {
3802+ g_free(ril);
3803+ return NULL;
3804+ }
3805+
3806+ ril->group = ril->parent->next_gid++;
3807+ ril->ref_count = 1;
3808+
3809+ return ril;
3810+}
3811+
3812+GRil *g_ril_clone(GRil *clone)
3813+{
3814+ GRil *ril;
3815+
3816+ if (clone == NULL)
3817+ return NULL;
3818+
3819+ ril = g_try_new0(GRil, 1);
3820+ if (ril == NULL)
3821+ return NULL;
3822+
3823+ ril->parent = clone->parent;
3824+ ril->group = ril->parent->next_gid++;
3825+ ril->ref_count = 1;
3826+ g_atomic_int_inc(&ril->parent->ref_count);
3827+
3828+ return ril;
3829+}
3830+
3831+GIOChannel *g_ril_get_channel(GRil *ril)
3832+{
3833+ if (ril == NULL || ril->parent->io == NULL)
3834+ return NULL;
3835+
3836+ return g_ril_io_get_channel(ril->parent->io);
3837+
3838+}
3839+
3840+GRilIO *g_ril_get_io(GRil *ril)
3841+{
3842+ if (ril == NULL)
3843+ return NULL;
3844+
3845+ return ril->parent->io;
3846+}
3847+
3848+GRil *g_ril_ref(GRil *ril)
3849+{
3850+ if (ril == NULL)
3851+ return NULL;
3852+
3853+ g_atomic_int_inc(&ril->ref_count);
3854+
3855+ return ril;
3856+}
3857+
3858+guint g_ril_send(GRil *ril, const guint req, const char *data,
3859+ const gsize data_len, GRilResponseFunc func,
3860+ gpointer user_data, GDestroyNotify notify)
3861+{
3862+ struct ril_request *r;
3863+ struct ril_s *p;
3864+
3865+ if (ril == NULL || ril->parent == NULL || ril->parent->command_queue == NULL)
3866+ return 0;
3867+
3868+ p = ril->parent;
3869+
3870+ r = ril_request_create(p, ril->group, req, p->next_cmd_id,
3871+ data, data_len, func,
3872+ user_data, notify, FALSE);
3873+ if (r == NULL)
3874+ return 0;
3875+
3876+ p->next_cmd_id++;
3877+
3878+ g_queue_push_tail(p->command_queue, r);
3879+
3880+ if (g_queue_get_length(p->command_queue) == 1) {
3881+ DBG("calling wakeup_writer: qlen: %d", g_queue_get_length(p->command_queue));
3882+ ril_wakeup_writer(p);
3883+ }
3884+
3885+ return r->id;
3886+}
3887+
3888+void g_ril_suspend(GRil *ril)
3889+{
3890+ if (ril == NULL)
3891+ return;
3892+
3893+ ril_suspend(ril->parent);
3894+}
3895+
3896+void g_ril_resume(GRil *ril)
3897+{
3898+ if (ril == NULL)
3899+ return;
3900+
3901+ ril_resume(ril->parent);
3902+}
3903+
3904+void g_ril_unref(GRil *ril)
3905+{
3906+ gboolean is_zero;
3907+
3908+ if (ril == NULL)
3909+ return;
3910+
3911+ is_zero = g_atomic_int_dec_and_test(&ril->ref_count);
3912+
3913+ if (is_zero == FALSE)
3914+ return;
3915+
3916+ ril_unref(ril->parent);
3917+
3918+ g_free(ril);
3919+}
3920+
3921+gboolean g_ril_set_debug(GRil *ril,
3922+ GRilDebugFunc func, gpointer user_data)
3923+{
3924+
3925+ if (ril == NULL || ril->group != 0)
3926+ return FALSE;
3927+
3928+ return ril_set_debug(ril->parent, func, user_data);
3929+}
3930+
3931+guint g_ril_register(GRil *ril, const int req,
3932+ GRilNotifyFunc func, gpointer user_data)
3933+{
3934+ if (ril == NULL)
3935+ return 0;
3936+
3937+ return ril_register(ril->parent, ril->group, req,
3938+ func, user_data);
3939+}
3940+
3941+gboolean g_ril_unregister(GRil *ril, guint id)
3942+{
3943+ if (ril == NULL)
3944+ return FALSE;
3945+
3946+ return ril_unregister(ril->parent, ril->parent->in_notify,
3947+ ril->group, id);
3948+}
3949+
3950+gboolean g_ril_unregister_all(GRil *ril)
3951+{
3952+ if (ril == NULL)
3953+ return FALSE;
3954+
3955+ return ril_unregister_all(ril->parent,
3956+ ril->parent->in_notify,
3957+ node_compare_by_group,
3958+ GUINT_TO_POINTER(ril->group));
3959+}
3960
3961=== added file 'gril/gril.h'
3962--- gril/gril.h 1970-01-01 00:00:00 +0000
3963+++ gril/gril.h 2013-04-09 20:01:20 +0000
3964@@ -0,0 +1,102 @@
3965+/*
3966+ *
3967+ * RIL library with GLib integration
3968+ *
3969+ * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
3970+ * Copyright (C) 2012 Canonical Ltd.
3971+ *
3972+ * This program is free software; you can redistribute it and/or modify
3973+ * it under the terms of the GNU General Public License version 2 as
3974+ * published by the Free Software Foundation.
3975+ *
3976+ * This program is distributed in the hope that it will be useful,
3977+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3978+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3979+ * GNU General Public License for more details.
3980+ *
3981+ * You should have received a copy of the GNU General Public License
3982+ * along with this program; if not, write to the Free Software
3983+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
3984+ *
3985+ */
3986+
3987+#ifndef __GRIL_H
3988+#define __GRIL_H
3989+
3990+#ifdef __cplusplus
3991+extern "C" {
3992+#endif
3993+
3994+#include "grilresponse.h"
3995+#include "grilutil.h"
3996+#include "grilio.h"
3997+#include "ril_constants.h"
3998+
3999+struct _GRil;
4000+
4001+typedef struct _GRil GRil;
4002+
4003+/*
4004+ * This struct represents an entire RIL message read
4005+ * from the command socket. It can hold responses or
4006+ * unsolicited requests from RILD.
4007+ */
4008+struct ril_msg {
4009+ gchar *buf;
4010+ gsize buf_len;
4011+ gboolean unsolicited;
4012+ int req;
4013+ int serial_no;
4014+ int error;
4015+};
4016+
4017+typedef void (*GRilResponseFunc)(struct ril_msg *message, gpointer user_data);
4018+
4019+typedef void (*GRilNotifyFunc)(struct ril_msg *message, gpointer user_data);
4020+
4021+GRil *g_ril_new();
4022+
4023+GIOChannel *g_ril_get_channel(GRil *ril);
4024+GRilIO *g_ril_get_io(GRil *ril);
4025+
4026+GRil *g_ril_ref(GRil *ril);
4027+void g_ril_unref(GRil *ril);
4028+
4029+GRil *g_ril_clone(GRil *ril);
4030+
4031+void g_ril_suspend(GRil *ril);
4032+void g_ril_resume(GRil *ril);
4033+
4034+gboolean g_ril_set_disconnect_function(GRil *ril, GRilDisconnectFunc disconnect,
4035+ gpointer user_data);
4036+
4037+/*!
4038+ * If the function is not NULL, then on every read/write from the GIOChannel
4039+ * provided to GRil the logging function will be called with the
4040+ * input/output string and user data
4041+ */
4042+gboolean g_ril_set_debug(GRil *ril, GRilDebugFunc func, gpointer user_data);
4043+
4044+/*!
4045+ * Queue an RIL request for execution. The request contents are given
4046+ * in data. Once the command executes, the callback function given by
4047+ * func is called with user provided data in user_data.
4048+ *
4049+ * Returns an id of the queued command which can be canceled using
4050+ * g_ril_cancel. If an error occurred, an id of 0 is returned.
4051+ *
4052+ */
4053+guint g_ril_send(GRil *ril, const guint req, const char *data, const gsize data_len,
4054+ GRilResponseFunc func, gpointer user_data, GDestroyNotify notify);
4055+
4056+guint g_ril_register(GRil *ril, const int req,
4057+ GRilNotifyFunc func, gpointer user_data);
4058+
4059+gboolean g_ril_unregister(GRil *ril, guint id);
4060+gboolean g_ril_unregister_all(GRil *ril);
4061+
4062+#ifdef __cplusplus
4063+}
4064+#endif
4065+
4066+#endif /* __GRIL_H */
4067
4068=== added file 'gril/grilio.c'
4069--- gril/grilio.c 1970-01-01 00:00:00 +0000
4070+++ gril/grilio.c 2013-04-09 20:01:20 +0000
4071@@ -0,0 +1,396 @@
4072+/*
4073+ *
4074+ * RIL chat library with GLib integration
4075+ *
4076+ * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
4077+ * Copyright (C) 2012 Canonical Ltd.
4078+ *
4079+ * This program is free software; you can redistribute it and/or modify
4080+ * it under the terms of the GNU General Public License version 2 as
4081+ * published by the Free Software Foundation.
4082+ *
4083+ * This program is distributed in the hope that it will be useful,
4084+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4085+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4086+ * GNU General Public License for more details.
4087+ *
4088+ * You should have received a copy of the GNU General Public License
4089+ * along with this program; if not, write to the Free Software
4090+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
4091+ *
4092+ */
4093+
4094+#ifdef HAVE_CONFIG_H
4095+#include <config.h>
4096+#endif
4097+
4098+#include <stdio.h>
4099+#include <unistd.h>
4100+#include <string.h>
4101+#include <assert.h>
4102+#include <ctype.h>
4103+#include <errno.h>
4104+
4105+#include <glib.h>
4106+
4107+#include "ringbuffer.h"
4108+#include "grilio.h"
4109+#include "grilutil.h"
4110+
4111+struct _GRilIO {
4112+ gint ref_count; /* Ref count */
4113+ guint read_watch; /* GSource read id, 0 if no */
4114+ guint write_watch; /* GSource write id, 0 if no */
4115+ GIOChannel *channel; /* comms channel */
4116+ GRilDisconnectFunc user_disconnect; /* user disconnect func */
4117+ gpointer user_disconnect_data; /* user disconnect data */
4118+ struct ring_buffer *buf; /* Current read buffer */
4119+ guint max_read_attempts; /* max reads / select */
4120+ GRilIOReadFunc read_handler; /* Read callback */
4121+ gpointer read_data; /* Read callback userdata */
4122+ gboolean use_write_watch; /* Use write select */
4123+ GRilIOWriteFunc write_handler; /* Write callback */
4124+ gpointer write_data; /* Write callback userdata */
4125+ GRilDebugFunc debugf; /* debugging output function */
4126+ gpointer debug_data; /* Data to pass to debug func */
4127+ GRilDisconnectFunc write_done_func; /* tx empty notifier */
4128+ gpointer write_done_data; /* tx empty data */
4129+ gboolean destroyed; /* Re-entrancy guard */
4130+};
4131+
4132+static void read_watcher_destroy_notify(gpointer user_data)
4133+{
4134+ GRilIO *io = user_data;
4135+
4136+ ring_buffer_free(io->buf);
4137+ io->buf = NULL;
4138+
4139+ io->debugf = NULL;
4140+ io->debug_data = NULL;
4141+
4142+ io->read_watch = 0;
4143+ io->read_handler = NULL;
4144+ io->read_data = NULL;
4145+
4146+ io->channel = NULL;
4147+
4148+ if (io->destroyed)
4149+ g_free(io);
4150+ else if (io->user_disconnect)
4151+ io->user_disconnect(io->user_disconnect_data);
4152+}
4153+
4154+static gboolean received_data(GIOChannel *channel, GIOCondition cond,
4155+ gpointer data)
4156+{
4157+ unsigned char *buf;
4158+ GRilIO *io = data;
4159+ GIOStatus status;
4160+ gsize rbytes;
4161+ gsize toread;
4162+ gsize total_read = 0;
4163+ guint read_count = 0;
4164+
4165+ if (cond & G_IO_NVAL)
4166+ return FALSE;
4167+
4168+ /* Regardless of condition, try to read all the data available */
4169+ do {
4170+ toread = ring_buffer_avail_no_wrap(io->buf);
4171+
4172+ if (toread == 0)
4173+ break;
4174+
4175+ rbytes = 0;
4176+ buf = ring_buffer_write_ptr(io->buf, 0);
4177+
4178+ status = g_io_channel_read_chars(channel, (char *) buf,
4179+ toread, &rbytes, NULL);
4180+
4181+ g_ril_util_debug_hexdump(TRUE, (char *)buf, rbytes,
4182+ io->debugf, io->debug_data);
4183+
4184+ read_count++;
4185+
4186+ total_read += rbytes;
4187+
4188+ if (rbytes > 0)
4189+ ring_buffer_write_advance(io->buf, rbytes);
4190+
4191+ } while (status == G_IO_STATUS_NORMAL && rbytes > 0 &&
4192+ read_count < io->max_read_attempts);
4193+
4194+ if (total_read > 0 && io->read_handler)
4195+ io->read_handler(io->buf, io->read_data);
4196+
4197+ if (cond & (G_IO_HUP | G_IO_ERR))
4198+ return FALSE;
4199+
4200+ if (read_count > 0 && rbytes == 0 && status != G_IO_STATUS_AGAIN)
4201+ return FALSE;
4202+
4203+ /* We're overflowing the buffer, shutdown the socket */
4204+ if (ring_buffer_avail(io->buf) == 0)
4205+ return FALSE;
4206+
4207+ return TRUE;
4208+}
4209+
4210+gsize g_ril_io_write(GRilIO *io, const gchar *data, gsize count)
4211+{
4212+ GIOStatus status;
4213+ gsize bytes_written;
4214+
4215+ status = g_io_channel_write_chars(io->channel, data,
4216+ count, &bytes_written, NULL);
4217+
4218+ if (status != G_IO_STATUS_NORMAL) {
4219+ g_source_remove(io->read_watch);
4220+ return 0;
4221+ }
4222+
4223+ g_ril_util_debug_hexdump(FALSE, data, bytes_written,
4224+ io->debugf, io->debug_data);
4225+
4226+ return bytes_written;
4227+}
4228+
4229+static void write_watcher_destroy_notify(gpointer user_data)
4230+{
4231+ GRilIO *io = user_data;
4232+
4233+ io->write_watch = 0;
4234+ io->write_handler = NULL;
4235+ io->write_data = NULL;
4236+
4237+ if (io->write_done_func) {
4238+ io->write_done_func(io->write_done_data);
4239+ io->write_done_func = NULL;
4240+ io->write_done_data = NULL;
4241+ }
4242+}
4243+
4244+static gboolean can_write_data(GIOChannel *channel, GIOCondition cond,
4245+ gpointer data)
4246+{
4247+ GRilIO *io = data;
4248+
4249+ if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR))
4250+ return FALSE;
4251+
4252+ if (io->write_handler == NULL)
4253+ return FALSE;
4254+
4255+ return io->write_handler(io->write_data);
4256+}
4257+
4258+static GRilIO *create_io(GIOChannel *channel, GIOFlags flags)
4259+{
4260+ GRilIO *io;
4261+
4262+ if (channel == NULL)
4263+ return NULL;
4264+
4265+ io = g_try_new0(GRilIO, 1);
4266+ if (io == NULL)
4267+ return io;
4268+
4269+ io->ref_count = 1;
4270+ io->debugf = NULL;
4271+
4272+ if (flags & G_IO_FLAG_NONBLOCK) {
4273+ io->max_read_attempts = 3;
4274+ io->use_write_watch = TRUE;
4275+ } else {
4276+ io->max_read_attempts = 1;
4277+ io->use_write_watch = FALSE;
4278+ }
4279+
4280+ io->buf = ring_buffer_new(8192);
4281+
4282+ if (!io->buf)
4283+ goto error;
4284+
4285+ if (!g_ril_util_setup_io(channel, flags))
4286+ goto error;
4287+
4288+ io->channel = channel;
4289+ io->read_watch = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT,
4290+ G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
4291+ received_data, io,
4292+ read_watcher_destroy_notify);
4293+
4294+ return io;
4295+
4296+error:
4297+ if (io->buf)
4298+ ring_buffer_free(io->buf);
4299+
4300+ g_free(io);
4301+
4302+ return NULL;
4303+}
4304+
4305+GRilIO *g_ril_io_new(GIOChannel *channel)
4306+{
4307+ return create_io(channel, G_IO_FLAG_NONBLOCK);
4308+}
4309+
4310+GRilIO *g_ril_io_new_blocking(GIOChannel *channel)
4311+{
4312+ return create_io(channel, 0);
4313+}
4314+
4315+GIOChannel *g_ril_io_get_channel(GRilIO *io)
4316+{
4317+ if (io == NULL)
4318+ return NULL;
4319+
4320+ return io->channel;
4321+}
4322+
4323+gboolean g_ril_io_set_read_handler(GRilIO *io, GRilIOReadFunc read_handler,
4324+ gpointer user_data)
4325+{
4326+ if (io == NULL)
4327+ return FALSE;
4328+
4329+ io->read_handler = read_handler;
4330+ io->read_data = user_data;
4331+
4332+ if (read_handler && ring_buffer_len(io->buf) > 0)
4333+ read_handler(io->buf, user_data);
4334+
4335+ return TRUE;
4336+}
4337+
4338+static gboolean call_blocking_read(gpointer user_data)
4339+{
4340+ GRilIO *io = user_data;
4341+
4342+ while (can_write_data(io->channel, G_IO_OUT, io) == TRUE);
4343+ write_watcher_destroy_notify(io);
4344+
4345+ return FALSE;
4346+}
4347+
4348+gboolean g_ril_io_set_write_handler(GRilIO *io, GRilIOWriteFunc write_handler,
4349+ gpointer user_data)
4350+{
4351+ if (io == NULL)
4352+ return FALSE;
4353+
4354+ if (io->write_watch > 0) {
4355+ if (write_handler == NULL) {
4356+ g_source_remove(io->write_watch);
4357+ return TRUE;
4358+ }
4359+
4360+ return FALSE;
4361+ }
4362+
4363+ if (write_handler == NULL)
4364+ return FALSE;
4365+
4366+ io->write_handler = write_handler;
4367+ io->write_data = user_data;
4368+
4369+ if (io->use_write_watch == TRUE)
4370+ io->write_watch = g_io_add_watch_full(io->channel,
4371+ G_PRIORITY_HIGH,
4372+ G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
4373+ can_write_data, io,
4374+ write_watcher_destroy_notify);
4375+ else
4376+ io->write_watch = g_idle_add(call_blocking_read, io);
4377+
4378+ return TRUE;
4379+}
4380+
4381+GRilIO *g_ril_io_ref(GRilIO *io)
4382+{
4383+ if (io == NULL)
4384+ return NULL;
4385+
4386+ g_atomic_int_inc(&io->ref_count);
4387+
4388+ return io;
4389+}
4390+
4391+static gboolean io_shutdown(GRilIO *io)
4392+{
4393+ /* Don't trigger user disconnect on shutdown */
4394+ io->user_disconnect = NULL;
4395+ io->user_disconnect_data = NULL;
4396+
4397+ if (io->read_watch > 0)
4398+ g_source_remove(io->read_watch);
4399+
4400+ if (io->write_watch > 0)
4401+ g_source_remove(io->write_watch);
4402+
4403+ return TRUE;
4404+}
4405+
4406+void g_ril_io_unref(GRilIO *io)
4407+{
4408+ gboolean is_zero;
4409+
4410+ if (io == NULL)
4411+ return;
4412+
4413+ is_zero = g_atomic_int_dec_and_test(&io->ref_count);
4414+
4415+ if (is_zero == FALSE)
4416+ return;
4417+
4418+ io_shutdown(io);
4419+
4420+ /* glib delays the destruction of the watcher until it exits, this
4421+ * means we can't free the data just yet, even though we've been
4422+ * destroyed already. We have to wait until the read_watcher
4423+ * destroy function gets called
4424+ */
4425+ if (io->read_watch > 0)
4426+ io->destroyed = TRUE;
4427+ else
4428+ g_free(io);
4429+}
4430+
4431+gboolean g_ril_io_set_disconnect_function(GRilIO *io,
4432+ GRilDisconnectFunc disconnect, gpointer user_data)
4433+{
4434+ if (io == NULL)
4435+ return FALSE;
4436+
4437+ io->user_disconnect = disconnect;
4438+ io->user_disconnect_data = user_data;
4439+
4440+ return TRUE;
4441+}
4442+
4443+gboolean g_ril_io_set_debug(GRilIO *io, GRilDebugFunc func, gpointer user_data)
4444+{
4445+ if (io == NULL)
4446+ return FALSE;
4447+
4448+ io->debugf = func;
4449+ io->debug_data = user_data;
4450+
4451+ return TRUE;
4452+}
4453+
4454+void g_ril_io_set_write_done(GRilIO *io, GRilDisconnectFunc func,
4455+ gpointer user_data)
4456+{
4457+ if (io == NULL)
4458+ return;
4459+
4460+ io->write_done_func = func;
4461+ io->write_done_data = user_data;
4462+}
4463+
4464+void g_ril_io_drain_ring_buffer(GRilIO *io, guint len)
4465+{
4466+ ring_buffer_drain(io->buf, len);
4467+}
4468
4469=== added file 'gril/grilio.h'
4470--- gril/grilio.h 1970-01-01 00:00:00 +0000
4471+++ gril/grilio.h 2013-04-09 20:01:20 +0000
4472@@ -0,0 +1,69 @@
4473+/*
4474+ *
4475+ * RIL chat library with GLib integration
4476+ *
4477+ * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
4478+ * Copyright (C) 2012 Canonical Ltd.
4479+ *
4480+ * This program is free software; you can redistribute it and/or modify
4481+ * it under the terms of the GNU General Public License version 2 as
4482+ * published by the Free Software Foundation.
4483+ *
4484+ * This program is distributed in the hope that it will be useful,
4485+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4486+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4487+ * GNU General Public License for more details.
4488+ *
4489+ * You should have received a copy of the GNU General Public License
4490+ * along with this program; if not, write to the Free Software
4491+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
4492+ *
4493+ */
4494+
4495+#ifndef __GRILIO_H
4496+#define __GRILIO_H
4497+
4498+#ifdef __cplusplus
4499+extern "C" {
4500+#endif
4501+
4502+#include "gfunc.h"
4503+
4504+struct _GRilIO;
4505+
4506+typedef struct _GRilIO GRilIO;
4507+
4508+struct ring_buffer;
4509+
4510+typedef void (*GRilIOReadFunc)(struct ring_buffer *buffer, gpointer user_data);
4511+typedef gboolean (*GRilIOWriteFunc)(gpointer user_data);
4512+
4513+GRilIO *g_ril_io_new(GIOChannel *channel);
4514+GRilIO *g_ril_io_new_blocking(GIOChannel *channel);
4515+
4516+GIOChannel *g_ril_io_get_channel(GRilIO *io);
4517+
4518+GRilIO *g_ril_io_ref(GRilIO *io);
4519+void g_ril_io_unref(GRilIO *io);
4520+
4521+gboolean g_ril_io_set_read_handler(GRilIO *io, GRilIOReadFunc read_handler,
4522+ gpointer user_data);
4523+gboolean g_ril_io_set_write_handler(GRilIO *io, GRilIOWriteFunc write_handler,
4524+ gpointer user_data);
4525+void g_ril_io_set_write_done(GRilIO *io, GRilDisconnectFunc func,
4526+ gpointer user_data);
4527+
4528+void g_ril_io_drain_ring_buffer(GRilIO *io, guint len);
4529+
4530+gsize g_ril_io_write(GRilIO *io, const gchar *data, gsize count);
4531+
4532+gboolean g_ril_io_set_disconnect_function(GRilIO *io,
4533+ GRilDisconnectFunc disconnect, gpointer user_data);
4534+
4535+gboolean g_ril_io_set_debug(GRilIO *io, GRilDebugFunc func, gpointer user_data);
4536+
4537+#ifdef __cplusplus
4538+}
4539+#endif
4540+
4541+#endif /* __GRILIO_H */
4542
4543=== added file 'gril/grilresponse.h'
4544--- gril/grilresponse.h 1970-01-01 00:00:00 +0000
4545+++ gril/grilresponse.h 2013-04-09 20:01:20 +0000
4546@@ -0,0 +1,46 @@
4547+/*
4548+ *
4549+ * RIL chat library with GLib integration
4550+ *
4551+ * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
4552+ * Copyright (C) 2012 Canonical Ltd.
4553+ *
4554+ * This program is free software; you can redistribute it and/or modify
4555+ * it under the terms of the GNU General Public License version 2 as
4556+ * published by the Free Software Foundation.
4557+ *
4558+ * This program is distributed in the hope that it will be useful,
4559+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4560+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4561+ * GNU General Public License for more details.
4562+ *
4563+ * You should have received a copy of the GNU General Public License
4564+ * along with this program; if not, write to the Free Software
4565+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
4566+ *
4567+ */
4568+
4569+#ifndef __GRIL_RESPONSE_H
4570+#define __GRIL_RESPONSE_H
4571+
4572+#ifdef __cplusplus
4573+extern "C" {
4574+#endif
4575+
4576+struct _GRilResponse {
4577+ GSList *lines;
4578+ char *final_or_pdu;
4579+};
4580+
4581+typedef struct _GRilResponse GRilResponse;
4582+
4583+#define G_RIL_RESPONSE_LINE_LENGTH_MAX 2048
4584+
4585+const char *g_ril_final_response(GRilResponse *response);
4586+const char *g_ril_response_pdu(GRilResponse *response);
4587+
4588+#ifdef __cplusplus
4589+}
4590+#endif
4591+
4592+#endif /* __GRIL_RESPONSE_H */
4593
4594=== added file 'gril/grilutil.c'
4595--- gril/grilutil.c 1970-01-01 00:00:00 +0000
4596+++ gril/grilutil.c 2013-04-09 20:01:20 +0000
4597@@ -0,0 +1,499 @@
4598+/*
4599+ *
4600+ * RIL library with GLib integration
4601+ *
4602+ * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
4603+ * Copyright (C) 2012 Canonical Ltd.
4604+ *
4605+ * This program is free software; you can redistribute it and/or modify
4606+ * it under the terms of the GNU General Public License version 2 as
4607+ * published by the Free Software Foundation.
4608+ *
4609+ * This program is distributed in the hope that it will be useful,
4610+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4611+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4612+ * GNU General Public License for more details.
4613+ *
4614+ * You should have received a copy of the GNU General Public License
4615+ * along with this program; if not, write to the Free Software
4616+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
4617+ *
4618+ */
4619+
4620+#ifdef HAVE_CONFIG_H
4621+#include <config.h>
4622+#endif
4623+
4624+#include <stdio.h>
4625+#include <ctype.h>
4626+#include <string.h>
4627+
4628+#include <glib.h>
4629+
4630+#include "grilutil.h"
4631+#include "ril_constants.h"
4632+
4633+const char *ril_appstate_to_string(int app_state)
4634+{
4635+ switch (app_state) {
4636+ case RIL_APPSTATE_UNKNOWN:
4637+ return "UNKNOWN";
4638+ case RIL_APPSTATE_DETECTED:
4639+ return "DETECTED";
4640+ case RIL_APPSTATE_PIN:
4641+ return "PIN";
4642+ case RIL_APPSTATE_PUK:
4643+ return "PUK";
4644+ case RIL_APPSTATE_SUBSCRIPTION_PERSO:
4645+ return "";
4646+ case RIL_APPSTATE_READY:
4647+ return "READY";
4648+ default:
4649+ return "<INVALID>";
4650+ }
4651+}
4652+
4653+const char *ril_apptype_to_string(int app_type)
4654+{
4655+
4656+ switch (app_type) {
4657+ case RIL_APPTYPE_UNKNOWN:
4658+ return "UNKNOWN";
4659+ case RIL_APPTYPE_SIM:
4660+ return "SIM";
4661+ case RIL_APPTYPE_USIM:
4662+ return "USIM";
4663+ case RIL_APPTYPE_RUIM:
4664+ return "RUIM";
4665+ case RIL_APPTYPE_CSIM:
4666+ return "CSIM";
4667+ case RIL_APPTYPE_ISIM:
4668+ return "ISIM";
4669+ default:
4670+ return "<INVALID>";
4671+ }
4672+}
4673+
4674+const char *ril_cardstate_to_string(int card_state)
4675+{
4676+ switch (card_state) {
4677+ case RIL_CARDSTATE_ABSENT:
4678+ return "ABSENT";
4679+ case RIL_CARDSTATE_PRESENT:
4680+ return "PRESENT";
4681+ case RIL_CARDSTATE_ERROR:
4682+ return "ERROR";
4683+ default:
4684+ return "<INVALID>";
4685+ }
4686+}
4687+
4688+const char *ril_pinstate_to_string(int pin_state)
4689+{
4690+ switch (pin_state) {
4691+ case RIL_PINSTATE_UNKNOWN:
4692+ return "UNKNOWN";
4693+ case RIL_PINSTATE_ENABLED_NOT_VERIFIED:
4694+ return "ENABLED_NOT_VERIFIED";
4695+ case RIL_PINSTATE_ENABLED_VERIFIED:
4696+ return "ENABLED_VERIFIED";
4697+ case RIL_PINSTATE_DISABLED:
4698+ return "DISABLED";
4699+ case RIL_PINSTATE_ENABLED_BLOCKED:
4700+ return "ENABLED_BLOCKED";
4701+ case RIL_PINSTATE_ENABLED_PERM_BLOCKED:
4702+ return "ENABLED_PERM_BLOCKED";
4703+ default:
4704+ return "<INVALID>";
4705+ }
4706+}
4707+
4708+const char *ril_request_id_to_string(int req)
4709+{
4710+ switch (req) {
4711+ case RIL_REQUEST_GET_SIM_STATUS:
4712+ return "RIL_REQUEST_GET_SIM_STATUS";
4713+ case RIL_REQUEST_ENTER_SIM_PIN:
4714+ return "RIL_REQUEST_ENTER_SIM_PIN";
4715+ case RIL_REQUEST_ENTER_SIM_PUK:
4716+ return "RIL_REQUEST_ENTER_SIM_PUK";
4717+ case RIL_REQUEST_ENTER_SIM_PIN2:
4718+ return "RIL_REQUEST_ENTER_SIM_PIN2";
4719+ case RIL_REQUEST_ENTER_SIM_PUK2:
4720+ return "RIL_REQUEST_ENTER_SIM_PUK2";
4721+ case RIL_REQUEST_CHANGE_SIM_PIN:
4722+ return "RIL_REQUEST_CHANGE_SIM_PIN";
4723+ case RIL_REQUEST_CHANGE_SIM_PIN2:
4724+ return "RIL_REQUEST_CHANGE_SIM_PIN2";
4725+ case RIL_REQUEST_ENTER_NETWORK_DEPERSONALIZATION:
4726+ return "RIL_REQUEST_ENTER_NETWORK_DEPERSONALIZATION";
4727+ case RIL_REQUEST_GET_CURRENT_CALLS:
4728+ return "RIL_REQUEST_GET_CURRENT_CALLS";
4729+ case RIL_REQUEST_DIAL:
4730+ return "RIL_REQUEST_DIAL";
4731+ case RIL_REQUEST_GET_IMSI:
4732+ return "RIL_REQUEST_GET_IMSI";
4733+ case RIL_REQUEST_HANGUP:
4734+ return "RIL_REQUEST_HANGUP";
4735+ case RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND:
4736+ return "RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND";
4737+ case RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND:
4738+ return "RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND";
4739+ case RIL_REQUEST_SWITCH_HOLDING_AND_ACTIVE:
4740+ return "RIL_REQUEST_SWITCH_HOLDING_AND_ACTIVE";
4741+ case RIL_REQUEST_CONFERENCE:
4742+ return "RIL_REQUEST_CONFERENCE";
4743+ case RIL_REQUEST_UDUB:
4744+ return "RIL_REQUEST_UDUB";
4745+ case RIL_REQUEST_LAST_CALL_FAIL_CAUSE:
4746+ return "RIL_REQUEST_LAST_CALL_FAIL_CAUSE";
4747+ case RIL_REQUEST_SIGNAL_STRENGTH:
4748+ return "RIL_REQUEST_SIGNAL_STRENGTH";
4749+ case RIL_REQUEST_VOICE_REGISTRATION_STATE:
4750+ return "RIL_REQUEST_VOICE_REGISTRATION_STATE";
4751+ case RIL_REQUEST_DATA_REGISTRATION_STATE:
4752+ return "RIL_REQUEST_DATA_REGISTRATION_STATE";
4753+ case RIL_REQUEST_OPERATOR:
4754+ return "RIL_REQUEST_OPERATOR";
4755+ case RIL_REQUEST_RADIO_POWER:
4756+ return "RIL_REQUEST_RADIO_POWER";
4757+ case RIL_REQUEST_DTMF:
4758+ return "RIL_REQUEST_DTMF";
4759+ case RIL_REQUEST_SEND_SMS:
4760+ return "RIL_REQUEST_SEND_SMS";
4761+ case RIL_REQUEST_SEND_SMS_EXPECT_MORE:
4762+ return "RIL_REQUEST_SEND_SMS_EXPECT_MORE";
4763+ case RIL_REQUEST_SETUP_DATA_CALL:
4764+ return "RIL_REQUEST_SETUP_DATA_CALL";
4765+ case RIL_REQUEST_SIM_IO:
4766+ return "RIL_REQUEST_SIM_IO";
4767+ case RIL_REQUEST_SEND_USSD:
4768+ return "RIL_REQUEST_SEND_USSD";
4769+ case RIL_REQUEST_CANCEL_USSD:
4770+ return "RIL_REQUEST_CANCEL_USSD";
4771+ case RIL_REQUEST_GET_CLIR:
4772+ return "RIL_REQUEST_GET_CLIR";
4773+ case RIL_REQUEST_SET_CLIR:
4774+ return "RIL_REQUEST_SET_CLIR";
4775+ case RIL_REQUEST_QUERY_CALL_FORWARD_STATUS:
4776+ return "RIL_REQUEST_QUERY_CALL_FORWARD_STATUS";
4777+ case RIL_REQUEST_SET_CALL_FORWARD:
4778+ return "RIL_REQUEST_SET_CALL_FORWARD";
4779+ case RIL_REQUEST_QUERY_CALL_WAITING:
4780+ return "RIL_REQUEST_QUERY_CALL_WAITING";
4781+ case RIL_REQUEST_SET_CALL_WAITING:
4782+ return "RIL_REQUEST_SET_CALL_WAITING";
4783+ case RIL_REQUEST_SMS_ACKNOWLEDGE :
4784+ return "RIL_REQUEST_SMS_ACKNOWLEDGE ";
4785+ case RIL_REQUEST_GET_IMEI:
4786+ return "RIL_REQUEST_GET_IMEI";
4787+ case RIL_REQUEST_GET_IMEISV:
4788+ return "RIL_REQUEST_GET_IMEISV";
4789+ case RIL_REQUEST_ANSWER:
4790+ return "RIL_REQUEST_ANSWER";
4791+ case RIL_REQUEST_DEACTIVATE_DATA_CALL:
4792+ return "RIL_REQUEST_DEACTIVATE_DATA_CALL";
4793+ case RIL_REQUEST_QUERY_FACILITY_LOCK:
4794+ return "RIL_REQUEST_QUERY_FACILITY_LOCK";
4795+ case RIL_REQUEST_SET_FACILITY_LOCK:
4796+ return "RIL_REQUEST_SET_FACILITY_LOCK";
4797+ case RIL_REQUEST_CHANGE_BARRING_PASSWORD:
4798+ return "RIL_REQUEST_CHANGE_BARRING_PASSWORD";
4799+ case RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE:
4800+ return "RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE";
4801+ case RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC:
4802+ return "RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC";
4803+ case RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL:
4804+ return "RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL";
4805+ case RIL_REQUEST_QUERY_AVAILABLE_NETWORKS:
4806+ return "RIL_REQUEST_QUERY_AVAILABLE_NETWORKS";
4807+ case RIL_REQUEST_DTMF_START:
4808+ return "RIL_REQUEST_DTMF_START";
4809+ case RIL_REQUEST_DTMF_STOP:
4810+ return "RIL_REQUEST_DTMF_STOP";
4811+ case RIL_REQUEST_BASEBAND_VERSION:
4812+ return "RIL_REQUEST_BASEBAND_VERSION";
4813+ case RIL_REQUEST_SEPARATE_CONNECTION:
4814+ return "RIL_REQUEST_SEPARATE_CONNECTION";
4815+ case RIL_REQUEST_SET_MUTE:
4816+ return "RIL_REQUEST_SET_MUTE";
4817+ case RIL_REQUEST_GET_MUTE:
4818+ return "RIL_REQUEST_GET_MUTE";
4819+ case RIL_REQUEST_QUERY_CLIP:
4820+ return "RIL_REQUEST_QUERY_CLIP";
4821+ case RIL_REQUEST_LAST_DATA_CALL_FAIL_CAUSE:
4822+ return "RIL_REQUEST_LAST_DATA_CALL_FAIL_CAUSE";
4823+ case RIL_REQUEST_DATA_CALL_LIST:
4824+ return "RIL_REQUEST_DATA_CALL_LIST";
4825+ case RIL_REQUEST_RESET_RADIO:
4826+ return "RIL_REQUEST_RESET_RADIO";
4827+ case RIL_REQUEST_OEM_HOOK_RAW:
4828+ return "RIL_REQUEST_OEM_HOOK_RAW";
4829+ case RIL_REQUEST_OEM_HOOK_STRINGS:
4830+ return "RIL_REQUEST_OEM_HOOK_STRINGS";
4831+ case RIL_REQUEST_SCREEN_STATE:
4832+ return "RIL_REQUEST_SCREEN_STATE";
4833+ case RIL_REQUEST_SET_SUPP_SVC_NOTIFICATION:
4834+ return "RIL_REQUEST_SET_SUPP_SVC_NOTIFICATION";
4835+ case RIL_REQUEST_WRITE_SMS_TO_SIM:
4836+ return "RIL_REQUEST_WRITE_SMS_TO_SIM";
4837+ case RIL_REQUEST_DELETE_SMS_ON_SIM:
4838+ return "RIL_REQUEST_DELETE_SMS_ON_SIM";
4839+ case RIL_REQUEST_SET_BAND_MODE:
4840+ return "RIL_REQUEST_SET_BAND_MODE";
4841+ case RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE:
4842+ return "RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE";
4843+ case RIL_REQUEST_STK_GET_PROFILE:
4844+ return "RIL_REQUEST_STK_GET_PROFILE";
4845+ case RIL_REQUEST_STK_SET_PROFILE:
4846+ return "RIL_REQUEST_STK_SET_PROFILE";
4847+ case RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND:
4848+ return "RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND";
4849+ case RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE:
4850+ return "RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE";
4851+ case RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM:
4852+ return "RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM";
4853+ case RIL_REQUEST_EXPLICIT_CALL_TRANSFER:
4854+ return "RIL_REQUEST_EXPLICIT_CALL_TRANSFER";
4855+ case RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE:
4856+ return "RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE";
4857+ case RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE:
4858+ return "RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE";
4859+ case RIL_REQUEST_GET_NEIGHBORING_CELL_IDS:
4860+ return "RIL_REQUEST_GET_NEIGHBORING_CELL_IDS";
4861+ case RIL_REQUEST_SET_LOCATION_UPDATES:
4862+ return "RIL_REQUEST_SET_LOCATION_UPDATES";
4863+ case RIL_REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE:
4864+ return "RIL_REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE";
4865+ case RIL_REQUEST_CDMA_SET_ROAMING_PREFERENCE:
4866+ return "RIL_REQUEST_CDMA_SET_ROAMING_PREFERENCE";
4867+ case RIL_REQUEST_CDMA_QUERY_ROAMING_PREFERENCE:
4868+ return "RIL_REQUEST_CDMA_QUERY_ROAMING_PREFERENCE";
4869+ case RIL_REQUEST_SET_TTY_MODE:
4870+ return "RIL_REQUEST_SET_TTY_MODE";
4871+ case RIL_REQUEST_QUERY_TTY_MODE:
4872+ return "RIL_REQUEST_QUERY_TTY_MODE";
4873+ case RIL_REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE:
4874+ return "RIL_REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE";
4875+ case RIL_REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE:
4876+ return "RIL_REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE";
4877+ case RIL_REQUEST_CDMA_FLASH:
4878+ return "RIL_REQUEST_CDMA_FLASH";
4879+ case RIL_REQUEST_CDMA_BURST_DTMF:
4880+ return "RIL_REQUEST_CDMA_BURST_DTMF";
4881+ case RIL_REQUEST_CDMA_VALIDATE_AND_WRITE_AKEY:
4882+ return "RIL_REQUEST_CDMA_VALIDATE_AND_WRITE_AKEY";
4883+ case RIL_REQUEST_CDMA_SEND_SMS:
4884+ return "RIL_REQUEST_CDMA_SEND_SMS";
4885+ case RIL_REQUEST_CDMA_SMS_ACKNOWLEDGE:
4886+ return "RIL_REQUEST_CDMA_SMS_ACKNOWLEDGE";
4887+ case RIL_REQUEST_GSM_GET_BROADCAST_SMS_CONFIG:
4888+ return "RIL_REQUEST_GSM_GET_BROADCAST_SMS_CONFIG";
4889+ case RIL_REQUEST_GSM_SET_BROADCAST_SMS_CONFIG:
4890+ return "RIL_REQUEST_GSM_SET_BROADCAST_SMS_CONFIG";
4891+ case RIL_REQUEST_GSM_SMS_BROADCAST_ACTIVATION:
4892+ return "RIL_REQUEST_GSM_SMS_BROADCAST_ACTIVATION";
4893+ case RIL_REQUEST_CDMA_GET_BROADCAST_SMS_CONFIG:
4894+ return "RIL_REQUEST_CDMA_GET_BROADCAST_SMS_CONFIG";
4895+ case RIL_REQUEST_CDMA_SET_BROADCAST_SMS_CONFIG:
4896+ return "RIL_REQUEST_CDMA_SET_BROADCAST_SMS_CONFIG";
4897+ case RIL_REQUEST_CDMA_SMS_BROADCAST_ACTIVATION:
4898+ return "RIL_REQUEST_CDMA_SMS_BROADCAST_ACTIVATION";
4899+ case RIL_REQUEST_CDMA_SUBSCRIPTION:
4900+ return "RIL_REQUEST_CDMA_SUBSCRIPTION";
4901+ case RIL_REQUEST_CDMA_WRITE_SMS_TO_RUIM:
4902+ return "RIL_REQUEST_CDMA_WRITE_SMS_TO_RUIM";
4903+ case RIL_REQUEST_CDMA_DELETE_SMS_ON_RUIM:
4904+ return "RIL_REQUEST_CDMA_DELETE_SMS_ON_RUIM";
4905+ case RIL_REQUEST_DEVICE_IDENTITY:
4906+ return "RIL_REQUEST_DEVICE_IDENTITY";
4907+ case RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE:
4908+ return "RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE";
4909+ case RIL_REQUEST_GET_SMSC_ADDRESS:
4910+ return "RIL_REQUEST_GET_SMSC_ADDRESS";
4911+ case RIL_REQUEST_SET_SMSC_ADDRESS:
4912+ return "RIL_REQUEST_SET_SMSC_ADDRESS";
4913+ case RIL_REQUEST_REPORT_SMS_MEMORY_STATUS:
4914+ return "RIL_REQUEST_REPORT_SMS_MEMORY_STATUS";
4915+ case RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING:
4916+ return "RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING";
4917+ case RIL_REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE:
4918+ return "RIL_REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE";
4919+ case RIL_REQUEST_ISIM_AUTHENTICATION:
4920+ return "RIL_REQUEST_ISIM_AUTHENTICATION";
4921+ case RIL_REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU:
4922+ return "RIL_REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU";
4923+ case RIL_REQUEST_STK_SEND_ENVELOPE_WITH_STATUS:
4924+ return "RIL_REQUEST_STK_SEND_ENVELOPE_WITH_STATUS";
4925+ default:
4926+ return "<INVALID>";
4927+ }
4928+}
4929+
4930+void g_ril_util_debug_chat(gboolean in, const char *str, gsize len,
4931+ GRilDebugFunc debugf, gpointer user_data)
4932+{
4933+ char type = in ? '<' : '>';
4934+ gsize escaped = 2; /* Enough for '<', ' ' */
4935+ char *escaped_str;
4936+ const char *esc = "<ESC>";
4937+ gsize esc_size = strlen(esc);
4938+ const char *ctrlz = "<CtrlZ>";
4939+ gsize ctrlz_size = strlen(ctrlz);
4940+ gsize i;
4941+
4942+ if (debugf == NULL || !len)
4943+ return;
4944+
4945+ for (i = 0; i < len; i++) {
4946+ char c = str[i];
4947+
4948+ if (g_ascii_isprint(c))
4949+ escaped += 1;
4950+ else if (c == '\r' || c == '\t' || c == '\n')
4951+ escaped += 2;
4952+ else if (c == 26)
4953+ escaped += ctrlz_size;
4954+ else if (c == 25)
4955+ escaped += esc_size;
4956+ else
4957+ escaped += 4;
4958+ }
4959+
4960+ escaped_str = g_try_malloc(escaped + 1);
4961+ if (escaped_str == NULL)
4962+ return;
4963+
4964+ escaped_str[0] = type;
4965+ escaped_str[1] = ' ';
4966+ escaped_str[2] = '\0';
4967+ escaped_str[escaped] = '\0';
4968+
4969+ for (escaped = 2, i = 0; i < len; i++) {
4970+ unsigned char c = str[i];
4971+
4972+ switch (c) {
4973+ case '\r':
4974+ escaped_str[escaped++] = '\\';
4975+ escaped_str[escaped++] = 'r';
4976+ break;
4977+ case '\t':
4978+ escaped_str[escaped++] = '\\';
4979+ escaped_str[escaped++] = 't';
4980+ break;
4981+ case '\n':
4982+ escaped_str[escaped++] = '\\';
4983+ escaped_str[escaped++] = 'n';
4984+ break;
4985+ case 26:
4986+ strncpy(&escaped_str[escaped], ctrlz, ctrlz_size);
4987+ escaped += ctrlz_size;
4988+ break;
4989+ case 25:
4990+ strncpy(&escaped_str[escaped], esc, esc_size);
4991+ escaped += esc_size;
4992+ break;
4993+ default:
4994+ if (g_ascii_isprint(c))
4995+ escaped_str[escaped++] = c;
4996+ else {
4997+ escaped_str[escaped++] = '\\';
4998+ escaped_str[escaped++] = '0' + ((c >> 6) & 07);
4999+ escaped_str[escaped++] = '0' + ((c >> 3) & 07);
5000+ escaped_str[escaped++] = '0' + (c & 07);
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches