void get_device_state(struct device_state *s)
{
    s->is_plugged_into_ac = is_plugged_into_ac();
    s->is_plugged_into_usb = is_plugged_into_usb();
    s->is_battery_present = is_battery_present();
    s->is_charging = is_charging();
    s->is_unknown = is_unknown();
    s->charge_level = charge_level();
    s->voltage_level = voltage_level();
}
示例#2
0
static void twl6030_charge_fault_work(struct work_struct *work)
{
	struct twl6030_bci_device_info	*di =
		container_of(work, struct twl6030_bci_device_info, charge_fault_work);

	if (is_charging(di))
		twl6030_start_usb_charger(di, 500);
	msleep(10);

	twl6030_determine_charge_state(di);
}
示例#3
0
static void charger_check_battery_level(struct charger_info *di)
{
	/* check for battery full condition */
	if (is_charging(di) && di->gg_capacity == 100) {
		if (di->gg_status == POWER_SUPPLY_STATUS_FULL) {
			dev_warn(di->dev, "gas gauge reports full capacity\n");
			di->battery_full = 1;
		} else if (di->gg_current_uA < CHARGER_TAPER_CURRENT) {
			dev_warn(di->dev, "gas gauge did not report full capacity\n");
			di->battery_full = 1;
		}
	}

	if (!is_powered(di))
		di->battery_full = 0;

	if (di->battery_full && di->gg_capacity <= di->recharge_capacity) {
		if (is_powered(di) && !is_charging(di))
			dev_warn(di->dev, "battery drained from full to %d%%, charging again\n", di->gg_capacity);
		di->battery_full = 0;
	}
}
示例#4
0
int charger_init(unsigned char bus)
{
    int usb_charger_type = dwc_otg_check_dpdm();

    debug("%s, charger_type = %d, dc_is_charging= %d\n",__func__,usb_charger_type,is_charging());
    if(1){
        pmic_rk808_charger_setting(3);
    }else if(usb_charger_type){
        pmic_rk808_charger_setting(usb_charger_type);
    }
    return 0;

}
示例#5
0
static int twl6030_get_battery_voltage(struct twl6030_bci_device_info *di)
{
	int v;
	/* when the charger is enabled the voltage does not reflect the
	 * actual battery voltage, so use the cached voltage (sampled
	 * periodically with the charger disabled)
	 */
	if (is_charging(di))
		return di->voltage_mV;
	v = twl6030_get_gpadc_conversion(di, di->gpadc_vbat_chnl);
	if (v <= 0)
		return di->voltage_mV;
	else
		return v;
}
示例#6
0
static void twl6030_monitor_work(struct work_struct *work)
{
	struct twl6030_bci_device_info *di = container_of(work,
			struct twl6030_bci_device_info, monitor_work.work);

	wake_lock(&battery_wake_lock);

	/* pet the charger watchdog */
	if (is_charging(di))
		twl6030_set_watchdog(di, di->watchdog_duration);

	queue_delayed_work(di->wq, &di->monitor_work,
			msecs_to_jiffies(1000 * di->monitoring_interval));

	twl6030_read_fuelgauge(di);

	/* TODO: monitor battery temperature */

	twl6030_determine_charge_state(di);

	wake_unlock(&battery_wake_lock);
}
示例#7
0
文件: usbtracker.c 项目: pgerdt/dsme
static void mode_request_cb(DBusPendingCall *pending,
                            void *user_data)
{
    (void)user_data; // not used

    DBusMessage *rsp = 0;
    DBusError    err = DBUS_ERROR_INIT;
    const char  *dta = 0;

    if( !(rsp = dbus_pending_call_steal_reply(pending)) )
        goto cleanup;

    if( dbus_set_error_from_message(&err, rsp) ||
            !dbus_message_get_args(rsp, &err,
                                   DBUS_TYPE_STRING, &dta,
                                   DBUS_TYPE_INVALID) )
    {
        dsme_log(LOG_ERR, "usbtracker: mode_request: %s: %s",
                 err.name, err.message);
        goto cleanup;
    }

    dsme_log(LOG_DEBUG, "usbtracker: mode = '%s'", dta ?: "???");

    if( dta )
    {
        charger_connected = is_charging(dta);
        send_charger_status(charger_connected);
        mounted_to_pc = is_mounted_pc(dta);
        send_usb_status(mounted_to_pc);
    }

cleanup:
    if( rsp ) dbus_message_unref(rsp);
    dbus_error_free(&err);
}
示例#8
0
static void twl6030_read_fuelgauge(struct twl6030_bci_device_info *di)
{
	s32 samples;
	int ret, newcap;
	s64 cap, cur;
	u64 tmp;
	int statechanged = 0;

	/* save last reading before taking a new reading */
	di->charge_n2 = di->charge_n1;
	di->timer_n2 = di->timer_n1;

	/* update timer_n1 and charge_n1 */
	ret = twl6030_read_gasguage_regs(di);
	if (ret < 0)
		goto err;

	samples = di->timer_n1 - di->timer_n2;

	/* check for timer overflow */
	if (di->timer_n1 < di->timer_n2)
		samples = samples + (1 << 24);

	/* IACC (As) = ((ACCUM - OFFSET * COUNT) * 62 [mV] ) / (10 [Mohm] * 32768 [HZ] ) */
	/* (As * 62000) / 3600 -> mAh */

	/* TODO: ensure we do this once an hour (3600*4 samples) to avoid overflow */
	cap = (di->charge_n1 - ((s64) di->cc_offset) * ((s64) di->timer_n1)) * 62000LL;
	tmp = (cap < 0) ? -cap : cap;
	do_div(tmp, 1179648);
	cap = (cap < 0) ? -tmp : tmp;

	cur = di->charge_n1 - di->charge_n2 - (di->cc_offset * samples);
	cur *= (62LL * 4LL * 100000LL);
	tmp = (cur < 0) ? -cur : cur;
	do_div(tmp, samples);
	tmp >>= 15; /* / 32768 */
	cur = (cur < 0) ? -tmp : tmp;
	
	di->current_avg_uA = (int) cur;

	twl6030_update_voltage(di);

	/* detect charge termination */
	/* TODO: make configurable */
	/* TODO: termination after X s even if other conditions not met */
	if (is_charging(di) && (di->voltage_mV > 4100) && (di->current_avg_uA < 50000)) {
		if (di->trust_capacity && (di->capacity_uAh < di->capacity_max_uAh) && (di->current_avg_uA > 25000)) {
			/* if we are charging back to a full state with the CC,
			 * be a bit more aggressive than if we only have voltage
			 * to go by
			 */

			/* bump the full time out until the aggressive conditions are not met */
			di->full_jiffies = msecs_to_jiffies(120 * 1000) + jiffies;
		} else if (time_after_eq(jiffies, di->full_jiffies)) {
			di->full_jiffies = msecs_to_jiffies(120 * 1000) + jiffies;
			di->trust_capacity = 1;
			printk("battery: full state detected\n");

			/* calibration will zero the cc accumulator */
			twl6030_calibrate_fuelgauge(di);
			di->capacity_offset = di->capacity_max_uAh;
			cap = 0;

			di->state = STATE_FULL;
			twl6030_stop_usb_charger(di);	
			statechanged = 1;
		}
	} else {
		/* bump the full time out as long as we aren't charging */
		di->full_jiffies = msecs_to_jiffies(120 * 1000) + jiffies;
	}

	cap += di->capacity_offset;

	/* limit capacity range to reasonable values */
	if (cap > ((s64) di->capacity_max_uAh))
		cap = di->capacity_max_uAh;
	if (cap < 0)
		cap = 0;

	di->capacity_uAh = cap;

	/* scale to percentage */
	newcap = cap;
	newcap = newcap / (di->capacity_max_uAh / 100);

	if (!di->trust_capacity) {
		/* if we haven't hit a known full charge state, we may
		 * have more capacity than measured by the CC, so use the
		 * CC measured capacity as the floor, but allow higher
		 * estimated capacities based on voltage
		 */
		ret = twl6030_estimate_capacity(di);
		if (ret > newcap)
			newcap = ret;
	}

	printk("battery: %lld uA  %lld uAh  %d mV  %d s  (%d%%) %s%s%s\n",
		cur, cap, di->voltage_mV, samples / 4, newcap,
		twl6030_state[di->state],
		is_charging(di) ? " CHG" : "",
		di->trust_capacity ? " CC" : " EST");

	if ((newcap != di->capacity) || statechanged) {
		di->capacity = newcap;
		power_supply_changed(&di->bat);
	}

	if ((di->state == STATE_FULL) && (di->capacity < 95)) {
		printk("battery: drained from full to %d%%, charging again\n", di->capacity);
		di->state = STATE_USB;
		twl6030_start_usb_charger(di, 500);
		statechanged = 1;
	}

	return;
err:
	pr_err("%s: Error access to TWL6030 (%d)\n", __func__, ret);
}
示例#9
0
static void twl6030_update_voltage(struct twl6030_bci_device_info *di)
{
	int i;
	int ret;
	int index, q;
	long long total, denom;
	int curr_voltage;

	if (is_charging(di)) {
		if (time_after_eq(jiffies, di->vbat_jiffies)) {
			di->vbat_jiffies = msecs_to_jiffies(60 * 1000) + jiffies;

			twl6030_stop_usb_charger(di);

			msleep(200);

			ret = twl6030_get_gpadc_conversion(di, di->gpadc_vbat_chnl);
			if (ret > 0)
				curr_voltage = ret;

			twl6030_start_usb_charger(di, 500);
		} else {
			/* if no sample is taken don't bother recalculating the weighted average */
			return;
		}
	} else {
		di->vbat_jiffies = jiffies;
		ret = twl6030_get_gpadc_conversion(di, di->gpadc_vbat_chnl);
		if (ret > 0)
			curr_voltage = ret;
	}

	/*
	 * store the measured voltage in the history table. the index points
	 * to the most recent sample.
	 */
	di->voltage_index = (di->voltage_index + 1) & (VOLTAGE_HISTORY_LENGTH - 1);
	di->voltage_history[di->voltage_index] = curr_voltage;

	/* filter the cached voltage using a weighted average */
	q = VOLTAGE_HISTORY_LENGTH; // we need this many bits in the fraction

	index = di->voltage_index;
	total = 0;
	denom = 0;

	for (i=0; i < VOLTAGE_HISTORY_LENGTH; i++) {
		total += (long long) di->voltage_history[index] << (q - i); // convert to q, divide by 2^i
		denom += 1LL << (q - i); // denom += 1/(2^i), in q format

		index = (index + 1) & (VOLTAGE_HISTORY_LENGTH - 1);

		printk("battery voltage history[%d] = %d %s\n", i, di->voltage_history[i], i == di->voltage_index ? "*" : "");
	}

	/* divide by the sum of the weights to get the weighted average */
	total <<= q;
	total += denom >> 1; // round up mid value
	do_div(total, denom);

	/* convert back from q format and store value */
	di->voltage_mV = total >> q;
}
示例#10
0
static void twl6030_determine_charge_state(struct twl6030_bci_device_info *di)
{
	u8 stat1;
	int newstate = STATE_BATTERY;

	/* TODO: i2c error -> fault? */
	twl_i2c_read_u8(TWL6030_MODULE_CHARGER, &stat1, CONTROLLER_STAT1);

	/* TODO: why is STAT1.0 (BAT_TEMP_OVRANGE) always set? */
	/* printk("battery: determine_charge_state() stat1=%02x int1=%02x\n", stat1, int1); */
	
	if (stat1 & VBUS_DET) {
		/* dedicated charger detected by PHY? */
		if (di->usb_event == USB_EVENT_CHARGER)
			newstate = STATE_AC;
		else
			newstate = STATE_USB;

		if (!di->vbus_online) {
			di->vbus_online = 1;
			wake_lock(&usb_wake_lock);
		}
	} else {
		/* ensure we don't have a stale USB_EVENT_CHARGER should detect bounce */
		di->usb_event = USB_EVENT_NONE;

		if (di->vbus_online) {
			di->vbus_online = 0;
			/* give USB and userspace some time to react before suspending */
			wake_lock_timeout(&usb_wake_lock, HZ / 2);
		}
	}

	if (di->state == newstate)
		return;

	switch (newstate) {
	case STATE_FAULT:
	case STATE_BATTERY:
		if (is_charging(di))
			twl6030_stop_usb_charger(di);
		break;
	case STATE_USB:
	case STATE_AC:
		/* moving out of STATE_FULL should only happen on unplug
		 * or if we actually run down the battery capacity
		 */
		if (di->state == STATE_FULL) {
			newstate = STATE_FULL;
			break;
		}

		/* TODO: high current? */
		if (!is_charging(di))
			twl6030_start_usb_charger(di, 500);
		break;
	}

	if (di->state != newstate) {
		printk("battery: state %s -> %s\n",
			twl6030_state[di->state], twl6030_state[newstate]);
		di->state = newstate;
		power_supply_changed(&di->bat);
		power_supply_changed(&di->usb);
	}
}
示例#11
0
static void charger_work(struct work_struct *work)
{
	struct charger_info *di = container_of(work, struct charger_info, work);
	int next_state;
	bool limiting_active;
	bool charge_source;

	if (is_charging(di))
		charger_pet_watchdog(di);

	charger_lock(di);

	/* update inputs and limit conditions */
	charger_gas_gauge_update(di);
	charger_check_temp_limits(di);
	charger_check_battery_level(di);

	/* aggregate limiting factors */
	limiting_active = di->battery_full || di->charge_disabled ||
		di->temperature_lockout;

	/* hardware ready for charging? */
	charge_source = di->vbus_online && !di->otg_online;

	dev_dbg(di->dev, "%s: battery_full=%d charge_disabled=%d temperature_lockout=%d "
			"invalid_charger=%d vbus_online=%d usb_online=%d otg_online=%d\n", __func__,
			di->battery_full, di->charge_disabled, di->temperature_lockout,
			di->invalid_charger, di->vbus_online, di->usb_online, di->otg_online);

	/* determine the next charger state */
	switch (di->state) {
		case CHARGER_STATE_UNPLUGGED:
		case CHARGER_STATE_CHARGING:
			if (charge_source) {
				if (limiting_active)
					next_state = CHARGER_STATE_NOT_CHARGING;
				else
					next_state = CHARGER_STATE_CHARGING;
			} else {
				next_state = CHARGER_STATE_UNPLUGGED;
			}
			break;

		case CHARGER_STATE_NOT_CHARGING:
			if (charge_source) {
				if (limiting_active)
					next_state = CHARGER_STATE_NOT_CHARGING;
				else
					next_state = CHARGER_STATE_CHARGING;
			} else {
				next_state = CHARGER_STATE_UNPLUGGED;
			}
			break;

		default:
			next_state = di->state; // silence compiler warning
	}

	/* if the state changed, fulfill the required changes */
	if (next_state != di->state) {
		dev_info(di->dev, "transitioning from %s to %s\n", state_to_str(di->state),
				state_to_str(next_state));

		switch (next_state) {
			case CHARGER_STATE_UNPLUGGED:
				wake_lock_timeout(&di->wake_lock, HZ / 2);
				charger_stop_usb_charger(di);
				break;

			case CHARGER_STATE_NOT_CHARGING:
				if (!is_powered(di))
					wake_lock(&di->wake_lock);

				charger_stop_usb_charger(di);
				break;

			case CHARGER_STATE_CHARGING:
				if (!is_powered(di))
					wake_lock(&di->wake_lock);

				charger_start_usb_charger(di);
				break;
		}

		di->state = next_state;
		power_supply_changed(&di->usb);

		twl6030_eval_led_state(di->led, is_powered(di), is_charging(di));
	}

	charger_unlock(di);

	/* update timer */
	mod_timer(&di->timer, di->monitor_interval_jiffies + jiffies);
}
示例#12
0
void component_key_alarm()
{
	const uint8 DATA_SIZE = sizeof(HMC5883L_data) + sizeof(RTC_Clock) + sizeof(MMA8451_data);
	char szTrace[piece_size];
	HMC5883L_data data_5883;
	RTC_Clock clock;
	Sensor data_8451;
	uint8 nIndex = 0;
    uint32 nVotage = 0;
	
	LED_Light(led_blue, true);
	sprintf(szTrace, "key = alarm, led = blue");
	post_trace(szTrace);
	
	for(nIndex = 0; nIndex < 60; ++nIndex) {
		HMC5883L_ReadXYZ(&data_5883);
		sprintf(szTrace, "hmc5883 x = %d, y = %d, z = %d", data_5883.x, data_5883.y, data_5883.z);
		post_trace(szTrace);
		
		clock = GetTime();			
		sprintf(szTrace, "sd2058: 20%02d:%02d:%02d %02d:%02d:%02d", clock.year, clock.month, clock.day, clock.hour, clock.minute, clock.second);
		post_trace(szTrace);
		
        if((MMA845x_readbyte(MMA845x_STATUS_00) & 0x08) != 0) { //三个轴数据更新	
            MMA845x_readData(&data_8451);
            if(data_8451.x == -1 && data_8451.y == -1 && data_8451.z == -1) {
                post_trace("MMA8451: read error data");
            } else {
                sprintf(szTrace, "MMA8451: x = %d, y = %d, z = %d", data_8451.x, data_8451.y, data_8451.z);
                post_trace(szTrace);
            }
        } else {
            post_trace("MMA8451: read error");
        }
        
        nVotage = ADC_Read();
        sprintf(szTrace, "votage = %d", nVotage);
		post_trace(szTrace);
		}
	
	memcpy(szTrace, &data_5883, sizeof(HMC5883L_data));
	memcpy(szTrace + sizeof(HMC5883L_data), &clock, sizeof(RTC_Clock));
	memcpy(szTrace + sizeof(HMC5883L_data) + sizeof(RTC_Clock), &data_8451, sizeof(MMA8451_data));
	write_file("temp", szTrace, DATA_SIZE);
	post_trace("save sensor data in file named \"temp\" in tf card");	
	
	{
		InfoBase base_info = { 0 };
		InfoState state_info = { 0 };
		
		if(get_base_info(&base_info)) {
			sprintf(szTrace, "base info, sid = %s, imei = %s", base_info.sid, base_info.imei);
			post_trace(szTrace);
		}
		
		if(get_state_info(&state_info)) {
			sprintf(szTrace, "state info, charging: %s, quantity: %d, sim card: %s, signal: %d, lac: %s, cell: %s, lng: %s, lat: %s", 
			(is_charging(&state_info) ? "yes" : "no"), get_quantity(&state_info), 
			(is_sim_card_exist(&state_info) ? (is_sim_card_valid(&state_info) ? "normal" : "error") : "lost"), get_signal(&state_info),
			state_info.lac, state_info.cell, state_info.lng, state_info.lat);
			post_trace(szTrace);
		}
	}
	post_trace("alarm completed");
	
	LED_Light(led_blue, false);
}