[haiku-development] Re: Joystick support

  • From: "Michael Lotz" <mmlr@xxxxxxxx>
  • To: haiku-development@xxxxxxxxxxxxx
  • Date: Thu, 17 Dec 2009 12:43:44

> 2009/12/17 Michael Lotz <mmlr@xxxxxxxx>:
> > That driver used a subset of HID to specifically support joysticks. 
> > The
> > usb_hid driver does parse and provide an internal API to use full 
> > HID
> > devices. So whatever you do, don't build a new driver, add it as a 
> > *
> > Device/ProtocolHandler to usb_hid and use the internal API to make 
> > use
> > of the HID data.
> Yes, that is exactly what I've started to do.

Just don't waste too much time to implement something for joystick like 
devices. If you eventually go with the framework then it would be easy 
to make BJoystick a client of that and drop any specific protocol you 
implement now.

> > But if you think along this line a bit further you will realize 
> > that
> > it's pretty pointless to add "joystick support". The only real use 
> > of
> > joystick support would be the legacy BJoystick API. Everything else
> > should not happen on the "this is a joystick, that is a gamepad, 
> > the
> > other one is some more complex other controller" level. HID was
> > invented to generically describe input (and output) devices so that 
> > you
> > don't have to do this categorization. If you read the specs it 
> > becomes
> > clear that the intention was that ultimately the client application
> > gets a nice way to extract data from devices and picks out what it
> > needs. Take a game where you control an airplane, the game just 
> > needs a
> > stream of x, y and maybe z coordinates. Whether they come from a
> > joystick, a data glove or even simply a mouse doesn't really matter.
> IMHO: As long as application will know what type of input device it 
> is
> and could choose whether to use it or not, yes. Don't know if it's
> always appropriate to use mouse as joypad for example.
> I think most of existing game input frameworks separates keyboards 
> and
> mice from everything else. Some of them even don't support the former
> at all. MS recommendation is not to use DI for keyboards and mice.

Why would the app care? HID has usage IDs which pretty specifically 
describe the function of an element. They are grouped into collections 
to form logical devices. The app can deduce from that what type of 
control it is and if it is a good choice to use it. The sensible 
application would then pick the best fitting controls as defaults and 
let the user choose from all the enumerated other controls. IMO the 
distinction between keyboards/mice and other input devices is mostly a 
historical one and comes from the fact that the OS already provides 
these. In the keyboard case you probably would want the OS provided 
info over the framework one, because in that case the OS would handle 
all the key-mapping logic while if you go through the framework you 
would simply get the individual keys. But already for mice it would 
make it more easy for an app to use the framework, because then it 
wouldn't need to implement two distinct ways of getting axis data. It 
of course depends largely on the application. In cases where you use OS 
native widgets and stuff you would want to use the normal mouse cursor 
and therefore also use the view based mouse handling. If on the other 
hand you have a game where you implement your own fancy OpenGL menu 
system anyway, you could care less about the traditional mouse hooks.

The general idea is that there are so many devices out there that have 
very different functionality but all export this information as nice 
HID descriptors. So why should the driver pick out some parts of these 
packages and only relay them to userland? It imposes a data loss by 
fitting a device into a certain category. If you provide the framework 
and let the app decide what info it wants to use and how it just makes 
more sense. It also avoids the need for device vendors (or more likely 
us) to write specific drivers that pick out different info from the 
same devices. Just think about how stupid it would be if you'd have to 
write an extra driver just to make some motion sensor available in a 
device that otherwise is perfectly HID solely because some limited API 
in the OS or the suposedly generic driver doesn't provide the needed 
data fields.

> > The conclusion is that what should be implemented is a generic 
> > input/
> > output framework that pretty much just forwards what the usb_hid
> > internal API already provides to userland. Whether or not this goes
> > through the input_server or if it is a standalone class that 
> > directly
> > communicates with a device by the means of some ioctl protocol 
> > doesn't
> > matter either. This generic API then should allow an application to
> > enumerate what data fields are available and "subscribe" to them in
> > some way or another.
> >
> > This framework then uses usb_hid and possible vendor specific 
> > protocols
> > to uniformly present "input/output" to the application. By 
> > designing it
> > along the lines of HID you can pretty much map any legacy device in
> > with very little effort. If you wanted to go the full distance you 
> > can
> > in the end also do the mouse/keyboard legacy drivers as backends to
> > this framework and the input_server just becomes a normal user of 
> > the
> > framework and enumerates the input devices to pick out keyboards/
> > mice/
> > phones/whatever.
> Yes, this all sounds nice. If this would be a standalone class it
> could also have an advantage of better "integration' of client app (a
> game) with the controller, allowing it to poll the data when it really
> needs it. Here legacy BJoystick API would fit nicely. And when the
> event based handling is needed, it could start automatic polling and
> broadcasting of messages.

You don't really want to poll. The best way to go is usually to setup a 
condition to wait on and then wait. In the case of input you'd pick out 
the data items you are interested in and then wait on them. That's how 
it is implemented in usb_hid. The handlers pick out the keys/buttons/
axis they are interested in and then block on the report. As soon as 
one comes in they go through the collection of items and check for 
updates. Something similar could be exported to userland. The framework 
could also abstract this internally, so that you'd only send messages 
out for actual changes. The app would then subscribe to some controls 
it is interested in. If it isn't interested in them for a while it 
could always unsubscribe from them.

Backing a polling interface by such an event based framework is pretty 
much a nobrainer, as you'd simply keep a state, modify it on events and 
return it on polls. Latency isn't an issue. You don't get any better 
latency with the polling interface, that's just the downside of polling 

> It all sounds pretty much like a plan, have you already thought about
> implementing such framework?

It's pretty obvious to implement it that way. It's just a bit of work 
to come up with a good design that is efficient and easy for the app 
developer to use. The protocol between the framework and the driver is 
the easiest part really. There needs to be a way to enumerate devices, 
collections of controls inside them that group certain functionality 
and then the individual controls. Then you need a way to start 
listening to events on these controls. Handing out control IDs and then 
being able to start listening by supplying the ID + some BLooper should 
be easy enough.

To reduce duplicated work it'd make sense if the input_server would do 
the state keeping and management and be the one who sends out the event 
messages to the different apps that are listening.


Other related posts: