/** * main: * @argc: Number of arguments given to program * @argv: Arguments given to program * * Returns: Return code * * Main entry point */ int main (int argc, char *argv[]) { dbus_bool_t rc = 0; char *udi = NULL; char *key = NULL; char *str_value = NULL; dbus_int32_t int_value = 0; dbus_uint64_t uint64_value = 0; double double_value = 0.0f; dbus_bool_t bool_value = TRUE; dbus_bool_t remove = FALSE; dbus_bool_t is_version = FALSE; int type = PROP_INVALID; DBusError error; dbus_bool_t direct = FALSE; 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}, {"int", 1, NULL, 0}, {"uint64", 1, NULL, 0}, {"string", 1, NULL, 0}, {"double", 1, NULL, 0}, {"bool", 1, NULL, 0}, {"strlist-pre", 1, NULL, 0}, {"strlist-post", 1, NULL, 0}, {"strlist-rem", 1, NULL, 0}, {"direct", 0, NULL, 0}, {"remove", 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, "key") == 0) { key = strdup (optarg); } else if (strcmp (opt, "string") == 0) { str_value = strdup (optarg); type = PROP_STRING; } else if (strcmp (opt, "int") == 0) { int_value = strtol (optarg, NULL, 0); type = PROP_INT; } else if (strcmp (opt, "uint64") == 0) { uint64_value = strtoull (optarg, NULL, 0); type = PROP_UINT64; } else if (strcmp (opt, "double") == 0) { double_value = (double) atof (optarg); type = PROP_DOUBLE; } else if (strcmp (opt, "bool") == 0) { if (strcmp (optarg, "true") == 0) bool_value = TRUE; else if (strcmp (optarg, "false") == 0) bool_value = FALSE; else { usage (argc, argv); return 1; } type = PROP_BOOL; } else if (strcmp (opt, "strlist-pre") == 0) { str_value = strdup (optarg); type = PROP_STRLIST_PRE; } else if (strcmp (opt, "strlist-post") == 0) { str_value = strdup (optarg); type = PROP_STRLIST_POST; } else if (strcmp (opt, "strlist-rem") == 0) { str_value = strdup (optarg); type = PROP_STRLIST_REM; } else if (strcmp (opt, "remove") == 0) { remove = TRUE; } else if (strcmp (opt, "direct") == 0) { direct = TRUE; } else if (strcmp (opt, "udi") == 0) { udi = strdup (optarg); } else if (strcmp (opt, "version") == 0) { is_version = TRUE; } break; default: usage (argc, argv); return 1; break; } } if (is_version) { printf ("hal-set-property " PACKAGE_VERSION "\n"); return 0; } /* must have at least one, but not neither or both */ if ((remove && type != PROP_INVALID) || ((!remove) && type == PROP_INVALID)) { usage (argc, argv); return 1; } fprintf (stderr, "\n"); dbus_error_init (&error); if (direct) { if ((hal_ctx = libhal_ctx_init_direct (&error)) == NULL) { fprintf (stderr, "error: libhal_ctx_init_direct\n"); LIBHAL_FREE_DBUS_ERROR (&error); return 1; } } else { 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); dbus_error_free (&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; } } if (remove) { rc = libhal_device_remove_property (hal_ctx, udi, key, &error); if (!rc) { fprintf (stderr, "error: libhal_device_remove_property: %s: %s\n", error.name, error.message); LIBHAL_FREE_DBUS_ERROR (&error); return 1; } } else { switch (type) { case PROP_STRING: rc = libhal_device_set_property_string (hal_ctx, udi, key, str_value, &error); break; case PROP_INT: rc = libhal_device_set_property_int (hal_ctx, udi, key, int_value, &error); break; case PROP_UINT64: rc = libhal_device_set_property_uint64 (hal_ctx, udi, key, uint64_value, &error); break; case PROP_DOUBLE: rc = libhal_device_set_property_double (hal_ctx, udi, key, double_value, &error); break; case PROP_BOOL: rc = libhal_device_set_property_bool (hal_ctx, udi, key, bool_value, &error); break; case PROP_STRLIST_PRE: rc = libhal_device_property_strlist_prepend (hal_ctx, udi, key, str_value, &error); break; case PROP_STRLIST_POST: rc = libhal_device_property_strlist_append (hal_ctx, udi, key, str_value, &error); break; case PROP_STRLIST_REM: rc = libhal_device_property_strlist_remove (hal_ctx, udi, key, str_value, &error); break; } if (!rc) { fprintf (stderr, "error: libhal_device_set_property: %s: %s\n", error.name, error.message); dbus_error_free (&error); return 1; } } return rc ? 0 : 1; }
/* Thanks to lmctl code. I'd LOVE, REALLY LOVE to see some docs though... */ static void check_battery (const char *hal_device_udi, PropertyCacheItem *pci) { struct usb_device *curr_device; usb_dev_handle *handle; char buf[80]; DBusError err; unsigned int addr; int is_dual = 0; int percentage = 0; if (pci == NULL) return; HAL_DEBUG (("CSR device: [%s]", hal_device_udi)); is_dual = pci->csr_is_dual; /* Which of subdevices to address */ HAL_DEBUG (("Is dual: %d", is_dual)); addr = is_dual? 1<<8 : 0; curr_device = find_device (pci); if (curr_device == NULL) { HAL_ERROR (("Device %s not found", hal_device_udi)); return; } handle = usb_open (curr_device); if (handle == NULL) { HAL_ERROR (("Could not open usb device")); return; } if (!usb_control_msg (handle, 0xc0, 0x09, 0x03|addr, 0x00|addr, buf, 8, TIMEOUT) != 8) { if ((P0 == 0x3b) && (P4 == 0)) { HAL_DEBUG (("Receiver busy, trying again later")); } else { int current_charge = P5 & 0x07; HAL_DEBUG (("Charge level: %d->%d", pci->current_charge, current_charge)); if (current_charge != pci->current_charge) { pci->current_charge = current_charge; dbus_error_init (&err); libhal_device_set_property_int (halctx, hal_device_udi, "battery.charge_level.current", current_charge, &err); LIBHAL_FREE_DBUS_ERROR (&err); if (current_charge != 0) { percentage = (100.0 / 7.0) * current_charge; libhal_device_set_property_int (halctx, hal_device_udi, "battery.charge_level.percentage", percentage, &err); } else { libhal_device_remove_property(halctx, hal_device_udi, "battery.charge_level.percentage", &err); } LIBHAL_FREE_DBUS_ERROR (&err); } } } else { perror ("Writing to USB device"); } usb_close (handle); }
static void battery_dynamic_update(LibHalContext *ctx, const char *udi, int fd) { int reporting_rate; int reporting_current; int reporting_lastfull; int design_voltage; int present_voltage; char *reporting_unit; int remaining_time; int remaining_percentage; gboolean charging; gboolean discharging; acpi_bst_t bst; LibHalChangeSet *cs; DBusError error; static int counter = 0; HAL_DEBUG(("battery_dynamic_update() enter")); bzero(&bst, sizeof (bst)); if (ioctl(fd, BATT_IOC_STATUS, &bst) < 0) { return; } charging = bst.bst_state & BATT_BST_CHARGING ? TRUE : FALSE; discharging = bst.bst_state & BATT_BST_DISCHARGING ? TRUE : FALSE; /* No need to continue if battery is essentially idle. */ if (counter && !charging && !discharging) { return; } dbus_error_init(&error); libhal_device_set_property_bool(ctx, udi, "battery.is_rechargeable", TRUE, &error); my_dbus_error_free(&error); if (libhal_device_property_exists(ctx, udi, "battery.charge_level.percentage", &error)) { remaining_percentage = libhal_device_get_property_int(ctx, udi, "battery.charge_level.percentage", &error); if ((remaining_percentage == 100) && charging) { charging = FALSE; } } libhal_device_set_property_bool(ctx, udi, "battery.rechargeable.is_charging", charging, &error); my_dbus_error_free(&error); libhal_device_set_property_bool(ctx, udi, "battery.rechargeable.is_discharging", discharging, &error); my_dbus_error_free(&error); reporting_current = bst.bst_rem_cap; libhal_device_set_property_int(ctx, udi, "battery.reporting.current", bst.bst_rem_cap, &error); my_dbus_error_free(&error); reporting_rate = bst.bst_rate; libhal_device_set_property_int(ctx, udi, "battery.reporting.rate", bst.bst_rate, &error); my_dbus_error_free(&error); present_voltage = bst.bst_voltage; libhal_device_set_property_int(ctx, udi, "battery.voltage.present", bst.bst_voltage, &error); /* get all the data we know */ my_dbus_error_free(&error); reporting_unit = libhal_device_get_property_string(ctx, udi, "battery.reporting.unit", &error); my_dbus_error_free(&error); reporting_lastfull = libhal_device_get_property_int(ctx, udi, "battery.reporting.last_full", &error); /* * Convert mAh to mWh since util_compute_time_remaining() works * for mWh. */ if (reporting_unit && strcmp(reporting_unit, "mAh") == 0) { my_dbus_error_free(&error); design_voltage = libhal_device_get_property_int(ctx, udi, "battery.voltage.design", &error); /* * If the present_voltage is inaccurate, set it to the * design_voltage. */ if (((present_voltage * 10) < design_voltage) || (present_voltage <= 0) || (present_voltage > design_voltage)) { present_voltage = design_voltage; } reporting_rate = (reporting_rate * present_voltage) / 1000; reporting_lastfull = (reporting_lastfull * present_voltage) / 1000; reporting_current = (reporting_current * present_voltage) / 1000; } /* Make sure the current charge does not exceed the full charge */ if (reporting_current > reporting_lastfull) { reporting_current = reporting_lastfull; } if (!charging && !discharging) { counter++; reporting_rate = 0; } if ((cs = libhal_device_new_changeset(udi)) == NULL) { HAL_DEBUG(("Cannot allocate changeset")); libhal_free_string(reporting_unit); my_dbus_error_free(&error); return; } libhal_changeset_set_property_int(cs, "battery.charge_level.rate", reporting_rate); libhal_changeset_set_property_int(cs, "battery.charge_level.last_full", reporting_lastfull); libhal_changeset_set_property_int(cs, "battery.charge_level.current", reporting_current); remaining_percentage = util_compute_percentage_charge(udi, reporting_current, reporting_lastfull); remaining_time = util_compute_time_remaining(udi, reporting_rate, reporting_current, reporting_lastfull, discharging, charging, 0); /* * Some batteries give bad remaining_time estimates relative to * the charge level. */ if (charging && ((remaining_time < 30) || ((remaining_time < 300) && (remaining_percentage < 95)) || (remaining_percentage > 97))) { remaining_time = util_compute_time_remaining(udi, reporting_rate, reporting_current, reporting_lastfull, discharging, charging, 1); } if (remaining_percentage > 0) { libhal_changeset_set_property_int(cs, "battery.charge_level.percentage", remaining_percentage); } else { my_dbus_error_free(&error); libhal_device_remove_property(ctx, udi, "battery.charge_level.percentage", &error); } if ((remaining_percentage == 100) && charging) { battery_last_full(cs, fd); } /* * remaining_percentage is more accurate so we handle cases * where the remaining_time cannot be correct. */ if ((!charging && !discharging) || ((remaining_percentage == 100) && !discharging)) { remaining_time = 0; } if (remaining_time < 0) { my_dbus_error_free(&error); libhal_device_remove_property(ctx, udi, "battery.remaining_time", &error); } else if (remaining_time >= 0) { libhal_changeset_set_property_int(cs, "battery.remaining_time", remaining_time); } my_dbus_error_free(&error); libhal_device_commit_changeset(ctx, cs, &error); libhal_device_free_changeset(cs); libhal_free_string(reporting_unit); my_dbus_error_free(&error); HAL_DEBUG(("battery_dynamic_update() exit")); }
static void battery_remove(LibHalContext *ctx, const char *udi) { DBusError error; HAL_DEBUG(("battery_remove() enter")); dbus_error_init(&error); libhal_device_remove_property(ctx, udi, "battery.remaining_time", &error); my_dbus_error_free(&error); libhal_device_remove_property(ctx, udi, "battery.charge_level.percentage", &error); my_dbus_error_free(&error); libhal_device_remove_property(ctx, udi, "battery.charge_level.rate", &error); my_dbus_error_free(&error); libhal_device_remove_property(ctx, udi, "battery.charge_level.last_full", &error); my_dbus_error_free(&error); libhal_device_remove_property(ctx, udi, "battery.charge_level.current", &error); my_dbus_error_free(&error); libhal_device_remove_property(ctx, udi, "battery.voltage.present", &error); my_dbus_error_free(&error); libhal_device_remove_property(ctx, udi, "battery.reporting.rate", &error); my_dbus_error_free(&error); libhal_device_remove_property(ctx, udi, "battery.reporting.current", &error); my_dbus_error_free(&error); libhal_device_remove_property(ctx, udi, "battery.rechargeable.is_discharging", &error); my_dbus_error_free(&error); libhal_device_remove_property(ctx, udi, "battery.rechargeable.is_charging", &error); my_dbus_error_free(&error); libhal_device_remove_property(ctx, udi, "battery.is_rechargeable", &error); my_dbus_error_free(&error); libhal_device_remove_property(ctx, udi, "battery.charge_level.unit", &error); my_dbus_error_free(&error); libhal_device_remove_property(ctx, udi, "battery.charge_level.granularity_2", &error); my_dbus_error_free(&error); libhal_device_remove_property(ctx, udi, "battery.charge_level.granularity_1", &error); my_dbus_error_free(&error); libhal_device_remove_property(ctx, udi, "battery.charge_level.low", &error); my_dbus_error_free(&error); libhal_device_remove_property(ctx, udi, "battery.charge_level.warning", &error); my_dbus_error_free(&error); libhal_device_remove_property(ctx, udi, "battery.charge_level.design", &error); my_dbus_error_free(&error); libhal_device_remove_property(ctx, udi, "battery.voltage.design", &error); my_dbus_error_free(&error); libhal_device_remove_property(ctx, udi, "battery.reporting.granularity_2", &error); my_dbus_error_free(&error); libhal_device_remove_property(ctx, udi, "battery.reporting.granularity_1", &error); my_dbus_error_free(&error); libhal_device_remove_property(ctx, udi, "battery.reporting.low", &error); my_dbus_error_free(&error); libhal_device_remove_property(ctx, udi, "battery.reporting.warning", &error); my_dbus_error_free(&error); libhal_device_remove_property(ctx, udi, "battery.reporting.design", &error); my_dbus_error_free(&error); libhal_device_remove_property(ctx, udi, "battery.reporting.last_full", &error); my_dbus_error_free(&error); libhal_device_remove_property(ctx, udi, "battery.reporting.unit", &error); my_dbus_error_free(&error); libhal_device_remove_property(ctx, udi, "battery.technology", &error); my_dbus_error_free(&error); libhal_device_remove_property(ctx, udi, "battery.reporting.technology", &error); my_dbus_error_free(&error); libhal_device_remove_property(ctx, udi, "battery.serial", &error); my_dbus_error_free(&error); libhal_device_remove_property(ctx, udi, "battery.model", &error); my_dbus_error_free(&error); libhal_device_remove_property(ctx, udi, "battery.vendor", &error); my_dbus_error_free(&error); HAL_DEBUG(("battery_remove() exit")); }
int add_properties(LibHalContext *hal_ctx, new_dev_t *nd, lh_prop_t *prop) { DBusError error; lh_prop_t *p; char *udi2 = NULL, *udi3 = NULL, **s; LibHalPropertyType old_type; dbus_error_init(&error); for(p = prop; p; p = p->next) { if (!strcmp(p->key, "udi") && p->type == LIBHAL_PROPERTY_TYPE_STRING) { udi2 = p->v.str_value; continue; } old_type = libhal_device_get_property_type(hal_ctx, nd->real_udi, p->key, &error); dbus_error_init(&error); if (old_type != LIBHAL_PROPERTY_TYPE_INVALID && ( p->type != old_type || p->type == LIBHAL_PROPERTY_TYPE_STRLIST)) { if (!libhal_device_remove_property(hal_ctx, nd->real_udi, p->key, &error)) { fprintf(stderr, "%s: %s\n", error.name, error.message); LIBHAL_FREE_DBUS_ERROR (&error); return 41; } } switch (p->type) { case LIBHAL_PROPERTY_TYPE_INVALID: break; case LIBHAL_PROPERTY_TYPE_BOOLEAN: if (!libhal_device_set_property_bool(hal_ctx, nd->real_udi, p->key, p->v.bool_value, &error)) { fprintf(stderr, "%s: %s\n", error.name, error.message); LIBHAL_FREE_DBUS_ERROR (&error); return 42; } break; case LIBHAL_PROPERTY_TYPE_INT32: if (!libhal_device_set_property_int(hal_ctx, nd->real_udi, p->key, p->v.int_value, &error)) { fprintf(stderr, "%s: %s\n", error.name, error.message); LIBHAL_FREE_DBUS_ERROR (&error); return 42; } break; case LIBHAL_PROPERTY_TYPE_UINT64: if (!libhal_device_set_property_uint64(hal_ctx, nd->real_udi, p->key, p->v.uint64_value, &error)) { fprintf(stderr, "%s: %s\n", error.name, error.message); LIBHAL_FREE_DBUS_ERROR (&error); return 42; } break; case LIBHAL_PROPERTY_TYPE_DOUBLE: if (!libhal_device_set_property_double(hal_ctx, nd->real_udi, p->key, p->v.double_value, &error)) { fprintf(stderr, "%s: %s\n", error.name, error.message); LIBHAL_FREE_DBUS_ERROR (&error); return 42; } break; case LIBHAL_PROPERTY_TYPE_STRING: if (!strcmp(p->key, "info.udi")) udi3 = p->v.str_value; if (!libhal_device_set_property_string(hal_ctx, nd->real_udi, p->key, p->v.str_value, &error)) { fprintf(stderr, "%s: %s\n", error.name, error.message); LIBHAL_FREE_DBUS_ERROR (&error); return 42; } break; case LIBHAL_PROPERTY_TYPE_STRLIST: for(s = p->v.strlist_value; *s; s++) { if (!libhal_device_property_strlist_append(hal_ctx, nd->real_udi, p->key, *s, &error)) { fprintf(stderr, "%s: %s\n", error.name, error.message); LIBHAL_FREE_DBUS_ERROR (&error); return 42; } } break; } } if (udi2) udi3 = NULL; if (udi3) udi2 = udi3; if (udi2 && !nd->udi) nd->udi = strdup(udi2); return 0; }