Skip to content

Commit

Permalink
Merge pull request #7 from MenosGrante/lakka
Browse files Browse the repository at this point in the history
Update 2.0
  • Loading branch information
Pavel Rekun authored Jul 26, 2018
2 parents d209359 + 15cfbba commit 6c1b200
Show file tree
Hide file tree
Showing 59 changed files with 831 additions and 145 deletions.
13 changes: 8 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
# Rekado
Fusee launcher written in Kotlin and based on [NXLoader](https://github.com/DavidBuchanan314/NXLoader) injector codebase.
Payload and Lakka launcher written in Kotlin.

**Application doesn't require Root on your device.**

[SX Loader](https://sx.xecuter.com/) payload bundled as default.
[Lakka](https://github.com/lakka-switch/boot-scripts/tree/master/payloads) payload and coreboot files bundled in application.

## Usage
* Launch application
* Find a cable to connect your device to the Nintendo Switch. For proper work, this should be a cable that is designed for data transmission, not just for charging. It is advisable to use an **A-to-C** cable and an **USB OTG** adapter.
* In the **"Payloads"** category, click the **"+"** button to select preloaded payload from your device's storage. Or simply transfer your payload to the Rekado folder in the device's memory. Or you can use the default payload (**SX OS**)
* Enter your Nintendo Switch into **RCM** mode in any convenient way. Your Nintendo Switch will power on by itself when plugged in, be sure to hold **VOLUME +**
* Connect the device to the Nintendo Switch and allow permission for the **USB** access if necessary. Wait until the program prompts you to select payload and choose the one you need
* Connect the device to the Nintendo Switch and allow permission for the **USB** access if necessary. Wait until the program prompts you to select what do you want to inject, payload or Lakka. If you will select payload, than you will have to choose the one you need. If you will choose Lakka, you should simply wait for it to load.
* Wait for payload to finish loading on your console

## Download
Expand All @@ -23,11 +24,13 @@ Application doesn't require Root on your device.

**Can it brick my device/console?**

This should not happen when using the "correct" loaders. But I am not responsible for possible problems.
This should not happen when using the "correct" payloads. But I am not responsible for possible problems.

**Will Recado ever run Linux?**
**Can Rekado launch Linux?**

In the near future, this is definitely not to be expected. Maybe in the future.
Yes, starting from 2.0 update Rekado can launch Lakka distribution.

## Thanks
* [DavidBuchanan314](https://github.com/DavidBuchanan314) for creating NXLoader.
* [natinusala](https://github.com/natinusala) for creating lakka_linux_launcher.
* [ealfonso93](https://github.com/ealfonso93) for contributing in this project.
3 changes: 2 additions & 1 deletion app/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
cmake_minimum_required(VERSION 3.4.1)
add_library( native-lib SHARED src/main/cpp/native-lib.cpp )
add_library( payload_launcher SHARED src/main/cpp/payload_launcher.cpp )
add_library( lakka_launcher SHARED src/main/cpp/lakka_launcher.cpp )
include_directories(src/main/cpp/)
4 changes: 2 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ android {
applicationId "com.pavelrekun.rekado"
minSdkVersion minimumSDKVersion
targetSdkVersion currentSDKVersion
versionCode 15
versionName "1.3"
versionCode 20
versionName "2.0"

externalNativeBuild {
cmake {
Expand Down
11 changes: 11 additions & 0 deletions app/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,14 @@
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

-keepattributes *Annotation*
-keepclassmembers class * {
@org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }

# Only required if you use AsyncExecutor
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
<init>(java.lang.Throwable);
}
2 changes: 1 addition & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
android:name=".RekadoApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/RekadoBaseTheme">
Expand Down Expand Up @@ -40,7 +41,6 @@
android:exported="false"
android:label="@string/app_name"
android:noHistory="true"
android:process=":UsbEventReceiverActivityProcess"
android:taskAffinity="com.example.taskAffinityUsbEventReceiver"
android:theme="@style/RekadoInvisibleTheme">
<intent-filter>
Expand Down
Binary file added app/src/main/assets/cbfs.bin
Binary file not shown.
Binary file added app/src/main/assets/coreboot.rom
Binary file not shown.
45 changes: 45 additions & 0 deletions app/src/main/cpp/lakka_launcher.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#include <cstring>
#include <thread>
#include <chrono>
#include <jni.h>
#include <linux/usb/ch9.h>
#include <linux/usbdevice_fs.h>
#include <sys/ioctl.h>
extern "C" JNIEXPORT void JNICALL
Java_com_pavelrekun_rekado_services_lakka_LakkaLoader_nativeControlReadUnbounded(JNIEnv *env,
jclass,
jint fd,
jint size) {


char* buffer = new char[sizeof(usb_ctrlrequest) + size];
usb_ctrlrequest* header = (usb_ctrlrequest*) buffer;
header->bRequestType = USB_TYPE_STANDARD | USB_RECIP_ENDPOINT | USB_DIR_IN;
header->bRequest = 0;
header->wValue = 0;
header->wIndex = 0;
header->wLength = (__le16) size;
memset(&buffer[sizeof(usb_ctrlrequest)], 0, (size_t) size);

usbdevfs_urb* urb = (usbdevfs_urb*) new char[sizeof(usbdevfs_urb) + 1024];
memset(urb, 0, sizeof(usbdevfs_urb) + 1024);
urb->type = USBDEVFS_URB_TYPE_CONTROL;
urb->endpoint = 0;
urb->buffer = buffer;
urb->buffer_length = sizeof(usb_ctrlrequest) + size;
urb->usercontext = (void*) 0xf0f;


ioctl(fd, USBDEVFS_SUBMITURB, urb);
std::this_thread::sleep_for(std::chrono::milliseconds(100));
ioctl(fd, USBDEVFS_DISCARDURB, urb);
usbdevfs_urb* purb;
do {
if (ioctl(fd, USBDEVFS_REAPURB, &purb)) {
break;
}
} while (purb != urb);

delete[] urb;
delete[] buffer;
}
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.pavelrekun.rekado.screens.lakka_fragment

interface LakkaContract {

interface View {

fun initViews()

fun initCBFSCategory()

fun initCorebootCategory()

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.pavelrekun.rekado.screens.lakka_fragment

import android.os.Bundle
import android.support.v4.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.pavelrekun.rekado.R
import com.pavelrekun.rekado.base.BaseActivity

class LakkaFragment : Fragment() {

private lateinit var mvpView: LakkaContract.View

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.fragment_lakka, container, false)
val activity = activity as BaseActivity

mvpView = LakkaView(activity)
return view
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
mvpView.initViews()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.pavelrekun.rekado.screens.lakka_fragment

import android.support.v4.content.ContextCompat
import com.pavelrekun.rekado.R
import com.pavelrekun.rekado.base.BaseActivity
import com.pavelrekun.rekado.services.lakka.LakkaHelper
import kotlinx.android.synthetic.main.fragment_lakka.*

class LakkaView(private val activity: BaseActivity) : LakkaContract.View {

override fun initViews() {
activity.setTitle(R.string.navigation_lakka)

initCBFSCategory()
initCorebootCategory()
}

override fun initCBFSCategory() {
if (LakkaHelper.checkCBFSPresent()) {
activity.lakkaCBFSStatus.text = activity.getString(R.string.lakka_tools_ready)
activity.lakkaCBFSStatus.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_lakka_ready, 0, 0, 0)
activity.lakkaCBFSStatus.setTextColor(ContextCompat.getColor(activity, R.color.colorGreen))
} else {
activity.lakkaCBFSStatus.text = activity.getString(R.string.lakka_tools_not_ready)
activity.lakkaCBFSStatus.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_lakka_not_ready, 0, 0, 0)
activity.lakkaCBFSStatus.setTextColor(ContextCompat.getColor(activity, R.color.colorRed))
}

activity.lakkaCBFSDate.text = activity.getString(R.string.lakka_last_update, LakkaHelper.PAYLOAD_UPDATE_DATE)
}

override fun initCorebootCategory() {
if (LakkaHelper.checkCorebootPresent()) {
activity.lakkaCorebootStatus.text = activity.getString(R.string.lakka_tools_ready)
activity.lakkaCorebootStatus.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_lakka_ready, 0, 0, 0)
activity.lakkaCorebootStatus.setTextColor(ContextCompat.getColor(activity, R.color.colorGreen))
} else {
activity.lakkaCorebootStatus.text = activity.getString(R.string.lakka_tools_not_ready)
activity.lakkaCorebootStatus.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_lakka_not_ready, 0, 0, 0)
activity.lakkaCorebootStatus.setTextColor(ContextCompat.getColor(activity, R.color.colorRed))
}

activity.lakkaCorebootDate.text = activity.getString(R.string.lakka_last_update, LakkaHelper.COREBOOT_UPDATE_DATE)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import com.pavelrekun.rekado.R
import com.pavelrekun.rekado.RekadoApplication
import com.pavelrekun.rekado.data.Log
import com.pavelrekun.rekado.services.logs.LogHelper
import com.pavelrekun.rekado.services.logs.LogHelper.ERROR
import kotlinx.android.extensions.LayoutContainer
import kotlinx.android.synthetic.main.item_log.*

Expand Down Expand Up @@ -36,7 +37,7 @@ class LogsAdapter(var data: MutableList<Log>) : RecyclerView.Adapter<LogsAdapter
fun bind(log: Log) {
itemLogName.text = log.message

itemLogType.setBackgroundColor(if(log.type == 0) ContextCompat.getColor(RekadoApplication.instance.applicationContext, R.color.colorRed)
itemLogType.setBackgroundColor(if(log.type == ERROR) ContextCompat.getColor(RekadoApplication.instance.applicationContext, R.color.colorRed)
else ContextCompat.getColor(RekadoApplication.instance.applicationContext, R.color.colorGreen))
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.github.javiersantos.appupdater.enums.UpdateFrom
import com.pavelrekun.rekado.R
import com.pavelrekun.rekado.base.BaseActivity
import com.pavelrekun.rekado.screens.instructions_fragment.InstructionsFragment
import com.pavelrekun.rekado.screens.lakka_fragment.LakkaFragment
import com.pavelrekun.rekado.screens.logs_fragment.LogsFragment
import com.pavelrekun.rekado.screens.payload_fragment.PayloadsFragment
import com.pavelrekun.rekado.services.Constants
Expand Down Expand Up @@ -54,6 +55,7 @@ class MainView(private val activity: BaseActivity) : MainContract.View {

when (id) {
R.id.navigation_payloads -> fragment = PayloadsFragment()
R.id.navigation_lakka -> fragment = LakkaFragment()
R.id.navigation_instructions -> fragment = InstructionsFragment()
R.id.navigation_logs -> fragment = LogsFragment()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class PayloadsFragment : Fragment() {
mvpView.onRequestPermissionsResult(requestCode, permissions, grantResults)
}

@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
@Subscribe(threadMode = ThreadMode.MAIN)
fun onEvent(event: Events.UpdateListEvent) {
mvpView.updateList()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.pavelrekun.rekado.screens.payload_fragment

import android.Manifest
import android.content.DialogInterface
import android.content.pm.PackageManager
import android.support.v4.app.Fragment
import android.support.v7.widget.LinearLayoutManager
Expand All @@ -16,7 +15,6 @@ import com.pavelrekun.rekado.services.logs.LogHelper
import com.pavelrekun.rekado.services.payloads.PayloadHelper
import com.pavelrekun.rekado.services.utils.MemoryUtils
import com.pavelrekun.rekado.services.utils.PermissionsUtils
import com.pavelrekun.rekado.services.utils.toFile
import kotlinx.android.synthetic.main.fragment_payloads.*
import org.greenrobot.eventbus.EventBus
import java.io.File
Expand All @@ -27,8 +25,6 @@ class PayloadsView(private val activity: BaseActivity, private val fragment: Fra

private lateinit var adapter: PayloadsAdapter

private var chooserStorageInternal = true

override fun initViews() {
activity.setTitle(R.string.navigation_payloads)

Expand Down Expand Up @@ -104,13 +100,13 @@ class PayloadsView(private val activity: BaseActivity, private val fragment: Fra
}

try {
pathFile.toFile(PayloadHelper.FOLDER_PATH + "/" + payload.name)
MemoryUtils.toFile(pathFile, (PayloadHelper.FOLDER_PATH + "/" + payload.name))

EventBus.getDefault().postSticky(Events.UpdateListEvent())
LogHelper.log(1, "Added new payload: ${payload.name}")
EventBus.getDefault().post(Events.UpdateListEvent())
LogHelper.log(LogHelper.INFO, "Added new payload: ${payload.name}")
} catch (e: IOException) {
e.printStackTrace()
LogHelper.log(0, "Failed to add payload: ${payload.name}")
LogHelper.log(LogHelper.ERROR, "Failed to add payload: ${payload.name}")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ class PayloadsAdapter(var data: MutableList<Payload>) : RecyclerView.Adapter<Pay

itemPayloadRemove.setOnClickListener {
MemoryUtils.removeFile(payload.path)
EventBus.getDefault().postSticky(Events.UpdateListEvent())
LogHelper.log(1, "Payload ${payload.name} deleted!")
EventBus.getDefault().post(Events.UpdateListEvent())
LogHelper.log(LogHelper.INFO, "Payload ${payload.name} deleted!")
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ class SettingsFragment : PreferenceFragmentCompat() {
autoInjectorPayload.isEnabled = newValue as Boolean

if (newValue) {
LogHelper.log(1, "\"Auto injector\" enabled!")
LogHelper.log(LogHelper.INFO, "\"Auto injector\" enabled!")
autoInjectorEnable.setTitle(R.string.settings_auto_injector_status_title_enabled)
} else {
LogHelper.log(1, "\"Auto injector\" disabled!")
LogHelper.log(LogHelper.INFO, "\"Auto injector\" disabled!")
autoInjectorEnable.setTitle(R.string.settings_auto_injector_status_title_disabled)
}

Expand All @@ -60,7 +60,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
PayloadHelper.clearFolder()
dialog.dismiss()

LogHelper.log(1, "Payloads database cleaned!")
LogHelper.log(LogHelper.INFO, "Payloads database cleaned!")
}
true
}
Expand Down
Loading

0 comments on commit 6c1b200

Please sign in to comment.