2020/11/25

regmap 的 reg_defaults

在 宣告 regmap_config 時,會又 reg_defaults 這個欄位。
這是說明 chip reset 後的 register default value。
並不是要 regmap 做初始話時,寫入的 value。

所以修改 reg_default[] 內的值,並不會跟心的 真正的 chip 上。

保險的作法是在 driver probe 時,把 default register 全部寫一次。

dreamsourcelab LA on WM8974 I2C decode

dreamsourcelab 的 LA 很有趣。
PC 端的軟體是 opensource 的。
所以在 linux 上使用的話,要clone github project,然後 configure, make ...



有 LA 的 decode 功能,幫你 decode 。

向上面就是 I2C 的波型。

decode 完可以 log。

上面就是做 WM8974 的 I2C log。

wm8974 因為只能 write,不能 read,所以沒變法確認write OK

用 LA log,然後寫一個程式update 每個 register 的 final value:
memo 一下 DSView 的操作:
  • 可以指定 log 的時間 (10sec),然後安下 play 開始 log
  • 滾輪是 zomm in/out
  • decode 出現的 dialog,指出要 decode 的 probe data (SDA, SCL)
  • decode 的 save 圖示,把 decode 完的結果 log 成 file

2020/11/20

wpa_supplicant & wpa_cli

ref:

wpa_supplicant
network 設定中:
mode
0 : infrastructure,預設值,會嘗試連結AP
1 : IBSS,ad-hoc, peer to peer
2 : AP
另外,
ap_scan:
0 : scan, 不connect
1 : scan, 找不道的話,舊自己當 AP
2 : scan, and connect

wpa_supplicant 的 config 檔,其中的 network { }區段。對應的就是 wpa_cli 的 add_network , set_network
所以 config 的內容,都可以用 wpa_cli 設定。

sendmail - 送不出..

phabricator 用 sendmail 寄公司內部信。
然後錢一陣子轉 vm 後,有人收不到 phabricator 的通知了。(據說是所有人都收步道..)

先看一下 /var/log/syslog...
...
Nov 20 11:20:01 franxx sm-msp-queue[9753]: My unqualified host name (franxx) unknown; sleeping for retry
Nov 20 11:21:01 franxx sm-msp-queue[9753]: unable to qualify my own domain name (franxx) -- using short name
Nov 20 11:24:34 franxx systemd[1]: Started Session 3645 of user darling.
Nov 20 11:39:01 franxx CRON[11008]: (root) CMD (  [ -x /usr/lib/php/sessionclean ] && if [ ! -d /run/systemd/system ]; then /usr/lib/php/sessionclean; fi)
Nov 20 11:39:01 franxx systemd[1]: Starting Clean php session files...
Nov 20 11:39:01 franxx systemd[1]: Started Clean php session files.
Nov 20 11:39:23 franxx sendmail[11087]: My unqualified host name (franxx) unknown; sleeping for retry
...
但是這個好像不影響,只是會慢一點。..

看一下sensmail 狀況..
$ sudo systemctl status sendmail
● sendmail.service - LSB: powerful, efficient, and scalable Mail Transport Agent
   Loaded: loaded (/etc/init.d/sendmail; bad; vendor preset: enabled)
   Active: active (running) since Mon 2020-10-26 14:14:32 CST; 3 weeks 3 days ago
     Docs: man:systemd-sysv-generator(8)
  Process: 1223 ExecStart=/etc/init.d/sendmail start (code=exited, status=0/SUCCESS)
    Tasks: 1
   Memory: 4.4M
      CPU: 53.028s
   CGroup: /system.slice/sendmail.service
           └─1615 sendmail: MTA: accepting connections 
           ov 18 15:24:34 franxx sm-mta[2047]: 0AD7L1bD018430: 0AI7OYgC002047: postmaster notify: User unknown
Nov 18 15:24:34 franxx sm-mta[2047]: 0AI7OYgC002047: to=MAILER-DAEMON, delay=00:00:00, mailer=local, pri=0, dsn=5.1.1, stat=User unknown
Nov 18 15:24:34 franxx sm-mta[2047]: 0AI7OYgC002047: to=postmaster, delay=00:00:00, mailer=local, pri=0, dsn=5.1.1, stat=User unknown
Nov 18 15:24:34 franxx sm-mta[2047]: 0AI7OYgC002047: 0AI7OYgD002047: return to sender: User unknown
Nov 18 15:24:34 franxx sm-mta[2047]: 0AI7OYgD002047: to=MAILER-DAEMON, delay=00:00:00, mailer=local, pri=0, dsn=5.1.1, stat=User unknown
Nov 18 15:24:34 franxx sm-mta[2047]: 0AI7OYgC002047: Saved message in /var/lib/sendmail/dead.letter
Nov 18 16:21:01 franxx sm-mta[3039]: 0AI8L1XF003039: from=<>, size=2253, class=0, nrcpts=1, msgid=<202011180821.0AI8L1I1003037@franxx>, pr
Nov 18 16:21:01 franxx sm-mta[3039]: 0AI8L1XF003039: to=, delay=00:00:00, mailer=local, pri=32253, dsn=4.4.3, stat=queued
Nov 18 16:21:01 franxx sm-mta[3039]: 0AI8L1XH003039: from=<>, size=2259, class=0, nrcpts=1, msgid=<202011180821.0AI8L1I2003037@franxx>, pr
Nov 18 16:21:01 franxx sm-mta[3039]: 0AI8L1XH003039: to=, delay=00:00:00, mailer=local, pri=32259, dsn=4.4.3, stat=queued
狀態正常,但是都記不出去。

