mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 10:04:04 +02:00
HID: intel-thc-hid: intel-quickspi: Add THC QuickSPI driver hid layer
Add HID Low level driver callbacks and hid probe function to register QucikSPI as a HID driver, and external touch device as a HID device. Co-developed-by: Xinpeng Sun <xinpeng.sun@intel.com> Signed-off-by: Xinpeng Sun <xinpeng.sun@intel.com> Signed-off-by: Even Xu <even.xu@intel.com> Tested-by: Rui Zhang <rui1.zhang@intel.com> Tested-by: Mark Pearson <mpearson-lenovo@squebb.ca> Reviewed-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Reviewed-by: Mark Pearson <mpearson-lenovo@squebb.ca> Tested-by: Aaron Ma <aaron.ma@canonical.com> Signed-off-by: Jiri Kosina <jkosina@suse.com>
This commit is contained in:
parent
c8f3027dd2
commit
4751113f24
|
|
@ -11,5 +11,6 @@ intel-thc-objs += intel-thc/intel-thc-dma.o
|
|||
|
||||
obj-$(CONFIG_INTEL_QUICKSPI) += intel-quickspi.o
|
||||
intel-quickspi-objs += intel-quickspi/pci-quickspi.o
|
||||
intel-quickspi-objs += intel-quickspi/quickspi-hid.o
|
||||
|
||||
ccflags-y += -I $(src)/intel-thc
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
#ifndef _QUICKSPI_DEV_H_
|
||||
#define _QUICKSPI_DEV_H_
|
||||
|
||||
#include <linux/hid-over-spi.h>
|
||||
|
||||
#define PCI_DEVICE_ID_INTEL_THC_MTL_DEVICE_ID_SPI_PORT1 0x7E49
|
||||
#define PCI_DEVICE_ID_INTEL_THC_MTL_DEVICE_ID_SPI_PORT2 0x7E4B
|
||||
#define PCI_DEVICE_ID_INTEL_THC_LNL_DEVICE_ID_SPI_PORT1 0xA849
|
||||
|
|
@ -38,24 +40,33 @@ struct quickspi_driver_data {
|
|||
struct device;
|
||||
struct pci_dev;
|
||||
struct thc_device;
|
||||
struct hid_device;
|
||||
|
||||
/**
|
||||
* struct quickspi_device - THC QuickSpi device struct
|
||||
* @dev: point to kernel device
|
||||
* @pdev: point to PCI device
|
||||
* @thc_hw: point to THC device
|
||||
* @hid_dev: point to hid device
|
||||
* @driver_data: point to quickspi specific driver data
|
||||
* @state: THC SPI device state
|
||||
* @mem_addr: MMIO memory address
|
||||
* @dev_desc: device descriptor for HIDSPI protocol
|
||||
* @report_descriptor: store a copy of device report descriptor
|
||||
*/
|
||||
struct quickspi_device {
|
||||
struct device *dev;
|
||||
struct pci_dev *pdev;
|
||||
struct thc_device *thc_hw;
|
||||
struct hid_device *hid_dev;
|
||||
struct quickspi_driver_data *driver_data;
|
||||
enum quickspi_dev_state state;
|
||||
|
||||
void __iomem *mem_addr;
|
||||
|
||||
struct hidspi_dev_descriptor dev_desc;
|
||||
|
||||
u8 *report_descriptor;
|
||||
};
|
||||
|
||||
#endif /* _QUICKSPI_DEV_H_ */
|
||||
|
|
|
|||
142
drivers/hid/intel-thc-hid/intel-quickspi/quickspi-hid.c
Normal file
142
drivers/hid/intel-thc-hid/intel-quickspi/quickspi-hid.c
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (c) 2024 Intel Corporation */
|
||||
|
||||
#include <linux/hid.h>
|
||||
#include <linux/input.h>
|
||||
|
||||
#include "quickspi-dev.h"
|
||||
#include "quickspi-hid.h"
|
||||
|
||||
/**
|
||||
* quickspi_hid_parse() - HID core parse() callback
|
||||
*
|
||||
* @hid: HID device instance
|
||||
*
|
||||
* This function gets called during call to hid_add_device
|
||||
*
|
||||
* Return: 0 on success and non zero on error.
|
||||
*/
|
||||
static int quickspi_hid_parse(struct hid_device *hid)
|
||||
{
|
||||
struct quickspi_device *qsdev = hid->driver_data;
|
||||
|
||||
if (qsdev->report_descriptor)
|
||||
return hid_parse_report(hid, qsdev->report_descriptor,
|
||||
le16_to_cpu(qsdev->dev_desc.rep_desc_len));
|
||||
|
||||
dev_err(qsdev->dev, "invalid report descriptor\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int quickspi_hid_start(struct hid_device *hid)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void quickspi_hid_stop(struct hid_device *hid)
|
||||
{
|
||||
}
|
||||
|
||||
static int quickspi_hid_open(struct hid_device *hid)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void quickspi_hid_close(struct hid_device *hid)
|
||||
{
|
||||
}
|
||||
|
||||
static int quickspi_hid_raw_request(struct hid_device *hid,
|
||||
unsigned char reportnum,
|
||||
__u8 *buf, size_t len,
|
||||
unsigned char rtype, int reqtype)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int quickspi_hid_power(struct hid_device *hid, int lvl)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct hid_ll_driver quickspi_hid_ll_driver = {
|
||||
.parse = quickspi_hid_parse,
|
||||
.start = quickspi_hid_start,
|
||||
.stop = quickspi_hid_stop,
|
||||
.open = quickspi_hid_open,
|
||||
.close = quickspi_hid_close,
|
||||
.power = quickspi_hid_power,
|
||||
.raw_request = quickspi_hid_raw_request,
|
||||
};
|
||||
|
||||
/**
|
||||
* quickspi_hid_probe() - Register HID low level driver
|
||||
*
|
||||
* @qsdev: point to quickspi device
|
||||
*
|
||||
* This function is used to allocate and add HID device.
|
||||
*
|
||||
* Return: 0 on success, non zero on error.
|
||||
*/
|
||||
int quickspi_hid_probe(struct quickspi_device *qsdev)
|
||||
{
|
||||
struct hid_device *hid;
|
||||
int ret;
|
||||
|
||||
hid = hid_allocate_device();
|
||||
if (IS_ERR(hid))
|
||||
return PTR_ERR(hid);
|
||||
|
||||
hid->ll_driver = &quickspi_hid_ll_driver;
|
||||
hid->bus = BUS_PCI;
|
||||
hid->dev.parent = qsdev->dev;
|
||||
hid->driver_data = qsdev;
|
||||
hid->version = le16_to_cpu(qsdev->dev_desc.version_id);
|
||||
hid->vendor = le16_to_cpu(qsdev->dev_desc.vendor_id);
|
||||
hid->product = le16_to_cpu(qsdev->dev_desc.product_id);
|
||||
snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X", "quickspi-hid",
|
||||
hid->vendor, hid->product);
|
||||
|
||||
ret = hid_add_device(hid);
|
||||
if (ret) {
|
||||
hid_destroy_device(hid);
|
||||
return ret;
|
||||
}
|
||||
|
||||
qsdev->hid_dev = hid;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* quickspi_hid_remove() - Destroy HID device
|
||||
*
|
||||
* @qsdev: point to quickspi device
|
||||
*
|
||||
* Return: 0 on success, non zero on error.
|
||||
*/
|
||||
void quickspi_hid_remove(struct quickspi_device *qsdev)
|
||||
{
|
||||
hid_destroy_device(qsdev->hid_dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* quickspi_hid_send_report() - Send HID input report data to HID core
|
||||
*
|
||||
* @qsdev: point to quickspi device
|
||||
* @data: point to input report data buffer
|
||||
* @data_len: the length of input report data
|
||||
*
|
||||
* Return: 0 on success, non zero on error.
|
||||
*/
|
||||
int quickspi_hid_send_report(struct quickspi_device *qsdev,
|
||||
void *data, size_t data_len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = hid_input_report(qsdev->hid_dev, HID_INPUT_REPORT, data, data_len, 1);
|
||||
if (ret)
|
||||
dev_err(qsdev->dev, "Failed to send HID input report, ret = %d.\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
14
drivers/hid/intel-thc-hid/intel-quickspi/quickspi-hid.h
Normal file
14
drivers/hid/intel-thc-hid/intel-quickspi/quickspi-hid.h
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (c) 2024 Intel Corporation */
|
||||
|
||||
#ifndef _QUICKSPI_HID_H_
|
||||
#define _QUICKSPI_HID_H_
|
||||
|
||||
struct quickspi_device;
|
||||
|
||||
int quickspi_hid_send_report(struct quickspi_device *qsdev,
|
||||
void *data, size_t data_size);
|
||||
int quickspi_hid_probe(struct quickspi_device *qsdev);
|
||||
void quickspi_hid_remove(struct quickspi_device *qsdev);
|
||||
|
||||
#endif /* _QUICKSPI_HID_H_ */
|
||||
37
include/linux/hid-over-spi.h
Normal file
37
include/linux/hid-over-spi.h
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright 2024 Intel Corporation */
|
||||
|
||||
#ifndef _HID_OVER_SPI_H_
|
||||
#define _HID_OVER_SPI_H_
|
||||
|
||||
/**
|
||||
* struct hidspi_dev_descriptor - HIDSPI device descriptor definition
|
||||
* @dev_desc_len: The length of the complete device descriptor, fixed to 0x18 (24).
|
||||
* @bcd_ver: The version number of the HIDSPI protocol supported.
|
||||
* In binary coded decimal (BCD) format. Must be fixed to 0x0300.
|
||||
* @rep_desc_len: The length of the report descriptor
|
||||
* @max_input_len: The length of the largest possible HID input (or feature) report
|
||||
* @max_output_len: The length of the largest output (or feature) report
|
||||
* @max_frag_len: The length of the largest fragment, where a fragment represents
|
||||
* the body of an input report.
|
||||
* @vendor_id: Device manufacturers vendor ID
|
||||
* @product_id: Device unique model/product ID
|
||||
* @version_id: Device’s unique version
|
||||
* @flags: Specify flags for the device’s operation
|
||||
* @reserved: Reserved and should be 0
|
||||
*/
|
||||
struct hidspi_dev_descriptor {
|
||||
__le16 dev_desc_len;
|
||||
__le16 bcd_ver;
|
||||
__le16 rep_desc_len;
|
||||
__le16 max_input_len;
|
||||
__le16 max_output_len;
|
||||
__le16 max_frag_len;
|
||||
__le16 vendor_id;
|
||||
__le16 product_id;
|
||||
__le16 version_id;
|
||||
__le16 flags;
|
||||
__le32 reserved;
|
||||
};
|
||||
|
||||
#endif /* _HID_OVER_SPI_H_ */
|
||||
Loading…
Reference in New Issue
Block a user