Compare commits

...

412 Commits

Author SHA1 Message Date
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
144 changed files with 12695 additions and 9512 deletions

5
ofono/.gitignore vendored
View File

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

View File

@@ -104,3 +104,12 @@ Alex J Lennon <ajlennon@dynamicdevices.co.uk>
Sergey Alirzaev <zl29ah@gmail.com> Sergey Alirzaev <zl29ah@gmail.com>
Marko Sulejic <marko.sulejic@hale.at> Marko Sulejic <marko.sulejic@hale.at>
Johannes 'josch' Schauer <josch@mister-muffin.de> 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>

View File

@@ -1,3 +1,24 @@
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: ver 1.17:
Fix issue with alphanumeric TP-OA handling. Fix issue with alphanumeric TP-OA handling.
Fix issue with push notification origin port. 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/' a feature that touches files under 'include/', 'src/' and 'drivers/'
directories, split in three separated patches, taking care not to directories, split in three separated patches, taking care not to
break compilation. 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/cdma-connman.h include/gnss.h \
include/private-network.h include/cdma-netreg.h \ include/private-network.h include/cdma-netreg.h \
include/cdma-provision.h include/handsfree.h \ include/cdma-provision.h include/handsfree.h \
include/handsfree-audio.h \
include/sim-mnclength.h \ include/sim-mnclength.h \
include/siri.h include/handsfree-audio.h include/siri.h \
include/netmon.h
nodist_pkginclude_HEADERS = include/version.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/server.c gisi/server.h \
gisi/socket.c gisi/socket.h gisi/socket.c gisi/socket.h
gril_sources = gril/gril.h gril/gril.c gril/grilio.h \ gril_sources = gril/gril.h gril/gril.c \
gril/grilio.c gril/grilutil.h \ gril/grilio.h gril/grilio.c \
gril/grilutil.c gril/ringbuffer.h \ gril/grilutil.h gril/grilutil.c \
gril/gfunc.h gril/ril.h \ gril/gfunc.h gril/gril.h \
gril/parcel.c gril/parcel.h \ gril/parcel.c gril/parcel.h \
gril/grilreply.c gril/grilreply.h \ gril/ril_constants.h
gril/grilrequest.c gril/grilrequest.h \
gril/grilunsol.c gril/grilunsol.h
btio_sources = btio/btio.h btio/btio.c btio_sources = btio/btio.h btio/btio.c
@@ -120,6 +118,7 @@ endif
if RILMODEM if RILMODEM
if JOLLA_RILMODEM if JOLLA_RILMODEM
builtin_modules += ril builtin_modules += ril
builtin_sources += drivers/ril/ril_call_barring.c \ builtin_sources += drivers/ril/ril_call_barring.c \
drivers/ril/ril_call_forward.c \ drivers/ril/ril_call_forward.c \
@@ -136,6 +135,7 @@ builtin_sources += drivers/ril/ril_call_barring.c \
drivers/ril/ril_gprs_context.c \ drivers/ril/ril_gprs_context.c \
drivers/ril/ril_modem.c \ drivers/ril/ril_modem.c \
drivers/ril/ril_mtu.c \ drivers/ril/ril_mtu.c \
drivers/ril/ril_netmon.c \
drivers/ril/ril_netreg.c \ drivers/ril/ril_netreg.c \
drivers/ril/ril_network.c \ drivers/ril/ril_network.c \
drivers/ril/ril_oem_raw.c \ drivers/ril/ril_oem_raw.c \
@@ -160,20 +160,29 @@ dist_conf_DATA += drivers/ril/ril_subscription.conf
endif endif
else else
builtin_sources += $(gril_sources) builtin_sources += $(gril_sources)
builtin_modules += rildev builtin_modules += rildev
builtin_sources += plugins/rildev.c builtin_sources += plugins/rildev.c
builtin_modules += ril 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_modules += rilmodem
builtin_sources += drivers/rilmodem/rilmodem.h \ builtin_sources += drivers/rilmodem/rilmodem.h \
drivers/rilmodem/vendor.h \
drivers/rilmodem/rilmodem.c \ drivers/rilmodem/rilmodem.c \
drivers/rilmodem/devinfo.c \ drivers/rilmodem/devinfo.c \
drivers/rilmodem/network-registration.c \ drivers/rilmodem/network-registration.c \
drivers/rilmodem/voicecall.c \ drivers/rilmodem/voicecall.c \
drivers/rilmodem/voicecall.h \
drivers/rilmodem/call-volume.c \ drivers/rilmodem/call-volume.c \
drivers/rilmodem/gprs.c \ drivers/rilmodem/gprs.c \
drivers/rilmodem/gprs-context.c \ drivers/rilmodem/gprs-context.c \
@@ -181,20 +190,14 @@ builtin_sources += drivers/rilmodem/rilmodem.h \
drivers/rilmodem/sms.c \ drivers/rilmodem/sms.c \
drivers/rilmodem/rilutil.c \ drivers/rilmodem/rilutil.c \
drivers/rilmodem/rilutil.h \ drivers/rilmodem/rilutil.h \
drivers/rilmodem/radio-settings.c \
drivers/rilmodem/phonebook.c \
drivers/rilmodem/ussd.c \ drivers/rilmodem/ussd.c \
drivers/rilmodem/call-settings.c \ drivers/rilmodem/call-settings.c \
drivers/rilmodem/call-forwarding.c \ drivers/rilmodem/call-forwarding.c \
drivers/rilmodem/cbs.c \ drivers/rilmodem/radio-settings.c \
drivers/rilmodem/oemraw-messages.c \
drivers/rilmodem/call-barring.c \ drivers/rilmodem/call-barring.c \
drivers/rilmodem/stk.c drivers/rilmodem/netmon.c \
drivers/rilmodem/stk.c \
if DATAFILES drivers/infineonmodem/infineon_constants.h
dist_conf_DATA += gril/ril_subscription.conf
endif
endif endif
endif endif
@@ -282,8 +285,7 @@ endif
if ATMODEM if ATMODEM
builtin_modules += atmodem builtin_modules += atmodem
builtin_sources += $(gatchat_sources) \ builtin_sources += drivers/atmodem/atmodem.h \
drivers/atmodem/atmodem.h \
drivers/atmodem/atmodem.c \ drivers/atmodem/atmodem.c \
drivers/atmodem/call-settings.c \ drivers/atmodem/call-settings.c \
drivers/atmodem/sms.c \ drivers/atmodem/sms.c \
@@ -421,6 +423,13 @@ builtin_sources += drivers/atmodem/atutil.h \
drivers/speedupmodem/speedupmodem.c \ drivers/speedupmodem/speedupmodem.c \
drivers/speedupmodem/ussd.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 if PHONESIM
builtin_modules += phonesim builtin_modules += phonesim
builtin_sources += plugins/phonesim.c builtin_sources += plugins/phonesim.c
@@ -527,9 +536,6 @@ builtin_sources += plugins/connman.c
if BLUETOOTH if BLUETOOTH
if BLUEZ4 if BLUEZ4
builtin_modules += bluez4
builtin_sources += plugins/bluez4.c plugins/bluez4.h
builtin_modules += telit builtin_modules += telit
builtin_sources += plugins/telit.c plugins/bluez4.h builtin_sources += plugins/telit.c plugins/bluez4.h
@@ -539,11 +545,25 @@ builtin_sources += plugins/sap.c plugins/bluez4.h
builtin_modules += hfp_bluez4 builtin_modules += hfp_bluez4
builtin_sources += plugins/hfp_hf_bluez4.c plugins/bluez4.h 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_modules += dun_gw_bluez4
builtin_sources += plugins/dun_gw_bluez4.c plugins/bluez4.h 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_sources += $(btio_sources)
builtin_cflags += @BLUEZ_CFLAGS@ builtin_cflags += @BLUEZ_CFLAGS@
@@ -552,15 +572,13 @@ else
builtin_modules += bluez5 builtin_modules += bluez5
builtin_sources += plugins/bluez5.c plugins/bluez5.h 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_modules += hfp_ag_bluez5
builtin_sources += plugins/hfp_ag_bluez5.c plugins/bluez5.h 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
endif endif
if UPOWER
builtin_modules += upower
builtin_sources += plugins/upower.c
endif endif
endif endif
@@ -626,9 +644,12 @@ endif
builtin_modules += sms_history builtin_modules += sms_history
builtin_sources += plugins/smshistory.c builtin_sources += plugins/smshistory.c
builtin_modules += allowed_apns
builtin_sources += plugins/allowed-apns.c
sbin_PROGRAMS = src/ofonod 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/main.c src/ofono.h src/log.c src/plugin.c \
src/modem.c src/common.h src/common.c \ src/modem.c src/common.h src/common.c \
src/manager.c src/dbus.c src/util.h src/util.c \ src/manager.c src/dbus.c src/util.h src/util.c \
@@ -654,7 +675,8 @@ src_ofonod_SOURCES = $(builtin_sources) src/ofono.ver \
src/cdma-provision.c src/handsfree.c \ src/cdma-provision.c src/handsfree.c \
src/handsfree-audio.c src/bluetooth.h \ src/handsfree-audio.c src/bluetooth.h \
src/sim-mnclength.c src/voicecallagent.c \ src/sim-mnclength.c src/voicecallagent.c \
src/hfp.h src/siri.c src/hfp.h src/siri.c \
src/netmon.c
src_ofonod_LDADD = gdbus/libgdbus-internal.la $(builtin_libadd) \ src_ofonod_LDADD = gdbus/libgdbus-internal.la $(builtin_libadd) \
@GLIB_LIBS@ @DBUS_LIBS@ -ldl @GLIB_LIBS@ @DBUS_LIBS@ -ldl
@@ -700,7 +722,9 @@ doc_files = doc/overview.txt doc/ofono-paper.txt doc/release-faq.txt \
doc/location-reporting-api.txt \ doc/location-reporting-api.txt \
doc/smshistory-api.txt doc/oemraw-api.txt \ doc/smshistory-api.txt doc/oemraw-api.txt \
doc/certification.txt doc/siri-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 \ test_scripts = test/backtrace \
@@ -798,7 +822,13 @@ test_scripts = test/backtrace \
test/set-msisdn \ test/set-msisdn \
test/test-voicecallagent \ test/test-voicecallagent \
test/get-network-time \ 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
if TEST if TEST
testdir = $(pkglibdir)/test testdir = $(pkglibdir)/test
@@ -816,12 +846,19 @@ unit_objects =
unit_tests = unit/test-common unit/test-util unit/test-idmap \ unit_tests = unit/test-common unit/test-util unit/test-idmap \
unit/test-simutil unit/test-stkutil \ unit/test-simutil unit/test-stkutil \
unit/test-sms unit/test-cdmasms \ unit/test-sms unit/test-cdmasms \
unit/test-grilrequest \
unit/test-grilreply \
unit/test-grilunsol \
unit/test-sms unit/test-cdmasms \
unit/test-provision 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
endif
endif
noinst_PROGRAMS = $(unit_tests) \ noinst_PROGRAMS = $(unit_tests) \
unit/test-sms-root unit/test-mux unit/test-caif unit/test-sms-root unit/test-mux unit/test-caif
@@ -872,21 +909,6 @@ unit_test_caif_SOURCES = unit/test-caif.c $(gatchat_sources) \
unit_test_caif_LDADD = @GLIB_LIBS@ unit_test_caif_LDADD = @GLIB_LIBS@
unit_objects += $(unit_test_caif_OBJECTS) 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 \ unit_test_provision_SOURCES = unit/test-provision.c \
plugins/provision.h plugins/provision.c \ plugins/provision.h plugins/provision.c \
plugins/mbpi.c src/gprs-provision.c \ plugins/mbpi.c src/gprs-provision.c \
@@ -894,6 +916,39 @@ unit_test_provision_SOURCES = unit/test-provision.c \
unit_test_provision_LDADD = @GLIB_LIBS@ -ldl unit_test_provision_LDADD = @GLIB_LIBS@ -ldl
unit_objects += $(unit_test_provision_OBJECTS) unit_objects += $(unit_test_provision_OBJECTS)
if RILMODEM
if JOLLA_RILMODEM
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 \
src/simutil.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)
endif
endif
TESTS = $(unit_tests) TESTS = $(unit_tests)
if TOOLS if TOOLS

View File

@@ -256,6 +256,16 @@ Voicecall
Priority: Medium Priority: Medium
Complexity: C1 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 Sim Toolkit
=========== ===========

View File

@@ -1,5 +1,5 @@
AC_PREREQ(2.60) AC_PREREQ(2.60)
AC_INIT(ofono, 1.17) AC_INIT(ofono, 1.18)
AM_INIT_AUTOMAKE([foreign subdir-objects color-tests]) AM_INIT_AUTOMAKE([foreign subdir-objects color-tests])
AC_CONFIG_HEADERS(config.h) AC_CONFIG_HEADERS(config.h)
@@ -64,8 +64,8 @@ AC_CHECK_FUNC(signalfd, dummy=yes,
AC_CHECK_LIB(dl, dlopen, dummy=yes, AC_CHECK_LIB(dl, dlopen, dummy=yes,
AC_MSG_ERROR(dynamic linking loader is required)) AC_MSG_ERROR(dynamic linking loader is required))
PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.28, dummy=yes, PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.32, dummy=yes,
AC_MSG_ERROR(GLib >= 2.28 is required)) AC_MSG_ERROR(GLib >= 2.32 is required))
AC_SUBST(GLIB_CFLAGS) AC_SUBST(GLIB_CFLAGS)
AC_SUBST(GLIB_LIBS) AC_SUBST(GLIB_LIBS)
@@ -238,6 +238,11 @@ if (test "${enable_provision}" != "no"); then
fi fi
AM_CONDITIONAL(PROVISION, test "${enable_provision}" != "no") 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], AC_ARG_ENABLE(datafiles, AC_HELP_STRING([--disable-datafiles],
[do not install configuration and data files]), [do not install configuration and data files]),
[enable_datafiles=${enableval}]) [enable_datafiles=${enableval}])

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). GPRS service registration (if known).
Possible values are: Possible values are:
"none", "gsm", "edge", "umts", "hsdpa", "hsupa", "none", "gprs", "edge", "umts", "hsdpa", "hsupa",
"hspa" (HSDPA and HSUPA at the same time) and "hspa" (HSDPA and HSUPA at the same time) and
"lte" "lte"

View File

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

View File

@@ -90,6 +90,11 @@ Properties boolean Powered [readwrite]
"hfp") this corresponds to the Bluetooth Device "hfp") this corresponds to the Bluetooth Device
Address of the remote device. Address of the remote device.
string SoftwareVersionNumber [readonly, optional]
String representing the software version number of the
modem device.
array{string} Features [readonly] array{string} Features [readonly]
List of currently enabled features. It uses simple 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 { struct gprs_data {
GAtChat *chat; GAtChat *chat;
unsigned int vendor; unsigned int vendor;
unsigned int last_auto_context_id;
}; };
static void at_cgatt_cb(gboolean ok, GAtResult *result, gpointer user_data) 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); 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) static void cgreg_notify(GAtResult *result, gpointer user_data)
{ {
struct ofono_gprs *gprs = 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) static void cgev_notify(GAtResult *result, gpointer user_data)
{ {
struct ofono_gprs *gprs = user_data; struct ofono_gprs *gprs = user_data;
struct gprs_data *gd = ofono_gprs_get_data(gprs);
GAtResultIter iter; GAtResultIter iter;
const char *event; const char *event;
@@ -172,6 +216,11 @@ static void cgev_notify(GAtResult *result, gpointer user_data)
g_str_equal(event, "ME DETACH")) { g_str_equal(event, "ME DETACH")) {
ofono_gprs_detached_notify(gprs); ofono_gprs_detached_notify(gprs);
return; 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: case 5:
bearer = 4; bearer = 4;
break; break;
case 7:
/* XXX: reserved - assume none. */
bearer = 0;
break;
case 8: case 8:
bearer = 1; bearer = 1;
break; break;
@@ -355,6 +400,7 @@ static void gprs_initialized(gboolean ok, GAtResult *result, gpointer user_data)
FALSE, gprs, NULL); FALSE, gprs, NULL);
break; break;
case OFONO_VENDOR_UBLOX: case OFONO_VENDOR_UBLOX:
case OFONO_VENDOR_UBLOX_TOBY_L2:
g_at_chat_register(gd->chat, "+UREG:", ublox_ureg_notify, g_at_chat_register(gd->chat, "+UREG:", ublox_ureg_notify,
FALSE, gprs, NULL); FALSE, gprs, NULL);
g_at_chat_send(gd->chat, "AT+UREG=1", none_prefix, 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, static ofono_bool_t build_cmer_string(char *buf, int *cmer_opts,
struct netreg_data *nd) struct netreg_data *nd)
{ {
const char *mode; const char *ind;
int len = sprintf(buf, "AT+CMER="); int len = sprintf(buf, "AT+CMER=");
const char *mode;
DBG(""); 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; * Forward unsolicited result codes directly to the TE;
* TATE link specific inband technique used to embed result codes and * TATE link specific inband technique used to embed result codes and
* data when TA is in online data mode * 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; return FALSE;
/* No keypad event reporting */ /* 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. * Telit does not support mode 1.
* All indicator events shall be directed from TA to TE. * All indicator events shall be directed from TA to TE.
*/ */
mode = "2"; ind = "2";
break; break;
default: default:
/* /*
* Only those indicator events, which are not caused by +CIND * Only those indicator events, which are not caused by +CIND
* shall be indicated by the TA to the TE. * shall be indicated by the TA to the TE.
*/ */
mode = "1"; ind = "1";
break; 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) * <ind> indicates the indicator order number (as specified for +CIND)
* and <value> is the new value of indicator. * 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 FALSE;
return TRUE; return TRUE;

View File

@@ -1120,6 +1120,7 @@ static void at_pin_retries_query(struct ofono_sim *sim,
return; return;
break; break;
case OFONO_VENDOR_UBLOX: case OFONO_VENDOR_UBLOX:
case OFONO_VENDOR_UBLOX_TOBY_L2:
if (g_at_chat_send(sd->chat, "AT+UPINCNT", upincnt_prefix, if (g_at_chat_send(sd->chat, "AT+UPINCNT", upincnt_prefix,
upincnt_cb, cbd, g_free) > 0) upincnt_cb, cbd, g_free) > 0)
return; return;

View File

@@ -45,5 +45,6 @@ enum ofono_vendor {
OFONO_VENDOR_ALCATEL, OFONO_VENDOR_ALCATEL,
OFONO_VENDOR_QUECTEL, OFONO_VENDOR_QUECTEL,
OFONO_VENDOR_UBLOX, OFONO_VENDOR_UBLOX,
OFONO_VENDOR_UBLOX_TOBY_L2,
OFONO_VENDOR_CINTERION, 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_full(vd->calls, g_free);
g_slist_free(vd->calls);
vd->calls = calls; vd->calls = calls;
@@ -1147,8 +1146,7 @@ static void at_voicecall_remove(struct ofono_voicecall *vc)
if (vd->vts_source) if (vd->vts_source)
g_source_remove(vd->vts_source); g_source_remove(vd->vts_source);
g_slist_foreach(vd->calls, (GFunc) g_free, NULL); g_slist_free_full(vd->calls, g_free);
g_slist_free(vd->calls);
ofono_voicecall_set_data(vc, NULL); 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); ofono_voicecall_mpty_hint(vc, mpty_ids);
g_slist_foreach(vd->calls, (GFunc) g_free, NULL); g_slist_free_full(vd->calls, g_free);
g_slist_free(vd->calls);
vd->calls = calls; vd->calls = calls;
@@ -709,6 +708,15 @@ static void ccwa_notify(GAtResult *result, gpointer user_data)
int num_type, validity; int num_type, validity;
struct ofono_call *call; 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 */ /* CCWA can repeat, ignore if we already have an waiting call */
if (g_slist_find_custom(vd->calls, if (g_slist_find_custom(vd->calls,
GINT_TO_POINTER(CALL_STATUS_WAITING), 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, vd->clcc_source = g_timeout_add(POLL_CLCC_DELAY,
poll_clcc, vc); 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) if (vd->expect_release_source)
g_source_remove(vd->expect_release_source); g_source_remove(vd->expect_release_source);
g_slist_foreach(vd->calls, (GFunc) g_free, NULL); g_slist_free_full(vd->calls, g_free);
g_slist_free(vd->calls);
ofono_voicecall_set_data(vc, NULL); ofono_voicecall_set_data(vc, NULL);

View File

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

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

View File

@@ -302,7 +302,12 @@ static struct ril_data_call *ril_data_call_parse(int version, GRilIoParser *rilp
if (version >= 9) { if (version >= 9) {
/* PCSCF */ /* PCSCF */
grilio_parser_skip_string(rilp); grilio_parser_skip_string(rilp);
if (version >= 11) {
/*
* All known rils that report version 10 are using
* RIL_Data_Call_Response_v11 (FairPhone 2, Nexus 4)
*/
if (version >= 10) {
/* MTU */ /* MTU */
grilio_parser_get_int32(rilp, &call->mtu); grilio_parser_get_int32(rilp, &call->mtu);
} }

View File

@@ -42,7 +42,7 @@ struct ril_gprs_context {
struct ril_network *network; struct ril_network *network;
struct ril_data *data; struct ril_data *data;
guint active_ctx_cid; guint active_ctx_cid;
gulong calls_changed_event_id; gulong calls_changed_id;
struct ril_mtu_watch *mtu_watch; struct ril_mtu_watch *mtu_watch;
struct ril_data_call *active_call; struct ril_data_call *active_call;
struct ril_gprs_context_call activate; 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); 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) { if (bits) {
const char *suffix = strchr(address, '/'); int nbits = atoi(bits);
if (suffix) { if (nbits > 0 && nbits < 33) {
int nbits = atoi(suffix + 1); const char* str;
if (nbits > 0 && nbits < 33) { struct in_addr in;
const char* str; in.s_addr = htonl((nbits == 32) ? 0xffffffff :
struct in_addr in;
in.s_addr = htonl((nbits == 32) ? 0xffffffff :
((1 << nbits)-1) << (32-nbits)); ((1 << nbits)-1) << (32-nbits));
str = inet_ntoa(in); str = inet_ntoa(in);
if (str) { if (str) {
return g_strdup(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, static int ril_gprs_context_address_family(const char *addr)
char * const *ip_addr)
{ {
const guint n = gutil_strv_length(ip_addr); if (strchr(addr, ':')) {
return AF_INET6;
if (n > 0) { } else if (strchr(addr, '.')) {
ofono_gprs_context_set_ipv4_address(gc, ip_addr[0], TRUE); return AF_INET;
if (n > 1) { } else {
ofono_gprs_context_set_ipv4_netmask(gc, ip_addr[1]); return AF_UNSPEC;
}
}
}
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);
}
}
} }
} }
@@ -111,9 +90,9 @@ static void ril_gprs_context_free_active_call(struct ril_gprs_context *gcd)
ril_data_call_free(gcd->active_call); ril_data_call_free(gcd->active_call);
gcd->active_call = NULL; gcd->active_call = NULL;
} }
if (gcd->calls_changed_event_id) { if (gcd->calls_changed_id) {
ril_data_remove_handler(gcd->data, gcd->calls_changed_event_id); ril_data_remove_handler(gcd->data, gcd->calls_changed_id);
gcd->calls_changed_event_id = 0; gcd->calls_changed_id = 0;
} }
if (gcd->mtu_watch) { if (gcd->mtu_watch) {
ril_mtu_watch_free(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, static void ril_gprs_context_set_address(struct ofono_gprs_context *gc,
char ***split_ip_addr, const struct ril_data_call *call)
char ***split_ipv6_addr)
{ {
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; int i;
*split_ipv6_addr = *split_ip_addr = NULL; for (i = 0; i < n && (!ipv6_addr || !ip_addr); i++) {
for (i = 0; i < n && (!*split_ipv6_addr || !*split_ip_addr); i++) { const char *addr = list[i];
const char *addr = ip_array[i]; switch (ril_gprs_context_address_family(addr)) {
switch (ril_address_family(addr)) {
case AF_INET: case AF_INET:
if (!*split_ip_addr) { if (!ip_addr) {
char *mask = ril_gprs_context_netmask(addr); const char* s = strstr(addr, "/");
*split_ip_addr = g_strsplit(addr, "/", 2); if (s) {
if (gutil_strv_length(*split_ip_addr) == 2) { const gsize len = s - addr;
g_free((*split_ip_addr)[1]); tmp_ip_addr = g_strndup(addr, len);
(*split_ip_addr)[1] = mask; ip_addr = tmp_ip_addr;
ip_mask = ril_gprs_context_netmask(s+1);
} else { } else {
/* This is rather unlikely to happen */ ip_addr = addr;
*split_ip_addr = }
gutil_strv_add(*split_ip_addr, if (!ip_mask) {
mask); ip_mask = g_strdup("255.255.255.0");
g_free(mask);
} }
} }
break; break;
case AF_INET6: case AF_INET6:
if (!*split_ipv6_addr) { if (!ipv6_addr) {
*split_ipv6_addr = g_strsplit(addr, "/", 2); 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, static void ril_gprs_context_set_gateway(struct ofono_gprs_context *gc,
char **ipv6_gw) 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; int i;
*ip_gw = *ipv6_gw = NULL; /* Pick 1 gw for each protocol*/
for (i = 0; i < n && (!*ipv6_gw || !*ip_gw); i++) { for (i = 0; i < n && (!ipv6_gw || !ip_gw); i++) {
const char *gw_addr = gw_array[i]; const char *addr = list[i];
switch (ril_address_family(gw_addr)) { switch (ril_gprs_context_address_family(addr)) {
case AF_INET: case AF_INET:
if (!*ip_gw) *ip_gw = g_strdup(gw_addr); if (!ip_gw) ip_gw = addr;
break; break;
case AF_INET6: case AF_INET6:
if (!*ipv6_gw) *ipv6_gw = g_strdup(gw_addr); if (!ipv6_gw) ipv6_gw = addr;
break; 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, static void ril_gprs_context_set_dns_servers(struct ofono_gprs_context *gc,
char ***dns_ipv6_addr) const struct ril_data_call *call)
{ {
const int n = gutil_strv_length(dns_array);
int i; 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++) { for (i = 0; i < n; i++) {
const char *addr = dns_array[i]; const char *addr = list[i];
switch (ril_address_family(addr)) { switch (ril_gprs_context_address_family(addr)) {
case AF_INET: case AF_INET:
*dns_addr = gutil_strv_add(*dns_addr, addr); *ip_ptr++ = addr;
break; break;
case AF_INET6: case AF_INET6:
*dns_ipv6_addr = gutil_strv_add(*dns_ipv6_addr, addr); *ipv6_ptr++ = addr;
break; 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 */ /* 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 *c1,
const struct ril_data_call *c2) const struct ril_data_call *c2)
{ {
if (!c1 && !c2) { if (!c1 && !c2) {
return TRUE; return 0;
} else if (c1 && c2) { } else if (c1 && c2) {
return c1->cid == c2->cid && int changes = 0;
c1->active == c2->active && c1->prot == c2->prot &&
!g_strcmp0(c1->ifname, c2->ifname) && if (g_strcmp0(c1->ifname, c2->ifname)) {
gutil_strv_equal(c1->dnses, c2->dnses) && changes |= DATA_CALL_IFNAME_CHANGED;
gutil_strv_equal(c1->gateways, c2->gateways) && }
gutil_strv_equal(c1->addresses, c2->addresses);
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 { } 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; struct ril_data_call *prev_call = gcd->active_call;
const struct ril_data_call *call = const struct ril_data_call *call =
ril_data_call_find(data->data_calls, prev_call->cid); ril_data_call_find(data->data_calls, prev_call->cid);
int change = 0;
if (call) { if (call && call->active != RIL_DATA_CALL_INACTIVE) {
/* 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;
/* Compare it against the last known state */ /* Compare it against the last known state */
} else if (ril_gprs_context_data_call_equal(call, prev_call)) { change = ril_gprs_context_data_call_change(call, prev_call);
DBG("call %u didn't change", call->cid);
call = NULL;
} else {
DBG("call %u changed", call->cid);
}
} else { } else {
ofono_error("Clearing active context"); ofono_error("Clearing active context");
ril_gprs_context_set_disconnected(gcd); ril_gprs_context_set_disconnected(gcd);
call = NULL;
} }
if (!call) { if (!call) {
/* We are not interested */ /* We are not interested */
return; 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); ofono_info("data call status: %d", call->status);
} }
if (call->active == RIL_DATA_CALL_ACTIVE) { if (change & DATA_CALL_IFNAME_CHANGED) {
gboolean signal = FALSE; DBG("interface changed");
ofono_gprs_context_set_interface(gc, call->ifname);
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_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); ril_data_call_free(prev_call);
} }
@@ -425,12 +388,6 @@ static void ril_gprs_context_activate_primary_cb(struct ril_data *data,
struct ril_gprs_context *gcd = user_data; struct ril_gprs_context *gcd = user_data;
struct ofono_gprs_context *gc = gcd->gc; struct ofono_gprs_context *gc = gcd->gc;
struct ofono_error error; 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; ofono_gprs_context_cb_t cb;
gpointer cb_data; gpointer cb_data;
@@ -438,80 +395,40 @@ static void ril_gprs_context_activate_primary_cb(struct ril_data *data,
if (ril_status != RIL_E_SUCCESS) { if (ril_status != RIL_E_SUCCESS) {
ofono_error("GPRS context: Reply failure: %s", ofono_error("GPRS context: Reply failure: %s",
ril_error_to_string(ril_status)); ril_error_to_string(ril_status));
goto done; } else if (call->status != PDP_FAIL_NONE) {
}
if (call->status != PDP_FAIL_NONE) {
ofono_error("Unexpected data call status %d", call->status); ofono_error("Unexpected data call status %d", call->status);
error.type = OFONO_ERROR_TYPE_CMS; error.type = OFONO_ERROR_TYPE_CMS;
error.error = call->status; error.error = call->status;
goto done; } else if (!call->ifname) {
} /* Must have interface */
/* Must have interface */
if (!call->ifname) {
ofono_error("GPRS context: No 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);
} }
ofono_info("setting up data call"); if (error.type != OFONO_ERROR_TYPE_NO_ERROR) {
gcd->active_ctx_cid = CTX_ID_NONE;
/* 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;
} }
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 = gcd->activate.cb;
cb_data = gcd->activate.data; cb_data = gcd->activate.data;
GASSERT(gcd->activate.req); GASSERT(gcd->activate.req);
memset(&gcd->activate, 0, sizeof(gcd->activate)); memset(&gcd->activate, 0, sizeof(gcd->activate));
if (cb) { if (cb) {
if (error.type != OFONO_ERROR_TYPE_NO_ERROR) {
gcd->active_ctx_cid = CTX_ID_NONE;
}
cb(&error, cb_data); cb(&error, cb_data);
} }
} }
@@ -654,7 +571,7 @@ static void ril_gprs_context_remove(struct ofono_gprs_context *gc)
NULL, NULL); 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_data_unref(gcd->data);
ril_network_unref(gcd->network); ril_network_unref(gcd->network);
ril_data_call_free(gcd->active_call); ril_data_call_free(gcd->active_call);

View File

@@ -18,6 +18,7 @@
#include "ril_radio.h" #include "ril_radio.h"
#include "ril_sim_card.h" #include "ril_sim_card.h"
#include "ril_sim_settings.h" #include "ril_sim_settings.h"
#include "ril_cell_info.h"
#include "ril_data.h" #include "ril_data.h"
#include "ril_util.h" #include "ril_util.h"
#include "ril_log.h" #include "ril_log.h"
@@ -300,6 +301,7 @@ static void ril_modem_post_online(struct ofono_modem *modem)
ofono_netreg_create(modem, 0, RILMODEM_DRIVER, md); ofono_netreg_create(modem, 0, RILMODEM_DRIVER, md);
ofono_ussd_create(modem, 0, RILMODEM_DRIVER, md); ofono_ussd_create(modem, 0, RILMODEM_DRIVER, md);
ofono_call_settings_create(modem, 0, RILMODEM_DRIVER, md); ofono_call_settings_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, static void ril_modem_set_online(struct ofono_modem *modem, ofono_bool_t online,
@@ -398,6 +400,7 @@ static void ril_modem_remove(struct ofono_modem *ofono)
ril_network_unref(modem->network); ril_network_unref(modem->network);
ril_sim_card_unref(modem->sim_card); ril_sim_card_unref(modem->sim_card);
ril_sim_settings_unref(modem->sim_settings); ril_sim_settings_unref(modem->sim_settings);
ril_cell_info_unref(modem->cell_info);
ril_data_unref(modem->data); ril_data_unref(modem->data);
grilio_channel_unref(modem->io); grilio_channel_unref(modem->io);
grilio_queue_cancel_all(md->q, FALSE); grilio_queue_cancel_all(md->q, FALSE);
@@ -410,7 +413,8 @@ static void ril_modem_remove(struct ofono_modem *ofono)
struct ril_modem *ril_modem_create(GRilIoChannel *io, const char *log_prefix, struct ril_modem *ril_modem_create(GRilIoChannel *io, const char *log_prefix,
const struct ril_slot_info *slot, struct ril_radio *radio, const struct ril_slot_info *slot, struct ril_radio *radio,
struct ril_network *network, struct ril_sim_card *card, 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" */ /* Skip the slash from the path, it looks like "/ril_0" */
struct ofono_modem *ofono = ofono_modem_create(slot->path + 1, struct ofono_modem *ofono = ofono_modem_create(slot->path + 1,
@@ -438,6 +442,7 @@ struct ril_modem *ril_modem_create(GRilIoChannel *io, const char *log_prefix,
modem->network = ril_network_ref(network); modem->network = ril_network_ref(network);
modem->sim_card = ril_sim_card_ref(card); modem->sim_card = ril_sim_card_ref(card);
modem->sim_settings = ril_sim_settings_ref(settings); modem->sim_settings = ril_sim_settings_ref(settings);
modem->cell_info = ril_cell_info_ref(cell_info);
modem->data = ril_data_ref(data); modem->data = ril_data_ref(data);
modem->io = grilio_channel_ref(io); modem->io = grilio_channel_ref(io);
md->q = grilio_queue_new(io); md->q = grilio_queue_new(io);

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

@@ -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 * supply some reasonable default. We don't need more than 2
* simultaneous data calls anyway. * simultaneous data calls anyway.
*/ */
if (nparams <= 5) { if (reg->max_calls < 1) {
reg->max_calls = 2; reg->max_calls = 2;
} }
@@ -753,6 +753,7 @@ struct ril_network *ril_network_new(GRilIoChannel *io, const char *log_prefix,
* Query the initial state. Querying network state before the radio * Query the initial state. Querying network state before the radio
* has been turned on makes RIL unhappy. * has been turned on makes RIL unhappy.
*/ */
ril_network_query_pref_mode(self);
if (radio->state == RADIO_STATE_ON) { if (radio->state == RADIO_STATE_ON) {
ril_network_poll_state(self); ril_network_poll_state(self);
} }

View File

@@ -820,7 +820,7 @@ static void ril_plugin_create_modem(struct ril_slot *slot)
modem = ril_modem_create(slot->io, ril_plugin_log_prefix(slot), modem = ril_modem_create(slot->io, ril_plugin_log_prefix(slot),
&slot->pub, slot->radio, slot->network, slot->sim_card, &slot->pub, slot->radio, slot->network, slot->sim_card,
slot->data, slot->sim_settings); slot->data, slot->sim_settings, slot->cell_info);
if (modem) { if (modem) {
struct ofono_sim *sim = ril_modem_ofono_sim(modem); struct ofono_sim *sim = ril_modem_ofono_sim(modem);
@@ -1659,6 +1659,7 @@ static int ril_plugin_init(void)
ofono_modem_driver_register(&ril_modem_driver); ofono_modem_driver_register(&ril_modem_driver);
ofono_sim_driver_register(&ril_sim_driver); ofono_sim_driver_register(&ril_sim_driver);
ofono_sms_driver_register(&ril_sms_driver); ofono_sms_driver_register(&ril_sms_driver);
ofono_netmon_driver_register(&ril_netmon_driver);
ofono_netreg_driver_register(&ril_netreg_driver); ofono_netreg_driver_register(&ril_netreg_driver);
ofono_devinfo_driver_register(&ril_devinfo_driver); ofono_devinfo_driver_register(&ril_devinfo_driver);
ofono_voicecall_driver_register(&ril_voicecall_driver); ofono_voicecall_driver_register(&ril_voicecall_driver);
@@ -1706,6 +1707,7 @@ static void ril_plugin_exit(void)
ofono_sim_driver_unregister(&ril_sim_driver); ofono_sim_driver_unregister(&ril_sim_driver);
ofono_sms_driver_unregister(&ril_sms_driver); ofono_sms_driver_unregister(&ril_sms_driver);
ofono_devinfo_driver_unregister(&ril_devinfo_driver); ofono_devinfo_driver_unregister(&ril_devinfo_driver);
ofono_netmon_driver_unregister(&ril_netmon_driver);
ofono_netreg_driver_unregister(&ril_netreg_driver); ofono_netreg_driver_unregister(&ril_netreg_driver);
ofono_voicecall_driver_unregister(&ril_voicecall_driver); ofono_voicecall_driver_unregister(&ril_voicecall_driver);
ofono_call_barring_driver_unregister(&ril_call_barring_driver); ofono_call_barring_driver_unregister(&ril_call_barring_driver);

View File

@@ -35,6 +35,7 @@
#include <ofono/stk.h> #include <ofono/stk.h>
#include <ofono/ussd.h> #include <ofono/ussd.h>
#include <ofono/voicecall.h> #include <ofono/voicecall.h>
#include <ofono/netmon.h>
#include <grilio_queue.h> #include <grilio_queue.h>
#include <grilio_request.h> #include <grilio_request.h>
@@ -75,6 +76,7 @@ struct ril_modem {
struct ril_network *network; struct ril_network *network;
struct ril_sim_card *sim_card; struct ril_sim_card *sim_card;
struct ril_sim_settings *sim_settings; struct ril_sim_settings *sim_settings;
struct ril_cell_info *cell_info;
struct ril_slot_config config; struct ril_slot_config config;
}; };
@@ -125,7 +127,8 @@ void ril_plugin_dbus_signal_sim(struct ril_plugin_dbus *dbus, int index,
struct ril_modem *ril_modem_create(GRilIoChannel *io, const char *log_prefix, struct ril_modem *ril_modem_create(GRilIoChannel *io, const char *log_prefix,
const struct ril_slot_info *slot, struct ril_radio *radio, const struct ril_slot_info *slot, struct ril_radio *radio,
struct ril_network *network, struct ril_sim_card *card, 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); void ril_modem_delete(struct ril_modem *modem);
struct ofono_sim *ril_modem_ofono_sim(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); struct ofono_gprs *ril_modem_ofono_gprs(struct ril_modem *modem);
@@ -160,6 +163,7 @@ extern const struct ofono_sms_driver ril_sms_driver;
extern const struct ofono_stk_driver ril_stk_driver; extern const struct ofono_stk_driver ril_stk_driver;
extern const struct ofono_ussd_driver ril_ussd_driver; extern const struct ofono_ussd_driver ril_ussd_driver;
extern const struct ofono_voicecall_driver ril_voicecall_driver; extern const struct ofono_voicecall_driver ril_voicecall_driver;
extern const struct ofono_netmon_driver ril_netmon_driver;
#endif /* RIL_PLUGIN_H */ #endif /* RIL_PLUGIN_H */

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. */ /* Returns enum access_technology or -1 on failure. */
int ril_parse_tech(const char *stech, int *ril_tech) int ril_parse_tech(const char *stech, int *ril_tech)
{ {

View File

@@ -25,7 +25,6 @@ const char *ril_request_to_string(guint request);
const char *ril_unsol_event_to_string(guint event); const char *ril_unsol_event_to_string(guint event);
const char *ril_radio_state_to_string(int radio_state); const char *ril_radio_state_to_string(int radio_state);
int ril_parse_tech(const char *stech, int *ril_tech); 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); gboolean ril_parse_mcc_mnc(const char *str, struct ofono_network_operator *op);
#define ril_error_init_ok(err) \ #define ril_error_init_ok(err) \

View File

@@ -4,6 +4,7 @@
* *
* Copyright (C) 2014 Jolla Ltd * Copyright (C) 2014 Jolla Ltd
* Contact: Miia Leinonen * Contact: Miia Leinonen
* Copyright (C) 2014 Canonical Ltd
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
@@ -20,65 +21,63 @@
* *
*/ */
#include <errno.h>
#include <glib.h> #include <glib.h>
#include <ofono/log.h> #include <ofono/log.h>
#include <ofono/modem.h> #include <ofono/modem.h>
#include <ofono/call-barring.h>
#include "common.h" #include "common.h"
#include "gril.h" #include "gril.h"
#include "call-barring.h"
#include "rilmodem.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 { struct barring_data {
GRil *ril; 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, static void ril_call_barring_query_cb(struct ril_msg *message,
gpointer user_data) gpointer user_data)
{ {
struct cb_data *cbd = user_data; struct cb_data *cbd = user_data;
struct parcel rilp;
struct ofono_error error;
ofono_call_barring_query_cb_t cb = cbd->cb; 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) { if (message->error != RIL_E_SUCCESS)
ofono_error("Call Barring query failed, err: %i", goto error;
message->error);
decode_ril_error(&error, "FAIL");
goto out;
}
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); 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: g_ril_append_print_buf(bd->ril, "{%d}", bearer_class);
cb(&error, bearer_class, cbd->data); 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, 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) void *data)
{ {
struct barring_data *bd = ofono_call_barring_get_data(cb); 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; struct parcel rilp;
int ret = 0; char svcs_str[4];
char cls_textual[RIL_MAX_SERVICE_LENGTH];
DBG("lock: %s, services to query: %i", lock, cls); DBG("lock: %s, services to query: %d", lock, cls);
/* FIXUP_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;
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_init(&rilp);
parcel_w_int32(&rilp, RIL_QUERY_STRING_COUNT); /* Nbr of strings */ parcel_w_int32(&rilp, 4); /* # of strings */
parcel_w_string(&rilp, (char *) lock); /* Facility code */ parcel_w_string(&rilp, lock);
parcel_w_int32(&rilp, RIL_LENGTH_ZERO); /* Password length */ parcel_w_string(&rilp, ""); /* Password is empty when not needed */
parcel_w_string(&rilp, (char *) cls_textual); snprintf(svcs_str, sizeof(svcs_str), "%d", cls);
parcel_w_string(&rilp, NULL); /* AID (for FDN, not yet supported) */ 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, g_ril_append_print_buf(bd->ril, "(%s,\"\",%s,(null))",
rilp.data, rilp.size, ril_call_barring_query_cb, lock, svcs_str);
cbd, g_free);
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) { g_free(cbd);
ofono_error("Sending Call Barring query failed, err: %i", ret); 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) static void ril_call_barring_set_cb(struct ril_msg *message, gpointer user_data)
{ {
struct cb_data *cbd = user_data; struct cb_data *cbd = user_data;
struct ofono_error error;
ofono_call_barring_set_cb_t cb = cbd->cb; 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) { if (message->error != RIL_E_SUCCESS)
ofono_error("Call Barring Set request failed, err: %i", goto error;
message->error);
decode_ril_error(&error, "FAIL");
goto out;
}
decode_ril_error(&error, "OK"); g_ril_init_parcel(message, &rilp);
out: /* mako reply has no payload for call barring */
cb(&error, cbd->data); 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, 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) void *data)
{ {
struct barring_data *bd = ofono_call_barring_get_data(cb); 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; struct parcel rilp;
int ret = 0; char svcs_str[4];
char cls_textual[RIL_MAX_SERVICE_LENGTH];
DBG("lock: %s, enable: %i, bearer class: %i", lock, enable, cls); DBG("lock: %s, enable: %d, bearer class: %d", lock, enable, cls);
/* FIXUP_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;
sprintf(cls_textual, "%d", cls);
/* See 3GPP 27.007 7.4 for parameter descriptions */
parcel_init(&rilp); parcel_init(&rilp);
parcel_w_int32(&rilp, RIL_SET_STRING_COUNT); /* Nbr of strings */ parcel_w_int32(&rilp, 5); /* # of strings */
parcel_w_string(&rilp, (char *) lock); /* Facility code */ parcel_w_string(&rilp, lock);
parcel_w_string(&rilp, enable ? "1" : "0");
if (enable) parcel_w_string(&rilp, passwd);
parcel_w_string(&rilp, RIL_FACILITY_LOCK); snprintf(svcs_str, sizeof(svcs_str), "%d", cls);
else parcel_w_string(&rilp, svcs_str);
parcel_w_string(&rilp, RIL_FACILITY_UNLOCK);
parcel_w_string(&rilp, (char *) passwd);
parcel_w_string(&rilp, (char *) cls_textual);
parcel_w_string(&rilp, NULL); /* AID (for FDN, not yet supported) */ parcel_w_string(&rilp, NULL); /* AID (for FDN, not yet supported) */
ret = g_ril_send(bd->ril, RIL_REQUEST_SET_FACILITY_LOCK, g_ril_append_print_buf(bd->ril, "(%s,%s,%s,%s,(null))",
rilp.data, rilp.size, ril_call_barring_set_cb, lock, enable ? "1" : "0", passwd, svcs_str);
cbd, g_free);
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) { g_free(cbd);
ofono_error("Sending Call Barring Set request failed, err: %i", CALLBACK_WITH_FAILURE(callback, data);
ret);
g_free(cbd);
CALLBACK_WITH_FAILURE(callback, data);
}
} }
static void ril_call_barring_set_passwd_cb(struct ril_msg *message, static void ril_call_barring_set_passwd_cb(struct ril_msg *message,
gpointer user_data) gpointer user_data)
{ {
struct cb_data *cbd = user_data; struct cb_data *cbd = user_data;
struct ofono_error error;
ofono_call_barring_set_cb_t cb = cbd->cb; ofono_call_barring_set_cb_t cb = cbd->cb;
struct barring_data *bd = cbd->user;
if (message->error != RIL_E_SUCCESS) { if (message->error != RIL_E_SUCCESS) {
ofono_error("Call Barring Set PW req failed, err: %i", ofono_error("%s: set password failed, err: %s", __func__,
message->error); ril_error_to_string(message->error));
decode_ril_error(&error, "FAIL"); goto error;
goto out;
} }
decode_ril_error(&error, "OK"); g_ril_print_response_no_args(bd->ril, message);
out: CALLBACK_WITH_SUCCESS(cb, cbd->data);
cb(&error, cbd->data); return;
error:
CALLBACK_WITH_FAILURE(cb, cbd->data);
} }
static void ril_call_barring_set_passwd(struct ofono_call_barring *barr, 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) void *data)
{ {
struct barring_data *bd = ofono_call_barring_get_data(barr); 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; struct parcel rilp;
int ret = 0;
DBG(""); DBG("lock %s old %s new %s", lock, old_passwd, new_passwd);
parcel_init(&rilp); 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, parcel_w_int32(&rilp, 3); /* # of strings */
rilp.data, rilp.size, ril_call_barring_set_passwd_cb, parcel_w_string(&rilp, lock);
cbd, g_free); 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) { if (g_ril_send(bd->ril, RIL_REQUEST_CHANGE_BARRING_PASSWORD, &rilp,
ofono_error("Sending Call Barring Set PW req failed, err: %i", ril_call_barring_set_passwd_cb, cbd, g_free) > 0)
ret); return;
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, data); g_free(cbd);
} CALLBACK_WITH_FAILURE(cb, data);
} }
static gboolean ril_delayed_register(gpointer user_data) static gboolean ril_delayed_register(gpointer user_data)
{ {
struct ofono_call_barring *cb = 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); ofono_call_barring_register(cb);
return FALSE; return FALSE;
@@ -270,10 +250,13 @@ static int ril_call_barring_probe(struct ofono_call_barring *cb,
{ {
GRil *ril = user; GRil *ril = user;
struct barring_data *bd = g_try_new0(struct barring_data, 1); struct barring_data *bd = g_try_new0(struct barring_data, 1);
if (bd == NULL)
return -ENOMEM;
bd->ril = g_ril_clone(ril); bd->ril = g_ril_clone(ril);
ofono_call_barring_set_data(cb, bd); 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; 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); struct barring_data *data = ofono_call_barring_get_data(cb);
ofono_call_barring_set_data(cb, NULL); ofono_call_barring_set_data(cb, NULL);
if (data->timer_id > 0)
g_source_remove(data->timer_id);
g_ril_unref(data->ril); g_ril_unref(data->ril);
g_free(data); g_free(data);
} }

View File

@@ -3,8 +3,9 @@
* oFono - Open Source Telephony * oFono - Open Source Telephony
* *
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved. * 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> * Contact: Jussi Kangas <jussi.kangas@tieto.com>
* Copyright (C) 2014 Canonical Ltd.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
@@ -35,39 +36,235 @@
#include <ofono/log.h> #include <ofono/log.h>
#include <ofono/modem.h> #include <ofono/modem.h>
#include <ofono/call-forwarding.h> #include <ofono/call-forwarding.h>
#include "common.h"
#include "gril.h" #include "gril.h"
#include "grilutil.h"
#include "rilmodem.h" #include "rilmodem.h"
#include "ril_constants.h"
#include "common.h"
struct forw_data { struct forw_data {
GRil *ril; GRil *ril;
guint timer_id; int last_cls;
}; };
enum call_forward_cmd { static void ril_query_call_fwd_cb(struct ril_msg *message, gpointer user_data)
CF_ACTION_DISABLE, {
CF_ACTION_ENABLE, struct cb_data *cbd = user_data;
CF_ACTION_UNUSED, struct forw_data *fd = ofono_call_forwarding_get_data(cbd->user);
CF_ACTION_REGISTRATION, ofono_call_forwarding_query_cb_t cb = cbd->cb;
CF_ACTION_ERASURE, 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) static void ril_set_forward_cb(struct ril_msg *message, gpointer user_data)
{ {
struct cb_data *cbd = user_data; struct cb_data *cbd = user_data;
ofono_call_forwarding_set_cb_t cb = cbd->cb; 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) if (message->error != RIL_E_SUCCESS) {
CALLBACK_WITH_SUCCESS(cb, cbd->data); ofono_error("%s: failed; rild error: %s", __func__,
else { ril_error_to_string(message->error));
ofono_error("CF setting failed");
CALLBACK_WITH_FAILURE(cb, cbd->data); 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, 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) void *data)
{ {
struct forw_data *fd = ofono_call_forwarding_get_data(cf); 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; struct parcel rilp;
int ret = 0;
ofono_info("cf registration"); FIXUP_CLS();
parcel_init(&rilp); parcel_init(&rilp);
parcel_w_int32(&rilp, CF_ACTION_REGISTRATION); parcel_w_int32(&rilp, 3); /* Registration: 3 */
parcel_w_int32(&rilp, type); 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, cls);
parcel_w_int32(&rilp, number->type); parcel_w_int32(&rilp, number->type);
parcel_w_string(&rilp, number->number);
parcel_w_string(&rilp, (char *) number->number);
parcel_w_int32(&rilp, time); parcel_w_int32(&rilp, time);
ret = g_ril_send(fd->ril, RIL_REQUEST_SET_CALL_FORWARD, g_ril_append_print_buf(fd->ril, "(action: 3, type: %d cls: %d "
rilp.data, rilp.size, ril_set_forward_cb, cbd, g_free); "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 (g_ril_send(fd->ril, RIL_REQUEST_SET_CALL_FORWARD,
if (ret <= 0) { &rilp, ril_set_forward_cb, cbd, g_free) > 0)
ofono_error("CF registration failed"); return;
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, data);
}
}
static void ril_send_forward_cmd(struct ofono_call_forwarding *cf, CALLBACK_WITH_FAILURE(cb, cbd->data);
int type, int cls, g_free(cbd);
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);
}
} }
static void ril_query(struct ofono_call_forwarding *cf, int type, int cls, 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) void *data)
{ {
struct forw_data *fd = ofono_call_forwarding_get_data(cf); 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; struct parcel rilp;
int ret = 0;
ofono_info("cf query"); FIXUP_CLS();
parcel_init(&rilp); parcel_init(&rilp);
parcel_w_int32(&rilp, 2); parcel_w_int32(&rilp, 2); /* Interrogation: 2 */
parcel_w_int32(&rilp, type); 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); parcel_w_int32(&rilp, cls);
APPEND_DUMMY_NUMBER();
APPEND_DUMMY_TIME();
/* Following 3 values have no real meaning in query g_ril_append_print_buf(fd->ril, "(action: 2, type: %d cls: %d "
* but apparently RIL expects them so fields need to "number type: %d number: %s time: %d)",
* be filled. Otherwise there is no response 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); CALLBACK_WITH_FAILURE(cb, 0, NULL, cbd->data);
g_free(cbd);
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);
}
} }
static gboolean ril_delayed_register(gpointer user_data) static gboolean ril_delayed_register(gpointer user_data)
{ {
struct ofono_call_forwarding *cf = 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); ofono_call_forwarding_register(cf);
return FALSE; return FALSE;
@@ -314,10 +345,23 @@ static int ril_call_forwarding_probe(struct ofono_call_forwarding *cf,
unsigned int vendor, void *user) unsigned int vendor, void *user)
{ {
GRil *ril = 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); fd->ril = g_ril_clone(ril);
ofono_call_forwarding_set_data(cf, fd); 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; 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); struct forw_data *data = ofono_call_forwarding_get_data(cf);
ofono_call_forwarding_set_data(cf, NULL); ofono_call_forwarding_set_data(cf, NULL);
if (data->timer_id > 0)
g_source_remove(data->timer_id);
g_ril_unref(data->ril); g_ril_unref(data->ril);
g_free(data); g_free(data);
} }
static struct ofono_call_forwarding_driver driver = { static struct ofono_call_forwarding_driver driver = {
.name = "rilmodem", .name = RILMODEM,
.probe = ril_call_forwarding_probe, .probe = ril_call_forwarding_probe,
.remove = ril_call_forwarding_remove, .remove = ril_call_forwarding_remove,
.erasure = ril_erasure, .erasure = ril_erasure,

View File

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

View File

@@ -3,7 +3,7 @@
* oFono - Open Source Telephony * oFono - Open Source Telephony
* *
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved. * 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 * 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 * it under the terms of the GNU General Public License version 2 as
@@ -34,19 +34,15 @@
#include <ofono/log.h> #include <ofono/log.h>
#include <ofono/modem.h> #include <ofono/modem.h>
#include <ofono/call-volume.h> #include <ofono/call-volume.h>
#include "gril.h"
#include "grilutil.h"
#include "common.h" #include "common.h"
#include "gril.h"
#include "rilmodem.h" #include "rilmodem.h"
#include "parcel.h"
struct cv_data { struct cv_data {
GRil *ril; GRil *ril;
unsigned int vendor; unsigned int vendor;
guint timer_id;
}; };
static void volume_mute_cb(struct ril_msg *message, gpointer user_data) 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, 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 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; struct parcel rilp;
int request = RIL_REQUEST_SET_MUTE;
int ret;
cbd->user = cvd;
DBG(""); DBG("muted: %d", muted);
parcel_init(&rilp); parcel_init(&rilp);
parcel_w_int32(&rilp, 1); parcel_w_int32(&rilp, 1);
parcel_w_int32(&rilp, muted); 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_append_print_buf(cvd->ril, "(%d)", muted);
g_ril_print_request(cvd->ril, ret, request);
if (ret <= 0) { if (g_ril_send(cvd->ril, RIL_REQUEST_SET_MUTE, &rilp,
ofono_error("Send RIL_REQUEST_SET_MUTE failed."); volume_mute_cb, cbd, g_free) > 0)
g_free(cbd); return;
CALLBACK_WITH_FAILURE(cb, data);
} g_free(cbd);
CALLBACK_WITH_FAILURE(cb, data);
} }
static void probe_mute_cb(struct ril_msg *message, gpointer user_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; struct parcel rilp;
int muted; int muted;
if (message->error != RIL_E_SUCCESS) { if (message->error != RIL_E_SUCCESS)
ofono_error("Could not retrive the ril mute state");
return; return;
}
ril_util_init_parcel(message, &rilp); g_ril_init_parcel(message, &rilp);
/*first item in int[] is len so let's skip that*/
/* skip length of int[] */
parcel_r_int32(&rilp); parcel_r_int32(&rilp);
muted = 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 ofono_call_volume *cv = user_data;
struct cv_data *cvd = ofono_call_volume_get_data(cv); 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, g_ril_send(cvd->ril, RIL_REQUEST_GET_MUTE, NULL,
probe_mute_cb, cv, NULL); probe_mute_cb, cv, NULL);
g_ril_print_request_no_args(cvd->ril, ret, request);
} }
static gboolean ril_delayed_register(gpointer user_data) static gboolean ril_delayed_register(gpointer user_data)
{ {
struct ofono_call_volume *cv = user_data; struct ofono_call_volume *cv = user_data;
struct cv_data *cvd = ofono_call_volume_get_data(cv);
DBG(""); DBG("");
cvd->timer_id = 0;
ofono_call_volume_register(cv); ofono_call_volume_register(cv);
/* Probe the mute state */ /* 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, static int ril_call_volume_probe(struct ofono_call_volume *cv,
unsigned int vendor, void *data) unsigned int vendor, void *data)
{ {
GRil *ril = data; GRil *ril = data;
struct cv_data *cvd; 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); 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 * ofono_call_volume_register() needs to be called after
* the driver has been set in ofono_call_volume_create(), * the driver has been set in ofono_call_volume_create(),
* which calls this function. Most other drivers make * which calls this function. Most other drivers make
* some kind of capabilities query to the modem, and then * some kind of capabilities query to the modem, and then
* call register in the callback; we use a timer instead. * 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; return 0;
} }
@@ -189,9 +166,6 @@ static void ril_call_volume_remove(struct ofono_call_volume *cv)
ofono_call_volume_set_data(cv, NULL); ofono_call_volume_set_data(cv, NULL);
if (cvd->timer_id > 0)
g_source_remove(cvd->timer_id);
g_ril_unref(cvd->ril); g_ril_unref(cvd->ril);
g_free(cvd); g_free(cvd);
} }

View File

@@ -1,159 +0,0 @@
/*
*
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. 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
* 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 <stdio.h>
#include <glib.h>
#include <ofono/log.h>
#include <ofono/modem.h>
#include <ofono/cbs.h>
#include "gril.h"
#include "grilutil.h"
#include "rilmodem.h"
#include "ril_constants.h"
struct cbs_data {
GRil *ril;
guint timer_id;
};
static void ril_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 reject
* incoming cb messages.
*/
CALLBACK_WITH_SUCCESS(cb, user_data);
}
static void ril_clear_topics(struct ofono_cbs *cbs,
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 parcel rilp;
ril_util_init_parcel(message, &rilp);
resp = parcel_r_string(&rilp);
memcpy(resp, pdu, strlen((char *)resp));
ofono_cbs_notify(cbs, pdu, strlen((char *)resp));
}
static gboolean ril_delayed_register(gpointer user_data)
{
struct ofono_cbs *cbs = user_data;
struct cbs_data *cd = ofono_cbs_get_data(cbs);
cd->timer_id = 0;
ofono_cbs_register(cbs);
g_ril_register(cd->ril, RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS,
ril_cbs_notify, cbs);
return FALSE;
}
static int ril_cbs_probe(struct ofono_cbs *cbs, unsigned int vendor,
void *user)
{
GRil *ril = user;
struct cbs_data *cd = g_try_new0(struct cbs_data, 1);
cd->ril = g_ril_clone(ril);
ofono_cbs_set_data(cbs, cd);
cd->timer_id = g_timeout_add_seconds(2, ril_delayed_register, cbs);
return 0;
}
static void ril_cbs_remove(struct ofono_cbs *cbs)
{
struct cbs_data *cd = 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);
}
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
};
void ril_cbs_init(void)
{
ofono_cbs_driver_register(&driver);
}
void ril_cbs_exit(void)
{
ofono_cbs_driver_unregister(&driver);
}

View File

@@ -3,8 +3,7 @@
* oFono - Open Source Telephony - RIL Modem Support * oFono - Open Source Telephony - RIL Modem Support
* *
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved. * 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 * 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 * it under the terms of the GNU General Public License version 2 as
@@ -41,150 +40,165 @@
#include "rilmodem.h" #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, static void ril_query_manufacturer(struct ofono_devinfo *info,
ofono_devinfo_query_cb_t cb, ofono_devinfo_query_cb_t cb,
void *data) 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, static void ril_query_model(struct ofono_devinfo *info,
ofono_devinfo_query_cb_t cb, ofono_devinfo_query_cb_t cb,
void *data) 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) static void query_revision_cb(struct ril_msg *message, gpointer user_data)
{ {
struct cb_data *cbd = user_data; struct cb_data *cbd = user_data;
ofono_devinfo_query_cb_t cb = cbd->cb; ofono_devinfo_query_cb_t cb = cbd->cb;
struct ofono_error error; GRil *ril = cbd->user;
struct parcel rilp; struct parcel rilp;
gchar *revision; char *revision;
if (message->error == RIL_E_SUCCESS) { if (message->error != RIL_E_SUCCESS)
decode_ril_error(&error, "OK"); goto error;
} else {
decode_ril_error(&error, "FAIL");
cb(&error, NULL, cbd->data);
return;
}
ril_util_init_parcel(message, &rilp); g_ril_init_parcel(message, &rilp);
revision = parcel_r_string(&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); g_free(revision);
return;
error:
CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
} }
static void ril_query_revision(struct ofono_devinfo *info, static void ril_query_revision(struct ofono_devinfo *info,
ofono_devinfo_query_cb_t cb, ofono_devinfo_query_cb_t cb,
void *data) void *data)
{ {
struct cb_data *cbd = cb_data_new(cb, data);
GRil *ril = ofono_devinfo_get_data(info); GRil *ril = ofono_devinfo_get_data(info);
int request = RIL_REQUEST_BASEBAND_VERSION; struct cb_data *cbd = cb_data_new(cb, data, ril);
int ret;
ret = g_ril_send(ril, request, NULL, 0, if (g_ril_send(ril, RIL_REQUEST_BASEBAND_VERSION, NULL,
query_revision_cb, cbd, g_free); 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) { static void query_svn_cb(struct ril_msg *message, gpointer user_data)
g_free(cbd); {
CALLBACK_WITH_FAILURE(cb, NULL, 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) static void query_serial_cb(struct ril_msg *message, gpointer user_data)
{ {
struct cb_data *cbd = user_data; struct cb_data *cbd = user_data;
ofono_devinfo_query_cb_t cb = cbd->cb; ofono_devinfo_query_cb_t cb = cbd->cb;
struct ofono_error error; GRil *ril = cbd->user;
struct parcel rilp; struct parcel rilp;
gchar *imei; char *imei;
if (message->error == RIL_E_SUCCESS) { if (message->error != RIL_E_SUCCESS)
decode_ril_error(&error, "OK"); goto error;
} else {
decode_ril_error(&error, "FAIL");
cb(&error, NULL, cbd->data);
return;
}
ril_util_init_parcel(message, &rilp); g_ril_init_parcel(message, &rilp);
imei = parcel_r_string(&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); g_free(imei);
return;
error:
CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
} }
static void ril_query_serial(struct ofono_devinfo *info, static void ril_query_serial(struct ofono_devinfo *info,
ofono_devinfo_query_cb_t cb, ofono_devinfo_query_cb_t cb,
void *data) void *data)
{ {
struct cb_data *cbd = cb_data_new(cb, data);
GRil *ril = ofono_devinfo_get_data(info); GRil *ril = ofono_devinfo_get_data(info);
/* TODO: make it support both RIL_REQUEST_GET_IMEI (deprecated) and struct cb_data *cbd = cb_data_new(cb, data, ril);
* RIL_REQUEST_DEVICE_IDENTITY depending on the rild version used */
int request = RIL_REQUEST_GET_IMEI;
int ret;
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); g_free(cbd);
CALLBACK_WITH_FAILURE(cb, NULL, data);
if (ret <= 0) {
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, NULL, data);
}
} }
static gboolean ril_delayed_register(gpointer user_data) static gboolean ril_delayed_register(gpointer user_data)
{ {
struct ofono_devinfo *info = user_data; struct ofono_devinfo *info = user_data;
DBG("");
timer_id = 0; DBG("");
ofono_devinfo_register(info); ofono_devinfo_register(info);
/* This makes the timeout a single-shot */
return FALSE; return FALSE;
} }
static int ril_devinfo_probe(struct ofono_devinfo *info, unsigned int vendor, static int ril_devinfo_probe(struct ofono_devinfo *info, unsigned int vendor,
void *data) void *data)
{ {
GRil *ril = NULL; GRil *ril = g_ril_clone(data);
if (data != NULL)
ril = g_ril_clone(data);
ofono_devinfo_set_data(info, ril); ofono_devinfo_set_data(info, ril);
g_idle_add(ril_delayed_register, info);
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);
return 0; return 0;
} }
@@ -195,20 +209,18 @@ static void ril_devinfo_remove(struct ofono_devinfo *info)
ofono_devinfo_set_data(info, NULL); ofono_devinfo_set_data(info, NULL);
if (timer_id > 0)
g_source_remove(timer_id);
g_ril_unref(ril); g_ril_unref(ril);
} }
static struct ofono_devinfo_driver driver = { static struct ofono_devinfo_driver driver = {
.name = "rilmodem", .name = RILMODEM,
.probe = ril_devinfo_probe, .probe = ril_devinfo_probe,
.remove = ril_devinfo_remove, .remove = ril_devinfo_remove,
.query_manufacturer = ril_query_manufacturer, .query_manufacturer = ril_query_manufacturer,
.query_model = ril_query_model, .query_model = ril_query_model,
.query_revision = ril_query_revision, .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) 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/gprs.h>
#include <ofono/types.h> #include <ofono/types.h>
#include "gril.h" #include <gril/gril.h>
#include "grilutil.h" #include <gril/grilutil.h>
#include "common.h" #include "common.h"
#include "rilmodem.h" #include "rilmodem.h"
#include <ofono/netreg.h> /* Time between get data status retries */
#include <ofono/sim.h> #define GET_STATUS_TIMER_MS 5000
#include "storage.h"
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. * 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 * 1. ofono_gprs_suspend/resume() are not used by this module, as
* the concept of suspended GPRS is not exposed by RILD. * 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 { static int ril_tech_to_bearer_tech(int ril_tech)
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)
{ {
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 == switch (ril_tech) {
RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED); case RADIO_TECH_GSM:
case RADIO_TECH_UNKNOWN:
DBG(""); return PACKET_BEARER_NONE;
case RADIO_TECH_GPRS:
/* We need to notify core always to cover situations when return PACKET_BEARER_GPRS;
* connection drops temporarily for example when user is case RADIO_TECH_EDGE:
* taking CS voice call from LTE or changing technology return PACKET_BEARER_EGPRS;
* preference */ case RADIO_TECH_UMTS:
ril_gprs_registration_status(gprs, NULL, NULL); return PACKET_BEARER_UMTS;
} case RADIO_TECH_HSDPA:
return PACKET_BEARER_HSDPA;
static gboolean ril_gprs_set_attached_callback(gpointer user_data) case RADIO_TECH_HSUPA:
{ return PACKET_BEARER_HSUPA;
struct ofono_error error; case RADIO_TECH_HSPAP:
struct cb_data *cbd = user_data; case RADIO_TECH_HSPA:
ofono_gprs_cb_t cb = cbd->cb; /*
struct ofono_gprs *gprs = cbd->user; * HSPAP is HSPA+; which ofono doesn't define;
struct gprs_data *gd = ofono_gprs_get_data(gprs); * so, if differentiating HSPA and HSPA+ is
* important, then ofono needs to be patched,
DBG(""); * and we probably also need to introduce a
* new indicator icon.
gd->timer_id = 0; */
return PACKET_BEARER_HSUPA_HSDPA;
decode_ril_error(&error, "OK"); case RADIO_TECH_LTE:
return PACKET_BEARER_EPS;
cb(&error, cbd->data); default:
return PACKET_BEARER_NONE;
g_free(cbd); }
return FALSE;
} }
static void ril_gprs_set_attached(struct ofono_gprs *gprs, int attached, static void ril_gprs_set_attached(struct ofono_gprs *gprs, int attached,
ofono_gprs_cb_t cb, void *data) ofono_gprs_cb_t cb, void *data)
{ {
struct cb_data *cbd = cb_data_new(cb, data); struct ril_gprs_data *gd = ofono_gprs_get_data(gprs);
struct gprs_data *gd = ofono_gprs_get_data(gprs);
DBG("attached: %d", attached); 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; gd->ofono_attached = attached;
CALLBACK_WITH_SUCCESS(cb, data);
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;
} }
static void ril_data_reg_cb(struct ril_msg *message, gpointer user_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; struct cb_data *cbd = user_data;
ofono_gprs_status_cb_t cb = cbd->cb; ofono_gprs_status_cb_t cb = cbd->cb;
struct ofono_gprs *gprs = cbd->user; struct ofono_gprs *gprs = cbd->user;
struct gprs_data *gd = ofono_gprs_get_data(gprs); struct ril_gprs_data *gd = ofono_gprs_get_data(gprs);
struct ofono_error error; struct ofono_modem *modem;
int lac, ci, tech; struct parcel rilp;
int max_cids = 1; int num_str;
int status = -1; 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) { old_status = gd->rild_status;
decode_ril_error(&error, "OK");
} else { if (message->error != RIL_E_SUCCESS) {
ofono_error("ril_data_reg_cb: reply failure: %s", ofono_error("%s: DATA_REGISTRATION_STATE reply failure: %s",
__func__,
ril_error_to_string(message->error)); ril_error_to_string(message->error));
decode_ril_error(&error, "FAIL"); goto error;
error.error = message->error;
goto exit;
} }
if (ril_util_parse_reg(gd->ril, message, &status, g_ril_init_parcel(message, &rilp);
&lac, &ci, &tech, &max_cids) == FALSE) { strv = parcel_r_strv(&rilp);
ofono_error("Failure parsing data registration response."); num_str = g_strv_length(strv);
decode_ril_error(&error, "FAIL");
goto exit;
}
if (status > 10) if (strv == NULL)
status = status - 10; goto error;
if (!ofono_registered) { debug_str = g_strjoinv(",", strv);
ofono_gprs_register(gprs); g_ril_append_print_buf(gd->ril, "{%d,%s}", num_str, debug_str);
ofono_registered = TRUE; g_free(debug_str);
} g_ril_print_response(gd->ril, message);
if (max_cids > gd->max_cids) { status = strtoul(strv[0], &end, 10);
DBG("Setting max cids to %d", max_cids); if (end == strv[0] || *end != '\0')
gd->max_cids = max_cids; goto error_free;
ofono_gprs_set_cid_range(gprs, 1, max_cids);
}
if (status == roaming) status = ril_util_registration_state_to_status(status);
status = check_if_really_roaming(status); if (status < 0)
goto error_free;
/* Let's minimize logging */ if (num_str >= 4) {
if (status != gd->rild_status) tech = strtoul(strv[3], &end, 10);
ofono_info("data reg changes %d (%d), attached %d", if (end == strv[3] || *end != '\0')
status, gd->rild_status, gd->ofono_attached); tech = -1;
/* Must be attached if registered or roaming */ if (g_ril_vendor(gd->ril) == OFONO_RIL_VENDOR_MTK) {
if ((gd->rild_status != registered) && (gd->rild_status != roaming)) { switch (tech) {
if (status == registered) case MTK_RADIO_TECH_HSDPAP:
gd->ofono_attached = TRUE; case MTK_RADIO_TECH_HSDPAP_UPA:
else if ((status == roaming) && (ril_roaming_allowed() == TRUE)) case MTK_RADIO_TECH_HSUPAP:
gd->ofono_attached = TRUE; case MTK_RADIO_TECH_HSUPAP_DPA:
} tech = RADIO_TECH_HSPAP;
break;
if (!ofono_modem_get_online(ofono_gprs_get_modem(gprs))) case MTK_RADIO_TECH_DC_DPA:
gd->ofono_attached = FALSE; tech = RADIO_TECH_HSDPA;
break;
/* if unsolicitated and no state change let's not notify core */ case MTK_RADIO_TECH_DC_UPA:
if ((status == gd->rild_status) && gd->ofono_attached) tech = RADIO_TECH_HSUPA;
goto cb_out; break;
case MTK_RADIO_TECH_DC_HSDPAP:
if (!gd->ofono_attached) { case MTK_RADIO_TECH_DC_HSDPAP_UPA:
if (!cb) { case MTK_RADIO_TECH_DC_HSDPAP_DPA:
if (status == roaming) { case MTK_RADIO_TECH_DC_HSPAP:
if (ril_roaming_allowed() == FALSE) tech = RADIO_TECH_HSPAP;
ofono_gprs_detached_notify(gprs); break;
/*
* This prevents core ending
* into eternal loop with driver
*/
decode_ril_error(&error, "FAIL");
} }
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; 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) 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) return;
{
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;
DBG(""); error_free:
g_strfreev(strv);
if (!(gd && message->error == RIL_E_SUCCESS)) { error:
ofono_error("ril_data_reg_cb: reply failure: %s", if (cb)
ril_error_to_string(message->error)); CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
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;
} }
static void ril_gprs_registration_status(struct ofono_gprs *gprs, static void ril_gprs_registration_status(struct ofono_gprs *gprs,
ofono_gprs_status_cb_t cb, ofono_gprs_status_cb_t cb, void *data)
void *data)
{ {
struct gprs_data *gd = ofono_gprs_get_data(gprs); struct ril_gprs_data *gd = ofono_gprs_get_data(gprs);
struct cb_data *cbd = cb_data_new(cb, data); struct cb_data *cbd = cb_data_new(cb, data, gprs);
int request = RIL_REQUEST_DATA_REGISTRATION_STATE;
guint ret;
DBG(""); DBG("");
if (gd == NULL || cbd == NULL) if (g_ril_send(gd->ril, RIL_REQUEST_DATA_REGISTRATION_STATE, NULL,
return; ril_data_reg_cb, cbd, g_free) == 0) {
ofono_error("%s: send "
cbd->user = gprs; "RIL_REQUEST_DATA_REGISTRATION_STATE failed",
__func__);
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.");
g_free(cbd); g_free(cbd);
if (cb) if (cb != NULL)
CALLBACK_WITH_FAILURE(cb, -1, data); CALLBACK_WITH_FAILURE(cb, -1, data);
} }
} }
static int ril_gprs_probe(struct ofono_gprs *gprs, static void query_max_cids_cb(struct ril_msg *message, gpointer user_data)
unsigned int vendor, void *data)
{ {
GRil *ril = data; struct ofono_gprs *gprs = user_data;
struct gprs_data *gd; 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) if (gd == NULL)
return -ENOMEM; return -ENOMEM;
gd->ril = g_ril_clone(ril); gd->ril = g_ril_clone(ril);
gd->ofono_attached = FALSE; gd->ofono_attached = FALSE;
gd->max_cids = 0;
gd->rild_status = -1; gd->rild_status = -1;
gd->registerid = -1;
gd->timer_id = 0;
ofono_registered = FALSE;
ofono_gprs_set_data(gprs, gd); ofono_gprs_set_data(gprs, gd);
ril_gprs_registration_status(gprs, NULL, NULL); get_active_data_calls(gprs);
return 0; return 0;
} }
static void ril_gprs_remove(struct ofono_gprs *gprs) 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(""); DBG("");
ofono_gprs_set_data(gprs, NULL); 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_ril_unref(gd->ril);
g_free(gd); g_free(gd);
} }
static struct ofono_gprs_driver driver = { static struct ofono_gprs_driver driver = {
.name = "rilmodem", .name = RILMODEM,
.probe = ril_gprs_probe, .probe = ril_gprs_probe,
.remove = ril_gprs_remove, .remove = ril_gprs_remove,
.set_attached = ril_gprs_set_attached, .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) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2013 Jolla Ltd * Copyright (C) 2013 Jolla Ltd
* Contact: Jussi Kangas <jussi.kangas@tieto.com> * Contact: Jussi Kangas <jussi.kangas@tieto.com>
* Copyright (C) 2014 Canonical Ltd
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
@@ -35,296 +36,409 @@
#include <ofono/log.h> #include <ofono/log.h>
#include <ofono/modem.h> #include <ofono/modem.h>
#include <ofono/radio-settings.h> #include <ofono/radio-settings.h>
#include <ofono/sim.h>
#include "gril.h" #include "gril.h"
#include "grilutil.h"
#include "storage.h"
#include "rilmodem.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 { struct radio_data {
GRil *ril; GRil *ril;
guint timer_id; gboolean fast_dormancy;
int ratmode; gboolean pending_fd;
unsigned int vendor;
}; };
static void ril_set_rat_cb(struct ril_msg *message, gpointer user_data) static void ril_set_rat_cb(struct ril_msg *message, gpointer user_data)
{ {
struct cb_data *cbd = 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; 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); CALLBACK_WITH_SUCCESS(cb, cbd->data);
else { } else {
ofono_error("rat mode setting failed"); ofono_error("%s: rat mode setting failed", __func__);
CALLBACK_WITH_FAILURE(cb, cbd->data); CALLBACK_WITH_FAILURE(cb, cbd->data);
} }
} }
static void ril_set_rat_mode(struct ofono_radio_settings *rs, static void ril_set_rat_mode(struct ofono_radio_settings *rs,
enum ofono_radio_access_mode mode, enum ofono_radio_access_mode mode,
ofono_radio_settings_rat_mode_set_cb_t cb, ofono_radio_settings_rat_mode_set_cb_t cb,
void *data) void *data)
{ {
struct radio_data *rd = ofono_radio_settings_get_data(rs); 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; struct parcel rilp;
int pref = rd->ratmode; int pref = PREF_NET_TYPE_GSM_WCDMA;
int ret = 0;
ofono_info("rat mode set %d", mode);
parcel_init(&rilp);
parcel_w_int32(&rilp, 1); /* Number of params */
switch (mode) { switch (mode) {
case OFONO_RADIO_ACCESS_MODE_ANY:
pref = PREF_NET_TYPE_LTE_GSM_WCDMA;
break;
case OFONO_RADIO_ACCESS_MODE_GSM: case OFONO_RADIO_ACCESS_MODE_GSM:
pref = PREF_NET_TYPE_GSM_ONLY; pref = PREF_NET_TYPE_GSM_ONLY;
break; break;
case OFONO_RADIO_ACCESS_MODE_UMTS: case OFONO_RADIO_ACCESS_MODE_UMTS:
pref = PREF_NET_TYPE_GSM_WCDMA_AUTO; /* according to UI design */ pref = PREF_NET_TYPE_GSM_WCDMA;
break; break;
case OFONO_RADIO_ACCESS_MODE_LTE: case OFONO_RADIO_ACCESS_MODE_LTE:
pref = PREF_NET_TYPE_LTE_ONLY; pref = PREF_NET_TYPE_LTE_GSM_WCDMA;
default:
break; break;
} }
parcel_init(&rilp);
parcel_w_int32(&rilp, 1); /* Number of params */
parcel_w_int32(&rilp, pref); parcel_w_int32(&rilp, pref);
ret = g_ril_send(rd->ril, RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE, g_ril_append_print_buf(rd->ril, "(%d)", pref);
rilp.data, rilp.size, ril_set_rat_cb,
cbd, g_free);
parcel_free(&rilp); if (g_ril_send(rd->ril, RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE,
&rilp, ril_set_rat_cb, cbd, g_free) > 0)
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)
return; return;
DBG("pref ril rat mode %d, ril current %d", pref, rd->ratmode); g_free(cbd);
CALLBACK_WITH_FAILURE(cb, data);
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);
} }
static void ril_rat_mode_cb(struct ril_msg *message, gpointer user_data) static void ril_rat_mode_cb(struct ril_msg *message, gpointer user_data)
{ {
DBG("");
struct cb_data *cbd = user_data; struct cb_data *cbd = user_data;
ofono_radio_settings_rat_mode_query_cb_t cb = cbd->cb; 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; struct parcel rilp;
int mode = OFONO_RADIO_ACCESS_MODE_ANY; int net_type;
int pref;
if (message->error == RIL_E_SUCCESS) { if (message->error != RIL_E_SUCCESS)
ril_util_init_parcel(message, &rilp); goto error;
/* first item in int[] is len so let's skip that */
parcel_r_int32(&rilp);
pref = parcel_r_int32(&rilp);
switch (pref) { g_ril_init_parcel(message, &rilp);
case PREF_NET_TYPE_LTE_ONLY: if (parcel_r_int32(&rilp) != 1)
mode = OFONO_RADIO_ACCESS_MODE_LTE; goto error;
case PREF_NET_TYPE_GSM_ONLY:
mode = OFONO_RADIO_ACCESS_MODE_GSM; 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; break;
case PREF_NET_TYPE_GSM_WCDMA_AUTO:/* according to UI design */ /* 3G or 2G preferred over LTE */
if (!cb) case MTK_PREF_NET_TYPE_GSM_WCDMA_LTE:
ril_force_rat_mode(cbd->user, pref); case MTK_PREF_NET_TYPE_GSM_WCDMA_LTE_MMDC:
case PREF_NET_TYPE_WCDMA: net_type = PREF_NET_TYPE_GSM_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:
break; 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_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, static void ril_query_rat_mode(struct ofono_radio_settings *rs,
ofono_radio_settings_rat_mode_query_cb_t cb, ofono_radio_settings_rat_mode_query_cb_t cb,
void *data){ 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)
{ {
GKeyFile *keyfile; struct radio_data *rd = ofono_radio_settings_get_data(rs);
GError *err = NULL; struct cb_data *cbd = cb_data_new(cb, data, rs);
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;
/* if (g_ril_send(rd->ril, RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE,
* First we need to check should the LTE be on NULL, ril_rat_mode_cb, cbd, g_free) > 0)
* or not return;
*/
keyfile = g_key_file_new(); g_free(cbd);
CALLBACK_WITH_FAILURE(cb, -1, data);
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;
} }
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 ofono_radio_settings *rs = user_data;
struct radio_data *rd = ofono_radio_settings_get_data(rs);
rd->timer_id = 0; if (error->type == OFONO_ERROR_TYPE_NO_ERROR)
ofono_radio_settings_register(rs);
ofono_radio_settings_register(rs); else
return FALSE; ofono_error("%s: cannot set default fast dormancy", __func__);
} }
static int ril_radio_settings_probe(struct ofono_radio_settings *rs, static int ril_radio_settings_probe(struct ofono_radio_settings *rs,
unsigned int vendor, unsigned int vendor, void *user)
void *user)
{ {
GRil *ril = user; GRil *ril = user;
struct cb_data *cbd = NULL; struct radio_data *rsd = g_new0(struct radio_data, 1);
int ret;
struct radio_data *rsd = g_try_new0(struct radio_data, 1);
rsd->ril = g_ril_clone(ril); rsd->ril = g_ril_clone(ril);
if (ril_get_net_config(rsd)) { rsd->vendor = vendor;
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);
}
ofono_radio_settings_set_data(rs, rsd); 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; return 0;
} }
@@ -334,19 +448,20 @@ static void ril_radio_settings_remove(struct ofono_radio_settings *rs)
struct radio_data *rd = ofono_radio_settings_get_data(rs); struct radio_data *rd = ofono_radio_settings_get_data(rs);
ofono_radio_settings_set_data(rs, NULL); ofono_radio_settings_set_data(rs, NULL);
if (rd->timer_id > 0)
g_source_remove(rd->timer_id);
g_ril_unref(rd->ril); g_ril_unref(rd->ril);
g_free(rd); g_free(rd);
} }
static struct ofono_radio_settings_driver driver = { static struct ofono_radio_settings_driver driver = {
.name = "rilmodem", .name = RILMODEM,
.probe = ril_radio_settings_probe, .probe = ril_radio_settings_probe,
.remove = ril_radio_settings_remove, .remove = ril_radio_settings_remove,
.query_rat_mode = ril_query_rat_mode, .query_rat_mode = ril_query_rat_mode,
.set_rat_mode = ril_set_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) void ril_radio_settings_init(void)

View File

@@ -4,7 +4,6 @@
* *
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved. * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2012 Canonical, Ltd. 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 * 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 * it under the terms of the GNU General Public License version 2 as
@@ -45,17 +44,14 @@ static int rilmodem_init(void)
ril_sms_init(); ril_sms_init();
ril_netreg_init(); ril_netreg_init();
ril_call_volume_init(); ril_call_volume_init();
ril_gprs_init(); ril_gprs_init();
ril_gprs_context_init(); ril_gprs_context_init();
ril_radio_settings_init();
ril_phonebook_init();
ril_ussd_init(); ril_ussd_init();
ril_call_settings_init(); ril_call_settings_init();
ril_call_forwarding_init(); ril_call_forwarding_init();
ril_radio_settings_init();
ril_call_barring_init(); ril_call_barring_init();
ril_cbs_init(); ril_netmon_init();
ril_oemraw_init();
ril_stk_init(); ril_stk_init();
return 0; return 0;
@@ -73,14 +69,12 @@ static void rilmodem_exit(void)
ril_call_volume_exit(); ril_call_volume_exit();
ril_gprs_exit(); ril_gprs_exit();
ril_gprs_context_exit(); ril_gprs_context_exit();
ril_radio_settings_exit();
ril_phonebook_exit();
ril_ussd_exit(); ril_ussd_exit();
ril_call_settings_exit(); ril_call_settings_exit();
ril_call_forwarding_exit(); ril_call_forwarding_exit();
ril_radio_settings_exit();
ril_call_barring_exit(); ril_call_barring_exit();
ril_cbs_exit(); ril_netmon_exit();
ril_oemraw_exit();
ril_stk_exit(); ril_stk_exit();
} }

View File

@@ -4,7 +4,6 @@
* *
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved. * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2012 Canonical Ltd. * Copyright (C) 2012 Canonical Ltd.
* Copyright (C) 2013 Jolla Ltd.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
@@ -28,14 +27,6 @@
/* Shared constants */ /* Shared constants */
#define EF_STATUS_INVALIDATED 0 #define EF_STATUS_INVALIDATED 0
#define EF_STATUS_VALID 1 #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_init(void);
extern void ril_devinfo_exit(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_init(void);
extern void ril_gprs_context_exit(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_init(void);
extern void ril_ussd_exit(void); extern void ril_ussd_exit(void);
@@ -73,18 +61,17 @@ extern void ril_call_settings_exit(void);
extern void ril_call_forwarding_init(void); extern void ril_call_forwarding_init(void);
extern void ril_call_forwarding_exit(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_init(void);
extern void ril_call_barring_exit(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_init(void);
extern void ril_phonebook_exit(void); extern void ril_phonebook_exit(void);
extern void ril_oemraw_init(void); extern void ril_netmon_init(void);
extern void ril_oemraw_exit(void); extern void ril_netmon_exit(void);
extern void ril_stk_init(void); extern void ril_stk_init(void);
extern void ril_stk_exit(void); extern void ril_stk_exit(void);

View File

@@ -4,7 +4,6 @@
* *
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved. * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2012 Canonical Ltd. * Copyright (C) 2012 Canonical Ltd.
* Copyright (C) 2013 Jolla Ltd.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
@@ -29,6 +28,7 @@
#include <gril.h> #include <gril.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <arpa/inet.h>
#define OFONO_API_SUBJECT_TO_CHANGE #define OFONO_API_SUBJECT_TO_CHANGE
#include <ofono/log.h> #include <ofono/log.h>
@@ -40,19 +40,6 @@
#include "util.h" #include "util.h"
#include "ril_constants.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) void decode_ril_error(struct ofono_error *error, const char *final)
{ {
if (!strcmp(final, "OK")) { 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) 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")) { if (g_str_has_suffix(address, "/29"))
result = PREFIX_30_NETMASK; return PREFIX_29_NETMASK;
} else if (g_str_has_suffix(address, "/29")) {
result = PREFIX_29_NETMASK; if (g_str_has_suffix(address, "/28"))
} else if (g_str_has_suffix(address, "/28")) { return PREFIX_28_NETMASK;
result = PREFIX_28_NETMASK;
} else if (g_str_has_suffix(address, "/27")) { if (g_str_has_suffix(address, "/27"))
result = PREFIX_27_NETMASK; return PREFIX_27_NETMASK;
} else if (g_str_has_suffix(address, "/26")) {
result = PREFIX_26_NETMASK; if (g_str_has_suffix(address, "/26"))
} else if (g_str_has_suffix(address, "/25")) { return PREFIX_26_NETMASK;
result = PREFIX_25_NETMASK;
} else if (g_str_has_suffix(address, "/24")) { if (g_str_has_suffix(address, "/25"))
result = PREFIX_24_NETMASK; return PREFIX_25_NETMASK;
} else {
/* if (g_str_has_suffix(address, "/24"))
* This handles the case where the return PREFIX_24_NETMASK;
* Samsung RILD returns an address without
* a prefix, however it explicitly sets a return NULL;
* /24 netmask ( which isn't returned as }
* an attribute of the DATA_CALL.
* void ril_util_build_deactivate_data_call(GRil *gril, struct parcel *rilp,
* TODO/OEM: this might need to be quirked int cid, unsigned int reason)
* for specific devices. {
*/ char *cid_str = NULL;
result = PREFIX_24_NETMASK; 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 reg_state;
return result;
} }
/* TODO: this function can go away, once all the code has been int ril_util_address_to_gprs_proto(const char *addr)
* re-factored to use grilreply.c */
void ril_util_init_parcel(struct ril_msg *message, struct parcel *rilp)
{ {
/* Set up Parcel struct for proper parsing */ int ret = -1;
rilp->data = message->buf; struct in_addr ipv4;
rilp->size = message->buf_len; struct in6_addr ipv6;
rilp->capacity = message->buf_len; char **addr_split = g_strsplit(addr, "/", 2);
rilp->offset = 0;
}
struct ril_util_sim_state_query *ril_util_sim_state_query_new(GRil *ril, if (addr_split == NULL || g_strv_length(addr_split) == 0)
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
goto done; goto done;
DBG("sim num_apps: %d", status->num_apps); if (inet_pton(AF_INET, addr_split[0], &ipv4) > 0) {
if (status->num_apps > MAX_UICC_APPS) { ret = OFONO_GPRS_PROTO_IP;
ofono_error("SIM error; too many apps: %d", status->num_apps); goto done;
status->num_apps = MAX_UICC_APPS;
} }
for (i = 0; i < status->num_apps; i++) { if (inet_pton(AF_INET6, addr_split[0], &ipv6) > 0) {
apps[i] = g_try_new0(struct sim_app, 1); ret = OFONO_GPRS_PROTO_IPV6;
if (apps[i] == NULL) { goto done;
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);
} }
done: done:
g_ril_append_print_buf(gril, "%s}", print_buf); g_strfreev(addr_split);
g_ril_print_response(gril, message);
return result; return ret;
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]);
}
} }

View File

@@ -19,10 +19,13 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* *
*/ */
#ifndef RILUTIL_H
#define RILUTIL_H
#include <stdio.h> #include <stdio.h>
#include <ofono/modem.h>
#include "parcel.h" #include <ofono/sim.h>
#include <ofono/gprs-context.h>
/* TODO: create a table lookup*/ /* TODO: create a table lookup*/
#define PREFIX_30_NETMASK "255.255.255.252" #define PREFIX_30_NETMASK "255.255.255.252"
@@ -33,6 +36,8 @@
#define PREFIX_25_NETMASK "255.255.255.128" #define PREFIX_25_NETMASK "255.255.255.128"
#define PREFIX_24_NETMASK "255.255.255.0" #define PREFIX_24_NETMASK "255.255.255.0"
#define MODEM_PROP_LTE_CAPABLE "lte-capable"
enum ril_util_sms_store { enum ril_util_sms_store {
RIL_UTIL_SMS_STORE_SM = 0, RIL_UTIL_SMS_STORE_SM = 0,
RIL_UTIL_SMS_STORE_ME = 1, RIL_UTIL_SMS_STORE_ME = 1,
@@ -62,74 +67,13 @@ enum at_util_charset {
RIL_UTIL_CHARSET_8859_H = 0x10000, 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); typedef void (*ril_util_sim_inserted_cb_t)(gboolean present, void *userdata);
void decode_ril_error(struct ofono_error *error, const char *final); 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); 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, void ril_util_build_deactivate_data_call(GRil *gril, struct parcel *rilp,
guint interval, guint num_times, int cid, unsigned int reason);
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);
struct cb_data { struct cb_data {
void *cb; void *cb;
@@ -137,29 +81,14 @@ struct cb_data {
void *user; 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; struct cb_data *ret;
ret = g_new0(struct cb_data, 1); ret = g_new0(struct cb_data, 1);
ret->cb = cb; ret->cb = cb;
ret->data = data; ret->data = data;
ret->user = user;
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;
}
return ret; return ret;
} }
@@ -176,6 +105,12 @@ static inline int ril_util_convert_signal_strength(int strength)
return result; 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) \ #define DECLARE_FAILURE(e) \
struct ofono_error e; \ struct ofono_error e; \
e.type = OFONO_ERROR_TYPE_FAILURE; \ e.type = OFONO_ERROR_TYPE_FAILURE; \
@@ -197,3 +132,5 @@ static inline int ril_util_convert_signal_strength(int strength)
e.error = 0; \ e.error = 0; \
f(&e, ##args); \ f(&e, ##args); \
} while (0) } 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 * oFono - Open Source Telephony - RIL Modem Support
* *
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved. * 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. * Copyright (C) 2013 Jolla Ltd.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@@ -38,35 +38,30 @@
#include <ofono/log.h> #include <ofono/log.h>
#include <ofono/modem.h> #include <ofono/modem.h>
#include <ofono/sms.h> #include <ofono/sms.h>
#include <ofono/types.h>
#include <ofono/sim.h>
#include "smsutil.h" #include "smsutil.h"
#include "util.h" #include "util.h"
#include "common.h"
#include "rilmodem.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 { struct sms_data {
GRil *ril; GRil *ril;
unsigned int vendor; unsigned int vendor;
guint timer_id;
}; };
static void ril_csca_set_cb(struct ril_msg *message, gpointer user_data) static void ril_csca_set_cb(struct ril_msg *message, gpointer user_data)
{ {
struct cb_data *cbd = user_data; struct cb_data *cbd = user_data;
ofono_sms_sca_set_cb_t cb = cbd->cb; 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); CALLBACK_WITH_SUCCESS(cb, cbd->data);
else { } else {
ofono_error("csca setting failed"); 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); 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, const struct ofono_phone_number *sca,
ofono_sms_sca_set_cb_t cb, void *user_data) ofono_sms_sca_set_cb_t cb, void *user_data)
{ {
struct sms_data *data = ofono_sms_get_data(sms); 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; struct parcel rilp;
int ret = -1;
char number[OFONO_MAX_PHONE_NUMBER_LENGTH + 4]; char number[OFONO_MAX_PHONE_NUMBER_LENGTH + 4];
if (sca->type == 129) snprintf(number, sizeof(number), "\"%s\"", phone_number_to_string(sca));
snprintf(number, sizeof(number), "\"%s\"", sca->number);
else
snprintf(number, sizeof(number), "\"+%s\"", sca->number);
DBG("Setting sca: %s", number);
parcel_init(&rilp); parcel_init(&rilp);
parcel_w_string(&rilp, number); parcel_w_string(&rilp, number);
/* Send request to RIL */ g_ril_append_print_buf(sd->ril, "(%s)", number);
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);
/* In case of error free cbd and return the cb with failure */ if (g_ril_send(sd->ril, RIL_REQUEST_SET_SMSC_ADDRESS, &rilp,
if (ret <= 0) { ril_csca_set_cb, cbd, g_free) > 0)
ofono_error("unable to set csca"); return;
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, user_data); g_free(cbd);
} CALLBACK_WITH_FAILURE(cb, user_data);
} }
static void ril_csca_query_cb(struct ril_msg *message, gpointer user_data) static void ril_csca_query_cb(struct ril_msg *message, gpointer user_data)
{ {
struct cb_data *cbd = user_data; struct cb_data *cbd = user_data;
ofono_sms_sca_query_cb_t cb = cbd->cb; 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 ofono_phone_number sca;
struct parcel rilp; struct parcel rilp;
gchar *number, *temp_buf; char *temp_buf;
char *number;
if (message->error == RIL_E_SUCCESS) { if (message->error != RIL_E_SUCCESS)
decode_ril_error(&error, "OK"); goto error;
} else {
ofono_error("csca query failed"); g_ril_init_parcel(message, &rilp);
decode_ril_error(&error, "FAIL");
cb(&error, NULL, cbd->data);
return;
}
ril_util_init_parcel(message, &rilp);
temp_buf = parcel_r_string(&rilp); temp_buf = parcel_r_string(&rilp);
if (temp_buf == NULL)
goto error;
if (temp_buf != NULL) { /* RIL gives address in quotes */
/* RIL gives address in quotes */ number = strtok(temp_buf, "\"");
number = strtok(temp_buf, "\""); if (number == NULL || *number == '\0') {
g_free(temp_buf);
if (number[0] == '+') { goto error;
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);
} }
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, static void ril_csca_query(struct ofono_sms *sms, ofono_sms_sca_query_cb_t cb,
void *user_data) void *user_data)
{ {
struct sms_data *data = ofono_sms_get_data(sms); 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);
int ret = -1;
DBG("Sending csca_query"); DBG("Sending csca_query");
ret = g_ril_send(data->ril, RIL_REQUEST_GET_SMSC_ADDRESS, NULL, 0, if (g_ril_send(sd->ril, RIL_REQUEST_GET_SMSC_ADDRESS, NULL,
ril_csca_query_cb, cbd, g_free); ril_csca_query_cb, cbd, g_free) == 0) {
if (ret <= 0) {
ofono_error("unable to send sca query");
g_free(cbd); g_free(cbd);
CALLBACK_WITH_FAILURE(cb, NULL, user_data); 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 cb_data *cbd = user_data;
struct ofono_error error;
ofono_sms_submit_cb_t cb = cbd->cb; ofono_sms_submit_cb_t cb = cbd->cb;
struct sms_data *sd = cbd->user; struct sms_data *sd = cbd->user;
struct parcel rilp;
int mr; int mr;
char *ack_pdu;
int error;
if (message->error == RIL_E_SUCCESS) { if (message->error != RIL_E_SUCCESS) {
ofono_info("sms sending successful"); CALLBACK_WITH_FAILURE(cb, 0, cbd->data);
decode_ril_error(&error, "OK"); return;
} 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");
} }
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, 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) ofono_sms_submit_cb_t cb, void *user_data)
{ {
struct sms_data *sd = ofono_sms_get_data(sms); 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; struct parcel rilp;
char *tpdu; int smsc_len;
int request = RIL_REQUEST_SEND_SMS; char hexbuf[tpdu_len * 2 + 1];
int ret, smsc_len;
cbd->user = sd;
DBG("pdu_len: %d, tpdu_len: %d mms: %d", pdu_len, tpdu_len, mms); DBG("pdu_len: %d, tpdu_len: %d mms: %d", pdu_len, tpdu_len, mms);
/* TODO: if (mms) { ... } */ /* TODO: if (mms) { ... } */
parcel_init(&rilp); 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 * smsc_len == 1, then zero-length SMSC was spec'd
* RILD expects a NULL string in this case instead * RILD expects a NULL string in this case instead
* of a zero-length string. * of a zero-length string.
*/ */
smsc_len = pdu_len - tpdu_len; smsc_len = pdu_len - tpdu_len;
if (smsc_len > 1) { /* TODO: encode SMSC & write to parcel */
/* TODO: encode SMSC & write to parcel */ if (smsc_len > 1)
DBG("SMSC address specified (smsc_len %d); NOT-IMPLEMENTED", smsc_len); ofono_error("SMSC address specified (smsc_len %d); "
} "NOT-IMPLEMENTED", smsc_len);
parcel_w_string(&rilp, NULL); /* SMSC address; NULL == default */ parcel_w_string(&rilp, NULL); /* SMSC address; NULL == default */
/* TPDU: /*
* TPDU:
* *
* 'pdu' is a raw hexadecimal string * 'pdu' is a raw hexadecimal string
* encode_hex() turns it into an ASCII/hex UTF8 buffer * encode_hex() turns it into an ASCII/hex UTF8 buffer
* parcel_w_string() encodes utf8 -> utf16 * parcel_w_string() encodes utf8 -> utf16
*/ */
tpdu = encode_hex(pdu + smsc_len, tpdu_len, 0); encode_hex_own_buf(pdu + smsc_len, tpdu_len, 0, hexbuf);
parcel_w_string(&rilp, tpdu); parcel_w_string(&rilp, hexbuf);
ret = g_ril_send(sd->ril, g_ril_append_print_buf(sd->ril, "(%s)", hexbuf);
request,
rilp.data,
rilp.size,
submit_sms_cb, cbd, g_free);
g_ril_append_print_buf(sd->ril, "(%s)", tpdu); if (g_ril_send(sd->ril, RIL_REQUEST_SEND_SMS, &rilp,
g_free(tpdu); ril_submit_sms_cb, cbd, g_free) > 0)
tpdu = NULL; return;
g_ril_print_request(sd->ril, ret, request);
parcel_free(&rilp); g_free(cbd);
CALLBACK_WITH_FAILURE(cb, -1, user_data);
if (ret <= 0) {
ofono_error("unable to send sms");
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, -1, user_data);
}
} }
static void ril_ack_delivery_cb(struct ril_msg *message, gpointer user_data) static void ril_ack_delivery_cb(struct ril_msg *message, gpointer user_data)
{ {
if (message->error != RIL_E_SUCCESS) if (message->error != RIL_E_SUCCESS)
ofono_error( ofono_error("SMS acknowledgement failed: "
"SMS acknowledgement failed: Further SMS reception is not guaranteed"); "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 sms_data *sd = ofono_sms_get_data(sms);
struct parcel rilp; struct parcel rilp;
int ret;
int request = RIL_REQUEST_SMS_ACKNOWLEDGE;
int code = 0;
if (!error)
code = 0xFF;
parcel_init(&rilp); parcel_init(&rilp);
parcel_w_int32(&rilp, 2); /* Number of int32 values in array */ 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, 1); /* Successful receipt */
parcel_w_int32(&rilp, code); /* error code */ parcel_w_int32(&rilp, 0); /* error code */
/* ACK the incoming NEW_SMS */
ret = g_ril_send(sd->ril, request,
rilp.data,
rilp.size,
ril_ack_delivery_cb, NULL, NULL);
g_ril_append_print_buf(sd->ril, "(1,0)"); 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) static void ril_sms_notify(struct ril_msg *message, gpointer user_data)
{ {
struct ofono_sms *sms = user_data; struct ofono_sms *sms = user_data;
struct sms_data *sd = ofono_sms_get_data(sms); struct sms_data *sd = ofono_sms_get_data(sms);
struct parcel rilp;
char *ril_pdu;
int ril_pdu_len;
unsigned int smsc_len; unsigned int smsc_len;
long ril_buf_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; DBG("req: %d; data_len: %d", message->req, (int) message->buf_len);
ril_data = NULL;
DBG("req: %d; data_len: %d", message->req, message->buf_len); g_ril_init_parcel(message, &rilp);
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);
ril_pdu = parcel_r_string(&rilp); ril_pdu = parcel_r_string(&rilp);
if (ril_pdu == NULL) 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); ril_pdu_len = strlen(ril_pdu);
DBG("ril_pdu_len is %d", ril_pdu_len); if (ril_pdu_len > sizeof(pdu) * 2)
ril_data = decode_hex(ril_pdu, ril_pdu_len, &ril_buf_len, -1); goto fail;
if (ril_data == NULL)
goto error;
/* The first octect in the pdu contains the SMSC address length if (decode_hex_own_buf(ril_pdu, ril_pdu_len,
* which is the X following octects it reads. We add 1 octet to &ril_buf_len, -1, pdu) == NULL)
* the read length to take into account this read octet in order goto fail;
* 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;
}
/* /*
* It seems when reading EFsms RIL returns the whole record including * The first octect in the pdu contains the SMSC address length
* 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
* which is the X following octects it reads. We add 1 octet to * 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 * the read length to take into account this read octet in order
* to calculate the proper tpdu length. * 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, if (message->req == RIL_UNSOL_RESPONSE_NEW_SMS)
length - smsc_len - 1); /* 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; /* ACK the incoming NEW_SMS */
ril_request_delete_sms_om_sim(sms,record); ril_ack_delivery(sms);
exit: fail:
g_free(cbd); g_free(ril_pdu);
}
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);
}
} }
static gboolean ril_delayed_register(gpointer user_data) 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); struct sms_data *data = ofono_sms_get_data(sms);
DBG(""); DBG("");
data->timer_id = 0;
ofono_sms_register(sms); ofono_sms_register(sms);
g_ril_register(data->ril, RIL_UNSOL_RESPONSE_NEW_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, g_ril_register(data->ril, RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT,
ril_sms_notify, sms); 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; return FALSE;
} }
@@ -494,17 +486,7 @@ static int ril_sms_probe(struct ofono_sms *sms, unsigned int vendor,
ofono_sms_set_data(sms, data); ofono_sms_set_data(sms, data);
/* g_idle_add(ril_delayed_register, sms);
* 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);
return 0; return 0;
} }
@@ -515,9 +497,6 @@ static void ril_sms_remove(struct ofono_sms *sms)
DBG(""); DBG("");
if (data->timer_id > 0)
g_source_remove(data->timer_id);
g_ril_unref(data->ril); g_ril_unref(data->ril);
g_free(data); g_free(data);
@@ -525,25 +504,22 @@ static void ril_sms_remove(struct ofono_sms *sms)
} }
static struct ofono_sms_driver driver = { static struct ofono_sms_driver driver = {
.name = "rilmodem", .name = RILMODEM,
.probe = ril_sms_probe, .probe = ril_sms_probe,
.remove = ril_sms_remove,
.sca_query = ril_csca_query, .sca_query = ril_csca_query,
.sca_set = ril_csca_set, .sca_set = ril_csca_set,
.remove = ril_sms_remove,
.submit = ril_cmgs, .submit = ril_cmgs,
.bearer_query = NULL, /* FIXME: needs investigation. */ .bearer_query = ril_sms_bearer_query,
.bearer_set = NULL, .bearer_set = ril_sms_bearer_set
}; };
void ril_sms_init(void) void ril_sms_init(void)
{ {
DBG(""); ofono_sms_driver_register(&driver);
if (ofono_sms_driver_register(&driver))
DBG("ofono_sms_driver_register failed!");
} }
void ril_sms_exit(void) void ril_sms_exit(void)
{ {
DBG("");
ofono_sms_driver_unregister(&driver); ofono_sms_driver_unregister(&driver);
} }

