diff --git a/src/gsm.c b/src/gsm.c deleted file mode 100644 index 6583906..0000000 --- a/src/gsm.c +++ /dev/null @@ -1,2705 +0,0 @@ -/* $Id$ */ -/* Copyright (c) 2011 Pierre Pronchery */ -/* 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 . */ - - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "command.h" -#include "modem.h" -#include "gsm.h" -#define _(string) gettext(string) -#define N_(string) (string) - -#define min(a, b) ((a) < (b) ? (a) : (b)) - - -/* GSM */ -/* private */ -/* types */ -typedef int (*GSMTriggerCallback)(GSM * gsm, char const * result, - gboolean * answered); - -typedef struct _GSMTrigger -{ - char const * trigger; - size_t trigger_cnt; - GSMTriggerCallback callback; -} GSMTrigger; - -struct _GSM -{ - /* settings */ - char * device; - unsigned int baudrate; - unsigned int retry; - unsigned int hwflow; - char * username; - char * password; - - /* callback */ - GSMCallback callback; - gpointer callback_data; - GSMEvent event; - GSMStatus status; - - /* queue */ - GSList * queue; - - /* internal */ - GSMModem * modem; - GSMMode mode; - guint source; - GIOChannel * channel; - char * rd_buf; - size_t rd_buf_cnt; - guint rd_source; - char * wr_buf; - size_t wr_buf_cnt; - guint wr_source; - GIOChannel * rd_ppp_channel; - guint rd_ppp_source; - GIOChannel * wr_ppp_channel; - guint wr_ppp_source; - - /* temporary buffers */ - char number[32]; -}; - - -/* variables */ -/* conversions */ -static struct -{ - unsigned char gsm; - unsigned char iso; -} _gsm_conv[] = -{ - { '\0', '@' }, - { 0x01, 163 }, /* £ */ - { 0x02, '$' }, - { 0x03, 165 }, /* ¥ */ - { 0x04, 232 }, /* è */ - { 0x05, 233 }, /* é */ - { 0x06, 249 }, /* ù */ - { 0x07, 236 }, /* ì */ - { 0x08, 242 }, /* ò */ - { 0x09, 199 }, /* Ç */ - { 0x0b, 216 }, /* Ø */ - { 0x0c, 248 }, /* ø */ - { 0x0e, 197 }, /* Å */ - { 0x0f, 229 }, /* å */ - { 0x10, ' ' }, /* XXX delta */ - { 0x11, '_' }, - { 0x12, ' ' }, /* XXX phi */ - { 0x13, ' ' }, /* XXX gamma */ - { 0x14, ' ' }, /* XXX lambda */ - { 0x15, ' ' }, /* XXX omega */ - { 0x16, ' ' }, /* XXX pi */ - { 0x17, ' ' }, /* XXX psi */ - { 0x18, ' ' }, /* XXX sigma */ - { 0x19, ' ' }, /* XXX theta */ - { 0x1a, ' ' }, /* XXX xi */ - { 0x1b, ' ' }, /* FIXME escape */ - { 0x1c, 198 }, - { 0x1d, 230 }, - { 0x1e, 223 }, - { 0x1f, 201 }, - { 0x24, 164 }, /* $ */ - { 0x40, 161 }, /* @ */ - { 0x5b, 196 }, /* [ */ - { 0x5c, 214 }, /* \ */ - { 0x5d, 209 }, /* ] */ - { 0x5e, 220 }, /* ^ */ - { 0x5f, 167 }, /* _ */ - { 0x60, 191 }, /* ` */ - { 0x7b, 228 }, /* { */ - { 0x7c, 246 }, /* | */ - { 0x7d, 241 }, /* } */ - { 0x7e, 252 }, /* ~ */ - { 0x7f, 224 } -}; - -/* errors */ -/* CME ERROR */ -static struct -{ - int code; - char const * error; -} _gsm_cme_errors[] = -{ - { 0, N_("Phone failure") }, - { 1, N_("No connection to phone") }, - { 3, N_("Operation not allowed") }, - { 4, N_("Operation not supported") }, - { 10, N_("SIM not inserted") }, - { 11, N_("SIM PIN required") }, - { 12, N_("SIM PUK required") }, - { 13, N_("SIM failure") }, - { 14, N_("SIM busy") }, - { 15, N_("SIM wrong") }, - { 16, N_("Incorrect password") }, - { 17, N_("SIM PIN2 required") }, - { 18, N_("SIM PUK2 required") }, - { 20, N_("Memory full") }, - { 21, N_("Invalid index") }, - { 22, N_("Not found") }, - { 23, N_("Memory failure") }, - { 24, N_("Text string too long") }, - { 25, N_("Invalid characters in text string") }, - { 26, N_("Dial string too long") }, - { 27, N_("Invalid characters in dial string") }, - { 30, N_("No network service") }, - { 31, N_("Network timeout") }, - { 32, N_("Network not allowed - emergency calls only")}, - { 100, N_("Unknown error") }, - { 0, NULL } -}; - -/* CMS ERROR */ -static struct -{ - int code; - char const * error; -} _gsm_cms_errors[] = -{ - { 300, N_("ME failure") }, - { 301, N_("SMS service of ME reserved") }, - { 302, N_("Operation not allowed") }, - { 303, N_("Operation not supported") }, - { 304, N_("Invalid PDU mode parameter") }, - { 310, N_("SIM not inserted") }, - { 311, N_("SIM PIN required") }, - { 314, N_("SIM busy") }, - { 320, N_("Memory failure") }, - { 321, N_("Invalid memory index") }, - { 322, N_("Memory full") }, - { 0, NULL } -}; - -/* EXT ERROR */ -static struct -{ - int code; - char const * error; -} _gsm_ext_errors[] = -{ - { 0, N_("Invalid index"), }, - { 1, N_("Parameter not allowed"), }, - { 2, N_("Data corrupted"), }, - { 3, N_("Internal error"), }, - { 4, N_("Call table full"), }, - { 5, N_("Service table full"), }, - { 6, N_("Call not found"), }, - { 7, N_("No data-call supported"), }, - { 8, N_("One call on hold"), }, - { 9, N_("Hold call not supported for this type"), }, - { 10, N_("Number not allowed by FDN"), }, - { 11, N_("Number not allowed by BDN"), }, - { 12, N_("Parallel USSD not supported"), }, - { 13, N_("Fax minimum speed condition"), }, - { 14, N_("Conflict with command details"), }, - { 0, NULL } -}; - - -/* models */ -static struct -{ - char const * model; - unsigned long quirks; -} _gsm_models[] = -{ - { "\"Neo1973 Embedded GSM Modem\"", - GSM_MODEM_QUIRK_CPIN_QUOTES - | GSM_MODEM_QUIRK_WANT_SMSC_IN_PDU }, - { "\"Neo1973 GTA01/GTA02 Embedded GSM Modem\"", - GSM_MODEM_QUIRK_CPIN_QUOTES - | GSM_MODEM_QUIRK_WANT_SMSC_IN_PDU }, - { "\"Neo1973 GTA02 Embedded GSM Modem\"", - GSM_MODEM_QUIRK_CPIN_QUOTES - | GSM_MODEM_QUIRK_WANT_SMSC_IN_PDU }, - { NULL, 0 } -}; - - -/* prototypes */ -/* conversions */ -static unsigned char _gsm_convert_from_iso(unsigned char c); -static unsigned char _gsm_convert_to_iso(unsigned char c); - -/* events */ -static int _gsm_event_send(GSM * gsm, GSMEventType type); -static int _gsm_event_set_status(GSM * gsm, GSMStatus status); - -/* parsing */ -static int _gsm_parse(GSM * gsm); -static int _gsm_parse_line(GSM * gsm, char const * line, gboolean * answered); - -/* queue management */ -static void _gsm_queue_flush(GSM * gsm); -static void _gsm_queue_pop(GSM * gsm); -static int _gsm_queue_push(GSM * gsm); - -/* triggers */ -static int _gsm_trigger_busy(GSM * gsm, char const * result, - gboolean * answered); -static int _gsm_trigger_cbc(GSM * gsm, char const * result); -static int _gsm_trigger_ccwa(GSM * gsm, char const * result); -static int _gsm_trigger_cfun(GSM * gsm, char const * result); -static int _gsm_trigger_cgatt(GSM * gsm, char const * result); -static int _gsm_trigger_cgmm(GSM * gsm, char const * result); -static int _gsm_trigger_cgreg(GSM * gsm, char const * result); -static int _gsm_trigger_clip(GSM * gsm, char const * result); -static int _gsm_trigger_cme_error(GSM * gsm, char const * result, - gboolean * answered); -static int _gsm_trigger_cms_error(GSM * gsm, char const * result); -static int _gsm_trigger_cmgl(GSM * gsm, char const * result); -static int _gsm_trigger_cmgr(GSM * gsm, char const * result); -static int _gsm_trigger_cmgs(GSM * gsm, char const * result); -static int _gsm_trigger_cmti(GSM * gsm, char const * result); -static int _gsm_trigger_cmut(GSM * gsm, char const * result); -static int _gsm_trigger_connect(GSM * gsm, char const * result, - gboolean * answered); -static int _gsm_trigger_cops(GSM * gsm, char const * result); -static int _gsm_trigger_cpas(GSM * gsm, char const * result); -static int _gsm_trigger_cpbr(GSM * gsm, char const * result); -static int _gsm_trigger_cpin(GSM * gsm, char const * result); -static int _gsm_trigger_creg(GSM * gsm, char const * result); -static int _gsm_trigger_cring(GSM * gsm, char const * result); -static int _gsm_trigger_cssi(GSM * gsm, char const * result); -static int _gsm_trigger_cssu(GSM * gsm, char const * result); -static int _gsm_trigger_csq(GSM * gsm, char const * result); -static int _gsm_trigger_ext_error(GSM * gsm, char const * result, - gboolean * answered); -static int _gsm_trigger_no_answer(GSM * gsm, char const * result, - gboolean * answered); -static int _gsm_trigger_no_carrier(GSM * gsm, char const * result, - gboolean * answered); -static int _gsm_trigger_no_dialtone(GSM * gsm, char const * result, - gboolean * answered); - -/* triggers */ -static GSMTrigger _gsm_triggers[] = -{ -#define GSM_TRIGGER(trigger, callback) \ - { trigger, sizeof(trigger) - 1, \ - (GSMTriggerCallback)_gsm_trigger_ ## callback } - GSM_TRIGGER("BUSY", busy), - GSM_TRIGGER("+CBC: ", cbc), - GSM_TRIGGER("+CCWA: ", ccwa), - GSM_TRIGGER("+CFUN: ", cfun), - GSM_TRIGGER("+CGATT: ", cgatt), - GSM_TRIGGER("+CGMM: ", cgmm), - GSM_TRIGGER("+CGREG: ", cgreg), - GSM_TRIGGER("+CLIP: ", clip), - GSM_TRIGGER("+CME ERROR: ", cme_error), - GSM_TRIGGER("+CMS ERROR: ", cms_error), - GSM_TRIGGER("+CMGL: ", cmgl), - GSM_TRIGGER("+CMGR: ", cmgr), - GSM_TRIGGER("+CMGS: ", cmgs), - GSM_TRIGGER("+CMTI: ", cmti), - GSM_TRIGGER("+CMUT: ", cmut), - GSM_TRIGGER("CONNECT", connect), - GSM_TRIGGER("+COPS: ", cops), - GSM_TRIGGER("+CPAS: ", cpas), - GSM_TRIGGER("+CPBR: ", cpbr), - GSM_TRIGGER("+CPIN: ", cpin), - GSM_TRIGGER("+CREG: ", creg), - GSM_TRIGGER("+CRING: ", cring), - GSM_TRIGGER("+CSQ: ", csq), - GSM_TRIGGER("+CSSI: ", cssi), - GSM_TRIGGER("+CSSU: ", cssu), - GSM_TRIGGER("+EXT ERROR: ", ext_error), - GSM_TRIGGER("NO ANSWER", no_answer), - GSM_TRIGGER("NO CARRIER", no_carrier), - GSM_TRIGGER("NO DIALTONE", no_dialtone), - { NULL, 0, NULL } -}; - -/* callbacks */ -static gboolean _on_reset(gpointer data); -static gboolean _on_timeout(gpointer data); -static gboolean _on_watch_can_read(GIOChannel * source, GIOCondition condition, - gpointer data); -static gboolean _on_watch_can_read_ppp(GIOChannel * source, - GIOCondition condition, gpointer data); -static gboolean _on_watch_can_write(GIOChannel * source, GIOCondition condition, - gpointer data); -static gboolean _on_watch_can_write_ppp(GIOChannel * source, - GIOCondition condition, gpointer data); - - -/* public */ -/* functions */ -/* gsm_new */ -static unsigned int _new_baudrate(unsigned int baudrate); - -GSM * gsm_new(char const * device, unsigned int baudrate, unsigned int hwflow) -{ - GSM * gsm; - - if((gsm = malloc(sizeof(*gsm))) == NULL) - return NULL; - /* settings */ - if(device == NULL) - device = "/dev/modem"; - gsm->device = strdup(device); - gsm->baudrate = _new_baudrate(baudrate); - gsm->retry = 1000; - gsm->hwflow = hwflow; - gsm->username = NULL; - gsm->password = NULL; - /* callback */ - gsm->callback = NULL; - gsm->callback_data = NULL; - memset(&gsm->event, 0, sizeof(gsm->event)); - gsm->status = GSM_STATUS_UNKNOWN; - /* queue */ - gsm->queue = NULL; - /* internal */ - gsm->modem = gsm_modem_new(gsm); - gsm->mode = GSM_MODE_INIT; - gsm->source = 0; - gsm->channel = NULL; - gsm->rd_buf = NULL; - gsm->rd_buf_cnt = 0; - gsm->rd_source = 0; - gsm->wr_buf = NULL; - gsm->wr_buf_cnt = 0; - gsm->wr_source = 0; - gsm->rd_ppp_channel = NULL; - gsm->rd_ppp_source = 0; - gsm->wr_ppp_channel = NULL; - gsm->wr_ppp_source = 0; - /* error checking */ - if(gsm->device == NULL || gsm->baudrate == 0 || gsm->modem == NULL) - { - gsm_delete(gsm); - return NULL; - } - return gsm; -} - -static unsigned int _new_baudrate(unsigned int baudrate) -{ - char const * error; - - error = _(": Unknown baudrate, assuming 115200"); - switch(baudrate) - { - case 1200: - return B1200; - case 2400: - return B2400; - case 4800: - return B4800; - case 9600: - return B9600; - case 19200: - return B19200; - case 38400: - return B38400; -#ifdef B76800 - case 76800: - return B76800; -#endif -#ifdef B14400 - case 14400: - return B14400; -#endif -#ifdef B28800 - case 28800: - return B28800; -#endif - case 57600: - return B57600; - case 115200: - return B115200; - case 460800: - return B460800; - case 921600: - return B921600; - default: - error_set("%u%s", baudrate, error, 115200); - return 115200; - } -} - - -/* gsm_delete */ -void gsm_delete(GSM * gsm) -{ - gsm_modem_delete(gsm->modem); - if(gsm->rd_source != 0) - g_source_remove(gsm->rd_source); - gsm->rd_source = 0; - _gsm_queue_flush(gsm); - free(gsm->password); - free(gsm->username); - free(gsm->device); - free(gsm); -} - - -/* accessors */ -/* gsm_get_retry */ -unsigned int gsm_get_retry(GSM * gsm) -{ -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s() => %u\n", __func__, gsm->retry); -#endif - return gsm->retry; -} - - -/* gsm_set_callback */ -void gsm_set_callback(GSM * gsm, GSMCallback callback, gpointer data) -{ - gsm->callback = callback; - gsm->callback_data = data; -} - - -/* gsm_set_call_presentation */ -int gsm_set_call_presentation(GSM * gsm, int set) -{ - return gsm_modem_set_call_presentation(gsm->modem, (set != 0) ? TRUE - : FALSE); -} - - -/* gsm_set_call_waiting_control */ -int gsm_set_call_waiting_control(GSM * gsm, int unsollicited) -{ - return gsm_modem_set_call_waiting_control(gsm->modem, - (unsollicited != 0) ? TRUE : FALSE); -} - - -/* gsm_set_extended_errors */ -int gsm_set_extended_errors(GSM * gsm, int extended) -{ - return gsm_modem_set_extended_errors(gsm->modem, (extended != 0) ? TRUE - : FALSE); -} - - -/* gsm_set_extended_ring_reports */ -int gsm_set_extended_ring_reports(GSM * gsm, gboolean extended) -{ - return gsm_modem_set_extended_ring_reports(gsm->modem, extended); -} - - -/* gsm_set_functional */ -int gsm_set_functional(GSM * gsm, int functional) -{ - return gsm_modem_set_functional(gsm->modem, (functional != 0) ? TRUE - : FALSE); -} - - -/* gsm_set_gprs_password */ -int gsm_set_gprs_password(GSM * gsm, char const * password) -{ - free(gsm->password); - if(password == NULL) - gsm->password = NULL; - else if((gsm->password = strdup(password)) == NULL) - return -1; - return 0; -} - - -/* gsm_set_gprs_username */ -int gsm_set_gprs_username(GSM * gsm, char const * username) -{ - free(gsm->username); - if(username == NULL) - gsm->username = NULL; - else if((gsm->username = strdup(username)) == NULL) - return -1; - return 0; -} - - -/* gsm_set_line_presentation */ -int gsm_set_line_presentation(GSM * gsm, int set) -{ - return gsm_modem_set_line_presentation(gsm->modem, (set != 0) ? TRUE - : FALSE); -} - - -/* gsm_set_message_indications */ -int gsm_set_message_indications(GSM * gsm, GSMMessageMode mode, - int unsollicited) -{ - return gsm_modem_set_message_indications(gsm->modem, mode, - (unsollicited != 0) ? TRUE : FALSE); -} - - -/* gsm_set_mute */ -int gsm_set_mute(GSM * gsm, int mute) -{ - return gsm_modem_set_mute(gsm->modem, (mute != 0) ? TRUE : FALSE); -} - - -/* gsm_set_operator_format */ -int gsm_set_operator_format(GSM * gsm, GSMOperatorFormat format) -{ - return gsm_modem_set_operator_format(gsm->modem, format); -} - - -/* gsm_set_operator_mode */ -int gsm_set_operator_mode(GSM * gsm, GSMOperatorMode mode) -{ - return gsm_modem_set_operator_mode(gsm->modem, mode); -} - - -/* gsm_set_registration_report */ -int gsm_set_registration_report(GSM * gsm, GSMRegistrationReport report) -{ - int ret; - - ret = gsm_modem_set_registration_report(gsm->modem, report); - ret |= gsm_fetch_registration(gsm); - return ret; -} - - -/* gsm_set_retry */ -int gsm_set_retry(GSM * gsm, unsigned int retry) -{ -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s(%u)\n", __func__, retry); -#endif - gsm->retry = retry; - return 0; -} - - -/* gsm_set_supplementary_service_notifications */ -int gsm_set_supplementary_service_notifications(GSM * gsm, int intermediate, - int unsollicited) -{ -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s(%s, %s)\n", __func__, (intermediate != 0) - ? "TRUE" : "FALSE", (unsollicited != 0) ? "TRUE" - : "FALSE"); -#endif - return gsm_modem_set_supplementary_service_notifications(gsm->modem, - (intermediate != 0) ? TRUE : FALSE, - (unsollicited != 0) ? TRUE : FALSE); -} - - -/* useful */ -/* gsm_call */ -int gsm_call(GSM * gsm, GSMCallType calltype, char const * number) -{ - if(number == NULL) - return gsm_modem_call_last(gsm->modem, calltype); - /* FIXME if the number is not valid try from the address book */ - return gsm_modem_call(gsm->modem, calltype, number); -} - - -/* gsm_call_answer */ -int gsm_call_answer(GSM * gsm) -{ - return gsm_modem_call_answer(gsm->modem); -} - - -/* gsm_call_contact */ -int gsm_call_contact(GSM * gsm, GSMCallType calltype, unsigned int index) -{ - return gsm_modem_call_contact(gsm->modem, calltype, index); -} - - -/* gsm_call_hangup */ -int gsm_call_hangup(GSM * gsm) -{ - return gsm_modem_call_hangup(gsm->modem); -} - - -/* gsm_call_reject */ -int gsm_call_reject(GSM * gsm) -{ - return gsm_modem_call_reject(gsm->modem); -} - - -/* callbacks */ -/* gsm_callback_on_message_deleted */ -void gsm_callback_on_message_deleted(GSM * gsm) -{ - GSMCommand * gsmc; - unsigned long index; - - if((gsmc = g_slist_nth_data(gsm->queue, 0)) == NULL) - return; - index = (unsigned long)gsm_command_get_data(gsmc); - gsm_event(gsm, GSM_EVENT_TYPE_MESSAGE_DELETED, index); -} - - -/* gsm_contact_delete */ -int gsm_contact_delete(GSM * gsm, unsigned int index) -{ - return gsm_modem_contact_delete(gsm->modem, index); -} - - -/* gsm_contact_edit */ -int gsm_contact_edit(GSM * gsm, unsigned int index, char const * name, - char const * number) -{ - return gsm_modem_contact_edit(gsm->modem, index, name, number); -} - - -/* gsm_contact_new */ -int gsm_contact_new(GSM * gsm, char const * name, char const * number) -{ - return gsm_modem_contact_new(gsm->modem, name, number); -} - - -/* gsm_enter_sim_pin */ -int gsm_enter_sim_pin(GSM * gsm, char const * code) -{ - if(code == NULL) - return gsm_modem_is_pin_valid(gsm->modem); - return gsm_modem_enter_sim_pin(gsm->modem, code); -} - - -/* gsm_event */ -int gsm_event(GSM * gsm, GSMEventType type, ...) -{ - va_list ap; - GSMEvent * event = &gsm->event; - -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s(%d)\n", __func__, type); -#endif - va_start(ap, type); - switch(type) - { - case GSM_EVENT_TYPE_ERROR: - event->error.error = va_arg(ap, GSMError); - event->error.message = va_arg(ap, char const *); - break; - case GSM_EVENT_TYPE_BATTERY_CHARGE: - event->battery_charge.status = va_arg(ap, - GSMBatteryStatus); - event->battery_charge.level = va_arg(ap, unsigned int); - break; - case GSM_EVENT_TYPE_CALL_PRESENTATION: - event->call_presentation.number = va_arg(ap, - char const *); - event->call_presentation.format = va_arg(ap, - unsigned int); - break; - case GSM_EVENT_TYPE_CALL_WAITING: - event->call_waiting_control.unsollicited = va_arg(ap, - unsigned int); - break; - case GSM_EVENT_TYPE_CONTACT: - event->contact.index = va_arg(ap, unsigned int); - event->contact.name = va_arg(ap, char const *); - event->contact.number = va_arg(ap, char const *); - break; - case GSM_EVENT_TYPE_CONTACT_LIST: - event->contact_list.start = va_arg(ap, unsigned int); - event->contact_list.end = va_arg(ap, unsigned int); - break; - case GSM_EVENT_TYPE_FUNCTIONAL: - event->functional.functional = va_arg(ap, unsigned int); - break; - case GSM_EVENT_TYPE_GPRS_ATTACHMENT: - event->gprs_attachment.attached = va_arg(ap, - unsigned int); - break; - case GSM_EVENT_TYPE_GPRS_CONNECTION: - event->gprs_connection.connected = va_arg(ap, - unsigned int); - break; - case GSM_EVENT_TYPE_INCOMING_CALL: - event->incoming_call.calltype = va_arg(ap, - unsigned int); - break; - case GSM_EVENT_TYPE_INCOMING_MESSAGE: - event->incoming_message.memory = va_arg(ap, - char const *); - event->incoming_message.index = va_arg(ap, - unsigned int); - break; - case GSM_EVENT_TYPE_MESSAGE: - event->message.index = va_arg(ap, unsigned int); - event->message.number = va_arg(ap, char const *); - event->message.date = va_arg(ap, time_t); - event->message.encoding = va_arg(ap, GSMEncoding); - event->message.length = va_arg(ap, unsigned int); - event->message.content = va_arg(ap, char const *); - break; - case GSM_EVENT_TYPE_MESSAGE_DELETED: - event->message.index = va_arg(ap, unsigned int); - break; - case GSM_EVENT_TYPE_MESSAGE_LIST: - event->message_list.start = va_arg(ap, unsigned int); - event->message_list.end = va_arg(ap, unsigned int); - break; - case GSM_EVENT_TYPE_MESSAGE_SENT: - event->message_sent.mr = va_arg(ap, unsigned int); - break; - case GSM_EVENT_TYPE_MUTE: - event->mute.mute = va_arg(ap, unsigned int); - break; - case GSM_EVENT_TYPE_OPERATOR: - event->operator.mode = va_arg(ap, GSMOperatorMode); - event->operator.format = va_arg(ap, GSMOperatorFormat); - event->operator.operator = va_arg(ap, char const *); - event->operator.lai = va_arg(ap, unsigned int); - break; - case GSM_EVENT_TYPE_PHONE_ACTIVITY: - event->phone_activity.activity = va_arg(ap, - GSMPhoneActivity); - break; - case GSM_EVENT_TYPE_REGISTRATION: - case GSM_EVENT_TYPE_GPRS_REGISTRATION: - event->registration.n = va_arg(ap, unsigned int); - event->registration.stat = va_arg(ap, unsigned int); - event->registration.area = va_arg(ap, unsigned int); - event->registration.cell = va_arg(ap, unsigned int); - break; - case GSM_EVENT_TYPE_SIGNAL_LEVEL: - event->signal_level.level = va_arg(ap, gdouble); - break; - case GSM_EVENT_TYPE_STATUS: - event->status.status = va_arg(ap, GSMStatus); - break; - case GSM_EVENT_TYPE_UNKNOWN: - event->unknown.command = va_arg(ap, char const *); - event->unknown.result = va_arg(ap, char const *); - break; - case GSM_EVENT_TYPE_OFFLINE: - case GSM_EVENT_TYPE_ONLINE: - case GSM_EVENT_TYPE_SIM_PIN_VALID: - case GSM_EVENT_TYPE_RESUME: - case GSM_EVENT_TYPE_SUSPEND: - break; - } - va_end(ap); - return _gsm_event_send(gsm, type); -} - - -/* gsm_fetch_battery_charge */ -int gsm_fetch_battery_charge(GSM * gsm) -{ - return gsm_modem_get_battery_charge(gsm->modem); -} - - -/* gsm_fetch_contact_list */ -int gsm_fetch_contact_list(GSM * gsm) -{ - return gsm_modem_get_contact_list(gsm->modem); -} - - -/* gsm_fetch_contacts */ -int gsm_fetch_contacts(GSM * gsm, unsigned int start, unsigned int end) -{ - return gsm_modem_get_contacts(gsm->modem, start, end); -} - - -/* gsm_fetch_message_list */ -int gsm_fetch_message_list(GSM * gsm, GSMMessageList list) -{ - return gsm_modem_get_message_list(gsm->modem, list); -} - - -/* gsm_fetch_message */ -int gsm_fetch_message(GSM * gsm, unsigned int index) -{ - return gsm_modem_get_message(gsm->modem, index); -} - - -/* gsm_fetch_operator */ -int gsm_fetch_operator(GSM * gsm) -{ - return gsm_modem_get_operator(gsm->modem); -} - - -/* gsm_fetch_registration */ -int gsm_fetch_registration(GSM * gsm) -{ - return gsm_modem_get_registration(gsm->modem); -} - - -/* gsm_fetch_signal_level */ -int gsm_fetch_signal_level(GSM * gsm) -{ - return gsm_modem_get_signal_level(gsm->modem); -} - - -/* queries */ -/* gsm_is_alive */ -int gsm_is_alive(GSM * gsm) -{ - return gsm_modem_is_alive(gsm->modem); -} - - -/* gsm_is_call_waiting_control */ -int gsm_is_call_waiting_control(GSM * gsm) -{ - return gsm_modem_is_call_waiting_control(gsm->modem); -} - - -/* gsm_is_functional */ -int gsm_is_functional(GSM * gsm) -{ - return gsm_modem_is_functional(gsm->modem); -} - - -/* gsm_is_gprs_attached */ -int gsm_is_gprs_attached(GSM * gsm) -{ - return gsm_modem_is_gprs_attached(gsm->modem); -} - - -/* gsm_is_mute */ -int gsm_is_mute(GSM * gsm) -{ - return gsm_modem_is_mute(gsm->modem); -} - - -/* gsm_is_phone_active */ -int gsm_is_phone_active(GSM * gsm) -{ - return gsm_modem_is_phone_active(gsm->modem); -} - - -/* gsm_is_pin_needed */ -int gsm_is_pin_needed(GSM * gsm) -{ - return gsm_modem_is_pin_needed(gsm->modem); -} - - -/* gsm_is_pin_valid */ -int gsm_is_pin_valid(GSM * gsm) -{ - return gsm_modem_is_pin_valid(gsm->modem); -} - - -/* gsm_is_registered */ -int gsm_is_registered(GSM * gsm) -{ - return gsm_modem_is_registered(gsm->modem); -} - - -/* messaging */ -/* gsm_message_delete */ -int gsm_message_delete(GSM * gsm, unsigned int index) -{ - return gsm_modem_message_delete(gsm->modem, index); -} - - -/* gsm_message_send */ -static int _message_send_utf8(GSM * gsm, char const * number, char const * text, - size_t length); - -int gsm_message_send(GSM * gsm, char const * number, GSMEncoding encoding, - char const * text, size_t length) -{ - switch(encoding) - { - case GSM_ENCODING_UTF8: - return _message_send_utf8(gsm, number, text, length); - case GSM_ENCODING_RAW_DATA: - return gsm_modem_message_send(gsm->modem, number, - GSM_MODEM_ALPHABET_DATA, text, length); - } - return 1; /* should not be reached */ -} - -static int _message_send_utf8(GSM * gsm, char const * number, char const * text, - size_t length) -{ - int ret; - gchar * p; - size_t i; - - if((p = g_convert(text, length, "ISO-8859-1", "UTF-8", NULL, &length, - NULL)) == NULL) - return 1; /* XXX report error */ - for(i = 0; i < length; i++) - p[i] = _gsm_convert_from_iso(text[i]); - ret = gsm_modem_message_send(gsm->modem, number, - GSM_MODEM_ALPHABET_DEFAULT, text, length); - g_free(p); - return ret; -} - - -/* queue management */ -/* gsm_queue */ -GSMCommand * gsm_queue(GSM * gsm, char const * command) -{ - GSMCommand * gsmc; - - if(command == NULL || command[0] == '\0') - return NULL; - if((gsmc = gsm_command_new(command)) == NULL) - return NULL; - if(gsm_queue_command(gsm, gsmc) == 0) - return gsmc; - gsm_command_delete(gsmc); - return NULL; -} - - -/* gsm_queue_command */ -int gsm_queue_command(GSM * gsm, GSMCommand * gsmc) -{ - GSMPriority priority; - GSList * l; - GSMCommand * p; - char const * q; - - if(gsmc == NULL) - return 1; - if(gsm->mode == GSM_MODE_DATA && (q = gsm_command_get_command(gsmc)) - && strcmp(q, "ATH") == 0) /* XXX */ - { - gsm_event(gsm, GSM_EVENT_TYPE_GPRS_CONNECTION, 0); - gsm_event(gsm, GSM_EVENT_TYPE_GPRS_ATTACHMENT, 0); - gsm_reset(gsm, 0, NULL); - return 0; - } - /* the GSM_PRIORITY_HIGHEST priority is meant to avoid races */ - if((priority = gsm_command_get_priority(gsmc)) > GSM_PRIORITY_HIGH) - priority = GSM_PRIORITY_HIGH; - for(l = gsm->queue; l != NULL; l = l->next) - { - p = l->data; - if(gsm_command_get_priority(p) < priority) - break; - } - if(l != NULL) - gsm->queue = g_slist_insert_before(gsm->queue, l, gsmc); - else if(gsm->queue == NULL && gsm->mode == GSM_MODE_COMMAND) - { - gsm->queue = g_slist_append(gsm->queue, gsmc); - _gsm_queue_push(gsm); - } - else if(gsm->mode == GSM_MODE_INIT && gsm->wr_source == 0) - { - gsm->queue = g_slist_append(gsm->queue, gsmc); - _gsm_queue_push(gsm); - } - else - gsm->queue = g_slist_append(gsm->queue, gsmc); - return 0; -} - - -/* gsm_queue_full */ -int gsm_queue_full(GSM * gsm, GSMPriority priority, char const * command, - GSMError error, GSMCommandCallback callback) -{ - return gsm_queue_full_mode(gsm, priority, command, error, callback, - GSM_MODE_COMMAND); -} - - -/* gsm_queue_full_mode */ -int gsm_queue_full_mode(GSM * gsm, GSMPriority priority, char const * command, - GSMError error, GSMCommandCallback callback, GSMMode mode) -{ - GSMCommand * gsmc; - - if(command == NULL || command[0] == '\0') - return 1; - if((gsmc = gsm_command_new(command)) == NULL) - return 1; - gsm_command_set_priority(gsmc, priority); - gsm_command_set_error(gsmc, error); - gsm_command_set_callback(gsmc, callback); - gsm_command_set_mode(gsmc, mode); - if(gsm_queue_command(gsm, gsmc) == 0) - return 0; - gsm_command_delete(gsmc); - return 1; -} - - -/* gsm_queue_with_error */ -int gsm_queue_with_error(GSM * gsm, char const * command, GSMError error) -{ - GSMCommand * gsmc; - - if((gsmc = gsm_queue(gsm, command)) == NULL) - return 1; - gsm_command_set_error(gsmc, error); - return 0; -} - - -/* gsm_reset */ -int gsm_reset(GSM * gsm, unsigned int delay, char const * device) -{ - int ret; - char * p = NULL; - - if(device != NULL && (p = strdup(device)) == NULL) - return -1; - if((ret = gsm_stop(gsm)) == 0) - { - if(p != NULL) - { - free(gsm->device); - gsm->device = p; - } - ret = gsm_start(gsm, delay); - } - else - free(p); - return ret; -} - - -/* gsm_start */ -int gsm_start(GSM * gsm, unsigned int delay) -{ - if(gsm->source != 0) /* XXX really already started? */ - return 0; - _gsm_event_send(gsm, GSM_EVENT_TYPE_RESUME); - if(delay > 0) - gsm->source = g_timeout_add(delay, _on_reset, gsm); - else - gsm->source = g_idle_add(_on_reset, gsm); - return 0; -} - - -/* gsm_stop */ -static void _stop_channel(GIOChannel * channel); - -int gsm_stop(GSM * gsm) -{ - _gsm_event_send(gsm, GSM_EVENT_TYPE_OFFLINE); - /* XXX let remaining commands be executed first? */ - _gsm_queue_flush(gsm); - if(gsm->source != 0) - g_source_remove(gsm->source); - gsm->source = 0; - _stop_channel(gsm->channel); - gsm->channel = NULL; - if(gsm->rd_ppp_source != 0) - g_source_remove(gsm->rd_ppp_source); - gsm->rd_ppp_source = 0; - _stop_channel(gsm->rd_ppp_channel); - gsm->rd_ppp_channel = NULL; - if(gsm->wr_ppp_source != 0) - g_source_remove(gsm->wr_ppp_source); - gsm->wr_ppp_source = 0; - _stop_channel(gsm->wr_ppp_channel); - gsm->wr_ppp_channel = NULL; - _gsm_event_send(gsm, GSM_EVENT_TYPE_SUSPEND); - return 0; -} - -static void _stop_channel(GIOChannel * channel) - /* XXX code duplication with _reset_channel() */ -{ - GError * error = NULL; - - if(channel == NULL) - return; - /* XXX should the file descriptor also be closed? */ - g_io_channel_shutdown(channel, TRUE, &error); - g_io_channel_unref(channel); -} - - -/* private */ -/* functions */ -/* conversions */ -/* gsm_convert_from_iso */ -static unsigned char _gsm_convert_from_iso(unsigned char c) -{ - size_t i; - - for(i = 0; i < sizeof(_gsm_conv) / sizeof(*_gsm_conv); i++) - if(_gsm_conv[i].iso == c) - return _gsm_conv[i].gsm; - return c & 0x7f; -} - - -/* gsm_convert_to_iso */ -static unsigned char _gsm_convert_to_iso(unsigned char c) -{ - size_t i; - - for(i = 0; i < sizeof(_gsm_conv) / sizeof(*_gsm_conv); i++) - if(_gsm_conv[i].gsm == c) - return _gsm_conv[i].iso; - return c; -} - - -/* events */ -/* gsm_event_send */ -static int _gsm_event_send(GSM * gsm, GSMEventType type) -{ - int ret; - - gsm->event.type = type; - ret = gsm->callback(&gsm->event, gsm->callback_data); - if(ret == 0) - return 0; - return error_set_code(ret, "%u: %s", type, _("Event not handled")); -} - - -/* gsm_event_set_status */ -static int _gsm_event_set_status(GSM * gsm, GSMStatus status) -{ - if(gsm->status == status) - return 0; - gsm->status = status; - return gsm_event(gsm, GSM_EVENT_TYPE_STATUS, status); -} - - -/* gsm_parse */ -static int _parse_pdu(GSM * gsm); -static int _parse_do(GSM * gsm, size_t * i); - -static int _gsm_parse(GSM * gsm) -{ - int ret = 0; - size_t i = 0; - char * p; - -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s() cnt=%lu\n", __func__, - (unsigned long)gsm->rd_buf_cnt); -#endif - while(i < gsm->rd_buf_cnt) - { - if(gsm->rd_buf[i] != '\r' && gsm->rd_buf[i] != '\n') - { - i++; - continue; - } - gsm->rd_buf[i++] = '\0'; - if(i < gsm->rd_buf_cnt && gsm->rd_buf[i] == '\n') - i++; - if(gsm->rd_buf[0] != '\0') - ret |= _parse_do(gsm, &i); - gsm->rd_buf_cnt -= i; - memmove(gsm->rd_buf, &gsm->rd_buf[i], gsm->rd_buf_cnt); - if((p = realloc(gsm->rd_buf, gsm->rd_buf_cnt)) != NULL) - gsm->rd_buf = p; /* we can ignore errors... */ - else if(gsm->rd_buf_cnt == 0) - gsm->rd_buf = NULL; /* ...except when it's not one */ - i = 0; - } - if(gsm->mode == GSM_MODE_PDU) - return _parse_pdu(gsm); - return ret; -} - -static int _parse_pdu(GSM * gsm) -{ - size_t i = 0; - char * p; - - if(gsm->rd_buf_cnt < 2) - return 0; - if(gsm->rd_buf[i++] == '>' && gsm->rd_buf[i++] == ' ') - { - _gsm_queue_pop(gsm); - _gsm_queue_push(gsm); - } - gsm->rd_buf_cnt -= i; - memmove(gsm->rd_buf, &gsm->rd_buf[i], gsm->rd_buf_cnt); - if((p = realloc(gsm->rd_buf, gsm->rd_buf_cnt)) != NULL) - gsm->rd_buf = p; /* we can ignore errors... */ - else if(gsm->rd_buf_cnt == 0) - gsm->rd_buf = NULL; /* ...except when it's not one */ - return 0; -} - -static int _parse_do(GSM * gsm, size_t * i) -{ - gboolean answered = FALSE; - - if(gsm->mode == GSM_MODE_INIT) - { - if(strcmp(gsm->rd_buf, "OK") != 0) - return 0; - if(gsm->source != 0) - g_source_remove(gsm->source); - gsm->source = 0; - *i = gsm->rd_buf_cnt; /* XXX ugly: flush read buffer */ - g_io_channel_flush(gsm->channel, NULL); /* XXX check errors? */ - gsm->mode = GSM_MODE_COMMAND; - gsm_modem_set_echo(gsm->modem, FALSE); - gsm_modem_set_verbose(gsm->modem, TRUE); - gsm_modem_set_extended_errors(gsm->modem, TRUE); - gsm_modem_get_model(gsm->modem); - _gsm_event_set_status(gsm, GSM_STATUS_INITIALIZED); - _gsm_queue_push(gsm); - } - else if(gsm->mode == GSM_MODE_COMMAND - /* XXX not sure about PDU mode here */ - || gsm->mode == GSM_MODE_PDU) - { - _gsm_parse_line(gsm, gsm->rd_buf, &answered); - if(answered) - { - if(gsm->source != 0) - { - g_source_remove(gsm->source); - gsm->source = 0; - } - _gsm_queue_pop(gsm); - _gsm_queue_push(gsm); - } - } - return 0; -} - - -/* gsm_parse_line */ -static int _gsm_parse_line(GSM * gsm, char const * line, gboolean * answered) -{ - size_t i; - GSMCommand * gsmc; - GSMCommandCallback callback; - GSMError error = GSM_ERROR_UNKNOWN; - char const * cmd = NULL; - size_t j; - int c; - -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, line); -#endif - if(answered != NULL) - *answered = FALSE; - if((gsmc = g_slist_nth_data(gsm->queue, 0)) != NULL - && (cmd = gsm_command_get_command(gsmc)) != NULL - && strcmp(line, cmd) == 0) - return 0; /* ignore echo */ - if(strcmp(line, "RING") == 0) - { - gsm_event(gsm, GSM_EVENT_TYPE_INCOMING_CALL, - GSM_CALL_TYPE_UNKNOWN); - return 0; - } - if(strcmp(line, "OK") == 0) - { - /* XXX the trigger may not have been called (if any) */ - if(answered != NULL) - *answered = TRUE; - /* XXX call it only if we were really answered? */ - if(gsmc != NULL && (callback = gsm_command_get_callback(gsmc)) - != NULL) - callback(gsm); - return 0; - } - for(i = 0; _gsm_triggers[i].trigger != NULL; i++) - if(strncmp(line, _gsm_triggers[i].trigger, - _gsm_triggers[i].trigger_cnt) == 0) - return _gsm_triggers[i].callback(gsm, - &line[_gsm_triggers[i].trigger_cnt], - answered); - if(strcmp(line, "ERROR") == 0) - { - if(answered != NULL) - *answered = TRUE; - if(gsmc != NULL) - error = gsm_command_get_error(gsmc); -#if 0 /* XXX disabled for now */ - gsm_event(gsm, GSM_EVENT_TYPE_ERROR, error, _("Unknown error")); -#endif - return 0; - } - /* XXX look for a potential trigger */ - if(cmd != NULL && strncmp(cmd, "AT+", 3) == 0 && isupper((c = cmd[3]))) - { - for(j = 2; cmd[j + 2] != '\0' && isupper((c = cmd[j + 2])); - j++); - for(i = 0; _gsm_triggers[i].trigger != NULL; i++) - if(strncmp(cmd + 2, _gsm_triggers[i].trigger, j) == 0) - return _gsm_triggers[i].callback(gsm, line, - answered); - } - return gsm_event(gsm, GSM_EVENT_TYPE_UNKNOWN, cmd, line); -} - - -/* queue management */ -/* _gsm_queue_flush */ -static void _gsm_queue_flush(GSM * gsm) -{ -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s()\n", __func__); -#endif - g_slist_foreach(gsm->queue, (GFunc)gsm_command_delete, NULL); - g_slist_free(gsm->queue); - gsm->queue = NULL; - free(gsm->rd_buf); - gsm->rd_buf = NULL; - gsm->rd_buf_cnt = 0; - if(gsm->rd_source != 0) - { - g_source_remove(gsm->rd_source); - gsm->rd_source = 0; - } - free(gsm->wr_buf); - gsm->wr_buf = NULL; - gsm->wr_buf_cnt = 0; - if(gsm->wr_source != 0) - { - g_source_remove(gsm->wr_source); - gsm->wr_source = 0; - } - if(gsm->source != 0) - { - g_source_remove(gsm->source); - gsm->source = 0; - } -} - - -/* gsm_queue_pop */ -static void _gsm_queue_pop(GSM * gsm) -{ - GSMCommand * gsmc; - -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s()\n", __func__); -#endif - if(gsm->queue == NULL) - return; - gsmc = gsm->queue->data; - gsm_command_delete(gsmc); - gsm->queue = g_slist_remove(gsm->queue, gsmc); -#if 0 /* FIXME this is useless */ - if(gsm->mode != GSM_MODE_COMMAND) - return; -#endif -} - - -/* gsm_queue_push */ -static int _gsm_queue_push(GSM * gsm) -{ - GSMCommand * gsmc; - char const * command; - char const suffix[] = "\r\n"; - -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s()\n", __func__); -#endif - if(gsm->queue == NULL) - return 0; - gsmc = gsm->queue->data; - command = gsm_command_get_command(gsmc); - gsm->wr_buf_cnt = strlen(command) + sizeof(suffix); - if((gsm->wr_buf = malloc(gsm->wr_buf_cnt)) == NULL) - return 1; - snprintf(gsm->wr_buf, gsm->wr_buf_cnt--, "%s%s", command, suffix); - /* FIXME shouldn't it always be the case? flush input queue first? */ - if(gsm->channel != NULL && gsm->wr_source == 0) - { - gsm->wr_source = g_io_add_watch(gsm->channel, G_IO_OUT, - _on_watch_can_write, gsm); - if(gsm->source != 0 && gsm->mode != GSM_MODE_INIT) - { - /* XXX still not sure it is always _on_timeout */ - g_source_remove(gsm->source); - gsm->source = 0; - } - } - return 0; -} - - -/* triggers */ -/* gsm_trigger_busy */ -static int _gsm_trigger_busy(GSM * gsm, char const * result, - gboolean * answered) -{ -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, result); -#endif - if(answered != NULL) - *answered = TRUE; - return gsm_event(gsm, GSM_EVENT_TYPE_ERROR, GSM_ERROR_BUSY, "BUSY"); -} - - -/* gsm_trigger_cbc */ -static int _gsm_trigger_cbc(GSM * gsm, char const * result) -{ -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, result); -#endif - if(sscanf(result, "%u,%u", &gsm->event.battery_charge.status, - &gsm->event.battery_charge.level) != 2) - return gsm_event(gsm, GSM_EVENT_TYPE_ERROR, - GSM_ERROR_BATTERY_CHARGE_FAILED, result); - return _gsm_event_send(gsm, GSM_EVENT_TYPE_BATTERY_CHARGE); -} - - -/* gsm_trigger_ccwa */ -static int _gsm_trigger_ccwa(GSM * gsm, char const * result) -{ -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, result); -#endif - if(sscanf(result, "%u", &gsm->event.call_waiting_control.unsollicited) - == 1) - return _gsm_event_send(gsm, GSM_EVENT_TYPE_CALL_WAITING); - return gsm_event(gsm, GSM_EVENT_TYPE_ERROR, - GSM_ERROR_CALL_WAITING_FAILED, result); -} - - -/* gsm_trigger_cfun */ -static int _gsm_trigger_cfun(GSM * gsm, char const * result) -{ -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, result); -#endif - if(sscanf(result, "%u", &gsm->event.functional.functional) != 1) - /* XXX nicer message */ - return gsm_event(gsm, GSM_EVENT_TYPE_ERROR, - GSM_ERROR_FUNCTIONAL_FAILED, result); - return _gsm_event_send(gsm, GSM_EVENT_TYPE_FUNCTIONAL); -} - - -/* gsm_trigger_cgatt */ -static int _gsm_trigger_cgatt(GSM * gsm, char const * result) -{ -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, result); -#endif - if(sscanf(result, "%u", &gsm->event.gprs_attachment.attached) != 1) - /* XXX nicer message */ - return gsm_event(gsm, GSM_EVENT_TYPE_ERROR, GSM_ERROR_UNKNOWN, - result); - return _gsm_event_send(gsm, GSM_EVENT_TYPE_GPRS_ATTACHMENT); -} - - -/* gsm_trigger_cgmm */ -static int _gsm_trigger_cgmm(GSM * gsm, char const * result) -{ - size_t i; - -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, result); -#endif - for(i = 0; _gsm_models[i].model != NULL; i++) - if(strcmp(_gsm_models[i].model, result) == 0) - break; - if(_gsm_models[i].model == NULL) - return 1; /* we do not know this model */ - gsm_modem_set_quirks(gsm->modem, _gsm_models[i].quirks); - return 0; -} - - -/* gsm_trigger_cgreg */ -static int _gsm_trigger_cgreg(GSM * gsm, char const * result) -{ - int ret; - int res; - -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, result); -#endif - if((res = sscanf(result, "%u,%u,%X,%X", &gsm->event.gprs_registration.n, - &gsm->event.gprs_registration.stat, - &gsm->event.gprs_registration.area, - &gsm->event.gprs_registration.cell)) - == 4) - ret = _gsm_event_send(gsm, GSM_EVENT_TYPE_GPRS_REGISTRATION); - else if(res == 2) - { - gsm->event.gprs_registration.area = 0; - gsm->event.gprs_registration.cell = 0; - ret = _gsm_event_send(gsm, GSM_EVENT_TYPE_GPRS_REGISTRATION); - } - else - return 1; - return ret; -} - - -/* gsm_trigger_clip */ -static int _gsm_trigger_clip(GSM * gsm, char const * result) -{ - char number[32]; - -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, result); -#endif - if(sscanf(result, "\"%31[^\"]\",%u", number, - &gsm->event.call_presentation.format) != 2) - return 1; /* XXX report error? */ - number[sizeof(number) - 1] = '\0'; - gsm->event.call_presentation.number = number; - return _gsm_event_send(gsm, GSM_EVENT_TYPE_CALL_PRESENTATION); -} - - -/* gsm_trigger_cme_error */ -static int _gsm_trigger_cme_error(GSM * gsm, char const * result, - gboolean * answered) -{ - int code; - char * p; - size_t i; - GSMError type = GSM_ERROR_UNKNOWN; - char const * error; - GSMCommand * gsmc; - -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, result); -#endif - error = _("Unknown error"); - if(answered != NULL) - *answered = TRUE; - code = strtol(result, &p, 10); - if(result[0] == '\0' || *p != '\0') - return 1; - for(i = 0; _gsm_cme_errors[i].error != NULL; i++) - if(_gsm_cme_errors[i].code == code) - break; - if(_gsm_cme_errors[i].error != NULL) - error = _(_gsm_cme_errors[i].error); - if(gsm->queue != NULL && (gsmc = gsm->queue->data) != NULL) - type = gsm_command_get_error(gsmc); - return gsm_event(gsm, GSM_EVENT_TYPE_ERROR, type, error); -} - - -/* gsm_trigger_cms_error */ -static int _gsm_trigger_cms_error(GSM * gsm, char const * result) -{ - int code; - char * p; - size_t i; - GSMError error = GSM_ERROR_UNKNOWN; - GSMCommand * gsmc; - -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, result); -#endif - code = strtol(result, &p, 10); - if(result[0] == '\0' || *p != '\0') - return 1; - for(i = 0; _gsm_cms_errors[i].error != NULL; i++) - if(_gsm_cms_errors[i].code == code) - break; - if(_gsm_cms_errors[i].error == NULL) - return 1; /* XXX report an error anyway? */ - if(gsm->queue != NULL && (gsmc = gsm->queue->data) != NULL) - error = gsm_command_get_error(gsmc); - return gsm_event(gsm, GSM_EVENT_TYPE_ERROR, error, - _(_gsm_cms_errors[i].error)); -} - - -/* gsm_trigger_cmgl */ -static int _gsm_trigger_cmgl(GSM * gsm, char const * result) -{ - unsigned int * start = &gsm->event.message_list.start; - unsigned int u; - -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, result); -#endif - /* FIXME this command may be long and the timeout triggered too soon */ - /* XXX we could already be reading the message at this point */ - if(sscanf(result, "%u,%u,%u,%u", start, &u, &u, &u) != 4 - && sscanf(result, "%u,%u,,%u", start, &u, &u) != 3) - /* XXX we may be stuck in PDU mode at this point */ - return gsm_event(gsm, GSM_EVENT_TYPE_ERROR, - GSM_ERROR_MESSAGE_FETCH_FAILED, - _("Unknown error")); - gsm->event.message_list.end = *start; - gsm->mode = GSM_MODE_PDU; - return _gsm_event_send(gsm, GSM_EVENT_TYPE_MESSAGE_LIST); -} - - -/* gsm_trigger_cmgr */ -static char * _cmgr_pdu_parse(char const * pdu, time_t * timestamp, - char number[32], GSMEncoding * encoding, size_t * length); -static void _cmgr_pdu_parse_number(unsigned int type, char const * number, - size_t length, char buf[32]); -static time_t _cmgr_pdu_parse_timestamp(char const * timestamp); -static char * _cmgr_pdu_parse_encoding_default(char const * pdu, size_t len, - size_t i, size_t hdr, GSMEncoding * encoding, size_t * length); -static char * _cmgr_pdu_parse_encoding_data(char const * pdu, size_t len, - size_t i, size_t hdr, GSMEncoding * encoding, size_t * length); - -static int _gsm_trigger_cmgr(GSM * gsm, char const * result) -{ - char buf[32]; - char date[32]; - unsigned int mbox; - unsigned int alpha = 0; - unsigned int * length = &gsm->event.message.length; - struct tm t; - char * p; - GSMCommand * gsmc; - size_t l = 0; - -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, result); -#endif - /* FIXME report which mailbox contains the message? */ - /* text mode support */ - if(sscanf(result, "\"%31[^\"]\",\"%31[^\"]\",,\"%31[^\"]\"", buf, - gsm->number, date) == 3) /* XXX improve */ - { - gsm->number[sizeof(gsm->number) - 1] = '\0'; - gsm->event.message.number = gsm->number; - date[sizeof(date) - 1] = '\0'; - if(strptime(date, "%y/%m/%d,%H:%M:%S", &t) == NULL) - /* XXX also parse the timezone? */ - localtime_r(NULL, &t); - gsm->event.message.date = mktime(&t); - *length = 0; - return 0; /* we need to wait for the next line */ - } - /* PDU mode support */ - if(sscanf(result, "%u,%u,%u", &mbox, &alpha, length) == 3 - || sscanf(result, "%u,,%u", &mbox, length) == 2) - return 0; /* we need to wait for the next line */ - /* message content */ - if(*length == 0) /* XXX assumes this is text mode */ - { - gsm->event.message.encoding = GSM_ENCODING_UTF8; - gsm->event.message.content = result; - *length = strlen(result) + 1; - _gsm_event_send(gsm, GSM_EVENT_TYPE_MESSAGE); - } - else if((p = _cmgr_pdu_parse(result, &gsm->event.message.date, - gsm->number, - &gsm->event.message.encoding, &l)) - != NULL) - { - gsm->event.message.index = 0; - if((gsmc = g_slist_nth_data(gsm->queue, 0)) != NULL) - gsm->event.message.index /* XXX ugly */ - = (unsigned long)gsm_command_get_data(gsmc); - gsm->event.message.number = gsm->number; /* XXX ugly */ - gsm->event.message.length = l; - gsm->event.message.content = p; - _gsm_event_send(gsm, GSM_EVENT_TYPE_MESSAGE); - free(p); - } - return 0; -} - -/* XXX this function is fat and ugly */ -static char * _cmgr_pdu_parse(char const * pdu, time_t * timestamp, - char number[32], GSMEncoding * encoding, size_t * length) -{ - size_t len; - unsigned int smscl; - unsigned int tp; - unsigned int hdr; - unsigned int addrl; - unsigned int pid; - unsigned int dcs; - unsigned int datal; - unsigned int u; - char const * q; - size_t i; - -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, pdu); -#endif - len = strlen(pdu); - if(sscanf(pdu, "%02X", &smscl) != 1) /* SMSC length */ - return NULL; - if((smscl * 2) + 2 > len) - return NULL; - q = pdu + (smscl * 2) + 2; - if(sscanf(q, "%02X", &tp) != 1) - return NULL; - if((tp & 0x03) != 0x00) /* TP-MTI not SMS-DELIVER */ - return NULL; - hdr = ((tp & 0x40) == 0x40) ? 1 : 0; /* TP-UDHI header present */ - if((smscl * 2) + 4 > len) - return NULL; - q = pdu + (smscl * 2) + 4; - if(sscanf(q, "%02X", &addrl) != 1) /* address length */ - return NULL; - if((smscl * 2) + 6 > len) - return NULL; - q = pdu + (smscl * 2) + 6; - if(sscanf(q, "%02X", &u) != 1) /* type of address */ - return NULL; - /* FIXME this probably depends on the type of address */ - if(addrl % 2 == 1) - addrl++; - if((smscl * 2) + 2 + 4 + addrl + 2 > len) - return NULL; - _cmgr_pdu_parse_number(u, q + 2, addrl, number); - q = pdu + (smscl * 2) + 2 + 4 + addrl + 2; - if(sscanf(q, "%02X", &pid) != 1) /* PID */ - return NULL; - if((smscl * 2) + 2 + 4 + addrl + 4 > len) - return NULL; - q = pdu + (smscl * 2) + 2 + 4 + addrl + 4; - if(sscanf(q, "%02X", &dcs) != 1) /* DCS */ - return NULL; - if((smscl * 2) + 2 + 4 + addrl + 6 > len) - return NULL; - q = pdu + (smscl * 2) + 2 + 4 + addrl + 6; - if(timestamp != NULL) - *timestamp = _cmgr_pdu_parse_timestamp(q); - if((smscl * 2) + 2 + 4 + addrl + 6 + 14 > len) - return NULL; - q = pdu + (smscl * 2) + 2 + 4 + addrl + 6 + 14; - if(sscanf(q, "%02X", &datal) != 1) /* data length */ - return NULL; - /* XXX check the data length */ - if((i = (smscl * 2) + 2 + 4 + addrl + 6 + 16) > len) - return NULL; - if(hdr != 0 && sscanf(&pdu[i], "%02X", &hdr) != 1) - return NULL; - if(dcs == 0x00) - return _cmgr_pdu_parse_encoding_default(pdu, len, i, hdr, - encoding, length); - if(dcs == 0x04) - return _cmgr_pdu_parse_encoding_data(pdu, len, i, hdr, - encoding, length); - return NULL; -} - -static char * _cmgr_pdu_parse_encoding_default(char const * pdu, size_t len, - size_t i, size_t hdr, GSMEncoding * encoding, size_t * length) -{ - unsigned char * p; - size_t j; - unsigned char rest; - int shift = 0; - char const * q; - unsigned int u; - unsigned char byte; - char * r; - - if((p = malloc(len - i + 1)) == NULL) - return NULL; - if(hdr != 0) - { - /* FIXME actually parse the header */ - u = 2 + (hdr * 2); - if(u % 7 != 0) /* fill bits */ - u += 7 - (u % 7); - i += u; - } - p[0] = '\0'; - for(j = 0, rest = 0; i + 1 < len; i+=2) - { - q = &pdu[i]; - if(sscanf(q, "%02X", &u) != 1) - break; /* FIXME report an error instead? */ - byte = u; - p[j] = (byte << (shift + 1) >> (shift + 1) << shift) & 0x7f; - p[j] |= rest; - p[j] = _gsm_convert_to_iso(p[j]); - j++; - rest = (byte >> (7 - shift)) & 0x7f; - if(++shift == 7) - { - shift = 0; - p[j++] = rest; - rest = 0; - } - } - *encoding = GSM_ENCODING_UTF8; - if((r = g_convert((char *)p, j, "UTF-8", "ISO-8859-1", NULL, NULL, - NULL)) != NULL) - { - free(p); - p = (unsigned char *)r; - j = strlen(r); - } - *length = j; - return (char *)p; -} - -static char * _cmgr_pdu_parse_encoding_data(char const * pdu, size_t len, - size_t i, size_t hdr, GSMEncoding * encoding, size_t * length) -{ - unsigned char * p; - size_t j; - unsigned int u; - - if((p = malloc(len - i + 1)) == NULL) /* XXX 2 times big enough? */ - return NULL; - /* FIXME actually parse the header */ - if(hdr != 0) - i += 2 + (hdr * 2); - for(j = 0; i + 1 < len; i+=2) - { - if(sscanf(&pdu[i], "%02X", &u) != 1) - { - free(p); - return NULL; - } - p[j++] = u; - } - *encoding = GSM_ENCODING_RAW_DATA; - *length = j; - p[j] = '\0'; - return (char *)p; -} - -static void _cmgr_pdu_parse_number(unsigned int type, char const * number, - size_t length, char buf[32]) -{ - char * b = buf; - size_t i; - - if(type == 0x91) - *(b++) = '+'; - for(i = 0; i < length - 1 && i < 32 - 1; i+=2) - { - if((number[i] != 'F' && (number[i] < '0' || number[i] > '9')) - || number[i + 1] < '0' || number[i + 1] > '9') - break; - b[i] = number[i + 1]; - if((b[i + 1] = number[i]) == 'F') - b[i + 1] = '\0'; - } - b[i] = '\0'; -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s(\"%s\", %lu) => \"%s\"\n", __func__, number, - (unsigned long)length, b); -#endif -} - -static time_t _cmgr_pdu_parse_timestamp(char const * timestamp) -{ - char const * p = timestamp; - size_t i; - struct tm t; -#ifdef DEBUG - char buf[32]; -#endif - - if(strlen(p) < 14) - return 0; - for(i = 0; i < 14; i++) - if(p[i] < '0' || p[i] > '9') - return 0; - memset(&t, 0, sizeof(t)); - t.tm_year = (p[0] - '0') + ((p[1] - '0') * 10); - t.tm_year = (t.tm_year > 70) ? t.tm_year : (100 + t.tm_year); - t.tm_mon = (p[2] - '0') + ((p[3] - '0') * 10); - if(t.tm_mon > 0) - t.tm_mon--; - t.tm_mday = (p[4] - '0') + ((p[5] - '0') * 10); - t.tm_hour = (p[6] - '0') + ((p[7] - '0') * 10); - t.tm_min = (p[8] - '0') + ((p[9] - '0') * 10); - t.tm_sec = (p[10] - '0') + ((p[11] - '0') * 10); -#ifdef DEBUG - strftime(buf, sizeof(buf), "%d/%m/%Y %H:%M:%S", &t); - fprintf(stderr, "DEBUG: %s() => \"%s\"\n", __func__, buf); -#endif - return mktime(&t); -} - - -/* gsm_trigger_cmgs */ -static int _gsm_trigger_cmgs(GSM * gsm, char const * result) -{ -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, result); -#endif - if(sscanf(result, "%u", &gsm->event.message_sent.mr) != 1) - return 1; - return _gsm_event_send(gsm, GSM_EVENT_TYPE_MESSAGE_SENT); -} - - -/* gsm_trigger_cmti */ -static int _gsm_trigger_cmti(GSM * gsm, char const * result) -{ - char memory[32]; - -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, result); -#endif - if(sscanf(result, "\"%31[^\"]\",%u", memory, - &gsm->event.incoming_message.index) != 2) - return 1; - memory[sizeof(memory) - 1] = '\0'; - gsm->event.incoming_message.memory = memory; - return _gsm_event_send(gsm, GSM_EVENT_TYPE_INCOMING_MESSAGE); -} - - -/* gsm_trigger_cmut */ -static int _gsm_trigger_cmut(GSM * gsm, char const * result) -{ -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, result); -#endif - if(sscanf(result, "%u", &gsm->event.mute.mute) != 1) - return 1; - return _gsm_event_send(gsm, GSM_EVENT_TYPE_MUTE); -} - - -/* gsm_trigger_connect */ -static int _gsm_trigger_connect(GSM * gsm, char const * result, - gboolean * answered) -{ - char * argv[] = { "/usr/sbin/pppd", "pppd", "call", "phone", - "user", "", "password", "", NULL }; - GSpawnFlags flags = G_SPAWN_FILE_AND_ARGV_ZERO; - int wfd; - int rfd; - GError * error = NULL; - -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, result); -#endif - if(answered != NULL) - *answered = TRUE; - gsm->mode = GSM_MODE_DATA; - if(gsm->username != NULL) - argv[5] = gsm->username; - if(gsm->password != NULL) - argv[7] = gsm->password; - if(g_spawn_async_with_pipes(NULL, argv, NULL, flags, NULL, NULL, NULL, - &wfd, &rfd, NULL, &error) - == FALSE) - { - gsm_reset(gsm, 0, NULL); - return 1; - } - gsm->rd_ppp_channel = g_io_channel_unix_new(rfd); - g_io_channel_set_encoding(gsm->rd_ppp_channel, NULL, &error); - g_io_channel_set_buffered(gsm->rd_ppp_channel, FALSE); - gsm->rd_ppp_source = g_io_add_watch(gsm->rd_ppp_channel, G_IO_IN, - _on_watch_can_read_ppp, gsm); - gsm->wr_ppp_channel = g_io_channel_unix_new(wfd); - g_io_channel_set_encoding(gsm->wr_ppp_channel, NULL, &error); - g_io_channel_set_buffered(gsm->wr_ppp_channel, FALSE); - gsm->wr_ppp_source = 0; - gsm_event(gsm, GSM_EVENT_TYPE_GPRS_ATTACHMENT, 1); - gsm_event(gsm, GSM_EVENT_TYPE_GPRS_CONNECTION, 1); - return 0; -} - - -/* gsm_trigger_cops */ -static int _gsm_trigger_cops(GSM * gsm, char const * result) -{ - char operator[32]; - -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, result); -#endif - gsm->event.operator.operator = operator; - gsm->event.operator.lai = 0; - if(sscanf(result, "%u,%u,\"%31[^\"]\",%u", &gsm->event.operator.mode, - &gsm->event.operator.format, operator, - &gsm->event.operator.lai) >= 3) - return _gsm_event_send(gsm, GSM_EVENT_TYPE_OPERATOR); - return 1; -} - - -/* gsm_trigger_cpas */ -static int _gsm_trigger_cpas(GSM * gsm, char const * result) -{ -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, result); -#endif - if(sscanf(result, "%u", &gsm->event.phone_activity.activity) != 1) - return 1; - return _gsm_event_send(gsm, GSM_EVENT_TYPE_PHONE_ACTIVITY); -} - - -/* _gsm_trigger_cpbr */ -static int _gsm_trigger_cpbr(GSM * gsm, char const * result) -{ - unsigned int start; - unsigned int end; - char number[32]; - char name[32]; - gchar * p; - -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, result); -#endif - if(sscanf(result, "(%u-%u)", &start, &end) == 2) - return gsm_event(gsm, GSM_EVENT_TYPE_CONTACT_LIST, start, end); - if(sscanf(result, "%u,\"%31[^\"]\",145,\"%31[^\"]\"", - &gsm->event.contact.index, number, name) != 3 - && sscanf(result, "%u,\"%31[^\"]\",129,\"%31[^\"]\"", - &gsm->event.contact.index, number, name) != 3) - return 1; - number[sizeof(number) - 1] = '\0'; - gsm->event.contact.number = number; - name[sizeof(name) - 1] = '\0'; - gsm->event.contact.name = name; - if((p = g_convert(name, -1, "UTF-8", "ISO-8859-1", NULL, NULL, NULL)) - != NULL) - { - snprintf(name, sizeof(name), "%s", p); - g_free(p); - } - return _gsm_event_send(gsm, GSM_EVENT_TYPE_CONTACT); -} - - -/* _gsm_trigger_cpin */ -static int _gsm_trigger_cpin(GSM * gsm, char const * result) -{ -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, result); -#endif - if(strcmp(result, "READY") == 0) - return _gsm_event_set_status(gsm, GSM_STATUS_READY); - if(strcmp(result, "SIM PIN") == 0) - return gsm_event(gsm, GSM_EVENT_TYPE_ERROR, - GSM_ERROR_SIM_PIN_REQUIRED, NULL); - /* XXX nicer message */ - return gsm_event(gsm, GSM_EVENT_TYPE_ERROR, GSM_ERROR_UNKNOWN, result); -} - - -/* gsm_trigger_creg */ -static int _gsm_trigger_creg(GSM * gsm, char const * result) -{ - int ret; - int res; - -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, result); -#endif - if((res = sscanf(result, "%u,%u,%X,%X", &gsm->event.registration.n, - &gsm->event.registration.stat, - &gsm->event.registration.area, - &gsm->event.registration.cell)) == 4) - ret = _gsm_event_send(gsm, GSM_EVENT_TYPE_REGISTRATION); - else if(res == 3) - { - gsm->event.registration.stat = gsm->event.registration.n; - gsm->event.registration.n = 2; - ret = _gsm_event_send(gsm, GSM_EVENT_TYPE_REGISTRATION); - } - else if(res == 2) - { - gsm->event.registration.area = 0; - gsm->event.registration.cell = 0; - ret = _gsm_event_send(gsm, GSM_EVENT_TYPE_REGISTRATION); - } - else if(res == 1) - { - gsm->event.registration.stat = gsm->event.registration.n; - gsm->event.registration.n = 2; - gsm->event.registration.area = 0; - gsm->event.registration.cell = 0; - ret = _gsm_event_send(gsm, GSM_EVENT_TYPE_REGISTRATION); - } - else - return 1; - switch(gsm->event.registration.stat) - { - case GSM_REGISTRATION_STATUS_NOT_SEARCHING: - ret |= _gsm_event_set_status(gsm, GSM_STATUS_READY); - break; - case GSM_REGISTRATION_STATUS_NOT_REGISTERED: - ret |= _gsm_event_set_status(gsm, - GSM_STATUS_REGISTERING); - break; - case GSM_REGISTRATION_STATUS_DENIED: - ret |= _gsm_event_set_status(gsm, - GSM_STATUS_REGISTERING_DENIED); - break; - case GSM_REGISTRATION_STATUS_REGISTERED_HOME: - ret |= _gsm_event_set_status(gsm, - GSM_STATUS_REGISTERED_HOME); - break; - case GSM_REGISTRATION_STATUS_REGISTERED_ROAMING: - ret |= _gsm_event_set_status(gsm, - GSM_STATUS_REGISTERED_ROAMING); - break; - case GSM_REGISTRATION_STATUS_UNKNOWN: - default: - ret |= _gsm_event_set_status(gsm, GSM_STATUS_UNKNOWN); - break; - } - return ret; -} - - -/* gsm_trigger_cring */ -static int _gsm_trigger_cring(GSM * gsm, char const * result) -{ - GSMCallType calltype = GSM_CALL_TYPE_UNKNOWN; - -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, result); -#endif - /* XXX implement the other call types */ - if(strcmp(result, "VOICE") == 0) - calltype = GSM_CALL_TYPE_VOICE; - return gsm_event(gsm, GSM_EVENT_TYPE_INCOMING_CALL, calltype); -} - - -/* _gsm_trigger_csq */ -static int _gsm_trigger_csq(GSM * gsm, char const * result) -{ - unsigned int rssi; - unsigned int ber; - -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, result); -#endif - if(sscanf(result, "%u,%u", &rssi, &ber) != 2) - return 1; - gsm->event.signal_level.level = rssi; - if(rssi > 31) - gsm->event.signal_level.level /= 0.0; - else - gsm->event.signal_level.level /= 32; - return _gsm_event_send(gsm, GSM_EVENT_TYPE_SIGNAL_LEVEL); -} - - -/* gsm_trigger_ext */ -static int _gsm_trigger_ext_error(GSM * gsm, char const * result, - gboolean * answered) -{ - int code; - char * p; - size_t i; - GSMError type = GSM_ERROR_UNKNOWN; - char const * error; - GSMCommand * gsmc; - -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, result); -#endif - error = _("Unknown error"); - if(answered != NULL) - *answered = TRUE; - code = strtol(result, &p, 10); - if(result[0] == '\0' || *p != '\0') - return 1; - for(i = 0; _gsm_ext_errors[i].error != NULL; i++) - if(_gsm_ext_errors[i].code == code) - break; - if(_gsm_ext_errors[i].error != NULL) - error = _(_gsm_ext_errors[i].error); - if(gsm->queue != NULL && (gsmc = gsm->queue->data) != NULL) - type = gsm_command_get_error(gsmc); - return gsm_event(gsm, GSM_EVENT_TYPE_ERROR, type, error); -} - - -/* gsm_trigger_cssi */ -static int _gsm_trigger_cssi(GSM * gsm, char const * result) -{ - unsigned int i; - unsigned int index = 10; /* XXX not used */ - -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, result); -#endif - if(sscanf(result, "%u,%u", &i, &index) < 1) - return 1; - if(i == 1) /* FIXME implement the rest */ - i = GSM_PHONE_ACTIVITY_CALL; - else - i = GSM_PHONE_ACTIVITY_UNKNOWN; - return gsm_event(gsm, GSM_EVENT_TYPE_PHONE_ACTIVITY, i); -} - - -/* gsm_trigger_cssu */ -static int _gsm_trigger_cssu(GSM * gsm, char const * result) -{ - unsigned int code; - unsigned int index = 10; - char number[32]; - -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, result); -#endif - if(sscanf(result, "%u,%u,\"%31[^\"]\"", &code, &index, number) < 1) - return 1; - number[sizeof(number) - 1] = '\0'; - /* FIXME implement */ - return 1; -} - - -/* gsm_trigger_no_answer */ -static int _gsm_trigger_no_answer(GSM * gsm, char const * result, - gboolean * answered) -{ -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, result); -#endif - if(answered != NULL) - *answered = TRUE; - return gsm_event(gsm, GSM_EVENT_TYPE_ERROR, GSM_ERROR_NO_ANSWER, - "No answer"); -} - - -/* gsm_trigger_no_carrier */ -static int _gsm_trigger_no_carrier(GSM * gsm, char const * result, - gboolean * answered) -{ -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, result); -#endif - if(answered != NULL) - *answered = TRUE; - return gsm_event(gsm, GSM_EVENT_TYPE_ERROR, GSM_ERROR_NO_CARRIER, - "No carrier"); -} - - -/* gsm_trigger_no_dialtone */ -static int _gsm_trigger_no_dialtone(GSM * gsm, char const * result, - gboolean * answered) -{ -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, result); -#endif - if(answered != NULL) - *answered = TRUE; - return gsm_event(gsm, GSM_EVENT_TYPE_ERROR, GSM_ERROR_NO_DIALTONE, - "No dialtone"); -} - - -/* callbacks */ -/* on_reset */ -static void _reset_channel(GIOChannel * channel); -static int _reset_do(GSM * gsm, int fd); -static gboolean _reset_settle(gpointer data); - -static gboolean _on_reset(gpointer data) -{ - GSM * gsm = data; - int fd; - GError * error = NULL; - -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s()\n", __func__); -#endif - if(gsm->source != 0) - g_source_remove(gsm->source); - _reset_channel(gsm->channel); - gsm->channel = NULL; - _reset_channel(gsm->rd_ppp_channel); - gsm->rd_ppp_channel = NULL; - _reset_channel(gsm->wr_ppp_channel); - gsm->wr_ppp_channel = NULL; - gsm->mode = GSM_MODE_INIT; - if((fd = open(gsm->device, O_RDWR | O_NONBLOCK)) < 0 - || _reset_do(gsm, fd) != 0) - { - if(fd >= 0) - close(fd); - if(gsm->retry > 0) - gsm->source = g_timeout_add(gsm->retry, _on_reset, gsm); - gsm->source = 0; - return error_set_code(FALSE, "%s%s%s", gsm->device, ": ", - strerror(errno)); - } - gsm->channel = g_io_channel_unix_new(fd); - if((g_io_channel_set_encoding(gsm->channel, NULL, &error)) - != G_IO_STATUS_NORMAL) - error_set(0, "%s", error->message); - g_io_channel_set_buffered(gsm->channel, FALSE); - gsm->rd_source = g_io_add_watch(gsm->channel, G_IO_IN, - _on_watch_can_read, gsm); - if(gsm->wr_buf_cnt > 0) - gsm->wr_source = g_io_add_watch(gsm->channel, G_IO_OUT, - _on_watch_can_write, gsm); - gsm->source = g_timeout_add(500, _reset_settle, gsm); - _reset_settle(gsm); - return FALSE; -} - -static void _reset_channel(GIOChannel * channel) -{ - GError * error = NULL; - - if(channel == NULL) - return; - /* XXX should the file descriptor also be freed? */ - g_io_channel_shutdown(channel, TRUE, &error); - g_io_channel_unref(channel); -} - -static int _reset_do(GSM * gsm, int fd) -{ - struct stat st; - int fl; - struct termios term; - - if(flock(fd, LOCK_EX | LOCK_NB) != 0) - return 1; - fl = fcntl(fd, F_GETFL, 0); - if(fcntl(fd, F_SETFL, fl & ~O_NONBLOCK) == -1) - return 1; - if(fstat(fd, &st) != 0) - return 1; - if(st.st_mode & S_IFCHR) /* character special */ - { - if(tcgetattr(fd, &term) != 0) - return 1; - term.c_cflag &= ~(CSIZE | PARENB); - term.c_cflag |= CS8; - term.c_cflag |= CREAD; - term.c_cflag |= CLOCAL; - if(gsm->hwflow) - term.c_cflag |= CRTSCTS; - else - term.c_cflag &= ~CRTSCTS; - term.c_iflag = (IGNPAR | IGNBRK); - term.c_lflag = 0; - term.c_oflag = 0; - term.c_cc[VMIN] = 1; - term.c_cc[VTIME] = 0; - if(cfsetispeed(&term, 0) != 0) /* same speed as output speed */ - error_set("%s", gsm->device); /* go on anyway */ - if(cfsetospeed(&term, gsm->baudrate) != 0) - error_set("%s", gsm->device); /* go on anyway */ - if(tcsetattr(fd, TCSAFLUSH, &term) != 0) - return 1; - } - return 0; -} - -static gboolean _reset_settle(gpointer data) -{ - GSM * gsm = data; - - gsm_modem_reset(gsm->modem); - /* XXX may be send multiple times until it really is online */ - _gsm_event_send(gsm, GSM_EVENT_TYPE_ONLINE); - return TRUE; -} - - -/* on_timeout */ -static gboolean _on_timeout(gpointer data) -{ - GSM * gsm = data; - GSMCommand * gsmc; - char const * cmd = "AT"; - size_t len; - char * p; - -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s()\n", __func__); -#endif - gsm->source = 0; - /* FIXME this code partly duplicates _gsm_queue_push() */ - /* check if the write handler is still running */ - if(gsm->channel == NULL || gsm->wr_source != 0) - return FALSE; - if(gsm->mode == GSM_MODE_PDU) /* let's get out of here */ - gsm->mode = GSM_MODE_COMMAND; - else if(gsm->queue == NULL || (gsmc = gsm->queue->data) == NULL - /* re-inject the command */ - || (cmd = gsm_command_get_command(gsmc)) == NULL) - return FALSE; - len = strlen(cmd) + 2; - if((p = realloc(gsm->wr_buf, len + 1)) == NULL) - return FALSE; - gsm->wr_buf = p; - snprintf(gsm->wr_buf, len + 1, "%s%s", cmd, "\r\n"); - gsm->wr_buf_cnt = len; - gsm->wr_source = g_io_add_watch(gsm->channel, G_IO_OUT, - _on_watch_can_write, gsm); - return FALSE; -} - - -/* on_watch_can_read */ -static gboolean _on_watch_can_read(GIOChannel * source, GIOCondition condition, - gpointer data) -{ - GSM * gsm = data; - gsize cnt = 0; - GError * error = NULL; - GIOStatus status; - char * p; - -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s()\n", __func__); -#endif - if(condition != G_IO_IN || source != gsm->channel) - return FALSE; /* should not happen */ - if((p = realloc(gsm->rd_buf, gsm->rd_buf_cnt + 256)) == NULL) - return TRUE; /* XXX retries immediately (delay?) */ - gsm->rd_buf = p; - status = g_io_channel_read_chars(source, &gsm->rd_buf[gsm->rd_buf_cnt], - 256, &cnt, &error); -#ifdef DEBUG - fprintf(stderr, "%s", "DEBUG: MODEM: "); - fwrite(&gsm->rd_buf[gsm->rd_buf_cnt], sizeof(*p), cnt, stderr); -#endif - gsm->rd_buf_cnt += cnt; - switch(status) - { - case G_IO_STATUS_NORMAL: - break; - case G_IO_STATUS_ERROR: - error_set("%s", error->message); /* XXX really print */ - case G_IO_STATUS_EOF: - default: /* should not happen... */ - if(gsm->retry > 0) - gsm_reset(gsm, gsm->retry, NULL); - gsm->rd_source = 0; - return FALSE; - } - switch(gsm->mode) - { - case GSM_MODE_INIT: - case GSM_MODE_COMMAND: - case GSM_MODE_PDU: /* XXX really parse? */ - _gsm_parse(gsm); - break; - case GSM_MODE_DATA: - if(gsm->wr_ppp_channel == NULL - || gsm->wr_ppp_source != 0) - break; - gsm->wr_ppp_source = g_io_add_watch(gsm->wr_ppp_channel, - G_IO_OUT, _on_watch_can_write_ppp, gsm); - break; - } - return TRUE; -} - - -/* on_watch_can_read_ppp */ -static gboolean _on_watch_can_read_ppp(GIOChannel * source, - GIOCondition condition, gpointer data) -{ - GSM * gsm = data; - gsize cnt = 0; - GError * error = NULL; - GIOStatus status; - char * p; - - if(condition != G_IO_IN || source != gsm->rd_ppp_channel) - return FALSE; /* should not happen */ - if((p = realloc(gsm->wr_buf, gsm->wr_buf_cnt + 256)) == NULL) - return TRUE; /* XXX retries immediately (delay?) */ - gsm->wr_buf = p; - status = g_io_channel_read_chars(source, - &gsm->wr_buf[gsm->wr_buf_cnt], 256, &cnt, &error); - gsm->wr_buf_cnt += cnt; - switch(status) - { - case G_IO_STATUS_NORMAL: - break; - case G_IO_STATUS_ERROR: - error_set("%s", error->message); /* XXX really print */ - case G_IO_STATUS_EOF: - default: - gsm->rd_ppp_source = 0; - gsm_event(gsm, GSM_EVENT_TYPE_GPRS_CONNECTION, 0); - gsm_reset(gsm, 0, NULL); - return FALSE; - } - if(gsm->channel != NULL && gsm->wr_source == 0) - gsm->wr_source = g_io_add_watch(gsm->channel, G_IO_OUT, - _on_watch_can_write, gsm); - return TRUE; -} - - -/* on_watch_can_write */ -static gboolean _on_watch_can_write(GIOChannel * source, GIOCondition condition, - gpointer data) -{ - GSM * gsm = data; - gsize cnt = 0; - GError * error = NULL; - GIOStatus status; - char * p; - GSMCommand * gsmc; - unsigned int timeout = 2000; - -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s() cnt=%lu\n", __func__, - (unsigned long)gsm->wr_buf_cnt); -#endif - if(condition != G_IO_OUT || source != gsm->channel) - return FALSE; /* should not happen */ - status = g_io_channel_write_chars(source, gsm->wr_buf, gsm->wr_buf_cnt, - &cnt, &error); -#ifdef DEBUG - fprintf(stderr, "%s", "DEBUG: PHONE: "); - fwrite(gsm->wr_buf, sizeof(*p), cnt, stderr); -#endif - if(cnt != 0) /* some data may have been written anyway */ - { - gsm->wr_buf_cnt -= cnt; - memmove(gsm->wr_buf, &gsm->wr_buf[cnt], gsm->wr_buf_cnt); - if((p = realloc(gsm->wr_buf, gsm->wr_buf_cnt)) != NULL) - gsm->wr_buf = p; /* we can ignore errors... */ - else if(gsm->wr_buf_cnt == 0) - gsm->wr_buf = NULL; /* ...except when it's not one */ - } - switch(status) - { - case G_IO_STATUS_NORMAL: - break; - case G_IO_STATUS_ERROR: - error_set("%s", error->message); /* XXX really print */ - case G_IO_STATUS_EOF: - default: /* should not happen */ - if(gsm->retry > 0) - gsm_reset(gsm, gsm->retry, NULL); - gsm->wr_source = 0; - return FALSE; - } - if(gsm->wr_buf_cnt > 0) /* there is more data to write */ - return TRUE; - gsm->wr_source = 0; - if(gsm->mode == GSM_MODE_INIT) - _gsm_queue_pop(gsm); - else - { - if(gsm->queue != NULL && (gsmc = gsm->queue->data) != NULL) - { - gsm->mode = gsm_command_get_mode(gsmc); - timeout = gsm_command_get_timeout(gsmc); - } - if(gsm->source != 0) - g_source_remove(gsm->source); - if(gsm->mode != GSM_MODE_DATA && timeout != 0) - gsm->source = g_timeout_add(timeout, _on_timeout, gsm); - } - return FALSE; -} - - -/* on_watch_can_write_ppp */ -static gboolean _on_watch_can_write_ppp(GIOChannel * source, - GIOCondition condition, gpointer data) -{ - GSM * gsm = data; - gsize cnt = 0; - GError * error = NULL; - GIOStatus status; - char * p; - - if(condition != G_IO_OUT || source != gsm->wr_ppp_channel) - return FALSE; /* should not happen */ - status = g_io_channel_write_chars(source, gsm->rd_buf, gsm->rd_buf_cnt, - &cnt, &error); - if(cnt != 0) /* some data may have been written anyway */ - { - gsm->rd_buf_cnt -= cnt; - memmove(gsm->rd_buf, &gsm->rd_buf[cnt], gsm->rd_buf_cnt); - if((p = realloc(gsm->rd_buf, gsm->rd_buf_cnt)) != NULL) - gsm->rd_buf = p; /* we can ignore errors... */ - else if(gsm->rd_buf_cnt == 0) - gsm->rd_buf = NULL; /* ...except when it's not one */ - } - switch(status) - { - case G_IO_STATUS_NORMAL: - break; - case G_IO_STATUS_ERROR: - error_set("%s", error->message); /* XXX really print */ - case G_IO_STATUS_EOF: - default: - gsm->wr_ppp_source = 0; - gsm_event(gsm, GSM_EVENT_TYPE_GPRS_CONNECTION, 0); - gsm_reset(gsm, 0, NULL); - return FALSE; - } - if(gsm->rd_buf_cnt > 0) /* there is more data to write */ - return TRUE; - gsm->wr_ppp_source = 0; - return FALSE; -} diff --git a/src/gsm.h b/src/gsm.h deleted file mode 100644 index ccec0a7..0000000 --- a/src/gsm.h +++ /dev/null @@ -1,417 +0,0 @@ -/* $Id$ */ -/* Copyright (c) 2011 Pierre Pronchery */ -/* 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 . */ - - - -#ifndef PHONE_GSM_H -# define PHONE_GSM_H - -# include "command.h" -# include - - -/* GSM */ -/* types */ -typedef enum _GSMBatteryStatus -{ - GSM_BATTERY_STATUS_POWERED = 0, - GSM_BATTERY_STATUS_NOT_POWERED = 1, - GSM_BATTERY_STATUS_NO_BATTERY = 2, - GSM_BATTERY_STATUS_POWER_FAULT = 3 -} GSMBatteryStatus; - -typedef enum _GSMCallType -{ - GSM_CALL_TYPE_UNKNOWN = 0, - GSM_CALL_TYPE_DATA, - GSM_CALL_TYPE_VOICE -} GSMCallType; - -typedef enum _GSMEncoding -{ - GSM_ENCODING_UTF8 = 0, - GSM_ENCODING_RAW_DATA -} GSMEncoding; - -typedef enum _GSMEventType -{ - GSM_EVENT_TYPE_ERROR = 0, - GSM_EVENT_TYPE_BATTERY_CHARGE, - GSM_EVENT_TYPE_CALL_PRESENTATION, - GSM_EVENT_TYPE_CALL_WAITING, - GSM_EVENT_TYPE_CONTACT, - GSM_EVENT_TYPE_CONTACT_LIST, - GSM_EVENT_TYPE_FUNCTIONAL, - GSM_EVENT_TYPE_GPRS_ATTACHMENT, - GSM_EVENT_TYPE_GPRS_CONNECTION, - GSM_EVENT_TYPE_GPRS_REGISTRATION, - GSM_EVENT_TYPE_INCOMING_CALL, - GSM_EVENT_TYPE_INCOMING_MESSAGE, - GSM_EVENT_TYPE_MESSAGE, - GSM_EVENT_TYPE_MESSAGE_DELETED, - GSM_EVENT_TYPE_MESSAGE_LIST, - GSM_EVENT_TYPE_MESSAGE_SENT, - GSM_EVENT_TYPE_MUTE, - GSM_EVENT_TYPE_OFFLINE, - GSM_EVENT_TYPE_ONLINE, - GSM_EVENT_TYPE_OPERATOR, - GSM_EVENT_TYPE_PHONE_ACTIVITY, - GSM_EVENT_TYPE_REGISTRATION, - GSM_EVENT_TYPE_RESUME, - GSM_EVENT_TYPE_SIGNAL_LEVEL, - GSM_EVENT_TYPE_SIM_PIN_VALID, - GSM_EVENT_TYPE_STATUS, - GSM_EVENT_TYPE_SUSPEND, - GSM_EVENT_TYPE_UNKNOWN -} GSMEventType; - -typedef enum _GSMMessageFormat -{ - GSM_MESSAGE_FORMAT_PDU = 0, - GSM_MESSAGE_FORMAT_TEXT = 1 -} GSMMessageFormat; - -typedef enum _GSMMessageList -{ - GSM_MESSAGE_LIST_UNREAD = 0, - GSM_MESSAGE_LIST_READ = 1, - GSM_MESSAGE_LIST_UNSENT = 2, - GSM_MESSAGE_LIST_SENT = 3, - GSM_MESSAGE_LIST_ALL = 4 -} GSMMessageList; - -typedef enum _GSMMessageMode -{ - GSM_MESSAGE_MODE_BUFFER_REPLACE = 0, - GSM_MESSAGE_MODE_DISCARD_REJECT = 1, - GSM_MESSAGE_MODE_BUFFER_FLUSH = 2, - GSM_MESSAGE_MODE_FORWARD = 3 -} GSMMessageMode; - -typedef enum _GSMOperatorFormat -{ - GSM_OPERATOR_FORMAT_LONG = 0, - GSM_OPERATOR_FORMAT_SHORT = 1, - GSM_OPERATOR_FORMAT_LAI = 2 -} GSMOperatorFormat; - -typedef enum _GSMOperatorMode -{ - GSM_OPERATOR_MODE_AUTOMATIC = 0, - GSM_OPERATOR_MODE_MANUAL = 1, - GSM_OPERATOR_MODE_DEREGISTER = 2, - GSM_OPERATOR_MODE_SET_FORMAT = 3, - GSM_OPERATOR_MODE_MANUAL_WITH_FALLBACK = 4 -} GSMOperatorMode; - -typedef enum _GSMPhoneActivity -{ - GSM_PHONE_ACTIVITY_READY = 0, - GSM_PHONE_ACTIVITY_UNKNOWN = 2, - GSM_PHONE_ACTIVITY_RINGING = 3, - GSM_PHONE_ACTIVITY_CALL = 4 -} GSMPhoneActivity; - -typedef enum _GSMRegistrationReport -{ - GSM_REGISTRATION_REPORT_DISABLE = 0, - GSM_REGISTRATION_REPORT_ENABLE = 1, - GSM_REGISTRATION_REPORT_ENABLE_WITH_LOCATION = 2 -} GSMRegistrationReport; - -typedef enum _GSMRegistrationStatus -{ - GSM_REGISTRATION_STATUS_NOT_SEARCHING = 0, - GSM_REGISTRATION_STATUS_REGISTERED_HOME = 1, - GSM_REGISTRATION_STATUS_NOT_REGISTERED = 2, - GSM_REGISTRATION_STATUS_DENIED = 3, - GSM_REGISTRATION_STATUS_UNKNOWN = 4, - GSM_REGISTRATION_STATUS_REGISTERED_ROAMING = 5 -} GSMRegistrationStatus; - -typedef enum _GSMStatus -{ - GSM_STATUS_UNKNOWN = 0, - GSM_STATUS_INITIALIZED, - GSM_STATUS_READY, - GSM_STATUS_REGISTERING, - GSM_STATUS_REGISTERING_DENIED, - GSM_STATUS_REGISTERED_HOME, - GSM_STATUS_REGISTERED_ROAMING -} GSMStatus; - -typedef union _GSMEvent -{ - GSMEventType type; - - /* GSM_EVENT_TYPE_ERROR */ - struct - { - GSMEventType type; - GSMError error; - char const * message; - } error; - - /* GSM_EVENT_TYPE_BATTERY_CHARGE */ - struct - { - GSMEventType type; - GSMBatteryStatus status; - unsigned int level; - } battery_charge; - - /* GSM_EVENT_TYPE_CALL_PRESENTATION */ - struct - { - GSMEventType type; - char const * number; - unsigned int format; - } call_presentation; - - /* GSM_EVENT_TYPE_CALL_WAITING_CONTROL */ - struct - { - GSMEventType type; - unsigned int unsollicited; - } call_waiting_control; - - /* GSM_EVENT_TYPE_CONTACT */ - struct - { - GSMEventType type; - unsigned int index; - char const * name; - char const * number; - } contact; - - /* GSM_EVENT_TYPE_CONTACT_LIST */ - /* GSM_EVENT_TYPE_MESSAGE_LIST */ - struct - { - GSMEventType type; - unsigned int start; - unsigned int end; - } contact_list, message_list; - - /* GSM_EVENT_TYPE_FUNCTIONAL */ - struct - { - GSMEventType type; - unsigned int functional; - } functional; - - /* GSM_EVENT_TYPE_GPRS_ATTACHMENT */ - struct - { - GSMEventType type; - unsigned int attached; - } gprs_attachment; - - /* GSM_EVENT_TYPE_GPRS_CONNECTION */ - struct - { - GSMEventType type; - unsigned int connected; - } gprs_connection; - - /* GSM_EVENT_TYPE_INCOMING_CALL */ - struct - { - GSMEventType type; - GSMCallType calltype; - } incoming_call; - - /* GSM_EVENT_TYPE_INCOMING_MESSAGE */ - struct - { - GSMEventType type; - char const * memory; - unsigned int index; - } incoming_message; - - /* GSM_EVENT_TYPE_MESSAGE */ - struct - { - GSMEventType type; - unsigned int index; - char const * number; - time_t date; - GSMEncoding encoding; - unsigned int length; - char const * content; - } message; - - /* GSM_EVENT_TYPE_MESSAGE_DELETED */ - struct - { - GSMEventType type; - unsigned int index; - } message_deleted; - - /* GSM_EVENT_TYPE_MESSAGE_SENT */ - struct - { - GSMEventType type; - unsigned int mr; - } message_sent; - - /* GSM_EVENT_TYPE_MUTE */ - struct - { - GSMEventType type; - unsigned int mute; - } mute; - - /* GSM_EVENT_TYPE_OPERATOR */ - struct - { - GSMEventType type; - GSMOperatorMode mode; - GSMOperatorFormat format; - char const * operator; - unsigned int lai; - } operator; - - /* GSM_EVENT_TYPE_PHONE_ACTIVITY */ - struct - { - GSMEventType type; - GSMPhoneActivity activity; - } phone_activity; - - /* GSM_EVENT_TYPE_REGISTRATION */ - struct - { - GSMEventType type; - GSMRegistrationReport n; - GSMRegistrationStatus stat; - unsigned int cell; - unsigned int area; - } registration, gprs_registration; - - /* GSM_EVENT_TYPE_SIGNAL_LEVEL */ - struct - { - GSMEventType type; - gdouble level; - } signal_level; - - /* GSM_EVENT_TYPE_STATUS */ - struct - { - GSMEventType type; - GSMStatus status; - } status; - - /* GSM_EVENT_TYPE_UNKNOWN */ - struct - { - GSMEventType type; - char const * command; - char const * result; - } unknown; -} GSMEvent; - -typedef int (*GSMCallback)(GSMEvent * event, gpointer data); - - -/* functions */ -GSM * gsm_new(char const * device, unsigned int baudrate, unsigned int hwflow); -void gsm_delete(GSM * gsm); - -/* accessors */ -void gsm_set_callback(GSM * gsm, GSMCallback callback, gpointer data); - -unsigned int gsm_get_retry(GSM * gsm); -int gsm_set_call_presentation(GSM * gsm, int set); -int gsm_set_call_waiting_control(GSM * gsm, int unsollicited); -int gsm_set_extended_ring_reports(GSM * gsm, int extended); -int gsm_set_functional(GSM * gsm, int functional); -int gsm_set_gprs_password(GSM * gsm, char const * password); -int gsm_set_gprs_username(GSM * gsm, char const * username); -int gsm_set_line_presentation(GSM * gsm, int set); -int gsm_set_message_indications(GSM * gsm, GSMMessageMode mode, - int unsollicited); -int gsm_set_mute(GSM * gsm, int mute); -int gsm_set_operator_format(GSM * gsm, GSMOperatorFormat format); -int gsm_set_operator_mode(GSM * gsm, GSMOperatorMode mode); -int gsm_set_registration_report(GSM * gsm, GSMRegistrationReport report); -int gsm_set_retry(GSM * gsm, unsigned int retry); -int gsm_set_supplementary_service_notifications(GSM * gsm, int intermediate, - int unsollicited); - -/* useful */ -/* 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_call_reject(GSM * gsm); - -/* callbacks */ -void gsm_callback_on_message_deleted(GSM * gsm); - -/* contacts */ -int gsm_contact_delete(GSM * gsm, unsigned int index); -int gsm_contact_edit(GSM * gsm, unsigned int index, char const * name, - char const * number); -int gsm_contact_new(GSM * gsm, char const * name, char const * number); - -int gsm_enter_sim_pin(GSM * gsm, char const * code); - -/* event */ -int gsm_event(GSM * gsm, GSMEventType type, ...); - -/* fetching data */ -int gsm_fetch_battery_charge(GSM * gsm); -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, GSMMessageList list); -int gsm_fetch_message(GSM * gsm, unsigned int index); -int gsm_fetch_mute(GSM * gsm); -int gsm_fetch_operator(GSM * gsm); -int gsm_fetch_registration(GSM * gsm); -int gsm_fetch_signal_level(GSM * gsm); - -/* messaging */ -int gsm_message_delete(GSM * gsm, unsigned int index); -int gsm_message_send(GSM * gsm, char const * number, GSMEncoding encoding, - char const * text, size_t length); - -/* queries */ -int gsm_is_alive(GSM * gsm); -int gsm_is_call_waiting_control(GSM * gsm); -int gsm_is_functional(GSM * gsm); -int gsm_is_gprs_attached(GSM * gsm); -int gsm_is_mute(GSM * gsm); -int gsm_is_phone_active(GSM * gsm); -int gsm_is_pin_needed(GSM * gsm); -int gsm_is_pin_valid(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, char const * device); -int gsm_start(GSM * gsm, unsigned int delay); -int gsm_stop(GSM * gsm); - -#endif /* !PHONE_GSM_H */