hal: Implement network interface setup
[platform/core/telephony/libtcore.git] / src / mux.c
1 /*
2  * libtcore
3  *
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Arijit Sen <arijit.sen@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20
21 #include <stdio.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <stdlib.h>
25
26 #include <glib.h>
27
28 #include "tcore.h"
29
30 #include "hal.h"
31 #include "plugin.h"
32 #include "user_request.h"
33 #include "server.h"
34 #include "mux.h"
35 #include "core_object.h"
36
37 /* Maximum Core objects per Logical HAL (indirectly per Channel) */
38 #define MAX_CMUX_CORE_OBJECTS           3
39
40 /* Max CMUX Buffer size */
41 #define MAX_CMUX_BUFFER_SIZE            4096
42
43 /* Max muber of CMUX Channels */
44 #define MAX_CMUX_CHANNELS_SUPPORTED     8
45
46 /* CMUX Commands */
47 #define CMUX_COMMAND_SABM                       0x2F
48 #define CMUX_COMMAND_UA                         0x63
49 #define CMUX_COMMAND_DM                         0x0F
50 #define CMUX_COMMAND_DISC                       0x43
51 #define CMUX_COMMAND_UIH                        0xEF
52 #define CMUX_COMMAND_UI                         0x03
53
54 /* MUX CONTROL COMMANDS
55   * We are supporting only MSC command for phase 1
56   */
57 #define  CMUX_COMMAND_MSC                       0xE3    // Modem Status Command
58 #define  CMUX_COMMAND_CLD                       0xC3    // Multiplexer close down
59
60 /* CMUX Channels [0-7] -
61   * Channel 0 - Control Channel for CMUX
62   * Channel 1 - CALL
63   * Channel 2 - SIM
64   * Channel 3 - SAT
65   * Channel 4 - SMS
66   * Channel 5 - SS
67   * Channel 6 - NETWORK
68   * Channel 7 - MODEM & PS
69   */
70 typedef enum CMUX_Channels {
71         CMUX_CHANNEL_0,
72         CMUX_CHANNEL_1,
73         CMUX_CHANNEL_2,
74         CMUX_CHANNEL_3,
75         CMUX_CHANNEL_4,
76         CMUX_CHANNEL_5,
77         CMUX_CHANNEL_6,
78         CMUX_CHANNEL_7
79 } CMUX_Channels;
80
81 /* MUX Channel States */
82 typedef enum MuxChannelState {
83         MUX_CHANNEL_CLOSED,
84         MUX_CHANNEL_SABM_SEND_WAITING_FOR_UA,
85         MUX_CHANNEL_ESTABLISHED,
86         MUX_CHANNEL_UA_NOT_RECEIVED_RETRY,
87         MUX_CHANNEL_DM_RECEIVED_CLOSING,
88         MUX_CHANNEL_DM_SEND,
89         MUX_CHANNEL_DISC_RECEIVED_CLOSING,
90         MUX_CHANNEL_DISC_SEND_WAITING_FOR_UA,
91         MUX_CHANNEL_UA_SEND_CLOSING,
92         MUX_CHANNEL_UA_RECEIVED,
93         MUX_CHANNEL_UA_SENDING,
94 } MuxChannelState;
95
96 /* MUX State */
97 typedef enum MuxState {
98         MUX_NOT_INITIALIZED,
99         MUX_INITIALIZED,
100         MUX_CLOSED
101 } MuxState;
102
103 #define FIND_LENGTH(buf, header_length, total_length)  do {     \
104                 if (*buf & 0x01) { \
105                         total_length = *buf++ >> 1;     \
106                         header_length = 6; \
107                 } \
108                 else { \
109                         total_length = *(buf + 0x01) << 7; \
110                         total_length = total_length | (*buf & 0xFE) >> 1; \
111                         header_length = 7; \
112                 } \
113 } while (0)
114
115 /*================= CRC TABLE=========================*/
116 const unsigned char crc_table[256] = { // reversed, 8-bit, poly=0x07
117         0x00, 0x91, 0xE3, 0x72, 0x07, 0x96, 0xE4, 0x75, 0x0E, 0x9F, 0xED, 0x7C, 0x09, 0x98, 0xEA, 0x7B,
118         0x1C, 0x8D, 0xFF, 0x6E, 0x1B, 0x8A, 0xF8, 0x69, 0x12, 0x83, 0xF1, 0x60, 0x15, 0x84, 0xF6, 0x67,
119         0x38, 0xA9, 0xDB, 0x4A, 0x3F, 0xAE, 0xDC, 0x4D, 0x36, 0xA7, 0xD5, 0x44, 0x31, 0xA0, 0xD2, 0x43,
120         0x24, 0xB5, 0xC7, 0x56, 0x23, 0xB2, 0xC0, 0x51, 0x2A, 0xBB, 0xC9, 0x58, 0x2D, 0xBC, 0xCE, 0x5F,
121         0x70, 0xE1, 0x93, 0x02, 0x77, 0xE6, 0x94, 0x05, 0x7E, 0xEF, 0x9D, 0x0C, 0x79, 0xE8, 0x9A, 0x0B,
122         0x6C, 0xFD, 0x8F, 0x1E, 0x6B, 0xFA, 0x88, 0x19, 0x62, 0xF3, 0x81, 0x10, 0x65, 0xF4, 0x86, 0x17,
123         0x48, 0xD9, 0xAB, 0x3A, 0x4F, 0xDE, 0xAC, 0x3D, 0x46, 0xD7, 0xA5, 0x34, 0x41, 0xD0, 0xA2, 0x33,
124         0x54, 0xC5, 0xB7, 0x26, 0x53, 0xC2, 0xB0, 0x21, 0x5A, 0xCB, 0xB9, 0x28, 0x5D, 0xCC, 0xBE, 0x2F,
125         0xE0, 0x71, 0x03, 0x92, 0xE7, 0x76, 0x04, 0x95, 0xEE, 0x7F, 0x0D, 0x9C, 0xE9, 0x78, 0x0A, 0x9B,
126         0xFC, 0x6D, 0x1F, 0x8E, 0xFB, 0x6A, 0x18, 0x89, 0xF2, 0x63, 0x11, 0x80, 0xF5, 0x64, 0x16, 0x87,
127         0xD8, 0x49, 0x3B, 0xAA, 0xDF, 0x4E, 0x3C, 0xAD, 0xD6, 0x47, 0x35, 0xA4, 0xD1, 0x40, 0x32, 0xA3,
128         0xC4, 0x55, 0x27, 0xB6, 0xC3, 0x52, 0x20, 0xB1, 0xCA, 0x5B, 0x29, 0xB8, 0xCD, 0x5C, 0x2E, 0xBF,
129         0x90, 0x01, 0x73, 0xE2, 0x97, 0x06, 0x74, 0xE5, 0x9E, 0x0F, 0x7D, 0xEC, 0x99, 0x08, 0x7A, 0xEB,
130         0x8C, 0x1D, 0x6F, 0xFE, 0x8B, 0x1A, 0x68, 0xF9, 0x82, 0x13, 0x61, 0xF0, 0x85, 0x14, 0x66, 0xF7,
131         0xA8, 0x39, 0x4B, 0xDA, 0xAF, 0x3E, 0x4C, 0xDD, 0xA6, 0x37, 0x45, 0xD4, 0xA1, 0x30, 0x42, 0xD3,
132         0xB4, 0x25, 0x57, 0xC6, 0xB3, 0x22, 0x50, 0xC1, 0xBA, 0x2B, 0x59, 0xC8, 0xBD, 0x2C, 0x5E, 0xCF
133 };
134 /*================= CRC TABLE=========================*/
135
136 /* CMUX Channel */
137 typedef struct cmux_channel {
138         GSList *co;
139         TcoreHal *hal;
140         MuxChannelState state;
141         CMUX_Channels channel_id;
142         int frame_type;
143         unsigned char ext_bit;
144         unsigned char cr_bit;
145         unsigned char poll_final_bit;
146 } CHANNEL;
147
148 /* CMUX callback prototype */
149 typedef gboolean (*mux_cb_func)(CHANNEL *channel_ptr);
150
151 /* CMUX structure */
152 typedef struct cmux {
153         MuxState state;
154         CHANNEL *channel_info[MAX_CMUX_CHANNELS_SUPPORTED];
155         int is_waiting;
156         int msg_len;
157         int cur_main_buf_len;
158         TcorePlugin *plugin;
159         TcoreHal *phy_hal;
160         CoreObject *modem_co;
161         mux_cb_func cb_func;
162         int info_field_len;
163         unsigned char *info_field;
164 } MUX;
165
166 /* Global pointer MUX Object pointer */
167 MUX *g_mux_obj_ptr = NULL;
168
169 /* CMUX mode of operation */
170 int g_mux_mode = 0; /* BASIC mode */
171
172 struct cmux_channel_object {
173         char *channel_id_name;
174         char *core_object_name[MAX_CMUX_CORE_OBJECTS];
175 };
176
177 /* Core Object names need to be verified, define a MACRO globally */
178 struct cmux_channel_object cmux_channel_core_object[] = {
179         {"channel_0", {"control", NULL, NULL}},
180         {"channel_1", {"call", NULL, NULL}},
181         {"channel_2", {"sim", "phonebook", NULL}},
182         {"channel_3", {"sat", "sap", NULL}},
183         {"channel_4", {"umts_sms", NULL, NULL}},
184         {"channel_5", {"ss", NULL, NULL}},
185         {"channel_6", {"umts_network", "gps", NULL}},
186         {"channel_7", {"modem", "umts_ps", NULL}},
187 };
188
189 /* All the local functions declared below */
190 static unsigned char calc_crc(unsigned char *header, int length);
191 static int rcv_crc_check(unsigned char *data, unsigned char len, unsigned char rcv_FCS);
192 MUX* tcore_cmux_new(void);
193 static void tcore_cmux_free(void);
194 void tcore_cmux_link_core_object_hal(CMUX_Channels channel_id, TcorePlugin *plugin);
195 static gboolean tcore_cmux_recv_mux_data(CHANNEL *channel_ptr);
196 static void tcore_cmux_process_rcv_frame(unsigned char *data, int len);
197 static void tcore_cmux_process_channel_data(CHANNEL *channel_info_ptr);
198 static void tcore_cmux_control_channel_handle(void);
199 static void tcore_cmux_flush_channel_data(void);
200 static void tcore_cmux_channel_init(CMUX_Channels channel_id);
201 static void tcore_cmux_close_channel(int channel_id);
202 static unsigned char* tcore_encode_cmux_frame(unsigned char *data, int length, int channel_id, int frame_type, unsigned char EA_bit, unsigned char CR_bit, unsigned char PF_bit, int *out_data_len);
203 static TReturn tcore_cmux_send_data(int data_len, unsigned char *data);
204
205 static TReturn tcore_cmux_hal_power(TcoreHal *h, gboolean flag)
206 {
207         TcorePlugin *p = NULL;
208         struct custom_data *user_data = NULL;
209
210         dbg("Entry");
211
212         p = tcore_hal_ref_plugin(h);
213         if (!p) {
214                 err("Plugin is undefined");
215                 return TCORE_RETURN_FAILURE;
216         }
217
218         user_data = tcore_hal_ref_user_data(h);
219         if (!user_data) {
220                 err("User data is undefined");
221                 return TCORE_RETURN_FAILURE;
222         }
223
224         tcore_hal_set_power_state(h, TRUE);
225
226         dbg("Exit");
227         return TCORE_RETURN_SUCCESS;
228 }
229
230 static TReturn tcore_cmux_hal_send(TcoreHal *h, unsigned int data_len, void *data)
231 {
232         unsigned char *send_data = NULL;
233         char *channel_name = NULL;
234         int channel_id = MAX_CMUX_CHANNELS_SUPPORTED;
235         int len = 0;
236         int i = 0;
237         int ret;
238
239         dbg("Entry");
240
241         /* Check if Logical HAL is Powered ON */
242         if (tcore_hal_get_power_state(h) == FALSE) {
243                 err("HAL is not Powered UP");
244                 return TCORE_RETURN_FAILURE;
245         }
246
247         channel_name = tcore_hal_get_name(h);
248         dbg("HAL name: %s", channel_name)
249         if (channel_name) {
250                 while (i < MAX_CMUX_CHANNELS_SUPPORTED) {
251                         if (0 == strcmp((char *) cmux_channel_core_object[i].channel_id_name, (char *) channel_name)) {
252                                 channel_id = i;
253                                 dbg("Found Channel ID: %d", channel_id);
254
255                                 /* Free memory */
256                                 free(channel_name);
257                                 break;
258                         }
259                         i++;
260                 }
261         } else {
262                 err("No name defined for HAL");
263                 return TCORE_RETURN_FAILURE;
264         }
265
266         if (channel_id > MAX_CMUX_CHANNELS_SUPPORTED) {
267                 err("Failed to find Channel ID");
268                 return TCORE_RETURN_FAILURE;
269         }
270
271         /* Muxing operation and Frame creation */
272         /* Encoding frame */
273         send_data = tcore_encode_cmux_frame(data, data_len, channel_id, CMUX_COMMAND_UIH, 1, 1, 0, &len);
274         if (0 == len) {
275                 err("Failed to encode");
276                 return TCORE_RETURN_FAILURE;
277         }
278
279         /* Send CMUX data */
280         ret = tcore_cmux_send_data(len, send_data);
281
282         dbg("Exit");
283         return TCORE_RETURN_SUCCESS;
284 }
285
286 static TReturn tcore_cmux_hal_setup_netif(CoreObject *co,
287                                         TcoreHalSetupNetifCallback func,
288                                         void *user_data, unsigned int cid,
289                                         gboolean enable)
290 {
291         TcoreHal *hal = g_mux_obj_ptr->phy_hal;
292
293         if (hal == NULL)
294                 return TCORE_RETURN_EINVAL;
295
296         return tcore_hal_setup_netif(hal, co, func, user_data, cid, enable);
297 }
298
299 /* CMUX supported HAL (Logical HAL) operations */
300 static struct tcore_hal_operations mux_hops = {
301         .power = tcore_cmux_hal_power,
302         .send = tcore_cmux_hal_send,
303         .setup_netif = tcore_cmux_hal_setup_netif,
304 };
305
306 static TReturn tcore_cmux_send_data(int data_len, unsigned char *data)
307 {
308         TReturn ret = TCORE_RETURN_SUCCESS;
309
310         dbg("Entry");
311
312         /* Directly send to Physical HAL */
313         ret = tcore_hal_send_data(g_mux_obj_ptr->phy_hal, data_len, (void *) data);
314         if (TCORE_RETURN_SUCCESS != ret) {
315                 err("Failed to send CMUX data");
316         } else {
317                 dbg("Successfully sent CMUX data");
318         }
319
320         dbg("Exit");
321         return ret;
322 }
323 static gboolean tcore_cmux_recv_mux_data(CHANNEL *channel_ptr)
324 {
325         TcoreHal *hal = NULL;
326
327         dbg("Entry");
328
329         /* Dereferencing HAL from Channel Pointer */
330         hal = channel_ptr->hal;
331
332         dbg("Dispatching to logical HAL - hal: %x", (unsigned int)hal);
333         tcore_hal_dispatch_response_data(hal, 0, g_mux_obj_ptr->info_field_len, g_mux_obj_ptr->info_field);
334
335         dbg("Exit");
336         return TRUE;
337 }
338
339 void tcore_cmux_link_core_object_hal(CMUX_Channels channel_id, TcorePlugin *plugin)
340 {
341         TcoreHal *hal = NULL;
342         CoreObject *co = NULL;
343         int index;
344
345         dbg("Entry");
346
347         if (CMUX_CHANNEL_0 != channel_id) {
348                 dbg("Normal channel [%d]", channel_id);
349
350                 /* Creating Logical HAL for Core Object - Mode - 'AT mode' */
351                 hal = tcore_hal_new(plugin, cmux_channel_core_object[channel_id].channel_id_name, &mux_hops, TCORE_HAL_MODE_AT);
352                 dbg("hal: %p", hal);
353
354                 /* Update Logical HAL of CMUX Channel */
355                 g_mux_obj_ptr->channel_info[channel_id]->hal = hal;
356
357                 index = 0;
358                 while (NULL != cmux_channel_core_object[channel_id].core_object_name[index]) {
359                         /* Retrieving Core Object */
360                         dbg("Core Object: '%s'", cmux_channel_core_object[channel_id].core_object_name[index]);
361                         co = tcore_plugin_ref_core_object(plugin, cmux_channel_core_object[channel_id].core_object_name[index]);
362                         dbg("co: %p", co);
363
364                         if (0 == strcmp((const char *) cmux_channel_core_object[channel_id].core_object_name[index], "modem")) {
365                                 g_mux_obj_ptr->modem_co = co;
366                                 dbg("'modem' Core object reference is stored");
367                         }
368
369                         /* Set Logical HAL to Core objects */
370                         tcore_object_set_hal(co, hal);
371
372                         /* Update Core Object list of CMUX Channel */
373                         g_mux_obj_ptr->channel_info[channel_id]->co = g_slist_append(g_mux_obj_ptr->channel_info[channel_id]->co, co);
374
375                         /* Next Core Object of the channel */
376                         index++;
377                 }
378         } else {
379                 /* Control Channel */
380                 dbg("Control channel");
381
382                 /* Creating Logical HAL for Core Object - Mode - 'AT mode' */
383                 hal = tcore_hal_new(plugin, cmux_channel_core_object[channel_id].channel_id_name, &mux_hops, TCORE_HAL_MODE_AT);
384                 dbg("hal: %p", hal);
385
386                 /* Update Logical HAL of CMUX Channel */
387                 g_mux_obj_ptr->channel_info[channel_id]->hal = hal;
388         }
389
390         /* Set Logical HAL Power State to TRUE */
391         tcore_hal_set_power_state(hal, TRUE);
392         dbg("HAL Power is SET");
393
394         dbg("Exit");
395         return;
396 }
397
398 MUX* tcore_cmux_new(void)
399 {
400         MUX *mux = NULL;
401         int i = 0;
402
403         /* Allocating memory for mux */
404         mux = (MUX *) calloc(1, sizeof(MUX));
405         if (!mux) {
406                 err("Failed to allocate memory");
407                 return NULL;
408         }
409
410         /* Allocating memory for info_field */
411         mux->info_field = (unsigned char *) calloc(MAX_CMUX_BUFFER_SIZE, 1);
412         if (!mux->info_field) {
413                 err("Failed to allocate memory for info field");
414                 goto ERROR;
415         }
416
417         /* MUX State initialize to MUX_NOT_INITIALIZED */
418         mux->state = MUX_NOT_INITIALIZED;
419
420         /* Allocating memory for channel_info */
421         for (i = 0; i < MAX_CMUX_CHANNELS_SUPPORTED; i++) {
422                 mux->channel_info[i] = (CHANNEL *) calloc(1, sizeof(CHANNEL));
423                 /* Check for Memory allocation failure */
424                 if (!mux->channel_info[i]) {
425                         err("Failed to allocate memory for channel_info of channel: %d", i);
426                         goto ERROR;
427                 }
428         }
429
430         return mux;
431
432 ERROR:
433         /* Free allocated memory */
434         if (mux) {
435                 if (mux->info_field) {
436                         free(mux->info_field);
437                 }
438
439                 for (i = 0; i < MAX_CMUX_CHANNELS_SUPPORTED; i++) {
440                         if (mux->channel_info[i]) {
441                                 free(mux->channel_info[i]);
442                         }
443                 }
444
445                 free(mux);
446         }
447
448         err("Exit");
449         return NULL;
450 }
451
452 static unsigned char calc_crc(unsigned char *header, int length)
453 {
454         unsigned char FCS = 0xFF; /*Init*/
455         unsigned char crc = 0x00;
456
457         /* 'length' is the number of bytes in the message, 'header' points to message */
458         while (length--) {
459                 FCS = crc_table[FCS ^ *header++];
460         }
461
462         /*Ones complement*/
463         crc = (0xFF - FCS);
464
465         dbg("Exit - crc: 0x%02x", crc)
466         return crc;
467 }
468
469 static unsigned char* tcore_encode_cmux_frame(unsigned char *data,
470                                                                                           int length,
471                                                                                           int channel_id,
472                                                                                           int frame_type,
473                                                                                           unsigned char EA_bit,
474                                                                                           unsigned char CR_bit,
475                                                                                           unsigned char PF_bit,
476                                                                                           int *out_data_len)
477 {
478         int frame_length = 0;
479         int total_frame_length = 0;
480         int crc_len = 0;
481
482         dbg("Entry");
483
484         /* Flush channel data */
485         tcore_cmux_flush_channel_data();
486
487         if (length > MAX_CMUX_BUFFER_SIZE) {
488                 err("Length - %d  exceeds the limit", length);
489                 return NULL;
490         }
491
492         /* Flag Octet */
493         g_mux_obj_ptr->info_field[frame_length++] = (char) 0xF9;
494
495         /* Mode of Operation */
496         if (0x00 == g_mux_mode) {                /* BASIC */
497                 /* EA: Extension Bit
498                 * C/R: Command Response
499                 */
500                 g_mux_obj_ptr->info_field[frame_length] = g_mux_obj_ptr->info_field[frame_length] | ((EA_bit & 0x01) | ((CR_bit << 1) & 0x02));
501
502                 /* DLCI: Data Link Connection Identifier */
503                 /* Check if the channel is within range */
504                 if (channel_id < MAX_CMUX_CHANNELS_SUPPORTED && channel_id >= 0) {
505                         dbg("Channel ID: %d", channel_id);
506                         g_mux_obj_ptr->info_field[frame_length] = g_mux_obj_ptr->info_field[frame_length] | ((unsigned char) channel_id << 2);
507                 } else {
508                         err("Channel is out of range[0-8]");
509                         return NULL;
510                 }
511                 frame_length++;
512
513                 /* Control Field
514                   * The content of the control field defines the type of frame.
515                   * ****************************************************************
516                   * Frame Type                                                                          0 1 2 3  4   5 6 7
517                   * SABM (Set Asynchronous Balanced Mode)                               1 1 1 1 P/F 1 0 0
518                   * UA (Unnumbered Acknowledgement)                                     1 1 0 0 P/F 1 1 0
519                   * DM (Disconnected Mode)                                                              1 1 1 1 P/F 0 0 0
520                   * DISC (Disconnect)                                                                   1 1 0 0 P/F 0 1 0
521                   * UIH (Unnumbered Information with Header check)                      1 1 1 1 P/F 1 1 1
522                   *****************************************************************/
523                 if (PF_bit) {
524                         g_mux_obj_ptr->info_field[frame_length++] = frame_type | 0x10;
525                 } else {
526                         g_mux_obj_ptr->info_field[frame_length++] = frame_type;
527                 }
528
529                 /* 5.2.1.5 Length Indicator */
530                 if (length < 128) {
531                         g_mux_obj_ptr->info_field[frame_length++] = (char) length << 1 | 0x01;
532
533                         /* CRC calculatable length */
534                         crc_len = 3;
535                 } else {
536                         g_mux_obj_ptr->info_field[frame_length++] = (char) (length << 1);  // Need to change
537                         g_mux_obj_ptr->info_field[frame_length++] = (char) (length >> 7);  // Need to change
538
539                         /* CRC calculatable length */
540                         crc_len = 4;
541                 }
542
543                 /* We need to divide the frames into maximum frame length supported by IMC.
544                 * If IMC supports length according to 27.010 , we can send max of 16,384 bytes.
545                 * Need to discuss with IMC.
546                 */
547
548                 /* 5.2.1.4 Information Field*/
549                 if (length > 0) {
550                         memcpy((g_mux_obj_ptr->info_field + frame_length), data, length);
551                         frame_length += length;
552                 } else {
553                         dbg("info field length is zero");
554                 }
555
556                 /*5.2.1.6 Frame Checking Sequence Field (FCS)*/
557                 g_mux_obj_ptr->info_field[frame_length++] = calc_crc(g_mux_obj_ptr->info_field + 1, crc_len);
558
559                 /*Flag Octet*/
560                 g_mux_obj_ptr->info_field[frame_length++] = 0xF9;
561
562                 total_frame_length = frame_length;
563         } else if (0x01 == g_mux_mode) {        /* TBD MUX_MODE_ADVANCE */
564                 dbg("Advanced MUX mode : TBD");
565         }
566
567         *out_data_len = total_frame_length;
568         dbg("*out_data_len: %d", *out_data_len);
569
570         dbg("Exit total_frame_length: %d", total_frame_length);
571         return g_mux_obj_ptr->info_field;
572 }
573
574 static int rcv_crc_check(unsigned char *data, unsigned char len, unsigned char rcv_FCS)
575 {
576         unsigned char FCS = 0xFF;
577
578         /* 'len' is the number of bytes in the message, 'data' points to message */
579         while (len--) {
580                 FCS = crc_table[FCS ^ *data++];
581         }
582
583         /*Ones complement*/
584         FCS = crc_table[FCS ^ rcv_FCS];
585
586         /* 0xCF is the reversed order of 11110011 */
587         if (0xCF == FCS) {      /* FCS is OK */
588                 return 1;
589         } else {            /* FCS is NOT OK */
590                 return 0;
591         }
592 }
593
594 static void tcore_cmux_flush_channel_data(void)
595 {
596         dbg("Entry");
597
598         g_mux_obj_ptr->info_field_len = 0x0;
599         memset(g_mux_obj_ptr->info_field, 0x0, MAX_CMUX_BUFFER_SIZE);
600
601         dbg("Exit");
602         return;
603 }
604
605 static void tcore_cmux_control_channel_handle(void)
606 {
607         unsigned char cmd_type;
608         int msg_len = 0;
609         unsigned char *msg_start_ptr = NULL;
610
611         dbg("Entry");
612
613         /* 5.4.6.1 Message format
614           * All messages sent between the multiplexers conform to the following type, length, value format:
615           * Type Length Value 1 Value2  \85
616           */
617         if (g_mux_obj_ptr->info_field_len > 0) {
618                 msg_start_ptr = g_mux_obj_ptr->info_field;
619                 cmd_type = g_mux_obj_ptr->info_field[0];
620
621                 /* The EA bit is an extension bit. The EA bit is set to 1 in the last octet of the sequence;
622                   * in other octets EA is set to 0.
623                   *
624                   * Search for the last octet
625                   */
626                 while ((*msg_start_ptr++ & 0x01)) { // TBD
627                         msg_len++;
628                 }
629
630                 if ((cmd_type & 0x02) == 0x02) { // This is a command Request
631                         switch (cmd_type) {
632                         case CMUX_COMMAND_MSC:
633                         {
634                                 dbg("Modem Status Command");
635                                 break;
636                         }
637
638                         case CMUX_COMMAND_CLD:
639                         {
640                                 dbg("Multiplexer close down");
641                                 tcore_cmux_close();
642                                 break;
643                         }
644
645                         default:
646                         {
647                                 /* We will be supporting these commands in Phase 2 */
648                                 dbg("Default");
649                                 break;
650                         }
651                         }
652                 }
653         } else {
654                 err("Frame length is less than ZERO");
655         }
656
657         dbg("Exit");
658         return;
659 }
660
661 static void tcore_cmux_process_channel_data(CHANNEL *channel_info_ptr)
662 {
663         int frame_type;
664         int channel_id;
665         int len;
666         unsigned char *send_data = NULL;
667         static int count = 0;
668         int ret;
669
670         dbg("Entry");
671
672         channel_id = channel_info_ptr->channel_id;
673         dbg("Channel ID: %d", channel_id);
674
675         frame_type = channel_info_ptr->frame_type & 0xEF;
676         dbg("frame_type: 0x%x", frame_type);
677
678         switch (frame_type) {
679         case CMUX_COMMAND_UI:
680         case CMUX_COMMAND_UIH:
681         {
682                 dbg("Received UI/UIH Frame");
683                 if (0 == channel_id) {              /* This is control info */
684                         dbg("Control information");
685                         tcore_cmux_control_channel_handle();
686                 } else {
687                         dbg("Normal information");
688                         // put in the logical HAL queue, this goes to the Cobject
689                         tcore_cmux_recv_mux_data(channel_info_ptr);
690                 }
691                 break;
692         }
693
694         case CMUX_COMMAND_UA:
695         {
696                 dbg("Received UA Frame");
697                 dbg("channel_info_ptr->state: %d", channel_info_ptr->state);
698                 if (MUX_CHANNEL_SABM_SEND_WAITING_FOR_UA == channel_info_ptr->state) {
699                         channel_info_ptr->state = MUX_CHANNEL_ESTABLISHED;
700
701                         count++;
702                         dbg("Count: %d", count);
703                         if (MAX_CMUX_CHANNELS_SUPPORTED == count) {
704                                 /* Indicate to CoreObject */
705                                 CoreObject *co = NULL;
706
707                                 /* 'modem' Core Object */
708                                 co = g_mux_obj_ptr->modem_co;
709                                 if (NULL == co) {
710                                         err("'modem' Core object is not present");
711                                         return;
712                                 }
713
714                                 /* Emit callback */
715                                 dbg("Emit Core object callback");
716                                 tcore_object_emit_callback(co, "CMUX-UP", NULL);
717                                 dbg("Emitted Core object callback");
718
719                                 /* Reset 'count' */
720                                 count = 0;
721                         }
722                 } else if (MUX_CHANNEL_DISC_SEND_WAITING_FOR_UA == channel_info_ptr->state) {
723                         channel_info_ptr->state = MUX_CHANNEL_CLOSED;
724
725                         if (0 == channel_id) {
726                                 g_mux_obj_ptr->state = MUX_CLOSED;
727                                 tcore_cmux_close();
728                         }
729                 } else {
730                         err("Received UA in wrong state!!!");
731                 }
732                 break;
733         }
734
735         case CMUX_COMMAND_DM:
736         {
737                 /* 5.4.1 DLC Establishment : If the responding station is not ready or unwilling
738                   * to establish the particular DLC it will reply with a DM frame with the
739                   * F-bit set to 1.
740                   */
741                 dbg("Received DM Frame");
742                 if ((MUX_CHANNEL_ESTABLISHED == channel_info_ptr->state)
743                         || (MUX_CHANNEL_SABM_SEND_WAITING_FOR_UA == channel_info_ptr->state)) {
744                         /* Channel State set to Close */
745                         channel_info_ptr->state = MUX_CHANNEL_CLOSED;
746                 }
747
748                 /* Flush the Channel data */
749                 tcore_cmux_flush_channel_data();
750
751                 break;
752         }
753
754         case CMUX_COMMAND_DISC:
755         {
756                 dbg("Received DISC Frame");
757                 if (0 == channel_info_ptr->poll_final_bit) {
758                         /* In the case where a CMUX_COMMAND_SABM or CMUX_COMMAND_DISC command with
759                           * the P bit set to 0 is received then the received frame shall be discarded.
760                           */
761
762                         /* Flush the Channel data */
763                         tcore_cmux_flush_channel_data();
764                 } else {
765                         if (MUX_CHANNEL_CLOSED == channel_info_ptr->state) {
766                                 /* If a CMUX_COMMAND_DISC command is received while in disconnected mode
767                                   * a CMUX_COMMAND_DM response should be sent
768                                   */
769
770                                 /* Encoding frame */
771                                 send_data = tcore_encode_cmux_frame(NULL, 0, channel_id, CMUX_COMMAND_DM, 1, 1, 1, &len);
772                         } else {         // send Unnumbered Acknowledgement
773                                 send_data = tcore_encode_cmux_frame(NULL, 0, channel_id, CMUX_COMMAND_UA, 1, 1, 1, &len);
774                         }
775
776                         if (0 == len) {
777                                 err("Failed to encode");
778                                 return;
779                         }
780
781                         /* Send CMUX data */
782                         ret = tcore_cmux_send_data(len, send_data);
783
784                         /* Flush the Channel data */
785                         tcore_cmux_flush_channel_data();
786
787                         /* 5.3.4 Disconnect (DISC) command: CMUX_COMMAND_DISC command sent at DLCI 0
788                           * have the same meaning as the Multiplexer Close Down command
789                           */
790                         if (0 == channel_id) {
791                                 g_mux_obj_ptr->state = MUX_CLOSED;
792
793                                 /* Close CMUX */
794                                 tcore_cmux_close();
795                         }
796                 }
797                 break;
798         }
799
800         case CMUX_COMMAND_SABM:
801         {
802                 dbg("Received SABM Frame");
803                 if (0 == channel_info_ptr->poll_final_bit) {
804                         /* In the case where a CMUX_COMMAND_SABM or CMUX_COMMAND_DISC command with
805                           * the P bit set to 0 is received then the received frame shall be discarded.
806                           */
807
808                         /* Flush the Channel data */
809                         tcore_cmux_flush_channel_data();
810                 } else {
811                         /* Encoding frame */
812                         send_data = tcore_encode_cmux_frame(NULL, 0, channel_id, CMUX_COMMAND_UA, 1, 1, 1, &len);
813                         if (0 != len) {
814                                 /* Send CMUX data */
815                                 ret = tcore_cmux_send_data(len, send_data);
816                         } else {
817                                 err("Failed to encode");
818                         }
819
820                         if (channel_info_ptr->state != MUX_CHANNEL_ESTABLISHED) {
821                                 /* Channel State set to Established */
822                                 channel_info_ptr->state = MUX_CHANNEL_ESTABLISHED;
823                         }
824                 }
825                 break;
826         }
827         }
828
829         dbg("Exit");
830         return;
831 }
832
833 static void tcore_cmux_process_rcv_frame(unsigned char *data, int len)
834 {
835         unsigned char *frame_process_ptr = data;
836         unsigned char *buf_start_ptr = data;
837
838         CHANNEL *ch = NULL;
839         unsigned char channel_id;
840         int header_length;
841
842         dbg("Entry");
843
844         tcore_cmux_flush_channel_data();
845
846         /* Get the Channel ID : 1st byte will be flag (F9)..Flag checking is already done.*/
847         channel_id = (*++frame_process_ptr >> 2) & 0x3F;
848
849         if (channel_id < MAX_CMUX_CHANNELS_SUPPORTED) {          // max channel is 8
850                 ch = g_mux_obj_ptr->channel_info[channel_id];
851
852                 ch->channel_id = channel_id;
853
854                 // get the EA bit
855                 ch->ext_bit = *frame_process_ptr & 0x01;
856
857                 // get the CR bit
858                 ch->cr_bit = (*frame_process_ptr++ >> 1) & 0x01;
859
860                 // get the Frame Type
861                 ch->frame_type = *frame_process_ptr++;
862
863                 // get the poll/Final bit
864                 ch->poll_final_bit = (ch->frame_type & 0x10) >> 4;
865
866                 // get the length . TBD
867                 dbg("*frame_process_ptr: %02x", *frame_process_ptr);
868                 dbg("*(frame_process_ptr+1): %02x", *(frame_process_ptr+1));
869                 if (*frame_process_ptr & 0x01) {                        // if, len < 127
870                         dbg("Length < 127");
871                         g_mux_obj_ptr->info_field_len = *frame_process_ptr++ >> 1;
872                         header_length = 3;
873                 } else {
874                         dbg("Length > 127");
875                         g_mux_obj_ptr->info_field_len = *(frame_process_ptr + 1) << 7;
876                         g_mux_obj_ptr->info_field_len = g_mux_obj_ptr->info_field_len | ((*frame_process_ptr++ & 0xFE) >> 1);
877                         header_length = 4;
878                         frame_process_ptr++;
879                 }
880                 dbg("info_field_len: %d", g_mux_obj_ptr->info_field_len);
881
882                 /* Copy received information field */
883                 memcpy(g_mux_obj_ptr->info_field, frame_process_ptr, g_mux_obj_ptr->info_field_len);
884
885                 frame_process_ptr = frame_process_ptr + g_mux_obj_ptr->info_field_len;
886
887                 // CRC check of the header
888                 if (rcv_crc_check(buf_start_ptr + 1, header_length, *frame_process_ptr)) {
889                         dbg("Calling tcore_cmux_process_channel_data");
890                         tcore_cmux_process_channel_data(ch);
891                 } else {
892                         err("CRC check of the header FAILED.. Drop the packet !!");
893                 }
894         } else {
895                 err("Incorrect channel... Drop the packet !!");
896         }
897
898         dbg("Exit");
899         return;
900 }
901
902 int tcore_cmux_rcv_from_hal(unsigned char *data, size_t length)
903 {
904         #define TCORE_MUX_DECODE_FLAG_HUNT 0
905         #define TCORE_MUX_DECODE_ADDR_HUNT 1
906         #define TCORE_MUX_DECODE_CONTROL_HUNT 2
907         #define TCORE_MUX_DECODE_LENGTH1_HUNT 3
908         #define TCORE_MUX_DECODE_LENGTH2_HUNT 4
909         #define TCORE_MUX_DECODE_DATA_HUNT 5
910         #define TCORE_MUX_DECODE_FCS_HUNT 6
911
912         static int decode_state = TCORE_MUX_DECODE_FLAG_HUNT;
913         static unsigned char dec_fcs = 0xff;
914         static unsigned char mux_buffer[4096];
915         static unsigned char* dec_data = mux_buffer;
916         static unsigned short dec_length = 0;
917         static size_t full_frame_len = 0;
918
919         size_t pos = -1;
920         int cp_len = 0;
921
922 DECODE_STATE_CHANGE:
923         if (++pos >= length)
924         {
925                 return 1;
926         }
927
928         switch(decode_state)
929         {
930         case TCORE_MUX_DECODE_FLAG_HUNT: full_frame_len = 0; dec_length = 0; dec_fcs = 0xff; dec_data = mux_buffer; goto FLAG_HUNT; break;
931         case TCORE_MUX_DECODE_ADDR_HUNT: goto ADDR_HUNT; break;
932         case TCORE_MUX_DECODE_CONTROL_HUNT: goto CONTROL_HUNT; break;
933         case TCORE_MUX_DECODE_LENGTH1_HUNT: goto LENGTH1_HUNT; break;
934         case TCORE_MUX_DECODE_LENGTH2_HUNT: goto LENGTH2_HUNT; break;
935         case TCORE_MUX_DECODE_DATA_HUNT: goto DATA_HUNT; break;
936         case TCORE_MUX_DECODE_FCS_HUNT: goto FCS_HUNT; break;
937         }
938
939 FLAG_HUNT:
940         while (data[pos] != 0xF9) {
941                 if (++pos >= length) {
942                         return 1;
943                 }
944         }
945         decode_state = TCORE_MUX_DECODE_ADDR_HUNT;
946         goto DECODE_STATE_CHANGE;
947
948 ADDR_HUNT:
949         while (data[pos] == 0xF9) {
950                 if (++pos >= length) {
951                         return 1;
952                 }
953         }
954
955         dec_fcs = crc_table[dec_fcs^data[pos]];
956         decode_state = TCORE_MUX_DECODE_CONTROL_HUNT;
957         *dec_data++ = 0xF9;
958         *dec_data++ = data[pos];
959         full_frame_len += 2;
960         goto DECODE_STATE_CHANGE;
961
962 CONTROL_HUNT:
963         dec_fcs = crc_table[dec_fcs^data[pos]];
964         decode_state = TCORE_MUX_DECODE_LENGTH1_HUNT;
965         *dec_data++ = data[pos];
966         full_frame_len++;
967         goto DECODE_STATE_CHANGE;
968
969 LENGTH1_HUNT:
970         dec_length = data[pos] >> 1;
971         dec_fcs = crc_table[dec_fcs^data[pos]];
972         if (data[pos] & 0x1)
973         { // ea
974                 if (dec_length > 0)
975                 {
976                         decode_state = TCORE_MUX_DECODE_DATA_HUNT;
977                 }
978                 else
979                 {
980                         decode_state = TCORE_MUX_DECODE_FCS_HUNT;
981                 }
982         }
983         else
984         {
985                 decode_state = TCORE_MUX_DECODE_LENGTH2_HUNT;
986         }
987
988         *dec_data++ = data[pos];
989         full_frame_len++;
990         goto DECODE_STATE_CHANGE;
991
992 LENGTH2_HUNT:
993         dec_length |= ((unsigned short)data[pos] << 7);
994         dec_fcs = crc_table[dec_fcs^data[pos]];
995         decode_state = TCORE_MUX_DECODE_DATA_HUNT;
996         *dec_data++ = data[pos];
997         full_frame_len++;
998         goto DECODE_STATE_CHANGE;
999
1000 DATA_HUNT:
1001         if (dec_length < (length - pos)) // frame data fully available in the buffer
1002         {
1003                 cp_len = dec_length;
1004                 decode_state = TCORE_MUX_DECODE_FCS_HUNT;
1005         }
1006         else    // frame data partially available in the buffer
1007         {
1008                 cp_len = (length - pos);
1009                 decode_state = TCORE_MUX_DECODE_DATA_HUNT;
1010         }
1011
1012         memcpy(dec_data, data + pos, cp_len);
1013         dec_data += cp_len;
1014         pos += (cp_len - 1);
1015         dec_length -= cp_len;
1016         full_frame_len += cp_len;
1017
1018         goto DECODE_STATE_CHANGE;
1019
1020 FCS_HUNT:
1021         //if (crc_table[dec_fcs^data[pos]] == 0xCF) // valid FCS, store frame.
1022         {
1023                 *dec_data++ = data[pos];
1024                 *dec_data++ = 0xF9;
1025                 full_frame_len += 2;
1026                 tcore_cmux_process_rcv_frame(mux_buffer, full_frame_len);
1027         }
1028
1029         // enter flag hunt mode
1030         decode_state = TCORE_MUX_DECODE_FLAG_HUNT;
1031         goto DECODE_STATE_CHANGE;
1032 }
1033
1034 static void tcore_cmux_channel_init(CMUX_Channels channel_id)
1035 {
1036         CHANNEL *ch = NULL;
1037
1038         ch = g_mux_obj_ptr->channel_info[channel_id];
1039         memset(ch, 0x0, sizeof(CHANNEL));
1040
1041         ch->channel_id = channel_id;
1042         ch->state = MUX_CHANNEL_SABM_SEND_WAITING_FOR_UA;
1043
1044         ch->co = NULL;
1045         ch->hal = NULL;
1046
1047         /* TODO - Check if required */
1048         ch->frame_type = CMUX_COMMAND_SABM;
1049         ch->ext_bit = 0x01;
1050         ch->cr_bit = 0x01;
1051         ch->poll_final_bit = 0x01;
1052
1053         dbg("Channel ID %d initialized", channel_id);
1054
1055         return;
1056 }
1057
1058 static void tcore_cmux_close_channel(int channel_id)
1059 {
1060         CHANNEL *ch = NULL;
1061         unsigned char *send_data = NULL;
1062         int ret, len = 0;
1063
1064         dbg("Entry");
1065
1066         ch = g_mux_obj_ptr->channel_info[channel_id];
1067
1068         if (ch->state != MUX_CHANNEL_CLOSED) {
1069                 ch->frame_type = CMUX_COMMAND_DISC;
1070                 ch->ext_bit = 0x01;
1071                 ch->cr_bit = 0x01;
1072                 ch->state = MUX_CHANNEL_DISC_SEND_WAITING_FOR_UA;
1073
1074                 /* Send DSC command */
1075                 /* Encoding frame */
1076                 send_data = tcore_encode_cmux_frame(NULL, 0, channel_id, CMUX_COMMAND_DISC, 0x01, 0x01, 0x01, &len);
1077                 if (0 != len) {
1078                         /* Send CMUX data */
1079                         ret = tcore_cmux_send_data(len, send_data);
1080                 } else {
1081                         err("Failed to encode");
1082                 }
1083         } else {
1084                 /* Channel is already closed */
1085                 err("Channel is already closed");
1086         }
1087
1088         dbg("Exit");
1089         return;
1090 }
1091
1092 static void tcore_cmux_free(void)
1093 {
1094         int channel;
1095
1096         dbg("Entry");
1097
1098         if (g_mux_obj_ptr) {
1099                 /* Free Information Field */
1100                 if (g_mux_obj_ptr->info_field) {
1101                         free(g_mux_obj_ptr->info_field);
1102                         g_mux_obj_ptr->info_field = NULL;
1103                 }
1104
1105                 for (channel = 0; channel < MAX_CMUX_CHANNELS_SUPPORTED; channel++) {
1106                         /* Free Channel Information */
1107                         if (g_mux_obj_ptr->channel_info[channel]) {
1108                                 free(g_mux_obj_ptr->channel_info[channel]);
1109                                 g_mux_obj_ptr->channel_info[channel] = NULL;
1110                         }
1111                 }
1112
1113                 /* Free MUX Object */
1114                 free(g_mux_obj_ptr);
1115                 g_mux_obj_ptr = NULL;
1116         } else {
1117                 err("MUX Object doesn't exist");
1118         }
1119
1120         dbg("Exit");
1121         return;
1122 }
1123
1124 TReturn tcore_cmux_init(TcorePlugin *plugin, TcoreHal *hal)
1125 {
1126         unsigned char *data = NULL;
1127         int data_len = 0;
1128
1129         int index;
1130
1131         TReturn ret = TCORE_RETURN_SUCCESS;
1132
1133         dbg("Entry");
1134
1135         dbg("Physical HAL: %x", (unsigned int)hal);
1136
1137         /* Creat new CMUX Object */
1138         g_mux_obj_ptr = tcore_cmux_new();
1139         if (NULL == g_mux_obj_ptr) {
1140                 err("Failed to create MUX object");
1141
1142                 ret = TCORE_RETURN_FAILURE;
1143                 goto ERROR;
1144         }
1145
1146         /* Save Plugin */
1147         g_mux_obj_ptr->plugin = plugin;
1148
1149         /* Save Physical HAL */
1150         g_mux_obj_ptr->phy_hal = hal;
1151
1152         /* Setting Receive callback function for data received from Physical HAL */
1153         g_mux_obj_ptr->cb_func = tcore_cmux_recv_mux_data;
1154
1155         /* After MUX setup, AT parse functionality of PHY HAL should be disabled,
1156           * here we change the mode of PHYSICAL HAL to Transparent.
1157           */
1158         tcore_hal_set_mode(g_mux_obj_ptr->phy_hal, TCORE_HAL_MODE_TRANSPARENT);
1159         dbg("Physical HAL mode changed to Transparent");
1160
1161         /* Initialize all the Channels */
1162         /* Open all Channels */
1163         for (index = 0; index < MAX_CMUX_CHANNELS_SUPPORTED; index++) {
1164                 dbg("Initialize the Channel %d", index);
1165                 tcore_cmux_channel_init((CMUX_Channels) index);
1166
1167                 dbg("Opening Channel %d", index);
1168                 /* Encode CMUX Frame */
1169                 data = tcore_encode_cmux_frame(NULL, 0, index, CMUX_COMMAND_SABM, 0x01, 0x01, 0x01, &data_len);
1170                 if (0 == data_len) {
1171                         err("Failed to encode");
1172
1173                         ret = TCORE_RETURN_FAILURE;
1174                         goto ERROR;
1175                 }
1176                 dbg("data_len: %d data: %s", data_len, data);
1177
1178                 /* Send CMUX data */
1179                 tcore_cmux_send_data(data_len, data);
1180                 dbg("CMUX Control Request sent to CP");
1181
1182                 /* Set Core object and HAL */
1183                 tcore_cmux_link_core_object_hal((CMUX_Channels) index, plugin);
1184         }
1185
1186         dbg("Exit");
1187         return ret;
1188
1189 ERROR:
1190         /* Free the allocated CMUX memory */
1191         tcore_cmux_free();
1192
1193         err("Exit");
1194         return ret;
1195 }
1196
1197 void tcore_cmux_close(void)
1198 {
1199         int channel = 0;
1200         int index = 0;
1201         CoreObject *co = NULL;
1202         GSList *co_list = NULL;
1203
1204         dbg("Entry");
1205
1206         for (channel = 0; channel < MAX_CMUX_CHANNELS_SUPPORTED; channel++) {
1207                 dbg("Channel ID: %d", channel);
1208                 index = 0;
1209
1210                 /* Close Channel - Send DSC command */
1211                 tcore_cmux_close_channel(channel);
1212
1213                 /* Revert Physical HAL as HAL of each Core Object associated to this Channel */
1214                 while (NULL != cmux_channel_core_object[channel].core_object_name[index]) {
1215                         co = NULL;
1216
1217                         /* Core Objects list */
1218                         co_list = g_mux_obj_ptr->channel_info[channel]->co;
1219                         dbg("Core Objects list : %p", co_list);
1220
1221                         /* Core Object list may contain multiple Core Objects.
1222                           * Revert to Physical HAL for each of the Core Objects associated
1223                           * with this Channel
1224                           */
1225                         while (NULL != co_list) {
1226                                 if (NULL != co_list->data) {
1227                                         if (!strcmp((const char *) cmux_channel_core_object[channel].core_object_name[index], (const char *) tcore_object_ref_name((CoreObject *) co_list->data))) {
1228                                                 co = (CoreObject *) co_list->data;
1229                                                 dbg("Core Object found ");
1230                                                 break;
1231                                         }
1232                                 }
1233
1234                                 /* To next Core Object in the list */
1235                                 co_list = co_list->next;
1236                         }
1237
1238                         /* Set the previous Physical HAL as HAL for Core Object */
1239                         if (NULL != co) {
1240                                 tcore_object_set_hal(co, g_mux_obj_ptr->phy_hal);
1241                         } else {
1242                                 /* Proceed to next Channel */
1243                                 err("No more Core Objects present in this Channel");
1244                                 break;
1245                         }
1246
1247                         /* To next Core Object */
1248                         index++;
1249                 }
1250
1251                 /* Free Logical HAL for Channel */
1252                 tcore_hal_free(g_mux_obj_ptr->channel_info[channel]->hal);
1253                 g_mux_obj_ptr->channel_info[channel]->hal = NULL;
1254         }
1255
1256         /* Change the mode of PHYSICAL HAL to Custom */
1257         tcore_hal_set_mode(g_mux_obj_ptr->phy_hal, TCORE_HAL_MODE_AT);
1258
1259         /* Free all the allocated memory */
1260         tcore_cmux_free();
1261
1262         dbg("Exit");
1263         return;
1264 }