static int ptpfs_release(struct inode *ino, struct file *filp) { //printk(KERN_INFO "%s object:%X dcount: %d\n", __FUNCTION__,ino->i_ino, filp->f_dentry->d_count); struct ptp_data_buffer *data=(struct ptp_data_buffer*)filp->private_data; if (data) { switch (filp->f_flags & O_ACCMODE) { case O_RDWR: case O_WRONLY: { struct ptp_object_info object; memset(&object,0,sizeof(object)); if (ptp_getobjectinfo(PTPFSSB(ino->i_sb),ino->i_ino,&object)!=PTP_RC_OK) { ptp_free_data_buffer(data); kfree(data); return -EPERM; } ptp_deleteobject(PTPFSSB(ino->i_sb),ino->i_ino,0); int count = 0; int x; for (x = 0; x < data->num_blocks; x++) { count += data->blocks[x].block_size; } int storage = object.storage_id; int parent = object.parent_object; int handle = ino->i_ino; object.object_compressed_size=count; int ret = ptp_sendobjectinfo(PTPFSSB(ino->i_sb), &storage, &parent, &handle, &object); ret = ptp_sendobject(PTPFSSB(ino->i_sb),data,count); ino->i_size = count; ino->i_mtime = CURRENT_TIME; ptpfs_free_inode_data(ino);//uncache ptpfs_free_inode_data(PTPFSINO(ino) -> parent);//uncache //the inode number will change. Kill this inode so next dir lookup will create a new one dput(filp->f_dentry); //iput(ino); } break; } ptp_free_data_buffer(data); kfree(data); } return 0; }
static int ptpfs_mkdir(struct inode *ino,struct dentry *d,int i) { //printk(KERN_INFO "%s %s %d\n",__FUNCTION__,d->d_name.name,i); __u32 storage; __u32 parent; __u32 handle; struct ptp_object_info objectinfo; memset(&objectinfo,0,sizeof(objectinfo)); storage = PTPFSINO(ino)->storage; if (PTPFSINO(ino)->type == INO_TYPE_STGDIR) { parent = 0xffffffff; } else { parent = ino->i_ino; } objectinfo.filename = (unsigned char *)d->d_name.name; objectinfo.object_format=PTP_OFC_Association; objectinfo.association_type = PTP_AT_GenericFolder; int ret = ptp_sendobjectinfo(PTPFSSB(ino->i_sb), &storage, &parent, &handle, &objectinfo); /* if (ret == PTP_RC_OK) { struct ptp_data_buffer data; memset(&data,0,sizeof(data)); ret = ptp_sendobject(PTPFSSB(ino->i_sb),&data,0); } */ objectinfo.filename = NULL; ptp_free_object_info(&objectinfo); if (ret == PTP_RC_OK) { ptpfs_free_inode_data(ino);//uncache ino->i_version++; return 0; } return -EPERM; }
static int ptpfs_create(struct inode *dir,struct dentry *d,int i) { //printk(KERN_INFO "%s %s %d\n",__FUNCTION__,d->d_name.name,i); __u32 storage; __u32 parent; __u32 handle; struct ptp_object_info objectinfo; memset(&objectinfo,0,sizeof(objectinfo)); storage = PTPFSINO(dir)->storage; if (PTPFSINO(dir)->type == INO_TYPE_STGDIR) { parent = 0xffffffff; } else { parent = dir->i_ino; } objectinfo.filename = (unsigned char *)d->d_name.name; objectinfo.object_format=get_format((unsigned char *)d->d_name.name,d->d_name.len); objectinfo.object_compressed_size=0; int ret = ptp_sendobjectinfo(PTPFSSB(dir->i_sb), &storage, &parent, &handle, &objectinfo); if (ret == PTP_RC_OK) { struct ptp_data_buffer data; struct ptp_block block; unsigned char buf[10]; memset(&data,0,sizeof(data)); memset(&block,0,sizeof(block)); data.blocks=█ data.num_blocks = 1; block.block_size = 0; block.block = buf; ret = ptp_sendobject(PTPFSSB(dir->i_sb),&data,0); if (handle == 0) { //problem - it didn't return the right handle - need to do something find it struct ptp_object_handles objects; objects.n = 0; objects.handles = NULL; ptpfs_get_dir_data(dir); if (PTPFSINO(dir)->type == INO_TYPE_DIR) { ptp_getobjecthandles(PTPFSSB(dir->i_sb), PTPFSINO(dir)->storage, 0x000000, dir->i_ino,&objects); } else { ptp_getobjecthandles(PTPFSSB(dir->i_sb), dir->i_ino, 0x000000, 0xffffffff ,&objects); } int x,y; for (x = 0; x < objects.n && !handle; x++ ) { for (y = 0; y < PTPFSINO(dir)->data.dircache.num_files; y++) { if (PTPFSINO(dir)->data.dircache.file_info[y].handle == objects.handles[x]) { objects.handles[x] = 0; y = PTPFSINO(dir)->data.dircache.num_files; } } if (objects.handles[x]) { handle = objects.handles[x]; } } ptp_free_object_handles(&objects); } int mode = S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH | S_IFREG; struct inode *newi = ptpfs_get_inode(dir->i_sb, mode , 0,handle); PTPFSINO(newi)->parent = dir; ptpfs_set_inode_info(newi,&objectinfo); atomic_inc(&newi->i_count); /* New dentry reference */ d_instantiate(d, newi); objectinfo.filename = NULL; ptp_free_object_info(&objectinfo); ptpfs_free_inode_data(dir);//uncache dir->i_version++; newi->i_mtime = CURRENT_TIME; return 0; } objectinfo.filename = NULL; ptp_free_object_info(&objectinfo); return -EPERM; }
/** * Sends a MTP object to the device. * * @param device a pointer to the device. * @param p_parenthandle a pointer to the parent handle. * @param p_handle a pointer to the handle. * @param meta the metadata to describe the object. * @param data the object data to send. */ void VitaMTP_SendObject(LIBMTP_mtpdevice_t *device, uint32_t* p_parenthandle, uint32_t* p_handle, metadata_t* meta, unsigned char* data){ uint32_t sendhandle = *p_parenthandle; uint32_t store = 0x00010001; // TODO: What is this number? Does it change? uint32_t handle = *p_handle; uint32_t parenthandle = *p_parenthandle; MTPProperties* props = NULL; int nProps = 0; PTPObjectInfo objectinfo; memset(&objectinfo, 0x0, sizeof(PTPObjectInfo)); if(meta->dataType == SaveData){ objectinfo.ObjectFormat = PTP_OFC_Association; // 0x3001 objectinfo.ThumbFormat = PTP_OFC_Undefined; // 0x3000 objectinfo.Filename = meta->data.saveData.dirName; ptp_sendobjectinfo((PTPParams*)device->params, &store, &parenthandle, &handle, &objectinfo); sendhandle = handle; // Totaly useless and unused, but official CMA does that VitaMTP_GetObjectPropList(device, handle, &props, &nProps); free(props); }else if(meta->dataType == File){ parenthandle = sendhandle; objectinfo.ObjectFormat = PTP_OFC_PSPSave; // 0xB00A objectinfo.ObjectCompressedSize = (uint32_t)meta->size; objectinfo.CaptureDate = meta->dateTimeCreated; objectinfo.ModificationDate = meta->dateTimeCreated; objectinfo.Filename = meta->data.file.name; ptp_sendobjectinfo((PTPParams*)device->params, &store, &parenthandle, &handle, &objectinfo); ptp_sendobject((PTPParams*)device->params, data, meta->size); MTPProperties prop; prop.property = PTP_OPC_Name; // 0xDC44 prop.datatype = PTP_DTC_STR; // 0xFFFF prop.ObjectHandle = handle; prop.propval.str = meta->title; ptp_mtp_setobjectproplist((PTPParams*)device->params, &prop, 1); // Totaly useless and unused, but official CMA does that VitaMTP_GetObjectPropList(device, handle, &props, &nProps); free(props); }else if(meta->dataType == Folder){ parenthandle = sendhandle; objectinfo.ObjectFormat = PTP_OFC_Association; // 0x3001 objectinfo.ObjectCompressedSize = 0; objectinfo.CaptureDate = meta->dateTimeCreated; objectinfo.ModificationDate = meta->dateTimeCreated; objectinfo.Filename = meta->data.folder.name; ptp_sendobjectinfo((PTPParams*)device->params, &store, &parenthandle, &handle, &objectinfo); MTPProperties prop; prop.property = PTP_OPC_Name; // 0xDC44 prop.datatype = PTP_DTC_STR; // 0xFFFF prop.ObjectHandle = handle; prop.propval.str = meta->data.folder.name; ptp_mtp_setobjectproplist((PTPParams*)device->params, &prop, 1); // Totaly useless and unused, but official CMA does that VitaMTP_GetObjectPropList(device, handle, &props, &nProps); free(props); } *p_handle = handle; *p_parenthandle = parenthandle; }