0%

没有太多时间去查看详细源代码,所以仍然有很多不清晰或者理解不到位的地方,后续将 Linux 相关知识学习得更深入的时候再来更新一次。

进程与线程

在 Linux 中,进程和线程几乎没有什么区别,主要的区别就是线程共享同样的虚拟内存地址空间。对于 kernel 来说,进程和线程都是一个可运行的 task 。

线程创建函数 pthread_create() 会调用 clone(), 而进程创建函数 fork() 最终也是调用 clone()。我们查看clone函数的介绍时,可以看到 clone() 的参数 flags 用来指明子‘进程’和父‘进程’共享什么,所以可以说进程就是不共享任何东西的一个典型线程(一个不成熟的观点,不一定正确)。
process_thread_to_task

摘录线程库发展史:Linux threading libraries evolution: Linux Threads, NGPT, NPTL. The library is part of gilbc, programmer interface is POSIX pthreads.

线程模型

Read more »

ARTS 简单介绍

Algorithm:
主要是为了编程训练和学习。每周至少做一个 leetcode 的算法题(先从Easy开始,然后再Medium,最后才Hard)。进行编程训练,如果不训练你看再多的算法书,你依然不会做算法题,看完书后,你需要训练。

Review:
主要是为了学习英文,如果你的英文不行,你基本上无缘技术高手。所以,需要你阅读并点评至少一篇英文技术文章,我个人最喜欢去的地方是 Medium(需要梯子)以及各个公司的技术 blog,如 Netflix 的。

Tip:
主要是为了总结和归纳你在是常工作中所遇到的知识点。学习至少一个技术技巧。你在工作中遇到的问题,踩过的坑,学习的点滴知识。

Share:
主要是为了建立你的影响力,能够输出价值观。分享一篇有观点和思考的技术文章。

Read more »

Term

  • DFP - Downstream Facing Port
    下行端口,可以理解为 Host 的 Type-c 端口或者作为 Host 的 hub ,DFP 提供 VBUS,可以提供数据。在协议规范中 DFP 特指数据的下行传输,笼统意义上指的是数据下行和对外提供电源的设备。典型的 DFP 设备是电源适配器。

  • UFP - Upstream Facing port
    上行端口,可以理解为 Device 上的 Type-c 端口或者连接到 Host/DFP of a hub ,UFP 从 VBUS 中取电,并可提供数据。典型设备是 U 盘,移动硬盘。

  • DRP - DUal Role Port (DFP + UFP)
    双角色端口,DRP 既可以做 DFP(Host),也可以做 UFP(Device),也可以在 DFP 与 UFP 间动态切换。典型的DRP设备是笔记本电脑。

引用摘录:A DRP port is a port that can operate as either a sink or source.

source - takes the data role of a DFP.
sink - take the data role of a UFP.

A current sink is a port or circuit point that accepts negative current, e.g. current into the circuit which it drains to ground.
A current source is a port or circuit point that provides positive current. A good example of a current source is a DC power supply

Description

逻辑:USB 默认为 UFP,不能使用 OTG ;若要使用需要通过 node 将其设为 DRP , 但是在拔出后需要将其设回 UFP。

问题: 当拔掉 OTG 之后,USB 仍然为 DRP ,导致不用设置 node 即可连接 OTG。

Solution

Read more »

从 Android P 开始,Google 开始推荐厂家再定制一个 health 。前不久遇到一个定制 health 中的信息未成功反应到 Framework 的问题,在分析解决问题的过程中,学习到了一点新知识,所以就在这篇文章里根据解决问题的流程做一个小小的记录。

问题:定制 health service 中的一些 health 信息未成功反应到 Framework。

已知:定制 health 和 Google healthd 进程都运行于设备中,定制 health 主要重写 healthd_board_battery_update 函数,会通过库文件引用原生代码(system/core/healthd/)中的实现。

初步方案

简单介绍

服务创建时都编写了一个 x.rc 文件,用来描述 health service 的一些特点,其中就包括其启动时机。如下:

1
2
3
4
5
6
7
8
# system/core/healthd/android.hardware.health@2.0-service.rc
/* sevice 类型的 setction 表示一个可执行程序(进程) */
service health-hal-2-0 /vendor/bin/hw/android.hardware.health@2.0-service or healthd.rc
class hal
user system
group system
file /dev/kmsg w

启动顺序: hal-> core-> main -> later

Read more »

前不久在高通 SDM450 平台接触了 voter 机制(投票机制)。最近终于得空,结合一个问题简单研究了一下。现将研究流程简单记录一下,由于时间有限,所以是实用为目的,没有做详细的分析,不过结合着这篇分析和源码一起参考,应该能快速地应用 voter 做一些事情。

voter

