pspdev/sdk/net/simple_prx porting from 1.50 to 3.xx

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
mypspdev
Posts: 178
Joined: Wed Jul 11, 2007 10:30 pm

pspdev/sdk/net/simple_prx porting from 1.50 to 3.xx

Post by mypspdev »

exports.exp as it is without changes required

New Makefile:

Code: Select all

TARGET = netsample
OBJS = main.o

PRX_EXPORTS=exports.exp
BUILD_PRX=1

USE_KERNEL_LIBC=1
USE_KERNEL_LIBS=1

INCDIR = 
CFLAGS = -O0 -G0 -Wall -g
CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti
ASFLAGS = $(CFLAGS)

LDFLAGS = -mno-crt0 -nostartfiles

LIBDIR =

PSPSDK=$(shell psp-config --pspsdk-path)
include $(PSPSDK)/lib/build.mak
New main.c for prx:

Code: Select all

#include <pspkernel.h>
#include <pspdebug.h>
#include <pspsdk.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pspnet.h>
#include <pspnet_inet.h>
#include <pspnet_apctl.h>
#include <pspnet_resolver.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <errno.h>

#define MODULE_NAME "NetSample"
#define HELLO_MSG   "Hello there. Type away.\r\n"

PSP_MODULE_INFO&#40;MODULE_NAME, 0x1006, 1, 1&#41;;
PSP_MAIN_THREAD_ATTR&#40;0&#41;;
PSP_MAIN_THREAD_NAME&#40;"NetSample"&#41;;

#define SERVER_PORT 23

int make_socket&#40;uint16_t port&#41;
&#123;
	int sock;
	int ret;
	struct sockaddr_in name;

	sock = socket&#40;PF_INET, SOCK_STREAM, 0&#41;;
	if&#40;sock < 0&#41;
	&#123;
		return -1;
	&#125;

	name.sin_family = AF_INET;
	name.sin_port = htons&#40;port&#41;;
	name.sin_addr.s_addr = htonl&#40;INADDR_ANY&#41;;
	ret = bind&#40;sock, &#40;struct sockaddr *&#41; &name, sizeof&#40;name&#41;&#41;;
	if&#40;ret < 0&#41;
	&#123;
		return -1;
	&#125;

	return sock;
&#125;

/* Start a simple tcp echo server */
void start_server&#40;const char *szIpAddr&#41;
&#123;
	int ret;
	int sock;
	int new = -1;
	struct sockaddr_in client;
	size_t size;
	int readbytes;
	char data&#91;1024&#93;;
	fd_set set;
	fd_set setsave;

	/* Create a socket for listening */
	sock = make_socket&#40;SERVER_PORT&#41;;
	if&#40;sock < 0&#41;
	&#123;
		printf&#40;"Error creating server socket\n"&#41;;
		return;
	&#125;

	ret = listen&#40;sock, 1&#41;;
	if&#40;ret < 0&#41;
	&#123;
		printf&#40;"Error calling listen\n"&#41;;
		return;
	&#125;

	printf&#40;"Listening for connections ip %s port %d\n", szIpAddr, SERVER_PORT&#41;;

	FD_ZERO&#40;&set&#41;;
	FD_SET&#40;sock, &set&#41;;
	setsave = set;

	while&#40;1&#41;
	&#123;
		int i;
		set = setsave;
		if&#40;select&#40;FD_SETSIZE, &set, NULL, NULL, NULL&#41; < 0&#41;
		&#123;
			printf&#40;"select error\n"&#41;;
			return;
		&#125;

		for&#40;i = 0; i < FD_SETSIZE; i++&#41;
		&#123;
			if&#40;FD_ISSET&#40;i, &set&#41;&#41;
			&#123;
				int val = i;

				if&#40;val == sock&#41;
				&#123;
					new = accept&#40;sock, &#40;struct sockaddr *&#41; &client, &size&#41;;
					if&#40;new < 0&#41;
					&#123;
						printf&#40;"Error in accept %s\n", strerror&#40;errno&#41;&#41;;
						close&#40;sock&#41;;
						return;
					&#125;

					printf&#40;"New connection %d from %s&#58;%d\n", val, 
							inet_ntoa&#40;client.sin_addr&#41;,
							ntohs&#40;client.sin_port&#41;&#41;;

					write&#40;new, HELLO_MSG, strlen&#40;HELLO_MSG&#41;&#41;;

					FD_SET&#40;new, &setsave&#41;;
				&#125;
				else
				&#123;
					readbytes = read&#40;val, data, sizeof&#40;data&#41;&#41;;
					if&#40;readbytes <= 0&#41;
					&#123;
						printf&#40;"Socket %d closed\n", val&#41;;
						FD_CLR&#40;val, &setsave&#41;;
						close&#40;val&#41;;
					&#125;
					else
					&#123;
						write&#40;val, data, readbytes&#41;;
						printf&#40;"%.*s", readbytes, data&#41;;
					&#125;
				&#125;
			&#125;
		&#125;
	&#125;

	close&#40;sock&#41;;
