File Index
Files and directories
Sign in
FILE

quicki2c-hid.c

File preview with syntax highlighting.

linux-6.19.14/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-hid.c C
  1/* SPDX-License-Identifier: GPL-2.0 */
  2/* Copyright (c) 2024 Intel Corporation */
  3
  4#include <linux/hid.h>
  5#include <linux/input.h>
  6#include <linux/pm_runtime.h>
  7
  8#include "quicki2c-dev.h"
  9#include "quicki2c-hid.h"
 10#include "quicki2c-protocol.h"
 11
 12/**
 13 * quicki2c_hid_parse() - HID core parse() callback
 14 *
 15 * @hid: HID device instance
 16 *
 17 * This function gets called during call to hid_add_device
 18 *
 19 * Return: 0 on success and non zero on error.
 20 */
 21static int quicki2c_hid_parse(struct hid_device *hid)
 22{
 23	struct quicki2c_device *qcdev = hid->driver_data;
 24
 25	if (qcdev->report_descriptor)
 26		return hid_parse_report(hid, qcdev->report_descriptor,
 27					le16_to_cpu(qcdev->dev_desc.report_desc_len));
 28
 29	dev_err_once(qcdev->dev, "invalid report descriptor\n");
 30	return -EINVAL;
 31}
 32
 33static int quicki2c_hid_start(struct hid_device *hid)
 34{
 35	return 0;
 36}
 37
 38static void quicki2c_hid_stop(struct hid_device *hid)
 39{
 40}
 41
 42static int quicki2c_hid_open(struct hid_device *hid)
 43{
 44	return 0;
 45}
 46
 47static void quicki2c_hid_close(struct hid_device *hid)
 48{
 49}
 50
 51static int quicki2c_hid_raw_request(struct hid_device *hid,
 52				    unsigned char reportnum,
 53				    __u8 *buf, size_t len,
 54				    unsigned char rtype, int reqtype)
 55{
 56	struct quicki2c_device *qcdev = hid->driver_data;
 57	int ret = 0;
 58
 59	ret = pm_runtime_resume_and_get(qcdev->dev);
 60	if (ret)
 61		return ret;
 62
 63	switch (reqtype) {
 64	case HID_REQ_GET_REPORT:
 65		ret = quicki2c_get_report(qcdev, rtype, reportnum, buf, len);
 66		break;
 67	case HID_REQ_SET_REPORT:
 68		ret = quicki2c_set_report(qcdev, rtype, reportnum, buf, len);
 69		break;
 70	default:
 71		dev_err(qcdev->dev, "Not supported request type %d\n", reqtype);
 72		break;
 73	}
 74
 75	pm_runtime_put_autosuspend(qcdev->dev);
 76
 77	return ret;
 78}
 79
 80static int quicki2c_hid_power(struct hid_device *hid, int lvl)
 81{
 82	return 0;
 83}
 84
 85static struct hid_ll_driver quicki2c_hid_ll_driver = {
 86	.parse = quicki2c_hid_parse,
 87	.start = quicki2c_hid_start,
 88	.stop = quicki2c_hid_stop,
 89	.open = quicki2c_hid_open,
 90	.close = quicki2c_hid_close,
 91	.power = quicki2c_hid_power,
 92	.raw_request = quicki2c_hid_raw_request,
 93};
 94
 95/**
 96 * quicki2c_hid_probe() - Register HID low level driver
 97 *
 98 * @qcdev: point to quicki2c device
 99 *
100 * This function is used to allocate and add HID device.
101 *
102 * Return: 0 on success, non zero on error.
103 */
104int quicki2c_hid_probe(struct quicki2c_device *qcdev)
105{
106	struct hid_device *hid;
107	int ret;
108
109	hid = hid_allocate_device();
110	if (IS_ERR(hid))
111		return PTR_ERR(hid);
112
113	hid->ll_driver = &quicki2c_hid_ll_driver;
114	hid->bus = BUS_PCI;
115	hid->dev.parent = qcdev->dev;
116	hid->driver_data = qcdev;
117	hid->version = le16_to_cpu(qcdev->dev_desc.version_id);
118	hid->vendor = le16_to_cpu(qcdev->dev_desc.vendor_id);
119	hid->product = le16_to_cpu(qcdev->dev_desc.product_id);
120	snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X", "quicki2c-hid",
121		 hid->vendor, hid->product);
122
123	ret = hid_add_device(hid);
124	if (ret) {
125		hid_destroy_device(hid);
126		return ret;
127	}
128
129	qcdev->hid_dev = hid;
130
131	return 0;
132}
133
134/**
135 * quicki2c_hid_remove() - Destroy HID device
136 *
137 * @qcdev: point to quicki2c device
138 *
139 * Return: 0 on success, non zero on error.
140 */
141void quicki2c_hid_remove(struct quicki2c_device *qcdev)
142{
143	hid_destroy_device(qcdev->hid_dev);
144}
145
146/**
147 * quicki2c_hid_send_report() - Send HID input report data to HID core
148 *
149 * @qcdev: point to quicki2c device
150 * @data: point to input report data buffer
151 * @data_len: the length of input report data
152 *
153 * Return: 0 on success, non zero on error.
154 */
155int quicki2c_hid_send_report(struct quicki2c_device *qcdev,
156			     void *data, size_t data_len)
157{
158	int ret;
159
160	ret = hid_input_report(qcdev->hid_dev, HID_INPUT_REPORT, data, data_len, 1);
161	if (ret)
162		dev_err(qcdev->dev, "Failed to send HID input report, ret = %d.\n", ret);
163
164	return ret;
165}
~/ Read-only file preview.