static void wake_pending_after_delay(struct gsmd *g, u_int8_t channel, u_int32_t initial_delay_secs) { struct timeval tv; if (g->chl_100ms_wait[channel].cb) { gsmd_log(GSMD_NOTICE, "wait already set\n"); } else { if (initial_delay_secs) { tv.tv_sec = initial_delay_secs; tv.tv_usec = 0; gsmd_log(GSMD_NOTICE, "long initial delay %d secs\n",initial_delay_secs); } else { /* Siemens specify a minimum 100ms delay before sending the next command in a sequence */ tv.tv_sec = 0; tv.tv_usec = 100000; } if (gsmd_timer_set(&g->chl_100ms_wait[channel], &tv, &wait_pending_timeout, g)) { gsmd_log(GSMD_ERROR, "failed to set pending timeout\n"); g->chl_100ms_wait[channel].cb = NULL; } } }
static void wait_pending_timeout(struct gsmd_timer *tmr, void *data) { struct gsmd *g = data; struct gsmd_atcmd *cmd = NULL; u_int8_t channel = 0; int found = 0; for (channel = 0; channel < GSMD_MAX_CHANNELS; channel++) { if (&g->chl_100ms_wait[channel] == tmr) { found = 1; break; } } if (!found) { gsmd_log(GSMD_ERROR, "Unknown 100ms timeout\n"); return; } g->chl_100ms_wait[channel].cb = NULL; if (!llist_empty(&g->pending_atcmds[channel])) { atcmd_wake_pending_queue(g,channel); } else { DEBUGP("Nothing more to send\n"); } }
static void alive_tmr_cb(struct gsmd_timer *tmr, void *data) { struct gsmd *g = data; DEBUGP("gsmd_alive timer expired\n"); if (g->alive_responded == 0) { gsmd_log(GSMD_FATAL, "modem dead!\n"); exit(3); } else gsmd_log(GSMD_INFO, "modem alive!\n"); /* FIXME: update some global state */ gsmd_timer_free(tmr); }
static void cancel_pending_timeout(struct gsmd *g, u_int8_t channel) { if (g->chl_100ms_wait[channel].cb) { gsmd_log(GSMD_NOTICE, "cancelled 100ms wait\n"); gsmd_timer_unregister(&g->chl_100ms_wait[channel]); g->chl_100ms_wait[channel].cb = NULL; } }
/* we submit the first atcmd and wait synchronously for a valid response */ static int firstcmd_atcb(struct gsmd_atcmd *cmd, void *ctx, char *resp) { struct gsmd *gsmd = ctx; if (strcmp(resp, "OK") && (!(gsmd->flags & GSMD_FLAG_V0) || resp[0] != '0')) { // temporarily changed to GSMD_ERROR instead of GSMD_FATAL + commented out exit(4) :M: gsmd_log(GSMD_ERROR, "response '%s' to initial command invalid", resp); //exit(4); } firstcmd_response = 1; if (daemonize) { if (fork()) { exit(0); } fclose(stdout); fclose(stderr); fclose(stdin); setsid(); } return gsmd_initsettings2(gsmd); }
static int siemens_call_status(char *buf, int len, const char *param, struct gsmd *gsmd) { //^SLCC: 1,0,0,0,0,1,"01223303528",129,"" // idx dir stat mode mpty tch number type alpha int retval = 0; char *comma = strchr(param, ','); gsmd_log(GSMD_DEBUG, "received call status (%s)\n",param); if (comma && ++comma) { unsigned char val = atoi(comma); received_valid_slcc = 1; gsmd_log(GSMD_NOTICE, "dir <%d>\n",val); comma = strchr(comma, ','); if (comma && ++comma) { struct gsmd_ucmd *ucmd = usock_build_event(GSMD_MSG_EVENT, GSMD_EVT_OUT_STATUS, sizeof(struct gsmd_evt_auxdata)); val = atoi(comma); gsmd_log(GSMD_NOTICE, "stat <%d>\n",val); if (valid_ucmd(ucmd)) { struct gsmd_evt_auxdata *eaux = ((void *)ucmd) + sizeof(struct gsmd_ucmd); char* out_ptr = (char*) &eaux->u.call_status.addr.number; switch (val) { case 0: gsmd_log(GSMD_DEBUG, "active\n"); eaux->u.call_status.prog = GSMD_CALLPROG_CONNECTED; break; case 1: gsmd_log(GSMD_DEBUG, "held\n"); break; case 2: gsmd_log(GSMD_DEBUG, "dialling\n"); eaux->u.call_status.prog = GSMD_CALLPROG_SETUP; break; case 3: gsmd_log(GSMD_DEBUG, "remote end is ringing\n"); eaux->u.call_status.prog = GSMD_CALLPROG_PROGRESS; break; case 4: gsmd_log(GSMD_DEBUG, "incoming call\n"); eaux->u.call_status.prog = GSMD_CALLPROG_ALERT; break; case 5: gsmd_log(GSMD_DEBUG, "call waiting\n"); break; } comma = strchr(comma, '"'); if (comma && ++comma) { char* t_ptr = comma; int loop; gsmd_log(GSMD_DEBUG, "t_ptr %s\n",t_ptr); if (t_ptr) { for (loop = 0; loop <= GSMD_ADDR_MAXLEN; loop++) { if (*t_ptr) { if (*t_ptr == '"') break; *out_ptr++ = *t_ptr++; } else { break; } } } } *out_ptr = 0; gsmd_log(GSMD_DEBUG, "call %s\n",eaux->u.call_status.addr.number); } retval = usock_evt_send(gsmd, ucmd, GSMD_EVT_OUT_STATUS); } } else { if (received_valid_slcc) { // Ignore if valid SLCC received prior to this SLCC gsmd_log(GSMD_DEBUG, "Ignoring blank SLCC\n"); received_valid_slcc = 0; } else { // Disconnected struct gsmd_ucmd *ucmd = usock_build_event(GSMD_MSG_EVENT, GSMD_EVT_OUT_STATUS, sizeof(struct gsmd_evt_auxdata)); if (valid_ucmd(ucmd)) { struct gsmd_evt_auxdata *eaux = ((void *)ucmd) + sizeof(struct gsmd_ucmd); eaux->u.call_status.prog = GSMD_CALLPROG_RELEASE; eaux->u.call_status.addr.number[0] = 0; } retval = usock_evt_send(gsmd, ucmd, GSMD_EVT_OUT_STATUS); } } return retval; }
static int atcmd_done(struct gsmd *g, struct gsmd_atcmd *cmd, const char *buf, u_int8_t channel) { int rc = 0; #if ENABLE_TIMEOUTS remove_channel_timeout(g, channel); #endif if (!cmd) { gsmd_log(GSMD_ERROR, "* Null cmd? *\n"); return -1; } if (!cmd->cb) { gsmd_log(GSMD_NOTICE, "command without cb!!!\n"); } else { cmd->flags = ATCMD_FINAL_CB_FLAG; /* send final result code if there is no information * response in mlbuf */ if (g->mlbuf_len[channel]) { cmd->resp = g->mlbuf[channel]; cmd->resplen = g->mlbuf_len[channel]; cmd->resp[cmd->resplen] = 0; } else { cmd->resp = (char*) buf; cmd->resplen = strlen(buf); } DEBUGP("Calling final cmd->cb() %d <%s>(%d) <%d>\n", g->mlbuf_len[channel],cmd->resp,cmd->resplen,cmd->ret); rc = cmd->cb(cmd, cmd->ctx, cmd->resp); if (rc < 0) { gsmd_log(GSMD_ERROR, "Failed to create response for client\n"); } DEBUGP("Clearing mlbuf\n"); g->mlbuf_len[channel] = 0; g->mlbuf[channel][0] = 0; } /* remove from list of currently executing cmds */ llist_del(&cmd->list); #if ENABLE_TIMEOUTS if (TIMEOUT_ERRORCODE == cmd->ret && STATUS_OK == g->modem_status) check_channel(g,channel); #endif atcmd_free(cmd); /* We're finished with the current command, but if still have pending * command(s) then pop off the first pending */ if (llist_empty(&g->busy_atcmds[channel])) { struct gsmd_atcmd *cur = NULL; u_int32_t initial_delay_secs = 0; if (!llist_empty(&g->pending_atcmds[channel])) { gsmd_log(GSMD_INFO, "cmds pending\n"); cur = llist_entry(g->pending_atcmds[channel].next, struct gsmd_atcmd, list); if (cur) { initial_delay_secs = cur->initial_delay_secs; } else { gsmd_log(GSMD_ERROR, "First pending is null?\n"); } } if (g->pin_status) { if (cur) { if (cur->flags & ATCMD_PIN_SENSITIVE) { gsmd_log(GSMD_INFO, "pin_status %d\n",g->pin_status); if (g->sim_status == GSM0707_CME_SIM_NOT_INSERTED) { gsmd_log(GSMD_INFO, "sim not inserted\n"); /* allow the modem to fail the cmd */ wake_pending_after_delay( g,channel,initial_delay_secs); } else { gsmd_log(GSMD_INFO, "* pin sensitive cmd delayed *\n"); g->pin_sensitive_cmds_waiting = 1; } } else { gsmd_log(GSMD_INFO, "wake pending after %d\n", initial_delay_secs); wake_pending_after_delay(g,channel,initial_delay_secs); } } } else { if (g->pin_sensitive_cmds_waiting) { if (cur && (cur->flags & ATCMD_PIN_SENSITIVE)) { u_int8_t ch_iter = 0; gsmd_log(GSMD_INFO, "chk chnls for pin delayed cmds\n"); for (ch_iter = 0; ch_iter < g->number_channels; ch_iter++) { if (ch_iter == channel) continue; if (!llist_empty(&g->pending_atcmds[ch_iter])) { struct gsmd_atcmd *cur2 = llist_entry(g->pending_atcmds[ch_iter].next, struct gsmd_atcmd, list); if (cur2 && (cur2->flags & ATCMD_PIN_SENSITIVE)) { gsmd_log(GSMD_INFO, "* waking chnl %d *\n", ch_iter); wake_pending_after_delay( g, ch_iter, initial_delay_secs); } } } g->pin_sensitive_cmds_waiting = 0; } } gsmd_log(GSMD_INFO, "wake pending after %d secs\n", initial_delay_secs); wake_pending_after_delay(g, channel,initial_delay_secs); }