ESP8266 is reset while overwriting the existing database - reset

If the test program is started by deleting (resetting) the database file each time it is run, the procedures are working.
/*
This creates two empty databases, populates values, and retrieves them back
from the SPIFFS file system.
*/
#include <stdio.h>
#include <stdlib.h>
#include <sqlite3.h>
#include <vfs.h>
#include <SPI.h>
#include <FS.h>
extern "C" {
#include "user_interface.h"
}
#include <ESP8266WiFi.h>
sqlite3* db1;
void WiFiOff() {
wifi_station_disconnect();
wifi_set_opmode(NULL_MODE);
wifi_set_sleep_type(MODEM_SLEEP_T);
wifi_fpm_open();
wifi_fpm_do_sleep(0xFFFFFFF);
}
const char* data = "Callback function called";
static int callback(void* data, int argc, char** argv, char** azColName) {
int i;
Serial.printf("%s: ", (const char*)data);
for (i = 0; i < argc; i++) {
Serial.printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
}
Serial.printf("\n");
return 0;
}
int db_open(const char* filename, sqlite3** db) {
int rc = sqlite3_open(filename, db);
if (rc) {
Serial.printf("Can't open database: %s\n", sqlite3_errmsg(*db));
return rc;
}
else {
Serial.printf("Opened database successfully\n");
}
return rc;
}
char* zErrMsg = 0;
int db_exec(sqlite3* db, const char* sql) {
Serial.println(sql);
long start = micros();
int rc = sqlite3_exec(db, sql, callback, (void*)data, &zErrMsg);
if (rc != SQLITE_OK) {
Serial.printf("SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}
else {
Serial.printf("Operation done successfully\n");
}
Serial.print(F("Time taken:"));
Serial.println(micros() - start);
return rc;
}
void OpenDatabase();
void CreateTable();
void InsertValues();
void SelectValues();
void setup() {
Serial.begin(74880);
system_update_cpu_freq(SYS_CPU_160MHZ);
WiFiOff();
if (!SPIFFS.begin()) {
Serial.println("Failed to mount file system");
return;
}
// list SPIFFS contents
Dir dir = SPIFFS.openDir("/");
while (dir.next()) {
String fileName = dir.fileName();
size_t fileSize = dir.fileSize();
Serial.printf("FS File: %s, size: %ld\n", fileName.c_str(), (long)fileSize);
}
Serial.printf("\n");
// remove existing file
SPIFFS.remove("/test1.db");
sqlite3_initialize();
OpenDatabase();
CreateTable();
InsertValues();
SelectValues(); */
// list SPIFFS contents
dir = SPIFFS.openDir("/");
while (dir.next()) {
String fileName = dir.fileName();
size_t fileSize = dir.fileSize();
Serial.printf("FS File: %s, size: %ld\n", fileName.c_str(), (long)fileSize);
}
Serial.printf("\n");
}
void loop() {
}
void OpenDatabase() {
int rc;
// Open databases
File db_file_obj_1;
vfs_set_spiffs_file_obj(&db_file_obj_1);
if (db_open("/test1.db", &db1)) return;
}
void CreateTable() {
int rc;
// Create Table
rc = db_exec(db1, "CREATE TABLE IF NOT EXISTS test1 (id INTEGER, content);");
if (rc != SQLITE_OK) {
sqlite3_close(db1);
return;
}
}
void InsertValues() {
int rc;
// Insert Values
rc = db_exec(db1, "INSERT INTO test1 VALUES (1, 'Hello, Hurol from test1');");
if (rc != SQLITE_OK) {
sqlite3_close(db1);
return;
}
}
void SelectValues() {
int rc;
// Select Values
rc = db_exec(db1, "SELECT * FROM test1");
if (rc != SQLITE_OK) {
sqlite3_close(db1);
return;
}
}
}
deleting the existing database file ...
// remove existing file
SPIFFS.remove("/test1.db");
But when the INSERT or SELECT procedure is executed on the table created without deleting the existing database, ESP8266 is reset.
// remove existing file
// SPIFFS.remove("/test1.db");
(If deletion of the existing database file is canceled)
How can I get the best document about the reset problem when using ESP8266 and SQLite?
Can you please help in this matter? Thank you from now.

It looks like it has improved. Thank you very much.
hw_wdt_disable();
void hw_wdt_disable() {
((volatile uint32_t)0x60000900) &= ~(1); // Hardware WDT OFF
}

Related

why bpf ringbuf can not use in uprobe of libbpf?

Recently, I am trying to use bpf ringbuf in uprobe example of libbpf. But when running, error occurred which is "libbpf: load bpf program failed: Invalid argument". I have no idea why this happened. Could anyone help? Below is my test code.
Kernel space code: uprobe.bpf.c, define a rb struct, and use bpf_ringbuf_reserve in uprobe code block.
#include <linux/bpf.h>
#include <linux/ptrace.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
char LICENSE[] SEC("license") = "Dual BSD/GPL";
struct {
__uint(type, BPF_MAP_TYPE_RINGBUF);
__uint(max_entries, 256 * 1024);
} rb SEC(".maps");
SEC("uprobe/func")
int BPF_KPROBE(uprobe, int a, int b)
{
__u64* e = bpf_ringbuf_reserve(&rb, sizeof(__u64), 0);
if (!e)
return 0;
bpf_printk("UPROBE ENTRY: a = %d, b = %d\n", a, b);
return 0;
}
SEC("uretprobe/func")
int BPF_KRETPROBE(uretprobe, int ret)
{
bpf_printk("UPROBE EXIT: return = %d\n", ret);
return 0;
}
User space code: uprobe.c
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/resource.h>
#include <bpf/libbpf.h>
#include "uprobe.skel.h"
static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args)
{
return vfprintf(stderr, format, args);
}
static void bump_memlock_rlimit(void)
{
struct rlimit rlim_new = {
.rlim_cur = RLIM_INFINITY,
.rlim_max = RLIM_INFINITY,
};
if (setrlimit(RLIMIT_MEMLOCK, &rlim_new)) {
fprintf(stderr, "Failed to increase RLIMIT_MEMLOCK limit!\n");
exit(1);
}
}
/* Find process's base load address. We use /proc/self/maps for that,
* searching for the first executable (r-xp) memory mapping:
*
* 5574fd254000-5574fd258000 r-xp 00002000 fd:01 668759 /usr/bin/cat
* ^^^^^^^^^^^^ ^^^^^^^^
*
* Subtracting that region's offset (4th column) from its absolute start
* memory address (1st column) gives us the process's base load address.
*/
static long get_base_addr() {
size_t start, offset;
char buf[256];
FILE *f;
f = fopen("/proc/self/maps", "r");
if (!f)
return -errno;
while (fscanf(f, "%zx-%*x %s %zx %*[^\n]\n", &start, buf, &offset) == 3) {
if (strcmp(buf, "r-xp") == 0) {
fclose(f);
return start - offset;
}
}
fclose(f);
return -1;
}
static int handle_event(void *ctx, void *data, size_t data_sz)
{
return 0;
}
/* It's a global function to make sure compiler doesn't inline it. */
int uprobed_function(int a, int b)
{
return a + b;
}
int main(int argc, char **argv)
{
struct ring_buffer *rb = NULL;
struct uprobe_bpf *skel;
long base_addr, uprobe_offset;
int err, i;
/* Set up libbpf errors and debug info callback */
libbpf_set_print(libbpf_print_fn);
/* Bump RLIMIT_MEMLOCK to allow BPF sub-system to do anything */
bump_memlock_rlimit();
/* Load and verify BPF application */
skel = uprobe_bpf__open_and_load();
if (!skel) {
fprintf(stderr, "Failed to open and load BPF skeleton\n");
return 1;
}
base_addr = get_base_addr();
if (base_addr < 0) {
fprintf(stderr, "Failed to determine process's load address\n");
err = base_addr;
goto cleanup;
}
/* uprobe/uretprobe expects relative offset of the function to attach
* to. This offset is relateve to the process's base load address. So
* easy way to do this is to take an absolute address of the desired
* function and substract base load address from it. If we were to
* parse ELF to calculate this function, we'd need to add .text
* section offset and function's offset within .text ELF section.
*/
uprobe_offset = (long)&uprobed_function - base_addr;
/* Attach tracepoint handler */
skel->links.uprobe = bpf_program__attach_uprobe(skel->progs.uprobe,
false /* not uretprobe */,
0 /* self pid */,
"/proc/self/exe",
uprobe_offset);
err = libbpf_get_error(skel->links.uprobe);
if (err) {
fprintf(stderr, "Failed to attach uprobe: %d\n", err);
goto cleanup;
}
/* we can also attach uprobe/uretprobe to any existing or future
* processes that use the same binary executable; to do that we need
* to specify -1 as PID, as we do here
*/
skel->links.uretprobe = bpf_program__attach_uprobe(skel->progs.uretprobe,
true /* uretprobe */,
-1 /* any pid */,
"/proc/self/exe",
uprobe_offset);
err = libbpf_get_error(skel->links.uretprobe);
if (err) {
fprintf(stderr, "Failed to attach uprobe: %d\n", err);
goto cleanup;
}
/* Set up ring buffer polling */
rb = ring_buffer__new(bpf_map__fd(skel->maps.rb), handle_event, NULL, NULL);
if (!rb) {
err = -1;
fprintf(stderr, "Failed to create ring buffer\n");
goto cleanup;
}
printf("Successfully started! Please run `sudo cat /sys/kernel/debug/tracing/trace_pipe` "
"to see output of the BPF programs.\n");
for (i = 0; ; i++) {
err = ring_buffer__poll(rb, 100 /* timeout, ms */);
/* trigger our BPF programs */
fprintf(stderr, ".");
uprobed_function(i, i + 1);
sleep(1);
}
cleanup:
ring_buffer__free(rb);
uprobe_bpf__destroy(skel);
return -err;
}

