2021年10月

转自: https://blog.csdn.net/daoshuti/article/details/72972350

AndroidTP驱动之(二)设备树解析

0. 前情提要

上文中我们已经初步搭好了TP驱动的框架。当然我们还缺了重要的部分input子系统,这个不急,我们下一篇文章再叙。 本文我们来完成TP driver中对设备树的解析。

1. probe函数

我们知道驱动匹配有四种方式:设备树匹配、设备名称匹配、设备ID匹配、ACPI方式匹配。 这里我们只用设备树匹配,这也是Android驱动中最常用的匹配方式。 我们知道当驱动和设备树匹配的时候,probe函数就会被执行。 这时一般首先进行设备树的解析,从设备树中获取设备的硬件信息。

    struct mytp_platform_data *pdata;
    int err;

    if (client->dev.of_node)
    {
        pdata = devm_kzalloc(&client->dev,
                sizeof(struct mytp_platform_data),
                GFP_KERNEL);
        if (!pdata)
        {
            PRINT_INFO("[MEMORY]Failed to allocate memory");
            return -ENOMEM;
        }
        err = mytp_parse_dt(&client->dev, pdata);
        if (err)
        {
            PRINT_INFO("[DTS]DT parsing failed");
        }
    }
    else
    {
        return -1;
    }

    if (!pdata)
    {
        PRINT_INFO("Invalid pdata");
        return -EINVAL;
    }

从代码中我们很清晰的看到,我们先是定义了一个结构体指针pdata。这是用来存放平台数据。 接着,我们为这结构体申请了内存,并做异常处理。 之后调用mytp_parse_dt函数对设备树进行解析。也做了相应的异常处理。

1.1 mytp_platform_data结构体

struct mytp_platform_data
{
    u32 irq_gpio;
    u32 irq_gpio_flags;
    u32 reset_gpio;
    u32 reset_gpio_flags;
    bool have_key;
    u32 key_number;
    u32 keys[4];
    u32 key_y_coord;
    u32 key_x_coords[4];
    u32 x_max;
    u32 y_max;
    u32 x_min;
    u32 y_min;
    u32 max_touch_number;
};

头四个结构体成员变量,分别是两个gpio所使用的,一个是irq中断,一个是TP的reset复位引脚。 之后的bool变量,是TP按键的标志,表示是否支持TP按键。 紧接着的四个key_打头的变量是提供给TP按键处理函数用的。 x_max、x_min、y_max、y_min限定了tp的触摸范围。 最后的一个变量限定了tp支持的最大多点触控数目。

1.2 mytp_parse_dt函数

这个函数就是用来解析设备树的。 其中的mytp_get_dt_coords函数是自己实现的,用来解析设备树中的数组的。具体实现见1.3小节。

static int mytp_parse_dt(struct device *dev, struct mytp_platform_data *pdata)
{
    int rc;
    struct device_node *np = dev->of_node;
    u32 temp_val;

    rc = mytp_get_dt_coords(dev, "focaltech,display-coords", pdata);
    if (rc)
        PRINT_INFO("Unable to get display-coords");

    /* key */
    pdata->have_key = of_property_read_bool(np, "focaltech,have-key");
    if (pdata->have_key)
    {
        rc = of_property_read_u32(np, "focaltech,key-number", &pdata->key_number);
        if (rc)
        {
            PRINT_INFO("Key number undefined!");
        }
        rc = of_property_read_u32_array(np, "focaltech,keys",
                pdata->keys, pdata->key_number);
        if (rc)
        {
            PRINT_INFO("Keys undefined!");
        }
        rc = of_property_read_u32(np, "focaltech,key-y-coord", &pdata->key_y_coord);
        if (rc)
        {
            PRINT_INFO("Key Y Coord undefined!");
        }
        rc = of_property_read_u32_array(np, "focaltech,key-x-coords",
                pdata->key_x_coords, pdata->key_number);
        if (rc)
        {
            PRINT_INFO("Key X Coords undefined!");
        }
        PRINT_INFO("%d: (%d, %d, %d), [%d, %d, %d][%d]",
                pdata->key_number, pdata->keys[0], pdata->keys[1], pdata->keys[2],
                pdata->key_x_coords[0], pdata->key_x_coords[1], pdata->key_x_coords[2],
                pdata->key_y_coord);
    }

    /* reset, irq gpio info */
    pdata->reset_gpio = of_get_named_gpio_flags(np, "focaltech,reset-gpio", 0, &pdata->reset_gpio_flags);
    if (pdata->reset_gpio < 0)
    {
        PRINT_INFO("Unable to get reset_gpio");
    }

    pdata->irq_gpio = of_get_named_gpio_flags(np, "focaltech,irq-gpio", 0, &pdata->irq_gpio_flags);
    if (pdata->irq_gpio < 0)
    {
        PRINT_INFO("Unable to get irq_gpio");
    }

    rc = of_property_read_u32(np, "focaltech,max-touch-number", &temp_val);
    if (!rc)
    {
        pdata->max_touch_number = temp_val;
        PRINT_INFO("max_touch_number=%d", pdata->max_touch_number);
    }
    else
    {
        PRINT_INFO("Unable to get max-touch-number");
        pdata->max_touch_number = MYTP_MAX_POINTS;
    }

    return 0;
}