&#125;

/* Connect to an access point */
int connect_to_apctl&#40;int config&#41;
&#123;
	int err;
	int stateLast = -1;

	/* Connect using the first profile */
	err = sceNetApctlConnect&#40;config&#41;;
	if &#40;err != 0&#41;
	&#123;
		printf&#40;MODULE_NAME "&#58; sceNetApctlConnect returns %08X\n", err&#41;;
		return 0;
	&#125;

	printf&#40;MODULE_NAME "&#58; Connecting...\n"&#41;;
	while &#40;1&#41;
	&#123;
		int state;
		err = sceNetApctlGetState&#40;&state&#41;;
		if &#40;err != 0&#41;
		&#123;
			printf&#40;MODULE_NAME "&#58; sceNetApctlGetState returns $%x\n", err&#41;;
			break;
		&#125;
		if &#40;state > stateLast&#41;
		&#123;
			printf&#40;"  connection state %d of 4\n", state&#41;;
			stateLast = state;
		&#125;
		if &#40;state == 4&#41;
			break;  // connected with static IP

		// wait a little before polling again
		sceKernelDelayThread&#40;50*1000&#41;; // 50ms
	&#125;
	printf&#40;MODULE_NAME "&#58; Connected!\n"&#41;;

	if&#40;err != 0&#41;
	&#123;
		return 0;
	&#125;

	return 1;
&#125;

/* Simple thread */
int main&#40;int argc, char **argv&#41;
&#123;
	int err;

	do
	&#123;
		if&#40;&#40;err = pspSdkInetInit&#40;&#41;&#41;&#41;
		&#123;
			printf&#40;MODULE_NAME "&#58; Error, could not initialise the network %08X\n", err&#41;;
			break;
		&#125;

		if&#40;connect_to_apctl&#40;1&#41;&#41;
		&#123;
			// connected, get my IPADDR and run test
			char szMyIPAddr&#91;32&#93;;
			if &#40;sceNetApctlGetInfo&#40;8, szMyIPAddr&#41; != 0&#41;
				strcpy&#40;szMyIPAddr, "unknown IP address"&#41;;

			start_server&#40;szMyIPAddr&#41;;
		&#125;
	&#125;
	while&#40;0&#41;;

	sceKernelSleepThread&#40;&#41;;

	return 0;
&#125;
int module_start&#40;SceSize args, void *argp&#41; 
&#123;
	return 0;
&#125;

int module_stop&#40;SceSize args, void *argp&#41;
&#123;
	&#40;void&#41; pspSdkInetTerm&#40;&#41;;

	return 0;
&#125;

/*
int module_stop&#40;&#41;
&#123;
	return 0;
&#125;
*/
I've errors when run make: a lot of undefined reference.

It does not happen if I delete from Makefile:

USE_KERNEL_LIBC=1
USE_KERNEL_LIBS=1

How to avoid the problem? thanks
Hellcat
Posts: 83
Joined: Wed Jan 24, 2007 2:52 pm

Post by Hellcat »

Yap, sounds familiar....
When compiling against kernel libraries most user functions stay out.
And it doesn't help much to put them back in (with adding the libs to the makefile).... 3.xx kernel is pretty restrictive, it's doesn't allow much user functions used from kernel modules.

I just have four days of headache behind me fighting with 3.xx kernel.

Put all your code in a simple usermode module and make another one (kernel mode, this time) that exports some functions that "channel" or "bridge" you over.
You call your exported function, that does the kernel calls.
And it's best to keep it minimum.

I think I also read the network stuff doesn't need kernel on higher FWs anymore.... is that right?
mypspdev
Posts: 178
Joined: Wed Jul 11, 2007 10:30 pm

Post by mypspdev »

Hi!
here is where I am.

TARGET: I'd like to run a server
WAY: re-using the /net/simple_prx example with the technique used for sio (see post)

I've created the simple.prx:

simple server prx main:

Code: Select all

/*
 * PSP Software Development Kit - http&#58;//www.pspdev.org
 * -----------------------------------------------------------------------
 * Licensed under the BSD license, see LICENSE in PSPSDK root for details.
 *
 * main.c - Simple prx based network example. Must load the net modules
 * before running.
 *
 * Copyright &#40;c&#41; 2005 James F <[email protected]>
 * Some small parts &#40;c&#41; 2005 PSPPet
 *
 * $Id&#58; main.c 1887 2006-05-01 03&#58;54&#58;06Z jim $
 * $HeadURL&#58; svn&#58;//svn.pspdev.org/psp/trunk/pspsdk/src/samples/net/simple_prx/main.c $
 */
#include <pspkernel.h>
#include <pspdebug.h>
#include <pspsdk.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pspnet.h>
#include <pspnet_inet.h>
#include <pspnet_apctl.h>
#include <pspnet_resolver.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <errno.h>

#define MODULE_NAME "NetSample"
#define HELLO_MSG   "Hello there. Type away.\r\n"

PSP_MODULE_INFO&#40;MODULE_NAME, 0x1006, 1, 1&#41;;
PSP_MAIN_THREAD_ATTR&#40;0&#41;;
PSP_MAIN_THREAD_NAME&#40;"NetSample"&#41;;

#define SERVER_PORT 23

int make_socket&#40;uint16_t port&#41;
&#123;
	int sock;
	int ret;
	struct sockaddr_in name;

	sock = socket&#40;PF_INET, SOCK_STREAM, 0&#41;;
	if&#40;sock < 0&#41;
	&#123;
		return -1;
	&#125;

	name.sin_family = AF_INET;
	name.sin_port = htons&#40;port&#41;;
	name.sin_addr.s_addr = htonl&#40;INADDR_ANY&#41;;
	ret = bind&#40;sock, &#40;struct sockaddr *&#41; &name, sizeof&#40;name&#41;&#41;;
	if&#40;ret < 0&#41;
	&#123;
		return -1;
	&#125;

	return sock;
&#125;

/* Start a simple tcp echo server */
void start_server&#40;const char *szIpAddr&#41;
&#123;
	int ret;
	int sock;
	int new = -1;
	struct sockaddr_in client;
	size_t size;
	int readbytes;
	char data&#91;1024&#93;;
	fd_set set;
	fd_set setsave;

	/* Create a socket for listening */
	sock = make_socket&#40;SERVER_PORT&#41;;
	if&#40;sock < 0&#41;
	&#123;
		printf&#40;"Error creating server socket\n"&#41;;
		return;
	&#125;

	ret = listen&#40;sock, 1&#41;;
	if&#40;ret < 0&#41;
	&#123;
		printf&#40;"Error calling listen\n"&#41;;
		return;
	&#125;

	printf&#40;"Listening for connections ip %s port %d\n", szIpAddr, SERVER_PORT&#41;;

	FD_ZERO&#40;&set&#41;;
	FD_SET&#40;sock, &set&#41;;
	setsave = set;

	while&#40;1&#41;
	&#123;
		int i;
		set = setsave;
		if&#40;select&#40;FD_SETSIZE, &set, NULL, NULL, NULL&#41; < 0&#41;
		&#123;
			printf&#40;"select error\n"&#41;;
			return;
		&#125;

		for&#40;i = 0; i < FD_SETSIZE; i++&#41;
		&#123;
			if&#40;FD_ISSET&#40;i, &set&#41;&#41;
			&#123;
				int val = i;

				if&#40;val == sock&#41;
				&#123;
					new = accept&#40;sock, &#40;struct sockaddr *&#41; &client, &size&#41;;
					if&#40;new < 0&#41;
					&#123;
						printf&#40;"Error in accept %s\n", strerror&#40;errno&#41;&#41;;
						close&#40;sock&#41;;
						return;
					&#125;

					printf&#40;"New connection %d from %s&#58;%d\n", val, 
							inet_ntoa&#40;client.sin_addr&#41;,
							ntohs&#40;client.sin_port&#41;&#41;;

					write&#40;new, HELLO_MSG, strlen&#40;HELLO_MSG&#41;&#41;;

					FD_SET&#40;new, &setsave&#41;;
				&#125;
				else
				&#123;
					readbytes = read&#40;val, data, sizeof&#40;data&#41;&#41;;
					if&#40;readbytes <= 0&#41;
					&#123;
						printf&#40;"Socket %d closed\n", val&#41;;
						FD_CLR&#40;val, &setsave&#41;;
						close&#40;val&#41;;
					&#125;
					else
					&#123;
						write&#40;val, data, readbytes&#41;;
						printf&#40;"%.*s", readbytes, data&#41;;
					&#125;
				&#125;
			&#125;
		&#125;
	&#125;

	close&#40;sock&#41;;
