1135 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.4 *5 * HID driver for NVIDIA SHIELD peripherals.6 */7 8#include <linux/hid.h>9#include <linux/idr.h>10#include <linux/input-event-codes.h>11#include <linux/input.h>12#include <linux/jiffies.h>13#include <linux/leds.h>14#include <linux/module.h>15#include <linux/power_supply.h>16#include <linux/spinlock.h>17#include <linux/timer.h>18#include <linux/workqueue.h>19 20#include "hid-ids.h"21 22#define NOT_INIT_STR "NOT INITIALIZED"23#define android_map_key(c) hid_map_usage(hi, usage, bit, max, EV_KEY, (c))24 25enum {26 HID_USAGE_ANDROID_PLAYPAUSE_BTN = 0xcd, /* Double-tap volume slider */27 HID_USAGE_ANDROID_VOLUMEUP_BTN = 0xe9,28 HID_USAGE_ANDROID_VOLUMEDOWN_BTN = 0xea,29 HID_USAGE_ANDROID_SEARCH_BTN = 0x221, /* NVIDIA btn on Thunderstrike */30 HID_USAGE_ANDROID_HOME_BTN = 0x223,31 HID_USAGE_ANDROID_BACK_BTN = 0x224,32};33 34enum {35 SHIELD_FW_VERSION_INITIALIZED = 0,36 SHIELD_BOARD_INFO_INITIALIZED,37 SHIELD_BATTERY_STATS_INITIALIZED,38 SHIELD_CHARGER_STATE_INITIALIZED,39};40 41enum {42 THUNDERSTRIKE_FW_VERSION_UPDATE = 0,43 THUNDERSTRIKE_BOARD_INFO_UPDATE,44 THUNDERSTRIKE_HAPTICS_UPDATE,45 THUNDERSTRIKE_LED_UPDATE,46 THUNDERSTRIKE_POWER_SUPPLY_STATS_UPDATE,47};48 49enum {50 THUNDERSTRIKE_HOSTCMD_REPORT_SIZE = 33,51 THUNDERSTRIKE_HOSTCMD_REQ_REPORT_ID = 0x4,52 THUNDERSTRIKE_HOSTCMD_RESP_REPORT_ID = 0x3,53};54 55enum {56 THUNDERSTRIKE_HOSTCMD_ID_FW_VERSION = 1,57 THUNDERSTRIKE_HOSTCMD_ID_LED = 6,58 THUNDERSTRIKE_HOSTCMD_ID_BATTERY,59 THUNDERSTRIKE_HOSTCMD_ID_BOARD_INFO = 16,60 THUNDERSTRIKE_HOSTCMD_ID_USB_INIT = 53,61 THUNDERSTRIKE_HOSTCMD_ID_HAPTICS = 57,62 THUNDERSTRIKE_HOSTCMD_ID_CHARGER,63};64 65struct power_supply_dev {66 struct power_supply *psy;67 struct power_supply_desc desc;68};69 70struct thunderstrike_psy_prop_values {71 int voltage_min;72 int voltage_now;73 int voltage_avg;74 int voltage_boot;75 int capacity;76 int status;77 int charge_type;78 int temp;79};80 81static const enum power_supply_property thunderstrike_battery_props[] = {82 POWER_SUPPLY_PROP_STATUS,83 POWER_SUPPLY_PROP_CHARGE_TYPE,84 POWER_SUPPLY_PROP_PRESENT,85 POWER_SUPPLY_PROP_VOLTAGE_MIN,86 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,87 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,88 POWER_SUPPLY_PROP_VOLTAGE_NOW,89 POWER_SUPPLY_PROP_VOLTAGE_AVG,90 POWER_SUPPLY_PROP_VOLTAGE_BOOT,91 POWER_SUPPLY_PROP_CAPACITY,92 POWER_SUPPLY_PROP_SCOPE,93 POWER_SUPPLY_PROP_TEMP,94 POWER_SUPPLY_PROP_TEMP_MIN,95 POWER_SUPPLY_PROP_TEMP_MAX,96 POWER_SUPPLY_PROP_TEMP_ALERT_MIN,97 POWER_SUPPLY_PROP_TEMP_ALERT_MAX,98};99 100enum thunderstrike_led_state {101 THUNDERSTRIKE_LED_OFF = 1,102 THUNDERSTRIKE_LED_ON = 8,103} __packed;104static_assert(sizeof(enum thunderstrike_led_state) == 1);105 106struct thunderstrike_hostcmd_battery {107 __le16 voltage_avg;108 u8 reserved_at_10;109 __le16 thermistor;110 __le16 voltage_min;111 __le16 voltage_boot;112 __le16 voltage_now;113 u8 capacity;114} __packed;115 116enum thunderstrike_charger_type {117 THUNDERSTRIKE_CHARGER_TYPE_NONE = 0,118 THUNDERSTRIKE_CHARGER_TYPE_TRICKLE,119 THUNDERSTRIKE_CHARGER_TYPE_NORMAL,120} __packed;121static_assert(sizeof(enum thunderstrike_charger_type) == 1);122 123enum thunderstrike_charger_state {124 THUNDERSTRIKE_CHARGER_STATE_UNKNOWN = 0,125 THUNDERSTRIKE_CHARGER_STATE_DISABLED,126 THUNDERSTRIKE_CHARGER_STATE_CHARGING,127 THUNDERSTRIKE_CHARGER_STATE_FULL,128 THUNDERSTRIKE_CHARGER_STATE_FAILED = 8,129} __packed;130static_assert(sizeof(enum thunderstrike_charger_state) == 1);131 132struct thunderstrike_hostcmd_charger {133 u8 connected;134 enum thunderstrike_charger_type type;135 enum thunderstrike_charger_state state;136} __packed;137 138struct thunderstrike_hostcmd_board_info {139 __le16 revision;140 __le16 serial[7];141} __packed;142 143struct thunderstrike_hostcmd_haptics {144 u8 motor_left;145 u8 motor_right;146} __packed;147 148struct thunderstrike_hostcmd_resp_report {149 u8 report_id; /* THUNDERSTRIKE_HOSTCMD_RESP_REPORT_ID */150 u8 cmd_id;151 u8 reserved_at_10;152 153 union {154 struct thunderstrike_hostcmd_board_info board_info;155 struct thunderstrike_hostcmd_haptics motors;156 __le16 fw_version;157 enum thunderstrike_led_state led_state;158 struct thunderstrike_hostcmd_battery battery;159 struct thunderstrike_hostcmd_charger charger;160 u8 payload[30];161 } __packed;162} __packed;163static_assert(sizeof(struct thunderstrike_hostcmd_resp_report) ==164 THUNDERSTRIKE_HOSTCMD_REPORT_SIZE);165 166struct thunderstrike_hostcmd_req_report {167 u8 report_id; /* THUNDERSTRIKE_HOSTCMD_REQ_REPORT_ID */168 u8 cmd_id;169 u8 reserved_at_10;170 171 union {172 struct __packed {173 u8 update;174 enum thunderstrike_led_state state;175 } led;176 struct __packed {177 u8 update;178 struct thunderstrike_hostcmd_haptics motors;179 } haptics;180 } __packed;181 u8 reserved_at_30[27];182} __packed;183static_assert(sizeof(struct thunderstrike_hostcmd_req_report) ==184 THUNDERSTRIKE_HOSTCMD_REPORT_SIZE);185 186/* Common struct for shield accessories. */187struct shield_device {188 struct hid_device *hdev;189 struct power_supply_dev battery_dev;190 191 unsigned long initialized_flags;192 const char *codename;193 u16 fw_version;194 struct {195 u16 revision;196 char serial_number[15];197 } board_info;198};199 200/*201 * Non-trivial to uniquely identify Thunderstrike controllers at initialization202 * time. Use an ID allocator to help with this.203 */204static DEFINE_IDA(thunderstrike_ida);205 206struct thunderstrike {207 struct shield_device base;208 209 int id;210 211 /* Sub-devices */212 struct input_dev *haptics_dev;213 struct led_classdev led_dev;214 215 /* Resources */216 void *req_report_dmabuf;217 unsigned long update_flags;218 struct thunderstrike_hostcmd_haptics haptics_val;219 spinlock_t haptics_update_lock;220 u8 led_state : 1;221 enum thunderstrike_led_state led_value;222 struct thunderstrike_psy_prop_values psy_stats;223 spinlock_t psy_stats_lock;224 struct timer_list psy_stats_timer;225 struct work_struct hostcmd_req_work;226};227 228static inline void thunderstrike_hostcmd_req_report_init(229 struct thunderstrike_hostcmd_req_report *report, u8 cmd_id)230{231 memset(report, 0, sizeof(*report));232 report->report_id = THUNDERSTRIKE_HOSTCMD_REQ_REPORT_ID;233 report->cmd_id = cmd_id;234}235 236static inline void shield_strrev(char *dest, size_t len, u16 rev)237{238 dest[0] = ('A' - 1) + (rev >> 8);239 snprintf(&dest[1], len - 1, "%02X", 0xff & rev);240}241 242static struct input_dev *shield_allocate_input_dev(struct hid_device *hdev,243 const char *name_suffix)244{245 struct input_dev *idev;246 247 idev = input_allocate_device();248 if (!idev)249 goto err_device;250 251 idev->id.bustype = hdev->bus;252 idev->id.vendor = hdev->vendor;253 idev->id.product = hdev->product;254 idev->id.version = hdev->version;255 idev->uniq = hdev->uniq;256 idev->name = devm_kasprintf(&hdev->dev, GFP_KERNEL, "%s %s", hdev->name,257 name_suffix);258 if (!idev->name)259 goto err_name;260 261 input_set_drvdata(idev, hdev);262 263 return idev;264 265err_name:266 input_free_device(idev);267err_device:268 return ERR_PTR(-ENOMEM);269}270 271static struct input_dev *shield_haptics_create(272 struct shield_device *dev,273 int (*play_effect)(struct input_dev *, void *, struct ff_effect *))274{275 struct input_dev *haptics;276 int ret;277 278 if (!IS_ENABLED(CONFIG_NVIDIA_SHIELD_FF))279 return NULL;280 281 haptics = shield_allocate_input_dev(dev->hdev, "Haptics");282 if (IS_ERR(haptics))283 return haptics;284 285 input_set_capability(haptics, EV_FF, FF_RUMBLE);286 ret = input_ff_create_memless(haptics, NULL, play_effect);287 if (ret)288 goto err;289 290 ret = input_register_device(haptics);291 if (ret)292 goto err;293 294 return haptics;295 296err:297 input_free_device(haptics);298 return ERR_PTR(ret);299}300 301static inline void thunderstrike_send_hostcmd_request(struct thunderstrike *ts)302{303 struct thunderstrike_hostcmd_req_report *report = ts->req_report_dmabuf;304 struct shield_device *shield_dev = &ts->base;305 int ret;306 307 ret = hid_hw_raw_request(shield_dev->hdev, report->report_id,308 ts->req_report_dmabuf,309 THUNDERSTRIKE_HOSTCMD_REPORT_SIZE,310 HID_OUTPUT_REPORT, HID_REQ_SET_REPORT);311 312 if (ret < 0) {313 hid_err(shield_dev->hdev,314 "Failed to output Thunderstrike HOSTCMD request HID report due to %pe\n",315 ERR_PTR(ret));316 }317}318 319static void thunderstrike_hostcmd_req_work_handler(struct work_struct *work)320{321 struct thunderstrike *ts =322 container_of(work, struct thunderstrike, hostcmd_req_work);323 struct thunderstrike_hostcmd_req_report *report;324 unsigned long flags;325 326 report = ts->req_report_dmabuf;327 328 if (test_and_clear_bit(THUNDERSTRIKE_FW_VERSION_UPDATE, &ts->update_flags)) {329 thunderstrike_hostcmd_req_report_init(330 report, THUNDERSTRIKE_HOSTCMD_ID_FW_VERSION);331 thunderstrike_send_hostcmd_request(ts);332 }333 334 if (test_and_clear_bit(THUNDERSTRIKE_LED_UPDATE, &ts->update_flags)) {335 thunderstrike_hostcmd_req_report_init(report, THUNDERSTRIKE_HOSTCMD_ID_LED);336 report->led.update = 1;337 report->led.state = ts->led_value;338 thunderstrike_send_hostcmd_request(ts);339 }340 341 if (test_and_clear_bit(THUNDERSTRIKE_POWER_SUPPLY_STATS_UPDATE, &ts->update_flags)) {342 thunderstrike_hostcmd_req_report_init(343 report, THUNDERSTRIKE_HOSTCMD_ID_BATTERY);344 thunderstrike_send_hostcmd_request(ts);345 346 thunderstrike_hostcmd_req_report_init(347 report, THUNDERSTRIKE_HOSTCMD_ID_CHARGER);348 thunderstrike_send_hostcmd_request(ts);349 }350 351 if (test_and_clear_bit(THUNDERSTRIKE_BOARD_INFO_UPDATE, &ts->update_flags)) {352 thunderstrike_hostcmd_req_report_init(353 report, THUNDERSTRIKE_HOSTCMD_ID_BOARD_INFO);354 thunderstrike_send_hostcmd_request(ts);355 }356 357 if (test_and_clear_bit(THUNDERSTRIKE_HAPTICS_UPDATE, &ts->update_flags)) {358 thunderstrike_hostcmd_req_report_init(359 report, THUNDERSTRIKE_HOSTCMD_ID_HAPTICS);360 361 report->haptics.update = 1;362 spin_lock_irqsave(&ts->haptics_update_lock, flags);363 report->haptics.motors = ts->haptics_val;364 spin_unlock_irqrestore(&ts->haptics_update_lock, flags);365 366 thunderstrike_send_hostcmd_request(ts);367 }368}369 370static inline void thunderstrike_request_firmware_version(struct thunderstrike *ts)371{372 set_bit(THUNDERSTRIKE_FW_VERSION_UPDATE, &ts->update_flags);373 schedule_work(&ts->hostcmd_req_work);374}375 376static inline void thunderstrike_request_board_info(struct thunderstrike *ts)377{378 set_bit(THUNDERSTRIKE_BOARD_INFO_UPDATE, &ts->update_flags);379 schedule_work(&ts->hostcmd_req_work);380}381 382static inline int383thunderstrike_update_haptics(struct thunderstrike *ts,384 struct thunderstrike_hostcmd_haptics *motors)385{386 unsigned long flags;387 388 spin_lock_irqsave(&ts->haptics_update_lock, flags);389 ts->haptics_val = *motors;390 spin_unlock_irqrestore(&ts->haptics_update_lock, flags);391 392 set_bit(THUNDERSTRIKE_HAPTICS_UPDATE, &ts->update_flags);393 schedule_work(&ts->hostcmd_req_work);394 395 return 0;396}397 398static int thunderstrike_play_effect(struct input_dev *idev, void *data,399 struct ff_effect *effect)400{401 struct hid_device *hdev = input_get_drvdata(idev);402 struct thunderstrike_hostcmd_haptics motors;403 struct shield_device *shield_dev;404 struct thunderstrike *ts;405 406 if (effect->type != FF_RUMBLE)407 return 0;408 409 shield_dev = hid_get_drvdata(hdev);410 ts = container_of(shield_dev, struct thunderstrike, base);411 412 /* Thunderstrike motor values range from 0 to 32 inclusively */413 motors.motor_left = effect->u.rumble.strong_magnitude / 2047;414 motors.motor_right = effect->u.rumble.weak_magnitude / 2047;415 416 hid_dbg(hdev, "Thunderstrike FF_RUMBLE request, left: %u right: %u\n",417 motors.motor_left, motors.motor_right);418 419 return thunderstrike_update_haptics(ts, &motors);420}421 422static enum led_brightness423thunderstrike_led_get_brightness(struct led_classdev *led)424{425 struct hid_device *hdev = to_hid_device(led->dev->parent);426 struct shield_device *shield_dev = hid_get_drvdata(hdev);427 struct thunderstrike *ts;428 429 ts = container_of(shield_dev, struct thunderstrike, base);430 431 return ts->led_state;432}433 434static void thunderstrike_led_set_brightness(struct led_classdev *led,435 enum led_brightness value)436{437 struct hid_device *hdev = to_hid_device(led->dev->parent);438 struct shield_device *shield_dev = hid_get_drvdata(hdev);439 struct thunderstrike *ts;440 441 ts = container_of(shield_dev, struct thunderstrike, base);442 443 switch (value) {444 case LED_OFF:445 ts->led_value = THUNDERSTRIKE_LED_OFF;446 break;447 default:448 ts->led_value = THUNDERSTRIKE_LED_ON;449 break;450 }451 452 set_bit(THUNDERSTRIKE_LED_UPDATE, &ts->update_flags);453 schedule_work(&ts->hostcmd_req_work);454}455 456static int thunderstrike_battery_get_property(struct power_supply *psy,457 enum power_supply_property psp,458 union power_supply_propval *val)459{460 struct shield_device *shield_dev = power_supply_get_drvdata(psy);461 struct thunderstrike_psy_prop_values prop_values;462 struct thunderstrike *ts;463 int ret = 0;464 465 ts = container_of(shield_dev, struct thunderstrike, base);466 spin_lock(&ts->psy_stats_lock);467 prop_values = ts->psy_stats;468 spin_unlock(&ts->psy_stats_lock);469 470 switch (psp) {471 case POWER_SUPPLY_PROP_STATUS:472 val->intval = prop_values.status;473 break;474 case POWER_SUPPLY_PROP_CHARGE_TYPE:475 val->intval = prop_values.charge_type;476 break;477 case POWER_SUPPLY_PROP_PRESENT:478 val->intval = 1;479 break;480 case POWER_SUPPLY_PROP_VOLTAGE_MIN:481 val->intval = prop_values.voltage_min;482 break;483 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:484 val->intval = 2900000; /* 2.9 V */485 break;486 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:487 val->intval = 2200000; /* 2.2 V */488 break;489 case POWER_SUPPLY_PROP_VOLTAGE_NOW:490 val->intval = prop_values.voltage_now;491 break;492 case POWER_SUPPLY_PROP_VOLTAGE_AVG:493 val->intval = prop_values.voltage_avg;494 break;495 case POWER_SUPPLY_PROP_VOLTAGE_BOOT:496 val->intval = prop_values.voltage_boot;497 break;498 case POWER_SUPPLY_PROP_CAPACITY:499 val->intval = prop_values.capacity;500 break;501 case POWER_SUPPLY_PROP_SCOPE:502 val->intval = POWER_SUPPLY_SCOPE_DEVICE;503 break;504 case POWER_SUPPLY_PROP_TEMP:505 val->intval = prop_values.temp;506 break;507 case POWER_SUPPLY_PROP_TEMP_MIN:508 val->intval = 0; /* 0 C */509 break;510 case POWER_SUPPLY_PROP_TEMP_MAX:511 val->intval = 400; /* 40 C */512 break;513 case POWER_SUPPLY_PROP_TEMP_ALERT_MIN:514 val->intval = 15; /* 1.5 C */515 break;516 case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:517 val->intval = 380; /* 38 C */518 break;519 default:520 ret = -EINVAL;521 break;522 }523 524 return ret;525}526 527static inline void thunderstrike_request_psy_stats(struct thunderstrike *ts)528{529 set_bit(THUNDERSTRIKE_POWER_SUPPLY_STATS_UPDATE, &ts->update_flags);530 schedule_work(&ts->hostcmd_req_work);531}532 533static void thunderstrike_psy_stats_timer_handler(struct timer_list *timer)534{535 struct thunderstrike *ts =536 container_of(timer, struct thunderstrike, psy_stats_timer);537 538 thunderstrike_request_psy_stats(ts);539 /* Query battery statistics from device every five minutes */540 mod_timer(timer, jiffies + 300 * HZ);541}542 543static void544thunderstrike_parse_fw_version_payload(struct shield_device *shield_dev,545 __le16 fw_version)546{547 shield_dev->fw_version = le16_to_cpu(fw_version);548 549 set_bit(SHIELD_FW_VERSION_INITIALIZED, &shield_dev->initialized_flags);550 551 hid_dbg(shield_dev->hdev, "Thunderstrike firmware version 0x%04X\n",552 shield_dev->fw_version);553}554 555static void556thunderstrike_parse_board_info_payload(struct shield_device *shield_dev,557 struct thunderstrike_hostcmd_board_info *board_info)558{559 char board_revision_str[4];560 int i;561 562 shield_dev->board_info.revision = le16_to_cpu(board_info->revision);563 for (i = 0; i < 7; ++i) {564 u16 val = le16_to_cpu(board_info->serial[i]);565 566 shield_dev->board_info.serial_number[2 * i] = val & 0xFF;567 shield_dev->board_info.serial_number[2 * i + 1] = val >> 8;568 }569 shield_dev->board_info.serial_number[14] = '\0';570 571 set_bit(SHIELD_BOARD_INFO_INITIALIZED, &shield_dev->initialized_flags);572 573 shield_strrev(board_revision_str, 4, shield_dev->board_info.revision);574 hid_dbg(shield_dev->hdev,575 "Thunderstrike BOARD_REVISION_%s (0x%04X) S/N: %s\n",576 board_revision_str, shield_dev->board_info.revision,577 shield_dev->board_info.serial_number);578}579 580static inline void581thunderstrike_parse_haptics_payload(struct shield_device *shield_dev,582 struct thunderstrike_hostcmd_haptics *haptics)583{584 hid_dbg(shield_dev->hdev,585 "Thunderstrike haptics HOSTCMD response, left: %u right: %u\n",586 haptics->motor_left, haptics->motor_right);587}588 589static void590thunderstrike_parse_led_payload(struct shield_device *shield_dev,591 enum thunderstrike_led_state led_state)592{593 struct thunderstrike *ts = container_of(shield_dev, struct thunderstrike, base);594 595 switch (led_state) {596 case THUNDERSTRIKE_LED_OFF:597 ts->led_state = 0;598 break;599 case THUNDERSTRIKE_LED_ON:600 ts->led_state = 1;601 break;602 }603 604 hid_dbg(shield_dev->hdev, "Thunderstrike led HOSTCMD response, 0x%02X\n", led_state);605}606 607static void thunderstrike_parse_battery_payload(608 struct shield_device *shield_dev,609 struct thunderstrike_hostcmd_battery *battery)610{611 struct thunderstrike *ts = container_of(shield_dev, struct thunderstrike, base);612 u16 hostcmd_voltage_boot = le16_to_cpu(battery->voltage_boot);613 u16 hostcmd_voltage_avg = le16_to_cpu(battery->voltage_avg);614 u16 hostcmd_voltage_min = le16_to_cpu(battery->voltage_min);615 u16 hostcmd_voltage_now = le16_to_cpu(battery->voltage_now);616 u16 hostcmd_thermistor = le16_to_cpu(battery->thermistor);617 int voltage_boot, voltage_avg, voltage_min, voltage_now;618 struct hid_device *hdev = shield_dev->hdev;619 u8 capacity = battery->capacity;620 int temp;621 622 /* Convert thunderstrike device values to µV and tenths of degree Celsius */623 voltage_boot = hostcmd_voltage_boot * 1000;624 voltage_avg = hostcmd_voltage_avg * 1000;625 voltage_min = hostcmd_voltage_min * 1000;626 voltage_now = hostcmd_voltage_now * 1000;627 temp = (1378 - (int)hostcmd_thermistor) * 10 / 19;628 629 /* Copy converted values */630 spin_lock(&ts->psy_stats_lock);631 ts->psy_stats.voltage_boot = voltage_boot;632 ts->psy_stats.voltage_avg = voltage_avg;633 ts->psy_stats.voltage_min = voltage_min;634 ts->psy_stats.voltage_now = voltage_now;635 ts->psy_stats.capacity = capacity;636 ts->psy_stats.temp = temp;637 spin_unlock(&ts->psy_stats_lock);638 639 set_bit(SHIELD_BATTERY_STATS_INITIALIZED, &shield_dev->initialized_flags);640 641 hid_dbg(hdev,642 "Thunderstrike battery HOSTCMD response, voltage_avg: %u voltage_now: %u\n",643 hostcmd_voltage_avg, hostcmd_voltage_now);644 hid_dbg(hdev,645 "Thunderstrike battery HOSTCMD response, voltage_boot: %u voltage_min: %u\n",646 hostcmd_voltage_boot, hostcmd_voltage_min);647 hid_dbg(hdev,648 "Thunderstrike battery HOSTCMD response, thermistor: %u\n",649 hostcmd_thermistor);650 hid_dbg(hdev,651 "Thunderstrike battery HOSTCMD response, capacity: %u%%\n",652 capacity);653}654 655static void thunderstrike_parse_charger_payload(656 struct shield_device *shield_dev,657 struct thunderstrike_hostcmd_charger *charger)658{659 struct thunderstrike *ts = container_of(shield_dev, struct thunderstrike, base);660 int charge_type = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN;661 struct hid_device *hdev = shield_dev->hdev;662 int status = POWER_SUPPLY_STATUS_UNKNOWN;663 664 switch (charger->type) {665 case THUNDERSTRIKE_CHARGER_TYPE_NONE:666 charge_type = POWER_SUPPLY_CHARGE_TYPE_NONE;667 break;668 case THUNDERSTRIKE_CHARGER_TYPE_TRICKLE:669 charge_type = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;670 break;671 case THUNDERSTRIKE_CHARGER_TYPE_NORMAL:672 charge_type = POWER_SUPPLY_CHARGE_TYPE_STANDARD;673 break;674 default:675 hid_warn(hdev, "Unhandled Thunderstrike charger HOSTCMD type, %u\n",676 charger->type);677 break;678 }679 680 switch (charger->state) {681 case THUNDERSTRIKE_CHARGER_STATE_UNKNOWN:682 status = POWER_SUPPLY_STATUS_UNKNOWN;683 break;684 case THUNDERSTRIKE_CHARGER_STATE_DISABLED:685 /* Indicates charger is disconnected */686 break;687 case THUNDERSTRIKE_CHARGER_STATE_CHARGING:688 status = POWER_SUPPLY_STATUS_CHARGING;689 break;690 case THUNDERSTRIKE_CHARGER_STATE_FULL:691 status = POWER_SUPPLY_STATUS_FULL;692 break;693 case THUNDERSTRIKE_CHARGER_STATE_FAILED:694 status = POWER_SUPPLY_STATUS_NOT_CHARGING;695 hid_err(hdev, "Thunderstrike device failed to charge\n");696 break;697 default:698 hid_warn(hdev, "Unhandled Thunderstrike charger HOSTCMD state, %u\n",699 charger->state);700 break;701 }702 703 if (!charger->connected)704 status = POWER_SUPPLY_STATUS_DISCHARGING;705 706 spin_lock(&ts->psy_stats_lock);707 ts->psy_stats.charge_type = charge_type;708 ts->psy_stats.status = status;709 spin_unlock(&ts->psy_stats_lock);710 711 set_bit(SHIELD_CHARGER_STATE_INITIALIZED, &shield_dev->initialized_flags);712 713 hid_dbg(hdev,714 "Thunderstrike charger HOSTCMD response, connected: %u, type: %u, state: %u\n",715 charger->connected, charger->type, charger->state);716}717 718static inline void thunderstrike_device_init_info(struct shield_device *shield_dev)719{720 struct thunderstrike *ts =721 container_of(shield_dev, struct thunderstrike, base);722 723 if (!test_bit(SHIELD_FW_VERSION_INITIALIZED, &shield_dev->initialized_flags))724 thunderstrike_request_firmware_version(ts);725 726 if (!test_bit(SHIELD_BOARD_INFO_INITIALIZED, &shield_dev->initialized_flags))727 thunderstrike_request_board_info(ts);728 729 if (!test_bit(SHIELD_BATTERY_STATS_INITIALIZED, &shield_dev->initialized_flags) ||730 !test_bit(SHIELD_CHARGER_STATE_INITIALIZED, &shield_dev->initialized_flags))731 thunderstrike_psy_stats_timer_handler(&ts->psy_stats_timer);732}733 734static int thunderstrike_parse_report(struct shield_device *shield_dev,735 struct hid_report *report, u8 *data,736 int size)737{738 struct thunderstrike_hostcmd_resp_report *hostcmd_resp_report;739 struct hid_device *hdev = shield_dev->hdev;740 741 switch (report->id) {742 case THUNDERSTRIKE_HOSTCMD_RESP_REPORT_ID:743 if (size != THUNDERSTRIKE_HOSTCMD_REPORT_SIZE) {744 hid_err(hdev,745 "Encountered Thunderstrike HOSTCMD HID report with unexpected size %d\n",746 size);747 return -EINVAL;748 }749 750 hostcmd_resp_report =751 (struct thunderstrike_hostcmd_resp_report *)data;752 753 switch (hostcmd_resp_report->cmd_id) {754 case THUNDERSTRIKE_HOSTCMD_ID_FW_VERSION:755 thunderstrike_parse_fw_version_payload(756 shield_dev, hostcmd_resp_report->fw_version);757 break;758 case THUNDERSTRIKE_HOSTCMD_ID_LED:759 thunderstrike_parse_led_payload(shield_dev, hostcmd_resp_report->led_state);760 break;761 case THUNDERSTRIKE_HOSTCMD_ID_BATTERY:762 thunderstrike_parse_battery_payload(shield_dev,763 &hostcmd_resp_report->battery);764 break;765 case THUNDERSTRIKE_HOSTCMD_ID_BOARD_INFO:766 thunderstrike_parse_board_info_payload(767 shield_dev, &hostcmd_resp_report->board_info);768 break;769 case THUNDERSTRIKE_HOSTCMD_ID_HAPTICS:770 thunderstrike_parse_haptics_payload(771 shield_dev, &hostcmd_resp_report->motors);772 break;773 case THUNDERSTRIKE_HOSTCMD_ID_USB_INIT:774 /* May block HOSTCMD requests till received initially */775 thunderstrike_device_init_info(shield_dev);776 break;777 case THUNDERSTRIKE_HOSTCMD_ID_CHARGER:778 /* May block HOSTCMD requests till received initially */779 thunderstrike_device_init_info(shield_dev);780 781 thunderstrike_parse_charger_payload(782 shield_dev, &hostcmd_resp_report->charger);783 break;784 default:785 hid_warn(hdev,786 "Unhandled Thunderstrike HOSTCMD id %d\n",787 hostcmd_resp_report->cmd_id);788 return -ENOENT;789 }790 791 break;792 default:793 return 0;794 }795 796 return 0;797}798 799static inline int thunderstrike_led_create(struct thunderstrike *ts)800{801 struct led_classdev *led = &ts->led_dev;802 803 led->name = devm_kasprintf(&ts->base.hdev->dev, GFP_KERNEL,804 "thunderstrike%d:blue:led", ts->id);805 if (!led->name)806 return -ENOMEM;807 led->max_brightness = 1;808 led->flags = LED_CORE_SUSPENDRESUME | LED_RETAIN_AT_SHUTDOWN;809 led->brightness_get = &thunderstrike_led_get_brightness;810 led->brightness_set = &thunderstrike_led_set_brightness;811 812 return led_classdev_register(&ts->base.hdev->dev, led);813}814 815static inline int thunderstrike_psy_create(struct shield_device *shield_dev)816{817 struct thunderstrike *ts = container_of(shield_dev, struct thunderstrike, base);818 struct power_supply_config psy_cfg = { .drv_data = shield_dev, };819 struct hid_device *hdev = shield_dev->hdev;820 int ret;821 822 /*823 * Set an initial capacity and temperature value to avoid prematurely824 * triggering alerts. Will be replaced by values queried from initial825 * HOSTCMD requests.826 */827 ts->psy_stats.capacity = 100;828 ts->psy_stats.temp = 182;829 830 shield_dev->battery_dev.desc.properties = thunderstrike_battery_props;831 shield_dev->battery_dev.desc.num_properties =832 ARRAY_SIZE(thunderstrike_battery_props);833 shield_dev->battery_dev.desc.get_property = thunderstrike_battery_get_property;834 shield_dev->battery_dev.desc.type = POWER_SUPPLY_TYPE_BATTERY;835 shield_dev->battery_dev.desc.name =836 devm_kasprintf(&ts->base.hdev->dev, GFP_KERNEL,837 "thunderstrike_%d", ts->id);838 if (!shield_dev->battery_dev.desc.name)839 return -ENOMEM;840 841 shield_dev->battery_dev.psy = power_supply_register(842 &hdev->dev, &shield_dev->battery_dev.desc, &psy_cfg);843 if (IS_ERR(shield_dev->battery_dev.psy)) {844 hid_err(hdev, "Failed to register Thunderstrike battery device\n");845 return PTR_ERR(shield_dev->battery_dev.psy);846 }847 848 ret = power_supply_powers(shield_dev->battery_dev.psy, &hdev->dev);849 if (ret) {850 hid_err(hdev, "Failed to associate battery device to Thunderstrike\n");851 goto err;852 }853 854 return 0;855 856err:857 power_supply_unregister(shield_dev->battery_dev.psy);858 return ret;859}860 861static struct shield_device *thunderstrike_create(struct hid_device *hdev)862{863 struct shield_device *shield_dev;864 struct thunderstrike *ts;865 int ret;866 867 ts = devm_kzalloc(&hdev->dev, sizeof(*ts), GFP_KERNEL);868 if (!ts)869 return ERR_PTR(-ENOMEM);870 871 ts->req_report_dmabuf = devm_kzalloc(872 &hdev->dev, THUNDERSTRIKE_HOSTCMD_REPORT_SIZE, GFP_KERNEL);873 if (!ts->req_report_dmabuf)874 return ERR_PTR(-ENOMEM);875 876 shield_dev = &ts->base;877 shield_dev->hdev = hdev;878 shield_dev->codename = "Thunderstrike";879 880 spin_lock_init(&ts->haptics_update_lock);881 spin_lock_init(&ts->psy_stats_lock);882 INIT_WORK(&ts->hostcmd_req_work, thunderstrike_hostcmd_req_work_handler);883 884 hid_set_drvdata(hdev, shield_dev);885 886 ts->id = ida_alloc(&thunderstrike_ida, GFP_KERNEL);887 if (ts->id < 0)888 return ERR_PTR(ts->id);889 890 ts->haptics_dev = shield_haptics_create(shield_dev, thunderstrike_play_effect);891 if (IS_ERR(ts->haptics_dev)) {892 hid_err(hdev, "Failed to create Thunderstrike haptics instance\n");893 ret = PTR_ERR(ts->haptics_dev);894 goto err_id;895 }896 897 ret = thunderstrike_psy_create(shield_dev);898 if (ret) {899 hid_err(hdev, "Failed to create Thunderstrike power supply instance\n");900 goto err_haptics;901 }902 903 ret = thunderstrike_led_create(ts);904 if (ret) {905 hid_err(hdev, "Failed to create Thunderstrike LED instance\n");906 goto err_psy;907 }908 909 timer_setup(&ts->psy_stats_timer, thunderstrike_psy_stats_timer_handler, 0);910 911 hid_info(hdev, "Registered Thunderstrike controller\n");912 return shield_dev;913 914err_psy:915 power_supply_unregister(shield_dev->battery_dev.psy);916err_haptics:917 if (ts->haptics_dev)918 input_unregister_device(ts->haptics_dev);919err_id:920 ida_free(&thunderstrike_ida, ts->id);921 return ERR_PTR(ret);922}923 924static void thunderstrike_destroy(struct thunderstrike *ts)925{926 led_classdev_unregister(&ts->led_dev);927 power_supply_unregister(ts->base.battery_dev.psy);928 if (ts->haptics_dev)929 input_unregister_device(ts->haptics_dev);930 ida_free(&thunderstrike_ida, ts->id);931}932 933static int android_input_mapping(struct hid_device *hdev, struct hid_input *hi,934 struct hid_field *field,935 struct hid_usage *usage, unsigned long **bit,936 int *max)937{938 if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)939 return 0;940 941 switch (usage->hid & HID_USAGE) {942 case HID_USAGE_ANDROID_PLAYPAUSE_BTN:943 android_map_key(KEY_PLAYPAUSE);944 break;945 case HID_USAGE_ANDROID_VOLUMEUP_BTN:946 android_map_key(KEY_VOLUMEUP);947 break;948 case HID_USAGE_ANDROID_VOLUMEDOWN_BTN:949 android_map_key(KEY_VOLUMEDOWN);950 break;951 case HID_USAGE_ANDROID_SEARCH_BTN:952 android_map_key(BTN_Z);953 break;954 case HID_USAGE_ANDROID_HOME_BTN:955 android_map_key(BTN_MODE);956 break;957 case HID_USAGE_ANDROID_BACK_BTN:958 android_map_key(BTN_SELECT);959 break;960 default:961 return 0;962 }963 964 return 1;965}966 967static ssize_t firmware_version_show(struct device *dev,968 struct device_attribute *attr, char *buf)969{970 struct hid_device *hdev = to_hid_device(dev);971 struct shield_device *shield_dev;972 int ret;973 974 shield_dev = hid_get_drvdata(hdev);975 976 if (test_bit(SHIELD_FW_VERSION_INITIALIZED, &shield_dev->initialized_flags))977 ret = sysfs_emit(buf, "0x%04X\n", shield_dev->fw_version);978 else979 ret = sysfs_emit(buf, NOT_INIT_STR "\n");980 981 return ret;982}983 984static DEVICE_ATTR_RO(firmware_version);985 986static ssize_t hardware_version_show(struct device *dev,987 struct device_attribute *attr, char *buf)988{989 struct hid_device *hdev = to_hid_device(dev);990 struct shield_device *shield_dev;991 char board_revision_str[4];992 int ret;993 994 shield_dev = hid_get_drvdata(hdev);995 996 if (test_bit(SHIELD_BOARD_INFO_INITIALIZED, &shield_dev->initialized_flags)) {997 shield_strrev(board_revision_str, 4, shield_dev->board_info.revision);998 ret = sysfs_emit(buf, "%s BOARD_REVISION_%s (0x%04X)\n",999 shield_dev->codename, board_revision_str,1000 shield_dev->board_info.revision);1001 } else1002 ret = sysfs_emit(buf, NOT_INIT_STR "\n");1003 1004 return ret;1005}1006 1007static DEVICE_ATTR_RO(hardware_version);1008 1009static ssize_t serial_number_show(struct device *dev,1010 struct device_attribute *attr, char *buf)1011{1012 struct hid_device *hdev = to_hid_device(dev);1013 struct shield_device *shield_dev;1014 int ret;1015 1016 shield_dev = hid_get_drvdata(hdev);1017 1018 if (test_bit(SHIELD_BOARD_INFO_INITIALIZED, &shield_dev->initialized_flags))1019 ret = sysfs_emit(buf, "%s\n", shield_dev->board_info.serial_number);1020 else1021 ret = sysfs_emit(buf, NOT_INIT_STR "\n");1022 1023 return ret;1024}1025 1026static DEVICE_ATTR_RO(serial_number);1027 1028static struct attribute *shield_device_attrs[] = {1029 &dev_attr_firmware_version.attr,1030 &dev_attr_hardware_version.attr,1031 &dev_attr_serial_number.attr,1032 NULL,1033};1034ATTRIBUTE_GROUPS(shield_device);1035 1036static int shield_raw_event(struct hid_device *hdev, struct hid_report *report,1037 u8 *data, int size)1038{1039 struct shield_device *dev = hid_get_drvdata(hdev);1040 1041 return thunderstrike_parse_report(dev, report, data, size);1042}1043 1044static int shield_probe(struct hid_device *hdev, const struct hid_device_id *id)1045{1046 struct shield_device *shield_dev = NULL;1047 struct thunderstrike *ts;1048 int ret;1049 1050 ret = hid_parse(hdev);1051 if (ret) {1052 hid_err(hdev, "Parse failed\n");1053 return ret;1054 }1055 1056 switch (id->product) {1057 case USB_DEVICE_ID_NVIDIA_THUNDERSTRIKE_CONTROLLER:1058 shield_dev = thunderstrike_create(hdev);1059 break;1060 }1061 1062 if (unlikely(!shield_dev)) {1063 hid_err(hdev, "Failed to identify SHIELD device\n");1064 return -ENODEV;1065 }1066 if (IS_ERR(shield_dev)) {1067 hid_err(hdev, "Failed to create SHIELD device\n");1068 return PTR_ERR(shield_dev);1069 }1070 1071 ts = container_of(shield_dev, struct thunderstrike, base);1072 1073 ret = hid_hw_start(hdev, HID_CONNECT_HIDINPUT);1074 if (ret) {1075 hid_err(hdev, "Failed to start HID device\n");1076 goto err_ts_create;1077 }1078 1079 ret = hid_hw_open(hdev);1080 if (ret) {1081 hid_err(hdev, "Failed to open HID device\n");1082 goto err_stop;1083 }1084 1085 thunderstrike_device_init_info(shield_dev);1086 1087 return ret;1088 1089err_stop:1090 hid_hw_stop(hdev);1091err_ts_create:1092 thunderstrike_destroy(ts);1093 return ret;1094}1095 1096static void shield_remove(struct hid_device *hdev)1097{1098 struct shield_device *dev = hid_get_drvdata(hdev);1099 struct thunderstrike *ts;1100 1101 ts = container_of(dev, struct thunderstrike, base);1102 1103 hid_hw_close(hdev);1104 thunderstrike_destroy(ts);1105 del_timer_sync(&ts->psy_stats_timer);1106 cancel_work_sync(&ts->hostcmd_req_work);1107 hid_hw_stop(hdev);1108}1109 1110static const struct hid_device_id shield_devices[] = {1111 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NVIDIA,1112 USB_DEVICE_ID_NVIDIA_THUNDERSTRIKE_CONTROLLER) },1113 { HID_USB_DEVICE(USB_VENDOR_ID_NVIDIA,1114 USB_DEVICE_ID_NVIDIA_THUNDERSTRIKE_CONTROLLER) },1115 { }1116};1117MODULE_DEVICE_TABLE(hid, shield_devices);1118 1119static struct hid_driver shield_driver = {1120 .name = "shield",1121 .id_table = shield_devices,1122 .input_mapping = android_input_mapping,1123 .probe = shield_probe,1124 .remove = shield_remove,1125 .raw_event = shield_raw_event,1126 .driver = {1127 .dev_groups = shield_device_groups,1128 },1129};1130module_hid_driver(shield_driver);1131 1132MODULE_AUTHOR("Rahul Rameshbabu <rrameshbabu@nvidia.com>");1133MODULE_DESCRIPTION("HID Driver for NVIDIA SHIELD peripherals.");1134MODULE_LICENSE("GPL");1135