diff --git a/stratosphere/tma/Makefile b/stratosphere/tma/Makefile
index 7dc12f262..9d0408a23 100644
--- a/stratosphere/tma/Makefile
+++ b/stratosphere/tma/Makefile
@@ -19,7 +19,7 @@ include $(DEVKITPRO)/libnx/switch_rules
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
-SOURCES := source
+SOURCES := source source/test
DATA := data
INCLUDES := include ../../common/include
EXEFS_SRC := exefs_src
diff --git a/stratosphere/tma/client/Main.py b/stratosphere/tma/client/Main.py
index b1469a1e1..3ea150608 100644
--- a/stratosphere/tma/client/Main.py
+++ b/stratosphere/tma/client/Main.py
@@ -12,12 +12,17 @@
# You should have received a copy of the GNU General Public License
from UsbConnection import UsbConnection
import sys, time
+from Packet import Packet
+import ServiceId
def main(argc, argv):
with UsbConnection(None) as c:
print 'Waiting for connection...'
c.wait_connected()
print 'Connected!'
+ c.intf.send_packet(Packet().set_service(ServiceId.ATMOSPHERE_TEST_SERVICE).set_task(0x01000000).write_u32(0x40))
+ resp = c.intf.read_packet()
+ print resp.body
return 0
if __name__ == '__main__':
diff --git a/stratosphere/tma/client/ServiceId.py b/stratosphere/tma/client/ServiceId.py
index 5207d2ae3..27b314f93 100644
--- a/stratosphere/tma/client/ServiceId.py
+++ b/stratosphere/tma/client/ServiceId.py
@@ -24,4 +24,6 @@ USB_SEND_HOST_INFO = hash("USBSendHostInfo")
USB_CONNECT = hash("USBConnect")
USB_DISCONNECT = hash("USBDisconnect")
+ATMOSPHERE_TEST_SERVICE = hash("AtmosphereTestService")
+
\ No newline at end of file
diff --git a/stratosphere/tma/source/test/atmosphere_test_service.cpp b/stratosphere/tma/source/test/atmosphere_test_service.cpp
new file mode 100644
index 000000000..7433882fa
--- /dev/null
+++ b/stratosphere/tma/source/test/atmosphere_test_service.cpp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018 Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+#include
+
+#include "atmosphere_test_service.hpp"
+#include "atmosphere_test_task.hpp"
+
+TmaTask *AtmosphereTestService::NewTask(TmaPacket *packet) {
+ auto new_task = new AtmosphereTestTask(this->manager);
+ new_task->SetServiceId(this->GetServiceId());
+ new_task->SetTaskId(packet->GetTaskId());
+ new_task->OnStart(packet);
+ new_task->SetNeedsPackets(true);
+
+ return new_task;
+}
diff --git a/stratosphere/tma/source/test/atmosphere_test_service.hpp b/stratosphere/tma/source/test/atmosphere_test_service.hpp
new file mode 100644
index 000000000..c01e7e5cb
--- /dev/null
+++ b/stratosphere/tma/source/test/atmosphere_test_service.hpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2018 Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#pragma once
+#include
+#include
+
+#include "../tma_conn_service_ids.hpp"
+#include "../tma_service.hpp"
+
+class AtmosphereTestService : public TmaService {
+ public:
+ AtmosphereTestService(TmaServiceManager *m) : TmaService(m, "AtmosphereTestService") { }
+ virtual ~AtmosphereTestService() { }
+
+ virtual TmaTask *NewTask(TmaPacket *packet) override;
+};
\ No newline at end of file
diff --git a/stratosphere/tma/source/test/atmosphere_test_task.cpp b/stratosphere/tma/source/test/atmosphere_test_task.cpp
new file mode 100644
index 000000000..57cb6078b
--- /dev/null
+++ b/stratosphere/tma/source/test/atmosphere_test_task.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2018 Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+#include
+
+#include "atmosphere_test_task.hpp"
+
+void AtmosphereTestTask::OnStart(TmaPacket *packet) {
+ packet->Read(this->arg);
+}
+
+void AtmosphereTestTask::OnReceivePacket(TmaPacket *packet) {
+ std::abort();
+}
+
+void AtmosphereTestTask::OnSendPacket(TmaPacket *packet) {
+ for (size_t i = 0; i < this->arg && i < 0x100; i++) {
+ packet->Write('A');
+ }
+
+ this->Complete();
+}
\ No newline at end of file
diff --git a/stratosphere/tma/source/test/atmosphere_test_task.hpp b/stratosphere/tma/source/test/atmosphere_test_task.hpp
new file mode 100644
index 000000000..ebbb62b03
--- /dev/null
+++ b/stratosphere/tma/source/test/atmosphere_test_task.hpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2018 Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#pragma once
+#include
+#include
+
+#include "../tma_task.hpp"
+
+class AtmosphereTestTask : public TmaTask {
+ private:
+ u32 arg;
+ public:
+ AtmosphereTestTask(TmaServiceManager *m) : TmaTask(m) { }
+ virtual ~AtmosphereTestTask() { }
+
+ virtual void OnStart(TmaPacket *packet) override;
+ virtual void OnReceivePacket(TmaPacket *packet) override;
+ virtual void OnSendPacket(TmaPacket *packet) override;
+};
diff --git a/stratosphere/tma/source/tma_conn_usb_connection.cpp b/stratosphere/tma/source/tma_conn_usb_connection.cpp
index ed7c2f707..d7c89199f 100644
--- a/stratosphere/tma/source/tma_conn_usb_connection.cpp
+++ b/stratosphere/tma/source/tma_conn_usb_connection.cpp
@@ -81,49 +81,53 @@ void TmaUsbConnection::RecvThreadFunc(void *arg) {
res = TmaUsbComms::ReceivePacket(packet);
if (res == TmaConnResult::Success) {
- switch (packet->GetServiceId()) {
- case TmaServiceId::UsbQueryTarget: {
- this_ptr->SetConnected(false);
-
- res = this_ptr->SendQueryReply(packet);
-
- if (!this_ptr->has_woken_up) {
- this_ptr->CancelTasks();
+ if (!IsMetaService(packet->GetServiceId())) {
+ this_ptr->OnReceivePacket(packet);
+ } else {
+ switch (packet->GetServiceId()) {
+ case TmaServiceId::UsbQueryTarget: {
+ this_ptr->SetConnected(false);
+
+ res = this_ptr->SendQueryReply(packet);
+
+ if (!this_ptr->has_woken_up) {
+ this_ptr->CancelTasks();
+ }
}
- }
- break;
- case TmaServiceId::UsbSendHostInfo: {
- struct {
- u32 version;
- u32 sleeping;
- } host_info;
- packet->Read(host_info);
-
- if (!this_ptr->has_woken_up || !host_info.sleeping) {
- this_ptr->CancelTasks();
- }
- }
- break;
- case TmaServiceId::UsbConnect: {
- res = this_ptr->SendQueryReply(packet);
-
- if (res == TmaConnResult::Success) {
- this_ptr->SetConnected(true);
- this_ptr->OnConnectionEvent(ConnectionEvent::Connected);
- }
- }
- break;
- case TmaServiceId::UsbDisconnect: {
- this_ptr->SetConnected(false);
- this_ptr->OnDisconnected();
-
- this_ptr->CancelTasks();
- }
- break;
- default:
break;
+ case TmaServiceId::UsbSendHostInfo: {
+ struct {
+ u32 version;
+ u32 sleeping;
+ } host_info;
+ packet->Read(host_info);
+
+ if (!this_ptr->has_woken_up || !host_info.sleeping) {
+ this_ptr->CancelTasks();
+ }
+ }
+ break;
+ case TmaServiceId::UsbConnect: {
+ res = this_ptr->SendQueryReply(packet);
+
+ if (res == TmaConnResult::Success) {
+ this_ptr->SetConnected(true);
+ this_ptr->OnConnectionEvent(ConnectionEvent::Connected);
+ }
+ }
+ break;
+ case TmaServiceId::UsbDisconnect: {
+ this_ptr->SetConnected(false);
+ this_ptr->OnDisconnected();
+
+ this_ptr->CancelTasks();
+ }
+ break;
+ default:
+ break;
+ }
+ this_ptr->FreePacket(packet);
}
- this_ptr->FreePacket(packet);
} else {
this_ptr->FreePacket(packet);
}
diff --git a/stratosphere/tma/source/tma_service_manager.cpp b/stratosphere/tma/source/tma_service_manager.cpp
index 2d2b18cec..e684f7e0c 100644
--- a/stratosphere/tma/source/tma_service_manager.cpp
+++ b/stratosphere/tma/source/tma_service_manager.cpp
@@ -327,6 +327,8 @@ void TmaServiceManager::HandleFreeTaskWork(TmaWorkItem *work_item) {
}
void TmaServiceManager::HandleReceivePacketWork(TmaWorkItem *work_item) {
+ ON_SCOPE_EXIT { this->FreePacket(work_item->packet); };
+
/* Handle continuation packets. */
if (work_item->packet->GetContinuation()) {
this->task_list.ReceivePacket(work_item->packet);
diff --git a/stratosphere/tma/source/tma_target.cpp b/stratosphere/tma/source/tma_target.cpp
index 227975c70..9873d952d 100644
--- a/stratosphere/tma/source/tma_target.cpp
+++ b/stratosphere/tma/source/tma_target.cpp
@@ -25,6 +25,8 @@
#include "tma_target.hpp"
+#include "test/atmosphere_test_service.hpp"
+
struct TmaTargetConfig {
char configuration_id1[0x80];
char serial_number[0x80];
@@ -204,6 +206,8 @@ void TmaTarget::Initialize() {
g_active_connection = nullptr;
g_service_manager = new TmaServiceManager();
+ /* TODO: Make this better. */
+ g_service_manager->AddService(new AtmosphereTestService(g_service_manager));
RefreshTargetConfig();
diff --git a/stratosphere/tma/source/tma_task.cpp b/stratosphere/tma/source/tma_task.cpp
index a9450be76..6133b5c5e 100644
--- a/stratosphere/tma/source/tma_task.cpp
+++ b/stratosphere/tma/source/tma_task.cpp
@@ -19,14 +19,19 @@
#include "tma_task.hpp"
#include "tma_service_manager.hpp"
+void TmaTask::SetNeedsPackets(bool n) {
+ this->needs_packets = n;
+ this->manager->Tick();
+}
+
void TmaTask::Complete() {
- /* TODO: Set packet state */
+ SetNeedsPackets(false);
this->state = TmaTaskState::Complete;
this->manager->Tick();
}
void TmaTask::Cancel() {
- /* TODO: Set packet state */
+ SetNeedsPackets(false);
this->state = TmaTaskState::Canceled;
this->manager->Tick();
}
\ No newline at end of file
diff --git a/stratosphere/tma/source/tma_task.hpp b/stratosphere/tma/source/tma_task.hpp
index 9e115893f..686a7a50d 100644
--- a/stratosphere/tma/source/tma_task.hpp
+++ b/stratosphere/tma/source/tma_task.hpp
@@ -43,6 +43,7 @@ class TmaTask {
HosSignal signal;
bool owned_by_task_list = true;
bool sleep_allowed = true;
+ bool needs_packets = false;
public:
TmaTask(TmaServiceManager *m) : manager(m) { }
virtual ~TmaTask() { }
@@ -54,6 +55,7 @@ class TmaTask {
TmaTaskState GetState() const { return this->state; }
bool GetOwnedByTaskList() const { return this->owned_by_task_list; }
bool GetSleepAllowed() const { return this->sleep_allowed; }
+ bool GetNeedsPackets() const { return this->needs_packets; }
void SetPriority(u32 p) { this->priority = p; }
void SetServiceId(TmaServiceId s) { this->service_id = s; }
@@ -61,6 +63,7 @@ class TmaTask {
void SetCommand(u32 c) { this->command = c; }
void SetOwnedByTaskList(bool o) { this->owned_by_task_list = o; }
void SetSleepAllowed(bool a) { this->sleep_allowed = a; }
+ void SetNeedsPackets(bool n);
void Signal() { this->signal.Signal(); }
void ResetSignal() { this->signal.Reset(); }
diff --git a/stratosphere/tma/source/tma_task_list.cpp b/stratosphere/tma/source/tma_task_list.cpp
index 2cb28b487..36f54bef9 100644
--- a/stratosphere/tma/source/tma_task_list.cpp
+++ b/stratosphere/tma/source/tma_task_list.cpp
@@ -70,9 +70,9 @@ bool TmaTaskList::SendPacket(bool connected, TmaPacket *packet) {
switch (task->GetState()) {
case TmaTaskState::InProgress:
it++;
- if (target_task == nullptr) {
+ if (target_task == nullptr && task->GetNeedsPackets()) {
if (connected || IsMetaService(task->GetServiceId())) {
- target_task = nullptr;
+ target_task = task;
}
}
break;