一种通过U盘热插拔的升级方法

来源:互联网 发布:h5能打开淘宝app吗 编辑:程序博客网 时间:2024/06/16 14:37

点击打开链接

在调试Android驱动中,有时会遇到无法使用adb的情况,如果能通过U盘的热插拔能运行shell命令,就可解决adb无法使用的困境。

         基本思路是是安装一个驱动,该驱动负责监测usb的插拔事件,然后通过异步通知发给上层的应用,应用通过读取u盘中的脚本,通过system运行脚本里面的函数。

  驱动文件如下 

[plain] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #include <linux/module.h>  
  2. #include <linux/usb.h>  
  3. #include <linux/miscdevice.h>  
  4.   
  5. #define DEVICE_NAME "usbupdate"  
  6. static struct fasync_struct *usbupdate_async_queue;  
  7. static struct miscdevice usbupdate_dev;  
  8.   
  9.   
  10. int usbupdate_open(struct inode *node, struct file *filp)  
  11. {  
  12.     return 0;  
  13. }  
  14.   
  15. int usbupdate_fasync(int fd, struct file *filp, int mode)  
  16. {  
  17.     return fasync_helper(fd, filp, mode, &usbupdate_async_queue);  
  18. }  
  19.   
  20. int usbupdate_release(struct inode *node, struct file *filp)  
  21. {  
  22.     usbupdate_fasync(-1, filp, 0);  
  23.     return 0;  
  24. }  
  25.   
  26. static struct file_operations usbupdate_dev_fops={  
  27.     .owner          = THIS_MODULE,  
  28.     .open           = usbupdate_open,  
  29.     .fasync         = usbupdate_fasync,  
  30.     .release        = usbupdate_release,  
  31. };  
  32.   
  33.   
  34. static struct miscdevice usbupdate_dev = {  
  35.     .minor          = MISC_DYNAMIC_MINOR,  
  36.     .name           = DEVICE_NAME,  
  37.     .fops           = &usbupdate_dev_fops,  
  38. };  
  39.   
  40.   
  41. static int usbupdate_notify(struct notifier_block *self, unsigned long action, void *dev)  
  42. {  
  43.     switch (action) {  
  44.     case USB_DEVICE_ADD:  
  45.             printk("usb device add\n");  
  46.             kill_fasync(&usbupdate_async_queue, SIGIO, POLL_IN);  
  47.         break;  
  48.     case USB_DEVICE_REMOVE:  
  49.             printk("usb device remove\n");  
  50.         break;  
  51.     }  
  52.     return NOTIFY_OK;  
  53. }  
  54.   
  55. static struct notifier_block usbupdate_nb = {  
  56.     .notifier_call =usbupdate_notify,  
  57. };  
  58.   
  59. static int __init update_init(void)   
  60. {  
  61.     int ret;  
  62.     usb_register_notify(&usbupdate_nb);  
  63.     ret = misc_register(&usbupdate_dev);  
  64.     printk("%s\n",__func__);  
  65.     return ret;  
  66. }  
  67.   
  68. static void __exit update_exit(void)  
  69. {  
  70.     misc_deregister(&usbupdate_dev);  
  71.     printk("%s\n",__func__);  
  72. }  
  73.   
  74. module_init(update_init);  
  75. module_exit(update_exit);  
  76.   
  77. MODULE_LICENSE("GPL");  
  78. MODULE_AUTHOR("www");  


应用层的文件为update.c

