예제 #1
0
파일: hal.c 프로젝트: JoliOS/xorg-server
static char *
get_prop_string_array(LibHalContext *hal_ctx, const char *udi, const char *prop)
{
    char **props, *ret, *str;
    int i, len = 0;

    props = libhal_device_get_property_strlist(hal_ctx, udi, prop, NULL);
    if (props) {
        for (i = 0; props[i]; i++)
            len += strlen(props[i]);

        ret = xcalloc(sizeof(char), len + i); /* i - 1 commas, 1 NULL */
        if (!ret) {
            libhal_free_string_array(props);
            return NULL;
        }

        str = ret;
        for (i = 0; props[i]; i++) {
            strcpy(str, props[i]);
            str += strlen(props[i]);
            *str++ = ',';
        }
        *(str-1) = '\0';

        libhal_free_string_array(props);
    }
    else {
        return NULL;
    }

    return ret;
}
예제 #2
0
static int
gather_capabilities(LibHalContext *ctx, const char *udi,
                    virNodeDevCapsDefPtr *caps_p)
{
    char *bus_name = NULL;
    virNodeDevCapsDefPtr caps = NULL;
    char **hal_cap_names = NULL;
    int rv;
    size_t i;

    if (STREQ(udi, "/org/freedesktop/Hal/devices/computer")) {
        rv = gather_capability(ctx, udi, "system", &caps);
        if (rv != 0)
            goto failure;
    }

    if (get_str_prop(ctx, udi, "info.subsystem", &bus_name) == 0 ||
        get_str_prop(ctx, udi, "linux.subsystem", &bus_name) == 0) {
        rv = gather_capability(ctx, udi, bus_name, &caps);
        if (rv != 0)
            goto failure;
    }

    hal_cap_names = libhal_device_get_property_strlist(ctx, udi,
                                                       "info.capabilities",
                                                       NULL);
    if (hal_cap_names) {
        for (i = 0; hal_cap_names[i]; i++) {
            if (! (bus_name && STREQ(hal_cap_names[i], bus_name))) {
                rv = gather_capability(ctx, udi, hal_cap_names[i], &caps);
                if (rv != 0)
                    goto failure;
            }
        }
        for (i = 0; hal_cap_names[i]; i++)
            VIR_FREE(hal_cap_names[i]);
        VIR_FREE(hal_cap_names);
    }
    VIR_FREE(bus_name);

    *caps_p = caps;
    return 0;

 failure:
    VIR_FREE(bus_name);
    if (hal_cap_names) {
        for (i = 0; hal_cap_names[i]; i++)
            VIR_FREE(hal_cap_names[i]);
        VIR_FREE(hal_cap_names);
    }
    while (caps) {
        virNodeDevCapsDefPtr next = caps->next;
        virNodeDevCapsDefFree(caps);
        caps = next;
    }
    return rv;
}
예제 #3
0
void CHALManager::HandleNewVolume(CStorageDevice *dev)
{
  if (g_advancedSettings.m_handleMounting)
  {
/* Here it can be checked if the device isn't mounted and then mount */
//TODO Have mountpoints be other than in /media/*
    if (!dev->Mounted && (dev->HotPlugged || dev->Type == 2) && dev->Approved)
    {
      char **capability;
      capability =libhal_device_get_property_strlist (m_Context, dev->UDI.c_str(), "info.capabilities", NULL);

      bool Mountable = false;
      if (dev->Type == 2 && (strcmp(capability[0], "volume.disc") == 0 && strcmp(capability[1], "volume") == 0)) // CD/DVD
        Mountable = true;
      else if ((strcmp(capability[0], "volume") == 0 && strcmp(capability[1], "block") == 0)) // HDD
        Mountable = true;

      if (Mountable)
      {
        CLog::Log(LOGNOTICE, "HAL: Trying to mount %s", dev->FriendlyName.c_str());
        CStdString MountPoint;
        CStdString TestPath;
        if (dev->Label.size() > 0)
        {
          MountPoint = dev->Label.c_str();
          TestPath.Format("/media/%s", MountPoint.c_str());
          struct stat St;
          if (stat("/media", &St) != 0)
            return; //If /media doesn't exist something is wrong.
          while(stat (TestPath.c_str(), &St) == 0 && S_ISDIR (St.st_mode))
          {
            CLog::Log(LOGDEBUG, "HAL: Proposed Mountpoint already existed");
            MountPoint.append("_");
            TestPath.Format("/media/%s", MountPoint.c_str());
          }
        }
        else
        {
          MountPoint = StorageTypeToString(dev->Type);
          TestPath.Format("/media/%s", MountPoint.c_str());
          int Nbr = 0;
          struct stat St;
          if (stat("/media", &St) != 0)
            return; //If /media doesn't exist something is wrong.
          while(stat (TestPath.c_str(), &St) == 0 && S_ISDIR (St.st_mode))
          {
            CLog::Log(LOGDEBUG, "HAL: Proposed Mountpoint already existed");
            Nbr++;
            MountPoint.Format("%s%i", StorageTypeToString(dev->Type), Nbr);
            TestPath.Format("/media/%s", MountPoint.c_str());
          }
        }
        if (Mount(dev, MountPoint))
        {
          CLog::Log(LOGINFO, "HAL: mounted %s on %s", dev->FriendlyName.c_str(), dev->MountPoint.c_str());
          if (m_Notifications)
            CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(13021), dev->FriendlyName.c_str(), TOAST_DISPLAY_TIME, false);
        }
      }
      libhal_free_string_array(capability);
    }
  }
}
예제 #4
0
/* Parse newly found device and add it to our remembered devices */
void CHALManager::AddDevice(const char *udi)
{
  CSingleLock lock(m_lock);
  char *category;
  category = libhal_device_get_property_string(m_Context, udi, "info.category", NULL);
  if (category == NULL)
    return;

  if (strcmp(category, "volume") == 0)
  {
    CStorageDevice dev(udi);
    if (DeviceFromVolumeUdi(udi, &dev))
    {
      CLog::Log(LOGDEBUG, "HAL: Added - %s | %s", CHALManager::StorageTypeToString(dev.Type),  dev.toString().c_str());
      HandleNewVolume(&dev);
      m_Volumes.push_back(dev);
    }
  }
#if defined(HAS_SDL_JOYSTICK)
  // Scan input devices
  else if (strcmp(category, "input") == 0)
  {
    DBusError dbusError;
    dbus_error_init(&dbusError);

    char **capability;
    capability =libhal_device_get_property_strlist (m_Context, udi, "info.capabilities", &dbusError);
    for(char **ptr = capability; *ptr != NULL;ptr++)
    {
      // Reload joysticks
      if(strcmp(*ptr, "input.joystick") == 0)
      {
        CLog::Log(LOGINFO, "HAL: Joystick plugged in");
        CHALDevice dev = CHALDevice(udi);
        dev.FriendlyName = libhal_device_get_property_string(m_Context, udi, "info.product", &m_Error);
        m_Joysticks.push_back(dev);

        if(m_Joysticks.size() < 2 || m_bMultipleJoysticksSupport)
        {
          // Restart SDL joystick subsystem
          if (!g_Joystick.Reinitialize())
            break;

          if (m_Notifications)
            CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(13024), dev.FriendlyName.c_str(), TOAST_DISPLAY_TIME, false);
        }
      }
    }
    libhal_free_string_array(capability);
  }
