Drivers may vary from microcontroller to microcontroller. For example, I am wrote my own variant for STM32. But report descriptor is the main part of any HID device. While descriptors are database, which keeps device configuration, the report descriptor usually a configurations of buttons, axes, and any other controls of input device.
Lets talk about my variant. My last project was about simple USB gamepad. This gamepad has a hat switch and two buttons. Here is this descriptor entirely:
const uint8_t gamepadReportDesc[gamepadReportDescSize] =
{
0x05, 0x01, // usage_page(Generic Desctop)
0x09, 0x05, // usage(Game pad)
0xa1, 0x01, // collection(Application)
0x09, 0x01, // usage(Pointer)
0xa1, 0x00, // collection(Physical)
0x09, 0x30, // usage(X)
0x09, 0x31, // usage(Y)
0x15, 0xff, // logical minimum(-1)
0x25, 0x01, // logical maximum(1)
0x95, 0x02, // report_count(2)
0x75, 0x02, // report_size(2)
0x81, 0x02, // input(Data,Var,Abs)
0x05, 0x09, // usage_page(Button)
0x19, 0x01, // usage_minimum(button1)
0x29, 0x02, // usage_maximum(button2)
0x15, 0x00, // logical minimum(0)
0x25, 0x01, // logical maximum(1)
0x95, 0x02, // report_count(2)
0x75, 0x01, // report_size(1)
0x81, 0x02, // input(Data,Var,Abs)
// byte alingment
0x95, 0x02, // report_count(2)
0x75, 0x01, // report_size(1)
0x81, 0x01, // input(Const)
0xc0, // end_collection (physical)
0xc0 // end_collection (application)
};
That structure is more complicated than it seems to. The report consists of items. Usually we deal with the main items, also there are global tags, which affects at all items while its parentheses not closed.
So, the typical main item tempate consist of:
Lets check theory on the example of axis:
- usage_page(Generic_Desctop) - stangard type of generic desctop PC device
- usage(Game pad) - this tag means that we deal with game pad
- usage(Pointer) - we position the pointer by folowing axes
- usage(X) - declare x axis
- usage(Y) - declare y axis
- logical minimum(-1) - the axis changes from -1 to 1
- logical maximum(1)
- report_count(2) - there are two axis
- report_size(2) - every axis takes 2 bits
- input(Data,Var,Abs) - the item of pointer consisting of two axes is input type item
The buttons example is much simple cause we do not need to announce tags again which are right for the all device, I mean usage_page(Generic Desctop) and usage(Game pad) tags.
- usage_page(Button) - here are click buttons array
- usage_minimum(button1) - from one up to two, two buttons
- usage_maximum(button2)
- logical minimum(0) - button changes its state from 0 to 1
- logical maximum(1)
- report_count(2) - there are two buttons
- report_size(1) - every is one bit size
- input(Data,Var,Abs) - of course this is input item too
As well there are global tags. In this case we need collection(Application) end_collection(Application) parentheses covering all descriptor, that means that there is top-level collection of data that can be used by the host application. And collection(physical) end_collection(physical) means that items inside this parentheses data represents only one point by the multiple axes.
To the report descriptor corresponds an report. As you seen our config takes only 6 bits, i.e. 4 for two two bit axis and two for two one bit buttons. In this case standard obliges to align descriptor to bytes using const input template. So I add two one bit fields using parameters: report_count(2), report_size(1), input(const). In conclusion, to that config corresponds a report byte described on the picture:
I thought that it is implemented, but linux driver do not recognize this feature. Hat switch from the last standard specification. In result I used two 2 bit axis instead of hat for the four button d-pad. And here is a not working hat switch:
0x09, 0x39, // usage(Hat switch)
0x15, 0x01, // logical minimum(1)
0x25, 0x08, // logical maximum(8)
0x35, 0x00, // physical minimum(0)
0x46, 0x3b, 0x01, // physical maximum(315)
0x65, 0x14, // unit(Eng Rot:Angular Pos)
0x95, 0x01, // report_count(1)
0x75, 0x04, // report_size(4)
0x81, 0x06, // input(Data,Var,Relative,Null)
Of course, I did not write this descriptor manually, I used constructor utility. On Wine it works but crashes, I would advised to use it on Virtualbox. I hope, that this example helps you in your projects, here is mine project.
Комментариев нет :
Отправить комментарий