aboutsummaryrefslogtreecommitdiffstats
path: root/Transceiver52M/device/ipc/shm.c
blob: cafb4f262ad2de9fc32a2e0ae68fe36e52e261f8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <osmocom/core/talloc.h>

#include "shm.h"

/* Convert offsets to pointers */
struct ipc_shm_stream *ipc_shm_decode_stream(void *tall_ctx, struct ipc_shm_raw_region *root_raw, struct ipc_shm_raw_stream *stream_raw)
{
        int i;
        struct ipc_shm_stream *stream;
        stream = talloc_zero(tall_ctx, struct ipc_shm_stream);
        stream = talloc_zero_size(tall_ctx, sizeof(struct ipc_shm_stream) +
                                          sizeof(struct ipc_shm_raw_smpl_buf *) * stream_raw->num_buffers);
        if (!stream)
                return NULL;
        stream->num_buffers = stream_raw->num_buffers;
        stream->buffer_size = stream_raw->buffer_size;
        stream->raw = stream_raw;
        for (i = 0; i < stream->num_buffers; i++) {
                fprintf(stderr, "decode: smpl_buf %d at offset %u\n", i, stream_raw->buffer_offset[i]);
                stream->buffers[i] = (struct ipc_shm_raw_smpl_buf *)(((uint8_t*)root_raw) + stream_raw->buffer_offset[i]);
        }
        return stream;
}

struct ipc_shm_channel *ipc_shm_decode_channel(void *tall_ctx, struct ipc_shm_raw_region *root_raw, struct ipc_shm_raw_channel *chan_raw)
{
        struct ipc_shm_channel *chan;
        chan = talloc_zero(tall_ctx, struct ipc_shm_channel);
        if (!chan)
                return NULL;
        fprintf(stderr, "decode: streams at offset %u and %u\n", chan_raw->dl_buf_offset, chan_raw->ul_buf_offset);
        chan->dl_stream = ipc_shm_decode_stream(chan, root_raw, (struct ipc_shm_raw_stream *)(((uint8_t*)root_raw) + chan_raw->dl_buf_offset));
        chan->ul_stream = ipc_shm_decode_stream(chan, root_raw, (struct ipc_shm_raw_stream *)(((uint8_t*)root_raw) + chan_raw->ul_buf_offset));
        return chan;
}
struct ipc_shm_region *ipc_shm_decode_region(void *tall_ctx, struct ipc_shm_raw_region *root_raw)
{
        int i;
        struct ipc_shm_region *root;
        root = talloc_zero_size(tall_ctx, sizeof(struct ipc_shm_region) +
                                          sizeof(struct ipc_shm_channel*) * root_raw->num_chans);
	if (!root)
		return NULL;

        root->num_chans = root_raw->num_chans;
        for (i = 0; i < root->num_chans; i++) {
                fprintf(stderr, "decode: channel %d at offset %u\n", i, root_raw->chan_offset[i]);
                root->channels[i] = ipc_shm_decode_channel(root, root_raw, (struct ipc_shm_raw_channel *)(((uint8_t*)root_raw) + root_raw->chan_offset[i]));
        }
        return root;
}

unsigned int ipc_shm_encode_smpl_buf(struct ipc_shm_raw_region *root_raw, struct ipc_shm_raw_smpl_buf *smpl_buf_raw, uint32_t buffer_size)
{
        uint8_t* start = (uint8_t*)smpl_buf_raw;
        unsigned int offset = sizeof(struct ipc_shm_raw_smpl_buf);

        fprintf(stderr, "encode: smpl_buf at offset %lu\n", (start - (uint8_t*)root_raw));

        offset += buffer_size * sizeof(uint16_t); /* samples */
        return offset;
}

unsigned int ipc_shm_encode_stream(struct ipc_shm_raw_region *root_raw, struct ipc_shm_raw_stream *stream_raw, uint32_t num_buffers, uint32_t buffer_size)
{
        int i;
        uint8_t* start = (uint8_t*)stream_raw;
        unsigned int offset = sizeof(struct ipc_shm_raw_stream) + sizeof(uint32_t)*num_buffers;

        fprintf(stderr, "encode: stream at offset %lu\n", (start - (uint8_t*)root_raw));

        if (root_raw) {
                stream_raw->num_buffers = num_buffers;
                stream_raw->buffer_size = buffer_size;
                stream_raw->read_next = 0;
                stream_raw->write_next = 0;
        }
        for (i = 0; i < num_buffers; i++) {
                if (root_raw)
                        stream_raw->buffer_offset[i] = (start + offset - (uint8_t*)root_raw);
                offset += ipc_shm_encode_smpl_buf(root_raw, (struct ipc_shm_raw_smpl_buf *)(start + offset), buffer_size);
        }
        return offset;
}
unsigned int ipc_shm_encode_channel(struct ipc_shm_raw_region *root_raw, struct ipc_shm_raw_channel *chan_raw, uint32_t num_buffers, uint32_t buffer_size)
{
        uint8_t* start = (uint8_t*)chan_raw;
        unsigned int offset = sizeof(struct ipc_shm_raw_channel);

        fprintf(stderr, "encode: channel at offset %lu\n", (start - (uint8_t*)root_raw));

        if (root_raw)
                chan_raw->dl_buf_offset = (start + offset - (uint8_t*)root_raw);
        offset += ipc_shm_encode_stream(root_raw, (struct ipc_shm_raw_stream *)(start + offset), num_buffers, buffer_size);
        if (root_raw)
                chan_raw->ul_buf_offset = (start + offset - (uint8_t*)root_raw);
        offset += ipc_shm_encode_stream(root_raw, (struct ipc_shm_raw_stream *)(start + offset), num_buffers, buffer_size);
        return offset;
}
/* if root_raw is NULL, then do a dry run, aka only calculate final offset */
unsigned int ipc_shm_encode_region(struct ipc_shm_raw_region *root_raw, uint32_t num_chans, uint32_t num_buffers, uint32_t buffer_size)
{
        int i;
        uint8_t* start = (uint8_t*)root_raw;
        unsigned int offset = sizeof(struct ipc_shm_raw_region) + sizeof(uint32_t)*num_chans;

        if (root_raw)
                root_raw->num_chans = num_chans;
        for (i = 0; i < num_chans; i++) {
                if (root_raw) {
                        root_raw->chan_offset[i] = (start + offset - (uint8_t*)root_raw);
                        fprintf(stderr, "encode: channel %d chan_offset[i]=%u\n", i, root_raw->chan_offset[i]);
                        offset += ipc_shm_encode_channel(root_raw, (struct ipc_shm_raw_channel *)(start + offset), num_buffers, buffer_size);
                }
        }
        //TODO: pass maximum size and verify we didn't go through
        return offset;
}