2 * Copyright (C) 2017 Konsulko Group
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.
23 #include <sys/types.h>
25 #include <json-c/json.h>
26 #include <afb/afb-binding.h>
27 #include <afb/afb-service-itf.h>
29 #include "radio_impl.h"
31 static const struct afb_binding_interface *interface;
33 static struct afb_event freq_event;
34 static struct afb_event scan_event;
36 static void freq_callback(uint32_t frequency, void *data)
38 json_object *jresp = json_object_new_object();
39 json_object *value = json_object_new_int((int) frequency);
41 json_object_object_add(jresp, "value", value);
42 afb_event_push(freq_event, json_object_get(jresp));
45 static void scan_callback(uint32_t frequency, void *data)
47 json_object *jresp = json_object_new_object();
48 json_object *value = json_object_new_int((int) frequency);
50 json_object_object_add(jresp, "value", value);
51 afb_event_push(scan_event, json_object_get(jresp));
55 * Binding verb handlers
59 * @brief Get (and optionally set) frequency
61 * @param struct afb_req : an afb request structure
64 static void frequency(struct afb_req request)
66 json_object *ret_json;
67 const char *value = afb_req_value(request, "value");
72 frequency = strtoul(value, &p, 10);
73 if(frequency && *p == '\0') {
74 radio_impl_set_frequency(frequency);
76 afb_req_fail(request, "failed", "Invalid scan direction");
80 ret_json = json_object_new_object();
81 frequency = radio_impl_get_frequency();
82 json_object_object_add(ret_json, "frequency", json_object_new_int((int32_t) frequency));
83 afb_req_success(request, ret_json, NULL);
87 * @brief Get (and optionally set) frequency band
89 * @param struct afb_req : an afb request structure
92 static void band(struct afb_req request)
94 json_object *ret_json;
95 const char *value = afb_req_value(request, "value");
101 if(!strcasecmp(value, "AM")) {
104 } else if(!strcasecmp(value, "FM")) {
109 band = strtoul(value, &p, 10);
110 if(p != value && *p == '\0') {
122 radio_impl_set_band(band);
124 afb_req_fail(request, "failed", "Invalid band");
128 ret_json = json_object_new_object();
129 band = radio_impl_get_band();
130 sprintf(band_name, "%s", band == BAND_AM ? "AM" : "FM");
131 json_object_object_add(ret_json, "band", json_object_new_string(band_name));
132 afb_req_success(request, ret_json, NULL);
136 * @brief Check if band is supported
138 * @param struct afb_req : an afb request structure
141 static void band_supported(struct afb_req request)
143 json_object *ret_json;
144 const char *value = afb_req_value(request, "band");
149 if(!strcasecmp(value, "AM")) {
152 } else if(!strcasecmp(value, "FM")) {
157 band = strtoul(value, &p, 10);
158 if(p != value && *p == '\0') {
171 afb_req_fail(request, "failed", "Invalid band");
174 ret_json = json_object_new_object();
175 json_object_object_add(ret_json,
177 json_object_new_int(radio_impl_band_supported(band)));
178 afb_req_success(request, ret_json, NULL);
182 * @brief Get frequency range for a band
184 * @param struct afb_req : an afb request structure
187 static void frequency_range(struct afb_req request)
189 json_object *ret_json;
190 const char *value = afb_req_value(request, "band");
193 uint32_t min_frequency;
194 uint32_t max_frequency;
197 if(!strcasecmp(value, "AM")) {
200 } else if(!strcasecmp(value, "FM")) {
205 band = strtoul(value, &p, 10);
206 if(p != value && *p == '\0') {
219 afb_req_fail(request, "failed", "Invalid band");
222 ret_json = json_object_new_object();
223 min_frequency = radio_impl_get_min_frequency(band);
224 max_frequency = radio_impl_get_max_frequency(band);
225 json_object_object_add(ret_json, "min", json_object_new_int((int32_t) min_frequency));
226 json_object_object_add(ret_json, "max", json_object_new_int((int32_t) max_frequency));
227 afb_req_success(request, ret_json, NULL);
231 * @brief Get frequency step size (Hz) for a band
233 * @param struct afb_req : an afb request structure
236 static void frequency_step(struct afb_req request)
238 json_object *ret_json;
239 const char *value = afb_req_value(request, "band");
245 if(!strcasecmp(value, "AM")) {
248 } else if(!strcasecmp(value, "FM")) {
253 band = strtoul(value, &p, 10);
254 if(p != value && *p == '\0') {
267 afb_req_fail(request, "failed", "Invalid band");
270 ret_json = json_object_new_object();
271 step = radio_impl_get_frequency_step(band);
272 json_object_object_add(ret_json, "step", json_object_new_int((int32_t) step));
273 afb_req_success(request, ret_json, NULL);
277 * @brief Start radio playback
279 * @param struct afb_req : an afb request structure
282 static void start(struct afb_req request)
285 afb_req_success(request, NULL, NULL);
289 * @brief Stop radio playback
291 * @param struct afb_req : an afb request structure
294 static void stop(struct afb_req request)
297 afb_req_success(request, NULL, NULL);
301 * @brief Scan for a station in the specified direction
303 * @param struct afb_req : an afb request structure
306 static void scan_start(struct afb_req request)
308 json_object *ret_json;
309 const char *value = afb_req_value(request, "direction");
311 radio_scan_direction_t direction;
314 if(!strcasecmp(value, "forward")) {
315 direction = SCAN_FORWARD;
317 } else if(!strcasecmp(value, "backward")) {
318 direction = SCAN_BACKWARD;
322 direction = strtoul(value, &p, 10);
323 if(p != value && *p == '\0') {
336 afb_req_fail(request, "failed", "Invalid direction");
339 radio_impl_scan_start(direction, scan_callback, NULL);
340 afb_req_success(request, ret_json, NULL);
344 * @brief Stop station scan
346 * @param struct afb_req : an afb request structure
349 static void scan_stop(struct afb_req request)
351 radio_impl_scan_stop();
352 afb_req_success(request, NULL, NULL);
356 * @brief Get (and optionally set) stereo mode
358 * @param struct afb_req : an afb request structure
361 static void stereo_mode(struct afb_req request)
363 json_object *ret_json;
364 const char *value = afb_req_value(request, "value");
366 radio_stereo_mode_t mode;
370 if(!strcasecmp(value, "mono")) {
373 } else if(!strcasecmp(value, "stereo")) {
378 mode = strtoul(value, &p, 10);
379 if(p != value && *p == '\0') {
391 radio_impl_set_stereo_mode(mode);
393 afb_req_fail(request, "failed", "Invalid mode");
397 ret_json = json_object_new_object();
398 mode = radio_impl_get_stereo_mode();
399 sprintf(mode_name, "%s", mode == MONO ? "mono" : "stereo");
400 json_object_object_add(ret_json, "mode", json_object_new_string(mode_name));
401 afb_req_success(request, ret_json, NULL);
405 * @brief Subscribe for an event
407 * @param struct afb_req : an afb request structure
410 static void subscribe(struct afb_req request)
412 const char *value = afb_req_value(request, "value");
414 if(!strcasecmp(value, "frequency")) {
415 afb_req_subscribe(request, freq_event);
416 } else if(!strcasecmp(value, "station_found")) {
417 afb_req_subscribe(request, scan_event);
419 afb_req_fail(request, "failed", "Invalid event");
423 afb_req_success(request, NULL, NULL);
427 * @brief Unsubscribe for an event
429 * @param struct afb_req : an afb request structure
432 static void unsubscribe(struct afb_req request)
434 const char *value = afb_req_value(request, "value");
436 if(!strcasecmp(value, "frequency")) {
437 afb_req_unsubscribe(request, freq_event);
438 } else if(!strcasecmp(value, "station_found")) {
439 afb_req_unsubscribe(request, scan_event);
441 afb_req_fail(request, "failed", "Invalid event");
445 afb_req_success(request, NULL, NULL);
448 static const struct afb_verb_desc_v1 verbs[]= {
449 { "frequency", AFB_SESSION_CHECK, frequency, "Get/Set frequency" },
450 { "band", AFB_SESSION_CHECK, band, "Get/Set band" },
451 { "band_supported", AFB_SESSION_CHECK, band_supported, "Check band support" },
452 { "frequency_range", AFB_SESSION_CHECK, frequency_range, "Get frequency range" },
453 { "frequency_step", AFB_SESSION_CHECK, frequency_step, "Get frequency step" },
454 { "start", AFB_SESSION_CHECK, start, "Start radio playback" },
455 { "stop", AFB_SESSION_CHECK, stop, "Stop radio playback" },
456 { "scan_start", AFB_SESSION_CHECK, scan_start, "Start station scan" },
457 { "scan_stop", AFB_SESSION_CHECK, scan_stop, "Stop station scan" },
458 { "stereo_mode", AFB_SESSION_CHECK, stereo_mode, "Get/Set stereo_mode" },
459 { "subscribe", AFB_SESSION_CHECK, subscribe, "Subscribe for an event" },
460 { "unsubscribe", AFB_SESSION_CHECK, unsubscribe, "Unsubscribe for an event" },
464 static const struct afb_binding binding_desc = {
465 .type = AFB_BINDING_VERSION_1,
467 .info = "radio service",
473 const struct afb_binding *afbBindingV1Register (const struct afb_binding_interface *itf)
477 return &binding_desc;
480 int afbBindingV1ServiceInit(struct afb_service service)
484 freq_event = afb_daemon_make_event(interface->daemon, "frequency");
485 scan_event = afb_daemon_make_event(interface->daemon, "station_found");
487 rc = radio_impl_init();
489 radio_impl_set_frequency_callback(freq_callback, NULL);