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);
744 _device_set_phase(DEVICE_PHASE_DATAIN);
745 h_file = _util_file_open(path, MTP_FILE_READ, &error);
746 if (h_file == NULL) {
747 ERR("_util_file_open() Fail");
748 _device_set_phase(DEVICE_PHASE_NOTREADY);
749 if (EACCES == error) {
750 _cmd_hdlr_send_response_code(hdlr,
751 PTP_RESPONSE_ACCESSDENIED);
755 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
760 _util_file_read(h_file, ptr, packet_len, &read_len);
762 ERR("_util_file_read() Fail");
763 ERR_SECURE("filename[%s]", path);
764 _device_set_phase(DEVICE_PHASE_NOTREADY);
765 resp = PTP_RESPONSE_INCOMPLETETRANSFER;
769 /* First Packet with Header */
770 if (PTP_EVENTCODE_CANCELTRANSACTION == _transport_get_control_event() ||
771 FALSE == _hdlr_send_bulk_data(blk.data, blk.len)) {
772 _device_set_phase(DEVICE_PHASE_NOTREADY);
773 resp = PTP_RESPONSE_INCOMPLETETRANSFER;
774 ERR("First Packet send Fail");
775 ERR_SECURE("filename[%s]\n", path);
779 sent = sizeof(header_container_t) + read_len;
782 while (sent < total_len) {
783 _util_file_read(h_file, ptr, g_conf.read_file_size, &read_len);
785 ERR("_util_file_read() Fail");
786 ERR_SECURE("filename[%s]\n", path);
787 _device_set_phase(DEVICE_PHASE_NOTREADY);
788 resp = PTP_RESPONSE_INCOMPLETETRANSFER;
792 if (PTP_EVENTCODE_CANCELTRANSACTION == _transport_get_control_event() ||
793 FALSE == _hdlr_send_bulk_data(ptr, read_len)) {
794 _device_set_phase(DEVICE_PHASE_NOTREADY);
795 resp = PTP_RESPONSE_INCOMPLETETRANSFER;
796 ERR("Packet send Fail");
797 ERR_SECURE("filename[%s]\n", path);
804 if (total_len % ((mtp_uint64)_transport_get_usb_packet_len()) == 0)
805 _transport_send_zlp();
808 _util_file_close(h_file);
811 _cmd_hdlr_send_response_code(hdlr, resp);
814 static void __send_object_info(mtp_handler_t *hdlr)
816 mtp_uint16 resp = PTP_RESPONSE_UNDEFINED;
817 mtp_uint32 store_id = 0;
818 mtp_uint32 h_parent = 0;
819 mtp_uint32 num_bytes = 0;
820 data_blk_t blk = { 0 };
821 mtp_uint32 resp_param[3] = { 0 };
822 mtp_obj_t *obj = NULL;
824 obj_data_t obdata = { 0 };
826 store_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
828 store_id = _device_get_default_store_id();
830 h_parent = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
832 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
833 resp = PTP_RESPONSE_PARAM_NOTSUPPORTED;
834 if (_device_get_phase() != DEVICE_PHASE_NOTREADY)
835 _cmd_hdlr_send_response_code(hdlr, resp);
840 _device_set_phase(DEVICE_PHASE_DATAOUT);
841 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
842 num_bytes = MAX_SIZE_IN_BYTES_OF_OBJECT_INFO;
843 if (_hdlr_rcv_data_container(&blk, num_bytes) == FALSE) {
844 _device_set_phase(DEVICE_PHASE_NOTREADY);
846 if (TRUE == hdlr->data4_send_obj.is_valid) {
847 obdata.store_id = hdlr->data4_send_obj.store_id;
848 obdata.obj_size = hdlr->data4_send_obj.file_size;
849 obdata.obj = hdlr->data4_send_obj.obj;
850 hdlr->data4_send_obj.obj = NULL;
852 ret = _hutil_construct_object_entry(store_id, h_parent,
853 ((hdlr->data4_send_obj.is_valid == TRUE) ? (&obdata)
854 : (NULL)), &obj, _hdlr_get_payload_data(&blk),
855 _hdlr_get_payload_size(&blk));
856 hdlr->data4_send_obj.is_valid = FALSE;
859 if (obj->obj_info->obj_fmt == PTP_FMT_ASSOCIATION) {
860 hdlr->data4_send_obj.obj = NULL;
861 hdlr->data4_send_obj.is_valid = FALSE;
862 hdlr->data4_send_obj.obj_handle = obj->obj_handle;
863 hdlr->data4_send_obj.h_parent = h_parent;
864 hdlr->data4_send_obj.store_id = store_id;
866 #ifdef MTP_USE_SELFMAKE_ABSTRACTION
867 else if (obj->obj_info->file_size == 0 &&
868 obj->obj_info->obj_fmt > MTP_FMT_UNDEFINED_COLLECTION &&
869 obj->obj_info->obj_fmt < MTP_FMT_UNDEFINED_DOC) {
870 hdlr->data4_send_obj.obj = NULL;
871 hdlr->data4_send_obj.is_valid = FALSE;
872 hdlr->data4_send_obj.obj_handle = obj->obj_handle;
873 hdlr->data4_send_obj.h_parent = h_parent;
874 hdlr->data4_send_obj.store_id = store_id;
876 #endif /*MTP_USE_SELFMAKE_ABSTRACTION*/
878 hdlr->data4_send_obj.is_valid = TRUE;
879 hdlr->data4_send_obj.obj_handle = obj->obj_handle;
880 hdlr->data4_send_obj.h_parent = h_parent;
881 hdlr->data4_send_obj.store_id = store_id;
882 hdlr->data4_send_obj.obj = obj;
883 hdlr->data4_send_obj.file_size =
884 obj->obj_info->file_size;
886 resp = PTP_RESPONSE_OK;
888 case MTP_ERROR_STORE_NOT_AVAILABLE:
889 resp = PTP_RESPONSE_STORENOTAVAILABLE;
890 DBG("PTP_RESPONSE_STORENOTAVAILABLE");
892 case MTP_ERROR_INVALID_PARAM:
893 resp = PTP_RESPONSE_PARAM_NOTSUPPORTED;
894 DBG("PTP_RESPONSE_PARAM_NOTSUPPORTED");
896 case MTP_ERROR_INVALID_STORE:
897 resp = PTP_RESPONSE_INVALID_STORE_ID;
898 DBG("PTP_RESPONSE_INVALID_STORE_ID");
900 case MTP_ERROR_STORE_READ_ONLY:
901 resp = PTP_RESPONSE_STORE_READONLY;
903 case MTP_ERROR_STORE_FULL:
904 resp = PTP_RESPONSE_STOREFULL;
905 DBG("PTP_RESPONSE_STOREFULL");
907 case MTP_ERROR_GENERAL:
908 resp = PTP_RESPONSE_GEN_ERROR;
909 DBG("PTP_RESPONSE_GEN_ERROR");
911 case MTP_ERROR_INVALID_OBJECT_INFO:
912 resp = MTP_RESPONSECODE_INVALIDDATASET;
913 DBG("MTP_RESPONSECODE_INVALIDDATASET");
915 case MTP_ERROR_INVALID_OBJECTHANDLE:
916 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
917 DBG("PTP_RESPONSE_INVALID_OBJ_HANDLE");
919 case MTP_ERROR_INVALID_PARENT:
920 resp = PTP_RESPONSE_INVALIDPARENT;
921 DBG("PTP_RESPONSE_INVALIDPARENT");
923 case MTP_ERROR_ACCESS_DENIED:
924 resp = PTP_RESPONSE_ACCESSDENIED;
925 DBG("PTP_RESPONSE_ACCESSDENIED");
928 resp = PTP_RESPONSE_GEN_ERROR;
929 DBG("PTP_RESPONSE_GEN_ERROR");
935 if (_device_get_phase() != DEVICE_PHASE_NOTREADY) {
936 if (resp == PTP_RESPONSE_OK) {
937 hdlr->last_fmt_code = obj->obj_info->obj_fmt;
938 resp_param[0] = hdlr->data4_send_obj.store_id;
940 /* PTP spec here requires that 0xFFFFFFFF be sent if root is the parent object,
941 * while in some situations(e.g. MoveObject, CopyObject), 0x00000000 (as
942 * PTP_OBJECTHANDLE_ROOT is defined) represents the root.
944 resp_param[1] = (hdlr->data4_send_obj.h_parent
945 != PTP_OBJECTHANDLE_ROOT) ?
946 hdlr->data4_send_obj.h_parent :
948 resp_param[2] = hdlr->data4_send_obj.obj_handle;
949 _cmd_hdlr_send_response(hdlr, resp, 3, resp_param);
951 _cmd_hdlr_send_response_code(hdlr, resp);
956 static void __send_object(mtp_handler_t *hdlr)
958 data_blk_t blk = { 0 };
959 mtp_uint16 resp = PTP_RESPONSE_OK;
960 mtp_char temp_fpath[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
962 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0) ||
963 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
964 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
966 ERR("unsupported parameter");
967 _device_set_phase(DEVICE_PHASE_NOTREADY);
968 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_INVALIDPARAM);
971 #ifndef MTP_USE_SELFMAKE_ABSTRACTION
972 if (hdlr->data4_send_obj.is_valid != TRUE) {
973 DBG("invalide object info");
974 _device_set_phase(DEVICE_PHASE_NOTREADY);
977 #endif /*MTP_USE_SELFMAKE_ABSTRACTION*/
979 _device_set_phase(DEVICE_PHASE_DATAOUT);
980 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
982 if (_hdlr_rcv_file_in_data_container(&blk, temp_fpath,
983 MTP_MAX_PATHNAME_SIZE + 1) == FALSE) {
984 _device_set_phase(DEVICE_PHASE_IDLE);
986 ERR("_hdlr_rcv_file_in_data_container() Fail");
988 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
992 switch (_hutil_write_file_data(hdlr->data4_send_obj.store_id,
993 hdlr->data4_send_obj.obj, temp_fpath)) {
995 case MTP_ERROR_INVALID_OBJECT_INFO:
996 resp = PTP_RESPONSE_NOVALID_OBJINFO;
997 DBG("PTP_RESPONSE_NOVALID_OBJINFO");
999 #ifdef MTP_USE_SELFMAKE_ABSTRACTION
1000 case MTP_ERROR_INVALID_PARAM: /* association file*/
1001 #endif /*MTP_USE_SELFMAKE_ABSTRACTION*/
1002 case MTP_ERROR_NONE:
1003 resp = PTP_RESPONSE_OK;
1004 DBG("PTP_RESPONSE_OK");
1006 case MTP_ERROR_STORE_FULL:
1007 resp = PTP_RESPONSE_STOREFULL;
1008 DBG("PTP_RESPONSE_STOREFULL");
1011 resp = PTP_RESPONSE_GEN_ERROR;
1012 DBG("PTP_RESPONSE_GEN_ERROR");
1014 _cmd_hdlr_send_response_code(hdlr, resp);
1016 /* This object info has been consumed.*/
1017 hdlr->data4_send_obj.obj = NULL;
1018 hdlr->data4_send_obj.is_valid = FALSE;
1023 static void __delete_object(mtp_handler_t *hdlr)
1025 mtp_uint32 obj_handle = 0;
1027 mtp_uint16 resp = 0;
1029 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
1031 ERR("Parameters not supported");
1032 _cmd_hdlr_send_response_code(hdlr,
1033 PTP_RESPONSE_PARAM_NOTSUPPORTED);
1037 obj_handle = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
1038 fmt = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
1039 if ((PTP_FORMATCODE_NOTUSED != fmt) &&
1040 (obj_handle != PTP_OBJECTHANDLE_ALL)) {
1041 ERR("Invalid object format");
1042 _cmd_hdlr_send_response_code(hdlr,
1043 PTP_RESPONSE_INVALID_OBJ_FMTCODE);
1047 _transport_set_mtp_operation_state(MTP_STATE_DATA_PROCESSING);
1049 switch (_hutil_remove_object_entry(obj_handle, fmt)) {
1050 case MTP_ERROR_NONE:
1051 resp = PTP_RESPONSE_OK;
1053 case MTP_ERROR_STORE_READ_ONLY:
1054 resp = PTP_RESPONSE_STORE_READONLY;
1056 case MTP_ERROR_PARTIAL_DELETION:
1057 resp = PTP_RESPONSE_PARTIAL_DELETION;
1059 case MTP_ERROR_OBJECT_WRITE_PROTECTED:
1060 resp = PTP_RESPONSE_OBJ_WRITEPROTECTED;
1062 case MTP_ERROR_ACCESS_DENIED:
1063 resp = PTP_RESPONSE_ACCESSDENIED;
1065 case MTP_ERROR_INVALID_OBJECTHANDLE:
1066 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
1069 resp = PTP_RESPONSE_GEN_ERROR;
1072 _transport_set_mtp_operation_state(MTP_STATE_ONSERVICE);
1073 _cmd_hdlr_send_response_code(hdlr, resp);
1076 static void __format_store(mtp_handler_t *hdlr)
1078 mtp_uint32 store_id = 0;
1079 mtp_uint32 fs_fmt = 0;
1081 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
1082 _cmd_hdlr_send_response_code(hdlr,
1083 PTP_RESPONSE_PARAM_NOTSUPPORTED);
1087 store_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
1088 fs_fmt = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
1090 _hutil_format_storage(store_id, fs_fmt);
1092 /* although there is remain file, send OK */
1093 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
1096 static void __reset_device(mtp_handler_t *hdlr)
1098 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0) ||
1099 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
1100 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
1102 _cmd_hdlr_send_response_code(hdlr,
1103 PTP_RESPONSE_PARAM_NOTSUPPORTED);
1107 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
1110 static void __get_device_prop_desc(mtp_handler_t *hdlr)
1112 device_prop_desc_t dev_prop = { { 0 }, };
1113 device_prop_desc_t *prop_ptr = NULL;
1114 ptp_string_t ptp_str = { 0, { 0 } };
1115 data_blk_t blk = { 0 };
1116 mtp_uint32 prop_id = 0;
1117 mtp_uint32 resp = 0;
1118 mtp_uint32 num_bytes = 0;
1119 mtp_uchar *ptr = NULL;
1120 mtp_wchar temp[MTP_MAX_REG_STRING + 1] = { 0 };
1122 prop_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
1124 #ifdef MTP_SUPPORT_DEVICEPROP_BATTERYLEVEL
1125 case PTP_PROPERTYCODE_BATTERYLEVEL:
1129 prop_ptr = _device_get_device_property(prop_id);
1130 if (NULL == prop_ptr) {
1131 ERR("prop_ptr is NULL!");
1135 batt = _util_get_battery_level();
1136 if (FALSE == _prop_set_current_integer(prop_ptr, batt))
1137 ERR("_util_get_battery_level() Fail");
1140 #endif /* MTP_SUPPORT_DEVICEPROP_BATTERYLEVEL */
1142 case MTP_PROPERTYCODE_DEVICEFRIENDLYNAME:
1144 mtp_char *dev_name = _device_get_device_name();
1145 if (dev_name == NULL) {
1146 ERR("_device_get_device_name() Fail");
1150 prop_ptr = _device_get_device_property(prop_id);
1151 if (NULL == prop_ptr) {
1152 ERR("prop_ptr is Null");
1156 _util_utf8_to_utf16(temp, sizeof(temp) / WCHAR_SIZ, dev_name);
1157 _prop_copy_char_to_ptpstring(&ptp_str, temp, WCHAR_TYPE);
1158 _prop_set_current_string(prop_ptr, &ptp_str);
1163 case MTP_PROPERTYCODE_SYNCHRONIZATIONPARTNER:
1165 mtp_char *sync_ptr = _device_get_sync_partner();
1166 if (NULL == sync_ptr) {
1167 ERR("_device_get_sync_partner() Fail");
1170 prop_ptr = _device_get_device_property(prop_id);
1171 if (NULL == prop_ptr) {
1172 ERR("prop_ptr is Null");
1177 _util_utf8_to_utf16(temp, sizeof(temp) / WCHAR_SIZ, sync_ptr);
1178 _prop_copy_char_to_ptpstring(&ptp_str, temp, WCHAR_TYPE);
1179 _prop_set_current_string(prop_ptr, &ptp_str);
1183 case MTP_PROPERTYCODE_DEVICEICON:
1186 mtp_uint32 bytes_read = 0;
1187 mtp_uint32 file_size = 0;
1189 mtp_uchar *data = NULL;
1192 prop_ptr = _device_get_device_property(prop_id);
1193 if (NULL == prop_ptr) {
1194 ERR("prop_ptr is Null");
1198 h_file = _util_file_open(MTP_DEVICE_ICON, MTP_FILE_READ, &err);
1199 if (h_file == NULL) {
1200 ERR("file handle is not valid");
1201 _cmd_hdlr_send_response_code(hdlr,
1202 PTP_RESPONSE_GEN_ERROR);
1205 if (fstat(fileno((FILE *)h_file), &buf) != 0) {
1206 _util_file_close(h_file);
1207 _cmd_hdlr_send_response_code(hdlr,
1208 PTP_RESPONSE_GEN_ERROR);
1211 file_size = buf.st_size;
1212 data = (mtp_uchar *)g_malloc(file_size + sizeof(mtp_uint32));
1214 ERR("g_malloc() Fail");
1215 _util_file_close(h_file);
1216 _cmd_hdlr_send_response_code(hdlr,
1217 PTP_RESPONSE_GEN_ERROR);
1220 memcpy(data, &file_size, sizeof(mtp_uint32));
1221 _util_file_read(h_file, &data[sizeof(mtp_uint32)], file_size,
1223 if (bytes_read != file_size) {
1224 ERR("Number of read bytes less than requested");
1225 _util_file_close(h_file);
1227 _cmd_hdlr_send_response_code(hdlr,
1228 PTP_RESPONSE_GEN_ERROR);
1232 _prop_set_current_array(prop_ptr, data);
1233 _prop_set_default_array(&(prop_ptr->propinfo),
1234 (mtp_uchar *)&data[sizeof(mtp_uint32)], bytes_read);
1236 _util_file_close(h_file);
1241 ERR("Unknown PropId : [0x%x]\n", prop_id);
1245 if (_hutil_get_device_property(prop_id, &dev_prop) != MTP_ERROR_NONE) {
1246 ERR("_hutil_get_device_property returned error");
1247 resp = PTP_RESPONSE_PROP_NOTSUPPORTED;
1248 _cmd_hdlr_send_response_code(hdlr, resp);
1251 num_bytes = _prop_size_device_prop_desc(&dev_prop);
1253 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
1254 ptr = _hdlr_alloc_buf_data_container(&blk, num_bytes, num_bytes);
1256 resp = PTP_RESPONSE_GEN_ERROR;
1257 _cmd_hdlr_send_response_code(hdlr, resp);
1262 if (_prop_pack_device_prop_desc(&dev_prop, ptr, num_bytes) != num_bytes) {
1263 resp = PTP_RESPONSE_GEN_ERROR;
1264 _cmd_hdlr_send_response_code(hdlr, resp);
1269 _device_set_phase(DEVICE_PHASE_DATAIN);
1270 if (_hdlr_send_data_container(&blk))
1271 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
1273 _device_set_phase(DEVICE_PHASE_NOTREADY);
1274 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
1281 static void __get_device_prop_value(mtp_handler_t *hdlr)
1284 ptp_string_t ptp_str = { 0, { 0 } };
1285 data_blk_t blk = { 0 };
1286 mtp_uint32 prop_id = 0;
1287 mtp_uint32 no_bytes = 0;
1288 mtp_uchar *ptr = NULL;
1289 mtp_wchar temp[MTP_MAX_REG_STRING + 1] = { 0 };
1291 prop_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
1292 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
1295 #ifdef MTP_SUPPORT_DEVICEPROP_BATTERYLEVEL
1296 case PTP_PROPERTYCODE_BATTERYLEVEL: {
1299 batt = _util_get_battery_level();
1300 no_bytes = sizeof(batt);
1302 ptr = _hdlr_alloc_buf_data_container(&blk, no_bytes, no_bytes);
1304 _cmd_hdlr_send_response_code(hdlr,
1305 PTP_RESPONSE_GEN_ERROR);
1309 memcpy(ptr, &batt, no_bytes);
1310 #ifdef __BIG_ENDIAN__
1311 _util_conv_byte_order(ptr, no_bytes);
1312 #endif /*__BIG_ENDIAN__*/
1315 #endif /* MTP_SUPPORT_DEVICEPROP_BATTERYLEVEL */
1317 case MTP_PROPERTYCODE_DEVICEFRIENDLYNAME:
1320 mtp_char *device = _device_get_device_name();
1321 if (device == NULL) {
1322 ERR("_device_get_device_name() Fail");
1323 _cmd_hdlr_send_response_code(hdlr,
1324 PTP_RESPONSE_GEN_ERROR);
1328 _util_utf8_to_utf16(temp, sizeof(temp) / WCHAR_SIZ, device);
1329 _prop_copy_char_to_ptpstring(&ptp_str, temp, WCHAR_TYPE);
1330 no_bytes = _prop_size_ptpstring(&ptp_str);
1333 ptr = _hdlr_alloc_buf_data_container(&blk, no_bytes, no_bytes);
1335 _cmd_hdlr_send_response_code(hdlr,
1336 PTP_RESPONSE_GEN_ERROR);
1341 if (_prop_pack_ptpstring(&ptp_str, ptr, no_bytes) != no_bytes) {
1342 _cmd_hdlr_send_response_code(hdlr,
1343 PTP_RESPONSE_GEN_ERROR);
1350 case MTP_PROPERTYCODE_SYNCHRONIZATIONPARTNER:
1353 mtp_char *sync_ptr = _device_get_sync_partner();
1354 if (sync_ptr == NULL) {
1355 ERR("_device_get_sync_partner() Fail");
1356 _cmd_hdlr_send_response_code(hdlr,
1357 PTP_RESPONSE_GEN_ERROR);
1360 _util_utf8_to_utf16(temp, sizeof(temp) / WCHAR_SIZ, sync_ptr);
1363 _prop_copy_char_to_ptpstring(&ptp_str, temp, WCHAR_TYPE);
1364 no_bytes = _prop_size_ptpstring(&ptp_str);
1366 ptr = _hdlr_alloc_buf_data_container(&blk, no_bytes, no_bytes);
1368 _cmd_hdlr_send_response_code(hdlr,
1369 PTP_RESPONSE_GEN_ERROR);
1374 if (_prop_pack_ptpstring(&ptp_str, ptr, no_bytes) != no_bytes) {
1375 _cmd_hdlr_send_response_code(hdlr,
1376 PTP_RESPONSE_GEN_ERROR);
1383 case MTP_PROPERTYCODE_DEVICEICON:
1387 mtp_uint32 read_bytes = 0;
1388 mtp_uint32 file_size = 0;
1390 mtp_uchar *data = NULL;
1392 ptp_array_t val_arr = { 0 };
1395 h_file = _util_file_open(MTP_DEVICE_ICON, MTP_FILE_READ, &err);
1396 if (h_file == NULL) {
1397 ERR("file handle is not valid");
1398 _cmd_hdlr_send_response_code(hdlr,
1399 PTP_RESPONSE_GEN_ERROR);
1402 if (fstat(fileno(h_file), &buf) != 0) {
1403 _util_file_close(h_file);
1404 _cmd_hdlr_send_response_code(hdlr,
1405 PTP_RESPONSE_GEN_ERROR);
1409 file_size = buf.st_size;
1410 data = (mtp_uchar *)g_malloc(file_size);
1412 ERR("g_malloc() Fail");
1413 _util_file_close(h_file);
1414 _cmd_hdlr_send_response_code(hdlr,
1415 PTP_RESPONSE_GEN_ERROR);
1419 _util_file_read(h_file, &data, file_size, &read_bytes);
1420 if (read_bytes != file_size) {
1421 ERR("Number of read bytes less than requested");
1422 _util_file_close(h_file);
1424 _cmd_hdlr_send_response_code(hdlr,
1425 PTP_RESPONSE_GEN_ERROR);
1429 _prop_init_ptparray(&val_arr, UINT8_TYPE);
1430 _prop_grow_ptparray(&val_arr, read_bytes);
1431 for (ii = 0; ii < read_bytes; ii++)
1432 _prop_append_ele_ptparray(&val_arr, data[ii]);
1434 no_bytes = _prop_get_size_ptparray(&val_arr);
1435 ptr = _hdlr_alloc_buf_data_container(&blk, no_bytes, no_bytes);
1437 _cmd_hdlr_send_response_code(hdlr,
1438 PTP_RESPONSE_GEN_ERROR);
1441 _util_file_close(h_file);
1442 _prop_deinit_ptparray(&val_arr);
1445 if (_prop_pack_ptparray(&val_arr, ptr, no_bytes) != no_bytes) {
1446 _cmd_hdlr_send_response_code(hdlr,
1447 PTP_RESPONSE_GEN_ERROR);
1450 _prop_deinit_ptparray(&val_arr);
1451 _util_file_close(h_file);
1456 _prop_deinit_ptparray(&val_arr);
1457 _util_file_close(h_file);
1463 ERR("Unknown PropId : [0x%x]\n", prop_id);
1464 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
1468 _device_set_phase(DEVICE_PHASE_DATAIN);
1469 if (_hdlr_send_data_container(&blk)) {
1470 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
1472 _device_set_phase(DEVICE_PHASE_NOTREADY);
1473 _cmd_hdlr_send_response_code(hdlr,
1474 PTP_RESPONSE_INCOMPLETETRANSFER);
1480 static void __set_device_prop_value(mtp_handler_t *hdlr)
1482 mtp_uint32 prop_id = 0;
1483 data_blk_t blk = { 0 };
1484 mtp_uint32 max_bytes = 0;
1485 mtp_uint16 resp = PTP_RESPONSE_OK;
1487 mtp_char *d_raw = NULL;
1489 prop_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
1490 _device_set_phase(DEVICE_PHASE_DATAOUT);
1492 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
1493 max_bytes = MAX_SIZE_IN_BYTES_OF_PROP_VALUE;
1495 if (FALSE == _hdlr_rcv_data_container(&blk, max_bytes)) {
1496 ERR("_hdlr_rcv_data_container() Fail");
1497 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
1502 d_raw = (mtp_char *)_hdlr_get_payload_data(&blk);
1503 if (NULL != d_raw) {
1504 ret = _hutil_set_device_property(prop_id, d_raw,
1505 _hdlr_get_payload_size(&blk));
1507 ret = MTP_ERROR_INVALID_OBJ_PROP_CODE;
1511 case MTP_ERROR_NONE: {
1512 #ifdef MTP_USE_INFORMATION_REGISTRY
1514 mtp_char temp[MTP_MAX_REG_STRING * 3 + 1] = { 0 };
1515 mtp_wchar parsed_buf[MTP_MAX_REG_STRING + 1] = { 0 };
1516 mtp_uchar parse_sz = 0;
1518 if (MTP_PROPERTYCODE_SYNCHRONIZATIONPARTNER == prop_id) {
1519 parse_sz = d_raw[0];
1520 _util_wchar_ncpy(parsed_buf, (mtp_wchar *)&d_raw[1],
1521 parse_sz > MTP_MAX_REG_STRING ?
1522 MTP_MAX_REG_STRING : parse_sz);
1523 _util_utf16_to_utf8(temp, sizeof(temp), parsed_buf);
1524 _device_set_sync_partner(temp);
1525 if (!g_strcmp0(temp,
1526 MTP_DEV_PROPERTY_NULL_SYNCPARTNER)) {
1527 vconf_set_str(VCONFKEY_MTP_SYNC_PARTNER_STR,
1530 vconf_set_str(VCONFKEY_MTP_SYNC_PARTNER_STR,
1534 #endif /*MTP_USE_INFORMATION_REGISTRY*/
1536 resp = PTP_RESPONSE_OK;
1538 case MTP_ERROR_ACCESS_DENIED:
1539 resp = PTP_RESPONSE_ACCESSDENIED;
1541 case MTP_ERROR_INVALID_OBJ_PROP_VALUE:
1542 resp = PTP_RESPONSE_INVALIDPROPVALUE;
1545 resp = PTP_RESPONSE_PROP_NOTSUPPORTED;
1548 _cmd_hdlr_send_response_code(hdlr, resp);
1554 static void __get_partial_object(mtp_handler_t *hdlr)
1556 mtp_uint32 h_obj = 0;
1558 mtp_uint32 data_sz = 0;
1559 mtp_uint32 send_bytes = 0;
1560 data_blk_t blk = { 0 };
1561 mtp_uchar *ptr = NULL;
1562 mtp_uint16 resp = 0;
1563 mtp_uint64 f_size = 0;
1564 mtp_uint64 total_sz = 0;
1566 offset = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
1567 data_sz = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2);
1568 h_obj = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
1570 switch (_hutil_get_object_entry_size(h_obj, &f_size)) {
1572 case MTP_ERROR_INVALID_OBJECTHANDLE:
1573 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
1575 case MTP_ERROR_NONE:
1576 if (data_sz > (f_size - offset))
1577 send_bytes = f_size - offset;
1579 send_bytes = data_sz;
1580 resp = PTP_RESPONSE_OK;
1583 resp = PTP_RESPONSE_GEN_ERROR;
1587 if (PTP_RESPONSE_OK != resp) {
1588 _cmd_hdlr_send_response_code(hdlr, resp);
1592 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
1593 ptr = _hdlr_alloc_buf_data_container(&blk, send_bytes, send_bytes);
1596 switch (_hutil_read_file_data_from_offset(h_obj, offset, ptr, &send_bytes)) {
1597 case MTP_ERROR_NONE:
1598 resp = PTP_RESPONSE_OK;
1600 case MTP_ERROR_INVALID_OBJECTHANDLE:
1601 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
1604 resp = PTP_RESPONSE_GEN_ERROR;
1607 resp = PTP_RESPONSE_GEN_ERROR;
1610 if (PTP_RESPONSE_OK == resp) {
1611 _device_set_phase(DEVICE_PHASE_DATAIN);
1612 if (_hdlr_send_data_container(&blk)) {
1613 total_sz = send_bytes + sizeof(header_container_t);
1614 if (total_sz % _transport_get_usb_packet_len() == 0)
1615 _transport_send_zlp();
1616 _cmd_hdlr_send_response(hdlr, resp, 1, &send_bytes);
1621 /*Host Cancelled data-in transfer*/
1622 _device_set_phase(DEVICE_PHASE_NOTREADY);
1627 _cmd_hdlr_send_response_code(hdlr, resp);
1633 static void __get_object_references(mtp_handler_t *hdlr)
1635 mtp_uint32 h_obj = 0;
1636 ptp_array_t ref_arr = { 0 };
1637 data_blk_t blk = { 0 };
1638 mtp_uint32 num_bytes = 0;
1639 mtp_uchar *ptr = NULL;
1640 mtp_uint32 num_ele = 0;
1641 mtp_uint16 resp = 0;
1643 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
1644 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
1646 ERR("Unsupported Parameters");
1647 _cmd_hdlr_send_response_code(hdlr,
1648 PTP_RESPONSE_PARAM_NOTSUPPORTED);
1652 h_obj = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
1654 switch (_hutil_get_object_references(h_obj, &ref_arr, &num_ele)) {
1655 case MTP_ERROR_INVALID_OBJECTHANDLE:
1656 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
1658 case MTP_ERROR_NONE:
1659 resp = PTP_RESPONSE_OK;
1662 resp = PTP_RESPONSE_GEN_ERROR;
1665 if (resp != PTP_RESPONSE_OK) {
1666 _cmd_hdlr_send_response_code(hdlr, resp);
1670 if (resp == PTP_RESPONSE_OK && num_ele == 0) {
1671 _cmd_hdlr_send_response_code(hdlr, resp);
1675 num_bytes = _prop_get_size_ptparray(&ref_arr);
1676 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
1678 ptr = _hdlr_alloc_buf_data_container(&blk, num_bytes, num_bytes);
1679 if (num_bytes == _prop_pack_ptparray(&ref_arr, ptr, num_bytes)) {
1680 _device_set_phase(DEVICE_PHASE_DATAIN);
1681 if (_hdlr_send_data_container(&blk)) {
1682 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
1684 /* Host Cancelled data-in transfer*/
1685 _device_set_phase(DEVICE_PHASE_NOTREADY);
1688 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
1691 _prop_deinit_ptparray(&ref_arr);
1697 static void __set_object_references(mtp_handler_t *hdlr)
1699 mtp_uint32 h_obj = 0;
1700 data_blk_t blk = { 0 };
1701 mtp_uint32 max_bytes = 0;
1702 mtp_uint16 resp = PTP_RESPONSE_OK;
1703 mtp_uint32 num_ref = 0;
1705 mtp_uint32 *ref_ptr = NULL;
1706 mtp_uchar *ptr = NULL;
1707 mtp_uint32 ref_handle = 0;
1709 h_obj = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
1710 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
1711 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
1713 resp = PTP_RESPONSE_PARAM_NOTSUPPORTED;
1714 _cmd_hdlr_send_response_code(hdlr, resp);
1717 _device_set_phase(DEVICE_PHASE_DATAOUT);
1718 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
1720 /* temporarily set a big number for data size received */
1722 max_bytes = MTP_MAX_REFDB_ROWCNT * sizeof(mtp_uint32);
1723 if (_hdlr_rcv_data_container(&blk, max_bytes) == FALSE) {
1724 DBG("_hdlr_rcv_data_container() Fail");
1725 _device_set_phase(DEVICE_PHASE_IDLE);
1726 resp = PTP_RESPONSE_GEN_ERROR;
1729 if (PTP_RESPONSE_OK != resp) {
1730 _cmd_hdlr_send_response_code(hdlr, resp);
1735 ptr = _hdlr_get_payload_data(&blk);
1741 memcpy(&num_ref, ptr, sizeof(mtp_uint32));
1742 #ifdef __BIG_ENDIAN__
1743 _util_conv_byte_order(&num_ref, sizeof(DWORD));
1744 #endif /* __BIG_ENDIAN__ */
1746 ptr += sizeof(mtp_uint32);
1747 if (_hdlr_get_payload_size(&blk) < (num_ref + 1) * sizeof(mtp_uint32)) {
1749 resp = PTP_RESPONSE_GEN_ERROR;
1750 _cmd_hdlr_send_response_code(hdlr, resp);
1755 ref_ptr = (mtp_uint32 *)ptr;
1756 if (MTP_ERROR_NONE != _hutil_remove_object_reference(h_obj,
1757 PTP_OBJECTHANDLE_ALL)) {
1758 resp = PTP_RESPONSE_GEN_ERROR;
1759 _cmd_hdlr_send_response_code(hdlr, resp);
1763 for (idx = 0; idx < num_ref; idx++) {
1764 ref_handle = ref_ptr[idx];
1765 #ifdef __BIG_ENDIAN__
1766 _util_conv_byte_order(&ref_handle, sizeof(mtp_uint32));
1767 #endif /*__BIG_ENDIAN__*/
1768 _device_get_object_with_handle(ref_handle);
1771 _hutil_add_object_references_enhanced(h_obj, (mtp_uchar *)ref_ptr,
1773 _cmd_hdlr_send_response_code(hdlr, resp);
1779 static void __get_object_prop_desc(mtp_handler_t *hdlr)
1781 mtp_uint32 prop_id = 0;
1783 obj_prop_desc_t prop = { { 0 }, };
1784 data_blk_t blk = { 0, };
1785 mtp_uint32 num_bytes = 0;
1786 mtp_uchar *ptr = NULL;
1788 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
1789 _cmd_hdlr_send_response_code(hdlr,
1790 PTP_RESPONSE_PARAM_NOTSUPPORTED);
1794 prop_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
1795 fmt = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
1797 if (MTP_ERROR_NONE != _hutil_get_prop_desc(fmt, prop_id, &prop)) {
1798 _cmd_hdlr_send_response_code(hdlr,
1799 PTP_RESPONSE_PROP_NOTSUPPORTED);
1803 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
1804 num_bytes = _prop_size_obj_prop_desc(&prop);
1805 ptr = _hdlr_alloc_buf_data_container(&blk, num_bytes, num_bytes);
1807 if (num_bytes == _prop_pack_obj_prop_desc(&prop, ptr, num_bytes)) {
1808 _device_set_phase(DEVICE_PHASE_DATAIN);
1809 if (_hdlr_send_data_container(&blk)) {
1810 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
1812 /* Host Cancelled data-in transfer */
1813 _device_set_phase(DEVICE_PHASE_NOTREADY);
1816 _cmd_hdlr_send_response_code(hdlr,
1817 PTP_RESPONSE_GEN_ERROR);
1824 static void __get_object_prop_supported(mtp_handler_t *hdlr)
1827 data_blk_t blk = { 0 };
1828 ptp_array_t props_supported = { 0 };
1829 mtp_uint32 num_bytes = 0;
1830 mtp_uchar *ptr = NULL;
1832 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
1833 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
1834 _cmd_hdlr_send_response_code(hdlr,
1835 PTP_RESPONSE_PARAM_NOTSUPPORTED);
1839 fmt = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
1840 _prop_init_ptparray(&props_supported, UINT16_TYPE);
1842 if (MTP_ERROR_NONE != _hutil_get_object_prop_supported(fmt,
1843 &props_supported)) {
1844 _prop_deinit_ptparray(&props_supported);
1845 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
1849 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
1850 num_bytes = _prop_get_size_ptparray(&props_supported);
1851 ptr = _hdlr_alloc_buf_data_container(&blk, num_bytes, num_bytes);
1854 _prop_pack_ptparray(&props_supported, ptr, num_bytes);
1855 _device_set_phase(DEVICE_PHASE_DATAIN);
1856 if (_hdlr_send_data_container(&blk)) {
1857 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
1859 /* Host Cancelled data-in transfer */
1860 _device_set_phase(DEVICE_PHASE_NOTREADY);
1863 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
1866 _prop_deinit_ptparray(&props_supported);
1872 static void __get_object_prop_value(mtp_handler_t *hdlr)
1874 mtp_uint32 h_obj = 0;
1875 mtp_uint32 prop_id = 0;
1876 mtp_uchar *ptr = NULL;
1877 mtp_uint32 num_bytes = 0;
1878 data_blk_t blk = { 0 };
1879 obj_prop_val_t prop_val = { 0 };
1881 mtp_obj_t *obj = NULL;
1882 #ifdef MTP_USE_RUNTIME_GETOBJECTPROPVALUE
1883 slist_node_t *node = NULL;
1884 slist_node_t *next_node = NULL;
1886 #endif /*MTP_USE_RUNTIME_GETOBJECTPROPVALUE*/
1888 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
1889 _cmd_hdlr_send_response_code(hdlr,
1890 PTP_RESPONSE_PARAM_NOTSUPPORTED);
1894 h_obj = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
1895 prop_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
1896 ret = _hutil_get_object_prop_value(h_obj, prop_id, &prop_val, &obj);
1898 if (MTP_ERROR_NONE == ret) {
1899 num_bytes = _prop_size_obj_propval(&prop_val);
1900 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code,
1902 ptr = _hdlr_alloc_buf_data_container(&blk, num_bytes,
1905 _prop_pack_obj_propval(&prop_val, ptr, num_bytes)) {
1907 _device_set_phase(DEVICE_PHASE_DATAIN);
1908 if (_hdlr_send_data_container(&blk)) {
1909 _cmd_hdlr_send_response_code(hdlr,
1912 /* Host Cancelled data-in transfer */
1913 _device_set_phase(DEVICE_PHASE_NOTREADY);
1916 _cmd_hdlr_send_response_code(hdlr,
1917 PTP_RESPONSE_GEN_ERROR);
1922 } else if (ret == MTP_ERROR_INVALID_OBJECTHANDLE) {
1923 _cmd_hdlr_send_response_code(hdlr,
1924 PTP_RESPONSE_INVALID_OBJ_HANDLE);
1926 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
1929 #ifdef MTP_USE_RUNTIME_GETOBJECTPROPVALUE
1931 ERR("Invalid object");
1935 for (ii = 0, next_node = obj->propval_list.start;
1936 ii < obj->propval_list.nnodes; ii++) {
1938 next_node = node->link;
1939 _prop_destroy_obj_propval((obj_prop_val_t *)node->value);
1942 obj->propval_list.start = NULL;
1943 obj->propval_list.end = NULL;
1944 obj->propval_list.nnodes = 0;
1945 #endif /*MTP_USE_RUNTIME_GETOBJECTPROPVALUE*/
1950 static void __set_object_prop_value(mtp_handler_t *hdlr)
1952 mtp_uint32 h_obj = 0;
1953 mtp_uint32 prop_id = 0;
1954 mtp_uint16 resp = PTP_RESPONSE_OK;
1955 data_blk_t blk = { 0 };
1956 mtp_uint32 max_bytes = 0;
1959 h_obj = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
1960 prop_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
1962 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
1963 ERR("Unsupported parameters");
1964 resp = PTP_RESPONSE_PARAM_NOTSUPPORTED;
1965 _cmd_hdlr_send_response_code(hdlr, resp);
1969 _device_set_phase(DEVICE_PHASE_DATAOUT);
1970 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
1971 max_bytes = MTP_MAX_PROP_DATASIZE;
1973 if (_hdlr_rcv_data_container(&blk, max_bytes) == FALSE) {
1974 ERR("_hdlr_rcv_data_container() Fail");
1975 _device_set_phase(DEVICE_PHASE_IDLE);
1976 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_INVALIDPROPVALUE);
1981 ret = _hutil_update_object_property(h_obj, prop_id, NULL,
1982 _hdlr_get_payload_data(&blk),
1983 _hdlr_get_payload_size(&blk), NULL);
1985 case MTP_ERROR_ACCESS_DENIED:
1986 resp = PTP_RESPONSE_ACCESSDENIED;
1988 case MTP_ERROR_INVALID_OBJECTHANDLE:
1989 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
1991 case MTP_ERROR_INVALID_OBJ_PROP_CODE:
1992 resp = PTP_RESPONSE_PROP_NOTSUPPORTED;
1994 case MTP_ERROR_GENERAL:
1995 resp = PTP_RESPONSE_GEN_ERROR;
1997 case MTP_ERROR_NONE:
1998 resp = PTP_RESPONSE_OK;
2001 resp = PTP_RESPONSE_INVALIDPROPVALUE;
2005 _cmd_hdlr_send_response_code(hdlr, resp);
2011 static void __get_object_prop_list(mtp_handler_t *hdlr)
2013 mtp_uint32 h_obj = 0;
2015 mtp_uint32 prop_id = 0;
2016 mtp_uint32 group_code = 0;
2017 mtp_uint32 depth = 0;
2019 mtp_uint16 resp = 0;
2020 obj_proplist_t prop_list = { { 0 } };
2021 data_blk_t blk = { 0 };
2022 mtp_uint32 num_bytes = 0;
2023 mtp_uchar *ptr = NULL;
2024 #ifdef MTP_USE_RUNTIME_GETOBJECTPROPVALUE
2025 ptp_array_t obj_arr = { 0 };
2026 slist_node_t *node = NULL;
2027 slist_node_t *next_node = NULL;
2030 mtp_obj_t *obj = NULL;
2031 #endif /*MTP_USE_RUNTIME_GETOBJECTPROPVALUE*/
2033 h_obj = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
2034 fmt = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
2035 prop_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2);
2036 group_code = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 3);
2037 depth = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 4);
2039 __enum_store_not_enumerated(h_obj, fmt, depth);
2041 #ifdef MTP_USE_RUNTIME_GETOBJECTPROPVALUE
2042 ret = _hutil_get_object_prop_list(h_obj, fmt, prop_id, group_code,
2043 depth, &prop_list, &obj_arr);
2044 #else /*MTP_USE_RUNTIME_GETOBJECTPROPVALUE*/
2045 ret = _hutil_get_object_prop_list(h_obj, fmt, prop_id, group_code,
2047 #endif /*MTP_USE_RUNTIME_GETOBJECTPROPVALUE*/
2050 case MTP_ERROR_NONE:
2051 resp = PTP_RESPONSE_OK;
2053 case MTP_ERROR_INVALID_OBJECTHANDLE:
2054 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
2056 case MTP_ERROR_INVALID_PARAM:
2057 resp = PTP_RESPONSE_INVALIDPARAM;
2059 case MTP_ERROR_NO_SPEC_BY_FORMAT:
2060 resp = PTP_RESPONSE_NOSPECIFICATIONBYFORMAT;
2062 case MTP_ERROR_GENERAL:
2064 resp = PTP_RESPONSE_GEN_ERROR;
2067 if (PTP_RESPONSE_OK != resp) {
2068 _cmd_hdlr_send_response_code(hdlr, resp);
2069 _prop_deinit_ptparray(&obj_arr);
2073 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
2074 num_bytes = _prop_size_obj_proplist(&prop_list);
2075 ptr = _hdlr_alloc_buf_data_container(&blk, num_bytes, num_bytes);
2076 if (num_bytes == _prop_pack_obj_proplist(&prop_list, ptr, num_bytes)) {
2078 _device_set_phase(DEVICE_PHASE_DATAIN);
2079 if (_hdlr_send_data_container(&blk)) {
2080 _cmd_hdlr_send_response_code(hdlr, resp);
2082 /* Host Cancelled data-in transfer*/
2083 _device_set_phase(DEVICE_PHASE_NOTREADY);
2087 _prop_destroy_obj_proplist(&prop_list);
2090 #ifdef MTP_USE_RUNTIME_GETOBJECTPROPVALUE
2091 if (resp == PTP_RESPONSE_OK && obj_arr.array_entry) {
2092 mtp_uint32 *obj_handles = obj_arr.array_entry;
2094 for (ii = 0; ii < obj_arr.num_ele; ii++) {
2095 mtp_store_t *store = NULL;
2097 store = _device_get_store_containing_obj(obj_handles[ii]);
2101 obj = _entity_get_object_from_store(store, obj_handles[ii]);
2102 if (NULL == obj || obj->propval_list.nnodes == 0)
2105 /*Remove all the old property value, and ready to set up new */
2106 for (jj = 0, next_node = obj->propval_list.start;
2107 jj < obj->propval_list.nnodes; jj++) {
2109 next_node = node->link;
2110 _prop_destroy_obj_propval
2111 ((obj_prop_val_t *)node->value);
2114 obj->propval_list.start = NULL;
2115 obj->propval_list.end = NULL;
2116 obj->propval_list.nnodes = 0;
2120 _prop_deinit_ptparray(&obj_arr);
2121 #endif /*MTP_USE_RUNTIME_GETOBJECTPROPVALUE*/
2125 static void __set_object_prop_list(mtp_handler_t *hdlr)
2128 mtp_uint16 resp = PTP_RESPONSE_OK;
2129 data_blk_t blk = { 0 };
2130 mtp_uint32 max_num_obj = 0;
2131 mtp_uint32 max_bytes = 0;
2132 mtp_uint32 h_obj = 0;
2133 mtp_uint32 prop_id = 0;
2134 mtp_uint32 data_type = 0;
2135 mtp_uchar *temp = NULL;
2136 mtp_int32 bytes_left = 0;
2137 mtp_uint32 prop_val_sz = 0;
2138 mtp_uint32 num_elem = 0;
2141 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0) ||
2142 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
2143 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2) ||
2144 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 3) ||
2145 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 4)) {
2146 resp = PTP_RESPONSE_PARAM_NOTSUPPORTED;
2149 _device_set_phase(DEVICE_PHASE_DATAOUT);
2150 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
2152 /* Gestimate the amount of data we will be receiving */
2153 _hutil_get_number_of_objects(PTP_STORAGEID_ALL, &max_num_obj);
2154 max_bytes = max_num_obj * 1000;
2156 /* If Host sent more data than we could receive, a device stall happens,
2157 * which cancels the data transfer
2159 if (max_bytes > 1000000) {
2160 max_bytes = 1000000;
2161 ERR("max_bytes is overflowed");
2163 if (FALSE == _hdlr_rcv_data_container(&blk, max_bytes)) {
2164 ERR("_hdlr_rcv_data_container() Fail");
2165 _device_set_phase(DEVICE_PHASE_NOTREADY);
2166 resp = PTP_RESPONSE_GEN_ERROR;
2169 if (PTP_RESPONSE_OK != resp) {
2170 _cmd_hdlr_send_response(hdlr, resp, 1, &i);
2175 temp = _hdlr_get_payload_data(&blk);
2176 bytes_left = (mtp_int32)_hdlr_get_payload_size(&blk);
2177 if (bytes_left < sizeof(mtp_uint32)) {
2179 resp = MTP_RESPONSE_INVALIDOBJPROPFORMAT;
2180 _cmd_hdlr_send_response(hdlr, resp, 1, &i);
2183 ERR("invalid object format, bytes_left [%d]:[%u]\n", bytes_left,
2184 sizeof(mtp_uint32));
2189 memcpy(&num_elem, temp, sizeof(mtp_uint32));
2190 temp += sizeof(mtp_uint32);
2191 bytes_left -= sizeof(mtp_uint32);
2193 for (i = 0; i < num_elem; i++) {
2197 /*Get object handle*/
2198 memcpy(&h_obj, temp, sizeof(mtp_uint32));
2199 temp += sizeof(mtp_uint32);
2200 bytes_left -= sizeof(mtp_uint32);
2204 /* Get property code */
2205 memcpy(&prop_id, temp, sizeof(mtp_uint16));
2206 temp += sizeof(mtp_uint16);
2207 bytes_left -= sizeof(mtp_uint16);
2212 memcpy(&data_type, temp, sizeof(mtp_uint16));
2213 temp += sizeof(mtp_uint16);
2214 bytes_left -= sizeof(mtp_uint16);
2218 /* Update property*/
2219 ret = _hutil_update_object_property(h_obj, prop_id,
2220 (mtp_uint16 *)&data_type, temp, bytes_left,
2224 case MTP_ERROR_INVALID_OBJECT_PROP_FORMAT:
2225 resp = MTP_RESPONSE_INVALIDOBJPROPFORMAT;
2226 _cmd_hdlr_send_response(hdlr, resp, 1, &i);
2228 ERR("invalid object format");
2231 case MTP_ERROR_ACCESS_DENIED:
2232 resp = PTP_RESPONSE_ACCESSDENIED;
2233 _cmd_hdlr_send_response(hdlr, resp, 1, &i);
2235 ERR("access denied");
2238 case MTP_ERROR_INVALID_OBJECTHANDLE:
2239 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
2240 _cmd_hdlr_send_response(hdlr, resp, 1, &i);
2242 ERR("invalid object handle");
2245 case MTP_ERROR_INVALID_OBJ_PROP_CODE:
2246 resp = PTP_RESPONSE_PROP_NOTSUPPORTED;
2247 _cmd_hdlr_send_response(hdlr, resp, 1, &i);
2249 ERR("property not supported");
2252 case MTP_ERROR_NONE:
2253 temp += prop_val_sz;
2254 bytes_left -= prop_val_sz;
2257 resp = PTP_RESPONSE_INVALIDPROPVALUE;
2258 _cmd_hdlr_send_response(hdlr, resp, 1, &i);
2260 ERR("invalid property value");
2266 resp = PTP_RESPONSE_OK;
2267 _cmd_hdlr_send_response(hdlr, resp, 1, &i);
2272 static void __report_acquired_content(mtp_handler_t *hdlr)
2275 mtp_uint32 start_idx = 0;
2276 mtp_uint32 max_size = 0;
2277 mtp_uint16 resp = PTP_RESPONSE_OK;
2278 mtp_uint32 resp_param[3] = { 0 };
2279 data_blk_t blk = { 0 };
2280 mtp_uchar *ptr = NULL;
2281 ptp_array_t guid_arr = { 0 };
2282 mtp_uint32 num_mod = 0;
2283 mtp_uint32 num_bytes = 0;
2284 mtp_uint32 num_lines = 0;
2285 mtp_uint32 rem_modified = 0;
2289 mtp_int32 diff_time;
2293 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 3)) {
2295 ERR("Unsupported parameters");
2296 _cmd_hdlr_send_response_code(hdlr,
2297 PTP_RESPONSE_PARAM_NOTSUPPORTED);
2301 tid = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
2302 start_idx = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
2303 max_size = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2);
2307 if (access(MTP_FILES_MODIFIED_FILES, F_OK) == 0)
2308 if (remove(MTP_FILES_MODIFIED_FILES) < 0)
2309 ERR("remove(%s) Fail", MTP_FILES_MODIFIED_FILES);
2311 resp = PTP_RESPONSE_OK;
2312 _prop_grow_ptparray(&guid_arr, 1);
2313 _prop_append_ele_ptparray(&guid_arr, 0);
2317 g_is_sync_estab = TRUE;
2319 if (!g_has_round_trip && start_idx == 0) {
2321 ret = vconf_get_int(VCONFKEY_MTP_SYNC_TIME_INT, (int *)&l_time);
2323 ERR("Error to get key value at [%s] path\n",
2324 VCONFKEY_MTP_SYNC_TIME_INT);
2325 resp = PTP_RESPONSE_OK;
2326 _prop_grow_ptparray(&guid_arr, 1);
2327 _prop_append_ele_ptparray(&guid_arr, 0);
2330 diff_time = (cur_time - l_time) / 60;
2331 if (diff_time < 0) {
2332 resp = PTP_RESPONSE_GEN_ERROR;
2333 _prop_init_ptparray(&guid_arr, UINT32_TYPE);
2334 _prop_append_ele_ptparray(&guid_arr, 0);
2337 _entity_list_modified_files(diff_time);
2340 h_file = _util_file_open(MTP_FILES_MODIFIED_FILES, MTP_FILE_READ, &err);
2341 if (h_file == NULL) {
2342 resp = PTP_RESPONSE_GEN_ERROR;
2343 _prop_init_ptparray(&guid_arr, UINT32_TYPE);
2344 _prop_append_ele_ptparray(&guid_arr, 0);
2348 if (!g_has_round_trip && start_idx == 0) {
2349 _util_count_num_lines(h_file, &g_mgr->meta_info.mod);
2350 _util_file_seek(h_file, 0, SEEK_SET);
2352 num_lines = g_mgr->meta_info.mod;
2353 num_mod = ((num_lines - start_idx) > max_size) ?
2354 max_size : num_lines - start_idx;
2356 rem_modified = (num_lines - start_idx > max_size) ?
2357 (num_lines - start_idx - max_size) : 0;
2359 g_has_round_trip = FALSE;
2360 _prop_init_ptparray(&guid_arr, UINT32_TYPE);
2361 _prop_grow_ptparray(&guid_arr, (num_mod * sizeof(mtp_uint32)) + 1);
2362 _prop_append_ele_ptparray(&guid_arr, num_mod);
2363 _util_fill_guid_array(&guid_arr, start_idx, h_file, num_mod);
2365 _util_file_close(h_file);
2366 if (rem_modified == 0) {
2367 if (remove(MTP_FILES_MODIFIED_FILES) < 0)
2368 ERR("remove(%s) Fail", MTP_FILES_MODIFIED_FILES);
2370 g_mgr->meta_info.mod = 0;
2374 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
2375 num_bytes = _prop_get_size_ptparray_without_elemsize(&guid_arr);
2376 ptr = _hdlr_alloc_buf_data_container(&blk, num_bytes, num_bytes);
2379 _prop_pack_ptparray_without_elemsize(&guid_arr, ptr, num_bytes);
2380 _device_set_phase(DEVICE_PHASE_DATAIN);
2383 if (_hdlr_send_data_container(&blk))
2384 resp = PTP_RESPONSE_OK;
2386 resp = PTP_RESPONSE_GEN_ERROR;
2388 _prop_deinit_ptparray(&guid_arr);
2391 if (PTP_RESPONSE_OK == resp) {
2393 resp_param[0] = hdlr->usb_cmd.tid;
2394 resp_param[1] = rem_modified;
2396 _cmd_hdlr_send_response(hdlr, resp, 3, resp_param);
2398 _cmd_hdlr_send_response_code(hdlr, resp);
2403 static void __send_playback_skip(mtp_handler_t *hdlr)
2406 mtp_uint16 resp = PTP_RESPONSE_INVALIDPARAM;
2408 skip = (mtp_int32) _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
2409 if (MTP_ERROR_NONE == _hutil_get_playback_skip(skip))
2410 resp = PTP_RESPONSE_OK;
2412 _cmd_hdlr_send_response_code(hdlr, resp);
2417 static void __self_test(mtp_handler_t *hdlr)
2419 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
2420 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
2421 ERR("Unsupported parameters");
2422 _cmd_hdlr_send_response_code(hdlr,
2423 PTP_RESPONSE_PARAM_NOTSUPPORTED);
2427 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
2428 /* Do device-specific tests */
2429 /* After the test */
2430 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
2434 #ifdef MTP_SUPPORT_SET_PROTECTION
2435 static void __set_object_protection(mtp_handler_t *hdlr)
2437 mtp_uint32 h_obj = 0;
2438 mtp_uint16 protcn_status = 0;
2439 mtp_uint16 resp = 0;
2441 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
2442 ERR("Unsupported parameter");
2443 _cmd_hdlr_send_response_code(hdlr,
2444 PTP_RESPONSE_PARAM_NOTSUPPORTED);
2448 h_obj = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
2449 protcn_status = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
2451 if ((protcn_status != PTP_PROTECTIONSTATUS_NOPROTECTION) &&
2452 (protcn_status != PTP_PROTECTIONSTATUS_READONLY) &&
2453 (protcn_status != MTP_PROTECTIONSTATUS_READONLY_DATA) &&
2454 (protcn_status != MTP_PROTECTIONSTATUS_NONTRANSFERABLE_DATA)) {
2456 resp = PTP_RESPONSE_INVALIDPARAM;
2457 _cmd_hdlr_send_response_code(hdlr, resp);
2461 switch (_hutil_set_protection(h_obj, protcn_status)) {
2462 case MTP_ERROR_INVALID_OBJECTHANDLE:
2463 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
2465 case MTP_ERROR_OBJECT_WRITE_PROTECTED:
2466 resp = PTP_RESPONSE_OBJ_WRITEPROTECTED;
2468 case MTP_ERROR_NONE:
2469 resp = PTP_RESPONSE_OK;
2471 case MTP_ERROR_OPERATION_NOT_SUPPORTED:
2472 resp = PTP_RESPONSE_OP_NOT_SUPPORTED;
2475 resp = PTP_RESPONSE_GEN_ERROR;
2478 _cmd_hdlr_send_response_code(hdlr, resp);
2481 #endif /* MTP_SUPPORT_SET_PROTECTION */
2483 static void __power_down(mtp_handler_t *hdlr)
2485 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0) ||
2486 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
2487 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
2488 ERR("Unsupported Parameter");
2489 _cmd_hdlr_send_response_code(hdlr,
2490 PTP_RESPONSE_PARAM_NOTSUPPORTED);
2494 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
2496 _cmd_hdlr_reset_cmd(hdlr);
2500 static void __move_object(mtp_handler_t *hdlr)
2502 mtp_uint32 store_id = 0;
2503 mtp_uint32 obj_handle = 0;
2504 mtp_uint32 h_parent = 0;
2505 mtp_uint32 resp = 0;
2507 obj_handle = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
2508 store_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
2509 h_parent = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2);
2511 _transport_set_mtp_operation_state(MTP_STATE_DATA_PROCESSING);
2513 switch (_hutil_move_object_entry(store_id, h_parent, obj_handle)) {
2514 case MTP_ERROR_NONE:
2515 resp = PTP_RESPONSE_OK;
2517 case MTP_ERROR_INVALID_OBJECTHANDLE:
2518 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
2520 case MTP_ERROR_OBJECT_WRITE_PROTECTED:
2521 resp = PTP_RESPONSE_OBJ_WRITEPROTECTED;
2523 case MTP_ERROR_ACCESS_DENIED:
2524 resp = PTP_RESPONSE_ACCESSDENIED;
2526 case MTP_ERROR_STORE_NOT_AVAILABLE:
2527 resp = PTP_RESPONSE_STORENOTAVAILABLE;
2529 case MTP_ERROR_INVALID_PARENT:
2530 resp = PTP_RESPONSE_INVALIDPARENT;
2532 case MTP_ERROR_INVALID_PARAM:
2533 resp = PTP_RESPONSE_INVALIDPARAM;
2535 case MTP_ERROR_STORE_FULL:
2536 resp = PTP_RESPONSE_STOREFULL;
2539 resp = PTP_RESPONSE_GEN_ERROR;
2542 _transport_set_mtp_operation_state(MTP_STATE_ONSERVICE);
2543 _cmd_hdlr_send_response_code(hdlr, resp);
2547 static void __copy_object(mtp_handler_t *hdlr)
2549 mtp_uint32 store_id = 0;
2550 mtp_uint32 h_obj = 0;
2551 mtp_uint32 h_parent = 0;
2552 mtp_uint32 new_handle = 0;
2553 mtp_uint16 resp = 0;
2555 h_obj = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
2556 store_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
2557 h_parent = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2);
2559 _transport_set_mtp_operation_state(MTP_STATE_DATA_PROCESSING);
2561 switch (_hutil_duplicate_object_entry(store_id, h_parent, h_obj,
2563 case MTP_ERROR_INVALID_OBJECTHANDLE:
2564 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
2566 case MTP_ERROR_OBJECT_WRITE_PROTECTED:
2567 resp = PTP_RESPONSE_OBJ_WRITEPROTECTED;
2569 case MTP_ERROR_STORE_NOT_AVAILABLE:
2570 resp = PTP_RESPONSE_STORENOTAVAILABLE;
2572 case MTP_ERROR_STORE_READ_ONLY:
2573 resp = PTP_RESPONSE_STORE_READONLY;
2575 case MTP_ERROR_INVALID_PARENT:
2576 resp = PTP_RESPONSE_INVALIDPARENT;
2578 case MTP_ERROR_INVALID_PARAM:
2579 resp = PTP_RESPONSE_INVALIDPARAM;
2581 case MTP_ERROR_STORE_FULL:
2582 resp = PTP_RESPONSE_STOREFULL;
2584 case MTP_ERROR_NONE:
2585 resp = PTP_RESPONSE_OK;
2587 case MTP_ERROR_ACCESS_DENIED:
2588 resp = PTP_RESPONSE_ACCESSDENIED;
2591 resp = PTP_RESPONSE_GEN_ERROR;
2593 _transport_set_mtp_operation_state(MTP_STATE_ONSERVICE);
2595 if (resp == PTP_RESPONSE_OK)
2596 _cmd_hdlr_send_response(hdlr, resp, 1, &new_handle);
2598 _cmd_hdlr_send_response_code(hdlr, resp);
2603 static void __reset_device_prop_value(mtp_handler_t *hdlr)
2605 mtp_uint32 prop_id = 0;
2606 device_prop_desc_t *prop = NULL;
2607 mtp_char temp[MTP_MAX_REG_STRING * 3 + 1] = { 0 };
2609 prop_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
2611 if (MTP_ERROR_NONE != _hutil_reset_device_entry(prop_id)) {
2612 _cmd_hdlr_send_response_code(hdlr,
2613 PTP_RESPONSE_PROP_NOTSUPPORTED);
2617 if (MTP_PROPERTYCODE_DEVICEFRIENDLYNAME == prop_id) {
2618 prop = _device_get_device_property(prop_id);
2620 _cmd_hdlr_send_response_code(hdlr,
2621 PTP_RESPONSE_PROP_NOTSUPPORTED);
2625 _util_utf16_to_utf8(temp, sizeof(temp),
2626 prop->current_val.str->str);
2627 _device_set_device_name(temp);
2629 } else if (MTP_PROPERTYCODE_SYNCHRONIZATIONPARTNER == prop_id) {
2630 prop = _device_get_device_property(prop_id);
2632 _cmd_hdlr_send_response_code(hdlr,
2633 PTP_RESPONSE_PROP_NOTSUPPORTED);
2637 _util_utf16_to_utf8(temp, sizeof(temp),
2638 prop->current_val.str->str);
2639 _device_set_sync_partner(temp);
2641 if (!g_strcmp0(temp, MTP_DEV_PROPERTY_NULL_SYNCPARTNER))
2642 vconf_set_str(VCONFKEY_MTP_SYNC_PARTNER_STR, "");
2644 vconf_set_str(VCONFKEY_MTP_SYNC_PARTNER_STR, temp);
2646 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
2651 /* Vendor-specific operations */
2652 #define GET_DEVICEPC_NAME 1
2653 static void __vendor_command1(mtp_handler_t *hdlr)
2655 switch (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0)) {
2656 case GET_DEVICEPC_NAME:
2661 /* Vendor command not properly handled*/
2662 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
2666 static void __get_interdep_prop_desc(mtp_handler_t *hdlr)
2669 data_blk_t blk = { 0 };
2670 mtp_uint32 num_bytes = 0;
2671 mtp_uchar *ptr = NULL;
2673 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
2674 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
2675 _cmd_hdlr_send_response_code(hdlr,
2676 PTP_RESPONSE_PARAM_NOTSUPPORTED);
2680 fmt = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
2681 if (0x0 == fmt || 0xFFFFFFFF == fmt) {
2682 ERR("Invalid format code");
2683 _cmd_hdlr_send_response_code(hdlr,
2684 PTP_RESPONSE_INVALIDCODEFORMAT);
2688 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
2689 _hutil_get_interdep_prop_config_list_size(&num_bytes, fmt);
2690 ptr = _hdlr_alloc_buf_data_container(&blk, num_bytes, num_bytes);
2692 if (MTP_ERROR_NONE != _hutil_get_interdep_prop_config_list_data(ptr,
2694 ERR("_hutil_get_interdep_prop_config_list_data() Fail");
2695 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
2700 _device_set_phase(DEVICE_PHASE_DATAIN);
2701 if (_hdlr_send_data_container(&blk)) {
2702 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
2704 /*Host Cancelled data-in transfer*/
2705 _device_set_phase(DEVICE_PHASE_NOTREADY);
2713 * void __cmd_hdlr_send_object_prop_list(mtp_handler_t *hdlr)
2714 * This function is used as an alternative first operation when the initiator
2715 * wants to send an object to the responder. This operation sends a
2716 * modified ObjectPropList dataset from the initiator to the Responder.
2720 static void __send_object_prop_list(mtp_handler_t *hdlr)
2723 mtp_uint16 resp = PTP_RESPONSE_OK;
2724 mtp_uint32 resp_param[MAX_MTP_PARAMS] = { 0 };
2725 mtp_obj_t *obj = NULL;
2727 mtp_uint64 f_size = 0;
2728 mtp_uint64 fsize_hbits = 0;
2729 mtp_uint32 store_id;
2730 mtp_uint32 h_parent;
2731 data_blk_t blk = { 0 };
2732 mtp_uint32 max_bytes = 0;
2734 obj_data_t objdata = { 0 };
2736 store_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
2737 h_parent = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
2738 fmt = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2);
2739 fsize_hbits = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 3);
2741 f_size = (fsize_hbits << 32) + _hdlr_get_param_cmd_container
2742 (&(hdlr->usb_cmd), 4);
2744 _device_set_phase(DEVICE_PHASE_DATAOUT);
2745 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
2747 max_bytes = MTP_MAX_METADATA;
2748 if (FALSE == _hdlr_rcv_data_container(&blk, max_bytes)) {
2749 _device_set_phase(DEVICE_PHASE_IDLE);
2750 ERR("_hdlr_rcv_data_container() Fail");
2751 resp = PTP_RESPONSE_GEN_ERROR;
2757 h_parent = _device_get_default_parent_handle();
2758 else if (h_parent == 0xFFFFFFFF)
2759 h_parent = PTP_OBJECTHANDLE_ROOT;
2761 store_id = _device_get_default_store_id();
2763 resp = PTP_RESPONSE_STORENOTAVAILABLE;
2765 /* If the second parameter is used, the first must
2768 resp = PTP_RESPONSE_PARAM_NOTSUPPORTED;
2770 h_parent = _device_get_default_parent_handle();
2773 if (f_size >= MTP_FILESIZE_4GB) {
2775 mtp_store_t *store = NULL;
2776 struct statfs buf = { 0 };
2779 store = _device_get_store(store_id);
2780 if (store == NULL) {
2781 ERR("Store Not Available");
2782 resp = PTP_RESPONSE_STORENOTAVAILABLE;
2784 DBG("StorePath = [%s]\n", store->root_path);
2785 ret = statfs(store->root_path, &buf);
2786 if (ret < 0 || buf.f_type == MSDOS_SUPER_MAGIC) {
2787 ERR("File System does not support files over 4gb");
2788 resp = MTP_RESPONSE_OBJECT_TOO_LARGE;
2793 if (PTP_RESPONSE_OK == resp) {
2795 mtp_uchar *data = NULL;
2797 if (TRUE == hdlr->data4_send_obj.is_valid) {
2799 objdata.store_id = hdlr->data4_send_obj.store_id;
2800 objdata.obj_size = hdlr->data4_send_obj.file_size;
2801 objdata.obj = hdlr->data4_send_obj.obj;
2802 hdlr->data4_send_obj.obj = NULL;
2805 data = _hdlr_get_payload_data(&blk);
2811 ret = _hutil_construct_object_entry_prop_list(store_id, h_parent,
2812 fmt, f_size, ((hdlr->data4_send_obj.is_valid == TRUE) ?
2813 (&objdata) : (NULL)), &obj, data,
2814 _hdlr_get_payload_size(&blk), &idx);
2815 hdlr->data4_send_obj.is_valid = FALSE;
2818 case MTP_ERROR_INVALID_STORE:
2819 resp = PTP_RESPONSE_INVALID_STORE_ID;
2821 case MTP_ERROR_STORE_READ_ONLY:
2822 resp = PTP_RESPONSE_STORE_READONLY;
2824 case MTP_ERROR_STORE_FULL:
2825 resp = PTP_RESPONSE_STOREFULL;
2827 case MTP_ERROR_GENERAL:
2828 resp = PTP_RESPONSE_GEN_ERROR;
2830 case MTP_ERROR_INVALID_DATASET:
2831 resp = MTP_RESPONSECODE_INVALIDDATASET;
2833 case MTP_ERROR_INVALID_OBJECTHANDLE:
2834 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
2836 case MTP_ERROR_INVALID_OBJ_PROP_CODE:
2837 resp = MTP_RESPONSE_INVALIDOBJPROPCODE;
2839 case MTP_ERROR_INVALID_OBJECT_PROP_FORMAT:
2840 resp = MTP_RESPONSE_INVALIDOBJPROPFORMAT;
2842 case MTP_ERROR_INVALID_OBJ_PROP_VALUE:
2843 resp = MTP_RESPONSE_INVALIDOBJPROPVALUE;
2845 case MTP_ERROR_INVALID_PARENT:
2846 resp = PTP_RESPONSE_INVALIDPARENT;
2848 case MTP_ERROR_ACCESS_DENIED:
2849 resp = PTP_RESPONSE_ACCESSDENIED;
2851 case MTP_ERROR_NONE:
2852 #ifdef MTP_USE_SELFMAKE_ABSTRACTION
2853 if ((obj->obj_info->obj_fmt == PTP_FMT_ASSOCIATION) ||
2854 (obj->obj_info->file_size == 0 &&
2855 obj->obj_info->obj_fmt >
2856 MTP_FMT_UNDEFINED_COLLECTION &&
2857 obj->obj_info->obj_fmt <
2858 MTP_FMT_UNDEFINED_DOC))
2859 #else /*MTP_USE_SELFMAKE_ABSTRACTION*/
2860 if (obj->obj_info->obj_fmt == PTP_FMT_ASSOCIATION)
2861 #endif /*MTP_USE_SELFMAKE_ABSTRACTION*/
2863 hdlr->data4_send_obj.obj = NULL;
2864 hdlr->data4_send_obj.is_valid = FALSE;
2865 hdlr->data4_send_obj.obj_handle = obj->obj_handle;
2866 hdlr->data4_send_obj.h_parent = h_parent;
2867 hdlr->data4_send_obj.store_id = store_id;
2868 hdlr->data4_send_obj.file_size = 0;
2870 hdlr->data4_send_obj.is_valid = TRUE;
2871 hdlr->data4_send_obj.obj_handle = obj->obj_handle;
2872 hdlr->data4_send_obj.h_parent = h_parent;
2873 hdlr->data4_send_obj.store_id = store_id;
2874 hdlr->data4_send_obj.obj = obj;
2875 hdlr->data4_send_obj.file_size =
2876 obj->obj_info->file_size;
2878 resp = PTP_RESPONSE_OK;
2881 resp = PTP_RESPONSE_GEN_ERROR;
2885 if (PTP_RESPONSE_OK != resp) {
2886 if (hdlr->data4_send_obj.obj)
2887 _entity_dealloc_mtp_obj(hdlr->data4_send_obj.obj);
2889 hdlr->data4_send_obj.obj = NULL;
2890 hdlr->data4_send_obj.is_valid = FALSE;
2891 resp_param[3] = idx;
2893 resp_param[0] = hdlr->data4_send_obj.store_id;
2895 /* PTP spec here requires that 0xFFFFFFFF be sent if root is the parent,
2896 * while in some situations (e.g. Move Object, Copy Object), 0x00000000
2897 *(as PTP_OBJECTHANDLE_ROOT is defined) represents the root
2899 resp_param[1] = (hdlr->data4_send_obj.h_parent !=
2900 PTP_OBJECTHANDLE_ROOT) ? hdlr->data4_send_obj.h_parent
2902 resp_param[2] = hdlr->data4_send_obj.obj_handle;
2906 _cmd_hdlr_send_response(hdlr, resp, 4, resp_param);
2913 void __close_session(mtp_handler_t *hdlr)
2915 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0) ||
2916 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
2917 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
2919 ERR("PTP_RESPONSE_PARAM_NOTSUPPORTED");
2920 _cmd_hdlr_send_response_code(hdlr,
2921 PTP_RESPONSE_PARAM_NOTSUPPORTED);
2926 if (hdlr->session_id) {
2927 hdlr->session_id = 0;
2928 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
2930 _cmd_hdlr_send_response_code(hdlr,
2931 PTP_RESPONSE_SESSIONNOTOPEN);
2932 ERR("PTP_RESPONSE_SESSIONNOTOPEN");
2937 mtp_bool _cmd_hdlr_send_response(mtp_handler_t *hdlr, mtp_uint16 resp,
2938 mtp_uint32 num_param, mtp_uint32 *params)
2940 mtp_bool ret = FALSE;
2941 resp_blk_t blk = { 0 };
2943 _hdlr_resp_container_init(&blk, resp, hdlr->usb_cmd.tid);
2945 ret = _hdlr_add_param_resp_container(&blk, num_param, params);
2947 _device_set_phase(DEVICE_PHASE_RESPONSE);
2948 ret = _hdlr_send_resp_container(&blk);
2949 _device_set_phase(DEVICE_PHASE_IDLE);
2951 if ((resp == PTP_RESPONSE_OK) && (ret == TRUE)) {
2952 DBG("[%s], Opcode[0x%4x], ResponseCode[0x%4x], NumParams[%d]\n",
2953 "SUCCESS", hdlr->usb_cmd.code, resp, num_param);
2955 ERR("[%s], Opcode = [0x%4x] ResponseCode[0x%4x], NumParams[%u]\n",
2956 "FAIL", hdlr->usb_cmd.code, resp, num_param);
2961 mtp_bool _cmd_hdlr_send_response_code(mtp_handler_t *hdlr, mtp_uint16 resp)
2963 return _cmd_hdlr_send_response(hdlr, resp, 0, NULL);
2966 #ifdef MTP_SUPPORT_PRINT_COMMAND
2967 static void __print_command(mtp_uint16 code)
2970 case PTP_OPCODE_GETDEVICEINFO:
2971 DBG("COMMAND ======== GET DEVICE INFO===========");
2973 case PTP_OPCODE_OPENSESSION:
2974 DBG("COMMAND ======== OPEN SESSION ===========");
2976 case PTP_OPCODE_CLOSESESSION:
2977 DBG("COMMAND ======== CLOSE SESSION ===========");
2979 case PTP_OPCODE_GETSTORAGEIDS:
2980 DBG("COMMAND ======== GET STORAGE IDS ===========");
2982 case PTP_OPCODE_GETSTORAGEINFO:
2983 DBG("COMMAND ======== GET STORAGE INFO ===========");
2985 case PTP_OPCODE_GETNUMOBJECTS:
2986 DBG("COMMAND ======== GET NUM OBJECTS ===========");
2988 case PTP_OPCODE_GETOBJECTHANDLES:
2989 DBG("COMMAND ======== GET OBJECT HANDLES ===========");
2991 case PTP_OPCODE_GETOBJECTINFO:
2992 DBG("COMMAND ======== GET OBJECT INFO ===========");
2994 case PTP_OPCODE_GETOBJECT:
2995 DBG("COMMAND ======== GET OBJECT ===========");
2997 case PTP_OPCODE_DELETEOBJECT:
2998 DBG("COMMAND ======== DELETE OBJECT ===========");
3000 case PTP_OPCODE_SENDOBJECTINFO:
3001 DBG("COMMAND ======== SEND OBJECT INFO ===========");
3003 case PTP_OPCODE_SENDOBJECT:
3004 DBG("COMMAND ======== SEND OBJECT ===========");
3006 case PTP_OPCODE_INITIATECAPTURE:
3007 DBG("COMMAND ======== INITIATE CAPTURE ===========");
3009 case PTP_OPCODE_FORMATSTORE:
3010 DBG("COMMAND ======== FORMAT STORE ===========");
3012 case PTP_OPCODE_RESETDEVICE:
3013 DBG("COMMAND ======== RESET DEVICE ===========");
3015 case PTP_OPCODE_SELFTEST:
3016 DBG("COMMAND ======== SELF TEST ===========");
3018 case PTP_OPCODE_SETOBJECTPROTECTION:
3019 DBG("COMMAND ======== SET OBJECT PROTECTION ===========");
3021 case PTP_OPCODE_POWERDOWN:
3022 DBG("COMMAND ======== POWER DOWN ===========");
3024 case PTP_OPCODE_GETDEVICEPROPDESC:
3025 DBG("COMMAND ======== GET DEVICE PROP DESC ===========");
3027 case PTP_OPCODE_GETDEVICEPROPVALUE:
3028 DBG("COMMAND ======== GET DEVICE PROP VALUE ===========");
3030 case PTP_OPCODE_SETDEVICEPROPVALUE:
3031 DBG("COMMAND ======== SET DEVICE PROP VALUE ===========");
3033 case PTP_OPCODE_RESETDEVICEPROPVALUE:
3034 DBG("COMMAND ======== RESET DEVICE PROP VALUE ===========");
3036 case PTP_OPCODE_TERMINATECAPTURE:
3037 DBG("COMMAND ======== TERMINATE CAPTURE ===========");
3039 case PTP_OPCODE_MOVEOBJECT:
3040 DBG("COMMAND ======== MOVE OBJECT ===========");
3042 case PTP_OPCODE_COPYOBJECT:
3043 DBG("COMMAND ======== COPY OBJECT ===========");
3045 case PTP_OPCODE_GETPARTIALOBJECT:
3046 DBG("COMMAND ======== GET PARTIAL OBJECT ===========");
3048 case PTP_OPCODE_INITIATEOPENCAPTURE:
3049 DBG("COMMAND ======== INITIATE OPEN CAPTURE ===========");
3051 case MTP_OPCODE_WMP_UNDEFINED:
3052 DBG("COMMAND ======== WMP UNDEFINED ==========");
3054 case MTP_OPCODE_WMP_REPORTACQUIREDCONTENT:
3055 DBG("COMMAND ======= REPORT ACQUIRED CONTENT =========");
3057 case MTP_OPCODE_GETOBJECTPROPSUPPORTED:
3058 DBG("COMMAND ======= GET OBJECT PROP SUPPORTED ========");
3060 case MTP_OPCODE_GETOBJECTPROPDESC:
3061 DBG("COMMAND ======== GET OBJECT PROP DESC ==========");
3063 case MTP_OPCODE_GETOBJECTPROPVALUE:
3064 DBG("COMMAND ======== GET OBJECT PROP VALUE ==========");
3066 case MTP_OPCODE_SETOBJECTPROPVALUE:
3067 DBG("COMMAND ======== SET OBJECT PROP VALUE ==========");
3069 case MTP_OPCODE_GETOBJECTPROPLIST:
3070 DBG("COMMAND ======== GET OBJECT PROP LIST ==========");
3072 case MTP_OPCODE_SETOBJECTPROPLIST:
3073 DBG("COMMAND ======== SET OBJECT PROP LIST ==========");
3075 case MTP_OPCODE_GETINTERDEPPROPDESC:
3076 DBG("COMMAND ======== GET INTERDEP PROP DESC ==========");
3078 case MTP_OPCODE_SENDOBJECTPROPLIST:
3079 DBG("COMMAND ======== SEND OBJECT PROP LIST ==========");
3081 case MTP_OPCODE_GETOBJECTREFERENCES:
3082 DBG("COMMAND ======== GET OBJECT REFERENCES ==========");
3084 case MTP_OPCODE_SETOBJECTREFERENCES:
3085 DBG("COMMAND ======== SET OBJECT REFERENCES ==========");
3087 case MTP_OPCODE_PLAYBACK_SKIP:
3088 DBG("COMMAND ======== PLAYBACK SKIP ==========");
3091 DBG("======== UNKNOWN COMMAND ==========");
3097 #endif /*MTP_SUPPORT_PRINT_COMMAND*/
3099 static void __enum_store_not_enumerated(mtp_uint32 obj_handle,
3100 mtp_uint32 fmt, mtp_uint32 depth)
3103 mtp_store_t *store = NULL;
3104 mtp_obj_t *obj = NULL;
3106 if (TRUE == g_is_full_enum) {
3107 DBG("Full Enumeration has been already done");
3111 DBG("obj_handle = [%u], format =[ %u], depth = [%u]\n", obj_handle,
3113 if (obj_handle == PTP_OBJECTHANDLE_ALL || obj_handle == PTP_OBJECTHANDLE_ROOT) {
3114 for (ii = 0; ii < _device_get_num_stores(); ii++) {
3115 store = _device_get_store_at_index(ii);
3116 if (store && store->obj_list.nnodes == 0)
3117 _entity_store_recursive_enum_folder_objects(store, NULL);
3119 g_is_full_enum = TRUE;
3120 } else if (obj_handle != PTP_OBJECTHANDLE_ROOT) {
3121 store = _device_get_store_containing_obj(obj_handle);
3122 obj = _entity_get_object_from_store(store, obj_handle);
3124 ERR("pObject is NULL");
3127 _entity_store_recursive_enum_folder_objects(store, obj);
3132 void _receive_mq_data_cb(mtp_char *buffer, mtp_int32 buf_len)
3134 cmd_blk_t cmd = { 0 };
3135 mtp_uint32 rx_size = _get_rx_pkt_size();
3137 if (_transport_get_mtp_operation_state() < MTP_STATE_READY_SERVICE) {
3138 ERR("MTP is stopped or initializing. ignore all");
3142 #ifdef MTP_SUPPORT_CONTROL_REQUEST
3143 /* process control request */
3144 switch (_transport_get_control_event()) {
3145 case PTP_EVENTCODE_CANCELTRANSACTION:
3146 DBG("PTP_EVENTCODE_CANCELTRANSACTION, just change state to IDLE");
3147 _transport_set_control_event(PTP_EVENTCODE_CANCELTRANSACTION);
3148 _device_set_phase(DEVICE_PHASE_IDLE);
3149 if ((buf_len == rx_size) ||
3150 (buf_len < sizeof(header_container_t))) {
3151 DBG("Cancelling Transaction. data length [%d]\n",
3153 _transport_set_control_event(PTP_EVENTCODE_CANCELTRANSACTION);
3158 cmd_container_t *tmp;
3164 for (i = 0; i < MAX_MTP_PARAMS; i++) { /* check size */
3165 /* check number of parameter */
3166 tmp = (cmd_container_t *)&buffer[buf_len -
3167 sizeof(header_container_t) -
3168 sizeof(mtp_dword) * i];
3173 if ((len == sizeof(header_container_t)
3174 + sizeof(mtp_dword) * i) &&
3175 (type == CONTAINER_CMD_BLK)) {
3176 DBG("Found Command in remaining data");
3177 memcpy(buffer, tmp, len);
3181 DBG("Not found command, length[%lu]\n", len);
3189 DBG("len[%ld], type[0x%x], code [0x%x], trid[0x%x]\n",
3190 len, type, code, trid);
3192 if (_hdlr_validate_cmd_container((mtp_byte *)tmp, len)
3194 ERR("Cancelling Transaction, invalid header, but last packet");
3195 } else { /*another command, cancelling is finished*/
3196 DBG("Cancelling Transaction, Finished.");
3199 _transport_set_control_event(0);
3200 _transport_set_mtp_operation_state(MTP_STATE_ONSERVICE);
3201 if (g_mgr->ftemp_st.fhandle != NULL) {
3202 DBG("In Cancel Transaction fclose ");
3203 _util_file_close(g_mgr->ftemp_st.fhandle);
3204 g_mgr->ftemp_st.fhandle = NULL;
3205 DBG("In Cancel Transaction, remove ");
3206 if (remove(g_mgr->ftemp_st.filepath) < 0)
3207 ERR_SECURE("remove(%s) Fail", g_mgr->ftemp_st.filepath);
3209 DBG("g_mgr->ftemp_st.fhandle is not valid, return");
3213 case PTP_EVENTCODE_DEVICERESET:
3214 DBG("Implement later, PTP_EVENTCODE_DEVICERESET");
3215 _device_set_phase(DEVICE_PHASE_IDLE);
3216 /* do close session, just skip save reference
3217 * mtp_save_object_references_mtp_device(MtpHandler.pDevice);
3219 g_mgr->hdlr.session_id = 0;
3220 _transport_set_control_event(0);
3221 _transport_set_mtp_operation_state(MTP_STATE_ONSERVICE);
3227 #endif/* MTP_SUPPORT_CONTROL_REQUEST */
3229 /* main processing */
3230 if (_device_get_phase() == DEVICE_PHASE_IDLE) {
3231 if (_hdlr_validate_cmd_container((mtp_uchar *)buffer, buf_len)
3233 _device_set_phase(DEVICE_PHASE_NOTREADY);
3234 ERR("MTP device phase NOT READY, invalid Command block");
3238 _transport_save_cmd_buffer(buffer, buf_len);
3239 _hdlr_copy_cmd_container_unknown_params((cmd_container_t *)buffer,
3241 #ifdef __BIG_ENDIAN__
3242 _hdlr_conv_cmd_container_byte_order(&cmd);
3243 #endif /* __BIG_ENDIAN__ */
3245 UTIL_LOCK_MUTEX(&g_cmd_inoti_mutex);
3246 __process_commands(&g_mtp_mgr.hdlr, &cmd);
3247 UTIL_UNLOCK_MUTEX(&g_cmd_inoti_mutex);
3248 } else if (_device_get_phase() == DEVICE_PHASE_DATAOUT) {
3249 if (g_mgr->ftemp_st.data_count == 0)
3250 __receive_temp_file_first_packet(buffer, buf_len);
3252 __receive_temp_file_next_packets(buffer, buf_len);
3255 /* ignore other case */
3256 ERR("MTP device phase[%d], unknown device PHASE\n",
3257 _device_get_phase());
3258 ERR("PhaseUnknown-> pData[0x%x], length=[%d]", buffer, buf_len);
3259 _device_set_phase(DEVICE_PHASE_IDLE);
3260 _transport_set_mtp_operation_state(MTP_STATE_ONSERVICE);
3265 static mtp_bool __receive_temp_file_first_packet(mtp_char *data,
3268 mtp_char *filepath = g_mgr->ftemp_st.filepath;
3269 mtp_int32 error = 0;
3270 mtp_uint32 *data_sz = &g_mgr->ftemp_st.data_size;
3271 mtp_char *buffer = g_mgr->ftemp_st.temp_buff;
3273 _transport_set_mtp_operation_state(MTP_STATE_DATA_TRANSFER_DL);
3274 if (access(filepath, F_OK) == 0) {
3275 if (g_mgr->ftemp_st.fhandle != NULL) {
3276 _util_file_close(g_mgr->ftemp_st.fhandle);
3277 g_mgr->ftemp_st.fhandle = NULL; /* initialize */
3280 if (remove(filepath) < 0) {
3281 ERR_SECURE("remove(%s) Fail", filepath);
3282 __finish_receiving_file_packets(data, data_len);
3287 g_mgr->ftemp_st.fhandle = _util_file_open(filepath, MTP_FILE_WRITE, &error);
3288 if (g_mgr->ftemp_st.fhandle == NULL) {
3289 ERR("First file handle is invalid!!");
3290 __finish_receiving_file_packets(data, data_len);
3293 /* consider header size */
3294 memcpy(&g_mgr->ftemp_st.header_buf, data, sizeof(header_container_t));
3296 g_mgr->ftemp_st.file_size = ((header_container_t *)data)->len -
3297 sizeof(header_container_t);
3298 *data_sz = data_len - sizeof(header_container_t);
3300 /* check whether last data packet */
3301 if (*data_sz == g_mgr->ftemp_st.file_size) {
3302 if (_util_file_write(g_mgr->ftemp_st.fhandle, &data[sizeof(header_container_t)],
3303 data_len - sizeof(header_container_t)) !=
3304 data_len - sizeof(header_container_t)) {
3305 ERR("fwrite error!");
3308 _util_file_close(g_mgr->ftemp_st.fhandle);
3309 g_mgr->ftemp_st.fhandle = NULL; /* initialize */
3310 __finish_receiving_file_packets(data, data_len);
3312 g_mgr->ftemp_st.data_count++;
3313 g_mgr->ftemp_st.size_remaining = *data_sz;
3315 memcpy(buffer, data + sizeof(header_container_t), *data_sz);
3320 static mtp_bool __receive_temp_file_next_packets(mtp_char *data,
3323 mtp_uint32 rx_size = _get_rx_pkt_size();
3324 mtp_uint32 *data_sz = &g_mgr->ftemp_st.data_size;
3325 mtp_char *buffer = g_mgr->ftemp_st.temp_buff;
3327 g_mgr->ftemp_st.data_count++;
3328 g_mgr->ftemp_st.size_remaining += data_len;
3330 if ((*data_sz + (mtp_uint32)data_len) > g_conf.write_file_size) {
3331 /* copy oversized packet to temp file */
3332 if (_util_file_write(g_mgr->ftemp_st.fhandle, buffer, *data_sz) != *data_sz)
3333 ERR("fwrite error writeSize=[%u]\n", *data_sz);
3338 memcpy(&buffer[*data_sz], data, data_len);
3339 *data_sz += data_len;
3341 /*Complete file is recieved, so close the file*/
3342 if (data_len < rx_size ||
3343 g_mgr->ftemp_st.size_remaining == g_mgr->ftemp_st.file_size) {
3345 if (_util_file_write(g_mgr->ftemp_st.fhandle, buffer, *data_sz) != *data_sz)
3346 ERR("fwrite error write size=[%u]\n", *data_sz);
3349 _util_file_close(g_mgr->ftemp_st.fhandle);
3350 g_mgr->ftemp_st.fhandle = NULL;
3351 __finish_receiving_file_packets(data, data_len);
3356 static void __finish_receiving_file_packets(mtp_char *data, mtp_int32 data_len)
3358 cmd_blk_t cmd = { 0 };
3359 mtp_uchar *cmd_buf = NULL;
3361 g_mgr->ftemp_st.data_count = 0;
3362 cmd_buf = (mtp_uchar *)data;
3364 if (!_hdlr_validate_cmd_container(cmd_buf, (mtp_uint32)data_len)) {
3365 cmd_buf = (mtp_uchar *)g_mgr->ftemp_st.cmd_buf;
3366 if (!_hdlr_validate_cmd_container(cmd_buf,
3367 g_mgr->ftemp_st.cmd_size)) {
3368 _device_set_phase(DEVICE_PHASE_IDLE);
3369 ERR("DATA PROCESS, device phase[%d], invalid Command\
3370 block\n", _device_get_phase());
3375 _transport_set_mtp_operation_state(MTP_STATE_ONSERVICE);
3376 _hdlr_copy_cmd_container_unknown_params((cmd_container_t *)cmd_buf,
3379 #ifdef __BIG_ENDIAN__
3380 _hdlr_conv_cmd_container_byte_order(&cmd);
3381 #endif /* __BIG_ENDIAN__ */
3383 UTIL_LOCK_MUTEX(&g_cmd_inoti_mutex);
3384 __process_commands(&g_mtp_mgr.hdlr, &cmd);
3385 UTIL_UNLOCK_MUTEX(&g_cmd_inoti_mutex);
3387 DBG("MTP device phase[%d], processing Command is complete\n",
3388 _device_get_phase());