&#125;

/* Connect to an access point */
int connect_to_apctl&#40;int config&#41;
&#123;
	int err;
	int stateLast = -1;

	/* Connect using the first profile */
	err = sceNetApctlConnect&#40;config&#41;;
	if &#40;err != 0&#41;
	&#123;
		printf&#40;MODULE_NAME "&#58; sceNetApctlConnect returns %08X\n", err&#41;;
		return 0;
	&#125;

	printf&#40;MODULE_NAME "&#58; Connecting...\n"&#41;;
	while &#40;1&#41;
	&#123;
		int state;
		err = sceNetApctlGetState&#40;&state&#41;;
		if &#40;err != 0&#41;
		&#123;
			printf&#40;MODULE_NAME "&#58; sceNetApctlGetState returns $%x\n", err&#41;;
			break;
		&#125;
		if &#40;state > stateLast&#41;
		&#123;
			printf&#40;"  connection state %d of 4\n", state&#41;;
			stateLast = state;
		&#125;
		if &#40;state == 4&#41;
			break;  // connected with static IP

		// wait a little before polling again
		sceKernelDelayThread&#40;50*1000&#41;; // 50ms
	&#125;
	printf&#40;MODULE_NAME "&#58; Connected!\n"&#41;;

	if&#40;err != 0&#41;
	&#123;
		return 0;
	&#125;

	return 1;
&#125;

/* Simple thread */
int prxmain&#40;int argc, char **argv&#41;
&#123;
	int err;

	do
	&#123;
		if&#40;&#40;err = pspSdkInetInit&#40;&#41;&#41;&#41;
		&#123;
			printf&#40;MODULE_NAME "&#58; Error, could not initialise the network %08X\n", err&#41;;
			break;
		&#125;

		if&#40;connect_to_apctl&#40;1&#41;&#41;
		&#123;
			// connected, get my IPADDR and run test
			char szMyIPAddr&#91;32&#93;;
			if &#40;sceNetApctlGetInfo&#40;8, szMyIPAddr&#41; != 0&#41;
				strcpy&#40;szMyIPAddr, "unknown IP address"&#41;;

			start_server&#40;szMyIPAddr&#41;;
		&#125;
	&#125;
	while&#40;0&#41;;

	sceKernelSleepThread&#40;&#41;;

	return 0;
&#125;

int module_stop&#40;SceSize args, void *argp&#41;
&#123;
	&#40;void&#41; pspSdkInetTerm&#40;&#41;;

	return 0;
&#125;

int module_start&#40;SceSize args, void *argp&#41;
&#123;
	return 0;
&#125;

main function has been substituted with prxmain.
PSP_MODULE_INFO(MODULE_NAME, 0x1006, 1, 1);
PSP_MAIN_THREAD_ATTR(0);
has been adapted.

Makefile for generating NetSample.prx:

Code: Select all

TARGET = NetSample
OBJS = main.o

PRX_EXPORTS=exports.exp
BUILD_PRX=1

