1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Roccat common functions for device specific drivers
5 * Copyright (c) 2011 Stefan Achatz <erazor_de@users.sourceforge.net>
11 #include <linux/hid.h>
12 #include <linux/slab.h>
13 #include <linux/module.h>
14 #include "hid-roccat-common.h"
16 static inline uint16_t roccat_common2_feature_report(uint8_t report_id
)
18 return 0x300 | report_id
;
21 int roccat_common2_receive(struct usb_device
*usb_dev
, uint report_id
,
22 void *data
, uint size
)
27 buf
= kmalloc(size
, GFP_KERNEL
);
31 len
= usb_control_msg(usb_dev
, usb_rcvctrlpipe(usb_dev
, 0),
33 USB_TYPE_CLASS
| USB_RECIP_INTERFACE
| USB_DIR_IN
,
34 roccat_common2_feature_report(report_id
),
35 0, buf
, size
, USB_CTRL_SET_TIMEOUT
);
37 memcpy(data
, buf
, size
);
39 return ((len
< 0) ? len
: ((len
!= size
) ? -EIO
: 0));
41 EXPORT_SYMBOL_GPL(roccat_common2_receive
);
43 int roccat_common2_send(struct usb_device
*usb_dev
, uint report_id
,
44 void const *data
, uint size
)
49 buf
= kmemdup(data
, size
, GFP_KERNEL
);
53 len
= usb_control_msg(usb_dev
, usb_sndctrlpipe(usb_dev
, 0),
55 USB_TYPE_CLASS
| USB_RECIP_INTERFACE
| USB_DIR_OUT
,
56 roccat_common2_feature_report(report_id
),
57 0, buf
, size
, USB_CTRL_SET_TIMEOUT
);
60 return ((len
< 0) ? len
: ((len
!= size
) ? -EIO
: 0));
62 EXPORT_SYMBOL_GPL(roccat_common2_send
);
64 enum roccat_common2_control_states
{
65 ROCCAT_COMMON_CONTROL_STATUS_CRITICAL
= 0,
66 ROCCAT_COMMON_CONTROL_STATUS_OK
= 1,
67 ROCCAT_COMMON_CONTROL_STATUS_INVALID
= 2,
68 ROCCAT_COMMON_CONTROL_STATUS_BUSY
= 3,
69 ROCCAT_COMMON_CONTROL_STATUS_CRITICAL_NEW
= 4,
72 static int roccat_common2_receive_control_status(struct usb_device
*usb_dev
)
75 struct roccat_common2_control control
;
79 retval
= roccat_common2_receive(usb_dev
,
80 ROCCAT_COMMON_COMMAND_CONTROL
,
81 &control
, sizeof(struct roccat_common2_control
));
86 switch (control
.value
) {
87 case ROCCAT_COMMON_CONTROL_STATUS_OK
:
89 case ROCCAT_COMMON_CONTROL_STATUS_BUSY
:
92 case ROCCAT_COMMON_CONTROL_STATUS_INVALID
:
93 case ROCCAT_COMMON_CONTROL_STATUS_CRITICAL
:
94 case ROCCAT_COMMON_CONTROL_STATUS_CRITICAL_NEW
:
97 dev_err(&usb_dev
->dev
,
98 "roccat_common2_receive_control_status: "
99 "unknown response value 0x%x\n",
107 int roccat_common2_send_with_status(struct usb_device
*usb_dev
,
108 uint command
, void const *buf
, uint size
)
112 retval
= roccat_common2_send(usb_dev
, command
, buf
, size
);
118 return roccat_common2_receive_control_status(usb_dev
);
120 EXPORT_SYMBOL_GPL(roccat_common2_send_with_status
);
122 int roccat_common2_device_init_struct(struct usb_device
*usb_dev
,
123 struct roccat_common2_device
*dev
)
125 mutex_init(&dev
->lock
);
128 EXPORT_SYMBOL_GPL(roccat_common2_device_init_struct
);
130 ssize_t
roccat_common2_sysfs_read(struct file
*fp
, struct kobject
*kobj
,
131 char *buf
, loff_t off
, size_t count
,
132 size_t real_size
, uint command
)
134 struct device
*dev
= kobj_to_dev(kobj
)->parent
->parent
;
135 struct roccat_common2_device
*roccat_dev
= hid_get_drvdata(dev_get_drvdata(dev
));
136 struct usb_device
*usb_dev
= interface_to_usbdev(to_usb_interface(dev
));
139 if (off
>= real_size
)
142 if (off
!= 0 || count
!= real_size
)
145 mutex_lock(&roccat_dev
->lock
);
146 retval
= roccat_common2_receive(usb_dev
, command
, buf
, real_size
);
147 mutex_unlock(&roccat_dev
->lock
);
149 return retval
? retval
: real_size
;
151 EXPORT_SYMBOL_GPL(roccat_common2_sysfs_read
);
153 ssize_t
roccat_common2_sysfs_write(struct file
*fp
, struct kobject
*kobj
,
154 void const *buf
, loff_t off
, size_t count
,
155 size_t real_size
, uint command
)
157 struct device
*dev
= kobj_to_dev(kobj
)->parent
->parent
;
158 struct roccat_common2_device
*roccat_dev
= hid_get_drvdata(dev_get_drvdata(dev
));
159 struct usb_device
*usb_dev
= interface_to_usbdev(to_usb_interface(dev
));
162 if (off
!= 0 || count
!= real_size
)
165 mutex_lock(&roccat_dev
->lock
);
166 retval
= roccat_common2_send_with_status(usb_dev
, command
, buf
, real_size
);
167 mutex_unlock(&roccat_dev
->lock
);
169 return retval
? retval
: real_size
;
171 EXPORT_SYMBOL_GPL(roccat_common2_sysfs_write
);
173 MODULE_AUTHOR("Stefan Achatz");
174 MODULE_DESCRIPTION("USB Roccat common driver");
175 MODULE_LICENSE("GPL v2");