硬盘盒来电自动启动改造

市面上常见的硬盘盒或硬盘柜几乎都设计了电源按钮开关,并不是外部供电就自动开机的,这也是一种保护措施。但如果我们用这类产品连接家庭服务器或NAS的话,在意外停电恢复后,外置硬盘盒设备就不能访问了,需要手工按一下电源开关。那么,有没有方法可以使这类产品能自动开机呢?方法不仅有,还不止一种哦。

下面,我们以ORICO 9528系列硬盘柜为例,介绍几种方案,其中短接和电容两种方法为来电自动开机方式,而继电器和伺服电机两种方法则可由单片机或各种派来远程控制。


短接
顾名思义,就是将微动电源开关一直按压住,可以使用强力胶带或其它任意有效方法实现。
优势:1. 简单有效且无需拆机。
缺陷:1. 仅部分产品有效。 2. 长期短接是否有风险。 3. 来电不稳定期损坏硬盘。

电容
相对直接短接,还可以串接电容来替换微动开关,在来电时,电容充电此时相当于开关按下,当电容充满时,相当于开关释放。
优势:1. 适用于所有微动开关。2. 无长期短接的不确定风险。
缺陷:1. 需要拆机,影响保修。2. 来电不稳定期损坏硬盘。

继电器
使用程控继电器替换电源开关,在来电后主机启动完成的情况下,由程序控制硬盘柜启动。
优势:1. 适用于所有开关情况。2. 无长期短接的不确定风险。3. 无来电不稳定损坏硬盘。
缺陷:1. 需要拆机,影响保修。

伺服电机
在硬盘柜电源按钮外安装伺服电机,由程序控制电机转动,再由连接在电机转轴上的机械臂按压微动开关。
优势:1. 适用于所有开关情况。2. 无长期短接的不确定风险。3. 无来电不稳定损坏硬盘。4. 无需拆机,不影响保修。
缺陷:暂无。

综合来看,采用伺服电机方法即有安全保障,又无拆机风险,同时成本并不高,大概20元左右。

清单
1. MG90S型舵机 x 1。

2. 母对公杜邦线 x 3。

3. 3M VHB强力双面胶带 x 1 (搜索ETC专用类,这种双面胶有一定的厚度和弹性,在舵机旋臂按压时有缓冲空间)。

安装
1. 剪取与舵机机身等长的两段3M双面胶粘与机身一面。
2. 再将舵机粘贴在硬盘盒微动开关处的合适位置之上。


3. 将舵机GND线连接树莓派GPIO的任意GND引脚,舵机的5V线连接树莓派GPIO的其中一个5V引脚,最后将舵机的信号线连接树莓派的任意具有GPIO功能的引脚。

4. 先不需要着急安装舵机的旋臂,在连接好线路并确认控制程序可工作后,再根据实际的旋转角度一点点调节旋臂,使之在转至最大角度时正好轻触微动开关,防止角度过大损坏设备。

使用
因为NanoPi M4的GPIO信号是3V电平,驱动不了MG90S舵机,正好手上有一块闲置的Rpi2,拿到当舵机控制模块(有点大材小用了,反面都是吃灰的命)。

NanoPi M4使用USB3.0连接硬盘盒,真千兆网口传输数据,再通过GPIO发送开关信号给Rpi2。Rpi2就比较简单了,在GPIO上监听信号事件,事件触发就产生PWM脉冲信号控制舵机旋转,按压开关按钮。

Rpi2自然也不需要跑完整的发行版啦,只要一个内核和initramfs中包含一个静态链接的控制程序作为init进程。

如果仅用树莓派来控制,控制舵机的关键程序如下:

    const double duty_up = 2.0;
    const double duty_down = 4.0;
    int i;
 
    for (i = 0; i < 10; i++) {
        gpio_write (fd, 1);
        usleep (duty_down * 200);
        gpio_write (fd, 0);
        usleep ((100.0 - duty_down) * 200);
    }
 
    for (i = 0; i < 10; i++) {
        gpio_write (fd, 1);
        usleep (duty_up * 200);
        gpio_write (fd, 0);
        usleep ((100.0 - duty_up) * 200);
    }

NanoPi+Rpi组合完整版控制程序:
https://gist.github.com/heiher/1d48924da7f134315e7128aad74ca6e1

Over!

