[haiku-commits] r42325 - haiku/trunk/src/add-ons/kernel/bus_managers/ps2

  • From: zharik@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sun, 26 Jun 2011 21:38:27 +0200 (CEST)

Author: siarzhuk
Date: 2011-06-26 21:38:26 +0200 (Sun, 26 Jun 2011)
New Revision: 42325
Changeset: https://dev.haiku-os.org/changeset/42325
Ticket: https://dev.haiku-os.org/ticket/2867
Ticket: https://dev.haiku-os.org/ticket/3594
Ticket: https://dev.haiku-os.org/ticket/4315

Modified:
   haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_defs.h
   haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_dev.cpp
   haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_dev.h
   haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_synaptics.cpp
Log:
* Implemented PS2_CMD_RESEND command handlig;

* Workaround for touchpad reset timeouts on some HP/Compaq KBCs. Looks like 
such 
  KBC marks the mouse reset request (xFF) as correctly sent (by xFA answer) but 
  does not wait enough time for the answer from touchpad. So complete answer 
  finally contains xFE xAA x00 bytes. The workaround detects this xFE xAA answer
  and issues the RESEND (xFE) request to touchpad. This forces touchpad to 
resend
  the last packet of data (xAA x00) that can be processed normally by the host;

* Fix for handling passthrough_command() call. The parent device was disabled at
  start of processing command and was not re-enabled back in case any error 
return.
  This fixes the touchpad "pass-through" feature handling on the same HP/Compaq 
HW.
  This KBC has the "pass-through" capability marked ON but cannot handle it as
  currently implemented - there is no answer from corresponding port. The 
parent 
  device stay in disabled state after this;

* Fix ps2_dev_publish() for handling passthrough devices (parent_dev != NULL)
  This workaround postpone the publishing such device until the parent device
  finishes it's opening and set the PS2_ENABLED_FALG. It prevent from mixing 
  the Synaptics multi-command sequences from synaptics_open() and 
ps2_dev_publish()
  routines and failing both initializations;

Fixes #2867 #3594 #4315



Modified: haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_defs.h
===================================================================
--- haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_defs.h  2011-06-26 
18:35:56 UTC (rev 42324)
+++ haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_defs.h  2011-06-26 
19:38:26 UTC (rev 42325)
@@ -57,6 +57,7 @@
 #define PS2_CMD_ENABLE                                 0xf4
 #define PS2_CMD_DISABLE                                        0xf5
 #define PS2_CMD_RESET                                  0xff
+#define PS2_CMD_RESEND                                 0xfe
 
 // reply codes
 #define PS2_REPLY_TEST_PASSED                  0x55

Modified: haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_dev.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_dev.cpp 2011-06-26 
18:35:56 UTC (rev 42324)
+++ haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_dev.cpp 2011-06-26 
19:38:26 UTC (rev 42325)
@@ -36,6 +36,14 @@
 
        status = ps2_dev_command(dev, PS2_CMD_RESET, NULL, 0, data, 2);
 
+       if (status == B_OK && data[0] == 0xFE && data[1] == 0xAA) {
+               // workaround for HP/Compaq KBCs timeout condition. #2867 #3594 
#4315
+               TRACE("ps2: KBC has timed out the mouse reset request. "
+                               "Response was: 0x%02x 0x%02x. Requesting the 
answer data.\n",
+                               data[0], data[1]);
+               status = ps2_dev_command(dev, PS2_CMD_RESEND, NULL, 0, data, 2);
+       }
+
        if (status == B_OK && data[0] != 0xAA && data[1] != 0x00) {
                TRACE("ps2: reset mouse failed, response was: 0x%02x 0x%02x\n",
                        data[0], data[1]);
@@ -173,7 +181,7 @@
 void
 ps2_dev_publish(ps2_dev *dev)
 {
-       status_t status;
+       status_t status = B_OK;
        TRACE("ps2: ps2_dev_publish %s\n", dev->name);
 
        if (dev->active)
@@ -182,10 +190,30 @@
        if (atomic_get(&dev->flags) & PS2_FLAG_KEYB) {
                status = devfs_publish_device(dev->name, &gKeyboardDeviceHooks);
        } else {
-               device_hooks *hooks;
-               status = ps2_dev_detect_pointing(dev, &hooks);
+               // Check if this is the "pass-through" device and wait until 
+               // the parent_dev goes to enabled state. It is required to 
prevent
+               // from messing up the Synaptics command sequences in 
synaptics_open.
+               if (dev->parent_dev) {
+                       const bigtime_t timeout = 2000000;
+                       bigtime_t start = system_time();
+                       while (!(atomic_get(&dev->parent_dev->flags) & 
PS2_FLAG_ENABLED)) {
+                               if ((system_time() - start) > timeout) {
+                                       status = B_BUSY;
+                                       break;
+                               }
+                               snooze(timeout / 20);
+                       }
+                       TRACE("ps2: publishing %s: parent %s is %s; wait time 
%Ld\n",
+                               dev->name, dev->parent_dev->name, 
+                               status == B_OK ? "enabled" : "busy", 
system_time() - start);
+               }
+
                if (status == B_OK) {
-                       status = devfs_publish_device(dev->name, hooks);
+                       device_hooks *hooks;
+                       status = ps2_dev_detect_pointing(dev, &hooks);
+                       if (status == B_OK) {
+                               status = devfs_publish_device(dev->name, hooks);
+                       }
                }
        }
 
@@ -247,6 +275,18 @@
                                                cnt++;
                                        }
                                }
