生活随笔
收集整理的这篇文章主要介绍了
一种通过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盘热插拔的升级方法的全部内容,希望文章能够帮你解决所遇到的问题。
如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。