NanoPi M4 GPIO

 +------+-----+----------+------+ Model  NanoPi-M4 +------+----------+-----+------+
 | GPIO | wPi |   Name   | Mode | V | Physical | V | Mode |   Name   | wPi | GPIO |
 +------+-----+----------+------+---+----++----+---+------+----------+-----+------+
 |      |     |     3.3V |      |   |  1 || 2  |   |      | 5V       |     |      |
 |      |     | I2C2_SDA |      |   |  3 || 4  |   |      | 5V       |     |      |
 |      |     | I2C2_SCL |      |   |  5 || 6  |   |      | GND(0V)  |     |      |
 |   32 |   7 | GPIO1_A0 |  OUT | 0 |  7 || 8  |   | ALT  | GPIO4_C1 | 15  |  145 |
 |      |     |  GND(0V) |      |   |  9 || 10 |   | ALT  | GPIO4_C0 | 16  |  144 |
 |   33 |   0 | GPIO1_A1 |   IN | 0 | 11 || 12 | 1 | IN   | GPIO1_C2 | 1   |  50  |
 |   35 |   2 | GPIO1_A3 |   IN | 0 | 13 || 14 |   |      | GND(0V)  |     |      |
 |   36 |   3 | GPIO1_A4 |   IN | 0 | 15 || 16 | 0 | IN   | GPIO1_C6 | 4   |  54  |
 |      |     |     3.3V |      |   | 17 || 18 | 0 | IN   | GPIO1_C7 | 5   |  55  |
 |      |     | UART4_TX |      |   | 19 || 20 |   |      | GND(0V)  |     |      |
 |      |     | UART4_RX |      |   | 21 || 22 | 0 | IN   | GPIO1_D0 | 6   |  56  |
 |      |     | SPI1_CLK |      |   | 23 || 24 |   |      | SPI1_CSn |     |      |
 |      |     |  GND(0V) |      |   | 25 || 26 |   | ALT  | GPIO4_C5 | 11  |  149 |
 |      |     | I2C2_SDA |      |   | 27 || 28 |   |      | I2C2_SCL |     |      |
 |      |     | I2S0_LRX |      |   | 29 || 30 |   |      | GND(0V)  |     |      |
 |      |     | I2S0_LTX |      |   | 31 || 32 |   |      | I2S_CLK  |     |      |
 |      |     | I2S0_SCL |      |   | 33 || 34 |   |      | GND(0V)  |     |      |
 |      |     | I2S0SDI0 |      |   | 35 || 36 |   |      | I2S0SDO0 |     |      |
 |      |     | I2S0I1O3 |      |   | 37 || 38 |   |      | I2S0I2O2 |     |      |
 |      |     |  GND(0V) |      |   | 39 || 40 |   |      | I2S0I3O1 |     |      |
 +------+-----+----------+------+---+----++----+---+------+----------+-----+------+

Over!

Nginx WebDAV Service

0x01 Installation

git clone --depth 1 https://github.com/heiher/nginx
cd nginx
git clone --depth 1 https://github.com/heiher/nginx-dav-ext-module
 
./auto/configure --prefix=/opt/nginx \
    --with-compat \
    --with-file-aio \
    --with-http_addition_module \
    --with-http_auth_request_module \
    --with-http_dav_module \
    --with-http_degradation_module \
    --with-http_flv_module \
    --with-http_geoip_module \
    --with-http_gunzip_module \
    --with-http_gzip_static_module \
    --with-http_mp4_module \
    --with-http_realip_module \
    --with-http_secure_link_module \
    --with-http_slice_module \
    --with-http_ssl_module \
    --with-http_stub_status_module \
    --with-http_sub_module \
    --with-http_v2_module \
    --with-pcre-jit \
    --with-threads \
    --add-module=nginx-dav-ext-module
 
make
sudo make install

0x02 Configuration
Main: /opt/nginx/conf/nginx.conf:

#user  nobody;
worker_processes  1;
 
#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;
 
#pid        logs/nginx.pid;
 
 
events {
    worker_connections  1024;
}
 
 
http {
    include       mime.types;
    default_type  application/octet-stream;
 
    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';
 
    #access_log  logs/access.log  main;
 
    sendfile        on;
    #tcp_nopush     on;
 
    #keepalive_timeout  0;
    keepalive_timeout  65;
 
    #gzip  on;
 
    dav_ext_lock_zone zone=foo:10m;
 
    server {
        listen       80;
        server_name  localhost;
 
        #charset koi8-r;
 
        #access_log  logs/host.access.log  main;
 
        location / {
            root   html;
 
            auth_basic Restricted;
            auth_basic_user_file htpasswd;
 
            dav_methods PUT DELETE MKCOL COPY MOVE;
            dav_ext_methods PROPFIND PROPPATCH OPTIONS LOCK UNLOCK;
            dav_ext_lock zone=foo;
            dav_access user:rw group:rw all:r;
 
            client_max_body_size 0;
            create_full_put_path on;
        }
 
        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }
 
}

