Remove the execution flag from non-executables
[platform/core/connectivity/mtp-responder.git] / src / ptp_container.c
1 /*
2  * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <glib.h>
18 #include "ptp_container.h"
19 #include "ptp_datacodes.h"
20 #include "mtp_transport.h"
21 #include "mtp_support.h"
22 #include "mtp_util.h"
23
24 /*
25  * FUNCTIONS
26  */
27 void _hdlr_init_cmd_container(cmd_container_t *cntr)
28 {
29         cntr->tid = 0;
30         cntr->type = CONTAINER_UNDEFINED;
31         cntr->code = PTP_OPCODE_UNDEFINED;
32         cntr->len = sizeof(header_container_t);
33         cntr->no_param = 0;
34         return;
35 }
36
37 mtp_uint32 _hdlr_get_param_cmd_container(cmd_container_t *cntr,
38                 mtp_uint32 index)
39 {
40         if (index < cntr->no_param)
41                 return cntr->params[index];
42
43         return 0;
44 }
45
46 /* LCOV_EXCL_START */
47 void _hdlr_copy_cmd_container_unknown_params(cmd_container_t *src,
48                 cmd_container_t *dst)
49 {
50         mtp_uint16 ii;
51
52         dst->tid = src->tid;
53         dst->type = src->type;
54         dst->code = src->code;
55         dst->len = src->len;
56         dst->no_param =
57                 (src->len - sizeof(header_container_t)) / sizeof(mtp_uint32);
58
59         for (ii = 0; ii < dst->no_param; ii++)
60                 dst->params[ii] = src->params[ii];
61
62         return;
63 }
64 /* LCOV_EXCL_STOP */
65
66 void _hdlr_copy_cmd_container(cmd_container_t *src, cmd_container_t *dst)
67 {
68         mtp_uint16 ii;
69
70         dst->tid = src->tid;
71         dst->type = src->type;
72         dst->code = src->code;
73         dst->len = src->len;
74         dst->no_param = src->no_param;
75
76         for (ii = 0; ii < dst->no_param; ii++)
77                 dst->params[ii] = src->params[ii];
78
79         return;
80 }
81
82 mtp_bool _hdlr_add_param_resp_container(resp_blk_t *dst, mtp_uint32 num,
83                 mtp_uint32 *params)
84 {
85         mtp_uint16 ii;
86
87         retvm_if(num > MAX_MTP_PARAMS, FALSE, "num(%d) exceed", num);
88         retvm_if(num != 0 && params == NULL, FALSE, "num = %d, params = %p", num, params);
89
90         dst->no_param = num;
91         dst->len = sizeof(header_container_t) + sizeof(mtp_uint32) * (dst->no_param);
92
93         for (ii = 0; ii < dst->no_param; ii++) {
94                 dst->params[ii] = params[ii];
95 #ifdef __BIG_ENDIAN__
96                 _util_conv_byte_order(&(dst->params[ii]),
97                                 sizeof(dst->params[ii]));
98 #endif /* __BIG_ENDIAN__ */
99         }
100 #ifdef __BIG_ENDIAN__
101         _util_conv_byte_order(&(dst->no_param), sizeof(dst->no_param));
102         _util_conv_byte_order(&(dst->len), sizeof(dst->len));
103 #endif /* __BIG_ENDIAN__ */
104
105         return TRUE;
106 }
107
108 mtp_bool _hdlr_validate_cmd_container(mtp_uchar *blk, mtp_uint32 size)
109 {
110         if (size < sizeof(header_container_t) || size > sizeof(cmd_container_t))
111                 return FALSE;
112
113         /* LCOV_EXCL_START */
114         cmd_container_t *ptr = NULL;
115
116         ptr = (cmd_container_t *)blk;
117
118         if (ptr->len != size || ptr->type != CONTAINER_CMD_BLK) {
119                 ERR("size = [%d] length[%d] type[%d]\n", size, ptr->len,
120                                 ptr->type);
121                 return FALSE;
122         }
123
124         return TRUE;
125         /* LCOV_EXCL_STOP */
126 }
127
128 void _hdlr_init_data_container(data_container_t *dst, mtp_uint16 code,
129                 mtp_uint32 trans_id)
130 {
131         _hdlr_init_cmd_container((cmd_container_t *)dst);
132         dst->type = CONTAINER_DATA_BLK;
133         dst->code = code;
134         dst->tid = trans_id;
135         dst->data = NULL;
136 #ifdef __BIG_ENDIAN__
137         _hdlr_conv_data_container_byte_order(dst);
138 #endif /* __BIG_ENDIAN__ */
139         return;
140 }
141
142 mtp_uchar *_hdlr_alloc_buf_data_container(data_container_t *dst,
143                 mtp_uint32 bufsz, mtp_uint64 pkt_size)
144 {
145         mtp_uint32 blk_len;
146         header_container_t *header = NULL;
147
148         pkt_size = (pkt_size + sizeof(header_container_t) > 0xFFFFFFFF) ?
149                 0xFFFFFFFF : pkt_size + sizeof(header_container_t);
150
151
152         blk_len = bufsz + sizeof(header_container_t);
153         dst->data = (mtp_uchar *)g_malloc(blk_len);
154         if (dst->data == NULL) {
155                 ERR("g_malloc() Fail");
156                 return NULL;
157         }
158
159         memset(dst->data, 0, blk_len);
160         dst->len = bufsz + sizeof(header_container_t);
161         header = (header_container_t *)dst->data;
162         header->len = pkt_size;
163 #ifdef __BIG_ENDIAN__
164         _util_conv_byte_order(&(header->len), sizeof(header->len));
165 #endif /* __BIG_ENDIAN__ */
166         header->type = dst->type;
167         header->code = dst->code;
168         header->tid = dst->tid;
169         return (dst->data + sizeof(header_container_t));
170 }
171
172 /* LCOV_EXCL_START */
173 mtp_bool _hdlr_send_data_container(data_container_t *dst)
174 {
175         mtp_uint32 sent;
176
177         sent = _transport_send_pkt_to_tx_mq(dst->data, dst->len);
178
179         if (sent != dst->len)
180                 return FALSE;
181
182         return TRUE;
183 }
184
185 mtp_bool _hdlr_send_bulk_data(mtp_uchar *dst, mtp_uint32 len)
186 {
187         mtp_uint32 sent = 0;
188
189         sent = _transport_send_bulk_pkt_to_tx_mq(dst, len);
190         if (sent != len)
191                 return FALSE;
192
193         return TRUE;
194 }
195 /* LCOV_EXCL_STOP */
196
197 mtp_bool _hdlr_rcv_data_container(data_container_t *dst, mtp_uint32 size)
198 {
199         mtp_uint32 blk_size;
200         mtp_uint32 bytes_rcvd;
201         mtp_uint16 exp_code;
202         mtp_uint32 exp_tid;
203         header_container_t *header = NULL;
204
205         g_free(dst->data);
206         dst->data = NULL;
207
208         /* Allocated space for data + header */
209         /* Also allocate extra space in case chip writes DWORDS */
210
211         blk_size = size + sizeof(header_container_t) + sizeof(mtp_uint32);
212         dst->data = (mtp_uchar *)g_malloc(blk_size);
213         if (dst->data == NULL) {
214                 ERR("g_malloc() Fail");
215                 return FALSE;
216         }
217         bytes_rcvd = 0;
218
219         _transport_rcv_temp_file_data(dst->data, blk_size, &bytes_rcvd);
220         exp_code = dst->code;
221         exp_tid = dst->tid;
222         header = (header_container_t *)dst->data;
223
224 #ifdef __BIG_ENDIAN__
225         _hdlr_conv_data_container_byte_order((data_container_t *)dst->data);
226 #endif /* __BIG_ENDIAN__ */
227
228         /* Copy the header from the data block to the structure */
229         dst->len = header->len;
230         dst->type = header->type;
231         dst->code = header->code;
232         dst->tid = header->tid;
233         if (dst->len != bytes_rcvd || dst->type != CONTAINER_DATA_BLK ||
234                         dst->code != exp_code || dst->tid != exp_tid) {
235                 ERR("HEADER FAILURE");
236                 ERR("HEADER length[%d], Type[%d], Code[%d], tid[%d]\n",
237                                 dst->len, dst->type, dst->code, dst->tid);
238                 ERR("EXPECTED length[%d], Type[%d], Code[%d], tid[%d]\n",
239                                 bytes_rcvd, CONTAINER_DATA_BLK, exp_code, exp_tid);
240                 return FALSE;
241         }
242
243         return TRUE;
244 }
245
246 /* LCOV_EXCL_START */
247 mtp_bool _hdlr_rcv_file_in_data_container(data_container_t *dst,
248                 mtp_char *filepath, mtp_uint32 path_len)
249 {
250         mtp_uint32 blk_size;
251         mtp_uint64 bytes_rcvd;
252         mtp_uint16 exp_code;
253         mtp_uint32 exp_tid;
254         header_container_t *header = NULL;
255
256         g_free(dst->data);
257         dst->data = NULL;
258
259         /* Allocated space for data + header */
260         /* Also allocate extra space in case chip writes DWORDS */
261
262         blk_size = sizeof(header_container_t) + sizeof(mtp_uint32);
263         dst->data = (mtp_uchar *)g_malloc((mtp_uint32) blk_size);
264         if (dst->data == NULL) {
265                 ERR("g_malloc() Fail");
266                 return FALSE;
267         }
268
269         bytes_rcvd = 0;
270         _transport_rcv_temp_file_info(dst->data, filepath, &bytes_rcvd,
271                         path_len);
272         exp_code = dst->code;
273         exp_tid = dst->tid;
274         header = (header_container_t *)dst->data;
275
276 #ifdef __BIG_ENDIAN__
277         _hdlr_conv_data_container_byte_order((data_container_t *)dst->data);
278 #endif /* __BIG_ENDIAN__ */
279
280         /* Copy the header from the data block to the structure */
281         dst->len = header->len;
282         dst->type = header->type;
283         dst->code = header->code;
284         dst->tid = header->tid;
285
286         if ((dst->len != bytes_rcvd && bytes_rcvd < MTP_FILESIZE_4GB) ||
287                         dst->type != CONTAINER_DATA_BLK ||
288                         dst->code != exp_code || dst->tid != exp_tid) {
289                 ERR("HEADER FAILURE");
290                 ERR("HEADER length[%d], Type[%d], Code[%d], tid[%d]\n",
291                                 dst->len, dst->type, dst->code, dst->tid);
292                 ERR("EXPECTED length[%llu], Type[%d], Code[%d], tid[%d]\n",
293                                 bytes_rcvd, CONTAINER_DATA_BLK, exp_code, exp_tid);
294                 return FALSE;
295         }
296
297         return TRUE;
298 }
299 /* LCOV_EXCL_STOP */
300
301 mtp_uint32 _hdlr_get_payload_size(data_container_t *dst)
302 {
303         if (dst->data == NULL) {
304                 ERR("Payload data is NULL");
305                 return 0;
306         }
307
308         return (dst->len - sizeof(header_container_t));
309 }
310
311 mtp_uchar *_hdlr_get_payload_data(data_container_t *dst)
312 {
313         if (dst->data == NULL) {
314                 ERR("Payload data is NULL");
315                 return NULL;
316         }
317
318         return (dst->data + sizeof(header_container_t));
319 }
320
321 void _hdlr_resp_container_init(cmd_container_t *dst, mtp_uint16 resp_code,
322                 mtp_uint32 tid)
323 {
324         _hdlr_init_cmd_container(dst);
325         dst->type = CONTAINER_RESP_BLK;
326         dst->code = resp_code;
327         dst->tid = tid;
328 #ifdef __BIG_ENDIAN__
329         _hdlr_conv_cmd_container_byte_order(dst);
330 #endif /* __BIG_ENDIAN__ */
331         return;
332 }
333
334 /* LCOV_EXCL_START */
335 mtp_bool _hdlr_send_resp_container(cmd_container_t *dst)
336 {
337         mtp_uint32 sent = 0;
338
339 #ifdef __BIG_ENDIAN__
340         resp_blk_t resp_blk;
341
342         _hdlr_copy_cmd_container(dst, &resp_blk);
343         _hdlr_conv_cmd_container_byte_order(&resp_blk);
344         sent = _transport_send_pkt_to_tx_mq((mtp_uchar *)&resp_blk, dst->len);
345 #else /* __BIG_ENDIAN__ */
346
347         sent = _transport_send_pkt_to_tx_mq((mtp_uchar *)dst, dst->len);
348 #endif
349         if (sent != dst->len) {
350                 ERR("_transport_send_pkt_to_tx_mq() Fail: dst->len(%u), sent(%u)",
351                         dst->len, sent);
352                 return FALSE;
353         }
354
355         return TRUE;
356 }
357 /* LCOV_EXCL_STOP */
358
359 void _hdlr_init_event_container(cmd_container_t *dst, mtp_uint16 code,
360                 mtp_uint32 tid, mtp_uint32 param1, mtp_uint32 param2)
361 {
362         dst->type = CONTAINER_EVENT_BLK;
363         dst->code = code;
364         dst->tid = tid;
365         dst->no_param = 1;
366         dst->params[0] = param1;
367         dst->len = sizeof(header_container_t) + sizeof(mtp_uint32) * 1;
368 #ifdef __BIG_ENDIAN__
369         _hdlr_conv_cmd_container_byte_order(dst);
370 #endif /* __BIG_ENDIAN__ */
371         return;
372 }
373
374 void _hdlr_init_event_container_with_param(cmd_container_t *dst,
375                 mtp_uint16 code, mtp_uint32 tid, mtp_uint32 param1, mtp_uint32 param2)
376 {
377         dst->type = CONTAINER_EVENT_BLK;
378         dst->code = code;
379         dst->tid = tid;
380         dst->no_param = 2;
381         dst->params[0] = param1;
382         dst->params[1] = param2;
383         dst->len = sizeof(header_container_t) + sizeof(mtp_uint32) * 3;
384 #ifdef __BIG_ENDIAN__
385         _hdlr_conv_cmd_container_byte_order(dst);
386 #endif /* __BIG_ENDIAN__ */
387         return;
388 }
389
390 /* LCOV_EXCL_START */
391 mtp_bool _hdlr_send_event_container(cmd_container_t *dst)
392 {
393         mtp_uint32 sent = 0;
394         mtp_err_t retval;
395
396         retval = _transport_send_event((mtp_uchar *)dst, dst->len, &sent);
397         return (retval == MTP_ERROR_NONE && sent == dst->len) ?
398                 TRUE : FALSE;
399 }
400 /* LCOV_EXCL_STOP */
401
402 void _hdlr_conv_cmd_container_byte_order(cmd_container_t *dst)
403 {
404 #ifdef __BIG_ENDIAN__
405         mtp_uchar idx;
406
407         _util_conv_byte_order(&(dst->code), sizeof(dst->code));
408         _util_conv_byte_order(&(dst->len), sizeof(dst->len));
409         _util_conv_byte_order(&(dst->no_param), sizeof(dst->NumParams));
410         _util_conv_byte_order(&(dst->tid), sizeof(dst->tid));
411         _util_conv_byte_order(&(dst->type), sizeof(dst->Type));
412
413         for (idx = 0; idx < dst->no_param; idx++) {
414                 _util_conv_byte_order(&(dst->params[idx]),
415                                 sizeof(dst->params[idx]));
416         }
417 #endif /* __BIG_ENDIAN__ */
418         return;
419 }
420
421 void _hdlr_conv_data_container_byte_order(data_container_t *dst)
422 {
423 #ifdef __BIG_ENDIAN__
424         mtp_uchar idx;
425
426         _util_conv_byte_order(&(dst->code), sizeof(dst->code));
427         _util_conv_byte_order(&(dst->len), sizeof(dst->len));
428         _util_conv_byte_order(&(dst->no_param), sizeof(dst->NumParams));
429         _util_conv_byte_order(&(dst->tid), sizeof(dst->tid));
430         _util_conv_byte_order(&(dst->type), sizeof(dst->Type));
431         for (idx = 0; idx < dst->no_param; idx++) {
432                 _util_conv_byte_order(&(dst->params[idx]),
433                                 sizeof(dst->params[idx]));
434         }
435 #endif /* __BIG_ENDIAN__ */
436         return;
437 }