Пример #1
0
/**
 * Init state handler
 *
 *	- check ac, charger, battery and temperature
 *	- initialize charger
 *	- new states: DISCHARGE, IDLE
 */
static enum charge_state state_init(struct charge_state_context *ctx)
{
	/* Stop charger, unconditionally */
	charge_request(0, 0);

	/* if battery was not detected initially, get battery info again */
	if (ctx->battery == NULL)
		ctx->battery = battery_get_info();

	/* Update static battery info */
	update_battery_info();

	/* Clear shutdown timer */
	ctx->shutdown_warning_time.val = 0;

	/* If AC is not present, switch to discharging state */
	if (!ctx->curr.ac)
		return PWR_STATE_DISCHARGE;

	/* Check general error conditions */
	if (ctx->curr.error)
		return PWR_STATE_ERROR;

	/* Send battery event to host */
	host_set_single_event(EC_HOST_EVENT_BATTERY);

	return PWR_STATE_IDLE0;
}
Пример #2
0
//Updates status and info of all batteries locally and in the xenstore.
void update_batteries(void) {

    struct battery_status *old_status = NULL;
    struct battery_info *old_info = NULL;
    char path[256];
    unsigned int old_num_batteries = 0;
    unsigned int num_batteries = 0;
    unsigned int i, new_array_size, old_array_size, num_batteries_to_update;
    bool present_batteries_changed = false;

    if ( pm_specs & PM_SPEC_NO_BATTERIES )
        return;

    //Keep a copy of what the battery status/info used to be.
    old_status = (struct battery_status *)malloc(num_battery_structs_allocd * sizeof(struct battery_status));
    old_info = (struct battery_info *)malloc(num_battery_structs_allocd * sizeof(struct battery_info));

    if (last_status != NULL)
        memcpy(old_status, last_status, num_battery_structs_allocd * sizeof(struct battery_status));
    else
        memset(old_status, 0, num_battery_structs_allocd * sizeof(struct battery_status));

    if (last_info != NULL)
        memcpy(old_info, last_info, num_battery_structs_allocd * sizeof(struct battery_info));
    else
        memset(old_info, 0, num_battery_structs_allocd * sizeof(struct battery_info));

    old_array_size = num_battery_structs_allocd;


    //Resize the arrays if necessary.
    new_array_size = (unsigned int)(get_max_battery_index() + 1);
    if (new_array_size != old_array_size) {
        if (new_array_size == 0) {
            xcpmd_log(LOG_INFO, "All batteries removed.\n");
            free(last_info);
            free(last_status);
        }
        else {
            last_info = (struct battery_info *)realloc(last_info, new_array_size * sizeof(struct battery_info));
            last_status = (struct battery_status *)realloc(last_status, new_array_size * sizeof(struct battery_status));
            memset(last_info, 0, new_array_size * sizeof(struct battery_info));
            memset(last_status, 0, new_array_size * sizeof(struct battery_status));
        }
        num_battery_structs_allocd = new_array_size;
    }

    num_batteries_to_update = (new_array_size > old_array_size) ? new_array_size : old_array_size;

    //Updating all status/info before writing to the xenstore prevents bad
    //calculations of aggregate data (e.g., warning level).
    for (i=0; i < num_batteries_to_update; ++i) {
        update_battery_status(i);
        update_battery_info(i);
    }

    //Write back to the xenstore and only send notifications if things have changed.
    for (i=0; i < num_batteries_to_update; ++i) {

        //No need to update status/info in Xenstore if there was no battery to begin with.
        //   On some latops, batteries index are not contiguous. It is not a big
        //   deal to have one or two empty array slot, but it should not be
        //   reported as a removed battery (OXT-614).
        if (last_status[i].present || old_status[i].present) {
            write_battery_status_to_xenstore(i);
            write_battery_info_to_xenstore(i);
        }

        if (i < old_array_size && i < new_array_size) {
            if (memcmp(&old_info[i], &last_info[i], sizeof(struct battery_info))) {
                snprintf(path, 255, "%s%i/%s", XS_BATTERY_EVENT_PATH, i, XS_BATTERY_INFO_EVENT_LEAF);
                xenstore_write("1", path);
            }

            if (memcmp(&old_status[i], &last_status[i], sizeof(struct battery_status))) {
                snprintf(path, 255, "%s%i/%s", XS_BATTERY_EVENT_PATH, i, XS_BATTERY_STATUS_EVENT_LEAF);
                xenstore_write("1", path);
            }

            if (old_status[i].present == YES)
                ++old_num_batteries;

            if (last_status[i].present == YES)
                ++num_batteries;

            if (old_status[i].present != last_status[i].present)
                present_batteries_changed = true;

        }
        else if (new_array_size > old_array_size) {
            //a battery has been added
            snprintf(path, 255, "%s%i/%s", XS_BATTERY_EVENT_PATH, i, XS_BATTERY_INFO_EVENT_LEAF);
            xenstore_write("1", path);
            snprintf(path, 255, "%s%i/%s", XS_BATTERY_EVENT_PATH, i, XS_BATTERY_STATUS_EVENT_LEAF);
            xenstore_write("1", path);

            if (last_status[i].present == YES)
                ++num_batteries;

            if (i < old_array_size) {
                if (old_status[i].present != last_status[i].present)
                    present_batteries_changed = true;
            }
            else {
                if (last_status[i].present == YES)
                    present_batteries_changed = true;
            }
        }
        else if (new_array_size < old_array_size) {
            //a battery has been removed
            snprintf(path, 255, "%s%i/%s", XS_BATTERY_EVENT_PATH, i, XS_BATTERY_INFO_EVENT_LEAF);
            xenstore_write("1", path);
            snprintf(path, 255, "%s%i/%s", XS_BATTERY_EVENT_PATH, i, XS_BATTERY_STATUS_EVENT_LEAF);
            xenstore_write("1", path);

            if (old_status[i].present == YES)
                ++old_num_batteries;

            if (i < new_array_size) {
                if (old_status[i].present != last_status[i].present)
                    present_batteries_changed = true;
            }
            else {
                if (old_status[i].present == YES)
                    present_batteries_changed = true;
            }
        }
    }

    if ((old_array_size != new_array_size) || (memcmp(old_info, last_info, new_array_size * sizeof(struct battery_info)))) {
        notify_com_citrix_xenclient_xcpmd_battery_info_changed(xcdbus_conn, XCPMD_SERVICE, XCPMD_PATH);
    }

    if ((old_array_size != new_array_size) || (memcmp(old_status, last_status, new_array_size * sizeof(struct battery_status)))) {
        //Here for compatibility--should eventually be removed
        xenstore_write("1", XS_BATTERY_STATUS_CHANGE_EVENT_PATH);
        notify_com_citrix_xenclient_xcpmd_battery_status_changed(xcdbus_conn, XCPMD_SERVICE, XCPMD_PATH);
    }

    if (present_batteries_changed) {
        notify_com_citrix_xenclient_xcpmd_num_batteries_changed(xcdbus_conn, XCPMD_SERVICE, XCPMD_PATH);
    }

    free(old_info);
    free(old_status);
}