The online racing simulator
Logitech Driving Force GT (DFGT) calibration with LTWheelConf
For testing reasons, I picked up the relevant code from the LTWheelConf for calibration of Driving Force GT DFGT.

In a separate thread (C++) I keep on checking whether the wheel is physically connected or not (by checking the read() status).

When I run this program the first time, the wheel options get set perfectly and the wheel rotates up to 900 degrees (as desired).

While the program continues running, I manually take out the wheel wire and then reconnect it again.

The modified code detects the reconnection, and thus recalls the all relevant LTWheelConf functions again (based on the originally supplied parameters like -w DFGT, native mode, range 900, autocenter=0).

All works fine - except that the wheel's rotation range gets automatically set to 180 degrees rather than the original 900 degrees.

I tried to reset the driver too (libusb_reset_device), but that doesn't help.

Any ideas?
The wheel has to be sent a specific command that makes it switch from fallback mode to native mode. In the fallback mode the wheel identifies and behaves like an old Logitech Driving Force (PID C294). 900 deg mode, extra buttons and stuff work only in the native mode. The command has to be sent EVERY time the wheel is connected. Also the wheel doesn't default to 900 range even in the native mode, you should specify the desired range after the wheel switches to the native mode.

You might try the latest 3.2 kernel which is patched to handle Logitech wheels properly.
Quote from MadCatX :The wheel has to be sent a specific command that makes it switch from fallback mode to native mode.

Thanks for replying.

Actually, after reconnecting, the following code gets called: See the red.

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();
}

This even prints the proper messages. Did you mean something else?
Quote from MadCatX :
You might try the latest 3.2 kernel which is patched to handle Logitech wheels properly.

I am currently on 2.6.34 kernel (64 bit) Suse 11.3.
I can't test your code at the moment, but you should see the wheel identified as 046D:C294 in dmesg when the kernel picks it up. When the wheel switches to the native mode the ID should change to 046D:C29A. Does the kernel pick the wheel up correctly after reconnecting?
Thanks again.

Is this what you were talking about?

[ 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

-EDIT: The above output is what I get from the end of the dmesg-

This is after the reconnection. wheel is stuck at 180. :mad:
Well, anyway, here is the whole dmesg.

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 #

There is apparently something going wrong as you get an error every time the device is probed. Was your application running when you plugged the wheel in for the first time?
I take it that your application claims and releases the USB interface whenever it sends a command to the wheel. Perhaps you could redesign it to claim the interface only once, set the wheel up completely and then release the interface? Have you checked for libusb error codes? Is the "set range" really sent to the wheel?
I don't recall anybody reporting such problem during the LTWC development.
Thanks for following up.

I found this: http://permalink.gmane.org/gma ... ibusb.devel.general/12888

and you were right, the code is claiming and releasing the interface before and after sending a command.

See this:
I haven't "touched" this code. this is from the LTconf's wheelFunctions.c file.

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;
}

One way to set the wheel up completely and then release the interface is by making the variables global (currently the handle is local)? How and why will that help, BTW?

Actually, now, the code of calling these usb functions is in a while (1) loop currently.
After the wire is "plugged" in, I start this program.
The wheel gets configured properly.
I take out the wire, and then plug it back again.
This time too the wheel gets configured "properly" but after a few seconds, these messages get displayed:

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 :-(

Please see if you can guide.
Without seeing the full source I can be only guessing, but if the wheel is configured properly, can it be a bug in the function that looks for the wheel? LTWC could this error when you try to switch a wheel to the native mode which is already switched. Do you check of the "native wheel" first?
Instead of polling the connected devices and looking for the wheel you could set up an udev rule which would call appropriate application automatically.
Okay so here is the code: (Combined in one file)
Have attached the zip file at the end of the post.

Required untouched functions from the wheels.c. I have removed the extra functions.

#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;
}

The major three functions of wheelfunctions.c. These are the ones needed for setting autocenter, nativemode, and the wheel name and range. I have removed the extra ones here too.

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;
}

and finally the main(): The while loop is only for the process running forever.

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;
}

Attached files
zipfile.zip - 3.2 KB - 282 views
I'm sorry for the late response, but I finally found some time to modify your application to test it with my DFP. It seemed to be working fine for me in Ubuntu 11.10 with 3.0.0 kernel.
I was able to reproduce the problem with the wheel not being detected in native nor restricted mode and in my case it was down to the kernel not parsing its device descriptor properly (there was a known problem with DFP which is fixed in the recent kernels). Perhaps the way this application repeatedly claims and releases the USB interface somehow confuses the USB subsystem, I really don't think this is a proper way to do this.

Instead of this approach, I recommend that you either
- Adopt the patch for 2.6.33 kernel (should not be a problem)
- Set up udev rules to switch your DFGT to native mode and set correct range/autocentering once the switch is done. (MikeB has an example udev rule for this in the LTWC thread).
MadCatX,

Thanks for testing the code.

Some days back my ex boss discovered that this problem occurs when we plug the wheel plug out and then plug it "back" again, and the LTconf configuration program (which in my case runs in an infinite loop) writes the configurations to the driver file BEFORE our wheel can complete its "initial default rotation".

So, we decided to put a sleep(7) before the code which configures the wheel so that the code doesn't start executing till the rotation completes. This trick worked.

Currently we haven;t updated to kernel 3.0.

Thanks for your help and tests.
Quote from Anisha Kaul :MadCatX,

Thanks for testing the code.

Some days back my ex boss discovered that this problem occurs when we plug the wheel plug out and then plug it "back" again, and the LTconf configuration program (which in my case runs in an infinite loop) writes the configurations to the driver file BEFORE our wheel can complete its "initial default rotation".

So, we decided to put a sleep(7) before the code which configures the wheel so that the code doesn't start executing till the rotation completes. This trick worked.

Currently we haven;t updated to kernel 3.0.

Thanks for your help and tests.

You're welcome. This is actually a valuable piece of information because all wheels we had a chance to test with didn't seem to care when the "go native" command was sent. I guess I should get someone to test this a bit more because the patched kernel driver does not take this into account.

FGED GREDG RDFGDR GSFDG