diff --git a/src/add-ons/kernel/drivers/random/driver.c b/src/add-ons/kernel/drivers/random/driver.c index 382f7448b3..0b26d82c10 100644 --- a/src/add-ons/kernel/drivers/random/driver.c +++ b/src/add-ons/kernel/drivers/random/driver.c @@ -4,197 +4,249 @@ */ /* Made into a BeOS /dev/random and /dev/urandom by Daniel Berlin */ -/* Adapted for OpenBeOS by david reid */ - -/* To compile on Sun: gcc -m32 -msupersparc -mcpu=v8 -g -O3 -finline-functions -Wa,-xarch= - v8plusc -Winline -lrt */ -/* To compile on Intel, MSVC with /G6 /Gr /O2 and with either /MT or /MD is recommended */ -/* If you want to export any of the following functions, you know what to do */ +/* Adapted for OpenBeOS by David Reid, Axel Doerfler */ -#include -#include #include +#include +#include #include -#include +#include +#include -#define thread_yield() snooze(10) -#define _rmtmp() -#define __int8 char -#define __int16 short -#define __int32 long -#define __int64 long long -//#define __cdecl -#define __fastcall -#define __forceinline __inline__ -#define ASM __asm__ -#define _lrotr(x, n) ((((unsigned __int32)(x)) >> ((int) ((n) & 31))) | (((unsigned __int32)(x)) << ((int) ((32 - ((n) & 31)))))) -#define _lrotl(x, n) ((((unsigned __int32)(x)) << ((int) ((n) & 31))) | (((unsigned __int32)(x)) >> ((int) ((32 - ((n) & 31)))))) - -#if defined (_M_IX86) || defined (__i386__) && defined (__GNUC__) - -static __inline__ unsigned long long clock_counter (void) -{ - return system_time(); /* eventually real_time_clock_usecs() ? */ -} - -#elif defined (sparc) || defined (__sparc) || defined (sun) || defined (__sun) && defined (__GNUC__) -static __inline unsigned long long clock_counter (void) -{ - register unsigned long x, y; - __asm__ __volatile__ ("rd %%tick, %0; clruw %0, %1; srlx %0, 32, %0" : "=r" (x), "=r" (y) : "0" (x), "1" (y)); - return ((unsigned long long) x << 32) | y; -} -#else -extern unsigned __int64 clock_counter (void); /* one of the above or any other clock - counter function compiled separately */ +#define TRACE_DRIVER 0 +#if TRACE_DRIVER +# define TRACE(x) dprintf x +#else +# define TRACE(x) ; #endif -#define rotr32(x, n) _lrotr (x, n) -#define rotl32(x, n) _lrotl (x, n) +int32 api_version = B_CUR_DRIVER_API_VERSION; -#define bswap32(x) ((rotl32 ((unsigned __int32)(x), 8) & 0x00ff00ff) | (rotr32 ((unsigned __int32)(x), 8) & 0xff00ff00)) +#define DRIVER_NAME "random" -#ifndef _OCTET_ -#define _OCTET_ -typedef union _OCTET -{ - unsigned __int64 Q[1]; - unsigned __int32 D[2]; - unsigned __int16 W[4]; - unsigned __int8 B[8]; -} OCTET; -#endif +static const char *sRandomNames[] = { + "random", + "urandom", + NULL +}; + +static status_t random_open(const char *name, uint32 flags, void **cookie); +static ssize_t random_read(void *cookie, off_t position, void *_buffer, size_t *_numBytes); +static ssize_t random_write(void *cookie, off_t position, const void *buffer, size_t *_numBytes); +static status_t random_control(void *cookie, uint32 op, void *arg, size_t length); +static status_t random_close(void *cookie); +static status_t random_free(void *cookie); + +static device_hooks sRandomHooks = { + random_open, + random_close, + random_free, + random_control, + random_read, + random_write, + NULL, + NULL, + NULL, + NULL +}; + + +// The number generator itself + +#define rotr32(x, n) ((((uint32)(x)) >> ((int) ((n) & 31))) | (((uint32)(x)) << ((int) ((32 - ((n) & 31)))))) +#define rotl32(x, n) ((((uint32)(x)) << ((int) ((n) & 31))) | (((uint32)(x)) >> ((int) ((32 - ((n) & 31)))))) + +#define bswap32(x) \ + ((rotl32((uint32)(x), 8) & 0x00ff00ff) | (rotr32((uint32)(x), 8) & 0xff00ff00)) + +typedef union _OCTET { + uint64 Q[1]; + uint32 D[2]; + uint16 W[4]; + uint8 B[8]; +} OCTET; + +#define NK 257 /* internal state size */ +#define NI 120 /* seed in increment */ +#define NA 70 /* rand out increment A */ +#define NB 139 /* rand out increment B */ + +typedef struct _ch_randgen { + OCTET ira[NK]; /* numbers live here */ + OCTET *seedptr; /* next seed pointer */ + OCTET *rndptrA; /* randomizing pointer #1 */ + OCTET *rndptrB; /* randomizing pointer #2 */ + OCTET *rndptrX; /* main randout pointer */ + OCTET rndLeft; /* left rand accumulator */ + OCTET rndRite; /* rite rand accumulator */ +} ch_randgen; + + +static ch_randgen *sRandomEnv; +static unsigned int randcount=0; +static sem_id sRandomSem; -#define NK 257 /* internal state size */ -#define NI 120 /* seed in increment */ -#define NA 70 /* rand out increment A */ -#define NB 139 /* rand out increment B */ -typedef struct _ch_randgen -{ - OCTET ira[NK]; /* numbers live here */ - OCTET *seedptr; /* next seed pointer */ - OCTET *rndptrA; /* randomizing pointer #1 */ - OCTET *rndptrB; /* randomizing pointer #2 */ - OCTET *rndptrX; /* main randout pointer */ - OCTET rndLeft; /* left rand accumulator */ - OCTET rndRite; /* rite rand accumulator */ -} ch_randgen; extern void hash_block(const unsigned char *block, const unsigned int block_byte_size, unsigned char *md); -#define HASH_BITS 160 /* I use Tiger. Modify it to match your HASH */ -#define HASH_BLOCK_BITS 512 /* I use Tiger. Modify it to match your HASH */ -#define HASH_BYTES (HASH_BITS / 8) -#define HASH_BLOCK_BYTES (HASH_BLOCK_BITS / 8) -#define HASH_OCTETS (HASH_BITS / 64) -#define HASH_BLOCK_OCTETS (HASH_BLOCK_BITS / 64) -/* attach by Yarrow Charnot. attaches x to y. can be seen as about 2-3 rounds of RC6 encryption +#define HASH_BITS 160 /* I use Tiger. Modify it to match your HASH */ +#define HASH_BLOCK_BITS 512 /* I use Tiger. Modify it to match your HASH */ +#define HASH_BYTES (HASH_BITS / 8) +#define HASH_BLOCK_BYTES (HASH_BLOCK_BITS / 8) +#define HASH_OCTETS (HASH_BITS / 64) +#define HASH_BLOCK_OCTETS (HASH_BLOCK_BITS / 64) + + +/* attach by Yarrow Charnot. attaches x to y. can be seen as about 2-3 rounds of RC6 encryption + */ + +static inline void +attach(OCTET *y, const OCTET *x, const uint32 anyA, const uint32 anyB, + const uint32 oddC, const uint32 oddD) +{ + register OCTET _x; + register OCTET _y; + + _x.D[0] = x->D[0]; + _x.D[1] = x->D[1]; + _y.D[0] = y->D[0]; + _y.D[1] = y->D[1]; + _x.D[0] = rotl32(((bswap32(_x.D[0]) | 1) * x->D[1]), 5); + _x.D[1] = rotl32((bswap32(_x.D[1]) | 1) * x->D[0], 5); + _y.D[0] = (bswap32(rotl32(_y.D[0] ^ _x.D[0], _x.D[1])) + anyA) * oddC; + _y.D[1] = (bswap32(rotl32(_y.D[1] ^ _x.D[1], _x.D[0])) + anyB) * oddD; + y->D[1] = _y.D[0]; + y->D[0] = _y.D[1]; +} + + +/** detach by Yarrow Charnot. detaches x from y. can be seen as about + * 2-3 rounds of RC6 decryption. + */ + +static inline void +detach(OCTET *y, const OCTET *x, const uint32 sameA, const uint32 sameB, + const uint32 invoddC, const uint32 invoddD) +{ + register OCTET _x; + register OCTET _y; + + _x.D[0] = x->D[0]; + _x.D[1] = x->D[1]; + _y.D[0] = y->D[1]; + _y.D[1] = y->D[0]; + _x.D[0] = rotl32((bswap32(_x.D[0]) | 1) * x->D[1], 5); + _x.D[1] = rotl32((bswap32(_x.D[1]) | 1) * x->D[0], 5); + _y.D[0] = rotr32(bswap32(_y.D[0] * invoddC - sameA), _x.D[1]) ^ _x.D[0]; + _y.D[1] = rotr32(bswap32(_y.D[1] * invoddD - sameB), _x.D[0]) ^ _x.D[1]; + y->D[0] = _y.D[0]; + y->D[1] = _y.D[1]; +} + + +/** QUICKLY seeds in a 64 bit number, modified so that a subsequent call really + * "stirs" in another seed value (no bullshit XOR here!) + */ + +static inline void +chseed(ch_randgen *prandgen, const uint64 seed) +{ + prandgen->seedptr += NI; + if (prandgen->seedptr >= (prandgen->ira + NK)) + prandgen->seedptr -= NK; + + attach(prandgen->seedptr, (OCTET *) &seed, 0x213D42F6U, 0x6552DAF9U, + 0x2E496B7BU, 0x1749A255U); +} + + +/** The heart of Yarrow 2000 Chuma Random Number Generator: fast and reliable + * randomness collection. + * Thread yielding function is the most OPTIMAL source of randomness combined + * with a clock counter (editor's note: thread_yield() is not properly done in BeOS). + * It doesn't have to switch to another thread, the call itself is random enough. + * Test it yourself. + * This FASTEST way to collect minimal randomness on each step couldn't use the + * processor any LESS. Even functions based on just creation of threads and their + * destruction can not compare by speed. + * Temporary file creation is just a little extra thwart to bewilder the processor + * cache and pipes. + * If you make clock_counter() (system_time()) return all 0's, still produces a + * stream indistinguishable from random. */ -__inline__ void __fastcall attach (OCTET *y, const OCTET *x, const unsigned __int32 anyA, const unsigned __int32 anyB, const unsigned __int32 oddC, const unsigned __int32 - oddD) -{ - register OCTET _x; - register OCTET _y; - _x.D[0] = x->D[0]; - _x.D[1] = x->D[1]; - _y.D[0] = y->D[0]; - _y.D[1] = y->D[1]; - _x.D[0] = rotl32 (((bswap32(_x.D[0]) | 1) * x->D[1]), 5); - _x.D[1] = rotl32 ((bswap32 (_x.D[1]) | 1) * x->D[0], 5); - _y.D[0] = (bswap32 (rotl32 (_y.D[0] ^ _x.D[0], _x.D[1])) + anyA) * oddC; - _y.D[1] = (bswap32 (rotl32 (_y.D[1] ^ _x.D[1], _x.D[0])) + anyB) * oddD; - y->D[1] = _y.D[0]; - y->D[0] = _y.D[1]; -} -/* detach by Yarrow Charnot. detaches x from y. can be seen as about 2-3 rounds of RC6 - decryption */ -__forceinline void __fastcall detach (OCTET *y, const OCTET *x, const unsigned __int32 - sameA, const unsigned __int32 sameB, const unsigned __int32 invoddC, const unsigned __int32 - invoddD) -{ - register OCTET _x; - register OCTET _y; - _x.D[0] = x->D[0]; - _x.D[1] = x->D[1]; - _y.D[0] = y->D[1]; - _y.D[1] = y->D[0]; - _x.D[0] = rotl32 ((bswap32 (_x.D[0]) | 1) * x->D[1], 5); - _x.D[1] = rotl32 ((bswap32 (_x.D[1]) | 1) * x->D[0], 5); - _y.D[0] = rotr32 (bswap32 (_y.D[0] * invoddC - sameA), _x.D[1]) ^ _x.D[0]; - _y.D[1] = rotr32 (bswap32 (_y.D[1] * invoddD - sameB), _x.D[0]) ^ _x.D[1]; - y->D[0] = _y.D[0]; - y->D[1] = _y.D[1]; -} -/* QUICKLY seeds in a 64 bit number, modified so that a subsequent call really "stirs" in another - seed value (no bullshit XOR here!) */ -__inline void chseed (ch_randgen *prandgen, const unsigned __int64 seed) -{ - prandgen->seedptr += NI; - if (prandgen->seedptr >= (prandgen->ira + NK)) prandgen->seedptr -= NK; - attach (prandgen->seedptr, (OCTET *) &seed, 0x213D42F6U, 0x6552DAF9U, - 0x2E496B7BU, 0x1749A255U); -} -/* The heart of Yarrow 2000 Chuma Random Number Generator: fast and reliable randomness - collection. */ -/* thread yielding function is the most OPTIMAL source of randomness combined with a clock - counter. */ -/* it doesn't have to switch to another thread, the call itself is random enough. test it yourself. */ -/* this FASTEST way to collect minimal randomness on each step couldn't use the processor - any LESS. */ -/* even functions based on just creation of threads and their destruction can not compare by - speed. */ -/* temporary file creation is just a little extra thwart to bewilder the processor cache and pipes. */ /* if you make clock_counter return all 0's, still produces a stream indistinguishable from - random. */ -void reseed (ch_randgen *prandgen, const unsigned int inittimes) -{ - volatile unsigned int i, j; - OCTET x, y; - for (j = inittimes; j; j--) - { - for (i = NK * inittimes; i; i--) - { - thread_yield (); - y.Q[0] += clock_counter (); - attach (&x, &y, 0x52437EFFU, 0x026A4CEBU, 0xD9E66AC9U, 0x56E5A975U); - attach (&y, &x, 0xC70B8B41U, 0x9126B036U, 0x36CC6FDBU, 0x31D477F7U); - chseed (prandgen, y.Q[0]); - } - } -} + +static void +reseed(ch_randgen *prandgen, const uint32 initTimes) +{ + volatile uint32 i, j; + OCTET x, y; + + for (j = initTimes; j; j--) { + for (i = NK * initTimes; i; i--) { + // Note: there is no yield() in BeOS - we use snooze as an approximation, + // although it might not work as good as this one (especially, it's not + // as cheap as). + //thread_yield(); + snooze(5); + + y.Q[0] += system_time(); + attach(&x, &y, 0x52437EFFU, 0x026A4CEBU, 0xD9E66AC9U, 0x56E5A975U); + attach(&y, &x, 0xC70B8B41U, 0x9126B036U, 0x36CC6FDBU, 0x31D477F7U); + chseed(prandgen, y.Q[0]); + } + } +} + + /* returns a 64 bit of Yarrow 2000 Chuma RNG random number */ -__inline unsigned __int64 chrand (ch_randgen *prandgen) -{ - prandgen->rndptrX ++; - prandgen->rndptrA += NA; - prandgen->rndptrB += NB; - if (prandgen->rndptrX >= (prandgen->ira + NK)) - { - prandgen->rndptrX -= NK; - reseed (prandgen, 1); - } - if (prandgen->rndptrA >= (prandgen->ira + NK)) prandgen->rndptrA -= NK; - if (prandgen->rndptrB >= (prandgen->ira + NK)) prandgen->rndptrB -= NK; - attach (&prandgen->rndLeft, prandgen->rndptrX, prandgen->rndptrA->D[0], prandgen - ->rndptrA->D[1], 0x49A3BC71UL, 0x60E285FDUL); - attach (&prandgen->rndRite, &prandgen->rndLeft, prandgen->rndptrB->D[0], prandgen - ->rndptrB->D[1], 0xC366A5FDUL, 0x20C763EFUL); - chseed (prandgen, prandgen->rndRite.Q[0]); - return prandgen->rndRite.Q[0] ^ prandgen->rndLeft.Q[0]; -} -/* returns a 32 bit random number */ -__inline unsigned __int32 chrand32 (ch_randgen *prandgen) -{ - OCTET r = {{chrand (prandgen)}}; - return r.D[0] ^ r.D[1]; -} -/* returns an 8 bit random number */ -__inline unsigned __int8 chrand8 (ch_randgen *prandgen) + +static inline uint64 +chrand(ch_randgen *prandgen) +{ + prandgen->rndptrX++; + prandgen->rndptrA += NA; + prandgen->rndptrB += NB; + if (prandgen->rndptrX >= (prandgen->ira + NK)) { + prandgen->rndptrX -= NK; + reseed (prandgen, 1); + } + + if (prandgen->rndptrA >= (prandgen->ira + NK)) + prandgen->rndptrA -= NK; + if (prandgen->rndptrB >= (prandgen->ira + NK)) + prandgen->rndptrB -= NK; + + attach(&prandgen->rndLeft, prandgen->rndptrX, prandgen->rndptrA->D[0], + prandgen->rndptrA->D[1], 0x49A3BC71UL, 0x60E285FDUL); + attach(&prandgen->rndRite, &prandgen->rndLeft, prandgen->rndptrB->D[0], + prandgen->rndptrB->D[1], 0xC366A5FDUL, 0x20C763EFUL); + + chseed(prandgen, prandgen->rndRite.Q[0]); + + return prandgen->rndRite.Q[0] ^ prandgen->rndLeft.Q[0]; +} + + +/** returns a 32 bit random number */ + +static inline uint32 +chrand32(ch_randgen *prandgen) { OCTET r = {{chrand(prandgen)}}; - return r.B[0] ^ r.B[1] ^ r.B[2] ^ r.B[3] ^ r.B[4] ^ r.B[5] ^ r.B[6] ^ r.B[7] ; + return r.D[0] ^ r.D[1]; +} + + +/** returns an 8 bit random number */ + +static inline uint8 +chrand8(ch_randgen *prandgen) +{ + OCTET r = {{chrand(prandgen)}}; + return r.B[0] ^ r.B[1] ^ r.B[2] ^ r.B[3] ^ r.B[4] ^ r.B[5] ^ r.B[6] ^ r.B[7]; } /* generates a cryptographically secure random big number 0 <= x < 32^n */ @@ -220,231 +272,169 @@ __inline unsigned __int8 chrand8 (ch_randgen *prandgen) } } */ -/* Initializes Yarrow 2000 Chuma Random Number Generator */ -/* reseeding about 8 times prior to the first use is recommended. */ -/* more than 16 will probably be a bit too much as time increases by n^2 */ - -__inline ch_randgen * -new_chrand(const unsigned int inittimes) -{ - ch_randgen *prandgen; - prandgen = (ch_randgen *)malloc(sizeof(ch_randgen)); - prandgen->seedptr = prandgen->ira; - prandgen->rndptrX = prandgen->ira; - prandgen->rndptrA = prandgen->ira; - prandgen->rndptrB = prandgen->ira; - prandgen->rndLeft.Q[0] = 0x1A4B385C72D69E0FUL; - prandgen->rndRite.Q[0] = 0x9C805FE7361A42DBUL; - reseed (prandgen, inittimes); - prandgen->seedptr = prandgen->ira + chrand (prandgen) % NK; - prandgen->rndptrX = prandgen->ira + chrand (prandgen) % NK; - prandgen->rndptrA = prandgen->ira + chrand (prandgen) % NK; - prandgen->rndptrB = prandgen->ira + chrand (prandgen) % NK; - return prandgen; -} - -/* Clean up after chuma */ -__inline void -kill_chrand(ch_randgen *randgen) -{ - memset(randgen, 0, sizeof (ch_randgen)); - free(randgen); -} - -/* ++++++++++ - driver.c - A skeletal device driver - +++++ */ - -//#include -#include -#include -#include -#include -static ch_randgen *rng; -static unsigned int randcount=0; -static sem_id rand_mutex; -#define DRIVER_NAME "random" -#define DEVICE_NAME "random" -#define DEVICE_NAME2 "urandom" -int32 api_version = B_CUR_DRIVER_API_VERSION; - -/* ---------- - init_hardware - called once the first time the driver is loaded - ----- */ -status_t init_hardware (void) +/** Initializes Yarrow 2000 Chuma Random Number Generator. + * Reseeding about 8 times prior to the first use is recommended. + * More than 16 will probably be a bit too much as time increases + * by n^2. + */ + +static ch_randgen * +new_chrand(const unsigned int inittimes) { -// dprintf (DRIVER_NAME ": init_hardware()\n"); + ch_randgen *prandgen; + + prandgen = (ch_randgen *)malloc(sizeof(ch_randgen)); + if (prandgen == NULL) + return NULL; + + prandgen->seedptr = prandgen->ira; + prandgen->rndptrX = prandgen->ira; + prandgen->rndptrA = prandgen->ira; + prandgen->rndptrB = prandgen->ira; + prandgen->rndLeft.Q[0] = 0x1A4B385C72D69E0FUL; + prandgen->rndRite.Q[0] = 0x9C805FE7361A42DBUL; + reseed (prandgen, inittimes); + + prandgen->seedptr = prandgen->ira + chrand (prandgen) % NK; + prandgen->rndptrX = prandgen->ira + chrand (prandgen) % NK; + prandgen->rndptrA = prandgen->ira + chrand (prandgen) % NK; + prandgen->rndptrB = prandgen->ira + chrand (prandgen) % NK; + return prandgen; +} + + +/** Clean up after chuma */ + +static void +kill_chrand(ch_randgen *randgen) +{ + memset(randgen, 0, sizeof (ch_randgen)); + free(randgen); +} + + +// #pragma mark - +// device driver + + +status_t +init_hardware(void) +{ + TRACE((DRIVER_NAME ": init_hardware()\n")); return B_OK; } -/* ---------- - init_driver - optional function - called every time the driver - is loaded. - ----- */ - - -status_t init_driver (void) +status_t +init_driver(void) { - rng = new_chrand(8); - rand_mutex = create_sem(1, "RNG semaphore"); -// dprintf (DRIVER_NAME ": init_driver()\n"); + TRACE((DRIVER_NAME ": init_driver()\n")); + sRandomEnv = new_chrand(8); + sRandomSem = create_sem(1, "RNG semaphore"); return B_OK; } -/* ---------- - uninit_driver - optional function - called every time the driver - is unloaded - ----- */ - -void uninit_driver (void) +void +uninit_driver(void) { - kill_chrand(rng); - delete_sem(rand_mutex); -// dprintf (DRIVER_NAME ": uninit_driver()\n"); + TRACE((DRIVER_NAME ": uninit_driver()\n")); + kill_chrand(sRandomEnv); + delete_sem(sRandomSem); } -/* ---------- - my_device_open - handle open() calls - ----- */ - -static status_t my_device_open (const char *name, uint32 flags, void** cookie) +const char ** +publish_devices(void) { -// dprintf (DRIVER_NAME ": open(\"%s\")\n", name); + TRACE((DRIVER_NAME ": publish_devices()\n")); + return sRandomNames; +} + +device_hooks * +find_device(const char* name) +{ + int i; + + TRACE((DRIVER_NAME ": find_device(\"%s\")\n", name)); + + for (i = 0; sRandomNames[i] != NULL; i++) + if (strcmp(name, sRandomNames[i]) == 0) + return &sRandomHooks; + + return NULL; +} + + +// #pragma mark - +// device functions + + +static status_t +random_open(const char *name, uint32 flags, void **cookie) +{ + TRACE((DRIVER_NAME ": open(\"%s\")\n", name)); return B_OK; } -/* ---------- - my_device_read - handle read() calls - ----- */ - -static ssize_t my_device_read (void* cookie, off_t position, void *buf, size_t* num_bytes) +static ssize_t +random_read(void *cookie, off_t position, void *_buffer, size_t *_numBytes) { - int32* buffer = (int32 *)buf; - unsigned char *buf8 = (unsigned char *)buf; - int i,j; - acquire_sem(rand_mutex); - randcount += *num_bytes; - + int32 *buffer = (int32 *)_buffer; + uint8 *buffer8 = (uint8 *)_buffer; + uint32 i, j; + + acquire_sem(sRandomSem); + randcount += *_numBytes; + /* Reseed if we have or are gonna use up > 1/16th the entropy around */ if (randcount >= NK/8) { randcount = 0; - reseed (rng, 1); + reseed(sRandomEnv, 1); } /* Yes, i know this is not the way we should do it. What we really should do is - * take the md5 or sha1 hash of the state of the pool, and return that. Someday. */ - for(i = 0 ; i < (*num_bytes)/4 ; i++) - buffer[i] = chrand32(rng); - for(j = 0 ; j < (*num_bytes) % 4; j++) - buf8[(i*4)+j] = chrand8(rng); - release_sem(rand_mutex); + * take the md5 or sha1 hash of the state of the pool, and return that. Someday. + */ + for (i = 0; i < (*_numBytes)/4; i++) + buffer[i] = chrand32(sRandomEnv); + for (j = 0; j < (*_numBytes) % 4; j++) + buffer8[(i*4) + j] = chrand8(sRandomEnv); + release_sem(sRandomSem); return B_OK; } -/* ---------- - my_device_write - handle write() calls - ----- */ - -static ssize_t my_device_write (void* cookie, off_t position, const void* buf, size_t* num_bytes) +static ssize_t +random_write(void *cookie, off_t position, const void *buffer, size_t *_numBytes) { return B_OK; } -/* ---------- - my_device_control - handle ioctl calls - ----- */ - -static status_t my_device_control (void* cookie, uint32 op, void* arg, size_t len) +static status_t +random_control(void *cookie, uint32 op, void *arg, size_t length) { - /*dprintf (DRIVER_NAME ": ioctl(%d)\n", op);*/ + TRACE((DRIVER_NAME ": ioctl(%d)\n", op)); return B_ERROR; } -/* ---------- - my_device_close - handle close() calls - ----- */ - - -static status_t my_device_close (void* cookie) +static status_t +random_close(void *cookie) { -// dprintf (DRIVER_NAME ": close()\n"); + TRACE((DRIVER_NAME ": close()\n")); return B_OK; } -/* ----- - my_device_free - called after the last device is closed, and after - all i/o is complete. - ----- */ - - -static status_t my_device_free (void* cookie) +static status_t +random_free(void *cookie) { -// dprintf (DRIVER_NAME ": free()\n"); + TRACE((DRIVER_NAME ": free()\n")); return B_OK; } - - -/* ----- - null-terminated array of device names supported by this driver - ----- */ - -static const char *my_device_name[] = { - DEVICE_NAME, - DEVICE_NAME2, - NULL -}; - -/* ----- - function pointers for the device hooks entry points - ----- */ - -static device_hooks my_device_hooks = { - my_device_open, /* -> open entry point */ - my_device_close, /* -> close entry point */ - my_device_free, /* -> free cookie */ - my_device_control, /* -> control entry point */ - my_device_read, /* -> read entry point */ - my_device_write, /* -> write entry point */ - NULL, - NULL, - NULL, - NULL -}; - -/* ---------- - publish_devices - return a null-terminated array of devices - supported by this driver. - ----- */ - - -const char **publish_devices() -{ -// dprintf (DRIVER_NAME ": publish_devices()\n"); - return my_device_name; -} - -/* ---------- - find_device - return ptr to device hooks structure for a - given device name - ----- */ -device_hooks *find_device(const char* name) -{ - int i; -// dprintf (DRIVER_NAME ": find_device(\"%s\")\n", name); - for (i = 0; my_device_name[i] != NULL; i++) - if (strcmp (name, my_device_name [i]) == 0) - return &my_device_hooks; - return NULL; -}