WL_SHM_FORMAT_ARGB8888 not fully transparent if color bit was set

I am learning Wayland client programming and now I'm trying to make transparent surface.
I created a buffer and paint each pixels to shared memory. I am using WL_SHM_FORMAT_ARGB8888 format but it is not working as I expected.
As I understand, 0x00ff0000 means 255 red, 0 green, 0 blue and 0 alpha so the pixel should not shown. But it shows semi-transparent red surface to me.
Below is entire source code working on Weston compositor.
// main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wayland-client.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <errno.h>
#include <unistd.h>
#include "xdg-shell.h"
struct wl_display *display = NULL;
struct wl_compositor *compositor = NULL;
struct wl_surface *surface;
struct zxdg_shell_v6 *xdg_shell = NULL;
struct zxdg_surface_v6 *xdg_surface;
struct zxdg_toplevel_v6 *xdg_toplevel;
struct wl_shm *shm;
struct wl_buffer *buffer;
void *shm_data;
int WIDTH = 480;
int HEIGHT = 360;
//===============
// Xdg
//===============
static void xdg_shell_ping_handler(void *data, struct zxdg_shell_v6 *xdg_shell,
uint32_t serial)
{
zxdg_shell_v6_pong(xdg_shell, serial);
printf("ping pong!\n");
}
static const struct zxdg_shell_v6_listener xdg_shell_listener = {
.ping = xdg_shell_ping_handler,
};
static void xdg_toplevel_configure_handler(void *data,
struct zxdg_toplevel_v6 *xdg_toplevel, int32_t width, int32_t height,
struct wl_array *states)
{
printf("Configure: %dx%d\n", width, height);
}
static void xdg_toplevel_close_handler(void *data,
struct zxdg_toplevel_v6 *xdg_toplevel)
{
printf("Close\n");
}
static const struct zxdg_toplevel_v6_listener xdg_toplevel_listener = {
.configure = xdg_toplevel_configure_handler,
.close = xdg_toplevel_close_handler,
};
static void xdg_surface_configure_handler(void *data,
struct zxdg_surface_v6 *xdg_surface, uint32_t serial)
{
fprintf(stderr, "xdg_surface_configure_handler().\n");
zxdg_surface_v6_ack_configure(xdg_surface, serial);
}
static const struct zxdg_surface_v6_listener xdg_surface_listener = {
.configure = xdg_surface_configure_handler,
};
//=================
// File system
//=================
static int set_cloexec_or_close(int fd)
{
long flags;
if (fd == -1) {
return -1;
}
flags = fcntl(fd, F_GETFD);
if (flags == -1)
goto err;
if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1)
goto err;
return fd;
err:
close(fd);
return -1;
}
static int create_tmpfile_cloexec(char *tmpname)
{
int fd;
#ifdef HAVE_MKOSTEMP
fd= mkostemp(tmpname, O_CLOEXEC);
if (fd >= 0) {
unlink(tmpname);
}
#else
fd = mkstemp(tmpname);
if (fd >= 0) {
fd = set_cloexec_or_close(fd);
unlink(tmpname);
}
#endif
return fd;
}
int os_create_anonymous_file(off_t size)
{
static const char template[] = "/blusher-shared-XXXXXX";
const char *path;
char *name;
int fd;
path = getenv("XDG_RUNTIME_DIR");
if (!path) {
errno = ENOENT;
return -1;
}
name = malloc(strlen(path) + sizeof(template));
if (!name) {
return -1;
}
strcpy(name, path);
strcat(name, template);
fd = create_tmpfile_cloexec(name);
free(name);
if (fd < 0) {
return -1;
}
if (ftruncate(fd, size) < 0) {
close(fd);
return -1;
}
return fd;
}
//==============
// Painting
//==============
static void paint_pixels()
{
uint32_t *pixel = shm_data;
fprintf(stderr, "Painting pixels.\n");
for (int n = 0; n < WIDTH * HEIGHT; ++n) {
if (n > 1100 && n < 1200) {
pixel[n] = 0xffff0000; // please ignore this
} else {
pixel[n] = 0x00ff0000;
}
}
}
static struct wl_buffer* create_buffer()
{
struct wl_shm_pool *pool;
int stride = WIDTH * 4; // 4 bytes per pixel
int size = stride * HEIGHT;
int fd;
struct wl_buffer *buff;
fd = os_create_anonymous_file(size);
if (fd < 0) {
fprintf(stderr, "Creating a buffer file for %d B filed: %m\n",
size);
exit(1);
}
shm_data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (shm_data == MAP_FAILED) {
fprintf(stderr, "mmap filed: %m\n");
close(fd);
exit(1);
}
pool = wl_shm_create_pool(shm, fd, size);
buff = wl_shm_pool_create_buffer(
pool,
0,
WIDTH,
HEIGHT,
stride,
WL_SHM_FORMAT_ARGB8888
);
wl_shm_pool_destroy(pool);
return buff;
}
static void create_window()
{
buffer = create_buffer();
wl_surface_attach(surface, buffer, 0, 0);
// wl_surface_damage(surface, 0, 0, WIDTH, HEIGHT);
wl_surface_commit(surface);
}
static void shm_format(void *data, struct wl_shm *wl_shm, uint32_t format)
{
// struct display *d = data;
// d->formats |= (1 << format);
fprintf(stderr, "Format %d\n", format);
}
struct wl_shm_listener shm_listener = {
shm_format,
};
//==============
// Global
//==============
static void global_registry_handler(void *data, struct wl_registry *registry,
uint32_t id, const char *interface, uint32_t version)
{
if (strcmp(interface, "wl_compositor") == 0) {
fprintf(stderr, "Interface is <wl_compositor>.\n");
compositor = wl_registry_bind(
registry,
id,
&wl_compositor_interface,
version
);
} else if (strcmp(interface, "zxdg_shell_v6") == 0) {
fprintf(stderr, "Interface is <zxdg_shell_v6>.\n");
xdg_shell = wl_registry_bind(registry, id, &zxdg_shell_v6_interface, 1);
} else if (strcmp(interface, "wl_shm") == 0) {
fprintf(stderr, "Interface is <wl_shm>.\n");
shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
wl_shm_add_listener(shm, &shm_listener, NULL);
} else {
// printf("(%d) Got a registry event for <%s> id <%d>\n",
// version, interface, id);
}
}
static void global_registry_remover(void *data, struct wl_registry *registry,
uint32_t id)
{
printf("Got a registry losing event for <%d>\n", id);
}
static const struct wl_registry_listener registry_listener = {
global_registry_handler,
global_registry_remover
};
//==============
// Main
//==============
int main(int argc, char *argv[])
{
(void)argc;
(void)argv;
display = wl_display_connect(NULL);
if (display == NULL) {
fprintf(stderr, "Can't connect to display.\n");
exit(1);
}
printf("Connected to display.\n");
struct wl_registry *registry = wl_display_get_registry(display);
wl_registry_add_listener(registry, &registry_listener, NULL);
wl_display_dispatch(display);
// wl_display_roundtrip(display);
// Check compositor.
fprintf(stderr, " - Checking compositor...\n");
if (compositor == NULL) {
fprintf(stderr, "Can't find compositor.\n");
exit(1);
}
// Check surface.
fprintf(stderr, " - Checking surface...\n");
surface = wl_compositor_create_surface(compositor);
if (surface == NULL) {
fprintf(stderr, "Can't create surface.\n");
exit(1);
}
if (xdg_shell == NULL) {
fprintf(stderr, "Haven't got a Xdg shell.\n");
exit(1);
}
zxdg_shell_v6_add_listener(xdg_shell, &xdg_shell_listener, NULL);
// Check shell surface.
xdg_surface =
zxdg_shell_v6_get_xdg_surface(xdg_shell, surface);
zxdg_surface_v6_add_listener(xdg_surface, &xdg_surface_listener, NULL);
xdg_toplevel = zxdg_surface_v6_get_toplevel(xdg_surface);
zxdg_toplevel_v6_add_listener(xdg_toplevel, &xdg_toplevel_listener, NULL);
// Signal that the surface is ready to be configured.
wl_surface_commit(surface);
// Wait for the surface to be configured.
wl_display_roundtrip(display);
create_window();
paint_pixels();
// wl_surface_attach(surface, buffer, 0, 0);
// wl_surface_commit(surface);
while (wl_display_dispatch(display) != -1) {
;
}
wl_display_disconnect(display);
printf("Disconnected from display.\n");
return 0;
}
# Makefile
default:
wayland-scanner client-header /usr/share/wayland-protocols/unstable/xdg-shell/xdg-shell-unstable-v6.xml xdg-shell.h
wayland-scanner public-code /usr/share/wayland-protocols/unstable/xdg-shell/xdg-shell-unstable-v6.xml xdg-shell.c
gcc -lwayland-client -lwayland-egl -lEGL -lGLESv2 main.c xdg-shell.c
But when I set pixel to 0x00000000, then it is fully transparent.
And in some tests, subsurfaces are completely transparent even there are color bits set. I want to know what is prevent the transparent toplevel surface with color bits.
If your wayland compositor supports alpha-compositing-v1 protocol you can use it do what you want.
In short; get a reference to zwp_alpha_compositing_v1 struct in you registry handler then after creating your surface you set it like this:
struct zwp_blending_v1* blending = zwp_alpha_compositing_v1_get_blending(<YOUR_ZWP_ALPHA_COMPOSITING>, <YOUR_WL_SURFACE>);
zwp_blending_v1_set_blending(blending, ZWP_BLENDING_V1_BLENDING_EQUATION_STRAIGHT);
This is an equivalent to (src_alpha, one_minus_src_alpha) blending.

