1 /*
2  * %CopyrightBegin%
3  *
4  * Copyright Ericsson AB 1999-2017. All Rights Reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * %CopyrightEnd%
19  */
20 
21 /*
22  * Include file for erlang driver writers.
23  */
24 
25 #ifndef __ERL_DRIVER_H__
26 #define __ERL_DRIVER_H__
27 
28 #ifdef HAVE_CONFIG_H
29 #  include "config.h"
30 #endif
31 
32 #define ERL_DRV_DEPRECATED_FUNC
33 #ifdef __GNUC__
34 #  if __GNUC__ >= 3
35 #    undef ERL_DRV_DEPRECATED_FUNC
36 #    define ERL_DRV_DEPRECATED_FUNC __attribute__((deprecated))
37 #  endif
38 #endif
39 
40 #include "erl_drv_nif.h"
41 
42 #include <stdlib.h>
43 
44 #if defined(__WIN32__) || defined(_WIN32) || defined(_WIN32_)
45 #ifndef STATIC_ERLANG_DRIVER
46    /* Windows dynamic drivers, everything is different... */
47 #define ERL_DRIVER_TYPES_ONLY
48 #define WIN32_DYNAMIC_ERL_DRIVER
49 #endif
50 #endif
51 
52 #ifndef EXTERN
53 #  ifdef __cplusplus
54 #    define EXTERN extern "C"
55 #  else
56 #    define EXTERN extern
57 #  endif
58 #endif
59 
60 #define ERL_DRV_READ  ((int)ERL_NIF_SELECT_READ)
61 #define ERL_DRV_WRITE ((int)ERL_NIF_SELECT_WRITE)
62 #define ERL_DRV_USE   ((int)ERL_NIF_SELECT_STOP)
63 #define ERL_DRV_USE_NO_CALLBACK (ERL_DRV_USE | (ERL_DRV_USE  << 1))
64 
65 /* Old deprecated */
66 #define DO_READ  ERL_DRV_READ
67 #define DO_WRITE ERL_DRV_WRITE
68 
69 #define ERL_DRV_EXTENDED_MARKER		(0xfeeeeeed)
70 #define ERL_DRV_EXTENDED_MAJOR_VERSION	3
71 #define ERL_DRV_EXTENDED_MINOR_VERSION	3
72 
73 /*
74  * The emulator will refuse to load a driver with a major version
75  * lower than ERL_DRV_MIN_REQUIRED_MAJOR_VERSION_ON_LOAD. The load
76  * may however fail if user have not removed use of deprecated
77  * symbols.
78  *
79  * The ERL_DRV_MIN_REQUIRED_MAJOR_VERSION_ON_LOAD have to allow
80  * loading of drivers built at least two major OTP releases
81  * ago.
82  *
83  * Bump of major version to 3 happened in OTP 17. That is, in
84  * OTP 19 we can increase ERL_DRV_MIN_REQUIRED_MAJOR_VERSION_ON_LOAD
85  * to 3.
86  */
87 #define ERL_DRV_MIN_REQUIRED_MAJOR_VERSION_ON_LOAD 2
88 
89 /*
90  * The emulator will refuse to load a driver with different major
91  * version than the one used by the emulator.
92  */
93 
94 
95 /* Values for set_port_control_flags() */
96 
97 #define PORT_CONTROL_FLAG_BINARY	(1 << 0)
98 #define PORT_CONTROL_FLAG_HEAVY		(1 << 1)
99 
100 /* Values for get_port_flags() */
101 
102 #define PORT_FLAG_BINARY                (1 << 0)
103 #define PORT_FLAG_LINE                  (1 << 1)
104 
105 
106 #define ERL_DRV_FLAG_USE_PORT_LOCKING	(1 << 0)
107 #define ERL_DRV_FLAG_SOFT_BUSY		(1 << 1)
108 #define ERL_DRV_FLAG_NO_BUSY_MSGQ	(1 << 2)
109 #define ERL_DRV_FLAG_USE_INIT_ACK	(1 << 3)
110 
111 /*
112  * Integer types
113  */
114 
115 typedef ErlNapiUInt64 ErlDrvUInt64;
116 typedef ErlNapiSInt64 ErlDrvSInt64;
117 typedef ErlNapiUInt ErlDrvUInt;
118 typedef ErlNapiSInt ErlDrvSInt;
119 typedef ErlNapiUInt ErlDrvTermData;
120 
121 #if defined(__WIN32__) || defined(_WIN32)
122 typedef ErlDrvUInt ErlDrvSizeT;
123 typedef ErlDrvSInt ErlDrvSSizeT;
124 #else
125 typedef size_t ErlDrvSizeT;
126 typedef ssize_t ErlDrvSSizeT;
127 #endif
128 
129 /*
130  * A binary as seen in a driver. Note that a binary should never be
131  * altered by the driver when it has been sent to Erlang.
132  */
133 
134 typedef struct erl_drv_binary {
135     ErlDrvSInt orig_size;        /* total length of binary */
136     char orig_bytes[1];   /* the data (char instead of byte!) */
137 } ErlDrvBinary;
138 
139 
140 /*
141  * Note: These types are incomplete to catch type errors easier.
142  */
143 
144 typedef struct _erl_drv_data* ErlDrvData; /* Data to be used by the driver itself. */
145 #ifndef ERL_SYS_DRV
146 typedef struct _erl_drv_event* ErlDrvEvent; /* An event to be selected on. */
147 #endif
148 typedef struct _erl_drv_port* ErlDrvPort; /* A port descriptor. */
149 typedef struct _erl_drv_port* ErlDrvThreadData; /* Thread data. */
150 
151 typedef struct {
152     unsigned long megasecs;
153     unsigned long secs;
154     unsigned long microsecs;
155 } ErlDrvNowData;
156 
157 typedef ErlDrvSInt64 ErlDrvTime;
158 
159 #define ERL_DRV_TIME_ERROR ((ErlDrvSInt64) ERTS_NAPI_TIME_ERROR__)
160 
161 typedef enum {
162     ERL_DRV_SEC = ERTS_NAPI_SEC__,
163     ERL_DRV_MSEC = ERTS_NAPI_MSEC__,
164     ERL_DRV_USEC = ERTS_NAPI_USEC__,
165     ERL_DRV_NSEC = ERTS_NAPI_NSEC__
166 } ErlDrvTimeUnit;
167 
168 /*
169  * Error codes that can be return from driver.
170  */
171 
172 /*
173  * Exception code from open_port/2 will be {'EXIT',{einval,Where}}.
174  */
175 #define ERL_DRV_ERROR_GENERAL ((ErlDrvData) -1)
176 
177 /*
178  * Exception code from open_port/2 will be {'EXIT',{Errno,Where}},
179  * where Errno is a textual representation of the errno variable
180  * (e.g. eacces if errno is EACCES).
181  */
182 #define ERL_DRV_ERROR_ERRNO ((ErlDrvData) -2)
183 
184 /*
185  * Exception code from open_port/2 will be {'EXIT',{badarg,Where}}.
186  */
187 #define ERL_DRV_ERROR_BADARG ((ErlDrvData) -3)
188 
189 typedef struct erl_io_vec {
190     int vsize;			/* length of vectors */
191     ErlDrvSizeT size;		/* total size in bytes */
192     SysIOVec* iov;
193     ErlDrvBinary** binv;
194 } ErlIOVec;
195 
196 /*
197  * erl driver thread types
198  */
199 
200 typedef struct ErlDrvTid_ *ErlDrvTid;
201 typedef struct ErlDrvMutex_ ErlDrvMutex;
202 typedef struct ErlDrvCond_ ErlDrvCond;
203 typedef struct ErlDrvRWLock_ ErlDrvRWLock;
204 typedef int ErlDrvTSDKey;
205 
206 /*
207  *
208  */
209 typedef struct erl_drv_port_data_lock * ErlDrvPDL;
210 
211 /*
212  * This structure defines a driver.
213  */
214 
215 typedef struct erl_drv_entry {
216     int (*init)(void);		/* called at system start up for statically
217 				   linked drivers, and after loading for
218 				   dynamically loaded drivers */
219 
220 #ifndef ERL_SYS_DRV
221     ErlDrvData (*start)(ErlDrvPort port, char *command);
222 				/* called when open_port/2 is invoked.
223 				   return value -1 means failure. */
224 #else
225     ErlDrvData (*start)(ErlDrvPort port, char *command, SysDriverOpts* opts);
226 				/* special options, only for system driver */
227 #endif
228     void (*stop)(ErlDrvData drv_data);
229                                 /* called when port is closed, and when the
230 				   emulator is halted. */
231     void (*output)(ErlDrvData drv_data, char *buf, ErlDrvSizeT len);
232 				/* called when we have output from erlang to
233 				   the port */
234     void (*ready_input)(ErlDrvData drv_data, ErlDrvEvent event);
235 				/* called when we have input from one of
236 				   the driver's handles */
237     void (*ready_output)(ErlDrvData drv_data, ErlDrvEvent event);
238 				/* called when output is possible to one of
239 				   the driver's handles */
240     char *driver_name;		/* name supplied as command
241 				   in open_port XXX ? */
242     void (*finish)(void);        /* called before unloading the driver -
243 				   DYNAMIC DRIVERS ONLY */
244     void *handle;		/* Reserved -- Used by emulator internally */
245     ErlDrvSSizeT (*control)(ErlDrvData drv_data, unsigned int command,
246 			    char *buf, ErlDrvSizeT len, char **rbuf,
247 			    ErlDrvSizeT rlen); /* "ioctl" for drivers - invoked by
248 						  port_control/3 */
249     void (*timeout)(ErlDrvData drv_data);	/* Handling of timeout in driver */
250     void (*outputv)(ErlDrvData drv_data, ErlIOVec *ev);
251 				/* called when we have output from erlang
252 				   to the port */
253     void (*ready_async)(ErlDrvData drv_data, ErlDrvThreadData thread_data);
254     void (*flush)(ErlDrvData drv_data);
255                                 /* called when the port is about to be
256 				   closed, and there is data in the
257 				   driver queue that needs to be flushed
258 				   before 'stop' can be called */
259     ErlDrvSSizeT (*call)(ErlDrvData drv_data,
260 			 unsigned int command, char *buf, ErlDrvSizeT len,
261 			 char **rbuf, ErlDrvSizeT rlen,
262 			 unsigned int *flags); /* Works mostly like 'control',
263 						  a synchronous
264 						  call into the driver. */
265     void (*unused_event_callback)(void);
266     int extended_marker;	/* ERL_DRV_EXTENDED_MARKER */
267     int major_version;		/* ERL_DRV_EXTENDED_MAJOR_VERSION */
268     int minor_version;		/* ERL_DRV_EXTENDED_MINOR_VERSION */
269     int driver_flags;		/* ERL_DRV_FLAGs */
270     void *handle2;              /* Reserved -- Used by emulator internally */
271     void (*process_exit)(ErlDrvData drv_data, ErlDrvMonitor *monitor);
272                                 /* Called when a process monitor fires */
273     void (*stop_select)(ErlDrvEvent event, void* reserved);
274     	                        /* Called on behalf of driver_select when
275 				   it is safe to release 'event'. A typical
276 				   unix driver would call close(event) */
277     void (*emergency_close)(ErlDrvData drv_data);
278                                 /* called when the port is closed abruptly.
279 				   specifically when erl_crash_dump is called. */
280     /* When adding entries here, dont forget to pad in obsolete/driver.h */
281 } ErlDrvEntry;
282 
283 /*
284  * This macro is used to name a dynamic driver's init function in
285  * a way that doesn't lead to conflicts. This is crucial when using
286  * operating systems that has one namespace for all symbols
287  * (e.g. VxWorks). Example: if you have an dynamic driver C source
288  * file named echo_drv.c, you use the macro like this:
289  *
290  *    DRIVER_INIT(echo_drv)
291  *    {
292  *	 ....
293  *    }
294  *
295  * This function will be called by the Erlang I/O system when the driver is loaded.
296  * It must initialize a ErlDrvEntry structure and return a pointer to it.
297  */
298 
299 #ifdef STATIC_ERLANG_DRIVER
300 #  define ERLANG_DRIVER_NAME(NAME) NAME ## _driver_init
301 #  define ERL_DRIVER_EXPORT
302 #else
303 #  define ERLANG_DRIVER_NAME(NAME) driver_init
304 #  if defined(__GNUC__) && __GNUC__ >= 4
305 #    define ERL_DRIVER_EXPORT __attribute__ ((visibility("default")))
306 #  elif defined (__SUNPRO_C) && (__SUNPRO_C >= 0x550)
307 #    define ERL_DRIVER_EXPORT __global
308 #  else
309 #    define ERL_DRIVER_EXPORT
310 #  endif
311 #endif
312 
313 #ifndef ERL_DRIVER_TYPES_ONLY
314 
315 #define DRIVER_INIT(DRIVER_NAME) \
316     ERL_DRIVER_EXPORT ErlDrvEntry* ERLANG_DRIVER_NAME(DRIVER_NAME)(void); \
317     ERL_DRIVER_EXPORT ErlDrvEntry* ERLANG_DRIVER_NAME(DRIVER_NAME)(void)
318 
319 #define ERL_DRV_BUSY_MSGQ_DISABLED	(~((ErlDrvSizeT) 0))
320 #define ERL_DRV_BUSY_MSGQ_READ_ONLY	((ErlDrvSizeT) 0)
321 #define ERL_DRV_BUSY_MSGQ_LIM_MAX	(ERL_DRV_BUSY_MSGQ_DISABLED - 1)
322 #define ERL_DRV_BUSY_MSGQ_LIM_MIN	((ErlDrvSizeT) 1)
323 
324 /*
325  * These are the functions available for driver writers.
326  */
327 EXTERN void erl_drv_busy_msgq_limits(ErlDrvPort port,
328 				     ErlDrvSizeT *low,
329 				     ErlDrvSizeT *high);
330 
331 EXTERN int driver_select(ErlDrvPort port, ErlDrvEvent event, int mode, int on);
332 
333 EXTERN int driver_output(ErlDrvPort port, char *buf, ErlDrvSizeT len);
334 EXTERN int driver_output2(ErlDrvPort port, char *hbuf, ErlDrvSizeT hlen,
335 			  char *buf, ErlDrvSizeT len);
336 EXTERN int driver_output_binary(ErlDrvPort port, char *hbuf, ErlDrvSizeT hlen,
337 				ErlDrvBinary* bin,
338 				ErlDrvSizeT offset, ErlDrvSizeT len);
339 EXTERN int driver_outputv(ErlDrvPort port, char* hbuf, ErlDrvSizeT hlen,
340 			  ErlIOVec *ev, ErlDrvSizeT skip);
341 EXTERN ErlDrvSizeT driver_vec_to_buf(ErlIOVec *ev, char *buf, ErlDrvSizeT len);
342 EXTERN int driver_set_timer(ErlDrvPort port, unsigned long time);
343 EXTERN int driver_cancel_timer(ErlDrvPort port);
344 EXTERN int driver_read_timer(ErlDrvPort port, unsigned long *time_left);
345 
346 /*
347  * Inform runtime system about lengthy work.
348  */
349 EXTERN int erl_drv_consume_timeslice(ErlDrvPort port, int percent);
350 
351 /*
352  * Get plain-text error message from within a driver
353  */
354 EXTERN char* erl_errno_id(int error);
355 
356 /*
357  * The following functions are used to initiate a close of a port
358  * from a driver.
359  */
360 EXTERN int driver_failure_eof(ErlDrvPort port);
361 EXTERN int driver_failure_atom(ErlDrvPort port, char *string);
362 EXTERN int driver_failure_posix(ErlDrvPort port, int error);
363 EXTERN int driver_failure(ErlDrvPort port, int error);
364 EXTERN int driver_exit (ErlDrvPort port, int err);
365 
366 
367 /*
368  * Port Data Lock
369  */
370 
371 EXTERN ErlDrvPDL driver_pdl_create(ErlDrvPort);
372 EXTERN void driver_pdl_lock(ErlDrvPDL);
373 EXTERN void driver_pdl_unlock(ErlDrvPDL);
374 EXTERN ErlDrvSInt driver_pdl_get_refc(ErlDrvPDL);
375 EXTERN ErlDrvSInt driver_pdl_inc_refc(ErlDrvPDL);
376 EXTERN ErlDrvSInt driver_pdl_dec_refc(ErlDrvPDL);
377 
378 /*
379  * Process monitors
380  */
381 EXTERN int
382 driver_monitor_process(ErlDrvPort port, ErlDrvTermData process,
383 		       ErlDrvMonitor *monitor);
384 EXTERN int
385 driver_demonitor_process(ErlDrvPort port, const ErlDrvMonitor *monitor);
386 EXTERN ErlDrvTermData
387 driver_get_monitored_process(ErlDrvPort port, const ErlDrvMonitor *monitor);
388 EXTERN int driver_compare_monitors(const ErlDrvMonitor *monitor1,
389 				   const ErlDrvMonitor *monitor2);
390 
391 /*
392  * Port attributes
393  */
394 EXTERN void set_busy_port(ErlDrvPort port, int on);
395 EXTERN void set_port_control_flags(ErlDrvPort port, int flags);
396 
397 EXTERN int  get_port_flags(ErlDrvPort port);
398 
399 
400 /* Binary interface */
401 
402 /*
403  * NOTE: DO NOT overwrite a binary with new data (if the data is delivered);
404  * since the binary is a shared object it MUST be written once.
405  */
406 
407 EXTERN ErlDrvBinary* driver_alloc_binary(ErlDrvSizeT size);
408 EXTERN ErlDrvBinary* driver_realloc_binary(ErlDrvBinary *bin, ErlDrvSizeT size);
409 EXTERN void driver_free_binary(ErlDrvBinary *bin);
410 
411 /* Referenc count on driver binaries */
412 EXTERN ErlDrvSInt driver_binary_get_refc(ErlDrvBinary *dbp);
413 EXTERN ErlDrvSInt driver_binary_inc_refc(ErlDrvBinary *dbp);
414 EXTERN ErlDrvSInt driver_binary_dec_refc(ErlDrvBinary *dbp);
415 
416 /* Allocation interface */
417 EXTERN void *driver_alloc(ErlDrvSizeT size);
418 EXTERN void *driver_realloc(void *ptr, ErlDrvSizeT size);
419 EXTERN void driver_free(void *ptr);
420 
421 /* Queue interface */
422 EXTERN int driver_enq(ErlDrvPort port, char* buf, ErlDrvSizeT len);
423 EXTERN int driver_pushq(ErlDrvPort port, char* buf, ErlDrvSizeT len);
424 EXTERN ErlDrvSizeT driver_deq(ErlDrvPort port, ErlDrvSizeT size);
425 EXTERN ErlDrvSizeT driver_sizeq(ErlDrvPort port);
426 EXTERN int driver_enq_bin(ErlDrvPort port, ErlDrvBinary *bin, ErlDrvSizeT offset,
427 			  ErlDrvSizeT len);
428 EXTERN int driver_pushq_bin(ErlDrvPort port, ErlDrvBinary *bin, ErlDrvSizeT offset,
429 			    ErlDrvSizeT len);
430 
431 EXTERN ErlDrvSizeT driver_peekqv(ErlDrvPort port, ErlIOVec *ev);
432 EXTERN SysIOVec* driver_peekq(ErlDrvPort port, int *vlen);
433 EXTERN int driver_enqv(ErlDrvPort port, ErlIOVec *ev, ErlDrvSizeT skip);
434 EXTERN int driver_pushqv(ErlDrvPort port, ErlIOVec *ev, ErlDrvSizeT skip);
435 
436 /*
437  * Add and remove driver entries.
438  */
439 EXTERN void add_driver_entry(ErlDrvEntry *de);
440 EXTERN int remove_driver_entry(ErlDrvEntry *de);
441 
442 /*
443  * System info
444  */
445 EXTERN void driver_system_info(ErlDrvSysInfo *sip, size_t si_size);
446 
447 /*
448  * erl driver thread functions.
449  */
450 
451 EXTERN ErlDrvMutex *erl_drv_mutex_create(char *name);
452 EXTERN void erl_drv_mutex_destroy(ErlDrvMutex *mtx);
453 EXTERN int erl_drv_mutex_trylock(ErlDrvMutex *mtx);
454 EXTERN void erl_drv_mutex_lock(ErlDrvMutex *mtx);
455 EXTERN void erl_drv_mutex_unlock(ErlDrvMutex *mtx);
456 EXTERN ErlDrvCond *erl_drv_cond_create(char *name);
457 EXTERN void erl_drv_cond_destroy(ErlDrvCond *cnd);
458 EXTERN void erl_drv_cond_signal(ErlDrvCond *cnd);
459 EXTERN void erl_drv_cond_broadcast(ErlDrvCond *cnd);
460 EXTERN void erl_drv_cond_wait(ErlDrvCond *cnd, ErlDrvMutex *mtx);
461 EXTERN ErlDrvRWLock *erl_drv_rwlock_create(char *name);
462 EXTERN void erl_drv_rwlock_destroy(ErlDrvRWLock *rwlck);
463 EXTERN int erl_drv_rwlock_tryrlock(ErlDrvRWLock *rwlck);
464 EXTERN void erl_drv_rwlock_rlock(ErlDrvRWLock *rwlck);
465 EXTERN void erl_drv_rwlock_runlock(ErlDrvRWLock *rwlck);
466 EXTERN int erl_drv_rwlock_tryrwlock(ErlDrvRWLock *rwlck);
467 EXTERN void erl_drv_rwlock_rwlock(ErlDrvRWLock *rwlck);
468 EXTERN void erl_drv_rwlock_rwunlock(ErlDrvRWLock *rwlck);
469 EXTERN int erl_drv_tsd_key_create(char *name, ErlDrvTSDKey *key);
470 EXTERN void erl_drv_tsd_key_destroy(ErlDrvTSDKey key);
471 EXTERN void erl_drv_tsd_set(ErlDrvTSDKey key, void *data);
472 EXTERN void *erl_drv_tsd_get(ErlDrvTSDKey key);
473 EXTERN ErlDrvThreadOpts *erl_drv_thread_opts_create(char *name);
474 EXTERN void erl_drv_thread_opts_destroy(ErlDrvThreadOpts *opts);
475 EXTERN int erl_drv_thread_create(char *name,
476 				 ErlDrvTid *tid,
477 				 void * (*func)(void *),
478 				 void *args,
479 				 ErlDrvThreadOpts *opts);
480 EXTERN ErlDrvTid erl_drv_thread_self(void);
481 EXTERN int erl_drv_equal_tids(ErlDrvTid tid1, ErlDrvTid tid2);
482 EXTERN void erl_drv_thread_exit(void *resp);
483 EXTERN int erl_drv_thread_join(ErlDrvTid, void **respp);
484 
485 EXTERN char* erl_drv_mutex_name(ErlDrvMutex *mtx);
486 EXTERN char* erl_drv_cond_name(ErlDrvCond *cnd);
487 EXTERN char* erl_drv_rwlock_name(ErlDrvRWLock *rwlck);
488 EXTERN char* erl_drv_thread_name(ErlDrvTid tid);
489 
490 /*
491  * Misc.
492  */
493 EXTERN int null_func(void);
494 
495 #endif /* !ERL_DRIVER_TYPES_ONLY */
496 
497 /* Constants for return flags from the 'port_call' callback */
498 #define DRIVER_CALL_KEEP_BUFFER 0x1
499 
500 /* ErlDrvTerm is the type to use for casts when building
501  * terms that should be sent to connected process,
502  * for instance a tuple on the form {tcp, Port, [Tag|Binary]}
503  *
504  * ErlDrvTerm spec[] = {
505  *    ERL_DRV_ATOM, driver_mk_atom("tcp"),
506  *    ERL_DRV_PORT, driver_mk_port(drv->ix),
507  *             ERL_DRV_INT, REPLY_TAG,
508  *             ERL_DRV_BINARY, (ErlDrvTerm)bin, 50, 0,
509  *             ERL_DRV_LIST, 2,
510  *    ERL_DRV_TUPLE, 3,
511  *  }
512  *
513  */
514 
515 #define TERM_DATA(x) ((ErlDrvTermData) (x))
516 
517 /* Possible types to send from driver          Argument type */
518 #define ERL_DRV_NIL         ((ErlDrvTermData) 1)  /* None */
519 #define ERL_DRV_ATOM        ((ErlDrvTermData) 2)  /* driver_mk_atom(string) */
520 #define ERL_DRV_INT         ((ErlDrvTermData) 3)  /* ErlDrvSInt */
521 #define ERL_DRV_PORT        ((ErlDrvTermData) 4)  /* driver_mk_port(ix) */
522 #define ERL_DRV_BINARY      ((ErlDrvTermData) 5)  /* ErlDrvBinary*,
523 						   * ErlDrvUInt size,
524 						   * ErlDrvUInt offs */
525 #define ERL_DRV_STRING      ((ErlDrvTermData) 6)  /* char*, ErlDrvUInt */
526 #define ERL_DRV_TUPLE       ((ErlDrvTermData) 7)  /* ErlDrvUInt */
527 #define ERL_DRV_LIST        ((ErlDrvTermData) 8)  /* ErlDrvUInt */
528 #define ERL_DRV_STRING_CONS ((ErlDrvTermData) 9)  /* char*, ErlDrvUInt */
529 #define ERL_DRV_PID         ((ErlDrvTermData) 10) /* driver_connected,... */
530 
531 #define ERL_DRV_FLOAT       ((ErlDrvTermData) 11) /* double * */
532 #define ERL_DRV_EXT2TERM    ((ErlDrvTermData) 12) /* char *, ErlDrvUInt */
533 #define ERL_DRV_UINT        ((ErlDrvTermData) 13) /* ErlDrvUInt */
534 #define ERL_DRV_BUF2BINARY  ((ErlDrvTermData) 14) /* char *, ErlDrvUInt */
535 #define ERL_DRV_INT64       ((ErlDrvTermData) 15) /* ErlDrvSInt64 * */
536 #define ERL_DRV_UINT64      ((ErlDrvTermData) 16) /* ErlDrvUInt64 * */
537 
538 #define ERL_DRV_MAP         ((ErlDrvTermData) 17) /* ErlDrvUInt */
539 
540 #ifndef ERL_DRIVER_TYPES_ONLY
541 
542 /* make terms for driver_output_term and driver_send_term */
543 EXTERN ErlDrvTermData driver_mk_atom(char*);
544 EXTERN ErlDrvTermData driver_mk_port(ErlDrvPort);
545 EXTERN ErlDrvTermData driver_connected(ErlDrvPort);
546 EXTERN ErlDrvTermData driver_caller(ErlDrvPort);
547 extern const ErlDrvTermData driver_term_nil;
548 EXTERN ErlDrvTermData driver_mk_term_nil(void);
549 EXTERN ErlDrvPort driver_create_port(ErlDrvPort creator_port,
550 				     ErlDrvTermData connected, /* pid */
551 				     char* name, /* driver name */
552 				     ErlDrvData drv_data);
553 
554 
555 /*
556  * driver_output_term() is deprecated, and scheduled for removal in
557  * OTP-R17. Use erl_drv_output_term() instead. For more information
558  * see the erl_driver(3) documentation.
559  */
560 EXTERN int driver_output_term(ErlDrvPort ix,
561 			      ErlDrvTermData* data,
562 			      int len) ERL_DRV_DEPRECATED_FUNC;
563 /*
564  * driver_send_term() is deprecated, and scheduled for removal in
565  * OTP-R17. Use erl_drv_send_term() instead. For more information
566  * see the erl_driver(3) documentation.
567  */
568 EXTERN int driver_send_term(ErlDrvPort ix,
569 			    ErlDrvTermData to,
570 			    ErlDrvTermData* data,
571 			    int len) ERL_DRV_DEPRECATED_FUNC;
572 
573 /* output term data to the port owner */
574 EXTERN int erl_drv_output_term(ErlDrvTermData port,
575 			       ErlDrvTermData* data,
576 			       int len);
577 /* output term data to a specific process */
578 EXTERN int erl_drv_send_term(ErlDrvTermData port,
579 			     ErlDrvTermData to,
580 			     ErlDrvTermData* data,
581 			     int len);
582 
583 /* Async IO functions */
584 EXTERN unsigned int driver_async_port_key(ErlDrvPort port);
585 
586 EXTERN long driver_async(ErlDrvPort ix,
587 			 unsigned int* key,
588 			 void (*async_invoke)(void*),
589 			 void* async_data,
590 			 void (*async_free)(void*));
591 
592 /* Locks the driver in the machine "forever", there is
593    no unlock function. Note that this is almost never useful, as an open
594    port towards the driver locks it until the port is closed, why unexpected
595    unloading "never" happens. */
596 EXTERN int driver_lock_driver(ErlDrvPort ix);
597 
598 /* Get the current 'now' timestamp (analogue to erlang:now()) */
599 EXTERN int driver_get_now(ErlDrvNowData *now) ERL_DRV_DEPRECATED_FUNC;
600 
601 /* Erlang Monotonic Time */
602 EXTERN ErlDrvTime erl_drv_monotonic_time(ErlDrvTimeUnit time_unit);
603 /* Time offset between Erlang Monotonic Time and Erlang System Time */
604 EXTERN ErlDrvTime erl_drv_time_offset(ErlDrvTimeUnit time_unit);
605 /* Time unit conversion */
606 EXTERN ErlDrvTime erl_drv_convert_time_unit(ErlDrvTime val,
607 					    ErlDrvTimeUnit from,
608 					    ErlDrvTimeUnit to);
609 
610 /* These were removed from the ANSI version, now they're back. */
611 
612 EXTERN void *driver_dl_open(char *);
613 EXTERN void *driver_dl_sym(void *, char *);
614 EXTERN int driver_dl_close(void *);
615 EXTERN char *driver_dl_error(void);
616 
617 /* environment */
618 EXTERN int erl_drv_putenv(const char *key, char *value);
619 EXTERN int erl_drv_getenv(const char *key, char *value, size_t *value_size);
620 
621 /* spawn start init ack */
622 EXTERN void erl_drv_init_ack(ErlDrvPort ix, ErlDrvData res);
623 
624 /* set the pid seen in port_info */
625 EXTERN void erl_drv_set_os_pid(ErlDrvPort ix, ErlDrvSInt pid);
626 
627 #endif /* !ERL_DRIVER_TYPES_ONLY */
628 
629 #ifdef WIN32_DYNAMIC_ERL_DRIVER
630 #  include "erl_win_dyn_driver.h"
631 #endif
632 
633 #endif
634 
635 /* also in global.h, but driver's can't include global.h */
636 void dtrace_drvport_str(ErlDrvPort port, char *port_buf);
637