add support for TSPDRV vibration
* Needed for the LG V30, G7, V35, V40
* Use TW_HAPTICS_TSPDRV in your BoardConfig.mk to enable it.
Change-Id: I0970ed5c046e851f7e6f562283523c7214c8d2b5
(cherry picked from commit 314cbd5698d1750a31c9cf4284d3ce8dfadce157)
diff --git a/minuitwrp/Android.mk b/minuitwrp/Android.mk
index 2b5650d..ac09e49 100644
--- a/minuitwrp/Android.mk
+++ b/minuitwrp/Android.mk
@@ -190,6 +190,11 @@
LOCAL_CFLAGS += -DWHITELIST_INPUT=$(TW_WHITELIST_INPUT)
endif
+ifeq ($(TW_HAPTICS_TSPDRV), true)
+ LOCAL_SRC_FILES += tspdrv.cpp
+ LOCAL_CFLAGS += -DTW_HAPTICS_TSPDRV
+endif
+
ifeq ($(TW_DISABLE_TTF), true)
$(warning ****************************************************************************)
$(warning * TW_DISABLE_TTF support has been deprecated in TWRP. *)
diff --git a/minuitwrp/events.cpp b/minuitwrp/events.cpp
index 955acf3..7e5bc42 100755
--- a/minuitwrp/events.cpp
+++ b/minuitwrp/events.cpp
@@ -128,6 +128,7 @@
}
#ifndef TW_NO_HAPTICS
+#ifndef TW_HAPTICS_TSPDRV
int vibrate(int timeout_ms)
{
if (timeout_ms > 10000) timeout_ms = 1000;
@@ -149,6 +150,7 @@
return 0;
}
#endif
+#endif
/* Returns empty tokens */
static char *vk_strtok_r(char *str, const char *delim, char **save_str)
diff --git a/minuitwrp/tspdrv.cpp b/minuitwrp/tspdrv.cpp
new file mode 100644
index 0000000..6967cd5
--- /dev/null
+++ b/minuitwrp/tspdrv.cpp
@@ -0,0 +1,193 @@
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <cinttypes>
+#include <cmath>
+#include <iostream>
+#include <sys/ioctl.h>
+
+#include "tspdrv.h"
+
+int tspdrv_initialized = 0;
+int tspdrv_file_desc;
+int tspdrv_numActuators = 0;
+
+int initialize_tspdrv()
+{
+ // Open device file as read/write for ioctl and write
+ tspdrv_file_desc = open(TSPDRV, O_RDWR);
+ if(tspdrv_file_desc < 0)
+ {
+ printf("Failed to open device file: %s", TSPDRV);
+ return -1;
+ }
+
+ // create default device parameters
+ device_parameter dev_param1 { 0, VIBE_KP_CFG_FREQUENCY_PARAM1, 0};
+ device_parameter dev_param2 { 0, VIBE_KP_CFG_FREQUENCY_PARAM2, 0};
+ device_parameter dev_param3 { 0, VIBE_KP_CFG_FREQUENCY_PARAM3, 0};
+ device_parameter dev_param4 { 0, VIBE_KP_CFG_FREQUENCY_PARAM4, 400};
+ device_parameter dev_param5 { 0, VIBE_KP_CFG_FREQUENCY_PARAM5, 13435};
+ device_parameter dev_param6 { 0, VIBE_KP_CFG_FREQUENCY_PARAM6, 0};
+ device_parameter dev_param_update_rate {0, VIBE_KP_CFG_UPDATE_RATE_MS, 5};
+
+ // Set magic number for vibration driver, wont allow us to write data without!
+ int ret = ioctl(tspdrv_file_desc, TSPDRV_SET_MAGIC_NUMBER, TSPDRV_MAGIC_NUMBER);
+ if(ret != 0)
+ {
+ printf("Failed to set magic number");
+ return -ret;
+ }
+
+ // Set default device parameter 1
+ ret = ioctl(tspdrv_file_desc, TSPDRV_SET_DEVICE_PARAMETER, &dev_param1);
+ if(ret != 0)
+ {
+ printf("Failed to set device parameter 1");
+ return -ret;
+ }
+
+ // Set default device parameter 2
+ ret = ioctl(tspdrv_file_desc, TSPDRV_SET_DEVICE_PARAMETER, &dev_param2);
+ if(ret != 0)
+ {
+ printf("Failed to set device parameter 2");
+ return -ret;
+ }
+
+ // Set default device parameter 3
+ ret = ioctl(tspdrv_file_desc, TSPDRV_SET_DEVICE_PARAMETER, &dev_param3);
+ if(ret != 0)
+ {
+ printf("Failed to set device parameter 3");
+ return -ret;
+ }
+
+ // Set default device parameter 4
+ ret = ioctl(tspdrv_file_desc, TSPDRV_SET_DEVICE_PARAMETER, &dev_param4);
+ if(ret != 0)
+ {
+ printf("Failed to set device parameter 4");
+ return -ret;
+ }
+
+ // Set default device parameter 5
+ ret = ioctl(tspdrv_file_desc, TSPDRV_SET_DEVICE_PARAMETER, &dev_param5);
+ if(ret != 0)
+ {
+ printf("Failed to set device parameter 5");
+ return -ret;
+ }
+
+ // Set default device parameter 6
+ ret = ioctl(tspdrv_file_desc, TSPDRV_SET_DEVICE_PARAMETER, &dev_param6);
+ if(ret != 0)
+ {
+ printf("Failed to set device parameter 6");
+ return -ret;
+ }
+
+ // Set default device parameter update rate
+ ret = ioctl(tspdrv_file_desc, TSPDRV_SET_DEVICE_PARAMETER, &dev_param_update_rate);
+ if(ret != 0)
+ {
+ printf("Failed to set device parameter update rate");
+ return -ret;
+ }
+
+ // Get number of actuators the device has
+ ret = ioctl(tspdrv_file_desc, TSPDRV_GET_NUM_ACTUATORS, 0);
+ if(ret == 0)
+ {
+ printf("No actuators found!");
+ return -2;
+ }
+
+ tspdrv_numActuators = ret;
+ tspdrv_initialized = 1;
+ return 0;
+}
+
+int tspdrv_off() {
+
+ for(int32_t i = 0; i < tspdrv_numActuators; i++)
+ {
+ int32_t ret = ioctl(tspdrv_file_desc, TSPDRV_DISABLE_AMP, i);
+ if(ret != 0)
+ {
+ printf("Failed to deactivate Actuator with index %d", i);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int vibrate(int timeout_ms)
+{
+ double BUFFER_ENTRIES_PER_MS = 8.21;
+ uint8_t DEFAULT_AMPLITUDE = 127;
+ int32_t OUTPUT_BUFFER_SIZE = 40;
+
+ if(!tspdrv_initialized)
+ {
+ printf("Initializing TSPDRV\n");
+ if(initialize_tspdrv() == 0)
+ {
+ printf("TSPDRV initialized\n");
+ }
+ }
+
+ // Calculate needed buffer entries
+ int32_t bufferSize = (int32_t) round(BUFFER_ENTRIES_PER_MS * timeout_ms);
+ VibeUInt8 fullBuffer[bufferSize];
+
+ // turn previous vibrations off
+ tspdrv_off();
+
+ for(int32_t i = 0; i < bufferSize; i++)
+ {
+ // The vibration is a sine curve, the negative parts are 255 + negative value
+ fullBuffer[i] = (VibeUInt8) (DEFAULT_AMPLITUDE * sin(i/BUFFER_ENTRIES_PER_MS));
+ }
+
+ // Amount of buffer arrays with size of OUTPUT_BUFFER_SIZE
+ int32_t numBuffers = (int32_t) ceil((double)bufferSize / (double)OUTPUT_BUFFER_SIZE);
+ VibeUInt8 outputBuffers[numBuffers][OUTPUT_BUFFER_SIZE];
+ memset(outputBuffers, 0, sizeof(outputBuffers)); // zero the array before we fill it with values
+
+ for(int32_t i = 0; i < bufferSize; i++)
+ {
+ // split fullBuffer into multiple smaller buffers with size OUTPUT_BUFFER_SIZE
+ outputBuffers[i/OUTPUT_BUFFER_SIZE][i%OUTPUT_BUFFER_SIZE] = fullBuffer[i];
+ }
+
+ for(int32_t i = 0; i < tspdrv_numActuators; i++)
+ {
+ for(int32_t j = 0; j < numBuffers; j++)
+ {
+ char output[OUTPUT_BUFFER_SIZE + SPI_HEADER_SIZE];
+ memset(output, 0, sizeof(output));
+ output[0] = i; // first byte is actuator index
+ output[1] = 8; // per definition has to be 8
+ output[2] = OUTPUT_BUFFER_SIZE; // size of the following output buffer
+ for(int32_t k = 3; k < OUTPUT_BUFFER_SIZE+3; k++)
+ {
+ output[k] = outputBuffers[j][k-3];
+ }
+ // write the buffer to the device
+ write(tspdrv_file_desc, output, sizeof(output));
+ if((j+1) % 4 == 0)
+ {
+ // every 4 buffers, but not the first if theres only 1, we send an ENABLE_AMP signal
+ int32_t ret = ioctl(tspdrv_file_desc, TSPDRV_ENABLE_AMP, i);
+ if(ret != 0)
+ {
+ printf("Failed to activate Actuator with index %d", i);
+ return -1;
+ }
+ }
+ }
+ }
+ return 0;
+}
\ No newline at end of file
diff --git a/minuitwrp/tspdrv.h b/minuitwrp/tspdrv.h
new file mode 100644
index 0000000..afb294e
--- /dev/null
+++ b/minuitwrp/tspdrv.h
@@ -0,0 +1,100 @@
+/*
+** =========================================================================
+** File:
+** tspdrv.h
+**
+** Description:
+** Constants and type definitions for the TouchSense Kernel Module.
+**
+** Portions Copyright (c) 2008-2017 Immersion Corporation. All Rights Reserved.
+**
+** This file contains Original Code and/or Modifications of Original Code
+** as defined in and that are subject to the GNU Public License v2 -
+** (the 'License'). You may not use this file except in compliance with the
+** License. You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software Foundation, Inc.,
+** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or contact
+** TouchSenseSales@immersion.com.
+**
+** The Original Code and all software distributed under the License are
+** distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+** EXPRESS OR IMPLIED, AND IMMERSION HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+** INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
+** FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see
+** the License for the specific language governing rights and limitations
+** under the License.
+** =========================================================================
+*/
+
+#ifndef _TSPDRV_H
+#define _TSPDRV_H
+
+/* Constants */
+#define MODULE_NAME "tspdrv"
+#define TSPDRV "/dev/tspdrv"
+#define TSPDRV_MAGIC_NUMBER 0x494D4D52
+#define TSPDRV_IOCTL_GROUP 0x52
+#define TSPDRV_STOP_KERNEL_TIMER _IO(TSPDRV_IOCTL_GROUP, 1) /* obsolete, may be removed in future */
+#define TSPDRV_SET_MAGIC_NUMBER _IO(TSPDRV_IOCTL_GROUP, 2)
+#define TSPDRV_ENABLE_AMP _IO(TSPDRV_IOCTL_GROUP, 3)
+#define TSPDRV_DISABLE_AMP _IO(TSPDRV_IOCTL_GROUP, 4)
+#define TSPDRV_GET_NUM_ACTUATORS _IO(TSPDRV_IOCTL_GROUP, 5)
+#define TSPDRV_SET_DEVICE_PARAMETER _IO(TSPDRV_IOCTL_GROUP, 6)
+#define TSPDRV_SET_DBG_LEVEL _IO(TSPDRV_IOCTL_GROUP, 7)
+#define TSPDRV_GET_DBG_LEVEL _IO(TSPDRV_IOCTL_GROUP, 8)
+#define TSPDRV_SET_RUNTIME_RECORD_FLAG _IO(TSPDRV_IOCTL_GROUP, 9)
+#define TSPDRV_GET_RUNTIME_RECORD_FLAG _IO(TSPDRV_IOCTL_GROUP, 10)
+#define TSPDRV_SET_RUNTIME_RECORD_BUF_SIZE _IO(TSPDRV_IOCTL_GROUP, 11)
+#define TSPDRV_GET_RUNTIME_RECORD_BUF_SIZE _IO(TSPDRV_IOCTL_GROUP, 12)
+#define TSPDRV_GET_PARAM_FILE_ID _IO(TSPDRV_IOCTL_GROUP, 13)
+#define TSPDRV_GET_DEVICE_STATUS _IO(TSPDRV_IOCTL_GROUP, 14)
+/*
+** Frequency constant parameters to control force output values and signals.
+*/
+#define VIBE_KP_CFG_FREQUENCY_PARAM1 85
+#define VIBE_KP_CFG_FREQUENCY_PARAM2 86
+#define VIBE_KP_CFG_FREQUENCY_PARAM3 87
+#define VIBE_KP_CFG_FREQUENCY_PARAM4 88
+#define VIBE_KP_CFG_FREQUENCY_PARAM5 89
+#define VIBE_KP_CFG_FREQUENCY_PARAM6 90
+
+/*
+** Force update rate in milliseconds.
+*/
+#define VIBE_KP_CFG_UPDATE_RATE_MS 95
+
+#define VIBE_MAX_DEVICE_NAME_LENGTH 64
+#define SPI_HEADER_SIZE 3 /* DO NOT CHANGE - SPI buffer header size */
+#define VIBE_OUTPUT_SAMPLE_SIZE 50 /* DO NOT CHANGE - maximum number of samples */
+#define MAX_DEBUG_BUFFER_LENGTH 1024
+
+typedef int8_t VibeInt8;
+typedef u_int8_t VibeUInt8;
+typedef int16_t VibeInt16;
+typedef u_int16_t VibeUInt16;
+typedef int32_t VibeInt32;
+typedef u_int32_t VibeUInt32;
+typedef u_int8_t VibeBool;
+typedef VibeInt32 VibeStatus;
+
+/* Device parameters sent to the kernel module, tspdrv.ko */
+typedef struct
+{
+ VibeInt32 nDeviceIndex;
+ VibeInt32 nDeviceParamID;
+ VibeInt32 nDeviceParamValue;
+} device_parameter;
+
+typedef struct
+{
+ VibeUInt8 nActuatorIndex; /* 1st byte is actuator index */
+ VibeUInt8 nBitDepth; /* 2nd byte is bit depth */
+ VibeUInt8 nBufferSize; /* 3rd byte is data size */
+ VibeUInt8 dataBuffer[40];
+} actuator_samples_buffer;
+
+/* Error and Return value codes */
+#define VIBE_S_SUCCESS 0 /* Success */
+#define VIBE_E_FAIL -4 /* Generic error */
+
+#endif /* _TSPDRV_H */