mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid
Pull HID updates from Jiri Kosina: - patch series that ensures that hid-multitouch driver disables touch and button-press reporting on hid-mt devices during suspend when the device is not configured as a wakeup-source, from Hans de Goede - support for ISH DMA on Intel EHL platform, from Even Xu - support for Renoir and Cezanne SoCs, Ambient Light Sensor and Human Presence Detection sensor for amd-sfh driver, from Basavaraj Natikar - other assorted code cleanups and device-specific fixes/quirks * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid: (45 commits) HID: thrustmaster: Switch to kmemdup() when allocate change_request HID: multitouch: Disable event reporting on suspend when the device is not a wakeup-source HID: logitech-dj: Implement may_wakeup ll-driver callback HID: usbhid: Implement may_wakeup ll-driver callback HID: core: Add hid_hw_may_wakeup() function HID: input: Add support for Programmable Buttons HID: wacom: Correct base usage for capacitive ExpressKey status bits HID: amd_sfh: Add initial support for HPD sensor HID: amd_sfh: Extend ALS support for newer AMD platform HID: amd_sfh: Extend driver capabilities for multi-generation support HID: surface-hid: Fix get-report request HID: sony: fix freeze when inserting ghlive ps3/wii dongles HID: usbkbd: Avoid GFP_ATOMIC when GFP_KERNEL is possible HID: amd_sfh: change in maintainer HID: intel-ish-hid: ipc: Specify that EHL no cache snooping HID: intel-ish-hid: ishtp: Add dma_no_cache_snooping() callback HID: intel-ish-hid: Set ISH driver depends on x86 HID: hid-input: add Surface Go battery quirk HID: intel-ish-hid: Fix minor typos in comments HID: usbmouse: Avoid GFP_ATOMIC when GFP_KERNEL is possible ...
This commit is contained in:
commit
df04fbe868
@ -973,7 +973,7 @@ F: drivers/net/ethernet/amd/xgbe/
|
|||||||
|
|
||||||
AMD SENSOR FUSION HUB DRIVER
|
AMD SENSOR FUSION HUB DRIVER
|
||||||
M: Nehal Shah <nehal-bakulchandra.shah@amd.com>
|
M: Nehal Shah <nehal-bakulchandra.shah@amd.com>
|
||||||
M: Sandeep Singh <sandeep.singh@amd.com>
|
M: Basavaraj Natikar <basavaraj.natikar@amd.com>
|
||||||
L: linux-input@vger.kernel.org
|
L: linux-input@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: Documentation/hid/amd-sfh*
|
F: Documentation/hid/amd-sfh*
|
||||||
|
@ -77,6 +77,7 @@ int amd_sfh_get_report(struct hid_device *hid, int report_id, int report_type)
|
|||||||
static void amd_sfh_work(struct work_struct *work)
|
static void amd_sfh_work(struct work_struct *work)
|
||||||
{
|
{
|
||||||
struct amdtp_cl_data *cli_data = container_of(work, struct amdtp_cl_data, work.work);
|
struct amdtp_cl_data *cli_data = container_of(work, struct amdtp_cl_data, work.work);
|
||||||
|
struct amd_input_data *in_data = cli_data->in_data;
|
||||||
struct request_list *req_node;
|
struct request_list *req_node;
|
||||||
u8 current_index, sensor_index;
|
u8 current_index, sensor_index;
|
||||||
u8 report_id, node_type;
|
u8 report_id, node_type;
|
||||||
@ -101,13 +102,11 @@ static void amd_sfh_work(struct work_struct *work)
|
|||||||
pr_err("AMDSFH: Invalid report size\n");
|
pr_err("AMDSFH: Invalid report size\n");
|
||||||
|
|
||||||
} else if (node_type == HID_INPUT_REPORT) {
|
} else if (node_type == HID_INPUT_REPORT) {
|
||||||
report_size = get_input_report(sensor_index, report_id,
|
report_size = get_input_report(current_index, sensor_index, report_id, in_data);
|
||||||
cli_data->input_report[current_index],
|
|
||||||
cli_data->sensor_virt_addr[current_index]);
|
|
||||||
if (report_size)
|
if (report_size)
|
||||||
hid_input_report(cli_data->hid_sensor_hubs[current_index],
|
hid_input_report(cli_data->hid_sensor_hubs[current_index],
|
||||||
cli_data->report_type[current_index],
|
cli_data->report_type[current_index],
|
||||||
cli_data->input_report[current_index], report_size, 0);
|
in_data->input_report[current_index], report_size, 0);
|
||||||
else
|
else
|
||||||
pr_err("AMDSFH: Invalid report size\n");
|
pr_err("AMDSFH: Invalid report size\n");
|
||||||
}
|
}
|
||||||
@ -119,21 +118,22 @@ static void amd_sfh_work(struct work_struct *work)
|
|||||||
static void amd_sfh_work_buffer(struct work_struct *work)
|
static void amd_sfh_work_buffer(struct work_struct *work)
|
||||||
{
|
{
|
||||||
struct amdtp_cl_data *cli_data = container_of(work, struct amdtp_cl_data, work_buffer.work);
|
struct amdtp_cl_data *cli_data = container_of(work, struct amdtp_cl_data, work_buffer.work);
|
||||||
|
struct amd_input_data *in_data = cli_data->in_data;
|
||||||
u8 report_size;
|
u8 report_size;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < cli_data->num_hid_devices; i++) {
|
for (i = 0; i < cli_data->num_hid_devices; i++) {
|
||||||
report_size = get_input_report(cli_data->sensor_idx[i], cli_data->report_id[i],
|
report_size = get_input_report(i, cli_data->sensor_idx[i], cli_data->report_id[i],
|
||||||
cli_data->input_report[i],
|
in_data);
|
||||||
cli_data->sensor_virt_addr[i]);
|
|
||||||
hid_input_report(cli_data->hid_sensor_hubs[i], HID_INPUT_REPORT,
|
hid_input_report(cli_data->hid_sensor_hubs[i], HID_INPUT_REPORT,
|
||||||
cli_data->input_report[i], report_size, 0);
|
in_data->input_report[i], report_size, 0);
|
||||||
}
|
}
|
||||||
schedule_delayed_work(&cli_data->work_buffer, msecs_to_jiffies(AMD_SFH_IDLE_LOOP));
|
schedule_delayed_work(&cli_data->work_buffer, msecs_to_jiffies(AMD_SFH_IDLE_LOOP));
|
||||||
}
|
}
|
||||||
|
|
||||||
int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
|
int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
|
||||||
{
|
{
|
||||||
|
struct amd_input_data *in_data = &privdata->in_data;
|
||||||
struct amdtp_cl_data *cl_data = privdata->cl_data;
|
struct amdtp_cl_data *cl_data = privdata->cl_data;
|
||||||
struct amd_mp2_sensor_info info;
|
struct amd_mp2_sensor_info info;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
@ -143,18 +143,16 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
|
|||||||
int rc, i;
|
int rc, i;
|
||||||
|
|
||||||
dev = &privdata->pdev->dev;
|
dev = &privdata->pdev->dev;
|
||||||
cl_data = devm_kzalloc(dev, sizeof(*cl_data), GFP_KERNEL);
|
|
||||||
if (!cl_data)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
cl_data->num_hid_devices = amd_mp2_get_sensor_num(privdata, &cl_data->sensor_idx[0]);
|
cl_data->num_hid_devices = amd_mp2_get_sensor_num(privdata, &cl_data->sensor_idx[0]);
|
||||||
|
|
||||||
INIT_DELAYED_WORK(&cl_data->work, amd_sfh_work);
|
INIT_DELAYED_WORK(&cl_data->work, amd_sfh_work);
|
||||||
INIT_DELAYED_WORK(&cl_data->work_buffer, amd_sfh_work_buffer);
|
INIT_DELAYED_WORK(&cl_data->work_buffer, amd_sfh_work_buffer);
|
||||||
INIT_LIST_HEAD(&req_list.list);
|
INIT_LIST_HEAD(&req_list.list);
|
||||||
|
cl_data->in_data = in_data;
|
||||||
|
|
||||||
for (i = 0; i < cl_data->num_hid_devices; i++) {
|
for (i = 0; i < cl_data->num_hid_devices; i++) {
|
||||||
cl_data->sensor_virt_addr[i] = dma_alloc_coherent(dev, sizeof(int) * 8,
|
in_data->sensor_virt_addr[i] = dma_alloc_coherent(dev, sizeof(int) * 8,
|
||||||
&cl_data->sensor_dma_addr[i],
|
&cl_data->sensor_dma_addr[i],
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
cl_data->sensor_sts[i] = 0;
|
cl_data->sensor_sts[i] = 0;
|
||||||
@ -181,8 +179,8 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
|
|||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
cl_data->input_report[i] = devm_kzalloc(dev, input_report_size, GFP_KERNEL);
|
in_data->input_report[i] = devm_kzalloc(dev, input_report_size, GFP_KERNEL);
|
||||||
if (!cl_data->input_report[i]) {
|
if (!in_data->input_report[i]) {
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
@ -202,44 +200,43 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
|
|||||||
rc = amdtp_hid_probe(cl_data->cur_hid_dev, cl_data);
|
rc = amdtp_hid_probe(cl_data->cur_hid_dev, cl_data);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
amd_start_sensor(privdata, info);
|
privdata->mp2_ops->start(privdata, info);
|
||||||
cl_data->sensor_sts[i] = 1;
|
cl_data->sensor_sts[i] = 1;
|
||||||
}
|
}
|
||||||
privdata->cl_data = cl_data;
|
|
||||||
schedule_delayed_work(&cl_data->work_buffer, msecs_to_jiffies(AMD_SFH_IDLE_LOOP));
|
schedule_delayed_work(&cl_data->work_buffer, msecs_to_jiffies(AMD_SFH_IDLE_LOOP));
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
for (i = 0; i < cl_data->num_hid_devices; i++) {
|
for (i = 0; i < cl_data->num_hid_devices; i++) {
|
||||||
if (cl_data->sensor_virt_addr[i]) {
|
if (in_data->sensor_virt_addr[i]) {
|
||||||
dma_free_coherent(&privdata->pdev->dev, 8 * sizeof(int),
|
dma_free_coherent(&privdata->pdev->dev, 8 * sizeof(int),
|
||||||
cl_data->sensor_virt_addr[i],
|
in_data->sensor_virt_addr[i],
|
||||||
cl_data->sensor_dma_addr[i]);
|
cl_data->sensor_dma_addr[i]);
|
||||||
}
|
}
|
||||||
devm_kfree(dev, cl_data->feature_report[i]);
|
devm_kfree(dev, cl_data->feature_report[i]);
|
||||||
devm_kfree(dev, cl_data->input_report[i]);
|
devm_kfree(dev, in_data->input_report[i]);
|
||||||
devm_kfree(dev, cl_data->report_descr[i]);
|
devm_kfree(dev, cl_data->report_descr[i]);
|
||||||
}
|
}
|
||||||
devm_kfree(dev, cl_data);
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int amd_sfh_hid_client_deinit(struct amd_mp2_dev *privdata)
|
int amd_sfh_hid_client_deinit(struct amd_mp2_dev *privdata)
|
||||||
{
|
{
|
||||||
struct amdtp_cl_data *cl_data = privdata->cl_data;
|
struct amdtp_cl_data *cl_data = privdata->cl_data;
|
||||||
|
struct amd_input_data *in_data = cl_data->in_data;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < cl_data->num_hid_devices; i++)
|
for (i = 0; i < cl_data->num_hid_devices; i++)
|
||||||
amd_stop_sensor(privdata, i);
|
privdata->mp2_ops->stop(privdata, i);
|
||||||
|
|
||||||
cancel_delayed_work_sync(&cl_data->work);
|
cancel_delayed_work_sync(&cl_data->work);
|
||||||
cancel_delayed_work_sync(&cl_data->work_buffer);
|
cancel_delayed_work_sync(&cl_data->work_buffer);
|
||||||
amdtp_hid_remove(cl_data);
|
amdtp_hid_remove(cl_data);
|
||||||
|
|
||||||
for (i = 0; i < cl_data->num_hid_devices; i++) {
|
for (i = 0; i < cl_data->num_hid_devices; i++) {
|
||||||
if (cl_data->sensor_virt_addr[i]) {
|
if (in_data->sensor_virt_addr[i]) {
|
||||||
dma_free_coherent(&privdata->pdev->dev, 8 * sizeof(int),
|
dma_free_coherent(&privdata->pdev->dev, 8 * sizeof(int),
|
||||||
cl_data->sensor_virt_addr[i],
|
in_data->sensor_virt_addr[i],
|
||||||
cl_data->sensor_dma_addr[i]);
|
cl_data->sensor_dma_addr[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,11 +9,16 @@
|
|||||||
#ifndef AMDSFH_HID_H
|
#ifndef AMDSFH_HID_H
|
||||||
#define AMDSFH_HID_H
|
#define AMDSFH_HID_H
|
||||||
|
|
||||||
#define MAX_HID_DEVICES 4
|
#define MAX_HID_DEVICES 5
|
||||||
#define BUS_AMD_AMDTP 0x20
|
#define BUS_AMD_AMDTP 0x20
|
||||||
#define AMD_SFH_HID_VENDOR 0x1022
|
#define AMD_SFH_HID_VENDOR 0x1022
|
||||||
#define AMD_SFH_HID_PRODUCT 0x0001
|
#define AMD_SFH_HID_PRODUCT 0x0001
|
||||||
|
|
||||||
|
struct amd_input_data {
|
||||||
|
u32 *sensor_virt_addr[MAX_HID_DEVICES];
|
||||||
|
u8 *input_report[MAX_HID_DEVICES];
|
||||||
|
};
|
||||||
|
|
||||||
struct amdtp_cl_data {
|
struct amdtp_cl_data {
|
||||||
u8 init_done;
|
u8 init_done;
|
||||||
u32 cur_hid_dev;
|
u32 cur_hid_dev;
|
||||||
@ -26,7 +31,6 @@ struct amdtp_cl_data {
|
|||||||
u8 *hid_descr[MAX_HID_DEVICES];
|
u8 *hid_descr[MAX_HID_DEVICES];
|
||||||
int hid_descr_size[MAX_HID_DEVICES];
|
int hid_descr_size[MAX_HID_DEVICES];
|
||||||
phys_addr_t phys_addr_base;
|
phys_addr_t phys_addr_base;
|
||||||
u32 *sensor_virt_addr[MAX_HID_DEVICES];
|
|
||||||
dma_addr_t sensor_dma_addr[MAX_HID_DEVICES];
|
dma_addr_t sensor_dma_addr[MAX_HID_DEVICES];
|
||||||
u32 sensor_sts[MAX_HID_DEVICES];
|
u32 sensor_sts[MAX_HID_DEVICES];
|
||||||
u32 sensor_requested_cnt[MAX_HID_DEVICES];
|
u32 sensor_requested_cnt[MAX_HID_DEVICES];
|
||||||
@ -34,8 +38,8 @@ struct amdtp_cl_data {
|
|||||||
u8 report_id[MAX_HID_DEVICES];
|
u8 report_id[MAX_HID_DEVICES];
|
||||||
u8 sensor_idx[MAX_HID_DEVICES];
|
u8 sensor_idx[MAX_HID_DEVICES];
|
||||||
u8 *feature_report[MAX_HID_DEVICES];
|
u8 *feature_report[MAX_HID_DEVICES];
|
||||||
u8 *input_report[MAX_HID_DEVICES];
|
|
||||||
u8 request_done[MAX_HID_DEVICES];
|
u8 request_done[MAX_HID_DEVICES];
|
||||||
|
struct amd_input_data *in_data;
|
||||||
struct delayed_work work;
|
struct delayed_work work;
|
||||||
struct delayed_work work_buffer;
|
struct delayed_work work_buffer;
|
||||||
};
|
};
|
||||||
@ -64,4 +68,6 @@ void amdtp_hid_remove(struct amdtp_cl_data *cli_data);
|
|||||||
int amd_sfh_get_report(struct hid_device *hid, int report_id, int report_type);
|
int amd_sfh_get_report(struct hid_device *hid, int report_id, int report_type);
|
||||||
void amd_sfh_set_report(struct hid_device *hid, int report_id, int report_type);
|
void amd_sfh_set_report(struct hid_device *hid, int report_id, int report_type);
|
||||||
void amdtp_hid_wakeup(struct hid_device *hid);
|
void amdtp_hid_wakeup(struct hid_device *hid);
|
||||||
|
u8 get_input_report(u8 current_index, int sensor_idx, int report_id,
|
||||||
|
struct amd_input_data *in_data);
|
||||||
#endif
|
#endif
|
||||||
|
@ -24,12 +24,55 @@
|
|||||||
#define ACEL_EN BIT(0)
|
#define ACEL_EN BIT(0)
|
||||||
#define GYRO_EN BIT(1)
|
#define GYRO_EN BIT(1)
|
||||||
#define MAGNO_EN BIT(2)
|
#define MAGNO_EN BIT(2)
|
||||||
|
#define HPD_EN BIT(16)
|
||||||
#define ALS_EN BIT(19)
|
#define ALS_EN BIT(19)
|
||||||
|
|
||||||
static int sensor_mask_override = -1;
|
static int sensor_mask_override = -1;
|
||||||
module_param_named(sensor_mask, sensor_mask_override, int, 0444);
|
module_param_named(sensor_mask, sensor_mask_override, int, 0444);
|
||||||
MODULE_PARM_DESC(sensor_mask, "override the detected sensors mask");
|
MODULE_PARM_DESC(sensor_mask, "override the detected sensors mask");
|
||||||
|
|
||||||
|
static void amd_start_sensor_v2(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info)
|
||||||
|
{
|
||||||
|
union sfh_cmd_base cmd_base;
|
||||||
|
|
||||||
|
cmd_base.ul = 0;
|
||||||
|
cmd_base.cmd_v2.cmd_id = ENABLE_SENSOR;
|
||||||
|
cmd_base.cmd_v2.period = info.period;
|
||||||
|
cmd_base.cmd_v2.sensor_id = info.sensor_idx;
|
||||||
|
cmd_base.cmd_v2.length = 16;
|
||||||
|
|
||||||
|
if (info.sensor_idx == als_idx)
|
||||||
|
cmd_base.cmd_v2.mem_type = USE_C2P_REG;
|
||||||
|
|
||||||
|
writeq(info.dma_address, privdata->mmio + AMD_C2P_MSG1);
|
||||||
|
writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void amd_stop_sensor_v2(struct amd_mp2_dev *privdata, u16 sensor_idx)
|
||||||
|
{
|
||||||
|
union sfh_cmd_base cmd_base;
|
||||||
|
|
||||||
|
cmd_base.ul = 0;
|
||||||
|
cmd_base.cmd_v2.cmd_id = DISABLE_SENSOR;
|
||||||
|
cmd_base.cmd_v2.period = 0;
|
||||||
|
cmd_base.cmd_v2.sensor_id = sensor_idx;
|
||||||
|
cmd_base.cmd_v2.length = 16;
|
||||||
|
|
||||||
|
writeq(0x0, privdata->mmio + AMD_C2P_MSG2);
|
||||||
|
writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void amd_stop_all_sensor_v2(struct amd_mp2_dev *privdata)
|
||||||
|
{
|
||||||
|
union sfh_cmd_base cmd_base;
|
||||||
|
|
||||||
|
cmd_base.cmd_v2.cmd_id = STOP_ALL_SENSORS;
|
||||||
|
cmd_base.cmd_v2.period = 0;
|
||||||
|
cmd_base.cmd_v2.sensor_id = 0;
|
||||||
|
|
||||||
|
writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0);
|
||||||
|
}
|
||||||
|
|
||||||
void amd_start_sensor(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info)
|
void amd_start_sensor(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info)
|
||||||
{
|
{
|
||||||
union sfh_cmd_param cmd_param;
|
union sfh_cmd_param cmd_param;
|
||||||
@ -98,7 +141,6 @@ int amd_mp2_get_sensor_num(struct amd_mp2_dev *privdata, u8 *sensor_id)
|
|||||||
{
|
{
|
||||||
int activestatus, num_of_sensors = 0;
|
int activestatus, num_of_sensors = 0;
|
||||||
const struct dmi_system_id *dmi_id;
|
const struct dmi_system_id *dmi_id;
|
||||||
u32 activecontrolstatus;
|
|
||||||
|
|
||||||
if (sensor_mask_override == -1) {
|
if (sensor_mask_override == -1) {
|
||||||
dmi_id = dmi_first_match(dmi_sensor_mask_overrides);
|
dmi_id = dmi_first_match(dmi_sensor_mask_overrides);
|
||||||
@ -109,8 +151,7 @@ int amd_mp2_get_sensor_num(struct amd_mp2_dev *privdata, u8 *sensor_id)
|
|||||||
if (sensor_mask_override >= 0) {
|
if (sensor_mask_override >= 0) {
|
||||||
activestatus = sensor_mask_override;
|
activestatus = sensor_mask_override;
|
||||||
} else {
|
} else {
|
||||||
activecontrolstatus = readl(privdata->mmio + AMD_P2C_MSG3);
|
activestatus = privdata->mp2_acs >> 4;
|
||||||
activestatus = activecontrolstatus >> 4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ACEL_EN & activestatus)
|
if (ACEL_EN & activestatus)
|
||||||
@ -125,13 +166,46 @@ int amd_mp2_get_sensor_num(struct amd_mp2_dev *privdata, u8 *sensor_id)
|
|||||||
if (ALS_EN & activestatus)
|
if (ALS_EN & activestatus)
|
||||||
sensor_id[num_of_sensors++] = als_idx;
|
sensor_id[num_of_sensors++] = als_idx;
|
||||||
|
|
||||||
|
if (HPD_EN & activestatus)
|
||||||
|
sensor_id[num_of_sensors++] = HPD_IDX;
|
||||||
|
|
||||||
return num_of_sensors;
|
return num_of_sensors;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void amd_mp2_pci_remove(void *privdata)
|
static void amd_mp2_pci_remove(void *privdata)
|
||||||
{
|
{
|
||||||
|
struct amd_mp2_dev *mp2 = privdata;
|
||||||
amd_sfh_hid_client_deinit(privdata);
|
amd_sfh_hid_client_deinit(privdata);
|
||||||
amd_stop_all_sensors(privdata);
|
mp2->mp2_ops->stop_all(mp2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct amd_mp2_ops amd_sfh_ops_v2 = {
|
||||||
|
.start = amd_start_sensor_v2,
|
||||||
|
.stop = amd_stop_sensor_v2,
|
||||||
|
.stop_all = amd_stop_all_sensor_v2,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct amd_mp2_ops amd_sfh_ops = {
|
||||||
|
.start = amd_start_sensor,
|
||||||
|
.stop = amd_stop_sensor,
|
||||||
|
.stop_all = amd_stop_all_sensors,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void mp2_select_ops(struct amd_mp2_dev *privdata)
|
||||||
|
{
|
||||||
|
u8 acs;
|
||||||
|
|
||||||
|
privdata->mp2_acs = readl(privdata->mmio + AMD_P2C_MSG3);
|
||||||
|
acs = privdata->mp2_acs & GENMASK(3, 0);
|
||||||
|
|
||||||
|
switch (acs) {
|
||||||
|
case V2_STATUS:
|
||||||
|
privdata->mp2_ops = &amd_sfh_ops_v2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
privdata->mp2_ops = &amd_sfh_ops;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||||
@ -160,10 +234,17 @@ static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
|
|||||||
rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
|
rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
privdata->cl_data = devm_kzalloc(&pdev->dev, sizeof(struct amdtp_cl_data), GFP_KERNEL);
|
||||||
|
if (!privdata->cl_data)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
rc = devm_add_action_or_reset(&pdev->dev, amd_mp2_pci_remove, privdata);
|
rc = devm_add_action_or_reset(&pdev->dev, amd_mp2_pci_remove, privdata);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
|
mp2_select_ops(privdata);
|
||||||
|
|
||||||
return amd_sfh_hid_client_init(privdata);
|
return amd_sfh_hid_client_init(privdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#define PCIE_MP2_AMD_H
|
#define PCIE_MP2_AMD_H
|
||||||
|
|
||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
|
#include "amd_sfh_hid.h"
|
||||||
|
|
||||||
#define PCI_DEVICE_ID_AMD_MP2 0x15E4
|
#define PCI_DEVICE_ID_AMD_MP2 0x15E4
|
||||||
|
|
||||||
@ -22,9 +23,15 @@
|
|||||||
#define AMD_C2P_MSG1 0x10504
|
#define AMD_C2P_MSG1 0x10504
|
||||||
#define AMD_C2P_MSG2 0x10508
|
#define AMD_C2P_MSG2 0x10508
|
||||||
|
|
||||||
|
#define AMD_C2P_MSG(regno) (0x10500 + ((regno) * 4))
|
||||||
|
|
||||||
/* MP2 P2C Message Registers */
|
/* MP2 P2C Message Registers */
|
||||||
#define AMD_P2C_MSG3 0x1068C /* Supported Sensors info */
|
#define AMD_P2C_MSG3 0x1068C /* Supported Sensors info */
|
||||||
|
|
||||||
|
#define V2_STATUS 0x2
|
||||||
|
|
||||||
|
#define HPD_IDX 16
|
||||||
|
|
||||||
/* SFH Command register */
|
/* SFH Command register */
|
||||||
union sfh_cmd_base {
|
union sfh_cmd_base {
|
||||||
u32 ul;
|
u32 ul;
|
||||||
@ -33,6 +40,15 @@ union sfh_cmd_base {
|
|||||||
u32 sensor_id : 8;
|
u32 sensor_id : 8;
|
||||||
u32 period : 16;
|
u32 period : 16;
|
||||||
} s;
|
} s;
|
||||||
|
struct {
|
||||||
|
u32 cmd_id : 4;
|
||||||
|
u32 intr_enable : 1;
|
||||||
|
u32 rsvd1 : 3;
|
||||||
|
u32 length : 7;
|
||||||
|
u32 mem_type : 1;
|
||||||
|
u32 sensor_id : 8;
|
||||||
|
u32 period : 8;
|
||||||
|
} cmd_v2;
|
||||||
};
|
};
|
||||||
|
|
||||||
union sfh_cmd_param {
|
union sfh_cmd_param {
|
||||||
@ -61,6 +77,10 @@ struct amd_mp2_dev {
|
|||||||
struct pci_dev *pdev;
|
struct pci_dev *pdev;
|
||||||
struct amdtp_cl_data *cl_data;
|
struct amdtp_cl_data *cl_data;
|
||||||
void __iomem *mmio;
|
void __iomem *mmio;
|
||||||
|
const struct amd_mp2_ops *mp2_ops;
|
||||||
|
struct amd_input_data in_data;
|
||||||
|
/* mp2 active control status */
|
||||||
|
u32 mp2_acs;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct amd_mp2_sensor_info {
|
struct amd_mp2_sensor_info {
|
||||||
@ -69,10 +89,33 @@ struct amd_mp2_sensor_info {
|
|||||||
dma_addr_t dma_address;
|
dma_addr_t dma_address;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum mem_use_type {
|
||||||
|
USE_DRAM,
|
||||||
|
USE_C2P_REG,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct hpd_status {
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
u32 human_presence_report : 4;
|
||||||
|
u32 human_presence_actual : 4;
|
||||||
|
u32 probablity : 8;
|
||||||
|
u32 object_distance : 16;
|
||||||
|
} shpd;
|
||||||
|
u32 val;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
void amd_start_sensor(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info);
|
void amd_start_sensor(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info);
|
||||||
void amd_stop_sensor(struct amd_mp2_dev *privdata, u16 sensor_idx);
|
void amd_stop_sensor(struct amd_mp2_dev *privdata, u16 sensor_idx);
|
||||||
void amd_stop_all_sensors(struct amd_mp2_dev *privdata);
|
void amd_stop_all_sensors(struct amd_mp2_dev *privdata);
|
||||||
int amd_mp2_get_sensor_num(struct amd_mp2_dev *privdata, u8 *sensor_id);
|
int amd_mp2_get_sensor_num(struct amd_mp2_dev *privdata, u8 *sensor_id);
|
||||||
int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata);
|
int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata);
|
||||||
int amd_sfh_hid_client_deinit(struct amd_mp2_dev *privdata);
|
int amd_sfh_hid_client_deinit(struct amd_mp2_dev *privdata);
|
||||||
|
|
||||||
|
struct amd_mp2_ops {
|
||||||
|
void (*start)(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info);
|
||||||
|
void (*stop)(struct amd_mp2_dev *privdata, u16 sensor_idx);
|
||||||
|
void (*stop_all)(struct amd_mp2_dev *privdata);
|
||||||
|
};
|
||||||
#endif
|
#endif
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "amd_sfh_pcie.h"
|
#include "amd_sfh_pcie.h"
|
||||||
#include "amd_sfh_hid_desc.h"
|
#include "amd_sfh_hid_desc.h"
|
||||||
#include "amd_sfh_hid_report_desc.h"
|
#include "amd_sfh_hid_report_desc.h"
|
||||||
|
#include "amd_sfh_hid.h"
|
||||||
|
|
||||||
#define AMD_SFH_FW_MULTIPLIER (1000)
|
#define AMD_SFH_FW_MULTIPLIER (1000)
|
||||||
#define HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM 0x41
|
#define HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM 0x41
|
||||||
@ -49,6 +50,11 @@ int get_report_descriptor(int sensor_idx, u8 *rep_desc)
|
|||||||
memcpy(rep_desc, als_report_descriptor,
|
memcpy(rep_desc, als_report_descriptor,
|
||||||
sizeof(als_report_descriptor));
|
sizeof(als_report_descriptor));
|
||||||
break;
|
break;
|
||||||
|
case HPD_IDX: /* HPD sensor */
|
||||||
|
memset(rep_desc, 0, sizeof(hpd_report_descriptor));
|
||||||
|
memcpy(rep_desc, hpd_report_descriptor,
|
||||||
|
sizeof(hpd_report_descriptor));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -98,6 +104,17 @@ u32 get_descr_sz(int sensor_idx, int descriptor_name)
|
|||||||
return sizeof(struct als_feature_report);
|
return sizeof(struct als_feature_report);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case HPD_IDX:
|
||||||
|
switch (descriptor_name) {
|
||||||
|
case descr_size:
|
||||||
|
return sizeof(hpd_report_descriptor);
|
||||||
|
case input_size:
|
||||||
|
return sizeof(struct hpd_input_report);
|
||||||
|
case feature_size:
|
||||||
|
return sizeof(struct hpd_feature_report);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -119,6 +136,7 @@ u8 get_feature_report(int sensor_idx, int report_id, u8 *feature_report)
|
|||||||
struct accel3_feature_report acc_feature;
|
struct accel3_feature_report acc_feature;
|
||||||
struct gyro_feature_report gyro_feature;
|
struct gyro_feature_report gyro_feature;
|
||||||
struct magno_feature_report magno_feature;
|
struct magno_feature_report magno_feature;
|
||||||
|
struct hpd_feature_report hpd_feature;
|
||||||
struct als_feature_report als_feature;
|
struct als_feature_report als_feature;
|
||||||
u8 report_size = 0;
|
u8 report_size = 0;
|
||||||
|
|
||||||
@ -161,6 +179,12 @@ u8 get_feature_report(int sensor_idx, int report_id, u8 *feature_report)
|
|||||||
memcpy(feature_report, &als_feature, sizeof(als_feature));
|
memcpy(feature_report, &als_feature, sizeof(als_feature));
|
||||||
report_size = sizeof(als_feature);
|
report_size = sizeof(als_feature);
|
||||||
break;
|
break;
|
||||||
|
case HPD_IDX: /* human presence detection sensor */
|
||||||
|
get_common_features(&hpd_feature.common_property, report_id);
|
||||||
|
memcpy(feature_report, &hpd_feature, sizeof(hpd_feature));
|
||||||
|
report_size = sizeof(hpd_feature);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -174,12 +198,18 @@ static void get_common_inputs(struct common_input_property *common, int report_i
|
|||||||
common->event_type = HID_USAGE_SENSOR_EVENT_DATA_UPDATED_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)
|
u8 get_input_report(u8 current_index, int sensor_idx, int report_id, struct amd_input_data *in_data)
|
||||||
{
|
{
|
||||||
|
struct amd_mp2_dev *privdata = container_of(in_data, struct amd_mp2_dev, in_data);
|
||||||
|
u32 *sensor_virt_addr = in_data->sensor_virt_addr[current_index];
|
||||||
|
u8 *input_report = in_data->input_report[current_index];
|
||||||
|
u8 supported_input = privdata->mp2_acs & GENMASK(3, 0);
|
||||||
|
struct magno_input_report magno_input;
|
||||||
struct accel3_input_report acc_input;
|
struct accel3_input_report acc_input;
|
||||||
struct gyro_input_report gyro_input;
|
struct gyro_input_report gyro_input;
|
||||||
struct magno_input_report magno_input;
|
struct hpd_input_report hpd_input;
|
||||||
struct als_input_report als_input;
|
struct als_input_report als_input;
|
||||||
|
struct hpd_status hpdstatus;
|
||||||
u8 report_size = 0;
|
u8 report_size = 0;
|
||||||
|
|
||||||
if (!sensor_virt_addr || !input_report)
|
if (!sensor_virt_addr || !input_report)
|
||||||
@ -213,10 +243,22 @@ u8 get_input_report(int sensor_idx, int report_id, u8 *input_report, u32 *sensor
|
|||||||
break;
|
break;
|
||||||
case als_idx: /* Als */
|
case als_idx: /* Als */
|
||||||
get_common_inputs(&als_input.common_property, report_id);
|
get_common_inputs(&als_input.common_property, report_id);
|
||||||
als_input.illuminance_value = (int)sensor_virt_addr[0] / AMD_SFH_FW_MULTIPLIER;
|
/* For ALS ,V2 Platforms uses C2P_MSG5 register instead of DRAM access method */
|
||||||
|
if (supported_input == V2_STATUS)
|
||||||
|
als_input.illuminance_value = (int)readl(privdata->mmio + AMD_C2P_MSG(5));
|
||||||
|
else
|
||||||
|
als_input.illuminance_value =
|
||||||
|
(int)sensor_virt_addr[0] / AMD_SFH_FW_MULTIPLIER;
|
||||||
report_size = sizeof(als_input);
|
report_size = sizeof(als_input);
|
||||||
memcpy(input_report, &als_input, sizeof(als_input));
|
memcpy(input_report, &als_input, sizeof(als_input));
|
||||||
break;
|
break;
|
||||||
|
case HPD_IDX: /* hpd */
|
||||||
|
get_common_inputs(&hpd_input.common_property, report_id);
|
||||||
|
hpdstatus.val = readl(privdata->mmio + AMD_C2P_MSG(4));
|
||||||
|
hpd_input.human_presence = hpdstatus.shpd.human_presence_actual;
|
||||||
|
report_size = sizeof(hpd_input);
|
||||||
|
memcpy(input_report, &hpd_input, sizeof(hpd_input));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -100,8 +100,17 @@ struct als_input_report {
|
|||||||
int illuminance_value;
|
int illuminance_value;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
|
struct hpd_feature_report {
|
||||||
|
struct common_feature_property common_property;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
struct hpd_input_report {
|
||||||
|
struct common_input_property common_property;
|
||||||
|
/* values specific to human presence sensor */
|
||||||
|
u8 human_presence;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
int get_report_descriptor(int sensor_idx, u8 rep_desc[]);
|
int get_report_descriptor(int sensor_idx, u8 rep_desc[]);
|
||||||
u32 get_descr_sz(int sensor_idx, int descriptor_name);
|
u32 get_descr_sz(int sensor_idx, int descriptor_name);
|
||||||
u8 get_feature_report(int sensor_idx, int report_id, u8 *feature_report);
|
u8 get_feature_report(int sensor_idx, int report_id, u8 *feature_report);
|
||||||
u8 get_input_report(int sensor_idx, int report_id, u8 *input_report, u32 *sensor_virt_addr);
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -642,4 +642,116 @@ const u8 als_report_descriptor[] = {
|
|||||||
0X81, 0x02, /* HID Input (Data_Arr_Abs) */
|
0X81, 0x02, /* HID Input (Data_Arr_Abs) */
|
||||||
0xC0 /* HID end collection */
|
0xC0 /* HID end collection */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* BIOMETRIC PRESENCE*/
|
||||||
|
static const u8 hpd_report_descriptor[] = {
|
||||||
|
0x05, 0x20, /* Usage page */
|
||||||
|
0x09, 0x11, /* BIOMETRIC PRESENCE */
|
||||||
|
0xA1, 0x00, /* HID Collection (Physical) */
|
||||||
|
|
||||||
|
//feature reports(xmit/receive)
|
||||||
|
0x85, 5, /* HID Report ID */
|
||||||
|
0x05, 0x20, /* HID usage page sensor */
|
||||||
|
0x0A, 0x09, 0x03, /* Sensor property and sensor connection type */
|
||||||
|
0x15, 0, /* HID logical MIN_8(0) */
|
||||||
|
0x25, 2, /* HID logical MAX_8(2) */
|
||||||
|
0x75, 8, /* HID report size(8) */
|
||||||
|
0x95, 1, /* HID report count(1) */
|
||||||
|
0xA1, 0x02, /* HID collection (logical) */
|
||||||
|
0x0A, 0x30, 0x08, /* Sensor property connection type intergated sel*/
|
||||||
|
0x0A, 0x31, 0x08, /* Sensor property connection type attached sel */
|
||||||
|
0x0A, 0x32, 0x08, /* Sensor property connection type external sel */
|
||||||
|
0xB1, 0x00, /* HID feature (Data_Arr_Abs) */
|
||||||
|
0xC0, /* HID end collection */
|
||||||
|
0x0A, 0x16, 0x03, /* HID usage sensor property reporting state */
|
||||||
|
0x15, 0, /* HID logical Min_8(0) */
|
||||||
|
0x25, 5, /* HID logical Max_8(5) */
|
||||||
|
0x75, 8, /* HID report size(8) */
|
||||||
|
0x95, 1, /* HID report count(1) */
|
||||||
|
0xA1, 0x02, /* HID collection(logical) */
|
||||||
|
0x0A, 0x40, 0x08, /* Sensor property report state no events sel */
|
||||||
|
0x0A, 0x41, 0x08, /* Sensor property report state all events sel */
|
||||||
|
0x0A, 0x42, 0x08, /* Sensor property report state threshold events sel */
|
||||||
|
0x0A, 0x43, 0x08, /* Sensor property report state no events wake sel */
|
||||||
|
0x0A, 0x44, 0x08, /* Sensor property report state all events wake sel */
|
||||||
|
0x0A, 0x45, 0x08, /* Sensor property report state threshold events wake sel */
|
||||||
|
0xB1, 0x00, /* HID feature (Data_Arr_Abs) */
|
||||||
|
0xC0, /* HID end collection */
|
||||||
|
0x0A, 0x19, 0x03, /* HID usage sensor property power state */
|
||||||
|
0x15, 0, /* HID logical Min_8(0) */
|
||||||
|
0x25, 5, /* HID logical Max_8(5) */
|
||||||
|
0x75, 8, /* HID report size(8) */
|
||||||
|
0x95, 1, /* HID report count(1) */
|
||||||
|
0xA1, 0x02, /* HID collection(logical) */
|
||||||
|
0x0A, 0x50, 0x08, /* Sensor property power state undefined sel */
|
||||||
|
0x0A, 0x51, 0x08, /* Sensor property power state D0 full power sel */
|
||||||
|
0x0A, 0x52, 0x08, /* Sensor property power state D1 low power sel */
|
||||||
|
0x0A, 0x53, 0x08, /* Sensor property power state D2 standby with wake sel */
|
||||||
|
0x0A, 0x54, 0x08, /* Sensor property power state D3 sleep with wake sel */
|
||||||
|
0x0A, 0x55, 0x08, /* Sensor property power state D4 power off sel */
|
||||||
|
0xB1, 0x00, /* HID feature (Data_Arr_Abs) */
|
||||||
|
0xC0, /* HID end collection */
|
||||||
|
0x0A, 0x01, 0x02, /* HID usage sensor state */
|
||||||
|
0x15, 0, /* HID logical Min_8(0) */
|
||||||
|
0x25, 6, /* HID logical Max_8(6) */
|
||||||
|
0x75, 8, /* HID report size(8) */
|
||||||
|
0x95, 1, /* HID report count(1) */
|
||||||
|
0xA1, 0x02, /* HID collection(logical) */
|
||||||
|
0x0A, 0x00, 0x08, /* HID usage sensor state unknown sel */
|
||||||
|
0x0A, 0x01, 0x08, /* HID usage sensor state ready sel */
|
||||||
|
0x0A, 0x02, 0x08, /* HID usage sensor state not available sel */
|
||||||
|
0x0A, 0x03, 0x08, /* HID usage sensor state no data sel */
|
||||||
|
0x0A, 0x04, 0x08, /* HID usage sensor state initializing sel */
|
||||||
|
0x0A, 0x05, 0x08, /* HID usage sensor state access denied sel */
|
||||||
|
0x0A, 0x06, 0x08, /* HID usage sensor state error sel */
|
||||||
|
0xB1, 0x00, /* HID feature (Data_Arr_Abs) */
|
||||||
|
0xC0, /* HID end collection */
|
||||||
|
0x0A, 0x0E, 0x03, /* HID usage sensor property report interval */
|
||||||
|
0x15, 0, /* HID logical Min_8(0) */
|
||||||
|
0x27, 0xFF, 0xFF, 0xFF, 0xFF, /* HID logical Max_32 */
|
||||||
|
|
||||||
|
0x75, 32, /* HID report size(32) */
|
||||||
|
0x95, 1, /* HID report count(1) */
|
||||||
|
0x55, 0, /* HID unit exponent(0) */
|
||||||
|
0xB1, 0x02, /* HID feature (Data_Var_Abs) */
|
||||||
|
|
||||||
|
//input report (transmit)
|
||||||
|
0x05, 0x20, /* HID usage page sensors */
|
||||||
|
0x0A, 0x01, 0x02, /* HID usage sensor state */
|
||||||
|
0x15, 0, /* HID logical Min_8(0) */
|
||||||
|
0x25, 6, /* HID logical Max_8(6) */
|
||||||
|
0x75, 8, /* HID report size(8) */
|
||||||
|
0x95, 1, /* HID report count (1) */
|
||||||
|
0xA1, 0x02, /* HID end collection (logical) */
|
||||||
|
0x0A, 0x00, 0x08, /* HID usage sensor state unknown sel */
|
||||||
|
0x0A, 0x01, 0x08, /* HID usage sensor state ready sel */
|
||||||
|
0x0A, 0x02, 0x08, /* HID usage sensor state not available sel */
|
||||||
|
0x0A, 0x03, 0x08, /* HID usage sensor state no data sel */
|
||||||
|
0x0A, 0x04, 0x08, /* HID usage sensor state initializing sel */
|
||||||
|
0x0A, 0x05, 0x08, /* HID usage sensor state access denied sel */
|
||||||
|
0x0A, 0x06, 0x08, /* HID usage sensor state error sel */
|
||||||
|
0X81, 0x00, /* HID Input (Data_Arr_Abs) */
|
||||||
|
0xC0, /* HID end collection */
|
||||||
|
0x0A, 0x02, 0x02, /* HID usage sensor event */
|
||||||
|
0x15, 0, /* HID logical Min_8(0) */
|
||||||
|
0x25, 5, /* HID logical Max_8(5) */
|
||||||
|
0x75, 8, /* HID report size(8) */
|
||||||
|
0x95, 1, /* HID report count (1) */
|
||||||
|
0xA1, 0x02, /* HID end collection (logical) */
|
||||||
|
0x0A, 0x10, 0x08, /* HID usage sensor event unknown sel */
|
||||||
|
0x0A, 0x11, 0x08, /* HID usage sensor event state changed sel */
|
||||||
|
0x0A, 0x12, 0x08, /* HID usage sensor event property changed sel */
|
||||||
|
0x0A, 0x13, 0x08, /* HID usage sensor event data updated sel */
|
||||||
|
0x0A, 0x14, 0x08, /* HID usage sensor event poll response sel */
|
||||||
|
0x0A, 0x15, 0x08, /* HID usage sensor event change sensitivity sel */
|
||||||
|
0X81, 0x00, /* HID Input (Data_Arr_Abs) */
|
||||||
|
0xC0, /* HID end collection */
|
||||||
|
0x0A, 0xB1, 0x04, /* HID usage sensor data BIOMETRIC HUMAN PRESENCE */
|
||||||
|
0x15, 0, /* HID logical Min_8(0) */
|
||||||
|
0x25, 1, /* HID logical Max_8(1) */
|
||||||
|
0x75, 8, /* HID report size(8) */
|
||||||
|
0x95, 1, /* HID report count (1) */
|
||||||
|
0X81, 0x02, /* HID Input (Data_Var_Abs) */
|
||||||
|
0xC0 /* HID end collection */
|
||||||
|
};
|
||||||
#endif
|
#endif
|
||||||
|
@ -2306,12 +2306,8 @@ static int hid_device_remove(struct device *dev)
|
|||||||
{
|
{
|
||||||
struct hid_device *hdev = to_hid_device(dev);
|
struct hid_device *hdev = to_hid_device(dev);
|
||||||
struct hid_driver *hdrv;
|
struct hid_driver *hdrv;
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
if (down_interruptible(&hdev->driver_input_lock)) {
|
down(&hdev->driver_input_lock);
|
||||||
ret = -EINTR;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
hdev->io_started = false;
|
hdev->io_started = false;
|
||||||
|
|
||||||
hdrv = hdev->driver;
|
hdrv = hdev->driver;
|
||||||
@ -2326,8 +2322,8 @@ static int hid_device_remove(struct device *dev)
|
|||||||
|
|
||||||
if (!hdev->io_started)
|
if (!hdev->io_started)
|
||||||
up(&hdev->driver_input_lock);
|
up(&hdev->driver_input_lock);
|
||||||
end:
|
|
||||||
return ret;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
|
static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
|
||||||
|
@ -122,6 +122,7 @@ static const struct hid_usage_entry hid_usage_table[] = {
|
|||||||
{ 9, 0, "Button" },
|
{ 9, 0, "Button" },
|
||||||
{ 10, 0, "Ordinal" },
|
{ 10, 0, "Ordinal" },
|
||||||
{ 12, 0, "Consumer" },
|
{ 12, 0, "Consumer" },
|
||||||
|
{0, 0x003, "ProgrammableButtons"},
|
||||||
{0, 0x238, "HorizontalWheel"},
|
{0, 0x238, "HorizontalWheel"},
|
||||||
{ 13, 0, "Digitizers" },
|
{ 13, 0, "Digitizers" },
|
||||||
{0, 0x01, "Digitizer"},
|
{0, 0x01, "Digitizer"},
|
||||||
@ -942,6 +943,16 @@ static const char *keys[KEY_MAX + 1] = {
|
|||||||
[KEY_KBDINPUTASSIST_NEXTGROUP] = "KbdInputAssistNextGroup",
|
[KEY_KBDINPUTASSIST_NEXTGROUP] = "KbdInputAssistNextGroup",
|
||||||
[KEY_KBDINPUTASSIST_ACCEPT] = "KbdInputAssistAccept",
|
[KEY_KBDINPUTASSIST_ACCEPT] = "KbdInputAssistAccept",
|
||||||
[KEY_KBDINPUTASSIST_CANCEL] = "KbdInputAssistCancel",
|
[KEY_KBDINPUTASSIST_CANCEL] = "KbdInputAssistCancel",
|
||||||
|
[KEY_MACRO1] = "Macro1", [KEY_MACRO2] = "Macro2", [KEY_MACRO3] = "Macro3",
|
||||||
|
[KEY_MACRO4] = "Macro4", [KEY_MACRO5] = "Macro5", [KEY_MACRO6] = "Macro6",
|
||||||
|
[KEY_MACRO7] = "Macro7", [KEY_MACRO8] = "Macro8", [KEY_MACRO9] = "Macro9",
|
||||||
|
[KEY_MACRO10] = "Macro10", [KEY_MACRO11] = "Macro11", [KEY_MACRO12] = "Macro12",
|
||||||
|
[KEY_MACRO13] = "Macro13", [KEY_MACRO14] = "Macro14", [KEY_MACRO15] = "Macro15",
|
||||||
|
[KEY_MACRO16] = "Macro16", [KEY_MACRO17] = "Macro17", [KEY_MACRO18] = "Macro18",
|
||||||
|
[KEY_MACRO19] = "Macro19", [KEY_MACRO20] = "Macro20", [KEY_MACRO21] = "Macro21",
|
||||||
|
[KEY_MACRO22] = "Macro22", [KEY_MACRO23] = "Macro23", [KEY_MACRO24] = "Macro24",
|
||||||
|
[KEY_MACRO25] = "Macro25", [KEY_MACRO26] = "Macro26", [KEY_MACRO27] = "Macro27",
|
||||||
|
[KEY_MACRO28] = "Macro28", [KEY_MACRO29] = "Macro29", [KEY_MACRO30] = "Macro30",
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *relatives[REL_MAX + 1] = {
|
static const char *relatives[REL_MAX + 1] = {
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include <linux/hid.h>
|
#include <linux/hid.h>
|
||||||
#include <linux/leds.h>
|
#include <linux/leds.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
#include <linux/of.h>
|
||||||
#include <linux/platform_data/cros_ec_commands.h>
|
#include <linux/platform_data/cros_ec_commands.h>
|
||||||
#include <linux/platform_data/cros_ec_proto.h>
|
#include <linux/platform_data/cros_ec_proto.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
@ -272,12 +273,21 @@ static const struct acpi_device_id cbas_ec_acpi_ids[] = {
|
|||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(acpi, cbas_ec_acpi_ids);
|
MODULE_DEVICE_TABLE(acpi, cbas_ec_acpi_ids);
|
||||||
|
|
||||||
|
#ifdef CONFIG_OF
|
||||||
|
static const struct of_device_id cbas_ec_of_match[] = {
|
||||||
|
{ .compatible = "google,cros-cbas" },
|
||||||
|
{ },
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, cbas_ec_of_match);
|
||||||
|
#endif
|
||||||
|
|
||||||
static struct platform_driver cbas_ec_driver = {
|
static struct platform_driver cbas_ec_driver = {
|
||||||
.probe = cbas_ec_probe,
|
.probe = cbas_ec_probe,
|
||||||
.remove = cbas_ec_remove,
|
.remove = cbas_ec_remove,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "cbas_ec",
|
.name = "cbas_ec",
|
||||||
.acpi_match_table = ACPI_PTR(cbas_ec_acpi_ids),
|
.acpi_match_table = ACPI_PTR(cbas_ec_acpi_ids),
|
||||||
|
.of_match_table = of_match_ptr(cbas_ec_of_match),
|
||||||
.pm = &cbas_ec_pm_ops,
|
.pm = &cbas_ec_pm_ops,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -396,6 +396,7 @@
|
|||||||
#define USB_DEVICE_ID_HP_X2_10_COVER 0x0755
|
#define USB_DEVICE_ID_HP_X2_10_COVER 0x0755
|
||||||
#define I2C_DEVICE_ID_HP_SPECTRE_X360_15 0x2817
|
#define I2C_DEVICE_ID_HP_SPECTRE_X360_15 0x2817
|
||||||
#define USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN 0x2706
|
#define USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN 0x2706
|
||||||
|
#define I2C_DEVICE_ID_SURFACE_GO_TOUCHSCREEN 0x261A
|
||||||
|
|
||||||
#define USB_VENDOR_ID_ELECOM 0x056e
|
#define USB_VENDOR_ID_ELECOM 0x056e
|
||||||
#define USB_DEVICE_ID_ELECOM_BM084 0x0061
|
#define USB_DEVICE_ID_ELECOM_BM084 0x0061
|
||||||
@ -763,6 +764,7 @@
|
|||||||
#define I2C_DEVICE_ID_LG_7010 0x7010
|
#define I2C_DEVICE_ID_LG_7010 0x7010
|
||||||
|
|
||||||
#define USB_VENDOR_ID_LOGITECH 0x046d
|
#define USB_VENDOR_ID_LOGITECH 0x046d
|
||||||
|
#define USB_DEVICE_ID_LOGITECH_Z_10_SPK 0x0a07
|
||||||
#define USB_DEVICE_ID_LOGITECH_AUDIOHUB 0x0a0e
|
#define USB_DEVICE_ID_LOGITECH_AUDIOHUB 0x0a0e
|
||||||
#define USB_DEVICE_ID_LOGITECH_T651 0xb00c
|
#define USB_DEVICE_ID_LOGITECH_T651 0xb00c
|
||||||
#define USB_DEVICE_ID_LOGITECH_DINOVO_EDGE_KBD 0xb309
|
#define USB_DEVICE_ID_LOGITECH_DINOVO_EDGE_KBD 0xb309
|
||||||
|
@ -326,6 +326,8 @@ static const struct hid_device_id hid_battery_quirks[] = {
|
|||||||
HID_BATTERY_QUIRK_IGNORE },
|
HID_BATTERY_QUIRK_IGNORE },
|
||||||
{ HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_SPECTRE_X360_15),
|
{ HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_SPECTRE_X360_15),
|
||||||
HID_BATTERY_QUIRK_IGNORE },
|
HID_BATTERY_QUIRK_IGNORE },
|
||||||
|
{ HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_SURFACE_GO_TOUCHSCREEN),
|
||||||
|
HID_BATTERY_QUIRK_IGNORE },
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -567,6 +569,16 @@ static void hidinput_update_battery(struct hid_device *dev, int value)
|
|||||||
}
|
}
|
||||||
#endif /* CONFIG_HID_BATTERY_STRENGTH */
|
#endif /* CONFIG_HID_BATTERY_STRENGTH */
|
||||||
|
|
||||||
|
static bool hidinput_field_in_collection(struct hid_device *device, struct hid_field *field,
|
||||||
|
unsigned int type, unsigned int usage)
|
||||||
|
{
|
||||||
|
struct hid_collection *collection;
|
||||||
|
|
||||||
|
collection = &device->collection[field->usage->collection_index];
|
||||||
|
|
||||||
|
return collection->type == type && collection->usage == usage;
|
||||||
|
}
|
||||||
|
|
||||||
static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field,
|
static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field,
|
||||||
struct hid_usage *usage)
|
struct hid_usage *usage)
|
||||||
{
|
{
|
||||||
@ -632,6 +644,18 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
|||||||
else
|
else
|
||||||
code += BTN_TRIGGER_HAPPY - 0x10;
|
code += BTN_TRIGGER_HAPPY - 0x10;
|
||||||
break;
|
break;
|
||||||
|
case HID_CP_CONSUMER_CONTROL:
|
||||||
|
if (hidinput_field_in_collection(device, field,
|
||||||
|
HID_COLLECTION_NAMED_ARRAY,
|
||||||
|
HID_CP_PROGRAMMABLEBUTTONS)) {
|
||||||
|
if (code <= 0x1d)
|
||||||
|
code += KEY_MACRO1;
|
||||||
|
else
|
||||||
|
code += BTN_TRIGGER_HAPPY - 0x1e;
|
||||||
|
} else {
|
||||||
|
goto ignore;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
switch (field->physical) {
|
switch (field->physical) {
|
||||||
case HID_GD_MOUSE:
|
case HID_GD_MOUSE:
|
||||||
@ -1316,12 +1340,12 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (usage->hid == (HID_UP_DIGITIZER | 0x003c)) { /* Invert */
|
if (usage->hid == HID_DG_INVERT) {
|
||||||
*quirks = value ? (*quirks | HID_QUIRK_INVERT) : (*quirks & ~HID_QUIRK_INVERT);
|
*quirks = value ? (*quirks | HID_QUIRK_INVERT) : (*quirks & ~HID_QUIRK_INVERT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (usage->hid == (HID_UP_DIGITIZER | 0x0032)) { /* InRange */
|
if (usage->hid == HID_DG_INRANGE) {
|
||||||
if (value) {
|
if (value) {
|
||||||
input_event(input, usage->type, (*quirks & HID_QUIRK_INVERT) ? BTN_TOOL_RUBBER : usage->code, 1);
|
input_event(input, usage->type, (*quirks & HID_QUIRK_INVERT) ? BTN_TOOL_RUBBER : usage->code, 1);
|
||||||
return;
|
return;
|
||||||
@ -1331,7 +1355,7 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (usage->hid == (HID_UP_DIGITIZER | 0x0030) && (*quirks & HID_QUIRK_NOTOUCH)) { /* Pressure */
|
if (usage->hid == HID_DG_TIPPRESSURE && (*quirks & HID_QUIRK_NOTOUCH)) {
|
||||||
int a = field->logical_minimum;
|
int a = field->logical_minimum;
|
||||||
int b = field->logical_maximum;
|
int b = field->logical_maximum;
|
||||||
input_event(input, EV_KEY, BTN_TOUCH, value > a + ((b - a) >> 3));
|
input_event(input, EV_KEY, BTN_TOUCH, value > a + ((b - a) >> 3));
|
||||||
|
@ -135,4 +135,5 @@ static struct hid_driver ite_driver = {
|
|||||||
};
|
};
|
||||||
module_hid_driver(ite_driver);
|
module_hid_driver(ite_driver);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
@ -28,6 +28,7 @@ enum lg_g15_model {
|
|||||||
LG_G15_V2,
|
LG_G15_V2,
|
||||||
LG_G510,
|
LG_G510,
|
||||||
LG_G510_USB_AUDIO,
|
LG_G510_USB_AUDIO,
|
||||||
|
LG_Z10,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum lg_g15_led_type {
|
enum lg_g15_led_type {
|
||||||
@ -457,6 +458,13 @@ static int lg_g15_get_initial_led_brightness(struct lg_g15_data *g15)
|
|||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
return lg_g510_update_mkey_led_brightness(g15);
|
return lg_g510_update_mkey_led_brightness(g15);
|
||||||
|
case LG_Z10:
|
||||||
|
/*
|
||||||
|
* Getting the LCD backlight brightness is not supported.
|
||||||
|
* Reading Feature(2) fails with -EPIPE and this crashes
|
||||||
|
* the LCD and touch keys part of the speakers.
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
return -EINVAL; /* Never reached */
|
return -EINVAL; /* Never reached */
|
||||||
}
|
}
|
||||||
@ -464,7 +472,20 @@ static int lg_g15_get_initial_led_brightness(struct lg_g15_data *g15)
|
|||||||
/******** Input functions ********/
|
/******** Input functions ********/
|
||||||
|
|
||||||
/* On the G15 Mark I Logitech has been quite creative with which bit is what */
|
/* On the G15 Mark I Logitech has been quite creative with which bit is what */
|
||||||
static int lg_g15_event(struct lg_g15_data *g15, u8 *data, int size)
|
static void lg_g15_handle_lcd_menu_keys(struct lg_g15_data *g15, u8 *data)
|
||||||
|
{
|
||||||
|
int i, val;
|
||||||
|
|
||||||
|
/* Most left (round/display) button below the LCD */
|
||||||
|
input_report_key(g15->input, KEY_KBD_LCD_MENU1, data[8] & 0x80);
|
||||||
|
/* 4 other buttons below the LCD */
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
val = data[i + 2] & 0x80;
|
||||||
|
input_report_key(g15->input, KEY_KBD_LCD_MENU2 + i, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lg_g15_event(struct lg_g15_data *g15, u8 *data)
|
||||||
{
|
{
|
||||||
int i, val;
|
int i, val;
|
||||||
|
|
||||||
@ -494,13 +515,7 @@ static int lg_g15_event(struct lg_g15_data *g15, u8 *data, int size)
|
|||||||
/* MR */
|
/* MR */
|
||||||
input_report_key(g15->input, KEY_MACRO_RECORD_START, data[7] & 0x40);
|
input_report_key(g15->input, KEY_MACRO_RECORD_START, data[7] & 0x40);
|
||||||
|
|
||||||
/* Most left (round) button below the LCD */
|
lg_g15_handle_lcd_menu_keys(g15, data);
|
||||||
input_report_key(g15->input, KEY_KBD_LCD_MENU1, data[8] & 0x80);
|
|
||||||
/* 4 other buttons below the LCD */
|
|
||||||
for (i = 0; i < 4; i++) {
|
|
||||||
val = data[i + 2] & 0x80;
|
|
||||||
input_report_key(g15->input, KEY_KBD_LCD_MENU2 + i, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Backlight cycle button pressed? */
|
/* Backlight cycle button pressed? */
|
||||||
if (data[1] & 0x80)
|
if (data[1] & 0x80)
|
||||||
@ -510,7 +525,7 @@ static int lg_g15_event(struct lg_g15_data *g15, u8 *data, int size)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lg_g15_v2_event(struct lg_g15_data *g15, u8 *data, int size)
|
static int lg_g15_v2_event(struct lg_g15_data *g15, u8 *data)
|
||||||
{
|
{
|
||||||
int i, val;
|
int i, val;
|
||||||
|
|
||||||
@ -542,7 +557,7 @@ static int lg_g15_v2_event(struct lg_g15_data *g15, u8 *data, int size)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lg_g510_event(struct lg_g15_data *g15, u8 *data, int size)
|
static int lg_g510_event(struct lg_g15_data *g15, u8 *data)
|
||||||
{
|
{
|
||||||
bool game_mode_enabled;
|
bool game_mode_enabled;
|
||||||
int i, val;
|
int i, val;
|
||||||
@ -586,7 +601,7 @@ static int lg_g510_event(struct lg_g15_data *g15, u8 *data, int size)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lg_g510_leds_event(struct lg_g15_data *g15, u8 *data, int size)
|
static int lg_g510_leds_event(struct lg_g15_data *g15, u8 *data)
|
||||||
{
|
{
|
||||||
bool backlight_disabled;
|
bool backlight_disabled;
|
||||||
|
|
||||||
@ -613,18 +628,24 @@ static int lg_g15_raw_event(struct hid_device *hdev, struct hid_report *report,
|
|||||||
switch (g15->model) {
|
switch (g15->model) {
|
||||||
case LG_G15:
|
case LG_G15:
|
||||||
if (data[0] == 0x02 && size == 9)
|
if (data[0] == 0x02 && size == 9)
|
||||||
return lg_g15_event(g15, data, size);
|
return lg_g15_event(g15, data);
|
||||||
break;
|
break;
|
||||||
case LG_G15_V2:
|
case LG_G15_V2:
|
||||||
if (data[0] == 0x02 && size == 5)
|
if (data[0] == 0x02 && size == 5)
|
||||||
return lg_g15_v2_event(g15, data, size);
|
return lg_g15_v2_event(g15, data);
|
||||||
|
break;
|
||||||
|
case LG_Z10:
|
||||||
|
if (data[0] == 0x02 && size == 9) {
|
||||||
|
lg_g15_handle_lcd_menu_keys(g15, data);
|
||||||
|
input_sync(g15->input);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case LG_G510:
|
case LG_G510:
|
||||||
case LG_G510_USB_AUDIO:
|
case LG_G510_USB_AUDIO:
|
||||||
if (data[0] == 0x03 && size == 5)
|
if (data[0] == 0x03 && size == 5)
|
||||||
return lg_g510_event(g15, data, size);
|
return lg_g510_event(g15, data);
|
||||||
if (data[0] == 0x04 && size == 2)
|
if (data[0] == 0x04 && size == 2)
|
||||||
return lg_g510_leds_event(g15, data, size);
|
return lg_g510_leds_event(g15, data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -645,25 +666,18 @@ static void lg_g15_input_close(struct input_dev *dev)
|
|||||||
hid_hw_close(hdev);
|
hid_hw_close(hdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lg_g15_register_led(struct lg_g15_data *g15, int i)
|
static int lg_g15_register_led(struct lg_g15_data *g15, int i, const char *name)
|
||||||
{
|
{
|
||||||
static const char * const led_names[] = {
|
|
||||||
"g15::kbd_backlight",
|
|
||||||
"g15::lcd_backlight",
|
|
||||||
"g15::macro_preset1",
|
|
||||||
"g15::macro_preset2",
|
|
||||||
"g15::macro_preset3",
|
|
||||||
"g15::macro_record",
|
|
||||||
};
|
|
||||||
|
|
||||||
g15->leds[i].led = i;
|
g15->leds[i].led = i;
|
||||||
g15->leds[i].cdev.name = led_names[i];
|
g15->leds[i].cdev.name = name;
|
||||||
|
|
||||||
switch (g15->model) {
|
switch (g15->model) {
|
||||||
case LG_G15:
|
case LG_G15:
|
||||||
case LG_G15_V2:
|
case LG_G15_V2:
|
||||||
g15->leds[i].cdev.brightness_set_blocking = lg_g15_led_set;
|
|
||||||
g15->leds[i].cdev.brightness_get = lg_g15_led_get;
|
g15->leds[i].cdev.brightness_get = lg_g15_led_get;
|
||||||
|
fallthrough;
|
||||||
|
case LG_Z10:
|
||||||
|
g15->leds[i].cdev.brightness_set_blocking = lg_g15_led_set;
|
||||||
if (i < LG_G15_BRIGHTNESS_MAX) {
|
if (i < LG_G15_BRIGHTNESS_MAX) {
|
||||||
g15->leds[i].cdev.flags = LED_BRIGHT_HW_CHANGED;
|
g15->leds[i].cdev.flags = LED_BRIGHT_HW_CHANGED;
|
||||||
g15->leds[i].cdev.max_brightness = 2;
|
g15->leds[i].cdev.max_brightness = 2;
|
||||||
@ -702,8 +716,38 @@ static int lg_g15_register_led(struct lg_g15_data *g15, int i)
|
|||||||
return devm_led_classdev_register(&g15->hdev->dev, &g15->leds[i].cdev);
|
return devm_led_classdev_register(&g15->hdev->dev, &g15->leds[i].cdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Common input device init code shared between keyboards and Z-10 speaker handling */
|
||||||
|
static void lg_g15_init_input_dev(struct hid_device *hdev, struct input_dev *input,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
input->name = name;
|
||||||
|
input->phys = hdev->phys;
|
||||||
|
input->uniq = hdev->uniq;
|
||||||
|
input->id.bustype = hdev->bus;
|
||||||
|
input->id.vendor = hdev->vendor;
|
||||||
|
input->id.product = hdev->product;
|
||||||
|
input->id.version = hdev->version;
|
||||||
|
input->dev.parent = &hdev->dev;
|
||||||
|
input->open = lg_g15_input_open;
|
||||||
|
input->close = lg_g15_input_close;
|
||||||
|
|
||||||
|
/* Keys below the LCD, intended for controlling a menu on the LCD */
|
||||||
|
for (i = 0; i < 5; i++)
|
||||||
|
input_set_capability(input, EV_KEY, KEY_KBD_LCD_MENU1 + i);
|
||||||
|
}
|
||||||
|
|
||||||
static int lg_g15_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
static int lg_g15_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||||
{
|
{
|
||||||
|
static const char * const led_names[] = {
|
||||||
|
"g15::kbd_backlight",
|
||||||
|
"g15::lcd_backlight",
|
||||||
|
"g15::macro_preset1",
|
||||||
|
"g15::macro_preset2",
|
||||||
|
"g15::macro_preset3",
|
||||||
|
"g15::macro_record",
|
||||||
|
};
|
||||||
u8 gkeys_settings_output_report = 0;
|
u8 gkeys_settings_output_report = 0;
|
||||||
u8 gkeys_settings_feature_report = 0;
|
u8 gkeys_settings_feature_report = 0;
|
||||||
struct hid_report_enum *rep_enum;
|
struct hid_report_enum *rep_enum;
|
||||||
@ -744,6 +788,8 @@ static int lg_g15_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||||||
|
|
||||||
g15->hdev = hdev;
|
g15->hdev = hdev;
|
||||||
g15->model = id->driver_data;
|
g15->model = id->driver_data;
|
||||||
|
g15->input = input;
|
||||||
|
input_set_drvdata(input, hdev);
|
||||||
hid_set_drvdata(hdev, (void *)g15);
|
hid_set_drvdata(hdev, (void *)g15);
|
||||||
|
|
||||||
switch (g15->model) {
|
switch (g15->model) {
|
||||||
@ -772,6 +818,9 @@ static int lg_g15_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||||||
gkeys_settings_feature_report = 0x01;
|
gkeys_settings_feature_report = 0x01;
|
||||||
gkeys = 18;
|
gkeys = 18;
|
||||||
break;
|
break;
|
||||||
|
case LG_Z10:
|
||||||
|
connect_mask = HID_CONNECT_HIDRAW;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = hid_hw_start(hdev, connect_mask);
|
ret = hid_hw_start(hdev, connect_mask);
|
||||||
@ -814,17 +863,21 @@ static int lg_g15_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||||||
if (ret)
|
if (ret)
|
||||||
goto error_hw_stop;
|
goto error_hw_stop;
|
||||||
|
|
||||||
|
if (g15->model == LG_Z10) {
|
||||||
|
lg_g15_init_input_dev(hdev, g15->input, "Logitech Z-10 LCD Menu Keys");
|
||||||
|
ret = input_register_device(g15->input);
|
||||||
|
if (ret)
|
||||||
|
goto error_hw_stop;
|
||||||
|
|
||||||
|
ret = lg_g15_register_led(g15, 1, "z-10::lcd_backlight");
|
||||||
|
if (ret)
|
||||||
|
goto error_hw_stop;
|
||||||
|
|
||||||
|
return 0; /* All done */
|
||||||
|
}
|
||||||
|
|
||||||
/* Setup and register input device */
|
/* Setup and register input device */
|
||||||
input->name = "Logitech Gaming Keyboard Gaming Keys";
|
lg_g15_init_input_dev(hdev, input, "Logitech Gaming Keyboard Gaming Keys");
|
||||||
input->phys = hdev->phys;
|
|
||||||
input->uniq = hdev->uniq;
|
|
||||||
input->id.bustype = hdev->bus;
|
|
||||||
input->id.vendor = hdev->vendor;
|
|
||||||
input->id.product = hdev->product;
|
|
||||||
input->id.version = hdev->version;
|
|
||||||
input->dev.parent = &hdev->dev;
|
|
||||||
input->open = lg_g15_input_open;
|
|
||||||
input->close = lg_g15_input_close;
|
|
||||||
|
|
||||||
/* G-keys */
|
/* G-keys */
|
||||||
for (i = 0; i < gkeys; i++)
|
for (i = 0; i < gkeys; i++)
|
||||||
@ -835,10 +888,6 @@ static int lg_g15_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||||||
input_set_capability(input, EV_KEY, KEY_MACRO_PRESET1 + i);
|
input_set_capability(input, EV_KEY, KEY_MACRO_PRESET1 + i);
|
||||||
input_set_capability(input, EV_KEY, KEY_MACRO_RECORD_START);
|
input_set_capability(input, EV_KEY, KEY_MACRO_RECORD_START);
|
||||||
|
|
||||||
/* Keys below the LCD, intended for controlling a menu on the LCD */
|
|
||||||
for (i = 0; i < 5; i++)
|
|
||||||
input_set_capability(input, EV_KEY, KEY_KBD_LCD_MENU1 + i);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* On the G510 only report headphone and mic mute keys when *not* using
|
* On the G510 only report headphone and mic mute keys when *not* using
|
||||||
* the builtin USB audio device. When the builtin audio is used these
|
* the builtin USB audio device. When the builtin audio is used these
|
||||||
@ -850,16 +899,13 @@ static int lg_g15_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||||||
input_set_capability(input, EV_KEY, KEY_F20);
|
input_set_capability(input, EV_KEY, KEY_F20);
|
||||||
}
|
}
|
||||||
|
|
||||||
g15->input = input;
|
|
||||||
input_set_drvdata(input, hdev);
|
|
||||||
|
|
||||||
ret = input_register_device(input);
|
ret = input_register_device(input);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto error_hw_stop;
|
goto error_hw_stop;
|
||||||
|
|
||||||
/* Register LED devices */
|
/* Register LED devices */
|
||||||
for (i = 0; i < LG_G15_LED_MAX; i++) {
|
for (i = 0; i < LG_G15_LED_MAX; i++) {
|
||||||
ret = lg_g15_register_led(g15, i);
|
ret = lg_g15_register_led(g15, i, led_names[i]);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto error_hw_stop;
|
goto error_hw_stop;
|
||||||
}
|
}
|
||||||
@ -890,6 +936,10 @@ static const struct hid_device_id lg_g15_devices[] = {
|
|||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
|
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
|
||||||
USB_DEVICE_ID_LOGITECH_G510_USB_AUDIO),
|
USB_DEVICE_ID_LOGITECH_G510_USB_AUDIO),
|
||||||
.driver_data = LG_G510_USB_AUDIO },
|
.driver_data = LG_G510_USB_AUDIO },
|
||||||
|
/* Z-10 speakers */
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
|
||||||
|
USB_DEVICE_ID_LOGITECH_Z_10_SPK),
|
||||||
|
.driver_data = LG_Z10 },
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(hid, lg_g15_devices);
|
MODULE_DEVICE_TABLE(hid, lg_g15_devices);
|
||||||
@ -902,4 +952,5 @@ static struct hid_driver lg_g15_driver = {
|
|||||||
};
|
};
|
||||||
module_hid_driver(lg_g15_driver);
|
module_hid_driver(lg_g15_driver);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
@ -100,6 +100,7 @@
|
|||||||
#define HIDPP_DEVICE_TYPE_MASK GENMASK(3, 0)
|
#define HIDPP_DEVICE_TYPE_MASK GENMASK(3, 0)
|
||||||
#define HIDPP_LINK_STATUS_MASK BIT(6)
|
#define HIDPP_LINK_STATUS_MASK BIT(6)
|
||||||
#define HIDPP_MANUFACTURER_MASK BIT(7)
|
#define HIDPP_MANUFACTURER_MASK BIT(7)
|
||||||
|
#define HIDPP_27MHZ_SECURE_MASK BIT(7)
|
||||||
|
|
||||||
#define HIDPP_DEVICE_TYPE_KEYBOARD 1
|
#define HIDPP_DEVICE_TYPE_KEYBOARD 1
|
||||||
#define HIDPP_DEVICE_TYPE_MOUSE 2
|
#define HIDPP_DEVICE_TYPE_MOUSE 2
|
||||||
@ -984,6 +985,13 @@ static void logi_hidpp_dev_conn_notif_27mhz(struct hid_device *hdev,
|
|||||||
workitem->reports_supported |= STD_MOUSE | HIDPP;
|
workitem->reports_supported |= STD_MOUSE | HIDPP;
|
||||||
break;
|
break;
|
||||||
case 3: /* Index 3 is always the keyboard */
|
case 3: /* Index 3 is always the keyboard */
|
||||||
|
if (hidpp_report->params[HIDPP_PARAM_DEVICE_INFO] & HIDPP_27MHZ_SECURE_MASK) {
|
||||||
|
hid_info(hdev, "Keyboard connection is encrypted\n");
|
||||||
|
} else {
|
||||||
|
hid_warn(hdev, "Keyboard events are send over the air in plain-text / unencrypted\n");
|
||||||
|
hid_warn(hdev, "See: https://gitlab.freedesktop.org/jwrdegoede/logitech-27mhz-keyboard-encryption-setup/\n");
|
||||||
|
}
|
||||||
|
fallthrough;
|
||||||
case 4: /* Index 4 is used for an optional separate numpad */
|
case 4: /* Index 4 is used for an optional separate numpad */
|
||||||
workitem->device_type = HIDPP_DEVICE_TYPE_KEYBOARD;
|
workitem->device_type = HIDPP_DEVICE_TYPE_KEYBOARD;
|
||||||
workitem->reports_supported |= STD_KEYBOARD | MULTIMEDIA |
|
workitem->reports_supported |= STD_KEYBOARD | MULTIMEDIA |
|
||||||
@ -1489,6 +1497,13 @@ static void logi_dj_ll_stop(struct hid_device *hid)
|
|||||||
dbg_hid("%s\n", __func__);
|
dbg_hid("%s\n", __func__);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool logi_dj_ll_may_wakeup(struct hid_device *hid)
|
||||||
|
{
|
||||||
|
struct dj_device *djdev = hid->driver_data;
|
||||||
|
struct dj_receiver_dev *djrcv_dev = djdev->dj_receiver_dev;
|
||||||
|
|
||||||
|
return hid_hw_may_wakeup(djrcv_dev->hidpp);
|
||||||
|
}
|
||||||
|
|
||||||
static struct hid_ll_driver logi_dj_ll_driver = {
|
static struct hid_ll_driver logi_dj_ll_driver = {
|
||||||
.parse = logi_dj_ll_parse,
|
.parse = logi_dj_ll_parse,
|
||||||
@ -1497,6 +1512,7 @@ static struct hid_ll_driver logi_dj_ll_driver = {
|
|||||||
.open = logi_dj_ll_open,
|
.open = logi_dj_ll_open,
|
||||||
.close = logi_dj_ll_close,
|
.close = logi_dj_ll_close,
|
||||||
.raw_request = logi_dj_ll_raw_request,
|
.raw_request = logi_dj_ll_raw_request,
|
||||||
|
.may_wakeup = logi_dj_ll_may_wakeup,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int logi_dj_dj_event(struct hid_device *hdev,
|
static int logi_dj_dj_event(struct hid_device *hdev,
|
||||||
|
@ -56,6 +56,8 @@ MODULE_PARM_DESC(disable_tap_to_click,
|
|||||||
#define HIDPP_SUB_ID_CONSUMER_VENDOR_KEYS 0x03
|
#define HIDPP_SUB_ID_CONSUMER_VENDOR_KEYS 0x03
|
||||||
#define HIDPP_SUB_ID_ROLLER 0x05
|
#define HIDPP_SUB_ID_ROLLER 0x05
|
||||||
#define HIDPP_SUB_ID_MOUSE_EXTRA_BTNS 0x06
|
#define HIDPP_SUB_ID_MOUSE_EXTRA_BTNS 0x06
|
||||||
|
#define HIDPP_SUB_ID_USER_IFACE_EVENT 0x08
|
||||||
|
#define HIDPP_USER_IFACE_EVENT_ENCRYPTION_KEY_LOST BIT(5)
|
||||||
|
|
||||||
#define HIDPP_QUIRK_CLASS_WTP BIT(0)
|
#define HIDPP_QUIRK_CLASS_WTP BIT(0)
|
||||||
#define HIDPP_QUIRK_CLASS_M560 BIT(1)
|
#define HIDPP_QUIRK_CLASS_M560 BIT(1)
|
||||||
@ -3529,6 +3531,16 @@ static int hidpp_raw_hidpp_event(struct hidpp_device *hidpp, u8 *data,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hidpp->hid_dev->group == HID_GROUP_LOGITECH_27MHZ_DEVICE &&
|
||||||
|
data[0] == REPORT_ID_HIDPP_SHORT &&
|
||||||
|
data[2] == HIDPP_SUB_ID_USER_IFACE_EVENT &&
|
||||||
|
(data[3] & HIDPP_USER_IFACE_EVENT_ENCRYPTION_KEY_LOST)) {
|
||||||
|
dev_err_ratelimited(&hidpp->hid_dev->dev,
|
||||||
|
"Error the keyboard's wireless encryption key has been lost, your keyboard will not work unless you re-configure encryption.\n");
|
||||||
|
dev_err_ratelimited(&hidpp->hid_dev->dev,
|
||||||
|
"See: https://gitlab.freedesktop.org/jwrdegoede/logitech-27mhz-keyboard-encryption-setup/\n");
|
||||||
|
}
|
||||||
|
|
||||||
if (hidpp->capabilities & HIDPP_CAPABILITY_HIDPP20_BATTERY) {
|
if (hidpp->capabilities & HIDPP_CAPABILITY_HIDPP20_BATTERY) {
|
||||||
ret = hidpp20_battery_event_1000(hidpp, data, size);
|
ret = hidpp20_battery_event_1000(hidpp, data, size);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
|
@ -1768,7 +1768,8 @@ static int mt_suspend(struct hid_device *hdev, pm_message_t state)
|
|||||||
struct mt_device *td = hid_get_drvdata(hdev);
|
struct mt_device *td = hid_get_drvdata(hdev);
|
||||||
|
|
||||||
/* High latency is desirable for power savings during S3/S0ix */
|
/* High latency is desirable for power savings during S3/S0ix */
|
||||||
if (td->mtclass.quirks & MT_QUIRK_DISABLE_WAKEUP)
|
if ((td->mtclass.quirks & MT_QUIRK_DISABLE_WAKEUP) ||
|
||||||
|
!hid_hw_may_wakeup(hdev))
|
||||||
mt_set_modes(hdev, HID_LATENCY_HIGH, false, false);
|
mt_set_modes(hdev, HID_LATENCY_HIGH, false, false);
|
||||||
else
|
else
|
||||||
mt_set_modes(hdev, HID_LATENCY_HIGH, true, true);
|
mt_set_modes(hdev, HID_LATENCY_HIGH, true, true);
|
||||||
|
@ -597,9 +597,8 @@ struct sony_sc {
|
|||||||
/* DS4 calibration data */
|
/* DS4 calibration data */
|
||||||
struct ds4_calibration_data ds4_calib_data[6];
|
struct ds4_calibration_data ds4_calib_data[6];
|
||||||
/* GH Live */
|
/* GH Live */
|
||||||
|
struct urb *ghl_urb;
|
||||||
struct timer_list ghl_poke_timer;
|
struct timer_list ghl_poke_timer;
|
||||||
struct usb_ctrlrequest *ghl_cr;
|
|
||||||
u8 *ghl_databuf;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static void sony_set_leds(struct sony_sc *sc);
|
static void sony_set_leds(struct sony_sc *sc);
|
||||||
@ -625,66 +624,54 @@ static inline void sony_schedule_work(struct sony_sc *sc,
|
|||||||
|
|
||||||
static void ghl_magic_poke_cb(struct urb *urb)
|
static void ghl_magic_poke_cb(struct urb *urb)
|
||||||
{
|
{
|
||||||
if (urb) {
|
struct sony_sc *sc = urb->context;
|
||||||
/* Free sc->ghl_cr and sc->ghl_databuf allocated in
|
|
||||||
* ghl_magic_poke()
|
if (urb->status < 0)
|
||||||
*/
|
hid_err(sc->hdev, "URB transfer failed : %d", urb->status);
|
||||||
kfree(urb->setup_packet);
|
|
||||||
kfree(urb->transfer_buffer);
|
mod_timer(&sc->ghl_poke_timer, jiffies + GHL_GUITAR_POKE_INTERVAL*HZ);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ghl_magic_poke(struct timer_list *t)
|
static void ghl_magic_poke(struct timer_list *t)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
struct sony_sc *sc = from_timer(sc, t, ghl_poke_timer);
|
struct sony_sc *sc = from_timer(sc, t, ghl_poke_timer);
|
||||||
|
|
||||||
int ret;
|
ret = usb_submit_urb(sc->ghl_urb, GFP_ATOMIC);
|
||||||
unsigned int pipe;
|
if (ret < 0)
|
||||||
struct urb *urb;
|
hid_err(sc->hdev, "usb_submit_urb failed: %d", ret);
|
||||||
struct usb_device *usbdev = to_usb_device(sc->hdev->dev.parent->parent);
|
}
|
||||||
const u16 poke_size =
|
|
||||||
ARRAY_SIZE(ghl_ps3wiiu_magic_data);
|
|
||||||
|
|
||||||
|
static int ghl_init_urb(struct sony_sc *sc, struct usb_device *usbdev)
|
||||||
|
{
|
||||||
|
struct usb_ctrlrequest *cr;
|
||||||
|
u16 poke_size;
|
||||||
|
u8 *databuf;
|
||||||
|
unsigned int pipe;
|
||||||
|
|
||||||
|
poke_size = ARRAY_SIZE(ghl_ps3wiiu_magic_data);
|
||||||
pipe = usb_sndctrlpipe(usbdev, 0);
|
pipe = usb_sndctrlpipe(usbdev, 0);
|
||||||
|
|
||||||
if (!sc->ghl_cr) {
|
cr = devm_kzalloc(&sc->hdev->dev, sizeof(*cr), GFP_ATOMIC);
|
||||||
sc->ghl_cr = kzalloc(sizeof(*sc->ghl_cr), GFP_ATOMIC);
|
if (cr == NULL)
|
||||||
if (!sc->ghl_cr)
|
return -ENOMEM;
|
||||||
goto resched;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!sc->ghl_databuf) {
|
databuf = devm_kzalloc(&sc->hdev->dev, poke_size, GFP_ATOMIC);
|
||||||
sc->ghl_databuf = kzalloc(poke_size, GFP_ATOMIC);
|
if (databuf == NULL)
|
||||||
if (!sc->ghl_databuf)
|
return -ENOMEM;
|
||||||
goto resched;
|
|
||||||
}
|
|
||||||
|
|
||||||
urb = usb_alloc_urb(0, GFP_ATOMIC);
|
cr->bRequestType =
|
||||||
if (!urb)
|
|
||||||
goto resched;
|
|
||||||
|
|
||||||
sc->ghl_cr->bRequestType =
|
|
||||||
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT;
|
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT;
|
||||||
sc->ghl_cr->bRequest = USB_REQ_SET_CONFIGURATION;
|
cr->bRequest = USB_REQ_SET_CONFIGURATION;
|
||||||
sc->ghl_cr->wValue = cpu_to_le16(ghl_ps3wiiu_magic_value);
|
cr->wValue = cpu_to_le16(ghl_ps3wiiu_magic_value);
|
||||||
sc->ghl_cr->wIndex = 0;
|
cr->wIndex = 0;
|
||||||
sc->ghl_cr->wLength = cpu_to_le16(poke_size);
|
cr->wLength = cpu_to_le16(poke_size);
|
||||||
memcpy(sc->ghl_databuf, ghl_ps3wiiu_magic_data, poke_size);
|
memcpy(databuf, ghl_ps3wiiu_magic_data, poke_size);
|
||||||
|
|
||||||
usb_fill_control_urb(
|
usb_fill_control_urb(
|
||||||
urb, usbdev, pipe,
|
sc->ghl_urb, usbdev, pipe,
|
||||||
(unsigned char *) sc->ghl_cr, sc->ghl_databuf,
|
(unsigned char *) cr, databuf, poke_size,
|
||||||
poke_size, ghl_magic_poke_cb, NULL);
|
ghl_magic_poke_cb, sc);
|
||||||
ret = usb_submit_urb(urb, GFP_ATOMIC);
|
return 0;
|
||||||
if (ret < 0) {
|
|
||||||
kfree(sc->ghl_databuf);
|
|
||||||
kfree(sc->ghl_cr);
|
|
||||||
}
|
|
||||||
usb_free_urb(urb);
|
|
||||||
|
|
||||||
resched:
|
|
||||||
/* Reschedule for next time */
|
|
||||||
mod_timer(&sc->ghl_poke_timer, jiffies + GHL_GUITAR_POKE_INTERVAL*HZ);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int guitar_mapping(struct hid_device *hdev, struct hid_input *hi,
|
static int guitar_mapping(struct hid_device *hdev, struct hid_input *hi,
|
||||||
@ -2981,6 +2968,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||||||
int ret;
|
int ret;
|
||||||
unsigned long quirks = id->driver_data;
|
unsigned long quirks = id->driver_data;
|
||||||
struct sony_sc *sc;
|
struct sony_sc *sc;
|
||||||
|
struct usb_device *usbdev;
|
||||||
unsigned int connect_mask = HID_CONNECT_DEFAULT;
|
unsigned int connect_mask = HID_CONNECT_DEFAULT;
|
||||||
|
|
||||||
if (!strcmp(hdev->name, "FutureMax Dance Mat"))
|
if (!strcmp(hdev->name, "FutureMax Dance Mat"))
|
||||||
@ -3000,6 +2988,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||||||
sc->quirks = quirks;
|
sc->quirks = quirks;
|
||||||
hid_set_drvdata(hdev, sc);
|
hid_set_drvdata(hdev, sc);
|
||||||
sc->hdev = hdev;
|
sc->hdev = hdev;
|
||||||
|
usbdev = to_usb_device(sc->hdev->dev.parent->parent);
|
||||||
|
|
||||||
ret = hid_parse(hdev);
|
ret = hid_parse(hdev);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
@ -3042,6 +3031,15 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sc->quirks & GHL_GUITAR_PS3WIIU) {
|
if (sc->quirks & GHL_GUITAR_PS3WIIU) {
|
||||||
|
sc->ghl_urb = usb_alloc_urb(0, GFP_ATOMIC);
|
||||||
|
if (!sc->ghl_urb)
|
||||||
|
return -ENOMEM;
|
||||||
|
ret = ghl_init_urb(sc, usbdev);
|
||||||
|
if (ret) {
|
||||||
|
hid_err(hdev, "error preparing URB\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
timer_setup(&sc->ghl_poke_timer, ghl_magic_poke, 0);
|
timer_setup(&sc->ghl_poke_timer, ghl_magic_poke, 0);
|
||||||
mod_timer(&sc->ghl_poke_timer,
|
mod_timer(&sc->ghl_poke_timer,
|
||||||
jiffies + GHL_GUITAR_POKE_INTERVAL*HZ);
|
jiffies + GHL_GUITAR_POKE_INTERVAL*HZ);
|
||||||
@ -3054,8 +3052,10 @@ static void sony_remove(struct hid_device *hdev)
|
|||||||
{
|
{
|
||||||
struct sony_sc *sc = hid_get_drvdata(hdev);
|
struct sony_sc *sc = hid_get_drvdata(hdev);
|
||||||
|
|
||||||
if (sc->quirks & GHL_GUITAR_PS3WIIU)
|
if (sc->quirks & GHL_GUITAR_PS3WIIU) {
|
||||||
del_timer_sync(&sc->ghl_poke_timer);
|
del_timer_sync(&sc->ghl_poke_timer);
|
||||||
|
usb_free_urb(sc->ghl_urb);
|
||||||
|
}
|
||||||
|
|
||||||
hid_hw_close(hdev);
|
hid_hw_close(hdev);
|
||||||
|
|
||||||
|
@ -311,12 +311,13 @@ static int thrustmaster_probe(struct hid_device *hdev, const struct hid_device_i
|
|||||||
goto error4;
|
goto error4;
|
||||||
}
|
}
|
||||||
|
|
||||||
tm_wheel->change_request = kzalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
|
tm_wheel->change_request = kmemdup(&change_request,
|
||||||
|
sizeof(struct usb_ctrlrequest),
|
||||||
|
GFP_KERNEL);
|
||||||
if (!tm_wheel->change_request) {
|
if (!tm_wheel->change_request) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto error5;
|
goto error5;
|
||||||
}
|
}
|
||||||
memcpy(tm_wheel->change_request, &change_request, sizeof(struct usb_ctrlrequest));
|
|
||||||
|
|
||||||
tm_wheel->usb_dev = interface_to_usbdev(to_usb_interface(hdev->dev.parent));
|
tm_wheel->usb_dev = interface_to_usbdev(to_usb_interface(hdev->dev.parent));
|
||||||
hid_set_drvdata(hdev, tm_wheel);
|
hid_set_drvdata(hdev, tm_wheel);
|
||||||
|
@ -5,6 +5,7 @@ menu "Intel ISH HID support"
|
|||||||
config INTEL_ISH_HID
|
config INTEL_ISH_HID
|
||||||
tristate "Intel Integrated Sensor Hub"
|
tristate "Intel Integrated Sensor Hub"
|
||||||
default n
|
default n
|
||||||
|
depends on X86
|
||||||
select HID
|
select HID
|
||||||
help
|
help
|
||||||
The Integrated Sensor Hub (ISH) enables the ability to offload
|
The Integrated Sensor Hub (ISH) enables the ability to offload
|
||||||
|
@ -544,7 +544,7 @@ static int ish_fw_reset_handler(struct ishtp_device *dev)
|
|||||||
#define TIMEOUT_FOR_HW_RDY_MS 300
|
#define TIMEOUT_FOR_HW_RDY_MS 300
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ish_fw_reset_work_fn() - FW reset worker function
|
* fw_reset_work_fn() - FW reset worker function
|
||||||
* @unused: not used
|
* @unused: not used
|
||||||
*
|
*
|
||||||
* Call ish_fw_reset_handler to complete FW reset
|
* Call ish_fw_reset_handler to complete FW reset
|
||||||
@ -889,6 +889,29 @@ static uint32_t ish_ipc_get_header(struct ishtp_device *dev, int length,
|
|||||||
return drbl_val;
|
return drbl_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* _dma_no_cache_snooping()
|
||||||
|
*
|
||||||
|
* Check on current platform, DMA supports cache snooping or not.
|
||||||
|
* This callback is used to notify uplayer driver if manully cache
|
||||||
|
* flush is needed when do DMA operation.
|
||||||
|
*
|
||||||
|
* Please pay attention to this callback implementation, if declare
|
||||||
|
* having cache snooping on a cache snooping not supported platform
|
||||||
|
* will cause uplayer driver receiving mismatched data; and if
|
||||||
|
* declare no cache snooping on a cache snooping supported platform
|
||||||
|
* will cause cache be flushed twice and performance hit.
|
||||||
|
*
|
||||||
|
* @dev: ishtp device pointer
|
||||||
|
*
|
||||||
|
* Return: false - has cache snooping capability
|
||||||
|
* true - no cache snooping, need manually cache flush
|
||||||
|
*/
|
||||||
|
static bool _dma_no_cache_snooping(struct ishtp_device *dev)
|
||||||
|
{
|
||||||
|
return dev->pdev->device == EHL_Ax_DEVICE_ID;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct ishtp_hw_ops ish_hw_ops = {
|
static const struct ishtp_hw_ops ish_hw_ops = {
|
||||||
.hw_reset = _ish_hw_reset,
|
.hw_reset = _ish_hw_reset,
|
||||||
.ipc_reset = _ish_ipc_reset,
|
.ipc_reset = _ish_ipc_reset,
|
||||||
@ -897,7 +920,8 @@ static const struct ishtp_hw_ops ish_hw_ops = {
|
|||||||
.write = write_ipc_to_queue,
|
.write = write_ipc_to_queue,
|
||||||
.get_fw_status = _ish_read_fw_sts_reg,
|
.get_fw_status = _ish_read_fw_sts_reg,
|
||||||
.sync_fw_clock = _ish_sync_fw_clock,
|
.sync_fw_clock = _ish_sync_fw_clock,
|
||||||
.ishtp_read_hdr = _ishtp_read_hdr
|
.ishtp_read_hdr = _ishtp_read_hdr,
|
||||||
|
.dma_no_cache_snooping = _dma_no_cache_snooping
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -263,7 +263,6 @@ static void __maybe_unused ish_resume_handler(struct work_struct *work)
|
|||||||
struct pci_dev *pdev = to_pci_dev(ish_resume_device);
|
struct pci_dev *pdev = to_pci_dev(ish_resume_device);
|
||||||
struct ishtp_device *dev = pci_get_drvdata(pdev);
|
struct ishtp_device *dev = pci_get_drvdata(pdev);
|
||||||
uint32_t fwsts = dev->ops->get_fw_status(dev);
|
uint32_t fwsts = dev->ops->get_fw_status(dev);
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (ish_should_leave_d0i3(pdev) && !dev->suspend_flag
|
if (ish_should_leave_d0i3(pdev) && !dev->suspend_flag
|
||||||
&& IPC_IS_ISH_ILUP(fwsts)) {
|
&& IPC_IS_ISH_ILUP(fwsts)) {
|
||||||
@ -275,7 +274,7 @@ static void __maybe_unused ish_resume_handler(struct work_struct *work)
|
|||||||
|
|
||||||
/* Waiting to get resume response */
|
/* Waiting to get resume response */
|
||||||
if (dev->resume_flag)
|
if (dev->resume_flag)
|
||||||
ret = wait_event_interruptible_timeout(dev->resume_wait,
|
wait_event_interruptible_timeout(dev->resume_wait,
|
||||||
!dev->resume_flag,
|
!dev->resume_flag,
|
||||||
msecs_to_jiffies(WAIT_FOR_RESUME_ACK_MS));
|
msecs_to_jiffies(WAIT_FOR_RESUME_ACK_MS));
|
||||||
|
|
||||||
|
@ -31,13 +31,13 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* enum ish_loader_commands - ISH loader host commands.
|
* enum ish_loader_commands - ISH loader host commands.
|
||||||
* LOADER_CMD_XFER_QUERY Query the Shim firmware loader for
|
* @LOADER_CMD_XFER_QUERY: Query the Shim firmware loader for
|
||||||
* capabilities
|
* capabilities
|
||||||
* LOADER_CMD_XFER_FRAGMENT Transfer one firmware image fragment at a
|
* @LOADER_CMD_XFER_FRAGMENT: Transfer one firmware image fragment at a
|
||||||
* time. The command may be executed
|
* time. The command may be executed
|
||||||
* multiple times until the entire firmware
|
* multiple times until the entire firmware
|
||||||
* image is downloaded to SRAM.
|
* image is downloaded to SRAM.
|
||||||
* LOADER_CMD_START Start executing the main firmware.
|
* @LOADER_CMD_START: Start executing the main firmware.
|
||||||
*/
|
*/
|
||||||
enum ish_loader_commands {
|
enum ish_loader_commands {
|
||||||
LOADER_CMD_XFER_QUERY = 0,
|
LOADER_CMD_XFER_QUERY = 0,
|
||||||
@ -95,6 +95,7 @@ static int dma_buf_size_limit = 4 * PAGE_SIZE;
|
|||||||
/**
|
/**
|
||||||
* struct loader_msg_hdr - Header for ISH Loader commands.
|
* struct loader_msg_hdr - Header for ISH Loader commands.
|
||||||
* @command: LOADER_CMD* commands. Bit 7 is the response.
|
* @command: LOADER_CMD* commands. Bit 7 is the response.
|
||||||
|
* @reserved: Reserved space
|
||||||
* @status: Command response status. Non 0, is error
|
* @status: Command response status. Non 0, is error
|
||||||
* condition.
|
* condition.
|
||||||
*
|
*
|
||||||
@ -173,16 +174,16 @@ struct loader_start {
|
|||||||
* struct response_info - Encapsulate firmware response related
|
* struct response_info - Encapsulate firmware response related
|
||||||
* information for passing between function
|
* information for passing between function
|
||||||
* loader_cl_send() and process_recv() callback.
|
* loader_cl_send() and process_recv() callback.
|
||||||
* @data Copy the data received from firmware here.
|
* @data: Copy the data received from firmware here.
|
||||||
* @max_size Max size allocated for the @data buffer. If the
|
* @max_size: Max size allocated for the @data buffer. If the
|
||||||
* received data exceeds this value, we log an
|
* received data exceeds this value, we log an
|
||||||
* error.
|
* error.
|
||||||
* @size Actual size of data received from firmware.
|
* @size: Actual size of data received from firmware.
|
||||||
* @error Returns 0 for success, negative error code for a
|
* @error: Returns 0 for success, negative error code for a
|
||||||
* failure in function process_recv().
|
* failure in function process_recv().
|
||||||
* @received Set to true on receiving a valid firmware
|
* @received: Set to true on receiving a valid firmware
|
||||||
* response to host command
|
* response to host command
|
||||||
* @wait_queue Wait queue for Host firmware loading where the
|
* @wait_queue: Wait queue for Host firmware loading where the
|
||||||
* client sends message to ISH firmware and waits
|
* client sends message to ISH firmware and waits
|
||||||
* for response
|
* for response
|
||||||
*/
|
*/
|
||||||
@ -195,13 +196,13 @@ struct response_info {
|
|||||||
wait_queue_head_t wait_queue;
|
wait_queue_head_t wait_queue;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* struct ishtp_cl_data - Encapsulate per ISH-TP Client Data.
|
* struct ishtp_cl_data - Encapsulate per ISH-TP Client Data.
|
||||||
* @work_ishtp_reset: Work queue for reset handling.
|
* @work_ishtp_reset: Work queue for reset handling.
|
||||||
* @work_fw_load: Work queue for host firmware loading.
|
* @work_fw_load: Work queue for host firmware loading.
|
||||||
* @flag_retry Flag for indicating host firmware loading should
|
* @flag_retry: Flag for indicating host firmware loading should
|
||||||
* be retried.
|
* be retried.
|
||||||
* @retry_count Count the number of retries.
|
* @retry_count: Count the number of retries.
|
||||||
*
|
*
|
||||||
* This structure is used to store data per client.
|
* This structure is used to store data per client.
|
||||||
*/
|
*/
|
||||||
@ -240,8 +241,8 @@ struct ishtp_cl_data {
|
|||||||
/**
|
/**
|
||||||
* get_firmware_variant() - Gets the filename of firmware image to be
|
* get_firmware_variant() - Gets the filename of firmware image to be
|
||||||
* loaded based on platform variant.
|
* loaded based on platform variant.
|
||||||
* @client_data Client data instance.
|
* @client_data: Client data instance.
|
||||||
* @filename Returns firmware filename.
|
* @filename: Returns firmware filename.
|
||||||
*
|
*
|
||||||
* Queries the firmware-name device property string.
|
* Queries the firmware-name device property string.
|
||||||
*
|
*
|
||||||
@ -266,11 +267,11 @@ static int get_firmware_variant(struct ishtp_cl_data *client_data,
|
|||||||
/**
|
/**
|
||||||
* loader_cl_send() Send message from host to firmware
|
* loader_cl_send() Send message from host to firmware
|
||||||
* @client_data: Client data instance
|
* @client_data: Client data instance
|
||||||
* @out_msg Message buffer to be sent to firmware
|
* @out_msg: Message buffer to be sent to firmware
|
||||||
* @out_size Size of out going message
|
* @out_size: Size of out going message
|
||||||
* @in_msg Message buffer where the incoming data copied.
|
* @in_msg: Message buffer where the incoming data copied.
|
||||||
* This buffer is allocated by calling
|
* This buffer is allocated by calling
|
||||||
* @in_size Max size of incoming message
|
* @in_size: Max size of incoming message
|
||||||
*
|
*
|
||||||
* Return: Number of bytes copied in the in_msg on success, negative
|
* Return: Number of bytes copied in the in_msg on success, negative
|
||||||
* error code on failure.
|
* error code on failure.
|
||||||
@ -435,7 +436,7 @@ end:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* loader_cl_event_cb() - bus driver callback for incoming message
|
* loader_cl_event_cb() - bus driver callback for incoming message
|
||||||
* @device: Pointer to the ishtp client device for which this
|
* @cl_device: Pointer to the ishtp client device for which this
|
||||||
* message is targeted
|
* message is targeted
|
||||||
*
|
*
|
||||||
* Remove the packet from the list and process the message by calling
|
* Remove the packet from the list and process the message by calling
|
||||||
@ -455,7 +456,7 @@ static void loader_cl_event_cb(struct ishtp_cl_device *cl_device)
|
|||||||
/**
|
/**
|
||||||
* ish_query_loader_prop() - Query ISH Shim firmware loader
|
* ish_query_loader_prop() - Query ISH Shim firmware loader
|
||||||
* @client_data: Client data instance
|
* @client_data: Client data instance
|
||||||
* @fw: Poiner to firmware data struct in host memory
|
* @fw: Pointer to firmware data struct in host memory
|
||||||
* @fw_info: Loader firmware properties
|
* @fw_info: Loader firmware properties
|
||||||
*
|
*
|
||||||
* This function queries the ISH Shim firmware loader for capabilities.
|
* This function queries the ISH Shim firmware loader for capabilities.
|
||||||
@ -536,7 +537,7 @@ static int ish_query_loader_prop(struct ishtp_cl_data *client_data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ish_fw_xfer_ishtp() Loads ISH firmware using ishtp interface
|
* ish_fw_xfer_ishtp() - Loads ISH firmware using ishtp interface
|
||||||
* @client_data: Client data instance
|
* @client_data: Client data instance
|
||||||
* @fw: Pointer to firmware data struct in host memory
|
* @fw: Pointer to firmware data struct in host memory
|
||||||
*
|
*
|
||||||
@ -733,7 +734,7 @@ end_err_dma_buf_release:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ish_fw_start() Start executing ISH main firmware
|
* ish_fw_start() - Start executing ISH main firmware
|
||||||
* @client_data: client data instance
|
* @client_data: client data instance
|
||||||
*
|
*
|
||||||
* This function sends message to Shim firmware loader to start
|
* This function sends message to Shim firmware loader to start
|
||||||
@ -756,7 +757,7 @@ static int ish_fw_start(struct ishtp_cl_data *client_data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* load_fw_from_host() Loads ISH firmware from host
|
* load_fw_from_host() - Loads ISH firmware from host
|
||||||
* @client_data: Client data instance
|
* @client_data: Client data instance
|
||||||
*
|
*
|
||||||
* This function loads the ISH firmware to ISH SRAM and starts execution
|
* This function loads the ISH firmware to ISH SRAM and starts execution
|
||||||
@ -1015,7 +1016,7 @@ static int loader_ishtp_cl_probe(struct ishtp_cl_device *cl_device)
|
|||||||
*
|
*
|
||||||
* Return: 0
|
* Return: 0
|
||||||
*/
|
*/
|
||||||
static int loader_ishtp_cl_remove(struct ishtp_cl_device *cl_device)
|
static void loader_ishtp_cl_remove(struct ishtp_cl_device *cl_device)
|
||||||
{
|
{
|
||||||
struct ishtp_cl_data *client_data;
|
struct ishtp_cl_data *client_data;
|
||||||
struct ishtp_cl *loader_ishtp_cl = ishtp_get_drvdata(cl_device);
|
struct ishtp_cl *loader_ishtp_cl = ishtp_get_drvdata(cl_device);
|
||||||
@ -1032,8 +1033,6 @@ static int loader_ishtp_cl_remove(struct ishtp_cl_device *cl_device)
|
|||||||
cancel_work_sync(&client_data->work_ishtp_reset);
|
cancel_work_sync(&client_data->work_ishtp_reset);
|
||||||
loader_deinit(loader_ishtp_cl);
|
loader_deinit(loader_ishtp_cl);
|
||||||
ishtp_put_device(cl_device);
|
ishtp_put_device(cl_device);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -11,6 +11,11 @@
|
|||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include "ishtp-hid.h"
|
#include "ishtp-hid.h"
|
||||||
|
|
||||||
|
/* ISH Transport protocol (ISHTP in short) GUID */
|
||||||
|
static const guid_t hid_ishtp_guid =
|
||||||
|
GUID_INIT(0x33AECD58, 0xB679, 0x4E54,
|
||||||
|
0x9B, 0xD9, 0xA0, 0x4D, 0x34, 0xF0, 0xC2, 0x26);
|
||||||
|
|
||||||
/* Rx ring buffer pool size */
|
/* Rx ring buffer pool size */
|
||||||
#define HID_CL_RX_RING_SIZE 32
|
#define HID_CL_RX_RING_SIZE 32
|
||||||
#define HID_CL_TX_RING_SIZE 16
|
#define HID_CL_TX_RING_SIZE 16
|
||||||
@ -18,7 +23,7 @@
|
|||||||
#define cl_data_to_dev(client_data) ishtp_device(client_data->cl_device)
|
#define cl_data_to_dev(client_data) ishtp_device(client_data->cl_device)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* report_bad_packets() - Report bad packets
|
* report_bad_packet() - Report bad packets
|
||||||
* @hid_ishtp_cl: Client instance to get stats
|
* @hid_ishtp_cl: Client instance to get stats
|
||||||
* @recv_buf: Raw received host interface message
|
* @recv_buf: Raw received host interface message
|
||||||
* @cur_pos: Current position index in payload
|
* @cur_pos: Current position index in payload
|
||||||
@ -779,7 +784,7 @@ static void hid_ishtp_cl_reset_handler(struct work_struct *work)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void (*hid_print_trace)(void *unused, const char *format, ...);
|
ishtp_print_log ishtp_hid_print_trace;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hid_ishtp_cl_probe() - ISHTP client driver probe
|
* hid_ishtp_cl_probe() - ISHTP client driver probe
|
||||||
@ -818,7 +823,7 @@ static int hid_ishtp_cl_probe(struct ishtp_cl_device *cl_device)
|
|||||||
|
|
||||||
INIT_WORK(&client_data->work, hid_ishtp_cl_reset_handler);
|
INIT_WORK(&client_data->work, hid_ishtp_cl_reset_handler);
|
||||||
|
|
||||||
hid_print_trace = ishtp_trace_callback(cl_device);
|
ishtp_hid_print_trace = ishtp_trace_callback(cl_device);
|
||||||
|
|
||||||
rv = hid_ishtp_cl_init(hid_ishtp_cl, 0);
|
rv = hid_ishtp_cl_init(hid_ishtp_cl, 0);
|
||||||
if (rv) {
|
if (rv) {
|
||||||
@ -838,7 +843,7 @@ static int hid_ishtp_cl_probe(struct ishtp_cl_device *cl_device)
|
|||||||
*
|
*
|
||||||
* Return: 0
|
* Return: 0
|
||||||
*/
|
*/
|
||||||
static int hid_ishtp_cl_remove(struct ishtp_cl_device *cl_device)
|
static void hid_ishtp_cl_remove(struct ishtp_cl_device *cl_device)
|
||||||
{
|
{
|
||||||
struct ishtp_cl *hid_ishtp_cl = ishtp_get_drvdata(cl_device);
|
struct ishtp_cl *hid_ishtp_cl = ishtp_get_drvdata(cl_device);
|
||||||
struct ishtp_cl_data *client_data = ishtp_get_client_data(hid_ishtp_cl);
|
struct ishtp_cl_data *client_data = ishtp_get_client_data(hid_ishtp_cl);
|
||||||
@ -856,8 +861,6 @@ static int hid_ishtp_cl_remove(struct ishtp_cl_device *cl_device)
|
|||||||
hid_ishtp_cl = NULL;
|
hid_ishtp_cl = NULL;
|
||||||
|
|
||||||
client_data->num_hid_devices = 0;
|
client_data->num_hid_devices = 0;
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -254,7 +254,7 @@ err_hid_data:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ishtp_hid_probe() - Remove registered hid device
|
* ishtp_hid_remove() - Remove registered hid device
|
||||||
* @client_data: client data pointer
|
* @client_data: client data pointer
|
||||||
*
|
*
|
||||||
* This function is used to destroy allocatd HID device.
|
* This function is used to destroy allocatd HID device.
|
||||||
|
@ -16,14 +16,9 @@
|
|||||||
#define IS_RESPONSE 0x80
|
#define IS_RESPONSE 0x80
|
||||||
|
|
||||||
/* Used to dump to Linux trace buffer, if enabled */
|
/* Used to dump to Linux trace buffer, if enabled */
|
||||||
extern void (*hid_print_trace)(void *unused, const char *format, ...);
|
extern ishtp_print_log ishtp_hid_print_trace;
|
||||||
#define hid_ishtp_trace(client, ...) \
|
#define hid_ishtp_trace(client, ...) \
|
||||||
(hid_print_trace)(NULL, __VA_ARGS__)
|
(ishtp_hid_print_trace)(NULL, __VA_ARGS__)
|
||||||
|
|
||||||
/* ISH Transport protocol (ISHTP in short) GUID */
|
|
||||||
static const guid_t hid_ishtp_guid =
|
|
||||||
GUID_INIT(0x33AECD58, 0xB679, 0x4E54,
|
|
||||||
0x9B, 0xD9, 0xA0, 0x4D, 0x34, 0xF0, 0xC2, 0x26);
|
|
||||||
|
|
||||||
/* ISH HID message structure */
|
/* ISH HID message structure */
|
||||||
struct hostif_msg_hdr {
|
struct hostif_msg_hdr {
|
||||||
|
@ -164,6 +164,7 @@ EXPORT_SYMBOL(ishtp_fw_cl_get_client);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* ishtp_get_fw_client_id() - Get fw client id
|
* ishtp_get_fw_client_id() - Get fw client id
|
||||||
|
* @fw_client: firmware client used to fetch the ID
|
||||||
*
|
*
|
||||||
* This interface is used to reset HW get FW client id.
|
* This interface is used to reset HW get FW client id.
|
||||||
*
|
*
|
||||||
@ -257,26 +258,19 @@ static int ishtp_cl_bus_match(struct device *dev, struct device_driver *drv)
|
|||||||
static int ishtp_cl_device_remove(struct device *dev)
|
static int ishtp_cl_device_remove(struct device *dev)
|
||||||
{
|
{
|
||||||
struct ishtp_cl_device *device = to_ishtp_cl_device(dev);
|
struct ishtp_cl_device *device = to_ishtp_cl_device(dev);
|
||||||
struct ishtp_cl_driver *driver;
|
struct ishtp_cl_driver *driver = to_ishtp_cl_driver(dev->driver);
|
||||||
|
|
||||||
if (!device || !dev->driver)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (device->event_cb) {
|
if (device->event_cb) {
|
||||||
device->event_cb = NULL;
|
device->event_cb = NULL;
|
||||||
cancel_work_sync(&device->event_work);
|
cancel_work_sync(&device->event_work);
|
||||||
}
|
}
|
||||||
|
|
||||||
driver = to_ishtp_cl_driver(dev->driver);
|
if (driver->remove)
|
||||||
if (!driver->remove) {
|
driver->remove(device);
|
||||||
dev->driver = NULL;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return driver->remove(device);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ishtp_cl_device_suspend() - Bus suspend callback
|
* ishtp_cl_device_suspend() - Bus suspend callback
|
||||||
* @dev: device
|
* @dev: device
|
||||||
@ -842,6 +836,7 @@ int ishtp_use_dma_transfer(void)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* ishtp_device() - Return device pointer
|
* ishtp_device() - Return device pointer
|
||||||
|
* @device: ISH-TP client device instance
|
||||||
*
|
*
|
||||||
* This interface is used to return device pointer from ishtp_cl_device
|
* This interface is used to return device pointer from ishtp_cl_device
|
||||||
* instance.
|
* instance.
|
||||||
@ -858,6 +853,7 @@ EXPORT_SYMBOL(ishtp_device);
|
|||||||
* ishtp_get_pci_device() - Return PCI device dev pointer
|
* ishtp_get_pci_device() - Return PCI device dev pointer
|
||||||
* This interface is used to return PCI device pointer
|
* This interface is used to return PCI device pointer
|
||||||
* from ishtp_cl_device instance.
|
* from ishtp_cl_device instance.
|
||||||
|
* @device: ISH-TP client device instance
|
||||||
*
|
*
|
||||||
* Return: device *.
|
* Return: device *.
|
||||||
*/
|
*/
|
||||||
@ -869,12 +865,13 @@ EXPORT_SYMBOL(ishtp_get_pci_device);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* ishtp_trace_callback() - Return trace callback
|
* ishtp_trace_callback() - Return trace callback
|
||||||
|
* @cl_device: ISH-TP client device instance
|
||||||
*
|
*
|
||||||
* This interface is used to return trace callback function pointer.
|
* This interface is used to return trace callback function pointer.
|
||||||
*
|
*
|
||||||
* Return: void *.
|
* Return: *ishtp_print_log()
|
||||||
*/
|
*/
|
||||||
void *ishtp_trace_callback(struct ishtp_cl_device *cl_device)
|
ishtp_print_log ishtp_trace_callback(struct ishtp_cl_device *cl_device)
|
||||||
{
|
{
|
||||||
return cl_device->ishtp_dev->print_log;
|
return cl_device->ishtp_dev->print_log;
|
||||||
}
|
}
|
||||||
@ -882,6 +879,7 @@ EXPORT_SYMBOL(ishtp_trace_callback);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* ish_hw_reset() - Call HW reset IPC callback
|
* ish_hw_reset() - Call HW reset IPC callback
|
||||||
|
* @dev: ISHTP device instance
|
||||||
*
|
*
|
||||||
* This interface is used to reset HW in case of error.
|
* This interface is used to reset HW in case of error.
|
||||||
*
|
*
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include <linux/wait.h>
|
#include <linux/wait.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
|
#include <asm/cacheflush.h>
|
||||||
#include "hbm.h"
|
#include "hbm.h"
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
|
|
||||||
@ -111,7 +112,7 @@ static void ishtp_cl_init(struct ishtp_cl *cl, struct ishtp_device *dev)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* ishtp_cl_allocate() - allocates client structure and sets it up.
|
* ishtp_cl_allocate() - allocates client structure and sets it up.
|
||||||
* @dev: ishtp device
|
* @cl_device: ishtp client device
|
||||||
*
|
*
|
||||||
* Allocate memory for new client device and call to initialize each field.
|
* Allocate memory for new client device and call to initialize each field.
|
||||||
*
|
*
|
||||||
@ -263,7 +264,6 @@ EXPORT_SYMBOL(ishtp_cl_unlink);
|
|||||||
int ishtp_cl_disconnect(struct ishtp_cl *cl)
|
int ishtp_cl_disconnect(struct ishtp_cl *cl)
|
||||||
{
|
{
|
||||||
struct ishtp_device *dev;
|
struct ishtp_device *dev;
|
||||||
int err;
|
|
||||||
|
|
||||||
if (WARN_ON(!cl || !cl->dev))
|
if (WARN_ON(!cl || !cl->dev))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
@ -283,7 +283,7 @@ int ishtp_cl_disconnect(struct ishtp_cl *cl)
|
|||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = wait_event_interruptible_timeout(cl->wait_ctrl_res,
|
wait_event_interruptible_timeout(cl->wait_ctrl_res,
|
||||||
(dev->dev_state != ISHTP_DEV_ENABLED ||
|
(dev->dev_state != ISHTP_DEV_ENABLED ||
|
||||||
cl->state == ISHTP_CL_DISCONNECTED),
|
cl->state == ISHTP_CL_DISCONNECTED),
|
||||||
ishtp_secs_to_jiffies(ISHTP_CL_CONNECT_TIMEOUT));
|
ishtp_secs_to_jiffies(ISHTP_CL_CONNECT_TIMEOUT));
|
||||||
@ -773,6 +773,14 @@ static void ishtp_cl_send_msg_dma(struct ishtp_device *dev,
|
|||||||
/* write msg to dma buf */
|
/* write msg to dma buf */
|
||||||
memcpy(msg_addr, cl_msg->send_buf.data, cl_msg->send_buf.size);
|
memcpy(msg_addr, cl_msg->send_buf.data, cl_msg->send_buf.size);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if current fw don't support cache snooping, driver have to
|
||||||
|
* flush the cache manually.
|
||||||
|
*/
|
||||||
|
if (dev->ops->dma_no_cache_snooping &&
|
||||||
|
dev->ops->dma_no_cache_snooping(dev))
|
||||||
|
clflush_cache_range(msg_addr, cl_msg->send_buf.size);
|
||||||
|
|
||||||
/* send dma_xfer hbm msg */
|
/* send dma_xfer hbm msg */
|
||||||
off = msg_addr - (unsigned char *)dev->ishtp_host_dma_tx_buf;
|
off = msg_addr - (unsigned char *)dev->ishtp_host_dma_tx_buf;
|
||||||
ishtp_hbm_hdr(&hdr, sizeof(struct dma_xfer_hbm));
|
ishtp_hbm_hdr(&hdr, sizeof(struct dma_xfer_hbm));
|
||||||
@ -997,6 +1005,15 @@ void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg,
|
|||||||
}
|
}
|
||||||
|
|
||||||
buffer = rb->buffer.data;
|
buffer = rb->buffer.data;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if current fw don't support cache snooping, driver have to
|
||||||
|
* flush the cache manually.
|
||||||
|
*/
|
||||||
|
if (dev->ops->dma_no_cache_snooping &&
|
||||||
|
dev->ops->dma_no_cache_snooping(dev))
|
||||||
|
clflush_cache_range(msg, hbm->msg_length);
|
||||||
|
|
||||||
memcpy(buffer, msg, hbm->msg_length);
|
memcpy(buffer, msg, hbm->msg_length);
|
||||||
rb->buf_idx = hbm->msg_length;
|
rb->buf_idx = hbm->msg_length;
|
||||||
|
|
||||||
|
@ -398,7 +398,7 @@ static void ishtp_hbm_cl_connect_res(struct ishtp_device *dev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ishtp_client_disconnect_request() - Receive disconnect request
|
* ishtp_hbm_fw_disconnect_req() - Receive disconnect request
|
||||||
* @dev: ISHTP device instance
|
* @dev: ISHTP device instance
|
||||||
* @disconnect_req: disconnect request structure
|
* @disconnect_req: disconnect request structure
|
||||||
*
|
*
|
||||||
@ -430,7 +430,7 @@ static void ishtp_hbm_fw_disconnect_req(struct ishtp_device *dev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ishtp_hbm_dma_xfer_ack(() - Receive transfer ACK
|
* ishtp_hbm_dma_xfer_ack() - Receive transfer ACK
|
||||||
* @dev: ISHTP device instance
|
* @dev: ISHTP device instance
|
||||||
* @dma_xfer: HBM transfer message
|
* @dma_xfer: HBM transfer message
|
||||||
*
|
*
|
||||||
@ -914,7 +914,7 @@ static inline void fix_cl_hdr(struct ishtp_msg_hdr *hdr, size_t length,
|
|||||||
/*** Suspend and resume notification ***/
|
/*** Suspend and resume notification ***/
|
||||||
|
|
||||||
static uint32_t current_state;
|
static uint32_t current_state;
|
||||||
static uint32_t supported_states = 0 | SUSPEND_STATE_BIT;
|
static uint32_t supported_states = SUSPEND_STATE_BIT | CONNECTED_STANDBY_STATE_BIT;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ishtp_send_suspend() - Send suspend message to FW
|
* ishtp_send_suspend() - Send suspend message to FW
|
||||||
@ -933,7 +933,7 @@ void ishtp_send_suspend(struct ishtp_device *dev)
|
|||||||
memset(&state_status_msg, 0, len);
|
memset(&state_status_msg, 0, len);
|
||||||
state_status_msg.hdr.cmd = SYSTEM_STATE_STATUS;
|
state_status_msg.hdr.cmd = SYSTEM_STATE_STATUS;
|
||||||
state_status_msg.supported_states = supported_states;
|
state_status_msg.supported_states = supported_states;
|
||||||
current_state |= SUSPEND_STATE_BIT;
|
current_state |= (SUSPEND_STATE_BIT | CONNECTED_STANDBY_STATE_BIT);
|
||||||
dev->print_log(dev, "%s() sends SUSPEND notification\n", __func__);
|
dev->print_log(dev, "%s() sends SUSPEND notification\n", __func__);
|
||||||
state_status_msg.states_status = current_state;
|
state_status_msg.states_status = current_state;
|
||||||
|
|
||||||
@ -959,7 +959,7 @@ void ishtp_send_resume(struct ishtp_device *dev)
|
|||||||
memset(&state_status_msg, 0, len);
|
memset(&state_status_msg, 0, len);
|
||||||
state_status_msg.hdr.cmd = SYSTEM_STATE_STATUS;
|
state_status_msg.hdr.cmd = SYSTEM_STATE_STATUS;
|
||||||
state_status_msg.supported_states = supported_states;
|
state_status_msg.supported_states = supported_states;
|
||||||
current_state &= ~SUSPEND_STATE_BIT;
|
current_state &= ~(CONNECTED_STANDBY_STATE_BIT | SUSPEND_STATE_BIT);
|
||||||
dev->print_log(dev, "%s() sends RESUME notification\n", __func__);
|
dev->print_log(dev, "%s() sends RESUME notification\n", __func__);
|
||||||
state_status_msg.states_status = current_state;
|
state_status_msg.states_status = current_state;
|
||||||
|
|
||||||
|
@ -235,6 +235,7 @@ struct dma_xfer_hbm {
|
|||||||
#define SYSTEM_STATE_QUERY_SUBSCRIBERS 0x3
|
#define SYSTEM_STATE_QUERY_SUBSCRIBERS 0x3
|
||||||
#define SYSTEM_STATE_STATE_CHANGE_REQ 0x4
|
#define SYSTEM_STATE_STATE_CHANGE_REQ 0x4
|
||||||
/*indicates suspend and resume states*/
|
/*indicates suspend and resume states*/
|
||||||
|
#define CONNECTED_STANDBY_STATE_BIT (1<<0)
|
||||||
#define SUSPEND_STATE_BIT (1<<1)
|
#define SUSPEND_STATE_BIT (1<<1)
|
||||||
|
|
||||||
struct ish_system_states_header {
|
struct ish_system_states_header {
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
|
#include <linux/intel-ish-client-if.h>
|
||||||
#include "bus.h"
|
#include "bus.h"
|
||||||
#include "hbm.h"
|
#include "hbm.h"
|
||||||
|
|
||||||
@ -118,6 +119,7 @@ struct ishtp_hw_ops {
|
|||||||
unsigned long buffer_length);
|
unsigned long buffer_length);
|
||||||
uint32_t (*get_fw_status)(struct ishtp_device *dev);
|
uint32_t (*get_fw_status)(struct ishtp_device *dev);
|
||||||
void (*sync_fw_clock)(struct ishtp_device *dev);
|
void (*sync_fw_clock)(struct ishtp_device *dev);
|
||||||
|
bool (*dma_no_cache_snooping)(struct ishtp_device *dev);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -202,8 +204,7 @@ struct ishtp_device {
|
|||||||
uint64_t ishtp_host_dma_rx_buf_phys;
|
uint64_t ishtp_host_dma_rx_buf_phys;
|
||||||
|
|
||||||
/* Dump to trace buffers if enabled*/
|
/* Dump to trace buffers if enabled*/
|
||||||
__printf(2, 3) void (*print_log)(struct ishtp_device *dev,
|
ishtp_print_log print_log;
|
||||||
const char *format, ...);
|
|
||||||
|
|
||||||
/* Debug stats */
|
/* Debug stats */
|
||||||
unsigned int ipc_rx_cnt;
|
unsigned int ipc_rx_cnt;
|
||||||
|
@ -143,7 +143,7 @@ static int ssam_hid_get_raw_report(struct surface_hid_device *shid, u8 rprt_id,
|
|||||||
rqst.target_id = shid->uid.target;
|
rqst.target_id = shid->uid.target;
|
||||||
rqst.instance_id = shid->uid.instance;
|
rqst.instance_id = shid->uid.instance;
|
||||||
rqst.command_id = SURFACE_HID_CID_GET_FEATURE_REPORT;
|
rqst.command_id = SURFACE_HID_CID_GET_FEATURE_REPORT;
|
||||||
rqst.flags = 0;
|
rqst.flags = SSAM_REQUEST_HAS_RESPONSE;
|
||||||
rqst.length = sizeof(rprt_id);
|
rqst.length = sizeof(rprt_id);
|
||||||
rqst.payload = &rprt_id;
|
rqst.payload = &rprt_id;
|
||||||
|
|
||||||
|
@ -1304,6 +1304,13 @@ static int usbhid_idle(struct hid_device *hid, int report, int idle,
|
|||||||
return hid_set_idle(dev, ifnum, report, idle);
|
return hid_set_idle(dev, ifnum, report, idle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool usbhid_may_wakeup(struct hid_device *hid)
|
||||||
|
{
|
||||||
|
struct usb_device *dev = hid_to_usb_dev(hid);
|
||||||
|
|
||||||
|
return device_may_wakeup(&dev->dev);
|
||||||
|
}
|
||||||
|
|
||||||
struct hid_ll_driver usb_hid_driver = {
|
struct hid_ll_driver usb_hid_driver = {
|
||||||
.parse = usbhid_parse,
|
.parse = usbhid_parse,
|
||||||
.start = usbhid_start,
|
.start = usbhid_start,
|
||||||
@ -1316,6 +1323,7 @@ struct hid_ll_driver usb_hid_driver = {
|
|||||||
.raw_request = usbhid_raw_request,
|
.raw_request = usbhid_raw_request,
|
||||||
.output_report = usbhid_output_report,
|
.output_report = usbhid_output_report,
|
||||||
.idle = usbhid_idle,
|
.idle = usbhid_idle,
|
||||||
|
.may_wakeup = usbhid_may_wakeup,
|
||||||
};
|
};
|
||||||
EXPORT_SYMBOL_GPL(usb_hid_driver);
|
EXPORT_SYMBOL_GPL(usb_hid_driver);
|
||||||
|
|
||||||
|
@ -239,11 +239,11 @@ static int usb_kbd_alloc_mem(struct usb_device *dev, struct usb_kbd *kbd)
|
|||||||
return -1;
|
return -1;
|
||||||
if (!(kbd->led = usb_alloc_urb(0, GFP_KERNEL)))
|
if (!(kbd->led = usb_alloc_urb(0, GFP_KERNEL)))
|
||||||
return -1;
|
return -1;
|
||||||
if (!(kbd->new = usb_alloc_coherent(dev, 8, GFP_ATOMIC, &kbd->new_dma)))
|
if (!(kbd->new = usb_alloc_coherent(dev, 8, GFP_KERNEL, &kbd->new_dma)))
|
||||||
return -1;
|
return -1;
|
||||||
if (!(kbd->cr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL)))
|
if (!(kbd->cr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL)))
|
||||||
return -1;
|
return -1;
|
||||||
if (!(kbd->leds = usb_alloc_coherent(dev, 1, GFP_ATOMIC, &kbd->leds_dma)))
|
if (!(kbd->leds = usb_alloc_coherent(dev, 1, GFP_KERNEL, &kbd->leds_dma)))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -130,7 +130,7 @@ static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_i
|
|||||||
if (!mouse || !input_dev)
|
if (!mouse || !input_dev)
|
||||||
goto fail1;
|
goto fail1;
|
||||||
|
|
||||||
mouse->data = usb_alloc_coherent(dev, 8, GFP_ATOMIC, &mouse->data_dma);
|
mouse->data = usb_alloc_coherent(dev, 8, GFP_KERNEL, &mouse->data_dma);
|
||||||
if (!mouse->data)
|
if (!mouse->data)
|
||||||
goto fail1;
|
goto fail1;
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@
|
|||||||
#define WACOM_HID_WD_TOUCHONOFF (WACOM_HID_UP_WACOMDIGITIZER | 0x0454)
|
#define WACOM_HID_WD_TOUCHONOFF (WACOM_HID_UP_WACOMDIGITIZER | 0x0454)
|
||||||
#define WACOM_HID_WD_BATTERY_LEVEL (WACOM_HID_UP_WACOMDIGITIZER | 0x043b)
|
#define WACOM_HID_WD_BATTERY_LEVEL (WACOM_HID_UP_WACOMDIGITIZER | 0x043b)
|
||||||
#define WACOM_HID_WD_EXPRESSKEY00 (WACOM_HID_UP_WACOMDIGITIZER | 0x0910)
|
#define WACOM_HID_WD_EXPRESSKEY00 (WACOM_HID_UP_WACOMDIGITIZER | 0x0910)
|
||||||
#define WACOM_HID_WD_EXPRESSKEYCAP00 (WACOM_HID_UP_WACOMDIGITIZER | 0x0950)
|
#define WACOM_HID_WD_EXPRESSKEYCAP00 (WACOM_HID_UP_WACOMDIGITIZER | 0x0940)
|
||||||
#define WACOM_HID_WD_MODE_CHANGE (WACOM_HID_UP_WACOMDIGITIZER | 0x0980)
|
#define WACOM_HID_WD_MODE_CHANGE (WACOM_HID_UP_WACOMDIGITIZER | 0x0980)
|
||||||
#define WACOM_HID_WD_MUTE_DEVICE (WACOM_HID_UP_WACOMDIGITIZER | 0x0981)
|
#define WACOM_HID_WD_MUTE_DEVICE (WACOM_HID_UP_WACOMDIGITIZER | 0x0981)
|
||||||
#define WACOM_HID_WD_CONTROLPANEL (WACOM_HID_UP_WACOMDIGITIZER | 0x0982)
|
#define WACOM_HID_WD_CONTROLPANEL (WACOM_HID_UP_WACOMDIGITIZER | 0x0982)
|
||||||
|
@ -703,7 +703,7 @@ end_ishtp_cl_alloc_error:
|
|||||||
*
|
*
|
||||||
* Return: 0
|
* Return: 0
|
||||||
*/
|
*/
|
||||||
static int cros_ec_ishtp_remove(struct ishtp_cl_device *cl_device)
|
static void cros_ec_ishtp_remove(struct ishtp_cl_device *cl_device)
|
||||||
{
|
{
|
||||||
struct ishtp_cl *cros_ish_cl = ishtp_get_drvdata(cl_device);
|
struct ishtp_cl *cros_ish_cl = ishtp_get_drvdata(cl_device);
|
||||||
struct ishtp_cl_data *client_data = ishtp_get_client_data(cros_ish_cl);
|
struct ishtp_cl_data *client_data = ishtp_get_client_data(cros_ish_cl);
|
||||||
@ -712,8 +712,6 @@ static int cros_ec_ishtp_remove(struct ishtp_cl_device *cl_device)
|
|||||||
cancel_work_sync(&client_data->work_ec_evt);
|
cancel_work_sync(&client_data->work_ec_evt);
|
||||||
cros_ish_deinit(cros_ish_cl);
|
cros_ish_deinit(cros_ish_cl);
|
||||||
ishtp_put_device(cl_device);
|
ishtp_put_device(cl_device);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -102,6 +102,7 @@ struct hid_item {
|
|||||||
#define HID_COLLECTION_PHYSICAL 0
|
#define HID_COLLECTION_PHYSICAL 0
|
||||||
#define HID_COLLECTION_APPLICATION 1
|
#define HID_COLLECTION_APPLICATION 1
|
||||||
#define HID_COLLECTION_LOGICAL 2
|
#define HID_COLLECTION_LOGICAL 2
|
||||||
|
#define HID_COLLECTION_NAMED_ARRAY 4
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* HID report descriptor global item tags
|
* HID report descriptor global item tags
|
||||||
@ -800,6 +801,7 @@ struct hid_driver {
|
|||||||
* @raw_request: send raw report request to device (e.g. feature report)
|
* @raw_request: send raw report request to device (e.g. feature report)
|
||||||
* @output_report: send output report to device
|
* @output_report: send output report to device
|
||||||
* @idle: send idle request to device
|
* @idle: send idle request to device
|
||||||
|
* @may_wakeup: return if device may act as a wakeup source during system-suspend
|
||||||
*/
|
*/
|
||||||
struct hid_ll_driver {
|
struct hid_ll_driver {
|
||||||
int (*start)(struct hid_device *hdev);
|
int (*start)(struct hid_device *hdev);
|
||||||
@ -824,6 +826,7 @@ struct hid_ll_driver {
|
|||||||
int (*output_report) (struct hid_device *hdev, __u8 *buf, size_t len);
|
int (*output_report) (struct hid_device *hdev, __u8 *buf, size_t len);
|
||||||
|
|
||||||
int (*idle)(struct hid_device *hdev, int report, int idle, int reqtype);
|
int (*idle)(struct hid_device *hdev, int report, int idle, int reqtype);
|
||||||
|
bool (*may_wakeup)(struct hid_device *hdev);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct hid_ll_driver i2c_hid_ll_driver;
|
extern struct hid_ll_driver i2c_hid_ll_driver;
|
||||||
@ -1149,6 +1152,22 @@ static inline int hid_hw_idle(struct hid_device *hdev, int report, int idle,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hid_may_wakeup - return if the hid device may act as a wakeup source during system-suspend
|
||||||
|
*
|
||||||
|
* @hdev: hid device
|
||||||
|
*/
|
||||||
|
static inline bool hid_hw_may_wakeup(struct hid_device *hdev)
|
||||||
|
{
|
||||||
|
if (hdev->ll_driver->may_wakeup)
|
||||||
|
return hdev->ll_driver->may_wakeup(hdev);
|
||||||
|
|
||||||
|
if (hdev->dev.parent)
|
||||||
|
return device_may_wakeup(hdev->dev.parent);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hid_hw_wait - wait for buffered io to complete
|
* hid_hw_wait - wait for buffered io to complete
|
||||||
*
|
*
|
||||||
|
@ -8,11 +8,17 @@
|
|||||||
#ifndef _INTEL_ISH_CLIENT_IF_H_
|
#ifndef _INTEL_ISH_CLIENT_IF_H_
|
||||||
#define _INTEL_ISH_CLIENT_IF_H_
|
#define _INTEL_ISH_CLIENT_IF_H_
|
||||||
|
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include <linux/uuid.h>
|
||||||
|
|
||||||
struct ishtp_cl_device;
|
struct ishtp_cl_device;
|
||||||
struct ishtp_device;
|
struct ishtp_device;
|
||||||
struct ishtp_cl;
|
struct ishtp_cl;
|
||||||
struct ishtp_fw_client;
|
struct ishtp_fw_client;
|
||||||
|
|
||||||
|
typedef __printf(2, 3) void (*ishtp_print_log)(struct ishtp_device *dev,
|
||||||
|
const char *format, ...);
|
||||||
|
|
||||||
/* Client state */
|
/* Client state */
|
||||||
enum cl_state {
|
enum cl_state {
|
||||||
ISHTP_CL_INITIALIZING = 0,
|
ISHTP_CL_INITIALIZING = 0,
|
||||||
@ -36,7 +42,7 @@ struct ishtp_cl_driver {
|
|||||||
const char *name;
|
const char *name;
|
||||||
const guid_t *guid;
|
const guid_t *guid;
|
||||||
int (*probe)(struct ishtp_cl_device *dev);
|
int (*probe)(struct ishtp_cl_device *dev);
|
||||||
int (*remove)(struct ishtp_cl_device *dev);
|
void (*remove)(struct ishtp_cl_device *dev);
|
||||||
int (*reset)(struct ishtp_cl_device *dev);
|
int (*reset)(struct ishtp_cl_device *dev);
|
||||||
const struct dev_pm_ops *pm;
|
const struct dev_pm_ops *pm;
|
||||||
};
|
};
|
||||||
@ -76,7 +82,7 @@ int ishtp_register_event_cb(struct ishtp_cl_device *device,
|
|||||||
/* Get the device * from ishtp device instance */
|
/* Get the device * from ishtp device instance */
|
||||||
struct device *ishtp_device(struct ishtp_cl_device *cl_device);
|
struct device *ishtp_device(struct ishtp_cl_device *cl_device);
|
||||||
/* Trace interface for clients */
|
/* Trace interface for clients */
|
||||||
void *ishtp_trace_callback(struct ishtp_cl_device *cl_device);
|
ishtp_print_log ishtp_trace_callback(struct ishtp_cl_device *cl_device);
|
||||||
/* Get device pointer of PCI device for DMA acces */
|
/* Get device pointer of PCI device for DMA acces */
|
||||||
struct device *ishtp_get_pci_device(struct ishtp_cl_device *cl_device);
|
struct device *ishtp_get_pci_device(struct ishtp_cl_device *cl_device);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user