1 /*
2 *
3 * SPDX-License-Identifier: GPL-2.0
4 *
5 * Copyright (C) 2011-2018 ARM or its affiliates
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 *
18 */
19
20 #include "acamera_event_queue.h"
21 #include "acamera_logger.h"
22 #include "system_spinlock.h"
23
24 static uint32_t reset_threshold = 1;
25 static uint64_t avail_event_mask;
26
acamera_event_queue_reset(acamera_loop_buf_ptr_t p_buf)27 static void acamera_event_queue_reset( acamera_loop_buf_ptr_t p_buf )
28 {
29 p_buf->head = p_buf->tail = 0;
30 avail_event_mask = 0;
31 }
32
acamera_event_queue_push(acamera_event_queue_ptr_t p_queue,int event)33 void acamera_event_queue_push( acamera_event_queue_ptr_t p_queue, int event )
34 {
35 int err = 0;
36 acamera_loop_buf_ptr_t p_buf = &( p_queue->buf );
37 unsigned long flags;
38
39 flags = system_spinlock_lock( p_queue->lock );
40
41 if ( ( p_buf->head < 0 ) ||
42 ( p_buf->head >= p_buf->data_buf_size ) ||
43 ( p_buf->tail < 0 ) ||
44 ( p_buf->tail >= p_buf->data_buf_size ) ) {
45 err = -1;
46 }
47
48 if ((1 << event) & avail_event_mask) {
49 err = 0;
50 LOG( LOG_DEBUG, "event %d is duplicated, skip it at this time", event);
51 } else {
52 int pos = acamera_loop_buffer_write_u8( p_buf, 0, (uint8_t)event );
53 if ( pos != p_buf->tail ) {
54 p_buf->head = pos;
55 avail_event_mask |= (1 << event);
56 } else {
57 err = -2;
58 acamera_event_queue_reset( p_buf );
59 }
60 }
61
62 system_spinlock_unlock( p_queue->lock, flags );
63
64 if ( -1 == err ) {
65 LOG( LOG_ERR, "Event Queue Corrupted\n" );
66 } else if ( -2 == err ) {
67 static uint32_t counter = 0;
68 if ( !( counter++ & 0x3F ) )
69 LOG( LOG_CRIT, "Event Queue overflow\n" );
70 }
71 }
72
acamera_event_queue_pop(acamera_event_queue_ptr_t p_queue)73 int acamera_event_queue_pop( acamera_event_queue_ptr_t p_queue )
74 {
75 int rc = 0;
76 unsigned long flags;
77 acamera_loop_buf_ptr_t p_buf = &( p_queue->buf );
78
79 flags = system_spinlock_lock( p_queue->lock );
80
81 if ( p_buf->head == p_buf->tail ) {
82 rc = -1;
83 }
84
85 if ( ( p_buf->head < 0 ) ||
86 ( p_buf->head >= p_buf->data_buf_size ) ||
87 ( p_buf->tail < 0 ) ||
88 ( p_buf->tail >= p_buf->data_buf_size ) ) {
89 rc = -2;
90 }
91
92 if ( !rc ) {
93 int pos;
94 rc = acamera_loop_buffer_read_u8( p_buf, 0 );
95
96 pos = p_buf->tail + 1;
97 if ( pos >= p_buf->data_buf_size ) {
98 pos -= p_buf->data_buf_size;
99 }
100
101 p_buf->tail = pos;
102 if (rc >= 0 && rc < 64) {
103 if (((1 << rc) & avail_event_mask) == 0)
104 LOG( LOG_DEBUG, "event %d is missed, mask is 0x%x", rc, avail_event_mask);
105 else
106 avail_event_mask &= ~(1 << rc);
107 }
108 }
109
110 system_spinlock_unlock( p_queue->lock, flags );
111
112 if ( -2 == rc ) {
113 LOG( LOG_ERR, "Event Queue Corrupted\n" );
114 }
115
116 return rc;
117 }
118
119
acamera_event_queue_not_empty(acamera_event_queue_ptr_t p_queue)120 int32_t acamera_event_queue_not_empty( acamera_event_queue_ptr_t p_queue )
121 {
122 int32_t result = -1;
123 uint32_t flags = 0;
124 uint32_t pos = 0;
125 uint64_t event = 0;
126 unsigned char event_id = 0;
127 acamera_loop_buf_ptr_t p_buf = &( p_queue->buf );
128 flags = system_spinlock_lock( p_queue->lock );
129 if ( p_buf->head == p_buf->tail )
130 result = 0;
131
132 if (result) {
133 while (p_buf->head > (p_buf->tail + pos)) {
134 event_id = p_buf->p_data_buf[pos + p_buf->tail];
135 event |= (1 << event_id);
136 pos++;
137 }
138
139 LOG( LOG_DEBUG, "p_buf->head:%d, p_buf->tail:%d, remained event mask: 0x%llx" , p_buf->head, p_buf->tail, event);
140 acamera_event_queue_reset(p_buf);
141
142 if (pos >= reset_threshold)
143 result = pos;
144 else
145 result = 0;
146 }
147 system_spinlock_unlock( p_queue->lock, flags );
148 return result;
149 }
150