INCDIR = 
CFLAGS = -O0 -G0 -Wall -g
CXXFLAGS = $&#40;CFLAGS&#41; -fno-exceptions -fno-rtti
ASFLAGS = $&#40;CFLAGS&#41;

LIBDIR =
LDFLAGS = -mno-crt0 -nostartfiles

PSPSDK=$&#40;shell psp-config --pspsdk-path&#41;
include $&#40;PSPSDK&#41;/lib/build.mak
of course it's forbidden to set-up
USE_KERNEL_LIBC=1
USE_KERNEL_LIBS=1

Then the exports.exp with the function to be called to create the net_thread: prxmain:

Code: Select all

# Define the exports for the prx
PSP_BEGIN_EXPORTS

# These four lines are mandatory &#40;although you can add other functions like module_stop&#41;
# syslib is a psynonym for the single mandatory export.
PSP_EXPORT_START&#40;syslib, 0, 0x8000&#41;
PSP_EXPORT_FUNC&#40;module_start&#41;
PSP_EXPORT_FUNC&#40;module_stop&#41;
PSP_EXPORT_VAR&#40;module_info&#41;
PSP_EXPORT_END

# Export our function
PSP_EXPORT_START&#40;NetSample, 0, 0x4001&#41;
PSP_EXPORT_FUNC&#40;prxmain&#41;
PSP_EXPORT_END

PSP_END_EXPORTS
The prx works: I've compiled NetSample.prx and the NetSample.S.

Then I have the main 3.xx program,

Code: Select all

PSP_MODULE_INFO&#40;"MyServer", 0, 1, 0&#41;;
PSP_MAIN_THREAD_ATTR&#40;THREAD_ATTR_USER&#41;;

PSP_HEAP_SIZE_KB&#40;5000&#41;;

////////////////////////////////
// Functions imported from prx&#58;
////////////////////////////////
int prxmain&#40;void&#41;;
with load and call:

Code: Select all

void NetSample&#40;&#41;
&#123;
	SceUID modid;
   	u32 oldButtons = 0;
   	pspDebugScreenInit&#40;&#41;;
   	pspDebugScreenClear&#40;&#41;;
	pspDebugScreenSetXY&#40;0, 1&#41;;
	printf&#40;"Call to exsternal PRX\n"&#41;;
	modid = pspSdkLoadStartModule&#40;"./prx/NetSample.prx", PSP_MEMORY_PARTITION_KERNEL&#41;;
	if &#40;modid < 0&#41;
	&#123;
		pspDebugScreenPrintf&#40;"Error 0x%08X loading/starting NetSample.prx.\n", modid&#41;;
        	sceKernelDelayThread&#40;5*1000*1000&#41;;
        	return -1;
	&#125;
	pspDebugScreenPrintf&#40;"Module ID %08X\n", modid&#41;;
	prxmain&#40;&#41;;
//	pspDebugScreenPrintf&#40;"Back from PRX %i\n", k&#41;;

	printf&#40;"Press START to continue\n"&#41;;
	for &#40;;;&#41;
	&#123;		
		sceCtrlReadBufferPositive&#40;&pad, 1&#41;;
		if &#40;oldButtons != pad.Buttons&#41; 
		&#123;
    			if &#40;pad.Buttons & PSP_CTRL_START&#41; 
			&#123;
				break;
			&#125;
		&#125;
		oldButtons = pad.Buttons;
		sceDisplayWaitVblankStart&#40;&#41;;
		sceKernelDelayThread&#40;50000&#41;;
	&#125;
&#125;
When running it, error loading NetSample.prx.

Any suggestion is appreciated so much ....

The same program is correctly calling another prx with a simple int value back sent.

Thanks
mypspdev
Posts: 178
Joined: Wed Jul 11, 2007 10:30 pm

Post by mypspdev »

Just tp share what I learned:

to run wifilanscan and simple (which a server on port 23), under 3.xx, just substitute net Initialization with something like:

sceUtilityLoadNetModule(1);
sceUtilityLoadNetModule(3);

thid = sceKernelCreateThread("scan_net_thread", scan_net_thread, 16, 256*1024, 0, NULL);

and do not run it as kernel mode.

Now thay've been ported to 3.xx.
Post Reply