-/* $OpenBSD: qcpas.c,v 1.2 2023/07/01 15:50:18 drahn Exp $ */
+/* $OpenBSD: qcpas.c,v 1.3 2024/07/25 20:21:40 kettenis Exp $ */
/*
* Copyright (c) 2023 Patrick Wildt <patrick@blueri.se>
*
return;
}
- /* Assume we can leave HW dangling if proto init fails */
- err = proto->init(NULL);
- if (err) {
- free(name, M_TEMP, namelen);
- return;
- }
-
ch = malloc(sizeof(*ch), M_DEVBUF, M_WAITOK | M_ZERO);
ch->ch_sc = sc;
ch->ch_proto = proto;
TAILQ_INIT(&ch->ch_r_intents);
TAILQ_INSERT_TAIL(&sc->sc_glink_channels, ch, ch_q);
+ /* Assume we can leave HW dangling if proto init fails */
+ err = proto->init(ch);
+ if (err) {
+ TAILQ_REMOVE(&sc->sc_glink_channels, ch, ch_q);
+ free(ch, M_TEMP, sizeof(*ch));
+ free(name, M_TEMP, namelen);
+ return;
+ }
+
msg.cmd = GLINK_CMD_OPEN_ACK;
msg.param1 = ch->ch_rcid;
msg.param2 = 0;
#define BATTMGR_BAT_STATE_CHARGING (1 << 1)
#define BATTMGR_BAT_STATE_CRITICAL_LOW (1 << 2)
uint32_t capacity;
- uint32_t rate;
+ int32_t rate;
uint32_t battery_voltage;
uint32_t power_state;
#define BATTMGR_PWR_STATE_AC_ON (1 << 0)
#if NAPM > 0
struct apm_power_info qcpas_pmic_rtr_apm_power_info;
-uint32_t qcpas_pmic_rtr_last_full_capacity;
+void *qcpas_pmic_rtr_apm_cookie;
#endif
int
info->battery_life = 0;
info->minutes_left = -1;
+ qcpas_pmic_rtr_apm_cookie = cookie;
apm_setinfohook(qcpas_pmic_rtr_apminfo);
#endif
return 0;
int
qcpas_pmic_rtr_recv(void *cookie, uint8_t *buf, int len)
{
+#if NAPM > 0
+ static uint32_t last_full_capacity;
+#endif
struct pmic_glink_hdr hdr;
uint32_t notification;
extern int hw_power;
bat = malloc(sizeof(*bat), M_TEMP, M_WAITOK);
memcpy((void *)bat, buf + sizeof(hdr), sizeof(*bat));
#if NAPM > 0
- qcpas_pmic_rtr_last_full_capacity =
- bat->last_full_capacity;
+ last_full_capacity = bat->last_full_capacity;
#endif
free(bat, M_TEMP, sizeof(*bat));
break;
struct battmgr_bat_status *bat;
#if NAPM > 0
struct apm_power_info *info;
+ uint32_t delta;
#endif
if (len - sizeof(hdr) != sizeof(*bat)) {
printf("%s: invalid battgmr bat status\n",
}
#if NAPM > 0
/* Needs BAT_INFO fist */
- if (!qcpas_pmic_rtr_last_full_capacity)
+ if (last_full_capacity == 0) {
+ wakeup(&qcpas_pmic_rtr_apm_power_info);
return 0;
+ }
#endif
bat = malloc(sizeof(*bat), M_TEMP, M_WAITOK);
memcpy((void *)bat, buf + sizeof(hdr), sizeof(*bat));
#if NAPM > 0
info = &qcpas_pmic_rtr_apm_power_info;
info->battery_life = ((bat->capacity * 100) /
- qcpas_pmic_rtr_last_full_capacity);
+ last_full_capacity);
if (info->battery_life > 50)
info->battery_state = APM_BATT_HIGH;
else if (info->battery_life > 25)
else if (bat->battery_state & BATTMGR_BAT_STATE_CRITICAL_LOW)
info->battery_state = APM_BATT_CRITICAL;
+ if (bat->rate < 0)
+ delta = bat->capacity;
+ else
+ delta = last_full_capacity - bat->capacity;
+ if (bat->rate == 0)
+ info->minutes_left = -1;
+ else
+ info->minutes_left =
+ (60 * delta) / abs(bat->rate);
+
if (bat->power_state & BATTMGR_PWR_STATE_AC_ON) {
info->ac_state = APM_AC_ON;
hw_power = 1;
info->ac_state = APM_AC_OFF;
hw_power = 0;
}
+ wakeup(&qcpas_pmic_rtr_apm_power_info);
#endif
free(bat, M_TEMP, sizeof(*bat));
break;
int
qcpas_pmic_rtr_apminfo(struct apm_power_info *info)
{
- memcpy(info, &qcpas_pmic_rtr_apm_power_info, sizeof(*info));
+ int error;
+ qcpas_pmic_rtr_battmgr_req_status(qcpas_pmic_rtr_apm_cookie);
+ error = tsleep_nsec(&qcpas_pmic_rtr_apm_power_info, PWAIT | PCATCH,
+ "qcapm", SEC_TO_NSEC(5));
+ if (error)
+ return error;
+
+ memcpy(info, &qcpas_pmic_rtr_apm_power_info, sizeof(*info));
return 0;
}
#endif