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_util_support.h"
28 #include "ptp_datacodes.h"
29 #include "mtp_util_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_util_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;
45 mtp_bool g_is_send_object = FALSE;
50 static mtp_mgr_t *g_mgr = &g_mtp_mgr;
51 static mtp_bool g_has_round_trip = FALSE;
52 #ifdef MTP_USE_SKIP_CONTINUOUS_OPENSESSION
53 static mtp_uint16 g_count_open_session = 0;
54 static mtp_uint32 g_old_open_session_time = 0;
55 #endif/*MTP_USE_SKIP_CONTINUOUS_OPENSESSION*/
62 static void __process_commands(mtp_handler_t *hdlr, cmd_blk_t *cmd);
63 static void __open_session(mtp_handler_t *hdlr);
64 static void __get_device_info(mtp_handler_t *hdlr);
65 static void __get_storage_ids(mtp_handler_t *hdlr);
66 static void __get_storage_info(mtp_handler_t *hdlr);
67 static void __get_num_objects(mtp_handler_t *hdlr);
68 static void __get_object_handles(mtp_handler_t *hdlr);
69 static void __get_object_info(mtp_handler_t *hdlr);
70 static void __get_object(mtp_handler_t *hdlr);
71 static void __send_object_info(mtp_handler_t *hdlr);
72 static void __send_object(mtp_handler_t *hdlr);
73 static void __delete_object(mtp_handler_t *hdlr);
74 static void __format_store(mtp_handler_t *hdlr);
75 static void __reset_device(mtp_handler_t *hdlr);
76 static void __get_device_prop_desc(mtp_handler_t *hdlr);
77 static void __get_device_prop_value(mtp_handler_t *hdlr);
78 static void __set_device_prop_value(mtp_handler_t *hdlr);
79 static void __get_partial_object(mtp_handler_t *hdlr);
80 static void __get_object_references(mtp_handler_t *hdlr);
81 static void __set_object_references(mtp_handler_t *hdlr);
82 static void __get_object_prop_desc(mtp_handler_t *hdlr);
83 static void __get_object_prop_supported(mtp_handler_t *hdlr);
84 static void __get_object_prop_value(mtp_handler_t *hdlr);
85 static void __set_object_prop_value(mtp_handler_t *hdlr);
86 static void __get_object_prop_list(mtp_handler_t *hdlr);
87 static void __set_object_prop_list(mtp_handler_t *hdlr);
88 static void __report_acquired_content(mtp_handler_t *hdlr);
89 static void __send_playback_skip(mtp_handler_t *hdlr);
91 static void __self_test(mtp_handler_t *hdlr);
92 #ifdef MTP_SUPPORT_SET_PROTECTION
93 static void __set_object_protection(mtp_handler_t *hdlr);
94 #endif /* MTP_SUPPORT_SET_PROTECTION */
95 static void __power_down(mtp_handler_t *hdlr);
96 static void __move_object(mtp_handler_t *hdlr);
97 static void __copy_object(mtp_handler_t *hdlr);
98 static void __reset_device_prop_value(mtp_handler_t *hdlr);
99 static void __vendor_command1(mtp_handler_t *hdlr);
100 static void __get_interdep_prop_desc(mtp_handler_t *hdlr);
101 static void __send_object_prop_list(mtp_handler_t *hdlr);
103 static void __close_session(mtp_handler_t *hdlr);
104 #ifdef MTP_SUPPORT_PRINT_COMMAND
105 static void __print_command(mtp_uint16 code);
106 #endif /* MTP_SUPPORT_PRINT_COMMAND */
107 static void __enum_store_not_enumerated(mtp_uint32 obj_handle,
108 mtp_uint32 fmt, mtp_uint32 depth);
109 static mtp_bool __receive_temp_file_first_packet(mtp_char *data,
111 static mtp_bool __receive_temp_file_next_packets(mtp_char *data,
113 static void __finish_receiving_file_packets(mtp_char *data, mtp_int32 data_len);
118 void _cmd_hdlr_reset_cmd(mtp_handler_t *hdlr)
120 if (hdlr->data4_send_obj.obj != NULL)
121 _entity_dealloc_mtp_obj(hdlr->data4_send_obj.obj);
123 memset(hdlr, 0x00, sizeof(mtp_handler_t));
125 #ifdef MTP_USE_SKIP_CONTINUOUS_OPENSESSION
126 /* reset open session count */
127 g_count_open_session = 0;
128 g_old_open_session_time = 0;
129 #endif /* MTP_USE_SKIP_CONTINUOUS_OPENSESSION */
132 /* LCOV_EXCL_START */
133 static void __process_commands(mtp_handler_t *hdlr, cmd_blk_t *cmd)
135 mtp_store_t *store = NULL;
137 /* Keep a local copy for this command */
138 _hdlr_copy_cmd_container(cmd, &(hdlr->usb_cmd));
140 if (hdlr->usb_cmd.code == PTP_OPCODE_GETDEVICEINFO) {
141 DBG("COMMAND CODE = [0x%4x]!!\n", hdlr->usb_cmd.code);
142 #ifdef MTP_SUPPORT_PRINT_COMMAND
143 __print_command(hdlr->usb_cmd.code);
144 #endif /*MTP_SUPPORT_PRINT_COMMAND*/
145 __get_device_info(hdlr);
149 /* Process OpenSession Command */
150 if (hdlr->usb_cmd.code == PTP_OPCODE_OPENSESSION) {
151 DBG("COMMAND CODE = [0x%4X]!!\n", hdlr->usb_cmd.code);
152 #ifdef MTP_SUPPORT_PRINT_COMMAND
153 __print_command(hdlr->usb_cmd.code);
154 #endif /*MTP_SUPPORT_PRINT_COMMAND*/
155 #ifdef MTP_USE_SKIP_CONTINUOUS_OPENSESSION
157 mtp_uint32 cur_time = 0;
159 cur_time = (mtp_uint32)t;
160 /*first opensession*/
161 if (g_count_open_session == 0) {
162 g_old_open_session_time = cur_time;
163 } else if (cur_time <= g_old_open_session_time + 1) {
164 /*under 1 sec. it might be skipped*/
165 ERR("skip continuous OPEN session");
168 ++g_count_open_session;
170 #endif /* MTP_USE_SKIP_CONTINUOUS_OPENSESSION */
171 __open_session(hdlr);
174 #ifdef MTP_USE_SKIP_CONTINUOUS_OPENSESSION
175 g_count_open_session = 0;
176 #endif /* MTP_USE_SKIP_CONTINUOUS_OPENSESSION */
178 /* Check if session is open or not, if not respond */
179 if (hdlr->session_id == 0) {
180 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_SESSIONNOTOPEN);
181 _device_set_phase(DEVICE_PHASE_IDLE);
184 DBG("COMMAND CODE = [0x%4x]!!\n", hdlr->usb_cmd.code);
185 #ifdef MTP_SUPPORT_PRINT_COMMAND
186 __print_command(hdlr->usb_cmd.code);
187 #endif /* MTP_SUPPORT_PRINT_COMMAND */
189 switch (hdlr->usb_cmd.code) {
190 case PTP_OPCODE_CLOSESESSION:
191 __close_session(hdlr);
193 case PTP_OPCODE_GETSTORAGEIDS:
194 __get_storage_ids(hdlr);
196 case PTP_OPCODE_GETSTORAGEINFO:
197 __get_storage_info(hdlr);
199 case PTP_OPCODE_GETNUMOBJECTS:
200 __get_num_objects(hdlr);
202 case PTP_OPCODE_GETOBJECTHANDLES:
203 __get_object_handles(hdlr);
205 case PTP_OPCODE_GETOBJECTINFO:
206 __get_object_info(hdlr);
208 case PTP_OPCODE_GETOBJECT:
209 _eh_send_event_req_to_eh_thread(EVENT_START_DATAIN, 0, 0, NULL);
211 _eh_send_event_req_to_eh_thread(EVENT_DONE_DATAIN, 0, 0, NULL);
213 case PTP_OPCODE_DELETEOBJECT:
214 __delete_object(hdlr);
216 case PTP_OPCODE_FORMATSTORE:
217 __format_store(hdlr);
219 case PTP_OPCODE_GETDEVICEPROPDESC:
220 __get_device_prop_desc(hdlr);
222 case PTP_OPCODE_GETDEVICEPROPVALUE:
223 __get_device_prop_value(hdlr);
225 case PTP_OPCODE_GETPARTIALOBJECT:
226 __get_partial_object(hdlr);
228 case MTP_OPCODE_GETOBJECTREFERENCES:
229 __get_object_references(hdlr);
231 case MTP_OPCODE_GETOBJECTPROPDESC:
232 __get_object_prop_desc(hdlr);
234 case MTP_OPCODE_GETOBJECTPROPSUPPORTED:
235 __get_object_prop_supported(hdlr);
237 case MTP_OPCODE_GETOBJECTPROPVALUE:
238 __get_object_prop_value(hdlr);
240 case MTP_OPCODE_GETOBJECTPROPLIST:
241 __get_object_prop_list(hdlr);
244 case PTP_OPCODE_RESETDEVICE:
245 __reset_device(hdlr);
247 case PTP_OPCODE_SELFTEST:
250 #ifdef MTP_SUPPORT_SET_PROTECTION
251 case PTP_OPCODE_SETOBJECTPROTECTION:
252 __set_object_protection(hdlr);
254 #endif /* MTP_SUPPORT_SET_PROTECTION */
255 case PTP_OPCODE_POWERDOWN:
258 case PTP_OPCODE_RESETDEVICEPROPVALUE:
259 __reset_device_prop_value(hdlr);
261 case PTP_OPCODE_MOVEOBJECT:
264 case PTP_OPCODE_COPYOBJECT:
267 case MTP_OPCODE_GETINTERDEPPROPDESC:
268 __get_interdep_prop_desc(hdlr);
270 case PTP_CODE_VENDOR_OP1: /* Vendor-specific operations */
271 __vendor_command1(hdlr);
274 case MTP_OPCODE_PLAYBACK_SKIP: /* Playback control */
275 __send_playback_skip(hdlr);
278 case MTP_OPCODE_WMP_REPORTACQUIREDCONTENT:
279 /* Windows Media 11 extension*/
280 __report_acquired_content(hdlr);
282 case PTP_OPCODE_SENDOBJECTINFO:
283 case PTP_OPCODE_SENDOBJECT:
284 case PTP_OPCODE_SETDEVICEPROPVALUE:
285 case MTP_OPCODE_SETOBJECTREFERENCES:
286 case MTP_OPCODE_SETOBJECTPROPVALUE:
287 case MTP_OPCODE_SETOBJECTPROPLIST:
289 case MTP_OPCODE_SENDOBJECTPROPLIST:
291 /* DATA_HANDLE_PHASE: Send operation will be blocked
292 * until data packet is received
294 if (_device_get_phase() == DEVICE_PHASE_IDLE) {
295 DBG("DATAOUT COMMAND PHASE!!");
296 if (hdlr->usb_cmd.code == PTP_OPCODE_SENDOBJECT) {
297 mtp_char parent_path[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
299 if (g_mgr->ftemp_st.filepath) {
300 _util_get_parent_path(g_mgr->ftemp_st.filepath, parent_path);
301 DBG("g_mgr->ftemp_st.filepath:[%s], parent_path[%s]\n", g_mgr->ftemp_st.filepath, parent_path);
303 if ((g_strcmp0(parent_path, "/tmp")) != 0)
304 g_is_send_object = TRUE;
307 _eh_send_event_req_to_eh_thread(EVENT_START_DATAOUT,
311 if (hdlr->usb_cmd.code == PTP_OPCODE_SENDOBJECT)
312 _eh_send_event_req_to_eh_thread(EVENT_START_DATAOUT,
314 _device_set_phase(DEVICE_PHASE_DATAOUT);
315 return; /* in command phase, just return and wait next data */
317 switch (hdlr->usb_cmd.code) {
318 case PTP_OPCODE_SENDOBJECTINFO:
319 __send_object_info(hdlr);
321 case PTP_OPCODE_SENDOBJECT:
323 g_is_send_object = FALSE;
325 _eh_send_event_req_to_eh_thread(EVENT_DONE_DATAOUT,
328 case PTP_OPCODE_SETDEVICEPROPVALUE:
329 __set_device_prop_value(hdlr);
331 case MTP_OPCODE_SETOBJECTREFERENCES:
332 __set_object_references(hdlr);
334 case MTP_OPCODE_SETOBJECTPROPVALUE:
335 __set_object_prop_value(hdlr);
337 case MTP_OPCODE_SETOBJECTPROPLIST:
338 __set_object_prop_list(hdlr);
341 case MTP_OPCODE_SENDOBJECTPROPLIST:
342 __send_object_prop_list(hdlr);
349 _cmd_hdlr_send_response_code(hdlr,
350 PTP_RESPONSE_OP_NOT_SUPPORTED);
351 DBG("Unsupported COMMAND[%d]\n", hdlr->usb_cmd.code);
355 if (((hdlr->last_opcode == PTP_OPCODE_SENDOBJECTINFO) ||
356 (hdlr->last_opcode == MTP_OPCODE_SENDOBJECTPROPLIST)) &&
357 ((hdlr->last_fmt_code != PTP_FMT_ASSOCIATION) &&
358 (hdlr->last_fmt_code != PTP_FMT_UNDEF))) {
359 DBG("Processed, last_opcode[0x%x], last_fmt_code[%d]\n",
360 hdlr->last_opcode, hdlr->last_fmt_code);
362 if ((hdlr->usb_cmd.code != PTP_OPCODE_SENDOBJECT) &&
363 hdlr->data4_send_obj.is_valid &&
364 hdlr->data4_send_obj.is_data_sent) {
366 DBG("Processed, COMMAND[0x%x]!!\n", hdlr->usb_cmd.code);
367 store = _device_get_store(hdlr->data4_send_obj.store_id);
369 /*Restore reserved space*/
370 store->store_info.free_space +=
371 hdlr->data4_send_obj.file_size;
374 if (hdlr->data4_send_obj.obj) {
375 _entity_dealloc_mtp_obj(hdlr->data4_send_obj.obj);
376 hdlr->data4_send_obj.obj = NULL;
378 memset(&(hdlr->data4_send_obj), 0x00,
379 sizeof(hdlr->data4_send_obj));
382 hdlr->last_opcode = hdlr->usb_cmd.code; /* Last operation code*/
385 static void __open_session(mtp_handler_t *hdlr)
387 mtp_uint32 session_id;
388 /*Check the parameters*/
389 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
390 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
391 /*Unknown parameters*/
392 _cmd_hdlr_send_response_code(hdlr,
393 PTP_RESPONSE_PARAM_NOTSUPPORTED);
396 /* Validate parameters*/
397 session_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
399 if (session_id == 0 || (hdlr->usb_cmd.tid != 0)) {
400 /*Session Id cannot be zero, while TransactionId must be zero.*/
401 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_INVALIDPARAM);
405 if (hdlr->session_id) { /*Session already open*/
406 _cmd_hdlr_send_response(hdlr,
407 PTP_RESPONSE_SESSIONALREADYOPENED, 1,
408 (mtp_uint32 *)&(hdlr->session_id));
409 } else { /*Save the Session ID*/
410 hdlr->session_id = session_id;
411 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
415 static void __get_device_info(mtp_handler_t *hdlr)
417 /* Check the parameters*/
418 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0) ||
419 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
420 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
421 /* Unknown parameters*/
422 _cmd_hdlr_send_response_code(hdlr,
423 PTP_RESPONSE_PARAM_NOTSUPPORTED);
427 /* When used outside a session, both the SessionID and TransactionID
428 * in the Operation Request dataset must be 0;
431 if ((hdlr->session_id == 0) &&
432 (hdlr->usb_cmd.tid != 0)) { /*INVALIDPARAMETER*/
433 _cmd_hdlr_send_response_code(hdlr,
434 PTP_RESPONSE_PARAM_NOTSUPPORTED);
435 ERR("Invalid Session ID[%u], Transaction ID[%u]\n",
436 hdlr->session_id, hdlr->usb_cmd.tid);
440 /*Build the data block for device info.*/
441 data_blk_t blk = { 0 };
442 mtp_uint32 num_bytes = 0;
443 mtp_uchar *buf_ptr = NULL;
445 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
446 num_bytes = _get_device_info_size();
447 buf_ptr = _hdlr_alloc_buf_data_container(&blk, num_bytes, num_bytes);
448 if (num_bytes == _pack_device_info(buf_ptr, num_bytes)) {
449 _device_set_phase(DEVICE_PHASE_DATAIN);
450 if (_hdlr_send_data_container(&blk)) {
451 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
453 /* Host Cancelled data-in transfer */
454 _device_set_phase(DEVICE_PHASE_NOTREADY);
455 DBG("Device phase is set to DEVICE_PHASE_NOTREADY");
458 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
464 static void __get_storage_ids(mtp_handler_t *hdlr)
466 data_blk_t blk = { 0 };
467 ptp_array_t ids = { 0 };
468 mtp_uint32 resp = PTP_RESPONSE_GEN_ERROR;
469 mtp_uint32 num_bytes = 0;
470 mtp_uchar *ptr = NULL;
472 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0) ||
473 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
474 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
476 _cmd_hdlr_send_response_code(hdlr,
477 PTP_RESPONSE_PARAM_NOTSUPPORTED);
481 _prop_init_ptparray(&ids, UINT32_TYPE);
483 if (_hutil_get_storage_ids(&ids) == MTP_ERROR_NONE) {
484 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code,
486 num_bytes = _prop_get_size_ptparray(&ids);
487 ptr = _hdlr_alloc_buf_data_container(&blk, num_bytes, num_bytes);
490 _prop_pack_ptparray(&ids, ptr, num_bytes);
491 _device_set_phase(DEVICE_PHASE_DATAIN);
492 /*Send the data block*/
493 if (FALSE == _hdlr_send_data_container(&blk)) {
494 /*Host Cancelled data-in transfer*/
495 _device_set_phase(DEVICE_PHASE_NOTREADY);
496 DBG("DEVICE_PHASE_NOTREADY!!");
498 resp = PTP_RESPONSE_OK;
503 _prop_deinit_ptparray(&ids);
504 _cmd_hdlr_send_response_code(hdlr, (mtp_uint16) resp);
507 static void __get_storage_info(mtp_handler_t *hdlr)
509 mtp_uint32 store_id = 0;
510 store_info_t store_info = { 0 };
511 mtp_uint32 pkt_sz = 0;
512 data_blk_t blk = { 0 };
513 mtp_uchar *ptr = NULL;
515 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
516 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
517 /*Unknown parameters*/
518 _cmd_hdlr_send_response_code(hdlr,
519 PTP_RESPONSE_PARAM_NOTSUPPORTED);
523 store_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
525 if (_hutil_get_storage_entry(store_id, &store_info) != MTP_ERROR_NONE) {
526 _cmd_hdlr_send_response_code(hdlr,
527 PTP_RESPONSE_INVALID_STORE_ID);
531 /* Build the data block for StorageInfo Dataset.*/
532 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
533 pkt_sz = _hutil_get_storage_info_size(&store_info);
534 ptr = _hdlr_alloc_buf_data_container(&blk, pkt_sz, pkt_sz);
536 if (pkt_sz == _entity_pack_store_info(&store_info, ptr, pkt_sz)) {
537 _device_set_phase(DEVICE_PHASE_DATAIN);
538 if (_hdlr_send_data_container(&blk)) {
539 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
541 /*Host Cancelled data-in transfer*/
542 _device_set_phase(DEVICE_PHASE_NOTREADY);
543 DBG("DEVICE_PHASE_NOTREADY!!");
546 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
552 static void __get_num_objects(mtp_handler_t *hdlr)
555 mtp_uint32 store_id = 0;
556 mtp_uint32 h_parent = 0;
558 mtp_uint32 num_obj = 0;
560 store_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
561 fmt = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
562 h_parent = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2);
564 switch (_hutil_get_num_objects(store_id, h_parent, fmt,
565 (mtp_uint32 *)(&num_obj))) {
566 case MTP_ERROR_INVALID_STORE:
567 resp = PTP_RESPONSE_INVALID_STORE_ID;
569 case MTP_ERROR_INVALID_OBJECTHANDLE:
570 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
572 case MTP_ERROR_INVALID_PARENT:
573 resp = PTP_RESPONSE_INVALIDPARENT;
575 case MTP_ERROR_STORE_NOT_AVAILABLE:
576 resp = PTP_RESPONSE_STORENOTAVAILABLE;
579 resp = PTP_RESPONSE_OK;
582 resp = PTP_RESPONSE_GEN_ERROR;
585 if (resp == PTP_RESPONSE_OK)
586 _cmd_hdlr_send_response(hdlr, resp, 1, (mtp_uint32 *)&num_obj);
588 _cmd_hdlr_send_response_code(hdlr, resp);
591 static void __get_object_handles(mtp_handler_t *hdlr)
593 mtp_uint32 store_id = 0;
595 mtp_uint32 h_parent = 0;
596 ptp_array_t handle_arr = { 0 };
597 data_blk_t blk = { 0 };
598 mtp_uint32 num_bytes = 0;
599 mtp_uchar *ptr = NULL;
602 _prop_init_ptparray(&handle_arr, UINT32_TYPE);
604 store_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
605 fmt = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
606 h_parent = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2);
608 DBG("store_id = [0x%x], Format Code = [0x%x], parent handle = [0x%x]\n",
609 store_id, fmt, h_parent);
610 switch (_hutil_get_object_handles(store_id, fmt, h_parent,
612 case MTP_ERROR_INVALID_STORE:
613 resp = PTP_RESPONSE_INVALID_STORE_ID;
615 case MTP_ERROR_INVALID_OBJECTHANDLE:
616 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
618 case MTP_ERROR_INVALID_PARENT:
619 resp = PTP_RESPONSE_INVALIDPARENT;
621 case MTP_ERROR_STORE_NOT_AVAILABLE:
622 resp = PTP_RESPONSE_STORENOTAVAILABLE;
625 resp = PTP_RESPONSE_OK;
628 resp = PTP_RESPONSE_GEN_ERROR;
631 if (resp != PTP_RESPONSE_OK) {
632 _prop_deinit_ptparray(&handle_arr);
633 _cmd_hdlr_send_response_code(hdlr, resp);
637 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
638 num_bytes = _prop_get_size_ptparray(&handle_arr);
639 ptr = _hdlr_alloc_buf_data_container(&blk, num_bytes, num_bytes);
641 _prop_pack_ptparray(&handle_arr, ptr, num_bytes);
642 _prop_deinit_ptparray(&handle_arr);
643 _device_set_phase(DEVICE_PHASE_DATAIN);
644 if (_hdlr_send_data_container(&blk)) {
645 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
647 /*Host Cancelled data-in transfer.*/
648 _device_set_phase(DEVICE_PHASE_NOTREADY);
649 DBG("DEVICE_PHASE_NOTREADY!!");
652 _prop_deinit_ptparray(&handle_arr);
653 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
659 static void __get_object_info(mtp_handler_t *hdlr)
661 mtp_uint32 obj_handle = 0;
662 data_blk_t blk = { 0 };
663 mtp_uint32 num_bytes = 0;
664 mtp_uchar *ptr = NULL;
665 mtp_obj_t *obj = NULL;
666 mtp_char f_name[MTP_MAX_FILENAME_SIZE + 1] = { 0 };
667 mtp_wchar wf_name[MTP_MAX_FILENAME_SIZE + 1] = { 0 };
668 ptp_string_t ptp_string = { 0 };
670 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
671 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
673 _cmd_hdlr_send_response_code(hdlr,
674 PTP_RESPONSE_PARAM_NOTSUPPORTED);
677 obj_handle = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
678 if (MTP_ERROR_NONE != _hutil_get_object_entry(obj_handle, &obj)) {
679 _cmd_hdlr_send_response_code(hdlr,
680 PTP_RESPONSE_INVALID_OBJ_HANDLE);
684 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
686 _util_get_file_name(obj->file_path, f_name);
687 _util_utf8_to_utf16(wf_name, sizeof(wf_name) / WCHAR_SIZ, f_name);
688 _prop_copy_char_to_ptpstring(&ptp_string, wf_name, WCHAR_TYPE);
690 num_bytes = _entity_get_object_info_size(obj, &ptp_string);
691 ptr = _hdlr_alloc_buf_data_container(&blk, num_bytes, num_bytes);
692 if (num_bytes == _entity_pack_obj_info(obj, &ptp_string, ptr,
694 _device_set_phase(DEVICE_PHASE_DATAIN);
695 if (_hdlr_send_data_container(&blk)) {
696 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
698 /* Host Cancelled data-in transfer*/
699 _device_set_phase(DEVICE_PHASE_NOTREADY);
700 DBG("DEVICE_PHASE_NOTREADY!!");
703 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
709 static void __get_object(mtp_handler_t *hdlr)
711 mtp_uint32 obj_handle;
716 mtp_uint64 num_bytes;
717 mtp_uint64 total_len;
719 mtp_uint16 resp = PTP_RESPONSE_OK;
720 mtp_uint32 packet_len;
721 mtp_uint32 read_len = 0;
725 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
726 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
727 _cmd_hdlr_send_response_code(hdlr,
728 PTP_RESPONSE_PARAM_NOTSUPPORTED);
732 obj_handle = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
733 obj = _device_get_object_with_handle(obj_handle);
735 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
736 _cmd_hdlr_send_response_code(hdlr, resp);
740 #ifdef MTP_SUPPORT_SET_PROTECTION
741 /* Check to see if the data is non-transferable */
742 if (obj->obj_info->protcn_status ==
743 MTP_PROTECTIONSTATUS_NONTRANSFERABLE_DATA) {
744 resp = PTP_RESPONSE_ACCESSDENIED;
745 _cmd_hdlr_send_response_code(hdlr, resp);
748 #endif /* MTP_SUPPORT_SET_PROTECTION */
750 path = obj->file_path;
751 num_bytes = obj->obj_info->file_size;
752 total_len = num_bytes + sizeof(header_container_t);
753 packet_len = total_len < g_conf.read_file_size ? num_bytes :
754 (g_conf.read_file_size - sizeof(header_container_t));
756 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
757 ptr = _hdlr_alloc_buf_data_container(&blk, packet_len, num_bytes);
759 ERR("_hdlr_alloc_buf_data_container() Fail");
760 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
765 _device_set_phase(DEVICE_PHASE_DATAIN);
766 h_file = _util_file_open(path, MTP_FILE_READ, &error);
767 if (h_file == NULL) {
768 ERR("_util_file_open() Fail");
769 _device_set_phase(DEVICE_PHASE_NOTREADY);
770 if (EACCES == error) {
771 _cmd_hdlr_send_response_code(hdlr,
772 PTP_RESPONSE_ACCESSDENIED);
776 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
781 _util_file_read(h_file, ptr, packet_len, &read_len);
783 ERR("_util_file_read() Fail");
784 ERR_SECURE("filename[%s]", path);
785 _device_set_phase(DEVICE_PHASE_NOTREADY);
786 resp = PTP_RESPONSE_INCOMPLETETRANSFER;
790 /* First Packet with Header */
791 if (PTP_EVENTCODE_CANCELTRANSACTION == _transport_get_control_event() ||
792 FALSE == _hdlr_send_bulk_data(blk.data, blk.len)) {
793 _device_set_phase(DEVICE_PHASE_NOTREADY);
794 resp = PTP_RESPONSE_INCOMPLETETRANSFER;
795 ERR("First Packet send Fail");
796 ERR_SECURE("filename[%s]\n", path);
800 sent = sizeof(header_container_t) + read_len;
803 while (sent < total_len) {
804 _util_file_read(h_file, ptr, g_conf.read_file_size, &read_len);
806 ERR("_util_file_read() Fail");
807 ERR_SECURE("filename[%s]\n", path);
808 _device_set_phase(DEVICE_PHASE_NOTREADY);
809 resp = PTP_RESPONSE_INCOMPLETETRANSFER;
813 if (PTP_EVENTCODE_CANCELTRANSACTION == _transport_get_control_event() ||
814 FALSE == _hdlr_send_bulk_data(ptr, read_len)) {
815 _device_set_phase(DEVICE_PHASE_NOTREADY);
816 resp = PTP_RESPONSE_INCOMPLETETRANSFER;
817 ERR("Packet send Fail");
818 ERR_SECURE("filename[%s]\n", path);
825 if (total_len % ((mtp_uint64)_transport_get_usb_packet_len()) == 0)
826 _transport_send_zlp();
829 _util_file_close(h_file);
832 _cmd_hdlr_send_response_code(hdlr, resp);
835 static void __send_object_info(mtp_handler_t *hdlr)
837 mtp_uint16 resp = PTP_RESPONSE_UNDEFINED;
838 mtp_uint32 store_id = 0;
839 mtp_uint32 h_parent = 0;
840 mtp_uint32 num_bytes = 0;
841 data_blk_t blk = { 0 };
842 mtp_uint32 resp_param[3] = { 0 };
843 mtp_obj_t *obj = NULL;
845 obj_data_t obdata = { 0 };
847 store_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
849 store_id = _device_get_default_store_id();
851 h_parent = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
853 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
854 resp = PTP_RESPONSE_PARAM_NOTSUPPORTED;
855 if (_device_get_phase() != DEVICE_PHASE_NOTREADY)
856 _cmd_hdlr_send_response_code(hdlr, resp);
861 _device_set_phase(DEVICE_PHASE_DATAOUT);
862 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
863 num_bytes = MAX_SIZE_IN_BYTES_OF_OBJECT_INFO;
864 if (_hdlr_rcv_data_container(&blk, num_bytes) == FALSE) {
865 _device_set_phase(DEVICE_PHASE_NOTREADY);
867 if (TRUE == hdlr->data4_send_obj.is_valid) {
868 obdata.store_id = hdlr->data4_send_obj.store_id;
869 obdata.obj_size = hdlr->data4_send_obj.file_size;
870 obdata.obj = hdlr->data4_send_obj.obj;
871 hdlr->data4_send_obj.obj = NULL;
873 ret = _hutil_construct_object_entry(store_id, h_parent,
874 ((hdlr->data4_send_obj.is_valid == TRUE) ? (&obdata)
875 : (NULL)), &obj, _hdlr_get_payload_data(&blk),
876 _hdlr_get_payload_size(&blk));
877 hdlr->data4_send_obj.is_valid = FALSE;
880 if (obj->obj_info->obj_fmt == PTP_FMT_ASSOCIATION) {
881 hdlr->data4_send_obj.obj = NULL;
882 hdlr->data4_send_obj.is_valid = FALSE;
883 hdlr->data4_send_obj.obj_handle = obj->obj_handle;
884 hdlr->data4_send_obj.h_parent = h_parent;
885 hdlr->data4_send_obj.store_id = store_id;
887 #ifdef MTP_USE_SELFMAKE_ABSTRACTION
888 else if (obj->obj_info->file_size == 0 &&
889 obj->obj_info->obj_fmt > MTP_FMT_UNDEFINED_COLLECTION &&
890 obj->obj_info->obj_fmt < MTP_FMT_UNDEFINED_DOC) {
891 hdlr->data4_send_obj.obj = NULL;
892 hdlr->data4_send_obj.is_valid = FALSE;
893 hdlr->data4_send_obj.obj_handle = obj->obj_handle;
894 hdlr->data4_send_obj.h_parent = h_parent;
895 hdlr->data4_send_obj.store_id = store_id;
897 #endif /*MTP_USE_SELFMAKE_ABSTRACTION*/
899 hdlr->data4_send_obj.is_valid = TRUE;
900 hdlr->data4_send_obj.obj_handle = obj->obj_handle;
901 hdlr->data4_send_obj.h_parent = h_parent;
902 hdlr->data4_send_obj.store_id = store_id;
903 hdlr->data4_send_obj.obj = obj;
904 hdlr->data4_send_obj.file_size =
905 obj->obj_info->file_size;
907 resp = PTP_RESPONSE_OK;
909 case MTP_ERROR_STORE_NOT_AVAILABLE:
910 resp = PTP_RESPONSE_STORENOTAVAILABLE;
911 DBG("PTP_RESPONSE_STORENOTAVAILABLE");
913 case MTP_ERROR_INVALID_PARAM:
914 resp = PTP_RESPONSE_PARAM_NOTSUPPORTED;
915 DBG("PTP_RESPONSE_PARAM_NOTSUPPORTED");
917 case MTP_ERROR_INVALID_STORE:
918 resp = PTP_RESPONSE_INVALID_STORE_ID;
919 DBG("PTP_RESPONSE_INVALID_STORE_ID");
921 case MTP_ERROR_STORE_READ_ONLY:
922 resp = PTP_RESPONSE_STORE_READONLY;
924 case MTP_ERROR_STORE_FULL:
925 resp = PTP_RESPONSE_STOREFULL;
926 DBG("PTP_RESPONSE_STOREFULL");
928 case MTP_ERROR_GENERAL:
929 resp = PTP_RESPONSE_GEN_ERROR;
930 DBG("PTP_RESPONSE_GEN_ERROR");
932 case MTP_ERROR_INVALID_OBJECT_INFO:
933 resp = MTP_RESPONSECODE_INVALIDDATASET;
934 DBG("MTP_RESPONSECODE_INVALIDDATASET");
936 case MTP_ERROR_INVALID_OBJECTHANDLE:
937 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
938 DBG("PTP_RESPONSE_INVALID_OBJ_HANDLE");
940 case MTP_ERROR_INVALID_PARENT:
941 resp = PTP_RESPONSE_INVALIDPARENT;
942 DBG("PTP_RESPONSE_INVALIDPARENT");
944 case MTP_ERROR_ACCESS_DENIED:
945 resp = PTP_RESPONSE_ACCESSDENIED;
946 DBG("PTP_RESPONSE_ACCESSDENIED");
949 resp = PTP_RESPONSE_GEN_ERROR;
950 DBG("PTP_RESPONSE_GEN_ERROR");
956 if (_device_get_phase() != DEVICE_PHASE_NOTREADY) {
957 if (resp == PTP_RESPONSE_OK) {
958 hdlr->last_fmt_code = obj->obj_info->obj_fmt;
959 resp_param[0] = hdlr->data4_send_obj.store_id;
961 /* PTP spec here requires that 0xFFFFFFFF be sent if root is the parent object,
962 * while in some situations(e.g. MoveObject, CopyObject), 0x00000000 (as
963 * PTP_OBJECTHANDLE_ROOT is defined) represents the root.
965 resp_param[1] = (hdlr->data4_send_obj.h_parent
966 != PTP_OBJECTHANDLE_ROOT) ?
967 hdlr->data4_send_obj.h_parent :
969 resp_param[2] = hdlr->data4_send_obj.obj_handle;
970 _cmd_hdlr_send_response(hdlr, resp, 3, resp_param);
972 _cmd_hdlr_send_response_code(hdlr, resp);
977 static void __send_object(mtp_handler_t *hdlr)
979 data_blk_t blk = { 0 };
980 mtp_uint16 resp = PTP_RESPONSE_OK;
981 mtp_char temp_fpath[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
983 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0) ||
984 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
985 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
987 ERR("unsupported parameter");
988 _device_set_phase(DEVICE_PHASE_NOTREADY);
989 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_INVALIDPARAM);
992 #ifndef MTP_USE_SELFMAKE_ABSTRACTION
993 if (hdlr->data4_send_obj.is_valid != TRUE) {
994 DBG("invalide object info");
995 _device_set_phase(DEVICE_PHASE_NOTREADY);
998 #endif /*MTP_USE_SELFMAKE_ABSTRACTION*/
1000 _device_set_phase(DEVICE_PHASE_DATAOUT);
1001 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
1003 if (_hdlr_rcv_file_in_data_container(&blk, temp_fpath,
1004 MTP_MAX_PATHNAME_SIZE + 1) == FALSE) {
1005 _device_set_phase(DEVICE_PHASE_IDLE);
1007 ERR("_hdlr_rcv_file_in_data_container() Fail");
1009 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
1013 switch (_hutil_write_file_data(hdlr->data4_send_obj.store_id,
1014 hdlr->data4_send_obj.obj, temp_fpath)) {
1016 case MTP_ERROR_INVALID_OBJECT_INFO:
1017 resp = PTP_RESPONSE_NOVALID_OBJINFO;
1018 DBG("PTP_RESPONSE_NOVALID_OBJINFO");
1020 #ifdef MTP_USE_SELFMAKE_ABSTRACTION
1021 case MTP_ERROR_INVALID_PARAM: /* association file*/
1022 #endif /*MTP_USE_SELFMAKE_ABSTRACTION*/
1023 case MTP_ERROR_NONE:
1024 resp = PTP_RESPONSE_OK;
1025 DBG("PTP_RESPONSE_OK");
1027 case MTP_ERROR_STORE_FULL:
1028 resp = PTP_RESPONSE_STOREFULL;
1029 DBG("PTP_RESPONSE_STOREFULL");
1032 resp = PTP_RESPONSE_GEN_ERROR;
1033 DBG("PTP_RESPONSE_GEN_ERROR");
1035 _cmd_hdlr_send_response_code(hdlr, resp);
1037 /* This object info has been consumed.*/
1038 hdlr->data4_send_obj.obj = NULL;
1039 hdlr->data4_send_obj.is_valid = FALSE;
1044 static void __delete_object(mtp_handler_t *hdlr)
1046 mtp_uint32 obj_handle = 0;
1048 mtp_uint16 resp = 0;
1050 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
1052 ERR("Parameters not supported");
1053 _cmd_hdlr_send_response_code(hdlr,
1054 PTP_RESPONSE_PARAM_NOTSUPPORTED);
1058 obj_handle = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
1059 fmt = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
1060 if ((PTP_FORMATCODE_NOTUSED != fmt) &&
1061 (obj_handle != PTP_OBJECTHANDLE_ALL)) {
1062 ERR("Invalid object format");
1063 _cmd_hdlr_send_response_code(hdlr,
1064 PTP_RESPONSE_INVALID_OBJ_FMTCODE);
1068 _transport_set_mtp_operation_state(MTP_STATE_DATA_PROCESSING);
1070 switch (_hutil_remove_object_entry(obj_handle, fmt)) {
1071 case MTP_ERROR_NONE:
1072 resp = PTP_RESPONSE_OK;
1074 case MTP_ERROR_STORE_READ_ONLY:
1075 resp = PTP_RESPONSE_STORE_READONLY;
1077 case MTP_ERROR_PARTIAL_DELETION:
1078 resp = PTP_RESPONSE_PARTIAL_DELETION;
1080 case MTP_ERROR_OBJECT_WRITE_PROTECTED:
1081 resp = PTP_RESPONSE_OBJ_WRITEPROTECTED;
1083 case MTP_ERROR_ACCESS_DENIED:
1084 resp = PTP_RESPONSE_ACCESSDENIED;
1086 case MTP_ERROR_INVALID_OBJECTHANDLE:
1087 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
1090 resp = PTP_RESPONSE_GEN_ERROR;
1093 _transport_set_mtp_operation_state(MTP_STATE_ONSERVICE);
1094 _cmd_hdlr_send_response_code(hdlr, resp);
1097 static void __format_store(mtp_handler_t *hdlr)
1099 mtp_uint32 store_id = 0;
1100 mtp_uint32 fs_fmt = 0;
1102 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
1103 _cmd_hdlr_send_response_code(hdlr,
1104 PTP_RESPONSE_PARAM_NOTSUPPORTED);
1108 store_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
1109 fs_fmt = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
1111 _hutil_format_storage(store_id, fs_fmt);
1113 /* although there is remain file, send OK */
1114 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
1117 static void __reset_device(mtp_handler_t *hdlr)
1119 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0) ||
1120 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
1121 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
1123 _cmd_hdlr_send_response_code(hdlr,
1124 PTP_RESPONSE_PARAM_NOTSUPPORTED);
1128 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
1131 static void __get_device_prop_desc(mtp_handler_t *hdlr)
1133 device_prop_desc_t dev_prop = { { 0 }, };
1134 device_prop_desc_t *prop_ptr = NULL;
1135 ptp_string_t ptp_str = { 0, { 0 } };
1136 data_blk_t blk = { 0 };
1137 mtp_uint32 prop_id = 0;
1138 mtp_uint32 resp = 0;
1139 mtp_uint32 num_bytes = 0;
1140 mtp_uchar *ptr = NULL;
1141 mtp_wchar temp[MTP_MAX_REG_STRING + 1] = { 0 };
1143 prop_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
1145 #ifdef MTP_SUPPORT_DEVICEPROP_BATTERYLEVEL
1146 case PTP_PROPERTYCODE_BATTERYLEVEL:
1150 prop_ptr = _device_get_device_property(prop_id);
1151 if (NULL == prop_ptr) {
1152 ERR("prop_ptr is NULL!");
1156 batt = _util_get_battery_level();
1157 if (FALSE == _prop_set_current_integer(prop_ptr, batt))
1158 ERR("_util_get_battery_level() Fail");
1161 #endif /* MTP_SUPPORT_DEVICEPROP_BATTERYLEVEL */
1163 case MTP_PROPERTYCODE_DEVICEFRIENDLYNAME:
1165 mtp_char *dev_name = _device_get_device_name();
1166 if (dev_name == NULL) {
1167 ERR("_device_get_device_name() Fail");
1171 prop_ptr = _device_get_device_property(prop_id);
1172 if (NULL == prop_ptr) {
1173 ERR("prop_ptr is Null");
1177 _util_utf8_to_utf16(temp, sizeof(temp) / WCHAR_SIZ, dev_name);
1178 _prop_copy_char_to_ptpstring(&ptp_str, temp, WCHAR_TYPE);
1179 _prop_set_current_string(prop_ptr, &ptp_str);
1184 case MTP_PROPERTYCODE_SYNCHRONIZATIONPARTNER:
1186 mtp_char *sync_ptr = _device_get_sync_partner();
1187 if (NULL == sync_ptr) {
1188 ERR("_device_get_sync_partner() Fail");
1191 prop_ptr = _device_get_device_property(prop_id);
1192 if (NULL == prop_ptr) {
1193 ERR("prop_ptr is Null");
1198 _util_utf8_to_utf16(temp, sizeof(temp) / WCHAR_SIZ, sync_ptr);
1199 _prop_copy_char_to_ptpstring(&ptp_str, temp, WCHAR_TYPE);
1200 _prop_set_current_string(prop_ptr, &ptp_str);
1204 case MTP_PROPERTYCODE_DEVICEICON:
1207 mtp_uint32 bytes_read = 0;
1208 mtp_uint32 file_size = 0;
1210 mtp_uchar *data = NULL;
1213 prop_ptr = _device_get_device_property(prop_id);
1214 if (NULL == prop_ptr) {
1215 ERR("prop_ptr is Null");
1219 h_file = _util_file_open(MTP_DEVICE_ICON, MTP_FILE_READ, &err);
1220 if (h_file == NULL) {
1221 ERR("file handle is not valid");
1222 _cmd_hdlr_send_response_code(hdlr,
1223 PTP_RESPONSE_GEN_ERROR);
1226 if (fstat(fileno((FILE *)h_file), &buf) != 0) {
1227 _util_file_close(h_file);
1228 _cmd_hdlr_send_response_code(hdlr,
1229 PTP_RESPONSE_GEN_ERROR);
1232 file_size = buf.st_size;
1233 data = (mtp_uchar *)g_malloc(file_size + sizeof(mtp_uint32));
1235 ERR("g_malloc() Fail");
1236 _util_file_close(h_file);
1237 _cmd_hdlr_send_response_code(hdlr,
1238 PTP_RESPONSE_GEN_ERROR);
1241 memcpy(data, &file_size, sizeof(mtp_uint32));
1242 _util_file_read(h_file, &data[sizeof(mtp_uint32)], file_size,
1244 if (bytes_read != file_size) {
1245 ERR("Number of read bytes less than requested");
1246 _util_file_close(h_file);
1248 _cmd_hdlr_send_response_code(hdlr,
1249 PTP_RESPONSE_GEN_ERROR);
1253 _prop_set_current_array(prop_ptr, data);
1254 _prop_set_default_array(&(prop_ptr->propinfo),
1255 (mtp_uchar *)&data[sizeof(mtp_uint32)], bytes_read);
1257 _util_file_close(h_file);
1262 ERR("Unknown PropId : [0x%x]\n", prop_id);
1266 if (_hutil_get_device_property(prop_id, &dev_prop) != MTP_ERROR_NONE) {
1267 ERR("_hutil_get_device_property returned error");
1268 resp = PTP_RESPONSE_PROP_NOTSUPPORTED;
1269 _cmd_hdlr_send_response_code(hdlr, resp);
1272 num_bytes = _prop_size_device_prop_desc(&dev_prop);
1274 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
1275 ptr = _hdlr_alloc_buf_data_container(&blk, num_bytes, num_bytes);
1277 resp = PTP_RESPONSE_GEN_ERROR;
1278 _cmd_hdlr_send_response_code(hdlr, resp);
1283 if (_prop_pack_device_prop_desc(&dev_prop, ptr, num_bytes) != num_bytes) {
1284 resp = PTP_RESPONSE_GEN_ERROR;
1285 _cmd_hdlr_send_response_code(hdlr, resp);
1290 _device_set_phase(DEVICE_PHASE_DATAIN);
1291 if (_hdlr_send_data_container(&blk))
1292 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
1294 _device_set_phase(DEVICE_PHASE_NOTREADY);
1295 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
1302 static void __get_device_prop_value(mtp_handler_t *hdlr)
1305 ptp_string_t ptp_str = { 0, { 0 } };
1306 data_blk_t blk = { 0 };
1307 mtp_uint32 prop_id = 0;
1308 mtp_uint32 no_bytes = 0;
1309 mtp_uchar *ptr = NULL;
1310 mtp_wchar temp[MTP_MAX_REG_STRING + 1] = { 0 };
1312 prop_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
1313 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
1316 #ifdef MTP_SUPPORT_DEVICEPROP_BATTERYLEVEL
1317 case PTP_PROPERTYCODE_BATTERYLEVEL: {
1320 batt = _util_get_battery_level();
1321 no_bytes = sizeof(batt);
1323 ptr = _hdlr_alloc_buf_data_container(&blk, no_bytes, no_bytes);
1325 _cmd_hdlr_send_response_code(hdlr,
1326 PTP_RESPONSE_GEN_ERROR);
1330 memcpy(ptr, &batt, no_bytes);
1331 #ifdef __BIG_ENDIAN__
1332 _util_conv_byte_order(ptr, no_bytes);
1333 #endif /*__BIG_ENDIAN__*/
1336 #endif /* MTP_SUPPORT_DEVICEPROP_BATTERYLEVEL */
1338 case MTP_PROPERTYCODE_DEVICEFRIENDLYNAME:
1341 mtp_char *device = _device_get_device_name();
1342 if (device == NULL) {
1343 ERR("_device_get_device_name() Fail");
1344 _cmd_hdlr_send_response_code(hdlr,
1345 PTP_RESPONSE_GEN_ERROR);
1349 _util_utf8_to_utf16(temp, sizeof(temp) / WCHAR_SIZ, device);
1350 _prop_copy_char_to_ptpstring(&ptp_str, temp, WCHAR_TYPE);
1351 no_bytes = _prop_size_ptpstring(&ptp_str);
1354 ptr = _hdlr_alloc_buf_data_container(&blk, no_bytes, no_bytes);
1356 _cmd_hdlr_send_response_code(hdlr,
1357 PTP_RESPONSE_GEN_ERROR);
1362 if (_prop_pack_ptpstring(&ptp_str, ptr, no_bytes) != no_bytes) {
1363 _cmd_hdlr_send_response_code(hdlr,
1364 PTP_RESPONSE_GEN_ERROR);
1371 case MTP_PROPERTYCODE_SYNCHRONIZATIONPARTNER:
1374 mtp_char *sync_ptr = _device_get_sync_partner();
1375 if (sync_ptr == NULL) {
1376 ERR("_device_get_sync_partner() Fail");
1377 _cmd_hdlr_send_response_code(hdlr,
1378 PTP_RESPONSE_GEN_ERROR);
1381 _util_utf8_to_utf16(temp, sizeof(temp) / WCHAR_SIZ, sync_ptr);
1384 _prop_copy_char_to_ptpstring(&ptp_str, temp, WCHAR_TYPE);
1385 no_bytes = _prop_size_ptpstring(&ptp_str);
1387 ptr = _hdlr_alloc_buf_data_container(&blk, no_bytes, no_bytes);
1389 _cmd_hdlr_send_response_code(hdlr,
1390 PTP_RESPONSE_GEN_ERROR);
1395 if (_prop_pack_ptpstring(&ptp_str, ptr, no_bytes) != no_bytes) {
1396 _cmd_hdlr_send_response_code(hdlr,
1397 PTP_RESPONSE_GEN_ERROR);
1404 case MTP_PROPERTYCODE_DEVICEICON:
1408 mtp_uint32 read_bytes = 0;
1409 mtp_uint32 file_size = 0;
1411 mtp_uchar *data = NULL;
1413 ptp_array_t val_arr = { 0 };
1416 h_file = _util_file_open(MTP_DEVICE_ICON, MTP_FILE_READ, &err);
1417 if (h_file == NULL) {
1418 ERR("file handle is not valid");
1419 _cmd_hdlr_send_response_code(hdlr,
1420 PTP_RESPONSE_GEN_ERROR);
1423 if (fstat(fileno(h_file), &buf) != 0) {
1424 _util_file_close(h_file);
1425 _cmd_hdlr_send_response_code(hdlr,
1426 PTP_RESPONSE_GEN_ERROR);
1430 file_size = buf.st_size;
1431 data = (mtp_uchar *)g_malloc(file_size);
1433 ERR("g_malloc() Fail");
1434 _util_file_close(h_file);
1435 _cmd_hdlr_send_response_code(hdlr,
1436 PTP_RESPONSE_GEN_ERROR);
1440 _util_file_read(h_file, &data, file_size, &read_bytes);
1441 if (read_bytes != file_size) {
1442 ERR("Number of read bytes less than requested");
1443 _util_file_close(h_file);
1445 _cmd_hdlr_send_response_code(hdlr,
1446 PTP_RESPONSE_GEN_ERROR);
1450 _prop_init_ptparray(&val_arr, UINT8_TYPE);
1451 _prop_grow_ptparray(&val_arr, read_bytes);
1452 for (ii = 0; ii < read_bytes; ii++)
1453 _prop_append_ele_ptparray(&val_arr, data[ii]);
1455 no_bytes = _prop_get_size_ptparray(&val_arr);
1456 ptr = _hdlr_alloc_buf_data_container(&blk, no_bytes, no_bytes);
1458 _cmd_hdlr_send_response_code(hdlr,
1459 PTP_RESPONSE_GEN_ERROR);
1462 _util_file_close(h_file);
1463 _prop_deinit_ptparray(&val_arr);
1466 if (_prop_pack_ptparray(&val_arr, ptr, no_bytes) != no_bytes) {
1467 _cmd_hdlr_send_response_code(hdlr,
1468 PTP_RESPONSE_GEN_ERROR);
1471 _prop_deinit_ptparray(&val_arr);
1472 _util_file_close(h_file);
1477 _prop_deinit_ptparray(&val_arr);
1478 _util_file_close(h_file);
1484 ERR("Unknown PropId : [0x%x]\n", prop_id);
1485 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
1489 _device_set_phase(DEVICE_PHASE_DATAIN);
1490 if (_hdlr_send_data_container(&blk)) {
1491 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
1493 _device_set_phase(DEVICE_PHASE_NOTREADY);
1494 _cmd_hdlr_send_response_code(hdlr,
1495 PTP_RESPONSE_INCOMPLETETRANSFER);
1501 static void __set_device_prop_value(mtp_handler_t *hdlr)
1503 mtp_uint32 prop_id = 0;
1504 data_blk_t blk = { 0 };
1505 mtp_uint32 max_bytes = 0;
1506 mtp_uint16 resp = PTP_RESPONSE_OK;
1508 mtp_char *d_raw = NULL;
1510 prop_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
1511 _device_set_phase(DEVICE_PHASE_DATAOUT);
1513 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
1514 max_bytes = MAX_SIZE_IN_BYTES_OF_PROP_VALUE;
1516 if (FALSE == _hdlr_rcv_data_container(&blk, max_bytes)) {
1517 ERR("_hdlr_rcv_data_container() Fail");
1518 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
1523 d_raw = (mtp_char *)_hdlr_get_payload_data(&blk);
1524 if (NULL != d_raw) {
1525 ret = _hutil_set_device_property(prop_id, d_raw,
1526 _hdlr_get_payload_size(&blk));
1528 ret = MTP_ERROR_INVALID_OBJ_PROP_CODE;
1532 case MTP_ERROR_NONE: {
1533 #ifdef MTP_USE_INFORMATION_REGISTRY
1535 mtp_char temp[MTP_MAX_REG_STRING * 3 + 1] = { 0 };
1536 mtp_wchar parsed_buf[MTP_MAX_REG_STRING + 1] = { 0 };
1537 mtp_uchar parse_sz = 0;
1539 if (MTP_PROPERTYCODE_SYNCHRONIZATIONPARTNER == prop_id) {
1540 parse_sz = d_raw[0];
1541 _util_wchar_ncpy(parsed_buf, (mtp_wchar *)&d_raw[1],
1542 parse_sz > MTP_MAX_REG_STRING ?
1543 MTP_MAX_REG_STRING : parse_sz);
1544 _util_utf16_to_utf8(temp, sizeof(temp), parsed_buf);
1545 _device_set_sync_partner(temp);
1546 if (!g_strcmp0(temp,
1547 MTP_DEV_PROPERTY_NULL_SYNCPARTNER)) {
1548 vconf_set_str(VCONFKEY_MTP_SYNC_PARTNER_STR,
1551 vconf_set_str(VCONFKEY_MTP_SYNC_PARTNER_STR,
1555 #endif /*MTP_USE_INFORMATION_REGISTRY*/
1557 resp = PTP_RESPONSE_OK;
1559 case MTP_ERROR_ACCESS_DENIED:
1560 resp = PTP_RESPONSE_ACCESSDENIED;
1562 case MTP_ERROR_INVALID_OBJ_PROP_VALUE:
1563 resp = PTP_RESPONSE_INVALIDPROPVALUE;
1566 resp = PTP_RESPONSE_PROP_NOTSUPPORTED;
1569 _cmd_hdlr_send_response_code(hdlr, resp);
1575 static void __get_partial_object(mtp_handler_t *hdlr)
1577 mtp_uint32 h_obj = 0;
1579 mtp_uint32 data_sz = 0;
1580 mtp_uint32 send_bytes = 0;
1581 data_blk_t blk = { 0 };
1582 mtp_uchar *ptr = NULL;
1583 mtp_uint16 resp = 0;
1584 mtp_uint64 f_size = 0;
1585 mtp_uint64 total_sz = 0;
1587 offset = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
1588 data_sz = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2);
1589 h_obj = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
1591 switch (_hutil_get_object_entry_size(h_obj, &f_size)) {
1593 case MTP_ERROR_INVALID_OBJECTHANDLE:
1594 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
1596 case MTP_ERROR_NONE:
1597 if (data_sz > (f_size - offset))
1598 send_bytes = f_size - offset;
1600 send_bytes = data_sz;
1601 resp = PTP_RESPONSE_OK;
1604 resp = PTP_RESPONSE_GEN_ERROR;
1608 if (PTP_RESPONSE_OK != resp) {
1609 _cmd_hdlr_send_response_code(hdlr, resp);
1613 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
1614 ptr = _hdlr_alloc_buf_data_container(&blk, send_bytes, send_bytes);
1617 switch (_hutil_read_file_data_from_offset(h_obj, offset, ptr, &send_bytes)) {
1618 case MTP_ERROR_NONE:
1619 resp = PTP_RESPONSE_OK;
1621 case MTP_ERROR_INVALID_OBJECTHANDLE:
1622 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
1625 resp = PTP_RESPONSE_GEN_ERROR;
1628 resp = PTP_RESPONSE_GEN_ERROR;
1631 if (PTP_RESPONSE_OK == resp) {
1632 _device_set_phase(DEVICE_PHASE_DATAIN);
1633 if (_hdlr_send_data_container(&blk)) {
1634 total_sz = send_bytes + sizeof(header_container_t);
1635 if (total_sz % _transport_get_usb_packet_len() == 0)
1636 _transport_send_zlp();
1637 _cmd_hdlr_send_response(hdlr, resp, 1, &send_bytes);
1642 /*Host Cancelled data-in transfer*/
1643 _device_set_phase(DEVICE_PHASE_NOTREADY);
1648 _cmd_hdlr_send_response_code(hdlr, resp);
1654 static void __get_object_references(mtp_handler_t *hdlr)
1656 mtp_uint32 h_obj = 0;
1657 ptp_array_t ref_arr = { 0 };
1658 data_blk_t blk = { 0 };
1659 mtp_uint32 num_bytes = 0;
1660 mtp_uchar *ptr = NULL;
1661 mtp_uint32 num_ele = 0;
1662 mtp_uint16 resp = 0;
1664 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
1665 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
1667 ERR("Unsupported Parameters");
1668 _cmd_hdlr_send_response_code(hdlr,
1669 PTP_RESPONSE_PARAM_NOTSUPPORTED);
1673 h_obj = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
1675 switch (_hutil_get_object_references(h_obj, &ref_arr, &num_ele)) {
1676 case MTP_ERROR_INVALID_OBJECTHANDLE:
1677 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
1679 case MTP_ERROR_NONE:
1680 resp = PTP_RESPONSE_OK;
1683 resp = PTP_RESPONSE_GEN_ERROR;
1686 if (resp != PTP_RESPONSE_OK) {
1687 _cmd_hdlr_send_response_code(hdlr, resp);
1691 if (resp == PTP_RESPONSE_OK && num_ele == 0) {
1692 _cmd_hdlr_send_response_code(hdlr, resp);
1696 num_bytes = _prop_get_size_ptparray(&ref_arr);
1697 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
1699 ptr = _hdlr_alloc_buf_data_container(&blk, num_bytes, num_bytes);
1700 if (num_bytes == _prop_pack_ptparray(&ref_arr, ptr, num_bytes)) {
1701 _device_set_phase(DEVICE_PHASE_DATAIN);
1702 if (_hdlr_send_data_container(&blk)) {
1703 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
1705 /* Host Cancelled data-in transfer*/
1706 _device_set_phase(DEVICE_PHASE_NOTREADY);
1709 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
1712 _prop_deinit_ptparray(&ref_arr);
1718 static void __set_object_references(mtp_handler_t *hdlr)
1720 mtp_uint32 h_obj = 0;
1721 data_blk_t blk = { 0 };
1722 mtp_uint32 max_bytes = 0;
1723 mtp_uint16 resp = PTP_RESPONSE_OK;
1724 mtp_uint32 num_ref = 0;
1726 mtp_uint32 *ref_ptr = NULL;
1727 mtp_uchar *ptr = NULL;
1728 mtp_uint32 ref_handle = 0;
1730 h_obj = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
1731 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
1732 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
1734 resp = PTP_RESPONSE_PARAM_NOTSUPPORTED;
1735 _cmd_hdlr_send_response_code(hdlr, resp);
1738 _device_set_phase(DEVICE_PHASE_DATAOUT);
1739 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
1741 /* temporarily set a big number for data size received */
1743 max_bytes = MTP_MAX_REFDB_ROWCNT * sizeof(mtp_uint32);
1744 if (_hdlr_rcv_data_container(&blk, max_bytes) == FALSE) {
1745 DBG("_hdlr_rcv_data_container() Fail");
1746 _device_set_phase(DEVICE_PHASE_IDLE);
1747 resp = PTP_RESPONSE_GEN_ERROR;
1750 if (PTP_RESPONSE_OK != resp) {
1751 _cmd_hdlr_send_response_code(hdlr, resp);
1756 ptr = _hdlr_get_payload_data(&blk);
1762 memcpy(&num_ref, ptr, sizeof(mtp_uint32));
1763 #ifdef __BIG_ENDIAN__
1764 _util_conv_byte_order(&num_ref, sizeof(DWORD));
1765 #endif /* __BIG_ENDIAN__ */
1767 ptr += sizeof(mtp_uint32);
1768 if (_hdlr_get_payload_size(&blk) < (num_ref + 1) * sizeof(mtp_uint32)) {
1770 resp = PTP_RESPONSE_GEN_ERROR;
1771 _cmd_hdlr_send_response_code(hdlr, resp);
1776 ref_ptr = (mtp_uint32 *)ptr;
1777 if (MTP_ERROR_NONE != _hutil_remove_object_reference(h_obj,
1778 PTP_OBJECTHANDLE_ALL)) {
1779 resp = PTP_RESPONSE_GEN_ERROR;
1780 _cmd_hdlr_send_response_code(hdlr, resp);
1784 for (idx = 0; idx < num_ref; idx++) {
1785 ref_handle = ref_ptr[idx];
1786 #ifdef __BIG_ENDIAN__
1787 _util_conv_byte_order(&ref_handle, sizeof(mtp_uint32));
1788 #endif /*__BIG_ENDIAN__*/
1789 _device_get_object_with_handle(ref_handle);
1792 _hutil_add_object_references_enhanced(h_obj, (mtp_uchar *)ref_ptr,
1794 _cmd_hdlr_send_response_code(hdlr, resp);
1800 static void __get_object_prop_desc(mtp_handler_t *hdlr)
1802 mtp_uint32 prop_id = 0;
1804 obj_prop_desc_t prop = { { 0 }, };
1805 data_blk_t blk = { 0, };
1806 mtp_uint32 num_bytes = 0;
1807 mtp_uchar *ptr = NULL;
1809 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
1810 _cmd_hdlr_send_response_code(hdlr,
1811 PTP_RESPONSE_PARAM_NOTSUPPORTED);
1815 prop_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
1816 fmt = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
1818 if (MTP_ERROR_NONE != _hutil_get_prop_desc(fmt, prop_id, &prop)) {
1819 _cmd_hdlr_send_response_code(hdlr,
1820 PTP_RESPONSE_PROP_NOTSUPPORTED);
1824 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
1825 num_bytes = _prop_size_obj_prop_desc(&prop);
1826 ptr = _hdlr_alloc_buf_data_container(&blk, num_bytes, num_bytes);
1828 if (num_bytes == _prop_pack_obj_prop_desc(&prop, ptr, num_bytes)) {
1829 _device_set_phase(DEVICE_PHASE_DATAIN);
1830 if (_hdlr_send_data_container(&blk)) {
1831 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
1833 /* Host Cancelled data-in transfer */
1834 _device_set_phase(DEVICE_PHASE_NOTREADY);
1837 _cmd_hdlr_send_response_code(hdlr,
1838 PTP_RESPONSE_GEN_ERROR);
1845 static void __get_object_prop_supported(mtp_handler_t *hdlr)
1848 data_blk_t blk = { 0 };
1849 ptp_array_t props_supported = { 0 };
1850 mtp_uint32 num_bytes = 0;
1851 mtp_uchar *ptr = NULL;
1853 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
1854 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
1855 _cmd_hdlr_send_response_code(hdlr,
1856 PTP_RESPONSE_PARAM_NOTSUPPORTED);
1860 fmt = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
1861 _prop_init_ptparray(&props_supported, UINT16_TYPE);
1863 if (MTP_ERROR_NONE != _hutil_get_object_prop_supported(fmt,
1864 &props_supported)) {
1865 _prop_deinit_ptparray(&props_supported);
1866 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
1870 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
1871 num_bytes = _prop_get_size_ptparray(&props_supported);
1872 ptr = _hdlr_alloc_buf_data_container(&blk, num_bytes, num_bytes);
1875 _prop_pack_ptparray(&props_supported, ptr, num_bytes);
1876 _device_set_phase(DEVICE_PHASE_DATAIN);
1877 if (_hdlr_send_data_container(&blk)) {
1878 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
1880 /* Host Cancelled data-in transfer */
1881 _device_set_phase(DEVICE_PHASE_NOTREADY);
1884 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
1887 _prop_deinit_ptparray(&props_supported);
1893 static void __get_object_prop_value(mtp_handler_t *hdlr)
1895 mtp_uint32 h_obj = 0;
1896 mtp_uint32 prop_id = 0;
1897 mtp_uchar *ptr = NULL;
1898 mtp_uint32 num_bytes = 0;
1899 data_blk_t blk = { 0 };
1900 obj_prop_val_t prop_val = { 0 };
1902 mtp_obj_t *obj = NULL;
1903 #ifdef MTP_USE_RUNTIME_GETOBJECTPROPVALUE
1904 slist_node_t *node = NULL;
1905 slist_node_t *next_node = NULL;
1907 #endif /*MTP_USE_RUNTIME_GETOBJECTPROPVALUE*/
1909 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
1910 _cmd_hdlr_send_response_code(hdlr,
1911 PTP_RESPONSE_PARAM_NOTSUPPORTED);
1915 h_obj = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
1916 prop_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
1917 ret = _hutil_get_object_prop_value(h_obj, prop_id, &prop_val, &obj);
1919 if (MTP_ERROR_NONE == ret) {
1920 num_bytes = _prop_size_obj_propval(&prop_val);
1921 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code,
1923 ptr = _hdlr_alloc_buf_data_container(&blk, num_bytes,
1926 _prop_pack_obj_propval(&prop_val, ptr, num_bytes)) {
1928 _device_set_phase(DEVICE_PHASE_DATAIN);
1929 if (_hdlr_send_data_container(&blk)) {
1930 _cmd_hdlr_send_response_code(hdlr,
1933 /* Host Cancelled data-in transfer */
1934 _device_set_phase(DEVICE_PHASE_NOTREADY);
1937 _cmd_hdlr_send_response_code(hdlr,
1938 PTP_RESPONSE_GEN_ERROR);
1943 } else if (ret == MTP_ERROR_INVALID_OBJECTHANDLE) {
1944 _cmd_hdlr_send_response_code(hdlr,
1945 PTP_RESPONSE_INVALID_OBJ_HANDLE);
1947 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
1950 #ifdef MTP_USE_RUNTIME_GETOBJECTPROPVALUE
1952 ERR("Invalid object");
1956 for (ii = 0, next_node = obj->propval_list.start;
1957 ii < obj->propval_list.nnodes; ii++) {
1959 next_node = node->link;
1960 _prop_destroy_obj_propval((obj_prop_val_t *)node->value);
1963 obj->propval_list.start = NULL;
1964 obj->propval_list.end = NULL;
1965 obj->propval_list.nnodes = 0;
1966 #endif /*MTP_USE_RUNTIME_GETOBJECTPROPVALUE*/
1971 static void __set_object_prop_value(mtp_handler_t *hdlr)
1973 mtp_uint32 h_obj = 0;
1974 mtp_uint32 prop_id = 0;
1975 mtp_uint16 resp = PTP_RESPONSE_OK;
1976 data_blk_t blk = { 0 };
1977 mtp_uint32 max_bytes = 0;
1980 h_obj = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
1981 prop_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
1983 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
1984 ERR("Unsupported parameters");
1985 resp = PTP_RESPONSE_PARAM_NOTSUPPORTED;
1986 _cmd_hdlr_send_response_code(hdlr, resp);
1990 _device_set_phase(DEVICE_PHASE_DATAOUT);
1991 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
1992 max_bytes = MTP_MAX_PROP_DATASIZE;
1994 if (_hdlr_rcv_data_container(&blk, max_bytes) == FALSE) {
1995 ERR("_hdlr_rcv_data_container() Fail");
1996 _device_set_phase(DEVICE_PHASE_IDLE);
1997 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_INVALIDPROPVALUE);
2002 ret = _hutil_update_object_property(h_obj, prop_id, NULL,
2003 _hdlr_get_payload_data(&blk),
2004 _hdlr_get_payload_size(&blk), NULL);
2006 case MTP_ERROR_ACCESS_DENIED:
2007 resp = PTP_RESPONSE_ACCESSDENIED;
2009 case MTP_ERROR_INVALID_OBJECTHANDLE:
2010 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
2012 case MTP_ERROR_INVALID_OBJ_PROP_CODE:
2013 resp = PTP_RESPONSE_PROP_NOTSUPPORTED;
2015 case MTP_ERROR_GENERAL:
2016 resp = PTP_RESPONSE_GEN_ERROR;
2018 case MTP_ERROR_NONE:
2019 resp = PTP_RESPONSE_OK;
2022 resp = PTP_RESPONSE_INVALIDPROPVALUE;
2026 _cmd_hdlr_send_response_code(hdlr, resp);
2032 static void __get_object_prop_list(mtp_handler_t *hdlr)
2034 mtp_uint32 h_obj = 0;
2036 mtp_uint32 prop_id = 0;
2037 mtp_uint32 group_code = 0;
2038 mtp_uint32 depth = 0;
2040 mtp_uint16 resp = 0;
2041 obj_proplist_t prop_list = { { 0 } };
2042 data_blk_t blk = { 0 };
2043 mtp_uint32 num_bytes = 0;
2044 mtp_uchar *ptr = NULL;
2045 #ifdef MTP_USE_RUNTIME_GETOBJECTPROPVALUE
2046 ptp_array_t obj_arr = { 0 };
2047 slist_node_t *node = NULL;
2048 slist_node_t *next_node = NULL;
2051 mtp_obj_t *obj = NULL;
2052 #endif /*MTP_USE_RUNTIME_GETOBJECTPROPVALUE*/
2054 h_obj = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
2055 fmt = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
2056 prop_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2);
2057 group_code = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 3);
2058 depth = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 4);
2060 __enum_store_not_enumerated(h_obj, fmt, depth);
2062 #ifdef MTP_USE_RUNTIME_GETOBJECTPROPVALUE
2063 ret = _hutil_get_object_prop_list(h_obj, fmt, prop_id, group_code,
2064 depth, &prop_list, &obj_arr);
2065 #else /*MTP_USE_RUNTIME_GETOBJECTPROPVALUE*/
2066 ret = _hutil_get_object_prop_list(h_obj, fmt, prop_id, group_code,
2068 #endif /*MTP_USE_RUNTIME_GETOBJECTPROPVALUE*/
2071 case MTP_ERROR_NONE:
2072 resp = PTP_RESPONSE_OK;
2074 case MTP_ERROR_INVALID_OBJECTHANDLE:
2075 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
2077 case MTP_ERROR_INVALID_PARAM:
2078 resp = PTP_RESPONSE_INVALIDPARAM;
2080 case MTP_ERROR_NO_SPEC_BY_FORMAT:
2081 resp = PTP_RESPONSE_NOSPECIFICATIONBYFORMAT;
2083 case MTP_ERROR_GENERAL:
2085 resp = PTP_RESPONSE_GEN_ERROR;
2088 if (PTP_RESPONSE_OK != resp) {
2089 _cmd_hdlr_send_response_code(hdlr, resp);
2090 _prop_deinit_ptparray(&obj_arr);
2094 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
2095 num_bytes = _prop_size_obj_proplist(&prop_list);
2096 ptr = _hdlr_alloc_buf_data_container(&blk, num_bytes, num_bytes);
2097 if (num_bytes == _prop_pack_obj_proplist(&prop_list, ptr, num_bytes)) {
2099 _device_set_phase(DEVICE_PHASE_DATAIN);
2100 if (_hdlr_send_data_container(&blk)) {
2101 _cmd_hdlr_send_response_code(hdlr, resp);
2103 /* Host Cancelled data-in transfer*/
2104 _device_set_phase(DEVICE_PHASE_NOTREADY);
2108 _prop_destroy_obj_proplist(&prop_list);
2111 #ifdef MTP_USE_RUNTIME_GETOBJECTPROPVALUE
2112 if (resp == PTP_RESPONSE_OK && obj_arr.array_entry) {
2113 mtp_uint32 *obj_handles = obj_arr.array_entry;
2115 for (ii = 0; ii < obj_arr.num_ele; ii++) {
2116 mtp_store_t *store = NULL;
2118 store = _device_get_store_containing_obj(obj_handles[ii]);
2122 obj = _entity_get_object_from_store(store, obj_handles[ii]);
2123 if (NULL == obj || obj->propval_list.nnodes == 0)
2126 /*Remove all the old property value, and ready to set up new */
2127 for (jj = 0, next_node = obj->propval_list.start;
2128 jj < obj->propval_list.nnodes; jj++) {
2130 next_node = node->link;
2131 _prop_destroy_obj_propval
2132 ((obj_prop_val_t *)node->value);
2135 obj->propval_list.start = NULL;
2136 obj->propval_list.end = NULL;
2137 obj->propval_list.nnodes = 0;
2141 _prop_deinit_ptparray(&obj_arr);
2142 #endif /*MTP_USE_RUNTIME_GETOBJECTPROPVALUE*/
2146 static void __set_object_prop_list(mtp_handler_t *hdlr)
2149 mtp_uint16 resp = PTP_RESPONSE_OK;
2150 data_blk_t blk = { 0 };
2151 mtp_uint32 max_num_obj = 0;
2152 mtp_uint32 max_bytes = 0;
2153 mtp_uint32 h_obj = 0;
2154 mtp_uint32 prop_id = 0;
2155 mtp_uint16 data_type = 0;
2156 mtp_uchar *temp = NULL;
2157 mtp_int32 bytes_left = 0;
2158 mtp_uint32 prop_val_sz = 0;
2159 mtp_uint32 num_elem = 0;
2162 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0) ||
2163 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
2164 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2) ||
2165 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 3) ||
2166 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 4)) {
2167 resp = PTP_RESPONSE_PARAM_NOTSUPPORTED;
2170 _device_set_phase(DEVICE_PHASE_DATAOUT);
2171 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
2173 /* Gestimate the amount of data we will be receiving */
2174 _hutil_get_number_of_objects(PTP_STORAGEID_ALL, &max_num_obj);
2175 max_bytes = max_num_obj * 1000;
2177 /* If Host sent more data than we could receive, a device stall happens,
2178 * which cancels the data transfer
2180 if (max_bytes > 1000000) {
2181 max_bytes = 1000000;
2182 ERR("max_bytes is overflowed");
2184 if (FALSE == _hdlr_rcv_data_container(&blk, max_bytes)) {
2185 ERR("_hdlr_rcv_data_container() Fail");
2186 _device_set_phase(DEVICE_PHASE_NOTREADY);
2187 resp = PTP_RESPONSE_GEN_ERROR;
2190 if (PTP_RESPONSE_OK != resp) {
2191 _cmd_hdlr_send_response(hdlr, resp, 1, &i);
2196 temp = _hdlr_get_payload_data(&blk);
2197 bytes_left = (mtp_int32)_hdlr_get_payload_size(&blk);
2198 if (bytes_left < sizeof(mtp_uint32)) {
2200 resp = MTP_RESPONSE_INVALIDOBJPROPFORMAT;
2201 _cmd_hdlr_send_response(hdlr, resp, 1, &i);
2204 ERR("invalid object format, bytes_left [%d]:[%zu]\n", bytes_left,
2205 sizeof(mtp_uint32));
2210 memcpy(&num_elem, temp, sizeof(mtp_uint32));
2211 temp += sizeof(mtp_uint32);
2212 bytes_left -= sizeof(mtp_uint32);
2214 for (i = 0; i < num_elem; i++) {
2218 /*Get object handle*/
2219 memcpy(&h_obj, temp, sizeof(mtp_uint32));
2220 temp += sizeof(mtp_uint32);
2221 bytes_left -= sizeof(mtp_uint32);
2225 /* Get property code */
2226 memcpy(&prop_id, temp, sizeof(mtp_uint16));
2227 temp += sizeof(mtp_uint16);
2228 bytes_left -= sizeof(mtp_uint16);
2233 memcpy(&data_type, temp, sizeof(mtp_uint16));
2234 temp += sizeof(mtp_uint16);
2235 bytes_left -= sizeof(mtp_uint16);
2239 /* Update property*/
2240 ret = _hutil_update_object_property(h_obj, prop_id,
2241 &data_type, temp, bytes_left,
2245 case MTP_ERROR_INVALID_OBJECT_PROP_FORMAT:
2246 resp = MTP_RESPONSE_INVALIDOBJPROPFORMAT;
2247 _cmd_hdlr_send_response(hdlr, resp, 1, &i);
2249 ERR("invalid object format");
2252 case MTP_ERROR_ACCESS_DENIED:
2253 resp = PTP_RESPONSE_ACCESSDENIED;
2254 _cmd_hdlr_send_response(hdlr, resp, 1, &i);
2256 ERR("access denied");
2259 case MTP_ERROR_INVALID_OBJECTHANDLE:
2260 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
2261 _cmd_hdlr_send_response(hdlr, resp, 1, &i);
2263 ERR("invalid object handle");
2266 case MTP_ERROR_INVALID_OBJ_PROP_CODE:
2267 resp = PTP_RESPONSE_PROP_NOTSUPPORTED;
2268 _cmd_hdlr_send_response(hdlr, resp, 1, &i);
2270 ERR("property not supported");
2273 case MTP_ERROR_NONE:
2274 temp += prop_val_sz;
2275 bytes_left -= prop_val_sz;
2278 resp = PTP_RESPONSE_INVALIDPROPVALUE;
2279 _cmd_hdlr_send_response(hdlr, resp, 1, &i);
2281 ERR("invalid property value");
2287 resp = PTP_RESPONSE_OK;
2288 _cmd_hdlr_send_response(hdlr, resp, 1, &i);
2293 static void __report_acquired_content(mtp_handler_t *hdlr)
2296 mtp_uint32 start_idx = 0;
2297 mtp_uint32 max_size = 0;
2298 mtp_uint16 resp = PTP_RESPONSE_OK;
2299 mtp_uint32 resp_param[3] = { 0 };
2300 data_blk_t blk = { 0 };
2301 mtp_uchar *ptr = NULL;
2302 ptp_array_t guid_arr = { 0 };
2303 mtp_uint32 num_mod = 0;
2304 mtp_uint32 num_bytes = 0;
2305 mtp_uint32 num_lines = 0;
2306 mtp_uint32 rem_modified = 0;
2310 mtp_int32 diff_time;
2314 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 3)) {
2316 ERR("Unsupported parameters");
2317 _cmd_hdlr_send_response_code(hdlr,
2318 PTP_RESPONSE_PARAM_NOTSUPPORTED);
2322 tid = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
2323 start_idx = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
2324 max_size = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2);
2328 if (access(MTP_FILES_MODIFIED_FILES, F_OK) == 0)
2329 if (remove(MTP_FILES_MODIFIED_FILES) < 0)
2330 ERR("remove(%s) Fail", MTP_FILES_MODIFIED_FILES);
2332 resp = PTP_RESPONSE_OK;
2333 _prop_grow_ptparray(&guid_arr, 1);
2334 _prop_append_ele_ptparray(&guid_arr, 0);
2338 g_is_sync_estab = TRUE;
2340 if (!g_has_round_trip && start_idx == 0) {
2342 ret = vconf_get_int(VCONFKEY_MTP_SYNC_TIME_INT, (int *)&l_time);
2344 ERR("Error to get key value at [%s] path\n",
2345 VCONFKEY_MTP_SYNC_TIME_INT);
2346 resp = PTP_RESPONSE_OK;
2347 _prop_grow_ptparray(&guid_arr, 1);
2348 _prop_append_ele_ptparray(&guid_arr, 0);
2351 diff_time = (cur_time - l_time) / 60;
2352 if (diff_time < 0) {
2353 resp = PTP_RESPONSE_GEN_ERROR;
2354 _prop_init_ptparray(&guid_arr, UINT32_TYPE);
2355 _prop_append_ele_ptparray(&guid_arr, 0);
2358 _entity_list_modified_files(diff_time);
2361 h_file = _util_file_open(MTP_FILES_MODIFIED_FILES, MTP_FILE_READ, &err);
2362 if (h_file == NULL) {
2363 resp = PTP_RESPONSE_GEN_ERROR;
2364 _prop_init_ptparray(&guid_arr, UINT32_TYPE);
2365 _prop_append_ele_ptparray(&guid_arr, 0);
2369 if (!g_has_round_trip && start_idx == 0) {
2370 _util_count_num_lines(h_file, &g_mgr->meta_info.mod);
2371 _util_file_seek(h_file, 0, SEEK_SET);
2373 num_lines = g_mgr->meta_info.mod;
2374 num_mod = ((num_lines - start_idx) > max_size) ?
2375 max_size : num_lines - start_idx;
2377 rem_modified = (num_lines - start_idx > max_size) ?
2378 (num_lines - start_idx - max_size) : 0;
2380 g_has_round_trip = FALSE;
2381 _prop_init_ptparray(&guid_arr, UINT32_TYPE);
2382 _prop_grow_ptparray(&guid_arr, (num_mod * sizeof(mtp_uint32)) + 1);
2383 _prop_append_ele_ptparray(&guid_arr, num_mod);
2384 _util_fill_guid_array(&guid_arr, start_idx, h_file, num_mod);
2386 _util_file_close(h_file);
2387 if (rem_modified == 0) {
2388 if (remove(MTP_FILES_MODIFIED_FILES) < 0)
2389 ERR("remove(%s) Fail", MTP_FILES_MODIFIED_FILES);
2391 g_mgr->meta_info.mod = 0;
2395 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
2396 num_bytes = _prop_get_size_ptparray_without_elemsize(&guid_arr);
2397 ptr = _hdlr_alloc_buf_data_container(&blk, num_bytes, num_bytes);
2400 _prop_pack_ptparray_without_elemsize(&guid_arr, ptr, num_bytes);
2401 _device_set_phase(DEVICE_PHASE_DATAIN);
2404 if (_hdlr_send_data_container(&blk))
2405 resp = PTP_RESPONSE_OK;
2407 resp = PTP_RESPONSE_GEN_ERROR;
2409 _prop_deinit_ptparray(&guid_arr);
2412 if (PTP_RESPONSE_OK == resp) {
2414 resp_param[0] = hdlr->usb_cmd.tid;
2415 resp_param[1] = rem_modified;
2417 _cmd_hdlr_send_response(hdlr, resp, 3, resp_param);
2419 _cmd_hdlr_send_response_code(hdlr, resp);
2424 static void __send_playback_skip(mtp_handler_t *hdlr)
2427 mtp_uint16 resp = PTP_RESPONSE_INVALIDPARAM;
2429 skip = (mtp_int32) _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
2430 if (MTP_ERROR_NONE == _hutil_get_playback_skip(skip))
2431 resp = PTP_RESPONSE_OK;
2433 _cmd_hdlr_send_response_code(hdlr, resp);
2438 static void __self_test(mtp_handler_t *hdlr)
2440 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
2441 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
2442 ERR("Unsupported parameters");
2443 _cmd_hdlr_send_response_code(hdlr,
2444 PTP_RESPONSE_PARAM_NOTSUPPORTED);
2448 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
2449 /* Do device-specific tests */
2450 /* After the test */
2451 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
2455 #ifdef MTP_SUPPORT_SET_PROTECTION
2456 static void __set_object_protection(mtp_handler_t *hdlr)
2458 mtp_uint32 h_obj = 0;
2459 mtp_uint16 protcn_status = 0;
2460 mtp_uint16 resp = 0;
2462 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
2463 ERR("Unsupported parameter");
2464 _cmd_hdlr_send_response_code(hdlr,
2465 PTP_RESPONSE_PARAM_NOTSUPPORTED);
2469 h_obj = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
2470 protcn_status = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
2472 if ((protcn_status != PTP_PROTECTIONSTATUS_NOPROTECTION) &&
2473 (protcn_status != PTP_PROTECTIONSTATUS_READONLY) &&
2474 (protcn_status != MTP_PROTECTIONSTATUS_READONLY_DATA) &&
2475 (protcn_status != MTP_PROTECTIONSTATUS_NONTRANSFERABLE_DATA)) {
2477 resp = PTP_RESPONSE_INVALIDPARAM;
2478 _cmd_hdlr_send_response_code(hdlr, resp);
2482 switch (_hutil_set_protection(h_obj, protcn_status)) {
2483 case MTP_ERROR_INVALID_OBJECTHANDLE:
2484 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
2486 case MTP_ERROR_OBJECT_WRITE_PROTECTED:
2487 resp = PTP_RESPONSE_OBJ_WRITEPROTECTED;
2489 case MTP_ERROR_NONE:
2490 resp = PTP_RESPONSE_OK;
2492 case MTP_ERROR_OPERATION_NOT_SUPPORTED:
2493 resp = PTP_RESPONSE_OP_NOT_SUPPORTED;
2496 resp = PTP_RESPONSE_GEN_ERROR;
2499 _cmd_hdlr_send_response_code(hdlr, resp);
2502 #endif /* MTP_SUPPORT_SET_PROTECTION */
2504 static void __power_down(mtp_handler_t *hdlr)
2506 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0) ||
2507 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
2508 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
2509 ERR("Unsupported Parameter");
2510 _cmd_hdlr_send_response_code(hdlr,
2511 PTP_RESPONSE_PARAM_NOTSUPPORTED);
2515 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
2517 _cmd_hdlr_reset_cmd(hdlr);
2521 static void __move_object(mtp_handler_t *hdlr)
2523 mtp_uint32 store_id = 0;
2524 mtp_uint32 obj_handle = 0;
2525 mtp_uint32 h_parent = 0;
2526 mtp_uint32 resp = 0;
2528 obj_handle = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
2529 store_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
2530 h_parent = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2);
2532 _transport_set_mtp_operation_state(MTP_STATE_DATA_PROCESSING);
2534 switch (_hutil_move_object_entry(store_id, h_parent, obj_handle)) {
2535 case MTP_ERROR_NONE:
2536 resp = PTP_RESPONSE_OK;
2538 case MTP_ERROR_INVALID_OBJECTHANDLE:
2539 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
2541 case MTP_ERROR_OBJECT_WRITE_PROTECTED:
2542 resp = PTP_RESPONSE_OBJ_WRITEPROTECTED;
2544 case MTP_ERROR_ACCESS_DENIED:
2545 resp = PTP_RESPONSE_ACCESSDENIED;
2547 case MTP_ERROR_STORE_NOT_AVAILABLE:
2548 resp = PTP_RESPONSE_STORENOTAVAILABLE;
2550 case MTP_ERROR_INVALID_PARENT:
2551 resp = PTP_RESPONSE_INVALIDPARENT;
2553 case MTP_ERROR_INVALID_PARAM:
2554 resp = PTP_RESPONSE_INVALIDPARAM;
2556 case MTP_ERROR_STORE_FULL:
2557 resp = PTP_RESPONSE_STOREFULL;
2560 resp = PTP_RESPONSE_GEN_ERROR;
2563 _transport_set_mtp_operation_state(MTP_STATE_ONSERVICE);
2564 _cmd_hdlr_send_response_code(hdlr, resp);
2568 static void __copy_object(mtp_handler_t *hdlr)
2570 mtp_uint32 store_id = 0;
2571 mtp_uint32 h_obj = 0;
2572 mtp_uint32 h_parent = 0;
2573 mtp_uint32 new_handle = 0;
2574 mtp_uint16 resp = 0;
2576 h_obj = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
2577 store_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
2578 h_parent = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2);
2580 _transport_set_mtp_operation_state(MTP_STATE_DATA_PROCESSING);
2582 switch (_hutil_duplicate_object_entry(store_id, h_parent, h_obj,
2584 case MTP_ERROR_INVALID_OBJECTHANDLE:
2585 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
2587 case MTP_ERROR_OBJECT_WRITE_PROTECTED:
2588 resp = PTP_RESPONSE_OBJ_WRITEPROTECTED;
2590 case MTP_ERROR_STORE_NOT_AVAILABLE:
2591 resp = PTP_RESPONSE_STORENOTAVAILABLE;
2593 case MTP_ERROR_STORE_READ_ONLY:
2594 resp = PTP_RESPONSE_STORE_READONLY;
2596 case MTP_ERROR_INVALID_PARENT:
2597 resp = PTP_RESPONSE_INVALIDPARENT;
2599 case MTP_ERROR_INVALID_PARAM:
2600 resp = PTP_RESPONSE_INVALIDPARAM;
2602 case MTP_ERROR_STORE_FULL:
2603 resp = PTP_RESPONSE_STOREFULL;
2605 case MTP_ERROR_NONE:
2606 resp = PTP_RESPONSE_OK;
2608 case MTP_ERROR_ACCESS_DENIED:
2609 resp = PTP_RESPONSE_ACCESSDENIED;
2612 resp = PTP_RESPONSE_GEN_ERROR;
2614 _transport_set_mtp_operation_state(MTP_STATE_ONSERVICE);
2616 if (resp == PTP_RESPONSE_OK)
2617 _cmd_hdlr_send_response(hdlr, resp, 1, &new_handle);
2619 _cmd_hdlr_send_response_code(hdlr, resp);
2624 static void __reset_device_prop_value(mtp_handler_t *hdlr)
2626 mtp_uint32 prop_id = 0;
2627 device_prop_desc_t *prop = NULL;
2628 mtp_char temp[MTP_MAX_REG_STRING * 3 + 1] = { 0 };
2630 prop_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
2632 if (MTP_ERROR_NONE != _hutil_reset_device_entry(prop_id)) {
2633 _cmd_hdlr_send_response_code(hdlr,
2634 PTP_RESPONSE_PROP_NOTSUPPORTED);
2638 if (MTP_PROPERTYCODE_DEVICEFRIENDLYNAME == prop_id) {
2639 prop = _device_get_device_property(prop_id);
2641 _cmd_hdlr_send_response_code(hdlr,
2642 PTP_RESPONSE_PROP_NOTSUPPORTED);
2646 _util_utf16_to_utf8(temp, sizeof(temp),
2647 prop->current_val.str->str);
2648 _device_set_device_name(temp);
2650 } else if (MTP_PROPERTYCODE_SYNCHRONIZATIONPARTNER == prop_id) {
2651 prop = _device_get_device_property(prop_id);
2653 _cmd_hdlr_send_response_code(hdlr,
2654 PTP_RESPONSE_PROP_NOTSUPPORTED);
2658 _util_utf16_to_utf8(temp, sizeof(temp),
2659 prop->current_val.str->str);
2660 _device_set_sync_partner(temp);
2662 if (!g_strcmp0(temp, MTP_DEV_PROPERTY_NULL_SYNCPARTNER))
2663 vconf_set_str(VCONFKEY_MTP_SYNC_PARTNER_STR, "");
2665 vconf_set_str(VCONFKEY_MTP_SYNC_PARTNER_STR, temp);
2667 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
2672 /* Vendor-specific operations */
2673 #define GET_DEVICEPC_NAME 1
2674 static void __vendor_command1(mtp_handler_t *hdlr)
2676 switch (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0)) {
2677 case GET_DEVICEPC_NAME:
2682 /* Vendor command not properly handled*/
2683 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
2687 static void __get_interdep_prop_desc(mtp_handler_t *hdlr)
2690 data_blk_t blk = { 0 };
2691 mtp_uint32 num_bytes = 0;
2692 mtp_uchar *ptr = NULL;
2694 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
2695 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
2696 _cmd_hdlr_send_response_code(hdlr,
2697 PTP_RESPONSE_PARAM_NOTSUPPORTED);
2701 fmt = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
2702 if (0x0 == fmt || 0xFFFFFFFF == fmt) {
2703 ERR("Invalid format code");
2704 _cmd_hdlr_send_response_code(hdlr,
2705 PTP_RESPONSE_INVALIDCODEFORMAT);
2709 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
2710 _hutil_get_interdep_prop_config_list_size(&num_bytes, fmt);
2711 ptr = _hdlr_alloc_buf_data_container(&blk, num_bytes, num_bytes);
2713 if (MTP_ERROR_NONE != _hutil_get_interdep_prop_config_list_data(ptr,
2715 ERR("_hutil_get_interdep_prop_config_list_data() Fail");
2716 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR);
2721 _device_set_phase(DEVICE_PHASE_DATAIN);
2722 if (_hdlr_send_data_container(&blk)) {
2723 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
2725 /*Host Cancelled data-in transfer*/
2726 _device_set_phase(DEVICE_PHASE_NOTREADY);
2734 * void __cmd_hdlr_send_object_prop_list(mtp_handler_t *hdlr)
2735 * This function is used as an alternative first operation when the initiator
2736 * wants to send an object to the responder. This operation sends a
2737 * modified ObjectPropList dataset from the initiator to the Responder.
2741 static void __send_object_prop_list(mtp_handler_t *hdlr)
2744 mtp_uint16 resp = PTP_RESPONSE_OK;
2745 mtp_uint32 resp_param[MAX_MTP_PARAMS] = { 0 };
2746 mtp_obj_t *obj = NULL;
2748 mtp_uint64 f_size = 0;
2749 mtp_uint64 fsize_hbits = 0;
2750 mtp_uint32 store_id;
2751 mtp_uint32 h_parent;
2752 data_blk_t blk = { 0 };
2753 mtp_uint32 max_bytes = 0;
2755 obj_data_t objdata = { 0 };
2757 store_id = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0);
2758 h_parent = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1);
2759 fmt = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2);
2760 fsize_hbits = _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 3);
2762 f_size = (fsize_hbits << 32) + _hdlr_get_param_cmd_container
2763 (&(hdlr->usb_cmd), 4);
2765 _device_set_phase(DEVICE_PHASE_DATAOUT);
2766 _hdlr_init_data_container(&blk, hdlr->usb_cmd.code, hdlr->usb_cmd.tid);
2768 max_bytes = MTP_MAX_METADATA;
2769 if (FALSE == _hdlr_rcv_data_container(&blk, max_bytes)) {
2770 _device_set_phase(DEVICE_PHASE_IDLE);
2771 ERR("_hdlr_rcv_data_container() Fail");
2772 resp = PTP_RESPONSE_GEN_ERROR;
2778 h_parent = _device_get_default_parent_handle();
2779 else if (h_parent == 0xFFFFFFFF)
2780 h_parent = PTP_OBJECTHANDLE_ROOT;
2782 store_id = _device_get_default_store_id();
2784 resp = PTP_RESPONSE_STORENOTAVAILABLE;
2786 /* If the second parameter is used, the first must
2789 resp = PTP_RESPONSE_PARAM_NOTSUPPORTED;
2791 h_parent = _device_get_default_parent_handle();
2794 if (f_size >= MTP_FILESIZE_4GB) {
2796 mtp_store_t *store = NULL;
2797 struct statfs buf = { 0 };
2800 store = _device_get_store(store_id);
2801 if (store == NULL) {
2802 ERR("Store Not Available");
2803 resp = PTP_RESPONSE_STORENOTAVAILABLE;
2805 DBG("StorePath = [%s]\n", store->root_path);
2806 ret = statfs(store->root_path, &buf);
2807 if (ret < 0 || buf.f_type == MSDOS_SUPER_MAGIC) {
2808 ERR("File System does not support files over 4gb");
2809 resp = MTP_RESPONSE_OBJECT_TOO_LARGE;
2814 if (PTP_RESPONSE_OK == resp) {
2816 mtp_uchar *data = NULL;
2818 if (TRUE == hdlr->data4_send_obj.is_valid) {
2820 objdata.store_id = hdlr->data4_send_obj.store_id;
2821 objdata.obj_size = hdlr->data4_send_obj.file_size;
2822 objdata.obj = hdlr->data4_send_obj.obj;
2823 hdlr->data4_send_obj.obj = NULL;
2826 data = _hdlr_get_payload_data(&blk);
2832 ret = _hutil_construct_object_entry_prop_list(store_id, h_parent,
2833 fmt, f_size, ((hdlr->data4_send_obj.is_valid == TRUE) ?
2834 (&objdata) : (NULL)), &obj, data,
2835 _hdlr_get_payload_size(&blk), &idx);
2836 hdlr->data4_send_obj.is_valid = FALSE;
2839 case MTP_ERROR_INVALID_STORE:
2840 resp = PTP_RESPONSE_INVALID_STORE_ID;
2842 case MTP_ERROR_STORE_READ_ONLY:
2843 resp = PTP_RESPONSE_STORE_READONLY;
2845 case MTP_ERROR_STORE_FULL:
2846 resp = PTP_RESPONSE_STOREFULL;
2848 case MTP_ERROR_GENERAL:
2849 resp = PTP_RESPONSE_GEN_ERROR;
2851 case MTP_ERROR_INVALID_DATASET:
2852 resp = MTP_RESPONSECODE_INVALIDDATASET;
2854 case MTP_ERROR_INVALID_OBJECTHANDLE:
2855 resp = PTP_RESPONSE_INVALID_OBJ_HANDLE;
2857 case MTP_ERROR_INVALID_OBJ_PROP_CODE:
2858 resp = MTP_RESPONSE_INVALIDOBJPROPCODE;
2860 case MTP_ERROR_INVALID_OBJECT_PROP_FORMAT:
2861 resp = MTP_RESPONSE_INVALIDOBJPROPFORMAT;
2863 case MTP_ERROR_INVALID_OBJ_PROP_VALUE:
2864 resp = MTP_RESPONSE_INVALIDOBJPROPVALUE;
2866 case MTP_ERROR_INVALID_PARENT:
2867 resp = PTP_RESPONSE_INVALIDPARENT;
2869 case MTP_ERROR_ACCESS_DENIED:
2870 resp = PTP_RESPONSE_ACCESSDENIED;
2872 case MTP_ERROR_NONE:
2873 #ifdef MTP_USE_SELFMAKE_ABSTRACTION
2874 if ((obj->obj_info->obj_fmt == PTP_FMT_ASSOCIATION) ||
2875 (obj->obj_info->file_size == 0 &&
2876 obj->obj_info->obj_fmt >
2877 MTP_FMT_UNDEFINED_COLLECTION &&
2878 obj->obj_info->obj_fmt <
2879 MTP_FMT_UNDEFINED_DOC))
2880 #else /*MTP_USE_SELFMAKE_ABSTRACTION*/
2881 if (obj->obj_info->obj_fmt == PTP_FMT_ASSOCIATION)
2882 #endif /*MTP_USE_SELFMAKE_ABSTRACTION*/
2884 hdlr->data4_send_obj.obj = NULL;
2885 hdlr->data4_send_obj.is_valid = FALSE;
2886 hdlr->data4_send_obj.obj_handle = obj->obj_handle;
2887 hdlr->data4_send_obj.h_parent = h_parent;
2888 hdlr->data4_send_obj.store_id = store_id;
2889 hdlr->data4_send_obj.file_size = 0;
2891 hdlr->data4_send_obj.is_valid = TRUE;
2892 hdlr->data4_send_obj.obj_handle = obj->obj_handle;
2893 hdlr->data4_send_obj.h_parent = h_parent;
2894 hdlr->data4_send_obj.store_id = store_id;
2895 hdlr->data4_send_obj.obj = obj;
2896 hdlr->data4_send_obj.file_size =
2897 obj->obj_info->file_size;
2899 resp = PTP_RESPONSE_OK;
2902 resp = PTP_RESPONSE_GEN_ERROR;
2906 if (PTP_RESPONSE_OK != resp) {
2907 if (hdlr->data4_send_obj.obj)
2908 _entity_dealloc_mtp_obj(hdlr->data4_send_obj.obj);
2910 hdlr->data4_send_obj.obj = NULL;
2911 hdlr->data4_send_obj.is_valid = FALSE;
2912 resp_param[3] = idx;
2914 resp_param[0] = hdlr->data4_send_obj.store_id;
2916 /* PTP spec here requires that 0xFFFFFFFF be sent if root is the parent,
2917 * while in some situations (e.g. Move Object, Copy Object), 0x00000000
2918 *(as PTP_OBJECTHANDLE_ROOT is defined) represents the root
2920 resp_param[1] = (hdlr->data4_send_obj.h_parent !=
2921 PTP_OBJECTHANDLE_ROOT) ? hdlr->data4_send_obj.h_parent
2923 resp_param[2] = hdlr->data4_send_obj.obj_handle;
2927 _cmd_hdlr_send_response(hdlr, resp, 4, resp_param);
2934 void __close_session(mtp_handler_t *hdlr)
2936 if (_hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 0) ||
2937 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 1) ||
2938 _hdlr_get_param_cmd_container(&(hdlr->usb_cmd), 2)) {
2940 ERR("PTP_RESPONSE_PARAM_NOTSUPPORTED");
2941 _cmd_hdlr_send_response_code(hdlr,
2942 PTP_RESPONSE_PARAM_NOTSUPPORTED);
2947 if (hdlr->session_id) {
2948 hdlr->session_id = 0;
2949 _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_OK);
2951 _cmd_hdlr_send_response_code(hdlr,
2952 PTP_RESPONSE_SESSIONNOTOPEN);
2953 ERR("PTP_RESPONSE_SESSIONNOTOPEN");
2957 /* LCOV_EXCL_STOP */
2959 mtp_bool _cmd_hdlr_send_response(mtp_handler_t *hdlr, mtp_uint16 resp,
2960 mtp_uint32 num_param, mtp_uint32 *params)
2962 mtp_bool ret = FALSE;
2963 resp_blk_t blk = { 0 };
2967 /* LCOV_EXCL_START */
2968 _hdlr_resp_container_init(&blk, resp, hdlr->usb_cmd.tid);
2970 ret = _hdlr_add_param_resp_container(&blk, num_param, params);
2972 _device_set_phase(DEVICE_PHASE_RESPONSE);
2973 ret = _hdlr_send_resp_container(&blk);
2974 _device_set_phase(DEVICE_PHASE_IDLE);
2976 if ((resp == PTP_RESPONSE_OK) && (ret == TRUE)) {
2977 DBG("[%s], Opcode[0x%4x], ResponseCode[0x%4x], NumParams[%d]\n",
2978 "SUCCESS", hdlr->usb_cmd.code, resp, num_param);
2980 ERR("[%s], Opcode = [0x%4x] ResponseCode[0x%4x], NumParams[%u]\n",
2981 "FAIL", hdlr->usb_cmd.code, resp, num_param);
2983 /* LCOV_EXCL_STOP */
2987 mtp_bool _cmd_hdlr_send_response_code(mtp_handler_t *hdlr, mtp_uint16 resp)
2989 return _cmd_hdlr_send_response(hdlr, resp, 0, NULL);
2992 /* LCOV_EXCL_START */
2993 #ifdef MTP_SUPPORT_PRINT_COMMAND
2994 static void __print_command(mtp_uint16 code)
2997 case PTP_OPCODE_GETDEVICEINFO:
2998 DBG("COMMAND ======== GET DEVICE INFO===========");
3000 case PTP_OPCODE_OPENSESSION:
3001 DBG("COMMAND ======== OPEN SESSION ===========");
3003 case PTP_OPCODE_CLOSESESSION:
3004 DBG("COMMAND ======== CLOSE SESSION ===========");
3006 case PTP_OPCODE_GETSTORAGEIDS:
3007 DBG("COMMAND ======== GET STORAGE IDS ===========");
3009 case PTP_OPCODE_GETSTORAGEINFO:
3010 DBG("COMMAND ======== GET STORAGE INFO ===========");
3012 case PTP_OPCODE_GETNUMOBJECTS:
3013 DBG("COMMAND ======== GET NUM OBJECTS ===========");
3015 case PTP_OPCODE_GETOBJECTHANDLES:
3016 DBG("COMMAND ======== GET OBJECT HANDLES ===========");
3018 case PTP_OPCODE_GETOBJECTINFO:
3019 DBG("COMMAND ======== GET OBJECT INFO ===========");
3021 case PTP_OPCODE_GETOBJECT:
3022 DBG("COMMAND ======== GET OBJECT ===========");
3024 case PTP_OPCODE_DELETEOBJECT:
3025 DBG("COMMAND ======== DELETE OBJECT ===========");
3027 case PTP_OPCODE_SENDOBJECTINFO:
3028 DBG("COMMAND ======== SEND OBJECT INFO ===========");
3030 case PTP_OPCODE_SENDOBJECT:
3031 DBG("COMMAND ======== SEND OBJECT ===========");
3033 case PTP_OPCODE_INITIATECAPTURE:
3034 DBG("COMMAND ======== INITIATE CAPTURE ===========");
3036 case PTP_OPCODE_FORMATSTORE:
3037 DBG("COMMAND ======== FORMAT STORE ===========");
3039 case PTP_OPCODE_RESETDEVICE:
3040 DBG("COMMAND ======== RESET DEVICE ===========");
3042 case PTP_OPCODE_SELFTEST:
3043 DBG("COMMAND ======== SELF TEST ===========");
3045 case PTP_OPCODE_SETOBJECTPROTECTION:
3046 DBG("COMMAND ======== SET OBJECT PROTECTION ===========");
3048 case PTP_OPCODE_POWERDOWN:
3049 DBG("COMMAND ======== POWER DOWN ===========");
3051 case PTP_OPCODE_GETDEVICEPROPDESC:
3052 DBG("COMMAND ======== GET DEVICE PROP DESC ===========");
3054 case PTP_OPCODE_GETDEVICEPROPVALUE:
3055 DBG("COMMAND ======== GET DEVICE PROP VALUE ===========");
3057 case PTP_OPCODE_SETDEVICEPROPVALUE:
3058 DBG("COMMAND ======== SET DEVICE PROP VALUE ===========");
3060 case PTP_OPCODE_RESETDEVICEPROPVALUE:
3061 DBG("COMMAND ======== RESET DEVICE PROP VALUE ===========");
3063 case PTP_OPCODE_TERMINATECAPTURE:
3064 DBG("COMMAND ======== TERMINATE CAPTURE ===========");
3066 case PTP_OPCODE_MOVEOBJECT:
3067 DBG("COMMAND ======== MOVE OBJECT ===========");
3069 case PTP_OPCODE_COPYOBJECT:
3070 DBG("COMMAND ======== COPY OBJECT ===========");
3072 case PTP_OPCODE_GETPARTIALOBJECT:
3073 DBG("COMMAND ======== GET PARTIAL OBJECT ===========");
3075 case PTP_OPCODE_INITIATEOPENCAPTURE:
3076 DBG("COMMAND ======== INITIATE OPEN CAPTURE ===========");
3078 case MTP_OPCODE_WMP_UNDEFINED:
3079 DBG("COMMAND ======== WMP UNDEFINED ==========");
3081 case MTP_OPCODE_WMP_REPORTACQUIREDCONTENT:
3082 DBG("COMMAND ======= REPORT ACQUIRED CONTENT =========");
3084 case MTP_OPCODE_GETOBJECTPROPSUPPORTED:
3085 DBG("COMMAND ======= GET OBJECT PROP SUPPORTED ========");
3087 case MTP_OPCODE_GETOBJECTPROPDESC:
3088 DBG("COMMAND ======== GET OBJECT PROP DESC ==========");
3090 case MTP_OPCODE_GETOBJECTPROPVALUE:
3091 DBG("COMMAND ======== GET OBJECT PROP VALUE ==========");
3093 case MTP_OPCODE_SETOBJECTPROPVALUE:
3094 DBG("COMMAND ======== SET OBJECT PROP VALUE ==========");
3096 case MTP_OPCODE_GETOBJECTPROPLIST:
3097 DBG("COMMAND ======== GET OBJECT PROP LIST ==========");
3099 case MTP_OPCODE_SETOBJECTPROPLIST:
3100 DBG("COMMAND ======== SET OBJECT PROP LIST ==========");
3102 case MTP_OPCODE_GETINTERDEPPROPDESC:
3103 DBG("COMMAND ======== GET INTERDEP PROP DESC ==========");
3105 case MTP_OPCODE_SENDOBJECTPROPLIST:
3106 DBG("COMMAND ======== SEND OBJECT PROP LIST ==========");
3108 case MTP_OPCODE_GETOBJECTREFERENCES:
3109 DBG("COMMAND ======== GET OBJECT REFERENCES ==========");
3111 case MTP_OPCODE_SETOBJECTREFERENCES:
3112 DBG("COMMAND ======== SET OBJECT REFERENCES ==========");
3114 case MTP_OPCODE_PLAYBACK_SKIP:
3115 DBG("COMMAND ======== PLAYBACK SKIP ==========");
3118 DBG("======== UNKNOWN COMMAND ==========");
3124 #endif /*MTP_SUPPORT_PRINT_COMMAND*/
3126 static void __enum_store_not_enumerated(mtp_uint32 obj_handle,
3127 mtp_uint32 fmt, mtp_uint32 depth)
3130 mtp_store_t *store = NULL;
3131 mtp_obj_t *obj = NULL;
3133 if (TRUE == g_is_full_enum) {
3134 DBG("Full Enumeration has been already done");
3138 DBG("obj_handle = [%u], format =[ %u], depth = [%u]\n", obj_handle,
3140 if (obj_handle == PTP_OBJECTHANDLE_ALL || obj_handle == PTP_OBJECTHANDLE_ROOT) {
3141 for (ii = 0; ii < _device_get_num_stores(); ii++) {
3142 store = _device_get_store_at_index(ii);
3143 if (store && store->obj_list.nnodes == 0)
3144 _entity_store_recursive_enum_folder_objects(store, NULL);
3146 g_is_full_enum = TRUE;
3147 } else if (obj_handle != PTP_OBJECTHANDLE_ROOT) {
3148 store = _device_get_store_containing_obj(obj_handle);
3149 obj = _entity_get_object_from_store(store, obj_handle);
3151 ERR("pObject is NULL");
3154 _entity_store_recursive_enum_folder_objects(store, obj);
3159 void _receive_mq_data_cb(mtp_char *buffer, mtp_int32 buf_len)
3161 cmd_blk_t cmd = { 0 };
3162 mtp_uint32 rx_size = _get_rx_pkt_size();
3164 if (_transport_get_mtp_operation_state() < MTP_STATE_READY_SERVICE) {
3165 ERR("MTP is stopped or initializing. ignore all");
3169 #ifdef MTP_SUPPORT_CONTROL_REQUEST
3170 /* process control request */
3171 switch (_transport_get_control_event()) {
3172 case PTP_EVENTCODE_CANCELTRANSACTION:
3173 DBG("PTP_EVENTCODE_CANCELTRANSACTION, just change state to IDLE");
3174 _transport_set_control_event(PTP_EVENTCODE_CANCELTRANSACTION);
3175 _device_set_phase(DEVICE_PHASE_IDLE);
3176 if ((buf_len == rx_size) ||
3177 (buf_len < sizeof(header_container_t))) {
3178 DBG("Cancelling Transaction. data length [%d]\n",
3180 _transport_set_control_event(PTP_EVENTCODE_CANCELTRANSACTION);
3185 cmd_container_t *tmp;
3194 for (i = 0; i < MAX_MTP_PARAMS; i++) { /* check size */
3195 /* check number of parameter */
3196 tmp = (cmd_container_t *)&buffer[buf_len -
3197 sizeof(header_container_t) -
3198 sizeof(mtp_dword) * i];
3203 if ((len == sizeof(header_container_t)
3204 + sizeof(mtp_dword) * i) &&
3205 (type == CONTAINER_CMD_BLK)) {
3206 DBG("Found Command in remaining data");
3207 memcpy(buffer, tmp, len);
3211 DBG("Not found command, length[%lu]\n", len);
3219 DBG("len[%lu], type[0x%x], code [0x%x], trid[0x%lu]\n",
3220 len, type, code, trid);
3222 if (_hdlr_validate_cmd_container((mtp_byte *)tmp, len)
3224 ERR("Cancelling Transaction, invalid header, but last packet");
3225 } else { /*another command, cancelling is finished*/
3226 DBG("Cancelling Transaction, Finished.");
3229 _transport_set_control_event(0);
3230 _transport_set_mtp_operation_state(MTP_STATE_ONSERVICE);
3231 if (g_mgr->ftemp_st.fhandle != NULL) {
3232 DBG("In Cancel Transaction fclose ");
3233 _util_file_close(g_mgr->ftemp_st.fhandle);
3234 g_mgr->ftemp_st.fhandle = NULL;
3235 DBG("In Cancel Transaction, remove ");
3236 if (remove(g_mgr->ftemp_st.filepath) < 0)
3237 ERR_SECURE("remove(%s) Fail", g_mgr->ftemp_st.filepath);
3239 DBG("g_mgr->ftemp_st.fhandle is not valid, return");
3243 case PTP_EVENTCODE_DEVICERESET:
3244 DBG("Implement later, PTP_EVENTCODE_DEVICERESET");
3245 _device_set_phase(DEVICE_PHASE_IDLE);
3246 /* do close session, just skip save reference
3247 * mtp_save_object_references_mtp_device(MtpHandler.pDevice);
3249 g_mgr->hdlr.session_id = 0;
3250 _transport_set_control_event(0);
3251 _transport_set_mtp_operation_state(MTP_STATE_ONSERVICE);
3257 #endif/* MTP_SUPPORT_CONTROL_REQUEST */
3259 /* main processing */
3260 if (_device_get_phase() == DEVICE_PHASE_IDLE) {
3261 if (_hdlr_validate_cmd_container((mtp_uchar *)buffer, buf_len)
3263 _device_set_phase(DEVICE_PHASE_NOTREADY);
3264 ERR("MTP device phase NOT READY, invalid Command block");
3268 _transport_save_cmd_buffer(buffer, buf_len);
3269 _hdlr_copy_cmd_container_unknown_params((cmd_container_t *)buffer,
3271 #ifdef __BIG_ENDIAN__
3272 _hdlr_conv_cmd_container_byte_order(&cmd);
3273 #endif /* __BIG_ENDIAN__ */
3275 UTIL_LOCK_MUTEX(&g_cmd_inoti_mutex);
3276 __process_commands(&g_mtp_mgr.hdlr, &cmd);
3277 UTIL_UNLOCK_MUTEX(&g_cmd_inoti_mutex);
3278 } else if (_device_get_phase() == DEVICE_PHASE_DATAOUT) {
3279 if (g_mgr->ftemp_st.data_count == 0)
3280 __receive_temp_file_first_packet(buffer, buf_len);
3282 __receive_temp_file_next_packets(buffer, buf_len);
3285 /* ignore other case */
3286 ERR("MTP device phase[%d], unknown device PHASE\n",
3287 _device_get_phase());
3288 ERR("PhaseUnknown-> pData[0x%p], length=[%d]", buffer, buf_len);
3289 _device_set_phase(DEVICE_PHASE_IDLE);
3290 _transport_set_mtp_operation_state(MTP_STATE_ONSERVICE);
3295 static mtp_bool __receive_temp_file_first_packet(mtp_char *data,
3298 temp_file_struct_t *t = &g_mgr->ftemp_st;
3299 mtp_int32 error = 0;
3300 mtp_uint32 *data_sz = &g_mgr->ftemp_st.data_size;
3301 mtp_char *buffer = g_mgr->ftemp_st.temp_buff;
3302 mtp_char buff[LEN], *ptr;
3303 mtp_char filename[MTP_MAX_FILENAME_SIZE] = {0};
3304 mtp_uint32 i, num, start, range;
3307 _transport_set_mtp_operation_state(MTP_STATE_DATA_TRANSFER_DL);
3308 if (!g_is_send_object) {
3309 /*create a unique filename for /tmp/.mtptemp.tmp only if
3310 is_send_object = 0. If is_send_object = 0 implies t->filepath
3311 is set in send_object_proplist command to receive the
3317 for (ptr = buff, i = 1; i < LEN; ++ptr, ++i) {
3318 num = rand_r(&seed) % range;
3323 g_snprintf(filename, MTP_MAX_FILENAME_SIZE, "%s%s%s", "/tmp/.mtptemp", buff, ".tmp");
3325 if (t->filepath != NULL) {
3326 g_free(t->filepath);
3330 t->filepath = g_strdup(filename);
3333 DBG("t->filepath :%s\n", t->filepath);
3335 if (access(t->filepath, F_OK) == 0) {
3336 if (g_mgr->ftemp_st.fhandle != NULL) {
3337 _util_file_close(g_mgr->ftemp_st.fhandle);
3338 g_mgr->ftemp_st.fhandle = NULL; /* initialize */
3341 if (remove(t->filepath) < 0) {
3342 ERR_SECURE("remove(%s) Fail", t->filepath);
3343 __finish_receiving_file_packets(data, data_len);
3348 g_mgr->ftemp_st.fhandle = _util_file_open(t->filepath, MTP_FILE_WRITE, &error);
3349 if (g_mgr->ftemp_st.fhandle == NULL) {
3350 ERR("First file handle is invalid!!");
3351 __finish_receiving_file_packets(data, data_len);
3354 /* consider header size */
3355 memcpy(&g_mgr->ftemp_st.header_buf, data, sizeof(header_container_t));
3357 g_mgr->ftemp_st.file_size = ((header_container_t *)data)->len -
3358 sizeof(header_container_t);
3359 *data_sz = data_len - sizeof(header_container_t);
3361 /* check whether last data packet */
3362 if (*data_sz == g_mgr->ftemp_st.file_size) {
3363 if (_util_file_write(g_mgr->ftemp_st.fhandle, &data[sizeof(header_container_t)],
3364 data_len - sizeof(header_container_t)) !=
3365 data_len - sizeof(header_container_t)) {
3366 ERR("fwrite error!");
3369 _util_file_close(g_mgr->ftemp_st.fhandle);
3370 g_mgr->ftemp_st.fhandle = NULL; /* initialize */
3371 __finish_receiving_file_packets(data, data_len);
3373 g_mgr->ftemp_st.data_count++;
3374 g_mgr->ftemp_st.size_remaining = *data_sz;
3376 memcpy(buffer, data + sizeof(header_container_t), *data_sz);
3381 static mtp_bool __receive_temp_file_next_packets(mtp_char *data,
3384 mtp_uint32 rx_size = _get_rx_pkt_size();
3385 mtp_uint32 *data_sz = &g_mgr->ftemp_st.data_size;
3386 mtp_char *buffer = g_mgr->ftemp_st.temp_buff;
3388 g_mgr->ftemp_st.data_count++;
3389 g_mgr->ftemp_st.size_remaining += data_len;
3391 if ((*data_sz + (mtp_uint32)data_len) > g_conf.write_file_size) {
3392 /* copy oversized packet to temp file */
3393 if (_util_file_write(g_mgr->ftemp_st.fhandle, buffer, *data_sz) != *data_sz)
3394 ERR("fwrite error writeSize=[%u]\n", *data_sz);
3399 memcpy(&buffer[*data_sz], data, data_len);
3400 *data_sz += data_len;
3402 /*Complete file is recieved, so close the file*/
3403 if (data_len < rx_size ||
3404 g_mgr->ftemp_st.size_remaining == g_mgr->ftemp_st.file_size) {
3406 if (_util_file_write(g_mgr->ftemp_st.fhandle, buffer, *data_sz) != *data_sz)
3407 ERR("fwrite error write size=[%u]\n", *data_sz);
3410 _util_file_close(g_mgr->ftemp_st.fhandle);
3411 g_mgr->ftemp_st.fhandle = NULL;
3412 __finish_receiving_file_packets(data, data_len);
3417 static void __finish_receiving_file_packets(mtp_char *data, mtp_int32 data_len)
3419 cmd_blk_t cmd = { 0 };
3420 mtp_uchar *cmd_buf = NULL;
3422 g_mgr->ftemp_st.data_count = 0;
3423 cmd_buf = (mtp_uchar *)data;
3425 if (!_hdlr_validate_cmd_container(cmd_buf, (mtp_uint32)data_len)) {
3426 cmd_buf = (mtp_uchar *)g_mgr->ftemp_st.cmd_buf;
3427 if (!_hdlr_validate_cmd_container(cmd_buf,
3428 g_mgr->ftemp_st.cmd_size)) {
3429 _device_set_phase(DEVICE_PHASE_IDLE);
3430 ERR("DATA PROCESS, device phase[%d], invalid Command\
3431 block\n", _device_get_phase());
3436 _transport_set_mtp_operation_state(MTP_STATE_ONSERVICE);
3437 _hdlr_copy_cmd_container_unknown_params((cmd_container_t *)cmd_buf,
3440 #ifdef __BIG_ENDIAN__
3441 _hdlr_conv_cmd_container_byte_order(&cmd);
3442 #endif /* __BIG_ENDIAN__ */
3444 UTIL_LOCK_MUTEX(&g_cmd_inoti_mutex);
3445 __process_commands(&g_mtp_mgr.hdlr, &cmd);
3446 UTIL_UNLOCK_MUTEX(&g_cmd_inoti_mutex);
3448 DBG("MTP device phase[%d], processing Command is complete\n",
3449 _device_get_phase());
3453 /* LCOV_EXCL_STOP */