1
votes

So I've been playing with the controllers for the PS2 game, Buzz. I've successfully used libusb to poll and read the buttons, and all is merry and bright.

The trouble is, I'd love to use the in-built lights to signal the folks who're using them (specifically to show them who has buzzed first). I know there's lights, I know that the PS2 was able to turn them on and off at will, and I know that someone has managed it with python. So I set out to implement their code with libusb in Ruby.

I've reproduced the SET_CONFIGURATION call they're making but I keep getting this error:

/home/ajfaraday/.rvm/gems/ruby-2.2.1/gems/libusb-0.5.0/lib/libusb/dev_handle.rb:539:in `submit_transfer': 
error TRANSFER_STALL (LIBUSB::ERROR_PIPE)

I can't find any material online about what this error is, except that it's a USB pipe error which is being translated to TRANSFER_STALL by libusb.

I also wrote it out in python, with the specific line from the forum above, and I got something that looks like the same error:

usb.core.USBError: [Errno 32] Pipe error

So I'm at a loss to find out what I'm doing wrong. I've managed to make the opposite call (GET_CONFIGURATION) to a successful response (\x00).

Here's my reproduction script (depends on the libusb gem):

require 'libusb'

usb_context = LIBUSB::Context.new
device = usb_context.devices(
  idVendor: 0x054c, idProduct: 0x0002
).first
handle = device.open

puts 'get configuration:'
x = handle.control_transfer(
  :bmRequestType => "10000000".to_i(2),
  :bRequest => 8,
  :wValue => 0,
  :wIndex => 0,
  :dataIn => 1
)  
puts x.inspect

puts 'set configuration:'
x = handle.control_transfer(
  :bmRequestType => "00000000".to_i(2),
  :bRequest => 9,
  :wValue => 0,
  :wIndex => 0,
  :dataOut => "\x00\xFF\xFF\xFF\xFF"
)
puts x.inspect

And here's it's output:

get configuration:
"\x00"
set configuration:
/home/ajfaraday/.rvm/gems/ruby-2.2.1/gems/libusb-0.5.0/lib/libusb/dev_handle.rb:539:in `submit_transfer': error TRANSFER_STALL (LIBUSB::ERROR_PIPE)
    from /home/ajfaraday/.rvm/gems/ruby-2.2.1/gems/libusb-0.5.0/lib/libusb/dev_handle.rb:515:in `control_transfer'
    from sketches/raw_script.rb:22:in `<main>'

It looks like the pipe error means there's something wrong with the setup or data I'm sending out, but I can't find out anywhere what it is.

I've tried:

  • putting different amounts of data into the dataOut attribute, too.
  • detaching the kernel driver first, also re-opening the handle
  • expressing the dataOut attribute as an array
  • running it on another (linux) machine
  • checking the libusb source code (it's converting a USB message, nothing more)
  • Using different types of message as defined in http://www.usbmadesimple.co.uk/ums_4.htm

I'd be very grateful of any assistance. This really should be possible, and I know it's been done.

1
I don't have time to go debugging this right now, but it appears your error is coming from around here: github.com/larskanis/libusb/blob/master/lib/libusb/… - Brennan
I had traced this back to the library. Unfortunately it really just tells me that it's translating a USB error. I might update the question to reflect this. - AJFaraday
I'm curious about if sending the string as opposed to the raw bytes is causing trouble. What happens if dataOut sends raw bytes instead: :dataOut => [0x00, 0xFF, 0xFF, 0xFF, 0xFF] - Brennan
The api calls for a string in :dataOut: rubydoc.info/gems/libusb/LIBUSB%2FDevHandle%3Acontrol_transfer it doesn't play nice with arrays... 'control_transfer': undefined method 'bytesize' for [0, 255, 255, 255, 255]:Array (NoMethodError) - AJFaraday
This kind of stuff is very dependent on what operating system you are using, which you neglected to mention. - David Grayson

1 Answers

1
votes

Libusb provides two functions named libusb_set_configuration and libusb_get_configuration. You should try to use those instead of rolling your own control transfers to do the same thing. They are documented here:

http://libusb.sourceforge.net/api-1.0/group__dev.html

You can check the source code or documentation of the Ruby libusb binding you are using to figure out how to call them from Ruby.

Also, setting a configuration is a semi-unusual thing to do to a USB device. You should make sure the drivers on your operating system do not already put the device into the correct configuration. Maybe you don't need to set the configuration.

Also, if this controller is an HID, the hidapi library might be a better fit than libusb.