1.3 mytp_get_dt_coords函数

static int mytp_get_dt_coords(struct device *dev, char *name,
        struct mytp_platform_data *pdata)
{
    u32 coords[MYTP_COORDS_ARR_SIZE];
    struct property *prop;
    struct device_node *np = dev->of_node;
    int coords_size, rc;

    prop = of_find_property(np, name, NULL);
    if (!prop)
        return -EINVAL;
    if (!prop->value)
        return -ENODATA;

    coords_size = prop->length / sizeof(u32);
    if (coords_size != MYTP_COORDS_ARR_SIZE)
    {
        PRINT_INFO("invalid %s", name);
        return -EINVAL;
    }

    rc = of_property_read_u32_array(np, name, coords, coords_size);
    if (rc && (rc != -EINVAL))
    {
        PRINT_INFO("Unable to read %s", name);
        return rc;
    }

    if (!strcmp(name, "focaltech,display-coords"))
    {
        pdata->x_min = coords[0];
        pdata->y_min = coords[1];
        pdata->x_max = coords[2];
        pdata->y_max = coords[3];
    }
    else
    {
        PRINT_INFO("unsupported property %s", name);
        return -EINVAL;
    }

    return 0;
}

End

至此我们完成了对设备树的解析。

转自: https://blog.csdn.net/daoshuti/article/details/72972112

AndroidTP驱动之(一)I2C

0. 前言

Android TP 驱动系列主要用来记录自己关于TP的心得体会。 为了完整的梳理TP driver相关的知识,也为了跟好回顾Linux driver的编写流程。 我将参照已有的驱动代码(focaltech的驱动代码)从零开始,一步一步写出一个TP驱动。 驱动模块的名字就叫做mytp。

1. 模块三要素

1.0 header & define

#include <linux/kernel.h>
#include <linux/module.h>

#define PRINT_INFO(fmt, args...) printk(KERN_ERR "[MYTP][%s]"fmt"\n", __func__, ##args)

1.1 module_init

static __init int mytp_init(void)
{
    PRINT_INFO("mytp init start!");
    PRINT_INFO("mytp init end!");
    return 0;
}
module_init(mytp_init);

1.2 module_exit

static __exit void mytp_exit(void)
{
    PRINT_INFO("mytp exit start!");
    PRINT_INFO("mytp exit end!");
}
module_exit(mytp_exit);

1.3 module info

MODULE_AUTHOR("wanghan");
MODULE_DESCRIPTION("TP Driver (ic:ft5435)");
MODULE_LICENSE("GPL");

2. I2C子系统

我们知道TP的IC基本都是使用I2C和CPU通信。所以,我们先通过i2c子系统创建一个字符设备驱动。 注意这里用到了头文件

#include <linux/i2c.h>

