/* This gets called to indicate an incoming call */ void gn_atem_call_passup(gn_call_status CallStatus, gn_call_info *CallInfo, struct gn_statemachine *state) { dprintf("gn_atem_call_passup called with %d\n", CallStatus); switch (CallStatus) { case GN_CALL_Incoming: IncomingCallNo = CallInfo->call_id; gn_atem_modem_result(MR_RING); ModemRegisters[REG_RINGCNT]++; gn_atem_cid_out(CallInfo); if (ModemRegisters[REG_RINGATA] != 0) gn_atem_answer_phone(); break; case GN_CALL_LocalHangup: case GN_CALL_RemoteHangup: if (IncomingCallNo > 0) { gn_atem_cpi(GSMD_CALLPROG_DISCONNECT, GSMD_CALL_DIR_MT, 0); gn_atem_cpi(GSMD_CALLPROG_RELEASE, GSMD_CALL_DIR_MT, 0); } IncomingCallNo = -1; break; default: break; } }
/* This gets called to indicate an incoming call */ void gn_atem_call_passup(gn_call_status CallStatus, gn_call_info *CallInfo, struct gn_statemachine *state, void *callback_data) { dprintf("gn_atem_call_passup called with %d\n", CallStatus); switch (CallStatus) { case GN_CALL_Incoming: gn_atem_modem_result(MR_RING); IncomingCallNo = CallInfo->call_id; ModemRegisters[REG_RINGCNT]++; gn_atem_cid_out(CallInfo); if (ModemRegisters[REG_RINGATA] != 0) gn_atem_answer_phone(); break; case GN_CALL_LocalHangup: case GN_CALL_RemoteHangup: IncomingCallNo = -1; break; default: break; } }
/* Parser for standard AT commands. cmd_buffer must be null terminated. */ void gn_atem_at_parse(char *cmd_buffer) { char *buf; int regno, val; char str[256]; if (!cmd_buffer[0]) return; if (strncasecmp (cmd_buffer, "AT", 2) != 0) { gn_atem_modem_result(MR_ERROR); return; } for (buf = &cmd_buffer[2]; *buf;) { switch (toupper(*buf)) { case 'Z': /* Reset modem */ buf++; switch (gn_atem_num_get(&buf)) { case -1: case 0: /* reset and load stored profile 0 */ case 1: /* reset and load stored profile 1 */ gn_atem_hangup_phone(); gn_atem_registers_init(); break; default: gn_atem_modem_result(MR_ERROR); return; } break; case 'A': /* Answer call */ buf++; gn_atem_answer_phone(); return; break; case 'D': /* Dial Data :-) */ /* FIXME - should parse this better */ /* For now we'll also initialise the datapump + rlp code again */ dp_Initialise(PtyRDFD, PtyWRFD); buf++; if (toupper(*buf) == 'T' || toupper(*buf) == 'P') buf++; while (*buf == ' ') buf++; data.call_notification = dp_CallPassup; gn_sm_functions(GN_OP_SetCallNotification, &data, sm); snprintf(data.call_info->number, sizeof(data.call_info->number), "%s", buf); if (ModemRegisters[S35] == 0) data.call_info->type = GN_CALL_DigitalData; else data.call_info->type = GN_CALL_NonDigitalData; data.call_info->send_number = GN_CALL_Default; CommandMode = false; if (gn_sm_functions(GN_OP_MakeCall, &data, sm) != GN_ERR_NONE) { CommandMode = true; dp_CallPassup(GN_CALL_RemoteHangup, NULL, NULL, NULL); } else { IncomingCallNo = data.call_info->call_id; gn_sm_loop(10, sm); } return; break; case 'H': /* Hang Up */ buf++; switch (gn_atem_num_get(&buf)) { case -1: case 0: /* hook off the phone */ gn_atem_hangup_phone(); break; case 1: /* hook on the phone */ break; default: gn_atem_modem_result(MR_ERROR); return; } break; case 'S': /* Change registers */ buf++; regno = gn_atem_num_get(&buf); if (regno < 0 || regno >= MAX_MODEM_REGISTERS) { gn_atem_modem_result(MR_ERROR); return; } if (*buf == '=') { buf++; val = gn_atem_num_get(&buf); if (val < 0 || val > 255) { gn_atem_modem_result(MR_ERROR); return; } ModemRegisters[regno] = val; } else if (*buf == '?') { buf++; snprintf(str, sizeof(str), "%d\r\n", ModemRegisters[regno]); gn_atem_string_out(str); } else { gn_atem_modem_result(MR_ERROR); return; } break; case 'E': /* E - Turn Echo on/off */ buf++; switch (gn_atem_num_get(&buf)) { case -1: case 0: ModemRegisters[REG_ECHO] &= ~BIT_ECHO; break; case 1: ModemRegisters[REG_ECHO] |= BIT_ECHO; break; default: gn_atem_modem_result(MR_ERROR); return; } break; case 'Q': /* Q - Turn Quiet on/off */ buf++; switch (gn_atem_num_get(&buf)) { case -1: case 0: ModemRegisters[REG_QUIET] &= ~BIT_QUIET; break; case 1: ModemRegisters[REG_QUIET] |= BIT_QUIET; break; default: gn_atem_modem_result(MR_ERROR); return; } break; case 'V': /* V - Turn Verbose on/off */ buf++; switch (gn_atem_num_get(&buf)) { case -1: case 0: ModemRegisters[REG_VERBOSE] &= ~BIT_VERBOSE; break; case 1: ModemRegisters[REG_VERBOSE] |= BIT_VERBOSE; break; default: gn_atem_modem_result(MR_ERROR); return; } break; case 'X': /* X - Set verbosity of the result messages */ buf++; switch (gn_atem_num_get(&buf)) { case -1: case 0: val = 0x00; break; case 1: val = 0x40; break; case 2: val = 0x50; break; case 3: val = 0x60; break; case 4: val = 0x70; break; case 5: val = 0x10; break; default: gn_atem_modem_result(MR_ERROR); return; } ModemRegisters[S22] = (ModemRegisters[S22] & 0x8f) | val; break; case 'I': /* I - info */ buf++; switch (gn_atem_num_get(&buf)) { case -1: case 0: /* terminal id */ snprintf(str, sizeof(str), "%d\r\n", ModemRegisters[39]); gn_atem_string_out(str); break; case 1: /* serial number (IMEI) */ snprintf(str, sizeof(str), "%s\r\n", imei); gn_atem_string_out(str); break; case 2: /* phone revision */ snprintf(str, sizeof(str), "%s\r\n", revision); gn_atem_string_out(str); break; case 3: /* modem revision */ gn_atem_string_out("gnokiid " VERSION "\r\n"); break; case 4: /* OEM string */ snprintf(str, sizeof(str), "%s %s\r\n", manufacturer, model); gn_atem_string_out(str); break; default: gn_atem_modem_result(MR_ERROR); return; } break; /* Handle AT* commands (Nokia proprietary I think) */ case '*': buf++; if (!strcasecmp(buf, "NOKIATEST")) { gn_atem_modem_result(MR_OK); /* FIXME? */ return; } else { if (!strcasecmp(buf, "C")) { gn_atem_modem_result(MR_OK); Parser = gn_atem_sms_parse; return; } } break; /* + is the precursor to another set of commands */ case '+': buf++; switch (toupper(*buf)) { case 'C': buf++; /* Returns true if error occured */ if (gn_atem_command_plusc(&buf) == true) { gn_atem_modem_result(MR_ERROR); return; } break; case 'G': buf++; /* Returns true if error occured */ if (gn_atem_command_plusg(&buf) == true) { gn_atem_modem_result(MR_ERROR); return; } break; default: gn_atem_modem_result(MR_ERROR); return; } break; /* # is the precursor to another set of commands */ case '#': buf++; /* Returns true if error occured */ if (gn_atem_command_diesis(&buf) == true) { gn_atem_modem_result(MR_ERROR); return; } break; default: gn_atem_modem_result(MR_ERROR); return; } } gn_atem_modem_result(MR_OK); }