4 * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Ja-young Gu <jygu@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
34 #include "user_request.h"
35 #include "core_object.h"
38 struct tcore_queue_type {
44 struct tcore_pending_type {
47 TcorePendingSendCallback on_send;
48 void *on_send_user_data;
49 TcorePendingTimeoutCallback on_timeout;
50 void *on_timeout_user_data;
51 TcorePendingResponseCallback on_response;
52 void *on_response_user_data;
54 enum tcore_pending_priority priority;
56 unsigned int data_len;
62 gboolean flag_received_response;
63 gboolean flag_auto_free_after_sent;
74 SEARCH_FIELD_ID_ALL = 0x01,
75 SEARCH_FIELD_ID_WAIT = 0x11,
76 SEARCH_FIELD_ID_SENT = 0x21,
77 SEARCH_FIELD_COMMAND_ALL = 0x02,
78 SEARCH_FIELD_COMMAND_WAIT = 0x12,
79 SEARCH_FIELD_COMMAND_SENT = 0x22,
82 static gboolean _on_pending_timeout(gpointer user_data)
84 TcorePending *p = user_data;
86 dbg("pending timeout!!");
91 tcore_pending_emit_timeout_callback(p);
93 p->on_response = NULL;
94 tcore_hal_free_timeout_pending_request(p->queue->hal, p, 0, NULL);
99 TcorePending *tcore_pending_new(CoreObject *co, unsigned int id)
103 p = calloc(1, sizeof(struct tcore_pending_type));
111 p->on_send_user_data = NULL;
112 p->on_response = NULL;
113 p->on_response_user_data = NULL;
114 p->on_timeout = NULL;
115 p->on_timeout_user_data = NULL;
119 p->priority = TCORE_PENDING_PRIORITY_DEFAULT;
120 p->flag_sent = FALSE;
122 p->plugin = tcore_object_ref_plugin(co);
127 void tcore_pending_free(TcorePending *pending)
132 dbg("pending(0x%x) free, id=0x%x", (unsigned int)pending, pending->id);
134 if (pending->queue) {
135 enum tcore_hal_mode mode = tcore_hal_get_mode(pending->queue->hal);
136 if ((mode != TCORE_HAL_MODE_AT)
137 && (mode != TCORE_HAL_MODE_TRANSPARENT))
142 if (pending->timer_src) {
143 g_source_remove(pending->timer_src);
149 unsigned int tcore_pending_get_id(TcorePending *pending)
157 TReturn tcore_pending_set_auto_free_status_after_sent(TcorePending *pending,
161 return TCORE_RETURN_EINVAL;
163 pending->flag_auto_free_after_sent = flag;
165 return TCORE_RETURN_SUCCESS;
168 gboolean tcore_pending_get_auto_free_status_after_sent(TcorePending *pending)
173 return pending->flag_auto_free_after_sent;
176 TReturn tcore_pending_set_request_data(TcorePending *pending,
177 unsigned int data_len, void *data)
180 return TCORE_RETURN_EINVAL;
183 if (pending->data_len != 0) {
185 pending->data = NULL;
189 pending->data_len = data_len;
190 if (pending->data_len > 0) {
191 pending->data = calloc(data_len, 1);
193 return TCORE_RETURN_ENOMEM;
195 memcpy(pending->data, data, data_len);
198 pending->data = data;
201 return TCORE_RETURN_SUCCESS;
204 void *tcore_pending_ref_request_data(TcorePending *pending, unsigned int *data_len)
210 *data_len = pending->data_len;
212 return pending->data;
215 TReturn tcore_pending_set_priority(TcorePending *pending,
216 enum tcore_pending_priority priority)
219 return TCORE_RETURN_EINVAL;
221 pending->priority = priority;
223 return TCORE_RETURN_SUCCESS;
226 TReturn tcore_pending_get_priority(TcorePending *pending,
227 enum tcore_pending_priority *result_priority)
229 if (!pending || !result_priority)
230 return TCORE_RETURN_EINVAL;
232 *result_priority = pending->priority;
234 return TCORE_RETURN_SUCCESS;
237 TReturn tcore_pending_start_timer(TcorePending *pending)
240 if (pending->timeout > 0 && pending->on_timeout) {
241 dbg("start pending timer! (%d secs)", pending->timeout);
242 pending->timer_src = g_timeout_add_seconds(pending->timeout, _on_pending_timeout, pending);
244 return TCORE_RETURN_SUCCESS;
247 TReturn tcore_pending_set_timeout(TcorePending *pending, unsigned int timeout)
250 return TCORE_RETURN_EINVAL;
252 pending->timeout = timeout;
254 return TCORE_RETURN_SUCCESS;
257 unsigned int tcore_pending_get_timeout(TcorePending *pending)
262 return pending->timeout;
265 TReturn tcore_pending_get_send_status(TcorePending *pending,
266 gboolean *result_status)
268 if (!pending || !result_status)
269 return TCORE_RETURN_EINVAL;
271 *result_status = pending->flag_sent;
273 return TCORE_RETURN_SUCCESS;
276 TReturn tcore_pending_set_send_callback(TcorePending *pending,
277 TcorePendingSendCallback func, void *user_data)
280 return TCORE_RETURN_EINVAL;
282 pending->on_send = func;
283 pending->on_send_user_data = user_data;
285 return TCORE_RETURN_SUCCESS;
288 TReturn tcore_pending_set_timeout_callback(TcorePending *pending,
289 TcorePendingTimeoutCallback func, void *user_data)
292 return TCORE_RETURN_EINVAL;
294 pending->on_timeout = func;
295 pending->on_timeout_user_data = user_data;
297 return TCORE_RETURN_SUCCESS;
300 TReturn tcore_pending_set_response_callback(TcorePending *pending,
301 TcorePendingResponseCallback func, void *user_data)
304 return TCORE_RETURN_EINVAL;
306 pending->on_response = func;
307 pending->on_response_user_data = user_data;
309 return TCORE_RETURN_SUCCESS;
312 TReturn tcore_pending_emit_send_callback(TcorePending *pending, gboolean result)
315 return TCORE_RETURN_EINVAL;
317 pending->flag_sent = TRUE;
319 if (pending->on_send)
320 pending->on_send(pending, result, pending->on_send_user_data);
322 return TCORE_RETURN_SUCCESS;
325 TReturn tcore_pending_emit_timeout_callback(TcorePending *pending)
328 return TCORE_RETURN_EINVAL;
330 if (pending->on_timeout)
331 pending->on_timeout(pending, pending->on_timeout_user_data);
333 return TCORE_RETURN_SUCCESS;
336 TReturn tcore_pending_emit_response_callback(TcorePending *pending,
337 int data_len, const void *data)
340 return TCORE_RETURN_EINVAL;
342 if (pending->on_response)
343 pending->on_response(pending, data_len, data,
344 pending->on_response_user_data);
346 return TCORE_RETURN_SUCCESS;
349 CoreObject *tcore_pending_ref_core_object(TcorePending *pending)
357 TcorePlugin *tcore_pending_ref_plugin(TcorePending *pending)
362 return pending->plugin;
365 TReturn tcore_pending_link_user_request(TcorePending *pending, UserRequest *ur)
368 return TCORE_RETURN_EINVAL;
372 return TCORE_RETURN_SUCCESS;
375 UserRequest *tcore_pending_ref_user_request(TcorePending *pending)
383 TcoreQueue *tcore_queue_new(TcoreHal *h)
387 queue = calloc(1, sizeof(struct tcore_queue_type));
393 queue->gq = g_queue_new();
399 g_queue_init(queue->gq);
404 void tcore_queue_free(TcoreQueue *queue)
410 g_queue_free(queue->gq);
415 static void _tcore_queue_push_head(TcoreQueue *queue, TcorePending *pending)
422 tmp = g_queue_peek_nth(queue->gq, i);
427 if (tmp->priority == TCORE_PENDING_PRIORITY_IMMEDIATELY)
433 g_queue_push_nth(queue->gq, pending, i);
436 TReturn tcore_queue_push(TcoreQueue *queue, TcorePending *pending)
438 enum tcore_pending_priority priority;
440 if (!queue || !pending)
441 return TCORE_RETURN_EINVAL;
443 if (pending->id == 0) {
444 pending->id = queue->next_id;
448 tcore_pending_get_priority(pending, &priority);
450 case TCORE_PENDING_PRIORITY_IMMEDIATELY:
451 case TCORE_PENDING_PRIORITY_HIGH:
452 pending->queue = queue;
453 _tcore_queue_push_head(queue, pending);
456 case TCORE_PENDING_PRIORITY_DEFAULT:
457 case TCORE_PENDING_PRIORITY_LOW:
458 pending->queue = queue;
459 g_queue_push_tail(queue->gq, pending);
463 return TCORE_RETURN_EINVAL;
467 dbg("pending(%p) push to queue(%p). queue length=%d",
468 (unsigned int)pending, queue, g_queue_get_length(queue->gq));
470 return TCORE_RETURN_SUCCESS;
473 TcorePending *tcore_queue_pop(TcoreQueue *queue)
478 return g_queue_pop_head(queue->gq);
481 TcorePending *tcore_queue_pop_by_pending(TcoreQueue *queue, TcorePending *pending)
490 tmp = g_queue_peek_nth(queue->gq, i);
494 if (tmp == pending) {
495 g_queue_pop_nth(queue->gq, i);
505 TcorePending *tcore_queue_pop_timeout_pending(TcoreQueue *queue)
508 TcorePending *pending = NULL;
514 pending = g_queue_peek_nth(queue->gq, i);
518 if (cur_time - pending->timestamp >= (int)pending->timeout) {
519 pending = g_queue_pop_nth(queue->gq, i);
524 } while (pending != NULL);
529 TcorePending *tcore_queue_ref_head(TcoreQueue *queue)
534 return g_queue_peek_head(queue->gq);
537 TcorePending *tcore_queue_ref_tail(TcoreQueue *queue)
542 return g_queue_peek_tail(queue->gq);
546 static TcorePending *_tcore_queue_search_full(TcoreQueue *queue, unsigned int id,
547 enum tcore_request_command command, enum search_field field, gboolean flag_pop)
549 TcorePending *pending = NULL;
557 pending = g_queue_peek_nth(queue->gq, i);
561 if ((field & 0xF0) == 0x10) {
562 /* search option is wait pending */
563 if (pending->flag_sent) {
568 else if ((field & 0xF0) == 0x20) {
569 /* search option is sent pending */
570 if (pending->flag_sent == FALSE) {
576 if ((field & 0x0F) == SEARCH_FIELD_ID_ALL) {
577 if (pending->id == id) {
578 if (flag_pop == TRUE) {
579 pending = g_queue_pop_nth(queue->gq, i);
584 else if ((field & 0x0F) == SEARCH_FIELD_COMMAND_ALL) {
585 ur = tcore_pending_ref_user_request(pending);
586 if (tcore_user_request_get_command(ur) == command) {
587 if (flag_pop == TRUE) {
588 pending = g_queue_pop_nth(queue->gq, i);
595 } while (pending != NULL);
600 TcorePending *tcore_queue_search_by_command(TcoreQueue *queue,
601 enum tcore_request_command command, gboolean flag_sent)
604 return _tcore_queue_search_full(queue, 0, command, SEARCH_FIELD_COMMAND_SENT, FALSE);
606 return _tcore_queue_search_full(queue, 0, command, SEARCH_FIELD_COMMAND_WAIT, FALSE);
609 TcorePending *tcore_queue_pop_by_id(TcoreQueue *queue, unsigned int id)
614 return _tcore_queue_search_full(queue, id, 0, SEARCH_FIELD_ID_ALL, TRUE);
617 TcorePending *tcore_queue_ref_pending_by_id(TcoreQueue *queue, unsigned int id)
622 return _tcore_queue_search_full(queue, id, 0, SEARCH_FIELD_ID_ALL, FALSE);
625 TcorePending *tcore_queue_ref_next_pending(TcoreQueue *queue)
627 TcorePending *pending = NULL;
634 pending = g_queue_peek_nth(queue->gq, i);
639 /* skip already sent immediately pending */
640 if (pending->priority == TCORE_PENDING_PRIORITY_IMMEDIATELY) {
641 if (pending->flag_sent == FALSE) {
651 } while (pending != NULL);
653 if (pending->flag_sent == TRUE) {
654 dbg("pending(0x%x) is waiting state.", (unsigned int)pending);
661 unsigned int tcore_queue_get_length(TcoreQueue *queue)
666 return g_queue_get_length(queue->gq);
669 unsigned int tcore_queue_get_normal_length(TcoreQueue *queue)
671 TcorePending *pending;
678 pending = g_queue_peek_nth(queue->gq, i);
683 if (pending->priority == TCORE_PENDING_PRIORITY_IMMEDIATELY) {
691 return g_queue_get_length(queue->gq) - i;
694 TcoreHal *tcore_queue_ref_hal(TcoreQueue *queue)
702 TReturn tcore_queue_cancel_pending_by_command(TcoreQueue *queue, enum tcore_request_command command)
704 TcorePending *pending;
707 return TCORE_RETURN_EINVAL;
710 pending = _tcore_queue_search_full(queue, 0, command, SEARCH_FIELD_COMMAND_ALL, FALSE);
714 dbg("pending(0x%x) cancel", (unsigned int)pending);
717 dbg("hal %p", queue->hal);
718 tcore_hal_dispatch_response_data(queue->hal, pending->id, 0, NULL);
722 pending = tcore_queue_pop_by_pending(queue, pending);
723 tcore_pending_emit_response_callback(pending, 0, NULL);
724 tcore_user_request_unref(tcore_pending_ref_user_request(pending));
725 tcore_pending_free(pending);
729 return TCORE_RETURN_SUCCESS;