一种通过U盘热插拔的升级方法
来源:互联网 发布:h5能打开淘宝app吗 编辑:程序博客网 时间:2024/06/16 14:37
点击打开链接
在调试Android驱动中,有时会遇到无法使用adb的情况,如果能通过U盘的热插拔能运行shell命令,就可解决adb无法使用的困境。
基本思路是是安装一个驱动,该驱动负责监测usb的插拔事件,然后通过异步通知发给上层的应用,应用通过读取u盘中的脚本,通过system运行脚本里面的函数。
驱动文件如下
- #include <linux/module.h>
- #include <linux/usb.h>
- #include <linux/miscdevice.h>
-
- #define DEVICE_NAME "usbupdate"
- static struct fasync_struct *usbupdate_async_queue;
- static struct miscdevice usbupdate_dev;
-
-
- int usbupdate_open(struct inode *node, struct file *filp)
- {
- return 0;
- }
-
- int usbupdate_fasync(int fd, struct file *filp, int mode)
- {
- return fasync_helper(fd, filp, mode, &usbupdate_async_queue);
- }
-
- int usbupdate_release(struct inode *node, struct file *filp)
- {
- usbupdate_fasync(-1, filp, 0);
- return 0;
- }
-
- static struct file_operations usbupdate_dev_fops={
- .owner = THIS_MODULE,
- .open = usbupdate_open,
- .fasync = usbupdate_fasync,
- .release = usbupdate_release,
- };
-
-
- static struct miscdevice usbupdate_dev = {
- .minor = MISC_DYNAMIC_MINOR,
- .name = DEVICE_NAME,
- .fops = &usbupdate_dev_fops,
- };
-
-
- static int usbupdate_notify(struct notifier_block *self, unsigned long action, void *dev)
- {
- switch (action) {
- case USB_DEVICE_ADD:
- printk("usb device add\n");
- kill_fasync(&usbupdate_async_queue, SIGIO, POLL_IN);
- break;
- case USB_DEVICE_REMOVE:
- printk("usb device remove\n");
- break;
- }
- return NOTIFY_OK;
- }
-
- static struct notifier_block usbupdate_nb = {
- .notifier_call =usbupdate_notify,
- };
-
- static int __init update_init(void)
- {
- int ret;
- usb_register_notify(&usbupdate_nb);
- ret = misc_register(&usbupdate_dev);
- printk("%s\n",__func__);
- return ret;
- }
-
- static void __exit update_exit(void)
- {
- misc_deregister(&usbupdate_dev);
- printk("%s\n",__func__);
- }
-
- module_init(update_init);
- module_exit(update_exit);
-
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("www");
应用层的文件为update.c
- #include <stdio.h>
- #include <stdlib.h>
- #include <sys/types.h>
- #include <sys/wait.h>
- #include <sys/stat.h>
- #include <sys/select.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <signal.h>
- #include <string.h>
- #include <cutils/log.h>
-
- #define DEVICE_POINT "/dev/usbupdate"
- #define LOG_TAG "usbupdate"
- #define filename "/mnt/udisk/update.sh" //升级脚本的路径,不同机型的u盘挂载路径不同,需根据机型修改
-
-
- int usb_update_state=0;
- int fd;
- int status;
- void systemstatus(int status){
- if (-1 == status) {
- SLOGE("system error!");
- }
- else {
- SLOGE("exit status value = [0x%x]\n", status);
- if (WIFEXITED(status)){
- if (0 == WEXITSTATUS(status)){
- SLOGE("run shell script successfully.\n");
- }
- else{
- SLOGE("run shell script fail, script exit code: %d\n", WEXITSTATUS(status));
- }
- }
- else{
- SLOGE("exit status = [%d]\n", WEXITSTATUS(status));
- }
- }
- }
-
- int read_file(void)
- {
- FILE *fp;
- char str[1024];
- char *buf;
- buf=(char *)malloc(1024);
- if(buf==NULL){
- SLOGE("malloc memory err\n");
- return -1;
- }
- SLOGE("malloc memory ok\n");
- fp=fopen(filename,"r");
- if(fp==NULL){
- SLOGE("open err!\n");
- return -1;
- }
- SLOGE("open ok!\n");
- while(!feof(fp)){
- if(fgets(str,1024,fp)==NULL)
- break;
- SLOGE("the msg is %s and the length is %d %d\n",str,strlen(str),sizeof(str));
- status=system(str);
- systemstatus(status);
- }
- fclose(fp);
- return 0;
- }
-
-
-
- void sig_handler(int sig)
- {
- SLOGE("%s\n", __FUNCTION__);
- read_file();
- usb_update_state=1;
- }
-
- void open_usb_update_point(void)
- {
- int f_flags;
- fd=open(DEVICE_POINT, O_RDWR);
- if(fd < 0){
- SLOGE("open");
- return;
- }
- signal(SIGIO, sig_handler);
- fcntl(fd, F_SETOWN, getpid());
- f_flags = fcntl(fd, F_GETFL);
- fcntl(fd, F_SETFL, FASYNC | f_flags);
- }
-
- int main(int argc,char **argv)
- {
- open_usb_update_point();
- while(1){
- sleep(1);
- // if(usb_update_state)
- // break;
-
- }
- SLOGE("usb update finish\n");
- close(fd);
- return 0;
- }
相应的Android.mk文件如下- LOCAL_PATH := $(call my-dir)
- include $(CLEAR_VARS)
- LOCAL_MODULE_TAGS := optional
- LOCAL_PRELINK_MODULE := false
- LOCAL_SHARED_LIBRARIES := liblog
- LOCAL_MODULE := update
- LOCAL_SRC_FILES := $(call all-subdir-c-files)
- include $(BUILD_EXECUTABLE)
在Android源码的根路径,source build/envsetup.sh,lunch选择具体机型,通过mmm -B 应用程序路径编译该应用程序成可执行文件,并丢进/system/bin/。
在init.rc通过如下服务启动update服务,由于需要可执行权限,需要在前面加上
- chmod 0777 /system/bin/update
- service loaddriver /system/bin/update
- class main
- user root
- group root
- oneshot
当然,还必须保证驱动在该服务起来之前加载,否则该服务会由于打开节点错误而退出。
然后将升级脚本拷贝到u盘,接上u盘,就可运行u盘上的脚本了。升级脚本示例如下
- mount -o remount /system
- touch /system/dddd
- mkdir /system/gggg
- insmod /system/wwww.ko
- cp /system/update.ko /system/
- reboot