• Synaptics ClickPad as a USB mouse

    Deling Ren08/05/2024 at 18:08 0 comments

    Context

    I harvested a touchpad from an old HP Envy Sleekbook 6 and wanted to use it as a standalone mouse. It's a clickpad. I.e. it has only one physical button and right click is simulated in software.

    Goals:

    • Cursor movements.
    • Left click and right click (with two fingers).
    • Two-finger scrolling.
    • Make a housing for it.

    Status:

    • Everything listed above is fully implemented.
    • No rigorous testing has been done.
    • Some basic error handling is done.
    • I have no problem using it as a daily drive.
    • It works very well for tracking and scrolling.
    • But it's slightly jerky when clicking the button with the thumb which is not as nimble and precise as other fingers.
    • I also want to be able to increase the granularity of scrolling. I'm not sure if it's feasible. The build-in touchpad on MacBooks have very fine control.
    • Housing is not done yet. I want to use a USB-C connector. My dev board is micro USB. I need to either get a USB-C dev board (such as Elite-C) or a USB-C breakout PCB.

    Most laptop touchpads are made by Synaptics. They usually use a PS/2 interface. By default (i.e. without any special drivers), they can usually simulate a regular PS/2 mouse. I.e. they can report finger movements and button clicks. But that's about it. They don't support more sophisticated gestures we normally find on laptops. To achieve those gestures, we need to implement proprietary but published (with some caveats) Synaptics protocols, documented in [Synaptics PS/2 TouchPad Interfacing Guide](touchpad_RevB.pdf).

    Touchpad info

    • Pulled from an HP Envy Sleekbook 6
    • Synaptics chip model number: T1320A
    • Physical pinout: Vcc, CLK, DAT, NC, NC, GND. Reverse engineered after watching this [YouTube video]()

    More info obtained from programatic queries, based on section 4.4. Information queries.

    • Query 0x00 (Identify TouchPad): 01 47 18. - Version 8.1
    • Query 0x01 (Read TouchPad Modes): 20 87 40. - Model 0x0887
    • Query 0x02 (Read Capabilities): D0 01 23 - Extended capability: yes - Extended queries: 13 - Middle button: no - Model sub number: 01 - Pass through: no - Low power: no - Multi finger report: yes - Can sleep: no - Four buttons: no - Ballitics: no - Multi finger detect: yes - Palm detect: yes
    • Query 0x03 (Read Model ID): 01 E2 B1 - Absolute mode: yes - Geometry: rectangule
    • Query 0x06 (Read Serial Number Prefix): 00 00 00
    • Query 0x07 (Read Serial Number Suffix): 00 00 00
    • Query 0x08 (Read Resolutions): 2F 80 42 - x units per mm: 47 - y units per mm: 66 * Query 0x09 (Extended Model ID): 84 03 00 - Light control: no - Peak detect: no - Glass pass: no - Vertical wheel: no - Ext. W mode: yes - H Scroll: no - V Scroll: no - Extended buttons: 0 - Product ID: 0x00
    • Query 0x0C (Continued Capabilities): 12 6C 00 - Covered Pad Gesture: no - MultiFinger Mode: 1.0 - Advanced Gestures: no - ClearPad: no - Reports Max Coordinates: yes - TouchButton Adjustable Threshold: no - InterTouch: yes - Reports Min Coordinates: yes - Uniform ClickPad: no (Hinged mechanism) - Reports V: yes - No Absolute Position Filter: no - Deluxe LEDs: no - ClickPad: One-button ClickPad
    • Query 0x0D (Maximum Coordinates): B1 6B 94 - max x: 5686 - max y: 4748
    • Query 0x0F (Minimum Coordinates): 27 94 22 - min x: 1256 - min y: 1106

    Implementing PS/2 on an MCU

    So, I'm using an atmel mega32u4 to interface with the touchpad. Any Leonardo clone should work. The reason I picked this MCU is its native USB HID support. Another alternative is to use tinyusb library to bit bang USB protocol on supported MCUs. It's probably pretty straight-forward too.

    Basically, I implemented syncrhonous writing, synchronous reading, and asynchronous reading. Synchronous writing because async writing is difficult to use. However, given the async nature of PS/2 protocol, it makes sense to have async, interrupt based reading. I.e. bits are transferred via interrupts and stored in a buffer. I have also implemented synchronous reading as a means to read responses after each write.
    I'm using [external interrupts](https://developerhelp.microchip.com/xwiki/bin/view/products/mcu-mpu/8-bit-avr/structure/extint/)...

    Read more »