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_dispatch_response_data(p->queue->hal, p->id, 0, NULL);
99 TcorePending *tcore_pending_new(CoreObject *co, unsigned int id)
103 p = calloc(sizeof(struct tcore_pending_type), 1);
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 ((tcore_hal_get_mode(pending->queue->hal) != TCORE_HAL_MODE_AT)
135 && (tcore_hal_get_mode(pending->queue->hal) != TCORE_HAL_MODE_TRANSPARENT))
141 if (pending->timer_src) {
142 g_source_remove(pending->timer_src);
148 unsigned int tcore_pending_get_id(TcorePending *pending)
156 TReturn tcore_pending_set_auto_free_status_after_sent(TcorePending *pending,
160 return TCORE_RETURN_EINVAL;
162 pending->flag_auto_free_after_sent = flag;
164 return TCORE_RETURN_SUCCESS;
167 gboolean tcore_pending_get_auto_free_status_after_sent(TcorePending *pending)
172 return pending->flag_auto_free_after_sent;
175 TReturn tcore_pending_set_request_data(TcorePending *pending,
176 unsigned int data_len, void *data)
179 return TCORE_RETURN_EINVAL;
182 if (pending->data_len != 0) {
184 pending->data = NULL;
188 pending->data_len = data_len;
189 if (pending->data_len > 0) {
190 pending->data = calloc(data_len, 1);
192 return TCORE_RETURN_ENOMEM;
194 memcpy(pending->data, data, data_len);
197 pending->data = data;
200 return TCORE_RETURN_SUCCESS;
203 void *tcore_pending_ref_request_data(TcorePending *pending, unsigned int *data_len)
209 *data_len = pending->data_len;
211 return pending->data;
214 TReturn tcore_pending_set_priority(TcorePending *pending,
215 enum tcore_pending_priority priority)
218 return TCORE_RETURN_EINVAL;
220 pending->priority = priority;
222 return TCORE_RETURN_SUCCESS;
225 TReturn tcore_pending_get_priority(TcorePending *pending,
226 enum tcore_pending_priority *result_priority)
228 if (!pending || !result_priority)
229 return TCORE_RETURN_EINVAL;
231 *result_priority = pending->priority;
233 return TCORE_RETURN_SUCCESS;
236 TReturn tcore_pending_set_timeout(TcorePending *pending, unsigned int timeout)
239 return TCORE_RETURN_EINVAL;
241 pending->timeout = timeout;
243 return TCORE_RETURN_SUCCESS;
246 TReturn tcore_pending_get_send_status(TcorePending *pending,
247 gboolean *result_status)
249 if (!pending || !result_status)
250 return TCORE_RETURN_EINVAL;
252 *result_status = pending->flag_sent;
254 return TCORE_RETURN_SUCCESS;
257 TReturn tcore_pending_set_send_callback(TcorePending *pending,
258 TcorePendingSendCallback func, void *user_data)
261 return TCORE_RETURN_EINVAL;
263 pending->on_send = func;
264 pending->on_send_user_data = user_data;
266 return TCORE_RETURN_SUCCESS;
269 TReturn tcore_pending_set_timeout_callback(TcorePending *pending,
270 TcorePendingTimeoutCallback func, void *user_data)
273 return TCORE_RETURN_EINVAL;
275 pending->on_timeout = func;
276 pending->on_timeout_user_data = user_data;
278 return TCORE_RETURN_SUCCESS;
281 TReturn tcore_pending_set_response_callback(TcorePending *pending,
282 TcorePendingResponseCallback func, void *user_data)
285 return TCORE_RETURN_EINVAL;
287 pending->on_response = func;
288 pending->on_response_user_data = user_data;
290 return TCORE_RETURN_SUCCESS;
293 TReturn tcore_pending_emit_send_callback(TcorePending *pending, gboolean result)
296 return TCORE_RETURN_EINVAL;
298 pending->flag_sent = TRUE;
300 if (pending->on_send)
301 pending->on_send(pending, result, pending->on_send_user_data);
303 if (result == TRUE) {
304 if (pending->flag_auto_free_after_sent == FALSE && pending->timeout > 0) {
306 dbg("start pending timer! (%d secs)", pending->timeout);
307 pending->timer_src = g_timeout_add_seconds(pending->timeout, _on_pending_timeout, pending);
311 return TCORE_RETURN_SUCCESS;
314 TReturn tcore_pending_emit_timeout_callback(TcorePending *pending)
317 return TCORE_RETURN_EINVAL;
319 if (pending->on_timeout)
320 pending->on_timeout(pending, pending->on_timeout_user_data);
322 return TCORE_RETURN_SUCCESS;
325 TReturn tcore_pending_emit_response_callback(TcorePending *pending,
326 int data_len, const void *data)
329 return TCORE_RETURN_EINVAL;
331 if (pending->on_response)
332 pending->on_response(pending, data_len, data,
333 pending->on_response_user_data);
335 return TCORE_RETURN_SUCCESS;
338 CoreObject *tcore_pending_ref_core_object(TcorePending *pending)
346 TcorePlugin *tcore_pending_ref_plugin(TcorePending *pending)
351 return pending->plugin;
354 TReturn tcore_pending_link_user_request(TcorePending *pending, UserRequest *ur)
357 return TCORE_RETURN_EINVAL;
361 return TCORE_RETURN_SUCCESS;
364 UserRequest *tcore_pending_ref_user_request(TcorePending *pending)
372 TcoreQueue *tcore_queue_new(TcoreHal *h)
376 queue = calloc(sizeof(struct tcore_queue_type), 1);
382 queue->gq = g_queue_new();
388 g_queue_init(queue->gq);
393 void tcore_queue_free(TcoreQueue *queue)
399 g_queue_free(queue->gq);
404 static void _tcore_queue_push_head(TcoreQueue *queue, TcorePending *pending)
411 tmp = g_queue_peek_nth(queue->gq, i);
416 if (tmp->priority == TCORE_PENDING_PRIORITY_IMMEDIATELY)
422 g_queue_push_nth(queue->gq, pending, i);
425 TReturn tcore_queue_push(TcoreQueue *queue, TcorePending *pending)
427 enum tcore_pending_priority priority;
429 if (!queue || !pending)
430 return TCORE_RETURN_EINVAL;
432 if (pending->id == 0) {
433 pending->id = queue->next_id;
437 tcore_pending_get_priority(pending, &priority);
439 case TCORE_PENDING_PRIORITY_IMMEDIATELY:
440 case TCORE_PENDING_PRIORITY_HIGH:
441 pending->queue = queue;
442 _tcore_queue_push_head(queue, pending);
445 case TCORE_PENDING_PRIORITY_DEFAULT:
446 case TCORE_PENDING_PRIORITY_LOW:
447 pending->queue = queue;
448 g_queue_push_tail(queue->gq, pending);
452 return TCORE_RETURN_EINVAL;
456 dbg("pending(0x%x) push to queue. queue length=%d",
457 (unsigned int)pending, g_queue_get_length(queue->gq));
459 return TCORE_RETURN_SUCCESS;
462 TcorePending *tcore_queue_pop(TcoreQueue *queue)
467 return g_queue_pop_head(queue->gq);
470 TcorePending *tcore_queue_pop_by_pending(TcoreQueue *queue, TcorePending *pending)
479 tmp = g_queue_peek_nth(queue->gq, i);
483 if (tmp == pending) {
484 g_queue_pop_nth(queue->gq, i);
494 TcorePending *tcore_queue_pop_timeout_pending(TcoreQueue *queue)
497 TcorePending *pending = NULL;
503 pending = g_queue_peek_nth(queue->gq, i);
507 if (cur_time - pending->timestamp >= (int)pending->timeout) {
508 pending = g_queue_pop_nth(queue->gq, i);
513 } while (pending != NULL);
518 TcorePending *tcore_queue_ref_head(TcoreQueue *queue)
523 return g_queue_peek_head(queue->gq);
526 TcorePending *tcore_queue_ref_tail(TcoreQueue *queue)
531 return g_queue_peek_tail(queue->gq);
535 static TcorePending *_tcore_queue_search_full(TcoreQueue *queue, unsigned int id,
536 enum tcore_request_command command, enum search_field field, gboolean flag_pop)
538 TcorePending *pending = NULL;
546 pending = g_queue_peek_nth(queue->gq, i);
550 if ((field & 0xF0) == 0x10) {
551 /* search option is wait pending */
552 if (pending->flag_sent) {
557 else if ((field & 0xF0) == 0x20) {
558 /* search option is sent pending */
559 if (pending->flag_sent == FALSE) {
565 if ((field & 0x0F) == SEARCH_FIELD_ID_ALL) {
566 if (pending->id == id) {
567 if (flag_pop == TRUE) {
568 pending = g_queue_pop_nth(queue->gq, i);
573 else if ((field & 0x0F) == SEARCH_FIELD_COMMAND_ALL) {
574 ur = tcore_pending_ref_user_request(pending);
575 if (tcore_user_request_get_command(ur) == command) {
576 if (flag_pop == TRUE) {
577 pending = g_queue_pop_nth(queue->gq, i);
584 } while (pending != NULL);
589 TcorePending *tcore_queue_search_by_command(TcoreQueue *queue,
590 enum tcore_request_command command, gboolean flag_sent)
593 return _tcore_queue_search_full(queue, 0, command, SEARCH_FIELD_COMMAND_SENT, FALSE);
595 return _tcore_queue_search_full(queue, 0, command, SEARCH_FIELD_COMMAND_WAIT, FALSE);
598 TcorePending *tcore_queue_pop_by_id(TcoreQueue *queue, unsigned int id)
603 return _tcore_queue_search_full(queue, id, 0, SEARCH_FIELD_ID_ALL, TRUE);
606 TcorePending *tcore_queue_ref_pending_by_id(TcoreQueue *queue, unsigned int id)
611 return _tcore_queue_search_full(queue, id, 0, SEARCH_FIELD_ID_ALL, FALSE);
614 TcorePending *tcore_queue_ref_next_pending(TcoreQueue *queue)
616 TcorePending *pending = NULL;
623 pending = g_queue_peek_nth(queue->gq, i);
628 /* skip already sent immediately pending */
629 if (pending->priority == TCORE_PENDING_PRIORITY_IMMEDIATELY) {
630 if (pending->flag_sent == FALSE) {
642 } while (pending != NULL);
644 if (pending->flag_sent == TRUE) {
645 dbg("pending(0x%x) is waiting state.", (unsigned int)pending);
652 unsigned int tcore_queue_get_length(TcoreQueue *queue)
657 return g_queue_get_length(queue->gq);
660 TcoreHal *tcore_queue_ref_hal(TcoreQueue *queue)
668 TReturn tcore_queue_cancel_pending_by_command(TcoreQueue *queue, enum tcore_request_command command)
670 TcorePending *pending;
673 return TCORE_RETURN_EINVAL;
676 pending = _tcore_queue_search_full(queue, 0, command, SEARCH_FIELD_COMMAND_ALL, FALSE);
680 dbg("pending(0x%x) cancel", pending);
683 tcore_hal_dispatch_response_data(queue->hal, pending->id, 0, NULL);
686 pending = tcore_queue_pop_by_pending(queue, pending);
687 tcore_pending_emit_response_callback(pending, 0, NULL);
688 tcore_user_request_unref(tcore_pending_ref_user_request(pending));
689 tcore_pending_free(pending);
693 return TCORE_RETURN_SUCCESS;