diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/gsmd/atcmd.c | 2 | ||||
| -rw-r--r-- | src/gsmd/unsolicited.c | 70 | ||||
| -rw-r--r-- | src/gsmd/usock.c | 18 | 
3 files changed, 82 insertions, 8 deletions
diff --git a/src/gsmd/atcmd.c b/src/gsmd/atcmd.c index c1d9324..356b637 100644 --- a/src/gsmd/atcmd.c +++ b/src/gsmd/atcmd.c @@ -404,7 +404,7 @@ static int ml_parse(const char *buf, int len, void *ctx)  		/* FIXME: handling of those special commands in response to  		 * ATD / ATA */ -		if (!strncmp(buf, "NO CARRIER", 11) || +		if (!strncmp(buf, "NO CARRIER", 10) ||  		    ((g->flags & GSMD_FLAG_V0) && buf[0] == '3')) {  			/* Part of Case 'D' */  			goto final_cb; diff --git a/src/gsmd/unsolicited.c b/src/gsmd/unsolicited.c index b4bf260..6e96b35 100644 --- a/src/gsmd/unsolicited.c +++ b/src/gsmd/unsolicited.c @@ -92,17 +92,75 @@ int usock_evt_send(struct gsmd *gsmd, struct gsmd_ucmd *ucmd, u_int32_t evt)  	return num_sent;  } +static void state_ringing_timeout(struct gsmd_timer *timer, void *opaque) +{ +	struct gsmd *gsmd = (struct gsmd *) opaque; +	struct gsmd_ucmd *ucmd; +	struct gsmd_evt_auxdata *aux; + +	gsmd->dev_state.ring_check = 0; +	gsmd_timer_free(timer); + +	/* Update state */ +	if (!gsmd->dev_state.ringing) +		return; +	gsmd->dev_state.ringing = 0; + +	gsmd_log(GSMD_INFO, "an incoming call timed out\n"); + +	/* Generate a timeout event */ +	ucmd = usock_build_event(GSMD_MSG_EVENT, GSMD_EVT_IN_CALL, +			sizeof(struct gsmd_evt_auxdata));	 +	if (!ucmd) +		goto err; + +	aux = (struct gsmd_evt_auxdata *) ucmd->buf; +	aux->u.call.type = GSMD_CALL_TIMEOUT; + +	if (usock_evt_send(gsmd, ucmd, GSMD_EVT_IN_CALL) < 0) +		goto err; +	return; +err: +	gsmd_log(GSMD_ERROR, "event generation failed\n"); +} + +#define GSMD_RING_MAX_JITTER (200 * 1000)	/* 0.2 s */ + +static void state_ringing_update(struct gsmd *gsmd) +{ +	struct timeval tv; + +	if (gsmd->dev_state.ring_check) +		gsmd_timer_unregister(gsmd->dev_state.ring_check); + +	/* Update state */ +	gsmd->dev_state.ringing = 1; + +	tv.tv_sec = 1; +	tv.tv_usec = GSMD_RING_MAX_JITTER; + +	if (gsmd->dev_state.ring_check) { +		gsmd->dev_state.ring_check->expires = tv; +		gsmd_timer_register(gsmd->dev_state.ring_check); +	} else +		gsmd->dev_state.ring_check = gsmd_timer_create(&tv, +				&state_ringing_timeout, gsmd); +} +  static int ring_parse(char *buf, int len, const char *param,  		      struct gsmd *gsmd)  { -	/* FIXME: generate ring event */ -	struct gsmd_ucmd *ucmd = usock_build_event(GSMD_MSG_EVENT, GSMD_EVT_IN_CALL, -					     sizeof(struct gsmd_evt_auxdata));	 +        struct gsmd_ucmd *ucmd;  	struct gsmd_evt_auxdata *aux; + +        state_ringing_update(gsmd); +        ucmd = usock_build_event(GSMD_MSG_EVENT, GSMD_EVT_IN_CALL, +                        sizeof(struct gsmd_evt_auxdata)); +	/* FIXME: generate ring event */  	if (!ucmd)  		return -ENOMEM; -	aux = (struct gsmd_evt_auxdata *)ucmd->buf; +	aux = (struct gsmd_evt_auxdata *) ucmd->buf;  	aux->u.call.type = GSMD_CALL_UNSPEC; @@ -134,7 +192,9 @@ static int cring_parse(char *buf, int len, const char *param, struct gsmd *gsmd)  		/* FIXME: change event type to GPRS */  		talloc_free(ucmd);  		return 0; -	} +	} else { +                aux->u.call.type = GSMD_CALL_UNSPEC; +        }  	/* FIXME: parse all the ALT* profiles, Chapter 6.11 */  	return usock_evt_send(gsmd, ucmd, GSMD_EVT_IN_CALL); diff --git a/src/gsmd/usock.c b/src/gsmd/usock.c index b16aff5..fd602b5 100644 --- a/src/gsmd/usock.c +++ b/src/gsmd/usock.c @@ -200,6 +200,17 @@ static int voicecall_get_stat_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)  			cmd->id, sizeof(gcs), &gcs);  } +static int usock_ringing_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp) +{ +        struct gsmd_user *gu = ctx; + +        /* If the incoming call answer/rejection succeeded then we +        * know the modem isn't ringing and we update the state info.  */ +        if (cmd->ret == 0) +                gu->gsmd->dev_state.ringing = 0; +        return usock_cmd_cb(cmd, ctx, resp); +} +  static int usock_rcv_voicecall(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,  				int len)  { @@ -223,7 +234,10 @@ static int usock_rcv_voicecall(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,  		break;  	case GSMD_VOICECALL_HANGUP:  		/* ATH0 is not supported by QC, we hope ATH is supported by everone */ -		cmd = atcmd_fill("ATH", 4, &usock_cmd_cb, gu, gph->id, NULL); +		cmd = atcmd_fill("ATH", 4, +                                gu->gsmd->dev_state.ringing ? +                                usock_ringing_cb : usock_cmd_cb, +                                gu, gph->id,NULL);                  /* This command is special because it needs to be sent to                  * the MS even if a command is currently executing.  */ @@ -232,7 +246,7 @@ static int usock_rcv_voicecall(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,                  }  		break;  	case GSMD_VOICECALL_ANSWER: -		cmd = atcmd_fill("ATA", 4, &usock_cmd_cb, gu, gph->id, NULL); +                cmd = atcmd_fill("ATA", 4, &usock_ringing_cb, gu, gph->id,NULL);  		break;  	case GSMD_VOICECALL_DTMF:  		if (len < sizeof(*gph) + sizeof(*gd))  | 
