Related
Does anyone have any information about how to adjust screen sensitivity under Android, specifricaly Froyo on Nexus One?
I'm trying to research this topic but there seems to be very little information about this. I can't find any tool, script or custom rom that would allow screen sensitivity to be adjusted.
I found a thread talking about doing it for Liqid's touch using script but that's about it. I took a look on the script and I can't move forward with it as the path's script uses do not exists in my Nexus One. If anyone has any experience with this please share. The goal is to make the screen more sensitive then it is as a default.
Thanks.
Thread reference above:
android.modaco.com/content-page/309503/increase-touch-screen-sensitivity-only-tested-on-liquide-1-100-05-based-roms/page/40/
Script:
#!/system/bin/sh
sensitivity=25
noise=25
echo "set sensitivity to $sensitivity"
echo $sensitivity > /sys/devices/platform/i2c-adapter/i2c-0/0-005c/sensitivity
echo "set noise to $noise"
echo $noise > /sys/devices/platform/i2c-adapter/i2c-0/0-005c/noise
echo "done"
Sorry for bringing back something from the dead, but I've been researching about this. Nexus One screen sensitivity is low, compared to other touch screens I've experimented with. I know Nexus One is using a Synaptics board. Digging in the source code of Android, I found that the settings on the device itself are located here:
/system/usr/idc/synaptics-rmi-touchscreen.idc
The contents of the file as per 2.3.7 are these (they are the same since Gingerbread):
# Copyright (C) 2010 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Input Device Calibration File for the Passion touch screen.
#
# These calibration values are derived from empirical measurements
# and may not be appropriate for use with other touch screens.
# Refer to the input device calibration documentation for more details.
#
# Touch Size
touch.touchSize.calibration = pressure
# Tool Size
# Driver reports tool size as a linear width measurement summed over
# all contact points.
#
# Raw width field measures approx. 1 unit per millimeter
# of tool size on the surface where a raw width of 1 corresponds
# to about 17mm of physical size. Given that the display resolution
# is 10px per mm we obtain a scale factor of 10 pixels / unit and
# a bias of 160 pixels. In addition, the raw width represents a
# sum of all contact area so we note this fact in the calibration.
touch.toolSize.calibration = linear
touch.toolSize.linearScale = 10
touch.toolSize.linearBias = 160
touch.toolSize.isSummed = 1
# Pressure
# Driver reports signal strength as pressure.
#
# A normal thumb touch while touching the back of the device
# typically registers about 100 signal strength units although
# this value is highly variable and is sensitive to contact area,
# manner of contact and environmental conditions. We set the
# scale so that a normal touch with good signal strength will be
# reported as having a pressure somewhere in the vicinity of 1.0,
# a featherlight touch will be below 1.0 and a heavy or large touch
# will be above 1.0. We don't expect these values to be accurate.
touch.pressure.calibration = amplitude
touch.pressure.source = default
touch.pressure.scale = 0.01
# Size
touch.size.calibration = normalized
# Orientation
touch.orientation.calibration = none
Click to expand...
Click to collapse
Also, in the kernel, the synaptics driver can be configured to be more sensitive. It is located here on the kernel source:
drivers/input/touchscreen/synaptics_i2c_rmi.c
/*
*
* Copyright (C) 2007 Google, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/earlysuspend.h>
#include <linux/hrtimer.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/synaptics_i2c_rmi.h>
static struct workqueue_struct *synaptics_wq;
struct synaptics_ts_data {
uint16_t addr;
struct i2c_client *client;
struct input_dev *input_dev;
int use_irq;
bool has_relative_report;
struct hrtimer timer;
struct work_struct work;
uint16_t max[2];
int snap_state[2][2];
int snap_down_on[2];
int snap_down_off[2];
int snap_up_on[2];
int snap_up_off[2];
int snap_down[2];
int snap_up[2];
uint32_t flags;
int reported_finger_count;
int8_t sensitivity_adjust;
int (*power)(int on);
struct early_suspend early_suspend;
};
#ifdef CONFIG_HAS_EARLYSUSPEND
static void synaptics_ts_early_suspend(struct early_suspend *h);
static void synaptics_ts_late_resume(struct early_suspend *h);
#endif
static int synaptics_init_panel(struct synaptics_ts_data *ts)
{
int ret;
ret = i2c_smbus_write_byte_data(ts->client, 0xff, 0x10); /* page select = 0x10 */
if (ret < 0) {
printk(KERN_ERR "i2c_smbus_write_byte_data failed for page select\n");
goto err_page_select_failed;
}
ret = i2c_smbus_write_byte_data(ts->client, 0x41, 0x04); /* Set "No Clip Z" */
if (ret < 0)
printk(KERN_ERR "i2c_smbus_write_byte_data failed for No Clip Z\n");
ret = i2c_smbus_write_byte_data(ts->client, 0x44,
ts->sensitivity_adjust);
if (ret < 0)
pr_err("synaptics_ts: failed to set Sensitivity Adjust\n");
err_page_select_failed:
ret = i2c_smbus_write_byte_data(ts->client, 0xff, 0x04); /* page select = 0x04 */
if (ret < 0)
printk(KERN_ERR "i2c_smbus_write_byte_data failed for page select\n");
ret = i2c_smbus_write_byte_data(ts->client, 0xf0, 0x81); /* normal operation, 80 reports per second */
if (ret < 0)
printk(KERN_ERR "synaptics_ts_resume: i2c_smbus_write_byte_data failed\n");
return ret;
}
static void synaptics_ts_work_func(struct work_struct *work)
{
int i;
int ret;
int bad_data = 0;
struct i2c_msg msg[2];
uint8_t start_reg;
uint8_t buf[15];
struct synaptics_ts_data *ts = container_of(work, struct synaptics_ts_data, work);
int buf_len = ts->has_relative_report ? 15 : 13;
msg[0].addr = ts->client->addr;
msg[0].flags = 0;
msg[0].len = 1;
msg[0].buf = &start_reg;
start_reg = 0x00;
msg[1].addr = ts->client->addr;
msg[1].flags = I2C_M_RD;
msg[1].len = buf_len;
msg[1].buf = buf;
/* printk("synaptics_ts_work_func\n"); */
for (i = 0; i < ((ts->use_irq && !bad_data) ? 1 : 10); i++) {
ret = i2c_transfer(ts->client->adapter, msg, 2);
if (ret < 0) {
printk(KERN_ERR "synaptics_ts_work_func: i2c_transfer failed\n");
bad_data = 1;
} else {
/* printk("synaptics_ts_work_func: %x %x %x %x %x %x" */
/* " %x %x %x %x %x %x %x %x %x, ret %d\n", */
/* buf[0], buf[1], buf[2], buf[3], */
/* buf[4], buf[5], buf[6], buf[7], */
/* buf[8], buf[9], buf[10], buf[11], */
/* buf[12], buf[13], buf[14], ret); */
if ((buf[buf_len - 1] & 0xc0) != 0x40) {
printk(KERN_WARNING "synaptics_ts_work_func:"
" bad read %x %x %x %x %x %x %x %x %x"
" %x %x %x %x %x %x, ret %d\n",
buf[0], buf[1], buf[2], buf[3],
buf[4], buf[5], buf[6], buf[7],
buf[8], buf[9], buf[10], buf[11],
buf[12], buf[13], buf[14], ret);
if (bad_data)
synaptics_init_panel(ts);
bad_data = 1;
continue;
}
bad_data = 0;
if ((buf[buf_len - 1] & 1) == 0) {
/* printk("read %d coordinates\n", i); */
break;
} else {
int pos[2][2];
int f, a;
int base;
/* int x = buf[3] | (uint16_t)(buf[2] & 0x1f) << 8; */
/* int y = buf[5] | (uint16_t)(buf[4] & 0x1f) << 8; */
int z = buf[1];
int w = buf[0] >> 4;
int finger = buf[0] & 7;
/* int x2 = buf[3+6] | (uint16_t)(buf[2+6] & 0x1f) << 8; */
/* int y2 = buf[5+6] | (uint16_t)(buf[4+6] & 0x1f) << 8; */
/* int z2 = buf[1+6]; */
/* int w2 = buf[0+6] >> 4; */
/* int finger2 = buf[0+6] & 7; */
/* int dx = (int8_t)buf[12]; */
/* int dy = (int8_t)buf[13]; */
int finger2_pressed;
/* printk("x %4d, y %4d, z %3d, w %2d, F %d, 2nd: x %4d, y %4d, z %3d, w %2d, F %d, dx %4d, dy %4d\n", */
/* x, y, z, w, finger, */
/* x2, y2, z2, w2, finger2, */
/* dx, dy); */
base = 2;
for (f = 0; f < 2; f++) {
uint32_t flip_flag = SYNAPTICS_FLIP_X;
for (a = 0; a < 2; a++) {
int p = buf[base + 1];
p |= (uint16_t)(buf[base] & 0x1f) << 8;
if (ts->flags & flip_flag)
p = ts->max[a] - p;
if (ts->flags & SYNAPTICS_SNAP_TO_INACTIVE_EDGE) {
if (ts->snap_state[f][a]) {
if (p <= ts->snap_down_off[a])
p = ts->snap_down[a];
else if (p >= ts->snap_up_off[a])
p = ts->snap_up[a];
else
ts->snap_state[f][a] = 0;
} else {
if (p <= ts->snap_down_on[a]) {
p = ts->snap_down[a];
ts->snap_state[f][a] = 1;
} else if (p >= ts->snap_up_on[a]) {
p = ts->snap_up[a];
ts->snap_state[f][a] = 1;
}
}
}
pos[f][a] = p;
base += 2;
flip_flag <<= 1;
}
base += 2;
if (ts->flags & SYNAPTICS_SWAP_XY)
swap(pos[f][0], pos[f][1]);
}
if (z) {
input_report_abs(ts->input_dev, ABS_X, pos[0][0]);
input_report_abs(ts->input_dev, ABS_Y, pos[0][1]);
}
input_report_abs(ts->input_dev, ABS_PRESSURE, z);
input_report_abs(ts->input_dev, ABS_TOOL_WIDTH, w);
input_report_key(ts->input_dev, BTN_TOUCH, finger);
finger2_pressed = finger > 1 && finger != 7;
input_report_key(ts->input_dev, BTN_2, finger2_pressed);
if (finger2_pressed) {
input_report_abs(ts->input_dev, ABS_HAT0X, pos[1][0]);
input_report_abs(ts->input_dev, ABS_HAT0Y, pos[1][1]);
}
if (!finger)
z = 0;
input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, z);
input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, w);
input_report_abs(ts->input_dev, ABS_MT_POSITION_X, pos[0][0]);
input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, pos[0][1]);
input_mt_sync(ts->input_dev);
if (finger2_pressed) {
input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, z);
input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, w);
input_report_abs(ts->input_dev, ABS_MT_POSITION_X, pos[1][0]);
input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, pos[1][1]);
input_mt_sync(ts->input_dev);
} else if (ts->reported_finger_count > 1) {
input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0);
input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0);
input_mt_sync(ts->input_dev);
}
ts->reported_finger_count = finger;
input_sync(ts->input_dev);
}
}
}
if (ts->use_irq)
enable_irq(ts->client->irq);
}
static enum hrtimer_restart synaptics_ts_timer_func(struct hrtimer *timer)
{
struct synaptics_ts_data *ts = container_of(timer, struct synaptics_ts_data, timer);
/* printk("synaptics_ts_timer_func\n"); */
queue_work(synaptics_wq, &ts->work);
hrtimer_start(&ts->timer, ktime_set(0, 12500000), HRTIMER_MODE_REL);
return HRTIMER_NORESTART;
}
static irqreturn_t synaptics_ts_irq_handler(int irq, void *dev_id)
{
struct synaptics_ts_data *ts = dev_id;
/* printk("synaptics_ts_irq_handler\n"); */
disable_irq_nosync(ts->client->irq);
queue_work(synaptics_wq, &ts->work);
return IRQ_HANDLED;
}
static int synaptics_ts_probe(
struct i2c_client *client, const struct i2c_device_id *id)
{
struct synaptics_ts_data *ts;
uint8_t buf0[4];
uint8_t buf1[8];
struct i2c_msg msg[2];
int ret = 0;
uint16_t max_x, max_y;
int fuzz_x, fuzz_y, fuzz_p, fuzz_w;
struct synaptics_i2c_rmi_platform_data *pdata;
unsigned long irqflags;
int inactive_area_left;
int inactive_area_right;
int inactive_area_top;
int inactive_area_bottom;
int snap_left_on;
int snap_left_off;
int snap_right_on;
int snap_right_off;
int snap_top_on;
int snap_top_off;
int snap_bottom_on;
int snap_bottom_off;
uint32_t panel_version;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
printk(KERN_ERR "synaptics_ts_probe: need I2C_FUNC_I2C\n");
ret = -ENODEV;
goto err_check_functionality_failed;
}
ts = kzalloc(sizeof(*ts), GFP_KERNEL);
if (ts == NULL) {
ret = -ENOMEM;
goto err_alloc_data_failed;
}
INIT_WORK(&ts->work, synaptics_ts_work_func);
ts->client = client;
i2c_set_clientdata(client, ts);
pdata = client->dev.platform_data;
if (pdata)
ts->power = pdata->power;
if (ts->power) {
ret = ts->power(1);
if (ret < 0) {
printk(KERN_ERR "synaptics_ts_probe power on failed\n");
goto err_power_failed;
}
}
ret = i2c_smbus_write_byte_data(ts->client, 0xf4, 0x01); /* device command = reset */
if (ret < 0) {
printk(KERN_ERR "i2c_smbus_write_byte_data failed\n");
/* fail? */
}
{
int retry = 10;
while (retry-- > 0) {
ret = i2c_smbus_read_byte_data(ts->client, 0xe4);
if (ret >= 0)
break;
msleep(100);
}
}
if (ret < 0) {
printk(KERN_ERR "i2c_smbus_read_byte_data failed\n");
goto err_detect_failed;
}
printk(KERN_INFO "synaptics_ts_probe: Product Major Version %x\n", ret);
panel_version = ret << 8;
ret = i2c_smbus_read_byte_data(ts->client, 0xe5);
if (ret < 0) {
printk(KERN_ERR "i2c_smbus_read_byte_data failed\n");
goto err_detect_failed;
}
printk(KERN_INFO "synaptics_ts_probe: Product Minor Version %x\n", ret);
panel_version |= ret;
ret = i2c_smbus_read_byte_data(ts->client, 0xe3);
if (ret < 0) {
printk(KERN_ERR "i2c_smbus_read_byte_data failed\n");
goto err_detect_failed;
}
printk(KERN_INFO "synaptics_ts_probe: product property %x\n", ret);
if (pdata) {
while (pdata->version > panel_version)
pdata++;
ts->flags = pdata->flags;
ts->sensitivity_adjust = pdata->sensitivity_adjust;
irqflags = pdata->irqflags;
inactive_area_left = pdata->inactive_left;
inactive_area_right = pdata->inactive_right;
inactive_area_top = pdata->inactive_top;
inactive_area_bottom = pdata->inactive_bottom;
snap_left_on = pdata->snap_left_on;
snap_left_off = pdata->snap_left_off;
snap_right_on = pdata->snap_right_on;
snap_right_off = pdata->snap_right_off;
snap_top_on = pdata->snap_top_on;
snap_top_off = pdata->snap_top_off;
snap_bottom_on = pdata->snap_bottom_on;
snap_bottom_off = pdata->snap_bottom_off;
fuzz_x = pdata->fuzz_x;
fuzz_y = pdata->fuzz_y;
fuzz_p = pdata->fuzz_p;
fuzz_w = pdata->fuzz_w;
} else {
irqflags = 0;
inactive_area_left = 0;
inactive_area_right = 0;
inactive_area_top = 0;
inactive_area_bottom = 0;
snap_left_on = 0;
snap_left_off = 0;
snap_right_on = 0;
snap_right_off = 0;
snap_top_on = 0;
snap_top_off = 0;
snap_bottom_on = 0;
snap_bottom_off = 0;
fuzz_x = 0;
fuzz_y = 0;
fuzz_p = 0;
fuzz_w = 0;
}
ret = i2c_smbus_read_byte_data(ts->client, 0xf0);
if (ret < 0) {
printk(KERN_ERR "i2c_smbus_read_byte_data failed\n");
goto err_detect_failed;
}
printk(KERN_INFO "synaptics_ts_probe: device control %x\n", ret);
ret = i2c_smbus_read_byte_data(ts->client, 0xf1);
if (ret < 0) {
printk(KERN_ERR "i2c_smbus_read_byte_data failed\n");
goto err_detect_failed;
}
printk(KERN_INFO "synaptics_ts_probe: interrupt enable %x\n", ret);
ret = i2c_smbus_write_byte_data(ts->client, 0xf1, 0); /* disable interrupt */
if (ret < 0) {
printk(KERN_ERR "i2c_smbus_write_byte_data failed\n");
goto err_detect_failed;
}
msg[0].addr = ts->client->addr;
msg[0].flags = 0;
msg[0].len = 1;
msg[0].buf = buf0;
buf0[0] = 0xe0;
msg[1].addr = ts->client->addr;
msg[1].flags = I2C_M_RD;
msg[1].len = 8;
msg[1].buf = buf1;
ret = i2c_transfer(ts->client->adapter, msg, 2);
if (ret < 0) {
printk(KERN_ERR "i2c_transfer failed\n");
goto err_detect_failed;
}
printk(KERN_INFO "synaptics_ts_probe: 0xe0: %x %x %x %x %x %x %x %x\n",
buf1[0], buf1[1], buf1[2], buf1[3],
buf1[4], buf1[5], buf1[6], buf1[7]);
ret = i2c_smbus_write_byte_data(ts->client, 0xff, 0x10); /* page select = 0x10 */
if (ret < 0) {
printk(KERN_ERR "i2c_smbus_write_byte_data failed for page select\n");
goto err_detect_failed;
}
ret = i2c_smbus_read_word_data(ts->client, 0x02);
if (ret < 0) {
printk(KERN_ERR "i2c_smbus_read_word_data failed\n");
goto err_detect_failed;
}
ts->has_relative_report = !(ret & 0x100);
printk(KERN_INFO "synaptics_ts_probe: Sensor properties %x\n", ret);
ret = i2c_smbus_read_word_data(ts->client, 0x04);
if (ret < 0) {
printk(KERN_ERR "i2c_smbus_read_word_data failed\n");
goto err_detect_failed;
}
ts->max[0] = max_x = (ret >> 8 & 0xff) | ((ret & 0x1f) << 8);
ret = i2c_smbus_read_word_data(ts->client, 0x06);
if (ret < 0) {
printk(KERN_ERR "i2c_smbus_read_word_data failed\n");
goto err_detect_failed;
}
ts->max[1] = max_y = (ret >> 8 & 0xff) | ((ret & 0x1f) << 8);
if (ts->flags & SYNAPTICS_SWAP_XY)
swap(max_x, max_y);
ret = synaptics_init_panel(ts); /* will also switch back to page 0x04 */
if (ret < 0) {
printk(KERN_ERR "synaptics_init_panel failed\n");
goto err_detect_failed;
}
ts->input_dev = input_allocate_device();
if (ts->input_dev == NULL) {
ret = -ENOMEM;
printk(KERN_ERR "synaptics_ts_probe: Failed to allocate input device\n");
goto err_input_dev_alloc_failed;
}
ts->input_dev->name = "synaptics-rmi-touchscreen";
set_bit(EV_SYN, ts->input_dev->evbit);
set_bit(EV_KEY, ts->input_dev->evbit);
set_bit(BTN_TOUCH, ts->input_dev->keybit);
set_bit(BTN_2, ts->input_dev->keybit);
set_bit(EV_ABS, ts->input_dev->evbit);
inactive_area_left = inactive_area_left * max_x / 0x10000;
inactive_area_right = inactive_area_right * max_x / 0x10000;
inactive_area_top = inactive_area_top * max_y / 0x10000;
inactive_area_bottom = inactive_area_bottom * max_y / 0x10000;
snap_left_on = snap_left_on * max_x / 0x10000;
snap_left_off = snap_left_off * max_x / 0x10000;
snap_right_on = snap_right_on * max_x / 0x10000;
snap_right_off = snap_right_off * max_x / 0x10000;
snap_top_on = snap_top_on * max_y / 0x10000;
snap_top_off = snap_top_off * max_y / 0x10000;
snap_bottom_on = snap_bottom_on * max_y / 0x10000;
snap_bottom_off = snap_bottom_off * max_y / 0x10000;
fuzz_x = fuzz_x * max_x / 0x10000;
fuzz_y = fuzz_y * max_y / 0x10000;
ts->snap_down[!!(ts->flags & SYNAPTICS_SWAP_XY)] = -inactive_area_left;
ts->snap_up[!!(ts->flags & SYNAPTICS_SWAP_XY)] = max_x + inactive_area_right;
ts->snap_down[!(ts->flags & SYNAPTICS_SWAP_XY)] = -inactive_area_top;
ts->snap_up[!(ts->flags & SYNAPTICS_SWAP_XY)] = max_y + inactive_area_bottom;
ts->snap_down_on[!!(ts->flags & SYNAPTICS_SWAP_XY)] = snap_left_on;
ts->snap_down_off[!!(ts->flags & SYNAPTICS_SWAP_XY)] = snap_left_off;
ts->snap_up_on[!!(ts->flags & SYNAPTICS_SWAP_XY)] = max_x - snap_right_on;
ts->snap_up_off[!!(ts->flags & SYNAPTICS_SWAP_XY)] = max_x - snap_right_off;
ts->snap_down_on[!(ts->flags & SYNAPTICS_SWAP_XY)] = snap_top_on;
ts->snap_down_off[!(ts->flags & SYNAPTICS_SWAP_XY)] = snap_top_off;
ts->snap_up_on[!(ts->flags & SYNAPTICS_SWAP_XY)] = max_y - snap_bottom_on;
ts->snap_up_off[!(ts->flags & SYNAPTICS_SWAP_XY)] = max_y - snap_bottom_off;
printk(KERN_INFO "synaptics_ts_probe: max_x %d, max_y %d\n", max_x, max_y);
printk(KERN_INFO "synaptics_ts_probe: inactive_x %d %d, inactive_y %d %d\n",
inactive_area_left, inactive_area_right,
inactive_area_top, inactive_area_bottom);
printk(KERN_INFO "synaptics_ts_probe: snap_x %d-%d %d-%d, snap_y %d-%d %d-%d\n",
snap_left_on, snap_left_off, snap_right_on, snap_right_off,
snap_top_on, snap_top_off, snap_bottom_on, snap_bottom_off);
input_set_abs_params(ts->input_dev, ABS_X, -inactive_area_left, max_x + inactive_area_right, fuzz_x, 0);
input_set_abs_params(ts->input_dev, ABS_Y, -inactive_area_top, max_y + inactive_area_bottom, fuzz_y, 0);
input_set_abs_params(ts->input_dev, ABS_PRESSURE, 0, 255, fuzz_p, 0);
input_set_abs_params(ts->input_dev, ABS_TOOL_WIDTH, 0, 15, fuzz_w, 0);
input_set_abs_params(ts->input_dev, ABS_HAT0X, -inactive_area_left, max_x + inactive_area_right, fuzz_x, 0);
input_set_abs_params(ts->input_dev, ABS_HAT0Y, -inactive_area_top, max_y + inactive_area_bottom, fuzz_y, 0);
input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, -inactive_area_left, max_x + inactive_area_right, fuzz_x, 0);
input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, -inactive_area_top, max_y + inactive_area_bottom, fuzz_y, 0);
input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, fuzz_p, 0);
input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 15, fuzz_w, 0);
/* ts->input_dev->name = ts->keypad_info->name; */
ret = input_register_device(ts->input_dev);
if (ret) {
printk(KERN_ERR "synaptics_ts_probe: Unable to register %s input device\n", ts->input_dev->name);
goto err_input_register_device_failed;
}
if (client->irq) {
ret = request_irq(client->irq, synaptics_ts_irq_handler, irqflags, client->name, ts);
if (ret == 0) {
ret = i2c_smbus_write_byte_data(ts->client, 0xf1, 0x01); /* enable abs int */
if (ret)
free_irq(client->irq, ts);
}
if (ret == 0)
ts->use_irq = 1;
else
dev_err(&client->dev, "request_irq failed\n");
}
if (!ts->use_irq) {
hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
ts->timer.function = synaptics_ts_timer_func;
hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
}
#ifdef CONFIG_HAS_EARLYSUSPEND
ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
ts->early_suspend.suspend = synaptics_ts_early_suspend;
ts->early_suspend.resume = synaptics_ts_late_resume;
register_early_suspend(&ts->early_suspend);
#endif
printk(KERN_INFO "synaptics_ts_probe: Start touchscreen %s in %s mode\n", ts->input_dev->name, ts->use_irq ? "interrupt" : "polling");
return 0;
err_input_register_device_failed:
input_free_device(ts->input_dev);
err_input_dev_alloc_failed:
err_detect_failed:
err_power_failed:
kfree(ts);
err_alloc_data_failed:
err_check_functionality_failed:
return ret;
}
static int synaptics_ts_remove(struct i2c_client *client)
{
struct synaptics_ts_data *ts = i2c_get_clientdata(client);
unregister_early_suspend(&ts->early_suspend);
if (ts->use_irq)
free_irq(client->irq, ts);
else
hrtimer_cancel(&ts->timer);
input_unregister_device(ts->input_dev);
kfree(ts);
return 0;
}
static int synaptics_ts_suspend(struct i2c_client *client, pm_message_t mesg)
{
int ret;
struct synaptics_ts_data *ts = i2c_get_clientdata(client);
if (ts->use_irq)
disable_irq(client->irq);
else
hrtimer_cancel(&ts->timer);
ret = cancel_work_sync(&ts->work);
if (ret && ts->use_irq) /* if work was pending disable-count is now 2 */
enable_irq(client->irq);
ret = i2c_smbus_write_byte_data(ts->client, 0xf1, 0); /* disable interrupt */
if (ret < 0)
printk(KERN_ERR "synaptics_ts_suspend: i2c_smbus_write_byte_data failed\n");
ret = i2c_smbus_write_byte_data(client, 0xf0, 0x86); /* deep sleep */
if (ret < 0)
printk(KERN_ERR "synaptics_ts_suspend: i2c_smbus_write_byte_data failed\n");
if (ts->power) {
ret = ts->power(0);
if (ret < 0)
printk(KERN_ERR "synaptics_ts_resume power off failed\n");
}
return 0;
}
static int synaptics_ts_resume(struct i2c_client *client)
{
int ret;
struct synaptics_ts_data *ts = i2c_get_clientdata(client);
if (ts->power) {
ret = ts->power(1);
if (ret < 0)
printk(KERN_ERR "synaptics_ts_resume power on failed\n");
}
synaptics_init_panel(ts);
if (ts->use_irq)
enable_irq(client->irq);
if (!ts->use_irq)
hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
else
i2c_smbus_write_byte_data(ts->client, 0xf1, 0x01); /* enable abs int */
return 0;
}
#ifdef CONFIG_HAS_EARLYSUSPEND
static void synaptics_ts_early_suspend(struct early_suspend *h)
{
struct synaptics_ts_data *ts;
ts = container_of(h, struct synaptics_ts_data, early_suspend);
synaptics_ts_suspend(ts->client, PMSG_SUSPEND);
}
static void synaptics_ts_late_resume(struct early_suspend *h)
{
struct synaptics_ts_data *ts;
ts = container_of(h, struct synaptics_ts_data, early_suspend);
synaptics_ts_resume(ts->client);
}
#endif
static const struct i2c_device_id synaptics_ts_id[] = {
{ SYNAPTICS_I2C_RMI_NAME, 0 },
{ }
};
static struct i2c_driver synaptics_ts_driver = {
.probe = synaptics_ts_probe,
.remove = synaptics_ts_remove,
#ifndef CONFIG_HAS_EARLYSUSPEND
.suspend = synaptics_ts_suspend,
.resume = synaptics_ts_resume,
#endif
.id_table = synaptics_ts_id,
.driver = {
.name = SYNAPTICS_I2C_RMI_NAME,
},
};
static int __devinit synaptics_ts_init(void)
{
synaptics_wq = create_singlethread_workqueue("synaptics_wq");
if (!synaptics_wq)
return -ENOMEM;
return i2c_add_driver(&synaptics_ts_driver);
}
static void __exit synaptics_ts_exit(void)
{
i2c_del_driver(&synaptics_ts_driver);
if (synaptics_wq)
destroy_workqueue(synaptics_wq);
}
module_init(synaptics_ts_init);
module_exit(synaptics_ts_exit);
MODULE_DESCRIPTION("Synaptics Touchscreen Driver");
MODULE_LICENSE("GPL");
Click to expand...
Click to collapse
Maybe we can tweak only the .icl file, or we'll have to dig deep into the kernel to improve the responsiveness of this touch screen!
Increased the sensitivity by changing the value:
touch.pressure.scale = 0.01 to touch.pressure.scale = 0.001
in /system/usr/idc/synaptics-rmi-touchscreen.idc
Please use the Q&A Forum for questions Thanks
Moving to Q&A
dferreira said:
Increased the sensitivity by changing the value:
touch.pressure.scale = 0.01 to touch.pressure.scale = 0.001
in /system/usr/idc/synaptics-rmi-touchscreen.idc
Click to expand...
Click to collapse
I just tried this on my MyTouch 4G Slide (htc Doubleshot) running CyanogenMod 10 (20130101). It either works beautifully or it's my imagination. Thanks!!!!!
Screen Sensitivity Enhancement
GandalfTW said:
Does anyone have any information about how to adjust screen sensitivity under Android, specifricaly Froyo on Nexus One?
I'm trying to research this topic but there seems to be very little information about this. I can't find any tool, script or custom rom that would allow screen sensitivity to be adjusted.
I found a thread talking about doing it for Liqid's touch using script but that's about it. I took a look on the script and I can't move forward with it as the path's script uses do not exists in my Nexus One. If anyone has any experience with this please share. The goal is to make the screen more sensitive then it is as a default.
Thanks.
Thread reference above:
android.modaco.com/content-page/309503/increase-touch-screen-sensitivity-only-tested-on-liquide-1-100-05-based-roms/page/40/
Script:
#!/system/bin/sh
sensitivity=25
noise=25
echo "set sensitivity to $sensitivity"
echo $sensitivity > /sys/devices/platform/i2c-adapter/i2c-0/0-005c/sensitivity
echo "set noise to $noise"
echo $noise > /sys/devices/platform/i2c-adapter/i2c-0/0-005c/noise
echo "done"
Click to expand...
Click to collapse
The easiest way you can change your screen sensitivity is by using Screen Booster apps from Google Play. Its really works dude
So let's say I did this and now my screen doesn't work. How can I get it back?
found new method
worked for my zte v9800
Go to System and find build.prop
Then copy the bellow lines and just paste in bulid.prop
# Touch screen calibration and scroll responsiveness
debug.performance.tuning=1
windowsmgr.max_events_per_sec=200
view.touch_slop=2
view.scroll_friction=1.5
view.minimum_fling_velocity=25
ro.max.fling_velocity=12000
ro.min.fling_velocity=8000
ro.min_pointer_dur=8
touch.size.calibration=geometric
touch.size.scale=100
#touch.size.bias=70
touch.pressure.calibration=amplitude
touch.pressure.scale=0.3
Will we ever manage to get rid of the boot screen? Where it says dual core technology with the Moto symbol?
When I flashed CM7 on my Cappy, it replaced the entire boot screen. Is this possible for us?
The furture cm7 probably have it but until we get the easy issues fix I doubt any time soon. Plus we need a dev to do it which we only have a hand full if them for ATRIX. The revs we have now have been really busy handling the important mods that make the ATRIX fun
Sent from my MB860 using XDA Premium App
http://forum.xda-developers.com/showthread.php?p=15529644 try this?
Sent from my MB860 using Tapatalk
Jnewell05 said:
http://forum.xda-developers.com/showthread.php?p=15529644 try this?
Sent from my MB860 using Tapatalk
Click to expand...
Click to collapse
Think they are talking about the boot screen which comes before the boot animation.
CaelanT said:
Think they are talking about the boot screen which comes before the boot animation.
Click to expand...
Click to collapse
Correct. The still image of the dual core technology.
Hi,
If you want to change the boot logo, you just fastboot flash logo logo.bin. It's mmcblk0p8.
The format is a constant string, 4 bytes, "SOL:" followed by 4 zero bytes, followed by 4 bytes for the width, 540, 4 bytes for the height 960, and the raw data of the image. Each pixel is 2 bytes, it's 565 format.
save a png as 540x960 called logo.png
$ convert -depth 8 logo.png rgb:logo.raw
$ ./rgb2565 < logo.raw > temp.bin
$ cat logo-heaader.bin temp.bin > logo.bin
$ sudo ./moto-fastboot flash logo logo.bin
Here is the source to rgb2565:
Code:
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define to565(r,g,b) \
((((r) >> 3) << 11) | (((g) >> 2) << 5) | ((b) >> 3))
#define from565_r(x) ((((x) >> 11) & 0x1f) * 255 / 31)
#define from565_g(x) ((((x) >> 5) & 0x3f) * 255 / 63)
#define from565_b(x) (((x) & 0x1f) * 255 / 31)
void to_565_raw(void)
{
unsigned char in[3];
unsigned short out;
while(read(0, in, 3) == 3) {
out = to565(in[0],in[1],in[2]);
write(1, &out, 2);
}
return;
}
void to_565_raw_dither(int width)
{
unsigned char in[3];
unsigned short out;
int i = 0;
int e;
int* error = malloc((width+2) * 3 * sizeof(int));
int* next_error = malloc((width+2) * 3 * sizeof(int));
memset(error, 0, (width+2) * 3 * sizeof(int));
memset(next_error, 0, (width+2) * 3 * sizeof(int));
error += 3; // array goes from [-3..((width+1)*3+2)]
next_error += 3;
while(read(0, in, 3) == 3) {
int r = in[0] + error[i*3+0];
int rb = (r < 0) ? 0 : ((r > 255) ? 255 : r);
int g = in[1] + error[i*3+1];
int gb = (g < 0) ? 0 : ((g > 255) ? 255 : g);
int b = in[2] + error[i*3+2];
int bb = (b < 0) ? 0 : ((b > 255) ? 255 : b);
out = to565(rb, gb, bb);
write(1, &out, 2);
#define apply_error(ch) { \
next_error[(i-1)*3+ch] += e * 3 / 16; \
next_error[(i)*3+ch] += e * 5 / 16; \
next_error[(i+1)*3+ch] += e * 1 / 16; \
error[(i+1)*3+ch] += e - ((e*1/16) + (e*3/16) + (e*5/16)); \
}
e = r - from565_r(out);
apply_error(0);
e = g - from565_g(out);
apply_error(1);
e = b - from565_b(out);
apply_error(2);
#undef apply_error
++i;
if (i == width) {
// error <- next_error; next_error <- 0
int* temp = error; error = next_error; next_error = temp;
memset(next_error, 0, (width+1) * 3 * sizeof(int));
i = 0;
}
}
free(error-3);
free(next_error-3);
return;
}
void to_565_rle(void)
{
unsigned char in[3];
unsigned short last, color, count;
unsigned total = 0;
count = 0;
while(read(0, in, 3) == 3) {
color = to565(in[0],in[1],in[2]);
if (count) {
if ((color == last) && (count != 65535)) {
count++;
continue;
} else {
write(1, &count, 2);
write(1, &last, 2);
total += count;
}
}
last = color;
count = 1;
}
if (count) {
write(1, &count, 2);
write(1, &last, 2);
total += count;
}
fprintf(stderr,"%d pixels\n",total);
}
int main(int argc, char **argv)
{
if ((argc == 2) && (!strcmp(argv[1],"-rle"))) {
to_565_rle();
} else {
if (argc > 2 && (!strcmp(argv[1], "-w"))) {
to_565_raw_dither(atoi(argv[2]));
} else {
to_565_raw();
}
}
return 0;
}
See example logo.bin attached.
Cheers!
Thanks NF! Your post kind of made my brain fry a little though
Sent from my MB860 using XDA Premium App
Sinful Animosity said:
Thanks NF! Your post kind of made my brain fry a little though
Sent from my MB860 using XDA Premium App
Click to expand...
Click to collapse
You're welcome!
I updated my zoomquilt 2 boot animation to use this, see sig.
Cheers!
Can someone give me link for working to565 program which helps convert raw image files to rle ?
1. Need linux.
2. Script. Name Do.sh
Code:
#!/bin/sh
convert -depth 8 logo.png rgb:logo.raw
./to565 -rle < logo.raw > initlogo.rle
And source. Name to565.c
Code:
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define to565(r,g,b) \
((((r) >> 3) << 11) | (((g) >> 2) << 5) | ((b) >> 3))
#define from565_r(x) ((((x) >> 11) & 0x1f) * 255 / 31)
#define from565_g(x) ((((x) >> 5) & 0x3f) * 255 / 63)
#define from565_b(x) (((x) & 0x1f) * 255 / 31)
void to_565_raw(void)
{
unsigned char in[3];
unsigned short out;
while(read(0, in, 3) == 3) {
out = to565(in[0],in[1],in[2]);
write(1, &out, 2);
}
return;
}
void to_565_raw_dither(int width)
{
unsigned char in[3];
unsigned short out;
int i = 0;
int e;
int* error = malloc((width+2) * 3 * sizeof(int));
int* next_error = malloc((width+2) * 3 * sizeof(int));
memset(error, 0, (width+2) * 3 * sizeof(int));
memset(next_error, 0, (width+2) * 3 * sizeof(int));
error += 3; // array goes from [-3..((width+1)*3+2)]
next_error += 3;
while(read(0, in, 3) == 3) {
int r = in[0] + error[i*3+0];
int rb = (r < 0) ? 0 : ((r > 255) ? 255 : r);
int g = in[1] + error[i*3+1];
int gb = (g < 0) ? 0 : ((g > 255) ? 255 : g);
int b = in[2] + error[i*3+2];
int bb = (b < 0) ? 0 : ((b > 255) ? 255 : b);
out = to565(rb, gb, bb);
write(1, &out, 2);
#define apply_error(ch) { \
next_error[(i-1)*3+ch] += e * 3 / 16; \
next_error[(i)*3+ch] += e * 5 / 16; \
next_error[(i+1)*3+ch] += e * 1 / 16; \
error[(i+1)*3+ch] += e - ((e*1/16) + (e*3/16) + (e*5/16)); \
}
e = r - from565_r(out);
apply_error(0);
e = g - from565_g(out);
apply_error(1);
e = b - from565_b(out);
apply_error(2);
#undef apply_error
++i;
if (i == width) {
// error <- next_error; next_error <- 0
int* temp = error; error = next_error; next_error = temp;
memset(next_error, 0, (width+1) * 3 * sizeof(int));
i = 0;
}
}
free(error-3);
free(next_error-3);
return;
}
void to_565_rle(void)
{
unsigned char in[3];
unsigned short last, color, count;
unsigned total = 0;
count = 0;
while(read(0, in, 3) == 3) {
color = to565(in[0],in[1],in[2]);
if (count) {
if ((color == last) && (count != 65535)) {
count++;
continue;
} else {
write(1, &count, 2);
write(1, &last, 2);
total += count;
}
}
last = color;
count = 1;
}
if (count) {
write(1, &count, 2);
write(1, &last, 2);
total += count;
}
fprintf(stderr,"%d pixels\n",total);
}
int main(int argc, char **argv)
{
if ((argc == 2) && (!strcmp(argv[1],"-rle"))) {
to_565_rle();
} else {
if (argc > 2 && (!strcmp(argv[1], "-w"))) {
to_565_raw_dither(atoi(argv[2]));
} else {
to_565_raw();
}
}
return 0;
}
Then build.
Code:
gcc -o to565 to565.c
Can you put the to565 program in $PATH?
Will the to565 program work if you put it in the $PATH?
Hello
I have problem with my sony xperia z2 i lost cell radio because radio is off... I don't now why but it is...
I try reinstal system many times reset all values and it don't work.. to time when i flash android 4.4..2 (or 4.4.4) and flash this i edit this flashable zip and this working but when i update to lolipop(5.1..1) radio is still off... i realize binary( radiooptions) for kitkat is difrent than lolipop. At this website is source code but i can't find compile binary to lolipop.. I be very happy if someone can compile radiooptions for lolipop or know how to repair this "bug" because after many attempt i don't now how
PS: All application to turn on cell radio don't work...
PS2: Sorry for my English...
code in case of...
Code:
/* //device/system/toolbox/resetradio.c
**
** Copyright 2006, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <cutils/sockets.h>
#define SOCKET_NAME_RIL_DEBUG "rild-debug" /* from ril.cpp */
#define SOCKET_NAME_RIL2_DEBUG "rild2-debug"
enum options {
RADIO_RESET,
RADIO_OFF,
UNSOL_NETWORK_STATE_CHANGE,
QXDM_ENABLE,
QXDM_DISABLE,
RADIO_ON,
SETUP_PDP,
DEACTIVATE_PDP,
DIAL_CALL,
ANSWER_CALL,
END_CALL,
};
static void print_usage() {
perror("Usage: radiooptions [option] [extra_socket_args]\n\
0 - RADIO_RESET, \n\
1 - RADIO_OFF, \n\
2 - UNSOL_NETWORK_STATE_CHANGE, \n\
3 - QXDM_ENABLE, \n\
4 - QXDM_DISABLE, \n\
5 - RADIO_ON, \n\
6 apn- SETUP_PDP apn, \n\
7 - DEACTIVE_PDP, \n\
8 number - DIAL_CALL number, \n\
9 - ANSWER_CALL, \n\
10 - END_CALL \n\
The argument before the last one must be SIM slot \n\
0 - SIM1, \n\
1 - SIM2, \n\
2 - SIM3, \n\
3 - SIM4, \n\
The last argument must be modem-socket style \n\
0 - one modem for one debug-socket, \n\
1 - one modem for multiple debug socket \n");
}
static int error_check(int argc, char * argv[]) {
if (argc < 2) {
return -1;
}
const int option = atoi(argv[1]);
if (option < 0 || option > 10) {
return 0;
} else if ((option == DIAL_CALL || option == SETUP_PDP) && argc == 5) {
return 0;
} else if ((option != DIAL_CALL && option != SETUP_PDP) && argc == 4) {
return 0;
}
return -1;
}
static int get_number_args(char *argv[]) {
const int option = atoi(argv[1]);
if (option != DIAL_CALL && option != SETUP_PDP) {
return 3;
} else {
return 4;
}
}
int main(int argc, char *argv[])
{
int fd;
int num_socket_args = 0;
int i = 0;
int modem_socket_type = 0;
int sim_id = 0;
char socket_name[20];
if(error_check(argc, argv)) {
print_usage();
exit(-1);
}
num_socket_args = get_number_args(argv);
modem_socket_type = atoi(argv[(num_socket_args-1)]);
sim_id = atoi(argv[(num_socket_args-2)]);
memset(socket_name, 0, sizeof(char)*20);
if (sim_id == 0 || modem_socket_type == 1) {
strncpy(socket_name, SOCKET_NAME_RIL_DEBUG, 19);
} else if (sim_id == 1) {
strncpy(socket_name, SOCKET_NAME_RIL2_DEBUG, 19);
}
fd = socket_local_client(socket_name,
ANDROID_SOCKET_NAMESPACE_RESERVED,
SOCK_STREAM);
if (fd < 0) {
perror ("opening radio debug socket");
exit(-1);
}
/* It is not necessacry to pass the argument "modem-socket style" to rild */
num_socket_args--;
int ret = send(fd, (const void *)&num_socket_args, sizeof(int), 0);
if(ret != sizeof(int)) {
perror ("Socket write error when sending num args");
close(fd);
exit(-1);
}
for (i = 0; i < num_socket_args; i++) {
// Send length of the arg, followed by the arg.
int len = strlen(argv[1 + i]);
ret = send(fd, &len, sizeof(int), 0);
if (ret != sizeof(int)) {
perror("Socket write Error: when sending arg length");
close(fd);
exit(-1);
}
ret = send(fd, argv[1 + i], sizeof(char) * len, 0);
if (ret != len * sizeof(char)) {
perror ("Socket write Error: When sending arg");
close(fd);
exit(-1);
}
}
close(fd);
return 0;
}
Hi everyone,
Like the title said, I'm searching a way to root this tablet based on MediaTek.
Aida64 Information :
CPU : MT8783 (64 Bits ARMv8-A Cortex A53 octa-cores @ 1.3Ghz)
Platform : MT6753
Hardware : MT6735
Manufacturer : Lenovo
Brand : Medion
Display : Mali-T720 [email protected], 225 dpi
RAM : 2GB DDR3
ROM : 32GB MMC
After unlocking the bootloader :
I have tried some tools like iRoot, KingRoot, Kingo Root, Genius Root, and more that I can find with some search with google, but no one work.
I have tried to boot a TWRP/CWM Recovery image based on the same hardware or platform (fastboot boot myrecovery.img), the device reboot in normal mode, or I need to make these recovery for my hadware, but I think it need a rooted device...
I have tried to use MTK Droid Tools 2.5.3d, this software couldn't found the rom structure (this software doesn't found my IMEI too), and manualy with adb :
cat /proc/mtd
file is empty
cat /proc/emmc
file doesn't exist
cat /proc/partitions
Code:
major minor #blocks name
7 0 1254 loop0
254 0 975236 zram0
179 0 30535680 mmcblk0
179 1 3072 mmcblk0p1
179 2 5120 mmcblk0p2
179 3 10240 mmcblk0p3
179 4 10240 mmcblk0p4
179 5 512 mmcblk0p5
179 6 512 mmcblk0p6
179 7 16384 mmcblk0p7
179 8 16384 mmcblk0p8
179 9 8192 mmcblk0p9
179 10 10240 mmcblk0p10
179 11 512 mmcblk0p11
179 12 2048 mmcblk0p12
179 13 6144 mmcblk0p13
179 14 8192 mmcblk0p14
179 15 5120 mmcblk0p15
179 16 5120 mmcblk0p16
179 17 1024 mmcblk0p17
179 18 32768 mmcblk0p18
179 19 37888 mmcblk0p19
179 20 2621440 mmcblk0p20
179 21 409600 mmcblk0p21
179 22 27307520 mmcblk0p22
179 23 16384 mmcblk0p23
179 96 4096 mmcblk0rpmb
179 64 4096 mmcblk0boot1
179 32 4096 mmcblk0boot0
179 128 7565312 mmcblk1
179 129 7564288 mmcblk1p1
253 0 2600764 dm-0
253 1 27307520 dm-1
cat /etc/recovery.fstab
Code:
# mount point fstype device [device2]
/boot emmc boot
/cache ext4 /dev/block/mmcblk0p4
/data ext4 /dev/block/mmcblk0p5
/misc emmc misc
/recovery emmc recovery
/sdcard vfat /dev/block/mmcblk0p6
/system ext4 /dev/block/mmcblk0p3
ls -l /dev/block/platform/mtk-msdc.0/11230000.msdc0/by-name
Permission denied
After some search, it's possible that this device has the same hardware like the Lenovo Phab 2 Plus (correct me if i'm wrong).
If anyone has some idea to root this device, It's would be great ^^
Regards
PS : Sorry if my english is wrong
Would like to know too :good:
As do i.
Me too
Sent from my D6503 using Tapatalk
I have follow a lot of "how to", create a scatter file and try to read-back with SPFT from Windows 7, 10 and Ubuntu 16.04 LTS all I have is
=> BROM_ERROR S_DL_GET_DRAM_SETTING_FAIL (5054)
With Miracle Box v2.27A, it don't find the device....
I have trying to boot a custom recovery based on same hardware / cpu, the device reboot in normal mode ^^'
So, now, we have just to see with Medion, they can send the source-code and maybe stock-rom.
(I don't know why it's not available on their support website... :/ )
I've been in contact with [email protected] and they stated, that they only release a recovery kit (what we need for safely rooting the tablet) when they release an update for the tablet that gives users problems and they need to go back/recover the tablet themselves.
I think it would be helpful if people who would like to root their tablet contact Medion at [email protected] to let them see that there is a demand for those files. Hopefully they will release it then.
I got the same answer. After ota we will have recovery kit. But I am not sure we will have updates
Guys, can you see which app is using the battery? I only get the graph and battery usage data isn't available. I tried with hard reset and it didn't help
diyabolic said:
I got the same answer. After ota we will have recovery kit. But I am not sure we will have updates
Guys, can you see which app is using the battery? I only get the graph and battery usage data isn't available. I tried with hard reset and it didn't help
Click to expand...
Click to collapse
I didn't realise it before but I have the same bug. I also only have the graph.
Hey, maybe that's a reason for an OTA!
Sure it is I bought an app accubattery, at least I can see something
Sent from my D6503 using Tapatalk
Hey guys
I have found a way to root this device and worked for me, and work certainly for all other un-rooted device.
For some curious, I explain below what I have doing to dump recovery partition and boot.
For other, you can find the ZIP link at the end of this post.
With the DirtyCow exploit, it's very easy to dump our boot or recovery partition but need a little time without a custom recovery working...
In a first step, read this : h**ps://github.com/jcadduono/android_external_dirtycow#running
(a big thank's to jcadduono ! )
Ok, it's need an Android OS Environnement and it's not for our device, but it's not realy a problem.
A little modification to this file < recowvery-applypatch.c > to dump our recovery or boot partition, like this :
Code:
#include <unistd.h>
#include <stdio.h>
#include <stdint.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <fcntl.h>
#include <sys/stat.h>
#define APP_NAME "recowvery"
#define HOST_NAME "applypatch"
#ifdef DEBUG
#include <android/log.h>
#define LOGV(...) { __android_log_print(ANDROID_LOG_INFO, APP_NAME, __VA_ARGS__); printf(__VA_ARGS__); printf("\n"); }
#define LOGE(...) { __android_log_print(ANDROID_LOG_ERROR, APP_NAME, __VA_ARGS__); fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\n"); }
#else
#define LOGV(...) { printf(__VA_ARGS__); printf("\n"); }
#define LOGE(...) { fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\n"); }
#endif
#define SEP LOGV("------------")
#include "bootimg.h"
/* Time delay in microsecond for next loop (1000 = 1ms)
* 1ms is good for every PC
* (you can try less than 1ms to speed the process, but you can have an <unexpected EOF>)
*/
#define DELAY_T 1000
/* For Medion LifeTab X10302 (May work on same hardware MT6735/MT6753)
* You can define BLOCK_EMMC to other path if needed.
* Use < adb shell mount > for help.
*/
#define BLOCK_EMMC "/dev/block/platform/mtk-msdc.0/11230000.msdc0/by-name/boot"
//#define BLOCK_EMMC "/dev/block/platform/mtk-msdc.0/11230000.msdc0/by-name/recovery"
//#define BLOCK_EMMC "/dev/block/platform/any-folder-point-to-by-name-folder/by-name/boot"
void delay(long t)
{
long timens = t * 1000;
nanosleep((const struct timespec[]){{0, timens}}, NULL);
}
int main(int argc, char **argv)
{
int ret = 0;
int i = 0;
LOGV("Welcome to %s! (%s)", APP_NAME, HOST_NAME);
for (i = 30; i > 0; i--)
{
LOGV("The process start in %is", i);
sleep(1);
}
byte rb[32];
char *content = malloc(256);
FILE *filetest;
size_t nread;
filetest = fopen(BLOCK_EMMC, "r");
if (filetest) {
LOGV("*** DUMP START ***");
LOGV("* BLOCK_EMMC = %s", BLOCK_EMMC);
while ((nread = fread(rb, 1, sizeof rb, filetest)) > 0)
{
sprintf(content, "HEXDUMP = [");
for (i = 0; i < (int)nread; i++)
{
if (i == 0)
sprintf(content, "%s%.2x", content, rb[i]);
else
sprintf(content, "%s,%.2x", content, rb[i]);
}
sprintf(content, "%s];", content);
LOGV("%s", content);
/* sleep to prevent any unexpected EOF with with pipe stream
* ex : adb logcat | my-prg.exe
*/
delay(DELAY_T);
}
if (ferror(filetest)) {
ret = 1;
LOGE("*** DUMP ERROR ***");
LOGE("Error while reading the file...");
}
LOGV("*** DUMP END ***");
fclose(filetest);
}
else
{
LOGV("Can't read the file...");
ret = 1;
goto oops;
}
return 0;
oops:
LOGE("*** DUMP ERROR ***");
LOGE("Error %d: %s", ret, strerror(ret));
LOGE("Exiting...");
return ret;
}
(Edit : Added a delay in loop, there is some time an <unexpected EOF> during the process)
What it does ?
When launched by <recowvery-app_process>, it only open "/dev/block/platform/mtk-msdc.0/11230000.msdc0/by-name/boot" (in my exemple) in read-only and do like a HexDump, or something else.
It's human readable, and visible from Windows or any Linux distribution via the command adb logcat -s recowvery. But, we need something to do the revert :silly:
To solve this issue, I have made a to do this for me
C# code version : (not opti)
Code:
/*
* Created by SharpDevelop.
* User: vince
* Date: 16/01/2017
* Time: 17:34
*
* To change this template use Tools | Options | Coding | Edit Standard Headers.
*/
using System;
using System.IO;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Diagnostics;
namespace HexDumpReader
{
class Program
{
private static string workingDir = Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location) + Path.DirectorySeparatorChar;
private static string outfile = null;
private static List<string> datalist = new List<string>();
public static int Main(string[] args)
{
int val = 0;
int ncrash = 0;
if (args.Length == 0 || Console.In.Peek() == -1)
{
DisplayUsage();
return 1;
}
try
{
// Shorter regex is possible, but I prefer like that.
// Used to start the process
Regex rs = new Regex("\\*\\*\\* DUMP START \\*\\*\\*");
// Used to match all data block, and populate < datalist >
Regex rl = new Regex("^\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}.\\d{3}\\s{1,2}\\d{3,5}\\s{1,2}\\d{3,5} I recowvery: HEXDUMP = \\[([^\\]].*)\\];$");
// Used to break the infinite loop and start parsing all data
Regex rf = new Regex("\\*\\*\\* DUMP END \\*\\*\\*");
// Used to intercept error from < recowvery-applypatch >
Regex re = new Regex("\\*\\*\\* DUMP ERROR \\*\\*\\*");
outfile = args[0];
bool start = false;
bool reboot = false;
/* If we want a reboot while finish */
if (args.Length > 1)
reboot = (args[1] == "-r");
while (true)
{
string line = Console.In.ReadLine();
/*
* If an unexpected EOF from recowvery-applypatch...
* We can't receive a null string, close fsout, set start to false and break the loop after 3 crashs.
*/
if (line == null)
{
Console.WriteLine("* < null > received !");
Console.WriteLine("Try again...");
break;
}
/*
* *** DUMP START ***
* set start = true, and init fsout FileStream
*/
if (rs.IsMatch(line))
start = true;
/*
* Add all matched group from HEXDUMP line to datalist.
* Note :
* It's possible to have matched line before intercept DUMP START,
* If we convert now, it's a good idea to have a broken output file.
* Important :
* Never try to parse all data on the fly, you can have a mysterious "unexpected EOF" error.
*/
if (start && rl.IsMatch(line))
{
datalist.Add(rl.Replace(line, "$1"));
Console.CursorLeft = 0;
Console.Write("Block read : " + datalist.Count);
}
/*
* Display the other lines (for debuging, logging...)
*/
else if (!rl.IsMatch(line) && (!rf.IsMatch(line) && !start) && line.Length > 1)
{
Console.WriteLine(line);
}
/*
* *** DUMP END ***
* Flush and close fsout, inform the user, and break the loop.
*/
if (start && rf.IsMatch(line))
break;
/*
* *** DUMP ERROR ***
* An error intercepted from ADB, close fsout, set start to false.
* < applypatch > will restart every 3 min.
* We break the loop after 3 errors.
*/
if (re.IsMatch(line))
{
Console.WriteLine("* Error received from ADB *");
start = false;
if (ncrash == 3)
{
Console.WriteLine("* Too many tries, please check your < recowvery-applypatch.c > and try again.");
break;
}
Console.WriteLine("* Be patient, recowvery-applypatch will restart in a few minutes.");
ncrash++;
}
}
Console.WriteLine();
Console.WriteLine("Parsing blocks...");
/* recowvery-applypatch read by block of 32 bytes.
* so, we can calculate the final size.
*/
double finalSize = 32 * datalist.Count;
/* used to display the new progression */
int lastprogress = 0;
FileStream fsout = File.OpenWrite(outfile);
fsout.SetLength(0);
foreach(string s in datalist)
{
string[] data = s.Split(',');
for (int c = 0; c < data.Length; c++)
{
try
{
byte[] b = StringToByteArrayFastest(data[c]);
fsout.Write(b, 0, b.Length);
/* Calculate progression */
int progress = (int)(((double)fsout.Position / finalSize) * 100);
/* Display the progression if needed */
if (progress != lastprogress)
{
Console.CursorLeft = 0;
Console.Write("Processing... " + progress + "% ");
lastprogress = progress;
}
}
catch(Exception ex)
{
Console.WriteLine();
Console.WriteLine("** Exception **");
Console.WriteLine(" - When convert : " + data[c]);
Console.WriteLine(" - Message : " + ex.Message);
Console.WriteLine(" - StackTrace : " + ex.StackTrace);
}
}
}
fsout.Flush();
fsout.Close();
Console.WriteLine();
Console.WriteLine("Finish !");
if (reboot)
rebootDevice();
else
Console.WriteLine("You can reboot your device.");
}
catch(Exception e)
{
Console.WriteLine("*** Exception ***");
Console.WriteLine(" - Message : " + e.Message);
Console.WriteLine(" - Source : " + e.Source);
Console.WriteLine(" - StackTrace : " + e.StackTrace);
val = e.HResult;
}
return val;
}
public static void DisplayUsage()
{
Console.WriteLine("Usage :");
Console.WriteLine(" adb logcat -s recowvery | " + System.Diagnostics.Process.GetCurrentProcess().ProcessName + ".exe myImage-output.img [-r]");
Console.WriteLine();
Console.WriteLine(" -r : Reboot your device when finish.");
Console.WriteLine(" (Run \"adb reboot\" for you)");
}
public static void rebootDevice()
{
ProcessStartInfo psi;
Process p;
string strout = "";
string strerr = "";
psi = new ProcessStartInfo("adb.exe", "reboot");
psi.WorkingDirectory = workingDir;
psi.RedirectStandardError = true;
psi.RedirectStandardOutput = true;
psi.UseShellExecute = false;
Console.WriteLine("Rebooting your device...");
p = new Process();
p.StartInfo = psi;
p.Start();
if (!p.StandardError.EndOfStream)
strerr = p.StandardError.ReadToEnd();
if (!p.StandardOutput.EndOfStream)
strout = p.StandardOutput.ReadToEnd();
if (strout.Length > 0)
Console.WriteLine(strout);
if (strerr.Length > 0)
{
Console.WriteLine(strerr);
}
p.WaitForExit();
}
public static byte[] StringToByteArrayFastest(string hex) {
if (hex.Length % 2 == 1)
throw new Exception("The binary key cannot have an odd number of digits");
byte[] arr = new byte[hex.Length >> 1];
for (int i = 0; i < hex.Length >> 1; ++i)
{
arr[i] = (byte)((GetHexVal(hex[i << 1]) << 4) + (GetHexVal(hex[(i << 1) + 1])));
}
return arr;
}
public static int GetHexVal(char hex) {
int val = (int)hex;
//For uppercase A-F letters:
//return val - (val < 58 ? 48 : 55);
//For lowercase a-f letters:
return val - (val < 58 ? 48 : 87);
//Or the two combined, but a bit slower:
//return val - (val < 58 ? 48 : (val < 97 ? 55 : 87));
}
}
}
To compile the C# code, you need :
An IDE like SharpDevelop, MonoDevelop, or VisualStudio
Create a <New Project> and select <Console Application>
copy the code below, and replace all to your main.cs or program.cs.
Run it
C++ code version : (Working good on Ubuntu 16.04, Windows too but not tested)
Code:
#include <iostream>
#include <regex>
#include <stdio.h>
typedef unsigned char byte;
using namespace std;
void DisplayUsage()
{
cout << string("Usage :") << endl;
cout << string(" adb logcat -s recowvery | ") << string("HexDumpReader") << string(".exe myImage-output.img [-r]") << endl;
cout << endl;
cout << string(" -r : Reboot your device when finish.") << endl;
cout << string(" (Run \"adb reboot\" for you)") << endl;
}
void split(const string &s, char delim, vector<string> &elems) {
stringstream ss;
ss.str(s);
string item;
while (getline(ss, item, delim)) {
elems.push_back(item);
}
}
vector<string> split(const string &s, char delim) {
vector<string> elems;
split(s, delim, elems);
return elems;
}
void string_to_bytearray(std::string str, unsigned char* &array, int& size)
{
int length = str.length();
// make sure the input string has an even digit numbers
if(length%2 == 1)
{
str = "0" + str;
length++;
}
// allocate memory for the output array
array = new unsigned char[length/2];
size = length/2;
std::stringstream sstr(str);
for(int i=0; i < size; i++)
{
char ch1, ch2;
sstr >> ch1 >> ch2;
int dig1, dig2;
if(isdigit(ch1)) dig1 = ch1 - '0';
else if(ch1>='A' && ch1<='F') dig1 = ch1 - 'A' + 10;
else if(ch1>='a' && ch1<='f') dig1 = ch1 - 'a' + 10;
if(isdigit(ch2)) dig2 = ch2 - '0';
else if(ch2>='A' && ch2<='F') dig2 = ch2 - 'A' + 10;
else if(ch2>='a' && ch2<='f') dig2 = ch2 - 'a' + 10;
array[i] = dig1*16 + dig2;
}
}
void rebootDevice()
{
system("adb reboot");
}
int main(int argc, char** argv)
{
/* Display help if no argument */
if (argc == 1)
{
DisplayUsage();
return 1;
}
cout << string("*** HexDumpReader ***") << endl;
int val = 0;
vector<string> datalist;
string outfile = string(argv[1]);
bool reboot = false;
int ncrash = 0;
/* Output image file */
cout << string("* Output file : ") << outfile << endl;
/* If we want a reboot while finish */
if (argc > 2)
{
reboot = (string(argv[2]) == "-r");
}
cout << string("* Reboot device : ") << reboot << endl;
try
{
// Shorter regex is possible, but I prefer like that.
// Used to start the process
regex rs("^.+I recowvery: (\\*\\*\\* DUMP START \\*\\*\\*)\\s+");
// Used to match all data block, and populate < datalist >
regex rl("^.+I recowvery: HEXDUMP = \\[([^\\]]+)\\];\\s+");
// Used to break the infinite loop and start parsing all data
regex rf("^.+I recowvery: (\\*\\*\\* DUMP END \\*\\*\\*)\\s+");
// Used to intercept error from < recowvery-applypatch >
regex re("^.+I recowvery: (\\*\\*\\* DUMP ERROR \\*\\*\\*)\\s+");
/* write or not to output file */
bool start = false;
FILE *fsout;
fsout = fopen(outfile.c_str(), "wb");
int nBlock = 0;
long currentSize = 0;
while (true)
{
string line;
getline(cin, line);
/*
* If an unexpected EOF from recowvery-applypatch or if no <pipe>...
* We can't receive a null string, so break the loop, close fsout, and exit the program.
*/
if (line.empty())
{
cout << string("* < null > received !") << endl;
cout << string("Try again...") << endl;
break;
}
/*
* *** DUMP START ***
* set start = true to write parsed data to fsout
*/
if (regex_match(line, rs))
{
start = true;
}
/*
* Parse all string received if match
* Note :
* It's possible to have matched string before intercept DUMP START,
* If we convert now, it's a good idea to have a broken output file.
*/
if (start && regex_match(line, rl))
{
string s = regex_replace(line, rl, "$1");
vector<string> data = split(s, ',');
for (int c = 0; c < (int)data.size(); c++)
{
try
{
byte *b = NULL;
int sb;
string_to_bytearray(data[c], b, sb);
fwrite(b, 1, sb, fsout);
}
catch (const std::exception &ex)
{
std::cout << std::endl;
std::cout << std::string("** Exception **") << std::endl;
std::cout << std::string(" - When convert : ") << data[c] << std::endl;
std::cout << std::string(" - Message : ") << ex.what() << std::endl;
}
}
nBlock++;
currentSize = nBlock * 32;
std::cout << "\r";
std::cout << std::string("Block read : ") << nBlock << string(" (Size : ") << currentSize << string(")");
}
/*
* Display the other lines (for debuging, logging...)
*/
else if (!regex_match(line, rl) && (!regex_match(line, rf) && !start) && line.length() > 1)
{
std::cout << line << std::endl;
}
/*
* *** DUMP END ***
* Flush and close fsout, inform the user, and break the loop.
*/
if (start && regex_match(line, rf))
{
break;
}
/*
* *** DUMP ERROR ***
* An error intercepted from ADB, close fsout, set start to false.
* < applypatch > will restart every 3 min.
* We break the loop after 3 errors.
*/
if (regex_match(line, re))
{
cout << std::string("* Error received from ADB *") << std::endl;
start = false;
if (ncrash == 3)
{
cout << std::string("* Too many tries, please check your < recowvery-applypatch.c > and try again.") << std::endl;
break;
}
cout << std::string("* Be patient, recowvery-applypatch will restart in a few minutes.") << std::endl;
ncrash++;
}
}
cout << endl;
fclose(fsout);
cout << std::endl;
cout << std::string("Finish !") << std::endl;
if (reboot)
{
rebootDevice();
}
else
{
std::cout << std::string("You can reboot your device.") << std::endl;
}
}
catch (const std::exception &e)
{
std::cout << std::string("*** Exception ***") << std::endl;
std::cout << std::string(" - Message : ") << e.what() << std::endl;
}
return val;
}
To build it, you need these CFLAGS : -m32 -std=C++11 -Wall (maybe -g for debug)
Ex :
g++ -Wall -fexceptions -g -Wall -std=c++11 -m32 -g -c main.cpp -o main.o
g++ -o HexDumpReader main.o -m32
Now, how It work ?
How can I dump my boot or recovery partition and make my own TWRP ? :crying:
It's like jcadduono explain here : h**ps://github.com/jcadduono/android_external_dirtycow
Follow only this steps :
Code:
adb push dirtycow /data/local/tmp
adb push recowvery-applypatch /data/local/tmp
adb push recowvery-app_process64 /data/local/tmp
adb push recowvery-run-as /data/local/tmp
adb shell
$ cd /data/local/tmp
$ chmod 0777 *
$ ./dirtycow /system/bin/applypatch recowvery-applypatch
"<wait for completion>"
$ ./dirtycow /system/bin/app_process64 recowvery-app_process64
"<wait for completion, your phone will look like it's crashing>"
$ exit
(It's change here =>)
adb logcat -s recowvery | HexDumpReader %USERPROFILE%\Documents\my-image-output.img -r
Wait a moment, you will see that it's finish, and you may see <my-image-output.img> in <%USERPROFILE%\Documents> folder.
You can try to extract your image from MKTool or any Kitchen tools, it's work, and finally make your TWRP, boot from it, backup your roms (if you have never doing this) and finally root your device.
I know that some of you can't do all these steps, or need simply the final image, you can download it from this url :
ZIP File : h**ps://goo.gl/IT7dpl (Contains original boot, recovery, TWRP & a readme)
(Bug found : battery stuck at 50%)
Thanks dude for your effort , you're the man ?
Is there a chance to fix the battery bug?
Sent from my D6503 using Tapatalk
diyabolic said:
Thanks dude for your effort , you're the man
Is there a chance to fix the battery bug?
Sent from my D6503 using Tapatalk
Click to expand...
Click to collapse
Hmmm... Without source code of this device, it's difficult to say if it's a TWRP issue or Kernel issue, or something else (It's possible that I miss something).
About the source code, a mail has been sent to Medion a days ago, but no answer...
In case if I've miss something, if someone can help, or give me a way to solve this ^^
Vince_02100 said:
Hmmm... Without source code of this device, it's difficult to say if it's a TWRP issue or Kernel issue, or something else (It's possible that I miss something).
About the source code, a mail has been sent to Medion a days ago, but no answer...
In case if I've miss something, if someone can help, or give me a way to solve this ^^
Click to expand...
Click to collapse
It's it charging till 50% or only indicating that is charged till 50 but actually is fully charged?
Sent from my D6503 using Tapatalk
It's only indicating at 50%. When you boot android, the real value about the battery is displayed
Ok. That's not a problem. Will root
Sent from my D6503 using Tapatalk
Working great!
For a permanent recovery I just renamed /system/recovery-from-boot.p
I try to root MD60348. I UNLOCK BOOTLOADER. Then stop. I cant do nothing. Device only back to factory setings...
kamilodiabolo said:
I try to root MD60348. I UNLOCK BOOTLOADER. Then stop. I cant do nothing. Device only back to factory setings...
Click to expand...
Click to collapse
Hi kamilodiabolo, after booting into TWRP you have to flash the UPDATE-SuperSU-v2.79.zip. After flashing the zip your tablet should boot without any problem. Without flashing the SuperSU update my tablet also stuck in bootloader.
Gadgetto said:
Hi kamilodiabolo, after booting into TWRP you have to flash the UPDATE-SuperSU-v2.79.zip. After flashing the zip your tablet should boot without any problem. Without flashing the SuperSU update my tablet also stuck in bootloader.
Click to expand...
Click to collapse
O know but i i dont know how to get my oryginal boot.img and stok recovery...
Adb pull
Guys, do you have problem with stuttering videos (yt, vimeo)? Before it was working perfectly, now every video stutters. I would rather not hard reset if I don't have to
Sent from my D6503 using Tapatalk