Merge "Initial implementation of broadcast radio HAL."
This commit is contained in:
commit
4433847341
13 changed files with 954 additions and 4 deletions
|
@ -66,6 +66,7 @@ LOCAL_SHARED_LIBRARIES := \
|
|||
android.hardware.audio.common@2.0 \
|
||||
android.hardware.audio.effect@2.0 \
|
||||
android.hardware.soundtrigger@2.0 \
|
||||
android.hardware.broadcastradio@1.0
|
||||
|
||||
ifeq ($(strip $(AUDIOSERVER_MULTILIB)),)
|
||||
LOCAL_MULTILIB := 32
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <android/hardware/audio/2.0/IDevicesFactory.h>
|
||||
#include <android/hardware/audio/effect/2.0/IEffectsFactory.h>
|
||||
#include <android/hardware/soundtrigger/2.0/ISoundTriggerHw.h>
|
||||
#include <android/hardware/broadcastradio/1.0/IBroadcastRadioFactory.h>
|
||||
|
||||
using android::hardware::IPCThreadState;
|
||||
using android::hardware::ProcessState;
|
||||
|
@ -27,10 +28,12 @@ using android::hardware::audio::effect::V2_0::IEffectsFactory;
|
|||
using android::hardware::audio::V2_0::IDevicesFactory;
|
||||
using android::hardware::soundtrigger::V2_0::ISoundTriggerHw;
|
||||
using android::hardware::registerPassthroughServiceImplementation;
|
||||
using android::hardware::broadcastradio::V1_0::IBroadcastRadioFactory;
|
||||
|
||||
int main(int /* argc */, char* /* argv */ []) {
|
||||
registerPassthroughServiceImplementation<IDevicesFactory>("audio_devices_factory");
|
||||
registerPassthroughServiceImplementation<IEffectsFactory>("audio_effects_factory");
|
||||
registerPassthroughServiceImplementation<ISoundTriggerHw>("sound_trigger.primary");
|
||||
registerPassthroughServiceImplementation<IBroadcastRadioFactory>("broadcastradio");
|
||||
return android::hardware::launchRpcServer(16);
|
||||
}
|
||||
|
|
|
@ -72,7 +72,9 @@ interface ITunerCallback {
|
|||
/*
|
||||
* Method called by the HAL when metadata for current station
|
||||
* are updated.
|
||||
* @param metadatas A list of all updated metada.
|
||||
* @param channel The channel the metadata is associated with.
|
||||
* @param subChannel The sub channel the metadata is associated with.
|
||||
* @param metadata A list of all updated metada.
|
||||
*/
|
||||
oneway newMetadata(vec<MetaData> metadatas);
|
||||
oneway newMetadata(uint32_t channel, uint32_t subChannel, vec<MetaData> metadata);
|
||||
};
|
27
broadcastradio/1.0/default/Android.mk
Normal file
27
broadcastradio/1.0/default/Android.mk
Normal file
|
@ -0,0 +1,27 @@
|
|||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := android.hardware.broadcastradio@1.0-impl
|
||||
LOCAL_MODULE_RELATIVE_PATH := hw
|
||||
LOCAL_SRC_FILES := \
|
||||
BroadcastRadio.cpp \
|
||||
BroadcastRadioFactory.cpp \
|
||||
Tuner.cpp \
|
||||
Utils.cpp
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libhidl \
|
||||
libhwbinder \
|
||||
libutils \
|
||||
liblog \
|
||||
libhardware \
|
||||
android.hardware.broadcastradio@1.0 \
|
||||
libradio_metadata
|
||||
|
||||
ifeq ($(strip $(AUDIOSERVER_MULTILIB)),)
|
||||
LOCAL_MULTILIB := 32
|
||||
else
|
||||
LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
|
||||
endif
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
141
broadcastradio/1.0/default/BroadcastRadio.cpp
Normal file
141
broadcastradio/1.0/default/BroadcastRadio.cpp
Normal file
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#define LOG_TAG "BroadcastRadio"
|
||||
//#define LOG_NDEBUG 0
|
||||
|
||||
#include <utils/Log.h>
|
||||
#include <hardware/radio.h>
|
||||
|
||||
#include "BroadcastRadio.h"
|
||||
#include "Tuner.h"
|
||||
#include "Utils.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace broadcastradio {
|
||||
namespace V1_0 {
|
||||
namespace implementation {
|
||||
|
||||
BroadcastRadio::BroadcastRadio(Class classId)
|
||||
: mStatus(Result::NOT_INITIALIZED), mClassId(classId), mHwDevice(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
BroadcastRadio::~BroadcastRadio()
|
||||
{
|
||||
if (mHwDevice != NULL) {
|
||||
radio_hw_device_close(mHwDevice);
|
||||
}
|
||||
}
|
||||
|
||||
void BroadcastRadio::onFirstRef()
|
||||
{
|
||||
const hw_module_t *mod;
|
||||
int rc;
|
||||
ALOGI("%s mClassId %d", __FUNCTION__, mClassId);
|
||||
|
||||
mHwDevice = NULL;
|
||||
const char *classString = Utils::getClassString(mClassId);
|
||||
if (classString == NULL) {
|
||||
ALOGE("invalid class ID %d", mClassId);
|
||||
mStatus = Result::INVALID_ARGUMENTS;
|
||||
return;
|
||||
}
|
||||
|
||||
ALOGI("%s RADIO_HARDWARE_MODULE_ID %s %s",
|
||||
__FUNCTION__, RADIO_HARDWARE_MODULE_ID, classString);
|
||||
|
||||
rc = hw_get_module_by_class(RADIO_HARDWARE_MODULE_ID, classString, &mod);
|
||||
if (rc != 0) {
|
||||
ALOGE("couldn't load radio module %s.%s (%s)",
|
||||
RADIO_HARDWARE_MODULE_ID, classString, strerror(-rc));
|
||||
return;
|
||||
}
|
||||
rc = radio_hw_device_open(mod, &mHwDevice);
|
||||
if (rc != 0) {
|
||||
ALOGE("couldn't open radio hw device in %s.%s (%s)",
|
||||
RADIO_HARDWARE_MODULE_ID, "primary", strerror(-rc));
|
||||
mHwDevice = NULL;
|
||||
return;
|
||||
}
|
||||
if (mHwDevice->common.version != RADIO_DEVICE_API_VERSION_CURRENT) {
|
||||
ALOGE("wrong radio hw device version %04x", mHwDevice->common.version);
|
||||
radio_hw_device_close(mHwDevice);
|
||||
mHwDevice = NULL;
|
||||
} else {
|
||||
mStatus = Result::OK;
|
||||
}
|
||||
}
|
||||
|
||||
int BroadcastRadio::closeHalTuner(const struct radio_tuner *halTuner)
|
||||
{
|
||||
ALOGV("%s", __FUNCTION__);
|
||||
if (mHwDevice == NULL) {
|
||||
return -ENODEV;
|
||||
}
|
||||
if (halTuner == 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
return mHwDevice->close_tuner(mHwDevice, halTuner);
|
||||
}
|
||||
|
||||
|
||||
// Methods from ::android::hardware::broadcastradio::V1_0::IBroadcastRadio follow.
|
||||
Return<void> BroadcastRadio::getProperties(getProperties_cb _hidl_cb)
|
||||
{
|
||||
int rc;
|
||||
radio_hal_properties_t halProperties;
|
||||
Properties properties;
|
||||
|
||||
if (mHwDevice == NULL) {
|
||||
rc = -ENODEV;
|
||||
goto exit;
|
||||
}
|
||||
rc = mHwDevice->get_properties(mHwDevice, &halProperties);
|
||||
if (rc == 0) {
|
||||
Utils::convertPropertiesFromHal(&properties, &halProperties);
|
||||
}
|
||||
|
||||
exit:
|
||||
_hidl_cb(Utils::convertHalResult(rc), properties);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> BroadcastRadio::openTuner(const BandConfig& config, bool audio,
|
||||
const sp<ITunerCallback>& callback, openTuner_cb _hidl_cb)
|
||||
{
|
||||
sp<Tuner> tunerImpl = new Tuner(callback, this);
|
||||
|
||||
radio_hal_band_config_t halConfig;
|
||||
const struct radio_tuner *halTuner;
|
||||
Utils::convertBandConfigToHal(&halConfig, &config);
|
||||
int rc = mHwDevice->open_tuner(mHwDevice, &halConfig, audio,
|
||||
Tuner::callback, tunerImpl.get(),
|
||||
&halTuner);
|
||||
if (rc == 0) {
|
||||
tunerImpl->setHalTuner(halTuner);
|
||||
}
|
||||
|
||||
_hidl_cb(Utils::convertHalResult(rc), tunerImpl);
|
||||
return Void();
|
||||
}
|
||||
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V1_0
|
||||
} // namespace broadcastradio
|
||||
} // namespace hardware
|
||||
} // namespace android
|
71
broadcastradio/1.0/default/BroadcastRadio.h
Normal file
71
broadcastradio/1.0/default/BroadcastRadio.h
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef HIDL_GENERATED_android_hardware_broadcastradio_V1_0_BroadcastRadio_H_
|
||||
#define HIDL_GENERATED_android_hardware_broadcastradio_V1_0_BroadcastRadio_H_
|
||||
|
||||
#include <android/hardware/broadcastradio/1.0/IBroadcastRadio.h>
|
||||
#include <hidl/Status.h>
|
||||
#include <hardware/radio.h>
|
||||
|
||||
#include <hidl/MQDescriptor.h>
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace broadcastradio {
|
||||
namespace V1_0 {
|
||||
namespace implementation {
|
||||
|
||||
struct BroadcastRadio : public IBroadcastRadio {
|
||||
|
||||
BroadcastRadio(Class classId);
|
||||
|
||||
// Methods from ::android::hardware::broadcastradio::V1_0::IBroadcastRadio follow.
|
||||
Return<void> getProperties(getProperties_cb _hidl_cb) override;
|
||||
Return<void> openTuner(const BandConfig& config, bool audio,
|
||||
const sp<ITunerCallback>& callback,
|
||||
openTuner_cb _hidl_cb) override;
|
||||
|
||||
|
||||
// RefBase
|
||||
virtual void onFirstRef();
|
||||
|
||||
Result initCheck() { return mStatus; }
|
||||
int closeHalTuner(const struct radio_tuner *halTuner);
|
||||
|
||||
private:
|
||||
virtual ~BroadcastRadio();
|
||||
|
||||
static const char * sClassModuleNames[];
|
||||
|
||||
Result convertHalResult(int rc);
|
||||
void convertBandConfigFromHal(BandConfig *config,
|
||||
const radio_hal_band_config_t *halConfig);
|
||||
void convertPropertiesFromHal(Properties *properties,
|
||||
const radio_hal_properties_t *halProperties);
|
||||
void convertBandConfigToHal(radio_hal_band_config_t *halConfig,
|
||||
const BandConfig *config);
|
||||
|
||||
Result mStatus;
|
||||
Class mClassId;
|
||||
struct radio_hw_device *mHwDevice;
|
||||
};
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V1_0
|
||||
} // namespace broadcastradio
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // HIDL_GENERATED_android_hardware_broadcastradio_V1_0_BroadcastRadio_H_
|
45
broadcastradio/1.0/default/BroadcastRadioFactory.cpp
Normal file
45
broadcastradio/1.0/default/BroadcastRadioFactory.cpp
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "BroadcastRadioFactory.h"
|
||||
#include "BroadcastRadio.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace broadcastradio {
|
||||
namespace V1_0 {
|
||||
namespace implementation {
|
||||
|
||||
// Methods from ::android::hardware::broadcastradio::V1_0::IBroadcastRadioFactory follow.
|
||||
Return<void> BroadcastRadioFactory::connectModule(Class classId, connectModule_cb _hidl_cb) {
|
||||
sp<BroadcastRadio> impl = new BroadcastRadio(classId);
|
||||
Result retval = Result::NOT_INITIALIZED;
|
||||
if (impl != 0) {
|
||||
retval = impl->initCheck();
|
||||
}
|
||||
_hidl_cb(retval, impl);
|
||||
return Void();
|
||||
}
|
||||
|
||||
|
||||
IBroadcastRadioFactory* HIDL_FETCH_IBroadcastRadioFactory(const char* /* name */) {
|
||||
return new BroadcastRadioFactory();
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V1_0
|
||||
} // namespace broadcastradio
|
||||
} // namespace hardware
|
||||
} // namespace android
|
43
broadcastradio/1.0/default/BroadcastRadioFactory.h
Normal file
43
broadcastradio/1.0/default/BroadcastRadioFactory.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef HIDL_GENERATED_android_hardware_broadcastradio_V1_0_BroadcastRadioFactory_H_
|
||||
#define HIDL_GENERATED_android_hardware_broadcastradio_V1_0_BroadcastRadioFactory_H_
|
||||
|
||||
#include <android/hardware/broadcastradio/1.0/IBroadcastRadioFactory.h>
|
||||
#include <hidl/Status.h>
|
||||
|
||||
#include <hidl/MQDescriptor.h>
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace broadcastradio {
|
||||
namespace V1_0 {
|
||||
namespace implementation {
|
||||
|
||||
struct BroadcastRadioFactory : public IBroadcastRadioFactory {
|
||||
// Methods from ::android::hardware::broadcastradio::V1_0::IBroadcastRadioFactory follow.
|
||||
Return<void> connectModule(Class classId, connectModule_cb _hidl_cb) override;
|
||||
|
||||
};
|
||||
|
||||
extern "C" IBroadcastRadioFactory* HIDL_FETCH_IBroadcastRadioFactory(const char* name);
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V1_0
|
||||
} // namespace broadcastradio
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // HIDL_GENERATED_android_hardware_broadcastradio_V1_0_BroadcastRadioFactory_H_
|
199
broadcastradio/1.0/default/Tuner.cpp
Normal file
199
broadcastradio/1.0/default/Tuner.cpp
Normal file
|
@ -0,0 +1,199 @@
|
|||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "Tuner"
|
||||
//#define LOG_NDEBUG 0
|
||||
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include "BroadcastRadio.h"
|
||||
#include "Tuner.h"
|
||||
#include "Utils.h"
|
||||
#include <system/radio_metadata.h>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace broadcastradio {
|
||||
namespace V1_0 {
|
||||
namespace implementation {
|
||||
|
||||
void Tuner::onCallback(radio_hal_event_t *halEvent)
|
||||
{
|
||||
BandConfig config;
|
||||
ProgramInfo info;
|
||||
hidl_vec<MetaData> metadata;
|
||||
|
||||
if (mCallback != 0) {
|
||||
switch(halEvent->type) {
|
||||
case RADIO_EVENT_CONFIG:
|
||||
Utils::convertBandConfigFromHal(&config, &halEvent->config);
|
||||
mCallback->configChange(Utils::convertHalResult(halEvent->status), config);
|
||||
break;
|
||||
case RADIO_EVENT_ANTENNA:
|
||||
mCallback->antennaStateChange(halEvent->on);
|
||||
break;
|
||||
case RADIO_EVENT_TUNED:
|
||||
Utils::convertProgramInfoFromHal(&info, &halEvent->info, true);
|
||||
mCallback->tuneComplete(Utils::convertHalResult(halEvent->status), info);
|
||||
break;
|
||||
case RADIO_EVENT_METADATA: {
|
||||
uint32_t channel;
|
||||
uint32_t sub_channel;
|
||||
if (radio_metadata_get_channel(halEvent->metadata, &channel, &sub_channel) == 0) {
|
||||
Utils::convertMetaDataFromHal(metadata, halEvent->metadata);
|
||||
mCallback->newMetadata(channel, sub_channel, metadata);
|
||||
}
|
||||
} break;
|
||||
case RADIO_EVENT_TA:
|
||||
mCallback->trafficAnnouncement(halEvent->on);
|
||||
break;
|
||||
case RADIO_EVENT_AF_SWITCH:
|
||||
Utils::convertProgramInfoFromHal(&info, &halEvent->info, true);
|
||||
mCallback->afSwitch(info);
|
||||
break;
|
||||
case RADIO_EVENT_EA:
|
||||
mCallback->emergencyAnnouncement(halEvent->on);
|
||||
break;
|
||||
case RADIO_EVENT_HW_FAILURE:
|
||||
default:
|
||||
mCallback->hardwareFailure();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
void Tuner::callback(radio_hal_event_t *halEvent, void *cookie)
|
||||
{
|
||||
wp<Tuner> weak(reinterpret_cast<Tuner*>(cookie));
|
||||
sp<Tuner> tuner = weak.promote();
|
||||
if (tuner == 0) return;
|
||||
tuner->onCallback(halEvent);
|
||||
}
|
||||
|
||||
Tuner::Tuner(const sp<ITunerCallback>& callback, const wp<BroadcastRadio>& parentDevice)
|
||||
: mHalTuner(NULL), mCallback(callback), mParentDevice(parentDevice)
|
||||
{
|
||||
ALOGV("%s", __FUNCTION__);
|
||||
}
|
||||
|
||||
|
||||
Tuner::~Tuner()
|
||||
{
|
||||
ALOGV("%s", __FUNCTION__);
|
||||
const sp<BroadcastRadio> parentDevice = mParentDevice.promote();
|
||||
if (parentDevice != 0) {
|
||||
parentDevice->closeHalTuner(mHalTuner);
|
||||
}
|
||||
}
|
||||
|
||||
// Methods from ::android::hardware::broadcastradio::V1_0::ITuner follow.
|
||||
Return<Result> Tuner::setConfiguration(const BandConfig& config) {
|
||||
ALOGV("%s", __FUNCTION__);
|
||||
if (mHalTuner == NULL) {
|
||||
return Utils::convertHalResult(-ENODEV);
|
||||
}
|
||||
radio_hal_band_config_t halConfig;
|
||||
Utils::convertBandConfigToHal(&halConfig, &config);
|
||||
int rc = mHalTuner->set_configuration(mHalTuner, &halConfig);
|
||||
return Utils::convertHalResult(rc);
|
||||
}
|
||||
|
||||
Return<void> Tuner::getConfiguration(getConfiguration_cb _hidl_cb) {
|
||||
int rc;
|
||||
radio_hal_band_config_t halConfig;
|
||||
BandConfig config;
|
||||
|
||||
ALOGV("%s", __FUNCTION__);
|
||||
if (mHalTuner == NULL) {
|
||||
rc = -ENODEV;
|
||||
goto exit;
|
||||
}
|
||||
rc = mHalTuner->get_configuration(mHalTuner, &halConfig);
|
||||
if (rc == 0) {
|
||||
Utils::convertBandConfigFromHal(&config, &halConfig);
|
||||
}
|
||||
|
||||
exit:
|
||||
_hidl_cb(Utils::convertHalResult(rc), config);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<Result> Tuner::scan(Direction direction, bool skipSubChannel) {
|
||||
if (mHalTuner == NULL) {
|
||||
return Utils::convertHalResult(-ENODEV);
|
||||
}
|
||||
int rc = mHalTuner->scan(mHalTuner, static_cast<radio_direction_t>(direction), skipSubChannel);
|
||||
return Utils::convertHalResult(rc);
|
||||
}
|
||||
|
||||
Return<Result> Tuner::step(Direction direction, bool skipSubChannel) {
|
||||
if (mHalTuner == NULL) {
|
||||
return Utils::convertHalResult(-ENODEV);
|
||||
}
|
||||
int rc = mHalTuner->step(mHalTuner, static_cast<radio_direction_t>(direction), skipSubChannel);
|
||||
return Utils::convertHalResult(rc);
|
||||
}
|
||||
|
||||
Return<Result> Tuner::tune(uint32_t channel, uint32_t subChannel) {
|
||||
if (mHalTuner == NULL) {
|
||||
return Utils::convertHalResult(-ENODEV);
|
||||
}
|
||||
int rc = mHalTuner->tune(mHalTuner, channel, subChannel);
|
||||
return Utils::convertHalResult(rc);
|
||||
}
|
||||
|
||||
Return<Result> Tuner::cancel() {
|
||||
if (mHalTuner == NULL) {
|
||||
return Utils::convertHalResult(-ENODEV);
|
||||
}
|
||||
int rc = mHalTuner->cancel(mHalTuner);
|
||||
return Utils::convertHalResult(rc);
|
||||
}
|
||||
|
||||
Return<void> Tuner::getProgramInformation(bool withMetadata, getProgramInformation_cb _hidl_cb) {
|
||||
int rc;
|
||||
radio_program_info_t halInfo;
|
||||
ProgramInfo info;
|
||||
|
||||
ALOGV("%s", __FUNCTION__);
|
||||
if (mHalTuner == NULL) {
|
||||
rc = -ENODEV;
|
||||
goto exit;
|
||||
}
|
||||
if (withMetadata) {
|
||||
radio_metadata_allocate(&halInfo.metadata, 0, 0);
|
||||
} else {
|
||||
halInfo.metadata = NULL;
|
||||
}
|
||||
rc = mHalTuner->get_program_information(mHalTuner, &halInfo);
|
||||
if (rc == 0) {
|
||||
Utils::convertProgramInfoFromHal(&info, &halInfo, withMetadata);
|
||||
}
|
||||
if (withMetadata) {
|
||||
radio_metadata_deallocate(halInfo.metadata);
|
||||
}
|
||||
|
||||
exit:
|
||||
_hidl_cb(Utils::convertHalResult(rc), info);
|
||||
return Void();
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V1_0
|
||||
} // namespace broadcastradio
|
||||
} // namespace hardware
|
||||
} // namespace android
|
67
broadcastradio/1.0/default/Tuner.h
Normal file
67
broadcastradio/1.0/default/Tuner.h
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef HIDL_GENERATED_android_hardware_broadcastradio_V1_0_Tuner_H_
|
||||
#define HIDL_GENERATED_android_hardware_broadcastradio_V1_0_Tuner_H_
|
||||
|
||||
#include <android/hardware/broadcastradio/1.0/ITuner.h>
|
||||
#include <android/hardware/broadcastradio/1.0/ITunerCallback.h>
|
||||
#include <hidl/Status.h>
|
||||
#include <hardware/radio.h>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace broadcastradio {
|
||||
namespace V1_0 {
|
||||
namespace implementation {
|
||||
|
||||
struct BroadcastRadio;
|
||||
|
||||
struct Tuner : public ITuner {
|
||||
|
||||
Tuner(const sp<ITunerCallback>& callback, const wp<BroadcastRadio>& mParentDevice);
|
||||
|
||||
// Methods from ::android::hardware::broadcastradio::V1_0::ITuner follow.
|
||||
Return<Result> setConfiguration(const BandConfig& config) override;
|
||||
Return<void> getConfiguration(getConfiguration_cb _hidl_cb) override;
|
||||
Return<Result> scan(Direction direction, bool skipSubChannel) override;
|
||||
Return<Result> step(Direction direction, bool skipSubChannel) override;
|
||||
Return<Result> tune(uint32_t channel, uint32_t subChannel) override;
|
||||
Return<Result> cancel() override;
|
||||
Return<void> getProgramInformation(bool withMetadata,
|
||||
getProgramInformation_cb _hidl_cb) override;
|
||||
|
||||
static void callback(radio_hal_event_t *halEvent, void *cookie);
|
||||
void onCallback(radio_hal_event_t *halEvent);
|
||||
|
||||
void setHalTuner(const struct radio_tuner *halTuner) { mHalTuner = halTuner; }
|
||||
const struct radio_tuner *getHalTuner() { return mHalTuner; }
|
||||
|
||||
private:
|
||||
~Tuner();
|
||||
|
||||
const struct radio_tuner *mHalTuner;
|
||||
const sp<ITunerCallback> mCallback;
|
||||
const wp<BroadcastRadio> mParentDevice;
|
||||
};
|
||||
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V1_0
|
||||
} // namespace broadcastradio
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // HIDL_GENERATED_android_hardware_broadcastradio_V1_0_Tuner_H_
|
297
broadcastradio/1.0/default/Utils.cpp
Normal file
297
broadcastradio/1.0/default/Utils.cpp
Normal file
|
@ -0,0 +1,297 @@
|
|||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#define LOG_TAG "BroadcastRadioHalUtils"
|
||||
//#define LOG_NDEBUG 0
|
||||
|
||||
#include <utils/Log.h>
|
||||
#include <utils/misc.h>
|
||||
#include <system/radio_metadata.h>
|
||||
|
||||
#include "Utils.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace broadcastradio {
|
||||
namespace V1_0 {
|
||||
namespace implementation {
|
||||
|
||||
const char *Utils::sClassModuleNames[] = {
|
||||
RADIO_HARDWARE_MODULE_ID_FM, /* corresponds to RADIO_CLASS_AM_FM */
|
||||
RADIO_HARDWARE_MODULE_ID_SAT, /* corresponds to RADIO_CLASS_SAT */
|
||||
RADIO_HARDWARE_MODULE_ID_DT, /* corresponds to RADIO_CLASS_DT */
|
||||
};
|
||||
|
||||
// make sure HIDL enum values are aligned with legacy values
|
||||
static_assert(RADIO_CLASS_AM_FM == static_cast<int>(Class::AM_FM),
|
||||
"AM/FM class mismatch with legacy");
|
||||
static_assert(RADIO_CLASS_SAT == static_cast<int>(Class::SAT),
|
||||
"SAT class mismatch with legacy");
|
||||
static_assert(RADIO_CLASS_DT == static_cast<int>(Class::DT),
|
||||
"DT class mismatch with legacy");
|
||||
|
||||
static_assert(RADIO_BAND_AM == static_cast<int>(Band::AM),
|
||||
"AM band mismatch with legacy");
|
||||
static_assert(RADIO_BAND_FM == static_cast<int>(Band::FM),
|
||||
"FM band mismatch with legacy");
|
||||
static_assert(RADIO_BAND_AM_HD == static_cast<int>(Band::AM_HD),
|
||||
"AM HD band mismatch with legacy");
|
||||
static_assert(RADIO_BAND_FM_HD == static_cast<int>(Band::FM_HD),
|
||||
"FM HD band mismatch with legacy");
|
||||
|
||||
static_assert(RADIO_RDS_NONE == static_cast<int>(Rds::NONE),
|
||||
"RDS NONE mismatch with legacy");
|
||||
static_assert(RADIO_RDS_WORLD == static_cast<int>(Rds::WORLD),
|
||||
"RDS WORLD mismatch with legacy");
|
||||
static_assert(RADIO_RDS_US == static_cast<int>(Rds::US),
|
||||
"RDS US mismatch with legacy");
|
||||
|
||||
static_assert(RADIO_DEEMPHASIS_50 == static_cast<int>(Deemphasis::D50),
|
||||
"De-emphasis 50 mismatch with legacy");
|
||||
static_assert(RADIO_DEEMPHASIS_75 == static_cast<int>(Deemphasis::D75),
|
||||
"De-emphasis 75 mismatch with legacy");
|
||||
|
||||
static_assert(RADIO_DIRECTION_UP == static_cast<int>(Direction::UP),
|
||||
"Direction Up mismatch with legacy");
|
||||
static_assert(RADIO_DIRECTION_DOWN == static_cast<int>(Direction::DOWN),
|
||||
"Direction Up mismatch with legacy");
|
||||
|
||||
static_assert(RADIO_METADATA_TYPE_INVALID == static_cast<int>(MetadataType::INVALID),
|
||||
"Metadata type INVALID mismatch with legacy");
|
||||
static_assert(RADIO_METADATA_TYPE_INT == static_cast<int>(MetadataType::INT),
|
||||
"Metadata type INT mismatch with legacy");
|
||||
static_assert(RADIO_METADATA_TYPE_TEXT == static_cast<int>(MetadataType::TEXT),
|
||||
"Metadata type TEXT mismatch with legacy");
|
||||
static_assert(RADIO_METADATA_TYPE_RAW == static_cast<int>(MetadataType::RAW),
|
||||
"Metadata type RAW mismatch with legacy");
|
||||
static_assert(RADIO_METADATA_TYPE_CLOCK == static_cast<int>(MetadataType::CLOCK),
|
||||
"Metadata type CLOCK mismatch with legacy");
|
||||
|
||||
static_assert(RADIO_METADATA_KEY_INVALID == static_cast<int>(MetadataKey::INVALID),
|
||||
"Metadata key INVALID mismatch with legacy");
|
||||
static_assert(RADIO_METADATA_KEY_RDS_PI == static_cast<int>(MetadataKey::RDS_PI),
|
||||
"Metadata key RDS_PI mismatch with legacy");
|
||||
static_assert(RADIO_METADATA_KEY_RDS_PS == static_cast<int>(MetadataKey::RDS_PS),
|
||||
"Metadata key RDS_PS mismatch with legacy");
|
||||
static_assert(RADIO_METADATA_KEY_RDS_PTY == static_cast<int>(MetadataKey::RDS_PTY),
|
||||
"Metadata key RDS_PTY mismatch with legacy");
|
||||
static_assert(RADIO_METADATA_KEY_RBDS_PTY == static_cast<int>(MetadataKey::RBDS_PTY),
|
||||
"Metadata key RBDS_PTY mismatch with legacy");
|
||||
static_assert(RADIO_METADATA_KEY_RDS_RT == static_cast<int>(MetadataKey::RDS_RT),
|
||||
"Metadata key RDS_RT mismatch with legacy");
|
||||
static_assert(RADIO_METADATA_KEY_TITLE == static_cast<int>(MetadataKey::TITLE),
|
||||
"Metadata key TITLE mismatch with legacy");
|
||||
static_assert(RADIO_METADATA_KEY_ARTIST == static_cast<int>(MetadataKey::ARTIST),
|
||||
"Metadata key ARTIST mismatch with legacy");
|
||||
static_assert(RADIO_METADATA_KEY_ALBUM == static_cast<int>(MetadataKey::ALBUM),
|
||||
"Metadata key ALBUM mismatch with legacy");
|
||||
static_assert(RADIO_METADATA_KEY_GENRE == static_cast<int>(MetadataKey::GENRE),
|
||||
"Metadata key GENRE mismatch with legacy");
|
||||
static_assert(RADIO_METADATA_KEY_ICON == static_cast<int>(MetadataKey::ICON),
|
||||
"Metadata key ICON mismatch with legacy");
|
||||
static_assert(RADIO_METADATA_KEY_ART == static_cast<int>(MetadataKey::ART),
|
||||
"Metadata key ART mismatch with legacy");
|
||||
static_assert(RADIO_METADATA_KEY_CLOCK == static_cast<int>(MetadataKey::CLOCK),
|
||||
"Metadata key CLOCK mismatch with legacy");
|
||||
|
||||
|
||||
//static
|
||||
const char * Utils::getClassString(Class ClassId)
|
||||
{
|
||||
int id = static_cast<int>(ClassId);
|
||||
|
||||
if ((id < 0) ||
|
||||
(id >= NELEM(sClassModuleNames))) {
|
||||
ALOGE("invalid class ID %d", id);
|
||||
return NULL;
|
||||
}
|
||||
return sClassModuleNames[id];
|
||||
}
|
||||
|
||||
//static
|
||||
Result Utils::convertHalResult(int rc)
|
||||
{
|
||||
switch (rc) {
|
||||
case 0:
|
||||
return Result::OK;
|
||||
case -EINVAL:
|
||||
return Result::INVALID_ARGUMENTS;
|
||||
case -ENOSYS:
|
||||
return Result::INVALID_STATE;
|
||||
case -ETIMEDOUT:
|
||||
return Result::TIMEOUT;
|
||||
case -ENODEV:
|
||||
default:
|
||||
return Result::NOT_INITIALIZED;
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
void Utils::convertBandConfigFromHal(
|
||||
BandConfig *config,
|
||||
const radio_hal_band_config_t *halConfig)
|
||||
{
|
||||
|
||||
config->type = static_cast<Band>(halConfig->type);
|
||||
config->antennaConnected = halConfig->antenna_connected;
|
||||
config->lowerLimit = halConfig->lower_limit;
|
||||
config->upperLimit = halConfig->upper_limit;
|
||||
config->spacings.setToExternal(const_cast<unsigned int *>(&halConfig->spacings[0]),
|
||||
halConfig->num_spacings * sizeof(uint32_t));
|
||||
// FIXME: transfer buffer ownership. should have a method for that in hidl_vec
|
||||
config->spacings.resize(halConfig->num_spacings);
|
||||
|
||||
if (config->type == Band::FM) {
|
||||
config->ext.fm.deemphasis = static_cast<Deemphasis>(halConfig->fm.deemphasis);
|
||||
config->ext.fm.stereo = halConfig->fm.stereo;
|
||||
config->ext.fm.rds = static_cast<Rds>(halConfig->fm.rds);
|
||||
config->ext.fm.ta = halConfig->fm.ta;
|
||||
config->ext.fm.af = halConfig->fm.af;
|
||||
config->ext.fm.ea = halConfig->fm.ea;
|
||||
} else {
|
||||
config->ext.am.stereo = halConfig->am.stereo;
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
void Utils::convertPropertiesFromHal(
|
||||
Properties *properties,
|
||||
const radio_hal_properties_t *halProperties)
|
||||
{
|
||||
properties->classId = static_cast<Class>(halProperties->class_id);
|
||||
properties->implementor.setToExternal(halProperties->implementor, strlen(halProperties->implementor));
|
||||
properties->product.setToExternal(halProperties->product, strlen(halProperties->product));
|
||||
properties->version.setToExternal(halProperties->version, strlen(halProperties->version));
|
||||
properties->serial.setToExternal(halProperties->serial, strlen(halProperties->serial));
|
||||
properties->numTuners = halProperties->num_tuners;
|
||||
properties->numAudioSources = halProperties->num_audio_sources;
|
||||
properties->supportsCapture = halProperties->supports_capture;
|
||||
|
||||
BandConfig *bands =
|
||||
new BandConfig[halProperties->num_bands];
|
||||
for (size_t i = 0; i < halProperties->num_bands; i++) {
|
||||
convertBandConfigFromHal(&bands[i], &halProperties->bands[i]);
|
||||
}
|
||||
properties->bands.setToExternal(bands, halProperties->num_bands);
|
||||
// FIXME: transfer buffer ownership. should have a method for that in hidl_vec
|
||||
properties->bands.resize(halProperties->num_bands);
|
||||
delete[] bands;
|
||||
}
|
||||
|
||||
//static
|
||||
void Utils::convertBandConfigToHal(
|
||||
radio_hal_band_config_t *halConfig,
|
||||
const BandConfig *config)
|
||||
{
|
||||
|
||||
halConfig->type = static_cast<radio_band_t>(config->type);
|
||||
halConfig->antenna_connected = config->antennaConnected;
|
||||
halConfig->lower_limit = config->lowerLimit;
|
||||
halConfig->upper_limit = config->upperLimit;
|
||||
halConfig->num_spacings = config->spacings.size();
|
||||
if (halConfig->num_spacings > RADIO_NUM_SPACINGS_MAX) {
|
||||
halConfig->num_spacings = RADIO_NUM_SPACINGS_MAX;
|
||||
}
|
||||
memcpy(halConfig->spacings, config->spacings.data(),
|
||||
sizeof(uint32_t) * halConfig->num_spacings);
|
||||
|
||||
if (config->type == Band::FM) {
|
||||
halConfig->fm.deemphasis = static_cast<radio_deemphasis_t>(config->ext.fm.deemphasis);
|
||||
halConfig->fm.stereo = config->ext.fm.stereo;
|
||||
halConfig->fm.rds = static_cast<radio_rds_t>(config->ext.fm.rds);
|
||||
halConfig->fm.ta = config->ext.fm.ta;
|
||||
halConfig->fm.af = config->ext.fm.af;
|
||||
halConfig->fm.ea = config->ext.fm.ea;
|
||||
} else {
|
||||
halConfig->am.stereo = config->ext.am.stereo;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//static
|
||||
void Utils::convertProgramInfoFromHal(ProgramInfo *info,
|
||||
radio_program_info_t *halInfo,
|
||||
bool withMetadata)
|
||||
{
|
||||
info->channel = halInfo->channel;
|
||||
info->subChannel = halInfo->sub_channel;
|
||||
info->tuned = halInfo->tuned;
|
||||
info->stereo = halInfo->stereo;
|
||||
info->digital = halInfo->digital;
|
||||
info->signalStrength = halInfo->signal_strength;
|
||||
if (withMetadata && halInfo->metadata != NULL) {
|
||||
convertMetaDataFromHal(info->metadata, halInfo->metadata);
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
int Utils::convertMetaDataFromHal(hidl_vec<MetaData>& metadata,
|
||||
radio_metadata_t *halMetadata)
|
||||
{
|
||||
if (halMetadata == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int count = radio_metadata_get_count(halMetadata);
|
||||
if (count <= 0) {
|
||||
return count;
|
||||
}
|
||||
MetaData *newMetadata =
|
||||
new MetaData[count];
|
||||
int outCount = 0;
|
||||
for (int i = 0; i < count; i++) {
|
||||
radio_metadata_key_t key;
|
||||
radio_metadata_type_t type;
|
||||
void *value;
|
||||
size_t size;
|
||||
if (radio_metadata_get_at_index(halMetadata, i , &key, &type, &value, &size) != 0 ||
|
||||
size == 0) {
|
||||
continue;
|
||||
}
|
||||
switch (type) {
|
||||
case RADIO_METADATA_TYPE_INT: {
|
||||
newMetadata[outCount].intValue = *(static_cast<int32_t *>(value));
|
||||
} break;
|
||||
case RADIO_METADATA_TYPE_TEXT: {
|
||||
newMetadata[outCount].stringValue = static_cast<char *>(value);
|
||||
} break;
|
||||
case RADIO_METADATA_TYPE_RAW: {
|
||||
newMetadata[outCount].rawValue.setToExternal(static_cast<uint8_t *>(value), size);
|
||||
// FIXME: transfer buffer ownership. should have a method for that in hidl_vec
|
||||
newMetadata[outCount].rawValue.resize(size);
|
||||
} break;
|
||||
case RADIO_METADATA_TYPE_CLOCK: {
|
||||
radio_metadata_clock_t *clock = static_cast<radio_metadata_clock_t *>(value);
|
||||
newMetadata[outCount].clockValue.utcSecondsSinceEpoch =
|
||||
clock->utc_seconds_since_epoch;
|
||||
newMetadata[outCount].clockValue.timezoneOffsetInMinutes =
|
||||
clock->timezone_offset_in_minutes;
|
||||
} break;
|
||||
}
|
||||
newMetadata[outCount].type = static_cast<MetadataType>(type);
|
||||
newMetadata[outCount].key = static_cast<MetadataKey>(key);
|
||||
outCount++;
|
||||
}
|
||||
metadata.setToExternal(newMetadata, outCount);
|
||||
// FIXME: transfer buffer ownership. should have a method for that in hidl_vec
|
||||
metadata.resize(outCount);
|
||||
return outCount;
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V1_0
|
||||
} // namespace broadcastradio
|
||||
} // namespace hardware
|
||||
} // namespace android
|
54
broadcastradio/1.0/default/Utils.h
Normal file
54
broadcastradio/1.0/default/Utils.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_0_UTILS_H
|
||||
#define ANDROID_HARDWARE_BROADCASTRADIO_V1_0_UTILS_H
|
||||
|
||||
#include <android/hardware/broadcastradio/1.0/types.h>
|
||||
#include <hardware/radio.h>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace broadcastradio {
|
||||
namespace V1_0 {
|
||||
namespace implementation {
|
||||
|
||||
class Utils {
|
||||
public:
|
||||
static const char * getClassString(Class ClassId);
|
||||
static Result convertHalResult(int rc);
|
||||
static void convertBandConfigFromHal(BandConfig *config,
|
||||
const radio_hal_band_config_t *halConfig);
|
||||
static void convertPropertiesFromHal(Properties *properties,
|
||||
const radio_hal_properties_t *halProperties);
|
||||
static void convertBandConfigToHal(radio_hal_band_config_t *halConfig,
|
||||
const BandConfig *config);
|
||||
static void convertProgramInfoFromHal(ProgramInfo *info,
|
||||
radio_program_info_t *halInfo,
|
||||
bool withMetadata);
|
||||
static int convertMetaDataFromHal(hidl_vec<MetaData>& metadata,
|
||||
radio_metadata_t *halMetadata);
|
||||
private:
|
||||
static const char * sClassModuleNames[];
|
||||
|
||||
};
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V1_0
|
||||
} // namespace broadcastradio
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // ANDROID_HARDWARE_BROADCASTRADIO_V1_0_UTILS_H
|
|
@ -54,7 +54,7 @@ enum Band : uint32_t {
|
|||
enum Rds : uint32_t {
|
||||
NONE = 0,
|
||||
WORLD = (1<<0),
|
||||
RDS_US = (1<<1),
|
||||
US = (1<<1),
|
||||
};
|
||||
|
||||
|
||||
|
@ -111,7 +111,7 @@ struct BandConfig {
|
|||
union Ext {
|
||||
FmBandConfig fm;
|
||||
AmBandConfig am;
|
||||
};
|
||||
} ext;
|
||||
};
|
||||
|
||||
/* Exposes properties of a given hardware radio module.
|
||||
|
|
Loading…
Reference in a new issue