#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <netinet/in.h>

#include "riscos.h"
#include "module-internet.h"

#define FIOSLEEPTW   0x80046679


bool Internet::SWI (unsigned int swinum, bool xbit)
{
  int ret;

//  printf("Internet: %x - %x %x %x\n", swinum, READ_REG(0), READ_REG(1), READ_REG(2));

  switch (swinum)
    {
    case Socket_Close:
      ret = close(READ_REG (0));
      break;

    case Socket_Creat:
      ret = socket(READ_REG (0), READ_REG (1), READ_REG(2));
      break;

    case Socket_Connect:
      {
        struct sockaddr *roaddr = (struct sockaddr *)READ_REG (1);

        if (roaddr->sa_family & 0xff00)
          roaddr->sa_family = roaddr->sa_family >> 8;

        ret = connect(READ_REG (0), roaddr, READ_REG(2));

        break;
      }

    case Socket_Recv:
      {
         ret = recv(READ_REG(0), (void *)READ_REG(1), READ_REG (2), READ_REG(3));
         break;
      }

    case Socket_Ioctl:
      {
        uint32_t cmd = READ_REG(1);

        if (cmd == FIOSLEEPTW)
          ret = 0;
        else
          ret = ioctl(READ_REG (0), READ_REG (1), READ_REG(2));
      }
      break;

    case Socket_Read:
      {
         ret = read(READ_REG(0), (void *)READ_REG(1), READ_REG (2));
         break;
      }

    case Socket_Send:
      ret = send(READ_REG (0), (void *)READ_REG (1), READ_REG (2), READ_REG(3));
      break;

    case Socket_Select:
      {
        fd_set *r, *w, *e;
        struct timeval *tv;

        r = (fd_set *)READ_REG(1);
        w = (fd_set *)READ_REG(2);
        e = (fd_set *)READ_REG(3);
        tv = (struct timeval *)READ_REG(4);

        ret = select(READ_REG(0), r, w, e, tv);
        break;
      }

    case Socket_Write:
      ret = write(READ_REG (0), (void *)READ_REG (1), READ_REG (2));
      break;

    case Socket_Recvfrom:
    case Socket_Recvfrom_1:
      {
         ret = recvfrom(READ_REG(0), (void *)READ_REG(1), READ_REG (2), READ_REG(3),
                        (struct sockaddr *)READ_REG (4),
                        (socklen_t *)READ_REG (5));
         break;                
      }

    default:
      return false;
      break;
    }

    if (ret < 0) {
      perror("Internet Error");
      BuildError(1, strerror(errno));
    }
    else
      WRITE_REG (0, ret);

  return true;
}


