2 * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include <linux/magic.h>
20 #include <sys/syscall.h>
21 #include <sys/types.h>
25 #include <glib/gprintf.h>
27 #include "mtp_support.h"
28 #include "ptp_datacodes.h"
29 #include "mtp_media_info.h"
30 #include "mtp_usb_driver.h"
31 #include "mtp_cmd_handler.h"
32 #include "mtp_cmd_handler_util.h"
33 #include "mtp_transport.h"
34 #include "mtp_thread.h"
37 * GLOBAL AND EXTERN VARIABLES
39 extern mtp_mgr_t g_mtp_mgr;
40 extern mtp_bool g_is_full_enum;
41 extern pthread_mutex_t g_cmd_inoti_mutex;
42 extern mtp_config_t g_conf;
44 mtp_bool g_is_sync_estab = FALSE;
49 static mtp_mgr_t *g_mgr = &g_mtp_mgr;
50 static mtp_bool g_has_round_trip = FALSE;
51 #ifdef MTP_USE_SKIP_CONTINUOUS_OPENSESSION
52 static mtp_uint16 g_count_open_session = 0;
53 static mtp_uint32 g_old_open_session_time = 0;
54 #endif/*MTP_USE_SKIP_CONTINUOUS_OPENSESSION*/
59 static void __process_commands(mtp_handler_t *hdlr, cmd_blk_t *cmd);
60 static void __open_session(mtp_handler_t *hdlr);
61 static void __get_device_info(mtp_handler_t *hdlr);
62 static void __get_storage_ids(mtp_handler_t *hdlr);
63 static void __get_storage_info(mtp_handler_t *hdlr);
64 static void __get_num_objects(mtp_handler_t *hdlr);
65 static void __get_object_handles(mtp_handler_t *hdlr);
66 static void __get_object_info(mtp_handler_t *hdlr);
67 static void __get_object(mtp_handler_t *hdlr);
68 static void __send_object_info(mtp_handler_t *hdlr);
69 static void __send_object(mtp_handler_t *hdlr);
70 static void __delete_object(mtp_handler_t *hdlr);
71 static void __format_store(mtp_handler_t *hdlr);
72 static void __reset_device(mtp_handler_t *hdlr);
73 static void __get_device_prop_desc(mtp_handler_t *hdlr);
74 static void __get_device_prop_value(mtp_handler_t *hdlr);
75 static void __set_device_prop_value(mtp_handler_t *hdlr);
76 static void __get_partial_object(mtp_handler_t *hdlr);
77 static void __get_object_references(mtp_handler_t *hdlr);
78 static void __set_object_references(mtp_handler_t *hdlr);
79 static void __get_object_prop_desc(mtp_handler_t *hdlr);
80 static void __get_object_prop_supported(mtp_handler_t *hdlr);
81 static void __get_object_prop_value(mtp_handler_t *hdlr);
82 static void __set_object_prop_value(mtp_handler_t *hdlr);
83 static void __get_object_prop_list(mtp_handler_t *hdlr);
84 static void __set_object_prop_list(mtp_handler_t *hdlr);
85 static void __report_acquired_content(mtp_handler_t *hdlr);
86 static void __send_playback_skip(mtp_handler_t *hdlr);
88 static void __self_test(mtp_handler_t *hdlr);
89 #ifdef MTP_SUPPORT_SET_PROTECTION
90 static void __set_object_protection(mtp_handler_t *hdlr);
91 #endif /* MTP_SUPPORT_SET_PROTECTION */
92 static void __power_down(mtp_handler_t *hdlr);
93 static void __move_object(mtp_handler_t *hdlr);
94 static void __copy_object(mtp_handler_t *hdlr);
95 static void __reset_device_prop_value(mtp_handler_t *hdlr);
96 static void __vendor_command1(mtp_handler_t *hdlr);
97 static void __get_interdep_prop_desc(mtp_handler_t *hdlr);
98 static void __send_object_prop_list(mtp_handler_t *hdlr);
100 static void __close_session(mtp_handler_t *hdlr);
101 #ifdef MTP_SUPPORT_PRINT_COMMAND
102 static void __print_command(mtp_uint16 code);
103 #endif /* MTP_SUPPORT_PRINT_COMMAND */
104 static void __enum_store_not_enumerated(mtp_uint32 obj_handle,
105 mtp_uint32 fmt, mtp_uint32 depth);
106 static mtp_bool __receive_temp_file_first_packet(mtp_char *data,
108 static mtp_bool __receive_temp_file_next_packets(mtp_char *data,
110 static void __finish_receiving_file_packets(mtp_char *data, mtp_int32 data_len);
115 void _cmd_hdlr_reset_cmd(mtp_handler_t *hdlr)
117 if (hdlr->data4_send_obj.obj != NULL)
118 _entity_dealloc_mtp_obj(hdlr->data4_send_obj.obj);
120 memset(hdlr, 0x00, sizeof(mtp_handler_t));
122 #ifdef MTP_USE_SKIP_CONTINUOUS_OPENSESSION
123 /* reset open session count */
124 g_count_open_session = 0;
125 g_old_open_session_time = 0;
126 #endif /* MTP_USE_SKIP_CONTINUOUS_OPENSESSION */
129 static void __process_commands(mtp_handler_t *hdlr, cmd_blk_t *cmd)
131 mtp_store_t *store = NULL;
133 /* Keep a local copy for this command */
134 _hdlr_copy_cmd_container(cmd, &(hdlr->usb_cmd));
136 if (hdlr->usb_cmd.code == PTP_OPCODE_GETDEVICEINFO) {
137 DBG("COMMAND CODE = [0x%4x]!!\n", hdlr->usb_cmd.code);
138 #ifdef MTP_SUPPORT_PRINT_COMMAND
139 __print_command(hdlr->usb_cmd.code);
140 #endif /*MTP_SUPPORT_PRINT_COMMAND*/
141 __get_device_info(hdlr);
145 /* Process OpenSession Command */
146 if (hdlr->usb_cmd.code == PTP_OPCODE_OPENSESSION) {
147 DBG("COMMAND CODE = [0x%4X]!!\n", hdlr->usb_cmd.code);
148 #ifdef MTP_SUPPORT_PRINT_COMMAND
149 __print_command(hdlr->usb_cmd.code);
150 #endif /*MTP_SUPPORT_PRINT_COMMAND*/
151 #ifdef MTP_USE_SKIP_CONTINUOUS_OPENSESSION
153 mtp_uint32 cur_time = 0;
155 cur_time = (mtp_uint32)t;
156 /*first opensession*/
157 if (g_count_open_session == 0) {
158 g_old_open_session_time = cur_time;
159 } else if (cur_time <= g_old_open_session_time + 1) {
160 /*under 1 sec. it might be skipped*/
161 ERR("skip continuous OPEN session");
164 ++g_count_open_session;
166 #endif /* MTP_USE_SKIP_CONTINUOUS_OPENSESSION */
167 __open_session(hdlr);
170 #ifdef MTP_USE_SKIP_CONTINUOUS_OPENSESSION
171 g_count_open_session = 0;
172 #endif /* MTP_USE_SKIP_CONTINUOUS_OPENSESSION */
174 /* Check if session is open or not, if not respond */
175 if (hdlr->session_id == 0) {
176 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_SESSIONNOTOPEN);
177 _device_set_phase(DEVICE_PHASE_IDLE);
180 DBG("COMMAND CODE = [0x%4x]!!\n", hdlr->usb_cmd.code);
181 #ifdef MTP_SUPPORT_PRINT_COMMAND
182 __print_command(hdlr->usb_cmd.code);
183 #endif /* MTP_SUPPORT_PRINT_COMMAND */
185 switch (hdlr->usb_cmd.code) {
186 case PTP_OPCODE_CLOSESESSION:
187 __close_session(hdlr);
189 case PTP_OPCODE_GETSTORAGEIDS:
190 __get_storage_ids(hdlr);
192 case PTP_OPCODE_GETSTORAGEINFO:
193 __get_storage_info(hdlr);
195 case PTP_OPCODE_GETNUMOBJECTS:
196 __get_num_objects(hdlr);
198 case PTP_OPCODE_GETOBJECTHANDLES:
199 __get_object_handles(hdlr);
201 case PTP_OPCODE_GETOBJECTINFO:
202 __get_object_info(hdlr);
204 case PTP_OPCODE_GETOBJECT:
205 _eh_send_event_req_to_eh_thread(EVENT_START_DATAIN, 0, 0, NULL);
207 _eh_send_event_req_to_eh_thread(EVENT_DONE_DATAIN, 0, 0, NULL);
209 case PTP_OPCODE_DELETEOBJECT:
210 __delete_object(hdlr);
212 case PTP_OPCODE_FORMATSTORE:
213 __format_store(hdlr);
215 case PTP_OPCODE_GETDEVICEPROPDESC:
216 __get_device_prop_desc(hdlr);
218 case PTP_OPCODE_GETDEVICEPROPVALUE:
219 __get_device_prop_value(hdlr);
221 case PTP_OPCODE_GETPARTIALOBJECT:
222 __get_partial_object(hdlr);
224 case MTP_OPCODE_GETOBJECTREFERENCES:
225 __get_object_references(hdlr);
227 case MTP_OPCODE_GETOBJECTPROPDESC:
228 __get_object_prop_desc(hdlr);
230 case MTP_OPCODE_GETOBJECTPROPSUPPORTED:
231 __get_object_prop_supported(hdlr);
233 case MTP_OPCODE_GETOBJECTPROPVALUE:
234 __get_object_prop_value(hdlr);
236 case MTP_OPCODE_GETOBJECTPROPLIST:
237 __get_object_prop_list(hdlr);
240 case PTP_OPCODE_RESETDEVICE:
241 __reset_device(hdlr);
243 case PTP_OPCODE_SELFTEST:
246 #ifdef MTP_SUPPORT_SET_PROTECTION
247 case PTP_OPCODE_SETOBJECTPROTECTION:
248 __set_object_protection(hdlr);
250 #endif /* MTP_SUPPORT_SET_PROTECTION */
251 case PTP_OPCODE_POWERDOWN:
254 case PTP_OPCODE_RESETDEVICEPROPVALUE:
255 __reset_device_prop_value(hdlr);
257 case PTP_OPCODE_MOVEOBJECT:
260 case PTP_OPCODE_COPYOBJECT:
263 case MTP_OPCODE_GETINTERDEPPROPDESC:
264 __get_interdep_prop_desc(hdlr);
266 case PTP_CODE_VENDOR_OP1: /* Vendor-specific operations */
267 __vendor_command1(hdlr);
270 case MTP_OPCODE_PLAYBACK_SKIP: /* Playback control */
271 __send_playback_skip(hdlr);
274 case MTP_OPCODE_WMP_REPORTACQUIREDCONTENT:
275 /* Windows Media 11 extension*/
276 __report_acquired_content(hdlr);
278 case PTP_OPCODE_SENDOBJECTINFO:
279 case PTP_OPCODE_SENDOBJECT:
280 case PTP_OPCODE_SETDEVICEPROPVALUE:
281 case MTP_OPCODE_SETOBJECTREFERENCES:
282 case MTP_OPCODE_SETOBJECTPROPVALUE:
283 case MTP_OPCODE_SETOBJECTPROPLIST:
285 case MTP_OPCODE_SENDOBJECTPROPLIST:
287 /* DATA_HANDLE_PHASE: Send operation will be blocked
288 * until data packet is received
290 if (_device_get_phase() == DEVICE_PHASE_IDLE) {
291 DBG("DATAOUT COMMAND PHASE!!");
292 if (hdlr->usb_cmd.code == PTP_OPCODE_SENDOBJECT)
293 _eh_send_event_req_to_eh_thread(EVENT_START_DATAOUT,
295 _device_set_phase(DEVICE_PHASE_DATAOUT);
296 return; /* in command phase, just return and wait next data */
298 switch (hdlr->usb_cmd.code) {
299 case PTP_OPCODE_SENDOBJECTINFO:
300 __send_object_info(hdlr);
302 case PTP_OPCODE_SENDOBJECT:
304 _eh_send_event_req_to_eh_thread(EVENT_DONE_DATAOUT,
307 case PTP_OPCODE_SETDEVICEPROPVALUE:
308 __set_device_prop_value(hdlr);
310 case MTP_OPCODE_SETOBJECTREFERENCES:
311 __set_object_references(hdlr);
313 case MTP_OPCODE_SETOBJECTPROPVALUE:
314 __set_object_prop_value(hdlr);
316 case MTP_OPCODE_SETOBJECTPROPLIST:
317 __set_object_prop_list(hdlr);
320 case MTP_OPCODE_SENDOBJECTPROPLIST:
321 __send_object_prop_list(hdlr);
328 _cmd_hdlr_send_response_code(hdlr,
329 PTP_RESPONSE_OP_NOT_SUPPORTED);
330 DBG("Unsupported COMMAND[%d]\n", hdlr->usb_cmd.code);
334 if (((hdlr->last_opcode == PTP_OPCODE_SENDOBJECTINFO) ||
335 (hdlr->last_opcode == MTP_OPCODE_SENDOBJECTPROPLIST)) &&
336 ((hdlr->last_fmt_code != PTP_FMT_ASSOCIATION) &&
337 (hdlr->last_fmt_code != PTP_FMT_UNDEF))) {
338 DBG("Processed, last_opcode[0x%x], last_fmt_code[%d]\n",
339 hdlr->last_opcode, hdlr->last_fmt_code);
341 if ((hdlr->usb_cmd.code != PTP_OPCODE_SENDOBJECT) &&
342 hdlr->data4_send_obj.is_valid &&
343 hdlr->data4_send_obj.is_data_sent) {
345 DBG("Processed, COMMAND[0x%x]!!\n", hdlr->usb_cmd.code);
346 store = _device_get_store(hdlr->data4_send_obj.store_id);
348 /*Restore reserved space*/
349 store->store_info.free_space +=
350 hdlr->data4_send_obj.file_size;
353 if (hdlr->data4_send_obj.obj) {
354 _entity_dealloc_mtp_obj(hdlr->data4_send_obj.obj);
355 hdlr->data4_send_obj.obj = NULL;
357 memset(&(hdlr->data4_send_obj), 0x00,
358 sizeof(hdlr->data4_send_obj));
361 hdlr->last_opcode = hdlr->usb_cmd.code; /* Last operation code*/
364 static void __open_session(mtp_handler_t *hdlr)
366 mtp_uint32 session_id;
367 /*Check the parameters*/
368 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
369 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
370 /*Unknown parameters*/
371 _cmd_hdlr_send_response_code(hdlr,
372 PTP_RESPONSE_PARAM_NOTSUPPORTED);
375 /* Validate parameters*/
376 session_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
378 if (session_id == 0 || (hdlr->usb_cmd.tid != 0)) {
379 /*Session Id cannot be zero, while TransactionId must be zero.*/
380 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_INVALIDPARAM);
384 if (hdlr->session_id) { /*Session already open*/
385 _cmd_hdlr_send_response(hdlr,
386 PTP_RESPONSE_SESSIONALREADYOPENED, 1,
387 (mtp_uint32 *)&(hdlr->session_id));
388 } else { /*Save the Session ID*/
389 hdlr->session_id = session_id;
390 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
394 static void __get_device_info(mtp_handler_t *hdlr)
396 /* Check the parameters*/
397 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0) ||
398 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
399 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
400 /* Unknown parameters*/
401 _cmd_hdlr_send_response_code(hdlr,
402 PTP_RESPONSE_PARAM_NOTSUPPORTED);
406 /* When used outside a session, both the SessionID and TransactionID
407 * in the Operation Request dataset must be 0;
410 if ((hdlr->session_id == 0) &&
411 (hdlr->usb_cmd.tid != 0)) { /*INVALIDPARAMETER*/
412 _cmd_hdlr_send_response_code(hdlr,
413 PTP_RESPONSE_PARAM_NOTSUPPORTED);
414 ERR("Invalid Session ID[%u], Transaction ID[%u]\n",
415 hdlr->session_id, hdlr->usb_cmd.tid);
419 /*Build the data block for device info.*/
420 data_blk_t blk = { 0 };
421 mtp_uint32 num_bytes = 0;
422 mtp_uchar *buf_ptr = NULL;
424 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
425 num_bytes = _get_device_info_size();
426 buf_ptr = _hdlr_alloc_buf_data_container(&blk, num_bytes, num_bytes);
427 if (num_bytes == _pack_device_info(buf_ptr, num_bytes)) {
428 _device_set_phase(DEVICE_PHASE_DATAIN);
429 if (_hdlr_send_data_container(&blk)) {
430 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
432 /* Host Cancelled data-in transfer */
433 _device_set_phase(DEVICE_PHASE_NOTREADY);
434 DBG("Device phase is set to DEVICE_PHASE_NOTREADY");
437 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
443 static void __get_storage_ids(mtp_handler_t *hdlr)
445 data_blk_t blk = { 0 };
446 ptp_array_t ids = { 0 };
447 mtp_uint32 resp = PTP_RESPONSE_GEN_ERROR;
448 mtp_uint32 num_bytes = 0;
449 mtp_uchar *ptr = NULL;
451 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0) ||
452 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
453 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
455 _cmd_hdlr_send_response_code(hdlr,
456 PTP_RESPONSE_PARAM_NOTSUPPORTED);
460 _prop_init_ptparray(&ids, UINT32_TYPE);
462 if (_hutil_get_storage_ids(&ids) == MTP_ERROR_NONE) {
463 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code,
465 num_bytes = _prop_get_size_ptparray(&ids);
466 ptr = _hdlr_alloc_buf_data_container(&blk, num_bytes, num_bytes);
469 _prop_pack_ptparray(&ids, ptr, num_bytes);
470 _device_set_phase(DEVICE_PHASE_DATAIN);
471 /*Send the data block*/
472 if (FALSE == _hdlr_send_data_container(&blk)) {
473 /*Host Cancelled data-in transfer*/
474 _device_set_phase(DEVICE_PHASE_NOTREADY);
475 DBG("DEVICE_PHASE_NOTREADY!!");
477 resp = PTP_RESPONSE_OK;
482 _prop_deinit_ptparray(&ids);
483 _cmd_hdlr_send_response_code(hdlr, (mtp_uint16) resp);
486 static void __get_storage_info(mtp_handler_t *hdlr)
488 mtp_uint32 store_id = 0;
489 store_info_t store_info = { 0 };
490 mtp_uint32 pkt_sz = 0;
491 data_blk_t blk = { 0 };
492 mtp_uchar *ptr = NULL;
494 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
495 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
496 /*Unknown parameters*/
497 _cmd_hdlr_send_response_code(hdlr,
498 PTP_RESPONSE_PARAM_NOTSUPPORTED);
502 store_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
504 if (_hutil_get_storage_entry(store_id, &store_info) != MTP_ERROR_NONE) {
505 _cmd_hdlr_send_response_code(hdlr,
506 PTP_RESPONSE_INVALID_STORE_ID);
510 /* Build the data block for StorageInfo Dataset.*/
511 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
512 pkt_sz = _hutil_get_storage_info_size(&store_info);
513 ptr = _hdlr_alloc_buf_data_container(&blk, pkt_sz, pkt_sz);
515 if (pkt_sz == _entity_pack_store_info(&store_info, ptr, pkt_sz)) {
516 _device_set_phase(DEVICE_PHASE_DATAIN);
517 if (_hdlr_send_data_container(&blk)) {
518 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
520 /*Host Cancelled data-in transfer*/
521 _device_set_phase(DEVICE_PHASE_NOTREADY);
522 DBG("DEVICE_PHASE_NOTREADY!!");
525 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
531 static void __get_num_objects(mtp_handler_t *hdlr)
534 mtp_uint32 store_id = 0;
535 mtp_uint32 h_parent = 0;
537 mtp_uint32 num_obj = 0;
539 store_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
540 fmt = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
541 h_parent = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2);
543 switch (_hutil_get_num_objects(store_id, h_parent, fmt,
544 (mtp_uint32 *)(&num_obj))) {
545 case MTP_ERROR_INVALID_STORE:
546 resp = PTP_RESPONSE_INVALID_STORE_ID;
548 case MTP_ERROR_INVALID_OBJECTHANDLE:
549 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
551 case MTP_ERROR_INVALID_PARENT:
552 resp = PTP_RESPONSE_INVALIDPARENT;
554 case MTP_ERROR_STORE_NOT_AVAILABLE:
555 resp = PTP_RESPONSE_STORENOTAVAILABLE;
558 resp = PTP_RESPONSE_OK;
561 resp = PTP_RESPONSE_GEN_ERROR;
564 if (resp == PTP_RESPONSE_OK)
565 _cmd_hdlr_send_response(hdlr, resp, 1, (mtp_uint32 *)&num_obj);
567 _cmd_hdlr_send_response_code(hdlr, resp);
570 static void __get_object_handles(mtp_handler_t *hdlr)
572 mtp_uint32 store_id = 0;
574 mtp_uint32 h_parent = 0;
575 ptp_array_t handle_arr = { 0 };
576 data_blk_t blk = { 0 };
577 mtp_uint32 num_bytes = 0;
578 mtp_uchar *ptr = NULL;
581 _prop_init_ptparray(&handle_arr, UINT32_TYPE);
583 store_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
584 fmt = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
585 h_parent = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2);
587 DBG("store_id = [0x%x], Format Code = [0x%x], parent handle = [0x%x]\n",
588 store_id, fmt, h_parent);
589 switch (_hutil_get_object_handles(store_id, fmt, h_parent,
591 case MTP_ERROR_INVALID_STORE:
592 resp = PTP_RESPONSE_INVALID_STORE_ID;
594 case MTP_ERROR_INVALID_OBJECTHANDLE:
595 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
597 case MTP_ERROR_INVALID_PARENT:
598 resp = PTP_RESPONSE_INVALIDPARENT;
600 case MTP_ERROR_STORE_NOT_AVAILABLE:
601 resp = PTP_RESPONSE_STORENOTAVAILABLE;
604 resp = PTP_RESPONSE_OK;
607 resp = PTP_RESPONSE_GEN_ERROR;
610 if (resp != PTP_RESPONSE_OK) {
611 _prop_deinit_ptparray(&handle_arr);
612 _cmd_hdlr_send_response_code(hdlr, resp);
616 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
617 num_bytes = _prop_get_size_ptparray(&handle_arr);
618 ptr = _hdlr_alloc_buf_data_container(&blk, num_bytes, num_bytes);
620 _prop_pack_ptparray(&handle_arr, ptr, num_bytes);
621 _prop_deinit_ptparray(&handle_arr);
622 _device_set_phase(DEVICE_PHASE_DATAIN);
623 if (_hdlr_send_data_container(&blk)) {
624 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
626 /*Host Cancelled data-in transfer.*/
627 _device_set_phase(DEVICE_PHASE_NOTREADY);
628 DBG("DEVICE_PHASE_NOTREADY!!");
631 _prop_deinit_ptparray(&handle_arr);
632 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
638 static void __get_object_info(mtp_handler_t *hdlr)
640 mtp_uint32 obj_handle = 0;
641 data_blk_t blk = { 0 };
642 mtp_uint32 num_bytes = 0;
643 mtp_uchar *ptr = NULL;
644 mtp_obj_t *obj = NULL;
645 mtp_char f_name[MTP_MAX_FILENAME_SIZE + 1] = { 0 };
646 mtp_wchar wf_name[MTP_MAX_FILENAME_SIZE + 1] = { 0 };
647 ptp_string_t ptp_string = { 0 };
649 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
650 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
652 _cmd_hdlr_send_response_code(hdlr,
653 PTP_RESPONSE_PARAM_NOTSUPPORTED);
656 obj_handle = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
657 if (MTP_ERROR_NONE != _hutil_get_object_entry(obj_handle, &obj)) {
658 _cmd_hdlr_send_response_code(hdlr,
659 PTP_RESPONSE_INVALID_OBJ_HANDLE);
663 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
665 _util_get_file_name(obj->file_path, f_name);
666 _util_utf8_to_utf16(wf_name, sizeof(wf_name) / WCHAR_SIZ, f_name);
667 _prop_copy_char_to_ptpstring(&ptp_string, wf_name, WCHAR_TYPE);
669 num_bytes = _entity_get_object_info_size(obj, &ptp_string);
670 ptr = _hdlr_alloc_buf_data_container(&blk, num_bytes, num_bytes);
671 if (num_bytes == _entity_pack_obj_info(obj, &ptp_string, ptr,
673 _device_set_phase(DEVICE_PHASE_DATAIN);
674 if (_hdlr_send_data_container(&blk)) {
675 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
677 /* Host Cancelled data-in transfer*/
678 _device_set_phase(DEVICE_PHASE_NOTREADY);
679 DBG("DEVICE_PHASE_NOTREADY!!");
682 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
688 static void __get_object(mtp_handler_t *hdlr)
690 mtp_uint32 obj_handle;
695 mtp_uint64 num_bytes;
696 mtp_uint64 total_len;
698 mtp_uint16 resp = PTP_RESPONSE_OK;
699 mtp_uint32 packet_len;
700 mtp_uint32 read_len = 0;
704 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
705 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
706 _cmd_hdlr_send_response_code(hdlr,
707 PTP_RESPONSE_PARAM_NOTSUPPORTED);
711 obj_handle = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
712 obj = _device_get_object_with_handle(obj_handle);
714 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
715 _cmd_hdlr_send_response_code(hdlr, resp);
719 #ifdef MTP_SUPPORT_SET_PROTECTION
720 /* Check to see if the data is non-transferable */
721 if (obj->obj_info->protcn_status ==
722 MTP_PROTECTIONSTATUS_NONTRANSFERABLE_DATA) {
723 resp = PTP_RESPONSE_ACCESSDENIED;
724 _cmd_hdlr_send_response_code(hdlr, resp);
727 #endif /* MTP_SUPPORT_SET_PROTECTION */
729 path = obj->file_path;
730 num_bytes = obj->obj_info->file_size;
731 total_len = num_bytes + sizeof(header_container_t);
732 packet_len = total_len < g_conf.read_file_size ? num_bytes :
733 (g_conf.read_file_size - sizeof(header_container_t));
735 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
736 ptr = _hdlr_alloc_buf_data_container(&blk, packet_len, num_bytes);
738 ERR("_hdlr_alloc_buf_data_container() Fail");
739 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
743 _device_set_phase(DEVICE_PHASE_DATAIN);
744 h_file = _util_file_open(path, MTP_FILE_READ, &error);
745 if (h_file == NULL) {
746 ERR("_util_file_open() Fail");
747 _device_set_phase(DEVICE_PHASE_NOTREADY);
748 if (EACCES == error) {
749 _cmd_hdlr_send_response_code(hdlr,
750 PTP_RESPONSE_ACCESSDENIED);
753 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
757 _util_file_read(h_file, ptr, packet_len, &read_len);
759 ERR("_util_file_read() Fail");
760 ERR_SECURE("filename[%s]", path);
761 _device_set_phase(DEVICE_PHASE_NOTREADY);
762 resp = PTP_RESPONSE_INCOMPLETETRANSFER;
766 /* First Packet with Header */
767 if (PTP_EVENTCODE_CANCELTRANSACTION == _transport_get_control_event() ||
768 FALSE == _hdlr_send_bulk_data(blk.data, blk.len)) {
769 _device_set_phase(DEVICE_PHASE_NOTREADY);
770 resp = PTP_RESPONSE_INCOMPLETETRANSFER;
771 ERR("First Packet send Fail");
772 ERR_SECURE("filename[%s]\n", path);
776 sent = sizeof(header_container_t) + read_len;
779 while (sent < total_len) {
780 _util_file_read(h_file, ptr, g_conf.read_file_size, &read_len);
782 ERR("_util_file_read() Fail");
783 ERR_SECURE("filename[%s]\n", path);
784 _device_set_phase(DEVICE_PHASE_NOTREADY);
785 resp = PTP_RESPONSE_INCOMPLETETRANSFER;
789 if (PTP_EVENTCODE_CANCELTRANSACTION == _transport_get_control_event() ||
790 FALSE == _hdlr_send_bulk_data(ptr, read_len)) {
791 _device_set_phase(DEVICE_PHASE_NOTREADY);
792 resp = PTP_RESPONSE_INCOMPLETETRANSFER;
793 ERR("Packet send Fail");
794 ERR_SECURE("filename[%s]\n", path);
801 if (total_len % ((mtp_uint64)_transport_get_usb_packet_len()) == 0)
802 _transport_send_zlp();
805 _util_file_close(h_file);
808 _cmd_hdlr_send_response_code(hdlr, resp);
811 static void __send_object_info(mtp_handler_t *hdlr)
813 mtp_uint16 resp = PTP_RESPONSE_UNDEFINED;
814 mtp_uint32 store_id = 0;
815 mtp_uint32 h_parent = 0;
816 mtp_uint32 num_bytes = 0;
817 data_blk_t blk = { 0 };
818 mtp_uint32 resp_param[3] = { 0 };
819 mtp_obj_t *obj = NULL;
821 obj_data_t obdata = { 0 };
823 store_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
825 store_id = _device_get_default_store_id();
827 h_parent = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
829 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
830 resp = PTP_RESPONSE_PARAM_NOTSUPPORTED;
831 if (_device_get_phase() != DEVICE_PHASE_NOTREADY)
832 _cmd_hdlr_send_response_code(hdlr, resp);
837 _device_set_phase(DEVICE_PHASE_DATAOUT);
838 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
839 num_bytes = MAX_SIZE_IN_BYTES_OF_OBJECT_INFO;
840 if (_hdlr_rcv_data_container(&blk, num_bytes) == FALSE) {
841 _device_set_phase(DEVICE_PHASE_NOTREADY);
843 if (TRUE == hdlr->data4_send_obj.is_valid) {
844 obdata.store_id = hdlr->data4_send_obj.store_id;
845 obdata.obj_size = hdlr->data4_send_obj.file_size;
846 obdata.obj = hdlr->data4_send_obj.obj;
847 hdlr->data4_send_obj.obj = NULL;
849 ret = _hutil_construct_object_entry(store_id, h_parent,
850 ((hdlr->data4_send_obj.is_valid == TRUE) ? (&obdata)
851 : (NULL)), &obj, _hdlr_get_payload_data(&blk),
852 _hdlr_get_payload_size(&blk));
853 hdlr->data4_send_obj.is_valid = FALSE;
856 if (obj->obj_info->obj_fmt == PTP_FMT_ASSOCIATION) {
857 hdlr->data4_send_obj.obj = NULL;
858 hdlr->data4_send_obj.is_valid = FALSE;
859 hdlr->data4_send_obj.obj_handle = obj->obj_handle;
860 hdlr->data4_send_obj.h_parent = h_parent;
861 hdlr->data4_send_obj.store_id = store_id;
863 #ifdef MTP_USE_SELFMAKE_ABSTRACTION
864 else if (obj->obj_info->file_size == 0 &&
865 obj->obj_info->obj_fmt > MTP_FMT_UNDEFINED_COLLECTION &&
866 obj->obj_info->obj_fmt < MTP_FMT_UNDEFINED_DOC) {
867 hdlr->data4_send_obj.obj = NULL;
868 hdlr->data4_send_obj.is_valid = FALSE;
869 hdlr->data4_send_obj.obj_handle = obj->obj_handle;
870 hdlr->data4_send_obj.h_parent = h_parent;
871 hdlr->data4_send_obj.store_id = store_id;
873 #endif /*MTP_USE_SELFMAKE_ABSTRACTION*/
875 hdlr->data4_send_obj.is_valid = TRUE;
876 hdlr->data4_send_obj.obj_handle = obj->obj_handle;
877 hdlr->data4_send_obj.h_parent = h_parent;
878 hdlr->data4_send_obj.store_id = store_id;
879 hdlr->data4_send_obj.obj = obj;
880 hdlr->data4_send_obj.file_size =
881 obj->obj_info->file_size;
883 resp = PTP_RESPONSE_OK;
885 case MTP_ERROR_STORE_NOT_AVAILABLE:
886 resp = PTP_RESPONSE_STORENOTAVAILABLE;
887 DBG("PTP_RESPONSE_STORENOTAVAILABLE");
889 case MTP_ERROR_INVALID_PARAM:
890 resp = PTP_RESPONSE_PARAM_NOTSUPPORTED;
891 DBG("PTP_RESPONSE_PARAM_NOTSUPPORTED");
893 case MTP_ERROR_INVALID_STORE:
894 resp = PTP_RESPONSE_INVALID_STORE_ID;
895 DBG("PTP_RESPONSE_INVALID_STORE_ID");
897 case MTP_ERROR_STORE_READ_ONLY:
898 resp = PTP_RESPONSE_STORE_READONLY;
900 case MTP_ERROR_STORE_FULL:
901 resp = PTP_RESPONSE_STOREFULL;
902 DBG("PTP_RESPONSE_STOREFULL");
904 case MTP_ERROR_GENERAL:
905 resp = PTP_RESPONSE_GEN_ERROR;
906 DBG("PTP_RESPONSE_GEN_ERROR");
908 case MTP_ERROR_INVALID_OBJECT_INFO:
909 resp = MTP_RESPONSECODE_INVALIDDATASET;
910 DBG("MTP_RESPONSECODE_INVALIDDATASET");
912 case MTP_ERROR_INVALID_OBJECTHANDLE:
913 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
914 DBG("PTP_RESPONSE_INVALID_OBJ_HANDLE");
916 case MTP_ERROR_INVALID_PARENT:
917 resp = PTP_RESPONSE_INVALIDPARENT;
918 DBG("PTP_RESPONSE_INVALIDPARENT");
920 case MTP_ERROR_ACCESS_DENIED:
921 resp = PTP_RESPONSE_ACCESSDENIED;
922 DBG("PTP_RESPONSE_ACCESSDENIED");
925 resp = PTP_RESPONSE_GEN_ERROR;
926 DBG("PTP_RESPONSE_GEN_ERROR");
932 if (_device_get_phase() != DEVICE_PHASE_NOTREADY) {
933 if (resp == PTP_RESPONSE_OK) {
934 hdlr->last_fmt_code = obj->obj_info->obj_fmt;
935 resp_param[0] = hdlr->data4_send_obj.store_id;
937 /* PTP spec here requires that 0xFFFFFFFF be sent if root is the parent object,
938 * while in some situations(e.g. MoveObject, CopyObject), 0x00000000 (as
939 * PTP_OBJECTHANDLE_ROOT is defined) represents the root.
941 resp_param[1] = (hdlr->data4_send_obj.h_parent
942 != PTP_OBJECTHANDLE_ROOT) ?
943 hdlr->data4_send_obj.h_parent :
945 resp_param[2] = hdlr->data4_send_obj.obj_handle;
946 _cmd_hdlr_send_response(hdlr, resp, 3, resp_param);
948 _cmd_hdlr_send_response_code(hdlr, resp);
953 static void __send_object(mtp_handler_t *hdlr)
955 data_blk_t blk = { 0 };
956 mtp_uint16 resp = PTP_RESPONSE_OK;
957 mtp_char temp_fpath[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
959 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0) ||
960 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
961 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
963 ERR("unsupported parameter");
964 _device_set_phase(DEVICE_PHASE_NOTREADY);
965 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_INVALIDPARAM);
968 #ifndef MTP_USE_SELFMAKE_ABSTRACTION
969 if (hdlr->data4_send_obj.is_valid != TRUE) {
970 DBG("invalide object info");
971 _device_set_phase(DEVICE_PHASE_NOTREADY);
974 #endif /*MTP_USE_SELFMAKE_ABSTRACTION*/
976 _device_set_phase(DEVICE_PHASE_DATAOUT);
977 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
979 if (_hdlr_rcv_file_in_data_container(&blk, temp_fpath,
980 MTP_MAX_PATHNAME_SIZE + 1) == FALSE) {
981 _device_set_phase(DEVICE_PHASE_IDLE);
983 ERR("_hdlr_rcv_file_in_data_container() Fail");
985 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
989 switch (_hutil_write_file_data(hdlr->data4_send_obj.store_id,
990 hdlr->data4_send_obj.obj, temp_fpath)) {
992 case MTP_ERROR_INVALID_OBJECT_INFO:
993 resp = PTP_RESPONSE_NOVALID_OBJINFO;
994 DBG("PTP_RESPONSE_NOVALID_OBJINFO");
996 #ifdef MTP_USE_SELFMAKE_ABSTRACTION
997 case MTP_ERROR_INVALID_PARAM: /* association file*/
998 #endif /*MTP_USE_SELFMAKE_ABSTRACTION*/
1000 resp = PTP_RESPONSE_OK;
1001 DBG("PTP_RESPONSE_OK");
1003 case MTP_ERROR_STORE_FULL:
1004 resp = PTP_RESPONSE_STOREFULL;
1005 DBG("PTP_RESPONSE_STOREFULL");
1008 resp = PTP_RESPONSE_GEN_ERROR;
1009 DBG("PTP_RESPONSE_GEN_ERROR");
1011 _cmd_hdlr_send_response_code(hdlr, resp);
1013 /* This object info has been consumed.*/
1014 hdlr->data4_send_obj.obj = NULL;
1015 hdlr->data4_send_obj.is_valid = FALSE;
1020 static void __delete_object(mtp_handler_t *hdlr)
1022 mtp_uint32 obj_handle = 0;
1024 mtp_uint16 resp = 0;
1026 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
1028 ERR("Parameters not supported");
1029 _cmd_hdlr_send_response_code(hdlr,
1030 PTP_RESPONSE_PARAM_NOTSUPPORTED);
1034 obj_handle = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
1035 fmt = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
1036 if ((PTP_FORMATCODE_NOTUSED != fmt) &&
1037 (obj_handle != PTP_OBJECTHANDLE_ALL)) {
1038 ERR("Invalid object format");
1039 _cmd_hdlr_send_response_code(hdlr,
1040 PTP_RESPONSE_INVALID_OBJ_FMTCODE);
1044 _transport_set_mtp_operation_state(MTP_STATE_DATA_PROCESSING);
1046 switch (_hutil_remove_object_entry(obj_handle, fmt)) {
1047 case MTP_ERROR_NONE:
1048 resp = PTP_RESPONSE_OK;
1050 case MTP_ERROR_STORE_READ_ONLY:
1051 resp = PTP_RESPONSE_STORE_READONLY;
1053 case MTP_ERROR_PARTIAL_DELETION:
1054 resp = PTP_RESPONSE_PARTIAL_DELETION;
1056 case MTP_ERROR_OBJECT_WRITE_PROTECTED:
1057 resp = PTP_RESPONSE_OBJ_WRITEPROTECTED;
1059 case MTP_ERROR_ACCESS_DENIED:
1060 resp = PTP_RESPONSE_ACCESSDENIED;
1062 case MTP_ERROR_INVALID_OBJECTHANDLE:
1063 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
1066 resp = PTP_RESPONSE_GEN_ERROR;
1069 _transport_set_mtp_operation_state(MTP_STATE_ONSERVICE);
1070 _cmd_hdlr_send_response_code(hdlr, resp);
1073 static void __format_store(mtp_handler_t *hdlr)
1075 mtp_uint32 store_id = 0;
1076 mtp_uint32 fs_fmt = 0;
1078 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
1079 _cmd_hdlr_send_response_code(hdlr,
1080 PTP_RESPONSE_PARAM_NOTSUPPORTED);
1084 store_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
1085 fs_fmt = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
1087 _hutil_format_storage(store_id, fs_fmt);
1089 /* although there is remain file, send OK */
1090 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
1093 static void __reset_device(mtp_handler_t *hdlr)
1095 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0) ||
1096 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
1097 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
1099 _cmd_hdlr_send_response_code(hdlr,
1100 PTP_RESPONSE_PARAM_NOTSUPPORTED);
1104 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
1107 static void __get_device_prop_desc(mtp_handler_t *hdlr)
1109 device_prop_desc_t dev_prop = { { 0 }, };
1110 device_prop_desc_t *prop_ptr = NULL;
1111 ptp_string_t ptp_str = { 0, { 0 } };
1112 data_blk_t blk = { 0 };
1113 mtp_uint32 prop_id = 0;
1114 mtp_uint32 resp = 0;
1115 mtp_uint32 num_bytes = 0;
1116 mtp_uchar *ptr = NULL;
1117 mtp_wchar temp[MTP_MAX_REG_STRING + 1] = { 0 };
1119 prop_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
1121 #ifdef MTP_SUPPORT_DEVICEPROP_BATTERYLEVEL
1122 case PTP_PROPERTYCODE_BATTERYLEVEL:
1126 prop_ptr = _device_get_device_property(prop_id);
1127 if (NULL == prop_ptr) {
1128 ERR("prop_ptr is NULL!");
1132 batt = _util_get_battery_level();
1133 if (FALSE == _prop_set_current_integer(prop_ptr, batt))
1134 ERR("_util_get_battery_level() Fail");
1137 #endif /* MTP_SUPPORT_DEVICEPROP_BATTERYLEVEL */
1139 case MTP_PROPERTYCODE_DEVICEFRIENDLYNAME:
1141 mtp_char *dev_name = _device_get_device_name();
1142 if (dev_name == NULL) {
1143 ERR("_device_get_device_name() Fail");
1147 prop_ptr = _device_get_device_property(prop_id);
1148 if (NULL == prop_ptr) {
1149 ERR("prop_ptr is Null");
1153 _util_utf8_to_utf16(temp, sizeof(temp) / WCHAR_SIZ, dev_name);
1154 _prop_copy_char_to_ptpstring(&ptp_str, temp, WCHAR_TYPE);
1155 _prop_set_current_string(prop_ptr, &ptp_str);
1160 case MTP_PROPERTYCODE_SYNCHRONIZATIONPARTNER:
1162 mtp_char *sync_ptr = _device_get_sync_partner();
1163 if (NULL == sync_ptr) {
1164 ERR("_device_get_sync_partner() Fail");
1167 prop_ptr = _device_get_device_property(prop_id);
1168 if (NULL == prop_ptr) {
1169 ERR("prop_ptr is Null");
1174 _util_utf8_to_utf16(temp, sizeof(temp) / WCHAR_SIZ, sync_ptr);
1175 _prop_copy_char_to_ptpstring(&ptp_str, temp, WCHAR_TYPE);
1176 _prop_set_current_string(prop_ptr, &ptp_str);
1180 case MTP_PROPERTYCODE_DEVICEICON:
1183 mtp_uint32 bytes_read = 0;
1184 mtp_uint32 file_size = 0;
1186 mtp_uchar *data = NULL;
1189 prop_ptr = _device_get_device_property(prop_id);
1190 if (NULL == prop_ptr) {
1191 ERR("prop_ptr is Null");
1195 h_file = _util_file_open(MTP_DEVICE_ICON, MTP_FILE_READ, &err);
1196 if (h_file == NULL) {
1197 ERR("file handle is not valid");
1198 _cmd_hdlr_send_response_code(hdlr,
1199 PTP_RESPONSE_GEN_ERROR);
1202 if (fstat(fileno((FILE *)h_file), &buf) != 0) {
1203 _util_file_close(h_file);
1204 _cmd_hdlr_send_response_code(hdlr,
1205 PTP_RESPONSE_GEN_ERROR);
1208 file_size = buf.st_size;
1209 data = (mtp_uchar *)g_malloc(file_size + sizeof(mtp_uint32));
1211 ERR("g_malloc() Fail");
1212 _util_file_close(h_file);
1213 _cmd_hdlr_send_response_code(hdlr,
1214 PTP_RESPONSE_GEN_ERROR);
1217 memcpy(data, &file_size, sizeof(mtp_uint32));
1218 _util_file_read(h_file, &data[sizeof(mtp_uint32)], file_size,
1220 if (bytes_read != file_size) {
1221 ERR("Number of read bytes less than requested");
1222 _util_file_close(h_file);
1224 _cmd_hdlr_send_response_code(hdlr,
1225 PTP_RESPONSE_GEN_ERROR);
1229 _prop_set_current_array(prop_ptr, data);
1230 _prop_set_default_array(&(prop_ptr->propinfo),
1231 (mtp_uchar *)&data[sizeof(mtp_uint32)], bytes_read);
1233 _util_file_close(h_file);
1238 ERR("Unknown PropId : [0x%x]\n", prop_id);
1242 if (_hutil_get_device_property(prop_id, &dev_prop) != MTP_ERROR_NONE) {
1243 ERR("_hutil_get_device_property returned error");
1244 resp = PTP_RESPONSE_PROP_NOTSUPPORTED;
1245 _cmd_hdlr_send_response_code(hdlr, resp);
1248 num_bytes = _prop_size_device_prop_desc(&dev_prop);
1250 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
1251 ptr = _hdlr_alloc_buf_data_container(&blk, num_bytes, num_bytes);
1253 resp = PTP_RESPONSE_GEN_ERROR;
1254 _cmd_hdlr_send_response_code(hdlr, resp);
1258 if (_prop_pack_device_prop_desc(&dev_prop, ptr, num_bytes) != num_bytes) {
1259 resp = PTP_RESPONSE_GEN_ERROR;
1260 _cmd_hdlr_send_response_code(hdlr, resp);
1265 _device_set_phase(DEVICE_PHASE_DATAIN);
1266 if (_hdlr_send_data_container(&blk))
1267 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
1269 _device_set_phase(DEVICE_PHASE_NOTREADY);
1270 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
1277 static void __get_device_prop_value(mtp_handler_t *hdlr)
1280 ptp_string_t ptp_str = { 0, { 0 } };
1281 data_blk_t blk = { 0 };
1282 mtp_uint32 prop_id = 0;
1283 mtp_uint32 no_bytes = 0;
1284 mtp_uchar *ptr = NULL;
1285 mtp_wchar temp[MTP_MAX_REG_STRING + 1] = { 0 };
1287 prop_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
1288 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
1291 #ifdef MTP_SUPPORT_DEVICEPROP_BATTERYLEVEL
1292 case PTP_PROPERTYCODE_BATTERYLEVEL: {
1295 batt = _util_get_battery_level();
1296 no_bytes = sizeof(batt);
1298 ptr = _hdlr_alloc_buf_data_container(&blk, no_bytes, no_bytes);
1300 _cmd_hdlr_send_response_code(hdlr,
1301 PTP_RESPONSE_GEN_ERROR);
1304 memcpy(ptr, &batt, no_bytes);
1305 #ifdef __BIG_ENDIAN__
1306 _util_conv_byte_order(ptr, no_bytes);
1307 #endif /*__BIG_ENDIAN__*/
1310 #endif /* MTP_SUPPORT_DEVICEPROP_BATTERYLEVEL */
1312 case MTP_PROPERTYCODE_DEVICEFRIENDLYNAME:
1315 mtp_char *device = _device_get_device_name();
1316 if (device == NULL) {
1317 ERR("_device_get_device_name() Fail");
1318 _cmd_hdlr_send_response_code(hdlr,
1319 PTP_RESPONSE_GEN_ERROR);
1323 _util_utf8_to_utf16(temp, sizeof(temp) / WCHAR_SIZ, device);
1324 _prop_copy_char_to_ptpstring(&ptp_str, temp, WCHAR_TYPE);
1325 no_bytes = _prop_size_ptpstring(&ptp_str);
1328 ptr = _hdlr_alloc_buf_data_container(&blk, no_bytes, no_bytes);
1330 _cmd_hdlr_send_response_code(hdlr,
1331 PTP_RESPONSE_GEN_ERROR);
1335 if (_prop_pack_ptpstring(&ptp_str, ptr, no_bytes) != no_bytes) {
1336 _cmd_hdlr_send_response_code(hdlr,
1337 PTP_RESPONSE_GEN_ERROR);
1344 case MTP_PROPERTYCODE_SYNCHRONIZATIONPARTNER:
1347 mtp_char *sync_ptr = _device_get_sync_partner();
1348 if (sync_ptr == NULL) {
1349 ERR("_device_get_sync_partner() Fail");
1350 _cmd_hdlr_send_response_code(hdlr,
1351 PTP_RESPONSE_GEN_ERROR);
1354 _util_utf8_to_utf16(temp, sizeof(temp) / WCHAR_SIZ, sync_ptr);
1357 _prop_copy_char_to_ptpstring(&ptp_str, temp, WCHAR_TYPE);
1358 no_bytes = _prop_size_ptpstring(&ptp_str);
1360 ptr = _hdlr_alloc_buf_data_container(&blk, no_bytes, no_bytes);
1362 _cmd_hdlr_send_response_code(hdlr,
1363 PTP_RESPONSE_GEN_ERROR);
1367 if (_prop_pack_ptpstring(&ptp_str, ptr, no_bytes) != no_bytes) {
1368 _cmd_hdlr_send_response_code(hdlr,
1369 PTP_RESPONSE_GEN_ERROR);
1376 case MTP_PROPERTYCODE_DEVICEICON:
1380 mtp_uint32 read_bytes = 0;
1381 mtp_uint32 file_size = 0;
1383 mtp_uchar *data = NULL;
1385 ptp_array_t val_arr = { 0 };
1388 h_file = _util_file_open(MTP_DEVICE_ICON, MTP_FILE_READ, &err);
1389 if (h_file == NULL) {
1390 ERR("file handle is not valid");
1391 _cmd_hdlr_send_response_code(hdlr,
1392 PTP_RESPONSE_GEN_ERROR);
1395 if (fstat(fileno(h_file), &buf) != 0) {
1396 _util_file_close(h_file);
1397 _cmd_hdlr_send_response_code(hdlr,
1398 PTP_RESPONSE_GEN_ERROR);
1402 file_size = buf.st_size;
1403 data = (mtp_uchar *)g_malloc(file_size);
1405 ERR("g_malloc() Fail");
1406 _util_file_close(h_file);
1407 _cmd_hdlr_send_response_code(hdlr,
1408 PTP_RESPONSE_GEN_ERROR);
1412 _util_file_read(h_file, &data, file_size, &read_bytes);
1413 if (read_bytes != file_size) {
1414 ERR("Number of read bytes less than requested");
1415 _util_file_close(h_file);
1417 _cmd_hdlr_send_response_code(hdlr,
1418 PTP_RESPONSE_GEN_ERROR);
1422 _prop_init_ptparray(&val_arr, UINT8_TYPE);
1423 _prop_grow_ptparray(&val_arr, read_bytes);
1424 for (ii = 0; ii < read_bytes; ii++)
1425 _prop_append_ele_ptparray(&val_arr, data[ii]);
1427 no_bytes = _prop_get_size_ptparray(&val_arr);
1428 ptr = _hdlr_alloc_buf_data_container(&blk, no_bytes, no_bytes);
1430 _cmd_hdlr_send_response_code(hdlr,
1431 PTP_RESPONSE_GEN_ERROR);
1433 _util_file_close(h_file);
1434 _prop_deinit_ptparray(&val_arr);
1437 if (_prop_pack_ptparray(&val_arr, ptr, no_bytes) != no_bytes) {
1438 _cmd_hdlr_send_response_code(hdlr,
1439 PTP_RESPONSE_GEN_ERROR);
1442 _prop_deinit_ptparray(&val_arr);
1443 _util_file_close(h_file);
1448 _prop_deinit_ptparray(&val_arr);
1449 _util_file_close(h_file);
1455 ERR("Unknown PropId : [0x%x]\n", prop_id);
1456 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
1460 _device_set_phase(DEVICE_PHASE_DATAIN);
1461 if (_hdlr_send_data_container(&blk)) {
1462 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
1464 _device_set_phase(DEVICE_PHASE_NOTREADY);
1465 _cmd_hdlr_send_response_code(hdlr,
1466 PTP_RESPONSE_INCOMPLETETRANSFER);
1472 static void __set_device_prop_value(mtp_handler_t *hdlr)
1474 mtp_uint32 prop_id = 0;
1475 data_blk_t blk = { 0 };
1476 mtp_uint32 max_bytes = 0;
1477 mtp_uint16 resp = PTP_RESPONSE_OK;
1479 mtp_char *d_raw = NULL;
1481 prop_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
1482 _device_set_phase(DEVICE_PHASE_DATAOUT);
1484 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
1485 max_bytes = MAX_SIZE_IN_BYTES_OF_PROP_VALUE;
1487 if (FALSE == _hdlr_rcv_data_container(&blk, max_bytes)) {
1488 ERR("_hdlr_rcv_data_container() Fail");
1489 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
1493 d_raw = (mtp_char *)_hdlr_get_payload_data(&blk);
1494 if (NULL != d_raw) {
1495 ret = _hutil_set_device_property(prop_id, d_raw,
1496 _hdlr_get_payload_size(&blk));
1498 ret = MTP_ERROR_INVALID_OBJ_PROP_CODE;
1502 case MTP_ERROR_NONE: {
1503 #ifdef MTP_USE_INFORMATION_REGISTRY
1505 mtp_char temp[MTP_MAX_REG_STRING * 3 + 1] = { 0 };
1506 mtp_wchar parsed_buf[MTP_MAX_REG_STRING + 1] = { 0 };
1507 mtp_uchar parse_sz = 0;
1509 if (MTP_PROPERTYCODE_SYNCHRONIZATIONPARTNER == prop_id) {
1510 parse_sz = d_raw[0];
1511 _util_wchar_ncpy(parsed_buf, (mtp_wchar *)&d_raw[1],
1512 parse_sz > MTP_MAX_REG_STRING ?
1513 MTP_MAX_REG_STRING : parse_sz);
1514 _util_utf16_to_utf8(temp, sizeof(temp), parsed_buf);
1515 _device_set_sync_partner(temp);
1516 if (!g_strcmp0(temp,
1517 MTP_DEV_PROPERTY_NULL_SYNCPARTNER)) {
1518 vconf_set_str(VCONFKEY_MTP_SYNC_PARTNER_STR,
1521 vconf_set_str(VCONFKEY_MTP_SYNC_PARTNER_STR,
1525 #endif /*MTP_USE_INFORMATION_REGISTRY*/
1527 resp = PTP_RESPONSE_OK;
1529 case MTP_ERROR_ACCESS_DENIED:
1530 resp = PTP_RESPONSE_ACCESSDENIED;
1532 case MTP_ERROR_INVALID_OBJ_PROP_VALUE:
1533 resp = PTP_RESPONSE_INVALIDPROPVALUE;
1536 resp = PTP_RESPONSE_PROP_NOTSUPPORTED;
1539 _cmd_hdlr_send_response_code(hdlr, resp);
1545 static void __get_partial_object(mtp_handler_t *hdlr)
1547 mtp_uint32 h_obj = 0;
1549 mtp_uint32 data_sz = 0;
1550 mtp_uint32 send_bytes = 0;
1551 data_blk_t blk = { 0 };
1552 mtp_uchar *ptr = NULL;
1553 mtp_uint16 resp = 0;
1554 mtp_uint64 f_size = 0;
1555 mtp_uint64 total_sz = 0;
1557 offset = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
1558 data_sz = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2);
1559 h_obj = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
1561 switch (_hutil_get_object_entry_size(h_obj, &f_size)) {
1563 case MTP_ERROR_INVALID_OBJECTHANDLE:
1564 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
1566 case MTP_ERROR_NONE:
1567 if (data_sz > (f_size - offset))
1568 send_bytes = f_size - offset;
1570 send_bytes = data_sz;
1571 resp = PTP_RESPONSE_OK;
1574 resp = PTP_RESPONSE_GEN_ERROR;
1578 if (PTP_RESPONSE_OK != resp) {
1579 _cmd_hdlr_send_response_code(hdlr, resp);
1583 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
1584 ptr = _hdlr_alloc_buf_data_container(&blk, send_bytes, send_bytes);
1587 switch (_hutil_read_file_data_from_offset(h_obj, offset, ptr, &send_bytes)) {
1588 case MTP_ERROR_NONE:
1589 resp = PTP_RESPONSE_OK;
1591 case MTP_ERROR_INVALID_OBJECTHANDLE:
1592 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
1595 resp = PTP_RESPONSE_GEN_ERROR;
1598 resp = PTP_RESPONSE_GEN_ERROR;
1601 if (PTP_RESPONSE_OK == resp) {
1602 _device_set_phase(DEVICE_PHASE_DATAIN);
1603 if (_hdlr_send_data_container(&blk)) {
1604 total_sz = send_bytes + sizeof(header_container_t);
1605 if (total_sz % _transport_get_usb_packet_len() == 0)
1606 _transport_send_zlp();
1607 _cmd_hdlr_send_response(hdlr, resp, 1, &send_bytes);
1612 /*Host Cancelled data-in transfer*/
1613 _device_set_phase(DEVICE_PHASE_NOTREADY);
1618 _cmd_hdlr_send_response_code(hdlr, resp);
1624 static void __get_object_references(mtp_handler_t *hdlr)
1626 mtp_uint32 h_obj = 0;
1627 ptp_array_t ref_arr = { 0 };
1628 data_blk_t blk = { 0 };
1629 mtp_uint32 num_bytes = 0;
1630 mtp_uchar *ptr = NULL;
1631 mtp_uint32 num_ele = 0;
1632 mtp_uint16 resp = 0;
1634 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
1635 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
1637 ERR("Unsupported Parameters");
1638 _cmd_hdlr_send_response_code(hdlr,
1639 PTP_RESPONSE_PARAM_NOTSUPPORTED);
1643 h_obj = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
1645 switch (_hutil_get_object_references(h_obj, &ref_arr, &num_ele)) {
1646 case MTP_ERROR_INVALID_OBJECTHANDLE:
1647 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
1649 case MTP_ERROR_NONE:
1650 resp = PTP_RESPONSE_OK;
1653 resp = PTP_RESPONSE_GEN_ERROR;
1656 if (resp != PTP_RESPONSE_OK) {
1657 _cmd_hdlr_send_response_code(hdlr, resp);
1661 if (resp == PTP_RESPONSE_OK && num_ele == 0) {
1662 _cmd_hdlr_send_response_code(hdlr, resp);
1666 num_bytes = _prop_get_size_ptparray(&ref_arr);
1667 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
1669 ptr = _hdlr_alloc_buf_data_container(&blk, num_bytes, num_bytes);
1670 if (num_bytes == _prop_pack_ptparray(&ref_arr, ptr, num_bytes)) {
1671 _device_set_phase(DEVICE_PHASE_DATAIN);
1672 if (_hdlr_send_data_container(&blk)) {
1673 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
1675 /* Host Cancelled data-in transfer*/
1676 _device_set_phase(DEVICE_PHASE_NOTREADY);
1679 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
1682 _prop_deinit_ptparray(&ref_arr);
1688 static void __set_object_references(mtp_handler_t *hdlr)
1690 mtp_uint32 h_obj = 0;
1691 data_blk_t blk = { 0 };
1692 mtp_uint32 max_bytes = 0;
1693 mtp_uint16 resp = PTP_RESPONSE_OK;
1694 mtp_uint32 num_ref = 0;
1696 mtp_uint32 *ref_ptr = NULL;
1697 mtp_uchar *ptr = NULL;
1698 mtp_uint32 ref_handle = 0;
1700 h_obj = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
1701 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
1702 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
1704 resp = PTP_RESPONSE_PARAM_NOTSUPPORTED;
1705 _cmd_hdlr_send_response_code(hdlr, resp);
1708 _device_set_phase(DEVICE_PHASE_DATAOUT);
1709 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
1711 /* temporarily set a big number for data size received */
1713 max_bytes = MTP_MAX_REFDB_ROWCNT * sizeof(mtp_uint32);
1714 if (_hdlr_rcv_data_container(&blk, max_bytes) == FALSE) {
1715 DBG("_hdlr_rcv_data_container() Fail");
1716 _device_set_phase(DEVICE_PHASE_IDLE);
1717 resp = PTP_RESPONSE_GEN_ERROR;
1720 if (PTP_RESPONSE_OK != resp) {
1721 _cmd_hdlr_send_response_code(hdlr, resp);
1726 ptr = _hdlr_get_payload_data(&blk);
1730 memcpy(&num_ref, ptr, sizeof(mtp_uint32));
1731 #ifdef __BIG_ENDIAN__
1732 _util_conv_byte_order(&num_ref, sizeof(DWORD));
1733 #endif /* __BIG_ENDIAN__ */
1735 ptr += sizeof(mtp_uint32);
1736 if (_hdlr_get_payload_size(&blk) < (num_ref + 1) * sizeof(mtp_uint32)) {
1738 resp = PTP_RESPONSE_GEN_ERROR;
1739 _cmd_hdlr_send_response_code(hdlr, resp);
1744 ref_ptr = (mtp_uint32 *)ptr;
1745 if (MTP_ERROR_NONE != _hutil_remove_object_reference(h_obj,
1746 PTP_OBJECTHANDLE_ALL)) {
1747 resp = PTP_RESPONSE_GEN_ERROR;
1748 _cmd_hdlr_send_response_code(hdlr, resp);
1752 for (idx = 0; idx < num_ref; idx++) {
1753 ref_handle = ref_ptr[idx];
1754 #ifdef __BIG_ENDIAN__
1755 _util_conv_byte_order(&ref_handle, sizeof(mtp_uint32));
1756 #endif /*__BIG_ENDIAN__*/
1757 _device_get_object_with_handle(ref_handle);
1760 _hutil_add_object_references_enhanced(h_obj, (mtp_uchar *)ref_ptr,
1762 _cmd_hdlr_send_response_code(hdlr, resp);
1768 static void __get_object_prop_desc(mtp_handler_t *hdlr)
1770 mtp_uint32 prop_id = 0;
1772 obj_prop_desc_t prop = { { 0 }, };
1773 data_blk_t blk = { 0, };
1774 mtp_uint32 num_bytes = 0;
1775 mtp_uchar *ptr = NULL;
1777 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
1778 _cmd_hdlr_send_response_code(hdlr,
1779 PTP_RESPONSE_PARAM_NOTSUPPORTED);
1783 prop_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
1784 fmt = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
1786 if (MTP_ERROR_NONE != _hutil_get_prop_desc(fmt, prop_id, &prop)) {
1787 _cmd_hdlr_send_response_code(hdlr,
1788 PTP_RESPONSE_PROP_NOTSUPPORTED);
1792 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
1793 num_bytes = _prop_size_obj_prop_desc(&prop);
1794 ptr = _hdlr_alloc_buf_data_container(&blk, num_bytes, num_bytes);
1796 if (num_bytes == _prop_pack_obj_prop_desc(&prop, ptr, num_bytes)) {
1797 _device_set_phase(DEVICE_PHASE_DATAIN);
1798 if (_hdlr_send_data_container(&blk)) {
1799 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
1801 /* Host Cancelled data-in transfer */
1802 _device_set_phase(DEVICE_PHASE_NOTREADY);
1805 _cmd_hdlr_send_response_code(hdlr,
1806 PTP_RESPONSE_GEN_ERROR);
1813 static void __get_object_prop_supported(mtp_handler_t *hdlr)
1816 data_blk_t blk = { 0 };
1817 ptp_array_t props_supported = { 0 };
1818 mtp_uint32 num_bytes = 0;
1819 mtp_uchar *ptr = NULL;
1821 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
1822 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
1823 _cmd_hdlr_send_response_code(hdlr,
1824 PTP_RESPONSE_PARAM_NOTSUPPORTED);
1828 fmt = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
1829 _prop_init_ptparray(&props_supported, UINT16_TYPE);
1831 if (MTP_ERROR_NONE != _hutil_get_object_prop_supported(fmt,
1832 &props_supported)) {
1833 _prop_deinit_ptparray(&props_supported);
1834 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
1838 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
1839 num_bytes = _prop_get_size_ptparray(&props_supported);
1840 ptr = _hdlr_alloc_buf_data_container(&blk, num_bytes, num_bytes);
1843 _prop_pack_ptparray(&props_supported, ptr, num_bytes);
1844 _device_set_phase(DEVICE_PHASE_DATAIN);
1845 if (_hdlr_send_data_container(&blk)) {
1846 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
1848 /* Host Cancelled data-in transfer */
1849 _device_set_phase(DEVICE_PHASE_NOTREADY);
1852 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
1855 _prop_deinit_ptparray(&props_supported);
1861 static void __get_object_prop_value(mtp_handler_t *hdlr)
1863 mtp_uint32 h_obj = 0;
1864 mtp_uint32 prop_id = 0;
1865 mtp_uchar *ptr = NULL;
1866 mtp_uint32 num_bytes = 0;
1867 data_blk_t blk = { 0 };
1868 obj_prop_val_t prop_val = { 0 };
1870 mtp_obj_t *obj = NULL;
1871 #ifdef MTP_USE_RUNTIME_GETOBJECTPROPVALUE
1872 slist_node_t *node = NULL;
1873 slist_node_t *next_node = NULL;
1875 #endif /*MTP_USE_RUNTIME_GETOBJECTPROPVALUE*/
1877 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
1878 _cmd_hdlr_send_response_code(hdlr,
1879 PTP_RESPONSE_PARAM_NOTSUPPORTED);
1883 h_obj = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
1884 prop_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
1885 ret = _hutil_get_object_prop_value(h_obj, prop_id, &prop_val, &obj);
1887 if (MTP_ERROR_NONE == ret) {
1888 num_bytes = _prop_size_obj_propval(&prop_val);
1889 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code,
1891 ptr = _hdlr_alloc_buf_data_container(&blk, num_bytes,
1894 _prop_pack_obj_propval(&prop_val, ptr, num_bytes)) {
1896 _device_set_phase(DEVICE_PHASE_DATAIN);
1897 if (_hdlr_send_data_container(&blk)) {
1898 _cmd_hdlr_send_response_code(hdlr,
1901 /* Host Cancelled data-in transfer */
1902 _device_set_phase(DEVICE_PHASE_NOTREADY);
1905 _cmd_hdlr_send_response_code(hdlr,
1906 PTP_RESPONSE_GEN_ERROR);
1911 } else if (ret == MTP_ERROR_INVALID_OBJECTHANDLE) {
1912 _cmd_hdlr_send_response_code(hdlr,
1913 PTP_RESPONSE_INVALID_OBJ_HANDLE);
1915 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
1918 #ifdef MTP_USE_RUNTIME_GETOBJECTPROPVALUE
1920 ERR("Invalid object");
1924 for (ii = 0, next_node = obj->propval_list.start;
1925 ii < obj->propval_list.nnodes; ii++) {
1927 next_node = node->link;
1928 _prop_destroy_obj_propval((obj_prop_val_t *)node->value);
1931 obj->propval_list.start = NULL;
1932 obj->propval_list.end = NULL;
1933 obj->propval_list.nnodes = 0;
1934 #endif /*MTP_USE_RUNTIME_GETOBJECTPROPVALUE*/
1939 static void __set_object_prop_value(mtp_handler_t *hdlr)
1941 mtp_uint32 h_obj = 0;
1942 mtp_uint32 prop_id = 0;
1943 mtp_uint16 resp = PTP_RESPONSE_OK;
1944 data_blk_t blk = { 0 };
1945 mtp_uint32 max_bytes = 0;
1948 h_obj = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
1949 prop_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
1951 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
1952 ERR("Unsupported parameters");
1953 resp = PTP_RESPONSE_PARAM_NOTSUPPORTED;
1954 _cmd_hdlr_send_response_code(hdlr, resp);
1958 _device_set_phase(DEVICE_PHASE_DATAOUT);
1959 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
1960 max_bytes = MTP_MAX_PROP_DATASIZE;
1962 if (_hdlr_rcv_data_container(&blk, max_bytes) == FALSE) {
1963 ERR("_hdlr_rcv_data_container() Fail");
1964 _device_set_phase(DEVICE_PHASE_IDLE);
1965 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_INVALIDPROPVALUE);
1970 ret = _hutil_update_object_property(h_obj, prop_id, NULL,
1971 _hdlr_get_payload_data(&blk),
1972 _hdlr_get_payload_size(&blk), NULL);
1974 case MTP_ERROR_ACCESS_DENIED:
1975 resp = PTP_RESPONSE_ACCESSDENIED;
1977 case MTP_ERROR_INVALID_OBJECTHANDLE:
1978 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
1980 case MTP_ERROR_INVALID_OBJ_PROP_CODE:
1981 resp = PTP_RESPONSE_PROP_NOTSUPPORTED;
1983 case MTP_ERROR_GENERAL:
1984 resp = PTP_RESPONSE_GEN_ERROR;
1986 case MTP_ERROR_NONE:
1987 resp = PTP_RESPONSE_OK;
1990 resp = PTP_RESPONSE_INVALIDPROPVALUE;
1994 _cmd_hdlr_send_response_code(hdlr, resp);
2000 static void __get_object_prop_list(mtp_handler_t *hdlr)
2002 mtp_uint32 h_obj = 0;
2004 mtp_uint32 prop_id = 0;
2005 mtp_uint32 group_code = 0;
2006 mtp_uint32 depth = 0;
2008 mtp_uint16 resp = 0;
2009 obj_proplist_t prop_list = { { 0 } };
2010 data_blk_t blk = { 0 };
2011 mtp_uint32 num_bytes = 0;
2012 mtp_uchar *ptr = NULL;
2013 #ifdef MTP_USE_RUNTIME_GETOBJECTPROPVALUE
2014 ptp_array_t obj_arr = { 0 };
2015 slist_node_t *node = NULL;
2016 slist_node_t *next_node = NULL;
2019 mtp_obj_t *obj = NULL;
2020 #endif /*MTP_USE_RUNTIME_GETOBJECTPROPVALUE*/
2022 h_obj = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
2023 fmt = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
2024 prop_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2);
2025 group_code = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 3);
2026 depth = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 4);
2028 __enum_store_not_enumerated(h_obj, fmt, depth);
2030 #ifdef MTP_USE_RUNTIME_GETOBJECTPROPVALUE
2031 ret = _hutil_get_object_prop_list(h_obj, fmt, prop_id, group_code,
2032 depth, &prop_list, &obj_arr);
2033 #else /*MTP_USE_RUNTIME_GETOBJECTPROPVALUE*/
2034 ret = _hutil_get_object_prop_list(h_obj, fmt, prop_id, group_code,
2036 #endif /*MTP_USE_RUNTIME_GETOBJECTPROPVALUE*/
2039 case MTP_ERROR_NONE:
2040 resp = PTP_RESPONSE_OK;
2042 case MTP_ERROR_INVALID_OBJECTHANDLE:
2043 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
2045 case MTP_ERROR_INVALID_PARAM:
2046 resp = PTP_RESPONSE_INVALIDPARAM;
2048 case MTP_ERROR_NO_SPEC_BY_FORMAT:
2049 resp = PTP_RESPONSE_NOSPECIFICATIONBYFORMAT;
2051 case MTP_ERROR_GENERAL:
2053 resp = PTP_RESPONSE_GEN_ERROR;
2056 if (PTP_RESPONSE_OK != resp) {
2057 _cmd_hdlr_send_response_code(hdlr, resp);
2058 _prop_deinit_ptparray(&obj_arr);
2062 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
2063 num_bytes = _prop_size_obj_proplist(&prop_list);
2064 ptr = _hdlr_alloc_buf_data_container(&blk, num_bytes, num_bytes);
2065 if (num_bytes == _prop_pack_obj_proplist(&prop_list, ptr, num_bytes)) {
2067 _device_set_phase(DEVICE_PHASE_DATAIN);
2068 if (_hdlr_send_data_container(&blk)) {
2069 _cmd_hdlr_send_response_code(hdlr, resp);
2071 /* Host Cancelled data-in transfer*/
2072 _device_set_phase(DEVICE_PHASE_NOTREADY);
2076 _prop_destroy_obj_proplist(&prop_list);
2079 #ifdef MTP_USE_RUNTIME_GETOBJECTPROPVALUE
2080 if (resp == PTP_RESPONSE_OK && obj_arr.array_entry) {
2081 mtp_uint32 *obj_handles = obj_arr.array_entry;
2083 for (ii = 0; ii < obj_arr.num_ele; ii++) {
2084 mtp_store_t *store = NULL;
2086 store = _device_get_store_containing_obj(obj_handles[ii]);
2090 obj = _entity_get_object_from_store(store, obj_handles[ii]);
2091 if (NULL == obj || obj->propval_list.nnodes == 0)
2094 /*Remove all the old property value, and ready to set up new */
2095 for (jj = 0, next_node = obj->propval_list.start;
2096 jj < obj->propval_list.nnodes; jj++) {
2098 next_node = node->link;
2099 _prop_destroy_obj_propval
2100 ((obj_prop_val_t *)node->value);
2103 obj->propval_list.start = NULL;
2104 obj->propval_list.end = NULL;
2105 obj->propval_list.nnodes = 0;
2109 _prop_deinit_ptparray(&obj_arr);
2110 #endif /*MTP_USE_RUNTIME_GETOBJECTPROPVALUE*/
2114 static void __set_object_prop_list(mtp_handler_t *hdlr)
2117 mtp_uint16 resp = PTP_RESPONSE_OK;
2118 data_blk_t blk = { 0 };
2119 mtp_uint32 max_num_obj = 0;
2120 mtp_uint32 max_bytes = 0;
2121 mtp_uint32 h_obj = 0;
2122 mtp_uint32 prop_id = 0;
2123 mtp_uint32 data_type = 0;
2124 mtp_uchar *temp = NULL;
2125 mtp_int32 bytes_left = 0;
2126 mtp_uint32 prop_val_sz = 0;
2127 mtp_uint32 num_elem = 0;
2130 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0) ||
2131 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
2132 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2) ||
2133 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 3) ||
2134 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 4)) {
2135 resp = PTP_RESPONSE_PARAM_NOTSUPPORTED;
2138 _device_set_phase(DEVICE_PHASE_DATAOUT);
2139 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
2141 /* Gestimate the amount of data we will be receiving */
2142 _hutil_get_number_of_objects(PTP_STORAGEID_ALL, &max_num_obj);
2143 max_bytes = max_num_obj * 1000;
2145 /* If Host sent more data than we could receive, a device stall happens,
2146 * which cancels the data transfer
2148 if (max_bytes > 1000000) {
2149 max_bytes = 1000000;
2150 ERR("max_bytes is overflowed");
2152 if (FALSE == _hdlr_rcv_data_container(&blk, max_bytes)) {
2153 ERR("_hdlr_rcv_data_container() Fail");
2154 _device_set_phase(DEVICE_PHASE_NOTREADY);
2155 resp = PTP_RESPONSE_GEN_ERROR;
2158 if (PTP_RESPONSE_OK != resp) {
2159 _cmd_hdlr_send_response(hdlr, resp, 1, &i);
2164 temp = _hdlr_get_payload_data(&blk);
2165 bytes_left = (mtp_int32)_hdlr_get_payload_size(&blk);
2166 if (bytes_left < sizeof(mtp_uint32)) {
2168 resp = MTP_RESPONSE_INVALIDOBJPROPFORMAT;
2169 _cmd_hdlr_send_response(hdlr, resp, 1, &i);
2172 ERR("invalid object format, bytes_left [%d]:[%u]\n", bytes_left,
2173 sizeof(mtp_uint32));
2178 memcpy(&num_elem, temp, sizeof(mtp_uint32));
2179 temp += sizeof(mtp_uint32);
2180 bytes_left -= sizeof(mtp_uint32);
2182 for (i = 0; i < num_elem; i++) {
2186 /*Get object handle*/
2187 memcpy(&h_obj, temp, sizeof(mtp_uint32));
2188 temp += sizeof(mtp_uint32);
2189 bytes_left -= sizeof(mtp_uint32);
2193 /* Get property code */
2194 memcpy(&prop_id, temp, sizeof(mtp_uint16));
2195 temp += sizeof(mtp_uint16);
2196 bytes_left -= sizeof(mtp_uint16);
2201 memcpy(&data_type, temp, sizeof(mtp_uint16));
2202 temp += sizeof(mtp_uint16);
2203 bytes_left -= sizeof(mtp_uint16);
2207 /* Update property*/
2208 ret = _hutil_update_object_property(h_obj, prop_id,
2209 (mtp_uint16 *)&data_type, temp, bytes_left,
2213 case MTP_ERROR_INVALID_OBJECT_PROP_FORMAT:
2214 resp = MTP_RESPONSE_INVALIDOBJPROPFORMAT;
2215 _cmd_hdlr_send_response(hdlr, resp, 1, &i);
2217 ERR("invalid object format");
2220 case MTP_ERROR_ACCESS_DENIED:
2221 resp = PTP_RESPONSE_ACCESSDENIED;
2222 _cmd_hdlr_send_response(hdlr, resp, 1, &i);
2224 ERR("access denied");
2227 case MTP_ERROR_INVALID_OBJECTHANDLE:
2228 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
2229 _cmd_hdlr_send_response(hdlr, resp, 1, &i);
2231 ERR("invalid object handle");
2234 case MTP_ERROR_INVALID_OBJ_PROP_CODE:
2235 resp = PTP_RESPONSE_PROP_NOTSUPPORTED;
2236 _cmd_hdlr_send_response(hdlr, resp, 1, &i);
2238 ERR("property not supported");
2241 case MTP_ERROR_NONE:
2242 temp += prop_val_sz;
2243 bytes_left -= prop_val_sz;
2246 resp = PTP_RESPONSE_INVALIDPROPVALUE;
2247 _cmd_hdlr_send_response(hdlr, resp, 1, &i);
2249 ERR("invalid property value");
2255 resp = PTP_RESPONSE_OK;
2256 _cmd_hdlr_send_response(hdlr, resp, 1, &i);
2261 static void __report_acquired_content(mtp_handler_t *hdlr)
2264 mtp_uint32 start_idx = 0;
2265 mtp_uint32 max_size = 0;
2266 mtp_uint16 resp = PTP_RESPONSE_OK;
2267 mtp_uint32 resp_param[3] = { 0 };
2268 data_blk_t blk = { 0 };
2269 mtp_uchar *ptr = NULL;
2270 ptp_array_t guid_arr = { 0 };
2271 mtp_uint32 num_mod = 0;
2272 mtp_uint32 num_bytes = 0;
2273 mtp_uint32 num_lines = 0;
2274 mtp_uint32 rem_modified = 0;
2278 mtp_int32 diff_time;
2282 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 3)) {
2284 ERR("Unsupported parameters");
2285 _cmd_hdlr_send_response_code(hdlr,
2286 PTP_RESPONSE_PARAM_NOTSUPPORTED);
2290 tid = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
2291 start_idx = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
2292 max_size = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2);
2296 if (access(MTP_FILES_MODIFIED_FILES, F_OK) == 0)
2297 if (remove(MTP_FILES_MODIFIED_FILES) < 0)
2298 ERR("remove(%s) Fail", MTP_FILES_MODIFIED_FILES);
2300 resp = PTP_RESPONSE_OK;
2301 _prop_grow_ptparray(&guid_arr, 1);
2302 _prop_append_ele_ptparray(&guid_arr, 0);
2306 g_is_sync_estab = TRUE;
2308 if (!g_has_round_trip && start_idx == 0) {
2310 ret = vconf_get_int(VCONFKEY_MTP_SYNC_TIME_INT, (int *)&l_time);
2312 ERR("Error to get key value at [%s] path\n",
2313 VCONFKEY_MTP_SYNC_TIME_INT);
2314 resp = PTP_RESPONSE_OK;
2315 _prop_grow_ptparray(&guid_arr, 1);
2316 _prop_append_ele_ptparray(&guid_arr, 0);
2319 diff_time = (cur_time - l_time) / 60;
2320 if (diff_time < 0) {
2321 resp = PTP_RESPONSE_GEN_ERROR;
2322 _prop_init_ptparray(&guid_arr, UINT32_TYPE);
2323 _prop_append_ele_ptparray(&guid_arr, 0);
2326 _entity_list_modified_files(diff_time);
2329 h_file = _util_file_open(MTP_FILES_MODIFIED_FILES, MTP_FILE_READ, &err);
2330 if (h_file == NULL) {
2331 resp = PTP_RESPONSE_GEN_ERROR;
2332 _prop_init_ptparray(&guid_arr, UINT32_TYPE);
2333 _prop_append_ele_ptparray(&guid_arr, 0);
2337 if (!g_has_round_trip && start_idx == 0) {
2338 _util_count_num_lines(h_file, &g_mgr->meta_info.mod);
2339 _util_file_seek(h_file, 0, SEEK_SET);
2341 num_lines = g_mgr->meta_info.mod;
2342 num_mod = ((num_lines - start_idx) > max_size) ?
2343 max_size : num_lines - start_idx;
2345 rem_modified = (num_lines - start_idx > max_size) ?
2346 (num_lines - start_idx - max_size) : 0;
2348 g_has_round_trip = FALSE;
2349 _prop_init_ptparray(&guid_arr, UINT32_TYPE);
2350 _prop_grow_ptparray(&guid_arr, (num_mod * sizeof(mtp_uint32)) + 1);
2351 _prop_append_ele_ptparray(&guid_arr, num_mod);
2352 _util_fill_guid_array(&guid_arr, start_idx, h_file, num_mod);
2354 _util_file_close(h_file);
2355 if (rem_modified == 0) {
2356 if (remove(MTP_FILES_MODIFIED_FILES) < 0)
2357 ERR("remove(%s) Fail", MTP_FILES_MODIFIED_FILES);
2359 g_mgr->meta_info.mod = 0;
2363 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
2364 num_bytes = _prop_get_size_ptparray_without_elemsize(&guid_arr);
2365 ptr = _hdlr_alloc_buf_data_container(&blk, num_bytes, num_bytes);
2368 _prop_pack_ptparray_without_elemsize(&guid_arr, ptr, num_bytes);
2369 _device_set_phase(DEVICE_PHASE_DATAIN);
2372 if (_hdlr_send_data_container(&blk))
2373 resp = PTP_RESPONSE_OK;
2375 resp = PTP_RESPONSE_GEN_ERROR;
2377 _prop_deinit_ptparray(&guid_arr);
2380 if (PTP_RESPONSE_OK == resp) {
2382 resp_param[0] = hdlr->usb_cmd.tid;
2383 resp_param[1] = rem_modified;
2385 _cmd_hdlr_send_response(hdlr, resp, 3, resp_param);
2387 _cmd_hdlr_send_response_code(hdlr, resp);
2392 static void __send_playback_skip(mtp_handler_t *hdlr)
2395 mtp_uint16 resp = PTP_RESPONSE_INVALIDPARAM;
2397 skip = (mtp_int32) _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
2398 if (MTP_ERROR_NONE == _hutil_get_playback_skip(skip))
2399 resp = PTP_RESPONSE_OK;
2401 _cmd_hdlr_send_response_code(hdlr, resp);
2406 static void __self_test(mtp_handler_t *hdlr)
2408 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
2409 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
2410 ERR("Unsupported parameters");
2411 _cmd_hdlr_send_response_code(hdlr,
2412 PTP_RESPONSE_PARAM_NOTSUPPORTED);
2416 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
2417 /* Do device-specific tests */
2418 /* After the test */
2419 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
2423 #ifdef MTP_SUPPORT_SET_PROTECTION
2424 static void __set_object_protection(mtp_handler_t *hdlr)
2426 mtp_uint32 h_obj = 0;
2427 mtp_uint16 protcn_status = 0;
2428 mtp_uint16 resp = 0;
2430 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
2431 ERR("Unsupported parameter");
2432 _cmd_hdlr_send_response_code(hdlr,
2433 PTP_RESPONSE_PARAM_NOTSUPPORTED);
2437 h_obj = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
2438 protcn_status = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
2440 if ((protcn_status != PTP_PROTECTIONSTATUS_NOPROTECTION) &&
2441 (protcn_status != PTP_PROTECTIONSTATUS_READONLY) &&
2442 (protcn_status != MTP_PROTECTIONSTATUS_READONLY_DATA) &&
2443 (protcn_status != MTP_PROTECTIONSTATUS_NONTRANSFERABLE_DATA)) {
2445 resp = PTP_RESPONSE_INVALIDPARAM;
2446 _cmd_hdlr_send_response_code(hdlr, resp);
2450 switch (_hutil_set_protection(h_obj, protcn_status)) {
2451 case MTP_ERROR_INVALID_OBJECTHANDLE:
2452 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
2454 case MTP_ERROR_OBJECT_WRITE_PROTECTED:
2455 resp = PTP_RESPONSE_OBJ_WRITEPROTECTED;
2457 case MTP_ERROR_NONE:
2458 resp = PTP_RESPONSE_OK;
2460 case MTP_ERROR_OPERATION_NOT_SUPPORTED:
2461 resp = PTP_RESPONSE_OP_NOT_SUPPORTED;
2464 resp = PTP_RESPONSE_GEN_ERROR;
2467 _cmd_hdlr_send_response_code(hdlr, resp);
2470 #endif /* MTP_SUPPORT_SET_PROTECTION */
2472 static void __power_down(mtp_handler_t *hdlr)
2474 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0) ||
2475 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
2476 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
2477 ERR("Unsupported Parameter");
2478 _cmd_hdlr_send_response_code(hdlr,
2479 PTP_RESPONSE_PARAM_NOTSUPPORTED);
2483 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
2485 _cmd_hdlr_reset_cmd(hdlr);
2489 static void __move_object(mtp_handler_t *hdlr)
2491 mtp_uint32 store_id = 0;
2492 mtp_uint32 obj_handle = 0;
2493 mtp_uint32 h_parent = 0;
2494 mtp_uint32 resp = 0;
2496 obj_handle = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
2497 store_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
2498 h_parent = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2);
2500 _transport_set_mtp_operation_state(MTP_STATE_DATA_PROCESSING);
2502 switch (_hutil_move_object_entry(store_id, h_parent, obj_handle)) {
2503 case MTP_ERROR_NONE:
2504 resp = PTP_RESPONSE_OK;
2506 case MTP_ERROR_INVALID_OBJECTHANDLE:
2507 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
2509 case MTP_ERROR_OBJECT_WRITE_PROTECTED:
2510 resp = PTP_RESPONSE_OBJ_WRITEPROTECTED;
2512 case MTP_ERROR_ACCESS_DENIED:
2513 resp = PTP_RESPONSE_ACCESSDENIED;
2515 case MTP_ERROR_STORE_NOT_AVAILABLE:
2516 resp = PTP_RESPONSE_STORENOTAVAILABLE;
2518 case MTP_ERROR_INVALID_PARENT:
2519 resp = PTP_RESPONSE_INVALIDPARENT;
2521 case MTP_ERROR_INVALID_PARAM:
2522 resp = PTP_RESPONSE_INVALIDPARAM;
2524 case MTP_ERROR_STORE_FULL:
2525 resp = PTP_RESPONSE_STOREFULL;
2528 resp = PTP_RESPONSE_GEN_ERROR;
2531 _transport_set_mtp_operation_state(MTP_STATE_ONSERVICE);
2532 _cmd_hdlr_send_response_code(hdlr, resp);
2536 static void __copy_object(mtp_handler_t *hdlr)
2538 mtp_uint32 store_id = 0;
2539 mtp_uint32 h_obj = 0;
2540 mtp_uint32 h_parent = 0;
2541 mtp_uint32 new_handle = 0;
2542 mtp_uint16 resp = 0;
2544 h_obj = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
2545 store_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
2546 h_parent = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2);
2548 _transport_set_mtp_operation_state(MTP_STATE_DATA_PROCESSING);
2550 switch (_hutil_duplicate_object_entry(store_id, h_parent, h_obj,
2552 case MTP_ERROR_INVALID_OBJECTHANDLE:
2553 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
2555 case MTP_ERROR_OBJECT_WRITE_PROTECTED:
2556 resp = PTP_RESPONSE_OBJ_WRITEPROTECTED;
2558 case MTP_ERROR_STORE_NOT_AVAILABLE:
2559 resp = PTP_RESPONSE_STORENOTAVAILABLE;
2561 case MTP_ERROR_STORE_READ_ONLY:
2562 resp = PTP_RESPONSE_STORE_READONLY;
2564 case MTP_ERROR_INVALID_PARENT:
2565 resp = PTP_RESPONSE_INVALIDPARENT;
2567 case MTP_ERROR_INVALID_PARAM:
2568 resp = PTP_RESPONSE_INVALIDPARAM;
2570 case MTP_ERROR_STORE_FULL:
2571 resp = PTP_RESPONSE_STOREFULL;
2573 case MTP_ERROR_NONE:
2574 resp = PTP_RESPONSE_OK;
2576 case MTP_ERROR_ACCESS_DENIED:
2577 resp = PTP_RESPONSE_ACCESSDENIED;
2580 resp = PTP_RESPONSE_GEN_ERROR;
2582 _transport_set_mtp_operation_state(MTP_STATE_ONSERVICE);
2584 if (resp == PTP_RESPONSE_OK)
2585 _cmd_hdlr_send_response(hdlr, resp, 1, &new_handle);
2587 _cmd_hdlr_send_response_code(hdlr, resp);
2592 static void __reset_device_prop_value(mtp_handler_t *hdlr)
2594 mtp_uint32 prop_id = 0;
2595 device_prop_desc_t *prop = NULL;
2596 mtp_char temp[MTP_MAX_REG_STRING * 3 + 1] = { 0 };
2598 prop_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
2600 if (MTP_ERROR_NONE != _hutil_reset_device_entry(prop_id)) {
2601 _cmd_hdlr_send_response_code(hdlr,
2602 PTP_RESPONSE_PROP_NOTSUPPORTED);
2606 if (MTP_PROPERTYCODE_DEVICEFRIENDLYNAME == prop_id) {
2607 prop = _device_get_device_property(prop_id);
2609 _cmd_hdlr_send_response_code(hdlr,
2610 PTP_RESPONSE_PROP_NOTSUPPORTED);
2614 _util_utf16_to_utf8(temp, sizeof(temp),
2615 prop->current_val.str->str);
2616 _device_set_device_name(temp);
2618 } else if (MTP_PROPERTYCODE_SYNCHRONIZATIONPARTNER == prop_id) {
2619 prop = _device_get_device_property(prop_id);
2621 _cmd_hdlr_send_response_code(hdlr,
2622 PTP_RESPONSE_PROP_NOTSUPPORTED);
2626 _util_utf16_to_utf8(temp, sizeof(temp),
2627 prop->current_val.str->str);
2628 _device_set_sync_partner(temp);
2630 if (!g_strcmp0(temp, MTP_DEV_PROPERTY_NULL_SYNCPARTNER))
2631 vconf_set_str(VCONFKEY_MTP_SYNC_PARTNER_STR, "");
2633 vconf_set_str(VCONFKEY_MTP_SYNC_PARTNER_STR, temp);
2635 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
2640 /* Vendor-specific operations */
2641 #define GET_DEVICEPC_NAME 1
2642 static void __vendor_command1(mtp_handler_t *hdlr)
2644 switch (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0)) {
2645 case GET_DEVICEPC_NAME:
2650 /* Vendor command not properly handled*/
2651 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
2655 static void __get_interdep_prop_desc(mtp_handler_t *hdlr)
2658 data_blk_t blk = { 0 };
2659 mtp_uint32 num_bytes = 0;
2660 mtp_uchar *ptr = NULL;
2662 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
2663 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
2664 _cmd_hdlr_send_response_code(hdlr,
2665 PTP_RESPONSE_PARAM_NOTSUPPORTED);
2669 fmt = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
2670 if (0x0 == fmt || 0xFFFFFFFF == fmt) {
2671 ERR("Invalid format code");
2672 _cmd_hdlr_send_response_code(hdlr,
2673 PTP_RESPONSE_INVALIDCODEFORMAT);
2677 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
2678 _hutil_get_interdep_prop_config_list_size(&num_bytes, fmt);
2679 ptr = _hdlr_alloc_buf_data_container(&blk, num_bytes, num_bytes);
2681 if (MTP_ERROR_NONE != _hutil_get_interdep_prop_config_list_data(ptr,
2683 ERR("_hutil_get_interdep_prop_config_list_data() Fail");
2684 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
2688 _device_set_phase(DEVICE_PHASE_DATAIN);
2689 if (_hdlr_send_data_container(&blk)) {
2690 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
2692 /*Host Cancelled data-in transfer*/
2693 _device_set_phase(DEVICE_PHASE_NOTREADY);
2701 * void __cmd_hdlr_send_object_prop_list(mtp_handler_t *hdlr)
2702 * This function is used as an alternative first operation when the initiator
2703 * wants to send an object to the responder. This operation sends a
2704 * modified ObjectPropList dataset from the initiator to the Responder.
2708 static void __send_object_prop_list(mtp_handler_t *hdlr)
2711 mtp_uint16 resp = PTP_RESPONSE_OK;
2712 mtp_uint32 resp_param[MAX_MTP_PARAMS] = { 0 };
2713 mtp_obj_t *obj = NULL;
2715 mtp_uint64 f_size = 0;
2716 mtp_uint64 fsize_hbits = 0;
2717 mtp_uint32 store_id;
2718 mtp_uint32 h_parent;
2719 data_blk_t blk = { 0 };
2720 mtp_uint32 max_bytes = 0;
2722 obj_data_t objdata = { 0 };
2724 store_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
2725 h_parent = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
2726 fmt = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2);
2727 fsize_hbits = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 3);
2729 f_size = (fsize_hbits << 32) + _hdlr_get_param_cmd_container
2730 (&(hdlr->usb_cmd), 4);
2732 _device_set_phase(DEVICE_PHASE_DATAOUT);
2733 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
2735 max_bytes = MTP_MAX_METADATA;
2736 if (FALSE == _hdlr_rcv_data_container(&blk, max_bytes)) {
2737 _device_set_phase(DEVICE_PHASE_IDLE);
2738 ERR("_hdlr_rcv_data_container() Fail");
2739 resp = PTP_RESPONSE_GEN_ERROR;
2745 h_parent = _device_get_default_parent_handle();
2746 else if (h_parent == 0xFFFFFFFF)
2747 h_parent = PTP_OBJECTHANDLE_ROOT;
2749 store_id = _device_get_default_store_id();
2751 resp = PTP_RESPONSE_STORENOTAVAILABLE;
2753 /* If the second parameter is used, the first must
2756 resp = PTP_RESPONSE_PARAM_NOTSUPPORTED;
2758 h_parent = _device_get_default_parent_handle();
2761 if (f_size >= MTP_FILESIZE_4GB) {
2763 mtp_store_t *store = NULL;
2764 struct statfs buf = { 0 };
2767 store = _device_get_store(store_id);
2768 if (store == NULL) {
2769 ERR("Store Not Available");
2770 resp = PTP_RESPONSE_STORENOTAVAILABLE;
2772 DBG("StorePath = [%s]\n", store->root_path);
2773 ret = statfs(store->root_path, &buf);
2774 if (ret < 0 || buf.f_type == MSDOS_SUPER_MAGIC) {
2775 ERR("File System does not support files over 4gb");
2776 resp = MTP_RESPONSE_OBJECT_TOO_LARGE;
2781 if (PTP_RESPONSE_OK == resp) {
2783 mtp_uchar *data = NULL;
2785 if (TRUE == hdlr->data4_send_obj.is_valid) {
2787 objdata.store_id = hdlr->data4_send_obj.store_id;
2788 objdata.obj_size = hdlr->data4_send_obj.file_size;
2789 objdata.obj = hdlr->data4_send_obj.obj;
2790 hdlr->data4_send_obj.obj = NULL;
2793 data = _hdlr_get_payload_data(&blk);
2797 ret = _hutil_construct_object_entry_prop_list(store_id, h_parent,
2798 fmt, f_size, ((hdlr->data4_send_obj.is_valid == TRUE) ?
2799 (&objdata) : (NULL)), &obj, data,
2800 _hdlr_get_payload_size(&blk), &idx);
2801 hdlr->data4_send_obj.is_valid = FALSE;
2804 case MTP_ERROR_INVALID_STORE:
2805 resp = PTP_RESPONSE_INVALID_STORE_ID;
2807 case MTP_ERROR_STORE_READ_ONLY:
2808 resp = PTP_RESPONSE_STORE_READONLY;
2810 case MTP_ERROR_STORE_FULL:
2811 resp = PTP_RESPONSE_STOREFULL;
2813 case MTP_ERROR_GENERAL:
2814 resp = PTP_RESPONSE_GEN_ERROR;
2816 case MTP_ERROR_INVALID_DATASET:
2817 resp = MTP_RESPONSECODE_INVALIDDATASET;
2819 case MTP_ERROR_INVALID_OBJECTHANDLE:
2820 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
2822 case MTP_ERROR_INVALID_OBJ_PROP_CODE:
2823 resp = MTP_RESPONSE_INVALIDOBJPROPCODE;
2825 case MTP_ERROR_INVALID_OBJECT_PROP_FORMAT:
2826 resp = MTP_RESPONSE_INVALIDOBJPROPFORMAT;
2828 case MTP_ERROR_INVALID_OBJ_PROP_VALUE:
2829 resp = MTP_RESPONSE_INVALIDOBJPROPVALUE;
2831 case MTP_ERROR_INVALID_PARENT:
2832 resp = PTP_RESPONSE_INVALIDPARENT;
2834 case MTP_ERROR_ACCESS_DENIED:
2835 resp = PTP_RESPONSE_ACCESSDENIED;
2837 case MTP_ERROR_NONE:
2838 #ifdef MTP_USE_SELFMAKE_ABSTRACTION
2839 if ((obj->obj_info->obj_fmt == PTP_FMT_ASSOCIATION) ||
2840 (obj->obj_info->file_size == 0 &&
2841 obj->obj_info->obj_fmt >
2842 MTP_FMT_UNDEFINED_COLLECTION &&
2843 obj->obj_info->obj_fmt <
2844 MTP_FMT_UNDEFINED_DOC))
2845 #else /*MTP_USE_SELFMAKE_ABSTRACTION*/
2846 if (obj->obj_info->obj_fmt == PTP_FMT_ASSOCIATION)
2847 #endif /*MTP_USE_SELFMAKE_ABSTRACTION*/
2849 hdlr->data4_send_obj.obj = NULL;
2850 hdlr->data4_send_obj.is_valid = FALSE;
2851 hdlr->data4_send_obj.obj_handle = obj->obj_handle;
2852 hdlr->data4_send_obj.h_parent = h_parent;
2853 hdlr->data4_send_obj.store_id = store_id;
2854 hdlr->data4_send_obj.file_size = 0;
2856 hdlr->data4_send_obj.is_valid = TRUE;
2857 hdlr->data4_send_obj.obj_handle = obj->obj_handle;
2858 hdlr->data4_send_obj.h_parent = h_parent;
2859 hdlr->data4_send_obj.store_id = store_id;
2860 hdlr->data4_send_obj.obj = obj;
2861 hdlr->data4_send_obj.file_size =
2862 obj->obj_info->file_size;
2864 resp = PTP_RESPONSE_OK;
2867 resp = PTP_RESPONSE_GEN_ERROR;
2871 if (PTP_RESPONSE_OK != resp) {
2872 if (hdlr->data4_send_obj.obj)
2873 _entity_dealloc_mtp_obj(hdlr->data4_send_obj.obj);
2875 hdlr->data4_send_obj.obj = NULL;
2876 hdlr->data4_send_obj.is_valid = FALSE;
2877 resp_param[3] = idx;
2879 resp_param[0] = hdlr->data4_send_obj.store_id;
2881 /* PTP spec here requires that 0xFFFFFFFF be sent if root is the parent,
2882 * while in some situations (e.g. Move Object, Copy Object), 0x00000000
2883 *(as PTP_OBJECTHANDLE_ROOT is defined) represents the root
2885 resp_param[1] = (hdlr->data4_send_obj.h_parent !=
2886 PTP_OBJECTHANDLE_ROOT) ? hdlr->data4_send_obj.h_parent
2888 resp_param[2] = hdlr->data4_send_obj.obj_handle;
2892 _cmd_hdlr_send_response(hdlr, resp, 4, resp_param);
2899 void __close_session(mtp_handler_t *hdlr)
2901 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0) ||
2902 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
2903 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
2905 ERR("PTP_RESPONSE_PARAM_NOTSUPPORTED");
2906 _cmd_hdlr_send_response_code(hdlr,
2907 PTP_RESPONSE_PARAM_NOTSUPPORTED);
2912 if (hdlr->session_id) {
2913 hdlr->session_id = 0;
2914 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
2916 _cmd_hdlr_send_response_code(hdlr,
2917 PTP_RESPONSE_SESSIONNOTOPEN);
2918 ERR("PTP_RESPONSE_SESSIONNOTOPEN");
2923 mtp_bool _cmd_hdlr_send_response(mtp_handler_t *hdlr, mtp_uint16 resp,
2924 mtp_uint32 num_param, mtp_uint32 *params)
2926 mtp_bool ret = FALSE;
2927 resp_blk_t blk = { 0 };
2929 _hdlr_resp_container_init(&blk, resp, hdlr->usb_cmd.tid);
2931 ret = _hdlr_add_param_resp_container(&blk, num_param, params);
2933 _device_set_phase(DEVICE_PHASE_RESPONSE);
2934 ret = _hdlr_send_resp_container(&blk);
2935 _device_set_phase(DEVICE_PHASE_IDLE);
2937 if ((resp == PTP_RESPONSE_OK) && (ret == TRUE)) {
2938 DBG("[%s], Opcode[0x%4x], ResponseCode[0x%4x], NumParams[%d]\n",
2939 "SUCCESS", hdlr->usb_cmd.code, resp, num_param);
2941 ERR("[%s], Opcode = [0x%4x] ResponseCode[0x%4x], NumParams[%u]\n",
2942 "FAIL", hdlr->usb_cmd.code, resp, num_param);
2947 mtp_bool _cmd_hdlr_send_response_code(mtp_handler_t *hdlr, mtp_uint16 resp)
2949 return _cmd_hdlr_send_response(hdlr, resp, 0, NULL);
2952 #ifdef MTP_SUPPORT_PRINT_COMMAND
2953 static void __print_command(mtp_uint16 code)
2956 case PTP_OPCODE_GETDEVICEINFO:
2957 DBG("COMMAND ======== GET DEVICE INFO===========");
2959 case PTP_OPCODE_OPENSESSION:
2960 DBG("COMMAND ======== OPEN SESSION ===========");
2962 case PTP_OPCODE_CLOSESESSION:
2963 DBG("COMMAND ======== CLOSE SESSION ===========");
2965 case PTP_OPCODE_GETSTORAGEIDS:
2966 DBG("COMMAND ======== GET STORAGE IDS ===========");
2968 case PTP_OPCODE_GETSTORAGEINFO:
2969 DBG("COMMAND ======== GET STORAGE INFO ===========");
2971 case PTP_OPCODE_GETNUMOBJECTS:
2972 DBG("COMMAND ======== GET NUM OBJECTS ===========");
2974 case PTP_OPCODE_GETOBJECTHANDLES:
2975 DBG("COMMAND ======== GET OBJECT HANDLES ===========");
2977 case PTP_OPCODE_GETOBJECTINFO:
2978 DBG("COMMAND ======== GET OBJECT INFO ===========");
2980 case PTP_OPCODE_GETOBJECT:
2981 DBG("COMMAND ======== GET OBJECT ===========");
2983 case PTP_OPCODE_DELETEOBJECT:
2984 DBG("COMMAND ======== DELETE OBJECT ===========");
2986 case PTP_OPCODE_SENDOBJECTINFO:
2987 DBG("COMMAND ======== SEND OBJECT INFO ===========");
2989 case PTP_OPCODE_SENDOBJECT:
2990 DBG("COMMAND ======== SEND OBJECT ===========");
2992 case PTP_OPCODE_INITIATECAPTURE:
2993 DBG("COMMAND ======== INITIATE CAPTURE ===========");
2995 case PTP_OPCODE_FORMATSTORE:
2996 DBG("COMMAND ======== FORMAT STORE ===========");
2998 case PTP_OPCODE_RESETDEVICE:
2999 DBG("COMMAND ======== RESET DEVICE ===========");
3001 case PTP_OPCODE_SELFTEST:
3002 DBG("COMMAND ======== SELF TEST ===========");
3004 case PTP_OPCODE_SETOBJECTPROTECTION:
3005 DBG("COMMAND ======== SET OBJECT PROTECTION ===========");
3007 case PTP_OPCODE_POWERDOWN:
3008 DBG("COMMAND ======== POWER DOWN ===========");
3010 case PTP_OPCODE_GETDEVICEPROPDESC:
3011 DBG("COMMAND ======== GET DEVICE PROP DESC ===========");
3013 case PTP_OPCODE_GETDEVICEPROPVALUE:
3014 DBG("COMMAND ======== GET DEVICE PROP VALUE ===========");
3016 case PTP_OPCODE_SETDEVICEPROPVALUE:
3017 DBG("COMMAND ======== SET DEVICE PROP VALUE ===========");
3019 case PTP_OPCODE_RESETDEVICEPROPVALUE:
3020 DBG("COMMAND ======== RESET DEVICE PROP VALUE ===========");
3022 case PTP_OPCODE_TERMINATECAPTURE:
3023 DBG("COMMAND ======== TERMINATE CAPTURE ===========");
3025 case PTP_OPCODE_MOVEOBJECT:
3026 DBG("COMMAND ======== MOVE OBJECT ===========");
3028 case PTP_OPCODE_COPYOBJECT:
3029 DBG("COMMAND ======== COPY OBJECT ===========");
3031 case PTP_OPCODE_GETPARTIALOBJECT:
3032 DBG("COMMAND ======== GET PARTIAL OBJECT ===========");
3034 case PTP_OPCODE_INITIATEOPENCAPTURE:
3035 DBG("COMMAND ======== INITIATE OPEN CAPTURE ===========");
3037 case MTP_OPCODE_WMP_UNDEFINED:
3038 DBG("COMMAND ======== WMP UNDEFINED ==========");
3040 case MTP_OPCODE_WMP_REPORTACQUIREDCONTENT:
3041 DBG("COMMAND ======= REPORT ACQUIRED CONTENT =========");
3043 case MTP_OPCODE_GETOBJECTPROPSUPPORTED:
3044 DBG("COMMAND ======= GET OBJECT PROP SUPPORTED ========");
3046 case MTP_OPCODE_GETOBJECTPROPDESC:
3047 DBG("COMMAND ======== GET OBJECT PROP DESC ==========");
3049 case MTP_OPCODE_GETOBJECTPROPVALUE:
3050 DBG("COMMAND ======== GET OBJECT PROP VALUE ==========");
3052 case MTP_OPCODE_SETOBJECTPROPVALUE:
3053 DBG("COMMAND ======== SET OBJECT PROP VALUE ==========");
3055 case MTP_OPCODE_GETOBJECTPROPLIST:
3056 DBG("COMMAND ======== GET OBJECT PROP LIST ==========");
3058 case MTP_OPCODE_SETOBJECTPROPLIST:
3059 DBG("COMMAND ======== SET OBJECT PROP LIST ==========");
3061 case MTP_OPCODE_GETINTERDEPPROPDESC:
3062 DBG("COMMAND ======== GET INTERDEP PROP DESC ==========");
3064 case MTP_OPCODE_SENDOBJECTPROPLIST:
3065 DBG("COMMAND ======== SEND OBJECT PROP LIST ==========");
3067 case MTP_OPCODE_GETOBJECTREFERENCES:
3068 DBG("COMMAND ======== GET OBJECT REFERENCES ==========");
3070 case MTP_OPCODE_SETOBJECTREFERENCES:
3071 DBG("COMMAND ======== SET OBJECT REFERENCES ==========");
3073 case MTP_OPCODE_PLAYBACK_SKIP:
3074 DBG("COMMAND ======== PLAYBACK SKIP ==========");
3077 DBG("======== UNKNOWN COMMAND ==========");
3083 #endif /*MTP_SUPPORT_PRINT_COMMAND*/
3085 static void __enum_store_not_enumerated(mtp_uint32 obj_handle,
3086 mtp_uint32 fmt, mtp_uint32 depth)
3089 mtp_store_t *store = NULL;
3090 mtp_obj_t *obj = NULL;
3092 if (TRUE == g_is_full_enum) {
3093 DBG("Full Enumeration has been already done");
3097 DBG("obj_handle = [%u], format =[ %u], depth = [%u]\n", obj_handle,
3099 if (obj_handle == PTP_OBJECTHANDLE_ALL || obj_handle == PTP_OBJECTHANDLE_ROOT) {
3100 for (ii = 0; ii < _device_get_num_stores(); ii++) {
3101 store = _device_get_store_at_index(ii);
3102 if (store && store->obj_list.nnodes == 0)
3103 _entity_store_recursive_enum_folder_objects(store, NULL);
3105 g_is_full_enum = TRUE;
3106 } else if (obj_handle != PTP_OBJECTHANDLE_ROOT) {
3107 store = _device_get_store_containing_obj(obj_handle);
3108 obj = _entity_get_object_from_store(store, obj_handle);
3110 ERR("pObject is NULL");
3113 _entity_store_recursive_enum_folder_objects(store, obj);
3118 void _receive_mq_data_cb(mtp_char *buffer, mtp_int32 buf_len)
3120 cmd_blk_t cmd = { 0 };
3121 mtp_uint32 rx_size = _get_rx_pkt_size();
3123 if (_transport_get_mtp_operation_state() < MTP_STATE_READY_SERVICE) {
3124 ERR("MTP is stopped or initializing. ignore all");
3128 #ifdef MTP_SUPPORT_CONTROL_REQUEST
3129 /* process control request */
3130 switch (_transport_get_control_event()) {
3131 case PTP_EVENTCODE_CANCELTRANSACTION:
3132 DBG("PTP_EVENTCODE_CANCELTRANSACTION, just change state to IDLE");
3133 _transport_set_control_event(PTP_EVENTCODE_CANCELTRANSACTION);
3134 _device_set_phase(DEVICE_PHASE_IDLE);
3135 if ((buf_len == rx_size) ||
3136 (buf_len < sizeof(header_container_t))) {
3137 DBG("Cancelling Transaction. data length [%d]\n",
3139 _transport_set_control_event(PTP_EVENTCODE_CANCELTRANSACTION);
3144 cmd_container_t *tmp;
3150 for (i = 0; i < MAX_MTP_PARAMS; i++) { /* check size */
3151 /* check number of parameter */
3152 tmp = (cmd_container_t *)&buffer[buf_len -
3153 sizeof(header_container_t) -
3154 sizeof(mtp_dword) * i];
3159 if ((len == sizeof(header_container_t)
3160 + sizeof(mtp_dword) * i) &&
3161 (type == CONTAINER_CMD_BLK)) {
3162 DBG("Found Command in remaining data");
3163 memcpy(buffer, tmp, len);
3167 DBG("Not found command, length[%lu]\n", len);
3175 DBG("len[%ld], type[0x%x], code [0x%x], trid[0x%x]\n",
3176 len, type, code, trid);
3178 if (_hdlr_validate_cmd_container((mtp_byte *)tmp, len)
3180 ERR("Cancelling Transaction, invalid header, but last packet");
3181 } else { /*another command, cancelling is finished*/
3182 DBG("Cancelling Transaction, Finished.");
3185 _transport_set_control_event(0);
3186 _transport_set_mtp_operation_state(MTP_STATE_ONSERVICE);
3187 if (g_mgr->ftemp_st.fhandle != NULL) {
3188 DBG("In Cancel Transaction fclose ");
3189 _util_file_close(g_mgr->ftemp_st.fhandle);
3190 g_mgr->ftemp_st.fhandle = NULL;
3191 DBG("In Cancel Transaction, remove ");
3192 if (remove(g_mgr->ftemp_st.filepath) < 0)
3193 ERR_SECURE("remove(%s) Fail", g_mgr->ftemp_st.filepath);
3195 DBG("g_mgr->ftemp_st.fhandle is not valid, return");
3199 case PTP_EVENTCODE_DEVICERESET:
3200 DBG("Implement later, PTP_EVENTCODE_DEVICERESET");
3201 _device_set_phase(DEVICE_PHASE_IDLE);
3202 /* do close session, just skip save reference
3203 * mtp_save_object_references_mtp_device(MtpHandler.pDevice);
3205 g_mgr->hdlr.session_id = 0;
3206 _transport_set_control_event(0);
3207 _transport_set_mtp_operation_state(MTP_STATE_ONSERVICE);
3213 #endif/* MTP_SUPPORT_CONTROL_REQUEST */
3215 /* main processing */
3216 if (_device_get_phase() == DEVICE_PHASE_IDLE) {
3217 if (_hdlr_validate_cmd_container((mtp_uchar *)buffer, buf_len)
3219 _device_set_phase(DEVICE_PHASE_NOTREADY);
3220 ERR("MTP device phase NOT READY, invalid Command block");
3224 _transport_save_cmd_buffer(buffer, buf_len);
3225 _hdlr_copy_cmd_container_unknown_params((cmd_container_t *)buffer,
3227 #ifdef __BIG_ENDIAN__
3228 _hdlr_conv_cmd_container_byte_order(&cmd);
3229 #endif /* __BIG_ENDIAN__ */
3231 UTIL_LOCK_MUTEX(&g_cmd_inoti_mutex);
3232 __process_commands(&g_mtp_mgr.hdlr, &cmd);
3233 UTIL_UNLOCK_MUTEX(&g_cmd_inoti_mutex);
3234 } else if (_device_get_phase() == DEVICE_PHASE_DATAOUT) {
3235 if (g_mgr->ftemp_st.data_count == 0)
3236 __receive_temp_file_first_packet(buffer, buf_len);
3238 __receive_temp_file_next_packets(buffer, buf_len);
3241 /* ignore other case */
3242 ERR("MTP device phase[%d], unknown device PHASE\n",
3243 _device_get_phase());
3244 ERR("PhaseUnknown-> pData[0x%x], length=[%d]", buffer, buf_len);
3245 _device_set_phase(DEVICE_PHASE_IDLE);
3246 _transport_set_mtp_operation_state(MTP_STATE_ONSERVICE);
3251 static mtp_bool __receive_temp_file_first_packet(mtp_char *data,
3254 mtp_char *filepath = g_mgr->ftemp_st.filepath;
3255 mtp_int32 error = 0;
3256 mtp_uint32 *data_sz = &g_mgr->ftemp_st.data_size;
3257 mtp_char *buffer = g_mgr->ftemp_st.temp_buff;
3259 _transport_set_mtp_operation_state(MTP_STATE_DATA_TRANSFER_DL);
3260 if (access(filepath, F_OK) == 0) {
3261 if (g_mgr->ftemp_st.fhandle != NULL) {
3262 _util_file_close(g_mgr->ftemp_st.fhandle);
3263 g_mgr->ftemp_st.fhandle = NULL; /* initialize */
3266 if (remove(filepath) < 0) {
3267 ERR_SECURE("remove(%s) Fail", filepath);
3268 __finish_receiving_file_packets(data, data_len);
3273 g_mgr->ftemp_st.fhandle = _util_file_open(filepath, MTP_FILE_WRITE, &error);
3274 if (g_mgr->ftemp_st.fhandle == NULL) {
3275 ERR("First file handle is invalid!!");
3276 __finish_receiving_file_packets(data, data_len);
3279 /* consider header size */
3280 memcpy(&g_mgr->ftemp_st.header_buf, data, sizeof(header_container_t));
3282 g_mgr->ftemp_st.file_size = ((header_container_t *)data)->len -
3283 sizeof(header_container_t);
3284 *data_sz = data_len - sizeof(header_container_t);
3286 /* check whether last data packet */
3287 if (*data_sz == g_mgr->ftemp_st.file_size) {
3288 if (_util_file_write(g_mgr->ftemp_st.fhandle, &data[sizeof(header_container_t)],
3289 data_len - sizeof(header_container_t)) !=
3290 data_len - sizeof(header_container_t)) {
3291 ERR("fwrite error!");
3294 _util_file_close(g_mgr->ftemp_st.fhandle);
3295 g_mgr->ftemp_st.fhandle = NULL; /* initialize */
3296 __finish_receiving_file_packets(data, data_len);
3298 g_mgr->ftemp_st.data_count++;
3299 g_mgr->ftemp_st.size_remaining = *data_sz;
3301 memcpy(buffer, data + sizeof(header_container_t), *data_sz);
3306 static mtp_bool __receive_temp_file_next_packets(mtp_char *data,
3309 mtp_uint32 rx_size = _get_rx_pkt_size();
3310 mtp_uint32 *data_sz = &g_mgr->ftemp_st.data_size;
3311 mtp_char *buffer = g_mgr->ftemp_st.temp_buff;
3313 g_mgr->ftemp_st.data_count++;
3314 g_mgr->ftemp_st.size_remaining += data_len;
3316 if ((*data_sz + (mtp_uint32)data_len) > g_conf.write_file_size) {
3317 /* copy oversized packet to temp file */
3318 if (_util_file_write(g_mgr->ftemp_st.fhandle, buffer, *data_sz) != *data_sz)
3319 ERR("fwrite error writeSize=[%u]\n", *data_sz);
3324 memcpy(&buffer[*data_sz], data, data_len);
3325 *data_sz += data_len;
3327 /*Complete file is recieved, so close the file*/
3328 if (data_len < rx_size ||
3329 g_mgr->ftemp_st.size_remaining == g_mgr->ftemp_st.file_size) {
3331 if (_util_file_write(g_mgr->ftemp_st.fhandle, buffer, *data_sz) != *data_sz)
3332 ERR("fwrite error write size=[%u]\n", *data_sz);
3335 _util_file_close(g_mgr->ftemp_st.fhandle);
3336 g_mgr->ftemp_st.fhandle = NULL;
3337 __finish_receiving_file_packets(data, data_len);
3342 static void __finish_receiving_file_packets(mtp_char *data, mtp_int32 data_len)
3344 cmd_blk_t cmd = { 0 };
3345 mtp_uchar *cmd_buf = NULL;
3347 g_mgr->ftemp_st.data_count = 0;
3348 cmd_buf = (mtp_uchar *)data;
3350 if (!_hdlr_validate_cmd_container(cmd_buf, (mtp_uint32)data_len)) {
3351 cmd_buf = (mtp_uchar *)g_mgr->ftemp_st.cmd_buf;
3352 if (!_hdlr_validate_cmd_container(cmd_buf,
3353 g_mgr->ftemp_st.cmd_size)) {
3354 _device_set_phase(DEVICE_PHASE_IDLE);
3355 ERR("DATA PROCESS, device phase[%d], invalid Command\
3356 block\n", _device_get_phase());
3361 _transport_set_mtp_operation_state(MTP_STATE_ONSERVICE);
3362 _hdlr_copy_cmd_container_unknown_params((cmd_container_t *)cmd_buf,
3365 #ifdef __BIG_ENDIAN__
3366 _hdlr_conv_cmd_container_byte_order(&cmd);
3367 #endif /* __BIG_ENDIAN__ */
3369 UTIL_LOCK_MUTEX(&g_cmd_inoti_mutex);
3370 __process_commands(&g_mtp_mgr.hdlr, &cmd);
3371 UTIL_UNLOCK_MUTEX(&g_cmd_inoti_mutex);
3373 DBG("MTP device phase[%d], processing Command is complete\n",
3374 _device_get_phase());