[plain] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #include <stdio.h>  
  2. #include <stdlib.h>    
  3. #include <sys/types.h>  
  4. #include <sys/wait.h>  
  5. #include <sys/stat.h>  
  6. #include <sys/select.h>  
  7. #include <fcntl.h>  
  8. #include <unistd.h>  
  9. #include <signal.h>  
  10. #include <string.h>  
  11. #include <cutils/log.h>   
  12.   
  13. #define DEVICE_POINT "/dev/usbupdate"  
  14. #define LOG_TAG  "usbupdate"  
  15. #define filename "/mnt/udisk/update.sh" //升级脚本的路径,不同机型的u盘挂载路径不同,需根据机型修改  
  16.   
  17.   
  18. int usb_update_state=0;  
  19. int fd;   
  20. int status;  
  21. void systemstatus(int status){  
  22.     if (-1 == status) {    
  23.         SLOGE("system error!");    
  24.     }    
  25.     else  {    
  26.         SLOGE("exit status value = [0x%x]\n", status);    
  27.         if (WIFEXITED(status)){    
  28.             if (0 == WEXITSTATUS(status)){    
  29.                 SLOGE("run shell script successfully.\n");    
  30.             }    
  31.             else{    
  32.                 SLOGE("run shell script fail, script exit code: %d\n", WEXITSTATUS(status));    
  33.             }    
  34.         }    
  35.         else{    
  36.             SLOGE("exit status = [%d]\n", WEXITSTATUS(status));    
  37.         }    
  38.     }     
  39. }   
  40.   
  41. int read_file(void)  
  42. {  
  43.    FILE *fp;  
  44.    char str[1024];  
  45.    char *buf;  
  46.    buf=(char *)malloc(1024);  
  47.    if(buf==NULL){  
  48.        SLOGE("malloc memory err\n");  
  49.        return -1;  
  50.    }  
  51.    SLOGE("malloc memory ok\n");  
  52.    fp=fopen(filename,"r");  
  53.    if(fp==NULL){  
  54.         SLOGE("open err!\n");  
  55.         return -1;  
  56.    }  
  57.    SLOGE("open ok!\n");  
  58.    while(!feof(fp)){  
  59.    if(fgets(str,1024,fp)==NULL)  
  60.       break;  
  61.         SLOGE("the msg is %s and the length is %d %d\n",str,strlen(str),sizeof(str));  
  62.         status=system(str);  
  63.         systemstatus(status);     
  64.    }  
  65.    fclose(fp);  
  66.    return 0;  
  67. }  
  68.   
  69.   
  70.   
  71. void sig_handler(int sig)  
  72. {  
  73.     SLOGE("%s\n", __FUNCTION__);  
  74.     read_file();  
  75.     usb_update_state=1;  
  76. }  
  77.   
  78. void open_usb_update_point(void)  
  79. {     
  80.     int f_flags;  
  81.     fd=open(DEVICE_POINT, O_RDWR);  
  82.     if(fd < 0){  
  83.         SLOGE("open");  
  84.         return;  
  85.     }  
  86.     signal(SIGIO, sig_handler);  
  87.     fcntl(fd, F_SETOWN, getpid());  
  88.     f_flags = fcntl(fd, F_GETFL);  
  89.     fcntl(fd, F_SETFL, FASYNC | f_flags);  
  90. }  
  91.   
  92. int main(int argc,char **argv)  
  93. {  
  94.     open_usb_update_point();  
  95.     while(1){  
  96.         sleep(1);  
  97.     //  if(usb_update_state)  
  98.     //      break;  
  99.           
  100.     }  
  101.     SLOGE("usb update finish\n");  
  102.     close(fd);  
  103.     return 0;  
  104. }  

相应的Android.mk文件如下

[plain] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. LOCAL_PATH := $(call my-dir)  
  2. include $(CLEAR_VARS)  
  3. LOCAL_MODULE_TAGS := optional  
  4. LOCAL_PRELINK_MODULE := false  
  5. LOCAL_SHARED_LIBRARIES := liblog  
  6. LOCAL_MODULE := update  
  7. LOCAL_SRC_FILES := $(call all-subdir-c-files)  
  8. include $(BUILD_EXECUTABLE)  

在Android源码的根路径,source build/envsetup.sh,lunch选择具体机型,通过mmm -B 应用程序路径编译该应用程序成可执行文件,并丢进/system/bin/。

在init.rc通过如下服务启动update服务,由于需要可执行权限,需要在前面加上

[plain] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. chmod 0777  /system/bin/update  
[plain] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. service loaddriver /system/bin/update    
  2.        class main    
  3.        user root    
  4.        group root    
  5.        oneshot    

当然,还必须保证驱动在该服务起来之前加载,否则该服务会由于打开节点错误而退出。

然后将升级脚本拷贝到u盘,接上u盘,就可运行u盘上的脚本了。升级脚本示例如下

[plain] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. mount -o remount /system  
  2. touch /system/dddd  
  3. mkdir /system/gggg  
  4. insmod /system/wwww.ko  
  5. cp /system/update.ko /system/  
  6. reboot  

原创粉丝点击