--- /dev/null
+/**\r
+ * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Contact: Arijit Sen <arijit.sen@samsung.com>\r
+ *\r
+ * PROPRIETARY/CONFIDENTIAL\r
+ *\r
+ * This software is the confidential and proprietary information of SAMSUNG ELECTRONICS ("Confidential Information").\r
+ * You shall not disclose such Confidential Information and shall\r
+ * use it only in accordance with the terms of the license agreement you entered into with SAMSUNG ELECTRONICS.\r
+ * SAMSUNG make no representations or warranties about the suitability\r
+ * of the software, either express or implied, including but not\r
+ * limited to the implied warranties of merchantability, fitness for a particular purpose, or non-infringement.\r
+ * SAMSUNG shall not be liable for any damages suffered by licensee as\r
+ * a result of using, modifying or distributing this software or its derivatives.\r
+ */\r
+\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <unistd.h>\r
+#include <stdlib.h>\r
+\r
+#include <glib.h>\r
+\r
+#include "tcore.h"\r
+\r
+#include "hal.h"\r
+#include "plugin.h"\r
+#include "user_request.h"\r
+#include "server.h"\r
+#include "mux.h"\r
+#include "core_object.h"\r
+\r
+/*For enabling MUX we need to set g_cmux_enable*/\r
+int g_cmux_enable = 1;\r
+\r
+/* Maximum Core objects per Logical HAL (indirectly per Channel) */\r
+#define CMUX_MAX_CORE_OBJECTS 3\r
+\r
+#define MAX_CMUX_BUFFER_SIZE 1024\r
+#define MAX_CHANNEL_SUPPORTED 8\r
+\r
+\r
+#define SABM 0x2F \r
+#define UA 0x63 \r
+#define DM 0x0F \r
+#define DISC 0x43 \r
+#define UIH 0xEF \r
+#define UI 0x03 \r
+\r
+\r
+\r
+/* MUX CONTROL COMMANDS \r
+ * We are supporting only MSC command for phase 1\r
+ */\r
+#define MSC 0xE3 //Modem Status Command\r
+#define CLD 0xC3 //Multiplexer close down\r
+\r
+/* \r
+#define PN //parameter negotiation\r
+#define PSC //Power Saving Control\r
+#define TEST //Test Command\r
+#define NSC //Non Supported Command Response\r
+#define RPN //Remote Port Negotiation Command\r
+#define RLS //Remote Line Status Command\r
+#define SNC //Service Negotiation Command */\r
+\r
+\r
+\r
+/* CMUX Channels [0-7] -\r
+ * Channel 0 - Control Channel for CMUX\r
+ * Channel 1 - CALL\r
+ * Channel 2 - SIM \r
+ * Channel 3 - SAT\r
+ * Channel 4 - SMS\r
+ * Channel 5 - SS\r
+ * Channel 6 - NETWORK\r
+ * Channel 7 - MODEM & PS\r
+ */\r
+typedef enum CMUX_Channels {\r
+ CMUX_CHANNEL_0,\r
+ CMUX_CHANNEL_1,\r
+ CMUX_CHANNEL_2,\r
+ CMUX_CHANNEL_3,\r
+ CMUX_CHANNEL_4,\r
+ CMUX_CHANNEL_5,\r
+ CMUX_CHANNEL_6,\r
+ CMUX_CHANNEL_7\r
+} CMUX_Channels;\r
+\r
+typedef enum MuxChannelState {\r
+ MUX_CHANNEL_CLOSED,\r
+ MUX_CHANNEL_SABM_SEND_WAITING_FOR_UA,\r
+ MUX_CHANNEL_ESTABLISHED,\r
+ MUX_CHANNEL_UA_NOT_RECEIVED_RETRY,\r
+ MUX_CHANNEL_DM_RECEIVED_CLOSING,\r
+ MUX_CHANNEL_DM_SEND,\r
+ MUX_CHANNEL_DISC_RECEIVED_CLOSING,\r
+ MUX_CHANNEL_DISC_SEND_WAITING_FOR_UA,\r
+ MUX_CHANNEL_UA_SEND_CLOSING,\r
+ MUX_CHANNEL_UA_RECEIVED,\r
+ MUX_CHANNEL_UA_SENDING,\r
+ \r
+} MuxChannelState;\r
+\r
+typedef enum MuxState {\r
+ MUX_NOT_INITIALIZED,\r
+ MUX_INITIALIZED,\r
+ MUX_CLOSED\r
+} MuxState;\r
+\r
+#define FIND_LENGTH(buf, hlen, Tlen) do{ \\r
+ if (*buf & 0x01) { \\r
+ Tlen = *buf++ >>1; \\r
+ hlen=6; \\r
+ } \\r
+ else { \\r
+ Tlen = *(buf + 0x01) << 7; \\r
+ Tlen = Tlen | (*buf & 0x7E) >> 1; \\r
+ hlen = 7; \\r
+ } \\r
+ } while(0)\r
+\r
+/*================= CRC TABLE=========================*/\r
+const unsigned char crctable[256] = { //reversed, 8-bit, poly=0x07\r
+ 0x00, 0x91, 0xE3, 0x72, 0x07, 0x96, 0xE4, 0x75, 0x0E, 0x9F, 0xED, 0x7C, 0x09, 0x98, 0xEA, 0x7B,\r
+ 0x1C, 0x8D, 0xFF, 0x6E, 0x1B, 0x8A, 0xF8, 0x69, 0x12, 0x83, 0xF1, 0x60, 0x15, 0x84, 0xF6, 0x67,\r
+ 0x38, 0xA9, 0xDB, 0x4A, 0x3F, 0xAE, 0xDC, 0x4D, 0x36, 0xA7, 0xD5, 0x44, 0x31, 0xA0, 0xD2, 0x43,\r
+ 0x24, 0xB5, 0xC7, 0x56, 0x23, 0xB2, 0xC0, 0x51, 0x2A, 0xBB, 0xC9, 0x58, 0x2D, 0xBC, 0xCE, 0x5F,\r
+ 0x70, 0xE1, 0x93, 0x02, 0x77, 0xE6, 0x94, 0x05, 0x7E, 0xEF, 0x9D, 0x0C, 0x79, 0xE8, 0x9A, 0x0B,\r
+ 0x6C, 0xFD, 0x8F, 0x1E, 0x6B, 0xFA, 0x88, 0x19, 0x62, 0xF3, 0x81, 0x10, 0x65, 0xF4, 0x86, 0x17,\r
+ 0x48, 0xD9, 0xAB, 0x3A, 0x4F, 0xDE, 0xAC, 0x3D, 0x46, 0xD7, 0xA5, 0x34, 0x41, 0xD0, 0xA2, 0x33,\r
+ 0x54, 0xC5, 0xB7, 0x26, 0x53, 0xC2, 0xB0, 0x21, 0x5A, 0xCB, 0xB9, 0x28, 0x5D, 0xCC, 0xBE, 0x2F,\r
+ 0xE0, 0x71, 0x03, 0x92, 0xE7, 0x76, 0x04, 0x95, 0xEE, 0x7F, 0x0D, 0x9C, 0xE9, 0x78, 0x0A, 0x9B,\r
+ 0xFC, 0x6D, 0x1F, 0x8E, 0xFB, 0x6A, 0x18, 0x89, 0xF2, 0x63, 0x11, 0x80, 0xF5, 0x64, 0x16, 0x87,\r
+ 0xD8, 0x49, 0x3B, 0xAA, 0xDF, 0x4E, 0x3C, 0xAD, 0xD6, 0x47, 0x35, 0xA4, 0xD1, 0x40, 0x32, 0xA3,\r
+ 0xC4, 0x55, 0x27, 0xB6, 0xC3, 0x52, 0x20, 0xB1, 0xCA, 0x5B, 0x29, 0xB8, 0xCD, 0x5C, 0x2E, 0xBF,\r
+ 0x90, 0x01, 0x73, 0xE2, 0x97, 0x06, 0x74, 0xE5, 0x9E, 0x0F, 0x7D, 0xEC, 0x99, 0x08, 0x7A, 0xEB,\r
+ 0x8C, 0x1D, 0x6F, 0xFE, 0x8B, 0x1A, 0x68, 0xF9, 0x82, 0x13, 0x61, 0xF0, 0x85, 0x14, 0x66, 0xF7,\r
+ 0xA8, 0x39, 0x4B, 0xDA, 0xAF, 0x3E, 0x4C, 0xDD, 0xA6, 0x37, 0x45, 0xD4, 0xA1, 0x30, 0x42, 0xD3,\r
+ 0xB4, 0x25, 0x57, 0xC6, 0xB3, 0x22, 0x50, 0xC1, 0xBA, 0x2B, 0x59, 0xC8, 0xBD, 0x2C, 0x5E, 0xCF\r
+};\r
+/*================= CRC TABLE=========================*/\r
+\r
+typedef struct cmux_channel { \r
+ GSList *co; \r
+ TcoreHal *hal;\r
+ \r
+ MuxChannelState state; \r
+ CMUX_Channels ChannelId;\r
+ int FrameType;\r
+ unsigned char ExtBit;\r
+ unsigned char CRBit;\r
+ unsigned char pollFinalBit;\r
+\r
+#if 0\r
+ int Len;\r
+\r
+ /*Information field*/\r
+ unsigned char *InfoField;\r
+\r
+#endif\r
+\r
+} CHANNEL;\r
+\r
+typedef gboolean (*mux_cb_func)(CHANNEL *channel_ptr);\r
+\r
+typedef struct cmux {\r
+ MuxState state;\r
+\r
+ CHANNEL *channelInfo[MAX_CHANNEL_SUPPORTED];\r
+ int isWaiting;\r
+ int pMsgLen;\r
+ int curMBufLen;\r
+\r
+ /* Plugin */\r
+ TcorePlugin *p;\r
+ \r
+ /* Physical HAL */\r
+ TcoreHal *phy_hal;\r
+\r
+ /* Modem Core Object */\r
+ CoreObject *modem_co;\r
+\r
+ mux_cb_func cb_func;\r
+\r
+ /* Resolve Crash issue*/\r
+ int Len;\r
+ /*Information field*/\r
+ unsigned char *InfoField;\r
+\r
+ unsigned char *muxTempBuffer;\r
+ unsigned char *muxMainBuffer;\r
+} MUX;\r
+\r
+/* Global pointer MUX Object pointer */\r
+MUX *MuxObjPtr = NULL;\r
+\r
+/* Global buffers for CMUX processing */\r
+//unsigned char Mux_buffer[MAX_CMUX_BUFFER_SIZE];\r
+//unsigned char muxTempBuffer[MAX_CMUX_BUFFER_SIZE];\r
+//unsigned char muxMainBuffer[MAX_CMUX_BUFFER_SIZE];\r
+\r
+/* CMUX mode of operation */\r
+int MUX_MODE = 0; /* BASIC mode */\r
+\r
+struct cmux_channel_object {\r
+ char *channel_id_name;\r
+ char *Cobject_name[CMUX_MAX_CORE_OBJECTS];\r
+};\r
+\r
+/* Core Object names need to be verified, define a MACRO globally */\r
+struct cmux_channel_object cmux_channel_Cobject[] = {\r
+ {"channel_0", {"control", NULL, NULL}}, \r
+ {"channel_1", {"call", NULL, NULL}},\r
+ {"channel_2", {"sim", NULL, NULL}},\r
+ {"channel_3", {"sat", NULL, NULL}},\r
+ {"channel_4", {"umts_sms", NULL, NULL}},\r
+ {"channel_5", {"ss", NULL, NULL}},\r
+ {"channel_6", {"umts_network", NULL, NULL}},\r
+ {"channel_7", {"modem", "umts_ps", NULL}},\r
+};\r
+\r
+/* All the local functions declared below */\r
+static unsigned char calc_crc(unsigned char *header , int length);\r
+static int rcv_crc_check(unsigned char *data , unsigned char len,unsigned char RcvFCS);\r
+\r
+MUX *tcore_cmux_new(void);\r
+static void tcore_cmux_free();\r
+\r
+void tcore_cmux_link_core_object_hal(CMUX_Channels channel_id, TcorePlugin *plugin);\r
+static gboolean tcore_cmux_recv_mux_data(CHANNEL* channel_ptr);\r
+static void tcore_cmux_process_rcv_frame( unsigned char *data, int len);\r
+static void tcore_cmux_process_channel_data(CHANNEL *ChannelInfoPtr);\r
+static void tcore_cmux_control_channel_handle();\r
+static void tcore_cmux_flush_channel_data();\r
+\r
+void tcore_cmux_channel_init(CMUX_Channels channel_id);\r
+int tcore_cmux_close_channel(int channelID);\r
+ \r
+static unsigned char *tcore_encode_cmux_frame(unsigned char *data,\r
+ int length,\r
+ int channel_id,\r
+ int FrameType,\r
+ unsigned char EABit,\r
+ unsigned char CRBit,\r
+ unsigned char PFBit,\r
+ int *out_data_len);\r
+\r
+static TReturn tcore_cmux_hal_power(TcoreHal *h, gboolean flag)\r
+{\r
+ TcorePlugin *p = 0;\r
+ struct custom_data *user_data = 0;\r
+// gboolean ret = 0;\r
+ dbg("Entry");\r
+\r
+ p = tcore_hal_ref_plugin(h);\r
+ if (!p) {\r
+ err("Plugin is undefined");\r
+ return TCORE_RETURN_FAILURE;\r
+ }\r
+\r
+ user_data = tcore_hal_ref_user_data(h);\r
+ if (!user_data) {\r
+ err("User data is undefined");\r
+ return TCORE_RETURN_FAILURE;\r
+ }\r
+\r
+ tcore_hal_set_power_state(h, TRUE);\r
+\r
+ dbg("Exit");\r
+ return TCORE_RETURN_SUCCESS;\r
+}\r
+\r
+static TReturn tcore_cmux_hal_send(TcoreHal *h, unsigned int data_len, void *data)\r
+{\r
+ unsigned char *send_data= NULL;\r
+ char *channel_name = NULL;\r
+ int channel_id = MAX_CHANNEL_SUPPORTED;\r
+ int len = 0;\r
+ int i = 0;\r
+\r
+ int ret;\r
+ dbg("Entry");\r
+ dbg("data: %s", (char *)data);\r
+\r
+ /* Check if Logical HAL is Powered ON */\r
+ if (tcore_hal_get_power_state(h) == FALSE) {\r
+ err("HAL is not Powered UP");\r
+ return TCORE_RETURN_FAILURE;\r
+ }\r
+\r
+ channel_name = tcore_hal_get_name(h);\r
+ dbg("HAL name: %s", channel_name)\r
+ if(channel_name) {\r
+ while(i < MAX_CHANNEL_SUPPORTED) {\r
+ dbg("HAL name of Channels: %s", cmux_channel_Cobject[i].channel_id_name);\r
+ if (0 == strcmp((char *) cmux_channel_Cobject[i].channel_id_name, (char *)channel_name)) {\r
+ channel_id = i;\r
+ dbg("Found Channel ID: %d", channel_id);\r
+\r
+ /* Free memory */\r
+ free(channel_name);\r
+ break;\r
+ }\r
+ i++;\r
+ }\r
+ }\r
+ else {\r
+ err("No name defined for HAL");\r
+ return TCORE_RETURN_FAILURE;\r
+ }\r
+\r
+ if(channel_id > MAX_CHANNEL_SUPPORTED) {\r
+ err("Failed to find Channel ID");\r
+ return TCORE_RETURN_FAILURE;\r
+ }\r
+ \r
+ /* Muxing operation and Frame creation */\r
+ /* Encoding frame */\r
+ send_data = tcore_encode_cmux_frame(data, data_len, channel_id, UIH, 1, 1, 0, &len);\r
+ if(NULL == send_data) {\r
+ err("Failed to encode");\r
+ return TCORE_RETURN_FAILURE;\r
+ }\r
+ \r
+ /* Directly send to Physical HAL */\r
+ ret = tcore_hal_send_data(MuxObjPtr->phy_hal, len, send_data);\r
+ \r
+ dbg("Exit");\r
+ return TCORE_RETURN_SUCCESS;\r
+}\r
+\r
+/* CMUX supported HAL (Logical HAL) operations */\r
+static struct tcore_hal_operations mux_hops =\r
+{\r
+ .power = tcore_cmux_hal_power,\r
+ .send = tcore_cmux_hal_send,\r
+};\r
+\r
+static gboolean tcore_cmux_recv_mux_data(CHANNEL *channel_ptr)\r
+{\r
+ TcoreHal *hal = NULL;\r
+ dbg("Entry");\r
+\r
+ /* Dereferencing HAL from Channel Pointer */\r
+ hal = channel_ptr->hal;\r
+ \r
+ dbg("Dispatching to logical HAL - hal: %x", hal);\r
+ tcore_hal_dispatch_response_data(hal, 0, MuxObjPtr->Len, MuxObjPtr->InfoField);\r
+\r
+ dbg("Exit");\r
+ return TRUE;\r
+}\r
+\r
+void tcore_cmux_link_core_object_hal(CMUX_Channels channel_id, TcorePlugin *plugin)\r
+{\r
+ TcoreHal *hal = NULL;\r
+ CoreObject *co = NULL;\r
+ int index;\r
+ dbg("Entry");\r
+\r
+ if(CMUX_CHANNEL_0 != channel_id) {\r
+ dbg("Normal channel [%d]", channel_id);\r
+ \r
+ /* Creating Logical HAL for Core Object - Mode - 'AT mode' */\r
+ hal = tcore_hal_new(plugin, cmux_channel_Cobject[channel_id].channel_id_name, &mux_hops, TCORE_HAL_MODE_AT);\r
+ dbg("hal: %p", hal);\r
+ \r
+ /* Update Logical HAL of CMUX Channel */\r
+ MuxObjPtr->channelInfo[channel_id]->hal = hal;\r
+ \r
+ index = 0;\r
+ while (NULL != cmux_channel_Cobject[channel_id].Cobject_name[index]) {\r
+ /* Retrieving Core Object */\r
+ dbg("Core Object: '%s'", cmux_channel_Cobject[channel_id].Cobject_name[index]);\r
+ co = tcore_plugin_ref_core_object(plugin, cmux_channel_Cobject[channel_id].Cobject_name[index]);\r
+ dbg("co: %p", co);\r
+\r
+ if (0 == strcmp((const char *)cmux_channel_Cobject[channel_id].Cobject_name[index], "modem")) {\r
+ MuxObjPtr->modem_co = co;\r
+ dbg("'modem' Core object reference is stored");\r
+ }\r
+\r
+ /* Set Logical HAL to Core objects */\r
+ tcore_object_set_hal(co, hal);\r
+\r
+ /* Update Core Object list of CMUX Channel */\r
+ MuxObjPtr->channelInfo[channel_id]->co = g_slist_append(MuxObjPtr->channelInfo[channel_id]->co, co);\r
+\r
+ index++;\r
+ };\r
+ }\r
+ else {\r
+ /* Control Channel */\r
+ dbg("Control channel");\r
+ \r
+ /* Creating Logical HAL for Core Object - Mode - 'AT mode' */\r
+ hal = tcore_hal_new(plugin, cmux_channel_Cobject[channel_id].channel_id_name, &mux_hops, TCORE_HAL_MODE_AT);\r
+ dbg("hal: %p", hal);\r
+ \r
+ /* Update Logical HAL of CMUX Channel */\r
+ MuxObjPtr->channelInfo[channel_id]->hal = hal;\r
+ }\r
+\r
+ /* Set Logical HAL Power State to TRUE */\r
+ tcore_hal_set_power_state(hal, TRUE);\r
+ dbg("HAL Power is SET");\r
+ \r
+ dbg("Exit");\r
+ return;\r
+}\r
+\r
+/************************************************************\r
+\r
+Here we initialize the MUX\r
+\r
+************************************************************/\r
+MUX *tcore_cmux_new(void)\r
+{\r
+ MUX *p = NULL;\r
+ int i = 0;\r
+ dbg("Entry");\r
+ \r
+ p = (MUX*)calloc(sizeof(MUX), 1);\r
+ if (!p) {\r
+ err("Failed to allocate memory");\r
+ return NULL;\r
+ }\r
+\r
+ p->InfoField = (unsigned char *)calloc(MAX_CMUX_BUFFER_SIZE, 1); \r
+ if (!p->InfoField) {\r
+ err("Failed to allocate memory for info field");\r
+ goto ERROR;\r
+ }\r
+ \r
+ p->muxTempBuffer = (unsigned char *)calloc(MAX_CMUX_BUFFER_SIZE, 1); \r
+ if (!p->InfoField) {\r
+ err("Failed to allocate memory for info field");\r
+ goto ERROR;\r
+ }\r
+ \r
+ p->muxMainBuffer = (unsigned char *)calloc(MAX_CMUX_BUFFER_SIZE, 1);\r
+ if (!p->InfoField) {\r
+ err("Failedto allocate memory for info field");\r
+ goto ERROR;\r
+ }\r
+ \r
+ p->state = MUX_NOT_INITIALIZED;\r
+\r
+ for(i = 0 ; i < MAX_CHANNEL_SUPPORTED ; i++) {\r
+ p->channelInfo[i] = (CHANNEL*)calloc(sizeof(CHANNEL) , 1);\r
+ /* Check for Memory allocation failure */\r
+ if(!p->channelInfo[i]) {\r
+ err("Failed to allocate memory for info field");\r
+ goto ERROR;\r
+ }\r
+ }\r
+\r
+ dbg("Exit");\r
+ return p;\r
+\r
+ERROR:\r
+ /* Free allocated memory */\r
+ if(p) {\r
+ if(p->InfoField) {\r
+ free(p->InfoField);\r
+ }\r
+ \r
+ if(p->muxTempBuffer) {\r
+ free(p->muxTempBuffer);\r
+ }\r
+ \r
+ if(p->muxMainBuffer) {\r
+ free(p->muxMainBuffer);\r
+ }\r
+\r
+ for(i = 0; i < MAX_CHANNEL_SUPPORTED ; i++) {\r
+ if(p->channelInfo[i]) {\r
+ free(p->channelInfo[i]);\r
+ }\r
+ }\r
+\r
+ free(p);\r
+ }\r
+\r
+ err("Exit");\r
+ return NULL;\r
+}\r
+\r
+\r
+\r
+/************************************************************\r
+This function is used while encoding .\r
+There is seperate function for decoding CRC\r
+Frame Checking Sequence Field\r
+************************************************************/\r
+static unsigned char calc_crc (unsigned char *header , int length)\r
+{\r
+ unsigned char FCS=0xFF; /*Init*/\r
+ \r
+ /*len is the number of bytes in the message, p points to message*/\r
+ while (length--) {\r
+ FCS = crctable[FCS ^ *header++];\r
+ }\r
+ \r
+ /*Ones complement*/\r
+ return (0xFF-FCS);\r
+}\r
+\r
+/************************************************************\r
+Function name : tcore_encode_cmux_frame\r
+\r
+\r
+************************************************************/\r
+static unsigned char *tcore_encode_cmux_frame(unsigned char *data,\r
+ int length,\r
+ int channel_id,\r
+ int FrameType,\r
+ unsigned char EABit,\r
+ unsigned char CRBit,\r
+ unsigned char PFBit,\r
+ int *out_data_len)\r
+{\r
+ int tLength=0, frameLen=0;\r
+ int crc_len =0;\r
+ dbg("Entry");\r
+\r
+\r
+ /* Flush channel data */\r
+ tcore_cmux_flush_channel_data();\r
+\r
+ if(length > MAX_CMUX_BUFFER_SIZE ){\r
+ err("Length - %d exceeds the limit", length);\r
+ return NULL;\r
+ }\r
+ //flag Octet\r
+ MuxObjPtr->InfoField[tLength++] = (char)0xF9;\r
+\r
+ if(0x00 == MUX_MODE) { /* BASIC */\r
+ /* EA: Extension Bit\r
+ * C/R: Command Response\r
+ */\r
+ MuxObjPtr->InfoField[tLength] = MuxObjPtr->InfoField[tLength] | ((EABit & 0x01) | ((CRBit << 1) & 0x02)); \r
+\r
+ /* DLCI: Data Link Connection Identifier */\r
+ /* Check if the channel is within range */\r
+ if(channel_id < MAX_CHANNEL_SUPPORTED && channel_id >=0) {\r
+ dbg("Channel ID: %d", channel_id);\r
+ MuxObjPtr->InfoField[tLength] = MuxObjPtr->InfoField[tLength]|((unsigned char) channel_id << 2);\r
+ }\r
+ else {\r
+ err("Channel is out of range[0-8]");\r
+ return NULL;\r
+ }\r
+ tLength++;\r
+\r
+ /* Control Field\r
+ * The content of the control field defines the type of frame.\r
+ * ***************************************************************\r
+ * Frame Type 0 1 2 3 4 5 6 7\r
+ * SABM (Set Asynchronous Balanced Mode) 1 1 1 1 P/F 1 0 0\r
+ * UA (Unnumbered Acknowledgement) 1 1 0 0 P/F 1 1 0\r
+ * DM (Disconnected Mode) 1 1 1 1 P/F 0 0 0\r
+ * DISC (Disconnect) 1 1 0 0 P/F 0 1 0\r
+ * UIH (Unnumbered Information with Header check) 1 1 1 1 P/F 1 1 1\r
+ ****************************************************************/\r
+ if(PFBit) {\r
+ MuxObjPtr->InfoField[tLength++] = FrameType |0x10;\r
+ }\r
+ else {\r
+ MuxObjPtr->InfoField[tLength++] = FrameType;\r
+ }\r
+\r
+ /* 5.2.1.5 Length Indicator */\r
+ if (length < 128) {\r
+ //length =(char)length <<1|0x01;\r
+ MuxObjPtr->InfoField[tLength++] =(char)length <<1|0x01;\r
+ \r
+ /* CRC calculatable length */\r
+ crc_len = 3;\r
+ }\r
+ else {\r
+ MuxObjPtr->InfoField[tLength++] = (char)(length << 1); //Need to change\r
+ MuxObjPtr->InfoField[tLength++] = (char)(length >> 7); //Need to change \r
+\r
+ /* CRC calculatable length */\r
+ crc_len = 4;\r
+ }\r
+\r
+ /* We need to divide the frames into maximum frame length supported by IMC.\r
+ * If IMC supports length according to 27.010 , we can send max of 16,384 bytes.\r
+ * Need to discuss with IMC.\r
+ */\r
+\r
+ /* 5.2.1.4 Information Field*/\r
+ if(length >0) {\r
+ dbg("MEMCPY :length= %d", length);\r
+ memcpy((MuxObjPtr->InfoField + tLength),data, length);\r
+ dbg("MEMCPY :DONE");\r
+ tLength += length;\r
+ }\r
+ else {\r
+ dbg("info field length is zero");\r
+ }\r
+\r
+ /*5.2.1.6 Frame Checking Sequence Field (FCS)*/\r
+ MuxObjPtr->InfoField[tLength++] = calc_crc(MuxObjPtr->InfoField+1, crc_len);\r
+\r
+ /*Flag Octet*/\r
+ MuxObjPtr->InfoField[tLength++] = 0xF9;\r
+\r
+ frameLen = tLength;\r
+ }\r
+ else if (0x01 == MUX_MODE) { /* TBD MUX_MODE_ADVANCE */\r
+ dbg("For PHASE 2 !!");\r
+ }\r
+\r
+ *out_data_len = frameLen;\r
+ dbg("*out_data_len: %d", *out_data_len);\r
+\r
+ dbg("Exit frameLen: %d", frameLen);\r
+ return MuxObjPtr->InfoField;\r
+}\r
+\r
+\r
+static int rcv_crc_check(unsigned char *data , unsigned char len,unsigned char RcvFCS)\r
+{\r
+ unsigned char FCS = 0xFF;\r
+\r
+ /* 'len' is the number of bytes in the message, 'p' points to message */\r
+ while (len--) {\r
+ //input =(char) *data++;\r
+ FCS = crctable[FCS ^ *data++];\r
+ }\r
+ \r
+ /*Ones complement*/\r
+ FCS = crctable[FCS ^ RcvFCS];\r
+ \r
+ /* 0xCF is the reversed order of 11110011 */\r
+ if (0xCF == FCS) { /* FCS is OK */\r
+ return 1;\r
+ }\r
+ else { /* FCS is NOT OK */\r
+ return 0;\r
+ }\r
+}\r
+\r
+/************************************************************\r
+Function name : tcore_cmux_flush_channel_data\r
+\r
+\r
+************************************************************/\r
+static void tcore_cmux_flush_channel_data()\r
+{\r
+ dbg("Entry");\r
+\r
+ MuxObjPtr->Len =0x0;\r
+ memset(MuxObjPtr->InfoField, 0x0, MAX_CMUX_BUFFER_SIZE);\r
+ \r
+ dbg("Exit");\r
+ return;\r
+}\r
+\r
+/************************************************************\r
+Function name : mux_control_chnl_handle\r
+\r
+\r
+************************************************************/\r
+static void tcore_cmux_control_channel_handle()\r
+{\r
+ unsigned char Cmdtype;\r
+ int MsgLen =0;\r
+ unsigned char *PtrMsgStart =NULL;\r
+ dbg("Entry");\r
+ \r
+ /* 5.4.6.1 Message format\r
+ * All messages sent between the multiplexers conform to the following type, length, value format:\r
+ * Type Length Value 1 Value2 \85\r
+ */\r
+ if (MuxObjPtr->Len > 0) { \r
+ PtrMsgStart = MuxObjPtr->InfoField ;\r
+ Cmdtype = MuxObjPtr->InfoField[0];\r
+ /* The EA bit is an extension bit. The EA bit is set to 1 in the last octet of the sequence; \r
+ * in other octets EA is set to 0.\r
+ * \r
+ * Search for the last octet\r
+ */\r
+ while( (*PtrMsgStart++ & 0x01)) { //TBD\r
+ MsgLen ++;\r
+ }\r
+ \r
+ if((Cmdtype & 0x02) == 0x02) { //This is a command Request\r
+ //Modem Status Command\r
+ if(Cmdtype == MSC ) { \r
+ dbg("Modem Status Command");\r
+ }\r
+ else if(Cmdtype == CLD) { //Modem Status Command\r
+ tcore_cmux_close();\r
+ }\r
+#if 0 /* We will be supporting the commands in Phase 2 */\r
+ else if(Cmdtype == PN) //Modem Status Command\r
+ {\r
+ }\r
+#endif /* We will be supporting the commands in Phase 2 */\r
+ }\r
+ }\r
+ else {\r
+ err("Frame length is less than ZERO");\r
+ }\r
+\r
+ dbg("Exit");\r
+ return;\r
+}\r
+\r
+/************************************************************\r
+Function name : tcore_cmux_process_channel_data\r
+\r
+Process the channel data\r
+************************************************************/\r
+static void tcore_cmux_process_channel_data(CHANNEL *ChannelInfoPtr)\r
+{\r
+ int frameType;\r
+ int ChannelId;\r
+ int len;\r
+ int ret;\r
+ unsigned char * send_data=NULL;\r
+ static int count = 0;\r
+ dbg("Entry");\r
+\r
+ ChannelId = ChannelInfoPtr->ChannelId;\r
+ dbg("Channel ID: %d", ChannelId);\r
+ \r
+ ChannelInfoPtr = MuxObjPtr->channelInfo[ChannelId];\r
+\r
+ frameType = ChannelInfoPtr->FrameType & 0xEF;\r
+ dbg("frameType: 0x%x", frameType);\r
+ \r
+ switch(frameType)\r
+ {\r
+ case UI:\r
+ case UIH:\r
+ {\r
+ dbg("Received UIH Frame");\r
+ if(0 == ChannelId) {\r
+ /*this is control info*/\r
+ dbg("Control information");\r
+ tcore_cmux_control_channel_handle();\r
+ }\r
+ else {\r
+ //put in the logical HAL queue\r
+ //this goes to the Cobject\r
+\r
+ //ChannelInfoPtr->Len = ChannelInfoPtr->Len;\r
+ //memcpy(ChannelInfoPtr->InfoField, ChannelInfoPtr->InfoField, ChannelInfoPtr->Len);\r
+ \r
+ tcore_cmux_recv_mux_data(ChannelInfoPtr);\r
+ }\r
+ break;\r
+ }\r
+ case UA:\r
+ {\r
+ dbg("Received UA Frame");\r
+ dbg("ChannelInfoPtr->state: %d", ChannelInfoPtr->state);\r
+ if(MUX_CHANNEL_SABM_SEND_WAITING_FOR_UA == ChannelInfoPtr->state) {\r
+ ChannelInfoPtr->state = MUX_CHANNEL_ESTABLISHED;\r
+\r
+ count++;\r
+ dbg("Count: %d", count);\r
+ if(MAX_CHANNEL_SUPPORTED == count) {\r
+ /* Indicate to CoreObject */\r
+ CoreObject *co = NULL;\r
+\r
+ /* 'modem' Core Object */\r
+ co = MuxObjPtr->modem_co;\r
+ if(NULL == co) {\r
+ err("'modem' Core object is not present");\r
+ return;\r
+ }\r
+\r
+ /* Emit callback */\r
+ dbg("Emit Core object callback");\r
+ tcore_object_emit_callback(co, "CMUX-UP", NULL);\r
+ dbg("Emitted Core object callback");\r
+ count = 0;\r
+ }\r
+ }\r
+ else if(MUX_CHANNEL_DISC_SEND_WAITING_FOR_UA == ChannelInfoPtr->state) {\r
+ ChannelInfoPtr->state = MUX_CHANNEL_CLOSED;\r
+\r
+ if(0 == ChannelId) {\r
+ MuxObjPtr->state = MUX_CLOSED;\r
+ tcore_cmux_close();\r
+ }\r
+ }\r
+ else {\r
+ err("Received UA in wrong state!!!");\r
+ }\r
+ break;\r
+ }\r
+ case DM:\r
+ {\r
+ /* 5.4.1 DLC Establishment : If the responding station is not ready or unwilling\r
+ * to establish the particular DLC it will reply with a DM frame with the\r
+ * F-bit set to 1.\r
+ */\r
+ dbg("Received DM Frame");\r
+ if((MUX_CHANNEL_ESTABLISHED == ChannelInfoPtr->state)\r
+ || (MUX_CHANNEL_SABM_SEND_WAITING_FOR_UA == ChannelInfoPtr->state)) {\r
+ ChannelInfoPtr->state = MUX_CHANNEL_CLOSED;\r
+ }\r
+ tcore_cmux_flush_channel_data();\r
+\r
+ break;\r
+ }\r
+ case DISC:\r
+ {\r
+ dbg("Received DISC Frame");\r
+ if(0 == ChannelInfoPtr->pollFinalBit) {\r
+ /* In the case where a SABM or DISC command with the P bit set to 0 is received then \r
+ * the received frame shall be discarded.\r
+ */\r
+ tcore_cmux_flush_channel_data();\r
+ }\r
+ else {\r
+ if(MUX_CHANNEL_CLOSED == ChannelInfoPtr->state) {\r
+ //If a DISC command is received while in disconnected mode a DM response should be sent\r
+ /* Encoding frame */\r
+ send_data = tcore_encode_cmux_frame(NULL, 0, ChannelId, DM, 1, 1, 1, &len);\r
+ \r
+ }\r
+ else { //send Unnumbered Acknowledgement\r
+ send_data = tcore_encode_cmux_frame(NULL,0, ChannelId, UA, 1, 1, 1,&len);\r
+ }\r
+\r
+ if(0 == len) {\r
+ err("Failed to encode");\r
+ return;\r
+ }\r
+ /* Directly send to Physical HAL */\r
+ ret = tcore_hal_send_data(MuxObjPtr->phy_hal,len, send_data);\r
+ \r
+ /*5.3.4 Disconnect (DISC) command: DISC command sent at DLCI 0 have the same \r
+ meaning as the Multiplexer Close Down command */\r
+ tcore_cmux_flush_channel_data(); \r
+ if(0 == ChannelId) {\r
+ MuxObjPtr->state =MUX_CLOSED;\r
+ tcore_cmux_close();\r
+ }\r
+ }\r
+ break;\r
+ } \r
+ case SABM:\r
+ {\r
+ dbg("Received SABM Frame");\r
+ if(0 == ChannelInfoPtr->pollFinalBit) {\r
+ /*In the case where a SABM or DISC command with the P bit set to 0 is received then \r
+ the received frame shall be discarded. */\r
+ //flush_rcv_data();\r
+ tcore_cmux_flush_channel_data();\r
+ }\r
+ else {\r
+ send_data = tcore_encode_cmux_frame(NULL,0, ChannelId, UA, 1, 1, 1,&len); \r
+ /* Directly send to Physical HAL */\r
+ ret = tcore_hal_send_data(MuxObjPtr->phy_hal, len,send_data);\r
+\r
+ if(ChannelInfoPtr->state != MUX_CHANNEL_ESTABLISHED) {\r
+ ChannelInfoPtr->state = MUX_CHANNEL_ESTABLISHED;\r
+ }\r
+ } \r
+ break;\r
+ }\r
+ }\r
+\r
+ return ;\r
+}\r
+\r
+/**********************************************\r
+\r
+Function name :tcore_cmux_rcv_from_hal\r
+\r
+This should be a callback from Physical HAL.\r
+DATA Received from CP side.\r
+\r
+***********************************************/\r
+static void tcore_cmux_process_rcv_frame( unsigned char *data, int len)\r
+{\r
+ unsigned char *PtrFrameProcess =data;\r
+ unsigned char *PtrBufStart = data;\r
+\r
+ CHANNEL *ch =NULL;\r
+ unsigned char ChannelId;\r
+ int hlen;\r
+ dbg("Entry");\r
+\r
+ tcore_cmux_flush_channel_data();\r
+\r
+ /* Get the Channel ID : 1st byte will be flag (F9)..Flag checking is already done.*/\r
+ if((ChannelId = ((*++PtrFrameProcess >> 2)& 0x3F)) < MAX_CHANNEL_SUPPORTED) { //max channel is 8\r
+\r
+ ch = MuxObjPtr->channelInfo[ChannelId];\r
+\r
+ ch->ChannelId = ChannelId;\r
+\r
+ //get the EA bit\r
+ ch->ExtBit = *PtrFrameProcess & 0x01;\r
+\r
+ //get the CR bit\r
+ ch->CRBit = (*PtrFrameProcess ++ >> 1) & 0x01;\r
+\r
+ //get the Frame Type\r
+ ch->FrameType = *PtrFrameProcess ++;\r
+\r
+ //get the poll/Final bit\r
+ ch->pollFinalBit = (ch->FrameType & 0x10)>> 4;\r
+\r
+ //get the length . TBD\r
+ if(*PtrFrameProcess & 0x01) { //if len <127\r
+ MuxObjPtr->Len = *PtrFrameProcess ++ >> 1;\r
+ hlen = 3;\r
+ }\r
+ else {\r
+ MuxObjPtr->Len = *(PtrFrameProcess +1) << 7;\r
+ MuxObjPtr->Len = MuxObjPtr->Len | ((* PtrFrameProcess ++ & 0xFE) >> 1);\r
+ hlen = 4;\r
+ PtrFrameProcess++;\r
+ }\r
+ \r
+ /* Copy received information field */\r
+ dbg("MEMCPY :length= %d", MuxObjPtr->Len);\r
+ memcpy(MuxObjPtr->InfoField, PtrFrameProcess, MuxObjPtr->Len);\r
+ dbg("MEMCPY :Done");\r
+ PtrFrameProcess = PtrFrameProcess + MuxObjPtr->Len;\r
+\r
+ //CRC check of the header\r
+ if (rcv_crc_check(PtrBufStart+1, hlen, *PtrFrameProcess)) {\r
+\r
+ dbg("Calling tcore_cmux_process_channel_data");\r
+ tcore_cmux_process_channel_data(ch);\r
+ }\r
+ else {\r
+ err("CRC check of the header FAILED.. Drop the packet !!");\r
+ }\r
+ } \r
+ else {\r
+ err("Incorrect channel... Drop the packet !!");\r
+ }\r
+\r
+ dbg("Exit");\r
+ return;\r
+}\r
+\r
+/**********************************************\r
+\r
+Function name :tcore_cmux_rcv_from_hal\r
+\r
+This should be a callback from Physical HAL.\r
+DATA Received from CP side.\r
+\r
+***********************************************/\r
+int tcore_cmux_rcv_from_hal(unsigned char *data, int len)\r
+{\r
+ unsigned char *buf =data;\r
+ int count =0, i =0;\r
+ int alen =0; //actual length\r
+ \r
+ unsigned char *muxTempBuffer = MuxObjPtr->muxTempBuffer;\r
+ unsigned char *muxMainBuffer = MuxObjPtr->muxMainBuffer;\r
+\r
+ int Tlen = 0; /* Total length */\r
+ int hlen = 0; /* Header length */\r
+ int currentFlen = 0; /* Current Frame length */ \r
+ int pLen = 0; /* pending length in array */ \r
+ \r
+ dbg("Entry");\r
+\r
+#if 1\r
+ //testing\r
+ dbg("len: %d ", len);\r
+ {\r
+ int i=0;\r
+ for(i = 0; i < len ; i++) {\r
+ msg("%02x", data[i]);\r
+ }\r
+ }\r
+#endif\r
+\r
+ if (len > MAX_CMUX_BUFFER_SIZE){\r
+ err("len - %d is more than MAX limit !!" ,len);\r
+ return 0;\r
+ }\r
+ \r
+\r
+ if( (len > 0 ) && (data != NULL)) {\r
+ if(MuxObjPtr->isWaiting) {\r
+ //* Checking if Frame fully contains F9 or not. If only F9,then reject, esle process.\r
+ while(*buf++ == 0xF9) {\r
+ count++;\r
+ }\r
+\r
+ if (count == len) { // In case all are F9 \r
+ err("Not a valid frame");\r
+ return 0;\r
+ }\r
+ dbg("MEMCPY :MuxObjPtr->curMBufLen: %d & len = %d", MuxObjPtr->curMBufLen,len);\r
+ memcpy((muxMainBuffer + MuxObjPtr->curMBufLen),data,len);\r
+ dbg("MEMCPY :DONE");\r
+ MuxObjPtr->curMBufLen = MuxObjPtr->curMBufLen + len;\r
+\r
+ if(MuxObjPtr->pMsgLen <= len) {\r
+ MuxObjPtr->isWaiting =0;\r
+ tcore_cmux_rcv_from_hal(muxMainBuffer,MuxObjPtr->curMBufLen);\r
+ }\r
+ else {\r
+ MuxObjPtr->pMsgLen = MuxObjPtr->pMsgLen - len;\r
+ dbg("Still waiting for the complete frame!!!");\r
+ }\r
+ }\r
+ else {\r
+ if(*buf ==0xF9) { // start flag present\r
+ //remove extra flags\r
+ while(*++buf == 0xF9) {\r
+ count++;\r
+ }\r
+\r
+ //check if received data has atleast three octets between flags\r
+ for(i = 0; ( (i<3) && (*(buf+i)!=0xF9)); i++);\r
+\r
+ if((i<3) || (count == (len-1))) { // In case all are F9 or three octets between falgs not found\r
+ err("Not a valid frame");\r
+ return 0;\r
+ }\r
+\r
+ alen = len - count;\r
+ memset(muxTempBuffer, 0x0, MAX_CMUX_BUFFER_SIZE);\r
+ dbg("MEMCPY :alen= %d", alen);\r
+ memcpy(muxTempBuffer, data + count, alen);\r
+ dbg("MEMCPY :DONE");\r
+ buf = muxTempBuffer + 3;\r
+\r
+ //find the info length field of the current frame\r
+ FIND_LENGTH(buf, hlen, Tlen);\r
+\r
+ //calculate the current frame length including the headers\r
+ currentFlen = hlen +Tlen;\r
+ memset(muxMainBuffer, 0x0, MAX_CMUX_BUFFER_SIZE);\r
+\r
+ if(currentFlen==alen) { //Only 1 frame is received and its a complete frame\r
+ if(muxTempBuffer[currentFlen-0x01] == 0xF9) {\r
+ dbg("MEMCPY :currentFlen= %d", currentFlen);\r
+ memcpy(muxMainBuffer,muxTempBuffer,currentFlen);\r
+ dbg("MEMCPY :DONE");\r
+ tcore_cmux_process_rcv_frame(muxMainBuffer ,currentFlen);\r
+ //initialze the main buffer\r
+ memset(muxMainBuffer, 0x0, MAX_CMUX_BUFFER_SIZE);\r
+ }\r
+ else {\r
+ err("End flag missing!!!");\r
+ return 0;\r
+ }\r
+ }\r
+ else if(currentFlen < alen) { //more than one frame\r
+ if(muxTempBuffer[currentFlen-0x01] == 0xF9) {\r
+ dbg("MEMCPY :currentFlen= %d", currentFlen);\r
+ memcpy(muxMainBuffer,muxTempBuffer,currentFlen);\r
+ dbg("MEMCPY :DONE");\r
+ tcore_cmux_process_rcv_frame(muxMainBuffer ,currentFlen);\r
+\r
+ //initialze the main buffer\r
+ memset(muxMainBuffer, 0x0, MAX_CMUX_BUFFER_SIZE);\r
+\r
+ muxMainBuffer[0]=0xF9;\r
+ pLen = alen - currentFlen;\r
+ dbg("MEMCPY :pLen= %d", pLen);\r
+ memcpy((muxMainBuffer + 0x01), (muxTempBuffer + currentFlen), pLen);\r
+ dbg("MEMCPY :DONE");\r
+ tcore_cmux_rcv_from_hal( muxMainBuffer,pLen + 0x01);\r
+ }\r
+ else {\r
+ err("End flag missing!!!");\r
+ return 0;\r
+ }\r
+ }\r
+ else if(currentFlen > alen) {//the frame is incomplete.Yet to receive the full frame\r
+ MuxObjPtr->isWaiting = 1;\r
+ dbg("MEMCPY :alen= %d", alen);\r
+ memcpy(muxMainBuffer, muxTempBuffer + count, alen);\r
+ dbg("MEMCPY :DONE");\r
+ MuxObjPtr->pMsgLen = currentFlen - alen;\r
+ MuxObjPtr->curMBufLen = alen ;\r
+ }\r
+ }\r
+ else {\r
+ err("Start flag missing!!!");\r
+ }\r
+ }\r
+ } \r
+ else {\r
+ err("Incorrect Length!!! or NULL Data!!");\r
+ }\r
+\r
+ dbg("Exit");\r
+ return 1;\r
+}\r
+\r
+#if 1\r
+void tcore_cmux_channel_init(CMUX_Channels channel_id)\r
+{\r
+ CHANNEL *ch = NULL;\r
+ dbg("Entry");\r
+ \r
+ ch = MuxObjPtr->channelInfo[channel_id];\r
+ memset(ch, 0x0, sizeof(CHANNEL));\r
+ \r
+ ch->ChannelId = channel_id;\r
+ ch->state = MUX_CHANNEL_SABM_SEND_WAITING_FOR_UA;\r
+\r
+ ch->co = NULL;\r
+ ch->hal = NULL;\r
+\r
+ /* TODO - Check if required */\r
+ ch->FrameType = SABM;\r
+ ch->ExtBit = 0x01;\r
+ ch->CRBit = 0x01;\r
+ ch->pollFinalBit = 0x01;\r
+\r
+ dbg("Channel ID %d initialized", channel_id);\r
+ \r
+ dbg("Exit");\r
+ return;\r
+}\r
+#else\r
+/*********************************************************\r
+\r
+OPEN CMUX CHANNEL\r
+*********************************************************/\r
+int open_cmux_channel(int channelID)\r
+{\r
+ CHANNEL *ch;\r
+ unsigned char *send_data;\r
+ int ret;\r
+ int len;\r
+ dbg("Entry");\r
+\r
+ ch = MuxObjPtr->channelInfo[channelID];\r
+\r
+ if(ch->state == MUX_CHANNEL_CLOSED) {\r
+ ch->FrameType = SABM;\r
+ ch->ExtBit = 0x01;\r
+ ch->CRBit = 0x01;\r
+\r
+ send_data = tcore_encode_cmux_frame(NULL, 0, channelID, SABM, 0x01, 0x01, 0x01, &len); \r
+ \r
+ /* Directly send to Physical HAL */\r
+ ret = tcore_hal_send_data(MuxObjPtr->phy_hal,len, send_data);\r
+ }\r
+ else {\r
+ //channel is already initialized\r
+ err("Channel is already initialized");\r
+ }\r
+\r
+ dbg("Exit");\r
+ return 1;\r
+ }\r
+#endif\r
+\r
+/*********************************************************\r
+ CLOSE CMUX CHANNEL\r
+*********************************************************/\r
+int tcore_cmux_close_channel(int channelID)\r
+{\r
+ CHANNEL *ch = NULL;\r
+ unsigned char *send_data = NULL;\r
+ int ret, len;\r
+ dbg("Entry");\r
+\r
+ ch = MuxObjPtr->channelInfo[channelID];\r
+ \r
+ if(ch->state != MUX_CHANNEL_CLOSED) {\r
+ ch->FrameType = DISC;\r
+ ch->ExtBit = 0x01;\r
+ ch->CRBit = 0x01;\r
+ ch->state = MUX_CHANNEL_DISC_SEND_WAITING_FOR_UA;\r
+\r
+ /* Send DSC command */\r
+ send_data = tcore_encode_cmux_frame(NULL,0, channelID, DISC, 0x01, 0x01, 0x01, &len); \r
+ \r
+ /* Directly send to Physical HAL */\r
+ ret = tcore_hal_send_data(MuxObjPtr->phy_hal, len, send_data);\r
+\r
+ }\r
+ else {\r
+ /* Channel is already closed */\r
+ err("Channel is already closed");\r
+ }\r
+\r
+ dbg("Exit");\r
+ return 1;\r
+}\r
+\r
+static void tcore_cmux_free()\r
+{\r
+ int channel;\r
+ dbg("Entry");\r
+ \r
+ if(MuxObjPtr) {\r
+\r
+ /* Free Information Field */\r
+ if (MuxObjPtr->InfoField) \r
+ free(MuxObjPtr->InfoField);\r
+ \r
+ for (channel = 0 ; channel < MAX_CHANNEL_SUPPORTED ; channel++)\r
+ {\r
+ /* Free Channel Information */\r
+ if(MuxObjPtr->channelInfo[channel]) {\r
+ free(MuxObjPtr->channelInfo[channel]);\r
+ }\r
+ }\r
+\r
+ /* Free MUX Object */\r
+ free(MuxObjPtr);\r
+ }\r
+ else {\r
+ err("MUX Object doesn't exist");\r
+ }\r
+\r
+ dbg("Exit");\r
+ return;\r
+}\r
+\r
+void tcore_cmux_init(TcorePlugin *plugin, TcoreHal *h)\r
+{\r
+ TcoreHal *physical_hal = NULL;\r
+ unsigned char *data = NULL;\r
+ int data_len = 0;\r
+\r
+ int index;\r
+ dbg("Entry");\r
+\r
+ physical_hal = (TcoreHal *)h;\r
+ dbg("Physical HAL: %x", physical_hal);\r
+\r
+ /* Creat new CMUX Object */\r
+ MuxObjPtr = tcore_cmux_new();\r
+ if(NULL == MuxObjPtr) {\r
+ err("Failed to create MUX object");\r
+ return;\r
+ }\r
+\r
+ /* Save Plugin */\r
+ MuxObjPtr->p = plugin;\r
+ \r
+ /* Save Physical HAL */\r
+ MuxObjPtr->phy_hal = physical_hal;\r
+\r
+ /* Setting Receive callback function for data received from Physical HAL */\r
+ MuxObjPtr->cb_func= tcore_cmux_recv_mux_data;\r
+ \r
+ /* After MUX setup, AT parse functionality of PHY HAL should be disabled,\r
+ * here we change the mode of PHYSICAL HAL to Custom.\r
+ */\r
+ tcore_hal_set_mode(MuxObjPtr->phy_hal , TCORE_HAL_MODE_TRANSPARENT);\r
+ dbg("Physical HAL mode changed to Transparent");\r
+ \r
+ /* Initialize all the Channels */\r
+ /* Open all Channels */\r
+ for(index = 0 ; index < MAX_CHANNEL_SUPPORTED ; index++) {\r
+\r
+ dbg("Initialize the Channel %d", index); \r
+ tcore_cmux_channel_init((CMUX_Channels)index);\r
+ \r
+ dbg("Opening Channel %d", index);\r
+ /* Encode CMUX Frame */\r
+ data = tcore_encode_cmux_frame(NULL, 0, index, SABM, 0x01, 0x01, 0x01, &data_len);\r
+ if(NULL == data) {\r
+ err("Failed to encode");\r
+ return;\r
+ }\r
+ dbg("data_len: %d data: %s", data_len, data);\r
+\r
+#if 1\r
+ /* For Testing */\r
+ {\r
+ int i;\r
+ \r
+ for(i = 0; i < data_len ; i++) {\r
+ msg("%02x", data[i]);\r
+ }\r
+ }\r
+#endif\r
+ /* Send Frame to CP */\r
+ tcore_hal_send_data(physical_hal, data_len, data);\r
+ dbg("CMUX Control Request sent to CP");\r
+\r
+ /* Set Core object and HAL */\r
+ tcore_cmux_link_core_object_hal((CMUX_Channels)index, plugin);\r
+ }\r
+\r
+ dbg("Exit");\r
+ return;\r
+}\r
+\r
+/*********************************************************\r
+\r
+MUX Close down\r
+\r
+*********************************************************/\r
+void tcore_cmux_close()\r
+{\r
+ int channel = 0;\r
+ int index = 0;\r
+ CoreObject *co = NULL;\r
+ GSList *co_list = NULL;\r
+ dbg("Entry");\r
+\r
+ for (channel = 0; channel < MAX_CHANNEL_SUPPORTED ; channel++) {\r
+ dbg("Channel ID: %d", channel);\r
+ index = 0;\r
+\r
+ /* Close Channel - Send DSC command */\r
+ tcore_cmux_close_channel(channel);\r
+\r
+ /* Revert Physical HAL as HAL of each Core Object associated to this Channel */\r
+ while (NULL != cmux_channel_Cobject[channel].Cobject_name[index]) {\r
+ co = NULL;\r
+\r
+ /* Core Objects list */\r
+ co_list = MuxObjPtr->channelInfo[channel]->co;\r
+ dbg("Core Objects list : %p", co_list);\r
+ \r
+ /* Core Object list may contain multiple Core Objects.\r
+ * Revert to Physical HAL for each of the Core Objects associated\r
+ * with this Channel\r
+ */\r
+ while(NULL != co_list) {\r
+ if(NULL != co_list->data) {\r
+ if(!strcmp((const char *)cmux_channel_Cobject[channel].Cobject_name[index], (const char *)tcore_object_ref_name((CoreObject *)co_list->data))) {\r
+ co = (CoreObject *)co_list->data;\r
+ dbg("Found the Core Object");\r
+ break;\r
+ }\r
+ }\r
+\r
+ /* To next Core Object in the list */\r
+ co_list = co_list->next;\r
+ }\r
+\r
+ /* Set the previous Physical HAL as HAL for Core Object */\r
+ if(NULL != co) {\r
+ tcore_object_set_hal(co, MuxObjPtr->phy_hal);\r
+ }\r
+ else {\r
+ /* Proceed to next Channel */\r
+ err("No more Core Objects present in this Channel");\r
+ break;\r
+ }\r
+\r
+ /* To next Core Object */\r
+ index++;\r
+ }\r
+ \r
+ /* Free Logical HAL for Channel */\r
+ tcore_hal_free(MuxObjPtr->channelInfo[channel]->hal);\r
+ }\r
+ \r
+ /* Change the mode of PHYSICAL HAL to Custom */\r
+ tcore_hal_set_mode(MuxObjPtr->phy_hal, TCORE_HAL_MODE_CUSTOM);\r
+\r
+ /* Free all the allocated memory */\r
+ tcore_cmux_free();\r
+ \r
+ dbg("Exit");\r
+ return;\r
+}\r