2.0 定义相关的i2c结构体变量

#define MYTP_DRIVER_NAME    "mytp_ft5435"

static const struct i2c_device_id mytp_id[] =
{
    {MYTP_DRIVER_NAME, 0},
    {},
};

static const struct of_device_id mytp_match_table[] =
{
    { .compatible = "focaltech,fts", },
    { },
};

static struct i2c_driver mytp_driver =
{
    .probe = mytp_probe,
    .remove = mytp_remove,
    .driver = {
        .name = MYTP_DRIVER_NAME,
        .owner = THIS_MODULE,
        .of_match_table = mytp_match_table,
    },
    .id_table = mytp_id,
};

2.1 实例化probe和remove函数

static int mytp_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
    PRINT_INFO("mytp prebo start!");

    PRINT_INFO("mytp prebo end!");
    return 0;
}

static int mytp_remove(struct i2c_client *client)
{
    PRINT_INFO("mytp remove start!");

    PRINT_INFO("mytp remove end!");
    return 0;
}

2.2 创建i2c设备

在mytp_init函数中加入

int ret;
ret = i2c_add_driver(&mytp_driver);
if ( ret != 0 )
{
    PRINT_INFO("TP driver init failed!");
}

2.3 注销i2c设备

i2c_del_driver(&mytp_driver);

End

至此,我们的驱动框架已经搭建好了。

转自: https://blog.csdn.net/xiaocaohuyang/article/details/114120766?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.no_search_link

文章目录

一、TP的硬件接口
二、代码路径
三、TP代码分析
    1、硬件参数设置
    2、TP设备驱动
    3、TP模组驱动

一、TP的硬件接口

引脚 名称及作用
VDD TP供电
RESET 复位引脚
EINT 中断引脚
SCL、SDA I2C接口

​ TP的工作方式比较简单: +上电后通过RESET脚控制TP芯片复位;

  • 通过I2C接口给TP设置参数或读取TP数据;
  • TP有触摸操作时通过EINT脚通知主控;

二、代码路径

描述 路径 文件
系统设置 device\top\top6737t_36_a_m0 kernel-3.18\arch\arm\configs ProjectConfig.mk user版本和userdebug版本对应:top6737t_36_a_m0_defconfig debug版本对应:top6737t_36_a_m0_debug_defconfig
接口设置 kernel-3.18\arch\arm\boot\dts top6737t_36_a_m0.dts cust_i2c.dtsi
Kernel代码 kernel-3.18\drivers\input\touchscreen\mediatek mtk_tpd.c

- 阅读剩余部分 -

转自: https://blog.csdn.net/MrDongShiYi/article/details/100709633?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.no_search_link

TP 相关引脚DTS中的定义 我们这个项目TP复位引脚是GPIO158,中断引脚是GPIO1,由下图原理图知道我们的TP挂载在I2c0上,3.3v的供电电压是有PMIC 2.8V供电电压通过i2c电平转换过来的,所以供电电压需要配置pmic 2.8v

- 阅读剩余部分 -

转自: https://blog.csdn.net/memory01/article/details/91895740

做Android bsp开发经常会遇到改了内核config需要快速验证的情况,如果用最简单的编译bootimage方式会很费时

肯定存在更简单的方法 以arm64位的芯片bsp包为例

cd KERNEL_PATH
$ export ARCH=arm64
/*如果你是目标defconfig是 "arch/arm64/msm8150_defconfig" */
$ make msm8150_defconfig
成功之后,这样就会出现 #configutation written to .config 提示

接下来就可以检查KERNEL_PATH 下的 .config 文件是否符合你的改动

当然如果要通过menuconfig方式来配置内核也行,执行上述命令之后再make menuconfig 即可

