Compare commits

...

106 Commits

Author SHA1 Message Date
Tommi Kenakkala
44585697c3 Merge pull request #286 from tkenakka/simmgr
Register SimManager interface always and simplify logic
2015-05-06 10:06:29 +03:00
Tommi Kenakkala
07da2f3fa7 [rilmodem] Minor updates to error debug logging
Added function name prefix printing.
2015-05-05 15:52:35 +03:00
Tommi Kenakkala
7d0d72a4a9 [rilmodem] Register SimManager always and simplify logic. MER#928
Register org.ofono.SimManager always, without this the dbus
interface does not exist when starting without a SIM card.
Simplified rilmodem SIM status handling.
Moved some debug logging from sim.c to rilutil.c.
2015-05-05 15:52:35 +03:00
Tommi Kenakkala
f9ee2ae9b8 [rilmodem] Remove rilplugin sim inserted notification. MER#928
Functionality combined in rilmodem/sim.c.
No need to notify from both ril.c and sim.c.
2015-05-05 15:52:35 +03:00
Tommi Kenakkala
c006d822f1 [rilmodem] Improve rilutil debug logging
Move some logs from rilmodem/sim.c to rilmodem/rilutil.c
and do some additional improvements.
2015-04-30 16:17:12 +03:00
Tommi Kenakkala
7331c88b41 Merge pull request #285 from tkenakka/merge1.16
Merge oFono upstream release 1.16
2015-03-04 13:48:08 +02:00
Tommi Kenakkala
063eefbac1 [ofono] Disable build time he910 modem 2015-03-03 15:27:45 +02:00
Tommi Kenakkala
12b510b4e7 [ofono] Update version to 1.16 2015-03-03 15:27:38 +02:00
Tommi Kenakkala
c04f5df8ec [ofono] Merge upstream release 1.16 2015-02-27 15:56:55 +02:00
Marcel Holtmann
c9e426ecd7 Release 1.16 2014-12-13 02:56:19 +01:00
Alfonso Sanchez-Beato
10f173981c radio-settings: Show all available technologies
Not all possible futures technologies were being showed on the DBus
interface.
2014-12-12 08:54:14 -06:00
Denis Kenzior
bb71141d79 phonesim: Instantiate radio-settings in post_sim 2014-12-10 11:03:17 -06:00
Denis Kenzior
4e466f6fec phonesim: Add minimal radio-settings functionality 2014-12-10 11:03:17 -06:00
Denis Kenzior
a89f8cd56d phonesim: Add skeleton of radio settings driver 2014-12-10 11:03:16 -06:00
Denis Kenzior
95482cb84a radio-settings: Always query available rats
If fast dormancy query is not implemented the available rats are not
queried.
2014-12-10 11:03:16 -06:00
Denis Kenzior
fce95b767a radio-settings: Add additional sanity check 2014-12-10 11:03:16 -06:00
Denis Kenzior
44049f064a radio-settings: rework AvailableTechnologies logic
Take advantage of the new enum structure to future proof and simplify
the logic of generating the AvailableTechnologies property
2014-12-10 11:03:16 -06:00
Denis Kenzior
b899f4aca2 include: No need for OFONO_FLAG* defines 2014-12-10 11:03:16 -06:00
Alfonso Sanchez-Beato
e1cbc5c5ea test: Add AvailableTechnologies to list-modems 2014-12-10 11:03:16 -06:00
Alfonso Sanchez-Beato
5210b85c22 src: Implement RAT list property 2014-12-10 11:03:16 -06:00
Alfonso Sanchez-Beato
e6048f1dc1 include: Add method to list RATs to radio-settings 2014-12-10 11:03:16 -06:00
Alfonso Sanchez-Beato
6bdc109ec0 doc: Add AvailableTechnologies property
This new property in org.ofono.RadioSettings interface will hold the
possible values for radio access technology for the modem.
2014-12-09 22:29:21 -06:00
Denis Kenzior
7dca0a7315 sim: Fix pin retries bogus values on some arch-es
On some architectures the SimManager.Retries property was getting bogus
values.  This is because we were sending an array which pointed to int
values instead of the expected unsigned char values.

This fix allocates a temporary array of unsigned chars to hold the
actual D-Bus values being sent.  Additionally, the dictionary array is
changed to point to the temporary unsigned char based values instead of
the raw 'int' based retry values.
2014-12-04 08:57:48 -06:00
Neil Jerram
19519b2132 test: Support receiving SMS with non-ASCII chars
Without this I get the following Python traceback, for an SMS that
contains the UK pound sign.

ERROR:dbus.connection:Exception in handler for D-Bus signal:
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/dbus/connection.py", line 230, in maybe_handle_message
    self._handler(*args, **kwargs)
  File "./receive-sms", line 9, in incoming_message
    print("%s" % (message))
UnicodeEncodeError: 'ascii' codec can't encode character u'\xa3' in position 51: ordinal not in range(128)
2014-11-24 12:29:45 -06:00
Kuba Pawlak
42ebb69384 he910: Update copyright 2014-10-22 21:23:25 -05:00
Kuba Pawlak
45478b17cf he910: enable location raporting atom 2014-10-22 21:22:33 -05:00
Kuba Pawlak
88f46a9b01 udev: add GPS port definition for HE910 2014-10-22 21:22:24 -05:00
Denis Kenzior
2abcb85809 telitmodem: Fix a few coding style violations 2014-10-22 21:21:49 -05:00
Denis Kenzior
331700a697 AUTHORS: Mention Kuba's contributions 2014-10-22 21:21:18 -05:00
Kuba Pawlak
a753d6c012 telitmodem: location reporting driver 2014-10-22 21:15:35 -05:00
Kuba Pawlak
d39007c948 doc: new file doc/telit-modem.txt 2014-10-22 21:10:50 -05:00
Denis Kenzior
6c4ac05fbc emulator: Refine +BIND support 2014-10-20 13:40:29 -05:00
Denis Kenzior
934ea9a9fe hfp_ag_bluez5: Bump HFP version to 1.7 2014-10-20 13:40:28 -05:00
Denis Kenzior
cf90f1505d emulator_fuzz: Add test plugin
This plugin creates an org.ofono.test.EmulatorFuzz interface on path
/test.  Currently only one method is implemented, SetIndicatorActive.

SetIndicatorActive("DistractedDrivingReduction", True|False) allows to
activate / deactivate the HF indicator via +BIND unsolicited
notification.
2014-10-20 13:40:28 -05:00
Denis Kenzior
f9d5ee5fa9 emulator: Implement new API 2014-10-20 13:40:28 -05:00
Denis Kenzior
e2785b1865 include: Add API to (de)activate HF indicators 2014-10-20 13:40:28 -05:00
Denis Kenzior
fb1b213e22 test: Add test/set-ddr
Script to set DistractedDrivingReduction property
2014-10-20 13:40:28 -05:00
Denis Kenzior
d3560b3784 handsfree: Be extra pedantic with booleans 2014-10-20 13:40:28 -05:00
Denis Kenzior
017c1161d4 hfp_hf_bluez5: Use latest HFP version 2014-10-20 13:40:28 -05:00
Denis Kenzior
de02f68a2e handsfree: Don't try to send a method return
When we are simply updating the AG of HF indicator changes, do not try
to send a method return message.
2014-10-20 13:40:28 -05:00
Denis Kenzior
0f28d9206d slc: Make sure to initialize variables 2014-10-20 13:40:28 -05:00
Denis Kenzior
eef67018b6 hfp: Implement +BIND notifications 2014-10-20 13:40:28 -05:00
Denis Kenzior
299ffc9620 hfp: Notify core of HF indicators supported by AG
This information was obtained from SLC negotiation
2014-10-20 13:40:28 -05:00
Denis Kenzior
39f08a5e1c hfp: Track supported / active indicators
This information is obtained during SLC establishment
2014-10-20 13:40:28 -05:00
Denis Kenzior
6c0f90fc1b handsfree: Implement new HF indicators API 2014-10-20 13:40:28 -05:00
Denis Kenzior
33537adb9f include: Add HF Indicators related API 2014-10-20 13:40:28 -05:00
Denis Kenzior
e176a9019f hfp: Add implementation of +BIEV 2014-10-20 13:40:28 -05:00
Denis Kenzior
7166aebd51 emulator: Refactor data types 2014-10-20 13:40:28 -05:00
Denis Kenzior
debb0d2d3e hfp: Add HF Indicators BRSF feature for 1.7
If HFP 1.7 client is used, enable the right BRSF feature
2014-10-20 13:40:28 -05:00
Denis Kenzior
ab5b6d1217 handsfree: Skeleton implementation of DDR
Distracted Driving Reduction or Enhanced Safety is implemented using HF
indicator 0x0001
2014-10-20 13:40:28 -05:00
Denis Kenzior
7e3a6628fa handsfree: Add new driver method for HF indicators 2014-10-20 13:40:28 -05:00
Denis Kenzior
fa105c4ba6 hfp: Add initial SLC negotiation for HFP 1.7 2014-10-20 13:40:28 -05:00
Denis Kenzior
99c03292ad doc: Add Distracted Driving Reduction to Handsfree 2014-10-20 13:40:28 -05:00
Denis Kenzior
66cf2a30fa handsfree: Implement new Features property value 2014-10-20 13:40:28 -05:00
Denis Kenzior
a4fa356b16 doc: Add 'hf-indicators' feature to Handsfree API 2014-10-20 13:40:28 -05:00
Denis Kenzior
43e83852dc emulator: Enable HF Indicator feature 2014-10-20 13:40:28 -05:00
Denis Kenzior
36a21da227 emulator: Extend BRSF bitmap
The current check of 8 bits is not enough with HFP 1.7
2014-10-20 13:40:28 -05:00
Denis Kenzior
bef4d610a3 emulator: Add +BIEV implementation 2014-10-20 13:40:28 -05:00
Denis Kenzior
2d158167c2 emulator: Add +BIND implementation 2014-10-20 13:40:27 -05:00
Denis Kenzior
02c5b73f6e emulator: Fix CHLD=? not treated as part of SLC 2014-10-20 13:40:27 -05:00
Denis Kenzior
0727da1d5b emulator: Improve SLC establishment logic 2014-10-20 13:40:27 -05:00
Denis Kenzior
d292e0e0ed hfp: Add enum for known HF Indicators 2014-10-20 13:40:27 -05:00
Denis Kenzior
881207ce18 hfp: Update for new HFP 1.7 values 2014-10-20 13:40:27 -05:00
Denis Kenzior
0f0733c348 doc: Fixup Handsfree API 2014-10-20 13:40:27 -05:00
Marcel Holtmann
8ebb17977b handsfree-audio: Fix broken coding style in switch statement 2014-09-20 16:13:45 +02:00
Alban Crequy
7fb4899970 gdbus: Fix match rule for NameOwnerChanged
When subscribing to the D-Bus signal NameOwnerChanged from the bus driver,
specify the object path and the sender in the match rule. Otherwise, random
connections on the bus could impersonate the bus driver.
2014-09-15 18:03:46 +02:00
Luiz Augusto von Dentz
1e0c41889f gdbus: Fix crash when watch is toggled or disconnected
This partially reverts 510b32b7156625b9df737c916b7a7a5c6fb285b9 since it
still necessary to take a reference before calling dbus_watch_handle
since internally it can call watch_info_free as in the following trace:

 Invalid read of size 8
   at 0x121085: watch_func (mainloop.c:105)
   by 0x4C72694: g_main_context_dispatch (gmain.c:2539)
   by 0x4C729C7: g_main_context_iterate.isra.23 (gmain.c:3146)
   by 0x4C72DC1: g_main_loop_run (gmain.c:3340)
   by 0x120541: main (main.c:551)
 Address 0x5bbcd90 is 16 bytes inside a block of size 24 free'd
   at 0x4A079AE: free (vg_replace_malloc.c:427)
   by 0x4C7837E: g_free (gmem.c:252)
   by 0x4F708BF: dbus_watch_set_data (dbus-watch.c:614)
   by 0x4F70938: _dbus_watch_unref (dbus-watch.c:132)
   by 0x4F6E9A7: _dbus_transport_handle_watch (dbus-transport.c:884)
   by 0x4F59AFB: _dbus_connection_handle_watch (dbus-connection.c:1497)
   by 0x4F70AF9: dbus_watch_handle (dbus-watch.c:683)
   by 0x121084: watch_func (mainloop.c:103)
   by 0x4C72694: g_main_context_dispatch (gmain.c:2539)
   by 0x4C729C7: g_main_context_iterate.isra.23 (gmain.c:3146)
   by 0x4C72DC1: g_main_loop_run (gmain.c:3340)
   by 0x120541: main (main.c:551)
2014-09-08 05:48:48 +02:00
Luiz Augusto von Dentz
08e673050a gdbus: Fix crash when calling g_dbus_add_service_watch
If g_dbus_add_service_watch is called for service which bus name is
already known the following crash can happen:

invalid read of size 1
  at 0x4C2A2F2: strlen (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
  by 0x4E97722: g_strdup (in /usr/lib64/libglib-2.0.so.0.3800.2)
  by 0x405B0C: update_name_cache (watch.c:435)
  by 0x405C37: update_service (watch.c:593)
  by 0x4E7A2A5: g_main_context_dispatch (in /usr/lib64/libglib-2.0.so.0.3800.2)
  by 0x4E7A627: ??? (in /usr/lib64/libglib-2.0.so.0.3800.2)
  by 0x4E7AA39: g_main_loop_run (in /usr/lib64/libglib-2.0.so.0.3800.2)
  by 0x4038EA: client_ready (test-gdbus-client.c:1014)
  by 0x4E9E5E0: ??? (in /usr/lib64/libglib-2.0.so.0.3800.2)
  by 0x4E9E7A5: ??? (in /usr/lib64/libglib-2.0.so.0.3800.2)
  by 0x4E9EB1A: g_test_run_suite (in /usr/lib64/libglib-2.0.so.0.3800.2)
  by 0x403614: main (test-gdbus-client.c:1058)
Address 0x5dbe5d0 is 0 bytes inside a block of size 7 free'd
  at 0x4C28577: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
  by 0x4E7FF7E: g_free (in /usr/lib64/libglib-2.0.so.0.3800.2)
  by 0x405B04: update_name_cache (watch.c:434)
  by 0x405C37: update_service (watch.c:593)
  by 0x4E7A2A5: g_main_context_dispatch (in /usr/lib64/libglib-2.0.so.0.3800.2)
  by 0x4E7A627: ??? (in /usr/lib64/libglib-2.0.so.0.3800.2)
  by 0x4E7AA39: g_main_loop_run (in /usr/lib64/libglib-2.0.so.0.3800.2)
  by 0x4038EA: client_ready (test-gdbus-client.c:1014)
  by 0x4E9E5E0: ??? (in /usr/lib64/libglib-2.0.so.0.3800.2)
  by 0x4E9E7A5: ??? (in /usr/lib64/libglib-2.0.so.0.3800.2)
  by 0x4E9EB1A: g_test_run_suite (in /usr/lib64/libglib-2.0.so.0.3800.2)
  by 0x403614: main (test-gdbus-client.c:1058)
2014-09-08 05:48:48 +02:00
Luiz Augusto von Dentz
1b1b1861ab Revert "gdbus: Don't include just added interfaces in GetManagedObjects"
This actually creates a problem since the code now does flush any pending
message on the queue any signal will be send right away before the
actual reply to GetManagedObjects which will not contain those interfaces.
2014-09-08 05:48:48 +02:00
Andrei Emeltchenko
8a4c29ca74 gdbus: Fix use after free
Refactor filter_data_remove_callback so that we do not iterate over
freed pointer.
2014-09-08 05:48:48 +02:00
Claudio Takahasi
9aeea028ed gdbus: Avoid reporting GDBusClient disconnect twice
No matter if disconnection was reported previously, g_dbus_client_unref()
was always calling service disconnect callback. This patch fix the
following scenario:
1) service disconnects from the bus
2) disconnect callback gets called
3) client calls g_dbus_client_unref(), disconnect callback is called
   again.
2014-09-08 05:48:48 +02:00
Denis Kenzior
22e892a22e build: Avoid warnings about _FORTIFY_SOURCE
Gentoo (and others) define _FORTIFY_SOURCE=2 by default.  We redefine
it, resulting in an error / configure failure.
2014-08-01 09:29:40 -05:00
Denis Kenzior
361eed7b9a ublox: Minor style cleanup 2014-07-08 08:58:48 -05:00
Denis Kenzior
864efe1add ublox: Remove unneeded VENDOR flags
devinfo and netreg atoms don't use vendor specific behavior
2014-07-08 08:56:55 -05:00
Philip Paeps
0d8a06af30 plugins: new driver for u-blox SARA-U270 modems
This driver may also work (perhaps with more or less trivial changes)
with other u-blox modems (SARA, LISA, LEON) but this hasn't been tested.
2014-07-08 08:53:13 -05:00
Philip Paeps
293c701e25 atmodem: set the auth method for u-blox modems 2014-07-08 08:52:25 -05:00
Philip Paeps
cca3e085b3 sim: query u-blox PIN retries with AT+UPINCNT 2014-07-08 08:51:54 -05:00
Philip Paeps
7f29608feb udevng: add detection logic for u-blox modems 2014-07-08 08:50:20 -05:00
Denis Kenzior
1f3e30f1ba quectel: Minor style cleanup 2014-07-08 08:44:21 -05:00
Denis Kenzior
7ab4034bf4 quectel: Remove unneeded VENDOR flags
Only the sim atom has QUECTEL specific code
2014-07-08 08:43:01 -05:00
Philip Paeps
bb1984cabb plugins: add a new driver for Quectel UC15 modems 2014-07-08 08:42:05 -05:00
Philip Paeps
6df64cd1a9 gprs: add support for u-blox +UREG URCs 2014-06-30 14:03:08 -05:00
Philip Paeps
4a0831bc80 atmodem: add vendor u-blox 2014-06-30 13:59:46 -05:00
Denis Kenzior
b2bfdd69d2 atmodem: Minor style fixups 2014-06-30 13:44:40 -05:00
Philip Paeps
1588e7c082 sim: query Quectel UC15 PIN retries with AT+QPINC? 2014-06-30 13:35:19 -05:00
Philip Paeps
5cffd8af95 udevng: add detection logic for Quectel modems 2014-06-30 13:26:51 -05:00
Philip Paeps
d2f6ffc18d atmodem: add vendor Quectel 2014-06-30 13:26:25 -05:00
Sergio Checa Blanco
6369cc902c hfpmodem: Fix crash with more than two calls
A periodic CLCC polling is started when there is an ongoing multiparty
call and a new call appears in the system. A simple way to reproduce
the crashing scenario is:

1. Place a call.
2. Place a second call.
3. Create a multiparty call with both calls.
4. Place a third call (incoming or outgoing does not matter).
5. Disconnect HFP from the modem.

Within the function ciev_callheld_notify, the AT+CLCC command is also
invoked, thus a new cyclic CLCC polling is started, and it overwrites
the timer resource identifier stored in voicecall_data.clcc_source.
This means that there are several timers doing the CLCC polling, but
only one of those is under control, i.e. it can be removed through its
source identifier, hence a timer source leak.

This has a fatal consequence when the HFP modem is disconnected. The
function hfp_voicecall_remove stops the timer that is under control
before freeing the voicecall_data struct. However there are other timers
that are still active and will execute its handler poll_clcc afterwards.
Inside poll_clcc the driver_data is accessed, which is already NULL.

A solution for this is to avoid starting a CLCC polling if there is
already one active, i.e. clcc_source is not 0. By doing this the
uncontrolled timers will not cycle forever.
2014-06-30 13:22:10 -05:00
Marcel Holtmann
d05b718cc0 Release 1.15 2014-06-29 22:20:08 +02:00
Philip Paeps
c144fadca6 gprs: provision the authentication method 2014-06-24 12:46:18 -05:00
Philip Paeps
532e8020e5 mbpi: add support for provisioning the auth method
Use the authentication method from the mobile-broadband-provider-info
database if it is specified and supported (we support CHAP and PAP).
Default to CHAP if the database does not specify a method (i.e.: the
previous behaviour).
2014-06-24 12:46:18 -05:00
Philip Paeps
310915429b include: add auth method to the provisioning API 2014-06-24 12:46:18 -05:00
Denis Kenzior
9285ec0d89 AUTHORS: Mention Philip's contributions 2014-06-21 12:05:43 -05:00
Philip Paeps
8cbe061c3b atmodem: set the PPP authentication method to use 2014-06-21 12:02:51 -05:00
Denis Kenzior
3e13676766 gprs: Make the code a bit easier to read 2014-06-21 12:02:05 -05:00
Philip Paeps
73831c3d76 gprs: make PPP authentication method configurable
Add a new "AuthenticationMethod" property to select between "pap"
and "chap" PPP authentication, defaulting to "chap" (i.e.: previous
behaviour).
2014-06-21 11:58:03 -05:00
Philip Paeps
7011dcdf2f include: add auth method to the gprs context API 2014-06-21 11:55:30 -05:00
Philip Paeps
f6341502c8 doc: describe the AuthenticationMethod property 2014-06-21 11:55:03 -05:00
Denis Kenzior
8edaaaf210 gatchat: Fix up minor coding style issues 2014-06-21 11:54:26 -05:00
Philip Paeps
a88662d23c gatchat: implement PAP authentication
Make the authentication method configurable, CHAP or PAP, defaulting to
CHAP (i.e.: previous behaviour).

