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