aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid
diff options
context:
space:
mode:
authorEdwin Velds <e.velds@gmail.com>2016-01-10 18:25:15 -0500
committerJiri Kosina <jkosina@suse.cz>2016-01-28 08:27:44 -0500
commitff21a635dd1a9c6ca378847160897649cdbbfae4 (patch)
treec30d97697d759bc599be8a6c69f74f5b7e44978f /drivers/hid
parentc2848f2eef4dd08b0fd2a8eba1694fd8e77ddb67 (diff)
HID: logitech-hidpp: Force feedback support for the Logitech G920
This patch implements force feedback support for the Logitech G920 Driving Force Racing Wheel. It is a generic implementation of feature 0x8123 of the Logitech HID++ protocol and should be usable for any future devices that implement this feature. This patch should be applied after the basic G920 support patch by Simon Wood: http://www.spinics.net/lists/linux-input/msg42174.html The driving supports everything that is supported by the G920 firmware: FF_CONSTANT FF_PERIODIC FF_SINE FF_SQUARE FF_SAW_UP FF_SAW_DOWN FF_TRIANGLE FF_SPRING FF_DAMPER FF_AUTOCENTER FF_GAIN and for version 2 firmware also: FF_FRICTION FF_INERTIA FF_RAMP Both envelopes and replay values are supported as well, but some problems may occur when using firmware release 1. There is also a small residual clockwise damper in the wheel when using the first firmware release. All problems are fixed in the soon te be released firmware version 2. The default spring is disabled by permanently placing a spring force in the wheel. This spring is also used as the autocenter spring. Note: The wheel _DOES_NOT_ auto switch to Logitech/HID mode (it is stuck in XBox since the xpad changes where not included). Michal has an alternative approach documented here (and the changes should be submitted upstream to usb_modeswitch project): === Create a file named "046d:c261" in "/etc/usb_modeswitch.d" with the following content: DefaultVendor=046d DefaultProduct=c261 MessageEndpoint=01 ResponseEndpoint=01 TargetClass=0x03 MessageContent="0f00010142" Then run "usb_modeswitch -c /etc/modeswitch.d/046d:c291" as root and watch the magic happen:) === [jkosina@suse.cz: added information about mode switching from Simon] [jkosina@suse.cz: fixed a few stylistic issues pointed out by Simon] [jkosina@suse.cz: fix merge conflict due to to_hid_device() changes] Signed-off-by: Edwin Velds <e.velds@gmail.com> Tested-by: Elias Vanderstuyft <elias.vds@gmail.com> Tested-by: Simon Wood <simon@mungewell.org> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid')
-rw-r--r--drivers/hid/hid-logitech-hidpp.c701
1 files changed, 593 insertions, 108 deletions
diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index bd2ab476c65e..2869bbff0899 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -15,13 +15,19 @@
15#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 15#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
16 16
17#include <linux/device.h> 17#include <linux/device.h>
18#include <linux/input.h>
19#include <linux/usb.h>
18#include <linux/hid.h> 20#include <linux/hid.h>
19#include <linux/module.h> 21#include <linux/module.h>
20#include <linux/slab.h> 22#include <linux/slab.h>
21#include <linux/sched.h> 23#include <linux/sched.h>
22#include <linux/kfifo.h> 24#include <linux/kfifo.h>
23#include <linux/input/mt.h> 25#include <linux/input/mt.h>
26#include <linux/workqueue.h>
27#include <linux/atomic.h>
28#include <linux/fixp-arith.h>
24#include <asm/unaligned.h> 29#include <asm/unaligned.h>
30#include "usbhid/usbhid.h"
25#include "hid-ids.h" 31#include "hid-ids.h"
26 32
27MODULE_LICENSE("GPL"); 33MODULE_LICENSE("GPL");
@@ -773,6 +779,589 @@ static void hidpp_touchpad_raw_xy_event(struct hidpp_device *hidpp_dev,
773 } 779 }
774} 780}
775 781
782/* -------------------------------------------------------------------------- */
783/* 0x8123: Force feedback support */
784/* -------------------------------------------------------------------------- */
785
786#define HIDPP_FF_GET_INFO 0x01
787#define HIDPP_FF_RESET_ALL 0x11
788#define HIDPP_FF_DOWNLOAD_EFFECT 0x21
789#define HIDPP_FF_SET_EFFECT_STATE 0x31
790#define HIDPP_FF_DESTROY_EFFECT 0x41
791#define HIDPP_FF_GET_APERTURE 0x51
792#define HIDPP_FF_SET_APERTURE 0x61
793#define HIDPP_FF_GET_GLOBAL_GAINS 0x71
794#define HIDPP_FF_SET_GLOBAL_GAINS 0x81
795
796#define HIDPP_FF_EFFECT_STATE_GET 0x00
797#define HIDPP_FF_EFFECT_STATE_STOP 0x01
798#define HIDPP_FF_EFFECT_STATE_PLAY 0x02
799#define HIDPP_FF_EFFECT_STATE_PAUSE 0x03
800
801#define HIDPP_FF_EFFECT_CONSTANT 0x00
802#define HIDPP_FF_EFFECT_PERIODIC_SINE 0x01
803#define HIDPP_FF_EFFECT_PERIODIC_SQUARE 0x02
804#define HIDPP_FF_EFFECT_PERIODIC_TRIANGLE 0x03
805#define HIDPP_FF_EFFECT_PERIODIC_SAWTOOTHUP 0x04
806#define HIDPP_FF_EFFECT_PERIODIC_SAWTOOTHDOWN 0x05
807#define HIDPP_FF_EFFECT_SPRING 0x06
808#define HIDPP_FF_EFFECT_DAMPER 0x07
809#define HIDPP_FF_EFFECT_FRICTION 0x08
810#define HIDPP_FF_EFFECT_INERTIA 0x09
811#define HIDPP_FF_EFFECT_RAMP 0x0A
812
813#define HIDPP_FF_EFFECT_AUTOSTART 0x80
814
815#define HIDPP_FF_EFFECTID_NONE -1
816#define HIDPP_FF_EFFECTID_AUTOCENTER -2
817
818#define HIDPP_FF_MAX_PARAMS 20
819#define HIDPP_FF_RESERVED_SLOTS 1
820
821struct hidpp_ff_private_data {
822 struct hidpp_device *hidpp;
823 u8 feature_index;
824 u8 version;
825 u16 gain;
826 s16 range;
827 u8 slot_autocenter;
828 u8 num_effects;
829 int *effect_ids;
830 struct workqueue_struct *wq;
831 atomic_t workqueue_size;
832};
833
834struct hidpp_ff_work_data {
835 struct work_struct work;
836 struct hidpp_ff_private_data *data;
837 int effect_id;
838 u8 command;
839 u8 params[HIDPP_FF_MAX_PARAMS];
840 u8 size;
841};
842
843static const signed short hiddpp_ff_effects[] = {
844 FF_CONSTANT,
845 FF_PERIODIC,
846 FF_SINE,
847 FF_SQUARE,
848 FF_SAW_UP,
849 FF_SAW_DOWN,
850 FF_TRIANGLE,
851 FF_SPRING,
852 FF_DAMPER,
853 FF_AUTOCENTER,
854 FF_GAIN,
855 -1
856};
857
858static const signed short hiddpp_ff_effects_v2[] = {
859 FF_RAMP,
860 FF_FRICTION,
861 FF_INERTIA,
862 -1
863};
864
865static const u8 HIDPP_FF_CONDITION_CMDS[] = {
866 HIDPP_FF_EFFECT_SPRING,
867 HIDPP_FF_EFFECT_FRICTION,
868 HIDPP_FF_EFFECT_DAMPER,
869 HIDPP_FF_EFFECT_INERTIA
870};
871
872static const char *HIDPP_FF_CONDITION_NAMES[] = {
873 "spring",
874 "friction",
875 "damper",
876 "inertia"
877};
878
879
880static u8 hidpp_ff_find_effect(struct hidpp_ff_private_data *data, int effect_id)
881{
882 int i;
883
884 for (i = 0; i < data->num_effects; i++)
885 if (data->effect_ids[i] == effect_id)
886 return i+1;
887
888 return 0;
889}
890
891static void hidpp_ff_work_handler(struct work_struct *w)
892{
893 struct hidpp_ff_work_data *wd = container_of(w, struct hidpp_ff_work_data, work);
894 struct hidpp_ff_private_data *data = wd->data;
895 struct hidpp_report response;
896 u8 slot;
897 int ret;
898
899 /* add slot number if needed */
900 switch (wd->effect_id) {
901 case HIDPP_FF_EFFECTID_AUTOCENTER:
902 wd->params[0] = data->slot_autocenter;
903 break;
904 case HIDPP_FF_EFFECTID_NONE:
905 /* leave slot as zero */
906 break;
907 default:
908 /* find current slot for effect */
909 wd->params[0] = hidpp_ff_find_effect(data, wd->effect_id);
910 break;
911 }
912
913 /* send command and wait for reply */
914 ret = hidpp_send_fap_command_sync(data->hidpp, data->feature_index,
915 wd->command, wd->params, wd->size, &response);
916
917 if (ret) {
918 hid_err(data->hidpp->hid_dev, "Failed to send command to device!\n");
919 goto out;
920 }
921
922 /* parse return data */
923 switch (wd->command) {
924 case HIDPP_FF_DOWNLOAD_EFFECT:
925 slot = response.fap.params[0];
926 if (slot > 0 && slot <= data->num_effects) {
927 if (wd->effect_id >= 0)
928 /* regular effect uploaded */
929 data->effect_ids[slot-1] = wd->effect_id;
930 else if (wd->effect_id >= HIDPP_FF_EFFECTID_AUTOCENTER)
931 /* autocenter spring uploaded */
932 data->slot_autocenter = slot;
933 }
934 break;
935 case HIDPP_FF_DESTROY_EFFECT:
936 if (wd->effect_id >= 0)
937 /* regular effect destroyed */
938 data->effect_ids[wd->params[0]-1] = -1;
939 else if (wd->effect_id >= HIDPP_FF_EFFECTID_AUTOCENTER)
940 /* autocenter spring destoyed */
941 data->slot_autocenter = 0;
942 break;
943 case HIDPP_FF_SET_GLOBAL_GAINS:
944 data->gain = (wd->params[0] << 8) + wd->params[1];
945 break;
946 case HIDPP_FF_SET_APERTURE:
947 data->range = (wd->params[0] << 8) + wd->params[1];
948 break;
949 default:
950 /* no action needed */
951 break;
952 }
953
954out:
955 atomic_dec(&data->workqueue_size);
956 kfree(wd);
957}
958
959static int hidpp_ff_queue_work(struct hidpp_ff_private_data *data, int effect_id, u8 command, u8 *params, u8 size)
960{
961 struct hidpp_ff_work_data *wd = kzalloc(sizeof(*wd), GFP_KERNEL);
962 int s;
963
964 if (!wd)
965 return -ENOMEM;
966
967 INIT_WORK(&wd->work, hidpp_ff_work_handler);
968
969 wd->data = data;
970 wd->effect_id = effect_id;
971 wd->command = command;
972 wd->size = size;
973 memcpy(wd->params, params, size);
974
975 atomic_inc(&data->workqueue_size);
976 queue_work(data->wq, &wd->work);
977
978 /* warn about excessive queue size */
979 s = atomic_read(&data->workqueue_size);
980 if (s >= 20 && s % 20 == 0)
981 hid_warn(data->hidpp->hid_dev, "Force feedback command queue contains %d commands, causing substantial delays!", s);
982
983 return 0;
984}
985
986static int hidpp_ff_upload_effect(struct input_dev *dev, struct ff_effect *effect, struct ff_effect *old)
987{
988 struct hidpp_ff_private_data *data = dev->ff->private;
989 u8 params[20];
990 u8 size;
991 int force;
992
993 /* set common parameters */
994 params[2] = effect->replay.length >> 8;
995 params[3] = effect->replay.length & 255;
996 params[4] = effect->replay.delay >> 8;
997 params[5] = effect->replay.delay & 255;
998
999 switch (effect->type) {
1000 case FF_CONSTANT:
1001 force = (effect->u.constant.level * fixp_sin16((effect->direction * 360) >> 16)) >> 15;
1002 params[1] = HIDPP_FF_EFFECT_CONSTANT;
1003 params[6] = force >> 8;
1004 params[7] = force & 255;
1005 params[8] = effect->u.constant.envelope.attack_level >> 7;
1006 params[9] = effect->u.constant.envelope.attack_length >> 8;
1007 params[10] = effect->u.constant.envelope.attack_length & 255;
1008 params[11] = effect->u.constant.envelope.fade_level >> 7;
1009 params[12] = effect->u.constant.envelope.fade_length >> 8;
1010 params[13] = effect->u.constant.envelope.fade_length & 255;
1011 size = 14;
1012 dbg_hid("Uploading constant force level=%d in dir %d = %d\n",
1013 effect->u.constant.level,
1014 effect->direction, force);
1015 dbg_hid(" envelope attack=(%d, %d ms) fade=(%d, %d ms)\n",
1016 effect->u.constant.envelope.attack_level,
1017 effect->u.constant.envelope.attack_length,
1018 effect->u.constant.envelope.fade_level,
1019 effect->u.constant.envelope.fade_length);
1020 break;
1021 case FF_PERIODIC:
1022 {
1023 switch (effect->u.periodic.waveform) {
1024 case FF_SINE:
1025 params[1] = HIDPP_FF_EFFECT_PERIODIC_SINE;
1026 break;
1027 case FF_SQUARE:
1028 params[1] = HIDPP_FF_EFFECT_PERIODIC_SQUARE;
1029 break;
1030 case FF_SAW_UP:
1031 params[1] = HIDPP_FF_EFFECT_PERIODIC_SAWTOOTHUP;
1032 break;
1033 case FF_SAW_DOWN:
1034 params[1] = HIDPP_FF_EFFECT_PERIODIC_SAWTOOTHDOWN;
1035 break;
1036 case FF_TRIANGLE:
1037 params[1] = HIDPP_FF_EFFECT_PERIODIC_TRIANGLE;
1038 break;
1039 default:
1040 hid_err(data->hidpp->hid_dev, "Unexpected periodic waveform type %i!\n", effect->u.periodic.waveform);
1041 return -EINVAL;
1042 }
1043 force = (effect->u.periodic.magnitude * fixp_sin16((effect->direction * 360) >> 16)) >> 15;
1044 params[6] = effect->u.periodic.magnitude >> 8;
1045 params[7] = effect->u.periodic.magnitude & 255;
1046 params[8] = effect->u.periodic.offset >> 8;
1047 params[9] = effect->u.periodic.offset & 255;
1048 params[10] = effect->u.periodic.period >> 8;
1049 params[11] = effect->u.periodic.period & 255;
1050 params[12] = effect->u.periodic.phase >> 8;
1051 params[13] = effect->u.periodic.phase & 255;
1052 params[14] = effect->u.periodic.envelope.attack_level >> 7;
1053 params[15] = effect->u.periodic.envelope.attack_length >> 8;
1054 params[16] = effect->u.periodic.envelope.attack_length & 255;
1055 params[17] = effect->u.periodic.envelope.fade_level >> 7;
1056 params[18] = effect->u.periodic.envelope.fade_length >> 8;
1057 params[19] = effect->u.periodic.envelope.fade_length & 255;
1058 size = 20;
1059 dbg_hid("Uploading periodic force mag=%d/dir=%d, offset=%d, period=%d ms, phase=%d\n",
1060 effect->u.periodic.magnitude, effect->direction,
1061 effect->u.periodic.offset,
1062 effect->u.periodic.period,
1063 effect->u.periodic.phase);
1064 dbg_hid(" envelope attack=(%d, %d ms) fade=(%d, %d ms)\n",
1065 effect->u.periodic.envelope.attack_level,
1066 effect->u.periodic.envelope.attack_length,
1067 effect->u.periodic.envelope.fade_level,
1068 effect->u.periodic.envelope.fade_length);
1069 break;
1070 }
1071 case FF_RAMP:
1072 params[1] = HIDPP_FF_EFFECT_RAMP;
1073 force = (effect->u.ramp.start_level * fixp_sin16((effect->direction * 360) >> 16)) >> 15;
1074 params[6] = force >> 8;
1075 params[7] = force & 255;
1076 force = (effect->u.ramp.end_level * fixp_sin16((effect->direction * 360) >> 16)) >> 15;
1077 params[8] = force >> 8;
1078 params[9] = force & 255;
1079 params[10] = effect->u.ramp.envelope.attack_level >> 7;
1080 params[11] = effect->u.ramp.envelope.attack_length >> 8;
1081 params[12] = effect->u.ramp.envelope.attack_length & 255;
1082 params[13] = effect->u.ramp.envelope.fade_level >> 7;
1083 params[14] = effect->u.ramp.envelope.fade_length >> 8;
1084 params[15] = effect->u.ramp.envelope.fade_length & 255;
1085 size = 16;
1086 dbg_hid("Uploading ramp force level=%d -> %d in dir %d = %d\n",
1087 effect->u.ramp.start_level,
1088 effect->u.ramp.end_level,
1089 effect->direction, force);
1090 dbg_hid(" envelope attack=(%d, %d ms) fade=(%d, %d ms)\n",
1091 effect->u.ramp.envelope.attack_level,
1092 effect->u.ramp.envelope.attack_length,
1093 effect->u.ramp.envelope.fade_level,
1094 effect->u.ramp.envelope.fade_length);
1095 break;
1096 case FF_FRICTION:
1097 case FF_INERTIA:
1098 case FF_SPRING:
1099 case FF_DAMPER:
1100 params[1] = HIDPP_FF_CONDITION_CMDS[effect->type - FF_SPRING];
1101 params[6] = effect->u.condition[0].left_saturation >> 9;
1102 params[7] = (effect->u.condition[0].left_saturation >> 1) & 255;
1103 params[8] = effect->u.condition[0].left_coeff >> 8;
1104 params[9] = effect->u.condition[0].left_coeff & 255;
1105 params[10] = effect->u.condition[0].deadband >> 9;
1106 params[11] = (effect->u.condition[0].deadband >> 1) & 255;
1107 params[12] = effect->u.condition[0].center >> 8;
1108 params[13] = effect->u.condition[0].center & 255;
1109 params[14] = effect->u.condition[0].right_coeff >> 8;
1110 params[15] = effect->u.condition[0].right_coeff & 255;
1111 params[16] = effect->u.condition[0].right_saturation >> 9;
1112 params[17] = (effect->u.condition[0].right_saturation >> 1) & 255;
1113 size = 18;
1114 dbg_hid("Uploading %s force left coeff=%d, left sat=%d, right coeff=%d, right sat=%d\n",
1115 HIDPP_FF_CONDITION_NAMES[effect->type - FF_SPRING],
1116 effect->u.condition[0].left_coeff,
1117 effect->u.condition[0].left_saturation,
1118 effect->u.condition[0].right_coeff,
1119 effect->u.condition[0].right_saturation);
1120 dbg_hid(" deadband=%d, center=%d\n",
1121 effect->u.condition[0].deadband,
1122 effect->u.condition[0].center);
1123 break;
1124 default:
1125 hid_err(data->hidpp->hid_dev, "Unexpected force type %i!\n", effect->type);
1126 return -EINVAL;
1127 }
1128
1129 return hidpp_ff_queue_work(data, effect->id, HIDPP_FF_DOWNLOAD_EFFECT, params, size);
1130}
1131
1132static int hidpp_ff_playback(struct input_dev *dev, int effect_id, int value)
1133{
1134 struct hidpp_ff_private_data *data = dev->ff->private;
1135 u8 params[2];
1136
1137 params[1] = value ? HIDPP_FF_EFFECT_STATE_PLAY : HIDPP_FF_EFFECT_STATE_STOP;
1138
1139 dbg_hid("St%sing playback of effect %d.\n", value?"art":"opp", effect_id);
1140
1141 return hidpp_ff_queue_work(data, effect_id, HIDPP_FF_SET_EFFECT_STATE, params, ARRAY_SIZE(params));
1142}
1143
1144static int hidpp_ff_erase_effect(struct input_dev *dev, int effect_id)
1145{
1146 struct hidpp_ff_private_data *data = dev->ff->private;
1147 u8 slot = 0;
1148
1149 dbg_hid("Erasing effect %d.\n", effect_id);
1150
1151 return hidpp_ff_queue_work(data, effect_id, HIDPP_FF_DESTROY_EFFECT, &slot, 1);
1152}
1153
1154static void hidpp_ff_set_autocenter(struct input_dev *dev, u16 magnitude)
1155{
1156 struct hidpp_ff_private_data *data = dev->ff->private;
1157 u8 params[18];
1158
1159 dbg_hid("Setting autocenter to %d.\n", magnitude);
1160
1161 /* start a standard spring effect */
1162 params[1] = HIDPP_FF_EFFECT_SPRING | HIDPP_FF_EFFECT_AUTOSTART;
1163 /* zero delay and duration */
1164 params[2] = params[3] = params[4] = params[5] = 0;
1165 /* set coeff to 25% of saturation */
1166 params[8] = params[14] = magnitude >> 11;
1167 params[9] = params[15] = (magnitude >> 3) & 255;
1168 params[6] = params[16] = magnitude >> 9;
1169 params[7] = params[17] = (magnitude >> 1) & 255;
1170 /* zero deadband and center */
1171 params[10] = params[11] = params[12] = params[13] = 0;
1172
1173 hidpp_ff_queue_work(data, HIDPP_FF_EFFECTID_AUTOCENTER, HIDPP_FF_DOWNLOAD_EFFECT, params, ARRAY_SIZE(params));
1174}
1175
1176static void hidpp_ff_set_gain(struct input_dev *dev, u16 gain)
1177{
1178 struct hidpp_ff_private_data *data = dev->ff->private;
1179 u8 params[4];
1180
1181 dbg_hid("Setting gain to %d.\n", gain);
1182
1183 params[0] = gain >> 8;
1184 params[1] = gain & 255;
1185 params[2] = 0; /* no boost */
1186 params[3] = 0;
1187
1188 hidpp_ff_queue_work(data, HIDPP_FF_EFFECTID_NONE, HIDPP_FF_SET_GLOBAL_GAINS, params, ARRAY_SIZE(params));
1189}
1190
1191static ssize_t hidpp_ff_range_show(struct device *dev, struct device_attribute *attr, char *buf)
1192{
1193 struct hid_device *hid = to_hid_device(dev);
1194 struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
1195 struct input_dev *idev = hidinput->input;
1196 struct hidpp_ff_private_data *data = idev->ff->private;
1197
1198 return scnprintf(buf, PAGE_SIZE, "%u\n", data->range);
1199}
1200
1201static ssize_t hidpp_ff_range_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
1202{
1203 struct hid_device *hid = to_hid_device(dev);
1204 struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
1205 struct input_dev *idev = hidinput->input;
1206 struct hidpp_ff_private_data *data = idev->ff->private;
1207 u8 params[2];
1208 int range = simple_strtoul(buf, NULL, 10);
1209
1210 range = clamp(range, 180, 900);
1211
1212 params[0] = range >> 8;
1213 params[1] = range & 0x00FF;
1214
1215 hidpp_ff_queue_work(data, -1, HIDPP_FF_SET_APERTURE, params, ARRAY_SIZE(params));
1216
1217 return count;
1218}
1219
1220static DEVICE_ATTR(range, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, hidpp_ff_range_show, hidpp_ff_range_store);
1221
1222static void hidpp_ff_destroy(struct ff_device *ff)
1223{
1224 struct hidpp_ff_private_data *data = ff->private;
1225
1226 kfree(data->effect_ids);
1227}
1228
1229int hidpp_ff_init(struct hidpp_device *hidpp, u8 feature_index)
1230{
1231 struct hid_device *hid = hidpp->hid_dev;
1232 struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
1233 struct input_dev *dev = hidinput->input;
1234 const struct usb_device_descriptor *udesc = &(hid_to_usb_dev(hid)->descriptor);
1235 const u16 bcdDevice = le16_to_cpu(udesc->bcdDevice);
1236 struct ff_device *ff;
1237 struct hidpp_report response;
1238 struct hidpp_ff_private_data *data;
1239 int error, j, num_slots;
1240 u8 version;
1241
1242 if (!dev) {
1243 hid_err(hid, "Struct input_dev not set!\n");
1244 return -EINVAL;
1245 }
1246
1247 /* Get firmware release */
1248 version = bcdDevice & 255;
1249
1250 /* Set supported force feedback capabilities */
1251 for (j = 0; hiddpp_ff_effects[j] >= 0; j++)
1252 set_bit(hiddpp_ff_effects[j], dev->ffbit);
1253 if (version > 1)
1254 for (j = 0; hiddpp_ff_effects_v2[j] >= 0; j++)
1255 set_bit(hiddpp_ff_effects_v2[j], dev->ffbit);
1256
1257 /* Read number of slots available in device */
1258 error = hidpp_send_fap_command_sync(hidpp, feature_index,
1259 HIDPP_FF_GET_INFO, NULL, 0, &response);
1260 if (error) {
1261 if (error < 0)
1262 return error;
1263 hid_err(hidpp->hid_dev, "%s: received protocol error 0x%02x\n",
1264 __func__, error);
1265 return -EPROTO;
1266 }
1267
1268 num_slots = response.fap.params[0] - HIDPP_FF_RESERVED_SLOTS;
1269
1270 error = input_ff_create(dev, num_slots);
1271
1272 if (error) {
1273 hid_err(dev, "Failed to create FF device!\n");
1274 return error;
1275 }
1276
1277 data = kzalloc(sizeof(*data), GFP_KERNEL);
1278 if (!data)
1279 return -ENOMEM;
1280 data->effect_ids = kcalloc(num_slots, sizeof(int), GFP_KERNEL);
1281 if (!data->effect_ids) {
1282 kfree(data);
1283 return -ENOMEM;
1284 }
1285 data->hidpp = hidpp;
1286 data->feature_index = feature_index;
1287 data->version = version;
1288 data->slot_autocenter = 0;
1289 data->num_effects = num_slots;
1290 for (j = 0; j < num_slots; j++)
1291 data->effect_ids[j] = -1;
1292
1293 ff = dev->ff;
1294 ff->private = data;
1295
1296 ff->upload = hidpp_ff_upload_effect;
1297 ff->erase = hidpp_ff_erase_effect;
1298 ff->playback = hidpp_ff_playback;
1299 ff->set_gain = hidpp_ff_set_gain;
1300 ff->set_autocenter = hidpp_ff_set_autocenter;
1301 ff->destroy = hidpp_ff_destroy;
1302
1303
1304 /* reset all forces */
1305 error = hidpp_send_fap_command_sync(hidpp, feature_index,
1306 HIDPP_FF_RESET_ALL, NULL, 0, &response);
1307
1308 /* Read current Range */
1309 error = hidpp_send_fap_command_sync(hidpp, feature_index,
1310 HIDPP_FF_GET_APERTURE, NULL, 0, &response);
1311 if (error)
1312 hid_warn(hidpp->hid_dev, "Failed to read range from device!\n");
1313 data->range = error ? 900 : get_unaligned_be16(&response.fap.params[0]);
1314
1315 /* Create sysfs interface */
1316 error = device_create_file(&(hidpp->hid_dev->dev), &dev_attr_range);
1317 if (error)
1318 hid_warn(hidpp->hid_dev, "Unable to create sysfs interface for \"range\", errno %d!\n", error);
1319
1320 /* Read the current gain values */
1321 error = hidpp_send_fap_command_sync(hidpp, feature_index,
1322 HIDPP_FF_GET_GLOBAL_GAINS, NULL, 0, &response);
1323 if (error)
1324 hid_warn(hidpp->hid_dev, "Failed to read gain values from device!\n");
1325 data->gain = error ? 0xffff : get_unaligned_be16(&response.fap.params[0]);
1326 /* ignore boost value at response.fap.params[2] */
1327
1328 /* init the hardware command queue */
1329 data->wq = create_singlethread_workqueue("hidpp-ff-sendqueue");
1330 atomic_set(&data->workqueue_size, 0);
1331
1332 /* initialize with zero autocenter to get wheel in usable state */
1333 hidpp_ff_set_autocenter(dev, 0);
1334
1335 hid_info(hid, "Force feeback support loaded (firmware release %d).\n", version);
1336
1337 return 0;
1338}
1339
1340int hidpp_ff_deinit(struct hid_device *hid)
1341{
1342 struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
1343 struct input_dev *dev = hidinput->input;
1344 struct hidpp_ff_private_data *data;
1345
1346 if (!dev) {
1347 hid_err(hid, "Struct input_dev not found!\n");
1348 return -EINVAL;
1349 }
1350
1351 hid_info(hid, "Unloading HID++ force feedback.\n");
1352 data = dev->ff->private;
1353 if (!data) {
1354 hid_err(hid, "Private data not found!\n");
1355 return -EINVAL;
1356 }
1357
1358 destroy_workqueue(data->wq);
1359 device_remove_file(&hid->dev, &dev_attr_range);
1360
1361 return 0;
1362}
1363
1364
776/* ************************************************************************** */ 1365/* ************************************************************************** */
777/* */ 1366/* */
778/* Device Support */ 1367/* Device Support */
@@ -1301,121 +1890,22 @@ static int k400_connect(struct hid_device *hdev, bool connected)
1301 1890
1302#define HIDPP_PAGE_G920_FORCE_FEEDBACK 0x8123 1891#define HIDPP_PAGE_G920_FORCE_FEEDBACK 0x8123
1303 1892
1304/* Using session ID = 1 */
1305#define CMD_G920_FORCE_GET_APERTURE 0x51
1306#define CMD_G920_FORCE_SET_APERTURE 0x61
1307
1308struct g920_private_data {
1309 u8 force_feature;
1310 u16 range;
1311};
1312
1313static ssize_t g920_range_show(struct device *dev, struct device_attribute *attr,
1314 char *buf)
1315{
1316 struct hid_device *hid = to_hid_device(dev);
1317 struct hidpp_device *hidpp = hid_get_drvdata(hid);
1318 struct g920_private_data *pdata;
1319
1320 pdata = hidpp->private_data;
1321 if (!pdata) {
1322 hid_err(hid, "Private driver data not found!\n");
1323 return -EINVAL;
1324 }
1325
1326 return scnprintf(buf, PAGE_SIZE, "%u\n", pdata->range);
1327}
1328
1329static ssize_t g920_range_store(struct device *dev, struct device_attribute *attr,
1330 const char *buf, size_t count)
1331{
1332 struct hid_device *hid = to_hid_device(dev);
1333 struct hidpp_device *hidpp = hid_get_drvdata(hid);
1334 struct g920_private_data *pdata;
1335 struct hidpp_report response;
1336 u8 params[2];
1337 int ret;
1338 u16 range = simple_strtoul(buf, NULL, 10);
1339
1340 pdata = hidpp->private_data;
1341 if (!pdata) {
1342 hid_err(hid, "Private driver data not found!\n");
1343 return -EINVAL;
1344 }
1345
1346 if (range < 180)
1347 range = 180;
1348 else if (range > 900)
1349 range = 900;
1350
1351 params[0] = range >> 8;
1352 params[1] = range & 0x00FF;
1353
1354 ret = hidpp_send_fap_command_sync(hidpp, pdata->force_feature,
1355 CMD_G920_FORCE_SET_APERTURE, params, 2, &response);
1356 if (ret)
1357 return ret;
1358
1359 pdata->range = range;
1360 return count;
1361}
1362
1363static DEVICE_ATTR(range, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, g920_range_show, g920_range_store);
1364
1365static int g920_allocate(struct hid_device *hdev)
1366{
1367 struct hidpp_device *hidpp = hid_get_drvdata(hdev);
1368 struct g920_private_data *pdata;
1369
1370 pdata = devm_kzalloc(&hdev->dev, sizeof(struct g920_private_data),
1371 GFP_KERNEL);
1372 if (!pdata)
1373 return -ENOMEM;
1374
1375 hidpp->private_data = pdata;
1376
1377 return 0;
1378}
1379
1380static int g920_get_config(struct hidpp_device *hidpp) 1893static int g920_get_config(struct hidpp_device *hidpp)
1381{ 1894{
1382 struct g920_private_data *pdata = hidpp->private_data;
1383 struct hidpp_report response;
1384 u8 feature_type; 1895 u8 feature_type;
1385 u8 feature_index; 1896 u8 feature_index;
1386 int ret; 1897 int ret;
1387 1898
1388 pdata = hidpp->private_data;
1389 if (!pdata) {
1390 hid_err(hidpp->hid_dev, "Private driver data not found!\n");
1391 return -EINVAL;
1392 }
1393
1394 /* Find feature and store for later use */ 1899 /* Find feature and store for later use */
1395 ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_G920_FORCE_FEEDBACK, 1900 ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_G920_FORCE_FEEDBACK,
1396 &feature_index, &feature_type); 1901 &feature_index, &feature_type);
1397 if (ret) 1902 if (ret)
1398 return ret; 1903 return ret;
1399 1904
1400 pdata->force_feature = feature_index; 1905 ret = hidpp_ff_init(hidpp, feature_index);
1401
1402 /* Read current Range */
1403 ret = hidpp_send_fap_command_sync(hidpp, feature_index,
1404 CMD_G920_FORCE_GET_APERTURE, NULL, 0, &response);
1405 if (ret > 0) {
1406 hid_err(hidpp->hid_dev, "%s: received protocol error 0x%02x\n",
1407 __func__, ret);
1408 return -EPROTO;
1409 }
1410 if (ret)
1411 return ret;
1412
1413 pdata->range = get_unaligned_be16(&response.fap.params[0]);
1414
1415 /* Create sysfs interface */
1416 ret = device_create_file(&(hidpp->hid_dev->dev), &dev_attr_range);
1417 if (ret) 1906 if (ret)
1418 hid_warn(hidpp->hid_dev, "Unable to create sysfs interface for \"range\", errno %d\n", ret); 1907 hid_warn(hidpp->hid_dev, "Unable to initialize force feedback support, errno %d\n",
1908 ret);
1419 1909
1420 return 0; 1910 return 0;
1421} 1911}
@@ -1739,10 +2229,6 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
1739 ret = k400_allocate(hdev); 2229 ret = k400_allocate(hdev);
1740 if (ret) 2230 if (ret)
1741 goto allocate_fail; 2231 goto allocate_fail;
1742 } else if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) {
1743 ret = g920_allocate(hdev);
1744 if (ret)
1745 goto allocate_fail;
1746 } 2232 }
1747 2233
1748 INIT_WORK(&hidpp->work, delayed_work_cb); 2234 INIT_WORK(&hidpp->work, delayed_work_cb);
@@ -1825,7 +2311,6 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
1825hid_hw_open_failed: 2311hid_hw_open_failed:
1826 hid_device_io_stop(hdev); 2312 hid_device_io_stop(hdev);
1827 if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) { 2313 if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) {
1828 device_remove_file(&hdev->dev, &dev_attr_range);
1829 hid_hw_close(hdev); 2314 hid_hw_close(hdev);
1830 hid_hw_stop(hdev); 2315 hid_hw_stop(hdev);
1831 } 2316 }
@@ -1843,7 +2328,7 @@ static void hidpp_remove(struct hid_device *hdev)
1843 struct hidpp_device *hidpp = hid_get_drvdata(hdev); 2328 struct hidpp_device *hidpp = hid_get_drvdata(hdev);
1844 2329
1845 if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) { 2330 if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) {
1846 device_remove_file(&hdev->dev, &dev_attr_range); 2331 hidpp_ff_deinit(hdev);
1847 hid_hw_close(hdev); 2332 hid_hw_close(hdev);
1848 } 2333 }
1849 hid_hw_stop(hdev); 2334 hid_hw_stop(hdev);