Auth: /opt/nginx/conf/htpasswd:

htpasswd -b -c /opt/nginx/conf/htpasswd YOUR_USERNAME YOUR_PASSWORD

Start, Stop and Reload:

# Start
sudo /opt/nginx/sbin/nginx
 
# Stop
sudo /opt/nginx/sbin/nginx -s stop
 
# Reload
sudo /opt/nginx/sbin/nginx -s reload

0x03 Clients
Nautils

Windows 10
Fix authentication and file size limits, open regedit and modify:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\WebClient\Parameters\
BasicAuthLevel = 2
FileSizeLimitInBytes = 0xffffffff



Over!

GCC: Dump enabled optimization options

-fverbose-asm
Put extra commentary information in the generated assembly code to make it more readable. This option is generally only of use to those who actually need to read the generated assembly code (perhaps while debugging the compiler itself).

-O3

gcc -O3 -fverbose-asm -o t.s t.c
	.arch armv8-a
	.file	"t.c"
// GNU C17 (GCC) version 9.2.0 (aarch64-unknown-linux-gnu)
//	compiled by GNU C version 9.2.0, GMP version 6.1.2, MPFR version 4.0.2, MPC version 1.1.0, isl version isl-0.21-GMP
 
// GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
// options passed:  t.c -march=armv8-a -mlittle-endian -mabi=lp64
// -auxbase-strip 3 -O3 -fverbose-asm
// options enabled:  -fPIC -fPIE -faggressive-loop-optimizations
// -falign-functions -falign-jumps -falign-labels -falign-loops
// -fassume-phsa -fasynchronous-unwind-tables -fauto-inc-dec
// -fbranch-count-reg -fcaller-saves -fcode-hoisting
// -fcombine-stack-adjustments -fcommon -fcompare-elim -fcprop-registers
// -fcrossjumping -fcse-follow-jumps -fdefer-pop
// -fdelete-null-pointer-checks -fdevirtualize -fdevirtualize-speculatively
// -fdwarf2-cfi-asm -fearly-inlining -feliminate-unused-debug-types
// -fexpensive-optimizations -fforward-propagate -ffp-int-builtin-inexact
// -ffunction-cse -fgcse -fgcse-after-reload -fgcse-lm -fgnu-runtime
// -fgnu-unique -fguess-branch-probability -fhoist-adjacent-loads -fident
// -fif-conversion -fif-conversion2 -findirect-inlining -finline
// -finline-atomics -finline-functions -finline-functions-called-once
// -finline-small-functions -fipa-bit-cp -fipa-cp -fipa-cp-clone -fipa-icf
// -fipa-icf-functions -fipa-icf-variables -fipa-profile -fipa-pure-const
// -fipa-ra -fipa-reference -fipa-reference-addressable -fipa-sra
// -fipa-stack-alignment -fipa-vrp -fira-hoist-pressure
// -fira-share-save-slots -fira-share-spill-slots
// -fisolate-erroneous-paths-dereference -fivopts -fkeep-static-consts
// -fleading-underscore -flifetime-dse -floop-interchange
// -floop-unroll-and-jam -flra-remat -flto-odr-type-merging -fmath-errno
// -fmerge-constants -fmerge-debug-strings -fmove-loop-invariants
// -fomit-frame-pointer -foptimize-sibling-calls -foptimize-strlen
// -fpartial-inlining -fpeel-loops -fpeephole -fpeephole2 -fplt
// -fpredictive-commoning -fprefetch-loop-arrays -free -freg-struct-return
// -freorder-blocks -freorder-functions -frerun-cse-after-loop
// -fsched-critical-path-heuristic -fsched-dep-count-heuristic
// -fsched-group-heuristic -fsched-interblock -fsched-last-insn-heuristic
// -fsched-pressure -fsched-rank-heuristic -fsched-spec
// -fsched-spec-insn-heuristic -fsched-stalled-insns-dep -fschedule-fusion
// -fschedule-insns -fschedule-insns2 -fsection-anchors
// -fsemantic-interposition -fshow-column -fshrink-wrap
// -fshrink-wrap-separate -fsigned-zeros -fsplit-ivs-in-unroller
// -fsplit-loops -fsplit-paths -fsplit-wide-types -fssa-backprop
// -fssa-phiopt -fstack-protector-strong -fstdarg-opt -fstore-merging
// -fstrict-aliasing -fstrict-volatile-bitfields -fsync-libcalls
// -fthread-jumps -ftoplevel-reorder -ftrapping-math -ftree-bit-ccp
// -ftree-builtin-call-dce -ftree-ccp -ftree-ch -ftree-coalesce-vars
// -ftree-copy-prop -ftree-cselim -ftree-dce -ftree-dominator-opts
// -ftree-dse -ftree-forwprop -ftree-fre -ftree-loop-distribute-patterns
// -ftree-loop-distribution -ftree-loop-if-convert -ftree-loop-im
// -ftree-loop-ivcanon -ftree-loop-optimize -ftree-loop-vectorize
// -ftree-parallelize-loops= -ftree-partial-pre -ftree-phiprop -ftree-pre
// -ftree-pta -ftree-reassoc -ftree-scev-cprop -ftree-sink
// -ftree-slp-vectorize -ftree-slsr -ftree-sra -ftree-switch-conversion
// -ftree-tail-merge -ftree-ter -ftree-vrp -funit-at-a-time
// -funswitch-loops -funwind-tables -fverbose-asm
// -fversion-loops-for-strides -fzero-initialized-in-bss
// -mfix-cortex-a53-835769 -mfix-cortex-a53-843419 -mglibc -mlittle-endian
// -momit-leaf-frame-pointer -mpc-relative-literal-loads
 
	.text
	.ident	"GCC: (GNU) 9.2.0"
	.section	.note.GNU-stack,"",@progbits

