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

  • From: clemens.zeidler@xxxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Mon, 28 Mar 2011 10:18:31 +0200 (CEST)

Author: czeidler
Date: 2011-03-28 10:18:31 +0200 (Mon, 28 Mar 2011)
New Revision: 41134
Changeset: https://dev.haiku-os.org/changeset/41134

Added:
   haiku/trunk/src/add-ons/kernel/bus_managers/ps2/movement_maker.cpp
   haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_alps.cpp
   haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_common.cpp
   haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_dev.cpp
   haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_module.cpp
   haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_standard_mouse.cpp
   haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_synaptics.cpp
   haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_trackpoint.cpp
Removed:
   haiku/trunk/src/add-ons/kernel/bus_managers/ps2/movement_maker.c
   haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_alps.c
   haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_common.c
   haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_dev.c
   haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_module.c
   haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_standard_mouse.c
   haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_synaptics.c
   haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_trackpoint.c
Modified:
   haiku/trunk/src/add-ons/kernel/bus_managers/ps2/Jamfile
   haiku/trunk/src/add-ons/kernel/bus_managers/ps2/movement_maker.h
   haiku/trunk/src/add-ons/kernel/bus_managers/ps2/packet_buffer.cpp
   haiku/trunk/src/add-ons/kernel/bus_managers/ps2/packet_buffer.h
   haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_alps.h
   haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_standard_mouse.h
   haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_synaptics.h
Log:
Reapply the ps2 cpp patch. Thanks Axel.



Modified: haiku/trunk/src/add-ons/kernel/bus_managers/ps2/Jamfile
===================================================================
--- haiku/trunk/src/add-ons/kernel/bus_managers/ps2/Jamfile     2011-03-28 
08:10:26 UTC (rev 41133)
+++ haiku/trunk/src/add-ons/kernel/bus_managers/ps2/Jamfile     2011-03-28 
08:18:31 UTC (rev 41134)
@@ -5,14 +5,14 @@
 
 KernelAddon ps2 :
        packet_buffer.cpp
-       ps2_alps.c
-       ps2_common.c
-       ps2_dev.c
+       ps2_alps.cpp
+       ps2_common.cpp
+       ps2_dev.cpp
        ps2_keyboard.cpp
-       ps2_module.c
-       ps2_standard_mouse.c
-       ps2_synaptics.c
-       ps2_trackpoint.c
+       ps2_module.cpp
+       ps2_standard_mouse.cpp
+       ps2_synaptics.cpp
+       ps2_trackpoint.cpp
        ps2_service.cpp
-       movement_maker.c
+       movement_maker.cpp
        ;

Copied: haiku/trunk/src/add-ons/kernel/bus_managers/ps2/movement_maker.cpp 
(from rev 41133, 
haiku/trunk/src/add-ons/kernel/bus_managers/ps2/movement_maker.c)
===================================================================
--- haiku/trunk/src/add-ons/kernel/bus_managers/ps2/movement_maker.cpp          
                (rev 0)
