Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

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