diff options
Diffstat (limited to 'chip/stm32/usb_hid_touchpad.c')
-rw-r--r-- | chip/stm32/usb_hid_touchpad.c | 424 |
1 files changed, 0 insertions, 424 deletions
diff --git a/chip/stm32/usb_hid_touchpad.c b/chip/stm32/usb_hid_touchpad.c deleted file mode 100644 index 0ead660432..0000000000 --- a/chip/stm32/usb_hid_touchpad.c +++ /dev/null @@ -1,424 +0,0 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "clock.h" -#include "common.h" -#include "config.h" -#include "console.h" -#include "gpio.h" -#include "hooks.h" -#include "hwtimer.h" -#include "link_defs.h" -#include "queue.h" -#include "registers.h" -#include "task.h" -#include "timer.h" -#include "util.h" -#include "usb_api.h" -#include "usb_descriptor.h" -#include "usb_hw.h" -#include "usb_hid.h" -#include "usb_hid_hw.h" -#include "usb_hid_touchpad.h" - -/* Console output macro */ -#define CPRINTF(format, args...) cprintf(CC_USB, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USB, format, ## args) - -static const int touchpad_debug; - -static struct queue const report_queue = QUEUE_NULL(8, - struct usb_hid_touchpad_report); -static struct mutex report_queue_mutex; - -#define HID_TOUCHPAD_REPORT_SIZE sizeof(struct usb_hid_touchpad_report) - -/* - * Touchpad EP interval: Make sure this value is smaller than the typical - * interrupt interval from the trackpad. - */ -#define HID_TOUCHPAD_EP_INTERVAL_MS 2 /* ms */ - -/* Discard TP events older than this time */ -#define EVENT_DISCARD_MAX_TIME (1 * SECOND) - -/* HID descriptors */ -const struct usb_interface_descriptor USB_IFACE_DESC(USB_IFACE_HID_TOUCHPAD) = { - .bLength = USB_DT_INTERFACE_SIZE, - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = USB_IFACE_HID_TOUCHPAD, - .bAlternateSetting = 0, - .bNumEndpoints = 1, - .bInterfaceClass = USB_CLASS_HID, - .bInterfaceSubClass = 0, - .bInterfaceProtocol = 0, - .iInterface = 0, -}; -const struct usb_endpoint_descriptor USB_EP_DESC(USB_IFACE_HID_TOUCHPAD, 81) = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x80 | USB_EP_HID_TOUCHPAD, - .bmAttributes = 0x03 /* Interrupt endpoint */, - .wMaxPacketSize = HID_TOUCHPAD_REPORT_SIZE, - .bInterval = HID_TOUCHPAD_EP_INTERVAL_MS /* polling interval */ -}; - -#define FINGER_USAGE \ - 0x05, 0x0D, /* Usage Page (Digitizer) */ \ - 0x09, 0x22, /* Usage (Finger) */ \ - 0xA1, 0x02, /* Collection (Logical) */ \ - 0x09, 0x47, /* Usage (Confidence) */ \ - 0x09, 0x42, /* Usage (Tip Switch) */ \ - 0x09, 0x32, /* Usage (In Range) */ \ - 0x15, 0x00, /* Logical Minimum (0) */ \ - 0x25, 0x01, /* Logical Maximum (1) */ \ - 0x75, 0x01, /* Report Size (1) */ \ - 0x95, 0x03, /* Report Count (3) */ \ - 0x81, 0x02, /* Input (Data,Var,Abs) */ \ - 0x09, 0x51, /* Usage (0x51) Contact identifier */ \ - 0x75, 0x04, /* Report Size (4) */ \ - 0x95, 0x01, /* Report Count (1) */ \ - 0x25, 0x0F, /* Logical Maximum (15) */ \ - 0x81, 0x02, /* Input (Data,Var,Abs) */ \ - 0x05, 0x0D, /* Usage Page (Digitizer) */ \ - /* Logical Maximum of Pressure */ \ - 0x26, (CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_PRESSURE & 0xFF), \ - (CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_PRESSURE >> 8), \ - 0x75, 0x09, /* Report Size (9) */ \ - 0x09, 0x30, /* Usage (Tip pressure) */ \ - 0x81, 0x02, /* Input (Data,Var,Abs) */ \ - 0x26, 0xFF, 0x0F, /* Logical Maximum (4095) */ \ - 0x75, 0x0C, /* Report Size (12) */ \ - 0x09, 0x48, /* Usage (WIDTH) */ \ - 0x81, 0x02, /* Input (Data,Var,Abs) */ \ - 0x09, 0x49, /* Usage (HEIGHT) */ \ - 0x81, 0x02, /* Input (Data,Var,Abs) */ \ - 0x05, 0x01, /* Usage Page (Generic Desktop Ctrls) */ \ - 0x75, 0x0C, /* Report Size (12) */ \ - 0x55, 0x0E, /* Unit Exponent (-2) */ \ - 0x65, 0x11, /* Unit (System: SI Linear, Length: cm) */ \ - 0x09, 0x30, /* Usage (X) */ \ - 0x35, 0x00, /* Physical Minimum (0) */ \ - 0x26, (CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_X & 0xff), \ - (CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_X >> 8), \ - /* Logical Maximum */ \ - 0x46, (CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_X & 0xff), \ - (CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_X >> 8), \ - /* Physical Maximum (tenth of mm) */ \ - 0x81, 0x02, /* Input (Data,Var,Abs) */ \ - 0x26, (CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_Y & 0xff), \ - (CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_Y >> 8), \ - /* Logical Maximum */ \ - 0x46, (CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_Y & 0xff), \ - (CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_Y >> 8), \ - /* Physical Maximum (tenth of mm) */ \ - 0x09, 0x31, /* Usage (Y) */ \ - 0x81, 0x02, /* Input (Data,Var,Abs) */ \ - 0xC0 /* End Collection */ - -/* - * HID: Report Descriptor - * TODO(b/35582031): There are ways to reduce flash usage, as the - * Finger Usage is repeated 5 times. - */ -static const uint8_t report_desc[] = { - /* Touchpad Collection */ - 0x05, 0x0D, /* Usage Page (Digitizer) */ - 0x09, 0x05, /* Usage (Touch Pad) */ - 0xA1, 0x01, /* Collection (Application) */ - 0x85, REPORT_ID_TOUCHPAD, /* Report ID (1, Touch) */ - /* Finger 0 */ - FINGER_USAGE, - /* Finger 1 */ - FINGER_USAGE, - /* Finger 2 */ - FINGER_USAGE, - /* Finger 3 */ - FINGER_USAGE, - /* Finger 4 */ - FINGER_USAGE, - /* Contact count */ - 0x05, 0x0D, /* Usage Page (Digitizer) */ - 0x09, 0x54, /* Usage (Contact count) */ - 0x25, MAX_FINGERS, /* Logical Maximum (MAX_FINGERS) */ - 0x75, 0x07, /* Report Size (7) */ - 0x95, 0x01, /* Report Count (1) */ - 0x81, 0x02, /* Input (Data,Var,Abs) */ - /* Button */ - 0x05, 0x01, /* Usage Page(Generic Desktop Ctrls) */ - 0x05, 0x09, /* Usage (Button) */ - 0x19, 0x01, /* Usage Minimum (0x01) */ - 0x29, 0x01, /* Usage Maximum (0x01) */ - 0x15, 0x00, /* Logical Minimum (0) */ - 0x25, 0x01, /* Logical Maximum (1) */ - 0x75, 0x01, /* Report Size (1) */ - 0x95, 0x01, /* Report Count (1) */ - 0x81, 0x02, /* Input (Data,Var,Abs) */ - /* Timestamp */ - 0x05, 0x0D, /* Usage Page (Digitizer) */ - 0x55, 0x0C, /* Unit Exponent (-4) */ - 0x66, 0x01, 0x10, /* Unit (Seconds) */ - 0x47, 0xFF, 0xFF, 0x00, 0x00, /* Physical Maximum (65535) */ - 0x27, 0xFF, 0xFF, 0x00, 0x00, /* Logical Maximum (65535) */ - 0x75, 0x10, /* Report Size (16) */ - 0x95, 0x01, /* Report Count (1) */ - 0x09, 0x56, /* Usage (0x56, Relative Scan Time) */ - 0x81, 0x02, /* Input (Data,Var,Abs) */ - - 0x85, REPORT_ID_DEVICE_CAPS, /* Report ID (Device Capabilities) */ - 0x09, 0x55, /* Usage (Contact Count Maximum) */ - 0x09, 0x59, /* Usage (Pad Type) */ - 0x25, 0x0F, /* Logical Maximum (15) */ - 0x75, 0x08, /* Report Size (8) */ - 0x95, 0x02, /* Report Count (2) */ - 0xB1, 0x02, /* Feature (Data,Var,Abs) */ - - /* Page 0xFF, usage 0xC5 is device certificate. */ - 0x06, 0x00, 0xFF, /* Usage Page (Vendor Defined) */ - 0x85, REPORT_ID_DEVICE_CERT, /* Report ID (Device Certification) */ - 0x09, 0xC5, /* Usage (Vendor Usage 0xC5) */ - 0x15, 0x00, /* Logical Minimum (0) */ - 0x26, 0xFF, 0x00, /* Logical Maximum (255) */ - 0x75, 0x08, /* Report Size (8) */ - 0x96, 0x00, 0x01, /* Report Count (256) */ - 0xB1, 0x02, /* Feature (Data,Var,Abs) */ - - 0xC0, /* End Collection */ -}; - -/* A 256-byte default blob for the 'device certification status' feature report. - * - * TODO(b/113248108): do we need a real certification? - */ -static const uint8_t device_cert_response[] = { - REPORT_ID_DEVICE_CERT, - - 0xFC, 0x28, 0xFE, 0x84, 0x40, 0xCB, 0x9A, 0x87, - 0x0D, 0xBE, 0x57, 0x3C, 0xB6, 0x70, 0x09, 0x88, - 0x07, 0x97, 0x2D, 0x2B, 0xE3, 0x38, 0x34, 0xB6, - 0x6C, 0xED, 0xB0, 0xF7, 0xE5, 0x9C, 0xF6, 0xC2, - 0x2E, 0x84, 0x1B, 0xE8, 0xB4, 0x51, 0x78, 0x43, - 0x1F, 0x28, 0x4B, 0x7C, 0x2D, 0x53, 0xAF, 0xFC, - 0x47, 0x70, 0x1B, 0x59, 0x6F, 0x74, 0x43, 0xC4, - 0xF3, 0x47, 0x18, 0x53, 0x1A, 0xA2, 0xA1, 0x71, - 0xC7, 0x95, 0x0E, 0x31, 0x55, 0x21, 0xD3, 0xB5, - 0x1E, 0xE9, 0x0C, 0xBA, 0xEC, 0xB8, 0x89, 0x19, - 0x3E, 0xB3, 0xAF, 0x75, 0x81, 0x9D, 0x53, 0xB9, - 0x41, 0x57, 0xF4, 0x6D, 0x39, 0x25, 0x29, 0x7C, - 0x87, 0xD9, 0xB4, 0x98, 0x45, 0x7D, 0xA7, 0x26, - 0x9C, 0x65, 0x3B, 0x85, 0x68, 0x89, 0xD7, 0x3B, - 0xBD, 0xFF, 0x14, 0x67, 0xF2, 0x2B, 0xF0, 0x2A, - 0x41, 0x54, 0xF0, 0xFD, 0x2C, 0x66, 0x7C, 0xF8, - 0xC0, 0x8F, 0x33, 0x13, 0x03, 0xF1, 0xD3, 0xC1, - 0x0B, 0x89, 0xD9, 0x1B, 0x62, 0xCD, 0x51, 0xB7, - 0x80, 0xB8, 0xAF, 0x3A, 0x10, 0xC1, 0x8A, 0x5B, - 0xE8, 0x8A, 0x56, 0xF0, 0x8C, 0xAA, 0xFA, 0x35, - 0xE9, 0x42, 0xC4, 0xD8, 0x55, 0xC3, 0x38, 0xCC, - 0x2B, 0x53, 0x5C, 0x69, 0x52, 0xD5, 0xC8, 0x73, - 0x02, 0x38, 0x7C, 0x73, 0xB6, 0x41, 0xE7, 0xFF, - 0x05, 0xD8, 0x2B, 0x79, 0x9A, 0xE2, 0x34, 0x60, - 0x8F, 0xA3, 0x32, 0x1F, 0x09, 0x78, 0x62, 0xBC, - 0x80, 0xE3, 0x0F, 0xBD, 0x65, 0x20, 0x08, 0x13, - 0xC1, 0xE2, 0xEE, 0x53, 0x2D, 0x86, 0x7E, 0xA7, - 0x5A, 0xC5, 0xD3, 0x7D, 0x98, 0xBE, 0x31, 0x48, - 0x1F, 0xFB, 0xDA, 0xAF, 0xA2, 0xA8, 0x6A, 0x89, - 0xD6, 0xBF, 0xF2, 0xD3, 0x32, 0x2A, 0x9A, 0xE4, - 0xCF, 0x17, 0xB7, 0xB8, 0xF4, 0xE1, 0x33, 0x08, - 0x24, 0x8B, 0xC4, 0x43, 0xA5, 0xE5, 0x24, 0xC2, -}; - -/* Device capabilities feature report. */ -static const uint8_t device_caps_response[] = { - REPORT_ID_DEVICE_CAPS, - - MAX_FINGERS, /* Contact Count Maximum */ - 0x00, /* Pad Type: Depressible click-pad */ -}; - -const struct usb_hid_descriptor USB_CUSTOM_DESC_VAR(USB_IFACE_HID_TOUCHPAD, - hid, hid_desc_tp) = { - .bLength = 9, - .bDescriptorType = USB_HID_DT_HID, - .bcdHID = 0x0100, - .bCountryCode = 0x00, /* Hardware target country */ - .bNumDescriptors = 1, - .desc = {{ - .bDescriptorType = USB_HID_DT_REPORT, - .wDescriptorLength = sizeof(report_desc) - }} -}; - -static usb_uint hid_ep_buf[DIV_ROUND_UP(HID_TOUCHPAD_REPORT_SIZE, 2)] __usb_ram; - -/* - * Write a report to EP, must be called with queue mutex held, and caller - * must first check that EP is not busy. - */ -static void write_touchpad_report(struct usb_hid_touchpad_report *report) -{ - memcpy_to_usbram((void *) usb_sram_addr(hid_ep_buf), - report, sizeof(*report)); - /* enable TX */ - STM32_TOGGLE_EP(USB_EP_HID_TOUCHPAD, EP_TX_MASK, EP_TX_VALID, 0); - - /* - * Wake the host. This is required to prevent a race between EP getting - * reloaded and host suspending the device, as, ideally, we never want - * to have EP loaded during suspend, to avoid reporting stale data. - */ - usb_wake(); -} - -static void hid_touchpad_process_queue(void); -DECLARE_DEFERRED(hid_touchpad_process_queue); - -static void hid_touchpad_process_queue(void) -{ - struct usb_hid_touchpad_report report; - uint16_t now; - int trimming = 0; - - mutex_lock(&report_queue_mutex); - - /* EP is busy, or nothing in queue: do nothing. */ - if (queue_count(&report_queue) == 0) - goto unlock; - - now = __hw_clock_source_read() / USB_HID_TOUCHPAD_TIMESTAMP_UNIT; - - if (usb_is_suspended() || - (STM32_USB_EP(USB_EP_HID_TOUCHPAD) & EP_TX_MASK) - == EP_TX_VALID) { - usb_wake(); - - /* Let's trim old events from the queue, if any. */ - trimming = 1; - } else { - hook_call_deferred(&hid_touchpad_process_queue_data, -1); - } - - if (touchpad_debug) - CPRINTS("TPQ t=%d (%d)", trimming, queue_count(&report_queue)); - - while (queue_count(&report_queue) > 0) { - int delta; - - queue_peek_units(&report_queue, &report, 0, 1); - - delta = (int)((uint16_t)(now - report.timestamp)) - * USB_HID_TOUCHPAD_TIMESTAMP_UNIT; - - if (touchpad_debug) - CPRINTS("evt t=%d d=%d", report.timestamp, delta); - - /* Drop old events */ - if (delta > EVENT_DISCARD_MAX_TIME) { - queue_advance_head(&report_queue, 1); - continue; - } - - if (trimming) { - /* - * If we stil fail to resume, this will discard the - * event after the timeout expires. - */ - hook_call_deferred(&hid_touchpad_process_queue_data, - EVENT_DISCARD_MAX_TIME - delta); - } else { - queue_advance_head(&report_queue, 1); - write_touchpad_report(&report); - } - break; - } - -unlock: - mutex_unlock(&report_queue_mutex); -} - -void set_touchpad_report(struct usb_hid_touchpad_report *report) -{ - static int print_full = 1; - - mutex_lock(&report_queue_mutex); - - /* USB/EP ready and nothing in queue, just write the report. */ - if (!usb_is_suspended() && - (STM32_USB_EP(USB_EP_HID_TOUCHPAD) & EP_TX_MASK) != EP_TX_VALID - && queue_count(&report_queue) == 0) { - write_touchpad_report(report); - mutex_unlock(&report_queue_mutex); - return; - } - - /* Else add to queue, dropping oldest event if needed. */ - if (touchpad_debug) - CPRINTS("sTP t=%d", report->timestamp); - if (queue_is_full(&report_queue)) { - if (print_full) - CPRINTF("TP queue full\n"); - print_full = 0; - - queue_advance_head(&report_queue, 1); - } else { - print_full = 1; - } - queue_add_unit(&report_queue, report); - - mutex_unlock(&report_queue_mutex); - - hid_touchpad_process_queue(); -} - -static void hid_touchpad_tx(void) -{ - hid_tx(USB_EP_HID_TOUCHPAD); - - if (queue_count(&report_queue) > 0) - hook_call_deferred(&hid_touchpad_process_queue_data, 0); -} - -static void hid_touchpad_event(enum usb_ep_event evt) -{ - if (evt == USB_EVENT_RESET) - hid_reset(USB_EP_HID_TOUCHPAD, hid_ep_buf, - HID_TOUCHPAD_REPORT_SIZE, NULL, 0); - else if (evt == USB_EVENT_DEVICE_RESUME && - queue_count(&report_queue) > 0) - hook_call_deferred(&hid_touchpad_process_queue_data, 0); -} - -USB_DECLARE_EP(USB_EP_HID_TOUCHPAD, hid_touchpad_tx, hid_touchpad_tx, - hid_touchpad_event); - -static int get_report(uint8_t report_id, uint8_t report_type, - const uint8_t **buffer_ptr, - int *buffer_size) -{ - switch (report_id) { - case REPORT_ID_DEVICE_CAPS: - *buffer_ptr = device_caps_response; - *buffer_size = MIN(sizeof(device_caps_response), *buffer_size); - return 0; - case REPORT_ID_DEVICE_CERT: - *buffer_ptr = device_cert_response; - *buffer_size = MIN(sizeof(device_cert_response), *buffer_size); - return 0; - } - return -1; -} - -static const struct usb_hid_config_t hid_config_tp = { - .report_desc = report_desc, - .report_size = sizeof(report_desc), - .hid_desc = &hid_desc_tp, - .get_report = get_report, -}; - -static int hid_touchpad_iface_request(usb_uint *ep0_buf_rx, - usb_uint *ep0_buf_tx) -{ - return hid_iface_request(ep0_buf_rx, ep0_buf_tx, &hid_config_tp); -} -USB_DECLARE_IFACE(USB_IFACE_HID_TOUCHPAD, hid_touchpad_iface_request) |