forked from sailfishos/ofono
Compare commits
106 Commits
mer/1.14+g
...
mer/1.16+g
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
44585697c3 | ||
|
|
07da2f3fa7 | ||
|
|
7d0d72a4a9 | ||
|
|
f9ee2ae9b8 | ||
|
|
c006d822f1 | ||
|
|
7331c88b41 | ||
|
|
063eefbac1 | ||
|
|
12b510b4e7 | ||
|
|
c04f5df8ec | ||
|
|
c9e426ecd7 | ||
|
|
10f173981c | ||
|
|
bb71141d79 | ||
|
|
4e466f6fec | ||
|
|
a89f8cd56d | ||
|
|
95482cb84a | ||
|
|
fce95b767a | ||
|
|
44049f064a | ||
|
|
b899f4aca2 | ||
|
|
e1cbc5c5ea | ||
|
|
5210b85c22 | ||
|
|
e6048f1dc1 | ||
|
|
6bdc109ec0 | ||
|
|
7dca0a7315 | ||
|
|
19519b2132 | ||
|
|
42ebb69384 | ||
|
|
45478b17cf | ||
|
|
88f46a9b01 | ||
|
|
2abcb85809 | ||
|
|
331700a697 | ||
|
|
a753d6c012 | ||
|
|
d39007c948 | ||
|
|
6c4ac05fbc | ||
|
|
934ea9a9fe | ||
|
|
cf90f1505d | ||
|
|
f9d5ee5fa9 | ||
|
|
e2785b1865 | ||
|
|
fb1b213e22 | ||
|
|
d3560b3784 | ||
|
|
017c1161d4 | ||
|
|
de02f68a2e | ||
|
|
0f28d9206d | ||
|
|
eef67018b6 | ||
|
|
299ffc9620 | ||
|
|
39f08a5e1c | ||
|
|
6c0f90fc1b | ||
|
|
33537adb9f | ||
|
|
e176a9019f | ||
|
|
7166aebd51 | ||
|
|
debb0d2d3e | ||
|
|
ab5b6d1217 | ||
|
|
7e3a6628fa | ||
|
|
fa105c4ba6 | ||
|
|
99c03292ad | ||
|
|
66cf2a30fa | ||
|
|
a4fa356b16 | ||
|
|
43e83852dc | ||
|
|
36a21da227 | ||
|
|
bef4d610a3 | ||
|
|
2d158167c2 | ||
|
|
02c5b73f6e | ||
|
|
0727da1d5b | ||
|
|
d292e0e0ed | ||
|
|
881207ce18 | ||
|
|
0f0733c348 | ||
|
|
8ebb17977b | ||
|
|
7fb4899970 | ||
|
|
1e0c41889f | ||
|
|
08e673050a | ||
|
|
1b1b1861ab | ||
|
|
8a4c29ca74 | ||
|
|
9aeea028ed | ||
|
|
22e892a22e | ||
|
|
361eed7b9a | ||
|
|
864efe1add | ||
|
|
0d8a06af30 | ||
|
|
293c701e25 | ||
|
|
cca3e085b3 | ||
|
|
7f29608feb | ||
|
|
1f3e30f1ba | ||
|
|
7ab4034bf4 | ||
|
|
bb1984cabb | ||
|
|
6df64cd1a9 | ||
|
|
4a0831bc80 | ||
|
|
b2bfdd69d2 | ||
|
|
1588e7c082 | ||
|
|
5cffd8af95 | ||
|
|
d2f6ffc18d | ||
|
|
6369cc902c | ||
|
|
d05b718cc0 | ||
|
|
c144fadca6 | ||
|
|
532e8020e5 | ||
|
|
310915429b | ||
|
|
9285ec0d89 | ||
|
|
8cbe061c3b | ||
|
|
3e13676766 | ||
|
|
73831c3d76 | ||
|
|
7011dcdf2f | ||
|
|
f6341502c8 | ||
|
|
8edaaaf210 | ||
|
|
a88662d23c | ||
|
|
1dd8580930 | ||
|
|
65be2b344c | ||
|
|
62c34467a2 | ||
|
|
d9f252fb61 | ||
|
|
815d62888f | ||
|
|
35feae07e5 |
@@ -96,3 +96,6 @@ Tony Espy <espy@canonical.com>
|
|||||||
Martin Pitt <martin.pitt@ubuntu.com>
|
Martin Pitt <martin.pitt@ubuntu.com>
|
||||||
Alfonso Sanchez-Beato <alfonso.sanchez-beato@canonical.com>
|
Alfonso Sanchez-Beato <alfonso.sanchez-beato@canonical.com>
|
||||||
Jussi Pakkanen <jussi.pakkanen@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>
|
||||||
|
|||||||
@@ -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:
|
ver 1.14:
|
||||||
Add support for Apple Siri specific Handsfree commands.
|
Add support for Apple Siri specific Handsfree commands.
|
||||||
Add support for provisioning of MMSC and Message Proxy.
|
Add support for provisioning of MMSC and Message Proxy.
|
||||||
|
|||||||
@@ -21,8 +21,9 @@ pkginclude_HEADERS = include/log.h include/plugin.h include/history.h \
|
|||||||
include/cdma-connman.h include/gnss.h \
|
include/cdma-connman.h include/gnss.h \
|
||||||
include/private-network.h include/cdma-netreg.h \
|
include/private-network.h include/cdma-netreg.h \
|
||||||
include/cdma-provision.h include/handsfree.h \
|
include/cdma-provision.h include/handsfree.h \
|
||||||
include/handsfree-audio.h include/sim-mnclength.h \
|
include/handsfree-audio.h \
|
||||||
include/oemraw.h include/siri.h
|
include/sim-mnclength.h include/oemraw.h \
|
||||||
|
include/siri.h
|
||||||
|
|
||||||
nodist_pkginclude_HEADERS = include/version.h
|
nodist_pkginclude_HEADERS = include/version.h
|
||||||
|
|
||||||
@@ -312,6 +313,12 @@ builtin_sources += drivers/atmodem/atutil.h \
|
|||||||
drivers/mbmmodem/stk.c \
|
drivers/mbmmodem/stk.c \
|
||||||
drivers/mbmmodem/location-reporting.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_modules += hsomodem
|
||||||
builtin_sources += drivers/atmodem/atutil.h \
|
builtin_sources += drivers/atmodem/atutil.h \
|
||||||
drivers/hsomodem/hsomodem.h \
|
drivers/hsomodem/hsomodem.h \
|
||||||
@@ -461,14 +468,20 @@ builtin_sources += plugins/samsung.c
|
|||||||
|
|
||||||
builtin_modules += sim900
|
builtin_modules += sim900
|
||||||
builtin_sources += plugins/sim900.c
|
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
|
endif
|
||||||
|
|
||||||
builtin_modules += connman
|
builtin_modules += connman
|
||||||
builtin_sources += plugins/connman.c
|
builtin_sources += plugins/connman.c
|
||||||
|
|
||||||
builtin_modules += he910
|
|
||||||
builtin_sources += plugins/he910.c
|
|
||||||
|
|
||||||
if BLUETOOTH
|
if BLUETOOTH
|
||||||
if BLUEZ4
|
if BLUEZ4
|
||||||
builtin_modules += bluez4
|
builtin_modules += bluez4
|
||||||
@@ -544,6 +557,9 @@ builtin_sources += examples/private-network.c
|
|||||||
|
|
||||||
builtin_modules += stktest
|
builtin_modules += stktest
|
||||||
builtin_sources += plugins/stktest.c
|
builtin_sources += plugins/stktest.c
|
||||||
|
|
||||||
|
builtin_modules += emulator_fuzz
|
||||||
|
builtin_sources += plugins/emulator_fuzz.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
builtin_modules += smart_messaging
|
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-sms.c src/private-network.c src/cdma-netreg.c \
|
||||||
src/cdma-provision.c src/handsfree.c \
|
src/cdma-provision.c src/handsfree.c \
|
||||||
src/handsfree-audio.c src/bluetooth.h \
|
src/handsfree-audio.c src/bluetooth.h \
|
||||||
src/hfp.h src/sim-mnclength.c src/oemraw.c \
|
src/sim-mnclength.c src/oemraw.c src/voicecallagent.c \
|
||||||
src/siri.c src/voicecallagent.c
|
src/hfp.h src/siri.c
|
||||||
|
|
||||||
src_ofonod_LDADD = gdbus/libgdbus-internal.la $(builtin_libadd) \
|
src_ofonod_LDADD = gdbus/libgdbus-internal.la $(builtin_libadd) \
|
||||||
@GLIB_LIBS@ @DBUS_LIBS@ -ldl
|
@GLIB_LIBS@ @DBUS_LIBS@ -ldl
|
||||||
@@ -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/sim-api.txt doc/stk-api.txt \
|
||||||
doc/audio-settings-api.txt doc/text-telephony-api.txt \
|
doc/audio-settings-api.txt doc/text-telephony-api.txt \
|
||||||
doc/calypso-modem.txt doc/message-api.txt \
|
doc/calypso-modem.txt doc/message-api.txt \
|
||||||
doc/location-reporting-api.txt doc/smshistory-api.txt \
|
doc/location-reporting-api.txt \
|
||||||
doc/oemraw-api.txt \
|
doc/smshistory-api.txt doc/oemraw-api.txt \
|
||||||
doc/certification.txt doc/siri-api.txt
|
doc/certification.txt doc/siri-api.txt \
|
||||||
|
doc/telit-modem.txt
|
||||||
|
|
||||||
|
|
||||||
test_scripts = test/backtrace \
|
test_scripts = test/backtrace \
|
||||||
@@ -732,7 +749,8 @@ test_scripts = test/backtrace \
|
|||||||
test/display-icon \
|
test/display-icon \
|
||||||
test/set-msisdn \
|
test/set-msisdn \
|
||||||
test/test-voicecallagent \
|
test/test-voicecallagent \
|
||||||
test/get-network-time
|
test/get-network-time \
|
||||||
|
test/set-ddr
|
||||||
|
|
||||||
if TEST
|
if TEST
|
||||||
testdir = $(pkglibdir)/test
|
testdir = $(pkglibdir)/test
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ AC_DEFUN([AC_PROG_CC_PIE], [
|
|||||||
|
|
||||||
AC_DEFUN([COMPILER_FLAGS], [
|
AC_DEFUN([COMPILER_FLAGS], [
|
||||||
if (test "${CFLAGS}" = ""); then
|
if (test "${CFLAGS}" = ""); then
|
||||||
CFLAGS="-Wall -O2 -D_FORTIFY_SOURCE=2"
|
CFLAGS="-Wall -O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2"
|
||||||
fi
|
fi
|
||||||
if (test "$USE_MAINTAINER_MODE" = "yes"); then
|
if (test "$USE_MAINTAINER_MODE" = "yes"); then
|
||||||
CFLAGS="$CFLAGS -Werror -Wextra"
|
CFLAGS="$CFLAGS -Werror -Wextra"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
AC_PREREQ(2.60)
|
AC_PREREQ(2.60)
|
||||||
AC_INIT(ofono, 1.14)
|
AC_INIT(ofono, 1.16)
|
||||||
|
|
||||||
AM_INIT_AUTOMAKE([foreign subdir-objects color-tests])
|
AM_INIT_AUTOMAKE([foreign subdir-objects color-tests])
|
||||||
AC_CONFIG_HEADERS(config.h)
|
AC_CONFIG_HEADERS(config.h)
|
||||||
|
|||||||
@@ -189,6 +189,10 @@ Properties boolean Active [readwrite]
|
|||||||
"wap" - Used by WAP related services
|
"wap" - Used by WAP related services
|
||||||
"ims" - Used by IMS 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]
|
string Username [readwrite]
|
||||||
|
|
||||||
Holds the username to be used for authentication
|
Holds the username to be used for authentication
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ Methods dict GetProperties()
|
|||||||
|
|
||||||
Possible Errors: [service].Error.InProgress
|
Possible Errors: [service].Error.InProgress
|
||||||
[service].Error.InvalidArguments
|
[service].Error.InvalidArguments
|
||||||
|
[service].Error.NotImplemented
|
||||||
|
[service].Error.NotSupported
|
||||||
|
|
||||||
string RequestPhoneNumber()
|
string RequestPhoneNumber()
|
||||||
|
|
||||||
@@ -51,6 +53,7 @@ Properties array{string} Features [readonly]
|
|||||||
"private-chat"
|
"private-chat"
|
||||||
"create-multiparty"
|
"create-multiparty"
|
||||||
"transfer"
|
"transfer"
|
||||||
|
"hf-indicators"
|
||||||
|
|
||||||
boolean InbandRinging [readonly]
|
boolean InbandRinging [readonly]
|
||||||
|
|
||||||
@@ -63,7 +66,7 @@ Properties array{string} Features [readonly]
|
|||||||
to activate or deactivate the function from the HF, or
|
to activate or deactivate the function from the HF, or
|
||||||
the AG could autonomously initiate it.
|
the AG could autonomously initiate it.
|
||||||
|
|
||||||
boolean EchoCancelingNoiseReduction [readwrite]
|
boolean EchoCancelingNoiseReduction [readwrite, optional]
|
||||||
|
|
||||||
Non-persistent Boolean property representing whether
|
Non-persistent Boolean property representing whether
|
||||||
echo canceling and noise reduction is enabled in the
|
echo canceling and noise reduction is enabled in the
|
||||||
@@ -80,3 +83,10 @@ Properties array{string} Features [readonly]
|
|||||||
array{string} SubscriberNumbers [readonly]
|
array{string} SubscriberNumbers [readonly]
|
||||||
|
|
||||||
List of subscriber numbers provided by the AG.
|
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.
|
||||||
|
|||||||
@@ -45,6 +45,11 @@ Properties string TechnologyPreference [readwrite]
|
|||||||
"umts" Only UMTS used for radio access.
|
"umts" Only UMTS used for radio access.
|
||||||
"lte" Only LTE 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]
|
string GsmBand [readwrite, optional]
|
||||||
|
|
||||||
Frequency band in which the modem is allowed to
|
Frequency band in which the modem is allowed to
|
||||||
|
|||||||
19
ofono/doc/telit-modem.txt
Normal file
19
ofono/doc/telit-modem.txt
Normal 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'.
|
||||||
@@ -59,6 +59,7 @@ enum state {
|
|||||||
struct gprs_context_data {
|
struct gprs_context_data {
|
||||||
GAtChat *chat;
|
GAtChat *chat;
|
||||||
unsigned int active_context;
|
unsigned int active_context;
|
||||||
|
GAtPPPAuthMethod auth_method;
|
||||||
char username[OFONO_GPRS_MAX_USERNAME_LENGTH + 1];
|
char username[OFONO_GPRS_MAX_USERNAME_LENGTH + 1];
|
||||||
char password[OFONO_GPRS_MAX_PASSWORD_LENGTH + 1];
|
char password[OFONO_GPRS_MAX_PASSWORD_LENGTH + 1];
|
||||||
GAtPPP *ppp;
|
GAtPPP *ppp;
|
||||||
@@ -154,6 +155,7 @@ static gboolean setup_ppp(struct ofono_gprs_context *gc)
|
|||||||
if (getenv("OFONO_PPP_DEBUG"))
|
if (getenv("OFONO_PPP_DEBUG"))
|
||||||
g_at_ppp_set_debug(gcd->ppp, ppp_debug, "PPP");
|
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);
|
g_at_ppp_set_credentials(gcd->ppp, gcd->username, gcd->password);
|
||||||
|
|
||||||
/* set connect and disconnect callbacks */
|
/* 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->username, ctx->username, sizeof(ctx->username));
|
||||||
memcpy(gcd->password, ctx->password, sizeof(ctx->password));
|
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;
|
gcd->state = STATE_ENABLING;
|
||||||
|
|
||||||
if (gcd->vendor == OFONO_VENDOR_ZTE) {
|
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);
|
len = snprintf(buf, sizeof(buf), "AT+CGDCONT=%u,\"IP\"", ctx->cid);
|
||||||
|
|
||||||
if (ctx->apn)
|
if (ctx->apn) {
|
||||||
snprintf(buf + len, sizeof(buf) - len - 3, ",\"%s\"",
|
switch (gcd->vendor) {
|
||||||
ctx->apn);
|
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,
|
if (g_at_chat_send(gcd->chat, buf, none_prefix,
|
||||||
at_cgdcont_cb, gc, NULL) > 0)
|
at_cgdcont_cb, gc, NULL) > 0)
|
||||||
|
|||||||
@@ -282,6 +282,44 @@ static void telit_mode_notify(GAtResult *result, gpointer user_data)
|
|||||||
ofono_gprs_bearer_notify(gprs, bearer);
|
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)
|
static void cpsb_notify(GAtResult *result, gpointer user_data)
|
||||||
{
|
{
|
||||||
struct ofono_gprs *gprs = 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,
|
g_at_chat_register(gd->chat, "^MODE:", huawei_mode_notify,
|
||||||
FALSE, gprs, NULL);
|
FALSE, gprs, NULL);
|
||||||
break;
|
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:
|
case OFONO_VENDOR_TELIT:
|
||||||
g_at_chat_register(gd->chat, "#PSNT:", telit_mode_notify,
|
g_at_chat_register(gd->chat, "#PSNT:", telit_mode_notify,
|
||||||
FALSE, gprs, NULL);
|
FALSE, gprs, NULL);
|
||||||
|
|||||||
@@ -67,6 +67,8 @@ static const char *epin_prefix[] = { "*EPIN:", NULL };
|
|||||||
static const char *spic_prefix[] = { "+SPIC:", NULL };
|
static const char *spic_prefix[] = { "+SPIC:", NULL };
|
||||||
static const char *pct_prefix[] = { "#PCT:", NULL };
|
static const char *pct_prefix[] = { "#PCT:", NULL };
|
||||||
static const char *pnnm_prefix[] = { "+PNNM:", 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 const char *none_prefix[] = { NULL };
|
||||||
|
|
||||||
static void at_crsm_info_cb(gboolean ok, GAtResult *result, gpointer user_data)
|
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);
|
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,
|
static void at_pin_retries_query(struct ofono_sim *sim,
|
||||||
ofono_sim_pin_retries_cb_t cb,
|
ofono_sim_pin_retries_cb_t cb,
|
||||||
void *data)
|
void *data)
|
||||||
@@ -1028,6 +1114,16 @@ static void at_pin_retries_query(struct ofono_sim *sim,
|
|||||||
at_pnnm_cb, cbd, g_free) > 0)
|
at_pnnm_cb, cbd, g_free) > 0)
|
||||||
return;
|
return;
|
||||||
break;
|
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:
|
default:
|
||||||
if (g_at_chat_send(sd->chat, "AT+CPINR", cpinr_prefixes,
|
if (g_at_chat_send(sd->chat, "AT+CPINR", cpinr_prefixes,
|
||||||
at_cpinr_cb, cbd, g_free) > 0)
|
at_cpinr_cb, cbd, g_free) > 0)
|
||||||
|
|||||||
@@ -42,5 +42,7 @@ enum ofono_vendor {
|
|||||||
OFONO_VENDOR_SIMCOM_SIM900,
|
OFONO_VENDOR_SIMCOM_SIM900,
|
||||||
OFONO_VENDOR_ICERA,
|
OFONO_VENDOR_ICERA,
|
||||||
OFONO_VENDOR_WAVECOM_Q2XXX,
|
OFONO_VENDOR_WAVECOM_Q2XXX,
|
||||||
OFONO_VENDOR_ALCATEL
|
OFONO_VENDOR_ALCATEL,
|
||||||
|
OFONO_VENDOR_QUECTEL,
|
||||||
|
OFONO_VENDOR_UBLOX,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -206,6 +206,27 @@ static void hfp_cnum_query(struct ofono_handsfree *hf,
|
|||||||
CALLBACK_WITH_FAILURE(cb, -1, NULL, data);
|
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)
|
static gboolean hfp_handsfree_register(gpointer user_data)
|
||||||
{
|
{
|
||||||
struct ofono_handsfree *hf = 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, "+BSIR:", bsir_notify, FALSE, hf, NULL);
|
||||||
g_at_chat_register(hd->chat, "+BVRA:", bvra_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, "+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)
|
if (hd->ag_features & HFP_AG_FEATURE_IN_BAND_RING_TONE)
|
||||||
ofono_handsfree_set_inband_ringing(hf, TRUE);
|
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 hfp_slc_info *info = data;
|
||||||
struct hf_data *hd;
|
struct hf_data *hd;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
DBG("");
|
DBG("");
|
||||||
hd = g_new0(struct hf_data, 1);
|
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,
|
ofono_handsfree_battchg_notify(hf,
|
||||||
info->cind_val[HFP_INDICATOR_BATTCHG]);
|
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);
|
hd->register_source = g_idle_add(hfp_handsfree_register, hf);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -360,6 +391,25 @@ static void hfp_disable_nrec(struct ofono_handsfree *hf,
|
|||||||
CALLBACK_WITH_FAILURE(cb, data);
|
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 = {
|
static struct ofono_handsfree_driver driver = {
|
||||||
.name = "hfpmodem",
|
.name = "hfpmodem",
|
||||||
.probe = hfp_handsfree_probe,
|
.probe = hfp_handsfree_probe,
|
||||||
@@ -368,6 +418,7 @@ static struct ofono_handsfree_driver driver = {
|
|||||||
.request_phone_number = hfp_request_phone_number,
|
.request_phone_number = hfp_request_phone_number,
|
||||||
.voice_recognition = hfp_voice_recognition,
|
.voice_recognition = hfp_voice_recognition,
|
||||||
.disable_nrec = hfp_disable_nrec,
|
.disable_nrec = hfp_disable_nrec,
|
||||||
|
.hf_indicator = hfp_hf_indicator,
|
||||||
};
|
};
|
||||||
|
|
||||||
void hfp_handsfree_init(void)
|
void hfp_handsfree_init(void)
|
||||||
|
|||||||
@@ -41,10 +41,12 @@
|
|||||||
#include "hfp.h"
|
#include "hfp.h"
|
||||||
#include "slc.h"
|
#include "slc.h"
|
||||||
|
|
||||||
|
static const char *none_prefix[] = { NULL };
|
||||||
static const char *brsf_prefix[] = { "+BRSF:", NULL };
|
static const char *brsf_prefix[] = { "+BRSF:", NULL };
|
||||||
static const char *cind_prefix[] = { "+CIND:", NULL };
|
static const char *cind_prefix[] = { "+CIND:", NULL };
|
||||||
static const char *cmer_prefix[] = { "+CMER:", NULL };
|
static const char *cmer_prefix[] = { "+CMER:", NULL };
|
||||||
static const char *chld_prefix[] = { "+CHLD:", NULL };
|
static const char *chld_prefix[] = { "+CHLD:", NULL };
|
||||||
|
static const char *bind_prefix[] = { "+BIND:", NULL };
|
||||||
|
|
||||||
struct slc_establish_data {
|
struct slc_establish_data {
|
||||||
gint ref_count;
|
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;
|
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:
|
done:
|
||||||
memset(info->cind_val, 0, sizeof(info->cind_val));
|
memset(info->cind_val, 0, sizeof(info->cind_val));
|
||||||
memset(info->cind_pos, 0, sizeof(info->cind_pos));
|
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);
|
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)
|
static void chld_cb(gboolean ok, GAtResult *result, gpointer user_data)
|
||||||
{
|
{
|
||||||
struct slc_establish_data *sed = 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;
|
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;
|
return;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
|||||||
@@ -39,6 +39,9 @@ struct hfp_slc_info {
|
|||||||
unsigned int hf_features;
|
unsigned int hf_features;
|
||||||
unsigned char cind_pos[HFP_INDICATOR_LAST];
|
unsigned char cind_pos[HFP_INDICATOR_LAST];
|
||||||
unsigned int cind_val[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);
|
void hfp_slc_info_init(struct hfp_slc_info *info, guint16 version);
|
||||||
|
|||||||
@@ -46,6 +46,7 @@
|
|||||||
#define POLL_CLCC_DELAY 50
|
#define POLL_CLCC_DELAY 50
|
||||||
#define EXPECT_RELEASE_DELAY 50
|
#define EXPECT_RELEASE_DELAY 50
|
||||||
#define CLIP_TIMEOUT 500
|
#define CLIP_TIMEOUT 500
|
||||||
|
#define EXPECT_RING_DELAY 200
|
||||||
|
|
||||||
static const char *none_prefix[] = { NULL };
|
static const char *none_prefix[] = { NULL };
|
||||||
static const char *clcc_prefix[] = { "+CLCC:", 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.
|
* we won't get indicator update if any of them is released by CHLD=1x.
|
||||||
* So we have to poll it.
|
* 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,
|
vd->clcc_source = g_timeout_add(POLL_CLCC_INTERVAL, poll_clcc,
|
||||||
vc);
|
vc);
|
||||||
}
|
}
|
||||||
@@ -499,6 +500,19 @@ static gboolean expect_release(gpointer user_data)
|
|||||||
return FALSE;
|
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,
|
static void release_all_active_cb(gboolean ok, GAtResult *result,
|
||||||
gpointer user_data)
|
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 voicecall_data *vd = ofono_voicecall_get_data(vc);
|
||||||
struct change_state_req *req = g_try_new0(struct change_state_req, 1);
|
struct change_state_req *req = g_try_new0(struct change_state_req, 1);
|
||||||
|
int len = strlen(dtmf);
|
||||||
char *buf;
|
char *buf;
|
||||||
int s;
|
int s;
|
||||||
|
int i;
|
||||||
|
|
||||||
if (req == NULL)
|
if (req == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
@@ -651,12 +667,15 @@ static void hfp_send_dtmf(struct ofono_voicecall *vc, const char *dtmf,
|
|||||||
req->data = data;
|
req->data = data;
|
||||||
req->affected_types = 0;
|
req->affected_types = 0;
|
||||||
|
|
||||||
/* strlen("AT+VTS=) = 7 + NULL */
|
/* strlen("AT") + (n-1) * strlen("+VTS=T;") + strlen(+VTS=T) + null */
|
||||||
buf = g_try_new(char, strlen(dtmf) + 8);
|
buf = g_try_new(char, len * 7 + 2);
|
||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
goto error;
|
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,
|
s = g_at_chat_send(vd->chat, buf, none_prefix,
|
||||||
generic_cb, req, g_free);
|
generic_cb, req, g_free);
|
||||||
@@ -752,6 +771,11 @@ static void ring_notify(GAtResult *result, gpointer user_data)
|
|||||||
struct ofono_call *call;
|
struct ofono_call *call;
|
||||||
GSList *waiting;
|
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 */
|
/* RING can repeat, ignore if we already have an incoming call */
|
||||||
if (g_slist_find_custom(vd->calls,
|
if (g_slist_find_custom(vd->calls,
|
||||||
GINT_TO_POINTER(CALL_STATUS_INCOMING),
|
GINT_TO_POINTER(CALL_STATUS_INCOMING),
|
||||||
@@ -976,7 +1000,15 @@ static void ciev_callsetup_notify(struct ofono_voicecall *vc,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
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;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
|
|||||||
@@ -375,7 +375,14 @@ gboolean ril_util_parse_sim_status(GRil *gril,
|
|||||||
* Do we just make a style-guide exception for PrintBuf operations?
|
* Do we just make a style-guide exception for PrintBuf operations?
|
||||||
*/
|
*/
|
||||||
g_ril_append_print_buf(gril,
|
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->card_state,
|
||||||
status->pin_state,
|
status->pin_state,
|
||||||
status->gsm_umts_index,
|
status->gsm_umts_index,
|
||||||
@@ -387,6 +394,7 @@ gboolean ril_util_parse_sim_status(GRil *gril,
|
|||||||
else
|
else
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
|
DBG("sim num_apps: %d", status->num_apps);
|
||||||
if (status->num_apps > MAX_UICC_APPS) {
|
if (status->num_apps > MAX_UICC_APPS) {
|
||||||
ofono_error("SIM error; too many apps: %d", status->num_apps);
|
ofono_error("SIM error; too many apps: %d", status->num_apps);
|
||||||
status->num_apps = MAX_UICC_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_type = parcel_r_int32(&rilp);
|
||||||
apps[i]->app_state = 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
|
* Consider RIL_APPSTATE_ILLEGAL also READY. Even if app state
|
||||||
* is RIL_APPSTATE_ILLEGAL (-1), ICC operations must be
|
* 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]->pin_replaced,
|
||||||
apps[i]->pin1_state,
|
apps[i]->pin1_state,
|
||||||
apps[i]->pin2_state);
|
apps[i]->pin2_state);
|
||||||
|
|
||||||
|
DBG("app[%d]: type=%d, state=%d, perso_substate=%d, aid_ptr=%s, app_label_ptr=%s, pin1_replaced=%d, pin1=%d, pin2=%d",
|
||||||
|
i, apps[i]->app_type,
|
||||||
|
apps[i]->app_state,
|
||||||
|
apps[i]->perso_substate,
|
||||||
|
apps[i]->aid_str,
|
||||||
|
apps[i]->app_str,
|
||||||
|
apps[i]->pin_replaced,
|
||||||
|
apps[i]->pin1_state,
|
||||||
|
apps[i]->pin2_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
@@ -606,8 +626,10 @@ gint ril_util_parse_sms_response(GRil *gril, struct ril_msg *message)
|
|||||||
*/
|
*/
|
||||||
mr = parcel_r_int32(&rilp);
|
mr = parcel_r_int32(&rilp);
|
||||||
ack_pdu = parcel_r_string(&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}",
|
g_ril_append_print_buf(gril, "{%d,%s,%d}",
|
||||||
mr, ack_pdu, error);
|
mr, ack_pdu, error);
|
||||||
|
|||||||
@@ -97,11 +97,9 @@ struct sim_data {
|
|||||||
guint app_type;
|
guint app_type;
|
||||||
gchar *app_str;
|
gchar *app_str;
|
||||||
guint app_index;
|
guint app_index;
|
||||||
gboolean sim_registered;
|
|
||||||
enum ofono_sim_password_type passwd_type;
|
enum ofono_sim_password_type passwd_type;
|
||||||
int retries[OFONO_SIM_PASSWORD_INVALID];
|
int retries[OFONO_SIM_PASSWORD_INVALID];
|
||||||
enum ofono_sim_password_type passwd_state;
|
enum ofono_sim_password_type passwd_state;
|
||||||
guint card_state;
|
|
||||||
guint idle_id;
|
guint idle_id;
|
||||||
gboolean initialized;
|
gboolean initialized;
|
||||||
gboolean removed;
|
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) {
|
} else if (sd->app_type == RIL_APPTYPE_SIM) {
|
||||||
len = sim_ef_db_get_path_2g(fileid, db_path);
|
len = sim_ef_db_get_path_2g(fileid, db_path);
|
||||||
} else {
|
} 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) {
|
if (len > 0) {
|
||||||
@@ -187,7 +186,7 @@ static void ril_file_info_cb(struct ril_msg *message, gpointer user_data)
|
|||||||
* core will crash.
|
* core will crash.
|
||||||
*/
|
*/
|
||||||
if (sd->removed == TRUE) {
|
if (sd->removed == TRUE) {
|
||||||
ofono_error("RIL_CARDSTATE_ABSENT");
|
ofono_error("%s RIL_CARDSTATE_ABSENT", __func__);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,14 +204,15 @@ static void ril_file_info_cb(struct ril_msg *message, gpointer user_data)
|
|||||||
&sw1,
|
&sw1,
|
||||||
&sw2,
|
&sw2,
|
||||||
&response_len)) == NULL) {
|
&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");
|
decode_ril_error(&error, "FAIL");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((sw1 != 0x90 && sw1 != 0x91 && sw1 != 0x92 && sw1 != 0x9f) ||
|
if ((sw1 != 0x90 && sw1 != 0x91 && sw1 != 0x92 && sw1 != 0x9f) ||
|
||||||
(sw1 == 0x90 && sw2 != 0x00)) {
|
(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));
|
memset(&error, 0, sizeof(error));
|
||||||
|
|
||||||
/* TODO: fix decode_ril_error to take type & 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) {
|
if (!ok) {
|
||||||
ofono_error("parse response failed");
|
ofono_error("%s parse response failed", __func__);
|
||||||
decode_ril_error(&error, "FAIL");
|
decode_ril_error(&error, "FAIL");
|
||||||
goto error;
|
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) {
|
if (message->error == RIL_E_SUCCESS) {
|
||||||
decode_ril_error(&error, "OK");
|
decode_ril_error(&error, "OK");
|
||||||
} else {
|
} else {
|
||||||
ofono_error("RILD reply failure: %s",
|
ofono_error("%s RILD reply failure: %s", __func__,
|
||||||
ril_error_to_string(message->error));
|
ril_error_to_string(message->error));
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@@ -336,7 +336,7 @@ static void ril_file_io_cb(struct ril_msg *message, gpointer user_data)
|
|||||||
&sw1,
|
&sw1,
|
||||||
&sw2,
|
&sw2,
|
||||||
&response_len)) == NULL) {
|
&response_len)) == NULL) {
|
||||||
ofono_error("Error parsing IO response");
|
ofono_error("%s Error parsing IO response", __func__);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -470,7 +470,7 @@ static void ril_imsi_cb(struct ril_msg *message, gpointer user_data)
|
|||||||
DBG("GET IMSI reply - OK");
|
DBG("GET IMSI reply - OK");
|
||||||
decode_ril_error(&error, "OK");
|
decode_ril_error(&error, "OK");
|
||||||
} else {
|
} else {
|
||||||
ofono_error("Reply failure: %s",
|
ofono_error("%s Reply failure: %s", __func__,
|
||||||
ril_error_to_string(message->error));
|
ril_error_to_string(message->error));
|
||||||
decode_ril_error(&error, "FAIL");
|
decode_ril_error(&error, "FAIL");
|
||||||
cb(&error, NULL, cbd->data);
|
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;
|
guint search_index = -1;
|
||||||
struct parcel rilp;
|
struct parcel rilp;
|
||||||
|
|
||||||
DBG("");
|
DBG("%p", message);
|
||||||
|
|
||||||
if (ril_util_parse_sim_status(sd->ril, message, &status, apps) &&
|
if (ril_util_parse_sim_status(sd->ril, message, &status, apps) &&
|
||||||
status.num_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
|
/* TODO(CDMA): need some kind of logic to
|
||||||
* set the correct app_index,
|
* 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);
|
* ril_util_parse_sim_status returns true only when
|
||||||
sd->sim_registered = TRUE;
|
* card status is RIL_CARDSTATE_PRESENT so notify TRUE always.
|
||||||
} else {
|
*
|
||||||
/* TODO: There doesn't seem to be any other
|
* ofono_sim_inserted_notify skips and returns if
|
||||||
* way to force the core SIM code to
|
* present/not_present status doesn't change from previous.
|
||||||
* recheck the PIN.
|
*/
|
||||||
* Wouldn't __ofono_sim_refresh be
|
ofono_sim_inserted_notify(sim, TRUE);
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
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);
|
__ofono_sim_recheck_pin(sim);
|
||||||
|
|
||||||
if (current_online_state == RIL_ONLINE_PREF) {
|
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;
|
current_online_state = RIL_ONLINE_PREF;
|
||||||
|
|
||||||
if (status.card_state == RIL_CARDSTATE_ABSENT) {
|
if (status.card_state == RIL_CARDSTATE_ABSENT) {
|
||||||
DBG("sd->card_state:%u,status.card_state:%u,",
|
ofono_info("%s: RIL_CARDSTATE_ABSENT", __func__);
|
||||||
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_sim_inserted_notify(sim, FALSE);
|
||||||
|
|
||||||
|
sd->removed = TRUE;
|
||||||
sd->initialized = FALSE;
|
sd->initialized = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: if no SIM present, handle emergency calling. */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int send_get_sim_status(struct ofono_sim *sim)
|
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) &&
|
if (ril_util_parse_sim_status(sd->ril, message, &status, apps) &&
|
||||||
status.num_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
|
/* TODO(CDMA): need some kind of logic to
|
||||||
* set the correct app_index,
|
* set the correct app_index,
|
||||||
*/
|
*/
|
||||||
@@ -1117,15 +1105,14 @@ static gboolean ril_sim_register(gpointer user)
|
|||||||
|
|
||||||
DBG("");
|
DBG("");
|
||||||
|
|
||||||
sd->idle_id = 0;
|
ofono_sim_register(sim);
|
||||||
|
|
||||||
send_get_sim_status(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);
|
(GRilNotifyFunc) ril_sim_status_changed, sim);
|
||||||
|
|
||||||
/* TODO: should we also register for RIL_UNSOL_SIM_REFRESH? */
|
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
315
ofono/drivers/telitmodem/location-reporting.c
Normal file
315
ofono/drivers/telitmodem/location-reporting.c
Normal 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, ¤t_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);
|
||||||
|
}
|
||||||
49
ofono/drivers/telitmodem/telitmodem.c
Normal file
49
ofono/drivers/telitmodem/telitmodem.c
Normal 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)
|
||||||
25
ofono/drivers/telitmodem/telitmodem.h
Normal file
25
ofono/drivers/telitmodem/telitmodem.h
Normal 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();
|
||||||
@@ -64,11 +64,13 @@ struct _GAtPPP {
|
|||||||
struct pppcp_data *ipcp;
|
struct pppcp_data *ipcp;
|
||||||
struct ppp_net *net;
|
struct ppp_net *net;
|
||||||
struct ppp_chap *chap;
|
struct ppp_chap *chap;
|
||||||
|
struct ppp_pap *pap;
|
||||||
GAtHDLC *hdlc;
|
GAtHDLC *hdlc;
|
||||||
gint mru;
|
gint mru;
|
||||||
gint mtu;
|
gint mtu;
|
||||||
char username[256];
|
char username[256];
|
||||||
char password[256];
|
char password[256];
|
||||||
|
GAtPPPAuthMethod auth_method;
|
||||||
GAtPPPConnectFunc connect_cb;
|
GAtPPPConnectFunc connect_cb;
|
||||||
gpointer connect_data;
|
gpointer connect_data;
|
||||||
GAtPPPDisconnectFunc disconnect_cb;
|
GAtPPPDisconnectFunc disconnect_cb;
|
||||||
@@ -150,13 +152,15 @@ static inline gboolean ppp_drop_packet(GAtPPP *ppp, guint16 protocol)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
break;
|
break;
|
||||||
case PPP_PHASE_AUTHENTICATION:
|
case PPP_PHASE_AUTHENTICATION:
|
||||||
if (protocol != LCP_PROTOCOL && protocol != CHAP_PROTOCOL)
|
if (protocol != LCP_PROTOCOL && protocol != CHAP_PROTOCOL &&
|
||||||
|
protocol != PAP_PROTOCOL)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
break;
|
break;
|
||||||
case PPP_PHASE_DEAD:
|
case PPP_PHASE_DEAD:
|
||||||
return TRUE;
|
return TRUE;
|
||||||
case PPP_PHASE_NETWORK:
|
case PPP_PHASE_NETWORK:
|
||||||
if (protocol != LCP_PROTOCOL && protocol != CHAP_PROTOCOL &&
|
if (protocol != LCP_PROTOCOL && protocol != CHAP_PROTOCOL &&
|
||||||
|
protocol != PAP_PROTOCOL &&
|
||||||
protocol != IPCP_PROTO)
|
protocol != IPCP_PROTO)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
break;
|
break;
|
||||||
@@ -221,6 +225,13 @@ static void ppp_receive(const unsigned char *buf, gsize len, void *data)
|
|||||||
break;
|
break;
|
||||||
case IPCP_PROTO:
|
case IPCP_PROTO:
|
||||||
pppcp_process_packet(ppp->ipcp, packet, len - offset);
|
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;
|
break;
|
||||||
case CHAP_PROTOCOL:
|
case CHAP_PROTOCOL:
|
||||||
if (ppp->chap) {
|
if (ppp->chap) {
|
||||||
@@ -359,6 +370,12 @@ void ppp_set_auth(GAtPPP *ppp, const guint8* auth_data)
|
|||||||
guint16 proto = get_host_short(auth_data);
|
guint16 proto = get_host_short(auth_data);
|
||||||
|
|
||||||
switch (proto) {
|
switch (proto) {
|
||||||
|
case PAP_PROTOCOL:
|
||||||
|
if (ppp->pap)
|
||||||
|
ppp_pap_free(ppp->pap);
|
||||||
|
|
||||||
|
ppp->pap = ppp_pap_new(ppp);
|
||||||
|
break;
|
||||||
case CHAP_PROTOCOL:
|
case CHAP_PROTOCOL:
|
||||||
if (ppp->chap)
|
if (ppp->chap)
|
||||||
ppp_chap_free(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)
|
void ppp_lcp_up_notify(GAtPPP *ppp)
|
||||||
{
|
{
|
||||||
/* Wait for the peer to send us a challenge if we expect auth */
|
|
||||||
if (ppp->chap != NULL) {
|
if (ppp->chap != NULL) {
|
||||||
|
/* Wait for the peer to send us a challenge. */
|
||||||
ppp_enter_phase(ppp, PPP_PHASE_AUTHENTICATION);
|
ppp_enter_phase(ppp, PPP_PHASE_AUTHENTICATION);
|
||||||
return;
|
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 */
|
/* Otherwise proceed as if auth succeeded */
|
||||||
@@ -588,6 +614,22 @@ const char *g_at_ppp_get_password(GAtPPP *ppp)
|
|||||||
return ppp->password;
|
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)
|
void g_at_ppp_set_recording(GAtPPP *ppp, const char *filename)
|
||||||
{
|
{
|
||||||
if (ppp == NULL)
|
if (ppp == NULL)
|
||||||
@@ -727,6 +769,9 @@ void g_at_ppp_unref(GAtPPP *ppp)
|
|||||||
else if (ppp->fd >= 0)
|
else if (ppp->fd >= 0)
|
||||||
close(ppp->fd);
|
close(ppp->fd);
|
||||||
|
|
||||||
|
if (ppp->pap)
|
||||||
|
ppp_pap_free(ppp->pap);
|
||||||
|
|
||||||
if (ppp->chap)
|
if (ppp->chap)
|
||||||
ppp_chap_free(ppp->chap);
|
ppp_chap_free(ppp->chap);
|
||||||
|
|
||||||
@@ -794,6 +839,9 @@ static GAtPPP *ppp_init_common(gboolean is_server, guint32 ip)
|
|||||||
/* initialize IPCP state */
|
/* initialize IPCP state */
|
||||||
ppp->ipcp = ipcp_new(ppp, is_server, ip);
|
ppp->ipcp = ipcp_new(ppp, is_server, ip);
|
||||||
|
|
||||||
|
/* chap authentication by default */
|
||||||
|
ppp->auth_method = G_AT_PPP_AUTH_METHOD_CHAP;
|
||||||
|
|
||||||
return ppp;
|
return ppp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,11 @@ typedef enum _GAtPPPDisconnectReason {
|
|||||||
G_AT_PPP_REASON_LOCAL_CLOSE, /* Normal user close */
|
G_AT_PPP_REASON_LOCAL_CLOSE, /* Normal user close */
|
||||||
} GAtPPPDisconnectReason;
|
} 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,
|
typedef void (*GAtPPPConnectFunc)(const char *iface, const char *local,
|
||||||
const char *peer,
|
const char *peer,
|
||||||
const char *dns1, const char *dns2,
|
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_username(GAtPPP *ppp);
|
||||||
const char *g_at_ppp_get_password(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_recording(GAtPPP *ppp, const char *filename);
|
||||||
|
|
||||||
void g_at_ppp_set_server_info(GAtPPP *ppp, const char *remote_ip,
|
void g_at_ppp_set_server_info(GAtPPP *ppp, const char *remote_ip,
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#include "ppp_cp.h"
|
#include "ppp_cp.h"
|
||||||
|
|
||||||
#define LCP_PROTOCOL 0xc021
|
#define LCP_PROTOCOL 0xc021
|
||||||
|
#define PAP_PROTOCOL 0xc023
|
||||||
#define CHAP_PROTOCOL 0xc223
|
#define CHAP_PROTOCOL 0xc223
|
||||||
#define IPCP_PROTO 0x8021
|
#define IPCP_PROTO 0x8021
|
||||||
#define IPV6CP_PROTO 0x8057
|
#define IPV6CP_PROTO 0x8057
|
||||||
@@ -38,6 +39,7 @@
|
|||||||
|
|
||||||
struct ppp_chap;
|
struct ppp_chap;
|
||||||
struct ppp_net;
|
struct ppp_net;
|
||||||
|
struct ppp_pap;
|
||||||
|
|
||||||
struct ppp_header {
|
struct ppp_header {
|
||||||
guint8 address;
|
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,
|
void ppp_chap_process_packet(struct ppp_chap *chap, const guint8 *new_packet,
|
||||||
gsize len);
|
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 */
|
/* TUN / Network related functions */
|
||||||
struct ppp_net *ppp_net_new(GAtPPP *ppp, int fd);
|
struct ppp_net *ppp_net_new(GAtPPP *ppp, int fd);
|
||||||
const char *ppp_net_get_interface(struct ppp_net *net);
|
const char *ppp_net_get_interface(struct ppp_net *net);
|
||||||
|
|||||||
@@ -54,6 +54,38 @@ enum chap_code {
|
|||||||
FAILURE
|
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)
|
static void chap_process_challenge(struct ppp_chap *chap, const guint8 *packet)
|
||||||
{
|
{
|
||||||
const struct chap_header *header = (const struct chap_header *) 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;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -238,25 +238,49 @@ static enum rcr_result lcp_rcr(struct pppcp_data *pppcp,
|
|||||||
guint8 method = option_data[2];
|
guint8 method = option_data[2];
|
||||||
guint8 *option;
|
guint8 *option;
|
||||||
|
|
||||||
if ((proto == CHAP_PROTOCOL) && (method == MD5))
|
switch (g_at_ppp_get_auth_method(ppp)) {
|
||||||
break;
|
case G_AT_PPP_AUTH_METHOD_CHAP:
|
||||||
|
if (proto == CHAP_PROTOCOL && method == MD5)
|
||||||
|
break;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* try to suggest CHAP & MD5. If we are out
|
* Try to suggest CHAP/MD5.
|
||||||
* of memory, just reject.
|
* Just reject if we run out of memory.
|
||||||
*/
|
*/
|
||||||
|
option = g_try_malloc0(5);
|
||||||
|
if (option == NULL)
|
||||||
|
return RCR_REJECT;
|
||||||
|
|
||||||
option = g_try_malloc0(5);
|
option[0] = AUTH_PROTO;
|
||||||
if (option == NULL)
|
option[1] = 5;
|
||||||
return RCR_REJECT;
|
put_network_short(&option[2], CHAP_PROTOCOL);
|
||||||
|
option[4] = MD5;
|
||||||
|
*new_options = option;
|
||||||
|
*new_len = 5;
|
||||||
|
|
||||||
option[0] = AUTH_PROTO;
|
return RCR_NAK;
|
||||||
option[1] = 5;
|
|
||||||
put_network_short(&option[2], CHAP_PROTOCOL);
|
case G_AT_PPP_AUTH_METHOD_PAP:
|
||||||
option[4] = MD5;
|
if (proto == PAP_PROTOCOL)
|
||||||
*new_options = option;
|
break;
|
||||||
*new_len = 5;
|
|
||||||
return RCR_NAK;
|
/*
|
||||||
|
* 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 ACCM:
|
||||||
case PFC:
|
case PFC:
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ struct GDBusClient {
|
|||||||
GDBusWatchFunction connect_func;
|
GDBusWatchFunction connect_func;
|
||||||
void *connect_data;
|
void *connect_data;
|
||||||
GDBusWatchFunction disconn_func;
|
GDBusWatchFunction disconn_func;
|
||||||
|
gboolean connected;
|
||||||
void *disconn_data;
|
void *disconn_data;
|
||||||
GDBusMessageFunction signal_func;
|
GDBusMessageFunction signal_func;
|
||||||
void *signal_data;
|
void *signal_data;
|
||||||
@@ -1146,6 +1147,8 @@ static void service_connect(DBusConnection *conn, void *user_data)
|
|||||||
|
|
||||||
get_managed_objects(client);
|
get_managed_objects(client);
|
||||||
|
|
||||||
|
client->connected = TRUE;
|
||||||
|
|
||||||
g_dbus_client_unref(client);
|
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);
|
g_list_free_full(client->proxy_list, proxy_free);
|
||||||
client->proxy_list = NULL;
|
client->proxy_list = NULL;
|
||||||
|
|
||||||
if (client->disconn_func)
|
if (client->disconn_func) {
|
||||||
client->disconn_func(conn, client->disconn_data);
|
client->disconn_func(conn, client->disconn_data);
|
||||||
|
client->connected = FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static DBusHandlerResult message_filter(DBusConnection *connection,
|
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->dbus_conn = dbus_connection_ref(connection);
|
||||||
client->service_name = g_strdup(service);
|
client->service_name = g_strdup(service);
|
||||||
client->base_path = g_strdup(path);
|
client->base_path = g_strdup(path);
|
||||||
|
client->connected = FALSE;
|
||||||
|
|
||||||
client->match_rules = g_ptr_array_sized_new(1);
|
client->match_rules = g_ptr_array_sized_new(1);
|
||||||
g_ptr_array_set_free_func(client->match_rules, g_free);
|
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);
|
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);
|
client->disconn_func(client->dbus_conn, client->disconn_data);
|
||||||
|
|
||||||
g_dbus_remove_watch(client->dbus_conn, client->watch);
|
g_dbus_remove_watch(client->dbus_conn, client->watch);
|
||||||
|
|||||||
@@ -88,16 +88,22 @@ static gboolean watch_func(GIOChannel *chan, GIOCondition cond, gpointer data)
|
|||||||
struct watch_info *info = data;
|
struct watch_info *info = data;
|
||||||
unsigned int flags = 0;
|
unsigned int flags = 0;
|
||||||
DBusDispatchStatus status;
|
DBusDispatchStatus status;
|
||||||
|
DBusConnection *conn;
|
||||||
|
|
||||||
if (cond & G_IO_IN) flags |= DBUS_WATCH_READABLE;
|
if (cond & G_IO_IN) flags |= DBUS_WATCH_READABLE;
|
||||||
if (cond & G_IO_OUT) flags |= DBUS_WATCH_WRITABLE;
|
if (cond & G_IO_OUT) flags |= DBUS_WATCH_WRITABLE;
|
||||||
if (cond & G_IO_HUP) flags |= DBUS_WATCH_HANGUP;
|
if (cond & G_IO_HUP) flags |= DBUS_WATCH_HANGUP;
|
||||||
if (cond & G_IO_ERR) flags |= DBUS_WATCH_ERROR;
|
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);
|
dbus_watch_handle(info->watch, flags);
|
||||||
|
|
||||||
status = dbus_connection_get_dispatch_status(info->conn);
|
status = dbus_connection_get_dispatch_status(conn);
|
||||||
queue_dispatch(info->conn, status);
|
queue_dispatch(conn, status);
|
||||||
|
|
||||||
|
dbus_connection_unref(conn);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1088,7 +1088,6 @@ static const GDBusMethodTable introspect_methods[] = {
|
|||||||
static void append_interfaces(struct generic_data *data, DBusMessageIter *iter)
|
static void append_interfaces(struct generic_data *data, DBusMessageIter *iter)
|
||||||
{
|
{
|
||||||
DBusMessageIter array;
|
DBusMessageIter array;
|
||||||
GSList *l;
|
|
||||||
|
|
||||||
dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
|
dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
|
||||||
DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
|
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
|
||||||
DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &array);
|
DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &array);
|
||||||
|
|
||||||
for (l = data->interfaces; l != NULL; l = l->next) {
|
g_slist_foreach(data->interfaces, append_interface, &array);
|
||||||
if (g_slist_find(data->added, l->data))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
append_interface(l->data, &array);
|
|
||||||
}
|
|
||||||
|
|
||||||
dbus_message_iter_close_container(iter, &array);
|
dbus_message_iter_close_container(iter, &array);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -362,6 +362,7 @@ static void service_data_free(struct service_data *data)
|
|||||||
callback->data = NULL;
|
callback->data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Returns TRUE if data is freed */
|
||||||
static gboolean filter_data_remove_callback(struct filter_data *data,
|
static gboolean filter_data_remove_callback(struct filter_data *data,
|
||||||
struct filter_callback *cb)
|
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
|
/* Don't remove the filter if other callbacks exist or data is lock
|
||||||
* processing callbacks */
|
* processing callbacks */
|
||||||
if (data->callbacks || data->lock)
|
if (data->callbacks || data->lock)
|
||||||
return TRUE;
|
return FALSE;
|
||||||
|
|
||||||
if (data->registered && !remove_match(data))
|
if (data->registered && !remove_match(data))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@@ -405,7 +406,9 @@ static DBusHandlerResult signal_filter(DBusConnection *connection,
|
|||||||
|
|
||||||
if (cb->signal_func && !cb->signal_func(connection, message,
|
if (cb->signal_func && !cb->signal_func(connection, message,
|
||||||
cb->user_data)) {
|
cb->user_data)) {
|
||||||
filter_data_remove_callback(data, cb);
|
if (filter_data_remove_callback(data, cb))
|
||||||
|
break;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -489,7 +492,9 @@ static DBusHandlerResult service_filter(DBusConnection *connection,
|
|||||||
/* Only auto remove if it is a bus name watch */
|
/* Only auto remove if it is a bus name watch */
|
||||||
if (data->argument[0] == ':' &&
|
if (data->argument[0] == ':' &&
|
||||||
(cb->conn_func == NULL || cb->disc_func == NULL)) {
|
(cb->conn_func == NULL || cb->disc_func == NULL)) {
|
||||||
filter_data_remove_callback(data, cb);
|
if (filter_data_remove_callback(data, cb))
|
||||||
|
break;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -586,7 +591,6 @@ static gboolean update_service(void *user_data)
|
|||||||
struct filter_callback *cb = data->callback;
|
struct filter_callback *cb = data->callback;
|
||||||
DBusConnection *conn;
|
DBusConnection *conn;
|
||||||
|
|
||||||
update_name_cache(data->name, data->owner);
|
|
||||||
conn = dbus_connection_ref(data->conn);
|
conn = dbus_connection_ref(data->conn);
|
||||||
service_data_free(data);
|
service_data_free(data);
|
||||||
|
|
||||||
@@ -695,7 +699,8 @@ guint g_dbus_add_service_watch(DBusConnection *connection, const char *name,
|
|||||||
if (name == NULL)
|
if (name == NULL)
|
||||||
return 0;
|
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",
|
DBUS_INTERFACE_DBUS, "NameOwnerChanged",
|
||||||
name);
|
name);
|
||||||
if (data == NULL)
|
if (data == NULL)
|
||||||
|
|||||||
@@ -104,6 +104,9 @@ enum ofono_emulator_request_type ofono_emulator_request_get_type(
|
|||||||
|
|
||||||
void ofono_emulator_set_indicator(struct ofono_emulator *em,
|
void ofono_emulator_set_indicator(struct ofono_emulator *em,
|
||||||
const char *name, int value);
|
const char *name, int value);
|
||||||
|
void ofono_emulator_set_hf_indicator_active(struct ofono_emulator *em,
|
||||||
|
int indicator,
|
||||||
|
ofono_bool_t active);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,6 +48,11 @@ enum ofono_gprs_context_type {
|
|||||||
OFONO_GPRS_CONTEXT_TYPE_IMS,
|
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 {
|
struct ofono_gprs_primary_context {
|
||||||
unsigned int cid;
|
unsigned int cid;
|
||||||
int direction;
|
int direction;
|
||||||
@@ -55,6 +60,7 @@ struct ofono_gprs_primary_context {
|
|||||||
char username[OFONO_GPRS_MAX_USERNAME_LENGTH + 1];
|
char username[OFONO_GPRS_MAX_USERNAME_LENGTH + 1];
|
||||||
char password[OFONO_GPRS_MAX_PASSWORD_LENGTH + 1];
|
char password[OFONO_GPRS_MAX_PASSWORD_LENGTH + 1];
|
||||||
enum ofono_gprs_proto proto;
|
enum ofono_gprs_proto proto;
|
||||||
|
enum ofono_gprs_auth_method auth_method;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef void (*ofono_gprs_context_cb_t)(const struct ofono_error *error,
|
typedef void (*ofono_gprs_context_cb_t)(const struct ofono_error *error,
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ struct ofono_gprs_provision_data {
|
|||||||
char *apn;
|
char *apn;
|
||||||
char *username;
|
char *username;
|
||||||
char *password;
|
char *password;
|
||||||
|
enum ofono_gprs_auth_method auth_method;
|
||||||
char *message_proxy;
|
char *message_proxy;
|
||||||
char *message_center;
|
char *message_center;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -56,6 +56,9 @@ struct ofono_handsfree_driver {
|
|||||||
ofono_handsfree_cb_t cb, void *data);
|
ofono_handsfree_cb_t cb, void *data);
|
||||||
void (*disable_nrec)(struct ofono_handsfree *hf,
|
void (*disable_nrec)(struct ofono_handsfree *hf,
|
||||||
ofono_handsfree_cb_t cb, void *data);
|
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,
|
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,
|
void ofono_handsfree_voice_recognition_notify(struct ofono_handsfree *hf,
|
||||||
ofono_bool_t enabled);
|
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,
|
void ofono_handsfree_battchg_notify(struct ofono_handsfree *hf,
|
||||||
unsigned char level);
|
unsigned char level);
|
||||||
|
|
||||||
|
|||||||
@@ -29,10 +29,10 @@ extern "C" {
|
|||||||
#include <ofono/types.h>
|
#include <ofono/types.h>
|
||||||
|
|
||||||
enum ofono_radio_access_mode {
|
enum ofono_radio_access_mode {
|
||||||
OFONO_RADIO_ACCESS_MODE_ANY = 0,
|
OFONO_RADIO_ACCESS_MODE_ANY = 0x0,
|
||||||
OFONO_RADIO_ACCESS_MODE_GSM = 1,
|
OFONO_RADIO_ACCESS_MODE_GSM = 0x1,
|
||||||
OFONO_RADIO_ACCESS_MODE_UMTS = 2,
|
OFONO_RADIO_ACCESS_MODE_UMTS = 0x2,
|
||||||
OFONO_RADIO_ACCESS_MODE_LTE = 3,
|
OFONO_RADIO_ACCESS_MODE_LTE = 0x4,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ofono_radio_band_gsm {
|
enum ofono_radio_band_gsm {
|
||||||
@@ -80,6 +80,11 @@ typedef void (*ofono_radio_settings_fast_dormancy_query_cb_t)(
|
|||||||
ofono_bool_t enable,
|
ofono_bool_t enable,
|
||||||
void *data);
|
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 {
|
struct ofono_radio_settings_driver {
|
||||||
const char *name;
|
const char *name;
|
||||||
int (*probe)(struct ofono_radio_settings *rs, unsigned int vendor,
|
int (*probe)(struct ofono_radio_settings *rs, unsigned int vendor,
|
||||||
@@ -107,6 +112,9 @@ struct ofono_radio_settings_driver {
|
|||||||
ofono_bool_t enable,
|
ofono_bool_t enable,
|
||||||
ofono_radio_settings_fast_dormancy_set_cb_t,
|
ofono_radio_settings_fast_dormancy_set_cb_t,
|
||||||
void *data);
|
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(
|
int ofono_radio_settings_driver_register(
|
||||||
|
|||||||
126
ofono/plugins/emulator_fuzz.c
Normal file
126
ofono/plugins/emulator_fuzz.c
Normal 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)
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
*
|
*
|
||||||
* oFono - Open Source Telephony
|
* 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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2 as
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
@@ -46,6 +46,7 @@
|
|||||||
#include <ofono/call-settings.h>
|
#include <ofono/call-settings.h>
|
||||||
#include <ofono/devinfo.h>
|
#include <ofono/devinfo.h>
|
||||||
#include <ofono/message-waiting.h>
|
#include <ofono/message-waiting.h>
|
||||||
|
#include <ofono/location-reporting.h>
|
||||||
#include <ofono/netreg.h>
|
#include <ofono/netreg.h>
|
||||||
#include <ofono/phonebook.h>
|
#include <ofono/phonebook.h>
|
||||||
#include <ofono/sim.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);
|
ofono_devinfo_create(modem, 0, "atmodem", data->chat);
|
||||||
data->sim = ofono_sim_create(modem, OFONO_VENDOR_TELIT, "atmodem",
|
data->sim = ofono_sim_create(modem, OFONO_VENDOR_TELIT, "atmodem",
|
||||||
data->chat);
|
data->chat);
|
||||||
|
ofono_location_reporting_create(modem, 0, "telitmodem", data->chat);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void he910_post_online(struct ofono_modem *modem)
|
static void he910_post_online(struct ofono_modem *modem)
|
||||||
|
|||||||
@@ -232,7 +232,7 @@ static void sim_state_watch(enum ofono_sim_state new_state, void *data)
|
|||||||
if (modems->next != NULL)
|
if (modems->next != NULL)
|
||||||
return;
|
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);
|
HFP_AG_EXT_PROFILE_PATH, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -299,7 +299,7 @@ static void voicecall_watch(struct ofono_atom *atom,
|
|||||||
if (modems->next != NULL)
|
if (modems->next != NULL)
|
||||||
return;
|
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);
|
HFP_AG_EXT_PROFILE_PATH, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ struct hfp {
|
|||||||
struct ofono_handsfree_card *card;
|
struct ofono_handsfree_card *card;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const char *none_prefix[] = { NULL };
|
||||||
static GDBusClient *bluez = NULL;
|
static GDBusClient *bluez = NULL;
|
||||||
|
|
||||||
static void hfp_debug(const char *str, void *user_data)
|
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);
|
sprintf(str, "AT+BCS=%d", value);
|
||||||
|
|
||||||
done:
|
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,
|
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 ...");
|
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);
|
HFP_EXT_PROFILE_PATH, NULL, features);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -132,6 +132,37 @@ static const GMarkupParser text_parser = {
|
|||||||
NULL,
|
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,
|
static void usage_start(GMarkupParseContext *context,
|
||||||
const gchar **attribute_names,
|
const gchar **attribute_names,
|
||||||
const gchar **attribute_values,
|
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"))
|
else if (g_str_equal(element_name, "password"))
|
||||||
g_markup_parse_context_push(context, &text_parser,
|
g_markup_parse_context_push(context, &text_parser,
|
||||||
&apn->password);
|
&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"))
|
else if (g_str_equal(element_name, "mmsc"))
|
||||||
g_markup_parse_context_push(context, &text_parser,
|
g_markup_parse_context_push(context, &text_parser,
|
||||||
&apn->message_center);
|
&apn->message_center);
|
||||||
@@ -298,6 +332,7 @@ static void apn_handler(GMarkupParseContext *context, struct gsm_data *gsm,
|
|||||||
ap->apn = g_strdup(apn);
|
ap->apn = g_strdup(apn);
|
||||||
ap->type = OFONO_GPRS_CONTEXT_TYPE_INTERNET;
|
ap->type = OFONO_GPRS_CONTEXT_TYPE_INTERNET;
|
||||||
ap->proto = OFONO_GPRS_PROTO_IP;
|
ap->proto = OFONO_GPRS_PROTO_IP;
|
||||||
|
ap->auth_method = OFONO_GPRS_AUTH_METHOD_CHAP;
|
||||||
|
|
||||||
g_markup_parse_context_push(context, &apn_parser, ap);
|
g_markup_parse_context_push(context, &apn_parser, ap);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -351,6 +351,65 @@ static void phonesim_ctm_set(struct ofono_ctm *ctm, ofono_bool_t enable,
|
|||||||
g_free(cbd);
|
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 = {
|
static struct ofono_gprs_context_driver context_driver = {
|
||||||
.name = "phonesim",
|
.name = "phonesim",
|
||||||
.probe = phonesim_context_probe,
|
.probe = phonesim_context_probe,
|
||||||
@@ -359,6 +418,14 @@ static struct ofono_gprs_context_driver context_driver = {
|
|||||||
.deactivate_primary = phonesim_deactivate_primary,
|
.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 = {
|
static struct ofono_ctm_driver ctm_driver = {
|
||||||
.name = "phonesim",
|
.name = "phonesim",
|
||||||
.probe = phonesim_ctm_probe,
|
.probe = phonesim_ctm_probe,
|
||||||
@@ -791,6 +858,8 @@ static void phonesim_post_sim(struct ofono_modem *modem)
|
|||||||
|
|
||||||
if (!data->calypso)
|
if (!data->calypso)
|
||||||
ofono_sms_create(modem, 0, "atmodem", data->chat);
|
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)
|
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_gprs_context_driver_register(&context_driver);
|
||||||
ofono_ctm_driver_register(&ctm_driver);
|
ofono_ctm_driver_register(&ctm_driver);
|
||||||
|
ofono_radio_settings_driver_register(&radio_settings_driver);
|
||||||
|
|
||||||
if (conf_override)
|
if (conf_override)
|
||||||
parse_config(conf_override);
|
parse_config(conf_override);
|
||||||
@@ -1103,6 +1173,7 @@ static void phonesim_exit(void)
|
|||||||
g_slist_free(modem_list);
|
g_slist_free(modem_list);
|
||||||
modem_list = NULL;
|
modem_list = NULL;
|
||||||
|
|
||||||
|
ofono_radio_settings_driver_unregister(&radio_settings_driver);
|
||||||
ofono_ctm_driver_unregister(&ctm_driver);
|
ofono_ctm_driver_unregister(&ctm_driver);
|
||||||
|
|
||||||
ofono_gprs_context_driver_unregister(&context_driver);
|
ofono_gprs_context_driver_unregister(&context_driver);
|
||||||
|
|||||||
376
ofono/plugins/quectel.c
Normal file
376
ofono/plugins/quectel.c
Normal 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)
|
||||||
@@ -91,7 +91,6 @@ struct ril_data {
|
|||||||
int power_on_retries;
|
int power_on_retries;
|
||||||
int sim_status_retries;
|
int sim_status_retries;
|
||||||
ofono_bool_t connected;
|
ofono_bool_t connected;
|
||||||
ofono_bool_t have_sim;
|
|
||||||
ofono_bool_t online;
|
ofono_bool_t online;
|
||||||
ofono_bool_t reported;
|
ofono_bool_t reported;
|
||||||
guint timer_id;
|
guint timer_id;
|
||||||
@@ -141,17 +140,12 @@ static void sim_status_cb(struct ril_msg *message, gpointer user_data)
|
|||||||
else
|
else
|
||||||
ofono_error("Max retries for GET_SIM_STATUS exceeded!");
|
ofono_error("Max retries for GET_SIM_STATUS exceeded!");
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
/* Returns TRUE if cardstate == PRESENT */
|
/* Returns TRUE if cardstate == PRESENT */
|
||||||
if (ril_util_parse_sim_status(ril->modem, message,
|
if (ril_util_parse_sim_status(ril->modem, message,
|
||||||
&status, apps)) {
|
&status, apps)) {
|
||||||
DBG("have_sim = TRUE; num_apps: %d",
|
|
||||||
status.num_apps);
|
|
||||||
|
|
||||||
if (status.num_apps)
|
if (status.num_apps)
|
||||||
ril_util_free_sim_apps(apps, status.num_apps);
|
ril_util_free_sim_apps(apps, status.num_apps);
|
||||||
|
|
||||||
ril->have_sim = TRUE;
|
|
||||||
} else {
|
} else {
|
||||||
ofono_warn("No SIM card present.");
|
ofono_warn("No SIM card present.");
|
||||||
}
|
}
|
||||||
@@ -237,13 +231,8 @@ static void ril_pre_sim(struct ofono_modem *modem)
|
|||||||
{
|
{
|
||||||
DBG("");
|
DBG("");
|
||||||
struct ril_data *ril = ofono_modem_get_data(modem);
|
struct ril_data *ril = ofono_modem_get_data(modem);
|
||||||
struct ofono_sim *sim;
|
ofono_sim_create(modem, 0, "rilmodem", ril->modem);
|
||||||
|
|
||||||
sim = ofono_sim_create(modem, 0, "rilmodem", ril->modem);
|
|
||||||
ofono_voicecall_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)
|
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);
|
DBG(" modem: %p", modem);
|
||||||
struct ril_data *ril = ofono_modem_get_data(modem);
|
struct ril_data *ril = ofono_modem_get_data(modem);
|
||||||
|
|
||||||
ril->have_sim = FALSE;
|
|
||||||
|
|
||||||
/* RIL expects user radio */
|
/* RIL expects user radio */
|
||||||
ril_switchUser();
|
ril_switchUser();
|
||||||
|
|
||||||
|
|||||||
292
ofono/plugins/ublox.c
Normal file
292
ofono/plugins/ublox.c
Normal 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)
|
||||||
@@ -636,7 +636,7 @@ static gboolean setup_telit(struct modem_info *modem)
|
|||||||
|
|
||||||
static gboolean setup_he910(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;
|
GSList *list;
|
||||||
|
|
||||||
DBG("%s", modem->syspath);
|
DBG("%s", modem->syspath);
|
||||||
@@ -652,16 +652,19 @@ static gboolean setup_he910(struct modem_info *modem)
|
|||||||
mdm = info->devnode;
|
mdm = info->devnode;
|
||||||
else if (g_strcmp0(info->number, "06") == 0)
|
else if (g_strcmp0(info->number, "06") == 0)
|
||||||
aux = info->devnode;
|
aux = info->devnode;
|
||||||
|
else if (g_strcmp0(info->number, "0a") == 0)
|
||||||
|
gps = info->devnode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aux == NULL || mdm == NULL)
|
if (aux == NULL || mdm == NULL)
|
||||||
return FALSE;
|
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, "Modem", mdm);
|
||||||
ofono_modem_set_string(modem->modem, "Aux", aux);
|
ofono_modem_set_string(modem->modem, "Aux", aux);
|
||||||
|
ofono_modem_set_string(modem->modem, "GPS", gps);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@@ -791,6 +794,86 @@ static gboolean setup_samsung(struct modem_info *modem)
|
|||||||
return TRUE;
|
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 {
|
static struct {
|
||||||
const char *name;
|
const char *name;
|
||||||
gboolean (*setup)(struct modem_info *modem);
|
gboolean (*setup)(struct modem_info *modem);
|
||||||
@@ -815,6 +898,8 @@ static struct {
|
|||||||
{ "zte", setup_zte },
|
{ "zte", setup_zte },
|
||||||
{ "icera", setup_icera },
|
{ "icera", setup_icera },
|
||||||
{ "samsung", setup_samsung },
|
{ "samsung", setup_samsung },
|
||||||
|
{ "quectel", setup_quectel },
|
||||||
|
{ "ublox", setup_ublox },
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1026,6 +1111,8 @@ static struct {
|
|||||||
{ "nokia", "option", "0421", "0623" },
|
{ "nokia", "option", "0421", "0623" },
|
||||||
{ "samsung", "option", "04e8", "6889" },
|
{ "samsung", "option", "04e8", "6889" },
|
||||||
{ "samsung", "kalmia" },
|
{ "samsung", "kalmia" },
|
||||||
|
{ "quectel", "option", "05c6", "9090" },
|
||||||
|
{ "ublox", "cdc_acm", "1546", "1102" },
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|
||||||
@@ -42,17 +43,18 @@ struct ofono_emulator {
|
|||||||
enum ofono_emulator_type type;
|
enum ofono_emulator_type type;
|
||||||
GAtServer *server;
|
GAtServer *server;
|
||||||
GAtPPP *ppp;
|
GAtPPP *ppp;
|
||||||
gboolean slc;
|
|
||||||
int l_features;
|
int l_features;
|
||||||
int r_features;
|
int r_features;
|
||||||
int events_mode;
|
|
||||||
gboolean events_ind;
|
|
||||||
unsigned char cmee_mode;
|
|
||||||
GSList *indicators;
|
GSList *indicators;
|
||||||
guint callsetup_source;
|
guint callsetup_source;
|
||||||
gboolean clip;
|
|
||||||
gboolean ccwa;
|
|
||||||
int pns_id;
|
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 {
|
struct indicator {
|
||||||
@@ -453,7 +455,7 @@ static void brsf_cb(GAtServer *server, GAtServerRequestType type,
|
|||||||
if (g_at_result_iter_next_number(&iter, &val) == FALSE)
|
if (g_at_result_iter_next_number(&iter, &val) == FALSE)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
if (val < 0 || val > 255)
|
if (val < 0 || val > 0xffff)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
em->r_features = val;
|
em->r_features = val;
|
||||||
@@ -636,7 +638,8 @@ done:
|
|||||||
|
|
||||||
g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
|
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;
|
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,
|
static void emulator_add_indicator(struct ofono_emulator *em, const char* name,
|
||||||
int min, int max, int dflt,
|
int min, int max, int dflt,
|
||||||
gboolean mandatory)
|
gboolean mandatory)
|
||||||
@@ -906,6 +1016,8 @@ void ofono_emulator_register(struct ofono_emulator *em, int fd)
|
|||||||
em);
|
em);
|
||||||
|
|
||||||
if (em->type == OFONO_EMULATOR_TYPE_HFP) {
|
if (em->type == OFONO_EMULATOR_TYPE_HFP) {
|
||||||
|
em->ddr_active = true;
|
||||||
|
|
||||||
emulator_add_indicator(em, OFONO_EMULATOR_IND_SERVICE, 0, 1, 0,
|
emulator_add_indicator(em, OFONO_EMULATOR_IND_SERVICE, 0, 1, 0,
|
||||||
FALSE);
|
FALSE);
|
||||||
emulator_add_indicator(em, OFONO_EMULATOR_IND_CALL, 0, 1, 0,
|
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, "+CCWA", ccwa_cb, em, NULL);
|
||||||
g_at_server_register(em->server, "+CMEE", cmee_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, "+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);
|
__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_STATUS;
|
||||||
em->l_features |= HFP_AG_FEATURE_ENHANCED_CALL_CONTROL;
|
em->l_features |= HFP_AG_FEATURE_ENHANCED_CALL_CONTROL;
|
||||||
em->l_features |= HFP_AG_FEATURE_EXTENDED_RES_CODE;
|
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->events_mode = 3; /* default mode is forwarding events */
|
||||||
em->cmee_mode = 0; /* CME ERROR disabled by default */
|
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,
|
static void handler_proxy(GAtServer *server, GAtServerRequestType type,
|
||||||
GAtResult *result, gpointer userdata)
|
GAtResult *result, gpointer userdata)
|
||||||
{
|
{
|
||||||
struct handler *h = userdata;
|
struct handler *h = userdata;
|
||||||
struct ofono_emulator_request req;
|
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) {
|
switch (type) {
|
||||||
case G_AT_SERVER_REQUEST_TYPE_COMMAND_ONLY:
|
case G_AT_SERVER_REQUEST_TYPE_COMMAND_ONLY:
|
||||||
req.type = OFONO_EMULATOR_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);
|
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)
|
static void handler_destroy(gpointer userdata)
|
||||||
{
|
{
|
||||||
struct handler *h = 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)
|
void *data, ofono_destroy_func destroy)
|
||||||
{
|
{
|
||||||
struct handler *h;
|
struct handler *h;
|
||||||
|
GAtServerNotifyFunc func = handler_proxy;
|
||||||
|
|
||||||
h = g_new0(struct handler, 1);
|
h = g_new0(struct handler, 1);
|
||||||
h->cb = cb;
|
h->cb = cb;
|
||||||
@@ -1125,7 +1263,14 @@ ofono_bool_t ofono_emulator_add_handler(struct ofono_emulator *em,
|
|||||||
h->destroy = destroy;
|
h->destroy = destroy;
|
||||||
h->em = em;
|
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)
|
handler_destroy) == TRUE)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
@@ -1266,3 +1411,52 @@ void __ofono_emulator_set_indicator_forced(struct ofono_emulator *em,
|
|||||||
ind->deferred = TRUE;
|
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);
|
||||||
|
}
|
||||||
|
|||||||
@@ -268,6 +268,32 @@ static gboolean gprs_proto_from_string(const char *str,
|
|||||||
return FALSE;
|
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)
|
static unsigned int gprs_cid_alloc(struct ofono_gprs *gprs)
|
||||||
{
|
{
|
||||||
return idmap_alloc(gprs->cid_map);
|
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,
|
ofono_dbus_dict_append(dict, "Password", DBUS_TYPE_STRING,
|
||||||
&strvalue);
|
&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) {
|
if (ctx->type == OFONO_GPRS_CONTEXT_TYPE_MMS) {
|
||||||
strvalue = ctx->message_proxy;
|
strvalue = ctx->message_proxy;
|
||||||
ofono_dbus_dict_append(dict, "MessageProxy",
|
ofono_dbus_dict_append(dict, "MessageProxy",
|
||||||
@@ -1385,6 +1415,37 @@ static DBusMessage *pri_set_message_center(struct pri_context *ctx,
|
|||||||
return NULL;
|
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,
|
static DBusMessage *pri_set_property(DBusConnection *conn,
|
||||||
DBusMessage *msg, void *data)
|
DBusMessage *msg, void *data)
|
||||||
{
|
{
|
||||||
@@ -1495,6 +1556,13 @@ static DBusMessage *pri_set_property(DBusConnection *conn,
|
|||||||
dbus_message_iter_get_basic(&var, &str);
|
dbus_message_iter_get_basic(&var, &str);
|
||||||
|
|
||||||
return pri_set_name(ctx, conn, msg, 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)
|
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,
|
static void write_context_settings(struct ofono_gprs *gprs,
|
||||||
struct pri_context *context)
|
struct pri_context *context)
|
||||||
{
|
{
|
||||||
|
const char *auth_method;
|
||||||
|
|
||||||
g_key_file_set_string(gprs->settings, context->key,
|
g_key_file_set_string(gprs->settings, context->key,
|
||||||
"Name", context->name);
|
"Name", context->name);
|
||||||
g_key_file_set_string(gprs->settings, context->key,
|
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);
|
"Username", context->context.username);
|
||||||
g_key_file_set_string(gprs->settings, context->key,
|
g_key_file_set_string(gprs->settings, context->key,
|
||||||
"Password", context->context.password);
|
"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",
|
g_key_file_set_string(gprs->settings, context->key, "Type",
|
||||||
gprs_context_type_to_string(context->type));
|
gprs_context_type_to_string(context->type));
|
||||||
g_key_file_set_string(gprs->settings, context->key, "Protocol",
|
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 *apn = NULL;
|
||||||
char *msgproxy = NULL;
|
char *msgproxy = NULL;
|
||||||
char *msgcenter = NULL;
|
char *msgcenter = NULL;
|
||||||
|
char *authstr = NULL;
|
||||||
gboolean ret = FALSE;
|
gboolean ret = FALSE;
|
||||||
gboolean legacy = FALSE;
|
gboolean legacy = FALSE;
|
||||||
struct pri_context *context;
|
struct pri_context *context;
|
||||||
enum ofono_gprs_context_type type;
|
enum ofono_gprs_context_type type;
|
||||||
enum ofono_gprs_proto proto;
|
enum ofono_gprs_proto proto;
|
||||||
|
enum ofono_gprs_auth_method auth;
|
||||||
unsigned int id;
|
unsigned int id;
|
||||||
|
|
||||||
if (sscanf(group, "context%d", &id) != 1) {
|
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)
|
if (password == NULL)
|
||||||
goto error;
|
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)
|
if (strlen(password) > OFONO_GPRS_MAX_PASSWORD_LENGTH)
|
||||||
goto error;
|
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.password, password);
|
||||||
strcpy(context->context.apn, apn);
|
strcpy(context->context.apn, apn);
|
||||||
context->context.proto = proto;
|
context->context.proto = proto;
|
||||||
|
context->context.auth_method = auth;
|
||||||
|
|
||||||
if (msgproxy != NULL)
|
if (msgproxy != NULL)
|
||||||
strcpy(context->message_proxy, msgproxy);
|
strcpy(context->message_proxy, msgproxy);
|
||||||
@@ -3073,6 +3159,7 @@ error:
|
|||||||
g_free(apn);
|
g_free(apn);
|
||||||
g_free(msgproxy);
|
g_free(msgproxy);
|
||||||
g_free(msgcenter);
|
g_free(msgcenter);
|
||||||
|
g_free(authstr);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -3204,6 +3291,8 @@ static void provision_context(const struct ofono_gprs_provision_data *ap,
|
|||||||
if (ap->password != NULL)
|
if (ap->password != NULL)
|
||||||
strcpy(context->context.password, ap->password);
|
strcpy(context->context.password, ap->password);
|
||||||
|
|
||||||
|
context->context.auth_method = ap->auth_method;
|
||||||
|
|
||||||
strcpy(context->context.apn, ap->apn);
|
strcpy(context->context.apn, ap->apn);
|
||||||
context->context.proto = ap->proto;
|
context->context.proto = ap->proto;
|
||||||
|
|
||||||
|
|||||||
@@ -72,10 +72,10 @@ static ofono_bool_t transparent_sco = FALSE;
|
|||||||
static uint16_t codec2setting(uint8_t codec)
|
static uint16_t codec2setting(uint8_t codec)
|
||||||
{
|
{
|
||||||
switch (codec) {
|
switch (codec) {
|
||||||
case HFP_CODEC_CVSD:
|
case HFP_CODEC_CVSD:
|
||||||
return BT_VOICE_CVSD_16BIT;
|
return BT_VOICE_CVSD_16BIT;
|
||||||
default:
|
default:
|
||||||
return BT_VOICE_TRANSPARENT;
|
return BT_VOICE_TRANSPARENT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -51,6 +51,12 @@ struct ofono_handsfree {
|
|||||||
ofono_bool_t inband_ringing;
|
ofono_bool_t inband_ringing;
|
||||||
ofono_bool_t voice_recognition;
|
ofono_bool_t voice_recognition;
|
||||||
ofono_bool_t voice_recognition_pending;
|
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_features;
|
||||||
unsigned int ag_chld_features;
|
unsigned int ag_chld_features;
|
||||||
unsigned char battchg;
|
unsigned char battchg;
|
||||||
@@ -96,6 +102,9 @@ static const char **ag_features_list(unsigned int features,
|
|||||||
if (chld_features & HFP_AG_CHLD_4)
|
if (chld_features & HFP_AG_CHLD_4)
|
||||||
list[i++] = "transfer";
|
list[i++] = "transfer";
|
||||||
|
|
||||||
|
if (features & HFP_AG_FEATURE_HF_INDICATORS)
|
||||||
|
list[i++] = "hf-indicators";
|
||||||
|
|
||||||
list[i] = NULL;
|
list[i] = NULL;
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
@@ -244,6 +253,10 @@ static DBusMessage *generate_get_properties_reply(struct ofono_handsfree *hf,
|
|||||||
ofono_dbus_dict_append(&dict, "EchoCancelingNoiseReduction",
|
ofono_dbus_dict_append(&dict, "EchoCancelingNoiseReduction",
|
||||||
DBUS_TYPE_BOOLEAN, &hf->nrec);
|
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;
|
voice_recognition = hf->voice_recognition;
|
||||||
ofono_dbus_dict_append(&dict, "VoiceRecognition", DBUS_TYPE_BOOLEAN,
|
ofono_dbus_dict_append(&dict, "VoiceRecognition", DBUS_TYPE_BOOLEAN,
|
||||||
&voice_recognition);
|
&voice_recognition);
|
||||||
@@ -356,6 +369,82 @@ static void voicerec_set_cb(const struct ofono_error *error, void *data)
|
|||||||
&hf->voice_recognition);
|
&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)
|
static void nrec_set_cb(const struct ofono_error *error, void *data)
|
||||||
{
|
{
|
||||||
struct ofono_handsfree *hf = data;
|
struct ofono_handsfree *hf = data;
|
||||||
@@ -434,6 +523,37 @@ static DBusMessage *handsfree_set_property(DBusConnection *conn,
|
|||||||
|
|
||||||
hf->pending = dbus_message_ref(msg);
|
hf->pending = dbus_message_ref(msg);
|
||||||
hf->driver->disable_nrec(hf, nrec_set_cb, hf);
|
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
|
} else
|
||||||
return __ofono_error_invalid_args(msg);
|
return __ofono_error_invalid_args(msg);
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ enum hfp_ag_feature {
|
|||||||
HFP_AG_FEATURE_ENHANCED_CALL_CONTROL = 0x80,
|
HFP_AG_FEATURE_ENHANCED_CALL_CONTROL = 0x80,
|
||||||
HFP_AG_FEATURE_EXTENDED_RES_CODE = 0x100,
|
HFP_AG_FEATURE_EXTENDED_RES_CODE = 0x100,
|
||||||
HFP_AG_FEATURE_CODEC_NEGOTIATION = 0x200,
|
HFP_AG_FEATURE_CODEC_NEGOTIATION = 0x200,
|
||||||
|
HFP_AG_FEATURE_HF_INDICATORS = 0x400,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* HFP HF supported features bitmap. Bluetooth HFP 1.6 spec page 88 */
|
/* 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_STATUS = 0x20,
|
||||||
HFP_HF_FEATURE_ENHANCED_CALL_CONTROL = 0x40,
|
HFP_HF_FEATURE_ENHANCED_CALL_CONTROL = 0x40,
|
||||||
HFP_HF_FEATURE_CODEC_NEGOTIATION = 0x80,
|
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 */
|
/* 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 {
|
enum hfp_version {
|
||||||
HFP_VERSION_1_5 = 0x0105,
|
HFP_VERSION_1_5 = 0x0105,
|
||||||
HFP_VERSION_1_6 = 0x0106,
|
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,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -507,8 +507,17 @@ void __ofono_gprs_provision_free_settings(
|
|||||||
int count);
|
int count);
|
||||||
|
|
||||||
#include <ofono/emulator.h>
|
#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,
|
void __ofono_emulator_set_indicator_forced(struct ofono_emulator *em,
|
||||||
const char *name, int value);
|
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/gnss.h>
|
||||||
#include <ofono/cdma-sms.h>
|
#include <ofono/cdma-sms.h>
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <gdbus.h>
|
#include <gdbus.h>
|
||||||
@@ -48,6 +49,7 @@ struct ofono_radio_settings {
|
|||||||
enum ofono_radio_band_gsm pending_band_gsm;
|
enum ofono_radio_band_gsm pending_band_gsm;
|
||||||
enum ofono_radio_band_umts pending_band_umts;
|
enum ofono_radio_band_umts pending_band_umts;
|
||||||
ofono_bool_t fast_dormancy_pending;
|
ofono_bool_t fast_dormancy_pending;
|
||||||
|
uint32_t available_rats;
|
||||||
const struct ofono_radio_settings_driver *driver;
|
const struct ofono_radio_settings_driver *driver;
|
||||||
void *driver_data;
|
void *driver_data;
|
||||||
struct ofono_atom *atom;
|
struct ofono_atom *atom;
|
||||||
@@ -222,6 +224,27 @@ static DBusMessage *radio_get_properties_reply(DBusMessage *msg,
|
|||||||
DBUS_TYPE_BOOLEAN, &value);
|
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);
|
dbus_message_iter_close_container(&iter, &dict);
|
||||||
|
|
||||||
return reply;
|
return reply;
|
||||||
@@ -374,6 +397,32 @@ static void radio_send_properties_reply(struct ofono_radio_settings *rs)
|
|||||||
__ofono_dbus_pending_reply(&rs->pending, reply);
|
__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,
|
static void radio_fast_dormancy_query_callback(const struct ofono_error *error,
|
||||||
ofono_bool_t enable, void *data)
|
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_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)
|
static void radio_query_fast_dormancy(struct ofono_radio_settings *rs)
|
||||||
{
|
{
|
||||||
if (rs->driver->query_fast_dormancy == NULL) {
|
if (rs->driver->query_fast_dormancy == NULL) {
|
||||||
radio_send_properties_reply(rs);
|
radio_query_available_rats(rs);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -267,10 +267,12 @@ static char **get_locked_pins(struct ofono_sim *sim)
|
|||||||
return ret;
|
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;
|
int i, nelem;
|
||||||
void **ret;
|
void **dict;
|
||||||
|
unsigned char *retries;
|
||||||
|
|
||||||
for (i = 1, nelem = 0; i < OFONO_SIM_PASSWORD_INVALID; i++) {
|
for (i = 1, nelem = 0; i < OFONO_SIM_PASSWORD_INVALID; i++) {
|
||||||
if (sim->pin_retries[i] == -1)
|
if (sim->pin_retries[i] == -1)
|
||||||
@@ -279,17 +281,22 @@ static void **get_pin_retries(struct ofono_sim *sim)
|
|||||||
nelem += 1;
|
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++) {
|
for (i = 1, nelem = 0; i < OFONO_SIM_PASSWORD_INVALID; i++) {
|
||||||
if (sim->pin_retries[i] == -1)
|
if (sim->pin_retries[i] == -1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ret[nelem++] = (void *) sim_passwd_name(i);
|
retries[nelem] = sim->pin_retries[i];
|
||||||
ret[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)
|
static char **get_service_numbers(GSList *service_numbers)
|
||||||
@@ -344,7 +351,8 @@ static DBusMessage *sim_get_properties(DBusConnection *conn,
|
|||||||
char **service_numbers;
|
char **service_numbers;
|
||||||
char **locked_pins;
|
char **locked_pins;
|
||||||
const char *pin_name;
|
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 present = sim->state != OFONO_SIM_STATE_NOT_PRESENT;
|
||||||
dbus_bool_t fdn;
|
dbus_bool_t fdn;
|
||||||
dbus_bool_t bdn;
|
dbus_bool_t bdn;
|
||||||
@@ -419,10 +427,11 @@ static DBusMessage *sim_get_properties(DBusConnection *conn,
|
|||||||
DBUS_TYPE_STRING,
|
DBUS_TYPE_STRING,
|
||||||
(void *) &pin_name);
|
(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,
|
ofono_dbus_dict_append_dict(&dict, "Retries", DBUS_TYPE_BYTE,
|
||||||
&pin_retries);
|
&pin_retries_dict);
|
||||||
g_free(pin_retries);
|
g_free(pin_retries_dict);
|
||||||
|
g_free(dbus_retries);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
dbus_message_iter_close_container(&iter, &dict);
|
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;
|
struct ofono_sim *sim = data;
|
||||||
DBusConnection *conn = ofono_dbus_get_connection();
|
DBusConnection *conn = ofono_dbus_get_connection();
|
||||||
const char *path = __ofono_atom_get_path(sim->atom);
|
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) {
|
if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
|
||||||
ofono_error("Querying remaining pin retries failed");
|
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));
|
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_dbus_signal_dict_property_changed(conn, path,
|
||||||
OFONO_SIM_MANAGER_INTERFACE, "Retries",
|
OFONO_SIM_MANAGER_INTERFACE, "Retries",
|
||||||
DBUS_TYPE_BYTE, &pin_retries);
|
DBUS_TYPE_BYTE, &pin_retries_dict);
|
||||||
g_free(pin_retries);
|
g_free(pin_retries_dict);
|
||||||
|
g_free(dbus_retries);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sim_pin_retries_check(struct ofono_sim *sim)
|
static void sim_pin_retries_check(struct ofono_sim *sim)
|
||||||
|
|||||||
@@ -3431,6 +3431,10 @@ static void emulator_chld_cb(struct ofono_emulator *em,
|
|||||||
|
|
||||||
ofono_emulator_send_info(em, buf, TRUE);
|
ofono_emulator_send_info(em, buf, TRUE);
|
||||||
result.type = OFONO_ERROR_TYPE_NO_ERROR;
|
result.type = OFONO_ERROR_TYPE_NO_ERROR;
|
||||||
|
|
||||||
|
__ofono_emulator_slc_condition(em,
|
||||||
|
OFONO_EMULATOR_SLC_CONDITION_CHLD);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OFONO_EMULATOR_REQUEST_TYPE_QUERY:
|
case OFONO_EMULATOR_REQUEST_TYPE_QUERY:
|
||||||
|
|||||||
@@ -5,36 +5,53 @@ import dbus
|
|||||||
|
|
||||||
bus = dbus.SystemBus()
|
bus = dbus.SystemBus()
|
||||||
|
|
||||||
manager = dbus.Interface(bus.get_object('org.ofono', '/'),
|
manager = dbus.Interface(bus.get_object('org.ofono', '/'), 'org.ofono.Manager')
|
||||||
'org.ofono.Manager')
|
|
||||||
|
|
||||||
modems = manager.GetModems()
|
if (len(sys.argv) == 3):
|
||||||
|
modem = sys.argv[1]
|
||||||
for path, properties in modems:
|
context_idx = int(sys.argv[2]) - 1
|
||||||
if "org.ofono.ConnectionManager" not in properties["Interfaces"]:
|
else:
|
||||||
continue
|
modem = None
|
||||||
|
modems = manager.GetModems()
|
||||||
connman = dbus.Interface(bus.get_object('org.ofono', path),
|
for path, properties in modems:
|
||||||
'org.ofono.ConnectionManager')
|
if "org.ofono.ConnectionManager" in properties["Interfaces"]:
|
||||||
|
modem = path
|
||||||
contexts = connman.GetContexts()
|
break
|
||||||
|
if (modem is None):
|
||||||
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)))
|
|
||||||
exit(2)
|
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)
|
||||||
|
|||||||
@@ -8,12 +8,14 @@ bus = dbus.SystemBus()
|
|||||||
manager = dbus.Interface(bus.get_object('org.ofono', '/'),
|
manager = dbus.Interface(bus.get_object('org.ofono', '/'),
|
||||||
'org.ofono.Manager')
|
'org.ofono.Manager')
|
||||||
|
|
||||||
modems = manager.GetModems()
|
if (len(sys.argv) == 1):
|
||||||
|
modems = manager.GetModems()
|
||||||
path = modems[0][0]
|
path = modems[0][0]
|
||||||
|
elif (len(sys.argv) == 2):
|
||||||
if (len(sys.argv) == 2):
|
|
||||||
path = sys.argv[1]
|
path = sys.argv[1]
|
||||||
|
else:
|
||||||
|
print("Usage: %s [modem]" % (sys.argv[0]))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
manager = dbus.Interface(bus.get_object('org.ofono', path),
|
manager = dbus.Interface(bus.get_object('org.ofono', path),
|
||||||
'org.ofono.VoiceCallManager')
|
'org.ofono.VoiceCallManager')
|
||||||
|
|||||||
@@ -5,34 +5,51 @@ import dbus
|
|||||||
|
|
||||||
bus = dbus.SystemBus()
|
bus = dbus.SystemBus()
|
||||||
|
|
||||||
manager = dbus.Interface(bus.get_object('org.ofono', '/'),
|
manager = dbus.Interface(bus.get_object('org.ofono', '/'), 'org.ofono.Manager')
|
||||||
'org.ofono.Manager')
|
|
||||||
|
|
||||||
modems = manager.GetModems()
|
if (len(sys.argv) == 3):
|
||||||
|
modem = sys.argv[1]
|
||||||
for path, properties in modems:
|
context_idx = int(sys.argv[2]) - 1
|
||||||
if "org.ofono.ConnectionManager" not in properties["Interfaces"]:
|
else:
|
||||||
continue
|
modem = None
|
||||||
|
modems = manager.GetModems()
|
||||||
connman = dbus.Interface(bus.get_object('org.ofono', path),
|
for path, properties in modems:
|
||||||
'org.ofono.ConnectionManager')
|
if "org.ofono.ConnectionManager" in properties["Interfaces"]:
|
||||||
|
modem = path
|
||||||
contexts = connman.GetContexts()
|
break
|
||||||
|
if (modem is None):
|
||||||
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)))
|
|
||||||
exit(2)
|
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)
|
||||||
|
|||||||
@@ -8,8 +8,14 @@ bus = dbus.SystemBus()
|
|||||||
manager = dbus.Interface(bus.get_object('org.ofono', '/'),
|
manager = dbus.Interface(bus.get_object('org.ofono', '/'),
|
||||||
'org.ofono.Manager')
|
'org.ofono.Manager')
|
||||||
|
|
||||||
modems = manager.GetModems()
|
if (len(sys.argv) == 1):
|
||||||
path = modems[0][0]
|
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),
|
manager = dbus.Interface(bus.get_object('org.ofono', path),
|
||||||
'org.ofono.VoiceCallManager')
|
'org.ofono.VoiceCallManager')
|
||||||
|
|||||||
@@ -40,7 +40,8 @@ for path, properties in modems:
|
|||||||
"PreferredLanguages",
|
"PreferredLanguages",
|
||||||
"PrimaryContexts",
|
"PrimaryContexts",
|
||||||
"LockedPins",
|
"LockedPins",
|
||||||
"Features"]:
|
"Features",
|
||||||
|
"AvailableTechnologies"]:
|
||||||
val = ""
|
val = ""
|
||||||
for i in properties[key]:
|
for i in properties[key]:
|
||||||
val += i + " "
|
val += i + " "
|
||||||
|
|||||||
@@ -3,24 +3,23 @@
|
|||||||
import sys
|
import sys
|
||||||
import dbus
|
import dbus
|
||||||
|
|
||||||
|
if (len(sys.argv) != 2):
|
||||||
|
print("Usage: %s [voicecall_path]" % (sys.argv[0]))
|
||||||
|
exit(1)
|
||||||
|
|
||||||
bus = dbus.SystemBus()
|
bus = dbus.SystemBus()
|
||||||
|
|
||||||
manager = dbus.Interface(bus.get_object('org.ofono', '/'),
|
manager = dbus.Interface(bus.get_object('org.ofono', '/'),
|
||||||
'org.ofono.Manager')
|
'org.ofono.Manager')
|
||||||
|
|
||||||
modems = manager.GetModems()
|
call = sys.argv[1]
|
||||||
path = modems[0][0]
|
sep = call.find("/", 1)
|
||||||
|
path = call[0:sep]
|
||||||
if (len(sys.argv) == 3):
|
|
||||||
path = sys.argv[1]
|
|
||||||
callid = sys.argv[2]
|
|
||||||
else:
|
|
||||||
callid = sys.argv[1]
|
|
||||||
|
|
||||||
manager = dbus.Interface(bus.get_object('org.ofono', path),
|
manager = dbus.Interface(bus.get_object('org.ofono', path),
|
||||||
'org.ofono.VoiceCallManager')
|
'org.ofono.VoiceCallManager')
|
||||||
|
|
||||||
mpty = manager.PrivateChat(callid, timeout=100)
|
mpty = manager.PrivateChat(call, timeout=100)
|
||||||
|
|
||||||
for path in mpty:
|
for path in mpty:
|
||||||
print(path)
|
print(path)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import dbus
|
|||||||
import dbus.mainloop.glib
|
import dbus.mainloop.glib
|
||||||
|
|
||||||
def incoming_message(message, details, path, interface):
|
def incoming_message(message, details, path, interface):
|
||||||
print("%s" % (message))
|
print("%s" % (message.encode('utf-8')))
|
||||||
|
|
||||||
for key in details:
|
for key in details:
|
||||||
val = details[key]
|
val = details[key]
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
import sys
|
||||||
import dbus
|
import dbus
|
||||||
|
|
||||||
bus = dbus.SystemBus()
|
bus = dbus.SystemBus()
|
||||||
@@ -7,16 +8,32 @@ bus = dbus.SystemBus()
|
|||||||
manager = dbus.Interface(bus.get_object('org.ofono', '/'),
|
manager = dbus.Interface(bus.get_object('org.ofono', '/'),
|
||||||
'org.ofono.Manager')
|
'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:
|
modemapi = dbus.Interface(bus.get_object('org.ofono', path), 'org.ofono.Modem')
|
||||||
print("[ %s ]" % (path))
|
properties = modemapi.GetProperties()
|
||||||
|
|
||||||
if "org.ofono.VoiceCallManager" not in properties["Interfaces"]:
|
if "org.ofono.VoiceCallManager" not in properties["Interfaces"]:
|
||||||
continue
|
print("org.ofono.VoiceCallManager not found")
|
||||||
|
exit(2)
|
||||||
|
|
||||||
mgr = dbus.Interface(bus.get_object('org.ofono', path),
|
print("[ %s ]" % (path))
|
||||||
'org.ofono.VoiceCallManager')
|
|
||||||
|
mgr = dbus.Interface(bus.get_object('org.ofono', path),
|
||||||
|
'org.ofono.VoiceCallManager')
|
||||||
|
|
||||||
|
mgr.ReleaseAndAnswer()
|
||||||
|
|
||||||
mgr.ReleaseAndAnswer()
|
|
||||||
break
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
import sys
|
||||||
import dbus
|
import dbus
|
||||||
|
|
||||||
bus = dbus.SystemBus()
|
bus = dbus.SystemBus()
|
||||||
@@ -7,16 +8,32 @@ bus = dbus.SystemBus()
|
|||||||
manager = dbus.Interface(bus.get_object('org.ofono', '/'),
|
manager = dbus.Interface(bus.get_object('org.ofono', '/'),
|
||||||
'org.ofono.Manager')
|
'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:
|
modemapi = dbus.Interface(bus.get_object('org.ofono', modem), 'org.ofono.Modem')
|
||||||
print("[ %s ]" % (path))
|
properties = modemapi.GetProperties()
|
||||||
|
|
||||||
if "org.ofono.VoiceCallManager" not in properties["Interfaces"]:
|
if "org.ofono.VoiceCallManager" not in properties["Interfaces"]:
|
||||||
continue
|
print("org.ofono.VoiceCallManager not found")
|
||||||
|
exit(2)
|
||||||
|
|
||||||
mgr = dbus.Interface(bus.get_object('org.ofono', path),
|
print("[ %s ]" % (modem))
|
||||||
'org.ofono.VoiceCallManager')
|
|
||||||
|
mgr = dbus.Interface(bus.get_object('org.ofono', modem),
|
||||||
|
'org.ofono.VoiceCallManager')
|
||||||
|
|
||||||
|
mgr.ReleaseAndSwap()
|
||||||
|
|
||||||
mgr.ReleaseAndSwap()
|
|
||||||
break
|
|
||||||
|
|||||||
21
ofono/test/set-ddr
Executable file
21
ofono/test/set-ddr
Executable 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])))
|
||||||
@@ -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
|
* Thu Jan 09 2014 Martti Piirainen <martti.piirainen@oss.tieto.com> - 1.14
|
||||||
- Update to upstream 1.14.
|
- Update to upstream 1.14.
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
Name: ofono
|
Name: ofono
|
||||||
|
|
||||||
Summary: Open Source Telephony
|
Summary: Open Source Telephony
|
||||||
Version: 1.14
|
Version: 1.16
|
||||||
Release: 1
|
Release: 1
|
||||||
Group: Communications/Connectivity Adaptation
|
Group: Communications/Connectivity Adaptation
|
||||||
License: GPLv2
|
License: GPLv2
|
||||||
|
|||||||
Reference in New Issue
Block a user