openwrt在MT7620a中实现了自动挂载U盘或硬盘,
但是不能自动卸载,还得手动umount,
请问各大神如何实现一键umonut弹出u盘?
离线
/etc/mdev.conf
mmcblk([0-9]+)p([0-9]+) 0:0 660 */sbin/automount.sh $MDEV X${ACTION}
mmcblk([0-9]+) 0:0 660 */sbin/automount.sh $MDEV X${ACTION}
sd([a-z]+)([0-9]+) 0:0 660 */sbin/automount.sh $MDEV X${ACTION}
sd([a-z]+) 0:0 660 */sbin/automount.sh $MDEV X${ACTION}
/sbin/automount.sh
#! /bin/sh
# debugging message
#echo "MDEV=$1 : ACTION=$2 : SUBSYSTEM=$SUBSYSTEM : DEVPATH=$DEVPATH : DEVNAME=$DEVNAME" >> /dev/consoleif [ "$1" == "" ]; then
echo "parameter is none" > /tmp/error.txt
exit 1
fiMNT=$1
#if [ $(echo $1 | grep mmcblk) ]; then
# if [ $(echo $1 | grep p[25]) ]; then
# MNT=sdcard2
# else
# MNT=sdcard
# fi
#elif [ $(echo $1 | grep sd) ]; then
# if [ $(echo $1 | grep p[25]) ]; then
# MNT=nandcard2
# else
# MNT=nandcard
# fi
#fi# there is no ACTION, it is for initial population
if [ "$2" = "X" ]; then
mounted=`mount | grep $1 | wc -l`
if [ $mounted -ge 1 ]; then
# mounted, assume the ACTION is remove
#ACT=Xremove
# only set add for initial population
ACT=Xadd
else
# not mounted, assume the ACTION is add
ACT=Xadd
fi
else
ACT=$2
fiif [ "$ACT" = "Xremove" ]; then
# umount the device
echo "$ACT /mnt/udisk" >> /tmp/mdev.log
if ! umount -l "/mnt/udisk"; then
exit 1
else
rm -f "/mnt/udisk"
echo "[Umount FS]: /dev/$1 -X-> /mnt/udisk" > /dev/console
fiif ! rmdir "/mnt/udisk"; then
exit 1
fi
else
# mount the device
mounted=`mount | grep $1 | wc -l`
#echo "par=$1,mounted=$mounted,MNT=$MNT" > /dev/console
if [ $mounted -ge 1 ]; then
#echo "device $1 is already mounted" > /dev/console
exit 0
fiif ! mkdir -p "/mnt/udisk"; then
exit 1
fiif [ $(echo $1 | grep mtd) ]; then
if mount -t jffs2 "/dev/$1" "/mnt/udisk"; then
echo "[Mount JFFS2]: /dev/$1 --> /mnt/udisk" > /dev/console
echo "$ACT /mnt/udisk" >> /tmp/mdev.log
elif mount -t yaffs2 -o"inband-tags" "/dev/$1" "/mnt/$1"; then
echo "[Mount YAFFS2]: /dev/$1 --> /mnt/udisk" > /dev/console
echo "$ACT /mnt/$1" >> /tmp/mdev.log
elif mount -t ubifs "/dev/$1" "/mnt/udisk"; then
echo "[Mount UBIFS]: /dev/$1 --> /mnt/udisk" > /dev/console
echo "$ACT /mnt/udisk" >> /tmp/mdev.log
else
# failed to mount, clean up mountpoint
if ! rmdir "/mnt/udisk"; then
exit 1
fi
fi
else
# try vfat only
if mount -t vfat -o noatime,shortname=mixed,utf8 "/dev/$1" "/mnt/udisk"; then
# ln -s /mnt/$1 /mnt/udisk
echo "[Mount VFAT]: /dev/$1 --> /mnt/udisk" > /dev/console
echo "$ACT /mnt/udisk" >> /tmp/mdev.log
else
# failed to mount, clean up mountpoint
if ! rmdir "/mnt/udisk"; then
exit 1
fi
exit 1
fi
fi
fi
上面是我的rootfs里面的 /etc/mdev.conf, /sbin/automount.sh,
在新唐nuc972, n32926, 全志V3s均可以正常卸载U盘和TF卡,
仅供参考。
离线
这个脚本是什么情况下卸载呢?是拔掉U盘就自动卸载么?
离线
这个脚本是什么情况下卸载呢?是拔掉U盘就自动卸载么?
对,拔出U盘后台执行的 /sbin/mdev 会执行 /sbin/automount.sh 的 umount 命令:
if [ "$ACT" = "Xremove" ]; then
# umount the device
echo "$ACT /mnt/udisk" >> /tmp/mdev.log
if ! umount -l "/mnt/udisk"; then
exit 1
else
rm -f "/mnt/udisk"
echo "[Umount FS]: /dev/$1 -X-> /mnt/udisk" > /dev/console
fi
if ! rmdir "/mnt/udisk"; then
exit 1
fi
widora neo是拔出U盘是可以正常卸载的。
离线
我现在想添加一个按键,当自动挂载上以后按下按键就umount,但是我现在不明白的是当按键按下触发异常以后是调用哪些路径下的脚本
离线
你想通过按下按键触发自己写的类式 umount.sh 脚本?
离线
嗯嗯!对!我参考了一键复位来做的,一键复位中修改了DTS中MT7620a.dts文件来修改GPIO口:(下面的S2用来复位,准备用S3来做一键U盘弹出)
gpio-keys-polled {
compatible = "gpio-keys";
#address-cells = <1>;
#size-cells = <0>;
poll-interval = <20>;
s2 {
label = "reset";
gpios = <&gpio0 1 1>;
linux,code = <0x198>;
};
s3 {
label = "S3";
gpios = <&gpio0 2 1>;
linux,code = <0x101>;
};
};
然后cd /etc/rc.button
vi reset 如下:
#!/bin/sh
[ "${ACTION}" = "released" ] || exit 0
. /lib/functions.sh
logger "$BUTTON pressed for $SEEN seconds"
if [ "$SEEN" -lt 1 ]
then
echo "REBOOT" > /dev/console
sync
reboot
elif [ "$SEEN" -gt 5 ]
then
echo "FACTORY RESET" > /dev/console
jffs2reset -y && reboot &
fi
return 0
这样就可以实现一键复位了,可是一键弹出U盘就不知该如何下手了
离线
嗯嗯!对!我参考了一键复位来做的,一键复位中修改了DTS中MT7620a.dts文件来修改GPIO口:(下面的S2用来复位,准备用S3来做一键U盘弹出)
gpio-keys-polled {
compatible = "gpio-keys";
#address-cells = <1>;
#size-cells = <0>;
poll-interval = <20>;
s2 {
label = "reset";
gpios = <&gpio0 1 1>;
linux,code = <0x198>;
};
s3 {
label = "S3";
gpios = <&gpio0 2 1>;
linux,code = <0x101>;
};
};然后cd /etc/rc.button
vi reset 如下:#!/bin/sh
[ "${ACTION}" = "released" ] || exit 0
. /lib/functions.sh
logger "$BUTTON pressed for $SEEN seconds"
if [ "$SEEN" -lt 1 ]
then
echo "REBOOT" > /dev/console
sync
reboot
elif [ "$SEEN" -gt 5 ]
then
echo "FACTORY RESET" > /dev/console
jffs2reset -y && reboot &
fireturn 0
这样就可以实现一键复位了,可是一键弹出U盘就不知该如何下手了
这个问题不大。
umount.sh
umount /mnt/udisk
/etc/rc.button 里面调用 umount.sh 即可。
一般在嵌入式系统只挂载U盘里面的第一个磁盘,而且是挂载到同一个文件夹。
离线
在/etc/rc.button目录下有如下文件:
failsafe power reset rfkill
我是要在/etc/rc.button目录下建一个文件调用umount.sh 呢?还是在上面的哪一个文件里调用umount.sh 按键按下系统是怎么找到这个脚本文件的呢?这点我一直没想明白
离线
在/etc/rc.button目录下有如下文件:
failsafe power reset rfkill
我是要在/etc/rc.button目录下建一个文件调用umount.sh 呢?还是在上面的哪一个文件里调用umount.sh 按键按下系统是怎么找到这个脚本文件的呢?这点我一直没想明白
umount.sh可以放文件系统任意地方, 比如/sbin/umount.sh
执行的时候用绝对目录就可以了。
/etc/rc.button 以前没有这么用过,不是看到你说,我都不知道能这么用。
离线
涨见识了: Button按键的检测
在OpenWRT中,按键的检测也是通过Hotplug机制来实现的。
它首先写了一个内核模块:gpio_button_hotplug, 用于监听按键,有中断和 poll 两种方式。然后在发出事件的同时, 将记录并计算得出的两次按键时间差也作为 uevent 变量发出来。这样在用户空间收到这个 uevent事件时就知道该次按键按下了多长时间。
hotplug.json中有描述, 如果 uevent 中含有BUTTON 字符串, 而且SUBSYSTEM 为 "button", 则执行/etc/rc.button/下的 %BUTTON%脚本来处理。
细节描述如下: 当按键时,则触发button_hotplug_event函数(gpio-button-hotplug.c)
调用button_hotplug_create_event产生uevent事件,调用button_hotplug_fill_event填充事件(JSON格式),并最终调用button_hotplug_work发出uevent广播。
上述广播,被守护进程procd中的hotplug_handler (procd/plug/hotplug.c) 收到,并根据etc/hotplug.json中预先定义的JSON内容匹配条件,定位到对应的执行函数,具体如下所示,命中了两个条目,所以会依次执行这两个条目队列中的操作函数:
[ "if",
[ "and",
[ "has", "BUTTON" ],
[ "eq", "SUBSYSTEM", "button" ],
],
[ "exec", "/etc/rc.button/%BUTTON%" ]
],
和
[ "if",
[ "eq", "SUBSYSTEM",
[ "net", "input", "usb", "ieee1394", "block", "atm", "zaptel", "tty", "button" ]
],
[ "exec", "/sbin/hotplug-call", "%SUBSYSTEM%" ]
],
在rc.button目录下,我们定义了reset按钮的执行脚本:root@OpenWrt:/etc/rc.button# cat reset
#!/bin/sh[ "${ACTION}" = "released" ] || exit 0
. /lib/functions.sh
logger "$BUTTON pressed for $SEEN seconds"
if [ "$SEEN" -lt 1 ]
then
echo "REBOOT" > /dev/console
sync
reboot
elif [ "$SEEN" -gt 5 ]
then
echo "FACTORY RESET" > /dev/console
jffs2reset -y && reboot &
fi
从脚本中我们可以清晰地看出,当按键时间小于1s时,执行reboot重启命令,当按键时间超过5s时,执行恢复出厂设置并重启命令。第二个条目,由于默认情况下没有在/etc/hotplug.d目录下创建button子目录,因此执行为空。
使用 export DBGLVL=10; procd -h /etc/hotplug.json 截获一些打印信息看看:
root@OpenWrt:/etc/rc.button# export DBGLVL=10; procd -h /etc/hotplug.json
procd:hotplug_handler_debug(404): {{"HOME":"\/","PATH":"\/sbin:\/bin:\/usr\/sbin:\/usr\/bin","SUBSYSTEM":"button","ACTION":"pressed","BUTTON":"reset","SEEN":"42949450","SEQNUM":"331"}}
procd: rule_handle_command(355): Command: exec
procd: rule_handle_command(357): /etc/rc.button/reset
procd: rule_handle_command(358):
procd: rule_handle_command(360): Message:
procd: rule_handle_command(362): HOME=/
procd: rule_handle_command(362): PATH=/sbin:/bin:/usr/sbin:/usr/bin
procd: rule_handle_command(362): SUBSYSTEM=button
procd: rule_handle_command(362): ACTION=pressed
procd: rule_handle_command(362): BUTTON=reset
procd: rule_handle_command(362): SEEN=42949450
procd: rule_handle_command(362): SEQNUM=331
procd: rule_handle_command(363):
procd: queue_next(281): Launched hotplug exec instance, pid=987
procd: rule_handle_command(355): Command: exec
procd: rule_handle_command(357): /sbin/hotplug-call
procd: rule_handle_command(357): button
procd: rule_handle_command(358):
procd: rule_handle_command(360): Message:
procd: rule_handle_command(362): HOME=/
procd: rule_handle_command(362): PATH=/sbin:/bin:/usr/sbin:/usr/bin
procd: rule_handle_command(362): SUBSYSTEM=button
procd: rule_handle_command(362): ACTION=pressed
procd: rule_handle_command(362): BUTTON=reset
procd: rule_handle_command(362): SEEN=42949450
procd: rule_handle_command(362): SEQNUM=331
procd: rule_handle_command(363):
procd: queue_proc_cb(286): Finished hotplug exec instance, pid=987
...
离线
大哥你在贴子上的回复我看到了,我非常感谢你的热心帮助,,不过有点没太明白,具体疑问如下:我在DTS中定义了
就相当于给
BUTTON赋值为“reset”所以就去执行/etc/rc.button/下的reset里的脚本文件?如果在DTS里改成
是不是就去执行/etc/rc.button/下的hello(当然前提得有这个文件),你看我的理解对么?
离线
我在DTS中定义了:
label = "reset";
gpio-keys-polled {
compatible = "gpio-keys";
#address-cells = <1>;
#size-cells = <0>;
poll-interval = <20>;
s2 {
label = "reset";
gpios = <&gpio0 1 1>;
linux,code = <0x198>;
};
s3 {
label = "S3";
gpios = <&gpio0 2 1>;
linux,code = <0x101>;
};
};
就相当于给
hotplug.json中有描述, 如果 uevent 中含有BUTTON 字符串, 而且SUBSYSTEM 为 "button", 则执行/etc/rc.button/下的 %BUTTON%脚本来处理。
BUTTON赋值为“reset”所以就去执行/etc/rc.button/下的reset里的脚本文件?如果在DTS里改成
label = "hello";
是不是就去执行/etc/rc.button/下的hello(当然前提得有这个文件),你看我的理解对么?
离线
根据看到的资料,我觉得是这样,不过以前没试过。有空拿出我的widora neo出来试一试
离线
不对!好像不是这样的,我在DTS中改了 label = "hello";
gpio-keys-polled {
compatible = "gpio-keys";
#address-cells = <1>;
#size-cells = <0>;
poll-interval = <20>;
s2 {
label = "hello";
gpios = <&gpio0 1 1>;
linux,code = <0x198>;
};
s3 {
label = "S3";
gpios = <&gpio0 2 1>;
linux,code = <0x101>;
};
};
编译后固件里/etc/rc.button/ 没有hello这个脚本文件还是reset ,an按下按键依然可以复位,所以好像不是上面描述那样的
failsafe power reset rfkill
离线
我的意思是说经过我刚刚的改动 ,按之前的理解
hotplug.json中有描述, 如果 uevent 中含有BUTTON 字符串, 而且SUBSYSTEM 为 "button", 则执行/etc/rc.button/下的 %BUTTON%脚本来处理。
BUTTON赋值为“hello”了所以就去执行/etc/rc.button/下的hello脚本文件,但是/etc/rc.button/下没有hello这个文件,所以应该没有任何反应才对,但实际上板子却复位了
离线
@晕哥
这完全就是一个伪需求,而且实现也是个掩耳盗铃的行为。
当内核检测到U盘被拔出时,设备已经断开,这时候再umount已经没了意义。
真正有意义的是绑定到按键上,按一下或长按多少秒再扫行umount行为,执行完,亮个灯,如果执行失败,就闪灯这种,才有意义 。
离线