cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

hid-roccat-common.c (4565B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Roccat common functions for device specific drivers
      4 *
      5 * Copyright (c) 2011 Stefan Achatz <erazor_de@users.sourceforge.net>
      6 */
      7
      8/*
      9 */
     10
     11#include <linux/hid.h>
     12#include <linux/slab.h>
     13#include <linux/module.h>
     14#include "hid-roccat-common.h"
     15
     16static inline uint16_t roccat_common2_feature_report(uint8_t report_id)
     17{
     18	return 0x300 | report_id;
     19}
     20
     21int roccat_common2_receive(struct usb_device *usb_dev, uint report_id,
     22		void *data, uint size)
     23{
     24	char *buf;
     25	int len;
     26
     27	buf = kmalloc(size, GFP_KERNEL);
     28	if (buf == NULL)
     29		return -ENOMEM;
     30
     31	len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
     32			HID_REQ_GET_REPORT,
     33			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
     34			roccat_common2_feature_report(report_id),
     35			0, buf, size, USB_CTRL_SET_TIMEOUT);
     36
     37	memcpy(data, buf, size);
     38	kfree(buf);
     39	return ((len < 0) ? len : ((len != size) ? -EIO : 0));
     40}
     41EXPORT_SYMBOL_GPL(roccat_common2_receive);
     42
     43int roccat_common2_send(struct usb_device *usb_dev, uint report_id,
     44		void const *data, uint size)
     45{
     46	char *buf;
     47	int len;
     48
     49	buf = kmemdup(data, size, GFP_KERNEL);
     50	if (buf == NULL)
     51		return -ENOMEM;
     52
     53	len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
     54			HID_REQ_SET_REPORT,
     55			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
     56			roccat_common2_feature_report(report_id),
     57			0, buf, size, USB_CTRL_SET_TIMEOUT);
     58
     59	kfree(buf);
     60	return ((len < 0) ? len : ((len != size) ? -EIO : 0));
     61}
     62EXPORT_SYMBOL_GPL(roccat_common2_send);
     63
     64enum roccat_common2_control_states {
     65	ROCCAT_COMMON_CONTROL_STATUS_CRITICAL = 0,
     66	ROCCAT_COMMON_CONTROL_STATUS_OK = 1,
     67	ROCCAT_COMMON_CONTROL_STATUS_INVALID = 2,
     68	ROCCAT_COMMON_CONTROL_STATUS_BUSY = 3,
     69	ROCCAT_COMMON_CONTROL_STATUS_CRITICAL_NEW = 4,
     70};
     71
     72static int roccat_common2_receive_control_status(struct usb_device *usb_dev)
     73{
     74	int retval;
     75	struct roccat_common2_control control;
     76
     77	do {
     78		msleep(50);
     79		retval = roccat_common2_receive(usb_dev,
     80				ROCCAT_COMMON_COMMAND_CONTROL,
     81				&control, sizeof(struct roccat_common2_control));
     82
     83		if (retval)
     84			return retval;
     85
     86		switch (control.value) {
     87		case ROCCAT_COMMON_CONTROL_STATUS_OK:
     88			return 0;
     89		case ROCCAT_COMMON_CONTROL_STATUS_BUSY:
     90			msleep(500);
     91			continue;
     92		case ROCCAT_COMMON_CONTROL_STATUS_INVALID:
     93		case ROCCAT_COMMON_CONTROL_STATUS_CRITICAL:
     94		case ROCCAT_COMMON_CONTROL_STATUS_CRITICAL_NEW:
     95			return -EINVAL;
     96		default:
     97			dev_err(&usb_dev->dev,
     98					"roccat_common2_receive_control_status: "
     99					"unknown response value 0x%x\n",
    100					control.value);
    101			return -EINVAL;
    102		}
    103
    104	} while (1);
    105}
    106
    107int roccat_common2_send_with_status(struct usb_device *usb_dev,
    108		uint command, void const *buf, uint size)
    109{
    110	int retval;
    111
    112	retval = roccat_common2_send(usb_dev, command, buf, size);
    113	if (retval)
    114		return retval;
    115
    116	msleep(100);
    117
    118	return roccat_common2_receive_control_status(usb_dev);
    119}
    120EXPORT_SYMBOL_GPL(roccat_common2_send_with_status);
    121
    122int roccat_common2_device_init_struct(struct usb_device *usb_dev,
    123		struct roccat_common2_device *dev)
    124{
    125	mutex_init(&dev->lock);
    126	return 0;
    127}
    128EXPORT_SYMBOL_GPL(roccat_common2_device_init_struct);
    129
    130ssize_t roccat_common2_sysfs_read(struct file *fp, struct kobject *kobj,
    131		char *buf, loff_t off, size_t count,
    132		size_t real_size, uint command)
    133{
    134	struct device *dev = kobj_to_dev(kobj)->parent->parent;
    135	struct roccat_common2_device *roccat_dev = hid_get_drvdata(dev_get_drvdata(dev));
    136	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
    137	int retval;
    138
    139	if (off >= real_size)
    140		return 0;
    141
    142	if (off != 0 || count != real_size)
    143		return -EINVAL;
    144
    145	mutex_lock(&roccat_dev->lock);
    146	retval = roccat_common2_receive(usb_dev, command, buf, real_size);
    147	mutex_unlock(&roccat_dev->lock);
    148
    149	return retval ? retval : real_size;
    150}
    151EXPORT_SYMBOL_GPL(roccat_common2_sysfs_read);
    152
    153ssize_t roccat_common2_sysfs_write(struct file *fp, struct kobject *kobj,
    154		void const *buf, loff_t off, size_t count,
    155		size_t real_size, uint command)
    156{
    157	struct device *dev = kobj_to_dev(kobj)->parent->parent;
    158	struct roccat_common2_device *roccat_dev = hid_get_drvdata(dev_get_drvdata(dev));
    159	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
    160	int retval;
    161
    162	if (off != 0 || count != real_size)
    163		return -EINVAL;
    164
    165	mutex_lock(&roccat_dev->lock);
    166	retval = roccat_common2_send_with_status(usb_dev, command, buf, real_size);
    167	mutex_unlock(&roccat_dev->lock);
    168
    169	return retval ? retval : real_size;
    170}
    171EXPORT_SYMBOL_GPL(roccat_common2_sysfs_write);
    172
    173MODULE_AUTHOR("Stefan Achatz");
    174MODULE_DESCRIPTION("USB Roccat common driver");
    175MODULE_LICENSE("GPL v2");