xref: /linux/sound/soc/sdca/sdca_hid.c (revision 746680ec6696585e30db3e18c93a63df9cbec39c)
1 // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
2 
3 /*
4  * The MIPI SDCA specification is available for public downloads at
5  * https://www.mipi.org/mipi-sdca-v1-0-download
6  */
7 
8 #include <linux/acpi.h>
9 #include <linux/byteorder/generic.h>
10 #include <linux/cleanup.h>
11 #include <linux/device.h>
12 #include <linux/dev_printk.h>
13 #include <linux/module.h>
14 #include <linux/property.h>
15 #include <linux/soundwire/sdw.h>
16 #include <linux/types.h>
17 #include <sound/sdca.h>
18 #include <sound/sdca_function.h>
19 #include <sound/sdca_hid.h>
20 
21 static int sdwhid_parse(struct hid_device *hid)
22 {
23 	struct sdca_entity *entity = hid->driver_data;
24 	unsigned int rsize;
25 	int ret;
26 
27 	rsize = le16_to_cpu(entity->hide.hid_desc.rpt_desc.wDescriptorLength);
28 
29 	if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) {
30 		dev_err(&hid->dev, "invalid size of report descriptor (%u)\n", rsize);
31 		return -EINVAL;
32 	}
33 
34 	ret = hid_parse_report(hid, entity->hide.hid_report_desc, rsize);
35 
36 	if (!ret)
37 		return 0;
38 
39 	dev_err(&hid->dev, "parsing report descriptor failed\n");
40 	return ret;
41 }
42 
43 static int sdwhid_start(struct hid_device *hid)
44 {
45 	return 0;
46 }
47 
48 static void sdwhid_stop(struct hid_device *hid)
49 {
50 }
51 
52 static int sdwhid_raw_request(struct hid_device *hid, unsigned char reportnum,
53 			      __u8 *buf, size_t len, unsigned char rtype, int reqtype)
54 {
55 	switch (reqtype) {
56 	case HID_REQ_GET_REPORT:
57 		/* not implemented yet */
58 		return 0;
59 	case HID_REQ_SET_REPORT:
60 		/* not implemented yet */
61 		return 0;
62 	default:
63 		return -EIO;
64 	}
65 }
66 
67 static int sdwhid_open(struct hid_device *hid)
68 {
69 	return 0;
70 }
71 
72 static void sdwhid_close(struct hid_device *hid)
73 {
74 }
75 
76 static const struct hid_ll_driver sdw_hid_driver = {
77 	.parse = sdwhid_parse,
78 	.start = sdwhid_start,
79 	.stop = sdwhid_stop,
80 	.open = sdwhid_open,
81 	.close = sdwhid_close,
82 	.raw_request = sdwhid_raw_request,
83 };
84 
85 int sdca_add_hid_device(struct device *dev, struct sdca_entity *entity)
86 {
87 	struct sdw_bus *bus;
88 	struct hid_device *hid;
89 	struct sdw_slave *slave = dev_to_sdw_dev(dev);
90 	int ret;
91 
92 	bus = slave->bus;
93 
94 	hid = hid_allocate_device();
95 	if (IS_ERR(hid))
96 		return PTR_ERR(hid);
97 
98 	hid->ll_driver = &sdw_hid_driver;
99 
100 	hid->dev.parent = dev;
101 	hid->bus = BUS_SDW;
102 	hid->version = le16_to_cpu(entity->hide.hid_desc.bcdHID);
103 
104 	snprintf(hid->name, sizeof(hid->name),
105 		 "HID sdw:%01x:%01x:%04x:%04x:%02x",
106 		 bus->controller_id, bus->link_id, slave->id.mfg_id,
107 		 slave->id.part_id, slave->id.class_id);
108 
109 	snprintf(hid->phys, sizeof(hid->phys), "%s", dev->bus->name);
110 
111 	hid->driver_data = entity;
112 
113 	ret = hid_add_device(hid);
114 	if (ret && ret != -ENODEV) {
115 		dev_err(dev, "can't add hid device: %d\n", ret);
116 		hid_destroy_device(hid);
117 		return ret;
118 	}
119 
120 	entity->hide.hid = hid;
121 
122 	return 0;
123 }
124 EXPORT_SYMBOL_NS(sdca_add_hid_device, "SND_SOC_SDCA");
125 
126 MODULE_LICENSE("Dual BSD/GPL");
127 MODULE_DESCRIPTION("SDCA HID library");
128