Skip to content

Commit 19f153a

Browse files
committed
Updated ELM327-plugin, added Makefile
- ELM327-Plugin now works properly and with higher polling-speed - added makefile for easier compilation (no cross-compilation for now) - fixed incorrect dpi calculation
1 parent 7a9f326 commit 19f153a

9 files changed

+396
-304
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
out
22
.vscode
3-
Makefile
3+
build.sh

Makefile

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
CC = cc
2+
LD = cc
3+
REAL_CFLAGS = -I./include $(shell pkg-config --cflags dri gbm libdrm glesv2 egl) -D_GNU_SOURCE -DBUILD_ELM327PLUGIN $(CFLAGS)
4+
REAL_LDFLAGS = $(shell pkg-config --libs dri gbm libdrm glesv2 egl) -lrt -lflutter_engine -lpthread -ldl $(LDFLAGS)
5+
6+
SOURCES = src/flutter-pi.c src/platformchannel.c src/pluginregistry.c src/plugins/elm327plugin.c src/plugins/services-plugin.c src/plugins/testplugin.c
7+
OBJECTS = $(patsubst src/%.c,out/obj/%.o,$(SOURCES))
8+
9+
all: out/flutter-pi
10+
11+
out/obj/%.o: src/%.c
12+
@mkdir -p $(@D)
13+
$(CC) -c $(REAL_CFLAGS) $(REAL_LDFLAGS) $< -o $@
14+
15+
out/flutter-pi: $(OBJECTS)
16+
@mkdir -p $(@D)
17+
$(CC) $(REAL_CFLAGS) $(REAL_LDFLAGS) $(OBJECTS) -o out/flutter-pi
18+
19+
clean:
20+
@mkdir -p out
21+
rm -rf $(OBJECTS) out/flutter-pi out/obj/*

include/flutter-pi.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99

1010
#define EGL_PLATFORM_GBM_KHR 0x31D7
1111

12-
struct LinkedTaskListElement {
13-
struct LinkedTaskListElement* next;
12+
struct FlutterPiTask {
13+
struct FlutterPiTask* next;
1414
bool is_vblank_event;
1515
union {
1616
FlutterTask task;

include/platformchannel.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -201,10 +201,10 @@ int PlatformChannel_encode(struct ChannelObject *object, uint8_t **buffer_out, s
201201

202202
/// Encodes a generic ChannelObject (anything, string/binary codec or Standard/JSON Method Calls and responses) as a platform message
203203
/// and sends it to flutter on channel `channel`
204-
/// When flutter responds to this message, it is automatically decoded using the codec given in `response_codec`.
205-
/// Then, on_response is called with the decoded ChannelObject and the userdata as an argument.
206-
/// Flutter _should_ always respond to platform messages, so it's okay if not calling your handler would cause a memory leak
207-
/// (since that should never happen)
204+
/// If you supply a response callback (i.e. on_response is != NULL):
205+
/// when flutter responds to this message, it is automatically decoded using the codec given in `response_codec`.
206+
/// Then, on_response is called with the decoded ChannelObject and the userdata as an argument.
207+
/// It's possible that flutter won't respond to your platform message, like when sending events via an EventChannel.
208208
/// userdata can be NULL.
209209
int PlatformChannel_send(char *channel, struct ChannelObject *object, enum ChannelCodec response_codec, PlatformMessageResponseCallback on_response, void *userdata);
210210

src/flutter-pi.c

Lines changed: 48 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <limits.h>
1616
#include <float.h>
1717
#include <assert.h>
18+
#include <time.h>
1819

1920
#include <xf86drm.h>
2021
#include <xf86drmMode.h>
@@ -118,32 +119,30 @@ struct {
118119

119120
pthread_t io_thread_id;
120121
pthread_t platform_thread_id;
121-
struct LinkedTaskListElement task_list_head_sentinel = {
122+
struct FlutterPiTask tasklist = {
122123
.next = NULL,
123124
.is_vblank_event = false,
124125
.target_time = 0,
125126
.task = {.runner = NULL, .task = 0}
126127
};
127-
pthread_mutex_t task_list_lock;
128-
bool should_notify_platform_thread = false;
129-
sigset_t sigusr1_set;
130-
128+
pthread_mutex_t tasklist_lock = PTHREAD_MUTEX_INITIALIZER;
129+
pthread_cond_t task_added = PTHREAD_COND_INITIALIZER;
131130

132131

133132
/*********************
134133
* FLUTTER CALLBACKS *
135134
*********************/
136135
bool make_current(void* userdata) {
137136
if (eglMakeCurrent(egl.display, egl.surface, egl.surface, egl.context) != EGL_TRUE) {
138-
fprintf(stderr, "Could not make the context current.\n");
137+
fprintf(stderr, "make_current: could not make the context current.\n");
139138
return false;
140139
}
141140

142141
return true;
143142
}
144143
bool clear_current(void* userdata) {
145144
if (eglMakeCurrent(egl.display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) != EGL_TRUE) {
146-
fprintf(stderr, "Could not clear the current context.\n");
145+
fprintf(stderr, "clear_current: could not clear the current context.\n");
147146
return false;
148147
}
149148

@@ -165,10 +164,12 @@ struct drm_fb* drm_fb_get_from_bo(struct gbm_bo *bo) {
165164
uint32_t width, height, format, strides[4] = {0}, handles[4] = {0}, offsets[4] = {0}, flags = 0;
166165
int ok = -1;
167166

167+
// if the buffer object already has some userdata associated with it,
168+
// it's the framebuffer we allocated.
168169
struct drm_fb *fb = gbm_bo_get_user_data(bo);
169-
170170
if (fb) return fb;
171171

172+
// if there's no framebuffer for the bo, we need to create one.
172173
fb = calloc(1, sizeof(struct drm_fb));
173174
fb->bo = bo;
174175

@@ -197,7 +198,7 @@ struct drm_fb* drm_fb_get_from_bo(struct gbm_bo *bo) {
197198

198199
if (ok) {
199200
if (flags)
200-
fprintf(stderr, "Modifiers failed!\n");
201+
fprintf(stderr, "drm_fb_get_from_bo: modifiers failed!\n");
201202

202203
memcpy(handles, (uint32_t [4]){gbm_bo_get_handle(bo).u32,0,0,0}, 16);
203204
memcpy(strides, (uint32_t [4]){gbm_bo_get_stride(bo),0,0,0}, 16);
@@ -207,7 +208,7 @@ struct drm_fb* drm_fb_get_from_bo(struct gbm_bo *bo) {
207208
}
208209

209210
if (ok) {
210-
fprintf(stderr, "failed to create fb: %s\n", strerror(errno));
211+
fprintf(stderr, "drm_fb_get_from_bo: failed to create fb: %s\n", strerror(errno));
211212
free(fb);
212213
return NULL;
213214
}
@@ -286,7 +287,7 @@ void cut_word_from_string(char* string, char* word) {
286287
} while (word_in_str[i++ + word_length] != 0);
287288
}
288289
}
289-
const GLubyte* hacked_glGetString(GLenum name) {
290+
const GLubyte *hacked_glGetString(GLenum name) {
290291
if (name == GL_EXTENSIONS) {
291292
static GLubyte* extensions;
292293

@@ -365,7 +366,7 @@ const GLubyte* hacked_glGetString(GLenum name) {
365366
return glGetString(name);
366367
}
367368
}
368-
void* proc_resolver(void* userdata, const char* name) {
369+
void *proc_resolver(void* userdata, const char* name) {
369370
if (name == NULL) return NULL;
370371

371372
/*
@@ -405,58 +406,36 @@ void handle_sigusr1(int _) {}
405406
bool init_message_loop() {
406407
platform_thread_id = pthread_self();
407408

408-
// first, initialize the task heap mutex
409-
if (pthread_mutex_init(&task_list_lock, NULL) != 0) {
410-
fprintf(stderr, "Could not initialize task list mutex\n");
411-
return false;
412-
}
413-
414-
sigemptyset(&sigusr1_set);
415-
sigaddset(&sigusr1_set, SIGUSR1);
416-
sigaction(SIGUSR1, &(struct sigaction) {.sa_handler = &handle_sigusr1}, NULL);
417-
pthread_sigmask(SIG_UNBLOCK, &sigusr1_set, NULL);
418-
419409
return true;
420410
}
421411
bool message_loop(void) {
422-
should_notify_platform_thread = true;
412+
struct timespec abstargetspec;
413+
uint64_t currenttime, abstarget;
423414

424415
while (true) {
425-
pthread_mutex_lock(&task_list_lock);
426-
if (task_list_head_sentinel.next == NULL) {
427-
pthread_mutex_unlock(&task_list_lock);
428-
sigwaitinfo(&sigusr1_set, NULL);
429-
continue;
430-
} else {
431-
uint64_t target_time = task_list_head_sentinel.next->target_time;
432-
uint64_t current_time = FlutterEngineGetCurrentTime();
433-
434-
if (target_time > current_time) {
435-
uint64_t diff = target_time - current_time;
436-
437-
struct timespec target_timespec = {
438-
.tv_sec = (uint64_t) (diff / 1000000000ull),
439-
.tv_nsec = (uint64_t) (diff % 1000000000ull)
440-
};
416+
pthread_mutex_lock(&tasklist_lock);
441417

442-
pthread_mutex_unlock(&task_list_lock);
443-
sigtimedwait(&sigusr1_set, NULL, &target_timespec);
444-
continue;
445-
}
418+
// wait for a task to be inserted into the list
419+
while ((tasklist.next == NULL))
420+
pthread_cond_wait(&task_added, &tasklist_lock);
421+
422+
// wait for a task to be ready to be run
423+
while (tasklist.target_time > (currenttime = FlutterEngineGetCurrentTime())) {
424+
clock_gettime(CLOCK_REALTIME, &abstargetspec);
425+
abstarget = abstargetspec.tv_nsec + abstargetspec.tv_sec*1000000000ull - currenttime;
426+
abstargetspec.tv_nsec = abstarget % 1000000000;
427+
abstargetspec.tv_sec = abstarget / 1000000000;
428+
429+
pthread_cond_timedwait(&task_added, &tasklist_lock, &abstargetspec);
446430
}
447431

448-
FlutterTask task = task_list_head_sentinel.next->task;
449-
bool is_vblank_event = task_list_head_sentinel.next->is_vblank_event;
450-
drmVBlankReply vbl = task_list_head_sentinel.next->vbl;
432+
FlutterTask task = tasklist.next->task;
433+
struct FlutterPiTask* new_first = tasklist.next->next;
434+
free(tasklist.next);
435+
tasklist.next = new_first;
451436

452-
struct LinkedTaskListElement* new_first = task_list_head_sentinel.next->next;
453-
free(task_list_head_sentinel.next);
454-
task_list_head_sentinel.next = new_first;
455-
pthread_mutex_unlock(&task_list_lock);
456-
457-
if (is_vblank_event) {
458-
459-
} else if (FlutterEngineRunTask(engine, &task) != kSuccess) {
437+
pthread_mutex_unlock(&tasklist_lock);
438+
if (FlutterEngineRunTask(engine, &task) != kSuccess) {
460439
fprintf(stderr, "Error running platform task\n");
461440
return false;
462441
};
@@ -465,24 +444,22 @@ bool message_loop(void) {
465444
return true;
466445
}
467446
void post_platform_task(FlutterTask task, uint64_t target_time, void* userdata) {
468-
struct LinkedTaskListElement* to_insert = malloc(sizeof(struct LinkedTaskListElement));
447+
// prepare the task to be inserted into the tasklist.
448+
struct FlutterPiTask* to_insert = malloc(sizeof(struct FlutterPiTask));
469449
to_insert->next = NULL;
470-
to_insert->is_vblank_event = false;
471450
to_insert->task = task;
472451
to_insert->target_time = target_time;
473452

474-
pthread_mutex_lock(&task_list_lock);
475-
struct LinkedTaskListElement* this = &task_list_head_sentinel;
476-
while ((this->next) != NULL && (target_time > this->next->target_time))
477-
this = this->next;
478-
479-
to_insert->next = this->next;
480-
this->next = to_insert;
481-
pthread_mutex_unlock(&task_list_lock);
482-
483-
if (should_notify_platform_thread) {
484-
pthread_kill(platform_thread_id, SIGUSR1);
485-
}
453+
// insert the task at a fitting position. (the tasks are ordered by target time)
454+
pthread_mutex_lock(&tasklist_lock);
455+
struct FlutterPiTask* this = &tasklist;
456+
while ((this->next) != NULL && (target_time > this->next->target_time))
457+
this = this->next;
458+
459+
to_insert->next = this->next;
460+
this->next = to_insert;
461+
pthread_mutex_unlock(&tasklist_lock);
462+
pthread_cond_signal(&task_added);
486463
}
487464
bool runs_platform_tasks_on_current_thread(void* userdata) {
488465
return pthread_equal(pthread_self(), platform_thread_id) != 0;
@@ -572,7 +549,7 @@ bool init_display(void) {
572549

573550
// only update the physical size of the display if the values
574551
// are not yet initialized / not set with a commandline option
575-
if (!((width_mm == 0) && (height_mm == 0))) {
552+
if ((width_mm == 0) && (height_mm == 0)) {
576553
if ((conn->mmWidth == 160) && (conn->mmHeight == 90)) {
577554
// if width and height is exactly 160mm x 90mm, the values are probably bogus.
578555
width_mm = 0;
@@ -939,6 +916,7 @@ bool init_application(void) {
939916

940917
return true;
941918
}
919+
942920
void destroy_application(void) {
943921
int ok;
944922

src/platformchannel.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ int PlatformChannel_writeStdMsgCodecValueToBuffer(struct StdMsgCodecValue* value
204204
break;
205205
case kFloat64:
206206
align8(pbuffer);
207-
write64(pbuffer, (uint64_t) value->float64_value);
207+
write64(pbuffer, *((uint64_t*) &(value->float64_value)));
208208
advance(pbuffer, 8);
209209
break;
210210
case kLargeInt:
@@ -871,7 +871,6 @@ int PlatformChannel_encode(struct ChannelObject *object, uint8_t **buffer_out, s
871871
*size_out = size;
872872
return 0;
873873

874-
875874
free_buffer_and_return_ok:
876875
free(buffer);
877876
return ok;
@@ -917,6 +916,13 @@ int PlatformChannel_send(char *channel, struct ChannelObject *object, enum Chann
917916
if (result != kSuccess) return EINVAL;
918917
}
919918

919+
//printf("[platformchannel] sending platform message to flutter on channel \"%s\". message_size: %d, has response_handle? %s\n", channel, size, response_handle ? "yes" : "no");
920+
//printf(" message buffer: \"");
921+
//for (int i = 0; i < size; i++)
922+
// if (isprint(buffer[i])) printf("%c", buffer[i]);
923+
// else printf("\\x%02X", buffer[i]);
924+
//printf("\"\n");
925+
920926
result = FlutterEngineSendPlatformMessage(
921927
engine,
922928
& (const FlutterPlatformMessage) {
@@ -960,8 +966,8 @@ int PlatformChannel_jsoncall(char *channel, char *method, struct JSONMsgCodecVal
960966
}
961967
int PlatformChannel_respond(FlutterPlatformMessageResponseHandle *handle, struct ChannelObject *response) {
962968
FlutterEngineResult result;
963-
uint8_t *buffer;
964-
size_t size;
969+
uint8_t *buffer = NULL;
970+
size_t size = 0;
965971
int ok;
966972

967973
ok = PlatformChannel_encode(response, &buffer, &size);

src/pluginregistry.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,12 @@ struct {
2626
struct FlutterPiPlugin hardcoded_plugins[] = {
2727
{.name = "services", .init = Services_init, .deinit = Services_deinit},
2828

29-
#ifdef INCLUDE_TESTPLUGIN
29+
#ifdef BUILD_TESTPLUGIN
3030
{.name = "testplugin", .init = TestPlugin_init, .deinit = TestPlugin_deinit}
3131
#endif
3232

33-
#ifdef INCLUDE_ELM327PLUGIN
34-
{.name = "elm327", .init = ELM327Plugin_init, .deinit = ELM327Plugin_deinit}
33+
#ifdef BUILD_ELM327PLUGIN
34+
{.name = "elm327plugin", .init = ELM327Plugin_init, .deinit = ELM327Plugin_deinit}
3535
#endif
3636
};
3737
//size_t hardcoded_plugins_count;

0 commit comments

Comments
 (0)