Previously, all the remotes attached to the same receiver would share the same power_supply. That's not good as the remotes will constantly change the battery information according to their own state.
To have something generic enough, we introduce struct wacom_battery which regroups all the information we need for a battery. This backport works around the split in the battery path at kernel 4.1. Signed-off-by: Benjamin Tissoires <benjamin.tissoi...@redhat.com> Acked-by: Ping Cheng <pi...@wacom.com> Signed-off-by: Jiri Kosina <jkos...@suse.cz> [aaron.sko...@wacom.com: Imported into input-wacom repository (59d69bc)] Signed-off-by: Aaron Armstrong Skomra <aaron.sko...@wacom.com> [aaron.sko...@wacom.com: Backported from input-wacom repository (89f769c)] Signed-off-by: Aaron Armstrong Skomra <aaron.sko...@wacom.com> --- 2.6.38/wacom.h | 14 +++- 2.6.38/wacom_sys.c | 91 ++++++++++++++--------- 2.6.38/wacom_wac.c | 55 +++++++------- 2.6.38/wacom_wac.h | 5 -- 3.17/wacom.h | 27 +++++-- 3.17/wacom_sys.c | 214 +++++++++++++++++++++++++++++++++-------------------- 3.17/wacom_wac.c | 53 ++++++------- 3.17/wacom_wac.h | 6 -- 3.7/wacom.h | 14 +++- 3.7/wacom_sys.c | 101 ++++++++++++++++--------- 3.7/wacom_wac.c | 55 +++++++------- 3.7/wacom_wac.h | 5 -- 12 files changed, 385 insertions(+), 255 deletions(-) diff --git a/2.6.38/wacom.h b/2.6.38/wacom.h index e501fae..0ccfcc1 100644 --- a/2.6.38/wacom.h +++ b/2.6.38/wacom.h @@ -119,6 +119,17 @@ enum wacom_worker { WACOM_WORKER_REMOTE, }; +struct wacom_battery { + struct power_supply battery; + struct power_supply ac; + char bat_name[WACOM_NAME_MAX]; + char ac_name[WACOM_NAME_MAX]; + int battery_capacity; + int bat_charging; + int bat_connected; + int ps_connected; +}; + struct wacom_remote { spinlock_t remote_lock; struct kfifo remote_fifo; @@ -128,6 +139,7 @@ struct wacom_remote { u32 serial; struct input_dev *input; bool registered; + struct wacom_battery battery; } remotes[WACOM_MAX_REMOTES]; }; @@ -150,7 +162,7 @@ struct wacom { u8 hlv; /* status led brightness button pressed (1..127) */ u8 img_lum; /* OLED matrix display brightness */ } led; - struct power_supply battery; + struct wacom_battery battery; }; static inline void wacom_schedule_work(struct wacom_wac *wacom_wac, diff --git a/2.6.38/wacom_sys.c b/2.6.38/wacom_sys.c index b8dbcc4..5683cd8 100644 --- a/2.6.38/wacom_sys.c +++ b/2.6.38/wacom_sys.c @@ -1159,12 +1159,13 @@ static int wacom_battery_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) { - struct wacom *wacom = container_of(psy, struct wacom, battery); + struct wacom_battery *battery = container_of(psy, struct wacom_battery, + battery); int ret = 0; switch (psp) { case POWER_SUPPLY_PROP_PRESENT: - val->intval = wacom->wacom_wac.bat_connected; + val->intval = battery->bat_connected; break; #ifdef POWER_SUPPLY_PROP_SCOPE case POWER_SUPPLY_PROP_SCOPE: @@ -1172,16 +1173,15 @@ static int wacom_battery_get_property(struct power_supply *psy, break; #endif case POWER_SUPPLY_PROP_CAPACITY: - val->intval = - wacom->wacom_wac.battery_capacity; + val->intval = battery->battery_capacity; break; case POWER_SUPPLY_PROP_STATUS: - if (wacom->wacom_wac.bat_charging) + if (battery->bat_charging) val->intval = POWER_SUPPLY_STATUS_CHARGING; - else if (wacom->wacom_wac.battery_capacity == 100 && - wacom->wacom_wac.ps_connected) + else if (battery->battery_capacity == 100 && + battery->ps_connected) val->intval = POWER_SUPPLY_STATUS_FULL; - else if (wacom->wacom_wac.ps_connected) + else if (battery->ps_connected) val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; else val->intval = POWER_SUPPLY_STATUS_DISCHARGING; @@ -1194,48 +1194,65 @@ static int wacom_battery_get_property(struct power_supply *psy, return ret; } -static int wacom_initialize_battery(struct wacom *wacom) +static int __wacom_initialize_battery(struct wacom *wacom, + struct wacom_battery *battery) { static atomic_t battery_no = ATOMIC_INIT(0); static DEFINE_SPINLOCK(ps_lock); unsigned long flags; int error = 0; + unsigned long n; spin_lock_irqsave(&ps_lock, flags); /* Prevent potential race for the "wacom_battery" name */ - if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_BATTERY) { - unsigned long n = atomic_inc_return(&battery_no) - 1; + n = atomic_inc_return(&battery_no) - 1; - if (power_supply_get_by_name("wacom_battery")) - sprintf(wacom->wacom_wac.bat_name, "wacom_battery_%ld", n); - else - sprintf(wacom->wacom_wac.bat_name, "wacom_battery"); + if (power_supply_get_by_name("wacom_battery")) + sprintf(battery->bat_name, "wacom_battery_%ld", n); + else + sprintf(battery->bat_name, "wacom_battery"); - wacom->battery.properties = wacom_battery_props; - wacom->battery.num_properties = ARRAY_SIZE(wacom_battery_props); - wacom->battery.get_property = wacom_battery_get_property; - wacom->battery.name = wacom->wacom_wac.bat_name; - wacom->battery.type = POWER_SUPPLY_TYPE_BATTERY; - wacom->battery.use_for_apm = 0; + battery->battery.properties = wacom_battery_props; + battery->battery.num_properties = ARRAY_SIZE(wacom_battery_props); + battery->battery.get_property = wacom_battery_get_property; + battery->battery.name = battery->bat_name; + battery->battery.type = POWER_SUPPLY_TYPE_BATTERY; + battery->battery.use_for_apm = 0; - error = power_supply_register(&wacom->usbdev->dev, - &wacom->battery); + error = power_supply_register(&wacom->usbdev->dev, + &battery->battery); #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0) - if (!error) - power_supply_powers(&wacom->battery, - &wacom->usbdev->dev); + if (!error) + power_supply_powers(&battery->battery, + &wacom->usbdev->dev); #endif - } + spin_unlock_irqrestore(&ps_lock, flags); return error; } +static int wacom_initialize_battery(struct wacom *wacom) +{ + if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_BATTERY) + return __wacom_initialize_battery(wacom, &wacom->battery); + + return 0; +} + static void wacom_destroy_battery(struct wacom *wacom) { - if (wacom->battery.dev) { - power_supply_unregister(&wacom->battery); - wacom->battery.dev = NULL; + if (wacom->battery.battery.dev) { + power_supply_unregister(&wacom->battery.battery); + wacom->battery.battery.dev = NULL; + } +} + +static void wacom_destroy_remote_battery(struct wacom_battery *battery) +{ + if (battery->battery.dev) { + power_supply_unregister(&battery->battery); + battery->battery.dev = NULL; } } @@ -1341,6 +1358,9 @@ static void wacom_remote_destroy_one(struct wacom *wacom, unsigned int index) if (remote->remotes[index].input) input_unregister_device(remote->remotes[index].input); + if (remote->remotes[index].battery.battery.dev) + wacom_destroy_remote_battery(&remote->remotes[index].battery); + for (i = 0; i < WACOM_MAX_REMOTES; i++) { if (remote->remotes[i].serial == serial) { remote->remotes[i].serial = 0; @@ -1402,7 +1422,7 @@ static void wacom_remotes_destroy(void *data) return; for (i = 0; i < WACOM_MAX_REMOTES; i++) { - if (wacom->remote->remotes[i].group.name) { + if (remote->remotes[i].registered) { wacom_remote_destroy_one(wacom, i); } } @@ -1611,6 +1631,11 @@ static int wacom_remote_create_one(struct wacom *wacom, u32 serial, remote->remotes[index].registered = true; + error = __wacom_initialize_battery(wacom, + &remote->remotes[index].battery); + if (error) + goto fail; + devres_close_group(dev, &remote->remotes[index]); return 0; @@ -1765,11 +1790,11 @@ void wacom_battery_work(struct work_struct *work) struct wacom *wacom = container_of(work, struct wacom, battery_work); if ((wacom->wacom_wac.features.quirks & WACOM_QUIRK_BATTERY) && - !wacom->battery.dev) { + !wacom->battery.battery.dev) { wacom_initialize_battery(wacom); } else if (!(wacom->wacom_wac.features.quirks & WACOM_QUIRK_BATTERY) && - wacom->battery.dev) { + wacom->battery.battery.dev) { wacom_destroy_battery(wacom); } } diff --git a/2.6.38/wacom_wac.c b/2.6.38/wacom_wac.c index 4e246d0..4d14e97 100644 --- a/2.6.38/wacom_wac.c +++ b/2.6.38/wacom_wac.c @@ -41,27 +41,36 @@ static void wacom_report_numbered_buttons(struct input_dev *input_dev, int button_cout, int mask); -static void wacom_notify_battery(struct wacom_wac *wacom_wac, +static void __wacom_notify_battery(struct wacom_battery *battery, int bat_capacity, bool bat_charging, bool bat_connected, bool ps_connected) { - struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac); - bool changed = wacom_wac->battery_capacity != bat_capacity || - wacom_wac->bat_charging != bat_charging || - wacom_wac->bat_connected != bat_connected || - wacom_wac->ps_connected != ps_connected; + bool changed = battery->battery_capacity != bat_capacity || + battery->bat_charging != bat_charging || + battery->bat_connected != bat_connected || + battery->ps_connected != ps_connected; if (changed) { - wacom_wac->battery_capacity = bat_capacity; - wacom_wac->bat_charging = bat_charging; - wacom_wac->bat_connected = bat_connected; - wacom_wac->ps_connected = ps_connected; + battery->battery_capacity = bat_capacity; + battery->bat_charging = bat_charging; + battery->bat_connected = bat_connected; + battery->ps_connected = ps_connected; - if (wacom->battery.dev) - power_supply_changed(&wacom->battery); + if (battery->battery.dev) + power_supply_changed(&battery->battery); } } +static void wacom_notify_battery(struct wacom_wac *wacom_wac, + int bat_capacity, bool bat_charging, bool bat_connected, + bool ps_connected) +{ + struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac); + + __wacom_notify_battery(&wacom->battery, bat_capacity, bat_charging, + bat_connected, ps_connected); +} + static int wacom_penpartner_irq(struct wacom_wac *wacom) { unsigned char *data = wacom->data; @@ -701,7 +710,6 @@ static int wacom_remote_irq(struct wacom_wac *wacom_wac, size_t len) { unsigned char *data = wacom_wac->data; struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac); - struct wacom_features *features = &wacom_wac->features; struct wacom_remote *remote = wacom->remote; struct input_dev *input; int bat_charging, bat_percent, touch_ring_mode; @@ -778,13 +786,8 @@ static int wacom_remote_irq(struct wacom_wac *wacom_wac, size_t len) wacom->led.select[i] = touch_ring_mode; } - if (!wacom->battery.dev && - !(features->quirks & WACOM_QUIRK_BATTERY)) { - features->quirks |= WACOM_QUIRK_BATTERY; - wacom_schedule_work(wacom_wac, WACOM_WORKER_BATTERY); - } - - wacom_notify_battery(wacom_wac, bat_percent, bat_charging, 1, bat_charging); + __wacom_notify_battery(&remote->remotes[index].battery, bat_percent, + bat_charging, 1, bat_charging); out: spin_unlock_irqrestore(&remote->remote_lock, flags); @@ -1557,7 +1560,6 @@ static int wacom_bpt_irq(struct wacom_wac *wacom, size_t len) static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len) { - struct wacom *w = container_of(wacom, struct wacom, wacom_wac); unsigned char *data = wacom->data; int connected; @@ -1585,8 +1587,7 @@ static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len) wacom_schedule_work(wacom, WACOM_WORKER_WIRELESS); } - if (w->battery.dev) - wacom_notify_battery(wacom, battery, charging, 1, 0); + wacom_notify_battery(wacom, battery, charging, 1, 0); } else if (wacom->pid != 0) { /* disconnected while previously connected */ @@ -1623,14 +1624,14 @@ static int wacom_status_irq(struct wacom_wac *wacom_wac, size_t len) wacom_notify_battery(wacom_wac, battery, charging, battery || charging, 1); - if (!wacom->battery.dev && + if (!wacom->battery.battery.dev && !(features->quirks & WACOM_QUIRK_BATTERY)) { features->quirks |= WACOM_QUIRK_BATTERY; wacom_schedule_work(wacom_wac, WACOM_WORKER_BATTERY); } } else if ((features->quirks & WACOM_QUIRK_BATTERY) && - wacom->battery.dev) { + wacom->battery.battery.dev) { features->quirks &= ~WACOM_QUIRK_BATTERY; wacom_schedule_work(wacom_wac, WACOM_WORKER_BATTERY); wacom_notify_battery(wacom_wac, 0, 0, 0, 0); @@ -1856,9 +1857,9 @@ void wacom_setup_device_quirks(struct wacom *wacom) } } - if (features->type == REMOTE) { + if (features->type == REMOTE) features->quirks |= WACOM_QUIRK_MONITOR; - } + } static void wacom_abs_set_axis(struct input_dev *input_dev, diff --git a/2.6.38/wacom_wac.h b/2.6.38/wacom_wac.h index abe52fb..844ab81 100644 --- a/2.6.38/wacom_wac.h +++ b/2.6.38/wacom_wac.h @@ -174,7 +174,6 @@ struct wacom_remote_data { struct wacom_wac { char name[WACOM_NAME_MAX]; - char bat_name[WACOM_NAME_MAX]; unsigned char *data; int tool[2]; int id[2]; @@ -184,12 +183,8 @@ struct wacom_wac { struct wacom_shared *shared; struct input_dev *input; int pid; - int battery_capacity; int num_contacts_left; int *slots; - int bat_charging; - int bat_connected; - int ps_connected; }; #endif diff --git a/3.17/wacom.h b/3.17/wacom.h index c299a83..d3fb8b9 100644 --- a/3.17/wacom.h +++ b/3.17/wacom.h @@ -130,6 +130,24 @@ struct wacom_group_leds { u8 select; /* status led selector (0..3) */ }; +struct wacom_battery { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,1,0) + struct power_supply_desc bat_desc; + struct power_supply_desc ac_desc; + struct power_supply *battery; + struct power_supply *ac; +#else + struct power_supply battery; + struct power_supply ac; +#endif + char bat_name[WACOM_NAME_MAX]; + char ac_name[WACOM_NAME_MAX]; + int battery_capacity; + int bat_charging; + int bat_connected; + int ps_connected; +}; + struct wacom_remote { spinlock_t remote_lock; struct kfifo remote_fifo; @@ -139,6 +157,7 @@ struct wacom_remote { u32 serial; struct input_dev *input; bool registered; + struct wacom_battery battery; } remotes[WACOM_MAX_REMOTES]; }; @@ -159,13 +178,9 @@ struct wacom { u8 img_lum; /* OLED matrix display brightness */ } led; #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,1,0) - struct power_supply *battery; - struct power_supply *ac; - struct power_supply_desc battery_desc; - struct power_supply_desc ac_desc; + struct wacom_battery battery; #else - struct power_supply battery; - struct power_supply ac; + struct wacom_battery battery; #endif bool resources; }; diff --git a/3.17/wacom_sys.c b/3.17/wacom_sys.c index efa03fb..793cb72 100644 --- a/3.17/wacom_sys.c +++ b/3.17/wacom_sys.c @@ -1118,30 +1118,29 @@ static int wacom_battery_get_property(struct power_supply *psy, union power_supply_propval *val) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,1,0) - struct wacom *wacom = power_supply_get_drvdata(psy); + struct wacom_battery *battery = power_supply_get_drvdata(psy); #else - struct wacom *wacom = container_of(psy, struct wacom, battery); + struct wacom_battery *battery = container_of(psy, struct wacom_battery, battery); #endif int ret = 0; switch (psp) { case POWER_SUPPLY_PROP_PRESENT: - val->intval = wacom->wacom_wac.bat_connected; + val->intval = battery->bat_connected; break; case POWER_SUPPLY_PROP_SCOPE: val->intval = POWER_SUPPLY_SCOPE_DEVICE; break; case POWER_SUPPLY_PROP_CAPACITY: - val->intval = - wacom->wacom_wac.battery_capacity; + val->intval = battery->battery_capacity; break; case POWER_SUPPLY_PROP_STATUS: - if (wacom->wacom_wac.bat_charging) + if (battery->bat_charging) val->intval = POWER_SUPPLY_STATUS_CHARGING; - else if (wacom->wacom_wac.battery_capacity == 100 && - wacom->wacom_wac.ps_connected) + else if (battery->battery_capacity == 100 && + battery->ps_connected) val->intval = POWER_SUPPLY_STATUS_FULL; - else if (wacom->wacom_wac.ps_connected) + else if (battery->ps_connected) val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; else val->intval = POWER_SUPPLY_STATUS_DISCHARGING; @@ -1159,9 +1158,9 @@ static int wacom_ac_get_property(struct power_supply *psy, union power_supply_propval *val) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,1,0) - struct wacom *wacom = power_supply_get_drvdata(psy); + struct wacom_battery *battery = power_supply_get_drvdata(psy); #else - struct wacom *wacom = container_of(psy, struct wacom, ac); + struct wacom_battery *battery = container_of(psy, struct wacom_battery, battery); #endif int ret = 0; @@ -1169,7 +1168,7 @@ static int wacom_ac_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_PRESENT: /* fall through */ case POWER_SUPPLY_PROP_ONLINE: - val->intval = wacom->wacom_wac.ps_connected; + val->intval = battery->ps_connected; break; case POWER_SUPPLY_PROP_SCOPE: val->intval = POWER_SUPPLY_SCOPE_DEVICE; @@ -1181,101 +1180,132 @@ static int wacom_ac_get_property(struct power_supply *psy, return ret; } -static int wacom_initialize_battery(struct wacom *wacom) +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,1,0) +static int __wacom_initialize_battery(struct wacom *wacom, + struct wacom_battery *battery) { static atomic_t battery_no = ATOMIC_INIT(0); struct device *dev = &wacom->hdev->dev; int error; unsigned long n; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,1,0) - struct power_supply_config psy_cfg = { .drv_data = wacom, }; - struct power_supply_desc *bat_desc = &WACOM_POWERSUPPLY_DESC(wacom->battery); - if (!devres_open_group(dev, bat_desc, GFP_KERNEL)) - return -ENOMEM; -#endif + n = atomic_inc_return(&battery_no) - 1; - if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_BATTERY) { - n = atomic_inc_return(&battery_no) - 1; - - WACOM_POWERSUPPLY_DESC(wacom->battery).properties = wacom_battery_props; - WACOM_POWERSUPPLY_DESC(wacom->battery).num_properties = ARRAY_SIZE(wacom_battery_props); - WACOM_POWERSUPPLY_DESC(wacom->battery).get_property = wacom_battery_get_property; - sprintf(wacom->wacom_wac.bat_name, "wacom_battery_%ld", n); - WACOM_POWERSUPPLY_DESC(wacom->battery).name = wacom->wacom_wac.bat_name; - WACOM_POWERSUPPLY_DESC(wacom->battery).type = POWER_SUPPLY_TYPE_BATTERY; - WACOM_POWERSUPPLY_DESC(wacom->battery).use_for_apm = 0; - - WACOM_POWERSUPPLY_DESC(wacom->ac).properties = wacom_ac_props; - WACOM_POWERSUPPLY_DESC(wacom->ac).num_properties = ARRAY_SIZE(wacom_ac_props); - WACOM_POWERSUPPLY_DESC(wacom->ac).get_property = wacom_ac_get_property; - sprintf(wacom->wacom_wac.ac_name, "wacom_ac_%ld", n); - WACOM_POWERSUPPLY_DESC(wacom->ac).name = wacom->wacom_wac.ac_name; - WACOM_POWERSUPPLY_DESC(wacom->battery).type = POWER_SUPPLY_TYPE_MAINS; - WACOM_POWERSUPPLY_DESC(wacom->battery).use_for_apm = 0; + battery->battery.properties = wacom_battery_props; + battery->battery.num_properties = ARRAY_SIZE(wacom_battery_props); + battery->battery.get_property = wacom_battery_get_property; + sprintf(wacom->battery.bat_name, "wacom_battery_%ld", n); + battery->battery.name = wacom->battery.bat_name; + battery->battery.type = POWER_SUPPLY_TYPE_BATTERY; + battery->battery.use_for_apm = 0; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,1,0) - wacom->battery = devm_power_supply_register(dev, - &WACOM_POWERSUPPLY_DESC(wacom->battery), - &psy_cfg); - if (IS_ERR(wacom->battery)) { - error = PTR_ERR(wacom->battery); - goto err; - } -#else - error = power_supply_register(dev, - &wacom->battery); + battery->ac.properties = wacom_ac_props; + battery->ac.num_properties = ARRAY_SIZE(wacom_ac_props); + battery->ac.get_property = wacom_ac_get_property; + sprintf(wacom->battery.ac_name, "wacom_ac_%ld", n); + battery->ac.name = wacom->battery.ac_name; + battery->ac.type = POWER_SUPPLY_TYPE_MAINS; + battery->ac.use_for_apm = 0; - if (error) - return error; -#endif + error = power_supply_register(dev, &battery->battery); + + if (error) + return error; - power_supply_powers(WACOM_POWERSUPPLY_REF(wacom->battery), dev); + power_supply_powers(WACOM_POWERSUPPLY_REF(battery->battery), dev); + + error = power_supply_register(dev, &battery->ac); + + if (error) { + power_supply_unregister(&battery->battery); + return error; + } + + power_supply_powers(WACOM_POWERSUPPLY_REF(battery->ac), dev); + + return 0; +} -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,1,0) - wacom->ac = devm_power_supply_register(dev, - &WACOM_POWERSUPPLY_DESC(wacom->battery), - &psy_cfg); - if (IS_ERR(wacom->ac)) { - error = PTR_ERR(wacom->ac); - goto err; - } #else - error = power_supply_register(dev, &wacom->ac); +static int __wacom_initialize_battery(struct wacom *wacom, + struct wacom_battery *battery) +{ + static atomic_t battery_no = ATOMIC_INIT(0); + struct device *dev = &wacom->hdev->dev; + struct power_supply_config psy_cfg = { .drv_data = battery, }; + struct power_supply *ps_bat, *ps_ac; + struct power_supply_desc *bat_desc = &battery->bat_desc; + struct power_supply_desc *ac_desc = &battery->ac_desc; + unsigned long n; + int error; - if (error) { - power_supply_unregister(&wacom->battery); - return error; - } -#endif - power_supply_powers(WACOM_POWERSUPPLY_REF(wacom->ac), dev); + if (!devres_open_group(dev, bat_desc, GFP_KERNEL)) + return -ENOMEM; + + n = atomic_inc_return(&battery_no) - 1; + + bat_desc->properties = wacom_battery_props; + bat_desc->num_properties = ARRAY_SIZE(wacom_battery_props); + bat_desc->get_property = wacom_battery_get_property; + sprintf(battery->bat_name, "wacom_battery_%ld", n); + bat_desc->name = battery->bat_name; + bat_desc->type = POWER_SUPPLY_TYPE_BATTERY; + bat_desc->use_for_apm = 0; + + ac_desc->properties = wacom_ac_props; + ac_desc->num_properties = ARRAY_SIZE(wacom_ac_props); + ac_desc->get_property = wacom_ac_get_property; + sprintf(battery->ac_name, "wacom_ac_%ld", n); + ac_desc->name = battery->ac_name; + ac_desc->type = POWER_SUPPLY_TYPE_MAINS; + ac_desc->use_for_apm = 0; + + ps_bat = devm_power_supply_register(dev, bat_desc, &psy_cfg); + if (IS_ERR(ps_bat)) { + error = PTR_ERR(ps_bat); + goto err; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,1,0) - devres_close_group(dev, bat_desc); -#endif + ps_ac = devm_power_supply_register(dev, ac_desc, &psy_cfg); + if (IS_ERR(ps_ac)) { + error = PTR_ERR(ps_ac); + goto err; + } + + power_supply_powers(ps_bat, &wacom->hdev->dev); + power_supply_powers(ps_ac, &wacom->hdev->dev); + battery->battery = ps_bat; + battery->ac = ps_ac; + + devres_close_group(dev, bat_desc); return 0; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,1,0) err: devres_release_group(dev, bat_desc); return error; +} #endif + +static int wacom_initialize_battery(struct wacom *wacom) +{ + if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_BATTERY) + return __wacom_initialize_battery(wacom, &wacom->battery); + + return 0; } static void wacom_destroy_battery(struct wacom *wacom) { - if (WACOM_POWERSUPPLY_DEVICE(wacom->battery)) { - + if (WACOM_POWERSUPPLY_DEVICE(wacom->battery.battery)) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,1,0) - devres_release_group(&wacom->hdev->dev, WACOM_POWERSUPPLY_DEVICE(wacom->battery)); + devres_release_group(&wacom->hdev->dev, wacom->battery.battery); #else - power_supply_unregister(WACOM_POWERSUPPLY_REF(wacom->battery)); - power_supply_unregister(WACOM_POWERSUPPLY_REF(wacom->ac)); + power_supply_unregister(&wacom->battery.battery); + power_supply_unregister(&wacom->battery.ac); #endif - WACOM_POWERSUPPLY_DEVICE(wacom->battery) = NULL; - WACOM_POWERSUPPLY_DEVICE(wacom->ac) = NULL; + WACOM_POWERSUPPLY_DEVICE(wacom->battery.battery) = NULL; + WACOM_POWERSUPPLY_DEVICE(wacom->battery.ac) = NULL; } } @@ -1439,9 +1469,28 @@ static void wacom_remotes_destroy(void *data) struct wacom *wacom = data; struct wacom_remote *remote = wacom->remote; +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,1,0) + int i; + unsigned long flags; +#endif + if (!remote) return; +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,1,0) + for (i = 0; i < WACOM_MAX_REMOTES; i++) { + if (remote->remotes[i].registered) { + spin_lock_irqsave(&remote->remote_lock, flags); + remote->remotes[i].registered = false; + spin_unlock_irqrestore(&remote->remote_lock, flags); + + if (WACOM_POWERSUPPLY_DEVICE(remote->remotes[i].battery.battery)) { + power_supply_unregister(&remote->remotes[i].battery.battery); + power_supply_unregister(&remote->remotes[i].battery.ac); + } + } + } +#endif kobject_put(remote->remote_dir); kfifo_free(&remote->remote_fifo); wacom->remote = NULL; @@ -1645,11 +1694,11 @@ void wacom_battery_work(struct work_struct *work) struct wacom *wacom = container_of(work, struct wacom, battery_work); if ((wacom->wacom_wac.features.quirks & WACOM_QUIRK_BATTERY) && - !WACOM_POWERSUPPLY_DEVICE(wacom->battery)) { + !WACOM_POWERSUPPLY_DEVICE(wacom->battery.battery)) { wacom_initialize_battery(wacom); } else if (!(wacom->wacom_wac.features.quirks & WACOM_QUIRK_BATTERY) && - WACOM_POWERSUPPLY_DEVICE(wacom->battery)) { + WACOM_POWERSUPPLY_DEVICE(wacom->battery.battery)) { wacom_destroy_battery(wacom); } } @@ -2047,6 +2096,11 @@ static int wacom_remote_create_one(struct wacom *wacom, u32 serial, if (error) goto fail; + error = __wacom_initialize_battery(wacom, + &remote->remotes[index].battery); + if (error) + goto fail; + remote->remotes[index].registered = true; devres_close_group(dev, &remote->remotes[index]); diff --git a/3.17/wacom_wac.c b/3.17/wacom_wac.c index 4cfd4dd..b2f3d6b 100644 --- a/3.17/wacom_wac.c +++ b/3.17/wacom_wac.c @@ -52,25 +52,34 @@ static unsigned short batcap_gr[8] = { 1, 15, 25, 35, 50, 70, 100, 100 }; */ static unsigned short batcap_i4[8] = { 1, 15, 30, 45, 60, 70, 85, 100 }; +static void __wacom_notify_battery(struct wacom_battery *battery, + int bat_capacity, bool bat_charging, + bool bat_connected, bool ps_connected) +{ + bool changed = battery->battery_capacity != bat_capacity || + battery->bat_charging != bat_charging || + battery->bat_connected != bat_connected || + battery->ps_connected != ps_connected; + + if (changed) { + battery->battery_capacity = bat_capacity; + battery->bat_charging = bat_charging; + battery->bat_connected = bat_connected; + battery->ps_connected = ps_connected; + + if (WACOM_POWERSUPPLY_DEVICE(battery->battery)) + power_supply_changed(WACOM_POWERSUPPLY_REF(battery->battery)); + } +} + static void wacom_notify_battery(struct wacom_wac *wacom_wac, int bat_capacity, bool bat_charging, bool bat_connected, bool ps_connected) { struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac); - bool changed = wacom_wac->battery_capacity != bat_capacity || - wacom_wac->bat_charging != bat_charging || - wacom_wac->bat_connected != bat_connected || - wacom_wac->ps_connected != ps_connected; - if (changed) { - wacom_wac->battery_capacity = bat_capacity; - wacom_wac->bat_charging = bat_charging; - wacom_wac->bat_connected = bat_connected; - wacom_wac->ps_connected = ps_connected; - - if (WACOM_POWERSUPPLY_DEVICE(wacom->battery)) - power_supply_changed(WACOM_POWERSUPPLY_REF(wacom->battery)); - } + __wacom_notify_battery(&wacom->battery, bat_capacity, bat_charging, + bat_connected, ps_connected); } static int wacom_penpartner_irq(struct wacom_wac *wacom) @@ -760,7 +769,6 @@ static int wacom_remote_irq(struct wacom_wac *wacom_wac, size_t len) struct input_dev *input; struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac); struct wacom_remote *remote = wacom->remote; - struct wacom_features *features = &wacom_wac->features; int bat_charging, bat_percent, touch_ring_mode; __u32 serial; int i, index = -1; @@ -835,14 +843,9 @@ static int wacom_remote_irq(struct wacom_wac *wacom_wac, size_t len) wacom->led.groups[i].select = touch_ring_mode; } - if (!WACOM_POWERSUPPLY_DEVICE(wacom->battery) && - !(features->quirks & WACOM_QUIRK_BATTERY)) { - features->quirks |= WACOM_QUIRK_BATTERY; - wacom_schedule_work(wacom_wac, WACOM_WORKER_BATTERY); - } + __wacom_notify_battery(&remote->remotes[index].battery, bat_percent, + bat_charging, 1, bat_charging); - wacom_notify_battery(wacom_wac, bat_percent, bat_charging, 1, - bat_charging); out: spin_unlock_irqrestore(&remote->remote_lock, flags); @@ -2139,7 +2142,6 @@ static int wacom_bamboo_pad_irq(struct wacom_wac *wacom, size_t len) static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len) { - struct wacom *w = container_of(wacom, struct wacom, wacom_wac); unsigned char *data = wacom->data; int connected; @@ -2167,8 +2169,7 @@ static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len) wacom_schedule_work(wacom, WACOM_WORKER_WIRELESS); } - if (WACOM_POWERSUPPLY_DEVICE(w->battery)) - wacom_notify_battery(wacom, battery, charging, 1, 0); + wacom_notify_battery(wacom, battery, charging, 1, 0); } else if (wacom->pid != 0) { /* disconnected while previously connected */ @@ -2205,14 +2206,14 @@ static int wacom_status_irq(struct wacom_wac *wacom_wac, size_t len) wacom_notify_battery(wacom_wac, battery, charging, battery || charging, 1); - if (!WACOM_POWERSUPPLY_DEVICE(wacom->battery) && + if (!WACOM_POWERSUPPLY_DEVICE(wacom->battery.battery) && !(features->quirks & WACOM_QUIRK_BATTERY)) { features->quirks |= WACOM_QUIRK_BATTERY; wacom_schedule_work(wacom_wac, WACOM_WORKER_BATTERY); } } else if ((features->quirks & WACOM_QUIRK_BATTERY) && - WACOM_POWERSUPPLY_DEVICE(wacom->battery)) { + WACOM_POWERSUPPLY_DEVICE(wacom->battery.battery)) { features->quirks &= ~WACOM_QUIRK_BATTERY; wacom_schedule_work(wacom_wac, WACOM_WORKER_BATTERY); wacom_notify_battery(wacom_wac, 0, 0, 0, 0); diff --git a/3.17/wacom_wac.h b/3.17/wacom_wac.h index b3c1a09..84e94ce 100644 --- a/3.17/wacom_wac.h +++ b/3.17/wacom_wac.h @@ -229,8 +229,6 @@ struct wacom_wac { char pen_name[WACOM_NAME_MAX]; char touch_name[WACOM_NAME_MAX]; char pad_name[WACOM_NAME_MAX]; - char bat_name[WACOM_NAME_MAX]; - char ac_name[WACOM_NAME_MAX]; unsigned char data[WACOM_PKGLEN_MAX]; int tool[2]; int id[2]; @@ -242,11 +240,7 @@ struct wacom_wac { struct input_dev *touch_input; struct input_dev *pad_input; int pid; - int battery_capacity; int num_contacts_left; - int bat_charging; - int bat_connected; - int ps_connected; u8 bt_features; u8 bt_high_speed; int mode_report; diff --git a/3.7/wacom.h b/3.7/wacom.h index 1183cbb..c6fc12c 100644 --- a/3.7/wacom.h +++ b/3.7/wacom.h @@ -115,6 +115,17 @@ enum wacom_worker { WACOM_WORKER_REMOTE, }; +struct wacom_battery { + struct power_supply battery; + struct power_supply ac; + char bat_name[WACOM_NAME_MAX]; + char ac_name[WACOM_NAME_MAX]; + int battery_capacity; + int bat_charging; + int bat_connected; + int ps_connected; +}; + struct wacom_remote { spinlock_t remote_lock; struct kfifo remote_fifo; @@ -124,6 +135,7 @@ struct wacom_remote { u32 serial; struct input_dev *input; bool registered; + struct wacom_battery battery; } remotes[WACOM_MAX_REMOTES]; }; @@ -146,7 +158,7 @@ struct wacom { u8 hlv; /* status led brightness button pressed (1..127) */ u8 img_lum; /* OLED matrix display brightness */ } led; - struct power_supply battery; + struct wacom_battery battery; }; static inline void wacom_schedule_work(struct wacom_wac *wacom_wac, diff --git a/3.7/wacom_sys.c b/3.7/wacom_sys.c index 3801468..0094ff5 100644 --- a/3.7/wacom_sys.c +++ b/3.7/wacom_sys.c @@ -1156,27 +1156,28 @@ static int wacom_battery_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) { - struct wacom *wacom = container_of(psy, struct wacom, battery); + struct wacom_battery *battery = container_of(psy, struct wacom_battery, + battery); + int ret = 0; switch (psp) { case POWER_SUPPLY_PROP_PRESENT: - val->intval = wacom->wacom_wac.bat_connected; + val->intval = battery->bat_connected; break; case POWER_SUPPLY_PROP_SCOPE: val->intval = POWER_SUPPLY_SCOPE_DEVICE; break; case POWER_SUPPLY_PROP_CAPACITY: - val->intval = - wacom->wacom_wac.battery_capacity; + val->intval = battery->battery_capacity; break; case POWER_SUPPLY_PROP_STATUS: - if (wacom->wacom_wac.bat_charging) + if (battery->bat_charging) val->intval = POWER_SUPPLY_STATUS_CHARGING; - else if (wacom->wacom_wac.battery_capacity == 100 && - wacom->wacom_wac.ps_connected) + else if (battery->battery_capacity == 100 && + battery->ps_connected) val->intval = POWER_SUPPLY_STATUS_FULL; - else if (wacom->wacom_wac.ps_connected) + else if (battery->ps_connected) val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; else val->intval = POWER_SUPPLY_STATUS_DISCHARGING; @@ -1189,46 +1190,64 @@ static int wacom_battery_get_property(struct power_supply *psy, return ret; } -static int wacom_initialize_battery(struct wacom *wacom) +static int __wacom_initialize_battery(struct wacom *wacom, + struct wacom_battery *battery) { static atomic_t battery_no = ATOMIC_INIT(0); static DEFINE_SPINLOCK(ps_lock); unsigned long flags; int error = 0; + unsigned long n; spin_lock_irqsave(&ps_lock, flags); /* Prevent potential race for the "wacom_battery" name */ - if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_BATTERY) { - unsigned long n = atomic_inc_return(&battery_no) - 1; - - if (power_supply_get_by_name("wacom_battery")) - sprintf(wacom->wacom_wac.bat_name, "wacom_battery_%ld", n); - else - sprintf(wacom->wacom_wac.bat_name, "wacom_battery"); - - wacom->battery.properties = wacom_battery_props; - wacom->battery.num_properties = ARRAY_SIZE(wacom_battery_props); - wacom->battery.get_property = wacom_battery_get_property; - wacom->battery.name = wacom->wacom_wac.bat_name; - wacom->battery.type = POWER_SUPPLY_TYPE_BATTERY; - wacom->battery.use_for_apm = 0; - - error = power_supply_register(&wacom->usbdev->dev, - &wacom->battery); - - if (!error) - power_supply_powers(&wacom->battery, - &wacom->usbdev->dev); - } + + n = atomic_inc_return(&battery_no) - 1; + + if (power_supply_get_by_name("wacom_battery")) + sprintf(battery->bat_name, "wacom_battery_%ld", n); + else + sprintf(battery->bat_name, "wacom_battery"); + + battery->battery.properties = wacom_battery_props; + battery->battery.num_properties = ARRAY_SIZE(wacom_battery_props); + battery->battery.get_property = wacom_battery_get_property; + battery->battery.name = battery->bat_name; + battery->battery.type = POWER_SUPPLY_TYPE_BATTERY; + battery->battery.use_for_apm = 0; + + error = power_supply_register(&wacom->usbdev->dev, + &battery->battery); + + if (!error) + power_supply_powers(&battery->battery, + &wacom->usbdev->dev); + spin_unlock_irqrestore(&ps_lock, flags); return error; } +static int wacom_initialize_battery(struct wacom *wacom) +{ + if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_BATTERY) + return __wacom_initialize_battery(wacom, &wacom->battery); + + return 0; +} + static void wacom_destroy_battery(struct wacom *wacom) { - if (wacom->battery.dev) { - power_supply_unregister(&wacom->battery); - wacom->battery.dev = NULL; + if (wacom->battery.battery.dev) { + power_supply_unregister(&wacom->battery.battery); + wacom->battery.battery.dev = NULL; + } +} + +static void wacom_destroy_remote_battery(struct wacom_battery *battery) +{ + if (battery->battery.dev) { + power_supply_unregister(&battery->battery); + battery->battery.dev = NULL; } } @@ -1333,6 +1352,9 @@ static void wacom_remote_destroy_one(struct wacom *wacom, unsigned int index) if (remote->remotes[index].input) input_unregister_device(remote->remotes[index].input); + if (remote->remotes[index].battery.battery.dev) + wacom_destroy_remote_battery(&remote->remotes[index].battery); + for (i = 0; i < WACOM_MAX_REMOTES; i++) { if (remote->remotes[i].serial == serial) { remote->remotes[i].serial = 0; @@ -1392,7 +1414,7 @@ static void wacom_remotes_destroy(struct wacom *wacom) return; for (i = 0; i < WACOM_MAX_REMOTES; i++) { - if (wacom->remote->remotes[i].group.name) { + if (remote->remotes[i].registered) { wacom_remote_destroy_one(wacom, i); } } @@ -1600,6 +1622,11 @@ static int wacom_remote_create_one(struct wacom *wacom, u32 serial, remote->remotes[index].registered = true; + error = __wacom_initialize_battery(wacom, + &remote->remotes[index].battery); + if (error) + goto fail; + devres_close_group(dev, &remote->remotes[index]); return 0; @@ -1758,11 +1785,11 @@ void wacom_battery_work(struct work_struct *work) struct wacom *wacom = container_of(work, struct wacom, battery_work); if ((wacom->wacom_wac.features.quirks & WACOM_QUIRK_BATTERY) && - !wacom->battery.dev) { + !wacom->battery.battery.dev) { wacom_initialize_battery(wacom); } else if (!(wacom->wacom_wac.features.quirks & WACOM_QUIRK_BATTERY) && - wacom->battery.dev) { + wacom->battery.battery.dev) { wacom_destroy_battery(wacom); } } diff --git a/3.7/wacom_wac.c b/3.7/wacom_wac.c index 252e871..ed8cedb 100644 --- a/3.7/wacom_wac.c +++ b/3.7/wacom_wac.c @@ -41,27 +41,36 @@ static void wacom_report_numbered_buttons(struct input_dev *input_dev, int button_cout, int mask); -static void wacom_notify_battery(struct wacom_wac *wacom_wac, +static void __wacom_notify_battery(struct wacom_battery *battery, int bat_capacity, bool bat_charging, bool bat_connected, bool ps_connected) { - struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac); - bool changed = wacom_wac->battery_capacity != bat_capacity || - wacom_wac->bat_charging != bat_charging || - wacom_wac->bat_connected != bat_connected || - wacom_wac->ps_connected != ps_connected; + bool changed = battery->battery_capacity != bat_capacity || + battery->bat_charging != bat_charging || + battery->bat_connected != bat_connected || + battery->ps_connected != ps_connected; if (changed) { - wacom_wac->battery_capacity = bat_capacity; - wacom_wac->bat_charging = bat_charging; - wacom_wac->bat_connected = bat_connected; - wacom_wac->ps_connected = ps_connected; + battery->battery_capacity = bat_capacity; + battery->bat_charging = bat_charging; + battery->bat_connected = bat_connected; + battery->ps_connected = ps_connected; - if (wacom->battery.dev) - power_supply_changed(&wacom->battery); + if (battery->battery.dev) + power_supply_changed(&battery->battery); } } +static void wacom_notify_battery(struct wacom_wac *wacom_wac, + int bat_capacity, bool bat_charging, bool bat_connected, + bool ps_connected) +{ + struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac); + + __wacom_notify_battery(&wacom->battery, bat_capacity, bat_charging, + bat_connected, ps_connected); +} + static int wacom_penpartner_irq(struct wacom_wac *wacom) { unsigned char *data = wacom->data; @@ -701,7 +710,6 @@ static int wacom_remote_irq(struct wacom_wac *wacom_wac, size_t len) { unsigned char *data = wacom_wac->data; struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac); - struct wacom_features *features = &wacom_wac->features; struct wacom_remote *remote = wacom->remote; struct input_dev *input; int bat_charging, bat_percent, touch_ring_mode; @@ -778,14 +786,8 @@ static int wacom_remote_irq(struct wacom_wac *wacom_wac, size_t len) wacom->led.select[i] = touch_ring_mode; } - if (!wacom->battery.dev && - !(features->quirks & WACOM_QUIRK_BATTERY)) { - features->quirks |= WACOM_QUIRK_BATTERY; - wacom_schedule_work(wacom_wac, WACOM_WORKER_BATTERY); - } - - wacom_notify_battery(wacom_wac, bat_percent, bat_charging, 1, - bat_charging); + __wacom_notify_battery(&remote->remotes[index].battery, bat_percent, + bat_charging, 1, bat_charging); out: spin_unlock_irqrestore(&remote->remote_lock, flags); @@ -1537,7 +1539,6 @@ static int wacom_bpt_irq(struct wacom_wac *wacom, size_t len) static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len) { - struct wacom *w = container_of(wacom, struct wacom, wacom_wac); unsigned char *data = wacom->data; int connected; @@ -1565,8 +1566,7 @@ static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len) wacom_schedule_work(wacom, WACOM_WORKER_WIRELESS); } - if (w->battery.dev) - wacom_notify_battery(wacom, battery, charging, 1, 0); + wacom_notify_battery(wacom, battery, charging, 1, 0); } else if (wacom->pid != 0) { /* disconnected while previously connected */ @@ -1603,14 +1603,14 @@ static int wacom_status_irq(struct wacom_wac *wacom_wac, size_t len) wacom_notify_battery(wacom_wac, battery, charging, battery || charging, 1); - if (!wacom->battery.dev && + if (!wacom->battery.battery.dev && !(features->quirks & WACOM_QUIRK_BATTERY)) { features->quirks |= WACOM_QUIRK_BATTERY; wacom_schedule_work(wacom_wac, WACOM_WORKER_BATTERY); } } else if ((features->quirks & WACOM_QUIRK_BATTERY) && - wacom->battery.dev) { + wacom->battery.battery.dev) { features->quirks &= ~WACOM_QUIRK_BATTERY; wacom_schedule_work(wacom_wac, WACOM_WORKER_BATTERY); wacom_notify_battery(wacom_wac, 0, 0, 0, 0); @@ -1835,9 +1835,8 @@ void wacom_setup_device_quirks(struct wacom *wacom) } } - if (features->type == REMOTE) { + if (features->type == REMOTE) features->quirks |= WACOM_QUIRK_MONITOR; - } } static void wacom_abs_set_axis(struct input_dev *input_dev, diff --git a/3.7/wacom_wac.h b/3.7/wacom_wac.h index 7e12b8b..25a9ac5 100644 --- a/3.7/wacom_wac.h +++ b/3.7/wacom_wac.h @@ -174,7 +174,6 @@ struct wacom_remote_data { struct wacom_wac { char name[WACOM_NAME_MAX]; - char bat_name[WACOM_NAME_MAX]; unsigned char *data; int tool[2]; int id[2]; @@ -184,11 +183,7 @@ struct wacom_wac { struct wacom_shared *shared; struct input_dev *input; int pid; - int battery_capacity; int num_contacts_left; - int bat_charging; - int bat_connected; - int ps_connected; }; #endif -- 2.7.4 ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, SlashDot.org! http://sdm.link/slashdot _______________________________________________ Linuxwacom-devel mailing list Linuxwacom-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxwacom-devel