Updated PCI IDs to latest snapshot.
[tangerine.git] / workbench / libs / uuid / uuid_generate.c
blob7a8e9ebf029664153be80567a1fba5cb7a2d0c2c
1 /*
2 Copyright © 2007-2008, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #define DEBUG 1
8 #include <aros/symbolsets.h>
9 #include <aros/debug.h>
10 #include <aros/libcall.h>
11 #include <proto/exec.h>
12 #include <proto/uuid.h>
13 #include <proto/timer.h>
14 #include <proto/dos.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <ctype.h>
20 #include <assert.h>
22 #include "uuid_private.h"
23 #include LC_LIBDEFS_FILE
25 static void uuid_generate_random(uuid_t *uuid, struct uuid_base *UUIDBase);
26 static void uuid_generate_time(uuid_t *uuid, struct uuid_base *UUIDBase);
28 /*****************************************************************************
30 NAME */
31 AROS_LH2(void, UUID_Generate,
33 /* SYNOPSIS */
34 AROS_LHA(uuid_type_t, type, D0),
35 AROS_LHA(uuid_t *, uuid, A0),
37 /* LOCATION */
38 struct uuid_base *, UUIDBase, 13, UUID)
40 /* FUNCTION
41 Generate Universally Unique Identifier conforming the RFC 4122.
43 INPUTS
44 type - type of the identifier:
45 UUID_TYPE_DCE_RANDOM - random identifier. Do not use it on purpose
46 due to the weak source of noise on AROS.
47 UUID_TYPE_DCE_TIME - system time based identifier.
49 uuid - storage for generated UUID.
51 RESULT
52 This function always succeeds.
54 NOTES
56 EXAMPLE
58 BUGS
60 SEE ALSO
62 INTERNALS
64 *****************************************************************************/
66 AROS_LIBFUNC_INIT
68 assert(uuid);
70 ObtainSemaphore(&LIBBASE->uuid_GlobalLock);
72 if (type == UUID_TYPE_DCE_RANDOM)
73 uuid_generate_random(uuid, UUIDBase);
74 else
75 uuid_generate_time(uuid, UUIDBase);
77 ReleaseSemaphore(&LIBBASE->uuid_GlobalLock);
79 D({
80 char buf[UUID_STRLEN+1];
81 buf[UUID_STRLEN] = 0;
83 UUID_Unparse(uuid, buf);
84 bug("[UUID] generated UUID = %s\n", buf);
87 AROS_LIBFUNC_EXIT
91 static uint32_t uuid_rand(struct uuid_base *UUIDBase)
93 return (UUIDBase->uuid_RandomSeed =
94 UUIDBase->uuid_RandomSeed * 1103515245 + 12345) % 0x7fffffff;
97 static void uuid_generate_random(uuid_t *uuid, struct uuid_base *UUIDBase)
99 uint8_t u[16];
100 int i;
102 D(bug("[UUID] Generating random UUID\n"));
104 for (i=0; i < 16; i++)
105 u[i] = uuid_rand(UUIDBase);
107 UUID_Unpack(u, uuid);
109 uuid->clock_seq_hi_and_reserved &= 0x3f;
110 uuid->clock_seq_hi_and_reserved |= 0x80;
111 uuid->time_hi_and_version &= 0x0fff;
112 uuid->time_hi_and_version |= 0x4000;
115 static void uuid_get_current_time(uuid_time_t *time, struct uuid_base *UUIDBase)
117 uuid_time_t time_now;
118 struct timeval tv;
120 for (;;)
122 GetSysTime(&tv);
123 time_now = ((uint64_t)tv.tv_secs + 2922) * 10000000 +
124 ((uint64_t)tv.tv_micro) * 10 +
125 ((uint64_t)0x01B21DD213814000LL);
127 if (time_now != LIBBASE->uuid_LastTime)
129 UUIDBase->uuid_UUIDs_ThisTick = 0;
130 LIBBASE->uuid_LastTime = time_now;
131 break;
134 if (UUIDBase->uuid_UUIDs_ThisTick < UUIDS_PER_TICK)
136 UUIDBase->uuid_UUIDs_ThisTick++;
137 break;
140 *time = time_now + UUIDBase->uuid_UUIDs_ThisTick;
143 static void uuid_get_node(uuid_node_t *node, struct uuid_base *UUIDBase)
145 if (!UUIDBase->uuid_Initialized)
147 if (!DOSBase)
148 DOSBase = OpenLibrary("dos.library", 0);
150 if (!(DOSBase && GetVar("uuid_state", (UBYTE*)&LIBBASE->uuid_State, sizeof(uuid_state_t),
151 GVF_BINARY_VAR | GVF_DONT_NULL_TERM) == sizeof(uuid_state_t)))
153 int i;
154 UUIDBase->uuid_State.ts = UUIDBase->uuid_LastTime;
155 UUIDBase->uuid_State.cs = uuid_rand(UUIDBase);
156 for (i=0; i < 6; i++)
158 UUIDBase->uuid_State.node.nodeID[i] = uuid_rand(UUIDBase);
160 UUIDBase->uuid_State.node.nodeID[0] |= 0x01;
162 LIBBASE->uuid_Initialized = 1;
164 if (DOSBase)
165 SetVar("uuid_state", (UBYTE*)&LIBBASE->uuid_State, sizeof(uuid_state_t),
166 GVF_BINARY_VAR | GVF_DONT_NULL_TERM | GVF_SAVE_VAR);
168 *node = UUIDBase->uuid_State.node;
171 static void uuid_get_state(uint16_t *cs, uuid_time_t *timestamp, uuid_node_t *node, struct uuid_base *UUIDBase)
173 if (!UUIDBase->uuid_Initialized)
175 if (!DOSBase)
176 DOSBase = OpenLibrary("dos.library", 0);
178 if (!(DOSBase && GetVar("uuid_state", (UBYTE*)&LIBBASE->uuid_State, sizeof(uuid_state_t),
179 GVF_BINARY_VAR | GVF_DONT_NULL_TERM) == sizeof(uuid_state_t)))
181 int i;
182 UUIDBase->uuid_State.ts = UUIDBase->uuid_LastTime;
183 UUIDBase->uuid_State.cs = uuid_rand(UUIDBase);
184 for (i=0; i < 6; i++)
186 UUIDBase->uuid_State.node.nodeID[i] = uuid_rand(UUIDBase);
188 UUIDBase->uuid_State.node.nodeID[0] |= 0x01;
190 UUIDBase->uuid_Initialized = 1;
193 *node = UUIDBase->uuid_State.node;
194 *timestamp = UUIDBase->uuid_State.ts;
195 *cs = UUIDBase->uuid_State.cs;
198 static void uuid_set_state(uint16_t cs, uuid_time_t timestamp, uuid_node_t node, struct uuid_base *UUIDBase)
200 UUIDBase->uuid_State.node = node;
201 UUIDBase->uuid_State.ts = timestamp;
202 UUIDBase->uuid_State.cs = cs;
204 D(bug("[UUID] uuid_set_state(). Timestamp=%08x%08x, NextUpdate=%08x%08x\n",
205 (uint32_t)(timestamp >> 32), (uint32_t)timestamp,
206 (uint32_t)(LIBBASE->uuid_NextUpdate >> 32), (uint32_t)LIBBASE->uuid_NextUpdate
209 if (timestamp >= LIBBASE->uuid_NextUpdate)
211 D(bug("[UUID] updating nonvolatile variable\n"));
213 if (!DOSBase)
214 DOSBase = OpenLibrary("dos.library", 0);
216 if (DOSBase)
217 SetVar("uuid_state", (UBYTE*)&LIBBASE->uuid_State, sizeof(uuid_state_t),
218 GVF_GLOBAL_ONLY | GVF_SAVE_VAR | LV_VAR);
220 LIBBASE->uuid_NextUpdate = timestamp + (10 * 10 * 1000000);
224 static void uuid_generate_time(uuid_t *uuid, struct uuid_base *UUIDBase)
226 uuid_time_t time, last_time;
227 uuid_node_t node, last_node;
228 uint16_t clockseq;
230 D(bug("[UUID] Generating time-based UUID\n"));
232 uuid_get_current_time(&time, UUIDBase);
233 uuid_get_node(&node, UUIDBase);
234 uuid_get_state(&clockseq, &last_time, &last_node, UUIDBase);
236 if (memcmp(&node, &last_node, sizeof(node)))
237 clockseq = uuid_rand(UUIDBase);
238 else if (time < last_time)
239 clockseq++;
241 uuid_set_state(clockseq, time, node, UUIDBase);
243 uuid->time_low = (uint32_t)(time & 0xFFFFFFFF);
244 uuid->time_mid = (uint16_t)((time >> 32) & 0xFFFF);
245 uuid->time_hi_and_version = (uint16_t)((time >> 48) & 0x0FFF);
246 uuid->time_hi_and_version |= (1 << 12);
247 uuid->clock_seq_low = clockseq & 0xFF;
248 uuid->clock_seq_hi_and_reserved = (clockseq & 0x3F00) >> 8;
249 uuid->clock_seq_hi_and_reserved |= 0x80;
250 memcpy(&uuid->node, &node, sizeof uuid->node);