Implementation details:

 o If PAP is configured, we NAK the CHAP authentication protocol option
   in LCP configuration requests and suggest PAP instead.  This works
   around the amusing requirement of 3GPP TS 29.061 that modems must
   send a forced positive acknowledgement of the authentication method
   tried (i.e.: the modem will successfully accept any CHAP handshake,
   but if the network only supports PAP, the modem will hang up
   when it tries and fails to activate the PDP context)

 o The PAP Authenticate-Request is resent a hard-coded three times at
   ten-second intervals.  This may be a bit too persistent.  Chances
   are if it doesn't work the first time, it'll never work, but the
   RFC insists that we MUST retry.
2014-06-21 11:50:34 -05:00
Denis Kenzior
1dd8580930 AUTHORS: Mention Sergio's contributions 2014-06-21 11:46:28 -05:00
Sergio Checa Blanco
65be2b344c hfpmodem: Split AT+VTS command into multiple +VTS
According to the standard "3GPP 27.007 v6.8.0" Appendix C.2.11,
when sending multiple DTMF characters, these must go in individual
+VTS commands for each tone. This adopts the AT modem approach.

Before: AT+VTS=1234\r
After:  AT+VTS=1;+VTS=2;+VTS=3;+VTS=4\r
2014-06-21 11:45:44 -05:00
Alfonso Sanchez-Beato
62c34467a2 test: Adapt data test scripts to multi-modem
Some tests scripts were not ready to handle situations with more than
one modem present. This change fixes the data context scripts.
2014-06-10 23:36:09 -05:00
Alfonso Sanchez-Beato
d9f252fb61 test: Adapt voice call test scripts to multi-modem
Some tests scripts were not ready to handle situations with more than
one modem present. This change fixes the scripts that handle voice
calls.
2014-06-10 23:23:51 -05:00
Denis Kenzior
815d62888f hfp: Fix case where RING never arrives 2014-05-30 12:25:23 -05:00
Denis Kenzior
35feae07e5 hfp: Use proper prefix
Otherwise the BCS command can consume unsolicited notifications.

ofonod[3270]: < \r\n+BCS: 2\r\n
ofonod[3270]: > AT+BCS=2\r
ofonod[3270]: < \r\n+CIEV: 1,1\r\n
ofonod[3270]: < \r\n+CIEV: 2,0\r\n
ofonod[3270]: < \r\nOK\r\n
2014-05-21 12:08:37 -05:00
67 changed files with 2963 additions and 267 deletions

View File

@@ -96,3 +96,6 @@ Tony Espy <espy@canonical.com>
Martin Pitt <martin.pitt@ubuntu.com>
Alfonso Sanchez-Beato <alfonso.sanchez-beato@canonical.com>
Jussi Pakkanen <jussi.pakkanen@canonical.com>
Sergio Checa Blanco <sergio.checa@bmw-carit.de>
Philip Paeps <philip@paeps.cx>
Kuba Pawlak <kubax.t.pawlak@intel.com>

View File

@@ -1,3 +1,23 @@
ver 1.16:
Fix issue with PIN retry handling.
Fix issue with HFP and multiple calls.
Add support for Distracted Driving Reduction.
Add support for available technologies property.
Add support for Telit location reporting driver.
Add support for u-blox SARA-U270 modems.
Add support for Quectel UC15 modems.
ver 1.15:
Fix issue with EF_PNN access affecting PLMN display.
Fix issue with SIM detection and Telit HE910 modems.
Fix issue with Mobile Provider Database provisioning.
Fix issue with bit-shifting and ID mapping allocations.
Fix issue with Handsfree and unsolicited notifications.
Fix issue with Handsfree and three way calling feature.
Add support for Handsfree subscriber number feature.
Add support for Handsfree multiple DTMF characters.
Add support for PAP authentication.
ver 1.14:
Add support for Apple Siri specific Handsfree commands.
Add support for provisioning of MMSC and Message Proxy.

View File

@@ -21,8 +21,9 @@ pkginclude_HEADERS = include/log.h include/plugin.h include/history.h \
include/cdma-connman.h include/gnss.h \
include/private-network.h include/cdma-netreg.h \
include/cdma-provision.h include/handsfree.h \
include/handsfree-audio.h include/sim-mnclength.h \
include/oemraw.h include/siri.h
include/handsfree-audio.h \
include/sim-mnclength.h include/oemraw.h \
include/siri.h
nodist_pkginclude_HEADERS = include/version.h
@@ -312,6 +313,12 @@ builtin_sources += drivers/atmodem/atutil.h \
drivers/mbmmodem/stk.c \
drivers/mbmmodem/location-reporting.c
builtin_modules += telitmodem
builtin_sources += drivers/atmodem/atutil.h \
drivers/telitmodem/telitmodem.h \
drivers/telitmodem/telitmodem.c \
drivers/telitmodem/location-reporting.c
builtin_modules += hsomodem
builtin_sources += drivers/atmodem/atutil.h \
drivers/hsomodem/hsomodem.h \
@@ -461,14 +468,20 @@ builtin_sources += plugins/samsung.c
builtin_modules += sim900
builtin_sources += plugins/sim900.c
builtin_modules += quectel
builtin_sources += plugins/quectel.c
builtin_modules += ublox
builtin_sources += plugins/ublox.c
builtin_modules += he910
builtin_sources += plugins/he910.c
endif
builtin_modules += connman
builtin_sources += plugins/connman.c
builtin_modules += he910
builtin_sources += plugins/he910.c
if BLUETOOTH
if BLUEZ4
builtin_modules += bluez4
@@ -544,6 +557,9 @@ builtin_sources += examples/private-network.c
builtin_modules += stktest
builtin_sources += plugins/stktest.c
builtin_modules += emulator_fuzz
builtin_sources += plugins/emulator_fuzz.c
endif
builtin_modules += smart_messaging
@@ -589,8 +605,8 @@ src_ofonod_SOURCES = $(builtin_sources) src/ofono.ver \
src/cdma-sms.c src/private-network.c src/cdma-netreg.c \
src/cdma-provision.c src/handsfree.c \
src/handsfree-audio.c src/bluetooth.h \
src/hfp.h src/sim-mnclength.c src/oemraw.c \
src/siri.c src/voicecallagent.c
src/sim-mnclength.c src/oemraw.c src/voicecallagent.c \
src/hfp.h src/siri.c
src_ofonod_LDADD = gdbus/libgdbus-internal.la $(builtin_libadd) \
@GLIB_LIBS@ @DBUS_LIBS@ -ldl
@@ -633,9 +649,10 @@ doc_files = doc/overview.txt doc/ofono-paper.txt doc/release-faq.txt \
doc/sim-api.txt doc/stk-api.txt \
doc/audio-settings-api.txt doc/text-telephony-api.txt \
doc/calypso-modem.txt doc/message-api.txt \
doc/location-reporting-api.txt doc/smshistory-api.txt \
doc/oemraw-api.txt \
doc/certification.txt doc/siri-api.txt
doc/location-reporting-api.txt \
doc/smshistory-api.txt doc/oemraw-api.txt \
doc/certification.txt doc/siri-api.txt \
doc/telit-modem.txt
test_scripts = test/backtrace \
@@ -732,7 +749,8 @@ test_scripts = test/backtrace \
test/display-icon \
test/set-msisdn \
test/test-voicecallagent \
test/get-network-time
test/get-network-time \
test/set-ddr
if TEST
testdir = $(pkglibdir)/test

View File

