2011-01-09 14:18:18 +00:00
|
|
|
/*
|
|
|
|
*
|
|
|
|
* oFono - Open Source Telephony
|
|
|
|
*
|
2012-06-21 23:09:57 +00:00
|
|
|
* Copyright (C) 2008-2012 Intel Corporation. All rights reserved.
|
2011-01-09 14:18:18 +00:00
|
|
|
*
|
|
|
|
* 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
|
|
|
|
|
2011-01-10 03:02:35 +00:00
|
|
|
#include <errno.h>
|
2012-06-21 23:09:57 +00:00
|
|
|
#include <fcntl.h>
|
|
|
|
#include <unistd.h>
|
2011-01-10 03:02:35 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
|
2011-01-09 14:18:18 +00:00
|
|
|
#define OFONO_API_SUBJECT_TO_CHANGE
|
|
|
|
#include <ofono/plugin.h>
|
|
|
|
#include <ofono/modem.h>
|
2011-01-10 03:02:35 +00:00
|
|
|
#include <ofono/devinfo.h>
|
|
|
|
#include <ofono/netreg.h>
|
2017-09-12 10:52:37 +00:00
|
|
|
#include <ofono/netmon.h>
|
2012-06-21 23:09:57 +00:00
|
|
|
#include <ofono/phonebook.h>
|
2012-06-25 19:11:45 +00:00
|
|
|
#include <ofono/voicecall.h>
|
2011-01-10 03:02:35 +00:00
|
|
|
#include <ofono/sim.h>
|
2012-06-21 23:09:57 +00:00
|
|
|
#include <ofono/stk.h>
|
|
|
|
#include <ofono/sms.h>
|
2012-06-26 03:14:29 +00:00
|
|
|
#include <ofono/ussd.h>
|
2011-01-22 12:14:07 +00:00
|
|
|
#include <ofono/gprs.h>
|
2011-07-27 22:03:46 +00:00
|
|
|
#include <ofono/gprs-context.h>
|
2018-03-05 12:31:02 +00:00
|
|
|
#include <ofono/lte.h>
|
2012-06-25 05:55:08 +00:00
|
|
|
#include <ofono/radio-settings.h>
|
2012-06-21 23:09:57 +00:00
|
|
|
#include <ofono/location-reporting.h>
|
|
|
|
#include <ofono/log.h>
|
2017-09-10 06:16:03 +00:00
|
|
|
#include <ofono/message-waiting.h>
|
2011-01-10 03:02:35 +00:00
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
#include <drivers/qmimodem/qmi.h>
|
|
|
|
#include <drivers/qmimodem/dms.h>
|
2017-03-25 16:57:53 +00:00
|
|
|
#include <drivers/qmimodem/wda.h>
|
2012-06-21 23:09:57 +00:00
|
|
|
#include <drivers/qmimodem/util.h>
|
2011-01-10 03:02:35 +00:00
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
#define GOBI_DMS (1 << 0)
|
|
|
|
#define GOBI_NAS (1 << 1)
|
|
|
|
#define GOBI_WMS (1 << 2)
|
|
|
|
#define GOBI_WDS (1 << 3)
|
|
|
|
#define GOBI_PDS (1 << 4)
|
|
|
|
#define GOBI_PBM (1 << 5)
|
|
|
|
#define GOBI_UIM (1 << 6)
|
|
|
|
#define GOBI_CAT (1 << 7)
|
|
|
|
#define GOBI_CAT_OLD (1 << 8)
|
2012-06-25 19:11:45 +00:00
|
|
|
#define GOBI_VOICE (1 << 9)
|
2017-03-25 16:57:53 +00:00
|
|
|
#define GOBI_WDA (1 << 10)
|
2011-01-10 03:02:35 +00:00
|
|
|
|
|
|
|
struct gobi_data {
|
2012-06-21 23:09:57 +00:00
|
|
|
struct qmi_device *device;
|
|
|
|
struct qmi_service *dms;
|
|
|
|
unsigned long features;
|
|
|
|
unsigned int discover_attempts;
|
|
|
|
uint8_t oper_mode;
|
2011-01-10 03:02:35 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static void gobi_debug(const char *str, void *user_data)
|
|
|
|
{
|
|
|
|
const char *prefix = user_data;
|
|
|
|
|
|
|
|
ofono_info("%s%s", prefix, str);
|
|
|
|
}
|
2011-01-09 14:18:18 +00:00
|
|
|
|
|
|
|
static int gobi_probe(struct ofono_modem *modem)
|
|
|
|
{
|
2011-01-10 03:02:35 +00:00
|
|
|
struct gobi_data *data;
|
|
|
|
|
|
|
|
DBG("%p", modem);
|
|
|
|
|
|
|
|
data = g_try_new0(struct gobi_data, 1);
|
2012-06-21 23:09:57 +00:00
|
|
|
if (!data)
|
2011-01-10 03:02:35 +00:00
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
ofono_modem_set_data(modem, data);
|
2011-01-09 14:18:18 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void gobi_remove(struct ofono_modem *modem)
|
|
|
|
{
|
2011-01-10 03:02:35 +00:00
|
|
|
struct gobi_data *data = ofono_modem_get_data(modem);
|
|
|
|
|
|
|
|
DBG("%p", modem);
|
|
|
|
|
|
|
|
ofono_modem_set_data(modem, NULL);
|
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
qmi_service_unref(data->dms);
|
|
|
|
|
|
|
|
qmi_device_unref(data->device);
|
2011-07-29 13:24:33 +00:00
|
|
|
|
2011-01-10 03:02:35 +00:00
|
|
|
g_free(data);
|
|
|
|
}
|
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
static void shutdown_cb(void *user_data)
|
2011-01-10 03:02:35 +00:00
|
|
|
{
|
2012-06-21 23:09:57 +00:00
|
|
|
struct ofono_modem *modem = user_data;
|
|
|
|
struct gobi_data *data = ofono_modem_get_data(modem);
|
2011-01-10 03:02:35 +00:00
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
DBG("");
|
2011-01-10 03:02:35 +00:00
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
data->discover_attempts = 0;
|
2011-01-10 03:02:35 +00:00
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
qmi_device_unref(data->device);
|
|
|
|
data->device = NULL;
|
2011-01-10 03:02:35 +00:00
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
ofono_modem_set_powered(modem, FALSE);
|
|
|
|
}
|
2011-07-27 14:09:11 +00:00
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
static void shutdown_device(struct ofono_modem *modem)
|
|
|
|
{
|
|
|
|
struct gobi_data *data = ofono_modem_get_data(modem);
|
2011-01-10 03:02:35 +00:00
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
DBG("%p", modem);
|
2011-01-10 03:02:35 +00:00
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
qmi_service_unref(data->dms);
|
|
|
|
data->dms = NULL;
|
2011-01-10 03:02:35 +00:00
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
qmi_device_shutdown(data->device, shutdown_cb, modem, NULL);
|
2011-01-10 03:02:35 +00:00
|
|
|
}
|
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
static void power_reset_cb(struct qmi_result *result, void *user_data)
|
2011-01-22 12:02:35 +00:00
|
|
|
{
|
|
|
|
struct ofono_modem *modem = user_data;
|
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
DBG("");
|
|
|
|
|
|
|
|
if (qmi_result_set_error(result, NULL)) {
|
|
|
|
shutdown_device(modem);
|
2011-01-22 12:02:35 +00:00
|
|
|
return;
|
2012-06-21 23:09:57 +00:00
|
|
|
}
|
2011-01-22 12:02:35 +00:00
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
ofono_modem_set_powered(modem, TRUE);
|
|
|
|
}
|
2011-01-22 12:02:35 +00:00
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
static void get_oper_mode_cb(struct qmi_result *result, void *user_data)
|
|
|
|
{
|
|
|
|
struct ofono_modem *modem = user_data;
|
|
|
|
struct gobi_data *data = ofono_modem_get_data(modem);
|
|
|
|
struct qmi_param *param;
|
|
|
|
uint8_t mode;
|
2011-01-22 12:02:35 +00:00
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
DBG("");
|
|
|
|
|
|
|
|
if (qmi_result_set_error(result, NULL)) {
|
|
|
|
shutdown_device(modem);
|
2011-01-22 12:02:35 +00:00
|
|
|
return;
|
2012-06-21 23:09:57 +00:00
|
|
|
}
|
2011-01-22 12:02:35 +00:00
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
if (!qmi_result_get_uint8(result, QMI_DMS_RESULT_OPER_MODE, &mode)) {
|
|
|
|
shutdown_device(modem);
|
2011-01-22 12:02:35 +00:00
|
|
|
return;
|
2012-06-21 23:09:57 +00:00
|
|
|
}
|
2011-01-22 12:02:35 +00:00
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
data->oper_mode = mode;
|
2011-01-22 12:02:35 +00:00
|
|
|
|
2017-03-24 14:51:45 +00:00
|
|
|
/*
|
|
|
|
* Telit QMI LTE modem must remain online. If powered down, it also
|
|
|
|
* powers down the sim card, and QMI interface has no way to bring
|
|
|
|
* it back alive.
|
|
|
|
*/
|
|
|
|
if (ofono_modem_get_boolean(modem, "AlwaysOnline")) {
|
|
|
|
ofono_modem_set_powered(modem, TRUE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
switch (data->oper_mode) {
|
|
|
|
case QMI_DMS_OPER_MODE_ONLINE:
|
|
|
|
param = qmi_param_new_uint8(QMI_DMS_PARAM_OPER_MODE,
|
|
|
|
QMI_DMS_OPER_MODE_PERSIST_LOW_POWER);
|
|
|
|
if (!param) {
|
|
|
|
shutdown_device(modem);
|
|
|
|
return;
|
2011-01-22 12:02:35 +00:00
|
|
|
}
|
2012-06-21 23:09:57 +00:00
|
|
|
|
|
|
|
if (qmi_service_send(data->dms, QMI_DMS_SET_OPER_MODE, param,
|
|
|
|
power_reset_cb, modem, NULL) > 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
shutdown_device(modem);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ofono_modem_set_powered(modem, TRUE);
|
|
|
|
break;
|
2011-01-22 12:02:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
static void get_caps_cb(struct qmi_result *result, void *user_data)
|
2011-01-10 03:02:35 +00:00
|
|
|
{
|
|
|
|
struct ofono_modem *modem = user_data;
|
2011-01-22 12:02:35 +00:00
|
|
|
struct gobi_data *data = ofono_modem_get_data(modem);
|
2012-06-21 23:09:57 +00:00
|
|
|
const struct qmi_dms_device_caps *caps;
|
|
|
|
uint16_t len;
|
|
|
|
uint8_t i;
|
2011-01-10 03:02:35 +00:00
|
|
|
|
2011-01-09 14:18:18 +00:00
|
|
|
DBG("");
|
2011-01-10 03:02:35 +00:00
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
if (qmi_result_set_error(result, NULL))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
caps = qmi_result_get(result, QMI_DMS_RESULT_DEVICE_CAPS, &len);
|
|
|
|
if (!caps)
|
|
|
|
goto error;
|
2011-07-27 14:29:52 +00:00
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
DBG("service capabilities %d", caps->data_capa);
|
|
|
|
DBG("sim supported %d", caps->sim_supported);
|
2011-01-22 12:02:35 +00:00
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
for (i = 0; i < caps->radio_if_count; i++)
|
|
|
|
DBG("radio = %d", caps->radio_if[i]);
|
|
|
|
|
|
|
|
if (qmi_service_send(data->dms, QMI_DMS_GET_OPER_MODE, NULL,
|
|
|
|
get_oper_mode_cb, modem, NULL) > 0)
|
2011-07-27 14:09:11 +00:00
|
|
|
return;
|
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
error:
|
|
|
|
shutdown_device(modem);
|
|
|
|
}
|
2011-01-22 12:02:35 +00:00
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
static void create_dms_cb(struct qmi_service *service, void *user_data)
|
|
|
|
{
|
|
|
|
struct ofono_modem *modem = user_data;
|
|
|
|
struct gobi_data *data = ofono_modem_get_data(modem);
|
2011-01-22 12:02:35 +00:00
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
DBG("");
|
2011-01-22 12:02:35 +00:00
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
if (!service)
|
|
|
|
goto error;
|
2011-07-27 14:09:11 +00:00
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
data->dms = qmi_service_ref(service);
|
|
|
|
|
|
|
|
if (qmi_service_send(data->dms, QMI_DMS_GET_CAPS, NULL,
|
|
|
|
get_caps_cb, modem, NULL) > 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
error:
|
|
|
|
shutdown_device(modem);
|
2011-07-27 14:29:52 +00:00
|
|
|
}
|
|
|
|
|
2017-12-05 17:52:37 +00:00
|
|
|
static void create_shared_dms(void *user_data)
|
|
|
|
{
|
|
|
|
struct ofono_modem *modem = user_data;
|
|
|
|
struct gobi_data *data = ofono_modem_get_data(modem);
|
|
|
|
|
|
|
|
qmi_service_create_shared(data->device, QMI_SERVICE_DMS,
|
|
|
|
create_dms_cb, modem, NULL);
|
|
|
|
}
|
|
|
|
|
2018-04-03 14:50:55 +00:00
|
|
|
static void discover_cb(void *user_data)
|
2011-07-27 14:29:52 +00:00
|
|
|
{
|
|
|
|
struct ofono_modem *modem = user_data;
|
|
|
|
struct gobi_data *data = ofono_modem_get_data(modem);
|
2018-04-03 14:50:55 +00:00
|
|
|
uint16_t major, minor;
|
2011-07-27 14:29:52 +00:00
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
DBG("");
|
2011-07-27 14:29:52 +00:00
|
|
|
|
2018-04-03 14:50:55 +00:00
|
|
|
if (qmi_device_has_service(data->device, QMI_SERVICE_DMS))
|
|
|
|
data->features |= GOBI_DMS;
|
|
|
|
if (qmi_device_has_service(data->device, QMI_SERVICE_NAS))
|
|
|
|
data->features |= GOBI_NAS;
|
|
|
|
if (qmi_device_has_service(data->device, QMI_SERVICE_WMS))
|
|
|
|
data->features |= GOBI_WMS;
|
|
|
|
if (qmi_device_has_service(data->device, QMI_SERVICE_WDS))
|
|
|
|
data->features |= GOBI_WDS;
|
|
|
|
if (qmi_device_has_service(data->device, QMI_SERVICE_WDA))
|
|
|
|
data->features |= GOBI_WDA;
|
|
|
|
if (qmi_device_has_service(data->device, QMI_SERVICE_PDS))
|
|
|
|
data->features |= GOBI_PDS;
|
|
|
|
if (qmi_device_has_service(data->device, QMI_SERVICE_PBM))
|
|
|
|
data->features |= GOBI_PBM;
|
|
|
|
if (qmi_device_has_service(data->device, QMI_SERVICE_UIM))
|
|
|
|
data->features |= GOBI_UIM;
|
|
|
|
if (qmi_device_has_service(data->device, QMI_SERVICE_CAT))
|
|
|
|
data->features |= GOBI_CAT;
|
|
|
|
if (qmi_device_get_service_version(data->device,
|
|
|
|
QMI_SERVICE_CAT_OLD, &major, &minor))
|
|
|
|
if (major > 0)
|
|
|
|
data->features |= GOBI_CAT_OLD;
|
|
|
|
if (qmi_device_has_service(data->device, QMI_SERVICE_VOICE))
|
2012-06-25 19:11:45 +00:00
|
|
|
data->features |= GOBI_VOICE;
|
2011-07-27 14:29:52 +00:00
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
if (!(data->features & GOBI_DMS)) {
|
|
|
|
if (++data->discover_attempts < 3) {
|
|
|
|
qmi_device_discover(data->device, discover_cb,
|
|
|
|
modem, NULL);
|
|
|
|
return;
|
|
|
|
}
|
2011-07-27 14:29:52 +00:00
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
shutdown_device(modem);
|
|
|
|
return;
|
|
|
|
}
|
2011-07-27 14:29:52 +00:00
|
|
|
|
2017-12-05 17:52:37 +00:00
|
|
|
if (qmi_device_is_sync_supported(data->device))
|
|
|
|
qmi_device_sync(data->device, create_shared_dms, modem);
|
|
|
|
else
|
|
|
|
create_shared_dms(modem);
|
2011-01-10 03:02:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int gobi_enable(struct ofono_modem *modem)
|
|
|
|
{
|
|
|
|
struct gobi_data *data = ofono_modem_get_data(modem);
|
2012-06-21 23:09:57 +00:00
|
|
|
const char *device;
|
|
|
|
int fd;
|
2011-01-10 03:02:35 +00:00
|
|
|
|
|
|
|
DBG("%p", modem);
|
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
device = ofono_modem_get_string(modem, "Device");
|
|
|
|
if (!device)
|
2011-01-10 03:02:35 +00:00
|
|
|
return -EINVAL;
|
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
fd = open(device, O_RDWR | O_NONBLOCK | O_CLOEXEC);
|
|
|
|
if (fd < 0)
|
|
|
|
return -EIO;
|
2011-01-10 03:02:35 +00:00
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
data->device = qmi_device_new(fd);
|
|
|
|
if (!data->device) {
|
|
|
|
close(fd);
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (getenv("OFONO_QMI_DEBUG"))
|
|
|
|
qmi_device_set_debug(data->device, gobi_debug, "QMI: ");
|
2011-01-10 03:02:35 +00:00
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
qmi_device_set_close_on_unref(data->device, true);
|
|
|
|
|
|
|
|
qmi_device_discover(data->device, discover_cb, modem, NULL);
|
2011-07-27 14:29:52 +00:00
|
|
|
|
2011-01-10 03:02:35 +00:00
|
|
|
return -EINPROGRESS;
|
|
|
|
}
|
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
static void power_disable_cb(struct qmi_result *result, void *user_data)
|
2011-01-10 03:02:35 +00:00
|
|
|
{
|
|
|
|
struct ofono_modem *modem = user_data;
|
|
|
|
|
|
|
|
DBG("");
|
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
shutdown_device(modem);
|
2011-01-10 03:02:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int gobi_disable(struct ofono_modem *modem)
|
|
|
|
{
|
|
|
|
struct gobi_data *data = ofono_modem_get_data(modem);
|
2012-06-21 23:09:57 +00:00
|
|
|
struct qmi_param *param;
|
2011-01-10 03:02:35 +00:00
|
|
|
|
|
|
|
DBG("%p", modem);
|
|
|
|
|
2012-06-25 17:25:49 +00:00
|
|
|
qmi_service_cancel_all(data->dms);
|
|
|
|
qmi_service_unregister_all(data->dms);
|
|
|
|
|
2017-03-24 14:51:45 +00:00
|
|
|
/*
|
|
|
|
* Telit QMI modem must remain online. If powered down, it also
|
|
|
|
* powers down the sim card, and QMI interface has no way to bring
|
|
|
|
* it back alive.
|
|
|
|
*/
|
|
|
|
if (ofono_modem_get_boolean(modem, "AlwaysOnline"))
|
|
|
|
goto out;
|
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
param = qmi_param_new_uint8(QMI_DMS_PARAM_OPER_MODE,
|
|
|
|
QMI_DMS_OPER_MODE_PERSIST_LOW_POWER);
|
|
|
|
if (!param)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
if (qmi_service_send(data->dms, QMI_DMS_SET_OPER_MODE, param,
|
|
|
|
power_disable_cb, modem, NULL) > 0)
|
|
|
|
return -EINPROGRESS;
|
2011-01-10 03:02:35 +00:00
|
|
|
|
2017-03-24 14:51:45 +00:00
|
|
|
out:
|
2012-06-21 23:09:57 +00:00
|
|
|
shutdown_device(modem);
|
2011-01-10 03:02:35 +00:00
|
|
|
|
|
|
|
return -EINPROGRESS;
|
|
|
|
}
|
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
static void set_online_cb(struct qmi_result *result, void *user_data)
|
2011-01-10 03:02:35 +00:00
|
|
|
{
|
|
|
|
struct cb_data *cbd = user_data;
|
|
|
|
ofono_modem_online_cb_t cb = cbd->cb;
|
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
DBG("");
|
|
|
|
|
|
|
|
if (qmi_result_set_error(result, NULL))
|
|
|
|
CALLBACK_WITH_FAILURE(cb, cbd->data);
|
|
|
|
else
|
|
|
|
CALLBACK_WITH_SUCCESS(cb, cbd->data);
|
2011-01-10 03:02:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void gobi_set_online(struct ofono_modem *modem, ofono_bool_t online,
|
|
|
|
ofono_modem_online_cb_t cb, void *user_data)
|
|
|
|
{
|
|
|
|
struct gobi_data *data = ofono_modem_get_data(modem);
|
|
|
|
struct cb_data *cbd = cb_data_new(cb, user_data);
|
2012-06-21 23:09:57 +00:00
|
|
|
struct qmi_param *param;
|
|
|
|
uint8_t mode;
|
2011-01-10 03:02:35 +00:00
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
DBG("%p %s", modem, online ? "online" : "offline");
|
2011-01-10 03:02:35 +00:00
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
if (online)
|
|
|
|
mode = QMI_DMS_OPER_MODE_ONLINE;
|
|
|
|
else
|
|
|
|
mode = QMI_DMS_OPER_MODE_LOW_POWER;
|
|
|
|
|
|
|
|
param = qmi_param_new_uint8(QMI_DMS_PARAM_OPER_MODE, mode);
|
|
|
|
if (!param)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (qmi_service_send(data->dms, QMI_DMS_SET_OPER_MODE, param,
|
2011-07-27 14:09:11 +00:00
|
|
|
set_online_cb, cbd, g_free) > 0)
|
2011-01-10 03:02:35 +00:00
|
|
|
return;
|
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
qmi_param_free(param);
|
|
|
|
|
|
|
|
error:
|
2011-01-10 03:02:35 +00:00
|
|
|
CALLBACK_WITH_FAILURE(cb, cbd->data);
|
2011-07-27 14:09:11 +00:00
|
|
|
|
|
|
|
g_free(cbd);
|
2011-01-10 03:02:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void gobi_pre_sim(struct ofono_modem *modem)
|
|
|
|
{
|
|
|
|
struct gobi_data *data = ofono_modem_get_data(modem);
|
2016-05-03 16:12:19 +00:00
|
|
|
const char *sim_driver = NULL;
|
2011-01-10 03:02:35 +00:00
|
|
|
|
|
|
|
DBG("%p", modem);
|
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
ofono_devinfo_create(modem, 0, "qmimodem", data->device);
|
|
|
|
|
|
|
|
if (data->features & GOBI_UIM)
|
2016-05-03 08:44:53 +00:00
|
|
|
sim_driver = "qmimodem";
|
2012-06-21 23:09:57 +00:00
|
|
|
else if (data->features & GOBI_DMS)
|
2016-05-03 08:44:53 +00:00
|
|
|
sim_driver = "qmimodem-legacy";
|
|
|
|
|
|
|
|
if (ofono_modem_get_boolean(modem, "ForceSimLegacy"))
|
|
|
|
sim_driver = "qmimodem-legacy";
|
|
|
|
|
2016-05-03 16:12:19 +00:00
|
|
|
if (sim_driver)
|
|
|
|
ofono_sim_create(modem, 0, sim_driver, data->device);
|
2012-06-25 19:11:45 +00:00
|
|
|
|
|
|
|
if (data->features & GOBI_VOICE)
|
|
|
|
ofono_voicecall_create(modem, 0, "qmimodem", data->device);
|
2012-06-25 19:28:08 +00:00
|
|
|
|
|
|
|
if (data->features & GOBI_PDS)
|
|
|
|
ofono_location_reporting_create(modem, 0, "qmimodem",
|
|
|
|
data->device);
|
2011-01-10 03:02:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void gobi_post_sim(struct ofono_modem *modem)
|
|
|
|
{
|
|
|
|
struct gobi_data *data = ofono_modem_get_data(modem);
|
|
|
|
|
|
|
|
DBG("%p", modem);
|
|
|
|
|
2018-03-12 14:37:43 +00:00
|
|
|
ofono_lte_create(modem, 0, "qmimodem", data->device);
|
2018-03-05 12:31:02 +00:00
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
if (data->features & GOBI_CAT)
|
|
|
|
ofono_stk_create(modem, 0, "qmimodem", data->device);
|
|
|
|
else if (data->features & GOBI_CAT_OLD)
|
|
|
|
ofono_stk_create(modem, 1, "qmimodem", data->device);
|
|
|
|
|
|
|
|
if (data->features & GOBI_PBM)
|
|
|
|
ofono_phonebook_create(modem, 0, "qmimodem", data->device);
|
2011-01-29 09:26:52 +00:00
|
|
|
|
2012-06-25 05:55:08 +00:00
|
|
|
if (data->features & GOBI_NAS)
|
|
|
|
ofono_radio_settings_create(modem, 0, "qmimodem", data->device);
|
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
if (data->features & GOBI_WMS)
|
|
|
|
ofono_sms_create(modem, 0, "qmimodem", data->device);
|
2017-09-10 06:16:03 +00:00
|
|
|
|
|
|
|
if ((data->features & GOBI_WMS) && (data->features & GOBI_UIM) &&
|
|
|
|
!ofono_modem_get_boolean(modem, "ForceSimLegacy")) {
|
|
|
|
struct ofono_message_waiting *mw =
|
|
|
|
ofono_message_waiting_create(modem);
|
|
|
|
|
|
|
|
if (mw)
|
|
|
|
ofono_message_waiting_register(mw);
|
|
|
|
}
|
2011-01-10 03:02:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void gobi_post_online(struct ofono_modem *modem)
|
|
|
|
{
|
|
|
|
struct gobi_data *data = ofono_modem_get_data(modem);
|
2012-06-21 23:09:57 +00:00
|
|
|
struct ofono_gprs *gprs;
|
|
|
|
struct ofono_gprs_context *gc;
|
2011-01-10 03:02:35 +00:00
|
|
|
|
|
|
|
DBG("%p", modem);
|
|
|
|
|
2017-09-12 10:52:37 +00:00
|
|
|
if (data->features & GOBI_NAS) {
|
2012-06-21 23:09:57 +00:00
|
|
|
ofono_netreg_create(modem, 0, "qmimodem", data->device);
|
2017-09-12 10:52:37 +00:00
|
|
|
ofono_netmon_create(modem, 0, "qmimodem", data->device);
|
|
|
|
}
|
2012-06-21 23:09:57 +00:00
|
|
|
|
2012-06-26 03:14:29 +00:00
|
|
|
if (data->features & GOBI_VOICE)
|
|
|
|
ofono_ussd_create(modem, 0, "qmimodem", data->device);
|
|
|
|
|
2012-06-21 23:09:57 +00:00
|
|
|
if (data->features & GOBI_WDS) {
|
|
|
|
gprs = ofono_gprs_create(modem, 0, "qmimodem", data->device);
|
|
|
|
gc = ofono_gprs_context_create(modem, 0, "qmimodem",
|
|
|
|
data->device);
|
|
|
|
|
|
|
|
if (gprs && gc)
|
|
|
|
ofono_gprs_add_context(gprs, gc);
|
|
|
|
}
|
2011-01-09 14:18:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static struct ofono_modem_driver gobi_driver = {
|
|
|
|
.name = "gobi",
|
|
|
|
.probe = gobi_probe,
|
|
|
|
.remove = gobi_remove,
|
2011-01-10 03:02:35 +00:00
|
|
|
.enable = gobi_enable,
|
|
|
|
.disable = gobi_disable,
|
2011-02-10 02:27:40 +00:00
|
|
|
.set_online = gobi_set_online,
|
2011-01-10 03:02:35 +00:00
|
|
|
.pre_sim = gobi_pre_sim,
|
|
|
|
.post_sim = gobi_post_sim,
|
2011-02-10 02:27:40 +00:00
|
|
|
.post_online = gobi_post_online,
|
2011-01-09 14:18:18 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static int gobi_init(void)
|
|
|
|
{
|
|
|
|
return ofono_modem_driver_register(&gobi_driver);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void gobi_exit(void)
|
|
|
|
{
|
|
|
|
ofono_modem_driver_unregister(&gobi_driver);
|
|
|
|
}
|
|
|
|
|
|
|
|
OFONO_PLUGIN_DEFINE(gobi, "Qualcomm Gobi modem driver", VERSION,
|
|
|
|
OFONO_PLUGIN_PRIORITY_DEFAULT, gobi_init, gobi_exit)
|