From: Nils Faerber Date: Sat, 13 Aug 2011 11:22:22 +0000 (+0200) Subject: Add GTK test client, rework API with callbacks, make library X-Git-Url: https://git.kernelconcepts.de/?p=metawatch.git;a=commitdiff_plain;h=36bbcbe1824acc18b9bc48426de62d862283dfc0;hp=59068bbd135c3d2ed046be5fd64850166ca04a5c Add GTK test client, rework API with callbacks, make library --- diff --git a/Makefile b/Makefile index d7bacfa..fa2d9e4 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ # prefix for installation and search path (like icons) PREFIX = /usr/local/ -CFLAGS = -DDEBUG -Wall -O2 $(CCFLAGS) `pkg-config --cflags glib-2.0` `pkg-config --cflags dbus-glib-1` `pkg-config --cflags dbus-1` +CFLAGS = -Wall -O2 $(CCFLAGS) `pkg-config --cflags glib-2.0` `pkg-config --cflags dbus-glib-1` `pkg-config --cflags dbus-1` #CFLAGS = -Wall -O2 $(CCFLAGS) LDFLAGS = `pkg-config --libs glib-2.0` `pkg-config --libs dbus-glib-1` `pkg-config --libs dbus-1` @@ -29,6 +29,8 @@ all: $(PRGNAME) $(PRGNAME): $(OBJS) $(CC) -o $@ $^ $(LDFLAGS) +libmetawatch.a: metawatch.o crc16ccitt.o mw_utility.o + ar -cvq libmetawatch.a metawatch.o crc16ccitt.o mw_utility.o clean: rm -f *.o *.d $(PRGNAME) diff --git a/gtk-gui/Makefile b/gtk-gui/Makefile new file mode 100644 index 0000000..5de16ab --- /dev/null +++ b/gtk-gui/Makefile @@ -0,0 +1,35 @@ +# Copyright (C) 2011 Nils Faerber + + $(pkg-config --libs --cflags glib-2.0) $(pkg-config --libs --cflags dbus-glib-1) $(pkg-config --libs --cflags dbus-1) + +# prefix for installation and search path (like icons) +PREFIX = /usr/local/ +CFLAGS = -DDEBUG -Wall -O2 -Wl,--export-dynamic $(CCFLAGS) -I.. `pkg-config --cflags glib-2.0` `pkg-config --cflags dbus-glib-1` `pkg-config --cflags dbus-1` `pkg-config --cflags gtk+-2.0` +#CFLAGS = -Wall -O2 $(CCFLAGS) + +LDFLAGS = `pkg-config --libs glib-2.0` `pkg-config --libs dbus-glib-1` `pkg-config --libs dbus-1` `pkg-config --libs gtk+-2.0` `pkg-config --libs gmodule-export-2.0` -L.. -lmetawatch + +PRGNAME = mw-client + +MEMBERS = mw-client + +# no need to change anything below this line +# ------------------------------------------ +.SUFFIXES: .d .c + +CFLAGS += -MD -DPREFIX=\"$(PREFIX)\" $(OPTIONS) +LDFLAGS += $(CLDFLAGS) + +SOURCES = $(patsubst %,%.c,$(MEMBERS)) +OBJS = $(patsubst %,%.o,$(MEMBERS)) +DEPS = $(patsubst %,%.d,$(MEMBERS)) + +all: $(PRGNAME) + +$(PRGNAME): $(OBJS) + $(CC) -o $@ $^ $(LDFLAGS) + +clean: + rm -f *.o *.d $(PRGNAME) + +-include $(DEPS) diff --git a/gtk-gui/mw-client.c b/gtk-gui/mw-client.c new file mode 100644 index 0000000..f2597ee --- /dev/null +++ b/gtk-gui/mw-client.c @@ -0,0 +1,395 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include + +typedef struct { + // GMainLoop *mloop; + GtkBuilder *builder; + mwdevice_t mwdevice; + unsigned char rcvbuf[128]; + int rcvbuf_pos; + int con_fd; /* console input fd */ + char cmdline[128]; + int cmdline_pos; + int bat_timeout_id; +} mwdata_t; + + +gboolean battery_level_get_timeout(gpointer user_data) +{ + mwdata_t *mdata = (mwdata_t *)user_data; + + mw_send_frame(&mdata->mwdevice, MW_READ_BATTERY_VOLTAGE_MSG, 0, NULL, 0); + return TRUE; +} + +void mw_get_battery_voltage_response_cb(mwdevice_t *mwdevice, unsigned short *voltage, unsigned char *pgood, unsigned char *charging, void *user_data) +{ + mwdata_t *mdata = (mwdata_t *)user_data; + gdouble volt = *voltage; + GtkAdjustment *batadjust; + GtkProgressBar *batbar; + gchar batstr[32]; + + batadjust = GTK_ADJUSTMENT(gtk_builder_get_object (mdata->builder, "bat_adjust")); + gtk_adjustment_set_value(batadjust, volt); + batbar = GTK_PROGRESS_BAR(gtk_builder_get_object (mdata->builder, "battery_status_bar")); + snprintf(batstr, 32, "%4.0fmV", volt); + gtk_progress_bar_set_text(batbar, batstr); +} + +void on_rtc_button_clicked (GtkButton *button, gpointer user_data) +{ + mwdata_t *mdata = (mwdata_t *)user_data; + + mw_send_frame(&mdata->mwdevice, MW_GET_REAL_TIME_CLOCK, 0, NULL, 0); +} + +void on_notify_button_clicked (GtkButton *button, gpointer user_data) +{ + mwdata_t *mdata = (mwdata_t *)user_data; + +} + +void bitmap_read(mwdevice_t *mwdevice, char *filename) +{ + int ffd, ret; + char rbuf[256]; + unsigned int width, height, i; +#ifdef DEBUG + unsigned int x, y; +#endif + unsigned int rowlength; + unsigned char *bmapbuf; + // unsigned char mw_buf[24]; + + ffd = open(filename, O_RDONLY); + if (ffd < 0) { + perror("open"); + return; + }; + ret = read(ffd, rbuf, 3); + if (rbuf[0] != 'P' || rbuf[1] != '4') { + fprintf(stderr, "not a PBM file\n"); + return; + } + memset(rbuf, 0, 256); + i = 0; + do { + ret = read(ffd, (rbuf+i), 1); + } while (!isspace(rbuf[i++])); + width = atoi(rbuf); + + memset(rbuf, 0, 256); + i = 0; + do { + ret = read(ffd, (rbuf+i), 1); + } while (!isspace(rbuf[i++])); + height = atoi(rbuf); + + rowlength = ((width / 8) + 1); + + bmapbuf = malloc(rowlength * height); + + ret = read(ffd, bmapbuf, rowlength * height); + close(ffd); + +#ifdef DEBUG + fprintf(stderr, "row length = %d bytes\n", rowlength); + fprintf(stderr, "bitmap resolution is %d x %d\n", width, height); + fprintf(stderr, "read %d of %d bytes\n", ret, rowlength * height); + fprintf(stderr, "\n"); + for (y=0; ybuilder, "main_win")); + dialog = gtk_file_chooser_dialog_new("Bitmap File", mwin, GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL); + if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { + gchar *filename; + filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); + /* send bitmap file */ + bitmap_read(&mdata->mwdevice, filename); + } + gtk_widget_destroy(dialog); +} + +void mw_get_real_time_clock_response_cb(mwdevice_t *mwdevice, struct tm *mw_tm, void *user_data) +{ + mwdata_t *mdata = (mwdata_t *)user_data; + GtkButton *rtc_button; + gchar label_str[256]; + + //g_print("watch RTC is %s\n", asctime(mw_tm)); + rtc_button = GTK_BUTTON (gtk_builder_get_object (mdata->builder, "rtc_button")); + snprintf(label_str, 256, "RTC\n%s", asctime(mw_tm)); + label_str[strlen(label_str)-1] = 0; + gtk_button_set_label(rtc_button, label_str); +} + +int open_socket(bdaddr_t *bdaddr, uint8_t channel) +{ + struct sockaddr_rc addr; + int sk, opt; + + sk = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); + if (sk < 0) { + fprintf(stderr, "Can't create socket: %s (%d)\n", + strerror(errno), errno); + return -1; + } + +/* + f = 1; + if (setsockopt(sk, SOL_BLUETOOTH, BT_FLUSHABLE, &f, sizeof(f)) < 0) { + fprintf(stderr, "Can't set flushable: %s (%d)\n", + strerror(errno), errno); + return -1; + } +*/ + memset(&addr, 0, sizeof(addr)); + addr.rc_family = AF_BLUETOOTH; + bacpy(&addr.rc_bdaddr, BDADDR_ANY); + + if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + fprintf(stderr, "Can't bind socket: %s (%d)\n", + strerror(errno), errno); + close(sk); + return -1; + } + + /* Set link mode */ + opt = 0; + opt |= RFCOMM_LM_MASTER; + opt |= RFCOMM_LM_AUTH; +/* + opt |= RFCOMM_LM_ENCRYPT; + opt |= RFCOMM_LM_SECURE; +*/ + if (opt && setsockopt(sk, SOL_RFCOMM, RFCOMM_LM, &opt, sizeof(opt)) < 0) { + fprintf(stderr, "Can't set RFCOMM link mode: %s (%d)", + strerror(errno), errno); + close(sk); + return -1; + } + + memset(&addr, 0, sizeof(addr)); + addr.rc_family = AF_BLUETOOTH; + bacpy(&addr.rc_bdaddr, bdaddr); + addr.rc_channel = channel; + + if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + fprintf(stderr, "Can't connect: %s (%d)\n", + strerror(errno), errno); + close(sk); + return -1; + } + + return sk; +} + +void baswap(bdaddr_t *dst, const bdaddr_t *src) +{ + register unsigned char *d = (unsigned char *) dst; + register const unsigned char *s = (const unsigned char *) src; + register int i; + + for (i = 0; i < 6; i++) + d[i] = s[5-i]; +} + +int bachk(const char *str) +{ + if (!str) + return -1; + + if (strlen(str) != 17) + return -1; + + while (*str) { + if (!isxdigit(*str++)) + return -1; + + if (!isxdigit(*str++)) + return -1; + + if (*str == 0) + break; + + if (*str++ != ':') + return -1; + } + + return 0; +} + +int str2ba(const char *str, bdaddr_t *ba) +{ + bdaddr_t b; + int i; + + if (bachk(str) < 0) { + memset(ba, 0, sizeof(*ba)); + return -1; + } + + for (i = 0; i < 6; i++, str += 3) + b.b[i] = strtol(str, NULL, 16); + + baswap(ba, &b); + + return 0; +} + +gboolean handle_mw_io(GIOChannel *mw_io, GIOCondition condition, gpointer udata) +{ + mwdata_t *mdata = (mwdata_t *)udata; + int rcvd; + int processed; + + rcvd = read(mdata->mwdevice.mw_fd, mdata->rcvbuf+mdata->rcvbuf_pos, 64); +#ifdef DEBUG + fprintf(stderr, "read %d bytes:\n", rcvd); +#endif + if (rcvd > 0) { +#ifdef DEBUG + dump_frame(mdata->rcvbuf, rcvd); +#endif + processed = decode_frame(&mdata->mwdevice, mdata->rcvbuf, rcvd); + if (processed > 0) { + mdata->rcvbuf_pos -= processed; + if (mdata->rcvbuf_pos > 0) + g_print("Warning: RCV buffer not yet empty\n"); + } else { + /* we should rather seek forward for a next potential frame start */ + mdata->rcvbuf_pos = 0; + } + } + + return TRUE; +} + +void +on_window_destroy (GtkObject *object, gpointer user_data) +{ + gtk_main_quit (); +} + + + +int +main (int argc, char *argv[]) +{ + GtkBuilder *builder; + GtkWidget *window; + GIOChannel *mw_io; + bdaddr_t btaddr; + int mw_fd; + struct termios tmwfd; + mwdata_t mdata; + + + if (argc != 2) { + fprintf(stderr, "Usage:\n\t%s \n", argv[0]); + return 1; + }; + + crc16ccitt_init(); + + if (str2ba(argv[1], &btaddr)) + return 1; + mw_fd = open_socket(&btaddr, 1); + if (mw_fd < 0) { + return 1; + } else { + fprintf(stderr, "connected to %s\n", argv[1]); + }; + + /* we have a connection, RFCOMM socket is on mw_fd */ + /* make the tty raw */ + tcgetattr(mw_fd, &tmwfd); + cfmakeraw(&tmwfd); + tmwfd.c_oflag |= ONLCR | OPOST; + tmwfd.c_lflag |= ISIG; + tcsetattr(mw_fd, TCSANOW, &tmwfd); + + mdata.mwdevice.mw_fd = mw_fd; + mdata.rcvbuf_pos = 0; + memset(mdata.rcvbuf, 0, 128); + + gtk_init (&argc, &argv); + + builder = gtk_builder_new (); + gtk_builder_add_from_file (builder, "mw-client.glade", NULL); + mdata.builder = builder; + window = GTK_WIDGET (gtk_builder_get_object (builder, "main_win")); + gtk_builder_connect_signals (builder, &mdata); + + //g_object_unref (G_OBJECT (builder)); + + gtk_widget_show (window); + + mw_io = g_io_channel_unix_new(mw_fd); + g_io_add_watch(mw_io, G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP, handle_mw_io, &mdata); + + mw_init(&mdata.mwdevice, mw_fd); + + mw_set_get_real_time_clock_response_cb(&mdata.mwdevice, mw_get_real_time_clock_response_cb, &mdata); + mw_set_get_battery_voltage_response_cb(&mdata.mwdevice, mw_get_battery_voltage_response_cb, &mdata); + + // mw_send_frame(&mdata.mwdevice, MW_READ_BATTERY_VOLTAGE_MSG, 0, NULL, 0); + + mdata.bat_timeout_id = g_timeout_add_seconds(10, battery_level_get_timeout, &mdata); + + gtk_main (); + + return 0; +} diff --git a/gtk-gui/mw-client.glade b/gtk-gui/mw-client.glade new file mode 100644 index 0000000..34a6559 --- /dev/null +++ b/gtk-gui/mw-client.glade @@ -0,0 +1,433 @@ + + + + + + 3500 + 4200 + 3700 + 1 + 10 + + + False + + + + + True + False + + + True + False + + + True + False + False + _Datei + True + + + True + False + + + gtk-new + True + False + False + True + True + + + + + gtk-open + True + False + False + True + True + + + + + gtk-save + True + False + False + True + True + + + + + gtk-save-as + True + False + False + True + True + + + + + True + False + False + + + + + gtk-quit + True + False + False + True + True + + + + + + + + + + True + False + False + _Bearbeiten + True + + + True + False + + + gtk-cut + True + False + False + True + True + + + + + gtk-copy + True + False + False + True + True + + + + + gtk-paste + True + False + False + True + True + + + + + gtk-delete + True + False + False + True + True + + + + + + + + + True + False + False + _Ansicht + True + + + + + True + False + False + _Hilfe + True + + + True + False + + + gtk-about + True + False + False + True + True + + + + + + + + + False + True + 0 + + + + + True + False + 3 + 3 + + + True + False + + + True + False + <b>F</b> + True + + + False + False + 0 + + + + + True + False + <b>E</b> + True + + + False + False + 1 + + + + + True + False + <b>D</b> + True + + + False + False + 2 + + + + + 1 + 2 + + + + + True + False + + + True + False + <b>A</b> + True + + + False + False + 0 + + + + + True + False + <b>B</b> + True + + + False + False + 1 + + + + + True + False + <b>C</b> + True + + + False + False + 2 + + + + + 2 + 3 + 1 + 2 + + + + + Notification + True + True + True + False + + + + 2 + 3 + + + + + Bitmap + True + True + True + False + + + + 1 + 2 + 2 + 3 + + + + + Vibration + True + True + True + False + + + + 2 + 3 + 2 + 3 + + + + + RTC + True + True + True + False + + + + 1 + 2 + + + + + + + + True + False + + + True + False + True + 0.28571428571428592 + Battery + bat_adjust + + + True + True + 0 + + + + + True + False + unknown + + + True + True + 1 + + + + + 2 + 3 + + + + + True + False + + + 1 + 2 + 1 + 2 + + + + + True + True + 1 + + + + + True + False + 2 + + + False + True + 2 + + + + + + diff --git a/metawatch.c b/metawatch.c index 348140a..08d5aca 100644 --- a/metawatch.c +++ b/metawatch.c @@ -51,6 +51,10 @@ const char *mw_status_string[] = { #define MW_FRAME_DELAY 0x00 +/* ---------------------------------------------------------------------- + * Debugging helpers + * ---------------------------------------------------------------------- */ + void dump_frame(unsigned char *frame, int len) { int i; @@ -61,7 +65,7 @@ void dump_frame(unsigned char *frame, int len) } -int mw_send_frame(int mw_fd, unsigned char msg_type, unsigned char options, unsigned char *data, unsigned char len) +int mw_send_frame(mwdevice_t *mwdevice, unsigned char msg_type, unsigned char options, unsigned char *data, unsigned char len) { unsigned short crc; unsigned char frame[64]; @@ -83,7 +87,7 @@ int mw_send_frame(int mw_fd, unsigned char msg_type, unsigned char options, unsi dump_frame(frame, tlen); #endif - while (((ret = write(mw_fd, frame, tlen)) >= 0) && (tlen > 0)) + while (((ret = write(mwdevice->mw_fd, frame, tlen)) >= 0) && (tlen > 0)) tlen -= ret; if (MW_FRAME_DELAY) @@ -101,7 +105,7 @@ int mw_send_frame(int mw_fd, unsigned char msg_type, unsigned char options, unsi * ---------------------------------------------------------------------- */ -void mw_set_rtc(int mw_fd, unsigned char clk1224, unsigned char date_fmt) +int mw_set_rtc(mwdevice_t *mwdevice, unsigned char clk1224, unsigned char date_fmt) { time_t mtime; struct tm mtm; @@ -123,10 +127,10 @@ void mw_set_rtc(int mw_fd, unsigned char clk1224, unsigned char date_fmt) data[8] = clk1224; data[9] = date_fmt; - mw_send_frame(mw_fd, MW_SET_REAL_TIME_CLOCK, 0, data, 10); + return mw_send_frame(mwdevice, MW_SET_REAL_TIME_CLOCK, 0, data, 10); } -void mw_set_vibrate_mode(int mw_fd, unsigned char enable, unsigned short on_time, unsigned short off_time, unsigned char cycles) +int mw_set_vibrate_mode(mwdevice_t *mwdevice, unsigned char enable, unsigned short on_time, unsigned short off_time, unsigned char cycles) { unsigned char mdata[7]; @@ -134,32 +138,35 @@ void mw_set_vibrate_mode(int mw_fd, unsigned char enable, unsigned short on_time *(unsigned short *)(mdata+1) = on_time; /* miliseconds */ *(unsigned short *)(mdata+3) = off_time; /* miliseconds */ mdata[5] = cycles; - mw_send_frame(mw_fd, MW_SET_VIBRATE_MODE, 0, mdata, 6); + + return mw_send_frame(mwdevice, MW_SET_VIBRATE_MODE, 0, mdata, 6); } -void mw_configure_watch_mode(int mw_fd, unsigned char mode, unsigned char save, unsigned char timeout, unsigned char invert) +int mw_configure_watch_mode(mwdevice_t *mwdevice, unsigned char mode, unsigned char save, unsigned char timeout, unsigned char invert) { unsigned char mdata[3]; mdata[0] = timeout; /* seconds */ mdata[1] = invert; /* 0=normal, 1=invert */ - mw_send_frame(mw_fd, MW_CONFIGURE_MODE, (mode & 0x0f) | ((save & 0x01) << 4), mdata, 2); + + return mw_send_frame(mwdevice, MW_CONFIGURE_MODE, (mode & 0x0f) | ((save & 0x01) << 4), mdata, 2); } -void mw_update_display(int mw_fd, unsigned char mode, unsigned char copy) +int mw_update_display(mwdevice_t *mwdevice, unsigned char mode, unsigned char copy) { - mw_send_frame(mw_fd, MW_UPDATE_DISPLAY, (mode & 0x0f) | ((copy & 0x01) << 4), NULL, 0); + return mw_send_frame(mwdevice, MW_UPDATE_DISPLAY, (mode & 0x0f) | ((copy & 0x01) << 4), NULL, 0); } -void mw_load_template(int mw_fd, unsigned char mode, unsigned char template_select) +int mw_load_template(mwdevice_t *mwdevice, unsigned char mode, unsigned char template_select) { - mw_send_frame(mw_fd, MW_LOAD_TEMPLATE, (mode & 0x0f), &template_select, 1); + return mw_send_frame(mwdevice, MW_LOAD_TEMPLATE, (mode & 0x0f), &template_select, 1); } /* * send line for screen-mode mode from *buffer to watch, starting at display row row_offset + * this is only for digital LCD watch */ -void mw_write_buffer(int mw_fd, +int mw_write_buffer(mwdevice_t *mwdevice, unsigned char mode, unsigned char numlines, /* number of lines, 0=two lines or 1=one line */ unsigned char row_offset, /* start at row_offset in display, e.g. lower part in idle @31 */ @@ -167,10 +174,13 @@ void mw_write_buffer(int mw_fd, { unsigned char mdata[32]; + if (mwdevice->devtype != MW_DEVICE_TYPE_DIGITAL && mwdevice->devtype != MW_DEVICE_TYPE_DEVB_DIGI) + return -1; + buflen = 12 * (buflen / 12); /* crop to 12 bytes */ if ((numlines == 0 && buflen < 12) || (numlines == 1 && buflen < 24)) { fprintf(stderr, "mw_write_buffer: bufferlen does not match number of lines\n"); - return; + return -1; }; memset(mdata, 0, 32); mdata[0] = row_offset; @@ -179,7 +189,8 @@ void mw_write_buffer(int mw_fd, mdata[13] = row_offset+1; memcpy((mdata+14), (buffer+12), 12); }; - mw_send_frame(mw_fd, MW_WRITE_BUFFER, (mode & 0x0f) | (((numlines & 0x01)<< 4) & 0x10), mdata, numlines ? 13 : 26); + + return mw_send_frame(mwdevice, MW_WRITE_BUFFER, (mode & 0x0f) | (((numlines & 0x01)<< 4) & 0x10), mdata, numlines ? 13 : 26); } /* @@ -198,7 +209,7 @@ void mw_write_buffer(int mw_fd, 0: Start index col 1..: data */ -void mw_write_oled_buffer(int mw_fd, +int mw_write_oled_buffer(mwdevice_t *mwdevice, unsigned char mode, /* idle or scroll */ unsigned char oled, /* which OLED */ unsigned char numcols, @@ -207,23 +218,27 @@ void mw_write_oled_buffer(int mw_fd, { unsigned char mdata[32]; int i; + + if (mwdevice->devtype != MW_DEVICE_TYPE_ANA_DIGI && mwdevice->devtype != MW_DEVICE_TYPE_DEVB_ANA_DIGI) + return -1; /* lower row first since display wil be updated after completion of upper row */ if (buflen > 80) { for (i=80; imw_get_real_time_clock_response_cb != NULL) + mwdevice->mw_get_real_time_clock_response_cb(mwdevice, &mtm, mwdevice->mw_grtcrsp_data); + + return 0; } -void mw_get_battery_voltage_response(int mw_fd, unsigned char *batrsp, int len) +void mw_set_get_real_time_clock_response_cb(mwdevice_t *mwdevice, void (*mw_get_real_time_clock_response_cb) (mwdevice_t *mwdevice, struct tm *mw_tm, void *user_data), void *user_data) +{ + if (mw_get_real_time_clock_response_cb != NULL) + mwdevice->mw_get_real_time_clock_response_cb = mw_get_real_time_clock_response_cb; + if (user_data != NULL) + mwdevice->mw_grtcrsp_data = user_data; +} + + +int mw_get_battery_voltage_response(mwdevice_t *mwdevice, unsigned char *batrsp, int len) { unsigned short voltage = *(unsigned short *)batrsp; unsigned char power_good = batrsp[2]; unsigned char bat_charging = batrsp[3]; - fprintf(stderr, "battery is at %dV, %s and %s\n", voltage, power_good ? "power is good" : "power fault", bat_charging ? "charging" : "not charging"); +#ifdef DEBUG + fprintf(stderr, "battery is at %dmV, %s and %s\n", voltage, power_good ? "power is good" : "power fault", bat_charging ? "charging" : "not charging"); +#endif + + if (mwdevice->mw_get_battery_voltage_response_cb != NULL) + mwdevice->mw_get_battery_voltage_response_cb(mwdevice, &voltage, &power_good, &bat_charging, mwdevice->mw_gbatvrsp_data); + + return 0; +} + +void mw_set_get_battery_voltage_response_cb(mwdevice_t *mwdevice, void (*mw_get_battery_voltage_response_cb) (mwdevice_t *mwdevice, unsigned short *voltage, unsigned char *pgood, unsigned char *charging, void *user_data), void *user_data) +{ + if (mw_get_battery_voltage_response_cb != NULL) + mwdevice->mw_get_battery_voltage_response_cb = mw_get_battery_voltage_response_cb; + if (user_data != NULL) + mwdevice->mw_gbatvrsp_data = user_data; } -void mw_read_button_config_response(int mw_fd, unsigned char *btnrsp, int len) +int mw_read_button_config_response(mwdevice_t *mwdevice, unsigned char *btnrsp, int len) { +#ifdef DEBUG fprintf(stderr, "read button config response\n"); fprintf(stderr, "screen mode : 0x%02x\n", btnrsp[0]); fprintf(stderr, "button index : 0x%02x\n", btnrsp[1]); @@ -308,22 +356,63 @@ void mw_read_button_config_response(int mw_fd, unsigned char *btnrsp, int len) fprintf(stderr, ")\n"); fprintf(stderr, "callback msg type: 0x%02x\n", btnrsp[3]); fprintf(stderr, "callback msg opts: 0x%02d\n", btnrsp[4]); +#endif + + return 0; } -void mw_read_light_sensor_response(int mw_fd, unsigned char *lightrsp, int len) +void mw_set_read_button_config_response_cb(mwdevice_t *mwdevice, void (*mw_read_button_config_response_cb) (mwdevice_t *mwdevice, void *user_data), void *user_data) +{ + if (mw_read_button_config_response_cb != NULL) + mwdevice->mw_read_button_config_response_cb = mw_read_button_config_response_cb; + if (user_data != NULL) + mwdevice->mw_rbtncnfrsp_data = user_data; +} + +int mw_read_light_sensor_response(mwdevice_t *mwdevice, unsigned char *lightrsp, int len) { unsigned char power_good = lightrsp[0]; unsigned char bat_charging = lightrsp[1]; - unsigned short voltage = *(unsigned short *)(lightrsp+2); + unsigned short light_level = *(unsigned short *)(lightrsp+2); + +#ifdef DEBUG + fprintf(stderr, "light sensor is at %d, power stat: %s and %s\n", light_level, power_good ? "power is good" : "power fault", bat_charging ? "charging" : "not charging"); +#endif + + if (mwdevice->mw_read_light_sensor_response_cb != NULL) + mwdevice->mw_read_light_sensor_response_cb(mwdevice, &light_level, mwdevice->mw_rlsrsp_data); - fprintf(stderr, "light sensor is at %d, power stat: %s and %s\n", voltage, power_good ? "power is good" : "power fault", bat_charging ? "charging" : "not charging"); + return 0; } -void mw_status_change_event(int mw_fd, unsigned char option, unsigned char *statrsp, int len) +void mw_set_read_light_sensor_response_cb(mwdevice_t *mwdevice, void (*mw_read_light_sensor_response_cb) (mwdevice_t *mwdevice, unsigned short *light_level, void *user_data), void *user_data) { + if (mw_read_light_sensor_response_cb != NULL) + mwdevice->mw_read_light_sensor_response_cb = mw_read_light_sensor_response_cb; + if (user_data != NULL) + mwdevice->mw_rlsrsp_data = user_data; +} + +int mw_status_change_event(mwdevice_t *mwdevice, unsigned char option, unsigned char *statrsp, int len) +{ + unsigned char mode = (option & 0x0f); + unsigned char status = statrsp[0]; #ifdef DEBUG fprintf(stderr, "Status change event for mode %s: %s\n", mw_screen_mode_names[option&0x0f], mw_status_string[statrsp[0]]); #endif + + if (mwdevice->mw_status_change_event_cb != NULL) + mwdevice->mw_status_change_event_cb(mwdevice, &mode, &status, mwdevice->mw_stchev_data); + + return 0; +} + +void mw_set_status_change_event_cb(mwdevice_t *mwdevice, void (*mw_status_change_event_cb) (mwdevice_t *mwdevice, unsigned char *scrmode, unsigned char *status, void *user_data), void *user_data) +{ + if (mw_status_change_event_cb != NULL) + mwdevice->mw_status_change_event_cb = mw_status_change_event_cb; + if (user_data != NULL) + mwdevice->mw_stchev_data = user_data; } @@ -331,8 +420,7 @@ void mw_status_change_event(int mw_fd, unsigned char option, unsigned char *stat * Protocol handling * ---------------------------------------------------------------------- */ - -int decode_frame(int mw_fd, unsigned char *buf, int len) +int decode_frame(mwdevice_t *mwdevice, unsigned char *buf, int len) { unsigned short crc; unsigned char msglen; @@ -345,7 +433,7 @@ int decode_frame(int mw_fd, unsigned char *buf, int len) crc = *(unsigned short *)(buf+len-2); if (crc != crc16ccitt(buf, len-2)) { fprintf(stderr, "decode frame CRC error\n"); - return 1; + return -1; } #ifdef DEBUG else @@ -353,7 +441,7 @@ int decode_frame(int mw_fd, unsigned char *buf, int len) #endif if (buf[0] != MW_SOF) { fprintf(stderr, "decode frame SOF not found\n"); - return 1; + return -1; } #ifdef DEBUG else @@ -389,25 +477,26 @@ int decode_frame(int mw_fd, unsigned char *buf, int len) fprintf(stderr, "unknown %d\n", msgdata[0]); break; }; + mwdevice->devtype = msgdata[0]; break; case MW_GET_INFORMATION_STRING_RSP: msgdata[len-2] = 0; fprintf(stderr, "Got info string '%s'\n", msgdata); break; case MW_GET_REAL_TIME_CLOCK_RSP: - mw_get_real_time_clock_response(mw_fd, msgdata, msgdatalen); + mw_get_real_time_clock_response(mwdevice, msgdata, msgdatalen); break; case MW_READ_BATTERY_VOLTAGE_RSP: - mw_get_battery_voltage_response(mw_fd, msgdata, msgdatalen); + mw_get_battery_voltage_response(mwdevice, msgdata, msgdatalen); break; case MW_READ_LIGHT_SENSOR_RSP: - mw_read_light_sensor_response(mw_fd, msgdata, msgdatalen); + mw_read_light_sensor_response(mwdevice, msgdata, msgdatalen); break; case MW_LOW_BATTERY_WARNING_MSG: fprintf(stderr, "Watch battery low, please connect charger\n"); break; case MW_READ_BUTTON_CONFIG_RSP: - mw_read_button_config_response(mw_fd, msgdata, msgdatalen); + mw_read_button_config_response(mwdevice, msgdata, msgdatalen); break; case MW_BUTTON_EVENT_MESSAGE: fprintf(stderr, "Button event message\n"); @@ -416,21 +505,62 @@ int decode_frame(int mw_fd, unsigned char *buf, int len) fprintf(stderr, "Watch battery extremely low - radio will turn off\n"); break; case MW_STATUS_CHANGE_EVENT: - mw_status_change_event(mw_fd, msgopt, msgdata, msgdatalen); + mw_status_change_event(mwdevice, msgopt, msgdata, msgdatalen); break; default: fprintf(stderr, "Unkown msgtype 0x%02x\n", msgtype); break; }; - return 0; + return msglen; } +/* ---------------------------------------------------------------------- + * General code usage + * ---------------------------------------------------------------------- */ + +int mw_init(mwdevice_t *mwdevice, int mw_fd) +{ + memset(mwdevice, 0, sizeof(mwdevice_t)); + mwdevice->mw_fd = mw_fd; + + /* figure out which device we run with */ + mw_send_frame(mwdevice, MW_GET_DEVICE_TYPE, 0, NULL, 0); + + return 0; +} + /* ---------------------------------------------------------------------- * Convenience functions not strictly part of the protocol * ---------------------------------------------------------------------- */ +int mw_get_resolution(mwdevice_t *mwdevice, unsigned int *width, unsigned int *height) +{ + if (width == NULL || height == NULL) + return -1; + + switch (mwdevice->devtype) { + case MW_DEVICE_TYPE_RESERVED: + return -1; + case MW_DEVICE_TYPE_ANA_DIGI: + case MW_DEVICE_TYPE_DEVB_ANA_DIGI: + *width = 80; + *height = 16; + break; + case MW_DEVICE_TYPE_DIGITAL: + case MW_DEVICE_TYPE_DEVB_DIGI: + *width = 96; + *height = 96; + break; + default: + break; + }; + + return 0; +} + + /* if flip=1 bits in each byte are inverted 7->1, 6->2, 5->3,... if invert=1 each byte is inverted */ @@ -453,7 +583,7 @@ void bmap_buffer_flipinvert(unsigned char flip, unsigned char invert, unsigned c } -void mw_send_bitmap(int mw_fd, unsigned char mode, int width, int height, int offset, unsigned char *bmapbuf, int buflen) +void mw_send_bitmap(mwdevice_t *mwdevice, unsigned char mode, int width, int height, int offset, unsigned char *bmapbuf, int buflen) { #ifdef DEBUG unsigned int i, x; @@ -483,7 +613,7 @@ void mw_send_bitmap(int mw_fd, unsigned char mode, int width, int height, int of memset(mw_buf, 0, 24); memcpy(mw_buf, (bmapbuf+(y*rowlength)), (rowlength > 12) ? 12 : rowlength); memcpy((mw_buf+12), (bmapbuf+((y+1)*rowlength)), (rowlength > 12) ? 12 : rowlength); - mw_write_buffer(mw_fd, mode, 0, offset+y, mw_buf, 24); + mw_write_buffer(mwdevice, mode, 0, offset+y, mw_buf, 24); } } diff --git a/metawatch.h b/metawatch.h index 1f1f777..eb93784 100644 --- a/metawatch.h +++ b/metawatch.h @@ -7,51 +7,78 @@ #ifndef _METAWATCH_H #define _METAWATCH_H +#include #include "metawatch_protocol.h" +typedef struct _mwdevice_t { + int mw_fd; /* file decriptor for MW connection */ + unsigned char devtype; /* the device type of the connected device */ + void (*mw_get_real_time_clock_response_cb) (struct _mwdevice_t *mwdevice, struct tm *mw_tm, void *user_data); + void *mw_grtcrsp_data; + void (*mw_get_battery_voltage_response_cb) (struct _mwdevice_t *mwdevice, unsigned short *voltage, unsigned char *pgood, unsigned char *charging, void *user_data); + void *mw_gbatvrsp_data; + void (*mw_read_button_config_response_cb) (struct _mwdevice_t *mwdevice, void *user_data); + void *mw_rbtncnfrsp_data; + void (*mw_read_light_sensor_response_cb) (struct _mwdevice_t *mwdevice, unsigned short *light_level, void *user_data); + void *mw_rlsrsp_data; + void (*mw_status_change_event_cb) (struct _mwdevice_t *mwdevice, unsigned char *scrmode, unsigned char *status, void *user_data); + void *mw_stchev_data; +} mwdevice_t; + void dump_frame(unsigned char *frame, int len); -int mw_send_frame(int mw_fd, unsigned char msg_type, unsigned char options, unsigned char *data, unsigned char len); +int mw_send_frame(mwdevice_t *mwdevice, unsigned char msg_type, unsigned char options, unsigned char *data, unsigned char len); -void mw_set_rtc(int mw_fd, unsigned char clk1224, unsigned char date_fmt); +int mw_set_rtc(mwdevice_t *mwdevice, unsigned char clk1224, unsigned char date_fmt); -void mw_set_vibrate_mode(int mw_fd, unsigned char enable, unsigned short on_time, unsigned short off_time, unsigned char cycles); +int mw_set_vibrate_mode(mwdevice_t *mwdevice, unsigned char enable, unsigned short on_time, unsigned short off_time, unsigned char cycles); -void mw_configure_watch_mode(int mw_fd, unsigned char mode, unsigned char save, unsigned char timeout, unsigned char invert); +int mw_configure_watch_mode(mwdevice_t *mwdevice, unsigned char mode, unsigned char save, unsigned char timeout, unsigned char invert); -void mw_update_display(int mw_fd, unsigned char mode, unsigned char copy); +int mw_update_display(mwdevice_t *mwdevice, unsigned char mode, unsigned char copy); -void mw_load_template(int mw_fd, unsigned char mode, unsigned char template_select); +int mw_load_template(mwdevice_t *mwdevice, unsigned char mode, unsigned char template_select); -void mw_write_buffer(int mw_fd, +int mw_write_buffer(mwdevice_t *mwdevice, unsigned char mode, unsigned char numlines, /* number of lines, 0=two lines or 1=one line */ unsigned char row_offset, /* start at row_offset in display, e.g. lower part in idle @31 */ unsigned char *buffer, int buflen); -void mw_write_oled_buffer(int mw_fd, +int mw_write_oled_buffer(mwdevice_t *mwdevice, unsigned char mode, /* idle or scroll */ unsigned char oled, /* which OLED */ unsigned char numcols, unsigned char col_index, /* starting index */ unsigned char *buffer, int buflen); -void mw_get_real_time_clock_response(int mw_fd, unsigned char *rtcrsp, int len); +int mw_get_real_time_clock_response(mwdevice_t *mwdevice, unsigned char *rtcrsp, int len); +void mw_set_get_real_time_clock_response_cb(mwdevice_t *mwdevice, void (*mw_get_real_time_clock_response_cb) (mwdevice_t *mwdevice, struct tm *mw_tm, void *user_data), void *user_data); + +int mw_get_battery_voltage_response(mwdevice_t *mwdevice, unsigned char *batrsp, int len); +void mw_set_get_battery_voltage_response_cb(mwdevice_t *mwdevice, void (*mw_get_battery_voltage_response_cb) (mwdevice_t *mwdevice, unsigned short *voltage, unsigned char *pgood, unsigned char *charging, void *user_data), void *user_data); -void mw_get_battery_voltage_response(int mw_fd, unsigned char *batrsp, int len); +int mw_read_button_config_response(mwdevice_t *mwdevice, unsigned char *btnrsp, int len); -void mw_status_change_event(int mw_fd, unsigned char option, unsigned char *statrsp, int len); +int mw_read_light_sensor_response(mwdevice_t *mwdevice, unsigned char *lightrsp, int len); +void mw_set_read_light_sensor_response_cb(mwdevice_t *mwdevice, void (*mw_read_light_sensor_response_cb) (mwdevice_t *mwdevice, unsigned short *light_level, void *user_data), void *user_data); -void mw_enable_button(int mw_fd, unsigned char mode, unsigned char button_index, unsigned char press_type, unsigned char callback_type, unsigned char callback_option); +int mw_status_change_event(mwdevice_t *mwdevice, unsigned char option, unsigned char *statrsp, int len); +void mw_set_status_change_event_cb(mwdevice_t *mwdevice, void (*mw_status_change_event_cb) (mwdevice_t *mwdevice, unsigned char *scrmode, unsigned char *status, void *user_data), void *user_data); -void mw_disable_button(int mw_fd, unsigned char mode, unsigned char button_index, unsigned char press_type); +int mw_enable_button(mwdevice_t *mwdevice, unsigned char mode, unsigned char button_index, unsigned char press_type, unsigned char callback_type, unsigned char callback_option); -int decode_frame(int mw_fd, unsigned char *buf, int len); +int mw_disable_button(mwdevice_t *mwdevice, unsigned char mode, unsigned char button_index, unsigned char press_type); +int decode_frame(mwdevice_t *mwdevice, unsigned char *buf, int len); +int mw_init(mwdevice_t *mwdevice, int mw_fd); + +/* helper function to flip bit order in a byte and optionally invert the image */ void bmap_buffer_flipinvert(unsigned char flip, unsigned char invert, unsigned char *buf, int len); -void mw_send_bitmap(int mw_fd, unsigned char mode, int width, int height, int offset, unsigned char *bmapbuf, int buflen); + +void mw_send_bitmap(mwdevice_t *mwdevice, unsigned char mode, int width, int height, int offset, unsigned char *bmapbuf, int buflen); #endif /* _METAWATCH_H */ diff --git a/metawatch_protocol.h b/metawatch_protocol.h index db3656e..65b991b 100644 --- a/metawatch_protocol.h +++ b/metawatch_protocol.h @@ -25,6 +25,13 @@ /* general */ #define MW_GET_DEVICE_TYPE 0x01 #define MW_GET_DEVICE_TYPE_RSP 0x02 + +#define MW_DEVICE_TYPE_RESERVED 0x00 +#define MW_DEVICE_TYPE_ANA_DIGI 0x01 +#define MW_DEVICE_TYPE_DIGITAL 0x02 +#define MW_DEVICE_TYPE_DEVB_DIGI 0x03 +#define MW_DEVICE_TYPE_DEVB_ANA_DIGI 0x04 + #define MW_GET_INFORMATION_STRING 0x03 #define MW_GET_INFORMATION_STRING_RSP 0x04 diff --git a/mw_main.c b/mw_main.c index 8fd34a3..4e871b4 100644 --- a/mw_main.c +++ b/mw_main.c @@ -36,15 +36,15 @@ typedef struct { GMainLoop *mloop; - int mw_fd; /* MetaWatch RFCOMM BT socket */ + mwdevice_t mwdevice; unsigned char rcvbuf[128]; int rcvbuf_pos; int con_fd; /* console input fd */ char cmdline[128]; int cmdline_pos; -} mwdata; +} mwdata_t; -void bitmap_test(int mw_fd) +void bitmap_test(mwdevice_t *mwdevice) { /* a nice checker-board pattern */ unsigned char checkbuf[24] = { @@ -53,15 +53,15 @@ void bitmap_test(int mw_fd) 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, }; - mw_write_buffer(mw_fd, MW_SCREEN_MODE_IDLE, 0, 31, checkbuf, 24); - mw_write_buffer(mw_fd, MW_SCREEN_MODE_IDLE, 0, 33, checkbuf, 24); - mw_write_buffer(mw_fd, MW_SCREEN_MODE_IDLE, 0, 35, checkbuf, 24); - mw_write_buffer(mw_fd, MW_SCREEN_MODE_IDLE, 0, 37, checkbuf, 24); + mw_write_buffer(mwdevice, MW_SCREEN_MODE_IDLE, 0, 31, checkbuf, 24); + mw_write_buffer(mwdevice, MW_SCREEN_MODE_IDLE, 0, 33, checkbuf, 24); + mw_write_buffer(mwdevice, MW_SCREEN_MODE_IDLE, 0, 35, checkbuf, 24); + mw_write_buffer(mwdevice, MW_SCREEN_MODE_IDLE, 0, 37, checkbuf, 24); - mw_update_display(mw_fd, MW_SCREEN_MODE_IDLE, 1); + mw_update_display(mwdevice, MW_SCREEN_MODE_IDLE, 1); } -void bitmap_test2(int mw_fd) +void bitmap_test2(mwdevice_t *mwdevice) { mw_buffer *mwbuf1, *mwbuf2; unsigned char *bbuf; @@ -78,8 +78,8 @@ void bitmap_test2(int mw_fd) mw_buf_draw_pixel(mwbuf1, x, x, MW_WHITE); mw_dump_mw_buffer(mwbuf1); bbuf = mw_make_mw_buffer(mwbuf1, &len); - mw_send_bitmap(mw_fd, MW_SCREEN_MODE_IDLE, 96, 65, 31, bbuf, len); - mw_update_display(mw_fd, MW_SCREEN_MODE_IDLE, 1); + mw_send_bitmap(mwdevice, MW_SCREEN_MODE_IDLE, 96, 65, 31, bbuf, len); + mw_update_display(mwdevice, MW_SCREEN_MODE_IDLE, 1); getchar(); }; @@ -87,7 +87,7 @@ void bitmap_test2(int mw_fd) mw_free_pbuffer(mwbuf2); } -void text_test(int mw_fd) +void text_test(mwdevice_t *mwdevice) { mw_buffer *mwbuf; unsigned char *bbuf; @@ -102,12 +102,12 @@ void text_test(int mw_fd) mw_buf_print(mwbuf, 1, 45, "Big Fat Clipping", 2, MW_BLACK, MW_WHITE); bbuf = mw_make_mw_buffer(mwbuf, &len); - mw_send_bitmap(mw_fd, MW_SCREEN_MODE_IDLE, 96, 65, 31, bbuf, len); - mw_update_display(mw_fd, MW_SCREEN_MODE_IDLE, 1); + mw_send_bitmap(mwdevice, MW_SCREEN_MODE_IDLE, 96, 65, 31, bbuf, len); + mw_update_display(mwdevice, MW_SCREEN_MODE_IDLE, 1); mw_free_pbuffer(mwbuf); } -void line_test(int mw_fd) +void line_test(mwdevice_t *mwdevice) { mw_buffer *mwbuf; unsigned char *bbuf; @@ -120,12 +120,12 @@ void line_test(int mw_fd) mw_buf_draw_line_bresenham(mwbuf, p, 0, 95-p, 65, MW_WHITE); bbuf = mw_make_mw_buffer(mwbuf, &len); - mw_send_bitmap(mw_fd, MW_SCREEN_MODE_IDLE, 96, 65, 31, bbuf, len); - mw_update_display(mw_fd, MW_SCREEN_MODE_IDLE, 1); + mw_send_bitmap(mwdevice, MW_SCREEN_MODE_IDLE, 96, 65, 31, bbuf, len); + mw_update_display(mwdevice, MW_SCREEN_MODE_IDLE, 1); mw_free_pbuffer(mwbuf); } -void bitmap_read(int mw_fd) +void bitmap_read(mwdevice_t *mwdevice) { int ffd, ret; char rbuf[256]; @@ -186,14 +186,14 @@ void bitmap_read(int mw_fd) /* reverse bits and invert the bmap */ bmap_buffer_flipinvert(1, 1, bmapbuf, rowlength * height); /* send the buffer to the watch */ - mw_send_bitmap(mw_fd, MW_SCREEN_MODE_IDLE, width, height, 31, bmapbuf, rowlength * height); + mw_send_bitmap(mwdevice, MW_SCREEN_MODE_IDLE, width, height, 31, bmapbuf, rowlength * height); /* update the display */ - mw_update_display(mw_fd, MW_SCREEN_MODE_IDLE, 1); + mw_update_display(mwdevice, MW_SCREEN_MODE_IDLE, 1); free(bmapbuf); } -void test_notification(int mw_fd) +void test_notification(mwdevice_t *mwdevice) { mw_buffer *mwbuf; unsigned char *bbuf; @@ -224,14 +224,14 @@ void test_notification(int mw_fd) mw_buf_print(mwbuf, 4, 85, "012345678901234", 0, MW_WHITE, MW_BLACK); bbuf = mw_make_mw_buffer(mwbuf, &len); - mw_send_bitmap(mw_fd, MW_SCREEN_MODE_NOTIFICATION, 96, 96, 0, bbuf, len); - mw_update_display(mw_fd, MW_SCREEN_MODE_NOTIFICATION, 1); + mw_send_bitmap(mwdevice, MW_SCREEN_MODE_NOTIFICATION, 96, 96, 0, bbuf, len); + mw_update_display(mwdevice, MW_SCREEN_MODE_NOTIFICATION, 1); mw_free_pbuffer(mwbuf); - mw_set_vibrate_mode(mw_fd, 1, 300, 300, 3); + mw_set_vibrate_mode(mwdevice, 1, 300, 300, 3); } -void mw_send_notify(int mw_fd, char *header, char *body) +void mw_send_notify(mwdevice_t *mwdevice, char *header, char *body) { mw_buffer *mwbuf; unsigned char *bbuf; @@ -258,21 +258,21 @@ void mw_send_notify(int mw_fd, char *header, char *body) }; bbuf = mw_make_mw_buffer(mwbuf, &len); - mw_send_bitmap(mw_fd, MW_SCREEN_MODE_APPLICATION, 96, 96, 0, bbuf, len); - mw_update_display(mw_fd, MW_SCREEN_MODE_APPLICATION, 1); + mw_send_bitmap(mwdevice, MW_SCREEN_MODE_APPLICATION, 96, 96, 0, bbuf, len); + mw_update_display(mwdevice, MW_SCREEN_MODE_APPLICATION, 1); mw_free_pbuffer(mwbuf); - mw_set_vibrate_mode(mw_fd, 1, 300, 300, 2); + mw_set_vibrate_mode(mwdevice, 1, 300, 300, 2); } -void test_application(int mw_fd) +void test_application(mwdevice_t *mwdevice) { mw_buffer *mwbuf; unsigned char *bbuf; int len; - mw_enable_button(mw_fd, MW_SCREEN_MODE_APPLICATION, MW_BUTTON_A, MW_BUTTON_IMMEDIATE, MW_BUTTON_EVENT_MESSAGE, MW_BUTTON_A); - mw_configure_watch_mode(mw_fd, MW_SCREEN_MODE_APPLICATION, 0, 30, 0); + mw_enable_button(mwdevice, MW_SCREEN_MODE_APPLICATION, MW_BUTTON_A, MW_BUTTON_IMMEDIATE, MW_BUTTON_EVENT_MESSAGE, MW_BUTTON_A); + mw_configure_watch_mode(mwdevice, MW_SCREEN_MODE_APPLICATION, 0, 30, 0); mwbuf = mw_alloc_pbuffer(96, 96, 1); mw_buf_clear(mwbuf, MW_BLACK); @@ -289,12 +289,12 @@ void test_application(int mw_fd) mw_buf_print(mwbuf, 0, 81, "0123456789012345", 0, MW_WHITE, MW_BLACK); bbuf = mw_make_mw_buffer(mwbuf, &len); - mw_send_bitmap(mw_fd, MW_SCREEN_MODE_APPLICATION, 96, 96, 0, bbuf, len); - mw_update_display(mw_fd, MW_SCREEN_MODE_APPLICATION, 1); + mw_send_bitmap(mwdevice, MW_SCREEN_MODE_APPLICATION, 96, 96, 0, bbuf, len); + mw_update_display(mwdevice, MW_SCREEN_MODE_APPLICATION, 1); mw_free_pbuffer(mwbuf); } -void test_oled(int mw_fd, unsigned char oled) +void test_oled(mwdevice_t *mwdevice, unsigned char oled) { mw_buffer *mwbuf; unsigned char *bbuf; @@ -303,11 +303,11 @@ void test_oled(int mw_fd, unsigned char oled) mwbuf = mw_alloc_pbuffer(80, 16, 1); mw_buf_clear(mwbuf, MW_BLACK); - mw_buf_print(mwbuf, 0, 0, "ApplicatiO", 0, MW_WHITE, MW_BLACK); - mw_buf_print(mwbuf, 0, 8, "0123456789", 0, MW_WHITE, MW_BLACK); + mw_buf_print(mwbuf, 0, 0, "Application", 0, MW_WHITE, MW_BLACK); + mw_buf_print(mwbuf, 0, 8, "012345678901234", 0, MW_WHITE, MW_BLACK); bbuf = mw_make_mw_oled_buffer(mwbuf, &len); - mw_write_oled_buffer(mw_fd, 0, oled, 80, 0, bbuf, len); + mw_write_oled_buffer(mwdevice, 0, oled, 80, 0, bbuf, len); mw_free_pbuffer(mwbuf); } @@ -316,7 +316,7 @@ void print_help(void) { } -void process_cmd(char *cmdline, int clinep, int mw_fd) +void process_cmd(char *cmdline, int clinep, mwdata_t *mwdata) { unsigned char mdata[32]; unsigned int intopt; @@ -324,9 +324,9 @@ void process_cmd(char *cmdline, int clinep, int mw_fd) fprintf(stderr, "command: '%s'\n", cmdline); if (strncmp(cmdline, "quit", 4) == 0) { - close(mw_fd); - exit(0); - // g_main_loop_quit (mdata->mloop); + //close(mw_fd); + //exit(0); + g_main_loop_quit (mwdata->mloop); } if (strncmp(cmdline, "help", 4) == 0) { print_help(); @@ -337,15 +337,15 @@ void process_cmd(char *cmdline, int clinep, int mw_fd) mdata[0] = intopt / 60; mdata[1] = intopt % 60; mdata[2] = 0; - mw_send_frame(mw_fd, MW_ADVANCE_WATCH_HANDS, 0, mdata, 3); + mw_send_frame(&mwdata->mwdevice, MW_ADVANCE_WATCH_HANDS, 0, mdata, 3); } if (strncmp(cmdline, "srtc", 4) == 0) { fprintf(stderr, "Setting RTC from system time..."); - mw_set_rtc(mw_fd, MW_RTC_CLOCK_24HR, MW_RTC_DATE_DDMM); + mw_set_rtc(&mwdata->mwdevice, MW_RTC_CLOCK_24HR, MW_RTC_DATE_DDMM); fprintf(stderr, "OK\n"); } if (strncmp(cmdline, "grtc", 4) == 0) { - mw_send_frame(mw_fd, MW_GET_REAL_TIME_CLOCK, 0, NULL, 0); + mw_send_frame(&mwdata->mwdevice, MW_GET_REAL_TIME_CLOCK, 0, NULL, 0); } if (strncmp(cmdline, "gistr", 5) == 0) { intopt = cmdline[6]-0x30; @@ -353,20 +353,20 @@ void process_cmd(char *cmdline, int clinep, int mw_fd) mdata[0] = intopt; else mdata[0] = 0; - mw_send_frame(mw_fd, MW_GET_INFORMATION_STRING, 0, mdata, 1); + mw_send_frame(&mwdata->mwdevice, MW_GET_INFORMATION_STRING, 0, mdata, 1); } if (strncmp(cmdline, "gdtype", 6) == 0) { - mw_send_frame(mw_fd, MW_GET_DEVICE_TYPE, 0, NULL, 0); + mw_send_frame(&mwdata->mwdevice, MW_GET_DEVICE_TYPE, 0, NULL, 0); } if (strncmp(cmdline, "rvbat", 5) == 0) { - mw_send_frame(mw_fd, MW_READ_BATTERY_VOLTAGE_MSG, 0, NULL, 0); + mw_send_frame(&mwdata->mwdevice, MW_READ_BATTERY_VOLTAGE_MSG, 0, NULL, 0); } if (strncmp(cmdline, "rlight", 6) == 0) { - mw_send_frame(mw_fd, MW_READ_LIGHT_SENSOR_MSG, 0, NULL, 0); + mw_send_frame(&mwdata->mwdevice, MW_READ_LIGHT_SENSOR_MSG, 0, NULL, 0); } if (strncmp(cmdline, "modecfg", 6) == 0) { - mw_configure_watch_mode(mw_fd, MW_SCREEN_MODE_IDLE, 0, 4, 1); - mw_update_display(mw_fd, MW_SCREEN_MODE_IDLE, 0); + mw_configure_watch_mode(&mwdata->mwdevice, MW_SCREEN_MODE_IDLE, 0, 4, 1); + mw_update_display(&mwdata->mwdevice, MW_SCREEN_MODE_IDLE, 0); } if (strncmp(cmdline, "rbtcfg", 6) == 0) { intopt = cmdline[7]-0x30; @@ -376,47 +376,47 @@ void process_cmd(char *cmdline, int clinep, int mw_fd) mdata[2] = 0; /* button press type */ mdata[3] = 0; /* callback message type */ mdata[4] = 0; /* callback message option */ - mw_send_frame(mw_fd, MW_READ_BUTTON_CONFIG, 0, mdata, 5); + mw_send_frame(&mwdata->mwdevice, MW_READ_BUTTON_CONFIG, 0, mdata, 5); } if (strncmp(cmdline, "svib", 4) == 0) { - mw_set_vibrate_mode(mw_fd, 1, 300, 300, 5); + mw_set_vibrate_mode(&mwdata->mwdevice, 1, 300, 300, 5); } if (strncmp(cmdline, "tbmp", 4) == 0) { - bitmap_test(mw_fd); + bitmap_test(&mwdata->mwdevice); } if (strncmp(cmdline, "t2bmp", 5) == 0) { - bitmap_test2(mw_fd); + bitmap_test2(&mwdata->mwdevice); } if (strncmp(cmdline, "text", 4) == 0) { - text_test(mw_fd); + text_test(&mwdata->mwdevice); } if (strncmp(cmdline, "tline", 5) == 0) { - line_test(mw_fd); + line_test(&mwdata->mwdevice); } if (strncmp(cmdline, "rbmp", 4) == 0) { - bitmap_read(mw_fd); + bitmap_read(&mwdata->mwdevice); } if (strncmp(cmdline, "tnote", 5) == 0) { - test_notification(mw_fd); + test_notification(&mwdata->mwdevice); } if (strncmp(cmdline, "tapp", 4) == 0) { - test_application(mw_fd); + test_application(&mwdata->mwdevice); } if (strncmp(cmdline, "eoled", 5) == 0) { intopt = cmdline[6]-0x30; if (intopt == MW_OLED_UPPER || intopt == MW_OLED_LOWER) - mw_send_frame(mw_fd, MW_ENABLE_OLED_DISPLAY_MSG, intopt, NULL, 0); + mw_send_frame(&mwdata->mwdevice, MW_ENABLE_OLED_DISPLAY_MSG, intopt, NULL, 0); } if (strncmp(cmdline, "toled", 5) == 0) { intopt = cmdline[6]-0x30; - test_oled(mw_fd, intopt); - //mw_write_oled_buffer(mw_fd, 0, 80, 0, mdata, 10); - //mw_send_frame(mw_fd, MW_UPDATE_OLED_DISPLAY_MSG, 0, NULL, 0); + test_oled(&mwdata->mwdevice, intopt); + //mw_write_oled_buffer(mwdevice, 0, 80, 0, mdata, 10); + //mw_send_frame(mwdevice, MW_UPDATE_OLED_DISPLAY_MSG, 0, NULL, 0); } } -int feed_menu(mwdata *mdata) +int feed_menu(mwdata_t *mdata) { int rcvd; @@ -425,7 +425,7 @@ int feed_menu(mwdata *mdata) if (mdata->cmdline[mdata->cmdline_pos] == '\r') { printf("\n"); mdata->cmdline[mdata->cmdline_pos--] = '\0'; - process_cmd(mdata->cmdline, mdata->cmdline_pos, mdata->mw_fd); + process_cmd(mdata->cmdline, mdata->cmdline_pos, mdata); mdata->cmdline_pos = 0; memset(mdata->cmdline, 0, 128); } else { @@ -556,10 +556,10 @@ int str2ba(const char *str, bdaddr_t *ba) gboolean handle_mw_io(GIOChannel *mw_io, GIOCondition condition, gpointer udata) { - mwdata *mdata = (mwdata *)udata; + mwdata_t *mdata = (mwdata_t *)udata; int rcvd; - rcvd = read(mdata->mw_fd, mdata->rcvbuf+mdata->rcvbuf_pos, 64); + rcvd = read(mdata->mwdevice.mw_fd, mdata->rcvbuf+mdata->rcvbuf_pos, 64); #ifdef DEBUG fprintf(stderr, "read %d bytes:\n", rcvd); #endif @@ -567,7 +567,7 @@ gboolean handle_mw_io(GIOChannel *mw_io, GIOCondition condition, gpointer udata) #ifdef DEBUG dump_frame(mdata->rcvbuf, rcvd); #endif - decode_frame(mdata->mw_fd, mdata->rcvbuf, rcvd); + decode_frame(&mdata->mwdevice, mdata->rcvbuf, rcvd); mdata->rcvbuf_pos = 0; } @@ -576,7 +576,7 @@ gboolean handle_mw_io(GIOChannel *mw_io, GIOCondition condition, gpointer udata) gboolean handle_min_io(GIOChannel *mw_io, GIOCondition condition, gpointer udata) { - mwdata *mdata = (mwdata *)udata; + mwdata_t *mdata = (mwdata_t *)udata; feed_menu(mdata); @@ -587,7 +587,7 @@ static DBusHandlerResult signal_filter (DBusConnection *connection, DBusMessage *message, void *user_data) { //GMainLoop *loop = user_data; - mwdata *mdata = (mwdata *)user_data; + mwdata_t *mdata = (mwdata_t *)user_data; DBusError error; char *app_name, *app_icon, *summary, *body; // **actions; int replace_id; // dict, expire; @@ -614,7 +614,7 @@ signal_filter (DBusConnection *connection, DBusMessage *message, void *user_data DBUS_TYPE_INT32, &expire, */ DBUS_TYPE_INVALID)) { g_print("Notify received: from app %s, icon %s:\nSummary: %s\nBody: %s\n", app_name, app_icon, summary, body); - mw_send_notify(mdata->mw_fd, summary, body); + mw_send_notify(&mdata->mwdevice, summary, body); /* we just listen, we do not handle it here */ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } else { @@ -632,7 +632,7 @@ signal_filter (DBusConnection *connection, DBusMessage *message, void *user_data int main(int argc, char **argv) { int mw_fd; - mwdata mdata; + mwdata_t mdata; struct termios tconfd, otconfd, tmwfd; bdaddr_t btaddr; GIOChannel *mw_io, *m_in; @@ -673,7 +673,7 @@ int main(int argc, char **argv) tmwfd.c_lflag |= ISIG; tcsetattr(mw_fd, TCSANOW, &tmwfd); - mdata.mw_fd = mw_fd; + mdata.mwdevice.mw_fd = mw_fd; mdata.rcvbuf_pos = 0; memset(mdata.rcvbuf, 0, 128); diff --git a/test.pbm b/test.pbm deleted file mode 100644 index 8420b3d..0000000 Binary files a/test.pbm and /dev/null differ diff --git a/test.pbm b/test.pbm new file mode 120000 index 0000000..2768964 --- /dev/null +++ b/test.pbm @@ -0,0 +1 @@ +pesthorn_sg.pbm \ No newline at end of file