+                       } else if ((flags & PS2_FLAG_RESEND)) {
+                               TRACE("ps2: ps2_dev_handle_int: processing 
RESEND request\n");
+                               atomic_or(&dev->flags, PS2_FLAG_ACK);
+                               if (dev->result_buf_cnt) {
+                                       dev->result_buf[dev->result_buf_idx] = 
data;
+                                       dev->result_buf_idx++;
+                                       dev->result_buf_cnt--;
+                                       if (dev->result_buf_cnt == 0) {
+                                               atomic_and(&dev->flags, 
~PS2_FLAG_CMD);
+                                               cnt++;
+                                       }
+                               }
                        } else {
 //                             TRACE("ps2: ps2_dev_handle_int unexpected data 
0x%02x while "
 //                                     "waiting for ack\n", data);
@@ -345,7 +385,7 @@
        for (i = -1; res == B_OK && i < out_count; i++) {
 
                atomic_and(&dev->flags,
-                       ~(PS2_FLAG_ACK | PS2_FLAG_NACK | PS2_FLAG_GETID));
+                       ~(PS2_FLAG_ACK | PS2_FLAG_NACK | PS2_FLAG_GETID | 
PS2_FLAG_RESEND));
 
                acquire_sem(gControllerSem);
 
@@ -365,6 +405,8 @@
                        if (i == -1) {
                                if (cmd == PS2_CMD_GET_DEVICE_ID)
                                        atomic_or(&dev->flags, PS2_FLAG_CMD | 
PS2_FLAG_GETID);
+                               else if (cmd == PS2_CMD_RESEND)
+                                       atomic_or(&dev->flags, PS2_FLAG_CMD | 
PS2_FLAG_RESEND);
                                else
                                        atomic_or(&dev->flags, PS2_FLAG_CMD);
                                ps2_write_data(cmd);

Modified: haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_dev.h
===================================================================
--- haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_dev.h   2011-06-26 
18:35:56 UTC (rev 42324)
+++ haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_dev.h   2011-06-26 
19:38:26 UTC (rev 42325)
@@ -59,6 +59,7 @@
 #define PS2_FLAG_ACK           (1 << 4)
 #define PS2_FLAG_NACK          (1 << 5)
 #define PS2_FLAG_GETID         (1 << 6)
+#define PS2_FLAG_RESEND                (1 << 7)
 
 
 #ifdef __cplusplus

Modified: haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_synaptics.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_synaptics.cpp   
2011-06-26 18:35:56 UTC (rev 42324)
+++ haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_synaptics.cpp   
2011-06-26 19:38:26 UTC (rev 42325)
@@ -232,24 +232,24 @@
                        val = out[i];
                status = send_touchpad_arg_timeout(dev->parent_dev, val, 
timeout);
                if (status != B_OK)
-                       return status;
+                       goto finalize;
                if (i != outCount -1) {
                        status = ps2_dev_command_timeout(dev->parent_dev,
                                PS2_CMD_SET_SAMPLE_RATE, &passThroughCmd, 1, 
NULL, 0, timeout);
                        if (status != B_OK)
-                               return status;
+                               goto finalize;
                }
        }
        status = ps2_dev_command_timeout(dev->parent_dev, 
PS2_CMD_SET_SAMPLE_RATE,
                &passThroughCmd, 1, passThroughIn, passThroughInCount, timeout);
        if (status != B_OK)
-               return status;
+               goto finalize;
 
        for (i = 0; i < inCount + 1; i++) {
                uint8 *inPointer = &passThroughIn[i * 6];
                if (!IS_SYN_PT_PACKAGE(inPointer)) {
                        TRACE("SYNAPTICS: not a pass throught package\n");
-                       return B_OK;
+                       goto finalize;
                }
                if (i == 0)
                        continue;
@@ -257,11 +257,13 @@
                in[i - 1] = passThroughIn[i * 6 + 1];
        }
 
-       status = ps2_dev_command(dev->parent_dev, PS2_CMD_ENABLE, NULL, 0, 
NULL, 0);
-       if (status != B_OK)
-               return status;
+finalize:      
+       status_t statusOfEnable = ps2_dev_command(dev->parent_dev, 
PS2_CMD_ENABLE,
+                       NULL, 0, NULL, 0);
+       if (statusOfEnable != B_OK)
+               TRACE("SYNAPTICS: enabling of parent failed: 0x%lx.\n", 
statusOfEnable);
 
-       return B_OK;
+       return status != B_OK ? status : statusOfEnable;
 }
 
 


Other related posts: