/* plugin.c generated by valac 0.14.2, the Vala compiler
 * generated from plugin.vala, do not modify */

/*
 * Copyright (C) 2012 Lukas 'Slyon' Märdian <lukasmaerdian@gmail.com>
 *               2012 Simon Busch <morphis@gravedo.de>
 *
 * 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; either version 2
 * of the License, or (at your option) any later version.

 * 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, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
 *
 */

#include <glib.h>
#include <glib-object.h>
#include <fsobasics.h>
#include <fsogsm.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fsoframework.h>


#define LOW_LEVEL_TYPE_GT_A04 (low_level_gt_a04_get_type ())
#define LOW_LEVEL_GT_A04(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LOW_LEVEL_TYPE_GT_A04, LowLevelGTA04))
#define LOW_LEVEL_GT_A04_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), LOW_LEVEL_TYPE_GT_A04, LowLevelGTA04Class))
#define LOW_LEVEL_IS_GT_A04(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LOW_LEVEL_TYPE_GT_A04))
#define LOW_LEVEL_IS_GT_A04_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), LOW_LEVEL_TYPE_GT_A04))
#define LOW_LEVEL_GT_A04_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), LOW_LEVEL_TYPE_GT_A04, LowLevelGTA04Class))

typedef struct _LowLevelGTA04 LowLevelGTA04;
typedef struct _LowLevelGTA04Class LowLevelGTA04Class;
typedef struct _LowLevelGTA04Private LowLevelGTA04Private;
#define _g_free0(var) (var = (g_free (var), NULL))

struct _LowLevelGTA04 {
	FsoFrameworkAbstractObject parent_instance;
	LowLevelGTA04Private * priv;
};

struct _LowLevelGTA04Class {
	FsoFrameworkAbstractObjectClass parent_class;
};

struct _LowLevelGTA04Private {
	gchar* sysfs_modem_gpio;
	gchar* modem_application_node;
};


static gpointer low_level_gt_a04_parent_class = NULL;
static FsoGsmLowLevelIface* low_level_gt_a04_fso_gsm_low_level_parent_iface = NULL;
static GType low_level_gt_a04_type_id = 0;

GType low_level_gt_a04_get_type (void) G_GNUC_CONST;
GType low_level_gt_a04_register_type (GTypeModule * module);
#define LOW_LEVEL_GT_A04_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), LOW_LEVEL_TYPE_GT_A04, LowLevelGTA04Private))
enum  {
	LOW_LEVEL_GT_A04_DUMMY_PROPERTY
};
#define LOW_LEVEL_GT_A04_MODULE_NAME "fsogsm.lowlevel_gta04"
static gchar* low_level_gt_a04_real_repr (FsoFrameworkAbstractObject* base);
gboolean low_level_gt_a04_is_powered (LowLevelGTA04* self);
static gboolean low_level_gt_a04_toggle_modem_power_state (LowLevelGTA04* self, gboolean desired_power_state);
static gboolean low_level_gt_a04_real_poweron (FsoGsmLowLevel* base);
static gboolean low_level_gt_a04_real_poweroff (FsoGsmLowLevel* base);
static gboolean low_level_gt_a04_real_suspend (FsoGsmLowLevel* base);
static gboolean low_level_gt_a04_real_resume (FsoGsmLowLevel* base);
LowLevelGTA04* low_level_gt_a04_new (void);
LowLevelGTA04* low_level_gt_a04_construct (GType object_type);
static GObject * low_level_gt_a04_constructor (GType type, guint n_construct_properties, GObjectConstructParam * construct_properties);
static void low_level_gt_a04_finalize (GObject* obj);
gchar* fso_factory_function (FsoFrameworkSubsystem* subsystem, GError** error);
void fso_register_function (GTypeModule* module);


static gchar* low_level_gt_a04_real_repr (FsoFrameworkAbstractObject* base) {
	LowLevelGTA04 * self;
	gchar* result = NULL;
	gchar* _tmp0_;
	self = (LowLevelGTA04*) base;
	_tmp0_ = g_strdup ("<>");
	result = _tmp0_;
	return result;
}


gboolean low_level_gt_a04_is_powered (LowLevelGTA04* self) {
	gboolean result = FALSE;
	const gchar* _tmp0_;
	gboolean _tmp1_ = FALSE;
	g_return_val_if_fail (self != NULL, FALSE);
	_tmp0_ = self->priv->modem_application_node;
	_tmp1_ = fso_framework_file_handling_isPresent (_tmp0_);
	result = _tmp1_;
	return result;
}