+++ haiku/trunk/src/add-ons/kernel/bus_managers/ps2/movement_maker.cpp  
2011-03-28 08:18:31 UTC (rev 41134)
@@ -0,0 +1,314 @@
+#include "movement_maker.h"
+
+#include <Debug.h>
+#if 1
+#      define INFO(x...) dprintf(x)
+#else
+#      define INFO(x...)
+#endif
+
+typedef union {
+  float value;
+  /* FIXME: Assumes 32 bit int.  */
+  unsigned int word;
+} ieee_float_shape_type;
+
+/* Get a 32 bit int from a float.  */
+
+#define GET_FLOAT_WORD(i,d)                                    \
+do {                                                           \
+  ieee_float_shape_type gf_u;                                  \
+  gf_u.value = (d);                                            \
+  (i) = gf_u.word;                                             \
+} while (0)
+
+/* Set a float from a 32 bit int.  */
+
+#define SET_FLOAT_WORD(d,i)                                    \
+do {                                                           \
+  ieee_float_shape_type sf_u;                                  \
+  sf_u.word = (i);                                             \
+  (d) = sf_u.value;                                            \
+} while (0)
+
+static const float huge = 1.0e30;
+
+float
+floorf(float x)
+{
+       int32 i0,j0;
+       uint32 i;
+       GET_FLOAT_WORD(i0,x);
+       j0 = ((i0>>23)&0xff)-0x7f;
+       if (j0<23) {
+           if (j0<0) {         /* raise inexact if x != 0 */
+               if (huge+x>(float)0.0) {/* return 0*sign(x) if |x|<1 */
+                   if (i0>=0) {i0=0;}
+                   else if ((i0&0x7fffffff)!=0)
+                       { i0=0xbf800000;}
+               }
+           } else {
+               i = (0x007fffff)>>j0;
+               if ((i0&i)==0) return x; /* x is integral */
+               if (huge+x>(float)0.0) {        /* raise inexact flag */
+                   if (i0<0) i0 += (0x00800000)>>j0;
+                   i0 &= (~i);
+               }
+           }
+       } else {
+           if (j0==0x80) return x+x;   /* inf or NaN */
+           else return x;              /* x is integral */
+       }
+       SET_FLOAT_WORD(x,i0);
+       return x;
+}
+
+
+float
+ceilf(float x)
+{
+       int32 i0,j0;
+       uint32 i;
+
+       GET_FLOAT_WORD(i0,x);
+       j0 = ((i0>>23)&0xff)-0x7f;
+       if (j0<23) {
+           if (j0<0) {         /* raise inexact if x != 0 */
+               if (huge+x>(float)0.0) {/* return 0*sign(x) if |x|<1 */
+                   if (i0<0) {i0=0x80000000;}
+                   else if (i0!=0) { i0=0x3f800000;}
+               }
+           } else {
+               i = (0x007fffff)>>j0;
+               if ((i0&i)==0) return x; /* x is integral */
+               if (huge+x>(float)0.0) {        /* raise inexact flag */
+                   if (i0>0) i0 += (0x00800000)>>j0;
+                   i0 &= (~i);
+               }
+           }
+       } else {
+           if (j0==0x80) return x+x;   /* inf or NaN */
+           else return x;              /* x is integral */
+       }
+       SET_FLOAT_WORD(x,i0);
+       return x;
+}
+
+static  const float        one        = 1.0, tiny=1.0e-30;
+
+float
+sqrtf(float x)
+{
+        float z;
+        int32 sign = (int)0x80000000;
+        int32 ix,s,q,m,t,i;
+        uint32 r;
+
+        GET_FLOAT_WORD(ix,x);
+
+    /* take care of Inf and NaN */
+        if ((ix&0x7f800000)==0x7f800000) {
+            return x*x+x;                /* sqrt(NaN)=NaN, sqrt(+inf)=+inf
+                                           sqrt(-inf)=sNaN */
+        }
+    /* take care of zero */
+        if (ix<=0) {
+            if ((ix&(~sign))==0) return x;/* sqrt(+-0) = +-0 */
+            else if (ix<0)
+                return (x-x)/(x-x);                /* sqrt(-ve) = sNaN */
+        }
+    /* normalize x */
+        m = (ix>>23);
+        if (m==0) {                                /* subnormal x */
+            for(i=0;(ix&0x00800000)==0;i++) ix<<=1;
+            m -= i-1;
+        }
+        m -= 127;        /* unbias exponent */
+        ix = (ix&0x007fffff)|0x00800000;
+        if (m&1)        /* odd m, double x to make it even */
+            ix += ix;
+        m >>= 1;        /* m = [m/2] */
+
+    /* generate sqrt(x) bit by bit */
+        ix += ix;
+        q = s = 0;                /* q = sqrt(x) */
+        r = 0x01000000;                /* r = moving bit from right to left */
+
+        while(r!=0) {
+            t = s+r;
+            if (t<=ix) {
+                s    = t+r;
+                ix  -= t;
+                q   += r;
+            }
+            ix += ix;
+            r>>=1;
+        }
+
+    /* use floating add to find out rounding direction */
+        if (ix!=0) {
+            z = one-tiny; /* trigger inexact flag */
+            if (z>=one) {
+                z = one+tiny;
+                if (z>one)
+                    q += 2;
+                else
+                    q += (q&1);
+            }
+        }
+        ix = (q>>1)+0x3f000000;
+        ix += (m <<23);
+        SET_FLOAT_WORD(z,ix);
+        return z;
+}
+
+
+int32
+make_small(float value)
+{
+       if (value > 0)
+               return floorf(value);
+       else
+               return ceilf(value);
+}
+
+
+void
+get_raw_movement(movement_maker *move, uint32 posX, uint32 posY)
+{
+       const float acceleration = 0.8;
+       const float translation = 12.0;
+
+       int diff;
+       float xDelta, yDelta;
+
+       if (move->movementStarted) {
+               move->movementStarted = false;
+               // init delta tracking
+               move->previousX = posX;
+               move->previousY = posY;
+               // deltas are automatically reset
+       }
+
+       // accumulate delta and store current pos, reset if pos did not change
+       diff = posX - move->previousX;
+       // lessen the effect of small diffs
+       if ((diff > -3 && diff < -1) || (diff > 1 && diff < 3))
+               diff /= 2;
+       if (diff == 0)
+               move->deltaSumX = 0.0;
+       else
+               move->deltaSumX += diff;
+
+       diff = posY - move->previousY;
+       // lessen the effect of small diffs
+       if ((diff > -3 && diff < -1) || (diff > 1 && diff < 3))
+               diff /= 2;
+       if (diff == 0)
+               move->deltaSumY = 0.0;
+       else
+               move->deltaSumY += diff;
+
+       move->previousX = posX;
+       move->previousY = posY;
+
+       // compute current delta and reset accumulated delta if
+       // abs() is greater than 1
+       xDelta = move->deltaSumX / translation;
+       yDelta = move->deltaSumY / translation;
+       if (xDelta > 1.0) {
+               move->deltaSumX = 0.0;
+               xDelta = 1.0 + (xDelta - 1.0) * acceleration;
+       } else if (xDelta < -1.0) {
+               move->deltaSumX = 0.0;
+               xDelta = -1.0 + (xDelta + 1.0) * acceleration;
+       }
+
+       if (yDelta > 1.0) {
+               move->deltaSumY = 0.0;
+               yDelta = 1.0 + (yDelta - 1.0) * acceleration;
+       } else if (yDelta < -1.0) {
+               move->deltaSumY = 0.0;
+               yDelta = -1.0 + (yDelta + 1.0) * acceleration;
+       }
+
+       move->xDelta = make_small(xDelta);
+       move->yDelta = make_small(yDelta);
+}
+
+
+void
+compute_acceleration(movement_maker *move, int8 accel_factor)
+{
+       // acceleration
+       float acceleration = 1;
+       if (accel_factor != 0) {
+               acceleration = 1 + sqrtf(move->xDelta * move->xDelta
+                       + move->yDelta * move->yDelta) * accel_factor / 50.0;
+       }
+
+       move->xDelta = make_small(move->xDelta * acceleration);
+       move->yDelta = make_small(move->yDelta * acceleration);
+}
+
+
+void
+get_movement(movement_maker *move, uint32 posX, uint32 posY)
+{
+       get_raw_movement(move, posX, posY);
+
+//     INFO("SYN: pos: %lu x %lu, delta: %ld x %ld, sums: %ld x %ld\n",
+//             posX, posY, move->xDelta, move->yDelta,
+//             move->deltaSumX, move->deltaSumY);
+
+       move->xDelta = move->xDelta * move->speed;
+       move->yDelta = move->yDelta * move->speed;
+}
+
+
+void
+get_scrolling(movement_maker *move, uint32 posX, uint32 posY)
+{
+       int32 stepsX = 0, stepsY = 0;
+
+       get_raw_movement(move, posX, posY);
+       compute_acceleration(move, move->scroll_acceleration);
+
+       if (move->scrolling_xStep > 0) {
+               move->scrolling_x += move->xDelta;
+
+               stepsX = make_small(move->scrolling_x / move->scrolling_xStep);
+
+               move->scrolling_x -= stepsX * move->scrolling_xStep;
+               move->xDelta = stepsX;
+       } else {
+               move->scrolling_x = 0;
+               move->xDelta = 0;
+       }
+       if (move->scrolling_yStep > 0) {
+               move->scrolling_y += move->yDelta;
+
+               stepsY = make_small(move->scrolling_y / move->scrolling_yStep);
+
+               move->scrolling_y -= stepsY * move->scrolling_yStep;
+               move->yDelta = -1 * stepsY;
+       } else {
+               move->scrolling_y = 0;
+               move->yDelta = 0;
+       }
+}
+
+
+void
+start_new_movment(movement_maker *move)
+{
+       if (move->scrolling_xStep <= 0)
+               move->scrolling_xStep = 1;
+       if (move->scrolling_yStep <= 0)
+               move->scrolling_yStep = 1;
+
+       move->movementStarted = true;
+       move->scrolling_x = 0;
+       move->scrolling_y = 0;
+}
+

