--- /dev/null
+Copyright (C) 2012 Intel Corporation. All rights reserved.\r
+\r
+ Apache License\r
+ Version 2.0, January 2004\r
+ http://www.apache.org/licenses/\r
+\r
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\r
+\r
+ 1. Definitions.\r
+\r
+ "License" shall mean the terms and conditions for use, reproduction,\r
+ and distribution as defined by Sections 1 through 9 of this document.\r
+\r
+ "Licensor" shall mean the copyright owner or entity authorized by\r
+ the copyright owner that is granting the License.\r
+\r
+ "Legal Entity" shall mean the union of the acting entity and all\r
+ other entities that control, are controlled by, or are under common\r
+ control with that entity. For the purposes of this definition,\r
+ "control" means (i) the power, direct or indirect, to cause the\r
+ direction or management of such entity, whether by contract or\r
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the\r
+ outstanding shares, or (iii) beneficial ownership of such entity.\r
+\r
+ "You" (or "Your") shall mean an individual or Legal Entity\r
+ exercising permissions granted by this License.\r
+\r
+ "Source" form shall mean the preferred form for making modifications,\r
+ including but not limited to software source code, documentation\r
+ source, and configuration files.\r
+\r
+ "Object" form shall mean any form resulting from mechanical\r
+ transformation or translation of a Source form, including but\r
+ not limited to compiled object code, generated documentation,\r
+ and conversions to other media types.\r
+\r
+ "Work" shall mean the work of authorship, whether in Source or\r
+ Object form, made available under the License, as indicated by a\r
+ copyright notice that is included in or attached to the work\r
+ (an example is provided in the Appendix below).\r
+\r
+ "Derivative Works" shall mean any work, whether in Source or Object\r
+ form, that is based on (or derived from) the Work and for which the\r
+ editorial revisions, annotations, elaborations, or other modifications\r
+ represent, as a whole, an original work of authorship. For the purposes\r
+ of this License, Derivative Works shall not include works that remain\r
+ separable from, or merely link (or bind by name) to the interfaces of,\r
+ the Work and Derivative Works thereof.\r
+\r
+ "Contribution" shall mean any work of authorship, including\r
+ the original version of the Work and any modifications or additions\r
+ to that Work or Derivative Works thereof, that is intentionally\r
+ submitted to Licensor for inclusion in the Work by the copyright owner\r
+ or by an individual or Legal Entity authorized to submit on behalf of\r
+ the copyright owner. For the purposes of this definition, "submitted"\r
+ means any form of electronic, verbal, or written communication sent\r
+ to the Licensor or its representatives, including but not limited to\r
+ communication on electronic mailing lists, source code control systems,\r
+ and issue tracking systems that are managed by, or on behalf of, the\r
+ Licensor for the purpose of discussing and improving the Work, but\r
+ excluding communication that is conspicuously marked or otherwise\r
+ designated in writing by the copyright owner as "Not a Contribution."\r
+\r
+ "Contributor" shall mean Licensor and any individual or Legal Entity\r
+ on behalf of whom a Contribution has been received by Licensor and\r
+ subsequently incorporated within the Work.\r
+\r
+ 2. Grant of Copyright License. Subject to the terms and conditions of\r
+ this License, each Contributor hereby grants to You a perpetual,\r
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable\r
+ copyright license to reproduce, prepare Derivative Works of,\r
+ publicly display, publicly perform, sublicense, and distribute the\r
+ Work and such Derivative Works in Source or Object form.\r
+\r
+ 3. Grant of Patent License. Subject to the terms and conditions of\r
+ this License, each Contributor hereby grants to You a perpetual,\r
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable\r
+ (except as stated in this section) patent license to make, have made,\r
+ use, offer to sell, sell, import, and otherwise transfer the Work,\r
+ where such license applies only to those patent claims licensable\r
+ by such Contributor that are necessarily infringed by their\r
+ Contribution(s) alone or by combination of their Contribution(s)\r
+ with the Work to which such Contribution(s) was submitted. If You\r
+ institute patent litigation against any entity (including a\r
+ cross-claim or counterclaim in a lawsuit) alleging that the Work\r
+ or a Contribution incorporated within the Work constitutes direct\r
+ or contributory patent infringement, then any patent licenses\r
+ granted to You under this License for that Work shall terminate\r
+ as of the date such litigation is filed.\r
+\r
+ 4. Redistribution. You may reproduce and distribute copies of the\r
+ Work or Derivative Works thereof in any medium, with or without\r
+ modifications, and in Source or Object form, provided that You\r
+ meet the following conditions:\r
+\r
+ (a) You must give any other recipients of the Work or\r
+ Derivative Works a copy of this License; and\r
+\r
+ (b) You must cause any modified files to carry prominent notices\r
+ stating that You changed the files; and\r
+\r
+ (c) You must retain, in the Source form of any Derivative Works\r
+ that You distribute, all copyright, patent, trademark, and\r
+ attribution notices from the Source form of the Work,\r
+ excluding those notices that do not pertain to any part of\r
+ the Derivative Works; and\r
+\r
+ (d) If the Work includes a "NOTICE" text file as part of its\r
+ distribution, then any Derivative Works that You distribute must\r
+ include a readable copy of the attribution notices contained\r
+ within such NOTICE file, excluding those notices that do not\r
+ pertain to any part of the Derivative Works, in at least one\r
+ of the following places: within a NOTICE text file distributed\r
+ as part of the Derivative Works; within the Source form or\r
+ documentation, if provided along with the Derivative Works; or,\r
+ within a display generated by the Derivative Works, if and\r
+ wherever such third-party notices normally appear. The contents\r
+ of the NOTICE file are for informational purposes only and\r
+ do not modify the License. You may add Your own attribution\r
+ notices within Derivative Works that You distribute, alongside\r
+ or as an addendum to the NOTICE text from the Work, provided\r
+ that such additional attribution notices cannot be construed\r
+ as modifying the License.\r
+\r
+ You may add Your own copyright statement to Your modifications and\r
+ may provide additional or different license terms and conditions\r
+ for use, reproduction, or distribution of Your modifications, or\r
+ for any such Derivative Works as a whole, provided Your use,\r
+ reproduction, and distribution of the Work otherwise complies with\r
+ the conditions stated in this License.\r
+\r
+ 5. Submission of Contributions. Unless You explicitly state otherwise,\r
+ any Contribution intentionally submitted for inclusion in the Work\r
+ by You to the Licensor shall be under the terms and conditions of\r
+ this License, without any additional terms or conditions.\r
+ Notwithstanding the above, nothing herein shall supersede or modify\r
+ the terms of any separate license agreement you may have executed\r
+ with Licensor regarding such Contributions.\r
+\r
+ 6. Trademarks. This License does not grant permission to use the trade\r
+ names, trademarks, service marks, or product names of the Licensor,\r
+ except as required for reasonable and customary use in describing the\r
+ origin of the Work and reproducing the content of the NOTICE file.\r
+\r
+ 7. Disclaimer of Warranty. Unless required by applicable law or\r
+ agreed to in writing, Licensor provides the Work (and each\r
+ Contributor provides its Contributions) on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\r
+ implied, including, without limitation, any warranties or conditions\r
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\r
+ PARTICULAR PURPOSE. You are solely responsible for determining the\r
+ appropriateness of using or redistributing the Work and assume any\r
+ risks associated with Your exercise of permissions under this License.\r
+\r
+ 8. Limitation of Liability. In no event and under no legal theory,\r
+ whether in tort (including negligence), contract, or otherwise,\r
+ unless required by applicable law (such as deliberate and grossly\r
+ negligent acts) or agreed to in writing, shall any Contributor be\r
+ liable to You for damages, including any direct, indirect, special,\r
+ incidental, or consequential damages of any character arising as a\r
+ result of this License or out of the use or inability to use the\r
+ Work (including but not limited to damages for loss of goodwill,\r
+ work stoppage, computer failure or malfunction, or any and all\r
+ other commercial damages or losses), even if such Contributor\r
+ has been advised of the possibility of such damages.\r
+\r
+ 9. Accepting Warranty or Additional Liability. While redistributing\r
+ the Work or Derivative Works thereof, You may choose to offer,\r
+ and charge a fee for, acceptance of support, warranty, indemnity,\r
+ or other liability obligations and/or rights consistent with this\r
+ License. However, in accepting such obligations, You may act only\r
+ on Your own behalf and on Your sole responsibility, not on behalf\r
+ of any other Contributor, and only if You agree to indemnify,\r
+ defend, and hold each Contributor harmless for any liability\r
+ incurred by, or claims asserted against, such Contributor by reason\r
+ of your accepting any such warranty or additional liability.\r
+\r
+ END OF TERMS AND CONDITIONS\r
+\r
+ APPENDIX: How to apply the Apache License to your work.\r
+\r
+ To apply the Apache License to your work, attach the following\r
+ boilerplate notice, with the fields enclosed by brackets "[]"\r
+ replaced with your own identifying information. (Don't include\r
+ the brackets!) The text should be enclosed in the appropriate\r
+ comment syntax for the file format. We also recommend that a\r
+ file or class name and description of purpose be included on the\r
+ same "printed page" as the copyright notice for easier\r
+ identification within third-party archives.\r
+\r
+ Copyright [yyyy] [name of copyright owner]\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
--- /dev/null
+/*
+*
+* tel-plugin-mfld-blackbay
+*
+* Copyright (C) 2013 Intel Corporation. All rights reserved.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <termios.h>
+#include <sys/stat.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <linux/if_ether.h>
+#include <fcntl.h>
+
+#include <glib.h>
+
+#include <tcore.h>
+#include <server.h>
+#include <plugin.h>
+#include <core_object.h>
+
+
+#include <user_request.h>
+#include <hal.h>
+#include <mux.h>
+#include <at.h>
+#include <queue.h>
+
+#include "util_mfld_blackbay.h"
+
+#define DEVICE_IFX "/dev/ttyIFX0"
+#define N_GSM0710 21
+#define NUM_DLC 7
+#define NUM_DATA_DLC 2
+#define BUF_LEN_MAX 512
+
+struct custom_data {
+ TcorePlugin *plugin;
+ GIOChannel *channel;
+ guint watch_id;
+ CoreObject *co;
+ void *cb;
+ void *cb_data;
+ guint dlc_poll_count;
+ guint dlc_poll_src;
+ gboolean rawip_enabled;
+ union {
+ TcoreHal *hal[NUM_DLC];
+ TcoreHal *data_hal[NUM_DATA_DLC];
+ };
+};
+
+#define GSMIOC_GETCONF _IOR('G', 0, struct gsm_config)
+#define GSMIOC_SETCONF _IOW('G', 1, struct gsm_config)
+#define GSMIOC_ENABLE_NET _IOW('G', 2, struct gsm_netconfig)
+#define GSMIOC_DISABLE_NET _IO('G', 3)
+
+struct gsm_config {
+ unsigned int adaption;
+ unsigned int encapsulation;
+ unsigned int initiator;
+ unsigned int t1;
+ unsigned int t2;
+ unsigned int t3;
+ unsigned int n2;
+ unsigned int mru;
+ unsigned int mtu;
+ unsigned int k;
+ unsigned int i;
+ unsigned int clocal;
+ unsigned int unused[7]; /* Padding for expansion without breaking stuff */
+};
+
+struct gsm_netconfig {
+ unsigned int adaption; /* Adaption to use in network mode */
+ unsigned short protocol; /* Protocol to use - only ETH_P_IP supported */
+ unsigned short unused2;
+ char if_name[IFNAMSIZ]; /* interface name format string */
+ __u8 unused[28]; /* For future use */
+};
+
+/* Virtual ttys for KERNEL mux */
+static const char *dlc_nodes[NUM_DLC] =
+ { "/dev/gsmtty1", "/dev/gsmtty2",
+ "/dev/gsmtty3", "/dev/gsmtty4",
+ "/dev/gsmtty6", "/dev/gsmtty7",
+ "/dev/gsmtty8" };
+
+static TReturn hal_power(TcoreHal *hal, gboolean flag);
+static TReturn hal_send(TcoreHal *hal, unsigned int data_len, void *data);
+static TReturn hal_setup_netif(CoreObject *co, TcoreHalSetupNetifCallback func,
+ void *user_data, unsigned int cid,
+ gboolean enable);
+
+static struct tcore_hal_operations hops = {
+ .power = hal_power,
+ .send = hal_send,
+ .setup_netif = hal_setup_netif,
+};
+
+static TReturn prepare_and_send_at_request(TcoreHal *hal,
+ const char *at_cmd,
+ const char *at_cmd_prefix,
+ enum tcore_at_command_type at_cmd_type,
+ TcorePendingResponseCallback resp_cb,
+ void *resp_cb_data)
+{
+ TcorePending *pending;
+ TcoreATRequest *req;
+
+ /* Create Pending Request */
+ pending = tcore_pending_new(NULL, 0);
+ if (pending == NULL) {
+ dbg("Memory failure, pending is NULL");
+ return TCORE_RETURN_ENOMEM;
+ }
+
+ /* Create AT-Command Request */
+ req = tcore_at_request_new(at_cmd, at_cmd_prefix, at_cmd_type);
+ if (req == NULL) {
+ dbg("Memory failure, request is NULL");
+ tcore_pending_free(pending);
+ return TCORE_RETURN_ENOMEM;
+ }
+
+ dbg("AT Command: %s, Prefix(if any):%s, AT-Command length: %d",
+ req->cmd, req->prefix, strlen(req->cmd));
+
+ tcore_pending_set_request_data(pending, 0, req);
+ tcore_pending_set_response_callback(pending, resp_cb, resp_cb_data);
+
+ return tcore_hal_send_request(hal, pending);
+}
+
+static gboolean on_recv_tty_message(GIOChannel *channel,
+ GIOCondition condition, gpointer data)
+{
+ TcoreHal *hal = data;
+ char read_buffer[BUF_LEN_MAX];
+ size_t bytes_read;
+
+ if (condition & G_IO_NVAL)
+ return FALSE;
+
+ bytes_read = channel_read(channel, read_buffer, BUF_LEN_MAX);
+ if (bytes_read == 0) {
+ err("channel_read error.");
+ return FALSE;
+ }
+
+ dbg("bytes_read = %d", bytes_read);
+ tcore_hal_emit_recv_callback(hal, bytes_read, read_buffer);
+
+ tcore_hal_dispatch_response_data(hal, 0, bytes_read, read_buffer);
+
+ return TRUE;
+}
+
+static gboolean setup_channel(GIOChannel *io)
+{
+ GIOFlags io_flags;
+
+ if (g_io_channel_set_encoding(io, NULL, NULL) != G_IO_STATUS_NORMAL)
+ return FALSE;
+
+ g_io_channel_set_buffered(io, FALSE);
+ io_flags = g_io_channel_get_flags(io);
+ io_flags |= (G_IO_FLAG_NONBLOCK & G_IO_FLAG_SET_MASK);
+
+ if (g_io_channel_set_flags(io, io_flags, NULL) != G_IO_STATUS_NORMAL)
+ return FALSE;
+
+ g_io_channel_set_close_on_unref(io, TRUE);
+
+ return TRUE;
+}
+
+static void set_termio(int fd)
+{
+ struct termios newtio;
+
+ /* Switch TTY to raw mode */
+ memset(&newtio, 0, sizeof(newtio));
+ cfmakeraw(&newtio);
+
+ /* Line is local */
+ newtio.c_cflag |= CLOCAL;
+
+ tcflush(fd, TCIFLUSH);
+ tcsetattr(fd, TCSANOW, &newtio);
+}
+
+static int open_device(const char *tty)
+{
+ int fd;
+
+ fd = open(tty, O_RDWR | O_NOCTTY | O_NONBLOCK);
+ if (fd < 0)
+ return -1;
+
+ set_termio(fd);
+
+ return fd;
+}
+
+static GIOChannel *tty_open(const char *tty)
+{
+ GIOChannel *channel;
+ int fd;
+
+ fd = open_device(tty);
+ if (fd < 0)
+ return NULL;
+
+ dbg("fd =%d ", fd);
+
+ channel = g_io_channel_unix_new(fd);
+ if (channel == NULL) {
+ close(fd);
+ return NULL;
+ }
+
+ setup_channel(channel);
+
+ return channel;
+}
+
+static guint register_gio_watch(GIOChannel *channel, void *callback,
+ TcoreHal *h)
+{
+ guint source;
+
+ if (channel == NULL || callback == NULL)
+ return 0;
+
+ source = g_io_add_watch(channel, G_IO_IN, (GIOFunc) callback, h);
+
+ return source;
+}
+
+/* This table contains information of which HAL <--> CoreObject Type */
+static void mapping_table_insert_hals(TcorePlugin *pg, TcoreHal **hal)
+{
+ struct custom_data *cdata = tcore_hal_ref_user_data(hal[4]);
+
+ dbg("Entry");
+
+ tcore_server_add_cp_mapping_tbl_entry(pg, CORE_OBJECT_TYPE_MODEM, hal[0]);
+ tcore_server_add_cp_mapping_tbl_entry(pg, CORE_OBJECT_TYPE_CALL, hal[0]);
+ tcore_server_add_cp_mapping_tbl_entry(pg, CORE_OBJECT_TYPE_SIM, hal[1]);
+ tcore_server_add_cp_mapping_tbl_entry(pg, CORE_OBJECT_TYPE_SAT, hal[1]);
+ tcore_server_add_cp_mapping_tbl_entry(pg, CORE_OBJECT_TYPE_SAP, hal[1]);
+ tcore_server_add_cp_mapping_tbl_entry(pg, CORE_OBJECT_TYPE_PHONEBOOK, hal[1]);
+ tcore_server_add_cp_mapping_tbl_entry(pg, CORE_OBJECT_TYPE_SMS, hal[2]);
+ tcore_server_add_cp_mapping_tbl_entry(pg, CORE_OBJECT_TYPE_NETWORK, hal[3]);
+ tcore_server_add_cp_mapping_tbl_entry(pg, CORE_OBJECT_TYPE_SS, hal[3]);
+ tcore_server_add_cp_mapping_tbl_entry(pg, CORE_OBJECT_TYPE_PS, hal[4]);
+ tcore_server_add_cp_mapping_tbl_entry(pg, CORE_OBJECT_TYPE_GPS, hal[4]);
+
+ cdata->data_hal[0] = hal[5];
+ cdata->data_hal[1] = hal[6];
+
+ dbg("Exit");
+}
+
+static void remove_custom_data(TcoreHal *hal_log)
+{
+ struct custom_data *cdata = tcore_hal_ref_user_data(hal_log);
+
+ if (cdata == NULL)
+ return;
+
+ if (cdata->watch_id > 0) {
+ g_source_remove(cdata->watch_id);
+ cdata->watch_id = 0;
+ }
+
+ g_io_channel_unref(cdata->channel);
+ g_free(cdata);
+}
+
+static void remove_logical_hals(TcoreHal *hal_phy)
+{
+ struct custom_data *cdata = tcore_hal_ref_user_data(hal_phy);
+ int i;
+
+ dbg("Entry");
+
+ for (i = 0; i < NUM_DLC; i++) {
+ if (cdata->hal[i] == NULL)
+ continue;
+
+ /* Remove mapping table entries based on hal */
+ tcore_server_remove_cp_mapping_tbl_entry(cdata->plugin,
+ cdata->hal[i]);
+
+ remove_custom_data(cdata->hal[i]);
+ tcore_hal_free(cdata->hal[i]);
+ }
+
+ dbg("Exit");
+}
+
+static gboolean dlc_ready_check(gpointer user_data)
+{
+ TcoreHal *h = user_data;
+ struct custom_data *cdata = tcore_hal_ref_user_data(h);
+ struct stat st;
+ Server *server;
+ int i;
+ gint fd;
+
+ dbg("Entry");
+
+ if (cdata == NULL) {
+ err("Cannot retrieve Custom DATA from physical HAL\n"
+ "Cannot proceed with dlc ready check");
+ return FALSE;
+ }
+ cdata->dlc_poll_count++;
+
+ if (stat(dlc_nodes[0], &st) < 0) {
+ /* only possible error is ENOENT */
+ if (cdata->dlc_poll_count > 6)
+ goto error;
+
+ return TRUE;
+ }
+
+ fd = g_io_channel_unix_get_fd(cdata->channel);
+ set_termio(fd);
+
+ for (i = 0; i < NUM_DLC; i++) {
+ TcoreHal *hal = NULL;
+ struct custom_data *hal_data;
+ char channel_id_name[16];
+
+ hal_data = g_try_new0(struct custom_data, 1);
+
+ hal_data->channel = tty_open(dlc_nodes[i]);
+
+ if (hal_data->channel == NULL) {
+ err("Failed to open tty port - [%s]", strerror(errno));
+
+ goto error;
+ } else
+ dbg("Virtual tty port opened successfully. channel:%p,"
+ "path:%s", hal_data->channel, dlc_nodes[i]);
+
+ snprintf(channel_id_name, sizeof(channel_id_name),
+ "channel_%d", i);
+ hal = tcore_hal_new(cdata->plugin, channel_id_name, &hops,
+ TCORE_HAL_MODE_AT);
+ hal_data->watch_id = register_gio_watch(hal_data->channel,
+ on_recv_tty_message,
+ hal);
+
+ dbg("hal=%p %s=%p watch_id=%d ", hal, channel_id_name,
+ hal_data->channel, hal_data->watch_id);
+
+ g_io_channel_unref(hal_data->channel);
+
+ tcore_hal_set_power_state(hal, TRUE);
+
+ tcore_hal_link_user_data(hal, hal_data);
+
+ cdata->hal[i] = hal;
+ }
+
+ /* Map Core Object to corresponding logical HAL */
+ mapping_table_insert_hals(cdata->plugin, cdata->hal);
+
+ server = tcore_plugin_ref_server(tcore_hal_ref_plugin(h));
+ if (tcore_server_load_modem_plugin(server, cdata->plugin,
+ "imc-plugin.so") != TCORE_RETURN_SUCCESS)
+ err("Failed to load Vendor plugin IMC");
+
+error:
+ cdata->dlc_poll_src = 0;
+
+ return FALSE;
+}
+
+static int setup_mux(TcoreHal *h)
+{
+ struct gsm_config cfg;
+ int ldisc = N_GSM0710;
+ int ret = 0;
+ struct custom_data *data;
+ gint fd;
+
+ dbg("Function Enter");
+
+ data = tcore_hal_ref_user_data(h);
+ if (!data) {
+ err("Cannot retrieve Custom DATA from physical HAL");
+ return TCORE_RETURN_FAILURE;
+ }
+
+ fd = g_io_channel_unix_get_fd(data->channel);
+ if (fd < 0){
+ err("fd not available\n");
+ return -1;
+ }
+
+ ret = ioctl(fd, TIOCSETD, &ldisc);
+ if (ret < 0) {
+ err("Set ioctl failed [%s]\n", strerror(errno));
+ return -1;
+ }
+
+ ret = ioctl(fd, TIOCGETD, &ldisc);
+ if (ret < 0) {
+ err("Get ioctl failed [%s]\n", strerror(errno));
+ return -1;
+ }
+
+ if (ldisc != N_GSM0710) {
+ err("Unable to set line discipline\n");
+ return -1;
+ }
+
+ /* configure mux */
+ memset(&cfg, 0, sizeof(struct gsm_config));
+
+ ret = ioctl(fd, GSMIOC_GETCONF, &cfg);
+ if (ret < 0) {
+ err("Get config ioctl failed [%s]\n", strerror(errno));
+ return -1;
+ }
+
+ cfg.encapsulation = 0; /* encoding -- set to basic */
+ cfg.initiator = 1; /* we are starting side */
+ cfg.mru = 32768; /* In specification 3GPP TS 27.010, 5.7.2 */
+ cfg.mtu = 32768; /* In specification 3GPP TS 27.010, 5.7.2 */
+
+ ret = ioctl(fd, GSMIOC_SETCONF, &cfg);
+ if (ret < 0) {
+ err("Set config ioctl failed [%s]\n", strerror(errno));
+ return -1;
+ }
+
+ data->dlc_poll_count = 0;
+ data->dlc_poll_src = g_timeout_add_full(G_PRIORITY_HIGH, 250,dlc_ready_check, h, 0);
+
+ return TCORE_RETURN_SUCCESS;
+}
+
+static void on_response_setupmux(TcorePending *p, int data_len,
+ const void *data, void *user_data)
+{
+ TcoreHal *hal = user_data;
+ struct custom_data *cdata = tcore_hal_ref_user_data(hal);
+
+ dbg("Entry");
+
+ if (cdata == NULL) {
+ err("Cannot retrieve Custom DATA from physical HAL");
+ return;
+ }
+
+ /*
+ * We don't need to exchange data on physical HAL, multiplexer
+ * channels will be used by core objects
+ */
+ if (cdata->watch_id > 0) {
+ g_source_remove(cdata->watch_id);
+ cdata->watch_id = 0;
+ }
+
+ /* Setup KERNEL CMUX */
+ if (setup_mux(hal) != TCORE_RETURN_SUCCESS)
+ err("Failed to initialize CMUX");
+
+ dbg("Exit");
+}
+
+static void on_response_poweron(TcorePending *p, int data_len,
+ const void *data, void *user_data)
+{
+ const TcoreATResponse *resp = data;
+ TcoreHal *hal = user_data;
+
+ if (resp->success == 0) {
+ dbg("RESPONSE NOK");
+ goto retry;
+ }
+
+ /* Disable UART for power saving */
+ prepare_and_send_at_request(hal, "AT+XPOW=0,0,0",
+ NULL, TCORE_AT_NO_RESULT, NULL, hal);
+
+ dbg("Proceed with mux initialization");
+
+ tcore_cmux_init(hal, 0, on_response_setupmux, hal);
+
+ return;
+
+retry:
+ if (tcore_hal_set_power(hal, TRUE) != TCORE_RETURN_SUCCESS)
+ err("Failed to power ON the modem");
+}
+
+static TReturn hal_power(TcoreHal *hal, gboolean flag)
+{
+ struct custom_data *cdata = tcore_hal_ref_user_data(hal);
+ Server *server;
+
+ dbg("Entry");
+
+ if (cdata == NULL) {
+ err("Cannot retrieve Custom DATA from physical HAL");
+ return TCORE_RETURN_FAILURE;
+ }
+
+ server = tcore_plugin_ref_server(cdata->plugin);
+ tcore_hal_set_power_state(hal, flag);
+
+ if (flag == TRUE) {
+ tcore_server_register_modem(server, cdata->plugin);
+
+ return prepare_and_send_at_request(hal,
+ "AT+CPAS",
+ "+CPAS", TCORE_AT_SINGLELINE,
+ on_response_poweron, hal);
+ } else {
+ remove_logical_hals(hal);
+
+ tcore_server_unregister_modem(server, cdata->plugin);
+
+ dbg("Phone Power Off success.");
+ }
+
+ return TCORE_RETURN_SUCCESS;
+}
+
+
+static TReturn hal_send(TcoreHal *hal, unsigned int data_len, void *data)
+{
+ size_t bytes_written;
+ struct custom_data *cdata;
+
+ if (tcore_hal_get_power_state(hal) == FALSE)
+ return TCORE_RETURN_FAILURE;
+
+ cdata = tcore_hal_ref_user_data(hal);
+ if (cdata == NULL) {
+ err("Cannot retrive custom data for hal %s",
+ tcore_hal_get_name(hal));
+ return TCORE_RETURN_FAILURE;
+ }
+
+ bytes_written = channel_write(cdata->channel, data, data_len);
+ if (bytes_written != data_len) {
+ err("channel_write failed");
+
+ return TCORE_RETURN_FAILURE;
+ }
+
+ dbg("channel_write success (channel=%p, len=%d)", cdata->channel, bytes_written);
+
+ return TCORE_RETURN_SUCCESS;
+}
+
+static const char *setup_rawip(GIOChannel *channel)
+{
+ struct gsm_netconfig netconfig;
+ int index;
+ char *interface;
+ char ifname[IFNAMSIZ];
+ int fd;
+
+ dbg("Entry");
+
+ memset(&netconfig, 0, sizeof(struct gsm_netconfig));
+
+ netconfig.adaption = 3;
+ netconfig.protocol = htons(ETH_P_IP);
+
+ fd = g_io_channel_unix_get_fd(channel);
+ if (fd < 0)
+ return NULL;
+
+ index = ioctl(fd, GSMIOC_ENABLE_NET, &netconfig);
+ if (index < 0) {
+ err("Set ioctl to create network failed [%s]\n", strerror(errno));
+ return NULL;
+ }
+
+ dbg("Net interface index: %d", index);
+
+ interface = if_indextoname(index, ifname);
+ if (interface == NULL) {
+ err("Interface index %d error %s", index, strerror(errno));
+ return NULL;
+ }
+
+ dbg("Interface name: %s", interface);
+
+ return interface;
+}
+
+static void on_response_setup_pdp(TcorePending *p, int data_len, const void *data, void *user_data)
+{
+ TcoreHal *hal = user_data;
+ const TcoreATResponse *resp = data;
+ struct custom_data *cdata = tcore_hal_ref_user_data(hal);
+ CoreObject *co = tcore_pending_ref_core_object(p);
+ TcoreHalSetupNetifCallback func = (TcoreHalSetupNetifCallback)cdata->cb;
+ const char *interface = NULL;
+
+ dbg("Entry");
+
+ if (resp->success == 0) {
+ dbg("Response NOk");
+ goto out;
+ }
+
+ dbg("Response Ok");
+
+ interface = setup_rawip(cdata->channel);
+ cdata->rawip_enabled = TRUE;
+
+out:
+ if (func != NULL)
+ func(co, interface, cdata->cb_data);
+}
+
+static gboolean disable_pdp_context(gpointer user_data)
+{
+ TcoreHal *hal = user_data;
+ struct custom_data *cdata = tcore_hal_ref_user_data(hal);
+ TcoreHalSetupNetifCallback func;
+ gint fd;
+
+ func = (TcoreHalSetupNetifCallback)cdata->cb;
+
+ fd = g_io_channel_unix_get_fd(cdata->channel);
+ if (ioctl(fd, GSMIOC_DISABLE_NET, NULL) < 0) {
+ err("Set ioctl to disable network interface failed [%s]",
+ strerror(errno));
+ goto out;
+ }
+
+ cdata->rawip_enabled = FALSE;
+
+out:
+ if (func != NULL)
+ func(cdata->co, NULL, cdata->cb_data);
+
+ return FALSE;
+}
+
+static TReturn hal_setup_netif(CoreObject *co, TcoreHalSetupNetifCallback func,
+ void *user_data, unsigned int cid,
+ gboolean enable)
+{
+ TcoreHal *hal = tcore_object_get_hal(co);
+ TcoreHal *data_hal;
+ char *cmd_str;
+ struct custom_data *cdata = tcore_hal_ref_user_data(hal);
+ TReturn ret;
+
+ dbg("Entry");
+
+ if (cdata == NULL) {
+ err("No custom data on PS HAL");
+ return TCORE_RETURN_FAILURE;
+ }
+
+ if (cid == 1)
+ data_hal = cdata->data_hal[0];
+ else if (cid == 2)
+ data_hal = cdata->data_hal[1];
+ else {
+ err("Invalid CID %d", cid);
+ return TCORE_RETURN_EINVAL;
+ }
+
+ if (data_hal == NULL) {
+ err("Fail to get channel data");
+ return TCORE_RETURN_FAILURE;
+ }
+
+ cdata = tcore_hal_ref_user_data(data_hal);
+ if (cdata == NULL) {
+ err("No custom data on DATA HAL");
+ return TCORE_RETURN_FAILURE;
+ }
+
+ if ((enable == FALSE) && (cdata->rawip_enabled == TRUE)) {
+ dbg("PDP context %d already disabled", cid);
+ return TCORE_RETURN_SUCCESS;
+ }
+
+ cdata->cb = (void *)func;
+ cdata->cb_data = user_data;
+
+ if (enable == FALSE) {
+ cdata->co = co;
+ g_idle_add(disable_pdp_context, data_hal);
+ return TCORE_RETURN_SUCCESS;
+ }
+
+ cmd_str = g_strdup_printf("AT+CGDATA=\"M-RAW_IP\",%d", cid);
+
+ ret = prepare_and_send_at_request(data_hal, cmd_str, NULL,
+ TCORE_AT_NO_RESULT,
+ on_response_setup_pdp, data_hal);
+
+ g_free(cmd_str);
+
+ return ret;
+}
+
+static gboolean on_load()
+{
+ dbg("I'm load!");
+
+ return TRUE;
+}
+
+static gboolean on_init(TcorePlugin *plugin)
+{
+ TcoreHal *hal;
+ struct custom_data *data;
+
+ if (!plugin)
+ return FALSE;
+
+ dbg("I'm init!");
+
+ /* Phonet init */
+ data = g_try_new0(struct custom_data, 1);
+ if (data == NULL) {
+ err("Memory failure");
+ return FALSE;
+ }
+
+ data->plugin = plugin;
+
+ data->channel = tty_open(DEVICE_IFX);
+ if (data->channel == NULL) {
+ err("Failed to open tty port - [%s]", strerror(errno));
+ g_free(data);
+ return FALSE;
+ }
+
+ dbg("tty port (%s) opened successfully", DEVICE_IFX);
+
+ /* HAL init */
+ hal = tcore_hal_new(plugin, "mfld-blackbay", &hops, TCORE_HAL_MODE_AT);
+ if (hal == NULL){
+ err("Failed to create HAL");
+ g_free(data);
+ return FALSE;
+ }
+
+ data->watch_id = register_gio_watch(data->channel,
+ on_recv_tty_message, hal);
+ if (data->watch_id == 0){
+ err("Failed to register gio watch ");
+ g_free(data);
+ tcore_hal_free(hal);
+ g_io_channel_unref(data->channel);
+ return FALSE;
+ }
+
+ tcore_hal_link_user_data(hal, data);
+
+ dbg("HAL is mfld-blackbay: channel = %p, watch_id=%d ", data->channel, data->watch_id);
+
+ if (tcore_hal_set_power(hal, TRUE) != TCORE_RETURN_SUCCESS) {
+ err("Failed to power ON the modem");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void on_unload(TcorePlugin *plugin)
+{
+ TcoreHal *hal;
+ struct custom_data *cdata;
+
+ if (!plugin)
+ return;
+
+ hal = tcore_plugin_ref_user_data(plugin);
+ if (hal == NULL)
+ return;
+
+ cdata = tcore_hal_ref_user_data(hal);
+ if (cdata == NULL)
+ return;
+
+ g_io_channel_unref(cdata->channel);
+ g_free(cdata);
+
+ tcore_hal_set_power(hal, FALSE);
+ tcore_hal_free(hal);
+
+ dbg("I'm unload");
+}
+
+struct tcore_plugin_define_desc plugin_define_desc =
+{
+ .name = "mfld-blackbay",
+ .priority = TCORE_PLUGIN_PRIORITY_HIGH,
+ .version = 1,
+ .load = on_load,
+ .init = on_init,
+ .unload = on_unload
+};