static gboolean low_level_gt_a04_toggle_modem_power_state (LowLevelGTA04* self, gboolean desired_power_state) {
	gboolean result = FALSE;
	gint retries;
	gint _tmp0_ = 0;
	gboolean _tmp1_;
	gint _tmp2_;
	gint first_sleep;
	gint _tmp3_ = 0;
	gboolean _tmp4_;
	gint _tmp5_;
	gint second_sleep;
	const gchar* _tmp6_;
	gboolean _tmp7_ = FALSE;
	gint _tmp36_;
	g_return_val_if_fail (self != NULL, FALSE);
	retries = 0;
	_tmp1_ = desired_power_state;
	if (_tmp1_) {
		_tmp0_ = 200;
	} else {
		_tmp0_ = 100;
	}
	_tmp2_ = _tmp0_;
	first_sleep = _tmp2_;
	_tmp4_ = desired_power_state;
	if (_tmp4_) {
		_tmp3_ = 100;
	} else {
		_tmp3_ = 200;
	}
	_tmp5_ = _tmp3_;
	second_sleep = _tmp5_;
	_tmp6_ = self->priv->sysfs_modem_gpio;
	_tmp7_ = fso_framework_file_handling_isPresent (_tmp6_);
	if (_tmp7_) {
		while (TRUE) {
			gint _tmp8_;
			const gchar* _tmp9_ = NULL;
			gboolean _tmp10_;
			FsoFrameworkLogger* _tmp11_;
			const gchar* _tmp12_;
			gchar* _tmp13_ = NULL;
			gchar* _tmp14_;
			gboolean _tmp15_ = FALSE;
			const gchar* _tmp16_;
			gint _tmp17_;
			const gchar* _tmp18_;
			gint _tmp19_;
			const gchar* _tmp20_;
			gboolean _tmp21_ = FALSE;
			gboolean _tmp22_ = FALSE;
			gboolean _tmp23_;
			gboolean _tmp26_;
			gboolean _tmp32_;
			gint _tmp33_;
			_tmp8_ = retries;
			if (!(_tmp8_ < 10)) {
				break;
			}
			_tmp10_ = desired_power_state;
			if (_tmp10_) {
				_tmp9_ = "on";
			} else {
				_tmp9_ = "off";
			}
			_tmp11_ = ((FsoFrameworkAbstractObject*) self)->logger;
			_tmp12_ = _tmp9_;
			_tmp13_ = g_strdup_printf ("Trying to power modem %s ...", _tmp12_);
			_tmp14_ = _tmp13_;
			_tmp15_ = fso_framework_logger_debug (_tmp11_, _tmp14_);
			g_assert (_tmp15_);
			_g_free0 (_tmp14_);
			_tmp16_ = self->priv->sysfs_modem_gpio;
			fso_framework_file_handling_write ("0\n", _tmp16_, FALSE);
			_tmp17_ = first_sleep;
			g_usleep ((gulong) (1000 * _tmp17_));
			_tmp18_ = self->priv->sysfs_modem_gpio;
			fso_framework_file_handling_write ("1\n", _tmp18_, FALSE);
			_tmp19_ = second_sleep;
			g_usleep ((gulong) (1000 * _tmp19_));
			_tmp20_ = self->priv->sysfs_modem_gpio;
			fso_framework_file_handling_write ("0\n", _tmp20_, FALSE);
			sleep ((guint) 3);
			_tmp23_ = desired_power_state;
			if (_tmp23_) {
				const gchar* _tmp24_;
				gboolean _tmp25_ = FALSE;
				_tmp24_ = self->priv->modem_application_node;
				_tmp25_ = fso_framework_file_handling_isPresent (_tmp24_);
				_tmp22_ = _tmp25_;
			} else {
				_tmp22_ = FALSE;
			}
			_tmp26_ = _tmp22_;
			if (_tmp26_) {
				_tmp21_ = TRUE;
			} else {
				gboolean _tmp27_ = FALSE;
				gboolean _tmp28_;
				gboolean _tmp31_;
				_tmp28_ = desired_power_state;
				if (!_tmp28_) {
					const gchar* _tmp29_;
					gboolean _tmp30_ = FALSE;
					_tmp29_ = self->priv->modem_application_node;
					_tmp30_ = fso_framework_file_handling_isPresent (_tmp29_);
					_tmp27_ = !_tmp30_;
				} else {
					_tmp27_ = FALSE;
				}
				_tmp31_ = _tmp27_;
				_tmp21_ = _tmp31_;
			}
			_tmp32_ = _tmp21_;
			if (_tmp32_) {
				break;
			}
			_tmp33_ = retries;
			retries = _tmp33_ + 1;
		}
	} else {
		FsoFrameworkLogger* _tmp34_;
		gboolean _tmp35_ = FALSE;
		_tmp34_ = ((FsoFrameworkAbstractObject*) self)->logger;
		_tmp35_ = fso_framework_logger_debug (_tmp34_, "Skipping modem power on/off sequence. Seems as we're on a GTA04A3.");
		g_assert (_tmp35_);
	}
	_tmp36_ = retries;
	result = _tmp36_ < 5;
	return result;
}


