4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
7 * Sooyoung Ha <yoosah.ha@samsung.com>
8 * Sungmin Ha <sungmin82.ha@samsung.com>
9 * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
11 * This library is free software; you can redistribute it and/or modify it under
12 * the terms of the GNU Lesser General Public License as published by the
13 * Free Software Foundation; either version 2.1 of the License, or (at your option)
16 * This library is distributed in the hope that it will be useful, but WITHOUT ANY
17 * WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
19 * License for more details.
21 * You should have received a copy of the GNU Lesser General Public License
22 * along with this library; if not, write to the Free Software Foundation, Inc., 51
23 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30 /////////////////////////////////////////////////////////////////////
37 #include "state.h" // linuxtapi.h
40 #include "phoneserver.h"
42 #include "vgsm_call.h"
43 #include "oem_tx_call.h"
44 #include "server_tx_call.h"
45 #include "server_common_call.h"
46 #include "server_tx_ss.h"
48 #include "at_gen_resp.h"
51 // caution: MAX_GSM_DIALED_DIGITS_NUMBER and MAX_GSM_DIALED_DIGITS_NUM are confusingly similar
53 int server_tx_call_msg(void)
59 get_current_state_machine(&state );
61 switch(STATE_SUB_CMD(state))
64 server_tx_call_status();
67 server_tx_call_list_resp();
70 log_msg(MSGL_WARN, "unknown subcommand %d\n", STATE_SUB_CMD(state));
78 //int TxCall_CallStatus()
79 int server_tx_call_status(void) // it means call state.
86 TRACE(MSGL_VGSM_INFO, "\n");
89 gsm_call_list_t * callList = malloc(sizeof(gsm_call_list_t));
92 memset(callList, 0, sizeof(gsm_call_list_t));
94 get_prev_state_machine( &prev );
96 // if( STATE_SUB_CMD(prev) == GSM_CALL_OUTGOING )
97 if( STATE_TYPE(prev) == STATE_STANDBY ) // it means GSM_CALL_OUTGOING in state_machine.
99 call_state = GSM_CALL_STATE_OUTGOING;
100 log_msg(MSGL_VGSM_INFO, "STATE_STANBY\n");
101 set_call_list_status( get_call_id(), 0, GSM_CALL_STATUS_DIALING );
102 get_call_list(callList);
104 else if( STATE_TYPE(prev) == STATE_CALL_WAITING_OUTGOING || STATE_TYPE(prev) == STATE_CALL_WAITING_INCOMING )
106 call_state = GSM_CALL_STATE_CONNECTED;
108 // find client id of incoming call & set active
109 get_call_list(callList);
110 for( i=0; i<MAX_CALL_COUNT; ++i ) {
111 if(callList->CallInfo[i].stat == GSM_CALL_STATUS_INCOMING || callList->CallInfo[i].stat == GSM_CALL_STATUS_WAITING){
112 log_msg(MSGL_VGSM_INFO,"call id(%d) is GSM_CALL_STATUS_INCOMING \n", i);
117 set_call_list_status( get_call_id(), 0, GSM_CALL_STATUS_ACTIVE );
118 at_gen_resp_send(AT_GEN_ERR_CONNECT);
121 get_call_list(callList);
123 for(i = 0; i < callList->CallCount; i++){
124 log_msg(MSGL_VGSM_INFO,"call id : %d, number : %s, multiparty : %d, stat : %d \n",
125 callList->CallInfo[i].idx, callList->CallInfo[i].number,
126 callList->CallInfo[i].mpty, callList->CallInfo[i].stat);
129 packet.data = (gsm_call_list_t*)callList;
130 packet.group = GSM_CALL;
131 packet.action = GSM_CALL_CONNECTED_LINE_NOTI;
132 packet.length = sizeof(gsm_call_list_t);
134 FuncServer->Cast(&GlobalPS, LXT_ID_CLIENT_EVENT_INJECTOR, &packet);
135 if(get_call_id() >= callList->CallCount) {
139 else if( STATE_TYPE(prev) == STATE_CALL_RELEASED )
141 call_state = GSM_CALL_STATE_RELEASED;
142 at_gen_resp_send(AT_GEN_ERR_RELEASE);
144 get_call_list(callList);
145 packet.data = (gsm_call_list_t*)callList;
146 packet.group = GSM_CALL;
147 packet.action = GSM_CALL_STATUS_NOTI;
148 packet.length = sizeof(gsm_call_list_t);
150 FuncServer->Cast(&GlobalPS, LXT_ID_CLIENT_EVENT_INJECTOR, &packet);
151 set_call_list_status( get_call_id(), 0, GSM_CALL_STATUS_NONE );
152 get_call_list(callList);
154 /* Why does not it exist in case of STATE_CALL_CONVERSATION */
156 /* In call status msg, incoming msg do not exist.
157 else if( STATE_SUB_CMD(prev) == GSM_CALL_INCOMING )
159 pdata[2] = GSM_CALL_STATE_INCOMING;
163 unsigned char pdata[128];
164 int at_stat = change_stat_for_at(callList->CallInfo[get_call_id()].stat);
165 TRACE(MSGL_VGSM_INFO, "call id:%d, orignal stat: %d, send stat: %d\n", get_call_id(), callList->CallInfo[get_call_id()].stat, at_stat);
167 if(strcmp(callList->CallInfo[get_call_id()].number, ""))
169 sprintf((char*)pdata, "%d,%d,%d,%d,%d,%s,%d", get_call_id() + 1, change_dir_for_at(callList->CallInfo[get_call_id()].dir),
170 at_stat, AT_CALL_MODE_VOICE, AT_CALL_MPTY_FALSE,
171 callList->CallInfo[get_call_id()].number,callList->CallInfo[get_call_id()].num_type);
175 sprintf((char*)pdata, "%d,%d,%d,%d,%d", get_call_id() + 1, change_dir_for_at(callList->CallInfo[get_call_id()].dir), at_stat, AT_CALL_MODE_VOICE, AT_CALL_MPTY_FALSE);
179 set_current_call_status_error( 0x00 );
181 ret = oem_tx_call_status_noti(pdata, strlen((char*)pdata));
188 int server_tx_call_list_noti(void)
192 int i = 0, j = 0, ret = 0;
195 unsigned char *data = NULL;
197 gsm_call_list_t * callList = malloc(sizeof(gsm_call_list_t));
199 get_call_list(callList);
200 CallCount = callList->CallCount;
201 // FIXME: probably want MAX_GSM_DIALED_DIGITS_NUM here
202 len = 32 + (8+MAX_GSM_DIALED_DIGITS_NUMBER);
203 data = malloc(len*2);
204 log_msg(MSGL_VGSM_INFO,"CallCount %d\n", CallCount);
206 for (i=0; i < MAX_CALL_COUNT; i++) {
207 if( callList->CallInfo[i].stat == GSM_CALL_STATUS_NONE )
209 log_msg(MSGL_VGSM_INFO,"index = %d : Call_STATUS %d\n", i, callList->CallInfo[i].stat);
211 assert(valid_call_type(callList->CallInfo[i].call_type));
212 memset( data, 0, len * 2 );
213 sprintf((char*)data, "%d,%d,%d,%d,%d,%s,%d%s", callList->CallInfo[i].idx + 1,
214 change_dir_for_at(callList->CallInfo[i].dir),
215 change_stat_for_at(callList->CallInfo[i].stat), AT_CALL_MODE_VOICE, callList->CallInfo[i].mpty,
216 callList->CallInfo[i].number, callList->CallInfo[i].num_type, CRLF);
217 log_msg(MSGL_VGSM_INFO, "%s", data);
218 ret = oem_tx_call_status_noti(data, strlen((char*)data));
222 packet.data = (gsm_call_list_t*)callList;
223 packet.length = sizeof(gsm_call_list_t);
224 packet.group = GSM_CALL;
225 packet.action = GSM_CALL_CALL_LIST_IND;
227 FuncServer->Cast(&GlobalPS, LXT_ID_CLIENT_EVENT_INJECTOR, &packet);
237 int change_stat_for_at(int gsm_stat)
242 case GSM_CALL_STATUS_NONE:
243 stat = AT_CALL_STAT_RELEASED;
245 case GSM_CALL_STATUS_ACTIVE:
246 stat = AT_CALL_STAT_ACTIVE;
248 case GSM_CALL_STATUS_HELD:
249 stat = AT_CALL_STAT_HELD;
251 case GSM_CALL_STATUS_DIALING:
252 stat = AT_CALL_STAT_DIALING;
254 case GSM_CALL_STATUS_ALERT:
255 stat = AT_CALL_STAT_ALERTING;
257 case GSM_CALL_STATUS_INCOMING:
258 stat = AT_CALL_STAT_INCOMING;
260 case GSM_CALL_STATUS_WAITING:
261 stat = AT_CALL_STAT_WAITING;
263 case GSM_CALL_STATUS_MAX:
265 stat = AT_CALL_STAT_DIALING;
272 int change_dir_for_at(int gsm_dir)
278 case GSM_CALL_DIR_MO:
281 case GSM_CALL_DIR_MT:
291 int server_tx_call_list_resp(void)
296 unsigned char *data = NULL;
297 gsm_call_list_t * callList = malloc(sizeof(gsm_call_list_t));
301 get_call_list(callList);
302 CallCount = callList->CallCount;
303 len = 32 + (8+MAX_GSM_DIALED_DIGITS_NUMBER);
304 data = malloc(len*2);
305 log_msg(MSGL_VGSM_INFO,"CallCount %d\n", CallCount);
306 for (i=0; i < MAX_CALL_COUNT; i++) {
307 if( callList->CallInfo[i].stat == GSM_CALL_STATUS_NONE )
309 log_msg(MSGL_VGSM_INFO,"index = %d : Call_STATUS %d\n", i, callList->CallInfo[i].stat);
311 assert(valid_call_type(callList->CallInfo[i].call_type));
312 memset( data, 0, len * 2);
313 sprintf((char*)data, "%s%d,%d,%d,%d,%d,%s,%d%s", CLCC,callList->CallInfo[i].idx + 1,
314 change_dir_for_at(callList->CallInfo[i].dir),
315 change_stat_for_at(callList->CallInfo[i].stat),
316 AT_CALL_MODE_VOICE, callList->CallInfo[i].mpty,
317 callList->CallInfo[i].number, callList->CallInfo[i].num_type, CRLF);
318 log_msg(MSGL_VGSM_INFO, "%s", data);
319 ret = oem_tx_call_list_resp(data, strlen((char*)data));
321 at_gen_resp_send(AT_GEN_ERR_NO_ERROR);
331 static void cast_call_incomming(unsigned char call_id)
335 unsigned char data[1];
337 TAPIMessageInit(&packet);
339 /* check general response error & call status error */
341 data[0] = call_id; //The object is simulator, 0x01 : Outgoing Call, 0x02 : Answer Call, 0x03 : Release Call
345 packet.group = GSM_CALL;
346 packet.action = GSM_CALL_ID;
348 FuncServer->Cast(&GlobalPS, LXT_ID_CLIENT_EVENT_INJECTOR, &packet);
350 log_msg(MSGL_VGSM_INFO," -------------------------incoming call id : %d\n",call_id);
354 int server_tx_call_incoming_noti( LXT_MESSAGE * packet ) //¸ÁÀÔÀå¿¡¼± outgoing call.
356 int num_len = 0, ret = 0, tmp = 0;
357 char number[MAX_GSM_DIALED_DIGITS_NUMBER];
358 char *p, data[MAX_GSM_DIALED_DIGITS_NUMBER*2];
359 unsigned char ss_present_indi ;
360 unsigned char ss_call_type ;
361 unsigned char ss_no_cli_cause ;
362 unsigned char call_id ;
364 gsm_call_list_t list;
365 gsm_call_status_e_type call_status = GSM_CALL_STATUS_INCOMING;
366 char clir = GSM_CALL_CLIR_STATUS_NOT_CHANGED; //gsm_clir_status_e_type
367 int call_exist = 0; // ÇöÀç call list¿¡, callÀÌ ¾ø´Ù¸é incoming noti Àü¼ÛÇÑ´Ù.
368 unsigned short call_type;
371 call_barring_entry_t * resp_entry = get_call_barring_entry() ;
373 TRACE(MSGL_VGSM_INFO, "\n");
376 TRACE(MSGL_VGSM_INFO, "CB entry is NULL!!!\n");
378 for(i=0; i<resp_entry[0].count; i++) {
379 TRACE(MSGL_VGSM_INFO,"i : %d, type : %d\n", i, resp_entry[i].type);
380 if(resp_entry[i].type == 4 && resp_entry[i].ss_mode == 3) { // 'All incoming calls' has set
381 TRACE(MSGL_VGSM_ERR, "Incoming Call Barring is set \n");
388 get_current_state_machine( &state );
389 if( ( state.state_type == STATE_CALL_WAITING_OUTGOING ) ||
390 ( state.state_type == STATE_CALL_WAITING_INCOMING ) )
392 log_msg(MSGL_WARN,"state_type = %d\n",state.state_type);
396 if( check_call() == 0 )
398 log_msg(MSGL_WARN, "1 active and 1 hold \n");
399 // delete for multi call ( 6 call ) return 0;
402 get_call_list( &list );
403 if( list.CallCount > 0 ) {
404 call_status = GSM_CALL_STATUS_WAITING;
406 // sub_cmd = GSM_CALL_WAITING;
407 call_exist = 1; // call list¿¡ call ÀÌ Á¸ÀçÇϸé, incoming noti ´ë½Å¿¡ waiting noti¸¦ Àü¼ÛÇÑ´Ù.
410 assert(packet->length >= 8);
413 call_id = make_call_id();
414 call_type = p[0] << 8;
415 cast_call_incomming(call_id);
416 set_call_type(call_type);
418 memset(number, 0, MAX_GSM_DIALED_DIGITS_NUMBER);
422 if(clir == GSM_CALL_CLIR_STATUS_INVOCATION)
424 log_msg(MSGL_VGSM_INFO," GSM_CALL_CLIR_STATUS_INVOCATION -> no num \n");
425 num_len = 0; // È®ÀÎÇÏÀÚ. num_len °¡ MAX_GSM_DIALED_DIGITS_NUMBER µÇ¾î¾ßÇÏ´ÂÁö check...
426 memset(number, 0, MAX_GSM_DIALED_DIGITS_NUMBER);
427 ss_present_indi = p[5];
428 ss_no_cli_cause = p[6];
435 TRACE(MSGL_VGSM_INFO, "ERROR!! Invalid value of packet.data.\n");
438 } else if ( tmp >= MAX_GSM_DIALED_DIGITS_NUMBER){
439 TRACE(MSGL_VGSM_INFO, "The number is too long. It will be cut.\n");
440 num_len = MAX_GSM_DIALED_DIGITS_NUMBER - 1;
444 memcpy(number, &p[7], num_len);
445 number[num_len] = '\0';
446 log_msg(MSGL_VGSM_INFO," call num len %d \n", num_len);
451 set_call_list( GSM_CALL_DIR_MT, call_status, call_type, number, num_len );
460 number_type = "145"; // default
464 sprintf(data, "%d,%d,%d,%d,%d,%s,%s", call_id + 1, AT_CALL_DIR_MT, AT_CALL_STAT_INCOMING, AT_CALL_MODE_VOICE, AT_CALL_MPTY_FALSE, number, number_type);
465 TRACE(MSGL_VGSM_INFO, "data: %s\n", data);
466 ret = oem_tx_call_incoming_noti(data, strlen(data));
470 sprintf(data, "%s,%s,%d", number, number_type, AT_CALL_CLASS_VOICE);
471 TRACE(MSGL_VGSM_INFO, "data: %s\n", data);
472 ret = oem_tx_call_waiting_noti(data, strlen(data));
474 memset(data, '\0', strlen(data));
475 sprintf(data, "%d,%d,%d,%d,%d,%s,%s", call_id + 1, AT_CALL_DIR_MT, AT_CALL_STAT_WAITING, AT_CALL_MODE_VOICE, AT_CALL_MPTY_FALSE, number, number_type);
476 TRACE(MSGL_VGSM_INFO, "data: %s\n", data);
477 return oem_tx_call_status_noti(data, strlen(data));
480 //log_msg(MSGL_VGSM_INFO,"!!!!!!!!server_tx_call_incoming_noti!!!!!!!!!!! number : %d, number len : %d \n", number[0], num_len);
481 if( GSM_CALL_TYPE_FORWARDED == p[1] )
483 ss_call_type = 0x33 ;
488 ss_call_type = 0x31 ; //calling party
491 log_msg(MSGL_VGSM_INFO," call type = %d, num len=%d PI=%d Cli-cause %d \n", p[0], num_len,ss_present_indi,ss_no_cli_cause);
493 server_tx_ss_cli(ss_call_type, ss_present_indi, ss_no_cli_cause); // TODO: it will be changed..
500 //int TxCall_ExecRelease( LXT_MESSAGE * packet )
501 int server_tx_call_release_exec(LXT_MESSAGE * packet )
505 unsigned char *p = 0;
507 int call_gen_resp_err =-1;
509 log_msg(MSGL_VGSM_INFO, "\n");
511 get_current_state_machine( &state );
513 if( state.state_type == STATE_STANDBY )
515 // general error send
516 call_gen_resp_err = check_call_error();
517 //oem_tx_call_gen_resp(call_gen_resp_err);
518 set_general_response_error(0x8000);
521 // STATE_CALL_WAITING_INCOMING
523 gsm_call_list_t *callList = malloc(sizeof(gsm_call_list_t));
527 p = (unsigned char *)packet->data; // call id
529 log_msg(MSGL_VGSM_INFO," release call id = %d \n", p[0]);
533 get_call_list(callList);
534 for (i=0; i < MAX_CALL_COUNT; i++)
536 if( callList->CallInfo[i].stat == GSM_CALL_STATUS_NONE )
538 if( callList->CallInfo[i].idx == call_id)
540 ret = server_tx_call_release_internal( call_id );
550 //int TxCall_ExecAnswer()
551 int server_tx_call_answer_exec(void)
555 TRACE(MSGL_VGSM_INFO, "\n");
560 get_call_list( &list );
561 if( list.CallCount <= 0 )
564 if( ( list.CallInfo[get_call_id()].stat == GSM_CALL_STATE_ACTIVE ) ||
565 ( list.CallInfo[get_call_id()].stat == GSM_Call_Held ) )
571 gsm_call_list_t * callList = malloc(sizeof(gsm_call_list_t));
577 get_call_list(callList);
579 if(callList->CallCount < 1) {
580 TRACE(MSGL_VGSM_ERR, "The call-count is %d!!\n", callList->CallCount);
585 for (i=0; i < MAX_CALL_COUNT; i++) {
586 if( callList->CallInfo[i].stat == GSM_CALL_STATUS_ALERT ) {
587 alerted_id = callList->CallInfo[i].idx;
592 if(alerted_id != get_call_id()) {
593 TRACE(MSGL_VGSM_INFO, "Current g_call_id(%d) is not the alerted_id(%d)\n", get_call_id(), alerted_id);
594 set_call_id(alerted_id);
598 set_current_state( STATE_CALL_WAITING_OUTGOING, GSM_CALL_CMD, GSM_CALL_ANSWER);
600 if( find_next_state( &next, STATE_FLAG_ALL ) ) {
601 set_state_machine( next );
612 int server_tx_call_alert_ind(void *ptr_data, int data_len )
616 TRACE(MSGL_VGSM_INFO, "\n");
618 //send resp ( no error ) to Phone
619 // oem_tx_call_gen_resp(0x8000);
621 //send noti ( outgoing )to Phone
622 // set_current_state( STATE_STANDBY, GSM_CALL_CMD, GSM_CALL_OUTGOING);
625 if( find_next_state( &next, STATE_FLAG_ALL ) ) {
626 // call server_tx_call_msg()
627 set_state_machine( next );
632 //send noti ( alert )to Phone
633 unsigned short call_type = get_call_type();
637 gsm_call_list_t * callList = malloc(sizeof(gsm_call_list_t));
643 get_call_list(callList);
645 if(callList->CallCount < 1) {
646 TRACE(MSGL_VGSM_ERR, "The call-count is %d!!\n", callList->CallCount);
651 for (i=0; i < MAX_CALL_COUNT; i++) {
652 if( callList->CallInfo[i].stat == GSM_CALL_STATUS_DIALING ) {
653 dialing_id = callList->CallInfo[i].idx;
658 if(dialing_id != get_call_id()) {
659 TRACE(MSGL_VGSM_INFO, "Current g_call_id(%d) is not the dialing_id(%d)\n", get_call_id(), dialing_id);
660 set_call_id(dialing_id);
663 char sndbuf[SEND_BUF_SIZE];
664 memset(sndbuf, '\0', sizeof(sndbuf));
665 sprintf(sndbuf, "%d,%d,%d,%d,%d", get_call_id() + 1, AT_CALL_DIR_MO, AT_CALL_STAT_ALERTING, AT_CALL_CLASS_VOICE, AT_CALL_MPTY_FALSE);
667 set_current_call_status_error( 0x00 );
669 set_call_list_status( get_call_id(), 0, GSM_CALL_STATUS_ALERT );
671 callback_callist(); // renewal call_list in the EI
674 return oem_tx_call_status_noti(sndbuf, strlen(sndbuf));
678 //int release_call( int call_id )
679 int server_tx_call_release_internal(int call_id)
684 gsm_call_list_t * list = malloc(sizeof(gsm_call_list_t));
688 TRACE(MSGL_VGSM_INFO, "\n");
690 set_call_id( call_id ); // ³ªÁß¿¡ server_tx_call_status() º¸³»´Â °æ¿ì¿¡, g_call_id¸¦ °¡Á®¿À¹Ç·Î ¿©±â¼ set ÇؾßÇÑ´Ù.
692 TAPIMessageInit(&packet);
694 data[0] = 0x03; //0x01 : Outgoing Call, 0x02 : Answer Call, 0x03 : Release Call
698 packet.group = GSM_CALL;
699 packet.action = GSM_CALL_STATE;
701 FuncServer->Cast(&GlobalPS, LXT_ID_CLIENT_EVENT_INJECTOR, &packet);
703 set_current_state( STATE_CALL_RELEASED, GSM_CALL_CMD, GSM_CALL_RELEASE);
705 set_ss_state(SS_NONE);
707 log_msg(MSGL_VGSM_INFO,"deleted call id : %d \n", call_id);
708 delete_call_list( call_id );
710 if( find_next_state( &next, STATE_FLAG_ALL ) ) {
711 set_state_machine( next );
718 packet.length = sizeof(gsm_call_list_t);
719 }/* Execution cannot reach this statement
725 packet.group = GSM_CALL;
726 packet.action = GSM_CALL_STATUS_NOTI;
728 FuncServer->Cast(&GlobalPS, LXT_ID_CLIENT_EVENT_INJECTOR, &packet);
735 int server_tx_call_all_release(void)
738 gsm_call_list_t * list = malloc(sizeof(gsm_call_list_t));
741 TRACE(MSGL_VGSM_INFO, "\n");
743 for( i=0; i<MAX_CALL_COUNT; ++i ) {
744 if( list->CallInfo[i].stat != GSM_CALL_STATUS_NONE )
745 server_tx_call_release_internal( list->CallInfo[i].idx );
754 void server_tx_call_burst_dtmf_noti(int success)
757 unsigned char data[1];
761 oem_tx_call_burst_dtmf_noti(data, n);
764 int server_tx_call_line_id_resp(void)
767 unsigned char data[1];
769 data[n++] = get_call_line_id();
771 oem_tx_call_line_id_resp(data, n);
776 void callback_callist(void)
781 gsm_call_list_t * callList = malloc(sizeof(gsm_call_list_t));
783 get_call_list(callList);
786 packet.data = (gsm_call_list_t*)callList;
787 packet.length = sizeof(gsm_call_list_t);
788 packet.group = GSM_CALL;
789 packet.action = GSM_CALL_CALL_LIST_IND; // 0x29 in vgsm_phone.h
791 FuncServer->Cast(&GlobalPS, LXT_ID_CLIENT_EVENT_INJECTOR, &packet);