/*
 * HAL devices support
 *
 * Copyright 2006 Alexandre Julliard
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include "config.h"
#include "wine/port.h"

#include <assert.h>
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <sys/time.h>

#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "winuser.h"
#include "excpt.h"

#include "wine/library.h"
#include "wine/exception.h"
#include "wine/debug.h"
#include "explorer_private.h"

WINE_DEFAULT_DEBUG_CHANNEL(explorer);

#ifdef SONAME_LIBHAL

#include <dbus/dbus.h>
#include <hal/libhal.h>

#define DBUS_FUNCS \
    DO_FUNC(dbus_bus_get); \
    DO_FUNC(dbus_connection_close); \
    DO_FUNC(dbus_connection_read_write_dispatch); \
    DO_FUNC(dbus_error_init); \
    DO_FUNC(dbus_error_free); \
    DO_FUNC(dbus_error_is_set)

#define HAL_FUNCS \
    DO_FUNC(libhal_ctx_free); \
    DO_FUNC(libhal_ctx_init); \
    DO_FUNC(libhal_ctx_new); \
    DO_FUNC(libhal_ctx_set_dbus_connection); \
    DO_FUNC(libhal_ctx_set_device_added); \
    DO_FUNC(libhal_ctx_set_device_property_modified); \
    DO_FUNC(libhal_ctx_set_device_removed); \
    DO_FUNC(libhal_ctx_shutdown); \
    DO_FUNC(libhal_device_get_property_bool); \
    DO_FUNC(libhal_device_get_property_string); \
    DO_FUNC(libhal_device_add_property_watch); \
    DO_FUNC(libhal_device_remove_property_watch); \
    DO_FUNC(libhal_free_string); \
    DO_FUNC(libhal_free_string_array); \
    DO_FUNC(libhal_get_all_devices)

#define DO_FUNC(f) static typeof(f) * p_##f
DBUS_FUNCS;
HAL_FUNCS;
#undef DO_FUNC

static BOOL load_functions(void)
{
    void *hal_handle;
    char error[128];

    /* Load libhal with RTLD_GLOBAL so that the dbus symbols are available.
     * We can't load libdbus directly since libhal may have been built against a
     * different version but with the same soname. Binary compatibility is for wimps. */

    if (!(hal_handle = wine_dlopen(SONAME_LIBHAL, RTLD_NOW|RTLD_GLOBAL, error, sizeof(error))))
        goto failed;

#define DO_FUNC(f) if (!(p_##f = wine_dlsym( RTLD_DEFAULT, #f, error, sizeof(error) ))) goto failed
    DBUS_FUNCS;
#undef DO_FUNC

#define DO_FUNC(f) if (!(p_##f = wine_dlsym( hal_handle, #f, error, sizeof(error) ))) goto failed
    HAL_FUNCS;
#undef DO_FUNC

    return TRUE;

failed:
    WINE_WARN( "failed to load HAL support: %s\n", error );
    return FALSE;
}

static WINE_EXCEPTION_FILTER(assert_fault)
{
    if (GetExceptionCode() == EXCEPTION_WINE_ASSERTION) return EXCEPTION_EXECUTE_HANDLER;
    return EXCEPTION_CONTINUE_SEARCH;
}

/* HAL callback for new device */
static void new_device( LibHalContext *ctx, const char *udi )
{
    DBusError error;
    char *parent = NULL;
    char *mount_point = NULL;
    char *device = NULL;
    char *type = NULL;

    p_dbus_error_init( &error );

    if (!(device = p_libhal_device_get_property_string( ctx, udi, "block.device", &error )))
        goto done;

    if (!(mount_point = p_libhal_device_get_property_string( ctx, udi, "volume.mount_point", &error )))
        goto done;

    if (!(parent = p_libhal_device_get_property_string( ctx, udi, "info.parent", &error )))
        goto done;

    if (!p_libhal_device_get_property_bool( ctx, parent, "storage.removable", &error ))
        goto done;

    if (!(type = p_libhal_device_get_property_string( ctx, parent, "storage.drive_type", &error )))
        p_dbus_error_free( &error );  /* ignore error */

    add_dos_device( udi, device, mount_point, type );

    /* add property watch for mount point */
    p_libhal_device_add_property_watch( ctx, udi, &error );

done:
    if (type) p_libhal_free_string( type );
    if (parent) p_libhal_free_string( parent );
    if (device) p_libhal_free_string( device );
    if (mount_point) p_libhal_free_string( mount_point );
    p_dbus_error_free( &error );
}

/* HAL callback for removed device */
static void removed_device( LibHalContext *ctx, const char *udi )
{
    DBusError error;

    WINE_TRACE( "removed %s\n", wine_dbgstr_a(udi) );

    if (remove_dos_device( udi ))
    {
        p_dbus_error_init( &error );
        p_libhal_device_remove_property_watch( ctx, udi, &error );
        p_dbus_error_free( &error );
    }
}

/* HAL callback for property changes */
static void property_modified (LibHalContext *ctx, const char *udi,
                               const char *key, dbus_bool_t is_removed, dbus_bool_t is_added)
{
    WINE_TRACE( "udi %s key %s %s\n", wine_dbgstr_a(udi), wine_dbgstr_a(key),
                is_added ? "added" : is_removed ? "removed" : "modified" );

    if (!strcmp( key, "volume.mount_point" )) new_device( ctx, udi );
}


static DWORD WINAPI hal_thread( void *arg )
{
    DBusError error;
    DBusConnection *dbc;
    LibHalContext *ctx;
    int i, num;
    char **list;

    if (!(ctx = p_libhal_ctx_new())) return 1;

    p_dbus_error_init( &error );
    if (!(dbc = p_dbus_bus_get( DBUS_BUS_SYSTEM, &error )))
    {
        WINE_WARN( "failed to get system dbus connection: %s\n", error.message );
        p_dbus_error_free( &error );
        return 1;
    }

    p_libhal_ctx_set_dbus_connection( ctx, dbc );
    p_libhal_ctx_set_device_added( ctx, new_device );
    p_libhal_ctx_set_device_removed( ctx, removed_device );
    p_libhal_ctx_set_device_property_modified( ctx, property_modified );

    if (!p_libhal_ctx_init( ctx, &error ))
    {
        WINE_WARN( "HAL context init failed: %s\n", error.message );
        p_dbus_error_free( &error );
        return 1;
    }

    /* retrieve all existing devices */
    if (!(list = p_libhal_get_all_devices( ctx, &num, &error ))) p_dbus_error_free( &error );
    else
    {
        for (i = 0; i < num; i++) new_device( ctx, list[i] );
        p_libhal_free_string_array( list );
    }

    __TRY
    {
        while (p_dbus_connection_read_write_dispatch( dbc, -1 )) /* nothing */ ;
    }
    __EXCEPT( assert_fault )
    {
        WINE_WARN( "dbus assertion failure, disabling HAL support\n" );
        return 1;
    }
    __ENDTRY;

    p_libhal_ctx_shutdown( ctx, &error );
    p_dbus_error_free( &error );  /* just in case */
    p_dbus_connection_close( dbc );
    p_libhal_ctx_free( ctx );
    return 0;
}

void initialize_hal(void)
{
    HANDLE handle;

    if (!load_functions()) return;
    if (!(handle = CreateThread( NULL, 0, hal_thread, NULL, 0, NULL ))) return;
    CloseHandle( handle );
}

#else  /* SONAME_LIBHAL */

void initialize_hal(void)
{
    WINE_TRACE( "Skipping, HAL support not compiled in\n" );
}

#endif  /* SONAME_LIBHAL */
