2012-03-09 15:13
371人阅读
评论(0)
收藏
举报
在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,constchar *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;
- }
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;
- }
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卡中读文件并解析文件,则需要编写对应的流文件解析代码段即可。