Let the modem command generation be done in its own class too
This commit is contained in:
parent
f0e4d57e23
commit
2dfa1e0cec
2
Makefile
2
Makefile
@ -40,6 +40,7 @@ dist:
|
||||
$(PACKAGE)-$(VERSION)/src/command.c \
|
||||
$(PACKAGE)-$(VERSION)/src/gsm.c \
|
||||
$(PACKAGE)-$(VERSION)/src/main.c \
|
||||
$(PACKAGE)-$(VERSION)/src/modem.c \
|
||||
$(PACKAGE)-$(VERSION)/src/phone.c \
|
||||
$(PACKAGE)-$(VERSION)/src/contacts.c \
|
||||
$(PACKAGE)-$(VERSION)/src/dialer.c \
|
||||
@ -48,6 +49,7 @@ dist:
|
||||
$(PACKAGE)-$(VERSION)/src/callbacks.h \
|
||||
$(PACKAGE)-$(VERSION)/src/command.h \
|
||||
$(PACKAGE)-$(VERSION)/src/gsm.h \
|
||||
$(PACKAGE)-$(VERSION)/src/modem.h \
|
||||
$(PACKAGE)-$(VERSION)/src/phone.h \
|
||||
$(PACKAGE)-$(VERSION)/src/common.c \
|
||||
$(PACKAGE)-$(VERSION)/src/project.conf \
|
||||
|
@ -16,7 +16,7 @@ INSTALL = install
|
||||
|
||||
all: $(TARGETS)
|
||||
|
||||
phone_OBJS = callbacks.o command.o gsm.o main.o phone.o
|
||||
phone_OBJS = callbacks.o command.o gsm.o main.o modem.o phone.o
|
||||
phone_CFLAGS = $(CPPFLAGSF) $(CPPFLAGS) $(CFLAGSF) $(CFLAGS)
|
||||
phone_LDFLAGS = $(LDFLAGSF) $(LDFLAGS)
|
||||
|
||||
@ -47,15 +47,18 @@ phone-messages: $(phone-messages_OBJS)
|
||||
callbacks.o: callbacks.c phone.h callbacks.h
|
||||
$(CC) $(phone_CFLAGS) -c callbacks.c
|
||||
|
||||
command.o: command.c
|
||||
command.o: command.c gsm.h command.h
|
||||
$(CC) $(phone_CFLAGS) -c command.c
|
||||
|
||||
gsm.o: gsm.c command.h phone.h gsm.h
|
||||
gsm.o: gsm.c command.h phone.h modem.h gsm.h
|
||||
$(CC) $(phone_CFLAGS) -c gsm.c
|
||||
|
||||
main.o: main.c phone.h ../config.h
|
||||
$(CC) $(phone_CFLAGS) -c main.c
|
||||
|
||||
modem.o: modem.c gsm.h modem.h
|
||||
$(CC) $(phone_CFLAGS) -c modem.c
|
||||
|
||||
phone.o: phone.c gsm.h callbacks.h phone.h
|
||||
$(CC) $(phone_CFLAGS) -c phone.c
|
||||
|
||||
|
@ -23,12 +23,6 @@
|
||||
|
||||
/* GSMCommand */
|
||||
/* public */
|
||||
/* types */
|
||||
typedef struct _GSMCommand GSMCommand;
|
||||
|
||||
typedef void (*GSMCommandCallback)(GSM * gsm);
|
||||
|
||||
|
||||
/* functions */
|
||||
/* commands */
|
||||
GSMCommand * gsm_command_new(char const * command);
|
||||
|
30
src/gsm.h
30
src/gsm.h
@ -23,6 +23,8 @@
|
||||
|
||||
/* GSM */
|
||||
/* types */
|
||||
typedef struct _GSM GSM;
|
||||
|
||||
typedef enum _GSMCallType
|
||||
{
|
||||
GSM_CALL_TYPE_UNKNOWN = 0,
|
||||
@ -30,6 +32,9 @@ typedef enum _GSMCallType
|
||||
GSM_CALL_TYPE_VOICE
|
||||
} GSMCallType;
|
||||
|
||||
typedef struct _GSMCommand GSMCommand;
|
||||
typedef void (*GSMCommandCallback)(GSM * gsm);
|
||||
|
||||
typedef enum _GSMEventType
|
||||
{
|
||||
GSM_EVENT_TYPE_ERROR = 0,
|
||||
@ -213,8 +218,6 @@ typedef union _GSMEvent
|
||||
|
||||
typedef int (*GSMCallback)(GSMEvent * event, gpointer data);
|
||||
|
||||
typedef struct _GSM GSM;
|
||||
|
||||
|
||||
/* functions */
|
||||
GSM * gsm_new(char const * device, unsigned int baudrate, unsigned int hwflow);
|
||||
@ -232,10 +235,18 @@ int gsm_set_registration_report(GSM * gsm, GSMRegistrationReport report);
|
||||
int gsm_set_retry(GSM * gsm, unsigned int retry);
|
||||
|
||||
/* useful */
|
||||
int gsm_answer(GSM * gsm);
|
||||
/* call management */
|
||||
int gsm_call_answer(GSM * gsm);
|
||||
int gsm_call(GSM * gsm, GSMCallType calltype, char const * number);
|
||||
int gsm_call_contact(GSM * gsm, GSMCallType calltype, unsigned int index);
|
||||
int gsm_call_hangup(GSM * gsm);
|
||||
|
||||
int gsm_enter_sim_pin(GSM * gsm, char const * code);
|
||||
|
||||
/* event */
|
||||
int gsm_event(GSM * gsm, GSMEventType type, ...);
|
||||
|
||||
/* fetching data */
|
||||
int gsm_fetch_contact_list(GSM * gsm);
|
||||
int gsm_fetch_contacts(GSM * gsm, unsigned int start, unsigned int end);
|
||||
int gsm_fetch_message_list(GSM * gsm);
|
||||
@ -243,10 +254,21 @@ int gsm_fetch_messages(GSM * gsm, unsigned int start, unsigned int end);
|
||||
int gsm_fetch_operator(GSM * gsm);
|
||||
int gsm_fetch_registration(GSM * gsm);
|
||||
int gsm_fetch_signal_level(GSM * gsm);
|
||||
int gsm_hangup(GSM * gsm);
|
||||
|
||||
int gsm_is_pin_needed(GSM * gsm);
|
||||
int gsm_is_registered(GSM * gsm);
|
||||
|
||||
/* queue management */
|
||||
GSMCommand * gsm_queue(GSM * gsm, char const * command);
|
||||
int gsm_queue_command(GSM * gsm, GSMCommand * command);
|
||||
int gsm_queue_full(GSM * gsm, GSMPriority priority, char const * command,
|
||||
GSMError error, GSMCommandCallback callback);
|
||||
int gsm_queue_full_mode(GSM * gsm, GSMPriority priority, char const * command,
|
||||
GSMError error, GSMCommandCallback callback, GSMMode mode);
|
||||
int gsm_queue_with_error(GSM * gsm, char const * command, GSMError error);
|
||||
|
||||
int gsm_reset(GSM * gsm, unsigned int delay);
|
||||
|
||||
int gsm_send_message(GSM * gsm, char const * number, char const * text);
|
||||
|
||||
#endif /* !PHONE_GSM_H */
|
||||
|
615
src/modem.c
Normal file
615
src/modem.c
Normal file
@ -0,0 +1,615 @@
|
||||
/* $Id$ */
|
||||
/* Copyright (c) 2010 Pierre Pronchery <khorben@defora.org> */
|
||||
/* This file is part of DeforaOS Desktop Phone */
|
||||
/* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "command.h"
|
||||
#include "modem.h"
|
||||
|
||||
|
||||
/* GSMModem */
|
||||
/* private */
|
||||
/* types */
|
||||
struct _GSMModem
|
||||
{
|
||||
GSM * gsm;
|
||||
unsigned long quirks;
|
||||
};
|
||||
|
||||
|
||||
/* prototypes */
|
||||
static int _is_code(char const * code);
|
||||
static int _is_figure(int c);
|
||||
static int _is_number(char const * number);
|
||||
|
||||
|
||||
/* public */
|
||||
/* functions */
|
||||
/* gsm_modem_new */
|
||||
GSMModem * gsm_modem_new(GSM * gsm)
|
||||
{
|
||||
GSMModem * gsmm;
|
||||
|
||||
if((gsmm = malloc(sizeof(*gsmm))) == NULL)
|
||||
return NULL;
|
||||
gsmm->gsm = gsm;
|
||||
gsmm->quirks = 0;
|
||||
return gsmm;
|
||||
}
|
||||
|
||||
|
||||
/* gsm_modem_delete */
|
||||
void gsm_modem_delete(GSMModem * gsmm)
|
||||
{
|
||||
free(gsmm);
|
||||
}
|
||||
|
||||
|
||||
/* accessors */
|
||||
void gsm_modem_set_quirks(GSMModem * gsmm, unsigned long quirks)
|
||||
{
|
||||
gsmm->quirks = quirks;
|
||||
}
|
||||
|
||||
|
||||
/* useful */
|
||||
/* gsm_modem_call */
|
||||
int gsm_modem_call(GSMModem * gsmm, GSMCallType calltype, char const * number)
|
||||
{
|
||||
int ret;
|
||||
char const cmd[] = "ATD";
|
||||
char const * suffix = "";
|
||||
size_t len;
|
||||
char * buf;
|
||||
|
||||
switch(calltype)
|
||||
{
|
||||
case GSM_CALL_TYPE_DATA:
|
||||
break;
|
||||
case GSM_CALL_TYPE_VOICE:
|
||||
suffix = ";";
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
if(!_is_number(number))
|
||||
return 1;
|
||||
len = sizeof(cmd) + strlen(number) + strlen(suffix);
|
||||
if((buf = malloc(len)) == NULL)
|
||||
return 1;
|
||||
snprintf(buf, len, "%s%s%s", cmd, number, suffix);
|
||||
ret = gsm_queue_full(gsmm->gsm, GSM_PRIORITY_HIGH, buf,
|
||||
GSM_ERROR_CALL_FAILED, NULL);
|
||||
free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* gsm_modem_call_answer */
|
||||
int gsm_modem_call_answer(GSMModem * gsmm)
|
||||
{
|
||||
char const cmd[] = "ATA";
|
||||
|
||||
return gsm_queue_with_error(gsmm->gsm, cmd, GSM_ERROR_ANSWER_FAILED);
|
||||
}
|
||||
|
||||
|
||||
/* gsm_modem_call_contact */
|
||||
int gsm_modem_call_contact(GSMModem * gsmm, GSMCallType calltype,
|
||||
unsigned int index)
|
||||
{
|
||||
char const cmd[] = "ATD>";
|
||||
char const * suffix = "";
|
||||
char buf[32];
|
||||
|
||||
switch(calltype)
|
||||
{
|
||||
case GSM_CALL_TYPE_DATA:
|
||||
break;
|
||||
case GSM_CALL_TYPE_VOICE:
|
||||
suffix = ";";
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
snprintf(buf, sizeof(buf), "%s%u%s", cmd, index, suffix);
|
||||
return gsm_queue_full(gsmm->gsm, GSM_PRIORITY_HIGH, buf,
|
||||
GSM_ERROR_CALL_FAILED, NULL);
|
||||
}
|
||||
|
||||
|
||||
/* gsm_modem_call_hangup */
|
||||
int gsm_modem_call_hangup(GSMModem * gsmm)
|
||||
{
|
||||
char const cmd[] = "ATH";
|
||||
|
||||
/* XXX probably should query the call status after that */
|
||||
return gsm_queue_full(gsmm->gsm, GSM_PRIORITY_HIGH, cmd,
|
||||
GSM_ERROR_HANGUP_FAILED, NULL);
|
||||
}
|
||||
|
||||
|
||||
/* gsm_modem_call_last */
|
||||
int gsm_modem_call_last(GSMModem * gsmm, GSMCallType calltype)
|
||||
{
|
||||
char const cmddata[] = "ATDL";
|
||||
char const cmdvoice[] = "ATDL;";
|
||||
char const * cmd;
|
||||
|
||||
switch(calltype)
|
||||
{
|
||||
case GSM_CALL_TYPE_DATA:
|
||||
cmd = cmddata;
|
||||
break;
|
||||
case GSM_CALL_TYPE_VOICE:
|
||||
cmd = cmdvoice;
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
return gsm_queue_full(gsmm->gsm, GSM_PRIORITY_HIGH, cmd,
|
||||
GSM_ERROR_CALL_FAILED, NULL);
|
||||
}
|
||||
|
||||
|
||||
/* gsm_modem_enter_sim_pin */
|
||||
void _modem_enter_sim_pin_callback(GSM * gsm);
|
||||
|
||||
int gsm_modem_enter_sim_pin(GSMModem * gsmm, char const * code)
|
||||
{
|
||||
int ret;
|
||||
char const cmd[] = "AT+CPIN=";
|
||||
size_t len;
|
||||
char * buf;
|
||||
|
||||
if(!_is_code(code))
|
||||
{
|
||||
gsm_event(gsmm->gsm, GSM_EVENT_TYPE_ERROR, GSM_ERROR_SIM_PIN_WRONG);
|
||||
return 1;
|
||||
}
|
||||
len = sizeof(cmd) + 1 + strlen(code) + 1;
|
||||
if((buf = malloc(len)) == NULL)
|
||||
return 1;
|
||||
if(gsmm->quirks & GSM_MODEM_QUIRK_CPIN_QUOTES)
|
||||
snprintf(buf, len, "%s\"%s\"", cmd, code);
|
||||
else
|
||||
snprintf(buf, len, "%s%s", cmd, code);
|
||||
ret = gsm_queue_full(gsmm->gsm, GSM_PRIORITY_NORMAL, buf,
|
||||
GSM_ERROR_SIM_PIN_WRONG, _modem_enter_sim_pin_callback);
|
||||
free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void _modem_enter_sim_pin_callback(GSM * gsm)
|
||||
{
|
||||
gsm_event(gsm, GSM_EVENT_TYPE_SIM_PIN_VALID);
|
||||
/* do we need another PIN code? */
|
||||
gsm_is_pin_needed(gsm);
|
||||
}
|
||||
|
||||
|
||||
/* gsm_modem_get_contact_list */
|
||||
int gsm_modem_get_contact_list(GSMModem * gsmm)
|
||||
{
|
||||
char const cmd[] = "AT+CPBR=?";
|
||||
|
||||
return gsm_queue_with_error(gsmm->gsm, cmd, GSM_ERROR_CONTACT_LIST_FAILED);
|
||||
}
|
||||
|
||||
|
||||
/* gsm_modem_get_contacts */
|
||||
int gsm_modem_get_contacts(GSMModem * gsmm, unsigned int start,
|
||||
unsigned int end)
|
||||
{
|
||||
char cmd[32];
|
||||
|
||||
snprintf(cmd, sizeof(cmd), "%s%u,%u", "AT+CPBR=", start, end);
|
||||
return gsm_queue_full(gsmm->gsm, GSM_PRIORITY_LOW, cmd,
|
||||
GSM_ERROR_CONTACT_FETCH_FAILED, NULL);
|
||||
}
|
||||
|
||||
|
||||
/* gsm_modem_get_message_list */
|
||||
int gsm_modem_get_message_list(GSMModem * gsmm)
|
||||
{
|
||||
char const cmd[] = "AT+CMGL=?";
|
||||
|
||||
return gsm_queue_with_error(gsmm->gsm, cmd, GSM_ERROR_MESSAGE_LIST_FAILED);
|
||||
}
|
||||
|
||||
|
||||
/* gsm_modem_get_messages */
|
||||
int gsm_modem_get_messages(GSMModem * gsmm, unsigned int start,
|
||||
unsigned int end)
|
||||
{
|
||||
char cmd[32];
|
||||
|
||||
snprintf(cmd, sizeof(cmd), "%s%u,%u", "AT+CMGR=", start, end);
|
||||
return gsm_queue_full(gsmm->gsm, GSM_PRIORITY_LOW, cmd,
|
||||
GSM_ERROR_MESSAGE_FETCH_FAILED, NULL);
|
||||
}
|
||||
|
||||
|
||||
/* gsm_modem_get_model */
|
||||
int gsm_modem_get_model(GSMModem * gsmm)
|
||||
{
|
||||
char const cmd[] = "AT+CGMM";
|
||||
|
||||
return (gsm_queue(gsmm->gsm, cmd) != NULL) ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
/* gsm_modem_get_operator */
|
||||
int gsm_modem_get_operator(GSMModem * gsmm)
|
||||
{
|
||||
char const cmd[] = "AT+COPS?";
|
||||
|
||||
return (gsm_queue(gsmm->gsm, cmd) != NULL) ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
/* gsm_modem_get_registration */
|
||||
int gsm_modem_get_registration(GSMModem * gsmm)
|
||||
{
|
||||
char const cmd[] = "AT+CREG?";
|
||||
|
||||
return (gsm_queue(gsmm->gsm, cmd) != NULL) ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
/* gsm_modem_get_signal_level */
|
||||
int gsm_modem_get_signal_level(GSMModem * gsmm)
|
||||
{
|
||||
char const cmd[] = "AT+CSQ";
|
||||
|
||||
return gsm_queue_with_error(gsmm->gsm, cmd, GSM_ERROR_SIGNAL_LEVEL_FAILED);
|
||||
}
|
||||
|
||||
|
||||
/* gsm_modem_is_pin_needed */
|
||||
int gsm_modem_is_pin_needed(GSMModem * gsmm)
|
||||
{
|
||||
char const cmd[] = "AT+CPIN?";
|
||||
|
||||
return (gsm_queue(gsmm->gsm, cmd) != NULL) ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
/* gsm_modem_is_registered */
|
||||
int gsm_modem_is_registered(GSMModem * gsmm)
|
||||
{
|
||||
char const cmd[] = "AT+CREG?";
|
||||
|
||||
return (gsm_queue(gsmm->gsm, cmd) != NULL) ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
/* gsm_modem_reset */
|
||||
int gsm_modem_reset(GSMModem * gsmm)
|
||||
{
|
||||
char const cmd[] = "ATZ";
|
||||
|
||||
return gsm_queue_full(gsmm->gsm, GSM_PRIORITY_HIGH, cmd,
|
||||
GSM_ERROR_RESET_FAILED, NULL);
|
||||
}
|
||||
|
||||
|
||||
/* gsm_modem_send_message */
|
||||
char * _number_to_address(char const * number);
|
||||
char * _text_to_sept(char const * text);
|
||||
|
||||
int gsm_modem_send_message(GSMModem * gsmm, char const * number,
|
||||
char const * text)
|
||||
{
|
||||
int ret = 1;
|
||||
char const cmd1[] = "AT+CMGS=";
|
||||
char * buf1;
|
||||
size_t len1;
|
||||
char const cmd2[] = "1100";
|
||||
char * buf2;
|
||||
size_t len2;
|
||||
char * addr;
|
||||
char * sept;
|
||||
char const pid[] = "00";
|
||||
char const dcs[] = "00";
|
||||
char const vp[] = "AA";
|
||||
GSMCommand * gsmc;
|
||||
|
||||
if(!_is_number(number) || text == NULL
|
||||
|| gsm_modem_set_message_format(gsmm,
|
||||
GSM_MESSAGE_FORMAT_PDU) != 0)
|
||||
return gsm_event(gsmm->gsm, GSM_EVENT_TYPE_ERROR,
|
||||
GSM_ERROR_MESSAGE_SEND_FAILED, NULL);
|
||||
addr = _number_to_address(number);
|
||||
sept = _text_to_sept(text);
|
||||
len2 = sizeof(cmd2) + 2 + strlen(addr ? addr : "") + sizeof(pid)
|
||||
+ sizeof(dcs) + 2 + strlen(sept ? sept : "") + 1;
|
||||
buf2 = malloc(len2);
|
||||
len1 = sizeof(cmd1) + 2;
|
||||
buf1 = malloc(len1);
|
||||
if(addr == NULL || sept == NULL || buf1 == NULL || buf2 == NULL)
|
||||
{
|
||||
free(addr);
|
||||
free(sept);
|
||||
free(buf1);
|
||||
free(buf2);
|
||||
return gsm_event(gsmm->gsm, GSM_EVENT_TYPE_ERROR,
|
||||
GSM_ERROR_MESSAGE_SEND_FAILED, NULL);
|
||||
}
|
||||
snprintf(buf2, len2, "%s%02lX%s%s%s%s%02lX%s\x1a", cmd2,
|
||||
number[0] == '+' ? strlen(number) - 1 : strlen(number),
|
||||
addr, pid, dcs, vp, strlen(text), sept);
|
||||
snprintf(buf1, len1, "%s%lu", cmd1, (len2 - 1) / 2);
|
||||
free(addr);
|
||||
free(sept);
|
||||
if((gsmc = gsm_command_new(buf1)) != NULL
|
||||
&& (ret = gsm_queue_command(gsmm->gsm, gsmc)) == 0)
|
||||
{
|
||||
gsm_command_set_error(gsmc, GSM_ERROR_MESSAGE_SEND_FAILED);
|
||||
gsm_command_set_mode(gsmc, GSM_MODE_PDU);
|
||||
gsm_command_set_priority(gsmc, GSM_PRIORITY_HIGHEST);
|
||||
if((gsmc = gsm_command_new(buf2)) != NULL
|
||||
/* XXX if this fails we're stuck in PDU mode */
|
||||
&& (ret = gsm_queue_command(gsmm->gsm, gsmc)) == 0)
|
||||
{
|
||||
gsm_command_set_error(gsmc,
|
||||
GSM_ERROR_MESSAGE_SEND_FAILED);
|
||||
gsm_command_set_priority(gsmc, GSM_PRIORITY_HIGHEST);
|
||||
}
|
||||
}
|
||||
if(ret != 0)
|
||||
gsm_command_delete(gsmc);
|
||||
free(buf1);
|
||||
free(buf2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
char * _number_to_address(char const * number)
|
||||
{
|
||||
char * buf;
|
||||
size_t len;
|
||||
size_t i;
|
||||
|
||||
len = 2 + strlen(number) + 2;
|
||||
if((buf = malloc(len)) == NULL)
|
||||
return NULL;
|
||||
snprintf(buf, len, "%02X", (number[0] == '+') ? 145 : 129);
|
||||
if(number[0] == '+')
|
||||
number++;
|
||||
for(i = 2; i < len; i+=2)
|
||||
{
|
||||
if(number[i - 2] == '\0')
|
||||
break;
|
||||
buf[i] = number[i - 1];
|
||||
buf[i + 1] = number[i - 2];
|
||||
if(number[i - 1] == '\0')
|
||||
{
|
||||
buf[i] = 'F';
|
||||
i += 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
buf[i] = '\0';
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* this function is heavily inspired from gsmd, (c) 2007 OpenMoko, Inc. */
|
||||
char * _text_to_sept(char const * text)
|
||||
{
|
||||
char const tab[] = "0123456789ABCDEF";
|
||||
unsigned char const * t = (unsigned char const *)text;
|
||||
char * buf;
|
||||
size_t len;
|
||||
char * p;
|
||||
size_t i;
|
||||
unsigned char ch1;
|
||||
unsigned char ch2;
|
||||
int shift = 0;
|
||||
|
||||
len = strlen(text);
|
||||
if((buf = malloc(len + 1)) == NULL)
|
||||
return NULL;
|
||||
p = buf;
|
||||
for(i = 0; i < len; i++)
|
||||
{
|
||||
ch1 = t[i] & 0x7f;
|
||||
ch1 = (ch1 >> shift);
|
||||
ch2 = t[i + 1] & 0x7f;
|
||||
ch2 = ch2 << (7 - shift);
|
||||
ch1 = ch1 | ch2;
|
||||
*(p++) = tab[(ch1 & 0xf0) >> 4];
|
||||
*(p++) = tab[ch1 & 0x0f];
|
||||
if(++shift == 7)
|
||||
{
|
||||
shift = 0;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
*p = '\0';
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
/* gsm_modem_set_echo */
|
||||
int gsm_modem_set_echo(GSMModem * gsmm, gboolean echo)
|
||||
{
|
||||
char cmd[] = "ATEX";
|
||||
|
||||
cmd[3] = echo ? '1' : '0';
|
||||
return (gsm_queue(gsmm->gsm, cmd) != NULL) ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
/* gsm_modem_set_extended_errors */
|
||||
int gsm_modem_set_extended_errors(GSMModem * gsmm, gboolean extended)
|
||||
{
|
||||
char cmd[] = "AT+CMEE=X";
|
||||
|
||||
cmd[8] = extended ? '1' : '0';
|
||||
return (gsm_queue(gsmm->gsm, cmd) != NULL) ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
/* gsm_modem_set_extended_ring_reports */
|
||||
int gsm_modem_set_extended_ring_reports(GSMModem * gsmm, gboolean extended)
|
||||
{
|
||||
char cmd[] = "AT+CRC=X";
|
||||
|
||||
cmd[7] = extended ? '1' : '0';
|
||||
return (gsm_queue(gsmm->gsm, cmd) != NULL) ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
/* gsm_modem_set_functional */
|
||||
int gsm_modem_set_functional(GSMModem * gsmm, gboolean functional)
|
||||
{
|
||||
char cmd[] = "AT+CFUN=X";
|
||||
|
||||
cmd[8] = functional ? '1' : '0';
|
||||
return gsm_queue_with_error(gsmm->gsm, cmd, GSM_ERROR_FUNCTIONAL_FAILED);
|
||||
}
|
||||
|
||||
|
||||
/* gsm_modem_set_message_format */
|
||||
int gsm_modem_set_message_format(GSMModem * gsmm, GSMMessageFormat format)
|
||||
{
|
||||
char cmd[] = "AT+CMGF=X";
|
||||
|
||||
switch(format)
|
||||
{
|
||||
case GSM_MESSAGE_FORMAT_PDU:
|
||||
case GSM_MESSAGE_FORMAT_TEXT:
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
cmd[8] = format + '0';
|
||||
return (gsm_queue(gsmm->gsm, cmd) != NULL) ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
/* gsm_modem_set_operator_format */
|
||||
int gsm_modem_set_operator_format(GSMModem * gsmm, GSMOperatorFormat format)
|
||||
{
|
||||
char cmd[] = "AT+COPS=X,X";
|
||||
|
||||
switch(format)
|
||||
{
|
||||
case GSM_OPERATOR_FORMAT_LONG:
|
||||
case GSM_OPERATOR_FORMAT_SHORT:
|
||||
case GSM_OPERATOR_FORMAT_LAI:
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
cmd[8] = GSM_OPERATOR_MODE_SET_FORMAT + '0';
|
||||
cmd[10] = format + '0';
|
||||
return (gsm_queue(gsmm->gsm, cmd) != NULL) ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
/* gsm_modem_set_operator_mode */
|
||||
int gsm_modem_set_operator_mode(GSMModem * gsmm, GSMOperatorMode mode)
|
||||
{
|
||||
char cmd[] = "AT+COPS=X";
|
||||
GSMCommand * gsmc;
|
||||
|
||||
switch(mode)
|
||||
{
|
||||
case GSM_OPERATOR_MODE_AUTOMATIC:
|
||||
case GSM_OPERATOR_MODE_MANUAL:
|
||||
case GSM_OPERATOR_MODE_DEREGISTER:
|
||||
break;
|
||||
case GSM_OPERATOR_MODE_MANUAL_WITH_FALLBACK:
|
||||
/* FIXME implement this one too */
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
cmd[8] = mode + '0';
|
||||
if((gsmc = gsm_queue(gsmm->gsm, cmd)) == NULL)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* gsm_modem_set_registration_report */
|
||||
int gsm_modem_set_registration_report(GSMModem * gsmm,
|
||||
GSMRegistrationReport report)
|
||||
{
|
||||
char cmd[] = "AT+CREG=X";
|
||||
|
||||
switch(report)
|
||||
{
|
||||
case GSM_REGISTRATION_REPORT_DISABLE_UNSOLLICITED:
|
||||
case GSM_REGISTRATION_REPORT_ENABLE_UNSOLLICITED:
|
||||
case GSM_REGISTRATION_REPORT_ENABLE_UNSOLLICITED_WITH_LOCATION:
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
cmd[8] = report + '0';
|
||||
return (gsm_queue(gsmm->gsm, cmd) != NULL) ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
/* gsm_modem_set_verbose */
|
||||
int gsm_modem_set_verbose(GSMModem * gsmm, gboolean verbose)
|
||||
{
|
||||
char cmd[] = "ATVX";
|
||||
|
||||
cmd[3] = verbose ? '1' : '0';
|
||||
return (gsm_queue(gsmm->gsm, cmd) != NULL) ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
/* private */
|
||||
/* functions */
|
||||
/* is_code */
|
||||
static int _is_code(char const * code)
|
||||
{
|
||||
int c;
|
||||
|
||||
while((c = *(code++)) != '\0')
|
||||
if(!isdigit(c))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* is_figure */
|
||||
static int _is_figure(int c)
|
||||
{
|
||||
if(c >= '0' && c <= '9')
|
||||
return 1;
|
||||
if(c == '*' || c == '+' || c == '#')
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* is_number */
|
||||
static int _is_number(char const * number)
|
||||
{
|
||||
if(number == NULL || number[0] == '\0')
|
||||
return 0;
|
||||
while(*number != '\0')
|
||||
if(!_is_figure(*(number++)))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
80
src/modem.h
Normal file
80
src/modem.h
Normal file
@ -0,0 +1,80 @@
|
||||
/* $Id$ */
|
||||
/* Copyright (c) 2010 Pierre Pronchery <khorben@defora.org> */
|
||||
/* This file is part of DeforaOS Desktop Phone */
|
||||
/* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
|
||||
|
||||
#ifndef PHONE_MODEM_H
|
||||
# define PHONE_MODEM_H
|
||||
|
||||
# include "gsm.h"
|
||||
|
||||
|
||||
/* GSMModem */
|
||||
/* public */
|
||||
/* types */
|
||||
typedef struct _GSMModem GSMModem;
|
||||
|
||||
typedef enum _GSMModemQuirk
|
||||
{
|
||||
GSM_MODEM_QUIRK_NONE = 0,
|
||||
GSM_MODEM_QUIRK_CPIN_QUOTES = 1
|
||||
} GSMModemQuirk;
|
||||
|
||||
|
||||
/* prototypes */
|
||||
GSMModem * gsm_modem_new(GSM * gsm);
|
||||
void gsm_modem_delete(GSMModem * gsmm);
|
||||
|
||||
/* accessors */
|
||||
void gsm_modem_set_quirks(GSMModem * gsmm, unsigned long quirks);
|
||||
|
||||
/* useful */
|
||||
int gsm_modem_call(GSMModem * gsmm, GSMCallType calltype, char const * number);
|
||||
int gsm_modem_call_answer(GSMModem * gsmm);
|
||||
int gsm_modem_call_contact(GSMModem * gsmm, GSMCallType calltype,
|
||||
unsigned int index);
|
||||
int gsm_modem_call_hangup(GSMModem * gsmm);
|
||||
int gsm_modem_call_last(GSMModem * gsmm, GSMCallType calltype);
|
||||
|
||||
int gsm_modem_enter_sim_pin(GSMModem * gsmm, char const * code);
|
||||
|
||||
int gsm_modem_get_contact_list(GSMModem * gsmm);
|
||||
int gsm_modem_get_contacts(GSMModem * gsmm, unsigned int start, unsigned int end);
|
||||
int gsm_modem_get_message_list(GSMModem * gsmm);
|
||||
int gsm_modem_get_messages(GSMModem * gsmm, unsigned int start, unsigned int end);
|
||||
int gsm_modem_get_model(GSMModem * gsmm);
|
||||
int gsm_modem_get_operator(GSMModem * gsmm);
|
||||
int gsm_modem_get_registration(GSMModem * gsmm);
|
||||
int gsm_modem_get_signal_level(GSMModem * gsmm);
|
||||
|
||||
int gsm_modem_is_pin_needed(GSMModem * gsmm);
|
||||
int gsm_modem_is_registered(GSMModem * gsmm);
|
||||
|
||||
int gsm_modem_reset(GSMModem * gsmm);
|
||||
|
||||
int gsm_modem_send_message(GSMModem * gsmm, char const * number, char const * text);
|
||||
|
||||
int gsm_modem_set_echo(GSMModem * gsmm, gboolean echo);
|
||||
int gsm_modem_set_extended_errors(GSMModem * gsmm, gboolean extended);
|
||||
int gsm_modem_set_extended_ring_reports(GSMModem * gsmm, gboolean extended);
|
||||
int gsm_modem_set_functional(GSMModem * gsmm, gboolean functional);
|
||||
int gsm_modem_set_message_format(GSMModem * gsmm, GSMMessageFormat format);
|
||||
int gsm_modem_set_operator_format(GSMModem * gsmm, GSMOperatorFormat format);
|
||||
int gsm_modem_set_operator_mode(GSMModem * gsmm, GSMOperatorMode mode);
|
||||
int gsm_modem_set_registration_report(GSMModem * gsmm,
|
||||
GSMRegistrationReport report);
|
||||
int gsm_modem_set_verbose(GSMModem * gsmm, gboolean verbose);
|
||||
|
||||
#endif /* !PHONE_MODEM_H */
|
@ -420,7 +420,7 @@ int phone_dialer_append(Phone * phone, char character)
|
||||
/* phone_hangup */
|
||||
void phone_hangup(Phone * phone)
|
||||
{
|
||||
gsm_hangup(phone->gsm);
|
||||
gsm_call_hangup(phone->gsm);
|
||||
if(phone->di_window != NULL)
|
||||
gtk_entry_set_text(GTK_ENTRY(phone->di_entry), "");
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ targets=phone,phone-contacts,phone-dialer,phone-messages
|
||||
cflags_force=-W
|
||||
cflags=-Wall -g -O2 -pedantic `pkg-config --cflags gtk+-2.0`
|
||||
ldflags_force=`pkg-config --libs gtk+-2.0`
|
||||
dist=Makefile,callbacks.h,command.h,gsm.h,phone.h,common.c
|
||||
dist=Makefile,callbacks.h,command.h,gsm.h,modem.h,phone.h,common.c
|
||||
|
||||
[phone-contacts]
|
||||
type=binary
|
||||
@ -30,17 +30,23 @@ depends=common.c
|
||||
|
||||
[phone]
|
||||
type=binary
|
||||
sources=callbacks.c,command.c,gsm.c,main.c,phone.c
|
||||
sources=callbacks.c,command.c,gsm.c,main.c,modem.c,phone.c
|
||||
install=$(BINDIR)
|
||||
|
||||
[callbacks.c]
|
||||
depends=phone.h,callbacks.h
|
||||
|
||||
[command.c]
|
||||
depends=gsm.h,command.h
|
||||
|
||||
[gsm.c]
|
||||
depends=command.h,phone.h,gsm.h
|
||||
depends=command.h,phone.h,modem.h,gsm.h
|
||||
|
||||
[main.c]
|
||||
depends=phone.h,../config.h
|
||||
|
||||
[modem.c]
|
||||
depends=gsm.h,modem.h
|
||||
|
||||
[phone.c]
|
||||
depends=gsm.h,callbacks.h,phone.h
|
||||
|
Loading…
Reference in New Issue
Block a user