mirror of
https://github.com/joel16/VitaShell.git
synced 2024-11-27 13:50:22 +00:00
Merge pull request #267 from cxziaho/master
Added QR Code scanner and file downloader
This commit is contained in:
commit
01949af3b4
2
.gitignore
vendored
2
.gitignore
vendored
@ -8,4 +8,4 @@
|
||||
*.sfo
|
||||
*.velf
|
||||
*.vpk
|
||||
build
|
||||
build
|
@ -68,11 +68,13 @@ add_executable(VitaShell
|
||||
main_context.c
|
||||
init.c
|
||||
usb.c
|
||||
qr.c
|
||||
io_process.c
|
||||
makezip.c
|
||||
package_installer.c
|
||||
refresh.c
|
||||
network_update.c
|
||||
network_download.c
|
||||
context_menu.c
|
||||
archive.c
|
||||
photo.c
|
||||
@ -129,6 +131,7 @@ target_link_libraries(VitaShell
|
||||
z
|
||||
m
|
||||
c
|
||||
quirc
|
||||
onigmo
|
||||
unrar
|
||||
stdc++
|
||||
@ -138,12 +141,14 @@ target_link_libraries(VitaShell
|
||||
SceAppUtil_stub
|
||||
SceAudio_stub
|
||||
SceAudiodec_stub
|
||||
SceCamera_stub
|
||||
SceCommonDialog_stub
|
||||
SceCtrl_stub
|
||||
SceDisplay_stub
|
||||
SceGxm_stub
|
||||
SceIme_stub
|
||||
SceHttp_stub
|
||||
SceLibKernel_stub
|
||||
SceMtpIfDriver_stub
|
||||
SceMusicExport_stub
|
||||
SceNet_stub
|
||||
|
3
init.c
3
init.c
@ -21,6 +21,7 @@
|
||||
#include "file.h"
|
||||
#include "package_installer.h"
|
||||
#include "utils.h"
|
||||
#include "qr.h"
|
||||
|
||||
#include "audio/vita_audio.h"
|
||||
|
||||
@ -357,6 +358,7 @@ void initVitaShell() {
|
||||
initVita2dLib();
|
||||
initSceAppUtil();
|
||||
initNet();
|
||||
initQR();
|
||||
|
||||
// Init power tick thread
|
||||
initPowerTickThread();
|
||||
@ -379,6 +381,7 @@ void finishVitaShell() {
|
||||
finishNet();
|
||||
finishSceAppUtil();
|
||||
finishVita2dLib();
|
||||
finishQR();
|
||||
vitaAudioShutdown();
|
||||
|
||||
// Unload modules
|
||||
|
@ -223,6 +223,12 @@ void loadLanguage(int id) {
|
||||
LANGUAGE_ENTRY(USB_CONNECTION_NOT_AVAILABLE),
|
||||
LANGUAGE_ENTRY(USB_WAIT_ATTACH),
|
||||
|
||||
// QR strings
|
||||
LANGUAGE_ENTRY(QR_SCANNING),
|
||||
LANGUAGE_ENTRY(QR_OPEN_WEBSITE),
|
||||
LANGUAGE_ENTRY(QR_CONFIRM_INSTALL),
|
||||
LANGUAGE_ENTRY(QR_SHOW_CONTENTS),
|
||||
|
||||
// Others
|
||||
LANGUAGE_ENTRY(IMC0_MOUNTED),
|
||||
LANGUAGE_ENTRY(SAFE_MODE),
|
||||
|
@ -181,6 +181,12 @@ enum LanguageContainer {
|
||||
USB_UMA0_MOUNTED,
|
||||
USB_UX0_MOUNTED,
|
||||
USB_UX0_UMOUNTED,
|
||||
|
||||
// QR strings
|
||||
QR_SCANNING,
|
||||
QR_OPEN_WEBSITE,
|
||||
QR_CONFIRM_INSTALL,
|
||||
QR_SHOW_CONTENTS,
|
||||
|
||||
// Others
|
||||
IMC0_MOUNTED,
|
||||
|
94
main.c
94
main.c
@ -24,6 +24,7 @@
|
||||
#include "makezip.h"
|
||||
#include "package_installer.h"
|
||||
#include "network_update.h"
|
||||
#include "network_download.h"
|
||||
#include "context_menu.h"
|
||||
#include "archive.h"
|
||||
#include "photo.h"
|
||||
@ -42,6 +43,7 @@
|
||||
#include "coredump.h"
|
||||
#include "archiveRAR.h"
|
||||
#include "usb.h"
|
||||
#include "qr.h"
|
||||
|
||||
int _newlib_heap_size_user = 128 * 1024 * 1024;
|
||||
|
||||
@ -1021,6 +1023,22 @@ static int dialogSteps() {
|
||||
break;
|
||||
}
|
||||
|
||||
case DIALOG_STEP_INSTALL_CONFIRMED_QR:
|
||||
{
|
||||
if (msg_result == MESSAGE_DIALOG_RESULT_RUNNING) {
|
||||
InstallArguments args;
|
||||
args.file = getLastDownloadQR();
|
||||
|
||||
setDialogStep(DIALOG_STEP_INSTALLING);
|
||||
|
||||
SceUID thid = sceKernelCreateThread("install_thread", (SceKernelThreadEntry)install_thread, 0x40, 0x100000, 0, 0, NULL);
|
||||
if (thid >= 0)
|
||||
sceKernelStartThread(thid, sizeof(InstallArguments), &args);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DIALOG_STEP_INSTALL_WARNING:
|
||||
{
|
||||
if (msg_result == MESSAGE_DIALOG_RESULT_YES) {
|
||||
@ -1109,6 +1127,73 @@ static int dialogSteps() {
|
||||
launchAppByUriExit("VSUPDATER");
|
||||
setDialogStep(DIALOG_STEP_NONE);
|
||||
break;
|
||||
|
||||
|
||||
case DIALOG_STEP_QR:
|
||||
{
|
||||
if (msg_result == MESSAGE_DIALOG_RESULT_FINISHED) {
|
||||
setDialogStep(DIALOG_STEP_NONE);
|
||||
setScannedQR(0);
|
||||
} else if (scannedQR()) {
|
||||
setDialogStep(DIALOG_STEP_QR_DONE);
|
||||
sceMsgDialogClose();
|
||||
setScannedQR(0);
|
||||
stopQR();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case DIALOG_STEP_QR_DONE:
|
||||
{
|
||||
if (msg_result == MESSAGE_DIALOG_RESULT_FINISHED) {
|
||||
stopQR();
|
||||
SceUID thid = sceKernelCreateThread("qr_scan_thread", (SceKernelThreadEntry)qr_scan_thread, 0x10000100, 0x100000, 0, 0, NULL);
|
||||
if (thid >= 0)
|
||||
sceKernelStartThread(thid, 0, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
case DIALOG_STEP_QR_CONFIRM:
|
||||
{
|
||||
if (msg_result == MESSAGE_DIALOG_RESULT_YES) {
|
||||
initMessageDialog(MESSAGE_DIALOG_PROGRESS_BAR, language_container[DOWNLOADING]);
|
||||
setDialogStep(DIALOG_STEP_QR_DOWNLOADING);
|
||||
} else if (msg_result == MESSAGE_DIALOG_RESULT_NO) {
|
||||
setDialogStep(DIALOG_STEP_NONE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case DIALOG_STEP_QR_DOWNLOADED:
|
||||
{
|
||||
if (msg_result == MESSAGE_DIALOG_RESULT_FINISHED) {
|
||||
initMessageDialog(MESSAGE_DIALOG_PROGRESS_BAR, language_container[INSTALLING]);
|
||||
setDialogStep(DIALOG_STEP_INSTALL_CONFIRMED_QR);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case DIALOG_STEP_QR_OPEN_WEBSITE:
|
||||
{
|
||||
if (msg_result == MESSAGE_DIALOG_RESULT_YES) {
|
||||
sceAppMgrLaunchAppByUri(0x20000, getLastQR());
|
||||
setDialogStep(DIALOG_STEP_NONE);
|
||||
} else if (msg_result == MESSAGE_DIALOG_RESULT_NO) {
|
||||
setDialogStep(DIALOG_STEP_NONE);
|
||||
} else if (msg_result == MESSAGE_DIALOG_RESULT_FINISHED) {
|
||||
sceAppMgrLaunchAppByUri(0x20000, getLastQR());
|
||||
setDialogStep(DIALOG_STEP_NONE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case DIALOG_STEP_QR_SHOW_CONTENTS:
|
||||
{
|
||||
if (msg_result == MESSAGE_DIALOG_RESULT_FINISHED) {
|
||||
setDialogStep(DIALOG_STEP_NONE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return refresh;
|
||||
@ -1162,7 +1247,14 @@ static int fileBrowserMenuCtrl() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// QR
|
||||
if (hold2_buttons & SCE_CTRL_LTRIGGER && hold2_buttons & SCE_CTRL_RTRIGGER && enabledQR()) {
|
||||
startQR();
|
||||
initMessageDialog(MESSAGE_DIALOG_QR_CODE, language_container[QR_SCANNING]);
|
||||
setDialogStep(DIALOG_STEP_QR);
|
||||
}
|
||||
|
||||
// Move
|
||||
if (hold_buttons & SCE_CTRL_UP || hold2_buttons & SCE_CTRL_LEFT_ANALOG_UP) {
|
||||
int old_pos = base_pos+rel_pos;
|
||||
|
16
main.h
16
main.h
@ -157,10 +157,17 @@
|
||||
// Uncommon dialog
|
||||
#define UNCOMMON_DIALOG_PROGRESS_BAR_BOX_WIDTH 420.0f
|
||||
#define UNCOMMON_DIALOG_PROGRESS_BAR_HEIGHT 8.0f
|
||||
#define MSG_DIALOG_MODE_QR_SCAN 10
|
||||
|
||||
// QR Camera
|
||||
#define CAM_WIDTH 640
|
||||
#define CAM_HEIGHT 360
|
||||
|
||||
// Max entries
|
||||
#define MAX_QR_LENGTH 1024
|
||||
#define MAX_POSITION 16
|
||||
#define MAX_ENTRIES 17
|
||||
#define MAX_URL_LENGTH 128
|
||||
|
||||
#define BIG_BUFFER_SIZE 16 * 1024 * 1024
|
||||
|
||||
@ -214,6 +221,7 @@ enum DialogSteps {
|
||||
|
||||
DIALOG_STEP_INSTALL_QUESTION,
|
||||
DIALOG_STEP_INSTALL_CONFIRMED,
|
||||
DIALOG_STEP_INSTALL_CONFIRMED_QR,
|
||||
DIALOG_STEP_INSTALL_WARNING,
|
||||
DIALOG_STEP_INSTALL_WARNING_AGREED,
|
||||
DIALOG_STEP_INSTALLING,
|
||||
@ -231,6 +239,14 @@ enum DialogSteps {
|
||||
|
||||
DIALOG_STEP_SETTINGS_AGREEMENT,
|
||||
DIALOG_STEP_SETTINGS_STRING,
|
||||
|
||||
DIALOG_STEP_QR,
|
||||
DIALOG_STEP_QR_DONE,
|
||||
DIALOG_STEP_QR_CONFIRM,
|
||||
DIALOG_STEP_QR_DOWNLOADING,
|
||||
DIALOG_STEP_QR_DOWNLOADED,
|
||||
DIALOG_STEP_QR_OPEN_WEBSITE,
|
||||
DIALOG_STEP_QR_SHOW_CONTENTS,
|
||||
};
|
||||
|
||||
extern FileList file_list, mark_list, copy_list, install_list;
|
||||
|
@ -48,6 +48,12 @@ int initMessageDialog(int type, const char *msg, ...) {
|
||||
|
||||
param.progBarParam = &progress_bar_param;
|
||||
param.mode = SCE_MSG_DIALOG_MODE_PROGRESS_BAR;
|
||||
} else if (type == MESSAGE_DIALOG_QR_CODE) {
|
||||
static SceMsgDialogUserMessageParam user_message_param;
|
||||
memset(&user_message_param, 0, sizeof(SceMsgDialogUserMessageParam));
|
||||
user_message_param.msg = (SceChar8 *)message_string;
|
||||
param.userMsgParam = &user_message_param;
|
||||
param.mode = MSG_DIALOG_MODE_QR_SCAN;
|
||||
} else {
|
||||
static SceMsgDialogUserMessageParam user_message_param;
|
||||
memset(&user_message_param, 0, sizeof(SceMsgDialogUserMessageParam));
|
||||
|
@ -26,6 +26,7 @@
|
||||
#define MESSAGE_DIALOG_RESULT_YES 4
|
||||
|
||||
#define MESSAGE_DIALOG_PROGRESS_BAR 5
|
||||
#define MESSAGE_DIALOG_QR_CODE 6
|
||||
|
||||
int initMessageDialog(int type, const char *msg, ...);
|
||||
int isMessageDialogRunning();
|
||||
|
226
network_download.c
Normal file
226
network_download.c
Normal file
@ -0,0 +1,226 @@
|
||||
/*
|
||||
VitaShell
|
||||
Copyright (C) 2015-2017, TheFloW
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "main.h"
|
||||
#include "io_process.h"
|
||||
#include "network_download.h"
|
||||
#include "package_installer.h"
|
||||
#include "archive.h"
|
||||
#include "file.h"
|
||||
#include "message_dialog.h"
|
||||
#include "language.h"
|
||||
#include "utils.h"
|
||||
|
||||
#define VITASHELL_USER_AGENT "VitaShell/1.00 libhttp/1.1"
|
||||
|
||||
int getDownloadFileSize(const char *src, uint64_t *size) {
|
||||
int res;
|
||||
int statusCode;
|
||||
int tmplId = -1, connId = -1, reqId = -1;
|
||||
|
||||
res = sceHttpCreateTemplate(VITASHELL_USER_AGENT, SCE_HTTP_VERSION_1_1, SCE_TRUE);
|
||||
if (res < 0)
|
||||
goto ERROR_EXIT;
|
||||
|
||||
tmplId = res;
|
||||
|
||||
res = sceHttpCreateConnectionWithURL(tmplId, src, SCE_TRUE);
|
||||
if (res < 0)
|
||||
goto ERROR_EXIT;
|
||||
|
||||
connId = res;
|
||||
|
||||
res = sceHttpCreateRequestWithURL(connId, SCE_HTTP_METHOD_GET, src, 0);
|
||||
if (res < 0)
|
||||
goto ERROR_EXIT;
|
||||
|
||||
reqId = res;
|
||||
|
||||
res = sceHttpSendRequest(reqId, NULL, 0);
|
||||
if (res < 0)
|
||||
goto ERROR_EXIT;
|
||||
|
||||
res = sceHttpGetStatusCode(reqId, &statusCode);
|
||||
if (res < 0)
|
||||
goto ERROR_EXIT;
|
||||
|
||||
if (statusCode == 200) {
|
||||
res = sceHttpGetResponseContentLength(reqId, size);
|
||||
}
|
||||
|
||||
ERROR_EXIT:
|
||||
if (reqId >= 0)
|
||||
sceHttpDeleteRequest(reqId);
|
||||
|
||||
if (connId >= 0)
|
||||
sceHttpDeleteConnection(connId);
|
||||
|
||||
if (tmplId >= 0)
|
||||
sceHttpDeleteTemplate(tmplId);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int downloadFile(const char *src, const char *dst, FileProcessParam *param) {
|
||||
int res;
|
||||
int statusCode;
|
||||
int tmplId = -1, connId = -1, reqId = -1;
|
||||
SceUID fd = -1;
|
||||
int ret = 1;
|
||||
|
||||
res = sceHttpCreateTemplate(VITASHELL_USER_AGENT, SCE_HTTP_VERSION_1_1, SCE_TRUE);
|
||||
if (res < 0)
|
||||
goto ERROR_EXIT;
|
||||
|
||||
tmplId = res;
|
||||
|
||||
res = sceHttpCreateConnectionWithURL(tmplId, src, SCE_TRUE);
|
||||
if (res < 0)
|
||||
goto ERROR_EXIT;
|
||||
|
||||
connId = res;
|
||||
|
||||
res = sceHttpCreateRequestWithURL(connId, SCE_HTTP_METHOD_GET, src, 0);
|
||||
if (res < 0)
|
||||
goto ERROR_EXIT;
|
||||
|
||||
reqId = res;
|
||||
|
||||
res = sceHttpSendRequest(reqId, NULL, 0);
|
||||
if (res < 0)
|
||||
goto ERROR_EXIT;
|
||||
|
||||
res = sceHttpGetStatusCode(reqId, &statusCode);
|
||||
if (res < 0)
|
||||
goto ERROR_EXIT;
|
||||
|
||||
if (statusCode == 200) {
|
||||
res = sceIoOpen(dst, SCE_O_WRONLY | SCE_O_CREAT | SCE_O_TRUNC, 0777);
|
||||
if (res < 0)
|
||||
goto ERROR_EXIT;
|
||||
|
||||
fd = res;
|
||||
|
||||
uint8_t buf[4096];
|
||||
|
||||
while (1) {
|
||||
int read = sceHttpReadData(reqId, buf, sizeof(buf));
|
||||
|
||||
if (read < 0) {
|
||||
res = read;
|
||||
break;
|
||||
}
|
||||
|
||||
if (read == 0)
|
||||
break;
|
||||
|
||||
int written = sceIoWrite(fd, buf, read);
|
||||
|
||||
if (written < 0) {
|
||||
res = written;
|
||||
break;
|
||||
}
|
||||
|
||||
if (param) {
|
||||
if (param->value)
|
||||
(*param->value) += read;
|
||||
|
||||
if (param->SetProgress)
|
||||
param->SetProgress(param->value ? *param->value : 0, param->max);
|
||||
|
||||
if (param->cancelHandler && param->cancelHandler()) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ERROR_EXIT:
|
||||
if (fd >= 0)
|
||||
sceIoClose(fd);
|
||||
|
||||
if (reqId >= 0)
|
||||
sceHttpDeleteRequest(reqId);
|
||||
|
||||
if (connId >= 0)
|
||||
sceHttpDeleteConnection(connId);
|
||||
|
||||
if (tmplId >= 0)
|
||||
sceHttpDeleteTemplate(tmplId);
|
||||
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int downloadFileProcess(const char *url, const char *dest, int successStep) {
|
||||
SceUID thid = -1;
|
||||
|
||||
// Lock power timers
|
||||
powerLock();
|
||||
|
||||
// Set progress to 0%
|
||||
sceMsgDialogProgressBarSetValue(SCE_MSG_DIALOG_PROGRESSBAR_TARGET_BAR_DEFAULT, 0);
|
||||
sceKernelDelayThread(DIALOG_WAIT); // Needed to see the percentage
|
||||
|
||||
// File size
|
||||
uint64_t size = 0;
|
||||
getDownloadFileSize(url, &size);
|
||||
|
||||
// Update thread
|
||||
thid = createStartUpdateThread(size, 1);
|
||||
|
||||
// Download
|
||||
uint64_t value = 0;
|
||||
|
||||
FileProcessParam param;
|
||||
param.value = &value;
|
||||
param.max = size;
|
||||
param.SetProgress = SetProgress;
|
||||
param.cancelHandler = cancelHandler;
|
||||
|
||||
int res = downloadFile(url, dest, ¶m);
|
||||
if (res <= 0) {
|
||||
sceIoRemove(dest);
|
||||
closeWaitDialog();
|
||||
setDialogStep(DIALOG_STEP_CANCELLED);
|
||||
errorDialog(res);
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
// Set progress to 100%
|
||||
sceMsgDialogProgressBarSetValue(SCE_MSG_DIALOG_PROGRESSBAR_TARGET_BAR_DEFAULT, 100);
|
||||
sceKernelDelayThread(COUNTUP_WAIT);
|
||||
|
||||
// Close
|
||||
if (successStep != 0) {
|
||||
sceMsgDialogClose();
|
||||
setDialogStep(successStep);
|
||||
}
|
||||
|
||||
EXIT:
|
||||
if (thid >= 0)
|
||||
sceKernelWaitThreadEnd(thid, NULL, NULL);
|
||||
|
||||
// Unlock power timers
|
||||
powerUnlock();
|
||||
|
||||
return sceKernelExitDeleteThread(0);
|
||||
}
|
32
network_download.h
Normal file
32
network_download.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
VitaShell
|
||||
Copyright (C) 2015-2017, TheFloW
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* network_download
|
||||
* same as network_update.h // network_update.c
|
||||
* just modified to download any file from url, destination and successStep (0 for no step)
|
||||
*/
|
||||
|
||||
#ifndef __NETWORK_DOWNLOAD_H__
|
||||
#define __NETWORK_DOWNLOAD_H__
|
||||
|
||||
int getDownloadFileSize(const char *src, uint64_t *size);
|
||||
int downloadFile(const char *src, const char *dst, FileProcessParam *param);
|
||||
int downloadFileProcess(const char *url, const char *dest, int successStep);
|
||||
|
||||
#endif
|
206
network_update.c
206
network_update.c
@ -19,6 +19,7 @@
|
||||
#include "main.h"
|
||||
#include "io_process.h"
|
||||
#include "network_update.h"
|
||||
#include "network_download.h"
|
||||
#include "package_installer.h"
|
||||
#include "archive.h"
|
||||
#include "file.h"
|
||||
@ -31,212 +32,11 @@
|
||||
#define VITASHELL_UPDATE_FILE "ux0:VitaShell/internal/VitaShell.vpk"
|
||||
#define VITASHELL_VERSION_FILE "ux0:VitaShell/internal/version.bin"
|
||||
|
||||
#define VITASHELL_USER_AGENT "VitaShell/1.00 libhttp/1.1"
|
||||
|
||||
extern unsigned char _binary_resources_updater_eboot_bin_start;
|
||||
extern unsigned char _binary_resources_updater_eboot_bin_size;
|
||||
extern unsigned char _binary_resources_updater_param_bin_start;
|
||||
extern unsigned char _binary_resources_updater_param_bin_size;
|
||||
|
||||
int getDownloadFileSize(const char *src, uint64_t *size) {
|
||||
int res;
|
||||
int statusCode;
|
||||
int tmplId = -1, connId = -1, reqId = -1;
|
||||
|
||||
res = sceHttpCreateTemplate(VITASHELL_USER_AGENT, SCE_HTTP_VERSION_1_1, SCE_TRUE);
|
||||
if (res < 0)
|
||||
goto ERROR_EXIT;
|
||||
|
||||
tmplId = res;
|
||||
|
||||
res = sceHttpCreateConnectionWithURL(tmplId, src, SCE_TRUE);
|
||||
if (res < 0)
|
||||
goto ERROR_EXIT;
|
||||
|
||||
connId = res;
|
||||
|
||||
res = sceHttpCreateRequestWithURL(connId, SCE_HTTP_METHOD_GET, src, 0);
|
||||
if (res < 0)
|
||||
goto ERROR_EXIT;
|
||||
|
||||
reqId = res;
|
||||
|
||||
res = sceHttpSendRequest(reqId, NULL, 0);
|
||||
if (res < 0)
|
||||
goto ERROR_EXIT;
|
||||
|
||||
res = sceHttpGetStatusCode(reqId, &statusCode);
|
||||
if (res < 0)
|
||||
goto ERROR_EXIT;
|
||||
|
||||
if (statusCode == 200) {
|
||||
res = sceHttpGetResponseContentLength(reqId, size);
|
||||
}
|
||||
|
||||
ERROR_EXIT:
|
||||
if (reqId >= 0)
|
||||
sceHttpDeleteRequest(reqId);
|
||||
|
||||
if (connId >= 0)
|
||||
sceHttpDeleteConnection(connId);
|
||||
|
||||
if (tmplId >= 0)
|
||||
sceHttpDeleteTemplate(tmplId);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int downloadFile(const char *src, const char *dst, FileProcessParam *param) {
|
||||
int res;
|
||||
int statusCode;
|
||||
int tmplId = -1, connId = -1, reqId = -1;
|
||||
SceUID fd = -1;
|
||||
int ret = 1;
|
||||
|
||||
res = sceHttpCreateTemplate(VITASHELL_USER_AGENT, SCE_HTTP_VERSION_1_1, SCE_TRUE);
|
||||
if (res < 0)
|
||||
goto ERROR_EXIT;
|
||||
|
||||
tmplId = res;
|
||||
|
||||
res = sceHttpCreateConnectionWithURL(tmplId, src, SCE_TRUE);
|
||||
if (res < 0)
|
||||
goto ERROR_EXIT;
|
||||
|
||||
connId = res;
|
||||
|
||||
res = sceHttpCreateRequestWithURL(connId, SCE_HTTP_METHOD_GET, src, 0);
|
||||
if (res < 0)
|
||||
goto ERROR_EXIT;
|
||||
|
||||
reqId = res;
|
||||
|
||||
res = sceHttpSendRequest(reqId, NULL, 0);
|
||||
if (res < 0)
|
||||
goto ERROR_EXIT;
|
||||
|
||||
res = sceHttpGetStatusCode(reqId, &statusCode);
|
||||
if (res < 0)
|
||||
goto ERROR_EXIT;
|
||||
|
||||
if (statusCode == 200) {
|
||||
res = sceIoOpen(dst, SCE_O_WRONLY | SCE_O_CREAT | SCE_O_TRUNC, 0777);
|
||||
if (res < 0)
|
||||
goto ERROR_EXIT;
|
||||
|
||||
fd = res;
|
||||
|
||||
uint8_t buf[4096];
|
||||
|
||||
while (1) {
|
||||
int read = sceHttpReadData(reqId, buf, sizeof(buf));
|
||||
|
||||
if (read < 0) {
|
||||
res = read;
|
||||
break;
|
||||
}
|
||||
|
||||
if (read == 0)
|
||||
break;
|
||||
|
||||
int written = sceIoWrite(fd, buf, read);
|
||||
|
||||
if (written < 0) {
|
||||
res = written;
|
||||
break;
|
||||
}
|
||||
|
||||
if (param) {
|
||||
if (param->value)
|
||||
(*param->value) += read;
|
||||
|
||||
if (param->SetProgress)
|
||||
param->SetProgress(param->value ? *param->value : 0, param->max);
|
||||
|
||||
if (param->cancelHandler && param->cancelHandler()) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ERROR_EXIT:
|
||||
if (fd >= 0)
|
||||
sceIoClose(fd);
|
||||
|
||||
if (reqId >= 0)
|
||||
sceHttpDeleteRequest(reqId);
|
||||
|
||||
if (connId >= 0)
|
||||
sceHttpDeleteConnection(connId);
|
||||
|
||||
if (tmplId >= 0)
|
||||
sceHttpDeleteTemplate(tmplId);
|
||||
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int downloadProcess(char *version_string) {
|
||||
SceUID thid = -1;
|
||||
|
||||
// Lock power timers
|
||||
powerLock();
|
||||
|
||||
// Set progress to 0%
|
||||
sceMsgDialogProgressBarSetValue(SCE_MSG_DIALOG_PROGRESSBAR_TARGET_BAR_DEFAULT, 0);
|
||||
sceKernelDelayThread(DIALOG_WAIT); // Needed to see the percentage
|
||||
|
||||
// Download url
|
||||
char url[128];
|
||||
snprintf(url, sizeof(url), BASE_ADDRESS "/%s/VitaShell.vpk", version_string);
|
||||
|
||||
// File size
|
||||
uint64_t size = 0;
|
||||
getDownloadFileSize(url, &size);
|
||||
|
||||
// Update thread
|
||||
thid = createStartUpdateThread(size, 1);
|
||||
|
||||
// Download
|
||||
uint64_t value = 0;
|
||||
|
||||
FileProcessParam param;
|
||||
param.value = &value;
|
||||
param.max = size;
|
||||
param.SetProgress = SetProgress;
|
||||
param.cancelHandler = cancelHandler;
|
||||
|
||||
int res = downloadFile(url, VITASHELL_UPDATE_FILE, ¶m);
|
||||
if (res <= 0) {
|
||||
closeWaitDialog();
|
||||
setDialogStep(DIALOG_STEP_CANCELLED);
|
||||
errorDialog(res);
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
// Set progress to 100%
|
||||
sceMsgDialogProgressBarSetValue(SCE_MSG_DIALOG_PROGRESSBAR_TARGET_BAR_DEFAULT, 100);
|
||||
sceKernelDelayThread(COUNTUP_WAIT);
|
||||
|
||||
// Close
|
||||
sceMsgDialogClose();
|
||||
|
||||
setDialogStep(DIALOG_STEP_DOWNLOADED);
|
||||
|
||||
EXIT:
|
||||
if (thid >= 0)
|
||||
sceKernelWaitThreadEnd(thid, NULL, NULL);
|
||||
|
||||
// Unlock power timers
|
||||
powerUnlock();
|
||||
|
||||
return sceKernelExitDeleteThread(0);
|
||||
}
|
||||
|
||||
int network_update_thread(SceSize args, void *argp) {
|
||||
sceHttpsDisableOption(SCE_HTTPS_FLAG_SERVER_VERIFY);
|
||||
|
||||
@ -277,8 +77,10 @@ int network_update_thread(SceSize args, void *argp) {
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
char url[128];
|
||||
snprintf(url, sizeof(url), BASE_ADDRESS "/%s/VitaShell.vpk", version_string);
|
||||
// Yes
|
||||
return downloadProcess(version_string);
|
||||
return downloadFileProcess(url, VITASHELL_UPDATE_FILE, DIALOG_STEP_DOWNLOADED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
247
qr.c
Normal file
247
qr.c
Normal file
@ -0,0 +1,247 @@
|
||||
/*
|
||||
VitaShell
|
||||
Copyright (C) 2015-2017, TheFloW
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qr.h"
|
||||
|
||||
#include <psp2/kernel/processmgr.h>
|
||||
#include <psp2/kernel/threadmgr.h>
|
||||
#include <psp2/camera.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <quirc.h>
|
||||
#include <vita2d.h>
|
||||
|
||||
#include "main.h"
|
||||
#include "io_process.h"
|
||||
#include "network_download.h"
|
||||
#include "package_installer.h"
|
||||
#include "archive.h"
|
||||
#include "file.h"
|
||||
#include "message_dialog.h"
|
||||
#include "language.h"
|
||||
#include "utils.h"
|
||||
|
||||
static int qr_enabled;
|
||||
|
||||
static struct quirc *qr;
|
||||
static uint32_t* qr_data;
|
||||
static int qr_next;
|
||||
|
||||
static vita2d_texture *camera_tex;
|
||||
|
||||
static SceCameraInfo cam_info;
|
||||
static SceCameraRead cam_info_read;
|
||||
|
||||
static char last_qr[MAX_QR_LENGTH];
|
||||
static char last_download[MAX_QR_LENGTH];
|
||||
static int last_qr_len;
|
||||
static int qr_scanned = 0;
|
||||
|
||||
static SceUID thid;
|
||||
|
||||
int qr_thread() {
|
||||
qr = quirc_new();
|
||||
quirc_resize(qr, CAM_WIDTH, CAM_HEIGHT);
|
||||
qr_next = 1;
|
||||
while (1) {
|
||||
sceKernelDelayThread(10);
|
||||
if (qr_next == 0 && qr_scanned == 0) {
|
||||
uint8_t *image;
|
||||
int w, h;
|
||||
image = quirc_begin(qr, &w, &h);
|
||||
uint32_t colourRGBA;
|
||||
int i;
|
||||
for (i = 0; i < w*h; i++) {
|
||||
colourRGBA = qr_data[i];
|
||||
image[i] = ((colourRGBA & 0x000000FF) + ((colourRGBA & 0x0000FF00) >> 8) + ((colourRGBA & 0x00FF0000) >> 16)) / 3;
|
||||
}
|
||||
quirc_end(qr);
|
||||
int num_codes = quirc_count(qr);
|
||||
if (num_codes > 0) {
|
||||
struct quirc_code code;
|
||||
struct quirc_data data;
|
||||
quirc_decode_error_t err;
|
||||
|
||||
quirc_extract(qr, 0, &code);
|
||||
err = quirc_decode(&code, &data);
|
||||
if (err) {
|
||||
} else {
|
||||
memcpy(last_qr, data.payload, data.payload_len);
|
||||
last_qr_len = data.payload_len;
|
||||
qr_scanned = 1;
|
||||
}
|
||||
}
|
||||
qr_next = 1;
|
||||
sceKernelDelayThread(250000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int qr_scan_thread(SceSize args, void *argp) {
|
||||
if (last_qr_len > 4) {
|
||||
if (!(last_qr[last_qr_len-4] == '.' && last_qr[last_qr_len-3] == 'v' && last_qr[last_qr_len-2] == 'p' && last_qr[last_qr_len-1] == 'k')) {
|
||||
if (last_qr[0] == 'h' && last_qr[1] == 't' && last_qr[2] == 't' && last_qr[3] == 'p') {
|
||||
initMessageDialog(SCE_MSG_DIALOG_BUTTON_TYPE_OK_CANCEL, language_container[QR_OPEN_WEBSITE], last_qr);
|
||||
setDialogStep(DIALOG_STEP_QR_OPEN_WEBSITE);
|
||||
} else {
|
||||
initMessageDialog(SCE_MSG_DIALOG_BUTTON_TYPE_OK, language_container[QR_SHOW_CONTENTS], last_qr);
|
||||
setDialogStep(DIALOG_STEP_QR_SHOW_CONTENTS);
|
||||
}
|
||||
return sceKernelExitDeleteThread(0);
|
||||
}
|
||||
} else {
|
||||
initMessageDialog(SCE_MSG_DIALOG_BUTTON_TYPE_OK, language_container[QR_SHOW_CONTENTS], last_qr);
|
||||
setDialogStep(DIALOG_STEP_QR_SHOW_CONTENTS);
|
||||
return sceKernelExitDeleteThread(0);
|
||||
}
|
||||
|
||||
initMessageDialog(SCE_MSG_DIALOG_BUTTON_TYPE_OK_CANCEL, language_container[QR_CONFIRM_INSTALL], last_qr);
|
||||
setDialogStep(DIALOG_STEP_QR_CONFIRM);
|
||||
|
||||
// Wait for response
|
||||
while (getDialogStep() == DIALOG_STEP_QR_CONFIRM) {
|
||||
sceKernelDelayThread(10 * 1000);
|
||||
}
|
||||
|
||||
// No
|
||||
if (getDialogStep() == DIALOG_STEP_NONE) {
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
// Yes
|
||||
char download_path[MAX_URL_LENGTH];
|
||||
char short_name[MAX_URL_LENGTH];
|
||||
int count = 0;
|
||||
|
||||
char *next;
|
||||
char *file_name = strdup(last_qr);
|
||||
while ((next = strpbrk(file_name + 1, "\\/"))) file_name = next;
|
||||
if (file_name != last_qr) file_name++;
|
||||
|
||||
char *ext = strrchr(file_name, '.');
|
||||
if (ext) {
|
||||
int len = ext-file_name;
|
||||
if (len > sizeof(short_name)-1)
|
||||
len = sizeof(short_name)-1;
|
||||
strncpy(short_name, file_name, len);
|
||||
short_name[len] = '\0';
|
||||
} else {
|
||||
strncpy(short_name, file_name, sizeof(short_name)-1);
|
||||
ext = "";
|
||||
}
|
||||
while (1) {
|
||||
if (count == 0)
|
||||
snprintf(download_path, sizeof(download_path)-1, "ux0:download/qr/%s", file_name);
|
||||
else
|
||||
snprintf(download_path, sizeof(download_path)-1, "ux0:download/qr/%s (%d)%s", short_name, count, ext);
|
||||
|
||||
SceIoStat stat;
|
||||
memset(&stat, 0, sizeof(SceIoStat));
|
||||
if (sceIoGetstat(download_path, &stat) < 0)
|
||||
break;
|
||||
count++;
|
||||
}
|
||||
|
||||
sceIoMkdir("ux0:download", 0006);
|
||||
sceIoMkdir("ux0:download/qr", 0006);
|
||||
|
||||
strcpy(last_download, download_path);
|
||||
return downloadFileProcess(last_qr, download_path, DIALOG_STEP_QR_DOWNLOADED);
|
||||
|
||||
EXIT:
|
||||
return sceKernelExitDeleteThread(0);
|
||||
}
|
||||
|
||||
int initQR() {
|
||||
SceKernelMemBlockType orig = vita2d_texture_get_alloc_memblock_type();
|
||||
vita2d_texture_set_alloc_memblock_type(SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW);
|
||||
camera_tex = vita2d_create_empty_texture(CAM_WIDTH, CAM_HEIGHT);
|
||||
vita2d_texture_set_alloc_memblock_type(orig);
|
||||
|
||||
cam_info.size = sizeof(SceCameraInfo);
|
||||
cam_info.format = SCE_CAMERA_FORMAT_ABGR;
|
||||
cam_info.resolution = SCE_CAMERA_RESOLUTION_640_360;
|
||||
cam_info.pitch = vita2d_texture_get_stride(camera_tex) - (CAM_WIDTH << 2);
|
||||
cam_info.sizeIBase = (CAM_WIDTH * CAM_HEIGHT) << 2;
|
||||
cam_info.pIBase = vita2d_texture_get_datap(camera_tex);
|
||||
cam_info.framerate = 30;
|
||||
|
||||
cam_info_read.size = sizeof(SceCameraRead);
|
||||
cam_info_read.mode = 0;
|
||||
if (sceCameraOpen(1, &cam_info) < 0) {
|
||||
qr_enabled = 0;
|
||||
vita2d_free_texture(camera_tex);
|
||||
return -1;
|
||||
}
|
||||
|
||||
thid = sceKernelCreateThread("qr_decode_thread", qr_thread, 0x40, 0x100000, 0, 0, NULL);
|
||||
if (thid >= 0) sceKernelStartThread(thid, 0, NULL);
|
||||
qr_enabled = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int finishQR() {
|
||||
sceKernelDeleteThread(thid);
|
||||
vita2d_free_texture(camera_tex);
|
||||
sceCameraClose(1);
|
||||
quirc_destroy(qr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int startQR() {
|
||||
return sceCameraStart(1);
|
||||
}
|
||||
|
||||
int stopQR() {
|
||||
return sceCameraStop(1);
|
||||
}
|
||||
|
||||
int renderCameraQR(int x, int y) {
|
||||
sceCameraRead(1, &cam_info_read);
|
||||
vita2d_draw_texture(camera_tex, x, y);
|
||||
if (qr_next) {
|
||||
qr_data = (uint32_t *)vita2d_texture_get_datap(camera_tex);
|
||||
qr_next = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *getLastQR() {
|
||||
return last_qr;
|
||||
}
|
||||
|
||||
char *getLastDownloadQR() {
|
||||
return last_download;
|
||||
}
|
||||
|
||||
int scannedQR() {
|
||||
return qr_scanned;
|
||||
}
|
||||
|
||||
void setScannedQR(int s) {
|
||||
qr_scanned = s;
|
||||
}
|
||||
|
||||
int enabledQR() {
|
||||
return qr_enabled;
|
||||
}
|
37
qr.h
Normal file
37
qr.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
VitaShell
|
||||
Copyright (C) 2015-2017, TheFloW
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __QR_H__
|
||||
#define __QR_H__
|
||||
|
||||
#include <psp2/kernel/sysmem.h>
|
||||
|
||||
int qr_scan_thread(SceSize args, void *argp);
|
||||
|
||||
int initQR();
|
||||
int finishQR();
|
||||
int startQR();
|
||||
int stopQR();
|
||||
int enabledQR();
|
||||
int scannedQR();
|
||||
int renderCameraQR(int x, int y);
|
||||
char *getLastQR();
|
||||
char *getLastDownloadQR();
|
||||
void setScannedQR(int scanned);
|
||||
|
||||
#endif
|
@ -162,6 +162,12 @@ USB_NOT_CONNECTED = "Connect this system to a PC system using
|
||||
USB_CONNECTION_NOT_AVAILABLE = "USB connection is not available on this device."
|
||||
USB_WAIT_ATTACH = "Please attach an USB flash drive to continue.\If it has already been attached, please detach\and reattach it."
|
||||
|
||||
# QR strings
|
||||
QR_SCANNING = "Scanning for QR Codes..."
|
||||
QR_OPEN_WEBSITE = "Do you want to open this URL:\%s"
|
||||
QR_CONFIRM_INSTALL = "Do you want to install this package:\%s"
|
||||
QR_SHOW_CONTENTS = "QR Code Says:\%s"
|
||||
|
||||
# Others
|
||||
IMC0_MOUNTED = "imc0: mounted."
|
||||
SAFE_MODE = "SAFE MODE"
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "language.h"
|
||||
#include "utils.h"
|
||||
#include "uncommon_dialog.h"
|
||||
#include "qr.h"
|
||||
|
||||
typedef struct {
|
||||
int dialog_status;
|
||||
@ -82,7 +83,12 @@ static void calculateDialogBoxSize() {
|
||||
uncommon_dialog.width = UNCOMMON_DIALOG_PROGRESS_BAR_BOX_WIDTH;
|
||||
uncommon_dialog.height += 2.0f*FONT_Y_SPACE;
|
||||
}
|
||||
|
||||
|
||||
if (uncommon_dialog.mode == MSG_DIALOG_MODE_QR_SCAN) {
|
||||
uncommon_dialog.width = CAM_WIDTH + 30;
|
||||
uncommon_dialog.height += CAM_HEIGHT;
|
||||
}
|
||||
|
||||
// More space for buttons
|
||||
if (uncommon_dialog.buttonType != SCE_MSG_DIALOG_BUTTON_TYPE_NONE)
|
||||
uncommon_dialog.height += 2.0f*FONT_Y_SPACE;
|
||||
@ -126,6 +132,13 @@ int sceMsgDialogInit(const SceMsgDialogParam *param) {
|
||||
break;
|
||||
}
|
||||
|
||||
case MSG_DIALOG_MODE_QR_SCAN:
|
||||
{
|
||||
strncpy(uncommon_dialog.msg, (char *)param->userMsgParam->msg, sizeof(uncommon_dialog.msg)-1);
|
||||
uncommon_dialog.buttonType = SCE_MSG_DIALOG_BUTTON_TYPE_CANCEL;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
@ -332,6 +345,11 @@ int drawUncommonDialog() {
|
||||
|
||||
string_y += 2.0f*FONT_Y_SPACE;
|
||||
}
|
||||
|
||||
if (uncommon_dialog.mode == MSG_DIALOG_MODE_QR_SCAN) {
|
||||
renderCameraQR(uncommon_dialog.x + 15, string_y + 10);
|
||||
string_y += CAM_HEIGHT;
|
||||
}
|
||||
|
||||
switch (uncommon_dialog.buttonType) {
|
||||
case SCE_MSG_DIALOG_BUTTON_TYPE_OK:
|
||||
|
Loading…
Reference in New Issue
Block a user