mirror of
https://github.com/afska/gba-link-connection.git
synced 2026-04-26 02:02:25 -05:00
ISP calling and login completed
This commit is contained in:
parent
0f2d09229f
commit
c1f01cd5af
|
|
@ -445,12 +445,13 @@ Name | Return type | Description
|
||||||
`shutdown()` | **bool** | Gracefully shuts down the adapter, closing all connections. After some time, the state will be changed to `SHUTDOWN`, and only then it's safe to call `deactivate()`.
|
`shutdown()` | **bool** | Gracefully shuts down the adapter, closing all connections. After some time, the state will be changed to `SHUTDOWN`, and only then it's safe to call `deactivate()`.
|
||||||
`call(phoneNumber)` | **bool** | Initiates a P2P connection with a `phoneNumber`. After some time, the state will be `CALL_ESTABLISHED`, or `ACTIVE_SESSION` if the connection fails or ends. In REON/libmobile the phone number can be a number assigned by the relay server, or a 12-digit IPv4 address (for example, `"127000000001"` would be `127.0.0.1`).
|
`call(phoneNumber)` | **bool** | Initiates a P2P connection with a `phoneNumber`. After some time, the state will be `CALL_ESTABLISHED`, or `ACTIVE_SESSION` if the connection fails or ends. In REON/libmobile the phone number can be a number assigned by the relay server, or a 12-digit IPv4 address (for example, `"127000000001"` would be `127.0.0.1`).
|
||||||
`transfer(dataToSend, receivedData)` | **bool** | Requests a data transfer (up to `254` bytes) within a P2P connection and responds the received data. The `receivedData` is a pointer to a `LinkWireless::DataTransfer` struct that will be filled with data. It can point to `dataToSend`. When the transfer is completed, the `completed` field will be `true`.
|
`transfer(dataToSend, receivedData)` | **bool** | Requests a data transfer (up to `254` bytes) within a P2P connection and responds the received data. The `receivedData` is a pointer to a `LinkWireless::DataTransfer` struct that will be filled with data. It can point to `dataToSend`. When the transfer is completed, the `completed` field will be `true`.
|
||||||
`hangUp()` | **bool** | Hangs up the current P2P call.
|
`hangUp()` | **bool** | Hangs up the current P2P or ISP call. Closes all connections.
|
||||||
`readConfiguration(configurationData)` | **bool** | Retrieves the adapter configuration, and puts it in the `configurationData` struct. If the adapter has an active session, the data is already loaded, so it's instantaneous.
|
`readConfiguration(configurationData)` | **bool** | Retrieves the adapter configuration, and puts it in the `configurationData` struct. If the adapter has an active session, the data is already loaded, so it's instantaneous.
|
||||||
`getState()` | **LinkMobile::State** | Returns the current state (one of `LinkMobile::State::NEEDS_RESET`, `LinkMobile::State::PINGING`, `LinkMobile::State::WAITING_TO_START`, `LinkMobile::State::STARTING_SESSION`, `LinkMobile::State::ACTIVATING_SIO32`, `LinkMobile::State::WAITING_32BIT_SWITCH`, `LinkMobile::State::READING_CONFIGURATION`, `LinkMobile::State::SESSION_ACTIVE`, `LinkMobile::State::CALL_REQUESTED`, `LinkMobile::State::CALLING`, `LinkMobile::State::CALL_ESTABLISHED`, `LinkMobile::State::ISP_CALL_REQUESTED`, `LinkMobile::State::ISP_CALLING`, `LinkMobile::State::ISP_LOGIN`, `LinkMobile::State::ISP_ACTIVE`, `LinkMobile::State::SHUTDOWN_REQUESTED`, `LinkMobile::State::ENDING_SESSION`, `LinkMobile::State::WAITING_8BIT_SWITCH`, or `LinkMobile::State::SHUTDOWN`).
|
`getState()` | **LinkMobile::State** | Returns the current state (one of `LinkMobile::State::NEEDS_RESET`, `LinkMobile::State::PINGING`, `LinkMobile::State::WAITING_TO_START`, `LinkMobile::State::STARTING_SESSION`, `LinkMobile::State::ACTIVATING_SIO32`, `LinkMobile::State::WAITING_32BIT_SWITCH`, `LinkMobile::State::READING_CONFIGURATION`, `LinkMobile::State::SESSION_ACTIVE`, `LinkMobile::State::CALL_REQUESTED`, `LinkMobile::State::CALLING`, `LinkMobile::State::CALL_ESTABLISHED`, `LinkMobile::State::ISP_CALL_REQUESTED`, `LinkMobile::State::ISP_CALLING`, `LinkMobile::State::ISP_LOGIN`, `LinkMobile::State::ISP_ACTIVE`, `LinkMobile::State::SHUTDOWN_REQUESTED`, `LinkMobile::State::ENDING_SESSION`, `LinkMobile::State::WAITING_8BIT_SWITCH`, or `LinkMobile::State::SHUTDOWN`).
|
||||||
`getRole()` | **LinkMobile::Role** | Returns the current role in the P2P connection (one of `LinkMobile::Role::NO_P2P_CONNECTION`, `LinkMobile::Role::CALLER`, or `LinkMobile::Role::RECEIVER`).
|
`getRole()` | **LinkMobile::Role** | Returns the current role in the P2P connection (one of `LinkMobile::Role::NO_P2P_CONNECTION`, `LinkMobile::Role::CALLER`, or `LinkMobile::Role::RECEIVER`).
|
||||||
`isConfigurationValid()` | **int** | Returns whether the adapter has been configured or not. Returns `1` = yes, `0` = no, `-1` = unknown (no session active).
|
`isConfigurationValid()` | **int** | Returns whether the adapter has been configured or not. Returns `1` = yes, `0` = no, `-1` = unknown (no session active).
|
||||||
`isP2PConnected()` | **bool** | Returns `true` if a P2P call is established (the state is `CALL_ESTABLISHED`).
|
`isConnectedP2P()` | **bool** | Returns `true` if a P2P call is established (the state is `CALL_ESTABLISHED`).
|
||||||
|
`isConnectedISP()` | **bool** | Returns `true` if an ISP call is active (the state is `ISP_ACTIVE`).
|
||||||
`isSessionActive()` | **bool** | Returns `true` if the session is active.
|
`isSessionActive()` | **bool** | Returns `true` if the session is active.
|
||||||
`canShutdown()` | **bool** | Returns `true` if there's an active session and there's no previous shutdown requests.
|
`canShutdown()` | **bool** | Returns `true` if there's an active session and there's no previous shutdown requests.
|
||||||
`getDataSize()` | **LinkSPI::DataSize** | Returns the current operation mode (`LinkSPI::DataSize`).
|
`getDataSize()` | **LinkSPI::DataSize** | Returns the current operation mode (`LinkSPI::DataSize`).
|
||||||
|
|
|
||||||
|
|
@ -89,14 +89,16 @@ start:
|
||||||
output += "\nSTART = Call the ISP";
|
output += "\nSTART = Call the ISP";
|
||||||
output += "\n (A = ok)\n (SELECT = stop)";
|
output += "\n (A = ok)\n (SELECT = stop)";
|
||||||
} else {
|
} else {
|
||||||
if (linkMobile->isP2PConnected()) {
|
if (linkMobile->isConnectedP2P()) {
|
||||||
output += "\n (A = send)";
|
output += "\n (A = send)";
|
||||||
output += "\n (L = hang up)";
|
output += "\n (L = hang up)";
|
||||||
|
} else if (linkMobile->isConnectedISP()) {
|
||||||
|
output += "\n (L = hang up)";
|
||||||
}
|
}
|
||||||
output += "\n (SELECT = stop)";
|
output += "\n (SELECT = stop)";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (linkMobile->isP2PConnected()) {
|
if (linkMobile->isConnectedP2P()) {
|
||||||
if (!isConnected) {
|
if (!isConnected) {
|
||||||
isConnected = true;
|
isConnected = true;
|
||||||
outgoingData = linkMobile->getRole() == LinkMobile::Role::CALLER
|
outgoingData = linkMobile->getRole() == LinkMobile::Role::CALLER
|
||||||
|
|
@ -181,9 +183,15 @@ start:
|
||||||
linkMobile->call(number.c_str());
|
linkMobile->call(number.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// START = Call the ISP
|
||||||
|
if (didPress(KEY_START, start)) {
|
||||||
|
linkMobile->callISP("asdasd");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LinkMobile::State::CALL_ESTABLISHED: {
|
case LinkMobile::State::CALL_ESTABLISHED:
|
||||||
|
case LinkMobile::State::ISP_ACTIVE: {
|
||||||
// L = hang up
|
// L = hang up
|
||||||
if (didPress(KEY_L, l)) {
|
if (didPress(KEY_L, l)) {
|
||||||
// (6) Hang up
|
// (6) Hang up
|
||||||
|
|
@ -368,12 +376,16 @@ std::string getErrorTypeString(LinkMobile::Error::Type errorType) {
|
||||||
switch (errorType) {
|
switch (errorType) {
|
||||||
case LinkMobile::Error::Type::ADAPTER_NOT_CONNECTED:
|
case LinkMobile::Error::Type::ADAPTER_NOT_CONNECTED:
|
||||||
return "ADAPTER_NOT_CONNECTED";
|
return "ADAPTER_NOT_CONNECTED";
|
||||||
|
case LinkMobile::Error::Type::ISP_LOGIN_FAILED:
|
||||||
|
return "ISP_LOGIN_FAILED";
|
||||||
case LinkMobile::Error::Type::COMMAND_FAILED:
|
case LinkMobile::Error::Type::COMMAND_FAILED:
|
||||||
return "COMMAND_FAILED";
|
return "COMMAND_FAILED";
|
||||||
case LinkMobile::Error::Type::WEIRD_RESPONSE:
|
case LinkMobile::Error::Type::WEIRD_RESPONSE:
|
||||||
return "WEIRD_RESPONSE";
|
return "WEIRD_RESPONSE";
|
||||||
case LinkMobile::Error::Type::TIMEOUT:
|
case LinkMobile::Error::Type::TIMEOUT:
|
||||||
return "TIMEOUT";
|
return "TIMEOUT";
|
||||||
|
case LinkMobile::Error::Type::WTF:
|
||||||
|
return "WTF";
|
||||||
default:
|
default:
|
||||||
return "?";
|
return "?";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
// // (do something until `linkMobile->isSessionActive()` returns `true`)
|
// // (do something until `linkMobile->isSessionActive()` returns `true`)
|
||||||
// - 4) Call someone:
|
// - 4) Call someone:
|
||||||
// linkMobile->call("127000000001");
|
// linkMobile->call("127000000001");
|
||||||
// // (do something until `linkMobile->isP2PConnected()` returns `true`)
|
// // (do something until `linkMobile->isConnectedP2P()` returns `true`)
|
||||||
// - 5) Send/receive data:
|
// - 5) Send/receive data:
|
||||||
// LinkMobile::DataTransfer dataTransfer = { .size = 5 };
|
// LinkMobile::DataTransfer dataTransfer = { .size = 5 };
|
||||||
// for (u32 i = 0; i < 5; i++)
|
// for (u32 i = 0; i < 5; i++)
|
||||||
|
|
@ -30,6 +30,7 @@
|
||||||
// linkMobile->hangUp();
|
// linkMobile->hangUp();
|
||||||
// - 7) Turn off the adapter:
|
// - 7) Turn off the adapter:
|
||||||
// linkMobile->shutdown();
|
// linkMobile->shutdown();
|
||||||
|
// TODO: DOCUMENT ISP METHODS
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// (*) libtonc's interrupt handler sometimes ignores interrupts due to a bug.
|
// (*) libtonc's interrupt handler sometimes ignores interrupts due to a bug.
|
||||||
// That causes packet loss. You REALLY want to use libugba's instead.
|
// That causes packet loss. You REALLY want to use libugba's instead.
|
||||||
|
|
@ -169,9 +170,11 @@ class LinkMobile {
|
||||||
enum Type {
|
enum Type {
|
||||||
NONE,
|
NONE,
|
||||||
ADAPTER_NOT_CONNECTED,
|
ADAPTER_NOT_CONNECTED,
|
||||||
|
ISP_LOGIN_FAILED,
|
||||||
COMMAND_FAILED,
|
COMMAND_FAILED,
|
||||||
WEIRD_RESPONSE,
|
WEIRD_RESPONSE,
|
||||||
TIMEOUT
|
TIMEOUT,
|
||||||
|
WTF
|
||||||
};
|
};
|
||||||
|
|
||||||
Error::Type type = Error::Type::NONE;
|
Error::Type type = Error::Type::NONE;
|
||||||
|
|
@ -356,12 +359,13 @@ class LinkMobile {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Hangs up the current P2P call.
|
* @brief Hangs up the current P2P or ISP call. Closes all connections.
|
||||||
* \warning Non-blocking. Returns `true` immediately, or `false` if there's no
|
* \warning Non-blocking. Returns `true` immediately, or `false` if there's no
|
||||||
* active call or available request slots.
|
* active call or available request slots.
|
||||||
*/
|
*/
|
||||||
bool hangUp() {
|
bool hangUp() {
|
||||||
if (state != CALL_ESTABLISHED || userRequests.isFull())
|
if ((state != CALL_ESTABLISHED && state != ISP_ACTIVE) ||
|
||||||
|
userRequests.isFull())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
pushRequest(UserRequest{.type = UserRequest::Type::HANG_UP});
|
pushRequest(UserRequest{.type = UserRequest::Type::HANG_UP});
|
||||||
|
|
@ -411,7 +415,13 @@ class LinkMobile {
|
||||||
* @brief Returns `true` if a P2P call is established (the state is
|
* @brief Returns `true` if a P2P call is established (the state is
|
||||||
* `CALL_ESTABLISHED`).
|
* `CALL_ESTABLISHED`).
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] bool isP2PConnected() { return state == CALL_ESTABLISHED; }
|
[[nodiscard]] bool isConnectedP2P() { return state == CALL_ESTABLISHED; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns `true` if an ISP call is active (the state is
|
||||||
|
* `ISP_ACTIVE`).
|
||||||
|
*/
|
||||||
|
[[nodiscard]] bool isConnectedISP() { return state == ISP_ACTIVE; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns `true` if the session is active.
|
* @brief Returns `true` if the session is active.
|
||||||
|
|
@ -544,6 +554,7 @@ class LinkMobile {
|
||||||
char password[LINK_MOBILE_MAX_PASSWORD_LENGTH + 1];
|
char password[LINK_MOBILE_MAX_PASSWORD_LENGTH + 1];
|
||||||
bool commandSent;
|
bool commandSent;
|
||||||
u32 timeout;
|
u32 timeout;
|
||||||
|
bool finished;
|
||||||
};
|
};
|
||||||
|
|
||||||
union AdapterConfiguration {
|
union AdapterConfiguration {
|
||||||
|
|
@ -696,6 +707,11 @@ class LinkMobile {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (userRequests.peek().finished)
|
||||||
|
userRequests.pop();
|
||||||
|
if (userRequests.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
auto request = userRequests.peek();
|
auto request = userRequests.peek();
|
||||||
request.timeout++;
|
request.timeout++;
|
||||||
if (shouldAbortOnRequestTimeout() && request.timeout >= config.timeout)
|
if (shouldAbortOnRequestTimeout() && request.timeout >= config.timeout)
|
||||||
|
|
@ -717,6 +733,23 @@ class LinkMobile {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case UserRequest::Type::ISP_LOGIN: {
|
||||||
|
if (state != SESSION_ACTIVE && state != ISP_CALL_REQUESTED &&
|
||||||
|
state != ISP_CALLING) {
|
||||||
|
userRequests.pop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (state == SESSION_ACTIVE)
|
||||||
|
setState(ISP_CALL_REQUESTED);
|
||||||
|
|
||||||
|
if (!asyncCommand.isActive && state == ISP_CALL_REQUESTED) {
|
||||||
|
setState(ISP_CALLING);
|
||||||
|
cmdDialTelephone(adapterConfiguration.isValid()
|
||||||
|
? adapterConfiguration.fields._ispNumber1
|
||||||
|
: FALLBACK_ISP_NUMBER);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case UserRequest::Type::TRANSFER: {
|
case UserRequest::Type::TRANSFER: {
|
||||||
if (state != CALL_ESTABLISHED) {
|
if (state != CALL_ESTABLISHED) {
|
||||||
userRequests.pop();
|
userRequests.pop();
|
||||||
|
|
@ -729,7 +762,7 @@ class LinkMobile {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case UserRequest::Type::HANG_UP: {
|
case UserRequest::Type::HANG_UP: {
|
||||||
if (state != CALL_ESTABLISHED) {
|
if (state != CALL_ESTABLISHED && state != ISP_ACTIVE) {
|
||||||
userRequests.pop();
|
userRequests.pop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -913,9 +946,10 @@ class LinkMobile {
|
||||||
setState(SESSION_ACTIVE);
|
setState(SESSION_ACTIVE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!asyncCommand.respondsTo(COMMAND_TRANSFER_DATA))
|
if (!asyncCommand.respondsTo(COMMAND_TRANSFER_DATA))
|
||||||
return;
|
return;
|
||||||
|
if (userRequests.isEmpty())
|
||||||
|
return abort(Error::Type::WTF);
|
||||||
|
|
||||||
auto request = userRequests.peek();
|
auto request = userRequests.peek();
|
||||||
|
|
||||||
|
|
@ -929,12 +963,50 @@ class LinkMobile {
|
||||||
request.receive->data[i] = asyncCommand.cmd.data.bytes[1 + i];
|
request.receive->data[i] = asyncCommand.cmd.data.bytes[1 + i];
|
||||||
request.receive->size = size;
|
request.receive->size = size;
|
||||||
request.receive->completed = true;
|
request.receive->completed = true;
|
||||||
userRequests.pop();
|
request.finished = true;
|
||||||
}
|
} else
|
||||||
|
return abort(Error::Type::WTF);
|
||||||
} else {
|
} else {
|
||||||
setState(SESSION_ACTIVE);
|
setState(SESSION_ACTIVE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case ISP_CALLING: {
|
||||||
|
if (!asyncCommand.respondsTo(COMMAND_DIAL_TELEPHONE))
|
||||||
|
return;
|
||||||
|
if (userRequests.isEmpty())
|
||||||
|
return abort(Error::Type::WTF);
|
||||||
|
|
||||||
|
auto request = userRequests.peek();
|
||||||
|
|
||||||
|
if (request.type == UserRequest::ISP_LOGIN) {
|
||||||
|
if (asyncCommand.result == CommandResult::SUCCESS) {
|
||||||
|
setState(ISP_LOGIN);
|
||||||
|
cmdISPLogin(request.loginId, request.password);
|
||||||
|
}
|
||||||
|
request.finished = true;
|
||||||
|
} else
|
||||||
|
return abort(Error::Type::WTF);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ISP_LOGIN: {
|
||||||
|
if (!asyncCommand.respondsTo(COMMAND_ISP_LOGIN))
|
||||||
|
return;
|
||||||
|
if (asyncCommand.result != CommandResult::SUCCESS)
|
||||||
|
return abort(Error::Type::ISP_LOGIN_FAILED);
|
||||||
|
|
||||||
|
setState(ISP_ACTIVE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ISP_ACTIVE: {
|
||||||
|
if (asyncCommand.respondsTo(COMMAND_HANG_UP_TELEPHONE)) {
|
||||||
|
setState(SESSION_ACTIVE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: IMPLEMENT
|
||||||
|
break;
|
||||||
|
}
|
||||||
case ENDING_SESSION: {
|
case ENDING_SESSION: {
|
||||||
if (!asyncCommand.respondsTo(COMMAND_END_SESSION))
|
if (!asyncCommand.respondsTo(COMMAND_END_SESSION))
|
||||||
return;
|
return;
|
||||||
|
|
@ -968,7 +1040,7 @@ class LinkMobile {
|
||||||
|
|
||||||
void cmdEndSession() { sendCommandAsync(buildCommand(COMMAND_END_SESSION)); }
|
void cmdEndSession() { sendCommandAsync(buildCommand(COMMAND_END_SESSION)); }
|
||||||
|
|
||||||
void cmdDialTelephone(char* phoneNumber) {
|
void cmdDialTelephone(const char* phoneNumber) {
|
||||||
addData(DIAL_PHONE_FIRST_BYTE[adapterType], true);
|
addData(DIAL_PHONE_FIRST_BYTE[adapterType], true);
|
||||||
for (u32 i = 0; i < std::strlen(phoneNumber); i++)
|
for (u32 i = 0; i < std::strlen(phoneNumber); i++)
|
||||||
addData(phoneNumber[i]);
|
addData(phoneNumber[i]);
|
||||||
|
|
@ -1005,6 +1077,26 @@ class LinkMobile {
|
||||||
sendCommandAsync(buildCommand(COMMAND_READ_CONFIGURATION_DATA, true));
|
sendCommandAsync(buildCommand(COMMAND_READ_CONFIGURATION_DATA, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cmdISPLogin(const char* loginId, const char* password) {
|
||||||
|
u32 loginIdLength = std::strlen(loginId);
|
||||||
|
addData(loginIdLength, true);
|
||||||
|
for (u32 i = 0; i < loginIdLength; i++)
|
||||||
|
addData(loginId[i]);
|
||||||
|
|
||||||
|
u32 passwordLength = std::strlen(password);
|
||||||
|
addData(passwordLength);
|
||||||
|
for (u32 i = 0; i < passwordLength; i++)
|
||||||
|
addData(password[i]);
|
||||||
|
|
||||||
|
bool isConfigured = isConfigurationValid();
|
||||||
|
for (u32 i = 0; i < 4; i++)
|
||||||
|
addData(isConfigured ? adapterConfiguration.fields.primaryDNS[i] : 0);
|
||||||
|
for (u32 i = 0; i < 4; i++)
|
||||||
|
addData(isConfigured ? adapterConfiguration.fields.secondaryDNS[i] : 0);
|
||||||
|
|
||||||
|
sendCommandAsync(buildCommand(COMMAND_ISP_LOGIN, true));
|
||||||
|
}
|
||||||
|
|
||||||
void setISPNumber() {
|
void setISPNumber() {
|
||||||
static const char BCD[16] = "0123456789#*cde";
|
static const char BCD[16] = "0123456789#*cde";
|
||||||
|
|
||||||
|
|
@ -1017,6 +1109,7 @@ class LinkMobile {
|
||||||
|
|
||||||
void pushRequest(UserRequest request) {
|
void pushRequest(UserRequest request) {
|
||||||
request.timeout = 0;
|
request.timeout = 0;
|
||||||
|
request.finished = false;
|
||||||
userRequests.syncPush(request);
|
userRequests.syncPush(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user