int ril_open(struct ril_handle *ril)
{
    char property[PROPERTY_VALUE_MAX];

    if (!ril)
        return -1;

    ril->handle = dlopen(RIL_CLIENT_LIBPATH, RTLD_NOW);

    if (!ril->handle) {
        LOGE("Cannot open '%s'", RIL_CLIENT_LIBPATH);
        return -1;
    }

    _ril_open_client = dlsym(ril->handle, "OpenClient_RILD");
    _ril_close_client = dlsym(ril->handle, "CloseClient_RILD");
    _ril_connect = dlsym(ril->handle, "Connect_RILD");
    _ril_is_connected = dlsym(ril->handle, "isConnected_RILD");
    _ril_disconnect = dlsym(ril->handle, "Disconnect_RILD");
    _ril_set_call_volume = dlsym(ril->handle, "SetCallVolume");
    _ril_set_call_audio_path = dlsym(ril->handle, "SetCallAudioPath");
    _ril_set_call_clock_sync = dlsym(ril->handle, "SetCallClockSync");
    _ril_register_unsolicited_handler = dlsym(ril->handle,
                                              "RegisterUnsolicitedHandler");

    if (!_ril_open_client || !_ril_close_client || !_ril_connect ||
        !_ril_is_connected || !_ril_disconnect || !_ril_set_call_volume ||
        !_ril_set_call_audio_path || !_ril_set_call_clock_sync ||
        !_ril_register_unsolicited_handler) {
        LOGE("Cannot get symbols from '%s'", RIL_CLIENT_LIBPATH);
        dlclose(ril->handle);
        return -1;
    }

    ril->client = _ril_open_client();
    if (!ril->client) {
        LOGE("ril_open_client() failed");
        dlclose(ril->handle);
        return -1;
    }

    property_get(VOLUME_STEPS_PROPERTY, property, VOLUME_STEPS_DEFAULT);
    ril->volume_steps_max = atoi(property);
    /* this catches the case where VOLUME_STEPS_PROPERTY does not contain
    an integer */
    if (ril->volume_steps_max == 0)
        ril->volume_steps_max = atoi(VOLUME_STEPS_DEFAULT);

    return 0;
}
int audio_ril_interface_open(struct audio_hw_device *dev, audio_devices_t device,
	struct tinyalsa_audio_ril_interface **ril_interface)
{
	struct audio_ril_interface *(*audio_ril_interface_open)(void);

	struct tinyalsa_audio_device *tinyalsa_audio_device;
	struct tinyalsa_audio_ril_interface *tinyalsa_audio_ril_interface;
	struct audio_ril_interface *interface;
	void *dl_handle;
	int rc;

	char property[PROPERTY_VALUE_MAX];

	ALOGD("%s(%p, %d, %p)", __func__, dev, device, ril_interface);

	if(dev == NULL || ril_interface == NULL)
		return -EINVAL;

	tinyalsa_audio_device = (struct tinyalsa_audio_device *) dev;
	tinyalsa_audio_ril_interface = calloc(1, sizeof(struct tinyalsa_audio_ril_interface));

	if(tinyalsa_audio_ril_interface == NULL)
		return -ENOMEM;

	tinyalsa_audio_ril_interface->device = tinyalsa_audio_device;
	tinyalsa_audio_device->ril_interface = tinyalsa_audio_ril_interface;

	dl_handle = dlopen(RIL_CLIENT_LIBPATH, RTLD_NOW);
	if(dl_handle == NULL) {
		ALOGE("Unable to dlopen lib: %s", RIL_CLIENT_LIBPATH);
		goto error_interface;
	}

	_ril_open_client = dlsym(dl_handle, "OpenClient_RILD");
	_ril_close_client = dlsym(dl_handle, "CloseClient_RILD");
	_ril_connect = dlsym(dl_handle, "Connect_RILD");
	_ril_is_connected = dlsym(dl_handle, "isConnected_RILD");
	_ril_disconnect = dlsym(dl_handle, "Disconnect_RILD");
	_ril_set_call_volume = dlsym(dl_handle, "SetCallVolume");
	_ril_set_call_audio_path = dlsym(dl_handle, "SetCallAudioPath");
	_ril_set_call_clock_sync = dlsym(dl_handle, "SetCallClockSync");
        _ril_set_call_twomic = dlsym(dl_handle, "SetTwoMicControl");

	_ril_register_unsolicited_handler = dlsym(dl_handle,
						  "RegisterUnsolicitedHandler");
	/* since this function is not supported in all RILs, don't require it */
	_ril_get_wb_amr = dlsym(dl_handle, "GetWB_AMR");

	if (!_ril_open_client || !_ril_close_client || !_ril_connect ||
	    !_ril_is_connected || !_ril_disconnect || !_ril_set_call_volume ||
	    !_ril_set_call_audio_path || !_ril_set_call_clock_sync ||
	    !_ril_register_unsolicited_handler || !_ril_set_call_twomic) {
	  ALOGE("Cannot get symbols from '%s'", RIL_CLIENT_LIBPATH);
	  dlclose(dl_handle);
	  goto error_interface;
	}

	interface = _ril_open_client();
	if(interface == NULL) {
		ALOGE("Unable to open audio ril interface");
		goto error_interface;
	}

	tinyalsa_audio_ril_interface->interface = interface;
	tinyalsa_audio_ril_interface->dl_handle = dl_handle;

	property_get(VOLUME_STEPS_PROPERTY, property, VOLUME_STEPS_DEFAULT);
	tinyalsa_audio_ril_interface->volume_steps_max = atoi(property);
	/* this catches the case where VOLUME_STEPS_PROPERTY does not contain
	   an integer */
	if (tinyalsa_audio_ril_interface->volume_steps_max == 0)
	  tinyalsa_audio_ril_interface->volume_steps_max = atoi(VOLUME_STEPS_DEFAULT);
	
	if(device) {
		tinyalsa_audio_ril_interface->device_current = device;
		audio_ril_interface_set_route(tinyalsa_audio_ril_interface, device);
	}

	*ril_interface = tinyalsa_audio_ril_interface;

	return 0;

error_interface:
	*ril_interface = NULL;
	free(tinyalsa_audio_ril_interface);
	tinyalsa_audio_device->ril_interface = NULL;

	if(dl_handle != NULL)
		dlclose(dl_handle);

	return -1;
}