生活随笔
收集整理的這篇文章主要介紹了
一种通过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盘热插拔的升级方法的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。