* [PATCH v8 1/3] scsi: ufs: add ioctl interface for query request
From: Gilad Broner @ 2015-04-14 11:51 UTC (permalink / raw)
To: James.Bottomley-d9PhHud1JfjCXq6kfMZ53/egYHeGw8Jk
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-scsi-u79uwXL29TY76Z2rM5mHXA,
linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
santoshsy-Re5JQEeQqe8AvxtiuMwx3w,
linux-scsi-owner-u79uwXL29TY76Z2rM5mHXA,
subhashj-sgV2jX0FEOL9JmXXK+q4OQ, ygardi-sgV2jX0FEOL9JmXXK+q4OQ,
draviv-sgV2jX0FEOL9JmXXK+q4OQ, Noa Rubens, Raviv Shvili,
Gilad Broner, Vinayak Holikatti, James E.J. Bottomley,
open list:ABI/API
In-Reply-To: <1429012281-24068-1-git-send-email-gbroner-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
From: Dolev Raviv <draviv-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
This patch exposes the ioctl interface for UFS driver via SCSI device
ioctl interface. As of now UFS driver would provide the ioctl for query
interface to connected UFS device.
Signed-off-by: Dolev Raviv <draviv-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
Signed-off-by: Noa Rubens <noag-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
Signed-off-by: Raviv Shvili <rshvili-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
Signed-off-by: Yaniv Gardi <ygardi-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
Signed-off-by: Gilad Broner <gbroner-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
---
drivers/scsi/ufs/ufs.h | 53 +++-------
drivers/scsi/ufs/ufshcd.c | 219 +++++++++++++++++++++++++++++++++++++++++-
include/scsi/scsi.h | 1 +
include/uapi/scsi/Kbuild | 1 +
include/uapi/scsi/ufs/Kbuild | 3 +
include/uapi/scsi/ufs/ioctl.h | 57 +++++++++++
include/uapi/scsi/ufs/ufs.h | 66 +++++++++++++
7 files changed, 356 insertions(+), 44 deletions(-)
create mode 100644 include/uapi/scsi/ufs/Kbuild
create mode 100644 include/uapi/scsi/ufs/ioctl.h
create mode 100644 include/uapi/scsi/ufs/ufs.h
diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 42c459a..1f023c4 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -38,6 +38,7 @@
#include <linux/mutex.h>
#include <linux/types.h>
+#include <scsi/ufs/ufs.h>
#define MAX_CDB_SIZE 16
#define GENERAL_UPIU_REQUEST_SIZE 32
@@ -71,6 +72,16 @@ enum {
UFS_UPIU_RPMB_WLUN = 0xC4,
};
+/**
+ * ufs_is_valid_unit_desc_lun - checks if the given LUN has a unit descriptor
+ * @lun: LU number to check
+ * @return: true if the lun has a matching unit descriptor, false otherwise
+ */
+static inline bool ufs_is_valid_unit_desc_lun(u8 lun)
+{
+ return (lun == UFS_UPIU_RPMB_WLUN || (lun < UFS_UPIU_MAX_GENERAL_LUN));
+}
+
/*
* UFS Protocol Information Unit related definitions
*/
@@ -126,35 +137,6 @@ enum {
UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST = 0x81,
};
-/* Flag idn for Query Requests*/
-enum flag_idn {
- QUERY_FLAG_IDN_FDEVICEINIT = 0x01,
- QUERY_FLAG_IDN_PWR_ON_WPE = 0x03,
- QUERY_FLAG_IDN_BKOPS_EN = 0x04,
-};
-
-/* Attribute idn for Query requests */
-enum attr_idn {
- QUERY_ATTR_IDN_ACTIVE_ICC_LVL = 0x03,
- QUERY_ATTR_IDN_BKOPS_STATUS = 0x05,
- QUERY_ATTR_IDN_EE_CONTROL = 0x0D,
- QUERY_ATTR_IDN_EE_STATUS = 0x0E,
-};
-
-/* Descriptor idn for Query requests */
-enum desc_idn {
- QUERY_DESC_IDN_DEVICE = 0x0,
- QUERY_DESC_IDN_CONFIGURAION = 0x1,
- QUERY_DESC_IDN_UNIT = 0x2,
- QUERY_DESC_IDN_RFU_0 = 0x3,
- QUERY_DESC_IDN_INTERCONNECT = 0x4,
- QUERY_DESC_IDN_STRING = 0x5,
- QUERY_DESC_IDN_RFU_1 = 0x6,
- QUERY_DESC_IDN_GEOMETRY = 0x7,
- QUERY_DESC_IDN_POWER = 0x8,
- QUERY_DESC_IDN_MAX,
-};
-
enum desc_header_offset {
QUERY_DESC_LENGTH_OFFSET = 0x00,
QUERY_DESC_DESC_TYPE_OFFSET = 0x01,
@@ -247,19 +229,6 @@ enum bkops_status {
BKOPS_STATUS_MAX = BKOPS_STATUS_CRITICAL,
};
-/* UTP QUERY Transaction Specific Fields OpCode */
-enum query_opcode {
- UPIU_QUERY_OPCODE_NOP = 0x0,
- UPIU_QUERY_OPCODE_READ_DESC = 0x1,
- UPIU_QUERY_OPCODE_WRITE_DESC = 0x2,
- UPIU_QUERY_OPCODE_READ_ATTR = 0x3,
- UPIU_QUERY_OPCODE_WRITE_ATTR = 0x4,
- UPIU_QUERY_OPCODE_READ_FLAG = 0x5,
- UPIU_QUERY_OPCODE_SET_FLAG = 0x6,
- UPIU_QUERY_OPCODE_CLEAR_FLAG = 0x7,
- UPIU_QUERY_OPCODE_TOGGLE_FLAG = 0x8,
-};
-
/* Query response result code */
enum {
QUERY_RESULT_SUCCESS = 0x00,
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index dfd72af..b6aa7fb 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -3,7 +3,7 @@
*
* This code is based on drivers/scsi/ufs/ufshcd.c
* Copyright (C) 2011-2013 Samsung India Software Operations
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
*
* Authors:
* Santosh Yaraganavi <santosh.sy-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
@@ -39,6 +39,7 @@
#include <linux/async.h>
#include <linux/devfreq.h>
+#include <scsi/ufs/ioctl.h>
#include "ufshcd.h"
#include "unipro.h"
@@ -74,6 +75,9 @@
/* Interrupt aggregation default timeout, unit: 40us */
#define INT_AGGR_DEF_TO 0x02
+/* IOCTL opcode for command - ufs set device read only */
+#define UFS_IOCTL_BLKROSET BLKROSET
+
#define ufshcd_toggle_vreg(_dev, _vreg, _on) \
({ \
int _ret; \
@@ -1885,7 +1889,7 @@ static inline int ufshcd_read_unit_desc_param(struct ufs_hba *hba,
* Unit descriptors are only available for general purpose LUs (LUN id
* from 0 to 7) and RPMB Well known LU.
*/
- if (lun != UFS_UPIU_RPMB_WLUN && (lun >= UFS_UPIU_MAX_GENERAL_LUN))
+ if (!ufs_is_valid_unit_desc_lun(lun))
return -EOPNOTSUPP;
return ufshcd_read_desc_param(hba, QUERY_DESC_IDN_UNIT, lun,
@@ -4236,6 +4240,216 @@ static void ufshcd_async_scan(void *data, async_cookie_t cookie)
ufshcd_probe_hba(hba);
}
+/**
+ * ufshcd_query_ioctl - perform user read queries
+ * @hba: per-adapter instance
+ * @lun: used for lun specific queries
+ * @buffer: user space buffer for reading and submitting query data and params
+ * @return: 0 for success negative error code otherwise
+ *
+ * Expected/Submitted buffer structure is struct ufs_ioctl_query_data.
+ * It will read the opcode, idn and buf_length parameters, and, put the
+ * response in the buffer field while updating the used size in buf_length.
+ */
+static int ufshcd_query_ioctl(struct ufs_hba *hba, u8 lun, void __user *buffer)
+{
+ struct ufs_ioctl_query_data *ioctl_data;
+ int err = 0;
+ int length = 0;
+ void *data_ptr;
+ bool flag;
+ u32 att;
+ u8 index;
+ u8 *desc = NULL;
+
+ if (!buffer) {
+ dev_err(hba->dev, "%s: User buffer is NULL!\n", __func__);
+ return -EINVAL;
+ }
+
+ ioctl_data = kzalloc(sizeof(struct ufs_ioctl_query_data), GFP_KERNEL);
+ if (!ioctl_data) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ /* extract params from user buffer */
+ if (copy_from_user(ioctl_data, buffer, sizeof(*ioctl_data))) {
+ err = -EFAULT;
+ goto out_release_mem;
+ }
+
+ /* verify legal parameters & send query */
+ switch (ioctl_data->opcode) {
+ case UPIU_QUERY_OPCODE_READ_DESC:
+ switch (ioctl_data->idn) {
+ case QUERY_DESC_IDN_DEVICE:
+ case QUERY_DESC_IDN_CONFIGURAION:
+ case QUERY_DESC_IDN_INTERCONNECT:
+ case QUERY_DESC_IDN_GEOMETRY:
+ case QUERY_DESC_IDN_POWER:
+ index = 0;
+ break;
+ case QUERY_DESC_IDN_UNIT:
+ if (!ufs_is_valid_unit_desc_lun(lun)) {
+ dev_err(hba->dev,
+ "%s: No unit descriptor for lun 0x%x\n",
+ __func__, lun);
+ err = -EINVAL;
+ goto out_release_mem;
+ }
+ index = lun;
+ break;
+ default:
+ goto out_einval;
+ }
+ length = min_t(int, QUERY_DESC_MAX_SIZE,
+ ioctl_data->buf_size);
+ desc = kzalloc(length, GFP_KERNEL);
+ if (!desc) {
+ dev_err(hba->dev, "%s: Failed allocating %d bytes\n",
+ __func__, length);
+ err = -ENOMEM;
+ goto out_release_mem;
+ }
+ err = ufshcd_query_descriptor(hba, ioctl_data->opcode,
+ ioctl_data->idn, index, 0, desc, &length);
+ break;
+ case UPIU_QUERY_OPCODE_READ_ATTR:
+ switch (ioctl_data->idn) {
+ case QUERY_ATTR_IDN_BOOT_LU_EN:
+ case QUERY_ATTR_IDN_POWER_MODE:
+ case QUERY_ATTR_IDN_ACTIVE_ICC_LVL:
+ case QUERY_ATTR_IDN_OOO_DATA_EN:
+ case QUERY_ATTR_IDN_BKOPS_STATUS:
+ case QUERY_ATTR_IDN_PURGE_STATUS:
+ case QUERY_ATTR_IDN_MAX_DATA_IN:
+ case QUERY_ATTR_IDN_MAX_DATA_OUT:
+ case QUERY_ATTR_IDN_REF_CLK_FREQ:
+ case QUERY_ATTR_IDN_CONF_DESC_LOCK:
+ case QUERY_ATTR_IDN_MAX_NUM_OF_RTT:
+ case QUERY_ATTR_IDN_EE_CONTROL:
+ case QUERY_ATTR_IDN_EE_STATUS:
+ case QUERY_ATTR_IDN_SECONDS_PASSED:
+ index = 0;
+ break;
+ case QUERY_ATTR_IDN_DYN_CAP_NEEDED:
+ case QUERY_ATTR_IDN_CORR_PRG_BLK_NUM:
+ index = lun;
+ break;
+ default:
+ goto out_einval;
+ }
+ err = ufshcd_query_attr(hba, ioctl_data->opcode,
+ ioctl_data->idn, index, 0, &att);
+ break;
+ case UPIU_QUERY_OPCODE_READ_FLAG:
+ switch (ioctl_data->idn) {
+ case QUERY_FLAG_IDN_FDEVICEINIT:
+ case QUERY_FLAG_IDN_PERMANENT_WPE:
+ case QUERY_FLAG_IDN_PWR_ON_WPE:
+ case QUERY_FLAG_IDN_BKOPS_EN:
+ case QUERY_FLAG_IDN_PURGE_ENABLE:
+ case QUERY_FLAG_IDN_FPHYRESOURCEREMOVAL:
+ case QUERY_FLAG_IDN_BUSY_RTC:
+ break;
+ default:
+ goto out_einval;
+ }
+ err = ufshcd_query_flag(hba, ioctl_data->opcode,
+ ioctl_data->idn, &flag);
+ break;
+ default:
+ goto out_einval;
+ }
+
+ if (err) {
+ dev_err(hba->dev, "%s: Query for idn %d failed\n", __func__,
+ ioctl_data->idn);
+ goto out_release_mem;
+ }
+
+ /*
+ * copy response data
+ * As we might end up reading less data then what is specified in
+ * "ioct_data->buf_size". So we are updating "ioct_data->
+ * buf_size" to what exactly we have read.
+ */
+ switch (ioctl_data->opcode) {
+ case UPIU_QUERY_OPCODE_READ_DESC:
+ ioctl_data->buf_size = min_t(int, ioctl_data->buf_size, length);
+ data_ptr = desc;
+ break;
+ case UPIU_QUERY_OPCODE_READ_ATTR:
+ ioctl_data->buf_size = sizeof(u32);
+ data_ptr = &att;
+ break;
+ case UPIU_QUERY_OPCODE_READ_FLAG:
+ ioctl_data->buf_size = 1;
+ data_ptr = &flag;
+ break;
+ default:
+ BUG_ON(true);
+ }
+
+ /* copy to user */
+ err = copy_to_user(buffer, ioctl_data, sizeof(*ioctl_data));
+ if (!err)
+ err = copy_to_user(buffer + sizeof(*ioctl_data), data_ptr,
+ ioctl_data->buf_size);
+ if (err)
+ err = -EFAULT;
+
+ goto out_release_mem;
+
+out_einval:
+ dev_err(hba->dev,
+ "%s: illegal ufs query ioctl data, opcode 0x%x, idn 0x%x\n",
+ __func__, ioctl_data->opcode, (unsigned int)ioctl_data->idn);
+ err = -EINVAL;
+out_release_mem:
+ kfree(ioctl_data);
+ kfree(desc);
+out:
+ return err;
+}
+
+/**
+ * ufshcd_ioctl - ufs ioctl callback registered in scsi_host
+ * @dev: scsi device required for per LUN queries
+ * @cmd: command opcode
+ * @buffer: user space buffer for transferring data
+ *
+ * Supported commands:
+ * UFS_IOCTL_QUERY
+ */
+static int ufshcd_ioctl(struct scsi_device *dev, int cmd, void __user *buffer)
+{
+ struct ufs_hba *hba = shost_priv(dev->host);
+ int err = 0;
+
+ BUG_ON(!hba);
+
+ switch (cmd) {
+ case UFS_IOCTL_QUERY:
+ pm_runtime_get_sync(hba->dev);
+ err = ufshcd_query_ioctl(hba, ufshcd_scsi_to_upiu_lun(dev->lun),
+ buffer);
+ pm_runtime_put_sync(hba->dev);
+ break;
+ case UFS_IOCTL_BLKROSET:
+ err = -ENOIOCTLCMD;
+ break;
+ default:
+ err = -EINVAL;
+ dev_err(hba->dev, "%s: Illegal ufs-IOCTL cmd %d\n", __func__,
+ cmd);
+ break;
+ }
+
+ return err;
+}
+
static struct scsi_host_template ufshcd_driver_template = {
.module = THIS_MODULE,
.name = UFSHCD,
@@ -4248,6 +4462,7 @@ static struct scsi_host_template ufshcd_driver_template = {
.eh_abort_handler = ufshcd_abort,
.eh_device_reset_handler = ufshcd_eh_device_reset_handler,
.eh_host_reset_handler = ufshcd_eh_host_reset_handler,
+ .ioctl = ufshcd_ioctl,
.this_id = -1,
.sg_tablesize = SG_ALL,
.cmd_per_lun = UFSHCD_CMD_PER_LUN,
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index d0a66aa..3feb501 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -569,6 +569,7 @@ static inline int scsi_is_wlun(u64 lun)
* Here are some scsi specific ioctl commands which are sometimes useful.
*
* Note that include/linux/cdrom.h also defines IOCTL 0x5300 - 0x5395
+ * include/uapi/scsi/ufs/ioctl.h defines 0x5388
*/
/* Used to obtain PUN and LUN info. Conflicts with CDROMAUDIOBUFSIZ */
diff --git a/include/uapi/scsi/Kbuild b/include/uapi/scsi/Kbuild
index 75746d5..d404525 100644
--- a/include/uapi/scsi/Kbuild
+++ b/include/uapi/scsi/Kbuild
@@ -1,5 +1,6 @@
# UAPI Header export list
header-y += fc/
+header-y += ufs/
header-y += scsi_bsg_fc.h
header-y += scsi_netlink.h
header-y += scsi_netlink_fc.h
diff --git a/include/uapi/scsi/ufs/Kbuild b/include/uapi/scsi/ufs/Kbuild
new file mode 100644
index 0000000..cc3ef20
--- /dev/null
+++ b/include/uapi/scsi/ufs/Kbuild
@@ -0,0 +1,3 @@
+# UAPI Header export list
+header-y += ioctl.h
+header-y += ufs.h
diff --git a/include/uapi/scsi/ufs/ioctl.h b/include/uapi/scsi/ufs/ioctl.h
new file mode 100644
index 0000000..bc4eed7
--- /dev/null
+++ b/include/uapi/scsi/ufs/ioctl.h
@@ -0,0 +1,57 @@
+#ifndef UAPI_UFS_IOCTL_H_
+#define UAPI_UFS_IOCTL_H_
+
+#include <linux/types.h>
+
+/*
+ * IOCTL opcode for ufs queries has the following opcode after
+ * SCSI_IOCTL_GET_PCI
+ */
+#define UFS_IOCTL_QUERY 0x5388
+
+/**
+ * struct ufs_ioctl_query_data - used to transfer data to and from user via ioctl
+ * @opcode: type of data to query (descriptor/attribute/flag)
+ * @idn: id of the data structure
+ * @buf_size: number of allocated bytes/data size on return
+ * @buffer: data location
+ *
+ * Received: buffer and buf_size (available space for transferred data)
+ * Submitted: opcode, idn, length, buf_size
+ */
+struct ufs_ioctl_query_data {
+ /*
+ * User should select one of the opcode defined in "enum query_opcode".
+ * Please check include/uapi/scsi/ufs/ufs.h for the definition of it.
+ * Note that only UPIU_QUERY_OPCODE_READ_DESC,
+ * UPIU_QUERY_OPCODE_READ_ATTR & UPIU_QUERY_OPCODE_READ_FLAG are
+ * supported as of now. All other query_opcode would be considered
+ * invalid.
+ * As of now only read query operations are supported.
+ */
+ __u32 opcode;
+ /*
+ * User should select one of the idn from "enum flag_idn" or "enum
+ * attr_idn" or "enum desc_idn" based on whether opcode above is
+ * attribute, flag or descriptor.
+ * Please check include/uapi/scsi/ufs/ufs.h for the definition of it.
+ */
+ __u8 idn;
+ /*
+ * User should specify the size of the buffer (buffer[0] below) where
+ * it wants to read the query data (attribute/flag/descriptor).
+ * As we might end up reading less data then what is specified in
+ * buf_size. So we are updating buf_size to what exactly we have read.
+ */
+ __u16 buf_size;
+ /*
+ * placeholder for the start of the data buffer where kernel will copy
+ * the query data (attribute/flag/descriptor) read from the UFS device
+ * Note:
+ * For Read Attribute you will have to allocate 4 bytes
+ * For Read Flag you will have to allocate 1 byte
+ */
+ __u8 buffer[0];
+};
+
+#endif /* UAPI_UFS_IOCTL_H_ */
diff --git a/include/uapi/scsi/ufs/ufs.h b/include/uapi/scsi/ufs/ufs.h
new file mode 100644
index 0000000..894ea45
--- /dev/null
+++ b/include/uapi/scsi/ufs/ufs.h
@@ -0,0 +1,66 @@
+#ifndef UAPI_UFS_H_
+#define UAPI_UFS_H_
+
+/* Flag idn for Query Requests*/
+enum flag_idn {
+ QUERY_FLAG_IDN_FDEVICEINIT = 0x01,
+ QUERY_FLAG_IDN_PERMANENT_WPE = 0x02,
+ QUERY_FLAG_IDN_PWR_ON_WPE = 0x03,
+ QUERY_FLAG_IDN_BKOPS_EN = 0x04,
+ QUERY_FLAG_IDN_RESERVED1 = 0x05,
+ QUERY_FLAG_IDN_PURGE_ENABLE = 0x06,
+ QUERY_FLAG_IDN_RESERVED2 = 0x07,
+ QUERY_FLAG_IDN_FPHYRESOURCEREMOVAL = 0x08,
+ QUERY_FLAG_IDN_BUSY_RTC = 0x09,
+};
+
+/* Attribute idn for Query requests */
+enum attr_idn {
+ QUERY_ATTR_IDN_BOOT_LU_EN = 0x00,
+ QUERY_ATTR_IDN_RESERVED = 0x01,
+ QUERY_ATTR_IDN_POWER_MODE = 0x02,
+ QUERY_ATTR_IDN_ACTIVE_ICC_LVL = 0x03,
+ QUERY_ATTR_IDN_OOO_DATA_EN = 0x04,
+ QUERY_ATTR_IDN_BKOPS_STATUS = 0x05,
+ QUERY_ATTR_IDN_PURGE_STATUS = 0x06,
+ QUERY_ATTR_IDN_MAX_DATA_IN = 0x07,
+ QUERY_ATTR_IDN_MAX_DATA_OUT = 0x08,
+ QUERY_ATTR_IDN_DYN_CAP_NEEDED = 0x09,
+ QUERY_ATTR_IDN_REF_CLK_FREQ = 0x0A,
+ QUERY_ATTR_IDN_CONF_DESC_LOCK = 0x0B,
+ QUERY_ATTR_IDN_MAX_NUM_OF_RTT = 0x0C,
+ QUERY_ATTR_IDN_EE_CONTROL = 0x0D,
+ QUERY_ATTR_IDN_EE_STATUS = 0x0E,
+ QUERY_ATTR_IDN_SECONDS_PASSED = 0x0F,
+ QUERY_ATTR_IDN_CNTX_CONF = 0x10,
+ QUERY_ATTR_IDN_CORR_PRG_BLK_NUM = 0x11,
+};
+
+/* Descriptor idn for Query requests */
+enum desc_idn {
+ QUERY_DESC_IDN_DEVICE = 0x0,
+ QUERY_DESC_IDN_CONFIGURAION = 0x1,
+ QUERY_DESC_IDN_UNIT = 0x2,
+ QUERY_DESC_IDN_RFU_0 = 0x3,
+ QUERY_DESC_IDN_INTERCONNECT = 0x4,
+ QUERY_DESC_IDN_STRING = 0x5,
+ QUERY_DESC_IDN_RFU_1 = 0x6,
+ QUERY_DESC_IDN_GEOMETRY = 0x7,
+ QUERY_DESC_IDN_POWER = 0x8,
+ QUERY_DESC_IDN_RFU_2 = 0x9,
+ QUERY_DESC_IDN_MAX,
+};
+
+/* UTP QUERY Transaction Specific Fields OpCode */
+enum query_opcode {
+ UPIU_QUERY_OPCODE_NOP = 0x0,
+ UPIU_QUERY_OPCODE_READ_DESC = 0x1,
+ UPIU_QUERY_OPCODE_WRITE_DESC = 0x2,
+ UPIU_QUERY_OPCODE_READ_ATTR = 0x3,
+ UPIU_QUERY_OPCODE_WRITE_ATTR = 0x4,
+ UPIU_QUERY_OPCODE_READ_FLAG = 0x5,
+ UPIU_QUERY_OPCODE_SET_FLAG = 0x6,
+ UPIU_QUERY_OPCODE_CLEAR_FLAG = 0x7,
+ UPIU_QUERY_OPCODE_TOGGLE_FLAG = 0x8,
+};
+#endif /* UAPI_UFS_H_ */
--
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related
* Re: [PATCH v4 7/8] vhost: feature to set the vring endianness
From: Cornelia Huck @ 2015-04-14 14:20 UTC (permalink / raw)
To: Greg Kurz
Cc: Rusty Russell, Michael S. Tsirkin,
linux-api-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, kvm-u79uwXL29TY76Z2rM5mHXA,
virtualization-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
In-Reply-To: <20150410101627.31843.21710.stgit-GiB8zCg7hOfDOqzlkpFKJg@public.gmane.org>
On Fri, 10 Apr 2015 12:19:16 +0200
Greg Kurz <gkurz-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org> wrote:
> This patch brings cross-endian support to vhost when used to implement
> legacy virtio devices. Since it is a relatively rare situation, the
> feature availability is controlled by a kernel config option (not set
> by default).
>
> The vq->is_le boolean field is added to cache the endianness to be
> used for ring accesses. It defaults to native endian, as expected
> by legacy virtio devices. When the ring gets active, we force little
> endian if the device is modern. When the ring is deactivated, we
> revert to the native endian default.
>
> If cross-endian was compiled in, a vq->user_be boolean field is added
> so that userspace may request a specific endianness. This field is
> used to override the default when activating the ring of a legacy
> device. It has no effect on modern devices.
>
> Signed-off-by: Greg Kurz <gkurz-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
> ---
> drivers/vhost/Kconfig | 10 ++++++
> drivers/vhost/vhost.c | 76 +++++++++++++++++++++++++++++++++++++++++++-
> drivers/vhost/vhost.h | 12 +++++--
> include/uapi/linux/vhost.h | 9 +++++
> 4 files changed, 103 insertions(+), 4 deletions(-)
> +#ifdef CONFIG_VHOST_SET_ENDIAN_LEGACY
> +static long vhost_set_vring_big_endian(struct vhost_virtqueue *vq,
> + int __user *argp)
> +{
> + struct vhost_vring_state s;
> +
> + if (vq->private_data)
> + return -EBUSY;
> +
> + if (copy_from_user(&s, argp, sizeof(s)))
> + return -EFAULT;
> +
> + if (s.num && s.num != 1)
Checking for s.num > 1 might be more obvious at a glance?
> + return -EINVAL;
> +
> + vq->user_be = s.num;
> +
> + return 0;
> +}
> +
(...)
> +#ifdef CONFIG_VHOST_SET_ENDIAN_LEGACY
> +static void vhost_init_is_le(struct vhost_virtqueue *vq)
> +{
> + vq->is_le = vhost_has_feature(vq, VIRTIO_F_VERSION_1) || !vq->user_be;
So if the endianness is not explicitly set to BE, it will be forced to
LE (instead of native endian)? Won't that break userspace that does not
yet use the new interface when CONFIG_VHOST_SET_ENDIAN_LEGACY is set?
> +}
> +#else
> +static void vhost_init_is_le(struct vhost_virtqueue *vq)
> +{
> + if (vhost_has_feature(vq, VIRTIO_F_VERSION_1))
> + vq->is_le = true;
> +}
> +#endif
> +
> int vhost_init_used(struct vhost_virtqueue *vq)
> {
> __virtio16 last_used_idx;
> int r;
> - if (!vq->private_data)
> + if (!vq->private_data) {
> + vq->is_le = virtio_legacy_is_little_endian();
> return 0;
> + }
> +
> + vhost_init_is_le(vq);
>
> r = vhost_update_used_flags(vq);
> if (r)
^ permalink raw reply
* Re: [PATCH v4 7/8] vhost: feature to set the vring endianness
From: Greg Kurz @ 2015-04-14 15:13 UTC (permalink / raw)
To: Cornelia Huck
Cc: Rusty Russell, Michael S. Tsirkin,
linux-api-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, kvm-u79uwXL29TY76Z2rM5mHXA,
virtualization-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
In-Reply-To: <20150414162023.2f8694fe.cornelia.huck-tA70FqPdS9bQT0dZR+AlfA@public.gmane.org>
On Tue, 14 Apr 2015 16:20:23 +0200
Cornelia Huck <cornelia.huck-tA70FqPdS9bQT0dZR+AlfA@public.gmane.org> wrote:
> On Fri, 10 Apr 2015 12:19:16 +0200
> Greg Kurz <gkurz-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org> wrote:
>
> > This patch brings cross-endian support to vhost when used to implement
> > legacy virtio devices. Since it is a relatively rare situation, the
> > feature availability is controlled by a kernel config option (not set
> > by default).
> >
> > The vq->is_le boolean field is added to cache the endianness to be
> > used for ring accesses. It defaults to native endian, as expected
> > by legacy virtio devices. When the ring gets active, we force little
> > endian if the device is modern. When the ring is deactivated, we
> > revert to the native endian default.
> >
> > If cross-endian was compiled in, a vq->user_be boolean field is added
> > so that userspace may request a specific endianness. This field is
> > used to override the default when activating the ring of a legacy
> > device. It has no effect on modern devices.
> >
> > Signed-off-by: Greg Kurz <gkurz-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
> > ---
> > drivers/vhost/Kconfig | 10 ++++++
> > drivers/vhost/vhost.c | 76 +++++++++++++++++++++++++++++++++++++++++++-
> > drivers/vhost/vhost.h | 12 +++++--
> > include/uapi/linux/vhost.h | 9 +++++
> > 4 files changed, 103 insertions(+), 4 deletions(-)
>
> > +#ifdef CONFIG_VHOST_SET_ENDIAN_LEGACY
> > +static long vhost_set_vring_big_endian(struct vhost_virtqueue *vq,
> > + int __user *argp)
> > +{
> > + struct vhost_vring_state s;
> > +
> > + if (vq->private_data)
> > + return -EBUSY;
> > +
> > + if (copy_from_user(&s, argp, sizeof(s)))
> > + return -EFAULT;
> > +
> > + if (s.num && s.num != 1)
>
> Checking for s.num > 1 might be more obvious at a glance?
>
Sure since s.num is unsigned.
> > + return -EINVAL;
> > +
> > + vq->user_be = s.num;
> > +
> > + return 0;
> > +}
> > +
>
> (...)
>
> > +#ifdef CONFIG_VHOST_SET_ENDIAN_LEGACY
> > +static void vhost_init_is_le(struct vhost_virtqueue *vq)
> > +{
> > + vq->is_le = vhost_has_feature(vq, VIRTIO_F_VERSION_1) || !vq->user_be;
>
> So if the endianness is not explicitly set to BE, it will be forced to
> LE (instead of native endian)? Won't that break userspace that does not
> yet use the new interface when CONFIG_VHOST_SET_ENDIAN_LEGACY is set?
>
If userspace doesn't use the new interface, then vq->user_be will retain its
default value that was set in vhost_vq_reset(), i.e. :
vq->user_be = !virtio_legacy_is_little_endian();
This means default is native endian.
What about adding this comment ?
static void vhost_init_is_le(struct vhost_virtqueue *vq)
{
/* Note for legacy virtio: user_be is initialized in vhost_vq_reset()
* according to the host endianness. If userspace does not set an
* explicit endianness, the default behavior is native endian, as
* expected by legacy virtio.
*/
vq->is_le = vhost_has_feature(vq, VIRTIO_F_VERSION_1) || !vq->user_be;
}
> > +}
> > +#else
> > +static void vhost_init_is_le(struct vhost_virtqueue *vq)
> > +{
> > + if (vhost_has_feature(vq, VIRTIO_F_VERSION_1))
> > + vq->is_le = true;
> > +}
> > +#endif
> > +
> > int vhost_init_used(struct vhost_virtqueue *vq)
> > {
> > __virtio16 last_used_idx;
> > int r;
> > - if (!vq->private_data)
> > + if (!vq->private_data) {
> > + vq->is_le = virtio_legacy_is_little_endian();
> > return 0;
> > + }
> > +
> > + vhost_init_is_le(vq);
> >
> > r = vhost_update_used_flags(vq);
> > if (r)
^ permalink raw reply
* Re: [PATCH v4 7/8] vhost: feature to set the vring endianness
From: Cornelia Huck @ 2015-04-14 15:22 UTC (permalink / raw)
To: Greg Kurz
Cc: kvm, Michael S. Tsirkin, linux-api, linux-kernel, virtualization
In-Reply-To: <20150414171352.105909ae@bahia.local>
On Tue, 14 Apr 2015 17:13:52 +0200
Greg Kurz <gkurz@linux.vnet.ibm.com> wrote:
> On Tue, 14 Apr 2015 16:20:23 +0200
> Cornelia Huck <cornelia.huck@de.ibm.com> wrote:
>
> > On Fri, 10 Apr 2015 12:19:16 +0200
> > Greg Kurz <gkurz@linux.vnet.ibm.com> wrote:
> >
> > > +#ifdef CONFIG_VHOST_SET_ENDIAN_LEGACY
> > > +static void vhost_init_is_le(struct vhost_virtqueue *vq)
> > > +{
> > > + vq->is_le = vhost_has_feature(vq, VIRTIO_F_VERSION_1) || !vq->user_be;
> >
> > So if the endianness is not explicitly set to BE, it will be forced to
> > LE (instead of native endian)? Won't that break userspace that does not
> > yet use the new interface when CONFIG_VHOST_SET_ENDIAN_LEGACY is set?
> >
>
> If userspace doesn't use the new interface, then vq->user_be will retain its
> default value that was set in vhost_vq_reset(), i.e. :
>
> vq->user_be = !virtio_legacy_is_little_endian();
>
> This means default is native endian.
>
> What about adding this comment ?
>
> static void vhost_init_is_le(struct vhost_virtqueue *vq)
> {
> /* Note for legacy virtio: user_be is initialized in vhost_vq_reset()
> * according to the host endianness. If userspace does not set an
> * explicit endianness, the default behavior is native endian, as
> * expected by legacy virtio.
> */
Good idea, as this is easy to miss.
> vq->is_le = vhost_has_feature(vq, VIRTIO_F_VERSION_1) || !vq->user_be;
> }
>
> > > +}
> > > +#else
> > > +static void vhost_init_is_le(struct vhost_virtqueue *vq)
> > > +{
> > > + if (vhost_has_feature(vq, VIRTIO_F_VERSION_1))
> > > + vq->is_le = true;
> > > +}
> > > +#endif
> > > +
> > > int vhost_init_used(struct vhost_virtqueue *vq)
> > > {
> > > __virtio16 last_used_idx;
> > > int r;
> > > - if (!vq->private_data)
> > > + if (!vq->private_data) {
> > > + vq->is_le = virtio_legacy_is_little_endian();
> > > return 0;
> > > + }
> > > +
> > > + vhost_init_is_le(vq);
> > >
> > > r = vhost_update_used_flags(vq);
> > > if (r)
>
^ permalink raw reply
* [PATCH/RFC 0/2] Repurpose the v4l2_plane data_offset field
From: Laurent Pinchart @ 2015-04-14 19:44 UTC (permalink / raw)
To: linux-media-u79uwXL29TY76Z2rM5mHXA
Cc: linux-api-u79uwXL29TY76Z2rM5mHXA, Sakari Ailus, Hans Verkuil,
Pawel Osciak, Marek Szyprowski, Mauro Carvalho Chehab
Hello,
The v4l2_plane data_offset field has been introduced at the same time as the
the multiplane API to convey header size information between kernelspace and
userspace.
The API then became slightly controversial, both because different developers
understood the purpose of the field differently (resulting for instance in an
out-of-tree driver abusing the field for a different purpose), and because of
competing proposals (see for instance "[RFC] Multi format stream support" at
http://www.spinics.net/lists/linux-media/msg69130.html).
Furthermore, the data_offset field isn't used by any mainline driver except
vivid (for testing purpose).
I need a different data offset in planes to allow data capture to or data
output from a userspace-selected offset within a buffer (mainly for the
DMABUF and MMAP memory types). As the data_offset field already has the
right name, is unused, and ill-defined, I propose repurposing it. This is what
this RFC is about.
If the proposal is accepted I'll add another patch to update data_offset usage
in the vivid driver.
Laurent Pinchart (2):
v4l: Repurpose the v4l2_plane data_offset field
videobuf2: Repurpose the v4l2_plane data_offset field
Documentation/DocBook/media/v4l/io.xml | 19 +++++++------
drivers/media/v4l2-core/videobuf2-core.c | 46 +++++++++++++++++++++++---------
include/media/videobuf2-core.h | 4 +++
include/media/videobuf2-dma-contig.h | 2 +-
include/uapi/linux/videodev2.h | 6 +++--
5 files changed, 54 insertions(+), 23 deletions(-)
--
Regards,
Laurent Pinchart
^ permalink raw reply
* [PATCH/RFC 1/2] v4l: Repurpose the v4l2_plane data_offset field
From: Laurent Pinchart @ 2015-04-14 19:44 UTC (permalink / raw)
To: linux-media
Cc: linux-api, Sakari Ailus, Hans Verkuil, Pawel Osciak,
Marek Szyprowski, Mauro Carvalho Chehab
In-Reply-To: <1429040689-23808-1-git-send-email-laurent.pinchart@ideasonboard.com>
The data_offset field has been introduced along with the multiplane API
to convey header size information between kernelspace and userspace.
It's not used by any mainline driver except vivid (for testing purpose).
A different data offset is needed to allow data capture to or data
output from a userspace-selected offset within a buffer (mainly for the
DMABUF and MMAP memory types). As the data_offset field already has the
right name and is unused, repurpose it.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
Documentation/DocBook/media/v4l/io.xml | 19 +++++++++++--------
include/uapi/linux/videodev2.h | 6 ++++--
2 files changed, 15 insertions(+), 10 deletions(-)
diff --git a/Documentation/DocBook/media/v4l/io.xml b/Documentation/DocBook/media/v4l/io.xml
index 1c17f80..416c05a 100644
--- a/Documentation/DocBook/media/v4l/io.xml
+++ b/Documentation/DocBook/media/v4l/io.xml
@@ -870,7 +870,7 @@ should set this to 0.</entry>
If the application sets this to 0 for an output stream, then
<structfield>bytesused</structfield> will be set to the size of the
plane (see the <structfield>length</structfield> field of this struct)
- by the driver. Note that the actual image data starts at
+ by the driver. Note that the actual plane data content starts at
<structfield>data_offset</structfield> which may not be 0.</entry>
</row>
<row>
@@ -917,13 +917,16 @@ should set this to 0.</entry>
<entry>__u32</entry>
<entry><structfield>data_offset</structfield></entry>
<entry></entry>
- <entry>Offset in bytes to video data in the plane.
- Drivers must set this field when <structfield>type</structfield>
- refers to an input stream, applications when it refers to an output stream.
- Note that data_offset is included in <structfield>bytesused</structfield>.
- So the size of the image in the plane is
- <structfield>bytesused</structfield>-<structfield>data_offset</structfield> at
- offset <structfield>data_offset</structfield> from the start of the plane.
+ <entry>Offset in bytes from the start of the plane buffer to the start of
+ captured or output data. Applications set this field for all stream types
+ when calling the <link linkend="vidioc-qbuf">VIDIOC_PREPARE_BUF</link> or
+ <link linkend="vidioc-qbuf">VIDIOC_QBUF</link> ioctls to instruct the driver
+ to capture or output data starting at an offset in the plane buffer. If the
+ requested data offset doesn't match device or driver constraints, device
+ drivers must return the &EINVAL; and either leave the field value untouched
+ if they support data offsets, or set it to 0 if they don't support data
+ offsets at all. Note that <structfield>data_offset</structfield> is not
+ included in <structfield>bytesused</structfield>.
</entry>
</row>
<row>
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index fa376f7..261fb66 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -706,8 +706,10 @@ struct v4l2_requestbuffers {
* pointing to this plane
* @fd: when memory is V4L2_MEMORY_DMABUF, a userspace file
* descriptor associated with this plane
- * @data_offset: offset in the plane to the start of data; usually 0,
- * unless there is a header in front of the data
+ * @data_offset: offset in bytes from the start of the plane buffer to
+ * the start of data; usually 0 unless applications need to
+ * capture data to or output data from elsewhere than the
+ * start of the buffer
*
* Multi-planar buffers consist of one or more planes, e.g. an YCbCr buffer
* with two planes can have one plane for Y, and another for interleaved CbCr
--
2.0.5
^ permalink raw reply related
* [PATCH/RFC 2/2] videobuf2: Repurpose the v4l2_plane data_offset field
From: Laurent Pinchart @ 2015-04-14 19:44 UTC (permalink / raw)
To: linux-media-u79uwXL29TY76Z2rM5mHXA
Cc: linux-api-u79uwXL29TY76Z2rM5mHXA, Sakari Ailus, Hans Verkuil,
Pawel Osciak, Marek Szyprowski, Mauro Carvalho Chehab
In-Reply-To: <1429040689-23808-1-git-send-email-laurent.pinchart-ryLnwIuWjnjg/C1BVhZhaw@public.gmane.org>
The v4l2_plane data_offset field has been repurposed in the V4L2 API.
Update videobuf2 accordingly.
Signed-off-by: Laurent Pinchart <laurent.pinchart-ryLnwIuWjnjg/C1BVhZhaw@public.gmane.org>
---
drivers/media/v4l2-core/videobuf2-core.c | 46 +++++++++++++++++++++++---------
include/media/videobuf2-core.h | 4 +++
include/media/videobuf2-dma-contig.h | 2 +-
3 files changed, 39 insertions(+), 13 deletions(-)
diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index 1329dcc..43f8fc5 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -572,15 +572,29 @@ static int __verify_planes_array(struct vb2_buffer *vb, const struct v4l2_buffer
}
/**
- * __verify_length() - Verify that the bytesused value for each plane fits in
- * the plane length and that the data offset doesn't exceed the bytesused value.
+ * __verify_length() - Verify for each plane that the data_offset matches driver
+ * constraints and that the bytesused plus data_offset value fits in the plane
+ * length.
*/
-static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b)
+static int __verify_length(struct vb2_buffer *vb, struct v4l2_buffer *b)
{
unsigned int length;
unsigned int bytesused;
+ unsigned int size;
unsigned int plane;
+ if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
+ unsigned int mask = vb->vb2_queue->data_offset_mask;
+
+ for (plane = 0; plane < vb->num_planes; ++plane) {
+ if (b->m.planes[plane].data_offset & ~mask) {
+ if (!mask)
+ b->m.planes[plane].data_offset = 0;
+ return -EINVAL;
+ }
+ }
+ }
+
if (!V4L2_TYPE_IS_OUTPUT(b->type))
return 0;
@@ -590,14 +604,16 @@ static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b)
b->memory == V4L2_MEMORY_DMABUF)
? b->m.planes[plane].length
: vb->v4l2_planes[plane].length;
- bytesused = b->m.planes[plane].bytesused
- ? b->m.planes[plane].bytesused : length;
- if (b->m.planes[plane].bytesused > length)
+ if (b->m.planes[plane].data_offset >= length)
return -EINVAL;
- if (b->m.planes[plane].data_offset > 0 &&
- b->m.planes[plane].data_offset >= bytesused)
+ size = b->m.planes[plane].bytesused
+ + b->m.planes[plane].data_offset;
+
+ /* Protect against integer overflows. */
+ if (size < b->m.planes[plane].bytesused ||
+ size > length)
return -EINVAL;
}
} else {
@@ -1122,11 +1138,13 @@ EXPORT_SYMBOL_GPL(vb2_create_bufs);
*/
void *vb2_plane_vaddr(struct vb2_buffer *vb, unsigned int plane_no)
{
+ void *addr;
+
if (plane_no > vb->num_planes || !vb->planes[plane_no].mem_priv)
return NULL;
- return call_ptr_memop(vb, vaddr, vb->planes[plane_no].mem_priv);
-
+ addr = call_ptr_memop(vb, vaddr, vb->planes[plane_no].mem_priv);
+ return addr + vb->v4l2_planes[plane_no].data_offset;
}
EXPORT_SYMBOL_GPL(vb2_plane_vaddr);
@@ -1258,6 +1276,11 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
}
if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
+ for (plane = 0; plane < vb->num_planes; ++plane) {
+ v4l2_planes[plane].data_offset =
+ b->m.planes[plane].data_offset;
+ }
+
if (b->memory == V4L2_MEMORY_USERPTR) {
for (plane = 0; plane < vb->num_planes; ++plane) {
v4l2_planes[plane].m.userptr =
@@ -1302,7 +1325,6 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
else
pdst->bytesused = psrc->bytesused ?
psrc->bytesused : pdst->length;
- pdst->data_offset = psrc->data_offset;
}
}
} else {
@@ -1618,7 +1640,7 @@ static void __enqueue_in_driver(struct vb2_buffer *vb)
call_void_vb_qop(vb, buf_queue, vb);
}
-static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b)
+static int __buf_prepare(struct vb2_buffer *vb, struct v4l2_buffer *b)
{
struct vb2_queue *q = vb->vb2_queue;
int ret;
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index a5790fd..c51c481 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -362,6 +362,9 @@ struct v4l2_fh;
* start_streaming() can be called. Used when a DMA engine
* cannot be started unless at least this number of buffers
* have been queued into the driver.
+ * @data_offset_mask: the data_offset alignment constraints expressed as a
+ * mask of bits that can be set in the data_offset value; "0"
+ * indicates the driver doesn't support data_offset
*
* @mmap_lock: private mutex used when buffers are allocated/freed/mmapped
* @memory: current memory type used
@@ -401,6 +404,7 @@ struct vb2_queue {
u32 timestamp_flags;
gfp_t gfp_flags;
u32 min_buffers_needed;
+ u32 data_offset_mask;
/* private: internal use only */
struct mutex mmap_lock;
diff --git a/include/media/videobuf2-dma-contig.h b/include/media/videobuf2-dma-contig.h
index 8197f87..ff60fac 100644
--- a/include/media/videobuf2-dma-contig.h
+++ b/include/media/videobuf2-dma-contig.h
@@ -21,7 +21,7 @@ vb2_dma_contig_plane_dma_addr(struct vb2_buffer *vb, unsigned int plane_no)
{
dma_addr_t *addr = vb2_plane_cookie(vb, plane_no);
- return *addr;
+ return *addr + vb->v4l2_planes[plane_no].data_offset;
}
void *vb2_dma_contig_init_ctx(struct device *dev);
--
2.0.5
^ permalink raw reply related
* Re: [PATCH/RFC 1/2] v4l: Repurpose the v4l2_plane data_offset field
From: Sakari Ailus @ 2015-04-14 20:10 UTC (permalink / raw)
To: Laurent Pinchart
Cc: linux-media, linux-api, Sakari Ailus, Hans Verkuil, Pawel Osciak,
Marek Szyprowski, Mauro Carvalho Chehab
In-Reply-To: <1429040689-23808-2-git-send-email-laurent.pinchart@ideasonboard.com>
Hi Laurent,
Thank you for the patchset.
On Tue, Apr 14, 2015 at 10:44:48PM +0300, Laurent Pinchart wrote:
> The data_offset field has been introduced along with the multiplane API
> to convey header size information between kernelspace and userspace.
> It's not used by any mainline driver except vivid (for testing purpose).
>
> A different data offset is needed to allow data capture to or data
> output from a userspace-selected offset within a buffer (mainly for the
> DMABUF and MMAP memory types). As the data_offset field already has the
> right name and is unused, repurpose it.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> Documentation/DocBook/media/v4l/io.xml | 19 +++++++++++--------
> include/uapi/linux/videodev2.h | 6 ++++--
> 2 files changed, 15 insertions(+), 10 deletions(-)
>
> diff --git a/Documentation/DocBook/media/v4l/io.xml b/Documentation/DocBook/media/v4l/io.xml
> index 1c17f80..416c05a 100644
> --- a/Documentation/DocBook/media/v4l/io.xml
> +++ b/Documentation/DocBook/media/v4l/io.xml
> @@ -870,7 +870,7 @@ should set this to 0.</entry>
> If the application sets this to 0 for an output stream, then
> <structfield>bytesused</structfield> will be set to the size of the
> plane (see the <structfield>length</structfield> field of this struct)
> - by the driver. Note that the actual image data starts at
> + by the driver. Note that the actual plane data content starts at
> <structfield>data_offset</structfield> which may not be 0.</entry>
> </row>
> <row>
> @@ -917,13 +917,16 @@ should set this to 0.</entry>
> <entry>__u32</entry>
> <entry><structfield>data_offset</structfield></entry>
> <entry></entry>
> - <entry>Offset in bytes to video data in the plane.
> - Drivers must set this field when <structfield>type</structfield>
> - refers to an input stream, applications when it refers to an output stream.
> - Note that data_offset is included in <structfield>bytesused</structfield>.
> - So the size of the image in the plane is
> - <structfield>bytesused</structfield>-<structfield>data_offset</structfield> at
> - offset <structfield>data_offset</structfield> from the start of the plane.
> + <entry>Offset in bytes from the start of the plane buffer to the start of
> + captured or output data. Applications set this field for all stream types
> + when calling the <link linkend="vidioc-qbuf">VIDIOC_PREPARE_BUF</link> or
> + <link linkend="vidioc-qbuf">VIDIOC_QBUF</link> ioctls to instruct the driver
> + to capture or output data starting at an offset in the plane buffer. If the
> + requested data offset doesn't match device or driver constraints, device
> + drivers must return the &EINVAL; and either leave the field value untouched
> + if they support data offsets, or set it to 0 if they don't support data
> + offsets at all. Note that <structfield>data_offset</structfield> is not
> + included in <structfield>bytesused</structfield>.
At most 80 characters per line would be nice.
How does the user discover what data_offsets are possible if the driver
returns an error if the data_offset does not match hardware capabilities?
I'd rather have the driver to adjust data_offset to match what it can do. If
the user needs to know that the data_offset was not modified, it should
check the field value after QBUF/PREPARE_BUF.
> </entry>
> </row>
> <row>
> diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
> index fa376f7..261fb66 100644
> --- a/include/uapi/linux/videodev2.h
> +++ b/include/uapi/linux/videodev2.h
> @@ -706,8 +706,10 @@ struct v4l2_requestbuffers {
> * pointing to this plane
> * @fd: when memory is V4L2_MEMORY_DMABUF, a userspace file
> * descriptor associated with this plane
> - * @data_offset: offset in the plane to the start of data; usually 0,
> - * unless there is a header in front of the data
> + * @data_offset: offset in bytes from the start of the plane buffer to
> + * the start of data; usually 0 unless applications need to
> + * capture data to or output data from elsewhere than the
> + * start of the buffer
> *
> * Multi-planar buffers consist of one or more planes, e.g. an YCbCr buffer
> * with two planes can have one plane for Y, and another for interleaved CbCr
--
Kind regards,
Sakari Ailus
e-mail: sakari.ailus@iki.fi XMPP: sailus@retiisi.org.uk
^ permalink raw reply
* Re: Revised futex(2) man page for review
From: Thomas Gleixner @ 2015-04-14 21:40 UTC (permalink / raw)
To: Peter Zijlstra
Cc: Michael Kerrisk (man-pages), Darren Hart, Carlos O'Donell,
Ingo Molnar, Jakub Jelinek,
linux-man-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, lkml,
Davidlohr Bueso, Arnd Bergmann, Steven Rostedt, Linux API,
Torvald Riegel, Roland McGrath, Darren Hart, Anton Blanchard,
Eric Dumazet, bill o gallmeister, Jan Kiszka, Daniel Wagner,
Rich Felker, Andy Lutomirski, bert hubert, Rusty Russell
In-Reply-To: <20150328114725.GJ27490-IIpfhp3q70z/8w/KjCw3T+5/BudmfyzbbVWyRVo5IupeoWH0uzbU5w@public.gmane.org>
On Sat, 28 Mar 2015, Peter Zijlstra wrote:
> On Sat, Mar 28, 2015 at 09:53:21AM +0100, Michael Kerrisk (man-pages) wrote:
> > So, please take a look at the page below. At this point,
> > I would most especially appreciate help with the FIXMEs.
>
> For people who cannot read that troff gibberish (me)..
Ditto :)
> NOTES
> Glibc does not provide a wrapper for this system call; call it using
> syscall(2).
You might mention that pthread_mutex, pthread_condvar interfaces are
high level wrappers for the syscall and recommended to be used for
normal use cases. IIRC unnamed semaphores are implemented with futexes
as well.
Thanks,
tglx
--
To unsubscribe from this list: send the line "unsubscribe linux-man" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v2 3/4] of: overlay: Add sysfs attributes
From: Rob Herring @ 2015-04-15 1:27 UTC (permalink / raw)
To: Pantelis Antoniou
Cc: Grant Likely, Andrew Morton, Matt Porter, Koen Kooi,
Guenter Roeck, devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
Pantelis Antoniou
In-Reply-To: <1428434632-13789-4-git-send-email-pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
On Tue, Apr 7, 2015 at 2:23 PM, Pantelis Antoniou
<pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org> wrote:
> Implement a number of sysfs attributes for overlays.
>
> * A throw once master enable switch to protect against any
> further overlay applications if the administrator desires so.
This one should be a separate patch.
> * A per overlay targets sysfs attribute listing the targets of
> the installed overlay.
What are targets? "targets lists targets" does not help me. The
documentation doesn't help me either.
> * A per overlay can_remove sysfs attribute that reports whether
> the overlay can be removed or not due to another overlapping overlay.
>
> Signed-off-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
> ---
> drivers/of/overlay.c | 167 ++++++++++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 166 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
> index f17f5ef..c54d097 100644
> --- a/drivers/of/overlay.c
> +++ b/drivers/of/overlay.c
> @@ -21,6 +21,7 @@
> #include <linux/err.h>
> #include <linux/idr.h>
> #include <linux/sysfs.h>
> +#include <linux/atomic.h>
>
> #include "of_private.h"
>
> @@ -55,8 +56,12 @@ struct of_overlay {
> struct kobject kobj;
> };
>
> +/* master enable switch; once set to 0 can't be re-enabled */
> +static atomic_t ov_enable = ATOMIC_INIT(1);
> +
> static int of_overlay_apply_one(struct of_overlay *ov,
> struct device_node *target, const struct device_node *overlay);
> +static int overlay_removal_is_ok(struct of_overlay *ov);
>
> static int of_overlay_apply_single_property(struct of_overlay *ov,
> struct device_node *target, struct property *prop)
> @@ -345,6 +350,144 @@ static struct kobj_type of_overlay_ktype = {
>
> static struct kset *ov_kset;
>
> +static ssize_t enable_read(struct file *filp, struct kobject *kobj,
> + struct bin_attribute *bin_attr, char *buf,
> + loff_t offset, size_t count)
> +{
> + char tbuf[3];
> +
> + if (offset < 0)
> + return -EINVAL;
> +
> + if (offset >= sizeof(tbuf))
> + return 0;
> +
> + if (count > sizeof(tbuf) - offset)
> + count = sizeof(tbuf) - offset;
> +
> + /* fill in temp */
> + tbuf[0] = '0' + atomic_read(&ov_enable);
> + tbuf[1] = '\n';
> + tbuf[2] = '\0';
> +
> + /* copy to buffer */
> + memcpy(buf, tbuf + offset, count);
> +
> + return count;
> +}
> +
> +static ssize_t enable_write(struct file *filp, struct kobject *kobj,
> + struct bin_attribute *bin_attr, char *buf,
> + loff_t off, size_t count)
> +{
> + unsigned int new_enable;
> +
> + if (off != 0 || (buf[0] != '0' && buf[0] != '1'))
> + return -EINVAL;
> +
> + new_enable = (unsigned int)(buf[0] - '0');
> + if (new_enable > 1)
> + return -EINVAL;
> +
> + /* NOP for same value */
> + if (new_enable == atomic_read(&ov_enable))
> + return count;
> +
> + /* if we've disabled it, no going back */
> + if (atomic_read(&ov_enable) == 0)
> + return -EPERM;
> +
> + atomic_set(&ov_enable, new_enable);
> + return count;
> +}
> +
> +/* just a single char + '\n' + '\0' */
> +static BIN_ATTR_RW(enable, 3);
Why are you using bin attribute? You are complicating the
implementation needlessly.
> +
> +static ssize_t targets_read(struct file *filp, struct kobject *kobj,
> + struct bin_attribute *bin_attr, char *buf,
> + loff_t offset, size_t count)
> +{
> + struct of_overlay *ov = kobj_to_overlay(kobj);
> + struct of_overlay_info *ovinfo;
> + char *tmpbuf, *s, *e;
> + const char *name;
> + ssize_t ret;
> + int i, len;
> +
> + /* allocate work buffer; we know that PAGE_SIZE is enough */
> + tmpbuf = kmalloc(PAGE_SIZE, GFP_KERNEL);
> + if (tmpbuf == NULL)
> + return -ENOMEM;
> +
> + s = tmpbuf;
> + e = tmpbuf + PAGE_SIZE;
> +
> + mutex_lock(&of_mutex);
> +
> + /* targets */
> + for (i = 0; i < ov->count; i++) {
> + ovinfo = &ov->ovinfo_tab[i];
> +
> + name = of_node_full_name(ovinfo->target);
> + len = strlen(name);
> + if (s + len + 1 >= e)
> + return -ENOMEM;
Leaking memory here and holding the mutex.
> + memcpy(s, name, len);
> + s += len;
> + *s++ = '\n';
> + }
> + if (s + 1 >= e)
> + return -ENOMEM;
And here.
> + *s++ = '\0';
> +
> + /* the buffer is zero terminated */
> + len = s - tmpbuf;
> +
> + mutex_unlock(&of_mutex);
> +
> + /* perform the read */
> + ret = memory_read_from_buffer(buf, count, &offset, tmpbuf, len);
> +
> + /* free the temporary buffer */
> + kfree(tmpbuf);
> +
> + return ret;
> +}
> +
> +/* targets property */
> +static BIN_ATTR_RO(targets, PAGE_SIZE);
> +
> +static ssize_t can_remove_read(struct file *filp, struct kobject *kobj,
> + struct bin_attribute *bin_attr, char *buf,
> + loff_t offset, size_t count)
> +{
> + struct of_overlay *ov = kobj_to_overlay(kobj);
> + char tbuf[3];
> +
> + if (offset < 0)
> + return -EINVAL;
> +
> + if (offset >= sizeof(tbuf))
> + return 0;
> +
> + if (count > sizeof(tbuf) - offset)
> + count = sizeof(tbuf) - offset;
> +
> + /* fill in temp */
> + tbuf[0] = '0' + overlay_removal_is_ok(ov);
> + tbuf[1] = '\n';
> + tbuf[2] = '\0';
> +
> + /* copy to buffer */
> + memcpy(buf, tbuf + offset, count);
> +
> + return count;
> +}
> +
> +/* can_remove property */
> +static BIN_ATTR_RO(can_remove, 3);
Same question about bin attr here.
> +
> /**
> * of_overlay_create() - Create and apply an overlay
> * @tree: Device node containing all the overlays
> @@ -360,6 +503,10 @@ int of_overlay_create(struct device_node *tree)
> struct of_overlay *ov;
> int err, id;
>
> + /* administratively disabled */
> + if (!atomic_read(&ov_enable))
> + return -EPERM;
> +
> /* allocate the overlay structure */
> ov = kzalloc(sizeof(*ov), GFP_KERNEL);
> if (ov == NULL)
> @@ -416,6 +563,22 @@ int of_overlay_create(struct device_node *tree)
> goto err_cancel_overlay;
> }
>
> + /* create targets file */
> + err = sysfs_create_bin_file(&ov->kobj, &bin_attr_targets);
> + if (err != 0) {
> + pr_err("%s: sysfs_create_bin_file() failed for tree@%s\n",
> + __func__, tree->full_name);
> + goto err_cancel_overlay;
> + }
> +
> + /* create can_remove file */
> + err = sysfs_create_bin_file(&ov->kobj, &bin_attr_can_remove);
> + if (err != 0) {
> + pr_err("%s: sysfs_create_bin_file() failed for tree@%s\n",
> + __func__, tree->full_name);
> + goto err_cancel_overlay;
> + }
> +
> /* add to the tail of the overlay list */
> list_add_tail(&ov->node, &ov_list);
>
> @@ -596,5 +759,7 @@ int of_overlay_init(void)
> if (!ov_kset)
> return -ENOMEM;
>
> - return 0;
> + rc = sysfs_create_bin_file(&ov_kset->kobj, &bin_attr_enable);
> + WARN(rc, "%s: error adding enable attribute\n", __func__);
> + return rc;
> }
> --
> 1.7.12
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v2 1/4] of: unittest: overlay: Keep track of created overlays
From: Rob Herring @ 2015-04-15 1:29 UTC (permalink / raw)
To: Pantelis Antoniou
Cc: Grant Likely, Andrew Morton, Matt Porter, Koen Kooi,
Guenter Roeck, devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
Pantelis Antoniou
In-Reply-To: <1428434632-13789-2-git-send-email-pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
On Tue, Apr 7, 2015 at 2:23 PM, Pantelis Antoniou
<pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org> wrote:
> During the course of the overlay selftests some of them remain
> applied. While this does not pose a real problem, make sure you track
> them and destroy them at the end of the test.
>
> Signed-off-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
I've applied this one. Patch 2 is okay, but the rest still needs some work.
Rob
> ---
> drivers/of/unittest.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 62 insertions(+)
>
> diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c
> index fdb5977..995cc73 100644
> --- a/drivers/of/unittest.c
> +++ b/drivers/of/unittest.c
> @@ -23,6 +23,8 @@
> #include <linux/i2c.h>
> #include <linux/i2c-mux.h>
>
> +#include <linux/bitops.h>
> +
> #include "of_private.h"
>
> static struct unittest_results {
> @@ -1095,6 +1097,59 @@ static const char *overlay_path(int nr)
>
> static const char *bus_path = "/testcase-data/overlay-node/test-bus";
>
> +/* it is guaranteed that overlay ids are assigned in sequence */
> +#define MAX_UNITTEST_OVERLAYS 256
> +static unsigned long overlay_id_bits[BITS_TO_LONGS(MAX_UNITTEST_OVERLAYS)];
> +static int overlay_first_id = -1;
> +
> +static void of_unittest_track_overlay(int id)
> +{
> + if (overlay_first_id < 0)
> + overlay_first_id = id;
> + id -= overlay_first_id;
> +
> + /* we shouldn't need that many */
> + BUG_ON(id >= MAX_UNITTEST_OVERLAYS);
> + overlay_id_bits[BIT_WORD(id)] |= BIT_MASK(id);
> +}
> +
> +static void of_unittest_untrack_overlay(int id)
> +{
> + if (overlay_first_id < 0)
> + return;
> + id -= overlay_first_id;
> + BUG_ON(id >= MAX_UNITTEST_OVERLAYS);
> + overlay_id_bits[BIT_WORD(id)] &= ~BIT_MASK(id);
> +}
> +
> +static void of_unittest_destroy_tracked_overlays(void)
> +{
> + int id, ret, defers;
> +
> + if (overlay_first_id < 0)
> + return;
> +
> + /* try until no defers */
> + do {
> + defers = 0;
> + /* remove in reverse order */
> + for (id = MAX_UNITTEST_OVERLAYS - 1; id >= 0; id--) {
> + if (!(overlay_id_bits[BIT_WORD(id)] & BIT_MASK(id)))
> + continue;
> +
> + ret = of_overlay_destroy(id + overlay_first_id);
> + if (ret != 0) {
> + defers++;
> + pr_warn("%s: overlay destroy failed for #%d\n",
> + __func__, id + overlay_first_id);
> + continue;
> + }
> +
> + overlay_id_bits[BIT_WORD(id)] &= ~BIT_MASK(id);
> + }
> + } while (defers > 0);
> +}
> +
> static int of_unittest_apply_overlay(int unittest_nr, int overlay_nr,
> int *overlay_id)
> {
> @@ -1116,6 +1171,7 @@ static int of_unittest_apply_overlay(int unittest_nr, int overlay_nr,
> goto out;
> }
> id = ret;
> + of_unittest_track_overlay(id);
>
> ret = 0;
>
> @@ -1329,6 +1385,7 @@ static void of_unittest_overlay_6(void)
> return;
> }
> ov_id[i] = ret;
> + of_unittest_track_overlay(ov_id[i]);
> }
>
> for (i = 0; i < 2; i++) {
> @@ -1353,6 +1410,7 @@ static void of_unittest_overlay_6(void)
> PDEV_OVERLAY));
> return;
> }
> + of_unittest_untrack_overlay(ov_id[i]);
> }
>
> for (i = 0; i < 2; i++) {
> @@ -1397,6 +1455,7 @@ static void of_unittest_overlay_8(void)
> return;
> }
> ov_id[i] = ret;
> + of_unittest_track_overlay(ov_id[i]);
> }
>
> /* now try to remove first overlay (it should fail) */
> @@ -1419,6 +1478,7 @@ static void of_unittest_overlay_8(void)
> PDEV_OVERLAY));
> return;
> }
> + of_unittest_untrack_overlay(ov_id[i]);
> }
>
> unittest(1, "overlay test %d passed\n", 8);
> @@ -1841,6 +1901,8 @@ static void __init of_unittest_overlay(void)
> of_unittest_overlay_i2c_cleanup();
> #endif
>
> + of_unittest_destroy_tracked_overlays();
> +
> out:
> of_node_put(bus_np);
> }
> --
> 1.7.12
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH] virtio_balloon: drop virtio_balloon_stat_modern
From: Rusty Russell @ 2015-04-15 3:15 UTC (permalink / raw)
To: Cornelia Huck, Michael S. Tsirkin; +Cc: linux-api, linux-kernel, virtualization
In-Reply-To: <20150414121327.4caacfba.cornelia.huck@de.ibm.com>
Cornelia Huck <cornelia.huck@de.ibm.com> writes:
> On Tue, 14 Apr 2015 12:01:13 +0200
> "Michael S. Tsirkin" <mst@redhat.com> wrote:
>
>> Looks like we are better off sticking with the misaligned stat struct,
>> to reduce the amount of virtio 1 specific code in balloon. So let's do
>> it.
>>
>> Add a detailed comment to reduce the chance people copy this bad example.
>>
>> This also fixes a bug on BE architectures: tag should use
>> cpu_to_le16, not cpu_to_le32.
>>
>> Acked-by: Cornelia Huck <cornelia.huck@de.ibm.com>
>> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
>> ---
>>
>> Just reposting so it's easier to apply.
>> Feel free to squash into previous patch if you think it's
>> neater.
>
> +1 for squashing from me. My A-b would also apply to the squashed patch.
Yes, I already squashed.
TBH, I would have squashed the next patches into one too, that simply
got rid of the virtio_device_is_legacy_only() function and all callers.
Thanks,
Rusty.
^ permalink raw reply
* Re: [Patch 2/3] firmware: dmi_scan: add SBMIOS entry and DMI tables
From: Roy Franz @ 2015-04-15 4:19 UTC (permalink / raw)
To: Ivan.khoronzhuk
Cc: Linux Kernel Mailing List, Matt Fleming, Jean Delvare,
Ard Biesheuvel, Grant Likely, linux-api-u79uwXL29TY76Z2rM5mHXA,
linux-doc-u79uwXL29TY76Z2rM5mHXA, mikew-hpIqsD4AKlfQT0dZR+AlfA,
dmidecode-devel-qX2TKyscuCcdnm+yROfE0A, Leif Lindholm,
Mark Salter
In-Reply-To: <551E5F0B.6050709-hExfYMNmJl/Cnp4W7fqMDg@public.gmane.org>
On Fri, Apr 3, 2015 at 2:36 AM, Ivan.khoronzhuk
<ivan.khoronzhuk-hExfYMNmJl/Cnp4W7fqMDg@public.gmane.org> wrote:
>
>
> On 02.04.15 15:57, Ivan Khoronzhuk wrote:
>>
>> Some utils, like dmidecode and smbios, need to access SMBIOS entry
>> table area in order to get information like SMBIOS version, size, etc.
>> Currently it's done via /dev/mem. But for situation when /dev/mem
>> usage is disabled, the utils have to use dmi sysfs instead, which
>> doesn't represent SMBIOS entry and adds code/delay redundancy when direct
>> access for table is needed.
>>
>> So this patch creates dmi/tables and adds SMBIOS entry point to allow
>> utils in question to work correctly without /dev/mem. Also patch adds
>> raw dmi table to simplify dmi table processing in user space, as
>> proposed by Jean Delvare.
>>
I have made modifications to dmidecode to support this interface, and it
works quite nicely for dmidecode. (changes posted to dmidecode-devel list)
The only open issue I am aware of is how the SMBIOS v3 entry point
will be handled,
especially in cases where there is a v2 and a v3 entry point.
In principal I think this a good change - are there any other open issues?
Thanks,
Roy
>> Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk-hExfYMNmJl/Cnp4W7fqMDg@public.gmane.org>
>> ---
>> .../ABI/testing/sysfs-firmware-dmi-tables | 22 ++++++
>> drivers/firmware/dmi-sysfs.c | 11 ++-
>> drivers/firmware/dmi_scan.c | 80
>> ++++++++++++++++++++++
>> include/linux/dmi.h | 1 +
>> 4 files changed, 107 insertions(+), 7 deletions(-)
>> create mode 100644 Documentation/ABI/testing/sysfs-firmware-dmi-tables
>>
>> diff --git a/Documentation/ABI/testing/sysfs-firmware-dmi-tables
>> b/Documentation/ABI/testing/sysfs-firmware-dmi-tables
>> new file mode 100644
>> index 0000000..f46158c
>> --- /dev/null
>> +++ b/Documentation/ABI/testing/sysfs-firmware-dmi-tables
>> @@ -0,0 +1,22 @@
>> +What: /sys/firmware/dmi/tables/
>> +Date: April 2015
>> +Contact: Ivan Khoronzhuk <ivan.khoronzhuk-hExfYMNmJl/Cnp4W7fqMDg@public.gmane.org>
>> +Description:
>> + The firmware provides DMI structures as a packed list of
>> + data referenced by a SMBIOS table entry point. The SMBIOS
>> + entry point contains general information, like SMBIOS
>> + version, DMI table size, etc. The structure, content and
>> + size of SMBIOS entry point is dependent on SMBIOS version.
>> + The format of SMBIOS entry point, equal as DMI structures
>> + can be read in SMBIOS specification.
>> +
>> + The dmi/tables provides raw SMBIOS entry point and DMI
>> tables
>> + through sysfs as an alternative to utilities reading them
>> + from /dev/mem. The raw SMBIOS entry point and DMI table
>> are
>> + presented as raw attributes and are accessible via:
>> +
>> + /sys/firmware/dmi/tables/smbios_entry_point
>> + /sys/firmware/dmi/tables/DMI
>> +
>> + The complete DMI information can be taken using these two
>> + tables.
>> diff --git a/drivers/firmware/dmi-sysfs.c b/drivers/firmware/dmi-sysfs.c
>> index e0f1cb3..8e1a411 100644
>> --- a/drivers/firmware/dmi-sysfs.c
>> +++ b/drivers/firmware/dmi-sysfs.c
>> @@ -566,7 +566,6 @@ static struct kobj_type dmi_sysfs_entry_ktype = {
>> .default_attrs = dmi_sysfs_entry_attrs,
>> };
>> -static struct kobject *dmi_kobj;
>> static struct kset *dmi_kset;
>> /* Global count of all instances seen. Only for setup */
>> @@ -651,10 +650,11 @@ static int __init dmi_sysfs_init(void)
>> int error = -ENOMEM;
>> int val;
>> - /* Set up our directory */
>> - dmi_kobj = kobject_create_and_add("dmi", firmware_kobj);
>> - if (!dmi_kobj)
>> + if (!dmi_kobj) {
>> + pr_err("dmi-sysfs: dmi entry is absent.\n");
>> + error = -ENOSYS;
>> goto err;
>> + }
>> dmi_kset = kset_create_and_add("entries", NULL, dmi_kobj);
>> if (!dmi_kset)
>> @@ -675,7 +675,6 @@ static int __init dmi_sysfs_init(void)
>> err:
>> cleanup_entry_list();
>> kset_unregister(dmi_kset);
>> - kobject_put(dmi_kobj);
>> return error;
>> }
>> @@ -685,8 +684,6 @@ static void __exit dmi_sysfs_exit(void)
>> pr_debug("dmi-sysfs: unloading.\n");
>> cleanup_entry_list();
>> kset_unregister(dmi_kset);
>> - kobject_del(dmi_kobj);
>> - kobject_put(dmi_kobj);
>> }
>> module_init(dmi_sysfs_init);
>> diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
>> index d3aae09..bb19f8b 100644
>> --- a/drivers/firmware/dmi_scan.c
>> +++ b/drivers/firmware/dmi_scan.c
>> @@ -10,6 +10,9 @@
>> #include <asm/dmi.h>
>> #include <asm/unaligned.h>
>> +struct kobject *dmi_kobj;
>> +EXPORT_SYMBOL_GPL(dmi_kobj);
>> +
>> /*
>> * DMI stands for "Desktop Management Interface". It is part
>> * of and an antecedent to, SMBIOS, which stands for System
>> @@ -20,6 +23,9 @@ static const char dmi_empty_string[] = " ";
>> static u32 dmi_ver __initdata;
>> static u32 dmi_len;
>> static u16 dmi_num;
>> +static u8 smbios_entry_point[32];
>> +static int smbios_entry_point_size;
>> +
>> /*
>> * Catch too early calls to dmi_check_system():
>> */
>> @@ -118,6 +124,7 @@ static void dmi_decode_table(u8 *buf,
>> }
>> static phys_addr_t dmi_base;
>> +static u8 *dmi_table;
>> static int __init dmi_walk_early(void (*decode)(const struct
>> dmi_header *,
>> void *))
>> @@ -476,6 +483,8 @@ static int __init dmi_present(const u8 *buf)
>> if (memcmp(buf, "_SM_", 4) == 0 &&
>> buf[5] < 32 && dmi_checksum(buf, buf[5])) {
>> smbios_ver = get_unaligned_be16(buf + 6);
>> + smbios_entry_point_size = buf[5];
>> + memcpy(smbios_entry_point, buf, smbios_entry_point_size);
>> /* Some BIOS report weird SMBIOS version, fix that up */
>> switch (smbios_ver) {
>> @@ -508,6 +517,9 @@ static int __init dmi_present(const u8 *buf)
>> dmi_ver >> 8, dmi_ver & 0xFF,
>> (dmi_ver < 0x0300) ? "" : ".x");
>> } else {
>> + smbios_entry_point_size = 15;
>> + memcpy(smbios_entry_point, buf,
>> + smbios_entry_point_size);
>> dmi_ver = (buf[14] & 0xF0) << 4 |
>> (buf[14] & 0x0F);
>> pr_info("Legacy DMI %d.%d present.\n",
>> @@ -535,6 +547,8 @@ static int __init dmi_smbios3_present(const u8 *buf)
>> dmi_ver &= 0xFFFFFF;
>> dmi_len = get_unaligned_le32(buf + 12);
>> dmi_base = get_unaligned_le64(buf + 16);
>> + smbios_entry_point_size = buf[6];
>> + memcpy(smbios_entry_point, buf, smbios_entry_point_size);
>> /*
>> * The 64-bit SMBIOS 3.0 entry point no longer has a field
>> @@ -638,6 +652,72 @@ void __init dmi_scan_machine(void)
>> dmi_initialized = 1;
>> }
>> +static ssize_t raw_table_read(struct file *file, struct kobject *kobj,
>> + struct bin_attribute *attr, char *buf,
>> + loff_t pos, size_t count)
>> +{
>> + memcpy(buf, attr->private + pos, count);
>> + return count;
>> +}
>> +
>> +static BIN_ATTR(smbios_entry_point, S_IRUSR, raw_table_read, NULL, 0);
>> +struct bin_attribute bin_attr_dmi_table =
>> + __BIN_ATTR(DMI, S_IRUSR, raw_table_read, NULL, 0);
>
>
> missed static here
>
>
>> +
>> +static int __init dmi_init(void)
>> +{
>> + int ret = -ENOMEM;
>> + struct kobject *tables_kobj = NULL;
>> +
>> + if (!dmi_available) {
>> + ret = -ENOSYS;
>> + goto err;
>> + }
>> +
>> + /* Set up dmi directory at /sys/firmware/dmi */
>> + dmi_kobj = kobject_create_and_add("dmi", firmware_kobj);
>> + if (!dmi_kobj)
>> + goto err;
>> +
>> + tables_kobj = kobject_create_and_add("tables", dmi_kobj);
>> + if (!tables_kobj)
>> + goto err;
>> +
>> + bin_attr_smbios_entry_point.size = smbios_entry_point_size;
>> + bin_attr_smbios_entry_point.private = smbios_entry_point;
>> + ret = sysfs_create_bin_file(tables_kobj,
>> &bin_attr_smbios_entry_point);
>> + if (ret)
>> + goto err;
>> +
>> + dmi_table = dmi_remap(dmi_base, dmi_len);
>> + if (!dmi_table)
>> + goto err;
>> +
>> + bin_attr_dmi_table.size = dmi_len;
>> + bin_attr_dmi_table.private = dmi_table;
>> + ret = sysfs_create_bin_file(tables_kobj, &bin_attr_dmi_table);
>> + if (ret) {
>> + dmi_unmap(dmi_table);
>> + goto err;
>> + }
>> +
>> + return 0;
>> +err:
>> + pr_err("dmi: Firmware registration failed.\n");
>> +
>> + if (tables_kobj)
>> + sysfs_remove_bin_file(tables_kobj,
>> + &bin_attr_smbios_entry_point);
>> + kobject_del(tables_kobj);
>> + kobject_put(tables_kobj);
>> + kobject_del(dmi_kobj);
>> + kobject_put(dmi_kobj);
>> + dmi_kobj = NULL;
>> +
>> + return ret;
>> +}
>> +subsys_initcall(dmi_init);
>> +
>> /**
>> * dmi_set_dump_stack_arch_desc - set arch description for dump_stack()
>> *
>> diff --git a/include/linux/dmi.h b/include/linux/dmi.h
>> index f820f0a..9f55f46 100644
>> --- a/include/linux/dmi.h
>> +++ b/include/linux/dmi.h
>> @@ -93,6 +93,7 @@ struct dmi_dev_onboard {
>> int devfn;
>> };
>> +extern struct kobject *dmi_kobj;
>> extern int dmi_check_system(const struct dmi_system_id *list);
>> const struct dmi_system_id *dmi_first_match(const struct dmi_system_id
>> *list);
>> extern const char * dmi_get_system_info(int field);
>
>
> --
> Regards,
> Ivan Khoronzhuk
>
^ permalink raw reply
* Re: Revised futex(2) man page for review
From: Torvald Riegel @ 2015-04-15 10:28 UTC (permalink / raw)
To: Thomas Gleixner
Cc: Peter Zijlstra, Michael Kerrisk (man-pages), Darren Hart,
Carlos O'Donell, Ingo Molnar, Jakub Jelinek,
linux-man-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, lkml,
Davidlohr Bueso, Arnd Bergmann, Steven Rostedt, Linux API,
Roland McGrath, Darren Hart, Anton Blanchard, Eric Dumazet,
bill o gallmeister, Jan Kiszka, Daniel Wagner, Rich Felker,
Andy Lutomirski, bert hubert, Rusty Russell
In-Reply-To: <alpine.DEB.2.11.1504142323290.3845@nanos>
On Tue, 2015-04-14 at 23:40 +0200, Thomas Gleixner wrote:
> On Sat, 28 Mar 2015, Peter Zijlstra wrote:
> > On Sat, Mar 28, 2015 at 09:53:21AM +0100, Michael Kerrisk (man-pages) wrote:
> > > So, please take a look at the page below. At this point,
> > > I would most especially appreciate help with the FIXMEs.
> >
> > For people who cannot read that troff gibberish (me)..
>
> Ditto :)
>
> > NOTES
> > Glibc does not provide a wrapper for this system call; call it using
> > syscall(2).
>
> You might mention that pthread_mutex, pthread_condvar interfaces are
> high level wrappers for the syscall and recommended to be used for
> normal use cases. IIRC unnamed semaphores are implemented with futexes
> as well.
If we add this, I'd rephrase it to something like that there are
high-level programming abstractions such as the pthread_condvar
interfaces or semaphores that are implemented using the syscall and that
are typically a better fit for normal use cases. I'd consider only the
condvars as something like a wrapper, or targeting a similar use case.
^ permalink raw reply
* Re: [Patch 1/3] firmware: dmi_scan: rename dmi_table to dmi_decode_table
From: Jean Delvare @ 2015-04-15 11:51 UTC (permalink / raw)
To: Ivan Khoronzhuk
Cc: linux-kernel, matt.fleming, ard.biesheuvel, grant.likely,
linux-api, linux-doc, mikew, dmidecode-devel, leif.lindholm,
msalter, roy.franz
In-Reply-To: <1427979423-22767-2-git-send-email-ivan.khoronzhuk@globallogic.com>
On Thu, 2 Apr 2015 15:57:01 +0300, Ivan Khoronzhuk wrote:
> The "dmi_table" function looks like data instance, but it does DMI
> table decode. This patch renames it to "dmi_decode_table" name as
> more appropriate. That allows us to use "dmi_table" name for correct
> purposes.
>
> Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk@globallogic.com>
> ---
> drivers/firmware/dmi_scan.c | 10 +++++-----
> 1 file changed, 5 insertions(+), 5 deletions(-)
> (...)
Yes, as discussed before, good idea.
Reviewed-by: Jean Delvare <jdelvare@suse.de>
--
Jean Delvare
SUSE L3 Support
^ permalink raw reply
* Re: [Patch 3/3] Documentation: ABI: sysfs-firmware-dmi: add -entries suffix to file name
From: Jean Delvare @ 2015-04-15 11:52 UTC (permalink / raw)
To: Ivan Khoronzhuk
Cc: linux-kernel, matt.fleming, ard.biesheuvel, grant.likely,
linux-api, linux-doc, mikew, dmidecode-devel, leif.lindholm,
msalter, roy.franz
In-Reply-To: <1427979423-22767-4-git-send-email-ivan.khoronzhuk@globallogic.com>
Hi Ivan,
On Thu, 2 Apr 2015 15:57:03 +0300, Ivan Khoronzhuk wrote:
> The dmi-sysfs module adds DMI table structures entries under
> /sys/firmware/dmi/entries only, so rename documentation file to
> sysfs-firmware-dmi-entries as more appropriate. Without renaming it's
> confusing to differ this from sysfs-firmware-dmi-tables that adds raw
> DMI table and actually adds "dmi" kobject.
>
> Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk@globallogic.com>
> ---
> .../ABI/testing/{sysfs-firmware-dmi => sysfs-firmware-dmi-entries} | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
> rename Documentation/ABI/testing/{sysfs-firmware-dmi => sysfs-firmware-dmi-entries} (99%)
>
> diff --git a/Documentation/ABI/testing/sysfs-firmware-dmi b/Documentation/ABI/testing/sysfs-firmware-dmi-entries
> similarity index 99%
> rename from Documentation/ABI/testing/sysfs-firmware-dmi
> rename to Documentation/ABI/testing/sysfs-firmware-dmi-entries
> index c78f9ab..210ad44 100644
> --- a/Documentation/ABI/testing/sysfs-firmware-dmi
> +++ b/Documentation/ABI/testing/sysfs-firmware-dmi-entries
> @@ -1,4 +1,4 @@
> -What: /sys/firmware/dmi/
> +What: /sys/firmware/dmi/entries/
> Date: February 2011
> Contact: Mike Waychison <mikew@google.com>
> Description:
Thanks for doing this.
Reviewed-by: Jean Delvare <jdelvare@suse.de>
--
Jean Delvare
SUSE L3 Support
^ permalink raw reply
* Re: [Patch 1/3] firmware: dmi_scan: rename dmi_table to dmi_decode_table
From: Matt Fleming @ 2015-04-15 14:35 UTC (permalink / raw)
To: Ivan Khoronzhuk
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
matt.fleming-ral2JQCrhuEAvxtiuMwx3w, jdelvare-l3A5Bk7waGM,
ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A,
grant.likely-QSEj5FYQhm4dnm+yROfE0A,
linux-api-u79uwXL29TY76Z2rM5mHXA,
linux-doc-u79uwXL29TY76Z2rM5mHXA, mikew-hpIqsD4AKlfQT0dZR+AlfA,
dmidecode-devel-qX2TKyscuCcdnm+yROfE0A,
leif.lindholm-QSEj5FYQhm4dnm+yROfE0A,
msalter-H+wXaHxf7aLQT0dZR+AlfA, roy.franz-QSEj5FYQhm4dnm+yROfE0A
In-Reply-To: <1427979423-22767-2-git-send-email-ivan.khoronzhuk-hExfYMNmJl/Cnp4W7fqMDg@public.gmane.org>
On Thu, 02 Apr, at 03:57:01PM, Ivan Khoronzhuk wrote:
> The "dmi_table" function looks like data instance, but it does DMI
> table decode. This patch renames it to "dmi_decode_table" name as
> more appropriate. That allows us to use "dmi_table" name for correct
> purposes.
>
> Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk-hExfYMNmJl/Cnp4W7fqMDg@public.gmane.org>
> ---
> drivers/firmware/dmi_scan.c | 10 +++++-----
> 1 file changed, 5 insertions(+), 5 deletions(-)
Looks good to me.
Jean, do you want me to pick this patch up or are you going to?
--
Matt Fleming, Intel Open Source Technology Center
^ permalink raw reply
* Re: [PATCH/RFC 1/2] v4l: Repurpose the v4l2_plane data_offset field
From: Laurent Pinchart @ 2015-04-15 20:37 UTC (permalink / raw)
To: Sakari Ailus
Cc: linux-media-u79uwXL29TY76Z2rM5mHXA,
linux-api-u79uwXL29TY76Z2rM5mHXA, Sakari Ailus, Hans Verkuil,
Pawel Osciak, Marek Szyprowski, Mauro Carvalho Chehab
In-Reply-To: <20150414201004.GA27451-S+BSfZ9RZZmRSg0ZkenSGLdO1Tsj/99ntUK59QYPAWc@public.gmane.org>
Hi Sakari,
Thank you for the review.
On Tuesday 14 April 2015 23:10:05 Sakari Ailus wrote:
> On Tue, Apr 14, 2015 at 10:44:48PM +0300, Laurent Pinchart wrote:
> > The data_offset field has been introduced along with the multiplane API
> > to convey header size information between kernelspace and userspace.
> > It's not used by any mainline driver except vivid (for testing purpose).
> >
> > A different data offset is needed to allow data capture to or data
> > output from a userspace-selected offset within a buffer (mainly for the
> > DMABUF and MMAP memory types). As the data_offset field already has the
> > right name and is unused, repurpose it.
> >
> > Signed-off-by: Laurent Pinchart <laurent.pinchart-ryLnwIuWjnjg/C1BVhZhaw@public.gmane.org>
> > ---
> >
> > Documentation/DocBook/media/v4l/io.xml | 19 +++++++++++--------
> > include/uapi/linux/videodev2.h | 6 ++++--
> > 2 files changed, 15 insertions(+), 10 deletions(-)
> >
> > diff --git a/Documentation/DocBook/media/v4l/io.xml
> > b/Documentation/DocBook/media/v4l/io.xml index 1c17f80..416c05a 100644
> > --- a/Documentation/DocBook/media/v4l/io.xml
> > +++ b/Documentation/DocBook/media/v4l/io.xml
> > @@ -870,7 +870,7 @@ should set this to 0.</entry>
> >
> > If the application sets this to 0 for an output stream, then
> > <structfield>bytesused</structfield> will be set to the size of
> > the
> > plane (see the <structfield>length</structfield> field of this
> > struct)
> > - by the driver. Note that the actual image data starts at
> > + by the driver. Note that the actual plane data content starts
at
> > <structfield>data_offset</structfield> which may not be
0.</entry>
> > </row>
> > <row>
> > @@ -917,13 +917,16 @@ should set this to 0.</entry>
> > <entry>__u32</entry>
> > <entry><structfield>data_offset</structfield></entry>
> > <entry></entry>
> > - <entry>Offset in bytes to video data in the plane.
> > - Drivers must set this field when
<structfield>type</structfield>
> > - refers to an input stream, applications when it refers to an
> > output stream. - Note that data_offset is included in
> > <structfield>bytesused</structfield>. - So the size of the image
in
> > the plane is
> > -
> > <structfield>bytesused</structfield>-<structfield>data_offset</structfiel
> > d> at - offset <structfield>data_offset</structfield> from the
start
> > of the plane. + <entry>Offset in bytes from the start of the plane
> > buffer to the start of + captured or output data. Applications
set
> > this field for all stream types + when calling the <link
> > linkend="vidioc-qbuf">VIDIOC_PREPARE_BUF</link> or + <link
> > linkend="vidioc-qbuf">VIDIOC_QBUF</link> ioctls to instruct the driver +
> > to capture or output data starting at an offset in the plane buffer.
> > If the + requested data offset doesn't match device or driver
> > constraints, device + drivers must return the &EINVAL; and either
> > leave the field value untouched + if they support data offsets,
or
> > set it to 0 if they don't support data + offsets at all. Note that
> > <structfield>data_offset</structfield> is not + included in
> > <structfield>bytesused</structfield>.
>
> At most 80 characters per line would be nice.
I've followed the coding style of the file, but I can certainly change that,
no issue.
> How does the user discover what data_offsets are possible if the driver
> returns an error if the data_offset does not match hardware capabilities?
>
> I'd rather have the driver to adjust data_offset to match what it can do. If
> the user needs to know that the data_offset was not modified, it should
> check the field value after QBUF/PREPARE_BUF.
I've discussed this with Hans before, and we thought negotiating data_offset
wasn't very useful. data_offset values used by applications are pretty much
mandatory, if you need to write the UV plane of an NV12 image at a given
offset in a Y+UV contiguous buffer, using a different negotiated offset is
pointless. Feel free to point us to use cases though.
> > </entry>
> > </row>
> > <row>
> > diff --git a/include/uapi/linux/videodev2.h
> > b/include/uapi/linux/videodev2.h index fa376f7..261fb66 100644
> > --- a/include/uapi/linux/videodev2.h
> > +++ b/include/uapi/linux/videodev2.h
> > @@ -706,8 +706,10 @@ struct v4l2_requestbuffers {
> > * pointing to this plane
> > * @fd: when memory is V4L2_MEMORY_DMABUF, a userspace file
> > * descriptor associated with this plane
> > - * @data_offset: offset in the plane to the start of data; usually 0,
> > - * unless there is a header in front of the data
> > + * @data_offset: offset in bytes from the start of the plane buffer to
> > + * the start of data; usually 0 unless applications need to
> > + * capture data to or output data from elsewhere than the
> > + * start of the buffer
> > *
> > * Multi-planar buffers consist of one or more planes, e.g. an YCbCr
> > buffer
> > * with two planes can have one plane for Y, and another for interleaved
> > CbCr
--
Regards,
Laurent Pinchart
^ permalink raw reply
* Re: [Patch 2/3] firmware: dmi_scan: add SBMIOS entry and DMI tables
From: Roy Franz @ 2015-04-16 0:54 UTC (permalink / raw)
To: Ivan.khoronzhuk
Cc: Linux Kernel Mailing List, Matt Fleming, Jean Delvare,
Ard Biesheuvel, Grant Likely, linux-api-u79uwXL29TY76Z2rM5mHXA,
linux-doc-u79uwXL29TY76Z2rM5mHXA, Mike Waychison,
dmidecode-devel-qX2TKyscuCcdnm+yROfE0A, Leif Lindholm,
Mark Salter
In-Reply-To: <CAFECyb_BGU82vCi0jOz+MbdsxRS-jFoHNsZe5KdOCgpt0K7y+A-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
On Tue, Apr 14, 2015 at 9:19 PM, Roy Franz <roy.franz-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> wrote:
> On Fri, Apr 3, 2015 at 2:36 AM, Ivan.khoronzhuk
> <ivan.khoronzhuk-hExfYMNmJl/Cnp4W7fqMDg@public.gmane.org> wrote:
>>
>>
>> On 02.04.15 15:57, Ivan Khoronzhuk wrote:
>>>
>>> Some utils, like dmidecode and smbios, need to access SMBIOS entry
>>> table area in order to get information like SMBIOS version, size, etc.
>>> Currently it's done via /dev/mem. But for situation when /dev/mem
>>> usage is disabled, the utils have to use dmi sysfs instead, which
>>> doesn't represent SMBIOS entry and adds code/delay redundancy when direct
>>> access for table is needed.
>>>
>>> So this patch creates dmi/tables and adds SMBIOS entry point to allow
>>> utils in question to work correctly without /dev/mem. Also patch adds
>>> raw dmi table to simplify dmi table processing in user space, as
>>> proposed by Jean Delvare.
>>>
>
> I have made modifications to dmidecode to support this interface, and it
> works quite nicely for dmidecode. (changes posted to dmidecode-devel list)
> The only open issue I am aware of is how the SMBIOS v3 entry point
> will be handled,
> especially in cases where there is a v2 and a v3 entry point.
> In principal I think this a good change - are there any other open issues?
>
> Thanks,
> Roy
>
I looked at the SMBIOS spec again, and the platform can provide either or
both of the 32-bit and 64-bit entry points. The spec says that an
implementation
"should" provide a 32-bit entry point for compatibility.
These 2 entry point structures can both point to the same SMBIOS
structure table,
or two distinct ones. If distinct, the one referenced by the 32-bit
entry point must be
a consistent subset of the 64-bit one.
There does not seem to be any prohibition from using new SMBIOS v3 structures
in a table referenced by a 32-bit entry point, so backwards
compatibility is completely
up to the implementation.
Since the point of this patchset (and related changes to dmidecode) is
to provide the
SMBIOS information without using /dev/mem, I think the interface we
define should
support all the cases outlined in the specification. I would like to
avoid a case where
we're back to using /dev/mem to deal with the dual entry/dual table
case if that becomes
important down the road.
Here's a proposal for files in /sys/firmware/dmi/tables:
smbios_entry_point32 - 32 bit (existing entry point type), if it exists.
smbios_entry_point64 - 64 bit entry, new in SMBIOS v3.0
DMI32 - smbios structure tables referenced by
32 bit entry point, if it exists
DMI64 - smbios structure tables referenced by
64 bit entry point, if it exists.
symlink to DMI32 if identical
smbios_entry_point - symlink to smbios_entry_point64 if it exists,
otherwise symlink to smbios_entry_point64
DMI - symlink to DMI64 if it exists,
otherwise symlink to DMI32
These last two would provide names to the 'preferred' tables, and
names that would always exist on all systems, which
I think is a nice property to have.
Thoughts?
Thanks,
Roy
>
>
>>> Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk-hExfYMNmJl/Cnp4W7fqMDg@public.gmane.org>
>>> ---
>>> .../ABI/testing/sysfs-firmware-dmi-tables | 22 ++++++
>>> drivers/firmware/dmi-sysfs.c | 11 ++-
>>> drivers/firmware/dmi_scan.c | 80
>>> ++++++++++++++++++++++
>>> include/linux/dmi.h | 1 +
>>> 4 files changed, 107 insertions(+), 7 deletions(-)
>>> create mode 100644 Documentation/ABI/testing/sysfs-firmware-dmi-tables
>>>
>>> diff --git a/Documentation/ABI/testing/sysfs-firmware-dmi-tables
>>> b/Documentation/ABI/testing/sysfs-firmware-dmi-tables
>>> new file mode 100644
>>> index 0000000..f46158c
>>> --- /dev/null
>>> +++ b/Documentation/ABI/testing/sysfs-firmware-dmi-tables
>>> @@ -0,0 +1,22 @@
>>> +What: /sys/firmware/dmi/tables/
>>> +Date: April 2015
>>> +Contact: Ivan Khoronzhuk <ivan.khoronzhuk-hExfYMNmJl/Cnp4W7fqMDg@public.gmane.org>
>>> +Description:
>>> + The firmware provides DMI structures as a packed list of
>>> + data referenced by a SMBIOS table entry point. The SMBIOS
>>> + entry point contains general information, like SMBIOS
>>> + version, DMI table size, etc. The structure, content and
>>> + size of SMBIOS entry point is dependent on SMBIOS version.
>>> + The format of SMBIOS entry point, equal as DMI structures
>>> + can be read in SMBIOS specification.
>>> +
>>> + The dmi/tables provides raw SMBIOS entry point and DMI
>>> tables
>>> + through sysfs as an alternative to utilities reading them
>>> + from /dev/mem. The raw SMBIOS entry point and DMI table
>>> are
>>> + presented as raw attributes and are accessible via:
>>> +
>>> + /sys/firmware/dmi/tables/smbios_entry_point
>>> + /sys/firmware/dmi/tables/DMI
>>> +
>>> + The complete DMI information can be taken using these two
>>> + tables.
>>> diff --git a/drivers/firmware/dmi-sysfs.c b/drivers/firmware/dmi-sysfs.c
>>> index e0f1cb3..8e1a411 100644
>>> --- a/drivers/firmware/dmi-sysfs.c
>>> +++ b/drivers/firmware/dmi-sysfs.c
>>> @@ -566,7 +566,6 @@ static struct kobj_type dmi_sysfs_entry_ktype = {
>>> .default_attrs = dmi_sysfs_entry_attrs,
>>> };
>>> -static struct kobject *dmi_kobj;
>>> static struct kset *dmi_kset;
>>> /* Global count of all instances seen. Only for setup */
>>> @@ -651,10 +650,11 @@ static int __init dmi_sysfs_init(void)
>>> int error = -ENOMEM;
>>> int val;
>>> - /* Set up our directory */
>>> - dmi_kobj = kobject_create_and_add("dmi", firmware_kobj);
>>> - if (!dmi_kobj)
>>> + if (!dmi_kobj) {
>>> + pr_err("dmi-sysfs: dmi entry is absent.\n");
>>> + error = -ENOSYS;
>>> goto err;
>>> + }
>>> dmi_kset = kset_create_and_add("entries", NULL, dmi_kobj);
>>> if (!dmi_kset)
>>> @@ -675,7 +675,6 @@ static int __init dmi_sysfs_init(void)
>>> err:
>>> cleanup_entry_list();
>>> kset_unregister(dmi_kset);
>>> - kobject_put(dmi_kobj);
>>> return error;
>>> }
>>> @@ -685,8 +684,6 @@ static void __exit dmi_sysfs_exit(void)
>>> pr_debug("dmi-sysfs: unloading.\n");
>>> cleanup_entry_list();
>>> kset_unregister(dmi_kset);
>>> - kobject_del(dmi_kobj);
>>> - kobject_put(dmi_kobj);
>>> }
>>> module_init(dmi_sysfs_init);
>>> diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
>>> index d3aae09..bb19f8b 100644
>>> --- a/drivers/firmware/dmi_scan.c
>>> +++ b/drivers/firmware/dmi_scan.c
>>> @@ -10,6 +10,9 @@
>>> #include <asm/dmi.h>
>>> #include <asm/unaligned.h>
>>> +struct kobject *dmi_kobj;
>>> +EXPORT_SYMBOL_GPL(dmi_kobj);
>>> +
>>> /*
>>> * DMI stands for "Desktop Management Interface". It is part
>>> * of and an antecedent to, SMBIOS, which stands for System
>>> @@ -20,6 +23,9 @@ static const char dmi_empty_string[] = " ";
>>> static u32 dmi_ver __initdata;
>>> static u32 dmi_len;
>>> static u16 dmi_num;
>>> +static u8 smbios_entry_point[32];
>>> +static int smbios_entry_point_size;
>>> +
>>> /*
>>> * Catch too early calls to dmi_check_system():
>>> */
>>> @@ -118,6 +124,7 @@ static void dmi_decode_table(u8 *buf,
>>> }
>>> static phys_addr_t dmi_base;
>>> +static u8 *dmi_table;
>>> static int __init dmi_walk_early(void (*decode)(const struct
>>> dmi_header *,
>>> void *))
>>> @@ -476,6 +483,8 @@ static int __init dmi_present(const u8 *buf)
>>> if (memcmp(buf, "_SM_", 4) == 0 &&
>>> buf[5] < 32 && dmi_checksum(buf, buf[5])) {
>>> smbios_ver = get_unaligned_be16(buf + 6);
>>> + smbios_entry_point_size = buf[5];
>>> + memcpy(smbios_entry_point, buf, smbios_entry_point_size);
>>> /* Some BIOS report weird SMBIOS version, fix that up */
>>> switch (smbios_ver) {
>>> @@ -508,6 +517,9 @@ static int __init dmi_present(const u8 *buf)
>>> dmi_ver >> 8, dmi_ver & 0xFF,
>>> (dmi_ver < 0x0300) ? "" : ".x");
>>> } else {
>>> + smbios_entry_point_size = 15;
>>> + memcpy(smbios_entry_point, buf,
>>> + smbios_entry_point_size);
>>> dmi_ver = (buf[14] & 0xF0) << 4 |
>>> (buf[14] & 0x0F);
>>> pr_info("Legacy DMI %d.%d present.\n",
>>> @@ -535,6 +547,8 @@ static int __init dmi_smbios3_present(const u8 *buf)
>>> dmi_ver &= 0xFFFFFF;
>>> dmi_len = get_unaligned_le32(buf + 12);
>>> dmi_base = get_unaligned_le64(buf + 16);
>>> + smbios_entry_point_size = buf[6];
>>> + memcpy(smbios_entry_point, buf, smbios_entry_point_size);
>>> /*
>>> * The 64-bit SMBIOS 3.0 entry point no longer has a field
>>> @@ -638,6 +652,72 @@ void __init dmi_scan_machine(void)
>>> dmi_initialized = 1;
>>> }
>>> +static ssize_t raw_table_read(struct file *file, struct kobject *kobj,
>>> + struct bin_attribute *attr, char *buf,
>>> + loff_t pos, size_t count)
>>> +{
>>> + memcpy(buf, attr->private + pos, count);
>>> + return count;
>>> +}
>>> +
>>> +static BIN_ATTR(smbios_entry_point, S_IRUSR, raw_table_read, NULL, 0);
>>> +struct bin_attribute bin_attr_dmi_table =
>>> + __BIN_ATTR(DMI, S_IRUSR, raw_table_read, NULL, 0);
>>
>>
>> missed static here
>>
>>
>>> +
>>> +static int __init dmi_init(void)
>>> +{
>>> + int ret = -ENOMEM;
>>> + struct kobject *tables_kobj = NULL;
>>> +
>>> + if (!dmi_available) {
>>> + ret = -ENOSYS;
>>> + goto err;
>>> + }
>>> +
>>> + /* Set up dmi directory at /sys/firmware/dmi */
>>> + dmi_kobj = kobject_create_and_add("dmi", firmware_kobj);
>>> + if (!dmi_kobj)
>>> + goto err;
>>> +
>>> + tables_kobj = kobject_create_and_add("tables", dmi_kobj);
>>> + if (!tables_kobj)
>>> + goto err;
>>> +
>>> + bin_attr_smbios_entry_point.size = smbios_entry_point_size;
>>> + bin_attr_smbios_entry_point.private = smbios_entry_point;
>>> + ret = sysfs_create_bin_file(tables_kobj,
>>> &bin_attr_smbios_entry_point);
>>> + if (ret)
>>> + goto err;
>>> +
>>> + dmi_table = dmi_remap(dmi_base, dmi_len);
>>> + if (!dmi_table)
>>> + goto err;
>>> +
>>> + bin_attr_dmi_table.size = dmi_len;
>>> + bin_attr_dmi_table.private = dmi_table;
>>> + ret = sysfs_create_bin_file(tables_kobj, &bin_attr_dmi_table);
>>> + if (ret) {
>>> + dmi_unmap(dmi_table);
>>> + goto err;
>>> + }
>>> +
>>> + return 0;
>>> +err:
>>> + pr_err("dmi: Firmware registration failed.\n");
>>> +
>>> + if (tables_kobj)
>>> + sysfs_remove_bin_file(tables_kobj,
>>> + &bin_attr_smbios_entry_point);
>>> + kobject_del(tables_kobj);
>>> + kobject_put(tables_kobj);
>>> + kobject_del(dmi_kobj);
>>> + kobject_put(dmi_kobj);
>>> + dmi_kobj = NULL;
>>> +
>>> + return ret;
>>> +}
>>> +subsys_initcall(dmi_init);
>>> +
>>> /**
>>> * dmi_set_dump_stack_arch_desc - set arch description for dump_stack()
>>> *
>>> diff --git a/include/linux/dmi.h b/include/linux/dmi.h
>>> index f820f0a..9f55f46 100644
>>> --- a/include/linux/dmi.h
>>> +++ b/include/linux/dmi.h
>>> @@ -93,6 +93,7 @@ struct dmi_dev_onboard {
>>> int devfn;
>>> };
>>> +extern struct kobject *dmi_kobj;
>>> extern int dmi_check_system(const struct dmi_system_id *list);
>>> const struct dmi_system_id *dmi_first_match(const struct dmi_system_id
>>> *list);
>>> extern const char * dmi_get_system_info(int field);
>>
>>
>> --
>> Regards,
>> Ivan Khoronzhuk
>>
^ permalink raw reply
* Re: [Patch 2/3] firmware: dmi_scan: add SBMIOS entry and DMI tables
From: Jean Delvare @ 2015-04-16 6:48 UTC (permalink / raw)
To: Roy Franz
Cc: Ivan.khoronzhuk, Linux Kernel Mailing List, Matt Fleming,
Ard Biesheuvel, Grant Likely, linux-api-u79uwXL29TY76Z2rM5mHXA,
linux-doc-u79uwXL29TY76Z2rM5mHXA, Mike Waychison,
dmidecode-devel-qX2TKyscuCcdnm+yROfE0A, Leif Lindholm,
Mark Salter
In-Reply-To: <CAFECyb9RFAEWMOFCDcKKYBgQk85HoDiG2yfyou6X9qm=Wq5+Pg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
Hi Roy,
On Wed, 15 Apr 2015 17:54:51 -0700, Roy Franz wrote:
> On Tue, Apr 14, 2015 at 9:19 PM, Roy Franz <roy.franz-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> wrote:
> > I have made modifications to dmidecode to support this interface, and it
> > works quite nicely for dmidecode. (changes posted to dmidecode-devel list)
> > The only open issue I am aware of is how the SMBIOS v3 entry point
> > will be handled,
> > especially in cases where there is a v2 and a v3 entry point.
> > In principal I think this a good change - are there any other open issues?
>
> I looked at the SMBIOS spec again, and the platform can provide either or
> both of the 32-bit and 64-bit entry points. The spec says that an
> implementation
> "should" provide a 32-bit entry point for compatibility.
>
> These 2 entry point structures can both point to the same SMBIOS
> structure table,
> or two distinct ones. If distinct, the one referenced by the 32-bit
> entry point must be
> a consistent subset of the 64-bit one.
> There does not seem to be any prohibition from using new SMBIOS v3 structures
> in a table referenced by a 32-bit entry point, so backwards
> compatibility is completely
> up to the implementation.
What do you mean with "new SMBIOS v3 structures"? I took a brief look
at the change log at the end of the SMBIOS 3.0.0 specification, and all
I can see are new enumerated values for existing fields, as well as 3
new fields in the type 4 structure. I can't see any new structure type.
Either way this is all backwards compatible, which is why both entry
points can point to the same table.
> Since the point of this patchset (and related changes to dmidecode) is
> to provide the
> SMBIOS information without using /dev/mem, I think the interface we
> define should
> support all the cases outlined in the specification. I would like to
> avoid a case where
> we're back to using /dev/mem to deal with the dual entry/dual table
> case if that becomes
> important down the road.
>
> Here's a proposal for files in /sys/firmware/dmi/tables:
>
> smbios_entry_point32 - 32 bit (existing entry point type), if it exists.
> smbios_entry_point64 - 64 bit entry, new in SMBIOS v3.0
> DMI32 - smbios structure tables referenced by
> 32 bit entry point, if it exists
> DMI64 - smbios structure tables referenced by
> 64 bit entry point, if it exists.
> symlink to DMI32 if identical
> smbios_entry_point - symlink to smbios_entry_point64 if it exists,
> otherwise symlink to smbios_entry_point64
> DMI - symlink to DMI64 if it exists,
> otherwise symlink to DMI32
>
> These last two would provide names to the 'preferred' tables, and
> names that would always exist on all systems, which
> I think is a nice property to have.
>
> Thoughts?
The idea was discussed before, and discarded. The question is, what use
cases do you envision from a user-space application perspective? As you
found out, the table pointed to by the _SM3_ entry point must be a
super-set of the one pointed to by the _SM_ entry point, so for a
compliant implementation there is no reason to follow the _SM_ entry
point when both exist. And if only one entry point exists, there is
nothing to choose from.
The kernel itself will have to choose one of the entry points when it
comes to dmi_scan and dmi-id. It can't provide two sets of DMI strings.
So it seems reasonable to only expose though sysfs that one entry point
and table that the kernel itself used.
The only case where it would make some sense to expose everything to
user-space is for BIOS debugging purpose: if both entry points exist
and point to different tables, and if the _SM3_ table is broken and
the _SM_ table is correct, then you may want to be able to temporarily
read the _SM_ table instead of the _SM3_ table, to check what needs to
be fixed in the latter. But I would argue that this is beyond the scope
of our code: neither the kernel nor dmidecode are DMI table or BIOS
authoring tools.
If there really ever is a need to ignore the _SM3_ entry point, I'd
rather have a kernel boot parameter for this. This would guarantee that
the kernel and user-space applications always operate on the same data.
So I would keep the sysfs interface simple, as Ivan implemented it.
--
Jean Delvare
SUSE L3 Support
^ permalink raw reply
* Re: [Patch 1/3] firmware: dmi_scan: rename dmi_table to dmi_decode_table
From: Jean Delvare @ 2015-04-16 8:35 UTC (permalink / raw)
To: Matt Fleming
Cc: Ivan Khoronzhuk, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
matt.fleming-ral2JQCrhuEAvxtiuMwx3w,
ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A,
grant.likely-QSEj5FYQhm4dnm+yROfE0A,
linux-api-u79uwXL29TY76Z2rM5mHXA,
linux-doc-u79uwXL29TY76Z2rM5mHXA, mikew-hpIqsD4AKlfQT0dZR+AlfA,
dmidecode-devel-qX2TKyscuCcdnm+yROfE0A,
leif.lindholm-QSEj5FYQhm4dnm+yROfE0A,
msalter-H+wXaHxf7aLQT0dZR+AlfA, roy.franz-QSEj5FYQhm4dnm+yROfE0A
In-Reply-To: <20150415143530.GF4804-mF/unelCI9GS6iBeEJttW/XRex20P6io@public.gmane.org>
Hi Matt,
On Wed, 15 Apr 2015 15:35:30 +0100, Matt Fleming wrote:
> On Thu, 02 Apr, at 03:57:01PM, Ivan Khoronzhuk wrote:
> > The "dmi_table" function looks like data instance, but it does DMI
> > table decode. This patch renames it to "dmi_decode_table" name as
> > more appropriate. That allows us to use "dmi_table" name for correct
> > purposes.
> >
> > Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk-hExfYMNmJl/Cnp4W7fqMDg@public.gmane.org>
> > ---
> > drivers/firmware/dmi_scan.c | 10 +++++-----
> > 1 file changed, 5 insertions(+), 5 deletions(-)
>
> Looks good to me.
>
> Jean, do you want me to pick this patch up or are you going to?
Good question, we need to agree on a strategy.
There are 3 patch sets to consider here.
1* My patch fixing the UUID ordering bug. It must go in first and
immediately, as it fixes a regression and will have to be backported
to stable branches.
2* 2 older patches from Ivan which are currently in your efi-next tree
if I'm not mistaken. Both were based on an old tree so they do not
apply cleanly on kernel v4.0, I had to fix them up manually. I have
no idea if git would be able to merge them properly, as the fix
above changed the context even more.
3* The 3 new patches from Ivan which I am reviewing now, which are not
applied in any public tree AFAIK.
I don't really care who picks these patches up and sends them to Linus,
but I think they should all follow the same route so that Linus has as
little merge work to do as possible. So either you pick them all, or I
do. If I do, you'll have to drop the 2 patches you have in efi-next.
Again I'm fine either way, so please let me know what makes your life
easier and let's do that.
Thanks,
--
Jean Delvare
SUSE L3 Support
^ permalink raw reply
* Re: [Patch 2/3] firmware: dmi_scan: add SBMIOS entry and DMI tables
From: Jean Delvare @ 2015-04-16 9:52 UTC (permalink / raw)
To: Ivan Khoronzhuk
Cc: linux-kernel, matt.fleming, ard.biesheuvel, grant.likely,
linux-api, linux-doc, mikew, dmidecode-devel, leif.lindholm,
msalter, roy.franz
In-Reply-To: <1427979423-22767-3-git-send-email-ivan.khoronzhuk@globallogic.com>
Hi Ivan,
On Thu, 2 Apr 2015 15:57:02 +0300, Ivan Khoronzhuk wrote:
> Some utils, like dmidecode and smbios, need to access SMBIOS entry
> table area in order to get information like SMBIOS version, size, etc.
> Currently it's done via /dev/mem. But for situation when /dev/mem
> usage is disabled, the utils have to use dmi sysfs instead, which
> doesn't represent SMBIOS entry and adds code/delay redundancy when direct
> access for table is needed.
>
> So this patch creates dmi/tables and adds SMBIOS entry point to allow
> utils in question to work correctly without /dev/mem. Also patch adds
> raw dmi table to simplify dmi table processing in user space, as
> proposed by Jean Delvare.
>
> Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk@globallogic.com>
> ---
> .../ABI/testing/sysfs-firmware-dmi-tables | 22 ++++++
> drivers/firmware/dmi-sysfs.c | 11 ++-
> drivers/firmware/dmi_scan.c | 80 ++++++++++++++++++++++
> include/linux/dmi.h | 1 +
> 4 files changed, 107 insertions(+), 7 deletions(-)
> create mode 100644 Documentation/ABI/testing/sysfs-firmware-dmi-tables
First of all: thanks for doing this, it looks mostly good now, and I've
tested it successfully on my own system.
> diff --git a/Documentation/ABI/testing/sysfs-firmware-dmi-tables b/Documentation/ABI/testing/sysfs-firmware-dmi-tables
> new file mode 100644
> index 0000000..f46158c
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-firmware-dmi-tables
> @@ -0,0 +1,22 @@
> +What: /sys/firmware/dmi/tables/
> +Date: April 2015
> +Contact: Ivan Khoronzhuk <ivan.khoronzhuk@globallogic.com>
> +Description:
> + The firmware provides DMI structures as a packed list of
> + data referenced by a SMBIOS table entry point. The SMBIOS
> + entry point contains general information, like SMBIOS
> + version, DMI table size, etc. The structure, content and
> + size of SMBIOS entry point is dependent on SMBIOS version.
> + The format of SMBIOS entry point, equal as DMI structures
> + can be read in SMBIOS specification.
"equal as" sounds strange, I think a simple "and" would be better.
> +
> + The dmi/tables provides raw SMBIOS entry point and DMI tables
> + through sysfs as an alternative to utilities reading them
> + from /dev/mem. The raw SMBIOS entry point and DMI table are
> + presented as raw attributes and are accessible via:
"binary attributes" rather than "raw attributes"? The "raw" nature is
already mentioned earlier in the sentence.
> +
> + /sys/firmware/dmi/tables/smbios_entry_point
> + /sys/firmware/dmi/tables/DMI
> +
> + The complete DMI information can be taken using these two
"obtained" or "decoded" would sound better than "taken" IMHO.
> + tables.
> diff --git a/drivers/firmware/dmi-sysfs.c b/drivers/firmware/dmi-sysfs.c
> index e0f1cb3..8e1a411 100644
> --- a/drivers/firmware/dmi-sysfs.c
> +++ b/drivers/firmware/dmi-sysfs.c
> @@ -566,7 +566,6 @@ static struct kobj_type dmi_sysfs_entry_ktype = {
> .default_attrs = dmi_sysfs_entry_attrs,
> };
>
> -static struct kobject *dmi_kobj;
> static struct kset *dmi_kset;
>
> /* Global count of all instances seen. Only for setup */
> @@ -651,10 +650,11 @@ static int __init dmi_sysfs_init(void)
> int error = -ENOMEM;
This initialization can be moved to the single error path left that
needs it. (I can do it myself in a separate patch if you don't want to
do it here.)
> int val;
>
> - /* Set up our directory */
> - dmi_kobj = kobject_create_and_add("dmi", firmware_kobj);
> - if (!dmi_kobj)
> + if (!dmi_kobj) {
> + pr_err("dmi-sysfs: dmi entry is absent.\n");
> + error = -ENOSYS;
> goto err;
> + }
>
> dmi_kset = kset_create_and_add("entries", NULL, dmi_kobj);
> if (!dmi_kset)
> @@ -675,7 +675,6 @@ static int __init dmi_sysfs_init(void)
> err:
> cleanup_entry_list();
> kset_unregister(dmi_kset);
> - kobject_put(dmi_kobj);
> return error;
> }
>
> @@ -685,8 +684,6 @@ static void __exit dmi_sysfs_exit(void)
> pr_debug("dmi-sysfs: unloading.\n");
> cleanup_entry_list();
> kset_unregister(dmi_kset);
> - kobject_del(dmi_kobj);
> - kobject_put(dmi_kobj);
> }
>
> module_init(dmi_sysfs_init);
> diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
> index d3aae09..bb19f8b 100644
> --- a/drivers/firmware/dmi_scan.c
> +++ b/drivers/firmware/dmi_scan.c
> @@ -10,6 +10,9 @@
> #include <asm/dmi.h>
> #include <asm/unaligned.h>
>
> +struct kobject *dmi_kobj;
> +EXPORT_SYMBOL_GPL(dmi_kobj);
> +
> /*
> * DMI stands for "Desktop Management Interface". It is part
> * of and an antecedent to, SMBIOS, which stands for System
> @@ -20,6 +23,9 @@ static const char dmi_empty_string[] = " ";
> static u32 dmi_ver __initdata;
> static u32 dmi_len;
> static u16 dmi_num;
> +static u8 smbios_entry_point[32];
> +static int smbios_entry_point_size;
> +
> /*
> * Catch too early calls to dmi_check_system():
> */
> @@ -118,6 +124,7 @@ static void dmi_decode_table(u8 *buf,
> }
>
> static phys_addr_t dmi_base;
> +static u8 *dmi_table;
This variable is only ever used in a single function (dmi_init). Does
it actually need to be a global variable? I suspect not.
>
> static int __init dmi_walk_early(void (*decode)(const struct dmi_header *,
> void *))
> @@ -476,6 +483,8 @@ static int __init dmi_present(const u8 *buf)
> if (memcmp(buf, "_SM_", 4) == 0 &&
> buf[5] < 32 && dmi_checksum(buf, buf[5])) {
> smbios_ver = get_unaligned_be16(buf + 6);
> + smbios_entry_point_size = buf[5];
> + memcpy(smbios_entry_point, buf, smbios_entry_point_size);
>
> /* Some BIOS report weird SMBIOS version, fix that up */
> switch (smbios_ver) {
> @@ -508,6 +517,9 @@ static int __init dmi_present(const u8 *buf)
> dmi_ver >> 8, dmi_ver & 0xFF,
> (dmi_ver < 0x0300) ? "" : ".x");
> } else {
> + smbios_entry_point_size = 15;
> + memcpy(smbios_entry_point, buf,
> + smbios_entry_point_size);
> dmi_ver = (buf[14] & 0xF0) << 4 |
> (buf[14] & 0x0F);
> pr_info("Legacy DMI %d.%d present.\n",
> @@ -535,6 +547,8 @@ static int __init dmi_smbios3_present(const u8 *buf)
> dmi_ver &= 0xFFFFFF;
> dmi_len = get_unaligned_le32(buf + 12);
> dmi_base = get_unaligned_le64(buf + 16);
> + smbios_entry_point_size = buf[6];
> + memcpy(smbios_entry_point, buf, smbios_entry_point_size);
>
> /*
> * The 64-bit SMBIOS 3.0 entry point no longer has a field
> @@ -638,6 +652,72 @@ void __init dmi_scan_machine(void)
> dmi_initialized = 1;
> }
>
> +static ssize_t raw_table_read(struct file *file, struct kobject *kobj,
> + struct bin_attribute *attr, char *buf,
> + loff_t pos, size_t count)
> +{
> + memcpy(buf, attr->private + pos, count);
> + return count;
> +}
> +
> +static BIN_ATTR(smbios_entry_point, S_IRUSR, raw_table_read, NULL, 0);
This one could be world-readable as it contains no sensitive
information.
> +struct bin_attribute bin_attr_dmi_table =
> + __BIN_ATTR(DMI, S_IRUSR, raw_table_read, NULL, 0);
I do not understand why you don't use BIN_ATTR here too? I tried naming
the attribute bin_attr_DMI and it seems to work just fine, checkpatch
doesn't even complain!
> +
> +static int __init dmi_init(void)
> +{
> + int ret = -ENOMEM;
> + struct kobject *tables_kobj = NULL;
> +
> + if (!dmi_available) {
> + ret = -ENOSYS;
> + goto err;
> + }
This is weird. Can this actually happen?
We currently have two ways to enter this module: dmi_scan_machine(),
which is called by the architecture code, and dmi_init(), which is
called at subsys_initcall time. As far as I can see,
core/arch_initcalls are guaranteed to be always called before
subsys_initcalls. If we can rely on that, the test above is not needed.
If for any reason we can't, that means that dmi_init() should not be a
subsys_initcall, but should instead be called explicitly at the end of
dmi_scan_machine().
> +
> + /* Set up dmi directory at /sys/firmware/dmi */
> + dmi_kobj = kobject_create_and_add("dmi", firmware_kobj);
> + if (!dmi_kobj)
> + goto err;
> +
> + tables_kobj = kobject_create_and_add("tables", dmi_kobj);
> + if (!tables_kobj)
> + goto err;
> +
> + bin_attr_smbios_entry_point.size = smbios_entry_point_size;
> + bin_attr_smbios_entry_point.private = smbios_entry_point;
> + ret = sysfs_create_bin_file(tables_kobj, &bin_attr_smbios_entry_point);
> + if (ret)
> + goto err;
> +
> + dmi_table = dmi_remap(dmi_base, dmi_len);
> + if (!dmi_table)
> + goto err;
At this point "ret" has value 0 so you will take the error path but
return with success. No good. I suggest that you move the call to
dmi_remap before the first call to sysfs_create_bin_file above, so that
"ret" still has value -ENOMEM.
> +
> + bin_attr_dmi_table.size = dmi_len;
> + bin_attr_dmi_table.private = dmi_table;
> + ret = sysfs_create_bin_file(tables_kobj, &bin_attr_dmi_table);
> + if (ret) {
> + dmi_unmap(dmi_table);
Doing this here goes against the logic of having a single error path.
Instead you should have an additional error label before err: and jump
there.
> + goto err;
> + }
> +
> + return 0;
> +err:
> + pr_err("dmi: Firmware registration failed.\n");
> +
> + if (tables_kobj)
> + sysfs_remove_bin_file(tables_kobj,
> + &bin_attr_smbios_entry_point);
> + kobject_del(tables_kobj);
> + kobject_put(tables_kobj);
These last two calls could be moved inside the conditional above. Even
better would be a separate error label so that you know exactly what
needs to be undone.
> + kobject_del(dmi_kobj);
> + kobject_put(dmi_kobj);
> + dmi_kobj = NULL;
I'm wondering, wouldn't it make sense to keep dmi_kobj alive (with an
appropriate comment), so that dmi-sysfs has a chance to load? As it is
now, a bug or some unexpected behavior in this new code could cause a
regression for dmi-sysfs users. Just because I don't like dmi_sysfs
doesn't mean we can break it ;-)
> +
> + return ret;
> +}
> +subsys_initcall(dmi_init);
> +
> /**
> * dmi_set_dump_stack_arch_desc - set arch description for dump_stack()
> *
> diff --git a/include/linux/dmi.h b/include/linux/dmi.h
> index f820f0a..9f55f46 100644
> --- a/include/linux/dmi.h
> +++ b/include/linux/dmi.h
> @@ -93,6 +93,7 @@ struct dmi_dev_onboard {
> int devfn;
> };
>
> +extern struct kobject *dmi_kobj;
struct kobject is defined in <linux/kobject.h> so I think you should
include that file to avoid random build failures in the future.
> extern int dmi_check_system(const struct dmi_system_id *list);
> const struct dmi_system_id *dmi_first_match(const struct dmi_system_id *list);
> extern const char * dmi_get_system_info(int field);
--
Jean Delvare
SUSE L3 Support
^ permalink raw reply
* Re: [Patch 2/3] firmware: dmi_scan: add SBMIOS entry and DMI tables
From: Ivan.khoronzhuk @ 2015-04-16 12:56 UTC (permalink / raw)
To: Jean Delvare
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
matt.fleming-ral2JQCrhuEAvxtiuMwx3w,
ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A,
grant.likely-QSEj5FYQhm4dnm+yROfE0A,
linux-api-u79uwXL29TY76Z2rM5mHXA,
linux-doc-u79uwXL29TY76Z2rM5mHXA, mikew-hpIqsD4AKlfQT0dZR+AlfA,
dmidecode-devel-qX2TKyscuCcdnm+yROfE0A,
leif.lindholm-QSEj5FYQhm4dnm+yROfE0A,
msalter-H+wXaHxf7aLQT0dZR+AlfA, roy.franz-QSEj5FYQhm4dnm+yROfE0A
In-Reply-To: <20150416115252.7dc964a3-R0o5gVi9kd7kN2dkZ6Wm7A@public.gmane.org>
Hi Jean,
On 16.04.15 12:52, Jean Delvare wrote:
> Hi Ivan,
>
> On Thu, 2 Apr 2015 15:57:02 +0300, Ivan Khoronzhuk wrote:
>> Some utils, like dmidecode and smbios, need to access SMBIOS entry
>> table area in order to get information like SMBIOS version, size, etc.
>> Currently it's done via /dev/mem. But for situation when /dev/mem
>> usage is disabled, the utils have to use dmi sysfs instead, which
>> doesn't represent SMBIOS entry and adds code/delay redundancy when direct
>> access for table is needed.
>>
>> So this patch creates dmi/tables and adds SMBIOS entry point to allow
>> utils in question to work correctly without /dev/mem. Also patch adds
>> raw dmi table to simplify dmi table processing in user space, as
>> proposed by Jean Delvare.
>>
>> Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk-hExfYMNmJl/Cnp4W7fqMDg@public.gmane.org>
>> ---
>> .../ABI/testing/sysfs-firmware-dmi-tables | 22 ++++++
>> drivers/firmware/dmi-sysfs.c | 11 ++-
>> drivers/firmware/dmi_scan.c | 80 ++++++++++++++++++++++
>> include/linux/dmi.h | 1 +
>> 4 files changed, 107 insertions(+), 7 deletions(-)
>> create mode 100644 Documentation/ABI/testing/sysfs-firmware-dmi-tables
> First of all: thanks for doing this, it looks mostly good now, and I've
> tested it successfully on my own system.
>
>> diff --git a/Documentation/ABI/testing/sysfs-firmware-dmi-tables b/Documentation/ABI/testing/sysfs-firmware-dmi-tables
>> new file mode 100644
>> index 0000000..f46158c
>> --- /dev/null
>> +++ b/Documentation/ABI/testing/sysfs-firmware-dmi-tables
>> @@ -0,0 +1,22 @@
>> +What: /sys/firmware/dmi/tables/
>> +Date: April 2015
>> +Contact: Ivan Khoronzhuk <ivan.khoronzhuk-hExfYMNmJl/Cnp4W7fqMDg@public.gmane.org>
>> +Description:
>> + The firmware provides DMI structures as a packed list of
>> + data referenced by a SMBIOS table entry point. The SMBIOS
>> + entry point contains general information, like SMBIOS
>> + version, DMI table size, etc. The structure, content and
>> + size of SMBIOS entry point is dependent on SMBIOS version.
>> + The format of SMBIOS entry point, equal as DMI structures
>> + can be read in SMBIOS specification.
> "equal as" sounds strange, I think a simple "and" would be better.
Ok
>
>> +
>> + The dmi/tables provides raw SMBIOS entry point and DMI tables
>> + through sysfs as an alternative to utilities reading them
>> + from /dev/mem. The raw SMBIOS entry point and DMI table are
>> + presented as raw attributes and are accessible via:
> "binary attributes" rather than "raw attributes"? The "raw" nature is
> already mentioned earlier in the sentence.
Ok
>
>> +
>> + /sys/firmware/dmi/tables/smbios_entry_point
>> + /sys/firmware/dmi/tables/DMI
>> +
>> + The complete DMI information can be taken using these two
> "obtained" or "decoded" would sound better than "taken" IMHO.
Ok
>
>> + tables.
>> diff --git a/drivers/firmware/dmi-sysfs.c b/drivers/firmware/dmi-sysfs.c
>> index e0f1cb3..8e1a411 100644
>> --- a/drivers/firmware/dmi-sysfs.c
>> +++ b/drivers/firmware/dmi-sysfs.c
>> @@ -566,7 +566,6 @@ static struct kobj_type dmi_sysfs_entry_ktype = {
>> .default_attrs = dmi_sysfs_entry_attrs,
>> };
>>
>> -static struct kobject *dmi_kobj;
>> static struct kset *dmi_kset;
>>
>> /* Global count of all instances seen. Only for setup */
>> @@ -651,10 +650,11 @@ static int __init dmi_sysfs_init(void)
>> int error = -ENOMEM;
> This initialization can be moved to the single error path left that
> needs it. (I can do it myself in a separate patch if you don't want to
> do it here.)
Let it be in this patch.
>> int val;
>>
>> - /* Set up our directory */
>> - dmi_kobj = kobject_create_and_add("dmi", firmware_kobj);
>> - if (!dmi_kobj)
>> + if (!dmi_kobj) {
>> + pr_err("dmi-sysfs: dmi entry is absent.\n");
>> + error = -ENOSYS;
>> goto err;
>> + }
>>
>> dmi_kset = kset_create_and_add("entries", NULL, dmi_kobj);
>> if (!dmi_kset)
>> @@ -675,7 +675,6 @@ static int __init dmi_sysfs_init(void)
>> err:
>> cleanup_entry_list();
>> kset_unregister(dmi_kset);
>> - kobject_put(dmi_kobj);
>> return error;
>> }
>>
>> @@ -685,8 +684,6 @@ static void __exit dmi_sysfs_exit(void)
>> pr_debug("dmi-sysfs: unloading.\n");
>> cleanup_entry_list();
>> kset_unregister(dmi_kset);
>> - kobject_del(dmi_kobj);
>> - kobject_put(dmi_kobj);
>> }
>>
>> module_init(dmi_sysfs_init);
>> diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
>> index d3aae09..bb19f8b 100644
>> --- a/drivers/firmware/dmi_scan.c
>> +++ b/drivers/firmware/dmi_scan.c
>> @@ -10,6 +10,9 @@
>> #include <asm/dmi.h>
>> #include <asm/unaligned.h>
>>
>> +struct kobject *dmi_kobj;
>> +EXPORT_SYMBOL_GPL(dmi_kobj);
>> +
>> /*
>> * DMI stands for "Desktop Management Interface". It is part
>> * of and an antecedent to, SMBIOS, which stands for System
>> @@ -20,6 +23,9 @@ static const char dmi_empty_string[] = " ";
>> static u32 dmi_ver __initdata;
>> static u32 dmi_len;
>> static u16 dmi_num;
>> +static u8 smbios_entry_point[32];
>> +static int smbios_entry_point_size;
>> +
>> /*
>> * Catch too early calls to dmi_check_system():
>> */
>> @@ -118,6 +124,7 @@ static void dmi_decode_table(u8 *buf,
>> }
>>
>> static phys_addr_t dmi_base;
>> +static u8 *dmi_table;
> This variable is only ever used in a single function (dmi_init). Does
> it actually need to be a global variable? I suspect not.
, Yes.
>
>>
>> static int __init dmi_walk_early(void (*decode)(const struct dmi_header *,
>> void *))
>> @@ -476,6 +483,8 @@ static int __init dmi_present(const u8 *buf)
>> if (memcmp(buf, "_SM_", 4) == 0 &&
>> buf[5] < 32 && dmi_checksum(buf, buf[5])) {
>> smbios_ver = get_unaligned_be16(buf + 6);
>> + smbios_entry_point_size = buf[5];
>> + memcpy(smbios_entry_point, buf, smbios_entry_point_size);
>>
>> /* Some BIOS report weird SMBIOS version, fix that up */
>> switch (smbios_ver) {
>> @@ -508,6 +517,9 @@ static int __init dmi_present(const u8 *buf)
>> dmi_ver >> 8, dmi_ver & 0xFF,
>> (dmi_ver < 0x0300) ? "" : ".x");
>> } else {
>> + smbios_entry_point_size = 15;
>> + memcpy(smbios_entry_point, buf,
>> + smbios_entry_point_size);
>> dmi_ver = (buf[14] & 0xF0) << 4 |
>> (buf[14] & 0x0F);
>> pr_info("Legacy DMI %d.%d present.\n",
>> @@ -535,6 +547,8 @@ static int __init dmi_smbios3_present(const u8 *buf)
>> dmi_ver &= 0xFFFFFF;
>> dmi_len = get_unaligned_le32(buf + 12);
>> dmi_base = get_unaligned_le64(buf + 16);
>> + smbios_entry_point_size = buf[6];
>> + memcpy(smbios_entry_point, buf, smbios_entry_point_size);
>>
>> /*
>> * The 64-bit SMBIOS 3.0 entry point no longer has a field
>> @@ -638,6 +652,72 @@ void __init dmi_scan_machine(void)
>> dmi_initialized = 1;
>> }
>>
>> +static ssize_t raw_table_read(struct file *file, struct kobject *kobj,
>> + struct bin_attribute *attr, char *buf,
>> + loff_t pos, size_t count)
>> +{
>> + memcpy(buf, attr->private + pos, count);
>> + return count;
>> +}
>> +
>> +static BIN_ATTR(smbios_entry_point, S_IRUSR, raw_table_read, NULL, 0);
> This one could be world-readable as it contains no sensitive
> information.
It contains the address of DMI table containing sensitive information.
Who knows which ways can be used to take it. Anyway, no see reasons in this
w/o DMI table. But if you insist I can do it "world-readable".
>
>> +struct bin_attribute bin_attr_dmi_table =
>> + __BIN_ATTR(DMI, S_IRUSR, raw_table_read, NULL, 0);
> I do not understand why you don't use BIN_ATTR here too? I tried naming
> the attribute bin_attr_DMI and it seems to work just fine, checkpatch
> doesn't even complain!
I dislike upper case in names, at least in such simple names.
It makes me using bin_attr_DMI lower in the code. That's why.
But if you like it, I will name it "bin_attr_DMI"
>
>> +
>> +static int __init dmi_init(void)
>> +{
>> + int ret = -ENOMEM;
>> + struct kobject *tables_kobj = NULL;
>> +
>> + if (!dmi_available) {
>> + ret = -ENOSYS;
>> + goto err;
>> + }
> This is weird. Can this actually happen?
>
> We currently have two ways to enter this module: dmi_scan_machine(),
> which is called by the architecture code, and dmi_init(), which is
> called at subsys_initcall time. As far as I can see,
> core/arch_initcalls are guaranteed to be always called before
> subsys_initcalls. If we can rely on that, the test above is not needed.
> If for any reason we can't, that means that dmi_init() should not be a
> subsys_initcall, but should instead be called explicitly at the end of
> dmi_scan_machine().
We cannot be sure that firmware_kobj created at time of dmi_init().
The sources don't oblige you to call it at core level,
for instance like it was done for arm64. For x86, dmi_init() can be called
before firmware_kobj is created. And if I call it from dmi_init() I suppose
I would face an error. As I can't call it in dmi_init I can't be sure that
DMI is available at all. So, no, we have to check dmi_available here and
call
it at subsys layer, where it's supposed to be.
>> +
>> + /* Set up dmi directory at /sys/firmware/dmi */
>> + dmi_kobj = kobject_create_and_add("dmi", firmware_kobj);
>> + if (!dmi_kobj)
>> + goto err;
>> +
>> + tables_kobj = kobject_create_and_add("tables", dmi_kobj);
>> + if (!tables_kobj)
>> + goto err;
>> +
>> + bin_attr_smbios_entry_point.size = smbios_entry_point_size;
>> + bin_attr_smbios_entry_point.private = smbios_entry_point;
>> + ret = sysfs_create_bin_file(tables_kobj, &bin_attr_smbios_entry_point);
>> + if (ret)
>> + goto err;
>> +
>> + dmi_table = dmi_remap(dmi_base, dmi_len);
>> + if (!dmi_table)
>> + goto err;
> At this point "ret" has value 0 so you will take the error path but
> return with success. No good. I suggest that you move the call to
> dmi_remap before the first call to sysfs_create_bin_file above, so that
> "ret" still has value -ENOMEM.
Yes.
>
>> +
>> + bin_attr_dmi_table.size = dmi_len;
>> + bin_attr_dmi_table.private = dmi_table;
>> + ret = sysfs_create_bin_file(tables_kobj, &bin_attr_dmi_table);
>> + if (ret) {
>> + dmi_unmap(dmi_table);
> Doing this here goes against the logic of having a single error path.
> Instead you should have an additional error label before err: and jump
> there.
I will redo this.
>
>> + goto err;
>> + }
>> +
>> + return 0;
>> +err:
>> + pr_err("dmi: Firmware registration failed.\n");
>> +
>> + if (tables_kobj)
>> + sysfs_remove_bin_file(tables_kobj,
>> + &bin_attr_smbios_entry_point);
>> + kobject_del(tables_kobj);
>> + kobject_put(tables_kobj);
> These last two calls could be moved inside the conditional above. Even
> better would be a separate error label so that you know exactly what
> needs to be undone.
Let it be.
>
>> + kobject_del(dmi_kobj);
>> + kobject_put(dmi_kobj);
>> + dmi_kobj = NULL;
> I'm wondering, wouldn't it make sense to keep dmi_kobj alive (with an
> appropriate comment), so that dmi-sysfs has a chance to load? As it is
> now, a bug or some unexpected behavior in this new code could cause a
> regression for dmi-sysfs users. Just because I don't like dmi_sysfs
> doesn't mean we can break it ;-)
As I remember it was not so critical for you last time.
"I don't care which way you choose". And I've explained my position.
But it's not very hard to me to change it. Anyway patch requires re-push.
>
>> +
>> + return ret;
>> +}
>> +subsys_initcall(dmi_init);
>> +
>> /**
>> * dmi_set_dump_stack_arch_desc - set arch description for dump_stack()
>> *
>> diff --git a/include/linux/dmi.h b/include/linux/dmi.h
>> index f820f0a..9f55f46 100644
>> --- a/include/linux/dmi.h
>> +++ b/include/linux/dmi.h
>> @@ -93,6 +93,7 @@ struct dmi_dev_onboard {
>> int devfn;
>> };
>>
>> +extern struct kobject *dmi_kobj;
> struct kobject is defined in <linux/kobject.h> so I think you should
> include that file to avoid random build failures in the future.
Ok
>
>> extern int dmi_check_system(const struct dmi_system_id *list);
>> const struct dmi_system_id *dmi_first_match(const struct dmi_system_id *list);
>> extern const char * dmi_get_system_info(int field);
>
Thanks Jean.
I will add you propositions and re-push the series.
If you are OK with my answer of-course.
--
Regards,
Ivan Khoronzhuk
^ permalink raw reply
* Re: [dmidecode] [Patch 2/3] firmware: dmi_scan: add SBMIOS entry and DMI tables
From: Jean Delvare @ 2015-04-16 15:44 UTC (permalink / raw)
To: Ivan.khoronzhuk
Cc: dmidecode-devel, matt.fleming, linux-doc, linux-api,
ard.biesheuvel, linux-kernel, leif.lindholm, mikew, roy.franz,
msalter, grant.likely
In-Reply-To: <552FB18D.6080207@globallogic.com>
Hi Ivan,
Le Thursday 16 April 2015 à 15:56 +0300, Ivan.khoronzhuk a écrit :
> On 16.04.15 12:52, Jean Delvare wrote:
> > On Thu, 2 Apr 2015 15:57:02 +0300, Ivan Khoronzhuk wrote:
> >> +static BIN_ATTR(smbios_entry_point, S_IRUSR, raw_table_read, NULL, 0);
> > This one could be world-readable as it contains no sensitive
> > information.
>
> It contains the address of DMI table containing sensitive information.
> Who knows which ways can be used to take it. Anyway, no see reasons in this
> w/o DMI table. But if you insist I can do it "world-readable".
OK, you convinced me.
> >
> >> +struct bin_attribute bin_attr_dmi_table =
> >> + __BIN_ATTR(DMI, S_IRUSR, raw_table_read, NULL, 0);
> > I do not understand why you don't use BIN_ATTR here too? I tried naming
> > the attribute bin_attr_DMI and it seems to work just fine, checkpatch
> > doesn't even complain!
>
> I dislike upper case in names, at least in such simple names.
> It makes me using bin_attr_DMI lower in the code. That's why.
> But if you like it, I will name it "bin_attr_DMI"
I don't like upper case in names either, but in this specific case, I'd
do it for consistency. As you wish though, I really only wanted to know
the reason.
> >> +
> >> +static int __init dmi_init(void)
> >> +{
> >> + int ret = -ENOMEM;
> >> + struct kobject *tables_kobj = NULL;
> >> +
> >> + if (!dmi_available) {
> >> + ret = -ENOSYS;
> >> + goto err;
> >> + }
> > This is weird. Can this actually happen?
> >
> > We currently have two ways to enter this module: dmi_scan_machine(),
> > which is called by the architecture code, and dmi_init(), which is
> > called at subsys_initcall time. As far as I can see,
> > core/arch_initcalls are guaranteed to be always called before
> > subsys_initcalls. If we can rely on that, the test above is not needed.
> > If for any reason we can't, that means that dmi_init() should not be a
> > subsys_initcall, but should instead be called explicitly at the end of
> > dmi_scan_machine().
>
> We cannot be sure that firmware_kobj created at time of dmi_init().
> The sources don't oblige you to call it at core level,
> for instance like it was done for arm64. For x86, dmi_init() can be called
> before firmware_kobj is created.
Looking at the code, it seems that firmware_kobj is created very, very
early in the boot process. In do_basic_setup(), you can see that
driver_init() (which in turn calls firmware_init(), creating
firmware_kobj) is called before do_initcalls(). So firmware_kobj must be
defined before dmi_scan_machine() or dmi_init() is called.
Oh, and this wasn't even my point ;-) I'm fine with you checking if
firmware_kobj is defined. My question was about the dmi_available check
above. But that question was silly anyway, sorry. I confused
dmi_available with dmi_initialized. Checking for dmi_available is
perfectly reasonable, please scratch my objection.
> And if I call it from dmi_init() I suppose
> I would face an error. As I can't call it in dmi_init I can't be sure that
> DMI is available at all. So, no, we have to check dmi_available here and
> call it at subsys layer, where it's supposed to be.
I can't parse that, I suspect you wrote dmi_init where you actually
meant dmi_scan_machine? Given how early firmware_kobj is created, I
think the code currently in dmi_init could in fact go at the end of
dmi_scan_machine. But it's not important for the time being, this can be
attempted later.
> >> (...)
> >> + kobject_del(dmi_kobj);
> >> + kobject_put(dmi_kobj);
> >> + dmi_kobj = NULL;
> > I'm wondering, wouldn't it make sense to keep dmi_kobj alive (with an
> > appropriate comment), so that dmi-sysfs has a chance to load? As it is
> > now, a bug or some unexpected behavior in this new code could cause a
> > regression for dmi-sysfs users. Just because I don't like dmi_sysfs
> > doesn't mean we can break it ;-)
>
> As I remember it was not so critical for you last time.
> "I don't care which way you choose". And I've explained my position.
> But it's not very hard to me to change it. Anyway patch requires re-push.
You're right, I did not remember we had discussed this already,
sorry :-(
Well, I still agree that it doesn't really matter, but of two acceptable
solutions for an event which will most likely never happen, why not go
for the ones with the fewer lines of code? ;-)
> (...)
> Thanks Jean.
> I will add you propositions and re-push the series.
> If you are OK with my answer of-course.
You're welcome. Yes I think we have clarified everything now so you can
submit the next (hopefully last) iteration.
Thank you,
--
Jean Delvare
SUSE L3 Support
_______________________________________________
https://lists.nongnu.org/mailman/listinfo/dmidecode-devel
^ permalink raw reply
* [PATCH] HID: roccat: Removing all modules except Kone
From: Stefan Achatz @ 2015-04-16 16:39 UTC (permalink / raw)
To: Jiri Kosina, linux-api-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-input-u79uwXL29TY76Z2rM5mHXA
This patch removes all roccat hid modules except the one for the first Kone.
Package roccat-tools is the only known user of these modules. Starting with
roccat-tools-2.2.0, released 7 months ago, I'm not using these modules
anymore. All functionality has been moved to userspace using hidraw.
The first Kone is not fully HID-compliant and still needs a module.
Signed-off-by: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
---
.../ABI/obsolete/sysfs-driver-hid-roccat-koneplus | 48 --
.../ABI/obsolete/sysfs-driver-hid-roccat-kovaplus | 66 --
.../ABI/obsolete/sysfs-driver-hid-roccat-pyra | 73 ---
.../ABI/testing/sysfs-driver-hid-roccat-arvo | 53 --
.../ABI/testing/sysfs-driver-hid-roccat-isku | 153 -----
.../ABI/testing/sysfs-driver-hid-roccat-koneplus | 96 ---
.../ABI/testing/sysfs-driver-hid-roccat-konepure | 105 ---
.../ABI/testing/sysfs-driver-hid-roccat-kovaplus | 49 --
.../ABI/testing/sysfs-driver-hid-roccat-lua | 7 -
.../ABI/testing/sysfs-driver-hid-roccat-pyra | 49 --
.../ABI/testing/sysfs-driver-hid-roccat-ryos | 178 ------
.../ABI/testing/sysfs-driver-hid-roccat-savu | 76 ---
drivers/hid/Kconfig | 6 +-
drivers/hid/Makefile | 5 +-
drivers/hid/hid-core.c | 15 -
drivers/hid/hid-ids.h | 15 -
drivers/hid/hid-roccat-arvo.c | 460 --------------
drivers/hid/hid-roccat-arvo.h | 85 ---
drivers/hid/hid-roccat-isku.c | 462 --------------
drivers/hid/hid-roccat-isku.h | 100 ---
drivers/hid/hid-roccat-koneplus.c | 578 -----------------
drivers/hid/hid-roccat-koneplus.h | 125 ----
drivers/hid/hid-roccat-konepure.c | 232 -------
drivers/hid/hid-roccat-kovaplus.c | 665 --------------------
drivers/hid/hid-roccat-kovaplus.h | 133 ----
drivers/hid/hid-roccat-lua.c | 215 -------
drivers/hid/hid-roccat-lua.h | 29 -
drivers/hid/hid-roccat-pyra.c | 615 ------------------
drivers/hid/hid-roccat-pyra.h | 152 -----
drivers/hid/hid-roccat-ryos.c | 241 -------
drivers/hid/hid-roccat-savu.c | 229 -------
drivers/hid/hid-roccat-savu.h | 55 --
32 files changed, 4 insertions(+), 5366 deletions(-)
delete mode 100644 Documentation/ABI/obsolete/sysfs-driver-hid-roccat-koneplus
delete mode 100644 Documentation/ABI/obsolete/sysfs-driver-hid-roccat-kovaplus
delete mode 100644 Documentation/ABI/obsolete/sysfs-driver-hid-roccat-pyra
delete mode 100644 Documentation/ABI/testing/sysfs-driver-hid-roccat-arvo
delete mode 100644 Documentation/ABI/testing/sysfs-driver-hid-roccat-isku
delete mode 100644 Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus
delete mode 100644 Documentation/ABI/testing/sysfs-driver-hid-roccat-konepure
delete mode 100644 Documentation/ABI/testing/sysfs-driver-hid-roccat-kovaplus
delete mode 100644 Documentation/ABI/testing/sysfs-driver-hid-roccat-lua
delete mode 100644 Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra
delete mode 100644 Documentation/ABI/testing/sysfs-driver-hid-roccat-ryos
delete mode 100644 Documentation/ABI/testing/sysfs-driver-hid-roccat-savu
delete mode 100644 drivers/hid/hid-roccat-arvo.c
delete mode 100644 drivers/hid/hid-roccat-arvo.h
delete mode 100644 drivers/hid/hid-roccat-isku.c
delete mode 100644 drivers/hid/hid-roccat-isku.h
delete mode 100644 drivers/hid/hid-roccat-koneplus.c
delete mode 100644 drivers/hid/hid-roccat-koneplus.h
delete mode 100644 drivers/hid/hid-roccat-konepure.c
delete mode 100644 drivers/hid/hid-roccat-kovaplus.c
delete mode 100644 drivers/hid/hid-roccat-kovaplus.h
delete mode 100644 drivers/hid/hid-roccat-lua.c
delete mode 100644 drivers/hid/hid-roccat-lua.h
delete mode 100644 drivers/hid/hid-roccat-pyra.c
delete mode 100644 drivers/hid/hid-roccat-pyra.h
delete mode 100644 drivers/hid/hid-roccat-ryos.c
delete mode 100644 drivers/hid/hid-roccat-savu.c
delete mode 100644 drivers/hid/hid-roccat-savu.h
diff --git a/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-koneplus b/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-koneplus
deleted file mode 100644
index 833fd59..0000000
--- a/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-koneplus
+++ /dev/null
@@ -1,48 +0,0 @@
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/startup_profile
-Date: October 2010
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: The integer value of this attribute ranges from 0-4.
- When read, this attribute returns the number of the actual
- profile. This value is persistent, so its equivalent to the
- profile that's active when the mouse is powered on next time.
- When written, this file sets the number of the startup profile
- and the mouse activates this profile immediately.
- Please use actual_profile, it does the same thing.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/firmware_version
-Date: October 2010
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When read, this file returns the raw integer version number of the
- firmware reported by the mouse. Using the integer value eases
- further usage in other programs. To receive the real version
- number the decimal point has to be shifted 2 positions to the
- left. E.g. a returned value of 121 means 1.21
- This file is readonly.
- Please read binary attribute info which contains firmware version.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile[1-5]_buttons
-Date: August 2010
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: The mouse can store 5 profiles which can be switched by the
- press of a button. A profile is split in settings and buttons.
- profile_buttons holds information about button layout.
- When read, these files return the respective profile buttons.
- The returned data is 77 bytes in size.
- This file is readonly.
- Write control to select profile and read profile_buttons instead.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile[1-5]_settings
-Date: August 2010
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: The mouse can store 5 profiles which can be switched by the
- press of a button. A profile is split in settings and buttons.
- profile_settings holds information like resolution, sensitivity
- and light effects.
- When read, these files return the respective profile settings.
- The returned data is 43 bytes in size.
- This file is readonly.
- Write control to select profile and read profile_settings instead.
-Users: http://roccat.sourceforge.net
\ No newline at end of file
diff --git a/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-kovaplus b/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-kovaplus
deleted file mode 100644
index 4a98e02..0000000
--- a/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-kovaplus
+++ /dev/null
@@ -1,66 +0,0 @@
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_cpi
-Date: January 2011
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: The integer value of this attribute ranges from 1-4.
- When read, this attribute returns the number of the active
- cpi level.
- This file is readonly.
- Has never been used. If bookkeeping is done, it's done in userland tools.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_sensitivity_x
-Date: January 2011
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: The integer value of this attribute ranges from 1-10.
- When read, this attribute returns the number of the actual
- sensitivity in x direction.
- This file is readonly.
- Has never been used. If bookkeeping is done, it's done in userland tools.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_sensitivity_y
-Date: January 2011
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: The integer value of this attribute ranges from 1-10.
- When read, this attribute returns the number of the actual
- sensitivity in y direction.
- This file is readonly.
- Has never been used. If bookkeeping is done, it's done in userland tools.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/firmware_version
-Date: January 2011
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When read, this file returns the raw integer version number of the
- firmware reported by the mouse. Using the integer value eases
- further usage in other programs. To receive the real version
- number the decimal point has to be shifted 2 positions to the
- left. E.g. a returned value of 121 means 1.21
- This file is readonly.
- Obsoleted by binary sysfs attribute "info".
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile[1-5]_buttons
-Date: January 2011
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: The mouse can store 5 profiles which can be switched by the
- press of a button. A profile is split in settings and buttons.
- profile_buttons holds information about button layout.
- When read, these files return the respective profile buttons.
- The returned data is 23 bytes in size.
- This file is readonly.
- Write control to select profile and read profile_buttons instead.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile[1-5]_settings
-Date: January 2011
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: The mouse can store 5 profiles which can be switched by the
- press of a button. A profile is split in settings and buttons.
- profile_settings holds information like resolution, sensitivity
- and light effects.
- When read, these files return the respective profile settings.
- The returned data is 16 bytes in size.
- This file is readonly.
- Write control to select profile and read profile_settings instead.
-Users: http://roccat.sourceforge.net
diff --git a/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-pyra b/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-pyra
deleted file mode 100644
index 87ac87e..0000000
--- a/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-pyra
+++ /dev/null
@@ -1,73 +0,0 @@
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/actual_cpi
-Date: August 2010
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: It is possible to switch the cpi setting of the mouse with the
- press of a button.
- When read, this file returns the raw number of the actual cpi
- setting reported by the mouse. This number has to be further
- processed to receive the real dpi value.
-
- VALUE DPI
- 1 400
- 2 800
- 4 1600
-
- This file is readonly.
- Has never been used. If bookkeeping is done, it's done in userland tools.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/actual_profile
-Date: August 2010
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When read, this file returns the number of the actual profile in
- range 0-4.
- This file is readonly.
- Please use binary attribute "settings" which provides this information.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/firmware_version
-Date: August 2010
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When read, this file returns the raw integer version number of the
- firmware reported by the mouse. Using the integer value eases
- further usage in other programs. To receive the real version
- number the decimal point has to be shifted 2 positions to the
- left. E.g. a returned value of 138 means 1.38
- This file is readonly.
- Please use binary attribute "info" which provides this information.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile[1-5]_buttons
-Date: August 2010
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: The mouse can store 5 profiles which can be switched by the
- press of a button. A profile is split in settings and buttons.
- profile_buttons holds information about button layout.
- When read, these files return the respective profile buttons.
- The returned data is 19 bytes in size.
- This file is readonly.
- Write control to select profile and read profile_buttons instead.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile[1-5]_settings
-Date: August 2010
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: The mouse can store 5 profiles which can be switched by the
- press of a button. A profile is split in settings and buttons.
- profile_settings holds information like resolution, sensitivity
- and light effects.
- When read, these files return the respective profile settings.
- The returned data is 13 bytes in size.
- This file is readonly.
- Write control to select profile and read profile_settings instead.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/startup_profile
-Date: August 2010
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: The integer value of this attribute ranges from 0-4.
- When read, this attribute returns the number of the profile
- that's active when the mouse is powered on.
- This file is readonly.
- Please use binary attribute "settings" which provides this information.
-Users: http://roccat.sourceforge.net
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-arvo b/Documentation/ABI/testing/sysfs-driver-hid-roccat-arvo
deleted file mode 100644
index 55e281b..0000000
--- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-arvo
+++ /dev/null
@@ -1,53 +0,0 @@
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/arvo/roccatarvo<minor>/actual_profile
-Date: Januar 2011
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: The integer value of this attribute ranges from 1-5.
- When read, this attribute returns the number of the actual
- profile which is also the profile that's active on device startup.
- When written this attribute activates the selected profile
- immediately.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/arvo/roccatarvo<minor>/button
-Date: Januar 2011
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: The keyboard can store short macros with consist of 1 button with
- several modifier keys internally.
- When written, this file lets one set the sequence for a specific
- button for a specific profile. Button and profile numbers are
- included in written data. The data has to be 24 bytes long.
- This file is writeonly.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/arvo/roccatarvo<minor>/info
-Date: Januar 2011
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When read, this file returns some info about the device like the
- installed firmware version.
- The size of the data is 8 bytes in size.
- This file is readonly.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/arvo/roccatarvo<minor>/key_mask
-Date: Januar 2011
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: The keyboard lets the user deactivate 5 certain keys like the
- windows and application keys, to protect the user from the outcome
- of accidentally pressing them.
- The integer value of this attribute has bits 0-4 set depending
- on the state of the corresponding key.
- When read, this file returns the current state of the buttons.
- When written, the given buttons are activated/deactivated
- immediately.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/arvo/roccatarvo<minor>/mode_key
-Date: Januar 2011
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: The keyboard has a condensed layout without num-lock key.
- Instead it uses a mode-key which activates a gaming mode where
- the assignment of the number block changes.
- The integer value of this attribute ranges from 0 (OFF) to 1 (ON).
- When read, this file returns the actual state of the key.
- When written, the key is activated/deactivated immediately.
-Users: http://roccat.sourceforge.net
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-isku b/Documentation/ABI/testing/sysfs-driver-hid-roccat-isku
deleted file mode 100644
index c601d0f..0000000
--- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-isku
+++ /dev/null
@@ -1,153 +0,0 @@
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/isku/roccatisku<minor>/actual_profile
-Date: June 2011
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: The integer value of this attribute ranges from 0-4.
- When read, this attribute returns the number of the actual
- profile. This value is persistent, so its equivalent to the
- profile that's active when the device is powered on next time.
- When written, this file sets the number of the startup profile
- and the device activates this profile immediately.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/isku/roccatisku<minor>/info
-Date: June 2011
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When read, this file returns general data like firmware version.
- The data is 6 bytes long.
- This file is readonly.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/isku/roccatisku<minor>/key_mask
-Date: June 2011
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When written, this file lets one deactivate certain keys like
- windows and application keys, to prevent accidental presses.
- Profile number for which this settings occur is included in
- written data. The data has to be 6 bytes long.
- Before reading this file, control has to be written to select
- which profile to read.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/isku/roccatisku<minor>/keys_capslock
-Date: June 2011
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When written, this file lets one set the function of the
- capslock key for a specific profile. Profile number is included
- in written data. The data has to be 6 bytes long.
- Before reading this file, control has to be written to select
- which profile to read.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/isku/roccatisku<minor>/keys_easyzone
-Date: June 2011
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When written, this file lets one set the function of the
- easyzone keys for a specific profile. Profile number is included
- in written data. The data has to be 65 bytes long.
- Before reading this file, control has to be written to select
- which profile to read.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/isku/roccatisku<minor>/keys_function
-Date: June 2011
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When written, this file lets one set the function of the
- function keys for a specific profile. Profile number is included
- in written data. The data has to be 41 bytes long.
- Before reading this file, control has to be written to select
- which profile to read.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/isku/roccatisku<minor>/keys_macro
-Date: June 2011
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When written, this file lets one set the function of the macro
- keys for a specific profile. Profile number is included in
- written data. The data has to be 35 bytes long.
- Before reading this file, control has to be written to select
- which profile to read.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/isku/roccatisku<minor>/keys_media
-Date: June 2011
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When written, this file lets one set the function of the media
- keys for a specific profile. Profile number is included in
- written data. The data has to be 29 bytes long.
- Before reading this file, control has to be written to select
- which profile to read.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/isku/roccatisku<minor>/keys_thumbster
-Date: June 2011
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When written, this file lets one set the function of the
- thumbster keys for a specific profile. Profile number is included
- in written data. The data has to be 23 bytes long.
- Before reading this file, control has to be written to select
- which profile to read.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/isku/roccatisku<minor>/last_set
-Date: June 2011
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When written, this file lets one set the time in secs since
- epoch in which the last configuration took place.
- The data has to be 20 bytes long.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/isku/roccatisku<minor>/light
-Date: June 2011
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When written, this file lets one set the backlight intensity for
- a specific profile. Profile number is included in written data.
- The data has to be 10 bytes long for Isku, IskuFX needs 16 bytes
- of data.
- Before reading this file, control has to be written to select
- which profile to read.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/isku/roccatisku<minor>/macro
-Date: June 2011
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When written, this file lets one store macros with max 500
- keystrokes for a specific button for a specific profile.
- Button and profile numbers are included in written data.
- The data has to be 2083 bytes long.
- Before reading this file, control has to be written to select
- which profile and key to read.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/isku/roccatisku<minor>/reset
-Date: November 2012
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When written, this file lets one reset the device.
- The data has to be 3 bytes long.
- This file is writeonly.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/isku/roccatisku<minor>/control
-Date: June 2011
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When written, this file lets one select which data from which
- profile will be read next. The data has to be 3 bytes long.
- This file is writeonly.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/isku/roccatisku<minor>/talk
-Date: June 2011
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When written, this file lets one trigger easyshift functionality
- from the host.
- The data has to be 16 bytes long.
- This file is writeonly.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/isku/roccatisku<minor>/talkfx
-Date: February 2013
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When written, this file lets one trigger temporary color schemes
- from the host.
- The data has to be 16 bytes long.
- This file is writeonly.
-Users: http://roccat.sourceforge.net
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus b/Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus
deleted file mode 100644
index 7bd776f..0000000
--- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus
+++ /dev/null
@@ -1,96 +0,0 @@
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/actual_profile
-Date: October 2010
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: The integer value of this attribute ranges from 0-4.
- When read, this attribute returns the number of the actual
- profile. This value is persistent, so its equivalent to the
- profile that's active when the mouse is powered on next time.
- When written, this file sets the number of the startup profile
- and the mouse activates this profile immediately.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/info
-Date: November 2012
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When read, this file returns general data like firmware version.
- When written, the device can be reset.
- The data is 8 bytes long.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/macro
-Date: October 2010
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: The mouse can store a macro with max 500 key/button strokes
- internally.
- When written, this file lets one set the sequence for a specific
- button for a specific profile. Button and profile numbers are
- included in written data. The data has to be 2082 bytes long.
- This file is writeonly.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile_buttons
-Date: August 2010
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: The mouse can store 5 profiles which can be switched by the
- press of a button. A profile is split in settings and buttons.
- profile_buttons holds information about button layout.
- When written, this file lets one write the respective profile
- buttons back to the mouse. The data has to be 77 bytes long.
- The mouse will reject invalid data.
- Which profile to write is determined by the profile number
- contained in the data.
- Before reading this file, control has to be written to select
- which profile to read.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile_settings
-Date: October 2010
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: The mouse can store 5 profiles which can be switched by the
- press of a button. A profile is split in settings and buttons.
- profile_settings holds information like resolution, sensitivity
- and light effects.
- When written, this file lets one write the respective profile
- settings back to the mouse. The data has to be 43 bytes long.
- The mouse will reject invalid data.
- Which profile to write is determined by the profile number
- contained in the data.
- Before reading this file, control has to be written to select
- which profile to read.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/sensor
-Date: October 2010
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: The mouse has a tracking- and a distance-control-unit. These
- can be activated/deactivated and the lift-off distance can be
- set. The data has to be 6 bytes long.
- This file is writeonly.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/talk
-Date: May 2011
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: Used to active some easy* functions of the mouse from outside.
- The data has to be 16 bytes long.
- This file is writeonly.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/tcu
-Date: October 2010
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When written a calibration process for the tracking control unit
- can be initiated/cancelled. Also lets one read/write sensor
- registers.
- The data has to be 4 bytes long.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/tcu_image
-Date: October 2010
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When read the mouse returns a 30x30 pixel image of the
- sampled underground. This works only in the course of a
- calibration process initiated with tcu.
- The returned data is 1028 bytes in size.
- This file is readonly.
-Users: http://roccat.sourceforge.net
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-konepure b/Documentation/ABI/testing/sysfs-driver-hid-roccat-konepure
deleted file mode 100644
index 41a9b7f..0000000
--- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-konepure
+++ /dev/null
@@ -1,105 +0,0 @@
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/konepure/roccatkonepure<minor>/actual_profile
-Date: December 2012
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: The mouse can store 5 profiles which can be switched by the
- press of a button. actual_profile holds number of actual profile.
- This value is persistent, so its value determines the profile
- that's active when the mouse is powered on next time.
- When written, the mouse activates the set profile immediately.
- The data has to be 3 bytes long.
- The mouse will reject invalid data.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/konepure/roccatkonepure<minor>/control
-Date: December 2012
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When written, this file lets one select which data from which
- profile will be read next. The data has to be 3 bytes long.
- This file is writeonly.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/konepure/roccatkonepure<minor>/info
-Date: December 2012
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When read, this file returns general data like firmware version.
- When written, the device can be reset.
- The data is 6 bytes long.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/konepure/roccatkonepure<minor>/macro
-Date: December 2012
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: The mouse can store a macro with max 500 key/button strokes
- internally.
- When written, this file lets one set the sequence for a specific
- button for a specific profile. Button and profile numbers are
- included in written data. The data has to be 2082 bytes long.
- This file is writeonly.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/konepure/roccatkonepure<minor>/profile_buttons
-Date: December 2012
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: The mouse can store 5 profiles which can be switched by the
- press of a button. A profile is split in settings and buttons.
- profile_buttons holds information about button layout.
- When written, this file lets one write the respective profile
- buttons back to the mouse. The data has to be 59 bytes long.
- The mouse will reject invalid data.
- Which profile to write is determined by the profile number
- contained in the data.
- Before reading this file, control has to be written to select
- which profile to read.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/konepure/roccatkonepure<minor>/profile_settings
-Date: December 2012
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: The mouse can store 5 profiles which can be switched by the
- press of a button. A profile is split in settings and buttons.
- profile_settings holds information like resolution, sensitivity
- and light effects.
- When written, this file lets one write the respective profile
- settings back to the mouse. The data has to be 31 bytes long.
- The mouse will reject invalid data.
- Which profile to write is determined by the profile number
- contained in the data.
- Before reading this file, control has to be written to select
- which profile to read.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/konepure/roccatkonepure<minor>/sensor
-Date: December 2012
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: The mouse has a tracking- and a distance-control-unit. These
- can be activated/deactivated and the lift-off distance can be
- set. The data has to be 6 bytes long.
- This file is writeonly.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/konepure/roccatkonepure<minor>/talk
-Date: December 2012
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: Used to active some easy* functions of the mouse from outside.
- The data has to be 16 bytes long.
- This file is writeonly.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/konepure/roccatkonepure<minor>/tcu
-Date: December 2012
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When written a calibration process for the tracking control unit
- can be initiated/cancelled. Also lets one read/write sensor
- registers.
- The data has to be 4 bytes long.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/konepure/roccatkonepure<minor>/tcu_image
-Date: December 2012
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When read the mouse returns a 30x30 pixel image of the
- sampled underground. This works only in the course of a
- calibration process initiated with tcu.
- The returned data is 1028 bytes in size.
- This file is readonly.
-Users: http://roccat.sourceforge.net
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-kovaplus b/Documentation/ABI/testing/sysfs-driver-hid-roccat-kovaplus
deleted file mode 100644
index a10404f..0000000
--- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-kovaplus
+++ /dev/null
@@ -1,49 +0,0 @@
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_profile
-Date: January 2011
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: The integer value of this attribute ranges from 0-4.
- When read, this attribute returns the number of the active
- profile.
- When written, the mouse activates this profile immediately.
- The profile that's active when powered down is the same that's
- active when the mouse is powered on.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/info
-Date: November 2012
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When read, this file returns general data like firmware version.
- When written, the device can be reset.
- The data is 6 bytes long.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile_buttons
-Date: January 2011
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: The mouse can store 5 profiles which can be switched by the
- press of a button. A profile is split in settings and buttons.
- profile_buttons holds information about button layout.
- When written, this file lets one write the respective profile
- buttons back to the mouse. The data has to be 23 bytes long.
- The mouse will reject invalid data.
- Which profile to write is determined by the profile number
- contained in the data.
- Before reading this file, control has to be written to select
- which profile to read.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile_settings
-Date: January 2011
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: The mouse can store 5 profiles which can be switched by the
- press of a button. A profile is split in settings and buttons.
- profile_settings holds information like resolution, sensitivity
- and light effects.
- When written, this file lets one write the respective profile
- settings back to the mouse. The data has to be 16 bytes long.
- The mouse will reject invalid data.
- Which profile to write is determined by the profile number
- contained in the data.
- Before reading this file, control has to be written to select
- which profile to read.
-Users: http://roccat.sourceforge.net
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-lua b/Documentation/ABI/testing/sysfs-driver-hid-roccat-lua
deleted file mode 100644
index 31c6c4c..0000000
--- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-lua
+++ /dev/null
@@ -1,7 +0,0 @@
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/control
-Date: October 2012
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When written, cpi, button and light settings can be configured.
- When read, actual cpi setting and sensor data are returned.
- The data has to be 8 bytes long.
-Users: http://roccat.sourceforge.net
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra b/Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra
deleted file mode 100644
index 9fa9de3..0000000
--- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra
+++ /dev/null
@@ -1,49 +0,0 @@
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/info
-Date: November 2012
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When read, this file returns general data like firmware version.
- When written, the device can be reset.
- The data is 6 bytes long.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile_settings
-Date: August 2010
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: The mouse can store 5 profiles which can be switched by the
- press of a button. A profile is split in settings and buttons.
- profile_settings holds information like resolution, sensitivity
- and light effects.
- When written, this file lets one write the respective profile
- settings back to the mouse. The data has to be 13 bytes long.
- The mouse will reject invalid data.
- Which profile to write is determined by the profile number
- contained in the data.
- Before reading this file, control has to be written to select
- which profile to read.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile_buttons
-Date: August 2010
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: The mouse can store 5 profiles which can be switched by the
- press of a button. A profile is split in settings and buttons.
- profile_buttons holds information about button layout.
- When written, this file lets one write the respective profile
- buttons back to the mouse. The data has to be 19 bytes long.
- The mouse will reject invalid data.
- Which profile to write is determined by the profile number
- contained in the data.
- Before reading this file, control has to be written to select
- which profile to read.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/settings
-Date: August 2010
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When read, this file returns the settings stored in the mouse.
- The size of the data is 3 bytes and holds information on the
- startup_profile.
- When written, this file lets write settings back to the mouse.
- The data has to be 3 bytes long. The mouse will reject invalid
- data.
-Users: http://roccat.sourceforge.net
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-ryos b/Documentation/ABI/testing/sysfs-driver-hid-roccat-ryos
deleted file mode 100644
index 1d6a8cf..0000000
--- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-ryos
+++ /dev/null
@@ -1,178 +0,0 @@
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/ryos/roccatryos<minor>/control
-Date: October 2013
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When written, this file lets one select which data from which
- profile will be read next. The data has to be 3 bytes long.
- This file is writeonly.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/ryos/roccatryos<minor>/profile
-Date: October 2013
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: The mouse can store 5 profiles which can be switched by the
- press of a button. profile holds index of actual profile.
- This value is persistent, so its value determines the profile
- that's active when the device is powered on next time.
- When written, the device activates the set profile immediately.
- The data has to be 3 bytes long.
- The device will reject invalid data.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/ryos/roccatryos<minor>/keys_primary
-Date: October 2013
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When written, this file lets one set the default of all keys for
- a specific profile. Profile index is included in written data.
- The data has to be 125 bytes long.
- Before reading this file, control has to be written to select
- which profile to read.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/ryos/roccatryos<minor>/keys_function
-Date: October 2013
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When written, this file lets one set the function of the
- function keys for a specific profile. Profile index is included
- in written data. The data has to be 95 bytes long.
- Before reading this file, control has to be written to select
- which profile to read.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/ryos/roccatryos<minor>/keys_macro
-Date: October 2013
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When written, this file lets one set the function of the macro
- keys for a specific profile. Profile index is included in
- written data. The data has to be 35 bytes long.
- Before reading this file, control has to be written to select
- which profile to read.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/ryos/roccatryos<minor>/keys_thumbster
-Date: October 2013
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When written, this file lets one set the function of the
- thumbster keys for a specific profile. Profile index is included
- in written data. The data has to be 23 bytes long.
- Before reading this file, control has to be written to select
- which profile to read.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/ryos/roccatryos<minor>/keys_extra
-Date: October 2013
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When written, this file lets one set the function of the
- capslock and function keys for a specific profile. Profile index
- is included in written data. The data has to be 8 bytes long.
- Before reading this file, control has to be written to select
- which profile to read.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/ryos/roccatryos<minor>/keys_easyzone
-Date: October 2013
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When written, this file lets one set the function of the
- easyzone keys for a specific profile. Profile index is included
- in written data. The data has to be 294 bytes long.
- Before reading this file, control has to be written to select
- which profile to read.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/ryos/roccatryos<minor>/key_mask
-Date: October 2013
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When written, this file lets one deactivate certain keys like
- windows and application keys, to prevent accidental presses.
- Profile index for which this settings occur is included in
- written data. The data has to be 6 bytes long.
- Before reading this file, control has to be written to select
- which profile to read.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/ryos/roccatryos<minor>/light
-Date: October 2013
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When written, this file lets one set the backlight intensity for
- a specific profile. Profile index is included in written data.
- This attribute is only valid for the glow and pro variant.
- The data has to be 16 bytes long.
- Before reading this file, control has to be written to select
- which profile to read.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/ryos/roccatryos<minor>/macro
-Date: October 2013
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When written, this file lets one store macros with max 480
- keystrokes for a specific button for a specific profile.
- Button and profile indexes are included in written data.
- The data has to be 2002 bytes long.
- Before reading this file, control has to be written to select
- which profile and key to read.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/ryos/roccatryos<minor>/info
-Date: October 2013
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When read, this file returns general data like firmware version.
- The data is 8 bytes long.
- This file is readonly.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/ryos/roccatryos<minor>/reset
-Date: October 2013
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When written, this file lets one reset the device.
- The data has to be 3 bytes long.
- This file is writeonly.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/ryos/roccatryos<minor>/talk
-Date: October 2013
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When written, this file lets one trigger easyshift functionality
- from the host.
- The data has to be 16 bytes long.
- This file is writeonly.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/ryos/roccatryos<minor>/light_control
-Date: October 2013
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When written, this file lets one switch between stored and custom
- light settings.
- This attribute is only valid for the pro variant.
- The data has to be 8 bytes long.
- This file is writeonly.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/ryos/roccatryos<minor>/stored_lights
-Date: October 2013
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When written, this file lets one set per-key lighting for different
- layers.
- This attribute is only valid for the pro variant.
- The data has to be 1382 bytes long.
- Before reading this file, control has to be written to select
- which profile to read.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/ryos/roccatryos<minor>/custom_lights
-Date: October 2013
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When written, this file lets one set the actual per-key lighting.
- This attribute is only valid for the pro variant.
- The data has to be 20 bytes long.
- This file is writeonly.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/ryos/roccatryos<minor>/light_macro
-Date: October 2013
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When written, this file lets one set a light macro that is looped
- whenever the device gets in dimness mode.
- This attribute is only valid for the pro variant.
- The data has to be 2002 bytes long.
- Before reading this file, control has to be written to select
- which profile to read.
-Users: http://roccat.sourceforge.net
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-savu b/Documentation/ABI/testing/sysfs-driver-hid-roccat-savu
deleted file mode 100644
index f1e02a9..0000000
--- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-savu
+++ /dev/null
@@ -1,76 +0,0 @@
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/savu/roccatsavu<minor>/buttons
-Date: Mai 2012
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: The mouse can store 5 profiles which can be switched by the
- press of a button. A profile is split into general settings and
- button settings. buttons holds informations about button layout.
- When written, this file lets one write the respective profile
- buttons to the mouse. The data has to be 47 bytes long.
- The mouse will reject invalid data.
- Which profile to write is determined by the profile number
- contained in the data.
- Before reading this file, control has to be written to select
- which profile to read.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/savu/roccatsavu<minor>/control
-Date: Mai 2012
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When written, this file lets one select which data from which
- profile will be read next. The data has to be 3 bytes long.
- This file is writeonly.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/savu/roccatsavu<minor>/general
-Date: Mai 2012
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: The mouse can store 5 profiles which can be switched by the
- press of a button. A profile is split into general settings and
- button settings. profile holds informations like resolution, sensitivity
- and light effects.
- When written, this file lets one write the respective profile
- settings back to the mouse. The data has to be 43 bytes long.
- The mouse will reject invalid data.
- Which profile to write is determined by the profile number
- contained in the data.
- This file is writeonly.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/savu/roccatsavu<minor>/info
-Date: Mai 2012
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When read, this file returns general data like firmware version.
- When written, the device can be reset.
- The data is 8 bytes long.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/savu/roccatsavu<minor>/macro
-Date: Mai 2012
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: When written, this file lets one store macros with max 500
- keystrokes for a specific button for a specific profile.
- Button and profile numbers are included in written data.
- The data has to be 2083 bytes long.
- Before reading this file, control has to be written to select
- which profile and key to read.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/savu/roccatsavu<minor>/profile
-Date: Mai 2012
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: The mouse can store 5 profiles which can be switched by the
- press of a button. profile holds number of actual profile.
- This value is persistent, so its value determines the profile
- that's active when the mouse is powered on next time.
- When written, the mouse activates the set profile immediately.
- The data has to be 3 bytes long.
- The mouse will reject invalid data.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/savu/roccatsavu<minor>/sensor
-Date: July 2012
-Contact: Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
-Description: The mouse has a Avago ADNS-3090 sensor.
- This file allows reading and writing of the mouse sensors registers.
- The data has to be 4 bytes long.
-Users: http://roccat.sourceforge.net
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 152b006..57802a3 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -651,11 +651,11 @@ config HID_PRIMAX
HID standard.
config HID_ROCCAT
- tristate "Roccat device support"
+ tristate "Roccat Kone support"
depends on USB_HID
---help---
- Support for Roccat devices.
- Say Y here if you have a Roccat mouse or keyboard and want
+ Support for Roccat Kone mouse.
+ Say Y here if you have a Roccat Kone mouse and want
support for its special functionalities.
config HID_SAITEK
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 6f19958..caf4872 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -73,10 +73,7 @@ hid-picolcd-$(CONFIG_DEBUG_FS) += hid-picolcd_debugfs.o
obj-$(CONFIG_HID_PLANTRONICS) += hid-plantronics.o
obj-$(CONFIG_HID_PRIMAX) += hid-primax.o
-obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o hid-roccat-common.o \
- hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \
- hid-roccat-koneplus.o hid-roccat-konepure.o hid-roccat-kovaplus.o \
- hid-roccat-lua.o hid-roccat-pyra.o hid-roccat-ryos.o hid-roccat-savu.o
+obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o hid-roccat-common.o hid-roccat-kone.o
obj-$(CONFIG_HID_RMI) += hid-rmi.o
obj-$(CONFIG_HID_SAITEK) += hid-saitek.o
obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 56ce8c2..e7f400f 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1908,22 +1908,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, HID_ANY_ID) },
{ HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) },
#if IS_ENABLED(CONFIG_HID_ROCCAT)
- { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) },
- { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) },
- { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKUFX) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) },
- { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) },
- { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPURE) },
- { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPURE_OPTICAL) },
- { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEXTD) },
- { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) },
- { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_LUA) },
- { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) },
- { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS) },
- { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_RYOS_MK) },
- { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_RYOS_MK_GLOW) },
- { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_RYOS_MK_PRO) },
- { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_SAVU) },
#endif
#if IS_ENABLED(CONFIG_HID_SAITEK)
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 9c47867..5c9a7bb 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -784,22 +784,7 @@
#define USB_DEVICE_ID_REALTEK_READER 0x0152
#define USB_VENDOR_ID_ROCCAT 0x1e7d
-#define USB_DEVICE_ID_ROCCAT_ARVO 0x30d4
-#define USB_DEVICE_ID_ROCCAT_ISKU 0x319c
-#define USB_DEVICE_ID_ROCCAT_ISKUFX 0x3264
#define USB_DEVICE_ID_ROCCAT_KONE 0x2ced
-#define USB_DEVICE_ID_ROCCAT_KONEPLUS 0x2d51
-#define USB_DEVICE_ID_ROCCAT_KONEPURE 0x2dbe
-#define USB_DEVICE_ID_ROCCAT_KONEPURE_OPTICAL 0x2db4
-#define USB_DEVICE_ID_ROCCAT_KONEXTD 0x2e22
-#define USB_DEVICE_ID_ROCCAT_KOVAPLUS 0x2d50
-#define USB_DEVICE_ID_ROCCAT_LUA 0x2c2e
-#define USB_DEVICE_ID_ROCCAT_PYRA_WIRED 0x2c24
-#define USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS 0x2cf6
-#define USB_DEVICE_ID_ROCCAT_RYOS_MK 0x3138
-#define USB_DEVICE_ID_ROCCAT_RYOS_MK_GLOW 0x31ce
-#define USB_DEVICE_ID_ROCCAT_RYOS_MK_PRO 0x3232
-#define USB_DEVICE_ID_ROCCAT_SAVU 0x2d5a
#define USB_VENDOR_ID_SAITEK 0x06a3
#define USB_DEVICE_ID_SAITEK_RUMBLEPAD 0xff17
diff --git a/drivers/hid/hid-roccat-arvo.c b/drivers/hid/hid-roccat-arvo.c
deleted file mode 100644
index 1948208..0000000
--- a/drivers/hid/hid-roccat-arvo.c
+++ /dev/null
@@ -1,460 +0,0 @@
-/*
- * Roccat Arvo driver for Linux
- *
- * Copyright (c) 2011 Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-/*
- * Roccat Arvo is a gamer keyboard with 5 macro keys that can be configured in
- * 5 profiles.
- */
-
-#include <linux/device.h>
-#include <linux/input.h>
-#include <linux/hid.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/hid-roccat.h>
-#include "hid-ids.h"
-#include "hid-roccat-common.h"
-#include "hid-roccat-arvo.h"
-
-static struct class *arvo_class;
-
-static ssize_t arvo_sysfs_show_mode_key(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct arvo_device *arvo =
- hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
- struct usb_device *usb_dev =
- interface_to_usbdev(to_usb_interface(dev->parent->parent));
- struct arvo_mode_key temp_buf;
- int retval;
-
- mutex_lock(&arvo->arvo_lock);
- retval = roccat_common2_receive(usb_dev, ARVO_COMMAND_MODE_KEY,
- &temp_buf, sizeof(struct arvo_mode_key));
- mutex_unlock(&arvo->arvo_lock);
- if (retval)
- return retval;
-
- return snprintf(buf, PAGE_SIZE, "%d\n", temp_buf.state);
-}
-
-static ssize_t arvo_sysfs_set_mode_key(struct device *dev,
- struct device_attribute *attr, char const *buf, size_t size)
-{
- struct arvo_device *arvo =
- hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
- struct usb_device *usb_dev =
- interface_to_usbdev(to_usb_interface(dev->parent->parent));
- struct arvo_mode_key temp_buf;
- unsigned long state;
- int retval;
-
- retval = kstrtoul(buf, 10, &state);
- if (retval)
- return retval;
-
- temp_buf.command = ARVO_COMMAND_MODE_KEY;
- temp_buf.state = state;
-
- mutex_lock(&arvo->arvo_lock);
- retval = roccat_common2_send(usb_dev, ARVO_COMMAND_MODE_KEY,
- &temp_buf, sizeof(struct arvo_mode_key));
- mutex_unlock(&arvo->arvo_lock);
- if (retval)
- return retval;
-
- return size;
-}
-static DEVICE_ATTR(mode_key, 0660,
- arvo_sysfs_show_mode_key, arvo_sysfs_set_mode_key);
-
-static ssize_t arvo_sysfs_show_key_mask(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct arvo_device *arvo =
- hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
- struct usb_device *usb_dev =
- interface_to_usbdev(to_usb_interface(dev->parent->parent));
- struct arvo_key_mask temp_buf;
- int retval;
-
- mutex_lock(&arvo->arvo_lock);
- retval = roccat_common2_receive(usb_dev, ARVO_COMMAND_KEY_MASK,
- &temp_buf, sizeof(struct arvo_key_mask));
- mutex_unlock(&arvo->arvo_lock);
- if (retval)
- return retval;
-
- return snprintf(buf, PAGE_SIZE, "%d\n", temp_buf.key_mask);
-}
-
-static ssize_t arvo_sysfs_set_key_mask(struct device *dev,
- struct device_attribute *attr, char const *buf, size_t size)
-{
- struct arvo_device *arvo =
- hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
- struct usb_device *usb_dev =
- interface_to_usbdev(to_usb_interface(dev->parent->parent));
- struct arvo_key_mask temp_buf;
- unsigned long key_mask;
- int retval;
-
- retval = kstrtoul(buf, 10, &key_mask);
- if (retval)
- return retval;
-
- temp_buf.command = ARVO_COMMAND_KEY_MASK;
- temp_buf.key_mask = key_mask;
-
- mutex_lock(&arvo->arvo_lock);
- retval = roccat_common2_send(usb_dev, ARVO_COMMAND_KEY_MASK,
- &temp_buf, sizeof(struct arvo_key_mask));
- mutex_unlock(&arvo->arvo_lock);
- if (retval)
- return retval;
-
- return size;
-}
-static DEVICE_ATTR(key_mask, 0660,
- arvo_sysfs_show_key_mask, arvo_sysfs_set_key_mask);
-
-/* retval is 1-5 on success, < 0 on error */
-static int arvo_get_actual_profile(struct usb_device *usb_dev)
-{
- struct arvo_actual_profile temp_buf;
- int retval;
-
- retval = roccat_common2_receive(usb_dev, ARVO_COMMAND_ACTUAL_PROFILE,
- &temp_buf, sizeof(struct arvo_actual_profile));
-
- if (retval)
- return retval;
-
- return temp_buf.actual_profile;
-}
-
-static ssize_t arvo_sysfs_show_actual_profile(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct arvo_device *arvo =
- hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
-
- return snprintf(buf, PAGE_SIZE, "%d\n", arvo->actual_profile);
-}
-
-static ssize_t arvo_sysfs_set_actual_profile(struct device *dev,
- struct device_attribute *attr, char const *buf, size_t size)
-{
- struct arvo_device *arvo =
- hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
- struct usb_device *usb_dev =
- interface_to_usbdev(to_usb_interface(dev->parent->parent));
- struct arvo_actual_profile temp_buf;
- unsigned long profile;
- int retval;
-
- retval = kstrtoul(buf, 10, &profile);
- if (retval)
- return retval;
-
- if (profile < 1 || profile > 5)
- return -EINVAL;
-
- temp_buf.command = ARVO_COMMAND_ACTUAL_PROFILE;
- temp_buf.actual_profile = profile;
-
- mutex_lock(&arvo->arvo_lock);
- retval = roccat_common2_send(usb_dev, ARVO_COMMAND_ACTUAL_PROFILE,
- &temp_buf, sizeof(struct arvo_actual_profile));
- if (!retval) {
- arvo->actual_profile = profile;
- retval = size;
- }
- mutex_unlock(&arvo->arvo_lock);
- return retval;
-}
-static DEVICE_ATTR(actual_profile, 0660,
- arvo_sysfs_show_actual_profile,
- arvo_sysfs_set_actual_profile);
-
-static ssize_t arvo_sysfs_write(struct file *fp,
- struct kobject *kobj, void const *buf,
- loff_t off, size_t count, size_t real_size, uint command)
-{
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
- struct arvo_device *arvo = hid_get_drvdata(dev_get_drvdata(dev));
- struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
- int retval;
-
- if (off != 0 || count != real_size)
- return -EINVAL;
-
- mutex_lock(&arvo->arvo_lock);
- retval = roccat_common2_send(usb_dev, command, buf, real_size);
- mutex_unlock(&arvo->arvo_lock);
-
- return (retval ? retval : real_size);
-}
-
-static ssize_t arvo_sysfs_read(struct file *fp,
- struct kobject *kobj, void *buf, loff_t off,
- size_t count, size_t real_size, uint command)
-{
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
- struct arvo_device *arvo = hid_get_drvdata(dev_get_drvdata(dev));
- struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
- int retval;
-
- if (off >= real_size)
- return 0;
-
- if (off != 0 || count != real_size)
- return -EINVAL;
-
- mutex_lock(&arvo->arvo_lock);
- retval = roccat_common2_receive(usb_dev, command, buf, real_size);
- mutex_unlock(&arvo->arvo_lock);
-
- return (retval ? retval : real_size);
-}
-
-static ssize_t arvo_sysfs_write_button(struct file *fp,
- struct kobject *kobj, struct bin_attribute *attr, char *buf,
- loff_t off, size_t count)
-{
- return arvo_sysfs_write(fp, kobj, buf, off, count,
- sizeof(struct arvo_button), ARVO_COMMAND_BUTTON);
-}
-static BIN_ATTR(button, 0220, NULL, arvo_sysfs_write_button,
- sizeof(struct arvo_button));
-
-static ssize_t arvo_sysfs_read_info(struct file *fp,
- struct kobject *kobj, struct bin_attribute *attr, char *buf,
- loff_t off, size_t count)
-{
- return arvo_sysfs_read(fp, kobj, buf, off, count,
- sizeof(struct arvo_info), ARVO_COMMAND_INFO);
-}
-static BIN_ATTR(info, 0440, arvo_sysfs_read_info, NULL,
- sizeof(struct arvo_info));
-
-static struct attribute *arvo_attrs[] = {
- &dev_attr_mode_key.attr,
- &dev_attr_key_mask.attr,
- &dev_attr_actual_profile.attr,
- NULL,
-};
-
-static struct bin_attribute *arvo_bin_attributes[] = {
- &bin_attr_button,
- &bin_attr_info,
- NULL,
-};
-
-static const struct attribute_group arvo_group = {
- .attrs = arvo_attrs,
- .bin_attrs = arvo_bin_attributes,
-};
-
-static const struct attribute_group *arvo_groups[] = {
- &arvo_group,
- NULL,
-};
-
-static int arvo_init_arvo_device_struct(struct usb_device *usb_dev,
- struct arvo_device *arvo)
-{
- int retval;
-
- mutex_init(&arvo->arvo_lock);
-
- retval = arvo_get_actual_profile(usb_dev);
- if (retval < 0)
- return retval;
- arvo->actual_profile = retval;
-
- return 0;
-}
-
-static int arvo_init_specials(struct hid_device *hdev)
-{
- struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
- struct usb_device *usb_dev = interface_to_usbdev(intf);
- struct arvo_device *arvo;
- int retval;
-
- if (intf->cur_altsetting->desc.bInterfaceProtocol
- == USB_INTERFACE_PROTOCOL_KEYBOARD) {
- hid_set_drvdata(hdev, NULL);
- return 0;
- }
-
- arvo = kzalloc(sizeof(*arvo), GFP_KERNEL);
- if (!arvo) {
- hid_err(hdev, "can't alloc device descriptor\n");
- return -ENOMEM;
- }
- hid_set_drvdata(hdev, arvo);
-
- retval = arvo_init_arvo_device_struct(usb_dev, arvo);
- if (retval) {
- hid_err(hdev, "couldn't init struct arvo_device\n");
- goto exit_free;
- }
-
- retval = roccat_connect(arvo_class, hdev,
- sizeof(struct arvo_roccat_report));
- if (retval < 0) {
- hid_err(hdev, "couldn't init char dev\n");
- } else {
- arvo->chrdev_minor = retval;
- arvo->roccat_claimed = 1;
- }
-
- return 0;
-exit_free:
- kfree(arvo);
- return retval;
-}
-
-static void arvo_remove_specials(struct hid_device *hdev)
-{
- struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
- struct arvo_device *arvo;
-
- if (intf->cur_altsetting->desc.bInterfaceProtocol
- == USB_INTERFACE_PROTOCOL_KEYBOARD)
- return;
-
- arvo = hid_get_drvdata(hdev);
- if (arvo->roccat_claimed)
- roccat_disconnect(arvo->chrdev_minor);
- kfree(arvo);
-}
-
-static int arvo_probe(struct hid_device *hdev,
- const struct hid_device_id *id)
-{
- int retval;
-
- retval = hid_parse(hdev);
- if (retval) {
- hid_err(hdev, "parse failed\n");
- goto exit;
- }
-
- retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
- if (retval) {
- hid_err(hdev, "hw start failed\n");
- goto exit;
- }
-
- retval = arvo_init_specials(hdev);
- if (retval) {
- hid_err(hdev, "couldn't install keyboard\n");
- goto exit_stop;
- }
-
- return 0;
-
-exit_stop:
- hid_hw_stop(hdev);
-exit:
- return retval;
-}
-
-static void arvo_remove(struct hid_device *hdev)
-{
- arvo_remove_specials(hdev);
- hid_hw_stop(hdev);
-}
-
-static void arvo_report_to_chrdev(struct arvo_device const *arvo,
- u8 const *data)
-{
- struct arvo_special_report const *special_report;
- struct arvo_roccat_report roccat_report;
-
- special_report = (struct arvo_special_report const *)data;
-
- roccat_report.profile = arvo->actual_profile;
- roccat_report.button = special_report->event &
- ARVO_SPECIAL_REPORT_EVENT_MASK_BUTTON;
- if ((special_report->event & ARVO_SPECIAL_REPORT_EVENT_MASK_ACTION) ==
- ARVO_SPECIAL_REPORT_EVENT_ACTION_PRESS)
- roccat_report.action = ARVO_ROCCAT_REPORT_ACTION_PRESS;
- else
- roccat_report.action = ARVO_ROCCAT_REPORT_ACTION_RELEASE;
-
- roccat_report_event(arvo->chrdev_minor,
- (uint8_t const *)&roccat_report);
-}
-
-static int arvo_raw_event(struct hid_device *hdev,
- struct hid_report *report, u8 *data, int size)
-{
- struct arvo_device *arvo = hid_get_drvdata(hdev);
-
- if (size != 3)
- return 0;
-
- if (arvo && arvo->roccat_claimed)
- arvo_report_to_chrdev(arvo, data);
-
- return 0;
-}
-
-static const struct hid_device_id arvo_devices[] = {
- { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) },
- { }
-};
-
-MODULE_DEVICE_TABLE(hid, arvo_devices);
-
-static struct hid_driver arvo_driver = {
- .name = "arvo",
- .id_table = arvo_devices,
- .probe = arvo_probe,
- .remove = arvo_remove,
- .raw_event = arvo_raw_event
-};
-
-static int __init arvo_init(void)
-{
- int retval;
-
- arvo_class = class_create(THIS_MODULE, "arvo");
- if (IS_ERR(arvo_class))
- return PTR_ERR(arvo_class);
- arvo_class->dev_groups = arvo_groups;
-
- retval = hid_register_driver(&arvo_driver);
- if (retval)
- class_destroy(arvo_class);
- return retval;
-}
-
-static void __exit arvo_exit(void)
-{
- hid_unregister_driver(&arvo_driver);
- class_destroy(arvo_class);
-}
-
-module_init(arvo_init);
-module_exit(arvo_exit);
-
-MODULE_AUTHOR("Stefan Achatz");
-MODULE_DESCRIPTION("USB Roccat Arvo driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/hid/hid-roccat-arvo.h b/drivers/hid/hid-roccat-arvo.h
deleted file mode 100644
index ce8415e..0000000
--- a/drivers/hid/hid-roccat-arvo.h
+++ /dev/null
@@ -1,85 +0,0 @@
-#ifndef __HID_ROCCAT_ARVO_H
-#define __HID_ROCCAT_ARVO_H
-
-/*
- * Copyright (c) 2011 Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-#include <linux/types.h>
-
-struct arvo_mode_key { /* 2 bytes */
- uint8_t command; /* ARVO_COMMAND_MODE_KEY */
- uint8_t state;
-} __packed;
-
-struct arvo_button {
- uint8_t unknown[24];
-} __packed;
-
-struct arvo_info {
- uint8_t unknown[8];
-} __packed;
-
-struct arvo_key_mask { /* 2 bytes */
- uint8_t command; /* ARVO_COMMAND_KEY_MASK */
- uint8_t key_mask;
-} __packed;
-
-/* selected profile is persistent */
-struct arvo_actual_profile { /* 2 bytes */
- uint8_t command; /* ARVO_COMMAND_ACTUAL_PROFILE */
- uint8_t actual_profile;
-} __packed;
-
-enum arvo_commands {
- ARVO_COMMAND_MODE_KEY = 0x3,
- ARVO_COMMAND_BUTTON = 0x4,
- ARVO_COMMAND_INFO = 0x5,
- ARVO_COMMAND_KEY_MASK = 0x6,
- ARVO_COMMAND_ACTUAL_PROFILE = 0x7,
-};
-
-struct arvo_special_report {
- uint8_t unknown1; /* always 0x01 */
- uint8_t event;
- uint8_t unknown2; /* always 0x70 */
-} __packed;
-
-enum arvo_special_report_events {
- ARVO_SPECIAL_REPORT_EVENT_ACTION_PRESS = 0x10,
- ARVO_SPECIAL_REPORT_EVENT_ACTION_RELEASE = 0x0,
-};
-
-enum arvo_special_report_event_masks {
- ARVO_SPECIAL_REPORT_EVENT_MASK_ACTION = 0xf0,
- ARVO_SPECIAL_REPORT_EVENT_MASK_BUTTON = 0x0f,
-};
-
-struct arvo_roccat_report {
- uint8_t profile;
- uint8_t button;
- uint8_t action;
-} __packed;
-
-enum arvo_roccat_report_action {
- ARVO_ROCCAT_REPORT_ACTION_RELEASE = 0,
- ARVO_ROCCAT_REPORT_ACTION_PRESS = 1,
-};
-
-struct arvo_device {
- int roccat_claimed;
- int chrdev_minor;
-
- struct mutex arvo_lock;
-
- int actual_profile;
-};
-
-#endif
diff --git a/drivers/hid/hid-roccat-isku.c b/drivers/hid/hid-roccat-isku.c
deleted file mode 100644
index bc62ed9..0000000
--- a/drivers/hid/hid-roccat-isku.c
+++ /dev/null
@@ -1,462 +0,0 @@
-/*
- * Roccat Isku driver for Linux
- *
- * Copyright (c) 2011 Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-/*
- * Roccat Isku is a gamer keyboard with macro keys that can be configured in
- * 5 profiles.
- */
-
-#include <linux/device.h>
-#include <linux/input.h>
-#include <linux/hid.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/hid-roccat.h>
-#include "hid-ids.h"
-#include "hid-roccat-common.h"
-#include "hid-roccat-isku.h"
-
-static struct class *isku_class;
-
-static void isku_profile_activated(struct isku_device *isku, uint new_profile)
-{
- isku->actual_profile = new_profile;
-}
-
-static int isku_receive(struct usb_device *usb_dev, uint command,
- void *buf, uint size)
-{
- return roccat_common2_receive(usb_dev, command, buf, size);
-}
-
-static int isku_get_actual_profile(struct usb_device *usb_dev)
-{
- struct isku_actual_profile buf;
- int retval;
-
- retval = isku_receive(usb_dev, ISKU_COMMAND_ACTUAL_PROFILE,
- &buf, sizeof(struct isku_actual_profile));
- return retval ? retval : buf.actual_profile;
-}
-
-static int isku_set_actual_profile(struct usb_device *usb_dev, int new_profile)
-{
- struct isku_actual_profile buf;
-
- buf.command = ISKU_COMMAND_ACTUAL_PROFILE;
- buf.size = sizeof(struct isku_actual_profile);
- buf.actual_profile = new_profile;
- return roccat_common2_send_with_status(usb_dev,
- ISKU_COMMAND_ACTUAL_PROFILE, &buf,
- sizeof(struct isku_actual_profile));
-}
-
-static ssize_t isku_sysfs_show_actual_profile(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct isku_device *isku =
- hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
- return snprintf(buf, PAGE_SIZE, "%d\n", isku->actual_profile);
-}
-
-static ssize_t isku_sysfs_set_actual_profile(struct device *dev,
- struct device_attribute *attr, char const *buf, size_t size)
-{
- struct isku_device *isku;
- struct usb_device *usb_dev;
- unsigned long profile;
- int retval;
- struct isku_roccat_report roccat_report;
-
- dev = dev->parent->parent;
- isku = hid_get_drvdata(dev_get_drvdata(dev));
- usb_dev = interface_to_usbdev(to_usb_interface(dev));
-
- retval = kstrtoul(buf, 10, &profile);
- if (retval)
- return retval;
-
- if (profile > 4)
- return -EINVAL;
-
- mutex_lock(&isku->isku_lock);
-
- retval = isku_set_actual_profile(usb_dev, profile);
- if (retval) {
- mutex_unlock(&isku->isku_lock);
- return retval;
- }
-
- isku_profile_activated(isku, profile);
-
- roccat_report.event = ISKU_REPORT_BUTTON_EVENT_PROFILE;
- roccat_report.data1 = profile + 1;
- roccat_report.data2 = 0;
- roccat_report.profile = profile + 1;
- roccat_report_event(isku->chrdev_minor, (uint8_t const *)&roccat_report);
-
- mutex_unlock(&isku->isku_lock);
-
- return size;
-}
-static DEVICE_ATTR(actual_profile, 0660, isku_sysfs_show_actual_profile,
- isku_sysfs_set_actual_profile);
-
-static struct attribute *isku_attrs[] = {
- &dev_attr_actual_profile.attr,
- NULL,
-};
-
-static ssize_t isku_sysfs_read(struct file *fp, struct kobject *kobj,
- char *buf, loff_t off, size_t count,
- size_t real_size, uint command)
-{
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
- struct isku_device *isku = hid_get_drvdata(dev_get_drvdata(dev));
- struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
- int retval;
-
- if (off >= real_size)
- return 0;
-
- if (off != 0 || count > real_size)
- return -EINVAL;
-
- mutex_lock(&isku->isku_lock);
- retval = isku_receive(usb_dev, command, buf, count);
- mutex_unlock(&isku->isku_lock);
-
- return retval ? retval : count;
-}
-
-static ssize_t isku_sysfs_write(struct file *fp, struct kobject *kobj,
- void const *buf, loff_t off, size_t count,
- size_t real_size, uint command)
-{
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
- struct isku_device *isku = hid_get_drvdata(dev_get_drvdata(dev));
- struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
- int retval;
-
- if (off != 0 || count > real_size)
- return -EINVAL;
-
- mutex_lock(&isku->isku_lock);
- retval = roccat_common2_send_with_status(usb_dev, command,
- (void *)buf, count);
- mutex_unlock(&isku->isku_lock);
-
- return retval ? retval : count;
-}
-
-#define ISKU_SYSFS_W(thingy, THINGY) \
-static ssize_t isku_sysfs_write_ ## thingy(struct file *fp, struct kobject *kobj, \
- struct bin_attribute *attr, char *buf, \
- loff_t off, size_t count) \
-{ \
- return isku_sysfs_write(fp, kobj, buf, off, count, \
- ISKU_SIZE_ ## THINGY, ISKU_COMMAND_ ## THINGY); \
-}
-
-#define ISKU_SYSFS_R(thingy, THINGY) \
-static ssize_t isku_sysfs_read_ ## thingy(struct file *fp, struct kobject *kobj, \
- struct bin_attribute *attr, char *buf, \
- loff_t off, size_t count) \
-{ \
- return isku_sysfs_read(fp, kobj, buf, off, count, \
- ISKU_SIZE_ ## THINGY, ISKU_COMMAND_ ## THINGY); \
-}
-
-#define ISKU_SYSFS_RW(thingy, THINGY) \
-ISKU_SYSFS_R(thingy, THINGY) \
-ISKU_SYSFS_W(thingy, THINGY)
-
-#define ISKU_BIN_ATTR_RW(thingy, THINGY) \
-ISKU_SYSFS_RW(thingy, THINGY); \
-static struct bin_attribute bin_attr_##thingy = { \
- .attr = { .name = #thingy, .mode = 0660 }, \
- .size = ISKU_SIZE_ ## THINGY, \
- .read = isku_sysfs_read_ ## thingy, \
- .write = isku_sysfs_write_ ## thingy \
-}
-
-#define ISKU_BIN_ATTR_R(thingy, THINGY) \
-ISKU_SYSFS_R(thingy, THINGY); \
-static struct bin_attribute bin_attr_##thingy = { \
- .attr = { .name = #thingy, .mode = 0440 }, \
- .size = ISKU_SIZE_ ## THINGY, \
- .read = isku_sysfs_read_ ## thingy, \
-}
-
-#define ISKU_BIN_ATTR_W(thingy, THINGY) \
-ISKU_SYSFS_W(thingy, THINGY); \
-static struct bin_attribute bin_attr_##thingy = { \
- .attr = { .name = #thingy, .mode = 0220 }, \
- .size = ISKU_SIZE_ ## THINGY, \
- .write = isku_sysfs_write_ ## thingy \
-}
-
-ISKU_BIN_ATTR_RW(macro, MACRO);
-ISKU_BIN_ATTR_RW(keys_function, KEYS_FUNCTION);
-ISKU_BIN_ATTR_RW(keys_easyzone, KEYS_EASYZONE);
-ISKU_BIN_ATTR_RW(keys_media, KEYS_MEDIA);
-ISKU_BIN_ATTR_RW(keys_thumbster, KEYS_THUMBSTER);
-ISKU_BIN_ATTR_RW(keys_macro, KEYS_MACRO);
-ISKU_BIN_ATTR_RW(keys_capslock, KEYS_CAPSLOCK);
-ISKU_BIN_ATTR_RW(light, LIGHT);
-ISKU_BIN_ATTR_RW(key_mask, KEY_MASK);
-ISKU_BIN_ATTR_RW(last_set, LAST_SET);
-ISKU_BIN_ATTR_W(talk, TALK);
-ISKU_BIN_ATTR_W(talkfx, TALKFX);
-ISKU_BIN_ATTR_W(control, CONTROL);
-ISKU_BIN_ATTR_W(reset, RESET);
-ISKU_BIN_ATTR_R(info, INFO);
-
-static struct bin_attribute *isku_bin_attributes[] = {
- &bin_attr_macro,
- &bin_attr_keys_function,
- &bin_attr_keys_easyzone,
- &bin_attr_keys_media,
- &bin_attr_keys_thumbster,
- &bin_attr_keys_macro,
- &bin_attr_keys_capslock,
- &bin_attr_light,
- &bin_attr_key_mask,
- &bin_attr_last_set,
- &bin_attr_talk,
- &bin_attr_talkfx,
- &bin_attr_control,
- &bin_attr_reset,
- &bin_attr_info,
- NULL,
-};
-
-static const struct attribute_group isku_group = {
- .attrs = isku_attrs,
- .bin_attrs = isku_bin_attributes,
-};
-
-static const struct attribute_group *isku_groups[] = {
- &isku_group,
- NULL,
-};
-
-static int isku_init_isku_device_struct(struct usb_device *usb_dev,
- struct isku_device *isku)
-{
- int retval;
-
- mutex_init(&isku->isku_lock);
-
- retval = isku_get_actual_profile(usb_dev);
- if (retval < 0)
- return retval;
- isku_profile_activated(isku, retval);
-
- return 0;
-}
-
-static int isku_init_specials(struct hid_device *hdev)
-{
- struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
- struct usb_device *usb_dev = interface_to_usbdev(intf);
- struct isku_device *isku;
- int retval;
-
- if (intf->cur_altsetting->desc.bInterfaceProtocol
- != ISKU_USB_INTERFACE_PROTOCOL) {
- hid_set_drvdata(hdev, NULL);
- return 0;
- }
-
- isku = kzalloc(sizeof(*isku), GFP_KERNEL);
- if (!isku) {
- hid_err(hdev, "can't alloc device descriptor\n");
- return -ENOMEM;
- }
- hid_set_drvdata(hdev, isku);
-
- retval = isku_init_isku_device_struct(usb_dev, isku);
- if (retval) {
- hid_err(hdev, "couldn't init struct isku_device\n");
- goto exit_free;
- }
-
- retval = roccat_connect(isku_class, hdev,
- sizeof(struct isku_roccat_report));
- if (retval < 0) {
- hid_err(hdev, "couldn't init char dev\n");
- } else {
- isku->chrdev_minor = retval;
- isku->roccat_claimed = 1;
- }
-
- return 0;
-exit_free:
- kfree(isku);
- return retval;
-}
-
-static void isku_remove_specials(struct hid_device *hdev)
-{
- struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
- struct isku_device *isku;
-
- if (intf->cur_altsetting->desc.bInterfaceProtocol
- != ISKU_USB_INTERFACE_PROTOCOL)
- return;
-
- isku = hid_get_drvdata(hdev);
- if (isku->roccat_claimed)
- roccat_disconnect(isku->chrdev_minor);
- kfree(isku);
-}
-
-static int isku_probe(struct hid_device *hdev,
- const struct hid_device_id *id)
-{
- int retval;
-
- retval = hid_parse(hdev);
- if (retval) {
- hid_err(hdev, "parse failed\n");
- goto exit;
- }
-
- retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
- if (retval) {
- hid_err(hdev, "hw start failed\n");
- goto exit;
- }
-
- retval = isku_init_specials(hdev);
- if (retval) {
- hid_err(hdev, "couldn't install keyboard\n");
- goto exit_stop;
- }
-
- return 0;
-
-exit_stop:
- hid_hw_stop(hdev);
-exit:
- return retval;
-}
-
-static void isku_remove(struct hid_device *hdev)
-{
- isku_remove_specials(hdev);
- hid_hw_stop(hdev);
-}
-
-static void isku_keep_values_up_to_date(struct isku_device *isku,
- u8 const *data)
-{
- struct isku_report_button const *button_report;
-
- switch (data[0]) {
- case ISKU_REPORT_NUMBER_BUTTON:
- button_report = (struct isku_report_button const *)data;
- switch (button_report->event) {
- case ISKU_REPORT_BUTTON_EVENT_PROFILE:
- isku_profile_activated(isku, button_report->data1 - 1);
- break;
- }
- break;
- }
-}
-
-static void isku_report_to_chrdev(struct isku_device const *isku,
- u8 const *data)
-{
- struct isku_roccat_report roccat_report;
- struct isku_report_button const *button_report;
-
- if (data[0] != ISKU_REPORT_NUMBER_BUTTON)
- return;
-
- button_report = (struct isku_report_button const *)data;
-
- roccat_report.event = button_report->event;
- roccat_report.data1 = button_report->data1;
- roccat_report.data2 = button_report->data2;
- roccat_report.profile = isku->actual_profile + 1;
- roccat_report_event(isku->chrdev_minor,
- (uint8_t const *)&roccat_report);
-}
-
-static int isku_raw_event(struct hid_device *hdev,
- struct hid_report *report, u8 *data, int size)
-{
- struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
- struct isku_device *isku = hid_get_drvdata(hdev);
-
- if (intf->cur_altsetting->desc.bInterfaceProtocol
- != ISKU_USB_INTERFACE_PROTOCOL)
- return 0;
-
- if (isku == NULL)
- return 0;
-
- isku_keep_values_up_to_date(isku, data);
-
- if (isku->roccat_claimed)
- isku_report_to_chrdev(isku, data);
-
- return 0;
-}
-
-static const struct hid_device_id isku_devices[] = {
- { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) },
- { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKUFX) },
- { }
-};
-
-MODULE_DEVICE_TABLE(hid, isku_devices);
-
-static struct hid_driver isku_driver = {
- .name = "isku",
- .id_table = isku_devices,
- .probe = isku_probe,
- .remove = isku_remove,
- .raw_event = isku_raw_event
-};
-
-static int __init isku_init(void)
-{
- int retval;
- isku_class = class_create(THIS_MODULE, "isku");
- if (IS_ERR(isku_class))
- return PTR_ERR(isku_class);
- isku_class->dev_groups = isku_groups;
-
- retval = hid_register_driver(&isku_driver);
- if (retval)
- class_destroy(isku_class);
- return retval;
-}
-
-static void __exit isku_exit(void)
-{
- hid_unregister_driver(&isku_driver);
- class_destroy(isku_class);
-}
-
-module_init(isku_init);
-module_exit(isku_exit);
-
-MODULE_AUTHOR("Stefan Achatz");
-MODULE_DESCRIPTION("USB Roccat Isku/FX driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/hid/hid-roccat-isku.h b/drivers/hid/hid-roccat-isku.h
deleted file mode 100644
index 5305686..0000000
--- a/drivers/hid/hid-roccat-isku.h
+++ /dev/null
@@ -1,100 +0,0 @@
-#ifndef __HID_ROCCAT_ISKU_H
-#define __HID_ROCCAT_ISKU_H
-
-/*
- * Copyright (c) 2011 Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-#include <linux/types.h>
-
-enum {
- ISKU_SIZE_CONTROL = 0x03,
- ISKU_SIZE_INFO = 0x06,
- ISKU_SIZE_KEY_MASK = 0x06,
- ISKU_SIZE_KEYS_FUNCTION = 0x29,
- ISKU_SIZE_KEYS_EASYZONE = 0x41,
- ISKU_SIZE_KEYS_MEDIA = 0x1d,
- ISKU_SIZE_KEYS_THUMBSTER = 0x17,
- ISKU_SIZE_KEYS_MACRO = 0x23,
- ISKU_SIZE_KEYS_CAPSLOCK = 0x06,
- ISKU_SIZE_LAST_SET = 0x14,
- ISKU_SIZE_LIGHT = 0x10,
- ISKU_SIZE_MACRO = 0x823,
- ISKU_SIZE_RESET = 0x03,
- ISKU_SIZE_TALK = 0x10,
- ISKU_SIZE_TALKFX = 0x10,
-};
-
-enum {
- ISKU_PROFILE_NUM = 5,
- ISKU_USB_INTERFACE_PROTOCOL = 0,
-};
-
-struct isku_actual_profile {
- uint8_t command; /* ISKU_COMMAND_ACTUAL_PROFILE */
- uint8_t size; /* always 3 */
- uint8_t actual_profile;
-} __packed;
-
-enum isku_commands {
- ISKU_COMMAND_CONTROL = 0x4,
- ISKU_COMMAND_ACTUAL_PROFILE = 0x5,
- ISKU_COMMAND_KEY_MASK = 0x7,
- ISKU_COMMAND_KEYS_FUNCTION = 0x8,
- ISKU_COMMAND_KEYS_EASYZONE = 0x9,
- ISKU_COMMAND_KEYS_MEDIA = 0xa,
- ISKU_COMMAND_KEYS_THUMBSTER = 0xb,
- ISKU_COMMAND_KEYS_MACRO = 0xd,
- ISKU_COMMAND_MACRO = 0xe,
- ISKU_COMMAND_INFO = 0xf,
- ISKU_COMMAND_LIGHT = 0x10,
- ISKU_COMMAND_RESET = 0x11,
- ISKU_COMMAND_KEYS_CAPSLOCK = 0x13,
- ISKU_COMMAND_LAST_SET = 0x14,
- ISKU_COMMAND_15 = 0x15,
- ISKU_COMMAND_TALK = 0x16,
- ISKU_COMMAND_TALKFX = 0x17,
- ISKU_COMMAND_FIRMWARE_WRITE = 0x1b,
- ISKU_COMMAND_FIRMWARE_WRITE_CONTROL = 0x1c,
-};
-
-struct isku_report_button {
- uint8_t number; /* ISKU_REPORT_NUMBER_BUTTON */
- uint8_t zero;
- uint8_t event;
- uint8_t data1;
- uint8_t data2;
-};
-
-enum isku_report_numbers {
- ISKU_REPORT_NUMBER_BUTTON = 3,
-};
-
-enum isku_report_button_events {
- ISKU_REPORT_BUTTON_EVENT_PROFILE = 0x2,
-};
-
-struct isku_roccat_report {
- uint8_t event;
- uint8_t data1;
- uint8_t data2;
- uint8_t profile;
-} __packed;
-
-struct isku_device {
- int roccat_claimed;
- int chrdev_minor;
-
- struct mutex isku_lock;
-
- int actual_profile;
-};
-
-#endif
diff --git a/drivers/hid/hid-roccat-koneplus.c b/drivers/hid/hid-roccat-koneplus.c
deleted file mode 100644
index 5e99fcd..0000000
--- a/drivers/hid/hid-roccat-koneplus.c
+++ /dev/null
@@ -1,578 +0,0 @@
-/*
- * Roccat Kone[+] driver for Linux
- *
- * Copyright (c) 2010 Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-/*
- * Roccat Kone[+] is an updated/improved version of the Kone with more memory
- * and functionality and without the non-standard behaviours the Kone had.
- * KoneXTD has same capabilities but updated sensor.
- */
-
-#include <linux/device.h>
-#include <linux/input.h>
-#include <linux/hid.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/hid-roccat.h>
-#include "hid-ids.h"
-#include "hid-roccat-common.h"
-#include "hid-roccat-koneplus.h"
-
-static uint profile_numbers[5] = {0, 1, 2, 3, 4};
-
-static struct class *koneplus_class;
-
-static void koneplus_profile_activated(struct koneplus_device *koneplus,
- uint new_profile)
-{
- koneplus->actual_profile = new_profile;
-}
-
-static int koneplus_send_control(struct usb_device *usb_dev, uint value,
- enum koneplus_control_requests request)
-{
- struct roccat_common2_control control;
-
- if ((request == KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS ||
- request == KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS) &&
- value > 4)
- return -EINVAL;
-
- control.command = ROCCAT_COMMON_COMMAND_CONTROL;
- control.value = value;
- control.request = request;
-
- return roccat_common2_send_with_status(usb_dev,
- ROCCAT_COMMON_COMMAND_CONTROL,
- &control, sizeof(struct roccat_common2_control));
-}
-
-
-/* retval is 0-4 on success, < 0 on error */
-static int koneplus_get_actual_profile(struct usb_device *usb_dev)
-{
- struct koneplus_actual_profile buf;
- int retval;
-
- retval = roccat_common2_receive(usb_dev, KONEPLUS_COMMAND_ACTUAL_PROFILE,
- &buf, KONEPLUS_SIZE_ACTUAL_PROFILE);
-
- return retval ? retval : buf.actual_profile;
-}
-
-static int koneplus_set_actual_profile(struct usb_device *usb_dev,
- int new_profile)
-{
- struct koneplus_actual_profile buf;
-
- buf.command = KONEPLUS_COMMAND_ACTUAL_PROFILE;
- buf.size = KONEPLUS_SIZE_ACTUAL_PROFILE;
- buf.actual_profile = new_profile;
-
- return roccat_common2_send_with_status(usb_dev,
- KONEPLUS_COMMAND_ACTUAL_PROFILE,
- &buf, KONEPLUS_SIZE_ACTUAL_PROFILE);
-}
-
-static ssize_t koneplus_sysfs_read(struct file *fp, struct kobject *kobj,
- char *buf, loff_t off, size_t count,
- size_t real_size, uint command)
-{
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
- struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev));
- struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
- int retval;
-
- if (off >= real_size)
- return 0;
-
- if (off != 0 || count != real_size)
- return -EINVAL;
-
- mutex_lock(&koneplus->koneplus_lock);
- retval = roccat_common2_receive(usb_dev, command, buf, real_size);
- mutex_unlock(&koneplus->koneplus_lock);
-
- if (retval)
- return retval;
-
- return real_size;
-}
-
-static ssize_t koneplus_sysfs_write(struct file *fp, struct kobject *kobj,
- void const *buf, loff_t off, size_t count,
- size_t real_size, uint command)
-{
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
- struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev));
- struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
- int retval;
-
- if (off != 0 || count != real_size)
- return -EINVAL;
-
- mutex_lock(&koneplus->koneplus_lock);
- retval = roccat_common2_send_with_status(usb_dev, command,
- buf, real_size);
- mutex_unlock(&koneplus->koneplus_lock);
-
- if (retval)
- return retval;
-
- return real_size;
-}
-
-#define KONEPLUS_SYSFS_W(thingy, THINGY) \
-static ssize_t koneplus_sysfs_write_ ## thingy(struct file *fp, \
- struct kobject *kobj, struct bin_attribute *attr, char *buf, \
- loff_t off, size_t count) \
-{ \
- return koneplus_sysfs_write(fp, kobj, buf, off, count, \
- KONEPLUS_SIZE_ ## THINGY, KONEPLUS_COMMAND_ ## THINGY); \
-}
-
-#define KONEPLUS_SYSFS_R(thingy, THINGY) \
-static ssize_t koneplus_sysfs_read_ ## thingy(struct file *fp, \
- struct kobject *kobj, struct bin_attribute *attr, char *buf, \
- loff_t off, size_t count) \
-{ \
- return koneplus_sysfs_read(fp, kobj, buf, off, count, \
- KONEPLUS_SIZE_ ## THINGY, KONEPLUS_COMMAND_ ## THINGY); \
-}
-
-#define KONEPLUS_SYSFS_RW(thingy, THINGY) \
-KONEPLUS_SYSFS_W(thingy, THINGY) \
-KONEPLUS_SYSFS_R(thingy, THINGY)
-
-#define KONEPLUS_BIN_ATTRIBUTE_RW(thingy, THINGY) \
-KONEPLUS_SYSFS_RW(thingy, THINGY); \
-static struct bin_attribute bin_attr_##thingy = { \
- .attr = { .name = #thingy, .mode = 0660 }, \
- .size = KONEPLUS_SIZE_ ## THINGY, \
- .read = koneplus_sysfs_read_ ## thingy, \
- .write = koneplus_sysfs_write_ ## thingy \
-}
-
-#define KONEPLUS_BIN_ATTRIBUTE_R(thingy, THINGY) \
-KONEPLUS_SYSFS_R(thingy, THINGY); \
-static struct bin_attribute bin_attr_##thingy = { \
- .attr = { .name = #thingy, .mode = 0440 }, \
- .size = KONEPLUS_SIZE_ ## THINGY, \
- .read = koneplus_sysfs_read_ ## thingy, \
-}
-
-#define KONEPLUS_BIN_ATTRIBUTE_W(thingy, THINGY) \
-KONEPLUS_SYSFS_W(thingy, THINGY); \
-static struct bin_attribute bin_attr_##thingy = { \
- .attr = { .name = #thingy, .mode = 0220 }, \
- .size = KONEPLUS_SIZE_ ## THINGY, \
- .write = koneplus_sysfs_write_ ## thingy \
-}
-KONEPLUS_BIN_ATTRIBUTE_W(control, CONTROL);
-KONEPLUS_BIN_ATTRIBUTE_W(talk, TALK);
-KONEPLUS_BIN_ATTRIBUTE_W(macro, MACRO);
-KONEPLUS_BIN_ATTRIBUTE_R(tcu_image, TCU_IMAGE);
-KONEPLUS_BIN_ATTRIBUTE_RW(info, INFO);
-KONEPLUS_BIN_ATTRIBUTE_RW(sensor, SENSOR);
-KONEPLUS_BIN_ATTRIBUTE_RW(tcu, TCU);
-KONEPLUS_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS);
-KONEPLUS_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS);
-
-static ssize_t koneplus_sysfs_read_profilex_settings(struct file *fp,
- struct kobject *kobj, struct bin_attribute *attr, char *buf,
- loff_t off, size_t count)
-{
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
- struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
- ssize_t retval;
-
- retval = koneplus_send_control(usb_dev, *(uint *)(attr->private),
- KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS);
- if (retval)
- return retval;
-
- return koneplus_sysfs_read(fp, kobj, buf, off, count,
- KONEPLUS_SIZE_PROFILE_SETTINGS,
- KONEPLUS_COMMAND_PROFILE_SETTINGS);
-}
-
-static ssize_t koneplus_sysfs_read_profilex_buttons(struct file *fp,
- struct kobject *kobj, struct bin_attribute *attr, char *buf,
- loff_t off, size_t count)
-{
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
- struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
- ssize_t retval;
-
- retval = koneplus_send_control(usb_dev, *(uint *)(attr->private),
- KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS);
- if (retval)
- return retval;
-
- return koneplus_sysfs_read(fp, kobj, buf, off, count,
- KONEPLUS_SIZE_PROFILE_BUTTONS,
- KONEPLUS_COMMAND_PROFILE_BUTTONS);
-}
-
-#define PROFILE_ATTR(number) \
-static struct bin_attribute bin_attr_profile##number##_settings = { \
- .attr = { .name = "profile" #number "_settings", .mode = 0440 }, \
- .size = KONEPLUS_SIZE_PROFILE_SETTINGS, \
- .read = koneplus_sysfs_read_profilex_settings, \
- .private = &profile_numbers[number-1], \
-}; \
-static struct bin_attribute bin_attr_profile##number##_buttons = { \
- .attr = { .name = "profile" #number "_buttons", .mode = 0440 }, \
- .size = KONEPLUS_SIZE_PROFILE_BUTTONS, \
- .read = koneplus_sysfs_read_profilex_buttons, \
- .private = &profile_numbers[number-1], \
-};
-PROFILE_ATTR(1);
-PROFILE_ATTR(2);
-PROFILE_ATTR(3);
-PROFILE_ATTR(4);
-PROFILE_ATTR(5);
-
-static ssize_t koneplus_sysfs_show_actual_profile(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct koneplus_device *koneplus =
- hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
- return snprintf(buf, PAGE_SIZE, "%d\n", koneplus->actual_profile);
-}
-
-static ssize_t koneplus_sysfs_set_actual_profile(struct device *dev,
- struct device_attribute *attr, char const *buf, size_t size)
-{
- struct koneplus_device *koneplus;
- struct usb_device *usb_dev;
- unsigned long profile;
- int retval;
- struct koneplus_roccat_report roccat_report;
-
- dev = dev->parent->parent;
- koneplus = hid_get_drvdata(dev_get_drvdata(dev));
- usb_dev = interface_to_usbdev(to_usb_interface(dev));
-
- retval = kstrtoul(buf, 10, &profile);
- if (retval)
- return retval;
-
- if (profile > 4)
- return -EINVAL;
-
- mutex_lock(&koneplus->koneplus_lock);
-
- retval = koneplus_set_actual_profile(usb_dev, profile);
- if (retval) {
- mutex_unlock(&koneplus->koneplus_lock);
- return retval;
- }
-
- koneplus_profile_activated(koneplus, profile);
-
- roccat_report.type = KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE;
- roccat_report.data1 = profile + 1;
- roccat_report.data2 = 0;
- roccat_report.profile = profile + 1;
- roccat_report_event(koneplus->chrdev_minor,
- (uint8_t const *)&roccat_report);
-
- mutex_unlock(&koneplus->koneplus_lock);
-
- return size;
-}
-static DEVICE_ATTR(actual_profile, 0660,
- koneplus_sysfs_show_actual_profile,
- koneplus_sysfs_set_actual_profile);
-static DEVICE_ATTR(startup_profile, 0660,
- koneplus_sysfs_show_actual_profile,
- koneplus_sysfs_set_actual_profile);
-
-static ssize_t koneplus_sysfs_show_firmware_version(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct koneplus_device *koneplus;
- struct usb_device *usb_dev;
- struct koneplus_info info;
-
- dev = dev->parent->parent;
- koneplus = hid_get_drvdata(dev_get_drvdata(dev));
- usb_dev = interface_to_usbdev(to_usb_interface(dev));
-
- mutex_lock(&koneplus->koneplus_lock);
- roccat_common2_receive(usb_dev, KONEPLUS_COMMAND_INFO,
- &info, KONEPLUS_SIZE_INFO);
- mutex_unlock(&koneplus->koneplus_lock);
-
- return snprintf(buf, PAGE_SIZE, "%d\n", info.firmware_version);
-}
-static DEVICE_ATTR(firmware_version, 0440,
- koneplus_sysfs_show_firmware_version, NULL);
-
-static struct attribute *koneplus_attrs[] = {
- &dev_attr_actual_profile.attr,
- &dev_attr_startup_profile.attr,
- &dev_attr_firmware_version.attr,
- NULL,
-};
-
-static struct bin_attribute *koneplus_bin_attributes[] = {
- &bin_attr_control,
- &bin_attr_talk,
- &bin_attr_macro,
- &bin_attr_tcu_image,
- &bin_attr_info,
- &bin_attr_sensor,
- &bin_attr_tcu,
- &bin_attr_profile_settings,
- &bin_attr_profile_buttons,
- &bin_attr_profile1_settings,
- &bin_attr_profile2_settings,
- &bin_attr_profile3_settings,
- &bin_attr_profile4_settings,
- &bin_attr_profile5_settings,
- &bin_attr_profile1_buttons,
- &bin_attr_profile2_buttons,
- &bin_attr_profile3_buttons,
- &bin_attr_profile4_buttons,
- &bin_attr_profile5_buttons,
- NULL,
-};
-
-static const struct attribute_group koneplus_group = {
- .attrs = koneplus_attrs,
- .bin_attrs = koneplus_bin_attributes,
-};
-
-static const struct attribute_group *koneplus_groups[] = {
- &koneplus_group,
- NULL,
-};
-
-static int koneplus_init_koneplus_device_struct(struct usb_device *usb_dev,
- struct koneplus_device *koneplus)
-{
- int retval;
-
- mutex_init(&koneplus->koneplus_lock);
-
- retval = koneplus_get_actual_profile(usb_dev);
- if (retval < 0)
- return retval;
- koneplus_profile_activated(koneplus, retval);
-
- return 0;
-}
-
-static int koneplus_init_specials(struct hid_device *hdev)
-{
- struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
- struct usb_device *usb_dev = interface_to_usbdev(intf);
- struct koneplus_device *koneplus;
- int retval;
-
- if (intf->cur_altsetting->desc.bInterfaceProtocol
- == USB_INTERFACE_PROTOCOL_MOUSE) {
-
- koneplus = kzalloc(sizeof(*koneplus), GFP_KERNEL);
- if (!koneplus) {
- hid_err(hdev, "can't alloc device descriptor\n");
- return -ENOMEM;
- }
- hid_set_drvdata(hdev, koneplus);
-
- retval = koneplus_init_koneplus_device_struct(usb_dev, koneplus);
- if (retval) {
- hid_err(hdev, "couldn't init struct koneplus_device\n");
- goto exit_free;
- }
-
- retval = roccat_connect(koneplus_class, hdev,
- sizeof(struct koneplus_roccat_report));
- if (retval < 0) {
- hid_err(hdev, "couldn't init char dev\n");
- } else {
- koneplus->chrdev_minor = retval;
- koneplus->roccat_claimed = 1;
- }
- } else {
- hid_set_drvdata(hdev, NULL);
- }
-
- return 0;
-exit_free:
- kfree(koneplus);
- return retval;
-}
-
-static void koneplus_remove_specials(struct hid_device *hdev)
-{
- struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
- struct koneplus_device *koneplus;
-
- if (intf->cur_altsetting->desc.bInterfaceProtocol
- == USB_INTERFACE_PROTOCOL_MOUSE) {
- koneplus = hid_get_drvdata(hdev);
- if (koneplus->roccat_claimed)
- roccat_disconnect(koneplus->chrdev_minor);
- kfree(koneplus);
- }
-}
-
-static int koneplus_probe(struct hid_device *hdev,
- const struct hid_device_id *id)
-{
- int retval;
-
- retval = hid_parse(hdev);
- if (retval) {
- hid_err(hdev, "parse failed\n");
- goto exit;
- }
-
- retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
- if (retval) {
- hid_err(hdev, "hw start failed\n");
- goto exit;
- }
-
- retval = koneplus_init_specials(hdev);
- if (retval) {
- hid_err(hdev, "couldn't install mouse\n");
- goto exit_stop;
- }
-
- return 0;
-
-exit_stop:
- hid_hw_stop(hdev);
-exit:
- return retval;
-}
-
-static void koneplus_remove(struct hid_device *hdev)
-{
- koneplus_remove_specials(hdev);
- hid_hw_stop(hdev);
-}
-
-static void koneplus_keep_values_up_to_date(struct koneplus_device *koneplus,
- u8 const *data)
-{
- struct koneplus_mouse_report_button const *button_report;
-
- switch (data[0]) {
- case KONEPLUS_MOUSE_REPORT_NUMBER_BUTTON:
- button_report = (struct koneplus_mouse_report_button const *)data;
- switch (button_report->type) {
- case KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE:
- koneplus_profile_activated(koneplus, button_report->data1 - 1);
- break;
- }
- break;
- }
-}
-
-static void koneplus_report_to_chrdev(struct koneplus_device const *koneplus,
- u8 const *data)
-{
- struct koneplus_roccat_report roccat_report;
- struct koneplus_mouse_report_button const *button_report;
-
- if (data[0] != KONEPLUS_MOUSE_REPORT_NUMBER_BUTTON)
- return;
-
- button_report = (struct koneplus_mouse_report_button const *)data;
-
- if ((button_report->type == KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_QUICKLAUNCH ||
- button_report->type == KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_TIMER) &&
- button_report->data2 != KONEPLUS_MOUSE_REPORT_BUTTON_ACTION_PRESS)
- return;
-
- roccat_report.type = button_report->type;
- roccat_report.data1 = button_report->data1;
- roccat_report.data2 = button_report->data2;
- roccat_report.profile = koneplus->actual_profile + 1;
- roccat_report_event(koneplus->chrdev_minor,
- (uint8_t const *)&roccat_report);
-}
-
-static int koneplus_raw_event(struct hid_device *hdev,
- struct hid_report *report, u8 *data, int size)
-{
- struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
- struct koneplus_device *koneplus = hid_get_drvdata(hdev);
-
- if (intf->cur_altsetting->desc.bInterfaceProtocol
- != USB_INTERFACE_PROTOCOL_MOUSE)
- return 0;
-
- if (koneplus == NULL)
- return 0;
-
- koneplus_keep_values_up_to_date(koneplus, data);
-
- if (koneplus->roccat_claimed)
- koneplus_report_to_chrdev(koneplus, data);
-
- return 0;
-}
-
-static const struct hid_device_id koneplus_devices[] = {
- { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) },
- { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEXTD) },
- { }
-};
-
-MODULE_DEVICE_TABLE(hid, koneplus_devices);
-
-static struct hid_driver koneplus_driver = {
- .name = "koneplus",
- .id_table = koneplus_devices,
- .probe = koneplus_probe,
- .remove = koneplus_remove,
- .raw_event = koneplus_raw_event
-};
-
-static int __init koneplus_init(void)
-{
- int retval;
-
- /* class name has to be same as driver name */
- koneplus_class = class_create(THIS_MODULE, "koneplus");
- if (IS_ERR(koneplus_class))
- return PTR_ERR(koneplus_class);
- koneplus_class->dev_groups = koneplus_groups;
-
- retval = hid_register_driver(&koneplus_driver);
- if (retval)
- class_destroy(koneplus_class);
- return retval;
-}
-
-static void __exit koneplus_exit(void)
-{
- hid_unregister_driver(&koneplus_driver);
- class_destroy(koneplus_class);
-}
-
-module_init(koneplus_init);
-module_exit(koneplus_exit);
-
-MODULE_AUTHOR("Stefan Achatz");
-MODULE_DESCRIPTION("USB Roccat Kone[+]/XTD driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/hid/hid-roccat-koneplus.h b/drivers/hid/hid-roccat-koneplus.h
deleted file mode 100644
index af7f57e..0000000
--- a/drivers/hid/hid-roccat-koneplus.h
+++ /dev/null
@@ -1,125 +0,0 @@
-#ifndef __HID_ROCCAT_KONEPLUS_H
-#define __HID_ROCCAT_KONEPLUS_H
-
-/*
- * Copyright (c) 2010 Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-#include <linux/types.h>
-
-enum {
- KONEPLUS_SIZE_ACTUAL_PROFILE = 0x03,
- KONEPLUS_SIZE_CONTROL = 0x03,
- KONEPLUS_SIZE_FIRMWARE_WRITE = 0x0402,
- KONEPLUS_SIZE_INFO = 0x06,
- KONEPLUS_SIZE_MACRO = 0x0822,
- KONEPLUS_SIZE_PROFILE_SETTINGS = 0x2b,
- KONEPLUS_SIZE_PROFILE_BUTTONS = 0x4d,
- KONEPLUS_SIZE_SENSOR = 0x06,
- KONEPLUS_SIZE_TALK = 0x10,
- KONEPLUS_SIZE_TCU = 0x04,
- KONEPLUS_SIZE_TCU_IMAGE = 0x0404,
-};
-
-enum koneplus_control_requests {
- KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS = 0x80,
- KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS = 0x90,
-};
-
-struct koneplus_actual_profile {
- uint8_t command; /* KONEPLUS_COMMAND_ACTUAL_PROFILE */
- uint8_t size; /* always 3 */
- uint8_t actual_profile; /* Range 0-4! */
-} __attribute__ ((__packed__));
-
-struct koneplus_info {
- uint8_t command; /* KONEPLUS_COMMAND_INFO */
- uint8_t size; /* always 6 */
- uint8_t firmware_version;
- uint8_t unknown[3];
-} __attribute__ ((__packed__));
-
-enum koneplus_commands {
- KONEPLUS_COMMAND_ACTUAL_PROFILE = 0x5,
- KONEPLUS_COMMAND_CONTROL = 0x4,
- KONEPLUS_COMMAND_PROFILE_SETTINGS = 0x6,
- KONEPLUS_COMMAND_PROFILE_BUTTONS = 0x7,
- KONEPLUS_COMMAND_MACRO = 0x8,
- KONEPLUS_COMMAND_INFO = 0x9,
- KONEPLUS_COMMAND_TCU = 0xc,
- KONEPLUS_COMMAND_TCU_IMAGE = 0xc,
- KONEPLUS_COMMAND_E = 0xe,
- KONEPLUS_COMMAND_SENSOR = 0xf,
- KONEPLUS_COMMAND_TALK = 0x10,
- KONEPLUS_COMMAND_FIRMWARE_WRITE = 0x1b,
- KONEPLUS_COMMAND_FIRMWARE_WRITE_CONTROL = 0x1c,
-};
-
-enum koneplus_mouse_report_numbers {
- KONEPLUS_MOUSE_REPORT_NUMBER_HID = 1,
- KONEPLUS_MOUSE_REPORT_NUMBER_AUDIO = 2,
- KONEPLUS_MOUSE_REPORT_NUMBER_BUTTON = 3,
-};
-
-struct koneplus_mouse_report_button {
- uint8_t report_number; /* always KONEPLUS_MOUSE_REPORT_NUMBER_BUTTON */
- uint8_t zero1;
- uint8_t type;
- uint8_t data1;
- uint8_t data2;
- uint8_t zero2;
- uint8_t unknown[2];
-} __attribute__ ((__packed__));
-
-enum koneplus_mouse_report_button_types {
- /* data1 = new profile range 1-5 */
- KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE = 0x20,
-
- /* data1 = button number range 1-24; data2 = action */
- KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_QUICKLAUNCH = 0x60,
-
- /* data1 = button number range 1-24; data2 = action */
- KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_TIMER = 0x80,
-
- /* data1 = setting number range 1-5 */
- KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_CPI = 0xb0,
-
- /* data1 and data2 = range 0x1-0xb */
- KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_SENSITIVITY = 0xc0,
-
- /* data1 = 22 = next track...
- * data2 = action
- */
- KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_MULTIMEDIA = 0xf0,
- KONEPLUS_MOUSE_REPORT_TALK = 0xff,
-};
-
-enum koneplus_mouse_report_button_action {
- KONEPLUS_MOUSE_REPORT_BUTTON_ACTION_PRESS = 0,
- KONEPLUS_MOUSE_REPORT_BUTTON_ACTION_RELEASE = 1,
-};
-
-struct koneplus_roccat_report {
- uint8_t type;
- uint8_t data1;
- uint8_t data2;
- uint8_t profile;
-} __attribute__ ((__packed__));
-
-struct koneplus_device {
- int actual_profile;
-
- int roccat_claimed;
- int chrdev_minor;
-
- struct mutex koneplus_lock;
-};
-
-#endif
diff --git a/drivers/hid/hid-roccat-konepure.c b/drivers/hid/hid-roccat-konepure.c
deleted file mode 100644
index 07de2f9..0000000
--- a/drivers/hid/hid-roccat-konepure.c
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * Roccat KonePure driver for Linux
- *
- * Copyright (c) 2012 Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-/*
- * Roccat KonePure is a smaller version of KoneXTD with less buttons and lights.
- */
-
-#include <linux/types.h>
-#include <linux/device.h>
-#include <linux/input.h>
-#include <linux/hid.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/hid-roccat.h>
-#include "hid-ids.h"
-#include "hid-roccat-common.h"
-
-enum {
- KONEPURE_MOUSE_REPORT_NUMBER_BUTTON = 3,
-};
-
-struct konepure_mouse_report_button {
- uint8_t report_number; /* always KONEPURE_MOUSE_REPORT_NUMBER_BUTTON */
- uint8_t zero;
- uint8_t type;
- uint8_t data1;
- uint8_t data2;
- uint8_t zero2;
- uint8_t unknown[2];
-} __packed;
-
-static struct class *konepure_class;
-
-ROCCAT_COMMON2_BIN_ATTRIBUTE_W(control, 0x04, 0x03);
-ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(actual_profile, 0x05, 0x03);
-ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(profile_settings, 0x06, 0x1f);
-ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(profile_buttons, 0x07, 0x3b);
-ROCCAT_COMMON2_BIN_ATTRIBUTE_W(macro, 0x08, 0x0822);
-ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(info, 0x09, 0x06);
-ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(tcu, 0x0c, 0x04);
-ROCCAT_COMMON2_BIN_ATTRIBUTE_R(tcu_image, 0x0c, 0x0404);
-ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(sensor, 0x0f, 0x06);
-ROCCAT_COMMON2_BIN_ATTRIBUTE_W(talk, 0x10, 0x10);
-
-static struct bin_attribute *konepure_bin_attrs[] = {
- &bin_attr_actual_profile,
- &bin_attr_control,
- &bin_attr_info,
- &bin_attr_talk,
- &bin_attr_macro,
- &bin_attr_sensor,
- &bin_attr_tcu,
- &bin_attr_tcu_image,
- &bin_attr_profile_settings,
- &bin_attr_profile_buttons,
- NULL,
-};
-
-static const struct attribute_group konepure_group = {
- .bin_attrs = konepure_bin_attrs,
-};
-
-static const struct attribute_group *konepure_groups[] = {
- &konepure_group,
- NULL,
-};
-
-static int konepure_init_specials(struct hid_device *hdev)
-{
- struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
- struct usb_device *usb_dev = interface_to_usbdev(intf);
- struct roccat_common2_device *konepure;
- int retval;
-
- if (intf->cur_altsetting->desc.bInterfaceProtocol
- != USB_INTERFACE_PROTOCOL_MOUSE) {
- hid_set_drvdata(hdev, NULL);
- return 0;
- }
-
- konepure = kzalloc(sizeof(*konepure), GFP_KERNEL);
- if (!konepure) {
- hid_err(hdev, "can't alloc device descriptor\n");
- return -ENOMEM;
- }
- hid_set_drvdata(hdev, konepure);
-
- retval = roccat_common2_device_init_struct(usb_dev, konepure);
- if (retval) {
- hid_err(hdev, "couldn't init KonePure device\n");
- goto exit_free;
- }
-
- retval = roccat_connect(konepure_class, hdev,
- sizeof(struct konepure_mouse_report_button));
- if (retval < 0) {
- hid_err(hdev, "couldn't init char dev\n");
- } else {
- konepure->chrdev_minor = retval;
- konepure->roccat_claimed = 1;
- }
-
- return 0;
-exit_free:
- kfree(konepure);
- return retval;
-}
-
-static void konepure_remove_specials(struct hid_device *hdev)
-{
- struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
- struct roccat_common2_device *konepure;
-
- if (intf->cur_altsetting->desc.bInterfaceProtocol
- != USB_INTERFACE_PROTOCOL_MOUSE)
- return;
-
- konepure = hid_get_drvdata(hdev);
- if (konepure->roccat_claimed)
- roccat_disconnect(konepure->chrdev_minor);
- kfree(konepure);
-}
-
-static int konepure_probe(struct hid_device *hdev,
- const struct hid_device_id *id)
-{
- int retval;
-
- retval = hid_parse(hdev);
- if (retval) {
- hid_err(hdev, "parse failed\n");
- goto exit;
- }
-
- retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
- if (retval) {
- hid_err(hdev, "hw start failed\n");
- goto exit;
- }
-
- retval = konepure_init_specials(hdev);
- if (retval) {
- hid_err(hdev, "couldn't install mouse\n");
- goto exit_stop;
- }
-
- return 0;
-
-exit_stop:
- hid_hw_stop(hdev);
-exit:
- return retval;
-}
-
-static void konepure_remove(struct hid_device *hdev)
-{
- konepure_remove_specials(hdev);
- hid_hw_stop(hdev);
-}
-
-static int konepure_raw_event(struct hid_device *hdev,
- struct hid_report *report, u8 *data, int size)
-{
- struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
- struct roccat_common2_device *konepure = hid_get_drvdata(hdev);
-
- if (intf->cur_altsetting->desc.bInterfaceProtocol
- != USB_INTERFACE_PROTOCOL_MOUSE)
- return 0;
-
- if (data[0] != KONEPURE_MOUSE_REPORT_NUMBER_BUTTON)
- return 0;
-
- if (konepure != NULL && konepure->roccat_claimed)
- roccat_report_event(konepure->chrdev_minor, data);
-
- return 0;
-}
-
-static const struct hid_device_id konepure_devices[] = {
- { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPURE) },
- { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPURE_OPTICAL) },
- { }
-};
-
-MODULE_DEVICE_TABLE(hid, konepure_devices);
-
-static struct hid_driver konepure_driver = {
- .name = "konepure",
- .id_table = konepure_devices,
- .probe = konepure_probe,
- .remove = konepure_remove,
- .raw_event = konepure_raw_event
-};
-
-static int __init konepure_init(void)
-{
- int retval;
-
- konepure_class = class_create(THIS_MODULE, "konepure");
- if (IS_ERR(konepure_class))
- return PTR_ERR(konepure_class);
- konepure_class->dev_groups = konepure_groups;
-
- retval = hid_register_driver(&konepure_driver);
- if (retval)
- class_destroy(konepure_class);
- return retval;
-}
-
-static void __exit konepure_exit(void)
-{
- hid_unregister_driver(&konepure_driver);
- class_destroy(konepure_class);
-}
-
-module_init(konepure_init);
-module_exit(konepure_exit);
-
-MODULE_AUTHOR("Stefan Achatz");
-MODULE_DESCRIPTION("USB Roccat KonePure/Optical driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/hid/hid-roccat-kovaplus.c b/drivers/hid/hid-roccat-kovaplus.c
deleted file mode 100644
index 9660477..0000000
--- a/drivers/hid/hid-roccat-kovaplus.c
+++ /dev/null
@@ -1,665 +0,0 @@
-/*
- * Roccat Kova[+] driver for Linux
- *
- * Copyright (c) 2011 Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-/*
- * Roccat Kova[+] is a bigger version of the Pyra with two more side buttons.
- */
-
-#include <linux/device.h>
-#include <linux/input.h>
-#include <linux/hid.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/hid-roccat.h>
-#include "hid-ids.h"
-#include "hid-roccat-common.h"
-#include "hid-roccat-kovaplus.h"
-
-static uint profile_numbers[5] = {0, 1, 2, 3, 4};
-
-static struct class *kovaplus_class;
-
-static uint kovaplus_convert_event_cpi(uint value)
-{
- return (value == 7 ? 4 : (value == 4 ? 3 : value));
-}
-
-static void kovaplus_profile_activated(struct kovaplus_device *kovaplus,
- uint new_profile_index)
-{
- kovaplus->actual_profile = new_profile_index;
- kovaplus->actual_cpi = kovaplus->profile_settings[new_profile_index].cpi_startup_level;
- kovaplus->actual_x_sensitivity = kovaplus->profile_settings[new_profile_index].sensitivity_x;
- kovaplus->actual_y_sensitivity = kovaplus->profile_settings[new_profile_index].sensitivity_y;
-}
-
-static int kovaplus_send_control(struct usb_device *usb_dev, uint value,
- enum kovaplus_control_requests request)
-{
- int retval;
- struct roccat_common2_control control;
-
- if ((request == KOVAPLUS_CONTROL_REQUEST_PROFILE_SETTINGS ||
- request == KOVAPLUS_CONTROL_REQUEST_PROFILE_BUTTONS) &&
- value > 4)
- return -EINVAL;
-
- control.command = ROCCAT_COMMON_COMMAND_CONTROL;
- control.value = value;
- control.request = request;
-
- retval = roccat_common2_send(usb_dev, ROCCAT_COMMON_COMMAND_CONTROL,
- &control, sizeof(struct roccat_common2_control));
-
- return retval;
-}
-
-static int kovaplus_select_profile(struct usb_device *usb_dev, uint number,
- enum kovaplus_control_requests request)
-{
- return kovaplus_send_control(usb_dev, number, request);
-}
-
-static int kovaplus_get_profile_settings(struct usb_device *usb_dev,
- struct kovaplus_profile_settings *buf, uint number)
-{
- int retval;
-
- retval = kovaplus_select_profile(usb_dev, number,
- KOVAPLUS_CONTROL_REQUEST_PROFILE_SETTINGS);
- if (retval)
- return retval;
-
- return roccat_common2_receive(usb_dev, KOVAPLUS_COMMAND_PROFILE_SETTINGS,
- buf, KOVAPLUS_SIZE_PROFILE_SETTINGS);
-}
-
-static int kovaplus_get_profile_buttons(struct usb_device *usb_dev,
- struct kovaplus_profile_buttons *buf, int number)
-{
- int retval;
-
- retval = kovaplus_select_profile(usb_dev, number,
- KOVAPLUS_CONTROL_REQUEST_PROFILE_BUTTONS);
- if (retval)
- return retval;
-
- return roccat_common2_receive(usb_dev, KOVAPLUS_COMMAND_PROFILE_BUTTONS,
- buf, KOVAPLUS_SIZE_PROFILE_BUTTONS);
-}
-
-/* retval is 0-4 on success, < 0 on error */
-static int kovaplus_get_actual_profile(struct usb_device *usb_dev)
-{
- struct kovaplus_actual_profile buf;
- int retval;
-
- retval = roccat_common2_receive(usb_dev, KOVAPLUS_COMMAND_ACTUAL_PROFILE,
- &buf, sizeof(struct kovaplus_actual_profile));
-
- return retval ? retval : buf.actual_profile;
-}
-
-static int kovaplus_set_actual_profile(struct usb_device *usb_dev,
- int new_profile)
-{
- struct kovaplus_actual_profile buf;
-
- buf.command = KOVAPLUS_COMMAND_ACTUAL_PROFILE;
- buf.size = sizeof(struct kovaplus_actual_profile);
- buf.actual_profile = new_profile;
-
- return roccat_common2_send_with_status(usb_dev,
- KOVAPLUS_COMMAND_ACTUAL_PROFILE,
- &buf, sizeof(struct kovaplus_actual_profile));
-}
-
-static ssize_t kovaplus_sysfs_read(struct file *fp, struct kobject *kobj,
- char *buf, loff_t off, size_t count,
- size_t real_size, uint command)
-{
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
- struct kovaplus_device *kovaplus = hid_get_drvdata(dev_get_drvdata(dev));
- struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
- int retval;
-
- if (off >= real_size)
- return 0;
-
- if (off != 0 || count != real_size)
- return -EINVAL;
-
- mutex_lock(&kovaplus->kovaplus_lock);
- retval = roccat_common2_receive(usb_dev, command, buf, real_size);
- mutex_unlock(&kovaplus->kovaplus_lock);
-
- if (retval)
- return retval;
-
- return real_size;
-}
-
-static ssize_t kovaplus_sysfs_write(struct file *fp, struct kobject *kobj,
- void const *buf, loff_t off, size_t count,
- size_t real_size, uint command)
-{
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
- struct kovaplus_device *kovaplus = hid_get_drvdata(dev_get_drvdata(dev));
- struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
- int retval;
-
- if (off != 0 || count != real_size)
- return -EINVAL;
-
- mutex_lock(&kovaplus->kovaplus_lock);
- retval = roccat_common2_send_with_status(usb_dev, command,
- buf, real_size);
- mutex_unlock(&kovaplus->kovaplus_lock);
-
- if (retval)
- return retval;
-
- return real_size;
-}
-
-#define KOVAPLUS_SYSFS_W(thingy, THINGY) \
-static ssize_t kovaplus_sysfs_write_ ## thingy(struct file *fp, \
- struct kobject *kobj, struct bin_attribute *attr, char *buf, \
- loff_t off, size_t count) \
-{ \
- return kovaplus_sysfs_write(fp, kobj, buf, off, count, \
- KOVAPLUS_SIZE_ ## THINGY, KOVAPLUS_COMMAND_ ## THINGY); \
-}
-
-#define KOVAPLUS_SYSFS_R(thingy, THINGY) \
-static ssize_t kovaplus_sysfs_read_ ## thingy(struct file *fp, \
- struct kobject *kobj, struct bin_attribute *attr, char *buf, \
- loff_t off, size_t count) \
-{ \
- return kovaplus_sysfs_read(fp, kobj, buf, off, count, \
- KOVAPLUS_SIZE_ ## THINGY, KOVAPLUS_COMMAND_ ## THINGY); \
-}
-
-#define KOVAPLUS_SYSFS_RW(thingy, THINGY) \
-KOVAPLUS_SYSFS_W(thingy, THINGY) \
-KOVAPLUS_SYSFS_R(thingy, THINGY)
-
-#define KOVAPLUS_BIN_ATTRIBUTE_RW(thingy, THINGY) \
-KOVAPLUS_SYSFS_RW(thingy, THINGY); \
-static struct bin_attribute bin_attr_##thingy = { \
- .attr = { .name = #thingy, .mode = 0660 }, \
- .size = KOVAPLUS_SIZE_ ## THINGY, \
- .read = kovaplus_sysfs_read_ ## thingy, \
- .write = kovaplus_sysfs_write_ ## thingy \
-}
-
-#define KOVAPLUS_BIN_ATTRIBUTE_W(thingy, THINGY) \
-KOVAPLUS_SYSFS_W(thingy, THINGY); \
-static struct bin_attribute bin_attr_##thingy = { \
- .attr = { .name = #thingy, .mode = 0220 }, \
- .size = KOVAPLUS_SIZE_ ## THINGY, \
- .write = kovaplus_sysfs_write_ ## thingy \
-}
-KOVAPLUS_BIN_ATTRIBUTE_W(control, CONTROL);
-KOVAPLUS_BIN_ATTRIBUTE_RW(info, INFO);
-KOVAPLUS_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS);
-KOVAPLUS_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS);
-
-static ssize_t kovaplus_sysfs_read_profilex_settings(struct file *fp,
- struct kobject *kobj, struct bin_attribute *attr, char *buf,
- loff_t off, size_t count)
-{
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
- struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
- ssize_t retval;
-
- retval = kovaplus_select_profile(usb_dev, *(uint *)(attr->private),
- KOVAPLUS_CONTROL_REQUEST_PROFILE_SETTINGS);
- if (retval)
- return retval;
-
- return kovaplus_sysfs_read(fp, kobj, buf, off, count,
- KOVAPLUS_SIZE_PROFILE_SETTINGS,
- KOVAPLUS_COMMAND_PROFILE_SETTINGS);
-}
-
-static ssize_t kovaplus_sysfs_read_profilex_buttons(struct file *fp,
- struct kobject *kobj, struct bin_attribute *attr, char *buf,
- loff_t off, size_t count)
-{
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
- struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
- ssize_t retval;
-
- retval = kovaplus_select_profile(usb_dev, *(uint *)(attr->private),
- KOVAPLUS_CONTROL_REQUEST_PROFILE_BUTTONS);
- if (retval)
- return retval;
-
- return kovaplus_sysfs_read(fp, kobj, buf, off, count,
- KOVAPLUS_SIZE_PROFILE_BUTTONS,
- KOVAPLUS_COMMAND_PROFILE_BUTTONS);
-}
-
-#define PROFILE_ATTR(number) \
-static struct bin_attribute bin_attr_profile##number##_settings = { \
- .attr = { .name = "profile" #number "_settings", .mode = 0440 }, \
- .size = KOVAPLUS_SIZE_PROFILE_SETTINGS, \
- .read = kovaplus_sysfs_read_profilex_settings, \
- .private = &profile_numbers[number-1], \
-}; \
-static struct bin_attribute bin_attr_profile##number##_buttons = { \
- .attr = { .name = "profile" #number "_buttons", .mode = 0440 }, \
- .size = KOVAPLUS_SIZE_PROFILE_BUTTONS, \
- .read = kovaplus_sysfs_read_profilex_buttons, \
- .private = &profile_numbers[number-1], \
-};
-PROFILE_ATTR(1);
-PROFILE_ATTR(2);
-PROFILE_ATTR(3);
-PROFILE_ATTR(4);
-PROFILE_ATTR(5);
-
-static ssize_t kovaplus_sysfs_show_actual_profile(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct kovaplus_device *kovaplus =
- hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
- return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->actual_profile);
-}
-
-static ssize_t kovaplus_sysfs_set_actual_profile(struct device *dev,
- struct device_attribute *attr, char const *buf, size_t size)
-{
- struct kovaplus_device *kovaplus;
- struct usb_device *usb_dev;
- unsigned long profile;
- int retval;
- struct kovaplus_roccat_report roccat_report;
-
- dev = dev->parent->parent;
- kovaplus = hid_get_drvdata(dev_get_drvdata(dev));
- usb_dev = interface_to_usbdev(to_usb_interface(dev));
-
- retval = kstrtoul(buf, 10, &profile);
- if (retval)
- return retval;
-
- if (profile >= 5)
- return -EINVAL;
-
- mutex_lock(&kovaplus->kovaplus_lock);
- retval = kovaplus_set_actual_profile(usb_dev, profile);
- if (retval) {
- mutex_unlock(&kovaplus->kovaplus_lock);
- return retval;
- }
-
- kovaplus_profile_activated(kovaplus, profile);
-
- roccat_report.type = KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE_1;
- roccat_report.profile = profile + 1;
- roccat_report.button = 0;
- roccat_report.data1 = profile + 1;
- roccat_report.data2 = 0;
- roccat_report_event(kovaplus->chrdev_minor,
- (uint8_t const *)&roccat_report);
-
- mutex_unlock(&kovaplus->kovaplus_lock);
-
- return size;
-}
-static DEVICE_ATTR(actual_profile, 0660,
- kovaplus_sysfs_show_actual_profile,
- kovaplus_sysfs_set_actual_profile);
-
-static ssize_t kovaplus_sysfs_show_actual_cpi(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct kovaplus_device *kovaplus =
- hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
- return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->actual_cpi);
-}
-static DEVICE_ATTR(actual_cpi, 0440, kovaplus_sysfs_show_actual_cpi, NULL);
-
-static ssize_t kovaplus_sysfs_show_actual_sensitivity_x(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct kovaplus_device *kovaplus =
- hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
- return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->actual_x_sensitivity);
-}
-static DEVICE_ATTR(actual_sensitivity_x, 0440,
- kovaplus_sysfs_show_actual_sensitivity_x, NULL);
-
-static ssize_t kovaplus_sysfs_show_actual_sensitivity_y(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct kovaplus_device *kovaplus =
- hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
- return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->actual_y_sensitivity);
-}
-static DEVICE_ATTR(actual_sensitivity_y, 0440,
- kovaplus_sysfs_show_actual_sensitivity_y, NULL);
-
-static ssize_t kovaplus_sysfs_show_firmware_version(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct kovaplus_device *kovaplus;
- struct usb_device *usb_dev;
- struct kovaplus_info info;
-
- dev = dev->parent->parent;
- kovaplus = hid_get_drvdata(dev_get_drvdata(dev));
- usb_dev = interface_to_usbdev(to_usb_interface(dev));
-
- mutex_lock(&kovaplus->kovaplus_lock);
- roccat_common2_receive(usb_dev, KOVAPLUS_COMMAND_INFO,
- &info, KOVAPLUS_SIZE_INFO);
- mutex_unlock(&kovaplus->kovaplus_lock);
-
- return snprintf(buf, PAGE_SIZE, "%d\n", info.firmware_version);
-}
-static DEVICE_ATTR(firmware_version, 0440,
- kovaplus_sysfs_show_firmware_version, NULL);
-
-static struct attribute *kovaplus_attrs[] = {
- &dev_attr_actual_cpi.attr,
- &dev_attr_firmware_version.attr,
- &dev_attr_actual_profile.attr,
- &dev_attr_actual_sensitivity_x.attr,
- &dev_attr_actual_sensitivity_y.attr,
- NULL,
-};
-
-static struct bin_attribute *kovaplus_bin_attributes[] = {
- &bin_attr_control,
- &bin_attr_info,
- &bin_attr_profile_settings,
- &bin_attr_profile_buttons,
- &bin_attr_profile1_settings,
- &bin_attr_profile2_settings,
- &bin_attr_profile3_settings,
- &bin_attr_profile4_settings,
- &bin_attr_profile5_settings,
- &bin_attr_profile1_buttons,
- &bin_attr_profile2_buttons,
- &bin_attr_profile3_buttons,
- &bin_attr_profile4_buttons,
- &bin_attr_profile5_buttons,
- NULL,
-};
-
-static const struct attribute_group kovaplus_group = {
- .attrs = kovaplus_attrs,
- .bin_attrs = kovaplus_bin_attributes,
-};
-
-static const struct attribute_group *kovaplus_groups[] = {
- &kovaplus_group,
- NULL,
-};
-
-static int kovaplus_init_kovaplus_device_struct(struct usb_device *usb_dev,
- struct kovaplus_device *kovaplus)
-{
- int retval, i;
- static uint wait = 70; /* device will freeze with just 60 */
-
- mutex_init(&kovaplus->kovaplus_lock);
-
- for (i = 0; i < 5; ++i) {
- msleep(wait);
- retval = kovaplus_get_profile_settings(usb_dev,
- &kovaplus->profile_settings[i], i);
- if (retval)
- return retval;
-
- msleep(wait);
- retval = kovaplus_get_profile_buttons(usb_dev,
- &kovaplus->profile_buttons[i], i);
- if (retval)
- return retval;
- }
-
- msleep(wait);
- retval = kovaplus_get_actual_profile(usb_dev);
- if (retval < 0)
- return retval;
- kovaplus_profile_activated(kovaplus, retval);
-
- return 0;
-}
-
-static int kovaplus_init_specials(struct hid_device *hdev)
-{
- struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
- struct usb_device *usb_dev = interface_to_usbdev(intf);
- struct kovaplus_device *kovaplus;
- int retval;
-
- if (intf->cur_altsetting->desc.bInterfaceProtocol
- == USB_INTERFACE_PROTOCOL_MOUSE) {
-
- kovaplus = kzalloc(sizeof(*kovaplus), GFP_KERNEL);
- if (!kovaplus) {
- hid_err(hdev, "can't alloc device descriptor\n");
- return -ENOMEM;
- }
- hid_set_drvdata(hdev, kovaplus);
-
- retval = kovaplus_init_kovaplus_device_struct(usb_dev, kovaplus);
- if (retval) {
- hid_err(hdev, "couldn't init struct kovaplus_device\n");
- goto exit_free;
- }
-
- retval = roccat_connect(kovaplus_class, hdev,
- sizeof(struct kovaplus_roccat_report));
- if (retval < 0) {
- hid_err(hdev, "couldn't init char dev\n");
- } else {
- kovaplus->chrdev_minor = retval;
- kovaplus->roccat_claimed = 1;
- }
-
- } else {
- hid_set_drvdata(hdev, NULL);
- }
-
- return 0;
-exit_free:
- kfree(kovaplus);
- return retval;
-}
-
-static void kovaplus_remove_specials(struct hid_device *hdev)
-{
- struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
- struct kovaplus_device *kovaplus;
-
- if (intf->cur_altsetting->desc.bInterfaceProtocol
- == USB_INTERFACE_PROTOCOL_MOUSE) {
- kovaplus = hid_get_drvdata(hdev);
- if (kovaplus->roccat_claimed)
- roccat_disconnect(kovaplus->chrdev_minor);
- kfree(kovaplus);
- }
-}
-
-static int kovaplus_probe(struct hid_device *hdev,
- const struct hid_device_id *id)
-{
- int retval;
-
- retval = hid_parse(hdev);
- if (retval) {
- hid_err(hdev, "parse failed\n");
- goto exit;
- }
-
- retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
- if (retval) {
- hid_err(hdev, "hw start failed\n");
- goto exit;
- }
-
- retval = kovaplus_init_specials(hdev);
- if (retval) {
- hid_err(hdev, "couldn't install mouse\n");
- goto exit_stop;
- }
-
- return 0;
-
-exit_stop:
- hid_hw_stop(hdev);
-exit:
- return retval;
-}
-
-static void kovaplus_remove(struct hid_device *hdev)
-{
- kovaplus_remove_specials(hdev);
- hid_hw_stop(hdev);
-}
-
-static void kovaplus_keep_values_up_to_date(struct kovaplus_device *kovaplus,
- u8 const *data)
-{
- struct kovaplus_mouse_report_button const *button_report;
-
- if (data[0] != KOVAPLUS_MOUSE_REPORT_NUMBER_BUTTON)
- return;
-
- button_report = (struct kovaplus_mouse_report_button const *)data;
-
- switch (button_report->type) {
- case KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE_1:
- kovaplus_profile_activated(kovaplus, button_report->data1 - 1);
- break;
- case KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_CPI:
- kovaplus->actual_cpi = kovaplus_convert_event_cpi(button_report->data1);
- break;
- case KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_SENSITIVITY:
- kovaplus->actual_x_sensitivity = button_report->data1;
- kovaplus->actual_y_sensitivity = button_report->data2;
- break;
- default:
- break;
- }
-}
-
-static void kovaplus_report_to_chrdev(struct kovaplus_device const *kovaplus,
- u8 const *data)
-{
- struct kovaplus_roccat_report roccat_report;
- struct kovaplus_mouse_report_button const *button_report;
-
- if (data[0] != KOVAPLUS_MOUSE_REPORT_NUMBER_BUTTON)
- return;
-
- button_report = (struct kovaplus_mouse_report_button const *)data;
-
- if (button_report->type == KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE_2)
- return;
-
- roccat_report.type = button_report->type;
- roccat_report.profile = kovaplus->actual_profile + 1;
-
- if (roccat_report.type == KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_MACRO ||
- roccat_report.type == KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_SHORTCUT ||
- roccat_report.type == KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_QUICKLAUNCH ||
- roccat_report.type == KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_TIMER)
- roccat_report.button = button_report->data1;
- else
- roccat_report.button = 0;
-
- if (roccat_report.type == KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_CPI)
- roccat_report.data1 = kovaplus_convert_event_cpi(button_report->data1);
- else
- roccat_report.data1 = button_report->data1;
-
- roccat_report.data2 = button_report->data2;
-
- roccat_report_event(kovaplus->chrdev_minor,
- (uint8_t const *)&roccat_report);
-}
-
-static int kovaplus_raw_event(struct hid_device *hdev,
- struct hid_report *report, u8 *data, int size)
-{
- struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
- struct kovaplus_device *kovaplus = hid_get_drvdata(hdev);
-
- if (intf->cur_altsetting->desc.bInterfaceProtocol
- != USB_INTERFACE_PROTOCOL_MOUSE)
- return 0;
-
- if (kovaplus == NULL)
- return 0;
-
- kovaplus_keep_values_up_to_date(kovaplus, data);
-
- if (kovaplus->roccat_claimed)
- kovaplus_report_to_chrdev(kovaplus, data);
-
- return 0;
-}
-
-static const struct hid_device_id kovaplus_devices[] = {
- { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) },
- { }
-};
-
-MODULE_DEVICE_TABLE(hid, kovaplus_devices);
-
-static struct hid_driver kovaplus_driver = {
- .name = "kovaplus",
- .id_table = kovaplus_devices,
- .probe = kovaplus_probe,
- .remove = kovaplus_remove,
- .raw_event = kovaplus_raw_event
-};
-
-static int __init kovaplus_init(void)
-{
- int retval;
-
- kovaplus_class = class_create(THIS_MODULE, "kovaplus");
- if (IS_ERR(kovaplus_class))
- return PTR_ERR(kovaplus_class);
- kovaplus_class->dev_groups = kovaplus_groups;
-
- retval = hid_register_driver(&kovaplus_driver);
- if (retval)
- class_destroy(kovaplus_class);
- return retval;
-}
-
-static void __exit kovaplus_exit(void)
-{
- hid_unregister_driver(&kovaplus_driver);
- class_destroy(kovaplus_class);
-}
-
-module_init(kovaplus_init);
-module_exit(kovaplus_exit);
-
-MODULE_AUTHOR("Stefan Achatz");
-MODULE_DESCRIPTION("USB Roccat Kova[+] driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/hid/hid-roccat-kovaplus.h b/drivers/hid/hid-roccat-kovaplus.h
deleted file mode 100644
index fbb7a16..0000000
--- a/drivers/hid/hid-roccat-kovaplus.h
+++ /dev/null
@@ -1,133 +0,0 @@
-#ifndef __HID_ROCCAT_KOVAPLUS_H
-#define __HID_ROCCAT_KOVAPLUS_H
-
-/*
- * Copyright (c) 2010 Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-#include <linux/types.h>
-
-enum {
- KOVAPLUS_SIZE_CONTROL = 0x03,
- KOVAPLUS_SIZE_INFO = 0x06,
- KOVAPLUS_SIZE_PROFILE_SETTINGS = 0x10,
- KOVAPLUS_SIZE_PROFILE_BUTTONS = 0x17,
-};
-
-enum kovaplus_control_requests {
- /* write; value = profile number range 0-4 */
- KOVAPLUS_CONTROL_REQUEST_PROFILE_SETTINGS = 0x10,
- /* write; value = profile number range 0-4 */
- KOVAPLUS_CONTROL_REQUEST_PROFILE_BUTTONS = 0x20,
-};
-
-struct kovaplus_actual_profile {
- uint8_t command; /* KOVAPLUS_COMMAND_ACTUAL_PROFILE */
- uint8_t size; /* always 3 */
- uint8_t actual_profile; /* Range 0-4! */
-} __packed;
-
-struct kovaplus_profile_settings {
- uint8_t command; /* KOVAPLUS_COMMAND_PROFILE_SETTINGS */
- uint8_t size; /* 16 */
- uint8_t profile_index; /* range 0-4 */
- uint8_t unknown1;
- uint8_t sensitivity_x; /* range 1-10 */
- uint8_t sensitivity_y; /* range 1-10 */
- uint8_t cpi_levels_enabled;
- uint8_t cpi_startup_level; /* range 1-4 */
- uint8_t data[8];
-} __packed;
-
-struct kovaplus_profile_buttons {
- uint8_t command; /* KOVAPLUS_COMMAND_PROFILE_BUTTONS */
- uint8_t size; /* 23 */
- uint8_t profile_index; /* range 0-4 */
- uint8_t data[20];
-} __packed;
-
-struct kovaplus_info {
- uint8_t command; /* KOVAPLUS_COMMAND_INFO */
- uint8_t size; /* 6 */
- uint8_t firmware_version;
- uint8_t unknown[3];
-} __packed;
-
-enum kovaplus_commands {
- KOVAPLUS_COMMAND_ACTUAL_PROFILE = 0x5,
- KOVAPLUS_COMMAND_CONTROL = 0x4,
- KOVAPLUS_COMMAND_PROFILE_SETTINGS = 0x6,
- KOVAPLUS_COMMAND_PROFILE_BUTTONS = 0x7,
- KOVAPLUS_COMMAND_INFO = 0x9,
- KOVAPLUS_COMMAND_A = 0xa,
-};
-
-enum kovaplus_mouse_report_numbers {
- KOVAPLUS_MOUSE_REPORT_NUMBER_MOUSE = 1,
- KOVAPLUS_MOUSE_REPORT_NUMBER_AUDIO = 2,
- KOVAPLUS_MOUSE_REPORT_NUMBER_BUTTON = 3,
- KOVAPLUS_MOUSE_REPORT_NUMBER_KBD = 4,
-};
-
-struct kovaplus_mouse_report_button {
- uint8_t report_number; /* KOVAPLUS_MOUSE_REPORT_NUMBER_BUTTON */
- uint8_t unknown1;
- uint8_t type;
- uint8_t data1;
- uint8_t data2;
-} __packed;
-
-enum kovaplus_mouse_report_button_types {
- /* data1 = profile_number range 1-5; no release event */
- KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE_1 = 0x20,
- /* data1 = profile_number range 1-5; no release event */
- KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE_2 = 0x30,
- /* data1 = button_number range 1-18; data2 = action */
- KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_MACRO = 0x40,
- /* data1 = button_number range 1-18; data2 = action */
- KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_SHORTCUT = 0x50,
- /* data1 = button_number range 1-18; data2 = action */
- KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_QUICKLAUNCH = 0x60,
- /* data1 = button_number range 1-18; data2 = action */
- KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_TIMER = 0x80,
- /* data1 = 1 = 400, 2 = 800, 4 = 1600, 7 = 3200; no release event */
- KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_CPI = 0xb0,
- /* data1 + data2 = sense range 1-10; no release event */
- KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_SENSITIVITY = 0xc0,
- /* data1 = type as in profile_buttons; data2 = action */
- KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_MULTIMEDIA = 0xf0,
-};
-
-enum kovaplus_mouse_report_button_actions {
- KOVAPLUS_MOUSE_REPORT_BUTTON_ACTION_PRESS = 0,
- KOVAPLUS_MOUSE_REPORT_BUTTON_ACTION_RELEASE = 1,
-};
-
-struct kovaplus_roccat_report {
- uint8_t type;
- uint8_t profile;
- uint8_t button;
- uint8_t data1;
- uint8_t data2;
-} __packed;
-
-struct kovaplus_device {
- int actual_profile;
- int actual_cpi;
- int actual_x_sensitivity;
- int actual_y_sensitivity;
- int roccat_claimed;
- int chrdev_minor;
- struct mutex kovaplus_lock;
- struct kovaplus_profile_settings profile_settings[5];
- struct kovaplus_profile_buttons profile_buttons[5];
-};
-
-#endif
diff --git a/drivers/hid/hid-roccat-lua.c b/drivers/hid/hid-roccat-lua.c
deleted file mode 100644
index 65e2e76..0000000
--- a/drivers/hid/hid-roccat-lua.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * Roccat Lua driver for Linux
- *
- * Copyright (c) 2012 Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-/*
- * Roccat Lua is a gamer mouse which cpi, button and light settings can be
- * configured.
- */
-
-#include <linux/device.h>
-#include <linux/input.h>
-#include <linux/hid.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/hid-roccat.h>
-#include "hid-ids.h"
-#include "hid-roccat-common.h"
-#include "hid-roccat-lua.h"
-
-static ssize_t lua_sysfs_read(struct file *fp, struct kobject *kobj,
- char *buf, loff_t off, size_t count,
- size_t real_size, uint command)
-{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct lua_device *lua = hid_get_drvdata(dev_get_drvdata(dev));
- struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
- int retval;
-
- if (off >= real_size)
- return 0;
-
- if (off != 0 || count != real_size)
- return -EINVAL;
-
- mutex_lock(&lua->lua_lock);
- retval = roccat_common2_receive(usb_dev, command, buf, real_size);
- mutex_unlock(&lua->lua_lock);
-
- return retval ? retval : real_size;
-}
-
-static ssize_t lua_sysfs_write(struct file *fp, struct kobject *kobj,
- void const *buf, loff_t off, size_t count,
- size_t real_size, uint command)
-{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct lua_device *lua = hid_get_drvdata(dev_get_drvdata(dev));
- struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
- int retval;
-
- if (off != 0 || count != real_size)
- return -EINVAL;
-
- mutex_lock(&lua->lua_lock);
- retval = roccat_common2_send(usb_dev, command, buf, real_size);
- mutex_unlock(&lua->lua_lock);
-
- return retval ? retval : real_size;
-}
-
-#define LUA_SYSFS_W(thingy, THINGY) \
-static ssize_t lua_sysfs_write_ ## thingy(struct file *fp, \
- struct kobject *kobj, struct bin_attribute *attr, \
- char *buf, loff_t off, size_t count) \
-{ \
- return lua_sysfs_write(fp, kobj, buf, off, count, \
- LUA_SIZE_ ## THINGY, LUA_COMMAND_ ## THINGY); \
-}
-
-#define LUA_SYSFS_R(thingy, THINGY) \
-static ssize_t lua_sysfs_read_ ## thingy(struct file *fp, \
- struct kobject *kobj, struct bin_attribute *attr, \
- char *buf, loff_t off, size_t count) \
-{ \
- return lua_sysfs_read(fp, kobj, buf, off, count, \
- LUA_SIZE_ ## THINGY, LUA_COMMAND_ ## THINGY); \
-}
-
-#define LUA_BIN_ATTRIBUTE_RW(thingy, THINGY) \
-LUA_SYSFS_W(thingy, THINGY) \
-LUA_SYSFS_R(thingy, THINGY) \
-static struct bin_attribute lua_ ## thingy ## _attr = { \
- .attr = { .name = #thingy, .mode = 0660 }, \
- .size = LUA_SIZE_ ## THINGY, \
- .read = lua_sysfs_read_ ## thingy, \
- .write = lua_sysfs_write_ ## thingy \
-};
-
-LUA_BIN_ATTRIBUTE_RW(control, CONTROL)
-
-static int lua_create_sysfs_attributes(struct usb_interface *intf)
-{
- return sysfs_create_bin_file(&intf->dev.kobj, &lua_control_attr);
-}
-
-static void lua_remove_sysfs_attributes(struct usb_interface *intf)
-{
- sysfs_remove_bin_file(&intf->dev.kobj, &lua_control_attr);
-}
-
-static int lua_init_lua_device_struct(struct usb_device *usb_dev,
- struct lua_device *lua)
-{
- mutex_init(&lua->lua_lock);
-
- return 0;
-}
-
-static int lua_init_specials(struct hid_device *hdev)
-{
- struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
- struct usb_device *usb_dev = interface_to_usbdev(intf);
- struct lua_device *lua;
- int retval;
-
- lua = kzalloc(sizeof(*lua), GFP_KERNEL);
- if (!lua) {
- hid_err(hdev, "can't alloc device descriptor\n");
- return -ENOMEM;
- }
- hid_set_drvdata(hdev, lua);
-
- retval = lua_init_lua_device_struct(usb_dev, lua);
- if (retval) {
- hid_err(hdev, "couldn't init struct lua_device\n");
- goto exit;
- }
-
- retval = lua_create_sysfs_attributes(intf);
- if (retval) {
- hid_err(hdev, "cannot create sysfs files\n");
- goto exit;
- }
-
- return 0;
-exit:
- kfree(lua);
- return retval;
-}
-
-static void lua_remove_specials(struct hid_device *hdev)
-{
- struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
- struct lua_device *lua;
-
- lua_remove_sysfs_attributes(intf);
-
- lua = hid_get_drvdata(hdev);
- kfree(lua);
-}
-
-static int lua_probe(struct hid_device *hdev,
- const struct hid_device_id *id)
-{
- int retval;
-
- retval = hid_parse(hdev);
- if (retval) {
- hid_err(hdev, "parse failed\n");
- goto exit;
- }
-
- retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
- if (retval) {
- hid_err(hdev, "hw start failed\n");
- goto exit;
- }
-
- retval = lua_init_specials(hdev);
- if (retval) {
- hid_err(hdev, "couldn't install mouse\n");
- goto exit_stop;
- }
-
- return 0;
-
-exit_stop:
- hid_hw_stop(hdev);
-exit:
- return retval;
-}
-
-static void lua_remove(struct hid_device *hdev)
-{
- lua_remove_specials(hdev);
- hid_hw_stop(hdev);
-}
-
-static const struct hid_device_id lua_devices[] = {
- { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_LUA) },
- { }
-};
-
-MODULE_DEVICE_TABLE(hid, lua_devices);
-
-static struct hid_driver lua_driver = {
- .name = "lua",
- .id_table = lua_devices,
- .probe = lua_probe,
- .remove = lua_remove
-};
-module_hid_driver(lua_driver);
-
-MODULE_AUTHOR("Stefan Achatz");
-MODULE_DESCRIPTION("USB Roccat Lua driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/hid/hid-roccat-lua.h b/drivers/hid/hid-roccat-lua.h
deleted file mode 100644
index 547d77a..0000000
--- a/drivers/hid/hid-roccat-lua.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef __HID_ROCCAT_LUA_H
-#define __HID_ROCCAT_LUA_H
-
-/*
- * Copyright (c) 2012 Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-#include <linux/types.h>
-
-enum {
- LUA_SIZE_CONTROL = 8,
-};
-
-enum lua_commands {
- LUA_COMMAND_CONTROL = 3,
-};
-
-struct lua_device {
- struct mutex lua_lock;
-};
-
-#endif
diff --git a/drivers/hid/hid-roccat-pyra.c b/drivers/hid/hid-roccat-pyra.c
deleted file mode 100644
index 47d7e74..0000000
--- a/drivers/hid/hid-roccat-pyra.c
+++ /dev/null
@@ -1,615 +0,0 @@
-/*
- * Roccat Pyra driver for Linux
- *
- * Copyright (c) 2010 Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-/*
- * Roccat Pyra is a mobile gamer mouse which comes in wired and wireless
- * variant. Wireless variant is not tested.
- * Userland tools can be found at http://sourceforge.net/projects/roccat
- */
-
-#include <linux/device.h>
-#include <linux/input.h>
-#include <linux/hid.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/hid-roccat.h>
-#include "hid-ids.h"
-#include "hid-roccat-common.h"
-#include "hid-roccat-pyra.h"
-
-static uint profile_numbers[5] = {0, 1, 2, 3, 4};
-
-/* pyra_class is used for creating sysfs attributes via roccat char device */
-static struct class *pyra_class;
-
-static void profile_activated(struct pyra_device *pyra,
- unsigned int new_profile)
-{
- if (new_profile >= ARRAY_SIZE(pyra->profile_settings))
- return;
- pyra->actual_profile = new_profile;
- pyra->actual_cpi = pyra->profile_settings[pyra->actual_profile].y_cpi;
-}
-
-static int pyra_send_control(struct usb_device *usb_dev, int value,
- enum pyra_control_requests request)
-{
- struct roccat_common2_control control;
-
- if ((request == PYRA_CONTROL_REQUEST_PROFILE_SETTINGS ||
- request == PYRA_CONTROL_REQUEST_PROFILE_BUTTONS) &&
- (value < 0 || value > 4))
- return -EINVAL;
-
- control.command = ROCCAT_COMMON_COMMAND_CONTROL;
- control.value = value;
- control.request = request;
-
- return roccat_common2_send(usb_dev, ROCCAT_COMMON_COMMAND_CONTROL,
- &control, sizeof(struct roccat_common2_control));
-}
-
-static int pyra_get_profile_settings(struct usb_device *usb_dev,
- struct pyra_profile_settings *buf, int number)
-{
- int retval;
- retval = pyra_send_control(usb_dev, number,
- PYRA_CONTROL_REQUEST_PROFILE_SETTINGS);
- if (retval)
- return retval;
- return roccat_common2_receive(usb_dev, PYRA_COMMAND_PROFILE_SETTINGS,
- buf, PYRA_SIZE_PROFILE_SETTINGS);
-}
-
-static int pyra_get_settings(struct usb_device *usb_dev,
- struct pyra_settings *buf)
-{
- return roccat_common2_receive(usb_dev, PYRA_COMMAND_SETTINGS,
- buf, PYRA_SIZE_SETTINGS);
-}
-
-static int pyra_set_settings(struct usb_device *usb_dev,
- struct pyra_settings const *settings)
-{
- return roccat_common2_send_with_status(usb_dev,
- PYRA_COMMAND_SETTINGS, settings,
- PYRA_SIZE_SETTINGS);
-}
-
-static ssize_t pyra_sysfs_read(struct file *fp, struct kobject *kobj,
- char *buf, loff_t off, size_t count,
- size_t real_size, uint command)
-{
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
- struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
- struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
- int retval;
-
- if (off >= real_size)
- return 0;
-
- if (off != 0 || count != real_size)
- return -EINVAL;
-
- mutex_lock(&pyra->pyra_lock);
- retval = roccat_common2_receive(usb_dev, command, buf, real_size);
- mutex_unlock(&pyra->pyra_lock);
-
- if (retval)
- return retval;
-
- return real_size;
-}
-
-static ssize_t pyra_sysfs_write(struct file *fp, struct kobject *kobj,
- void const *buf, loff_t off, size_t count,
- size_t real_size, uint command)
-{
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
- struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
- struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
- int retval;
-
- if (off != 0 || count != real_size)
- return -EINVAL;
-
- mutex_lock(&pyra->pyra_lock);
- retval = roccat_common2_send_with_status(usb_dev, command, (void *)buf, real_size);
- mutex_unlock(&pyra->pyra_lock);
-
- if (retval)
- return retval;
-
- return real_size;
-}
-
-#define PYRA_SYSFS_W(thingy, THINGY) \
-static ssize_t pyra_sysfs_write_ ## thingy(struct file *fp, \
- struct kobject *kobj, struct bin_attribute *attr, char *buf, \
- loff_t off, size_t count) \
-{ \
- return pyra_sysfs_write(fp, kobj, buf, off, count, \
- PYRA_SIZE_ ## THINGY, PYRA_COMMAND_ ## THINGY); \
-}
-
-#define PYRA_SYSFS_R(thingy, THINGY) \
-static ssize_t pyra_sysfs_read_ ## thingy(struct file *fp, \
- struct kobject *kobj, struct bin_attribute *attr, char *buf, \
- loff_t off, size_t count) \
-{ \
- return pyra_sysfs_read(fp, kobj, buf, off, count, \
- PYRA_SIZE_ ## THINGY, PYRA_COMMAND_ ## THINGY); \
-}
-
-#define PYRA_SYSFS_RW(thingy, THINGY) \
-PYRA_SYSFS_W(thingy, THINGY) \
-PYRA_SYSFS_R(thingy, THINGY)
-
-#define PYRA_BIN_ATTRIBUTE_RW(thingy, THINGY) \
-PYRA_SYSFS_RW(thingy, THINGY); \
-static struct bin_attribute bin_attr_##thingy = { \
- .attr = { .name = #thingy, .mode = 0660 }, \
- .size = PYRA_SIZE_ ## THINGY, \
- .read = pyra_sysfs_read_ ## thingy, \
- .write = pyra_sysfs_write_ ## thingy \
-}
-
-#define PYRA_BIN_ATTRIBUTE_R(thingy, THINGY) \
-PYRA_SYSFS_R(thingy, THINGY); \
-static struct bin_attribute bin_attr_##thingy = { \
- .attr = { .name = #thingy, .mode = 0440 }, \
- .size = PYRA_SIZE_ ## THINGY, \
- .read = pyra_sysfs_read_ ## thingy, \
-}
-
-#define PYRA_BIN_ATTRIBUTE_W(thingy, THINGY) \
-PYRA_SYSFS_W(thingy, THINGY); \
-static struct bin_attribute bin_attr_##thingy = { \
- .attr = { .name = #thingy, .mode = 0220 }, \
- .size = PYRA_SIZE_ ## THINGY, \
- .write = pyra_sysfs_write_ ## thingy \
-}
-
-PYRA_BIN_ATTRIBUTE_W(control, CONTROL);
-PYRA_BIN_ATTRIBUTE_RW(info, INFO);
-PYRA_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS);
-PYRA_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS);
-
-static ssize_t pyra_sysfs_read_profilex_settings(struct file *fp,
- struct kobject *kobj, struct bin_attribute *attr, char *buf,
- loff_t off, size_t count)
-{
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
- struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
- ssize_t retval;
-
- retval = pyra_send_control(usb_dev, *(uint *)(attr->private),
- PYRA_CONTROL_REQUEST_PROFILE_SETTINGS);
- if (retval)
- return retval;
-
- return pyra_sysfs_read(fp, kobj, buf, off, count,
- PYRA_SIZE_PROFILE_SETTINGS,
- PYRA_COMMAND_PROFILE_SETTINGS);
-}
-
-static ssize_t pyra_sysfs_read_profilex_buttons(struct file *fp,
- struct kobject *kobj, struct bin_attribute *attr, char *buf,
- loff_t off, size_t count)
-{
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
- struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
- ssize_t retval;
-
- retval = pyra_send_control(usb_dev, *(uint *)(attr->private),
- PYRA_CONTROL_REQUEST_PROFILE_BUTTONS);
- if (retval)
- return retval;
-
- return pyra_sysfs_read(fp, kobj, buf, off, count,
- PYRA_SIZE_PROFILE_BUTTONS,
- PYRA_COMMAND_PROFILE_BUTTONS);
-}
-
-#define PROFILE_ATTR(number) \
-static struct bin_attribute bin_attr_profile##number##_settings = { \
- .attr = { .name = "profile" #number "_settings", .mode = 0440 }, \
- .size = PYRA_SIZE_PROFILE_SETTINGS, \
- .read = pyra_sysfs_read_profilex_settings, \
- .private = &profile_numbers[number-1], \
-}; \
-static struct bin_attribute bin_attr_profile##number##_buttons = { \
- .attr = { .name = "profile" #number "_buttons", .mode = 0440 }, \
- .size = PYRA_SIZE_PROFILE_BUTTONS, \
- .read = pyra_sysfs_read_profilex_buttons, \
- .private = &profile_numbers[number-1], \
-};
-PROFILE_ATTR(1);
-PROFILE_ATTR(2);
-PROFILE_ATTR(3);
-PROFILE_ATTR(4);
-PROFILE_ATTR(5);
-
-static ssize_t pyra_sysfs_write_settings(struct file *fp,
- struct kobject *kobj, struct bin_attribute *attr, char *buf,
- loff_t off, size_t count)
-{
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
- struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
- struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
- int retval = 0;
- struct pyra_roccat_report roccat_report;
- struct pyra_settings const *settings;
-
- if (off != 0 || count != PYRA_SIZE_SETTINGS)
- return -EINVAL;
-
- settings = (struct pyra_settings const *)buf;
- if (settings->startup_profile >= ARRAY_SIZE(pyra->profile_settings))
- return -EINVAL;
-
- mutex_lock(&pyra->pyra_lock);
-
- retval = pyra_set_settings(usb_dev, settings);
- if (retval) {
- mutex_unlock(&pyra->pyra_lock);
- return retval;
- }
-
- profile_activated(pyra, settings->startup_profile);
-
- roccat_report.type = PYRA_MOUSE_EVENT_BUTTON_TYPE_PROFILE_2;
- roccat_report.value = settings->startup_profile + 1;
- roccat_report.key = 0;
- roccat_report_event(pyra->chrdev_minor,
- (uint8_t const *)&roccat_report);
-
- mutex_unlock(&pyra->pyra_lock);
- return PYRA_SIZE_SETTINGS;
-}
-
-PYRA_SYSFS_R(settings, SETTINGS);
-static struct bin_attribute bin_attr_settings =
- __BIN_ATTR(settings, (S_IWUSR | S_IRUGO),
- pyra_sysfs_read_settings, pyra_sysfs_write_settings,
- PYRA_SIZE_SETTINGS);
-
-static ssize_t pyra_sysfs_show_actual_cpi(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct pyra_device *pyra =
- hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
- return snprintf(buf, PAGE_SIZE, "%d\n", pyra->actual_cpi);
-}
-static DEVICE_ATTR(actual_cpi, 0440, pyra_sysfs_show_actual_cpi, NULL);
-
-static ssize_t pyra_sysfs_show_actual_profile(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct pyra_device *pyra =
- hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
- struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
- struct pyra_settings settings;
-
- mutex_lock(&pyra->pyra_lock);
- roccat_common2_receive(usb_dev, PYRA_COMMAND_SETTINGS,
- &settings, PYRA_SIZE_SETTINGS);
- mutex_unlock(&pyra->pyra_lock);
-
- return snprintf(buf, PAGE_SIZE, "%d\n", settings.startup_profile);
-}
-static DEVICE_ATTR(actual_profile, 0440, pyra_sysfs_show_actual_profile, NULL);
-static DEVICE_ATTR(startup_profile, 0440, pyra_sysfs_show_actual_profile, NULL);
-
-static ssize_t pyra_sysfs_show_firmware_version(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct pyra_device *pyra;
- struct usb_device *usb_dev;
- struct pyra_info info;
-
- dev = dev->parent->parent;
- pyra = hid_get_drvdata(dev_get_drvdata(dev));
- usb_dev = interface_to_usbdev(to_usb_interface(dev));
-
- mutex_lock(&pyra->pyra_lock);
- roccat_common2_receive(usb_dev, PYRA_COMMAND_INFO,
- &info, PYRA_SIZE_INFO);
- mutex_unlock(&pyra->pyra_lock);
-
- return snprintf(buf, PAGE_SIZE, "%d\n", info.firmware_version);
-}
-static DEVICE_ATTR(firmware_version, 0440, pyra_sysfs_show_firmware_version,
- NULL);
-
-static struct attribute *pyra_attrs[] = {
- &dev_attr_actual_cpi.attr,
- &dev_attr_actual_profile.attr,
- &dev_attr_firmware_version.attr,
- &dev_attr_startup_profile.attr,
- NULL,
-};
-
-static struct bin_attribute *pyra_bin_attributes[] = {
- &bin_attr_control,
- &bin_attr_info,
- &bin_attr_profile_settings,
- &bin_attr_profile_buttons,
- &bin_attr_settings,
- &bin_attr_profile1_settings,
- &bin_attr_profile2_settings,
- &bin_attr_profile3_settings,
- &bin_attr_profile4_settings,
- &bin_attr_profile5_settings,
- &bin_attr_profile1_buttons,
- &bin_attr_profile2_buttons,
- &bin_attr_profile3_buttons,
- &bin_attr_profile4_buttons,
- &bin_attr_profile5_buttons,
- NULL,
-};
-
-static const struct attribute_group pyra_group = {
- .attrs = pyra_attrs,
- .bin_attrs = pyra_bin_attributes,
-};
-
-static const struct attribute_group *pyra_groups[] = {
- &pyra_group,
- NULL,
-};
-
-static int pyra_init_pyra_device_struct(struct usb_device *usb_dev,
- struct pyra_device *pyra)
-{
- struct pyra_settings settings;
- int retval, i;
-
- mutex_init(&pyra->pyra_lock);
-
- retval = pyra_get_settings(usb_dev, &settings);
- if (retval)
- return retval;
-
- for (i = 0; i < 5; ++i) {
- retval = pyra_get_profile_settings(usb_dev,
- &pyra->profile_settings[i], i);
- if (retval)
- return retval;
- }
-
- profile_activated(pyra, settings.startup_profile);
-
- return 0;
-}
-
-static int pyra_init_specials(struct hid_device *hdev)
-{
- struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
- struct usb_device *usb_dev = interface_to_usbdev(intf);
- struct pyra_device *pyra;
- int retval;
-
- if (intf->cur_altsetting->desc.bInterfaceProtocol
- == USB_INTERFACE_PROTOCOL_MOUSE) {
-
- pyra = kzalloc(sizeof(*pyra), GFP_KERNEL);
- if (!pyra) {
- hid_err(hdev, "can't alloc device descriptor\n");
- return -ENOMEM;
- }
- hid_set_drvdata(hdev, pyra);
-
- retval = pyra_init_pyra_device_struct(usb_dev, pyra);
- if (retval) {
- hid_err(hdev, "couldn't init struct pyra_device\n");
- goto exit_free;
- }
-
- retval = roccat_connect(pyra_class, hdev,
- sizeof(struct pyra_roccat_report));
- if (retval < 0) {
- hid_err(hdev, "couldn't init char dev\n");
- } else {
- pyra->chrdev_minor = retval;
- pyra->roccat_claimed = 1;
- }
- } else {
- hid_set_drvdata(hdev, NULL);
- }
-
- return 0;
-exit_free:
- kfree(pyra);
- return retval;
-}
-
-static void pyra_remove_specials(struct hid_device *hdev)
-{
- struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
- struct pyra_device *pyra;
-
- if (intf->cur_altsetting->desc.bInterfaceProtocol
- == USB_INTERFACE_PROTOCOL_MOUSE) {
- pyra = hid_get_drvdata(hdev);
- if (pyra->roccat_claimed)
- roccat_disconnect(pyra->chrdev_minor);
- kfree(hid_get_drvdata(hdev));
- }
-}
-
-static int pyra_probe(struct hid_device *hdev, const struct hid_device_id *id)
-{
- int retval;
-
- retval = hid_parse(hdev);
- if (retval) {
- hid_err(hdev, "parse failed\n");
- goto exit;
- }
-
- retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
- if (retval) {
- hid_err(hdev, "hw start failed\n");
- goto exit;
- }
-
- retval = pyra_init_specials(hdev);
- if (retval) {
- hid_err(hdev, "couldn't install mouse\n");
- goto exit_stop;
- }
- return 0;
-
-exit_stop:
- hid_hw_stop(hdev);
-exit:
- return retval;
-}
-
-static void pyra_remove(struct hid_device *hdev)
-{
- pyra_remove_specials(hdev);
- hid_hw_stop(hdev);
-}
-
-static void pyra_keep_values_up_to_date(struct pyra_device *pyra,
- u8 const *data)
-{
- struct pyra_mouse_event_button const *button_event;
-
- switch (data[0]) {
- case PYRA_MOUSE_REPORT_NUMBER_BUTTON:
- button_event = (struct pyra_mouse_event_button const *)data;
- switch (button_event->type) {
- case PYRA_MOUSE_EVENT_BUTTON_TYPE_PROFILE_2:
- profile_activated(pyra, button_event->data1 - 1);
- break;
- case PYRA_MOUSE_EVENT_BUTTON_TYPE_CPI:
- pyra->actual_cpi = button_event->data1;
- break;
- }
- break;
- }
-}
-
-static void pyra_report_to_chrdev(struct pyra_device const *pyra,
- u8 const *data)
-{
- struct pyra_roccat_report roccat_report;
- struct pyra_mouse_event_button const *button_event;
-
- if (data[0] != PYRA_MOUSE_REPORT_NUMBER_BUTTON)
- return;
-
- button_event = (struct pyra_mouse_event_button const *)data;
-
- switch (button_event->type) {
- case PYRA_MOUSE_EVENT_BUTTON_TYPE_PROFILE_2:
- case PYRA_MOUSE_EVENT_BUTTON_TYPE_CPI:
- roccat_report.type = button_event->type;
- roccat_report.value = button_event->data1;
- roccat_report.key = 0;
- roccat_report_event(pyra->chrdev_minor,
- (uint8_t const *)&roccat_report);
- break;
- case PYRA_MOUSE_EVENT_BUTTON_TYPE_MACRO:
- case PYRA_MOUSE_EVENT_BUTTON_TYPE_SHORTCUT:
- case PYRA_MOUSE_EVENT_BUTTON_TYPE_QUICKLAUNCH:
- if (button_event->data2 == PYRA_MOUSE_EVENT_BUTTON_PRESS) {
- roccat_report.type = button_event->type;
- roccat_report.key = button_event->data1;
- /*
- * pyra reports profile numbers with range 1-5.
- * Keeping this behaviour.
- */
- roccat_report.value = pyra->actual_profile + 1;
- roccat_report_event(pyra->chrdev_minor,
- (uint8_t const *)&roccat_report);
- }
- break;
- }
-}
-
-static int pyra_raw_event(struct hid_device *hdev, struct hid_report *report,
- u8 *data, int size)
-{
- struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
- struct pyra_device *pyra = hid_get_drvdata(hdev);
-
- if (intf->cur_altsetting->desc.bInterfaceProtocol
- != USB_INTERFACE_PROTOCOL_MOUSE)
- return 0;
-
- if (pyra == NULL)
- return 0;
-
- pyra_keep_values_up_to_date(pyra, data);
-
- if (pyra->roccat_claimed)
- pyra_report_to_chrdev(pyra, data);
-
- return 0;
-}
-
-static const struct hid_device_id pyra_devices[] = {
- { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT,
- USB_DEVICE_ID_ROCCAT_PYRA_WIRED) },
- { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT,
- USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS) },
- { }
-};
-
-MODULE_DEVICE_TABLE(hid, pyra_devices);
-
-static struct hid_driver pyra_driver = {
- .name = "pyra",
- .id_table = pyra_devices,
- .probe = pyra_probe,
- .remove = pyra_remove,
- .raw_event = pyra_raw_event
-};
-
-static int __init pyra_init(void)
-{
- int retval;
-
- /* class name has to be same as driver name */
- pyra_class = class_create(THIS_MODULE, "pyra");
- if (IS_ERR(pyra_class))
- return PTR_ERR(pyra_class);
- pyra_class->dev_groups = pyra_groups;
-
- retval = hid_register_driver(&pyra_driver);
- if (retval)
- class_destroy(pyra_class);
- return retval;
-}
-
-static void __exit pyra_exit(void)
-{
- hid_unregister_driver(&pyra_driver);
- class_destroy(pyra_class);
-}
-
-module_init(pyra_init);
-module_exit(pyra_exit);
-
-MODULE_AUTHOR("Stefan Achatz");
-MODULE_DESCRIPTION("USB Roccat Pyra driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/hid/hid-roccat-pyra.h b/drivers/hid/hid-roccat-pyra.h
deleted file mode 100644
index beedcf0..0000000
--- a/drivers/hid/hid-roccat-pyra.h
+++ /dev/null
@@ -1,152 +0,0 @@
-#ifndef __HID_ROCCAT_PYRA_H
-#define __HID_ROCCAT_PYRA_H
-
-/*
- * Copyright (c) 2010 Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-#include <linux/types.h>
-
-enum {
- PYRA_SIZE_CONTROL = 0x03,
- PYRA_SIZE_INFO = 0x06,
- PYRA_SIZE_PROFILE_SETTINGS = 0x0d,
- PYRA_SIZE_PROFILE_BUTTONS = 0x13,
- PYRA_SIZE_SETTINGS = 0x03,
-};
-
-enum pyra_control_requests {
- PYRA_CONTROL_REQUEST_PROFILE_SETTINGS = 0x10,
- PYRA_CONTROL_REQUEST_PROFILE_BUTTONS = 0x20
-};
-
-struct pyra_settings {
- uint8_t command; /* PYRA_COMMAND_SETTINGS */
- uint8_t size; /* always 3 */
- uint8_t startup_profile; /* Range 0-4! */
-} __attribute__ ((__packed__));
-
-struct pyra_profile_settings {
- uint8_t command; /* PYRA_COMMAND_PROFILE_SETTINGS */
- uint8_t size; /* always 0xd */
- uint8_t number; /* Range 0-4 */
- uint8_t xysync;
- uint8_t x_sensitivity; /* 0x1-0xa */
- uint8_t y_sensitivity;
- uint8_t x_cpi; /* unused */
- uint8_t y_cpi; /* this value is for x and y */
- uint8_t lightswitch; /* 0 = off, 1 = on */
- uint8_t light_effect;
- uint8_t handedness;
- uint16_t checksum; /* byte sum */
-} __attribute__ ((__packed__));
-
-struct pyra_info {
- uint8_t command; /* PYRA_COMMAND_INFO */
- uint8_t size; /* always 6 */
- uint8_t firmware_version;
- uint8_t unknown1; /* always 0 */
- uint8_t unknown2; /* always 1 */
- uint8_t unknown3; /* always 0 */
-} __attribute__ ((__packed__));
-
-enum pyra_commands {
- PYRA_COMMAND_CONTROL = 0x4,
- PYRA_COMMAND_SETTINGS = 0x5,
- PYRA_COMMAND_PROFILE_SETTINGS = 0x6,
- PYRA_COMMAND_PROFILE_BUTTONS = 0x7,
- PYRA_COMMAND_INFO = 0x9,
- PYRA_COMMAND_B = 0xb
-};
-
-enum pyra_mouse_report_numbers {
- PYRA_MOUSE_REPORT_NUMBER_HID = 1,
- PYRA_MOUSE_REPORT_NUMBER_AUDIO = 2,
- PYRA_MOUSE_REPORT_NUMBER_BUTTON = 3,
-};
-
-struct pyra_mouse_event_button {
- uint8_t report_number; /* always 3 */
- uint8_t unknown; /* always 0 */
- uint8_t type;
- uint8_t data1;
- uint8_t data2;
-} __attribute__ ((__packed__));
-
-struct pyra_mouse_event_audio {
- uint8_t report_number; /* always 2 */
- uint8_t type;
- uint8_t unused; /* always 0 */
-} __attribute__ ((__packed__));
-
-/* hid audio controls */
-enum pyra_mouse_event_audio_types {
- PYRA_MOUSE_EVENT_AUDIO_TYPE_MUTE = 0xe2,
- PYRA_MOUSE_EVENT_AUDIO_TYPE_VOLUME_UP = 0xe9,
- PYRA_MOUSE_EVENT_AUDIO_TYPE_VOLUME_DOWN = 0xea,
-};
-
-enum pyra_mouse_event_button_types {
- /*
- * Mouse sends tilt events on report_number 1 and 3
- * Tilt events are sent repeatedly with 0.94s between first and second
- * event and 0.22s on subsequent
- */
- PYRA_MOUSE_EVENT_BUTTON_TYPE_TILT = 0x10,
-
- /*
- * These are sent sequentially
- * data1 contains new profile number in range 1-5
- */
- PYRA_MOUSE_EVENT_BUTTON_TYPE_PROFILE_1 = 0x20,
- PYRA_MOUSE_EVENT_BUTTON_TYPE_PROFILE_2 = 0x30,
-
- /*
- * data1 = button_number (rmp index)
- * data2 = pressed/released
- */
- PYRA_MOUSE_EVENT_BUTTON_TYPE_MACRO = 0x40,
- PYRA_MOUSE_EVENT_BUTTON_TYPE_SHORTCUT = 0x50,
-
- /*
- * data1 = button_number (rmp index)
- */
- PYRA_MOUSE_EVENT_BUTTON_TYPE_QUICKLAUNCH = 0x60,
-
- /* data1 = new cpi */
- PYRA_MOUSE_EVENT_BUTTON_TYPE_CPI = 0xb0,
-
- /* data1 and data2 = new sensitivity */
- PYRA_MOUSE_EVENT_BUTTON_TYPE_SENSITIVITY = 0xc0,
-
- PYRA_MOUSE_EVENT_BUTTON_TYPE_MULTIMEDIA = 0xf0,
-};
-
-enum {
- PYRA_MOUSE_EVENT_BUTTON_PRESS = 0,
- PYRA_MOUSE_EVENT_BUTTON_RELEASE = 1,
-};
-
-struct pyra_roccat_report {
- uint8_t type;
- uint8_t value;
- uint8_t key;
-} __attribute__ ((__packed__));
-
-struct pyra_device {
- int actual_profile;
- int actual_cpi;
- int roccat_claimed;
- int chrdev_minor;
- struct mutex pyra_lock;
- struct pyra_profile_settings profile_settings[5];
-};
-
-#endif
diff --git a/drivers/hid/hid-roccat-ryos.c b/drivers/hid/hid-roccat-ryos.c
deleted file mode 100644
index 47cc8f3..0000000
--- a/drivers/hid/hid-roccat-ryos.c
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Roccat Ryos driver for Linux
- *
- * Copyright (c) 2013 Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-#include <linux/types.h>
-#include <linux/device.h>
-#include <linux/input.h>
-#include <linux/hid.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/hid-roccat.h>
-#include "hid-ids.h"
-#include "hid-roccat-common.h"
-
-enum {
- RYOS_REPORT_NUMBER_SPECIAL = 3,
- RYOS_USB_INTERFACE_PROTOCOL = 0,
-};
-
-struct ryos_report_special {
- uint8_t number; /* RYOS_REPORT_NUMBER_SPECIAL */
- uint8_t data[4];
-} __packed;
-
-static struct class *ryos_class;
-
-ROCCAT_COMMON2_BIN_ATTRIBUTE_W(control, 0x04, 0x03);
-ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(profile, 0x05, 0x03);
-ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(keys_primary, 0x06, 0x7d);
-ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(keys_function, 0x07, 0x5f);
-ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(keys_macro, 0x08, 0x23);
-ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(keys_thumbster, 0x09, 0x17);
-ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(keys_extra, 0x0a, 0x08);
-ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(keys_easyzone, 0x0b, 0x126);
-ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(key_mask, 0x0c, 0x06);
-ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(light, 0x0d, 0x10);
-ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(macro, 0x0e, 0x7d2);
-ROCCAT_COMMON2_BIN_ATTRIBUTE_R(info, 0x0f, 0x08);
-ROCCAT_COMMON2_BIN_ATTRIBUTE_W(reset, 0x11, 0x03);
-ROCCAT_COMMON2_BIN_ATTRIBUTE_W(light_control, 0x13, 0x08);
-ROCCAT_COMMON2_BIN_ATTRIBUTE_W(talk, 0x16, 0x10);
-ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(stored_lights, 0x17, 0x0566);
-ROCCAT_COMMON2_BIN_ATTRIBUTE_W(custom_lights, 0x18, 0x14);
-ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(light_macro, 0x19, 0x07d2);
-
-static struct bin_attribute *ryos_bin_attrs[] = {
- &bin_attr_control,
- &bin_attr_profile,
- &bin_attr_keys_primary,
- &bin_attr_keys_function,
- &bin_attr_keys_macro,
- &bin_attr_keys_thumbster,
- &bin_attr_keys_extra,
- &bin_attr_keys_easyzone,
- &bin_attr_key_mask,
- &bin_attr_light,
- &bin_attr_macro,
- &bin_attr_info,
- &bin_attr_reset,
- &bin_attr_light_control,
- &bin_attr_talk,
- &bin_attr_stored_lights,
- &bin_attr_custom_lights,
- &bin_attr_light_macro,
- NULL,
-};
-
-static const struct attribute_group ryos_group = {
- .bin_attrs = ryos_bin_attrs,
-};
-
-static const struct attribute_group *ryos_groups[] = {
- &ryos_group,
- NULL,
-};
-
-static int ryos_init_specials(struct hid_device *hdev)
-{
- struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
- struct usb_device *usb_dev = interface_to_usbdev(intf);
- struct roccat_common2_device *ryos;
- int retval;
-
- if (intf->cur_altsetting->desc.bInterfaceProtocol
- != RYOS_USB_INTERFACE_PROTOCOL) {
- hid_set_drvdata(hdev, NULL);
- return 0;
- }
-
- ryos = kzalloc(sizeof(*ryos), GFP_KERNEL);
- if (!ryos) {
- hid_err(hdev, "can't alloc device descriptor\n");
- return -ENOMEM;
- }
- hid_set_drvdata(hdev, ryos);
-
- retval = roccat_common2_device_init_struct(usb_dev, ryos);
- if (retval) {
- hid_err(hdev, "couldn't init Ryos device\n");
- goto exit_free;
- }
-
- retval = roccat_connect(ryos_class, hdev,
- sizeof(struct ryos_report_special));
- if (retval < 0) {
- hid_err(hdev, "couldn't init char dev\n");
- } else {
- ryos->chrdev_minor = retval;
- ryos->roccat_claimed = 1;
- }
-
- return 0;
-exit_free:
- kfree(ryos);
- return retval;
-}
-
-static void ryos_remove_specials(struct hid_device *hdev)
-{
- struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
- struct roccat_common2_device *ryos;
-
- if (intf->cur_altsetting->desc.bInterfaceProtocol
- != RYOS_USB_INTERFACE_PROTOCOL)
- return;
-
- ryos = hid_get_drvdata(hdev);
- if (ryos->roccat_claimed)
- roccat_disconnect(ryos->chrdev_minor);
- kfree(ryos);
-}
-
-static int ryos_probe(struct hid_device *hdev,
- const struct hid_device_id *id)
-{
- int retval;
-
- retval = hid_parse(hdev);
- if (retval) {
- hid_err(hdev, "parse failed\n");
- goto exit;
- }
-
- retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
- if (retval) {
- hid_err(hdev, "hw start failed\n");
- goto exit;
- }
-
- retval = ryos_init_specials(hdev);
- if (retval) {
- hid_err(hdev, "couldn't install mouse\n");
- goto exit_stop;
- }
-
- return 0;
-
-exit_stop:
- hid_hw_stop(hdev);
-exit:
- return retval;
-}
-
-static void ryos_remove(struct hid_device *hdev)
-{
- ryos_remove_specials(hdev);
- hid_hw_stop(hdev);
-}
-
-static int ryos_raw_event(struct hid_device *hdev,
- struct hid_report *report, u8 *data, int size)
-{
- struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
- struct roccat_common2_device *ryos = hid_get_drvdata(hdev);
-
- if (intf->cur_altsetting->desc.bInterfaceProtocol
- != RYOS_USB_INTERFACE_PROTOCOL)
- return 0;
-
- if (data[0] != RYOS_REPORT_NUMBER_SPECIAL)
- return 0;
-
- if (ryos != NULL && ryos->roccat_claimed)
- roccat_report_event(ryos->chrdev_minor, data);
-
- return 0;
-}
-
-static const struct hid_device_id ryos_devices[] = {
- { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_RYOS_MK) },
- { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_RYOS_MK_GLOW) },
- { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_RYOS_MK_PRO) },
- { }
-};
-
-MODULE_DEVICE_TABLE(hid, ryos_devices);
-
-static struct hid_driver ryos_driver = {
- .name = "ryos",
- .id_table = ryos_devices,
- .probe = ryos_probe,
- .remove = ryos_remove,
- .raw_event = ryos_raw_event
-};
-
-static int __init ryos_init(void)
-{
- int retval;
-
- ryos_class = class_create(THIS_MODULE, "ryos");
- if (IS_ERR(ryos_class))
- return PTR_ERR(ryos_class);
- ryos_class->dev_groups = ryos_groups;
-
- retval = hid_register_driver(&ryos_driver);
- if (retval)
- class_destroy(ryos_class);
- return retval;
-}
-
-static void __exit ryos_exit(void)
-{
- hid_unregister_driver(&ryos_driver);
- class_destroy(ryos_class);
-}
-
-module_init(ryos_init);
-module_exit(ryos_exit);
-
-MODULE_AUTHOR("Stefan Achatz");
-MODULE_DESCRIPTION("USB Roccat Ryos MK/Glow/Pro driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/hid/hid-roccat-savu.c b/drivers/hid/hid-roccat-savu.c
deleted file mode 100644
index 6dbf6e0..0000000
--- a/drivers/hid/hid-roccat-savu.c
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * Roccat Savu driver for Linux
- *
- * Copyright (c) 2012 Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-/* Roccat Savu is a gamer mouse with macro keys that can be configured in
- * 5 profiles.
- */
-
-#include <linux/device.h>
-#include <linux/input.h>
-#include <linux/hid.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/hid-roccat.h>
-#include "hid-ids.h"
-#include "hid-roccat-common.h"
-#include "hid-roccat-savu.h"
-
-static struct class *savu_class;
-
-ROCCAT_COMMON2_BIN_ATTRIBUTE_W(control, 0x4, 0x03);
-ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(profile, 0x5, 0x03);
-ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(general, 0x6, 0x10);
-ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(buttons, 0x7, 0x2f);
-ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(macro, 0x8, 0x0823);
-ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(info, 0x9, 0x08);
-ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(sensor, 0xc, 0x04);
-
-static struct bin_attribute *savu_bin_attrs[] = {
- &bin_attr_control,
- &bin_attr_profile,
- &bin_attr_general,
- &bin_attr_buttons,
- &bin_attr_macro,
- &bin_attr_info,
- &bin_attr_sensor,
- NULL,
-};
-
-static const struct attribute_group savu_group = {
- .bin_attrs = savu_bin_attrs,
-};
-
-static const struct attribute_group *savu_groups[] = {
- &savu_group,
- NULL,
-};
-
-static int savu_init_specials(struct hid_device *hdev)
-{
- struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
- struct usb_device *usb_dev = interface_to_usbdev(intf);
- struct roccat_common2_device *savu;
- int retval;
-
- if (intf->cur_altsetting->desc.bInterfaceProtocol
- != USB_INTERFACE_PROTOCOL_MOUSE) {
- hid_set_drvdata(hdev, NULL);
- return 0;
- }
-
- savu = kzalloc(sizeof(*savu), GFP_KERNEL);
- if (!savu) {
- hid_err(hdev, "can't alloc device descriptor\n");
- return -ENOMEM;
- }
- hid_set_drvdata(hdev, savu);
-
- retval = roccat_common2_device_init_struct(usb_dev, savu);
- if (retval) {
- hid_err(hdev, "couldn't init Savu device\n");
- goto exit_free;
- }
-
- retval = roccat_connect(savu_class, hdev,
- sizeof(struct savu_roccat_report));
- if (retval < 0) {
- hid_err(hdev, "couldn't init char dev\n");
- } else {
- savu->chrdev_minor = retval;
- savu->roccat_claimed = 1;
- }
-
- return 0;
-exit_free:
- kfree(savu);
- return retval;
-}
-
-static void savu_remove_specials(struct hid_device *hdev)
-{
- struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
- struct roccat_common2_device *savu;
-
- if (intf->cur_altsetting->desc.bInterfaceProtocol
- != USB_INTERFACE_PROTOCOL_MOUSE)
- return;
-
- savu = hid_get_drvdata(hdev);
- if (savu->roccat_claimed)
- roccat_disconnect(savu->chrdev_minor);
- kfree(savu);
-}
-
-static int savu_probe(struct hid_device *hdev,
- const struct hid_device_id *id)
-{
- int retval;
-
- retval = hid_parse(hdev);
- if (retval) {
- hid_err(hdev, "parse failed\n");
- goto exit;
- }
-
- retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
- if (retval) {
- hid_err(hdev, "hw start failed\n");
- goto exit;
- }
-
- retval = savu_init_specials(hdev);
- if (retval) {
- hid_err(hdev, "couldn't install mouse\n");
- goto exit_stop;
- }
-
- return 0;
-
-exit_stop:
- hid_hw_stop(hdev);
-exit:
- return retval;
-}
-
-static void savu_remove(struct hid_device *hdev)
-{
- savu_remove_specials(hdev);
- hid_hw_stop(hdev);
-}
-
-static void savu_report_to_chrdev(struct roccat_common2_device const *savu,
- u8 const *data)
-{
- struct savu_roccat_report roccat_report;
- struct savu_mouse_report_special const *special_report;
-
- if (data[0] != SAVU_MOUSE_REPORT_NUMBER_SPECIAL)
- return;
-
- special_report = (struct savu_mouse_report_special const *)data;
-
- roccat_report.type = special_report->type;
- roccat_report.data[0] = special_report->data[0];
- roccat_report.data[1] = special_report->data[1];
- roccat_report_event(savu->chrdev_minor,
- (uint8_t const *)&roccat_report);
-}
-
-static int savu_raw_event(struct hid_device *hdev,
- struct hid_report *report, u8 *data, int size)
-{
- struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
- struct roccat_common2_device *savu = hid_get_drvdata(hdev);
-
- if (intf->cur_altsetting->desc.bInterfaceProtocol
- != USB_INTERFACE_PROTOCOL_MOUSE)
- return 0;
-
- if (savu == NULL)
- return 0;
-
- if (savu->roccat_claimed)
- savu_report_to_chrdev(savu, data);
-
- return 0;
-}
-
-static const struct hid_device_id savu_devices[] = {
- { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_SAVU) },
- { }
-};
-
-MODULE_DEVICE_TABLE(hid, savu_devices);
-
-static struct hid_driver savu_driver = {
- .name = "savu",
- .id_table = savu_devices,
- .probe = savu_probe,
- .remove = savu_remove,
- .raw_event = savu_raw_event
-};
-
-static int __init savu_init(void)
-{
- int retval;
-
- savu_class = class_create(THIS_MODULE, "savu");
- if (IS_ERR(savu_class))
- return PTR_ERR(savu_class);
- savu_class->dev_groups = savu_groups;
-
- retval = hid_register_driver(&savu_driver);
- if (retval)
- class_destroy(savu_class);
- return retval;
-}
-
-static void __exit savu_exit(void)
-{
- hid_unregister_driver(&savu_driver);
- class_destroy(savu_class);
-}
-
-module_init(savu_init);
-module_exit(savu_exit);
-
-MODULE_AUTHOR("Stefan Achatz");
-MODULE_DESCRIPTION("USB Roccat Savu driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/hid/hid-roccat-savu.h b/drivers/hid/hid-roccat-savu.h
deleted file mode 100644
index d23217b..0000000
--- a/drivers/hid/hid-roccat-savu.h
+++ /dev/null
@@ -1,55 +0,0 @@
-#ifndef __HID_ROCCAT_SAVU_H
-#define __HID_ROCCAT_SAVU_H
-
-/*
- * Copyright (c) 2012 Stefan Achatz <erazor_de-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-#include <linux/types.h>
-
-struct savu_mouse_report_special {
- uint8_t report_number; /* always 3 */
- uint8_t zero;
- uint8_t type;
- uint8_t data[2];
-} __packed;
-
-enum {
- SAVU_MOUSE_REPORT_NUMBER_SPECIAL = 3,
-};
-
-enum savu_mouse_report_button_types {
- /* data1 = new profile range 1-5 */
- SAVU_MOUSE_REPORT_BUTTON_TYPE_PROFILE = 0x20,
-
- /* data1 = button number range 1-24; data2 = action */
- SAVU_MOUSE_REPORT_BUTTON_TYPE_QUICKLAUNCH = 0x60,
-
- /* data1 = button number range 1-24; data2 = action */
- SAVU_MOUSE_REPORT_BUTTON_TYPE_TIMER = 0x80,
-
- /* data1 = setting number range 1-5 */
- SAVU_MOUSE_REPORT_BUTTON_TYPE_CPI = 0xb0,
-
- /* data1 and data2 = range 0x1-0xb */
- SAVU_MOUSE_REPORT_BUTTON_TYPE_SENSITIVITY = 0xc0,
-
- /* data1 = 22 = next track...
- * data2 = action
- */
- SAVU_MOUSE_REPORT_BUTTON_TYPE_MULTIMEDIA = 0xf0,
-};
-
-struct savu_roccat_report {
- uint8_t type;
- uint8_t data[2];
-} __packed;
-
-#endif
--
1.7.3.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox