现在的位置: 首页 > 综合 > 正文

Linux平台从SD卡读文件并处理的方法

2013年02月19日 ⁄ 综合 ⁄ 共 2662字 ⁄ 字号 评论关闭

        在Linux的应用平台上,很多时候我们需要用到从SD卡读数据来使用,比如升级触摸屏固件,比如载入调试文本等,都需要用到Linux的文件系统来操作。通过举一个实例来说明VFS FILE操作细节,即在ADB中通过echo 到DEVICE_ATTR的store来升级TP固件,相关升级函数可以参见博文http://blog.csdn.net/zhandoushi1982/article/details/7704416

(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卡中读文件并解析文件,则需要编写对应的流文件解析代码段即可。

抱歉!评论已关闭.