1/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 *     * Redistributions of source code must retain the above copyright
7 *       notice, this list of conditions and the following disclaimer.
8 *     * Redistributions in binary form must reproduce the above
9 *       copyright notice, this list of conditions and the following
10 *       disclaimer in the documentation and/or other materials provided
11 *       with the distribution.
12 *     * Neither the name of The Linux Foundation nor the names of its
13 *       contributors may be used to endorse or promote products derived
14 *       from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <stdint.h>
30#include <stdlib.h>
31#include <string.h>
32
33#define LOG_TAG  "WifiHAL"
34
35#include <utils/Log.h>
36
37typedef unsigned char u8;
38typedef uint16_t u16;
39typedef uint32_t u32;
40typedef uint64_t u64;
41
42#include "ring_buffer.h"
43
44enum rb_bool {
45    RB_TRUE = 0,
46    RB_FALSE = 1
47};
48
49typedef struct rb_entry_s {
50    u8 *data;
51    unsigned int last_wr_index;
52    u8 full;
53} rb_entry_t;
54
55typedef struct ring_buf_cb {
56    unsigned int rd_buf_no; // Current buffer number to be read from
57    unsigned int wr_buf_no; // Current buffer number to be written into
58    unsigned int cur_rd_buf_idx; // Read index within the current read buffer
59    unsigned int cur_wr_buf_idx; // Write index within the current write buffer
60    rb_entry_t *bufs; // Array of buffer pointers
61
62    unsigned int max_num_bufs; // Maximum number of buffers that should be used
63    size_t each_buf_size; // Size of each buffer in bytes
64
65    pthread_mutex_t rb_rw_lock;
66
67    /* Threshold vars */
68    unsigned int num_min_bytes;
69    void (*threshold_cb)(void *);
70    void *cb_ctx;
71
72    u32 total_bytes_written;
73    u32 total_bytes_read;
74    u32 total_bytes_overwritten;
75    u32 cur_valid_bytes;
76    enum rb_bool threshold_reached;
77} rbc_t;
78
79
80#define RB_MIN(x, y) ((x) < (y)?(x):(y))
81inline void rb_lock(pthread_mutex_t *lock)
82{
83    int error = pthread_mutex_lock(lock);
84
85    if (error)
86        ALOGE("Failed to acquire lock with err %d", error);
87    // TODO Handle the lock failure
88}
89
90inline void rb_unlock(pthread_mutex_t *lock)
91{
92    int error = pthread_mutex_unlock(lock);
93
94    if (error)
95        ALOGE("Failed to release lock with err %d", error);
96    // TODO Handle the unlock failure
97}
98
99void * ring_buffer_init(size_t size_of_buf, int num_bufs)
100{
101    struct ring_buf_cb *rbc;
102    int status;
103
104    rbc = (struct ring_buf_cb *)malloc(sizeof(struct ring_buf_cb));
105    if (rbc == NULL) {
106        ALOGE("Failed to alloc rbc");
107        return NULL;
108    }
109    memset(rbc, 0, sizeof(struct ring_buf_cb));
110
111    rbc->bufs = (rb_entry_t *)malloc(num_bufs * sizeof(rb_entry_t));
112    if (rbc->bufs == NULL) {
113        free(rbc);
114        ALOGE("Failed to alloc rbc->bufs");
115        return NULL;
116    }
117    memset(rbc->bufs, 0, (num_bufs * sizeof(rb_entry_t)));
118
119    rbc->each_buf_size = size_of_buf;
120    rbc->max_num_bufs = num_bufs;
121
122    status = pthread_mutex_init(&rbc->rb_rw_lock, NULL);
123    if (status != 0) {
124        ALOGE("Failed to initialize rb_rw_lock");
125        // TODO handle lock initialization failure
126    }
127    rbc->threshold_reached = RB_FALSE;
128    return rbc;
129}
130
131void ring_buffer_deinit(void *ctx)
132{
133    rbc_t *rbc = (rbc_t *)ctx;
134    int status;
135    unsigned int buf_no;
136
137    status = pthread_mutex_destroy(&rbc->rb_rw_lock);
138    if (status != 0) {
139        ALOGE("Failed to destroy rb_rw_lock");
140        // TODO handle the lock destroy failure
141    }
142    for (buf_no = 0; buf_no < rbc->max_num_bufs; buf_no++) {
143        free(rbc->bufs[buf_no].data);
144    }
145    free(rbc->bufs);
146    free(rbc);
147}
148
149/*
150 * record_length : 0  - byte boundary
151 *               : >0 - Ensures to write record_length no.of bytes to the same buffer.
152 */
153enum rb_status rb_write (void *ctx, u8 *buf, size_t length, int overwrite,
154                         size_t record_length)
155{
156    rbc_t *rbc = (rbc_t *)ctx;
157    unsigned int bytes_written = 0; // bytes written into rb so far
158    unsigned int push_in_rd_ptr = 0; // push required in read pointer because of
159                                     // write in current buffer
160    unsigned int total_push_in_rd_ptr = 0; // Total amount of push in read pointer in this write
161
162    if (record_length > rbc->each_buf_size) {
163        return RB_FAILURE;
164    }
165
166    if (overwrite == 0) {
167        /* Check if the complete RB is full. If the current wr_buf is also
168         * full, it indicates that the complete RB is full
169         */
170        if (rbc->bufs[rbc->wr_buf_no].full == 1)
171            return RB_FULL;
172        /* Check whether record fits in current buffer */
173        if (rbc->wr_buf_no == rbc->rd_buf_no) {
174            if ((rbc->cur_wr_buf_idx == rbc->cur_rd_buf_idx) &&
175                rbc->cur_valid_bytes) {
176                return RB_FULL;
177            } else if (rbc->cur_wr_buf_idx < rbc->cur_rd_buf_idx) {
178                if (record_length >
179                    (rbc->cur_rd_buf_idx - rbc->cur_wr_buf_idx)) {
180                    return RB_FULL;
181                }
182            } else {
183                if (record_length > (rbc->each_buf_size - rbc->cur_wr_buf_idx)) {
184                    /* Check if the next buffer is not full to write this record into
185                     * next buffer
186                     */
187                    unsigned int next_buf_no = rbc->wr_buf_no + 1;
188
189                    if (next_buf_no >= rbc->max_num_bufs) {
190                        next_buf_no = 0;
191                    }
192                    if (rbc->bufs[next_buf_no].full == 1) {
193                        return RB_FULL;
194                    }
195                }
196            }
197        } else if (record_length > (rbc->each_buf_size - rbc->cur_wr_buf_idx)) {
198            /* Check if the next buffer is not full to write this record into
199             * next buffer
200             */
201            unsigned int next_buf_no = rbc->wr_buf_no + 1;
202
203            if (next_buf_no >= rbc->max_num_bufs) {
204                next_buf_no = 0;
205            }
206            if (rbc->bufs[next_buf_no].full == 1) {
207                return RB_FULL;
208            }
209        }
210    }
211
212    /* Go to next buffer if the current buffer is not enough to write the
213     * complete record
214     */
215    if (record_length > (rbc->each_buf_size - rbc->cur_wr_buf_idx)) {
216        rbc->bufs[rbc->wr_buf_no].full = 1;
217        rbc->bufs[rbc->wr_buf_no].last_wr_index = rbc->cur_wr_buf_idx;
218        rbc->wr_buf_no++;
219        if (rbc->wr_buf_no == rbc->max_num_bufs) {
220            rbc->wr_buf_no = 0;
221        }
222        rbc->cur_wr_buf_idx = 0;
223    }
224
225
226    /* In each iteration of below loop, the data that can be fit into
227     * buffer @wr_buf_no will be copied from input buf */
228    while (bytes_written < length) {
229        unsigned int cur_copy_len;
230
231        /* Allocate a buffer if no buf available @ wr_buf_no */
232        if (rbc->bufs[rbc->wr_buf_no].data == NULL) {
233            rbc->bufs[rbc->wr_buf_no].data = (u8 *)malloc(rbc->each_buf_size);
234            if (rbc->bufs[rbc->wr_buf_no].data == NULL) {
235                ALOGE("Failed to alloc write buffer");
236                return RB_RETRY;
237            }
238        }
239
240        /* Take the minimum of the remaining length that needs to be written
241         * from buf and the maximum length that can be written into current
242         * buffer in ring buffer
243         */
244        cur_copy_len = RB_MIN((rbc->each_buf_size - rbc->cur_wr_buf_idx),
245                              (length - bytes_written));
246
247        rb_lock(&rbc->rb_rw_lock);
248
249        /* Push the read pointer in case of overrun */
250        if (rbc->rd_buf_no == rbc->wr_buf_no) {
251            if ((rbc->cur_rd_buf_idx > rbc->cur_wr_buf_idx) ||
252                ((rbc->cur_rd_buf_idx == rbc->cur_wr_buf_idx) &&
253                 rbc->cur_valid_bytes)) {
254                /* If read ptr is ahead of write pointer and if the
255                 * gap is not enough to fit the cur_copy_len bytes then
256                 * push the read pointer so that points to the start of
257                 * old bytes after this write
258                 */
259                if ((rbc->cur_rd_buf_idx - rbc->cur_wr_buf_idx) <
260                    cur_copy_len) {
261                    push_in_rd_ptr += cur_copy_len -
262                                    (rbc->cur_rd_buf_idx - rbc->cur_wr_buf_idx);
263                    rbc->cur_rd_buf_idx = rbc->cur_wr_buf_idx + cur_copy_len;
264                    if (rbc->cur_rd_buf_idx >=
265                        rbc->bufs[rbc->rd_buf_no].last_wr_index) {
266                        rbc->cur_rd_buf_idx = 0;
267                        rbc->rd_buf_no++;
268                        if (rbc->rd_buf_no == rbc->max_num_bufs) {
269                            rbc->rd_buf_no = 0;
270                            ALOGV("Pushing read to the start of ring buffer");
271                        }
272                        /* the previous buffer might have little more empty room
273                         * after overwriting the remaining bytes
274                         */
275                        rbc->bufs[rbc->wr_buf_no].full = 0;
276                    }
277                }
278            }
279        }
280        rb_unlock(&rbc->rb_rw_lock);
281
282        /* don't use lock while doing memcpy, so that we don't block the read
283         * context for too long. There is no harm while writing the memory if
284         * locking is properly done while upgrading the pointers */
285        memcpy((rbc->bufs[rbc->wr_buf_no].data + rbc->cur_wr_buf_idx),
286               (buf + bytes_written),
287               cur_copy_len);
288
289        rb_lock(&rbc->rb_rw_lock);
290        /* Update the write idx by the amount of write done in this iteration */
291        rbc->cur_wr_buf_idx += cur_copy_len;
292        if (rbc->cur_wr_buf_idx == rbc->each_buf_size) {
293            /* Increment the wr_buf_no as the current buffer is full */
294            rbc->bufs[rbc->wr_buf_no].full = 1;
295            rbc->bufs[rbc->wr_buf_no].last_wr_index = rbc->cur_wr_buf_idx;
296            rbc->wr_buf_no++;
297            if (rbc->wr_buf_no == rbc->max_num_bufs) {
298                ALOGV("Write rolling over to the start of ring buffer");
299                rbc->wr_buf_no = 0;
300            }
301            /* Reset the write index to zero as this is a new buffer */
302            rbc->cur_wr_buf_idx = 0;
303        }
304
305        if ((rbc->cur_valid_bytes + (cur_copy_len - push_in_rd_ptr)) >
306            (rbc->max_num_bufs * rbc->each_buf_size)) {
307            /* The below is only a precautionary print and ideally should never
308             * come */
309            ALOGE("Something going wrong in ring buffer");
310        } else {
311            /* Increase the valid bytes count by number of bytes written without
312             * overwriting the old bytes */
313            rbc->cur_valid_bytes += cur_copy_len - push_in_rd_ptr;
314        }
315        total_push_in_rd_ptr += push_in_rd_ptr;
316        push_in_rd_ptr = 0;
317        rb_unlock(&rbc->rb_rw_lock);
318        bytes_written += cur_copy_len;
319    }
320
321    rb_lock(&rbc->rb_rw_lock);
322    rbc->total_bytes_written += bytes_written - total_push_in_rd_ptr;
323    rbc->total_bytes_overwritten += total_push_in_rd_ptr;
324
325    /* check if valid bytes is going more than threshold */
326    if ((rbc->threshold_reached == RB_FALSE) &&
327        (rbc->cur_valid_bytes >= rbc->num_min_bytes) &&
328        ((length == record_length) || !record_length) &&
329        rbc->threshold_cb) {
330        /* Release the lock before calling threshold_cb as it might call rb_read
331         * in this same context in order to avoid dead lock
332         */
333        rbc->threshold_reached = RB_TRUE;
334        rb_unlock(&rbc->rb_rw_lock);
335        rbc->threshold_cb(rbc->cb_ctx);
336    } else {
337        rb_unlock(&rbc->rb_rw_lock);
338    }
339    return RB_SUCCESS;
340}
341
342size_t rb_read (void *ctx, u8 *buf, size_t max_length)
343{
344    rbc_t *rbc = (rbc_t *)ctx;
345    unsigned int bytes_read = 0;
346    unsigned int no_more_bytes_available = 0;
347
348    rb_lock(&rbc->rb_rw_lock);
349    while (bytes_read < max_length) {
350        unsigned int cur_cpy_len;
351
352        if (rbc->bufs[rbc->rd_buf_no].data == NULL) {
353            break;
354        }
355
356        /* if read and write are on same buffer, work with rd, wr indices */
357        if (rbc->rd_buf_no == rbc->wr_buf_no) {
358            if (rbc->cur_rd_buf_idx < rbc->cur_wr_buf_idx) {
359                /* Check if all the required bytes are available, if not
360                 * read only the available bytes in the current buffer and
361                 * break out after reading current buffer
362                 */
363                if ((rbc->cur_wr_buf_idx - rbc->cur_rd_buf_idx) <
364                        (max_length - bytes_read)) {
365                    cur_cpy_len = rbc->cur_wr_buf_idx - rbc->cur_rd_buf_idx;
366                    no_more_bytes_available = 1;
367                } else {
368                    cur_cpy_len = max_length - bytes_read;
369                }
370            } else {
371                /* When there are no bytes available to read cur_rd_buf_idx
372                 * will be euqal to cur_wr_buf_idx. Handle this scenario using
373                 * cur_valid_bytes */
374                if (rbc->cur_valid_bytes <= bytes_read) {
375                    /* Suppress possible static analyzer's warning */
376                    cur_cpy_len = 0;
377                    break;
378                }
379                cur_cpy_len = RB_MIN((rbc->each_buf_size - rbc->cur_rd_buf_idx),
380                                     (max_length - bytes_read));
381            }
382        } else {
383            /* Check if all remaining_length bytes can be read from this
384             * buffer, if not read only the available bytes in the current
385             * buffer and go to next buffer using the while loop.
386             */
387            cur_cpy_len = RB_MIN((rbc->each_buf_size - rbc->cur_rd_buf_idx),
388                                 (max_length - bytes_read));
389        }
390
391        memcpy((buf + bytes_read),
392               (rbc->bufs[rbc->rd_buf_no].data + rbc->cur_rd_buf_idx),
393               cur_cpy_len);
394
395        /* Update the read index */
396        rbc->cur_rd_buf_idx += cur_cpy_len;
397        if (rbc->cur_rd_buf_idx == rbc->each_buf_size) {
398            /* Increment rd_buf_no as the current buffer is completely read */
399            if (rbc->rd_buf_no != rbc->wr_buf_no) {
400                free(rbc->bufs[rbc->rd_buf_no].data);
401                rbc->bufs[rbc->rd_buf_no].data = NULL;
402            }
403            rbc->rd_buf_no++;
404            if (rbc->rd_buf_no == rbc->max_num_bufs) {
405                ALOGV("Read rolling over to the start of ring buffer");
406                rbc->rd_buf_no = 0;
407            }
408            /* Reset the read index as this is a new buffer */
409            rbc->cur_rd_buf_idx = 0;
410        }
411
412        bytes_read += cur_cpy_len;
413        if (no_more_bytes_available) {
414            break;
415        }
416    }
417
418    rbc->total_bytes_read += bytes_read;
419    if (rbc->cur_valid_bytes < bytes_read) {
420        /* The below is only a precautionary print and ideally should never
421         * come */
422        ALOGE("Something going wrong in ring buffer");
423    } else {
424        rbc->cur_valid_bytes -= bytes_read;
425    }
426
427    /* check if valid bytes is going less than threshold */
428    if (rbc->threshold_reached == RB_TRUE) {
429        if (rbc->cur_valid_bytes < rbc->num_min_bytes) {
430            rbc->threshold_reached = RB_FALSE;
431        }
432    }
433    rb_unlock(&rbc->rb_rw_lock);
434    return bytes_read;
435}
436
437u8 *rb_get_read_buf(void *ctx, size_t *length)
438{
439    rbc_t *rbc = (rbc_t *)ctx;
440    unsigned int cur_read_len = 0;
441    u8 *buf;
442
443    /* If no buffer is available for reading */
444    if (rbc->bufs[rbc->rd_buf_no].data == NULL) {
445        *length = 0;
446        return NULL;
447    }
448
449    rb_lock(&rbc->rb_rw_lock);
450    if ((rbc->bufs[rbc->rd_buf_no].full == 1) &&
451        (rbc->cur_rd_buf_idx == rbc->bufs[rbc->rd_buf_no].last_wr_index)) {
452        if (rbc->wr_buf_no != rbc->rd_buf_no) {
453            free(rbc->bufs[rbc->rd_buf_no].data);
454            rbc->bufs[rbc->rd_buf_no].data = NULL;
455        }
456        rbc->bufs[rbc->rd_buf_no].full = 0;
457        rbc->rd_buf_no++;
458        if (rbc->rd_buf_no == rbc->max_num_bufs) {
459            rbc->rd_buf_no = 0;
460        }
461        rbc->cur_rd_buf_idx = 0;
462    }
463
464    if (rbc->wr_buf_no == rbc->rd_buf_no) {
465        /* If read and write are happening on the same buffer currently, use
466         * rd and wr indices within the buffer */
467        if ((rbc->cur_rd_buf_idx == rbc->cur_wr_buf_idx) &&
468            (rbc->cur_valid_bytes == 0)) {
469            /* No bytes available for reading */
470            *length = 0;
471            rb_unlock(&rbc->rb_rw_lock);
472            return NULL;
473        } else if (rbc->cur_rd_buf_idx < rbc->cur_wr_buf_idx) {
474            /* write is just ahead of read in this buffer */
475            cur_read_len = rbc->cur_wr_buf_idx - rbc->cur_rd_buf_idx;
476        } else {
477            /* write is rolled over and just behind the read */
478            cur_read_len = rbc->bufs[rbc->rd_buf_no].last_wr_index - rbc->cur_rd_buf_idx;
479        }
480    } else {
481        if (rbc->cur_rd_buf_idx == 0) {
482            /* The complete buffer can be read out */
483            cur_read_len = rbc->bufs[rbc->rd_buf_no].last_wr_index;
484        } else {
485            /* Read the remaining bytes in this buffer */
486            cur_read_len = rbc->bufs[rbc->rd_buf_no].last_wr_index - rbc->cur_rd_buf_idx;
487        }
488    }
489
490    if ((rbc->bufs[rbc->rd_buf_no].full == 1) &&
491         (rbc->cur_rd_buf_idx == 0)) {
492        /* Pluck out the complete buffer and send it out */
493        buf = rbc->bufs[rbc->rd_buf_no].data;
494        rbc->bufs[rbc->rd_buf_no].data = NULL;
495
496        /* Move to the next buffer */
497        rbc->bufs[rbc->rd_buf_no].full = 0;
498        rbc->rd_buf_no++;
499        if (rbc->rd_buf_no == rbc->max_num_bufs) {
500            ALOGV("Read rolling over to the start of ring buffer");
501            rbc->rd_buf_no = 0;
502        }
503    } else {
504        /* We cannot give out the complete buffer, so allocate a new memory and
505         * and copy the data into it.
506         */
507        buf = (u8 *)malloc(cur_read_len);
508        if (buf == NULL) {
509            ALOGE("Failed to alloc buffer for partial buf read");
510            *length = 0;
511            rb_unlock(&rbc->rb_rw_lock);
512            return NULL;
513        }
514        memcpy(buf,
515               (rbc->bufs[rbc->rd_buf_no].data + rbc->cur_rd_buf_idx),
516               cur_read_len);
517
518        /* Update the read index */
519        if (rbc->bufs[rbc->rd_buf_no].full == 1) {
520            if (rbc->wr_buf_no != rbc->rd_buf_no) {
521                free(rbc->bufs[rbc->rd_buf_no].data);
522                rbc->bufs[rbc->rd_buf_no].data = NULL;
523            }
524            rbc->bufs[rbc->rd_buf_no].full = 0;
525            rbc->rd_buf_no++;
526            if (rbc->rd_buf_no == rbc->max_num_bufs) {
527                rbc->rd_buf_no = 0;
528            }
529            rbc->cur_rd_buf_idx = 0;
530        } else {
531            rbc->cur_rd_buf_idx += cur_read_len;
532        }
533    }
534
535    rbc->total_bytes_read += cur_read_len;
536    if (rbc->cur_valid_bytes < cur_read_len) {
537        /* The below is only a precautionary print and ideally should never
538         * come */
539        ALOGE("Something going wrong in ring buffer");
540    } else {
541        rbc->cur_valid_bytes -= cur_read_len;
542    }
543
544    /* check if valid bytes is going less than threshold */
545    if (rbc->threshold_reached == RB_TRUE) {
546        if (rbc->cur_valid_bytes < rbc->num_min_bytes) {
547            rbc->threshold_reached = RB_FALSE;
548        }
549    }
550    rb_unlock(&rbc->rb_rw_lock);
551
552    *length = cur_read_len;
553    return buf;
554}
555
556void rb_config_threshold(void *ctx,
557                         unsigned int num_min_bytes,
558                         threshold_call_back callback,
559                         void *cb_ctx)
560{
561    rbc_t *rbc = (rbc_t *)ctx;
562
563    rbc->num_min_bytes = num_min_bytes;
564    rbc->threshold_cb = callback;
565    rbc->cb_ctx = cb_ctx;
566}
567
568void rb_get_stats(void *ctx, struct rb_stats *rbs)
569{
570    rbc_t *rbc = (rbc_t *)ctx;
571
572    rbs->total_bytes_written = rbc->total_bytes_written;
573    rbs->total_bytes_read = rbc->total_bytes_read;
574    rbs->cur_valid_bytes = rbc->cur_valid_bytes;
575    rbs->each_buf_size = rbc->each_buf_size;
576    rbs->max_num_bufs = rbc->max_num_bufs;
577}
578