欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

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

发布时间:2025/4/16 编程问答 33 豆豆
生活随笔 收集整理的这篇文章主要介绍了 一种通过U盘热插拔的升级方法 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

点击打开链接

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

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

  驱动文件如下 

[plain] view plaincopy
  • #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

    [plain] view plaincopy
  • #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文件如下

    [plain] view plaincopy
  • 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服务,由于需要可执行权限,需要在前面加上

    [plain] view plaincopy
  • chmod 0777  /system/bin/update  
  • [plain] view plaincopy
  • service loaddriver /system/bin/update    
  •        class main    
  •        user root    
  •        group root    
  •        oneshot    
  • 当然,还必须保证驱动在该服务起来之前加载,否则该服务会由于打开节点错误而退出。

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

    [plain] view plaincopy
  • mount -o remount /system  
  • touch /system/dddd  
  • mkdir /system/gggg  
  • insmod /system/wwww.ko  
  • cp /system/update.ko /system/  
  • reboot  

  • 总结

    以上是生活随笔为你收集整理的一种通过U盘热插拔的升级方法的全部内容,希望文章能够帮你解决所遇到的问题。

    如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。