e3c280387dd74dd225794292f6d4046e3efdf341
[platform/core/api/radio.git] / src / radio.c
1 /*
2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <mm_types.h>
21 #include <radio_private.h>
22 #include <dlog.h>
23 #include <glib.h>
24 #include <system_info.h>
25
26 #ifdef LOG_TAG
27 #undef LOG_TAG
28 #endif
29 #define LOG_TAG "TIZEN_N_RADIO"
30
31 /*
32 * Internal Macros
33 */
34 #define RADIO_CHECK_CONDITION(condition, error, msg)    \
35         do {    \
36                 if (condition) { \
37                 } else {        \
38                         LOGE("%s(0x%08x)", msg, error); \
39                         return error;   \
40                 } \
41         } while (0)
42
43 #define RADIO_INSTANCE_CHECK(radio)     \
44         RADIO_CHECK_CONDITION(radio != NULL, RADIO_ERROR_INVALID_PARAMETER, "RADIO_ERROR_INVALID_PARAMETER")
45
46 #define RADIO_STATE_CHECK(radio, expected_state)        \
47         RADIO_CHECK_CONDITION(radio->state == expected_state, RADIO_ERROR_INVALID_STATE, "RADIO_ERROR_INVALID_STATE")
48
49 #define RADIO_NULL_ARG_CHECK(arg)       \
50         RADIO_CHECK_CONDITION(arg != NULL, RADIO_ERROR_INVALID_PARAMETER, "RADIO_ERROR_INVALID_PARAMETER")
51
52 #define RADIO_SUPPORT_CHECK(arg)        \
53         RADIO_CHECK_CONDITION(arg != false, RADIO_ERROR_NOT_SUPPORTED, "RADIO_ERROR_NOT_SUPPORTED")
54
55 /*
56 * Internal Implementation
57 */
58 static int __convert_error_code(int code, char *func_name)
59 {
60         int ret = RADIO_ERROR_NONE;
61         char *msg = "RADIO_ERROR_NONE";
62         LOGI("Enter code :%x", code);
63         switch (code) {
64         case MM_ERROR_NONE:
65                 ret = RADIO_ERROR_NONE;
66                 msg = "RADIO_ERROR_NONE";
67                 break;
68         case MM_ERROR_RADIO_NO_FREE_SPACE:
69         case MM_ERROR_OUT_OF_MEMORY:
70                 ret = RADIO_ERROR_OUT_OF_MEMORY;
71                 msg = "RADIO_ERROR_OUT_OF_MEMORY";
72                 break;
73         case MM_ERROR_RADIO_NOT_INITIALIZED:
74         case MM_ERROR_RADIO_NO_OP:
75         case MM_ERROR_RADIO_INVALID_STATE:
76                 ret = RADIO_ERROR_INVALID_STATE;
77                 msg = "RADIO_ERROR_INVALID_STATE";
78                 break;
79         case MM_ERROR_COMMON_INVALID_ARGUMENT:
80         case MM_ERROR_INVALID_ARGUMENT:
81                 ret = RADIO_ERROR_INVALID_PARAMETER;
82                 msg = "RADIO_ERROR_INVALID_PARAMETER";
83                 break;
84         case MM_ERROR_POLICY_BLOCKED:
85         case MM_ERROR_POLICY_INTERRUPTED:
86         case MM_ERROR_POLICY_INTERNAL:
87         case MM_ERROR_POLICY_DUPLICATED:
88                 ret = RADIO_ERROR_SOUND_POLICY;
89                 msg = "RADIO_ERROR_SOUND_POLICY";
90                 break;
91         case MM_ERROR_RADIO_DEVICE_NOT_FOUND:
92                 ret = RADIO_ERROR_NOT_SUPPORTED;
93                 msg = "RADIO_ERROR_NOT_SUPPORTED";
94                 break;
95         case MM_ERROR_RADIO_NO_ANTENNA:
96                 ret = RADIO_ERROR_NO_ANTENNA;
97                 msg = "RADIO_ERROR_NO_ANTENNA";
98                 break;
99         case MM_ERROR_RADIO_DEVICE_NOT_OPENED:
100         case MM_ERROR_RADIO_PERMISSION_DENIED:
101                 ret = RADIO_ERROR_PERMISSION_DENIED;
102                 msg = "RADIO_ERROR_PERMISSION_DENIED";
103                 break;
104         case MM_ERROR_NOT_IMPLEMENTED:
105         case MM_ERROR_RADIO_INTERNAL:
106         case MM_ERROR_RADIO_RESPONSE_TIMEOUT:
107         default:
108                 ret = RADIO_ERROR_INVALID_OPERATION;
109                 msg = "RADIO_ERROR_INVALID_OPERATION";
110                 break;
111         }
112         LOGE("[%s] %s(0x%08x) : core fw error(0x%x)", func_name, msg, ret, code);
113         return ret;
114 }
115
116 static radio_state_e __convert_radio_state(MMRadioStateType state)
117 {
118         int converted_state = RADIO_STATE_READY;
119         LOGI("Enter state: %d", state);
120         switch (state) {
121
122         case MM_RADIO_STATE_PLAYING:
123                 converted_state = RADIO_STATE_PLAYING;
124                 break;
125         case MM_RADIO_STATE_SCANNING:
126                 converted_state = RADIO_STATE_SCANNING;
127                 break;
128         case MM_RADIO_STATE_NULL:
129         case MM_RADIO_STATE_READY:
130         default:
131                 converted_state = RADIO_STATE_READY;
132                 break;
133         }
134         LOGI("Leave converted_state: %d", converted_state);
135         return converted_state;
136 }
137
138 static int __set_callback(_radio_event_e type, radio_h radio, void *callback, void *user_data)
139 {
140         RADIO_INSTANCE_CHECK(radio);
141         RADIO_NULL_ARG_CHECK(callback);
142         radio_s *handle = (radio_s *)radio;
143         handle->user_cb[type] = callback;
144         handle->user_data[type] = user_data;
145         LOGI("Event type : %d", type);
146         return RADIO_ERROR_NONE;
147 }
148
149 static int __unset_callback(_radio_event_e type, radio_h radio)
150 {
151         RADIO_INSTANCE_CHECK(radio);
152         radio_s *handle = (radio_s *)radio;
153         handle->user_cb[type] = NULL;
154         handle->user_data[type] = NULL;
155         LOGI("Event type : %d", type);
156         return RADIO_ERROR_NONE;
157 }
158
159 static int __msg_callback(int message, void *param, void *user_data)
160 {
161         radio_s *handle = (radio_s *)user_data;
162         MMMessageParamType *msg = (MMMessageParamType *)param;
163         LOGI("Got message type : 0x%x", message);
164         switch (message) {
165         case MM_MESSAGE_RADIO_SCAN_INFO:
166                 if (handle->user_cb[_RADIO_EVENT_TYPE_SCAN_INFO])
167                         ((radio_scan_updated_cb)handle->user_cb[_RADIO_EVENT_TYPE_SCAN_INFO])(msg->radio_scan.frequency, handle->user_data[_RADIO_EVENT_TYPE_SCAN_INFO]);
168                 break;
169         case MM_MESSAGE_RADIO_SCAN_STOP:
170                 if (handle->user_cb[_RADIO_EVENT_TYPE_SCAN_STOP])
171                         ((radio_scan_stopped_cb)handle->user_cb[_RADIO_EVENT_TYPE_SCAN_STOP])(handle->user_data[_RADIO_EVENT_TYPE_SCAN_STOP]);
172                 __unset_callback(_RADIO_EVENT_TYPE_SCAN_STOP, (radio_h)handle);
173                 __unset_callback(_RADIO_EVENT_TYPE_SCAN_INFO, (radio_h)handle);
174                 break;
175         case MM_MESSAGE_RADIO_SCAN_FINISH:
176                 if (handle->user_cb[_RADIO_EVENT_TYPE_SCAN_FINISH])
177                         ((radio_scan_completed_cb)handle->user_cb[_RADIO_EVENT_TYPE_SCAN_FINISH])(handle->user_data[_RADIO_EVENT_TYPE_SCAN_FINISH]);
178                 __unset_callback(_RADIO_EVENT_TYPE_SCAN_INFO, (radio_h)handle);
179                 break;
180         case MM_MESSAGE_RADIO_SEEK_FINISH:
181                 if (handle->user_cb[_RADIO_EVENT_TYPE_SEEK_FINISH]) {
182                         ((radio_seek_completed_cb)handle->user_cb[_RADIO_EVENT_TYPE_SEEK_FINISH])(msg->radio_scan.frequency, handle->user_data[_RADIO_EVENT_TYPE_SEEK_FINISH]);
183                         handle->seeking = false;
184                 }
185                 __unset_callback(_RADIO_EVENT_TYPE_SEEK_FINISH, (radio_h)handle);
186                 break;
187         //LCOV_EXCL_START
188         case MM_MESSAGE_STATE_INTERRUPTED:
189                 if (msg->union_type == MM_MSG_UNION_STATE) {
190                         handle->state = __convert_radio_state(msg->state.current);
191                         if (handle->user_cb[_RADIO_EVENT_TYPE_INTERRUPT])
192                                 ((radio_interrupted_cb)handle->user_cb[_RADIO_EVENT_TYPE_INTERRUPT])(RADIO_INTERRUPTED_BY_RESOURCE_CONFLICT, handle->user_data[_RADIO_EVENT_TYPE_INTERRUPT]);
193                 }
194                 break;
195         case MM_MESSAGE_ERROR:
196                 __convert_error_code(msg->code, (char *)__FUNCTION__);
197                 break;
198         //LCOV_EXCL_STOP
199         case MM_MESSAGE_RADIO_SCAN_START:
200                 LOGI("Scan Started");
201                 break;
202         case MM_MESSAGE_STATE_CHANGED:
203                 handle->state = __convert_radio_state(msg->state.current);
204                 LOGI("State Changed --- from : %d , to : %d", __convert_radio_state(msg->state.previous), handle->state);
205                 break;
206         case MM_MESSAGE_RADIO_SEEK_START:
207                 LOGI("Seek Started");
208                 break;
209         default:
210                 break;
211         }
212         return 1;
213 }
214
215 static int __radio_check_system_info_feature_supported()
216 {
217         bool val = false;
218         int ret = false;
219
220         ret = system_info_get_platform_bool("http://tizen.org/feature/fmradio", &val);
221
222         if (ret != SYSTEM_INFO_ERROR_NONE) {
223                 LOGE("SYSTEM_INFO_ERROR");
224                 return false;
225         }
226
227         if (val == false)
228                 LOGI("system_info_get_platform_bool returned Unsupported feature capability");
229         else
230                 LOGI("system_info_get_platform_bool returned Supported status feature");
231
232         return val;
233 }
234
235 /*
236 * Public Implementation
237 */
238 int radio_create(radio_h *radio)
239 {
240         LOGI("Enter");
241         RADIO_SUPPORT_CHECK(__radio_check_system_info_feature_supported());
242         RADIO_INSTANCE_CHECK(radio);
243         radio_s *handle;
244
245         handle = (radio_s *)malloc(sizeof(radio_s));
246         if (!handle) {
247                 LOGE("RADIO_ERROR_OUT_OF_MEMORY(0x%08x)", RADIO_ERROR_OUT_OF_MEMORY);
248                 return RADIO_ERROR_OUT_OF_MEMORY;
249         }
250
251         memset(handle, 0, sizeof(radio_s));
252
253         int ret = mm_radio_create(&handle->mm_handle);
254         if (ret != MM_ERROR_NONE) {
255                 free(handle);
256                 handle = NULL;
257                 return __convert_error_code(ret, (char *)__FUNCTION__);
258         }
259
260         *radio = (radio_h)handle;
261
262         ret = mm_radio_set_message_callback(handle->mm_handle, __msg_callback, (void *)handle);
263         if (ret != MM_ERROR_NONE)
264                 LOGW("Failed to set message callback function (0x%x)", ret);
265
266         ret = mm_radio_realize(handle->mm_handle);
267         if (ret != MM_ERROR_NONE)
268                 return __convert_error_code(ret, (char *)__FUNCTION__);
269
270         handle->state = RADIO_STATE_READY;
271         handle->mute = false;
272         handle->seeking = false;
273         return RADIO_ERROR_NONE;
274 }
275
276 int radio_destroy(radio_h radio)
277 {
278         LOGI("Enter");
279         RADIO_SUPPORT_CHECK(__radio_check_system_info_feature_supported());
280         RADIO_INSTANCE_CHECK(radio);
281         radio_s *handle = (radio_s *)radio;
282
283         int ret;
284         ret = mm_radio_unrealize(handle->mm_handle);
285         if (ret != MM_ERROR_NONE)
286                 LOGW("Failed to unrealize (0x%x)", ret);
287
288         ret = mm_radio_destroy(handle->mm_handle);
289         if (ret != MM_ERROR_NONE)
290                 return __convert_error_code(ret, (char *)__FUNCTION__);
291
292         free(handle);
293         handle = NULL;
294         return RADIO_ERROR_NONE;
295 }
296
297 int radio_get_state(radio_h radio, radio_state_e *state)
298 {
299         LOGI("Enter");
300         RADIO_SUPPORT_CHECK(__radio_check_system_info_feature_supported());
301         RADIO_INSTANCE_CHECK(radio);
302         RADIO_NULL_ARG_CHECK(state);
303         radio_s *handle = (radio_s *)radio;
304         MMRadioStateType currentStat = MM_RADIO_STATE_NULL;
305         int ret = mm_radio_get_state(handle->mm_handle, &currentStat);
306         if (ret != MM_ERROR_NONE) {
307                 *state = handle->state;
308                 return __convert_error_code(ret, (char *)__FUNCTION__);
309         }
310
311         handle->state = __convert_radio_state(currentStat);
312         *state = handle->state;
313         return RADIO_ERROR_NONE;
314 }
315
316 int radio_start(radio_h radio)
317 {
318         LOGI("Enter");
319         RADIO_SUPPORT_CHECK(__radio_check_system_info_feature_supported());
320         RADIO_INSTANCE_CHECK(radio);
321         radio_s *handle = (radio_s *)radio;
322         RADIO_STATE_CHECK(handle, RADIO_STATE_READY);
323
324         int ret = mm_radio_start(handle->mm_handle);
325         if (ret != MM_ERROR_NONE)
326                 return __convert_error_code(ret, (char *)__FUNCTION__);
327
328         handle->state = RADIO_STATE_PLAYING;
329         return RADIO_ERROR_NONE;
330 }
331
332 int radio_stop(radio_h radio)
333 {
334         LOGI("Enter");
335         RADIO_SUPPORT_CHECK(__radio_check_system_info_feature_supported());
336         RADIO_INSTANCE_CHECK(radio);
337         radio_s *handle = (radio_s *)radio;
338         RADIO_STATE_CHECK(handle, RADIO_STATE_PLAYING);
339
340         int ret = mm_radio_stop(handle->mm_handle);
341         if (ret != MM_ERROR_NONE)
342                 return __convert_error_code(ret, (char *)__FUNCTION__);
343
344         handle->state = RADIO_STATE_READY;
345         return RADIO_ERROR_NONE;
346 }
347
348 int radio_seek_up(radio_h radio, radio_seek_completed_cb callback, void *user_data)
349 {
350         LOGI("Enter");
351         RADIO_SUPPORT_CHECK(__radio_check_system_info_feature_supported());
352         RADIO_INSTANCE_CHECK(radio);
353         radio_s *handle = (radio_s *)radio;
354         RADIO_STATE_CHECK(handle, RADIO_STATE_PLAYING);
355
356         if (handle->seeking) {
357                 LOGI("radio is seeking, can't serve another request try again");
358                 return RADIO_ERROR_INVALID_OPERATION;
359         }
360
361         handle->seeking = true;
362
363         if (callback != NULL)
364                 __set_callback(_RADIO_EVENT_TYPE_SEEK_FINISH, radio, callback, user_data);
365         else
366                 __unset_callback(_RADIO_EVENT_TYPE_SEEK_FINISH, radio);
367
368         int ret = mm_radio_seek(handle->mm_handle, MM_RADIO_SEEK_UP);
369         if (ret != MM_ERROR_NONE)
370                 return __convert_error_code(ret, (char *)__FUNCTION__);
371
372         return RADIO_ERROR_NONE;
373 }
374
375 int radio_seek_down(radio_h radio, radio_seek_completed_cb callback, void *user_data)
376 {
377         LOGI("Enter");
378         RADIO_SUPPORT_CHECK(__radio_check_system_info_feature_supported());
379         RADIO_INSTANCE_CHECK(radio);
380         radio_s *handle = (radio_s *)radio;
381         RADIO_STATE_CHECK(handle, RADIO_STATE_PLAYING);
382
383         if (handle->seeking) {
384                 LOGI("radio is seeking, can't serve another request try again");
385                 return RADIO_ERROR_INVALID_OPERATION;
386         }
387
388         handle->seeking = true;
389
390         if (callback != NULL)
391                 __set_callback(_RADIO_EVENT_TYPE_SEEK_FINISH, radio, callback, user_data);
392         else
393                 __unset_callback(_RADIO_EVENT_TYPE_SEEK_FINISH, radio);
394
395         int ret = mm_radio_seek(handle->mm_handle, MM_RADIO_SEEK_DOWN);
396         if (ret != MM_ERROR_NONE)
397                 return __convert_error_code(ret, (char *)__FUNCTION__);
398
399         return RADIO_ERROR_NONE;
400 }
401
402 int radio_set_frequency(radio_h radio, int frequency)
403 {
404         LOGI("Enter");
405         RADIO_SUPPORT_CHECK(__radio_check_system_info_feature_supported());
406         RADIO_INSTANCE_CHECK(radio);
407         if (frequency < 87500 || frequency > 108000) {
408                 LOGE("RADIO_ERROR_INVALID_PARAMETER(0x%08x) : Out of range (87500 ~ 108000)", RADIO_ERROR_INVALID_PARAMETER);
409                 return RADIO_ERROR_INVALID_PARAMETER;
410         }
411
412         radio_s *handle = (radio_s *)radio;
413         int ret = mm_radio_set_frequency(handle->mm_handle, frequency);
414         if (ret != MM_ERROR_NONE)
415                 return __convert_error_code(ret, (char *)__FUNCTION__);
416
417         return RADIO_ERROR_NONE;
418 }
419
420 int radio_get_frequency(radio_h radio, int *frequency)
421 {
422         LOGI("Enter");
423         RADIO_SUPPORT_CHECK(__radio_check_system_info_feature_supported());
424         RADIO_INSTANCE_CHECK(radio);
425         RADIO_NULL_ARG_CHECK(frequency);
426         radio_s *handle = (radio_s *)radio;
427
428         int freq;
429         int ret = mm_radio_get_frequency(handle->mm_handle, &freq);
430         if (ret != MM_ERROR_NONE)
431                 return __convert_error_code(ret, (char *)__FUNCTION__);
432
433         *frequency = freq;
434         return RADIO_ERROR_NONE;
435 }
436
437 int radio_get_signal_strength(radio_h radio, int *strength)
438 {
439         LOGI("Enter");
440         RADIO_SUPPORT_CHECK(__radio_check_system_info_feature_supported());
441         RADIO_INSTANCE_CHECK(radio);
442         RADIO_NULL_ARG_CHECK(strength);
443         radio_s *handle = (radio_s *)radio;
444
445         int _strength;
446         int ret = mm_radio_get_signal_strength(handle->mm_handle, &_strength);
447         if (ret != MM_ERROR_NONE)
448                 return __convert_error_code(ret, (char *)__FUNCTION__);
449
450         *strength = _strength;
451         return RADIO_ERROR_NONE;
452 }
453
454 int radio_scan_start(radio_h radio, radio_scan_updated_cb callback, void *user_data)
455 {
456         LOGI("Enter");
457         RADIO_SUPPORT_CHECK(__radio_check_system_info_feature_supported());
458         RADIO_INSTANCE_CHECK(radio);
459         radio_s *handle = (radio_s *)radio;
460
461         if (callback != NULL)
462                 __set_callback(_RADIO_EVENT_TYPE_SCAN_INFO, radio, callback, user_data);
463         else
464                 __unset_callback(_RADIO_EVENT_TYPE_SCAN_INFO, radio);
465
466         int ret = mm_radio_scan_start(handle->mm_handle);
467         if (ret != MM_ERROR_NONE)
468                 return __convert_error_code(ret, (char *)__FUNCTION__);
469
470         handle->state = RADIO_STATE_SCANNING;
471         return RADIO_ERROR_NONE;
472
473 }
474
475 int radio_scan_stop(radio_h radio, radio_scan_stopped_cb callback, void *user_data)
476 {
477         LOGI("Enter");
478         RADIO_SUPPORT_CHECK(__radio_check_system_info_feature_supported());
479         RADIO_INSTANCE_CHECK(radio);
480         radio_s *handle = (radio_s *)radio;
481         RADIO_STATE_CHECK(handle, RADIO_STATE_SCANNING);
482
483         if (handle->user_cb[_RADIO_EVENT_TYPE_SCAN_STOP]) {
484                 LOGW("Failed to stop scan (0x%x)", RADIO_ERROR_INVALID_OPERATION);
485                 return RADIO_ERROR_INVALID_OPERATION;
486         }
487
488         if (callback != NULL)
489                 __set_callback(_RADIO_EVENT_TYPE_SCAN_STOP, radio, callback, user_data);
490         else
491                 __unset_callback(_RADIO_EVENT_TYPE_SCAN_STOP, radio);
492
493         int ret = mm_radio_scan_stop(handle->mm_handle);
494         if (ret != MM_ERROR_NONE)
495                 return __convert_error_code(ret, (char *)__FUNCTION__);
496
497         return RADIO_ERROR_NONE;
498 }
499
500 int radio_set_mute(radio_h radio, bool muted)
501 {
502         LOGI("Enter");
503         RADIO_SUPPORT_CHECK(__radio_check_system_info_feature_supported());
504         RADIO_INSTANCE_CHECK(radio);
505         radio_s *handle = (radio_s *)radio;
506
507         int ret = mm_radio_set_mute(handle->mm_handle, muted);
508         if (ret != MM_ERROR_NONE)
509                 return __convert_error_code(ret, (char *)__FUNCTION__);
510
511         handle->mute = muted;
512         return RADIO_ERROR_NONE;
513
514 }
515
516 int radio_is_muted(radio_h radio, bool *muted)
517 {
518         LOGI("Enter");
519         RADIO_SUPPORT_CHECK(__radio_check_system_info_feature_supported());
520         RADIO_INSTANCE_CHECK(radio);
521         RADIO_NULL_ARG_CHECK(muted);
522         radio_s *handle = (radio_s *)radio;
523         *muted = handle->mute;
524         return RADIO_ERROR_NONE;
525 }
526
527 int radio_set_scan_completed_cb(radio_h radio, radio_scan_completed_cb callback, void *user_data)
528 {
529         LOGI("Enter");
530         RADIO_SUPPORT_CHECK(__radio_check_system_info_feature_supported());
531         return __set_callback(_RADIO_EVENT_TYPE_SCAN_FINISH, radio, callback, user_data);
532 }
533
534 int radio_unset_scan_completed_cb(radio_h radio)
535 {
536         LOGI("Enter");
537         RADIO_SUPPORT_CHECK(__radio_check_system_info_feature_supported());
538         return __unset_callback(_RADIO_EVENT_TYPE_SCAN_FINISH, radio);
539 }
540
541 int radio_set_interrupted_cb(radio_h radio, radio_interrupted_cb callback, void *user_data)
542 {
543         LOGI("Enter");
544         RADIO_SUPPORT_CHECK(__radio_check_system_info_feature_supported());
545         return __set_callback(_RADIO_EVENT_TYPE_INTERRUPT, radio, callback, user_data);
546 }
547
548 int radio_unset_interrupted_cb(radio_h radio)
549 {
550         LOGI("Enter");
551         RADIO_SUPPORT_CHECK(__radio_check_system_info_feature_supported());
552         return __unset_callback(_RADIO_EVENT_TYPE_INTERRUPT, radio);
553 }
554
555 int radio_get_frequency_range(radio_h radio, int *min_freq, int *max_freq)
556 {
557         LOGI("Enter");
558         RADIO_SUPPORT_CHECK(__radio_check_system_info_feature_supported());
559         RADIO_INSTANCE_CHECK(radio);
560         RADIO_NULL_ARG_CHECK(min_freq);
561         RADIO_NULL_ARG_CHECK(max_freq);
562         radio_s *handle = (radio_s *)radio;
563
564         unsigned int min = 0;
565         unsigned int max = 0;
566
567         int ret = mm_radio_get_region_frequency_range(handle->mm_handle, &min, &max);
568         if (ret != MM_ERROR_NONE)
569                 return __convert_error_code(ret, (char *)__FUNCTION__);
570
571         *min_freq = min;
572         *max_freq = max;
573         return RADIO_ERROR_NONE;
574 }
575
576 int radio_get_channel_spacing(radio_h radio, int *channel_spacing)
577 {
578         LOGI("Enter");
579         RADIO_SUPPORT_CHECK(__radio_check_system_info_feature_supported());
580         RADIO_INSTANCE_CHECK(radio);
581
582         radio_s *handle = (radio_s *)radio;
583
584         int ret = mm_radio_get_channel_spacing(handle->mm_handle, channel_spacing);
585         if (ret != MM_ERROR_NONE)
586                 return __convert_error_code(ret, (char *)__FUNCTION__);
587
588         return RADIO_ERROR_NONE;
589 }
590
591 int radio_set_volume(radio_h radio, float volume)
592 {
593         LOGI("Enter");
594         RADIO_SUPPORT_CHECK(__radio_check_system_info_feature_supported());
595         RADIO_INSTANCE_CHECK(radio);
596         if (volume < 0.0 || volume > 1.0) {
597                 LOGE("RADIO_ERROR_INVALID_PARAMETER(0x%08x) : Out of range (0.0 ~ 1.0)", RADIO_ERROR_INVALID_PARAMETER);
598                 return RADIO_ERROR_INVALID_PARAMETER;
599         }
600
601         radio_s *handle = (radio_s *)radio;
602         int ret = mm_radio_set_volume(handle->mm_handle, volume);
603         if (ret != MM_ERROR_NONE)
604                 return __convert_error_code(ret, (char *)__FUNCTION__);
605
606         return RADIO_ERROR_NONE;
607 }
608
609 int radio_get_volume(radio_h radio, float *volume)
610 {
611         LOGI("Enter");
612         RADIO_SUPPORT_CHECK(__radio_check_system_info_feature_supported());
613         RADIO_INSTANCE_CHECK(radio);
614         RADIO_NULL_ARG_CHECK(volume);
615         radio_s *handle = (radio_s *)radio;
616
617         float vol;
618         int ret = mm_radio_get_volume(handle->mm_handle, &vol);
619         if (ret != MM_ERROR_NONE)
620                 return __convert_error_code(ret, (char *)__FUNCTION__);
621
622         *volume = vol;
623         return RADIO_ERROR_NONE;
624 }