4 * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Arijit Sen <arijit.sen@samsung.com>
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
32 #include "user_request.h"
35 #include "core_object.h"
37 /* Maximum Core objects per Logical HAL (indirectly per Channel) */
38 #define MAX_CMUX_CORE_OBJECTS 3
40 /* Max CMUX Buffer size */
41 #define MAX_CMUX_BUFFER_SIZE 4096
43 /* Max muber of CMUX Channels */
44 #define MAX_CMUX_CHANNELS_SUPPORTED 8
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
54 /* MUX CONTROL COMMANDS
55 * We are supporting only MSC command for phase 1
57 #define CMUX_COMMAND_MSC 0xE3 // Modem Status Command
58 #define CMUX_COMMAND_CLD 0xC3 // Multiplexer close down
60 /* CMUX Channels [0-7] -
61 * Channel 0 - Control Channel for CMUX
68 * Channel 7 - MODEM & PS
70 typedef enum CMUX_Channels {
81 /* MUX Channel States */
82 typedef enum MuxChannelState {
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,
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,
97 typedef enum MuxState {
103 #define FIND_LENGTH(buf, header_length, total_length) do { \
105 total_length = *buf++ >> 1; \
109 total_length = *(buf + 0x01) << 7; \
110 total_length = total_length | (*buf & 0xFE) >> 1; \
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
134 /*================= CRC TABLE=========================*/
137 typedef struct cmux_channel {
140 MuxChannelState state;
141 CMUX_Channels channel_id;
143 unsigned char ext_bit;
144 unsigned char cr_bit;
145 unsigned char poll_final_bit;
148 /* CMUX callback prototype */
149 typedef gboolean (*mux_cb_func)(CHANNEL *channel_ptr);
152 typedef struct cmux {
154 CHANNEL *channel_info[MAX_CMUX_CHANNELS_SUPPORTED];
157 int cur_main_buf_len;
160 CoreObject *modem_co;
163 unsigned char *info_field;
166 /* Global pointer MUX Object pointer */
167 MUX *g_mux_obj_ptr = NULL;
169 /* CMUX mode of operation */
170 int g_mux_mode = 0; /* BASIC mode */
172 struct cmux_channel_object {
173 char *channel_id_name;
174 char *core_object_name[MAX_CMUX_CORE_OBJECTS];
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}},
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);
205 static TReturn tcore_cmux_hal_power(TcoreHal *h, gboolean flag)
207 TcorePlugin *p = NULL;
208 struct custom_data *user_data = NULL;
212 p = tcore_hal_ref_plugin(h);
214 err("Plugin is undefined");
215 return TCORE_RETURN_FAILURE;
218 user_data = tcore_hal_ref_user_data(h);
220 err("User data is undefined");
221 return TCORE_RETURN_FAILURE;
224 tcore_hal_set_power_state(h, TRUE);
227 return TCORE_RETURN_SUCCESS;
230 static TReturn tcore_cmux_hal_send(TcoreHal *h, unsigned int data_len, void *data)
232 unsigned char *send_data = NULL;
233 char *channel_name = NULL;
234 int channel_id = MAX_CMUX_CHANNELS_SUPPORTED;
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;
247 channel_name = tcore_hal_get_name(h);
248 dbg("HAL name: %s", 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)) {
253 dbg("Found Channel ID: %d", channel_id);
262 err("No name defined for HAL");
263 return TCORE_RETURN_FAILURE;
266 if (channel_id > MAX_CMUX_CHANNELS_SUPPORTED) {
267 err("Failed to find Channel ID");
268 return TCORE_RETURN_FAILURE;
271 /* Muxing operation and Frame creation */
273 send_data = tcore_encode_cmux_frame(data, data_len, channel_id, CMUX_COMMAND_UIH, 1, 1, 0, &len);
275 err("Failed to encode");
276 return TCORE_RETURN_FAILURE;
280 ret = tcore_cmux_send_data(len, send_data);
283 return TCORE_RETURN_SUCCESS;
286 static TReturn tcore_cmux_hal_setup_netif(CoreObject *co,
287 TcoreHalSetupNetifCallback func,
288 void *user_data, unsigned int cid,
291 TcoreHal *hal = g_mux_obj_ptr->phy_hal;
294 return TCORE_RETURN_EINVAL;
296 return tcore_hal_setup_netif(hal, co, func, user_data, cid, enable);
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,
306 static TReturn tcore_cmux_send_data(int data_len, unsigned char *data)
308 TReturn ret = TCORE_RETURN_SUCCESS;
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");
317 dbg("Successfully sent CMUX data");
323 static gboolean tcore_cmux_recv_mux_data(CHANNEL *channel_ptr)
325 TcoreHal *hal = NULL;
329 /* Dereferencing HAL from Channel Pointer */
330 hal = channel_ptr->hal;
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);
339 void tcore_cmux_link_core_object_hal(CMUX_Channels channel_id, TcorePlugin *plugin)
341 TcoreHal *hal = NULL;
342 CoreObject *co = NULL;
347 if (CMUX_CHANNEL_0 != channel_id) {
348 dbg("Normal channel [%d]", channel_id);
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);
354 /* Update Logical HAL of CMUX Channel */
355 g_mux_obj_ptr->channel_info[channel_id]->hal = hal;
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]);
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");
369 /* Set Logical HAL to Core objects */
370 tcore_object_set_hal(co, hal);
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);
375 /* Next Core Object of the channel */
379 /* Control Channel */
380 dbg("Control channel");
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);
386 /* Update Logical HAL of CMUX Channel */
387 g_mux_obj_ptr->channel_info[channel_id]->hal = hal;
390 /* Set Logical HAL Power State to TRUE */
391 tcore_hal_set_power_state(hal, TRUE);
392 dbg("HAL Power is SET");
398 MUX* tcore_cmux_new(void)
403 /* Allocating memory for mux */
404 mux = (MUX *) calloc(1, sizeof(MUX));
406 err("Failed to allocate memory");
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");
417 /* MUX State initialize to MUX_NOT_INITIALIZED */
418 mux->state = MUX_NOT_INITIALIZED;
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);
433 /* Free allocated memory */
435 if (mux->info_field) {
436 free(mux->info_field);
439 for (i = 0; i < MAX_CMUX_CHANNELS_SUPPORTED; i++) {
440 if (mux->channel_info[i]) {
441 free(mux->channel_info[i]);
452 static unsigned char calc_crc(unsigned char *header, int length)
454 unsigned char FCS = 0xFF; /*Init*/
455 unsigned char crc = 0x00;
457 /* 'length' is the number of bytes in the message, 'header' points to message */
459 FCS = crc_table[FCS ^ *header++];
465 dbg("Exit - crc: 0x%02x", crc)
469 static unsigned char* tcore_encode_cmux_frame(unsigned char *data,
473 unsigned char EA_bit,
474 unsigned char CR_bit,
475 unsigned char PF_bit,
478 int frame_length = 0;
479 int total_frame_length = 0;
484 /* Flush channel data */
485 tcore_cmux_flush_channel_data();
487 if (length > MAX_CMUX_BUFFER_SIZE) {
488 err("Length - %d exceeds the limit", length);
493 g_mux_obj_ptr->info_field[frame_length++] = (char) 0xF9;
495 /* Mode of Operation */
496 if (0x00 == g_mux_mode) { /* BASIC */
498 * C/R: Command Response
500 g_mux_obj_ptr->info_field[frame_length] = g_mux_obj_ptr->info_field[frame_length] | ((EA_bit & 0x01) | ((CR_bit << 1) & 0x02));
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);
508 err("Channel is out of range[0-8]");
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 *****************************************************************/
524 g_mux_obj_ptr->info_field[frame_length++] = frame_type | 0x10;
526 g_mux_obj_ptr->info_field[frame_length++] = frame_type;
529 /* 5.2.1.5 Length Indicator */
531 g_mux_obj_ptr->info_field[frame_length++] = (char) length << 1 | 0x01;
533 /* CRC calculatable length */
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
539 /* CRC calculatable length */
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.
548 /* 5.2.1.4 Information Field*/
550 memcpy((g_mux_obj_ptr->info_field + frame_length), data, length);
551 frame_length += length;
553 dbg("info field length is zero");
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);
560 g_mux_obj_ptr->info_field[frame_length++] = 0xF9;
562 total_frame_length = frame_length;
563 } else if (0x01 == g_mux_mode) { /* TBD MUX_MODE_ADVANCE */
564 dbg("Advanced MUX mode : TBD");
567 *out_data_len = total_frame_length;
568 dbg("*out_data_len: %d", *out_data_len);
570 dbg("Exit total_frame_length: %d", total_frame_length);
571 return g_mux_obj_ptr->info_field;
574 static int rcv_crc_check(unsigned char *data, unsigned char len, unsigned char rcv_FCS)
576 unsigned char FCS = 0xFF;
578 /* 'len' is the number of bytes in the message, 'data' points to message */
580 FCS = crc_table[FCS ^ *data++];
584 FCS = crc_table[FCS ^ rcv_FCS];
586 /* 0xCF is the reversed order of 11110011 */
587 if (0xCF == FCS) { /* FCS is OK */
589 } else { /* FCS is NOT OK */
594 static void tcore_cmux_flush_channel_data(void)
598 g_mux_obj_ptr->info_field_len = 0x0;
599 memset(g_mux_obj_ptr->info_field, 0x0, MAX_CMUX_BUFFER_SIZE);
605 static void tcore_cmux_control_channel_handle(void)
607 unsigned char cmd_type;
609 unsigned char *msg_start_ptr = NULL;
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
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];
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.
624 * Search for the last octet
626 while ((*msg_start_ptr++ & 0x01)) { // TBD
630 if ((cmd_type & 0x02) == 0x02) { // This is a command Request
632 case CMUX_COMMAND_MSC:
634 dbg("Modem Status Command");
638 case CMUX_COMMAND_CLD:
640 dbg("Multiplexer close down");
647 /* We will be supporting these commands in Phase 2 */
654 err("Frame length is less than ZERO");
661 static void tcore_cmux_process_channel_data(CHANNEL *channel_info_ptr)
666 unsigned char *send_data = NULL;
667 static int count = 0;
672 channel_id = channel_info_ptr->channel_id;
673 dbg("Channel ID: %d", channel_id);
675 frame_type = channel_info_ptr->frame_type & 0xEF;
676 dbg("frame_type: 0x%x", frame_type);
678 switch (frame_type) {
679 case CMUX_COMMAND_UI:
680 case CMUX_COMMAND_UIH:
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();
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);
694 case CMUX_COMMAND_UA:
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;
702 dbg("Count: %d", count);
703 if (MAX_CMUX_CHANNELS_SUPPORTED == count) {
704 /* Indicate to CoreObject */
705 CoreObject *co = NULL;
707 /* 'modem' Core Object */
708 co = g_mux_obj_ptr->modem_co;
710 err("'modem' Core object is not present");
715 dbg("Emit Core object callback");
716 tcore_object_emit_callback(co, "CMUX-UP", NULL);
717 dbg("Emitted Core object callback");
722 } else if (MUX_CHANNEL_DISC_SEND_WAITING_FOR_UA == channel_info_ptr->state) {
723 channel_info_ptr->state = MUX_CHANNEL_CLOSED;
725 if (0 == channel_id) {
726 g_mux_obj_ptr->state = MUX_CLOSED;
730 err("Received UA in wrong state!!!");
735 case CMUX_COMMAND_DM:
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
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;
748 /* Flush the Channel data */
749 tcore_cmux_flush_channel_data();
754 case CMUX_COMMAND_DISC:
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.
762 /* Flush the Channel data */
763 tcore_cmux_flush_channel_data();
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
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);
777 err("Failed to encode");
782 ret = tcore_cmux_send_data(len, send_data);
784 /* Flush the Channel data */
785 tcore_cmux_flush_channel_data();
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
790 if (0 == channel_id) {
791 g_mux_obj_ptr->state = MUX_CLOSED;
800 case CMUX_COMMAND_SABM:
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.
808 /* Flush the Channel data */
809 tcore_cmux_flush_channel_data();
812 send_data = tcore_encode_cmux_frame(NULL, 0, channel_id, CMUX_COMMAND_UA, 1, 1, 1, &len);
815 ret = tcore_cmux_send_data(len, send_data);
817 err("Failed to encode");
820 if (channel_info_ptr->state != MUX_CHANNEL_ESTABLISHED) {
821 /* Channel State set to Established */
822 channel_info_ptr->state = MUX_CHANNEL_ESTABLISHED;
833 static void tcore_cmux_process_rcv_frame(unsigned char *data, int len)
835 unsigned char *frame_process_ptr = data;
836 unsigned char *buf_start_ptr = data;
839 unsigned char channel_id;
844 tcore_cmux_flush_channel_data();
846 /* Get the Channel ID : 1st byte will be flag (F9)..Flag checking is already done.*/
847 channel_id = (*++frame_process_ptr >> 2) & 0x3F;
849 if (channel_id < MAX_CMUX_CHANNELS_SUPPORTED) { // max channel is 8
850 ch = g_mux_obj_ptr->channel_info[channel_id];
852 ch->channel_id = channel_id;
855 ch->ext_bit = *frame_process_ptr & 0x01;
858 ch->cr_bit = (*frame_process_ptr++ >> 1) & 0x01;
860 // get the Frame Type
861 ch->frame_type = *frame_process_ptr++;
863 // get the poll/Final bit
864 ch->poll_final_bit = (ch->frame_type & 0x10) >> 4;
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
871 g_mux_obj_ptr->info_field_len = *frame_process_ptr++ >> 1;
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);
880 dbg("info_field_len: %d", g_mux_obj_ptr->info_field_len);
882 /* Copy received information field */
883 memcpy(g_mux_obj_ptr->info_field, frame_process_ptr, g_mux_obj_ptr->info_field_len);
885 frame_process_ptr = frame_process_ptr + g_mux_obj_ptr->info_field_len;
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);
892 err("CRC check of the header FAILED.. Drop the packet !!");
895 err("Incorrect channel... Drop the packet !!");
902 int tcore_cmux_rcv_from_hal(unsigned char *data, size_t length)
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
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;
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;
940 while (data[pos] != 0xF9) {
941 if (++pos >= length) {
945 decode_state = TCORE_MUX_DECODE_ADDR_HUNT;
946 goto DECODE_STATE_CHANGE;
949 while (data[pos] == 0xF9) {
950 if (++pos >= length) {
955 dec_fcs = crc_table[dec_fcs^data[pos]];
956 decode_state = TCORE_MUX_DECODE_CONTROL_HUNT;
958 *dec_data++ = data[pos];
960 goto DECODE_STATE_CHANGE;
963 dec_fcs = crc_table[dec_fcs^data[pos]];
964 decode_state = TCORE_MUX_DECODE_LENGTH1_HUNT;
965 *dec_data++ = data[pos];
967 goto DECODE_STATE_CHANGE;
970 dec_length = data[pos] >> 1;
971 dec_fcs = crc_table[dec_fcs^data[pos]];
976 decode_state = TCORE_MUX_DECODE_DATA_HUNT;
980 decode_state = TCORE_MUX_DECODE_FCS_HUNT;
985 decode_state = TCORE_MUX_DECODE_LENGTH2_HUNT;
988 *dec_data++ = data[pos];
990 goto DECODE_STATE_CHANGE;
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];
998 goto DECODE_STATE_CHANGE;
1001 if (dec_length < (length - pos)) // frame data fully available in the buffer
1003 cp_len = dec_length;
1004 decode_state = TCORE_MUX_DECODE_FCS_HUNT;
1006 else // frame data partially available in the buffer
1008 cp_len = (length - pos);
1009 decode_state = TCORE_MUX_DECODE_DATA_HUNT;
1012 memcpy(dec_data, data + pos, cp_len);
1014 pos += (cp_len - 1);
1015 dec_length -= cp_len;
1016 full_frame_len += cp_len;
1018 goto DECODE_STATE_CHANGE;
1021 //if (crc_table[dec_fcs^data[pos]] == 0xCF) // valid FCS, store frame.
1023 *dec_data++ = data[pos];
1025 full_frame_len += 2;
1026 tcore_cmux_process_rcv_frame(mux_buffer, full_frame_len);
1029 // enter flag hunt mode
1030 decode_state = TCORE_MUX_DECODE_FLAG_HUNT;
1031 goto DECODE_STATE_CHANGE;
1034 static void tcore_cmux_channel_init(CMUX_Channels channel_id)
1038 ch = g_mux_obj_ptr->channel_info[channel_id];
1039 memset(ch, 0x0, sizeof(CHANNEL));
1041 ch->channel_id = channel_id;
1042 ch->state = MUX_CHANNEL_SABM_SEND_WAITING_FOR_UA;
1047 /* TODO - Check if required */
1048 ch->frame_type = CMUX_COMMAND_SABM;
1051 ch->poll_final_bit = 0x01;
1053 dbg("Channel ID %d initialized", channel_id);
1058 static void tcore_cmux_close_channel(int channel_id)
1061 unsigned char *send_data = NULL;
1066 ch = g_mux_obj_ptr->channel_info[channel_id];
1068 if (ch->state != MUX_CHANNEL_CLOSED) {
1069 ch->frame_type = CMUX_COMMAND_DISC;
1072 ch->state = MUX_CHANNEL_DISC_SEND_WAITING_FOR_UA;
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);
1078 /* Send CMUX data */
1079 ret = tcore_cmux_send_data(len, send_data);
1081 err("Failed to encode");
1084 /* Channel is already closed */
1085 err("Channel is already closed");
1092 static void tcore_cmux_free(void)
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;
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;
1113 /* Free MUX Object */
1114 free(g_mux_obj_ptr);
1115 g_mux_obj_ptr = NULL;
1117 err("MUX Object doesn't exist");
1124 TReturn tcore_cmux_init(TcorePlugin *plugin, TcoreHal *hal)
1126 unsigned char *data = NULL;
1131 TReturn ret = TCORE_RETURN_SUCCESS;
1135 dbg("Physical HAL: %x", (unsigned int)hal);
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");
1142 ret = TCORE_RETURN_FAILURE;
1147 g_mux_obj_ptr->plugin = plugin;
1149 /* Save Physical HAL */
1150 g_mux_obj_ptr->phy_hal = hal;
1152 /* Setting Receive callback function for data received from Physical HAL */
1153 g_mux_obj_ptr->cb_func = tcore_cmux_recv_mux_data;
1155 /* After MUX setup, AT parse functionality of PHY HAL should be disabled,
1156 * here we change the mode of PHYSICAL HAL to Transparent.
1158 tcore_hal_set_mode(g_mux_obj_ptr->phy_hal, TCORE_HAL_MODE_TRANSPARENT);
1159 dbg("Physical HAL mode changed to Transparent");
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);
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");
1173 ret = TCORE_RETURN_FAILURE;
1176 dbg("data_len: %d data: %s", data_len, data);
1178 /* Send CMUX data */
1179 tcore_cmux_send_data(data_len, data);
1180 dbg("CMUX Control Request sent to CP");
1182 /* Set Core object and HAL */
1183 tcore_cmux_link_core_object_hal((CMUX_Channels) index, plugin);
1190 /* Free the allocated CMUX memory */
1197 void tcore_cmux_close(void)
1201 CoreObject *co = NULL;
1202 GSList *co_list = NULL;
1206 for (channel = 0; channel < MAX_CMUX_CHANNELS_SUPPORTED; channel++) {
1207 dbg("Channel ID: %d", channel);
1210 /* Close Channel - Send DSC command */
1211 tcore_cmux_close_channel(channel);
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]) {
1217 /* Core Objects list */
1218 co_list = g_mux_obj_ptr->channel_info[channel]->co;
1219 dbg("Core Objects list : %p", co_list);
1221 /* Core Object list may contain multiple Core Objects.
1222 * Revert to Physical HAL for each of the Core Objects associated
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 ");
1234 /* To next Core Object in the list */
1235 co_list = co_list->next;
1238 /* Set the previous Physical HAL as HAL for Core Object */
1240 tcore_object_set_hal(co, g_mux_obj_ptr->phy_hal);
1242 /* Proceed to next Channel */
1243 err("No more Core Objects present in this Channel");
1247 /* To next Core Object */
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;
1256 /* Change the mode of PHYSICAL HAL to Custom */
1257 tcore_hal_set_mode(g_mux_obj_ptr->phy_hal, TCORE_HAL_MODE_AT);
1259 /* Free all the allocated memory */