本文共 5440 字,大约阅读时间需要 18 分钟。
2012-03-09 15:13 371人阅读 (0)在Linux的应用平台上,很多时候我们需要用到从SD卡读数据来使用,比如升级触摸屏固件,比如载入调试文本等,都需要用到Linux的文件系统来操作。通过举一个实例来说明VFS FILE操作细节,即在ADB中通过echo 到DEVICE_ATTR的store来升级TP固件,相关升级函数可以参见博文。
(1)store属性函数
static ssize_t melfas_fwupdate_store(struct device *dev,struct device_attribute *attr,const char *buf, size_t count){ int UpResult; mt65xx_eint_mask(CUST_EINT_TOUCH_PANEL_NUM);printk("run here \r\n"); UpResult = ms6000_firmware_upgrade_from_TCard(); //T卡升级主函数 if(UpResult== MS6000_RET_SUCCESS){ printk("MFS6000 DOWNLOAD SUCCESS \r\n"); msleep(100); } else mfs6000_print_fail_result(UpResult); i2c_client->addr = MS6000_8BIT_I2CADDR; mt_set_gpio_mode(GPIO_I2C0_SCA_PIN, GPIO_I2C0_SCA_PIN_M_SCL); mt_set_gpio_mode(GPIO_I2C0_SDA_PIN, GPIO_I2C0_SDA_PIN_M_SDA); mt65xx_eint_unmask(CUST_EINT_TOUCH_PANEL_NUM); //恢复中断和I2C脚的使用 return count;}
(2)从T卡读文件并处理
static int ms6000_firmware_upgrade_from_TCard(){ unsigned char NewFwVersion,OldFwVersion; UINT16 rdlen; //实际读入内存的文件长度 loff_t file_size; //文件大小 UINT8 *buf = NULL; //分配的内存指针 struct file *fp = NULL; struct inode *inode = NULL; int ret = MS6000_RET_FILE_ACCESS_FAILED; mm_segment_t old_fs; const struct cred *old_cred; struct cred *override_cred; override_cred = prepare_creds(); if (!override_cred) return -ENOMEM; override_cred->fsuid = 0; override_cred->fsgid = 0; old_cred = (struct cred *)override_creds(override_cred); //权限属性 old_fs = get_fs(); set_fs(KERNEL_DS); //权限属性 if(mfs_i2c_read_single_reg(0x21,&OldFwVersion) == true){ NewFwVersion = ms6000_GetLibVer(); //从T卡中读文件,并取出存于特定字节的版本号值 printk("mfs6000 NewFwVersionis 0x%x,OldFwVersion is 0x%x \r\n",NewFwVersion,OldFwVersion); } i2c_client->addr = MS6000_8BIT_DOWNLOAD_ADDR; if(1NewFwVersion != OldFwVersion){ fp = filp_open("/mnt/sdcard/MCH_U5(S)_R01_VF6.bin", O_RDONLY, 0); //载入BIN格式的固件 if (IS_ERR(fp)) { printk("ERROR opening file \r\n"); return MS6000_RET_OPENFILE_ERROR; } else { if (!(fp->f_op)) { printk("File has no file operations registered!\r\n"); filp_close(fp, NULL); return MS6000_RET_OPENFILE_ERROR; } if (!fp->f_op->read) { printk(" File has no READ operations registered!\r\n"); filp_close(fp, NULL); return MS6000_RET_OPENFILE_ERROR; } } inode = fp->f_dentry->d_inode; file_size = inode->i_size; buf = (UINT8 *)kmalloc(file_size, GFP_KERNEL); if(buf < 0) return -ENOMEM; rdlen = vfs_read(fp, buf, file_size, &(fp->f_pos)); printk("start download, file_size is %d,rdlen is %d\r\n",file_size,rdlen); mtk_wdt_disable(); ret = ms6000_download(buf,rdlen); //升级主函数参见文章头部博文 mtk_wdt_get_en_setting(); kfree(buf); filp_close(fp, NULL); revert_creds(old_cred); put_cred(override_cred); set_fs(old_fs); //恢复权限 } else{ printk("because of the same lib, update abort!\r\n"); } return ret;}
按以上方式升级完后不用重启手机即可正常操作。验证成功与否的话,进入工厂菜单中即可看到正确的版本号F6,则说明升级成功。需要注意的是:该种方式只能用BIN固件升级,不能用C格式固件,因为读入的是流文件,也解释了之前升级C固件却导致TP不能用的原因。
(3)以上是升级TP固件,如果是从T卡中读文件并解析文件,则需要编写对应的流文件解析代码段即可。转载地址:http://sbbsi.baihongyu.com/