1// Copyright 2016 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "hid-fifo.h"
6
7#include <stdlib.h>
8#include <stdio.h>
9#include <string.h>
10
11#define min(a,b) ((a) < (b) ? (a) : (b))
12
13zx_status_t zx_hid_fifo_create(zx_hid_fifo_t** fifo) {
14    *fifo = malloc(sizeof(zx_hid_fifo_t));
15    if (*fifo == NULL)
16        return ZX_ERR_NO_MEMORY;
17    zx_hid_fifo_init(*fifo);
18    return ZX_OK;
19}
20
21void zx_hid_fifo_init(zx_hid_fifo_t* fifo) {
22    memset(fifo->buf, 0, HID_FIFO_SIZE);
23    fifo->head = fifo->tail = 0;
24    fifo->empty = true;
25    mtx_init(&fifo->lock, mtx_plain);
26}
27
28size_t zx_hid_fifo_size(zx_hid_fifo_t* fifo) {
29    if (fifo->empty) return 0;
30    if (fifo->head > fifo->tail)
31        return fifo->head - fifo->tail;
32    return HID_FIFO_SIZE - fifo->tail + fifo->head;
33}
34
35ssize_t zx_hid_fifo_peek(zx_hid_fifo_t* fifo, void* out) {
36    if (fifo->empty)
37        return 0;
38    *(uint8_t*)out = fifo->buf[fifo->tail];
39    return 1;
40}
41
42ssize_t zx_hid_fifo_read(zx_hid_fifo_t* fifo, void* buf, size_t len) {
43    if (!buf) return ZX_ERR_INVALID_ARGS;
44    if (fifo->empty) return 0;
45    if (!len) return 0;
46
47    len = min(zx_hid_fifo_size(fifo), len);
48    for (size_t c = len; c > 0; c--, fifo->tail = (fifo->tail + 1) & HID_FIFO_MASK) {
49        *(uint8_t*)buf++ = fifo->buf[fifo->tail];
50    }
51    if (fifo->tail == fifo->head) fifo->empty = true;
52    return len;
53}
54
55ssize_t zx_hid_fifo_write(zx_hid_fifo_t* fifo, const void* buf, size_t len) {
56    if (!fifo->empty && fifo->tail == fifo->head) return ZX_ERR_BUFFER_TOO_SMALL;
57    if (len > HID_FIFO_SIZE - zx_hid_fifo_size(fifo)) return ZX_ERR_BUFFER_TOO_SMALL;
58
59    for (size_t c = len; c > 0; c--, fifo->head = (fifo->head + 1) & HID_FIFO_MASK) {
60        fifo->buf[fifo->head] = *(uint8_t*)buf++;
61    }
62    fifo->empty = false;
63    return len;
64}
65
66void zx_hid_fifo_dump(zx_hid_fifo_t* fifo) {
67    printf("zx_hid_fifo_dump %p\n", fifo);
68    printf("head: %u  tail: %u  empty: %s\n", fifo->head, fifo->tail, fifo->empty ? "Y" : "N");
69    if (fifo->empty) {
70        return;
71    }
72    uint32_t c = fifo->tail;
73    int i = 0;
74    do {
75        printf("%02x ", fifo->buf[c]);
76        if (i++ % 8 == 7) printf("\n");
77        c = (c + 1) & HID_FIFO_MASK;
78    } while (c != fifo->head);
79    printf("\n");
80}
81