225 lines
7.8 KiB
C
225 lines
7.8 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/*
|
|
* AMD SFH Report Descriptor generator
|
|
* Copyright 2020 Advanced Micro Devices, Inc.
|
|
* Authors: Nehal Bakulchandra Shah <Nehal-Bakulchandra.Shah@amd.com>
|
|
* Sandeep Singh <sandeep.singh@amd.com>
|
|
*/
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/string.h>
|
|
#include <linux/slab.h>
|
|
#include "amd_sfh_pcie.h"
|
|
#include "amd_sfh_hid_desc.h"
|
|
#include "amd_sfh_hid_report_desc.h"
|
|
|
|
#define AMD_SFH_FW_MULTIPLIER (1000)
|
|
#define HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM 0x41
|
|
#define HID_USAGE_SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM 0x51
|
|
#define HID_DEFAULT_REPORT_INTERVAL 0x50
|
|
#define HID_DEFAULT_MIN_VALUE 0X7F
|
|
#define HID_DEFAULT_MAX_VALUE 0x80
|
|
#define HID_DEFAULT_SENSITIVITY 0x7F
|
|
#define HID_USAGE_SENSOR_PROPERTY_CONNECTION_TYPE_PC_INTEGRATED_ENUM 0x01
|
|
/* state enums */
|
|
#define HID_USAGE_SENSOR_STATE_READY_ENUM 0x02
|
|
#define HID_USAGE_SENSOR_STATE_INITIALIZING_ENUM 0x05
|
|
#define HID_USAGE_SENSOR_EVENT_DATA_UPDATED_ENUM 0x04
|
|
|
|
int get_report_descriptor(int sensor_idx, u8 *rep_desc)
|
|
{
|
|
switch (sensor_idx) {
|
|
case accel_idx: /* accel */
|
|
memset(rep_desc, 0, sizeof(accel3_report_descriptor));
|
|
memcpy(rep_desc, accel3_report_descriptor,
|
|
sizeof(accel3_report_descriptor));
|
|
break;
|
|
case gyro_idx: /* gyro */
|
|
memset(rep_desc, 0, sizeof(gyro3_report_descriptor));
|
|
memcpy(rep_desc, gyro3_report_descriptor,
|
|
sizeof(gyro3_report_descriptor));
|
|
break;
|
|
case mag_idx: /* Magnetometer */
|
|
memset(rep_desc, 0, sizeof(comp3_report_descriptor));
|
|
memcpy(rep_desc, comp3_report_descriptor,
|
|
sizeof(comp3_report_descriptor));
|
|
break;
|
|
case als_idx: /* ambient light sensor */
|
|
memset(rep_desc, 0, sizeof(als_report_descriptor));
|
|
memcpy(rep_desc, als_report_descriptor,
|
|
sizeof(als_report_descriptor));
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
u32 get_descr_sz(int sensor_idx, int descriptor_name)
|
|
{
|
|
switch (sensor_idx) {
|
|
case accel_idx:
|
|
switch (descriptor_name) {
|
|
case descr_size:
|
|
return sizeof(accel3_report_descriptor);
|
|
case input_size:
|
|
return sizeof(struct accel3_input_report);
|
|
case feature_size:
|
|
return sizeof(struct accel3_feature_report);
|
|
}
|
|
break;
|
|
case gyro_idx:
|
|
switch (descriptor_name) {
|
|
case descr_size:
|
|
return sizeof(gyro3_report_descriptor);
|
|
case input_size:
|
|
return sizeof(struct gyro_input_report);
|
|
case feature_size:
|
|
return sizeof(struct gyro_feature_report);
|
|
}
|
|
break;
|
|
case mag_idx:
|
|
switch (descriptor_name) {
|
|
case descr_size:
|
|
return sizeof(comp3_report_descriptor);
|
|
case input_size:
|
|
return sizeof(struct magno_input_report);
|
|
case feature_size:
|
|
return sizeof(struct magno_feature_report);
|
|
}
|
|
break;
|
|
case als_idx:
|
|
switch (descriptor_name) {
|
|
case descr_size:
|
|
return sizeof(als_report_descriptor);
|
|
case input_size:
|
|
return sizeof(struct als_input_report);
|
|
case feature_size:
|
|
return sizeof(struct als_feature_report);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void get_common_features(struct common_feature_property *common, int report_id)
|
|
{
|
|
common->report_id = report_id;
|
|
common->connection_type = HID_USAGE_SENSOR_PROPERTY_CONNECTION_TYPE_PC_INTEGRATED_ENUM;
|
|
common->report_state = HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM;
|
|
common->power_state = HID_USAGE_SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM;
|
|
common->sensor_state = HID_USAGE_SENSOR_STATE_INITIALIZING_ENUM;
|
|
common->report_interval = HID_DEFAULT_REPORT_INTERVAL;
|
|
}
|
|
|
|
u8 get_feature_report(int sensor_idx, int report_id, u8 *feature_report)
|
|
{
|
|
struct accel3_feature_report acc_feature;
|
|
struct gyro_feature_report gyro_feature;
|
|
struct magno_feature_report magno_feature;
|
|
struct als_feature_report als_feature;
|
|
u8 report_size = 0;
|
|
|
|
if (!feature_report)
|
|
return report_size;
|
|
|
|
switch (sensor_idx) {
|
|
case accel_idx: /* accel */
|
|
get_common_features(&acc_feature.common_property, report_id);
|
|
acc_feature.accel_change_sesnitivity = HID_DEFAULT_SENSITIVITY;
|
|
acc_feature.accel_sensitivity_min = HID_DEFAULT_MIN_VALUE;
|
|
acc_feature.accel_sensitivity_max = HID_DEFAULT_MAX_VALUE;
|
|
memcpy(feature_report, &acc_feature, sizeof(acc_feature));
|
|
report_size = sizeof(acc_feature);
|
|
break;
|
|
case gyro_idx: /* gyro */
|
|
get_common_features(&gyro_feature.common_property, report_id);
|
|
gyro_feature.gyro_change_sesnitivity = HID_DEFAULT_SENSITIVITY;
|
|
gyro_feature.gyro_sensitivity_min = HID_DEFAULT_MIN_VALUE;
|
|
gyro_feature.gyro_sensitivity_max = HID_DEFAULT_MAX_VALUE;
|
|
memcpy(feature_report, &gyro_feature, sizeof(gyro_feature));
|
|
report_size = sizeof(gyro_feature);
|
|
break;
|
|
case mag_idx: /* Magnetometer */
|
|
get_common_features(&magno_feature.common_property, report_id);
|
|
magno_feature.magno_headingchange_sensitivity = HID_DEFAULT_SENSITIVITY;
|
|
magno_feature.heading_min = HID_DEFAULT_MIN_VALUE;
|
|
magno_feature.heading_max = HID_DEFAULT_MAX_VALUE;
|
|
magno_feature.flux_change_sensitivity = HID_DEFAULT_MIN_VALUE;
|
|
magno_feature.flux_min = HID_DEFAULT_MIN_VALUE;
|
|
magno_feature.flux_max = HID_DEFAULT_MAX_VALUE;
|
|
memcpy(feature_report, &magno_feature, sizeof(magno_feature));
|
|
report_size = sizeof(magno_feature);
|
|
break;
|
|
case als_idx: /* ambient light sensor */
|
|
get_common_features(&als_feature.common_property, report_id);
|
|
als_feature.als_change_sesnitivity = HID_DEFAULT_SENSITIVITY;
|
|
als_feature.als_sensitivity_min = HID_DEFAULT_MIN_VALUE;
|
|
als_feature.als_sensitivity_max = HID_DEFAULT_MAX_VALUE;
|
|
memcpy(feature_report, &als_feature, sizeof(als_feature));
|
|
report_size = sizeof(als_feature);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return report_size;
|
|
}
|
|
|
|
static void get_common_inputs(struct common_input_property *common, int report_id)
|
|
{
|
|
common->report_id = report_id;
|
|
common->sensor_state = HID_USAGE_SENSOR_STATE_READY_ENUM;
|
|
common->event_type = HID_USAGE_SENSOR_EVENT_DATA_UPDATED_ENUM;
|
|
}
|
|
|
|
u8 get_input_report(int sensor_idx, int report_id, u8 *input_report, u32 *sensor_virt_addr)
|
|
{
|
|
struct accel3_input_report acc_input;
|
|
struct gyro_input_report gyro_input;
|
|
struct magno_input_report magno_input;
|
|
struct als_input_report als_input;
|
|
u8 report_size = 0;
|
|
|
|
if (!sensor_virt_addr || !input_report)
|
|
return report_size;
|
|
|
|
switch (sensor_idx) {
|
|
case accel_idx: /* accel */
|
|
get_common_inputs(&acc_input.common_property, report_id);
|
|
acc_input.in_accel_x_value = (int)sensor_virt_addr[0] / AMD_SFH_FW_MULTIPLIER;
|
|
acc_input.in_accel_y_value = (int)sensor_virt_addr[1] / AMD_SFH_FW_MULTIPLIER;
|
|
acc_input.in_accel_z_value = (int)sensor_virt_addr[2] / AMD_SFH_FW_MULTIPLIER;
|
|
memcpy(input_report, &acc_input, sizeof(acc_input));
|
|
report_size = sizeof(acc_input);
|
|
break;
|
|
case gyro_idx: /* gyro */
|
|
get_common_inputs(&gyro_input.common_property, report_id);
|
|
gyro_input.in_angel_x_value = (int)sensor_virt_addr[0] / AMD_SFH_FW_MULTIPLIER;
|
|
gyro_input.in_angel_y_value = (int)sensor_virt_addr[1] / AMD_SFH_FW_MULTIPLIER;
|
|
gyro_input.in_angel_z_value = (int)sensor_virt_addr[2] / AMD_SFH_FW_MULTIPLIER;
|
|
memcpy(input_report, &gyro_input, sizeof(gyro_input));
|
|
report_size = sizeof(gyro_input);
|
|
break;
|
|
case mag_idx: /* Magnetometer */
|
|
get_common_inputs(&magno_input.common_property, report_id);
|
|
magno_input.in_magno_x = (int)sensor_virt_addr[0] / AMD_SFH_FW_MULTIPLIER;
|
|
magno_input.in_magno_y = (int)sensor_virt_addr[1] / AMD_SFH_FW_MULTIPLIER;
|
|
magno_input.in_magno_z = (int)sensor_virt_addr[2] / AMD_SFH_FW_MULTIPLIER;
|
|
magno_input.in_magno_accuracy = (u16)sensor_virt_addr[3] / AMD_SFH_FW_MULTIPLIER;
|
|
memcpy(input_report, &magno_input, sizeof(magno_input));
|
|
report_size = sizeof(magno_input);
|
|
break;
|
|
case als_idx: /* Als */
|
|
get_common_inputs(&als_input.common_property, report_id);
|
|
als_input.illuminance_value = (int)sensor_virt_addr[0] / AMD_SFH_FW_MULTIPLIER;
|
|
report_size = sizeof(als_input);
|
|
memcpy(input_report, &als_input, sizeof(als_input));
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return report_size;
|
|
}
|