Hi folks - question from newbie.

There is a piece of software that was written several years ago to allow Linux 
users to configure a USB joystick from Ultimarc.  The company has Windows 
specific tools but no formal support for Linux.
The tool relies on libhid and the libusb-compat libraries.  A recent firmware 
change for this joystick seems to have broken the current version of the Linux 
configuration tool and I am trying to get some help modifying it to work with 
this latest FW update.

The joystick is VID/PID d209:0511.  It exposes three separate endpoints, EP 2 
IN (0x82) which is the two-axis joystick, EP 1 IN which allows the joystick to 
sometimes behave as a mouse, and then there is EP 3 IN (0x83) which is 
evidently the endpoint that needs to be written to in order to configure the 
stick.

The present version of the application is successful at finding and 
force_opening the device, but I have a suspicion that it may not be writing to 
the correct endpoint with this latest firmware release.  The stick manufacturer 
confirms that they used to use libusb under Windows, but with this latest 
release they use native Windows functionality to write to the HID device.  They 
also confirm that EP3 is where the data's supposed to go.  However, they 
haven't been entirely forthcoming with complete documentation of the 
vendor-specific protocol, but they claim no changes have been made in the 
actual data that needs to be transmitted to the device.

The existing version of the utility seems to rely on making calls to 
usb_control_msg() to actually send the data, but the behavior I see now with 
the latest firmware is that the line I've marked below with an arrow always 
fails with EPIPE, saying that the endpoint is stalled.  (I added some debug 
prints to my copy of the code to inspect the return values, which the original 
author was ignoring.)  Unfortunately I'm a little new to USB programming (at 
least at this level of detail) and am having a little difficulty in translating 
the calls the original author of the application (now unresponsive) is making 
into the commands in the USB spec, and therefore, what I would need to change 
in order to make a hopefully simple change to direct the traffic to endpoint EP 
3, (if indeed that is the problem.)

I've included a snippet of the app below, please let me know if there's 
something reasonably obvious I can change to ensure that the data goes to the 
correct endpoint, or whether there is potentially some other avenue of 
investigation I should be looking at.  I can always email the entire single 
source file (it's not very long) if you need to see more, but I think this is 
really the relevant piece.  I don't want to rewrite the whole app, I just want 
to get it basically functional again.  Thanks for any/all help!

// *********************Send Map Transfer*******************************
                                // This is only for Map Size = 9
                                //
                                // 3 "Data Write" Transfers of 32 Bytes
                                // -First Transfer-
                                // Byte[0] = 0x50 (Header)
                                // Byte[1] = 0x09 (Map Size?)
                                // Byte[2] = Restrictor (RestrictorOn = 0x09, 
RestrictorOff = 0x10)
                                // Byte[3]-Byte[10] = Map Border Location
                                // Byte[11]-Byte[31] = Mapping of Block 
Location. starting from topleft and read left to right.
                                //
                                // -Second Transfer-
                                // 32 Bytes - Continue Mapping of Block Location
                                //
                                // -Third Transfer-
                                // Byte[0]-Byte[27] - Continue Mapping of Block 
Location
                                // Byte[28]-Byte[30] - 0x00
                                // Byte[31] - (Write to Flash 0x00) (Write to 
RAM 0xFF, supported in Firmware 2.2)
                                //
                                //
                                // 
****************************************************
                                // USB      Mapping
                                // 0x00 =   Analog (-)
                                // 0x01 =   Center (C)
                                // 0x02 =   Up (N)
                                // 0x03 =   UPRight (NE)
                                // 0x04 =   Right (E)
                                // 0x05 =   DownRight (SE)
                                // 0x06 =   Down (S)
                                // 0x07 =   DownLeft (SW)
                                // 0x08 =   Left (W)
                                // 0x09 =   UPLeft (NW)
                                // 0x0A =   Sticky (*)

                                // MapFileFormatVersion=1.0

                                // MapSize=9
                                // 
MapBorderLocations=30,58,86,114,142,170,198,226
                                // MapRow1=W,W,W,C,C,C,E,E,E
                                // MapRow2=W,W,W,C,C,C,E,E,E
                                // MapRow3=W,W,W,C,C,C,E,E,E
                                // MapRow4=W,W,W,C,C,C,E,E,E
                                // MapRow5=W,W,W,C,C,C,E,E,E
                                // MapRow6=W,W,W,C,C,C,E,E,E
                                // MapRow7=W,W,W,C,C,C,E,E,E
                                // MapRow8=W,W,W,C,C,C,E,E,E
                                // MapRow9=W,W,W,C,C,C,E,E,E

                                if(arguments.rowcount == 9){

                                                int usbret = 
usb_control_msg(hid->dev_handle,0x43,0xE9,0x0001, 0 , NULL, 0,1000);
                                                char data[32*3]; // 9*9 + 3 + 8 
+ 1 round up to nearest 32 block.
                                                memset(data,0,sizeof(data));

                                                data[0]  = 0x50; // Byte[0] = 
0x50 (Header)
                                                data[1]  = 0x09; // Byte[1] = 
0x09 (Map Size?)
                                                data[2] = ( 
arguments.restrictor ? 0x09 : 0x10 ); // Byte[2] = Restrictor (RestrictorOn = 
0x09, RestrictorOff = 0x10)
                                                data[95] = ( arguments.flash ? 
0x00 : 0xFF ); // Byte[31] - (Write to Flash 0x00) (Write to RAM 0xFF, 
supported in Firmware 2.2)

                                                if(arguments.border_set){
                                                                // 
Byte[3]-Byte[10] = Map Border Location
                                                                
memcpy(&data[3],arguments.border,sizeof(arguments.border));
                                                }

                                                
memcpy(&data[11],arguments.matrix,9*9);

                                                for(int i=0;i<3;i++){
                                                                usbret = 
usb_control_msg(hid->dev_handle,0x43,0xEB,0x0000, 0 , data+(32*i), 
sizeof(data)/3,1000);

This fails---------------->                  usbret = 
usb_control_msg(hid->dev_handle,0xC3,0xEA,0x0000, 0 , NULL, 0 ,1000);

                                                }

                                                usbret = 
usb_control_msg(hid->dev_handle,0x43,0xE9,0x0000, 0 , NULL, 0,1000);
                                }
                }
_______________________________________________
libhid-discuss mailing list
libhid-discuss@lists.alioth.debian.org
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/libhid-discuss
http://libhid.alioth.debian.org/

Reply via email to