/**
     * Power on the modem. After calling this the modem is ready to use.
     * NOTE: Calling poweron() will probably block for some seconds until the
     * modem is completely initialized.
     **/
static gboolean low_level_gt_a04_real_poweron (FsoGsmLowLevel* base) {
	LowLevelGTA04 * self;
	gboolean result = FALSE;
	gboolean _tmp0_ = FALSE;
	FsoFrameworkLogger* _tmp3_;
	gboolean _tmp4_ = FALSE;
	gboolean _tmp5_ = FALSE;
	self = (LowLevelGTA04*) base;
	_tmp0_ = fso_gsm_low_level_poweroff ((FsoGsmLowLevel*) self);
	if (!_tmp0_) {
		FsoFrameworkLogger* _tmp1_;
		gboolean _tmp2_ = FALSE;
		_tmp1_ = ((FsoFrameworkAbstractObject*) self)->logger;
		_tmp2_ = fso_framework_logger_debug (_tmp1_, "Already active modem could not powered off!");
		g_assert (_tmp2_);
		result = FALSE;
		return result;
	}
	_tmp3_ = ((FsoFrameworkAbstractObject*) self)->logger;
	_tmp4_ = fso_framework_logger_debug (_tmp3_, "Powering modem on now ...");
	g_assert (_tmp4_);
	_tmp5_ = low_level_gt_a04_toggle_modem_power_state (self, TRUE);
	result = _tmp5_;
	return result;
}


/**
     * Powering off the modem.
     * NOTE: Calling poweroff() will probably block for some seconds until the
     * modem is completely powered off.
     **/
static gboolean low_level_gt_a04_real_poweroff (FsoGsmLowLevel* base) {
	LowLevelGTA04 * self;
	gboolean result = FALSE;
	gboolean _tmp0_ = FALSE;
	gboolean _tmp3_ = FALSE;
	self = (LowLevelGTA04*) base;
	_tmp0_ = low_level_gt_a04_is_powered (self);
	if (!_tmp0_) {
		FsoFrameworkLogger* _tmp1_;
		gboolean _tmp2_ = FALSE;
		_tmp1_ = ((FsoFrameworkAbstractObject*) self)->logger;
		_tmp2_ = fso_framework_logger_debug (_tmp1_, "Skipping poweroff as modem is already not powered");
		g_assert (_tmp2_);
		result = TRUE;
		return result;
	}
	_tmp3_ = low_level_gt_a04_toggle_modem_power_state (self, FALSE);
	result = _tmp3_;
	return result;
}


/**
     * Suspend the modem - UNIMPLEMENTED
     **/
static gboolean low_level_gt_a04_real_suspend (FsoGsmLowLevel* base) {
	LowLevelGTA04 * self;
	gboolean result = FALSE;
	self = (LowLevelGTA04*) base;
	result = TRUE;
	return result;
}


/**
     * Resume the modem - UNIMPLEMENTED
     **/
static gboolean low_level_gt_a04_real_resume (FsoGsmLowLevel* base) {
	LowLevelGTA04 * self;
	gboolean result = FALSE;
	self = (LowLevelGTA04*) base;
	result = TRUE;
	return result;
}


LowLevelGTA04* low_level_gt_a04_construct (GType object_type) {
	LowLevelGTA04 * self = NULL;
	self = (LowLevelGTA04*) fso_framework_abstract_object_construct (object_type);
	return self;
}


LowLevelGTA04* low_level_gt_a04_new (void) {
	return low_level_gt_a04_construct (LOW_LEVEL_TYPE_GT_A04);
}