第一步是找到 voter 的实现代码,然后分析 voter 的机制。voter 的实现代码主要是为各种 voter 提供接口,我提炼了两个最关键的接口,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# kernel/msm-4.9/drivers/power/supply/qcom/pmic-voter.c
/*
** vote 函数主要用来给 votable 添加投票选项
** votable: 投票的对象
** client_str: 投票者
** enabled: 投票者的内容(val)是否参与投票
** val: 投票内容
**/
int vote(struct votable *votable, const char *client_str, bool enabled, int val)
{
...
switch (votable->type) { // type 的值来自于 create_votable()
case VOTE_MIN: // 取投票对象所有内容的最小值
vote_min(votable, client_id, &effective_result, &effective_id);
break;
case VOTE_MAX:
vote_max(votable, client_id, &effective_result, &effective_id);
break;
case VOTE_SET_ANY:
vote_set_any(votable, client_id,
&effective_result, &effective_id);
break;
...
}

/* 投票相关参数,可以在此文件中搜索此结构体的成员找到其值从哪儿来*/
struct votable {
int type;
...
int (*callback)(struct votable *votable,
}
--->

struct votable *create_votable(const char *name,
int votable_type,
int (*callback)(struct votable *votable,..)
{
// 创建 votable, 引入 votable type 和 callback 函数
...
/* 创建 debugfs*/
debug_root = debugfs_create_dir("pmic-votable", NULL);
...
}
eg: 创建流入电池电流的投票对象
chip->fcc_votable = create_votable("FCC", VOTE_MIN,
pl_fcc_vote_callback,
chip);
Read more »

Add node

此方法只为一个示例,有些平台不是使用此文件,如 SDM450(MSM8953)使用的 dwc3-qcom.c 。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# kernel/msm-4.9/drivers/usb/phy/phy-msm-usb.c
@@ -51,6 +51,11 @@

#include <linux/msm-bus.h>

+#undef dev_dbg
+#define dev_dbg dev_info
+#undef pr_debug
+#define pr_debug pr_info
+
/**
* Requested USB votes for BUS bandwidth
*
@@ -3601,6 +3606,53 @@ static int msm_otg_setup_devices(struct
return retval;
}

+
+#define DUMP_ENTRIES 152
+
+static ssize_t usbphy_regs_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct msm_otg *motg = the_msm_otg;
+ //struct msm_otg_platform_data *pdata = motg->pdata;
+ struct usb_phy *phy = &motg->phy;
+ u32 *dump;
+ unsigned int i, n = 0;
+ //dbg_trace("[%s] %pK\n", __func__, buf);
+ if (attr == NULL || buf == NULL) {
+ dev_err(dev, "[%s] EINVAL\n", __func__);
+ return 0;
+ }
+ if (atomic_read(&motg->in_lpm)){
+ dev_err(dev, "[%s] usb in lpm\n", __func__);
+ return 0;
+ }
+ dump = kmalloc(sizeof(u8) * DUMP_ENTRIES, GFP_KERNEL);
+ if (!dump)
+ return 0;
+
+ for(i = 0; i < DUMP_ENTRIES -1; i++)
+ dump[i] = ulpi_read(phy, i);
+
+ for (i = 0; i < DUMP_ENTRIES -1; i++) {
+ n += scnprintf(buf + n, PAGE_SIZE - n,
+ "reg[0x%04X] = 0x%04X\n",
+ i, dump[i]);
+ }
+ kfree(dump);
+
+ return n;
+}
+
+static ssize_t usbphy_regs_store(struct device *dev,
+ struct device_attribute *attr, const char
+ *buf, size_t size)
+{
+ return size;
+}
+
+static DEVICE_ATTR(usbphy_regs, 0644,
+ usbphy_regs_show, usbphy_regs_store);
+
static ssize_t dpdm_pulldown_enable_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -4426,6 +4478,7 @@ static int msm_otg_probe(struct platform
motg->caps |= ALLOW_HOST_PHY_RETENTION;

device_create_file(&pdev->dev, &dev_attr_dpdm_pulldown_enable);
+ device_create_file(&pdev->dev, &dev_attr_usbphy_regs);

if (motg->pdata->enable_lpm_on_dev_suspend)
motg->caps |= ALLOW_LPM_ON_DEV_SUSPEND;
@@ -4527,6 +4580,7 @@ otg_remove_devices:
remove_cdev:
pm_runtime_disable(&pdev->dev);
device_remove_file(&pdev->dev, &dev_attr_dpdm_pulldown_enable);
+ device_remove_file(&pdev->dev, &dev_attr_usbphy_regs);
msm_otg_debugfs_cleanup();
phy_reg_deinit:
devm_regulator_unregister(motg->phy.dev, motg->dpdm_rdev);
@@ -4619,6 +4673,7 @@ static int msm_otg_remove(struct platfor
usb_remove_phy(phy);

device_remove_file(&pdev->dev, &dev_attr_dpdm_pulldown_enable);
+ device_remove_file(&pdev->dev, &dev_attr_usbphy_regs);

/*
* Put PHY in low power mode.
Read more »

时光总是匆匆,一转眼 18 年都已经 2 月份了,今天是农历新年前倒数第二天上班了。17 年过得不那么顺畅,自己想做的很多事都没做,很遗憾;18 年自己即将 30 岁,想想还是很惶恐,已到而立之年了。这些时间自己的懒散加上工作上的事情,很久没有写东西了,博客也好久没有更新过了,考虑到今年的状态,和明年一些决定,今天来写个小结,列个计划。

遗憾的 17 年

17 年整体来说对自己是有些失望的,生活上遇到了一件让自己痛心的事情,也完成了人生一件最重要的事情,工作上除了薪资的涨幅,自己没有明显的进步,也没有什么成就感。

Read more »

这真的是一篇简析。。。 (╯_╰) 本来准备详细分析整个 sensor 架构的,实在时间紧张,只能先简析了。

Platform information: MTK6797(X20)+ Android 7.0

Android 支持的传感器

现在 Android 支持多达数十种的各种各样的传感器,支持的类型如下:

Sensor_Type

Android Sensor 架构

Read more »