summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorAidan MacDonald <amachronic@protonmail.com>2022-04-03 13:48:52 +0100
committerAidan MacDonald <amachronic@protonmail.com>2022-09-25 11:05:59 +0100
commite4aec7d648de2553653b378518b5e90f29aeeac3 (patch)
tree37c1f0f542742032573d1a99cc4b68c061fedb10 /apps
parentf47aa584a8b447d8225fc5b09afb2d1fe6764c1d (diff)
downloadrockbox-e4aec7d648de2553653b378518b5e90f29aeeac3.tar.gz
rockbox-e4aec7d648de2553653b378518b5e90f29aeeac3.zip
key remap: simplify and use movable allocations
Have action.c control the key remap buflib allocation so that it can be made movable. With memory management offloaded, core_keymap.c only needs to deal with loading keymap files. Simplify the code there and use buflib pinning so the file can be loaded directly into the buffer. Change-Id: Ia654cc05ce6b286f96c1031fa4f7d4b3859a2c1a
Diffstat (limited to 'apps')
-rw-r--r--apps/action.c121
-rw-r--r--apps/action.h6
-rw-r--r--apps/core_keymap.c134
-rw-r--r--apps/core_keymap.h7
4 files changed, 117 insertions, 151 deletions
diff --git a/apps/action.c b/apps/action.c
index 9ef10936f2..da08e29dbb 100644
--- a/apps/action.c
+++ b/apps/action.c
@@ -34,6 +34,7 @@
34#include "button.h" 34#include "button.h"
35#include "action.h" 35#include "action.h"
36#include "kernel.h" 36#include "kernel.h"
37#include "core_alloc.h"
37 38
38#include "splash.h" 39#include "splash.h"
39#include "settings.h" 40#include "settings.h"
@@ -70,7 +71,7 @@ static action_last_t action_last =
70 .wait_for_release = false, 71 .wait_for_release = false,
71 72
72#ifndef DISABLE_ACTION_REMAP 73#ifndef DISABLE_ACTION_REMAP
73 .core_keymap = NULL, 74 .key_remap = 0,
74#endif 75#endif
75 76
76#ifdef HAVE_TOUCHSCREEN 77#ifdef HAVE_TOUCHSCREEN
@@ -601,9 +602,8 @@ static inline void action_code_lookup(action_last_t *last, action_cur_t *cur)
601#endif 602#endif
602 603
603#ifndef DISABLE_ACTION_REMAP 604#ifndef DISABLE_ACTION_REMAP
604 bool check_remap = (last->core_keymap != NULL);
605 /* attempt to look up the button in user supplied remap */ 605 /* attempt to look up the button in user supplied remap */
606 if(check_remap && (context & CONTEXT_PLUGIN) == 0) 606 if(last->key_remap && (context & CONTEXT_PLUGIN) == 0)
607 { 607 {
608#if 0 /*Disable the REMOTE context for remap for now (BUTTON_REMOTE != 0)*/ 608#if 0 /*Disable the REMOTE context for remap for now (BUTTON_REMOTE != 0)*/
609 if ((cur->button & BUTTON_REMOTE) != 0) 609 if ((cur->button & BUTTON_REMOTE) != 0)
@@ -611,7 +611,7 @@ static inline void action_code_lookup(action_last_t *last, action_cur_t *cur)
611 context |= CONTEXT_REMOTE; 611 context |= CONTEXT_REMOTE;
612 } 612 }
613#endif 613#endif
614 cur->items = last->core_keymap; 614 cur->items = core_get_data(last->key_remap);
615 i = 0; 615 i = 0;
616 action = ACTION_UNKNOWN; 616 action = ACTION_UNKNOWN;
617 /* check the lut at the beginning for the desired context */ 617 /* check the lut at the beginning for the desired context */
@@ -1193,66 +1193,89 @@ int get_action(int context, int timeout)
1193 1193
1194int action_set_keymap(struct button_mapping* core_keymap, int count) 1194int action_set_keymap(struct button_mapping* core_keymap, int count)
1195{ 1195{
1196#ifdef DISABLE_ACTION_REMAP
1197 (void)core_keymap;
1198 (void)count;
1199 return -1;
1200#else
1201 if (count <= 0 || core_keymap == NULL)
1202 return action_set_keymap_handle(0, 0);
1203
1204 size_t keyremap_buf_size = count * sizeof(struct button_mapping);
1205 int handle = core_alloc("keyremap", keyremap_buf_size);
1206 if (handle < 0)
1207 return -6;
1196 1208
1209 memcpy(core_get_data(handle), core_keymap, keyremap_buf_size);
1210 return action_set_keymap_handle(handle, count);
1211#endif
1212}
1213
1214int action_set_keymap_handle(int handle, int count)
1215{
1197#ifdef DISABLE_ACTION_REMAP 1216#ifdef DISABLE_ACTION_REMAP
1198 count = -1; 1217 (void)core_keymap;
1218 (void)count;
1219 return -1;
1199#else 1220#else
1200 if (count > 0 && core_keymap != NULL) /* saf-tey checks :) */ 1221 /* free an existing remap */
1222 if (action_last.key_remap > 0)
1223 action_last.key_remap = core_free(action_last.key_remap);
1224
1225 /* if clearing the remap, we're done */
1226 if (count <= 0 || handle <= 0)
1227 return 0;
1228
1229 /* validate the keymap */
1230 struct button_mapping* core_keymap = core_get_data(handle);
1231 struct button_mapping* entry = &core_keymap[count - 1];
1232 if (entry->action_code != (int) CONTEXT_STOPSEARCHING ||
1233 entry->button_code != BUTTON_NONE) /* check for sentinel at end*/
1201 { 1234 {
1202 int i = 0; 1235 /* missing sentinel entry */
1203 struct button_mapping* entry = &core_keymap[count - 1]; 1236 return -1;
1204 if (entry->action_code != (int) CONTEXT_STOPSEARCHING || 1237 }
1205 entry->button_code != BUTTON_NONE) /* check for sentinel at end*/
1206 {
1207 count = -1;
1208 }
1209 1238
1210 while (count > 0 && /* check the lut at the beginning for invalid offsets */ 1239 /* check the lut at the beginning for invalid offsets */
1211 (entry = &core_keymap[i])->action_code != (int) CONTEXT_STOPSEARCHING) 1240 for (int i = 0; i < count; ++i)
1212 { 1241 {
1213 1242 entry = &core_keymap[i];
1214 if ((entry->action_code & CONTEXT_REMAPPED) == CONTEXT_REMAPPED) 1243 if (entry->action_code == (int)CONTEXT_STOPSEARCHING)
1215 { 1244 break;
1216 int firstbtn = entry->button_code;
1217 int endpos = firstbtn + entry->pre_button_code;
1218 if (firstbtn > count || firstbtn < i || endpos > count)
1219 {
1220 /* offset out of bounds */
1221 count = -2;
1222 break;
1223 }
1224 1245
1225 if (core_keymap[endpos].button_code != BUTTON_NONE) 1246 if ((entry->action_code & CONTEXT_REMAPPED) == CONTEXT_REMAPPED)
1226 { 1247 {
1227 /* stop sentinel is not at end of action lut*/ 1248 int firstbtn = entry->button_code;
1228 count = -3; 1249 int endpos = firstbtn + entry->pre_button_code;
1229 } 1250 if (firstbtn > count || firstbtn < i || endpos > count)
1230 }
1231 else /* something other than a context remap in the lut */
1232 { 1251 {
1233 count = -4; 1252 /* offset out of bounds */
1234 break; 1253 return -2;
1235 } 1254 }
1236 1255
1237 i++; 1256 if (core_keymap[endpos].button_code != BUTTON_NONE)
1238
1239 if (i >= count) /* no sentinel in the lut */
1240 { 1257 {
1241 count = -5; 1258 /* stop sentinel is not at end of action lut */
1242 break; 1259 return -3;
1243 } 1260 }
1244 } 1261 }
1262 else
1263 {
1264 /* something other than a context remap in the lut */
1265 return -4;
1266 }
1245 1267
1246 if (count <= 0) 1268 if (i+1 >= count)
1247 core_keymap = NULL; 1269 {
1248 } 1270 /* no sentinel in the lut */
1249 else 1271 return -5;
1250#endif 1272 }
1251 {
1252 core_keymap = NULL;
1253 } 1273 }
1254 action_last.core_keymap = core_keymap; 1274
1275 /* success */
1276 action_last.key_remap = handle;
1255 return count; 1277 return count;
1278#endif
1256} 1279}
1257 1280
1258int get_custom_action(int context,int timeout, 1281int get_custom_action(int context,int timeout,
diff --git a/apps/action.h b/apps/action.h
index 35f08a3dbd..444437edf8 100644
--- a/apps/action.h
+++ b/apps/action.h
@@ -419,7 +419,7 @@ typedef struct
419 bool wait_for_release; 419 bool wait_for_release;
420 420
421#ifndef DISABLE_ACTION_REMAP 421#ifndef DISABLE_ACTION_REMAP
422 struct button_mapping* core_keymap; 422 int key_remap;
423#endif 423#endif
424 424
425#ifdef HAVE_TOUCHSCREEN 425#ifdef HAVE_TOUCHSCREEN
@@ -449,7 +449,9 @@ bool action_userabort(int timeout);
449const struct button_mapping* get_context_mapping(int context); 449const struct button_mapping* get_context_mapping(int context);
450 450
451/* load a key map to allow buttons for actions to be remapped see: core_keymap */ 451/* load a key map to allow buttons for actions to be remapped see: core_keymap */
452int action_set_keymap(struct button_mapping* core_button_map, int count); 452int action_set_keymap(struct button_mapping* core_keymap, int count);
453/* load keymap in a handle: takes ownership of the handle on success */
454int action_set_keymap_handle(int handle, int count);
453 455
454/* returns the status code variable from action.c for the button just pressed 456/* returns the status code variable from action.c for the button just pressed
455 If button != NULL it will be set to the actual button code */ 457 If button != NULL it will be set to the actual button code */
diff --git a/apps/core_keymap.c b/apps/core_keymap.c
index dbe7ae0072..9d54fcffac 100644
--- a/apps/core_keymap.c
+++ b/apps/core_keymap.c
@@ -27,119 +27,67 @@
27#include "logf.h" 27#include "logf.h"
28 28
29#if !defined(__PCTOOL__) || defined(CHECKWPS) 29#if !defined(__PCTOOL__) || defined(CHECKWPS)
30static int keymap_handle = -1; 30int core_set_keyremap(struct button_mapping* core_keymap, int count)
31
32static int core_alloc_keymap(size_t bufsz)
33{ 31{
34 keymap_handle = core_alloc_ex("key remap", bufsz, &buflib_ops_locked); 32 return action_set_keymap(core_keymap, count);
35 return keymap_handle;
36} 33}
37 34
38static void core_free_keymap(void) 35static int open_key_remap(const char *filename, int *countp)
39{ 36{
40 action_set_keymap(NULL, -1); 37 int fd = open(filename, O_RDONLY);
41 if (keymap_handle > 0) /* free old buffer */ 38 if (fd < 0)
39 return fd;
40
41 size_t fsize = filesize(fd);
42 int count = fsize / sizeof(struct button_mapping);
43 if (count == 0 || (size_t)(count * sizeof(struct button_mapping)) != fsize)
42 { 44 {
43 keymap_handle = core_free(keymap_handle); 45 logf("core_keyremap: bad filesize %d / %lu", count, (unsigned long)fsize);
46 goto error;
44 } 47 }
45}
46
47/* Allocates buffer from core and copies keymap into it */
48int core_set_keyremap(struct button_mapping* core_keymap, int count)
49{
50 48
51 core_free_keymap(); 49 struct button_mapping header;
52 if (count > 0) 50 if(read(fd, &header, sizeof(header)) != (ssize_t)sizeof(header))
53 { 51 {
54 size_t bufsize = count * sizeof(struct button_mapping); 52 logf("core_keyremap: read error");
55 if (core_keymap != NULL && core_alloc_keymap(bufsize) > 0) 53 goto error;
56 {
57 char *buf = core_get_data(keymap_handle);
58 memcpy(buf, core_keymap, bufsize);
59 count = action_set_keymap((struct button_mapping *) buf, count);
60 }
61 else
62 count = -1;
63 } 54 }
64 return count;
65}
66
67int core_load_key_remap(const char *filename)
68{
69 char *buf;
70 int fd = -1;
71 int count = 0;
72 size_t fsize = 0;
73 core_free_keymap();
74 55
75 if (filename != NULL) 56 if (header.action_code != KEYREMAP_VERSION ||
76 count = open_key_remap(filename, &fd, &fsize); 57 header.button_code != KEYREMAP_HEADERID ||
77 while (count > 0) 58 header.pre_button_code != count)
78 { 59 {
79 if (core_alloc_keymap(fsize) <= 0) 60 logf("core_keyremap: bad header %d", count);
80 { 61 goto error;
81 count = -30;
82 logf("core_keymap: %d Failed to allocate buffer", count);
83 break;
84 }
85 buf = core_get_data(keymap_handle);
86 if (read(fd, buf, fsize) == (ssize_t) fsize)
87 {
88 count = action_set_keymap((struct button_mapping *) buf, count);
89 }
90 else
91 {
92 count = -40;
93 logf("core_keymap: %d Failed to read", count);
94 }
95 break;
96 } 62 }
63
64 *countp = count - 1;
65 return fd;
66
67 error:
97 close(fd); 68 close(fd);
98 return count; 69 return -1;
99} 70}
100 71
101int open_key_remap(const char *filename, int *fd, size_t *fsize) 72int core_load_key_remap(const char *filename)
102{ 73{
103 int count = 0; 74 int count = 0; /* gcc falsely believes this may be used uninitialized */
75 int fd = open_key_remap(filename, &count);
76 if (fd < 0)
77 return -1;
104 78
105 while (filename && fd && fsize) 79 size_t bufsize = count * sizeof(struct button_mapping);
80 int handle = core_alloc("keyremap", bufsize);
81 if (handle > 0)
106 { 82 {
107 *fsize = 0; 83 core_pin(handle);
108 *fd = open(filename, O_RDONLY); 84 if (read(fd, core_get_data(handle), bufsize) == (ssize_t)bufsize)
109 if (*fd) 85 count = action_set_keymap_handle(handle, count);
110 {
111 *fsize = filesize(*fd);
112
113 count = *fsize / sizeof(struct button_mapping);
114
115 if (count * sizeof(struct button_mapping) != *fsize)
116 {
117 count = -10;
118 logf("core_keymap: %d Size mismatch", count);
119 break;
120 }
121 86
122 if (count > 1) 87 core_unpin(handle);
123 {
124 struct button_mapping header = {0};
125 read(*fd, &header, sizeof(struct button_mapping));
126 if (KEYREMAP_VERSION == header.action_code &&
127 KEYREMAP_HEADERID == header.button_code &&
128 header.pre_button_code == count)
129 {
130 count--;
131 *fsize -= sizeof(struct button_mapping);
132 }
133 else /* Header mismatch */
134 {
135 count = -20;
136 logf("core_keymap: %d Header mismatch", count);
137 break;
138 }
139 }
140 }
141 break;
142 } 88 }
89
90 close(fd);
143 return count; 91 return count;
144} 92}
145 93
diff --git a/apps/core_keymap.h b/apps/core_keymap.h
index dad9875364..2077daa685 100644
--- a/apps/core_keymap.h
+++ b/apps/core_keymap.h
@@ -34,13 +34,6 @@
34/* Allocates core buffer, copies keymap to allow buttons for actions to be remapped*/ 34/* Allocates core buffer, copies keymap to allow buttons for actions to be remapped*/
35int core_set_keyremap(struct button_mapping* core_keymap, int count); 35int core_set_keyremap(struct button_mapping* core_keymap, int count);
36 36
37/* open_key_remap(filename , *fd (you must close file_descriptor), *fsize)
38 * checks/strips header and returns remaining count
39 * fd is opened and set to first record
40 * filesize contains the size of the remaining records
41*/
42int open_key_remap(const char *filename, int *fd, size_t *filesize);
43
44/* load a remap file to allow buttons for actions to be remapped */ 37/* load a remap file to allow buttons for actions to be remapped */
45int core_load_key_remap(const char *filename); 38int core_load_key_remap(const char *filename);
46 39