Merge lp:~awe/phablet-extras/ofono-raring into lp:phablet-extras/ofono
- ofono-raring
- Merge into ofono
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 |
Related bugs: |
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.
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.
PS Jenkins bot (ps-jenkins) wrote : | # |
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/
/home/phablet/
plugins/hfp_hf.o: In function `hfp_agent_
/home/phablet/
plugins/hfp_hf.o: In function `service_
/home/phablet/
collect2: error: ld returned 1 exit status
make[2]: *** [src/ofonod] Error 1
make[1]: *** [all] Error 2
make[1]: Leaving directory `/home/
make: *** [debian/
dpkg-buildpackage: error: debian/rules build gave error exit status 2
Trying to build the package with dpkg-buildpackage -uc -us.
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-
src/
-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-
-Wl,
=== 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~),
+ dh-autoreconf,
+ libwaudio1-dev (>= 1.4~quantal1),
=== 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_
include /usr/share/
+include /usr/share/
include /usr/share/
#include /usr/share/
include /usr/share/
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:32
http://
Executed test runs:
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:34
http://
Executed test runs:
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
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.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:35
http://
Executed test runs:
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
Ricardo Salveti (rsalveti) wrote : | # |
Good, worked fine at both quantal and raring, with phone calls and sms.
Thanks!
Preview Diff
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); |
PASSED: Continuous integration, rev:31 jenkins. qa.ubuntu. com/job/ phablet- extras- ofono-ci/ 2/ jenkins. qa.ubuntu. com/job/ phablet- extras- ofono-raring- armhf-ci/ 2 jenkins. qa.ubuntu. com/job/ phablet- extras- ofono-raring- armhf-ci/ 2/artifact/ work/output/ *zip*/output. zip
http://
Executed test runs:
SUCCESS: http://
deb: http://
Click here to trigger a rebuild: s-jenkins: 8080/job/ phablet- extras- ofono-ci/ 2/rebuild
http://