Modified: haiku/trunk/src/add-ons/kernel/bus_managers/ps2/movement_maker.h
===================================================================
--- haiku/trunk/src/add-ons/kernel/bus_managers/ps2/movement_maker.h    
2011-03-28 08:10:26 UTC (rev 41133)
+++ haiku/trunk/src/add-ons/kernel/bus_managers/ps2/movement_maker.h    
2011-03-28 08:18:31 UTC (rev 41134)
@@ -30,7 +30,6 @@
 } movement_maker;
 
 
-
 void get_raw_movement(movement_maker *move, uint32 posX, uint32 posY);
 void compute_acceleration(movement_maker *move, int8 accel_factor);
 void get_movement(movement_maker *move, uint32 posX, uint32 posY);

Modified: haiku/trunk/src/add-ons/kernel/bus_managers/ps2/packet_buffer.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/bus_managers/ps2/packet_buffer.cpp   
2011-03-28 08:10:26 UTC (rev 41133)
+++ haiku/trunk/src/add-ons/kernel/bus_managers/ps2/packet_buffer.cpp   
2011-03-28 08:18:31 UTC (rev 41134)
@@ -6,32 +6,16 @@
 
 #include "packet_buffer.h"
 
-#include <KernelExport.h>
 #include <util/ring_buffer.h>
 
 #include <stdlib.h>
 #include <string.h>
 
 
