Esempio n. 1
0
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;
		}
	}
}
Esempio n. 2
0
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");
	}
}
Esempio n. 3
0
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);
}
Esempio n. 4
0
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;
	}
}
Esempio n. 5
0
/* 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);
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
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);
		}