1 /*
2     This file is part of Android File Transfer For Linux.
3     Copyright (C) 2015-2020  Vladimir Menshakov
4 
5     This library is free software; you can redistribute it and/or modify it
6     under the terms of the GNU Lesser General Public License as published by
7     the Free Software Foundation; either version 2.1 of the License,
8     or (at your option) any later version.
9 
10     This library is distributed in the hope that it will be useful, but
11     WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13     Lesser General Public License for more details.
14 
15     You should have received a copy of the GNU Lesser General Public License
16     along with this library; if not, write to the Free Software Foundation,
17     Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19 
20 #ifndef AFTL_MTP_PTP_SESSION_H
21 #define AFTL_MTP_PTP_SESSION_H
22 
23 #include <mtp/usb/BulkPipe.h>
24 #include <mtp/ptp/Messages.h>
25 #include <mtp/ptp/DeviceProperty.h>
26 #include <mtp/ptp/IObjectStream.h>
27 #include <mtp/ptp/ObjectId.h>
28 #include <mtp/ptp/ObjectProperty.h>
29 #include <mtp/ptp/PipePacketer.h>
30 #include <time.h>
31 
32 namespace mtp
33 {
34 	struct OperationRequest;
35 
36 	class Session;
37 	DECLARE_PTR(Session);
38 
39 	class Session //! Main MTP interaction / object manipulation class
40 	{
41 		class Transaction;
42 
43 		std::mutex		_mutex, _transactionMutex;
44 		PipePacketer	_packeter;
45 		u32				_sessionId;
46 		u32				_nextTransactionId;
47 		Transaction *	_transaction;
48 
49 		msg::DeviceInfo	_deviceInfo;
50 		bool			_getPartialObject64Supported;
51 		bool			_editObjectSupported;
52 		bool			_getObjectPropertyListSupported;
53 		bool			_getObjectPropValueSupported;
54 		bool			_getObjectModificationTimeBuggy;
55 		bool			_separateBulkWrites;
56 		int				_defaultTimeout;
57 
58 	public:
59 		static constexpr int DefaultTimeout		= 10000;
60 		static constexpr int LongTimeout		= 30000;
61 
62 		static const StorageId AllStorages;
63 		static const StorageId AnyStorage;
64 		static const ObjectId Device;
65 		static const ObjectId Root;
66 
67 		///sub-session object which handles partial writes and truncation
68 		class ObjectEditSession : Noncopyable
69 		{
70 			SessionPtr	_session;
71 			ObjectId	_objectId;
72 
73 		public:
74 			ObjectEditSession(const SessionPtr & session, ObjectId objectId);
75 			~ObjectEditSession();
76 
77 			void Truncate(u64 size);
78 			void Send(u64 offset, const ByteArray &data);
79 		};
80 		DECLARE_PTR(ObjectEditSession);
81 
82 		Session(const PipePacketer & packeter, u32 sessionId);
83 		~Session();
84 
GetDeviceInfo()85 		const msg::DeviceInfo & GetDeviceInfo() const
86 		{ return _deviceInfo; }
87 
88 		msg::ObjectHandles GetObjectHandles(StorageId storageId = AllStorages, ObjectFormat objectFormat = ObjectFormat::Any, ObjectId parent = Device, int timeout = LongTimeout);
89 		msg::StorageIDs GetStorageIDs();
90 		msg::StorageInfo GetStorageInfo(StorageId storageId);
91 
92 		msg::NewObjectInfo CreateDirectory(const std::string &name, ObjectId parentId, StorageId storageId = AnyStorage, AssociationType type = AssociationType::GenericFolder);
93 		msg::ObjectInfo GetObjectInfo(ObjectId objectId);
94 		void GetObject(ObjectId objectId, const IObjectOutputStreamPtr &outputStream);
95 		void GetThumb(ObjectId objectId, const IObjectOutputStreamPtr &outputStream);
96 		ByteArray GetPartialObject(ObjectId objectId, u64 offset, u32 size);
97 		msg::NewObjectInfo SendObjectInfo(const msg::ObjectInfo &objectInfo, StorageId storageId = AnyStorage, ObjectId parentObject = Device);
98 		void SendObject(const IObjectInputStreamPtr &inputStream, int timeout = LongTimeout);
99 		void DeleteObject(ObjectId objectId, int timeout = LongTimeout);
100 
EditObjectSupported()101 		bool EditObjectSupported() const
102 		{ return _editObjectSupported; }
GetObjectPropertyListSupported()103 		bool GetObjectPropertyListSupported() const
104 		{ return _getObjectPropertyListSupported; }
105 
EditObject(const SessionPtr & session,ObjectId objectId)106 		static ObjectEditSessionPtr EditObject(const SessionPtr &session, ObjectId objectId)
107 		{ return std::make_shared<ObjectEditSession>(session, objectId); }
108 
109 		msg::ObjectPropertiesSupported GetObjectPropertiesSupported(ObjectFormat format);
110 		ByteArray GetObjectPropertyDesc(ObjectProperty code);
111 
112 		void SetObjectProperty(ObjectId objectId, ObjectProperty property, const ByteArray &value);
113 		void SetObjectProperty(ObjectId objectId, ObjectProperty property, u64 value);
114 		void SetObjectProperty(ObjectId objectId, ObjectProperty property, const std::string &value);
115 		void SetObjectPropertyAsArray(ObjectId objectId, ObjectProperty property, const ByteArray &value);
116 		time_t GetObjectModificationTime(ObjectId id);
117 
118 		//common properties shortcuts
119 		StorageId GetObjectStorage(ObjectId id);
120 		ObjectId GetObjectParent(ObjectId id);
121 
122 		ByteArray GetObjectProperty(ObjectId objectId, ObjectProperty property);
123 		u64 GetObjectIntegerProperty(ObjectId objectId, ObjectProperty property);
124 		std::string GetObjectStringProperty(ObjectId objectId, ObjectProperty property);
125 
126 		ByteArray GetObjectPropertyList(ObjectId objectId, ObjectFormat format, ObjectProperty property, u32 groupCode, u32 depth, int timeout = LongTimeout);
127 		msg::SendObjectPropListResponse SendObjectPropList(StorageId storageId, ObjectId parentId, ObjectFormat format, u64 objectSize, const ByteArray & propList);
128 
129 		msg::DevicePropertyDesc GetDevicePropertyDesc(DeviceProperty property);
130 		ByteArray GetDeviceProperty(DeviceProperty property);
131 		u64 GetDeviceIntegerProperty(DeviceProperty property);
132 		std::string GetDeviceStringProperty(DeviceProperty property);
133 		void SetDeviceProperty(DeviceProperty property, const ByteArray & value);
134 		void SetDeviceProperty(DeviceProperty property, const std::string & value);
135 
136 		void AbortCurrentTransaction(int timeout = DefaultTimeout);
137 
138 		ByteArray GenericOperation(OperationCode code);
139 		ByteArray GenericOperation(OperationCode code, const ByteArray & payload);
140 
141 		void SetObjectReferences(ObjectId objectId, const msg::ObjectHandles &objects);
142 		msg::ObjectHandles GetObjectReferences(ObjectId objectId);
143 
144 		//windows specific
145 		void EnableSecureFileOperations(u32 cmac1[4]);
146 
147 		static msg::DeviceInfo GetDeviceInfo(PipePacketer& packeter, int timeout = 0);
148 
149 	private:
150 		template<typename ... Args>
RunTransaction(int timeout,OperationCode code,Args &&...args)151 		ByteArray RunTransaction(int timeout, OperationCode code, Args && ... args)
152 		{ ByteArray response; return RunTransactionWithDataRequest<Args...>(timeout, code, response, nullptr, std::forward<Args>(args) ... ); }
153 		template<typename ... Args>
154 		ByteArray RunTransactionWithDataRequest(int timeout, OperationCode code, ByteArray & response, const IObjectInputStreamPtr & inputStream, Args && ... args);
155 
156 		void SetCurrentTransaction(Transaction *);
157 
158 
159 		void BeginEditObject(ObjectId objectId);
160 		void SendPartialObject(ObjectId objectId, u64 offset, const ByteArray &data);
161 		void TruncateObject(ObjectId objectId, u64 size);
162 		void EndEditObject(ObjectId objectId);
163 
164 		ByteArray Get(u32 transaction, ByteArray & response, int timeout = 0);
165 		static ByteArray Get(PipePacketer &packeter, u32 transaction, ByteArray & response, int timeout = 0);
166 
167 		void Send(const OperationRequest &req, int timeout = 0);
168 		static void Send(PipePacketer &packeter, const OperationRequest &req, int timeout = 0);
169 		void Close();
170 	};
171 
172 }
173 
174 #endif	/* SESSION_H */
175 
176