-/**    The idea behind this packet buffer is to have multi-threading safe
- *     implementation that can be used in interrupts on top of the
- *     ring_buffer implementation provided by the kernel.
- *     It uses a spinlock for synchronization.
- *
- *     IOW if you don't have such high restrictions in your environment,
- *     you better don't want to use it at all.
- */
-
-struct packet_buffer {
-       struct ring_buffer      *buffer;
-       spinlock                        lock;
-};
-
-
-struct packet_buffer *
+packet_buffer*
 create_packet_buffer(size_t size)
 {
-       struct packet_buffer *buffer
+       packet_buffer* buffer
                = (packet_buffer *)malloc(sizeof(packet_buffer));
        if (buffer == NULL)
                return NULL;
@@ -48,7 +32,7 @@
 
 
 void
-delete_packet_buffer(struct packet_buffer *buffer)
+delete_packet_buffer(packet_buffer* buffer)
 {
        delete_ring_buffer(buffer->buffer);
        free(buffer);
@@ -56,7 +40,7 @@
 
 
 void
-packet_buffer_clear(struct packet_buffer *buffer)
+packet_buffer_clear(packet_buffer* buffer)
 {
        cpu_status state = disable_interrupts();
        acquire_spinlock(&buffer->lock);
@@ -69,7 +53,7 @@
 
 
 size_t
-packet_buffer_readable(struct packet_buffer *buffer)
+packet_buffer_readable(packet_buffer* buffer)
 {
        cpu_status state = disable_interrupts();
        acquire_spinlock(&buffer->lock);
@@ -84,7 +68,7 @@
 
 
 size_t
-packet_buffer_writable(struct packet_buffer *buffer)
+packet_buffer_writable(packet_buffer* buffer)
 {
        cpu_status state = disable_interrupts();
        acquire_spinlock(&buffer->lock);
@@ -99,7 +83,7 @@
 
 
 void
-packet_buffer_flush(struct packet_buffer *buffer, size_t length)
+packet_buffer_flush(packet_buffer* buffer, size_t length)
 {
        cpu_status state = disable_interrupts();
        acquire_spinlock(&buffer->lock);
@@ -112,7 +96,7 @@
 
 
 size_t
-packet_buffer_read(struct packet_buffer *buffer, uint8 *data, size_t length)
+packet_buffer_read(packet_buffer* buffer, uint8 *data, size_t length)
 {
        cpu_status state = disable_interrupts();
        acquire_spinlock(&buffer->lock);
@@ -127,7 +111,7 @@
 
 
 size_t
-packet_buffer_write(struct packet_buffer *buffer, const uint8 *data,
+packet_buffer_write(packet_buffer* buffer, const uint8 *data,
        size_t length)
 {
        cpu_status state = disable_interrupts();

Modified: haiku/trunk/src/add-ons/kernel/bus_managers/ps2/packet_buffer.h
===================================================================
--- haiku/trunk/src/add-ons/kernel/bus_managers/ps2/packet_buffer.h     
2011-03-28 08:10:26 UTC (rev 41133)
+++ haiku/trunk/src/add-ons/kernel/bus_managers/ps2/packet_buffer.h     
2011-03-28 08:18:31 UTC (rev 41134)
@@ -6,30 +6,37 @@
 #define PACKET_BUFFER_H
 
 
+#include <KernelExport.h>
 #include <OS.h>
 
 
-struct packet_buffer;
-typedef struct packet_buffer packet_buffer;
+struct ring_buffer;
 
-#ifdef __cplusplus
-extern "C" {
-#endif
 
-struct packet_buffer *create_packet_buffer(size_t size);
-void delete_packet_buffer(struct packet_buffer *buffer);
+/**    The idea behind this packet buffer is to have multi-threading safe
+ *     implementation that can be used in interrupts on top of the
+ *     ring_buffer implementation provided by the kernel.
+ *     It uses a spinlock for synchronization.
+ *
+ *     IOW if you don't have such high restrictions in your environment,
+ *     you better don't want to use it at all.
+ */
+struct packet_buffer {
+       struct ring_buffer*     buffer;
+       spinlock                        lock;
+};
 
-void packet_buffer_clear(struct packet_buffer *buffer);
-size_t packet_buffer_readable(struct packet_buffer *buffer);
+
+struct packet_buffer* create_packet_buffer(size_t size);
+void delete_packet_buffer(struct packet_buffer* buffer);
+
+void packet_buffer_clear(struct packet_buffer* buffer);
+size_t packet_buffer_readable(struct packet_buffer* buffer);
 size_t packet_buffer_writable(struct packet_buffer *buffer);
-void packet_buffer_flush(struct packet_buffer *buffer, size_t bytes);
-size_t packet_buffer_read(struct packet_buffer *buffer, uint8 *data, size_t
+void packet_buffer_flush(struct packet_buffer* buffer, size_t bytes);
+size_t packet_buffer_read(struct packet_buffer* buffer, uint8* data, size_t
        length);
-size_t packet_buffer_write(struct packet_buffer *buffer, const uint8 *data,
+size_t packet_buffer_write(struct packet_buffer* buffer, const uint8* data,
        size_t length);
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* PACKET_BUFFER_H */

Copied: haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_alps.cpp (from rev 
41133, haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_alps.c)
===================================================================
--- haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_alps.cpp                
                (rev 0)
+++ haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_alps.cpp        
2011-03-28 08:18:31 UTC (rev 41134)
@@ -0,0 +1,836 @@
+/*
+ * Copyright 2011, Haiku, Inc.
+ * Distributed under the terms of the MIT License.
+ *
+ * The alps_model_info struct and all the hardware specs are taken from the
+ * linux driver, thanks a lot!
+ *
+ * Authors:
+ *             Clemens Zeidler (haiku@xxxxxxxxxxxxxxxxxx)
+ */
+
+
+#include "ps2_alps.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <keyboard_mouse_driver.h>
+
+#include "ps2_service.h"
+
+
+const char* kALPSPath[4] = {
+       "input/touchpad/ps2/alps_0",
+       "input/touchpad/ps2/alps_1",
+       "input/touchpad/ps2/alps_2",
+       "input/touchpad/ps2/alps_3"
+};
+
+
+enum button_ids
+{
+       kLeftButton = 0x01,
+       kRightButton = 0x02     
+};
+
+
+typedef struct alps_model_info {
+       uint8           id[3];
+       uint8           firstByte;
+       uint8           maskFirstByte;
+       uint8           flags;
+} alps_model_info;
+
+
+#define ALPS_OLDPROTO           0x01   // old style input
+#define ALPS_DUALPOINT          0x02   // touchpad has trackstick
+#define ALPS_PASS               0x04    // device has a pass-through port
+
+#define ALPS_WHEEL              0x08   // hardware wheel present
+#define ALPS_FW_BK_1            0x10   // front & back buttons present
+#define ALPS_FW_BK_2            0x20   // front & back buttons present
+#define ALPS_FOUR_BUTTONS       0x40   // 4 direction button present
+#define ALPS_PS2_INTERLEAVED    0x80   // 3-byte PS/2 packet interleaved with
+                                                                               
// 6-byte ALPS packet
+
+static const struct alps_model_info gALPSModelInfos[] = {
+//     {{0x32, 0x02, 0x14}, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT},
+               // Toshiba Salellite Pro M10 
+//     {{0x33, 0x02, 0x0a}, 0x88, 0xf8, ALPS_OLDPROTO},
+               // UMAX-530T
+       {{0x53, 0x02, 0x0a}, 0xf8, 0xf8, 0},
+       {{0x53, 0x02, 0x14}, 0xf8, 0xf8, 0},
+       {{0x60, 0x03, 0xc8}, 0xf8, 0xf8, 0},
+               // HP ze1115
+       {{0x63, 0x02, 0x0a}, 0xf8, 0xf8, 0},
+       {{0x63, 0x02, 0x14}, 0xf8, 0xf8, 0},
+//     {{0x63, 0x02, 0x28}, 0xf8, 0xf8, ALPS_FW_BK_2},
+               // Fujitsu Siemens S6010
+//     {{0x63, 0x02, 0x3c}, 0x8f, 0x8f, ALPS_WHEEL},
+               // Toshiba Satellite S2400-103
+//     {{0x63, 0x02, 0x50}, 0xef, 0xef, ALPS_FW_BK_1},
+               // NEC Versa L320
+       {{0x63, 0x02, 0x64}, 0xf8, 0xf8, 0},
+//     {{0x63, 0x03, 0xc8}, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT},
+               // Dell Latitude D800
+       {{0x73, 0x00, 0x0a}, 0xf8, 0xf8, ALPS_DUALPOINT},
+               // ThinkPad R61 8918-5QG, x301
+       {{0x73, 0x02, 0x0a}, 0xf8, 0xf8, 0},
+//     {{0x73, 0x02, 0x14}, 0xf8, 0xf8, ALPS_FW_BK_2},
+               // Ahtec Laptop
+//     {{0x20, 0x02, 0x0e}, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT},
+               // XXX
+//     {{0x22, 0x02, 0x0a}, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT},
+//     {{0x22, 0x02, 0x14}, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT},
+               // Dell Latitude D600
+//     {{0x62, 0x02, 0x14}, 0xcf, 0xcf,  ALPS_PASS | ALPS_DUALPOINT
+//             | ALPS_PS2_INTERLEAVED},
+               // Dell Latitude E5500, E6400, E6500, Precision M4400
+//     {{0x73, 0x02, 0x50}, 0xcf, 0xcf, ALPS_FOUR_BUTTONS},
+               // Dell Vostro 1400
+//     {{0x52, 0x01, 0x14}, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT
+//             | ALPS_PS2_INTERLEAVED},
+               // Toshiba Tecra A11-11L
+       {{0, 0, 0}, 0, 0, 0}
+};
+
+
+static alps_model_info* sFoundModel = NULL;
+
+
+#define PS2_MOUSE_CMD_SET_SCALE11              0xe6
+#define PS2_MOUSE_CMD_SET_SCALE21              0xe7
+#define PS2_MOUSE_CMD_SET_RES                  0xe8
+#define PS2_MOUSE_CMD_GET_INFO                 0xe9
+#define PS2_MOUSE_CMD_SET_STREAM               0xea
+#define PS2_MOUSE_CMD_SET_POLL                 0xf0
+#define PS2_MOUSE_CMD_SET_RATE                 0xf3
+
+
+// touchpad proportions
+#define SPEED_FACTOR           5
+#define EDGE_MOTION_WIDTH      10 
+#define EDGE_MOTION_SPEED      (5 * SPEED_FACTOR)
+// increase the touchpad size a little bit
+#define AREA_START_X           50
+#define AREA_END_X                     985
+#define AREA_WIDTH_X           (AREA_END_X - AREA_START_X)
+#define AREA_START_Y           45
+#define AREA_END_Y                     735
+#define AREA_WIDTH_Y           (AREA_END_Y - AREA_START_Y)
+
+#define TAP_TIMEOUT                    200000
+
+#define MIN_PRESSURE           15
+#define MAX_PRESSURE           115
+
+#define ALPS_HISTORY_SIZE      256
+
+
+typedef struct {
+       uint8           buttons;
+       uint32          xPosition;
+       uint32          yPosition;
+       uint8           zPressure;
+       // absolut mode
+       bool            finger;
+       // absolut w mode
+       uint8           wValue;
+} touch_event;
+
+
+static bool
+edge_motion(mouse_movement *movement, touch_event *event, bool validStart)
+{
+       int32 xdelta = 0;
+       int32 ydelta = 0;
+
+       if (event->xPosition < AREA_START_X + EDGE_MOTION_WIDTH)
+               xdelta = -EDGE_MOTION_SPEED;
+       else if (event->xPosition > AREA_END_X - EDGE_MOTION_WIDTH)
+               xdelta = EDGE_MOTION_SPEED;
+
+       if (event->yPosition < AREA_START_Y + EDGE_MOTION_WIDTH)
+               ydelta = -EDGE_MOTION_SPEED;
+       else if (event->yPosition > AREA_END_Y - EDGE_MOTION_WIDTH)
+               ydelta = EDGE_MOTION_SPEED;
+
+       if (xdelta && validStart)
+               movement->xdelta = xdelta;
+       if (ydelta && validStart)
+               movement->ydelta = ydelta;
+
+       if ((xdelta || ydelta) && !validStart)
+               return false;
+
+       return true;
+}
+
+
+/*!    If a button has been clicked (movement->buttons must be set 
accordingly),
+       this function updates the click_count of the \a cookie, as well as the
+       \a movement's clicks field.
+       Also, it sets the cookie's button state from movement->buttons.
+*/
+static inline void
+update_buttons(alps_cookie *cookie, mouse_movement *movement)
+{
+       // set click count correctly according to double click timeout
+       if (movement->buttons != 0 && cookie->buttons_state == 0) {
+               if (cookie->click_last_time + cookie->click_speed > 
movement->timestamp)
+                       cookie->click_count++;
+               else
+                       cookie->click_count = 1;
+
+               cookie->click_last_time = movement->timestamp;
+       }
+
+       if (movement->buttons != 0)
+               movement->clicks = cookie->click_count;
+
+       cookie->buttons_state = movement->buttons;
+}
+
+
+static inline void
+no_touch_to_movement(alps_cookie *cookie, touch_event *event,
+       mouse_movement *movement)
+{
+       uint32 buttons = event->buttons;
+
+       TRACE("ALPS: no touch event\n");
+
+       cookie->scrolling_started = false;
+       cookie->movement_started = false;
+
+       if (cookie->tapdrag_started
+               && (movement->timestamp - cookie->tap_time) < TAP_TIMEOUT) {
+               buttons = 0x01;
+       }
+
+       // if the movement stopped switch off the tap drag when timeout is 
expired
+       if ((movement->timestamp - cookie->tap_time) > TAP_TIMEOUT) {
+               cookie->tapdrag_started = false;
+               cookie->valid_edge_motion = false;
+               TRACE("ALPS: tap drag gesture timed out\n");
+       }
+
+       if (abs(cookie->tap_delta_x) > 15 || abs(cookie->tap_delta_y) > 15) {
+               cookie->tap_started = false;
+               cookie->tap_clicks = 0;
+       }
+
+       if (cookie->tap_started || cookie->double_click) {
+               TRACE("ALPS: tap gesture\n");
+               cookie->tap_clicks++;
+
+               if (cookie->tap_clicks > 1) {
+                       TRACE("ALPS: empty click\n");
+                       buttons = 0x00;
+                       cookie->tap_clicks = 0;
+                       cookie->double_click = true;
+               } else {
+                       buttons = 0x01;
+                       cookie->tap_started = false;
+                       cookie->tapdrag_started = true;
+                       cookie->double_click = false;
+               }
+       }
+
+       movement->buttons = buttons;
+       update_buttons(cookie, movement);
+}
+
+
+static inline void
+move_to_movement(alps_cookie *cookie, touch_event *event,
+       mouse_movement *movement)
+{
+       touchpad_settings *settings = &cookie->settings;
+       bool isStartOfMovement = false;
+       float pressure = 0;
+
+       TRACE("ALPS: movement event\n");
+       if (!cookie->movement_started) {
+               isStartOfMovement = true;
+               cookie->movement_started = true;
+               start_new_movment(&cookie->movementMaker);
+       }
+
+       get_movement(&cookie->movementMaker, event->xPosition, 
event->yPosition);
+
+       movement->xdelta = cookie->movementMaker.xDelta;
+       movement->ydelta = cookie->movementMaker.yDelta;
+
+       // tap gesture
+       cookie->tap_delta_x += cookie->movementMaker.xDelta;
+       cookie->tap_delta_y += cookie->movementMaker.yDelta;
+
+       if (cookie->tapdrag_started) {
+               movement->buttons = kLeftButton;
+               movement->clicks = 0;
+
+               cookie->valid_edge_motion = edge_motion(movement, event,
+                       cookie->valid_edge_motion);
+               TRACE("ALPS: tap drag\n");
+       } else {
+               TRACE("ALPS: movement set buttons\n");
+               movement->buttons = event->buttons;
+       }
+
+       // use only a fraction of pressure range, the max pressure seems to be
+       // to high
+       pressure = 20 * (event->zPressure - MIN_PRESSURE)
+               / (MAX_PRESSURE - MIN_PRESSURE - 40);
+       if (!cookie->tap_started
+               && isStartOfMovement
+               && settings->tapgesture_sensibility > 0.
+               && settings->tapgesture_sensibility > (20 - pressure)) {
+               TRACE("ALPS: tap started\n");
+               cookie->tap_started = true;
+               cookie->tap_time = system_time();
+               cookie->tap_delta_x = 0;
+               cookie->tap_delta_y = 0;
+       }
+
+       update_buttons(cookie, movement);
+}
+
+
+/*!    Checks if this is a scrolling event or not, and also actually does the
+       scrolling work if it is.
+
+       \return \c true if this was a scrolling event, \c false if not.
+*/
+static inline bool
+check_scrolling_to_movement(alps_cookie *cookie, touch_event *event,
+       mouse_movement *movement)
+{
+       touchpad_settings *settings = &cookie->settings;
+       bool isSideScrollingV = false;
+       bool isSideScrollingH = false;
+
+       // if a button is pressed don't allow to scroll, we likely be in a drag
+       // action
+       if (cookie->buttons_state != 0)
+               return false;
+
+       if ((AREA_END_X - AREA_WIDTH_X * settings->scroll_rightrange
+                       < event->xPosition && !cookie->movement_started
+               && settings->scroll_rightrange > 0.000001)
+                       || settings->scroll_rightrange > 0.999999) {
+               isSideScrollingV = true;
+       }
+       if ((AREA_START_Y + AREA_WIDTH_Y * settings->scroll_bottomrange
+                               > event->yPosition && !cookie->movement_started
+                       && settings->scroll_bottomrange > 0.000001)
+                               || settings->scroll_bottomrange > 0.999999) {
+               isSideScrollingH = true;
+       }
+       if ((event->wValue == 0 || event->wValue == 1)
+               && settings->scroll_twofinger) {
+               // two finger scrolling is enabled
+               isSideScrollingV = true;
+               isSideScrollingH = settings->scroll_twofinger_horizontal;
+       }
+
+       if (!isSideScrollingV && !isSideScrollingH) {
+               cookie->scrolling_started = false;
+               return false;
+       }
+
+       TRACE("ALPS: scroll event\n");
+
+       cookie->tap_started = false;
+       cookie->tap_clicks = 0;
+       cookie->tapdrag_started = false;
+       cookie->valid_edge_motion = false;
+       if (!cookie->scrolling_started) {
+               cookie->scrolling_started = true;
+               start_new_movment(&cookie->movementMaker);
+       }
+       get_scrolling(&cookie->movementMaker, event->xPosition,
+               event->yPosition);
+       movement->wheel_ydelta = cookie->movementMaker.yDelta;
+       movement->wheel_xdelta = cookie->movementMaker.xDelta;
+
+       if (isSideScrollingV && !isSideScrollingH)
+               movement->wheel_xdelta = 0;
+       else if (isSideScrollingH && !isSideScrollingV)
+               movement->wheel_ydelta = 0;
+
+       cookie->buttons_state = movement->buttons;
+
+       return true;
+}
+
+
+static status_t
+event_to_movement(alps_cookie *cookie, touch_event *event,
+       mouse_movement *movement)
+{
+       if (!movement)
+               return B_ERROR;
+
+       movement->xdelta = 0;
+       movement->ydelta = 0;
+       movement->buttons = 0;
+       movement->wheel_ydelta = 0;
+       movement->wheel_xdelta = 0;
+       movement->modifiers = 0;
+       movement->clicks = 0;
+       movement->timestamp = system_time();
+
+       if ((movement->timestamp - cookie->tap_time) > TAP_TIMEOUT) {
+               TRACE("ALPS: tap gesture timed out\n");
+               cookie->tap_started = false;
+               if (!cookie->double_click
+                       || (movement->timestamp - cookie->tap_time) > 2 * 
TAP_TIMEOUT) {
+                       cookie->tap_clicks = 0;
+               }
+       }
+
+       if (event->buttons & kLeftButton) {
+               cookie->tap_clicks = 0;
+               cookie->tapdrag_started = false;
+               cookie->tap_started = false;
+               cookie->valid_edge_motion = false;
+       }
+
+       if (event->zPressure >= MIN_PRESSURE && event->zPressure < MAX_PRESSURE
+               && ((event->wValue >=4 && event->wValue <=7)
+                       || event->wValue == 0 || event->wValue == 1)
+               && (event->xPosition != 0 || event->yPosition != 0)) {
+               // The touch pad is in touch with at least one finger
+               if (!check_scrolling_to_movement(cookie, event, movement))
+                       move_to_movement(cookie, event, movement);
+       } else
+               no_touch_to_movement(cookie, event, movement);
+
+       return B_OK;
+}
+
+
+/* Data taken from linux driver:
+ALPS absolute Mode - new format
+byte 0:  1    ?    ?    ?    1    ?    ?    ?
+byte 1:  0   x6   x5   x4   x3   x2   x1   x0
+byte 2:  0  x10   x9   x8   x7    ?  fin  ges
+byte 3:  0   y9   y8   y7    1    M    R    L
+byte 4:  0   y6   y5   y4   y3   y2   y1   y0
+byte 5:  0   z6   z5   z4   z3   z2   z1   z0
+*/
+// debug 
+static uint32 minX = 50000;
+static uint32 minY = 50000;
+static uint32 maxX = 0;
+static uint32 maxY = 0;
+static uint32 maxZ = 0;
+// debug end
+static status_t
+get_alps_movment(alps_cookie *cookie, mouse_movement *movement)
+{
+       status_t status;
+       touch_event event;
+       uint8 event_buffer[PS2_PACKET_ALPS];
+
+       status = acquire_sem_etc(cookie->sem, 1, B_CAN_INTERRUPT, 0);
+       if (status < B_OK)
+               return status;
+
+       if (!cookie->dev->active) {
+               TRACE("ALPS: read_event: Error device no longer active\n");
+               return B_ERROR;
+       }
+
+       if (packet_buffer_read(cookie->ring_buffer, event_buffer,
+                       cookie->dev->packet_size) != cookie->dev->packet_size) {
+               TRACE("ALPS: error copying buffer\n");
+               return B_ERROR;
+       }
+
+       event.buttons = event_buffer[3] & 3;
+       event.zPressure = event_buffer[5];
+
+       // finger on touchpad
+       if (event_buffer[2] & 0x2) {
+               // finger with normal width
+               event.wValue = 4;
+       } else {
+               event.wValue = 3;
+       }
+
+       // tabgesture
+       if (event_buffer[2] & 0x1) {
+               event.zPressure = 80;
+               event.wValue = 4;
+       }
+
+       event.xPosition = event_buffer[1] | ((event_buffer[2] & 0x78) << 4);
+       event.yPosition = event_buffer[4] | ((event_buffer[3] & 0x70) << 3);
+

[... truncated: 2878 lines follow ...]

Other related posts:

  • » [haiku-commits] r41134 - haiku/trunk/src/add-ons/kernel/bus_managers/ps2 - clemens . zeidler