看一下 phabricator: ref:testing outbound:
phabricator/ $ ./bin/mail list-outbound   # List outbound mail.
phabricator/ $ ./bin/mail show-outbound   # Show details about messages.
phabricator/ $ ./bin/mail send-test       # Send test messages.
看一下out-bound...
XXX:/opt/phabricator$ ./bin/mail list-outbound
263 Sent   D163: Fix: If low battery, the alert sound keep ringing in security screen after PND resume.
264 Sent   D162: Fix 2 issues.
265 Sent   D162: Fix 2 issues.
266 Sent   D164: Fix: If low battery, the alert sound keep ringing in security screen after PND resume.
267 Sent   D164: Fix: If low battery, the alert sound keep ringing in security screen after PND resume.
268 Sent   D164: Fix: If low battery, the alert sound keep ringing in security screen after PND resume.
269 Sent   D164: Fix: If low battery, the alert sound keep ringing in security screen after PND resume.
270 Sent   D164: Fix: If low battery, the alert sound keep ringing in security screen after PND resume.
271 Sent   D164: Fix: If low battery, the alert sound keep ringing in security screen after PND resume.
...
284 Sent   D167: Fix 3 suspend/wakeup issues.
285 Sent   D167: Fix 3 suspend/wakeup issues.
286 Sent   D168: Fix 3 suspend/wakeup issues.
287 Sent   D168: Fix 3 suspend/wakeup issues.
288 Sent   D167: Fix 3 suspend/wakeup issues.
289 Sent   D167: Fix 3 suspend/wakeup issues.
290 Sent   D168: Fix 3 suspend/wakeup issues.
291 Sent   D168: Fix 3 suspend/wakeup issues.
292 Sent   D168: Fix 3 suspend/wakeup issues.
293 Sent   D168: Fix 3 suspend/wakeup issues.
294 Sent   D167: Fix 3 suspend/wakeup issues.
295 Sent   D167: Fix 3 suspend/wakeup issues.
果然queue住一堆..


測試一下 sendmail 吧。(ref:how to test sendmail)
$ echo "from franzz" | sendmail -v charles.chang@localtek.com
WARNING: local host name (franxx) is not qualified; see cf/README: WHO AM I?
localtek.com: Name server timeout
charles.chang@localtek.com... Transient parse error -- message queued for future delivery
charles.chang@localtek.com... queued
果然,是 dns 的問題。

轉到 vm 時,dns 沒設定,所以沒動作,test ping google 也 fail
所以把 dns 設好後用 sendmail 測試 OK

2020/11/17

regmap, 有關沒對齊的 reg, value bits 的 i2c transfer function.