View File

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

View File

@@ -4,6 +4,7 @@
* *
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved. * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2013 Jolla Ltd * Copyright (C) 2013 Jolla Ltd
* Copyright (C) 2013 Canonical Ltd
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
@@ -38,25 +39,39 @@
#include <util.h> #include <util.h>
#include "gril.h" #include "gril.h"
#include "grilutil.h"
#include "rilmodem.h" #include "rilmodem.h"
#include "ril_constants.h"
struct ussd_data { struct ussd_data {
GRil *ril; 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) 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 * We fake an ON_USSD event if there was an error sending the request,
* segmentation fault. There is theoretical possibility that no * as core will be waiting for one to respond to the Initiate() call.
* RIL_UNSOL_ON_USSD is received and therefore the original request * Note that we already made the callback (see ril_ussd_request()).
* is not freed in oFono.
*/ */
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, 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) ofono_ussd_cb_t cb, void *data)
{ {
struct ussd_data *ud = ofono_ussd_get_data(ussd); struct ussd_data *ud = ofono_ussd_get_data(ussd);
struct cb_data *cbd = cb_data_new(cb, data); struct cb_data *cbd = cb_data_new(cb, data, ussd);
enum sms_charset charset; char *text;
int ret = -1; 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, parcel_init(&rilp);
NULL, NULL, NULL)) { parcel_w_string(&rilp, text);
if (charset == SMS_CHARSET_7BIT) {
unsigned char unpacked_buf[182] = "";
long written;
int length;
unpack_7bit_own_buf(pdu, len, 0, TRUE, g_ril_append_print_buf(ud->ril, "(%s)", text);
sizeof(unpacked_buf), &written, 0,
unpacked_buf);
if (written >= 1) { ret = g_ril_send(ud->ril, RIL_REQUEST_SEND_USSD,
/* &rilp, ril_ussd_cb, ussd, NULL);
* When USSD was packed, additional CR g_free(text);
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);
}
}
}
/* /*
* It cannot be guaranteed that response is received before notify or * TODO: Is g_idle_add necessary?
* user-activity request so we must complete the request now and later * We do not wait for the SEND_USSD reply to do the callback, as some
* ignore the actual response. * 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) { if (ret > 0) {
g_free(cbd); g_idle_add(request_success, cbd);
CALLBACK_WITH_FAILURE(cb, data); return;
} else {
CALLBACK_WITH_SUCCESS(cb, cbd->data);
} }
error:
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, data);
} }
static void ril_ussd_cancel_cb(struct ril_msg *message, gpointer user_data) static void ril_ussd_cancel_cb(struct ril_msg *message, gpointer user_data)
{ {
struct cb_data *cbd = 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; ofono_ussd_cb_t cb = cbd->cb;
struct ofono_error error;
DBG("%d", message->error); if (message->error == RIL_E_SUCCESS) {
g_ril_print_response_no_args(ud->ril, message);
if (message->error == RIL_E_SUCCESS) CALLBACK_WITH_SUCCESS(cb, cbd->data);
decode_ril_error(&error, "OK"); } else {
else { CALLBACK_WITH_FAILURE(cb, cbd->data);
ofono_error("ussd canceling failed");
decode_ril_error(&error, "FAIL");
} }
cb(&error, cbd->data);
} }
static void ril_ussd_cancel(struct ofono_ussd *ussd, static void ril_ussd_cancel(struct ofono_ussd *ussd,
ofono_ussd_cb_t cb, void *user_data) ofono_ussd_cb_t cb, void *user_data)
{ {
struct ussd_data *ud = ofono_ussd_get_data(ussd); 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"); if (g_ril_send(ud->ril, RIL_REQUEST_CANCEL_USSD, NULL,
cbd->user = ud;
if (g_ril_send(ud->ril, RIL_REQUEST_CANCEL_USSD, NULL, 0,
ril_ussd_cancel_cb, cbd, g_free) > 0) ril_ussd_cancel_cb, cbd, g_free) > 0)
return; return;
ofono_error("unable cancel ussd");
g_free(cbd); g_free(cbd);
CALLBACK_WITH_FAILURE(cb, user_data); CALLBACK_WITH_FAILURE(cb, user_data);
} }
static void ril_ussd_notify(struct ril_msg *message, gpointer user_data) static void ril_ussd_notify(struct ril_msg *message, gpointer user_data)
{ {
struct ofono_ussd *ussd = user_data; struct ofono_ussd *ussd = user_data;
struct ussd_data *ud = ofono_ussd_get_data(ussd);
struct parcel rilp; struct parcel rilp;
gchar *ussd_from_network = NULL; int numstr;
gchar *type = NULL; char *typestr;
gint ussdtype = 0; 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); numstr = parcel_r_int32(&rilp);
parcel_r_int32(&rilp); if (numstr < 1)
type = parcel_r_string(&rilp); return;
ussdtype = g_ascii_xdigit_value(*type);
g_free(type);
type = NULL;
ussd_from_network = parcel_r_string(&rilp);
/* ussd_from_network not freed because core does that if dcs is 0xFF */ typestr = parcel_r_string(&rilp);
if (ussd_from_network) { if (typestr == NULL || *typestr == '\0')
DBG("ussd_received, length %d", strlen(ussd_from_network)); return;
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);
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) static gboolean ril_delayed_register(gpointer user_data)
@@ -200,13 +211,10 @@ static gboolean ril_delayed_register(gpointer user_data)
DBG(""); DBG("");
ud->timer_id = 0;
ofono_ussd_register(ussd); ofono_ussd_register(ussd);
/* Register for USSD responses */ /* Register for USSD responses */
g_ril_register(ud->ril, RIL_UNSOL_ON_USSD, g_ril_register(ud->ril, RIL_UNSOL_ON_USSD, ril_ussd_notify, ussd);
ril_ussd_notify, ussd);
return FALSE; return FALSE;
} }
@@ -216,10 +224,11 @@ static int ril_ussd_probe(struct ofono_ussd *ussd,
void *user) void *user)
{ {
GRil *ril = 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); ud->ril = g_ril_clone(ril);
ofono_ussd_set_data(ussd, ud); 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; return 0;
} }
@@ -229,19 +238,16 @@ static void ril_ussd_remove(struct ofono_ussd *ussd)
struct ussd_data *ud = ofono_ussd_get_data(ussd); struct ussd_data *ud = ofono_ussd_get_data(ussd);
ofono_ussd_set_data(ussd, NULL); ofono_ussd_set_data(ussd, NULL);
if (ud->timer_id > 0)
g_source_remove(ud->timer_id);
g_ril_unref(ud->ril); g_ril_unref(ud->ril);
g_free(ud); g_free(ud);
} }
static struct ofono_ussd_driver driver = { static struct ofono_ussd_driver driver = {
.name = "rilmodem", .name = RILMODEM,
.probe = ril_ussd_probe, .probe = ril_ussd_probe,
.remove = ril_ussd_remove, .remove = ril_ussd_remove,
.request = ril_ussd_request, .request = ril_ussd_request,
.cancel = ril_ussd_cancel .cancel = ril_ussd_cancel
}; };
void ril_ussd_init(void) void ril_ussd_init(void)
@@ -253,4 +259,3 @@ void ril_ussd_exit(void)
{ {
ofono_ussd_driver_unregister(&driver); 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) 2014 Canonical Ltd. All rights reserved.
* Copyright (C) 2012 Canonical Ltd.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
@@ -20,27 +19,15 @@
* *
*/ */
#ifndef __GRIL_RESPONSE_H #ifndef RILMODEM_VENDOR_H
#define __GRIL_RESPONSE_H #define RILMODEM_VENDOR_H
#ifdef __cplusplus enum ofono_ril_vendor {
extern "C" { OFONO_RIL_VENDOR_AOSP = 0,
#endif OFONO_RIL_VENDOR_MTK,
OFONO_RIL_VENDOR_INFINEON,
struct _GRilResponse { OFONO_RIL_VENDOR_QCOM_MSIM,
GSList *lines; OFONO_RIL_VENDOR_IMC_SOFIA3GR
char *final_or_pdu;
}; };
typedef struct _GRilResponse GRilResponse; #endif /* RILMODEM_VENDOR_H */
#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 */

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); struct voicecall_data *vd = ofono_voicecall_get_data(vc);
g_slist_foreach(vd->calls, (GFunc) g_free, NULL); g_slist_free_full(vd->calls, g_free);
g_slist_free(vd->calls);
ofono_voicecall_set_data(vc, NULL); 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) 2016 Endocode AG. All rights reserved.
* Copyright (C) 2012-2013 Canonical Ltd.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
@@ -20,38 +19,31 @@
* *
*/ */
#ifndef __GRILREPLY_H #ifdef HAVE_CONFIG_H
#define __GRILREPLY_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 <ofono/types.h>
#include "gril.h" #include "ubloxmodem.h"
#ifdef __cplusplus static int ubloxmodem_init(void)
extern "C" { {
#endif ublox_gprs_context_init();
struct reply_setup_data_call { return 0;
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
} }
#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 * 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 * it under the terms of the GNU General Public License version 2 as
@@ -19,14 +19,7 @@
* *
*/ */
#ifndef __RILDEV_H #include <drivers/atmodem/atutil.h>
#define __RILDEV_H
#define RILD_CMD_SOCKET "/dev/socket/rild" extern void ublox_gprs_context_init(void);
#define RILD_SOCKET_DIR "/dev/socket" extern void ublox_gprs_context_exit(void);
#define RILD_SOCKET_FILE "rild"
void ril_modem_remove(struct ofono_modem *modem);
#endif /* __RILDEV_H */

View File

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

View File

@@ -1073,6 +1073,9 @@ static gboolean signal_cb(GIOChannel *channel, GIOCondition cond, gpointer data)
case SIGTERM: case SIGTERM:
server_cleanup(); server_cleanup();
break; break;
case SIGUSR1:
g_at_ppp_shutdown(ppp);
break;
default: default:
break; break;
} }
@@ -1089,6 +1092,7 @@ static int create_signal_io(void)
sigemptyset(&mask); sigemptyset(&mask);
sigaddset(&mask, SIGTERM); sigaddset(&mask, SIGTERM);
sigaddset(&mask, SIGINT); sigaddset(&mask, SIGINT);
sigaddset(&mask, SIGUSR1);
if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) { if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) {
g_error("Can't set signal mask"); 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 "grilutil.h"
#include "parcel.h" #include "parcel.h"
#include "ril_constants.h" #include "ril_constants.h"
#include "drivers/rilmodem/vendor.h"
struct _GRil; struct _GRil;
@@ -43,7 +44,7 @@ typedef struct _GRil GRil;
*/ */
struct ril_msg { struct ril_msg {
gchar *buf; gchar *buf;
gsize buf_len; unsigned int buf_len;
gboolean unsolicited; gboolean unsolicited;
int req; int req;
int serial_no; 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 void (*GRilNotifyFunc)(struct ril_msg *message, gpointer user_data);
typedef const char *(*GRilMsgIdToStrFunc)(int msg_id);
/** /**
* TRACE: * TRACE:
* @fmt: format string * @fmt: format string
@@ -64,36 +67,50 @@ typedef void (*GRilNotifyFunc)(struct ril_msg *message, gpointer user_data);
*/ */
#define G_RIL_TRACE(gril, fmt, arg...) do { \ #define G_RIL_TRACE(gril, fmt, arg...) do { \
if (gril && g_ril_get_trace(gril)) \ if (gril && g_ril_get_trace(gril)) \
ofono_debug(fmt, ## arg); \ ofono_debug(fmt, ## arg); \
} while (0) } while (0)
extern char print_buf[]; extern char print_buf[];
#define g_ril_print_request(gril, token, req) \ #define g_ril_print_request(gril, token, req) \
G_RIL_TRACE(gril, "[%04d]> %s %s", token, ril_request_id_to_string(req), print_buf) G_RIL_TRACE(gril, "[%d,%04d]> %s %s", \
g_ril_get_slot(gril), token, \
g_ril_request_id_to_string(gril, req), print_buf)
#define g_ril_print_request_no_args(gril, token, req) \ #define g_ril_print_request_no_args(gril, token, req) \
G_RIL_TRACE(gril, "[%04d]> %s", token, ril_request_id_to_string(req)) G_RIL_TRACE(gril, "[%d,%04d]> %s", \
#define g_ril_print_response(gril, message) \ g_ril_get_slot(gril), token, \
G_RIL_TRACE(gril, "[%04d]< %s %s", message->serial_no, \ g_ril_request_id_to_string(gril, req))
ril_request_id_to_string(message->req), print_buf) #define g_ril_print_response(gril, message) \
#define g_ril_print_response_no_args(gril, message) \ G_RIL_TRACE(gril, "[%d,%04d]< %s %s", \
G_RIL_TRACE(gril, "[%04d]< %s", message->serial_no, \ g_ril_get_slot(gril), \
ril_request_id_to_string(message->req)) message->serial_no, \
g_ril_request_id_to_string(gril, message->req), \
print_buf)
#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 { \ #define g_ril_append_print_buf(gril, x...) do { \
if (gril && g_ril_get_trace(gril)) \ if (gril && g_ril_get_trace(gril)) \
sprintf(print_buf, x); \ sprintf(print_buf, x); \
} while (0) } while (0)
#define g_ril_print_unsol(gril, message) \ #define g_ril_print_unsol(gril, message) \
G_RIL_TRACE(gril, "[UNSOL]< %s %s", ril_unsol_request_to_string(message->req), \ G_RIL_TRACE(gril, "[%d,UNSOL]< %s %s", \
g_ril_get_slot(gril), \
g_ril_unsol_request_to_string(gril, \
message->req), \
print_buf) print_buf)
#define g_ril_print_unsol_no_args(gril, message) \ #define g_ril_print_unsol_no_args(gril, message) \
G_RIL_TRACE(gril, "[UNSOL]< %s", ril_unsol_request_to_string(message->req)) 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); GIOChannel *g_ril_get_channel(GRil *ril);
GRilIO *g_ril_get_io(GRil *ril); GRilIO *g_ril_get_io(GRil *ril);
@@ -103,15 +120,15 @@ void g_ril_unref(GRil *ril);
GRil *g_ril_clone(GRil *ril); GRil *g_ril_clone(GRil *ril);
void g_ril_suspend(GRil *ril); void g_ril_set_disconnect_function(GRil *ril, GRilDisconnectFunc disconnect,
void g_ril_resume(GRil *ril);
gboolean g_ril_set_disconnect_function(GRil *ril, GRilDisconnectFunc disconnect,
gpointer user_data); gpointer user_data);
gboolean g_ril_get_trace(GRil *ril); gboolean g_ril_get_trace(GRil *ril);
gboolean g_ril_set_trace(GRil *ril, gboolean trace); 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 * 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 * provided to GRil the logging function will be called with the
@@ -119,6 +136,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_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 * Queue an RIL request for execution. The request contents are given
* in data. Once the command executes, the callback function given by * in data. Once the command executes, the callback function given by
@@ -128,9 +150,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. * 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, gint g_ril_send(GRil *ril, const gint reqid, struct parcel *rilp,
const gsize data_len, GRilResponseFunc func, GRilResponseFunc func, gpointer user_data,
gpointer user_data, GDestroyNotify notify); GDestroyNotify notify);
guint g_ril_register(GRil *ril, const int req, guint g_ril_register(GRil *ril, const int req,
GRilNotifyFunc func, gpointer user_data); GRilNotifyFunc func, gpointer user_data);
@@ -138,7 +160,10 @@ guint g_ril_register(GRil *ril, const int req,
gboolean g_ril_unregister(GRil *ril, guint id); gboolean g_ril_unregister(GRil *ril, guint id);
gboolean g_ril_unregister_all(GRil *ril); 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 #ifdef __cplusplus
} }

