Skip to content

Commit e23fb3a

Browse files
authored
Fix I2C HID Interrupt Behavior (#193)
Read in HID interrupt reports rather than querying registers directly. Fixes freezing on boot and spammed IRQs on I2C touchpads.
1 parent 12384ef commit e23fb3a

24 files changed

+213
-220
lines changed

VoodooRMI/Functions/F01.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -373,13 +373,12 @@ int F01::rmi_f01_resume()
373373
return error;
374374
}
375375

376-
void F01::attention()
376+
void F01::attention(AbsoluteTime time, UInt8 *data[], size_t *size)
377377
{
378-
int error;
378+
IOReturn error;
379379
UInt8 device_status = 0;
380380

381381
error = readByte(getDataAddr(), &device_status);
382-
383382
if (error) {
384383
IOLogError("F01: Failed to read device status: %d", error);
385384
return;

VoodooRMI/Functions/F01.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ class F01 : public RMIFunction {
125125
public:
126126
bool attach(IOService *provider) override;
127127
IOReturn config() override;
128-
void attention() override;
128+
void attention(AbsoluteTime time, UInt8 *data[], size_t *size) override;
129129

130130
IOReturn setPowerState(unsigned long powerStateOrdinal, IOService *whatDevice) override;
131131

VoodooRMI/Functions/F03.cpp

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ int F03::rmi_f03_pt_write(unsigned char val)
155155
return error;
156156
}
157157

158-
void F03::handlePacket(UInt8 *packet)
158+
void F03::handlePacket(AbsoluteTime time, UInt8 *packet)
159159
{
160160
RMITrackpointReport report;
161161
// Trackpoint isn't initialized!
@@ -172,6 +172,7 @@ void F03::handlePacket(UInt8 *packet)
172172
timer->enable();
173173
}
174174

175+
report.timestamp = time;
175176
report.buttons = (packet[0] & 0x7);
176177
report.dx = ((packet[0] & 0x10) ? 0xffffff00 : 0) | packet[1];
177178
report.dy = -(((packet[0] & 0x20) ? 0xffffff00 : 0) | packet[2]);
@@ -199,26 +200,21 @@ IOReturn F03::setPowerState(unsigned long powerStateOrdinal, IOService *whatDevi
199200
return kIOPMAckImplied;
200201
}
201202

202-
void F03::attention()
203+
void F03::attention(AbsoluteTime time, UInt8 *data[], size_t *size)
203204
{
204-
const UInt16 data_addr = getDataAddr() + RMI_F03_OB_OFFSET;
205-
const UInt8 ob_len = rx_queue_length * RMI_F03_OB_SIZE;
206-
UInt8 obs[RMI_F03_QUEUE_LENGTH * RMI_F03_OB_SIZE];
205+
const UInt8 ob_len = RMI_F03_OB_OFFSET + (rx_queue_length * RMI_F03_OB_SIZE);
206+
UInt8 obs[RMI_F03_OB_OFFSET + (RMI_F03_QUEUE_LENGTH * RMI_F03_OB_SIZE)];
207207

208-
int error = readBlock(data_addr, obs, ob_len);
209-
if (error) {
210-
IOLogError("F03 - Failed to read output buffers: %d", error);
208+
if (!getInputData(obs, ob_len, data, size))
211209
return;
212-
}
213210

214-
for (int i = 0; i < ob_len; i += RMI_F03_OB_SIZE) {
211+
for (int i = RMI_F03_OB_OFFSET; i < ob_len; i += RMI_F03_OB_SIZE) {
215212
UInt8 ob_status = obs[i];
216213
UInt8 ob_data = obs[i + RMI_F03_OB_DATA_OFFSET];
217214

218215
if (!(ob_status & RMI_F03_RX_DATA_OFB))
219216
continue;
220217

221-
222218
IOLogDebug("F03 - Recieved data over PS2: %x", ob_data);
223219
if (ob_status & RMI_F03_OB_FLAG_TIMEOUT) {
224220
IOLogDebug("F03 Timeout Flag");
@@ -229,7 +225,7 @@ void F03::attention()
229225
continue;
230226
}
231227

232-
handleByte(ob_data);
228+
handleByte(time, ob_data);
233229
}
234230
}
235231

@@ -296,7 +292,7 @@ void F03::initPS2Interrupt(OSObject *owner, IOTimerEventSource *timer)
296292
timer->disable();
297293
}
298294

299-
void F03::handleByte(UInt8 byte)
295+
void F03::handleByte(AbsoluteTime time, UInt8 byte)
300296
{
301297
if (!cmdcnt && !flags) {
302298
// Wait for start of packets
@@ -306,7 +302,7 @@ void F03::handleByte(UInt8 byte)
306302
databuf[index++] = byte;
307303

308304
if (index == 3)
309-
handlePacket(databuf);
305+
handlePacket(time, databuf);
310306
return;
311307
}
312308

VoodooRMI/Functions/F03.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class F03 : public RMITrackpointFunction {
2424
bool start(IOService *provider) override;
2525
void stop(IOService *provider) override;
2626
IOReturn setPowerState(unsigned long powerStateOrdinal, IOService *whatDevice) override;
27-
void attention() override;
27+
void attention(AbsoluteTime time, UInt8 *data[], size_t *size) override;
2828

2929
private:
3030
IOWorkLoop *work_loop {nullptr};
@@ -53,11 +53,11 @@ class F03 : public RMITrackpointFunction {
5353
int ps2DoSendbyteGated(UInt8 byte, uint64_t timeout);
5454
int ps2CommandGated(UInt8 *param, unsigned int *command);
5555
int ps2Command(UInt8 *param, unsigned int command);
56-
void handleByte(UInt8);
56+
void handleByte(AbsoluteTime time, UInt8);
5757
void initPS2();
5858
void initPS2Interrupt(OSObject *owner, IOTimerEventSource *timer);
5959

60-
void handlePacket(UInt8 *packet);
60+
void handlePacket(AbsoluteTime time, UInt8 *packet);
6161
};
6262

6363
#endif /* F03_hpp */

VoodooRMI/Functions/F11.cpp

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,22 +40,31 @@ void F11::free()
4040
super::free();
4141
}
4242

43-
void F11::attention()
43+
void F11::attention(AbsoluteTime time, UInt8 *data[], size_t *size)
4444
{
4545
int error, abs_size;
4646
size_t fingers;
4747
UInt8 finger_state;
48-
AbsoluteTime timestamp;
4948

50-
error = readBlock(getDataAddr(), data_pkt, pkt_size);
51-
if (error < 0) {
52-
IOLogError("Could not read F11 attention data: %d", error);
53-
return;
49+
if (*data) {
50+
if (*size < attn_size) {
51+
IOLogError("F11 attention larger than remaining data");
52+
return;
53+
}
54+
55+
memcpy(data_pkt, *data, attn_size);
56+
(*data) += attn_size;
57+
(*size) -= attn_size;
58+
} else {
59+
error = readBlock(getDataAddr(), data_pkt, pkt_size);
60+
61+
if (error < 0) {
62+
IOLogError("F11 Could not read attention data: %d", error);
63+
return;
64+
}
5465
}
5566

56-
clock_get_uptime(&timestamp);
57-
58-
if (shouldDiscardReport(timestamp))
67+
if (shouldDiscardReport(time))
5968
return;
6069

6170
IOLogDebug("F11 Packet");
@@ -94,7 +103,7 @@ void F11::attention()
94103
}
95104
}
96105

97-
report.timestamp = timestamp;
106+
report.timestamp = time;
98107
report.fingers = fingers;
99108

100109
handleReport(&report);

VoodooRMI/Functions/F11.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -500,7 +500,7 @@ class F11 : public RMITrackpadFunction {
500500

501501
public:
502502
bool attach(IOService *provider) override;
503-
void attention() override;
503+
void attention(AbsoluteTime time, UInt8 *data[], size_t *size) override;
504504
void free() override;
505505

506506
IOReturn config() override;

VoodooRMI/Functions/F12.cpp

Lines changed: 42 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -79,53 +79,33 @@ bool F12::attach(IOService *provider)
7979
/*
8080
* Figure out what data is contained in the data registers. HID devices
8181
* may have registers defined, but their data is not reported in the
82-
* HID attention report. Registers which are not reported in the HID
83-
* attention report check to see if the device is receiving data from
84-
* HID attention reports.
82+
* HID attention report. As we don't care about pen or acm data, we can do
83+
* a simplified check for ACM data to get attention size and ignore the data
84+
* offset.
8585
*/
8686
item = rmi_get_register_desc_item(&data_reg_desc, 0);
8787
if (item)
8888
data_offset += item->reg_size;
8989

9090
item = rmi_get_register_desc_item(&data_reg_desc, 1);
9191
if (!item) {
92-
return false;
9392
IOLogError("F12 - No Data1 Reg!");
93+
return false;
9494
}
95-
96-
data1 = item;
95+
9796
data1_offset = data_offset;
98-
data_offset += item->reg_size;
99-
nbr_fingers = item->num_subpackets;
100-
report_abs = 1;
10197
attn_size += item->reg_size;
102-
103-
item = rmi_get_register_desc_item(&data_reg_desc, 2);
104-
if (item)
105-
data_offset += item->reg_size;
106-
107-
item = rmi_get_register_desc_item(&data_reg_desc, 3);
108-
if (item)
109-
data_offset += item->reg_size;
110-
111-
item = rmi_get_register_desc_item(&data_reg_desc, 4);
112-
if (item)
113-
data_offset += item->reg_size;
98+
nbr_fingers = item->num_subpackets;
11499

115100
item = rmi_get_register_desc_item(&data_reg_desc, 5);
116-
if (item) {
117-
data5 = item;
118-
data5_offset = data_offset;
119-
data_offset += item->reg_size;
101+
if (item)
120102
attn_size += item->reg_size;
121-
}
122103

123-
// Skip 6-15 as they do not increase attention size and only gives relative info
104+
// Skip 6-15 as they do not increase attention size
124105

125106
setProperty("Number of fingers", nbr_fingers, 8);
126107
IOLogDebug("F12 - Number of fingers %u", nbr_fingers);
127108

128-
129109
return true;
130110
}
131111

@@ -267,22 +247,31 @@ int F12::rmi_f12_read_sensor_tuning()
267247
return 0;
268248
}
269249

270-
void F12::attention()
250+
void F12::attention(AbsoluteTime time, UInt8 *data[], size_t *size)
271251
{
272-
AbsoluteTime timestamp;
273-
274-
if (!data1)
275-
return;
276-
277-
int retval = readBlock(getDataAddr(), data_pkt, pkt_size);
278-
279-
if (retval < 0) {
280-
IOLogError("F12 - Failed to read object data. Code: %d", retval);
281-
return;
252+
RMI2DSensorReport report {};
253+
size_t offset = data1_offset;
254+
255+
if (*data) {
256+
if (*size < attn_size) {
257+
IOLogError("F12 attention larger than remaining data");
258+
return;
259+
}
260+
261+
memcpy(data_pkt, *data, attn_size);
262+
(*data) += attn_size;
263+
(*size) -= attn_size;
264+
offset = 0;
265+
} else {
266+
IOReturn error = readBlock(getDataAddr(), data_pkt, pkt_size);
267+
268+
if (error < 0) {
269+
IOLogError("F12 Could not read attention data: %d", error);
270+
return;
271+
}
282272
}
283273

284-
clock_get_uptime(&timestamp);
285-
if (shouldDiscardReport(timestamp))
274+
if (shouldDiscardReport(time))
286275
return;
287276

288277
IOLogDebug("F12 Packet");
@@ -293,32 +282,29 @@ void F12::attention()
293282
#endif // debug
294283

295284
int fingers = min (nbr_fingers, 5);
296-
UInt8 *data = &data_pkt[data1_offset];
297-
298285
for (int i = 0; i < fingers; i++) {
299-
rmi_2d_sensor_abs_object *obj = &report.objs[i];
286+
rmi_2d_sensor_abs_object &obj = report.objs[i];
287+
UInt8 *fingerData = &data_pkt[offset + (i * F12_DATA1_BYTES_PER_OBJ)];
300288

301-
switch (data[0]) {
289+
switch (fingerData[0]) {
302290
case RMI_F12_OBJECT_FINGER:
303-
obj->type = RMI_2D_OBJECT_FINGER;
291+
obj.type = RMI_2D_OBJECT_FINGER;
304292
break;
305293
case RMI_F12_OBJECT_STYLUS:
306-
obj->type = RMI_2D_OBJECT_STYLUS;
294+
obj.type = RMI_2D_OBJECT_STYLUS;
307295
break;
308296
default:
309-
obj->type = RMI_2D_OBJECT_NONE;
297+
obj.type = RMI_2D_OBJECT_NONE;
310298
}
311299

312-
obj->x = (data[2] << 8) | data[1];
313-
obj->y = (data[4] << 8) | data[3];
314-
obj->z = data[5];
315-
obj->wx = data[6];
316-
obj->wy = data[7];
317-
318-
data += F12_DATA1_BYTES_PER_OBJ;
300+
obj.x = (fingerData[2] << 8) | fingerData[1];
301+
obj.y = (fingerData[4] << 8) | fingerData[3];
302+
obj.z = fingerData[5];
303+
obj.wx = fingerData[6];
304+
obj.wy = fingerData[7];
319305
}
320306

321-
report.timestamp = timestamp;
307+
report.timestamp = time;
322308
report.fingers = fingers;
323309

324310
handleReport(&report);

VoodooRMI/Functions/F12.hpp

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -54,16 +54,14 @@ class F12 : public RMITrackpadFunction {
5454

5555
public:
5656
bool attach(IOService *provider) override;
57-
void attention() override;
57+
void attention(AbsoluteTime time, UInt8 *data[], size_t *size) override;
5858
void free() override;
5959

6060
IOReturn config() override;
6161

6262
private:
6363
IOService *voodooInputInstance {nullptr};
6464

65-
RMI2DSensorReport report {};
66-
6765
static rmi_register_desc_item *rmi_get_register_desc_item(rmi_register_descriptor *rdesc, UInt16 reg);
6866
static size_t rmi_register_desc_calc_size(rmi_register_descriptor *rdesc);
6967
static int rmi_register_desc_calc_reg_offset(rmi_register_descriptor *rdesc, UInt16 reg);
@@ -72,26 +70,15 @@ class F12 : public RMITrackpadFunction {
7270

7371
/* F12 Data */
7472
UInt8 *data_pkt;
75-
size_t pkt_size;
76-
size_t attn_size;
73+
size_t pkt_size {0};
74+
size_t attn_size {0};
7775
bool has_dribble;
76+
size_t data1_offset;
7877

7978
rmi_register_descriptor query_reg_desc;
8079
rmi_register_descriptor control_reg_desc;
8180
rmi_register_descriptor data_reg_desc;
8281

83-
/* F12 Data1 describes sensed objects */
84-
const rmi_register_desc_item *data1 {nullptr};
85-
UInt16 data1_offset;
86-
87-
/* F12 Data5 describes finger ACM */
88-
const rmi_register_desc_item *data5 {nullptr};
89-
UInt16 data5_offset;
90-
91-
/* F12 Data5 describes Pen */
92-
const rmi_register_desc_item *data6 {nullptr};
93-
UInt16 data6_offset;
94-
9582
int rmi_f12_read_sensor_tuning();
9683
int rmi_read_register_desc(UInt16 addr,
9784
rmi_register_descriptor *rdesc);

0 commit comments

Comments
 (0)