freebsd-ports/devel/psptoolchain-newlib/files/patch-newlib-libc-sys-psp-pipe.c
Marcelo Araujo 8cbd3957fb The PlayStation Portable Toolchain is a collection of tools and utilities
for homebrew PSP development.

WWW: http://www.ps2dev.org

PR:		ports/132323, ports/132324, ports/132325, ports/132326
		ports/132327, ports/132328, ports/132329, ports/132330
Submitted by:	Tassilo Philipp <tphilipp@potion-studios.com>
2009-08-21 00:54:33 +00:00

308 lines
6.7 KiB
C

--- newlib/libc/sys/psp/pipe.c.orig 1970-01-01 02:00:00.000000000 +0200
+++ newlib/libc/sys/psp/pipe.c 2007-06-01 12:22:26.000000000 +0300
@@ -0,0 +1,305 @@
+/*
+ * PSP Software Development Kit - http://www.pspdev.org
+ * -----------------------------------------------------------------------
+ * Licensed under the BSD license, see LICENSE in PSPSDK root for details.
+ *
+ * pipe.c - Socket wrappers to provide similar functions to normal unix
+ *
+ * Copyright (c) 2006 Rafael Cabezas <rafpsp@gmail.com>
+ *
+ * - 20070630 Alper Akcan "anhanguera" <distchx@yahoo.com>
+ * [non]blocking read/write() fix
+ * illegal size fix for read/write()
+ *
+ */
+#include <stdio.h>
+#include <errno.h>
+#include <sys/syslimits.h>
+#include <sys/fd_set.h>
+
+#include <psptypes.h>
+#include <pspthreadman.h>
+#include <pspmodulemgr.h>
+#include <pspkerror.h>
+#include "fdman.h"
+
+/* Pipe functions */
+/* Returns how many bytes are in the pipe -- waiting to be read */
+size_t __psp_pipe_peekmsgsize(int fd)
+{
+ SceKernelMppInfo info;
+ info.size = sizeof(info);
+
+ if (!__PSP_IS_FD_OF_TYPE(fd, __PSP_DESCRIPTOR_TYPE_PIPE)) {
+ errno = EBADF;
+ return -1;
+ }
+
+ if (sceKernelReferMsgPipeStatus(__psp_descriptormap[fd]->sce_descriptor, &info) == 0) {
+ return (info.bufSize - info.freeSize);
+ }
+ else {
+ return -1;
+ }
+}
+
+int pipe(int fildes[2])
+{
+ static int iIndex = 0;
+ char name[32];
+ iIndex++;
+
+ sprintf(name, "__psp_pipe_%02d", iIndex);
+
+ SceUID uid = sceKernelCreateMsgPipe(name, PSP_MEMORY_PARTITION_USER, 0, (void *)PIPE_BUF, NULL);
+
+ if (uid >= 0) {
+ fildes[0] = __psp_fdman_get_new_descriptor();
+ if (fildes[0] != -1) {
+ __psp_descriptormap[fildes[0]]->sce_descriptor = uid;
+ __psp_descriptormap[fildes[0]]->type = __PSP_DESCRIPTOR_TYPE_PIPE;
+ }
+ else {
+ sceKernelDeleteMsgPipe(uid);
+ errno = EFAULT;
+ return -1;
+ }
+
+ fildes[1] = __psp_fdman_get_dup_descriptor(fildes[0]);
+ if (fildes[1] != -1) {
+ __psp_descriptormap[fildes[1]]->sce_descriptor = uid;
+ return 0;
+ }
+ else {
+ sceKernelDeleteMsgPipe(uid);
+ errno = EFAULT;
+ return -1;
+ }
+
+ }
+ else {
+ errno = EFAULT;
+ return -1;
+ }
+}
+
+int __psp_pipe_close(int fd)
+{
+ int ret = 0;
+
+ if (!__PSP_IS_FD_OF_TYPE(fd, __PSP_DESCRIPTOR_TYPE_PIPE)) {
+ errno = EBADF;
+ return -1;
+ }
+
+
+ if ( __psp_descriptormap[fd]->ref_count == 1 ) {
+ /**
+ * Delete a message pipe
+ *
+ * @param uid - The UID of the pipe
+ *
+ * @return 0 on success, < 0 on error
+ */
+ ret = sceKernelDeleteMsgPipe(__psp_descriptormap[fd]->sce_descriptor);
+ }
+
+ __psp_fdman_release_descriptor(fd);
+
+ if(ret < 0) {
+ return __psp_set_errno(ret);
+ }
+
+ return 0;
+}
+
+int __psp_pipe_nonblocking_read(int fd, void *buf, size_t len)
+{
+ int ret;
+ int sceuid;
+ int size;
+
+ if (!__PSP_IS_FD_OF_TYPE(fd, __PSP_DESCRIPTOR_TYPE_PIPE)) {
+ errno = EBADF;
+ return -1;
+ }
+
+ sceuid = __psp_descriptormap[fd]->sce_descriptor;
+
+ size = __psp_pipe_peekmsgsize(fd);
+ if (size > 0) {
+ if (size < len) {
+ len = size;
+ }
+ }
+ else if (size == 0) {
+ errno = EAGAIN;
+ return -1;
+ }
+ else {
+ errno = EBADF;
+ return -1;
+ }
+
+ /**
+ * Receive a message from a pipe
+ *
+ * @param uid - The UID of the pipe
+ * @param message - Pointer to the message
+ * @param size - Size of the message
+ * @param unk1 - Unknown
+ * @param unk2 - Unknown
+ * @param timeout - Timeout for receive
+ *
+ * @return 0 on success, < 0 on error
+ */
+ ret = sceKernelTryReceiveMsgPipe(sceuid, buf, len, 0, 0);
+
+ if (ret == 0) {/* Success - Data */
+ return len;
+ }
+ else if (ret == SCE_KERNEL_ERROR_MPP_EMPTY) {/* No data */
+ errno = EAGAIN;
+ return -1;
+ }
+ else {/* Error */
+ return __psp_set_errno(ret);
+ }
+}
+
+int __psp_pipe_read(int fd, void *buf, size_t len)
+{
+ int ret;
+ int sceuid;
+ int size;
+
+ if (!__PSP_IS_FD_OF_TYPE(fd, __PSP_DESCRIPTOR_TYPE_PIPE)) {
+ errno = EBADF;
+ return -1;
+ }
+
+ sceuid = __psp_descriptormap[fd]->sce_descriptor;
+
+#if 0
+ /* we should block until there is some data (or maybe for enough data),
+ * peeking the msg size should be only for nonblocking reads
+ */
+ size = __psp_pipe_peekmsgsize(fd);
+ if (size > 0) {
+ if (size < len) {
+ len = size;
+ }
+ }
+ else {
+ errno = EBADF;
+ return -1;
+ }
+#endif
+ /* if len is greater than PIPE_BUF then, MsgPipe functions returns
+ * SCE_KERNEL_ERROR_ILLEGAL_SIZE, but it should read at least
+ * PIPE_BUF bytes, and return the number of bytes read.
+ */
+ if (len > PIPE_BUF) {
+ len = PIPE_BUF;
+ }
+
+ /**
+ * Receive a message from a pipe
+ *
+ * @param uid - The UID of the pipe
+ * @param message - Pointer to the message
+ * @param size - Size of the message
+ * @param unk1 - Unknown
+ * @param unk2 - Unknown
+ * @param timeout - Timeout for receive
+ *
+ * @return 0 on success, < 0 on error
+ */
+ ret = sceKernelReceiveMsgPipe(sceuid, buf, len, 0, NULL, NULL);
+
+ if (ret == 0) {/* Success - Data */
+ return len;
+ }
+ else {/* Error */
+ return __psp_set_errno(ret);
+ }
+}
+
+int __psp_pipe_write(int fd, const void *buf, size_t len)
+{
+ int ret;
+ int sceuid;
+ char *cbuf;
+
+ if (!__PSP_IS_FD_OF_TYPE(fd, __PSP_DESCRIPTOR_TYPE_PIPE)) {
+ errno = EBADF;
+ return -1;
+ }
+
+ sceuid = __psp_descriptormap[fd]->sce_descriptor;
+
+ /* if len is greater than PIPE_BUF then, MsgPipe functions returns
+ * SCE_KERNEL_ERROR_ILLEGAL_SIZE, but it should write at least
+ * PIPE_BUF bytes, and return the number of bytes written.
+ */
+ if (len > PIPE_BUF) {
+ len = PIPE_BUF;
+ }
+
+ /**
+ * Send a message to a pipe
+ *
+ * @param uid - The UID of the pipe
+ * @param message - Pointer to the message
+ * @param size - Size of the message
+ * @param unk1 - Unknown
+ * @param unk2 - Unknown
+ * @param timeout - Timeout for send
+ *
+ * @return 0 on success, < 0 on error
+ */
+ cbuf = (char *)buf;
+ ret = sceKernelSendMsgPipe(sceuid, cbuf, len, 0, NULL, NULL);
+ if (ret == 0) {/* Success - Data */
+ return len;
+ }
+ else {/* Error */
+ return __psp_set_errno(ret);
+ }
+}
+
+int __psp_pipe_nonblocking_write(int fd, const void *buf, size_t len)
+{
+ int ret;
+ int sceuid;
+ char *cbuf;
+
+ if (!__PSP_IS_FD_OF_TYPE(fd, __PSP_DESCRIPTOR_TYPE_PIPE)) {
+ errno = EBADF;
+ return -1;
+ }
+
+ sceuid = __psp_descriptormap[fd]->sce_descriptor;
+
+ /* if len is greater than PIPE_BUF then, MsgPipe functions returns
+ * SCE_KERNEL_ERROR_ILLEGAL_SIZE, but it should write at least
+ * PIPE_BUF bytes, and return the number of bytes written.
+ */
+ if (len > PIPE_BUF) {
+ len = PIPE_BUF;
+ }
+
+ cbuf = (char *)buf;
+ ret = sceKernelTrySendMsgPipe(sceuid, cbuf, len, 0, 0);
+
+ if (ret == 0) {/* Success - Data */
+ return len;
+ }
+ else if (ret == SCE_KERNEL_ERROR_MPP_FULL) {
+ errno = EAGAIN;
+ return -1;
+ }
+ else {/* Error */
+ return __psp_set_errno(ret);
+ }
+}