View File

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

View File

@@ -29,6 +29,8 @@ extern "C" {
#include "gfunc.h" #include "gfunc.h"
#define GRIL_BUFFER_SIZE 8192
struct _GRilIO; struct _GRilIO;
typedef struct _GRilIO 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 */

View File

@@ -35,7 +35,6 @@
#include <ofono/types.h> #include <ofono/types.h>
#include "grilutil.h" #include "grilutil.h"
#include "parcel.h"
#include "ril_constants.h" #include "ril_constants.h"
/* Constants used by CALL_LIST, and SETUP_DATA_CALL RIL requests */ /* Constants used by CALL_LIST, and SETUP_DATA_CALL RIL requests */
@@ -43,26 +42,7 @@
#define PROTO_IPV6_STR "IPV6" #define PROTO_IPV6_STR "IPV6"
#define PROTO_IPV4V6_STR "IPV4V6" #define PROTO_IPV4V6_STR "IPV4V6"
const char *ril_ofono_protocol_to_ril_string(guint protocol) static char temp_str[32];
{
char *result;
switch (protocol) {
case OFONO_GPRS_PROTO_IPV6:
result = PROTO_IPV6_STR;
break;
case OFONO_GPRS_PROTO_IPV4V6:
result = PROTO_IPV4V6_STR;
break;
case OFONO_GPRS_PROTO_IP:
result = PROTO_IP_STR;
break;
default:
result = NULL;
}
return result;
}
int ril_protocol_string_to_ofono_protocol(gchar *protocol_str) int ril_protocol_string_to_ofono_protocol(gchar *protocol_str)
{ {
@@ -80,64 +60,8 @@ int ril_protocol_string_to_ofono_protocol(gchar *protocol_str)
return result; return result;
} }
const char *ril_appstate_to_string(int app_state)
{
switch (app_state) {
case RIL_APPSTATE_UNKNOWN:
return "UNKNOWN";
case RIL_APPSTATE_DETECTED:
return "DETECTED";
case RIL_APPSTATE_PIN:
return "PIN";
case RIL_APPSTATE_PUK:
return "PUK";
case RIL_APPSTATE_SUBSCRIPTION_PERSO:
return "";
case RIL_APPSTATE_READY:
return "READY";
default:
return "<INVALID>";
}
}
const char *ril_apptype_to_string(int app_type)
{
switch (app_type) {
case RIL_APPTYPE_UNKNOWN:
return "UNKNOWN";
case RIL_APPTYPE_SIM:
return "SIM";
case RIL_APPTYPE_USIM:
return "USIM";
case RIL_APPTYPE_RUIM:
return "RUIM";
case RIL_APPTYPE_CSIM:
return "CSIM";
case RIL_APPTYPE_ISIM:
return "ISIM";
default:
return "<INVALID>";
}
}
const char *ril_cardstate_to_string(int card_state)
{
switch (card_state) {
case RIL_CARDSTATE_ABSENT:
return "ABSENT";
case RIL_CARDSTATE_PRESENT:
return "PRESENT";
case RIL_CARDSTATE_ERROR:
return "ERROR";
default:
return "<INVALID>";
}
}
const char *ril_error_to_string(int error) const char *ril_error_to_string(int error)
{ {
static char unknown[24];
switch (error) { switch (error) {
case RIL_E_SUCCESS: return "SUCCESS"; case RIL_E_SUCCESS: return "SUCCESS";
case RIL_E_RADIO_NOT_AVAILABLE: return "RADIO_NOT_AVAILABLE"; case RIL_E_RADIO_NOT_AVAILABLE: return "RADIO_NOT_AVAILABLE";
@@ -158,27 +82,36 @@ const char *ril_error_to_string(int error)
case RIL_E_MODE_NOT_SUPPORTED: return "MODE_NOT_SUPPORTED"; case RIL_E_MODE_NOT_SUPPORTED: return "MODE_NOT_SUPPORTED";
case RIL_E_FDN_CHECK_FAILURE: return "FDN_CHECK_FAILURE"; case RIL_E_FDN_CHECK_FAILURE: return "FDN_CHECK_FAILURE";
case RIL_E_ILLEGAL_SIM_OR_ME: return "ILLEGAL_SIM_OR_ME"; case RIL_E_ILLEGAL_SIM_OR_ME: return "ILLEGAL_SIM_OR_ME";
default: case RIL_E_DIAL_MODIFIED_TO_USSD: return "DIAL_MODIFIED_TO_USSD";
snprintf(unknown, sizeof(unknown), "%d", error); case RIL_E_DIAL_MODIFIED_TO_SS: return "DIAL_MODIFIED_TO_SS";
return unknown; case RIL_E_DIAL_MODIFIED_TO_DIAL: return "DIAL_MODIFIED_TO_DIAL";
case RIL_E_USSD_MODIFIED_TO_DIAL: return "USSD_MODIFIED_TO_DIAL";
case RIL_E_USSD_MODIFIED_TO_SS: return "USSD_MODIFIED_TO_SS";
case RIL_E_USSD_MODIFIED_TO_USSD: return "USSD_MODIFIED_TO_USSD";
case RIL_E_SS_MODIFIED_TO_DIAL: return "SS_MODIFIED_TO_DIAL";
case RIL_E_SS_MODIFIED_TO_USSD: return "SS_MODIFIED_TO_USSD";
case RIL_E_SS_MODIFIED_TO_SS: return "SS_MODIFIED_TO_SS";
case RIL_E_SUBSCRIPTION_NOT_SUPPORTED:
return "SUBSCRIPTION_NOT_SUPPORTED";
default: return "<unknown errno>";
} }
} }
const char *ril_pinstate_to_string(int pin_state) const char *ril_radio_state_to_string(int radio_state)
{ {
switch (pin_state) { switch (radio_state) {
case RIL_PINSTATE_UNKNOWN: case RADIO_STATE_OFF:
return "UNKNOWN"; return "OFF";
case RIL_PINSTATE_ENABLED_NOT_VERIFIED: case RADIO_STATE_UNAVAILABLE:
return "ENABLED_NOT_VERIFIED"; return "UNAVAILABLE";
case RIL_PINSTATE_ENABLED_VERIFIED: case RADIO_STATE_SIM_NOT_READY:
return "ENABLED_VERIFIED"; return "SIM_NOT_READY";
case RIL_PINSTATE_DISABLED: case RADIO_STATE_SIM_LOCKED_OR_ABSENT:
return "DISABLED"; return "SIM_LOCKED_OR_ABSENT";
case RIL_PINSTATE_ENABLED_BLOCKED: case RADIO_STATE_SIM_READY:
return "ENABLED_BLOCKED"; return "SIM_READY";
case RIL_PINSTATE_ENABLED_PERM_BLOCKED: case RADIO_STATE_ON:
return "ENABLED_PERM_BLOCKED"; return "ON";
default: default:
return "<INVALID>"; return "<INVALID>";
} }
@@ -186,7 +119,6 @@ const char *ril_pinstate_to_string(int pin_state)
const char *ril_request_id_to_string(int req) const char *ril_request_id_to_string(int req)
{ {
static char unknown[24];
switch (req) { switch (req) {
case RIL_REQUEST_GET_SIM_STATUS: case RIL_REQUEST_GET_SIM_STATUS:
return "RIL_REQUEST_GET_SIM_STATUS"; return "RIL_REQUEST_GET_SIM_STATUS";
@@ -402,17 +334,17 @@ const char *ril_request_id_to_string(int req)
return "RIL_REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU"; return "RIL_REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU";
case RIL_REQUEST_STK_SEND_ENVELOPE_WITH_STATUS: case RIL_REQUEST_STK_SEND_ENVELOPE_WITH_STATUS:
return "RIL_REQUEST_STK_SEND_ENVELOPE_WITH_STATUS"; return "RIL_REQUEST_STK_SEND_ENVELOPE_WITH_STATUS";
case RIL_REQUEST_SET_UICC_SUBSCRIPTION: case RIL_REQUEST_GET_CELL_INFO_LIST:
return "RIL_REQUEST_SET_UICC_SUBSCRIPTION"; return "RIL_REQUEST_GET_CELL_INFO_LIST";
case RIL_REQUEST_SET_INITIAL_ATTACH_APN:
return "RIL_REQUEST_SET_INITIAL_ATTACH_APN";
default: default:
snprintf(unknown, sizeof(unknown), "RIL_REQUEST_%d", req); return "<INVALID>";
return unknown;
} }
} }
const char *ril_unsol_request_to_string(int request) const char *ril_unsol_request_to_string(int request)
{ {
static char unknown[24];
switch (request) { switch (request) {
case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED: case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED:
return "UNSOL_RESPONSE_RADIO_STATE_CHANGED"; return "UNSOL_RESPONSE_RADIO_STATE_CHANGED";
@@ -434,6 +366,8 @@ const char *ril_unsol_request_to_string(int request)
return "UNSOL_NITZ_TIME_RECEIVED"; return "UNSOL_NITZ_TIME_RECEIVED";
case RIL_UNSOL_SIGNAL_STRENGTH: case RIL_UNSOL_SIGNAL_STRENGTH:
return "UNSOL_SIGNAL_STRENGTH"; return "UNSOL_SIGNAL_STRENGTH";
case RIL_UNSOL_SUPP_SVC_NOTIFICATION:
return "UNSOL_SUPP_SVC_NOTIFICATION";
case RIL_UNSOL_STK_SESSION_END: case RIL_UNSOL_STK_SESSION_END:
return "UNSOL_STK_SESSION_END"; return "UNSOL_STK_SESSION_END";
case RIL_UNSOL_STK_PROACTIVE_COMMAND: case RIL_UNSOL_STK_PROACTIVE_COMMAND:
@@ -482,114 +416,69 @@ const char *ril_unsol_request_to_string(int request)
return "UNSOL_EXIT_EMERGENCY_CALLBACK_MODE"; return "UNSOL_EXIT_EMERGENCY_CALLBACK_MODE";
case RIL_UNSOL_RIL_CONNECTED: case RIL_UNSOL_RIL_CONNECTED:
return "UNSOL_RIL_CONNECTED"; return "UNSOL_RIL_CONNECTED";
case RIL_UNSOL_SUPP_SVC_NOTIFICATION:
return "UNSOL_SUPP_SVC_NOTIFICATION";
default: default:
snprintf(unknown, sizeof(unknown), "UNSOL_%d", request); return "<unknown request>";
return unknown;
} }
} }
void g_ril_util_debug_chat(gboolean in, const char *str, gsize len, const char *ril_pdp_fail_to_string(int status)
GRilDebugFunc debugf, gpointer user_data)
{ {
char type = in ? '<' : '>'; switch (status) {
gsize escaped = 2; /* Enough for '<', ' ' */ case PDP_FAIL_NONE:
char *escaped_str; return "NONE";
const char *esc = "<ESC>"; case PDP_FAIL_OPERATOR_BARRED:
gsize esc_size = strlen(esc); return "OPERATOR_BARRED";
const char *ctrlz = "<CtrlZ>"; case PDP_FAIL_INSUFFICIENT_RESOURCES:
gsize ctrlz_size = strlen(ctrlz); return "INSUFFICIENT_RESOURCES";
gsize i; case PDP_FAIL_MISSING_UKNOWN_APN:
return "MISSING_UKNOWN_APN";
if (debugf == NULL || !len) case PDP_FAIL_UNKNOWN_PDP_ADDRESS_TYPE:
return; return "UNKNOWN_PDP_ADDRESS_TYPE";
case PDP_FAIL_USER_AUTHENTICATION:
for (i = 0; i < len; i++) { return "USER_AUTHENTICATION";
char c = str[i]; case PDP_FAIL_ACTIVATION_REJECT_GGSN:
return "ACTIVATION_REJECT_GGSN";
if (g_ascii_isprint(c)) case PDP_FAIL_ACTIVATION_REJECT_UNSPECIFIED:
escaped += 1; return "ACTIVATION_REJECT_UNSPECIFIED";
else if (c == '\r' || c == '\t' || c == '\n') case PDP_FAIL_SERVICE_OPTION_NOT_SUPPORTED:
escaped += 2; return "SERVICE_OPTION_NOT_SUPPORTED";
else if (c == 26) case PDP_FAIL_SERVICE_OPTION_NOT_SUBSCRIBED:
escaped += ctrlz_size; return "SERVICE_OPTION_NOT_SUBSCRIBED";
else if (c == 25) case PDP_FAIL_SERVICE_OPTION_OUT_OF_ORDER:
escaped += esc_size; return "SERVICE_OPTION_OUT_OF_ORDER";
case PDP_FAIL_NSAPI_IN_USE:
return "NSAPI_IN_USE";
case PDP_FAIL_REGULAR_DEACTIVATION:
return "REGULAR_DEACTIVATION";
case PDP_FAIL_ONLY_IPV4_ALLOWED:
return "ONLY_IPV4_ALLOWED";
case PDP_FAIL_ONLY_IPV6_ALLOWED:
return "ONLY_IPV6_ALLOWED";
case PDP_FAIL_ONLY_SINGLE_BEARER_ALLOWED:
return "ONLY_SINGLE_BEARER_ALLOWED";
case PDP_FAIL_PROTOCOL_ERRORS:
return "PROTOCOL_ERRORS";
case PDP_FAIL_VOICE_REGISTRATION_FAIL:
return "VOICE_REGISTRATION_FAIL";
case PDP_FAIL_DATA_REGISTRATION_FAIL:
return "DATA_REGISTRATION_FAIL";
case PDP_FAIL_SIGNAL_LOST:
return "SIGNAL_LOST";
case PDP_FAIL_PREF_RADIO_TECH_CHANGED:
return "PREF_RADIO_TECH_CHANGED";
case PDP_FAIL_RADIO_POWER_OFF:
return "RADIO_POWER_OFF";
case PDP_FAIL_TETHERED_CALL_ACTIVE:
return "TETHERED_CALL_ACTIVE";
case PDP_FAIL_ERROR_UNSPECIFIED:
return "ERROR_UNSPECIFIED";
default:
if (g_snprintf(temp_str, sizeof(temp_str),
"<UNKNOWN (%d)>", status))
return temp_str;
else else
escaped += 4; return "<UNKNOWN>";
} }
escaped_str = g_try_malloc(escaped + 1);
if (escaped_str == NULL)
return;
escaped_str[0] = type;
escaped_str[1] = ' ';
escaped_str[2] = '\0';
escaped_str[escaped] = '\0';
for (escaped = 2, i = 0; i < len; i++) {
unsigned char c = str[i];
switch (c) {
case '\r':
escaped_str[escaped++] = '\\';
escaped_str[escaped++] = 'r';
break;
case '\t':
escaped_str[escaped++] = '\\';
escaped_str[escaped++] = 't';
break;
case '\n':
escaped_str[escaped++] = '\\';
escaped_str[escaped++] = 'n';
break;
case 26:
strncpy(&escaped_str[escaped], ctrlz, ctrlz_size);
escaped += ctrlz_size;
break;
case 25:
strncpy(&escaped_str[escaped], esc, esc_size);
escaped += esc_size;
break;
default:
if (g_ascii_isprint(c))
escaped_str[escaped++] = c;
else {
escaped_str[escaped++] = '\\';
escaped_str[escaped++] = '0' + ((c >> 6) & 07);
escaped_str[escaped++] = '0' + ((c >> 3) & 07);
escaped_str[escaped++] = '0' + (c & 07);
}
}
}
debugf(escaped_str, user_data);
g_free(escaped_str);
}
void g_ril_util_debug_dump(gboolean in, const unsigned char *buf, gsize len,
GRilDebugFunc debugf, gpointer user_data)
{
char type = in ? '<' : '>';
GString *str;
gsize i;
if (debugf == NULL || !len)
return;
str = g_string_sized_new(1 + (len * 2));
if (str == NULL)
return;
g_string_append_c(str, type);
for (i = 0; i < len; i++)
g_string_append_printf(str, " %02x", buf[i]);
debugf(str->str, user_data);
g_string_free(str, TRUE);
} }
void g_ril_util_debug_hexdump(gboolean in, const unsigned char *buf, gsize len, void g_ril_util_debug_hexdump(gboolean in, const unsigned char *buf, gsize len,

View File

@@ -31,29 +31,12 @@ extern "C" {
#include "parcel.h" #include "parcel.h"
#include "gril.h" #include "gril.h"
enum online_states {
RIL_OFFLINE,
RIL_ONLINE_PREF,
RIL_ONLINE,
};
static const char defaultpasswd[] = "NOTGIVEN";
const char *ril_ofono_protocol_to_ril_string(guint protocol);
int ril_protocol_string_to_ofono_protocol(gchar *protocol_str); int ril_protocol_string_to_ofono_protocol(gchar *protocol_str);
const char *ril_appstate_to_string(int app_state);
const char *ril_apptype_to_string(int app_type);
const char *ril_cardstate_to_string(int card_state);
const char *ril_error_to_string(int error); const char *ril_error_to_string(int error);
const char *ril_pinstate_to_string(int pin_state); const char *ril_radio_state_to_string(int radio_state);
const char *ril_request_id_to_string(int req); const char *ril_request_id_to_string(int req);
const char *ril_unsol_request_to_string(int request); const char *ril_unsol_request_to_string(int request);
const char *ril_pdp_fail_to_string(int status);
void g_ril_util_debug_chat(gboolean in, const char *str, gsize len,
GRilDebugFunc debugf, gpointer user_data);
void g_ril_util_debug_dump(gboolean in, const unsigned char *buf, gsize len,
GRilDebugFunc debugf, gpointer user_data);
void g_ril_util_debug_hexdump(gboolean in, const unsigned char *buf, gsize len, void g_ril_util_debug_hexdump(gboolean in, const unsigned char *buf, gsize len,
GRilDebugFunc debugf, gpointer user_data); GRilDebugFunc debugf, gpointer user_data);

View File

@@ -1,7 +1,6 @@
/* /*
* Copyright (C) 2011 Joel Armstrong <jcarmst@sandia.gov> * Copyright (C) 2011 Joel Armstrong <jcarmst@sandia.gov>
* Copyright (C) 2012 Canonical Ltd. * Copyright (C) 2012 Canonical Ltd.
* Copyright (C) 2013 Jolla Ltd.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License (`GPL') as published by * it under the terms of the GNU General Public License (`GPL') as published by
@@ -33,6 +32,8 @@
#include <glib.h> #include <glib.h>
#include <ofono/log.h>
/* Parcel-handling code */ /* Parcel-handling code */
#include <sys/types.h> #include <sys/types.h>
#include <string.h> #include <string.h>
@@ -52,6 +53,7 @@ void parcel_init(struct parcel *p)
p->size = 0; p->size = 0;
p->capacity = sizeof(int32_t); p->capacity = sizeof(int32_t);
p->offset = 0; p->offset = 0;
p->malformed = 0;
} }
void parcel_grow(struct parcel *p, size_t size) void parcel_grow(struct parcel *p, size_t size)
@@ -72,7 +74,17 @@ void parcel_free(struct parcel *p)
int32_t parcel_r_int32(struct parcel *p) int32_t parcel_r_int32(struct parcel *p)
{ {
int32_t ret; int32_t ret;
ret = *((int32_t *) (p->data + p->offset));
if (p->malformed)
return 0;
if (p->offset + sizeof(int32_t) > p->size) {
ofono_error("%s: parcel is too small", __func__);
p->malformed = 1;
return 0;
}
ret = *((int32_t *) (void *) (p->data + p->offset));
p->offset += sizeof(int32_t); p->offset += sizeof(int32_t);
return ret; return ret;
} }
@@ -83,7 +95,7 @@ int parcel_w_int32(struct parcel *p, int32_t val)
if (p->offset + sizeof(int32_t) < p->capacity) { if (p->offset + sizeof(int32_t) < p->capacity) {
/* There's enough space */ /* There's enough space */
*((int32_t *) (p->data + p->offset)) = val; *((int32_t *) (void *) (p->data + p->offset)) = val;
p->offset += sizeof(int32_t); p->offset += sizeof(int32_t);
p->size += sizeof(int32_t); p->size += sizeof(int32_t);
break; break;
@@ -95,24 +107,7 @@ int parcel_w_int32(struct parcel *p, int32_t val)
return 0; return 0;
} }
int parcel_w_byte(struct parcel *p, const char val) int parcel_w_string(struct parcel *p, const char *str)
{
for (;;) {
if (p->offset + sizeof(char) < p->capacity) {
/* There's enough space */
*((char *) (p->data + p->offset)) = val;
p->offset += sizeof(char);
p->size += sizeof(char);
break;
} else {
/* Grow data and retry */
parcel_grow(p, sizeof(int32_t));
}
}
return 0;
}
int parcel_w_string(struct parcel *p, char *str)
{ {
gunichar2 *gs16; gunichar2 *gs16;
glong gs16_len; glong gs16_len;
@@ -126,9 +121,8 @@ int parcel_w_string(struct parcel *p, char *str)
gs16 = g_utf8_to_utf16(str, -1, NULL, &gs16_len, NULL); gs16 = g_utf8_to_utf16(str, -1, NULL, &gs16_len, NULL);
if (parcel_w_int32(p, gs16_len) == -1) { if (parcel_w_int32(p, gs16_len) == -1)
return -1; return -1;
}
gs16_size = gs16_len * sizeof(char16_t); gs16_size = gs16_len * sizeof(char16_t);
len = gs16_size + sizeof(char16_t); len = gs16_size + sizeof(char16_t);
@@ -138,7 +132,8 @@ int parcel_w_string(struct parcel *p, char *str)
if (p->offset + len < p->capacity) { if (p->offset + len < p->capacity) {
/* There's enough space */ /* There's enough space */
memcpy(p->data + p->offset, gs16, gs16_size); memcpy(p->data + p->offset, gs16, gs16_size);
*((char16_t *) (p->data + p->offset + gs16_size)) = 0; *((char16_t *) (void *)
(p->data + p->offset + gs16_size)) = 0;
p->offset += padded; p->offset += padded;
p->size += padded; p->size += padded;
if (padded != len) { if (padded != len) {
@@ -155,7 +150,9 @@ int parcel_w_string(struct parcel *p, char *str)
0x0000ffff, 0x000000ff 0x0000ffff, 0x000000ff
}; };
#endif #endif
*((uint32_t*)(p->data + p->offset - 4)) &=
*((uint32_t *) (void *)
(p->data + p->offset - 4)) &=
mask[padded - len]; mask[padded - len];
} }
break; break;
@@ -170,26 +167,135 @@ int parcel_w_string(struct parcel *p, char *str)
return 0; return 0;
} }
char* parcel_r_string(struct parcel *p) char *parcel_r_string(struct parcel *p)
{ {
char *ret; char *ret;
int len16 = parcel_r_int32(p); int len16 = parcel_r_int32(p);
int strbytes;
if (p->malformed)
return NULL;
/* This is how a null string is sent */ /* This is how a null string is sent */
if (len16 < 0) if (len16 < 0)
return NULL; return NULL;
ret = g_utf16_to_utf8((gunichar2 *) (p->data + p->offset), strbytes = PAD_SIZE((len16 + 1) * sizeof(char16_t));
if (p->offset + strbytes > p->size) {
ofono_error("%s: parcel is too small", __func__);
p->malformed = 1;
return NULL;
}
ret = g_utf16_to_utf8((gunichar2 *) (void *) (p->data + p->offset),
len16, NULL, NULL, NULL); len16, NULL, NULL, NULL);
if (ret == NULL) if (ret == NULL) {
ofono_error("%s: wrong UTF16 coding", __func__);
p->malformed = 1;
return NULL;
}
p->offset += strbytes;
return ret;
}
void parcel_skip_string(struct parcel *p)
{
int len16 = parcel_r_int32(p);
int strbytes;
if (p->malformed)
return;
/* This is how a null string is sent */
if (len16 < 0)
return;
strbytes = PAD_SIZE((len16 + 1) * sizeof(char16_t));
if (p->offset + strbytes > p->size) {
p->malformed = 1;
return;
}
p->offset += strbytes;
}
int parcel_w_raw(struct parcel *p, const void *data, size_t len)
{
if (data == NULL) {
parcel_w_int32(p, -1);
return 0;
}
parcel_w_int32(p, len);
for (;;) {
if (p->offset + len < p->capacity) {
/* There's enough space */
memcpy(p->data + p->offset, data, len);
p->offset += len;
p->size += len;
break;
} else {
/* Grow data and retry */
parcel_grow(p, len);
}
}
return 0;
}
void *parcel_r_raw(struct parcel *p, int *len)
{
char *ret;
*len = parcel_r_int32(p);
if (p->malformed || *len <= 0)
return NULL; return NULL;
p->offset += PAD_SIZE((len16 + 1) * sizeof(char16_t)); if (p->offset + *len > p->size) {
ofono_error("%s: parcel is too small", __func__);
p->malformed = 1;
return NULL;
}
ret = g_try_malloc0(*len);
if (ret == NULL) {
ofono_error("%s: out of memory (%d bytes)", __func__, *len);
return NULL;
}
memcpy(ret, p->data + p->offset, *len);
p->offset += *len;
return ret; return ret;
} }
size_t parcel_data_avail(struct parcel *p) size_t parcel_data_avail(struct parcel *p)
{ {
return (p->size - p->offset); return p->size - p->offset;
}
char **parcel_r_strv(struct parcel *p)
{
int i;
int num_str = parcel_r_int32(p);
char **strv;
if (p->malformed || num_str <= 0)
return NULL;
strv = g_new0(char *, num_str + 1);
for (i = 0; i < num_str; i++)
strv[i] = parcel_r_string(p);
if (p->malformed) {
g_strfreev(strv);
strv = NULL;
}
return strv;
} }

View File

@@ -1,6 +1,5 @@
/* /*
* Copyright © 2011 Joel Armstrong <jcarmst@sandia.gov> * Copyright © 2011 Joel Armstrong <jcarmst@sandia.gov>
* Copyright © 2013 Jolla Ltd.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License (`GPL') as published by * it under the terms of the GNU General Public License (`GPL') as published by
@@ -30,6 +29,7 @@ struct parcel {
size_t offset; size_t offset;
size_t capacity; size_t capacity;
size_t size; size_t size;
int malformed;
}; };
void parcel_init(struct parcel *p); void parcel_init(struct parcel *p);
@@ -37,9 +37,12 @@ void parcel_grow(struct parcel *p, size_t size);
void parcel_free(struct parcel *p); void parcel_free(struct parcel *p);
int32_t parcel_r_int32(struct parcel *p); int32_t parcel_r_int32(struct parcel *p);
int parcel_w_int32(struct parcel *p, int32_t val); int parcel_w_int32(struct parcel *p, int32_t val);
int parcel_w_byte(struct parcel *p, const char val); int parcel_w_string(struct parcel *p, const char *str);
int parcel_w_string(struct parcel *p, char *str);
char *parcel_r_string(struct parcel *p); char *parcel_r_string(struct parcel *p);
void parcel_skip_string(struct parcel *p);
int parcel_w_raw(struct parcel *p, const void *data, size_t len);
void *parcel_r_raw(struct parcel *p, int *len);
size_t parcel_data_avail(struct parcel *p); size_t parcel_data_avail(struct parcel *p);
char **parcel_r_strv(struct parcel *p);
#endif #endif

View File

@@ -5,7 +5,6 @@
* /hardware/ril/reference_ril/ril.h * /hardware/ril/reference_ril/ril.h
* *
* Copyright (C) 2013 Canonical Ltd. * Copyright (C) 2013 Canonical Ltd.
* Copyright (C) 2013 Jolla Ltd.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
@@ -43,7 +42,12 @@
#define RIL_E_MODE_NOT_SUPPORTED 13 #define RIL_E_MODE_NOT_SUPPORTED 13
#define RIL_E_FDN_CHECK_FAILURE 14 #define RIL_E_FDN_CHECK_FAILURE 14
#define RIL_E_ILLEGAL_SIM_OR_ME 15 #define RIL_E_ILLEGAL_SIM_OR_ME 15
#define RIL_E_UNUSED 16 /*
* Following error codes are actually Qualcomm-specific, but as they are used by
* our reference platform, we consider them valid for vendor
* OFONO_RIL_VENDOR_AOSP. The definition comes from cyanogenmod ril.h, which in
* turn copied it from codeaurora.
*/
#define RIL_E_DIAL_MODIFIED_TO_USSD 17 #define RIL_E_DIAL_MODIFIED_TO_USSD 17
#define RIL_E_DIAL_MODIFIED_TO_SS 18 #define RIL_E_DIAL_MODIFIED_TO_SS 18
#define RIL_E_DIAL_MODIFIED_TO_DIAL 19 #define RIL_E_DIAL_MODIFIED_TO_DIAL 19
@@ -54,45 +58,45 @@
#define RIL_E_SS_MODIFIED_TO_USSD 24 #define RIL_E_SS_MODIFIED_TO_USSD 24
#define RIL_E_SS_MODIFIED_TO_SS 25 #define RIL_E_SS_MODIFIED_TO_SS 25
#define RIL_E_SUBSCRIPTION_NOT_SUPPORTED 26 #define RIL_E_SUBSCRIPTION_NOT_SUPPORTED 26
#define RIL_E_MISSING_RESOURCE 27
#define RIL_E_NO_SUCH_ELEMENT 28
#define RIL_E_INVALID_PARAMETER 29
/* call states */ /*
#define RIL_CALL_ACTIVE 0 * Data Call Failure causes ( see TS 24.008 )
#define RIL_CALL_HOLDING 1 * section 6.1.3.1.3 or TS 24.301 Release 8+ Annex B.
#define RIL_CALL_DIALING 2 */
#define RIL_CALL_ALERTING 3 #define PDP_FAIL_NONE 0
#define RIL_CALL_INCOMING 4 #define PDP_FAIL_OPERATOR_BARRED 0x08
#define RIL_CALL_WAITING 5 #define PDP_FAIL_INSUFFICIENT_RESOURCES 0x1A
#define PDP_FAIL_MISSING_UKNOWN_APN 0x1B
#define PDP_FAIL_UNKNOWN_PDP_ADDRESS_TYPE 0x1C
#define PDP_FAIL_USER_AUTHENTICATION 0x1D
#define PDP_FAIL_ACTIVATION_REJECT_GGSN 0x1E
#define PDP_FAIL_ACTIVATION_REJECT_UNSPECIFIED 0x1F
#define PDP_FAIL_SERVICE_OPTION_NOT_SUPPORTED 0x20
#define PDP_FAIL_SERVICE_OPTION_NOT_SUBSCRIBED 0x21
#define PDP_FAIL_SERVICE_OPTION_OUT_OF_ORDER 0x22
#define PDP_FAIL_NSAPI_IN_USE 0x23
#define PDP_FAIL_REGULAR_DEACTIVATION 0x24 /* restart radio */
#define PDP_FAIL_ONLY_IPV4_ALLOWED 0x32
#define PDP_FAIL_ONLY_IPV6_ALLOWED 0x33
#define PDP_FAIL_ONLY_SINGLE_BEARER_ALLOWED 0x34
#define PDP_FAIL_PROTOCOL_ERRORS 0x6F
#define PDP_FAIL_VOICE_REGISTRATION_FAIL -1
#define PDP_FAIL_DATA_REGISTRATION_FAIL -2
#define PDP_FAIL_SIGNAL_LOST -3
#define PDP_FAIL_PREF_RADIO_TECH_CHANGED -4
#define PDP_FAIL_RADIO_POWER_OFF -5
#define PDP_FAIL_TETHERED_CALL_ACTIVE -6
#define PDP_FAIL_ERROR_UNSPECIFIED 0xffff
/* Radio state */ /* Radio States */
#define RADIO_STATE_OFF 0 #define RADIO_STATE_OFF 0
#define RADIO_STATE_UNAVAILABLE 1 #define RADIO_STATE_UNAVAILABLE 1
#define RADIO_STATE_ON 10
/* Deprecated, but still used by some modems */
#define RADIO_STATE_SIM_NOT_READY 2 #define RADIO_STATE_SIM_NOT_READY 2
#define RADIO_STATE_SIM_LOCKED_OR_ABSENT 3 #define RADIO_STATE_SIM_LOCKED_OR_ABSENT 3
#define RADIO_STATE_SIM_READY 4 #define RADIO_STATE_SIM_READY 4
#define RADIO_STATE_RUIM_NOT_READY 5
#define RADIO_STATE_RUIM_READY 6
#define RADIO_STATE_RUIM_LOCKED_OR_ABSENT 7
#define RADIO_STATE_NV_NOT_READY 8
#define RADIO_STATE_NV_READY 9
#define RADIO_STATE_ON 10
/* 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
/* Radio technologies */ /* Radio technologies */
#define RADIO_TECH_UNKNOWN 0 #define RADIO_TECH_UNKNOWN 0
@@ -112,8 +116,18 @@
#define RADIO_TECH_LTE 14 #define RADIO_TECH_LTE 14
#define RADIO_TECH_HSPAP 15 #define RADIO_TECH_HSPAP 15
#define RADIO_TECH_GSM 16 #define RADIO_TECH_GSM 16
#define RADIO_TECH_TD_SCDMA 17 /* MTK specific values for radio technologies */
#define RADIO_TECH_DC_HSDPA 18 #define MTK_RADIO_TECH_BASE 128
#define MTK_RADIO_TECH_HSDPAP (MTK_RADIO_TECH_BASE + 1)
#define MTK_RADIO_TECH_HSDPAP_UPA (MTK_RADIO_TECH_BASE + 2)
#define MTK_RADIO_TECH_HSUPAP (MTK_RADIO_TECH_BASE + 3)
#define MTK_RADIO_TECH_HSUPAP_DPA (MTK_RADIO_TECH_BASE + 4)
#define MTK_RADIO_TECH_DC_DPA (MTK_RADIO_TECH_BASE + 5)
#define MTK_RADIO_TECH_DC_UPA (MTK_RADIO_TECH_BASE + 6)
#define MTK_RADIO_TECH_DC_HSDPAP (MTK_RADIO_TECH_BASE + 7)
#define MTK_RADIO_TECH_DC_HSDPAP_UPA (MTK_RADIO_TECH_BASE + 8)
#define MTK_RADIO_TECH_DC_HSDPAP_DPA (MTK_RADIO_TECH_BASE + 9)
#define MTK_RADIO_TECH_DC_HSPAP (MTK_RADIO_TECH_BASE + 10)
/* See RIL_REQUEST_LAST_CALL_FAIL_CAUSE */ /* See RIL_REQUEST_LAST_CALL_FAIL_CAUSE */
#define CALL_FAIL_UNOBTAINABLE_NUMBER 1 #define CALL_FAIL_UNOBTAINABLE_NUMBER 1
@@ -152,7 +166,16 @@
#define RIL_DATA_PROFILE_FOTA 3 /* FOTA = Firmware Over the Air */ #define RIL_DATA_PROFILE_FOTA 3 /* FOTA = Firmware Over the Air */
#define RIL_DATA_PROFILE_CBS 4 #define RIL_DATA_PROFILE_CBS 4
#define RIL_DATA_PROFILE_OEM_BASE 1000 /* Start of OEM-specific profiles */ #define RIL_DATA_PROFILE_OEM_BASE 1000 /* Start of OEM-specific profiles */
/* MTK specific profile for MMS */
#define RIL_DATA_PROFILE_MTK_MMS (RIL_DATA_PROFILE_OEM_BASE + 1)
/*
* auth type -1 seems to mean 0 (RIL_AUTH_NONE) if no user/password is
* specified or 3 (RIL_AUTH_BOTH) otherwise. See $ANDROID/packages/
* providers/TelephonyProvider/src/com/android/providers/telephony/
* TelephonyProvider.java.
*/
#define RIL_AUTH_ANY -1
#define RIL_AUTH_NONE 0 #define RIL_AUTH_NONE 0
#define RIL_AUTH_PAP 1 #define RIL_AUTH_PAP 1
#define RIL_AUTH_CHAP 2 #define RIL_AUTH_CHAP 2
@@ -163,7 +186,31 @@
#define RIL_CARDSTATE_PRESENT 1 #define RIL_CARDSTATE_PRESENT 1
#define RIL_CARDSTATE_ERROR 2 #define RIL_CARDSTATE_ERROR 2
/* SIM personalization substates */ /* SIM - App states */
#define RIL_APPSTATE_UNKNOWN 0
#define RIL_APPSTATE_DETECTED 1
#define RIL_APPSTATE_PIN 2
#define RIL_APPSTATE_PUK 3
#define RIL_APPSTATE_SUBSCRIPTION_PERSO 4
#define RIL_APPSTATE_READY 5
/* SIM - PIN states */
#define RIL_PINSTATE_UNKNOWN 0
#define RIL_PINSTATE_ENABLED_NOT_VERIFIED 1
#define RIL_PINSTATE_ENABLED_VERIFIED 2
#define RIL_PINSTATE_DISABLED 3
#define RIL_PINSTATE_ENABLED_BLOCKED 4
#define RIL_PINSTATE_ENABLED_PERM_BLOCKED 5
/* SIM - App types */
#define RIL_APPTYPE_UNKNOWN 0
#define RIL_APPTYPE_SIM 1
#define RIL_APPTYPE_USIM 2
#define RIL_APPTYPE_RUIM 3
#define RIL_APPTYPE_CSIM 4
#define RIL_APPTYPE_ISIM 5
/* SIM - PersoSubstate */
#define RIL_PERSOSUBSTATE_UNKNOWN 0 #define RIL_PERSOSUBSTATE_UNKNOWN 0
#define RIL_PERSOSUBSTATE_IN_PROGRESS 1 #define RIL_PERSOSUBSTATE_IN_PROGRESS 1
#define RIL_PERSOSUBSTATE_READY 2 #define RIL_PERSOSUBSTATE_READY 2
@@ -190,31 +237,6 @@
#define RIL_PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK 23 #define RIL_PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK 23
#define RIL_PERSOSUBSTATE_RUIM_RUIM_PUK 24 #define RIL_PERSOSUBSTATE_RUIM_RUIM_PUK 24
/* SIM - App states */
#define RIL_APPSTATE_ILLEGAL -1
#define RIL_APPSTATE_UNKNOWN 0
#define RIL_APPSTATE_DETECTED 1
#define RIL_APPSTATE_PIN 2
#define RIL_APPSTATE_PUK 3
#define RIL_APPSTATE_SUBSCRIPTION_PERSO 4
#define RIL_APPSTATE_READY 5
/* SIM - PIN states */
#define RIL_PINSTATE_UNKNOWN 0
#define RIL_PINSTATE_ENABLED_NOT_VERIFIED 1
#define RIL_PINSTATE_ENABLED_VERIFIED 2
#define RIL_PINSTATE_DISABLED 3
#define RIL_PINSTATE_ENABLED_BLOCKED 4
#define RIL_PINSTATE_ENABLED_PERM_BLOCKED 5
/* SIM - App types */
#define RIL_APPTYPE_UNKNOWN 0
#define RIL_APPTYPE_SIM 1
#define RIL_APPTYPE_USIM 2
#define RIL_APPTYPE_RUIM 3
#define RIL_APPTYPE_CSIM 4
#define RIL_APPTYPE_ISIM 5
/* RIL Request Messages */ /* RIL Request Messages */
#define RIL_REQUEST_GET_SIM_STATUS 1 #define RIL_REQUEST_GET_SIM_STATUS 1
#define RIL_REQUEST_ENTER_SIM_PIN 2 #define RIL_REQUEST_ENTER_SIM_PIN 2
@@ -325,20 +347,8 @@
#define RIL_REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU 106 #define RIL_REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU 106
#define RIL_REQUEST_STK_SEND_ENVELOPE_WITH_STATUS 107 #define RIL_REQUEST_STK_SEND_ENVELOPE_WITH_STATUS 107
#define RIL_REQUEST_VOICE_RADIO_TECH 108 #define RIL_REQUEST_VOICE_RADIO_TECH 108
#define RIL_REQUEST_IMS_REGISTRATION_STATE 109 #define RIL_REQUEST_GET_CELL_INFO_LIST 109
#define RIL_REQUEST_IMS_SEND_SMS 110 #define RIL_REQUEST_SET_INITIAL_ATTACH_APN 111
#define RIL_REQUEST_GET_DATA_CALL_PROFILE 111
#define RIL_REQUEST_SETUP_QOS 112
#define RIL_REQUEST_RELEASE_QOS 113
#define RIL_REQUEST_GET_QOS_STATUS 114
#define RIL_REQUEST_MODIFY_QOS 115
#define RIL_REQUEST_SUSPEND_QOS 116
#define RIL_REQUEST_RESUME_QOS 117
#define RIL_REQUEST_SET_UICC_SUBSCRIPTION 122
#define RIL_REQUEST_SET_DATA_SUBSCRIPTION 119
#define RIL_REQUEST_GET_UICC_SUBSCRIPTION 120
#define RIL_REQUEST_GET_DATA_SUBSCRIPTION 121
#define RIL_REQUEST_SET_SUBSCRIPTION_MODE 122
/* RIL Unsolicited Messages */ /* RIL Unsolicited Messages */
#define RIL_UNSOL_RESPONSE_BASE 1000 #define RIL_UNSOL_RESPONSE_BASE 1000
@@ -378,18 +388,20 @@
#define RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE 1033 #define RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE 1033
#define RIL_UNSOL_RIL_CONNECTED 1034 #define RIL_UNSOL_RIL_CONNECTED 1034
#define RIL_UNSOL_VOICE_RADIO_TECH_CHANGED 1035 #define RIL_UNSOL_VOICE_RADIO_TECH_CHANGED 1035
#define RIL_UNSOL_RESPONSE_IMS_NETWORK_STATE_CHANGED 1036
#define RIL_UNSOL_RESPONSE_TETHERED_MODE_STATE_CHANGED 1037
#define RIL_UNSOL_QOS_STATE_CHANGED_IND 1038
#define RIL_UNSOL_ON_SS 1039
#define RIL_UNSOL_STK_CC_ALPHA_NOTIFY 1040
#define RIL_UNSOL_UICC_SUBSCRIPTION_STATUS_CHANGED 1041
/* Suplementary services Service class*/ /* Suplementary services Service class*/
#define SERVICE_CLASS_NONE 0 #define SERVICE_CLASS_NONE 0
/* RIL_FACILITY_LOCK parameters */ /* Network registration states */
#define RIL_FACILITY_UNLOCK "0" #define RIL_REG_STATE_NOT_REGISTERED 0
#define RIL_FACILITY_LOCK "1" #define RIL_REG_STATE_REGISTERED 1
#define RIL_REG_STATE_SEARCHING 2
#define RIL_REG_STATE_DENIED 3
#define RIL_REG_STATE_UNKNOWN 4
#define RIL_REG_STATE_ROAMING 5
#define RIL_REG_STATE_EMERGENCY_NOT_REGISTERED 10
#define RIL_REG_STATE_EMERGENCY_SEARCHING 12
#define RIL_REG_STATE_EMERGENCY_DENIED 13
#define RIL_REG_STATE_EMERGENCY_UNKNOWN 14
#endif /*__RIL_CONSTANTS_H*/ #endif /*__RIL_CONSTANTS_H*/

View File

@@ -1,15 +0,0 @@
# This is configuration file for ril
#
# current subscription possibilities are
# - none ( leave lines commented out ). Works with old ril version
# - SUB1 (sub=SUB1)
# - SUB2 (sub=SUB2)
#
# current lte configuration possibilities
# - none ( leave lines commented out ). LTE is not supported
# - 4gOn LTE is supported
#[sub]
#sub=SUB1
#[4gOn]

View File

@@ -1,107 +0,0 @@
/*
*
* AT chat library with GLib integration
*
* Copyright (C) 2008-2011 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
*
*/
struct ring_buffer;
/*!
* Creates a new ring buffer with capacity size
*/
struct ring_buffer *ring_buffer_new(unsigned int size);
/*!
* Frees the resources allocated for the ring buffer
*/
void ring_buffer_free(struct ring_buffer *buf);
/*!
* Returns the capacity of the ring buffer
*/
int ring_buffer_capacity(struct ring_buffer *buf);
/*!
* Resets the ring buffer, all data inside the buffer is lost
*/
void ring_buffer_reset(struct ring_buffer *buf);
/*!
* Writes data of size len into the ring buffer buf. Returns -1 if the
* write failed or the number of bytes written
*/
int ring_buffer_write(struct ring_buffer *buf, const void *data,
unsigned int len);
/*!
* Advances the write counter by len, this is meant to be used with
* the ring_buffer_write_ptr function. Returns the number of bytes
* actually advanced (the capacity of the buffer)
*/
int ring_buffer_write_advance(struct ring_buffer *buf, unsigned int len);
/*!
* Returns the write pointer with write offset specified by offset. Careful
* not to write past the end of the buffer. Use the ring_buffer_avail_no_wrap
* function, and ring_buffer_write_advance.
*/
unsigned char *ring_buffer_write_ptr(struct ring_buffer *buf,
unsigned int offset);
/*!
* Returns the number of free bytes available in the buffer
*/
int ring_buffer_avail(struct ring_buffer *buf);
/*!
* Returns the number of free bytes available in the buffer without wrapping
*/
int ring_buffer_avail_no_wrap(struct ring_buffer *buf);
/*!
* Reads data from the ring buffer buf into memory region pointed to by data.
* A maximum of len bytes will be read. Returns -1 if the read failed or
* the number of bytes read
*/
int ring_buffer_read(struct ring_buffer *buf, void *data,
unsigned int len);
/*!
* Returns the read pointer with read offset specified by offset. No bounds
* checking is performed. Be careful not to read past the end of the buffer.
* Use the ring_buffer_len_no_wrap function, and ring_buffer_drain.
*/
unsigned char *ring_buffer_read_ptr(struct ring_buffer *buf,
unsigned int offset);
/*!
* Returns the number of bytes currently available to be read in the buffer
*/
int ring_buffer_len(struct ring_buffer *buf);
/*!
* Returns the number of bytes currently available to be read in the buffer
* without wrapping.
*/
int ring_buffer_len_no_wrap(struct ring_buffer *buf);
/*!
* Drains the ring buffer of len bytes. Returns the number of bytes the
* read counter was actually advanced.
*/
int ring_buffer_drain(struct ring_buffer *buf, unsigned int len);

View File

@@ -62,6 +62,7 @@ extern "C" {
#define OFONO_HANDSFREE_INTERFACE OFONO_SERVICE ".Handsfree" #define OFONO_HANDSFREE_INTERFACE OFONO_SERVICE ".Handsfree"
#define OFONO_NETWORK_TIME_INTERFACE OFONO_SERVICE ".NetworkTime" #define OFONO_NETWORK_TIME_INTERFACE OFONO_SERVICE ".NetworkTime"
#define OFONO_SIRI_INTERFACE OFONO_SERVICE ".Siri" #define OFONO_SIRI_INTERFACE OFONO_SERVICE ".Siri"
#define OFONO_NETMON_INTERFACE OFONO_SERVICE ".NetworkMonitor"
/* CDMA Interfaces */ /* CDMA Interfaces */
#define OFONO_CDMA_VOICECALL_MANAGER_INTERFACE "org.ofono.cdma.VoiceCallManager" #define OFONO_CDMA_VOICECALL_MANAGER_INTERFACE "org.ofono.cdma.VoiceCallManager"

View File

@@ -46,6 +46,8 @@ struct ofono_devinfo_driver {
ofono_devinfo_query_cb_t cb, void *data); ofono_devinfo_query_cb_t cb, void *data);
void (*query_revision)(struct ofono_devinfo *info, void (*query_revision)(struct ofono_devinfo *info,
ofono_devinfo_query_cb_t cb, void *data); ofono_devinfo_query_cb_t cb, void *data);
void (*query_svn)(struct ofono_devinfo *info,
ofono_devinfo_query_cb_t cb, void *data);
}; };
int ofono_devinfo_driver_register(const struct ofono_devinfo_driver *d); int ofono_devinfo_driver_register(const struct ofono_devinfo_driver *d);

View File

@@ -50,6 +50,7 @@ extern "C" {
struct ofono_emulator; struct ofono_emulator;
struct ofono_emulator_request; struct ofono_emulator_request;
struct ofono_handsfree_card;
enum ofono_emulator_type { enum ofono_emulator_type {
OFONO_EMULATOR_TYPE_DUN, OFONO_EMULATOR_TYPE_DUN,
@@ -108,6 +109,14 @@ void ofono_emulator_set_hf_indicator_active(struct ofono_emulator *em,
int indicator, int indicator,
ofono_bool_t active); ofono_bool_t active);
void ofono_emulator_set_handsfree_card(struct ofono_emulator *em,
struct ofono_handsfree_card *card);
typedef void (*ofono_emulator_codec_negotiation_cb)(int err, void *data);
int ofono_emulator_start_codec_negotiation(struct ofono_emulator *em,
ofono_emulator_codec_negotiation_cb cb, void *data);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -79,6 +79,9 @@ struct ofono_gprs_context_driver {
ofono_gprs_context_cb_t cb, void *data); ofono_gprs_context_cb_t cb, void *data);
void (*detach_shutdown)(struct ofono_gprs_context *gc, void (*detach_shutdown)(struct ofono_gprs_context *gc,
unsigned int id); unsigned int id);
void (*read_settings)(struct ofono_gprs_context *gc,
unsigned int cid,
ofono_gprs_context_cb_t cb, void *data);
}; };
void ofono_gprs_context_deactivated(struct ofono_gprs_context *gc, void ofono_gprs_context_deactivated(struct ofono_gprs_context *gc,

View File

@@ -81,6 +81,8 @@ void ofono_gprs_add_context(struct ofono_gprs *gprs,
struct ofono_gprs_context *gc); struct ofono_gprs_context *gc);
ofono_bool_t ofono_gprs_get_roaming_allowed(struct ofono_gprs *gprs); ofono_bool_t ofono_gprs_get_roaming_allowed(struct ofono_gprs *gprs);
void ofono_gprs_cid_activated(struct ofono_gprs *gprs, unsigned int cid,
const char *apn);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -30,6 +30,11 @@ extern "C" {
struct ofono_handsfree_card; struct ofono_handsfree_card;
enum ofono_handsfree_card_type {
OFONO_HANDSFREE_CARD_TYPE_HANDSFREE,
OFONO_HANDSFREE_CARD_TYPE_GATEWAY,
};
typedef void (*ofono_handsfree_card_connect_cb_t)( typedef void (*ofono_handsfree_card_connect_cb_t)(
const struct ofono_error *error, void *data); const struct ofono_error *error, void *data);
@@ -45,8 +50,9 @@ struct ofono_handsfree_card_driver {
}; };
struct ofono_handsfree_card *ofono_handsfree_card_create(unsigned int vendor, struct ofono_handsfree_card *ofono_handsfree_card_create(unsigned int vendor,
const char *driver, enum ofono_handsfree_card_type type,
void *data); const char *driver,
void *data);
int ofono_handsfree_card_register(struct ofono_handsfree_card *card); int ofono_handsfree_card_register(struct ofono_handsfree_card *card);
void ofono_handsfree_card_remove(struct ofono_handsfree_card *card); void ofono_handsfree_card_remove(struct ofono_handsfree_card *card);
ofono_bool_t ofono_handsfree_card_set_codec(struct ofono_handsfree_card *card, ofono_bool_t ofono_handsfree_card_set_codec(struct ofono_handsfree_card *card,

100
ofono/include/netmon.h Normal file
View File

@@ -0,0 +1,100 @@
/*
*
* 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
*
*/
#ifndef __OFONO_NETMON_H
#define __OFONO_NETMON_H
#ifdef __cplusplus
extern "C" {
#endif
#include <ofono/types.h>
struct ofono_netmon;
typedef void (*ofono_netmon_cb_t)(const struct ofono_error *error, void *data);
struct ofono_netmon_driver {
const char *name;
int (*probe)(struct ofono_netmon *netmon, unsigned int vendor,
void *data);
void (*remove)(struct ofono_netmon *netmon);
void (*request_update)(struct ofono_netmon *netmon,
ofono_netmon_cb_t cb, void *data);
};
enum ofono_netmon_cell_type {
OFONO_NETMON_CELL_TYPE_GSM,
OFONO_NETMON_CELL_TYPE_UMTS,
OFONO_NETMON_CELL_TYPE_LTE,
};
enum ofono_netmon_info {
OFONO_NETMON_INFO_MCC, /* char *, up to 3 digits + null */
OFONO_NETMON_INFO_MNC, /* char *, up to 3 digits + null */
OFONO_NETMON_INFO_LAC, /* int */
OFONO_NETMON_INFO_CI, /* int */
OFONO_NETMON_INFO_ARFCN, /* int */
OFONO_NETMON_INFO_BSIC, /* int */
OFONO_NETMON_INFO_RXLEV, /* int */
OFONO_NETMON_INFO_BER, /* int */
OFONO_NETMON_INFO_RSSI, /* int */
OFONO_NETMON_INFO_TIMING_ADVANCE, /* int */
OFONO_NETMON_INFO_PSC, /* int */
OFONO_NETMON_INFO_INVALID,
};
/*
* Examples:
* ofono_netmon_serving_cell_notify(netmon, OFONO_NETMON_CELL_TYPE_GSM,
* OFONO_NETMON_INFO_MCC, "123",
* OFONO_NETMON_INFO_MNC, "456",
* OFONO_NETMON_INFO_LAC, lac,
* OFONO_NETMON_INFO_CI, ci,
* OFONO_NETMON_INFO_RSSI, rssi,
* OFONO_NETMON_INFO_RXLEV, rxlev,
* OFONO_NETMON_INFO_INVALID);
*/
void ofono_netmon_serving_cell_notify(struct ofono_netmon *netmon,
enum ofono_netmon_cell_type type,
int info_type, ...);
int ofono_netmon_driver_register(const struct ofono_netmon_driver *d);
void ofono_netmon_driver_unregister(const struct ofono_netmon_driver *d);
struct ofono_netmon *ofono_netmon_create(struct ofono_modem *modem,
unsigned int vendor,
const char *driver, void *data);
void ofono_netmon_register(struct ofono_netmon *netmon);
void ofono_netmon_remove(struct ofono_netmon *netmon);
void ofono_netmon_set_data(struct ofono_netmon *netmon, void *data);
void *ofono_netmon_get_data(struct ofono_netmon *netmon);
#ifdef __cplusplus
}
#endif
#endif /* __OFONO_NETMON_H */

View File

@@ -0,0 +1,283 @@
/*
*
* 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
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <glib.h>
#include <ofono.h>
#include <simutil.h>
#define OFONO_API_SUBJECT_TO_CHANGE
#include <ofono/plugin.h>
#include <ofono/modem.h>
#include <ofono/sim.h>
#include <ofono/dbus.h>
#include <gdbus.h>
#define SIM_EFACL_FILEID 0x6f57
#define ALLOWED_ACCESS_POINTS_INTERFACE "org.ofono.AllowedAccessPoints"
guint modemwatch_id;
GSList *context_list;
struct allowed_apns_ctx {
guint simwatch_id;
guint atomwatch_id;
struct ofono_modem *modem;
struct ofono_sim *sim;
struct ofono_sim_context *sim_context;
DBusMessage *pending;
DBusMessage *reply;
};
static void context_destroy(gpointer data)
{
struct allowed_apns_ctx *ctx = data;
if (ctx->simwatch_id)
ofono_sim_remove_state_watch(ctx->sim,
ctx->simwatch_id);
if (ctx->atomwatch_id)
__ofono_modem_remove_atom_watch(ctx->modem,
ctx->atomwatch_id);
if (ctx->sim_context)
ofono_sim_context_free(ctx->sim_context);
g_free(ctx);
}
static void atomwatch_destroy(gpointer data)
{
struct allowed_apns_ctx *ctx = data;
ctx->atomwatch_id = 0;
}
static void sim_acl_read_cb(int ok, int total_length, int record,
const unsigned char *data, int record_length,
void *userdata)
{
struct allowed_apns_ctx *ctx = userdata;
DBusMessage *reply = ctx->reply;
DBusMessageIter iter;
DBusMessageIter array;
struct simple_tlv_iter tlv_iter;
char *apn;
if (!ok) {
reply = __ofono_error_failed(ctx->pending);
__ofono_dbus_pending_reply(&ctx->pending, reply);
return;
}
reply = dbus_message_new_method_return(ctx->pending);
if (reply == NULL)
return;
dbus_message_iter_init_append(reply, &iter);
dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
DBUS_TYPE_STRING_AS_STRING,
&array);
if (data[0] == 0)
goto done;
simple_tlv_iter_init(&tlv_iter, &data[1], total_length - 1);
while (simple_tlv_iter_next(&tlv_iter)) {
if (simple_tlv_iter_get_tag(&tlv_iter) != 0xDD)
continue;
apn = g_strndup(
(char *) simple_tlv_iter_get_data(&tlv_iter),
simple_tlv_iter_get_length(&tlv_iter));
dbus_message_iter_append_basic(&array,
DBUS_TYPE_STRING,
&apn);
g_free(apn);
}
done:
dbus_message_iter_close_container(&iter, &array);
__ofono_dbus_pending_reply(&ctx->pending, reply);
}
static DBusMessage *get_allowed_apns(DBusConnection *conn,
DBusMessage *msg, void *data)
{
struct allowed_apns_ctx *ctx = data;
if (ctx->pending)
return __ofono_error_busy(msg);
ctx->pending = dbus_message_ref(msg);
ofono_sim_read(ctx->sim_context, SIM_EFACL_FILEID,
OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
sim_acl_read_cb, ctx);
return NULL;
}
static const GDBusMethodTable allowed_apns_methods[] = {
{ GDBUS_ASYNC_METHOD("GetAllowedAccessPoints",
NULL, GDBUS_ARGS({ "apnlist", "as" }),
get_allowed_apns) },
{ }
};
static void sim_state_watch(enum ofono_sim_state new_state, void *data)
{
struct allowed_apns_ctx *ctx = data;
DBusConnection *conn = ofono_dbus_get_connection();
if (new_state != OFONO_SIM_STATE_READY) {
g_dbus_unregister_interface(conn,
ofono_modem_get_path(ctx->modem),
ALLOWED_ACCESS_POINTS_INTERFACE);
ofono_modem_remove_interface(ctx->modem,
ALLOWED_ACCESS_POINTS_INTERFACE);
return;
}
if (!g_dbus_register_interface(conn,
ofono_modem_get_path(ctx->modem),
ALLOWED_ACCESS_POINTS_INTERFACE,
allowed_apns_methods, NULL, NULL,
ctx, NULL)) {
ofono_error("Cannot create %s Interface\n",
ALLOWED_ACCESS_POINTS_INTERFACE);
return;
}
ofono_modem_add_interface(ctx->modem,
ALLOWED_ACCESS_POINTS_INTERFACE);
}
static void sim_watch(struct ofono_atom *atom,
enum ofono_atom_watch_condition cond,
void *data)
{
struct allowed_apns_ctx *ctx = data;
if (cond == OFONO_ATOM_WATCH_CONDITION_UNREGISTERED) {
if (ctx->simwatch_id) {
ofono_sim_remove_state_watch(ctx->sim, ctx->simwatch_id);
ctx->simwatch_id = 0;
}
if (ctx->sim_context) {
ofono_sim_context_free(ctx->sim_context);
ctx->sim_context = NULL;
}
return;
}
ctx->sim = __ofono_atom_get_data(atom);
ctx->sim_context = ofono_sim_context_create(ctx->sim);
ctx->simwatch_id = ofono_sim_add_state_watch(ctx->sim,
sim_state_watch,
ctx, NULL);
}
static gint context_list_modem_compare(gconstpointer data1,
gconstpointer data2)
{
const struct allowed_apns_ctx *ctx = data1;
const struct ofono_modem *modem = data2;
return (ctx->modem == modem);
}
static void modem_watch(struct ofono_modem *modem,
gboolean added, void *userdata)
{
struct allowed_apns_ctx *ctx;
GSList *l;
if (added == FALSE) {
l = g_slist_find_custom(context_list,
modem, context_list_modem_compare);
if (l) {
ctx = l->data;
context_destroy(ctx);
context_list = g_slist_delete_link(context_list, l);
}
return;
}
ctx = g_try_new0(struct allowed_apns_ctx, 1);
if (ctx == NULL)
return;
context_list = g_slist_prepend(context_list, ctx);
ctx->modem = modem;
ctx->atomwatch_id = __ofono_modem_add_atom_watch(ctx->modem,
OFONO_ATOM_TYPE_SIM,
sim_watch, ctx,
atomwatch_destroy);
}
static void call_modemwatch(struct ofono_modem *modem, void *userdata)
{
modem_watch(modem, TRUE, userdata);
}
static int allowed_apns_init(void)
{
modemwatch_id = __ofono_modemwatch_add(modem_watch, NULL, NULL);
__ofono_modem_foreach(call_modemwatch, NULL);
return 0;
}
static void allowed_apns_exit(void)
{
__ofono_modemwatch_remove(modemwatch_id);
g_slist_free_full(context_list, context_destroy);
}
OFONO_PLUGIN_DEFINE(allowed_apns, "Plugin to read EFACL from SIM",
VERSION, OFONO_PLUGIN_PRIORITY_DEFAULT,
allowed_apns_init, allowed_apns_exit)

View File

@@ -225,8 +225,7 @@ void bluetooth_parse_properties(DBusMessage *reply, const char *property, ...)
} }
done: done:
g_slist_foreach(prop_handlers, (GFunc) g_free, NULL); g_slist_free_full(prop_handlers, g_free);
g_slist_free(prop_handlers);
} }
static void parse_uuids(DBusMessageIter *array, gpointer user_data) static void parse_uuids(DBusMessageIter *array, gpointer user_data)
@@ -692,7 +691,7 @@ static void find_adapter_cb(DBusPendingCall *call, gpointer user_data)
adapter_any_path = g_strdup(path); adapter_any_path = g_strdup(path);
g_slist_foreach(server_list, (GFunc) add_record, NULL); g_slist_foreach(server_list, add_record, NULL);
done: done:
dbus_message_unref(reply); dbus_message_unref(reply);
@@ -820,7 +819,7 @@ static void bluetooth_disconnect(DBusConnection *conn, void *user_data)
g_hash_table_foreach(uuid_hash, bluetooth_remove, NULL); g_hash_table_foreach(uuid_hash, bluetooth_remove, NULL);
g_slist_foreach(server_list, (GFunc) remove_service_handle, NULL); g_slist_foreach(server_list, remove_service_handle, NULL);
} }
static guint bluetooth_watch; static guint bluetooth_watch;

View File

@@ -23,6 +23,7 @@
#include <config.h> #include <config.h>
#endif #endif
#define _GNU_SOURCE
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
@@ -413,15 +414,22 @@ error:
static void gobi_pre_sim(struct ofono_modem *modem) static void gobi_pre_sim(struct ofono_modem *modem)
{ {
struct gobi_data *data = ofono_modem_get_data(modem); struct gobi_data *data = ofono_modem_get_data(modem);
const char *sim_driver = NULL;
DBG("%p", modem); DBG("%p", modem);
ofono_devinfo_create(modem, 0, "qmimodem", data->device); ofono_devinfo_create(modem, 0, "qmimodem", data->device);
if (data->features & GOBI_UIM) if (data->features & GOBI_UIM)
ofono_sim_create(modem, 0, "qmimodem", data->device); sim_driver = "qmimodem";
else if (data->features & GOBI_DMS) else if (data->features & GOBI_DMS)
ofono_sim_create(modem, 0, "qmimodem-legacy", data->device); sim_driver = "qmimodem-legacy";
if (ofono_modem_get_boolean(modem, "ForceSimLegacy"))
sim_driver = "qmimodem-legacy";
if (sim_driver)
ofono_sim_create(modem, 0, sim_driver, data->device);
if (data->features & GOBI_VOICE) if (data->features & GOBI_VOICE)
ofono_voicecall_create(modem, 0, "qmimodem", data->device); ofono_voicecall_create(modem, 0, "qmimodem", data->device);

View File

@@ -22,6 +22,7 @@
#include <config.h> #include <config.h>
#endif #endif
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <errno.h> #include <errno.h>
@@ -35,21 +36,112 @@
#include <ofono/plugin.h> #include <ofono/plugin.h>
#include <ofono/log.h> #include <ofono/log.h>
#include <ofono/modem.h> #include <ofono/modem.h>
#include <ofono/handsfree-audio.h>
typedef struct GAtChat GAtChat;
typedef struct GAtResult GAtResult;
#include "drivers/atmodem/atutil.h"
#include "hfp.h" #include "hfp.h"
#include "bluez5.h" #include "bluez5.h"
#include "bluetooth.h"
#ifndef DBUS_TYPE_UNIX_FD #ifndef DBUS_TYPE_UNIX_FD
#define DBUS_TYPE_UNIX_FD -1 #define DBUS_TYPE_UNIX_FD -1
#endif #endif
#define HFP_AG_EXT_PROFILE_PATH "/bluetooth/profile/hfp_ag" #define HFP_AG_EXT_PROFILE_PATH "/bluetooth/profile/hfp_ag"
#define BT_ADDR_SIZE 18
#define HFP_AG_DRIVER "hfp-ag-driver"
static guint modemwatch_id; static guint modemwatch_id;
static GList *modems; static GList *modems;
static GHashTable *sim_hash = NULL; static GHashTable *sim_hash = NULL;
static GHashTable *connection_hash; static GHashTable *connection_hash;
static int hfp_card_probe(struct ofono_handsfree_card *card,
unsigned int vendor, void *data)
{
DBG("");
return 0;
}
static void hfp_card_remove(struct ofono_handsfree_card *card)
{
DBG("");
}
static void codec_negotiation_done_cb(int err, void *data)
{
struct cb_data *cbd = data;
ofono_handsfree_card_connect_cb_t cb = cbd->cb;
DBG("err %d", err);
if (err < 0) {
CALLBACK_WITH_FAILURE(cb, cbd->data);
goto done;
}
/*
* We don't have anything to do at this point as when the
* codec negotiation succeeded the emulator internally
* already triggered the SCO connection setup of the
* handsfree card which also takes over the processing
* of the pending dbus message
*/
done:
g_free(cbd);
}
static void hfp_card_connect(struct ofono_handsfree_card *card,
ofono_handsfree_card_connect_cb_t cb,
void *data)
{
int err;
struct ofono_emulator *em = ofono_handsfree_card_get_data(card);
struct cb_data *cbd;
DBG("");
cbd = cb_data_new(cb, data);
/*
* The emulator core will take care if the remote side supports
* codec negotiation or not.
*/
err = ofono_emulator_start_codec_negotiation(em,
codec_negotiation_done_cb, cbd);
if (err < 0) {
CALLBACK_WITH_FAILURE(cb, data);
g_free(cbd);
return;
}
/*
* We hand over to the emulator core here to establish the
* SCO connection once the codec is negotiated
* */
}
static void hfp_sco_connected_hint(struct ofono_handsfree_card *card)
{
DBG("");
}
static struct ofono_handsfree_card_driver hfp_ag_driver = {
.name = HFP_AG_DRIVER,
.probe = hfp_card_probe,
.remove = hfp_card_remove,
.connect = hfp_card_connect,
.sco_connected_hint = hfp_sco_connected_hint,
};
static void connection_destroy(gpointer data) static void connection_destroy(gpointer data)
{ {
int fd = GPOINTER_TO_INT(data); int fd = GPOINTER_TO_INT(data);
@@ -77,8 +169,13 @@ static DBusMessage *profile_new_connection(DBusConnection *conn,
const char *device; const char *device;
GIOChannel *io; GIOChannel *io;
int fd, fd_dup; int fd, fd_dup;
struct sockaddr_rc saddr;
socklen_t optlen;
struct ofono_emulator *em; struct ofono_emulator *em;
struct ofono_modem *modem; struct ofono_modem *modem;
char local[BT_ADDR_SIZE], remote[BT_ADDR_SIZE];
struct ofono_handsfree_card *card;
int err;
DBG("Profile handler NewConnection"); DBG("Profile handler NewConnection");
@@ -95,12 +192,15 @@ static DBusMessage *profile_new_connection(DBusConnection *conn,
goto invalid; goto invalid;
dbus_message_iter_get_basic(&entry, &fd); dbus_message_iter_get_basic(&entry, &fd);
dbus_message_iter_next(&entry);
if (fd < 0) if (fd < 0)
goto invalid; goto invalid;
DBG("%s", device); dbus_message_iter_next(&entry);
if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_ARRAY) {
close(fd);
goto invalid;
}
/* Pick the first voicecall capable modem */ /* Pick the first voicecall capable modem */
if (modems == NULL) { if (modems == NULL) {
@@ -111,8 +211,35 @@ static DBusMessage *profile_new_connection(DBusConnection *conn,
} }
modem = modems->data; modem = modems->data;
DBG("Picked modem %p for emulator", modem); DBG("Picked modem %p for emulator", modem);
memset(&saddr, 0, sizeof(saddr));
optlen = sizeof(saddr);
if (getsockname(fd, (struct sockaddr *) &saddr, &optlen) < 0) {
err = errno;
ofono_error("RFCOMM getsockname(): %s (%d)", strerror(err),
err);
close(fd);
goto invalid;
}
bt_ba2str(&saddr.rc_bdaddr, local);
memset(&saddr, 0, sizeof(saddr));
optlen = sizeof(saddr);
if (getpeername(fd, (struct sockaddr *) &saddr, &optlen) < 0) {
err = errno;
ofono_error("RFCOMM getpeername(): %s (%d)", strerror(err),
err);
close(fd);
goto invalid;
}
bt_ba2str(&saddr.rc_bdaddr, remote);
em = ofono_emulator_create(modem, OFONO_EMULATOR_TYPE_HFP); em = ofono_emulator_create(modem, OFONO_EMULATOR_TYPE_HFP);
if (em == NULL) { if (em == NULL) {
close(fd); close(fd);
@@ -129,6 +256,17 @@ static DBusMessage *profile_new_connection(DBusConnection *conn,
g_strdup(device), g_free); g_strdup(device), g_free);
g_io_channel_unref(io); g_io_channel_unref(io);
card = ofono_handsfree_card_create(0,
OFONO_HANDSFREE_CARD_TYPE_GATEWAY,
HFP_AG_DRIVER, em);
ofono_handsfree_card_set_data(card, em);
ofono_handsfree_card_set_local(card, local);
ofono_handsfree_card_set_remote(card, remote);
ofono_emulator_set_handsfree_card(em, card);
g_hash_table_insert(connection_hash, g_strdup(device), g_hash_table_insert(connection_hash, g_strdup(device),
GINT_TO_POINTER(fd_dup)); GINT_TO_POINTER(fd_dup));
@@ -324,6 +462,7 @@ static void call_modemwatch(struct ofono_modem *modem, void *user)
static int hfp_ag_init(void) static int hfp_ag_init(void)
{ {
DBusConnection *conn = ofono_dbus_get_connection(); DBusConnection *conn = ofono_dbus_get_connection();
int err;
if (DBUS_TYPE_UNIX_FD < 0) if (DBUS_TYPE_UNIX_FD < 0)
return -EBADF; return -EBADF;
@@ -338,6 +477,13 @@ static int hfp_ag_init(void)
return -EIO; return -EIO;
} }
err = ofono_handsfree_card_driver_register(&hfp_ag_driver);
if (err < 0) {
g_dbus_unregister_interface(conn, HFP_AG_EXT_PROFILE_PATH,
BLUEZ_PROFILE_INTERFACE);
return err;
}
sim_hash = g_hash_table_new(g_direct_hash, g_direct_equal); sim_hash = g_hash_table_new(g_direct_hash, g_direct_equal);
modemwatch_id = __ofono_modemwatch_add(modem_watch, NULL, NULL); modemwatch_id = __ofono_modemwatch_add(modem_watch, NULL, NULL);
@@ -346,6 +492,8 @@ static int hfp_ag_init(void)
connection_hash = g_hash_table_new_full(g_str_hash, g_str_equal, connection_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
g_free, connection_destroy); g_free, connection_destroy);
ofono_handsfree_audio_ref();
return 0; return 0;
} }
@@ -357,11 +505,15 @@ static void hfp_ag_exit(void)
g_dbus_unregister_interface(conn, HFP_AG_EXT_PROFILE_PATH, g_dbus_unregister_interface(conn, HFP_AG_EXT_PROFILE_PATH,
BLUEZ_PROFILE_INTERFACE); BLUEZ_PROFILE_INTERFACE);
ofono_handsfree_card_driver_unregister(&hfp_ag_driver);
g_hash_table_destroy(connection_hash); g_hash_table_destroy(connection_hash);
g_list_free(modems); g_list_free(modems);
g_hash_table_foreach_remove(sim_hash, sim_watch_remove, NULL); g_hash_table_foreach_remove(sim_hash, sim_watch_remove, NULL);
g_hash_table_destroy(sim_hash); g_hash_table_destroy(sim_hash);
ofono_handsfree_audio_unref();
} }
OFONO_PLUGIN_DEFINE(hfp_ag_bluez5, "Hands-Free Audio Gateway Profile Plugins", OFONO_PLUGIN_DEFINE(hfp_ag_bluez5, "Hands-Free Audio Gateway Profile Plugins",

View File

@@ -590,7 +590,9 @@ static DBusMessage *profile_new_connection(DBusConnection *conn,
if (version >= HFP_VERSION_1_6) if (version >= HFP_VERSION_1_6)
driver = HFP16_HF_DRIVER; driver = HFP16_HF_DRIVER;
hfp->card = ofono_handsfree_card_create(0, driver, hfp); hfp->card = ofono_handsfree_card_create(0,
OFONO_HANDSFREE_CARD_TYPE_HANDSFREE,
driver, hfp);
ofono_handsfree_card_set_data(hfp->card, hfp); ofono_handsfree_card_set_data(hfp->card, hfp);
ofono_handsfree_card_set_local(hfp->card, local); ofono_handsfree_card_set_local(hfp->card, local);

77
ofono/plugins/infineon.c Normal file
View File

@@ -0,0 +1,77 @@
/*
*
* oFono - Open Source Telephony - RIL-based devices: infineon modems
*
* 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
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#define OFONO_API_SUBJECT_TO_CHANGE
#include <ofono/plugin.h>
#include <ofono/log.h>
#include <ofono/modem.h>
#include "ofono.h"
#include "drivers/rilmodem/vendor.h"
#include "ril.h"
static int inf_probe(struct ofono_modem *modem)
{
return ril_create(modem, OFONO_RIL_VENDOR_INFINEON);
}
static struct ofono_modem_driver infineon_driver = {
.name = "infineon",
.probe = inf_probe,
.remove = ril_remove,
.enable = ril_enable,
.disable = ril_disable,
.pre_sim = ril_pre_sim,
.post_sim = ril_post_sim,
.post_online = ril_post_online,
.set_online = ril_set_online,
};
/*
* This plugin is a device plugin for infineon modems that use RIL interface.
* The plugin 'rildev' is used to determine which RIL plugin should be loaded
* based upon an environment variable.
*/
static int inf_init(void)
{
int retval = 0;
retval = ofono_modem_driver_register(&infineon_driver);
if (retval != 0)
DBG("ofono_modem_driver_register returned: %d", retval);
return retval;
}
static void inf_exit(void)
{
DBG("");
ofono_modem_driver_unregister(&infineon_driver);
}
OFONO_PLUGIN_DEFINE(infineon, "Infineon modem driver", VERSION,
OFONO_PLUGIN_PRIORITY_DEFAULT, inf_init, inf_exit)

View File

@@ -318,6 +318,26 @@ static int comp_mcc(const void *key, const void *value)
return mcc - mccmnc->mcc; return mcc - mccmnc->mcc;
} }
int mnclength(int mcc, int mnc)
{
int mccmnc_num = 1000*mcc + mnc;
int *mccmnc3_res = bsearch(&mccmnc_num, codes_mnclen3_db,
G_N_ELEMENTS(codes_mnclen3_db),
sizeof(codes_mnclen3_db[0]), comp_int);
if (mccmnc3_res) {
return 3;
} else {
const struct mcc_mnclength *mccmnc_res =
bsearch(&mcc, mnclen_db, G_N_ELEMENTS(mnclen_db),
sizeof(mnclen_db[0]), comp_mcc);
if (mccmnc_res) {
return mccmnc_res->mnclength;
}
}
return -ENOENT;
}
static int mnclength_get_mnclength(const char *imsi) static int mnclength_get_mnclength(const char *imsi)
{ {
char mccmnc[OFONO_MAX_MCC_LENGTH + OFONO_MAX_MNC_LENGTH + 1]; char mccmnc[OFONO_MAX_MCC_LENGTH + OFONO_MAX_MNC_LENGTH + 1];

View File

@@ -635,7 +635,7 @@ static int gpio_probe_links(void)
char const *gpiodir = "/sys/class/gpio"; char const *gpiodir = "/sys/class/gpio";
char const *cmtdir = "/dev/cmt"; char const *cmtdir = "/dev/cmt";
DIR *gpio; DIR *gpio;
struct dirent *d, entry[1]; struct dirent *d;
if (file_exists(cmtdir)) { if (file_exists(cmtdir)) {
DBG("Using %s", cmtdir); DBG("Using %s", cmtdir);
@@ -657,16 +657,11 @@ static int gpio_probe_links(void)
return -(errno = ENODEV); return -(errno = ENODEV);
} }
while (readdir_r(gpio, entry, &d) == 0) { while ((d = readdir(gpio)) != NULL) {
char nn[PATH_MAX], name[PATH_MAX], from[PATH_MAX], to[PATH_MAX]; char nn[PATH_MAX], name[PATH_MAX], from[PATH_MAX], to[PATH_MAX];
FILE *nf; FILE *nf;
size_t len; size_t len;
if (d == NULL) {
(void) closedir(gpio);
return 0;
}
snprintf(nn, sizeof nn, "%s/%s/name", gpiodir, d->d_name); snprintf(nn, sizeof nn, "%s/%s/name", gpiodir, d->d_name);
nf = fopen(nn, "rb"); nf = fopen(nn, "rb");

View File

@@ -3,7 +3,7 @@
* oFono - Open Source Telephony - RIL-based devices * oFono - Open Source Telephony - RIL-based devices
* *
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved. * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2012 Canonical Ltd. * Copyright (C) 2012-2014 Canonical Ltd.
* Copyright (C) 2013 Jolla Ltd. * Copyright (C) 2013 Jolla Ltd.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@@ -29,15 +29,9 @@
#include <errno.h> #include <errno.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <glib.h>
#include <gril.h>
#include <parcel.h>
#include <gdbus.h>
#include <linux/capability.h>
#include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include <sys/syscall.h> #include <glib.h>
#include <sys/prctl.h>
#define OFONO_API_SUBJECT_TO_CHANGE #define OFONO_API_SUBJECT_TO_CHANGE
#include <ofono/plugin.h> #include <ofono/plugin.h>
@@ -61,54 +55,39 @@
#include <ofono/gprs-context.h> #include <ofono/gprs-context.h>
#include <ofono/audio-settings.h> #include <ofono/audio-settings.h>
#include <ofono/types.h> #include <ofono/types.h>
#include <ofono/message-waiting.h>
#include <ofono/oemraw.h>
#include <ofono/stk.h>
#include "rildev.h" #include <gril/gril.h>
#include "ofono.h"
#include "ril.h"
#include "drivers/rilmodem/rilmodem.h" #include "drivers/rilmodem/rilmodem.h"
#include "drivers/rilmodem/vendor.h"
#define MAX_POWER_ON_RETRIES 5 #define RADIO_GID 1001
#define MAX_SIM_STATUS_RETRIES 15 #define RADIO_UID 1001
#define RADIO_ID 1001
#define MAX_PDP_CONTEXTS 2
/* MCE definitions */ #define MAX_SIM_STATUS_RETRIES 15
#define MCE_SERVICE "com.nokia.mce"
#define MCE_SIGNAL_IF "com.nokia.mce.signal"
/* MCE signal definitions */ /* this gives 30s for rild to initialize */
#define MCE_DISPLAY_SIG "display_status_ind" #define RILD_MAX_CONNECT_RETRIES 5
#define RILD_CONNECT_RETRY_TIME_S 5
#define MCE_DISPLAY_ON_STRING "on" char *RILD_CMD_SOCKET[] = {"/dev/socket/rild", "/dev/socket/rild1"};
char *GRIL_HEX_PREFIX[] = {"Device 0: ", "Device 1: "};
/* transitional state between ON and OFF (3 seconds) */
#define MCE_DISPLAY_DIM_STRING "dimmed"
#define MCE_DISPLAY_OFF_STRING "off"
#define RILMODEM_CONF_FILE "/etc/ofono/ril_subscription.conf"
#define RILSOCK_CONF_GROUP "cmdsocket"
#define RILSOCK_CONF_PATH "path"
#define DEFAULT_CMD_SOCK "/dev/socket/rild"
struct ril_data { struct ril_data {
GRil *modem; GRil *ril;
int power_on_retries; enum ofono_ril_vendor vendor;
int sim_status_retries; int sim_status_retries;
ofono_bool_t connected; ofono_bool_t connected;
ofono_bool_t online; ofono_bool_t ofono_online;
ofono_bool_t reported; int radio_state;
guint timer_id; struct ofono_sim *sim;
struct ofono_radio_settings *radio_settings;
int rild_connect_retries;
}; };
static guint mce_daemon_watch;
static guint signal_watch;
static DBusConnection *connection;
static int ril_init(void);
static void ril_exit(void);
static int send_get_sim_status(struct ofono_modem *modem);
static void ril_debug(const char *str, void *user_data) static void ril_debug(const char *str, void *user_data)
{ {
const char *prefix = user_data; const char *prefix = user_data;
@@ -116,423 +95,258 @@ static void ril_debug(const char *str, void *user_data)
ofono_info("%s%s", prefix, str); ofono_info("%s%s", prefix, str);
} }
static void sim_status_cb(struct ril_msg *message, gpointer user_data) static void ril_radio_state_changed(struct ril_msg *message, gpointer user_data)
{ {
DBG("error=%d", message->error);
struct ofono_modem *modem = user_data; struct ofono_modem *modem = user_data;
struct ril_data *ril = ofono_modem_get_data(modem); struct ril_data *rd = ofono_modem_get_data(modem);
struct sim_status status; struct parcel rilp;
struct sim_app *apps[MAX_UICC_APPS]; int radio_state;
/* g_ril_init_parcel(message, &rilp);
* ril.h claims this should NEVER fail!
* However this isn't quite true. So,
* on anything other than SUCCESS, we
* log an error, and schedule another
* GET_SIM_STATUS request.
*/
if (message->error != RIL_E_SUCCESS) { radio_state = parcel_r_int32(&rilp);
ril->sim_status_retries++;
ofono_error("GET_SIM_STATUS reques failed: %d; retries: %d", if (rilp.malformed) {
message->error, ril->sim_status_retries); ofono_error("%s: malformed parcel received", __func__);
ofono_modem_set_powered(modem, FALSE);
return;
}
if (ril->sim_status_retries < MAX_SIM_STATUS_RETRIES) g_ril_append_print_buf(rd->ril, "(state: %s)",
ril->timer_id = g_timeout_add_seconds(2, (GSourceFunc) ril_radio_state_to_string(radio_state));
send_get_sim_status, g_ril_print_unsol(rd->ril, message);
(gpointer) modem);
else
ofono_error("Max retries for GET_SIM_STATUS exceeded!");
} else {
/* Returns TRUE if cardstate == PRESENT */
if (ril_util_parse_sim_status(ril->modem, message,
&status, apps)) {
if (status.num_apps) if (radio_state != rd->radio_state) {
ril_util_free_sim_apps(apps, status.num_apps); ofono_info("%s: state: %s rd->ofono_online: %d",
} else { __func__,
ofono_warn("No SIM card present."); ril_radio_state_to_string(radio_state),
rd->ofono_online);
rd->radio_state = radio_state;
switch (radio_state) {
case RADIO_STATE_ON:
if (rd->radio_settings == NULL)
rd->radio_settings =
ofono_radio_settings_create(modem,
rd->vendor, RILMODEM,
rd->ril);
break;
case RADIO_STATE_UNAVAILABLE:
case RADIO_STATE_OFF:
/*
* Unexpected radio state change, as we are supposed to
* be online. UNAVAILABLE has been seen occassionally
* when powering off the phone. We wait 5 secs to avoid
* too fast re-spawns, then exit with error to make
* upstart re-start ofono.
*/
if (rd->ofono_online)
ofono_error("%s: radio self-powered off!",
__func__);
break;
} }
/*
* We cannot power on modem, but we need to get
* certain interfaces up to be able to make emergency calls
* in offline mode and without SIM
*/
ofono_modem_set_powered(modem, TRUE);
} }
} }
static int send_get_sim_status(struct ofono_modem *modem) int ril_create(struct ofono_modem *modem, enum ofono_ril_vendor vendor)
{ {
struct ril_data *ril = ofono_modem_get_data(modem); ofono_bool_t lte_cap;
int request = RIL_REQUEST_GET_SIM_STATUS; struct ril_data *rd = g_try_new0(struct ril_data, 1);
guint ret; if (rd == NULL) {
ril->timer_id = 0;
ret = g_ril_send(ril->modem, request,
NULL, 0, sim_status_cb, modem, NULL);
g_ril_print_request_no_args(ril->modem, ret, request);
/*
* This function is used as a callback function for
* g_timeout_add_seconds therefore we must always return FALSE.
* The other place where this is called is from ril_connected but it
* doesn't even check the return value.
*/
return FALSE;
}
static int ril_probe(struct ofono_modem *modem)
{
DBG("modem: %p", modem);
struct ril_data *ril = NULL;
ril = g_try_new0(struct ril_data, 1);
if (ril == NULL) {
errno = ENOMEM; errno = ENOMEM;
goto error; goto error;
} }
ril->modem = NULL; DBG("");
ofono_modem_set_data(modem, ril); rd->vendor = vendor;
rd->ofono_online = FALSE;
rd->radio_state = RADIO_STATE_OFF;
lte_cap = getenv("OFONO_RIL_RAT_LTE") ? TRUE : FALSE;
ofono_modem_set_boolean(modem, MODEM_PROP_LTE_CAPABLE, lte_cap);
ofono_modem_set_data(modem, rd);
return 0; return 0;
error: error:
g_free(ril); g_free(rd);
return -errno; return -errno;
} }
static void ril_remove(struct ofono_modem *modem) static int ril_probe(struct ofono_modem *modem)
{ {
struct ril_data *ril = ofono_modem_get_data(modem); return ril_create(modem, OFONO_RIL_VENDOR_AOSP);
DBG("modem: %p ril: %p", modem, ril); }
void ril_remove(struct ofono_modem *modem)
{
struct ril_data *rd = ofono_modem_get_data(modem);
ofono_modem_set_data(modem, NULL); ofono_modem_set_data(modem, NULL);
if (!ril) if (!rd)
return; return;
if (ril->timer_id > 0) g_ril_unref(rd->ril);
g_source_remove(ril->timer_id);
g_ril_unref(ril->modem); g_free(rd);
g_free(ril);
g_dbus_remove_watch(connection, mce_daemon_watch);
if (signal_watch > 0)
g_dbus_remove_watch(connection, signal_watch);
} }
static void ril_pre_sim(struct ofono_modem *modem) void ril_pre_sim(struct ofono_modem *modem)
{ {
struct ril_data *rd = ofono_modem_get_data(modem);
DBG(""); DBG("");
struct ril_data *ril = ofono_modem_get_data(modem);
ofono_sim_create(modem, 0, "rilmodem", ril->modem); ofono_devinfo_create(modem, rd->vendor, RILMODEM, rd->ril);
ofono_voicecall_create(modem, 0, "rilmodem", ril->modem); ofono_voicecall_create(modem, rd->vendor, RILMODEM, rd->ril);
ofono_call_volume_create(modem, rd->vendor, RILMODEM, rd->ril);
rd->sim = ofono_sim_create(modem, rd->vendor, RILMODEM, rd->ril);
} }
static void ril_post_sim(struct ofono_modem *modem) void ril_post_sim(struct ofono_modem *modem)
{ {
DBG(""); struct ril_data *rd = ofono_modem_get_data(modem);
struct ril_data *ril = ofono_modem_get_data(modem);
struct ofono_gprs *gprs;
struct ofono_gprs_context *gc;
struct ofono_message_waiting *mw; struct ofono_message_waiting *mw;
int i;
/* TODO: this function should setup: /* TODO: this function should setup:
* - phonebook
* - stk ( SIM toolkit ) * - stk ( SIM toolkit )
* - radio_settings
*/ */
ofono_sms_create(modem, 0, "rilmodem", ril->modem); ofono_sms_create(modem, rd->vendor, RILMODEM, rd->ril);
gprs = ofono_gprs_create(modem, 0, "rilmodem", ril->modem);
if (gprs) {
for (i = 0; i < MAX_PDP_CONTEXTS; i++) {
gc = ofono_gprs_context_create(modem, 0, "rilmodem",
ril->modem);
if (gc == NULL)
break;
ofono_gprs_add_context(gprs, gc);
}
}
ofono_radio_settings_create(modem, 0, "rilmodem", ril->modem);
ofono_phonebook_create(modem, 0, "rilmodem", ril->modem);
ofono_call_forwarding_create(modem, 0, "rilmodem", ril->modem);
ofono_call_barring_create(modem, 0, "rilmodem", ril->modem);
ofono_stk_create(modem, 0, "rilmodem", ril->modem);
mw = ofono_message_waiting_create(modem); mw = ofono_message_waiting_create(modem);
if (mw) if (mw)
ofono_message_waiting_register(mw); ofono_message_waiting_register(mw);
ofono_call_forwarding_create(modem, rd->vendor, RILMODEM, rd->ril);
ofono_stk_create(modem, rd->vendor, RILMODEM, rd->ril);
ofono_phonebook_create(modem, rd->vendor, RILMODEM, modem);
} }
static void ril_post_online(struct ofono_modem *modem) void ril_post_online(struct ofono_modem *modem)
{ {
DBG(""); struct ril_data *rd = ofono_modem_get_data(modem);
struct ril_data *ril = ofono_modem_get_data(modem); struct ofono_gprs *gprs;
struct ofono_gprs_context *gc;
ofono_call_volume_create(modem, 0, "rilmodem", ril->modem); ofono_netreg_create(modem, rd->vendor, RILMODEM, rd->ril);
ofono_ussd_create(modem, rd->vendor, RILMODEM, rd->ril);
ofono_call_settings_create(modem, rd->vendor, RILMODEM, rd->ril);
ofono_call_barring_create(modem, rd->vendor, RILMODEM, rd->ril);
gprs = ofono_gprs_create(modem, rd->vendor, RILMODEM, rd->ril);
gc = ofono_gprs_context_create(modem, rd->vendor, RILMODEM, rd->ril);
ofono_netreg_create(modem, 0, "rilmodem", ril->modem); if (gc) {
ofono_ussd_create(modem, 0, "rilmodem", ril->modem); ofono_gprs_context_set_type(gc,
ofono_call_settings_create(modem, 0, "rilmodem", ril->modem); OFONO_GPRS_CONTEXT_TYPE_INTERNET);
ofono_oem_raw_create(modem, 0, "rilmodem", ril->modem); ofono_gprs_add_context(gprs, gc);
}
gc = ofono_gprs_context_create(modem, rd->vendor, RILMODEM, rd->ril);
if (gc) {
ofono_gprs_context_set_type(gc, OFONO_GPRS_CONTEXT_TYPE_MMS);
ofono_gprs_add_context(gprs, gc);
}
} }
static void ril_set_online_cb(struct ril_msg *message, gpointer user_data) static void ril_set_online_cb(struct ril_msg *message, gpointer user_data)
{ {
DBG("");
struct cb_data *cbd = user_data; struct cb_data *cbd = user_data;
struct ril_data *rd = cbd->user;
ofono_modem_online_cb_t cb = cbd->cb; ofono_modem_online_cb_t cb = cbd->cb;
if (message->error == RIL_E_SUCCESS) if (message->error == RIL_E_SUCCESS) {
DBG("%s: set_online OK: rd->ofono_online: %d", __func__,
rd->ofono_online);
CALLBACK_WITH_SUCCESS(cb, cbd->data); CALLBACK_WITH_SUCCESS(cb, cbd->data);
else
CALLBACK_WITH_FAILURE(cb, cbd->data);
}
static void ril_set_online(struct ofono_modem *modem, ofono_bool_t online,
ofono_modem_online_cb_t callback, void *data)
{
DBG("Set online state (online = 1, offline = 0)): %i", online);
struct ril_data *ril = ofono_modem_get_data(modem);
struct cb_data *cbd = cb_data_new(callback, data);
struct parcel rilp;
int ret = 0;
parcel_init(&rilp);
parcel_w_int32(&rilp, 1); /* Number of params */
parcel_w_int32(&rilp, online); /* Radio ON = 1, Radio OFF = 0 */
ofono_info("%s: RIL_REQUEST_RADIO_POWER %d", __func__, online);
ret = g_ril_send(ril->modem, RIL_REQUEST_RADIO_POWER, rilp.data,
rilp.size, ril_set_online_cb, cbd, g_free);
parcel_free(&rilp);
DBG("RIL_REQUEST_RADIO_POWER done");
if (ret <= 0) {
g_free(cbd);
CALLBACK_WITH_FAILURE(callback, data);
} else { } else {
if (online) ofono_error("%s: set_online: %d failed", __func__,
current_online_state = RIL_ONLINE_PREF; rd->ofono_online);
else CALLBACK_WITH_FAILURE(cb, cbd->data);
current_online_state = RIL_OFFLINE;
} }
} }
static int ril_screen_state(struct ofono_modem *modem, ofono_bool_t state) static void ril_send_power(struct ril_data *rd, ofono_bool_t online,
GRilResponseFunc func,
gpointer user_data)
{ {
struct ril_data *ril = ofono_modem_get_data(modem); struct cb_data *cbd = user_data;
ofono_modem_online_cb_t cb;
GDestroyNotify notify = NULL;
struct parcel rilp; struct parcel rilp;
int request = RIL_REQUEST_SCREEN_STATE;
guint ret; if (cbd != NULL) {
notify = g_free;
cb = cbd->cb;
}
DBG("(online = 1, offline = 0)): %i", online);
parcel_init(&rilp); parcel_init(&rilp);
parcel_w_int32(&rilp, 1); /* size of array */ parcel_w_int32(&rilp, 1);
parcel_w_int32(&rilp, state); /* screen on/off */ parcel_w_int32(&rilp, online);
/* fire and forget i.e. not waiting for the callback*/ g_ril_append_print_buf(rd->ril, "(%d)", online);
ret = g_ril_send(ril->modem, request, rilp.data,
rilp.size, NULL, NULL, NULL);
g_ril_append_print_buf(ril->modem, "(0)"); if (g_ril_send(rd->ril, RIL_REQUEST_RADIO_POWER, &rilp,
g_ril_print_request(ril->modem, ret, request); func, cbd, notify) == 0 && cbd != NULL) {
CALLBACK_WITH_FAILURE(cb, cbd->data);
parcel_free(&rilp); g_free(cbd);
}
return 0;
} }
static gboolean display_changed(DBusConnection *conn, void ril_set_online(struct ofono_modem *modem, ofono_bool_t online,
DBusMessage *message, void *user_data) ofono_modem_online_cb_t callback, void *data)
{ {
DBG(""); struct ril_data *rd = ofono_modem_get_data(modem);
struct ofono_modem *modem = user_data; struct cb_data *cbd = cb_data_new(callback, data, rd);
DBusMessageIter iter;
const char *value;
if (!dbus_message_iter_init(message, &iter)) rd->ofono_online = online;
return TRUE;
dbus_message_iter_get_basic(&iter, &value); DBG("setting rd->ofono_online to: %d", online);
DBG("Screen state: %s", value);
if (g_strcmp0(value, MCE_DISPLAY_ON_STRING) == 0) ril_send_power(rd, online, ril_set_online_cb, cbd);
ril_screen_state(modem, TRUE);
else if (g_strcmp0(value, MCE_DISPLAY_OFF_STRING) == 0)
ril_screen_state(modem, FALSE);
else
ril_screen_state(modem, TRUE); /* Dimmed, interpreted as ON */
return TRUE;
}
static void mce_connect(DBusConnection *conn, void *user_data)
{
DBG("");
signal_watch = g_dbus_add_signal_watch(conn,
MCE_SERVICE, NULL,
MCE_SIGNAL_IF,
MCE_DISPLAY_SIG,
display_changed,
user_data, NULL);
}
static void mce_disconnect(DBusConnection *conn, void *user_data)
{
DBG("");
g_dbus_remove_watch(conn, signal_watch);
signal_watch = 0;
} }
static void ril_connected(struct ril_msg *message, gpointer user_data) static void ril_connected(struct ril_msg *message, gpointer user_data)
{ {
DBG("");
struct ofono_modem *modem = (struct ofono_modem *) user_data; struct ofono_modem *modem = (struct ofono_modem *) user_data;
struct ril_data *ril = ofono_modem_get_data(modem); struct ril_data *rd = ofono_modem_get_data(modem);
int ril_version = 0;
struct parcel rilp;
ril_util_init_parcel(message, &rilp); ofono_info("[%d,UNSOL]< %s", g_ril_get_slot(rd->ril),
ril_version = parcel_r_int32(&rilp); g_ril_unsol_request_to_string(rd->ril, message->req));
ofono_debug("%s: [UNSOL]< %s, RIL_VERSION %d",
__func__, ril_unsol_request_to_string(message->req),
ril_version);
ril->connected = TRUE; /* TODO: need a disconnect function to restart things! */
rd->connected = TRUE;
send_get_sim_status(modem); DBG("calling set_powered(TRUE)");
connection = ofono_dbus_get_connection(); ofono_modem_set_powered(modem, TRUE);
mce_daemon_watch = g_dbus_add_service_watch(connection, MCE_SERVICE,
mce_connect, mce_disconnect, modem, NULL);
}
static int create_gril(struct ofono_modem *modem);
static gboolean connect_rild(gpointer user_data)
{
struct ofono_modem *modem = (struct ofono_modem *) user_data;
ofono_info("%s: Connecting %p to rild...", __func__, modem);
if (create_gril(modem) < 0) {
DBG("Connecting %p to rild failed, retry timer continues...",
modem);
return TRUE;
}
return FALSE;
}
/* RIL socket callback from g_io channel */
static void gril_disconnected(gpointer user_data)
{
struct ofono_modem *modem = user_data;
ofono_error("%s: modem: %p", __func__, modem);
DBusConnection *conn = ofono_dbus_get_connection();
if (ofono_modem_is_registered(modem)) {
mce_disconnect(conn, user_data);
ril_modem_remove(modem);
}
}
void ril_switchUser()
{
if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0)
ofono_error("%s: prctl(PR_SET_KEEPCAPS) failed:%s,%d",
__func__, strerror(errno), errno);
if (setgid(RADIO_ID) < 0)
ofono_error("%s: setgid(%d) failed:%s,%d",
__func__, RADIO_ID, strerror(errno), errno);
if (setuid(RADIO_ID) < 0)
ofono_error("%s: setuid(%d) failed:%s,%d",
__func__, RADIO_ID, strerror(errno), errno);
struct __user_cap_header_struct header;
struct __user_cap_data_struct cap;
header.version = _LINUX_CAPABILITY_VERSION;
header.pid = 0;
cap.effective = cap.permitted = (1 << CAP_NET_ADMIN)
| (1 << CAP_NET_RAW);
cap.inheritable = 0;
if (syscall(SYS_capset, &header, &cap) < 0)
ofono_error("%s: syscall(SYS_capset) failed:%s,%d",
__func__, strerror(errno), errno);
}
/* TODO: Reading RILD socket path by for now from rilmodem .conf file,
* but change this later to StateFs when plans are more concrete.
* return: Null-terminated path string. Ownership transferred.
* */
static char *ril_socket_path()
{
GError *err = NULL;
GKeyFile *keyfile = NULL;
char *res = NULL;
keyfile = g_key_file_new();
g_key_file_set_list_separator(keyfile, ',');
if (!g_key_file_load_from_file(keyfile, RILMODEM_CONF_FILE, 0, &err)) {
if (err) {
DBG("conf load result: %s", err->message);
g_error_free(err);
}
} else {
if (g_key_file_has_group(keyfile, RILSOCK_CONF_GROUP)) {
res = g_key_file_get_string(
keyfile, RILSOCK_CONF_GROUP, RILSOCK_CONF_PATH, &err);
if (err) {
DBG("conf get result: %s", err->message);
g_error_free(err);
}
}
}
g_key_file_free(keyfile);
if (!res) {
DBG("Falling back to default cmd sock path");
res = g_strdup(DEFAULT_CMD_SOCK);
}
return res;
} }
static int create_gril(struct ofono_modem *modem) static int create_gril(struct ofono_modem *modem)
{ {
DBG(" modem: %p", modem); struct ril_data *rd = ofono_modem_get_data(modem);
struct ril_data *ril = ofono_modem_get_data(modem); int slot_id = ofono_modem_get_integer(modem, "Slot");
/* RIL expects user radio */ ofono_info("Using %s as socket for slot %d.",
ril_switchUser(); RILD_CMD_SOCKET[slot_id], slot_id);
char *path = ril_socket_path(); /* RIL expects user radio to connect to the socket */
ril->modem = g_ril_new(path); rd->ril = g_ril_new_with_ucred(RILD_CMD_SOCKET[slot_id],
g_free(path); OFONO_RIL_VENDOR_AOSP,
path = NULL; RADIO_UID, RADIO_GID);
g_ril_set_disconnect_function(ril->modem, gril_disconnected, modem);
/* NOTE: Since AT modems open a tty, and then call /* NOTE: Since AT modems open a tty, and then call
* g_at_chat_new(), they're able to return -EIO if * g_at_chat_new(), they're able to return -EIO if
@@ -542,67 +356,66 @@ static int create_gril(struct ofono_modem *modem)
* abstraction... ( probaby not a bad idea ). * abstraction... ( probaby not a bad idea ).
*/ */
if (ril->modem == NULL) { if (rd->ril == NULL) {
DBG("g_ril_new() failed to create modem!"); ofono_error("g_ril_new() failed to create modem!");
return -EIO; return -EIO;
} }
g_ril_set_slot(rd->ril, slot_id);
if (getenv("OFONO_RIL_TRACE")) if (getenv("OFONO_RIL_TRACE"))
g_ril_set_trace(ril->modem, TRUE); g_ril_set_trace(rd->ril, TRUE);
if (getenv("OFONO_RIL_HEX_TRACE")) if (getenv("OFONO_RIL_HEX_TRACE"))
g_ril_set_debugf(ril->modem, ril_debug, "Device: "); g_ril_set_debugf(rd->ril, ril_debug, GRIL_HEX_PREFIX[slot_id]);
g_ril_register(ril->modem, RIL_UNSOL_RIL_CONNECTED, g_ril_register(rd->ril, RIL_UNSOL_RIL_CONNECTED,
ril_connected, modem); ril_connected, modem);
ofono_devinfo_create(modem, 0, "rilmodem", ril->modem); g_ril_register(rd->ril, RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED,
ril_radio_state_changed, modem);
return 0; return 0;
} }
static gboolean connect_rild(gpointer user_data)
{
struct ofono_modem *modem = (struct ofono_modem *) user_data;
struct ril_data *rd = ofono_modem_get_data(modem);
static int ril_enable(struct ofono_modem *modem) ofono_info("Trying to reconnect to rild...");
if (rd->rild_connect_retries++ < RILD_MAX_CONNECT_RETRIES) {
if (create_gril(modem) < 0)
return TRUE;
} else {
ofono_error("Failed to connect to rild.");
return TRUE;
}
return FALSE;
}
int ril_enable(struct ofono_modem *modem)
{ {
int ret; int ret;
DBG(""); DBG("");
ret = create_gril(modem); ret = create_gril(modem);
if (ret < 0) { if (ret < 0)
DBG("create gril: %d, queue reconnect", ret); g_timeout_add_seconds(RILD_CONNECT_RETRY_TIME_S,
g_timeout_add_seconds(2, connect_rild, modem);
connect_rild, modem);
}
return -EINPROGRESS; return -EINPROGRESS;
} }
static int ril_disable(struct ofono_modem *modem) int ril_disable(struct ofono_modem *modem)
{ {
struct ril_data *rd = ofono_modem_get_data(modem);
DBG("%p", modem); DBG("%p", modem);
struct ril_data *ril = ofono_modem_get_data(modem); ril_send_power(rd, FALSE, NULL, NULL);
struct parcel rilp;
int request = RIL_REQUEST_RADIO_POWER;
guint ret;
parcel_init(&rilp);
parcel_w_int32(&rilp, 1); /* size of array */
parcel_w_int32(&rilp, 0); /* POWER=OFF */
ofono_info("%s: RIL_REQUEST_RADIO_POWER OFF", __func__);
/* fire and forget i.e. not waiting for the callback*/
ret = g_ril_send(ril->modem, request, rilp.data,
rilp.size, NULL, NULL, NULL);
g_ril_append_print_buf(ril->modem, "(0)");
g_ril_print_request(ril->modem, ret, request);
parcel_free(&rilp);
/* this will trigger the cleanup of g_io_channel */
g_ril_unref(ril->modem);
ril->modem = NULL;
return 0; return 0;
} }
@@ -619,10 +432,16 @@ static struct ofono_modem_driver ril_driver = {
.set_online = ril_set_online, .set_online = ril_set_online,
}; };
/*
* This plugin is a generic ( aka default ) device plugin for RIL-based devices.
* The plugin 'rildev' is used to determine which RIL plugin should be loaded
* based upon an environment variable.
*/
static int ril_init(void) static int ril_init(void)
{ {
int retval = ofono_modem_driver_register(&ril_driver); int retval = ofono_modem_driver_register(&ril_driver);
if (retval)
if (retval != 0)
DBG("ofono_modem_driver_register returned: %d", retval); DBG("ofono_modem_driver_register returned: %d", retval);
return retval; return retval;
@@ -630,8 +449,9 @@ static int ril_init(void)
static void ril_exit(void) static void ril_exit(void)
{ {
DBG("");
ofono_modem_driver_unregister(&ril_driver); ofono_modem_driver_unregister(&ril_driver);
} }
OFONO_PLUGIN_DEFINE(ril, "RIL modem plugin", VERSION, OFONO_PLUGIN_DEFINE(ril, "RIL modem driver", VERSION,
OFONO_PLUGIN_PRIORITY_DEFAULT, ril_init, ril_exit) OFONO_PLUGIN_PRIORITY_DEFAULT, ril_init, ril_exit)

30
ofono/plugins/ril.h Normal file
View File

@@ -0,0 +1,30 @@
/*
*
* oFono - Open Source Telephony - RIL-based devices
*
* 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
*
*/
int ril_create(struct ofono_modem *modem, enum ofono_ril_vendor vendor);
void ril_remove(struct ofono_modem *modem);
int ril_enable(struct ofono_modem *modem);
int ril_disable(struct ofono_modem *modem);
void ril_pre_sim(struct ofono_modem *modem);
void ril_post_sim(struct ofono_modem *modem);
void ril_post_online(struct ofono_modem *modem);
void ril_set_online(struct ofono_modem *modem, ofono_bool_t online,
ofono_modem_online_cb_t callback, void *data);

View File

@@ -0,0 +1,291 @@
/*
*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2008-2015 Intel Corporation. All rights reserved.
* Copyright (C) 2012-2014 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
* 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 <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <glib.h>
#define OFONO_API_SUBJECT_TO_CHANGE
#include <ofono/plugin.h>
#include <ofono/log.h>
#include <ofono/types.h>
#include <ofono/modem.h>
#include <ofono/devinfo.h>
#include <ofono/netreg.h>
#include <ofono/sms.h>
#include <ofono/sim.h>
#include <ofono/gprs.h>
#include <ofono/gprs-context.h>
#include <ofono/radio-settings.h>
#include <ofono/ussd.h>
#include <ofono/netmon.h>
#include <gril/gril.h>
#include "drivers/rilmodem/rilmodem.h"
#include "drivers/rilmodem/vendor.h"
struct ril_data {
GRil *ril;
};
static int ril_send_power(GRil *ril, ofono_bool_t online,
GRilResponseFunc func,
gpointer user_data,
GDestroyNotify destroy)
{
struct parcel rilp;
DBG("%d", online);
parcel_init(&rilp);
parcel_w_int32(&rilp, 1);
parcel_w_int32(&rilp, online);
g_ril_append_print_buf(ril, "(%d)", online);
return g_ril_send(ril, RIL_REQUEST_RADIO_POWER, &rilp,
func, user_data, destroy);
}
static void ril_debug(const char *str, void *user_data)
{
const char *prefix = user_data;
ofono_info("%s%s", prefix, str);
}
static void ril_radio_state_changed(struct ril_msg *message,
gpointer user_data)
{
struct ofono_modem *modem = user_data;
struct ril_data *rd = ofono_modem_get_data(modem);
struct parcel rilp;
int radio_state;
g_ril_init_parcel(message, &rilp);
radio_state = parcel_r_int32(&rilp);
if (rilp.malformed) {
ofono_error("%s: malformed parcel received", __func__);
ofono_modem_set_powered(modem, FALSE);
return;
}
g_ril_append_print_buf(rd->ril, "(state: %s)",
ril_radio_state_to_string(radio_state));
g_ril_print_unsol(rd->ril, message);
switch (radio_state) {
case RADIO_STATE_ON:
break;
case RADIO_STATE_UNAVAILABLE:
ofono_modem_set_powered(modem, FALSE);
break;
case RADIO_STATE_OFF:
break;
}
}
static int ril_probe(struct ofono_modem *modem)
{
struct ril_data *rd;
DBG("");
rd = g_new0(struct ril_data, 1);
ofono_modem_set_data(modem, rd);
return 0;
}
static void ril_remove(struct ofono_modem *modem)
{
struct ril_data *rd = ofono_modem_get_data(modem);
ofono_modem_set_data(modem, NULL);
g_ril_unref(rd->ril);
g_free(rd);
}
static void ril_pre_sim(struct ofono_modem *modem)
{
struct ril_data *rd = ofono_modem_get_data(modem);
DBG("");
ofono_devinfo_create(modem, 0, "rilmodem", rd->ril);
ofono_sim_create(modem, 0, "rilmodem", rd->ril);
}
static void ril_post_sim(struct ofono_modem *modem)
{
struct ril_data *rd = ofono_modem_get_data(modem);
struct ofono_gprs *gprs;
struct ofono_gprs_context *gc;
ofono_sms_create(modem, OFONO_RIL_VENDOR_IMC_SOFIA3GR,
"rilmodem", rd->ril);
gprs = ofono_gprs_create(modem, 0, "rilmodem", rd->ril);
gc = ofono_gprs_context_create(modem, 0, "rilmodem", rd->ril);
if (gc) {
ofono_gprs_context_set_type(gc,
OFONO_GPRS_CONTEXT_TYPE_INTERNET);
ofono_gprs_add_context(gprs, gc);
}
}
static void ril_post_online(struct ofono_modem *modem)
{
struct ril_data *rd = ofono_modem_get_data(modem);
ofono_netreg_create(modem, 0, "rilmodem", rd->ril);
ofono_radio_settings_create(modem, OFONO_RIL_VENDOR_IMC_SOFIA3GR,
"rilmodem", rd->ril);
ofono_ussd_create(modem, 0, "rilmodem", rd->ril);
ofono_netmon_create(modem, 0, "rilmodem", rd->ril);
}
static void ril_set_online_cb(struct ril_msg *message, gpointer user_data)
{
struct cb_data *cbd = user_data;
ofono_modem_online_cb_t cb = cbd->cb;
DBG("%d", message->error);
if (message->error == RIL_E_SUCCESS)
CALLBACK_WITH_SUCCESS(cb, cbd->data);
else
CALLBACK_WITH_FAILURE(cb, cbd->data);
}
static void ril_set_online(struct ofono_modem *modem, ofono_bool_t online,
ofono_modem_online_cb_t cb, void *data)
{
struct ril_data *rd = ofono_modem_get_data(modem);
struct cb_data *cbd = cb_data_new(cb, data, rd);
if (ril_send_power(rd->ril, online, ril_set_online_cb, cbd, g_free) > 0)
return;
CALLBACK_WITH_FAILURE(cb, cbd->data);
g_free(cbd);
}
static void ril_init_power(struct ril_msg *message, gpointer user_data)
{
struct ofono_modem *modem = user_data;
ofono_bool_t powered;
DBG("%d", message->error);
powered = message->error != RIL_E_SUCCESS ? FALSE : TRUE;
ofono_modem_set_powered(modem, powered);
}
static void ril_connected(struct ril_msg *message, gpointer user_data)
{
struct ofono_modem *modem = user_data;
struct ril_data *rd = ofono_modem_get_data(modem);
DBG("");
/* Set Modem Offline */
if (ril_send_power(rd->ril, FALSE, ril_init_power, modem, NULL) > 0)
return;
ofono_modem_set_powered(modem, FALSE);
}
static int ril_enable(struct ofono_modem *modem)
{
struct ril_data *rd = ofono_modem_get_data(modem);
DBG("");
rd->ril = g_ril_new("/tmp/rild", OFONO_RIL_VENDOR_AOSP);
if (rd->ril == NULL) {
ofono_error("g_ril_new() failed to create modem!");
return -EIO;
}
if (getenv("OFONO_RIL_TRACE"))
g_ril_set_trace(rd->ril, TRUE);
if (getenv("OFONO_RIL_HEX_TRACE"))
g_ril_set_debugf(rd->ril, ril_debug, "Sofia3GR:");
g_ril_register(rd->ril, RIL_UNSOL_RIL_CONNECTED,
ril_connected, modem);
g_ril_register(rd->ril, RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED,
ril_radio_state_changed, modem);
return -EINPROGRESS;
}
static int ril_disable(struct ofono_modem *modem)
{
struct ril_data *rd = ofono_modem_get_data(modem);
DBG("%p", modem);
ril_send_power(rd->ril, FALSE, NULL, NULL, NULL);
return 0;
}
static struct ofono_modem_driver ril_driver = {
.name = "ril_sofia3gr",
.probe = ril_probe,
.remove = ril_remove,
.enable = ril_enable,
.disable = ril_disable,
.pre_sim = ril_pre_sim,
.post_sim = ril_post_sim,
.post_online = ril_post_online,
.set_online = ril_set_online,
};
static int ril_init(void)
{
return ofono_modem_driver_register(&ril_driver);
}
static void ril_exit(void)
{
ofono_modem_driver_unregister(&ril_driver);
}
OFONO_PLUGIN_DEFINE(ril_sofia3gr, "SoFiA 3GR RIL-based modem driver", VERSION,
OFONO_PLUGIN_PRIORITY_DEFAULT, ril_init, ril_exit)

View File

@@ -4,7 +4,6 @@
* *
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved. * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2014 Canonical Ltd. * Copyright (C) 2014 Canonical Ltd.
* Copyright (C) 2015 Jolla Ltd.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
@@ -32,249 +31,87 @@
#include <glib.h> #include <glib.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <unistd.h>
#include <sys/inotify.h>
#define OFONO_API_SUBJECT_TO_CHANGE #define OFONO_API_SUBJECT_TO_CHANGE
#include <ofono/plugin.h> #include <ofono/plugin.h>
#include <ofono/modem.h> #include <ofono/modem.h>
#include <ofono/log.h> #include <ofono/log.h>
#include "rildev.h"
#define EVENT_SIZE (sizeof(struct inotify_event))
/*
* As a best guess use a buffer size of 100 inotify events.
* NAME_MAX+1 from inotify documentation.
*/
#define IBUF_LEN (100*(EVENT_SIZE + NAME_MAX + 1))
static int inotify_fd = -1;
static int inotify_watch_id = -1;
static guint inotify_watch_source_id;
static GIOChannel *inotify_watch_channel;
static GSList *modem_list; static GSList *modem_list;
static int watch_for_rild_socket(void);
static void detect_rild(void);
static struct ofono_modem *find_ril_modem(int slot)
{
GSList *list;
for (list = modem_list; list; list = list->next) {
struct ofono_modem *modem = list->data;
int ril_slot = ofono_modem_get_integer(modem, "Slot");
if (ril_slot == slot)
return modem;
}
return NULL;
}
static void remove_watchers(void)
{
DBG("");
if (inotify_watch_channel == NULL)
return;
g_source_remove(inotify_watch_source_id);
inotify_watch_source_id = 0;
g_io_channel_unref(inotify_watch_channel);
inotify_watch_channel = NULL;
inotify_rm_watch(inotify_fd, inotify_watch_id);
inotify_watch_id = -1;
close(inotify_fd);
inotify_fd = -1;
}
/* Removes a RIL modem and initiates a sequence to create a new one */
void ril_modem_remove(struct ofono_modem *modem)
{
DBG("modem: %p", modem);
struct ofono_modem *list_modem;
int slot = -1;
list_modem = NULL;
if (modem)
slot = ofono_modem_get_integer(modem, "Slot");
if (slot >= 0)
list_modem = find_ril_modem(slot);
if (list_modem) {
ofono_modem_remove(modem);
modem_list = g_slist_remove(modem_list, list_modem);
}
detect_rild();
}
/* return: 0 if successful or modem already exists, otherwise and error */
static int create_rilmodem(const char *ril_type, int slot) static int create_rilmodem(const char *ril_type, int slot)
{ {
struct ofono_modem *modem; struct ofono_modem *modem;
char dev_name[64]; char dev_name[64];
int retval; int retval;
DBG("");
snprintf(dev_name, sizeof(dev_name), "ril_%d", slot); snprintf(dev_name, sizeof(dev_name), "ril_%d", slot);
/* Check that not created already */
if (find_ril_modem(slot))
return 0;
/* Currently there is only one ril implementation, create always */
modem = ofono_modem_create(dev_name, ril_type); modem = ofono_modem_create(dev_name, ril_type);
if (modem == NULL) { if (modem == NULL) {
DBG("ofono_modem_create failed for type: %s", ril_type); DBG("ofono_modem_create failed for type %s", ril_type);
return -ENODEV; return -ENODEV;
} }
DBG("created modem: %p", modem);
modem_list = g_slist_prepend(modem_list, modem); modem_list = g_slist_prepend(modem_list, modem);
ofono_modem_set_integer(modem, "Slot", slot); ofono_modem_set_integer(modem, "Slot", slot);
/* This causes driver->probe() to be called */ /* This causes driver->probe() to be called... */
retval = ofono_modem_register(modem); retval = ofono_modem_register(modem);
if (retval != 0) { if (retval != 0) {
ofono_error("%s: ofono_modem_register error: %d", ofono_error("%s: ofono_modem_register returned: %d",
__func__, retval); __func__, retval);
return retval; return retval;
} }
return 0;
}
/*
* Try creating a ril modem
* return: false if failed, true successful or modem already exists.
*/
static gboolean try_create_modem()
{
gboolean result = FALSE;
int ares = access(RILD_CMD_SOCKET, F_OK);
if (ares != -1)
result = !create_rilmodem("ril", 0);
else
DBG("problems accessing rild socket: %d", ares);
return result;
}
static gboolean rild_inotify(GIOChannel *gio, GIOCondition c,
gpointer data)
{
DBG("");
struct inotify_event *event = 0;
int i = 0;
int length = 0;
char *ievents = 0; /* inotify event buffer */
gboolean result = TRUE;
ievents = g_try_malloc(IBUF_LEN);
if (!ievents) {
/* Continue observing so don't set "result" false here */
goto end;
}
length = read(inotify_fd, ievents, IBUF_LEN);
/* /*
* If iNotify fd read returns an error, just keep on watching for * kickstart the modem:
* read events. * causes core modem code to call
* - set_powered(TRUE) - which in turn
* calls driver->enable()
*
* - driver->pre_sim()
*
* Could also be done via:
*
* - a DBus call to SetProperties w/"Powered=TRUE" *1
* - sim_state_watch ( handles SIM removal? LOCKED states? **2
* - ofono_modem_set_powered()
*/ */
while (i < length) { ofono_modem_reset(modem);
event = (struct inotify_event *) &ievents[i];
if (event->len && (event->mask & IN_CREATE)
&& (!(event->mask & IN_ISDIR))) {
DBG("File created: %s", event->name);
if (!strcmp(event->name, RILD_SOCKET_FILE)) {
result = !try_create_modem();
/*
* On modem create fail continue observing
* events so don't set result false here.
*/
goto end;
}
}
i += EVENT_SIZE + event->len;
}
end:
/* "if" works around potential glib runtime warning */
if (ievents)
g_free(ievents);
if (!result)
remove_watchers();
return result;
}
/* return 0 if successful, otherwise an error */
static int watch_for_rild_socket(void)
{
DBG("");
inotify_fd = inotify_init();
if (inotify_fd < 0)
return -EIO;
inotify_watch_channel = g_io_channel_unix_new(inotify_fd);
if (inotify_watch_channel == NULL) {
ofono_error("%s: rildev gio chan creation fail!", __func__);
close(inotify_fd);
inotify_fd = -1;
return -EIO;
}
inotify_watch_id = inotify_add_watch(inotify_fd, RILD_SOCKET_DIR,
IN_CREATE);
if (inotify_watch_id < 0) {
ofono_error("%s: inotify says: %d, errno: %d",
__func__, inotify_watch_id, errno);
g_io_channel_unref(inotify_watch_channel);
inotify_watch_channel = NULL;
close(inotify_fd);
inotify_fd = -1;
return -EIO;
}
inotify_watch_source_id = g_io_add_watch(inotify_watch_channel,
G_IO_IN,
rild_inotify, NULL);
if (inotify_watch_source_id <= 0) {
ofono_error("%s: rildev add gio watch fail!", __func__);
g_io_channel_unref(inotify_watch_channel);
inotify_watch_channel = NULL;
inotify_rm_watch(inotify_fd, inotify_watch_id);
inotify_watch_id = -1;
close(inotify_fd);
inotify_fd = -1;
return -EIO;
}
return 0; return 0;
} }
static void detect_rild(void)
{
DBG("");
gboolean created = try_create_modem();
if (!created)
watch_for_rild_socket();
/* Let's re-check if we just missed the notification */
if (!created && try_create_modem())
remove_watchers();
}
static int detect_init(void) static int detect_init(void)
{ {
DBG(""); const char *ril_type;
detect_rild(); const char *multi_sim;
int num_slots = 1;
int i;
ril_type = getenv("OFONO_RIL_DEVICE");
if (ril_type == NULL)
return 0;
/* Check for multi-SIM support */
multi_sim = getenv("OFONO_RIL_NUM_SIM_SLOTS");
if (multi_sim != NULL && *multi_sim != '\0') {
int env_slots;
char *endp;
env_slots = (int) strtoul(multi_sim, &endp, 10);
if (*endp == '\0')
num_slots = env_slots;
}
ofono_info("RILDEV detected modem type %s, %d SIM slot(s)",
ril_type, num_slots);
for (i = 0; i < num_slots; ++i)
create_rilmodem(ril_type, i);
return 0; return 0;
} }
@@ -282,8 +119,6 @@ static void detect_exit(void)
{ {
GSList *list; GSList *list;
DBG("");
for (list = modem_list; list; list = list->next) { for (list = modem_list; list; list = list->next) {
struct ofono_modem *modem = list->data; struct ofono_modem *modem = list->data;
@@ -292,8 +127,7 @@ static void detect_exit(void)
g_slist_free(modem_list); g_slist_free(modem_list);
modem_list = NULL; modem_list = NULL;
remove_watchers();
} }
OFONO_PLUGIN_DEFINE(rildev, "RIL type detection", VERSION, OFONO_PLUGIN_DEFINE(rildev, "ril type detection", VERSION,
OFONO_PLUGIN_PRIORITY_DEFAULT, detect_init, detect_exit) OFONO_PLUGIN_PRIORITY_DEFAULT, detect_init, detect_exit)

View File

@@ -216,8 +216,7 @@ static DBusMessage *smart_messaging_send_vcard(DBusConnection *conn,
err = __ofono_sms_txq_submit(sm->sms, msg_list, flags, &uuid, err = __ofono_sms_txq_submit(sm->sms, msg_list, flags, &uuid,
message_queued, msg); message_queued, msg);
g_slist_foreach(msg_list, (GFunc)g_free, NULL); g_slist_free_full(msg_list, g_free);
g_slist_free(msg_list);
if (err < 0) if (err < 0)
return __ofono_error_failed(msg); return __ofono_error_failed(msg);
@@ -259,8 +258,7 @@ static DBusMessage *smart_messaging_send_vcal(DBusConnection *conn,
err = __ofono_sms_txq_submit(sm->sms, msg_list, flags, &uuid, err = __ofono_sms_txq_submit(sm->sms, msg_list, flags, &uuid,
message_queued, msg); message_queued, msg);
g_slist_foreach(msg_list, (GFunc)g_free, NULL); g_slist_free_full(msg_list, g_free);
g_slist_free(msg_list);
if (err < 0) if (err < 0)
return __ofono_error_failed(msg); return __ofono_error_failed(msg);

View File

@@ -162,11 +162,11 @@ static void set_online_cb(gboolean ok, GAtResult *result, gpointer user_data)
{ {
struct cb_data *cbd = user_data; struct cb_data *cbd = user_data;
ofono_modem_online_cb_t callback = cbd->cb; ofono_modem_online_cb_t callback = cbd->cb;
struct ofono_error error;
decode_at_error(&error, g_at_result_final_response(result)); if (ok)
CALLBACK_WITH_SUCCESS(callback, cbd->data);
callback(&error, cbd->data); else
CALLBACK_WITH_FAILURE(callback, cbd->data);
} }
static void stktest_set_online(struct ofono_modem *modem, ofono_bool_t online, static void stktest_set_online(struct ofono_modem *modem, ofono_bool_t online,

View File

@@ -44,9 +44,18 @@
static const char *none_prefix[] = { NULL }; static const char *none_prefix[] = { NULL };
enum supported_models {
SARA_G270 = 1102,
TOBYL2_COMPATIBLE_MODE = 1141,
TOBYL2_MEDIUM_THROUGHPUT_MODE = 1143,
TOBYL2_HIGH_THROUGHPUT_MODE = 1146,
};
struct ublox_data { struct ublox_data {
GAtChat *modem; GAtChat *modem;
GAtChat *aux; GAtChat *aux;
int model_id;
enum ofono_vendor vendor_family;
}; };
static void ublox_debug(const char *str, void *user_data) static void ublox_debug(const char *str, void *user_data)
@@ -132,30 +141,67 @@ static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data)
return; return;
} }
if (data->model_id == TOBYL2_HIGH_THROUGHPUT_MODE)
/* use bridged mode until routed mode support is added */
g_at_chat_send(data->aux, "AT+UBMCONF=2", none_prefix,
NULL, NULL, NULL);
ofono_modem_set_powered(modem, TRUE); ofono_modem_set_powered(modem, TRUE);
} }
static int ublox_enable(struct ofono_modem *modem) static int ublox_enable(struct ofono_modem *modem)
{ {
struct ublox_data *data = ofono_modem_get_data(modem); struct ublox_data *data = ofono_modem_get_data(modem);
const char *model_str = NULL;
DBG("%p", modem); DBG("%p", modem);
data->modem = open_device(modem, "Modem", "Modem: "); model_str = ofono_modem_get_string(modem, "Model");
if (data->modem == NULL) if (model_str == NULL)
return -EINVAL; return -EINVAL;
data->aux = open_device(modem, "Aux", "Aux: "); /*
if (data->aux == NULL) { * Toby L2 devices are more complex and special than previously
g_at_chat_unref(data->modem); * supported U-Blox devices. So they need a vendor of their own.
data->modem = NULL; */
return -EIO; data->model_id = atoi(model_str);
switch (data->model_id) {
case SARA_G270:
data->vendor_family = OFONO_VENDOR_UBLOX;
break;
case TOBYL2_COMPATIBLE_MODE:
case TOBYL2_HIGH_THROUGHPUT_MODE:
data->vendor_family = OFONO_VENDOR_UBLOX_TOBY_L2;
break;
case TOBYL2_MEDIUM_THROUGHPUT_MODE:
DBG("low/medium throughtput profile unsupported");
default:
DBG("unknown ublox model id %d", data->model_id);
return -EINVAL;
} }
g_at_chat_set_slave(data->modem, data->aux); data->aux = open_device(modem, "Aux", "Aux: ");
if (data->aux == NULL)
return -EINVAL;
if (data->vendor_family == OFONO_VENDOR_UBLOX) {
data->modem = open_device(modem, "Modem", "Modem: ");
if (data->modem == NULL) {
g_at_chat_unref(data->aux);
data->aux = NULL;
return -EIO;
}
g_at_chat_set_slave(data->modem, data->aux);
g_at_chat_send(data->modem, "ATE0 +CMEE=1", none_prefix,
NULL, NULL, NULL);
}
/* The modem can take a while to wake up if just powered on. */
g_at_chat_set_wakeup_command(data->aux, "AT\r", 1000, 11000);
g_at_chat_send(data->modem, "ATE0 +CMEE=1", none_prefix,
NULL, NULL, NULL);
g_at_chat_send(data->aux, "ATE0 +CMEE=1", none_prefix, g_at_chat_send(data->aux, "ATE0 +CMEE=1", none_prefix,
NULL, NULL, NULL); NULL, NULL, NULL);
@@ -235,7 +281,7 @@ static void ublox_pre_sim(struct ofono_modem *modem)
DBG("%p", modem); DBG("%p", modem);
ofono_devinfo_create(modem, 0, "atmodem", data->aux); ofono_devinfo_create(modem, 0, "atmodem", data->aux);
sim = ofono_sim_create(modem, OFONO_VENDOR_UBLOX, "atmodem", sim = ofono_sim_create(modem, data->vendor_family, "atmodem",
data->aux); data->aux);
if (sim) if (sim)
@@ -247,23 +293,33 @@ static void ublox_post_sim(struct ofono_modem *modem)
struct ublox_data *data = ofono_modem_get_data(modem); struct ublox_data *data = ofono_modem_get_data(modem);
struct ofono_gprs *gprs; struct ofono_gprs *gprs;
struct ofono_gprs_context *gc; struct ofono_gprs_context *gc;
GAtChat *chat = data->modem ? data->modem : data->aux;
const char *driver = data->model_id == TOBYL2_HIGH_THROUGHPUT_MODE ?
"ubloxmodem" : "atmodem";
/* Toby L2: Create same number of contexts as supported PDP contexts. */
int ncontexts = data->model_id == TOBYL2_HIGH_THROUGHPUT_MODE ? 8 : 1;
DBG("%p", modem); DBG("%p", modem);
gprs = ofono_gprs_create(modem, OFONO_VENDOR_UBLOX, "atmodem", gprs = ofono_gprs_create(modem, data->vendor_family, "atmodem",
data->aux); data->aux);
gc = ofono_gprs_context_create(modem, OFONO_VENDOR_UBLOX, "atmodem",
data->modem);
if (gprs && gc) while (ncontexts) {
ofono_gprs_add_context(gprs, gc); gc = ofono_gprs_context_create(modem, data->vendor_family,
driver, chat);
if (gprs && gc)
ofono_gprs_add_context(gprs, gc);
--ncontexts;
}
} }
static void ublox_post_online(struct ofono_modem *modem) static void ublox_post_online(struct ofono_modem *modem)
{ {
struct ublox_data *data = ofono_modem_get_data(modem); struct ublox_data *data = ofono_modem_get_data(modem);
ofono_netreg_create(modem, 0, "atmodem", data->aux); ofono_netreg_create(modem, data->vendor_family, "atmodem", data->aux);
} }
static struct ofono_modem_driver ublox_driver = { static struct ofono_modem_driver ublox_driver = {

View File

@@ -55,6 +55,7 @@ struct device_info {
char *number; char *number;
char *label; char *label;
char *sysattr; char *sysattr;
char *subsystem;
}; };
static gboolean setup_isi(struct modem_info *modem) static gboolean setup_isi(struct modem_info *modem)
@@ -219,7 +220,7 @@ static gboolean setup_gobi(struct modem_info *modem)
static gboolean setup_sierra(struct modem_info *modem) static gboolean setup_sierra(struct modem_info *modem)
{ {
const char *mdm = NULL, *app = NULL, *net = NULL, *diag = NULL; const char *mdm = NULL, *app = NULL, *net = NULL, *diag = NULL, *qmi = NULL;
GSList *list; GSList *list;
DBG("%s", modem->syspath); DBG("%s", modem->syspath);
@@ -227,8 +228,8 @@ static gboolean setup_sierra(struct modem_info *modem)
for (list = modem->devices; list; list = list->next) { for (list = modem->devices; list; list = list->next) {
struct device_info *info = list->data; struct device_info *info = list->data;
DBG("%s %s %s %s", info->devnode, info->interface, DBG("%s %s %s %s %s", info->devnode, info->interface,
info->number, info->label); info->number, info->label, info->subsystem);
if (g_strcmp0(info->interface, "255/255/255") == 0) { if (g_strcmp0(info->interface, "255/255/255") == 0) {
if (g_strcmp0(info->number, "01") == 0) if (g_strcmp0(info->number, "01") == 0)
@@ -239,14 +240,30 @@ static gboolean setup_sierra(struct modem_info *modem)
app = info->devnode; app = info->devnode;
else if (g_strcmp0(info->number, "07") == 0) else if (g_strcmp0(info->number, "07") == 0)
net = info->devnode; net = info->devnode;
else if (g_strcmp0(info->number, "0a") == 0) {
if (g_strcmp0(info->subsystem, "net") == 0)
net = info->devnode;
else if (g_strcmp0(info->subsystem,
"usbmisc") == 0)
qmi = info->devnode;
}
} }
} }
if (qmi != NULL && net != NULL) {
ofono_modem_set_driver(modem->modem, "gobi");
/* Fixup SIM interface for Sierra QMI devices */
ofono_modem_set_boolean(modem->modem, "ForceSimLegacy", TRUE);
goto done;
}
if (mdm == NULL || net == NULL) if (mdm == NULL || net == NULL)
return FALSE; return FALSE;
DBG("modem=%s app=%s net=%s diag=%s", mdm, app, net, diag); done:
DBG("modem=%s app=%s net=%s diag=%s qmi=%s", mdm, app, net, diag, qmi);
ofono_modem_set_string(modem->modem, "Device", qmi);
ofono_modem_set_string(modem->modem, "Modem", mdm); ofono_modem_set_string(modem->modem, "Modem", mdm);
ofono_modem_set_string(modem->modem, "App", app); ofono_modem_set_string(modem->modem, "App", app);
ofono_modem_set_string(modem->modem, "Diag", diag); ofono_modem_set_string(modem->modem, "Diag", diag);
@@ -838,7 +855,7 @@ static gboolean setup_quectel(struct modem_info *modem)
static gboolean setup_ublox(struct modem_info *modem) static gboolean setup_ublox(struct modem_info *modem)
{ {
const char *aux = NULL, *mdm = NULL; const char *aux = NULL, *mdm = NULL, *net = NULL;
GSList *list; GSList *list;
DBG("%s", modem->syspath); DBG("%s", modem->syspath);
@@ -857,21 +874,40 @@ static gboolean setup_ublox(struct modem_info *modem)
mdm = info->devnode; mdm = info->devnode;
if (aux != NULL) if (aux != NULL)
break; break;
/*
* "2/2/1"
* - a common modem interface both for older models like LISA,
* and for newer models like TOBY.
* For TOBY-L2, NetworkInterface can be detected for each
* profile:
* - low-medium throughput profile : 2/6/0
* - fairly backward-compatible profile : 10/0/0
* - high throughput profile : 224/1/3
*/
} else if (g_strcmp0(info->interface, "2/2/1") == 0) { } else if (g_strcmp0(info->interface, "2/2/1") == 0) {
if (g_strcmp0(info->number, "02") == 0) if (g_strcmp0(info->number, "02") == 0)
aux = info->devnode; aux = info->devnode;
else if (g_strcmp0(info->number, "00") == 0) else if (g_strcmp0(info->number, "00") == 0)
mdm = info->devnode; mdm = info->devnode;
} else if (g_strcmp0(info->interface, "2/6/0") == 0 ||
g_strcmp0(info->interface, "10/0/0") == 0 ||
g_strcmp0(info->interface, "224/1/3") == 0) {
net = info->devnode;
} }
} }
if (aux == NULL || mdm == NULL) /* Abort only if both interfaces are NULL, as it's highly possible that
* only one of 2 interfaces is available for U-blox modem.
*/
if (aux == NULL && mdm == NULL)
return FALSE; return FALSE;
DBG("aux=%s modem=%s", aux, mdm); DBG("aux=%s modem=%s net=%s", aux, mdm, net);
ofono_modem_set_string(modem->modem, "Aux", aux); ofono_modem_set_string(modem->modem, "Aux", aux);
ofono_modem_set_string(modem->modem, "Modem", mdm); ofono_modem_set_string(modem->modem, "Modem", mdm);
ofono_modem_set_string(modem->modem, "Model", modem->model);
ofono_modem_set_string(modem->modem, "NetworkInterface", net);
return TRUE; return TRUE;
} }
@@ -939,6 +975,7 @@ static void destroy_modem(gpointer data)
g_free(info->number); g_free(info->number);
g_free(info->label); g_free(info->label);
g_free(info->sysattr); g_free(info->sysattr);
g_free(info->subsystem);
g_free(info); g_free(info);
list->data = NULL; list->data = NULL;
@@ -997,9 +1034,11 @@ static void add_device(const char *syspath, const char *devname,
const char *model, struct udev_device *device) const char *model, struct udev_device *device)
{ {
struct udev_device *intf; struct udev_device *intf;
const char *devpath, *devnode, *interface, *number, *label, *sysattr; const char *devpath, *devnode, *interface, *number;
const char *label, *sysattr, *subsystem;
struct modem_info *modem; struct modem_info *modem;
struct device_info *info; struct device_info *info;
struct udev_device *parent;
devpath = udev_device_get_syspath(device); devpath = udev_device_get_syspath(device);
if (devpath == NULL) if (devpath == NULL)
@@ -1037,7 +1076,20 @@ static void add_device(const char *syspath, const char *devname,
interface = udev_device_get_property_value(intf, "INTERFACE"); interface = udev_device_get_property_value(intf, "INTERFACE");
number = udev_device_get_property_value(device, "ID_USB_INTERFACE_NUM"); number = udev_device_get_property_value(device, "ID_USB_INTERFACE_NUM");
/* If environment variable is not set, get value from attributes (or parent's ones) */
if (number == NULL) {
number = udev_device_get_sysattr_value(device,
"bInterfaceNumber");
if (number == NULL) {
parent = udev_device_get_parent(device);
number = udev_device_get_sysattr_value(parent,
"bInterfaceNumber");
}
}
label = udev_device_get_property_value(device, "OFONO_LABEL"); label = udev_device_get_property_value(device, "OFONO_LABEL");
subsystem = udev_device_get_subsystem(device);
if (modem->sysattr != NULL) if (modem->sysattr != NULL)
sysattr = udev_device_get_sysattr_value(device, modem->sysattr); sysattr = udev_device_get_sysattr_value(device, modem->sysattr);
@@ -1059,6 +1111,7 @@ static void add_device(const char *syspath, const char *devname,
info->number = g_strdup(number); info->number = g_strdup(number);
info->label = g_strdup(label); info->label = g_strdup(label);
info->sysattr = g_strdup(sysattr); info->sysattr = g_strdup(sysattr);
info->subsystem = g_strdup(subsystem);
modem->devices = g_slist_insert_sorted(modem->devices, info, modem->devices = g_slist_insert_sorted(modem->devices, info,
compare_device); compare_device);
@@ -1096,6 +1149,8 @@ static struct {
{ "hso", "hso" }, { "hso", "hso" },
{ "gobi", "qmi_wwan" }, { "gobi", "qmi_wwan" },
{ "gobi", "qcserial" }, { "gobi", "qcserial" },
{ "sierra", "qmi_wwan", "1199" },
{ "sierra", "qcserial", "1199" },
{ "sierra", "sierra" }, { "sierra", "sierra" },
{ "sierra", "sierra_net" }, { "sierra", "sierra_net" },
{ "option", "option", "0af0" }, { "option", "option", "0af0" },
@@ -1120,6 +1175,8 @@ static struct {
{ "samsung", "kalmia" }, { "samsung", "kalmia" },
{ "quectel", "option", "05c6", "9090" }, { "quectel", "option", "05c6", "9090" },
{ "ublox", "cdc_acm", "1546", "1102" }, { "ublox", "cdc_acm", "1546", "1102" },
{ "ublox", "rndis_host", "1546", "1146" },
{ "ublox", "cdc_acm", "1546", "1146" },
{ } { }
}; };
@@ -1217,7 +1274,8 @@ static void check_device(struct udev_device *device)
return; return;
} }
if (g_str_equal(bus, "usb") == TRUE) if ((g_str_equal(bus, "usb") == TRUE) ||
(g_str_equal(bus, "usbmisc") == TRUE))
check_usb_device(device); check_usb_device(device);
} }
@@ -1267,6 +1325,7 @@ static void enumerate_devices(struct udev *context)
udev_enumerate_add_match_subsystem(enumerate, "tty"); udev_enumerate_add_match_subsystem(enumerate, "tty");
udev_enumerate_add_match_subsystem(enumerate, "usb"); udev_enumerate_add_match_subsystem(enumerate, "usb");
udev_enumerate_add_match_subsystem(enumerate, "usbmisc");
udev_enumerate_add_match_subsystem(enumerate, "net"); udev_enumerate_add_match_subsystem(enumerate, "net");
udev_enumerate_scan_devices(enumerate); udev_enumerate_scan_devices(enumerate);
@@ -1389,6 +1448,8 @@ static int detect_init(void)
udev_monitor_filter_add_match_subsystem_devtype(udev_mon, "tty", NULL); udev_monitor_filter_add_match_subsystem_devtype(udev_mon, "tty", NULL);
udev_monitor_filter_add_match_subsystem_devtype(udev_mon, "usb", NULL); udev_monitor_filter_add_match_subsystem_devtype(udev_mon, "usb", NULL);
udev_monitor_filter_add_match_subsystem_devtype(udev_mon,
"usbmisc", NULL);
udev_monitor_filter_add_match_subsystem_devtype(udev_mon, "net", NULL); udev_monitor_filter_add_match_subsystem_devtype(udev_mon, "net", NULL);
udev_monitor_filter_update(udev_mon); udev_monitor_filter_update(udev_mon);

370
ofono/plugins/upower.c Normal file
View File

@@ -0,0 +1,370 @@
/*
*
* oFono - Open Source Telephony
*
* Copyright (C) 2015 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 <glib.h>
#include <gdbus.h>
#include <ofono.h>
#define OFONO_API_SUBJECT_TO_CHANGE
#include <ofono/plugin.h>
#include <ofono/modem.h>
#include <ofono/log.h>
#include <ofono/emulator.h>
#define DBUS_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"
#define UPOWER_SERVICE "org.freedesktop.UPower"
#define UPOWER_PATH "/org/freedesktop/UPower"
#define UPOWER_INTERFACE UPOWER_SERVICE
#define UPOWER_DEVICE_INTERFACE UPOWER_SERVICE ".Device"
static guint modem_watch;
static guint upower_daemon_watch;
static DBusConnection *connection;
static int last_battery_level;
static char *battery_device_path;
static void emulator_battery_cb(struct ofono_atom *atom, void *data)
{
struct ofono_emulator *em = __ofono_atom_get_data(atom);
int val = GPOINTER_TO_INT(data);
DBG("calling set_indicator: %d", val);
ofono_emulator_set_indicator(em, OFONO_EMULATOR_IND_BATTERY, val);
}
static void update_modem_battery_indicator(struct ofono_modem *modem,
void *data)
{
__ofono_modem_foreach_registered_atom(modem,
OFONO_ATOM_TYPE_EMULATOR_HFP,
emulator_battery_cb,
data);
}
static void update_battery_level(double percentage_val)
{
int battery_level;
if (percentage_val <= 1.00) {
battery_level = 0;
} else if (percentage_val > 1.00 && percentage_val <= 100.00) {
battery_level = ((int) percentage_val - 1) / 20 + 1;
} else {
ofono_error("%s: Invalid value for battery level: %f",
__func__,
percentage_val);
return;
}
DBG("last_battery_level: %d battery_level: %d (%f)", last_battery_level,
battery_level, percentage_val);
if (last_battery_level == battery_level)
return;
last_battery_level = battery_level;
__ofono_modem_foreach(update_modem_battery_indicator,
GINT_TO_POINTER(battery_level));
}
static gboolean battery_props_changed(DBusConnection *conn, DBusMessage *msg,
void *user_data)
{
const char *iface;
DBusMessageIter iter, dict;
double percentage_val;
gboolean percentage_found = FALSE;
gboolean retval = FALSE;
DBG("");
dbus_message_iter_init(msg, &iter);
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) {
ofono_error("%s: iface != TYPE_STRING!", __func__);
goto done;
}
dbus_message_iter_get_basic(&iter, &iface);
if (g_str_equal(iface, UPOWER_DEVICE_INTERFACE) != TRUE) {
ofono_error("%s: wrong iface: %s!", __func__, iface);
goto done;
}
if (!dbus_message_iter_next(&iter)) {
ofono_error("%s: advance iter failed!", __func__);
goto done;
}
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) {
ofono_error("%s: type != ARRAY!", __func__);
goto done;
}
dbus_message_iter_recurse(&iter, &dict);
while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
DBusMessageIter entry, val;
const char *key;
dbus_message_iter_recurse(&dict, &entry);
if (dbus_message_iter_get_arg_type(&entry) !=
DBUS_TYPE_STRING) {
ofono_error("%s: key type != STRING!", __func__);
goto done;
}
dbus_message_iter_get_basic(&entry, &key);
if (g_str_equal(key, "Percentage") != TRUE) {
dbus_message_iter_next(&dict);
continue;
}
dbus_message_iter_next(&entry);
if (dbus_message_iter_get_arg_type(&entry) !=
DBUS_TYPE_VARIANT) {
ofono_error("%s: 'Percentage' val != VARIANT",
__func__);
goto done;
}
dbus_message_iter_recurse(&entry, &val);
if (dbus_message_iter_get_arg_type(&val) != DBUS_TYPE_DOUBLE) {
ofono_error("%s: 'Percentage' val != DOUBLE", __func__);
goto done;
}
dbus_message_iter_get_basic(&val, &percentage_val);
percentage_found = TRUE;
break;
}
/* No errors found during parsing, so don't trigger cb removal */
retval = TRUE;
if (percentage_found == FALSE)
goto done;
update_battery_level(percentage_val);
done:
return retval;
}
static void emulator_hfp_watch(struct ofono_atom *atom,
enum ofono_atom_watch_condition cond,
void *data)
{
if (cond == OFONO_ATOM_WATCH_CONDITION_REGISTERED) {
struct ofono_emulator *em = __ofono_atom_get_data(atom);
DBG("REGISTERED; calling set_indicator: %d", last_battery_level);
ofono_emulator_set_indicator(em, OFONO_EMULATOR_IND_BATTERY,
last_battery_level);
return;
}
DBG("UNREGISTERED");
}
static void modemwatch(struct ofono_modem *modem, gboolean added, void *user)
{
const char *path = ofono_modem_get_path(modem);
DBG("modem: %s, added: %d", path, added);
if (added)
__ofono_modem_add_atom_watch(modem,
OFONO_ATOM_TYPE_EMULATOR_HFP,
emulator_hfp_watch, NULL, NULL);
}
static void call_modemwatch(struct ofono_modem *modem, void *user)
{
modemwatch(modem, TRUE, user);
}
static gboolean parse_devices_reply(DBusMessage *reply)
{
DBusMessageIter array, iter;
const char *path;
DBG("");
if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
ofono_error("%s: ERROR reply to EnumerateDevices", __func__);
return FALSE;
}
if (dbus_message_iter_init(reply, &array) == FALSE) {
ofono_error("%s: error initializing array iter", __func__);
return FALSE;
}
if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY) {
ofono_error("%s: type != ARRAY!", __func__);
return FALSE;
}
dbus_message_iter_recurse(&array, &iter);
while (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_OBJECT_PATH) {
dbus_message_iter_get_basic(&iter, &path);
if (g_strrstr(path, "/battery_")) {
ofono_info("%s: found 1st battery device: %s", __func__,
path);
battery_device_path = g_strdup(path);
break;
}
if (!dbus_message_iter_next(&iter))
break;
}
return TRUE;
}
static void enum_devices_reply(DBusPendingCall *call, void *user_data)
{
DBusMessage *reply;
DBG("");
reply = dbus_pending_call_steal_reply(call);
if (reply == NULL) {
ofono_error("%s: dbus_message_new_method failed", __func__);
goto done;
}
if (parse_devices_reply(reply) == FALSE)
goto done;
DBG("parse_devices_reply OK");
/* TODO: handle removable batteries */
if (battery_device_path == NULL) {
ofono_error("%s: no battery detected", __func__);
goto done;
}
/* Always listen to PropertiesChanged for battery */
g_dbus_add_signal_watch(connection, UPOWER_SERVICE, battery_device_path,
DBUS_INTERFACE_PROPERTIES,
"PropertiesChanged",
battery_props_changed,
NULL, NULL);
modem_watch = __ofono_modemwatch_add(modemwatch, NULL, NULL);
__ofono_modem_foreach(call_modemwatch, NULL);
done:
if (reply)
dbus_message_unref(reply);
dbus_pending_call_unref(call);
}
static void upower_connect(DBusConnection *conn, void *user_data)
{
DBusPendingCall *call;
DBusMessage *msg;
DBG("upower connect");
msg = dbus_message_new_method_call(UPOWER_SERVICE,
UPOWER_PATH,
UPOWER_INTERFACE,
"EnumerateDevices");
if (msg == NULL) {
ofono_error("%s: dbus_message_new_method failed", __func__);
return;
}
if (!dbus_connection_send_with_reply(conn, msg, &call, -1)) {
ofono_error("%s: Sending EnumerateDevices failed", __func__);
goto done;
}
dbus_pending_call_set_notify(call, enum_devices_reply, NULL, NULL);
done:
dbus_message_unref(msg);
}
static void upower_disconnect(DBusConnection *conn, void *user_data)
{
DBG("upower disconnect");
if (modem_watch) {
__ofono_modemwatch_remove(modem_watch);
modem_watch = 0;
}
if (battery_device_path) {
g_free(battery_device_path);
battery_device_path = NULL;
}
}
static int upower_init(void)
{
DBG("upower init");
connection = ofono_dbus_get_connection();
upower_daemon_watch = g_dbus_add_service_watch(connection,
UPOWER_SERVICE,
upower_connect,
upower_disconnect,
NULL, NULL);
return 0;
}
static void upower_exit(void)
{
if (upower_daemon_watch)
g_dbus_remove_watch(connection, upower_daemon_watch);
if (modem_watch)
__ofono_modemwatch_remove(modem_watch);
if (battery_device_path)
g_free(battery_device_path);
}
OFONO_PLUGIN_DEFINE(upower, "upower battery monitor", VERSION,
OFONO_PLUGIN_PRIORITY_DEFAULT, upower_init, upower_exit)

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