Initialize medfield blackbay modem interface plugin
authorGuillaume Zajac <guillaume.zajac@linux.intel.com>
Thu, 31 Jan 2013 16:04:58 +0000 (17:04 +0100)
committerPhilippe Nunes <philippe.nunes@linux.intel.com>
Thu, 14 Mar 2013 10:43:35 +0000 (11:43 +0100)
Change-Id: Idc7996c64c9df8e2422b808fce719584b8705139

AUTHORS [new file with mode: 0644]
CMakeLists.txt [new file with mode: 0644]
LICENSE [new file with mode: 0644]
include/util_mfld_blackbay.h [new file with mode: 0644]
packaging/tel-plugin-mfld-blackbay.spec [new file with mode: 0644]
src/desc_mfld_blackbay.c [new file with mode: 0644]
src/util_mfld_blackbay.c [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
new file mode 100644 (file)
index 0000000..b5abe82
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,3 @@
+Guillaume Zajac <guillaume.zajac@intel.com>
+Nicolas Bertrand <nicolas.bertrand@intel.com>
+Philippe Nunes <philippe.nunes@intel.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644 (file)
index 0000000..4e35ede
--- /dev/null
@@ -0,0 +1,45 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(mfld-blackbay-plugin C)
+
+### Global setting ###
+SET(PREFIX ${CMAKE_INSTALL_PREFIX})
+SET(EXEC_PREFIX "\${prefix}")
+SET(LIBDIR "\${prefix}/lib")
+SET(INCLUDEDIR "\${prefix}/include")
+SET(PKGCONFIGDIR "${PREFIX}/lib/pkgconfig" CACHE PATH PKGCONFIGDIR)
+SET(CMAKE_INSTALL_PREFIX "${PREFIX}")
+
+# Set required packages
+INCLUDE(FindPkgConfig)
+pkg_check_modules(pkgs REQUIRED glib-2.0 tcore dlog)
+
+FOREACH(flag ${pkgs_CFLAGS})
+       SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include/)
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -Werror -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Wdeclaration-after-statement -Wmissing-declarations -Wredundant-decls -Wcast-align")
+
+ADD_DEFINITIONS("-DFEATURE_DLOG_DEBUG")
+ADD_DEFINITIONS("-DTCORE_LOG_TAG=\"MFLD-BLACKBAY\"")
+
+MESSAGE(${CMAKE_C_FLAGS})
+MESSAGE(${CMAKE_EXE_LINKER_FLAGS})
+
+SET(SRCS
+       src/desc_mfld_blackbay.c
+       src/util_mfld_blackbay.c
+)
+
+MESSAGE( "SOURCES: ${SRCS}" )
+
+# library build
+ADD_LIBRARY(mfld-blackbay-plugin SHARED ${SRCS})
+TARGET_LINK_LIBRARIES(mfld-blackbay-plugin ${pkgs_LDFLAGS})
+SET_TARGET_PROPERTIES(mfld-blackbay-plugin PROPERTIES PREFIX "" OUTPUT_NAME mfld-blackbay-plugin)
+
+
+# install
+INSTALL(TARGETS mfld-blackbay-plugin
+               LIBRARY DESTINATION lib/telephony/plugins)
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..d38fbf0
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,204 @@
+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
diff --git a/include/util_mfld_blackbay.h b/include/util_mfld_blackbay.h
new file mode 100644 (file)
index 0000000..a9dd226
--- /dev/null
@@ -0,0 +1,29 @@
+/*\r
+*\r
+*  tel-plugin-mfld-blackbay\r
+*\r
+* Copyright (C) 2013  Intel Corporation. All rights reserved.\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
+*/\r
+\r
+#ifndef __UTIL_MFLD_BLACKBAY_H__\r
+#define __UTIL_MFLD_BLACKBAY_H__\r
+\r
+size_t channel_read(GIOChannel *channel, void* buf, size_t nbytes);\r
+size_t channel_write(GIOChannel *channel, void* buf, size_t nbytes);\r
+\r
+void util_hex_dump(char *pad, int size, const void *data);\r
+\r
+#endif\r
diff --git a/packaging/tel-plugin-mfld-blackbay.spec b/packaging/tel-plugin-mfld-blackbay.spec
new file mode 100644 (file)
index 0000000..bcfda83
--- /dev/null
@@ -0,0 +1,38 @@
+Name:       tel-plugin-mfld-blackbay
+Summary:    Medfield Blackbay plateform telephony plugin
+Version: 0.0.2
+Release:    1
+Group:      System/Libraries
+License:    Apache
+Source0:    tel-plugin-mfld-blackbay-%{version}.tar.gz
+Requires(post): /sbin/ldconfig
+Requires(postun): /sbin/ldconfig
+BuildRequires:  cmake
+BuildRequires:  pkgconfig(glib-2.0)
+BuildRequires:  pkgconfig(dlog)
+BuildRequires:  pkgconfig(tcore)
+
+
+%description
+Medfield Blackbay platform telephony plugin
+
+%prep
+%setup -q
+
+%build
+cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix}
+make %{?jobs:-j%jobs}
+
+%post
+/sbin/ldconfig
+
+%postun -p /sbin/ldconfig
+
+%install
+rm -rf %{buildroot}
+%make_install
+
+%files
+%defattr(-,root,root,-)
+#%doc COPYING
+%{_libdir}/telephony/plugins/*
diff --git a/src/desc_mfld_blackbay.c b/src/desc_mfld_blackbay.c
new file mode 100644 (file)
index 0000000..bae498d
--- /dev/null
@@ -0,0 +1,832 @@
+/*
+*
+*  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
+};
diff --git a/src/util_mfld_blackbay.c b/src/util_mfld_blackbay.c
new file mode 100644 (file)
index 0000000..b05273f
--- /dev/null
@@ -0,0 +1,153 @@
+/*\r
+*\r
+*  tel-plugin-mfld-blackbay\r
+*\r
+* Copyright (C) 2013  Intel Corporation. All rights reserved.\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
+*/\r
+\r
+#include <string.h>\r
+#include <stdlib.h>\r
+#include <stdio.h>\r
+#include <errno.h>\r
+#include <sys/time.h>\r
+#include <sys/mman.h>\r
+#include <unistd.h>\r
+#include <fcntl.h>\r
+\r
+#include <glib.h>\r
+\r
+#include <log.h>\r
+#include <util_mfld_blackbay.h>\r
+\r
+#define MAX_READ_ATTEMPTS      4\r
+#define MAX_WRITE_ATTEMPTS     10\r
+\r
+/* Read data from a GIOChannel */\r
+size_t channel_read(GIOChannel *channel, void* buf, size_t nbytes)\r
+{\r
+       GIOStatus status;\r
+       size_t rbytes;\r
+       size_t toread = nbytes;\r
+       size_t bytes_read = 0;\r
+       unsigned int read_count = 0;\r
+\r
+       do {\r
+               rbytes = 0;\r
+\r
+               status = g_io_channel_read_chars(channel, buf, toread, &rbytes, NULL);\r
+\r
+               read_count++;\r
+\r
+               err("g_io_channel_read_chars.. status[%d] rbytes =%d read_count = %d", status, rbytes, read_count);\r
+\r
+               bytes_read += rbytes;\r
+               toread -= rbytes;\r
+\r
+               if (rbytes > 0)\r
+                       buf+=rbytes;\r
+\r
+               if (toread == 0)\r
+                       break;\r
+\r
+       } while (status == G_IO_STATUS_NORMAL && rbytes > 0 && read_count < MAX_READ_ATTEMPTS);\r
+\r
+       return bytes_read;\r
+}\r
+\r
+static void __selectsleep(int sec,int msec)\r
+{\r
+       struct timeval tv;\r
+\r
+       tv.tv_sec=sec;\r
+       tv.tv_usec=msec;\r
+\r
+       select(0,NULL,NULL,NULL,&tv);\r
+\r
+       return;\r
+}\r
+\r
+/* Write data to a GIOChannel */\r
+size_t channel_write(GIOChannel *channel, void* buf, size_t nbytes)\r
+{\r
+       GIOStatus status;\r
+       size_t tbytes = 0;\r
+       size_t bytes_written = 0;\r
+       unsigned int retry = 0;\r
+\r
+       do {\r
+               status = g_io_channel_write_chars(channel, (const gchar*)buf, nbytes - bytes_written, &tbytes, NULL);\r
+\r
+               if (status == G_IO_STATUS_AGAIN) {\r
+                       err("write failed. Retry.. status[%d] Nb attempt[%d]", status, retry);\r
+\r
+                       __selectsleep(0,50);\r
+\r
+                       if (retry == MAX_WRITE_ATTEMPTS)\r
+                               return 0;\r
+\r
+                       retry = retry + 1;\r
+\r
+                       continue;\r
+               }\r
+\r
+               if (status != G_IO_STATUS_NORMAL) {\r
+                       if (bytes_written != nbytes)\r
+                               err("write failed. status[%d] with errno[%d]", status, errno);\r
+\r
+                       return bytes_written;\r
+               }\r
+\r
+               bytes_written += tbytes;\r
+               buf += tbytes;\r
+\r
+       } while (bytes_written < nbytes);\r
+\r
+       return bytes_written;\r
+}\r
+\r
+void util_hex_dump(char *pad, int size, const void *data)\r
+{\r
+       char buf[255] = {0, };\r
+       char hex[4] = {0, };\r
+       int i;\r
+       unsigned char *p;\r
+\r
+       if (size <= 0) {\r
+               msg("%sno data", pad);\r
+               return;\r
+       }\r
+\r
+       p = (unsigned char *) data;\r
+\r
+       snprintf(buf, 255, "%s%04X: ", pad, 0);\r
+       for (i = 0; i < size; i++) {\r
+               snprintf(hex, 4, "%02X ", p[i]);\r
+               strcat(buf, hex);\r
+\r
+               if ((i + 1) % 8 == 0) {\r
+                       if ((i + 1) % 16 == 0) {\r
+                               msg("%s", buf);\r
+                               memset(buf, 0, 255);\r
+                               snprintf(buf, 255, "%s%04X: ", pad, i + 1);\r
+                       } else {\r
+                               strcat(buf, "  ");\r
+                       }\r
+               }\r
+       }\r
+\r
+       msg("%s", buf);\r
+}\r
+\r