Home | History | Annotate | Download | only in radio
      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 
     34 void usage() {
     35     printf("Usage: "
     36             "./radio_hal_tool -l\n"
     37             "-l: List properties global to the Radio.\n"
     38     );
     39 }
     40 
     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 
     67 void callback(radio_hal_event_t *event, void *cookie) {
     68     printf("\nEvent detected\n"
     69            "Type: %d\n", event->type);
     70 }
     71 
     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 
    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 
    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