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.
19 #include "mtp_config.h"
20 #include "mtp_transport.h"
21 #include "mtp_support.h"
23 #include "ptp_datacodes.h"
24 #include "mtp_device.h"
26 #include "mtp_cmd_handler.h"
27 #include "mtp_thread.h"
28 #include "mtp_usb_driver.h"
31 * GLOBAL AND EXTERN VARIABLES
33 extern mtp_config_t g_conf;
34 extern mtp_mgr_t g_mtp_mgr;
39 static mtp_mgr_t *g_mgr = &g_mtp_mgr;
40 static mtp_bool g_usb_threads_created = FALSE;
41 static pthread_t g_tx_thrd = 0;
42 static pthread_t g_rx_thrd = 0;
43 static pthread_t g_data_rcv = 0;
44 static msgq_id_t mtp_to_usb_mqid;
45 static msgq_id_t g_usb_to_mtp_mqid;
46 static status_info_t g_status;
51 static void *__transport_thread_data_rcv(void *func);
52 static mtp_err_t __transport_init_io();
53 static void __transport_deinit_io();
58 void _transport_save_cmd_buffer(mtp_char *buffer, mtp_uint32 size)
60 memcpy(g_mgr->ftemp_st.cmd_buf, buffer, size);
61 g_mgr->ftemp_st.cmd_size = size;
62 g_mgr->ftemp_st.data_count = 0;
66 mtp_err_t _transport_rcv_temp_file_data(mtp_byte *buffer, mtp_uint32 size,
74 h_file = _util_file_open(g_mgr->ftemp_st.filepath,
75 MTP_FILE_READ, &error);
77 DBG_SECURE("_util_file_open(%s) Fail", g_mgr->ftemp_st.filepath);
78 return MTP_ERROR_NONE;
82 memcpy(buffer, g_mgr->ftemp_st.header_buf,
83 sizeof(header_container_t));
86 data_sz = size - sizeof(header_container_t);
87 _util_file_read(h_file, &buffer[sizeof(header_container_t)],
90 ERR("file read error expected [%u] actual [%u]\n",
94 *count += sizeof(header_container_t);
96 if (_util_file_close(h_file) != 0) {
97 ERR("_util_file_close Fail");
101 /* delete temp file, it have to be called in receive_data fn */
102 if (remove(g_mgr->ftemp_st.filepath) < 0) {
103 ERR_SECURE("remove(%s) Fail", g_mgr->ftemp_st.filepath);
107 g_mgr->ftemp_st.data_size = 0;
108 g_mgr->ftemp_st.data_count = 0;
110 return MTP_ERROR_NONE;
113 mtp_err_t _transport_rcv_temp_file_info(mtp_byte *buf, char *filepath,
114 mtp_uint64 *t_size, mtp_uint32 filepath_len)
116 file_attr_t atttrs = { 0 };
117 mtp_bool ret = FALSE;
119 memcpy(buf, g_mgr->ftemp_st.header_buf,
120 sizeof(header_container_t));
122 ret = _util_get_file_attrs(g_mgr->ftemp_st.filepath, &atttrs);
124 ERR_SECURE("_util_get_file_attrs(%s) Fail", g_mgr->ftemp_st.filepath);
125 return MTP_ERROR_GENERAL;
128 *t_size = sizeof(header_container_t) + atttrs.fsize;
129 g_strlcpy(filepath, g_mgr->ftemp_st.filepath, filepath_len);
131 g_mgr->ftemp_st.data_size = 0;
132 g_mgr->ftemp_st.data_count = 0;
134 g_strlcpy(g_mgr->ftemp_st.filepath, MTP_TEMP_FILE_DEFAULT,
135 MTP_MAX_PATHNAME_SIZE + 1);
136 g_mgr->ftemp_st.fhandle = NULL;
137 g_mgr->ftemp_st.file_size = 0;
139 return MTP_ERROR_NONE;
142 mtp_err_t _transport_send_event(mtp_byte *buf, mtp_uint32 size,
145 mtp_bool resp = FALSE;
146 msgq_ptr_t pkt = { 0 };
148 retv_if(buf == NULL, MTP_ERROR_INVALID_PARAM);
149 retvm_if(size > _get_tx_pkt_size(), MTP_ERROR_INVALID_PARAM,
150 "size = %d, _get_tx_pkt_size() = (%d)", size, _get_tx_pkt_size());
152 pkt.mtype = MTP_EVENT_PACKET;
156 pkt.buffer = (mtp_uchar *)g_malloc(size);
157 if (NULL == pkt.buffer) {
158 ERR("g_malloc() Fail");
159 return MTP_ERROR_GENERAL;
161 memcpy(pkt.buffer, buf, size);
162 resp = _util_msgq_send(mtp_to_usb_mqid, (void *)&pkt,
163 sizeof(msgq_ptr_t) - sizeof(long), 0);
165 ERR("_util_msgq_send() Fail");
166 return MTP_ERROR_GENERAL;
170 return MTP_ERROR_NONE;
174 * This function writes data to Message Queue, which will be read by a thread.
175 * the thread will write message, read from MQ, on USB.
176 * @param buf [in] A pointer to data written.
177 * @param pkt_len [in] Specifies the number of bytes to write.
178 * @return This function returns length of written data in bytes
180 mtp_uint32 _transport_send_pkt_to_tx_mq(const mtp_byte *buf,
184 mtp_uint32 len = pkt_len;
185 mtp_uint32 sent_len = 0;
186 msgq_ptr_t pkt = { 0 };
187 mtp_uint32 tx_size = _get_tx_pkt_size();
188 const mtp_uchar *temp = (const mtp_uchar *)buf;
190 retv_if(buf == NULL, 0);
191 retv_if(pkt_len == 0, 0);
193 pkt.mtype = MTP_DATA_PACKET;
197 sent_len = len < tx_size ? len : tx_size;
199 pkt.length = sent_len;
200 pkt.buffer = (mtp_uchar *)g_malloc(sent_len);
201 if (NULL == pkt.buffer) {
202 ERR("g_malloc() Fail");
206 memcpy(pkt.buffer, temp, sent_len);
207 ret = _util_msgq_send(mtp_to_usb_mqid, (void *)&pkt,
208 sizeof(msgq_ptr_t) - sizeof(long), 0);
210 ERR("_util_msgq_send() Fail");
222 mtp_uint32 _transport_send_bulk_pkt_to_tx_mq(const mtp_byte *buf,
225 mtp_uint32 sent_len = 0;
226 mtp_uint32 tx_size = _get_tx_pkt_size();
227 msgq_ptr_t pkt = {MTP_BULK_PACKET, 0, 0, NULL};
229 retv_if(buf == NULL, 0);
230 retv_if(pkt_len == 0, 0);
232 pkt.length = tx_size;
233 while (pkt_len > tx_size) {
234 pkt.buffer = (mtp_uchar *)g_malloc(pkt.length);
235 if (NULL == pkt.buffer) {
236 ERR("g_malloc() Fail");
239 memcpy(pkt.buffer, &buf[sent_len], pkt.length);
241 if (!_util_msgq_send(mtp_to_usb_mqid, (void *)&pkt,
242 sizeof(msgq_ptr_t) - sizeof(long), 0)) {
243 ERR("_util_msgq_send() Fail");
248 pkt_len -= pkt.length;
249 sent_len += pkt.length;
252 pkt.length = pkt_len;
253 pkt.buffer = (mtp_uchar *)g_malloc(pkt.length);
254 if (NULL == pkt.buffer) {
255 ERR("g_malloc() Fail");
258 memcpy(pkt.buffer, &buf[sent_len], pkt.length);
260 if (!_util_msgq_send(mtp_to_usb_mqid, (void *)&pkt,
261 sizeof(msgq_ptr_t) - sizeof(long), 0)) {
262 ERR("_util_msgq_send() Fail");
266 sent_len += pkt.length;
271 void _transport_send_zlp(void)
273 msgq_ptr_t pkt = { 0 };
274 mtp_bool resp = FALSE;
276 pkt.mtype = MTP_ZLP_PACKET;
281 resp = _util_msgq_send(mtp_to_usb_mqid, (void *)&pkt,
282 sizeof(msgq_ptr_t) - sizeof(long), 0);
284 ERR("_util_msgq_send() Fail");
288 static mtp_err_t __transport_init_io()
291 thread_func_t usb_write_thread = _transport_thread_usb_write;
292 thread_func_t usb_read_thread = _transport_thread_usb_read;
294 res = _util_thread_create(&g_tx_thrd, "usb write thread",
295 PTHREAD_CREATE_JOINABLE, usb_write_thread,
296 (void *)&mtp_to_usb_mqid);
298 ERR("_util_thread_create(TX) Fail");
302 res = _util_thread_create(&g_rx_thrd, "usb read thread",
303 PTHREAD_CREATE_JOINABLE, usb_read_thread,
304 (void *)&g_usb_to_mtp_mqid);
306 ERR("_util_thread_create(RX) Fail");
310 g_usb_threads_created = TRUE;
312 return MTP_ERROR_NONE;
318 res = _util_thread_cancel(g_rx_thrd);
319 DBG("pthread_cancel [%d]\n", res);
323 res = _util_thread_cancel(g_tx_thrd);
324 DBG("pthread_cancel [%d]\n", res);
327 g_usb_threads_created = FALSE;
329 return MTP_ERROR_GENERAL;
332 static void __transport_deinit_io()
334 if (g_usb_threads_created == FALSE) {
335 ERR("io threads are not created.");
340 if (FALSE == _util_thread_cancel(g_rx_thrd))
341 ERR("_util_thread_cancel(rx) Fail");
343 if (_util_thread_join(g_rx_thrd, 0) == FALSE)
344 ERR("_util_thread_join(rx) Fail");
348 if (FALSE == _util_thread_cancel(g_tx_thrd))
349 ERR("_util_thread_cancel(tx) Fail");
351 if (_util_thread_join(g_tx_thrd, 0) == FALSE)
352 ERR("_util_thread_join(tx) Fail");
356 g_usb_threads_created = FALSE;
360 mtp_bool _transport_init_interfaces(_cmd_handler_cb func)
363 mtp_bool ret = FALSE;
365 ret = _transport_init_usb_device();
367 /* mtp driver open failed */
368 ERR("_transport_init_usb_device() Fail");
372 if (_transport_mq_init(&g_usb_to_mtp_mqid, &mtp_to_usb_mqid) == FALSE) {
373 ERR("_transport_mq_init() Fail");
374 _transport_deinit_usb_device();
378 if (__transport_init_io() != MTP_ERROR_NONE) {
379 ERR("__transport_init_io() Fail");
380 _transport_mq_deinit(&g_usb_to_mtp_mqid, &mtp_to_usb_mqid);
381 _transport_deinit_usb_device();
385 res = _util_thread_create(&g_data_rcv, "Data Receive thread",
386 PTHREAD_CREATE_JOINABLE, __transport_thread_data_rcv,
389 ERR("_util_thread_create(data_rcv) Fail");
390 __transport_deinit_io();
391 _transport_mq_deinit(&g_usb_to_mtp_mqid, &mtp_to_usb_mqid);
392 _transport_deinit_usb_device();
399 void _transport_usb_finalize(void)
402 void *th_result = NULL;
404 mtp_uint32 rx_size = _get_rx_pkt_size();
406 __transport_deinit_io();
408 if (g_data_rcv != 0) {
409 pkt.buffer = (mtp_uchar *)g_malloc(rx_size);
410 if (pkt.buffer == NULL) {
411 ERR("g_malloc() Fail");
414 pkt.mtype = MTP_DATA_PACKET;
417 memset(pkt.buffer, 0, rx_size);
418 if (FALSE == _util_msgq_send(g_usb_to_mtp_mqid, (void *)&pkt,
419 sizeof(msgq_ptr_t) - sizeof(long), 0)) {
420 ERR("_util_msgq_send() Fail");
423 res = _util_thread_join(g_data_rcv, &th_result);
425 ERR("_util_thread_join(data_rcv) Fail");
428 if (_transport_mq_deinit(&g_usb_to_mtp_mqid, &mtp_to_usb_mqid) == FALSE)
429 ERR("_transport_mq_deinit() Fail");
431 _transport_deinit_usb_device();
436 static void *__transport_thread_data_rcv(void *func)
438 msgq_ptr_t pkt = { 0 };
439 mtp_uchar *pkt_data = NULL;
440 mtp_uint32 pkt_len = 0;
443 _cmd_handler_cb _cmd_handler_func = (_cmd_handler_cb)func;
446 if (_util_msgq_receive(g_usb_to_mtp_mqid, (void *)&pkt,
447 sizeof(pkt) - sizeof(long), 0, &len) == FALSE) {
448 ERR("_util_msgq_receive() Fail");
452 if (len == sizeof(msgq_ptr_t) - sizeof(long)) {
454 if (pkt.length == 6 && pkt.signal == 0xABCD) {
455 ERR("Got NULL character in MQ");
459 pkt_data = pkt.buffer;
460 pkt_len = pkt.length;
461 _cmd_handler_func((mtp_char *)pkt_data, pkt_len);
465 memset(&pkt, 0, sizeof(pkt));
469 ERR("Received packet is less than real size");
473 ERR("thread_data_rcv[%u] exiting\n", g_data_rcv);
474 _util_thread_exit("__transport_thread_data_rcv is over");
478 void _transport_init_status_info(void)
480 memset((void *)&g_status, 0, sizeof(status_info_t));
484 mtp_int32 _transport_get_control_event(void)
486 mtp_uint32 event_code;
488 event_code = g_status.ctrl_event_code;
490 /* initialize for next usage */
492 g_status.ctrl_event_code = 0;
497 void _transport_set_control_event(mtp_int32 event_code)
499 g_status.ctrl_event_code = event_code;
502 mtp_state_t _transport_get_mtp_operation_state(void)
504 return g_status.mtp_op_state;
507 void _transport_set_mtp_operation_state(mtp_state_t state)
509 g_status.mtp_op_state = state;
513 void _transport_set_usb_discon_state(mtp_bool is_usb_discon)
515 g_status.is_usb_discon = is_usb_discon;
519 mtp_bool _transport_get_usb_discon_state(void)
521 return g_status.is_usb_discon;
524 void _transport_set_cancel_initialization(mtp_bool value)
526 g_status.cancel_intialization = value;
529 mtp_bool _transport_get_cancel_initialization(void)
531 return g_status.cancel_intialization;