C++ class member variable resetting to 0

I'm trying to increment and decrement the index of a list of readings, however, everytime I run update(), m_notifIndex gets set back to zero. I'm sorry if this type of question has been asked before, but after looking for the answer for an hour, I gave up and went on to ask my first question here. Sorry for the bad formatting too, again, this is my first time posting.
Display.cpp
#include "display.h"
#include <time.h>
#include <unistd.h>
#include <iostream>
Display::Display(unsigned int width, unsigned int height, unsigned int num_sensors, std::string* sensors, const std::string& dir, Message* messages) {
m_notifIndex = 0;
}
void Display::update() {
if (m_showNotif) {
//when there are no more messages, show the notifications
while (!m_notifications->isEmpty()) {
//first draw the notification if there is a warning in the current index
if (m_notifications->sensors[m_notifIndex] != NULL) {
m_oled->clear(PAGE);
drawSensor();
m_oled->display();
sleep(1);
//keep updating the message and notif stack when there are no inputs
while (m_a->pinRead() == HIGH && m_right->pinRead() == HIGH && m_left->pinRead() == HIGH && m_b->pinRead() == HIGH) {
m_messages->updateMsgStack();
updateNotif();
if (!m_messages->isEmpty() || m_notifications->warnings[m_notifIndex])
return; //break away from the loop if a new message comes in
}
//listen in for inputs
if (m_right->pinRead() == LOW) {
//wait until the button is released
while (m_right->pinRead() == LOW) {}
if (m_notifIndex == m_num_sensors-1)
m_notifIndex = 0; //wrap around when at the end
else m_notifIndex++;
}
else if (m_left->pinRead() == LOW) {
while (m_left->pinRead() == LOW) {}
if (m_notifIndex == 0)
m_notifIndex = m_num_sensors-1; //wrap around when at the beginning
else m_notifIndex--;
}
else if (m_a->pinRead() == LOW) {
while (m_a->pinRead() == LOW) {}
m_showNotif = false;
return;
}
checkForPanic();
}
else { //when the current index has no warning
if (m_notifIndex == m_num_sensors-1)
m_notifIndex = 0; //wrap around when at the end
else m_notifIndex++;
}
}
}
}
void Display::updateNotif() {
std::string line;
for (unsigned int i = 0; i < sizeof(m_sensors)/sizeof(m_sensors[0]); i++) {
const char* filePath = (m_notifDir + m_sensors[i] + ".txt").c_str();
if (m_messages->exists(filePath)) {
usleep(10000);
try {
m_messages->m_incMsg.open(filePath);
while(std::getline(m_messages->m_incMsg, line)) {
m_notifications->addWarning (line, i);
}
m_messages->m_incMsg.close();
}
catch (std::ios_base::failure& e) {
std::cerr << e.what() << '\n' << std::endl;
}
}
else m_notifications->removeWarning (i); //delete the warning when the file doesnt exist
}
}
void Display::checkForPanic() {
if (m_b->pinRead() == LOW) {
time_t hold;
time(&hold);
while (m_b->pinRead() == LOW) {
if (time(NULL) > hold + 3) { //if the timer reaches 3 seconds
//m_messages->sendReply("Miner_Emergency");
return;
}
}
}
}
Display.h
#ifndef OLED_DISPLAY_H_
#define OLED_DISPLAY_H_
#include <sstream>
#include <string>
#include "image/image.h"
#include "oled/Edison_OLED.h"
#include "message.h"
#include "DataStructs/Notif.h"
#include "gpio/gpio.h"
#define SLEEPTIMEOUT 20
class Display {
public:
Display(unsigned int width, unsigned int height, unsigned int num_sensors, std::string* sensors, const std::string& dir, Message* messages);
void run();
~Display();
private:
edOLED* m_oled;
const unsigned int m_height, m_width;
Image* m_miner;
Image* m_checkin;
Image* m_reminder;
Image* m_blast;
Image* m_go_to;
Image* m_goto_zone;
bool m_isSleeping, m_showNotif;
time_t m_timer;
Message* m_messages;
std::string* m_sensors;
std::string m_notifDir;
NotifHandler* m_notifications;
unsigned int m_notifIndex;
const unsigned int m_num_sensors;
gpio* m_up;
gpio* m_down;
gpio* m_left;
gpio* m_right;
gpio* m_a;
gpio* m_b;
void drawImage(Image* image);
void update();
void drawMessage(MsgNode* message);
void drawTime();
void drawSensor();
void updateNotif();
void checkForPanic();
};
#endif //OLED_DISPLAY_H_

