1 /*
2 * Copyright (C) 2015 The Android Open Source Project
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 #define LOG_TAG "radio_hal_tool"
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <unistd.h>
23
24 #include <log/log.h>
25
26 #include <hardware/hardware.h>
27 #include <hardware/radio.h>
28 #include <system/radio.h>
29 #include <system/radio_metadata.h>
30
31 // Global state variables.
32 const struct radio_tuner *hal_tuner = NULL;
33
usage()34 void usage() {
35 printf("Usage: "
36 "./radio_hal_tool -l\n"
37 "-l: List properties global to the Radio.\n"
38 );
39 }
40
list_all_properties(radio_hw_device_t * device)41 void list_all_properties(radio_hw_device_t *device) {
42 radio_hal_properties_t hal_properties;
43 device->get_properties(device, &hal_properties);
44 printf("Class: %d\n"
45 "Impl: %s\n"
46 "Tuners: %d\n"
47 "Bands: %d\n\n",
48 hal_properties.class_id, hal_properties.implementor, hal_properties.num_tuners,
49 hal_properties.num_bands);
50
51 uint32_t i;
52 for (i = 0; i < hal_properties.num_bands; i++) {
53 printf("Band Information\n"
54 "Type: %d\n"
55 "Connected: %d\n"
56 "Lower limit: %d\n"
57 "Upper limit: %d\n"
58 "Spacing: %d\n\n",
59 hal_properties.bands[i].type,
60 hal_properties.bands[i].antenna_connected,
61 hal_properties.bands[i].lower_limit,
62 hal_properties.bands[i].upper_limit,
63 hal_properties.bands[i].num_spacings);
64 }
65 }
66
callback(radio_hal_event_t * event,void * cookie)67 void callback(radio_hal_event_t *event, void *cookie) {
68 printf("\nEvent detected\n"
69 "Type: %d\n", event->type);
70 }
71
tune(radio_hw_device_t * device,int band_number)72 void tune(radio_hw_device_t *device, int band_number) {
73 int ret;
74 radio_hal_properties_t hal_properties;
75 ret = device->get_properties(device, &hal_properties);
76 if (ret != 0) {
77 printf("Err: get_properties returned: %d\n", ret);
78 return;
79 }
80
81 if ((uint32_t) band_number >= hal_properties.num_bands) {
82 printf("Tuner number range should be: [0, %d]\n", hal_properties.num_bands);
83 }
84 printf("Setting band config as:\n"
85 "Type: %d\n"
86 "Connected: %d\n"
87 "Lower limit: %d\n"
88 "Upper limit: %d\n"
89 "Spacing: %d\n\n",
90 hal_properties.bands[band_number].type,
91 hal_properties.bands[band_number].antenna_connected,
92 hal_properties.bands[band_number].lower_limit,
93 hal_properties.bands[band_number].upper_limit,
94 hal_properties.bands[band_number].num_spacings);
95 int cookie = 0;
96 ret = device->open_tuner(
97 device, (const radio_hal_band_config_t *) (&(hal_properties.bands[band_number])), false,
98 callback, &cookie, &hal_tuner);
99 if (ret != 0) {
100 printf("Err: open_tuner returned: %d\n", ret);
101 return;
102 }
103 // It takes some time to apply the config which is currently set as 500ms in
104 // the stub implementation.
105 sleep(1);
106
107 // Stub tuner implementation will regard this magic channel as a valid channel to tune.
108 ret = hal_tuner->tune(hal_tuner, 87916, 0);
109 if (ret != 0) {
110 printf("Err: tune returned: %d\n", ret);
111 return;
112 }
113 // In the stub implementation it takes ~100ms to tune to the channel and the
114 // data is set rightafter.
115 sleep(1);
116 }
117
get_tuner_metadata(radio_hw_device_t * device)118 void get_tuner_metadata(radio_hw_device_t *device) {
119 // Get the metadata and print it.
120 radio_program_info_t info;
121 radio_metadata_allocate(&info.metadata, 87916, 0);
122 int ret;
123 ret = hal_tuner->get_program_information(hal_tuner, &info);
124 if (ret != 0) {
125 printf("Err: Get program info ret code: %d\n", ret);
126 return;
127 }
128
129 // Print the info.
130 printf("Metadata from the band\n");
131 int i;
132 for (i = 0; i < radio_metadata_get_count(info.metadata); i++) {
133 radio_metadata_key_t key;
134 radio_metadata_type_t type;
135 void *value;
136 size_t size;
137
138 radio_metadata_get_at_index(info.metadata, i, &key, &type, &value, &size);
139
140 printf("\nMetadata key: %d\n"
141 "Type: %d\n", key, type);
142
143 switch (type) {
144 case RADIO_METADATA_TYPE_INT:
145 printf("Int value: %d\n", *((int *) value));
146 break;
147 case RADIO_METADATA_TYPE_TEXT:
148 printf("Text value: %s\n", (char *) value);
149 break;
150 case RADIO_METADATA_TYPE_RAW:
151 printf("Raw value, skipping\n");
152 break;
153 case RADIO_METADATA_TYPE_CLOCK:
154 printf("UTC Epoch: %lld\n"
155 "UTC Offset: %d\n",
156 (long long)((radio_metadata_clock_t *) value)->utc_seconds_since_epoch,
157 ((radio_metadata_clock_t *) value)->timezone_offset_in_minutes);
158 }
159 }
160
161 // Close the tuner when we are done.
162 ret = device->close_tuner(device, hal_tuner);
163 if (ret != 0) {
164 printf("Err: close_tuner returned: %d\n", ret);
165 }
166 }
167
main(int argc,char ** argv)168 int main(int argc, char** argv) {
169 // Open the radio module and just ask for the list of properties.
170 const hw_module_t *hw_module = NULL;
171 int rc;
172 rc = hw_get_module_by_class(RADIO_HARDWARE_MODULE_ID, RADIO_HARDWARE_MODULE_ID_FM, &hw_module);
173 if (rc != 0) {
174 printf("Cannot open the hw module. Does the HAL exist? %d\n", rc);
175 return -1;
176 }
177
178 radio_hw_device_t *dev;
179 rc = radio_hw_device_open(hw_module, &dev);
180 if (rc != 0) {
181 printf("Cannot open the device. Check that HAL implementation. %d\n", rc);
182 return -1;
183 }
184 printf("HAL Loaded!\n");
185
186 // If this is a list properties command - we check for -l command.
187 int list_properties = 0;
188 // Get metadata.
189 int get_metadata = 0;
190 // Tune. Takes a tuner number (see bands obtainaed by list_properties).
191 int should_tune = 0;
192 int band_number = -1;
193
194 int opt;
195 while ((opt = getopt(argc, argv, "lmt:")) != -1) {
196 switch (opt) {
197 case 'l':
198 list_properties = 1;
199 break;
200 case 't':
201 should_tune = 1;
202 band_number = atoi(optarg);
203 break;
204 case 'm':
205 get_metadata = 1;
206 break;
207 }
208 }
209
210 if (list_properties) {
211 printf("Listing properties...\n");
212 list_all_properties(dev);
213 } else {
214 if (should_tune) {
215 if (band_number < 0) {
216 printf("Tuner number should be positive");
217 return -1;
218 }
219 printf("Tuning to a station...\n");
220 tune(dev, band_number);
221 }
222 if (get_metadata) {
223 if (!hal_tuner) {
224 printf("Please pass -t <band_number> to tune to a valid station to get metadata.");
225 exit(1);
226 }
227 get_tuner_metadata(dev);
228 }
229 }
230 return 0;
231 }
232