#endif
/*
  else if (strcmp(category, "camera") == 0)
  { // PTP-Devices }
  else if (strcmp(category, "bluetooth_hci") == 0)
  { // Bluetooth-Devices }
  else if (strcmp(category, "portable audio player") == 0)
  { // MTP-Devices }
  else if (strcmp(category, "alsa") == 0)
  { //Alsa Devices }
*/

  libhal_free_string(category);
}
예제 #5
0
/** Entry point
 *
 *  @param  argc                Number of arguments given to program
 *  @param  argv                Arguments given to program
 *  @return                     Return code
 */
int
main (int argc, char *argv[])
{
	char *udi = NULL;
	char *key = NULL;
	int type;
	dbus_bool_t is_hex = FALSE;
	dbus_bool_t is_verbose = FALSE;
	dbus_bool_t is_version = FALSE;
	char *str;
	DBusError error;

	if (argc <= 1) {
		usage (argc, argv);
		return 1;
	}

	while (1) {
		int c;
		int option_index = 0;
		const char *opt;
		static struct option long_options[] = {
			{"udi", 1, NULL, 0},
			{"key", 1, NULL, 0},
			{"hex", 0, NULL, 0},
			{"verbose", 0, NULL, 0},
			{"version", 0, NULL, 0},
			{"help", 0, NULL, 0},
			{NULL, 0, NULL, 0}
		};

		c = getopt_long (argc, argv, "",
				 long_options, &option_index);
		if (c == -1)
			break;

		switch (c) {
		case 0:
			opt = long_options[option_index].name;

			if (strcmp (opt, "help") == 0) {
				usage (argc, argv);
				return 0;
			} else if (strcmp (opt, "hex") == 0) {
				is_hex = TRUE;
			} else if (strcmp (opt, "verbose") == 0) {
				is_verbose = TRUE;
			} else if (strcmp (opt, "version") == 0) {
				is_version = TRUE;
			} else if (strcmp (opt, "key") == 0) {
				key = strdup (optarg);
			} else if (strcmp (opt, "udi") == 0) {
				udi = strdup (optarg);
			}
			break;

		default:
			usage (argc, argv);
			return 1;
			break;
		}
	}

	if (is_version) {
		printf ("hal-get-property " PACKAGE_VERSION "\n");
		return 0;
	}

	if (udi == NULL || key == NULL) {
		usage (argc, argv);
		return 1;
	}

	dbus_error_init (&error);	
	if ((hal_ctx = libhal_ctx_new ()) == NULL) {
		fprintf (stderr, "error: libhal_ctx_new\n");
		return 1;
	}
	if (!libhal_ctx_set_dbus_connection (hal_ctx, dbus_bus_get (DBUS_BUS_SYSTEM, &error))) {
		fprintf (stderr, "error: libhal_ctx_set_dbus_connection: %s: %s\n", error.name, error.message);
		LIBHAL_FREE_DBUS_ERROR (&error);
		return 1;
	}
	if (!libhal_ctx_init (hal_ctx, &error)) {
		if (dbus_error_is_set(&error)) {
			fprintf (stderr, "error: libhal_ctx_init: %s: %s\n", error.name, error.message);
			LIBHAL_FREE_DBUS_ERROR (&error);
		}
		fprintf (stderr, "Could not initialise connection to hald.\n"
				 "Normally this means the HAL daemon (hald) is not running or not ready.\n");
		return 1;
	}

	type = libhal_device_get_property_type (hal_ctx, udi, key, &error);
	if (type == LIBHAL_PROPERTY_TYPE_INVALID) {
		fprintf (stderr, "error: libhal_device_get_property_type: %s: %s\n", error.name, error.message);
		LIBHAL_FREE_DBUS_ERROR (&error);
		return 1;
	}
	/* emit the value to stdout */
	switch (type) {
	case LIBHAL_PROPERTY_TYPE_STRING:
		str = libhal_device_get_property_string (hal_ctx, udi, key, &error);
		if (is_verbose)
			printf ("Type is string\n");
		printf ("%s\n", str);
		libhal_free_string (str);
		break;
	case LIBHAL_PROPERTY_TYPE_INT32:
		if (is_verbose)
			printf ("Type is integer (shown in %s)\n",
				(is_hex ? "hexadecimal" : "decimal"));
		printf ((is_hex ? "%x\n" : "%d\n"),
			libhal_device_get_property_int (hal_ctx, udi, key, &error));
		break;
	case LIBHAL_PROPERTY_TYPE_UINT64:
		if (is_verbose)
			printf ("Type is uint64 (shown in %s)\n",
				(is_hex ? "hexadecimal" : "decimal"));
		printf ((is_hex ? "%llx\n" : "%llu\n"),
			(long long unsigned int) libhal_device_get_property_uint64 (hal_ctx, udi, key, &error));
		break;
	case LIBHAL_PROPERTY_TYPE_DOUBLE:
		if (is_verbose)
			printf ("Type is double\n");
		printf ("%f\n",
			libhal_device_get_property_double (hal_ctx, udi, key, &error));
		break;
	case LIBHAL_PROPERTY_TYPE_BOOLEAN:
		if (is_verbose)
			printf ("Type is boolean\n");
		printf ("%s\n",
			libhal_device_get_property_bool (hal_ctx, udi, key, &error) ? "true" : "false");
		break;

	case LIBHAL_PROPERTY_TYPE_STRLIST:
	{
		unsigned int i;
		char **strlist;
		
		if ((strlist = libhal_device_get_property_strlist (hal_ctx, udi, key, &error)) != NULL) {
			
			for (i = 0; strlist[i] != 0; i++) {
				printf ("%s", strlist[i]);
				if (strlist[i+1] != NULL)
					printf (" ");
			}
		} 
		break;
	}
	default:
		printf ("Unknown type %d='%c'\n", type, type);
		return 1;
		break;
	}

	if (dbus_error_is_set (&error)) {
		fprintf (stderr, "error: %s: %s\n", error.name, error.message);
		dbus_error_free (&error);
		return 1;
	}


	return 0;
}
예제 #6
0
gboolean
check_libhal (const char *server_addr)
{
	pid_t child_pid;

	child_pid = fork ();
	if (child_pid == -1) {
		printf ("Cannot fork\n");
		exit (1);
	} else if (child_pid == 0) {
		DBusError error;
		DBusConnection *conn;
		LibHalContext *ctx;
		dbus_bool_t passed;

		printf ("server address='%s'\n", server_addr);

		dbus_error_init (&error);
		if ((conn = dbus_connection_open (server_addr, &error)) == NULL) {
			printf ("Error connecting to server: %s\n", error.message);
			goto fail;
		}

		dbus_connection_setup_with_g_main (conn, NULL);

		if ((ctx = libhal_ctx_new ()) == NULL) {
			printf ("Error getting libhal context\n");
			goto fail;
		}

		
		libhal_ctx_set_dbus_connection (ctx, conn);

		libhal_ctx_init (ctx, &error);

		if (dbus_error_is_set (&error)) {
			printf ("FAILED98: %s\n", error.message);			
			goto fail;
		}
		printf ("SUCCESS98\n");

		libhal_device_print (ctx, "/org/freedesktop/Hal/devices/testobj1", &error);


		if (dbus_error_is_set (&error)) {
			printf ("FAILED99: %s\n", error.message);			
			goto fail;
		}
		printf ("SUCCESS99\n");

		passed = FALSE;

		{
			char *val;
			
			val = libhal_device_get_property_string (ctx, "/org/freedesktop/Hal/devices/testobj1", "test.string", &error);

			if (val == NULL || strcmp (val, "fooooobar22") != 0 || dbus_error_is_set (&error)) {
				libhal_free_string (val);
				printf ("FAILED100\n");			
				goto fail;
			}
			printf ("SUCCESS100\n");
			libhal_free_string (val);
		}

		{
			char *val;
			val = libhal_device_get_property_string (ctx, "/org/freedesktop/Hal/devices/testobj1", "test.string2", &error);
			if (val == NULL || strcmp (val, "fooøةמ") != 0 || dbus_error_is_set (&error)) {
				libhal_free_string (val);
				printf ("FAILED101: %s\n", error.message);			
				goto fail;
			}
			libhal_free_string (val);
			printf ("SUCCESS101\n");
		}

		{
			dbus_bool_t b;
			b = libhal_device_get_property_bool (
			    ctx, "/org/freedesktop/Hal/devices/testobj1", 
			    "test.bool", &error);
			    
			if (!b || dbus_error_is_set (&error)) {
				printf ("FAILED102: %s, %i\n", error.message, b);			
				goto fail;
			}
			printf ("SUCCESS102\n");
		}

		{
			double val;
			double expected_val = 0.53434343;

			val = libhal_device_get_property_double (ctx, "/org/freedesktop/Hal/devices/testobj1", 
								 "test.double", &error);
			if ( memcmp (&val, &expected_val, sizeof (double)) != 0 || dbus_error_is_set (&error)) {
				printf ("FAILED103\n");
				goto fail;
			}
			printf ("SUCCESS103\n");
		}

		if (libhal_device_get_property_uint64 (
			    ctx, "/org/freedesktop/Hal/devices/testobj1", "test.uint64", &error) != 
		    ((((dbus_uint64_t)1)<<35) + 5) ||
		    dbus_error_is_set (&error)) {
			printf ("FAILED104: %s\n", error.message);			
			goto fail;
		}
		printf ("SUCCESS104\n");
		
		{
			char **val;
			val = libhal_device_get_property_strlist (ctx, "/org/freedesktop/Hal/devices/testobj1", "test.strlist", &error);
			if (val == NULL ||  dbus_error_is_set (&error)) {
				libhal_free_string_array (val);
				printf ("FAILED105: %s\n", error.message);			
				goto fail;
			}
			printf ("SUCCESS105\n");
			
			if (libhal_string_array_length (val) != 2) {
				libhal_free_string_array (val);
				printf ("FAILED106\n");			
				goto fail;
			}
			printf ("SUCCESS106\n");

			if (strcmp (val[0], "foostrlist2") != 0 ||
			    strcmp (val[1], "foostrlist3") != 0) {
				libhal_free_string_array (val);
				printf ("FAILED107\n");			
				goto fail;
			}
			printf ("SUCCESS107\n");

			libhal_free_string_array (val);
		}

		if (libhal_device_get_property_int (
			    ctx, "/org/freedesktop/Hal/devices/testobj1", "test.int", &error) != 42 ||
		    dbus_error_is_set (&error)) {
			printf ("FAILED108\n");			
			goto fail;
		}
		printf ("SUCCESS108\n");
	
		/* tests for libhal_psi */
		{
			int type;
			char *key;
			LibHalPropertySet *pset;
			LibHalPropertySetIterator it;
			unsigned int psi_num_passed;
			unsigned int psi_num_elems;

			if ((pset = libhal_device_get_all_properties (ctx, "/org/freedesktop/Hal/devices/testobj1", 
								      &error)) == NULL)
				return FALSE;
			printf ("SUCCESS110\n");

			psi_num_passed = 0;
			psi_num_elems = libhal_property_set_get_num_elems (pset);

			for (libhal_psi_init (&it, pset); libhal_psi_has_more (&it); libhal_psi_next (&it)) {
				type = libhal_psi_get_type (&it);
				key = libhal_psi_get_key (&it);

				switch (type) {
				case LIBHAL_PROPERTY_TYPE_STRING:
					if (strcmp (key, "info.udi") == 0) {
						if (strcmp (libhal_psi_get_string (&it), 
							    "/org/freedesktop/Hal/devices/testobj1") == 0) {
							psi_num_passed++;
						} else {
							printf ("fail on %s\n", key);
						}
					} else if (strcmp (key, "test.string") == 0) {
						if (strcmp (libhal_psi_get_string (&it), 
							    "fooooobar22") == 0) {
							psi_num_passed++;
						} else {
							printf ("fail on %s\n", key);
						}
					} else if (strcmp (key, "test.string2") == 0) {
						if (strcmp (libhal_psi_get_string (&it), 
							    "fooøةמ") == 0) {
							psi_num_passed++;
						} else {
							printf ("fail on %s\n", key);
						}
					}
					break;

				case LIBHAL_PROPERTY_TYPE_INT32:
					if (strcmp (key, "test.int") == 0) {
						if (libhal_psi_get_int (&it) == 42)
							psi_num_passed++;
						else
							printf ("fail on %s\n", key);
					}
					break;

				case LIBHAL_PROPERTY_TYPE_UINT64:
					if (strcmp (key, "test.uint64") == 0) {
						if (libhal_psi_get_uint64 (&it) == ((((dbus_uint64_t)1)<<35) + 5))
							psi_num_passed++;
						else
							printf ("fail on %s\n", key);
					}
					break;

				case LIBHAL_PROPERTY_TYPE_BOOLEAN:
					if (strcmp (key, "test.bool") == 0) {
						if (libhal_psi_get_bool (&it) == TRUE)
							psi_num_passed++;
						else
							printf ("fail on %s\n", key);
					}
					break;

				case LIBHAL_PROPERTY_TYPE_DOUBLE:
					if (strcmp (key, "test.double") == 0) {
						double val = 0.53434343;
						double val2;

						val2 = libhal_psi_get_double (&it);
						if (memcmp (&val, &val2, sizeof (double)) == 0)
							psi_num_passed++;
						else
							printf ("fail on %s\n", key);
					}
					break;

				case LIBHAL_PROPERTY_TYPE_STRLIST:
					if (strcmp (key, "test.strlist") == 0) {
						char **val;
					
						val = libhal_psi_get_strlist (&it);
						if (libhal_string_array_length (val) == 2 &&
						    strcmp (val[0], "foostrlist2") == 0 &&
						    strcmp (val[1], "foostrlist3") == 0 &&
						    val[2] == NULL)
							psi_num_passed++;
						else
							printf ("fail on %s\n", key);
					}
					break;

				default:
					printf ("    *** unknown type for key %s\n", key);
					break;
				}
			}
			libhal_free_property_set (pset);

			if (psi_num_passed != psi_num_elems) {
				printf ("FAILED111\n");			
				goto fail;
			}
			printf ("SUCCESS111\n");			


		} /* end libhal_test_psi */

	
		printf ("Passed all libhal tests\n");
		passed = TRUE;
		
	fail:
		if (dbus_error_is_set (&error))
			dbus_error_free (&error);
			
		send_tests_done (conn, passed);
		exit (1);

	} else {
		printf ("child pid=%d\n", child_pid);
	}
	return TRUE;
}
예제 #7
0
static void
device_added(LibHalContext *hal_ctx, const char *udi)
{
    char **props;
    /* Cleverly, these are currently all leaked. */
    char *path = NULL, *driver = NULL, *name = NULL, *xkb_rules = NULL;
    char *xkb_model = NULL, *xkb_layout = NULL, *xkb_variant = NULL;
    char **xkb_options = NULL;
    DBusError error;
    struct xserver_option *options = NULL;
    int type = TYPE_NONE;
    int i;
    DeviceIntPtr dev = NULL;

    dbus_error_init(&error);

    props = libhal_device_get_property_strlist(hal_ctx, udi,
                                               "info.capabilities", &error);
    if (!props) {
        DebugF("[config/hal] couldn't get capabilities for %s: %s (%s)\n",
               udi, error.name, error.message);
        goto out_error;
    }
    for (i = 0; props[i]; i++) {
        /* input.keys is the new, of which input.keyboard is a subset, but
         * input.keyboard is the old 'we have keys', so we have to keep it
         * around. */
        if (strcmp(props[i], "input.keys") == 0 ||
            strcmp(props[i], "input.keyboard") == 0)
            type |= TYPE_KEYS;
        if (strcmp(props[i], "input.mouse") == 0)
            type |= TYPE_POINTER;
    }
    libhal_free_string_array(props);

    if (!type)
        goto out_error;

    driver = get_prop_string(hal_ctx, udi, "input.x11_driver");
    path = get_prop_string(hal_ctx, udi, "input.device");
    if (!driver || !path) {
        DebugF("[config/hal] no driver or path specified for %s\n", udi);
        goto unwind;
    }
    name = get_prop_string(hal_ctx, udi, "info.product");
    if (!name)
        name = xstrdup("(unnamed)");

    if (type & TYPE_KEYS) {
        xkb_rules = get_prop_string(hal_ctx, udi, "input.xkb.rules");
        xkb_model = get_prop_string(hal_ctx, udi, "input.xkb.model");
        xkb_layout = get_prop_string(hal_ctx, udi, "input.xkb.layout");
        xkb_variant = get_prop_string(hal_ctx, udi, "input.xkb.variant");
        xkb_options = get_prop_string_array(hal_ctx, udi, "input.xkb.options");
    }

    options = xcalloc(sizeof(*options), 1);
    options->key = xstrdup("_source");
    options->value = xstrdup("server/hal");
    if (!options->key || !options->value) {
        ErrorF("[config] couldn't allocate first key/value pair\n");
        goto unwind;
    }

    add_option(&options, "path", path);
    add_option(&options, "driver", driver);
    add_option(&options, "name", name);
    add_option(&options, "hal_udi", udi);

    if (xkb_model)
        add_option(&options, "xkb_model", xkb_model);
    if (xkb_layout)
        add_option(&options, "xkb_layout", xkb_layout);
    if (xkb_variant)
        add_option(&options, "xkb_variant", xkb_variant);
#if 0
    if (xkb_options)
        add_option(&options, "xkb_options", xkb_options);
#endif

    /* Maemo-specific hack.  Ugh. */
    if (type & TYPE_KEYS)
        add_option(&options, "type", "keyboard");
    else
        add_option(&options, "type", "pointer");

    if (NewInputDeviceRequest(options, &dev) != Success) {
        DebugF("[config/hal] NewInputDeviceRequest failed\n");
        goto unwind;
    }

    dbus_error_free(&error);

    return;

unwind:
    if (path)
        xfree(path);
    if (driver)
        xfree(driver);
    if (name)
        xfree(name);
    if (xkb_rules)
        xfree(xkb_rules);
    if (xkb_model)
        xfree(xkb_model);
    if (xkb_layout)
        xfree(xkb_layout);
    if (xkb_options) {
        for (i = 0; xkb_options[i]; i++)
            xfree(xkb_options[i]);
        xfree(xkb_options);
    }

out_error:
    dbus_error_free(&error);

    return;
}
gboolean
rb_generic_player_is_mount_player (GMount *mount)
{
	gboolean result = FALSE;
#ifdef HAVE_HAL
	LibHalContext *ctx;

	ctx = get_hal_context ();
	if (ctx != NULL) {
		char *udi = get_hal_udi_for_player (ctx, mount);
		if (udi != NULL) {
			DBusError error;
			char **proplist;
			char *prop;

			rb_debug ("Checking udi %s", udi);
			/* check that it can be accessed as mass-storage */
			dbus_error_init (&error);
			proplist = libhal_device_get_property_strlist (ctx, udi, "portable_audio_player.access_method.protocols", &error);
			if (proplist != NULL && !dbus_error_is_set (&error)) {
				int i;
				for (i = 0; proplist[i] != NULL; i++) {
					rb_debug ("device access method: %s", proplist[i]);
					if (strcmp (proplist[i], "storage") == 0) {
						result = TRUE;
						break;
					}
				}

				libhal_free_string_array (proplist);
			}
			free_dbus_error ("checking device access method", &error);

			if (result == FALSE) {
				dbus_error_init (&error);
				prop = libhal_device_get_property_string (ctx, udi, "portable_audio_player.access_method", &error);
				if (prop != NULL && strcmp (prop, "storage") == 0 && !dbus_error_is_set (&error)) {
					/* the device has passed all tests, so it should be a usable player */
					result = TRUE;
				}

				libhal_free_string (prop);
				free_dbus_error ("checking device access method", &error);
			}

			if (result == FALSE) {
				rb_debug ("device cannot be accessed via storage");
			}

		} else {
			rb_debug ("device is not an audio player");
		}
		g_free (udi);
	}
	cleanup_hal_context (ctx);

#endif /* HAVE_HAL */

	/* treat as audio player if ".is_audio_player" exists in the root of the volume  */
	if (!result) {
		GFile *is_audio_player;
		is_audio_player = get_is_audio_player_file (mount);
		if (is_audio_player != NULL) {
			result = TRUE;
			g_object_unref (is_audio_player);
		}
	}

	return result;
}
static void
get_device_info (RBGenericPlayerSource *source)
{
	RBGenericPlayerSourcePrivate *priv = GENERIC_PLAYER_SOURCE_GET_PRIVATE (source);
	GMount *mount;
	GFile *is_audio_player;
	GError *error = NULL;
#ifdef HAVE_HAL
	LibHalContext *ctx;
#endif
	g_object_get (source, "mount", &mount, NULL);

#ifdef HAVE_HAL
	ctx = get_hal_context ();
	if (ctx != NULL) {
		char *udi;

		udi = get_hal_udi_for_player (ctx, mount);

		if (udi != NULL) {
			DBusError error;
			char *prop;
			char **proplist;
			int value;

			/* get audio folders */
			dbus_error_init (&error);
			proplist = libhal_device_get_property_strlist (ctx, udi, "portable_audio_player.audio_folders", &error);
			if (proplist) {
				if (!dbus_error_is_set (&error)) {
					priv->audio_folders = g_strdupv (proplist);
				}
				libhal_free_string_array (proplist);
			}
			free_dbus_error ("getting audio folder list", &error);

			/* get supported mime-types */
			dbus_error_init (&error);
			proplist = libhal_device_get_property_strlist (ctx, udi, "portable_audio_player.output_formats", &error);
			if (proplist) {
				if (!dbus_error_is_set (&error)) {
					priv->output_mime_types = g_strdupv (proplist);
				}
				libhal_free_string_array (proplist);
			}
			free_dbus_error ("getting supported mime-type list", &error);

			/* get playlist format */
			dbus_error_init (&error);
			proplist = libhal_device_get_property_strlist (ctx, udi, "portable_audio_player.playlist_format", &error);
			if (proplist) {
				if (!dbus_error_is_set (&error)) {
					set_playlist_formats (source, proplist);
				}
				libhal_free_string_array (proplist);
			}
			free_dbus_error ("getting playlist format", &error);

			/* get playlist path - in current hal-info packages, this is sometimes a string
			 * and sometimes a strlist, so try both. 
			 * http://bugs.freedesktop.org/show_bug.cgi?id=19961
			 */
			dbus_error_init (&error);
			proplist = libhal_device_get_property_strlist (ctx, udi, "portable_audio_player.playlist_path", &error);
			if (proplist && !dbus_error_is_set (&error)) {
				set_playlist_path (source, proplist[0]);
				libhal_free_string_array (proplist);
			}
			free_dbus_error ("getting playlist path (strlist)", &error);
			
			dbus_error_init (&error);
			prop = libhal_device_get_property_string (ctx, udi, "portable_audio_player.playlist_path", &error);
			if (prop && !dbus_error_is_set (&error)) {
				set_playlist_path (source, prop);
				libhal_free_string (prop);
			}
			free_dbus_error ("getting playlist path (string)", &error);

			/* get max folder depth */
			dbus_error_init (&error);
			value = libhal_device_get_property_int (ctx, udi, "portable_audio_player.folder_depth", &error);
			if (!dbus_error_is_set (&error)) {
				priv->folder_depth = value;
			}
			free_dbus_error ("getting max folder depth", &error);

			debug_device_info (source, mount, "HAL");
		} else {
			rb_debug ("no player info available (HAL doesn't recognise it as a player");
		}
		g_free (udi);
	}
	cleanup_hal_context (ctx);
#endif

	/* allow HAL info to be overridden with .is_audio_player file */
	is_audio_player = get_is_audio_player_file (mount);
	if (is_audio_player != NULL) {
		char *data = NULL;
		gsize data_size = 0;

		rb_debug ("reading .is_audio_player file");

		g_file_load_contents (is_audio_player, NULL, &data, &data_size, NULL, &error);
		if (error != NULL) {
			/* can we sensibly report this anywhere? */
			rb_debug ("error reading .is_audio_player file: %s", error->message);
			g_clear_error (&error);
		} else {
			GKeyFile *keyfile;
			GError *error = NULL;
			char *munged;
			gsize munged_size;
			const char *fake_group = "[x-rb-data]\n";
			char *group;

			/* prepend a group name to the file contents */
			munged_size = data_size + strlen (fake_group);
			munged = g_malloc0 (munged_size + 1);
			strcpy (munged, fake_group);
			memcpy (munged + strlen (fake_group), data, data_size);

			keyfile = g_key_file_new ();
			g_key_file_set_list_separator (keyfile, ',');
			if (g_key_file_load_from_data (keyfile, munged, munged_size, G_KEY_FILE_NONE, &error) == FALSE) {
				/* and this */
				rb_debug ("error loading .is_audio_player file: %s", error->message);
				g_error_free (error);
			} else {
				char *value;
				char **list;

				group = g_key_file_get_start_group (keyfile);
				
				list = g_key_file_get_string_list (keyfile, group, "audio_folders", NULL, NULL);
				if (list != NULL) {
					g_strfreev (priv->audio_folders);
					priv->audio_folders = list;
				}

				list = g_key_file_get_string_list (keyfile, group, "output_formats", NULL, NULL);
				if (list != NULL) {
					g_strfreev (priv->output_mime_types);
					priv->output_mime_types = list;
				}
				
				list = g_key_file_get_string_list (keyfile, group, "playlist_format", NULL, NULL);
				if (list != NULL) {
					set_playlist_formats (source, list);
					g_strfreev (list);
				}

				value = g_key_file_get_string (keyfile, group, "playlist_path", NULL);
				if (value != NULL) {
					set_playlist_path (source, value);
					g_free (value);
				}

				if (g_key_file_has_key (keyfile, group, "folder_depth", NULL)) {
					priv->folder_depth = g_key_file_get_integer (keyfile, group, "folder_depth", NULL);
				}
				g_free (group);
			}

			g_key_file_free (keyfile);
			g_free (munged);
			
			debug_device_info (source, mount, ".is_audio_player file");
		}
		g_free (data);

		g_object_unref (is_audio_player);
	} else {
		rb_debug ("no .is_audio_player file found on this device");
	}

	g_object_unref (mount);
}