⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sbs.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	if (*dir) {		remove_proc_entry(ACPI_SBS_FILE_INFO, *dir);		remove_proc_entry(ACPI_SBS_FILE_STATE, *dir);		remove_proc_entry(ACPI_SBS_FILE_ALARM, *dir);		remove_proc_entry((*dir)->name, parent_dir);		*dir = NULL;	}}/* Smart Battery Interface */static struct proc_dir_entry *acpi_battery_dir = NULL;static inline char *acpi_battery_units(struct acpi_battery *battery){	return acpi_battery_mode(battery) ? " mW" : " mA";}static int acpi_battery_read_info(struct seq_file *seq, void *offset){	struct acpi_battery *battery = seq->private;	struct acpi_sbs *sbs = battery->sbs;	int result = 0;	mutex_lock(&sbs->lock);	seq_printf(seq, "present:                 %s\n",		   (battery->present) ? "yes" : "no");	if (!battery->present)		goto end;	seq_printf(seq, "design capacity:         %i%sh\n",		   battery->design_capacity * acpi_battery_scale(battery),		   acpi_battery_units(battery));	seq_printf(seq, "last full capacity:      %i%sh\n",		   battery->full_charge_capacity * acpi_battery_scale(battery),		   acpi_battery_units(battery));	seq_printf(seq, "battery technology:      rechargeable\n");	seq_printf(seq, "design voltage:          %i mV\n",		   battery->design_voltage * acpi_battery_vscale(battery));	seq_printf(seq, "design capacity warning: unknown\n");	seq_printf(seq, "design capacity low:     unknown\n");	seq_printf(seq, "capacity granularity 1:  unknown\n");	seq_printf(seq, "capacity granularity 2:  unknown\n");	seq_printf(seq, "model number:            %s\n", battery->device_name);	seq_printf(seq, "serial number:           %i\n",		   battery->serial_number);	seq_printf(seq, "battery type:            %s\n",		   battery->device_chemistry);	seq_printf(seq, "OEM info:                %s\n",		   battery->manufacturer_name);      end:	mutex_unlock(&sbs->lock);	return result;}static int acpi_battery_info_open_fs(struct inode *inode, struct file *file){	return single_open(file, acpi_battery_read_info, PDE(inode)->data);}static int acpi_battery_read_state(struct seq_file *seq, void *offset){	struct acpi_battery *battery = seq->private;	struct acpi_sbs *sbs = battery->sbs;	int rate;	mutex_lock(&sbs->lock);	seq_printf(seq, "present:                 %s\n",		   (battery->present) ? "yes" : "no");	if (!battery->present)		goto end;	acpi_battery_get_state(battery);	seq_printf(seq, "capacity state:          %s\n",		   (battery->state & 0x0010) ? "critical" : "ok");	seq_printf(seq, "charging state:          %s\n",		   (battery->current_now < 0) ? "discharging" :		   ((battery->current_now > 0) ? "charging" : "charged"));	rate = abs(battery->current_now) * acpi_battery_ipscale(battery);	rate *= (acpi_battery_mode(battery))?(battery->voltage_now *			acpi_battery_vscale(battery)/1000):1;	seq_printf(seq, "present rate:            %d%s\n", rate,		   acpi_battery_units(battery));	seq_printf(seq, "remaining capacity:      %i%sh\n",		   battery->capacity_now * acpi_battery_scale(battery),		   acpi_battery_units(battery));	seq_printf(seq, "present voltage:         %i mV\n",		   battery->voltage_now * acpi_battery_vscale(battery));      end:	mutex_unlock(&sbs->lock);	return 0;}static int acpi_battery_state_open_fs(struct inode *inode, struct file *file){	return single_open(file, acpi_battery_read_state, PDE(inode)->data);}static int acpi_battery_read_alarm(struct seq_file *seq, void *offset){	struct acpi_battery *battery = seq->private;	struct acpi_sbs *sbs = battery->sbs;	int result = 0;	mutex_lock(&sbs->lock);	if (!battery->present) {		seq_printf(seq, "present:                 no\n");		goto end;	}	acpi_battery_get_alarm(battery);	seq_printf(seq, "alarm:                   ");	if (battery->alarm_capacity)		seq_printf(seq, "%i%sh\n",			   battery->alarm_capacity *			   acpi_battery_scale(battery),			   acpi_battery_units(battery));	else		seq_printf(seq, "disabled\n");      end:	mutex_unlock(&sbs->lock);	return result;}static ssize_tacpi_battery_write_alarm(struct file *file, const char __user * buffer,			 size_t count, loff_t * ppos){	struct seq_file *seq = file->private_data;	struct acpi_battery *battery = seq->private;	struct acpi_sbs *sbs = battery->sbs;	char alarm_string[12] = { '\0' };	int result = 0;	mutex_lock(&sbs->lock);	if (!battery->present) {		result = -ENODEV;		goto end;	}	if (count > sizeof(alarm_string) - 1) {		result = -EINVAL;		goto end;	}	if (copy_from_user(alarm_string, buffer, count)) {		result = -EFAULT;		goto end;	}	alarm_string[count] = 0;	battery->alarm_capacity = simple_strtoul(alarm_string, NULL, 0) /					acpi_battery_scale(battery);	acpi_battery_set_alarm(battery);      end:	mutex_unlock(&sbs->lock);	if (result)		return result;	return count;}static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file){	return single_open(file, acpi_battery_read_alarm, PDE(inode)->data);}static struct file_operations acpi_battery_info_fops = {	.open = acpi_battery_info_open_fs,	.read = seq_read,	.llseek = seq_lseek,	.release = single_release,	.owner = THIS_MODULE,};static struct file_operations acpi_battery_state_fops = {	.open = acpi_battery_state_open_fs,	.read = seq_read,	.llseek = seq_lseek,	.release = single_release,	.owner = THIS_MODULE,};static struct file_operations acpi_battery_alarm_fops = {	.open = acpi_battery_alarm_open_fs,	.read = seq_read,	.write = acpi_battery_write_alarm,	.llseek = seq_lseek,	.release = single_release,	.owner = THIS_MODULE,};/* Legacy AC Adapter Interface */static struct proc_dir_entry *acpi_ac_dir = NULL;static int acpi_ac_read_state(struct seq_file *seq, void *offset){	struct acpi_sbs *sbs = seq->private;	mutex_lock(&sbs->lock);	seq_printf(seq, "state:                   %s\n",		   sbs->charger_present ? "on-line" : "off-line");	mutex_unlock(&sbs->lock);	return 0;}static int acpi_ac_state_open_fs(struct inode *inode, struct file *file){	return single_open(file, acpi_ac_read_state, PDE(inode)->data);}static struct file_operations acpi_ac_state_fops = {	.open = acpi_ac_state_open_fs,	.read = seq_read,	.llseek = seq_lseek,	.release = single_release,	.owner = THIS_MODULE,};#endif/* --------------------------------------------------------------------------                                 Driver Interface   -------------------------------------------------------------------------- */static int acpi_battery_read(struct acpi_battery *battery){	int result = 0, saved_present = battery->present;	u16 state;	if (battery->sbs->manager_present) {		result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD,				ACPI_SBS_MANAGER, 0x01, (u8 *)&state);		if (!result)			battery->present = state & (1 << battery->id);		state &= 0x0fff;		state |= 1 << (battery->id + 12);		acpi_smbus_write(battery->sbs->hc, SMBUS_WRITE_WORD,				  ACPI_SBS_MANAGER, 0x01, (u8 *)&state, 2);	} else if (battery->id == 0)		battery->present = 1;	if (result || !battery->present)		return result;	if (saved_present != battery->present) {		battery->update_time = 0;		result = acpi_battery_get_info(battery);		if (result)			return result;	}	result = acpi_battery_get_state(battery);	return result;}/* Smart Battery */static int acpi_battery_add(struct acpi_sbs *sbs, int id){	struct acpi_battery *battery = &sbs->battery[id];	int result;	battery->id = id;	battery->sbs = sbs;	result = acpi_battery_read(battery);	if (result)		return result;	sprintf(battery->name, ACPI_BATTERY_DIR_NAME, id);#ifdef CONFIG_ACPI_PROCFS_POWER	acpi_sbs_add_fs(&battery->proc_entry, acpi_battery_dir,			battery->name, &acpi_battery_info_fops,			&acpi_battery_state_fops, &acpi_battery_alarm_fops,			battery);#endif#ifdef CONFIG_ACPI_SYSFS_POWER	battery->bat.name = battery->name;	battery->bat.type = POWER_SUPPLY_TYPE_BATTERY;	if (!acpi_battery_mode(battery)) {		battery->bat.properties = sbs_charge_battery_props;		battery->bat.num_properties =		    ARRAY_SIZE(sbs_charge_battery_props);	} else {		battery->bat.properties = sbs_energy_battery_props;		battery->bat.num_properties =		    ARRAY_SIZE(sbs_energy_battery_props);	}	battery->bat.get_property = acpi_sbs_battery_get_property;	result = power_supply_register(&sbs->device->dev, &battery->bat);	if (result)		goto end;	result = device_create_file(battery->bat.dev, &alarm_attr);	if (result)		goto end;	battery->have_sysfs_alarm = 1;      end:#endif	printk(KERN_INFO PREFIX "%s [%s]: Battery Slot [%s] (battery %s)\n",	       ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device),	       battery->name, sbs->battery->present ? "present" : "absent");	return result;}static void acpi_battery_remove(struct acpi_sbs *sbs, int id){	struct acpi_battery *battery = &sbs->battery[id];#ifdef CONFIG_ACPI_SYSFS_POWER	if (battery->bat.dev) {		if (battery->have_sysfs_alarm)			device_remove_file(battery->bat.dev, &alarm_attr);		power_supply_unregister(&battery->bat);	}#endif#ifdef CONFIG_ACPI_PROCFS_POWER	if (battery->proc_entry)		acpi_sbs_remove_fs(&battery->proc_entry, acpi_battery_dir);#endif}static int acpi_charger_add(struct acpi_sbs *sbs){	int result;	result = acpi_ac_get_present(sbs);	if (result)		goto end;#ifdef CONFIG_ACPI_PROCFS_POWER	result = acpi_sbs_add_fs(&sbs->charger_entry, acpi_ac_dir,				 ACPI_AC_DIR_NAME, NULL,				 &acpi_ac_state_fops, NULL, sbs);	if (result)		goto end;#endif#ifdef CONFIG_ACPI_SYSFS_POWER	sbs->charger.name = "sbs-charger";	sbs->charger.type = POWER_SUPPLY_TYPE_MAINS;	sbs->charger.properties = sbs_ac_props;	sbs->charger.num_properties = ARRAY_SIZE(sbs_ac_props);	sbs->charger.get_property = sbs_get_ac_property;	power_supply_register(&sbs->device->dev, &sbs->charger);#endif	printk(KERN_INFO PREFIX "%s [%s]: AC Adapter [%s] (%s)\n",	       ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device),	       ACPI_AC_DIR_NAME, sbs->charger_present ? "on-line" : "off-line");      end:	return result;}static void acpi_charger_remove(struct acpi_sbs *sbs){#ifdef CONFIG_ACPI_SYSFS_POWER	if (sbs->charger.dev)		power_supply_unregister(&sbs->charger);#endif#ifdef CONFIG_ACPI_PROCFS_POWER	if (sbs->charger_entry)		acpi_sbs_remove_fs(&sbs->charger_entry, acpi_ac_dir);#endif}void acpi_sbs_callback(void *context){	int id;	struct acpi_sbs *sbs = context;	struct acpi_battery *bat;	u8 saved_charger_state = sbs->charger_present;	u8 saved_battery_state;	acpi_ac_get_present(sbs);	if (sbs->charger_present != saved_charger_state) {#ifdef CONFIG_ACPI_PROC_EVENT		acpi_bus_generate_proc_event4(ACPI_AC_CLASS, ACPI_AC_DIR_NAME,					      ACPI_SBS_NOTIFY_STATUS,					      sbs->charger_present);#endif#ifdef CONFIG_ACPI_SYSFS_POWER		kobject_uevent(&sbs->charger.dev->kobj, KOBJ_CHANGE);#endif	}	if (sbs->manager_present) {		for (id = 0; id < MAX_SBS_BAT; ++id) {			if (!(sbs->batteries_supported & (1 << id)))				continue;			bat = &sbs->battery[id];			saved_battery_state = bat->present;			acpi_battery_read(bat);			if (saved_battery_state == bat->present)				continue;#ifdef CONFIG_ACPI_PROC_EVENT			acpi_bus_generate_proc_event4(ACPI_BATTERY_CLASS,						      bat->name,						      ACPI_SBS_NOTIFY_STATUS,						      bat->present);#endif#ifdef CONFIG_ACPI_SYSFS_POWER			kobject_uevent(&bat->bat.dev->kobj, KOBJ_CHANGE);#endif		}	}}static int acpi_sbs_remove(struct acpi_device *device, int type);static int acpi_sbs_add(struct acpi_device *device){	struct acpi_sbs *sbs;	int result = 0;	int id;	sbs = kzalloc(sizeof(struct acpi_sbs), GFP_KERNEL);	if (!sbs) {		result = -ENOMEM;		goto end;	}	mutex_init(&sbs->lock);	sbs->hc = acpi_driver_data(device->parent);	sbs->device = device;	strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME);	strcpy(acpi_device_class(device), ACPI_SBS_CLASS);	acpi_driver_data(device) = sbs;	result = acpi_charger_add(sbs);	if (result)		goto end;	result = acpi_manager_get_info(sbs);	if (!result) {		sbs->manager_present = 1;		for (id = 0; id < MAX_SBS_BAT; ++id)			if ((sbs->batteries_supported & (1 << id)))				acpi_battery_add(sbs, id);	} else		acpi_battery_add(sbs, 0);	acpi_smbus_register_callback(sbs->hc, acpi_sbs_callback, sbs);      end:	if (result)		acpi_sbs_remove(device, 0);	return result;}static int acpi_sbs_remove(struct acpi_device *device, int type){	struct acpi_sbs *sbs;	int id;	if (!device)		return -EINVAL;	sbs = acpi_driver_data(device);	if (!sbs)		return -EINVAL;	mutex_lock(&sbs->lock);	acpi_smbus_unregister_callback(sbs->hc);	for (id = 0; id < MAX_SBS_BAT; ++id)		acpi_battery_remove(sbs, id);	acpi_charger_remove(sbs);	mutex_unlock(&sbs->lock);	mutex_destroy(&sbs->lock);	kfree(sbs);	return 0;}static void acpi_sbs_rmdirs(void){#ifdef CONFIG_ACPI_PROCFS_POWER	if (acpi_ac_dir) {		acpi_unlock_ac_dir(acpi_ac_dir);		acpi_ac_dir = NULL;	}	if (acpi_battery_dir) {		acpi_unlock_battery_dir(acpi_battery_dir);		acpi_battery_dir = NULL;	}#endif}static int acpi_sbs_resume(struct acpi_device *device){	struct acpi_sbs *sbs;	if (!device)		return -EINVAL;	sbs = device->driver_data;	acpi_sbs_callback(sbs);	return 0;}static struct acpi_driver acpi_sbs_driver = {	.name = "sbs",	.class = ACPI_SBS_CLASS,	.ids = sbs_device_ids,	.ops = {		.add = acpi_sbs_add,		.remove = acpi_sbs_remove,		.resume = acpi_sbs_resume,		},};static int __init acpi_sbs_init(void){	int result = 0;	if (acpi_disabled)		return -ENODEV;#ifdef CONFIG_ACPI_PROCFS_POWER	acpi_ac_dir = acpi_lock_ac_dir();	if (!acpi_ac_dir)		return -ENODEV;	acpi_battery_dir = acpi_lock_battery_dir();	if (!acpi_battery_dir) {		acpi_sbs_rmdirs();		return -ENODEV;	}#endif	result = acpi_bus_register_driver(&acpi_sbs_driver);	if (result < 0) {		acpi_sbs_rmdirs();		return -ENODEV;	}	return 0;}static void __exit acpi_sbs_exit(void){	acpi_bus_unregister_driver(&acpi_sbs_driver);	acpi_sbs_rmdirs();	return;}module_init(acpi_sbs_init);module_exit(acpi_sbs_exit);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -