- Updated documentation for nickel_orientation action. - Updated documentation for nickel_browser action. - Updated nickel_open:library:* action. - Updated nickel_misc:home action. - Updated symbol tests for 4.23.15505.
This commit is contained in:
3
res/doc
3
res/doc
@@ -31,11 +31,12 @@
|
|||||||
# nickel_setting - changes a setting
|
# nickel_setting - changes a setting
|
||||||
# nickel_extras - opens one of the beta features
|
# nickel_extras - opens one of the beta features
|
||||||
# nickel_browser - opens the browser
|
# nickel_browser - opens the browser
|
||||||
|
# (on firmware 4.23.15505+, you won't be able to exit the browser unless you use the "modal" option or add "menu_item:browser:Quit:nickel_misc:home" to the config)
|
||||||
# nickel_misc - other stuff which isn't significant enough for its own category
|
# nickel_misc - other stuff which isn't significant enough for its own category
|
||||||
# nickel_open - opens a view
|
# nickel_open - opens a view
|
||||||
# nickel_wifi - controls wifi (note: it doesn't wait for it to connect or disconnect, neither does it check for success)
|
# nickel_wifi - controls wifi (note: it doesn't wait for it to connect or disconnect, neither does it check for success)
|
||||||
# nickel_orientation - controls screen orientation
|
# nickel_orientation - controls screen orientation
|
||||||
# (devices without an orientation sensor need to use the kobopatch patch "Allow rotation on all devices" or set [DeveloperSettings] ForceAllowLandscape=true)
|
# (devices without an orientation sensor may need to use the kobopatch patch "Allow rotation on all devices" or set [DeveloperSettings] ForceAllowLandscape=true)
|
||||||
# (devices with an orientation sensor don't need to do anything, but can set the config setting to make this work on all views)
|
# (devices with an orientation sensor don't need to do anything, but can set the config setting to make this work on all views)
|
||||||
# (this will override the rotation icon/popup until it is set to something different or the device is rebooted)
|
# (this will override the rotation icon/popup until it is set to something different or the device is rebooted)
|
||||||
# power - gracefully controls the power state
|
# power - gracefully controls the power state
|
||||||
|
|||||||
@@ -60,6 +60,25 @@ NM_ACTION_(nickel_open) {
|
|||||||
char *arg2 = strtrim(tmp1);
|
char *arg2 = strtrim(tmp1);
|
||||||
NM_CHECK(nullptr, arg2, "could not find a : in the argument");
|
NM_CHECK(nullptr, arg2, "could not find a : in the argument");
|
||||||
|
|
||||||
|
//libnickel 4.23.15505 * _ZN11MainNavViewC1EP7QWidget
|
||||||
|
if (dlsym(RTLD_DEFAULT, "_ZN11MainNavViewC1EP7QWidget")) {
|
||||||
|
NM_LOG("nickel_open: detected firmware >15505 (new nav tab bar), checking special cases");
|
||||||
|
|
||||||
|
if (!strcmp(arg1, "library") && !strcmp(arg2, "dropbox")) {
|
||||||
|
//libnickel 4.23.15505 * _ZN14MoreController7dropboxEv
|
||||||
|
void (*MoreController_dropbox)(void*);
|
||||||
|
reinterpret_cast<void*&>(MoreController_dropbox) = dlsym(RTLD_DEFAULT, "_ZN14MoreController7dropboxEv");
|
||||||
|
NM_CHECK(nullptr, MoreController_dropbox, "could not dlsym MoreController::dropbox");
|
||||||
|
|
||||||
|
// technically, we need a MoreController, but it isn't used as of 15505, so it doesn't matter (and if it ever does, it's not going to crash in a critical place)
|
||||||
|
MoreController_dropbox(nullptr);
|
||||||
|
|
||||||
|
return nm_action_result_silent();
|
||||||
|
}
|
||||||
|
|
||||||
|
NM_LOG("nickel_open: no special handling needed for '%s:%s' on fw >15505", arg1, arg2);
|
||||||
|
}
|
||||||
|
|
||||||
const char *sym_c = nullptr; // *NavMixin constructor (subclass of QObject)
|
const char *sym_c = nullptr; // *NavMixin constructor (subclass of QObject)
|
||||||
const char *sym_d = nullptr; // *NavMixin destructor (D1, not D0 because it also tries to call delete)
|
const char *sym_d = nullptr; // *NavMixin destructor (D1, not D0 because it also tries to call delete)
|
||||||
const char *sym_f = nullptr; // *NavMixin::* function
|
const char *sym_f = nullptr; // *NavMixin::* function
|
||||||
@@ -83,7 +102,7 @@ NM_ACTION_(nickel_open) {
|
|||||||
else if (!strcmp(arg2, "series")) sym_f = "_ZN15LibraryNavMixin10showSeriesEv"; //libnickel 4.20.14601 * _ZN15LibraryNavMixin10showSeriesEv
|
else if (!strcmp(arg2, "series")) sym_f = "_ZN15LibraryNavMixin10showSeriesEv"; //libnickel 4.20.14601 * _ZN15LibraryNavMixin10showSeriesEv
|
||||||
else if (!strcmp(arg2, "shelves")) sym_f = "_ZN15LibraryNavMixin11showShelvesEv"; //libnickel 4.6 * _ZN15LibraryNavMixin11showShelvesEv
|
else if (!strcmp(arg2, "shelves")) sym_f = "_ZN15LibraryNavMixin11showShelvesEv"; //libnickel 4.6 * _ZN15LibraryNavMixin11showShelvesEv
|
||||||
else if (!strcmp(arg2, "pocket")) sym_f = "_ZN15LibraryNavMixin17showPocketLibraryEv"; //libnickel 4.6 * _ZN15LibraryNavMixin17showPocketLibraryEv
|
else if (!strcmp(arg2, "pocket")) sym_f = "_ZN15LibraryNavMixin17showPocketLibraryEv"; //libnickel 4.6 * _ZN15LibraryNavMixin17showPocketLibraryEv
|
||||||
else if (!strcmp(arg2, "dropbox")) sym_f = "_ZN15LibraryNavMixin11showDropboxEv"; //libnickel 4.18.13737 * _ZN15LibraryNavMixin11showDropboxEv
|
else if (!strcmp(arg2, "dropbox")) sym_f = "_ZN15LibraryNavMixin11showDropboxEv"; //libnickel 4.18.13737 4.22.15268 _ZN15LibraryNavMixin11showDropboxEv
|
||||||
} else if (!strcmp(arg1, "reading_life")) {
|
} else if (!strcmp(arg1, "reading_life")) {
|
||||||
sym_c = "_ZN19ReadingLifeNavMixinC1Ev"; //libnickel 4.6 * _ZN19ReadingLifeNavMixinC1Ev
|
sym_c = "_ZN19ReadingLifeNavMixinC1Ev"; //libnickel 4.6 * _ZN19ReadingLifeNavMixinC1Ev
|
||||||
sym_d = "_ZN19ReadingLifeNavMixinD1Ev"; //libnickel 4.6 * _ZN19ReadingLifeNavMixinD1Ev
|
sym_d = "_ZN19ReadingLifeNavMixinD1Ev"; //libnickel 4.6 * _ZN19ReadingLifeNavMixinD1Ev
|
||||||
@@ -104,9 +123,9 @@ NM_ACTION_(nickel_open) {
|
|||||||
NM_CHECK(nullptr, sym_d, "destructor not specified (this is a bug)");
|
NM_CHECK(nullptr, sym_d, "destructor not specified (this is a bug)");
|
||||||
NM_CHECK(nullptr, sym_f, "unknown view '%s' (in '%s:%s')", arg2, arg1, arg2);
|
NM_CHECK(nullptr, sym_f, "unknown view '%s' (in '%s:%s')", arg2, arg1, arg2);
|
||||||
|
|
||||||
void (*fn_c)(QObject *_this);
|
void (*fn_c)(void *_this);
|
||||||
void (*fn_d)(QObject *_this);
|
void (*fn_d)(void *_this);
|
||||||
void (*fn_f)(QObject *_this);
|
void (*fn_f)(void *_this);
|
||||||
|
|
||||||
reinterpret_cast<void*&>(fn_c) = dlsym(RTLD_DEFAULT, sym_c);
|
reinterpret_cast<void*&>(fn_c) = dlsym(RTLD_DEFAULT, sym_c);
|
||||||
reinterpret_cast<void*&>(fn_d) = dlsym(RTLD_DEFAULT, sym_d);
|
reinterpret_cast<void*&>(fn_d) = dlsym(RTLD_DEFAULT, sym_d);
|
||||||
@@ -117,10 +136,27 @@ NM_ACTION_(nickel_open) {
|
|||||||
NM_CHECK(nullptr, fn_f, "could not find function %s (is your firmware too old?)", sym_f);
|
NM_CHECK(nullptr, fn_f, "could not find function %s (is your firmware too old?)", sym_f);
|
||||||
NM_LOG("c: %s = %p; d: %s = %p; f: %s = %p", sym_c, fn_c, sym_d, fn_d, sym_f, fn_f);
|
NM_LOG("c: %s = %p; d: %s = %p; f: %s = %p", sym_c, fn_c, sym_d, fn_d, sym_f, fn_f);
|
||||||
|
|
||||||
QObject obj(nullptr);
|
// HACK: I don't exactly know why this is needed, but without it, most of
|
||||||
fn_c(&obj);
|
// the LibraryNavMixin ones segfault. On firmware versions before 15505, it
|
||||||
fn_f(&obj);
|
// must be initialized as a QObject (I don't understand why, though). Before
|
||||||
fn_d(&obj);
|
// 15505, I used to just declare it as a QObject on the stack like `QObject
|
||||||
|
// obj(nullptr);`, but this doesn't work anymore after 15505 because it's
|
||||||
|
// too small for the pointer to the LibraryBuilder the LibraryNavMixin now
|
||||||
|
// uses. To solve that, we allocate more than enough memory on the stack,
|
||||||
|
// then use placement new to initialize the QObject. Note that I'm not
|
||||||
|
// calling the QObject destructor (even though we should) since I don't feel
|
||||||
|
// comfortable with it because I don't totally understand how the
|
||||||
|
// LibraryNavMixin does its initialization, and there isn't a risk of there
|
||||||
|
// being signals pointing to this stack variable since the nav mixins don't
|
||||||
|
// use signals/slots or keep references to themselves.
|
||||||
|
// TODO: Figure out how this actually works.
|
||||||
|
|
||||||
|
void *obj = alloca(512);
|
||||||
|
new(obj) QObject();
|
||||||
|
|
||||||
|
fn_c(obj);
|
||||||
|
fn_f(obj);
|
||||||
|
fn_d(obj);
|
||||||
|
|
||||||
return nm_action_result_silent();
|
return nm_action_result_silent();
|
||||||
}
|
}
|
||||||
@@ -407,12 +443,16 @@ NM_ACTION_(nickel_browser) {
|
|||||||
|
|
||||||
NM_ACTION_(nickel_misc) {
|
NM_ACTION_(nickel_misc) {
|
||||||
if (!strcmp(arg, "home")) {
|
if (!strcmp(arg, "home")) {
|
||||||
//libnickel 4.6 * _ZN19StatusBarController4homeEv
|
//libnickel 4.6 * _ZN19StatusBarController4homeEv _ZN17MainNavController4homeEv
|
||||||
void (*StatusBarController_home)();
|
void (*StatusBarController_home)(void*);
|
||||||
reinterpret_cast<void*&>(StatusBarController_home) = dlsym(RTLD_DEFAULT, "_ZN19StatusBarController4homeEv");
|
void (*MainNavController_home)(void*);
|
||||||
NM_CHECK(nullptr, StatusBarController_home, "could not dlsym StatusBarController::home");
|
|
||||||
|
|
||||||
StatusBarController_home();
|
reinterpret_cast<void*&>(StatusBarController_home) = dlsym(RTLD_DEFAULT, "_ZN19StatusBarController4homeEv");
|
||||||
|
reinterpret_cast<void*&>(MainNavController_home) = dlsym(RTLD_DEFAULT, "_ZN17MainNavController4homeEv");
|
||||||
|
NM_CHECK(nullptr, StatusBarController_home || MainNavController_home, "could not dlsym StatusBarController::home (pre-4.23.15505) or MainNavController::home (4.23.15505+)");
|
||||||
|
|
||||||
|
// technically, we need an instance, but it isn't used so it doesn't matter (and if it does crash, we can fix it later as it's not critical) as of 15505
|
||||||
|
(StatusBarController_home ?: MainNavController_home)(nullptr);
|
||||||
} else if (!strcmp(arg, "rescan_books")) {
|
} else if (!strcmp(arg, "rescan_books")) {
|
||||||
//libnickel 4.13.12638 * _ZN19PlugWorkflowManager14sharedInstanceEv
|
//libnickel 4.13.12638 * _ZN19PlugWorkflowManager14sharedInstanceEv
|
||||||
PlugWorkflowManager *(*PlugWorkflowManager_sharedInstance)();
|
PlugWorkflowManager *(*PlugWorkflowManager_sharedInstance)();
|
||||||
@@ -685,7 +725,7 @@ NM_ACTION_(nickel_orientation) {
|
|||||||
|
|
||||||
NM_LOG(Device_hasOrientationSensor(dev)
|
NM_LOG(Device_hasOrientationSensor(dev)
|
||||||
? "nickel_orientation: if this didn't do anything, you may need to set [DeveloperSettings] ForceAllowLandscape=true to allow landscape orientations on all views"
|
? "nickel_orientation: if this didn't do anything, you may need to set [DeveloperSettings] ForceAllowLandscape=true to allow landscape orientations on all views"
|
||||||
: "nickel_orientation: if this didn't do anything, ensure you have applied the 'Allow rotation on all devices' kobopatch patch, or that you have set [DeveloperSettings] ForceAllowLandscape=true");
|
: "nickel_orientation: if this didn't do anything, you may need to apply the 'Allow rotation on all devices' kobopatch patch, or that you have set [DeveloperSettings] ForceAllowLandscape=true");
|
||||||
|
|
||||||
// Set the orientation.
|
// Set the orientation.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ func main() {
|
|||||||
"4.11.11982", "4.11.12019", "4.12.12111", "4.13.12638", "4.14.12777",
|
"4.11.11982", "4.11.12019", "4.12.12111", "4.13.12638", "4.14.12777",
|
||||||
"4.15.12920", "4.16.13162", "4.17.13651", "4.17.13694", "4.18.13737",
|
"4.15.12920", "4.16.13162", "4.17.13651", "4.17.13694", "4.18.13737",
|
||||||
"4.19.14123", "4.20.14601", "4.20.14617", "4.20.14622", "4.21.15015",
|
"4.19.14123", "4.20.14601", "4.20.14617", "4.20.14622", "4.21.15015",
|
||||||
"4.22.15190", "4.22.15268",
|
"4.22.15190", "4.22.15268", "4.23.15505",
|
||||||
}
|
}
|
||||||
|
|
||||||
checks := map[string]map[string][]SymCheck{}
|
checks := map[string]map[string][]SymCheck{}
|
||||||
@@ -144,7 +144,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetPatcher(version, lib string) (*patchlib.Patcher, error) {
|
func GetPatcher(version, lib string) (*patchlib.Patcher, error) {
|
||||||
resp, err := http.Get("https://github.com/pgaskin/kobopatch-patches/raw/v64/testdata/" + version + ".tar.xz")
|
resp, err := http.Get("https://github.com/pgaskin/kobopatch-patches/raw/v65/testdata/" + version + ".tar.xz")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("get kobopatch testdata for %#v: %w", version, err)
|
return nil, fmt.Errorf("get kobopatch testdata for %#v: %w", version, err)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user