1/*
2 *
3 * Copyright 2012 Samsung Electronics S.LSI Co. LTD
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18/*
19 * @file        srp_api.c
20 * @brief
21 * @author      Yunji Kim (yunji.kim@samsung.com)
22 * @version     1.1.0
23 * @history
24 *   2012.02.28 : Create
25 */
26
27#include <sys/types.h>
28#include <sys/stat.h>
29#include <sys/ioctl.h>
30#include <sys/mman.h>
31#include <sys/time.h>
32#include <fcntl.h>
33#include <ctype.h>
34#include <unistd.h>
35#include <string.h>
36#include <errno.h>
37#include <stdio.h>
38
39#include "srp_api.h"
40
41#define LOG_NDEBUG 1
42#define LOG_TAG "libsrpapi"
43#include <utils/Log.h>
44
45static struct srp_buf_info ibuf_info;
46static struct srp_buf_info obuf_info;
47static struct srp_buf_info pcm_info;
48
49static int srp_dev = -1;
50static int srp_block_mode = SRP_INIT_BLOCK_MODE;
51
52int SRP_Create(int block_mode)
53{
54    if (srp_dev == -1) {
55        srp_block_mode = block_mode;
56        srp_dev = open(SRP_DEV_NAME, O_RDWR |
57                    ((block_mode == SRP_INIT_NONBLOCK_MODE) ? O_NDELAY : 0));
58        if (srp_dev > 0)
59            return srp_dev;
60        else
61            return SRP_ERROR_OPEN_FAIL;
62    }
63
64    ALOGE("%s: Device is already opened", __func__);
65    return SRP_ERROR_ALREADY_OPEN;
66}
67
68int SRP_Init()
69{
70    int ret = SRP_RETURN_OK;
71    unsigned int mmapped_size = 0;
72
73    if (srp_dev != -1) {
74        ret = ioctl(srp_dev, SRP_INIT);
75        if (ret < 0)
76            return ret;
77
78        /* mmap for OBUF */
79        ret = ioctl(srp_dev, SRP_GET_MMAP_SIZE, &mmapped_size);
80        if (ret < 0) {
81            ALOGE("%s: SRP_GET_MMAP_SIZE is failed", __func__);
82            return SRP_ERROR_OBUF_MMAP;
83        }
84        obuf_info.mmapped_addr = mmap(0, mmapped_size,
85                    PROT_READ | PROT_WRITE, MAP_SHARED, srp_dev, 0);
86        if (!obuf_info.mmapped_addr) {
87            ALOGE("%s: mmap is failed", __func__);
88            return SRP_ERROR_OBUF_MMAP;
89        }
90        obuf_info.mmapped_size = mmapped_size;
91
92        ret = SRP_RETURN_OK;
93    } else {
94        ALOGE("%s: Device is not ready", __func__);
95        ret = SRP_ERROR_NOT_READY; /* device is not created */
96    }
97
98    return ret;
99}
100
101int SRP_Decode(void *buff, int size_byte)
102{
103    int ret = SRP_RETURN_OK;
104
105    if (srp_dev != -1) {
106        if (size_byte > 0) {
107            ALOGV("%s: Send data to RP (%d bytes)", __func__, size_byte);
108
109            ret = write(srp_dev, buff, size_byte);  /* Write Buffer to RP Driver */
110            if (ret < 0) {
111                if (ret != SRP_ERROR_IBUF_OVERFLOW)
112                    ALOGE("SRP_Decode returned error code: %d", ret);
113            }
114            return ret; /* Write Success */
115        } else {
116            return ret;
117        }
118    }
119
120    ALOGE("%s: Device is not ready", __func__);
121    return SRP_ERROR_NOT_READY;
122}
123
124int SRP_Send_EOS(void)
125{
126    if (srp_dev != -1)
127        return ioctl(srp_dev, SRP_SEND_EOS);
128
129    return SRP_ERROR_NOT_READY;
130}
131
132int SRP_SetParams(int id, unsigned long val)
133{
134    if (srp_dev != -1)
135        return 0; /* not yet */
136
137    return SRP_ERROR_NOT_READY;
138}
139
140int SRP_GetParams(int id, unsigned long *pval)
141{
142    if (srp_dev != -1)
143        return ioctl(srp_dev, id, pval);
144
145    return SRP_ERROR_NOT_READY;
146}
147
148int SRP_Flush(void)
149{
150    if (srp_dev != -1)
151        return ioctl(srp_dev, SRP_FLUSH);
152
153    return SRP_ERROR_NOT_READY;
154}
155
156int SRP_Get_PCM(void **addr, unsigned int *size)
157{
158    int ret = SRP_RETURN_OK;
159
160    if (srp_dev != -1) {
161        ret = read(srp_dev, &pcm_info, 0);
162        if (ret == -1) {
163            *size = 0;
164            ALOGE("%s: PCM read fail", __func__);
165            return SRP_ERROR_OBUF_READ;
166        }
167
168        *addr = pcm_info.addr;
169        *size = pcm_info.size;
170    } else {
171        return SRP_ERROR_NOT_READY;
172    }
173
174    return ret; /* Read Success */
175}
176
177int SRP_Get_Dec_Info(struct srp_dec_info *dec_info)
178{
179    int ret;
180
181    if (srp_dev != -1) {
182        ret = ioctl(srp_dev, SRP_GET_DEC_INFO, dec_info);
183        if (ret < 0) {
184            ALOGE("%s: Failed to get dec info", __func__);
185            return SRP_ERROR_GETINFO_FAIL;
186        }
187
188        ALOGV("numChannels(%d), samplingRate(%d)", dec_info->channels, dec_info->sample_rate);
189
190        ret = SRP_RETURN_OK;
191    } else {
192        ret = SRP_ERROR_NOT_READY;
193    }
194
195    return ret;
196}
197
198int SRP_Get_Ibuf_Info(void **addr, unsigned int *size, unsigned int *num)
199{
200    int ret = SRP_RETURN_OK;
201
202    if (srp_dev != -1) {
203        ret = ioctl(srp_dev, SRP_GET_IBUF_INFO, &ibuf_info);
204        if (ret == -1) {
205            ALOGE("%s: Failed to get Ibuf info", __func__);
206            return SRP_ERROR_IBUF_INFO;
207        }
208
209        *addr = ibuf_info.addr;
210        *size = ibuf_info.size;
211        *num = ibuf_info.num;
212
213        if (*num == 0) {
214            ALOGE("%s: IBUF num is 0", __func__);
215            return SRP_ERROR_INVALID_SETTING;
216        }
217
218        ret = SRP_RETURN_OK;
219    } else {
220        ret = SRP_ERROR_NOT_READY;
221    }
222
223    return ret;
224}
225
226int SRP_Get_Obuf_Info(void **addr, unsigned int *size, unsigned int *num)
227{
228    int ret = SRP_RETURN_OK;
229
230    if (srp_dev != -1) {
231        if (obuf_info.addr == NULL) {
232            ret = ioctl(srp_dev, SRP_GET_OBUF_INFO, &obuf_info);
233            if (ret < 0) {
234                ALOGE("%s: SRP_GET_OBUF_INFO is failed", __func__);
235                return SRP_ERROR_OBUF_INFO;
236            }
237        }
238
239        *addr = obuf_info.addr;
240        *size = obuf_info.size;
241        *num = obuf_info.num;
242
243        if (*num == 0) {
244            ALOGE("%s: OBUF num is 0", __func__);
245            return SRP_ERROR_INVALID_SETTING;
246        }
247
248        ret = SRP_RETURN_OK;
249    } else {
250        ret = SRP_ERROR_NOT_READY;
251    }
252
253    return ret;
254}
255
256int SRP_Deinit(void)
257{
258    if (srp_dev != -1) {
259        munmap(obuf_info.mmapped_addr, obuf_info.mmapped_size);
260        return ioctl(srp_dev, SRP_DEINIT);
261    }
262
263    return SRP_ERROR_NOT_READY;
264}
265
266int SRP_Terminate(void)
267{
268    int ret;
269
270    if (srp_dev != -1) {
271        ret = close(srp_dev);
272
273        if (ret == 0) {
274            srp_dev = -1; /* device closed */
275            return SRP_RETURN_OK;
276        }
277    }
278
279    return SRP_ERROR_NOT_READY;
280}
281
282int SRP_IsOpen(void)
283{
284    if (srp_dev == -1) {
285        ALOGV("%s: Device is not opened", __func__);
286        return 0;
287    }
288
289    ALOGV("%s: Device is opened", __func__);
290    return 1;
291}
292