All the mail mirrored from lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 5/6] coex: Added xmm7modem driver for coex
@ 2018-10-01 10:35 Antara Borwankar
  0 siblings, 0 replies; only message in thread
From: Antara Borwankar @ 2018-10-01 10:35 UTC (permalink / raw
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 16789 bytes --]

From: Antara <antara.borwankar@intel.com>

adding coex driver for xmm7modem which uses intel  proprietory
AT commands. To enable/disable coex in modem and get bt and wifi
notifications. The driver will also be able to get the PLMN history.
---
 drivers/xmm7modem/coex.c | 641 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 641 insertions(+)
 create mode 100644 drivers/xmm7modem/coex.c

diff --git a/drivers/xmm7modem/coex.c b/drivers/xmm7modem/coex.c
new file mode 100644
index 0000000..fa0b0c4
--- /dev/null
+++ b/drivers/xmm7modem/coex.c
@@ -0,0 +1,641 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2008-2016  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <glib.h>
+
+#include <ofono/modem.h>
+#include <ofono/log.h>
+#include <ofono/coex.h>
+
+#include "gatchat.h"
+#include "gatresult.h"
+
+#include "xmm7modem.h"
+
+#define BAND_LEN 20
+static const char *xnvmplmn_prefix[] = { "+XNVMPLMN:", NULL };
+
+struct coex_data {
+	GAtChat *chat;
+	ofono_bool_t wlan_active;
+	enum ofono_wlan_bw wlan_bw;
+	ofono_bool_t bt_active;
+	ofono_bool_t wlan_active_pending;
+	enum ofono_wlan_bw wlan_bw_pending;
+	ofono_bool_t bt_active_pending;
+};
+
+enum xmm_net_band_lte {
+	NET_BAND_LTE_INVALID = 0,
+	NET_BAND_LTE_1 = 101,
+	NET_BAND_LTE_2,
+	NET_BAND_LTE_3,
+	NET_BAND_LTE_4,
+	NET_BAND_LTE_5,
+	NET_BAND_LTE_6,
+	NET_BAND_LTE_7,
+	NET_BAND_LTE_8,
+	NET_BAND_LTE_9,
+	NET_BAND_LTE_10,
+	NET_BAND_LTE_11,
+	NET_BAND_LTE_12,
+	NET_BAND_LTE_13,
+	NET_BAND_LTE_14,
+	NET_BAND_LTE_15,
+	NET_BAND_LTE_16,
+	NET_BAND_LTE_17,
+	NET_BAND_LTE_18,
+	NET_BAND_LTE_19,
+	NET_BAND_LTE_20,
+	NET_BAND_LTE_21,
+	NET_BAND_LTE_22,
+	NET_BAND_LTE_23,
+	NET_BAND_LTE_24,
+	NET_BAND_LTE_25,
+	NET_BAND_LTE_26,
+	NET_BAND_LTE_27,
+	NET_BAND_LTE_28,
+	NET_BAND_LTE_29,
+	NET_BAND_LTE_30,
+	NET_BAND_LTE_31,
+	NET_BAND_LTE_32,
+	NET_BAND_LTE_33,
+	NET_BAND_LTE_34,
+	NET_BAND_LTE_35,
+	NET_BAND_LTE_36,
+	NET_BAND_LTE_37,
+	NET_BAND_LTE_38,
+	NET_BAND_LTE_39,
+	NET_BAND_LTE_40,
+	NET_BAND_LTE_41,
+	NET_BAND_LTE_42,
+	NET_BAND_LTE_43 = 143
+};
+
+static const char *none_prefix[] = { NULL };
+
+static void xmm_set_bt_active_cb(gboolean ok, GAtResult *result,
+					gpointer user_data);
+
+static void xmm_set_wlan_active_cb(gboolean ok, GAtResult *result,
+					gpointer user_data);
+
+static void xmm_coex_l_notify(GAtResult *result, gpointer user_data)
+{
+	struct ofono_coex *coex = user_data;
+	GAtResultIter iter;
+	int lte_active;
+
+	g_at_result_iter_init(&iter, result);
+
+	if (!g_at_result_iter_next(&iter, "+XNRTCWSL:"))
+		return;
+
+	if (!g_at_result_iter_next_number(&iter, &lte_active))
+		return;
+
+	DBG("lte_active:%d", lte_active);
+
+	ofono_lte_coex_status_notify(coex, lte_active);
+}
+
+void xmm_get_band_string(int lte_band, char* band)
+{
+	switch (lte_band) {
+		case NET_BAND_LTE_1:
+		strncpy(band,"BAND_LTE_1",BAND_LEN);
+		break;
+		case NET_BAND_LTE_2:
+		strncpy(band,"BAND_LTE_2",BAND_LEN);
+		break;
+		case NET_BAND_LTE_3:
+		strncpy(band,"BAND_LTE_3",BAND_LEN);
+		break;
+		case NET_BAND_LTE_4:
+		strncpy(band,"BAND_LTE_4",BAND_LEN);
+		break;
+		case NET_BAND_LTE_5:
+		strncpy(band,"BAND_LTE_5",BAND_LEN);
+		break;
+		case NET_BAND_LTE_6:
+		strncpy(band,"BAND_LTE_6",BAND_LEN);
+		break;
+		case NET_BAND_LTE_7:
+		strncpy(band,"BAND_LTE_7",BAND_LEN);
+		break;
+		case NET_BAND_LTE_8:
+		strncpy(band,"BAND_LTE_8",BAND_LEN);
+		break;
+		case NET_BAND_LTE_9:
+		strncpy(band,"BAND_LTE_9",BAND_LEN);
+		break;
+		case NET_BAND_LTE_10:
+		strncpy(band,"BAND_LTE_10",BAND_LEN);
+		break;
+		case NET_BAND_LTE_11:
+		strncpy(band,"BAND_LTE_11",BAND_LEN);
+		break;
+		case NET_BAND_LTE_12:
+		strncpy(band,"BAND_LTE_12",BAND_LEN);
+		break;
+		case NET_BAND_LTE_13:
+		strncpy(band,"BAND_LTE_13",BAND_LEN);
+		break;
+		case NET_BAND_LTE_14:
+		strncpy(band,"BAND_LTE_14",BAND_LEN);
+		break;
+		case NET_BAND_LTE_15:
+		strncpy(band,"BAND_LTE_15",BAND_LEN);
+		break;
+		case NET_BAND_LTE_16:
+		strncpy(band,"BAND_LTE_16",BAND_LEN);
+		break;
+		case NET_BAND_LTE_17:
+		strncpy(band,"BAND_LTE_17",BAND_LEN);
+		break;
+		case NET_BAND_LTE_18:
+		strncpy(band,"BAND_LTE_18",BAND_LEN);
+		break;
+		case NET_BAND_LTE_19:
+		strncpy(band,"BAND_LTE_19",BAND_LEN);
+		break;
+		case NET_BAND_LTE_20:
+		strncpy(band,"BAND_LTE_20",BAND_LEN);
+		break;
+		case NET_BAND_LTE_21:
+		strncpy(band,"BAND_LTE_21",BAND_LEN);
+		break;
+		case NET_BAND_LTE_22:
+		strncpy(band,"BAND_LTE_22",BAND_LEN);
+		break;
+		case NET_BAND_LTE_23:
+		strncpy(band,"BAND_LTE_23",BAND_LEN);
+		break;
+		case NET_BAND_LTE_24:
+		strncpy(band,"BAND_LTE_24",BAND_LEN);
+		break;
+		case NET_BAND_LTE_25:
+		strncpy(band,"BAND_LTE_25",BAND_LEN);
+		break;
+		case NET_BAND_LTE_26:
+		strncpy(band,"BAND_LTE_26",BAND_LEN);
+		break;
+		case NET_BAND_LTE_27:
+		strncpy(band,"BAND_LTE_27",BAND_LEN);
+		break;
+		case NET_BAND_LTE_28:
+		strncpy(band,"BAND_LTE_28",BAND_LEN);
+		break;
+		case NET_BAND_LTE_33:
+		strncpy(band,"BAND_LTE_33",BAND_LEN);
+		break;
+		case NET_BAND_LTE_34:
+		strncpy(band,"BAND_LTE_34",BAND_LEN);
+		break;
+		case NET_BAND_LTE_35:
+		strncpy(band,"BAND_LTE_35",BAND_LEN);
+		break;
+		case NET_BAND_LTE_36:
+		strncpy(band,"BAND_LTE_36",BAND_LEN);
+		break;
+		case NET_BAND_LTE_37:
+		strncpy(band,"BAND_LTE_37",BAND_LEN);
+		break;
+		case NET_BAND_LTE_38:
+		strncpy(band,"BAND_LTE_38",BAND_LEN);
+		break;
+		case NET_BAND_LTE_39:
+		strncpy(band,"BAND_LTE_39",BAND_LEN);
+		break;
+		case NET_BAND_LTE_40:
+		strncpy(band,"BAND_LTE_40",BAND_LEN);
+		break;
+		case NET_BAND_LTE_41:
+		strncpy(band,"BAND_LTE_41",BAND_LEN);
+		break;
+		case NET_BAND_LTE_42:
+		strncpy(band,"BAND_LTE_42",BAND_LEN);
+		break;
+		case NET_BAND_LTE_43:
+		strncpy(band,"BAND_LTE_43",BAND_LEN);
+		break;
+		default:
+		strncpy(band,"INVALID",BAND_LEN);
+		break;
+	}
+}
+
+static void xmm_lte_band_notify(GAtResult *result, gpointer user_data)
+{
+	struct ofono_coex *coex = user_data;
+	GAtResultIter iter;
+	int lte_band;
+	char band[BAND_LEN];
+
+	g_at_result_iter_init(&iter, result);
+
+	if (!g_at_result_iter_next(&iter, "+XCCINFO:"))
+		return;
+
+	g_at_result_iter_skip_next(&iter);
+	g_at_result_iter_skip_next(&iter);
+	g_at_result_iter_skip_next(&iter);
+	g_at_result_iter_skip_next(&iter);
+
+	if (!g_at_result_iter_next_number(&iter, &lte_band))
+		return;
+
+	xmm_get_band_string(lte_band, band);
+
+	DBG("lte_band:%s", band);
+	ofono_coex_ril_lte_band_notify(coex, band);
+}
+
+static void xmm_coex_w_notify(GAtResult *result, gpointer user_data)
+{
+	struct ofono_coex *coex = user_data;
+	GAtResultIter iter;
+	int safe_tx_min;
+	int safe_tx_max;
+	int safe_rx_min;
+	int safe_rx_max;
+	int safe_vector[MAX_BT_SAFE_VECTOR];
+	int num_safe_vector;
+	int count;
+
+	g_at_result_iter_init(&iter, result);
+
+	if (!g_at_result_iter_next(&iter, "+XNRTCWSW:"))
+		return;
+
+	g_at_result_iter_next_number(&iter, &safe_rx_min);
+
+	g_at_result_iter_skip_next(&iter);
+
+	g_at_result_iter_skip_next(&iter);
+
+	g_at_result_iter_next_number(&iter, &safe_rx_max);
+
+	g_at_result_iter_skip_next(&iter);
+
+	g_at_result_iter_skip_next(&iter);
+
+	g_at_result_iter_next_number(&iter, &safe_tx_min);
+
+	g_at_result_iter_skip_next(&iter);
+
+	g_at_result_iter_skip_next(&iter);
+
+	g_at_result_iter_next_number(&iter, &safe_tx_max);
+
+	g_at_result_iter_skip_next(&iter);
+
+	g_at_result_iter_skip_next(&iter);
+
+	g_at_result_iter_skip_next(&iter);
+
+	g_at_result_iter_next_number(&iter, &num_safe_vector);
+
+	for(count = 0; count < num_safe_vector; count++) {
+		g_at_result_iter_next_number(&iter, &safe_vector[count]);
+	}
+
+	DBG("WLAN notification");
+
+	ofono_wlan_coex_status_notify(coex, safe_tx_min, safe_tx_max,
+		safe_rx_min, safe_rx_max,num_safe_vector,safe_vector);
+}
+
+
+static void xmm_coex_b_notify(GAtResult *result, gpointer user_data)
+{
+	struct ofono_coex *coex = user_data;
+	GAtResultIter iter;
+	int safe_tx_min;
+	int safe_tx_max;
+	int safe_rx_min;
+	int safe_rx_max;
+	int safe_vector[MAX_BT_SAFE_VECTOR];
+	int num_safe_vector;
+	int count;
+
+	g_at_result_iter_init(&iter, result);
+
+	if (!g_at_result_iter_next(&iter, "+XNRTCWSB:"))
+		return;
+
+	g_at_result_iter_next_number(&iter, &safe_rx_min);
+
+	g_at_result_iter_next_number(&iter, &safe_rx_max);
+
+	g_at_result_iter_next_number(&iter, &safe_tx_min);
+
+	g_at_result_iter_next_number(&iter, &safe_tx_max);
+
+	g_at_result_iter_next_number(&iter, &num_safe_vector);
+
+	for(count = 0; count < num_safe_vector; count++) {
+		g_at_result_iter_next_number(&iter, &safe_vector[count]);
+	}
+
+	DBG("BT notification");
+
+	ofono_wlan_coex_status_notify(coex, safe_tx_min, safe_tx_max,
+		safe_rx_min, safe_rx_max,num_safe_vector,safe_vector);
+}
+
+static void xmm_coex_enable_cb(gboolean ok, GAtResult *result,
+					gpointer user_data)
+{
+	struct cb_data *cbd = user_data;
+	ofono_coex_enable_cb_t cd = cbd->cb;
+
+	DBG("ok %d", ok);
+
+	if (!ok) {
+		struct ofono_error error;
+		decode_at_error(&error, g_at_result_final_response(result));
+		cd(&error, cbd->data);
+		return;
+	}
+
+	CALLBACK_WITH_SUCCESS(cd, cbd->data);
+}
+
+
+
+static void xmm_coex_enable(struct ofono_coex *coex,
+			ofono_coex_enable_cb_t cb, void *data)
+{
+	struct coex_data *cd = ofono_coex_get_data(coex);
+	struct cb_data *cbd = cb_data_new(cb, data);
+
+	DBG("");
+
+	if(g_at_chat_send(cd->chat, "AT+XNRTCWS=7", none_prefix,
+				xmm_coex_enable_cb, cbd, NULL) > 0)
+		return;
+
+	CALLBACK_WITH_FAILURE(cb, data);
+	g_free(cbd);
+}
+
+static int xmm_coex_probe(struct ofono_coex *coex, unsigned int vendor,
+				void *user)
+{
+	GAtChat *chat = user;
+	struct coex_data *cd;
+
+	DBG("at coex probe");
+
+	cd = g_try_new0(struct coex_data, 1);
+	if (!cd)
+		return -ENOMEM;
+
+	cd->chat = g_at_chat_clone(chat);
+
+	ofono_coex_set_data(coex, cd);
+
+	g_at_chat_register(cd->chat, "+XNRTCWSL:", xmm_coex_l_notify,
+					FALSE, coex, NULL);
+	g_at_chat_register(cd->chat, "+XNRTCWSW:", xmm_coex_w_notify,
+					FALSE, coex, NULL);
+	g_at_chat_register(cd->chat, "+XNRTCWSB:", xmm_coex_b_notify,
+					FALSE, coex, NULL);
+	g_at_chat_register(cd->chat, "+XCCINFO:", xmm_lte_band_notify,
+					FALSE, coex, NULL);
+
+	g_at_chat_send(cd->chat, "AT+XCCINFO=1", none_prefix,
+				NULL, NULL, NULL);
+	g_at_chat_send(cd->chat, "AT+XNRTAPP=10,100", none_prefix,
+				NULL, NULL, NULL);
+
+	ofono_coex_register(coex);
+
+	return 0;
+}
+
+static void xmm_coex_remove_cb(gboolean ok, GAtResult *result,
+					gpointer user_data)
+{
+	struct cb_data *cbd = user_data;
+	ofono_coex_enable_cb_t cd = cbd->cb;
+
+	DBG("ok %d", ok);
+
+	if (!ok) {
+		struct ofono_error error;
+		decode_at_error(&error, g_at_result_final_response(result));
+		cd(&error, cbd->data);
+		return;
+	}
+
+	CALLBACK_WITH_SUCCESS(cd, cbd->data);
+}
+
+
+static void xmm_coex_remove(struct ofono_coex *coex,
+			ofono_coex_remove_cb_t cb, void *data)
+{
+	struct coex_data *cd = ofono_coex_get_data(coex);
+	struct cb_data *cbd = cb_data_new(cb, data);
+
+	DBG("");
+
+	if(g_at_chat_send(cd->chat, "AT+XNRTCWS=0", none_prefix,
+				xmm_coex_remove_cb, cbd, NULL) > 0)
+		return;
+
+	CALLBACK_WITH_FAILURE(cb, data);
+	g_free(cbd);
+}
+
+static void xmm_set_bt_active_cb(gboolean ok, GAtResult *result,
+					gpointer user_data)
+{
+	struct cb_data *cbd = user_data;
+	ofono_coex_enable_cb_t cd = cbd->cb;
+	struct coex_data* coex = ofono_coex_get_data(cbd->data);
+
+	DBG("ok %d", ok);
+
+	if (!ok) {
+		struct ofono_error error;
+		decode_at_error(&error, g_at_result_final_response(result));
+		cd(&error, cbd->data);
+		return;
+	}
+
+	coex->bt_active = coex->bt_active_pending;
+	CALLBACK_WITH_SUCCESS(cd, cbd->data);
+}
+
+
+
+static void xmm_set_bt_active(struct ofono_coex *coex, ofono_bool_t bt_active,
+			ofono_coex_bt_active_set_cb_t cb, void *data)
+{
+	struct coex_data *cd = ofono_coex_get_data(coex);
+	struct cb_data *cbd = cb_data_new(cb, data);
+	char buf[64];
+
+	DBG("");
+	sprintf(buf, "AT+XNRTCWS=65535,%u,%u,%u", (int)cd->wlan_active,
+				(int)cd->wlan_bw,bt_active);
+	if(g_at_chat_send(cd->chat, buf, none_prefix,
+				xmm_set_bt_active_cb, cbd, NULL) > 0) {
+	cd->bt_active_pending = bt_active;
+		return;
+	}
+
+	CALLBACK_WITH_FAILURE(cb, data);
+	g_free(cbd);
+}
+
+
+static void xmm_set_wlan_active_cb(gboolean ok, GAtResult *result,
+					gpointer user_data)
+{
+	struct cb_data *cbd = user_data;
+	ofono_coex_enable_cb_t cd = cbd->cb;
+	struct coex_data* coex = ofono_coex_get_data(cbd->data);
+
+	DBG("ok %d", ok);
+
+	if (!ok) {
+		struct ofono_error error;
+		decode_at_error(&error, g_at_result_final_response(result));
+		cd(&error, cbd->data);
+		return;
+	}
+
+	coex->wlan_active = coex->wlan_active_pending;
+	coex->wlan_bw = coex->wlan_bw_pending;
+	CALLBACK_WITH_SUCCESS(cd, cbd->data);
+}
+
+static void xmm_get_plmn_history_cb(gboolean ok, GAtResult *result,
+					gpointer user_data)
+{
+	struct cb_data *cbd = user_data;
+	ofono_coex_get_plmn_history_cb_t cd = cbd->cb;
+	struct Plmnhist *list = NULL;
+	GAtResultIter iter;
+	int list_size = 0;
+
+	DBG("ok %d", ok);
+
+	if (!ok) {
+		CALLBACK_WITH_FAILURE(cd, 0, NULL, cbd->data);
+		return;
+	}
+
+	g_at_result_iter_init(&iter, result);
+
+	while (g_at_result_iter_next(&iter, "+XNVMPLMN:")) {
+		if (!list_size)
+			list = g_new0(struct Plmnhist, ++list_size);
+		else
+			list = g_renew(struct Plmnhist, list, ++list_size);
+
+		g_at_result_iter_next_number(&iter, (int*)&list[list_size - 1].mcc);
+		g_at_result_iter_next_number(&iter, (int*)&list[list_size - 1].mnc);
+		g_at_result_iter_next_number(&iter, (int*)&list[list_size - 1].fdd);
+		g_at_result_iter_next_number(&iter, (int*)&list[list_size - 1].tdd);
+		g_at_result_iter_next_number(&iter, (int*)&list[list_size - 1].bw);
+
+		DBG("list_size = %d", list_size);
+	}
+
+	CALLBACK_WITH_SUCCESS(cd, list_size, list, cbd->data);
+	if(list)
+		g_free(list);
+}
+
+static void xmm_get_plmn_history(struct ofono_coex *coex,
+			ofono_coex_get_plmn_history_cb_t cb, void *data)
+{
+	struct coex_data *cd = ofono_coex_get_data(coex);
+	struct cb_data *cbd = cb_data_new(cb, data);
+
+	DBG("");
+	if(g_at_chat_send(cd->chat, "AT+XNVMPLMN=2,2", xnvmplmn_prefix,
+				xmm_get_plmn_history_cb, cbd, NULL) > 0) {
+		return;
+	}
+
+	CALLBACK_WITH_FAILURE(cb, 0, NULL, cbd->data);
+	g_free(cbd);
+}
+
+
+static void xmm_set_wlan_active(struct ofono_coex *coex,
+			ofono_bool_t wlan_active, enum ofono_wlan_bw wlan_bw,
+			ofono_coex_bt_active_set_cb_t cb, void *data)
+{
+	struct coex_data *cd = ofono_coex_get_data(coex);
+	struct cb_data *cbd = cb_data_new(cb, data);
+	char buf[64];
+
+	DBG("");
+	sprintf(buf, "AT+XNRTCWS=65535,%u,%u", (int)wlan_active,
+				(int)wlan_bw);
+	if(g_at_chat_send(cd->chat, buf, none_prefix,
+				xmm_set_wlan_active_cb, cbd, NULL) > 0) {
+		cd->wlan_active_pending = wlan_active;
+		cd->wlan_bw = wlan_bw;
+		return;
+	}
+
+	CALLBACK_WITH_FAILURE(cb, data);
+	g_free(cbd);
+}
+
+
+static struct ofono_coex_driver driver = {
+	.name = "xmm7modem",
+	.probe = xmm_coex_probe,
+	.enable = xmm_coex_enable,
+	.remove = xmm_coex_remove,
+	.set_bt_active = xmm_set_bt_active,
+	.set_wlan_active = xmm_set_wlan_active,
+	.get_plmn_history = xmm_get_plmn_history
+};
+
+void xmm_coex_init(void)
+{
+	ofono_coex_driver_register(&driver);
+}
+
+void xmm_coex_exit(void)
+{
+	ofono_coex_driver_unregister(&driver);
+}
-- 
1.9.1


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2018-10-01 10:35 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-10-01 10:35 [PATCH 5/6] coex: Added xmm7modem driver for coex Antara Borwankar

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.