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

371人阅读 评论(0) 收藏 举报

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

(1)store属性函数

  1. static ssize_t melfas_fwupdate_store(struct device *dev,struct device_attribute *attr,constchar *buf, size_t count) 
  2.     int UpResult; 
  3.     mt65xx_eint_mask(CUST_EINT_TOUCH_PANEL_NUM); 
  4. printk("run here \r\n"); 
  5.     UpResult = ms6000_firmware_upgrade_from_TCard();    //T卡升级主函数 
  6.     if(UpResult== MS6000_RET_SUCCESS){ 
  7.         printk("MFS6000 DOWNLOAD SUCCESS \r\n"); 
  8.         msleep(100); 
  9.     } 
  10.     else 
  11.         mfs6000_print_fail_result(UpResult); 
  12.     i2c_client->addr = MS6000_8BIT_I2CADDR; 
  13.     mt_set_gpio_mode(GPIO_I2C0_SCA_PIN, GPIO_I2C0_SCA_PIN_M_SCL); 
  14.     mt_set_gpio_mode(GPIO_I2C0_SDA_PIN, GPIO_I2C0_SDA_PIN_M_SDA); 
  15.     mt65xx_eint_unmask(CUST_EINT_TOUCH_PANEL_NUM);  //恢复中断和I2C脚的使用 
  16.  
  17.     return count; 
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卡读文件并处理

  1. static int ms6000_firmware_upgrade_from_TCard() 
  2.     unsigned char NewFwVersion,OldFwVersion; 
  3.     UINT16 rdlen;           //实际读入内存的文件长度 
  4.     loff_t file_size;           //文件大小 
  5.     UINT8 *buf = NULL;          //分配的内存指针 
  6.     struct file *fp = NULL; 
  7.     struct inode *inode = NULL; 
  8.     int ret = MS6000_RET_FILE_ACCESS_FAILED; 
  9.     mm_segment_t old_fs; 
  10.     const struct cred *old_cred; 
  11.     struct cred *override_cred; 
  12.  
  13.     override_cred = prepare_creds(); 
  14.     if (!override_cred) 
  15.         return -ENOMEM; 
  16.     override_cred->fsuid = 0; 
  17.     override_cred->fsgid = 0; 
  18.     old_cred = (struct cred *)override_creds(override_cred);   //权限属性 
  19.      
  20.     old_fs = get_fs(); 
  21.     set_fs(KERNEL_DS);                  //权限属性 
  22.  
  23.     if(mfs_i2c_read_single_reg(0x21,&OldFwVersion) ==true){ 
  24.         NewFwVersion = ms6000_GetLibVer();  //从T卡中读文件,并取出存于特定字节的版本号值 
  25.         printk("mfs6000 NewFwVersionis 0x%x,OldFwVersion is 0x%x \r\n",NewFwVersion,OldFwVersion); 
  26.     } 
  27.     i2c_client->addr = MS6000_8BIT_DOWNLOAD_ADDR;     
  28.     if(1NewFwVersion != OldFwVersion){ 
  29.         fp = filp_open("/mnt/sdcard/MCH_U5(S)_R01_VF6.bin", O_RDONLY, 0); //载入BIN格式的固件 
  30.         if (IS_ERR(fp)) { 
  31.             printk("ERROR opening file  \r\n"); 
  32.             return MS6000_RET_OPENFILE_ERROR; 
  33.         } else {         
  34.             if (!(fp->f_op)) { 
  35.                 printk("File has no file operations registered!\r\n");           
  36.                 filp_close(fp, NULL); 
  37.                 return MS6000_RET_OPENFILE_ERROR;        
  38.             }        
  39.             if (!fp->f_op->read) { 
  40.                 printk(" File has no READ operations registered!\r\n");          
  41.                 filp_close(fp, NULL); 
  42.                 return MS6000_RET_OPENFILE_ERROR;        
  43.             } 
  44.         } 
  45.  
  46.         inode = fp->f_dentry->d_inode; 
  47.         file_size = inode->i_size; 
  48.         buf = (UINT8 *)kmalloc(file_size, GFP_KERNEL); 
  49.         if(buf < 0) 
  50.             return -ENOMEM; 
  51.         rdlen = vfs_read(fp, buf, file_size, &(fp->f_pos)); 
  52.  
  53.         printk("start download, file_size is %d,rdlen is %d\r\n",file_size,rdlen); 
  54.         mtk_wdt_disable(); 
  55.         ret = ms6000_download(buf,rdlen);   //升级主函数参见文章头部博文 
  56.         mtk_wdt_get_en_setting(); 
  57.  
  58.         kfree(buf); 
  59.         filp_close(fp, NULL); 
  60.         revert_creds(old_cred); 
  61.         put_cred(override_cred); 
  62.         set_fs(old_fs);     //恢复权限 
  63.     } 
  64.     else
  65.         printk("because of the same lib, update abort!\r\n"); 
  66.     } 
  67.     return ret; 
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卡中读文件并解析文件,则需要编写对应的流文件解析代码段即可。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值