-Og

gcc -Og -fverbose-asm -o t.s t.c
	.arch armv8-a
	.file	"t.c"
// GNU C17 (GCC) version 9.2.0 (aarch64-unknown-linux-gnu)
//	compiled by GNU C version 9.2.0, GMP version 6.1.2, MPFR version 4.0.2, MPC version 1.1.0, isl version isl-0.21-GMP
 
// GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
// options passed:  t.c -march=armv8-a -mlittle-endian -mabi=lp64
// -auxbase-strip 3 -Og -fverbose-asm
// options enabled:  -fPIC -fPIE -faggressive-loop-optimizations
// -fassume-phsa -fasynchronous-unwind-tables -fauto-inc-dec
// -fcombine-stack-adjustments -fcommon -fcompare-elim -fcprop-registers
// -fdefer-pop -fdelete-null-pointer-checks -fdwarf2-cfi-asm
// -fearly-inlining -feliminate-unused-debug-types -fforward-propagate
// -ffp-int-builtin-inexact -ffunction-cse -fgcse-lm -fgnu-runtime
// -fgnu-unique -fguess-branch-probability -fident -finline
// -finline-atomics -fipa-profile -fipa-pure-const -fipa-reference
// -fipa-reference-addressable -fipa-stack-alignment -fira-hoist-pressure
// -fira-share-save-slots -fira-share-spill-slots -fivopts
// -fkeep-static-consts -fleading-underscore -flifetime-dse
// -flto-odr-type-merging -fmath-errno -fmerge-constants
// -fmerge-debug-strings -fomit-frame-pointer -fpeephole -fplt
// -fprefetch-loop-arrays -freg-struct-return -freorder-blocks
// -fsched-critical-path-heuristic -fsched-dep-count-heuristic
// -fsched-group-heuristic -fsched-interblock -fsched-last-insn-heuristic
// -fsched-pressure -fsched-rank-heuristic -fsched-spec
// -fsched-spec-insn-heuristic -fsched-stalled-insns-dep -fschedule-fusion
// -fsection-anchors -fsemantic-interposition -fshow-column -fshrink-wrap
// -fshrink-wrap-separate -fsigned-zeros -fsplit-ivs-in-unroller
// -fsplit-wide-types -fssa-backprop -fstack-protector-strong -fstdarg-opt
// -fstrict-volatile-bitfields -fsync-libcalls -ftoplevel-reorder
// -ftrapping-math -ftree-builtin-call-dce -ftree-ccp -ftree-ch
// -ftree-coalesce-vars -ftree-copy-prop -ftree-cselim -ftree-dce
// -ftree-dominator-opts -ftree-dse -ftree-forwprop -ftree-fre
// -ftree-loop-if-convert -ftree-loop-im -ftree-loop-ivcanon
// -ftree-loop-optimize -ftree-parallelize-loops= -ftree-phiprop
// -ftree-reassoc -ftree-scev-cprop -ftree-sink -ftree-slsr -ftree-ter
// -funit-at-a-time -funwind-tables -fverbose-asm -fzero-initialized-in-bss
// -mfix-cortex-a53-835769 -mfix-cortex-a53-843419 -mglibc -mlittle-endian
// -momit-leaf-frame-pointer -mpc-relative-literal-loads
 
	.text
	.ident	"GCC: (GNU) 9.2.0"
	.section	.note.GNU-stack,"",@progbits

