4 * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
5 * Contact: Arijit Sen <arijit.sen@samsung.com>
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
31 #include "user_request.h"
34 #include "core_object.h"
36 /* Maximum Core objects per Logical HAL (indirectly per Channel) */
37 #define MAX_CMUX_CORE_OBJECTS 3
39 /* Max CMUX Buffer size */
40 #define MAX_CMUX_BUFFER_SIZE 4096
42 /* Max muber of CMUX Channels */
43 #define MAX_CMUX_CHANNELS_SUPPORTED 8
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
53 /* MUX CONTROL COMMANDS
54 * We are supporting only MSC command for phase 1
56 #define CMUX_COMMAND_MSC 0xE3 // Modem Status Command
57 #define CMUX_COMMAND_CLD 0xC3 // Multiplexer close down
59 /* CMUX Channels [0-7] -
60 * Channel 0 - Control Channel for CMUX
67 * Channel 7 - MODEM & PS
69 typedef enum CMUX_Channels {
80 /* MUX Channel States */
81 typedef enum MuxChannelState {
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,
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,
96 typedef enum MuxState {
102 #define FIND_LENGTH(buf, header_length, total_length) do { \
104 total_length = *buf++ >> 1; \
108 total_length = *(buf + 0x01) << 7; \
109 total_length = total_length | (*buf & 0xFE) >> 1; \
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
133 /*================= CRC TABLE=========================*/
136 typedef struct cmux_channel {
139 MuxChannelState state;
140 CMUX_Channels channel_id;
142 unsigned char ext_bit;
143 unsigned char cr_bit;
144 unsigned char poll_final_bit;
147 /* CMUX callback prototype */
148 typedef gboolean (*mux_cb_func)(CHANNEL *channel_ptr);
151 typedef struct cmux {
153 CHANNEL *channel_info[MAX_CMUX_CHANNELS_SUPPORTED];
156 int cur_main_buf_len;
159 CoreObject *modem_co;
162 unsigned char *info_field;
165 /* Global pointer MUX Object pointer */
166 MUX *g_mux_obj_ptr = NULL;
168 /* CMUX mode of operation */
169 int g_mux_mode = 0; /* BASIC mode */
171 struct cmux_channel_object {
172 char *channel_id_name;
173 char *core_object_name[MAX_CMUX_CORE_OBJECTS];
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}},
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);
204 static TReturn tcore_cmux_hal_power(TcoreHal *h, gboolean flag)
206 TcorePlugin *p = NULL;
207 struct custom_data *user_data = NULL;
211 p = tcore_hal_ref_plugin(h);
213 err("Plugin is undefined");
214 return TCORE_RETURN_FAILURE;
217 user_data = tcore_hal_ref_user_data(h);
219 err("User data is undefined");
220 return TCORE_RETURN_FAILURE;
223 tcore_hal_set_power_state(h, TRUE);
226 return TCORE_RETURN_SUCCESS;
229 static TReturn tcore_cmux_hal_send(TcoreHal *h, unsigned int data_len, void *data)
231 unsigned char *send_data = NULL;
232 char *channel_name = NULL;
233 int channel_id = MAX_CMUX_CHANNELS_SUPPORTED;
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;
246 channel_name = tcore_hal_get_name(h);
247 dbg("HAL name: %s", 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)) {
252 dbg("Found Channel ID: %d", channel_id);
261 err("No name defined for HAL");
262 return TCORE_RETURN_FAILURE;
265 if (channel_id > MAX_CMUX_CHANNELS_SUPPORTED) {
266 err("Failed to find Channel ID");
267 return TCORE_RETURN_FAILURE;
270 /* Muxing operation and Frame creation */
272 send_data = tcore_encode_cmux_frame(data, data_len, channel_id, CMUX_COMMAND_UIH, 1, 1, 0, &len);
274 err("Failed to encode");
275 return TCORE_RETURN_FAILURE;
279 ret = tcore_cmux_send_data(len, send_data);
282 return TCORE_RETURN_SUCCESS;
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,
291 static TReturn tcore_cmux_send_data(int data_len, unsigned char *data)
293 TReturn ret = TCORE_RETURN_SUCCESS;
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");
302 dbg("Successfully sent CMUX data");
308 static gboolean tcore_cmux_recv_mux_data(CHANNEL *channel_ptr)
310 TcoreHal *hal = NULL;
314 /* Dereferencing HAL from Channel Pointer */
315 hal = channel_ptr->hal;
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);
324 void tcore_cmux_link_core_object_hal(CMUX_Channels channel_id, TcorePlugin *plugin)
326 TcoreHal *hal = NULL;
327 CoreObject *co = NULL;
332 if (CMUX_CHANNEL_0 != channel_id) {
333 dbg("Normal channel [%d]", channel_id);
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);
339 /* Update Logical HAL of CMUX Channel */
340 g_mux_obj_ptr->channel_info[channel_id]->hal = hal;
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]);
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");
354 /* Set Logical HAL to Core objects */
355 tcore_object_set_hal(co, hal);
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);
360 /* Next Core Object of the channel */
364 /* Control Channel */
365 dbg("Control channel");
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);
371 /* Update Logical HAL of CMUX Channel */
372 g_mux_obj_ptr->channel_info[channel_id]->hal = hal;
375 /* Set Logical HAL Power State to TRUE */
376 tcore_hal_set_power_state(hal, TRUE);
377 dbg("HAL Power is SET");
383 MUX* tcore_cmux_new(void)
388 /* Allocating memory for mux */
389 mux = (MUX *) calloc(sizeof(MUX), 1);
391 err("Failed to allocate memory");
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");
402 /* MUX State initialize to MUX_NOT_INITIALIZED */
403 mux->state = MUX_NOT_INITIALIZED;
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);
418 /* Free allocated memory */
420 if (mux->info_field) {
421 free(mux->info_field);
424 for (i = 0; i < MAX_CMUX_CHANNELS_SUPPORTED; i++) {
425 if (mux->channel_info[i]) {
426 free(mux->channel_info[i]);
437 static unsigned char calc_crc(unsigned char *header, int length)
439 unsigned char FCS = 0xFF; /*Init*/
440 unsigned char crc = 0x00;
442 /* 'length' is the number of bytes in the message, 'header' points to message */
444 FCS = crc_table[FCS ^ *header++];
450 dbg("Exit - crc: 0x%02x", crc)
454 static unsigned char* tcore_encode_cmux_frame(unsigned char *data,
458 unsigned char EA_bit,
459 unsigned char CR_bit,
460 unsigned char PF_bit,
463 int frame_length = 0;
464 int total_frame_length = 0;
469 /* Flush channel data */
470 tcore_cmux_flush_channel_data();
472 if (length > MAX_CMUX_BUFFER_SIZE) {
473 err("Length - %d exceeds the limit", length);
478 g_mux_obj_ptr->info_field[frame_length++] = (char) 0xF9;
480 /* Mode of Operation */
481 if (0x00 == g_mux_mode) { /* BASIC */
483 * C/R: Command Response
485 g_mux_obj_ptr->info_field[frame_length] = g_mux_obj_ptr->info_field[frame_length] | ((EA_bit & 0x01) | ((CR_bit << 1) & 0x02));
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);
493 err("Channel is out of range[0-8]");
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 *****************************************************************/
509 g_mux_obj_ptr->info_field[frame_length++] = frame_type | 0x10;
511 g_mux_obj_ptr->info_field[frame_length++] = frame_type;
514 /* 5.2.1.5 Length Indicator */
516 g_mux_obj_ptr->info_field[frame_length++] = (char) length << 1 | 0x01;
518 /* CRC calculatable length */
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
524 /* CRC calculatable length */
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.
533 /* 5.2.1.4 Information Field*/
535 memcpy((g_mux_obj_ptr->info_field + frame_length), data, length);
536 frame_length += length;
538 dbg("info field length is zero");
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);
545 g_mux_obj_ptr->info_field[frame_length++] = 0xF9;
547 total_frame_length = frame_length;
548 } else if (0x01 == g_mux_mode) { /* TBD MUX_MODE_ADVANCE */
549 dbg("Advanced MUX mode : TBD");
552 *out_data_len = total_frame_length;
553 dbg("*out_data_len: %d", *out_data_len);
555 dbg("Exit total_frame_length: %d", total_frame_length);
556 return g_mux_obj_ptr->info_field;
559 static int rcv_crc_check(unsigned char *data, unsigned char len, unsigned char rcv_FCS)
561 unsigned char FCS = 0xFF;
563 /* 'len' is the number of bytes in the message, 'data' points to message */
565 FCS = crc_table[FCS ^ *data++];
569 FCS = crc_table[FCS ^ rcv_FCS];
571 /* 0xCF is the reversed order of 11110011 */
572 if (0xCF == FCS) { /* FCS is OK */
574 } else { /* FCS is NOT OK */
579 static void tcore_cmux_flush_channel_data(void)
583 g_mux_obj_ptr->info_field_len = 0x0;
584 memset(g_mux_obj_ptr->info_field, 0x0, MAX_CMUX_BUFFER_SIZE);
590 static void tcore_cmux_control_channel_handle(void)
592 unsigned char cmd_type;
594 unsigned char *msg_start_ptr = NULL;
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
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];
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.
609 * Search for the last octet
611 while ((*msg_start_ptr++ & 0x01)) { // TBD
615 if ((cmd_type & 0x02) == 0x02) { // This is a command Request
617 case CMUX_COMMAND_MSC:
619 dbg("Modem Status Command");
623 case CMUX_COMMAND_CLD:
625 dbg("Multiplexer close down");
632 /* We will be supporting these commands in Phase 2 */
639 err("Frame length is less than ZERO");
646 static void tcore_cmux_process_channel_data(CHANNEL *channel_info_ptr)
651 unsigned char *send_data = NULL;
652 static int count = 0;
657 channel_id = channel_info_ptr->channel_id;
658 dbg("Channel ID: %d", channel_id);
660 frame_type = channel_info_ptr->frame_type & 0xEF;
661 dbg("frame_type: 0x%x", frame_type);
663 switch (frame_type) {
664 case CMUX_COMMAND_UI:
665 case CMUX_COMMAND_UIH:
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();
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);
679 case CMUX_COMMAND_UA:
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;
687 dbg("Count: %d", count);
688 if (MAX_CMUX_CHANNELS_SUPPORTED == count) {
689 /* Indicate to CoreObject */
690 CoreObject *co = NULL;
692 /* 'modem' Core Object */
693 co = g_mux_obj_ptr->modem_co;
695 err("'modem' Core object is not present");
700 dbg("Emit Core object callback");
701 tcore_object_emit_callback(co, "CMUX-UP", NULL);
702 dbg("Emitted Core object callback");
707 } else if (MUX_CHANNEL_DISC_SEND_WAITING_FOR_UA == channel_info_ptr->state) {
708 channel_info_ptr->state = MUX_CHANNEL_CLOSED;
710 if (0 == channel_id) {
711 g_mux_obj_ptr->state = MUX_CLOSED;
715 err("Received UA in wrong state!!!");
720 case CMUX_COMMAND_DM:
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
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;
733 /* Flush the Channel data */
734 tcore_cmux_flush_channel_data();
739 case CMUX_COMMAND_DISC:
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.
747 /* Flush the Channel data */
748 tcore_cmux_flush_channel_data();
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
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);
762 err("Failed to encode");
767 ret = tcore_cmux_send_data(len, send_data);
769 /* Flush the Channel data */
770 tcore_cmux_flush_channel_data();
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
775 if (0 == channel_id) {
776 g_mux_obj_ptr->state = MUX_CLOSED;
785 case CMUX_COMMAND_SABM:
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.
793 /* Flush the Channel data */
794 tcore_cmux_flush_channel_data();
797 send_data = tcore_encode_cmux_frame(NULL, 0, channel_id, CMUX_COMMAND_UA, 1, 1, 1, &len);
800 ret = tcore_cmux_send_data(len, send_data);
802 err("Failed to encode");
805 if (channel_info_ptr->state != MUX_CHANNEL_ESTABLISHED) {
806 /* Channel State set to Established */
807 channel_info_ptr->state = MUX_CHANNEL_ESTABLISHED;
818 static void tcore_cmux_process_rcv_frame(unsigned char *data, int len)
820 unsigned char *frame_process_ptr = data;
821 unsigned char *buf_start_ptr = data;
824 unsigned char channel_id;
829 tcore_cmux_flush_channel_data();
831 /* Get the Channel ID : 1st byte will be flag (F9)..Flag checking is already done.*/
832 channel_id = (*++frame_process_ptr >> 2) & 0x3F;
834 if (channel_id < MAX_CMUX_CHANNELS_SUPPORTED) { // max channel is 8
835 ch = g_mux_obj_ptr->channel_info[channel_id];
837 ch->channel_id = channel_id;
840 ch->ext_bit = *frame_process_ptr & 0x01;
843 ch->cr_bit = (*frame_process_ptr++ >> 1) & 0x01;
845 // get the Frame Type
846 ch->frame_type = *frame_process_ptr++;
848 // get the poll/Final bit
849 ch->poll_final_bit = (ch->frame_type & 0x10) >> 4;
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;
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);
861 dbg("info_field_len: %d", g_mux_obj_ptr->info_field_len);
863 /* Copy received information field */
864 memcpy(g_mux_obj_ptr->info_field, frame_process_ptr, g_mux_obj_ptr->info_field_len);
866 frame_process_ptr = frame_process_ptr + g_mux_obj_ptr->info_field_len;
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);
873 err("CRC check of the header FAILED.. Drop the packet !!");
876 err("Incorrect channel... Drop the packet !!");
883 int tcore_cmux_rcv_from_hal(unsigned char *data, size_t length)
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
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;
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;
921 while (data[pos] != 0xF9) {
922 if (++pos >= length) {
926 decode_state = TCORE_MUX_DECODE_ADDR_HUNT;
927 goto DECODE_STATE_CHANGE;
930 while (data[pos] == 0xF9) {
931 if (++pos >= length) {
936 dec_fcs = crc_table[dec_fcs^data[pos]];
937 decode_state = TCORE_MUX_DECODE_CONTROL_HUNT;
939 *dec_data++ = data[pos];
941 goto DECODE_STATE_CHANGE;
944 dec_fcs = crc_table[dec_fcs^data[pos]];
945 decode_state = TCORE_MUX_DECODE_LENGTH1_HUNT;
946 *dec_data++ = data[pos];
948 goto DECODE_STATE_CHANGE;
951 dec_length = data[pos] >> 1;
952 dec_fcs = crc_table[dec_fcs^data[pos]];
957 decode_state = TCORE_MUX_DECODE_DATA_HUNT;
961 decode_state = TCORE_MUX_DECODE_FCS_HUNT;
966 decode_state = TCORE_MUX_DECODE_LENGTH2_HUNT;
969 *dec_data++ = data[pos];
971 goto DECODE_STATE_CHANGE;
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];
979 goto DECODE_STATE_CHANGE;
982 if (dec_length < (length - pos)) // frame data fully available in the buffer
985 decode_state = TCORE_MUX_DECODE_FCS_HUNT;
987 else // frame data partially available in the buffer
989 cp_len = (length - pos);
990 decode_state = TCORE_MUX_DECODE_DATA_HUNT;
993 memcpy(dec_data, data + pos, cp_len);
996 dec_length -= cp_len;
997 full_frame_len += cp_len;
999 goto DECODE_STATE_CHANGE;
1002 //if (crc_table[dec_fcs^data[pos]] == 0xCF) // valid FCS, store frame.
1004 *dec_data++ = data[pos];
1006 full_frame_len += 2;
1007 tcore_cmux_process_rcv_frame(mux_buffer, full_frame_len);
1010 // enter flag hunt mode
1011 decode_state = TCORE_MUX_DECODE_FLAG_HUNT;
1012 goto DECODE_STATE_CHANGE;
1015 static void tcore_cmux_channel_init(CMUX_Channels channel_id)
1019 ch = g_mux_obj_ptr->channel_info[channel_id];
1020 memset(ch, 0x0, sizeof(CHANNEL));
1022 ch->channel_id = channel_id;
1023 ch->state = MUX_CHANNEL_SABM_SEND_WAITING_FOR_UA;
1028 /* TODO - Check if required */
1029 ch->frame_type = CMUX_COMMAND_SABM;
1032 ch->poll_final_bit = 0x01;
1034 dbg("Channel ID %d initialized", channel_id);
1039 static void tcore_cmux_close_channel(int channel_id)
1042 unsigned char *send_data = NULL;
1047 ch = g_mux_obj_ptr->channel_info[channel_id];
1049 if (ch->state != MUX_CHANNEL_CLOSED) {
1050 ch->frame_type = CMUX_COMMAND_DISC;
1053 ch->state = MUX_CHANNEL_DISC_SEND_WAITING_FOR_UA;
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);
1059 /* Send CMUX data */
1060 ret = tcore_cmux_send_data(len, send_data);
1062 err("Failed to encode");
1065 /* Channel is already closed */
1066 err("Channel is already closed");
1073 static void tcore_cmux_free(void)
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;
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;
1094 /* Free MUX Object */
1095 free(g_mux_obj_ptr);
1096 g_mux_obj_ptr = NULL;
1098 err("MUX Object doesn't exist");
1105 TReturn tcore_cmux_init(TcorePlugin *plugin, TcoreHal *hal)
1107 unsigned char *data = NULL;
1112 TReturn ret = TCORE_RETURN_SUCCESS;
1116 dbg("Physical HAL: %x", hal);
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");
1123 ret = TCORE_RETURN_FAILURE;
1128 g_mux_obj_ptr->plugin = plugin;
1130 /* Save Physical HAL */
1131 g_mux_obj_ptr->phy_hal = hal;
1133 /* Setting Receive callback function for data received from Physical HAL */
1134 g_mux_obj_ptr->cb_func = tcore_cmux_recv_mux_data;
1136 /* After MUX setup, AT parse functionality of PHY HAL should be disabled,
1137 * here we change the mode of PHYSICAL HAL to Transparent.
1139 tcore_hal_set_mode(g_mux_obj_ptr->phy_hal, TCORE_HAL_MODE_TRANSPARENT);
1140 dbg("Physical HAL mode changed to Transparent");
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);
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");
1154 ret = TCORE_RETURN_FAILURE;
1157 dbg("data_len: %d data: %s", data_len, data);
1159 /* Send CMUX data */
1160 tcore_cmux_send_data(data_len, data);
1161 dbg("CMUX Control Request sent to CP");
1163 /* Set Core object and HAL */
1164 tcore_cmux_link_core_object_hal((CMUX_Channels) index, plugin);
1171 /* Free the allocated CMUX memory */
1178 void tcore_cmux_close(void)
1182 CoreObject *co = NULL;
1183 GSList *co_list = NULL;
1187 for (channel = 0; channel < MAX_CMUX_CHANNELS_SUPPORTED; channel++) {
1188 dbg("Channel ID: %d", channel);
1191 /* Close Channel - Send DSC command */
1192 tcore_cmux_close_channel(channel);
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]) {
1198 /* Core Objects list */
1199 co_list = g_mux_obj_ptr->channel_info[channel]->co;
1200 dbg("Core Objects list : %p", co_list);
1202 /* Core Object list may contain multiple Core Objects.
1203 * Revert to Physical HAL for each of the Core Objects associated
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 ");
1215 /* To next Core Object in the list */
1216 co_list = co_list->next;
1219 /* Set the previous Physical HAL as HAL for Core Object */
1221 tcore_object_set_hal(co, g_mux_obj_ptr->phy_hal);
1223 /* Proceed to next Channel */
1224 err("No more Core Objects present in this Channel");
1228 /* To next Core Object */
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;
1237 /* Change the mode of PHYSICAL HAL to Custom */
1238 tcore_hal_set_mode(g_mux_obj_ptr->phy_hal, TCORE_HAL_MODE_AT);
1240 /* Free all the allocated memory */