转自: http://bbs.100ask.net/article/35#:~:text=%E7%94%B1%E4%BA%8Elinux%E7%9A%84IIC%E5%9C%B0%E5%9D%80%E5%9C%A8%E4%BD%8E7%E4%BD%8D%EF%BC%8C%E5%9B%A0%E6%AD%A4gt911%E7%9A%84%E5%AE%9E%E9%99%85%E5%9C%B0%E5%9D%80%E6%98%AF0xBA%3E1%3D0x5d%2C%E8%BF%99%E5%B0%B1%E6%98%AF%E4%B8%BA%E4%BB%80%E4%B9%88%E6%88%91%E4%BB%AC%E5%9C%A8%E8%AE%BE%E5%A4%87%E6%A0%91%E4%B8%AD%E5%B0%86GT911%E7%9A%84%E5%9C%B0%E5%9D%80%E9%85%8D%E7%BD%AE%E4%B8%BA0x5d,gt911%E9%9C%80%E8%A6%81%E9%85%8D%E7%BD%AE%E7%9A%84%E5%AF%84%E5%AD%98%E5%99%A8%20gt911%E9%9C%80%E8%A6%81%E9%85%8D%E7%BD%AE186%E4%B8%AA%E5%AF%84%E5%AD%98%E5%99%A8%EF%BC%8C%E5%88%86%E5%88%AB%E4%B8%BA0x8047-0x8100

源码在最下面

问题一:资源获取Gt911数据手册

在韦老师给的资料里,路径为\06_Datasheet\Extend_modules\7寸LCD模块\电容触控芯片GT911 Datasheet_121120(海威思.pdf

问题二:需要准备哪些知识

  1. 能够修改设备树
  2. 能够编写字符设备驱动
  3. 能够在linux下编写中断程序
  4. 能够在linux下编写IIC收发程序
  5. 了解input子系统
  6. 移植tslib(用于校准,测试触摸屏)

- 阅读剩余部分 -

原因是 jcenter 在 2021.05 停止服务了。

修改顶层的 build.gradle

在每个 jcenter() 上面增加一行 mavenCentral()

修改 app 目录下的 build.gradle

implementation 'com.gu.android:toolargetool:0.2.1@aar' 改为 implementation 'com.gu.android:toolargetool:0.3.0@aar'

参考:

http://5.9.10.113/67450126/android-project-build-failing-after-bintray-sunset https://www.5axxw.com/questions/content/hm6zjg

这个一般是旧工程在新 android studio 中打开

"No toolchains found in the NDK toolchains folder for ABI" 需要安装ndk

file -> settings -> android sdk -> sdk tools -> ndk(side by side) 勾选进行安装。 file -> project structure -> sdk location -> android ndk location 里面选择 ndk

"NDK does not contain any platforms” 这个需要安装低版本 ndk

file -> settings -> android sdk -> sdk tools -> ndk(side by side) 勾选 右下角的 show package details,选择低版本,比如说 20.0.5594570 ,安装低版本。

file -> project structure -> sdk location -> android ndk location 选择低版本的 ndk.

参考:

https://blog.csdn.net/qq_24118527/article/details/82867864
https://blog.csdn.net/hiphopxiao/article/details/112220228#:~:text=%E5%9C%A8%20Android%20Studio%E4%B8%AD%E9%85%8D%E7%BD%AE%20NDK%20%E6%97%B6%EF%BC%8C%E5%8F%AF%E8%83%BD%20%E5%87%BA%E7%8E%B0NDK%20does%20not,does%20not%20contain%20any%20platforms%20.%20%E6%89%BE%E4%BA%86%E5%BE%88%E5%A4%9A%E8%B5%84%E6%96%99%EF%BC%8C%E4%B8%8D%E7%9F%A5%E9%81%93%E4%BB%80%E4%B9%88%E5%8E%9F%E5%9B%A0%E3%80%82%20%E5%90%8E%E9%9D%A2%E6%98%AF%E9%80%9A%E8%BF%87%E4%B8%8B%E8%BD%BD%E6%97%A9%E5%89%8D%E7%9A%84%E7%89%88%E6%9C%AC%E8%A7%A3%E5%86%B3%E4%BA%86%E8%BF%99%E4%B8%AA%E9%97%AE%E9%A2%98%EF%BC%8C%E8%AE%B0%E5%BD%95%E4%B8%8B%3A