Compare commits

...

577 Commits

Author SHA1 Message Date
Slava Monich
56e0d9dffa Merge branch 'file_watches' into 'master'
Prevent a crash in sim_fs_notify_file_watches

See merge request !118
2017-05-12 20:33:58 +00:00
Slava Monich
6867ba65cb [simfs] Prevent a crash in sim_fs_notify_file_watches. Fixes JB#38656
If no file watchers have ever been added, context->file_watches
is NULL and sim_fs_notify_file_watches() should take that into
account.
2017-05-12 18:51:53 +03:00
Slava Monich
1219ab6a3f Merge branch 'permlock' into 'master'
Detection of permanently locked SIM cards

See merge request !116
2017-04-28 16:13:23 +00:00
Slava Monich
85a956d9eb [ril] Improved detection of permanently locked SIM cards. JB#38257
If PUK is required, app state is PUK and pin1_state is ENABLED_BLOCKED.
If the card is permanently locked, app state is still PUK but pin1_state
becomes ENABLED_PERM_BLOCKED. That way we can tell whether the SIM card
is locked even if the number of remaining attempts is not available.
2017-04-28 16:06:22 +03:00
Slava Monich
c83d992a3b Merge branch 'retries' into 'master'
Query PUK retry count

See merge request !115
2017-04-28 11:54:09 +00:00
Slava Monich
b22027017c [ril] Query PUK retry count. JB#38257
PUK retry counts can be queried in a way similar to PIN retry counts
on those RILs that support it.
2017-04-27 21:36:46 +03:00
Slava Monich
1fa137b36d [sim] Allow plugins to use puk2pin() function 2017-04-27 21:27:27 +03:00
Slava Monich
cfd837b1db Merge branch 'puk' into 'master'
Always refresh SIM status from query_passwd_state

See merge request !114
2017-04-27 08:08:20 +00:00
Slava Monich
735ad21e89 [ril] Always refresh SIM status from query_passwd_state. Fixes JB#38257
After we have entered an invalid pin too many times, RIL signals
the SIM status change, we request the new status but ofono core
asks us for the new passwd state before our SIM status query has
completed. We need to wait for the query to complete before we can
report the new status to the core.

It also won't hurt if we request a fresh SIM status every time
when query_passwd_state callback is called, just in case if RIL
fails to notify us about the SIM status change.
2017-04-26 15:03:26 +03:00
Slava Monich
c9078404de [ril] Housekeeping 2017-04-14 19:51:42 +03:00
Slava Monich
e375195c92 Merge branch 'tech' into 'master'
Add "technologies" configuration option

See merge request !111
2017-04-10 21:10:22 +00:00
Slava Monich
ef5610f741 [ril] Added "technologies" configuration option. Fixes JB#38295
It supersedes enable4G option.
2017-04-05 21:18:00 +03:00
jpoutiai
aef9bbd3e0 Merge branch 'jb38053' into 'master'
[plugins] support bt call audio control. Fixes JB#38053

See merge request !110
2017-04-05 10:23:27 +00:00
Jarko Poutiainen
c6eb410f21 [plugins] support bt call audio control. Fixes JB#38053 2017-04-05 08:35:55 +03:00
Slava Monich
08b3ea3d0f Merge branch 'last_fail' into 'master'
Handle fancy variant of LAST_CALL_FAIL_CAUSE response

Some RILs get creative and invent their own formats.
They must be very proud of it.

See merge request !106
2017-03-15 21:46:11 +00:00
Slava Monich
2978862417 [ril] Handle fancy variant of LAST_CALL_FAIL_CAUSE response. Fixes JB#38079
Some RILs get creative and invent their own formats.
2017-03-15 17:19:37 +02:00
Slava Monich
19228c9e67 Merge branch 'lastcause' into 'master'
Allow to configure custom hangup reasons

One can define localHangupReasons and remoteHangupReasons in
ril_subscription.conf which will be treated as normal local or
remote hangup reasons.

See merge request !104
2017-02-24 13:11:46 +00:00
Slava Monich
9be791d531 [ofono] Allow to conifigure custom hangup reasons. Fixes JB#37879
One can define localHangupReasons and remoteHangupReasons in
ril_subscription.conf which will be treated as normal local or
remote hangup reasons. The value is a comma-separated list of
numbers, e.g.

localHangupReasons=20,39
2017-02-24 12:07:57 +02:00
Slava Monich
6b9eb7bf8f Merge branch 'voicecall' into 'master'
Don't use internal voicecall data structures

Added ofono_voicecall_find_call API instead

See merge request !105
2017-02-24 10:06:39 +00:00
Slava Monich
01f8989aee [ril] Don't use internal voicecall data structures
Use newly added ofono_voicecall_find_call API instead
2017-02-24 00:28:50 +02:00
Slava Monich
2f5efaf591 [ofono] Added ofono_voicecall_find_call API
For use by plugins
2017-02-24 00:28:18 +02:00
Slava Monich
ca1d06c37a Merge branch 'disable' into 'master'
Disable some unnecessary and harmful functionality

See merge request !103
2017-01-12 15:17:23 +00:00
Slava Monich
5f45928a84 [ofono] Disable PhoNet/ISI and QMI modem support. MER#1734
This makes ARM executable smaller by 170 KB
2017-01-12 00:47:04 +02:00
Slava Monich
19f74e6c85 [ofono] Don't allow to add or remove connection context over D-Bus. Fixes MER#1733
Quite a few things in SailfishOS assume that each modem has exactly
one internet and one mms context. However, ofono's D-Bus API allows
any application to arbitrarily add and remove connection contexts
which can screw things up quite badly. Since this functionality is
not used by SailfishOS, it should be disabled.
2017-01-12 00:27:17 +02:00
Slava Monich
41d5cfcab2 Merge branch 'modem-error' into 'master'
Count rild crashes

See merge request !102
2017-01-11 11:58:42 +00:00
Slava Monich
357c5db580 [ril] Count rild crashes. Contributes to JB#35780
org.nemomobile.ofono.ModemManager.ModemError signal is emitted
when rild crash is detected. Also, the new GetModemErrors method
allows to query how many times which instance of rild has crashed
since ofono was (re)started.
2017-01-11 13:24:23 +02:00
Slava Monich
8cea5b9f96 [ril] Allow to retry GET_BROADCAST_SMS_CONFIG. MER#1729
RIL_REQUEST_GSM_GET_BROADCAST_SMS_CONFIG sometimes fails at startup.
We may have to retry a few times (typically, once or twice on Jolla 1)
2017-01-05 18:40:50 +03:00
Slava Monich
5fb35d5fb4 Merge branch 'v1.19' into 'master'
Update ofono baseline to 1.19

It's the latest stable release.

See merge request !101
2017-01-05 12:39:13 +00:00
Slava Monich
e8d57bb928 [ofono] Update baseline to 1.19
Removed merge artifacts
2017-01-05 15:37:58 +03:00
Slava Monich
2bfde2418e [ril] Removed old workaround breaking hot-swap. Fixes MER#1730
The workaround is no longer needed. All SIM I/O requests have to
be completed even if the SIM card is removed while the request is
pending. Otherwise simfs request queue gets stuck.
2017-01-05 15:35:29 +03:00
Marcel Holtmann
c710ce76c1 Release 1.19 2017-01-05 11:20:08 +03:00
Alfonso Sánchez-Beato
78acd90464 gitignore: unit/test-rilmodem-gprs binary 2017-01-05 11:20:08 +03:00
Alfonso Sánchez-Beato
e51b3ca0c8 build: add rilmodem gprs unit tests
Conflicts:
	ofono/Makefile.am
2017-01-05 11:20:08 +03:00
Alfonso Sánchez-Beato
b3c8813bd4 unit: add rilmodem gprs tests
Add rilmodem gprs tests, which use the rilmodem test engine.
2017-01-05 11:20:08 +03:00
Alfonso Sánchez-Beato
e2a3acd9d0 unit: add rilmodem test engine
Add rilmodem test engine. This engine is an improvement on the rilmodem
test server that allows us to test generic interactions with the
rilmodem driver. Instead of just be able to check content of received/
sent bytes on the rild socket, we can now specify a set of steps for a
test that include interactions with the atom. The step types are

- TST_ACTION_SEND: The harness sends a parcel
- TST_ACTION_CALL: The harness calls a driver function
- TST_EVENT_RECEIVE: The driver sends a parcel
- TST_EVENT_CALL: The driver calls a harness (atom) function
2017-01-05 11:20:08 +03:00
Slava Monich
2054ca9570 include: Remove unused field from primary_context 2017-01-05 11:20:08 +03:00
Denis Kenzior
48dbb7912a AUTHORS: Mention Antoine's contributions 2017-01-05 11:20:08 +03:00
Denis Kenzior
d7e7ad671d gatchat: Fix style 2017-01-05 11:20:08 +03:00
Antoine Aubert
5b5a86dc80 gatmux: fix read channel remove on error
In case of invalid IO, read_watch is not reset. This fix crash on
destroy gatmux.
2017-01-05 11:20:08 +03:00
Slava Monich
c232524e99 main: Make -d option repeatable
Concatenating the patterns makes more sense than using the last
supplied value and leaking the previous allocated patterns.
2017-01-05 11:20:08 +03:00
Frédéric Dalleau
bfd09a5c14 udevng: Detect huawei E3372 modem and pcui
When the modes are modified with AT^SETPORT="FF;12,1,16", this modem
and pcui will appear using different ids. Update the interfaces
identifier accordingly.
2017-01-05 11:20:08 +03:00
Frédéric Dalleau
f8adcd2550 udevng: Detect huawei E3372 pcui
The huawei E3372 exposes two USB tty at /dev/ttyUSB0 and /dev/ttyUSB1
/dev/ttyUSB1 is properly detected as modem.
/dev/ttyUSB0 is the pcui.

lsusb shows 12d1:1506 Huawei Technologies Co., Ltd. Modem/Networkcard
2017-01-05 11:20:08 +03:00
Denis Kenzior
2a97567147 handsfree-audio: Fix crash
For HFP 1.5 devices the driver is always set to NULL.  So if the AG
establishes the SCO connection first, we might crash.
2017-01-05 11:20:07 +03:00
Santtu Lakkala
04d84b615e huaweimodem: Fix DHCP parsing on 32-bit platforms
strtol clamps returned value between INT_MIN and INT_MAX, causing
invalid value (255.255.255.127) being reported for any address
if last octet > 127 when sizeof(long) == 4.
2017-01-05 11:20:07 +03:00
Samrat Guha Niyogi
6e34792323 sim: remove locked_pin reset from sim_free_main_state 2017-01-05 11:20:07 +03:00
Samrat Guha Niyogi
d6a59f5dc4 rilmodem: fix cbd init in ril_query_facility_lock 2017-01-05 11:20:07 +03:00
Samrat Guha Niyogi
23e299055f rilmodem: fix num_params in query_facility_lock_cb 2017-01-05 11:20:07 +03:00
Denis Kenzior
a56ef3ba0f rilmodem: Co-locate the callback with invocation 2017-01-05 11:20:07 +03:00
Denis Kenzior
7294433906 rilmodem: Co-locate the callback with invocation 2017-01-05 11:20:07 +03:00
Samrat Guha Niyogi
d7263cd344 rilmodem: split ril_pin_change_state_cb
split ril_pin_change_state_cb based on functionality w.r.t.
facility lock, puk and pin. Rename ril_pin_change_state to
more appropriate name ril_set_facility_lock and rename
ril_pin_change_state_cb to ril_enter_sim_pin_cb.
2017-01-05 11:20:07 +03:00
Samrat Guha Niyogi
2f3b469fbb rilmodem: Remove unneeded pin sending logic 2017-01-05 11:20:07 +03:00
Denis Kenzior
4187e7ee8f sim: Fix style 2017-01-05 11:20:07 +03:00
Samrat Guha Niyogi
4d3f89bae0 sim: query facility during initialization in chain manner
query facility during initialization is modified from back
to back invocation to chain manner to keep it inline with
RIL design. All vendor RIL does not support back to back
handling since RIL telephony framework sends the request
synchronously.
2017-01-05 11:20:07 +03:00
Denis Kenzior
cbd1c5d524 sim: return false for SIM_PASSWORD_NONE 2017-01-05 11:20:07 +03:00
Ankit Navik
7976e44746 ril_sofia3gr: use vendor modem power down command 2017-01-05 11:20:07 +03:00
Denis Kenzior
3d6e220686 test: Add cancel-sms script 2017-01-05 11:20:07 +03:00
Denis Kenzior
919526d392 test: Fix permissions 2017-01-05 11:20:07 +03:00
Anirudh Gargi
b7082146e8 gril: Fix print macros to use latest print_buf 2017-01-05 11:20:07 +03:00
Denis Kenzior
094a296a14 AUTHORS: Mention Rajagopal's contributions 2017-01-05 11:20:07 +03:00
Rajagopal Aravindan
5c259e751b test: Added test to disable sofia 3gr tx throttling 2017-01-05 11:20:07 +03:00
Rajagopal Aravindan
69e5d5b356 test: Added test to enable sofia 3gr tx throttling 2017-01-05 11:20:07 +03:00
Rajagopal Aravindan
56e7d0e8ea ril_sofia3gr: Add transmit power throttling
Added 'sofia3gr.ThermalManagement' interface to sofia3gr plugin and
floated 'TransmitPowerThrottling' as an ofono property under that,
to support modem throttling.

'sofia3gr.ThermalManagement'
    1.Will be available ONLY if modem throttling is supported in RIL.
      This is determined by sending a RIL request during ofono start,
      to get current throttling state. If it succeeds, interface is
      published otherwise not.

'TransmitPowerThrottling'
    1.GetProperties will be allowed both when modem is ON & OFF.
    2.GetProperties will be serviced by looking it up from state
      information maintained inside ofono. No RIL call will be made.
    3.SetProperty will be allowed ONLY when modem is ON.
    4.SetProperty request will be forwarded to RIL ONLY if
      new state != current state. If RIL request succeeds, state
      information will be updated and also, a property change signal
      will be emitted.
2017-01-05 11:20:07 +03:00
Nishanth V
bb2ae6d1a1 rilmodem: fix WCDMA only in query rat mode 2017-01-05 11:20:07 +03:00
Caiwen Zhang
cf7692db49 plugins/ril: enable cbs 2017-01-05 11:20:07 +03:00
Caiwen Zhang
63f3311cd6 rilmodem: add cell broadcast message support 2017-01-05 11:20:07 +03:00
Samrat Guha Niyogi
c5aae77d41 ril_sofia3gr: Return -EINPROGRESS on disable() 2017-01-05 11:20:07 +03:00
Denis Kenzior
f8e21c8ad4 AUTHORS: Mention Suman's contributions 2017-01-05 11:20:07 +03:00
Suman Mallela
8e6dfe433b rilmodem: Fix PIN retries logic
The SIM PIN retries were not getting reset when the correct PIN/PUK
was entered.
2017-01-05 11:20:07 +03:00
Caiwen Zhang
ae23bb552b gril: avoid glib runtime warning
gril may be destroyed in the request callback (e.g in the callback of
set modem power off request). 'out_queue' and 'command_queue' is NULL.
there will be glib runtime warning if use them.
2017-01-05 11:20:06 +03:00
Caiwen Zhang
2becd051d4 plugins/ril: complete modem power off process 2017-01-05 11:20:06 +03:00
Slava Monich
8cfb1d5ca3 Merge branch 'cbs' into 'master'
Enable Cell Broadcast support

It was totally broken. 

See merge request !100
2017-01-05 08:15:45 +00:00
Slava Monich
50f35458f6 Merge branch 'rat' into 'master'
Preferred network mode, more corner cases

See merge request !99
2017-01-05 08:14:43 +00:00
Slava Monich
51843accf7 [ril] Enable Cell Broadcast support. Fixes MER#1729 2017-01-04 20:34:54 +03:00
Slava Monich
fb856dc7d6 [ril] Preferred network mode, more corner cases. Contributes to JB#36683
Prevents repeated rat mode setting failures when data SIM is not selected.
2017-01-04 16:05:11 +03:00
Slava Monich
1482748183 Merge branch 'silent-retry' into 'master'
Retry data call more than once

See merge request !98
2016-12-10 18:16:16 +00:00
Slava Monich
869ffda61e [ofono] Retry data call more than once. Contributes to JB#35406
Sometimes one retry is not enough, we need to allow more.
The first retry occurs immediately, then short delays are
applied. The delays and the number of retries are configurable.
The default is 4 retries and 200 ms delay before each retry
(except for the first one).

That should reduce the number of "Problem with connection" banners
thrown into the user's face.
2016-12-09 18:32:46 +02:00
Slava Monich
f875cbfda2 [ril] A few debug log changes 2016-12-08 18:20:43 +02:00
Slava Monich
2a60eaa6e3 Merge branch 'radiosetting' into 'master'
Fix the problem with radio settings saved to the wrong place

After the baseline was upgraded to 1.18, ofono core started saving
its radio settings to a file, and in order to save it to the right
place, the radio settings module needs to know the IMSI. So we have
to make sure that IMSI is available when we register the radio
settings atom.

See merge request !97
2016-11-25 13:41:02 +00:00
Slava Monich
29b6c41d48 [ril] Register ofono radio settings only when IMSI is available. Fixes MER#1708
Otherwise its radiosetting files gets written directly to /var/lib/ofono
instead of the SIM specific subdirectory.
2016-11-25 01:57:19 +02:00
Slava Monich
2f6491d005 [ril] Reset imsi in ril_sim_settings to NULL when SIM is removed. 2016-11-25 01:56:33 +02:00
Slava Monich
1a25047e9d Merge branch 'jb36957' into 'master'
Fix receiving UTF-16 encoded messages with split 4-byte char.

See merge request !96
2016-11-18 16:58:17 +00:00
Martin Jones
899e14bf17 [ofono] Fix receiving UTF-16 encoded messages with split 4-byte char. Fixes JB#36957
The spec supports UCS2, but in reality UTF-16 is used, which supports
4-byte characters, which could be split into different message
fragments. Accumulate the entire UTF-16 message before converting to
UTF8.
2016-11-18 14:06:57 +02:00
Slava Monich
2520664c63 Merge branch 'gprs-picks' into 'master'
Couple of upstream picks

One of those eliminates a possible root cause of mobile data
becoming disabled under certain (fairly rare) circumstances.

See merge request !95
2016-11-07 09:43:04 +00:00
Slava Monich
445bbbd66f gprs: Check GPRS_FLAG_ATTACHED_UPDATE
... in pri_deactivate_callback

This prevents attached state from getting stuck at 0 like this:

1. Context deactivation is initiated over D-Bus, ctx->pending is set
2. Attached becomes FALSE, context is still marked as active
3. Attached becomes TRUE, gprs_attached_update sets GPRS_FLAG_ATTACHED_UPDATE
4. Deactivation completes, attached is 0, driver_attached is 1

Futher network status updates don't call gprs_attached_update because
driver_attached is still 1, so attached is staying 0 until we lose the
data registration again which may not happen for quite a long time.
2016-11-04 12:14:48 +03:00
Caiwen Zhang
08fc4b0d03 gprs: fix crash removing a context being activated
If remove the context before context activation is completed, it may
cause a crash.
2016-11-04 12:14:18 +03:00
Slava Monich
c82e94ffb4 Merge branch 'cancel' into 'master'
Make sure that data request completion callback is always called on cancel

See merge request !94
2016-10-31 16:12:52 +00:00
Slava Monich
fd3712940b [ril] Make sure data request completion callback is called on cancel. Contributes to JB#33640
Completion callback wasn't invoked if the data request was cancelled
before it was actually submitted to RIL.
2016-10-28 15:46:06 +03:00
Slava Monich
8410c985c9 Merge branch 'nitz' into 'master'
Handle NITZ information coming before MCC/MNC

See merge request !93
2016-10-27 09:26:05 +00:00
Slava Monich
0878decdc0 Merge branch 'prefmode' into 'master'
Preferred network mode, corner cases

See merge request !92
2016-10-27 09:25:18 +00:00
Slava Monich
cb69984722 [ril] Preferred network mode, corner cases. Fixes JB#36683
Really make sure that we don't try to set preferred network mode to LTE
for more than one slot at a time.
2016-10-26 17:30:01 +03:00
Slava Monich
1fe8701f1a [nettime] Handle NITZ information coming before MCC/MNC. Fixes MER#1680
Due to the order in which events are delivered and network registration
information requiring one extra query, NITZ information may be delivered
to ofono before MCC/MNC are known.
2016-10-26 16:56:30 +03:00
Slava Monich
c5286fee70 Merge branch 'rat' into 'master'
Check network mode after ril_data is created

Not sure if it completely fixes the issue but it could cause
repeating SET_PREFERRED_NETWORK_TYPE failures.

See merge request !91
2016-10-23 21:04:29 +00:00
Slava Monich
3c5f6f84e1 Merge branch 'data_calls' into 'master'
Make data call format configurable

Different RILs use different data call structures which don't
necessarily match the format specified in the data list header.
The header may have version 9 but the list may contain 
RIL_Data_Call_Response_v6` structures, list version 10 may
contain RIL_Data_Call_Response_v11 and so on. By default ofono
assumes that the version from the list header matches the contents
but sometimes you have to explicitly tell ofono which one to use.

Possible values are 6, 9, 11 and auto.

See merge request !90
2016-10-23 21:03:52 +00:00
Slava Monich
8b87b55e8d [ril] Check network mode after ril_data is created. Contributes to JB#36683 2016-10-20 14:41:29 +03:00
Slava Monich
bce34cbff3 [ril] Housekeeping
Removed unnecessary forward declaration
2016-10-20 14:38:04 +03:00
Slava Monich
f8351cacf1 [ril] Made data call format configurable. Contributes to MER#1679
This commit adds dataCallFormat configuration option to
ril_subscriptuion.conf which allows to select which data
call format to use. There are quite a few rils where version
provided in the data call list header doesn't match the contents.
2016-10-19 12:30:13 +03:00
Slava Monich
6b9b8583dc Merge branch 'v10' into 'master'
Assume RIL_Data_Call_Response_v11 for RIL version 10

See merge request !89
2016-10-18 13:15:37 +00:00
Slava Monich
1df56480ba [ril] Assume RIL_Data_Call_Response_v11 for RIL version 10. Fixes MER#1679
All known rils that report version 10 are using RIL_Data_Call_Response_v11
(FairPhone 2, Nexus 4).
2016-10-18 15:11:00 +03:00
Slava Monich
adc8fce399 Merge branch 'v1.18' into 'master'
Update to upstream 1.18

This pulls the baseline from 1.17 to 1.18

See merge request !87
2016-10-17 12:08:43 +00:00
Slava Monich
d24ce4d9de Merge branch 'prefmode' into 'master'
Query preferred network mode at startup

Not knowing the initial state may result in endless attempts to
switch to LTE, failing because the other slot has LTE on.

See merge request !88
2016-10-17 12:07:35 +00:00
Slava Monich
f726af3309 [spec] Bumped version 2016-10-14 23:24:22 +03:00
Slava Monich
0ba1fd641b [ril] Query preferred network mode at startup
Not knowing the initial state may result in endless attempts to switch
to LTE, failing because the other slot has LTE on.
2016-10-14 20:46:39 +03:00
Slava Monich
41c0b0a2e6 Fixed merge artifact that was breaking OBS build 2016-10-14 20:18:47 +03:00
Slava Monich
322282258a netmon: Make sure we don't pass NULL message to g_dbus_send_message 2016-10-14 19:34:32 +03:00
Slava Monich
f6a7c39bba [ril] Added support for org.ofono.NetworkMonitor interface
Even though it's not as useful as org.nemomobile.ofono.CellInfo
it has the advantage of being the official one.
2016-10-14 19:33:07 +03:00
Denis Kenzior
3d3f68c798 allowed-apns: Fix crash
When a modem is being removed, all of the modem's atom watches have
already been cleaned up.  Trying to remove it again results in a crash.

Fix by registering a destroy callback which will be notified when the
atomwatch has been removed.
2016-10-14 19:00:35 +03:00
Nishanth V
e8d057c39e plugins: Fix allowed apn plugin exit 2016-10-14 19:00:28 +03:00
Slava Monich
357e5b69ca [update] Update to upstream 1.18. Fixes MER#1673 2016-10-14 17:09:35 +03:00
Slava Monich
e77efed603 [ofono] Fixed compilation after 1.18 merge 2016-10-14 17:09:00 +03:00
Marcel Holtmann
fa252b8d4a Release 1.18 2016-10-14 17:04:11 +03:00
Caiwen Zhang
321c092d6b plugins/ril: enable STK 2016-10-14 17:04:11 +03:00
Caiwen Zhang
ee912bafe3 rilmodem/stk: add STK support for rilmodem 2016-10-14 17:04:11 +03:00
Denis Kenzior
35eb528a70 gobi: Fix warning
plugins/gobi.c: In function ‘gobi_pre_sim’:
plugins/gobi.c:431:2: error: ‘sim_driver’ may be used uninitialized in
this function [-Werror=maybe-uninitialized]
  ofono_sim_create(modem, 0, sim_driver, data->device);
    ^
2016-10-14 17:04:11 +03:00
Denis Kenzior
22a6c4438b udevng: Fixup various minor style issues 2016-10-14 17:04:11 +03:00
Martin Chaplet
652bdc15ad udevng: Add support for Sierra MC73xx QMI modems
Udevng layer is changed in order to support Sierra QMI modems like
MC73cxx. Identically to Huawei modems, these modems are parsed by
setup_sierra. If QMI interface is detected, the Gobi modem driver is
selected.

Unfortunately, MC73xx chips seem to have a broken QMI UIM interface.
The qmimodem-legacy is so forced in setup function.
2016-10-14 17:04:11 +03:00
Martin Chaplet
a71e277850 udevng: Improve modem properties detection
* Add driver's subsystem information (net, usb, tty, ...)
 * Improve interface number extraction by scanning also device and
 parent attributes
2016-10-14 17:04:11 +03:00
Martin Chaplet
fbee06e8be gobi: Enable SIM driver forcing
Some gobi devices do not actually support UIM interface.  So if the
"ForceSimLegacy" property is set, force the qmimodem-legacy SIM driver.
2016-10-14 17:04:11 +03:00
Denis Kenzior
26029566e2 AUTHORS: Mention Martin's contributions 2016-10-14 17:04:11 +03:00
Martin Chaplet
0074ff2660 udevng: Add usbmisc scan for QMI devices
cdc-wdm0 are now usbmisc devices
2016-10-14 17:04:10 +03:00
Denis Kenzior
82fa5e977a radio-settings: Fix style 2016-10-14 17:04:10 +03:00
Antara Borwankar
823f13a1fa radio-settings: Init pending_band_{gsm|umts}
The set_band method takes two parameters for band settings, one for gsm
and one for umts.  When loaded from storage, and they are not set to
defaults, the band variables can get out of sync when setting the
GsmBand and UmtsBand properties.
2016-10-14 17:04:10 +03:00
Denis Kenzior
7b34498b1e rilmodem: Remove no longer relevant TODO 2016-10-14 17:04:10 +03:00
Denis Kenzior
37d4e1983b include: Remove unused query_locked method
Conflicts:
	ofono/include/sim.h
2016-10-14 17:04:09 +03:00
Denis Kenzior
e6f26f3bcf rilmodem: Fix style 2016-10-14 17:00:59 +03:00
Samrat Guha Niyogi
23e1d2c516 rilmodem: Implement sim atom query_facility_lock 2016-10-14 17:00:59 +03:00
Samrat Guha Niyogi
1f246cc28c include: Add query_facility_lock method
Conflicts:
	ofono/include/sim.h
2016-10-14 17:00:56 +03:00
Caiwen Zhang
ec20f44124 doc: Fix enumeration value to be gprs and not gsm 2016-10-14 16:57:35 +03:00
Denis Kenzior
8b6139aea8 radio-settings: Fix 80-character limit 2016-10-14 16:57:35 +03:00
Denis Kenzior
b79c3c3a95 AUTHORS: Mention Antara's contributions 2016-10-14 16:57:35 +03:00
Antara Borwankar
c885744273 radio-settings: Store GSM and UMTS band settings 2016-10-14 16:57:35 +03:00
John Ernberg
cdd0e4eaff stk: clean up undefined function pointer casts 2016-10-14 16:57:35 +03:00
John Ernberg
402783f877 configure: Bump glib dependecy to 2.32
Needed to support g_queue_free_full
2016-10-14 16:57:35 +03:00
Denis Kenzior
4755990237 ril_sofia3gr: Add quirk to radio_settings atom 2016-10-14 16:57:35 +03:00
Denis Kenzior
7a91b4e069 ril: vendorize SoFiA set_band implementation
Since the set_band implementation uses an OEM hook, it should be wrapped
behind a vendor quirk.
2016-10-14 16:57:35 +03:00
Antara Borwankar
35d4ca1e53 rilmodem: Driver code to set band mode and value
set_band driver to set GSM band and UMTS band
2016-10-14 16:57:35 +03:00
John Ernberg
ea334e9daa simfs: Remove explicit casts 2016-10-14 16:57:35 +03:00
John Ernberg
16964bb8f2 sim: Remove explicit casts 2016-10-14 16:57:35 +03:00
John Ernberg
0b93ab2d76 phonebook: Remove explicit casts
Casting between incompatible function pointer types is undefined.  So
remove such casts when possible.
2016-10-14 16:57:35 +03:00
John Ernberg
0bed313ecb unit: Use g_slist_free_full 2016-10-14 16:57:35 +03:00
John Ernberg
cfd1d2c30a voicecall: Use g_slist_free_full 2016-10-14 16:57:35 +03:00
John Ernberg
cb7c408beb ussd: Use g_slist_free_full 2016-10-14 16:57:35 +03:00
John Ernberg
202d8cf162 stkutil: Use g_slist_free_full 2016-10-14 16:57:35 +03:00
John Ernberg
a15a558af6 smsutil: Use g_slist_free_full 2016-10-14 16:57:35 +03:00
John Ernberg
fd8429465f sms: Use g_slist_free_full 2016-10-14 16:57:35 +03:00
John Ernberg
8db1008790 simutil: Use g_slist_free_full 2016-10-14 16:57:35 +03:00
John Ernberg
3e3b4971da network: Use g_slist_free_full 2016-10-14 16:57:34 +03:00
John Ernberg
7c8245e432 modem: Use g_slist_free_full 2016-10-14 16:57:34 +03:00
John Ernberg
5a06b04e05 handsfree: Use g_slist_free_full 2016-10-14 16:57:34 +03:00
John Ernberg
1c12df9e99 cdma-smsutil: Use g_slist_free_full 2016-10-14 16:57:34 +03:00
John Ernberg
fa3d80cd39 cbs: use g_slist_free_full 2016-10-14 16:57:34 +03:00
John Ernberg
18507364ea smart-messaging: Use g_slist_free_full 2016-10-14 16:57:34 +03:00
John Ernberg
c409ec2940 bluez4: Remove unneeded casts 2016-10-14 16:57:34 +03:00
John Ernberg
bba910a1d6 gatchat: Use g_slist_free_full 2016-10-14 16:57:34 +03:00
John Ernberg
a7867d24e9 stemodem: Use g_slist_free_full 2016-10-14 16:57:34 +03:00
John Ernberg
8909d4928b rilmodem: Use g_slist_free_full 2016-10-14 16:57:34 +03:00
John Ernberg
d9e39a69a5 ifxmodem: Use g_slist_free_full 2016-10-14 16:57:34 +03:00
John Ernberg
0477eeb75f hfpmodem: Use g_slist_free_full 2016-10-14 16:57:34 +03:00
John Ernberg
2ff3613e9b atmodem: use g_slist_free_full 2016-10-14 16:57:34 +03:00
Caiwen Zhang
e5d040f7f9 plugins/ril: Move GPRS atom to 'post_online' state
At gprs atom 'probe' state, max cid query may fail due to rild
status isn't RADIO_STATUS_ON. It causes gprs atom is removed, gprs
feature is inavailable. Move gprs atom creating to 'post_online'
state to make sure rild status is RADIO_STATUS_ON when query max
cid.
2016-10-14 16:57:34 +03:00
John Ernberg
604a3dd22e voicecall: limit g_drivers variable exposure 2016-10-14 16:57:34 +03:00
John Ernberg
5eb923ad28 voicecall: fix CreateMultiparty method introspection
This caused problems with stricter dbus wrappers such as dbus-c++.
2016-10-14 16:57:34 +03:00
Denis Kenzior
94fa037b93 rilmodem: Remove some unneeded whitespace 2016-10-14 16:57:34 +03:00
Denis Kenzior
41135af282 rilmodem: Rename addrs to addr when not plural
addrs variable seems to be used whenever multiple addresses are being
references.  Either as a strv or a compound string separated by a
separator.  In these cases addrs was used for a single address, which
was confusing.
2016-10-14 16:57:34 +03:00
Denis Kenzior
47359a3083 rilmodem: Refactor away some explicit casts 2016-10-14 16:57:34 +03:00
Nishanth V
9c6c354d5a rilmodem: Add IPv6 support in gprs-context 2016-10-14 16:57:34 +03:00
Nishanth V
8ca5fc24ed rilmodem: Add address to protocol type util func 2016-10-14 16:57:34 +03:00
Nishanth V
aecb63423f ril: don't set an ipv4 netmask if not provided
For historical reasons a netmask was always being set, even if one was
not provided.
2016-10-14 16:57:34 +03:00
Nishanth V
f72f84ec0f test: Add list allowed access points script 2016-10-14 16:57:34 +03:00
Nishanth V
e593476d81 plugins: Add allowed apn list
Conflicts:
	ofono/Makefile.am
2016-10-14 16:57:31 +03:00
Nishanth V
1a4f1b0f9f simutil: Add EFACL in elementary file db 2016-10-14 16:52:07 +03:00
Nishanth V
14904ddaeb doc: Add allowed-apns api doc 2016-10-14 16:52:07 +03:00
Caiwen Zhang
5fc9827e5d sim: fix crash when going into state LOCKED_OUT
After input PIN wrong 3 times, sim main state (include spn_watches)
is freed. but the watch id still be kept by other atoms (network and
gprs), when remove the atom, it will try to remove the watch from
spn_watches, ofono daemon will crash.

Conflicts:
	ofono/src/sim.c
2016-10-14 16:52:05 +03:00
Nishanth V
3539b5c9f9 gprs-context: fix set ipv4 netmask for rilmodem 2016-10-14 16:45:55 +03:00
Denis Kenzior
916c1ac904 log: Fix style 2016-10-14 16:45:55 +03:00
Harald Welte
9f659d47b0 log: Don't crash when addr2line output contains no newline 2016-10-14 16:45:55 +03:00
Kuba Pawlak
7d3ec8e9dc unit: fix GCC 6.0 compilation issues
-Werror=unused-const-variable
2016-10-14 16:45:55 +03:00
Kuba Pawlak
d5977f9014 plugins/nokia-gpio: fix glibc 2.23.9+ issues
readdir_r’ is deprecated [-Werror=deprecated-declarations]
2016-10-14 16:45:55 +03:00
Kuba Pawlak
513b922814 drivers/isimodem: fix GCC 6.0 errors
-Werror=misleading-indentation
2016-10-14 16:45:55 +03:00
Denis Kenzior
7f0cc63b3d radio-settings: Fix potential leak
rs->imsi is only freed when rs->settings is true.  So tweak the logic
inside radio_load_settings to only strdup the imsi when settings
creation has succeeded.
2016-10-14 16:45:55 +03:00
Denis Kenzior
9fb47a6382 radio-settings: Fix minor style issues 2016-10-14 16:45:55 +03:00
Anirudh Gargi
ae35e7bff3 radio-settings: Add RAT mode to ofono storage 2016-10-14 16:45:55 +03:00
Alfonso Sanchez-Beato
c7dc8cf262 gprs: Deactivate old contexts on attach
In some cases it is possible that a context is opened after a detach
event has been received, and right before an attach, depending on the
modem. We make sure that those contexts are removed to keep
consistency.
2016-10-14 16:45:55 +03:00
Kuba Pawlak
213df4e7c4 hfp: Handle +CCWA at HFP connection setup
Some phones with an active and waiting call at the time of HFP SLC
establishment, may send call waiting notification before all calls
are synchronized. This will lead to call Id mismatch because call
object is created with assumed Id 1 and not Id assigned by the phone.

In example below waiting call is created with Id 1 but in AT+CLCC
this phone returns active call as call with Id 1, and waiting as 2.

< \r\n+CCWA: "+1234567890",145\r\n
< \r\n+CIEV: 2,1\r\n
drivers/hfpmodem/voicecall.c:ccwa_notify() ccwa_notify: +1234567890 145 0
src/voicecall.c:ofono_voicecall_notify() Got a voicecall event, status: 5, id: 1, number: +1234567890 called_number: , called_name
src/voicecall.c:ofono_voicecall_notify() Did not find a call with id: 1
> AT+CIND?\r
< \r\n+CIND: 1,1,1,4,0,2,0\r\n\r\nOK\r\n
src/network.c:ofono_netreg_status_notify() /hfp/org/bluez/hci0/dev_60_AF_6D_F7_8E_37 status 1 tech -1
> AT+VGS=7\r
< \r\nOK\r\n
> AT+VGM=7\r
< \r\nOK\r\n
> AT+CLCC\r
< \r\n+CLCC: 1,1,0,0,0,"+9876543210",145\r\n
< \r\n+CLCC: 2,1,5,0,0,"+1234567890",145\r\n\r\nOK\r\n
src/voicecall.c:ofono_voicecall_notify() Got a voicecall event, status: 0, id: 1, number: +9876543210 called_number: , called_name
src/voicecall.c:ofono_voicecall_notify() Found call with id: 1
src/voicecall.c:ofono_voicecall_notify() Got a voicecall event, status: 5, id: 2, number: +1234567890 called_number: , called_name
src/voicecall.c:ofono_voicecall_notify() Did not find a call with id: 2
src/voicecall.c:ofono_voicecall_mpty_hint() ids: 0
2016-10-14 16:45:55 +03:00
Denis Kenzior
e78daccea9 AUTHORS: Mention Nishanth's contributions 2016-10-14 16:45:55 +03:00
Samrat Guha Niyogi
4f10d24638 test: Support SoftwareVersionNumber in test-modem 2016-10-14 16:45:55 +03:00
Samrat Guha Niyogi
cfa7ec6dd5 rilmodem: Add support of IMEISV 2016-10-14 16:45:55 +03:00
Denis Kenzior
d18ba4e9a4 modem: Fix style 2016-10-14 16:45:55 +03:00
Samrat Guha Niyogi
8846c58b53 devinfo: Add support of IMEISV 2016-10-14 16:45:55 +03:00
Samrat Guha Niyogi
4f088c85c7 include: Add support for IMEISV in devinfo 2016-10-14 16:45:55 +03:00
Samrat Guha Niyogi
6587a2456a doc: Add SoftwareVersionNumber to Modem interface 2016-10-14 16:45:55 +03:00
Nishanth V
edab9dbf2b test: Add get serving cell information script 2016-10-14 16:45:55 +03:00
Nishanth V
b6cc94bf84 sofia3gr: Add netmon support 2016-10-14 16:45:55 +03:00
Denis Kenzior
4039bed591 rilmodem: Fix minor style issues 2016-10-14 16:45:55 +03:00
Nishanth V
1f56e8350b rilmodem: Add netmon support 2016-10-14 16:45:55 +03:00
Denis Kenzior
34b0d68cdd netmon: Fix minor style issues 2016-10-14 16:45:55 +03:00
Denis Kenzior
ec60fa4eac netmon: Add ofono/netmon.h into ofono.h
Conflicts:
	ofono/src/ofono.h
2016-10-14 16:45:50 +03:00
Nishanth V
a066917c4d netmon: Add serving cell info support
Conflicts:
	ofono/Makefile.am
2016-10-14 16:43:40 +03:00
Nishanth V
da23ddbc15 gril: Added RIL_REQUEST_GET_CELL_INFO_LIST 2016-10-14 16:36:35 +03:00
Denis Kenzior
207f67ab62 include: Fix whitespace issues 2016-10-14 16:36:35 +03:00
Nishanth V
3e3720f416 include: Add netmon changes 2016-10-14 16:36:35 +03:00
Alfonso Sanchez-Beato
985dbf9795 gril: Really use given uid/gid to open ril socket 2016-10-14 16:36:35 +03:00
Denis Kenzior
8b56a11936 AUTHORS: Mention Anirudh's contributions 2016-10-14 16:36:35 +03:00
Denis Kenzior
40aa517183 build: Add recently added test scripts 2016-10-14 16:36:35 +03:00
Anirudh Gargi
6fdf38b74b test: Add sms bearer set and SMSC set scripts 2016-10-14 16:36:35 +03:00
Denis Kenzior
8dc0b46bb3 sofia3gr: Fix style issue 2016-10-14 16:36:35 +03:00
Anirudh Gargi
b772df434b sofia3gr: Enable vendor type in SMS driver 2016-10-14 16:36:34 +03:00
Anirudh Gargi
3726a1a48a rilmodem: Add sms bearer set and bearer query func 2016-10-14 16:36:34 +03:00
Dragos Tatulea
5e309e5d45 gprs: assume attached state when registered on LTE
LTE doesn't really use the concept of an attached state. However,
the oFono API needs it. ConnMan needs it as well.
2016-10-14 16:36:34 +03:00
Denis Kenzior
ea65572935 ubloxmodem: Remove unneeded #include 2016-10-14 16:36:34 +03:00
Dragos Tatulea
83f8e1cbe6 ubloxmodem: support automatic ctx activation
... by imlementing read_settings.
2016-10-14 16:36:34 +03:00
Dragos Tatulea
c97d28cd23 atmodem: gprs: handle automatic context activation
When the event comes, trigger CGCONT? to read the APN for the
activated cid and then call ogono_gprs_cid_activated to handle
the event.
2016-10-14 16:36:34 +03:00
Dragos Tatulea
9279a008ed gprs: implement ofono_gprs_cid_activated
It works by looking for a context with the same APN and tries to use
that. Otherwise it will create it's own.

Then it assigns a gprs context driver and calls it's read_settings if
it exists.
2016-10-14 16:36:34 +03:00
Dragos Tatulea
e9c1603c8b gprs-context.h: add op for reading context config
This will be implemented by a gprs-context driver to support
automatic context activation. The gprs atom will call the driver
to read the ip configuration without activating the context.
2016-10-14 16:36:34 +03:00
Dragos Tatulea
5a8eb818ee idmap: add api for finding a certain id in map 2016-10-14 16:36:34 +03:00
Dragos Tatulea
7ab6bffd07 gprs: pri_set_apn: make reply msg optional
Automatic context activation will set the apn by itself. No
dbus message to reply to.
2016-10-14 16:36:34 +03:00
Dragos Tatulea
86f8a5c1f6 gprs: automatic context configuration notifier
Useful for LTE automatic bearer activation.

This is called from the gprs driver to let the gprs atom know that
a new context has been activated.

Conflicts:
	ofono/include/gprs.h
2016-10-14 16:36:31 +03:00
Dragos Tatulea
f1a87e5f6c gprs: custom cid for assign_context
It's optional though. If 0 a cid is picked up automatically from the
allowed range.
2016-10-14 16:33:19 +03:00
Dragos Tatulea
4dbdf95b12 ubloxmodem: support authentication
If username and password specified, issue an UAUTHREQ
command with the configured authentication method, selected cid
and credentials.
2016-10-14 16:33:19 +03:00
Dragos Tatulea
dab3e86325 ubloxmodem: add Toby L2 gprs context driver
For now the driver works only with bridged mode for 2G/3G.

Once it activates the context it reads the ip, netmask,
gw, dns and sets them in the context settings.
2016-10-14 16:33:19 +03:00
Dragos Tatulea
b62f6c1041 ublox: support more internet contexts
Create multiple gprs-context instances and let the gprs core use
them as it sees fit.

Only for Toby L2.
2016-10-14 16:33:19 +03:00
Dragos Tatulea
f41a998695 ublox: enable ubloxmodem driver when possible
Where possible means Toby L2 in high speed mode.

The bridge mode is set before enabling the modem because the
driver requires this.
2016-10-14 16:33:19 +03:00
Dragos Tatulea
42fa3983ef ublox: give names to model ids
To make it easier to understand the code.
2016-10-14 16:33:19 +03:00
Denis Kenzior
f8a47ae530 ublox: devinfo atom driver has no vendor behavior 2016-10-14 16:33:19 +03:00
Dragos Tatulea
cf202b1568 atmodem: add support for U-Blox TOBY L2 modems
Besides exceptions below, act like normal U-Blox devices.

gprs-context: don't set auth for TOBY L2. U-Blox Toby L2
doesn't support PAP/CHAP APN auth method.

atmodem: TOBY L2 supports only CMER mode 1. Also chaged original
mode variable to ind, which is a more appropriate name.
mode is what is being set first.
2016-10-14 16:33:19 +03:00
Dragos Tatulea
14ebdfe7b9 ublox: use vendor from structure instead of fixed
That's because we need to differentiate between multiple ublox
devices.
2016-10-14 16:33:19 +03:00
Dragos Tatulea
8732a885a3 ublox: allow enabling of TOBY L2 modems
For this we need to:
* Set the vendor family based on model id.
* Not use modem interface for the TOBY L2 family.
2016-10-14 16:33:19 +03:00
Dongsu Park
3f5fa672a5 udevng: Support U-blox TOBY series of devices
Each modem expresses their interfaces with its own interface string,
which is composed of 3 different USB attributes:
"bInterfaceClass/bInterfaceSubClass/bInterfaceProtocol".
While the old models like LISA support only "2/2/1" for modem
interfaces, TOBY-L2 also supports an unique string for NetworkInterface
for each profile.

* low-medium throughput profile : 2/6/0
* fairly backward-compatible profile : 10/0/0
* high throughput profile : 224/1/3

Besides the condition for checking NULL for mdm/aux/net should be relaxed
a little bit.
2016-10-14 16:33:19 +03:00
Denis Kenzior
e358485f37 ril_sofia3gr: Fix warning 2016-10-14 16:33:19 +03:00
Denis Kenzior
e964307ced AUTHORS: Mention Samrat's contributions 2016-10-14 16:33:19 +03:00
Denis Kenzior
d1d69cf667 AUTHORS: Mention Dragos' contributions 2016-10-14 16:33:19 +03:00
Denis Kenzior
bf6210bdbb AUTHORS: Mention Dongsu's contributions 2016-10-14 16:33:19 +03:00
Samrat Guha Niyogi
bcdd5a95c1 ril_sofia3gr: add ussd atom to post_online 2016-10-14 16:33:19 +03:00
Denis Kenzior
fcea7919f9 netmon: Fix enumeration 2016-10-14 16:33:19 +03:00
Denis Kenzior
6fd1c1ef33 include: Add netmon.h
Conflicts:
	ofono/Makefile.am
2016-10-14 16:33:17 +03:00
Denis Kenzior
4d960d898d doc: Add NetworkMonitor API 2016-10-14 16:30:46 +03:00
Denis Kenzior
a9f47b77ce udevng: Move from setup_icera to setup_ublox
As intended by 126b04
2016-10-14 16:30:46 +03:00
Dragos Tatulea
fb81c3571b atmodem: ublox: EPS now supported by newer ublox
Based on UBX-13002752 R33
2016-10-14 16:30:46 +03:00
Dragos Tatulea
7809498588 atmodem: add vendor enumeration for ublox toby
Required to differentiate between the old LISA family
of supported devices and future TOBY L2 devices.
2016-10-14 16:30:46 +03:00
Dragos Tatulea
4d05522b2a plugins/udevng: ublox: set model string
Necessary for supporting the ublox TOBY L2 modem.
2016-10-14 16:30:46 +03:00
Dongsu Park
b6b0306b39 plugins/udevng: support the U-Blox TOBY-L2 series
The newest generation of U-Blox TOBY-L2 series can be detected with
VID 0x1546 (the same as before), and one of the following PIDs:

* "0x1146" : high throughput profile
* "0x1141" : fairly back-compatible profile
* "0x1143" : low/medium throughput profile

This patch adds detection for high throughput mode.
2016-10-14 16:30:46 +03:00
Denis Kenzior
5c938a5b64 test: Add register-operator 2016-10-14 16:30:46 +03:00
Denis Kenzior
b04d30ff3e test: Add register-auto
Conflicts:
	ofono/Makefile.am
2016-10-14 16:30:44 +03:00
Denis Kenzior
4bdc8ac62c gitignore: Add rilmodem-cb and rilmodem-sms 2016-10-14 16:24:07 +03:00
Kuba Pawlak
fa20be318d hfpmodem: Handle repeated held call indicator
An issue with iPhone 5C iOS 9.2 triggers desynchronization in call
states. When an active call is put on hold and another call arrives,
it is in WAITING state. It should be possible to answer it by issuing
AT+CHLD=2 but the phone changes its state to INCOMING so ATA should be
used. This change is advertised by sending callheld:2 event, but it is
not handled. This event can be used to trigger CLCC poll to synchronize
call states.

+CIEV: 3,1   <- first call arrives
AT+CLCC
+CLCC: 1,1,4,0,0,"01234567890",129
OK
RING
+CLIP: "01234567890",129
ATA
OK
+CIEV: 2,1
+CIEV: 3,0.
AT+CHLD=2.$  <- first call is put on hold
OK
+CIEV: 7,2   <- notification confirming that call #1 is on hold
+CCWA: "09876543210",129,1     <- second call arrives
+CIEV: 7,2
+CIEV: 3,1
AT+CLCC
+CLCC: 1,1,1,0,0,"01234567890",129
+CLCC: 2,1,5,0,0,"09876543210",129 <- new call is still in WAITING state
OK
+CIEV: 7,2 <- phone iternally promotes WAITING call to INCOMING
AT+CHLD=2  <- there is no WAITING call anymore, ATA should be used
+CME ERROR:3
2016-10-14 16:24:07 +03:00
Denis Kenzior
3598f4edab gatchat: Add support for shutting down the server
By sending SIGUSR1 we can initiate a soft server-shutdown.
2016-10-14 16:24:07 +03:00
Denis Kenzior
0524862743 ril_sofia3gr: Add radio_settings atom 2016-10-14 16:23:57 +03:00
Denis Kenzior
d2cfc16201 AUTHORS: Mention John's contributions 2016-10-14 16:23:48 +03:00
Tony Espy
fd874f3a4c build: add support for upower plugin 2016-10-14 16:23:36 +03:00
Tony Espy
0a039db7da plugins: add upower battery monitor for bluetooth 2016-10-14 16:23:36 +03:00
Denis Kenzior
0e6ce9a38e rilmodem: Initialize ofono_error correctly 2016-10-14 16:23:36 +03:00
Tony Espy
3cad68861c build: untangle ATMODEM and BLUETOOTH conditionals 2016-10-14 16:23:36 +03:00
Denis Kenzior
70d9366499 HACKING: Update instructions with email address 2016-10-14 16:23:36 +03:00
Denis Kenzior
6c17d2b79c ril: Use g_ril_new_with_ucred 2016-10-14 16:23:36 +03:00
Denis Kenzior
811b478903 gril: Add g_ril_new_with_ucred 2016-10-14 16:23:36 +03:00
Denis Kenzior
6fcc2a1f68 gril: Remove unneeded defines 2016-10-14 16:23:36 +03:00
Denis Kenzior
792c4674c2 plugins: Add sofia3GR ril driver 2016-10-14 16:23:36 +03:00
Denis Kenzior
e9df792102 build: Fix building without atmodem support 2016-10-14 16:23:36 +03:00
Denis Kenzior
eb92f42c7d stktest: Remove usage of decode_at_error
Otherwise the build fails when building without atmodem support
2016-10-14 16:23:36 +03:00
Tony Espy
bcafdc8d70 build: add support for new test-rilmodem-cb
Conflicts:
	ofono/Makefile.am
2016-10-14 16:23:23 +03:00
Tony Espy
5aa8f72aaa rilmodem: fix call_barring_query_cb
The return value from a RIL_REQUEST_GET_FACILITY_LOCK
is the TS 27.007 service class bit vector of services
for the specified barring facility.  The value canf be
zero, which indicates "disabled for all".
2016-10-14 16:21:52 +03:00
Tony Espy
704a3ae354 unit: add new test-rilmodem-cb 2016-10-14 16:21:52 +03:00
Denis Kenzior
a4f91f2d80 ril: Get rid of ril_gprs_context_data 2016-10-14 16:21:52 +03:00
Denis Kenzior
e655837ccb rilmodem: Get rid of ril_gprs_context_data 2016-10-14 16:21:52 +03:00
Denis Kenzior
800ad72129 ril: Don't use ril_sim_data 2016-10-14 16:21:41 +03:00
Denis Kenzior
e6cae75c40 rilmodem: Get rid of ril_sim_data 2016-10-14 16:21:41 +03:00
Denis Kenzior
d655aec432 sim: Silence warning on 32-bit 2016-10-14 16:21:41 +03:00
Denis Kenzior
cd2d6a28aa gril: Use unsigned int instead of gsize
Sizeof gsize changes depending on 32/64 bit system.  However, in reality
it is always 4 bytes.
2016-10-14 16:21:41 +03:00
Denis Kenzior
8507197fa6 sim: Tweak debug statement 2016-10-14 16:21:41 +03:00
Denis Kenzior
ee6b3385db sim: Add additional DBG statements 2016-10-14 16:21:41 +03:00
Tony Espy
24b6aeab5c rilmodem: fix sim_status_cb debug logging
During the re-factoring of rilmodem's sim atom
messaging code, the sim_status_cb function's
RIL tracing code was converted to DBG calls.
This change adds the same prefix to DBG/trace
calls when a single message's parameters span
more than one DBG call. This makes it easier
to filter out trace messages when looking at a
log file.
2016-10-14 16:21:41 +03:00
Tony Espy
5436c2beea unit: update test-rilmodem-sms set_sca test case
Update test-rilmodem-sms set_sca test case to take
into account additional quotes used for sending
a SET_SMSC_ADDRESS request.
2016-10-14 16:21:41 +03:00
Tony Espy
87d947fe48 rilmodem: restore SET_SMSC_ADDRESS number format
Restore quoting of SMSC number string, as it's
required by at least one rild implementation (mako).
2016-10-14 16:21:41 +03:00
Denis Kenzior
af45298bc7 rilmodem: Remove unneeded include 2016-10-14 16:21:41 +03:00
Denis Kenzior
cdb32c9139 gril: Remove grilunsol.[ch] 2016-10-14 16:21:41 +03:00
Denis Kenzior
85a9daa5f4 rilmodem: Don't include grilunsol.h 2016-10-14 16:21:41 +03:00
Denis Kenzior
17a4fd7b78 ril: Don't include grilunsol.h 2016-10-14 16:21:41 +03:00
Denis Kenzior
d42b983dee gril: Remove g_ril_unsol_parse_data_call_list 2016-10-14 16:21:41 +03:00
Denis Kenzior
33b14a3326 rilmodem: Implement ril_setup_data_call_cb inline 2016-10-14 16:21:41 +03:00
Denis Kenzior
09ac10c3ac rilmodem: Implement get_active_data_calls_cb inline 2016-10-14 16:21:41 +03:00
Denis Kenzior
f47fe40799 gril: Remove unused str_array functions 2016-10-14 16:21:41 +03:00
Denis Kenzior
ef0532222f gril: Remove unused ril_radio_tech_to_string 2016-10-14 16:21:41 +03:00
Denis Kenzior
edf7608da8 gril: Remove unused ril_pinstate_to_string 2016-10-14 16:21:41 +03:00
Denis Kenzior
1bd019aec7 gril: Remove unused ril_cardstate_to_string 2016-10-14 16:21:41 +03:00
Denis Kenzior
57ea46e0d7 gril: Remove unused ril_authtype_to_string 2016-10-14 16:21:41 +03:00
Denis Kenzior
90c4dfe1e5 gril: Remove unused ril_apptype_to_string 2016-10-14 16:21:41 +03:00
Denis Kenzior
4112433e86 gril: Remove unused ril_appstate_to_string 2016-10-14 16:21:41 +03:00
Denis Kenzior
97830c757f gril: Remove unused ril_ofono_protocol_to_ril_string 2016-10-14 16:21:41 +03:00
Denis Kenzior
2dcfd64ff4 rilmodem: Remove drivers/rilmodem/gprs.h 2016-10-14 16:21:41 +03:00
Denis Kenzior
cba91bff8b rilmodem: Don't expose private structures 2016-10-14 16:21:41 +03:00
Denis Kenzior
7bf1f707ff rilmodem: Get rid of unnecessary exports 2016-10-14 16:21:24 +03:00
Denis Kenzior
aa6eed4eeb rilmodem: Get rid of ril_gprs_driver_data 2016-10-14 16:21:24 +03:00
Denis Kenzior
18e6d86edd ril: Get rid of gprs_driver_data 2016-10-14 16:21:24 +03:00
Denis Kenzior
e40d9e80c7 rilmodem: Get rid of useless member variable 2016-10-14 16:21:24 +03:00
Denis Kenzior
4176a82a0b rilmodem: Remove data reg state query retry logic
This is no longer needed as the query for max_cid is done in a different
logic flow.
2016-10-14 16:21:23 +03:00
Denis Kenzior
447d0af56c gril: Remove grilreply.[ch] 2016-10-14 16:21:23 +03:00
Denis Kenzior
284c7dfc48 rilmodem: Don't include grilreply.h 2016-10-14 16:21:23 +03:00
Denis Kenzior
a1a6ff7976 ril: Don't include grilreply.h 2016-10-14 16:21:23 +03:00
Denis Kenzior
e2e4b7c868 rilmodem: use g_new0 instead of g_try_new0 2016-10-14 16:21:23 +03:00
Denis Kenzior
5103af4321 gril: Remove g_ril_reply_parse_get_calls 2016-10-14 16:21:23 +03:00
Denis Kenzior
b3a10881e7 rilmodem: Implement clcc_poll_cb inline 2016-10-14 16:21:23 +03:00
Denis Kenzior
cbc9ce47e0 gril: Remove g_ril_reply_parse_retries 2016-10-14 16:21:23 +03:00
Denis Kenzior
cf059171d7 rilmodem: Implement ril_pin_change_state_cb inline 2016-10-14 16:21:23 +03:00
Denis Kenzior
ddabae7a54 gril: Remove g_ril_reply_oem_hook_raw 2016-10-14 16:21:23 +03:00
Denis Kenzior
aabfd23aed rilmodem: Implement inf_pin_retries_cb inline 2016-10-14 16:21:23 +03:00
Denis Kenzior
f7a1089bd6 gril: Remove g_ril_reply_oem_hook_strings 2016-10-14 16:21:23 +03:00
Denis Kenzior
1ba9668f55 rilmodem: Implement mtk_pin_retries_cb inline 2016-10-14 16:21:23 +03:00
Denis Kenzior
f6adb2a47e gril: Remove grilrequest.[ch] 2016-10-14 16:21:23 +03:00
Denis Kenzior
1254716006 rilmodem: Don't include grilrequest.h 2016-10-14 16:21:23 +03:00
Denis Kenzior
1da578f9af ril: Remove grilrequest.h 2016-10-14 16:21:23 +03:00
Denis Kenzior
863b91f79e gril: Remove g_ril_request_oem_hook_strings 2016-10-14 16:21:23 +03:00
Denis Kenzior
5c4cd29fc2 rilmodem: Inline g_ril_request_oem_hook_strings 2016-10-14 16:21:23 +03:00
Denis Kenzior
78ea7d9946 gril: Remove g_ril_request_oem_hook_raw 2016-10-14 16:21:23 +03:00
Denis Kenzior
e684560e16 rilmodem: inline request_oem_hook_raw 2016-10-14 16:21:23 +03:00
Denis Kenzior
0af7fd0c2c gril: Remove g_ril_reply_parse_data_reg_state 2016-10-14 16:21:23 +03:00
Denis Kenzior
9b20f4c904 rilmodem: Refactor ril_data_reg_cb 2016-10-14 16:21:23 +03:00
Denis Kenzior
1c217547fd gril: Remove g_ril_reply_parse_voice_reg_state 2016-10-14 16:21:23 +03:00
Denis Kenzior
1939a251a0 rilmodem: Implement reg_cb inline 2016-10-14 16:21:23 +03:00
Denis Kenzior
deaee2b27d rilmodem: Add ril_util_registration_state_to_status 2016-10-14 16:21:23 +03:00
Denis Kenzior
28d59901c2 gril: Add parcel_r_strv 2016-10-14 16:21:23 +03:00
Denis Kenzior
d6ffc2dae7 gril: Remove g_ril_request_setup_data_call 2016-10-14 16:21:23 +03:00
Denis Kenzior
59d80cdaa2 rilmodem: Implement activate_primary inline 2016-10-14 16:21:23 +03:00
Denis Kenzior
e680c7a3dc rilmodem: Add ril_util_gprs_proto_to_ril_string 2016-10-14 16:21:23 +03:00
Denis Kenzior
8fb813ab94 gril: Remove g_ril_reply_parse_sim_status 2016-10-14 16:21:23 +03:00
Denis Kenzior
ca507cbfaf rilmodem: Refactor get_sim_status reply parsing 2016-10-14 16:21:23 +03:00
Denis Kenzior
d40079d0b5 gril: Add parcel skip string 2016-10-14 16:21:23 +03:00
Denis Kenzior
9579ce72a0 gril: Remove g_ril_reply_parse_sim_io & related 2016-10-14 16:21:23 +03:00
Denis Kenzior
59880f886c rilmodem: Implement sim io parser inline 2016-10-14 16:21:23 +03:00
Denis Kenzior
3cb3b96104 rilmodem: Remove unused ril_util_sim_state_query 2016-10-14 16:21:01 +03:00
Tony Espy
4a384a95a0 rilmodem: fix set_call_barring reply trace (mako)
This change restores the trace output for a reply to a
REQUEST_SET_FACILITY_LOCK used by the set function.
2016-10-14 16:21:01 +03:00
Tony Espy
c69b01677f unit: add new test-rilmodem-sms test cases
Add new test-rilmodem-sms test cases for the remaining
untested atom functions, including two tests for incoming
SMS unsolicited responses. Also updated test-rilmodem-cs
due to rilmodem-test-server changes.
2016-10-14 16:21:01 +03:00
Tony Espy
fd358758ce unit: add write support to rilmodem-test-server
This change adds write support to the rilmodem-test-server
in order to support testing receipt of unsolicted RIL
responses.
2016-10-14 16:21:01 +03:00
Denis Kenzior
b2d55c3bc4 rilmodem: Remove unused ril_util_call_compare_by_status 2016-10-14 16:21:01 +03:00
Denis Kenzior
d0c9970d15 rilmodem: Remove unused compare_by_phone_number 2016-10-14 16:21:01 +03:00
Denis Kenzior
daccbdbeaf rilmodem: Remove unused ril_util_call_compare 2016-10-14 16:21:01 +03:00
Denis Kenzior
71c032167d rilmodem: Remove unused ril_util_call_compare_by_id 2016-10-14 16:21:01 +03:00
Denis Kenzior
82ed6eeba5 gril: Remove g_ril_request_set_net_select_manual 2016-10-14 16:21:01 +03:00
Denis Kenzior
51cb5c773a rilmodem: Implement ril_register_manual inline 2016-10-14 16:21:01 +03:00
Denis Kenzior
da3fd754a7 gril: Remove g_ril_request_deactivate_data_call 2016-10-14 16:21:01 +03:00
Denis Kenzior
7b70463912 rilmodem: Use ril_util_build_deactivate_data_call 2016-10-14 16:21:01 +03:00
Denis Kenzior
3107fa0ce4 rilmodem: Add ril_util_build_deactivate_data_call 2016-10-14 16:21:01 +03:00
Denis Kenzior
ade915136b gril: Remove g_ril_request_sim_write_record 2016-10-14 16:21:01 +03:00
Denis Kenzior
4ad21b004a rilmodem: implement update_record inline 2016-10-14 16:21:01 +03:00
Denis Kenzior
9ef2e5353c gril: Remove g_ril_request_sim_write_binary 2016-10-14 16:21:01 +03:00
Denis Kenzior
1ca3716e8f rilmodem: Implement ril_sim_update_binary inline 2016-10-14 16:21:01 +03:00
Denis Kenzior
3df6a64280 gril: Remove g_ril_request_sim_read_record 2016-10-14 16:21:01 +03:00
Denis Kenzior
476af72e35 rilmodem: Implement ril_sim_read_record inline 2016-10-14 16:21:01 +03:00
Denis Kenzior
b8c7bcc996 gril: Remove g_ril_request_sim_read_binary 2016-10-14 16:21:01 +03:00
Denis Kenzior
0418a7db78 rilmodem: Implement ril_sim_read_binary inline 2016-10-14 16:21:01 +03:00
Denis Kenzior
1ab5d2e278 gril: Remove g_ril_request_sim_read_info 2016-10-14 16:21:01 +03:00
Denis Kenzior
4155f4ad82 rilmodem: Implement ril_sim_read_info inline 2016-10-14 16:21:01 +03:00
Tony Espy
4b5ebcbefd build: update for test-rilmodem-cs changes
Conflicts:
	ofono/Makefile.am
2016-10-14 16:20:59 +03:00
Tony Espy
1298be1adb unit: re-factor test-rilmodem-cs server logic
Use the new rilmodem-test-server functions.
2016-10-14 16:17:51 +03:00
Tony Espy
52a4e9b5e6 build: add support for test-rilmodem-sms
Conflicts:
	ofono/Makefile.am
2016-10-14 16:17:48 +03:00
Tony Espy
23373e6ce7 unit: add new test-rilmodem-sms 2016-10-14 16:11:14 +03:00
Tony Espy
ed23172c8b plugins: rm unneeded exits/sleeps from ril plugin 2016-10-14 16:11:14 +03:00
Tony Espy
1c3fc7dedc ril: remove unecessary sleep from ril plugin 2016-10-14 16:11:14 +03:00
Denis Kenzior
8f4101d57e gril: Remove g_ril_unsol_parse_radio_state_changed 2016-10-14 16:11:14 +03:00
Denis Kenzior
2cda8bc793 ril: Implement radio state changed parsing inline 2016-10-14 16:11:14 +03:00
Petr Vorel
51d004c32c gobi: Add missing _GNU_SOURCE
as we're using O_CLOEXEC
2016-10-14 16:11:14 +03:00
Denis Kenzior
74e7e2444f rilmodem: Simplify ril_gprs_set_attached 2016-10-14 16:11:14 +03:00
Denis Kenzior
5e6a565274 gril: Remove g_ril_reply_parse_operator 2016-10-14 16:10:52 +03:00
Denis Kenzior
f2c7812932 rilmodem: Implement ril_cops_cb inline 2016-10-14 16:10:52 +03:00
Denis Kenzior
8ce00e707b gril: Remove g_ril_reply_parse_avail_ops 2016-10-14 16:10:52 +03:00
Denis Kenzior
6aaae6bc6a rilmodem: Implement ril_cops_list_cb inline 2016-10-14 16:10:52 +03:00
Denis Kenzior
d34c5fd54d gril: Remove g_ril_unsol_parse_nitz 2016-10-14 16:10:52 +03:00
Denis Kenzior
8ed185e32d rilmodem: Implement ril_nitz_notify inline 2016-10-14 16:10:52 +03:00
Denis Kenzior
d789992c87 gril: Remove g_ril_unsol_parse_signal_strength 2016-10-14 16:10:52 +03:00
Denis Kenzior
d3f266372b rilmodem: Inline signal strength parsing & calc 2016-10-14 16:10:52 +03:00
Alfonso Sanchez-Beato
8e036c29fc gitignore: Ignore rilmodem-cs test binary 2016-10-14 16:10:46 +03:00
Denis Kenzior
8950228a9f gril: Remove g_ril_reply_parse_call_fail_cause 2016-10-14 16:09:58 +03:00
Denis Kenzior
54cfafa20d rilmodem: Implement lastcause_cb inline 2016-10-14 16:09:58 +03:00
Denis Kenzior
17fdc3f451 gril: Remove g_ril_unsol_parse_supp_svc_notif 2016-10-14 16:09:57 +03:00
Denis Kenzior
8fe0b753e8 rilmodem: Implement ril_ss_notify inline 2016-10-14 16:09:57 +03:00
Denis Kenzior
06e61e1d8b gril: Remove g_ril_request_dial 2016-10-14 16:09:57 +03:00
Denis Kenzior
4cbc64e4e9 rilmodem: Implement dial inline 2016-10-14 16:09:57 +03:00
Denis Kenzior
7d90b6e86c gril: Remove g_ril_request_hangup 2016-10-14 16:09:57 +03:00
Denis Kenzior
01fcc3df4b rilmodem: Implement hangups inline 2016-10-14 16:09:57 +03:00
Denis Kenzior
52a0680c31 gril: Remove g_ril_request_dtmf 2016-10-14 16:09:57 +03:00
Denis Kenzior
809cd31f3f rilmodem: Implement send_one_dtmf inline 2016-10-14 16:09:57 +03:00
Denis Kenzior
c05b8864b0 TODO: Add DTMF batch hint task 2016-10-14 16:09:57 +03:00
Denis Kenzior
f12701af82 gril: Remove g_ril_request_separate_conn 2016-10-14 16:09:57 +03:00
Denis Kenzior
f6f27acb04 rilmodem: Implement ril_private_chat inline 2016-10-14 16:09:57 +03:00
Denis Kenzior
5f45c9487b gril: Remove g_ril_request_set_supp_svc_notif 2016-10-14 16:09:57 +03:00
Denis Kenzior
fc286131db rilmodem: Implement enable_supp_svc inline 2016-10-14 16:09:57 +03:00
Denis Kenzior
e037227dc1 rilmodem: Get rid of ril_voicecall_driver_data 2016-10-14 16:09:57 +03:00
Denis Kenzior
7cd35aaac3 voicecall: Remove redundant comment 2016-10-14 16:09:57 +03:00
Denis Kenzior
0c52074896 ril: Don't use ril_voicecall_driver_data 2016-10-14 16:09:57 +03:00
Denis Kenzior
c351edd7a5 rilmodem: Remove auto-answering logic
This was only used for testing at the factory for a specific product.
Does not belong in the driver code.
2016-10-14 16:09:57 +03:00
Denis Kenzior
80ead5dedb gril: Remove g_ril_request_pin_change_state 2016-10-14 16:09:57 +03:00
Denis Kenzior
0684eeffc0 rilmodem: Implement ril_pin_change_state inline 2016-10-14 16:09:57 +03:00
Denis Kenzior
918706835b gril: Remove g_ril_request_change_passwd 2016-10-14 16:09:57 +03:00
Denis Kenzior
67b37c9cd5 rilmodem: Implement ril_change_passwd inline 2016-10-14 16:09:57 +03:00
Denis Kenzior
9bcb302884 gril: Remove g_ril_request_pin_send_puk 2016-10-14 16:09:57 +03:00
Denis Kenzior
80f7393415 rilmodem: Implement ril_pin_send_puk inline 2016-10-14 16:09:57 +03:00
Denis Kenzior
58759583fa gril: Remove g_ril_request_pin_send 2016-10-14 16:09:57 +03:00
Denis Kenzior
63b3dc2be9 rilmodem: Implement ril_pin_send inline 2016-10-14 16:09:57 +03:00
Denis Kenzior
57a242851a rilmodem: Fix up headers in sms 2016-10-14 16:09:57 +03:00
Denis Kenzior
b5f01aa8d2 gril: Remove g_ril_reply_parse_get_smsc_address 2016-10-14 16:09:57 +03:00
Denis Kenzior
19563292d9 rilmodem: Implement ril_csca_query_cb inline 2016-10-14 16:09:57 +03:00
Denis Kenzior
6780b25091 gril: Remove g_ril_reply_parse_sms_response 2016-10-14 16:09:57 +03:00
Denis Kenzior
7c9242398e rilmodem: Implement ril_submit_sms_cb inline 2016-10-14 16:09:57 +03:00
Denis Kenzior
e244554917 gril: Remove g_ril_request_sms_acknowledge 2016-10-14 16:09:57 +03:00
Denis Kenzior
60782673dc rilmodem: Implement ril_ack_delivery inline 2016-10-14 16:09:57 +03:00
Denis Kenzior
8442cc21cd gril: Remove g_ril_request_sms_cmgs 2016-10-14 16:09:57 +03:00
Denis Kenzior
1d6082005e rilmodem: Implement ril_cmgs inline 2016-10-14 16:09:57 +03:00
Denis Kenzior
2a45912752 gril: Remove g_ril_request_set_smsc_address 2016-10-14 16:09:57 +03:00
Denis Kenzior
bef4e531b7 rilmodem: Implement ril_csca_set inline 2016-10-14 16:09:57 +03:00
Denis Kenzior
cc2781ee50 gril: Remove g_ril_unsol_parse_new_sms & related 2016-10-14 16:09:57 +03:00
Denis Kenzior
340b66025b rilmodem: Implement ril_sms_notify inline 2016-10-14 16:09:57 +03:00
Denis Kenzior
9879fd990c rilmodem: Remove unneeded code 2016-10-14 16:09:57 +03:00
Denis Kenzior
74db6eb392 rilmodem: Remove comments that state the obvious 2016-10-14 16:09:57 +03:00
Denis Kenzior
771d338001 gril: Remove radio-setting specific constants 2016-10-14 16:09:57 +03:00
Denis Kenzior
6808dd688e rilmodem: Move constants from gril 2016-10-14 16:09:57 +03:00
Denis Kenzior
2d46bbac4d gril: Remove g_ril_request_set_preferred_network_type 2016-10-14 16:09:57 +03:00
Denis Kenzior
442b427a19 rilmodem: Implement ril_set_rat_mode inline 2016-10-14 16:09:57 +03:00
Denis Kenzior
bebe9d8d8a gril: Remove g_ril_reply_parse_get_preferred_network_type 2016-10-14 16:09:57 +03:00
Denis Kenzior
1b21edb1f5 rilmodem: Implement ril_rat_mode_cb inline 2016-10-14 16:09:57 +03:00
Denis Kenzior
52ee74f0af gril: Remove g_ril_request_screen_state 2016-10-14 16:09:57 +03:00
Denis Kenzior
296dd76ff7 rilmodem: Implement ril_set_fast_dormancy inline 2016-10-14 16:09:57 +03:00
Denis Kenzior
0e68c13837 rilmodem: Get rid of pointless g_idle_add 2016-10-14 16:09:57 +03:00
Denis Kenzior
d332624f5c rilmodem: Get rid of ril_radio_settings_driver_data 2016-10-14 16:09:57 +03:00
Denis Kenzior
fbee20e850 ril: Pass GRil object to radio_settings
Instead of ril_radio_settings_driver_data
2016-10-14 16:09:57 +03:00
Denis Kenzior
eb52bc247a rilmodem: Get rid of radio-settings.h 2016-10-14 16:03:39 +03:00
Denis Kenzior
0741acca48 build: Make distcheck pass again 2016-10-14 16:03:39 +03:00
Denis Kenzior
70d2d70623 gril: Fix distcheck error 2016-10-14 16:03:39 +03:00
Denis Kenzior
baca4c0371 rilmodem: Get rid of g_try_new0 2016-10-14 16:03:39 +03:00
Denis Kenzior
aa5e04cbca build: Tweak gril_sources 2016-10-14 16:03:39 +03:00
Tony Espy
f1cc9990b3 build: add support for rilmodem-cs test
Conflicts:
	ofono/Makefile.am
2016-10-14 16:03:37 +03:00
Tony Espy
6bd0264a22 unit: add new test rilmodem-cs
This commit adds a new style of build-time/unit test to
rilmodem.  These tests setup a dummy server socket and
attach a gril instance to it.  This allows rilmodem
call-settings atom functions to be tested directly,
validating request parcels received by the server-side,
and callbacks that happen in response to canned responses
sent by the server-side.
2016-10-14 16:00:33 +03:00
Denis Kenzior
19166a33ef gril: Remove g_ril_request_send_ussd 2016-10-14 16:00:26 +03:00
Denis Kenzior
eb6128ccb6 rilmodem: Make ril_ussd_request inline 2016-10-14 16:00:26 +03:00
Denis Kenzior
46e5909e17 rilmodem: Rework ril_ussd_request 2016-10-14 16:00:26 +03:00
Denis Kenzior
b5652aaf09 rilmodem: Rework ril_ussd_cancel 2016-10-14 16:00:26 +03:00
Denis Kenzior
aa4b7c2a89 gril: Remove g_ril_unsol_parse_ussd and related 2016-10-14 16:00:26 +03:00
Denis Kenzior
1b274a6470 rilmodem: Implement ril_ussd_notify inline 2016-10-14 16:00:26 +03:00
Denis Kenzior
cc6a53b191 rilmodem: Inline query_serial and query_revision
query_serial was supposed to use parse_imei functionality, but called
baseband_version instead.  Rework both these to use inline parsers.
2016-10-14 16:00:26 +03:00
Denis Kenzior
1b5b1b545b gril: Remove g_ril_reply_parse_get_imei 2016-10-14 16:00:26 +03:00
Denis Kenzior
4389fffb72 gril: Remove g_ril_reply_parse_baseband_version 2016-10-14 16:00:26 +03:00
Denis Kenzior
95ca9ae64d rilmodem: Rework devinfo driver
Remove comments that state the obvious
Remove pointless allocations / frees
2016-10-14 16:00:26 +03:00
Denis Kenzior
71aded607f rilmodem: Rework header order in call-volume 2016-10-14 16:00:26 +03:00
Denis Kenzior
d209f372d4 gril: Remove g_ril_reply_parse_get_mute 2016-10-14 16:00:26 +03:00
Denis Kenzior
aa16342fc1 rilmodem: Implement probe_mute_cb inline 2016-10-14 16:00:26 +03:00
Denis Kenzior
2a7a6f7f0c gril: Remove g_ril_request_set_mute 2016-10-14 16:00:26 +03:00
Denis Kenzior
08a320ad90 rilmodem: Implement ril_call_volume_mute inline 2016-10-14 16:00:26 +03:00
Denis Kenzior
ff1dffebe4 rilmodem: Rework header order in call-settings 2016-10-14 16:00:26 +03:00
Denis Kenzior
fac809eac9 rilmodem: Rework header order in call-forwarding 2016-10-14 16:00:26 +03:00
Denis Kenzior
6420640395 rilmodem: Rework header order in call-barring 2016-10-14 16:00:26 +03:00
Denis Kenzior
400cfed044 gril: Remove g_ril_reply_parse_set_facility_lock 2016-10-14 16:00:26 +03:00
Denis Kenzior
eef25504f9 rilmodem: Implement ril_call_barring_set_cb inline 2016-10-14 16:00:26 +03:00
Denis Kenzior
4db63e87f7 gril: Remove g_ril_reply_parse_query_facility_lock 2016-10-14 16:00:26 +03:00
Denis Kenzior
440da3c009 rilmodem: Implement ril_call_barring_query_cb inline 2016-10-14 16:00:26 +03:00
Denis Kenzior
d3e2ce9c9b gril: Remove g_ril_request_change_barring_password 2016-10-14 16:00:26 +03:00
Denis Kenzior
93cd410a7b rilmodem: Make ril_call_barring_set_passwd inline 2016-10-14 16:00:26 +03:00
Denis Kenzior
e0fbec976b gril: Remove g_ril_request_set_facility_lock 2016-10-14 16:00:25 +03:00
Denis Kenzior
f34d2f9dcf rilmodem: Implement ril_call_barring_set inline 2016-10-14 16:00:25 +03:00
Denis Kenzior
361c552898 gril: Remove g_ril_request_query_facility_lock 2016-10-14 16:00:25 +03:00
Denis Kenzior
d675c3362f rilmodem: Implement ril_call_barring_query inline 2016-10-14 16:00:25 +03:00
Denis Kenzior
9c014fba03 gril: Remove g_ril_request_power 2016-10-14 16:00:25 +03:00
Denis Kenzior
89a76af30f ril: Implement power on/off inline 2016-10-14 16:00:25 +03:00
Denis Kenzior
120f200ba1 gril: Remove g_ril_reply_parse_query_call_fwd 2016-10-14 16:00:25 +03:00
Denis Kenzior
f2a8ccf079 rilmodem: Implement g_ril_request_call_fwd inline 2016-10-14 16:00:25 +03:00
Denis Kenzior
dec2dcd735 gril: Remove g_ril_request_call_fwd and related 2016-10-14 16:00:25 +03:00
Denis Kenzior
29a1f8d9ed rilmodem: Rework call-forwarding requests 2016-10-14 16:00:25 +03:00
Denis Kenzior
3b7ef48976 gril: Remove g_ril_reply_parse_imsi 2016-10-14 16:00:25 +03:00
Denis Kenzior
b9ea2e0924 rilmodem: Implement ril_imsi_cb inline 2016-10-14 16:00:25 +03:00
Denis Kenzior
0845da6a2e gril: Remove g_ril_reply_parse_get_clir & related 2016-10-14 16:00:25 +03:00
Denis Kenzior
300a11c2e3 rilmodem: Implement ril_clir_query_cb inline 2016-10-14 16:00:25 +03:00
Denis Kenzior
c5cc1ff7c8 gril: Remove g_ril_reply_parse_query_clip 2016-10-14 16:00:25 +03:00
Denis Kenzior
cdaa2fedab rilmodem: Implement ril_clip_query_cb inline 2016-10-14 16:00:25 +03:00
Denis Kenzior
2684fbf24d gril: Remove g_ril_reply_parse_query_call_waiting 2016-10-14 16:00:25 +03:00
Denis Kenzior
93300ee95e rilmodem: Implement ril_cw_query_cb inline 2016-10-14 16:00:25 +03:00
Denis Kenzior
8c175ab282 gril: Remove g_ril_request_set_clir 2016-10-14 16:00:25 +03:00
Denis Kenzior
24b9943dc1 rilmodem: Implement ril_clir_set inline 2016-10-14 16:00:25 +03:00
Denis Kenzior
3e711843cb gril: g_ril_request_query_call_waiting 2016-10-14 16:00:25 +03:00
Denis Kenzior
ead815513d rilmodem: Implement ril_cw_query inline 2016-10-14 16:00:25 +03:00
Denis Kenzior
dd78ee5fcb gril: Remove g_ril_request_set_call_waiting 2016-10-14 16:00:25 +03:00
Denis Kenzior
e61bfe0f38 rilmodem: Implement ril_cw_set inline 2016-10-14 16:00:25 +03:00
Alfonso Sanchez-Beato
f22a531051 gril: Fix access to notify callbacks
Entries to the table of notification callbacks can be added by the
callbacks while being called. This caused a glib error as gril was
using an iterator to the hash table while the table was being modified.
Fixed by avoiding the unnecesary loop.
2016-10-14 16:00:25 +03:00
Simon Fels
c2a1c60b92 hfp_ag_bluez5: use codec negotiation 2016-10-14 16:00:25 +03:00
Simon Fels
82bf1057bb emulator: add codec negotiation support 2016-10-14 16:00:25 +03:00
Simon Fels
1a25661400 hfp_ag_bluez5: Add initial handsfree audio driver 2016-10-14 16:00:25 +03:00
Alfonso Sanchez-Beato
466a65f2da gril: Remove asserts 2016-10-14 16:00:25 +03:00
Alfonso Sanchez-Beato
a672583053 rildev: Do not create modems if no env var set
Do not create rilmodem instances if the environment variable
OFONO_RIL_DEVICE is not set.
2016-10-14 16:00:25 +03:00
Denis Kenzior
f47e720628 gril: Remove g_ril_request_read_imsi 2016-10-14 16:00:25 +03:00
Denis Kenzior
c0433efc12 rilmodem: Move get_imsi implementation to rilmodem 2016-10-14 16:00:25 +03:00
Denis Kenzior
5fc98f5b59 gril: Fix IO reference counting 2016-10-14 16:00:25 +03:00
Denis Kenzior
e7d60078db gril: Remove unused structure members 2016-10-14 16:00:25 +03:00
Denis Kenzior
b6abbc0ece gril: Remove unused header 2016-10-14 16:00:25 +03:00
Denis Kenzior
a7eb318f01 gril: Remove unused function 2016-10-14 16:00:25 +03:00
Denis Kenzior
1674126665 gril: Remove unused function 2016-10-14 16:00:25 +03:00
Alfonso Sanchez-Beato
b1bb48e59f build: Add rilmodem to the build
Build gril, the rilmodem and infineon drivers, and the corresponding
plugins.

Conflicts:
	ofono/Makefile.am
	ofono/configure.ac
2016-10-14 16:00:23 +03:00
Alfonso Sanchez-Beato
abfebddbb9 rildev: plugin that creates ril-type modems
This plugin creates modems that use the rilmodem driver by looking at
environment variables: when OFONO_RIL_DEVICE exists it creates a ril
modem of the sub-type specified by the variable. OFONO_RIL_NUM_SIM_SLOTS
specifies the number of SIM slots for multi-SIM modems.
2016-10-14 15:57:52 +03:00
Alfonso Sanchez-Beato
5fb4a13562 infineon: Definitions for infineon modem 2016-10-14 15:57:52 +03:00
Alfonso Sanchez-Beato
4ff1488b2e infineon: Plugin for infineon modems
Plugin for infineon modems, which is a variant of the ril modem.
2016-10-14 15:57:52 +03:00
Tony Espy
2b4db9a52b ril: Plugin for Android modems
Plugin for Android modem, which uses the rilmodem driver.

Co-authored-by: Tony Espy <espy@canonical.com>
Co-authored-by: Ricardo Salveti de Araujo <ricardo.salveti@canonical.com>
Co-authored-by: Alfonso Sanchez-Beato <alfonso.sanchez-beato@canonical.com>
Co-authored-by: Islam Amer <islam.amer@jollamobile.com>
Co-authored-by: Jussi Kangas <jussi.kangas@tieto.com>
Co-authored-by: Juho Hämäläinen <juho.hamalainen@tieto.com>
Co-authored-by: Martti Piirainen <martti.piirainen@canonical.com>
Co-authored-by: Jarko Poutiainen <Jarko.Poutiainen@oss.tieto.com>
Co-authored-by: Tommi Kenakkala <tommi.kenakkala@oss.tieto.com>
Co-authored-by: Petri Takalokastari <petri.takalokastari@oss.tieto.com>
Co-authored-by: Miia Leinonen <miia.leinonen@oss.tieto.com>
Co-authored-by: Mikko Hurskainen <mikko.hurskainen@nomovok.com>
Co-authored-by: You-Sheng Yang <vicamo.yang@canonical.com>
2016-10-14 15:57:51 +03:00
Tony Espy
05ca5c155b rilmodem: driver for Android modems
Driver for modems that are accessed through the Android Radio Interface
Layer (RIL) for telephony, using the gril library. The driver is almost
feature complete with some exceptions, being CBS and SAT the most
prominent.

Co-authored-by: Tony Espy <espy@canonical.com>
Co-authored-by: Ricardo Salveti de Araujo <ricardo.salveti@canonical.com>
Co-authored-by: Alfonso Sanchez-Beato <alfonso.sanchez-beato@canonical.com>
Co-authored-by: Islam Amer <islam.amer@jollamobile.com>
Co-authored-by: Jussi Kangas <jussi.kangas@tieto.com>
Co-authored-by: Juho Hämäläinen <juho.hamalainen@tieto.com>
Co-authored-by: Petri Takalokastari <petri.takalokastari@oss.tieto.com>
Co-authored-by: Jarko Poutiainen <Jarko.Poutiainen@oss.tieto.com>
Co-authored-by: Tommi Kenakkala <tommi.kenakkala@oss.tieto.com>
Co-authored-by: Miia Leinonen <miia.leinonen@oss.tieto.com>
Co-authored-by: Martti Piirainen <martti.piirainen@canonical.com>
Co-authored-by: You-Sheng Yang <vicamo.yang@canonical.com>
2016-10-14 15:57:51 +03:00
Tony Espy
c55ac50f4c gril: Library to communicate with rild
gril is a library used to communicate with rild, the Android telephony
daemon. Communication happens using a named socket over which binder
parcels are transmitted.

Co-authored-by: Tony Espy <espy@canonical.com>
Co-authored-by: Ricardo Salveti de Araujo <ricardo.salveti@canonical.com>
Co-authored-by: Alfonso Sanchez-Beato <alfonso.sanchez-beato@canonical.com>
Co-authored-by: Mikko Hurskainen <mikko.hurskainen@nomovok.com>
Co-authored-by: You-Sheng Yang <vicamo.yang@canonical.com>
Co-authored-by: Ratchanan Srirattanamet <peathot@hotmail.com>
2016-10-14 15:57:30 +03:00
Simon Fels
aa32435945 hfp_ag_bluez5: register audio card
To let others (PulseAudio) be notified when a handsfree device is
connected with us and can be used for audio routing we need to
expose this by registering a audio card with the correct type.
2016-10-14 15:57:07 +03:00
Denis Kenzior
e940b97389 emulator: Add ofono_emulator_set_handsfree_card 2016-10-14 15:57:07 +03:00
Denis Kenzior
24ba9a3cf7 include: Add ofono_emulator_set_handsfree_card 2016-10-14 15:57:07 +03:00
Denis Kenzior
f7b8c07a3b AUTHORS: Mention Simon's contributions 2016-10-14 15:57:07 +03:00
Simon Fels
159083d9c3 handsfree-audio: add type for our audio cards
When registering audio cards for the handsfree and gateway roles we
need a way for our users to differentiate between both to decide which
of them they start using for their purpose.
2016-10-14 15:57:07 +03:00
Slava Monich
37d7bc057c [ofono] Remove merge artifact 2016-10-14 15:55:57 +03:00
Slava Monich
6d1521313f [ofono] Remove the old rilemodem
It's going to be overwritten by the one coming from upstream.
2016-10-14 15:55:21 +03:00
Slava Monich
1d926b9415 Merge branch 'housekeeping' into 'master'
See merge request !86
2016-10-14 08:52:55 +00:00
Slava Monich
f665278df3 Merge branch 'max_calls' into 'master'
Make sure that maximum number of simultaneous calls is not zero

Some RILs provide NULL string instead of this parameter.
Reported by the community.

See merge request !85
2016-10-14 08:52:07 +00:00
Slava Monich
0bd5130e02 [ofono] Housekeeping
Removed some unnecessary and suplicate code from ril_gprs_context.

Moved ril_address_family to ril_gprs_context.c because it's not used
anywhere else.
2016-10-13 13:10:31 +03:00
Slava Monich
af2c27ea0f [ril] Make sure that maximum number of simultaneous calls is not zero. Fixes MER#1672
Some RILs provide NULL string instead of this parameter.
2016-10-13 12:15:09 +03:00
Slava Monich
3370c09c89 main: Make -d option repeatable
Concatenating the patterns makes more sense than using the last
supplied value and leaking the previous allocated patterns.
2016-10-07 10:48:39 +03:00
Slava Monich
cd23203094 Merge branch 'libmce' into 'master'
Use libmce-glib to track the display state

See merge request !84
2016-10-07 07:48:05 +00:00
Slava Monich
64fcdddaac [ofono] Use libmce-glib to track the display state. JB#36523 2016-10-06 17:36:17 +03:00
Slava Monich
2039b1bd09 Merge branch 'empty' into 'master'
Add EmptyConfig option

See merge request !83
2016-10-03 12:42:56 +00:00
Slava Monich
a52666dc20 [ril] Added EmptyConfig configuration option. Fixes MER#1660
If it's enabled, then all [ril_x] sections are ignored even
if they are present, and no default configuration is created.
2016-10-01 16:43:50 +03:00
Slava Monich
3b4ce1f47b Merge branch 'cached_spn' into 'master'
Don't update SPN while slot is being enabled or disabled

To avoid bothering clients with inconsistent states that make
little sense.

See merge request !82
2016-09-29 10:42:46 +00:00
Slava Monich
d8aefd40c4 [ril] Don't update SPN while slot is being enabled or disabled. Fixes JB#36420
It's better to hold it off until we arrive at a consistent state.
2016-09-28 00:18:15 +03:00
Slava Monich
e79055354c Merge branch 'master' into 'master'
Remove bluez build requirement

There doesn't seem to be any reason for requiring bluez at build time.
Besides since bluez (5) is renamed as bluez5 this won't be compatible
with it.

See merge request !81
2016-09-21 21:45:12 +00:00
Slava Monich
5e75f650c3 Merge branch 'ussd' into 'master'
Don't fail USSD cancel requests

See merge request !80
2016-09-21 21:44:25 +00:00
Jarko Poutiainen
ae782ca6f2 [packaging] remove bluez build requirement.Contributes to JB#36046 2016-09-21 16:10:59 +03:00
Slava Monich
b929a8e8c8 [ril] Don't fail USSD cancel requests from the core. Contributest to JB#36348
If we pass RIL_REQUEST_CANCEL_USSD error to the core, ofono will stay in
its current state and reject the subsequent USSD requests.
2016-09-21 13:41:47 +03:00
Slava Monich
530c3bc812 [ril] Improved parsing of RIL_UNSOL_ON_USSD packets
Particularly, prevent the crash if the USSD type string is missing.
2016-09-21 13:34:15 +03:00
martinjones
0e1a58781f Merge branch 'conf_proto' into 'master'
[ril] Fix creating multiparty and splitting multiparty. Contributes to JB#4743



See merge request !79
2016-08-11 09:41:40 +00:00
Martin Jones
77a26177e5 [ril] Fix creating multiparty and splitting multiparty. Contributes to JB#4743 2016-08-11 09:39:40 +00:00
Slava Monich
f6ea7e4c36 Merge branch 'cf_get_prop' into 'master'
Allow multiple pending org.ofono.CallForwarding.GetProperties

See merge request !77
2016-08-11 08:13:22 +00:00
Slava Monich
babea14604 Merge branch 'jb35840' into 'master'
See merge request !78
2016-07-27 13:24:16 +00:00
Slava Monich
e13ae6d5b3 [ril] Fixed default single-SIM config. Fixes JB#35840
It has to be Jolla1 compatible.
2016-07-27 16:00:54 +03:00
Slava Monich
40ce8f7185 Merge branch 'sim_write' into 'master'
SIM write support

If it's done right, quite a few things (those that have to do with
writing stuff to SIM card) should start working.

See merge request !76
2016-07-25 09:19:54 +00:00
Slava Monich
f68585a784 [ril] Implemented SIM write I/O support. Fixes MER#1199 2016-07-25 12:15:06 +03:00
Slava Monich
16105b8ace [ril] Cleaned up call forwarding code. JB#20921 2016-07-25 12:13:22 +03:00
Slava Monich
91245de799 [ofono] call-forwarding: allow multiple pending GetProperties
The very first call that that every org.ofono.CallForwarding
client makes is GetProperties. With multiple clients, only the
first one was waiting for the completion of the initial query,
all other calls were rejected with org.ofono.Error.InProgress.
In theory, the clients could retry the call later, but in
reality very few clients actually do that.
2016-07-20 22:57:49 +03:00
Slava Monich
c52471132a Merge branch 'pin_retries' into 'master'
Query number of retries left with empty pin

This works with some Qualcomm RILs. Those RILs that don't support
it will fail this request with no harm done. In case if it turns
out to be harmful with some RILs, it can be turned off with
emptyPinQuery=false in ril_subscription.conf

See merge request !75
2016-07-15 14:07:17 +00:00
Slava Monich
a8e7b86733 Merge branch 'band-mode' into 'master'
Query available band modes at startup

With some RIL implementations, RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE
causes some magic Android properties to appear. Otherwise it's
harmless and fairly useless.

See merge request !72
2016-07-15 14:07:00 +00:00
Slava Monich
8829682fad [ril] Query number of retries left with empty pin. MER#1089
This works with some Qualcomm RILs. Those RILs that don't support it
will fail this request with no harm done.

In case if turns out to be harmful with some RILs, it can be turned off
with emptyPinQuery=false in ril_subscription.conf
2016-07-07 11:37:54 +03:00
Slava Monich
246e30d1a5 Merge branch 'locked_pins' into 'master'
Implement SC facility lock query

Otherwise `org.ofono.SimManager` `LockedPins` state gets lost after
ofono is restarted. A few cherry-picks from upstream were required.

See merge request !73
2016-07-07 08:34:25 +00:00
Slava Monich
83267e1fa5 Merge branch 'ril_phonebook' into 'master'
Free phonebook state if export hasn't finished

Fixes memory leaks like these:

==21616== 56 (8 direct, 48 indirect) bytes in 1 blocks are definitely lost in loss record 437 of 520
==21616==    at 0x483F380: malloc (vg_replace_malloc.c:296)
==21616==    by 0x4AEB26F: g_malloc (gmem.c:94)
==21616==    by 0x4B010D9: g_slice_alloc (gslice.c:1025)
==21616==    by 0x4B01FC7: g_slist_append (gslist.c:213)
==21616==    by 0x32553: start_sim_app_read (ril_phonebook.c:860)
==21616==    by 0x3276B: pb_reference_data_cb (ril_phonebook.c:903)
==21616==    by 0x153EB3: sim_fs_op_error (simfs.c:271)
==21616==    by 0x1552BB: sim_fs_op_info_cb (simfs.c:682)
==21616==    by 0x3BBA3: ril_sim_file_info_cb (ril_sim.c:358)
==21616==    by 0x489F679: grilio_channel_handle_packet (grilio_channel.c:711)
==21616==    by 0x489F679: grilio_channel_read (grilio_channel.c:811)
==21616==    by 0x489F679: grilio_channel_read_callback (grilio_channel.c:824)
==21616==    by 0x4AE621B: g_main_dispatch (gmain.c:3154)
==21616==    by 0x4AE621B: g_main_context_dispatch (gmain.c:3769)
==21616==    by 0x4AE64C9: g_main_context_iterate.isra.4 (gmain.c:3840)
==21616== 
==21616== 366 (28 direct, 338 indirect) bytes in 1 blocks are definitely lost in loss record 503 of 520
==21616==    at 0x483F380: malloc (vg_replace_malloc.c:296)
==21616==    by 0x4AEB26F: g_malloc (gmem.c:94)
==21616==    by 0x4B010D9: g_slice_alloc (gslice.c:1025)
==21616==    by 0x4B1076B: g_tree_new_full (gtree.c:217)
==21616==    by 0x324CF: start_sim_app_read (ril_phonebook.c:846)
==21616==    by 0x3276B: pb_reference_data_cb (ril_phonebook.c:903)
==21616==    by 0x153EB3: sim_fs_op_error (simfs.c:271)
==21616==    by 0x1552BB: sim_fs_op_info_cb (simfs.c:682)
==21616==    by 0x3BBA3: ril_sim_file_info_cb (ril_sim.c:358)
==21616==    by 0x489F679: grilio_channel_handle_packet (grilio_channel.c:711)
==21616==    by 0x489F679: grilio_channel_read (grilio_channel.c:811)
==21616==    by 0x489F679: grilio_channel_read_callback (grilio_channel.c:824)
==21616==    by 0x4AE621B: g_main_dispatch (gmain.c:3154)
==21616==    by 0x4AE621B: g_main_context_dispatch (gmain.c:3769)
==21616==    by 0x4AE64C9: g_main_context_iterate.isra.4 (gmain.c:3840)

Those occur if SIM card is removed before phonebook export is finished

See merge request !74
2016-07-07 08:33:47 +00:00
Slava Monich
e1ab11ad25 Merge branch 'configs-mer' into 'master'
configs-mer doesn't need to require ofono

The dependency goes the other way around.

See merge request !71
2016-07-07 08:32:36 +00:00
Slava Monich
a9193282d5 [ril] Fixed another memory leak in RIL phonebook. Fixes to MER#1615 2016-07-07 00:11:27 +03:00
Slava Monich
f80bb5c5bb [ril] Implement facility lock query. Fixes MER#1614 2016-07-06 19:27:34 +03:00
Slava Monich
66eb87777f sim: Query the status of SC facility lock 2016-07-06 19:27:00 +03:00
Denis Kenzior
e5291006fd include: Remove unused query_locked method 2016-07-06 19:27:00 +03:00
Denis Kenzior
c609d7cc07 isi: Change query_locked to query_facility_lock 2016-07-06 19:27:00 +03:00
Denis Kenzior
0de562b019 isimodem: Remove unimplemented query_locked method 2016-07-06 19:27:00 +03:00
Denis Kenzior
60b11f712c atmodem: Change query_locked to query_facility_lock 2016-07-06 19:27:00 +03:00
Samrat Guha Niyogi
80d347b964 sim: Query the status of PS and PN facility locks 2016-07-06 19:27:00 +03:00
Samrat Guha Niyogi
97abd10984 include: Add query_facility_lock method 2016-07-06 19:27:00 +03:00
Slava Monich
5201fc0183 [ril] Free phonebook state if export hasn't finished. Contributes to MER#1615 2016-07-06 12:37:21 +03:00
Slava Monich
14e4ef8e07 [ril] Query available band modes at startup. Contributes to JB#35461 2016-07-04 23:21:23 +03:00
Slava Monich
22bc6d526e [rpm] configs-mer doesn't need to require ofono
The dependency goes the other way around.
2016-07-04 21:20:28 +03:00
Slava Monich
baa4fe30e5 Merge branch 'master' into 'master'
Ensure /var/lib/ofono exists on package.

Directory wasn't being created with new automake.

Makefile.am includes:

statedir = $(localstatedir)/lib/ofono
state_DATA =

Suspect newer just skips it as empty. mkdir should be a safe workaround.

See merge request !69
2016-07-04 16:58:03 +00:00
Slava Monich
d0d0793ccb Merge branch 'allow-data' into 'master'
Add allowDataReq ril_subscription.conf option

That fixes Nexus 5 port. Tested by community.

See merge request !70
2016-07-04 16:56:21 +00:00
Slava Monich
55dd461ce7 [ril] Allow to specify default values in Settings section of ril_subscription.conf
Those will become default for all modems but still can be overwritten in
per-modem config sections.
2016-07-03 16:18:48 +03:00
Slava Monich
4da1a30290 [ril] Added allowDataReq ril_subscription.conf option. Fixes MER#1613
Set to true if your RIL doesn't support RIL_REQUEST_ALLOW_DATA
2016-07-02 14:17:06 +03:00
Slava Monich
303f527d79 [ofono] Deleted obsolete debuglog-api.txt 2016-06-28 14:13:05 +03:00
Pekka Vuorela
27e8621c0b [ofono] Ensure /var/lib/ofono exists on package. Contributes to JB#35132 2016-06-16 15:47:44 +03:00
Slava Monich
200237372a Merge branch 'jb35406' into 'master'
Retry data call on PDP_FAIL_ERROR_UNSPECIFIED

According to comment in android's ril.h, if data call setup fails
with status PDP_FAIL_ERROR_UNSPECIFIED, then we need to silently
retry the call. Let's do that.

See merge request !68
2016-06-07 11:27:31 +00:00
Slava Monich
9cae262c80 [ril] Retry data call on PDP_FAIL_ERROR_UNSPECIFIED. Fixes JB#35406
According to comment in android's ril.h, if data call setup fails
with status PDP_FAIL_ERROR_UNSPECIFIED, then we need to silently
retry the call.
2016-06-07 11:23:49 +03:00
Slava Monich
5e23459b67 Merge branch 'debuglog' into 'master'
Control ofono logging over D-Bus

The previous solution only allowed switching logs on/off, this one
allows to pipe the log to another process.

See merge request !67
2016-05-30 20:29:56 +00:00
Slava Monich
a88d7af6c8 Merge branch 'dtmf' into 'master'
Fix memory trashing after sending DTMF tone

After a DTMF tone was sent,tone_queue buffer was becoming just
a few bytes long but the code kept on assuming that it's still
pointing to at least MAX_DTMF_BUFFER bytes of memory. Under
valgrind it looked like this:

==3914== Invalid write of size 1
==3914==    at 0x4B01AEE: g_strlcat (gstrfuncs.c:1488)
==3914==    by 0x33645: ril_voicecall_send_dtmf (ril_voicecall.c:639)
==3914==    by 0x7EE4B: tone_request_run (voicecall.c:4001)
==3914==    by 0x4AE5B57: g_timeout_dispatch (gmain.c:4577)
==3914==    by 0x4AE521B: g_main_dispatch (gmain.c:3154)
==3914==    by 0x4AE521B: g_main_context_dispatch (gmain.c:3769)
==3914==    by 0x4AE54C9: g_main_context_iterate.isra.4 (gmain.c:3840)
==3914==    by 0x4AE573B: g_main_loop_run (gmain.c:4034)
==3914==    by 0x1F0AF: main (main.c:252)
==3914==  Address 0x591c361 is 0 bytes after a block of size 1 alloc'd
==3914==    at 0x483F380: malloc (vg_replace_malloc.c:296)
==3914==    by 0x4AEA26F: g_malloc (gmem.c:94)
==3914==    by 0x4B0130D: g_strdup (gstrfuncs.c:363)
==3914==    by 0x336AB: ril_voicecall_send_dtmf_cb (ril_voicecall.c:600)
==3914==    by 0x489F679: grilio_channel_handle_packet (grilio_channel.c:711)
==3914==    by 0x489F679: grilio_channel_read (grilio_channel.c:811)
==3914==    by 0x489F679: grilio_channel_read_callback (grilio_channel.c:824)
==3914==    by 0x4AE521B: g_main_dispatch (gmain.c:3154)
==3914==    by 0x4AE521B: g_main_context_dispatch (gmain.c:3769)
==3914==    by 0x4AE54C9: g_main_context_iterate.isra.4 (gmain.c:3840)
==3914==    by 0x4AE573B: g_main_loop_run (gmain.c:4034)
==3914==    by 0x1F0AF: main (main.c:252)

This patch replaces tone_queue with a FIFO ring buffer.

See merge request !66
2016-05-30 19:56:28 +00:00
Slava Monich
290c3d2388 [ofono] Control ofono logging over D-Bus. Contributes to JB#34874
The previous solution only allowed switching logs on/off, this one
allows to pipe the log to another process.
2016-05-30 19:00:42 +03:00
Slava Monich
ee880398ad [ril] Fix memory trashing after sending DTMF tone. Fixes JB#35384 2016-05-30 16:18:23 +03:00
Slava Monich
d65bbc3236 Merge branch 'jb35249' into 'master'
Fix crash on exit if data call setup is pending

See merge request !65
2016-05-17 13:57:18 +00:00
Slava Monich
655544be45 [ril] Fix crash on exit if data call setup is pending. Fixes JB#35249
When context is being removed, the core has already completed its
pending D-Bus request, invoking the completion callback causes
libdbus to panic.
2016-05-16 18:04:34 +03:00
Slava Monich
50a544a191 Merge branch 'default-proto' into 'master'
Use the right data protocol for default context settings

Follow-up to mer-core/ofono!60

See merge request !64
2016-05-14 08:42:27 +00:00
Slava Monich
9e7a4a4d72 [ofono] Use the right data protocol for default context settings. Contributes to JB#32750 2016-05-14 11:40:38 +03:00
Slava Monich
c5b5e3109d Merge branch 'ackretry' into 'master'
Retry RIL_REQUEST_SMS_ACKNOWLEDGE

People report seeing `SMS acknowledgement failed: Further SMS
reception is not guaranteed` message in the log, when they have
some sort of trouble with SMS. Let's see if retry helps.

See merge request !63
2016-04-23 15:48:20 +00:00
Slava Monich
deb106343a [ril] Retry RIL_REQUEST_SMS_ACKNOWLEDGE. Contributes to JB#34851
People report seeing "SMS acknowledgement failed: Further SMS reception
is not guaranteed" message in the log, when they have some sort of trouble
with SMS. Let's see if retry helps.
2016-04-23 12:21:23 +03:00
Slava Monich
771e8becf2 Merge branch 'imei' into 'master'
Fix IMEI query at startup.

See merge request !62
2016-04-22 08:56:45 +00:00
Slava Monich
a0b69f974a [ril] Fixed IMEI query at startup. Fixes JB#34937
IMEI related queries were being completed too early.
2016-04-21 12:25:58 +03:00
Slava Monich
b3a4aaea95 [ofono] Silence "Interface xxx not found on the interface_list" messages
Attempt to remove a modem interface already removed (internally) by ofono
is not an error.
2016-04-20 12:22:33 +03:00
Slava Monich
137e504e10 Merge branch 'jb34928' into 'master'
Prevent crash in ril_delayed_register

See merge request !61
2016-04-19 12:18:32 +00:00
Slava Monich
2de3e445f0 Merge branch 'ipv4v6' into 'master'
Use IPV4V6 for internet contexts by default

Once the packet data protocol is configured, it's saved in the
config file and can be changed via UI. In other words, default
value only affects first-time configuration (i.e. provisioning)
and "Reset to default" function.

See merge request !60
2016-04-19 12:17:57 +00:00
Slava Monich
1cd0d60768 [ril] Prevent crash in ril_delayed_register. Fixes JB#34928
Delayed registration needs to be cancelled by ril_phonebook_remove
if it (registration) hasn't been done yet.
2016-04-19 00:41:33 +03:00
Slava Monich
d1f1f16355 [ofono] Use IPV4V6 (dual) for internet context by default. Fixes JB#32750 2016-04-18 18:59:09 +03:00
Slava Monich
4df72c9376 [ofono] mbpi: Make default packet data protocol configurable. Contributes to JB#32750
Note that according to TS 23.401, UE which is IPv6 and IPv4 capable
should request IPv4v6.
2016-04-18 18:53:50 +03:00
Slava Monich
a35ca2bbd9 [ofono] mbpi: Make MBPI database file configurable at runtime
Useful for provisioning unit tests, if nothing else.
2016-04-18 18:53:28 +03:00
Slava Monich
8376174c76 Merge branch 'oemraw' into 'master'
See merge request !59
2016-04-15 16:12:38 +00:00
Slava Monich
b6f5befcac [ril] Simplify OemRaw D-Bus interface implementation
Since support for this interface has never been merged upstream (and
most likely never will) there is no need to touch ofono core at all.
Moving everything into RIL plugin simplifies the implementation and
allows to delete a few hundred lines of unnecessary code.
2016-04-14 19:03:57 +03:00
Slava Monich
403f29320c [mbpi] Housekeeping 2016-04-13 17:51:32 +03:00
194 changed files with 18161 additions and 11674 deletions

6
ofono/.gitignore vendored
View File

@@ -42,6 +42,12 @@ unit/test-mux
unit/test-caif
unit/test-stkutil
unit/test-cdmasms
unit/test-rilmodem-cb
unit/test-rilmodem-cs
unit/test-rilmodem-gprs
unit/test-rilmodem-sms
unit/test-*.log
unit/test-*.trs
tools/huawei-audio
tools/auto-enable

View File

@@ -104,3 +104,15 @@ Alex J Lennon <ajlennon@dynamicdevices.co.uk>
Sergey Alirzaev <zl29ah@gmail.com>
Marko Sulejic <marko.sulejic@hale.at>
Johannes 'josch' Schauer <josch@mister-muffin.de>
Simon Fels <simon.fels@canonical.com>
John Ernberg <john.ernberg@actia.se>
Dongsu Park <dongsu@endocode.com>
Dragos Tatulea <dragos@endocode.com>
Samrat Guha Niyogi <samrat.guha.niyogi@intel.com>
Anirudh Gargi <anirudh.gargi@intel.com>
Nishanth V <nishanth.v@intel.com>
Antara Borwankar <antara.borwankar@gmail.com>
Martin Chaplet <m.chaplet@kerlink.fr>
Suman Mallela <suman.m@intel.com>
Rajagopal Aravindan <rajagopalx.aravindan@intel.com>
Antoine Aubert <a.aubert@overkiz.com>

View File

@@ -1,3 +1,34 @@
ver 1.19:
Fix issue with DHCP parsing and Huawei modems.
Fix issue with detecting Huawei E3372 modem.
Fix issue with handling serving cell info.
Fix issue with handling SIM SC facility lock.
Fix issue with Android RIL PIN retry logic.
Fix issue with Android RIL and RAT handling.
Add support for Android RIL cell broadcast.
Add support for SoFIA 3GR thermal management.
ver 1.18:
Fix issue with cell broadcast and use-after-fee.
Fix issue with repeated held call indicator.
Fix issue with +CCWA and connection setup.
Fix issue with empty operator scan results.
Fix issue with persistent RAT mode handling.
Fix issue with multiparty call introspection.
Fix issue with GRPS context introspection.
Fix issue with stale context deactivation.
Add support for automatic context activation.
Add support for SIM service provider names.
Add support for handling allowed APN lists.
Add support for network monitoring interface.
Add support for U-Blox TOBY-L2 modem series.
Add support for Sierra MC73xx QMI modems.
Add support for SoFIA 3GR modem series.
Add support for upower battery monitoring.
Add support for gateway audio card types.
Add support for Handsfree audio driver.
Add support for Android RIL integration.
ver 1.17:
Fix issue with alphanumeric TP-OA handling.
Fix issue with push notification origin port.

View File

@@ -113,3 +113,5 @@ doc/coding-style.txt.
a feature that touches files under 'include/', 'src/' and 'drivers/'
directories, split in three separated patches, taking care not to
break compilation.
4) Submit patches using git send-email to ofono@ofono.org

View File

@@ -21,9 +21,9 @@ pkginclude_HEADERS = include/log.h include/plugin.h include/history.h \
include/cdma-connman.h include/gnss.h \
include/private-network.h include/cdma-netreg.h \
include/cdma-provision.h include/handsfree.h \
include/handsfree-audio.h \
include/sim-mnclength.h include/oemraw.h \
include/siri.h
include/sim-mnclength.h \
include/handsfree-audio.h include/siri.h \
include/netmon.h
nodist_pkginclude_HEADERS = include/version.h
@@ -97,14 +97,12 @@ gisi_sources = gisi/client.c gisi/client.h gisi/common.h \
gisi/server.c gisi/server.h \
gisi/socket.c gisi/socket.h
gril_sources = gril/gril.h gril/gril.c gril/grilio.h \
gril/grilio.c gril/grilutil.h \
gril/grilutil.c gril/ringbuffer.h \
gril/gfunc.h gril/ril.h \
gril_sources = gril/gril.h gril/gril.c \
gril/grilio.h gril/grilio.c \
gril/grilutil.h gril/grilutil.c \
gril/gfunc.h gril/gril.h \
gril/parcel.c gril/parcel.h \
gril/grilreply.c gril/grilreply.h \
gril/grilrequest.c gril/grilrequest.h \
gril/grilunsol.c gril/grilunsol.h
gril/ril_constants.h
btio_sources = btio/btio.h btio/btio.c
@@ -120,6 +118,7 @@ endif
if RILMODEM
if JOLLA_RILMODEM
builtin_modules += ril
builtin_sources += drivers/ril/ril_call_barring.c \
drivers/ril/ril_call_forward.c \
@@ -127,15 +126,16 @@ builtin_sources += drivers/ril/ril_call_barring.c \
drivers/ril/ril_call_volume.c \
drivers/ril/ril_cell_info.c \
drivers/ril/ril_cell_info_dbus.c \
drivers/ril/ril_config.c \
drivers/ril/ril_cbs.c \
drivers/ril/ril_data.c \
drivers/ril/ril_devinfo.c \
drivers/ril/ril_ecclist.c \
drivers/ril/ril_gprs.c \
drivers/ril/ril_gprs_context.c \
drivers/ril/ril_mce.c \
drivers/ril/ril_modem.c \
drivers/ril/ril_mtu.c \
drivers/ril/ril_netmon.c \
drivers/ril/ril_netreg.c \
drivers/ril/ril_network.c \
drivers/ril/ril_oem_raw.c \
@@ -160,20 +160,29 @@ dist_conf_DATA += drivers/ril/ril_subscription.conf
endif
else
builtin_sources += $(gril_sources)
builtin_modules += rildev
builtin_sources += plugins/rildev.c
builtin_modules += ril
builtin_sources += plugins/ril.c
builtin_sources += plugins/ril.c plugins/ril.h
builtin_modules += infineon
builtin_sources += plugins/infineon.c
builtin_modules += ril_sofia3gr
builtin_sources += plugins/ril_sofia3gr.c
builtin_modules += rilmodem
builtin_sources += drivers/rilmodem/rilmodem.h \
drivers/rilmodem/vendor.h \
drivers/rilmodem/rilmodem.c \
drivers/rilmodem/devinfo.c \
drivers/rilmodem/network-registration.c \
drivers/rilmodem/voicecall.c \
drivers/rilmodem/voicecall.h \
drivers/rilmodem/call-volume.c \
drivers/rilmodem/gprs.c \
drivers/rilmodem/gprs-context.c \
@@ -181,20 +190,15 @@ builtin_sources += drivers/rilmodem/rilmodem.h \
drivers/rilmodem/sms.c \
drivers/rilmodem/rilutil.c \
drivers/rilmodem/rilutil.h \
drivers/rilmodem/radio-settings.c \
drivers/rilmodem/phonebook.c \
drivers/rilmodem/ussd.c \
drivers/rilmodem/call-settings.c \
drivers/rilmodem/call-forwarding.c \
drivers/rilmodem/cbs.c \
drivers/rilmodem/oemraw-messages.c \
drivers/rilmodem/radio-settings.c \
drivers/rilmodem/call-barring.c \
drivers/rilmodem/stk.c
if DATAFILES
dist_conf_DATA += gril/ril_subscription.conf
endif
drivers/rilmodem/netmon.c \
drivers/rilmodem/stk.c \
drivers/rilmodem/cbs.c \
drivers/infineonmodem/infineon_constants.h
endif
endif
@@ -282,8 +286,7 @@ endif
if ATMODEM
builtin_modules += atmodem
builtin_sources += $(gatchat_sources) \
drivers/atmodem/atmodem.h \
builtin_sources += drivers/atmodem/atmodem.h \
drivers/atmodem/atmodem.c \
drivers/atmodem/call-settings.c \
drivers/atmodem/sms.c \
@@ -421,6 +424,13 @@ builtin_sources += drivers/atmodem/atutil.h \
drivers/speedupmodem/speedupmodem.c \
drivers/speedupmodem/ussd.c
builtin_modules += ubloxmodem
builtin_sources += drivers/atmodem/atutil.h \
drivers/ubloxmodem/ubloxmodem.h \
drivers/ubloxmodem/ubloxmodem.c \
drivers/ubloxmodem/gprs-context.c
if PHONESIM
builtin_modules += phonesim
builtin_sources += plugins/phonesim.c
@@ -527,9 +537,6 @@ builtin_sources += plugins/connman.c
if BLUETOOTH
if BLUEZ4
builtin_modules += bluez4
builtin_sources += plugins/bluez4.c plugins/bluez4.h
builtin_modules += telit
builtin_sources += plugins/telit.c plugins/bluez4.h
@@ -539,11 +546,25 @@ builtin_sources += plugins/sap.c plugins/bluez4.h
builtin_modules += hfp_bluez4
builtin_sources += plugins/hfp_hf_bluez4.c plugins/bluez4.h
builtin_modules += hfp_ag_bluez4
builtin_sources += plugins/hfp_ag_bluez4.c plugins/bluez4.h
builtin_modules += dun_gw_bluez4
builtin_sources += plugins/dun_gw_bluez4.c plugins/bluez4.h
else
builtin_modules += hfp_bluez5
builtin_sources += plugins/hfp_hf_bluez5.c plugins/bluez5.h
builtin_modules += dun_gw_bluez5
builtin_sources += plugins/dun_gw_bluez5.c plugins/bluez5.h
endif
endif
endif
if BLUETOOTH
if BLUEZ4
builtin_modules += bluez4
builtin_sources += plugins/bluez4.c plugins/bluez4.h
builtin_modules += hfp_ag_bluez4
builtin_sources += plugins/hfp_ag_bluez4.c plugins/bluez4.h
builtin_sources += $(btio_sources)
builtin_cflags += @BLUEZ_CFLAGS@
@@ -552,16 +573,19 @@ else
builtin_modules += bluez5
builtin_sources += plugins/bluez5.c plugins/bluez5.h
builtin_modules += hfp_bluez5
builtin_sources += plugins/hfp_hf_bluez5.c plugins/bluez5.h
builtin_modules += hfp_ag_bluez5
builtin_sources += plugins/hfp_ag_bluez5.c plugins/bluez5.h
builtin_modules += dun_gw_bluez5
builtin_sources += plugins/dun_gw_bluez5.c plugins/bluez5.h
if SAILFISHFOS
builtin_modules += sfos_bt
builtin_sources += plugins/sfos_bt.c
endif
endif
if UPOWER
builtin_modules += upower
builtin_sources += plugins/upower.c
endif
endif
if NETTIME
@@ -618,7 +642,7 @@ builtin_cflags += @WSPCODEC_CFLAGS@
builtin_libadd += @WSPCODEC_LIBS@
endif
if LOGCONTROL
if DEBUGLOG
builtin_modules += debuglog
builtin_sources += plugins/debuglog.c
endif
@@ -626,9 +650,12 @@ endif
builtin_modules += sms_history
builtin_sources += plugins/smshistory.c
builtin_modules += allowed_apns
builtin_sources += plugins/allowed-apns.c
sbin_PROGRAMS = src/ofonod
src_ofonod_SOURCES = $(builtin_sources) src/ofono.ver \
src_ofonod_SOURCES = $(builtin_sources) $(gatchat_sources) src/ofono.ver \
src/main.c src/ofono.h src/log.c src/plugin.c \
src/modem.c src/common.h src/common.c \
src/manager.c src/dbus.c src/util.h src/util.c \
@@ -653,8 +680,9 @@ src_ofonod_SOURCES = $(builtin_sources) src/ofono.ver \
src/cdma-sms.c src/private-network.c src/cdma-netreg.c \
src/cdma-provision.c src/handsfree.c \
src/handsfree-audio.c src/bluetooth.h \
src/sim-mnclength.c src/oemraw.c src/voicecallagent.c \
src/hfp.h src/siri.c
src/sim-mnclength.c src/voicecallagent.c \
src/hfp.h src/siri.c \
src/netmon.c
src_ofonod_LDADD = gdbus/libgdbus-internal.la $(builtin_libadd) \
@GLIB_LIBS@ @DBUS_LIBS@ -ldl
@@ -700,7 +728,9 @@ doc_files = doc/overview.txt doc/ofono-paper.txt doc/release-faq.txt \
doc/location-reporting-api.txt \
doc/smshistory-api.txt doc/oemraw-api.txt \
doc/certification.txt doc/siri-api.txt \
doc/telit-modem.txt
doc/telit-modem.txt \
doc/networkmonitor-api.txt \
doc/allowed-apns-api.txt
test_scripts = test/backtrace \
@@ -734,6 +764,7 @@ test_scripts = test/backtrace \
test/receive-sms \
test/remove-contexts \
test/send-sms \
test/cancel-sms \
test/set-mic-volume \
test/set-speaker-volume \
test/test-stk-menu \
@@ -798,7 +829,15 @@ test_scripts = test/backtrace \
test/set-msisdn \
test/test-voicecallagent \
test/get-network-time \
test/set-ddr
test/set-ddr \
test/register-auto \
test/register-operator \
test/set-sms-smsc \
test/set-sms-bearer \
test/get-serving-cell-info \
test/list-allowed-access-points \
test/enable-throttling \
test/disable-throttling
if TEST
testdir = $(pkglibdir)/test
@@ -816,12 +855,20 @@ unit_objects =
unit_tests = unit/test-common unit/test-util unit/test-idmap \
unit/test-simutil unit/test-stkutil \
unit/test-sms unit/test-cdmasms \
unit/test-grilrequest \
unit/test-grilreply \
unit/test-grilunsol \
unit/test-sms unit/test-cdmasms \
unit/test-provision
if RILMODEM
if JOLLA_RILMODEM
unit_tests += unit/test-rilmodem-cs \
unit/test-rilmodem-cs \
unit/test-rilmodem-sms \
unit/test-rilmodem-cb \
unit/test-rilmodem-gprs
endif
endif
noinst_PROGRAMS = $(unit_tests) \
unit/test-sms-root unit/test-mux unit/test-caif
@@ -872,21 +919,6 @@ unit_test_caif_SOURCES = unit/test-caif.c $(gatchat_sources) \
unit_test_caif_LDADD = @GLIB_LIBS@
unit_objects += $(unit_test_caif_OBJECTS)
unit_test_grilrequest_SOURCES = unit/test-grilrequest.c $(gril_sources) \
src/log.c gatchat/ringbuffer.c
unit_test_grilrequest_LDADD = @GLIB_LIBS@ -ldl
unit_objects += $(unit_test_grilrequest_OBJECTS)
unit_test_grilreply_SOURCES = unit/test-grilreply.c $(gril_sources) \
src/log.c gatchat/ringbuffer.c
unit_test_grilreply_LDADD = @GLIB_LIBS@ -ldl
unit_objects += $(unit_test_grilreply_OBJECTS)
unit_test_grilunsol_SOURCES = unit/test-grilunsol.c $(gril_sources) \
src/log.c gatchat/ringbuffer.c
unit_test_grilunsol_LDADD = @GLIB_LIBS@ -ldl
unit_objects += $(unit_test_grilunsol_OBJECTS)
unit_test_provision_SOURCES = unit/test-provision.c \
plugins/provision.h plugins/provision.c \
plugins/mbpi.c src/gprs-provision.c \
@@ -894,6 +926,43 @@ unit_test_provision_SOURCES = unit/test-provision.c \
unit_test_provision_LDADD = @GLIB_LIBS@ -ldl
unit_objects += $(unit_test_provision_OBJECTS)
test_rilmodem_sources = $(gril_sources) src/log.c src/common.c src/util.c \
gatchat/ringbuffer.h gatchat/ringbuffer.c \
unit/rilmodem-test-server.h \
unit/rilmodem-test-server.c \
unit/rilmodem-test-engine.h \
unit/rilmodem-test-engine.c \
src/simutil.c \
drivers/rilmodem/rilutil.c
unit_test_rilmodem_cs_SOURCES = $(test_rilmodem_sources) \
unit/test-rilmodem-cs.c \
drivers/rilmodem/call-settings.c
unit_test_rilmodem_cs_LDADD = gdbus/libgdbus-internal.la $(builtin_libadd) \
@GLIB_LIBS@ @DBUS_LIBS@ -ldl
unit_objects += $(unit_test_rilmodem_cs_OBJECTS)
unit_test_rilmodem_sms_SOURCES = $(test_rilmodem_sources) \
unit/test-rilmodem-sms.c \
drivers/rilmodem/sms.c
unit_test_rilmodem_sms_LDADD = gdbus/libgdbus-internal.la $(builtin_libadd) \
@GLIB_LIBS@ @DBUS_LIBS@ -ldl
unit_objects += $(unit_test_rilmodem_sms_OBJECTS)
unit_test_rilmodem_cb_SOURCES = $(test_rilmodem_sources) \
unit/test-rilmodem-cb.c \
drivers/rilmodem/call-barring.c
unit_test_rilmodem_cb_LDADD = gdbus/libgdbus-internal.la $(builtin_libadd) \
@GLIB_LIBS@ @DBUS_LIBS@ -ldl
unit_objects += $(unit_test_rilmodem_cb_OBJECTS)
unit_test_rilmodem_gprs_SOURCES = $(test_rilmodem_sources) \
unit/test-rilmodem-gprs.c \
drivers/rilmodem/gprs.c
unit_test_rilmodem_gprs_LDADD = gdbus/libgdbus-internal.la $(builtin_libadd) \
@GLIB_LIBS@ @DBUS_LIBS@ -ldl
unit_objects += $(unit_test_rilmodem_gprs_OBJECTS)
TESTS = $(unit_tests)
if TOOLS

View File

@@ -256,6 +256,16 @@ Voicecall
Priority: Medium
Complexity: C1
- DTMF Driver hints
Currently multiple DTMF tones are sent to the driver in batches of up to 8
characters. For those drivers that can only accept a limited set of DTMF
characters at a time (e.g. one), add a setting to the core that will change
this batch size limit.
Priority: Medium
Complexity: C1
Sim Toolkit
===========

View File

@@ -1,5 +1,5 @@
AC_PREREQ(2.60)
AC_INIT(ofono, 1.17)
AC_INIT(ofono, 1.19)
AM_INIT_AUTOMAKE([foreign subdir-objects color-tests])
AC_CONFIG_HEADERS(config.h)
@@ -64,8 +64,8 @@ AC_CHECK_FUNC(signalfd, dummy=yes,
AC_CHECK_LIB(dl, dlopen, dummy=yes,
AC_MSG_ERROR(dynamic linking loader is required))
PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.28, dummy=yes,
AC_MSG_ERROR(GLib >= 2.28 is required))
PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.32, dummy=yes,
AC_MSG_ERROR(GLib >= 2.32 is required))
AC_SUBST(GLIB_CFLAGS)
AC_SUBST(GLIB_LIBS)
@@ -177,10 +177,19 @@ if (test "${enable_jolla_rilmodem}" = "yes"); then
AC_MSG_ERROR(libgrilio >= 1.0.6 is required))
PKG_CHECK_MODULES(GLIBUTIL, libglibutil >= 1.0.5, dummy=yes,
AC_MSG_ERROR(libglibutil >= 1.0.5 is required))
CFLAGS="$CFLAGS $GRILIO_CFLAGS $GLIBUTIL_CFLAGS"
LIBS="$LIBS $GRILIO_LIBS $GLIBUTIL_LIBS"
PKG_CHECK_MODULES(LIBMCE, libmce-glib, dummy=yes,
AC_MSG_ERROR(libmce-glib is required))
CFLAGS="$CFLAGS $GRILIO_CFLAGS $GLIBUTIL_CFLAGS $LIBMCE_CFLAGS"
LIBS="$LIBS $GRILIO_LIBS $GLIBUTIL_LIBS $LIBMCE_LIBS"
fi
AC_ARG_ENABLE(add-remove-context, AC_HELP_STRING([--disable-add-remove-context],
[don't allow to add or remove connection context over D-Bus]), [
if (test "${enableval}" = "no"); then
CFLAGS="$CFLAGS -DDISABLE_ADD_REMOVE_CONTEXT"
fi
])
AC_ARG_ENABLE(qmimodem, AC_HELP_STRING([--disable-qmimodem],
[disable Qualcomm QMI modem support]),
[enable_qmimodem=${enableval}])
@@ -204,6 +213,10 @@ fi
AM_CONDITIONAL(BLUEZ4, test "${enable_bluetooth}" != "no" && test "${enable_bluez4}" = "yes")
AM_CONDITIONAL(BLUETOOTH, test "${enable_bluetooth}" != "no")
AC_ARG_ENABLE(sailfishos, AC_HELP_STRING([--enable-sailfishos],
[enable sailfishos plugin]), [enable_sailfishos=${enableval}])
AM_CONDITIONAL(SAILFISHFOS, test "${enable_sailfishos}" = "yes")
AC_ARG_ENABLE(nettime, AC_HELP_STRING([--disable-nettime],
[disable Nettime plugin]),
[enable_nettime=${enableval}])
@@ -236,6 +249,11 @@ if (test "${enable_provision}" != "no"); then
fi
AM_CONDITIONAL(PROVISION, test "${enable_provision}" != "no")
AC_ARG_ENABLE(upower, AC_HELP_STRING([--disable-upower],
[disable UPower plugin]),
[enable_upower=${enableval}])
AM_CONDITIONAL(UPOWER, test "${enable_power}" != "no")
AC_ARG_ENABLE(datafiles, AC_HELP_STRING([--disable-datafiles],
[do not install configuration and data files]),
[enable_datafiles=${enableval}])
@@ -252,10 +270,16 @@ if (test "${enable_pushforwarder}" != "no"); then
AC_SUBST(WSPCODEC_LIBS)
fi
AC_ARG_ENABLE(logcontrol,
AC_HELP_STRING([--enable-logcontrol], [enable log control plugin]),
[enable_logcontrol=${enableval}], [enable_logcontrol="no"])
AM_CONDITIONAL(LOGCONTROL, test "${enable_logcontrol}" != "no")
AC_ARG_ENABLE(debuglog,
AC_HELP_STRING([--enable-debuglog], [enable log control plugin]),
[enable_debuglog=${enableval}], [enable_debuglog="no"])
AM_CONDITIONAL(DEBUGLOG, test "${enable_debuglog}" != "no")
if (test "${enable_debuglog}" = "yes"); then
PKG_CHECK_MODULES(DBUSLOG, libdbuslogserver-dbus, dummy=yes,
AC_MSG_ERROR(libdbuslogserver-dbus is required))
CFLAGS="$CFLAGS $DBUSLOG_CFLAGS"
LIBS="$LIBS $DBUSLOG_LIBS"
fi
if (test "${prefix}" = "NONE"); then
dnl no prefix and no localstatedir, so default to /var

View File

@@ -0,0 +1,17 @@
Allowed APNs hierarchy
=========================
Service org.ofono
Interface org.ofono.AllowedAccessPoints
Object path [variable prefix]/{modem0,modem1,...}
Methods array{string} GetAllowedAccessPoints()
Get the list of allowed access points provided
in the SIM card.
This method returns an array of strings which
contains a list of Access Point Names supported
by network provider. Returns with an error if
SIM reading failed or an empty list if there
are no access points listed on the SIM.

View File

@@ -106,7 +106,7 @@ Properties boolean Attached [readonly]
GPRS service registration (if known).
Possible values are:
"none", "gsm", "edge", "umts", "hsdpa", "hsupa",
"none", "gprs", "edge", "umts", "hsdpa", "hsupa",
"hspa" (HSDPA and HSUPA at the same time) and
"lte"

View File

@@ -1,28 +0,0 @@
Debug log control
=================
Service org.ofono
Interface org.ofono.DebugLog
Object path /
Methods void Enable(string pattern)
Enables all logs that match the pattern.
void Disable(string pattern)
Disables all logs that match the pattern.
array(string,boolean) List()
Returns all available log names and their current
states.
In order for Enable or Disable call to have any
effect, the pattern must match one or more of
these strings.
Signals Changed(string name, boolean enabled)
This signal indicates a changed log status of the
given log module.

View File

@@ -89,6 +89,10 @@ Properties string RemoteAddress [readonly]
Bluetooth address of the local adapter.
string Type [readonly]
Type of the card. Valid values are "gateway" or
"handsfree".
Handsfree Audio Agent hierarchy [experimental]
===============================

View File

@@ -90,6 +90,11 @@ Properties boolean Powered [readwrite]
"hfp") this corresponds to the Bluetooth Device
Address of the remote device.
string SoftwareVersionNumber [readonly, optional]
String representing the software version number of the
modem device.
array{string} Features [readonly]
List of currently enabled features. It uses simple

View File

@@ -0,0 +1,83 @@
Network Monitor hierarchy
=========================
Service org.ofono
Interface org.ofono.NetworkMonitor
Object path [variable prefix]/{modem0,modem1,...}
Methods a{sv} GetServingCellInformation()
Requests the latest serving cell information and basic
measurements from oFono. The returned value is a
dictionary with the possible key / values documented
below. The type of cell is given by the 'Technology'
property.
Based on the type of cell, the dictionary will contain
additional key/value pairs. If a given key/value pair
is not present, then it is not known or unsupported
by the underlying driver.
Refer to the sections below for which property types
are available, their valid value ranges and
applicability to different cell types.
Network Monitor Property Types
==============================
string Technology
Contains the cell type. Possible values are:
"gsm", "umts", "lte"
uint16 LocationAreaCode [optional, gsm, umts]
Contains the current location area code. Valid range of values is
0-65535.
uint32 CellId [optional, gsm, umts]
Contains the current network cell id. Valid range of values is
0-65535 for gsm and 0-268435455 in umts.
string MobileNetworkCode [optional, gsm, umts]
Contains the MNC of the cell.
string MobileCountryCode [optional, gsm, umts]
Contains the MCC of the cell.
uint16 ARFCN [optional, gsm]
Contains the Absolute Radio Frequency Channel Number. Valid range of
values is 0-1023.
byte ReceivedSignalStrength [optional, gsm]
Contains the received signal strength level in dBm. Refer to <rxlev>
in 27.007, Section 8.69 for more details. Valid range of values is
0-63.
byte BSIC [optional, gsm]
Contains the Base Station Identity Code. Valid range of values is 0-63.
byte BitErrorRate [optional, gsm]
Contains the bit error rate. Refer to <ber> in 27.007, Section 8.69
for more details. Valid range of values is 0-7.
uint16 PrimaryScramblingCode [optional, umts]
Contains the scrambling code. Valid range of values is 0-512.
byte TimingAdvance [optional, gsm]
Contains the Timing Advance. Valid range of values is 0-219.
byte Strength [optional, gsm, umts]
Contains the signal strength. Valid values are 0-31. Refer to <rssi>
in 27.007, Section 8.5.

View File

@@ -49,6 +49,7 @@ static const char *none_prefix[] = { NULL };
struct gprs_data {
GAtChat *chat;
unsigned int vendor;
unsigned int last_auto_context_id;
};
static void at_cgatt_cb(gboolean ok, GAtResult *result, gpointer user_data)
@@ -141,6 +142,48 @@ static void at_gprs_registration_status(struct ofono_gprs *gprs,
CALLBACK_WITH_FAILURE(cb, -1, data);
}
static void at_cgdcont_read_cb(gboolean ok, GAtResult *result,
gpointer user_data)
{
struct ofono_gprs *gprs = user_data;
struct gprs_data *gd = ofono_gprs_get_data(gprs);
int activated_cid = gd->last_auto_context_id;
const char *apn = NULL;
GAtResultIter iter;
DBG("ok %d", ok);
if (!ok) {
ofono_warn("Can't read CGDCONT contexts.");
return;
}
g_at_result_iter_init(&iter, result);
while (g_at_result_iter_next(&iter, "+CGDCONT:")) {
int read_cid;
if (!g_at_result_iter_next_number(&iter, &read_cid))
break;
if (read_cid != activated_cid)
continue;
/* ignore protocol */
g_at_result_iter_skip_next(&iter);
g_at_result_iter_next_string(&iter, &apn);
break;
}
if (apn)
ofono_gprs_cid_activated(gprs, activated_cid, apn);
else
ofono_warn("cid %u: Received activated but no apn present",
activated_cid);
}
static void cgreg_notify(GAtResult *result, gpointer user_data)
{
struct ofono_gprs *gprs = user_data;
@@ -157,6 +200,7 @@ static void cgreg_notify(GAtResult *result, gpointer user_data)
static void cgev_notify(GAtResult *result, gpointer user_data)
{
struct ofono_gprs *gprs = user_data;
struct gprs_data *gd = ofono_gprs_get_data(gprs);
GAtResultIter iter;
const char *event;
@@ -172,6 +216,11 @@ static void cgev_notify(GAtResult *result, gpointer user_data)
g_str_equal(event, "ME DETACH")) {
ofono_gprs_detached_notify(gprs);
return;
} else if (g_str_has_prefix(event, "ME PDN ACT")) {
sscanf(event, "%*s %*s %*s %u", &gd->last_auto_context_id);
g_at_chat_send(gd->chat, "AT+CGDCONT?", cgdcont_prefix,
at_cgdcont_read_cb, gprs, NULL);
}
}
@@ -303,10 +352,6 @@ static void ublox_ureg_notify(GAtResult *result, gpointer user_data)
case 5:
bearer = 4;
break;
case 7:
/* XXX: reserved - assume none. */
bearer = 0;
break;
case 8:
bearer = 1;
break;
@@ -355,6 +400,7 @@ static void gprs_initialized(gboolean ok, GAtResult *result, gpointer user_data)
FALSE, gprs, NULL);
break;
case OFONO_VENDOR_UBLOX:
case OFONO_VENDOR_UBLOX_TOBY_L2:
g_at_chat_register(gd->chat, "+UREG:", ublox_ureg_notify,
FALSE, gprs, NULL);
g_at_chat_send(gd->chat, "AT+UREG=1", none_prefix,

View File

@@ -1580,17 +1580,28 @@ static inline ofono_bool_t append_cmer_element(char *buf, int *len, int cap,
static ofono_bool_t build_cmer_string(char *buf, int *cmer_opts,
struct netreg_data *nd)
{
const char *mode;
const char *ind;
int len = sprintf(buf, "AT+CMER=");
const char *mode;
DBG("");
switch (nd->vendor) {
case OFONO_VENDOR_UBLOX_TOBY_L2:
/* UBX-13002752 R33: TOBY L2 doesn't support mode 2 and 3 */
mode = "1";
break;
default:
mode = "3";
break;
}
/*
* Forward unsolicited result codes directly to the TE;
* TATE link specific inband technique used to embed result codes and
* data when TA is in online data mode
*/
if (!append_cmer_element(buf, &len, cmer_opts[0], "3", FALSE))
if (!append_cmer_element(buf, &len, cmer_opts[0], mode, FALSE))
return FALSE;
/* No keypad event reporting */
@@ -1607,14 +1618,14 @@ static ofono_bool_t build_cmer_string(char *buf, int *cmer_opts,
* Telit does not support mode 1.
* All indicator events shall be directed from TA to TE.
*/
mode = "2";
ind = "2";
break;
default:
/*
* Only those indicator events, which are not caused by +CIND
* shall be indicated by the TA to the TE.
*/
mode = "1";
ind = "1";
break;
}
@@ -1623,7 +1634,7 @@ static ofono_bool_t build_cmer_string(char *buf, int *cmer_opts,
* <ind> indicates the indicator order number (as specified for +CIND)
* and <value> is the new value of indicator.
*/
if (!append_cmer_element(buf, &len, cmer_opts[3], mode, TRUE))
if (!append_cmer_element(buf, &len, cmer_opts[3], ind, TRUE))
return FALSE;
return TRUE;

View File

@@ -1120,6 +1120,7 @@ static void at_pin_retries_query(struct ofono_sim *sim,
return;
break;
case OFONO_VENDOR_UBLOX:
case OFONO_VENDOR_UBLOX_TOBY_L2:
if (g_at_chat_send(sd->chat, "AT+UPINCNT", upincnt_prefix,
upincnt_cb, cbd, g_free) > 0)
return;
@@ -1516,7 +1517,7 @@ static void at_lock_status_cb(gboolean ok, GAtResult *result,
{
struct cb_data *cbd = user_data;
GAtResultIter iter;
ofono_sim_locked_cb_t cb = cbd->cb;
ofono_query_facility_lock_cb_t cb = cbd->cb;
struct ofono_error error;
int locked;
@@ -1541,9 +1542,9 @@ static void at_lock_status_cb(gboolean ok, GAtResult *result,
cb(&error, locked, cbd->data);
}
static void at_pin_query_enabled(struct ofono_sim *sim,
static void at_query_clck(struct ofono_sim *sim,
enum ofono_sim_password_type passwd_type,
ofono_sim_locked_cb_t cb, void *data)
ofono_query_facility_lock_cb_t cb, void *data)
{
struct sim_data *sd = ofono_sim_get_data(sim);
struct cb_data *cbd = cb_data_new(cb, data);
@@ -1626,7 +1627,7 @@ static struct ofono_sim_driver driver = {
.reset_passwd = at_pin_send_puk,
.lock = at_pin_enable,
.change_passwd = at_change_passwd,
.query_locked = at_pin_query_enabled,
.query_facility_lock = at_query_clck,
};
static struct ofono_sim_driver driver_noef = {
@@ -1640,7 +1641,7 @@ static struct ofono_sim_driver driver_noef = {
.reset_passwd = at_pin_send_puk,
.lock = at_pin_enable,
.change_passwd = at_change_passwd,
.query_locked = at_pin_query_enabled,
.query_facility_lock = at_query_clck,
};
void at_sim_init(void)

View File

@@ -45,5 +45,6 @@ enum ofono_vendor {
OFONO_VENDOR_ALCATEL,
OFONO_VENDOR_QUECTEL,
OFONO_VENDOR_UBLOX,
OFONO_VENDOR_UBLOX_TOBY_L2,
OFONO_VENDOR_CINTERION,
};

View File

@@ -253,8 +253,7 @@ static void clcc_poll_cb(gboolean ok, GAtResult *result, gpointer user_data)
}
}
g_slist_foreach(vd->calls, (GFunc) g_free, NULL);
g_slist_free(vd->calls);
g_slist_free_full(vd->calls, g_free);
vd->calls = calls;
@@ -1147,8 +1146,7 @@ static void at_voicecall_remove(struct ofono_voicecall *vc)
if (vd->vts_source)
g_source_remove(vd->vts_source);
g_slist_foreach(vd->calls, (GFunc) g_free, NULL);
g_slist_free(vd->calls);
g_slist_free_full(vd->calls, g_free);
ofono_voicecall_set_data(vc, NULL);

View File

@@ -286,8 +286,7 @@ static void clcc_poll_cb(gboolean ok, GAtResult *result, gpointer user_data)
ofono_voicecall_mpty_hint(vc, mpty_ids);
g_slist_foreach(vd->calls, (GFunc) g_free, NULL);
g_slist_free(vd->calls);
g_slist_free_full(vd->calls, g_free);
vd->calls = calls;
@@ -709,6 +708,15 @@ static void ccwa_notify(GAtResult *result, gpointer user_data)
int num_type, validity;
struct ofono_call *call;
/* Waiting call notification makes no sense, when there are
* no calls at all. This can happen when a phone already has
* waiting and active calls and is being connected over HFP
* but it first sends +CCWA before we manage to synchronize
* calls with AT+CLCC.
*/
if (!vd->calls)
return;
/* CCWA can repeat, ignore if we already have an waiting call */
if (g_slist_find_custom(vd->calls,
GINT_TO_POINTER(CALL_STATUS_WAITING),
@@ -1110,6 +1118,17 @@ static void ciev_callheld_notify(struct ofono_voicecall *vc,
*/
vd->clcc_source = g_timeout_add(POLL_CLCC_DELAY,
poll_clcc, vc);
} else {
if (vd->clcc_source)
g_source_remove(vd->clcc_source);
/*
* We got a notification that there is a held call
* and no active call but we already are in such state.
* Let's schedule a poll to see what happened.
*/
vd->clcc_source = g_timeout_add(POLL_CLCC_DELAY,
poll_clcc, vc);
}
}
@@ -1236,8 +1255,7 @@ static void hfp_voicecall_remove(struct ofono_voicecall *vc)
if (vd->expect_release_source)
g_source_remove(vd->expect_release_source);
g_slist_foreach(vd->calls, (GFunc) g_free, NULL);
g_slist_free(vd->calls);
g_slist_free_full(vd->calls, g_free);
ofono_voicecall_set_data(vc, NULL);

View File

@@ -80,7 +80,7 @@ static gboolean get_next_addr(GAtResultIter *iter, char **addr)
if (g_at_result_iter_next_unquoted_string(iter, &str) == FALSE)
return FALSE;
val = strtol(str, NULL, 16);
val = strtoul(str, NULL, 16);
if (addr)
*addr = g_strdup_printf("%u.%u.%u.%u",

View File

@@ -1009,8 +1009,7 @@ static void ifx_voicecall_remove(struct ofono_voicecall *vc)
{
struct voicecall_data *vd = ofono_voicecall_get_data(vc);
g_slist_foreach(vd->calls, (GFunc) g_free, NULL);
g_slist_free(vd->calls);
g_slist_free_full(vd->calls, g_free);
g_strfreev(vd->en_list);

View File

@@ -0,0 +1,77 @@
/*
*
* RIL constants for infineon modem
*
* Copyright (C) 2014 Canonical Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef INFINEON_CONSTANTS_H
#define INFINEON_CONSTANTS_H
/* Messages encapsulated in RIL_REQUEST_OEM_HOOK_RAW requests */
#define INF_RIL_REQUEST_OEM_QUERY_SELECT_BAND 1
#define INF_RIL_REQUEST_OEM_SET_SELECT_BAND 2
#define INF_RIL_REQUEST_OEM_SET_CIRCUIT_SWITCHING_PAGING 3
#define INF_RIL_REQUEST_OEM_GET_LAST_FAILURE_REPORT_FOR_CS_REGISTRATION 4
#define INF_RIL_REQUEST_OEM_GET_SELECT_BEARER_SERVICE_TYPE 5
#define INF_RIL_REQUEST_OEM_GET_XPROGRESS_STATUS 6
#define INF_RIL_REQUEST_OEM_SET_SS_NOTIFY 7
#define INF_RIL_REQUEST_OEM_GET_SS_NOTIFY 8
#define INF_RIL_REQUEST_OEM_SET_AUTHENTICATION_TYPE 9
#define INF_RIL_REQUEST_OEM_SWITCH_OFF_MS 10
#define INF_RIL_REQUEST_OEM_SET_AUTO_TIMEZONE_UPDATE 11
#define INF_RIL_REQUEST_OEM_SET_TIMEZONE_RESPORTING 12
#define INF_RIL_REQUEST_OEM_SET_DISPLAY_SIM_AND_PB_STATUS 13
#define INF_RIL_REQUEST_OEM_GET_REMAIN_SIM_PIN_ATTEMPTS 14
#define INF_RIL_REQUEST_OEM_SET_AUTO_REDIAL 15
#define INF_RIL_REQUEST_OEM_QUERY_CALL_STATUS_REPORTING 16
#define INF_RIL_REQUEST_OEM_SET_AUTO_ANSWER 17
#define INF_RIL_REQUEST_OEM_SET_LINE 18
#define INF_RIL_REQUEST_OEM_PDP_ACTIVATE_OR_DEACTIVATE 19
#define INF_RIL_REQUEST_OEM_QUERY_GPRS_MS_CLASS 20
#define INF_RIL_REQUEST_OEM_SET_TRACE_AND_AT_INTERFACES 21
#define INF_RIL_REQUEST_OEM_QUERY_TRACE_AND_AT_INTERFACES_CONFIGURE 22
#define INF_RIL_REQUEST_OEM_SWITCH_TRACE_ON_OR_OFF 23
#define INF_RIL_REQUEST_OEM_READ_EXCEPTION_LOG 24
#define INF_RIL_REQUEST_OEM_GET_PHONE_ACTIVITY_STATUS 25
#define INF_RIL_REQUEST_OEM_INITIATE_RESEND_SMS_IF_GPRS_FAILS 26
#define INF_RIL_REQUEST_OEM_GET_DEVICE_NUMBER 27
#define INF_RIL_REQUEST_OEM_ENABLE_STK 28
#define INF_RIL_REQUEST_OEM_GET_SUBSCRIBER_NUMBER 29
#define INF_RIL_REQUEST_OEM_SELECT_PHONE_BOOK 30
#define INF_RIL_REQUEST_OEM_READ_PHONE_BOOK 31
#define INF_RIL_REQUEST_OEM_INSERT_RECORD_TO_PHONE_BOOK 32
#define INF_RIL_REQUEST_OEM_DELECT_RECORD_IN_PHONE_BOOK 33
#define INF_RIL_REQUEST_OEM_GET_RECORD_FIELDS_MAX_LEN 34
#define INF_RIL_REQUEST_OEM_SET_SERIAL_PORT 35
#define INF_RIL_REQUEST_OEM_SET_DATA_PREFERED 36
#define INF_RIL_REQUEST_OEM_SET_MODEM_ROUTING 37
#define INF_RIL_REQUEST_OEM_CLEAR_MISS_NUMBER 38
#define INF_RIL_REQUEST_OEM_ATH 39
#define INF_RIL_REQUEST_OEM_NOSIG_MODE_TEST 40
#define INF_RIL_REQUEST_OEM_SELECT_3G_BAND 41
#define INF_RIL_REQUEST_OEM_QUERY_3G_BAND 42
#define INF_RIL_REQUEST_OEM_HW_RESET_MODEM 43
#define INF_RIL_REQUEST_OEM_QUERY_DIRECT 44
#define INF_RIL_REQUEST_OEM_USER_PLMN_QUERY 45
#define INF_RIL_REQUEST_OEM_USER_PLMN_SET 46
#define INF_RIL_REQUEST_OEM_USER_PLMN_DELTE 47
#define INF_RIL_REQUEST_OEM_SET_USB_LOG 48
#define INF_RIL_REQUEST_OEM_UPDATE_CSQ 49
#define INF_RIL_REQUEST_OEM_DUMP_CELL_ENV 50
#endif /* INFINEON_CONSTANTS_H */

View File

@@ -652,7 +652,7 @@ static void sec_code_state_resp_cb(const GIsiMessage *msg, void *opaque)
static void isi_query_locked(struct ofono_sim *sim,
enum ofono_sim_password_type passwd_type,
ofono_sim_locked_cb_t cb, void *data)
ofono_query_facility_lock_cb_t cb, void *data)
{
struct sim_data *sd = ofono_sim_get_data(sim);
struct isi_cb_data *cbd = isi_cb_data_new(sim, cb, data);
@@ -963,7 +963,7 @@ static struct ofono_sim_driver driver = {
.reset_passwd = isi_reset_passwd,
.lock = isi_lock,
.change_passwd = isi_change_passwd,
.query_locked = isi_query_locked,
.query_facility_lock = isi_query_locked,
};
void isi_sim_init(void)

View File

@@ -1032,14 +1032,6 @@ static void uicc_lock(struct ofono_sim *sim, enum ofono_sim_password_type type,
CALLBACK_WITH_FAILURE(cb, data);
}
static void uicc_query_locked(struct ofono_sim *sim,
enum ofono_sim_password_type type,
ofono_sim_locked_cb_t cb, void *data)
{
DBG("Not implemented");
CALLBACK_WITH_FAILURE(cb, -1, data);
}
static gboolean decode_fcp_pin_status(const GIsiSubBlockIter *iter, uint8_t read,
uint8_t *pin1, uint8_t *pin2)
{
@@ -1677,7 +1669,6 @@ static struct ofono_sim_driver driver = {
.reset_passwd = uicc_reset_passwd,
.change_passwd = uicc_change_passwd,
.lock = uicc_lock,
.query_locked = uicc_query_locked,
};
void isi_uicc_init(void)

View File

@@ -1715,7 +1715,7 @@ static void isi_release_specific(struct ofono_voicecall *ovc, int id,
if ((status->mode_info & CALL_MODE_ORIGINATOR))
cause = CALL_CAUSE_BUSY_USER_REQUEST;
break;
break;
}
isi_call_release_req(ovc, id, CALL_CAUSE_TYPE_CLIENT, cause, cb, data);

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015 Jolla Ltd.
* Copyright (C) 2015-2016 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -25,14 +25,16 @@ struct ril_call_forward {
guint timer_id;
};
enum ril_call_forward_cmd {
enum ril_call_forward_action {
CF_ACTION_DISABLE,
CF_ACTION_ENABLE,
CF_ACTION_UNUSED,
CF_ACTION_INTERROGATE,
CF_ACTION_REGISTRATION,
CF_ACTION_ERASURE
};
#define CF_TIME_DEFAULT (0)
struct ril_call_forward_cbd {
struct ril_call_forward *fd;
union _ofono_call_forward_cb {
@@ -43,35 +45,57 @@ struct ril_call_forward_cbd {
gpointer data;
};
#define ril_call_forward_cbd_free g_free
static inline struct ril_call_forward *ril_call_forward_get_data(
struct ofono_call_forwarding *cf)
{
return ofono_call_forwarding_get_data(cf);
}
static void ril_call_forward_cbd_free(gpointer cbd)
{
g_slice_free(struct ril_call_forward_cbd, cbd);
}
static struct ril_call_forward_cbd *ril_call_forward_cbd_new(void *cb,
void *data)
{
struct ril_call_forward_cbd *cbd;
cbd = g_new0(struct ril_call_forward_cbd, 1);
cbd = g_slice_new0(struct ril_call_forward_cbd);
cbd->cb.ptr = cb;
cbd->data = data;
return cbd;
}
static inline void ril_call_forward_submit_request(struct ril_call_forward *fd,
GRilIoRequest* req, guint code, GRilIoChannelResponseFunc response,
void *cb, void *data)
static GRilIoRequest *ril_call_forward_req(enum ril_call_forward_action action,
int type, int cls, const struct ofono_phone_number *number, int time)
{
grilio_queue_send_request_full(fd->q, req, code, response,
ril_call_forward_cbd_free,
ril_call_forward_cbd_new(cb, data));
GRilIoRequest *req = grilio_request_new();
/*
* Modem seems to respond with error to all requests
* made with bearer class BEARER_CLASS_DEFAULT.
*/
if (cls == BEARER_CLASS_DEFAULT) {
cls = SERVICE_CLASS_NONE;
}
grilio_request_append_int32(req, action);
grilio_request_append_int32(req, type);
grilio_request_append_int32(req, cls); /* Service class */
if (number) {
grilio_request_append_int32(req, number->type);
grilio_request_append_utf8(req, number->number);
} else {
grilio_request_append_int32(req, 0x81); /* TOA unknown */
grilio_request_append_utf8(req, NULL); /* No number */
}
grilio_request_append_int32(req, time);
return req;
}
static void ril_forward_set_cb(GRilIoChannel *io, int status,
static void ril_call_forward_set_cb(GRilIoChannel *io, int status,
const void *data, guint len, void *user_data)
{
struct ofono_error error;
@@ -86,93 +110,51 @@ static void ril_forward_set_cb(GRilIoChannel *io, int status,
}
}
static void ril_call_forward_set(struct ofono_call_forwarding *cf,
enum ril_call_forward_action cmd, int type, int cls,
const struct ofono_phone_number *number, int time,
ofono_call_forwarding_set_cb_t cb, void *data)
{
struct ril_call_forward *fd = ril_call_forward_get_data(cf);
GRilIoRequest *req = ril_call_forward_req(cmd, type, cls, number, time);
grilio_queue_send_request_full(fd->q, req, RIL_REQUEST_SET_CALL_FORWARD,
ril_call_forward_set_cb, ril_call_forward_cbd_free,
ril_call_forward_cbd_new(cb, data));
grilio_request_unref(req);
}
static void ril_call_forward_registration(struct ofono_call_forwarding *cf,
int type, int cls, const struct ofono_phone_number *number,
int time, ofono_call_forwarding_set_cb_t cb, void *data)
{
struct ril_call_forward *fd = ril_call_forward_get_data(cf);
GRilIoRequest *req = grilio_request_new();
ofono_info("cf registration");
grilio_request_append_int32(req, CF_ACTION_REGISTRATION);
grilio_request_append_int32(req, type);
/*
* Modem seems to respond with error to all queries
* or settings made with bearer class
* BEARER_CLASS_DEFAULT. Design decision: If given
* class is BEARER_CLASS_DEFAULT let's map it to
* BEARER_CLASS_VOICE as per RIL design.
*/
if (cls == BEARER_CLASS_DEFAULT) {
cls = BEARER_CLASS_VOICE;
}
grilio_request_append_int32(req, cls);
grilio_request_append_int32(req, number->type);
grilio_request_append_utf8(req, number->number);
grilio_request_append_int32(req, time);
ril_call_forward_submit_request(fd, req, RIL_REQUEST_SET_CALL_FORWARD,
ril_forward_set_cb, cb, data);
grilio_request_unref(req);
}
static void ril_call_forward_send_cmd(struct ofono_call_forwarding *cf,
int type, int cls, ofono_call_forwarding_set_cb_t cb,
void *data, int action)
{
struct ril_call_forward *fd = ril_call_forward_get_data(cf);
GRilIoRequest *req = grilio_request_new();
grilio_request_append_int32(req, action);
grilio_request_append_int32(req, type);
/*
* Modem seems to respond with error to all queries
* or settings made with bearer class
* BEARER_CLASS_DEFAULT. Design decision: If given
* class is BEARER_CLASS_DEFAULT let's map it to
* BEARER_CLASS_VOICE as per RIL design.
*/
if (cls == BEARER_CLASS_DEFAULT) {
cls = BEARER_CLASS_VOICE;
}
grilio_request_append_int32(req, cls); /* Service class */
/* Following 3 values have no real meaning in erasure
* but apparently RIL expects them so fields need to
* be filled. Otherwise there is no response
*/
grilio_request_append_int32(req, 0x81); /* TOA unknown */
grilio_request_append_utf8(req, "1234567890");
grilio_request_append_int32(req, 60);
ril_call_forward_submit_request(fd, req, RIL_REQUEST_SET_CALL_FORWARD,
ril_forward_set_cb, cb, data);
grilio_request_unref(req);
ril_call_forward_set(cf, CF_ACTION_REGISTRATION, type, cls,
number, time, cb, data);
}
static void ril_call_forward_erasure(struct ofono_call_forwarding *cf,
int type, int cls, ofono_call_forwarding_set_cb_t cb, void *data)
{
ofono_info("CF_ACTION_ERASURE");
ril_call_forward_send_cmd(cf, type, cls, cb, data, CF_ACTION_ERASURE);
ofono_info("cf erasure");
ril_call_forward_set(cf, CF_ACTION_ERASURE, type, cls,
NULL, CF_TIME_DEFAULT, cb, data);
}
static void ril_call_forward_deactivate(struct ofono_call_forwarding *cf,
int type, int cls, ofono_call_forwarding_set_cb_t cb, void *data)
{
ofono_info("CF_ACTION_DISABLE");
ril_call_forward_send_cmd(cf, type, cls, cb, data, CF_ACTION_DISABLE);
ofono_info("cf disable");
ril_call_forward_set(cf, CF_ACTION_DISABLE, type, cls,
NULL, CF_TIME_DEFAULT, cb, data);
}
static void ril_call_forward_activate(struct ofono_call_forwarding *cf,
int type, int cls, ofono_call_forwarding_set_cb_t cb, void *data)
{
ofono_info("CF_ACTION_ENABLE");
ril_call_forward_send_cmd(cf, type, cls, cb, data, CF_ACTION_ENABLE);
ofono_info("cf enable");
ril_call_forward_set(cf, CF_ACTION_ENABLE, type, cls,
NULL, CF_TIME_DEFAULT, cb, data);
}
static void ril_call_forward_query_cb(GRilIoChannel *io, int status,
@@ -223,36 +205,14 @@ static void ril_call_forward_query(struct ofono_call_forwarding *cf, int type,
int cls, ofono_call_forwarding_query_cb_t cb, void *data)
{
struct ril_call_forward *fd = ril_call_forward_get_data(cf);
GRilIoRequest *req = grilio_request_new();
GRilIoRequest *req = ril_call_forward_req(CF_ACTION_INTERROGATE,
type, cls, NULL, CF_TIME_DEFAULT);
ofono_info("cf query");
grilio_request_append_int32(req, 2);
grilio_request_append_int32(req, type);
/*
* Modem seems to respond with error to all queries
* or settings made with bearer class
* BEARER_CLASS_DEFAULT. Design decision: If given
* class is BEARER_CLASS_DEFAULT let's map it to
* SERVICE_CLASS_NONE as per RIL design.
*/
if (cls == BEARER_CLASS_DEFAULT) {
cls = SERVICE_CLASS_NONE;
}
grilio_request_append_int32(req, cls);
/* Following 3 values have no real meaning in query
* but apparently RIL expects them so fields need to
* be filled. Otherwise there is no response
*/
grilio_request_append_int32(req, 0x81); /* TOA unknown */
grilio_request_append_utf8(req, "1234567890");
grilio_request_append_int32(req, 0);
ril_call_forward_submit_request(fd, req,
RIL_REQUEST_QUERY_CALL_FORWARD_STATUS,
ril_call_forward_query_cb, cb, data);
grilio_queue_send_request_full(fd->q, req,
RIL_REQUEST_QUERY_CALL_FORWARD_STATUS,
ril_call_forward_query_cb, ril_call_forward_cbd_free,
ril_call_forward_cbd_new(cb, data));
grilio_request_unref(req);
}
@@ -286,7 +246,7 @@ static void ril_call_forward_remove(struct ofono_call_forwarding *cf)
DBG("");
ofono_call_forwarding_set_data(cf, NULL);
if (fd->timer_id > 0) {
if (fd->timer_id) {
g_source_remove(fd->timer_id);
}

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015 Jolla Ltd.
* Copyright (C) 2015-2017 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -16,60 +16,155 @@
#include "ril_plugin.h"
#include "ril_util.h"
#include "ril_log.h"
#include "ril_constants.h"
#include <gutil_strv.h>
struct ril_cbs {
struct ofono_cbs *cbs;
GRilIoChannel *io;
guint timer_id;
GRilIoQueue *q;
char *log_prefix;
gulong event_id;
};
static void ril_set_topics(struct ofono_cbs *cbs, const char *topics,
ofono_cbs_set_cb_t cb, void *data)
struct ril_cbs_cbd {
struct ril_cbs *cd;
ofono_cbs_set_cb_t cb;
gpointer data;
};
#define RIL_CBS_CHECK_RETRY_MS 1000
#define RIL_CBS_CHECK_RETRY_COUNT 30
#define DBG_(cd,fmt,args...) DBG("%s" fmt, (cd)->log_prefix, ##args)
#define ril_cbs_cbd_free g_free
static struct ril_cbs_cbd *ril_cbs_cbd_new(struct ril_cbs *cd,
ofono_cbs_set_cb_t cb, void *data)
{
struct ofono_error error;
cb(ril_error_ok(&error), data);
struct ril_cbs_cbd *cbd = g_new(struct ril_cbs_cbd, 1);
cbd->cd = cd;
cbd->cb = cb;
cbd->data = data;
return cbd;
}
static void ril_clear_topics(struct ofono_cbs *cbs,
static void ril_cbs_request_activation(struct ril_cbs *cd,
gboolean activate, GRilIoChannelResponseFunc response,
GDestroyNotify destroy, void* user_data)
{
GRilIoRequest* req = grilio_request_sized_new(8);
grilio_request_append_int32(req, 1);
grilio_request_append_int32(req, activate ? 0 :1);
DBG_(cd, "%sactivating CB", activate ? "" : "de");
grilio_queue_send_request_full(cd->q, req,
RIL_REQUEST_GSM_SMS_BROADCAST_ACTIVATION,
response, destroy, user_data);
grilio_request_unref(req);
}
static void ril_cbs_set_config(struct ril_cbs *cd, const char *topics,
GRilIoChannelResponseFunc response,
GDestroyNotify destroy, void* user_data)
{
char **list = topics ? g_strsplit(topics, ",", 0) : NULL;
int i, n = gutil_strv_length(list);
GRilIoRequest* req = grilio_request_new();
grilio_request_append_int32(req, n);
for (i = 0; i < n; i++) {
const char *entry = list[i];
const char *delim = strchr(entry, '-');
int from, to;
if (delim) {
char **range = g_strsplit(topics, "-", 0);
from = atoi(range[0]);
to = atoi(range[1]);
g_strfreev(range);
} else {
from = to = atoi(entry);
}
grilio_request_append_int32(req, from);
grilio_request_append_int32(req, to);
grilio_request_append_int32(req, 0);
grilio_request_append_int32(req, 0xff);
grilio_request_append_int32(req, 1);
}
DBG_(cd, "configuring CB");
grilio_queue_send_request_full(cd->q, req,
RIL_REQUEST_GSM_SET_BROADCAST_SMS_CONFIG,
response, destroy, user_data);
grilio_request_unref(req);
g_strfreev(list);
}
static void ril_cbs_cb(GRilIoChannel *io, int ril_status,
const void *data, guint len, void *user_data)
{
struct ril_cbs_cbd *cbd = user_data;
if (cbd->cb) {
struct ofono_error error;
if (ril_status == RIL_E_SUCCESS) {
cbd->cb(ril_error_ok(&error), cbd->data);
} else {
cbd->cb(ril_error_failure(&error), cbd->data);
}
}
}
static void ril_cbs_set_topics(struct ofono_cbs *cbs, const char *topics,
ofono_cbs_set_cb_t cb, void *data)
{
struct ofono_error error;
cb(ril_error_ok(&error), data);
struct ril_cbs *cd = ofono_cbs_get_data(cbs);
DBG_(cd, "%s", topics);
ril_cbs_set_config(cd, topics, ril_cbs_cb, ril_cbs_cbd_free,
ril_cbs_cbd_new(cd, cb, data));
}
static void ril_cbs_clear_topics(struct ofono_cbs *cbs,
ofono_cbs_set_cb_t cb, void *data)
{
struct ril_cbs *cd = ofono_cbs_get_data(cbs);
DBG_(cd, "");
ril_cbs_request_activation(cd, FALSE, ril_cbs_cb, ril_cbs_cbd_free,
ril_cbs_cbd_new(cd, cb, data));
}
static void ril_cbs_notify(GRilIoChannel *io, guint code,
const void *data, guint len, void *user_data)
{
struct ril_cbs *cd = user_data;
GRilIoParser rilp;
char* pdu;
GASSERT(code == RIL_UNSOL_ON_USSD);
grilio_parser_init(&rilp, data, len);
pdu = grilio_parser_get_utf8(&rilp);
DBG("%s", pdu);
if (pdu) {
ofono_cbs_notify(cd->cbs, (const guchar *)pdu, strlen(pdu));
g_free(pdu);
}
GASSERT(code == RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS);
DBG_(cd, "%u bytes", len);
ofono_cbs_notify(cd->cbs, data, len);
}
static gboolean ril_cbs_register(gpointer user_data)
static void ril_cbs_probe_done_cb(GRilIoChannel *io, int status,
const void *data, guint len, void *user_data)
{
struct ril_cbs *cd = user_data;
DBG("");
GASSERT(cd->timer_id);
cd->timer_id = 0;
ofono_cbs_register(cd->cbs);
cd->event_id = grilio_channel_add_unsol_event_handler(cd->io,
ril_cbs_notify, RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS, cd);
/* Single-shot */
return FALSE;
if (status == RIL_E_SUCCESS) {
DBG_(cd, "registering for CB");
cd->event_id = grilio_channel_add_unsol_event_handler(cd->io,
ril_cbs_notify, RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS,
cd);
ofono_cbs_register(cd->cbs);
} else {
DBG_(cd, "failed to query CB config");
ofono_cbs_remove(cd->cbs);
}
}
static int ril_cbs_probe(struct ofono_cbs *cbs, unsigned int vendor,
@@ -77,12 +172,27 @@ static int ril_cbs_probe(struct ofono_cbs *cbs, unsigned int vendor,
{
struct ril_modem *modem = data;
struct ril_cbs *cd = g_try_new0(struct ril_cbs, 1);
GRilIoRequest* req = grilio_request_new();
DBG("");
cd->cbs = cbs;
cd->io = grilio_channel_ref(ril_modem_io(modem));
cd->timer_id = g_idle_add(ril_cbs_register, cd);
ofono_cbs_set_data(cbs, cd);
cd->log_prefix = (modem->log_prefix && modem->log_prefix[0]) ?
g_strconcat(modem->log_prefix, " ", NULL) : g_strdup("");
cd->cbs = cbs;
DBG_(cd, "");
cd->io = grilio_channel_ref(ril_modem_io(modem));
cd->q = grilio_queue_new(cd->io);
/*
* RIL_REQUEST_GSM_GET_BROADCAST_SMS_CONFIG often fails at startup.
* We may have to retry a few times.
*/
grilio_request_set_retry(req, RIL_CBS_CHECK_RETRY_MS,
RIL_CBS_CHECK_RETRY_COUNT);
grilio_queue_send_request_full(cd->q, req,
RIL_REQUEST_GSM_GET_BROADCAST_SMS_CONFIG,
ril_cbs_probe_done_cb, NULL, cd);
grilio_request_unref(req);
return 0;
}
@@ -90,15 +200,13 @@ static void ril_cbs_remove(struct ofono_cbs *cbs)
{
struct ril_cbs *cd = ofono_cbs_get_data(cbs);
DBG("");
DBG_(cd, "");
ofono_cbs_set_data(cbs, NULL);
if (cd->timer_id > 0) {
g_source_remove(cd->timer_id);
}
grilio_channel_remove_handler(cd->io, cd->event_id);
grilio_channel_unref(cd->io);
grilio_queue_cancel_all(cd->q, FALSE);
grilio_queue_unref(cd->q);
g_free(cd->log_prefix);
g_free(cd);
}
@@ -106,8 +214,8 @@ const struct ofono_cbs_driver ril_cbs_driver = {
.name = RILMODEM_DRIVER,
.probe = ril_cbs_probe,
.remove = ril_cbs_remove,
.set_topics = ril_set_topics,
.clear_topics = ril_clear_topics
.set_topics = ril_cbs_set_topics,
.clear_topics = ril_cbs_clear_topics
};
/*

View File

@@ -17,13 +17,14 @@
#include "ril_sim_card.h"
#include "ril_radio.h"
#include "ril_util.h"
#include "ril_mce.h"
#include "ril_log.h"
#include <grilio_channel.h>
#include <grilio_request.h>
#include <grilio_parser.h>
#include <gutil_misc.h>
#define DISPLAY_ON_UPDATE_RATE (1000) /* 1 sec */
#define DISPLAY_OFF_UPDATE_RATE (60000) /* 1 min */
@@ -32,7 +33,7 @@ typedef struct ril_cell_info RilCellInfo;
struct ril_cell_info_priv {
GRilIoChannel *io;
struct ril_mce *mce;
MceDisplay *display;
struct ril_radio *radio;
struct ril_sim_card *sim_card;
gulong display_state_event_id;
@@ -355,11 +356,11 @@ static void ril_cell_info_update_rate(struct ril_cell_info *self)
struct ril_cell_info_priv *priv = self->priv;
ril_cell_info_set_rate(self,
(priv->mce->display_state == RIL_MCE_DISPLAY_OFF) ?
(priv->display->state == MCE_DISPLAY_STATE_OFF) ?
DISPLAY_OFF_UPDATE_RATE : DISPLAY_ON_UPDATE_RATE);
}
static void ril_cell_info_display_state_cb(struct ril_mce *mce, void *arg)
static void ril_cell_info_display_state_cb(MceDisplay *display, void *arg)
{
struct ril_cell_info *self = RIL_CELL_INFO(arg);
struct ril_cell_info_priv *priv = self->priv;
@@ -420,14 +421,14 @@ void ril_cell_info_remove_handler(struct ril_cell_info *self, gulong id)
}
struct ril_cell_info *ril_cell_info_new(GRilIoChannel *io,
const char *log_prefix, struct ril_mce *mce,
const char *log_prefix, MceDisplay *display,
struct ril_radio *radio, struct ril_sim_card *sim_card)
{
struct ril_cell_info *self = g_object_new(RIL_CELL_INFO_TYPE, 0);
struct ril_cell_info_priv *priv = self->priv;
priv->io = grilio_channel_ref(io);
priv->mce = ril_mce_ref(mce);
priv->display = mce_display_ref(display);
priv->radio = ril_radio_ref(radio);
priv->sim_card = ril_sim_card_ref(sim_card);
priv->log_prefix = (log_prefix && log_prefix[0]) ?
@@ -436,7 +437,7 @@ struct ril_cell_info *ril_cell_info_new(GRilIoChannel *io,
priv->event_id = grilio_channel_add_unsol_event_handler(priv->io,
ril_cell_info_list_changed_cb, RIL_UNSOL_CELL_INFO_LIST, self);
priv->display_state_event_id =
ril_mce_add_display_state_changed_handler(mce,
mce_display_add_state_changed_handler(display,
ril_cell_info_display_state_cb, self);
priv->radio_state_event_id =
ril_radio_add_state_changed_handler(radio,
@@ -490,10 +491,8 @@ static void ril_cell_info_dispose(GObject *object)
FALSE);
priv->set_rate_id = 0;
}
if (priv->display_state_event_id) {
ril_mce_remove_handler(priv->mce, priv->display_state_event_id);
priv->display_state_event_id = 0;
}
gutil_disconnect_handlers(priv->display,
&priv->display_state_event_id, 1);
ril_radio_remove_handlers(priv->radio, &priv->radio_state_event_id, 1);
ril_sim_card_remove_handlers(priv->sim_card,
&priv->sim_status_event_id, 1);
@@ -508,7 +507,7 @@ static void ril_cell_info_finalize(GObject *object)
DBG_(self, "");
g_free(priv->log_prefix);
grilio_channel_unref(priv->io);
ril_mce_unref(priv->mce);
mce_display_unref(priv->display);
ril_radio_unref(priv->radio);
ril_sim_card_unref(priv->sim_card);
g_slist_free_full(self->cells, g_free);

View File

@@ -17,6 +17,7 @@
#define RIL_CELL_INFO_H
#include "ril_types.h"
#include <mce_display.h>
struct ril_cell {
enum ril_cell_info_type type;
@@ -42,7 +43,7 @@ gint ril_cell_compare_location(const struct ril_cell *c1,
const struct ril_cell *c2);
struct ril_cell_info *ril_cell_info_new(GRilIoChannel *io,
const char *log_prefix, struct ril_mce *mce,
const char *log_prefix, MceDisplay *display,
struct ril_radio *radio, struct ril_sim_card *sim_card);
struct ril_cell_info *ril_cell_info_ref(struct ril_cell_info *info);
void ril_cell_info_unref(struct ril_cell_info *info);

View File

@@ -0,0 +1,188 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2017 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "ril_config.h"
#include <gutil_intarray.h>
#include <gutil_ints.h>
/* Utilities for parsing ril_subscription.conf */
char *ril_config_get_string(GKeyFile *file, const char *group, const char *key)
{
char *val = g_key_file_get_string(file, group, key, NULL);
if (!val && strcmp(group, RILCONF_SETTINGS_GROUP)) {
/* Check the common section */
val = g_key_file_get_string(file, RILCONF_SETTINGS_GROUP, key,
NULL);
}
return val;
}
char **ril_config_get_strings(GKeyFile *file, const char *group,
const char *key, char delimiter)
{
char *str = ril_config_get_string(file, group, key);
if (str) {
char **strv, **p;
char delimiter_str[2];
delimiter_str[0] = delimiter;
delimiter_str[1] = 0;
strv = g_strsplit(str, delimiter_str, -1);
/* Strip whitespaces */
for (p = strv; *p; p++) {
*p = g_strstrip(*p);
}
g_free(str);
return strv;
}
return NULL;
}
gboolean ril_config_get_integer(GKeyFile *file, const char *group,
const char *key, int *out_value)
{
GError *error = NULL;
int value = g_key_file_get_integer(file, group, key, &error);
if (!error) {
if (out_value) {
*out_value = value;
}
return TRUE;
} else {
g_error_free(error);
if (strcmp(group, RILCONF_SETTINGS_GROUP)) {
/* Check the common section */
error = NULL;
value = g_key_file_get_integer(file,
RILCONF_SETTINGS_GROUP, key, &error);
if (!error) {
if (out_value) {
*out_value = value;
}
return TRUE;
}
g_error_free(error);
}
return FALSE;
}
}
gboolean ril_config_get_boolean(GKeyFile *file, const char *group,
const char *key, gboolean *out_value)
{
GError *error = NULL;
gboolean value = g_key_file_get_boolean(file, group, key, &error);
if (!error) {
if (out_value) {
*out_value = value;
}
return TRUE;
} else {
g_error_free(error);
if (strcmp(group, RILCONF_SETTINGS_GROUP)) {
/* Check the common section */
error = NULL;
value = g_key_file_get_boolean(file,
RILCONF_SETTINGS_GROUP, key, &error);
if (!error) {
if (out_value) {
*out_value = value;
}
return TRUE;
}
g_error_free(error);
}
return FALSE;
}
}
gboolean ril_config_get_flag(GKeyFile *file, const char *group,
const char *key, int flag, int *flags)
{
gboolean value;
if (ril_config_get_boolean(file, group, key, &value)) {
if (value) {
*flags |= flag;
} else {
*flags &= ~flag;
}
return TRUE;
} else {
return FALSE;
}
}
GUtilInts *ril_config_get_ints(GKeyFile *file, const char *group,
const char *key)
{
char *value = ril_config_get_string(file, group, key);
if (value) {
char **values = g_strsplit(value, ",", -1);
char **ptr = values;
GUtilIntArray *array = gutil_int_array_new();
while (*ptr) {
const char *str = *ptr++;
char *end = NULL;
long ival = strtol(str, &end, 0);
if (str[0] && !end[0]) {
gutil_int_array_append(array, ival);
}
}
g_free(value);
g_strfreev(values);
return gutil_int_array_free_to_ints(array);
}
return NULL;
}
char *ril_config_ints_to_string(GUtilInts *ints, char separator)
{
if (ints) {
guint i, n;
const int *data = gutil_ints_get_data(ints, &n);
GString *buf = g_string_new(NULL);
for (i=0; i<n; i++) {
if (buf->len > 0) {
g_string_append_c(buf, separator);
}
g_string_append_printf(buf, "%d", data[i]);
}
return g_string_free(buf, FALSE);
}
return NULL;
}
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

View File

@@ -0,0 +1,47 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2017 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef RIL_CONFIG_H
#define RIL_CONFIG_H
#include "ril_types.h"
/* Utilities for parsing ril_subscription.conf */
#define RILCONF_SETTINGS_GROUP "Settings"
char *ril_config_get_string(GKeyFile *file, const char *group,
const char *key);
char **ril_config_get_strings(GKeyFile *file, const char *group,
const char *key, char delimiter);
gboolean ril_config_get_integer(GKeyFile *file, const char *group,
const char *key, int *value);
gboolean ril_config_get_boolean(GKeyFile *file, const char *group,
const char *key, gboolean *value);
gboolean ril_config_get_flag(GKeyFile *file, const char *group,
const char *key, int flag, int *flags);
GUtilInts *ril_config_get_ints(GKeyFile *file, const char *group,
const char *key);
char *ril_config_ints_to_string(GUtilInts *ints, char separator);
#endif /* RIL_CONFIG_H */
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

View File

@@ -1,11 +1,10 @@
/*
*
* RIL constants adopted from AOSP's header:
*
* /hardware/ril/reference_ril/ril.h
*
* Copyright (C) 2013 Canonical Ltd.
* Copyright (C) 2013-2016 Jolla Ltd.
* Copyright (C) 2013-2017 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -118,45 +117,68 @@ enum ril_radio_tech {
};
/* See RIL_REQUEST_LAST_CALL_FAIL_CAUSE */
#define CALL_FAIL_UNOBTAINABLE_NUMBER 1
#define CALL_FAIL_NORMAL 16
#define CALL_FAIL_BUSY 17
#define CALL_FAIL_CONGESTION 34
#define CALL_FAIL_ACM_LIMIT_EXCEEDED 68
#define CALL_FAIL_CALL_BARRED 240
#define CALL_FAIL_FDN_BLOCKED 241
#define CALL_FAIL_IMSI_UNKNOWN_IN_VLR 242
#define CALL_FAIL_IMEI_NOT_ACCEPTED 243
#define CALL_FAIL_DIAL_MODIFIED_TO_USSD 244
#define CALL_FAIL_DIAL_MODIFIED_TO_SS 245
#define CALL_FAIL_DIAL_MODIFIED_TO_DIAL 246
#define CALL_FAIL_CDMA_LOCKED_UNTIL_POWER_CYCLE 1000
#define CALL_FAIL_CDMA_DROP 1001
#define CALL_FAIL_CDMA_INTERCEPT 1002
#define CALL_FAIL_CDMA_REORDER 1003
#define CALL_FAIL_CDMA_SO_REJECT 1004
#define CALL_FAIL_CDMA_RETRY_ORDER 1005
#define CALL_FAIL_CDMA_ACCESS_FAILURE 1006
#define CALL_FAIL_CDMA_PREEMPTED 1007
#define CALL_FAIL_CDMA_NOT_EMERGENCY 1008
#define CALL_FAIL_CDMA_ACCESS_BLOCKED 1009
#define CALL_FAIL_ERROR_UNSPECIFIED 0xffff
enum ril_call_fail_cause {
CALL_FAIL_UNOBTAINABLE_NUMBER = 1,
CALL_FAIL_NO_ROUTE_TO_DESTINATION = 3,
CALL_FAIL_CHANNEL_UNACCEPTABLE = 6,
CALL_FAIL_OPERATOR_DETERMINED_BARRING = 8,
CALL_FAIL_NORMAL = 16,
CALL_FAIL_BUSY = 17,
CALL_FAIL_NO_USER_RESPONDING = 18,
CALL_FAIL_NO_ANSWER_FROM_USER = 19,
CALL_FAIL_CALL_REJECTED = 21,
CALL_FAIL_NUMBER_CHANGED = 22,
CALL_FAIL_DESTINATION_OUT_OF_ORDER = 27,
CALL_FAIL_INVALID_NUMBER_FORMAT = 28,
CALL_FAIL_FACILITY_REJECTED = 29,
CALL_FAIL_RESP_TO_STATUS_ENQUIRY = 30,
CALL_FAIL_NORMAL_UNSPECIFIED = 31,
CALL_FAIL_CONGESTION = 34,
CALL_FAIL_NETWORK_OUT_OF_ORDER = 38,
CALL_FAIL_TEMPORARY_FAILURE = 41,
CALL_FAIL_SWITCHING_EQUIPMENT_CONGESTION = 42,
CALL_FAIL_ACCESS_INFORMATION_DISCARDED = 43,
CALL_FAIL_REQUESTED_CIRCUIT_OR_CHANNEL_NOT_AVAILABLE = 44,
CALL_FAIL_RESOURCES_UNAVAILABLE_OR_UNSPECIFIED = 47,
CALL_FAIL_QOS_UNAVAILABLE = 49,
CALL_FAIL_REQUESTED_FACILITY_NOT_SUBSCRIBED = 50,
CALL_FAIL_INCOMING_CALLS_BARRED_WITHIN_CUG = 55,
CALL_FAIL_BEARER_CAPABILITY_NOT_AUTHORIZED = 57,
CALL_FAIL_BEARER_CAPABILITY_UNAVAILABLE = 58,
CALL_FAIL_SERVICE_OPTION_NOT_AVAILABLE = 63,
CALL_FAIL_BEARER_SERVICE_NOT_IMPLEMENTED = 65,
CALL_FAIL_ACM_LIMIT_EXCEEDED = 68,
CALL_FAIL_REQUESTED_FACILITY_NOT_IMPLEMENTED = 69,
CALL_FAIL_ONLY_DIGITAL_INFORMATION_BEARER_AVAILABLE = 70,
CALL_FAIL_SERVICE_OR_OPTION_NOT_IMPLEMENTED = 79,
CALL_FAIL_INVALID_TRANSACTION_IDENTIFIER = 81,
CALL_FAIL_USER_NOT_MEMBER_OF_CUG = 87,
CALL_FAIL_INCOMPATIBLE_DESTINATION = 88,
CALL_FAIL_INVALID_TRANSIT_NW_SELECTION = 91,
CALL_FAIL_SEMANTICALLY_INCORRECT_MESSAGE = 95,
CALL_FAIL_INVALID_MANDATORY_INFORMATION = 96,
CALL_FAIL_MESSAGE_TYPE_NON_IMPLEMENTED = 97,
CALL_FAIL_MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 98,
CALL_FAIL_INFORMATION_ELEMENT_NON_EXISTENT = 99,
CALL_FAIL_CONDITIONAL_IE_ERROR = 100,
CALL_FAIL_MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 101,
CALL_FAIL_RECOVERY_ON_TIMER_EXPIRED = 102,
CALL_FAIL_PROTOCOL_ERROR_UNSPECIFIED = 111,
CALL_FAIL_INTERWORKING_UNSPECIFIED = 127,
CALL_FAIL_CALL_BARRED = 240,
CALL_FAIL_FDN_BLOCKED = 241,
CALL_FAIL_IMSI_UNKNOWN_IN_VLR = 242,
CALL_FAIL_IMEI_NOT_ACCEPTED = 243,
CALL_FAIL_DIAL_MODIFIED_TO_USSD = 244,
CALL_FAIL_DIAL_MODIFIED_TO_SS = 245,
CALL_FAIL_DIAL_MODIFIED_TO_DIAL = 246,
CALL_FAIL_ERROR_UNSPECIFIED = 0xffff,
/* Not defined in ril.h but valid 3GPP specific cause values
* for call control. See 3GPP TS 24.008 Annex H. */
#define CALL_FAIL_NO_ROUTE_TO_DESTINATION 3
#define CALL_FAIL_CHANNEL_UNACCEPTABLE 6
#define CALL_FAIL_OPERATOR_DETERMINED_BARRING 8
#define CALL_FAIL_NO_USER_RESPONDING 18
#define CALL_FAIL_USER_ALERTING_NO_ANSWER 19
#define CALL_FAIL_CALL_REJECTED 21
#define CALL_FAIL_NUMBER_CHANGED 22
#define CALL_FAIL_ANONYMOUS_CALL_REJECTION 24
#define CALL_FAIL_PRE_EMPTION 25
#define CALL_FAIL_DESTINATION_OUT_OF_ORDER 27
#define CALL_FAIL_INCOMPLETE_NUMBER 28
#define CALL_FAIL_FACILITY_REJECTED 29
#define CALL_FAIL_NORMAL_UNSPECIFIED 31
CALL_FAIL_ANONYMOUS_CALL_REJECTION = 24,
CALL_FAIL_PRE_EMPTION = 25
};
enum ril_data_call_fail_cause {
PDP_FAIL_NONE = 0,

View File

@@ -36,6 +36,7 @@
#define PROTO_IPV4V6_STR "IPV4V6"
enum ril_data_priv_flags {
RIL_DATA_FLAG_NONE = 0x00,
RIL_DATA_FLAG_ALLOWED = 0x01,
RIL_DATA_FLAG_MAX_SPEED = 0x02,
RIL_DATA_FLAG_ON = 0x04
@@ -99,6 +100,8 @@ struct ril_data_priv {
struct ril_data_request *req_queue;
struct ril_data_request *pending_req;
struct ril_data_options options;
guint slot;
char *log_prefix;
guint query_id;
gulong io_event_id;
@@ -158,6 +161,8 @@ struct ril_data_request_setup {
char *password;
enum ofono_gprs_proto proto;
enum ofono_gprs_auth_method auth_method;
guint retry_count;
guint retry_delay_id;
};
struct ril_data_request_deact {
@@ -170,7 +175,6 @@ struct ril_data_request_2g {
gulong handler_id;
};
static gboolean ril_data_manager_handover(struct ril_data_manager *dm);
static void ril_data_manager_check_data(struct ril_data_manager *dm);
static void ril_data_manager_check_network_mode(struct ril_data_manager *dm);
@@ -270,7 +274,8 @@ static int ril_data_protocol_to_ofono(gchar *str)
return -1;
}
static struct ril_data_call *ril_data_call_parse(int version, GRilIoParser *rilp)
static struct ril_data_call *ril_data_call_parse(int version,
GRilIoParser *rilp)
{
int prot;
char *prot_str;
@@ -278,6 +283,7 @@ static struct ril_data_call *ril_data_call_parse(int version, GRilIoParser *rilp
guint32 active = RIL_DATA_CALL_INACTIVE;
struct ril_data_call *call = g_new0(struct ril_data_call, 1);
/* RIL_Data_Call_Response_v6 (see ril.h) */
grilio_parser_get_uint32(rilp, &status);
grilio_parser_get_int32(rilp, &call->retry_time);
grilio_parser_get_int32(rilp, &call->cid);
@@ -297,9 +303,12 @@ static struct ril_data_call *ril_data_call_parse(int version, GRilIoParser *rilp
call->status = status;
call->active = active;
/* RIL_Data_Call_Response_v9 */
if (version >= 9) {
/* PCSCF */
grilio_parser_skip_string(rilp);
/* RIL_Data_Call_Response_v11 */
if (version >= 11) {
/* MTU */
grilio_parser_get_int32(rilp, &call->mtu);
@@ -310,7 +319,8 @@ static struct ril_data_call *ril_data_call_parse(int version, GRilIoParser *rilp
return call;
}
struct ril_data_call_list *ril_data_call_list_parse(const void *data, guint len)
static struct ril_data_call_list *ril_data_call_list_parse(const void *data,
guint len, enum ril_data_call_format format)
{
unsigned int version, n, i;
GRilIoParser rilp;
@@ -321,8 +331,13 @@ struct ril_data_call_list *ril_data_call_list_parse(const void *data, guint len)
struct ril_data_call_list *list =
g_new0(struct ril_data_call_list, 1);
DBG("version=%u,num=%u", version, n);
list->version = version;
if (format == RIL_DATA_CALL_FORMAT_AUTO || format == version) {
DBG("version=%u,num=%u", version, n);
list->version = version;
} else {
DBG("version=%u(%d),num=%u", version, format, n);
list->version = format;
}
for (i = 0; i < n && !grilio_parser_at_end(&rilp); i++) {
struct ril_data_call *call =
@@ -492,7 +507,8 @@ static void ril_data_call_list_changed_cb(GRilIoChannel *io, guint event,
priv->query_id = 0;
}
ril_data_set_calls(self, ril_data_call_list_parse(data, len));
ril_data_set_calls(self, ril_data_call_list_parse(data, len,
priv->options.data_call_format));
}
static void ril_data_query_data_calls_cb(GRilIoChannel *io, int ril_status,
@@ -504,7 +520,8 @@ static void ril_data_query_data_calls_cb(GRilIoChannel *io, int ril_status,
GASSERT(priv->query_id);
priv->query_id = 0;
if (ril_status == RIL_E_SUCCESS) {
ril_data_set_calls(self, ril_data_call_list_parse(data, len));
ril_data_set_calls(self, ril_data_call_list_parse(data, len,
priv->options.data_call_format));
}
}
@@ -579,11 +596,11 @@ static gboolean ril_data_request_do_cancel(struct ril_data_request *req)
struct ril_data_priv *priv = req->data->priv;
DBG_(req->data, "canceling %s request %p", req->name, req);
if (req->cancel) {
req->cancel(req);
}
if (priv->pending_req == req) {
/* Request has been submitted already */
if (req->cancel) {
req->cancel(req);
}
priv->pending_req = NULL;
} else if (priv->req_queue == req) {
/* It's the first one in the queue */
@@ -666,15 +683,33 @@ static void ril_data_request_queue(struct ril_data_request *req)
static void ril_data_call_setup_cancel(struct ril_data_request *req)
{
if (req->pending_id) {
grilio_queue_cancel_request(req->data->priv->q,
req->pending_id, FALSE);
req->pending_id = 0;
if (req->cb.setup) {
req->cb.setup(req->data, GRILIO_STATUS_CANCELLED,
NULL, req->arg);
}
struct ril_data_request_setup *setup =
G_CAST(req, struct ril_data_request_setup, req);
ril_data_request_cancel_io(req);
if (setup->retry_delay_id) {
g_source_remove(setup->retry_delay_id);
setup->retry_delay_id = 0;
}
if (req->cb.setup) {
ril_data_call_setup_cb_t cb = req->cb.setup;
req->cb.setup = NULL;
cb(req->data, GRILIO_STATUS_CANCELLED, NULL, req->arg);
}
}
static gboolean ril_data_call_setup_retry(void *user_data)
{
struct ril_data_request_setup *setup = user_data;
struct ril_data_request *req = &setup->req;
GASSERT(setup->retry_delay_id);
setup->retry_delay_id = 0;
setup->retry_count++;
DBG("silent retry %u out of %u", setup->retry_count,
req->data->priv->options.data_call_retry_limit);
req->submit(req);
return G_SOURCE_REMOVE;
}
static void ril_data_call_setup_cb(GRilIoChannel *io, int ril_status,
@@ -683,13 +718,13 @@ static void ril_data_call_setup_cb(GRilIoChannel *io, int ril_status,
struct ril_data_request_setup *setup = user_data;
struct ril_data_request *req = &setup->req;
struct ril_data *self = req->data;
struct ril_data_priv *priv = self->priv;
struct ril_data_call_list *list = NULL;
struct ril_data_call *call = NULL;
ril_data_request_completed(req);
if (ril_status == RIL_E_SUCCESS) {
list = ril_data_call_list_parse(data, len);
list = ril_data_call_list_parse(data, len,
priv->options.data_call_format);
}
if (list) {
@@ -701,6 +736,32 @@ static void ril_data_call_setup_cb(GRilIoChannel *io, int ril_status,
}
}
if (call && call->status == PDP_FAIL_ERROR_UNSPECIFIED &&
setup->retry_count < priv->options.data_call_retry_limit) {
/*
* According to the comment from ril.h we should silently
* retry. First time we retry immediately and if that doedsn't
* work, then after certain delay.
*/
req->pending_id = 0;
GASSERT(!setup->retry_delay_id);
if (!setup->retry_count) {
setup->retry_count++;
DBG("silent retry %u out of %u", setup->retry_count,
priv->options.data_call_retry_limit);
req->submit(req);
} else {
guint ms = priv->options.data_call_retry_delay_ms;
DBG("silent retry scheduled in %u ms", ms);
setup->retry_delay_id = g_timeout_add(ms,
ril_data_call_setup_retry, setup);
}
ril_data_call_list_free(list);
return;
}
ril_data_request_completed(req);
if (call && call->status == PDP_FAIL_NONE) {
if (ril_data_call_list_move_calls(self->data_calls, list) > 0) {
DBG("data call(s) added");
@@ -823,14 +884,11 @@ static struct ril_data_request *ril_data_call_setup_new(struct ril_data *data,
static void ril_data_call_deact_cancel(struct ril_data_request *req)
{
if (req->pending_id) {
grilio_queue_cancel_request(req->data->priv->q,
req->pending_id, FALSE);
req->pending_id = 0;
if (req->cb.setup) {
req->cb.deact(req->data, GRILIO_STATUS_CANCELLED,
req->arg);
}
ril_data_request_cancel_io(req);
if (req->cb.deact) {
ril_data_call_deactivate_cb_t cb = req->cb.deact;
req->cb.deact = NULL;
cb(req->data, GRILIO_STATUS_CANCELLED, req->arg);
}
}
@@ -1002,9 +1060,20 @@ static void ril_data_settings_changed(struct ril_sim_settings *settings,
ril_data_manager_check_network_mode(RIL_DATA(user_data)->priv->dm);
}
static gint ril_data_compare_cb(gconstpointer a, gconstpointer b)
{
const struct ril_data *d1 = a;
const struct ril_data *d2 = b;
const struct ril_data_priv *p1 = d1->priv;
const struct ril_data_priv *p2 = d2->priv;
return p1->slot < p2->slot ? (-1) : p1->slot > p2->slot ? 1 : 0;
}
struct ril_data *ril_data_new(struct ril_data_manager *dm, const char *name,
struct ril_radio *radio, struct ril_network *network,
GRilIoChannel *io)
struct ril_radio *radio, struct ril_network *network,
GRilIoChannel *io, const struct ril_data_options *options,
const struct ril_slot_config *config)
{
GASSERT(dm);
if (G_LIKELY(dm)) {
@@ -1013,9 +1082,25 @@ struct ril_data *ril_data_new(struct ril_data_manager *dm, const char *name,
struct ril_sim_settings *settings = network->settings;
GRilIoRequest *req = grilio_request_new();
priv->options = *options;
switch (priv->options.allow_data) {
case RIL_ALLOW_DATA_ON:
case RIL_ALLOW_DATA_OFF:
break;
default:
/*
* When RIL_REQUEST_ALLOW_DATA first appeared in ril.h
* RIL_VERSION was 10
*/
priv->options.allow_data = (io->ril_version > 10) ?
RIL_ALLOW_DATA_ON : RIL_ALLOW_DATA_OFF;
break;
}
priv->log_prefix = (name && name[0]) ?
g_strconcat(name, " ", NULL) : g_strdup("");
priv->slot = config->slot;
priv->q = grilio_queue_new(io);
priv->io = grilio_channel_ref(io);
priv->dm = ril_data_manager_ref(dm);
@@ -1040,7 +1125,10 @@ struct ril_data *ril_data_new(struct ril_data_manager *dm, const char *name,
NULL, self);
grilio_request_unref(req);
dm->data_list = g_slist_append(dm->data_list, self);
/* Order data contexts according to slot numbers */
dm->data_list = g_slist_insert_sorted(dm->data_list, self,
ril_data_compare_cb);
ril_data_manager_check_network_mode(dm);
return self;
}
return NULL;
@@ -1343,6 +1431,16 @@ void ril_data_manager_unref(struct ril_data_manager *self)
}
}
static gboolean ril_data_manager_handover(struct ril_data_manager *self)
{
/*
* The 3G/LTE handover thing only makes sense if we are managing
* more than one SIM slot. Otherwise leave things where they are.
*/
return (self->data_list && self->data_list->next &&
(self->flags & RIL_DATA_MANAGER_3GLTE_HANDOVER));
}
static gboolean ril_data_manager_requests_pending(struct ril_data_manager *self)
{
GSList *l;
@@ -1362,53 +1460,54 @@ static void ril_data_manager_check_network_mode(struct ril_data_manager *self)
GSList *l;
if (ril_data_manager_handover(self)) {
gboolean need_fast_access = FALSE;
struct ril_network *lte_network = NULL;
int non_gsm_count = 0;
/*
* Count number of SIMs for which GSM is selected
* Count number of SIMs for which non-GSM mode is selected
*/
for (l= self->data_list; l; l = l->next) {
struct ril_data *data = l->data;
struct ril_data_priv *priv = data->priv;
struct ril_sim_settings *sim = priv->network->settings;
struct ril_network *network = priv->network;
struct ril_sim_settings *sim = network->settings;
if (sim->pref_mode != OFONO_RADIO_ACCESS_MODE_GSM &&
sim->imsi) {
if (sim->pref_mode != OFONO_RADIO_ACCESS_MODE_GSM) {
non_gsm_count++;
if (priv->flags & RIL_DATA_FLAG_MAX_SPEED) {
need_fast_access = TRUE;
if ((priv->flags & RIL_DATA_FLAG_MAX_SPEED) &&
!lte_network) {
lte_network = network;
}
}
}
/*
* If the SIM selected for internet access has non-GSM mode
* enabled and non-GSM mode is enabled for more than one SIM,
* then we need to limit other SIMs to GSM. Otherwise, turn
* all limits off.
* If there's no SIM selected for internet access
* then choose the first slot for LTE.
*/
if (need_fast_access && non_gsm_count > 1) {
for (l= self->data_list; l; l = l->next) {
struct ril_data *data = l->data;
struct ril_data_priv *priv = data->priv;
ril_network_set_max_pref_mode(priv->network,
(priv->flags & RIL_DATA_FLAG_MAX_SPEED) ?
OFONO_RADIO_ACCESS_MODE_ANY :
OFONO_RADIO_ACCESS_MODE_GSM,
FALSE);
}
return;
if (!lte_network) {
struct ril_data *data = self->data_list->data;
lte_network = data->priv->network;
}
}
/* Otherwise there's no reason to limit anything */
for (l= self->data_list; l; l = l->next) {
struct ril_data *data = l->data;
ril_network_set_max_pref_mode(data->priv->network,
for (l= self->data_list; l; l = l->next) {
struct ril_data *data = l->data;
struct ril_network *network = data->priv->network;
ril_network_set_max_pref_mode(network,
(network == lte_network) ?
OFONO_RADIO_ACCESS_MODE_ANY :
OFONO_RADIO_ACCESS_MODE_GSM,
FALSE);
}
} else {
/* Otherwise there's no reason to limit anything */
for (l= self->data_list; l; l = l->next) {
struct ril_data *data = l->data;
ril_network_set_max_pref_mode(data->priv->network,
OFONO_RADIO_ACCESS_MODE_ANY, FALSE);
}
}
}
@@ -1426,16 +1525,6 @@ static struct ril_data *ril_data_manager_allowed(struct ril_data_manager *self)
return NULL;
}
static gboolean ril_data_manager_handover(struct ril_data_manager *self)
{
/*
* The 3G/LTE handover thing only makes sense if we are managing
* more than one SIM slot. Otherwise leave things where they are.
*/
return (self->data_list && self->data_list->next &&
(self->flags & RIL_DATA_MANAGER_3GLTE_HANDOVER));
}
static void ril_data_manager_switch_data_on(struct ril_data_manager *self,
struct ril_data *data)
{
@@ -1449,11 +1538,8 @@ static void ril_data_manager_switch_data_on(struct ril_data_manager *self,
OFONO_RADIO_ACCESS_MODE_ANY, TRUE);
}
/*
* RIL_VERSION in ril.h was 10 when RIL_REQUEST_ALLOW_DATA first
* appeared there.
*/
if (priv->io->ril_version >= 10) {
if (priv->options.allow_data == RIL_ALLOW_DATA_ON) {
ril_data_request_queue(ril_data_allow_new(data));
} else {
priv->flags |= RIL_DATA_FLAG_ON;

View File

@@ -54,6 +54,26 @@ enum ril_data_manager_flags {
RIL_DATA_MANAGER_3GLTE_HANDOVER = 0x01
};
enum ril_data_allow_data_opt {
RIL_ALLOW_DATA_AUTO,
RIL_ALLOW_DATA_ON,
RIL_ALLOW_DATA_OFF
};
enum ril_data_call_format {
RIL_DATA_CALL_FORMAT_AUTO,
RIL_DATA_CALL_FORMAT_6 = 6,
RIL_DATA_CALL_FORMAT_9 = 9,
RIL_DATA_CALL_FORMAT_11 = 11
};
struct ril_data_options {
enum ril_data_allow_data_opt allow_data;
enum ril_data_call_format data_call_format;
unsigned int data_call_retry_limit;
unsigned int data_call_retry_delay_ms;
};
enum ril_data_role {
RIL_DATA_ROLE_NONE, /* Data not allowed */
RIL_DATA_ROLE_MMS, /* Data is allowed at any speed */
@@ -73,8 +93,9 @@ typedef void (*ril_data_call_deactivate_cb_t)(struct ril_data *data,
int ril_status, void *arg);
struct ril_data *ril_data_new(struct ril_data_manager *dm, const char *name,
struct ril_radio *radio, struct ril_network *network,
GRilIoChannel *io);
struct ril_radio *radio, struct ril_network *network,
GRilIoChannel *io, const struct ril_data_options *options,
const struct ril_slot_config *config);
struct ril_data *ril_data_ref(struct ril_data *data);
void ril_data_unref(struct ril_data *data);
gboolean ril_data_allowed(struct ril_data *data);

View File

@@ -42,7 +42,7 @@ struct ril_gprs_context {
struct ril_network *network;
struct ril_data *data;
guint active_ctx_cid;
gulong calls_changed_event_id;
gulong calls_changed_id;
struct ril_mtu_watch *mtu_watch;
struct ril_data_call *active_call;
struct ril_gprs_context_call activate;
@@ -55,53 +55,32 @@ static inline struct ril_gprs_context *ril_gprs_context_get_data(
return ofono_gprs_context_get_data(gprs);
}
static char *ril_gprs_context_netmask(const char *address)
static char *ril_gprs_context_netmask(const char *bits)
{
if (address) {
const char *suffix = strchr(address, '/');
if (suffix) {
int nbits = atoi(suffix + 1);
if (nbits > 0 && nbits < 33) {
const char* str;
struct in_addr in;
in.s_addr = htonl((nbits == 32) ? 0xffffffff :
if (bits) {
int nbits = atoi(bits);
if (nbits > 0 && nbits < 33) {
const char* str;
struct in_addr in;
in.s_addr = htonl((nbits == 32) ? 0xffffffff :
((1 << nbits)-1) << (32-nbits));
str = inet_ntoa(in);
if (str) {
return g_strdup(str);
}
str = inet_ntoa(in);
if (str) {
return g_strdup(str);
}
}
}
return g_strdup("255.255.255.0");
return NULL;
}
static void ril_gprs_context_set_ipv4(struct ofono_gprs_context *gc,
char * const *ip_addr)
static int ril_gprs_context_address_family(const char *addr)
{
const guint n = gutil_strv_length(ip_addr);
if (n > 0) {
ofono_gprs_context_set_ipv4_address(gc, ip_addr[0], TRUE);
if (n > 1) {
ofono_gprs_context_set_ipv4_netmask(gc, ip_addr[1]);
}
}
}
static void ril_gprs_context_set_ipv6(struct ofono_gprs_context *gc,
char * const *ipv6_addr)
{
const guint n = gutil_strv_length(ipv6_addr);
if (n > 0) {
ofono_gprs_context_set_ipv6_address(gc, ipv6_addr[0]);
if (n > 1) {
const int p = atoi(ipv6_addr[1]);
if (p > 0 && p <= 128) {
ofono_gprs_context_set_ipv6_prefix_length(gc, p);
}
}
if (strchr(addr, ':')) {
return AF_INET6;
} else if (strchr(addr, '.')) {
return AF_INET;
} else {
return AF_UNSPEC;
}
}
@@ -111,9 +90,9 @@ static void ril_gprs_context_free_active_call(struct ril_gprs_context *gcd)
ril_data_call_free(gcd->active_call);
gcd->active_call = NULL;
}
if (gcd->calls_changed_event_id) {
ril_data_remove_handler(gcd->data, gcd->calls_changed_event_id);
gcd->calls_changed_event_id = 0;
if (gcd->calls_changed_id) {
ril_data_remove_handler(gcd->data, gcd->calls_changed_id);
gcd->calls_changed_id = 0;
}
if (gcd->mtu_watch) {
ril_mtu_watch_free(gcd->mtu_watch);
@@ -174,97 +153,161 @@ static void ril_gprs_context_set_disconnected(struct ril_gprs_context *gcd)
}
}
static void ril_gprs_split_ip_by_protocol(char **ip_array,
char ***split_ip_addr,
char ***split_ipv6_addr)
static void ril_gprs_context_set_address(struct ofono_gprs_context *gc,
const struct ril_data_call *call)
{
const int n = gutil_strv_length(ip_array);
const char *ip_addr = NULL;
char *ip_mask = NULL;
const char *ipv6_addr = NULL;
unsigned char ipv6_prefix_length = 0;
char *tmp_ip_addr = NULL;
char *tmp_ipv6_addr = NULL;
char * const *list = call->addresses;
const int n = gutil_strv_length(list);
int i;
*split_ipv6_addr = *split_ip_addr = NULL;
for (i = 0; i < n && (!*split_ipv6_addr || !*split_ip_addr); i++) {
const char *addr = ip_array[i];
switch (ril_address_family(addr)) {
for (i = 0; i < n && (!ipv6_addr || !ip_addr); i++) {
const char *addr = list[i];
switch (ril_gprs_context_address_family(addr)) {
case AF_INET:
if (!*split_ip_addr) {
char *mask = ril_gprs_context_netmask(addr);
*split_ip_addr = g_strsplit(addr, "/", 2);
if (gutil_strv_length(*split_ip_addr) == 2) {
g_free((*split_ip_addr)[1]);
(*split_ip_addr)[1] = mask;
if (!ip_addr) {
const char* s = strstr(addr, "/");
if (s) {
const gsize len = s - addr;
tmp_ip_addr = g_strndup(addr, len);
ip_addr = tmp_ip_addr;
ip_mask = ril_gprs_context_netmask(s+1);
} else {
/* This is rather unlikely to happen */
*split_ip_addr =
gutil_strv_add(*split_ip_addr,
mask);
g_free(mask);
ip_addr = addr;
}
if (!ip_mask) {
ip_mask = g_strdup("255.255.255.0");
}
}
break;
case AF_INET6:
if (!*split_ipv6_addr) {
*split_ipv6_addr = g_strsplit(addr, "/", 2);
if (!ipv6_addr) {
const char* s = strstr(addr, "/");
if (s) {
const gsize len = s - addr;
const int prefix = atoi(s + 1);
tmp_ipv6_addr = g_strndup(addr, len);
ipv6_addr = tmp_ipv6_addr;
if (prefix >= 0 && prefix <= 128) {
ipv6_prefix_length = prefix;
}
} else {
ipv6_addr = addr;
}
}
}
}
ofono_gprs_context_set_ipv4_address(gc, ip_addr, TRUE);
ofono_gprs_context_set_ipv4_netmask(gc, ip_mask);
ofono_gprs_context_set_ipv6_address(gc, ipv6_addr);
ofono_gprs_context_set_ipv6_prefix_length(gc, ipv6_prefix_length);
if (!ip_addr && !ipv6_addr) {
ofono_error("GPRS context: No IP address");
}
/* Allocate temporary strings */
g_free(ip_mask);
g_free(tmp_ip_addr);
g_free(tmp_ipv6_addr);
}
static void ril_gprs_split_gw_by_protocol(char **gw_array, char **ip_gw,
char **ipv6_gw)
static void ril_gprs_context_set_gateway(struct ofono_gprs_context *gc,
const struct ril_data_call *call)
{
const int n = gutil_strv_length(gw_array);
const char *ip_gw = NULL;
const char *ipv6_gw = NULL;
char * const *list = call->gateways;
const int n = gutil_strv_length(list);
int i;
*ip_gw = *ipv6_gw = NULL;
for (i = 0; i < n && (!*ipv6_gw || !*ip_gw); i++) {
const char *gw_addr = gw_array[i];
switch (ril_address_family(gw_addr)) {
/* Pick 1 gw for each protocol*/
for (i = 0; i < n && (!ipv6_gw || !ip_gw); i++) {
const char *addr = list[i];
switch (ril_gprs_context_address_family(addr)) {
case AF_INET:
if (!*ip_gw) *ip_gw = g_strdup(gw_addr);
if (!ip_gw) ip_gw = addr;
break;
case AF_INET6:
if (!*ipv6_gw) *ipv6_gw = g_strdup(gw_addr);
if (!ipv6_gw) ipv6_gw = addr;
break;
}
}
ofono_gprs_context_set_ipv4_gateway(gc, ip_gw);
ofono_gprs_context_set_ipv6_gateway(gc, ipv6_gw);
}
static void ril_gprs_split_dns_by_protocol(char **dns_array, char ***dns_addr,
char ***dns_ipv6_addr)
static void ril_gprs_context_set_dns_servers(struct ofono_gprs_context *gc,
const struct ril_data_call *call)
{
const int n = gutil_strv_length(dns_array);
int i;
char * const *list = call->dnses;
const int n = gutil_strv_length(list);
const char **ip_dns = g_new0(const char *, n+1);
const char **ipv6_dns = g_new0(const char *, n+1);
const char **ip_ptr = ip_dns;
const char **ipv6_ptr = ipv6_dns;
*dns_ipv6_addr = *dns_addr = 0;
for (i = 0; i < n; i++) {
const char *addr = dns_array[i];
switch (ril_address_family(addr)) {
const char *addr = list[i];
switch (ril_gprs_context_address_family(addr)) {
case AF_INET:
*dns_addr = gutil_strv_add(*dns_addr, addr);
*ip_ptr++ = addr;
break;
case AF_INET6:
*dns_ipv6_addr = gutil_strv_add(*dns_ipv6_addr, addr);
*ipv6_ptr++ = addr;
break;
}
}
ofono_gprs_context_set_ipv4_dns_servers(gc, ip_dns);
ofono_gprs_context_set_ipv6_dns_servers(gc, ipv6_dns);
g_free(ip_dns);
g_free(ipv6_dns);
}
/* Only compares the stuff that's important to us */
static gboolean ril_gprs_context_data_call_equal(
#define DATA_CALL_IFNAME_CHANGED (0x01)
#define DATA_CALL_ADDRESS_CHANGED (0x02)
#define DATA_CALL_GATEWAY_CHANGED (0x04)
#define DATA_CALL_DNS_CHANGED (0x08)
#define DATA_CALL_ALL_CHANGED (0x0f)
static int ril_gprs_context_data_call_change(
const struct ril_data_call *c1,
const struct ril_data_call *c2)
{
if (!c1 && !c2) {
return TRUE;
return 0;
} else if (c1 && c2) {
return c1->cid == c2->cid &&
c1->active == c2->active && c1->prot == c2->prot &&
!g_strcmp0(c1->ifname, c2->ifname) &&
gutil_strv_equal(c1->dnses, c2->dnses) &&
gutil_strv_equal(c1->gateways, c2->gateways) &&
gutil_strv_equal(c1->addresses, c2->addresses);
int changes = 0;
if (g_strcmp0(c1->ifname, c2->ifname)) {
changes |= DATA_CALL_IFNAME_CHANGED;
}
if (!gutil_strv_equal(c1->addresses, c2->addresses)) {
changes |= DATA_CALL_ADDRESS_CHANGED;
}
if (!gutil_strv_equal(c1->gateways, c2->gateways)) {
changes |= DATA_CALL_GATEWAY_CHANGED;
}
if (!gutil_strv_equal(c1->dnses, c2->dnses)) {
changes |= DATA_CALL_DNS_CHANGED;
}
return changes;
} else {
return FALSE;
return DATA_CALL_ALL_CHANGED;
}
}
@@ -281,30 +324,25 @@ static void ril_gprs_context_call_list_changed(struct ril_data *data, void *arg)
struct ril_data_call *prev_call = gcd->active_call;
const struct ril_data_call *call =
ril_data_call_find(data->data_calls, prev_call->cid);
int change = 0;
if (call) {
/* Check if the call has been disconnected */
if (call->active == RIL_DATA_CALL_INACTIVE) {
ofono_error("Clearing active context");
ril_gprs_context_set_disconnected(gcd);
call = NULL;
if (call && call->active != RIL_DATA_CALL_INACTIVE) {
/* Compare it against the last known state */
} else if (ril_gprs_context_data_call_equal(call, prev_call)) {
DBG("call %u didn't change", call->cid);
call = NULL;
} else {
DBG("call %u changed", call->cid);
}
change = ril_gprs_context_data_call_change(call, prev_call);
} else {
ofono_error("Clearing active context");
ril_gprs_context_set_disconnected(gcd);
call = NULL;
}
if (!call) {
/* We are not interested */
return;
} else if (!change) {
DBG("call %u didn't change", call->cid);
return;
} else {
DBG("call %u changed", call->cid);
}
/*
@@ -319,102 +357,27 @@ static void ril_gprs_context_call_list_changed(struct ril_data *data, void *arg)
ofono_info("data call status: %d", call->status);
}
if (call->active == RIL_DATA_CALL_ACTIVE) {
gboolean signal = FALSE;
if (call->ifname && g_strcmp0(call->ifname, prev_call->ifname)) {
DBG("interface changed");
signal = TRUE;
ofono_gprs_context_set_interface(gc, call->ifname);
}
if (!gutil_strv_equal(call->addresses, prev_call->addresses)) {
char **split_ip_addr = NULL;
char **split_ipv6_addr = NULL;
DBG("address changed");
signal = TRUE;
/* Pick 1 address of each protocol */
ril_gprs_split_ip_by_protocol(call->addresses,
&split_ip_addr, &split_ipv6_addr);
if ((call->prot == OFONO_GPRS_PROTO_IPV4V6 ||
call->prot == OFONO_GPRS_PROTO_IPV6) &&
split_ipv6_addr) {
ril_gprs_context_set_ipv6(gc, split_ipv6_addr);
}
if ((call->prot == OFONO_GPRS_PROTO_IPV4V6 ||
call->prot == OFONO_GPRS_PROTO_IP) &&
split_ip_addr) {
ril_gprs_context_set_ipv4(gc, split_ip_addr);
}
g_strfreev(split_ip_addr);
g_strfreev(split_ipv6_addr);
}
if (!gutil_strv_equal(call->gateways, prev_call->gateways)){
char *ip_gw = NULL;
char *ipv6_gw = NULL;
DBG("gateway changed");
signal = TRUE;
/* Pick 1 gw for each protocol*/
ril_gprs_split_gw_by_protocol(call->gateways,
&ip_gw, &ipv6_gw);
if ((call->prot == OFONO_GPRS_PROTO_IPV4V6 ||
call->prot == OFONO_GPRS_PROTO_IPV6) &&
ipv6_gw) {
ofono_gprs_context_set_ipv6_gateway(gc, ipv6_gw);
}
if ((call->prot == OFONO_GPRS_PROTO_IPV4V6 ||
call->prot == OFONO_GPRS_PROTO_IP) &&
ip_gw) {
ofono_gprs_context_set_ipv4_gateway(gc, ip_gw);
}
g_free(ip_gw);
g_free(ipv6_gw);
}
if (!gutil_strv_equal(call->dnses, prev_call->dnses)){
char **dns_ip = NULL;
char **dns_ipv6 = NULL;
DBG("name server(s) changed");
signal = TRUE;
/* split based on protocol*/
ril_gprs_split_dns_by_protocol(call->dnses,
&dns_ip, &dns_ipv6);
if ((call->prot == OFONO_GPRS_PROTO_IPV4V6 ||
call->prot == OFONO_GPRS_PROTO_IPV6) &&
dns_ipv6) {
ofono_gprs_context_set_ipv6_dns_servers(gc,
(const char **) dns_ipv6);
}
if ((call->prot == OFONO_GPRS_PROTO_IPV4V6 ||
call->prot == OFONO_GPRS_PROTO_IP) && dns_ip) {
ofono_gprs_context_set_ipv4_dns_servers(gc,
(const char**)dns_ip);
}
g_strfreev(dns_ip);
g_strfreev(dns_ipv6);
}
if (signal) {
ofono_gprs_context_signal_change(gc, call->cid);
}
if (change & DATA_CALL_IFNAME_CHANGED) {
DBG("interface changed");
ofono_gprs_context_set_interface(gc, call->ifname);
}
if (change & DATA_CALL_ADDRESS_CHANGED) {
DBG("address changed");
ril_gprs_context_set_address(gc, call);
}
if (change & DATA_CALL_GATEWAY_CHANGED) {
DBG("gateway changed");
ril_gprs_context_set_gateway(gc, call);
}
if (change & DATA_CALL_DNS_CHANGED) {
DBG("name server(s) changed");
ril_gprs_context_set_dns_servers(gc, call);
}
ofono_gprs_context_signal_change(gc, call->cid);
ril_data_call_free(prev_call);
}
@@ -425,93 +388,47 @@ static void ril_gprs_context_activate_primary_cb(struct ril_data *data,
struct ril_gprs_context *gcd = user_data;
struct ofono_gprs_context *gc = gcd->gc;
struct ofono_error error;
char **split_ip_addr = NULL;
char **split_ipv6_addr = NULL;
char* ip_gw = NULL;
char* ipv6_gw = NULL;
char** dns_addr = NULL;
char** dns_ipv6_addr = NULL;
ofono_gprs_context_cb_t cb;
gpointer cb_data;
ofono_info("setting up data call");
ril_error_init_failure(&error);
if (ril_status != RIL_E_SUCCESS) {
ofono_error("GPRS context: Reply failure: %s",
ril_error_to_string(ril_status));
goto done;
}
if (call->status != PDP_FAIL_NONE) {
} else if (call->status != PDP_FAIL_NONE) {
ofono_error("Unexpected data call status %d", call->status);
error.type = OFONO_ERROR_TYPE_CMS;
error.error = call->status;
goto done;
}
/* Must have interface */
if (!call->ifname) {
} else if (!call->ifname) {
/* Must have interface */
ofono_error("GPRS context: No interface");
goto done;
} else {
ofono_info("setting up data call");
GASSERT(!gcd->calls_changed_id);
ril_data_remove_handler(gcd->data, gcd->calls_changed_id);
gcd->calls_changed_id =
ril_data_add_calls_changed_handler(gcd->data,
ril_gprs_context_call_list_changed, gcd);
ril_gprs_context_set_active_call(gcd, call);
ofono_gprs_context_set_interface(gc, call->ifname);
ril_gprs_context_set_address(gc, call);
ril_gprs_context_set_gateway(gc, call);
ril_gprs_context_set_dns_servers(gc, call);
ril_error_init_ok(&error);
}
/* Check the ip address */
ril_gprs_split_ip_by_protocol(call->addresses, &split_ip_addr,
&split_ipv6_addr);
if (!split_ip_addr && !split_ipv6_addr) {
ofono_error("GPRS context: No IP address");
goto done;
if (error.type != OFONO_ERROR_TYPE_NO_ERROR) {
gcd->active_ctx_cid = CTX_ID_NONE;
}
ril_error_init_ok(&error);
ril_gprs_context_set_active_call(gcd, call);
GASSERT(!gcd->calls_changed_event_id);
ril_data_remove_handler(gcd->data, gcd->calls_changed_event_id);
gcd->calls_changed_event_id =
ril_data_add_calls_changed_handler(gcd->data,
ril_gprs_context_call_list_changed, gcd);
ofono_gprs_context_set_interface(gc, call->ifname);
ril_gprs_split_gw_by_protocol(call->gateways, &ip_gw, &ipv6_gw);
ril_gprs_split_dns_by_protocol(call->dnses, &dns_addr, &dns_ipv6_addr);
if (split_ipv6_addr &&
(call->prot == OFONO_GPRS_PROTO_IPV6 ||
call->prot == OFONO_GPRS_PROTO_IPV4V6)) {
ril_gprs_context_set_ipv6(gc, split_ipv6_addr);
ofono_gprs_context_set_ipv6_gateway(gc, ipv6_gw);
ofono_gprs_context_set_ipv6_dns_servers(gc,
(const char **) dns_ipv6_addr);
}
if (split_ip_addr &&
(call->prot == OFONO_GPRS_PROTO_IP ||
call->prot == OFONO_GPRS_PROTO_IPV4V6)) {
ril_gprs_context_set_ipv4(gc, split_ip_addr);
ofono_gprs_context_set_ipv4_gateway(gc, ip_gw);
ofono_gprs_context_set_ipv4_dns_servers(gc,
(const char **) dns_addr);
}
done:
g_strfreev(split_ip_addr);
g_strfreev(split_ipv6_addr);
g_strfreev(dns_addr);
g_strfreev(dns_ipv6_addr);
g_free(ip_gw);
g_free(ipv6_gw);
cb = gcd->activate.cb;
cb_data = gcd->activate.data;
GASSERT(gcd->activate.req);
memset(&gcd->activate, 0, sizeof(gcd->activate));
if (cb) {
if (error.type != OFONO_ERROR_TYPE_NO_ERROR) {
gcd->active_ctx_cid = CTX_ID_NONE;
}
cb(&error, cb_data);
}
}
@@ -531,14 +448,14 @@ static void ril_gprs_context_activate_primary(struct ofono_gprs_context *gc,
ril_netreg_check_if_really_roaming(netreg, rs) ==
NETWORK_REGISTRATION_STATUS_ROAMING) {
struct ofono_error error;
ofono_info("Can't activate context %d (roaming)",
ofono_info("Can't activate context %u (roaming)",
ctx->cid);
cb(ril_error_failure(&error), data);
return;
}
}
ofono_info("Activating context: %d", ctx->cid);
ofono_info("Activating context: %u", ctx->cid);
GASSERT(!gcd->activate.req);
GASSERT(ctx->cid != CTX_ID_NONE);
@@ -592,7 +509,7 @@ static void ril_gprs_context_deactivate_primary(struct ofono_gprs_context *gc,
struct ril_gprs_context *gcd = ril_gprs_context_get_data(gc);
GASSERT(gcd->active_call && gcd->active_ctx_cid == id);
ofono_info("Deactivate primary");
ofono_info("Deactivating context: %u", id);
if (gcd->active_call && gcd->active_ctx_cid == id) {
gcd->deactivate.cb = cb;
@@ -609,7 +526,7 @@ static void ril_gprs_context_deactivate_primary(struct ofono_gprs_context *gc,
static void ril_gprs_context_detach_shutdown(struct ofono_gprs_context *gc,
unsigned int id)
{
DBG("%d", id);
DBG("%u", id);
ril_gprs_context_deactivate_primary(gc, id, NULL, NULL);
}
@@ -636,7 +553,15 @@ static void ril_gprs_context_remove(struct ofono_gprs_context *gc)
DBG("");
ofono_gprs_context_set_data(gc, NULL);
ril_data_request_cancel(gcd->activate.req);
if (gcd->activate.req) {
/*
* The core has already completed its pending D-Bus
* request, invoking the completion callback will
* cause libdbus to panic.
*/
ril_data_request_detach(gcd->activate.req);
ril_data_request_cancel(gcd->activate.req);
}
if (gcd->deactivate.req) {
/* Let it complete but we won't be around to be notified. */
@@ -646,7 +571,7 @@ static void ril_gprs_context_remove(struct ofono_gprs_context *gc)
NULL, NULL);
}
ril_data_remove_handler(gcd->data, gcd->calls_changed_event_id);
ril_data_remove_handler(gcd->data, gcd->calls_changed_id);
ril_data_unref(gcd->data);
ril_network_unref(gcd->network);
ril_data_call_free(gcd->active_call);

View File

@@ -1,268 +0,0 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2016 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "ril_mce.h"
#include "ril_log.h"
#include <ofono/dbus.h>
#include <gdbus.h>
/* <mce/dbus-names.h> */
#define MCE_SERVICE "com.nokia.mce"
#define MCE_SIGNAL_IF "com.nokia.mce.signal"
#define MCE_REQUEST_IF "com.nokia.mce.request"
#define MCE_REQUEST_PATH "/com/nokia/mce/request"
#define MCE_DISPLAY_STATUS_GET "get_display_status"
#define MCE_DISPLAY_SIG "display_status_ind"
#define MCE_DISPLAY_DIM_STRING "dimmed"
#define MCE_DISPLAY_ON_STRING "on"
#define MCE_DISPLAY_OFF_STRING "off"
typedef GObjectClass RilMceClass;
typedef struct ril_mce RilMce;
struct ril_mce_priv {
GRilIoChannel *io;
DBusConnection *conn;
DBusPendingCall *req;
guint daemon_watch;
guint signal_watch;
};
enum ril_mce_signal {
SIGNAL_DISPLAY_STATE_CHANGED,
SIGNAL_COUNT
};
#define SIGNAL_DISPLAY_STATE_CHANGED_NAME "ril-mce-display-state-changed"
static guint ril_mce_signals[SIGNAL_COUNT] = { 0 };
G_DEFINE_TYPE(RilMce, ril_mce, G_TYPE_OBJECT)
#define RIL_MCE_TYPE (ril_mce_get_type())
#define RIL_MCE(obj) (G_TYPE_CHECK_INSTANCE_CAST(obj,RIL_MCE_TYPE,RilMce))
static const char *ril_mce_display_state_string(enum ril_mce_display_state ds)
{
switch (ds) {
case RIL_MCE_DISPLAY_OFF:
return MCE_DISPLAY_OFF_STRING;
case RIL_MCE_DISPLAY_DIM:
return MCE_DISPLAY_DIM_STRING;
case RIL_MCE_DISPLAY_ON:
return MCE_DISPLAY_ON_STRING;
default:
return NULL;
}
}
static enum ril_mce_display_state ril_mce_parse_display_state(DBusMessage *msg)
{
DBusMessageIter it;
if (dbus_message_iter_init(msg, &it) &&
dbus_message_iter_get_arg_type(&it) == DBUS_TYPE_STRING) {
const char *value = NULL;
dbus_message_iter_get_basic(&it, &value);
if (!g_strcmp0(value, MCE_DISPLAY_OFF_STRING)) {
return RIL_MCE_DISPLAY_OFF;
} else if (!g_strcmp0(value, MCE_DISPLAY_DIM_STRING)) {
return RIL_MCE_DISPLAY_DIM;
} else {
GASSERT(!g_strcmp0(value, MCE_DISPLAY_ON_STRING));
}
}
return RIL_MCE_DISPLAY_ON;
}
static void ril_mce_update_display_state(struct ril_mce *self,
enum ril_mce_display_state state)
{
if (self->display_state != state) {
self->display_state = state;
g_signal_emit(self, ril_mce_signals[
SIGNAL_DISPLAY_STATE_CHANGED], 0);
}
}
static gboolean ril_mce_display_changed(DBusConnection *conn,
DBusMessage *msg, void *user_data)
{
enum ril_mce_display_state state = ril_mce_parse_display_state(msg);
DBG("%s", ril_mce_display_state_string(state));
ril_mce_update_display_state(RIL_MCE(user_data), state);
return TRUE;
}
static void ril_mce_display_status_reply(DBusPendingCall *call, void *user_data)
{
struct ril_mce *self = RIL_MCE(user_data);
struct ril_mce_priv *priv = self->priv;
DBusMessage *reply = dbus_pending_call_steal_reply(call);
enum ril_mce_display_state state = ril_mce_parse_display_state(reply);
GASSERT(priv->req);
dbus_message_unref(reply);
dbus_pending_call_unref(priv->req);
priv->req = NULL;
DBG("%s", ril_mce_display_state_string(state));
ril_mce_update_display_state(self, state);
}
static void ril_mce_connect(DBusConnection *conn, void *user_data)
{
struct ril_mce *self = RIL_MCE(user_data);
struct ril_mce_priv *priv = self->priv;
DBG("");
if (!priv->req) {
DBusMessage *msg = dbus_message_new_method_call(MCE_SERVICE,
MCE_REQUEST_PATH, MCE_REQUEST_IF,
MCE_DISPLAY_STATUS_GET);
if (g_dbus_send_message_with_reply(conn, msg, &priv->req, -1)) {
dbus_pending_call_set_notify(priv->req,
ril_mce_display_status_reply,
self, NULL);
dbus_message_unref(msg);
}
}
if (!priv->signal_watch) {
priv->signal_watch = g_dbus_add_signal_watch(conn,
MCE_SERVICE, NULL, MCE_SIGNAL_IF, MCE_DISPLAY_SIG,
ril_mce_display_changed, self, NULL);
}
}
static void ril_mce_disconnect(DBusConnection *conn, void *user_data)
{
struct ril_mce *self = user_data;
struct ril_mce_priv *priv = self->priv;
DBG("");
if (priv->signal_watch) {
g_dbus_remove_watch(conn, priv->signal_watch);
priv->signal_watch = 0;
}
if (priv->req) {
dbus_pending_call_cancel(priv->req);
dbus_pending_call_unref(priv->req);
}
}
struct ril_mce *ril_mce_new()
{
struct ril_mce *self = g_object_new(RIL_MCE_TYPE, NULL);
struct ril_mce_priv *priv = self->priv;
DBG("");
priv->daemon_watch = g_dbus_add_service_watch(priv->conn, MCE_SERVICE,
ril_mce_connect, ril_mce_disconnect, self, NULL);
return self;
}
struct ril_mce *ril_mce_ref(struct ril_mce *self)
{
if (G_LIKELY(self)) {
g_object_ref(RIL_MCE(self));
return self;
} else {
return NULL;
}
}
void ril_mce_unref(struct ril_mce *self)
{
if (G_LIKELY(self)) {
g_object_unref(RIL_MCE(self));
}
}
gulong ril_mce_add_display_state_changed_handler(struct ril_mce *self,
ril_mce_cb_t cb, void *arg)
{
return (G_LIKELY(self) && G_LIKELY(cb)) ? g_signal_connect(self,
SIGNAL_DISPLAY_STATE_CHANGED_NAME, G_CALLBACK(cb), arg) : 0;
}
void ril_mce_remove_handler(struct ril_mce *self, gulong id)
{
if (G_LIKELY(self) && G_LIKELY(id)) {
g_signal_handler_disconnect(self, id);
}
}
static void ril_mce_init(struct ril_mce *self)
{
struct ril_mce_priv *priv = G_TYPE_INSTANCE_GET_PRIVATE(self,
RIL_MCE_TYPE, struct ril_mce_priv);
priv->conn = dbus_connection_ref(ofono_dbus_get_connection());
self->priv = priv;
}
static void ril_mce_dispose(GObject *object)
{
struct ril_mce *self = RIL_MCE(object);
struct ril_mce_priv *priv = self->priv;
if (priv->signal_watch) {
g_dbus_remove_watch(priv->conn, priv->signal_watch);
priv->signal_watch = 0;
}
if (priv->daemon_watch) {
g_dbus_remove_watch(priv->conn, priv->daemon_watch);
priv->daemon_watch = 0;
}
if (priv->req) {
dbus_pending_call_cancel(priv->req);
dbus_pending_call_unref(priv->req);
}
G_OBJECT_CLASS(ril_mce_parent_class)->dispose(object);
}
static void ril_mce_finalize(GObject *object)
{
struct ril_mce *self = RIL_MCE(object);
struct ril_mce_priv *priv = self->priv;
dbus_connection_unref(priv->conn);
G_OBJECT_CLASS(ril_mce_parent_class)->finalize(object);
}
static void ril_mce_class_init(RilMceClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS(klass);
object_class->dispose = ril_mce_dispose;
object_class->finalize = ril_mce_finalize;
g_type_class_add_private(klass, sizeof(struct ril_mce_priv));
ril_mce_signals[SIGNAL_DISPLAY_STATE_CHANGED] =
g_signal_new(SIGNAL_DISPLAY_STATE_CHANGED_NAME,
G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_FIRST,
0, NULL, NULL, NULL, G_TYPE_NONE, 0);
}
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

View File

@@ -1,51 +0,0 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2016 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef RIL_MCE_H
#define RIL_MCE_H
#include "ril_types.h"
enum ril_mce_display_state {
RIL_MCE_DISPLAY_OFF,
RIL_MCE_DISPLAY_DIM,
RIL_MCE_DISPLAY_ON
};
struct ril_mce_priv;
struct ril_mce {
GObject object;
struct ril_mce_priv *priv;
enum ril_mce_display_state display_state;
};
struct ril_mce *ril_mce_new(void);
struct ril_mce *ril_mce_ref(struct ril_mce *mce);
void ril_mce_unref(struct ril_mce *mce);
typedef void (*ril_mce_cb_t)(struct ril_mce *mce, void *arg);
gulong ril_mce_add_display_state_changed_handler(struct ril_mce *mce,
ril_mce_cb_t cb, void *arg);
void ril_mce_remove_handler(struct ril_mce *mce, gulong id);
#endif /* RIL_MCE_H */
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

View File

@@ -18,6 +18,7 @@
#include "ril_radio.h"
#include "ril_sim_card.h"
#include "ril_sim_settings.h"
#include "ril_cell_info.h"
#include "ril_data.h"
#include "ril_util.h"
#include "ril_log.h"
@@ -50,11 +51,12 @@ struct ril_modem_online_request {
struct ril_modem_data {
struct ril_modem modem;
GRilIoQueue *q;
struct ofono_radio_settings *radio_settings;
char *log_prefix;
char *imei;
char *ecclist_file;
gboolean pre_sim_done;
gboolean allow_data;
gulong sim_imsi_event_id;
guint online_check_id;
enum ril_modem_power_state power_state;
@@ -72,6 +74,8 @@ struct ril_modem_data {
#define RADIO_POWER_TAG(md) (md)
#define DBG_(md,fmt,args...) DBG("%s" fmt, (md)->log_prefix, ##args)
static struct ril_modem_data *ril_modem_data_from_ofono(struct ofono_modem *o)
{
struct ril_modem_data *md = ofono_modem_get_data(o);
@@ -114,6 +118,12 @@ struct ofono_netreg *ril_modem_ofono_netreg(struct ril_modem *modem)
return ril_modem_get_atom_data(modem, OFONO_ATOM_TYPE_NETREG);
}
static inline struct ofono_radio_settings *ril_modem_radio_settings(
struct ril_modem *modem)
{
return ril_modem_get_atom_data(modem, OFONO_ATOM_TYPE_RADIO_SETTINGS);
}
void ril_modem_delete(struct ril_modem *md)
{
if (md && md->ofono) {
@@ -222,17 +232,23 @@ static void ril_modem_schedule_online_check(struct ril_modem_data *md)
static void ril_modem_update_radio_settings(struct ril_modem_data *md)
{
if (md->modem.radio->state == RADIO_STATE_ON) {
if (!md->radio_settings) {
DBG("Initializing radio settings interface");
md->radio_settings =
ofono_radio_settings_create(md->modem.ofono, 0,
RILMODEM_DRIVER, md);
struct ril_modem *m = &md->modem;
if (m->radio->state == RADIO_STATE_ON && m->sim_settings->imsi) {
/* radio-settings.c assumes that IMSI is available */
if (!ril_modem_radio_settings(m)) {
DBG_(md, "initializing radio settings interface");
ofono_radio_settings_create(m->ofono, 0,
RILMODEM_DRIVER, md);
}
} else {
/* ofono core may remove radio settings atom internally */
struct ofono_radio_settings *rs = ril_modem_radio_settings(m);
if (rs) {
DBG_(md, "removing radio settings interface");
ofono_radio_settings_remove(rs);
} else {
DBG_(md, "radio settings interface is already gone");
}
} else if (md->radio_settings) {
DBG("Removing radio settings interface");
ofono_radio_settings_remove(md->radio_settings);
md->radio_settings = NULL;
}
}
@@ -245,6 +261,14 @@ static void ril_modem_radio_state_cb(struct ril_radio *radio, void *data)
ril_modem_update_online_state(md);
}
static void ril_modem_imsi_cb(struct ril_sim_settings *settings, void *data)
{
struct ril_modem_data *md = data;
GASSERT(md->modem.sim_settings == settings);
ril_modem_update_radio_settings(md);
}
static void ril_modem_pre_sim(struct ofono_modem *modem)
{
struct ril_modem_data *md = ril_modem_data_from_ofono(modem);
@@ -254,7 +278,6 @@ static void ril_modem_pre_sim(struct ofono_modem *modem)
ofono_devinfo_create(modem, 0, RILMODEM_DRIVER, md);
ofono_sim_create(modem, 0, RILMODEM_DRIVER, md);
ofono_voicecall_create(modem, 0, RILMODEM_DRIVER, md);
ril_modem_update_radio_settings(md);
if (!md->radio_state_event_id) {
md->radio_state_event_id =
ril_radio_add_state_changed_handler(md->modem.radio,
@@ -288,6 +311,7 @@ static void ril_modem_post_sim(struct ofono_modem *modem)
ofono_call_forwarding_create(modem, 0, RILMODEM_DRIVER, md);
ofono_call_barring_create(modem, 0, RILMODEM_DRIVER, md);
ofono_stk_create(modem, 0, RILMODEM_DRIVER, md);
ofono_cbs_create(modem, 0, RILMODEM_DRIVER, md);
ofono_message_waiting_register(ofono_message_waiting_create(modem));
}
@@ -300,7 +324,7 @@ static void ril_modem_post_online(struct ofono_modem *modem)
ofono_netreg_create(modem, 0, RILMODEM_DRIVER, md);
ofono_ussd_create(modem, 0, RILMODEM_DRIVER, md);
ofono_call_settings_create(modem, 0, RILMODEM_DRIVER, md);
ofono_oem_raw_create(modem, 0, RILMODEM_DRIVER, md);
ofono_netmon_create(modem, 0, RILMODEM_DRIVER, md);
}
static void ril_modem_set_online(struct ofono_modem *modem, ofono_bool_t online,
@@ -384,6 +408,10 @@ static void ril_modem_remove(struct ofono_modem *ofono)
ril_radio_power_off(modem->radio, RADIO_POWER_TAG(md));
ril_radio_unref(modem->radio);
ril_sim_settings_remove_handler(modem->sim_settings,
md->sim_imsi_event_id);
ril_sim_settings_unref(modem->sim_settings);
if (md->online_check_id) {
g_source_remove(md->online_check_id);
}
@@ -398,12 +426,13 @@ static void ril_modem_remove(struct ofono_modem *ofono)
ril_network_unref(modem->network);
ril_sim_card_unref(modem->sim_card);
ril_sim_settings_unref(modem->sim_settings);
ril_cell_info_unref(modem->cell_info);
ril_data_unref(modem->data);
grilio_channel_unref(modem->io);
grilio_queue_cancel_all(md->q, FALSE);
grilio_queue_unref(md->q);
g_free(md->ecclist_file);
g_free(md->log_prefix);
g_free(md->imei);
g_free(md);
}
@@ -411,7 +440,8 @@ static void ril_modem_remove(struct ofono_modem *ofono)
struct ril_modem *ril_modem_create(GRilIoChannel *io, const char *log_prefix,
const struct ril_slot_info *slot, struct ril_radio *radio,
struct ril_network *network, struct ril_sim_card *card,
struct ril_data *data, struct ril_sim_settings *settings)
struct ril_data *data, struct ril_sim_settings *settings,
struct ril_cell_info *cell_info)
{
/* Skip the slash from the path, it looks like "/ril_0" */
struct ofono_modem *ofono = ofono_modem_create(slot->path + 1,
@@ -433,15 +463,28 @@ struct ril_modem *ril_modem_create(GRilIoChannel *io, const char *log_prefix,
modem->log_prefix = log_prefix;
modem->ecclist_file =
md->ecclist_file = g_strdup(slot->ecclist_file);
md->log_prefix = (log_prefix && log_prefix[0]) ?
g_strconcat(log_prefix, " ", NULL) : g_strdup("");
modem->ofono = ofono;
modem->radio = ril_radio_ref(radio);
modem->network = ril_network_ref(network);
modem->sim_card = ril_sim_card_ref(card);
modem->sim_settings = ril_sim_settings_ref(settings);
modem->cell_info = ril_cell_info_ref(cell_info);
modem->data = ril_data_ref(data);
modem->io = grilio_channel_ref(io);
md->q = grilio_queue_new(io);
/*
* modem->sim_settings->imsi follows IMSI known to the ofono
* core, unlike ril_sim_info->imsi which may point to the
* cached IMSI even before the PIN code is entered.
*/
md->sim_imsi_event_id =
ril_sim_settings_add_imsi_changed_handler(settings,
ril_modem_imsi_cb, md);
md->set_online.md = md;
md->set_offline.md = md;
ofono_modem_set_data(ofono, md);
@@ -457,6 +500,17 @@ struct ril_modem *ril_modem_create(GRilIoChannel *io, const char *log_prefix,
ofono_modem_set_powered(modem->ofono, FALSE);
ofono_modem_set_powered(modem->ofono, TRUE);
md->power_state = POWERED_ON;
/*
* With some RIL implementations, querying available
* band modes causes some magic Android properties to
* appear. Otherwise this request is pretty harmless
* and useless.
*/
grilio_queue_send_request(md->q, NULL,
RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE);
ril_modem_update_radio_settings(md);
return modem;
} else {
ofono_error("Error %d registering %s",

View File

@@ -0,0 +1,202 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2016 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "ril_plugin.h"
#include "ril_cell_info.h"
#include "ril_util.h"
#include "ril_log.h"
#include "ofono.h"
struct ril_netmon {
struct ofono_netmon *netmon;
struct ril_cell_info *cell_info;
guint register_id;
};
static inline struct ril_netmon *ril_netmon_get_data(struct ofono_netmon *ofono)
{
return ofono ? ofono_netmon_get_data(ofono) : NULL;
}
static void ril_netmon_format_mccmnc(char *s_mcc, char *s_mnc, int mcc, int mnc)
{
s_mcc[0] = 0;
s_mnc[0] = 0;
if (mcc >= 0 && mcc <= 999) {
snprintf(s_mcc, OFONO_MAX_MCC_LENGTH + 1, "%03d", mcc);
if (mnc >= 0 && mnc <= 999) {
const int mnclen = mnclength(mcc, mnc);
const char *format[] = { "%d", "%02d", "%03d" };
const char *fmt = (mnclen > 0 &&
mnclen <= G_N_ELEMENTS(format)) ?
format[mnclen - 1] : format[0];
snprintf(s_mnc, OFONO_MAX_MNC_LENGTH + 1, fmt, mnc);
}
}
}
static void ril_netmon_notify_gsm(struct ofono_netmon *netmon,
const struct ril_cell_info_gsm *gsm)
{
char mcc[OFONO_MAX_MCC_LENGTH + 1];
char mnc[OFONO_MAX_MNC_LENGTH + 1];
ril_netmon_format_mccmnc(mcc, mnc, gsm->mcc, gsm->mnc);
ofono_netmon_serving_cell_notify(netmon,
OFONO_NETMON_CELL_TYPE_GSM,
OFONO_NETMON_INFO_MCC, mcc,
OFONO_NETMON_INFO_MNC, mnc,
OFONO_NETMON_INFO_LAC, gsm->lac,
OFONO_NETMON_INFO_CI, gsm->cid,
OFONO_NETMON_INFO_RSSI, gsm->signalStrength,
OFONO_NETMON_INFO_BER, gsm->bitErrorRate,
OFONO_NETMON_INFO_INVALID);
}
static void ril_netmon_notify_wcdma(struct ofono_netmon *netmon,
const struct ril_cell_info_wcdma *wcdma)
{
char mcc[OFONO_MAX_MCC_LENGTH + 1];
char mnc[OFONO_MAX_MNC_LENGTH + 1];
ril_netmon_format_mccmnc(mcc, mnc, wcdma->mcc, wcdma->mnc);
ofono_netmon_serving_cell_notify(netmon,
OFONO_NETMON_CELL_TYPE_UMTS,
OFONO_NETMON_INFO_MCC, mcc,
OFONO_NETMON_INFO_MNC, mnc,
OFONO_NETMON_INFO_LAC, wcdma->lac,
OFONO_NETMON_INFO_CI, wcdma->cid,
OFONO_NETMON_INFO_PSC, wcdma->psc,
OFONO_NETMON_INFO_RSSI, wcdma->signalStrength,
OFONO_NETMON_INFO_BER, wcdma->bitErrorRate,
OFONO_NETMON_INFO_INVALID);
}
static void ril_netmon_notify_lte(struct ofono_netmon *netmon,
const struct ril_cell_info_lte *lte)
{
char mcc[OFONO_MAX_MCC_LENGTH + 1];
char mnc[OFONO_MAX_MNC_LENGTH + 1];
ril_netmon_format_mccmnc(mcc, mnc, lte->mcc, lte->mnc);
ofono_netmon_serving_cell_notify(netmon,
OFONO_NETMON_CELL_TYPE_LTE,
OFONO_NETMON_INFO_MCC, mcc,
OFONO_NETMON_INFO_MNC, mnc,
OFONO_NETMON_INFO_CI, lte->ci,
OFONO_NETMON_INFO_RSSI, lte->signalStrength,
OFONO_NETMON_INFO_TIMING_ADVANCE, lte->timingAdvance,
OFONO_NETMON_INFO_INVALID);
}
static void ril_netmon_request_update(struct ofono_netmon *netmon,
ofono_netmon_cb_t cb, void *data)
{
struct ril_netmon *nm = ril_netmon_get_data(netmon);
struct ofono_error error;
GSList *l;
for (l = nm->cell_info->cells; l; l = l->next) {
const struct ril_cell *cell = l->data;
if (cell->registered) {
switch (cell->type) {
case RIL_CELL_INFO_TYPE_GSM:
ril_netmon_notify_gsm(netmon,
&cell->info.gsm);
break;
case RIL_CELL_INFO_TYPE_WCDMA:
ril_netmon_notify_wcdma(netmon,
&cell->info.wcdma);
break;
case RIL_CELL_INFO_TYPE_LTE:
ril_netmon_notify_lte(netmon,
&cell->info.lte);
break;
default:
break;
}
}
}
cb(ril_error_ok(&error), data);
}
static gboolean ril_netmon_register(gpointer user_data)
{
struct ril_netmon *nm = user_data;
GASSERT(nm->register_id);
nm->register_id = 0;
ofono_netmon_register(nm->netmon);
return G_SOURCE_REMOVE;
}
static int ril_netmon_probe(struct ofono_netmon *netmon, unsigned int vendor,
void *data)
{
struct ril_modem *modem = data;
int ret;
if (modem->cell_info) {
struct ril_netmon *nm = g_slice_new0(struct ril_netmon);
nm->cell_info = ril_cell_info_ref(modem->cell_info);
nm->netmon = netmon;
ofono_netmon_set_data(netmon, nm);
nm->register_id = g_idle_add(ril_netmon_register, nm);
ret = 0;
} else {
DBG("%s no", modem->log_prefix ? modem->log_prefix : "");
ret = -1;
}
DBG("%s %d", modem->log_prefix ? modem->log_prefix : "", ret);
return ret;
}
static void ril_netmon_remove(struct ofono_netmon *netmon)
{
struct ril_netmon *nm = ril_netmon_get_data(netmon);
DBG("");
ofono_netmon_set_data(netmon, NULL);
if (nm->register_id > 0) {
g_source_remove(nm->register_id);
}
ril_cell_info_unref(nm->cell_info);
g_slice_free(struct ril_netmon, nm);
}
const struct ofono_netmon_driver ril_netmon_driver = {
.name = RILMODEM_DRIVER,
.probe = ril_netmon_probe,
.remove = ril_netmon_remove,
.request_update = ril_netmon_request_update,
};
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2016 Jolla Ltd.
* Copyright (C) 2015-2017 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -196,7 +196,7 @@ static gboolean ril_network_parse_response(struct ril_network *self,
* supply some reasonable default. We don't need more than 2
* simultaneous data calls anyway.
*/
if (nparams <= 5) {
if (reg->max_calls < 1) {
reg->max_calls = 2;
}
@@ -420,13 +420,16 @@ static int ril_network_mode_to_rat(struct ril_network *self,
switch (mode) {
case OFONO_RADIO_ACCESS_MODE_ANY:
case OFONO_RADIO_ACCESS_MODE_LTE:
if (self->settings->enable_4g) {
if (self->settings->techs & OFONO_RADIO_ACCESS_MODE_LTE) {
return PREF_NET_TYPE_LTE_GSM_WCDMA;
}
/* no break */
default:
case OFONO_RADIO_ACCESS_MODE_UMTS:
return PREF_NET_TYPE_GSM_WCDMA_AUTO;
if (self->settings->techs & OFONO_RADIO_ACCESS_MODE_UMTS) {
return PREF_NET_TYPE_GSM_WCDMA_AUTO;
}
/* no break */
case OFONO_RADIO_ACCESS_MODE_GSM:
return PREF_NET_TYPE_GSM_ONLY;
}
@@ -436,9 +439,30 @@ static int ril_network_pref_mode_expected(struct ril_network *self)
{
struct ril_sim_settings *settings = self->settings;
struct ril_network_priv *priv = self->priv;
const enum ofono_radio_access_mode pref_mode = priv->max_pref_mode ?
MIN(settings->pref_mode, priv->max_pref_mode) :
settings->pref_mode;
/*
* On dual-SIM phones such as Jolla C only one slot at a time
* is allowed to use LTE. Even if the slot which has been using
* LTE gets powered off, we still need to explicitely set its
* preferred mode to GSM, to make LTE machinery available to
* the other slot. This sort of behaviour might not be necessary
* on some hardware and can (should) be made configurable when
* it becomes necessary.
*/
const enum ofono_radio_access_mode max_pref_mode =
(priv->radio->state == RADIO_STATE_ON) ? priv->max_pref_mode :
OFONO_RADIO_ACCESS_MODE_GSM;
/*
* OFONO_RADIO_ACCESS_MODE_ANY is zero. If both pref_mode
* and max_pref_mode are not ANY, we pick the smallest value.
* Otherwise we take any non-zero value if there is one.
*/
const enum ofono_radio_access_mode pref_mode =
(settings->pref_mode && max_pref_mode) ?
MIN(settings->pref_mode, max_pref_mode) :
settings->pref_mode ? settings->pref_mode :
max_pref_mode;
return ril_network_mode_to_rat(self, pref_mode);
}
@@ -555,6 +579,31 @@ static int ril_network_parse_pref_resp(const void *data, guint len)
return pref;
}
static void ril_network_startup_query_pref_mode_cb(GRilIoChannel *io,
int status, const void *data, guint len, void *user_data)
{
if (status == RIL_E_SUCCESS) {
struct ril_network *self = RIL_NETWORK(user_data);
struct ril_network_priv *priv = self->priv;
const enum ofono_radio_access_mode pref_mode = self->pref_mode;
priv->rat = ril_network_parse_pref_resp(data, len);
self->pref_mode = ril_network_rat_to_mode(priv->rat);
DBG_(self, "rat mode %d (%s)", priv->rat,
ofono_radio_access_mode_to_string(self->pref_mode));
if (self->pref_mode != pref_mode) {
ril_network_emit(self, SIGNAL_PREF_MODE_CHANGED);
}
/*
* Unlike ril_network_query_pref_mode_cb, this one always
* checks the preferred mode.
*/
ril_network_check_pref_mode(self, FALSE);
}
}
static void ril_network_query_pref_mode_cb(GRilIoChannel *io, int status,
const void *data, guint len, void *user_data)
{
@@ -661,8 +710,11 @@ static void ril_network_voice_state_changed_cb(GRilIoChannel *io, guint code,
static void ril_network_radio_state_cb(struct ril_radio *radio, void *data)
{
struct ril_network *self = RIL_NETWORK(data);
ril_network_check_pref_mode(self, FALSE);
if (radio->state == RADIO_STATE_ON) {
ril_network_poll_state(RIL_NETWORK(data));
ril_network_poll_state(self);
}
}
@@ -753,6 +805,9 @@ struct ril_network *ril_network_new(GRilIoChannel *io, const char *log_prefix,
* Query the initial state. Querying network state before the radio
* has been turned on makes RIL unhappy.
*/
grilio_queue_send_request_full(priv->q, NULL,
RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE,
ril_network_startup_query_pref_mode_cb, NULL, self);
if (radio->state == RADIO_STATE_ON) {
ril_network_poll_state(self);
}

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015 Jolla Ltd.
* Copyright (C) 2015-2016 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -16,118 +16,147 @@
#include "ril_plugin.h"
#include "ril_util.h"
#include "ril_log.h"
#include "ril_constants.h"
#include "gdbus.h"
#include "ofono.h"
#define RIL_OEM_RAW_INTERFACE "org.ofono.OemRaw"
#define RIL_OEM_RAW_TIMEOUT (60*1000) /* 60 sec */
struct ril_oem_raw {
struct ril_modem *modem;
GRilIoQueue *q;
guint timer_id;
DBusConnection *conn;
char *path;
char *log_prefix;
};
struct ril_oem_raw_cbd {
ofono_oem_raw_query_cb_t cb;
gpointer data;
};
#define DBG_(oem,fmt,args...) DBG("%s" fmt, (oem)->log_prefix, ##args)
#define ril_oem_raw_cbd_free g_free
static inline struct ril_oem_raw *ril_oem_raw_get_data(
struct ofono_oem_raw *raw)
{
return ofono_oem_raw_get_data(raw);
}
static struct ril_oem_raw_cbd *ril_oem_raw_cbd_new(ofono_oem_raw_query_cb_t cb,
void *data)
{
struct ril_oem_raw_cbd *cbd = g_new0(struct ril_oem_raw_cbd, 1);
cbd->cb = cb;
cbd->data = data;
return cbd;
}
static void ril_oem_raw_request_cb(GRilIoChannel *io, int status,
static void ril_oem_raw_send_cb(GRilIoChannel *io, int ril_status,
const void *data, guint len, void *user_data)
{
struct ofono_error error;
struct ril_oem_raw_cbd *cbd = user_data;
DBusMessage *msg = user_data;
DBusMessage *reply;
if (status == RIL_E_SUCCESS) {
struct ofono_oem_raw_results result;
if (ril_status == RIL_E_SUCCESS) {
DBusMessageIter it, array;
const guchar* bytes = data;
guint i;
result.data = (void *)data;
result.length = len;
cbd->cb(ril_error_ok(&error), &result, cbd->data);
reply = dbus_message_new_method_return(msg);
dbus_message_iter_init_append(reply, &it);
dbus_message_iter_open_container(&it, DBUS_TYPE_ARRAY,
DBUS_TYPE_BYTE_AS_STRING, &array);
for (i = 0; i < len; i++) {
guchar byte = bytes[i];
dbus_message_iter_append_basic(&array, DBUS_TYPE_BYTE,
&byte);
}
dbus_message_iter_close_container(&it, &array);
} else if (ril_status == GRILIO_STATUS_TIMEOUT) {
DBG("Timed out");
reply = __ofono_error_timed_out(msg);
} else {
DBG("error:%d len:%d ", status, len);
cbd->cb(ril_error_failure(&error), NULL, cbd->data);
DBG("Error %s", ril_error_to_string(ril_status));
reply = __ofono_error_failed(msg);
}
__ofono_dbus_pending_reply(&msg, reply);
}
static DBusMessage *ril_oem_raw_send(DBusConnection *conn, DBusMessage *msg,
void *user_data)
{
DBusMessageIter it;
struct ril_oem_raw *oem = user_data;
dbus_message_iter_init(msg, &it);
if (dbus_message_iter_get_arg_type(&it) == DBUS_TYPE_ARRAY &&
dbus_message_iter_get_element_type(&it) == DBUS_TYPE_BYTE) {
char *data;
int data_len;
DBusMessageIter array;
GRilIoRequest *req;
/* Fetch the data */
dbus_message_iter_recurse(&it, &array);
dbus_message_iter_get_fixed_array(&array, &data, &data_len);
DBG_(oem, "%d bytes", data_len);
/*
* And forward it to rild. Set a timeout because rild may
* never respond to invalid requests.
*/
req = grilio_request_sized_new(data_len);
grilio_request_set_timeout(req, RIL_OEM_RAW_TIMEOUT);
grilio_request_append_bytes(req, data, data_len);
grilio_queue_send_request_full(oem->q, req,
RIL_REQUEST_OEM_HOOK_RAW, ril_oem_raw_send_cb,
NULL, dbus_message_ref(msg));
grilio_request_unref(req);
return NULL;
} else {
DBG_(oem, "Unexpected signature");
return __ofono_error_invalid_args(msg);
}
}
static void ril_oem_raw_request(struct ofono_oem_raw *raw,
const struct ofono_oem_raw_request *request,
ofono_oem_raw_query_cb_t cb, void *data)
{
struct ril_oem_raw *od = ril_oem_raw_get_data(raw);
GRilIoRequest *req = grilio_request_sized_new(request->length);
grilio_request_append_bytes(req, request->data, request->length);
grilio_queue_send_request_full(od->q, req, RIL_REQUEST_OEM_HOOK_RAW,
ril_oem_raw_request_cb, ril_oem_raw_cbd_free,
ril_oem_raw_cbd_new(cb, data));
grilio_request_unref(req);
}
static gboolean ril_oem_raw_register(gpointer user_data)
{
struct ofono_oem_raw *raw = user_data;
struct ril_oem_raw *od = ril_oem_raw_get_data(raw);
DBG("");
GASSERT(od->timer_id);
od->timer_id = 0;
ofono_oem_raw_dbus_register(raw);
/* Single-shot */
return FALSE;
}
static int ril_oem_raw_probe(struct ofono_oem_raw *raw, unsigned int vendor,
void *data)
{
struct ril_modem *modem = data;
struct ril_oem_raw *od = g_new0(struct ril_oem_raw, 1);
DBG("");
od->q = grilio_queue_new(ril_modem_io(modem));
od->timer_id = g_idle_add(ril_oem_raw_register, raw);
ofono_oem_raw_set_data(raw, od);
return 0;
}
static void ril_oem_raw_remove(struct ofono_oem_raw *raw)
{
struct ril_oem_raw *od = ril_oem_raw_get_data(raw);
DBG("");
grilio_queue_cancel_all(od->q, TRUE);
ofono_oem_raw_set_data(raw, NULL);
if (od->timer_id) {
g_source_remove(od->timer_id);
}
grilio_queue_unref(od->q);
g_free(od);
}
/* const */ struct ofono_oem_raw_driver ril_oem_raw_driver = {
.name = RILMODEM_DRIVER,
.probe = ril_oem_raw_probe,
.remove = ril_oem_raw_remove,
.request = ril_oem_raw_request,
static const GDBusMethodTable ril_oem_raw_methods[] = {
{ GDBUS_ASYNC_METHOD("Send",
GDBUS_ARGS({ "request", "ay" }),
GDBUS_ARGS({ "response", "ay" }),
ril_oem_raw_send) },
{ }
};
struct ril_oem_raw *ril_oem_raw_new(struct ril_modem *modem,
const char *log_prefix)
{
struct ril_oem_raw *oem = g_new0(struct ril_oem_raw, 1);
DBG("%s", ril_modem_get_path(modem));
oem->modem = modem;
oem->path = g_strdup(ril_modem_get_path(modem));
oem->conn = dbus_connection_ref(ofono_dbus_get_connection());
oem->q = grilio_queue_new(ril_modem_io(modem));
oem->log_prefix = (log_prefix && log_prefix[0]) ?
g_strconcat(log_prefix, " ", NULL) : g_strdup("");
/* Register D-Bus interface */
if (g_dbus_register_interface(oem->conn, oem->path,
RIL_OEM_RAW_INTERFACE, ril_oem_raw_methods,
NULL, NULL, oem, NULL)) {
ofono_modem_add_interface(modem->ofono, RIL_OEM_RAW_INTERFACE);
return oem;
} else {
ofono_error("OemRaw D-Bus register failed");
ril_oem_raw_free(oem);
return NULL;
}
}
void ril_oem_raw_free(struct ril_oem_raw *oem)
{
if (oem) {
DBG("%s", oem->path);
g_dbus_unregister_interface(oem->conn, oem->path,
RIL_OEM_RAW_INTERFACE);
ofono_modem_remove_interface(oem->modem->ofono,
RIL_OEM_RAW_INTERFACE);
dbus_connection_unref(oem->conn);
grilio_queue_cancel_all(oem->q, TRUE);
grilio_queue_unref(oem->q);
g_free(oem->log_prefix);
g_free(oem->path);
g_free(oem);
}
}
/*
* Local Variables:
* mode: C

View File

@@ -4,8 +4,8 @@
*
* Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
* Copyright (C) ST-Ericsson SA 2010.
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2013 Jolla Ltd
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2013-2016 Jolla Ltd
* Contact: Jussi Kangas <jussi.kangas@tieto.com>
* Copyright (C) 2014 Canonical Ltd
*
@@ -17,11 +17,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include "ril_plugin.h"
@@ -31,24 +26,6 @@
#include "simutil.h"
#include "util.h"
struct cb_data {
void *cb;
void *data;
void *user;
};
static inline struct cb_data *cb_data_new(void *cb, void *data, void *user)
{
struct cb_data *ret;
ret = g_new0(struct cb_data, 1);
ret->cb = cb;
ret->data = data;
ret->user = user;
return ret;
}
#define CALLBACK_WITH_FAILURE(cb, args...) \
do { \
struct ofono_error cb_e; \
@@ -153,7 +130,10 @@ struct pb_data {
struct ofono_sim *sim;
struct ofono_sim_context *sim_context;
const unsigned char *df_path;
guint register_id;
size_t df_size;
ofono_phonebook_cb_t cb;
void *cb_data;
};
static void read_info_cb(int ok, unsigned char file_status,
@@ -587,6 +567,20 @@ static void decode_read_response(const struct record_to_read *rec_data,
}
}
static gboolean free_entry(gpointer key, gpointer value, gpointer data)
{
struct phonebook_entry *entry = value;
g_free(entry->name);
g_free(entry->number);
g_free(entry->email);
g_free(entry->anr);
g_free(entry->sne);
g_free(entry);
return FALSE;
}
static gboolean export_entry(gpointer key, gpointer value, gpointer data)
{
struct ofono_phonebook *pb = data;
@@ -601,29 +595,18 @@ static gboolean export_entry(gpointer key, gpointer value, gpointer data)
entry->email,
NULL, NULL);
g_free(entry->name);
g_free(entry->number);
g_free(entry->email);
g_free(entry->anr);
g_free(entry->sne);
g_free(entry);
return FALSE;
return free_entry(key, value, NULL);
}
static void export_and_return(gboolean ok, struct cb_data *cbd)
static void free_pb_refs(struct pb_data *pbd, GTraverseFunc entry_func,
struct ofono_phonebook *pb)
{
struct ofono_phonebook *pb = cbd->user;
ofono_phonebook_cb_t cb = cbd->cb;
struct pb_data *pbd = ofono_phonebook_get_data(pb);
GSList *l;
DBG("phonebook fully read");
for (l = pbd->pb_refs; l != NULL; l = l->next) {
struct pb_ref_rec *ref = l->data;
g_tree_foreach(ref->phonebook, export_entry, pb);
g_tree_foreach(ref->phonebook, entry_func, pb);
g_tree_destroy(ref->phonebook);
g_slist_free_full(ref->pending_records, g_free);
g_slist_free_full(ref->pb_files, g_free);
@@ -631,28 +614,38 @@ static void export_and_return(gboolean ok, struct cb_data *cbd)
g_slist_free_full(pbd->pb_refs, g_free);
pbd->pb_refs = NULL;
}
if (ok)
CALLBACK_WITH_SUCCESS(cb, cbd->data);
else
CALLBACK_WITH_FAILURE(cb, cbd->data);
static void export_and_return(struct ofono_phonebook *pb, gboolean ok)
{
struct pb_data *pbd = ofono_phonebook_get_data(pb);
g_free(cbd);
DBG("phonebook fully read");
free_pb_refs(pbd, export_entry, pb);
if (pbd->cb) {
if (ok) {
CALLBACK_WITH_SUCCESS(pbd->cb, pbd->cb_data);
} else {
CALLBACK_WITH_FAILURE(pbd->cb, pbd->cb_data);
}
pbd->cb = NULL;
pbd->cb_data = NULL;
}
}
static void read_record_cb(int ok, int total_length, int record,
const unsigned char *data,
int record_length, void *userdata)
{
struct cb_data *cbd = userdata;
struct ofono_phonebook *pb = cbd->user;
struct ofono_phonebook *pb = userdata;
struct pb_data *pbd = ofono_phonebook_get_data(pb);
struct pb_ref_rec *ref = pbd->pb_ref_next->data;
struct record_to_read *rec;
if (!ok) {
ofono_error("%s: error %d", __func__, ok);
export_and_return(FALSE, cbd);
export_and_return(pb, FALSE);
return;
}
@@ -678,13 +671,13 @@ static void read_record_cb(int ok, int total_length, int record,
rec->record,
rec->record_length,
pbd->df_path, pbd->df_size,
read_record_cb, cbd);
read_record_cb, pb);
} else {
/* Read files from next EF_PBR record, if any */
pbd->pb_ref_next = pbd->pb_ref_next->next;
if (pbd->pb_ref_next == NULL) {
export_and_return(TRUE, cbd);
export_and_return(pb, TRUE);
} else {
struct pb_ref_rec *ref;
@@ -693,7 +686,7 @@ static void read_record_cb(int ok, int total_length, int record,
ref = pbd->pb_ref_next->data;
if (!ref->pb_files) {
export_and_return(TRUE, cbd);
export_and_return(pb, TRUE);
} else {
struct pb_file_info *file_info;
@@ -704,7 +697,7 @@ static void read_record_cb(int ok, int total_length, int record,
file_info->file_id,
OFONO_SIM_FILE_STRUCTURE_FIXED,
pbd->df_path, pbd->df_size,
read_info_cb, cbd);
read_info_cb, pb);
}
}
}
@@ -714,15 +707,14 @@ static void pb_adn_cb(int ok, int total_length, int record,
const unsigned char *data,
int record_length, void *userdata)
{
struct cb_data *cbd = userdata;
struct ofono_phonebook *pb = cbd->user;
struct ofono_phonebook *pb = userdata;
struct pb_data *pbd = ofono_phonebook_get_data(pb);
struct pb_ref_rec *ref = pbd->pb_ref_next->data;
GSList *l;
if (!ok) {
ofono_error("%s: error %d", __func__, ok);
export_and_return(FALSE, cbd);
export_and_return(pb, FALSE);
return;
}
@@ -768,9 +760,9 @@ static void pb_adn_cb(int ok, int total_length, int record,
rec->record,
rec->record_length,
pbd->df_path, pbd->df_size,
read_record_cb, cbd);
read_record_cb, pb);
} else {
export_and_return(TRUE, cbd);
export_and_return(pb, TRUE);
}
}
}
@@ -779,8 +771,7 @@ static void read_info_cb(int ok, unsigned char file_status,
int total_length, int record_length,
void *userdata)
{
struct cb_data *cbd = userdata;
struct ofono_phonebook *pb = cbd->user;
struct ofono_phonebook *pb = userdata;
struct pb_data *pbd = ofono_phonebook_get_data(pb);
struct pb_file_info *file_info;
struct pb_ref_rec *ref = pbd->pb_ref_next->data;
@@ -803,7 +794,7 @@ static void read_info_cb(int ok, unsigned char file_status,
if (ref->pb_next == NULL) {
if (ref->pb_files == NULL) {
ofono_warn("%s: no phonebook on SIM", __func__);
export_and_return(FALSE, cbd);
export_and_return(pb, FALSE);
return;
}
@@ -813,20 +804,19 @@ static void read_info_cb(int ok, unsigned char file_status,
ofono_sim_read_path(pbd->sim_context, file_info->file_id,
OFONO_SIM_FILE_STRUCTURE_FIXED,
pbd->df_path, pbd->df_size,
pb_adn_cb, cbd);
pb_adn_cb, pb);
} else {
file_info = ref->pb_next->data;
ofono_sim_read_info(pbd->sim_context, file_info->file_id,
OFONO_SIM_FILE_STRUCTURE_FIXED,
pbd->df_path, pbd->df_size,
read_info_cb, cbd);
read_info_cb, pb);
}
}
static void start_sim_app_read(struct cb_data *cbd)
static void start_sim_app_read(struct ofono_phonebook *pb)
{
struct ofono_phonebook *pb = cbd->user;
struct pb_data *pbd = ofono_phonebook_get_data(pb);
struct pb_ref_rec *ref_rec;
struct pb_file_info *f_info;
@@ -838,7 +828,7 @@ static void start_sim_app_read(struct cb_data *cbd)
ref_rec = g_try_malloc0(sizeof(*ref_rec));
if (ref_rec == NULL) {
ofono_error("%s: OOM", __func__);
export_and_return(FALSE, cbd);
export_and_return(pb, FALSE);
return;
}
@@ -849,7 +839,7 @@ static void start_sim_app_read(struct cb_data *cbd)
f_info = g_try_malloc0(sizeof(*f_info));
if (f_info == NULL) {
ofono_error("%s: OOM", __func__);
export_and_return(FALSE, cbd);
export_and_return(pb, FALSE);
return;
}
@@ -861,7 +851,7 @@ static void start_sim_app_read(struct cb_data *cbd)
f_ext1 = g_try_malloc0(sizeof(*f_ext1));
if (f_ext1 == NULL) {
ofono_error("%s: OOM", __func__);
export_and_return(FALSE, cbd);
export_and_return(pb, FALSE);
return;
}
@@ -879,15 +869,14 @@ static void start_sim_app_read(struct cb_data *cbd)
ofono_sim_read_info(pbd->sim_context, f_info->file_id,
OFONO_SIM_FILE_STRUCTURE_FIXED,
pbd->df_path, pbd->df_size,
read_info_cb, cbd);
read_info_cb, pb);
}
static void pb_reference_data_cb(int ok, int total_length, int record,
const unsigned char *sdata,
int record_length, void *userdata)
{
struct cb_data *cbd = userdata;
struct ofono_phonebook *pb = cbd->user;
struct ofono_phonebook *pb = userdata;
struct pb_data *pbd = ofono_phonebook_get_data(pb);
const unsigned char *ptr = sdata;
gboolean finished = FALSE;
@@ -899,14 +888,14 @@ static void pb_reference_data_cb(int ok, int total_length, int record,
if (!ok) {
/* We migh have a SIM instead of USIM application: try that */
DBG("%s: error %d, trying SIM files", __func__, ok);
start_sim_app_read(cbd);
start_sim_app_read(pb);
return;
}
ref_rec = g_try_malloc0(sizeof(*ref_rec));
if (ref_rec == NULL) {
ofono_error("%s: OOM", __func__);
export_and_return(FALSE, cbd);
export_and_return(pb, FALSE);
return;
}
@@ -930,7 +919,7 @@ static void pb_reference_data_cb(int ok, int total_length, int record,
g_try_new0(struct pb_file_info, 1);
if (!file_info) {
ofono_error("%s: OOM", __func__);
export_and_return(FALSE, cbd);
export_and_return(pb, FALSE);
return;
}
@@ -972,7 +961,7 @@ static void pb_reference_data_cb(int ok, int total_length, int record,
if (ref->pb_files == NULL) {
ofono_error("%s: no files to read", __func__);
export_and_return(FALSE, cbd);
export_and_return(pb, FALSE);
return;
}
@@ -984,7 +973,7 @@ static void pb_reference_data_cb(int ok, int total_length, int record,
ofono_sim_read_info(pbd->sim_context, file_info->file_id,
OFONO_SIM_FILE_STRUCTURE_FIXED,
pbd->df_path, pbd->df_size,
read_info_cb, cbd);
read_info_cb, pb);
}
}
@@ -993,7 +982,6 @@ static void ril_export_entries(struct ofono_phonebook *pb,
ofono_phonebook_cb_t cb, void *data)
{
struct pb_data *pbd = ofono_phonebook_get_data(pb);
struct cb_data *cbd;
DBG("Storage %s", storage);
@@ -1003,7 +991,8 @@ static void ril_export_entries(struct ofono_phonebook *pb,
return;
}
cbd = cb_data_new(cb, data, pb);
pbd->cb = cb;
pbd->cb_data = data;
/* Assume USIM, change in case EF_PBR is not present */
pbd->df_path = usim_path;
@@ -1011,13 +1000,15 @@ static void ril_export_entries(struct ofono_phonebook *pb,
ofono_sim_read(pbd->sim_context, SIM_EFPBR_FILEID,
OFONO_SIM_FILE_STRUCTURE_FIXED,
pb_reference_data_cb, cbd);
pb_reference_data_cb, pb);
}
static gboolean ril_delayed_register(gpointer user_data)
{
struct ofono_phonebook *pb = user_data;
struct pb_data *pbd = ofono_phonebook_get_data(pb);
pbd->register_id = 0;
ofono_phonebook_register(pb);
return FALSE;
}
@@ -1040,7 +1031,7 @@ static int ril_phonebook_probe(struct ofono_phonebook *pb,
ofono_phonebook_set_data(pb, pd);
g_idle_add(ril_delayed_register, pb);
pd->register_id = g_idle_add(ril_delayed_register, pb);
return 0;
}
@@ -1049,9 +1040,14 @@ static void ril_phonebook_remove(struct ofono_phonebook *pb)
{
struct pb_data *pbd = ofono_phonebook_get_data(pb);
if (pbd->register_id) {
g_source_remove(pbd->register_id);
}
ofono_phonebook_set_data(pb, NULL);
ofono_sim_context_free(pbd->sim_context);
free_pb_refs(pbd, free_entry, NULL);
g_free(pbd);
}

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2016 Jolla Ltd.
* Copyright (C) 2015-2017 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -14,6 +14,7 @@
*/
#include "ril_plugin.h"
#include "ril_config.h"
#include "ril_sim_card.h"
#include "ril_sim_info.h"
#include "ril_sim_settings.h"
@@ -21,12 +22,15 @@
#include "ril_network.h"
#include "ril_radio.h"
#include "ril_data.h"
#include "ril_mce.h"
#include "ril_util.h"
#include "ril_log.h"
#include <gdbus.h>
#include <gutil_ints.h>
#include <gutil_strv.h>
#include <gutil_misc.h>
#include <mce_display.h>
#include <mce_log.h>
#include <linux/capability.h>
#include <sys/types.h>
#include <sys/syscall.h>
@@ -37,6 +41,10 @@
#include "ofono.h"
#include "storage.h"
#define OFONO_RADIO_ACCESS_MODE_ALL (OFONO_RADIO_ACCESS_MODE_GSM |\
OFONO_RADIO_ACCESS_MODE_UMTS |\
OFONO_RADIO_ACCESS_MODE_LTE)
#define RADIO_GID 1001
#define RADIO_UID 1001
#define RIL_SUB_SIZE 4
@@ -45,14 +53,19 @@
#define RILMODEM_DEFAULT_SOCK "/dev/socket/rild"
#define RILMODEM_DEFAULT_SOCK2 "/dev/socket/rild2"
#define RILMODEM_DEFAULT_SUB "SUB1"
#define RILMODEM_DEFAULT_4G TRUE /* 4G is on by default */
#define RILMODEM_DEFAULT_TECHS OFONO_RADIO_ACCESS_MODE_ALL
#define RILMODEM_DEFAULT_SLOT 0xffffffff
#define RILMODEM_DEFAULT_TIMEOUT 0 /* No timeout */
#define RILMODEM_DEFAULT_SIM_FLAGS RIL_SIM_CARD_V9_UICC_SUBSCRIPTION_WORKAROUND
#define RILMODEM_DEFAULT_DATA_OPT RIL_ALLOW_DATA_AUTO
#define RILMODEM_DEFAULT_DM_FLAGS RIL_DATA_MANAGER_3GLTE_HANDOVER
#define RILMODEM_DEFAULT_DATA_CALL_FORMAT RIL_DATA_CALL_FORMAT_AUTO
#define RILMODEM_DEFAULT_DATA_CALL_RETRY_LIMIT 4
#define RILMODEM_DEFAULT_DATA_CALL_RETRY_DELAY 200 /* ms */
#define RILMODEM_DEFAULT_EMPTY_PIN_QUERY TRUE /* optimistic */
#define RILMODEM_CONF_GROUP "Settings"
#define RILMODEM_CONF_3GHANDOVER "3GLTEHandover"
#define RILCONF_SETTINGS_EMPTY "EmptyConfig"
#define RILCONF_SETTINGS_3GHANDOVER "3GLTEHandover"
#define RILCONF_DEV_PREFIX "ril_"
#define RILCONF_PATH_PREFIX "/" RILCONF_DEV_PREFIX
@@ -61,9 +74,17 @@
#define RILCONF_SLOT "slot"
#define RILCONF_SUB "sub"
#define RILCONF_TIMEOUT "timeout"
#define RILCONF_4G "enable4G"
#define RILCONF_4G "enable4G" /* Deprecated */
#define RILCONF_TECHS "technologies"
#define RILCONF_UICC_WORKAROUND "uiccWorkaround"
#define RILCONF_ECCLIST_FILE "ecclistFile"
#define RILCONF_ALLOW_DATA_REQ "allowDataReq"
#define RILCONF_EMPTY_PIN_QUERY "emptyPinQuery"
#define RILCONF_DATA_CALL_FORMAT "dataCallFormat"
#define RILCONF_DATA_CALL_RETRY_LIMIT "dataCallRetryLimit"
#define RILCONF_DATA_CALL_RETRY_DELAY "dataCallRetryDelay"
#define RILCONF_LOCAL_HANGUP_REASONS "localHangupReasons"
#define RILCONF_REMOTE_HANGUP_REASONS "remoteHangupReasons"
#define RIL_STORE "ril"
#define RIL_STORE_GROUP "Settings"
@@ -72,6 +93,12 @@
#define RIL_STORE_DEFAULT_DATA_SIM "DefaultDataSim"
#define RIL_STORE_SLOTS_SEP ","
/* The file where error statistics is stored */
#define RIL_ERROR_STORAGE "rilerror"
/* Modem error ids, must be static strings (only one is defined for now) */
static const char RIL_ERROR_ID_RILD_RESTART[] = "rild-restart";
enum ril_plugin_io_events {
IO_EVENT_CONNECTED,
IO_EVENT_ERROR,
@@ -80,13 +107,19 @@ enum ril_plugin_io_events {
IO_EVENT_COUNT
};
enum ril_plugin_display_events {
DISPLAY_EVENT_VALID,
DISPLAY_EVENT_STATE,
DISPLAY_EVENT_COUNT
};
struct ril_plugin_priv {
struct ril_plugin pub;
struct ril_plugin_dbus *dbus;
struct ril_data_manager *data_manager;
struct ril_mce *mce;
MceDisplay *display;
gboolean display_on;
gulong display_state_change_id;
gulong display_event_id[DISPLAY_EVENT_COUNT];
GSList *slots;
ril_slot_info_ptr *slots_info;
struct ril_slot *voice_slot;
@@ -106,13 +139,13 @@ struct ril_slot {
char *sockpath;
char *sub;
char *ecclist_file;
gint timeout; /* RIL timeout, in milliseconds */
int timeout; /* RIL timeout, in milliseconds */
int index;
int sim_flags;
struct ril_data_options data_opt;
struct ril_slot_config config;
struct ril_plugin_priv *plugin;
struct ril_modem *modem;
struct ril_mce *mce;
struct ofono_sim *sim;
struct ril_radio *radio;
struct ril_network *network;
@@ -122,7 +155,9 @@ struct ril_slot {
struct ril_sim_settings *sim_settings;
struct ril_cell_info *cell_info;
struct ril_cell_info_dbus *cell_info_dbus;
struct ril_oem_raw *oem_raw;
struct ril_data *data;
MceDisplay *display;
GRilIoChannel *io;
gulong io_event_id[IO_EVENT_COUNT];
gulong imei_req_id;
@@ -142,20 +177,30 @@ struct ril_plugin_settings {
static void ril_debug_trace_notify(struct ofono_debug_desc *desc);
static void ril_debug_dump_notify(struct ofono_debug_desc *desc);
static void ril_debug_grilio_notify(struct ofono_debug_desc *desc);
static void ril_debug_mce_notify(struct ofono_debug_desc *desc);
static void ril_plugin_debug_notify(struct ofono_debug_desc *desc);
static void ril_plugin_retry_init_io(struct ril_slot *slot);
GLOG_MODULE_DEFINE("rilmodem");
static const char ril_debug_trace_name[] = "ril_trace";
static GLogModule ril_debug_trace_module = {
.name = ril_debug_trace_name,
.max_level = GLOG_LEVEL_VERBOSE,
.level = GLOG_LEVEL_VERBOSE,
.flags = GLOG_FLAG_HIDE_NAME
};
static struct ofono_debug_desc ril_debug_trace OFONO_DEBUG_ATTR = {
.name = "ril_trace",
.flags = OFONO_DEBUG_FLAG_DEFAULT,
.name = ril_debug_trace_name,
.flags = OFONO_DEBUG_FLAG_DEFAULT | OFONO_DEBUG_FLAG_HIDE_NAME,
.notify = ril_debug_trace_notify
};
static struct ofono_debug_desc ril_debug_dump OFONO_DEBUG_ATTR = {
.name = "ril_dump",
.flags = OFONO_DEBUG_FLAG_DEFAULT,
.flags = OFONO_DEBUG_FLAG_DEFAULT | OFONO_DEBUG_FLAG_HIDE_NAME,
.notify = ril_debug_dump_notify
};
@@ -165,12 +210,24 @@ static struct ofono_debug_desc grilio_debug OFONO_DEBUG_ATTR = {
.notify = ril_debug_grilio_notify
};
static struct ofono_debug_desc mce_debug OFONO_DEBUG_ATTR = {
.name = "mce",
.flags = OFONO_DEBUG_FLAG_DEFAULT,
.notify = ril_debug_mce_notify
};
static struct ofono_debug_desc ril_plugin_debug OFONO_DEBUG_ATTR = {
.name = "ril_plugin",
.flags = OFONO_DEBUG_FLAG_DEFAULT,
.notify = ril_plugin_debug_notify
};
static inline const char *ril_slot_debug_prefix(const struct ril_slot *slot)
{
/* slot->path always starts with a slash, skip it */
return slot->path + 1;
}
static struct ril_plugin_priv *ril_plugin_cast(struct ril_plugin *pub)
{
return G_CAST(pub, struct ril_plugin_priv, pub);
@@ -205,12 +262,18 @@ static void ril_plugin_send_screen_state(struct ril_slot *slot)
}
}
static void ril_plugin_display_state_cb(struct ril_mce *mce, void *user_data)
static gboolean ril_plugin_display_on(MceDisplay *display)
{
return display && display->valid &&
display->state != MCE_DISPLAY_STATE_OFF;
}
static void ril_plugin_display_cb(MceDisplay *display, void *user_data)
{
struct ril_plugin_priv *plugin = user_data;
const gboolean display_was_on = plugin->display_on;
plugin->display_on = (mce->display_state != RIL_MCE_DISPLAY_OFF);
plugin->display_on = ril_plugin_display_on(display);
if (plugin->display_on != display_was_on) {
ril_plugin_foreach_slot(plugin, ril_plugin_send_screen_state);
}
@@ -518,8 +581,9 @@ static void ril_plugin_update_ready(struct ril_plugin_priv *plugin)
}
if (plugin->pub.ready != ready) {
DBG("%sready", ready ? "" : "not ");
plugin->pub.ready = ready;
ril_plugin_dbus_block_imei_requests(plugin->dbus, !ready);
DBG("%sready", ready ? "" : "not ");
ril_plugin_dbus_signal(plugin->dbus, RIL_PLUGIN_SIGNAL_READY);
}
}
@@ -567,7 +631,7 @@ static void ril_plugin_sim_state_watch(enum ofono_sim_state new_state,
struct ril_slot *slot = data;
struct ril_plugin_priv *plugin = slot->plugin;
DBG("%s sim state %d", slot->path + 1, new_state);
DBG("%s sim state %d", ril_slot_debug_prefix(slot), new_state);
slot->sim_state = new_state;
if (new_state == OFONO_SIM_STATE_READY) {
struct ril_slot *voice_slot = plugin->voice_slot;
@@ -623,10 +687,10 @@ static void ril_plugin_sim_watch(struct ofono_atom *atom,
struct ril_slot *slot = data;
if (cond == OFONO_ATOM_WATCH_CONDITION_REGISTERED) {
DBG("%s sim registered", slot->path + 1);
DBG("%s sim registered", ril_slot_debug_prefix(slot));
ril_plugin_register_sim(slot, __ofono_atom_get_data(atom));
} else if (cond == OFONO_ATOM_WATCH_CONDITION_UNREGISTERED) {
DBG("%s sim unregistered", slot->path + 1);
DBG("%s sim unregistered", ril_slot_debug_prefix(slot));
slot->sim = NULL;
}
@@ -634,8 +698,35 @@ static void ril_plugin_sim_watch(struct ofono_atom *atom,
ril_plugin_update_modem_paths_full(slot->plugin);
}
static void ril_plugin_handle_error(struct ril_slot *slot)
static void ril_plugin_count_error(struct ril_slot *slot, const char *key,
const char *message)
{
GHashTable *errors = slot->pub.errors;
GKeyFile *storage = storage_open(NULL, RIL_ERROR_STORAGE);
/* Update life-time statistics */
if (storage) {
/* slot->path always starts with a slash, skip it */
const char *group = slot->path + 1;
g_key_file_set_integer(storage, group, key,
g_key_file_get_integer(storage, group, key, NULL) + 1);
storage_close(NULL, RIL_ERROR_STORAGE, storage, TRUE);
}
/* Update run-time error counts. The key is the error id which
* is always a static string */
g_hash_table_insert(errors, (void*)key, GINT_TO_POINTER(
GPOINTER_TO_INT(g_hash_table_lookup(errors, key)) + 1));
/* Issue the D-Bus signal */
ril_plugin_dbus_signal_modem_error(slot->plugin->dbus,
slot->index, key, message);
}
static void ril_plugin_handle_error(struct ril_slot *slot, const char *msg)
{
ofono_error("%s %s", ril_slot_debug_prefix(slot), msg);
ril_plugin_count_error(slot, RIL_ERROR_ID_RILD_RESTART, msg);
ril_plugin_shutdown_slot(slot, TRUE);
ril_plugin_update_modem_paths_full(slot->plugin);
ril_plugin_retry_init_io(slot);
@@ -644,12 +735,12 @@ static void ril_plugin_handle_error(struct ril_slot *slot)
static void ril_plugin_slot_error(GRilIoChannel *io, const GError *error,
void *data)
{
ril_plugin_handle_error((struct ril_slot *)data);
ril_plugin_handle_error((struct ril_slot *)data, GERRMSG(error));
}
static void ril_plugin_slot_disconnected(GRilIoChannel *io, void *data)
{
ril_plugin_handle_error((struct ril_slot *)data);
ril_plugin_handle_error((struct ril_slot *)data, "disconnected");
}
static void ril_plugin_modem_online(struct ril_modem *modem, gboolean online,
@@ -657,7 +748,7 @@ static void ril_plugin_modem_online(struct ril_modem *modem, gboolean online,
{
struct ril_slot *slot = data;
DBG("%s %d", slot->path + 1, online);
DBG("%s %d", ril_slot_debug_prefix(slot), online);
GASSERT(slot->modem);
GASSERT(slot->modem == modem);
@@ -673,6 +764,11 @@ static void ril_plugin_modem_removed(struct ril_modem *modem, void *data)
GASSERT(slot->modem);
GASSERT(slot->modem == modem);
if (slot->oem_raw) {
ril_oem_raw_free(slot->oem_raw);
slot->oem_raw = NULL;
}
if (slot->sim_info_dbus) {
ril_sim_info_dbus_free(slot->sim_info_dbus);
slot->sim_info_dbus = NULL;
@@ -692,12 +788,7 @@ static void ril_plugin_modem_removed(struct ril_modem *modem, void *data)
static void ril_plugin_trace(GRilIoChannel *io, GRILIO_PACKET_TYPE type,
guint id, guint code, const void *data, guint data_len, void *user_data)
{
/* Turn prefix off */
static GLogModule log_module = {
.max_level = GLOG_LEVEL_VERBOSE,
.level = GLOG_LEVEL_VERBOSE
};
static const GLogModule* log_module = &ril_debug_trace_module;
const char *prefix = io->name ? io->name : "";
const char dir = (type == GRILIO_PACKET_REQ) ? '<' : '>';
const char *scode;
@@ -710,21 +801,21 @@ static void ril_plugin_trace(GRilIoChannel *io, GRILIO_PACKET_TYPE type,
} else {
scode = ril_request_to_string(code);
}
gutil_log(&log_module, GLOG_LEVEL_VERBOSE, "%s%c [%08x] %s",
gutil_log(log_module, GLOG_LEVEL_VERBOSE, "%s%c [%08x] %s",
prefix, dir, id, scode);
break;
case GRILIO_PACKET_RESP:
gutil_log(&log_module, GLOG_LEVEL_VERBOSE, "%s%c [%08x] %s",
gutil_log(log_module, GLOG_LEVEL_VERBOSE, "%s%c [%08x] %s",
prefix, dir, id, ril_error_to_string(code));
break;
case GRILIO_PACKET_UNSOL:
gutil_log(&log_module, GLOG_LEVEL_VERBOSE, "%s%c %s",
gutil_log(log_module, GLOG_LEVEL_VERBOSE, "%s%c %s",
prefix, dir, ril_unsol_event_to_string(code));
break;
}
}
static void ril_debug_dump_update_slot(struct ril_slot *slot)
static void ril_debug_dump_update(struct ril_slot *slot)
{
if (slot->io) {
if (ril_debug_dump.flags & OFONO_DEBUG_FLAG_PRINT) {
@@ -740,7 +831,7 @@ static void ril_debug_dump_update_slot(struct ril_slot *slot)
}
}
static void ril_debug_trace_update_slot(struct ril_slot *slot)
static void ril_debug_trace_update(struct ril_slot *slot)
{
if (slot->io) {
if (ril_debug_trace.flags & OFONO_DEBUG_FLAG_PRINT) {
@@ -758,7 +849,7 @@ static void ril_debug_trace_update_slot(struct ril_slot *slot)
slot->dump_id);
slot->dump_id = 0;
}
ril_debug_dump_update_slot(slot);
ril_debug_dump_update(slot);
}
} else if (slot->trace_id) {
grilio_channel_remove_logger(slot->io, slot->trace_id);
@@ -769,20 +860,21 @@ static void ril_debug_trace_update_slot(struct ril_slot *slot)
static const char *ril_plugin_log_prefix(struct ril_slot *slot)
{
return ril_plugin_multisim(slot->plugin) ? (slot->path + 1) : "";
return ril_plugin_multisim(slot->plugin) ?
ril_slot_debug_prefix(slot) : "";
}
static void ril_plugin_create_modem(struct ril_slot *slot)
{
struct ril_modem *modem;
DBG("%s", slot->path);
DBG("%s", ril_slot_debug_prefix(slot));
GASSERT(slot->io && slot->io->connected);
GASSERT(!slot->modem);
modem = ril_modem_create(slot->io, ril_plugin_log_prefix(slot),
&slot->pub, slot->radio, slot->network, slot->sim_card,
slot->data, slot->sim_settings);
slot->data, slot->sim_settings, slot->cell_info);
if (modem) {
struct ofono_sim *sim = ril_modem_ofono_sim(modem);
@@ -804,6 +896,9 @@ static void ril_plugin_create_modem(struct ril_slot *slot)
slot->cell_info);
}
slot->oem_raw = ril_oem_raw_new(slot->modem,
ril_plugin_log_prefix(slot));
ril_modem_set_removed_cb(modem, ril_plugin_modem_removed, slot);
ril_modem_set_online_cb(modem, ril_plugin_modem_online, slot);
} else {
@@ -827,16 +922,13 @@ static void ril_plugin_imei_cb(GRilIoChannel *io, int status,
const void *data, guint len, void *user_data)
{
struct ril_slot *slot = user_data;
struct ril_plugin_priv *plugin = slot->plugin;
gboolean all_done = TRUE;
GSList *link;
char *imei = NULL;
GASSERT(slot->imei_req_id);
slot->imei_req_id = 0;
if (status == RIL_E_SUCCESS) {
GRilIoParser rilp;
char *imei;
grilio_parser_init(&rilp, data, len);
imei = grilio_parser_get_utf8(&rilp);
@@ -849,26 +941,16 @@ static void ril_plugin_imei_cb(GRilIoChannel *io, int status,
* IMEI (if rild crashed and we have reconnected)
*/
GASSERT(!slot->imei || !g_strcmp0(slot->imei, imei));
g_free(slot->imei);
slot->pub.imei = slot->imei = imei;
ril_plugin_check_modem(slot);
ril_plugin_update_ready(plugin);
} else {
ofono_error("Slot %u IMEI query error: %s", slot->config.slot,
ril_error_to_string(status));
}
for (link = plugin->slots; link && all_done; link = link->next) {
if (((struct ril_slot *)link->data)->imei_req_id) {
all_done = FALSE;
}
}
g_free(slot->imei);
slot->pub.imei = slot->imei = (imei ? imei : g_strdup("ERROR"));
if (all_done) {
DBG("all done");
ril_plugin_dbus_block_imei_requests(plugin->dbus, FALSE);
}
ril_plugin_check_modem(slot);
ril_plugin_update_ready(slot->plugin);
}
/*
@@ -941,12 +1023,13 @@ static void ril_plugin_slot_connected(struct ril_slot *slot)
GASSERT(!slot->data);
slot->data = ril_data_new(slot->plugin->data_manager, log_prefix,
slot->radio, slot->network, slot->io);
slot->radio, slot->network, slot->io, &slot->data_opt,
&slot->config);
GASSERT(!slot->cell_info);
if (slot->io->ril_version > 8) {
slot->cell_info = ril_cell_info_new(slot->io, log_prefix,
plugin->mce, slot->radio, slot->sim_card);
plugin->display, slot->radio, slot->sim_card);
}
ril_plugin_send_screen_state(slot);
@@ -968,8 +1051,8 @@ static void ril_plugin_init_io(struct ril_slot *slot)
DBG("%s %s", slot->sockpath, slot->sub);
slot->io = grilio_channel_new_socket(slot->sockpath, slot->sub);
if (slot->io) {
ril_debug_trace_update_slot(slot);
ril_debug_dump_update_slot(slot);
ril_debug_trace_update(slot);
ril_debug_dump_update(slot);
if (slot->name) {
grilio_channel_set_name(slot->io, slot->name);
@@ -1022,45 +1105,49 @@ static void ril_plugin_retry_init_io(struct ril_slot *slot)
ril_plugin_retry_init_io_cb, slot);
}
static struct ril_slot *ril_plugin_slot_new(const char *sockpath,
const char *path, const char *name, guint slot_index)
{
struct ril_slot *slot = g_new0(struct ril_slot, 1);
slot->sockpath = g_strdup(sockpath);
slot->path = g_strdup(path);
slot->name = g_strdup(name);
slot->config.slot = slot_index;
slot->config.techs = RILMODEM_DEFAULT_TECHS;
slot->config.empty_pin_query = RILMODEM_DEFAULT_EMPTY_PIN_QUERY;
slot->timeout = RILMODEM_DEFAULT_TIMEOUT;
slot->sim_flags = RILMODEM_DEFAULT_SIM_FLAGS;
slot->data_opt.allow_data = RILMODEM_DEFAULT_DATA_OPT;
slot->data_opt.data_call_format = RILMODEM_DEFAULT_DATA_CALL_FORMAT;
slot->data_opt.data_call_retry_limit =
RILMODEM_DEFAULT_DATA_CALL_RETRY_LIMIT;
slot->data_opt.data_call_retry_delay_ms =
RILMODEM_DEFAULT_DATA_CALL_RETRY_DELAY;
slot->pub.errors = g_hash_table_new(g_str_hash, g_str_equal);
return slot;
}
static GSList *ril_plugin_create_default_config()
{
GSList *list = NULL;
if (g_file_test(RILMODEM_DEFAULT_SOCK, G_FILE_TEST_EXISTS)) {
struct ril_slot *slot;
if (g_file_test(RILMODEM_DEFAULT_SOCK2, G_FILE_TEST_EXISTS)) {
DBG("Falling back to default 2-SIM config");
slot = g_new0(struct ril_slot, 1);
slot->path = g_strdup(RILCONF_PATH_PREFIX "0");
slot->sockpath = g_strdup(RILMODEM_DEFAULT_SOCK);
slot->name = g_strdup("RIL1");
slot->config.enable_4g = RILMODEM_DEFAULT_4G;
slot->timeout = RILMODEM_DEFAULT_TIMEOUT;
slot->sim_flags = RILMODEM_DEFAULT_SIM_FLAGS;
list = g_slist_append(list, slot);
slot = g_new0(struct ril_slot, 1);
slot->path = g_strdup(RILCONF_PATH_PREFIX "1");
slot->sockpath = g_strdup(RILMODEM_DEFAULT_SOCK2);
slot->name = g_strdup("RIL2");
slot->config.enable_4g = RILMODEM_DEFAULT_4G;
slot->timeout = RILMODEM_DEFAULT_TIMEOUT;
slot->sim_flags = RILMODEM_DEFAULT_SIM_FLAGS;
slot->config.slot = 1;
list = g_slist_append(list, slot);
DBG("Falling back to default dual SIM config");
list = g_slist_append(list,
ril_plugin_slot_new(RILMODEM_DEFAULT_SOCK,
RILCONF_PATH_PREFIX "0", "RIL1", 0));
list = g_slist_append(list,
ril_plugin_slot_new(RILMODEM_DEFAULT_SOCK2,
RILCONF_PATH_PREFIX "1", "RIL2", 1));
} else {
DBG("Falling back to default Jolla1 config");
struct ril_slot * slot =
ril_plugin_slot_new(RILMODEM_DEFAULT_SOCK,
RILCONF_PATH_PREFIX "0", "RIL", 0);
slot = g_new0(struct ril_slot, 1);
slot->path = g_strdup(RILCONF_PATH_PREFIX "0");
slot->sockpath = g_strdup(RILMODEM_DEFAULT_SOCK);
DBG("Falling back to default single SIM config");
slot->sub = g_strdup(RILMODEM_DEFAULT_SUB);
slot->name = g_strdup("");
slot->config.enable_4g = RILMODEM_DEFAULT_4G;
slot->timeout = RILMODEM_DEFAULT_TIMEOUT;
slot->sim_flags = RILMODEM_DEFAULT_SIM_FLAGS;
list = g_slist_append(list, slot);
}
} else {
@@ -1070,20 +1157,6 @@ static GSList *ril_plugin_create_default_config()
return list;
}
static void ril_plugin_read_config_flag(GKeyFile *file, const char *group,
const char *key, int flag, int *flags)
{
GError *err = NULL;
if (g_key_file_get_boolean(file, group, key, &err)) {
*flags |= flag;
} else if (!err) {
*flags &= ~flag;
} else {
g_error_free(err);
}
}
static struct ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
const char *group)
{
@@ -1091,16 +1164,15 @@ static struct ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
char *sock = g_key_file_get_string(file, group, RILCONF_SOCKET, NULL);
if (sock) {
int value;
GError *err = NULL;
char *sub = g_key_file_get_string(file, group, RILCONF_SUB,
NULL);
char *strval;
char **strv;
char *sub = ril_config_get_string(file, group, RILCONF_SUB);
slot = g_new0(struct ril_slot, 1);
slot = ril_plugin_slot_new(NULL, NULL, NULL,
RILMODEM_DEFAULT_SLOT);
slot->sockpath = sock;
slot->path = g_strconcat("/", group, NULL);
slot->name = g_key_file_get_string(file, group, RILCONF_NAME,
NULL);
slot->sim_flags = RILMODEM_DEFAULT_SIM_FLAGS;
slot->name = ril_config_get_string(file, group, RILCONF_NAME);
if (sub && strlen(sub) == RIL_SUB_SIZE) {
DBG("%s: %s:%s", group, sock, sub);
@@ -1110,58 +1182,174 @@ static struct ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
g_free(sub);
}
value = g_key_file_get_integer(file, group, RILCONF_SLOT, &err);
if (!err && value >= 0) {
if (ril_config_get_integer(file, group, RILCONF_SLOT, &value) &&
value >= 0) {
slot->config.slot = value;
DBG("%s: slot %u", group, slot->config.slot);
} else {
slot->config.slot = RILMODEM_DEFAULT_SLOT;
if (err) {
g_error_free(err);
err = NULL;
}
}
value = g_key_file_get_integer(file, group, RILCONF_TIMEOUT,
&err);
if (!err) {
slot->timeout = value;
if (ril_config_get_integer(file, group, RILCONF_TIMEOUT,
&slot->timeout)) {
DBG("%s: timeout %d", group, slot->timeout);
} else {
slot->timeout = RILMODEM_DEFAULT_TIMEOUT;
if (err) {
g_error_free(err);
err = NULL;
}
strv = ril_config_get_strings(file, group, RILCONF_TECHS, ',');
if (strv) {
char **p;
slot->config.techs = 0;
for (p = strv; *p; p++) {
const char *s = *p;
enum ofono_radio_access_mode m;
if (!s[0]) {
continue;
}
if (!strcmp(s, "all")) {
slot->config.techs =
OFONO_RADIO_ACCESS_MODE_ALL;
break;
}
if (!ofono_radio_access_mode_from_string(s,
&m)) {
ofono_warn("Unknown technology %s "
"in [%s] section of %s", s,
group, RILMODEM_CONF_FILE);
continue;
}
if (m == OFONO_RADIO_ACCESS_MODE_ANY) {
slot->config.techs =
OFONO_RADIO_ACCESS_MODE_ALL;
break;
}
slot->config.techs |= m;
}
g_strfreev(strv);
}
slot->config.enable_4g = g_key_file_get_boolean(file, group,
RILCONF_4G, &err);
if (err) {
/* Set to default */
slot->config.enable_4g = RILMODEM_DEFAULT_4G;
g_error_free(err);
err = NULL;
/* "enable4G" is deprecated */
value = slot->config.techs;
if (ril_config_get_flag(file, group, RILCONF_4G,
OFONO_RADIO_ACCESS_MODE_LTE, &value)) {
slot->config.techs = value;
}
DBG("%s: 4G %s", group, slot->config.enable_4g ? "on" : "off");
ril_plugin_read_config_flag(file, group,
RILCONF_UICC_WORKAROUND,
RIL_SIM_CARD_V9_UICC_SUBSCRIPTION_WORKAROUND,
&slot->sim_flags);
DBG("%s: UICC workaround %s", group, (slot->sim_flags &
DBG("%s: technologies 0x%02x", group, slot->config.techs);
if (ril_config_get_boolean(file, group, RILCONF_EMPTY_PIN_QUERY,
&slot->config.empty_pin_query)) {
DBG("%s: %s %s", group, RILCONF_EMPTY_PIN_QUERY,
slot->config.empty_pin_query ? "on" : "off");
}
if (ril_config_get_flag(file, group, RILCONF_UICC_WORKAROUND,
RIL_SIM_CARD_V9_UICC_SUBSCRIPTION_WORKAROUND,
&slot->sim_flags)) {
DBG("%s: %s %s", group, RILCONF_UICC_WORKAROUND,
(slot->sim_flags &
RIL_SIM_CARD_V9_UICC_SUBSCRIPTION_WORKAROUND) ?
"on" : "off");
"on" : "off");
}
slot->ecclist_file = g_key_file_get_string(file, group,
RILCONF_ECCLIST_FILE, NULL);
strval = ril_config_get_string(file, group,
RILCONF_ALLOW_DATA_REQ);
if (strval) {
/*
* Some people are thinking that # is a comment
* anywhere on the line, not just at the beginning
*/
char *comment = strchr(strval, '#');
if (comment) *comment = 0;
g_strstrip(strval);
slot->data_opt.allow_data =
!strcasecmp(strval, "on") ? RIL_ALLOW_DATA_ON :
!strcasecmp(strval, "off")? RIL_ALLOW_DATA_OFF :
RIL_ALLOW_DATA_AUTO;
DBG("%s: %s %s", group, RILCONF_ALLOW_DATA_REQ,
slot->data_opt.allow_data ==
RIL_ALLOW_DATA_ON ? "on":
slot->data_opt.allow_data ==
RIL_ALLOW_DATA_OFF ? "off":
"auto");
g_free(strval);
}
strval = ril_config_get_string(file, group,
RILCONF_DATA_CALL_FORMAT);
if (strval) {
/*
* Some people are thinking that # is a comment
* anywhere on the line, not just at the beginning
*/
char *comment = strchr(strval, '#');
if (comment) *comment = 0;
g_strstrip(strval);
slot->data_opt.data_call_format =
!strcmp(strval, "6") ? RIL_DATA_CALL_FORMAT_6:
!strcmp(strval, "9") ? RIL_DATA_CALL_FORMAT_9:
!strcmp(strval, "11")? RIL_DATA_CALL_FORMAT_11:
RIL_DATA_CALL_FORMAT_AUTO;
if (slot->data_opt.data_call_format ==
RIL_DATA_CALL_FORMAT_AUTO) {
DBG("%s: %s auto", group,
RILCONF_DATA_CALL_FORMAT);
} else {
DBG("%s: %s %d", group,
RILCONF_DATA_CALL_FORMAT,
slot->data_opt.data_call_format);
}
g_free(strval);
}
if (ril_config_get_integer(file, group,
RILCONF_DATA_CALL_RETRY_LIMIT, &value) && value >= 0) {
DBG("%s: %s %d", group,
RILCONF_DATA_CALL_RETRY_LIMIT, value);
slot->data_opt.data_call_retry_limit = value;
}
if (ril_config_get_integer(file, group,
RILCONF_DATA_CALL_RETRY_DELAY, &value) && value >= 0) {
DBG("%s: %s %d ms", group,
RILCONF_DATA_CALL_RETRY_DELAY, value);
slot->data_opt.data_call_retry_delay_ms = value;
}
slot->ecclist_file = ril_config_get_string(file, group,
RILCONF_ECCLIST_FILE);
if (slot->ecclist_file && slot->ecclist_file[0]) {
DBG("%s: ecclist file %s", group, slot->ecclist_file);
DBG("%s: %s %s", group, RILCONF_ECCLIST_FILE,
slot->ecclist_file);
slot->pub.ecclist_file = slot->ecclist_file;
} else {
g_free(slot->ecclist_file);
slot->ecclist_file = NULL;
}
slot->config.local_hangup_reasons = ril_config_get_ints(file,
group, RILCONF_LOCAL_HANGUP_REASONS);
strval = ril_config_ints_to_string(
slot->config.local_hangup_reasons, ',');
if (strval) {
DBG("%s: %s %s", group, RILCONF_LOCAL_HANGUP_REASONS,
strval);
g_free(strval);
}
slot->config.remote_hangup_reasons = ril_config_get_ints(file,
group, RILCONF_REMOTE_HANGUP_REASONS);
strval = ril_config_ints_to_string(
slot->config.remote_hangup_reasons, ',');
if (strval) {
DBG("%s: %s %s", group, RILCONF_REMOTE_HANGUP_REASONS,
strval);
g_free(strval);
}
} else {
DBG("no socket path in %s", group);
}
@@ -1174,6 +1362,9 @@ static void ril_plugin_delete_slot(struct ril_slot *slot)
ril_plugin_shutdown_slot(slot, TRUE);
ril_sim_info_unref(slot->sim_info);
ril_sim_settings_unref(slot->sim_settings);
gutil_ints_unref(slot->config.local_hangup_reasons);
gutil_ints_unref(slot->config.remote_hangup_reasons);
g_hash_table_destroy(slot->pub.errors);
g_free(slot->path);
g_free(slot->imei);
g_free(slot->name);
@@ -1239,10 +1430,10 @@ static GSList *ril_plugin_parse_config_file(GKeyFile *file,
if (slot) {
list = ril_plugin_add_slot(list, slot);
}
} else if (!strcmp(group, RILMODEM_CONF_GROUP)) {
} else if (!strcmp(group, RILCONF_SETTINGS_GROUP)) {
/* Plugin configuration */
ril_plugin_read_config_flag(file, group,
RILMODEM_CONF_3GHANDOVER,
ril_config_get_flag(file, group,
RILCONF_SETTINGS_3GHANDOVER,
RIL_DATA_MANAGER_3GLTE_HANDOVER,
&ps->dm_flags);
}
@@ -1268,16 +1459,22 @@ static GSList *ril_plugin_parse_config_file(GKeyFile *file,
GError *err = NULL;
GSList *list = NULL;
GKeyFile *file = g_key_file_new();
gboolean empty = FALSE;
if (g_key_file_load_from_file(file, path, 0, &err)) {
DBG("loading %s", path);
list = ril_plugin_parse_config_file(file, ps);
DBG("Loading %s", path);
if (ril_config_get_boolean(file, RILCONF_SETTINGS_GROUP,
RILCONF_SETTINGS_EMPTY, &empty) && empty) {
DBG("Empty config");
} else {
list = ril_plugin_parse_config_file(file, ps);
}
} else {
DBG("conf load error: %s", err->message);
g_error_free(err);
}
if (!list) {
if (!list && !empty) {
list = ril_plugin_create_default_config();
}
@@ -1323,7 +1520,7 @@ static void ril_plugin_switch_user()
static void ril_plugin_update_enabled_slot(struct ril_slot *slot)
{
if (slot->pub.enabled) {
DBG("%s enabled", slot->path + 1);
DBG("%s enabled", ril_slot_debug_prefix(slot));
ril_plugin_check_modem(slot);
}
}
@@ -1331,7 +1528,7 @@ static void ril_plugin_update_enabled_slot(struct ril_slot *slot)
static void ril_plugin_update_disabled_slot(struct ril_slot *slot)
{
if (!slot->pub.enabled) {
DBG("%s disabled", slot->path + 1);
DBG("%s disabled", ril_slot_debug_prefix(slot));
ril_plugin_shutdown_slot(slot, FALSE);
ril_plugin_update_modem_paths_full(slot->plugin);
}
@@ -1525,19 +1722,19 @@ static void ril_plugin_enable_slot(struct ril_slot *slot)
slot->pub.enabled = TRUE;
}
struct ril_plugin_priv *ril_plugin = NULL;
static struct ril_plugin_priv *ril_plugin = NULL;
static void ril_debug_trace_notify(struct ofono_debug_desc *desc)
{
if (ril_plugin) {
ril_plugin_foreach_slot(ril_plugin, ril_debug_trace_update_slot);
ril_plugin_foreach_slot(ril_plugin, ril_debug_trace_update);
}
}
static void ril_debug_dump_notify(struct ofono_debug_desc *desc)
{
if (ril_plugin) {
ril_plugin_foreach_slot(ril_plugin, ril_debug_dump_update_slot);
ril_plugin_foreach_slot(ril_plugin, ril_debug_dump_update);
}
}
@@ -1547,6 +1744,12 @@ static void ril_debug_grilio_notify(struct ofono_debug_desc *desc)
GLOG_LEVEL_VERBOSE : GLOG_LEVEL_INHERIT;
}
static void ril_debug_mce_notify(struct ofono_debug_desc *desc)
{
mce_log.level = (desc->flags & OFONO_DEBUG_FLAG_PRINT) ?
GLOG_LEVEL_VERBOSE : GLOG_LEVEL_INHERIT;
}
static void ril_plugin_debug_notify(struct ofono_debug_desc *desc)
{
GLOG_MODULE_NAME.level = (desc->flags & OFONO_DEBUG_FLAG_PRINT) ?
@@ -1564,7 +1767,23 @@ static int ril_plugin_init(void)
DBG("");
GASSERT(!ril_plugin);
/* ofono core calls openlog() */
/*
* Log categories (accessible via D-Bus) are generated from
* ofono_debug_desc structures, while libglibutil based log
* functions receive the log module name. Those should match
* otherwise the client receiving the log won't get the category
* information.
*/
grilio_hexdump_log.name = ril_debug_dump.name;
grilio_log.name = grilio_debug.name;
mce_log.name = mce_debug.name;
/*
* Debug log plugin hooks gutil_log_func2 while we replace
* gutil_log_func, they don't interfere with each other.
*
* Note that ofono core calls openlog(), so we don't need to.
*/
gutil_log_func = gutil_log_syslog;
ril_plugin_switch_user();
@@ -1574,9 +1793,8 @@ static int ril_plugin_init(void)
ril_plugin_init_slots(ril_plugin);
ril_plugin->dbus = ril_plugin_dbus_new(&ril_plugin->pub);
ril_plugin->data_manager = ril_data_manager_new(ps.dm_flags);
ril_plugin->mce = ril_mce_new();
ril_plugin->display_on =
(ril_plugin->mce->display_state != RIL_MCE_DISPLAY_OFF);
ril_plugin->display = mce_display_new();
ril_plugin->display_on = ril_plugin_display_on(ril_plugin->display);
if (ril_plugin->slots) {
/*
@@ -1620,6 +1838,7 @@ static int ril_plugin_init(void)
ofono_modem_driver_register(&ril_modem_driver);
ofono_sim_driver_register(&ril_sim_driver);
ofono_sms_driver_register(&ril_sms_driver);
ofono_netmon_driver_register(&ril_netmon_driver);
ofono_netreg_driver_register(&ril_netreg_driver);
ofono_devinfo_driver_register(&ril_devinfo_driver);
ofono_voicecall_driver_register(&ril_voicecall_driver);
@@ -1633,7 +1852,6 @@ static int ril_plugin_init(void)
ofono_phonebook_driver_register(&ril_phonebook_driver);
ofono_ussd_driver_register(&ril_ussd_driver);
ofono_cbs_driver_register(&ril_cbs_driver);
ofono_oem_raw_driver_register(&ril_oem_raw_driver);
ofono_stk_driver_register(&ril_stk_driver);
/* This will create the modems (those that are enabled) */
@@ -1647,9 +1865,12 @@ static int ril_plugin_init(void)
/* Set initial screen state and register for updates */
ril_plugin_foreach_slot(ril_plugin, ril_plugin_send_screen_state);
ril_plugin->display_state_change_id =
ril_mce_add_display_state_changed_handler(ril_plugin->mce,
ril_plugin_display_state_cb, ril_plugin);
ril_plugin->display_event_id[DISPLAY_EVENT_VALID] =
mce_display_add_valid_changed_handler(ril_plugin->display,
ril_plugin_display_cb, ril_plugin);
ril_plugin->display_event_id[DISPLAY_EVENT_STATE] =
mce_display_add_state_changed_handler(ril_plugin->display,
ril_plugin_display_cb, ril_plugin);
/* This will set 'ready' flag if we have no modems at all */
ril_plugin_update_ready(ril_plugin);
@@ -1665,6 +1886,7 @@ static void ril_plugin_exit(void)
ofono_sim_driver_unregister(&ril_sim_driver);
ofono_sms_driver_unregister(&ril_sms_driver);
ofono_devinfo_driver_unregister(&ril_devinfo_driver);
ofono_netmon_driver_unregister(&ril_netmon_driver);
ofono_netreg_driver_unregister(&ril_netreg_driver);
ofono_voicecall_driver_unregister(&ril_voicecall_driver);
ofono_call_barring_driver_unregister(&ril_call_barring_driver);
@@ -1677,16 +1899,15 @@ static void ril_plugin_exit(void)
ofono_phonebook_driver_unregister(&ril_phonebook_driver);
ofono_ussd_driver_unregister(&ril_ussd_driver);
ofono_cbs_driver_unregister(&ril_cbs_driver);
ofono_oem_raw_driver_unregister(&ril_oem_raw_driver);
ofono_stk_driver_unregister(&ril_stk_driver);
if (ril_plugin) {
g_slist_free_full(ril_plugin->slots, ril_plugin_destroy_slot);
ril_plugin_dbus_free(ril_plugin->dbus);
ril_data_manager_unref(ril_plugin->data_manager);
ril_mce_remove_handler(ril_plugin->mce,
ril_plugin->display_state_change_id);
ril_mce_unref(ril_plugin->mce);
gutil_disconnect_handlers(ril_plugin->display,
ril_plugin->display_event_id, DISPLAY_EVENT_COUNT);
mce_display_unref(ril_plugin->display);
g_key_file_free(ril_plugin->storage);
g_free(ril_plugin->slots_info);
g_free(ril_plugin->default_voice_imsi);

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2016 Jolla Ltd.
* Copyright (C) 2015-2017 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -28,7 +28,6 @@
#include <ofono/gprs-context.h>
#include <ofono/gprs.h>
#include <ofono/netreg.h>
#include <ofono/oemraw.h>
#include <ofono/phonebook.h>
#include <ofono/radio-settings.h>
#include <ofono/sim.h>
@@ -36,6 +35,7 @@
#include <ofono/stk.h>
#include <ofono/ussd.h>
#include <ofono/voicecall.h>
#include <ofono/netmon.h>
#include <grilio_queue.h>
#include <grilio_request.h>
@@ -52,6 +52,7 @@ struct ril_slot_info {
gboolean enabled;
gboolean sim_present;
const struct ril_slot_config *config;
GHashTable *errors;
};
struct ril_plugin {
@@ -76,6 +77,7 @@ struct ril_modem {
struct ril_network *network;
struct ril_sim_card *sim_card;
struct ril_sim_settings *sim_settings;
struct ril_cell_info *cell_info;
struct ril_slot_config config;
};
@@ -99,6 +101,11 @@ void ril_plugin_set_default_voice_imsi(struct ril_plugin *plugin,
void ril_plugin_set_default_data_imsi(struct ril_plugin *plugin,
const char *imsi);
struct ril_oem_raw;
struct ril_oem_raw *ril_oem_raw_new(struct ril_modem *md,
const char *log_prefix);
void ril_oem_raw_free(struct ril_oem_raw *raw);
struct ril_sim_info_dbus;
struct ril_sim_info_dbus *ril_sim_info_dbus_new(struct ril_modem *md,
struct ril_sim_info *info);
@@ -117,11 +124,14 @@ void ril_plugin_dbus_block_imei_requests(struct ril_plugin_dbus *dbus,
void ril_plugin_dbus_signal(struct ril_plugin_dbus *dbus, int mask);
void ril_plugin_dbus_signal_sim(struct ril_plugin_dbus *dbus, int index,
gboolean present);
void ril_plugin_dbus_signal_modem_error(struct ril_plugin_dbus *dbus,
int index, const char *id, const char *message);
struct ril_modem *ril_modem_create(GRilIoChannel *io, const char *log_prefix,
const struct ril_slot_info *slot, struct ril_radio *radio,
struct ril_network *network, struct ril_sim_card *card,
struct ril_data *data, struct ril_sim_settings *settings);
struct ril_data *data, struct ril_sim_settings *settings,
struct ril_cell_info *cell_info);
void ril_modem_delete(struct ril_modem *modem);
struct ofono_sim *ril_modem_ofono_sim(struct ril_modem *modem);
struct ofono_gprs *ril_modem_ofono_gprs(struct ril_modem *modem);
@@ -149,7 +159,6 @@ extern const struct ofono_gprs_context_driver ril_gprs_context_driver;
extern const struct ofono_gprs_driver ril_gprs_driver;
extern const struct ofono_modem_driver ril_modem_driver;
extern const struct ofono_netreg_driver ril_netreg_driver;
extern /* const */ struct ofono_oem_raw_driver ril_oem_raw_driver;
extern const struct ofono_phonebook_driver ril_phonebook_driver;
extern const struct ofono_radio_settings_driver ril_radio_settings_driver;
extern const struct ofono_sim_driver ril_sim_driver;
@@ -157,6 +166,7 @@ extern const struct ofono_sms_driver ril_sms_driver;
extern const struct ofono_stk_driver ril_stk_driver;
extern const struct ofono_ussd_driver ril_ussd_driver;
extern const struct ofono_voicecall_driver ril_voicecall_driver;
extern const struct ofono_netmon_driver ril_netmon_driver;
#endif /* RIL_PLUGIN_H */

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2016 Jolla Ltd.
* Copyright (C) 2015-2017 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -46,7 +46,7 @@ struct ril_plugin_dbus {
#define RIL_DBUS_PATH "/"
#define RIL_DBUS_INTERFACE "org.nemomobile.ofono.ModemManager"
#define RIL_DBUS_INTERFACE_VERSION (5)
#define RIL_DBUS_INTERFACE_VERSION (6)
#define RIL_DBUS_SIGNAL_ENABLED_MODEMS_CHANGED "EnabledModemsChanged"
#define RIL_DBUS_SIGNAL_PRESENT_SIMS_CHANGED "PresentSimsChanged"
@@ -57,8 +57,11 @@ struct ril_plugin_dbus {
#define RIL_DBUS_SIGNAL_MMS_SIM_CHANGED "MmsSimChanged"
#define RIL_DBUS_SIGNAL_MMS_MODEM_CHANGED "MmsModemChanged"
#define RIL_DBUS_SIGNAL_READY_CHANGED "ReadyChanged"
#define RIL_DBUS_SIGNAL_MODEM_ERROR "ModemError"
#define RIL_DBUS_IMSI_AUTO "auto"
#define RIL_DBUS_ERROR_SIGNATURE "si"
static gboolean ril_plugin_dbus_enabled(const struct ril_slot_info *slot)
{
return slot->enabled;
@@ -167,6 +170,48 @@ static void ril_plugin_dbus_message_append_path_array(DBusMessage *msg,
ril_plugin_dbus_append_path_array(&iter, dbus, fn);
}
static void ril_plugin_dbus_append_modem_error(DBusMessageIter *it,
const char *id, dbus_uint32_t count)
{
DBusMessageIter sub;
dbus_message_iter_open_container(it, DBUS_TYPE_STRUCT, NULL, &sub);
dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &id);
dbus_message_iter_append_basic(&sub, DBUS_TYPE_INT32, &count);
dbus_message_iter_close_container(it, &sub);
}
static void ril_plugin_dbus_append_modem_errors(DBusMessageIter *it,
struct ril_plugin_dbus *dbus)
{
DBusMessageIter slots;
const struct ril_slot_info *const *ptr = dbus->plugin->slots;
dbus_message_iter_open_container(it, DBUS_TYPE_ARRAY,
"a(" RIL_DBUS_ERROR_SIGNATURE ")", &slots);
while (*ptr) {
const struct ril_slot_info *slot = *ptr++;
DBusMessageIter errors;
dbus_message_iter_open_container(&slots, DBUS_TYPE_ARRAY,
"(" RIL_DBUS_ERROR_SIGNATURE ")", &errors);
if (g_hash_table_size(slot->errors)) {
gpointer key, value;
GHashTableIter iter;
g_hash_table_iter_init(&iter, slot->errors);
while (g_hash_table_iter_next(&iter, &key, &value)) {
ril_plugin_dbus_append_modem_error(&errors,
key, GPOINTER_TO_INT(value));
}
}
dbus_message_iter_close_container(&slots, &errors);
}
dbus_message_iter_close_container(it, &slots);
}
static void ril_plugin_dbus_signal_path_array(struct ril_plugin_dbus *dbus,
const char *name, ril_plugin_dbus_slot_select_fn fn)
{
@@ -257,6 +302,19 @@ void ril_plugin_dbus_signal_sim(struct ril_plugin_dbus *dbus, int index,
DBUS_TYPE_INVALID);
}
void ril_plugin_dbus_signal_modem_error(struct ril_plugin_dbus *dbus,
int index, const char *id, const char *message)
{
const char *path = dbus->plugin->slots[index]->path;
if (!message) message = "";
g_dbus_emit_signal(dbus->conn, RIL_DBUS_PATH, RIL_DBUS_INTERFACE,
RIL_DBUS_SIGNAL_MODEM_ERROR,
DBUS_TYPE_OBJECT_PATH, &path,
DBUS_TYPE_STRING, &id,
DBUS_TYPE_STRING, &message,
DBUS_TYPE_INVALID);
}
static DBusMessage *ril_plugin_dbus_reply_with_path_array(DBusMessage *msg,
struct ril_plugin_dbus *dbus, ril_plugin_dbus_slot_select_fn fn)
{
@@ -375,6 +433,13 @@ static void ril_plugin_dbus_append_all5(DBusMessageIter *it,
ril_plugin_dbus_append_boolean(it, dbus->plugin->ready);
}
static void ril_plugin_dbus_append_all6(DBusMessageIter *it,
struct ril_plugin_dbus *dbus)
{
ril_plugin_dbus_append_all5(it, dbus);
ril_plugin_dbus_append_modem_errors(it, dbus);
}
static DBusMessage *ril_plugin_dbus_get_all(DBusConnection *conn,
DBusMessage *msg, void *data)
{
@@ -410,6 +475,13 @@ static DBusMessage *ril_plugin_dbus_get_all5(DBusConnection *conn,
ril_plugin_dbus_append_all5);
}
static DBusMessage *ril_plugin_dbus_get_all6(DBusConnection *conn,
DBusMessage *msg, void *data)
{
return ril_plugin_dbus_imei_reply(msg, (struct ril_plugin_dbus *)data,
ril_plugin_dbus_append_all6);
}
static DBusMessage *ril_plugin_dbus_get_interface_version(DBusConnection *conn,
DBusMessage *msg, void *data)
{
@@ -554,6 +626,13 @@ static DBusMessage *ril_plugin_dbus_get_ready(DBusConnection *conn,
return reply;
}
static DBusMessage *ril_plugin_dbus_get_modem_errors(DBusConnection *conn,
DBusMessage *msg, void *data)
{
return ril_plugin_dbus_reply(msg, (struct ril_plugin_dbus *)data,
ril_plugin_dbus_append_modem_errors);
}
static DBusMessage *ril_plugin_dbus_set_enabled_modems(DBusConnection *conn,
DBusMessage *msg, void *data)
{
@@ -697,28 +776,44 @@ static DBusMessage *ril_plugin_dbus_set_mms_sim(DBusConnection *conn,
* talking to.
*/
#define RIL_DBUS_VERSION_ARG {"version", "i"}
#define RIL_DBUS_AVAILABLE_MODEMS_ARG {"availableModems", "ao"}
#define RIL_DBUS_ENABLED_MODEMS_ARG {"enabledModems", "ao" }
#define RIL_DBUS_DEFAULT_DATA_SIM_ARG {"defaultDataSim", "s" }
#define RIL_DBUS_DEFAULT_VOICE_SIM_ARG {"defaultVoiceSim", "s" }
#define RIL_DBUS_DEFAULT_DATA_MODEM_ARG {"defaultDataModem", "s" }
#define RIL_DBUS_DEFAULT_VOICE_MODEM_ARG {"defaultVoiceModem" , "s"}
#define RIL_DBUS_PRESENT_SIMS_ARG {"presentSims" , "ab"}
#define RIL_DBUS_IMEI_ARG {"imei" , "as"}
#define RIL_DBUS_MMS_SIM_ARG {"mmsSim", "s"}
#define RIL_DBUS_MMS_MODEM_ARG {"mmsModem" , "s"}
#define RIL_DBUS_READY_ARG {"ready" , "b"}
#define RIL_DBUS_MODEM_ERRORS_ARG {"errors" , \
"aa(" RIL_DBUS_ERROR_SIGNATURE ")"}
#define RIL_DBUS_GET_ALL_ARGS \
{"version", "i" }, \
{"availableModems", "ao" }, \
{"enabledModems", "ao" }, \
{"defaultDataSim", "s" }, \
{"defaultVoiceSim", "s" }, \
{"defaultDataModem", "s" }, \
{"defaultVoiceModem" , "s"}
RIL_DBUS_VERSION_ARG, \
RIL_DBUS_AVAILABLE_MODEMS_ARG, \
RIL_DBUS_ENABLED_MODEMS_ARG, \
RIL_DBUS_DEFAULT_DATA_SIM_ARG, \
RIL_DBUS_DEFAULT_VOICE_SIM_ARG, \
RIL_DBUS_DEFAULT_DATA_MODEM_ARG, \
RIL_DBUS_DEFAULT_VOICE_MODEM_ARG
#define RIL_DBUS_GET_ALL2_ARGS \
RIL_DBUS_GET_ALL_ARGS, \
{"presentSims" , "ab"}
RIL_DBUS_PRESENT_SIMS_ARG
#define RIL_DBUS_GET_ALL3_ARGS \
RIL_DBUS_GET_ALL2_ARGS, \
{"imei" , "as"}
RIL_DBUS_IMEI_ARG
#define RIL_DBUS_GET_ALL4_ARGS \
RIL_DBUS_GET_ALL3_ARGS, \
{"mmsSim", "s" }, \
{"mmsModem" , "s"}
RIL_DBUS_MMS_SIM_ARG, \
RIL_DBUS_MMS_MODEM_ARG
#define RIL_DBUS_GET_ALL5_ARGS \
RIL_DBUS_GET_ALL4_ARGS, \
{"ready" , "b"}
RIL_DBUS_READY_ARG
#define RIL_DBUS_GET_ALL6_ARGS \
RIL_DBUS_GET_ALL5_ARGS, \
RIL_DBUS_MODEM_ERRORS_ARG
static const GDBusMethodTable ril_plugin_dbus_methods[] = {
{ GDBUS_METHOD("GetAll",
NULL, GDBUS_ARGS(RIL_DBUS_GET_ALL_ARGS),
@@ -735,42 +830,48 @@ static const GDBusMethodTable ril_plugin_dbus_methods[] = {
{ GDBUS_ASYNC_METHOD("GetAll5",
NULL, GDBUS_ARGS(RIL_DBUS_GET_ALL5_ARGS),
ril_plugin_dbus_get_all5) },
{ GDBUS_ASYNC_METHOD("GetAll6",
NULL, GDBUS_ARGS(RIL_DBUS_GET_ALL6_ARGS),
ril_plugin_dbus_get_all6) },
{ GDBUS_METHOD("GetInterfaceVersion",
NULL, GDBUS_ARGS({ "version", "i" }),
NULL, GDBUS_ARGS(RIL_DBUS_VERSION_ARG),
ril_plugin_dbus_get_interface_version) },
{ GDBUS_METHOD("GetAvailableModems",
NULL, GDBUS_ARGS({ "modems", "ao" }),
NULL, GDBUS_ARGS(RIL_DBUS_AVAILABLE_MODEMS_ARG),
ril_plugin_dbus_get_available_modems) },
{ GDBUS_METHOD("GetEnabledModems",
NULL, GDBUS_ARGS({ "modems", "ao" }),
NULL, GDBUS_ARGS(RIL_DBUS_ENABLED_MODEMS_ARG),
ril_plugin_dbus_get_enabled_modems) },
{ GDBUS_METHOD("GetPresentSims",
NULL, GDBUS_ARGS({ "presentSims", "ab" }),
NULL, GDBUS_ARGS(RIL_DBUS_PRESENT_SIMS_ARG),
ril_plugin_dbus_get_present_sims) },
{ GDBUS_ASYNC_METHOD("GetIMEI",
NULL, GDBUS_ARGS({ "imei", "as" }),
NULL, GDBUS_ARGS(RIL_DBUS_IMEI_ARG),
ril_plugin_dbus_get_imei) },
{ GDBUS_METHOD("GetDefaultDataSim",
NULL, GDBUS_ARGS({ "imsi", "s" }),
NULL, GDBUS_ARGS(RIL_DBUS_DEFAULT_DATA_SIM_ARG),
ril_plugin_dbus_get_default_data_sim) },
{ GDBUS_METHOD("GetDefaultVoiceSim",
NULL, GDBUS_ARGS({ "imsi", "s" }),
NULL, GDBUS_ARGS(RIL_DBUS_DEFAULT_VOICE_SIM_ARG),
ril_plugin_dbus_get_default_voice_sim) },
{ GDBUS_METHOD("GetMmsSim",
NULL, GDBUS_ARGS({ "imsi", "s" }),
NULL, GDBUS_ARGS(RIL_DBUS_MMS_SIM_ARG),
ril_plugin_dbus_get_mms_sim) },
{ GDBUS_METHOD("GetDefaultDataModem",
NULL, GDBUS_ARGS({ "path", "s" }),
NULL, GDBUS_ARGS(RIL_DBUS_DEFAULT_DATA_MODEM_ARG),
ril_plugin_dbus_get_default_data_modem) },
{ GDBUS_METHOD("GetDefaultVoiceModem",
NULL, GDBUS_ARGS({ "path", "s" }),
NULL, GDBUS_ARGS(RIL_DBUS_DEFAULT_VOICE_MODEM_ARG),
ril_plugin_dbus_get_default_voice_modem) },
{ GDBUS_METHOD("GetMmsModem",
NULL, GDBUS_ARGS({ "path", "s" }),
NULL, GDBUS_ARGS(RIL_DBUS_MMS_MODEM_ARG),
ril_plugin_dbus_get_mms_modem) },
{ GDBUS_METHOD("GetReady",
NULL, GDBUS_ARGS({ "ready", "b" }),
NULL, GDBUS_ARGS(RIL_DBUS_READY_ARG),
ril_plugin_dbus_get_ready) },
{ GDBUS_METHOD("GetModemErrors",
NULL, GDBUS_ARGS(RIL_DBUS_MODEM_ERRORS_ARG),
ril_plugin_dbus_get_modem_errors) },
{ GDBUS_METHOD("SetEnabledModems",
GDBUS_ARGS({ "modems", "ao" }), NULL,
ril_plugin_dbus_set_enabled_modems) },
@@ -788,24 +889,28 @@ static const GDBusMethodTable ril_plugin_dbus_methods[] = {
static const GDBusSignalTable ril_plugin_dbus_signals[] = {
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_ENABLED_MODEMS_CHANGED,
GDBUS_ARGS({ "modems", "ao" })) },
GDBUS_ARGS(RIL_DBUS_ENABLED_MODEMS_ARG)) },
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_PRESENT_SIMS_CHANGED,
GDBUS_ARGS({"index", "i" },
{"present" , "b"})) },
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_DEFAULT_DATA_SIM_CHANGED,
GDBUS_ARGS({ "imsi", "s" })) },
GDBUS_ARGS(RIL_DBUS_DEFAULT_DATA_SIM_ARG)) },
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_DEFAULT_VOICE_SIM_CHANGED,
GDBUS_ARGS({ "imsi", "s" })) },
GDBUS_ARGS(RIL_DBUS_DEFAULT_VOICE_SIM_ARG)) },
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_DEFAULT_DATA_MODEM_CHANGED,
GDBUS_ARGS({ "path", "s" })) },
GDBUS_ARGS(RIL_DBUS_DEFAULT_DATA_MODEM_ARG)) },
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_DEFAULT_VOICE_MODEM_CHANGED,
GDBUS_ARGS({ "path", "s" })) },
GDBUS_ARGS(RIL_DBUS_DEFAULT_VOICE_MODEM_ARG)) },
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_MMS_SIM_CHANGED,
GDBUS_ARGS({ "imsi", "s" })) },
GDBUS_ARGS(RIL_DBUS_MMS_SIM_ARG)) },
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_MMS_MODEM_CHANGED,
GDBUS_ARGS({ "path", "s" })) },
GDBUS_ARGS(RIL_DBUS_MMS_MODEM_ARG)) },
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_READY_CHANGED,
GDBUS_ARGS({ "ready", "b" })) },
GDBUS_ARGS(RIL_DBUS_READY_ARG)) },
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_MODEM_ERROR,
GDBUS_ARGS({"path","o"},
{"error_id", "s"},
{"message", "s"})) },
{ }
};

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2016 Jolla Ltd.
* Copyright (C) 2015-2017 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -113,15 +113,11 @@ static gboolean ril_radio_settings_query_available_rats_cb(gpointer data)
struct ofono_error error;
struct ril_radio_settings_cbd *cbd = data;
struct ril_radio_settings *rsd = cbd->rsd;
guint rats = OFONO_RADIO_ACCESS_MODE_GSM | OFONO_RADIO_ACCESS_MODE_UMTS;
if (cbd->rsd->settings->enable_4g) {
rats |= OFONO_RADIO_ACCESS_MODE_LTE;
}
GASSERT(cbd->rsd->source_id);
GASSERT(rsd->source_id);
rsd->source_id = 0;
cbd->cb.available_rats(ril_error_ok(&error), rats, cbd->data);
cbd->cb.available_rats(ril_error_ok(&error), rsd->settings->techs,
cbd->data);
return G_SOURCE_REMOVE;
}
@@ -132,8 +128,8 @@ static void ril_radio_settings_query_available_rats(
struct ril_radio_settings *rsd = ril_radio_settings_get_data(rs);
DBG_(rsd, "");
ril_radio_settings_later(rsd, ril_radio_settings_query_available_rats_cb,
cb, data);
ril_radio_settings_later(rsd,
ril_radio_settings_query_available_rats_cb, cb, data);
}
static gboolean ril_radio_settings_register(gpointer user_data)

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2016 Jolla Ltd.
* Copyright (C) 2015-2017 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -64,8 +64,6 @@ G_DEFINE_TYPE(RilSimCard, ril_sim_card, G_TYPE_OBJECT)
#define RIL_SIMCARD_STATE_CHANGED (0x01)
#define RIL_SIMCARD_STATUS_CHANGED (0x02)
static void ril_sim_card_request_status(struct ril_sim_card *self);
static gboolean ril_sim_card_app_equal(const struct ril_sim_card_app *a1,
const struct ril_sim_card_app *a2)
{
@@ -365,7 +363,7 @@ static void ril_sim_card_status_cb(GRilIoChannel *io, int ril_status,
}
}
static void ril_sim_card_request_status(struct ril_sim_card *self)
void ril_sim_card_request_status(struct ril_sim_card *self)
{
struct ril_sim_card_priv *priv = self->priv;

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2016 Jolla Ltd.
* Copyright (C) 2015-2017 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -55,6 +55,7 @@ typedef void (*ril_sim_card_cb_t)(struct ril_sim_card *sc, void *arg);
struct ril_sim_card *ril_sim_card_new(GRilIoChannel *io, guint slot, int flags);
struct ril_sim_card *ril_sim_card_ref(struct ril_sim_card *sc);
void ril_sim_card_unref(struct ril_sim_card *sc);
void ril_sim_card_request_status(struct ril_sim_card *self);
gboolean ril_sim_card_ready(struct ril_sim_card *sc);
gulong ril_sim_card_add_status_received_handler(struct ril_sim_card *sc,
ril_sim_card_cb_t cb, void *arg);

View File

@@ -57,6 +57,7 @@ struct ril_sim_info_priv {
char *sim_spn;
char *public_spn;
char default_spn[RIL_SIM_DEFAULT_SPN_BUFSIZE];
int public_spn_block;
struct ofono_sim *sim;
struct ril_sim_info_watch state_watch;
struct ril_sim_info_watch iccid_watch;
@@ -209,14 +210,18 @@ static void ril_sim_info_set_imsi(struct ril_sim_info *self, const char *imsi)
static void ril_sim_info_update_public_spn(struct ril_sim_info *self)
{
struct ril_sim_info_priv *priv = self->priv;
const char *spn = priv->sim_spn ? priv->sim_spn :
GASSERT(priv->public_spn_block >= 0);
if (!priv->public_spn_block) {
const char *spn = priv->sim_spn ? priv->sim_spn :
priv->cached_spn ? priv->cached_spn :
priv->default_spn;
if (g_strcmp0(priv->public_spn, spn)) {
g_free(priv->public_spn);
self->spn = priv->public_spn = g_strdup(spn);
ril_sim_info_signal_emit(self, SIGNAL_SPN_CHANGED);
if (g_strcmp0(priv->public_spn, spn)) {
g_free(priv->public_spn);
self->spn = priv->public_spn = g_strdup(spn);
ril_sim_info_signal_emit(self, SIGNAL_SPN_CHANGED);
}
}
}
@@ -226,11 +231,15 @@ static void ril_sim_info_set_cached_spn(struct ril_sim_info *self,
struct ril_sim_info_priv *priv = self->priv;
if (g_strcmp0(priv->cached_spn, spn)) {
DBG_(self, "cached spn \"%s\"", spn);
g_free(priv->cached_spn);
priv->cached_spn = g_strdup(spn);
priv->update_imsi_cache = TRUE;
ril_sim_info_update_imsi_cache(self);
if (spn) {
DBG_(self, "cached spn \"%s\"", spn);
priv->cached_spn = g_strdup(spn);
priv->update_imsi_cache = TRUE;
ril_sim_info_update_imsi_cache(self);
} else {
priv->cached_spn = NULL;
}
ril_sim_info_update_public_spn(self);
}
}
@@ -505,6 +514,7 @@ void ril_sim_info_set_ofono_sim(struct ril_sim_info *self,
struct ril_sim_info_priv *priv = self->priv;
if (priv->sim != sim) {
priv->public_spn_block++;
ril_sim_info_watch_remove(&priv->state_watch);
ril_sim_info_watch_remove(&priv->iccid_watch);
ril_sim_info_watch_remove(&priv->imsi_watch);
@@ -524,9 +534,14 @@ void ril_sim_info_set_ofono_sim(struct ril_sim_info *self,
DBG_(self, "attached to sim");
ril_sim_info_handle_sim_state(self,
ofono_sim_get_state(sim));
} else {
DBG_(self, "detached from sim");
ril_sim_info_update_default_spn(self);
ril_sim_info_network_check(self);
}
ril_sim_info_network_check(self);
priv->public_spn_block--;
ril_sim_info_update_public_spn(self);
}
}
}

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2016 Jolla Ltd.
* Copyright (C) 2016-2017 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -17,6 +17,8 @@
#include "ril_sim_info.h"
#include "ril_log.h"
#include <gutil_misc.h>
#include <ofono/dbus.h>
#include <gdbus.h>
@@ -32,7 +34,7 @@ enum sim_info_event_id {
};
struct ril_sim_info_dbus {
struct ril_modem *md;
struct ril_modem *modem;
struct ril_sim_info *info;
DBusConnection *conn;
char *path;
@@ -113,35 +115,43 @@ static DBusMessage *ril_sim_info_dbus_get_spn(DBusConnection *conn,
return ril_sim_info_dbus_reply_with_string(msg, dbus->info->spn);
}
#define RIL_SIM_INFO_DBUS_VERSION_ARG {"version", "i"}
#define RIL_SIM_INFO_DBUS_ICCID_ARG {"iccid", "s"}
#define RIL_SIM_INFO_DBUS_IMSI_ARG {"imsi", "s"}
#define RIL_SIM_INFO_DBUS_SPN_ARG {"spn" , "s"}
#define RIL_SIM_INFO_DBUS_GET_ALL_ARGS \
RIL_SIM_INFO_DBUS_VERSION_ARG, \
RIL_SIM_INFO_DBUS_ICCID_ARG, \
RIL_SIM_INFO_DBUS_IMSI_ARG, \
RIL_SIM_INFO_DBUS_SPN_ARG
static const GDBusMethodTable ril_sim_info_dbus_methods[] = {
{ GDBUS_METHOD("GetAll",
NULL, GDBUS_ARGS({"version", "i" },
{"iccid", "s" },
{"imsi", "s" },
{"spn" , "s"}),
NULL, GDBUS_ARGS(RIL_SIM_INFO_DBUS_GET_ALL_ARGS),
ril_sim_info_dbus_get_all) },
{ GDBUS_METHOD("GetInterfaceVersion",
NULL, GDBUS_ARGS({ "version", "i" }),
NULL, GDBUS_ARGS(RIL_SIM_INFO_DBUS_VERSION_ARG),
ril_sim_info_dbus_get_version) },
{ GDBUS_METHOD("GetCardIdentifier",
NULL, GDBUS_ARGS({ "iccid", "s" }),
NULL, GDBUS_ARGS(RIL_SIM_INFO_DBUS_ICCID_ARG),
ril_sim_info_dbus_get_iccid) },
{ GDBUS_METHOD("GetSubscriberIdentity",
NULL, GDBUS_ARGS({ "imsi", "s" }),
NULL, GDBUS_ARGS(RIL_SIM_INFO_DBUS_IMSI_ARG),
ril_sim_info_dbus_get_imsi) },
{ GDBUS_METHOD("GetServiceProviderName",
NULL, GDBUS_ARGS({ "spn", "s" }),
NULL, GDBUS_ARGS(RIL_SIM_INFO_DBUS_SPN_ARG),
ril_sim_info_dbus_get_spn) },
{ }
};
static const GDBusSignalTable ril_sim_info_dbus_signals[] = {
{ GDBUS_SIGNAL(RIL_SIM_INFO_DBUS_ICCID_CHANGED_SIGNAL,
GDBUS_ARGS({ "iccid", "s" })) },
GDBUS_ARGS(RIL_SIM_INFO_DBUS_ICCID_ARG)) },
{ GDBUS_SIGNAL(RIL_SIM_INFO_DBUS_IMSI_CHANGED_SIGNAL,
GDBUS_ARGS({ "imsi", "s" })) },
GDBUS_ARGS(RIL_SIM_INFO_DBUS_IMSI_ARG)) },
{ GDBUS_SIGNAL(RIL_SIM_INFO_DBUS_SPN_CHANGED_SIGNAL,
GDBUS_ARGS({ "spn", "s" })) },
GDBUS_ARGS(RIL_SIM_INFO_DBUS_SPN_ARG)) },
{ }
};
@@ -156,23 +166,20 @@ static void ril_sim_info_dbus_emit(struct ril_sim_info_dbus *dbus,
static void ril_sim_info_dbus_iccid_cb(struct ril_sim_info *info, void *arg)
{
struct ril_sim_info_dbus *dbus = arg;
ril_sim_info_dbus_emit(dbus, RIL_SIM_INFO_DBUS_ICCID_CHANGED_SIGNAL,
info->iccid);
ril_sim_info_dbus_emit((struct ril_sim_info_dbus *)arg,
RIL_SIM_INFO_DBUS_ICCID_CHANGED_SIGNAL, info->iccid);
}
static void ril_sim_info_dbus_imsi_cb(struct ril_sim_info *info, void *arg)
{
struct ril_sim_info_dbus *dbus = arg;
ril_sim_info_dbus_emit(dbus, RIL_SIM_INFO_DBUS_IMSI_CHANGED_SIGNAL,
info->imsi);
ril_sim_info_dbus_emit((struct ril_sim_info_dbus *)arg,
RIL_SIM_INFO_DBUS_IMSI_CHANGED_SIGNAL, info->imsi);
}
static void ril_sim_info_dbus_spn_cb(struct ril_sim_info *info, void *arg)
{
struct ril_sim_info_dbus *dbus = arg;
ril_sim_info_dbus_emit(dbus, RIL_SIM_INFO_DBUS_SPN_CHANGED_SIGNAL,
info->spn);
ril_sim_info_dbus_emit((struct ril_sim_info_dbus *)arg,
RIL_SIM_INFO_DBUS_SPN_CHANGED_SIGNAL, info->spn);
}
struct ril_sim_info_dbus *ril_sim_info_dbus_new(struct ril_modem *md,
@@ -181,7 +188,7 @@ struct ril_sim_info_dbus *ril_sim_info_dbus_new(struct ril_modem *md,
struct ril_sim_info_dbus *dbus = g_new0(struct ril_sim_info_dbus, 1);
DBG("%s", ril_modem_get_path(md));
dbus->md = md;
dbus->modem = md;
dbus->path = g_strdup(ril_modem_get_path(md));
dbus->info = ril_sim_info_ref(info);
dbus->conn = dbus_connection_ref(ofono_dbus_get_connection());
@@ -205,7 +212,7 @@ struct ril_sim_info_dbus *ril_sim_info_dbus_new(struct ril_modem *md,
return dbus;
} else {
ofono_error("CellInfo D-Bus register failed");
ofono_error("SimInfo D-Bus register failed");
ril_sim_info_dbus_free(dbus);
return NULL;
}
@@ -214,19 +221,15 @@ struct ril_sim_info_dbus *ril_sim_info_dbus_new(struct ril_modem *md,
void ril_sim_info_dbus_free(struct ril_sim_info_dbus *dbus)
{
if (dbus) {
unsigned int i;
DBG("%s", dbus->path);
g_dbus_unregister_interface(dbus->conn, dbus->path,
RIL_SIM_INFO_DBUS_INTERFACE);
ofono_modem_remove_interface(dbus->md->ofono,
ofono_modem_remove_interface(dbus->modem->ofono,
RIL_SIM_INFO_DBUS_INTERFACE);
dbus_connection_unref(dbus->conn);
for (i=0; i<G_N_ELEMENTS(dbus->handler_id); i++) {
ril_sim_info_remove_handler(dbus->info,
dbus->handler_id[i]);
}
gutil_disconnect_handlers(dbus->info, dbus->handler_id,
G_N_ELEMENTS(dbus->handler_id));
ril_sim_info_unref(dbus->info);
g_free(dbus->path);

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2016 Jolla Ltd.
* Copyright (C) 2016-2017 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -26,8 +26,12 @@
#define RIL_SIM_STORE_GROUP "Settings"
#define RIL_SIM_STORE_PREF_MODE "TechnologyPreference"
#define RIL_SIM_STORE_PREF_MODE_DEFAULT(self) ((self)->enable_4g ? \
OFONO_RADIO_ACCESS_MODE_LTE : OFONO_RADIO_ACCESS_MODE_UMTS)
#define RIL_SIM_STORE_PREF_MODE_DEFAULT(self) (\
((self)->techs & OFONO_RADIO_ACCESS_MODE_LTE) ? \
OFONO_RADIO_ACCESS_MODE_LTE : \
((self)->techs & OFONO_RADIO_ACCESS_MODE_UMTS) ? \
OFONO_RADIO_ACCESS_MODE_UMTS : \
OFONO_RADIO_ACCESS_MODE_GSM)
typedef GObjectClass RilSimSettingsClass;
typedef struct ril_sim_settings RilSimSettings;
@@ -84,8 +88,7 @@ static void ril_sim_settings_reload(struct ril_sim_settings *self)
mode_str = g_key_file_get_string(priv->storage,
RIL_SIM_STORE_GROUP, RIL_SIM_STORE_PREF_MODE, NULL);
if (ofono_radio_access_mode_from_string(mode_str, &mode)) {
if (!self->enable_4g &&
mode == OFONO_RADIO_ACCESS_MODE_LTE) {
if (!(self->techs & mode)) {
mode = OFONO_RADIO_ACCESS_MODE_ANY;
}
} else {
@@ -154,22 +157,18 @@ static void ril_sim_settings_imsi_watch_done(void *user_data)
priv->imsi_watch_id = 0;
}
static void ril_sim_settings_ready(struct ril_sim_settings *self)
static void ril_sim_settings_state_check(struct ril_sim_settings *self,
enum ofono_sim_state new_state)
{
struct ril_sim_settings_priv *priv = self->priv;
GASSERT(!priv->imsi_watch_id);
priv->imsi_watch_id = ofono_sim_add_imsi_watch(priv->sim,
ril_sim_settings_imsi_watch_cb, self,
ril_sim_settings_imsi_watch_done);
if (new_state != OFONO_SIM_STATE_READY) {
ril_sim_settings_set_imsi(self, NULL);
}
}
static void ril_sim_settings_state_watch(enum ofono_sim_state new_state,
void *user_data)
{
if (new_state == OFONO_SIM_STATE_READY) {
ril_sim_settings_ready(RIL_SIM_SETTINGS(user_data));
}
ril_sim_settings_state_check(RIL_SIM_SETTINGS(user_data), new_state);
}
static void ril_sim_settings_state_watch_done(void *user_data)
@@ -191,13 +190,19 @@ void ril_sim_settings_set_ofono_sim(struct ril_sim_settings *self,
if (priv->imsi_watch_id) {
ofono_sim_remove_imsi_watch(priv->sim,
priv->imsi_watch_id);
/* ril_sim_settings_imsi_watch_done clears it */
/*
* ril_sim_settings_imsi_watch_done
* clears it
*/
GASSERT(!priv->imsi_watch_id);
}
if (priv->state_watch_id) {
ofono_sim_remove_state_watch(priv->sim,
priv->state_watch_id);
/* ril_sim_settings_state_watch_done clears it */
/*
* ril_sim_settings_state_watch_done
* clears it
*/
GASSERT(!priv->state_watch_id);
}
priv->sim = sim;
@@ -207,13 +212,25 @@ void ril_sim_settings_set_ofono_sim(struct ril_sim_settings *self,
ril_sim_settings_state_watch, self,
ril_sim_settings_state_watch_done);
GASSERT(priv->state_watch_id);
if (ofono_sim_get_state(sim) ==
OFONO_SIM_STATE_READY) {
ril_sim_settings_ready(self);
}
} else {
ril_sim_settings_set_imsi(self, NULL);
ril_sim_settings_state_check(self,
ofono_sim_get_state(sim));
/*
* ofono_sim_add_imsi_watch immediately
* calls the event callback if IMSI is
* already known. It's useless though
* because we still have to check the
* current state in case if IMSI is not
* available yet.
*/
priv->imsi_watch_id =
ofono_sim_add_imsi_watch(priv->sim,
ril_sim_settings_imsi_watch_cb, self,
ril_sim_settings_imsi_watch_done);
GASSERT(priv->state_watch_id);
}
/* Luckily, ofono_sim_get_imsi handles NULL pointer */
ril_sim_settings_set_imsi(self,
ofono_sim_get_imsi(sim));
}
}
}
@@ -249,7 +266,7 @@ void ril_sim_settings_remove_handlers(struct ril_sim_settings *self,
struct ril_sim_settings *ril_sim_settings_new(const struct ril_slot_config *sc)
{
struct ril_sim_settings *self = g_object_new(RIL_SIM_SETTINGS_TYPE, 0);
self->enable_4g = sc->enable_4g;
self->techs = sc->techs;
self->slot = sc->slot;
self->pref_mode = RIL_SIM_STORE_PREF_MODE_DEFAULT(self);
return self;

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2016 Jolla Ltd.
* Copyright (C) 2016-2017 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -18,16 +18,14 @@
#include "ril_types.h"
#include <ofono/radio-settings.h>
struct ril_sim_settings_priv;
struct ril_sim_settings {
GObject object;
struct ril_sim_settings_priv *priv;
gboolean enable_4g;
guint slot;
const char *imsi;
enum ofono_radio_access_mode techs;
enum ofono_radio_access_mode pref_mode;
};

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015 Jolla Ltd.
* Copyright (C) 2015-2016 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -22,6 +22,9 @@
#include "util.h"
#include "simutil.h"
#define RIL_SMS_ACK_RETRY_MS 1000
#define RIL_SMS_ACK_RETRY_COUNT 10
#define SIM_EFSMS_FILEID 0x6F3C
#define EFSMS_LENGTH 176
@@ -278,6 +281,8 @@ static void ril_ack_delivery(struct ril_sms *sd, gboolean error)
grilio_request_append_int32(req, code); /* error code */
/* ACK the incoming NEW_SMS */
grilio_request_set_retry(req, RIL_SMS_ACK_RETRY_MS,
RIL_SMS_ACK_RETRY_COUNT);
grilio_queue_send_request_full(sd->q, req,
RIL_REQUEST_SMS_ACKNOWLEDGE, ril_ack_delivery_cb, NULL, NULL);
grilio_request_unref(req);

View File

@@ -1,4 +1,4 @@
# This is a sample configuration file for the ril driver
# This is a sample configuration file for Jolla ril driver
#
# This file is expected to be installed in /etc/ofono
#
@@ -6,9 +6,21 @@
# common settings are in the [Settings] section, all other sections
# are ignored.
#
# If any value from [ril_x] section (except "socket") is defined
# in the [Settings] section, it becomes the default for all modems.
# Default values can still be redefined at [ril_x] level.
#
[Settings]
# This option stops RIL plugin from creating any RIL modems.
# If it's set to true, all [ril_x] sections are ignored even
# if they are present, and no default configurtation is created.
#
# Default is false
#
#EmptyConfig=false
# If the phone has more than one SIM slot, the 3G/LTE module may be
# shared by all modems, meaning that only one of the slots can use
# 3G/LTE. In order to "hand 4G over" to the other slot, the modem
@@ -55,9 +67,15 @@ socket=/dev/socket/rild
#
#timeout=0
# Setting this one to false would disable 4G technology selection.
# Comma-separated list of radio technologies supported by the modem.
# Valid technologies are "gsm", "umts" and "lte". The special value
# "all" means that all technologies are supported.
#
# By default 4G is enabled
# The default is all
#
#technologies=all
# This one is deprecated, use the technologies entry instead (above).
#
#enable4G=true
@@ -83,3 +101,59 @@ socket=/dev/socket/rild
# chmod 0644 /var/lib/ofono/ril.ecclist
#
#ecclistFile=/var/lib/ofono/ril.ecclist
# RIL_REQUEST_ALLOW_DATA may or may not be supported by your RIL.
# This option allows you to forcibly enable or disable use of this request.
# Possible values are auto, on and off
#
# Default is auto (usage based on the RIL version)
#
#allowDataReq=auto
# Since RIL interface doesn't provide the standard way of querying the
# number of pin retries left, some RIL implementation (namely Qualcomm)
# allow to query the retry count by sending the empty pin. If your RIL
# actually does check the empty pin (and decrements the retry count)
# then you should turn this feature off.
#
# Default is true
#
#emptyPinQuery=true
# Different RILs use different data call structures which don't necessarily
# match the format specified in the data list header. The header may have
# version 9 but the list may contain RIL_Data_Call_Response_v6 structures,
# list version 10 may contain RIL_Data_Call_Response_v11 and so on. By default
# ofono assumes that the version from the list header matches the contents
# but sometimes you have to explicitly tell ofono which one to use.
# Possible values are 6, 9, 11 and auto.
#
# Default is auto
#
#dataCallFormat=auto
# Data call may fail with status 65535 which according to ril.h means that
# we need to retry silently. The maximum number of retries is limited by
# this parameter. Usually, one retry is enough. The first retry occurs
# immediately, the subsequent ones after dataCallRetryDelay (see below)
#
# Default is 4
#
#dataCallRetryLimit=4
# Delay between data call retries, in milliseconds. Note that the first
# retry occurs immediately after the first failure, the delays are only
# applied if the first retry fails too.
#
# Default is 200 ms
#
#dataCallRetryDelay=200
# Additional local and remote hangup reasons. Remote reasons are checked
# first. Normally, RIL plugin figures it out automatically. You would only
# need to define these if your RIL does something unusual.
#
# No default
#
#remoteHangupReasons=20
#localHangupReasons=23

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2016 Jolla Ltd.
* Copyright (C) 2015-2017 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -23,11 +23,12 @@
#include <grilio_types.h>
#include <gutil_macros.h>
#include <ofono/types.h>
struct ofono_modem;
struct ofono_sim;
#include <ofono/types.h>
#include <ofono/radio-settings.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
@@ -51,7 +52,10 @@ struct ril_cell_info;
struct ril_slot_config {
guint slot;
gboolean enable_4g;
enum ofono_radio_access_mode techs;
gboolean empty_pin_query;
GUtilInts *local_hangup_reasons;
GUtilInts *remote_hangup_reasons;
};
#endif /* RIL_TYPES_H */

View File

@@ -50,17 +50,15 @@ static struct ril_ussd_cbd *ril_ussd_cbd_new(ofono_ussd_cb_t cb, void *data)
return cbd;
}
static void ril_ussd_cb(GRilIoChannel *io, int status,
static void ril_ussd_cancel_cb(GRilIoChannel *io, int status,
const void *data, guint len, void *user_data)
{
struct ofono_error error;
struct ril_ussd_cbd *cbd = user_data;
if (status == RIL_E_SUCCESS) {
cbd->cb(ril_error_ok(&error), cbd->data);
} else {
cbd->cb(ril_error_failure(&error), cbd->data);
}
/* Always report sucessful completion, otherwise ofono may get
* stuck in the USSD_STATE_ACTIVE state */
cbd->cb(ril_error_ok(&error), cbd->data);
}
static void ril_ussd_request(struct ofono_ussd *ussd, int dcs,
@@ -120,7 +118,8 @@ static void ril_ussd_cancel(struct ofono_ussd *ussd,
ofono_info("send ussd cancel");
grilio_queue_send_request_full(ud->q, NULL, RIL_REQUEST_CANCEL_USSD,
ril_ussd_cb, ril_ussd_cbd_free, ril_ussd_cbd_new(cb, data));
ril_ussd_cancel_cb, ril_ussd_cbd_free,
ril_ussd_cbd_new(cb, data));
}
static void ril_ussd_notify(GRilIoChannel *io, guint code,
@@ -128,32 +127,32 @@ static void ril_ussd_notify(GRilIoChannel *io, guint code,
{
struct ril_ussd *ud = user_data;
GRilIoParser rilp;
char *ussd_from_network = NULL;
char *type = NULL;
int ussdtype = 0;
char *type;
guint32 n = 0;
ofono_info("ussd_received");
ofono_info("ussd received");
GASSERT(code == RIL_UNSOL_ON_USSD);
grilio_parser_init(&rilp, data, len);
grilio_parser_get_uint32(&rilp, NULL);
grilio_parser_get_uint32(&rilp, &n);
type = grilio_parser_get_utf8(&rilp);
ussd_from_network = grilio_parser_get_utf8(&rilp);
ussdtype = g_ascii_xdigit_value(*type);
if (type) {
int ussdtype = g_ascii_xdigit_value(*type);
char *msg = (n > 1) ? grilio_parser_get_utf8(&rilp) : NULL;
if (ussd_from_network) {
const int data_len = strlen(ussd_from_network);
DBG("ussd_received, length %d", data_len);
ofono_ussd_notify(ud->ussd, ussdtype, 0xFF,
(const unsigned char *) ussd_from_network, data_len);
} else {
ofono_ussd_notify(ud->ussd, ussdtype, 0, NULL, 0);
if (msg) {
const int msglen = strlen(msg);
DBG("ussd length %d", msglen);
ofono_ussd_notify(ud->ussd, ussdtype, 0xFF,
(const unsigned char *)msg, msglen);
/* msg is freed by core if dcs is 0xFF */
} else {
ofono_ussd_notify(ud->ussd, ussdtype, 0, NULL, 0);
}
g_free(type);
}
/* ussd_from_network not freed because core does that if dcs is 0xFF */
g_free(type);
return;
}
static gboolean ril_ussd_register(gpointer user_data)
@@ -170,7 +169,7 @@ static gboolean ril_ussd_register(gpointer user_data)
ril_ussd_notify, RIL_UNSOL_ON_USSD, ud);
/* Single-shot */
return FALSE;
return G_SOURCE_REMOVE;
}
static int ril_ussd_probe(struct ofono_ussd *ussd, unsigned int vendor,

View File

@@ -288,17 +288,6 @@ const char *ril_radio_state_to_string(int radio_state)
}
}
int ril_address_family(const char *addr)
{
if (strchr(addr, ':')) {
return AF_INET6;
} else if (strchr(addr, '.')) {
return AF_INET;
} else {
return AF_UNSPEC;
}
}
/* Returns enum access_technology or -1 on failure. */
int ril_parse_tech(const char *stech, int *ril_tech)
{

View File

@@ -25,16 +25,18 @@ const char *ril_request_to_string(guint request);
const char *ril_unsol_event_to_string(guint event);
const char *ril_radio_state_to_string(int radio_state);
int ril_parse_tech(const char *stech, int *ril_tech);
int ril_address_family(const char *addr);
gboolean ril_parse_mcc_mnc(const char *str, struct ofono_network_operator *op);
#define ril_error_init_ok(err) \
((err)->error = 0, (err)->type = OFONO_ERROR_TYPE_NO_ERROR)
#define ril_error_init_failure(err) \
((err)->error = 0, (err)->type = OFONO_ERROR_TYPE_FAILURE)
#define ril_error_init_sim_error(err,sw1,sw2) \
((err)->error = ((sw1) << 8)|(sw2), (err)->type = OFONO_ERROR_TYPE_SIM)
#define ril_error_ok(err) (ril_error_init_ok(err), err)
#define ril_error_failure(err) (ril_error_init_failure(err), err)
#define ril_error_sim(err,sw1,sw2) (ril_error_init_sim_error(err,sw1,sw2), err)
#endif /* RIL_UTIL_H */

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2016 Jolla Ltd.
* Copyright (C) 2015-2017 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -21,9 +21,10 @@
#include "common.h"
/* Amount of ms we wait between CLCC calls */
#include <gutil_ints.h>
#include <gutil_ring.h>
#define FLAG_NEED_CLIP 1
#define MAX_DTMF_BUFFER 32
enum ril_voicecall_events {
VOICECALL_EVENT_CALL_STATE_CHANGED,
@@ -43,7 +44,9 @@ struct ril_voicecall {
ofono_voicecall_cb_t cb;
void *data;
guint timer_id;
gchar *tone_queue;
GUtilRing *dtmf_queue;
GUtilInts *local_hangup_reasons;
GUtilInts *remote_hangup_reasons;
guint send_dtmf_id;
guint clcc_poll_id;
gulong event_id[VOICECALL_EVENT_COUNT];
@@ -60,28 +63,13 @@ struct ril_voicecall_change_state_req {
};
struct lastcause_req {
struct ofono_voicecall *vc;
struct ril_voicecall *vd;
int id;
};
static void ril_voicecall_send_one_dtmf(struct ril_voicecall *vd);
static void ril_voicecall_clear_dtmf_queue(struct ril_voicecall *vd);
/*
* structs ofono_voicecall and voicecall are fully defined
* in src/voicecall.c; we need (read) access to the
* call objects, so partially redefine them here.
*/
struct ofono_voicecall {
GSList *call_list;
/* ... */
};
struct voicecall {
struct ofono_call *call;
/* ... */
};
static inline struct ril_voicecall *ril_voicecall_get_data(
struct ofono_voicecall *vc)
{
@@ -166,38 +154,76 @@ static GSList *ril_voicecall_parse_clcc(const void *data, guint len)
}
/* Valid call statuses have value >= 0 */
static int call_status_with_id(struct ofono_voicecall *vc, int id)
static int ril_voicecall_status_with_id(struct ofono_voicecall *vc,
unsigned int id)
{
GSList *l;
struct voicecall *v;
struct ofono_call *call = ofono_voicecall_find_call(vc, id);
GASSERT(vc);
return call ? call->status : -1;
}
for (l = vc->call_list; l; l = l->next) {
v = l->data;
if (v->call->id == id) {
return v->call->status;
/* Tries to parse the payload as a uint followed by a string */
static int ril_voicecall_parse_lastcause_1(const void *data, guint len)
{
int result = -1;
if (len > 8) {
int code;
char *msg = NULL;
GRilIoParser rilp;
grilio_parser_init(&rilp, data, len);
if (grilio_parser_get_int32(&rilp, &code) && code >= 0 &&
(msg = grilio_parser_get_utf8(&rilp)) &&
grilio_parser_at_end(&rilp)) {
DBG("%d \"%s\"", code, msg);
result = code;
}
g_free(msg);
}
return -1;
return result;
}
static void ril_voicecall_lastcause_cb(GRilIoChannel *io, int status,
const void *data, guint len, void *user_data)
{
struct lastcause_req *reqdata = user_data;
struct ofono_voicecall *vc = reqdata->vc;
int tmp;
struct ril_voicecall *vd = reqdata->vd;
struct ofono_voicecall *vc = vd->vc;
int id = reqdata->id;
int call_status;
enum ofono_disconnect_reason reason = OFONO_DISCONNECT_REASON_ERROR;
int last_cause = CALL_FAIL_ERROR_UNSPECIFIED;
GRilIoParser rilp;
grilio_parser_init(&rilp, data, len);
if (grilio_parser_get_int32(&rilp, &tmp) && tmp > 0) {
grilio_parser_get_int32(&rilp, &last_cause);
int last_cause;
/*
* According to ril.h:
*
* "response" is a "int *"
* ((int *)response)[0] is RIL_LastCallFailCause. GSM failure
* reasons are mapped to cause codes defined in TS 24.008 Annex H
* where possible.
*
* However some RILs feel free to invent their own formats,
* try those first.
*/
last_cause = ril_voicecall_parse_lastcause_1(data, len);
if (last_cause < 0) {
GRilIoParser rilp;
int num, code;
/* Default format described in ril.h */
grilio_parser_init(&rilp, data, len);
if (grilio_parser_get_int32(&rilp, &num) && num == 1 &&
grilio_parser_get_int32(&rilp, &code) &&
grilio_parser_at_end(&rilp)) {
last_cause = code;
} else {
ofono_warn("Unable to parse last call fail cause");
last_cause = CALL_FAIL_ERROR_UNSPECIFIED;
}
}
/*
@@ -208,7 +234,14 @@ static void ril_voicecall_lastcause_cb(GRilIoChannel *io, int status,
* CALL_FAIL_ERROR_UNSPECIFIED, and thus indistinguishable
* from a network failure.
*/
switch (last_cause) {
if (gutil_ints_contains(vd->remote_hangup_reasons, last_cause)) {
DBG("hangup cause %d => remote hangup", last_cause);
reason = OFONO_DISCONNECT_REASON_REMOTE_HANGUP;
} else if (gutil_ints_contains(vd->local_hangup_reasons, last_cause)) {
DBG("hangup cause %d => local hangup", last_cause);
reason = OFONO_DISCONNECT_REASON_LOCAL_HANGUP;
} else {
switch (last_cause) {
case CALL_FAIL_UNOBTAINABLE_NUMBER:
case CALL_FAIL_NORMAL:
case CALL_FAIL_BUSY:
@@ -216,19 +249,19 @@ static void ril_voicecall_lastcause_cb(GRilIoChannel *io, int status,
case CALL_FAIL_CHANNEL_UNACCEPTABLE:
case CALL_FAIL_OPERATOR_DETERMINED_BARRING:
case CALL_FAIL_NO_USER_RESPONDING:
case CALL_FAIL_USER_ALERTING_NO_ANSWER:
case CALL_FAIL_NO_ANSWER_FROM_USER:
case CALL_FAIL_CALL_REJECTED:
case CALL_FAIL_NUMBER_CHANGED:
case CALL_FAIL_ANONYMOUS_CALL_REJECTION:
case CALL_FAIL_PRE_EMPTION:
case CALL_FAIL_DESTINATION_OUT_OF_ORDER:
case CALL_FAIL_INCOMPLETE_NUMBER:
case CALL_FAIL_INVALID_NUMBER_FORMAT:
case CALL_FAIL_FACILITY_REJECTED:
reason = OFONO_DISCONNECT_REASON_REMOTE_HANGUP;
break;
case CALL_FAIL_NORMAL_UNSPECIFIED:
call_status = call_status_with_id(vc, id);
call_status = ril_voicecall_status_with_id(vc, id);
if (call_status == CALL_STATUS_ACTIVE ||
call_status == CALL_STATUS_HELD ||
call_status == CALL_STATUS_DIALING ||
@@ -240,7 +273,7 @@ static void ril_voicecall_lastcause_cb(GRilIoChannel *io, int status,
break;
case CALL_FAIL_ERROR_UNSPECIFIED:
call_status = call_status_with_id(vc, id);
call_status = ril_voicecall_status_with_id(vc, id);
if (call_status == CALL_STATUS_DIALING ||
call_status == CALL_STATUS_ALERTING) {
reason = OFONO_DISCONNECT_REASON_REMOTE_HANGUP;
@@ -250,6 +283,7 @@ static void ril_voicecall_lastcause_cb(GRilIoChannel *io, int status,
default:
reason = OFONO_DISCONNECT_REASON_ERROR;
break;
}
}
ofono_info("Call %d ended with RIL cause %d -> ofono reason %d",
@@ -295,7 +329,7 @@ static void ril_voicecall_clcc_poll_cb(GRilIoChannel *io, int status,
struct lastcause_req *reqdata =
g_new0(struct lastcause_req, 1);
reqdata->vc = vd->vc;
reqdata->vd = vd;
reqdata->id = oc->id;
grilio_queue_send_request_full(vd->q, NULL,
RIL_REQUEST_LAST_CALL_FAIL_CAUSE,
@@ -596,11 +630,6 @@ static void ril_voicecall_send_dtmf_cb(GRilIoChannel *io, int status,
vd->send_dtmf_id = 0;
if (status == RIL_E_SUCCESS) {
/* Remove sent DTMF character from queue */
gchar *tmp = g_strdup(vd->tone_queue + 1);
g_free(vd->tone_queue);
vd->tone_queue = tmp;
/* Send the next one */
ril_voicecall_send_one_dtmf(vd);
} else {
@@ -611,12 +640,15 @@ static void ril_voicecall_send_dtmf_cb(GRilIoChannel *io, int status,
static void ril_voicecall_send_one_dtmf(struct ril_voicecall *vd)
{
if (!vd->send_dtmf_id && vd->tone_queue && vd->tone_queue[0]) {
if (!vd->send_dtmf_id && gutil_ring_size(vd->dtmf_queue) > 0) {
GRilIoRequest *req = grilio_request_sized_new(4);
const char dtmf_char = (char)
GPOINTER_TO_UINT(gutil_ring_get(vd->dtmf_queue));
/* RIL wants just one character */
DBG("%c", vd->tone_queue[0]);
grilio_request_append_utf8_chars(req, vd->tone_queue, 1);
GASSERT(dtmf_char);
DBG("%c", dtmf_char);
grilio_request_append_utf8_chars(req, &dtmf_char, 1);
vd->send_dtmf_id = grilio_queue_send_request_full(vd->q, req,
RIL_REQUEST_DTMF, ril_voicecall_send_dtmf_cb, NULL, vd);
grilio_request_unref(req);
@@ -629,43 +661,34 @@ static void ril_voicecall_send_dtmf(struct ofono_voicecall *vc,
struct ril_voicecall *vd = ril_voicecall_get_data(vc);
struct ofono_error error;
DBG("Queue '%s'",dtmf);
/*
* Queue any incoming DTMF (up to MAX_DTMF_BUFFER characters),
* send them to RIL one-by-one, immediately call back
* core with no error
* Queue any incoming DTMF, send them to RIL one-by-one,
* immediately call back core with no error
*/
g_strlcat(vd->tone_queue, dtmf, MAX_DTMF_BUFFER);
ril_voicecall_send_one_dtmf(vd);
DBG("Queue '%s'", dtmf);
while (*dtmf) {
gutil_ring_put(vd->dtmf_queue, GUINT_TO_POINTER(*dtmf));
dtmf++;
}
ril_voicecall_send_one_dtmf(vd);
cb(ril_error_ok(&error), data);
}
static void ril_voicecall_clear_dtmf_queue(struct ril_voicecall *vd)
{
g_free(vd->tone_queue);
vd->tone_queue = g_strnfill(MAX_DTMF_BUFFER + 1, '\0');
gutil_ring_clear(vd->dtmf_queue);
if (vd->send_dtmf_id) {
grilio_channel_cancel_request(vd->io, vd->send_dtmf_id, FALSE);
vd->send_dtmf_id = 0;
}
}
static void ril_voicecall_clcc_poll_on_success(GRilIoChannel *io,
int status, const void *data, guint len, void *user_data)
{
if (status == RIL_E_SUCCESS) {
ril_voicecall_clcc_poll((struct ril_voicecall *)user_data);
}
}
static void ril_voicecall_create_multiparty(struct ofono_voicecall *vc,
ofono_voicecall_cb_t cb, void *data)
{
struct ril_voicecall *vd = ril_voicecall_get_data(vc);
grilio_queue_send_request_full(vd->q, NULL, RIL_REQUEST_CONFERENCE,
ril_voicecall_clcc_poll_on_success, NULL, vd);
ril_voicecall_request(RIL_REQUEST_CONFERENCE,
vc, 0, NULL, cb, data);
}
static void ril_voicecall_transfer(struct ofono_voicecall *vc,
@@ -678,14 +701,17 @@ static void ril_voicecall_transfer(struct ofono_voicecall *vc,
static void ril_voicecall_private_chat(struct ofono_voicecall *vc, int id,
ofono_voicecall_cb_t cb, void *data)
{
struct ril_voicecall *vd = ril_voicecall_get_data(vc);
GRilIoRequest *req = grilio_request_sized_new(8);
struct ofono_error error;
DBG("Private chat with id %d", id);
grilio_request_append_int32(req, 1);
grilio_request_append_int32(req, id);
grilio_queue_send_request_full(vd->q, req,
RIL_REQUEST_SEPARATE_CONNECTION,
ril_voicecall_clcc_poll_on_success, NULL, vd);
ril_voicecall_request(RIL_REQUEST_SEPARATE_CONNECTION,
vc, 0, req, NULL, NULL);
grilio_request_unref(req);
cb(ril_error_ok(&error), data);
}
static void ril_voicecall_swap_without_accept(struct ofono_voicecall *vc,
@@ -811,12 +837,16 @@ static int ril_voicecall_probe(struct ofono_voicecall *vc, unsigned int vendor,
void *data)
{
struct ril_modem *modem = data;
const struct ril_slot_config *cfg = &modem->config;
struct ril_voicecall *vd;
DBG("");
vd = g_new0(struct ril_voicecall, 1);
vd->io = grilio_channel_ref(ril_modem_io(modem));
vd->q = grilio_queue_new(vd->io);
vd->dtmf_queue = gutil_ring_new();
vd->local_hangup_reasons = gutil_ints_ref(cfg->local_hangup_reasons);
vd->remote_hangup_reasons = gutil_ints_ref(cfg->remote_hangup_reasons);
vd->vc = vc;
vd->timer_id = g_idle_add(ril_delayed_register, vd);
if (modem->ecclist_file) {
@@ -847,7 +877,9 @@ static void ril_voicecall_remove(struct ofono_voicecall *vc)
grilio_channel_unref(vd->io);
grilio_queue_cancel_all(vd->q, FALSE);
grilio_queue_unref(vd->q);
g_free(vd->tone_queue);
gutil_ring_unref(vd->dtmf_queue);
gutil_ints_unref(vd->local_hangup_reasons);
gutil_ints_unref(vd->remote_hangup_reasons);
g_free(vd);
}

View File

@@ -4,6 +4,7 @@
*
* Copyright (C) 2014 Jolla Ltd
* Contact: Miia Leinonen
* Copyright (C) 2014 Canonical Ltd
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -20,65 +21,63 @@
*
*/
#include <errno.h>
#include <glib.h>
#include <ofono/log.h>
#include <ofono/modem.h>
#include <ofono/call-barring.h>
#include "common.h"
#include "gril.h"
#include "call-barring.h"
#include "rilmodem.h"
#include "ril_constants.h"
/* See 3GPP 27.007 7.4 for possible values */
#define RIL_MAX_SERVICE_LENGTH 3
/*
* ril.h does not state that string count must be given, but that is
* still expected by the modem
*/
#define RIL_QUERY_STRING_COUNT 4
#define RIL_SET_STRING_COUNT 5
#define RIL_SET_PW_STRING_COUNT 3
#define RIL_LENGTH_ZERO 0
struct barring_data {
GRil *ril;
guint timer_id;
};
/*
* RIL modems do not support 7 as default bearer class. According to TS 22.030
* Annex C: When service code is not given it corresponds to "All tele and
* bearer services"
*/
#define FIXUP_CLS() \
if (cls == BEARER_CLASS_DEFAULT) \
cls = SERVICE_CLASS_NONE \
static void ril_call_barring_query_cb(struct ril_msg *message,
gpointer user_data)
{
struct cb_data *cbd = user_data;
struct parcel rilp;
struct ofono_error error;
ofono_call_barring_query_cb_t cb = cbd->cb;
int bearer_class = 0;
struct barring_data *bd = cbd->user;
struct parcel rilp;
int bearer_class;
if (message->error != RIL_E_SUCCESS) {
ofono_error("Call Barring query failed, err: %i",
message->error);
decode_ril_error(&error, "FAIL");
goto out;
}
if (message->error != RIL_E_SUCCESS)
goto error;
ril_util_init_parcel(message, &rilp);
g_ril_init_parcel(message, &rilp);
/* TODO: infineon returns two integers, use a quirk here */
if (parcel_r_int32(&rilp) < 1)
goto error;
/*
* Services for which the specified barring facility is active.
* "0" means "disabled for all, -1 if unknown"
*/
parcel_r_int32(&rilp); /* count - we know there is only 1 */
bearer_class = parcel_r_int32(&rilp);
DBG("Active services: %i", bearer_class);
decode_ril_error(&error, "OK");
if (bearer_class < 0 || rilp.malformed)
goto error;
out:
cb(&error, bearer_class, cbd->data);
g_ril_append_print_buf(bd->ril, "{%d}", bearer_class);
g_ril_print_response(bd->ril, message);
CALLBACK_WITH_SUCCESS(cb, bearer_class, cbd->data);
return;
error:
CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
}
static void ril_call_barring_query(struct ofono_call_barring *cb,
@@ -87,65 +86,67 @@ static void ril_call_barring_query(struct ofono_call_barring *cb,
void *data)
{
struct barring_data *bd = ofono_call_barring_get_data(cb);
struct cb_data *cbd = cb_data_new(callback, data);
struct cb_data *cbd = cb_data_new(callback, data, bd);
struct parcel rilp;
int ret = 0;
char cls_textual[RIL_MAX_SERVICE_LENGTH];
char svcs_str[4];
DBG("lock: %s, services to query: %i", lock, cls);
DBG("lock: %s, services to query: %d", lock, cls);
/*
* RIL modems do not support 7 as default bearer class. According to
* the 22.030 Annex C: When service code is not given it corresponds to
* "All tele and bearer services"
*/
if (cls == BEARER_CLASS_DEFAULT)
cls = SERVICE_CLASS_NONE;
FIXUP_CLS();
sprintf(cls_textual, "%d", cls);
/*
* See 3GPP 27.007 7.4 for parameter descriptions.
* According to ril.h password should be empty string "" when not
* needed, but in reality we only need to give string length as 0
*/
parcel_init(&rilp);
parcel_w_int32(&rilp, RIL_QUERY_STRING_COUNT); /* Nbr of strings */
parcel_w_string(&rilp, (char *) lock); /* Facility code */
parcel_w_int32(&rilp, RIL_LENGTH_ZERO); /* Password length */
parcel_w_string(&rilp, (char *) cls_textual);
parcel_w_string(&rilp, NULL); /* AID (for FDN, not yet supported) */
parcel_w_int32(&rilp, 4); /* # of strings */
parcel_w_string(&rilp, lock);
parcel_w_string(&rilp, ""); /* Password is empty when not needed */
snprintf(svcs_str, sizeof(svcs_str), "%d", cls);
parcel_w_string(&rilp, svcs_str);
parcel_w_string(&rilp, NULL); /* AID (for FDN, not yet supported) */
ret = g_ril_send(bd->ril, RIL_REQUEST_QUERY_FACILITY_LOCK,
rilp.data, rilp.size, ril_call_barring_query_cb,
cbd, g_free);
g_ril_append_print_buf(bd->ril, "(%s,\"\",%s,(null))",
lock, svcs_str);
parcel_free(&rilp);
if (g_ril_send(bd->ril, RIL_REQUEST_QUERY_FACILITY_LOCK, &rilp,
ril_call_barring_query_cb, cbd, g_free) > 0)
return;
if (ret <= 0) {
ofono_error("Sending Call Barring query failed, err: %i", ret);
g_free(cbd);
CALLBACK_WITH_FAILURE(callback, -1, data);
}
g_free(cbd);
CALLBACK_WITH_FAILURE(callback, -1, data);
}
static void ril_call_barring_set_cb(struct ril_msg *message, gpointer user_data)
{
struct cb_data *cbd = user_data;
struct ofono_error error;
ofono_call_barring_set_cb_t cb = cbd->cb;
struct barring_data *bd = cbd->user;
struct parcel rilp;
int retries = -1;
if (message->error != RIL_E_SUCCESS) {
ofono_error("Call Barring Set request failed, err: %i",
message->error);
decode_ril_error(&error, "FAIL");
goto out;
}
if (message->error != RIL_E_SUCCESS)
goto error;
decode_ril_error(&error, "OK");
g_ril_init_parcel(message, &rilp);
out:
cb(&error, cbd->data);
/* mako reply has no payload for call barring */
if (parcel_data_avail(&rilp) == 0)
goto done;
if (parcel_r_int32(&rilp) != 1)
goto error;
retries = parcel_r_int32(&rilp);
if (rilp.malformed)
goto error;
done:
g_ril_append_print_buf(bd->ril, "{%d}", retries);
g_ril_print_response(bd->ril, message);
CALLBACK_WITH_SUCCESS(cb, cbd->data);
return;
error:
CALLBACK_WITH_FAILURE(cb, cbd->data);
}
static void ril_call_barring_set(struct ofono_call_barring *cb,
@@ -155,69 +156,54 @@ static void ril_call_barring_set(struct ofono_call_barring *cb,
void *data)
{
struct barring_data *bd = ofono_call_barring_get_data(cb);
struct cb_data *cbd = cb_data_new(callback, data);
struct cb_data *cbd = cb_data_new(callback, data, bd);
struct parcel rilp;
int ret = 0;
char cls_textual[RIL_MAX_SERVICE_LENGTH];
char svcs_str[4];
DBG("lock: %s, enable: %i, bearer class: %i", lock, enable, cls);
DBG("lock: %s, enable: %d, bearer class: %d", lock, enable, cls);
/*
* RIL modem does not support 7 as default bearer class. According to
* the 22.030 Annex C: When service code is not given it corresponds to
* "All tele and bearer services"
*/
if (cls == BEARER_CLASS_DEFAULT)
cls = SERVICE_CLASS_NONE;
FIXUP_CLS();
sprintf(cls_textual, "%d", cls);
/* See 3GPP 27.007 7.4 for parameter descriptions */
parcel_init(&rilp);
parcel_w_int32(&rilp, RIL_SET_STRING_COUNT); /* Nbr of strings */
parcel_w_string(&rilp, (char *) lock); /* Facility code */
if (enable)
parcel_w_string(&rilp, RIL_FACILITY_LOCK);
else
parcel_w_string(&rilp, RIL_FACILITY_UNLOCK);
parcel_w_string(&rilp, (char *) passwd);
parcel_w_string(&rilp, (char *) cls_textual);
parcel_w_int32(&rilp, 5); /* # of strings */
parcel_w_string(&rilp, lock);
parcel_w_string(&rilp, enable ? "1" : "0");
parcel_w_string(&rilp, passwd);
snprintf(svcs_str, sizeof(svcs_str), "%d", cls);
parcel_w_string(&rilp, svcs_str);
parcel_w_string(&rilp, NULL); /* AID (for FDN, not yet supported) */
ret = g_ril_send(bd->ril, RIL_REQUEST_SET_FACILITY_LOCK,
rilp.data, rilp.size, ril_call_barring_set_cb,
cbd, g_free);
g_ril_append_print_buf(bd->ril, "(%s,%s,%s,%s,(null))",
lock, enable ? "1" : "0", passwd, svcs_str);
parcel_free(&rilp);
if (g_ril_send(bd->ril, RIL_REQUEST_SET_FACILITY_LOCK, &rilp,
ril_call_barring_set_cb, cbd, g_free) > 0)
return;
if (ret <= 0) {
ofono_error("Sending Call Barring Set request failed, err: %i",
ret);
g_free(cbd);
CALLBACK_WITH_FAILURE(callback, data);
}
g_free(cbd);
CALLBACK_WITH_FAILURE(callback, data);
}
static void ril_call_barring_set_passwd_cb(struct ril_msg *message,
gpointer user_data)
{
struct cb_data *cbd = user_data;
struct ofono_error error;
ofono_call_barring_set_cb_t cb = cbd->cb;
struct barring_data *bd = cbd->user;
if (message->error != RIL_E_SUCCESS) {
ofono_error("Call Barring Set PW req failed, err: %i",
message->error);
decode_ril_error(&error, "FAIL");
goto out;
ofono_error("%s: set password failed, err: %s", __func__,
ril_error_to_string(message->error));
goto error;
}
decode_ril_error(&error, "OK");
g_ril_print_response_no_args(bd->ril, message);
out:
cb(&error, cbd->data);
CALLBACK_WITH_SUCCESS(cb, cbd->data);
return;
error:
CALLBACK_WITH_FAILURE(cb, cbd->data);
}
static void ril_call_barring_set_passwd(struct ofono_call_barring *barr,
@@ -228,38 +214,32 @@ static void ril_call_barring_set_passwd(struct ofono_call_barring *barr,
void *data)
{
struct barring_data *bd = ofono_call_barring_get_data(barr);
struct cb_data *cbd = cb_data_new(cb, data);
struct cb_data *cbd = cb_data_new(cb, data, bd);
struct parcel rilp;
int ret = 0;
DBG("");
DBG("lock %s old %s new %s", lock, old_passwd, new_passwd);
parcel_init(&rilp);
parcel_w_int32(&rilp, RIL_SET_PW_STRING_COUNT); /* Nbr of strings */
parcel_w_string(&rilp, (char *) lock); /* Facility code */
parcel_w_string(&rilp, (char *) old_passwd);
parcel_w_string(&rilp, (char *) new_passwd);
ret = g_ril_send(bd->ril, RIL_REQUEST_CHANGE_BARRING_PASSWORD,
rilp.data, rilp.size, ril_call_barring_set_passwd_cb,
cbd, g_free);
parcel_w_int32(&rilp, 3); /* # of strings */
parcel_w_string(&rilp, lock);
parcel_w_string(&rilp, old_passwd);
parcel_w_string(&rilp, new_passwd);
parcel_free(&rilp);
g_ril_append_print_buf(bd->ril, "(%s,%s,%s)",
lock, old_passwd, new_passwd);
if (ret <= 0) {
ofono_error("Sending Call Barring Set PW req failed, err: %i",
ret);
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, data);
}
if (g_ril_send(bd->ril, RIL_REQUEST_CHANGE_BARRING_PASSWORD, &rilp,
ril_call_barring_set_passwd_cb, cbd, g_free) > 0)
return;
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, data);
}
static gboolean ril_delayed_register(gpointer user_data)
{
struct ofono_call_barring *cb = user_data;
struct barring_data *bd = ofono_call_barring_get_data(cb);
bd->timer_id = 0;
ofono_call_barring_register(cb);
return FALSE;
@@ -270,10 +250,13 @@ static int ril_call_barring_probe(struct ofono_call_barring *cb,
{
GRil *ril = user;
struct barring_data *bd = g_try_new0(struct barring_data, 1);
if (bd == NULL)
return -ENOMEM;
bd->ril = g_ril_clone(ril);
ofono_call_barring_set_data(cb, bd);
bd->timer_id = g_timeout_add_seconds(2, ril_delayed_register, cb);
g_idle_add(ril_delayed_register, cb);
return 0;
}
@@ -283,9 +266,6 @@ static void ril_call_barring_remove(struct ofono_call_barring *cb)
struct barring_data *data = ofono_call_barring_get_data(cb);
ofono_call_barring_set_data(cb, NULL);
if (data->timer_id > 0)
g_source_remove(data->timer_id);
g_ril_unref(data->ril);
g_free(data);
}

View File

@@ -3,8 +3,9 @@
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2013-2014 Jolla Ltd
* Copyright (C) 2013 Jolla Ltd
* Contact: Jussi Kangas <jussi.kangas@tieto.com>
* Copyright (C) 2014 Canonical Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -35,39 +36,235 @@
#include <ofono/log.h>
#include <ofono/modem.h>
#include <ofono/call-forwarding.h>
#include "common.h"
#include "gril.h"
#include "grilutil.h"
#include "rilmodem.h"
#include "ril_constants.h"
#include "common.h"
struct forw_data {
GRil *ril;
guint timer_id;
int last_cls;
};
enum call_forward_cmd {
CF_ACTION_DISABLE,
CF_ACTION_ENABLE,
CF_ACTION_UNUSED,
CF_ACTION_REGISTRATION,
CF_ACTION_ERASURE,
};
static void ril_query_call_fwd_cb(struct ril_msg *message, gpointer user_data)
{
struct cb_data *cbd = user_data;
struct forw_data *fd = ofono_call_forwarding_get_data(cbd->user);
ofono_call_forwarding_query_cb_t cb = cbd->cb;
struct ofono_call_forwarding_condition *list;
struct parcel rilp;
unsigned int list_size;
unsigned int i;
if (message->error != RIL_E_SUCCESS) {
ofono_error("%s: rild error: %s", __func__,
ril_error_to_string(message->error));
goto error;
}
g_ril_init_parcel(message, &rilp);
if (rilp.size < sizeof(int32_t))
goto error;
list_size = parcel_r_int32(&rilp);
if (list_size == 0) {
list = g_new0(struct ofono_call_forwarding_condition, 1);
list_size = 1;
list->status = 0;
list->cls = fd->last_cls;
goto done;
}
list = g_new0(struct ofono_call_forwarding_condition, list_size);
g_ril_append_print_buf(fd->ril, "{");
for (i = 0; i < list_size; i++) {
char *str;
list[i].status = parcel_r_int32(&rilp);
parcel_r_int32(&rilp); /* skip reason */
list[i].cls = parcel_r_int32(&rilp);
list[i].phone_number.type = parcel_r_int32(&rilp);
str = parcel_r_string(&rilp);
if (str != NULL) {
strncpy(list[i].phone_number.number, str,
OFONO_MAX_PHONE_NUMBER_LENGTH);
g_free(str);
list[i].phone_number.number[
OFONO_MAX_PHONE_NUMBER_LENGTH] = '\0';
}
list[i].time = parcel_r_int32(&rilp);
if (rilp.malformed) {
ofono_error("%s: malformed parcel", __func__);
g_free(list);
goto error;
}
g_ril_append_print_buf(fd->ril, "%s [%d,%d,%d,%s,%d]",
print_buf,
list[i].status,
list[i].cls,
list[i].phone_number.type,
list[i].phone_number.number,
list[i].time);
}
g_ril_append_print_buf(fd->ril, "%s}", print_buf);
g_ril_print_response(fd->ril, message);
done:
CALLBACK_WITH_SUCCESS(cb, (int) list_size, list, cbd->data);
g_free(list);
return;
error:
CALLBACK_WITH_FAILURE(cb, 0, NULL, cbd->data);
}
static void ril_set_forward_cb(struct ril_msg *message, gpointer user_data)
{
struct cb_data *cbd = user_data;
ofono_call_forwarding_set_cb_t cb = cbd->cb;
struct forw_data *fd = ofono_call_forwarding_get_data(cbd->user);
if (message->error == RIL_E_SUCCESS)
CALLBACK_WITH_SUCCESS(cb, cbd->data);
else {
ofono_error("CF setting failed");
if (message->error != RIL_E_SUCCESS) {
ofono_error("%s: failed; rild error: %s", __func__,
ril_error_to_string(message->error));
CALLBACK_WITH_FAILURE(cb, cbd->data);
}
g_ril_print_response_no_args(fd->ril, message);
CALLBACK_WITH_SUCCESS(cb, cbd->data);
}
/*
* Modem seems to respond with error to all queries or settings made with
* bearer class BEARER_CLASS_DEFAULT. Design decision: If given class is
* BEARER_CLASS_DEFAULT let's map it to SERVICE_CLASS_NONE as with it e.g.
* ./send-ussd '*21*<phone_number>#' returns cls:53 i.e. 1+4+16+32 as
* service class.
*/
#define FIXUP_CLS() \
if (cls == BEARER_CLASS_DEFAULT) \
cls = SERVICE_CLASS_NONE \
/*
* Activation/deactivation/erasure actions, have no number associated with them,
* but apparently rild expects a number anyway. So fields need to be filled.
* Otherwise there is no response.
*/
#define APPEND_DUMMY_NUMBER() \
parcel_w_int32(&rilp, 0x81); \
parcel_w_string(&rilp, "1234567890") \
/*
* Time has no real meaing for action commands other then registration, so
* if not needed, set arbitrary 60s time so rild doesn't return an error.
*/
#define APPEND_DUMMY_TIME() \
parcel_w_int32(&rilp, 60);
static void ril_activate(struct ofono_call_forwarding *cf,
int type, int cls,
ofono_call_forwarding_set_cb_t cb, void *data)
{
struct forw_data *fd = ofono_call_forwarding_get_data(cf);
struct cb_data *cbd = cb_data_new(cb, data, cf);
struct parcel rilp;
FIXUP_CLS();
parcel_init(&rilp);
parcel_w_int32(&rilp, 1); /* Activation: 1 */
parcel_w_int32(&rilp, type);
parcel_w_int32(&rilp, cls);
APPEND_DUMMY_NUMBER();
APPEND_DUMMY_TIME();
g_ril_append_print_buf(fd->ril, "(action: 1, type: %d cls: %d "
"number type: %d number: %s time: %d)",
type, cls, 0x81, "1234567890", 60);
if (g_ril_send(fd->ril, RIL_REQUEST_SET_CALL_FORWARD,
&rilp, ril_set_forward_cb, cbd, g_free) > 0)
return;
CALLBACK_WITH_FAILURE(cb, cbd->data);
g_free(cbd);
}
static void ril_erasure(struct ofono_call_forwarding *cf,
int type, int cls,
ofono_call_forwarding_set_cb_t cb, void *data)
{
struct forw_data *fd = ofono_call_forwarding_get_data(cf);
struct cb_data *cbd = cb_data_new(cb, data, cf);
struct parcel rilp;
FIXUP_CLS();
parcel_init(&rilp);
parcel_w_int32(&rilp, 4); /* Erasure: 4 */
parcel_w_int32(&rilp, type);
parcel_w_int32(&rilp, cls);
APPEND_DUMMY_NUMBER();
APPEND_DUMMY_TIME();
g_ril_append_print_buf(fd->ril, "(action: 4, type: %d cls: %d "
"number type: %d number: %s time: %d)",
type, cls, 0x81, "1234567890", 60);
if (g_ril_send(fd->ril, RIL_REQUEST_SET_CALL_FORWARD,
&rilp, ril_set_forward_cb, cbd, g_free) > 0)
return;
CALLBACK_WITH_FAILURE(cb, cbd->data);
g_free(cbd);
}
static void ril_deactivate(struct ofono_call_forwarding *cf,
int type, int cls,
ofono_call_forwarding_set_cb_t cb, void *data)
{
struct forw_data *fd = ofono_call_forwarding_get_data(cf);
struct cb_data *cbd = cb_data_new(cb, data, cf);
struct parcel rilp;
FIXUP_CLS();
parcel_init(&rilp);
parcel_w_int32(&rilp, 0); /* Deactivation: 0 */
parcel_w_int32(&rilp, type);
parcel_w_int32(&rilp, cls);
APPEND_DUMMY_NUMBER();
APPEND_DUMMY_TIME();
g_ril_append_print_buf(fd->ril, "(action: 0, type: %d cls: %d "
"number type: %d number: %s time: %d)",
type, cls, 0x81, "1234567890", 60);
if (g_ril_send(fd->ril, RIL_REQUEST_SET_CALL_FORWARD,
&rilp, ril_set_forward_cb, cbd, g_free) > 0)
return;
CALLBACK_WITH_FAILURE(cb, cbd->data);
g_free(cbd);
}
static void ril_registration(struct ofono_call_forwarding *cf, int type,
@@ -77,173 +274,31 @@ static void ril_registration(struct ofono_call_forwarding *cf, int type,
void *data)
{
struct forw_data *fd = ofono_call_forwarding_get_data(cf);
struct cb_data *cbd = cb_data_new(cb, data);
struct cb_data *cbd = cb_data_new(cb, data, cf);
struct parcel rilp;
int ret = 0;
ofono_info("cf registration");
FIXUP_CLS();
parcel_init(&rilp);
parcel_w_int32(&rilp, CF_ACTION_REGISTRATION);
parcel_w_int32(&rilp, 3); /* Registration: 3 */
parcel_w_int32(&rilp, type);
/*
* Modem seems to respond with error to all queries
* or settings made with bearer class
* BEARER_CLASS_DEFAULT. Design decision: If given
* class is BEARER_CLASS_DEFAULT let's map it to
* BEARER_CLASS_VOICE as per RIL design.
*/
if (cls == BEARER_CLASS_DEFAULT)
cls = BEARER_CLASS_VOICE;
parcel_w_int32(&rilp, cls);
parcel_w_int32(&rilp, number->type);
parcel_w_string(&rilp, (char *) number->number);
parcel_w_string(&rilp, number->number);
parcel_w_int32(&rilp, time);
ret = g_ril_send(fd->ril, RIL_REQUEST_SET_CALL_FORWARD,
rilp.data, rilp.size, ril_set_forward_cb, cbd, g_free);
g_ril_append_print_buf(fd->ril, "(action: 3, type: %d cls: %d "
"number type: %d number: %s time: %d)",
type, cls, number->type, number->number,
time);
/* In case of error free cbd and return the cb with failure */
if (ret <= 0) {
ofono_error("CF registration failed");
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, data);
}
}
if (g_ril_send(fd->ril, RIL_REQUEST_SET_CALL_FORWARD,
&rilp, ril_set_forward_cb, cbd, g_free) > 0)
return;
static void ril_send_forward_cmd(struct ofono_call_forwarding *cf,
int type, int cls,
ofono_call_forwarding_set_cb_t cb, void *data,
int action)
{
struct forw_data *fd = ofono_call_forwarding_get_data(cf);
struct cb_data *cbd = cb_data_new(cb, data);
struct parcel rilp;
int ret = 0;
parcel_init(&rilp);
parcel_w_int32(&rilp, action);
parcel_w_int32(&rilp, type);
/*
* Modem seems to respond with error to all queries
* or settings made with bearer class
* BEARER_CLASS_DEFAULT. Design decision: If given
* class is BEARER_CLASS_DEFAULT let's map it to
* BEARER_CLASS_VOICE as per RIL design.
*/
if (cls == BEARER_CLASS_DEFAULT)
cls = BEARER_CLASS_VOICE;
parcel_w_int32(&rilp, cls); /* Service class */
/* Following 3 values have no real meaning in erasure
* but apparently RIL expects them so fields need to
* be filled. Otherwise there is no response
* */
parcel_w_int32(&rilp, 0x81); /* TOA unknown */
parcel_w_string(&rilp, "1234567890");
parcel_w_int32(&rilp, 60);
ret = g_ril_send(fd->ril, RIL_REQUEST_SET_CALL_FORWARD,
rilp.data, rilp.size, ril_set_forward_cb, cbd, g_free);
parcel_free(&rilp);
/* In case of error free cbd and return the cb with failure */
if (ret <= 0) {
ofono_error("CF action failed");
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, data);
}
}
static void ril_erasure(struct ofono_call_forwarding *cf,
int type, int cls,
ofono_call_forwarding_set_cb_t cb, void *data)
{
ofono_info("CF_ACTION_ERASURE");
ril_send_forward_cmd(cf, type, cls, cb, data, CF_ACTION_ERASURE);
}
static void ril_deactivate(struct ofono_call_forwarding *cf,
int type, int cls,
ofono_call_forwarding_set_cb_t cb, void *data)
{
ofono_info("CF_ACTION_DISABLE");
ril_send_forward_cmd(cf, type, cls, cb, data, CF_ACTION_DISABLE);
}
static void ril_activate(struct ofono_call_forwarding *cf,
int type, int cls,
ofono_call_forwarding_set_cb_t cb, void *data)
{
ofono_info("CF_ACTION_ENABLE");
ril_send_forward_cmd(cf, type, cls, cb, data, CF_ACTION_ENABLE);
}
static void ril_query_cb(struct ril_msg *message, gpointer user_data)
{
struct cb_data *cbd = user_data;
ofono_call_forwarding_query_cb_t cb = cbd->cb;
struct ofono_call_forwarding_condition *list = NULL;
struct parcel rilp;
int nmbr_of_resps = 0;
int i;
if (message->error == RIL_E_SUCCESS) {
ril_util_init_parcel(message, &rilp);
nmbr_of_resps = parcel_r_int32(&rilp);
list = g_new0(
struct ofono_call_forwarding_condition,
nmbr_of_resps);
for (i = 0; i < nmbr_of_resps; i++) {
char *str = NULL;
list[i].status = parcel_r_int32(&rilp);
parcel_r_int32(&rilp);
list[i].cls = parcel_r_int32(&rilp);
list[i].phone_number.type = parcel_r_int32(&rilp);
str = parcel_r_string(&rilp);
if (str) {
strncpy(list[i].phone_number.number,
str,
OFONO_MAX_PHONE_NUMBER_LENGTH);
list[i].phone_number.number[
OFONO_MAX_PHONE_NUMBER_LENGTH] = '\0';
g_free(str);
}
list[i].time = parcel_r_int32(&rilp);
}
CALLBACK_WITH_SUCCESS(cb, nmbr_of_resps, list, cbd->data);
g_free(list);
} else {
ofono_error("CF query failed");
CALLBACK_WITH_FAILURE(cb, 0, NULL, cbd->data);
}
CALLBACK_WITH_FAILURE(cb, cbd->data);
g_free(cbd);
}
static void ril_query(struct ofono_call_forwarding *cf, int type, int cls,
@@ -251,60 +306,36 @@ static void ril_query(struct ofono_call_forwarding *cf, int type, int cls,
void *data)
{
struct forw_data *fd = ofono_call_forwarding_get_data(cf);
struct cb_data *cbd = cb_data_new(cb, data);
struct cb_data *cbd = cb_data_new(cb, data, cf);
struct parcel rilp;
int ret = 0;
ofono_info("cf query");
FIXUP_CLS();
parcel_init(&rilp);
parcel_w_int32(&rilp, 2);
parcel_w_int32(&rilp, 2); /* Interrogation: 2 */
parcel_w_int32(&rilp, type);
/*
* Modem seems to respond with error to all queries
* or settings made with bearer class
* BEARER_CLASS_DEFAULT. Design decision: If given
* class is BEARER_CLASS_DEFAULT let's map it to
* SERVICE_CLASS_NONE as per RIL design.
*/
if (cls == BEARER_CLASS_DEFAULT)
cls = SERVICE_CLASS_NONE;
parcel_w_int32(&rilp, cls);
APPEND_DUMMY_NUMBER();
APPEND_DUMMY_TIME();
/* Following 3 values have no real meaning in query
* but apparently RIL expects them so fields need to
* be filled. Otherwise there is no response
*/
g_ril_append_print_buf(fd->ril, "(action: 2, type: %d cls: %d "
"number type: %d number: %s time: %d)",
type, cls, 0x81, "1234567890", 60);
parcel_w_int32(&rilp, 0x81); /* TOA unknown */
fd->last_cls = cls;
parcel_w_string(&rilp, "1234567890");
if (g_ril_send(fd->ril, RIL_REQUEST_QUERY_CALL_FORWARD_STATUS,
&rilp, ril_query_call_fwd_cb, cbd, g_free) > 0)
return;
parcel_w_int32(&rilp, 60);
ret = g_ril_send(fd->ril, RIL_REQUEST_QUERY_CALL_FORWARD_STATUS,
rilp.data, rilp.size, ril_query_cb, cbd, g_free);
parcel_free(&rilp);
/* In case of error free cbd and return the cb with failure */
if (ret <= 0) {
ofono_error("unable to send CF query");
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, 0, NULL, data);
}
CALLBACK_WITH_FAILURE(cb, 0, NULL, cbd->data);
g_free(cbd);
}
static gboolean ril_delayed_register(gpointer user_data)
{
struct ofono_call_forwarding *cf = user_data;
struct forw_data *fd = ofono_call_forwarding_get_data(cf);
fd->timer_id = 0;
ofono_call_forwarding_register(cf);
return FALSE;
@@ -314,10 +345,23 @@ static int ril_call_forwarding_probe(struct ofono_call_forwarding *cf,
unsigned int vendor, void *user)
{
GRil *ril = user;
struct forw_data *fd = g_try_new0(struct forw_data, 1);
struct forw_data *fd;
fd = g_try_new0(struct forw_data, 1);
if (fd == NULL)
return -ENOMEM;
fd->ril = g_ril_clone(ril);
ofono_call_forwarding_set_data(cf, fd);
fd->timer_id = g_timeout_add_seconds(2, ril_delayed_register, cf);
/*
* ofono_call_forwarding_register() needs to be called after
* the driver has been set in ofono_call_forwarding_create(),
* which calls this function. Most other drivers make
* some kind of capabilities query to the modem, and then
* call register in the callback; we use an idle event instead.
*/
g_idle_add(ril_delayed_register, cf);
return 0;
}
@@ -327,15 +371,12 @@ static void ril_call_forwarding_remove(struct ofono_call_forwarding *cf)
struct forw_data *data = ofono_call_forwarding_get_data(cf);
ofono_call_forwarding_set_data(cf, NULL);
if (data->timer_id > 0)
g_source_remove(data->timer_id);
g_ril_unref(data->ril);
g_free(data);
}
static struct ofono_call_forwarding_driver driver = {
.name = "rilmodem",
.name = RILMODEM,
.probe = ril_call_forwarding_probe,
.remove = ril_call_forwarding_remove,
.erasure = ril_erasure,

View File

@@ -4,6 +4,7 @@
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2013 Jolla Ltd
* Copyright (C) 2013 Canonical Ltd
* Contact: Jussi Kangas <jussi.kangas@tieto.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -36,81 +37,59 @@
#include <ofono/log.h>
#include <ofono/modem.h>
#include <ofono/call-settings.h>
#include "common.h"
#include "gril.h"
#include "grilutil.h"
#include "rilmodem.h"
#include "ril_constants.h"
#include "common.h"
struct settings_data {
GRil *ril;
guint timer_id;
};
static void ril_clip_cb(struct ril_msg *message, gpointer user_data)
{
struct cb_data *cbd = user_data;
ofono_call_settings_status_cb_t cb = cbd->cb;
struct parcel rilp;
int res = 0;
if (message->error == RIL_E_SUCCESS) {
ril_util_init_parcel(message, &rilp);
/* data length of the response */
res = parcel_r_int32(&rilp);
if (res > 0)
res = parcel_r_int32(&rilp);
CALLBACK_WITH_SUCCESS(cb, res, cbd->data);
} else
CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
}
static void ril_set_cb(struct ril_msg *message, gpointer user_data)
{
struct cb_data *cbd = user_data;
struct ofono_call_settings *cs = cbd->user;
struct settings_data *sd = ofono_call_settings_get_data(cs);
ofono_call_settings_set_cb_t cb = cbd->cb;
if (message->error == RIL_E_SUCCESS)
if (message->error == RIL_E_SUCCESS) {
g_ril_print_response_no_args(sd->ril, message);
CALLBACK_WITH_SUCCESS(cb, cbd->data);
else
} else {
CALLBACK_WITH_FAILURE(cb, cbd->data);
}
}
static void ril_cw_set(struct ofono_call_settings *cs, int mode, int cls,
ofono_call_settings_set_cb_t cb, void *data){
ofono_call_settings_set_cb_t cb, void *data)
{
struct settings_data *sd = ofono_call_settings_get_data(cs);
struct cb_data *cbd = cb_data_new(cb, data);
int ret = 0;
struct cb_data *cbd = cb_data_new(cb, data, cs);
int ret;
struct parcel rilp;
parcel_init(&rilp);
parcel_w_int32(&rilp, 2); /* Number of params */
parcel_w_int32(&rilp, mode); /* on/off */
/* Modem seems to respond with error to all queries
/*
* Modem seems to respond with error to all queries
* or settings made with bearer class
* BEARER_CLASS_DEFAULT. Design decision: If given
* class is BEARER_CLASS_DEFAULT let's map it to
* SERVICE_CLASS_VOICE effectively making it the
* default bearer. This in line with API which is
* contains only voice anyways.
* default bearer.
*/
if (cls == BEARER_CLASS_DEFAULT)
cls = BEARER_CLASS_VOICE;
parcel_w_int32(&rilp, cls); /* Service class */
parcel_init(&rilp);
parcel_w_int32(&rilp, 2); /* Number of params */
parcel_w_int32(&rilp, mode); /* on/off */
parcel_w_int32(&rilp, cls); /* Service class */
ret = g_ril_send(sd->ril, RIL_REQUEST_SET_CALL_WAITING,
rilp.data, rilp.size, ril_set_cb, cbd, g_free);
g_ril_append_print_buf(sd->ril, "(%d, 0x%x)", mode, cls);
parcel_free(&rilp);
ret = g_ril_send(sd->ril, RIL_REQUEST_SET_CALL_WAITING, &rilp,
ril_set_cb, cbd, g_free);
/* In case of error free cbd and return the cb with failure */
if (ret <= 0) {
@@ -122,55 +101,63 @@ static void ril_cw_set(struct ofono_call_settings *cs, int mode, int cls,
static void ril_cw_query_cb(struct ril_msg *message, gpointer user_data)
{
struct cb_data *cbd = user_data;
struct ofono_call_settings *cs = cbd->user;
struct settings_data *sd = ofono_call_settings_get_data(cs);
ofono_call_settings_status_cb_t cb = cbd->cb;
struct parcel rilp;
int res = 0;
int sv = 0;
int numparams;
int enabled;
int cls;
if (message->error == RIL_E_SUCCESS) {
ril_util_init_parcel(message, &rilp);
if (message->error != RIL_E_SUCCESS)
goto error;
/* first value in int[] is len so let's skip that */
parcel_r_int32(&rilp);
g_ril_init_parcel(message, &rilp);
numparams = parcel_r_int32(&rilp);
if (numparams < 1)
goto error;
/* status of call waiting service, disabled is returned only if
* service is not active for any service class */
res = parcel_r_int32(&rilp);
DBG("CW enabled/disabled: %d", res);
enabled = parcel_r_int32(&rilp);
if (enabled && numparams < 2)
goto error;
if (res > 0) {
/* services for which call waiting is enabled, 27.007 7.12 */
sv = parcel_r_int32(&rilp);
DBG("CW enabled for: %d", sv);
}
if (enabled > 0)
cls = parcel_r_int32(&rilp);
else
cls = 0;
CALLBACK_WITH_SUCCESS(cb, sv, cbd->data);
} else
CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
g_ril_append_print_buf(sd->ril, "{%d,0x%x}", enabled, cls);
g_ril_print_response(sd->ril, message);
CALLBACK_WITH_SUCCESS(cb, cls, cbd->data);
return;
error:
CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
}
static void ril_cw_query(struct ofono_call_settings *cs, int cls,
ofono_call_settings_status_cb_t cb, void *data)
{
struct settings_data *sd = ofono_call_settings_get_data(cs);
struct cb_data *cbd = cb_data_new(cb, data);
int ret = 0;
struct cb_data *cbd = cb_data_new(cb, data, cs);
int ret;
struct parcel rilp;
parcel_init(&rilp);
parcel_w_int32(&rilp, 1); /* Number of params */
/*
* RILD expects service class to be 0 as certain carriers can reject the
* query with specific service class
*/
parcel_w_int32(&rilp, 0);
cls = 0;
ret = g_ril_send(sd->ril, RIL_REQUEST_QUERY_CALL_WAITING,
rilp.data, rilp.size, ril_cw_query_cb, cbd, g_free);
parcel_init(&rilp);
parcel_w_int32(&rilp, 1); /* Number of params */
parcel_w_int32(&rilp, cls); /* Service Class */
parcel_free(&rilp);
g_ril_append_print_buf(sd->ril, "(0)");
ret = g_ril_send(sd->ril, RIL_REQUEST_QUERY_CALL_WAITING, &rilp,
ril_cw_query_cb, cbd, g_free);
/* In case of error free cbd and return the cb with failure */
if (ret <= 0) {
@@ -179,16 +166,44 @@ static void ril_cw_query(struct ofono_call_settings *cs, int cls,
}
}
static void ril_clip_query_cb(struct ril_msg *message, gpointer user_data)
{
struct cb_data *cbd = user_data;
struct ofono_call_settings *cs = cbd->user;
struct settings_data *sd = ofono_call_settings_get_data(cs);
ofono_call_settings_status_cb_t cb = cbd->cb;
struct parcel rilp;
int clip_status;
if (message->error != RIL_E_SUCCESS)
goto error;
g_ril_init_parcel(message, &rilp);
if (parcel_r_int32(&rilp) != 1)
goto error;
clip_status = parcel_r_int32(&rilp);
g_ril_append_print_buf(sd->ril, "{%d}", clip_status);
g_ril_print_response(sd->ril, message);
CALLBACK_WITH_SUCCESS(cb, clip_status, cbd->data);
return;
error:
CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
}
static void ril_clip_query(struct ofono_call_settings *cs,
ofono_call_settings_status_cb_t cb, void *data)
{
struct settings_data *sd = ofono_call_settings_get_data(cs);
struct cb_data *cbd = cb_data_new(cb, data);
int ret = 0;
struct cb_data *cbd = cb_data_new(cb, data, cs);
int ret;
ret = g_ril_send(sd->ril, RIL_REQUEST_QUERY_CLIP,
NULL, 0, ril_clip_cb, cbd, g_free);
ret = g_ril_send(sd->ril, RIL_REQUEST_QUERY_CLIP, NULL,
ril_clip_query_cb, cbd, g_free);
/* In case of error free cbd and return the cb with failure */
if (ret <= 0) {
@@ -197,38 +212,49 @@ static void ril_clip_query(struct ofono_call_settings *cs,
}
}
static void ril_clir_cb(struct ril_msg *message, gpointer user_data)
static void ril_clir_query_cb(struct ril_msg *message, gpointer user_data)
{
struct cb_data *cbd = user_data;
struct ofono_call_settings *cs = cbd->user;
struct settings_data *sd = ofono_call_settings_get_data(cs);
ofono_call_settings_clir_cb_t cb = cbd->cb;
struct parcel rilp;
int override, network;
int override;
int network;
if (message->error != RIL_E_SUCCESS) {
ofono_error("%s: Reply failure: %s", __func__,
ril_error_to_string(message->error));
goto error;
}
if (message->error == RIL_E_SUCCESS) {
ril_util_init_parcel(message, &rilp);
/*first value in int[] is len so let's skip that*/
parcel_r_int32(&rilp);
/* Set HideCallerId property from network */
override = parcel_r_int32(&rilp);
/* CallingLineRestriction indicates the state of
the CLIR supplementary service in the network */
network = parcel_r_int32(&rilp);
g_ril_init_parcel(message, &rilp);
CALLBACK_WITH_SUCCESS(cb, override, network, cbd->data);
} else
CALLBACK_WITH_FAILURE(cb, -1, -1, cbd->data);
if (parcel_r_int32(&rilp) != 2)
goto error;
override = parcel_r_int32(&rilp);
network = parcel_r_int32(&rilp);
g_ril_append_print_buf(sd->ril, "{%d,%d}", override, network);
g_ril_print_response(sd->ril, message);
CALLBACK_WITH_SUCCESS(cb, override, network, cbd->data);
return;
error:
CALLBACK_WITH_FAILURE(cb, -1, -1, cbd->data);
}
static void ril_clir_query(struct ofono_call_settings *cs,
ofono_call_settings_clir_cb_t cb, void *data)
{
struct settings_data *sd = ofono_call_settings_get_data(cs);
struct cb_data *cbd = cb_data_new(cb, data);
int ret = 0;
struct cb_data *cbd = cb_data_new(cb, data, cs);
int ret;
ret = g_ril_send(sd->ril, RIL_REQUEST_GET_CLIR,
NULL, 0, ril_clir_cb, cbd, g_free);
ret = g_ril_send(sd->ril, RIL_REQUEST_GET_CLIR, NULL,
ril_clir_query_cb, cbd, g_free);
if (ret <= 0) {
g_free(cbd);
@@ -241,20 +267,19 @@ static void ril_clir_set(struct ofono_call_settings *cs, int mode,
ofono_call_settings_set_cb_t cb, void *data)
{
struct settings_data *sd = ofono_call_settings_get_data(cs);
struct cb_data *cbd = cb_data_new(cb, data);
int ret = 0;
struct cb_data *cbd = cb_data_new(cb, data, cs);
struct parcel rilp;
int ret;
parcel_init(&rilp);
parcel_w_int32(&rilp, 1); /* Number of params */
parcel_w_int32(&rilp, 1); /* Number of params */
parcel_w_int32(&rilp, mode);
parcel_w_int32(&rilp, mode); /* for outgoing calls */
g_ril_append_print_buf(sd->ril, "(%d)", mode);
ret = g_ril_send(sd->ril, RIL_REQUEST_SET_CLIR,
rilp.data, rilp.size, ril_set_cb, cbd, g_free);
parcel_free(&rilp);
ret = g_ril_send(sd->ril, RIL_REQUEST_SET_CLIR, &rilp,
ril_set_cb, cbd, g_free);
if (ret <= 0) {
g_free(cbd);
@@ -265,9 +290,6 @@ static void ril_clir_set(struct ofono_call_settings *cs, int mode,
static gboolean ril_delayed_register(gpointer user_data)
{
struct ofono_call_settings *cs = user_data;
struct settings_data *sd = ofono_call_settings_get_data(cs);
sd->timer_id = 0;
ofono_call_settings_register(cs);
@@ -278,14 +300,13 @@ static int ril_call_settings_probe(struct ofono_call_settings *cs,
unsigned int vendor, void *user)
{
GRil *ril = user;
struct settings_data *sd = g_try_new0(struct settings_data, 1);
struct settings_data *sd = g_new0(struct settings_data, 1);
sd->ril = g_ril_clone(ril);
ofono_call_settings_set_data(cs, sd);
sd->timer_id = g_timeout_add_seconds(2, ril_delayed_register, cs);
g_idle_add(ril_delayed_register, cs);
return 0;
}
@@ -295,15 +316,12 @@ static void ril_call_settings_remove(struct ofono_call_settings *cs)
struct settings_data *sd = ofono_call_settings_get_data(cs);
ofono_call_settings_set_data(cs, NULL);
if (sd->timer_id > 0)
g_source_remove(sd->timer_id);
g_ril_unref(sd->ril);
g_free(sd);
}
static struct ofono_call_settings_driver driver = {
.name = "rilmodem",
.name = RILMODEM,
.probe = ril_call_settings_probe,
.remove = ril_call_settings_remove,
.clip_query = ril_clip_query,
@@ -316,7 +334,7 @@ static struct ofono_call_settings_driver driver = {
* Not supported in RIL API
* .colp_query = ril_colp_query,
* .colr_query = ril_colr_query
*/
*/
};
void ril_call_settings_init(void)

View File

@@ -3,7 +3,7 @@
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2012 Canonical Ltd.
* Copyright (C) 2012-2013 Canonical Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -34,19 +34,15 @@
#include <ofono/log.h>
#include <ofono/modem.h>
#include <ofono/call-volume.h>
#include "gril.h"
#include "grilutil.h"
#include "common.h"
#include "gril.h"
#include "rilmodem.h"
#include "parcel.h"
struct cv_data {
GRil *ril;
unsigned int vendor;
guint timer_id;
};
static void volume_mute_cb(struct ril_msg *message, gpointer user_data)
@@ -70,33 +66,27 @@ static void volume_mute_cb(struct ril_msg *message, gpointer user_data)
}
static void ril_call_volume_mute(struct ofono_call_volume *cv, int muted,
ofono_call_volume_cb_t cb, void *data)
ofono_call_volume_cb_t cb, void *data)
{
struct cv_data *cvd = ofono_call_volume_get_data(cv);
struct cb_data *cbd = cb_data_new(cb, data);
struct cb_data *cbd = cb_data_new(cb, data, cvd);
struct parcel rilp;
int request = RIL_REQUEST_SET_MUTE;
int ret;
cbd->user = cvd;
DBG("");
DBG("muted: %d", muted);
parcel_init(&rilp);
parcel_w_int32(&rilp, 1);
parcel_w_int32(&rilp, muted);
DBG("Initial ril muted state: %d", muted);
ret = g_ril_send(cvd->ril, request, rilp.data,
rilp.size, volume_mute_cb, cbd, g_free);
parcel_free(&rilp);
g_ril_append_print_buf(cvd->ril, "(%d)", muted);
g_ril_print_request(cvd->ril, ret, request);
if (ret <= 0) {
ofono_error("Send RIL_REQUEST_SET_MUTE failed.");
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, data);
}
if (g_ril_send(cvd->ril, RIL_REQUEST_SET_MUTE, &rilp,
volume_mute_cb, cbd, g_free) > 0)
return;
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, data);
}
static void probe_mute_cb(struct ril_msg *message, gpointer user_data)
@@ -106,13 +96,12 @@ static void probe_mute_cb(struct ril_msg *message, gpointer user_data)
struct parcel rilp;
int muted;
if (message->error != RIL_E_SUCCESS) {
ofono_error("Could not retrive the ril mute state");
if (message->error != RIL_E_SUCCESS)
return;
}
ril_util_init_parcel(message, &rilp);
/*first item in int[] is len so let's skip that*/
g_ril_init_parcel(message, &rilp);
/* skip length of int[] */
parcel_r_int32(&rilp);
muted = parcel_r_int32(&rilp);
@@ -126,24 +115,15 @@ static void call_probe_mute(gpointer user_data)
{
struct ofono_call_volume *cv = user_data;
struct cv_data *cvd = ofono_call_volume_get_data(cv);
int request = RIL_REQUEST_GET_MUTE;
int ret;
ret = g_ril_send(cvd->ril, request, NULL, 0,
probe_mute_cb, cv, NULL);
g_ril_print_request_no_args(cvd->ril, ret, request);
g_ril_send(cvd->ril, RIL_REQUEST_GET_MUTE, NULL,
probe_mute_cb, cv, NULL);
}
static gboolean ril_delayed_register(gpointer user_data)
{
struct ofono_call_volume *cv = user_data;
struct cv_data *cvd = ofono_call_volume_get_data(cv);
DBG("");
cvd->timer_id = 0;
ofono_call_volume_register(cv);
/* Probe the mute state */
@@ -154,7 +134,7 @@ static gboolean ril_delayed_register(gpointer user_data)
}
static int ril_call_volume_probe(struct ofono_call_volume *cv,
unsigned int vendor, void *data)
unsigned int vendor, void *data)
{
GRil *ril = data;
struct cv_data *cvd;
@@ -169,16 +149,13 @@ static int ril_call_volume_probe(struct ofono_call_volume *cv,
ofono_call_volume_set_data(cv, cvd);
/*
* TODO: analyze if capability check is needed
* and/or timer should be adjusted.
*
* ofono_call_volume_register() needs to be called after
* the driver has been set in ofono_call_volume_create(),
* which calls this function. Most other drivers make
* some kind of capabilities query to the modem, and then
* call register in the callback; we use a timer instead.
* some kind of capabilities query to the modem, and then
* call register in the callback; we use an idle event instead.
*/
cvd->timer_id = g_timeout_add_seconds(2, ril_delayed_register, cv);
g_idle_add(ril_delayed_register, cv);
return 0;
}
@@ -189,9 +166,6 @@ static void ril_call_volume_remove(struct ofono_call_volume *cv)
ofono_call_volume_set_data(cv, NULL);
if (cvd->timer_id > 0)
g_source_remove(cvd->timer_id);
g_ril_unref(cvd->ril);
g_free(cvd);
}

View File

@@ -2,8 +2,7 @@
*
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2013 Jolla Ltd
* Copyright (C) 2008-2016 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -27,124 +26,180 @@
#define _GNU_SOURCE
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <glib.h>
#include <ofono/log.h>
#include <ofono/modem.h>
#include <ofono/cbs.h>
#include "util.h"
#include "gril.h"
#include "grilutil.h"
#include <gril.h>
#include <parcel.h>
#include "rilmodem.h"
#include "ril_constants.h"
#include "vendor.h"
struct cbs_data {
GRil *ril;
guint timer_id;
unsigned int vendor;
};
static void ril_set_topics(struct ofono_cbs *cbs, const char *topics,
ofono_cbs_set_cb_t cb, void *user_data)
static void ril_cbs_set_cb(struct ril_msg *message, gpointer user_data)
{
/*
* Although this does not do anything real
* towards network or modem, it is needed
* because without it ofono core does not
* change powered flag and it would reject
* incoming cb messages.
*/
CALLBACK_WITH_SUCCESS(cb, user_data);
struct cb_data *cbd = user_data;
ofono_cbs_set_cb_t cb = cbd->cb;
struct cbs_data *cd = cbd->user;
if (message->error == RIL_E_SUCCESS) {
CALLBACK_WITH_SUCCESS(cb, cbd->data);
} else {
ofono_error("%s RILD reply failure: %s",
g_ril_request_id_to_string(cd->ril, message->req),
ril_error_to_string(message->error));
CALLBACK_WITH_FAILURE(cb, cbd->data);
}
}
static void ril_clear_topics(struct ofono_cbs *cbs,
ofono_cbs_set_cb_t cb, void *user_data)
static void ril_cbs_set_topics(struct ofono_cbs *cbs, const char *topics,
ofono_cbs_set_cb_t cb, void *user_data)
{
/*
* Although this does not do anything real
* towards network or modem, it is needed
* because without it ofono core does not
* change powered flag and it would allow
* incoming cb messages.
*/
CALLBACK_WITH_SUCCESS(cb, user_data);
}
static void ril_cbs_notify(struct ril_msg *message, gpointer user_data)
{
struct ofono_cbs *cbs = user_data;
/*
* Ofono does not support UMTS CB - see
* src/smsutil.c method cbs_decode.
* But let's let the core to make
* the rejection reserve memory here
* for maximum UMTS CB length
*/
unsigned char pdu[1252];
char *resp;
struct cbs_data *cd = ofono_cbs_get_data(cbs);
struct cb_data *cbd = cb_data_new(cb, user_data, cd);
int i = 0, from, to;
const char *p, *pto;
char **segments;
struct parcel rilp;
ril_util_init_parcel(message, &rilp);
segments = g_strsplit(topics, ",", 0);
resp = parcel_r_string(&rilp);
while (segments[i])
i++;
memcpy(resp, pdu, strlen((char *)resp));
parcel_init(&rilp);
parcel_w_int32(&rilp, i);
ofono_cbs_notify(cbs, pdu, strlen((char *)resp));
i = 0;
while (segments[i]) {
p = segments[i++];
from = atoi(p);
to = from;
pto = strchr(p, '-');
if (pto)
to = atoi(pto + 1);
parcel_w_int32(&rilp, from);
parcel_w_int32(&rilp, to);
parcel_w_int32(&rilp, 0);
parcel_w_int32(&rilp, 0xFF);
parcel_w_int32(&rilp, 1);
}
g_strfreev(segments);
if (g_ril_send(cd->ril, RIL_REQUEST_GSM_SET_BROADCAST_SMS_CONFIG, &rilp,
ril_cbs_set_cb, cbd, g_free) > 0)
return;
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, user_data);
}
static gboolean ril_delayed_register(gpointer user_data)
static void ril_cbs_clear_topics(struct ofono_cbs *cbs,
ofono_cbs_set_cb_t cb, void *user_data)
{
ril_cbs_set_topics(cbs, "", cb, user_data);
}
static void ril_cbs_received(struct ril_msg *message, gpointer user_data)
{
struct ofono_cbs *cbs = user_data;
struct cbs_data *cd = ofono_cbs_get_data(cbs);
struct parcel rilp;
int pdulen;
unsigned char *pdu;
cd->timer_id = 0;
g_ril_print_unsol_no_args(cd->ril, message);
ofono_cbs_register(cbs);
DBG("req: %d; data_len: %d", message->req, (int) message->buf_len);
g_ril_init_parcel(message, &rilp);
pdu = parcel_r_raw(&rilp, &pdulen);
if (!pdu || pdulen != 88) {
ofono_error("%s: it isn't a gsm cell broadcast msg", __func__);
return;
}
ofono_cbs_notify(cbs, pdu, pdulen);
g_free(pdu);
}
static void ril_cbs_register(const struct ofono_error *error, void *data)
{
struct ofono_cbs *cbs = data;
struct cbs_data *cd = ofono_cbs_get_data(cbs);
g_ril_register(cd->ril, RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS,
ril_cbs_notify, cbs);
ril_cbs_received, cbs);
return FALSE;
ofono_cbs_register(cbs);
}
static void get_cbs_config_cb(struct ril_msg *message,
gpointer user_data)
{
struct ofono_cbs *cbs = user_data;
if (message->error != RIL_E_SUCCESS) {
ofono_error("%s: RIL error %s", __func__,
ril_error_to_string(message->error));
ofono_cbs_remove(cbs);
return;
}
ril_cbs_clear_topics(cbs, ril_cbs_register, cbs);
}
static int ril_cbs_probe(struct ofono_cbs *cbs, unsigned int vendor,
void *user)
{
GRil *ril = user;
struct cbs_data *data;
struct cbs_data *cd = g_try_new0(struct cbs_data, 1);
data = g_new0(struct cbs_data, 1);
data->ril = g_ril_clone(ril);
data->vendor = vendor;
cd->ril = g_ril_clone(ril);
ofono_cbs_set_data(cbs, data);
ofono_cbs_set_data(cbs, cd);
cd->timer_id = g_timeout_add_seconds(2, ril_delayed_register, cbs);
if (g_ril_send(ril, RIL_REQUEST_GSM_GET_BROADCAST_SMS_CONFIG, NULL,
get_cbs_config_cb, cbs, NULL) == 0)
ofono_error("%s: send failed", __func__);
return 0;
}
static void ril_cbs_remove(struct ofono_cbs *cbs)
{
struct cbs_data *cd = ofono_cbs_get_data(cbs);
struct cbs_data *data = ofono_cbs_get_data(cbs);
ofono_cbs_set_data(cbs, NULL);
if (cd->timer_id > 0)
g_source_remove(cd->timer_id);
g_ril_unref(cd->ril);
g_free(cd);
g_ril_unref(data->ril);
g_free(data);
}
static struct ofono_cbs_driver driver = {
.name = "rilmodem",
.probe = ril_cbs_probe,
.remove = ril_cbs_remove,
.set_topics = ril_set_topics,
.clear_topics = ril_clear_topics
.name = RILMODEM,
.probe = ril_cbs_probe,
.remove = ril_cbs_remove,
.set_topics = ril_cbs_set_topics,
.clear_topics = ril_cbs_clear_topics,
};
void ril_cbs_init(void)
@@ -156,4 +211,3 @@ void ril_cbs_exit(void)
{
ofono_cbs_driver_unregister(&driver);
}

View File

@@ -3,8 +3,7 @@
* oFono - Open Source Telephony - RIL Modem Support
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2012 Canonical Ltd.
* Copyright (C) 2013 Jolla Ltd.
* Copyright (C) 2012-2013 Canonical Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -41,150 +40,165 @@
#include "rilmodem.h"
/*
* TODO: No public RIL api to query manufacturer or model.
* Check where to get, could /system/build.prop be updated to have good values?
*/
guint timer_id;
static void ril_query_manufacturer(struct ofono_devinfo *info,
ofono_devinfo_query_cb_t cb,
void *data)
{
CALLBACK_WITH_FAILURE(cb, "", data);
/* TODO: Implement properly */
CALLBACK_WITH_SUCCESS(cb, "Fake Modem Manufacturer", data);
}
static void ril_query_model(struct ofono_devinfo *info,
ofono_devinfo_query_cb_t cb,
void *data)
{
CALLBACK_WITH_FAILURE(cb, "", data);
/* TODO: Implement properly */
CALLBACK_WITH_SUCCESS(cb, "Fake Modem Model", data);
}
static void query_revision_cb(struct ril_msg *message, gpointer user_data)
{
struct cb_data *cbd = user_data;
ofono_devinfo_query_cb_t cb = cbd->cb;
struct ofono_error error;
GRil *ril = cbd->user;
struct parcel rilp;
gchar *revision;
char *revision;
if (message->error == RIL_E_SUCCESS) {
decode_ril_error(&error, "OK");
} else {
decode_ril_error(&error, "FAIL");
cb(&error, NULL, cbd->data);
return;
}
if (message->error != RIL_E_SUCCESS)
goto error;
ril_util_init_parcel(message, &rilp);
g_ril_init_parcel(message, &rilp);
revision = parcel_r_string(&rilp);
cb(&error, revision, cbd->data);
g_ril_append_print_buf(ril, "{%s}", revision);
g_ril_print_response(ril, message);
CALLBACK_WITH_SUCCESS(cb, revision, cbd->data);
g_free(revision);
return;
error:
CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
}
static void ril_query_revision(struct ofono_devinfo *info,
ofono_devinfo_query_cb_t cb,
void *data)
{
struct cb_data *cbd = cb_data_new(cb, data);
GRil *ril = ofono_devinfo_get_data(info);
int request = RIL_REQUEST_BASEBAND_VERSION;
int ret;
struct cb_data *cbd = cb_data_new(cb, data, ril);
ret = g_ril_send(ril, request, NULL, 0,
query_revision_cb, cbd, g_free);
if (g_ril_send(ril, RIL_REQUEST_BASEBAND_VERSION, NULL,
query_revision_cb, cbd, g_free) > 0)
return;
g_ril_print_request_no_args(ril, ret, request);
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, NULL, data);
}
if (ret <= 0) {
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, NULL, data);
}
static void query_svn_cb(struct ril_msg *message, gpointer user_data)
{
struct cb_data *cbd = user_data;
ofono_devinfo_query_cb_t cb = cbd->cb;
GRil *ril = cbd->user;
struct parcel rilp;
char *imeisv;
if (message->error != RIL_E_SUCCESS)
goto error;
g_ril_init_parcel(message, &rilp);
imeisv = parcel_r_string(&rilp);
g_ril_append_print_buf(ril, "{%s}", imeisv);
g_ril_print_response(ril, message);
CALLBACK_WITH_SUCCESS(cb, imeisv, cbd->data);
g_free(imeisv);
return;
error:
CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
}
static void ril_query_svn(struct ofono_devinfo *info,
ofono_devinfo_query_cb_t cb,
void *data)
{
GRil *ril = ofono_devinfo_get_data(info);
struct cb_data *cbd = cb_data_new(cb, data, ril);
if (g_ril_send(ril, RIL_REQUEST_GET_IMEISV, NULL,
query_svn_cb, cbd, g_free) > 0)
return;
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, NULL, data);
}
static void query_serial_cb(struct ril_msg *message, gpointer user_data)
{
struct cb_data *cbd = user_data;
ofono_devinfo_query_cb_t cb = cbd->cb;
struct ofono_error error;
GRil *ril = cbd->user;
struct parcel rilp;
gchar *imei;
char *imei;
if (message->error == RIL_E_SUCCESS) {
decode_ril_error(&error, "OK");
} else {
decode_ril_error(&error, "FAIL");
cb(&error, NULL, cbd->data);
return;
}
if (message->error != RIL_E_SUCCESS)
goto error;
ril_util_init_parcel(message, &rilp);
g_ril_init_parcel(message, &rilp);
imei = parcel_r_string(&rilp);
cb(&error, imei, cbd->data);
g_ril_append_print_buf(ril, "{%s}", imei);
g_ril_print_response(ril, message);
CALLBACK_WITH_SUCCESS(cb, imei, cbd->data);
g_free(imei);
return;
error:
CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
}
static void ril_query_serial(struct ofono_devinfo *info,
ofono_devinfo_query_cb_t cb,
void *data)
{
struct cb_data *cbd = cb_data_new(cb, data);
GRil *ril = ofono_devinfo_get_data(info);
/* TODO: make it support both RIL_REQUEST_GET_IMEI (deprecated) and
* RIL_REQUEST_DEVICE_IDENTITY depending on the rild version used */
int request = RIL_REQUEST_GET_IMEI;
int ret;
struct cb_data *cbd = cb_data_new(cb, data, ril);
ret = g_ril_send(ril, request, NULL, 0,
query_serial_cb, cbd, g_free);
/*
* TODO: make it support both RIL_REQUEST_GET_IMEI (deprecated) and
* RIL_REQUEST_DEVICE_IDENTITY depending on the rild version used
*/
if (g_ril_send(ril, RIL_REQUEST_GET_IMEI, NULL,
query_serial_cb, cbd, g_free) > 0)
return;
g_ril_print_request_no_args(ril, ret, request);
if (ret <= 0) {
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, NULL, data);
}
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, NULL, data);
}
static gboolean ril_delayed_register(gpointer user_data)
{
struct ofono_devinfo *info = user_data;
DBG("");
timer_id = 0;
DBG("");
ofono_devinfo_register(info);
/* This makes the timeout a single-shot */
return FALSE;
}
static int ril_devinfo_probe(struct ofono_devinfo *info, unsigned int vendor,
void *data)
{
GRil *ril = NULL;
if (data != NULL)
ril = g_ril_clone(data);
GRil *ril = g_ril_clone(data);
ofono_devinfo_set_data(info, ril);
DBG("");
/*
* TODO: analyze if capability check is needed
* and/or timer should be adjusted.
*
* ofono_devinfo_register() needs to be called after
* the driver has been set in ofono_devinfo_create(),
* which calls this function. Most other drivers make
* some kind of capabilities query to the modem, and then
* call register in the callback; we use a timer instead.
*/
timer_id = g_timeout_add_seconds(1, ril_delayed_register, info);
g_idle_add(ril_delayed_register, info);
return 0;
}
@@ -195,20 +209,18 @@ static void ril_devinfo_remove(struct ofono_devinfo *info)
ofono_devinfo_set_data(info, NULL);
if (timer_id > 0)
g_source_remove(timer_id);
g_ril_unref(ril);
}
static struct ofono_devinfo_driver driver = {
.name = "rilmodem",
.name = RILMODEM,
.probe = ril_devinfo_probe,
.remove = ril_devinfo_remove,
.query_manufacturer = ril_query_manufacturer,
.query_model = ril_query_model,
.query_revision = ril_query_revision,
.query_serial = ril_query_serial
.query_serial = ril_query_serial,
.query_svn = ril_query_svn
};
void ril_devinfo_init(void)

File diff suppressed because it is too large Load Diff

View File

@@ -39,14 +39,22 @@
#include <ofono/gprs.h>
#include <ofono/types.h>
#include "gril.h"
#include "grilutil.h"
#include <gril/gril.h>
#include <gril/grilutil.h>
#include "common.h"
#include "rilmodem.h"
#include <ofono/netreg.h>
#include <ofono/sim.h>
#include "storage.h"
/* Time between get data status retries */
#define GET_STATUS_TIMER_MS 5000
struct ril_gprs_data {
GRil *ril;
struct ofono_modem *modem;
gboolean ofono_attached;
int rild_status;
int pending_deact_req;
};
/*
* This module is the ofono_gprs_driver implementation for rilmodem.
@@ -55,128 +63,67 @@
*
* 1. ofono_gprs_suspend/resume() are not used by this module, as
* the concept of suspended GPRS is not exposed by RILD.
*
* 2. ofono_gprs_bearer_notify() is never called as RILD does not
* expose an unsolicited event equivalent to +CPSB ( see 27.007
* 7.29 ), and the tech values returned by REQUEST_DATA/VOICE
* _REGISTRATION requests do not match the values defined for
* <AcT> in the +CPSB definition. Note, the values returned by
* the *REGISTRATION commands are aligned with those defined by
* +CREG ( see 27.003 7.2 ).
*/
struct gprs_data {
GRil *ril;
gboolean ofono_attached;
int max_cids;
int rild_status; /* Driver Status */
guint registerid;
guint timer_id;
};
/* Following constants are purely to improve readability */
static const int roaming = NETWORK_REGISTRATION_STATUS_ROAMING;
static const int registered = NETWORK_REGISTRATION_STATUS_REGISTERED;
/*if we have called ofono_gprs_register or not*/
static gboolean ofono_registered;
static void ril_gprs_registration_status(struct ofono_gprs *gprs,
ofono_gprs_status_cb_t cb,
void *data);
static void ril_gprs_state_change(struct ril_msg *message, gpointer user_data)
static int ril_tech_to_bearer_tech(int ril_tech)
{
struct ofono_gprs *gprs = user_data;
/*
* This code handles the mapping between the RIL_RadioTechnology
* and packet bearer values ( see <curr_bearer> values - 27.007
* Section 7.29 ).
*/
g_assert(message->req ==
RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED);
DBG("");
/* We need to notify core always to cover situations when
* connection drops temporarily for example when user is
* taking CS voice call from LTE or changing technology
* preference */
ril_gprs_registration_status(gprs, NULL, NULL);
}
static gboolean ril_gprs_set_attached_callback(gpointer user_data)
{
struct ofono_error error;
struct cb_data *cbd = user_data;
ofono_gprs_cb_t cb = cbd->cb;
struct ofono_gprs *gprs = cbd->user;
struct gprs_data *gd = ofono_gprs_get_data(gprs);
DBG("");
gd->timer_id = 0;
decode_ril_error(&error, "OK");
cb(&error, cbd->data);
g_free(cbd);
return FALSE;
switch (ril_tech) {
case RADIO_TECH_GSM:
case RADIO_TECH_UNKNOWN:
return PACKET_BEARER_NONE;
case RADIO_TECH_GPRS:
return PACKET_BEARER_GPRS;
case RADIO_TECH_EDGE:
return PACKET_BEARER_EGPRS;
case RADIO_TECH_UMTS:
return PACKET_BEARER_UMTS;
case RADIO_TECH_HSDPA:
return PACKET_BEARER_HSDPA;
case RADIO_TECH_HSUPA:
return PACKET_BEARER_HSUPA;
case RADIO_TECH_HSPAP:
case RADIO_TECH_HSPA:
/*
* HSPAP is HSPA+; which ofono doesn't define;
* so, if differentiating HSPA and HSPA+ is
* important, then ofono needs to be patched,
* and we probably also need to introduce a
* new indicator icon.
*/
return PACKET_BEARER_HSUPA_HSDPA;
case RADIO_TECH_LTE:
return PACKET_BEARER_EPS;
default:
return PACKET_BEARER_NONE;
}
}
static void ril_gprs_set_attached(struct ofono_gprs *gprs, int attached,
ofono_gprs_cb_t cb, void *data)
{
struct cb_data *cbd = cb_data_new(cb, data);
struct gprs_data *gd = ofono_gprs_get_data(gprs);
struct ril_gprs_data *gd = ofono_gprs_get_data(gprs);
DBG("attached: %d", attached);
/*
* As RIL offers no actual control over the GPRS 'attached'
* state, we save the desired state, and use it to override
* the actual modem's state in the 'attached_status' function.
* This is similar to the way the core ofono gprs code handles
* data roaming ( see src/gprs.c gprs_netreg_update().
*
* The core gprs code calls driver->set_attached() when a netreg
* notification is received and any configured roaming conditions
* are met.
*/
/*
* As RIL offers no actual control over the GPRS 'attached'
* state, we save the desired state, and use it to override
* the actual modem's state in the 'attached_status' function.
* This is similar to the way the core ofono gprs code handles
* data roaming ( see src/gprs.c gprs_netreg_update().
*
* The core gprs code calls driver->set_attached() when a netreg
* notificaiton is received and any configured roaming conditions
* are met.
*/
gd->ofono_attached = attached;
cbd->user = gprs;
/*
* However we cannot respond immediately, since core sets the
* value of driver_attached after calling set_attached and that
* leads to comparison failure in gprs_attached_update in
* connection drop phase
*/
gd->timer_id = g_timeout_add_seconds(1, ril_gprs_set_attached_callback,
cbd);
}
gboolean ril_roaming_allowed()
{
GError *error;
error = NULL;
GKeyFile *settings;
struct ofono_sim *sim;
sim = get_sim();
const char *imsi = ofono_sim_get_imsi(sim);
settings = storage_open(imsi, "gprs");
gboolean roaming_allowed = g_key_file_get_boolean(settings,
"Settings",
"RoamingAllowed",
&error);
if (error)
g_error_free(error);
storage_close(imsi, "gprs", settings, FALSE);
DBG("roaming_allowed: %d", roaming_allowed);
return roaming_allowed;
CALLBACK_WITH_SUCCESS(cb, data);
}
static void ril_data_reg_cb(struct ril_msg *message, gpointer user_data)
@@ -184,245 +131,392 @@ static void ril_data_reg_cb(struct ril_msg *message, gpointer user_data)
struct cb_data *cbd = user_data;
ofono_gprs_status_cb_t cb = cbd->cb;
struct ofono_gprs *gprs = cbd->user;
struct gprs_data *gd = ofono_gprs_get_data(gprs);
struct ofono_error error;
int lac, ci, tech;
int max_cids = 1;
int status = -1;
struct ril_gprs_data *gd = ofono_gprs_get_data(gprs);
struct ofono_modem *modem;
struct parcel rilp;
int num_str;
char **strv;
char *debug_str;
char *end;
int status;
int tech = -1;
gboolean attached = FALSE;
gboolean notify_status = FALSE;
int old_status;
if (gd && message->error == RIL_E_SUCCESS) {
decode_ril_error(&error, "OK");
} else {
ofono_error("ril_data_reg_cb: reply failure: %s",
old_status = gd->rild_status;
if (message->error != RIL_E_SUCCESS) {
ofono_error("%s: DATA_REGISTRATION_STATE reply failure: %s",
__func__,
ril_error_to_string(message->error));
decode_ril_error(&error, "FAIL");
error.error = message->error;
goto exit;
goto error;
}
if (ril_util_parse_reg(gd->ril, message, &status,
&lac, &ci, &tech, &max_cids) == FALSE) {
ofono_error("Failure parsing data registration response.");
decode_ril_error(&error, "FAIL");
goto exit;
}
g_ril_init_parcel(message, &rilp);
strv = parcel_r_strv(&rilp);
num_str = g_strv_length(strv);
if (status > 10)
status = status - 10;
if (strv == NULL)
goto error;
if (!ofono_registered) {
ofono_gprs_register(gprs);
ofono_registered = TRUE;
}
debug_str = g_strjoinv(",", strv);
g_ril_append_print_buf(gd->ril, "{%d,%s}", num_str, debug_str);
g_free(debug_str);
g_ril_print_response(gd->ril, message);
if (max_cids > gd->max_cids) {
DBG("Setting max cids to %d", max_cids);
gd->max_cids = max_cids;
ofono_gprs_set_cid_range(gprs, 1, max_cids);
}
status = strtoul(strv[0], &end, 10);
if (end == strv[0] || *end != '\0')
goto error_free;
if (status == roaming)
status = check_if_really_roaming(status);
status = ril_util_registration_state_to_status(status);
if (status < 0)
goto error_free;
/* Let's minimize logging */
if (status != gd->rild_status)
ofono_info("data reg changes %d (%d), attached %d",
status, gd->rild_status, gd->ofono_attached);
if (num_str >= 4) {
tech = strtoul(strv[3], &end, 10);
if (end == strv[3] || *end != '\0')
tech = -1;
/* Must be attached if registered or roaming */
if ((gd->rild_status != registered) && (gd->rild_status != roaming)) {
if (status == registered)
gd->ofono_attached = TRUE;
else if ((status == roaming) && (ril_roaming_allowed() == TRUE))
gd->ofono_attached = TRUE;
}
if (!ofono_modem_get_online(ofono_gprs_get_modem(gprs)))
gd->ofono_attached = FALSE;
/* if unsolicitated and no state change let's not notify core */
if ((status == gd->rild_status) && gd->ofono_attached)
goto cb_out;
if (!gd->ofono_attached) {
if (!cb) {
if (status == roaming) {
if (ril_roaming_allowed() == FALSE)
ofono_gprs_detached_notify(gprs);
/*
* This prevents core ending
* into eternal loop with driver
*/
decode_ril_error(&error, "FAIL");
if (g_ril_vendor(gd->ril) == OFONO_RIL_VENDOR_MTK) {
switch (tech) {
case MTK_RADIO_TECH_HSDPAP:
case MTK_RADIO_TECH_HSDPAP_UPA:
case MTK_RADIO_TECH_HSUPAP:
case MTK_RADIO_TECH_HSUPAP_DPA:
tech = RADIO_TECH_HSPAP;
break;
case MTK_RADIO_TECH_DC_DPA:
tech = RADIO_TECH_HSDPA;
break;
case MTK_RADIO_TECH_DC_UPA:
tech = RADIO_TECH_HSUPA;
break;
case MTK_RADIO_TECH_DC_HSDPAP:
case MTK_RADIO_TECH_DC_HSDPAP_UPA:
case MTK_RADIO_TECH_DC_HSDPAP_DPA:
case MTK_RADIO_TECH_DC_HSPAP:
tech = RADIO_TECH_HSPAP;
break;
}
ofono_gprs_status_notify(gprs, status);
} else {
/*
* This prevents core ending
* into eternal loop with driver
*/
decode_ril_error(&error, "FAIL");
}
}
/*
* There are two cases that can result in this callback
* running:
*
* 1) ril_gprs_state_change() is called due to an unsolicited
* event from RILD. No ofono cb exists.
*
* 2) The ofono code code calls the driver's attached_status()
* function. A valid ofono cb exists.
*/
if (gd->rild_status != status) {
gd->rild_status = status;
goto exit;
if (cb == NULL)
notify_status = TRUE;
}
if (!cb)
ofono_gprs_status_notify(gprs, status);
/*
* Override the actual status based upon the desired
* attached status set by the core GPRS code ( controlled
* by the ConnnectionManager's 'Powered' property ).
*/
attached = status == NETWORK_REGISTRATION_STATUS_REGISTERED ||
status == NETWORK_REGISTRATION_STATUS_ROAMING;
gd->rild_status = status;
if (attached && gd->ofono_attached == FALSE) {
DBG("attached=true; ofono_attached=false; return !REGISTERED");
status = NETWORK_REGISTRATION_STATUS_NOT_REGISTERED;
/*
* Further optimization so that if ril_status ==
* NOT_REGISTERED, ofono_attached == false, and status ==
* ROAMING | REGISTERED, then notify gets cleared...
*
* As is, this results in unecessary status notify calls
* when nothing has changed.
*/
if (notify_status && status == old_status)
notify_status = FALSE;
}
/* Just need to notify ofono if it's already attached */
if (notify_status) {
/*
* If network disconnect has occurred, call detached_notify()
* instead of status_notify().
*/
if (!attached &&
(old_status == NETWORK_REGISTRATION_STATUS_REGISTERED ||
old_status ==
NETWORK_REGISTRATION_STATUS_ROAMING)) {
DBG("calling ofono_gprs_detached_notify()");
ofono_gprs_detached_notify(gprs);
tech = RADIO_TECH_UNKNOWN;
} else {
DBG("calling ofono_gprs_status_notify()");
ofono_gprs_status_notify(gprs, status);
}
}
modem = ofono_gprs_get_modem(gprs);
ofono_modem_set_integer(modem, "RilDataRadioTechnology", tech);
ofono_gprs_bearer_notify(gprs, ril_tech_to_bearer_tech(tech));
exit:
DBG("data reg status %d, rild_status %d, attached %d",
status, gd->rild_status, gd->ofono_attached);
cb_out:
if (cb)
cb(&error, status, cbd->data);
}
CALLBACK_WITH_SUCCESS(cb, status, cbd->data);
static void ril_data_probe_reg_cb(struct ril_msg *message, gpointer user_data)
{
struct cb_data *cbd = user_data;
struct ofono_gprs *gprs = cbd->user;
struct gprs_data *gd = ofono_gprs_get_data(gprs);
struct ofono_error error;
int status, lac, ci, tech;
int max_cids = 1;
int id = RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED;
return;
DBG("");
error_free:
g_strfreev(strv);
if (!(gd && message->error == RIL_E_SUCCESS)) {
ofono_error("ril_data_reg_cb: reply failure: %s",
ril_error_to_string(message->error));
decode_ril_error(&error, "FAIL");
error.error = message->error;
status = NETWORK_REGISTRATION_STATUS_UNKNOWN;
goto out;
}
decode_ril_error(&error, "OK");
status = -1;
if (ril_util_parse_reg(gd->ril, message, &status,
&lac, &ci, &tech, &max_cids) == FALSE) {
ofono_error("Failure parsing data registration response.");
decode_ril_error(&error, "FAIL");
if (status == -1)
status = NETWORK_REGISTRATION_STATUS_UNKNOWN;
goto out;
}
if (status > 10)
status = status - 10;
ofono_gprs_register(gprs);
ofono_registered = TRUE;
if (max_cids > gd->max_cids) {
DBG("Setting max cids to %d", max_cids);
gd->max_cids = max_cids;
ofono_gprs_set_cid_range(gprs, 1, max_cids);
}
if (status == roaming)
status = check_if_really_roaming(status);
out:
ofono_info("data reg status probed %d", status);
gd->registerid = g_ril_register(gd->ril,
id, ril_gprs_state_change, gprs);
gd->rild_status = status;
error:
if (cb)
CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
}
static void ril_gprs_registration_status(struct ofono_gprs *gprs,
ofono_gprs_status_cb_t cb,
void *data)
ofono_gprs_status_cb_t cb, void *data)
{
struct gprs_data *gd = ofono_gprs_get_data(gprs);
struct cb_data *cbd = cb_data_new(cb, data);
int request = RIL_REQUEST_DATA_REGISTRATION_STATE;
guint ret;
struct ril_gprs_data *gd = ofono_gprs_get_data(gprs);
struct cb_data *cbd = cb_data_new(cb, data, gprs);
DBG("");
if (gd == NULL || cbd == NULL)
return;
cbd->user = gprs;
ret = g_ril_send(gd->ril, request,
NULL, 0,
((gd->rild_status == -1)
? ril_data_probe_reg_cb
: ril_data_reg_cb), cbd, g_free);
g_ril_print_request_no_args(gd->ril, ret, request);
if (ret <= 0) {
ofono_error("Send RIL_REQUEST_DATA_RESTISTRATION_STATE fail.");
if (g_ril_send(gd->ril, RIL_REQUEST_DATA_REGISTRATION_STATE, NULL,
ril_data_reg_cb, cbd, g_free) == 0) {
ofono_error("%s: send "
"RIL_REQUEST_DATA_REGISTRATION_STATE failed",
__func__);
g_free(cbd);
if (cb)
if (cb != NULL)
CALLBACK_WITH_FAILURE(cb, -1, data);
}
}
static int ril_gprs_probe(struct ofono_gprs *gprs,
unsigned int vendor, void *data)
static void query_max_cids_cb(struct ril_msg *message, gpointer user_data)
{
GRil *ril = data;
struct gprs_data *gd;
struct ofono_gprs *gprs = user_data;
struct ril_gprs_data *gd = ofono_gprs_get_data(gprs);
struct parcel rilp;
int num_str;
char **strv;
char *debug_str;
char *end;
int max_calls = 2;
gd = g_try_new0(struct gprs_data, 1);
if (message->error != RIL_E_SUCCESS) {
ofono_error("%s: DATA_REGISTRATION_STATE reply failure: %s",
__func__,
ril_error_to_string(message->error));
goto error;
}
g_ril_init_parcel(message, &rilp);
strv = parcel_r_strv(&rilp);
if (strv == NULL)
goto error;
num_str = g_strv_length(strv);
debug_str = g_strjoinv(",", strv);
g_ril_append_print_buf(gd->ril, "{%d,%s}", num_str, debug_str);
g_free(debug_str);
g_ril_print_response(gd->ril, message);
if (num_str < 6)
goto reg_atom;
max_calls = strtoul(strv[5], &end, 10);
if (end == strv[5] || *end != '\0')
goto error_free;
reg_atom:
g_strfreev(strv);
ofono_gprs_set_cid_range(gprs, 1, max_calls);
ofono_gprs_register(gprs);
return;
error_free:
g_strfreev(strv);
error:
ofono_error("Unable to query max CIDs");
ofono_gprs_remove(gprs);
}
static void ril_gprs_state_change(struct ril_msg *message, gpointer user_data)
{
struct ofono_gprs *gprs = user_data;
struct ril_gprs_data *gd = ofono_gprs_get_data(gprs);
g_ril_print_unsol_no_args(gd->ril, message);
/*
* We just want to track network data status if ofono
* itself is attached, so we avoid unnecessary data state requests.
*/
if (gd->ofono_attached == TRUE)
ril_gprs_registration_status(gprs, NULL, NULL);
}
static void query_max_cids(struct ofono_gprs *gprs)
{
struct ril_gprs_data *gd = ofono_gprs_get_data(gprs);
g_ril_register(gd->ril, RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED,
ril_gprs_state_change, gprs);
/*
* MTK modem does not return max_cids, string, so hard-code it
* here
*/
if (g_ril_vendor(gd->ril) == OFONO_RIL_VENDOR_MTK) {
ofono_gprs_set_cid_range(gprs, 1, 3);
ofono_gprs_register(gprs);
return;
}
if (g_ril_send(gd->ril, RIL_REQUEST_DATA_REGISTRATION_STATE, NULL,
query_max_cids_cb, gprs, NULL) < 0)
ofono_gprs_remove(gprs);
}
static void drop_data_call_cb(struct ril_msg *message, gpointer user_data)
{
struct ofono_gprs *gprs = user_data;
struct ril_gprs_data *gd = ofono_gprs_get_data(gprs);
if (message->error == RIL_E_SUCCESS)
g_ril_print_response_no_args(gd->ril, message);
else
ofono_error("%s: RIL error %s", __func__,
ril_error_to_string(message->error));
if (--(gd->pending_deact_req) == 0)
query_max_cids(gprs);
}
static int drop_data_call(struct ofono_gprs *gprs, int cid)
{
struct ril_gprs_data *gd = ofono_gprs_get_data(gprs);
struct parcel rilp;
ril_util_build_deactivate_data_call(gd->ril, &rilp, cid,
RIL_DEACTIVATE_DATA_CALL_NO_REASON);
if (g_ril_send(gd->ril, RIL_REQUEST_DEACTIVATE_DATA_CALL,
&rilp, drop_data_call_cb, gprs, NULL) > 0)
return 0;
return -1;
}
static void get_active_data_calls_cb(struct ril_msg *message,
gpointer user_data)
{
struct ofono_gprs *gprs = user_data;
struct ril_gprs_data *gd = ofono_gprs_get_data(gprs);
struct parcel rilp;
int num_calls;
int cid;
int i;
if (message->error != RIL_E_SUCCESS) {
ofono_error("%s: RIL error %s", __func__,
ril_error_to_string(message->error));
goto end;
}
g_ril_init_parcel(message, &rilp);
/* Version */
parcel_r_int32(&rilp);
num_calls = parcel_r_int32(&rilp);
/*
* We disconnect from previous calls here, which might be needed
* because of a previous ofono abort, as some rild implementations do
* not disconnect the calls even after the ril socket is closed.
*/
for (i = 0; i < num_calls; i++) {
parcel_r_int32(&rilp); /* status */
parcel_r_int32(&rilp); /* ignore */
cid = parcel_r_int32(&rilp);
parcel_r_int32(&rilp); /* active */
parcel_skip_string(&rilp); /* type */
parcel_skip_string(&rilp); /* ifname */
parcel_skip_string(&rilp); /* addresses */
parcel_skip_string(&rilp); /* dns */
parcel_skip_string(&rilp); /* gateways */
/* malformed check */
if (rilp.malformed) {
ofono_error("%s: malformed parcel received", __func__);
goto end;
}
DBG("Standing data call with cid %d", cid);
if (drop_data_call(gprs, cid) == 0)
++(gd->pending_deact_req);
}
end:
if (gd->pending_deact_req == 0)
query_max_cids(gprs);
}
static void get_active_data_calls(struct ofono_gprs *gprs)
{
struct ril_gprs_data *gd = ofono_gprs_get_data(gprs);
if (g_ril_send(gd->ril, RIL_REQUEST_DATA_CALL_LIST, NULL,
get_active_data_calls_cb, gprs, NULL) == 0)
ofono_error("%s: send failed", __func__);
}
static int ril_gprs_probe(struct ofono_gprs *gprs, unsigned int vendor,
void *userdata)
{
GRil *ril = userdata;
struct ril_gprs_data *gd;
gd = g_try_new0(struct ril_gprs_data, 1);
if (gd == NULL)
return -ENOMEM;
gd->ril = g_ril_clone(ril);
gd->ofono_attached = FALSE;
gd->max_cids = 0;
gd->rild_status = -1;
gd->registerid = -1;
gd->timer_id = 0;
ofono_registered = FALSE;
ofono_gprs_set_data(gprs, gd);
ril_gprs_registration_status(gprs, NULL, NULL);
get_active_data_calls(gprs);
return 0;
}
static void ril_gprs_remove(struct ofono_gprs *gprs)
{
struct gprs_data *gd = ofono_gprs_get_data(gprs);
struct ril_gprs_data *gd = ofono_gprs_get_data(gprs);
DBG("");
ofono_gprs_set_data(gprs, NULL);
if (gd->registerid != -1)
g_ril_unregister(gd->ril, gd->registerid);
if (gd->timer_id > 0)
g_source_remove(gd->timer_id);
g_ril_unref(gd->ril);
g_free(gd);
}
static struct ofono_gprs_driver driver = {
.name = "rilmodem",
.name = RILMODEM,
.probe = ril_gprs_probe,
.remove = ril_gprs_remove,
.set_attached = ril_gprs_set_attached,

View File

@@ -0,0 +1,282 @@
/*
*
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2016 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <glib.h>
#include <ofono/log.h>
#include <ofono/modem.h>
#include <ofono/netmon.h>
#include "gril.h"
#include "rilmodem.h"
/*
* Defined below are copy of
* RIL_CellInfoType defined in Ril.h
*/
#define NETMON_RIL_CELLINFO_TYPE_GSM 1
#define NETMON_RIL_CELLINFO_TYPE_CDMA 2
#define NETMON_RIL_CELLINFO_TYPE_LTE 3
#define NETMON_RIL_CELLINFO_TYPE_UMTS 4
#define NETMON_RIL_CELLINFO_TYPE_TDSCDMA 5
/* size of RIL_CellInfoGsm */
#define NETMON_RIL_CELLINFO_SIZE_GSM 24
/* size of RIL_CellInfoCDMA */
#define NETMON_RIL_CELLINFO_SIZE_CDMA 40
/* size of RIL_CellInfoLte */
#define NETMON_RIL_CELLINFO_SIZE_LTE 44
/* size of RIL_CellInfoWcdma */
#define NETMON_RIL_CELLINFO_SIZE_UMTS 28
/* size of RIL_CellInfoTdscdma */
#define NETMON_RIL_CELLINFO_SIZE_TDSCDMA 24
struct netmon_data {
GRil *ril;
};
static gboolean ril_delayed_register(gpointer user_data)
{
struct ofono_netmon *netmon = user_data;
ofono_netmon_register(netmon);
return FALSE;
}
static int ril_cell_type_to_size(int cell_type)
{
switch (cell_type) {
case NETMON_RIL_CELLINFO_TYPE_GSM:
return NETMON_RIL_CELLINFO_SIZE_GSM;
case NETMON_RIL_CELLINFO_TYPE_CDMA:
return NETMON_RIL_CELLINFO_SIZE_CDMA;
case NETMON_RIL_CELLINFO_TYPE_LTE:
return NETMON_RIL_CELLINFO_SIZE_LTE;
case NETMON_RIL_CELLINFO_TYPE_UMTS:
return NETMON_RIL_CELLINFO_SIZE_UMTS;
case NETMON_RIL_CELLINFO_TYPE_TDSCDMA:
return NETMON_RIL_CELLINFO_SIZE_TDSCDMA;
}
return 0;
}
static void ril_netmon_update_cb(struct ril_msg *message, gpointer user_data)
{
struct cb_data *cbd = user_data;
ofono_netmon_cb_t cb = cbd->cb;
struct ofono_netmon *netmon = cbd->data;
struct parcel rilp;
int skip_len;
int cell_info_cnt;
int cell_type;
int registered = 0;
int mcc, mnc;
int lac, cid, psc;
int rssi, ber;
char s_mcc[OFONO_MAX_MCC_LENGTH + 1];
char s_mnc[OFONO_MAX_MNC_LENGTH + 1];
int i, j;
if (message->error != RIL_E_SUCCESS)
goto error;
g_ril_init_parcel(message, &rilp);
cell_info_cnt = parcel_r_int32(&rilp);
for (i = 0; i < cell_info_cnt; i++) {
cell_type = parcel_r_int32(&rilp);
registered = parcel_r_int32(&rilp);
/* skipping unneeded timeStampType in Ril cell info */
(void)parcel_r_int32(&rilp);
/*skipping timeStamp which is a uint64_t type */
(void)parcel_r_int32(&rilp);
(void)parcel_r_int32(&rilp);
if (registered)
break;
/*
* not serving cell,
* skip remainder of current cell info
*/
skip_len = ril_cell_type_to_size(cell_type)/sizeof(int);
for (j = 0; j < skip_len; j++)
(void)parcel_r_int32(&rilp);
}
if (!registered)
goto error;
if (cell_type == NETMON_RIL_CELLINFO_TYPE_GSM) {
mcc = parcel_r_int32(&rilp);
mnc = parcel_r_int32(&rilp);
lac = parcel_r_int32(&rilp);
cid = parcel_r_int32(&rilp);
rssi = parcel_r_int32(&rilp);
ber = parcel_r_int32(&rilp);
if (mcc >= 0 && mcc <= 999)
snprintf(s_mcc, sizeof(s_mcc), "%03d", mcc);
else
strcpy(s_mcc, "");
if (mnc >= 0 && mnc <= 999)
snprintf(s_mnc, sizeof(s_mnc), "%03d", mnc);
else
strcpy(s_mnc, "");
lac = (lac >= 0 && lac <= 65535) ? lac : -1;
cid = (cid >= 0 && cid <= 65535) ? cid : -1;
rssi = (rssi >= 0 && rssi <= 31) ? rssi : -1;
ber = (ber >= 0 && ber <= 7) ? ber : -1;
ofono_netmon_serving_cell_notify(netmon,
OFONO_NETMON_CELL_TYPE_GSM,
OFONO_NETMON_INFO_MCC, s_mcc,
OFONO_NETMON_INFO_MNC, s_mnc,
OFONO_NETMON_INFO_LAC, lac,
OFONO_NETMON_INFO_CI, cid,
OFONO_NETMON_INFO_RSSI, rssi,
OFONO_NETMON_INFO_BER, ber,
OFONO_NETMON_INFO_INVALID);
} else if (cell_type == NETMON_RIL_CELLINFO_TYPE_UMTS) {
mcc = parcel_r_int32(&rilp);
mnc = parcel_r_int32(&rilp);
lac = parcel_r_int32(&rilp);
cid = parcel_r_int32(&rilp);
psc = parcel_r_int32(&rilp);
rssi = parcel_r_int32(&rilp);
ber = parcel_r_int32(&rilp);
if (mcc >= 0 && mcc <= 999)
snprintf(s_mcc, sizeof(s_mcc), "%03d", mcc);
else
strcpy(s_mcc, "");
if (mnc >= 0 && mnc <= 999)
snprintf(s_mnc, sizeof(s_mnc), "%03d", mnc);
else
strcpy(s_mnc, "");
lac = (lac >= 0 && lac <= 65535) ? lac : -1;
cid = (cid >= 0 && cid <= 268435455) ? cid : -1;
psc = (psc >= 0 && rssi <= 511) ? psc : -1;
rssi = (rssi >= 0 && rssi <= 31) ? rssi : -1;
ber = (ber >= 0 && ber <= 7) ? ber : -1;
ofono_netmon_serving_cell_notify(netmon,
OFONO_NETMON_CELL_TYPE_UMTS,
OFONO_NETMON_INFO_MCC, s_mcc,
OFONO_NETMON_INFO_MNC, s_mnc,
OFONO_NETMON_INFO_LAC, lac,
OFONO_NETMON_INFO_CI, cid,
OFONO_NETMON_INFO_PSC, psc,
OFONO_NETMON_INFO_RSSI, rssi,
OFONO_NETMON_INFO_BER, ber,
OFONO_NETMON_INFO_INVALID);
} else {
goto error;
}
CALLBACK_WITH_SUCCESS(cb, cbd->data);
return;
error:
CALLBACK_WITH_FAILURE(cb, cbd->data);
}
static int ril_netmon_probe(struct ofono_netmon *netmon,
unsigned int vendor, void *user)
{
GRil *ril = user;
struct netmon_data *ud = g_new0(struct netmon_data, 1);
ud->ril = g_ril_clone(ril);
ofono_netmon_set_data(netmon, ud);
g_idle_add(ril_delayed_register, netmon);
return 0;
}
static void ril_netmon_remove(struct ofono_netmon *netmon)
{
struct netmon_data *nmd = ofono_netmon_get_data(netmon);
ofono_netmon_set_data(netmon, NULL);
g_ril_unref(nmd->ril);
}
static void ril_netmon_request_update(struct ofono_netmon *netmon,
ofono_netmon_cb_t cb, void *data)
{
struct netmon_data *nmd = ofono_netmon_get_data(netmon);
struct cb_data *cbd = cb_data_new(cb, data, nmd);
if (g_ril_send(nmd->ril, RIL_REQUEST_GET_CELL_INFO_LIST, NULL,
ril_netmon_update_cb, cbd, NULL) > 0)
return;
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, data);
}
static struct ofono_netmon_driver driver = {
.name = RILMODEM,
.probe = ril_netmon_probe,
.remove = ril_netmon_remove,
.request_update = ril_netmon_request_update,
};
void ril_netmon_init(void)
{
ofono_netmon_driver_register(&driver);
}
void ril_netmon_exit(void)
{
ofono_netmon_driver_unregister(&driver);
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,169 +0,0 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2013 Jolla Ltd
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#define _GNU_SOURCE
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <glib.h>
#include <ofono/log.h>
#include <ofono/modem.h>
#include <ofono/oemraw.h>
#include "common.h"
#include "gril.h"
#include "rilmodem.h"
struct oem_raw_data {
GRil *ril;
unsigned int vendor;
guint timer_id;
};
static gboolean ril_oemraw_delayed_register(gpointer user_data)
{
struct ofono_oem_raw *raw = user_data;
struct oem_raw_data *od = ofono_oem_raw_get_data(raw);
DBG("");
od->timer_id = 0;
ofono_oem_raw_dbus_register(raw);
return FALSE; /* This makes the timeout a single-shot */
}
static int ril_oemraw_probe(struct ofono_oem_raw *raw, unsigned int vendor,
void *data)
{
GRil *ril = data;
struct oem_raw_data *od;
DBG("");
od = g_new0(struct oem_raw_data, 1);
od->ril = g_ril_clone(ril);
od->vendor = vendor;
ofono_oem_raw_set_data(raw, od);
od->timer_id = g_timeout_add_seconds(1, ril_oemraw_delayed_register,
raw);
return 0;
}
static void ril_oemraw_remove(struct ofono_oem_raw *raw)
{
struct oem_raw_data *od;
DBG("");
od = ofono_oem_raw_get_data(raw);
ofono_oem_raw_set_data(raw, NULL);
if (od->timer_id)
g_source_remove(od->timer_id);
g_ril_unref(od->ril);
g_free(od);
}
static void ril_oemraw_request_cb(struct ril_msg *msg,
gpointer user_data)
{
struct ofono_error error;
struct ofono_oem_raw_results result;
struct cb_data *cbd = user_data;
ofono_oem_raw_query_cb_t cb = cbd->cb;
if (msg && msg->error == RIL_E_SUCCESS) {
decode_ril_error(&error, "OK");
} else {
DBG("error:%d len:%d unsol:%d req:%d serial_no:%d",
msg->error, msg->buf_len, msg->unsolicited,
msg->req, msg->serial_no);
CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
return;
}
result.data = msg->buf;
result.length = msg->buf_len;
cb(&error, &result, cbd->data);
}
static void ril_oemraw_request(struct ofono_oem_raw *raw,
const struct ofono_oem_raw_request *request,
ofono_oem_raw_query_cb_t cb, void *data)
{
int ret;
int i;
struct cb_data *cbd;
struct oem_raw_data *od;
struct parcel parcel;
cbd = cb_data_new(cb, data);
od = ofono_oem_raw_get_data(raw);
parcel_init(&parcel);
for (i = 0; i < request->length; i++) {
/*DBG("Byte: 0x%x", request->data[i]); Enable for debugging*/
parcel_w_byte(&parcel, request->data[i]);
}
ret = g_ril_send(od->ril, RIL_REQUEST_OEM_HOOK_RAW, parcel.data,
parcel.size, ril_oemraw_request_cb, cbd,
g_free);
parcel_free(&parcel);
if (ret <= 0) {
g_free(cbd);
DBG("Failed to issue an OEM RAW request to RIL: result=%d ",
ret);
CALLBACK_WITH_FAILURE(cb, NULL, data);
}
return;
}
static struct ofono_oem_raw_driver driver = {
.name = "rilmodem",
.probe = ril_oemraw_probe,
.remove = ril_oemraw_remove,
.request = ril_oemraw_request,
};
void ril_oemraw_init(void)
{
DBG("");
ofono_oem_raw_driver_register(&driver);
}
void ril_oemraw_exit(void)
{
DBG("");
ofono_oem_raw_driver_unregister(&driver);
}

File diff suppressed because it is too large Load Diff

View File

@@ -5,6 +5,7 @@
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2013 Jolla Ltd
* Contact: Jussi Kangas <jussi.kangas@tieto.com>
* Copyright (C) 2014 Canonical Ltd
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -35,296 +36,410 @@
#include <ofono/log.h>
#include <ofono/modem.h>
#include <ofono/radio-settings.h>
#include <ofono/sim.h>
#include "gril.h"
#include "grilutil.h"
#include "storage.h"
#include "rilmodem.h"
#include "ril_constants.h"
/* Preferred network types */
#define PREF_NET_TYPE_GSM_WCDMA 0
#define PREF_NET_TYPE_GSM_ONLY 1
#define PREF_NET_TYPE_WCDMA 2
#define PREF_NET_TYPE_GSM_WCDMA_AUTO 3
#define PREF_NET_TYPE_CDMA_EVDO_AUTO 4
#define PREF_NET_TYPE_CDMA_ONLY 5
#define PREF_NET_TYPE_EVDO_ONLY 6
#define PREF_NET_TYPE_GSM_WCDMA_CDMA_EVDO_AUTO 7
#define PREF_NET_TYPE_LTE_CDMA_EVDO 8
#define PREF_NET_TYPE_LTE_GSM_WCDMA 9
#define PREF_NET_TYPE_LTE_CMDA_EVDO_GSM_WCDMA 10
#define PREF_NET_TYPE_LTE_ONLY 11
#define PREF_NET_TYPE_LTE_WCDMA 12
/* MTK specific network types */
#define MTK_PREF_NET_TYPE_BASE 30
#define MTK_PREF_NET_TYPE_LTE_GSM_WCDMA (MTK_PREF_NET_TYPE_BASE + 1)
#define MTK_PREF_NET_TYPE_LTE_GSM_WCDMA_MMDC (MTK_PREF_NET_TYPE_BASE + 2)
#define MTK_PREF_NET_TYPE_GSM_WCDMA_LTE (MTK_PREF_NET_TYPE_BASE + 3)
#define MTK_PREF_NET_TYPE_GSM_WCDMA_LTE_MMDC (MTK_PREF_NET_TYPE_BASE + 4)
#define MTK_PREF_NET_TYPE_LTE_GSM_TYPE (MTK_PREF_NET_TYPE_BASE + 5)
#define MTK_PREF_NET_TYPE_LTE_GSM_MMDC_TYPE (MTK_PREF_NET_TYPE_BASE + 6)
/*GSM Band*/
#define PREF_NET_BAND_GSM_AUTOMATIC 255
#define PREF_NET_BAND_GSM850 6
#define PREF_NET_BAND_GSM900_P 1
#define PREF_NET_BAND_GSM900_E 2
#define PREF_NET_BAND_GSM1800 4
#define PREF_NET_BAND_GSM1900 5
/*UMTS Band*/
#define PREF_NET_BAND_UMTS_AUTOMATIC 255
#define PREF_NET_BAND_UMTS_V 54
#define PREF_NET_BAND_UMTS_VIII 57
#define PREF_NET_BAND_UMTS_IV 53
#define PREF_NET_BAND_UMTS_II 51
#define PREF_NET_BAND_UMTS_I 50
struct radio_data {
GRil *ril;
guint timer_id;
int ratmode;
gboolean fast_dormancy;
gboolean pending_fd;
unsigned int vendor;
};
static void ril_set_rat_cb(struct ril_msg *message, gpointer user_data)
{
struct cb_data *cbd = user_data;
struct ofono_radio_settings *rs = cbd->user;
struct radio_data *rd = ofono_radio_settings_get_data(rs);
ofono_radio_settings_rat_mode_set_cb_t cb = cbd->cb;
if (message->error == RIL_E_SUCCESS)
if (message->error == RIL_E_SUCCESS) {
g_ril_print_response_no_args(rd->ril, message);
CALLBACK_WITH_SUCCESS(cb, cbd->data);
else {
ofono_error("rat mode setting failed");
} else {
ofono_error("%s: rat mode setting failed", __func__);
CALLBACK_WITH_FAILURE(cb, cbd->data);
}
}
static void ril_set_rat_mode(struct ofono_radio_settings *rs,
enum ofono_radio_access_mode mode,
ofono_radio_settings_rat_mode_set_cb_t cb,
void *data)
enum ofono_radio_access_mode mode,
ofono_radio_settings_rat_mode_set_cb_t cb,
void *data)
{
struct radio_data *rd = ofono_radio_settings_get_data(rs);
struct cb_data *cbd = cb_data_new(cb, data);
struct cb_data *cbd = cb_data_new(cb, data, rs);
struct parcel rilp;
int pref = rd->ratmode;
int ret = 0;
ofono_info("rat mode set %d", mode);
parcel_init(&rilp);
parcel_w_int32(&rilp, 1); /* Number of params */
int pref = PREF_NET_TYPE_GSM_WCDMA;
switch (mode) {
case OFONO_RADIO_ACCESS_MODE_ANY:
pref = PREF_NET_TYPE_LTE_GSM_WCDMA;
break;
case OFONO_RADIO_ACCESS_MODE_GSM:
pref = PREF_NET_TYPE_GSM_ONLY;
break;
case OFONO_RADIO_ACCESS_MODE_UMTS:
pref = PREF_NET_TYPE_GSM_WCDMA_AUTO; /* according to UI design */
pref = PREF_NET_TYPE_GSM_WCDMA;
break;
case OFONO_RADIO_ACCESS_MODE_LTE:
pref = PREF_NET_TYPE_LTE_ONLY;
default:
pref = PREF_NET_TYPE_LTE_GSM_WCDMA;
break;
}
parcel_init(&rilp);
parcel_w_int32(&rilp, 1); /* Number of params */
parcel_w_int32(&rilp, pref);
ret = g_ril_send(rd->ril, RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE,
rilp.data, rilp.size, ril_set_rat_cb,
cbd, g_free);
g_ril_append_print_buf(rd->ril, "(%d)", pref);
parcel_free(&rilp);
if (ret <= 0) {
ofono_error("unable to set rat mode");
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, data);
}
}
static void ril_force_rat_mode(struct radio_data *rd, int pref)
{
struct parcel rilp;
if (pref == rd->ratmode)
if (g_ril_send(rd->ril, RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE,
&rilp, ril_set_rat_cb, cbd, g_free) > 0)
return;
DBG("pref ril rat mode %d, ril current %d", pref, rd->ratmode);
parcel_init(&rilp);
parcel_w_int32(&rilp, 1);
parcel_w_int32(&rilp, rd->ratmode);
g_ril_send(rd->ril,
RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE,
rilp.data, rilp.size, NULL,
NULL, g_free);
parcel_free(&rilp);
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, data);
}
static void ril_rat_mode_cb(struct ril_msg *message, gpointer user_data)
{
DBG("");
struct cb_data *cbd = user_data;
ofono_radio_settings_rat_mode_query_cb_t cb = cbd->cb;
struct ofono_radio_settings *rs = cbd->user;
struct radio_data *rd = ofono_radio_settings_get_data(rs);
int mode;
struct parcel rilp;
int mode = OFONO_RADIO_ACCESS_MODE_ANY;
int pref;
int net_type;
if (message->error == RIL_E_SUCCESS) {
ril_util_init_parcel(message, &rilp);
/* first item in int[] is len so let's skip that */
parcel_r_int32(&rilp);
pref = parcel_r_int32(&rilp);
if (message->error != RIL_E_SUCCESS)
goto error;
switch (pref) {
case PREF_NET_TYPE_LTE_ONLY:
mode = OFONO_RADIO_ACCESS_MODE_LTE;
case PREF_NET_TYPE_GSM_ONLY:
mode = OFONO_RADIO_ACCESS_MODE_GSM;
g_ril_init_parcel(message, &rilp);
if (parcel_r_int32(&rilp) != 1)
goto error;
net_type = parcel_r_int32(&rilp);
if (rilp.malformed)
goto error;
g_ril_append_print_buf(rd->ril, "{%d}", net_type);
g_ril_print_response(rd->ril, message);
/* Try to translate special MTK settings */
if (g_ril_vendor(rd->ril) == OFONO_RIL_VENDOR_MTK) {
switch (net_type) {
/* 4G preferred */
case MTK_PREF_NET_TYPE_LTE_GSM_WCDMA:
case MTK_PREF_NET_TYPE_LTE_GSM_WCDMA_MMDC:
case MTK_PREF_NET_TYPE_LTE_GSM_TYPE:
case MTK_PREF_NET_TYPE_LTE_GSM_MMDC_TYPE:
net_type = PREF_NET_TYPE_LTE_GSM_WCDMA;
break;
case PREF_NET_TYPE_GSM_WCDMA_AUTO:/* according to UI design */
if (!cb)
ril_force_rat_mode(cbd->user, pref);
case PREF_NET_TYPE_WCDMA:
case PREF_NET_TYPE_GSM_WCDMA: /* according to UI design */
mode = OFONO_RADIO_ACCESS_MODE_UMTS;
break;
case PREF_NET_TYPE_LTE_CDMA_EVDO:
case PREF_NET_TYPE_LTE_GSM_WCDMA:
case PREF_NET_TYPE_LTE_CMDA_EVDO_GSM_WCDMA:
if (!cb)
ril_force_rat_mode(cbd->user, pref);
break;
case PREF_NET_TYPE_CDMA_EVDO_AUTO:
case PREF_NET_TYPE_CDMA_ONLY:
case PREF_NET_TYPE_EVDO_ONLY:
case PREF_NET_TYPE_GSM_WCDMA_CDMA_EVDO_AUTO:
default:
/* 3G or 2G preferred over LTE */
case MTK_PREF_NET_TYPE_GSM_WCDMA_LTE:
case MTK_PREF_NET_TYPE_GSM_WCDMA_LTE_MMDC:
net_type = PREF_NET_TYPE_GSM_WCDMA;
break;
}
ofono_info("rat mode %d (ril %d)", mode, pref);
if (cb)
CALLBACK_WITH_SUCCESS(cb, mode, cbd->data);
} else {
if (cb)
CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
ofono_error("rat mode query failed");
}
if (net_type < 0 || net_type > PREF_NET_TYPE_LTE_ONLY) {
ofono_error("%s: unknown network type", __func__);
goto error;
}
/*
* GSM_WCDMA_AUTO -> ril.h: GSM/WCDMA (auto mode, according to PRL)
* PRL: preferred roaming list.
* This value is returned when selecting the slot as having 3G
* capabilities, so it is sort of the default for MTK modems.
*/
switch (net_type) {
case PREF_NET_TYPE_WCDMA:
case PREF_NET_TYPE_GSM_WCDMA:
case PREF_NET_TYPE_GSM_WCDMA_AUTO:
mode = OFONO_RADIO_ACCESS_MODE_UMTS;
break;
case PREF_NET_TYPE_GSM_ONLY:
mode = OFONO_RADIO_ACCESS_MODE_GSM;
break;
case PREF_NET_TYPE_LTE_GSM_WCDMA:
mode = OFONO_RADIO_ACCESS_MODE_LTE;
break;
default:
ofono_error("%s: Unexpected preferred network type (%d)",
__func__, net_type);
mode = OFONO_RADIO_ACCESS_MODE_ANY;
break;
}
CALLBACK_WITH_SUCCESS(cb, mode, cbd->data);
return;
error:
CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
}
static void ril_query_rat_mode(struct ofono_radio_settings *rs,
ofono_radio_settings_rat_mode_query_cb_t cb,
void *data){
DBG("");
struct radio_data *rd = ofono_radio_settings_get_data(rs);
struct cb_data *cbd = cb_data_new(cb, data);
int ret = 0;
ofono_info("rat mode query");
ret = g_ril_send(rd->ril, RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE,
NULL, 0, ril_rat_mode_cb, cbd, g_free);
/* In case of error free cbd and return the cb with failure */
if (ret <= 0) {
ofono_error("unable to send rat mode query");
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, -1, data);
}
}
static gboolean ril_get_net_config(struct radio_data *rsd)
ofono_radio_settings_rat_mode_query_cb_t cb,
void *data)
{
GKeyFile *keyfile;
GError *err = NULL;
char *config_path = RIL_CONFIG_DIR;
char **alreadyset = NULL;
gboolean needsconfig = FALSE;
gboolean value = FALSE;
gboolean found = FALSE;
rsd->ratmode = PREF_NET_TYPE_GSM_WCDMA_AUTO;
GDir *config_dir;
const gchar *config_file;
gsize length;
gchar **codes = NULL;
int i;
struct radio_data *rd = ofono_radio_settings_get_data(rs);
struct cb_data *cbd = cb_data_new(cb, data, rs);
/*
* First we need to check should the LTE be on
* or not
*/
if (g_ril_send(rd->ril, RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE,
NULL, ril_rat_mode_cb, cbd, g_free) > 0)
return;
keyfile = g_key_file_new();
g_key_file_set_list_separator(keyfile, ',');
config_dir = g_dir_open(config_path, 0, NULL);
while ((config_file = g_dir_read_name(config_dir)) != NULL) {
char *path = g_strconcat(RIL_CONFIG_DIR "/", config_file, NULL);
DBG("Rilconfig handling %s", path);
gboolean ok = g_key_file_load_from_file(keyfile, path, 0, &err);
g_free(path);
if (!ok) {
g_error_free(err);
DBG("Rilconfig file skipped");
continue;
}
if (g_key_file_has_group(keyfile, LTE_FLAG))
found = TRUE;
else if (g_key_file_has_group(keyfile, MCC_LIST)) {
codes = g_key_file_get_string_list(keyfile, MCC_LIST,
MCC_KEY, &length, NULL);
if (codes) {
for (i = 0; codes[i]; i++) {
if (g_str_equal(codes[i],
ofono_sim_get_mcc(get_sim()))
== TRUE) {
found = TRUE;
break;
}
}
g_strfreev(codes);
}
}
if (found) {
rsd->ratmode = PREF_NET_TYPE_LTE_GSM_WCDMA;
break;
}
}
g_key_file_free(keyfile);
g_dir_close(config_dir);
/* Then we need to check if it already set */
keyfile = storage_open(NULL, RIL_STORE);
alreadyset = g_key_file_get_groups(keyfile, NULL);
if (alreadyset[0])
value = g_key_file_get_boolean(
keyfile, alreadyset[0], LTE_FLAG, NULL);
else if (rsd->ratmode == PREF_NET_TYPE_GSM_WCDMA_AUTO)
value = TRUE;
if (!value && rsd->ratmode == PREF_NET_TYPE_LTE_GSM_WCDMA) {
g_key_file_set_boolean(keyfile,
LTE_FLAG, LTE_FLAG, TRUE);
needsconfig = TRUE;
} else if (value && rsd->ratmode == PREF_NET_TYPE_GSM_WCDMA_AUTO) {
g_key_file_set_boolean(keyfile,
LTE_FLAG, LTE_FLAG, FALSE);
needsconfig = TRUE;
}
g_strfreev(alreadyset);
storage_close(NULL, RIL_STORE, keyfile, TRUE);
DBG("needsconfig %d, rat mode %d", needsconfig, rsd->ratmode);
return needsconfig;
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, -1, data);
}
static gboolean ril_delayed_register(gpointer user_data)
static void ril_query_fast_dormancy(struct ofono_radio_settings *rs,
ofono_radio_settings_fast_dormancy_query_cb_t cb,
void *data)
{
struct radio_data *rd = ofono_radio_settings_get_data(rs);
CALLBACK_WITH_SUCCESS(cb, rd->fast_dormancy, data);
}
static void ril_display_state_cb(struct ril_msg *message, gpointer user_data)
{
struct cb_data *cbd = user_data;
struct ofono_radio_settings *rs = cbd->user;
struct radio_data *rd = ofono_radio_settings_get_data(rs);
ofono_radio_settings_fast_dormancy_set_cb_t cb = cbd->cb;
if (message->error == RIL_E_SUCCESS) {
g_ril_print_response_no_args(rd->ril, message);
rd->fast_dormancy = rd->pending_fd;
CALLBACK_WITH_SUCCESS(cb, cbd->data);
} else {
CALLBACK_WITH_FAILURE(cb, cbd->data);
}
}
static void ril_set_fast_dormancy(struct ofono_radio_settings *rs,
ofono_bool_t enable,
ofono_radio_settings_fast_dormancy_set_cb_t cb,
void *data)
{
struct radio_data *rd = ofono_radio_settings_get_data(rs);
struct cb_data *cbd = cb_data_new(cb, data, rs);
struct parcel rilp;
parcel_init(&rilp);
parcel_w_int32(&rilp, 1); /* Number of params */
parcel_w_int32(&rilp, enable);
g_ril_append_print_buf(rd->ril, "(%d)", enable);
rd->pending_fd = enable;
if (g_ril_send(rd->ril, RIL_REQUEST_SCREEN_STATE, &rilp,
ril_display_state_cb, cbd, g_free) > 0)
return;
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, data);
}
static void ril_query_available_rats(struct ofono_radio_settings *rs,
ofono_radio_settings_available_rats_query_cb_t cb,
void *data)
{
unsigned int available_rats;
struct ofono_modem *modem = ofono_radio_settings_get_modem(rs);
available_rats = OFONO_RADIO_ACCESS_MODE_GSM
| OFONO_RADIO_ACCESS_MODE_UMTS;
if (ofono_modem_get_boolean(modem, MODEM_PROP_LTE_CAPABLE))
available_rats |= OFONO_RADIO_ACCESS_MODE_LTE;
CALLBACK_WITH_SUCCESS(cb, available_rats, data);
}
static void ril_set_band_cb(struct ril_msg *message, gpointer user_data)
{
struct cb_data *cbd = user_data;
struct ofono_radio_settings *rs = cbd->user;
struct radio_data *rd = ofono_radio_settings_get_data(rs);
ofono_radio_settings_band_set_cb_t cb = cbd->cb;
if (message->error == RIL_E_SUCCESS) {
g_ril_print_response_no_args(rd->ril, message);
CALLBACK_WITH_SUCCESS(cb, cbd->data);
} else {
CALLBACK_WITH_FAILURE(cb, cbd->data);
}
}
static void ril_sofia3gr_set_band(struct ofono_radio_settings *rs,
enum ofono_radio_band_gsm band_gsm,
enum ofono_radio_band_umts band_umts,
ofono_radio_settings_band_set_cb_t cb,
void *data)
{
struct radio_data *rd = ofono_radio_settings_get_data(rs);
struct cb_data *cbd = cb_data_new(cb, data, rs);
struct parcel rilp;
char cmd_buf[9], gsm_band[4], umts_band[4];
/* RIL_OEM_HOOK_STRING_SET_BAND_PREFERENCE = 0x000000CE */
int cmd_id = 0x000000CE;
sprintf(cmd_buf, "%d", cmd_id);
switch (band_gsm) {
case OFONO_RADIO_BAND_GSM_ANY:
sprintf(gsm_band, "%d", PREF_NET_BAND_GSM_AUTOMATIC);
break;
case OFONO_RADIO_BAND_GSM_850:
sprintf(gsm_band, "%d", PREF_NET_BAND_GSM850);
break;
case OFONO_RADIO_BAND_GSM_900P:
sprintf(gsm_band, "%d", PREF_NET_BAND_GSM900_P);
break;
case OFONO_RADIO_BAND_GSM_900E:
sprintf(gsm_band, "%d", PREF_NET_BAND_GSM900_E);
break;
case OFONO_RADIO_BAND_GSM_1800:
sprintf(gsm_band, "%d", PREF_NET_BAND_GSM1800);
break;
case OFONO_RADIO_BAND_GSM_1900:
sprintf(gsm_band, "%d", PREF_NET_BAND_GSM1900);
break;
default:
CALLBACK_WITH_FAILURE(cb, data);
return;
}
switch (band_umts) {
case OFONO_RADIO_BAND_UMTS_ANY:
sprintf(umts_band, "%d", PREF_NET_BAND_UMTS_AUTOMATIC);
break;
case OFONO_RADIO_BAND_UMTS_850:
sprintf(umts_band, "%d", PREF_NET_BAND_UMTS_V);
break;
case OFONO_RADIO_BAND_UMTS_900:
sprintf(umts_band, "%d", PREF_NET_BAND_UMTS_VIII);
break;
case OFONO_RADIO_BAND_UMTS_1700AWS:
sprintf(umts_band, "%d", PREF_NET_BAND_UMTS_IV);
break;
case OFONO_RADIO_BAND_UMTS_1900:
sprintf(umts_band, "%d", PREF_NET_BAND_UMTS_II);
break;
case OFONO_RADIO_BAND_UMTS_2100:
sprintf(umts_band, "%d", PREF_NET_BAND_UMTS_I);
break;
default:
CALLBACK_WITH_FAILURE(cb, data);
return;
}
parcel_init(&rilp);
parcel_w_int32(&rilp, 3); /* Number of params */
parcel_w_string(&rilp, cmd_buf);
parcel_w_string(&rilp, gsm_band);
parcel_w_string(&rilp, umts_band);
if (g_ril_send(rd->ril, RIL_REQUEST_OEM_HOOK_STRINGS, &rilp,
ril_set_band_cb, cbd, g_free) > 0)
return;
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, data);
}
static void ril_set_band(struct ofono_radio_settings *rs,
enum ofono_radio_band_gsm band_gsm,
enum ofono_radio_band_umts band_umts,
ofono_radio_settings_band_set_cb_t cb,
void *data)
{
struct radio_data *rd = ofono_radio_settings_get_data(rs);
switch (rd->vendor) {
case OFONO_RIL_VENDOR_IMC_SOFIA3GR:
ril_sofia3gr_set_band(rs, band_gsm, band_umts, cb, data);
return;
default:
break;
}
CALLBACK_WITH_FAILURE(cb, data);
}
static void ril_delayed_register(const struct ofono_error *error,
void *user_data)
{
struct ofono_radio_settings *rs = user_data;
struct radio_data *rd = ofono_radio_settings_get_data(rs);
rd->timer_id = 0;
ofono_radio_settings_register(rs);
return FALSE;
if (error->type == OFONO_ERROR_TYPE_NO_ERROR)
ofono_radio_settings_register(rs);
else
ofono_error("%s: cannot set default fast dormancy", __func__);
}
static int ril_radio_settings_probe(struct ofono_radio_settings *rs,
unsigned int vendor,
void *user)
unsigned int vendor, void *user)
{
GRil *ril = user;
struct cb_data *cbd = NULL;
int ret;
struct radio_data *rsd = g_try_new0(struct radio_data, 1);
struct radio_data *rsd = g_new0(struct radio_data, 1);
rsd->ril = g_ril_clone(ril);
if (ril_get_net_config(rsd)) {
cbd = cb_data_new2(rsd, NULL, NULL);
ret = g_ril_send(rsd->ril,
RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE,
NULL, 0, ril_rat_mode_cb, cbd, g_free);
if (ret <= 0)
g_free(cbd);
}
rsd->vendor = vendor;
ofono_radio_settings_set_data(rs, rsd);
rsd->timer_id = g_timeout_add_seconds(2, ril_delayed_register, rs);
ril_set_fast_dormancy(rs, FALSE, ril_delayed_register, rs);
return 0;
}
@@ -334,19 +449,20 @@ static void ril_radio_settings_remove(struct ofono_radio_settings *rs)
struct radio_data *rd = ofono_radio_settings_get_data(rs);
ofono_radio_settings_set_data(rs, NULL);
if (rd->timer_id > 0)
g_source_remove(rd->timer_id);
g_ril_unref(rd->ril);
g_free(rd);
}
static struct ofono_radio_settings_driver driver = {
.name = "rilmodem",
.probe = ril_radio_settings_probe,
.remove = ril_radio_settings_remove,
.name = RILMODEM,
.probe = ril_radio_settings_probe,
.remove = ril_radio_settings_remove,
.query_rat_mode = ril_query_rat_mode,
.set_rat_mode = ril_set_rat_mode,
.set_band = ril_set_band,
.query_fast_dormancy = ril_query_fast_dormancy,
.set_fast_dormancy = ril_set_fast_dormancy,
.query_available_rats = ril_query_available_rats
};
void ril_radio_settings_init(void)

View File

@@ -4,7 +4,6 @@
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2012 Canonical, Ltd. All rights reserved.
* Copyright (C) 2013 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -45,18 +44,16 @@ static int rilmodem_init(void)
ril_sms_init();
ril_netreg_init();
ril_call_volume_init();
ril_gprs_init();
ril_gprs_context_init();
ril_radio_settings_init();
ril_phonebook_init();
ril_ussd_init();
ril_call_settings_init();
ril_call_forwarding_init();
ril_radio_settings_init();
ril_call_barring_init();
ril_cbs_init();
ril_oemraw_init();
ril_netmon_init();
ril_stk_init();
ril_cbs_init();
return 0;
}
@@ -73,15 +70,14 @@ static void rilmodem_exit(void)
ril_call_volume_exit();
ril_gprs_exit();
ril_gprs_context_exit();
ril_radio_settings_exit();
ril_phonebook_exit();
ril_ussd_exit();
ril_call_settings_exit();
ril_call_forwarding_exit();
ril_radio_settings_exit();
ril_call_barring_exit();
ril_cbs_exit();
ril_oemraw_exit();
ril_netmon_exit();
ril_stk_exit();
ril_cbs_exit();
}
OFONO_PLUGIN_DEFINE(rilmodem, "RIL modem driver", VERSION,

View File

@@ -4,7 +4,6 @@
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2012 Canonical Ltd.
* Copyright (C) 2013 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -28,14 +27,6 @@
/* Shared constants */
#define EF_STATUS_INVALIDATED 0
#define EF_STATUS_VALID 1
#define RIL_HW_CONFIG "/etc/ofono/ril_subscription.conf"
#define RIL_CONFIG_DIR "/etc/ofono/"
#define RIL_STORE "rilmodem"
#define LTE_FLAG "4gOn"
#define MCC_LIST "MCC-whitelist"
#define MCC_KEY "Countries"
#define UI_LANG "/var/lib/environment/nemo/locale.conf"
#define CFG_LANG "LANG="
extern void ril_devinfo_init(void);
extern void ril_devinfo_exit(void);
@@ -61,9 +52,6 @@ extern void ril_gprs_exit(void);
extern void ril_gprs_context_init(void);
extern void ril_gprs_context_exit(void);
extern void ril_radio_settings_init(void);
extern void ril_radio_settings_exit(void);
extern void ril_ussd_init(void);
extern void ril_ussd_exit(void);
@@ -73,18 +61,20 @@ extern void ril_call_settings_exit(void);
extern void ril_call_forwarding_init(void);
extern void ril_call_forwarding_exit(void);
extern void ril_radio_settings_init(void);
extern void ril_radio_settings_exit(void);
extern void ril_call_barring_init(void);
extern void ril_call_barring_exit(void);
extern void ril_cbs_init(void);
extern void ril_cbs_exit(void);
extern void ril_phonebook_init(void);
extern void ril_phonebook_exit(void);
extern void ril_oemraw_init(void);
extern void ril_oemraw_exit(void);
extern void ril_netmon_init(void);
extern void ril_netmon_exit(void);
extern void ril_stk_init(void);
extern void ril_stk_exit(void);
extern void ril_cbs_init(void);
extern void ril_cbs_exit(void);

View File

@@ -4,7 +4,6 @@
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2012 Canonical Ltd.
* Copyright (C) 2013 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -29,6 +28,7 @@
#include <gril.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
#define OFONO_API_SUBJECT_TO_CHANGE
#include <ofono/log.h>
@@ -40,19 +40,6 @@
#include "util.h"
#include "ril_constants.h"
struct ril_util_sim_state_query {
GRil *ril;
guint cpin_poll_source;
guint cpin_poll_count;
guint interval;
guint num_times;
ril_util_sim_inserted_cb_t cb;
void *userdata;
GDestroyNotify destroy;
};
static gboolean cpin_check(gpointer userdata);
void decode_ril_error(struct ofono_error *error, const char *final)
{
if (!strcmp(final, "OK")) {
@@ -64,642 +51,111 @@ void decode_ril_error(struct ofono_error *error, const char *final)
}
}
gint ril_util_call_compare_by_status(gconstpointer a, gconstpointer b)
{
const struct ofono_call *call = a;
int status = GPOINTER_TO_INT(b);
if (status != call->status)
return 1;
return 0;
}
gint ril_util_call_compare_by_phone_number(gconstpointer a, gconstpointer b)
{
const struct ofono_call *call = a;
const struct ofono_phone_number *pb = b;
return memcmp(&call->phone_number, pb,
sizeof(struct ofono_phone_number));
}
gint ril_util_call_compare_by_id(gconstpointer a, gconstpointer b)
{
const struct ofono_call *call = a;
unsigned int id = GPOINTER_TO_UINT(b);
if (id < call->id)
return -1;
if (id > call->id)
return 1;
return 0;
}
gint ril_util_call_compare(gconstpointer a, gconstpointer b)
{
const struct ofono_call *ca = a;
const struct ofono_call *cb = b;
if (ca->id < cb->id)
return -1;
if (ca->id > cb->id)
return 1;
return 0;
}
static gboolean cpin_check(gpointer userdata)
{
struct ril_util_sim_state_query *req = userdata;
req->cpin_poll_source = 0;
return FALSE;
}
gchar *ril_util_get_netmask(const gchar *address)
{
char *result;
if (g_str_has_suffix(address, "/30"))
return PREFIX_30_NETMASK;
if (g_str_has_suffix(address, "/30")) {
result = PREFIX_30_NETMASK;
} else if (g_str_has_suffix(address, "/29")) {
result = PREFIX_29_NETMASK;
} else if (g_str_has_suffix(address, "/28")) {
result = PREFIX_28_NETMASK;
} else if (g_str_has_suffix(address, "/27")) {
result = PREFIX_27_NETMASK;
} else if (g_str_has_suffix(address, "/26")) {
result = PREFIX_26_NETMASK;
} else if (g_str_has_suffix(address, "/25")) {
result = PREFIX_25_NETMASK;
} else if (g_str_has_suffix(address, "/24")) {
result = PREFIX_24_NETMASK;
} else {
/*
* This handles the case where the
* Samsung RILD returns an address without
* a prefix, however it explicitly sets a
* /24 netmask ( which isn't returned as
* an attribute of the DATA_CALL.
*
* TODO/OEM: this might need to be quirked
* for specific devices.
*/
result = PREFIX_24_NETMASK;
if (g_str_has_suffix(address, "/29"))
return PREFIX_29_NETMASK;
if (g_str_has_suffix(address, "/28"))
return PREFIX_28_NETMASK;
if (g_str_has_suffix(address, "/27"))
return PREFIX_27_NETMASK;
if (g_str_has_suffix(address, "/26"))
return PREFIX_26_NETMASK;
if (g_str_has_suffix(address, "/25"))
return PREFIX_25_NETMASK;
if (g_str_has_suffix(address, "/24"))
return PREFIX_24_NETMASK;
return NULL;
}
void ril_util_build_deactivate_data_call(GRil *gril, struct parcel *rilp,
int cid, unsigned int reason)
{
char *cid_str = NULL;
char *reason_str = NULL;
cid_str = g_strdup_printf("%d", cid);
reason_str = g_strdup_printf("%d", reason);
parcel_init(rilp);
parcel_w_int32(rilp, 2);
parcel_w_string(rilp, cid_str);
parcel_w_string(rilp, reason_str);
g_ril_append_print_buf(gril, "(%s,%s)", cid_str, reason_str);
g_free(cid_str);
g_free(reason_str);
}
const char *ril_util_gprs_proto_to_ril_string(enum ofono_gprs_proto proto)
{
switch (proto) {
case OFONO_GPRS_PROTO_IPV6:
return "IPV6";
case OFONO_GPRS_PROTO_IPV4V6:
return "IPV4V6";
case OFONO_GPRS_PROTO_IP:
default:
return "IP";
}
}
int ril_util_registration_state_to_status(int reg_state)
{
switch (reg_state) {
case RIL_REG_STATE_NOT_REGISTERED:
case RIL_REG_STATE_REGISTERED:
case RIL_REG_STATE_SEARCHING:
case RIL_REG_STATE_DENIED:
case RIL_REG_STATE_UNKNOWN:
case RIL_REG_STATE_ROAMING:
break;
case RIL_REG_STATE_EMERGENCY_NOT_REGISTERED:
case RIL_REG_STATE_EMERGENCY_SEARCHING:
case RIL_REG_STATE_EMERGENCY_DENIED:
case RIL_REG_STATE_EMERGENCY_UNKNOWN:
reg_state -= RIL_REG_STATE_EMERGENCY_NOT_REGISTERED;
break;
default:
reg_state = NETWORK_REGISTRATION_STATUS_UNKNOWN;
}
DBG("address: %s netmask: %s", address, result);
return result;
return reg_state;
}
/* TODO: this function can go away, once all the code has been
* re-factored to use grilreply.c */
void ril_util_init_parcel(struct ril_msg *message, struct parcel *rilp)
int ril_util_address_to_gprs_proto(const char *addr)
{
/* Set up Parcel struct for proper parsing */
rilp->data = message->buf;
rilp->size = message->buf_len;
rilp->capacity = message->buf_len;
rilp->offset = 0;
}
int ret = -1;
struct in_addr ipv4;
struct in6_addr ipv6;
char **addr_split = g_strsplit(addr, "/", 2);
struct ril_util_sim_state_query *ril_util_sim_state_query_new(GRil *ril,
guint interval, guint num_times,
ril_util_sim_inserted_cb_t cb,
void *userdata,
GDestroyNotify destroy)
{
struct ril_util_sim_state_query *req;
req = g_new0(struct ril_util_sim_state_query, 1);
req->ril = ril;
req->interval = interval;
req->num_times = num_times;
req->cb = cb;
req->userdata = userdata;
req->destroy = destroy;
cpin_check(req);
return req;
}
void ril_util_sim_state_query_free(struct ril_util_sim_state_query *req)
{
if (req == NULL)
return;
if (req->cpin_poll_source > 0)
g_source_remove(req->cpin_poll_source);
if (req->destroy)
req->destroy(req->userdata);
g_free(req);
}
GSList *ril_util_parse_clcc(GRil *gril, struct ril_msg *message)
{
struct ofono_call *call;
struct parcel rilp;
GSList *l = NULL;
int num, i;
gchar *number, *name;
ril_util_init_parcel(message, &rilp);
g_ril_append_print_buf(gril, "{");
/* Number of RIL_Call structs */
num = parcel_r_int32(&rilp);
for (i = 0; i < num; i++) {
call = g_try_new(struct ofono_call, 1);
if (call == NULL)
break;
ofono_call_init(call);
call->status = parcel_r_int32(&rilp);
call->id = parcel_r_int32(&rilp);
call->phone_number.type = parcel_r_int32(&rilp);
parcel_r_int32(&rilp); /* isMpty */
call->direction = (parcel_r_int32(&rilp) ? /* isMT */
CALL_DIRECTION_MOBILE_TERMINATED :
CALL_DIRECTION_MOBILE_ORIGINATED);
parcel_r_int32(&rilp); /* als */
call->type = parcel_r_int32(&rilp); /* isVoice */
parcel_r_int32(&rilp); /* isVoicePrivacy */
number = parcel_r_string(&rilp);
if (number) {
strncpy(call->phone_number.number, number,
OFONO_MAX_PHONE_NUMBER_LENGTH);
g_free(number);
}
parcel_r_int32(&rilp); /* numberPresentation */
name = parcel_r_string(&rilp);
if (name) {
strncpy(call->name, name,
OFONO_MAX_CALLER_NAME_LENGTH);
g_free(name);
}
parcel_r_int32(&rilp); /* namePresentation */
parcel_r_int32(&rilp); /* uusInfo */
if (strlen(call->phone_number.number) > 0)
call->clip_validity = 0;
else
call->clip_validity = 2;
/* TODO: figure out how to line-wrap properly
* without introducing spaces in string.
*/
g_ril_append_print_buf(gril,
"%s [id=%d,status=%d,type=%d,number=%s,name=%s]",
print_buf,
call->id, call->status, call->type,
call->phone_number.number, call->name);
l = g_slist_insert_sorted(l, call, ril_util_call_compare);
}
g_ril_append_print_buf(gril, "%s}", print_buf);
g_ril_print_response(gril, message);
return l;
}
char *ril_util_parse_sim_io_rsp(GRil *gril,
struct ril_msg *message,
int *sw1, int *sw2,
int *hex_len)
{
struct parcel rilp;
char *response = NULL;
char *hex_response = NULL;
/* Minimum length of SIM_IO_Response is 12:
* sw1 (int32)
* sw2 (int32)
* simResponse (string)
*/
if (message->buf_len < 12) {
ofono_error("Invalid SIM IO reply: size too small (< 12): %d ",
message->buf_len);
return FALSE;
}
DBG("message->buf_len is: %d", message->buf_len);
ril_util_init_parcel(message, &rilp);
*sw1 = parcel_r_int32(&rilp);
*sw2 = parcel_r_int32(&rilp);
response = parcel_r_string(&rilp);
if (response) {
DBG("response is set; len is: %d", strlen(response));
hex_response = (char *) decode_hex((const char *) response,
strlen(response),
(long *) hex_len, -1);
}
g_ril_append_print_buf(gril,
"(sw1=0x%.2X,sw2=0x%.2X,%s)",
*sw1,
*sw2,
response);
g_ril_print_response(gril, message);
g_free(response);
return hex_response;
}
gboolean ril_util_parse_sim_status(GRil *gril,
struct ril_msg *message,
struct sim_status *status,
struct sim_app **apps)
{
struct parcel rilp;
gboolean result = FALSE;
int i;
g_ril_append_print_buf(gril, "[%04d]< %s",
message->serial_no,
ril_request_id_to_string(message->req));
ril_util_init_parcel(message, &rilp);
/*
* FIXME: Need to come up with a common scheme for verifying the
* size of RIL message and properly reacting to bad messages.
* This could be a runtime assertion, disconnect, drop/ignore
* the message, ...
*
* 20 is the min length of RIL_CardStatus_v6 as the AppState
* array can be 0-length.
*/
if (message->buf_len < 20) {
ofono_error("Size of SIM_STATUS reply too small: %d bytes",
message->buf_len);
status->card_state = RIL_CARDSTATE_ERROR;
return FALSE;
}
status->card_state = parcel_r_int32(&rilp);
/*
* NOTE:
*
* The global pin_status is used for multi-application
* UICC cards. For example, there are SIM cards that
* can be used in both GSM and CDMA phones. Instead
* of managed PINs for both applications, a global PIN
* is set instead. It's not clear at this point if
* such SIM cards are supported by ofono or RILD.
*/
status->pin_state = parcel_r_int32(&rilp);
status->gsm_umts_index = parcel_r_int32(&rilp);
status->cdma_index = parcel_r_int32(&rilp);
status->ims_index = parcel_r_int32(&rilp);
status->num_apps = parcel_r_int32(&rilp);
/* TODO:
* How do we handle long (>80 chars) ril_append_print_buf strings?
* Using line wrapping ( via '\' ) introduces spaces in the output.
* Do we just make a style-guide exception for PrintBuf operations?
*/
g_ril_append_print_buf(gril,
"card_state=%d,universal_pin_state=%d,gsm_umts_index=%d,cdma_index=%d,ims_index=%d, ",
status->card_state,
status->pin_state,
status->gsm_umts_index,
status->cdma_index,
status->ims_index);
DBG("card_state=%d, universal_pin_state=%d, gsm_umts_index=%d, cdma_index=%d, ims_index=%d",
status->card_state,
status->pin_state,
status->gsm_umts_index,
status->cdma_index,
status->ims_index);
if (status->card_state == RIL_CARDSTATE_PRESENT)
result = TRUE;
else
if (addr_split == NULL || g_strv_length(addr_split) == 0)
goto done;
DBG("sim num_apps: %d", status->num_apps);
if (status->num_apps > MAX_UICC_APPS) {
ofono_error("SIM error; too many apps: %d", status->num_apps);
status->num_apps = MAX_UICC_APPS;
if (inet_pton(AF_INET, addr_split[0], &ipv4) > 0) {
ret = OFONO_GPRS_PROTO_IP;
goto done;
}
for (i = 0; i < status->num_apps; i++) {
apps[i] = g_try_new0(struct sim_app, 1);
if (apps[i] == NULL) {
ofono_error("Can't allocate app_data");
goto error;
}
apps[i]->app_type = parcel_r_int32(&rilp);
apps[i]->app_state = parcel_r_int32(&rilp);
/*
* Consider RIL_APPSTATE_ILLEGAL also READY. Even if app state
* is RIL_APPSTATE_ILLEGAL (-1), ICC operations must be
* permitted. Network access requests will anyway be rejected
* and ME will be in limited service.
*/
if (apps[i]->app_state == RIL_APPSTATE_ILLEGAL) {
DBG("RIL_APPSTATE_ILLEGAL => RIL_APPSTATE_READY");
apps[i]->app_state = RIL_APPSTATE_READY;
}
apps[i]->perso_substate = parcel_r_int32(&rilp);
/* TODO: we need a way to instruct parcel to skip
* a string, without allocating memory...
*/
apps[i]->aid_str = parcel_r_string(&rilp); /* app ID (AID) */
apps[i]->app_str = parcel_r_string(&rilp); /* app label */
apps[i]->pin_replaced = parcel_r_int32(&rilp);
apps[i]->pin1_state = parcel_r_int32(&rilp);
apps[i]->pin2_state = parcel_r_int32(&rilp);
g_ril_append_print_buf(gril,
"%s[app_type=%d,app_state=%d,perso_substate=%d,aid_ptr=%s,app_label_ptr=%s,pin1_replaced=%d,pin1=%d,pin2=%d],",
print_buf,
apps[i]->app_type,
apps[i]->app_state,
apps[i]->perso_substate,
apps[i]->aid_str,
apps[i]->app_str,
apps[i]->pin_replaced,
apps[i]->pin1_state,
apps[i]->pin2_state);
DBG("app[%d]: type=%d, state=%d, perso_substate=%d, aid_ptr=%s, app_label_ptr=%s, pin1_replaced=%d, pin1=%d, pin2=%d",
i, apps[i]->app_type,
apps[i]->app_state,
apps[i]->perso_substate,
apps[i]->aid_str,
apps[i]->app_str,
apps[i]->pin_replaced,
apps[i]->pin1_state,
apps[i]->pin2_state);
if (inet_pton(AF_INET6, addr_split[0], &ipv6) > 0) {
ret = OFONO_GPRS_PROTO_IPV6;
goto done;
}
done:
g_ril_append_print_buf(gril, "%s}", print_buf);
g_ril_print_response(gril, message);
g_strfreev(addr_split);
return result;
error:
if (apps)
ril_util_free_sim_apps(apps, status->num_apps);
return FALSE;
}
gboolean ril_util_parse_reg(GRil *gril,
struct ril_msg *message, int *status,
int *lac, int *ci, int *tech, int *max_calls)
{
struct parcel rilp;
int tmp;
gchar *sstatus = NULL, *slac = NULL, *sci = NULL;
gchar *stech = NULL, *sreason = NULL, *smax = NULL;
ril_util_init_parcel(message, &rilp);
/* FIXME: need minimum message size check FIRST!!! */
/* Size of response string array
*
* Should be:
* >= 4 for VOICE_REG reply
* >= 5 for DATA_REG reply
*/
tmp = parcel_r_int32(&rilp);
if (tmp < 4) {
DBG("Size of response array is too small: %d", tmp);
goto error;
}
sstatus = parcel_r_string(&rilp);
slac = parcel_r_string(&rilp);
sci = parcel_r_string(&rilp);
stech = parcel_r_string(&rilp);
tmp -= 4;
/* FIXME: need to review VOICE_REGISTRATION response
* as it returns ~15 parameters ( vs. 6 for DATA ).
*
* The first four parameters are the same for both
* responses ( although status includes values for
* emergency calls for VOICE response ).
*
* Parameters 5 & 6 have different meanings for
* voice & data response.
*/
if (tmp--) {
/* TODO: different use for CDMA */
sreason = parcel_r_string(&rilp);
if (tmp--) {
/* TODO: different use for CDMA */
smax = parcel_r_string(&rilp);
if (smax && max_calls)
*max_calls = atoi(smax);
}
}
if (status) {
if (!sstatus) {
DBG("No sstatus value returned!");
goto error;
}
*status = atoi(sstatus);
}
if (lac) {
if (slac)
*lac = strtol(slac, NULL, 16);
else
*lac = -1;
}
if (ci) {
if (sci)
*ci = strtol(sci, NULL, 16);
else
*ci = -1;
}
if (tech) {
if (stech) {
switch (atoi(stech)) {
case RADIO_TECH_UNKNOWN:
*tech = -1;
break;
case RADIO_TECH_GPRS:
case RADIO_TECH_GSM:
*tech = ACCESS_TECHNOLOGY_GSM;
break;
case RADIO_TECH_EDGE:
*tech = ACCESS_TECHNOLOGY_GSM_EGPRS;
break;
case RADIO_TECH_UMTS:
*tech = ACCESS_TECHNOLOGY_UTRAN;
break;
case RADIO_TECH_HSDPA:
*tech = ACCESS_TECHNOLOGY_UTRAN_HSDPA;
break;
case RADIO_TECH_HSUPA:
*tech = ACCESS_TECHNOLOGY_UTRAN_HSUPA;
break;
case RADIO_TECH_HSPA:
case RADIO_TECH_HSPAP:
case RADIO_TECH_DC_HSDPA:
*tech = ACCESS_TECHNOLOGY_UTRAN_HSDPA_HSUPA;
break;
case RADIO_TECH_LTE:
*tech = ACCESS_TECHNOLOGY_EUTRAN;
break;
default:
*tech = -1;
}
} else
*tech = -1;
}
g_ril_append_print_buf(gril,
"{%s,%s,%s,%s,%s,%s}",
registration_status_to_string(*status),
slac,
sci,
registration_tech_to_string(*tech),
sreason,
smax);
g_ril_print_response(gril, message);
/* Free our parcel handlers */
g_free(sstatus);
g_free(slac);
g_free(sci);
g_free(stech);
g_free(sreason);
g_free(smax);
return TRUE;
error:
return FALSE;
}
gint ril_util_parse_sms_response(GRil *gril, struct ril_msg *message)
{
struct parcel rilp;
int error, mr;
char *ack_pdu;
/* Set up Parcel struct for proper parsing */
ril_util_init_parcel(message, &rilp);
/* TP-Message-Reference for GSM/
* BearerData MessageId for CDMA
*/
mr = parcel_r_int32(&rilp);
ack_pdu = parcel_r_string(&rilp);
/* error: 3GPP 27.005, 3.2.5, -1 if unknown or not applicable */
error = parcel_r_int32(&rilp);
DBG("sms msg ref: %d, error: %d, ack_pdu: %s", mr, error, ack_pdu);
g_ril_append_print_buf(gril, "{%d,%s,%d}",
mr, ack_pdu, error);
g_ril_print_response(gril, message);
return mr;
}
gint ril_util_get_signal(GRil *gril, struct ril_msg *message)
{
struct parcel rilp;
int gw_signal, cdma_dbm, evdo_dbm, lte_signal;
/* Set up Parcel struct for proper parsing */
ril_util_init_parcel(message, &rilp);
/* RIL_SignalStrength_v6 */
/* GW_SignalStrength */
gw_signal = parcel_r_int32(&rilp);
parcel_r_int32(&rilp); /* bitErrorRate */
/* CDMA_SignalStrength */
cdma_dbm = parcel_r_int32(&rilp);
parcel_r_int32(&rilp); /* ecio */
/* EVDO_SignalStrength */
evdo_dbm = parcel_r_int32(&rilp);
parcel_r_int32(&rilp); /* ecio */
parcel_r_int32(&rilp); /* signalNoiseRatio */
/* LTE_SignalStrength */
lte_signal = parcel_r_int32(&rilp);
parcel_r_int32(&rilp); /* rsrp */
parcel_r_int32(&rilp); /* rsrq */
parcel_r_int32(&rilp); /* rssnr */
parcel_r_int32(&rilp); /* cqi */
g_ril_append_print_buf(gril, "(gw: %d, cdma: %d, evdo: %d, lte: %d)",
gw_signal, cdma_dbm, evdo_dbm, lte_signal);
if (message->unsolicited)
g_ril_print_unsol(gril, message);
else
g_ril_print_response(gril, message);
/* Return the first valid one */
if ((gw_signal != 99) && (gw_signal != -1))
return (gw_signal * 100) / 31;
if ((lte_signal != 99) && (lte_signal != -1))
return (lte_signal * 100) / 31;
/* In case of dbm, return the value directly */
if (cdma_dbm != -1) {
if (cdma_dbm > 100)
cdma_dbm = 100;
return cdma_dbm;
}
if (evdo_dbm != -1) {
if (evdo_dbm > 100)
evdo_dbm = 100;
return evdo_dbm;
}
return -1;
}
void ril_util_free_sim_apps(struct sim_app **apps, guint num_apps)
{
guint i;
for (i = 0; i < num_apps; i++) {
g_free(apps[i]->aid_str);
g_free(apps[i]->app_str);
g_free(apps[i]);
}
return ret;
}

View File

@@ -19,10 +19,13 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef RILUTIL_H
#define RILUTIL_H
#include <stdio.h>
#include "parcel.h"
#include <ofono/modem.h>
#include <ofono/sim.h>
#include <ofono/gprs-context.h>
/* TODO: create a table lookup*/
#define PREFIX_30_NETMASK "255.255.255.252"
@@ -33,6 +36,8 @@
#define PREFIX_25_NETMASK "255.255.255.128"
#define PREFIX_24_NETMASK "255.255.255.0"
#define MODEM_PROP_LTE_CAPABLE "lte-capable"
enum ril_util_sms_store {
RIL_UTIL_SMS_STORE_SM = 0,
RIL_UTIL_SMS_STORE_ME = 1,
@@ -62,74 +67,13 @@ enum at_util_charset {
RIL_UTIL_CHARSET_8859_H = 0x10000,
};
#define MAX_UICC_APPS 16
struct sim_status {
guint card_state;
guint pin_state;
guint gsm_umts_index;
guint cdma_index;
guint ims_index;
guint num_apps;
};
struct sim_app {
guint app_type;
guint app_state;
guint perso_substate;
char *aid_str;
char *app_str;
guint pin_replaced;
guint pin1_state;
guint pin2_state;
};
typedef void (*ril_util_sim_inserted_cb_t)(gboolean present, void *userdata);
void decode_ril_error(struct ofono_error *error, const char *final);
gint ril_util_call_compare_by_status(gconstpointer a, gconstpointer b);
gint ril_util_call_compare_by_phone_number(gconstpointer a, gconstpointer b);
gint ril_util_call_compare_by_id(gconstpointer a, gconstpointer b);
gint ril_util_call_compare(gconstpointer a, gconstpointer b);
gchar *ril_util_get_netmask(const char *address);
void ril_util_init_parcel(struct ril_msg *message, struct parcel *rilp);
struct ril_util_sim_state_query *ril_util_sim_state_query_new(GRil *ril,
guint interval, guint num_times,
ril_util_sim_inserted_cb_t cb,
void *userdata,
GDestroyNotify destroy);
void ril_util_sim_state_query_free(struct ril_util_sim_state_query *req);
GSList *ril_util_parse_clcc(GRil *gril, struct ril_msg *message);
char *ril_util_parse_sim_io_rsp(GRil *gril, struct ril_msg *message,
int *sw1, int *sw2,
int *hex_len);
gboolean ril_util_parse_sim_status(GRil *gril, struct ril_msg *message,
struct sim_status *status,
struct sim_app **apps);
gboolean ril_util_parse_reg(GRil *gril, struct ril_msg *message, int *status,
int *lac, int *ci, int *tech, int *max_calls);
gint ril_util_parse_sms_response(GRil *gril, struct ril_msg *message);
gint ril_util_get_signal(GRil *gril, struct ril_msg *message);
gint ril_get_app_type();
struct ofono_sim_driver *get_sim_driver();
struct ofono_sim *get_sim();
gint check_if_really_roaming(gint status);
gboolean ril_roaming_allowed();
gboolean check_if_ok_to_attach();
gint get_current_network_status();
void ril_util_free_sim_apps(struct sim_app **apps, guint num_apps);
void ril_util_build_deactivate_data_call(GRil *gril, struct parcel *rilp,
int cid, unsigned int reason);
struct cb_data {
void *cb;
@@ -137,29 +81,14 @@ struct cb_data {
void *user;
};
static inline struct cb_data *cb_data_new(void *cb, void *data)
static inline struct cb_data *cb_data_new(void *cb, void *data, void *user)
{
struct cb_data *ret;
ret = g_new0(struct cb_data, 1);
ret->cb = cb;
ret->data = data;
return ret;
}
static inline struct cb_data *cb_data_new2(void *user, void *cb,
void *data)
{
struct cb_data *ret;
ret = g_new0(struct cb_data, 1);
if (ret) {
ret->cb = cb;
ret->data = data;
ret->user = user;
}
ret->user = user;
return ret;
}
@@ -176,6 +105,12 @@ static inline int ril_util_convert_signal_strength(int strength)
return result;
}
const char *ril_util_gprs_proto_to_ril_string(enum ofono_gprs_proto);
int ril_util_registration_state_to_status(int reg_state);
int ril_util_address_to_gprs_proto(const char *addr);
#define DECLARE_FAILURE(e) \
struct ofono_error e; \
e.type = OFONO_ERROR_TYPE_FAILURE; \
@@ -197,3 +132,5 @@ static inline int ril_util_convert_signal_strength(int strength)
e.error = 0; \
f(&e, ##args); \
} while (0)
#endif /* RILUTIL_H */

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,7 @@
* oFono - Open Source Telephony - RIL Modem Support
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2012 Canonical Ltd.
* Copyright (C) 2012-2013 Canonical Ltd.
* Copyright (C) 2013 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
@@ -38,35 +38,30 @@
#include <ofono/log.h>
#include <ofono/modem.h>
#include <ofono/sms.h>
#include <ofono/types.h>
#include <ofono/sim.h>
#include "smsutil.h"
#include "util.h"
#include "common.h"
#include "rilmodem.h"
#include "simutil.h"
#define SIM_EFSMS_FILEID 0x6F3C
#define EFSMS_LENGTH 176
unsigned char path[4] = {0x3F, 0x00, 0x7F, 0x10};
struct sms_data {
GRil *ril;
unsigned int vendor;
guint timer_id;
};
static void ril_csca_set_cb(struct ril_msg *message, gpointer user_data)
{
struct cb_data *cbd = user_data;
ofono_sms_sca_set_cb_t cb = cbd->cb;
struct sms_data *sd = cbd->user;
if (message->error == RIL_E_SUCCESS)
if (message->error == RIL_E_SUCCESS) {
CALLBACK_WITH_SUCCESS(cb, cbd->data);
else {
ofono_error("csca setting failed");
} else {
ofono_error("%s RILD reply failure: %s",
g_ril_request_id_to_string(sd->ril, message->req),
ril_error_to_string(message->error));
CALLBACK_WITH_FAILURE(cb, cbd->data);
}
}
@@ -75,121 +70,259 @@ static void ril_csca_set(struct ofono_sms *sms,
const struct ofono_phone_number *sca,
ofono_sms_sca_set_cb_t cb, void *user_data)
{
struct sms_data *data = ofono_sms_get_data(sms);
struct cb_data *cbd = cb_data_new(cb, user_data);
struct sms_data *sd = ofono_sms_get_data(sms);
struct cb_data *cbd = cb_data_new(cb, user_data, sd);
struct parcel rilp;
int ret = -1;
char number[OFONO_MAX_PHONE_NUMBER_LENGTH + 4];
if (sca->type == 129)
snprintf(number, sizeof(number), "\"%s\"", sca->number);
else
snprintf(number, sizeof(number), "\"+%s\"", sca->number);
DBG("Setting sca: %s", number);
snprintf(number, sizeof(number), "\"%s\"", phone_number_to_string(sca));
parcel_init(&rilp);
parcel_w_string(&rilp, number);
/* Send request to RIL */
ret = g_ril_send(data->ril, RIL_REQUEST_SET_SMSC_ADDRESS, rilp.data,
rilp.size, ril_csca_set_cb, cbd, g_free);
parcel_free(&rilp);
g_ril_append_print_buf(sd->ril, "(%s)", number);
/* In case of error free cbd and return the cb with failure */
if (ret <= 0) {
ofono_error("unable to set csca");
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, user_data);
}
if (g_ril_send(sd->ril, RIL_REQUEST_SET_SMSC_ADDRESS, &rilp,
ril_csca_set_cb, cbd, g_free) > 0)
return;
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, user_data);
}
static void ril_csca_query_cb(struct ril_msg *message, gpointer user_data)
{
struct cb_data *cbd = user_data;
ofono_sms_sca_query_cb_t cb = cbd->cb;
struct ofono_error error;
struct sms_data *sd = cbd->user;
struct ofono_phone_number sca;
struct parcel rilp;
gchar *number, *temp_buf;
char *temp_buf;
char *number;
if (message->error == RIL_E_SUCCESS) {
decode_ril_error(&error, "OK");
} else {
ofono_error("csca query failed");
decode_ril_error(&error, "FAIL");
cb(&error, NULL, cbd->data);
return;
}
if (message->error != RIL_E_SUCCESS)
goto error;
g_ril_init_parcel(message, &rilp);
ril_util_init_parcel(message, &rilp);
temp_buf = parcel_r_string(&rilp);
if (temp_buf == NULL)
goto error;
if (temp_buf != NULL) {
/* RIL gives address in quotes */
number = strtok(temp_buf, "\"");
if (number[0] == '+') {
number = number + 1;
sca.type = 145;
} else {
sca.type = 129;
}
strncpy(sca.number, number, OFONO_MAX_PHONE_NUMBER_LENGTH);
sca.number[OFONO_MAX_PHONE_NUMBER_LENGTH] = '\0';
DBG("csca_query_cb: %s, %d", sca.number, sca.type);
g_free(temp_buf); /*g_utf16_to_utf8 used by parcel_r_string*/
cb(&error, &sca, cbd->data);
} else {
ofono_error("return value invalid");
CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
/* RIL gives address in quotes */
number = strtok(temp_buf, "\"");
if (number == NULL || *number == '\0') {
g_free(temp_buf);
goto error;
}
if (number[0] == '+') {
number = number + 1;
sca.type = OFONO_NUMBER_TYPE_INTERNATIONAL;
} else
sca.type = OFONO_NUMBER_TYPE_UNKNOWN;
strncpy(sca.number, number, OFONO_MAX_PHONE_NUMBER_LENGTH);
sca.number[OFONO_MAX_PHONE_NUMBER_LENGTH] = '\0';
g_ril_append_print_buf(sd->ril, "{type=%d,number=%s}",
sca.type, sca.number);
g_ril_print_response(sd->ril, message);
g_free(temp_buf);
CALLBACK_WITH_SUCCESS(cb, &sca, cbd->data);
return;
error:
CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
}
static void ril_csca_query(struct ofono_sms *sms, ofono_sms_sca_query_cb_t cb,
void *user_data)
{
struct sms_data *data = ofono_sms_get_data(sms);
struct cb_data *cbd = cb_data_new(cb, user_data);
int ret = -1;
struct sms_data *sd = ofono_sms_get_data(sms);
struct cb_data *cbd = cb_data_new(cb, user_data, sd);
DBG("Sending csca_query");
ret = g_ril_send(data->ril, RIL_REQUEST_GET_SMSC_ADDRESS, NULL, 0,
ril_csca_query_cb, cbd, g_free);
if (ret <= 0) {
ofono_error("unable to send sca query");
if (g_ril_send(sd->ril, RIL_REQUEST_GET_SMSC_ADDRESS, NULL,
ril_csca_query_cb, cbd, g_free) == 0) {
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, NULL, user_data);
}
}
static void submit_sms_cb(struct ril_msg *message, gpointer user_data)
static void ril_submit_sms_cb(struct ril_msg *message, gpointer user_data)
{
struct cb_data *cbd = user_data;
struct ofono_error error;
ofono_sms_submit_cb_t cb = cbd->cb;
struct sms_data *sd = cbd->user;
struct parcel rilp;
int mr;
char *ack_pdu;
int error;
if (message->error == RIL_E_SUCCESS) {
ofono_info("sms sending successful");
decode_ril_error(&error, "OK");
} else if (message->error == RIL_E_GENERIC_FAILURE) {
ofono_info("not allowed by MO SMS control, do not retry");
error.type = OFONO_ERROR_TYPE_CMS;
error.error = 500;
} else {
ofono_error("sms sending failed, retry");
decode_ril_error(&error, "FAIL");
if (message->error != RIL_E_SUCCESS) {
CALLBACK_WITH_FAILURE(cb, 0, cbd->data);
return;
}
mr = ril_util_parse_sms_response(sd->ril, message);
g_ril_init_parcel(message, &rilp);
cb(&error, mr, cbd->data);
/*
* TP-Message-Reference for GSM/
* BearerData MessageId for CDMA
*/
mr = parcel_r_int32(&rilp);
ack_pdu = parcel_r_string(&rilp);
error = parcel_r_int32(&rilp);
g_ril_append_print_buf(sd->ril, "{%d,%s,%d}", mr, ack_pdu, error);
g_ril_print_response(sd->ril, message);
g_free(ack_pdu);
CALLBACK_WITH_SUCCESS(cb, mr, cbd->data);
}
static void imc_sms_bearer_query_cb(struct ril_msg *message,
gpointer user_data)
{
struct cb_data *cbd = user_data;
ofono_sms_bearer_query_cb_t cb = cbd->cb;
struct parcel rilp;
int bearer;
char **strv = NULL;
char *endptr;
DBG("");
if (message->error != RIL_E_SUCCESS) {
ofono_error("Reply failure: %s",
ril_error_to_string(message->error));
goto error;
}
/*
* OEM_HOOK_STRINGS response is a char**, representing
* an array of null-terminated UTF-8 strings.
*/
g_ril_init_parcel(message, &rilp);
strv = parcel_r_strv(&rilp);
if (strv == NULL) {
ofono_error("%s: malformed parcel", __func__);
goto error;
}
bearer = strtoul(strv[0], &endptr, 10); /* convert to int */
if (endptr == strv[0] || *endptr != '\0') {
ofono_error("Convert to Int failed");
goto error;
}
g_strfreev(strv);
CALLBACK_WITH_SUCCESS(cb, bearer, cbd->data);
return;
error:
if(strv != NULL)
g_strfreev(strv);
CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
}
static void ril_sms_bearer_query(struct ofono_sms *sms,
ofono_sms_bearer_query_cb_t cb, void *user_data)
{
struct sms_data *sd = ofono_sms_get_data(sms);
struct cb_data *cbd = cb_data_new(cb, user_data, sd);
struct parcel rilp;
int cmd_id;
char buf[4];
DBG("");
if (sd->vendor == OFONO_RIL_VENDOR_IMC_SOFIA3GR) {
/*
* OEM_HOOK_STRINGS request is a char **, representing an array
* of null-terminated UTF-8 strings. Here just cmd_id as string.
*/
parcel_init(&rilp);
parcel_w_int32(&rilp, 1); /* No. of strings */
/* RIL_OEM_HOOK_STRING_GET_SMS_TRANSPORT_MODE = 0x000000A9 */
cmd_id = 0x000000A9;
sprintf(buf, "%d", cmd_id);
parcel_w_string(&rilp, buf);
if (g_ril_send(sd->ril, RIL_REQUEST_OEM_HOOK_STRINGS, &rilp,
imc_sms_bearer_query_cb,
cbd, g_free) > 0)
return;
}
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, -1, user_data);
}
static void imc_set_domain_pref_cb(struct ril_msg *message, void *user_data)
{
struct cb_data *cbd = user_data;
ofono_sms_bearer_set_cb_t cb = cbd->cb;
struct sms_data *sd = cbd->user;
DBG("");
if (message->error != RIL_E_SUCCESS) {
ofono_error("%s RILD reply failure: %s",
g_ril_request_id_to_string(sd->ril, message->req),
ril_error_to_string(message->error));
CALLBACK_WITH_FAILURE(cb, cbd->data);
return;
}
CALLBACK_WITH_SUCCESS(cb, cbd->data);
}
static void ril_sms_bearer_set(struct ofono_sms *sms, int bearer,
ofono_sms_bearer_set_cb_t cb, void *user_data)
{
struct sms_data *sd = ofono_sms_get_data(sms);
struct cb_data *cbd = cb_data_new(cb, user_data, sd);
struct parcel rilp;
int cmd_id;
char buf1[4];
char buf2[4];
DBG("Bearer: %d", bearer);
if (sd->vendor == OFONO_RIL_VENDOR_IMC_SOFIA3GR) {
/*
* OEM_HOOK_STRINGS request is a char **, representing an array
* of null-terminated UTF-8 strings. Here cmd_id and domain
* to be sent as strings.
*/
parcel_init(&rilp);
parcel_w_int32(&rilp, 2); /* no. of strings */
/* RIL_OEM_HOOK_STRING_SET_SMS_TRANSPORT_MODE = 0x000000AA */
cmd_id = 0x000000AA;
sprintf(buf1, "%d", cmd_id);
parcel_w_string(&rilp, buf1);
sprintf(buf2, "%d", bearer);
parcel_w_string(&rilp, buf2);
if (g_ril_send(sd->ril, RIL_REQUEST_OEM_HOOK_STRINGS, &rilp,
imc_set_domain_pref_cb,
cbd, g_free) > 0)
return;
}
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, user_data);
}
static void ril_cmgs(struct ofono_sms *sms, const unsigned char *pdu,
@@ -197,267 +330,132 @@ static void ril_cmgs(struct ofono_sms *sms, const unsigned char *pdu,
ofono_sms_submit_cb_t cb, void *user_data)
{
struct sms_data *sd = ofono_sms_get_data(sms);
struct cb_data *cbd = cb_data_new(cb, user_data);
struct cb_data *cbd = cb_data_new(cb, user_data, sd);
struct parcel rilp;
char *tpdu;
int request = RIL_REQUEST_SEND_SMS;
int ret, smsc_len;
cbd->user = sd;
int smsc_len;
char hexbuf[tpdu_len * 2 + 1];
DBG("pdu_len: %d, tpdu_len: %d mms: %d", pdu_len, tpdu_len, mms);
/* TODO: if (mms) { ... } */
parcel_init(&rilp);
parcel_w_int32(&rilp, 2); /* Number of strings */
parcel_w_int32(&rilp, 2); /* Number of strings */
/* SMSC address:
/*
* SMSC address:
*
* smsc_len == 1, then zero-length SMSC was spec'd
* RILD expects a NULL string in this case instead
* of a zero-length string.
*/
smsc_len = pdu_len - tpdu_len;
if (smsc_len > 1) {
/* TODO: encode SMSC & write to parcel */
DBG("SMSC address specified (smsc_len %d); NOT-IMPLEMENTED", smsc_len);
}
/* TODO: encode SMSC & write to parcel */
if (smsc_len > 1)
ofono_error("SMSC address specified (smsc_len %d); "
"NOT-IMPLEMENTED", smsc_len);
parcel_w_string(&rilp, NULL); /* SMSC address; NULL == default */
/* TPDU:
/*
* TPDU:
*
* 'pdu' is a raw hexadecimal string
* encode_hex() turns it into an ASCII/hex UTF8 buffer
* parcel_w_string() encodes utf8 -> utf16
*/
tpdu = encode_hex(pdu + smsc_len, tpdu_len, 0);
parcel_w_string(&rilp, tpdu);
encode_hex_own_buf(pdu + smsc_len, tpdu_len, 0, hexbuf);
parcel_w_string(&rilp, hexbuf);
ret = g_ril_send(sd->ril,
request,
rilp.data,
rilp.size,
submit_sms_cb, cbd, g_free);
g_ril_append_print_buf(sd->ril, "(%s)", hexbuf);
g_ril_append_print_buf(sd->ril, "(%s)", tpdu);
g_free(tpdu);
tpdu = NULL;
g_ril_print_request(sd->ril, ret, request);
if (g_ril_send(sd->ril, RIL_REQUEST_SEND_SMS, &rilp,
ril_submit_sms_cb, cbd, g_free) > 0)
return;
parcel_free(&rilp);
if (ret <= 0) {
ofono_error("unable to send sms");
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, -1, user_data);
}
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, -1, user_data);
}
static void ril_ack_delivery_cb(struct ril_msg *message, gpointer user_data)
{
if (message->error != RIL_E_SUCCESS)
ofono_error(
"SMS acknowledgement failed: Further SMS reception is not guaranteed");
ofono_error("SMS acknowledgement failed: "
"Further SMS reception is not guaranteed");
}
static void ril_ack_delivery(struct ofono_sms *sms, int error)
static void ril_ack_delivery(struct ofono_sms *sms)
{
struct sms_data *sd = ofono_sms_get_data(sms);
struct parcel rilp;
int ret;
int request = RIL_REQUEST_SMS_ACKNOWLEDGE;
int code = 0;
if (!error)
code = 0xFF;
parcel_init(&rilp);
parcel_w_int32(&rilp, 2); /* Number of int32 values in array */
parcel_w_int32(&rilp, error); /* Successful (1)/Failed (0) receipt */
parcel_w_int32(&rilp, code); /* error code */
/* ACK the incoming NEW_SMS */
ret = g_ril_send(sd->ril, request,
rilp.data,
rilp.size,
ril_ack_delivery_cb, NULL, NULL);
parcel_w_int32(&rilp, 1); /* Successful receipt */
parcel_w_int32(&rilp, 0); /* error code */
g_ril_append_print_buf(sd->ril, "(1,0)");
g_ril_print_request(sd->ril, ret, request);
parcel_free(&rilp);
/* TODO: should ACK be sent for either of the error cases? */
/* ACK the incoming NEW_SMS */
g_ril_send(sd->ril, RIL_REQUEST_SMS_ACKNOWLEDGE, &rilp,
ril_ack_delivery_cb, NULL, NULL);
}
static void ril_sms_notify(struct ril_msg *message, gpointer user_data)
{
struct ofono_sms *sms = user_data;
struct sms_data *sd = ofono_sms_get_data(sms);
struct parcel rilp;
char *ril_pdu;
int ril_pdu_len;
unsigned int smsc_len;
long ril_buf_len;
guchar *ril_data;
struct parcel rilp;
char *ril_pdu;
size_t ril_pdu_len;
unsigned char pdu[176];
ril_pdu = NULL;
ril_data = NULL;
DBG("req: %d; data_len: %d", message->req, (int) message->buf_len);
DBG("req: %d; data_len: %d", message->req, message->buf_len);
switch (message->req) {
case RIL_UNSOL_RESPONSE_NEW_SMS:
case RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT:
break;
default:
goto error;
}
ril_util_init_parcel(message, &rilp);
g_ril_init_parcel(message, &rilp);
ril_pdu = parcel_r_string(&rilp);
if (ril_pdu == NULL)
goto error;
return;
g_ril_append_print_buf(sd->ril, "{%s}", ril_pdu);
g_ril_print_unsol(sd->ril, message);
ril_pdu_len = strlen(ril_pdu);
DBG("ril_pdu_len is %d", ril_pdu_len);
ril_data = decode_hex(ril_pdu, ril_pdu_len, &ril_buf_len, -1);
if (ril_data == NULL)
goto error;
if (ril_pdu_len > sizeof(pdu) * 2)
goto fail;
/* The first octect in the pdu contains the SMSC address length
* which is the X following octects it reads. We add 1 octet to
* the read length to take into account this read octet in order
* to calculate the proper tpdu length.
*/
smsc_len = ril_data[0] + 1;
ofono_info("sms received, smsc_len is %d", smsc_len);
g_ril_append_print_buf(sd->ril, "(%s)", ril_pdu);
g_free(ril_pdu);
ril_pdu = NULL;
g_ril_print_unsol(sd->ril, message);
if (message->req == RIL_UNSOL_RESPONSE_NEW_SMS) {
/* Last parameter is 'tpdu_len' ( substract SMSC length ) */
ofono_sms_deliver_notify(sms, ril_data,
ril_buf_len,
ril_buf_len - smsc_len);
} else if (message->req == RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT) {
ofono_sms_status_notify(sms, ril_data, ril_buf_len,
ril_buf_len - smsc_len);
}
g_free(ril_data);
ril_data = NULL;
ril_ack_delivery(sms, TRUE);
return;
error:
g_free(ril_pdu);
ril_pdu = NULL;
g_free(ril_data);
ril_data = NULL;
ril_ack_delivery(sms, FALSE);
ofono_error("Unable to parse NEW_SMS notification");
}
static void ril_new_sms_on_sim_cb(struct ril_msg *message, gpointer user_data)
{
DBG("");
if (message->error == RIL_E_SUCCESS)
ofono_info("sms deleted from sim");
else
ofono_error("deleting sms from sim failed");
}
static void ril_request_delete_sms_om_sim(struct ofono_sms *sms,int record)
{
struct sms_data *data = ofono_sms_get_data(sms);
struct parcel rilp;
int request = RIL_REQUEST_DELETE_SMS_ON_SIM;
int ret;
DBG("Deleting record: %d", record);
parcel_init(&rilp);
parcel_w_int32(&rilp, 1); /* Number of int32 values in array */
parcel_w_int32(&rilp, record);
ret = g_ril_send(data->ril, request, rilp.data,
rilp.size, ril_new_sms_on_sim_cb, NULL, NULL);
parcel_free(&rilp);
if (ret <= 0)
ofono_error("cannot delete sms from sim");
}
static void ril_read_sms_on_sim_cb(const struct ofono_error *error,
const unsigned char *sdata,
int length, void *data)
{
struct cb_data *cbd = data;
struct ofono_sms *sms = cbd->user;
int record;
unsigned int smsc_len;
if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
ofono_error("cannot read sms from sim");
goto exit;
}
if (decode_hex_own_buf(ril_pdu, ril_pdu_len,
&ril_buf_len, -1, pdu) == NULL)
goto fail;
/*
* It seems when reading EFsms RIL returns the whole record including
* the first status byte therefore we ignore that as we are only
* interested of the following pdu
*/
/* The first octect in the pdu contains the SMSC address length
* The first octect in the pdu contains the SMSC address length
* which is the X following octects it reads. We add 1 octet to
* the read length to take into account this read octet in order
* to calculate the proper tpdu length.
*/
smsc_len = sdata[1] + 1;
smsc_len = pdu[0] + 1;
DBG("smsc_len is %d", smsc_len);
ofono_sms_deliver_notify(sms, sdata + 1, length - 1,
length - smsc_len - 1);
if (message->req == RIL_UNSOL_RESPONSE_NEW_SMS)
/* Last parameter is 'tpdu_len' ( substract SMSC length ) */
ofono_sms_deliver_notify(sms, pdu, ril_buf_len,
ril_buf_len - smsc_len);
else if (message->req == RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT)
ofono_sms_status_notify(sms, pdu, ril_buf_len,
ril_buf_len - smsc_len);
record = (int)cbd->data;
ril_request_delete_sms_om_sim(sms,record);
/* ACK the incoming NEW_SMS */
ril_ack_delivery(sms);
exit:
g_free(cbd);
}
static void ril_new_sms_on_sim(struct ril_msg *message, gpointer user_data)
{
struct ofono_sms *sms = user_data;
struct parcel rilp;
int record;
ofono_info("new sms on sim");
ril_util_init_parcel(message, &rilp);
/* data length of the response */
record = parcel_r_int32(&rilp);
if (record > 0) {
record = parcel_r_int32(&rilp);
struct cb_data *cbd = cb_data_new2(sms, NULL, (void*)record);
DBG(":%d", record);
get_sim_driver()->read_file_linear(get_sim(), SIM_EFSMS_FILEID,
record, EFSMS_LENGTH, path,
sizeof(path),
ril_read_sms_on_sim_cb, cbd);
}
fail:
g_free(ril_pdu);
}
static gboolean ril_delayed_register(gpointer user_data)
@@ -466,19 +464,13 @@ static gboolean ril_delayed_register(gpointer user_data)
struct sms_data *data = ofono_sms_get_data(sms);
DBG("");
data->timer_id = 0;
ofono_sms_register(sms);
g_ril_register(data->ril, RIL_UNSOL_RESPONSE_NEW_SMS,
ril_sms_notify, sms);
ril_sms_notify, sms);
g_ril_register(data->ril, RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT,
ril_sms_notify, sms);
g_ril_register(data->ril, RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM,
ril_new_sms_on_sim, sms);
/* This makes the timeout a single-shot */
return FALSE;
}
@@ -494,17 +486,7 @@ static int ril_sms_probe(struct ofono_sms *sms, unsigned int vendor,
ofono_sms_set_data(sms, data);
/*
* TODO: analyze if capability check is needed
* and/or timer should be adjusted.
*
* ofono_sms_register() needs to be called after
* the driver has been set in ofono_sms_create(), which
* calls this function. Most other drivers make some
* kind of capabilities query to the modem, and then
* call register in the callback; we use a timer instead.
*/
data->timer_id = g_timeout_add_seconds(2, ril_delayed_register, sms);
g_idle_add(ril_delayed_register, sms);
return 0;
}
@@ -515,9 +497,6 @@ static void ril_sms_remove(struct ofono_sms *sms)
DBG("");
if (data->timer_id > 0)
g_source_remove(data->timer_id);
g_ril_unref(data->ril);
g_free(data);
@@ -525,25 +504,22 @@ static void ril_sms_remove(struct ofono_sms *sms)
}
static struct ofono_sms_driver driver = {
.name = "rilmodem",
.name = RILMODEM,
.probe = ril_sms_probe,
.remove = ril_sms_remove,
.sca_query = ril_csca_query,
.sca_set = ril_csca_set,
.remove = ril_sms_remove,
.submit = ril_cmgs,
.bearer_query = NULL, /* FIXME: needs investigation. */
.bearer_set = NULL,
.bearer_query = ril_sms_bearer_query,
.bearer_set = ril_sms_bearer_set
};
void ril_sms_init(void)
{
DBG("");
if (ofono_sms_driver_register(&driver))
DBG("ofono_sms_driver_register failed!");
ofono_sms_driver_register(&driver);
}
void ril_sms_exit(void)
{
DBG("");
ofono_sms_driver_unregister(&driver);
}

View File

@@ -2,8 +2,7 @@
*
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2014 Jolla Ltd
* Copyright (C) 2008-2016 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -26,178 +25,136 @@
#define _GNU_SOURCE
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <glib.h>
#include <ofono/log.h>
#include <ofono/modem.h>
#include <ofono/stk.h>
#include "gril.h"
#include "util.h"
#include <gril.h>
#include <parcel.h>
#include "rilmodem.h"
#include "ril_constants.h"
#include "vendor.h"
struct stk_data {
GRil *ril;
unsigned int vendor;
};
gboolean subscribed;
static void ril_envelope_cb(struct ril_msg *message, gpointer user_data)
{
struct cb_data *cbd = user_data;
ofono_stk_envelope_cb_t cb = cbd->cb;
struct ofono_error error;
DBG("");
if (message->error == RIL_E_SUCCESS) {
decode_ril_error(&error, "OK");
} else {
DBG("Envelope reply failure: %s",
ril_error_to_string(message->error));
decode_ril_error(&error, "FAIL");
}
cb(&error, NULL, 0, cbd->data);
}
static void ril_stk_envelope(struct ofono_stk *stk, int length,
const unsigned char *command,
ofono_stk_envelope_cb_t cb, void *data)
{
struct stk_data *sd = ofono_stk_get_data(stk);
struct cb_data *cbd = cb_data_new(cb, data);
struct parcel rilp;
char *hex_envelope = NULL;
int request = RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND;
guint ret;
DBG("");
hex_envelope = encode_hex(command, length, 0);
DBG("rilmodem envelope: %s", hex_envelope);
parcel_init(&rilp);
parcel_w_string(&rilp, hex_envelope);
g_free(hex_envelope);
hex_envelope = NULL;
ret = g_ril_send(sd->ril, request,
rilp.data, rilp.size, ril_envelope_cb,
cbd, g_free);
parcel_free(&rilp);
if (ret <= 0) {
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, NULL, -1, data);
}
}
static void ril_tr_cb(struct ril_msg *message, gpointer user_data)
static void ril_stk_terminal_response_cb(struct ril_msg *message,
gpointer user_data)
{
struct cb_data *cbd = user_data;
ofono_stk_generic_cb_t cb = cbd->cb;
struct ofono_error error;
struct stk_data *sd = cbd->user;
DBG("");
g_ril_print_response(sd->ril, message);
if (message->error == RIL_E_SUCCESS) {
decode_ril_error(&error, "OK");
CALLBACK_WITH_SUCCESS(cb, cbd->data);
} else {
DBG("Error in sending terminal response");
ofono_error("Error in sending terminal response");
decode_ril_error(&error, "FAIL");
ofono_error("%s RILD reply failure: %s",
g_ril_request_id_to_string(sd->ril, message->req),
ril_error_to_string(message->error));
CALLBACK_WITH_FAILURE(cb, cbd->data);
}
cb(&error, cbd->data);
}
static void ril_stk_terminal_response(struct ofono_stk *stk, int length,
const unsigned char *resp,
ofono_stk_generic_cb_t cb, void *data)
static void ril_stk_terminal_response(struct ofono_stk *stk, int len,
const unsigned char *data,
ofono_stk_generic_cb_t cb, void *user_data)
{
struct stk_data *sd = ofono_stk_get_data(stk);
struct cb_data *cbd = cb_data_new(cb, data);
struct cb_data *cbd = cb_data_new(cb, user_data, sd);
struct parcel rilp;
char *hex_tr = NULL;
int request = RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE;
guint ret;
char *buf = alloca(len * 2 + 1);
int size = 0;
DBG("");
hex_tr = encode_hex(resp, length, 0);
DBG("rilmodem terminal response: %s", hex_tr);
for (; len; len--)
size += sprintf(buf + size, "%02hhX", *data++);
parcel_init(&rilp);
parcel_w_string(&rilp, hex_tr);
g_free(hex_tr);
hex_tr = NULL;
parcel_w_string(&rilp, buf);
ret = g_ril_send(sd->ril, request,
rilp.data, rilp.size, ril_tr_cb,
cbd, g_free);
if (g_ril_send(sd->ril, RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE, &rilp,
ril_stk_terminal_response_cb, cbd, g_free) > 0)
return;
parcel_free(&rilp);
if (ret <= 0) {
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, data);
}
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, user_data);
}
static void ril_stk_user_confirmation(struct ofono_stk *stk,
ofono_bool_t confirm)
static void ril_stk_envelope_cb(struct ril_msg *message, gpointer user_data)
{
struct cb_data *cbd = user_data;
ofono_stk_envelope_cb_t cb = cbd->cb;
struct stk_data *sd = cbd->user;
struct parcel rilp;
unsigned char *response = NULL;
long len = 0;
char *pdu;
g_ril_print_response(sd->ril, message);
if (message->error == RIL_E_SUCCESS) {
g_ril_init_parcel(message, &rilp);
pdu = parcel_r_string(&rilp);
if (pdu)
response = decode_hex(pdu, -1, &len, -1);
CALLBACK_WITH_SUCCESS(cb, response, len, cbd->data);
g_free(response);
} else {
ofono_error("%s RILD reply failure: %s",
g_ril_request_id_to_string(sd->ril, message->req),
ril_error_to_string(message->error));
CALLBACK_WITH_FAILURE(cb, NULL, 0, cbd->data);
}
}
static void ril_stk_envelope(struct ofono_stk *stk, int len,
const unsigned char *cmd,
ofono_stk_envelope_cb_t cb, void *user_data)
{
struct stk_data *sd = ofono_stk_get_data(stk);
struct cb_data *cbd = cb_data_new(cb, user_data, sd);
struct parcel rilp;
int request = RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM;
int ret;
char *buf = alloca(len * 2 + 1);
int size = 0;
DBG("");
for (; len; len--)
size += sprintf(buf + size, "%02hhX", *cmd++);
/* Only pcmd needing user confirmation is call set up
* RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM
*/
parcel_init(&rilp);
parcel_w_int32(&rilp, 1); /* size of array */
parcel_w_int32(&rilp, confirm); /* yes/no */
parcel_w_string(&rilp, buf);
/* fire and forget i.e. not waiting for the callback*/
ret = g_ril_send(sd->ril, request, rilp.data,
rilp.size, NULL, NULL, NULL);
if (g_ril_send(sd->ril, RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND, &rilp,
ril_stk_envelope_cb, cbd, g_free) > 0)
return;
g_ril_print_request_no_args(sd->ril, ret, request);
parcel_free(&rilp);
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, NULL, 0, user_data);
}
static void ril_stk_pcmd_notify(struct ril_msg *message, gpointer user_data)
static void ril_stk_proactive_cmd_notify(struct ril_msg *message,
gpointer user_data)
{
struct ofono_stk *stk = user_data;
struct parcel rilp;
char *pcmd = NULL;
guchar *pdu = NULL;
long len;
long pdulen;
unsigned char *pdu;
DBG("");
ril_util_init_parcel(message, &rilp);
pcmd = parcel_r_string(&rilp);
DBG("pcmd: %s", pcmd);
g_ril_init_parcel(message, &rilp);
pdu = decode_hex(parcel_r_string(&rilp), -1, &pdulen, -1);
pdu = decode_hex((const char *) pcmd,
strlen(pcmd),
&len, -1);
g_free(pcmd);
ofono_stk_proactive_command_notify(stk, len, (const guchar *)pdu);
ofono_stk_proactive_command_notify(stk, pdulen, pdu);
g_free(pdu);
}
@@ -205,130 +162,69 @@ static void ril_stk_event_notify(struct ril_msg *message, gpointer user_data)
{
struct ofono_stk *stk = user_data;
struct parcel rilp;
char *pcmd = NULL;
guchar *pdu = NULL;
long len;
long pdulen;
unsigned char *pdu;
DBG("");
/* Proactive command has been handled by the modem. */
ril_util_init_parcel(message, &rilp);
pcmd = parcel_r_string(&rilp);
DBG("pcmd: %s", pcmd);
pdu = decode_hex((const char *) pcmd,
strlen(pcmd),
&len, -1);
g_free(pcmd);
pcmd = NULL;
ofono_stk_proactive_command_handled_notify(stk, len,
(const guchar *)pdu);
g_ril_init_parcel(message, &rilp);
pdu = decode_hex(parcel_r_string(&rilp), -1, &pdulen, -1);
ofono_stk_proactive_command_handled_notify(stk, pdulen, pdu);
g_free(pdu);
}
static void ril_stk_session_end_notify(struct ril_msg *message,
gpointer user_data)
gpointer user_data)
{
struct ofono_stk *stk = user_data;
DBG("");
ofono_stk_proactive_session_end_notify(stk);
}
static void ril_stk_agent_ready(struct ofono_stk *stk)
static int ril_stk_probe(struct ofono_stk *stk, unsigned int vendor,
void *user)
{
struct stk_data *sd = ofono_stk_get_data(stk);
int request = RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING;
int ret;
GRil *ril = user;
struct stk_data *data;
DBG("");
data = g_new0(struct stk_data, 1);
data->ril = g_ril_clone(ril);
data->vendor = vendor;
if (!subscribed) {
DBG("Subscribing notifications");
g_ril_register(sd->ril, RIL_UNSOL_STK_PROACTIVE_COMMAND,
ril_stk_pcmd_notify, stk);
ofono_stk_set_data(stk, data);
g_ril_register(sd->ril, RIL_UNSOL_STK_SESSION_END,
ril_stk_session_end_notify, stk);
g_ril_register(ril, RIL_UNSOL_STK_PROACTIVE_COMMAND,
ril_stk_proactive_cmd_notify, stk);
g_ril_register(sd->ril, RIL_UNSOL_STK_EVENT_NOTIFY,
ril_stk_event_notify, stk);
subscribed = TRUE;
}
g_ril_register(ril, RIL_UNSOL_STK_SESSION_END,
ril_stk_session_end_notify, stk);
/* fire and forget i.e. not waiting for the callback*/
ret = g_ril_send(sd->ril, request, NULL, 0,
NULL, NULL, NULL);
g_ril_register(ril, RIL_UNSOL_STK_EVENT_NOTIFY,
ril_stk_event_notify, stk);
g_ril_print_request_no_args(sd->ril, ret, request);
}
void ril_stk_set_lang()
{
gchar *contents;
GError *err = NULL;
if (!g_file_get_contents(UI_LANG, &contents, NULL, &err)) {
if (err)
ofono_error("cannot open %s error: %d: message: %s",
UI_LANG, err->code, err->message);
g_error_free(err);
} else {
gchar *pch = g_strrstr(contents, CFG_LANG);
/* Set System UI lang to env LANG */
if (pch) {
setenv("LANG", pch + strlen(CFG_LANG), 1);
DBG("LANG %s", getenv("LANG"));
}
g_free(contents);
}
}
static int ril_stk_probe(struct ofono_stk *stk, unsigned int vendor, void *data)
{
GRil *ril = data;
struct stk_data *sd;
DBG("");
sd = g_try_new0(struct stk_data, 1);
if (sd == NULL)
return -ENOMEM;
sd->ril = g_ril_clone(ril);
ofono_stk_set_data(stk, sd);
/* Register interface in this phase for stk agent */
ofono_stk_register(stk);
subscribed = FALSE;
/* UI language for local info */
ril_stk_set_lang();
return 0;
}
static void ril_stk_remove(struct ofono_stk *stk)
{
struct stk_data *sd = ofono_stk_get_data(stk);
DBG("");
struct stk_data *data = ofono_stk_get_data(stk);
ofono_stk_set_data(stk, NULL);
g_ril_unref(sd->ril);
g_free(sd);
g_ril_unref(data->ril);
g_free(data);
}
static struct ofono_stk_driver driver = {
.name = "rilmodem",
.probe = ril_stk_probe,
.remove = ril_stk_remove,
.envelope = ril_stk_envelope,
.terminal_response = ril_stk_terminal_response,
.user_confirmation = ril_stk_user_confirmation,
.ready = ril_stk_agent_ready
.name = RILMODEM,
.probe = ril_stk_probe,
.remove = ril_stk_remove,
.envelope = ril_stk_envelope,
.terminal_response = ril_stk_terminal_response,
};
void ril_stk_init(void)

View File

@@ -4,6 +4,7 @@
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2013 Jolla Ltd
* Copyright (C) 2013 Canonical Ltd
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -38,25 +39,39 @@
#include <util.h>
#include "gril.h"
#include "grilutil.h"
#include "rilmodem.h"
#include "ril_constants.h"
struct ussd_data {
GRil *ril;
guint timer_id;
};
static gboolean request_success(gpointer data)
{
struct cb_data *cbd = data;
ofono_ussd_cb_t cb = cbd->cb;
CALLBACK_WITH_SUCCESS(cb, cbd->data);
g_free(cbd);
return FALSE;
}
static void ril_ussd_cb(struct ril_msg *message, gpointer user_data)
{
struct ofono_ussd *ussd = user_data;
struct ussd_data *ud = ofono_ussd_get_data(ussd);
/*
* Calling oFono callback function at this point may lead to
* segmentation fault. There is theoretical possibility that no
* RIL_UNSOL_ON_USSD is received and therefore the original request
* is not freed in oFono.
* We fake an ON_USSD event if there was an error sending the request,
* as core will be waiting for one to respond to the Initiate() call.
* Note that we already made the callback (see ril_ussd_request()).
*/
if (message->error == RIL_E_SUCCESS)
g_ril_print_response_no_args(ud->ril, message);
else
ofono_ussd_notify(ussd, OFONO_USSD_STATUS_NOT_SUPPORTED,
0, NULL, 0);
}
static void ril_ussd_request(struct ofono_ussd *ussd, int dcs,
@@ -64,133 +79,129 @@ static void ril_ussd_request(struct ofono_ussd *ussd, int dcs,
ofono_ussd_cb_t cb, void *data)
{
struct ussd_data *ud = ofono_ussd_get_data(ussd);
struct cb_data *cbd = cb_data_new(cb, data);
enum sms_charset charset;
int ret = -1;
struct cb_data *cbd = cb_data_new(cb, data, ussd);
char *text;
struct parcel rilp;
int ret;
ofono_info("send ussd, len:%d", len);
text = ussd_decode(dcs, len, pdu);
if (!text)
goto error;
if (cbs_dcs_decode(dcs, NULL, NULL, &charset,
NULL, NULL, NULL)) {
if (charset == SMS_CHARSET_7BIT) {
unsigned char unpacked_buf[182] = "";
long written;
int length;
parcel_init(&rilp);
parcel_w_string(&rilp, text);
unpack_7bit_own_buf(pdu, len, 0, TRUE,
sizeof(unpacked_buf), &written, 0,
unpacked_buf);
g_ril_append_print_buf(ud->ril, "(%s)", text);
if (written >= 1) {
/*
* When USSD was packed, additional CR
might have been added (according to
23.038 6.1.2.3.1). So if the last
character is CR, it should be removed
here. And in addition written doesn't
contain correct length...
Over 2 characters long USSD string must
end with # (checked in
valid_ussd_string() ), so it should be
safe to remove extra CR.
*/
length = strlen((char *)unpacked_buf);
if (length > 2 &&
unpacked_buf[length-1] == '\r')
unpacked_buf[length-1] = 0;
struct parcel rilp;
parcel_init(&rilp);
parcel_w_string(&rilp, (char *)unpacked_buf);
ret = g_ril_send(ud->ril,
RIL_REQUEST_SEND_USSD,
rilp.data, rilp.size,
ril_ussd_cb, cbd, g_free);
parcel_free(&rilp);
}
}
}
ret = g_ril_send(ud->ril, RIL_REQUEST_SEND_USSD,
&rilp, ril_ussd_cb, ussd, NULL);
g_free(text);
/*
* It cannot be guaranteed that response is received before notify or
* user-activity request so we must complete the request now and later
* ignore the actual response.
* TODO: Is g_idle_add necessary?
* We do not wait for the SEND_USSD reply to do the callback, as some
* networks send it after sending one or more ON_USSD events. From the
* ofono core perspective, Initiate() does not return until one ON_USSD
* event is received: making here a successful callback just makes the
* core wait for that event.
*/
if (ret <= 0) {
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, data);
} else {
CALLBACK_WITH_SUCCESS(cb, cbd->data);
if (ret > 0) {
g_idle_add(request_success, cbd);
return;
}
error:
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, data);
}
static void ril_ussd_cancel_cb(struct ril_msg *message, gpointer user_data)
{
struct cb_data *cbd = user_data;
struct ofono_ussd *ussd = cbd->user;
struct ussd_data *ud = ofono_ussd_get_data(ussd);
ofono_ussd_cb_t cb = cbd->cb;
struct ofono_error error;
DBG("%d", message->error);
if (message->error == RIL_E_SUCCESS)
decode_ril_error(&error, "OK");
else {
ofono_error("ussd canceling failed");
decode_ril_error(&error, "FAIL");
if (message->error == RIL_E_SUCCESS) {
g_ril_print_response_no_args(ud->ril, message);
CALLBACK_WITH_SUCCESS(cb, cbd->data);
} else {
CALLBACK_WITH_FAILURE(cb, cbd->data);
}
cb(&error, cbd->data);
}
static void ril_ussd_cancel(struct ofono_ussd *ussd,
ofono_ussd_cb_t cb, void *user_data)
{
struct ussd_data *ud = ofono_ussd_get_data(ussd);
struct cb_data *cbd = cb_data_new(cb, user_data);
struct cb_data *cbd = cb_data_new(cb, user_data, ussd);
ofono_info("send ussd cancel");
cbd->user = ud;
if (g_ril_send(ud->ril, RIL_REQUEST_CANCEL_USSD, NULL, 0,
if (g_ril_send(ud->ril, RIL_REQUEST_CANCEL_USSD, NULL,
ril_ussd_cancel_cb, cbd, g_free) > 0)
return;
ofono_error("unable cancel ussd");
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, user_data);
}
static void ril_ussd_notify(struct ril_msg *message, gpointer user_data)
{
struct ofono_ussd *ussd = user_data;
struct ussd_data *ud = ofono_ussd_get_data(ussd);
struct parcel rilp;
gchar *ussd_from_network = NULL;
gchar *type = NULL;
gint ussdtype = 0;
int numstr;
char *typestr;
int type;
char *str = NULL;
gsize written;
char *ucs2;
ofono_info("ussd_received");
g_ril_init_parcel(message, &rilp);
ril_util_init_parcel(message, &rilp);
parcel_r_int32(&rilp);
type = parcel_r_string(&rilp);
ussdtype = g_ascii_xdigit_value(*type);
g_free(type);
type = NULL;
ussd_from_network = parcel_r_string(&rilp);
numstr = parcel_r_int32(&rilp);
if (numstr < 1)
return;
/* ussd_from_network not freed because core does that if dcs is 0xFF */
if (ussd_from_network) {
DBG("ussd_received, length %d", strlen(ussd_from_network));
ofono_ussd_notify(ussd, ussdtype, 0xFF,
(const unsigned char *)ussd_from_network,
strlen(ussd_from_network));
} else
ofono_ussd_notify(ussd, ussdtype, 0, NULL, 0);
typestr = parcel_r_string(&rilp);
if (typestr == NULL || *typestr == '\0')
return;
return;
type = *typestr - '0';
g_free(typestr);
if (numstr > 1)
str = parcel_r_string(&rilp);
g_ril_append_print_buf(ud->ril, "{%d,%s}", type, str);
g_ril_print_unsol(ud->ril, message);
/* To fix bug in MTK: USSD-Notify arrive with type 2 instead of 0 */
if (g_ril_vendor(ud->ril) == OFONO_RIL_VENDOR_MTK &&
str != NULL && type == 2)
type = 0;
if (str == NULL) {
ofono_ussd_notify(ussd, type, 0, NULL, 0);
return;
}
/*
* With data coding scheme 0x48, we are saying that the ussd string is a
* UCS-2 string, uncompressed, and with unspecified message class. For
* the DCS coding, see 3gpp 23.038, sect. 5.
*/
ucs2 = g_convert(str, -1, "UCS-2BE//TRANSLIT",
"UTF-8", NULL, &written, NULL);
g_free(str);
if (ucs2 == NULL) {
ofono_error("%s: Error transcoding", __func__);
return;
}
ofono_ussd_notify(ussd, type, 0x48, (unsigned char *) ucs2, written);
g_free(ucs2);
}
static gboolean ril_delayed_register(gpointer user_data)
@@ -200,13 +211,10 @@ static gboolean ril_delayed_register(gpointer user_data)
DBG("");
ud->timer_id = 0;
ofono_ussd_register(ussd);
/* Register for USSD responses */
g_ril_register(ud->ril, RIL_UNSOL_ON_USSD,
ril_ussd_notify, ussd);
g_ril_register(ud->ril, RIL_UNSOL_ON_USSD, ril_ussd_notify, ussd);
return FALSE;
}
@@ -216,10 +224,11 @@ static int ril_ussd_probe(struct ofono_ussd *ussd,
void *user)
{
GRil *ril = user;
struct ussd_data *ud = g_try_new0(struct ussd_data, 1);
struct ussd_data *ud = g_new0(struct ussd_data, 1);
ud->ril = g_ril_clone(ril);
ofono_ussd_set_data(ussd, ud);
ud->timer_id = g_timeout_add_seconds(2, ril_delayed_register, ussd);
g_idle_add(ril_delayed_register, ussd);
return 0;
}
@@ -229,19 +238,16 @@ static void ril_ussd_remove(struct ofono_ussd *ussd)
struct ussd_data *ud = ofono_ussd_get_data(ussd);
ofono_ussd_set_data(ussd, NULL);
if (ud->timer_id > 0)
g_source_remove(ud->timer_id);
g_ril_unref(ud->ril);
g_free(ud);
}
static struct ofono_ussd_driver driver = {
.name = "rilmodem",
.probe = ril_ussd_probe,
.remove = ril_ussd_remove,
.request = ril_ussd_request,
.cancel = ril_ussd_cancel
.name = RILMODEM,
.probe = ril_ussd_probe,
.remove = ril_ussd_remove,
.request = ril_ussd_request,
.cancel = ril_ussd_cancel
};
void ril_ussd_init(void)
@@ -253,4 +259,3 @@ void ril_ussd_exit(void)
{
ofono_ussd_driver_unregister(&driver);
}

View File

@@ -1,9 +1,8 @@
/*
*
* RIL chat library with GLib integration
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2012 Canonical Ltd.
* Copyright (C) 2014 Canonical Ltd. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -20,27 +19,15 @@
*
*/
#ifndef __GRIL_RESPONSE_H
#define __GRIL_RESPONSE_H
#ifndef RILMODEM_VENDOR_H
#define RILMODEM_VENDOR_H
#ifdef __cplusplus
extern "C" {
#endif
struct _GRilResponse {
GSList *lines;
char *final_or_pdu;
enum ofono_ril_vendor {
OFONO_RIL_VENDOR_AOSP = 0,
OFONO_RIL_VENDOR_MTK,
OFONO_RIL_VENDOR_INFINEON,
OFONO_RIL_VENDOR_QCOM_MSIM,
OFONO_RIL_VENDOR_IMC_SOFIA3GR
};
typedef struct _GRilResponse GRilResponse;
#define G_RIL_RESPONSE_LINE_LENGTH_MAX 2048
const char *g_ril_final_response(GRilResponse *response);
const char *g_ril_response_pdu(GRilResponse *response);
#ifdef __cplusplus
}
#endif
#endif /* __GRIL_RESPONSE_H */
#endif /* RILMODEM_VENDOR_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,66 @@
/*
*
* oFono - Open Source Telephony
*
* Copyright (C) 2014 Canonical Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
struct ril_voicecall_data {
GSList *calls;
/* Call local hangup indicator, one bit per call (1 << call_id) */
unsigned int local_release;
unsigned int clcc_source;
GRil *ril;
unsigned int vendor;
unsigned char flags;
ofono_voicecall_cb_t cb;
void *data;
gchar *tone_queue;
gboolean tone_pending;
};
int ril_voicecall_probe(struct ofono_voicecall *vc, unsigned int vendor,
void *data);
void ril_voicecall_remove(struct ofono_voicecall *vc);
void ril_dial(struct ofono_voicecall *vc, const struct ofono_phone_number *ph,
enum ofono_clir_option clir, ofono_voicecall_cb_t cb,
void *data);
void ril_answer(struct ofono_voicecall *vc,
ofono_voicecall_cb_t cb, void *data);
void ril_hangup_all(struct ofono_voicecall *vc, ofono_voicecall_cb_t cb,
void *data);
void ril_hangup_specific(struct ofono_voicecall *vc,
int id, ofono_voicecall_cb_t cb, void *data);
void ril_send_dtmf(struct ofono_voicecall *vc, const char *dtmf,
ofono_voicecall_cb_t cb, void *data);
void ril_create_multiparty(struct ofono_voicecall *vc,
ofono_voicecall_cb_t cb, void *data);
void ril_private_chat(struct ofono_voicecall *vc, int id,
ofono_voicecall_cb_t cb, void *data);
void ril_swap_without_accept(struct ofono_voicecall *vc,
ofono_voicecall_cb_t cb, void *data);
void ril_hold_all_active(struct ofono_voicecall *vc,
ofono_voicecall_cb_t cb, void *data);
void ril_release_all_held(struct ofono_voicecall *vc,
ofono_voicecall_cb_t cb, void *data);
void ril_set_udub(struct ofono_voicecall *vc,
ofono_voicecall_cb_t cb, void *data);
void ril_release_all_active(struct ofono_voicecall *vc,
ofono_voicecall_cb_t cb, void *data);
void ril_call_state_notify(struct ril_msg *message, gpointer user_data);
gboolean ril_poll_clcc(gpointer user_data);

View File

@@ -574,8 +574,7 @@ static void ste_voicecall_remove(struct ofono_voicecall *vc)
{
struct voicecall_data *vd = ofono_voicecall_get_data(vc);
g_slist_foreach(vd->calls, (GFunc) g_free, NULL);
g_slist_free(vd->calls);
g_slist_free_full(vd->calls, g_free);
ofono_voicecall_set_data(vc, NULL);

View File

@@ -0,0 +1,464 @@
/*
*
* oFono - Open Source Telephony
*
* Copyright (C) 2016 EndoCode AG. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#define _GNU_SOURCE
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <errno.h>
#include <glib.h>
#include <ofono/log.h>
#include <ofono/modem.h>
#include <ofono/gprs-context.h>
#include "gatchat.h"
#include "gatresult.h"
#include "ubloxmodem.h"
static const char *none_prefix[] = { NULL };
static const char *cgcontrdp_prefix[] = { "+CGCONTRDP:", NULL };
struct gprs_context_data {
GAtChat *chat;
unsigned int active_context;
ofono_gprs_context_cb_t cb;
void *cb_data;
};
/*
* CGCONTRDP returns addr + netmask in the same string in the form
* of "a.b.c.d.m.m.m.m" for IPv4. IPv6 is not supported so we ignore it.
*/
static int set_address_and_netmask(struct ofono_gprs_context *gc,
const char *addrnetmask)
{
char *dup = strdup(addrnetmask);
char *s = dup;
const char *addr = s;
const char *netmask = NULL;
int ret = -EINVAL;
int i;
/* Count 7 dots for ipv4, less or more means error. */
for (i = 0; i < 8; i++, s++) {
s = strchr(s, '.');
if (!s)
break;
if (i == 3) {
/* set netmask ptr and break the string */
netmask = s + 1;
s[0] = 0;
}
}
if (i == 7) {
ofono_gprs_context_set_ipv4_address(gc, addr, 1);
ofono_gprs_context_set_ipv4_netmask(gc, netmask);
ret = 0;
}
free(dup);
return ret;
}
static void set_gprs_context_interface(struct ofono_gprs_context *gc)
{
struct ofono_modem *modem;
const char *interface;
/* read interface name read at detection time */
modem = ofono_gprs_context_get_modem(gc);
interface = ofono_modem_get_string(modem, "NetworkInterface");
ofono_gprs_context_set_interface(gc, interface);
}
static void cgcontrdp_cb(gboolean ok, GAtResult *result, gpointer user_data)
{
struct ofono_gprs_context *gc = user_data;
struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
GAtResultIter iter;
const char *laddrnetmask = NULL;
const char *gw = NULL;
const char *dns[3] = { NULL, NULL, NULL };
DBG("ok %d", ok);
if (!ok) {
struct ofono_error error;
decode_at_error(&error, g_at_result_final_response(result));
gcd->cb(&error, gcd->cb_data);
return;
}
g_at_result_iter_init(&iter, result);
while (g_at_result_iter_next(&iter, "+CGCONTRDP:")) {
/* skip cid, bearer_id, apn */
g_at_result_iter_skip_next(&iter);
g_at_result_iter_skip_next(&iter);
g_at_result_iter_skip_next(&iter);
if (!g_at_result_iter_next_string(&iter, &laddrnetmask))
break;
if (!g_at_result_iter_next_string(&iter, &gw))
break;
if (!g_at_result_iter_next_string(&iter, &dns[0]))
break;
if (!g_at_result_iter_next_string(&iter, &dns[1]))
break;
}
set_gprs_context_interface(gc);
if (!laddrnetmask || set_address_and_netmask(gc, laddrnetmask) < 0) {
CALLBACK_WITH_FAILURE(gcd->cb, gcd->cb_data);
return;
}
if (gw)
ofono_gprs_context_set_ipv4_gateway(gc, gw);
if (dns[0])
ofono_gprs_context_set_ipv4_dns_servers(gc, dns);
CALLBACK_WITH_SUCCESS(gcd->cb, gcd->cb_data);
}
static int ublox_send_cgcontrdp(struct ofono_gprs_context *gc)
{
struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
char buf[64];
/* read ip configuration info */
snprintf(buf, sizeof(buf), "AT+CGCONTRDP=%u", gcd->active_context);
return g_at_chat_send(gcd->chat, buf, cgcontrdp_prefix,
cgcontrdp_cb, gc, NULL);
}
static void ublox_read_settings(struct ofono_gprs_context *gc)
{
struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
if (ublox_send_cgcontrdp(gc) < 0)
CALLBACK_WITH_FAILURE(gcd->cb, gcd->cb_data);
}
static void ublox_gprs_read_settings(struct ofono_gprs_context *gc,
unsigned int cid,
ofono_gprs_context_cb_t cb, void *data)
{
struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
DBG("cid %u", cid);
gcd->active_context = cid;
gcd->cb = cb;
gcd->cb_data = data;
ublox_read_settings(gc);
}
static void cgact_enable_cb(gboolean ok, GAtResult *result, gpointer user_data)
{
struct ofono_gprs_context *gc = user_data;
struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
DBG("ok %d", ok);
if (!ok) {
struct ofono_error error;
gcd->active_context = 0;
decode_at_error(&error, g_at_result_final_response(result));
gcd->cb(&error, gcd->cb_data);
return;
}
ublox_read_settings(gc);
}
static void cgdcont_cb(gboolean ok, GAtResult *result, gpointer user_data)
{
struct ofono_gprs_context *gc = user_data;
struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
char buf[64];
DBG("ok %d", ok);
if (!ok) {
struct ofono_error error;
gcd->active_context = 0;
decode_at_error(&error, g_at_result_final_response(result));
gcd->cb(&error, gcd->cb_data);
return;
}
snprintf(buf, sizeof(buf), "AT+CGACT=1,%u", gcd->active_context);
if (g_at_chat_send(gcd->chat, buf, none_prefix,
cgact_enable_cb, gc, NULL))
return;
CALLBACK_WITH_FAILURE(gcd->cb, gcd->cb_data);
}
#define UBLOX_MAX_USER_LEN 50
#define UBLOX_MAX_PASS_LEN 50
static void ublox_send_uauthreq(struct ofono_gprs_context *gc,
const char *username, const char *password,
enum ofono_gprs_auth_method auth_method)
{
struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
char buf[UBLOX_MAX_USER_LEN + UBLOX_MAX_PASS_LEN + 32];
unsigned auth;
switch (auth_method) {
case OFONO_GPRS_AUTH_METHOD_PAP:
auth = 1;
break;
case OFONO_GPRS_AUTH_METHOD_CHAP:
auth = 2;
break;
default:
ofono_error("Unsupported auth type %u", auth_method);
return;
}
snprintf(buf, sizeof(buf), "AT+UAUTHREQ=%u,%u,\"%s\",\"%s\"",
gcd->active_context, auth, username, password);
/* If this failed, we will see it during context activation. */
g_at_chat_send(gcd->chat, buf, none_prefix, NULL, NULL, NULL);
}
static void ublox_send_cgdcont(struct ofono_gprs_context *gc, const char *apn,
const char *username, const char *password,
enum ofono_gprs_auth_method auth_method)
{
struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
char buf[OFONO_GPRS_MAX_APN_LENGTH + 128];
size_t u_len, p_len;
int len;
len = snprintf(buf, sizeof(buf), "AT+CGDCONT=%u,\"IP\"",
gcd->active_context);
if (apn)
snprintf(buf + len, sizeof(buf) - len - 3, ",\"%s\"", apn);
if (g_at_chat_send(gcd->chat, buf, none_prefix,
cgdcont_cb, gc, NULL) == 0)
goto error;
u_len = strlen(username);
p_len = strlen(password);
if (u_len && p_len) {
if (u_len >= UBLOX_MAX_USER_LEN ||
p_len >= UBLOX_MAX_PASS_LEN) {
ofono_error("Toby L2: user or password length too big");
goto error;
}
ublox_send_uauthreq(gc, username, password, auth_method);
}
return;
error:
CALLBACK_WITH_FAILURE(gcd->cb, gcd->cb_data);
}
static void ublox_gprs_activate_primary(struct ofono_gprs_context *gc,
const struct ofono_gprs_primary_context *ctx,
ofono_gprs_context_cb_t cb, void *data)
{
struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
/* IPv6 support not implemented */
if (ctx->proto != OFONO_GPRS_PROTO_IP) {
CALLBACK_WITH_FAILURE(cb, data);
return;
}
DBG("cid %u", ctx->cid);
gcd->active_context = ctx->cid;
if (!gcd->active_context) {
ofono_error("can't activate more contexts");
CALLBACK_WITH_FAILURE(cb, data);
return;
}
gcd->cb = cb;
gcd->cb_data = data;
ublox_send_cgdcont(gc, ctx->apn, ctx->username, ctx->password,
ctx->auth_method);
}
static void cgact_disable_cb(gboolean ok, GAtResult *result, gpointer user_data)
{
struct ofono_gprs_context *gc = user_data;
struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
DBG("ok %d", ok);
if (!ok) {
CALLBACK_WITH_FAILURE(gcd->cb, gcd->cb_data);
return;
}
gcd->active_context = 0;
CALLBACK_WITH_SUCCESS(gcd->cb, gcd->cb_data);
}
static void ublox_gprs_deactivate_primary(struct ofono_gprs_context *gc,
unsigned int cid,
ofono_gprs_context_cb_t cb, void *data)
{
struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
char buf[64];
DBG("cid %u", cid);
gcd->cb = cb;
gcd->cb_data = data;
snprintf(buf, sizeof(buf), "AT+CGACT=0,%u", gcd->active_context);
g_at_chat_send(gcd->chat, buf, none_prefix,
cgact_disable_cb, gc, NULL);
}
static void cgev_notify(GAtResult *result, gpointer user_data)
{
struct ofono_gprs_context *gc = user_data;
struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
GAtResultIter iter;
const char *event;
gint cid;
g_at_result_iter_init(&iter, result);
if (!g_at_result_iter_next(&iter, "+CGEV:"))
return;
if (!g_at_result_iter_next_unquoted_string(&iter, &event))
return;
if (g_str_has_prefix(event, "NW PDN DEACT"))
sscanf(event, "%*s %*s %*s %u", &cid);
else if (g_str_has_prefix(event, "NW DEACT"))
sscanf(event, "%*s %*s %u", &cid);
else
return;
DBG("cid %d", cid);
if ((unsigned int) cid != gcd->active_context)
return;
ofono_gprs_context_deactivated(gc, gcd->active_context);
gcd->active_context = 0;
}
static int ublox_gprs_context_probe(struct ofono_gprs_context *gc,
unsigned int vendor, void *data)
{
GAtChat *chat = data;
struct gprs_context_data *gcd;
DBG("");
gcd = g_try_new0(struct gprs_context_data, 1);
if (gcd == NULL)
return -ENOMEM;
gcd->chat = g_at_chat_clone(chat);
ofono_gprs_context_set_data(gc, gcd);
g_at_chat_register(chat, "+CGEV:", cgev_notify, FALSE, gc, NULL);
return 0;
}
static void ublox_gprs_context_remove(struct ofono_gprs_context *gc)
{
struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
DBG("");
ofono_gprs_context_set_data(gc, NULL);
g_at_chat_unref(gcd->chat);
memset(gcd, 0, sizeof(*gcd));
}
static struct ofono_gprs_context_driver driver = {
.name = "ubloxmodem",
.probe = ublox_gprs_context_probe,
.remove = ublox_gprs_context_remove,
.activate_primary = ublox_gprs_activate_primary,
.deactivate_primary = ublox_gprs_deactivate_primary,
.read_settings = ublox_gprs_read_settings,
};
void ublox_gprs_context_init(void)
{
ofono_gprs_context_driver_register(&driver);
}
void ublox_gprs_context_exit(void)
{
ofono_gprs_context_driver_unregister(&driver);
}

View File

@@ -1,9 +1,8 @@
/*
*
* RIL library with GLib integration
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2012-2013 Canonical Ltd.
* Copyright (C) 2016 Endocode AG. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -20,38 +19,31 @@
*
*/
#ifndef __GRILREPLY_H
#define __GRILREPLY_H
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <glib.h>
#include <gatchat.h>
#define OFONO_API_SUBJECT_TO_CHANGE
#include <ofono/plugin.h>
#include <ofono/types.h>
#include "gril.h"
#include "ubloxmodem.h"
#ifdef __cplusplus
extern "C" {
#endif
static int ubloxmodem_init(void)
{
ublox_gprs_context_init();
struct reply_setup_data_call {
guint version;
guint status;
gint cid;
guint retry_time;
guint active;
guint protocol;
gchar *ifname;
gchar **dns_addresses;
gchar **gateways;
gchar **ip_addrs;
};
void g_ril_reply_free_setup_data_call(struct reply_setup_data_call *reply);
struct reply_setup_data_call *g_ril_reply_parse_data_call(GRil *gril,
struct ril_msg *message,
struct ofono_error *error);
#ifdef __cplusplus
return 0;
}
#endif
#endif /* __GRILREPLY_H */
static void ubloxmodem_exit(void)
{
ublox_gprs_context_exit();
}
OFONO_PLUGIN_DEFINE(ubloxmodem, "U-Blox Toby L2 high speed modem driver",
VERSION, OFONO_PLUGIN_PRIORITY_DEFAULT,
ubloxmodem_init, ubloxmodem_exit)

View File

@@ -1,8 +1,8 @@
/*
*
* oFono - Open Source Telephony - RIL-based devices
* oFono - Open Source Telephony
*
* Copyright (C) 2015 Jolla Ltd.
* Copyright (C) 2016 Endocode AG. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -19,14 +19,7 @@
*
*/
#ifndef __RILDEV_H
#define __RILDEV_H
#include <drivers/atmodem/atutil.h>
#define RILD_CMD_SOCKET "/dev/socket/rild"
#define RILD_SOCKET_DIR "/dev/socket"
#define RILD_SOCKET_FILE "rild"
void ril_modem_remove(struct ofono_modem *modem);
#endif /* __RILDEV_H */
extern void ublox_gprs_context_init(void);
extern void ublox_gprs_context_exit(void);

View File

@@ -305,8 +305,9 @@ static void at_command_destroy(struct at_command *cmd)
g_free(cmd);
}
static void free_terminator(struct terminator_info *info)
static void free_terminator(gpointer pointer)
{
struct terminator_info *info = pointer;
g_free(info->terminator);
info->terminator = NULL;
g_free(info);
@@ -325,8 +326,7 @@ static void chat_cleanup(struct at_chat *chat)
chat->command_queue = NULL;
/* Cleanup any response lines we have pending */
g_slist_foreach(chat->response_lines, (GFunc)g_free, NULL);
g_slist_free(chat->response_lines);
g_slist_free_full(chat->response_lines, g_free);
chat->response_lines = NULL;
/* Cleanup registered notifications */
@@ -357,9 +357,7 @@ static void chat_cleanup(struct at_chat *chat)
chat->syntax = NULL;
if (chat->terminator_list) {
g_slist_foreach(chat->terminator_list,
(GFunc)free_terminator, NULL);
g_slist_free(chat->terminator_list);
g_slist_free_full(chat->terminator_list, free_terminator);
chat->terminator_list = NULL;
}
}
@@ -461,8 +459,7 @@ static void at_chat_finish_command(struct at_chat *p, gboolean ok, char *final)
cmd->callback(ok, &result, cmd->user_data);
}
g_slist_foreach(response_lines, (GFunc)g_free, NULL);
g_slist_free(response_lines);
g_slist_free_full(response_lines, g_free);
g_free(final);
at_command_destroy(cmd);

View File

@@ -598,6 +598,13 @@ void g_at_mux_unref(GAtMux *mux)
}
}
static void read_watcher_destroy_notify(gpointer user_data)
{
GAtMux *mux = user_data;
mux->read_watch = 0;
}
gboolean g_at_mux_start(GAtMux *mux)
{
if (mux->channel == NULL)
@@ -611,7 +618,8 @@ gboolean g_at_mux_start(GAtMux *mux)
mux->read_watch = g_io_add_watch_full(mux->channel, G_PRIORITY_DEFAULT,
G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
received_data, mux, NULL);
received_data, mux,
read_watcher_destroy_notify);
mux->shutdown = FALSE;

View File

@@ -1073,6 +1073,9 @@ static gboolean signal_cb(GIOChannel *channel, GIOCondition cond, gpointer data)
case SIGTERM:
server_cleanup();
break;
case SIGUSR1:
g_at_ppp_shutdown(ppp);
break;
default:
break;
}
@@ -1089,6 +1092,7 @@ static int create_signal_io(void)
sigemptyset(&mask);
sigaddset(&mask, SIGTERM);
sigaddset(&mask, SIGINT);
sigaddset(&mask, SIGUSR1);
if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) {
g_error("Can't set signal mask");

File diff suppressed because it is too large Load Diff

View File

@@ -31,6 +31,7 @@ extern "C" {
#include "grilutil.h"
#include "parcel.h"
#include "ril_constants.h"
#include "drivers/rilmodem/vendor.h"
struct _GRil;
@@ -43,7 +44,7 @@ typedef struct _GRil GRil;
*/
struct ril_msg {
gchar *buf;
gsize buf_len;
unsigned int buf_len;
gboolean unsolicited;
int req;
int serial_no;
@@ -54,6 +55,8 @@ typedef void (*GRilResponseFunc)(struct ril_msg *message, gpointer user_data);
typedef void (*GRilNotifyFunc)(struct ril_msg *message, gpointer user_data);
typedef const char *(*GRilMsgIdToStrFunc)(int msg_id);
/**
* TRACE:
* @fmt: format string
@@ -64,36 +67,52 @@ typedef void (*GRilNotifyFunc)(struct ril_msg *message, gpointer user_data);
*/
#define G_RIL_TRACE(gril, fmt, arg...) do { \
if (gril && g_ril_get_trace(gril)) \
ofono_debug(fmt, ## arg); \
ofono_debug(fmt, ## arg); \
} while (0)
extern char print_buf[];
#define g_ril_print_request(gril, token, req) \
G_RIL_TRACE(gril, "[%04d]> %s %s", token, ril_request_id_to_string(req), print_buf)
#define g_ril_print_request(gril, token, req) \
G_RIL_TRACE(gril, "[%d,%04d]> %s %s", \
g_ril_get_slot(gril), token, \
g_ril_request_id_to_string(gril, req), print_buf); \
print_buf[0] = '\0';
#define g_ril_print_request_no_args(gril, token, req) \
G_RIL_TRACE(gril, "[%04d]> %s", token, ril_request_id_to_string(req))
#define g_ril_print_response(gril, message) \
G_RIL_TRACE(gril, "[%04d]< %s %s", message->serial_no, \
ril_request_id_to_string(message->req), print_buf)
#define g_ril_print_response_no_args(gril, message) \
G_RIL_TRACE(gril, "[%04d]< %s", message->serial_no, \
ril_request_id_to_string(message->req))
G_RIL_TRACE(gril, "[%d,%04d]> %s", \
g_ril_get_slot(gril), token, \
g_ril_request_id_to_string(gril, req))
#define g_ril_print_response(gril, message) \
G_RIL_TRACE(gril, "[%d,%04d]< %s %s", \
g_ril_get_slot(gril), \
message->serial_no, \
g_ril_request_id_to_string(gril, message->req), \
print_buf); \
print_buf[0] = '\0';
#define g_ril_print_response_no_args(gril, message) \
G_RIL_TRACE(gril, "[%d,%04d]< %s", \
g_ril_get_slot(gril), message->serial_no, \
g_ril_request_id_to_string(gril, message->req))
#define g_ril_append_print_buf(gril, x...) do { \
if (gril && g_ril_get_trace(gril)) \
sprintf(print_buf, x); \
#define g_ril_append_print_buf(gril, x...) do { \
if (gril && g_ril_get_trace(gril)) \
sprintf(print_buf, x); \
} while (0)
#define g_ril_print_unsol(gril, message) \
G_RIL_TRACE(gril, "[UNSOL]< %s %s", ril_unsol_request_to_string(message->req), \
#define g_ril_print_unsol(gril, message) \
G_RIL_TRACE(gril, "[%d,UNSOL]< %s %s", \
g_ril_get_slot(gril), \
g_ril_unsol_request_to_string(gril, \
message->req), \
print_buf)
#define g_ril_print_unsol_no_args(gril, message) \
G_RIL_TRACE(gril, "[UNSOL]< %s", ril_unsol_request_to_string(message->req))
#define g_ril_print_unsol_no_args(gril, message) \
G_RIL_TRACE(gril, "[%d,UNSOL]< %s", g_ril_get_slot(gril), \
g_ril_unsol_request_to_string(gril, message->req))
void g_ril_init_parcel(struct ril_msg *message, struct parcel *rilp);
void g_ril_init_parcel(const struct ril_msg *message, struct parcel *rilp);
GRil *g_ril_new(const char *sockpath);
GRil *g_ril_new(const char *sock_path, enum ofono_ril_vendor vendor);
GRil *g_ril_new_with_ucred(const char *sock_path, enum ofono_ril_vendor vendor,
unsigned int uid, unsigned int gid);
GIOChannel *g_ril_get_channel(GRil *ril);
GRilIO *g_ril_get_io(GRil *ril);
@@ -103,15 +122,15 @@ void g_ril_unref(GRil *ril);
GRil *g_ril_clone(GRil *ril);
void g_ril_suspend(GRil *ril);
void g_ril_resume(GRil *ril);
gboolean g_ril_set_disconnect_function(GRil *ril, GRilDisconnectFunc disconnect,
void g_ril_set_disconnect_function(GRil *ril, GRilDisconnectFunc disconnect,
gpointer user_data);
gboolean g_ril_get_trace(GRil *ril);
gboolean g_ril_set_trace(GRil *ril, gboolean trace);
int g_ril_get_slot(GRil *ril);
gboolean g_ril_set_slot(GRil *ril, int slot);
/*!
* If the function is not NULL, then on every read/write from the GIOChannel
* provided to GRil the logging function will be called with the
@@ -119,6 +138,11 @@ gboolean g_ril_set_trace(GRil *ril, gboolean trace);
*/
gboolean g_ril_set_debugf(GRil *ril, GRilDebugFunc func, gpointer user_data);
gboolean g_ril_set_vendor_print_msg_id_funcs(GRil *ril,
GRilMsgIdToStrFunc req_to_string,
GRilMsgIdToStrFunc unsol_to_string);
/*!
* Queue an RIL request for execution. The request contents are given
* in data. Once the command executes, the callback function given by
@@ -128,9 +152,9 @@ gboolean g_ril_set_debugf(GRil *ril, GRilDebugFunc func, gpointer user_data);
* g_ril_cancel. If an error occurred, an id of 0 is returned.
*
*/
guint g_ril_send(GRil *ril, const guint reqid, const char *data,
const gsize data_len, GRilResponseFunc func,
gpointer user_data, GDestroyNotify notify);
gint g_ril_send(GRil *ril, const gint reqid, struct parcel *rilp,
GRilResponseFunc func, gpointer user_data,
GDestroyNotify notify);
guint g_ril_register(GRil *ril, const int req,
GRilNotifyFunc func, gpointer user_data);
@@ -138,7 +162,10 @@ guint g_ril_register(GRil *ril, const int req,
gboolean g_ril_unregister(GRil *ril, guint id);
gboolean g_ril_unregister_all(GRil *ril);
guint current_online_state;
enum ofono_ril_vendor g_ril_vendor(GRil *ril);
const char *g_ril_request_id_to_string(GRil *ril, int req);
const char *g_ril_unsol_request_to_string(GRil *ril, int req);
#ifdef __cplusplus
}

View File

@@ -4,7 +4,6 @@
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2012 Canonical Ltd.
* Copyright (C) 2013 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -28,7 +27,6 @@
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <ctype.h>
#include <errno.h>
@@ -73,7 +71,6 @@ static void read_watcher_destroy_notify(gpointer user_data)
io->read_handler = NULL;
io->read_data = NULL;
g_io_channel_unref(io->channel);
io->channel = NULL;
if (io->destroyed)
@@ -109,7 +106,7 @@ static gboolean received_data(GIOChannel *channel, GIOCondition cond,
status = g_io_channel_read_chars(channel, (char *) buf,
toread, &rbytes, NULL);
g_ril_util_debug_hexdump(TRUE, buf, rbytes,
g_ril_util_debug_hexdump(TRUE, (guchar *) buf, rbytes,
io->debugf, io->debug_data);
read_count++;
@@ -151,8 +148,8 @@ gsize g_ril_io_write(GRilIO *io, const gchar *data, gsize count)
return 0;
}
g_ril_util_debug_hexdump(FALSE, (const unsigned char *)data,
bytes_written, io->debugf, io->debug_data);
g_ril_util_debug_hexdump(FALSE, (guchar *) data, bytes_written,
io->debugf, io->debug_data);
return bytes_written;
}
@@ -208,7 +205,7 @@ static GRilIO *create_io(GIOChannel *channel, GIOFlags flags)
io->use_write_watch = FALSE;
}
io->buf = ring_buffer_new(8192);
io->buf = ring_buffer_new(GRIL_BUFFER_SIZE);
if (!io->buf)
goto error;
@@ -270,7 +267,9 @@ static gboolean call_blocking_read(gpointer user_data)
{
GRilIO *io = user_data;
while (can_write_data(io->channel, G_IO_OUT, io) == TRUE);
while (can_write_data(io->channel, G_IO_OUT, io) == TRUE)
;
write_watcher_destroy_notify(io);
return FALSE;
@@ -288,7 +287,7 @@ gboolean g_ril_io_set_write_handler(GRilIO *io, GRilIOWriteFunc write_handler,
return TRUE;
}
return FALSE;
return FALSE;
}
if (write_handler == NULL)

View File

@@ -29,6 +29,8 @@ extern "C" {
#include "gfunc.h"
#define GRIL_BUFFER_SIZE 8192
struct _GRilIO;
typedef struct _GRilIO GRilIO;

View File

@@ -1,214 +0,0 @@
/*
*
* RIL library with GLib integration
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2012-2013 Canonical Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <string.h>
#include <glib.h>
#include <ofono/log.h>
#include <ofono/modem.h>
#include <ofono/gprs-context.h>
#include "grilreply.h"
#include "grilutil.h"
/* SETUP_DATA_CALL_PARAMS reply params */
#define MIN_DATA_CALL_REPLY_SIZE 36
/* TODO: move this to grilutil.c */
void g_ril_reply_free_setup_data_call(struct reply_setup_data_call *reply)
{
if (reply) {
g_free(reply->ifname);
g_strfreev(reply->dns_addresses);
g_strfreev(reply->gateways);
g_strfreev(reply->ip_addrs);
g_free(reply);
}
}
struct reply_setup_data_call *g_ril_reply_parse_data_call(GRil *gril,
struct ril_msg *message,
struct ofono_error *error)
{
struct parcel rilp;
int num = 0;
int protocol;
char *type = NULL, *raw_ip_addrs = NULL;
char *dnses = NULL, *raw_gws = NULL;
struct reply_setup_data_call *reply =
g_new0(struct reply_setup_data_call, 1);
OFONO_NO_ERROR(error);
reply->cid = -1;
/* TODO:
* Cleanup duplicate code between this function and
* ril_util_parse_data_call_list().
*/
/* valid size: 36 (34 if HCRADIO defined) */
if (message->buf_len < MIN_DATA_CALL_REPLY_SIZE) {
/* TODO: make a macro for error logging */
ofono_error("%s: reply too small: %d",
__func__,
(int) message->buf_len);
OFONO_EINVAL(error);
goto error;
}
g_ril_init_parcel(message, &rilp);
/*
* ril.h documents the reply to a RIL_REQUEST_SETUP_DATA_CALL
* as being a RIL_Data_Call_Response_v6 struct, however in
* reality, the response actually includes the version of the
* struct, followed by an array of calls, so the array size
* also has to be read after the version.
*
* TODO: What if there's more than 1 call in the list??
*/
/*
* TODO: consider using 'unused' variable; however if we
* do this, the alternative is a few more append_print_buf
* calls ( which become no-ops if tracing isn't enabled.
*/
reply->version = parcel_r_int32(&rilp);
num = parcel_r_int32(&rilp);
if (num != 1) {
ofono_error("%s: too many calls: %d", __func__, num);
OFONO_EINVAL(error);
goto error;
}
reply->status = parcel_r_int32(&rilp);
reply->retry_time = parcel_r_int32(&rilp);
reply->cid = parcel_r_int32(&rilp);
reply->active = parcel_r_int32(&rilp);
type = parcel_r_string(&rilp);
reply->ifname = parcel_r_string(&rilp);
raw_ip_addrs = parcel_r_string(&rilp);
dnses = parcel_r_string(&rilp);
raw_gws = parcel_r_string(&rilp);
g_ril_append_print_buf(gril,
"{version=%d,num=%d [status=%d,retry=%d,"
"cid=%d,active=%d,type=%s,ifname=%s,address=%s"
",dns=%s,gateways=%s]}",
reply->version,
num,
reply->status,
reply->retry_time,
reply->cid,
reply->active,
type,
reply->ifname,
raw_ip_addrs,
dnses,
raw_gws);
g_ril_print_response(gril, message);
protocol = ril_protocol_string_to_ofono_protocol(type);
if (protocol < 0) {
ofono_error("%s: Invalid type(protocol) specified: %s",
__func__,
type);
OFONO_EINVAL(error);
goto error;
}
reply->protocol = (guint) protocol;
if (reply->ifname == NULL || strlen(reply->ifname) == 0) {
ofono_error("%s: No interface specified: %s",
__func__,
reply->ifname);
OFONO_EINVAL(error);
goto error;
}
if (raw_ip_addrs)
reply->ip_addrs = g_strsplit(raw_ip_addrs, " ", -1);
else
reply->ip_addrs = NULL;
/* TODO: I'm not sure it's possible to specify a zero-length
* in a parcel in a parcel. If *not*, then this can be
* simplified.
*/
if (reply->ip_addrs == NULL || (sizeof(reply->ip_addrs) == 0)) {
ofono_error("%s no IP address: %s", __func__, raw_ip_addrs);
OFONO_EINVAL(error);
goto error;
}
/*
* RILD can return multiple addresses; oFono only supports
* setting a single IPv4 gateway.
*/
if (raw_gws)
reply->gateways = g_strsplit(raw_gws, " ", -1);
else
reply->gateways = NULL;
if (reply->gateways == NULL || (sizeof(reply->gateways) == 0)) {
ofono_error("%s: no gateways: %s", __func__, raw_gws);
OFONO_EINVAL(error);
goto error;
}
/* Split DNS addresses */
if (dnses)
reply->dns_addresses = g_strsplit(dnses, " ", -1);
else
reply->dns_addresses = NULL;
if (reply->dns_addresses == NULL ||
(sizeof(reply->dns_addresses) == 0)) {
ofono_error("%s: no DNS: %s", __func__, dnses);
OFONO_EINVAL(error);
goto error;
}
error:
g_free(type);
g_free(raw_ip_addrs);
g_free(dnses);
g_free(raw_gws);
return reply;
}

View File

@@ -1,234 +0,0 @@
/*
*
* RIL library with GLib integration
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2012-2013 Canonical Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <string.h>
#include <glib.h>
#include <ofono/log.h>
#include <ofono/modem.h>
#include <ofono/gprs-context.h>
#include "grilrequest.h"
/* DEACTIVATE_DATA_CALL request parameters */
#define DEACTIVATE_DATA_CALL_NUM_PARAMS 2
/* SETUP_DATA_CALL_PARAMS request parameters */
#define SETUP_DATA_CALL_PARAMS 7
#define DATA_PROFILE_DEFAULT_STR "0"
#define DATA_PROFILE_TETHERED_STR "1"
#define DATA_PROFILE_IMS_STR "2"
#define DATA_PROFILE_FOTA_STR "3"
#define DATA_PROFILE_CBS_STR "4"
#define DATA_PROFILE_OEM_BASE_STR "1000"
/* SETUP_DATA_CALL_PARAMS reply parameters */
#define MIN_DATA_CALL_REPLY_SIZE 36
/*
* TODO:
*
* A potential future change here is to create a driver
* abstraction for each request/reply/event method, and a
* corresponding method to allow new per-message implementations
* to be registered. This would allow PES to easily add code
* to quirk a particular RIL implementation.
*
* struct g_ril_messages_driver {
* const char *name;
* };
*
*/
gboolean g_ril_request_deactivate_data_call(GRil *gril,
const struct req_deactivate_data_call *req,
struct parcel *rilp,
struct ofono_error *error)
{
gchar *cid_str = NULL;
gchar *reason_str = NULL;
if (req->reason != RIL_DEACTIVATE_DATA_CALL_NO_REASON &&
req->reason != RIL_DEACTIVATE_DATA_CALL_RADIO_SHUTDOWN) {
goto error;
}
parcel_init(rilp);
parcel_w_int32(rilp, DEACTIVATE_DATA_CALL_NUM_PARAMS);
cid_str = g_strdup_printf("%d", req->cid);
parcel_w_string(rilp, cid_str);
/*
* TODO: airplane-mode; change reason to '1',
* which means "radio power off".
*/
reason_str = g_strdup_printf("%d", req->reason);
parcel_w_string(rilp, reason_str);
g_free(cid_str);
g_free(reason_str);
OFONO_NO_ERROR(error);
return TRUE;
error:
OFONO_EINVAL(error);
return FALSE;
}
gboolean g_ril_request_setup_data_call(GRil *gril,
const struct req_setup_data_call *req,
struct parcel *rilp,
struct ofono_error *error)
{
const gchar *protocol_str;
gchar *tech_str;
gchar *auth_str;
gchar *profile_str;
size_t apn_len;
DBG("");
if (req->tech < RADIO_TECH_GPRS || req->tech > RADIO_TECH_GSM) {
ofono_error("%s: Invalid tech value: %d", __func__, req->tech);
goto error;
}
/*
* TODO(OEM): This code doesn't currently support
* OEM data profiles. If a use case exist, then
* this code will need to be modified.
*/
switch (req->data_profile) {
case RIL_DATA_PROFILE_DEFAULT:
profile_str = DATA_PROFILE_DEFAULT_STR;
break;
case RIL_DATA_PROFILE_TETHERED:
profile_str = DATA_PROFILE_TETHERED_STR;
break;
case RIL_DATA_PROFILE_IMS:
profile_str = DATA_PROFILE_IMS_STR;
break;
case RIL_DATA_PROFILE_FOTA:
profile_str = DATA_PROFILE_FOTA_STR;
break;
case RIL_DATA_PROFILE_CBS:
profile_str = DATA_PROFILE_CBS_STR;
break;
default:
ofono_error("%s, invalid data_profile value: %d",
__func__,
req->data_profile);
goto error;
}
if (req->apn == NULL)
goto error;
apn_len = strlen(req->apn);
if (apn_len == 0 || apn_len > 100) {
ofono_error("%s: invalid apn length: %d",
__func__,
(int) apn_len);
goto error;
}
if (req->auth_type > RIL_AUTH_BOTH) {
ofono_error("%s: Invalid auth type: %d",
__func__,
req->auth_type);
goto error;
}
protocol_str = ril_ofono_protocol_to_ril_string(req->protocol);
if (protocol_str == NULL) {
ofono_error("%s: Invalid protocol: %d",
__func__,
req->protocol);
goto error;
}
parcel_init(rilp);
parcel_w_int32(rilp, SETUP_DATA_CALL_PARAMS);
tech_str = g_strdup_printf("%d", req->tech);
parcel_w_string(rilp, (char *) tech_str);
parcel_w_string(rilp, (char *) profile_str);
parcel_w_string(rilp, (char *) req->apn);
parcel_w_string(rilp, (char *) req->username);
parcel_w_string(rilp, (char *) req->password);
auth_str = g_strdup_printf("%d", req->auth_type);
parcel_w_string(rilp, (char *) auth_str);
parcel_w_string(rilp, (char *) protocol_str);
g_ril_append_print_buf(gril,
"(%s,%s,%s,%s,%s,%s,%s)",
tech_str,
profile_str,
req->apn,
req->username,
req->password,
auth_str,
protocol_str);
g_free(tech_str);
g_free(auth_str);
OFONO_NO_ERROR(error);
return TRUE;
error:
OFONO_EINVAL(error);
return FALSE;
}
void g_ril_request_set_uicc_subscription(GRil *gril, int slot_id,
int app_index,
int sub_id,
int sub_status,
struct parcel *rilp)
{
parcel_init(rilp);
parcel_w_int32(rilp, slot_id);
parcel_w_int32(rilp, app_index);
parcel_w_int32(rilp, sub_id);
parcel_w_int32(rilp, sub_status);
g_ril_append_print_buf(gril, "(%d, %d, %d, %d(%s))",
slot_id,
app_index,
sub_id,
sub_status,
sub_status ? "ACTIVATE" : "DEACTIVATE");
}

View File

@@ -1,69 +0,0 @@
/*
*
* RIL library with GLib integration
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2012-2013 Canonical Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef __GRILREQUEST_H
#define __GRILREQUEST_H
#include <ofono/types.h>
#include "gril.h"
#ifdef __cplusplus
extern "C" {
#endif
struct req_deactivate_data_call {
guint cid;
guint reason;
};
struct req_setup_data_call {
guint tech;
guint data_profile;
gchar *apn;
gchar *username;
gchar *password;
guint auth_type;
guint protocol;
};
gboolean g_ril_request_deactivate_data_call(GRil *gril,
const struct req_deactivate_data_call *req,
struct parcel *rilp,
struct ofono_error *error);
gboolean g_ril_request_setup_data_call(GRil *gril,
const struct req_setup_data_call *req,
struct parcel *rilp,
struct ofono_error *error);
void g_ril_request_set_uicc_subscription(GRil *gril, int slot_id,
int app_index,
int sub_id,
int sub_status,
struct parcel *rilp);
#ifdef __cplusplus
}
#endif
#endif /* __GRILREQUEST_H */

View File

@@ -1,210 +0,0 @@
/*
*
* RIL library with GLib integration
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2012-2013 Canonical Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <string.h>
#include <glib.h>
#include <ofono/log.h>
#include <ofono/modem.h>
#include <ofono/gprs-context.h>
#include "grilunsol.h"
/* Minimum size is two int32s version/number of calls */
#define MIN_DATA_CALL_LIST_SIZE 8
static gint data_call_compare(gconstpointer a, gconstpointer b)
{
const struct data_call *ca = a;
const struct data_call *cb = b;
if (ca->cid < cb->cid)
return -1;
if (ca->cid > cb->cid)
return 1;
return 0;
}
static void free_data_call(gpointer data, gpointer user_data)
{
struct data_call *call = data;
if (call) {
g_free(call->type);
g_free(call->ifname);
g_free(call->addresses);
g_free(call->dnses);
g_free(call->gateways);
g_free(call);
}
}
void g_ril_unsol_free_data_call_list(struct unsol_data_call_list *unsol)
{
if (unsol) {
g_slist_foreach(unsol->call_list, (GFunc) free_data_call, NULL);
g_slist_free(unsol->call_list);
g_free(unsol);
}
}
gboolean g_ril_unsol_cmp_dcl(struct unsol_data_call_list *current,
struct unsol_data_call_list *old,
gint cid)
{
GSList *nl,*ol;
struct data_call *new_call, *old_call;
new_call = old_call = NULL;
gboolean no_cid = TRUE;
if (!current || !old)
return FALSE;
if (current->num != old->num)
return FALSE;
for (nl = current->call_list; nl; nl = nl->next) {
new_call = (struct data_call *) nl->data;
if (new_call->cid != cid)
continue;
for (ol = old->call_list; ol; ol = ol->next) {
old_call = (struct data_call *) ol->data;
if(new_call->cid == old_call->cid) {
no_cid = FALSE;
break;
}
}
if (no_cid)
return FALSE;
if (new_call->active != old_call->active)
return FALSE;
if (g_strcmp0(new_call->type,old_call->type))
return FALSE;
if (g_strcmp0(new_call->ifname,old_call->ifname))
return FALSE;
if (g_strcmp0(new_call->addresses,old_call->addresses))
return FALSE;
if (g_strcmp0(new_call->dnses,old_call->dnses))
return FALSE;
if (g_strcmp0(new_call->gateways,old_call->gateways))
return FALSE;
}
if (no_cid)
return FALSE;
return TRUE;
}
struct unsol_data_call_list *g_ril_unsol_parse_data_call_list(GRil *gril,
struct ril_msg *message,
struct ofono_error *error)
{
struct data_call *call;
struct parcel rilp;
struct unsol_data_call_list *reply =
g_new0(struct unsol_data_call_list, 1);
int i;
DBG("");
OFONO_NO_ERROR(error);
if (message->buf_len < MIN_DATA_CALL_LIST_SIZE) {
ofono_error("%s: message too small: %d",
__func__,
(int) message->buf_len);
OFONO_EINVAL(error);
goto error;
}
g_ril_init_parcel(message, &rilp);
/*
* ril.h documents the reply to a RIL_REQUEST_DATA_CALL_LIST
* as being an array of RIL_Data_Call_Response_v6 structs,
* however in reality, the response also includes a version
* to start.
*/
reply->version = parcel_r_int32(&rilp);
reply->num = parcel_r_int32(&rilp);
g_ril_append_print_buf(gril,
"(version=%d,num=%d",
reply->version,
reply->num);
for (i = 0; i < reply->num; i++) {
call = g_new0(struct data_call, 1);
call->status = parcel_r_int32(&rilp);
call->retry = parcel_r_int32(&rilp);
call->cid = parcel_r_int32(&rilp);
call->active = parcel_r_int32(&rilp);
call->type = parcel_r_string(&rilp);
call->ifname = parcel_r_string(&rilp);
call->addresses = parcel_r_string(&rilp);
call->dnses = parcel_r_string(&rilp);
call->gateways = parcel_r_string(&rilp);
g_ril_append_print_buf(gril,
"%s [status=%d,retry=%d,cid=%d,"
"active=%d,type=%s,ifname=%s,"
"address=%s,dns=%s,gateways=%s]",
print_buf,
call->status,
call->retry,
call->cid,
call->active,
call->type,
call->ifname,
call->addresses,
call->dnses,
call->gateways);
reply->call_list =
g_slist_insert_sorted(reply->call_list,
call,
data_call_compare);
}
g_ril_append_print_buf(gril, "%s}", print_buf);
g_ril_print_unsol(gril, message);
error:
return reply;
}

View File

@@ -1,65 +0,0 @@
/*
*
* RIL library with GLib integration
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2012-2013 Canonical Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef __GRILUNSOL_H
#define __GRILUNSOL_H
#include <ofono/types.h>
#include "gril.h"
#ifdef __cplusplus
extern "C" {
#endif
struct unsol_data_call_list {
guint version;
guint num;
GSList *call_list;
};
struct data_call {
guint status;
guint retry;
guint cid;
guint active;
char *type;
char *ifname;
char *addresses;
char *dnses;
char *gateways;
};
void g_ril_unsol_free_data_call_list(struct unsol_data_call_list *unsol);
gboolean g_ril_unsol_cmp_dcl(struct unsol_data_call_list *current,
struct unsol_data_call_list *old, gint cid);
struct unsol_data_call_list *g_ril_unsol_parse_data_call_list(GRil *gril,
struct ril_msg *message,
struct ofono_error *error);
#ifdef __cplusplus
}
#endif
#endif /* __GRILUNSOL_H */

Some files were not shown because too many files have changed in this diff Show More