@@ -12,7 +12,7 @@ AC_DEFUN([AC_PROG_CC_PIE], [
AC_DEFUN([COMPILER_FLAGS], [
if (test "${CFLAGS}" = ""); then
CFLAGS="-Wall -O2 -D_FORTIFY_SOURCE=2"
CFLAGS="-Wall -O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2"
fi
if (test "$USE_MAINTAINER_MODE" = "yes"); then
CFLAGS="$CFLAGS -Werror -Wextra"

View File

@@ -1,5 +1,5 @@
AC_PREREQ(2.60)
AC_INIT(ofono, 1.14)
AC_INIT(ofono, 1.16)
AM_INIT_AUTOMAKE([foreign subdir-objects color-tests])
AC_CONFIG_HEADERS(config.h)

View File

@@ -189,6 +189,10 @@ Properties boolean Active [readwrite]
"wap" - Used by WAP related services
"ims" - Used by IMS related services
string AuthenticationMethod [readwrite]
Holds the PPP authentication method to use. Valid
values are "pap" and "chap". Defaults to "chap".
string Username [readwrite]
Holds the username to be used for authentication

View File

@@ -19,6 +19,8 @@ Methods dict GetProperties()
Possible Errors: [service].Error.InProgress
[service].Error.InvalidArguments
[service].Error.NotImplemented
[service].Error.NotSupported
string RequestPhoneNumber()
@@ -51,6 +53,7 @@ Properties array{string} Features [readonly]
"private-chat"
"create-multiparty"
"transfer"
"hf-indicators"
boolean InbandRinging [readonly]
@@ -63,7 +66,7 @@ Properties array{string} Features [readonly]
to activate or deactivate the function from the HF, or
the AG could autonomously initiate it.
boolean EchoCancelingNoiseReduction [readwrite]
boolean EchoCancelingNoiseReduction [readwrite, optional]
Non-persistent Boolean property representing whether
echo canceling and noise reduction is enabled in the
@@ -80,3 +83,10 @@ Properties array{string} Features [readonly]
array{string} SubscriberNumbers [readonly]
List of subscriber numbers provided by the AG.
boolean DistractedDrivingReduction [readwrite, optional]
Non-persistent property representing whether
distracted driving reduction mode should be enabled in
the AG. Support for this feature is optional on the
AG.

View File

@@ -45,6 +45,11 @@ Properties string TechnologyPreference [readwrite]
"umts" Only UMTS used for radio access.
"lte" Only LTE used for radio access.
array{string} AvailableTechnologies [readonly, optional]
List of values for TechnologyPreference property
supported by the modem.
string GsmBand [readwrite, optional]
Frequency band in which the modem is allowed to

19
ofono/doc/telit-modem.txt Normal file
View File

@@ -0,0 +1,19 @@
oFono - Open Source Telephony
*****************************
Purpose
=======
The purpose of this document is to identify issues and configuration
requirements with Telit's modems.
HE910
=====
GPS:
To enable location reporting on the Telit HE910 the modem needs to be
switched to Port Configuration #8. Please refer to Telit's
'HE910 UE910 Family Ports Arrangements' section 4.1.3 for rationale and
'AT Commands Reference Guide' section 3.5.7.1.96 for specific AT command.
After setting the configuration, a power cycle is required.
Port Configiuration #8 is available since firmware 12.00.004. Firmware version
can be checked using 'AT+CGMR'.

View File

@@ -59,6 +59,7 @@ enum state {
struct gprs_context_data {
GAtChat *chat;
unsigned int active_context;
GAtPPPAuthMethod auth_method;
char username[OFONO_GPRS_MAX_USERNAME_LENGTH + 1];
char password[OFONO_GPRS_MAX_PASSWORD_LENGTH + 1];
GAtPPP *ppp;
@@ -154,6 +155,7 @@ static gboolean setup_ppp(struct ofono_gprs_context *gc)
if (getenv("OFONO_PPP_DEBUG"))
g_at_ppp_set_debug(gcd->ppp, ppp_debug, "PPP");
g_at_ppp_set_auth_method(gcd->ppp, gcd->auth_method);
g_at_ppp_set_credentials(gcd->ppp, gcd->username, gcd->password);
/* set connect and disconnect callbacks */
@@ -243,6 +245,18 @@ static void at_gprs_activate_primary(struct ofono_gprs_context *gc,
memcpy(gcd->username, ctx->username, sizeof(ctx->username));
memcpy(gcd->password, ctx->password, sizeof(ctx->password));
/* We only support CHAP and PAP */
switch (ctx->auth_method) {
case OFONO_GPRS_AUTH_METHOD_CHAP:
gcd->auth_method = G_AT_PPP_AUTH_METHOD_CHAP;
break;
case OFONO_GPRS_AUTH_METHOD_PAP:
gcd->auth_method = G_AT_PPP_AUTH_METHOD_PAP;
break;
default:
goto error;
}
gcd->state = STATE_ENABLING;
if (gcd->vendor == OFONO_VENDOR_ZTE) {
@@ -268,9 +282,34 @@ static void at_gprs_activate_primary(struct ofono_gprs_context *gc,
len = snprintf(buf, sizeof(buf), "AT+CGDCONT=%u,\"IP\"", ctx->cid);
if (ctx->apn)
snprintf(buf + len, sizeof(buf) - len - 3, ",\"%s\"",
ctx->apn);
if (ctx->apn) {
switch (gcd->vendor) {
case OFONO_VENDOR_UBLOX:
/*
* U-blox modems require a magic prefix to the APN to
* specify the authentication method to use in the
* network. See UBX-13002752 - R21.
*
* As the response of the read command omits this magic
* prefix, this is the least invasive place to set it.
*/
switch (ctx->auth_method) {
case OFONO_GPRS_AUTH_METHOD_CHAP:
snprintf(buf + len, sizeof(buf) - len - 3,
",\"CHAP:%s\"", ctx->apn);
break;
case OFONO_GPRS_AUTH_METHOD_PAP:
snprintf(buf + len, sizeof(buf) - len - 3,
",\"PAP:%s\"", ctx->apn);
break;
}
break;
default:
snprintf(buf + len, sizeof(buf) - len - 3, ",\"%s\"",
ctx->apn);
break;
}
}
if (g_at_chat_send(gcd->chat, buf, none_prefix,
at_cgdcont_cb, gc, NULL) > 0)

View File

@@ -282,6 +282,44 @@ static void telit_mode_notify(GAtResult *result, gpointer user_data)
ofono_gprs_bearer_notify(gprs, bearer);
}
static void ublox_ureg_notify(GAtResult *result, gpointer user_data)
{
struct ofono_gprs *gprs = user_data;
GAtResultIter iter;
gint state, bearer;
g_at_result_iter_init(&iter, result);
if (!g_at_result_iter_next(&iter, "+UREG:"))
return;
if (!g_at_result_iter_next_number(&iter, &state))
return;
switch (state) {
case 4:
bearer = 5;
break;
case 5:
bearer = 4;
break;
case 7:
/* XXX: reserved - assume none. */
bearer = 0;
break;
case 8:
bearer = 1;
break;
case 9:
bearer = 2;
break;
default:
bearer = state;
}
ofono_gprs_bearer_notify(gprs, bearer);
}
static void cpsb_notify(GAtResult *result, gpointer user_data)
{
struct ofono_gprs *gprs = user_data;
@@ -316,6 +354,12 @@ static void gprs_initialized(gboolean ok, GAtResult *result, gpointer user_data)
g_at_chat_register(gd->chat, "^MODE:", huawei_mode_notify,
FALSE, gprs, NULL);
break;
case OFONO_VENDOR_UBLOX:
g_at_chat_register(gd->chat, "+UREG:", ublox_ureg_notify,
FALSE, gprs, NULL);
g_at_chat_send(gd->chat, "AT+UREG=1", none_prefix,
NULL, NULL, NULL);
break;
case OFONO_VENDOR_TELIT:
g_at_chat_register(gd->chat, "#PSNT:", telit_mode_notify,
FALSE, gprs, NULL);

View File

@@ -67,6 +67,8 @@ static const char *epin_prefix[] = { "*EPIN:", NULL };
static const char *spic_prefix[] = { "+SPIC:", NULL };
static const char *pct_prefix[] = { "#PCT:", NULL };
static const char *pnnm_prefix[] = { "+PNNM:", NULL };
static const char *qpinc_prefix[] = { "+QPINC:", NULL };
static const char *upincnt_prefix[] = { "+UPINCNT:", NULL };
static const char *none_prefix[] = { NULL };
static void at_crsm_info_cb(gboolean ok, GAtResult *result, gpointer user_data)
@@ -967,6 +969,90 @@ error:
CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
}
static void at_qpinc_cb(gboolean ok, GAtResult *result, gpointer user_data)
{
struct cb_data *cbd = user_data;
ofono_sim_pin_retries_cb_t cb = cbd->cb;
const char *final = g_at_result_final_response(result);
GAtResultIter iter;
struct ofono_error error;
int retries[OFONO_SIM_PASSWORD_INVALID];
size_t i;
decode_at_error(&error, final);
if (!ok) {
cb(&error, NULL, cbd->data);
return;
}
for (i = 0; i < OFONO_SIM_PASSWORD_INVALID; i++)
retries[i] = -1;
g_at_result_iter_init(&iter, result);
while (g_at_result_iter_next(&iter, "+QPINC:")) {
const char *name;
int pin, puk;
if (!g_at_result_iter_next_string(&iter, &name))
continue;
if (!g_at_result_iter_next_number(&iter, &pin))
continue;
if (!g_at_result_iter_next_number(&iter, &puk))
continue;
if (!strcmp(name, "SC")) {
retries[OFONO_SIM_PASSWORD_SIM_PIN] = pin;
retries[OFONO_SIM_PASSWORD_SIM_PUK] = puk;
} else if (!strcmp(name, "P2")) {
retries[OFONO_SIM_PASSWORD_SIM_PIN2] = pin;
retries[OFONO_SIM_PASSWORD_SIM_PUK2] = puk;
}
}
cb(&error, retries, cbd->data);
}
static void upincnt_cb(gboolean ok, GAtResult *result, gpointer user_data)
{
struct cb_data *cbd = user_data;
ofono_sim_pin_retries_cb_t cb = cbd->cb;
const char *final = g_at_result_final_response(result);
GAtResultIter iter;
struct ofono_error error;
int retries[OFONO_SIM_PASSWORD_INVALID];
size_t i;
static enum ofono_sim_password_type password_types[] = {
OFONO_SIM_PASSWORD_SIM_PIN,
OFONO_SIM_PASSWORD_SIM_PIN2,
OFONO_SIM_PASSWORD_SIM_PUK,
OFONO_SIM_PASSWORD_SIM_PUK2,
};
decode_at_error(&error, final);
if (!ok) {
cb(&error, NULL, cbd->data);
return;
}
g_at_result_iter_init(&iter, result);
if (!g_at_result_iter_next(&iter, "+UPINCNT:"))
goto error;
BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
retries);
cb(&error, retries, cbd->data);
return;
error:
CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
}
static void at_pin_retries_query(struct ofono_sim *sim,
ofono_sim_pin_retries_cb_t cb,
void *data)
@@ -1028,6 +1114,16 @@ static void at_pin_retries_query(struct ofono_sim *sim,
at_pnnm_cb, cbd, g_free) > 0)
return;
break;
case OFONO_VENDOR_QUECTEL:
if (g_at_chat_send(sd->chat, "AT+QPINC?", qpinc_prefix,
at_qpinc_cb, cbd, g_free) > 0)
return;
break;
case OFONO_VENDOR_UBLOX:
if (g_at_chat_send(sd->chat, "AT+UPINCNT", upincnt_prefix,
upincnt_cb, cbd, g_free) > 0)
return;
break;
default:
if (g_at_chat_send(sd->chat, "AT+CPINR", cpinr_prefixes,
at_cpinr_cb, cbd, g_free) > 0)

View File

@@ -42,5 +42,7 @@ enum ofono_vendor {
OFONO_VENDOR_SIMCOM_SIM900,
OFONO_VENDOR_ICERA,
OFONO_VENDOR_WAVECOM_Q2XXX,
OFONO_VENDOR_ALCATEL
OFONO_VENDOR_ALCATEL,
OFONO_VENDOR_QUECTEL,
OFONO_VENDOR_UBLOX,
};

View File

@@ -206,6 +206,27 @@ static void hfp_cnum_query(struct ofono_handsfree *hf,
CALLBACK_WITH_FAILURE(cb, -1, NULL, data);
}
static void bind_notify(GAtResult *result, gpointer user_data)
{
struct ofono_handsfree *hf = user_data;
int hf_indicator;
int active;
GAtResultIter iter;
g_at_result_iter_init(&iter, result);
if (!g_at_result_iter_next(&iter, "+BIND:"))
return;
if (!g_at_result_iter_next_number(&iter, &hf_indicator))
return;
if (!g_at_result_iter_next_number(&iter, &active))
return;
ofono_handsfree_hf_indicator_active_notify(hf, hf_indicator, active);
}
static gboolean hfp_handsfree_register(gpointer user_data)
{
struct ofono_handsfree *hf = user_data;
@@ -216,6 +237,7 @@ static gboolean hfp_handsfree_register(gpointer user_data)
g_at_chat_register(hd->chat, "+BSIR:", bsir_notify, FALSE, hf, NULL);
g_at_chat_register(hd->chat, "+BVRA:", bvra_notify, FALSE, hf, NULL);
g_at_chat_register(hd->chat, "+CIEV:", ciev_notify, FALSE, hf, NULL);
g_at_chat_register(hd->chat, "+BIND:", bind_notify, FALSE, hf, NULL);
if (hd->ag_features & HFP_AG_FEATURE_IN_BAND_RING_TONE)
ofono_handsfree_set_inband_ringing(hf, TRUE);
@@ -232,6 +254,7 @@ static int hfp_handsfree_probe(struct ofono_handsfree *hf,
{
struct hfp_slc_info *info = data;
struct hf_data *hd;
unsigned int i;
DBG("");
hd = g_new0(struct hf_data, 1);
@@ -245,6 +268,14 @@ static int hfp_handsfree_probe(struct ofono_handsfree *hf,
ofono_handsfree_battchg_notify(hf,
info->cind_val[HFP_INDICATOR_BATTCHG]);
ofono_handsfree_set_hf_indicators(hf, info->hf_indicators,
info->num_hf_indicators);
for (i = 0; i < info->num_hf_indicators; i++)
ofono_handsfree_hf_indicator_active_notify(hf,
info->hf_indicators[i],
info->hf_indicator_active_map & (1 << i));
hd->register_source = g_idle_add(hfp_handsfree_register, hf);
return 0;
@@ -360,6 +391,25 @@ static void hfp_disable_nrec(struct ofono_handsfree *hf,
CALLBACK_WITH_FAILURE(cb, data);
}
static void hfp_hf_indicator(struct ofono_handsfree *hf,
unsigned short indicator, unsigned int value,
ofono_handsfree_cb_t cb, void *data)
{
struct hf_data *hd = ofono_handsfree_get_data(hf);
struct cb_data *cbd = cb_data_new(cb, data);
char buf[128];
snprintf(buf, sizeof(buf), "AT+BIEV=%u,%u", indicator, value);
if (g_at_chat_send(hd->chat, buf, NULL, hf_generic_set_cb,
cbd, g_free) > 0)
return;
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, data);
}
static struct ofono_handsfree_driver driver = {
.name = "hfpmodem",
.probe = hfp_handsfree_probe,
@@ -368,6 +418,7 @@ static struct ofono_handsfree_driver driver = {
.request_phone_number = hfp_request_phone_number,
.voice_recognition = hfp_voice_recognition,
.disable_nrec = hfp_disable_nrec,
.hf_indicator = hfp_hf_indicator,
};
void hfp_handsfree_init(void)

View File

@@ -41,10 +41,12 @@
#include "hfp.h"
#include "slc.h"
static const char *none_prefix[] = { NULL };
static const char *brsf_prefix[] = { "+BRSF:", NULL };
static const char *cind_prefix[] = { "+CIND:", NULL };
static const char *cmer_prefix[] = { "+CMER:", NULL };
static const char *chld_prefix[] = { "+CHLD:", NULL };
static const char *bind_prefix[] = { "+BIND:", NULL };
struct slc_establish_data {
gint ref_count;
@@ -76,6 +78,14 @@ void hfp_slc_info_init(struct hfp_slc_info *info, guint16 version)
info->hf_features |= HFP_HF_FEATURE_CODEC_NEGOTIATION;
if (version < HFP_VERSION_1_7)
goto done;
info->hf_features |= HFP_HF_FEATURE_HF_INDICATORS;
memset(info->hf_indicators, 0, sizeof(info->hf_indicators));
info->num_hf_indicators = 0;
info->hf_indicator_active_map = 0;
done:
memset(info->cind_val, 0, sizeof(info->cind_val));
memset(info->cind_pos, 0, sizeof(info->cind_pos));
@@ -107,6 +117,104 @@ static void slc_established(struct slc_establish_data *sed)
sed->connect_cb(sed->userdata);
}
static void bind_query_cb(gboolean ok, GAtResult *result, gpointer user_data)
{
struct slc_establish_data *sed = user_data;
struct hfp_slc_info *info = sed->info;
GAtResultIter iter;
int hf_indicator;
int enabled;
unsigned int i;
if (!ok)
goto error;
g_at_result_iter_init(&iter, result);
while (g_at_result_iter_next(&iter, "+BIND:")) {
if (!g_at_result_iter_next_number(&iter, &hf_indicator))
goto error;
if (!g_at_result_iter_next_number(&iter, &enabled))
goto error;
ofono_info("AG wants indicator %d %s",
hf_indicator, enabled ? "enabled" : "disabled");
for (i = 0; i < info->num_hf_indicators; i++) {
if (info->hf_indicators[i] != hf_indicator)
continue;
info->hf_indicator_active_map |= enabled << i;
}
ofono_info("Active map: %02x", info->hf_indicator_active_map);
}
slc_established(sed);
return;
error:
slc_failed(sed);
}
static void bind_support_cb(gboolean ok, GAtResult *result, gpointer user_data)
{
struct slc_establish_data *sed = user_data;
struct hfp_slc_info *info = sed->info;
GAtResultIter iter;
int hf_indicator;
if (!ok)
goto error;
g_at_result_iter_init(&iter, result);
if (!g_at_result_iter_next(&iter, "+BIND:"))
goto error;
if (!g_at_result_iter_open_list(&iter))
goto error;
while (g_at_result_iter_next_number(&iter, &hf_indicator)) {
if (info->num_hf_indicators >= 20)
goto error;
ofono_info("AG supports the following HF indicator: %d",
hf_indicator);
info->hf_indicators[info->num_hf_indicators] = hf_indicator;
info->num_hf_indicators += 1;
}
if (!g_at_result_iter_close_list(&iter))
goto error;
slc_establish_data_ref(sed);
g_at_chat_send(info->chat, "AT+BIND?", bind_prefix,
bind_query_cb, sed, slc_establish_data_unref);
return;
error:
slc_failed(sed);
}
static void bind_set_cb(gboolean ok, GAtResult *result, gpointer user_data)
{
struct slc_establish_data *sed = user_data;
struct hfp_slc_info *info = sed->info;
if (!ok) {
slc_failed(sed);
return;
}
slc_establish_data_ref(sed);
g_at_chat_send(info->chat, "AT+BIND=?", bind_prefix,
bind_support_cb, sed, slc_establish_data_unref);
}
static void chld_cb(gboolean ok, GAtResult *result, gpointer user_data)
{
struct slc_establish_data *sed = user_data;
@@ -148,7 +256,14 @@ static void chld_cb(gboolean ok, GAtResult *result, gpointer user_data)
info->ag_mpty_features = ag_mpty_feature;
slc_established(sed);
if ((info->ag_features & HFP_AG_FEATURE_HF_INDICATORS) &&
(info->hf_features & HFP_HF_FEATURE_HF_INDICATORS)) {
slc_establish_data_ref(sed);
g_at_chat_send(info->chat, "AT+BIND=1", none_prefix,
bind_set_cb, sed, slc_establish_data_unref);
} else
slc_established(sed);
return;
error:

View File

@@ -39,6 +39,9 @@ struct hfp_slc_info {
unsigned int hf_features;
unsigned char cind_pos[HFP_INDICATOR_LAST];
unsigned int cind_val[HFP_INDICATOR_LAST];
unsigned short hf_indicators[20];
unsigned char num_hf_indicators;
unsigned int hf_indicator_active_map;
};
void hfp_slc_info_init(struct hfp_slc_info *info, guint16 version);

View File

@@ -46,6 +46,7 @@
#define POLL_CLCC_DELAY 50
#define EXPECT_RELEASE_DELAY 50
#define CLIP_TIMEOUT 500
#define EXPECT_RING_DELAY 200
static const char *none_prefix[] = { NULL };
static const char *clcc_prefix[] = { "+CLCC:", NULL };
@@ -294,7 +295,7 @@ static void clcc_poll_cb(gboolean ok, GAtResult *result, gpointer user_data)
* we won't get indicator update if any of them is released by CHLD=1x.
* So we have to poll it.
*/
if (num_active > 1 || num_held > 1)
if ((num_active > 1 || num_held > 1) && !vd->clcc_source)
vd->clcc_source = g_timeout_add(POLL_CLCC_INTERVAL, poll_clcc,
vc);
}
@@ -499,6 +500,19 @@ static gboolean expect_release(gpointer user_data)
return FALSE;
}
static gboolean expect_ring(gpointer user_data)
{
struct ofono_voicecall *vc = user_data;
struct voicecall_data *vd = ofono_voicecall_get_data(vc);
g_at_chat_send(vd->chat, "AT+CLCC", clcc_prefix,
clcc_poll_cb, vc, NULL);
vd->clip_source = 0;
return FALSE;
}
static void release_all_active_cb(gboolean ok, GAtResult *result,
gpointer user_data)
{
@@ -640,8 +654,10 @@ static void hfp_send_dtmf(struct ofono_voicecall *vc, const char *dtmf,
{
struct voicecall_data *vd = ofono_voicecall_get_data(vc);
struct change_state_req *req = g_try_new0(struct change_state_req, 1);
int len = strlen(dtmf);
char *buf;
int s;
int i;
if (req == NULL)
goto error;
@@ -651,12 +667,15 @@ static void hfp_send_dtmf(struct ofono_voicecall *vc, const char *dtmf,
req->data = data;
req->affected_types = 0;
/* strlen("AT+VTS=) = 7 + NULL */
buf = g_try_new(char, strlen(dtmf) + 8);
/* strlen("AT") + (n-1) * strlen("+VTS=T;") + strlen(+VTS=T) + null */
buf = g_try_new(char, len * 7 + 2);
if (buf == NULL)
goto error;
sprintf(buf, "AT+VTS=%s", dtmf);
s = sprintf(buf, "AT+VTS=%c", dtmf[0]);
for (i = 1; i < len; i++)
s += sprintf(buf + s, ";+VTS=%c", dtmf[i]);
s = g_at_chat_send(vd->chat, buf, none_prefix,
generic_cb, req, g_free);
@@ -752,6 +771,11 @@ static void ring_notify(GAtResult *result, gpointer user_data)
struct ofono_call *call;
GSList *waiting;
if (vd->clip_source) {
g_source_remove(vd->clip_source);
vd->clip_source = 0;
}
/* RING can repeat, ignore if we already have an incoming call */
if (g_slist_find_custom(vd->calls,
GINT_TO_POINTER(CALL_STATUS_INCOMING),
@@ -976,7 +1000,15 @@ static void ciev_callsetup_notify(struct ofono_voicecall *vc,
break;
case 1:
/* Handled in RING/CCWA */
/*
* Handled in RING/CCWA most of the time, however sometimes
* the call is answered before the RING unsolicited
* notification has a chance to be generated on the device.
* In this case, we use a failsafe CLCC poll in expect_ring
* callback.
* */
vd->clip_source = g_timeout_add(EXPECT_RING_DELAY,
expect_ring, vc);
break;
case 2:

View File

@@ -375,7 +375,14 @@ gboolean ril_util_parse_sim_status(GRil *gril,
* 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, ",
"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,
@@ -387,6 +394,7 @@ gboolean ril_util_parse_sim_status(GRil *gril,
else
goto done;
DBG("sim num_apps: %d", status->num_apps);
if (status->num_apps > MAX_UICC_APPS) {
ofono_error("SIM error; too many apps: %d", status->num_apps);
status->num_apps = MAX_UICC_APPS;
@@ -403,6 +411,8 @@ gboolean ril_util_parse_sim_status(GRil *gril,
apps[i]->app_type = parcel_r_int32(&rilp);
apps[i]->app_state = parcel_r_int32(&rilp);
DBG("app[%d]: app_type: %d, app_state: %d", i,
apps[i]->app_type, apps[i]->app_state);
/*
* Consider RIL_APPSTATE_ILLEGAL also READY. Even if app state
* is RIL_APPSTATE_ILLEGAL (-1), ICC operations must be
@@ -437,6 +447,16 @@ gboolean ril_util_parse_sim_status(GRil *gril,
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:
@@ -606,8 +626,10 @@ gint ril_util_parse_sms_response(GRil *gril, struct ril_msg *message)
*/
mr = parcel_r_int32(&rilp);
ack_pdu = parcel_r_string(&rilp);
error = parcel_r_int32(&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);

View File

@@ -97,11 +97,9 @@ struct sim_data {
guint app_type;
gchar *app_str;
guint app_index;
gboolean sim_registered;
enum ofono_sim_password_type passwd_type;
int retries[OFONO_SIM_PASSWORD_INVALID];
enum ofono_sim_password_type passwd_state;
guint card_state;
guint idle_id;
gboolean initialized;
gboolean removed;
@@ -128,7 +126,8 @@ static void set_path(struct sim_data *sd, struct parcel *rilp,
} else if (sd->app_type == RIL_APPTYPE_SIM) {
len = sim_ef_db_get_path_2g(fileid, db_path);
} else {
ofono_error("Unsupported app_type: 0%x", sd->app_type);
ofono_error("%s Unsupported app_type: 0%x", __func__,
sd->app_type);
}
if (len > 0) {
@@ -187,7 +186,7 @@ static void ril_file_info_cb(struct ril_msg *message, gpointer user_data)
* core will crash.
*/
if (sd->removed == TRUE) {
ofono_error("RIL_CARDSTATE_ABSENT");
ofono_error("%s RIL_CARDSTATE_ABSENT", __func__);
return;
}
@@ -205,14 +204,15 @@ static void ril_file_info_cb(struct ril_msg *message, gpointer user_data)
&sw1,
&sw2,
&response_len)) == NULL) {
ofono_error("Can't parse SIM IO response from RILD");
ofono_error("%s Can't parse SIM IO response", __func__);
decode_ril_error(&error, "FAIL");
goto error;
}
if ((sw1 != 0x90 && sw1 != 0x91 && sw1 != 0x92 && sw1 != 0x9f) ||
(sw1 == 0x90 && sw2 != 0x00)) {
ofono_error("invalid values: sw1: %02x sw2: %02x", sw1, sw2);
ofono_error("%s invalid values: sw1: %02x sw2: %02x", __func__,
sw1, sw2);
memset(&error, 0, sizeof(error));
/* TODO: fix decode_ril_error to take type & error */
@@ -235,7 +235,7 @@ static void ril_file_info_cb(struct ril_msg *message, gpointer user_data)
}
if (!ok) {
ofono_error("parse response failed");
ofono_error("%s parse response failed", __func__);
decode_ril_error(&error, "FAIL");
goto error;
}
@@ -325,7 +325,7 @@ static void ril_file_io_cb(struct ril_msg *message, gpointer user_data)
if (message->error == RIL_E_SUCCESS) {
decode_ril_error(&error, "OK");
} else {
ofono_error("RILD reply failure: %s",
ofono_error("%s RILD reply failure: %s", __func__,
ril_error_to_string(message->error));
goto error;
}
@@ -336,7 +336,7 @@ static void ril_file_io_cb(struct ril_msg *message, gpointer user_data)
&sw1,
&sw2,
&response_len)) == NULL) {
ofono_error("Error parsing IO response");
ofono_error("%s Error parsing IO response", __func__);
goto error;
}
@@ -470,7 +470,7 @@ static void ril_imsi_cb(struct ril_msg *message, gpointer user_data)
DBG("GET IMSI reply - OK");
decode_ril_error(&error, "OK");
} else {
ofono_error("Reply failure: %s",
ofono_error("%s Reply failure: %s", __func__,
ril_error_to_string(message->error));
decode_ril_error(&error, "FAIL");
cb(&error, NULL, cbd->data);
@@ -637,14 +637,11 @@ static void sim_status_cb(struct ril_msg *message, gpointer user_data)
guint search_index = -1;
struct parcel rilp;
DBG("");
DBG("%p", message);
if (ril_util_parse_sim_status(sd->ril, message, &status, apps) &&
status.num_apps) {
DBG("num_apps: %d gsm_umts_index: %d", status.num_apps,
status.gsm_umts_index);
/* TODO(CDMA): need some kind of logic to
* set the correct app_index,
*/
@@ -660,25 +657,24 @@ static void sim_status_cb(struct ril_msg *message, gpointer user_data)
}
}
if (sd->sim_registered == FALSE) {
ofono_sim_register(sim);
sd->sim_registered = TRUE;
} else {
/* TODO: There doesn't seem to be any other
* way to force the core SIM code to
* recheck the PIN.
* Wouldn't __ofono_sim_refresh be
* more appropriate call here??
* __ofono_sim_refresh(sim, NULL, TRUE, TRUE);
*/
DBG("sd->card_state:%u", sd->card_state);
if (sd->card_state != RIL_CARDSTATE_PRESENT) {
ofono_sim_inserted_notify(sim, TRUE);
sd->card_state = RIL_CARDSTATE_PRESENT;
sd->removed = FALSE;
}
}
/*
* ril_util_parse_sim_status returns true only when
* card status is RIL_CARDSTATE_PRESENT so notify TRUE always.
*
* ofono_sim_inserted_notify skips and returns if
* present/not_present status doesn't change from previous.
*/
ofono_sim_inserted_notify(sim, TRUE);
sd->removed = FALSE;
/* TODO: There doesn't seem to be any other
* way to force the core SIM code to
* recheck the PIN.
* Wouldn't __ofono_sim_refresh be
* more appropriate call here??
* __ofono_sim_refresh(sim, NULL, TRUE, TRUE);
*/
__ofono_sim_recheck_pin(sim);
if (current_online_state == RIL_ONLINE_PREF) {
@@ -705,19 +701,14 @@ static void sim_status_cb(struct ril_msg *message, gpointer user_data)
current_online_state = RIL_ONLINE_PREF;
if (status.card_state == RIL_CARDSTATE_ABSENT) {
DBG("sd->card_state:%u,status.card_state:%u,",
sd->card_state, status.card_state);
ofono_info("RIL_CARDSTATE_ABSENT");
ofono_sim_inserted_notify(sim, FALSE);
if (sd->card_state == RIL_CARDSTATE_PRESENT)
sd->removed = TRUE;
sd->card_state = RIL_CARDSTATE_ABSENT;
ofono_info("%s: RIL_CARDSTATE_ABSENT", __func__);
ofono_sim_inserted_notify(sim, FALSE);
sd->removed = TRUE;
sd->initialized = FALSE;
}
}
/* TODO: if no SIM present, handle emergency calling. */
}
static int send_get_sim_status(struct ofono_sim *sim)
@@ -770,9 +761,6 @@ static void ril_query_passwd_state_cb(struct ril_msg *message, gpointer user_dat
if (ril_util_parse_sim_status(sd->ril, message, &status, apps) &&
status.num_apps) {
DBG("num_apps: %d gsm_umts_index: %d", status.num_apps,
status.gsm_umts_index);
/* TODO(CDMA): need some kind of logic to
* set the correct app_index,
*/
@@ -1117,15 +1105,14 @@ static gboolean ril_sim_register(gpointer user)
DBG("");
sd->idle_id = 0;
ofono_sim_register(sim);
send_get_sim_status(sim);
g_ril_register(sd->ril, RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED,
sd->idle_id = 0;
sd->idle_id = g_ril_register(sd->ril,
RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED,
(GRilNotifyFunc) ril_sim_status_changed, sim);
/* TODO: should we also register for RIL_UNSOL_SIM_REFRESH? */
return FALSE;
}

View File

@@ -0,0 +1,315 @@
/*
*
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2014 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 <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <glib.h>
#include <ofono/log.h>
#include <ofono/modem.h>
#include <ofono/location-reporting.h>
#include "gatchat.h"
#include "gatresult.h"
#include "gattty.h"
#include "telitmodem.h"
static const char *none_prefix[] = { NULL };
static const char *portcfg_prefix[] = { "#PORTCFG:", NULL };
static const char *gpsctl_prefix[] = { "$GPSP:", NULL };
struct gps_data {
GAtChat *chat;
};
static void telit_gps_disable_cb(gboolean ok, GAtResult *result,
gpointer user_data)
{
struct cb_data *cbd = user_data;
struct ofono_location_reporting *lr = cbd->user;
ofono_location_reporting_disable_cb_t cb = cbd->cb;
DBG("lr=%p, ok=%d", lr, ok);
if (!ok) {
struct ofono_error error;
decode_at_error(&error, g_at_result_final_response(result));
cb(&error, cbd->data);
return;
}
CALLBACK_WITH_SUCCESS(cb, cbd->data);
}
static void telit_location_reporting_disable(
struct ofono_location_reporting *lr,
ofono_location_reporting_disable_cb_t cb,
void *data)
{
struct gps_data *gd = ofono_location_reporting_get_data(lr);
struct cb_data *cbd = cb_data_new(cb, data);
DBG("lr=%p", lr);
cbd->user = lr;
if (g_at_chat_send(gd->chat, "AT$GPSP=0", none_prefix,
telit_gps_disable_cb, cbd, g_free) > 0)
return;
CALLBACK_WITH_FAILURE(cb, data);
g_free(cbd);
}
static int enable_data_stream(struct ofono_location_reporting *lr)
{
struct ofono_modem *modem;
const char *gps_dev;
GHashTable *options;
GIOChannel *channel;
int fd;
modem = ofono_location_reporting_get_modem(lr);
gps_dev = ofono_modem_get_string(modem, "GPS");
options = g_hash_table_new(g_str_hash, g_str_equal);
if (options == NULL)
return -1;
g_hash_table_insert(options, "Baud", "115200");
channel = g_at_tty_open(gps_dev, options);
g_hash_table_destroy(options);
if (channel == NULL)
return -1;
fd = g_io_channel_unix_get_fd(channel);
g_io_channel_set_close_on_unref(channel, FALSE);
g_io_channel_unref(channel);
return fd;
}
static void telit_gps_ctl_cb(gboolean ok, GAtResult *result,
gpointer user_data)
{
struct cb_data *cbd = user_data;
ofono_location_reporting_enable_cb_t cb = cbd->cb;
struct ofono_location_reporting *lr = cbd->user;
struct ofono_error error;
int fd;
DBG("lr=%p ok=%d", lr, ok);
decode_at_error(&error, g_at_result_final_response(result));
if (!ok) {
cb(&error, -1, cbd->data);
return;
}
fd = enable_data_stream(lr);
if (fd < 0) {
CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
return;
}
cb(&error, fd, cbd->data);
close(fd);
}
static void telit_gps_enable_cb(gboolean ok, GAtResult *result,
gpointer user_data)
{
struct cb_data *cbd = user_data;
ofono_location_reporting_enable_cb_t cb = cbd->cb;
struct ofono_location_reporting *lr = cbd->user;
struct gps_data *gd = ofono_location_reporting_get_data(lr);
struct ofono_error error;
DBG("lr=%p ok=%d", lr, ok);
decode_at_error(&error, g_at_result_final_response(result));
if (!ok) {
cb(&error, -1, cbd->data);
g_free(cbd);
return;
}
if (g_at_chat_send(gd->chat, "AT$GPSNMUN=1,0,0,0,0,0,0",
none_prefix, telit_gps_ctl_cb, cbd, g_free) > 0)
return;
CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
g_free(cbd);
}
static void telit_portcfg_check_cb(gboolean ok, GAtResult *result,
gpointer user_data)
{
struct cb_data *cbd = user_data;
ofono_location_reporting_enable_cb_t cb = cbd->cb;
struct ofono_location_reporting *lr = cbd->user;
struct gps_data *gd = ofono_location_reporting_get_data(lr);
struct ofono_error error;
int requested_portcfg, current_portcfg;
GAtResultIter iter;
DBG("lr=%p ok=%d", lr, ok);
decode_at_error(&error, g_at_result_final_response(result));
if (!ok) {
cb(&error, -1, cbd->data);
g_free(cbd);
return;
}
g_at_result_iter_init(&iter, result);
if (!g_at_result_iter_next(&iter, "#PORTCFG:"))
goto fail;
if (!g_at_result_iter_next_number(&iter, &requested_portcfg))
goto fail;
if (!g_at_result_iter_next_number(&iter, &current_portcfg))
goto fail;
if (current_portcfg != 8) {
ofono_warn("Unable to start GPS, modem configuration invalid");
ofono_warn("Refer to doc/telit-modem.txt section HE910/GPS");
goto fail;
}
if (g_at_chat_send(gd->chat, "AT$GPSP=1", none_prefix,
telit_gps_enable_cb, cbd, NULL) > 0)
return;
fail:
CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
g_free(cbd);
}
static void telit_location_reporting_enable(struct ofono_location_reporting *lr,
ofono_location_reporting_enable_cb_t cb,
void *data)
{
struct gps_data *gd = ofono_location_reporting_get_data(lr);
struct cb_data *cbd = cb_data_new(cb, data);
DBG("lr=%p", lr);
cbd->user = lr;
if (g_at_chat_send(gd->chat, "AT#PORTCFG?", portcfg_prefix,
telit_portcfg_check_cb, cbd, NULL) > 0)
return;
CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
g_free(cbd);
}
static void telit_location_reporting_support_cb(gboolean ok, GAtResult *result,
gpointer user_data)
{
struct ofono_location_reporting *lr = user_data;
if (!ok) {
ofono_location_reporting_remove(lr);
return;
}
ofono_location_reporting_register(lr);
}
static int telit_location_reporting_probe(struct ofono_location_reporting *lr,
unsigned int vendor, void *data)
{
GAtChat *chat = data;
struct gps_data *gd;
gd = g_try_new0(struct gps_data, 1);
if (gd == NULL)
return -ENOMEM;
gd->chat = g_at_chat_clone(chat);
ofono_location_reporting_set_data(lr, gd);
g_at_chat_send(gd->chat, "AT$GPSP=?", gpsctl_prefix,
telit_location_reporting_support_cb,
lr, NULL);
return 0;
}
static void telit_location_reporting_remove(struct ofono_location_reporting *lr)
{
struct gps_data *gd = ofono_location_reporting_get_data(lr);
ofono_location_reporting_set_data(lr, NULL);
g_at_chat_unref(gd->chat);
g_free(gd);
}
static struct ofono_location_reporting_driver driver = {
.name = "telitmodem",
.type = OFONO_LOCATION_REPORTING_TYPE_NMEA,
.probe = telit_location_reporting_probe,
.remove = telit_location_reporting_remove,
.enable = telit_location_reporting_enable,
.disable = telit_location_reporting_disable,
};
void telit_location_reporting_init()
{
ofono_location_reporting_driver_register(&driver);
}
void telit_location_reporting_exit()
{
ofono_location_reporting_driver_unregister(&driver);
}

View File

@@ -0,0 +1,49 @@
/*
*
* oFono - Open Source Telephony
*
* 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
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <glib.h>
#include <gatchat.h>
#define OFONO_API_SUBJECT_TO_CHANGE
#include <ofono/plugin.h>
#include <ofono/types.h>
#include "telitmodem.h"
static int telitmodem_init(void)
{
telit_location_reporting_init();
return 0;
}
static void telitmodem_exit(void)
{
telit_location_reporting_exit();
}
OFONO_PLUGIN_DEFINE(telitmodem, "Telit modem driver", VERSION,
OFONO_PLUGIN_PRIORITY_DEFAULT,
telitmodem_init, telitmodem_exit)

View File

@@ -0,0 +1,25 @@
/*
*
* oFono - Open Source Telephony
*
* 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
*
*/
#include <drivers/atmodem/atutil.h>
extern void telit_location_reporting_init();
extern void telit_location_reporting_exit();

View File

@@ -64,11 +64,13 @@ struct _GAtPPP {
struct pppcp_data *ipcp;
struct ppp_net *net;
struct ppp_chap *chap;
struct ppp_pap *pap;
GAtHDLC *hdlc;
gint mru;
gint mtu;
char username[256];
char password[256];
GAtPPPAuthMethod auth_method;
GAtPPPConnectFunc connect_cb;
gpointer connect_data;
GAtPPPDisconnectFunc disconnect_cb;
@@ -150,13 +152,15 @@ static inline gboolean ppp_drop_packet(GAtPPP *ppp, guint16 protocol)
return TRUE;
break;
case PPP_PHASE_AUTHENTICATION:
if (protocol != LCP_PROTOCOL && protocol != CHAP_PROTOCOL)
if (protocol != LCP_PROTOCOL && protocol != CHAP_PROTOCOL &&
protocol != PAP_PROTOCOL)
return TRUE;
break;
case PPP_PHASE_DEAD:
return TRUE;
case PPP_PHASE_NETWORK:
if (protocol != LCP_PROTOCOL && protocol != CHAP_PROTOCOL &&
protocol != PAP_PROTOCOL &&
protocol != IPCP_PROTO)
return TRUE;
break;
@@ -221,6 +225,13 @@ static void ppp_receive(const unsigned char *buf, gsize len, void *data)
break;
case IPCP_PROTO:
pppcp_process_packet(ppp->ipcp, packet, len - offset);
break;
case PAP_PROTOCOL:
if (ppp->pap)
ppp_pap_process_packet(ppp->pap, packet, len - offset);
else
pppcp_send_protocol_reject(ppp->lcp, buf, len);
break;
case CHAP_PROTOCOL:
if (ppp->chap) {
@@ -359,6 +370,12 @@ void ppp_set_auth(GAtPPP *ppp, const guint8* auth_data)
guint16 proto = get_host_short(auth_data);
switch (proto) {
case PAP_PROTOCOL:
if (ppp->pap)
ppp_pap_free(ppp->pap);
ppp->pap = ppp_pap_new(ppp);
break;
case CHAP_PROTOCOL:
if (ppp->chap)
ppp_chap_free(ppp->chap);
@@ -437,10 +454,19 @@ void ppp_ipcp_finished_notify(GAtPPP *ppp)
void ppp_lcp_up_notify(GAtPPP *ppp)
{
/* Wait for the peer to send us a challenge if we expect auth */
if (ppp->chap != NULL) {
/* Wait for the peer to send us a challenge. */
ppp_enter_phase(ppp, PPP_PHASE_AUTHENTICATION);
return;
} else if (ppp->pap != NULL) {
/* Try to send an Authenticate-Request and wait for reply. */
if (ppp_pap_start(ppp->pap) == TRUE)
ppp_enter_phase(ppp, PPP_PHASE_AUTHENTICATION);
else
/* It'll never work out. */
ppp_auth_notify(ppp, FALSE);
return;
}
/* Otherwise proceed as if auth succeeded */
@@ -588,6 +614,22 @@ const char *g_at_ppp_get_password(GAtPPP *ppp)
return ppp->password;
}
gboolean g_at_ppp_set_auth_method(GAtPPP *ppp, GAtPPPAuthMethod method)
{
if (method != G_AT_PPP_AUTH_METHOD_CHAP &&
method != G_AT_PPP_AUTH_METHOD_PAP)
return FALSE;
ppp->auth_method = method;
return TRUE;
}
GAtPPPAuthMethod g_at_ppp_get_auth_method(GAtPPP *ppp)
{
return ppp->auth_method;
}
void g_at_ppp_set_recording(GAtPPP *ppp, const char *filename)
{
if (ppp == NULL)
@@ -727,6 +769,9 @@ void g_at_ppp_unref(GAtPPP *ppp)
else if (ppp->fd >= 0)
close(ppp->fd);
if (ppp->pap)
ppp_pap_free(ppp->pap);
if (ppp->chap)
ppp_chap_free(ppp->chap);
@@ -794,6 +839,9 @@ static GAtPPP *ppp_init_common(gboolean is_server, guint32 ip)
/* initialize IPCP state */
ppp->ipcp = ipcp_new(ppp, is_server, ip);
/* chap authentication by default */
ppp->auth_method = G_AT_PPP_AUTH_METHOD_CHAP;
return ppp;
}

View File

@@ -43,6 +43,11 @@ typedef enum _GAtPPPDisconnectReason {
G_AT_PPP_REASON_LOCAL_CLOSE, /* Normal user close */
} GAtPPPDisconnectReason;
typedef enum _GAtPPPAuthMethod {
G_AT_PPP_AUTH_METHOD_CHAP,
G_AT_PPP_AUTH_METHOD_PAP,
} GAtPPPAuthMethod;
typedef void (*GAtPPPConnectFunc)(const char *iface, const char *local,
const char *peer,
const char *dns1, const char *dns2,
@@ -74,6 +79,9 @@ gboolean g_at_ppp_set_credentials(GAtPPP *ppp, const char *username,
const char *g_at_ppp_get_username(GAtPPP *ppp);
const char *g_at_ppp_get_password(GAtPPP *ppp);
gboolean g_at_ppp_set_auth_method(GAtPPP *ppp, GAtPPPAuthMethod method);
GAtPPPAuthMethod g_at_ppp_get_auth_method(GAtPPP *ppp);
void g_at_ppp_set_recording(GAtPPP *ppp, const char *filename);
void g_at_ppp_set_server_info(GAtPPP *ppp, const char *remote_ip,

View File

@@ -22,6 +22,7 @@
#include "ppp_cp.h"
#define LCP_PROTOCOL 0xc021
#define PAP_PROTOCOL 0xc023
#define CHAP_PROTOCOL 0xc223
#define IPCP_PROTO 0x8021
#define IPV6CP_PROTO 0x8057
@@ -38,6 +39,7 @@
struct ppp_chap;
struct ppp_net;
struct ppp_pap;
struct ppp_header {
guint8 address;
@@ -109,6 +111,13 @@ void ppp_chap_free(struct ppp_chap *chap);
void ppp_chap_process_packet(struct ppp_chap *chap, const guint8 *new_packet,
gsize len);
/* PAP related functions */
struct ppp_pap *ppp_pap_new(GAtPPP *ppp);
void ppp_pap_free(struct ppp_pap *pap);
gboolean ppp_pap_start(struct ppp_pap *pap);
void ppp_pap_process_packet(struct ppp_pap *pap, const guint8 *new_packet,
gsize len);
/* TUN / Network related functions */
struct ppp_net *ppp_net_new(GAtPPP *ppp, int fd);
const char *ppp_net_get_interface(struct ppp_net *net);

View File

@@ -54,6 +54,38 @@ enum chap_code {
FAILURE
};
struct pap_header {
guint8 code;
guint8 identifier;
guint16 length;
guint8 data[0];
} __attribute__((packed));
struct ppp_pap {
GAtPPP *ppp;
struct ppp_header *authreq;
guint16 authreq_len;
guint retry_timer;
guint retries;
};
enum pap_code {
PAP_REQUEST = 1,
PAP_ACK,
PAP_NAK
};
/*
* RFC 1334 2.1.1:
* The Authenticate-Request packet MUST be repeated until a valid
* reply packet is received, or an optional retry counter expires.
*
* If we don't get a reply after this many attempts, we can safely
* assume we're never going to get one.
*/
#define PAP_MAX_RETRY 3 /* attempts */
#define PAP_TIMEOUT 10 /* seconds */
static void chap_process_challenge(struct ppp_chap *chap, const guint8 *packet)
{
const struct chap_header *header = (const struct chap_header *) packet;
@@ -166,3 +198,114 @@ struct ppp_chap *ppp_chap_new(GAtPPP *ppp, guint8 method)
return chap;
}
void ppp_pap_process_packet(struct ppp_pap *pap, const guint8 *new_packet,
gsize len)
{
guint8 code;
if (len < sizeof(struct pap_header))
return;
code = new_packet[0];
switch (code) {
case PAP_ACK:
g_source_remove(pap->retry_timer);
pap->retry_timer = 0;
ppp_auth_notify(pap->ppp, TRUE);
break;
case PAP_NAK:
g_source_remove(pap->retry_timer);
pap->retry_timer = 0;
ppp_auth_notify(pap->ppp, FALSE);
break;
default:
break;
}
}
static gboolean ppp_pap_timeout(gpointer user_data)
{
struct ppp_pap *pap = (struct ppp_pap *)user_data;
struct pap_header *authreq;
if (++pap->retries >= PAP_MAX_RETRY) {
pap->retry_timer = 0;
ppp_auth_notify(pap->ppp, FALSE);
return FALSE;
}
/*
* RFC 1334 2.2.1:
* The Identifier field MUST be changed each time an
* Authenticate-Request packet is issued.
*/
authreq = (struct pap_header *)&pap->authreq->info;
authreq->identifier++;
ppp_transmit(pap->ppp, (guint8 *)pap->authreq, pap->authreq_len);
return TRUE;
}
gboolean ppp_pap_start(struct ppp_pap *pap)
{
struct pap_header *authreq;
struct ppp_header *packet;
const char *username = g_at_ppp_get_username(pap->ppp);
const char *password = g_at_ppp_get_password(pap->ppp);
guint16 length;
length = sizeof(*authreq) + strlen(username) + strlen(password) + 2;
packet = ppp_packet_new(length, PAP_PROTOCOL);
if (packet == NULL)
return FALSE;
pap->authreq = packet;
pap->authreq_len = length;
authreq = (struct pap_header *)&packet->info;
authreq->code = PAP_REQUEST;
authreq->identifier = 1;
authreq->length = htons(length);
authreq->data[0] = (unsigned char) strlen(username);
memcpy(authreq->data + 1, username, strlen(username));
authreq->data[strlen(username) + 1] = (unsigned char)strlen(password);
memcpy(authreq->data + 1 + strlen(username) + 1, password,
strlen(password));
/* Transmit the packet and schedule a retry. */
ppp_transmit(pap->ppp, (guint8 *)packet, length);
pap->retries = 0;
pap->retry_timer = g_timeout_add_seconds(PAP_TIMEOUT,
ppp_pap_timeout, pap);
return TRUE;
}
void ppp_pap_free(struct ppp_pap *pap)
{
if (pap->retry_timer != 0)
g_source_remove(pap->retry_timer);
if (pap->authreq != NULL)
g_free(pap->authreq);
g_free(pap);
}
struct ppp_pap *ppp_pap_new(GAtPPP *ppp)
{
struct ppp_pap *pap;
pap = g_try_new0(struct ppp_pap, 1);
if (pap == NULL)
return NULL;
pap->ppp = ppp;
return pap;
}

View File

@@ -238,25 +238,49 @@ static enum rcr_result lcp_rcr(struct pppcp_data *pppcp,
guint8 method = option_data[2];
guint8 *option;
if ((proto == CHAP_PROTOCOL) && (method == MD5))
break;
switch (g_at_ppp_get_auth_method(ppp)) {
case G_AT_PPP_AUTH_METHOD_CHAP:
if (proto == CHAP_PROTOCOL && method == MD5)
break;
/*
* try to suggest CHAP & MD5. If we are out
* of memory, just reject.
*/
/*
* Try to suggest CHAP/MD5.
* Just reject if we run out of memory.
*/
option = g_try_malloc0(5);
if (option == NULL)
return RCR_REJECT;
option = g_try_malloc0(5);
if (option == NULL)
return RCR_REJECT;
option[0] = AUTH_PROTO;
option[1] = 5;
put_network_short(&option[2], CHAP_PROTOCOL);
option[4] = MD5;
*new_options = option;
*new_len = 5;
option[0] = AUTH_PROTO;
option[1] = 5;
put_network_short(&option[2], CHAP_PROTOCOL);
option[4] = MD5;
*new_options = option;
*new_len = 5;
return RCR_NAK;
return RCR_NAK;
case G_AT_PPP_AUTH_METHOD_PAP:
if (proto == PAP_PROTOCOL)
break;
/*
* Try to suggest PAP.
* Just reject if we run out of memory.
*/
option = g_try_malloc0(4);
if (option == NULL)
return RCR_REJECT;
option[0] = AUTH_PROTO;
option[1] = 4;
put_network_short(&option[2], PAP_PROTOCOL);
*new_options = option;
*new_len = 4;
return RCR_NAK;
}
break;
}
case ACCM:
case PFC:

View File

@@ -51,6 +51,7 @@ struct GDBusClient {
GDBusWatchFunction connect_func;
void *connect_data;
GDBusWatchFunction disconn_func;
gboolean connected;
void *disconn_data;
GDBusMessageFunction signal_func;
void *signal_data;
@@ -1146,6 +1147,8 @@ static void service_connect(DBusConnection *conn, void *user_data)
get_managed_objects(client);
client->connected = TRUE;
g_dbus_client_unref(client);
}
@@ -1156,8 +1159,10 @@ static void service_disconnect(DBusConnection *conn, void *user_data)
g_list_free_full(client->proxy_list, proxy_free);
client->proxy_list = NULL;
if (client->disconn_func)
if (client->disconn_func) {
client->disconn_func(conn, client->disconn_data);
client->connected = FALSE;
}
}
static DBusHandlerResult message_filter(DBusConnection *connection,
@@ -1210,6 +1215,7 @@ GDBusClient *g_dbus_client_new(DBusConnection *connection,
client->dbus_conn = dbus_connection_ref(connection);
client->service_name = g_strdup(service);
client->base_path = g_strdup(path);
client->connected = FALSE;
client->match_rules = g_ptr_array_sized_new(1);
g_ptr_array_set_free_func(client->match_rules, g_free);
@@ -1284,7 +1290,11 @@ void g_dbus_client_unref(GDBusClient *client)
g_list_free_full(client->proxy_list, proxy_free);
if (client->disconn_func)
/*
* Don't call disconn_func twice if disconnection
* was previously reported.
*/
if (client->disconn_func && client->connected)
client->disconn_func(client->dbus_conn, client->disconn_data);
g_dbus_remove_watch(client->dbus_conn, client->watch);

View File

@@ -88,16 +88,22 @@ static gboolean watch_func(GIOChannel *chan, GIOCondition cond, gpointer data)
struct watch_info *info = data;
unsigned int flags = 0;
DBusDispatchStatus status;
DBusConnection *conn;
if (cond & G_IO_IN) flags |= DBUS_WATCH_READABLE;
if (cond & G_IO_OUT) flags |= DBUS_WATCH_WRITABLE;
if (cond & G_IO_HUP) flags |= DBUS_WATCH_HANGUP;
if (cond & G_IO_ERR) flags |= DBUS_WATCH_ERROR;
/* Protect connection from being destroyed by dbus_watch_handle */
conn = dbus_connection_ref(info->conn);
dbus_watch_handle(info->watch, flags);
status = dbus_connection_get_dispatch_status(info->conn);
queue_dispatch(info->conn, status);
status = dbus_connection_get_dispatch_status(conn);
queue_dispatch(conn, status);
dbus_connection_unref(conn);
return TRUE;
}

View File

@@ -1088,7 +1088,6 @@ static const GDBusMethodTable introspect_methods[] = {
static void append_interfaces(struct generic_data *data, DBusMessageIter *iter)
{
DBusMessageIter array;
GSList *l;
dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
@@ -1100,12 +1099,7 @@ static void append_interfaces(struct generic_data *data, DBusMessageIter *iter)
DBUS_DICT_ENTRY_END_CHAR_AS_STRING
DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &array);
for (l = data->interfaces; l != NULL; l = l->next) {
if (g_slist_find(data->added, l->data))
continue;
append_interface(l->data, &array);
}
g_slist_foreach(data->interfaces, append_interface, &array);
dbus_message_iter_close_container(iter, &array);
}

View File

@@ -362,6 +362,7 @@ static void service_data_free(struct service_data *data)
callback->data = NULL;
}
/* Returns TRUE if data is freed */
static gboolean filter_data_remove_callback(struct filter_data *data,
struct filter_callback *cb)
{
@@ -383,7 +384,7 @@ static gboolean filter_data_remove_callback(struct filter_data *data,
/* Don't remove the filter if other callbacks exist or data is lock
* processing callbacks */
if (data->callbacks || data->lock)
return TRUE;
return FALSE;
if (data->registered && !remove_match(data))
return FALSE;
@@ -405,7 +406,9 @@ static DBusHandlerResult signal_filter(DBusConnection *connection,
if (cb->signal_func && !cb->signal_func(connection, message,
cb->user_data)) {
filter_data_remove_callback(data, cb);
if (filter_data_remove_callback(data, cb))
break;
continue;
}
@@ -489,7 +492,9 @@ static DBusHandlerResult service_filter(DBusConnection *connection,
/* Only auto remove if it is a bus name watch */
if (data->argument[0] == ':' &&
(cb->conn_func == NULL || cb->disc_func == NULL)) {
filter_data_remove_callback(data, cb);
if (filter_data_remove_callback(data, cb))
break;
continue;
}
@@ -586,7 +591,6 @@ static gboolean update_service(void *user_data)
struct filter_callback *cb = data->callback;
DBusConnection *conn;
update_name_cache(data->name, data->owner);
conn = dbus_connection_ref(data->conn);
service_data_free(data);
@@ -695,7 +699,8 @@ guint g_dbus_add_service_watch(DBusConnection *connection, const char *name,
if (name == NULL)
return 0;
data = filter_data_get(connection, service_filter, NULL, NULL,
data = filter_data_get(connection, service_filter,
DBUS_SERVICE_DBUS, DBUS_PATH_DBUS,
DBUS_INTERFACE_DBUS, "NameOwnerChanged",
name);
if (data == NULL)

View File

@@ -104,6 +104,9 @@ enum ofono_emulator_request_type ofono_emulator_request_get_type(
void ofono_emulator_set_indicator(struct ofono_emulator *em,
const char *name, int value);
void ofono_emulator_set_hf_indicator_active(struct ofono_emulator *em,
int indicator,
ofono_bool_t active);
#ifdef __cplusplus
}

View File

@@ -48,6 +48,11 @@ enum ofono_gprs_context_type {
OFONO_GPRS_CONTEXT_TYPE_IMS,
};
enum ofono_gprs_auth_method {
OFONO_GPRS_AUTH_METHOD_CHAP = 0,
OFONO_GPRS_AUTH_METHOD_PAP,
};
struct ofono_gprs_primary_context {
unsigned int cid;
int direction;
@@ -55,6 +60,7 @@ struct ofono_gprs_primary_context {
char username[OFONO_GPRS_MAX_USERNAME_LENGTH + 1];
char password[OFONO_GPRS_MAX_PASSWORD_LENGTH + 1];
enum ofono_gprs_proto proto;
enum ofono_gprs_auth_method auth_method;
};
typedef void (*ofono_gprs_context_cb_t)(const struct ofono_error *error,

View File

@@ -37,6 +37,7 @@ struct ofono_gprs_provision_data {
char *apn;
char *username;
char *password;
enum ofono_gprs_auth_method auth_method;
char *message_proxy;
char *message_center;
};

View File

@@ -56,6 +56,9 @@ struct ofono_handsfree_driver {
ofono_handsfree_cb_t cb, void *data);
void (*disable_nrec)(struct ofono_handsfree *hf,
ofono_handsfree_cb_t cb, void *data);
void (*hf_indicator)(struct ofono_handsfree *hf,
unsigned short indicator, unsigned int value,
ofono_handsfree_cb_t cb, void *data);
};
void ofono_handsfree_set_ag_features(struct ofono_handsfree *hf,
@@ -67,6 +70,13 @@ void ofono_handsfree_set_inband_ringing(struct ofono_handsfree *hf,
void ofono_handsfree_voice_recognition_notify(struct ofono_handsfree *hf,
ofono_bool_t enabled);
void ofono_handsfree_set_hf_indicators(struct ofono_handsfree *hf,
const unsigned short *indicators,
unsigned int num);
void ofono_handsfree_hf_indicator_active_notify(struct ofono_handsfree *hf,
unsigned int indicator,
ofono_bool_t active);
void ofono_handsfree_battchg_notify(struct ofono_handsfree *hf,
unsigned char level);

View File

@@ -29,10 +29,10 @@ extern "C" {
#include <ofono/types.h>
enum ofono_radio_access_mode {
OFONO_RADIO_ACCESS_MODE_ANY = 0,
OFONO_RADIO_ACCESS_MODE_GSM = 1,
OFONO_RADIO_ACCESS_MODE_UMTS = 2,
OFONO_RADIO_ACCESS_MODE_LTE = 3,
OFONO_RADIO_ACCESS_MODE_ANY = 0x0,
OFONO_RADIO_ACCESS_MODE_GSM = 0x1,
OFONO_RADIO_ACCESS_MODE_UMTS = 0x2,
OFONO_RADIO_ACCESS_MODE_LTE = 0x4,
};
enum ofono_radio_band_gsm {
@@ -80,6 +80,11 @@ typedef void (*ofono_radio_settings_fast_dormancy_query_cb_t)(
ofono_bool_t enable,
void *data);
typedef void (*ofono_radio_settings_available_rats_query_cb_t)(
const struct ofono_error *error,
unsigned int available_rats,
void *data);
struct ofono_radio_settings_driver {
const char *name;
int (*probe)(struct ofono_radio_settings *rs, unsigned int vendor,
@@ -107,6 +112,9 @@ struct ofono_radio_settings_driver {
ofono_bool_t enable,
ofono_radio_settings_fast_dormancy_set_cb_t,
void *data);
void (*query_available_rats)(struct ofono_radio_settings *rs,
ofono_radio_settings_available_rats_query_cb_t cb,
void *data);
};
int ofono_radio_settings_driver_register(

View File

@@ -0,0 +1,126 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2014 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 <unistd.h>
#include <errno.h>
#include <stdint.h>
#include <sys/socket.h>
#include <glib.h>
#include <ofono.h>
#include <gdbus.h>
#define OFONO_API_SUBJECT_TO_CHANGE
#include <ofono/plugin.h>
#include <ofono/log.h>
#include <ofono/modem.h>
#include <ofono/emulator.h>
#include "hfp.h"
#define EMULATOR_FUZZ_INTERFACE "org.ofono.test.EmulatorFuzz"
#define EMULATOR_FUZZ_PATH "/test"
static void emulator_set_indicator(struct ofono_atom *atom, void *data)
{
struct ofono_emulator *em = __ofono_atom_get_data(atom);
ofono_bool_t active = GPOINTER_TO_INT(data);
ofono_emulator_set_hf_indicator_active(em,
HFP_HF_INDICATOR_ENHANCED_SAFETY, active);
}
static void modem_set_indicators(struct ofono_modem *modem, void *user)
{
__ofono_modem_foreach_registered_atom(modem,
OFONO_ATOM_TYPE_EMULATOR_HFP,
emulator_set_indicator,
user);
}
static DBusMessage *set_indicator_active(DBusConnection *conn,
DBusMessage *msg, void *user_data)
{
const char *indicator;
dbus_bool_t active;
DBG("");
if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &indicator,
DBUS_TYPE_BOOLEAN, &active,
DBUS_TYPE_INVALID) == FALSE)
goto invalid;
DBG("%s,%d", indicator, active);
if (strcmp(indicator, "DistractedDrivingReduction"))
goto invalid;
__ofono_modem_foreach(modem_set_indicators, GINT_TO_POINTER(active));
return dbus_message_new_method_return(msg);
invalid:
return g_dbus_create_error(msg, "org.ofono.test.Error",
"Invalid arguments in method call");
}
static const GDBusMethodTable emulator_fuzz_methods[] = {
{ GDBUS_ASYNC_METHOD("SetIndicatorActive",
GDBUS_ARGS({ "indicator", "s" }, { "active", "b" }),
NULL, set_indicator_active) },
{ },
};
static int emulator_fuzz_init(void)
{
DBusConnection *conn = ofono_dbus_get_connection();
DBG("");
if (!g_dbus_register_interface(conn, EMULATOR_FUZZ_PATH,
EMULATOR_FUZZ_INTERFACE,
emulator_fuzz_methods, NULL,
NULL, NULL, NULL)) {
ofono_error("Register Profile interface failed: %s",
EMULATOR_FUZZ_PATH);
return -EIO;
}
return 0;
}
static void emulator_fuzz_exit(void)
{
DBusConnection *conn = ofono_dbus_get_connection();
DBG("");
g_dbus_unregister_interface(conn, EMULATOR_FUZZ_PATH,
EMULATOR_FUZZ_INTERFACE);
}
OFONO_PLUGIN_DEFINE(emulator_fuzz, "Emulator Fuzz",
VERSION, OFONO_PLUGIN_PRIORITY_DEFAULT,
emulator_fuzz_init, emulator_fuzz_exit)

View File

@@ -2,7 +2,7 @@
*
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2008-2014 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
@@ -46,6 +46,7 @@
#include <ofono/call-settings.h>
#include <ofono/devinfo.h>
#include <ofono/message-waiting.h>
#include <ofono/location-reporting.h>
#include <ofono/netreg.h>
#include <ofono/phonebook.h>
#include <ofono/sim.h>
@@ -318,6 +319,7 @@ static void he910_pre_sim(struct ofono_modem *modem)
ofono_devinfo_create(modem, 0, "atmodem", data->chat);
data->sim = ofono_sim_create(modem, OFONO_VENDOR_TELIT, "atmodem",
data->chat);
ofono_location_reporting_create(modem, 0, "telitmodem", data->chat);
}
static void he910_post_online(struct ofono_modem *modem)

View File

@@ -232,7 +232,7 @@ static void sim_state_watch(enum ofono_sim_state new_state, void *data)
if (modems->next != NULL)
return;
bt_register_profile(conn, HFP_AG_UUID, HFP_VERSION_1_5, "hfp_ag",
bt_register_profile(conn, HFP_AG_UUID, HFP_VERSION_1_7, "hfp_ag",
HFP_AG_EXT_PROFILE_PATH, NULL, 0);
}
@@ -299,7 +299,7 @@ static void voicecall_watch(struct ofono_atom *atom,
if (modems->next != NULL)
return;
bt_register_profile(conn, HFP_AG_UUID, HFP_VERSION_1_5, "hfp_ag",
bt_register_profile(conn, HFP_AG_UUID, HFP_VERSION_1_7, "hfp_ag",
HFP_AG_EXT_PROFILE_PATH, NULL, 0);
}

View File

@@ -72,6 +72,7 @@ struct hfp {
struct ofono_handsfree_card *card;
};
static const char *none_prefix[] = { NULL };
static GDBusClient *bluez = NULL;
static void hfp_debug(const char *str, void *user_data)
@@ -348,7 +349,7 @@ static void bcs_notify(GAtResult *result, gpointer user_data)
sprintf(str, "AT+BCS=%d", value);
done:
g_at_chat_send(info->chat, str, NULL, NULL, NULL, NULL);
g_at_chat_send(info->chat, str, none_prefix, NULL, NULL, NULL);
}
static int hfp16_card_probe(struct ofono_handsfree_card *card,
@@ -643,7 +644,7 @@ static void connect_handler(DBusConnection *conn, void *user_data)
DBG("Registering External Profile handler ...");
bt_register_profile(conn, HFP_HS_UUID, HFP_VERSION_1_6, "hfp_hf",
bt_register_profile(conn, HFP_HS_UUID, HFP_VERSION_1_7, "hfp_hf",
HFP_EXT_PROFILE_PATH, NULL, features);
}

View File

@@ -132,6 +132,37 @@ static const GMarkupParser text_parser = {
NULL,
};
static void authentication_start(GMarkupParseContext *context,
const gchar **attribute_names,
const gchar **attribute_values,
enum ofono_gprs_auth_method *auth_method,
GError **error)
{
const char *text = NULL;
int i;
for (i = 0; attribute_names[i]; i++)
if (g_str_equal(attribute_names[i], "method") == TRUE)
text = attribute_values[i];
if (text == NULL) {
mbpi_g_set_error(context, error, G_MARKUP_ERROR,
G_MARKUP_ERROR_MISSING_ATTRIBUTE,
"Missing attribute: method");
return;
}
if (strcmp(text, "chap") == 0)
*auth_method = OFONO_GPRS_AUTH_METHOD_CHAP;
else if (strcmp(text, "pap") == 0)
*auth_method = OFONO_GPRS_AUTH_METHOD_PAP;
else
mbpi_g_set_error(context, error, G_MARKUP_ERROR,
G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
"Unknown authentication method: %s",
text);
}
static void usage_start(GMarkupParseContext *context,
const gchar **attribute_names,
const gchar **attribute_values,
@@ -178,6 +209,9 @@ static void apn_start(GMarkupParseContext *context, const gchar *element_name,
else if (g_str_equal(element_name, "password"))
g_markup_parse_context_push(context, &text_parser,
&apn->password);
else if (g_str_equal(element_name, "authentication"))
authentication_start(context, attribute_names,
attribute_values, &apn->auth_method, error);
else if (g_str_equal(element_name, "mmsc"))
g_markup_parse_context_push(context, &text_parser,
&apn->message_center);
@@ -298,6 +332,7 @@ static void apn_handler(GMarkupParseContext *context, struct gsm_data *gsm,
ap->apn = g_strdup(apn);
ap->type = OFONO_GPRS_CONTEXT_TYPE_INTERNET;
ap->proto = OFONO_GPRS_PROTO_IP;
ap->auth_method = OFONO_GPRS_AUTH_METHOD_CHAP;
g_markup_parse_context_push(context, &apn_parser, ap);
}

View File

@@ -351,6 +351,65 @@ static void phonesim_ctm_set(struct ofono_ctm *ctm, ofono_bool_t enable,
g_free(cbd);
}
static gboolean phonesim_radio_settings_register(gpointer user)
{
struct ofono_radio_settings *rs = user;
ofono_radio_settings_register(rs);
return FALSE;
}
static int phonesim_radio_settings_probe(struct ofono_radio_settings *rs,
unsigned int vendor, void *data)
{
GAtChat *chat;
DBG("");
chat = g_at_chat_clone(data);
ofono_radio_settings_set_data(rs, chat);
g_idle_add(phonesim_radio_settings_register, rs);
return 0;
}
static void phonesim_radio_settings_remove(struct ofono_radio_settings *rs)
{
GAtChat *chat = ofono_radio_settings_get_data(rs);
DBG("");
ofono_radio_settings_set_data(rs, NULL);
g_at_chat_unref(chat);
}
static void phonesim_query_rat_mode(struct ofono_radio_settings *rs,
ofono_radio_settings_rat_mode_query_cb_t cb,
void *data)
{
DBG("");
CALLBACK_WITH_SUCCESS(cb, OFONO_RADIO_ACCESS_MODE_ANY, data);
}
static void phonesim_query_available_rats(struct ofono_radio_settings *rs,
ofono_radio_settings_available_rats_query_cb_t cb,
void *data)
{
uint32_t techs = 0;
DBG("");
techs |= OFONO_RADIO_ACCESS_MODE_GSM;
techs |= OFONO_RADIO_ACCESS_MODE_UMTS;
techs |= OFONO_RADIO_ACCESS_MODE_LTE;
CALLBACK_WITH_SUCCESS(cb, techs, data);
}
static struct ofono_gprs_context_driver context_driver = {
.name = "phonesim",
.probe = phonesim_context_probe,
@@ -359,6 +418,14 @@ static struct ofono_gprs_context_driver context_driver = {
.deactivate_primary = phonesim_deactivate_primary,
};
static struct ofono_radio_settings_driver radio_settings_driver = {
.name = "phonesim",
.probe = phonesim_radio_settings_probe,
.remove = phonesim_radio_settings_remove,
.query_rat_mode = phonesim_query_rat_mode,
.query_available_rats = phonesim_query_available_rats,
};
static struct ofono_ctm_driver ctm_driver = {
.name = "phonesim",
.probe = phonesim_ctm_probe,
@@ -791,6 +858,8 @@ static void phonesim_post_sim(struct ofono_modem *modem)
if (!data->calypso)
ofono_sms_create(modem, 0, "atmodem", data->chat);
ofono_radio_settings_create(modem, 0, "phonesim", data->chat);
}
static void phonesim_post_online(struct ofono_modem *modem)
@@ -1081,6 +1150,7 @@ static int phonesim_init(void)
ofono_gprs_context_driver_register(&context_driver);
ofono_ctm_driver_register(&ctm_driver);
ofono_radio_settings_driver_register(&radio_settings_driver);
if (conf_override)
parse_config(conf_override);
@@ -1103,6 +1173,7 @@ static void phonesim_exit(void)
g_slist_free(modem_list);
modem_list = NULL;
ofono_radio_settings_driver_unregister(&radio_settings_driver);
ofono_ctm_driver_unregister(&ctm_driver);
ofono_gprs_context_driver_unregister(&context_driver);

376
ofono/plugins/quectel.c Normal file
View File

@@ -0,0 +1,376 @@
/*
*
* oFono - Open Source Telephony
*
* Copyright (C) 2014 Philip Paeps. 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 <errno.h>
#include <stdlib.h>
#include <glib.h>
#include <gatchat.h>
#include <gattty.h>
#define OFONO_API_SUBJECT_TO_CHANGE
#include <ofono/plugin.h>
#include <ofono/modem.h>
#include <ofono/devinfo.h>
#include <ofono/netreg.h>
#include <ofono/sim.h>
#include <ofono/gprs.h>
#include <ofono/gprs-context.h>
#include <ofono/log.h>
#include <drivers/atmodem/atutil.h>
#include <drivers/atmodem/vendor.h>
static const char *cfun_prefix[] = { "+CFUN:", NULL };
static const char *cpin_prefix[] = { "+CPIN:", NULL };
static const char *none_prefix[] = { NULL };
struct quectel_data {
GAtChat *modem;
GAtChat *aux;
guint cpin_ready;
gboolean have_sim;
};
static void quectel_debug(const char *str, void *user_data)
{
const char *prefix = user_data;
ofono_info("%s%s", prefix, str);
}
static int quectel_probe(struct ofono_modem *modem)
{
struct quectel_data *data;
DBG("%p", modem);
data = g_try_new0(struct quectel_data, 1);
if (data == NULL)
return -ENOMEM;
ofono_modem_set_data(modem, data);
return 0;
}
static void quectel_remove(struct ofono_modem *modem)
{
struct quectel_data *data = ofono_modem_get_data(modem);
DBG("%p", modem);
if (data->cpin_ready != 0)
g_at_chat_unregister(data->aux, data->cpin_ready);
ofono_modem_set_data(modem, NULL);
g_at_chat_unref(data->aux);
g_at_chat_unref(data->modem);
g_free(data);
}
static GAtChat *open_device(struct ofono_modem *modem,
const char *key, char *debug)
{
const char *device;
GAtSyntax *syntax;
GIOChannel *channel;
GAtChat *chat;
device = ofono_modem_get_string(modem, key);
if (device == NULL)
return NULL;
DBG("%s %s", key, device);
channel = g_at_tty_open(device, NULL);
if (channel == NULL)
return NULL;
syntax = g_at_syntax_new_gsm_permissive();
chat = g_at_chat_new(channel, syntax);
g_at_syntax_unref(syntax);
g_io_channel_unref(channel);
if (chat == NULL)
return NULL;
if (getenv("OFONO_AT_DEBUG"))
g_at_chat_set_debug(chat, quectel_debug, debug);
return chat;
}
static void cpin_notify(GAtResult *result, gpointer user_data)
{
struct ofono_modem *modem = user_data;
struct quectel_data *data = ofono_modem_get_data(modem);
const char *sim_inserted;
GAtResultIter iter;
DBG("%p", modem);
g_at_result_iter_init(&iter, result);
if (!g_at_result_iter_next(&iter, "+CPIN:"))
return;
g_at_result_iter_next_unquoted_string(&iter, &sim_inserted);
if (g_strcmp0(sim_inserted, "NOT INSERTED") != 0)
data->have_sim = TRUE;
ofono_modem_set_powered(modem, TRUE);
/* Turn off the radio. */
g_at_chat_send(data->aux, "AT+CFUN=4", none_prefix, NULL, NULL, NULL);
g_at_chat_unregister(data->aux, data->cpin_ready);
data->cpin_ready = 0;
}
static void cpin_query(gboolean ok, GAtResult *result, gpointer user_data)
{
DBG("ok %d", ok);
if (ok)
cpin_notify(result, user_data);
}
static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data)
{
struct ofono_modem *modem = user_data;
struct quectel_data *data = ofono_modem_get_data(modem);
DBG("ok %d", ok);
if (!ok) {
g_at_chat_unref(data->aux);
data->aux = NULL;
g_at_chat_unref(data->modem);
data->modem = NULL;
ofono_modem_set_powered(modem, FALSE);
return;
}
data->cpin_ready = g_at_chat_register(data->aux, "+CPIN", cpin_notify,
FALSE, modem, NULL);
g_at_chat_send(data->aux, "AT+CPIN?", cpin_prefix, cpin_query,
modem, NULL);
}
static void cfun_query(gboolean ok, GAtResult *result, gpointer user_data)
{
struct ofono_modem *modem = user_data;
struct quectel_data *data = ofono_modem_get_data(modem);
GAtResultIter iter;
int status;
DBG("ok %d", ok);
if (!ok)
return;
g_at_result_iter_init(&iter, result);
if (g_at_result_iter_next(&iter, "+CFUN:") == FALSE)
return;
g_at_result_iter_next_number(&iter, &status);
/*
* The modem firmware powers up in CFUN=1 but will respond to AT+CFUN=4
* with ERROR until some amount of time (which varies with temperature)
* passes. Empirical evidence suggests that the firmware will report an
* unsolicited +CPIN: notification when it is ready to be useful.
*
* Work around this feature by only transitioning to CFUN=4 after we've
* received an unsolicited +CPIN: notification.
*/
if (status != 1) {
g_at_chat_send(data->aux, "AT+CFUN=4", none_prefix,
cfun_enable, modem, NULL);
return;
}
cfun_enable(TRUE, NULL, modem);
}
static int quectel_enable(struct ofono_modem *modem)
{
struct quectel_data *data = ofono_modem_get_data(modem);
DBG("%p", modem);
data->modem = open_device(modem, "Modem", "Modem: ");
if (data->modem == NULL)
return -EINVAL;
data->aux = open_device(modem, "Aux", "Aux: ");
if (data->aux == NULL) {
g_at_chat_unref(data->modem);
data->modem = NULL;
return -EIO;
}
g_at_chat_set_slave(data->modem, data->aux);
g_at_chat_send(data->modem, "ATE0 &C0 +CMEE=1", none_prefix,
NULL, NULL, NULL);
g_at_chat_send(data->aux, "ATE0 &C0 +CMEE=1", none_prefix,
NULL, NULL, NULL);
g_at_chat_send(data->aux, "AT+CFUN?", cfun_prefix,
cfun_query, modem, NULL);
return -EINPROGRESS;
}
static void cfun_disable(gboolean ok, GAtResult *result, gpointer user_data)
{
struct ofono_modem *modem = user_data;
struct quectel_data *data = ofono_modem_get_data(modem);
DBG("");
g_at_chat_unref(data->aux);
data->aux = NULL;
if (ok)
ofono_modem_set_powered(modem, FALSE);
}
static int quectel_disable(struct ofono_modem *modem)
{
struct quectel_data *data = ofono_modem_get_data(modem);
DBG("%p", modem);
g_at_chat_cancel_all(data->modem);
g_at_chat_unregister_all(data->modem);
g_at_chat_unref(data->modem);
data->modem = NULL;
g_at_chat_cancel_all(data->aux);
g_at_chat_unregister_all(data->aux);
g_at_chat_send(data->aux, "AT+CFUN=0", cfun_prefix,
cfun_disable, modem, NULL);
return -EINPROGRESS;
}
static void set_online_cb(gboolean ok, GAtResult *result, gpointer user_data)
{
struct cb_data *cbd = user_data;
ofono_modem_online_cb_t cb = cbd->cb;
struct ofono_error error;
decode_at_error(&error, g_at_result_final_response(result));
cb(&error, cbd->data);
}
static void quectel_set_online(struct ofono_modem *modem, ofono_bool_t online,
ofono_modem_online_cb_t cb, void *user_data)
{
struct quectel_data *data = ofono_modem_get_data(modem);
struct cb_data *cbd = cb_data_new(cb, user_data);
char const *command = online ? "AT+CFUN=1" : "AT+CFUN=4";
DBG("modem %p %s", modem, online ? "online" : "offline");
if (g_at_chat_send(data->aux, command, cfun_prefix, set_online_cb,
cbd, g_free) > 0)
return;
CALLBACK_WITH_FAILURE(cb, cbd->data);
g_free(cbd);
}
static void quectel_pre_sim(struct ofono_modem *modem)
{
struct quectel_data *data = ofono_modem_get_data(modem);
struct ofono_sim *sim;
DBG("%p", modem);
ofono_devinfo_create(modem, 0, "atmodem", data->aux);
sim = ofono_sim_create(modem, OFONO_VENDOR_QUECTEL, "atmodem",
data->aux);
if (sim && data->have_sim == TRUE)
ofono_sim_inserted_notify(sim, TRUE);
}
static void quectel_post_sim(struct ofono_modem *modem)
{
struct quectel_data *data = ofono_modem_get_data(modem);
struct ofono_gprs *gprs;
struct ofono_gprs_context *gc;
DBG("%p", modem);
gprs = ofono_gprs_create(modem, 0, "atmodem", data->aux);
gc = ofono_gprs_context_create(modem, 0, "atmodem", data->modem);
if (gprs && gc)
ofono_gprs_add_context(gprs, gc);
}
static void quectel_post_online(struct ofono_modem *modem)
{
struct quectel_data *data = ofono_modem_get_data(modem);
ofono_netreg_create(modem, 0, "atmodem", data->aux);
}
static struct ofono_modem_driver quectel_driver = {
.name = "quectel",
.probe = quectel_probe,
.remove = quectel_remove,
.enable = quectel_enable,
.disable = quectel_disable,
.set_online = quectel_set_online,
.pre_sim = quectel_pre_sim,
.post_sim = quectel_post_sim,
.post_online = quectel_post_online,
};
static int quectel_init(void)
{
return ofono_modem_driver_register(&quectel_driver);
}
static void quectel_exit(void)
{
ofono_modem_driver_unregister(&quectel_driver);
}
OFONO_PLUGIN_DEFINE(quectel, "Quectel driver", VERSION,
OFONO_PLUGIN_PRIORITY_DEFAULT, quectel_init, quectel_exit)

View File

@@ -91,7 +91,6 @@ struct ril_data {
int power_on_retries;
int sim_status_retries;
ofono_bool_t connected;
ofono_bool_t have_sim;
ofono_bool_t online;
ofono_bool_t reported;
guint timer_id;
@@ -141,17 +140,12 @@ static void sim_status_cb(struct ril_msg *message, gpointer user_data)
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)) {
DBG("have_sim = TRUE; num_apps: %d",
status.num_apps);
if (status.num_apps)
ril_util_free_sim_apps(apps, status.num_apps);
ril->have_sim = TRUE;
} else {
ofono_warn("No SIM card present.");
}
@@ -237,13 +231,8 @@ static void ril_pre_sim(struct ofono_modem *modem)
{
DBG("");
struct ril_data *ril = ofono_modem_get_data(modem);
struct ofono_sim *sim;
sim = ofono_sim_create(modem, 0, "rilmodem", ril->modem);
ofono_sim_create(modem, 0, "rilmodem", ril->modem);
ofono_voicecall_create(modem, 0, "rilmodem", ril->modem);
if (sim && ril->have_sim)
ofono_sim_inserted_notify(sim, TRUE);
}
static void ril_post_sim(struct ofono_modem *modem)
@@ -491,8 +480,6 @@ static int create_gril(struct ofono_modem *modem)
DBG(" modem: %p", modem);
struct ril_data *ril = ofono_modem_get_data(modem);
ril->have_sim = FALSE;
/* RIL expects user radio */
ril_switchUser();

292
ofono/plugins/ublox.c Normal file
View File

@@ -0,0 +1,292 @@
/*
*
* oFono - Open Source Telephony
*
* Copyright (C) 2014 Philip Paeps. 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 <errno.h>
#include <stdlib.h>
#include <glib.h>
#include <gatchat.h>
#include <gattty.h>
#define OFONO_API_SUBJECT_TO_CHANGE
#include <ofono/plugin.h>
#include <ofono/modem.h>
#include <ofono/devinfo.h>
#include <ofono/netreg.h>
#include <ofono/sim.h>
#include <ofono/gprs.h>
#include <ofono/gprs-context.h>
#include <drivers/atmodem/atutil.h>
#include <drivers/atmodem/vendor.h>
static const char *none_prefix[] = { NULL };
struct ublox_data {
GAtChat *modem;
GAtChat *aux;
};
static void ublox_debug(const char *str, void *user_data)
{
const char *prefix = user_data;
ofono_info("%s%s", prefix, str);
}
static int ublox_probe(struct ofono_modem *modem)
{
struct ublox_data *data;
DBG("%p", modem);
data = g_try_new0(struct ublox_data, 1);
if (data == NULL)
return -ENOMEM;
ofono_modem_set_data(modem, data);
return 0;
}
static void ublox_remove(struct ofono_modem *modem)
{
struct ublox_data *data = ofono_modem_get_data(modem);
DBG("%p", modem);
ofono_modem_set_data(modem, NULL);
g_at_chat_unref(data->aux);
g_at_chat_unref(data->modem);
g_free(data);
}
static GAtChat *open_device(struct ofono_modem *modem,
const char *key, char *debug)
{
const char *device;
GAtSyntax *syntax;
GIOChannel *channel;
GAtChat *chat;
device = ofono_modem_get_string(modem, key);
if (device == NULL)
return NULL;
DBG("%s %s", key, device);
channel = g_at_tty_open(device, NULL);
if (channel == NULL)
return NULL;
syntax = g_at_syntax_new_gsm_permissive();
chat = g_at_chat_new(channel, syntax);
g_at_syntax_unref(syntax);
g_io_channel_unref(channel);
if (chat == NULL)
return NULL;
if (getenv("OFONO_AT_DEBUG"))
g_at_chat_set_debug(chat, ublox_debug, debug);
return chat;
}
static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data)
{
struct ofono_modem *modem = user_data;
struct ublox_data * data = ofono_modem_get_data(modem);
DBG("ok %d", ok);
if (!ok) {
g_at_chat_unref(data->aux);
data->aux = NULL;
g_at_chat_unref(data->modem);
data->modem = NULL;
ofono_modem_set_powered(modem, FALSE);
return;
}
ofono_modem_set_powered(modem, TRUE);
}
static int ublox_enable(struct ofono_modem *modem)
{
struct ublox_data *data = ofono_modem_get_data(modem);
DBG("%p", modem);
data->modem = open_device(modem, "Modem", "Modem: ");
if (data->modem == NULL)
return -EINVAL;
data->aux = open_device(modem, "Aux", "Aux: ");
if (data->aux == NULL) {
g_at_chat_unref(data->modem);
data->modem = 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);
g_at_chat_send(data->aux, "ATE0 +CMEE=1", none_prefix,
NULL, NULL, NULL);
g_at_chat_send(data->aux, "AT+CFUN=4", none_prefix,
cfun_enable, modem, NULL);
return -EINPROGRESS;
}
static void cfun_disable(gboolean ok, GAtResult *result, gpointer user_data)
{
struct ofono_modem *modem = user_data;
struct ublox_data *data = ofono_modem_get_data(modem);
DBG("");
g_at_chat_unref(data->aux);
data->aux = NULL;
if (ok)
ofono_modem_set_powered(modem, FALSE);
}
static int ublox_disable(struct ofono_modem *modem)
{
struct ublox_data *data = ofono_modem_get_data(modem);
DBG("%p", modem);
g_at_chat_cancel_all(data->modem);
g_at_chat_unregister_all(data->modem);
g_at_chat_unref(data->modem);
data->modem = NULL;
g_at_chat_cancel_all(data->aux);
g_at_chat_unregister_all(data->aux);
g_at_chat_send(data->aux, "AT+CFUN=0", none_prefix,
cfun_disable, modem, NULL);
return -EINPROGRESS;
}
static void set_online_cb(gboolean ok, GAtResult *result, gpointer user_data)
{
struct cb_data *cbd = user_data;
ofono_modem_online_cb_t cb = cbd->cb;
struct ofono_error error;
decode_at_error(&error, g_at_result_final_response(result));
cb(&error, cbd->data);
}
static void ublox_set_online(struct ofono_modem *modem, ofono_bool_t online,
ofono_modem_online_cb_t cb, void *user_data)
{
struct ublox_data *data = ofono_modem_get_data(modem);
struct cb_data *cbd = cb_data_new(cb, user_data);
char const *command = online ? "AT+CFUN=1" : "AT+CFUN=4";
DBG("modem %p %s", modem, online ? "online" : "offline");
if (g_at_chat_send(data->aux, command, none_prefix, set_online_cb,
cbd, g_free) > 0)
return;
CALLBACK_WITH_FAILURE(cb, cbd->data);
g_free(cbd);
}
static void ublox_pre_sim(struct ofono_modem *modem)
{
struct ublox_data *data = ofono_modem_get_data(modem);
struct ofono_sim *sim;
DBG("%p", modem);
ofono_devinfo_create(modem, 0, "atmodem", data->aux);
sim = ofono_sim_create(modem, OFONO_VENDOR_UBLOX, "atmodem",
data->aux);
if (sim)
ofono_sim_inserted_notify(sim, TRUE);
}
static void ublox_post_sim(struct ofono_modem *modem)
{
struct ublox_data *data = ofono_modem_get_data(modem);
struct ofono_gprs *gprs;
struct ofono_gprs_context *gc;
DBG("%p", modem);
gprs = ofono_gprs_create(modem, OFONO_VENDOR_UBLOX, "atmodem",
data->aux);
gc = ofono_gprs_context_create(modem, OFONO_VENDOR_UBLOX, "atmodem",
data->modem);
if (gprs && gc)
ofono_gprs_add_context(gprs, gc);
}
static void ublox_post_online(struct ofono_modem *modem)
{
struct ublox_data *data = ofono_modem_get_data(modem);
ofono_netreg_create(modem, 0, "atmodem", data->aux);
}
static struct ofono_modem_driver ublox_driver = {
.name = "ublox",
.probe = ublox_probe,
.remove = ublox_remove,
.enable = ublox_enable,
.disable = ublox_disable,
.set_online = ublox_set_online,
.pre_sim = ublox_pre_sim,
.post_sim = ublox_post_sim,
.post_online = ublox_post_online,
};
static int ublox_init(void)
{
return ofono_modem_driver_register(&ublox_driver);
}
static void ublox_exit(void)
{
ofono_modem_driver_unregister(&ublox_driver);
}
OFONO_PLUGIN_DEFINE(ublox, "u-blox modem driver", VERSION,
OFONO_PLUGIN_PRIORITY_DEFAULT, ublox_init, ublox_exit)

View File

@@ -636,7 +636,7 @@ static gboolean setup_telit(struct modem_info *modem)
static gboolean setup_he910(struct modem_info *modem)
{
const char *mdm = NULL, *aux = NULL;
const char *mdm = NULL, *aux = NULL, *gps = NULL;
GSList *list;
DBG("%s", modem->syspath);
@@ -652,16 +652,19 @@ static gboolean setup_he910(struct modem_info *modem)
mdm = info->devnode;
else if (g_strcmp0(info->number, "06") == 0)
aux = info->devnode;
else if (g_strcmp0(info->number, "0a") == 0)
gps = info->devnode;
}
}
if (aux == NULL || mdm == NULL)
return FALSE;
DBG("modem=%s aux=%s", mdm, aux);
DBG("modem=%s aux=%s gps=%s", mdm, aux, gps);
ofono_modem_set_string(modem->modem, "Modem", mdm);
ofono_modem_set_string(modem->modem, "Aux", aux);
ofono_modem_set_string(modem->modem, "GPS", gps);
return TRUE;
}
@@ -791,6 +794,86 @@ static gboolean setup_samsung(struct modem_info *modem)
return TRUE;
}
static gboolean setup_quectel(struct modem_info *modem)
{
const char *aux = NULL, *mdm = NULL;
GSList *list;
DBG("%s", modem->syspath);
for (list = modem->devices; list; list = list->next) {
struct device_info *info = list->data;
DBG("%s %s %s %s", info->devnode, info->interface,
info->number, info->label);
if (g_strcmp0(info->label, "aux") == 0) {
aux = info->devnode;
if (mdm != NULL)
break;
} else if (g_strcmp0(info->label, "modem") == 0) {
mdm = info->devnode;
if (aux != NULL)
break;
} else if (g_strcmp0(info->interface, "255/255/255") == 0) {
if (g_strcmp0(info->number, "02") == 0)
aux = info->devnode;
else if (g_strcmp0(info->number, "03") == 0)
mdm = info->devnode;
}
}
if (aux == NULL || mdm == NULL)
return FALSE;
DBG("aux=%s modem=%s", aux, mdm);
ofono_modem_set_string(modem->modem, "Aux", aux);
ofono_modem_set_string(modem->modem, "Modem", mdm);
return TRUE;
}
static gboolean setup_ublox(struct modem_info *modem)
{
const char *aux = NULL, *mdm = NULL;
GSList *list;
DBG("%s", modem->syspath);
for (list = modem->devices; list; list = list->next) {
struct device_info *info = list->data;
DBG("%s %s %s %s", info->devnode, info->interface,
info->number, info->label);
if (g_strcmp0(info->label, "aux") == 0) {
aux = info->devnode;
if (mdm != NULL)
break;
} else if (g_strcmp0(info->label, "modem") == 0) {
mdm = info->devnode;
if (aux != NULL)
break;
} else if (g_strcmp0(info->interface, "2/2/1") == 0) {
if (g_strcmp0(info->number, "02") == 0)
aux = info->devnode;
else if (g_strcmp0(info->number, "00") == 0)
mdm = info->devnode;
}
}
if (aux == NULL || mdm == NULL)
return FALSE;
DBG("aux=%s modem=%s", aux, mdm);
ofono_modem_set_string(modem->modem, "Aux", aux);
ofono_modem_set_string(modem->modem, "Modem", mdm);
return TRUE;
}
static struct {
const char *name;
gboolean (*setup)(struct modem_info *modem);
@@ -815,6 +898,8 @@ static struct {
{ "zte", setup_zte },
{ "icera", setup_icera },
{ "samsung", setup_samsung },
{ "quectel", setup_quectel },
{ "ublox", setup_ublox },
{ }
};
@@ -1026,6 +1111,8 @@ static struct {
{ "nokia", "option", "0421", "0623" },
{ "samsung", "option", "04e8", "6889" },
{ "samsung", "kalmia" },
{ "quectel", "option", "05c6", "9090" },
{ "ublox", "cdc_acm", "1546", "1102" },
{ }
};

View File

@@ -26,6 +26,7 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>
#include <glib.h>
@@ -42,17 +43,18 @@ struct ofono_emulator {
enum ofono_emulator_type type;
GAtServer *server;
GAtPPP *ppp;
gboolean slc;
int l_features;
int r_features;
int events_mode;
gboolean events_ind;
unsigned char cmee_mode;
GSList *indicators;
guint callsetup_source;
gboolean clip;
gboolean ccwa;
int pns_id;
bool slc : 1;
unsigned int events_mode : 2;
bool events_ind : 1;
unsigned int cmee_mode : 2;
bool clip : 1;
bool ccwa : 1;
bool ddr_active : 1;
};
struct indicator {
@@ -453,7 +455,7 @@ static void brsf_cb(GAtServer *server, GAtServerRequestType type,
if (g_at_result_iter_next_number(&iter, &val) == FALSE)
goto fail;
if (val < 0 || val > 255)
if (val < 0 || val > 0xffff)
goto fail;
em->r_features = val;
@@ -636,7 +638,8 @@ done:
g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
em->slc = TRUE;
__ofono_emulator_slc_condition(em,
OFONO_EMULATOR_SLC_CONDITION_CMER);
break;
}
@@ -826,6 +829,113 @@ fail:
}
}
static void bind_cb(GAtServer *server, GAtServerRequestType type,
GAtResult *result, gpointer user_data)
{
struct ofono_emulator *em = user_data;
char buf[128];
switch (type) {
case G_AT_SERVER_REQUEST_TYPE_QUERY:
g_at_server_send_info(em->server, "+BIND: 1,1", TRUE);
g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
__ofono_emulator_slc_condition(em,
OFONO_EMULATOR_SLC_CONDITION_BIND);
break;
case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
sprintf(buf, "+BIND: (1)");
g_at_server_send_info(em->server, buf, TRUE);
g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
break;
case G_AT_SERVER_REQUEST_TYPE_SET:
{
GAtResultIter iter;
int hf_indicator;
int num_hf_indicators = 0;
g_at_result_iter_init(&iter, result);
g_at_result_iter_next(&iter, "");
/* check validity of the request */
while (num_hf_indicators < 20 &&
g_at_result_iter_next_number(&iter,
&hf_indicator)) {
if (hf_indicator > 0xffff)
goto fail;
num_hf_indicators += 1;
}
/* Check that we have nothing extra in the stream */
if (g_at_result_iter_skip_next(&iter) == TRUE)
goto fail;
/* request is valid, update the indicator activation status */
g_at_result_iter_init(&iter, result);
g_at_result_iter_next(&iter, "");
while (g_at_result_iter_next_number(&iter, &hf_indicator))
ofono_info("HF supports indicator: 0x%04x",
hf_indicator);
g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
break;
}
default:
fail:
g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
break;
}
}
static void biev_cb(GAtServer *server, GAtServerRequestType type,
GAtResult *result, gpointer user_data)
{
struct ofono_emulator *em = user_data;
switch (type) {
case G_AT_SERVER_REQUEST_TYPE_SET:
{
GAtResultIter iter;
int hf_indicator;
int val;
g_at_result_iter_init(&iter, result);
g_at_result_iter_next(&iter, "");
if (g_at_result_iter_next_number(&iter, &hf_indicator) == FALSE)
goto fail;
if (hf_indicator != HFP_HF_INDICATOR_ENHANCED_SAFETY)
goto fail;
if (em->ddr_active == FALSE)
goto fail;
if (g_at_result_iter_next_number(&iter, &val) == FALSE)
goto fail;
if (val < 0 || val > 1)
goto fail;
ofono_info("Enhanced Safety indicator: %d", val);
g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
break;
}
default:
fail:
g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
break;
}
}
static void emulator_add_indicator(struct ofono_emulator *em, const char* name,
int min, int max, int dflt,
gboolean mandatory)
@@ -906,6 +1016,8 @@ void ofono_emulator_register(struct ofono_emulator *em, int fd)
em);
if (em->type == OFONO_EMULATOR_TYPE_HFP) {
em->ddr_active = true;
emulator_add_indicator(em, OFONO_EMULATOR_IND_SERVICE, 0, 1, 0,
FALSE);
emulator_add_indicator(em, OFONO_EMULATOR_IND_CALL, 0, 1, 0,
@@ -928,6 +1040,8 @@ void ofono_emulator_register(struct ofono_emulator *em, int fd)
g_at_server_register(em->server, "+CCWA", ccwa_cb, em, NULL);
g_at_server_register(em->server, "+CMEE", cmee_cb, em, NULL);
g_at_server_register(em->server, "+BIA", bia_cb, em, NULL);
g_at_server_register(em->server, "+BIND", bind_cb, em, NULL);
g_at_server_register(em->server, "+BIEV", biev_cb, em, NULL);
}
__ofono_atom_register(em->atom, emulator_unregister);
@@ -981,6 +1095,7 @@ struct ofono_emulator *ofono_emulator_create(struct ofono_modem *modem,
em->l_features |= HFP_AG_FEATURE_ENHANCED_CALL_STATUS;
em->l_features |= HFP_AG_FEATURE_ENHANCED_CALL_CONTROL;
em->l_features |= HFP_AG_FEATURE_EXTENDED_RES_CODE;
em->l_features |= HFP_AG_FEATURE_HF_INDICATORS;
em->events_mode = 3; /* default mode is forwarding events */
em->cmee_mode = 0; /* CME ERROR disabled by default */
@@ -1072,16 +1187,11 @@ struct ofono_emulator_request {
};
static void handler_proxy(GAtServer *server, GAtServerRequestType type,
GAtResult *result, gpointer userdata)
GAtResult *result, gpointer userdata)
{
struct handler *h = userdata;
struct ofono_emulator_request req;
if (h->em->type == OFONO_EMULATOR_TYPE_HFP && h->em->slc == FALSE) {
g_at_server_send_final(h->em->server, G_AT_SERVER_RESULT_ERROR);
return;
}
switch (type) {
case G_AT_SERVER_REQUEST_TYPE_COMMAND_ONLY:
req.type = OFONO_EMULATOR_REQUEST_TYPE_COMMAND_ONLY;
@@ -1102,6 +1212,33 @@ static void handler_proxy(GAtServer *server, GAtServerRequestType type,
h->cb(h->em, &req, h->data);
}
static void handler_proxy_need_slc(GAtServer *server,
GAtServerRequestType type,
GAtResult *result, gpointer userdata)
{
struct handler *h = userdata;
if (h->em->slc == FALSE) {
g_at_server_send_final(h->em->server, G_AT_SERVER_RESULT_ERROR);
return;
}
handler_proxy(server, type, result, userdata);
}
static void handler_proxy_chld(GAtServer *server, GAtServerRequestType type,
GAtResult *result, gpointer userdata)
{
struct handler *h = userdata;
if (h->em->slc == FALSE && type != G_AT_SERVER_REQUEST_TYPE_SUPPORT) {
g_at_server_send_final(h->em->server, G_AT_SERVER_RESULT_ERROR);
return;
}
handler_proxy(server, type, result, userdata);
}
static void handler_destroy(gpointer userdata)
{
struct handler *h = userdata;
@@ -1118,6 +1255,7 @@ ofono_bool_t ofono_emulator_add_handler(struct ofono_emulator *em,
void *data, ofono_destroy_func destroy)
{
struct handler *h;
GAtServerNotifyFunc func = handler_proxy;
h = g_new0(struct handler, 1);
h->cb = cb;
@@ -1125,7 +1263,14 @@ ofono_bool_t ofono_emulator_add_handler(struct ofono_emulator *em,
h->destroy = destroy;
h->em = em;
if (g_at_server_register(em->server, prefix, handler_proxy, h,
if (em->type == OFONO_EMULATOR_TYPE_HFP) {
func = handler_proxy_need_slc;
if (!strcmp(prefix, "+CHLD"))
func = handler_proxy_chld;
}
if (g_at_server_register(em->server, prefix, func, h,
handler_destroy) == TRUE)
return TRUE;
@@ -1266,3 +1411,52 @@ void __ofono_emulator_set_indicator_forced(struct ofono_emulator *em,
ind->deferred = TRUE;
}
}
void __ofono_emulator_slc_condition(struct ofono_emulator *em,
enum ofono_emulator_slc_condition cond)
{
if (em->slc == TRUE)
return;
switch (cond) {
case OFONO_EMULATOR_SLC_CONDITION_CMER:
if ((em->r_features & HFP_HF_FEATURE_3WAY) &&
(em->l_features & HFP_AG_FEATURE_3WAY))
return;
/* Fall Through */
case OFONO_EMULATOR_SLC_CONDITION_CHLD:
if ((em->r_features & HFP_HF_FEATURE_HF_INDICATORS) &&
(em->l_features & HFP_HF_FEATURE_HF_INDICATORS))
return;
/* Fall Through */
case OFONO_EMULATOR_SLC_CONDITION_BIND:
ofono_info("SLC reached");
em->slc = TRUE;
default:
break;
}
}
void ofono_emulator_set_hf_indicator_active(struct ofono_emulator *em,
int indicator,
ofono_bool_t active)
{
char buf[64];
if (!(em->l_features & HFP_HF_FEATURE_HF_INDICATORS))
return;
if (!(em->r_features & HFP_HF_FEATURE_HF_INDICATORS))
return;
if (indicator != HFP_HF_INDICATOR_ENHANCED_SAFETY)
return;
em->ddr_active = active;
sprintf(buf, "+BIND: %d,%d", HFP_HF_INDICATOR_ENHANCED_SAFETY, active);
g_at_server_send_unsolicited(em->server, buf);
}

View File

@@ -268,6 +268,32 @@ static gboolean gprs_proto_from_string(const char *str,
return FALSE;
}
static const char *gprs_auth_method_to_string(enum ofono_gprs_auth_method auth)
{
switch (auth) {
case OFONO_GPRS_AUTH_METHOD_CHAP:
return "chap";
case OFONO_GPRS_AUTH_METHOD_PAP:
return "pap";
};
return NULL;
}
static gboolean gprs_auth_method_from_string(const char *str,
enum ofono_gprs_auth_method *auth)
{
if (g_str_equal(str, "chap")) {
*auth = OFONO_GPRS_AUTH_METHOD_CHAP;
return TRUE;
} else if (g_str_equal(str, "pap")) {
*auth = OFONO_GPRS_AUTH_METHOD_PAP;
return TRUE;
}
return FALSE;
}
static unsigned int gprs_cid_alloc(struct ofono_gprs *gprs)
{
return idmap_alloc(gprs->cid_map);
@@ -1040,6 +1066,10 @@ static void append_context_properties(struct pri_context *ctx,
ofono_dbus_dict_append(dict, "Password", DBUS_TYPE_STRING,
&strvalue);
strvalue = gprs_auth_method_to_string(ctx->context.auth_method);
ofono_dbus_dict_append(dict, "AuthenticationMethod", DBUS_TYPE_STRING,
&strvalue);
if (ctx->type == OFONO_GPRS_CONTEXT_TYPE_MMS) {
strvalue = ctx->message_proxy;
ofono_dbus_dict_append(dict, "MessageProxy",
@@ -1385,6 +1415,37 @@ static DBusMessage *pri_set_message_center(struct pri_context *ctx,
return NULL;
}
static DBusMessage *pri_set_auth_method(struct pri_context *ctx,
DBusConnection *conn,
DBusMessage *msg, const char *str)
{
GKeyFile *settings = ctx->gprs->settings;
enum ofono_gprs_auth_method auth;
if (gprs_auth_method_from_string(str, &auth) == FALSE)
return __ofono_error_invalid_format(msg);
if (ctx->context.auth_method == auth)
return dbus_message_new_method_return(msg);
ctx->context.auth_method = auth;
if (settings) {
g_key_file_set_string(settings, ctx->key,
"AuthenticationMethod", str);
storage_sync(ctx->gprs->imsi, SETTINGS_STORE, settings);
}
g_dbus_send_reply(conn, msg, DBUS_TYPE_INVALID);
ofono_dbus_signal_property_changed(conn, ctx->path,
OFONO_CONNECTION_CONTEXT_INTERFACE,
"AuthenticationMethod",
DBUS_TYPE_STRING, &str);
return NULL;
}
static DBusMessage *pri_set_property(DBusConnection *conn,
DBusMessage *msg, void *data)
{
@@ -1495,6 +1556,13 @@ static DBusMessage *pri_set_property(DBusConnection *conn,
dbus_message_iter_get_basic(&var, &str);
return pri_set_name(ctx, conn, msg, str);
} else if (!strcmp(property, "AuthenticationMethod")) {
if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_STRING)
return __ofono_error_invalid_args(msg);
dbus_message_iter_get_basic(&var, &str);
return pri_set_auth_method(ctx, conn, msg, str);
}
if (ctx->type != OFONO_GPRS_CONTEXT_TYPE_MMS)
@@ -1982,6 +2050,8 @@ static DBusMessage *gprs_set_property(DBusConnection *conn,
static void write_context_settings(struct ofono_gprs *gprs,
struct pri_context *context)
{
const char *auth_method;
g_key_file_set_string(gprs->settings, context->key,
"Name", context->name);
g_key_file_set_string(gprs->settings, context->key,
@@ -1990,6 +2060,11 @@ static void write_context_settings(struct ofono_gprs *gprs,
"Username", context->context.username);
g_key_file_set_string(gprs->settings, context->key,
"Password", context->context.password);
auth_method = gprs_auth_method_to_string(context->context.auth_method);
g_key_file_set_string(gprs->settings, context->key,
"AuthenticationMethod", auth_method);
g_key_file_set_string(gprs->settings, context->key, "Type",
gprs_context_type_to_string(context->type));
g_key_file_set_string(gprs->settings, context->key, "Protocol",
@@ -2959,11 +3034,13 @@ static gboolean load_context(struct ofono_gprs *gprs, const char *group)
char *apn = NULL;
char *msgproxy = NULL;
char *msgcenter = NULL;
char *authstr = NULL;
gboolean ret = FALSE;
gboolean legacy = FALSE;
struct pri_context *context;
enum ofono_gprs_context_type type;
enum ofono_gprs_proto proto;
enum ofono_gprs_auth_method auth;
unsigned int id;
if (sscanf(group, "context%d", &id) != 1) {
@@ -3008,6 +3085,14 @@ static gboolean load_context(struct ofono_gprs *gprs, const char *group)
if (password == NULL)
goto error;
authstr = g_key_file_get_string(gprs->settings, group,
"AuthenticationMethod", NULL);
if (authstr == NULL)
authstr = g_strdup("chap");
if (gprs_auth_method_from_string(authstr, &auth) == FALSE)
goto error;
if (strlen(password) > OFONO_GPRS_MAX_PASSWORD_LENGTH)
goto error;
@@ -3044,6 +3129,7 @@ static gboolean load_context(struct ofono_gprs *gprs, const char *group)
strcpy(context->context.password, password);
strcpy(context->context.apn, apn);
context->context.proto = proto;
context->context.auth_method = auth;
if (msgproxy != NULL)
strcpy(context->message_proxy, msgproxy);
@@ -3073,6 +3159,7 @@ error:
g_free(apn);
g_free(msgproxy);
g_free(msgcenter);
g_free(authstr);
return ret;
}
@@ -3204,6 +3291,8 @@ static void provision_context(const struct ofono_gprs_provision_data *ap,
if (ap->password != NULL)
strcpy(context->context.password, ap->password);
context->context.auth_method = ap->auth_method;
strcpy(context->context.apn, ap->apn);
context->context.proto = ap->proto;

View File

@@ -72,10 +72,10 @@ static ofono_bool_t transparent_sco = FALSE;
static uint16_t codec2setting(uint8_t codec)
{
switch (codec) {
case HFP_CODEC_CVSD:
return BT_VOICE_CVSD_16BIT;
default:
return BT_VOICE_TRANSPARENT;
case HFP_CODEC_CVSD:
return BT_VOICE_CVSD_16BIT;
default:
return BT_VOICE_TRANSPARENT;
}
}

View File

@@ -51,6 +51,12 @@ struct ofono_handsfree {
ofono_bool_t inband_ringing;
ofono_bool_t voice_recognition;
ofono_bool_t voice_recognition_pending;
ofono_bool_t ddr;
ofono_bool_t ddr_pending;
ofono_bool_t have_ddr;
ofono_bool_t ddr_active;
unsigned int ag_features;
unsigned int ag_chld_features;
unsigned char battchg;
@@ -96,6 +102,9 @@ static const char **ag_features_list(unsigned int features,
if (chld_features & HFP_AG_CHLD_4)
list[i++] = "transfer";
if (features & HFP_AG_FEATURE_HF_INDICATORS)
list[i++] = "hf-indicators";
list[i] = NULL;
return list;
@@ -244,6 +253,10 @@ static DBusMessage *generate_get_properties_reply(struct ofono_handsfree *hf,
ofono_dbus_dict_append(&dict, "EchoCancelingNoiseReduction",
DBUS_TYPE_BOOLEAN, &hf->nrec);
if (hf->ag_features & HFP_AG_FEATURE_HF_INDICATORS)
ofono_dbus_dict_append(&dict, "DistractedDrivingReduction",
DBUS_TYPE_BOOLEAN, &hf->ddr);
voice_recognition = hf->voice_recognition;
ofono_dbus_dict_append(&dict, "VoiceRecognition", DBUS_TYPE_BOOLEAN,
&voice_recognition);
@@ -356,6 +369,82 @@ static void voicerec_set_cb(const struct ofono_error *error, void *data)
&hf->voice_recognition);
}
static void ddr_set_cb(const struct ofono_error *error, void *data)
{
struct ofono_handsfree *hf = data;
DBusConnection *conn = ofono_dbus_get_connection();
const char *path = __ofono_atom_get_path(hf->atom);
if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
__ofono_dbus_pending_reply(&hf->pending,
__ofono_error_failed(hf->pending));
return;
}
hf->ddr = hf->ddr_pending;
__ofono_dbus_pending_reply(&hf->pending,
dbus_message_new_method_return(hf->pending));
ofono_dbus_signal_property_changed(conn, path,
OFONO_HANDSFREE_INTERFACE,
"DistractedDrivingReduction",
DBUS_TYPE_BOOLEAN,
&hf->voice_recognition);
}
void ofono_handsfree_set_hf_indicators(struct ofono_handsfree *hf,
const unsigned short *indicators,
unsigned int num)
{
unsigned int i;
for (i = 0; i < num; i++) {
switch (indicators[i]) {
case HFP_HF_INDICATOR_ENHANCED_SAFETY:
hf->have_ddr = TRUE;
break;
}
}
}
static void ddr_update_cb(const struct ofono_error *error, void *data)
{
if (error->type == OFONO_ERROR_TYPE_NO_ERROR)
return;
ofono_info("Failed to update DDR indicator");
}
void ofono_handsfree_hf_indicator_active_notify(struct ofono_handsfree *hf,
unsigned int indicator,
ofono_bool_t active)
{
DBG("%d, %d", indicator, active);
if (active)
active = TRUE;
else
active = FALSE;
switch (indicator) {
case HFP_HF_INDICATOR_ENHANCED_SAFETY:
if (!hf->have_ddr)
return;
if (hf->ddr_active == active)
return;
hf->ddr_active = active;
if (hf->ddr_active && hf->driver && hf->driver->hf_indicator)
hf->driver->hf_indicator(hf,
HFP_HF_INDICATOR_ENHANCED_SAFETY,
hf->ddr, ddr_update_cb, hf);
break;
}
}
static void nrec_set_cb(const struct ofono_error *error, void *data)
{
struct ofono_handsfree *hf = data;
@@ -434,6 +523,37 @@ static DBusMessage *handsfree_set_property(DBusConnection *conn,
hf->pending = dbus_message_ref(msg);
hf->driver->disable_nrec(hf, nrec_set_cb, hf);
} else if (g_str_equal(name, "DistractedDrivingReduction") == TRUE) {
if (!(hf->ag_features & HFP_AG_FEATURE_HF_INDICATORS))
return __ofono_error_not_supported(msg);
if (!hf->driver->hf_indicator)
return __ofono_error_not_implemented(msg);
if (!hf->have_ddr)
return __ofono_error_not_supported(msg);
if (hf->ddr == enabled)
return dbus_message_new_method_return(msg);
if (!hf->ddr_active) {
hf->ddr = enabled;
g_dbus_send_reply(conn, msg, DBUS_TYPE_INVALID);
ofono_dbus_signal_property_changed(conn,
__ofono_atom_get_path(hf->atom),
OFONO_HANDSFREE_INTERFACE,
"DistractedDrivingReduction",
DBUS_TYPE_BOOLEAN,
&hf->voice_recognition);
} else {
hf->pending = dbus_message_ref(msg);
hf->ddr_pending = enabled;
hf->driver->hf_indicator(hf,
HFP_HF_INDICATOR_ENHANCED_SAFETY,
enabled, ddr_set_cb, hf);
}
} else
return __ofono_error_invalid_args(msg);

View File

@@ -31,6 +31,7 @@ enum hfp_ag_feature {
HFP_AG_FEATURE_ENHANCED_CALL_CONTROL = 0x80,
HFP_AG_FEATURE_EXTENDED_RES_CODE = 0x100,
HFP_AG_FEATURE_CODEC_NEGOTIATION = 0x200,
HFP_AG_FEATURE_HF_INDICATORS = 0x400,
};
/* HFP HF supported features bitmap. Bluetooth HFP 1.6 spec page 88 */
@@ -43,6 +44,7 @@ enum hfp_hf_feature {
HFP_HF_FEATURE_ENHANCED_CALL_STATUS = 0x20,
HFP_HF_FEATURE_ENHANCED_CALL_CONTROL = 0x40,
HFP_HF_FEATURE_CODEC_NEGOTIATION = 0x80,
HFP_HF_FEATURE_HF_INDICATORS = 0x100,
};
/* HFP AG supported call hold and multiparty services bitmap. Bluetooth HFP 1.6 spec page 76 */
@@ -83,5 +85,10 @@ enum hfp_codec {
enum hfp_version {
HFP_VERSION_1_5 = 0x0105,
HFP_VERSION_1_6 = 0x0106,
HFP_VERSION_LATEST = HFP_VERSION_1_6,
HFP_VERSION_1_7 = 0x0107,
HFP_VERSION_LATEST = HFP_VERSION_1_7,
};
enum hfp_hf_indicator {
HFP_HF_INDICATOR_ENHANCED_SAFETY = 0x0001,
};

View File

@@ -507,8 +507,17 @@ void __ofono_gprs_provision_free_settings(
int count);
#include <ofono/emulator.h>
enum ofono_emulator_slc_condition {
OFONO_EMULATOR_SLC_CONDITION_CMER,
OFONO_EMULATOR_SLC_CONDITION_CHLD,
OFONO_EMULATOR_SLC_CONDITION_BIND,
};
void __ofono_emulator_set_indicator_forced(struct ofono_emulator *em,
const char *name, int value);
void __ofono_emulator_slc_condition(struct ofono_emulator *em,
enum ofono_emulator_slc_condition cond);
#include <ofono/gnss.h>
#include <ofono/cdma-sms.h>

View File

@@ -26,6 +26,7 @@
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <stdint.h>
#include <glib.h>
#include <gdbus.h>
@@ -48,6 +49,7 @@ struct ofono_radio_settings {
enum ofono_radio_band_gsm pending_band_gsm;
enum ofono_radio_band_umts pending_band_umts;
ofono_bool_t fast_dormancy_pending;
uint32_t available_rats;
const struct ofono_radio_settings_driver *driver;
void *driver_data;
struct ofono_atom *atom;
@@ -222,6 +224,27 @@ static DBusMessage *radio_get_properties_reply(DBusMessage *msg,
DBUS_TYPE_BOOLEAN, &value);
}
if (rs->available_rats) {
const char *rats[sizeof(uint32_t) * CHAR_BIT + 1];
const char **dbus_rats = rats;
int n = 0;
unsigned int i;
for (i = 0; i < sizeof(uint32_t) * CHAR_BIT; i++) {
int tech = 1 << i;
if (!(rs->available_rats & tech))
continue;
rats[n++] = radio_access_mode_to_string(tech);
}
rats[n] = NULL;
ofono_dbus_dict_append_array(&dict, "AvailableTechnologies",
DBUS_TYPE_STRING, &dbus_rats);
}
dbus_message_iter_close_container(&iter, &dict);
return reply;
@@ -374,6 +397,32 @@ static void radio_send_properties_reply(struct ofono_radio_settings *rs)
__ofono_dbus_pending_reply(&rs->pending, reply);
}
static void radio_available_rats_query_callback(const struct ofono_error *error,
unsigned int available_rats,
void *data)
{
struct ofono_radio_settings *rs = data;
if (error->type == OFONO_ERROR_TYPE_NO_ERROR)
rs->available_rats = available_rats & 0x7;
else
DBG("Error while querying available rats");
radio_send_properties_reply(rs);
}
static void radio_query_available_rats(struct ofono_radio_settings *rs)
{
/* Modem technology is not supposed to change, so one query is enough */
if (rs->driver->query_available_rats == NULL || rs->available_rats) {
radio_send_properties_reply(rs);
return;
}
rs->driver->query_available_rats(
rs, radio_available_rats_query_callback, rs);
}
static void radio_fast_dormancy_query_callback(const struct ofono_error *error,
ofono_bool_t enable, void *data)
{
@@ -390,13 +439,13 @@ static void radio_fast_dormancy_query_callback(const struct ofono_error *error,
}
radio_set_fast_dormancy(rs, enable);
radio_send_properties_reply(rs);
radio_query_available_rats(rs);
}
static void radio_query_fast_dormancy(struct ofono_radio_settings *rs)
{
if (rs->driver->query_fast_dormancy == NULL) {
radio_send_properties_reply(rs);
radio_query_available_rats(rs);
return;
}

View File

@@ -267,10 +267,12 @@ static char **get_locked_pins(struct ofono_sim *sim)
return ret;
}
static void **get_pin_retries(struct ofono_sim *sim)
static void get_pin_retries(struct ofono_sim *sim, void ***out_dict,
unsigned char **out_retries)
{
int i, nelem;
void **ret;
void **dict;
unsigned char *retries;
for (i = 1, nelem = 0; i < OFONO_SIM_PASSWORD_INVALID; i++) {
if (sim->pin_retries[i] == -1)
@@ -279,17 +281,22 @@ static void **get_pin_retries(struct ofono_sim *sim)
nelem += 1;
}
ret = g_new0(void *, nelem * 2 + 1);
dict = g_new0(void *, nelem * 2 + 1);
retries = g_new0(unsigned char, nelem);
for (i = 1, nelem = 0; i < OFONO_SIM_PASSWORD_INVALID; i++) {
if (sim->pin_retries[i] == -1)
continue;
ret[nelem++] = (void *) sim_passwd_name(i);
ret[nelem++] = &sim->pin_retries[i];
retries[nelem] = sim->pin_retries[i];
dict[nelem * 2] = (void *) sim_passwd_name(i);
dict[nelem * 2 + 1] = &retries[nelem];
nelem += 1;
}
return ret;
*out_dict = dict;
*out_retries = retries;
}
static char **get_service_numbers(GSList *service_numbers)
@@ -344,7 +351,8 @@ static DBusMessage *sim_get_properties(DBusConnection *conn,
char **service_numbers;
char **locked_pins;
const char *pin_name;
void **pin_retries;
void **pin_retries_dict;
unsigned char *dbus_retries;
dbus_bool_t present = sim->state != OFONO_SIM_STATE_NOT_PRESENT;
dbus_bool_t fdn;
dbus_bool_t bdn;
@@ -419,10 +427,11 @@ static DBusMessage *sim_get_properties(DBusConnection *conn,
DBUS_TYPE_STRING,
(void *) &pin_name);
pin_retries = get_pin_retries(sim);
get_pin_retries(sim, &pin_retries_dict, &dbus_retries);
ofono_dbus_dict_append_dict(&dict, "Retries", DBUS_TYPE_BYTE,
&pin_retries);
g_free(pin_retries);
&pin_retries_dict);
g_free(pin_retries_dict);
g_free(dbus_retries);
done:
dbus_message_iter_close_container(&iter, &dict);
@@ -437,7 +446,8 @@ static void sim_pin_retries_query_cb(const struct ofono_error *error,
struct ofono_sim *sim = data;
DBusConnection *conn = ofono_dbus_get_connection();
const char *path = __ofono_atom_get_path(sim->atom);
void **pin_retries;
void **pin_retries_dict;
unsigned char *dbus_retries;
if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
ofono_error("Querying remaining pin retries failed");
@@ -449,11 +459,12 @@ static void sim_pin_retries_query_cb(const struct ofono_error *error,
memcpy(sim->pin_retries, retries, sizeof(sim->pin_retries));
pin_retries = get_pin_retries(sim);
get_pin_retries(sim, &pin_retries_dict, &dbus_retries);
ofono_dbus_signal_dict_property_changed(conn, path,
OFONO_SIM_MANAGER_INTERFACE, "Retries",
DBUS_TYPE_BYTE, &pin_retries);
g_free(pin_retries);
DBUS_TYPE_BYTE, &pin_retries_dict);
g_free(pin_retries_dict);
g_free(dbus_retries);
}
static void sim_pin_retries_check(struct ofono_sim *sim)

View File

@@ -3431,6 +3431,10 @@ static void emulator_chld_cb(struct ofono_emulator *em,
ofono_emulator_send_info(em, buf, TRUE);
result.type = OFONO_ERROR_TYPE_NO_ERROR;
__ofono_emulator_slc_condition(em,
OFONO_EMULATOR_SLC_CONDITION_CHLD);
break;
case OFONO_EMULATOR_REQUEST_TYPE_QUERY:

View File

@@ -5,36 +5,53 @@ import dbus
bus = dbus.SystemBus()
manager = dbus.Interface(bus.get_object('org.ofono', '/'),
'org.ofono.Manager')
manager = dbus.Interface(bus.get_object('org.ofono', '/'), 'org.ofono.Manager')
modems = manager.GetModems()
for path, properties in modems:
if "org.ofono.ConnectionManager" not in properties["Interfaces"]:
continue
connman = dbus.Interface(bus.get_object('org.ofono', path),
'org.ofono.ConnectionManager')
contexts = connman.GetContexts()
if (len(contexts) == 0):
print("No context available")
sys.exit(1)
connman.SetProperty("Powered", dbus.Boolean(1))
if len(sys.argv) > 1:
path = contexts[int(sys.argv[1])][0]
else:
path = contexts[0][0]
context = dbus.Interface(bus.get_object('org.ofono', path),
'org.ofono.ConnectionContext')
try:
context.SetProperty("Active", dbus.Boolean(1), timeout = 100)
except dbus.DBusException as e:
print("Error activating %s: %s" % (path, str(e)))
if (len(sys.argv) == 3):
modem = sys.argv[1]
context_idx = int(sys.argv[2]) - 1
else:
modem = None
modems = manager.GetModems()
for path, properties in modems:
if "org.ofono.ConnectionManager" in properties["Interfaces"]:
modem = path
break
if (modem is None):
exit(2)
if (len(sys.argv) == 1):
context_idx = 0
elif (len(sys.argv) == 2):
context_idx = int(sys.argv[1]) - 1
else:
print("Usage: %s [modem] [context_number]" % (sys.argv[0]))
exit(1)
modemapi = dbus.Interface(bus.get_object('org.ofono', modem), 'org.ofono.Modem')
properties = modemapi.GetProperties()
if "org.ofono.ConnectionManager" not in properties["Interfaces"]:
print("org.ofono.ConnectionManager not found")
exit(2)
connman = dbus.Interface(bus.get_object('org.ofono', modem),
'org.ofono.ConnectionManager')
contexts = connman.GetContexts()
if (len(contexts) == 0):
print("No context available")
exit(1)
connman.SetProperty("Powered", dbus.Boolean(1))
path = contexts[context_idx][0]
context = dbus.Interface(bus.get_object('org.ofono', path),
'org.ofono.ConnectionContext')
try:
context.SetProperty("Active", dbus.Boolean(1), timeout = 100)
except dbus.DBusException as e:
print("Error activating %s: %s" % (path, str(e)))
exit(2)

View File

@@ -8,12 +8,14 @@ bus = dbus.SystemBus()
manager = dbus.Interface(bus.get_object('org.ofono', '/'),
'org.ofono.Manager')
modems = manager.GetModems()
path = modems[0][0]
if (len(sys.argv) == 2):
if (len(sys.argv) == 1):
modems = manager.GetModems()
path = modems[0][0]
elif (len(sys.argv) == 2):
path = sys.argv[1]
else:
print("Usage: %s [modem]" % (sys.argv[0]))
sys.exit(1)
manager = dbus.Interface(bus.get_object('org.ofono', path),
'org.ofono.VoiceCallManager')

View File

@@ -5,34 +5,51 @@ import dbus
bus = dbus.SystemBus()
manager = dbus.Interface(bus.get_object('org.ofono', '/'),
'org.ofono.Manager')
manager = dbus.Interface(bus.get_object('org.ofono', '/'), 'org.ofono.Manager')
modems = manager.GetModems()
for path, properties in modems:
if "org.ofono.ConnectionManager" not in properties["Interfaces"]:
continue
connman = dbus.Interface(bus.get_object('org.ofono', path),
'org.ofono.ConnectionManager')
contexts = connman.GetContexts()
if (len(contexts) == 0):
print("No context available")
sys.exit(1)
if len(sys.argv) > 1:
path = contexts[int(sys.argv[1])][0]
else:
path = contexts[0][0]
context = dbus.Interface(bus.get_object('org.ofono', path),
'org.ofono.ConnectionContext')
try:
context.SetProperty("Active", dbus.Boolean(0))
except dbus.DBusException as e:
print("Error activating %s: %s" % (path, str(e)))
if (len(sys.argv) == 3):
modem = sys.argv[1]
context_idx = int(sys.argv[2]) - 1
else:
modem = None
modems = manager.GetModems()
for path, properties in modems:
if "org.ofono.ConnectionManager" in properties["Interfaces"]:
modem = path
break
if (modem is None):
exit(2)
if (len(sys.argv) == 1):
context_idx = 0
elif (len(sys.argv) == 2):
context_idx = int(sys.argv[1]) - 1
else:
print("Usage: %s [modem] [context_number]" % (sys.argv[0]))
exit(1)
modemapi = dbus.Interface(bus.get_object('org.ofono', modem), 'org.ofono.Modem')
properties = modemapi.GetProperties()
if "org.ofono.ConnectionManager" not in properties["Interfaces"]:
print("org.ofono.ConnectionManager not found")
exit(2)
connman = dbus.Interface(bus.get_object('org.ofono', modem),
'org.ofono.ConnectionManager')
contexts = connman.GetContexts()
if (len(contexts) == 0):
print("No context available")
sys.exit(1)
path = contexts[context_idx][0]
context = dbus.Interface(bus.get_object('org.ofono', path),
'org.ofono.ConnectionContext')
try:
context.SetProperty("Active", dbus.Boolean(0))
except dbus.DBusException as e:
print("Error deactivating %s: %s" % (path, str(e)))
exit(2)

View File

@@ -8,8 +8,14 @@ bus = dbus.SystemBus()
manager = dbus.Interface(bus.get_object('org.ofono', '/'),
'org.ofono.Manager')
modems = manager.GetModems()
path = modems[0][0]
if (len(sys.argv) == 1):
modems = manager.GetModems()
path = modems[0][0]
elif (len(sys.argv) == 2):
path = sys.argv[1]
else:
print("Usage: %s [modem]" % (sys.argv[0]))
sys.exit(1)
manager = dbus.Interface(bus.get_object('org.ofono', path),
'org.ofono.VoiceCallManager')

View File

@@ -40,7 +40,8 @@ for path, properties in modems:
"PreferredLanguages",
"PrimaryContexts",
"LockedPins",
"Features"]:
"Features",
"AvailableTechnologies"]:
val = ""
for i in properties[key]:
val += i + " "

View File

@@ -3,24 +3,23 @@
import sys
import dbus
if (len(sys.argv) != 2):
print("Usage: %s [voicecall_path]" % (sys.argv[0]))
exit(1)
bus = dbus.SystemBus()
manager = dbus.Interface(bus.get_object('org.ofono', '/'),
'org.ofono.Manager')
modems = manager.GetModems()
path = modems[0][0]
if (len(sys.argv) == 3):
path = sys.argv[1]
callid = sys.argv[2]
else:
callid = sys.argv[1]
call = sys.argv[1]
sep = call.find("/", 1)
path = call[0:sep]
manager = dbus.Interface(bus.get_object('org.ofono', path),
'org.ofono.VoiceCallManager')
mpty = manager.PrivateChat(callid, timeout=100)
mpty = manager.PrivateChat(call, timeout=100)
for path in mpty:
print(path)

View File

@@ -6,7 +6,7 @@ import dbus
import dbus.mainloop.glib
def incoming_message(message, details, path, interface):
print("%s" % (message))
print("%s" % (message.encode('utf-8')))
for key in details:
val = details[key]

View File

@@ -1,5 +1,6 @@
#!/usr/bin/python3
import sys
import dbus
bus = dbus.SystemBus()
@@ -7,16 +8,32 @@ bus = dbus.SystemBus()
manager = dbus.Interface(bus.get_object('org.ofono', '/'),
'org.ofono.Manager')
modems = manager.GetModems()
if (len(sys.argv) == 1):
path = None
modems = manager.GetModems()
for path_i, properties in modems:
if "org.ofono.VoiceCallManager" in properties["Interfaces"]:
path = path_i
break
if (path is None):
exit(2)
elif (len(sys.argv) == 2):
path = sys.argv[1]
else:
print("Usage: %s [modem]" % (sys.argv[0]))
exit(1)
for path, properties in modems:
print("[ %s ]" % (path))
modemapi = dbus.Interface(bus.get_object('org.ofono', path), 'org.ofono.Modem')
properties = modemapi.GetProperties()
if "org.ofono.VoiceCallManager" not in properties["Interfaces"]:
continue
if "org.ofono.VoiceCallManager" not in properties["Interfaces"]:
print("org.ofono.VoiceCallManager not found")
exit(2)
mgr = dbus.Interface(bus.get_object('org.ofono', path),
'org.ofono.VoiceCallManager')
print("[ %s ]" % (path))
mgr = dbus.Interface(bus.get_object('org.ofono', path),
'org.ofono.VoiceCallManager')
mgr.ReleaseAndAnswer()
mgr.ReleaseAndAnswer()
break

View File

@@ -1,5 +1,6 @@
#!/usr/bin/python3
import sys
import dbus
bus = dbus.SystemBus()
@@ -7,16 +8,32 @@ bus = dbus.SystemBus()
manager = dbus.Interface(bus.get_object('org.ofono', '/'),
'org.ofono.Manager')
modems = manager.GetModems()
if (len(sys.argv) == 1):
modem = None
modems = manager.GetModems()
for path, properties in modems:
if "org.ofono.VoiceCallManager" in properties["Interfaces"]:
modem = path
break
if (modem is None):
exit(2)
elif (len(sys.argv) == 2):
modem = sys.argv[1]
else:
print("Usage: %s [modem]" % (sys.argv[0]))
exit(1)
for path, properties in modems:
print("[ %s ]" % (path))
modemapi = dbus.Interface(bus.get_object('org.ofono', modem), 'org.ofono.Modem')
properties = modemapi.GetProperties()
if "org.ofono.VoiceCallManager" not in properties["Interfaces"]:
continue
if "org.ofono.VoiceCallManager" not in properties["Interfaces"]:
print("org.ofono.VoiceCallManager not found")
exit(2)
mgr = dbus.Interface(bus.get_object('org.ofono', path),
'org.ofono.VoiceCallManager')
print("[ %s ]" % (modem))
mgr = dbus.Interface(bus.get_object('org.ofono', modem),
'org.ofono.VoiceCallManager')
mgr.ReleaseAndSwap()
mgr.ReleaseAndSwap()
break

21
ofono/test/set-ddr Executable file
View File

@@ -0,0 +1,21 @@
#!/usr/bin/python
import sys
import dbus
bus = dbus.SystemBus()
manager = dbus.Interface(bus.get_object('org.ofono', '/'),
'org.ofono.Manager')
modems = manager.GetModems()
for path, properties in modems:
if "org.ofono.Handsfree" not in properties["Interfaces"]:
continue
handsfree = dbus.Interface(bus.get_object('org.ofono', path),
'org.ofono.Handsfree')
handsfree.SetProperty("DistractedDrivingReduction",\
dbus.Boolean(int(sys.argv[1])))

View File

@@ -1,3 +1,8 @@
* Fri Feb 27 2015 Tommi Kenakkala <tommi.kenakkala@tieto.com> - 1.16
- Update to upstream 1.16
- Rilmodem work
- Some core changes and API extensions
* Thu Jan 09 2014 Martti Piirainen <martti.piirainen@oss.tieto.com> - 1.14
- Update to upstream 1.14.

View File

@@ -1,7 +1,7 @@
Name: ofono
Summary: Open Source Telephony
Version: 1.14
Version: 1.16
Release: 1
Group: Communications/Connectivity Adaptation
License: GPLv2