drivers/power/supply/ipaq_micro_battery.c

Source file repositories/reference/linux-study-clean/drivers/power/supply/ipaq_micro_battery.c

File Facts

System
Linux kernel
Corpus path
drivers/power/supply/ipaq_micro_battery.c
Extension
.c
Size
7644 bytes
Lines
295
Domain
Driver Families
Bucket
drivers/power
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct micro_battery {
	struct ipaq_micro *micro;
	struct workqueue_struct *wq;
	struct delayed_work update;
	u8 ac;
	u8 chemistry;
	unsigned int voltage;
	u16 temperature;
	u8 flag;
};

static void micro_battery_work(struct work_struct *work)
{
	struct micro_battery *mb = container_of(work,
				struct micro_battery, update.work);
	struct ipaq_micro_msg msg_battery = {
		.id = MSG_BATTERY,
	};
	struct ipaq_micro_msg msg_sensor = {
		.id = MSG_THERMAL_SENSOR,
	};

	/* First send battery message */
	ipaq_micro_tx_msg_sync(mb->micro, &msg_battery);
	if (msg_battery.rx_len < 4)
		pr_info("ERROR");

	/*
	 * Returned message format:
	 * byte 0:   0x00 = Not plugged in
	 *           0x01 = AC adapter plugged in
	 * byte 1:   chemistry
	 * byte 2:   voltage LSB
	 * byte 3:   voltage MSB
	 * byte 4:   flags
	 * byte 5-9: same for battery 2
	 */
	mb->ac = msg_battery.rx_data[0];
	mb->chemistry = msg_battery.rx_data[1];
	mb->voltage = ((((unsigned short)msg_battery.rx_data[3] << 8) +
			msg_battery.rx_data[2]) * 5000L) * 1000 / 1024;
	mb->flag = msg_battery.rx_data[4];

	if (msg_battery.rx_len == 9)
		pr_debug("second battery ignored\n");

	/* Then read the sensor */
	ipaq_micro_tx_msg_sync(mb->micro, &msg_sensor);
	mb->temperature = msg_sensor.rx_data[1] << 8 | msg_sensor.rx_data[0];

	queue_delayed_work(mb->wq, &mb->update, msecs_to_jiffies(BATT_PERIOD));
}

static int get_capacity(struct power_supply *b)
{
	struct micro_battery *mb = dev_get_drvdata(b->dev.parent);

	switch (mb->flag & 0x07) {
	case MICRO_BATT_STATUS_HIGH:
		return 100;
		break;
	case MICRO_BATT_STATUS_LOW:
		return 50;
		break;
	case MICRO_BATT_STATUS_CRITICAL:
		return 5;
		break;
	default:
		break;
	}
	return 0;
}

static int get_status(struct power_supply *b)
{
	struct micro_battery *mb = dev_get_drvdata(b->dev.parent);

	if (mb->flag == MICRO_BATT_STATUS_UNKNOWN)
		return POWER_SUPPLY_STATUS_UNKNOWN;

	if (mb->flag & MICRO_BATT_STATUS_FULL)
		return POWER_SUPPLY_STATUS_FULL;

	if ((mb->flag & MICRO_BATT_STATUS_CHARGING) ||
		(mb->flag & MICRO_BATT_STATUS_CHARGEMAIN))
		return POWER_SUPPLY_STATUS_CHARGING;

	return POWER_SUPPLY_STATUS_DISCHARGING;
}

Annotation

Implementation Notes