static GObject * low_level_gt_a04_constructor (GType type, guint n_construct_properties, GObjectConstructParam * construct_properties) {
	GObject * obj;
	GObjectClass * parent_class;
	LowLevelGTA04 * self;
	FsoFrameworkSmartKeyFile* _tmp0_;
	gchar* _tmp1_ = NULL;
	FsoFrameworkSmartKeyFile* _tmp2_;
	gchar* _tmp3_ = NULL;
	FsoFrameworkLogger* _tmp4_;
	parent_class = G_OBJECT_CLASS (low_level_gt_a04_parent_class);
	obj = parent_class->constructor (type, n_construct_properties, construct_properties);
	self = LOW_LEVEL_GT_A04 (obj);
	_tmp0_ = ((FsoFrameworkAbstractObject*) self)->config;
	_tmp1_ = fso_framework_smart_key_file_stringValue (_tmp0_, LOW_LEVEL_GT_A04_MODULE_NAME, "modem_toggle", "/sys/class/gpio/gpio186/value");
	_g_free0 (self->priv->sysfs_modem_gpio);
	self->priv->sysfs_modem_gpio = _tmp1_;
	_tmp2_ = ((FsoFrameworkAbstractObject*) self)->config;
	_tmp3_ = fso_framework_smart_key_file_stringValue (_tmp2_, LOW_LEVEL_GT_A04_MODULE_NAME, "modem_application_node", "/dev/ttyHS_Application");
	_g_free0 (self->priv->modem_application_node);
	self->priv->modem_application_node = _tmp3_;
	_tmp4_ = ((FsoFrameworkAbstractObject*) self)->logger;
	fso_framework_logger_info (_tmp4_, "Registering gta04 low level modem toggle");
	return obj;
}


static void low_level_gt_a04_class_init (LowLevelGTA04Class * klass) {
	low_level_gt_a04_parent_class = g_type_class_peek_parent (klass);
	g_type_class_add_private (klass, sizeof (LowLevelGTA04Private));
	FSO_FRAMEWORK_ABSTRACT_OBJECT_CLASS (klass)->repr = low_level_gt_a04_real_repr;
	G_OBJECT_CLASS (klass)->constructor = low_level_gt_a04_constructor;
	G_OBJECT_CLASS (klass)->finalize = low_level_gt_a04_finalize;
}


static void low_level_gt_a04_fso_gsm_low_level_interface_init (FsoGsmLowLevelIface * iface) {
	low_level_gt_a04_fso_gsm_low_level_parent_iface = g_type_interface_peek_parent (iface);
	iface->poweron = (gboolean (*)(FsoGsmLowLevel*)) low_level_gt_a04_real_poweron;
	iface->poweroff = (gboolean (*)(FsoGsmLowLevel*)) low_level_gt_a04_real_poweroff;
	iface->suspend = (gboolean (*)(FsoGsmLowLevel*)) low_level_gt_a04_real_suspend;
	iface->resume = (gboolean (*)(FsoGsmLowLevel*)) low_level_gt_a04_real_resume;
}


static void low_level_gt_a04_instance_init (LowLevelGTA04 * self) {
	self->priv = LOW_LEVEL_GT_A04_GET_PRIVATE (self);
}


static void low_level_gt_a04_finalize (GObject* obj) {
	LowLevelGTA04 * self;
	self = LOW_LEVEL_GT_A04 (obj);
	_g_free0 (self->priv->sysfs_modem_gpio);
	_g_free0 (self->priv->modem_application_node);
	G_OBJECT_CLASS (low_level_gt_a04_parent_class)->finalize (obj);
}


GType low_level_gt_a04_get_type (void) {
	return low_level_gt_a04_type_id;
}


GType low_level_gt_a04_register_type (GTypeModule * module) {
	static const GTypeInfo g_define_type_info = { sizeof (LowLevelGTA04Class), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) low_level_gt_a04_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (LowLevelGTA04), 0, (GInstanceInitFunc) low_level_gt_a04_instance_init, NULL };
	static const GInterfaceInfo fso_gsm_low_level_info = { (GInterfaceInitFunc) low_level_gt_a04_fso_gsm_low_level_interface_init, (GInterfaceFinalizeFunc) NULL, NULL};
	low_level_gt_a04_type_id = g_type_module_register_type (module, FSO_FRAMEWORK_TYPE_ABSTRACT_OBJECT, "LowLevelGTA04", &g_define_type_info, 0);
	g_type_module_add_interface (module, low_level_gt_a04_type_id, FSO_GSM_TYPE_LOW_LEVEL, &fso_gsm_low_level_info);
	return low_level_gt_a04_type_id;
}


/**
 * This function gets called on plugin initialization time.
 * @return the name of your plugin here
 * @note that it needs to be a name in the format <subsystem>.<plugin>
 * else your module will be unloaded immediately.
 **/
gchar* fso_factory_function (FsoFrameworkSubsystem* subsystem, GError** error) {
	gchar* result = NULL;
	FsoFrameworkLogger* _tmp0_;
	gchar* _tmp1_;
	g_return_val_if_fail (subsystem != NULL, NULL);
	_tmp0_ = fso_framework_theLogger;
	fso_framework_logger_debug (_tmp0_, "lowlevel_gta04 fso_factory_function");
	_tmp1_ = g_strdup (LOW_LEVEL_GT_A04_MODULE_NAME);
	result = _tmp1_;
	return result;
}


void fso_register_function (GTypeModule* module) {
	g_return_if_fail (module != NULL);
	low_level_gt_a04_register_type (module);
}



