Ticket #18888: tworeport.diff

File tworeport.diff, 18.6 KB (added by donn, 3 weeks ago)
Line 
1*** HIDReport.h.dist 2024-04-18 08:04:24.950272000 +0100
2--- HIDReport.h 2024-04-25 23:33:06.950009856 +0100
3***************
4*** 29,34 ****
5--- 29,35 ----
6
7 uint8 Type() { return fType; };
8 uint8 ID() { return fReportID; };
9+ status_t Status() { return fReportStatus; };
10 size_t ReportSize() { return (fReportSize + 7) / 8; };
11
12 HIDParser * Parser() { return fParser; };
13***************
14*** 56,61 ****
15--- 57,63 ----
16
17 #ifndef USERLAND_HID
18 status_t WaitForReport(bigtime_t timeout);
19+ status_t WaitMoreReport(bigtime_t timeout);
20 void DoneProcessing();
21 #endif
22
23*** HIDReport.cpp.dist 2024-04-25 23:27:01.043253760 +0100
24--- HIDReport.cpp 2024-04-25 23:32:27.376963072 +0100
25***************
26*** 251,256 ****
27--- 251,269 ----
28 return B_OK;
29 }
30
31+ status_t
32+ HIDReport::WaitMoreReport(bigtime_t timeout)
33+ {
34+ while (atomic_get(&fBusyCount) != 0)
35+ snooze(1000);
36+
37+ if (fReportStatus != B_OK)
38+ return fReportStatus;
39+
40+ atomic_add(&fBusyCount, 1);
41+ return B_OK;
42+ }
43+
44
45 void
46 HIDReport::DoneProcessing()
47*** ProtocolHandler.h.dist 2024-04-22 00:21:07.873725952 +0100
48--- ProtocolHandler.h 2024-04-26 15:34:58.022806528 +0100
49***************
50*** 11,16 ****
51--- 11,20 ----
52
53 #define PROTOCOL_HANDLER_COOKIE_FLAG_CLOSED 0x80000000
54
55+ #define PROTOCOL_NEED_MOUSE_XY 0x0001
56+ #define PROTOCOL_NEED_MOUSE_BUTTON 0x0002
57+ #define PROTOCOL_NEED_MOUSE_WHEEL 0x0004
58+ #define PROTOCOL_NEED_MOUSE_ALL 0x0007
59
60 class HIDDevice;
61 class HIDReport;
62***************
63*** 22,27 ****
64--- 26,34 ----
65 const char *basePath,
66 size_t ringBufferSize);
67 virtual ~ProtocolHandler();
68+ bool NeedFlag(int32 flag) { return (flag & fNeedCapability) != 0; }
69+ void ClearFlag(int32 flag) { fNeedCapability &= ~flag; }
70+ void SetFlags(int32 flag) { fNeedCapability = flag; }
71
72 status_t InitCheck() { return fStatus; }
73
74***************
75*** 64,69 ****
76--- 71,77 ----
77 HIDDevice * fDevice;
78 const char * fBasePath;
79 char * fPublishPath;
80+ uint32 fNeedCapability;
81 struct ring_buffer *fRingBuffer;
82
83 ProtocolHandler * fNextHandler;
84*** ProtocolHandler.cpp.dist 2024-04-18 08:04:25.077332480 +0100
85--- ProtocolHandler.cpp 2024-04-26 14:40:35.703594496 +0100
86***************
87*** 27,32 ****
88--- 27,33 ----
89 fDevice(device),
90 fBasePath(basePath),
91 fPublishPath(NULL),
92+ fNeedCapability(0),
93 fRingBuffer(NULL),
94 fNextHandler(NULL)
95 {
96*** MouseProtocolHandler.h.dist 2024-04-23 10:47:52.149159936 +0100
97--- MouseProtocolHandler.h 2024-04-26 14:06:34.458489856 +0100
98***************
99*** 22,30 ****
100
101 class MouseProtocolHandler : public ProtocolHandler {
102 public:
103! MouseProtocolHandler(HIDReport &report,
104! HIDReportItem &xAxis,
105! HIDReportItem &yAxis);
106
107 static void AddHandlers(HIDDevice &device,
108 HIDCollection &collection,
109--- 22,34 ----
110
111 class MouseProtocolHandler : public ProtocolHandler {
112 public:
113! MouseProtocolHandler(HIDReport *report);
114! uint32 GetButtonInfo(HIDReport *report);
115! void InitAxes(HIDReport *report,
116! HIDReportItem *xAxis,
117! HIDReportItem *yAxis);
118! void InitWheel(HIDReport *report,
119! HIDReportItem *wheel);
120
121 static void AddHandlers(HIDDevice &device,
122 HIDCollection &collection,
123***************
124*** 36,46 ****
125 private:
126 status_t _ReadReport(void *buffer, uint32 *cookie);
127
128! HIDReport & fReportWheel;
129! HIDReport & fReportAxes;
130
131! HIDReportItem & fXAxis;
132! HIDReportItem & fYAxis;
133 HIDReportItem * fWheel;
134 HIDReportItem * fHorizontalPan;
135 HIDReportItem * fButtons[B_MAX_MOUSE_BUTTONS];
136--- 40,50 ----
137 private:
138 status_t _ReadReport(void *buffer, uint32 *cookie);
139
140! HIDReport * fReportAxes;
141! HIDReport * fReportWheel;
142
143! HIDReportItem * fXAxis;
144! HIDReportItem * fYAxis;
145 HIDReportItem * fWheel;
146 HIDReportItem * fHorizontalPan;
147 HIDReportItem * fButtons[B_MAX_MOUSE_BUTTONS];
148*** MouseProtocolHandler.cpp.dist 2024-04-18 08:04:25.054525952 +0100
149--- MouseProtocolHandler.cpp 2024-04-26 15:41:31.460849152 +0100
150***************
151*** 22,69 ****
152 #include <kernel.h>
153 #include <keyboard_mouse_driver.h>
154
155
156! MouseProtocolHandler::MouseProtocolHandler(HIDReport &report,
157! HIDReportItem &xAxis, HIDReportItem &yAxis)
158 :
159! ProtocolHandler(report.Device(), "input/mouse/" DEVICE_PATH_SUFFIX "/", 0),
160! fReport(report),
161!
162! fXAxis(xAxis),
163! fYAxis(yAxis),
164 fWheel(NULL),
165 fHorizontalPan(NULL),
166-
167 fLastButtons(0),
168 fClickCount(0),
169 fLastClickTime(0),
170 fClickSpeed(250000)
171 {
172 uint32 buttonCount = 0;
173! for (uint32 i = 0; i < report.CountItems(); i++) {
174! HIDReportItem *item = report.ItemAt(i);
175 if (!item->HasData())
176 continue;
177
178 if (item->UsagePage() == B_HID_USAGE_PAGE_BUTTON
179! && item->UsageID() - 1 < B_MAX_MOUSE_BUTTONS) {
180 fButtons[buttonCount++] = item;
181 }
182 }
183
184! fButtons[buttonCount] = NULL;
185
186! fWheel = report.FindItem(B_HID_USAGE_PAGE_GENERIC_DESKTOP,
187! B_HID_UID_GD_WHEEL);
188! fHorizontalPan = report.FindItem(B_HID_USAGE_PAGE_CONSUMER,
189! B_HID_UID_CON_AC_PAN);
190
191! TRACE("mouse device with %" B_PRIu32 " buttons %sand %swheel\n",
192 buttonCount, fHorizontalPan == NULL ? "" : ", horizontal pan ",
193 fWheel == NULL ? "no " : "");
194! TRACE("report id: %u\n", report.ID());
195 }
196
197
198 void
199 MouseProtocolHandler::AddHandlers(HIDDevice &device, HIDCollection &collection,
200--- 22,142 ----
201 #include <kernel.h>
202 #include <keyboard_mouse_driver.h>
203
204+ // Supported configurations:
205+ // - one report with axis and button codes
206+ // or
207+ // - two reports:
208+ // -- axis
209+ // -- wheel and buttons, must have wheel
210
211! MouseProtocolHandler::MouseProtocolHandler(HIDReport *report)
212 :
213! ProtocolHandler(report->Device(), "input/mouse/" DEVICE_PATH_SUFFIX "/", 0),
214! fReportAxes(report),
215! fReportWheel(report),
216! fXAxis(NULL),
217! fYAxis(NULL),
218 fWheel(NULL),
219 fHorizontalPan(NULL),
220 fLastButtons(0),
221 fClickCount(0),
222 fLastClickTime(0),
223 fClickSpeed(250000)
224 {
225+ fButtons[0] = NULL;
226+ // Report items yet identifying axes, buttons etc. will be found
227+ // and added in later.
228+ SetFlags(PROTOCOL_NEED_MOUSE_ALL);
229+ TRACE("mouse device initialized on report id: %u\n", report->ID());
230+ }
231+
232+ uint32
233+ MouseProtocolHandler::GetButtonInfo(HIDReport *report)
234+ {
235+ // why isn't this just "int"?
236 uint32 buttonCount = 0;
237! for (buttonCount = 0; buttonCount < B_MAX_MOUSE_BUTTONS; ++buttonCount) {
238! if (!fButtons[buttonCount])
239! break;
240! }
241! for (uint32 i = 0; i < report->CountItems(); i++) {
242! HIDReportItem *item = report->ItemAt(i);
243 if (!item->HasData())
244 continue;
245+ TRACE(" report item : %x %x @%d\n", item->UsagePage(), item->UsageID(), buttonCount);
246
247 if (item->UsagePage() == B_HID_USAGE_PAGE_BUTTON
248! && item->UsageID() - 1 < B_MAX_MOUSE_BUTTONS
249! && buttonCount < B_MAX_MOUSE_BUTTONS) {
250 fButtons[buttonCount++] = item;
251+ ClearFlag(PROTOCOL_NEED_MOUSE_BUTTON);
252 }
253 }
254
255! if (buttonCount < B_MAX_MOUSE_BUTTONS)
256! fButtons[buttonCount] = NULL;
257! else
258! TRACE_ALWAYS("button count maxed out.\n");
259!
260! if (!fWheel) {
261! fWheel = report->FindItem(B_HID_USAGE_PAGE_GENERIC_DESKTOP,
262! B_HID_UID_GD_WHEEL);
263! ClearFlag(PROTOCOL_NEED_MOUSE_WHEEL);
264! }
265!
266! if (!fHorizontalPan)
267! fHorizontalPan = report->FindItem(B_HID_USAGE_PAGE_CONSUMER,
268! B_HID_UID_CON_AC_PAN);
269
270! return buttonCount;
271! }
272
273! void
274! MouseProtocolHandler::InitAxes(HIDReport *report,
275! HIDReportItem *xAxis, HIDReportItem *yAxis)
276! {
277! fReportAxes = report;
278! fXAxis = xAxis;
279! fYAxis = yAxis;
280! ClearFlag(PROTOCOL_NEED_MOUSE_XY);
281!
282! TRACE("InitAxes(Report ID %d\n)\n", report->ID());
283! uint32 buttonCount = GetButtonInfo(report);
284!
285! // TRACE_ALWAYS, because build will abort when TRACE is off, due to
286! // unused button count.
287! TRACE_ALWAYS("mouse device with %" B_PRIu32 " buttons %sand %swheel\n",
288 buttonCount, fHorizontalPan == NULL ? "" : ", horizontal pan ",
289 fWheel == NULL ? "no " : "");
290! TRACE("report id: %u\n", fReportAxes->ID());
291 }
292
293+ void
294+ MouseProtocolHandler::InitWheel(HIDReport *report, HIDReportItem *wheel)
295+ {
296+ fReportWheel = report;
297+ fWheel = wheel;
298+ ClearFlag(PROTOCOL_NEED_MOUSE_WHEEL);
299+
300+ TRACE("InitWheel(Report ID %d\n)\n", report->ID());
301+ uint32 buttonCount = GetButtonInfo(report);
302+
303+ TRACE_ALWAYS("mouse device with %" B_PRIu32 " buttons %sand %swheel\n",
304+ buttonCount, fHorizontalPan == NULL ? "" : ", horizontal pan ",
305+ fWheel == NULL ? "no " : "");
306+ TRACE("report id: %u\n", fReportWheel->ID());
307+ }
308+
309+ static MouseProtocolHandler *
310+ findNeededHandler(ProtocolHandler *t, int32 need)
311+ {
312+ while (t) {
313+ if (t->NeedFlag(need))
314+ return (MouseProtocolHandler *) t;
315+ t = t->NextHandler();
316+ }
317+ return NULL;
318+ }
319
320 void
321 MouseProtocolHandler::AddHandlers(HIDDevice &device, HIDCollection &collection,
322***************
323*** 105,127 ****
324 // try to find at least an absolute x and y axis
325 HIDReportItem *xAxis = inputReport->FindItem(
326 B_HID_USAGE_PAGE_GENERIC_DESKTOP, B_HID_UID_GD_X);
327! if (xAxis == NULL || !xAxis->Relative())
328! continue;
329
330! HIDReportItem *yAxis = inputReport->FindItem(
331! B_HID_USAGE_PAGE_GENERIC_DESKTOP, B_HID_UID_GD_Y);
332! if (yAxis == NULL || !yAxis->Relative())
333! continue;
334
335! ProtocolHandler *newHandler = new(std::nothrow) MouseProtocolHandler(
336! *inputReport, *xAxis, *yAxis);
337! if (newHandler == NULL) {
338! TRACE("failed to allocated mouse protocol handler\n");
339! continue;
340 }
341
342! newHandler->SetNextHandler(handlerList);
343! handlerList = newHandler;
344 }
345 }
346
347--- 178,244 ----
348 // try to find at least an absolute x and y axis
349 HIDReportItem *xAxis = inputReport->FindItem(
350 B_HID_USAGE_PAGE_GENERIC_DESKTOP, B_HID_UID_GD_X);
351! if (xAxis && xAxis->Relative()) {
352! HIDReportItem *yAxis = inputReport->FindItem(
353! B_HID_USAGE_PAGE_GENERIC_DESKTOP, B_HID_UID_GD_Y);
354! if (yAxis && yAxis->Relative()) {
355!
356! MouseProtocolHandler *oldHandler = findNeededHandler(handlerList, PROTOCOL_NEED_MOUSE_XY);
357! MouseProtocolHandler *newHandler;
358! if (oldHandler) {
359! newHandler = NULL;
360! } else {
361! newHandler = new(std::nothrow) MouseProtocolHandler(inputReport);
362! if (newHandler == NULL) {
363! TRACE("failed to allocated mouse protocol handler\n");
364! continue;
365! } else {
366! oldHandler = newHandler;
367! }
368! }
369
370! oldHandler->InitAxes(inputReport, xAxis, yAxis);
371
372! if (newHandler) {
373! newHandler->SetNextHandler(handlerList);
374! handlerList = (ProtocolHandler *) newHandler;
375! }
376! // Here ends the apparently normal mouse button report, with X Y axes
377! // and apparently everything else reported.
378! continue;
379! }
380! // X, no Y
381 }
382+ TRACE("mouse? no x/y\n");
383+ // Failed to find x-y, but maybe there's wheel ...
384+ // Honestly I'd rather look for buttons here, but from the listing it seemed
385+ // unclear what the first parameter would be - USAGE_PAGE_GENERIC_DESKTOP ?
386+ HIDReportItem *wheel = inputReport->FindItem(
387+ B_HID_USAGE_PAGE_GENERIC_DESKTOP, B_HID_UID_GD_WHEEL);
388+ if (wheel) {
389+ MouseProtocolHandler *oldHandler = findNeededHandler(handlerList, PROTOCOL_NEED_MOUSE_WHEEL);
390+ MouseProtocolHandler *newHandler;
391+ if (oldHandler) {
392+ newHandler = NULL;
393+ } else {
394+ // It's the first mouse protocol report.
395+ newHandler = new(std::nothrow) MouseProtocolHandler(inputReport);
396+ if (newHandler == NULL) {
397+ TRACE("failed to allocated mouse protocol handler\n");
398+ continue;
399+ } else {
400+ oldHandler = newHandler;
401+ }
402+ }
403+
404+ oldHandler->InitWheel(inputReport, wheel);
405
406! if (newHandler) {
407! newHandler->SetNextHandler(handlerList);
408! handlerList = (MouseProtocolHandler *) newHandler;
409! }
410! } else
411! TRACE("mouse? no wheel\n");
412 }
413 }
414
415***************
416*** 161,167 ****
417
418 case MS_NUM_EVENTS:
419 {
420! if (fReport.Device()->IsRemoved())
421 return B_DEV_NOT_READY;
422
423 // we are always on demand, so 0 queued events
424--- 278,285 ----
425
426 case MS_NUM_EVENTS:
427 {
428! // ?
429! if (fReportAxes->Device()->IsRemoved())
430 return B_DEV_NOT_READY;
431
432 // we are always on demand, so 0 queued events
433***************
434*** 185,193 ****
435 status_t
436 MouseProtocolHandler::_ReadReport(void *buffer, uint32 *cookie)
437 {
438! status_t result = fReport.WaitForReport(B_INFINITE_TIMEOUT);
439! if (result != B_OK) {
440! if (fReport.Device()->IsRemoved()) {
441 TRACE("device has been removed\n");
442 return B_DEV_NOT_READY;
443 }
444--- 303,325 ----
445 status_t
446 MouseProtocolHandler::_ReadReport(void *buffer, uint32 *cookie)
447 {
448!
449! bool got_axes = false;
450! bool got_buttons = false;
451! status_t resultWheel;
452!
453! // Look for input on the axis report, first.
454! status_t resultAxes = fReportAxes->WaitForReport(B_INFINITE_TIMEOUT);
455! TRACE("WaitForReport -> %d, axis %d report status %d %p, button %d status %d %p\n", resultAxes, fReportAxes->ID(), fReportAxes->Status(), fReportAxes->CurrentReport(), fReportWheel->ID(), fReportWheel->Status(), fReportWheel->CurrentReport());
456!
457! if (resultAxes == B_OK) {
458! got_axes = true;
459! } else {
460! got_axes = false;
461!
462! // Doesn't matter which report, for the following?
463!
464! if (fReportAxes->Device()->IsRemoved()) {
465 TRACE("device has been removed\n");
466 return B_DEV_NOT_READY;
467 }
468***************
469*** 195,255 ****
470 if ((*cookie & PROTOCOL_HANDLER_COOKIE_FLAG_CLOSED) != 0)
471 return B_CANCELED;
472
473! if (result != B_INTERRUPTED) {
474 // interrupts happen when other reports come in on the same
475 // input as ours
476! TRACE_ALWAYS("error waiting for report: %s\n", strerror(result));
477 }
478-
479- // signal that we simply want to try again
480- return B_INTERRUPTED;
481 }
482
483 uint32 axisRelativeData[2];
484 axisRelativeData[0] = 0;
485 axisRelativeData[1] = 0;
486
487! if (fXAxis.Extract() == B_OK && fXAxis.Valid())
488! axisRelativeData[0] = fXAxis.Data();
489
490! if (fYAxis.Extract() == B_OK && fYAxis.Valid())
491! axisRelativeData[1] = fYAxis.Data();
492
493! uint32 wheelData[2] = {0};
494! if (fWheel != NULL && fWheel->Extract() == B_OK && fWheel->Valid())
495! wheelData[0] = fWheel->Data();
496! if (fHorizontalPan != NULL && fHorizontalPan->Extract() == B_OK
497! && fHorizontalPan->Valid())
498! wheelData[1] = fHorizontalPan->Data();
499
500! uint32 buttons = 0;
501! for (uint32 i = 0; i < B_MAX_MOUSE_BUTTONS; i++) {
502! HIDReportItem *button = fButtons[i];
503! if (button == NULL)
504! break;
505
506! if (button->Extract() == B_OK && button->Valid())
507! buttons |= (button->Data() & 1) << (button->UsageID() - 1);
508 }
509
510! fReport.DoneProcessing();
511 TRACE("got mouse report\n");
512
513- int32 clicks = 0;
514 bigtime_t timestamp = system_time();
515! if (buttons != 0) {
516! if (fLastButtons == 0) {
517! if (fLastClickTime + fClickSpeed > timestamp)
518! fClickCount++;
519! else
520! fClickCount = 1;
521! }
522
523! fLastClickTime = timestamp;
524! clicks = fClickCount;
525! }
526
527! fLastButtons = buttons;
528
529 mouse_movement *info = (mouse_movement *)buffer;
530 memset(info, 0, sizeof(mouse_movement));
531--- 327,439 ----
532 if ((*cookie & PROTOCOL_HANDLER_COOKIE_FLAG_CLOSED) != 0)
533 return B_CANCELED;
534
535! if (resultAxes != B_INTERRUPTED) {
536 // interrupts happen when other reports come in on the same
537 // input as ours
538! TRACE_ALWAYS("error waiting for report: %s\n", strerror(resultAxes));
539 }
540 }
541
542+ // If no axis report, these will be the outcome values.
543 uint32 axisRelativeData[2];
544 axisRelativeData[0] = 0;
545 axisRelativeData[1] = 0;
546
547! if (got_axes && fXAxis != NULL && fYAxis != NULL) {
548! if (fXAxis->Extract() == B_OK && fXAxis->Valid())
549! axisRelativeData[0] = fXAxis->Data();
550! else if (!fXAxis->Valid())
551! TRACE("X axis invalid\n");
552! else
553! TRACE("X Extract not OK?\n");
554!
555! if (fYAxis->Extract() == B_OK && fYAxis->Valid())
556! axisRelativeData[1] = fYAxis->Data();
557! else if (!fYAxis->Valid())
558! TRACE("Y axis invalid\n");
559! else
560! TRACE("Y Extract not OK?\n");
561! }
562
563! // Unblock the axis report, if it was blocked.
564! if (resultAxes == B_OK)
565! fReportAxes->DoneProcessing();
566!
567! resultWheel = fReportWheel->Status();
568! bool separateWheel = fReportWheel->ID() != fReportAxes->ID();
569!
570! if (separateWheel && fReportWheel->Status() == B_OK) {
571! // There are two reports, and peeking at their status values
572! // it appears that the wheel/button report is the one that
573! // actually has data. So block it, while we get the data.
574
575! resultWheel = fReportWheel->WaitMoreReport(B_INFINITE_TIMEOUT);
576! TRACE("WaitMoreReport -> %d, axis %d report status %d %p, button %d status %d %p\n", resultWheel, fReportAxes->ID(), fReportAxes->Status(), fReportAxes->CurrentReport(), fReportWheel->ID(), fReportWheel->Status(), fReportWheel->CurrentReport());
577! }
578
579! if (resultWheel == B_OK) {
580! got_buttons = true;
581! } else {
582! if (resultAxes == B_OK) {
583! // if only one report, resultWheel = resultAxes,
584! // se evidently this is axis only.
585! got_buttons = false;
586! } else {
587! // signal that we simply want to try again
588! return B_INTERRUPTED;
589! }
590! }
591
592! uint32 wheelData[2] = {0, 0};
593! uint32 buttons = 0;
594! if (got_buttons) {
595! if (fWheel != NULL && fWheel->Extract() == B_OK && fWheel->Valid())
596! wheelData[0] = fWheel->Data();
597! if (fHorizontalPan != NULL && fHorizontalPan->Extract() == B_OK
598! && fHorizontalPan->Valid())
599! wheelData[1] = fHorizontalPan->Data();
600! TRACE("wheel %d / %d\n", wheelData[0], wheelData[1]);
601!
602! for (uint32 i = 0; i < B_MAX_MOUSE_BUTTONS; i++) {
603! HIDReportItem *button = fButtons[i];
604! if (button == NULL)
605! break;
606!
607! if (button->Extract() == B_OK && button->Valid()) {
608! buttons |= (button->Data() & 1) << (button->UsageID() - 1);
609! TRACE("perceived button %d / %x\n", i, buttons);
610! }
611! }
612 }
613
614! // If there was a button/wheel report with data on it, unblock it now.
615! if (separateWheel && resultWheel == B_OK)
616! fReportWheel->DoneProcessing();
617!
618 TRACE("got mouse report\n");
619+ TRACE("last buttons %x\n", fLastButtons);
620
621 bigtime_t timestamp = system_time();
622! int32 clicks = 0;
623
624! // If it wasn't just axis info, work out happenings with the buttons.
625! // Otherwise, just use stored button mask.
626! if (got_buttons) {
627! if (buttons != 0) {
628! if (fLastButtons == 0) {
629! if (fLastClickTime + fClickSpeed > timestamp)
630! fClickCount++;
631! else
632! fClickCount = 1;
633! }
634
635! fLastClickTime = timestamp;
636! clicks = fClickCount;
637! }
638! fLastButtons = buttons;
639! } else
640! buttons = fLastButtons;
641! TRACE("mouse buttons %x\n", buttons);
642
643 mouse_movement *info = (mouse_movement *)buffer;
644 memset(info, 0, sizeof(mouse_movement));