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(); }
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); }
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; } }
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; }
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; }
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); }
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); }
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); }
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; }
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); } }
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); }
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); }