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