regmap.c 中有...
    switch (config->reg_bits + map->reg_shift) {

    ...
    
    case 7:
        switch (config->val_bits) {
        case 9:
            map->format.format_write = regmap_format_7_9_write;
            break;
然後
static void regmap_format_7_9_write(struct regmap *map,
                    unsigned int reg, unsigned int val)
{
    __be16 *out = map->work_buf;
    *out = cpu_to_be16((reg << 9) | val);
}


所以wm8974 的 code:
static const struct regmap_config wm8974_regmap = {
    .reg_bits = 7,
    .val_bits = 9,

的確可以送出 follow wm8974 奇怪 protocol 的格式。

2020/11/14

ubuntu - unattended-upgrade, 有點煩

太煩了。把 unattended-upgrade 移除了,
如果不是每天開機,用這格反而麻煩。
偶額開機要用,要安裝 package,他卻卡住dpkg lock 好久...

每天開機的機器可能比較適合,他會自動安排更新時間。

2020/11/13

inode and partition space

在disk partition 中要能create 新檔,除了要有剩餘空間外,還有有inode 剩下才行。
一般用 df
# df -i
Filesystem              Inodes      Used Available Use% Mounted on
/dev/root                 3.6K      3.5K        66  98% /
devtmpfs                 23.6K       353     23.2K   1% /dev
tmpfs                   124.6K         1    124.6K   0% /dev/shm
tmpfs                   124.6K       384    124.2K   0% /run
tmpfs                   124.6K         6    124.6K   0% /sys/fs/cgroup
tmpfs                   124.6K         8    124.6K   0% /tmp
tmpfs                   124.6K         5    124.6K   0% /var/tmp
/dev/mmcblk0p8               0         0         0   0% /data
tmpfs                   124.6K         4    124.6K   0% /run/user/0

# df 
Filesystem                Size      Used Available Use% Mounted on
/dev/root               504.4M    422.5M     51.8M  89% /
devtmpfs                 94.2M         0     94.2M   0% /dev
tmpfs                   498.4M         0    498.4M   0% /dev/shm
tmpfs                   498.4M    268.0K    498.1M   0% /run
tmpfs                   498.4M         0    498.4M   0% /sys/fs/cgroup
tmpfs                   498.4M      4.0K    498.4M   0% /tmp
tmpfs                   498.4M         0    498.4M   0% /var/tmp
/dev/mmcblk0p8            6.6G      1.0M      6.6G   0% /data
tmpfs                    99.7M         0     99.7M   0% /run/user/0
像 df -i 中,/dev/root 已經用掉 98%,剩下 66 個 inode。
touch 66 個 file 後,inode 剩下 0
這時候,就算是 df 中 /dev/root 還有 50M 的空間,也沒辦法再 create 新檔了。

另外,..
du --inode folder
也會列出 folder 內的inode 用量。
其中根目錄會列出subfolder 的inode 用量總和。


如果是慢慢漲起來的..可以用 find . 然後依照 file time sorting,找出新增的檔案...
find . -type f -name '*.kk' -printf "%T+ %p\n" | sort

一般embedded system 是在 rootfs 遭遇這個問題,rootfs 又是一個 block device,用 loopback 做出來。
可以用tune2fs 來看,不用真的 mount 起來..
$ tune2fs -l ext4 
tune2fs 1.44.1 (24-Mar-2018)
Filesystem volume name:   
Last mounted on:          
Filesystem UUID:          a34e7a5d-cb27-4f62-bdce-3d68b3e55537
Filesystem magic number:  0xEF53
Filesystem revision #:    1 (dynamic)
Filesystem features:      has_journal dir_index extent
Filesystem flags:         signed_directory_hash 
Default mount options:    (none)
Filesystem state:         clean
Errors behavior:          Unknown (continue)
Filesystem OS type:       Linux
Inode count:              3712
Block count:              468226
Reserved block count:     23411
Free blocks:              29952
Free inodes:              129
First block:              1
Block size:               1024
Fragment size:            1024
Blocks per group:         8080
Fragments per group:      8080
Inodes per group:         64
Inode blocks per group:   8
Last mount time:          n/a
Last write time:          Thu Oct 29 11:30:35 2020
Mount count:              0
Maximum mount count:      -1
Last checked:             Thu Oct 29 11:30:19 2020
Check interval:           0 ()
Reserved blocks uid:      0 (user root)
Reserved blocks gid:      0 (group root)
First inode:              11
Inode size:	          128
Journal inode:            8
Default directory hash:   half_md4
Directory Hash Seed:      0e89286e-5c9d-4f0c-9aad-37b2cd127b29
Journal backup:           inode blocks

ref:

2020/11/12

紀錄 make, linking with libnl-3...

 fatal error: netlink/genl/genl.h: No such file or directory
 #include <netlink/genl/genl.h>

找一下..因為已經有 install lib-nl-3-dev 了...
apt-file search genl.h
..
libnl-3-dev: /usr/include/libnl3/netlink/genl/genl
所以修改 Makefile..
加入
CFLAGS += -I/usr/include/libnl3

然後出現..
/usr/bin/ld: cannot find -lnl-genl-3

然後一樣用 apt-file
apt-file search libnl-genl

libnl-genl-3-dev: /lib/aarch64-linux-gnu/libnl-genl-3.a
libnl-genl-3-dev: /lib/aarch64-linux-gnu/libnl-genl-3.so

但是用 find ..
$ sudo find . -name libnl-genl*
./lib/aarch64-linux-gnu/libnl-genl-3.so.200.24.0
./lib/aarch64-linux-gnu/libnl-genl-3.so.200
./var/lib/dpkg/info/libnl-genl-3-200:arm64.symbols
./var/lib/dpkg/info/libnl-genl-3-200:arm64.triggers
./var/lib/dpkg/info/libnl-genl-3-200:arm64.list
./var/lib/dpkg/info/libnl-genl-3-200:arm64.md5sums
./var/lib/dpkg/info/libnl-genl-3-200:arm64.shlibs
./usr/share/doc/libnl-genl-3-200
所以.. 自己建 link ?:
姊果一直說 fail,沒版法建,只好直接 copy, rename..
cp libnl-genl-3.so.200.24.0 libnl-genl-3.so
之後再 make 舊 OK

WM8974 , 奇怪的 audio codec..

在linux kernel 中,很久以前,就有 wm8974 的 driver 了。
datasheet 看到這個不叫 i2c,叫 2 wire。

從 2 wire command diagram 來看.. 的確很奇怪:

address 部份跟一般 i2c 一樣,前 7 個是 address,最後一個 bit 是 read/write bit
接著是 reg , 只有 7 bit,所以最後一個 bit 是 data 的 highest bit

wm8974 的 reg 只有 7 bit,data 有 9 bit
register value 說明也真的有定義第9bit..

所以 i2c protocl:
1: chip address(7)+R/W(1)
2: reg index(7) + Data 8th bit(1)
3: Data 7-0 bit (8)
跟一般 I2C 裝置不一樣。

因為這樣,wm8974 沒有 read 動作。
也就是說,不能 read register。 --- 不然 protocol 要怎樣....



Linux driver 的部份:

古老的 wm8974 driver 使用自己提供的 i2c_read, i2c_write,看得出這個奇怪的動作:
static inline unsigned int wm8974_read_reg_cache(struct snd_soc_codec * codec,
	unsigned int reg)
{
	u16 *cache = codec->reg_cache;
	if (reg == WM8974_RESET)
		return 0;
	if (reg >= WM8974_CACHEREGNUM)
		return -1;
	return cache[reg];
}

/*
 * write wm8974 register cache
 */
static inline void wm8974_write_reg_cache(struct snd_soc_codec *codec,
	u16 reg, unsigned int value)
{
	u16 *cache = codec->reg_cache;
	if (reg >= WM8974_CACHEREGNUM)
		return;
	cache[reg] = value;
}

/*
 * write to the WM8974 register space
 */
static int wm8974_write(struct snd_soc_codec *codec, unsigned int reg,
	unsigned int value)
{
	u8 data[2];

	/* data is
	 *   D15..D9 WM8974 register offset
	 *   D8...D0 register data
	 */
	data[0] = (reg << 1) | ((value >> 8) & 0x0001);
	data[1] = value & 0x00ff;

	wm8974_write_reg_cache (codec, reg, value);
	if (codec->hw_write(codec->control_data, data, 2) == 2)
		return 0;
	else
		return -EIO;
}
i2c_write 內容有看到把 data shift 到 reg 一個bit
然後沒有提供 i2c_read

然後 driver 註冊時...
static int wm8974_init(struct snd_soc_device *socdev)
{
	struct snd_soc_codec *codec = socdev->codec;
	int ret = 0;

	codec->name = "WM8974";
	codec->owner = THIS_MODULE;
	codec->read = wm8974_read_reg_cache;
	codec->write = wm8974_write;
..
read 用的是 read_reg_cache



然後新版的kernel (3.1 以上),新增加了 regmap 這個 結構,
就是把 register map cache 起來,write 時同時更新 cache,
read 時就拿 cache 值,不用真的去 read。
-- 當然也可以真的去 read

同時 regmap 也增加了 reg_bits, val_bits 這兩個 properties。
所以新版的 wm8974 driver,已經有:
static const struct regmap_config wm8974_regmap = {
    .reg_bits = 7,
    .val_bits = 9,

    .max_register = WM8974_MONOMIX,
    .reg_defaults = wm8974_reg_defaults,
    .num_reg_defaults = ARRAY_SIZE(wm8974_reg_defaults),
    .cache_type = REGCACHE_FLAT,
};

比較漂亮的寫法就是用regmap : regmap, 有關沒對齊的 reg, value bits 的 i2c transfer function.

用了 regmap,cache type 用 FLAT,就會 使用 cache,這樣,read 就會從 cache 做,
這時候,要 dump register 舊只能用 regmap support 的地方:
# cat /sys/kernel/debug/regmap/2-001a/registers 
00: 0000
01: 002e
02: 0000
03: 0000
04: 0010
05: 0001
06: 0120
07: 0000
08: 0000
09: 0000
0a: 0041
0b: 00d7
0c: 0000
0d: 0000
0e: 0100
0f: 00ff
10: 0000
11: 0000
12: 012c
13: 002c
14: 002c
15: 002c
16: 002c
17: 0000
18: 0032
19: 0000
1a: 0000
1b: 0000
1c: 0000
1d: 0000
1e: 0000
1f: 0000
20: 0038
21: 000b
22: 0032
23: 0000
24: 001b
25: 0001
26: 0133
27: 0066
28: 0000
29: 0000
2a: 0000
2b: 0000
2c: 0003
2d: 0010
2e: 0000
2f: 0000
30: 0000
31: 0002
32: 0000
33: 0000
34: 0000
35: 0000
36: 0025
37: 0000
38: 0001

2020/11/11

Face Recognition : FAR and FRR

ref: 在臉部辨識上提到的這兩個名詞
  • FAR : False Acceptance Rate
  • FRR : False Rejection Rate
Face recognition 用的手都是參數化的方法,NN 把臉部圖形轉成一組 128 個數值的向量。
和 data base 中每個人的 參數比較,計算出"引力"(距離平方反比),跟誰引力最大,就是誰。

但是也有 "不認識","不屬於 database 中" 的情況出現。
這時候,就要把 "距離" 加上一個 threshold,要引力大於這個值才算,否則就是 "不認識" 的人。

而這個 threshold 舊決定了 FAR 跟 FRR。

FAR 隨著threshold 增加而降低。
FRR 隨著threshold 增加而增加。

兩個剛好在左右兩端達到最大。
所以最佳 threshold 的值就是 FAR, FRR 都最小的中間數值。



感想:看完上面ref 的內容,感覺 face recognition 蠻不准的....

2020/11/10

bookmark : CRA (Chief Ray Angle)

Image Sensor 用的參數。

Image Sensor 的每個 pixel 上都會有一個 micro-lens。
micro-lens 用來聚焦光線到 pixel 上。

lens 有 FOV (field of view),所以必須要和外接的鏡頭搭配,讓經由鏡頭篇折的光線,進入 micro-lense 後,能夠正確的落在 pixel 上。
如果沒有批配的話,光線進入 micro-lense 後,就會落掉旁邊的 pixel ,造成雜訊點或是影像失真。

所以 sensor 的 CRA 必須要和鏡頭設計一起考慮。


實際測試的姊果,lens fov 與 CRA 符合的 camera,影像較 CRV 0 的清楚很多,相較起來,CRV0 的影像好像是對焦沒對好。

2020/11/8

opencv document: cross build

這篇很詳細講opencv cross build for arm 的方法,基本上和上次寫的cmake cross build 的方法一樣。
opencv 寫好了platform,XXX.cmake。
所以只要準備好要的cross-tool,然後用opencv 的 toolchain cmake 就可以。

其他如果有需要的library,可以參考上次寫的。放在set_ 裡面。

其實embeddes system opencv port,比較重要的是 bsp 有沒有hardware support,還有opencv 要怎麼link 到 bsp 的hardware 加速library。
另外,還要build 出 python support module,放在target system 得 python class loading path 中,這樣 target system 的 python 才能 import。

python 3 and opencv3.4.2 ..imshow fail. --- centor of contours

一個 imshow 就 fail 掉:
cv2.error: OpenCV(3.4.2) /tmp/build/80754af9/opencv-suite_1535558553474/work/modules/highgui/src/window.cpp:632: 
error: (-2:Unspecified error) The function is not implemented. Rebuild the library with Windows, GTK+ 2.x or Carbon support. 
If you are on Ubuntu or Debian, install libgtk2.0-dev and pkg-config, 
then re-run cmake or configure script in function 'cvShowImage'

結果follow 這一個:
conda remove opencv
conda install -c conda-forge opencv=4.1.0
..意思是說..3.4.2 板的沒有enable WITH_GTK=ON ?

haha 6 月的時後,已經發生過了...

另外,很有趣,python 因為可以return tuple type,所以function 把 rc code(success, fail) 和 process result 包成一個 tuple 傳回來。
所以,以 opencv 的 threshold( ) function:
rc, out = cv2.threshold(blurred,60,255,cv2.THRESH_BINARY)
rc 是 成功或失敗,out 是 threshold 處理以後的結果。
如果要直接拿結果,不管成功失敗,可以直接取 tuple 的 elememt:
out = cv2.threshold(blurred,60,255,cv2.THRESH_BINARY)[1]


依照這篇文章,利用findContour找出輪廓,再用moments 找出輪廓中心座標的 code,在: 加上了最小面積偵測,如果太小就不採用。(實際上是遭遇到雜訊點面積為0的錯誤)
另外,為了考慮能porting 到 embedd system,所以拿掉而外的 module。
參考文章說的,findcontours 的傳回格式跟opencv 版本有關。

這一篇是同樣方法的中文版本,說得更清楚,也有用實際照片做例子
-- 看起來這是標準的方法...

這一篇是用C++的example,如果python porting 不上去,或是 bsp 的 opencv port 沒有support python時,可以用C++做。
-- 參考他的作法,改成跟python 版 一樣的 algorithm 版本的 C++ code,一樣在 github project 中。

沒用用到什模特殊的,最後一個 commit,把 show image 的部份刪除就可以在 target board 上 run 了,用存檔來檢查每一個 process 的結果。

2020/11/6

pthread return value

pthread 可以 return value 給 parent process (who create it)
這個 方法:
#include <pthread.>
#include <stdio.h>
void *myThread()
{
   printf("in thread now\n");
   return (void *) 42;
}

int main()
{
   pthread_t tid;
   int status;

   pthread_create(&tid, NULL, myThread, NULL);
   pthread_join(tid, (void*)&status);

   printf("%d\n",status);   

   return 0;
}  
 
.. 這個 status 的宣告...
要測試 一下..

等等... 感覺怪怪的...
因為 return 一個 cast 成 (void*) 的 scalar value
...
要是看這一篇的話,thread要為return value alloc一塊記憶體,不能隨thread 退出兒消失。
經由把指標return 給 creator 後,creator 負責 free 掉。


有關 return 跟 exit() :
這一篇說明看起來好可怕...
對C++來說,return 會 call 所有 local scope 物件的 destructor,一一release 完再結束,而exit( )不會這樣做,它直接結束。
-- 可以寫sample code 試試,看看 1.不寫 2.return 3.exit( ) 對於 local 物件有蛇麼差別。


實際上用 g++ -S main.cpp 產生 assembly file 來看有 return 跟沒 return 的差別。
只插在 有return 的,多一個 intruction 把 return value 放到 eax,沒return 的,就放一個 nop (為什麼要放?)

add read/write function in i2c_client driver function

snd_soc_codec_driver
裡面有:
  • write : i2c_write
  • read : i2c_read
如果沒有指定,就會用 platform 內的。

所以如果想要 debug snd_soc_code driver,知道該 driver 對 i2c 的動作。
可以自己寫 i2c_read, i2c_write 放進去。
static unsigned int my_i2c_read(struct snd_soc_codec *codec, unsigned int reg)
{
    struct my_priv *mypriv = snd_soc_codec_get_drvdata(codec);
    int ret = -1; 
    unsigned char tx[1], rx[1];

    struct i2c_msg xfer[2];
    struct i2c_client *client = mypriv->i2c;

    tx[0] = reg;
    rx[0] = 0;

    /* Write register */
    xfer[0].addr = client->addr;
    xfer[0].flags = 0;
    xfer[0].len = 1;
    xfer[0].buf = tx;

    /* Read data */
    xfer[1].addr = client->addr;
    xfer[1].flags = I2C_M_RD;
    xfer[1].len = 1;
    xfer[1].buf = rx;

    ret = i2c_transfer(client->adapter, xfer, 2);

    if (ret != 2)
        printk("\t%s error ret = %d\n", __func__, ret);

    return (unsigned int)rx[0];

}

static int my_i2c_write(struct snd_soc_codec *codec, unsigned int reg,
                unsigned int value)
{
    struct my_priv *mypriv = snd_soc_codec_get_drvdata(codec);
    int ret = -1;
    unsigned char tx[2];
    size_t  len = 2;

    if(reg==1)
        value |= 0x02; // don't power off spk 

    tx[0] = reg;
    tx[1] = value;

    printk("\t %s: (addr,data)=(%x, %x)\n", __func__, reg, value);

    ret = i2c_master_send(mypriv->i2c, tx, len);

    if (ret != len)
        return -EIO;

    return 0;
}
但是要struct my_priv 要把 probe 時,register 的 i2c client 田進變數
struct my_priv {
    struct i2c_client *i2c;
     ...
然後 module probe function...
static int my_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
{
    struct my_priv *mypriv;
    mypriv = devm_kzalloc(&i2c->dev. sizeof(struct my_priv), GFP_KERNEL);
    
    i2c_set_client_data(i2c, mypriv);
    mypriv->i2c = i2c;
    ...
這樣,這個 driver call snd_soc_read/write 時,就會 call 到 自己的 i2c_read/write function.
然後舊可以加 debug message...
但是這樣舊沒用到 regmap,所以 sys/kernel/debug/regmap/XXXX/registers 的內容不會顯示。

2020/11/5

nginx : get auth failcount behind proxy

proxy 後方的 restful server 要知道nginx 端 login fail 的次數。
可能要參考這一篇。
改用 auth_request module.
然後把 fail 頁面倒到令一個 restful api 上,並且把 failcount 放進 parameters..

.. 還沒試過..

使用 auth_request 的方法。可以參考這一篇

或是用 basic_auth,然後在 error page 時,導到 resetful server. 大概是這樣做

2020/11/3

記 一下 i2c tool 的動作, i2cget , i2cset

其實單獨執行。不加 argument 的時候,都會有 help.

# i2cdetect 
BusyBox v1.31.1 (2020-02-18 12:01:00 CST) multi-call binary.

Usage: i2cdetect -l | -F I2CBUS | [-ya] [-q|-r] I2CBUS [FIRST LAST]

Detect I2C chips

	-l	List installed buses
	-F BUS#	List functionalities on this bus
	-y	Disable interactive mode
	-a	Force scanning of non-regular addresses
	-q	Use smbus quick write commands for probing (default)
	-r	Use smbus read byte commands for probing
	FIRST and LAST limit probing range


# i2cdetect -y -a 2
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- UU -- -- -- -- -- UU -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 


# i2cdump 
BusyBox v1.31.1 (2020-02-18 12:01:00 CST) multi-call binary.

Usage: i2cdump [-fy] [-r FIRST-LAST] BUS ADDR [MODE]

Examine I2C registers

	I2CBUS	I2C bus number
	ADDRESS	0x03-0x77
MODE is:
	b	Byte (default)
	w	Word
	W	Word on even register addresses
	i	I2C block
	s	SMBus block
	c	Consecutive byte
	Append p for SMBus PEC

	-f	Force access
	-y	Disable interactive mode
	-r	Limit the number of registers being accessed


# i2cdump -fy 2 0x12
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: c9 06 48 01 60 50 0b 23 00 00 60 00 e1 e1 f0 00    ??H?`P?#..`.???.
10: 18 1e fc fc fc fc 07 03 03 d0 1f 60 20 00 10 00    ???????????` .?.
20: 00 0f 33 05 10 29 22 f6 bd 00 73 3e 79 e1 1d 03    .?3??)"??.s>y???
30: 92 39 3a e6 00 10 f1 1d 00 00 00 00 00 00 00 00    ?9:?.???........
40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................


# i2cget
BusyBox v1.31.1 (2020-02-18 12:01:00 CST) multi-call binary.

Usage: i2cget [-fy] BUS CHIP-ADDRESS [DATA-ADDRESS [MODE]]

Read from I2C/SMBus chip registers

	I2CBUS	I2C bus number
	ADDRESS	0x03-0x77
MODE is:
	b	Read byte data (default)
	w	Read word data
	c	Write byte/read byte
	Append p for SMBus PEC

	-f	Force access
	-y	Disable interactive mode


# i2cget -fy 2 0x12 0
0xc9
# i2cget -fy 2 0x12 1
0x06


# i2cset
BusyBox v1.31.1 (2020-02-18 12:01:00 CST) multi-call binary.

Usage: i2cset [-fy] [-m MASK] BUS CHIP-ADDRESS DATA-ADDRESS [VALUE] ... [MODE]

Set I2C registers

	I2CBUS	I2C bus number
	ADDRESS	0x03-0x77
MODE is:
	c	Byte, no value
	b	Byte data (default)
	w	Word data
	i	I2C block data
	s	SMBus block data
	Append p for SMBus PEC

	-f	Force access
	-y	Disable interactive mode
	-r	Read back and compare the result
	-m MASK	Mask specifying which bits to write
# i2cset -fy 2 0x12 0 0xc8
# i2cget -fy 2 0x12 0
0xc8

clang, disable optimize for latter pass

這一篇,用 llvm-11 的話,opt 的指令沒有效。
stack overflow 有說。
在 compile 時,如果沒有加上 -O,在產生的 ll file, function 錢會有 optnone,避免 reg2mem 做 optimization:
; Function Attrs: noinline nounwind optnone uwtable
define i32 @add(i32, i32) #0 {
  %3 = alloca i32, align 4
  %4 = alloca i32, align 4
  store i32 %0, i32* %3, align 4
所以 compile 時要加場上 -O
clang -S -emit-llvm -O  main.c
這樣就不會有 optnone 的標記:
; Function Attrs: norecurse nounwind readnone uwtable
define i32 @add(i32, i32) local_unnamed_addr #0 {
  %3 = add nsw i32 %1, %0
  ret i32 %3
}
但是也optimize 過了...

如果不要他先 optimize,又要加
clang -S -emit-llvm -O -Xclang -disable-llvm-passes main.c
這樣才能完成跟街學文章一樣的code
; Function Attrs: nounwind uwtable
define i32 @add(i32, i32) #0 {
  %3 = alloca i32, align 4
  %4 = alloca i32, align 4
  store i32 %0, i32* %3, align 4, !tbaa !2
  store i32 %1, i32* %4, align 4, !tbaa !2
  %5 = load i32, i32* %3, align 4, !tbaa !2



最後,用 as 和 ld link 出 exeutable file,
要指定 crt1.o, crti.o,但是最終還是無法執行。

可能是 default library 的關係。
用 gcc assembly front-end 舊可以..
gcc main.s -no-pie -o main
用 -v 可以看一下 gcc ld 的 default crt.o 和 library
或許照著寫舊可以用 ld 成功 link..

這一篇 就是這樣做
ld -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 test.o  /usr/lib64/crt1.o /usr/lib64/crti.o /usr/lib64/gcc/x86_64-linux/4.3/crtbegin.o -lc /usr/lib64/gcc/x86_64-linux/4.3/crtend.o /usr/lib64/crtn.o
用了 ld-linux-x86-64.so crti.o crtbegin.o

依照 error mesaage,最後。minimum:
ld main.o /usr/lib/x86_64-linux-gnu/crt1.o /usr/lib/x86_64-linux-gnu/crti.o -lc
但是link 出來的 a.out 執行出現 'No such file or directory'

這一篇 的回答好像才是重點,interpreter 的問題。
用 gcc compile 的 a.out 和 ld link 出來的 a.out,用 readelf -l 看, interpreter 不一樣。

用 patchelf 的話..
$ patchelf --print-interpreter a.out 
/lib/ld64.so.1
$ patchelf --print-interpreter gmain 
/lib64/ld-linux-x86-64.so.2
不一樣。
實際上沒有 /lib/ld64.so.1
所以 Error message 是 'No sunch file or directory'

用 patchelf 設定正確的 interpreter;
patchelf --set-interpreter /lib64/ld-linux-x86-64.so.2 a.out 
所以。最後,正確 ld 的 command 是:
ld -o a.out -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/x86_64-linux-gnu/crt1.o /usr/lib/x86_64-linux-gnu/crti.o -lc  /usr/lib/x86_64-linux-gnu/crtn.o main.

這一篇 有詳細講crtX.o 和 interpreter 之間的關係和實驗。

2020/11/2

https 基本原理

Browser, Server 都先準備好自己的 private/public key pair

  • Browser 透過 https 向 Server 發出 request
  • Server 把自己經過 CA 認證的 site.crt 送給 browser,(crt 裡面有 server 的 public key 和 CA 的 sign
  • Browser 收到 crt, 先用 CA 的 public key 確認 crt 裡,CA 的 sign 是正確的,還有 checksum 正確,代表 crt 沒被竄改
  • Browser 把 crt 裡的 public 拿出來,加密自己的 public key,送給 Server
  • Server 收到 Browser 的 public key 了
完成以上動作後,Browser, Server 就互相有對方的 public key 了。

兩人用對方的 public 加密送資料給對方。
對方就可以用自己的 private key 解開。

用 tls 通訊 Boost 的 example

boost asio 有 ssl 的 programming example: 但是沒有操作說明。

這一篇是 操作說明,可惜是以 windows 為 platform
.. 現在在 linux 上試試看。

這一篇 也有產生 key, crt 和example 修改的範例
這一篇用 boost asio ssl 模擬 browser 對 https 的 request 動作。



先亂寫一下...,不知道政不正確...

SSL certication
  • Cryptographic Key
  • server/domain , organization name
某網站的公鑰

然後這個 certication 是經果某個機構認證的。
機構:Cerfitication Authority (CA)

把自己的 public key 和自己的 location, domain name 包成 CSR (Certificate Signing Request) 格式,交給 CA
CA 會去檢查你是不是就是這個 CSR 內的 domain owner
-- 會要求你提供一堆資料。

CA 確認的話,CA 就會寄一份 SSL certification 給你,內容包含你的機構名稱,public key。
然後你就可以把這個SSL certication 放在你的 server 中。

CA 寄給你的 SSL certification 會包另一個 " trust root" 的 certification。

Browser 都會內建一堆 CA 機構的的 Root certification。
這樣舊知道你的 SSL certification 是不是真的。

browser 收到你用 private 加密的內容。
browser 有你的 SSL 憑證,包含一個CA root 的認證。好確保這個憑證是真的。
裡面有你的 public key,可以用來解開你用 private key 加密的內容。


CSR 送給 CA 機構,他確認正確後,就會把CSR 的資料斷做 checksum,然後用CA 自己的 private key 加密後,附在你的 CSR 後面。t
這就是CRT 了。
CA 會把 CRT 寄給你。


browser 都有內建一堆 CA 的 public key.
所以收到某網站的 CRT,他先用 CA 的 public key 確認這格 CRT 真的是 CA 認可(sign) 過得。
然後因為 checksum 的關係,。同時確認這格 CRT 沒有被修改。
這樣他就可以相信這個 CRT 裡的 public key 跟 domain 資料。
舊可以用 public key 來解開/確認這格 domain 用 private key 加密過後的資料。



openssl 可以作到所有的事,也可以用來列出 CSR, CRT, Key 的內容。

產生 private key
openssl genesa -out mypriv.key 4096
用private key 做出 CSR
openssl req -out mysite.csr -key mypriv.key -new



這一篇 使用 openssl 產生 private/public key pair。
然後各自加密檔案,再用對方解密。
同時還說明 crt 中用來 verify signature 的方法(command)


這一篇直接寫出command.
# Generate keys
openssl genrsa -out key.pem
openssl rsa -in key.pem -out key.pub -pubout

# Encrypt and Decrypt a file (using public key to encrypt)
echo --pass-- >> pass.txt
openssl rsautl -in pass.txt -out pass.enc -pubin -inkey key.pub -encrypt
openssl rsautl -in pass.enc -out pass.dec -inkey key.pem -decrypt
cat pass.dec