2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 #include <radio_private.h>
24 #include <system_info.h>
29 #define LOG_TAG "TIZEN_N_RADIO"
34 #define RADIO_CHECK_CONDITION(condition, error, msg) \
38 LOGE("%s(0x%08x)", msg, error); \
43 #define RADIO_INSTANCE_CHECK(radio) \
44 RADIO_CHECK_CONDITION(radio != NULL, RADIO_ERROR_INVALID_PARAMETER, "RADIO_ERROR_INVALID_PARAMETER")
46 #define RADIO_STATE_CHECK(radio, expected_state) \
47 RADIO_CHECK_CONDITION(radio->state == expected_state, RADIO_ERROR_INVALID_STATE, "RADIO_ERROR_INVALID_STATE")
49 #define RADIO_NULL_ARG_CHECK(arg) \
50 RADIO_CHECK_CONDITION(arg != NULL, RADIO_ERROR_INVALID_PARAMETER, "RADIO_ERROR_INVALID_PARAMETER")
52 #define RADIO_SUPPORT_CHECK(arg) \
53 RADIO_CHECK_CONDITION(arg != false, RADIO_ERROR_NOT_SUPPORTED, "RADIO_ERROR_NOT_SUPPORTED")
56 * Internal Implementation
58 static int __convert_error_code(int code, char *func_name)
60 int ret = RADIO_ERROR_NONE;
61 char *msg = "RADIO_ERROR_NONE";
62 LOGI("Enter code :%x", code);
65 ret = RADIO_ERROR_NONE;
66 msg = "RADIO_ERROR_NONE";
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";
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";
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";
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";
91 case MM_ERROR_RADIO_DEVICE_NOT_FOUND:
92 ret = RADIO_ERROR_NOT_SUPPORTED;
93 msg = "RADIO_ERROR_NOT_SUPPORTED";
95 case MM_ERROR_RADIO_NO_ANTENNA:
96 ret = RADIO_ERROR_NO_ANTENNA;
97 msg = "RADIO_ERROR_NO_ANTENNA";
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";
104 case MM_ERROR_NOT_IMPLEMENTED:
105 case MM_ERROR_RADIO_INTERNAL:
106 case MM_ERROR_RADIO_RESPONSE_TIMEOUT:
108 ret = RADIO_ERROR_INVALID_OPERATION;
109 msg = "RADIO_ERROR_INVALID_OPERATION";
112 LOGE("[%s] %s(0x%08x) : core fw error(0x%x)", func_name, msg, ret, code);
116 static radio_state_e __convert_radio_state(MMRadioStateType state)
118 int converted_state = RADIO_STATE_READY;
119 LOGI("Enter state: %d", state);
122 case MM_RADIO_STATE_PLAYING:
123 converted_state = RADIO_STATE_PLAYING;
125 case MM_RADIO_STATE_SCANNING:
126 converted_state = RADIO_STATE_SCANNING;
128 case MM_RADIO_STATE_NULL:
129 case MM_RADIO_STATE_READY:
131 converted_state = RADIO_STATE_READY;
134 LOGI("Leave converted_state: %d", converted_state);
135 return converted_state;
138 static int __set_callback(_radio_event_e type, radio_h radio, void *callback, void *user_data)
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;
149 static int __unset_callback(_radio_event_e type, radio_h radio)
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;
159 static int __msg_callback(int message, void *param, void *user_data)
161 radio_s *handle = (radio_s *)user_data;
162 MMMessageParamType *msg = (MMMessageParamType *)param;
163 LOGI("Got message type : 0x%x", 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]);
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);
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);
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;
185 __unset_callback(_RADIO_EVENT_TYPE_SEEK_FINISH, (radio_h)handle);
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]);
195 case MM_MESSAGE_ERROR:
196 __convert_error_code(msg->code, (char *)__FUNCTION__);
199 case MM_MESSAGE_RADIO_SCAN_START:
200 LOGI("Scan Started");
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);
206 case MM_MESSAGE_RADIO_SEEK_START:
207 LOGI("Seek Started");
215 static int __radio_check_system_info_feature_supported()
220 ret = system_info_get_platform_bool("http://tizen.org/feature/fmradio", &val);
222 if (ret != SYSTEM_INFO_ERROR_NONE) {
223 LOGE("SYSTEM_INFO_ERROR");
228 LOGI("system_info_get_platform_bool returned Unsupported feature capability");
230 LOGI("system_info_get_platform_bool returned Supported status feature");
236 * Public Implementation
238 int radio_create(radio_h *radio)
241 RADIO_SUPPORT_CHECK(__radio_check_system_info_feature_supported());
242 RADIO_INSTANCE_CHECK(radio);
245 handle = (radio_s *)malloc(sizeof(radio_s));
247 LOGE("RADIO_ERROR_OUT_OF_MEMORY(0x%08x)", RADIO_ERROR_OUT_OF_MEMORY);
248 return RADIO_ERROR_OUT_OF_MEMORY;
251 memset(handle, 0, sizeof(radio_s));
253 int ret = mm_radio_create(&handle->mm_handle);
254 if (ret != MM_ERROR_NONE) {
257 return __convert_error_code(ret, (char *)__FUNCTION__);
260 *radio = (radio_h)handle;
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);
266 ret = mm_radio_realize(handle->mm_handle);
267 if (ret != MM_ERROR_NONE)
268 return __convert_error_code(ret, (char *)__FUNCTION__);
270 handle->state = RADIO_STATE_READY;
271 handle->mute = false;
272 handle->seeking = false;
273 return RADIO_ERROR_NONE;
276 int radio_destroy(radio_h radio)
279 RADIO_SUPPORT_CHECK(__radio_check_system_info_feature_supported());
280 RADIO_INSTANCE_CHECK(radio);
281 radio_s *handle = (radio_s *)radio;
284 ret = mm_radio_unrealize(handle->mm_handle);
285 if (ret != MM_ERROR_NONE)
286 LOGW("Failed to unrealize (0x%x)", ret);
288 ret = mm_radio_destroy(handle->mm_handle);
289 if (ret != MM_ERROR_NONE)
290 return __convert_error_code(ret, (char *)__FUNCTION__);
294 return RADIO_ERROR_NONE;
297 int radio_get_state(radio_h radio, radio_state_e *state)
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, ¤tStat);
306 if (ret != MM_ERROR_NONE) {
307 *state = handle->state;
308 return __convert_error_code(ret, (char *)__FUNCTION__);
311 handle->state = __convert_radio_state(currentStat);
312 *state = handle->state;
313 return RADIO_ERROR_NONE;
316 int radio_start(radio_h radio)
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);
324 int ret = mm_radio_start(handle->mm_handle);
325 if (ret != MM_ERROR_NONE)
326 return __convert_error_code(ret, (char *)__FUNCTION__);
328 handle->state = RADIO_STATE_PLAYING;
329 return RADIO_ERROR_NONE;
332 int radio_stop(radio_h radio)
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);
340 int ret = mm_radio_stop(handle->mm_handle);
341 if (ret != MM_ERROR_NONE)
342 return __convert_error_code(ret, (char *)__FUNCTION__);
344 handle->state = RADIO_STATE_READY;
345 return RADIO_ERROR_NONE;
348 int radio_seek_up(radio_h radio, radio_seek_completed_cb callback, void *user_data)
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);
356 if (handle->seeking) {
357 LOGI("radio is seeking, can't serve another request try again");
358 return RADIO_ERROR_INVALID_OPERATION;
361 handle->seeking = true;
363 if (callback != NULL)
364 __set_callback(_RADIO_EVENT_TYPE_SEEK_FINISH, radio, callback, user_data);
366 __unset_callback(_RADIO_EVENT_TYPE_SEEK_FINISH, radio);
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__);
372 return RADIO_ERROR_NONE;
375 int radio_seek_down(radio_h radio, radio_seek_completed_cb callback, void *user_data)
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);
383 if (handle->seeking) {
384 LOGI("radio is seeking, can't serve another request try again");
385 return RADIO_ERROR_INVALID_OPERATION;
388 handle->seeking = true;
390 if (callback != NULL)
391 __set_callback(_RADIO_EVENT_TYPE_SEEK_FINISH, radio, callback, user_data);
393 __unset_callback(_RADIO_EVENT_TYPE_SEEK_FINISH, radio);
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__);
399 return RADIO_ERROR_NONE;
402 int radio_set_frequency(radio_h radio, int frequency)
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;
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__);
417 return RADIO_ERROR_NONE;
420 int radio_get_frequency(radio_h radio, int *frequency)
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;
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__);
434 return RADIO_ERROR_NONE;
437 int radio_get_signal_strength(radio_h radio, int *strength)
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;
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__);
450 *strength = _strength;
451 return RADIO_ERROR_NONE;
454 int radio_scan_start(radio_h radio, radio_scan_updated_cb callback, void *user_data)
457 RADIO_SUPPORT_CHECK(__radio_check_system_info_feature_supported());
458 RADIO_INSTANCE_CHECK(radio);
459 radio_s *handle = (radio_s *)radio;
461 if (callback != NULL)
462 __set_callback(_RADIO_EVENT_TYPE_SCAN_INFO, radio, callback, user_data);
464 __unset_callback(_RADIO_EVENT_TYPE_SCAN_INFO, radio);
466 int ret = mm_radio_scan_start(handle->mm_handle);
467 if (ret != MM_ERROR_NONE)
468 return __convert_error_code(ret, (char *)__FUNCTION__);
470 handle->state = RADIO_STATE_SCANNING;
471 return RADIO_ERROR_NONE;
475 int radio_scan_stop(radio_h radio, radio_scan_stopped_cb callback, void *user_data)
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);
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;
488 if (callback != NULL)
489 __set_callback(_RADIO_EVENT_TYPE_SCAN_STOP, radio, callback, user_data);
491 __unset_callback(_RADIO_EVENT_TYPE_SCAN_STOP, radio);
493 int ret = mm_radio_scan_stop(handle->mm_handle);
494 if (ret != MM_ERROR_NONE)
495 return __convert_error_code(ret, (char *)__FUNCTION__);
497 return RADIO_ERROR_NONE;
500 int radio_set_mute(radio_h radio, bool muted)
503 RADIO_SUPPORT_CHECK(__radio_check_system_info_feature_supported());
504 RADIO_INSTANCE_CHECK(radio);
505 radio_s *handle = (radio_s *)radio;
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__);
511 handle->mute = muted;
512 return RADIO_ERROR_NONE;
516 int radio_is_muted(radio_h radio, bool *muted)
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;
527 int radio_set_scan_completed_cb(radio_h radio, radio_scan_completed_cb callback, void *user_data)
530 RADIO_SUPPORT_CHECK(__radio_check_system_info_feature_supported());
531 return __set_callback(_RADIO_EVENT_TYPE_SCAN_FINISH, radio, callback, user_data);
534 int radio_unset_scan_completed_cb(radio_h radio)
537 RADIO_SUPPORT_CHECK(__radio_check_system_info_feature_supported());
538 return __unset_callback(_RADIO_EVENT_TYPE_SCAN_FINISH, radio);
541 int radio_set_interrupted_cb(radio_h radio, radio_interrupted_cb callback, void *user_data)
544 RADIO_SUPPORT_CHECK(__radio_check_system_info_feature_supported());
545 return __set_callback(_RADIO_EVENT_TYPE_INTERRUPT, radio, callback, user_data);
548 int radio_unset_interrupted_cb(radio_h radio)
551 RADIO_SUPPORT_CHECK(__radio_check_system_info_feature_supported());
552 return __unset_callback(_RADIO_EVENT_TYPE_INTERRUPT, radio);
555 int radio_get_frequency_range(radio_h radio, int *min_freq, int *max_freq)
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;
564 unsigned int min = 0;
565 unsigned int max = 0;
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__);
573 return RADIO_ERROR_NONE;
576 int radio_get_channel_spacing(radio_h radio, int *channel_spacing)
579 RADIO_SUPPORT_CHECK(__radio_check_system_info_feature_supported());
580 RADIO_INSTANCE_CHECK(radio);
582 radio_s *handle = (radio_s *)radio;
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__);
588 return RADIO_ERROR_NONE;
591 int radio_set_volume(radio_h radio, float volume)
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;
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__);
606 return RADIO_ERROR_NONE;
609 int radio_get_volume(radio_h radio, float *volume)
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;
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__);
623 return RADIO_ERROR_NONE;