config [COLOR="red"]LOGIWHEELS_FF [/COLOR]
bool "Logitech force feedback support"
depends on HID_LOGITECH
[COLOR="Red"]default y [/COLOR]
select INPUT_FF_MEMLESS
help
Say Y here if you have one of these devices:
-Logitech WingMan Cordless RumblePad
-Logitech WingMan Cordless RumblePad 2
-Logitech WingMan Force 3D
-Logitech Formula Force EX
-Logitech WingMan Formula Force GP
-Logitech MOMO Force wheel
and if you want to enable force feedback for them.
Note: if you say N here, this device will still be supported, but without
force feedback
linux-dopx:/home/anisha/ # fftest /dev/input/event4
Force feedback test program.
HOLD FIRMLY YOUR WHEEL OR JOYSTICK TO PREVENT DAMAGES
Device /dev/input/event4 opened
Axes query:
Effects: Constant
Number of simultaneous effects: 16
Upload effects[0]: Invalid argument
Upload effects[2]: Invalid argument
Upload effects[3]: Invalid argument
Upload effects[4]: Invalid argument
Upload effects[5]: Invalid argument
Enter effect number, -1 to exit
1
Now Playing: Constant Force
Enter effect number, -1 to exit
linux-dopx:/home/anisha/tarBalls/TripleSpeeder-LTWheelConf-665e227 # [B]./ltwheelconf --wheel DFGT --nativemode --range 900 --autocenter 0 --gain=100 -d /dev/input/event4[/B]
Found a Driving Force GT already in native mode.
Wheel rotation range of Driving Force GT is now set to 900 degrees.
Autocenter for Driving Force GT is now set to 0 with rampspeed 0.
Wheel forcefeedback gain is now set to 100.
linux-dopx:/home/anisha # [B]fftest /dev/input/event4[/b]
Force feedback test program.
HOLD FIRMLY YOUR WHEEL OR JOYSTICK TO PREVENT DAMAGES
Device /dev/input/event4 opened
Axes query:
Effects:
Number of simultaneous effects: 0
[B]Upload effects[0]: Function not implemented
Upload effects[1]: Function not implemented
Upload effects[2]: Function not implemented
Upload effects[3]: Function not implemented
Upload effects[4]: Function not implemented
Upload effects[5]: Function not implemented[/B]
Enter effect number, -1 to exit
^C
linux-dopx:/home/anisha # [B]ffcfstress -d /dev/input/event4[/B]
ERROR: device (or driver) has no force feedback support [ffcfstress.c:165]
linux-dopx:/home/anisha/# [B]ffcfstress -d /dev/input/js0 [/B]
ERROR: can not get key bits (Invalid argument) [ffcfstress.c:118]
#include "writeToJoystickDriver.h"
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <linux/input.h>
#define TRANSFER_WAIT_TIMEOUT_MS 5000
#define CONFIGURE_WAIT_SEC 3
#define UDEV_WAIT_SEC 2
int get_nativemode_cmd_DFGT (cmdstruct *c)
{
c->cmds[0][0] = 0xf8;
c->cmds[0][1] = 0x0a;
c->cmds[0][2] = 0x00;
c->cmds[0][3] = 0x00;
c->cmds[0][4] = 0x00;
c->cmds[0][5] = 0x00;
c->cmds[0][6] = 0x00;
c->cmds[0][7] = 0x00;
c->cmds[1][0] = 0xf8;
c->cmds[1][1] = 0x09;
c->cmds[1][2] = 0x03;
c->cmds[1][3] = 0x01;
c->cmds[1][4] = 0x00;
c->cmds[1][5] = 0x00;
c->cmds[1][6] = 0x00;
c->cmds[1][7] = 0x00;
c->numCmds = 2;
return 0;
}
/* used by DFGT, G25, G27 */
int get_range_cmd(cmdstruct *c, int range)
{
c->cmds[0][0] = 0xf8;
c->cmds[0][1] = 0x81;
c->cmds[0][2] = range & 0x00ff;
c->cmds[0][3] = (range & 0xff00)>>8;
c->cmds[0][4] = 0x00;
c->cmds[0][5] = 0x00;
c->cmds[0][6] = 0x00;
c->cmds[0][7] = 0x00;
c->numCmds = 1;
return 0;
}
/* used by all wheels */
int get_autocenter_cmd(cmdstruct *c, int centerforce, int rampspeed)
{
c->cmds[0][0] = 0xfe;
c->cmds[0][1] = 0x0d;
c->cmds[0][2] = rampspeed & 0x0f;
c->cmds[0][3] = rampspeed & 0x0f;
c->cmds[0][4] = centerforce & 0xff;
c->cmds[0][5] = 0x00;
c->cmds[0][6] = 0x00;
c->cmds[0][7] = 0x00;
c->numCmds = 1;
return 0;
}
void [COLOR="Red"][B]print_cmd[/B][/COLOR](char *result, unsigned char cmd[8]) {
sprintf(result, "%02X %02X %02X %02X %02X %02X %02X %02X", cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], cmd[6], cmd[7]);
}
int [B][COLOR="Red"]send_command[/COLOR][/B](libusb_device_handle *handle, cmdstruct command ) {
if (command.numCmds == 0) {
printf( "send_command: Empty command provided! Not sending anything...\n");
return 0;
}
int stat;
stat = libusb_detach_kernel_driver(handle, 0);
if ((stat < 0 ))// || verbose_flag)
perror("Detach kernel driver");
stat = libusb_claim_interface( handle, 0 );
if ( (stat < 0))
{ //|| verbose_flag)
perror("Claiming USB interface");
}
int transferred = 0;
// send all command strings provided in command
int cmdCount;
for (cmdCount=0; cmdCount < command.numCmds; cmdCount++) {
if (1){//verbose_flag) {
char raw_string[255];
print_cmd(raw_string, command.cmds[cmdCount]);
printf("\tSending string: \"%s\"\n", raw_string);
}
stat = libusb_interrupt_transfer( handle, 1, command.cmds[cmdCount], sizeof( command.cmds[cmdCount] ), &transferred, TRANSFER_WAIT_TIMEOUT_MS );
/*if ( stat < 0) {
//|| verbose_flag)
perror("Sending USB command");
}*/
if ( stat < 0) perror("Sending USB command");
}
/* In case the command just sent caused the device to switch from restricted mode to native mode
* the following two commands will fail due to invalid device handle (because the device changed
* its pid on the USB bus).
* So it is not possible anymore to release the interface and re-attach kernel driver.
* I am not sure if this produces a memory leak within libusb, but i do not think there is another
* solution possible...
*/
stat = libusb_release_interface(handle, 0 );
if (stat != LIBUSB_ERROR_NO_DEVICE) { // silently ignore "No such device" error due to reasons explained above.
if ( (stat < 0)){// || verbose_flag) {
perror("Releasing USB interface.");
}
}
stat = libusb_attach_kernel_driver( handle, 0);
if (stat != LIBUSB_ERROR_NO_DEVICE) { // silently ignore "No such device" error due to reasons explained above.
if ( (stat < 0)){// || verbose_flag) {
perror("Reattaching kernel driver");
}
}
return 0;
}
int [COLOR="Red"][B]set_native_mode[/B][/COLOR](wheelstruct* w)
{
// first check if wheel has restriced/native mode at all
if (w->native_pid == w->restricted_pid) {
printf( "%s is always in native mode.\n", w->name);
return 0;
}
// check if wheel is already in native mode
libusb_device_handle *handle = libusb_open_device_with_vid_pid(NULL, VID_LOGITECH, w->native_pid);
if ( handle != NULL ) {
printf( "Found a %s already in native mode.\n", w->name);
return 0;
}
// try to get handle to device in restricted mode
handle = libusb_open_device_with_vid_pid(NULL, VID_LOGITECH, w->restricted_pid );
if ( handle == NULL ) {
printf( "Can not find %s in restricted mode (PID %x). This should not happen :-(\n", w->name, w->restricted_pid);
return -1;
}
// check if we know how to set native mode
if (!w->get_nativemode_cmd) {
printf( "Sorry, do not know how to set %s into native mode.\n", w->name);
return -1;
}
cmdstruct c;
memset(&c, 0, sizeof(c));
w->get_nativemode_cmd(&c);
send_command(handle, c);
// wait until wheel reconfigures to new PID...
sleep(CONFIGURE_WAIT_SEC);
// If above command was successfully we should now find the wheel in extended mode
handle = libusb_open_device_with_vid_pid(NULL, VID_LOGITECH, w->native_pid);
if ( handle != NULL ) {
printf ( "%s is now set to native mode.\n", w->name);
} else {
// this should not happen, just in case
printf ( "Unable to set %s to native mode.\n", w->name );
return -1;
}
libusb_close(handle);
return 0;
}
short unsigned int [B][COLOR="Red"]clamprange[/COLOR][/B](wheelstruct* w, short unsigned int range)
{
if (range < w->min_rotation) {
printf("Minimum range for %s is %d degrees.\n", w->name, w->min_rotation);
range = w->min_rotation;
}
if (range > w->max_rotation) {
range = w->max_rotation;
printf("Maximum range for %s is %d degrees.\n", w->name, w->max_rotation);
}
return range;
}
int [COLOR="Red"][B]set_range[/B][/COLOR](wheelstruct* w, short unsigned int range)
{
libusb_device_handle *handle = libusb_open_device_with_vid_pid(NULL, VID_LOGITECH, w->native_pid );
if ( handle == NULL ) {
printf ( "%s not found. Make sure it is set to native mode (use --native).\n", w->name);
return -1;
}
if (!w->get_range_cmd) {
printf( "Sorry, do not know how to set rotation range for %s.\n", w->name);
return -1;
}
cmdstruct c;
memset(&c, 0, sizeof(c));
w->get_range_cmd(&c, range);
send_command(handle, c);
printf ("Wheel rotation range of %s is now set to %d degrees.\n", w->name, range);
libusb_close(handle);
return 0;
}
int [B][COLOR="Red"]set_autocenter[/COLOR][/B](wheelstruct* w, int centerforce, int rampspeed)
{
libusb_device_handle *handle = libusb_open_device_with_vid_pid(NULL, VID_LOGITECH, w->native_pid );
if ( handle == NULL ) {
printf ( "%s not found. Make sure it is set to native mode (use --native).\n", w->name);
return -1;
}
if (!w->get_autocenter_cmd) {
printf( "Sorry, do not know how to set autocenter force for %s. Please try generic implementation using --alt_autocenter.\n", w->name);
return -1;
}
cmdstruct c;
memset(&c, 0, sizeof(c));
w->get_autocenter_cmd(&c, centerforce, rampspeed);
send_command(handle, c);
printf ("Autocenter for %s is now set to %d with rampspeed %d.\n", w->name, centerforce, rampspeed);
libusb_close(handle);
return 0;
}
int main () {
[B]while (1)[/B]
{
unsigned short int range = 0;
unsigned short int centerforce = 0;
char device_file_name[128];
char shortname[255];
memset(device_file_name, 0, sizeof(device_file_name));
range = 900;
centerforce = 0;
strncpy(shortname, "DFGT", 255);
libusb_init(NULL);
libusb_set_debug(0, 3);
wheelstruct* wheel = 0;
// do_validate_wheel
int numWheels = sizeof(wheels)/sizeof(wheelstruct);
int i = 0;
for (i=0; i < numWheels; i++) {
if (strncasecmp(wheels[i].shortname, shortname, 255) == 0) {
// found matching wheel
wheel = &(wheels[i]);
break;
}
}
if (!wheel) {
printf("Wheel \"%s\" not supported. Did you spell the shortname correctly?\n", shortname);
}
/[COLOR="Red"][B]/ do_native
set_native_mode(wheel);
// do_range
set_range(wheel, clamprange(wheel, range));
// do_autocenter
set_autocenter (wheel, centerforce, 0);[/B][/COLOR]
libusb_exit(NULL);
}
return 0;
}
int send_command(libusb_device_handle *handle, cmdstruct command ) {
if (command.numCmds == 0) {
printf( "send_command: Empty command provided! Not sending anything...\n");
return 0;
}
int stat;
[COLOR="Red"][B]stat = libusb_detach_kernel_driver(handle, 0);
if ((stat < 0 ))// || verbose_flag)
perror("Detach kernel driver");
stat = libusb_claim_interface( handle, 0 );
if ( (stat < 0))
{ //|| verbose_flag)
perror("Claiming USB interface");
}[/B][/COLOR]
int transferred = 0;
// send all command strings provided in command
int cmdCount;
for (cmdCount=0; cmdCount < command.numCmds; cmdCount++) {
if (1){//verbose_flag) {
char raw_string[255];
print_cmd(raw_string, command.cmds[cmdCount]);
printf("\tSending string: \"%s\"\n", raw_string);
}
stat = libusb_interrupt_transfer( handle, 1, command.cmds[cmdCount], sizeof( command.cmds[cmdCount] ), &transferred, TRANSFER_WAIT_TIMEOUT_MS );
/*if ( stat < 0) {
//|| verbose_flag)
perror("Sending USB command");
}*/
if ( stat < 0) perror("Sending USB command");
}
[COLOR="SeaGreen"]/* In case the command just sent caused the device to switch from restricted mode to native mode
* the following two commands will fail due to invalid device handle (because the device changed
* its pid on the USB bus).
* So it is not possible anymore to release the interface and re-attach kernel driver.
* I am not sure if this produces a memory leak within libusb, but i do not think there is another
* solution possible...
*/[/COLOR]
s[COLOR="Red"][B]tat = libusb_release_interface(handle, 0 );
if (stat != LIBUSB_ERROR_NO_DEVICE) { // silently ignore "No such device" error due to reasons explained above.
if ( (stat < 0)){// || verbose_flag) {
perror("Releasing USB interface.");
}
}
stat = libusb_attach_kernel_driver( handle, 0);
if (stat != LIBUSB_ERROR_NO_DEVICE) { // silently ignore "No such device" error due to reasons explained above.
if ( (stat < 0)){// || verbose_flag) {
perror("Reattaching kernel driver");
}
}[/B][/COLOR]
return 0;
}
Driving Force GT not found. Make sure it is set to native mode (use --native).
libusb:error [sysfs_scan_device] open busnum failed, errno=24
libusb:error [sysfs_scan_device] open busnum failed, errno=24
Can not find Driving Force GT in restricted mode (PID c294). This should not happen :-(
linux-dopx:# [B]dmesg[/B]
[ 8996.971013] usb 2-2: new full speed USB device using uhci_hcd and address 18
[ 8997.128002] usb 2-2: New USB device found, idVendor=046d, idProduct=c294
[ 8997.128006] usb 2-2: New USB device strings: Mfr=0, Product=2, SerialNumber=0
[ 8997.128009] usb 2-2: Product: Driving Force GT
[ 8997.137710] input: Driving Force GT as /devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0/input/input49
[COLOR=Red][B]
[ 8997.137837] logitech 0003:046D:C294.0036: input,hidraw0: USB HID v1.00 Joystick [Driving Force GT] on usb-0000:00:1d.0-2/input0[/B][/COLOR]
[ 8997.137842] Force feedback for Logitech force feedback devices by Johann Deneux <[email protected]>
[ 9005.319352] logitech 0003:046D:C294.0037: parse failed
[ 9005.319370] logitech: probe of 0003:046D:C294.0037 failed with error -71
[ 9005.454042] usb 2-2: USB disconnect, address 18
[ 9005.764015] usb 2-2: new full speed USB device using uhci_hcd and address 19
[ 9005.919296] usb 2-2: New USB device found, idVendor=046d, idProduct=c29a
[ 9005.919300] usb 2-2: New USB device strings: Mfr=0, Product=2, SerialNumber=0
[ 9005.919303] usb 2-2: Product: Driving Force GT
[ 9005.939561] input: Driving Force GT as /devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0/input/input50
[ 9005.939728] generic-usb 0003:046D:C29A.0038: input,hidraw0: USB HID v1.11 Joystick [Driving Force GT] on usb-0000:00:1d.0-2/input0
[ 9008.340387] input: Driving Force GT as /devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0/input/input51
[ 9008.340521] generic-usb 0003:046D:C29A.0039: input,hidraw0: USB HID v1.11 Joystick [Driving Force GT] on usb-0000:00:1d.0-2/input0
[ 9008.361374] input: Driving Force GT as /devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0/input/input52
[ 9008.361486] generic-usb 0003:046D:C29A.003A: input,hidraw0: USB HID v1.11 Joystick [Driving Force GT] on usb-0000:00:1d.0-2/input0
[ 9015.454167] usb 2-2: USB disconnect, address 19
[ 9021.533142] usb 2-2: new full speed USB device using uhci_hcd and address 20
[ 9021.690125] usb 2-2: New USB device found, idVendor=046d, idProduct=c294
[ 9021.690130] usb 2-2: New USB device strings: Mfr=0, Product=2, SerialNumber=0
[ 9021.690133] usb 2-2: Product: Driving Force GT
[ 9021.700145] input: Driving Force GT as /devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0/input/input53
[ 9021.700358] logitech 0003:046D:C294.003B: input,hidraw0: USB HID v1.00 Joystick [Driving Force GT] on usb-0000:00:1d.0-2/input0
[ 9021.700363] Force feedback for Logitech force feedback devices by Johann Deneux <[email protected]>
[ 9021.734120] logitech 0003:046D:C294.003C: parse failed
[ 9021.734126] logitech: probe of 0003:046D:C294.003C failed with error -71
[ 9022.047049] usb 2-2: USB disconnect, address 20
[ 9022.253018] usb 2-2: new full speed USB device using uhci_hcd and address 21
[ 9022.408065] usb 2-2: New USB device found, idVendor=046d, idProduct=c29a
[ 9022.408069] usb 2-2: New USB device strings: Mfr=0, Product=2, SerialNumber=0
[ 9022.408072] usb 2-2: Product: Driving Force GT
[ 9022.425328] input: Driving Force GT as /devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0/input/input54
[ 9022.425445] generic-usb 0003:046D:C29A.003D: input,hidraw0: USB HID v1.11 Joystick [Driving Force GT] on usb-0000:00:1d.0-2/input0
[ 9024.755225] input: Driving Force GT as /devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0/input/input55
[ 9024.755386] generic-usb 0003:046D:C29A.003E: input,hidraw0: USB HID v1.11 Joystick [Driving Force GT] on usb-0000:00:1d.0-2/input0
[ 9024.774162] input: Driving Force GT as /devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0/input/input56
[ 9024.774294] generic-usb 0003:046D:C29A.003F: input,hidraw0: USB HID v1.11 Joystick [Driving Force GT] on usb-0000:00:1d.0-2/input0
linux-dopx:/home/anisha/Desktop/wheel/finalMerge #
[ 9022.425445] generic-usb 0003:046D:C29A.003D: input,hidraw0: USB HID v1.11 Joystick [Driving Force GT] on usb-0000:00:1d.0-2/input0
[ 9024.755225] input: Driving Force GT as /devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0/input/input55
[ 9024.755386] generic-usb 0003:046D:C29A.003E: input,hidraw0: USB HID v1.11 Joystick [Driving Force GT] on usb-0000:00:1d.0-2/input0
[ 9024.774162] input: Driving Force GT as /devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0/input/input56
[ 9024.774294] generic-usb 0003:046D:C29A.003F: input,hidraw0: USB HID v1.11 Joystick [Driving Force GT] on usb-0000:00:1d.0-2/input0
if (argcc > 0)
{
libusb_init(NULL);
//if (verbose_flag > 1)
libusb_set_debug(0, 3);
int wait_for_udev = 0;
wheelstruct* wheel = 0;
if (do_help) {
help();
} else {
if (do_validate_wheel) {
int numWheels = sizeof(wheels)/sizeof(wheelstruct);
int i = 0;
for (i=0; i < numWheels; i++) {
if (strncasecmp(wheels[i].shortname, shortname, 255) == 0) {
// found matching wheel
cout << "\nfound matching wheel";
wheel = &(wheels[i]);
break;
}
}
if (!wheel) {
printf("Wheel \"%s\" not supported. Did you spell the shortname correctly?\n", shortname);
}
}
[B][COLOR=Red] if (do_native) {
if (!wheel) {
printf("Please provide --wheel parameter!\n");
} else {
cout << "\nfound matching wheel 2";
set_native_mode(wheel);
wait_for_udev = 1;
}
}[/COLOR][/B]
if (do_reset) {
if (!wheel) {
printf("Please provide --wheel parameter!\n");
} else {
int h = reset_wheel(wheel);
cout << "\nReset value: " << h;
wait_for_udev = 1;
}
}
if (do_range) {
if (!wheel) {
printf("Please provide --wheel parameter!\n");
} else {
cout << "\nfound matching wheel 3";
set_range(wheel, clamprange(wheel, range));
wait_for_udev = 1;
}
}
if (do_autocenter) {
if (!wheel) {
printf("Please provide --wheel parameter!\n");
} else {
if (centerforce == 0) {
cout << "\nfound matching wheel 4";
set_autocenter(wheel, centerforce, 0);
wait_for_udev = 1;
} else if (rampspeed == -1) {
printf("Please provide '--rampspeed' parameter\n");
} else {
cout << "\nfound matching wheel 5";
set_autocenter(wheel, centerforce, rampspeed);
wait_for_udev = 1;
}
}
}
}
libusb_exit(NULL);
} else {
// display usage information if no arguments given
help();
}
struct [URL="http://rrlib.informatik.uni-kl.de/fileadmin/rrlib/docs/mca2-kl/html/mcal_general_ext/structjs__corr.html"]js_corr[/URL] { __s32 [URL="http://rrlib.informatik.uni-kl.de/fileadmin/rrlib/docs/mca2-kl/html/mcal_general_ext/structjs__corr.html#a8de9942afd2e0a7c204637b1bcc06b81"]coef[/URL][8]; __s16 [URL="http://rrlib.informatik.uni-kl.de/fileadmin/rrlib/docs/mca2-kl/html/mcal_general_ext/structjs__corr.html#a98f99c7733f4569d9c990ec2d99d2d03"]prec[/URL]; __u16 [URL="http://rrlib.informatik.uni-kl.de/fileadmin/rrlib/docs/mca2-kl/html/mcal_general_ext/structjs__corr.html#a31ac1577e9b707e4537958f5d3f5e283"]type[/URL]; };