How can I compile HAL examples on Neatbeans?

I am trying to compile a HAL API example on Netbeans. Netbeans shows warning and error about some header files. But I am able to compile my sample codes using following command line:
gcc `pkg-config --libs --cflags dbus-1 hal hal-storage dbus-glib-1 glib-2.0` main.c HalDemos.c HalDemos.h -o HalDemos -lpthread
How can apply this command to my Netbeans project?
Here the codes which I am trying to compile:
/*
* File: HallDemos.h
* Author: olcay
*
* Created on December 25, 2011, 5:05 AM
*/
#ifndef HALLDEMOS_H
#define HALLDEMOS_H
#ifdef __cplusplus
extern "C" {
#endif
#include <hal/libhal.h>
#include <hal/libhal-storage.h>
#include <dbus/dbus.h>
#include <glib-1.2/glib.h>
//#include <dbus/dbus-glib-lowlevel.h>
#define HAL_DBUS_SERVICE "org.freedesktop.Hal"
#define HAL_ROOT_COMPUTER "/org/freedesktop/Hal/devices/computer"
#define HAL_DBUS_INTERFACE_POWER "org.freedesktop.Hal.Device.SystemPowerManagement"
static void handle_device_removed(LibHalContext *ctx, const char *udi);
static void handle_device_added(LibHalContext *ctx, const char *udi);
DBusConnection *connection;
DBusError error;
DBusMessage *mess;
DBusMessage *reply;
LibHalContext *ctx;
LibHalDrive *drive;
LibHalVolume *volume;
const char *udi;
int exit_code;
int initHal();
int getSystemInfo();
int getDeviceWithCapability(const char *capability);
void callbackLoop();
void listDeviceContent();
#ifdef __cplusplus
}
#endif
#endif /* HALLDEMOS_H */
#include "HalDemos.h"
#include <stdio.h>
static void handle_device_removed(LibHalContext *ctx, const char *udi) {
printf("Device with udi=%s is removed\n", udi);
}
static void handle_device_added(LibHalContext *ctx, const char *udi) {
dbus_bool_t is_storage;
is_storage = libhal_device_query_capability(ctx, udi, "storage", NULL);
if (is_storage) {
drive = libhal_drive_from_udi(ctx, udi);
volume = libhal_volume_from_udi(ctx, udi);
if (libhal_drive_is_hotpluggable(drive) || libhal_drive_uses_removable_media(drive)) {
printf("Storage device added %s model %s\n",
libhal_drive_get_device_file(drive),
libhal_drive_get_model(drive));
//printf("Mount point = %s\n", libhal_volume_get_mount_point(volume));
}
libhal_drive_free(drive);
}
//printf("Device with udi=%s is added\n", udi);
}
int initHal() {
udi = "/org/freedesktop/Hal/devices/computer";
dbus_error_init(&error);
connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
if (dbus_error_is_set(&error)) {
printf("Unable to connect to Dbus: %s\n", error.message);
dbus_error_free(&error);
return 1;
}
ctx = libhal_ctx_new();
if (!libhal_ctx_set_dbus_connection(ctx, connection)) {
printf("Error: %s\n", error.message);
dbus_error_free(&error);
return 1;
}
if (!libhal_ctx_init(ctx, &error)) {
printf("Hal context initializing failure %s\n", error.message);
return 1;
}
}
int getSystemInfo() {
char *kernel_version = libhal_device_get_property_string(ctx, udi, "system.kernel.version", &error);
if (dbus_error_is_set(&error)) {
printf("Error getting string property %s\n", error.message);
dbus_error_free(&error);
return 1;
}
char *power_management_type = libhal_device_get_property_string(ctx, udi, "power_management.type", &error);
if (dbus_error_is_set(&error)) {
printf("Error getting string property %s\n", error.message);
dbus_error_free(&error);
return 1;
}
dbus_bool_t can_hibernate = libhal_device_get_property_bool(ctx, udi, "power_management.can_hibernate", &error);
if (dbus_error_is_set(&error)) {
printf("Error getting bool property %s\n", error.message);
dbus_error_free(&error);
return 1;
}
printf("System information:\n");
printf("Kernel = %s\n", kernel_version);
printf("Power management type = %s\n", power_management_type);
printf("Hibernate = %s\n", can_hibernate ? "Supported" : "Not supported");
libhal_free_string(kernel_version);
libhal_free_string(power_management_type);
return 0;
}
int getDeviceWithCapability(const char* capability) {
int num_devices = 0;
char **udis = libhal_find_device_by_capability(ctx, capability, &num_devices, &error);
if (dbus_error_is_set(&error)) {
printf("Error getting bool property %s\n", error.message);
dbus_error_free(&error);
return 1;
}
if (num_devices == 0) {
printf("No device found with input capability!");
return 0;
}
int i;
printf("Devices with input capability:\n");
for (i = 0; udis[i]; i++) {
printf("%2d - udi = %s\n", i + 1, udis[i]);
/* Do something with it */
}
/* Free the string array */
libhal_free_string_array(udis);
}
void callbackLoop() {
GMainLoop *loop;
loop = (GMainLoop*) g_main_loop_new(NULL, FALSE);
dbus_connection_setup_with_g_main(connection, NULL);
libhal_ctx_set_device_added(ctx, handle_device_added);
libhal_ctx_set_device_removed(ctx, handle_device_removed);
g_main_loop_run(loop);
}
void listDeviceContent(){
}
UPDATE:
Writing the command I used with $$() and adding it to additional compiler settings solved my problem.
Go to your project properties -> Build -> C Compiler -> Additional Options
Put your compiler flags here between $$() like:
$$(pkg-config --libs --cflags dbus-1 hal hal-storage dbus-glib-1 glib-2.0)