References
GCC Options – https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html

红米Note7 Pro使用LineageOS 16问题备忘录

红米Note7 Pro使用LineageOS 16过程中遇到了若干问题,经过摸索后问题已解决,这里给自己备忘一下,同时也能方便其他同学少走弯路或一起讨论更好的解决方法。

1. TWRP无法启动
状态:已解决
现象:解除Bootloader锁后,使用fastboot刷入官方TWRP后,TWRP启动卡住。
原因:MIUI系统的userdata分区(包括/data和/sdcard)默认使用了加密的f2fs,官方的TWRP目前不能直接挂载加密的/data和/sdcard,导致recovery系统初始化失败。
修复:TWRP启动卡住时,使用adb shell访问设备,使用命令清除userdata分区并重启:

dd if=/dev/zero of=/dev/block/bootdevice/by-name/userdata bs=1m count=10

2. LineageOS无法启动
状态:已解决
现象:刷入LineageOS后,首次启动卡在系统启动动画界面。
原因:LineageOS(device violet)对userdata分区的文件系统默认为f2fs,并且启用了加密,不匹配导致了/data无法读写。
修复:修复方案可能有两种:
1. 使用TWRP重建userdata分区的文件系统为f2fs并且启用加密。
2. 使用TWRP重建userdata分区为f2fs但关闭加密,修改LineageOS的/vendor/etc/fstab.qcom同样关闭加密。

方案1没有验证过,我直接采用了方案2,具体步骤为:
1. TWRP中“清除数据”,“高级选项”,“变更文件系统”,将data分区初始化为f2fs。
2. TWRP中挂载vendor分区,修改/vendor/etc/fstab.qcom的userdata挂载配置。

-/dev/block/bootdevice/by-name/userdata                  /data                    f2fs    noatime,nosuid,nodev,discard,reserve_root=32768,resgid=1065,fsync_mode=nobarrier    latemount,wait,check,fileencryption=ice,wrappedkey,reservedsize=128M
+/dev/block/bootdevice/by-name/userdata                  /data                    f2fs    noatime,nosuid,nodev,discard,reserve_root=32768,resgid=1065,fsync_mode=nobarrier    latemount,wait,check,wrappedkey,reservedsize=128M

3. LineageOS、TWRP相互干扰启动
状态:已解决
现象:刷入LineageOS后TWRP无法启动
原因:violet设备将内核的devicetree配置放在独立的分区dtbo中,官方TWRP的内核是与MIUI同源的,而与LineageOS不同,所以在刷入LineageOS的dtbo.img后,TWRP内核就没有匹配的devicetree配置。
修复:使用官方TWRP时,要先刷入MIUI线刷包中的dtbo.img;使用LineageOS系统时,要先刷入LineageOS线刷包中的dtbo.img。

4. LineageOS系统普通App调用su(root)失败
状态:已解决
现象:刷入su addon后,在普通App(例如terminal)中调用su命令有段错误。
原因:su命令中有map操作,但在SELinux的配置中未允许普通App(untrusted_app)的map访问。
修复:解决该问题需要修改LineageOS的源代码,详见补丁,争取推到上游社区中。

5. 听筒输出的通话中,对方听到回音
状态:已解决
现象:在使用听筒输出声音的通话中,对方有明显的回音干扰。
原因:ro.vendor.audio.sdk.fluencetype配置为none。
修复:解决该问题有两种方案:1. 直接编辑/vendor中的build.prop文件。2. 修改LineageOS源代码。详见补丁

6. VoLTE视频无法连接
状态:已解决
现象:使用VoLTE通话过程中,视频信道无法正常建立连接。
原因:LineageOS默认的apns-conf.xml中不包含中国三大运营商的ims类型APN配置。
修复:手工创建一个新的APN,名称为IMS,APN为:ims,APN类型为:ims。

修复上述问题的预编译版
下载:http://hev.cc/sftp/lineage/

boot.img     // 内核
dtbo.img     // DeviceTree
recovery.img // TWRP (已适配LineageOS的dtbo.img)
system.img   // 系统
vbmeta.img   // Verify-Boot元数据
vendor.img   // Vendor

安装方法:
1. 使用fastboot刷入对应分区。
2. 启动至recovery,清除cache,清除或重建Data分区,文件系统格式为f2fs。

Over!