/*
 * sunrand - Phisical random generator with /dev/audio
 * Copyright (C) 1999 Masanao Izumo <mo@goice.co.jp>
 * version 1.1
 */

/* Intarfaces: */
int sunrand_init(void);
/*   Initialize to generate random.  Open /dev/audio.  Return the file
 *   descriptor.
 */

int sunrand(void *buf, int nbytes);
/*   Generate n-bytes randoms (1 byte ramdoms/sec)
 *   It returns number of bytes are stores.  If error, it returns -1.
 */

int sunrand_bit(void);
/*   Generate 1 bit random.  sunrand_bit() returns 0 or 1.
 *   If error, it returns -1.
 */

void sunrand_end(void);
/*   End of sunrand.  Close /dev/audio.
 */

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#define BITSPARRAND 1024

static int fd = -1;

int sunrand_init(void)
{
    if(fd != -1)
	sunrand_end();
    fd = open("/dev/audio", O_RDONLY);
    return fd;
}

int sunrand_bit(void)
{
    int i, j, n;
    unsigned char bits[BITSPARRAND/8];

    if(read(fd, bits, sizeof(bits)) == -1)
	return -1;
    n = 0;
    for(i = 0; i < sizeof(bits); i++)
	for(j = 0; j < 8; j++)
	    if(bits[i] & (1u<<j))
		n = !n;
    return n;
}

int sunrand(void *buf, int nbytes)
{
    unsigned char *ptr;
    int i, j, abit, val;

    ptr = (unsigned char *)buf;
    for(i = 0; i < nbytes; i++)
    {
	val = 0;
	for(j = 0; j < 8; j++)
	{
	    if((abit = sunrand_bit()) < 0)
		return i - 1;
	    val |= abit << j;
	}
	ptr[i] = val;
    }
    return nbytes;
}

void sunrand_end(void)
{
    if(fd != -1)
    {
	close(fd);
	fd = -1;
    }
}


#if 0

#include <stdio.h>
int main(void)
{
    unsigned int rnd;
    int i;

    if(sunrand_init() == -1) {
	perror("/dev/audio");
	return 1;
    }

    for(i = 0; i < 10; i++)
    {
	sunrand(&rnd, sizeof(rnd));
	printf("%08x\n", rnd);
    }
    sunrand_end();
    return 0;
}

#endif