Is there easy way to do macro to string map?

For example,in Windows,if I want to make the error message of gethostbyname meaningful,I would need to manually map the error code to message, as follows,
#include <stdio.h>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
int
main(void)
{
struct hostent *host;
WSAData wsaData;
int errcode;
if (WSAStartup(MAKEWORD(2, 2), &wsaData)) {
perror("WSAStartup failed");
exit(-1);
}
host = gethostbyname("www.google.com");
if (host != NULL) {
printf("the offical name of the host is: %s\n", host->h_name);
} else {
errcode = WSAGetLastError();
printf("the error code is %d\n", errcode);
if (errcode == WSAENETDOWN)
perror("network down");
else if (errcode == WSANOTINITIALISED)
perror("call WSAStartup before");
else if ...
perror("gethostbyname failed");
return -1;
}
return 0;
}
Is there easy way to do this?
thanks.
I think you codes is in the easy way already, check the error code and return the error message. If you just want to make your codes more elegant, you could use an array of custom struct like below.
struct ErrorInfo
{
int Code;
const char* Message;
};
ErrorInfo* errorMap =
{
{ WSAENETDOWN, "network down" },
{ WSANOTINITIALISED, "call WSAStartup before" },
};
const char* GetErrorMessage(int errorCode)
{
for(int i=0; i<sizeof(errorMap)/sizeof(ErrorInfo)); i++)
{
if(errorMap[i].Code == errorCode)
return errorMap[i].Message;
}
return "";
}