/* * %CopyrightBegin% * * Copyright Ericsson AB 1996-2009. All Rights Reserved. * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * %CopyrightEnd% */ /* * OLD, OBSOLETE include file for erlang driver writers. * New drivers should use erl_driver.h instead. */ #ifndef __DRIVER_H__ #define __DRIVER_H__ #include #include "driver_int.h" #undef _ANSI_ARGS_ #undef CONST #if ((defined(__STDC__) || defined(SABER)) && !defined(NO_PROTOTYPE)) || defined(__cplusplus) || defined(USE_PROTOTYPE) # define _USING_PROTOTYPES_ 1 # define _ANSI_ARGS_(x) x # define CONST const #else # define _ANSI_ARGS_(x) () # define CONST #endif #ifdef __cplusplus # define EXTERN extern "C" #else # define EXTERN extern #endif /* Values for mode arg to driver_select() */ #define DO_READ (1 << 0) #define DO_WRITE (1 << 1) /* Flags for set_port_control_flags() */ #define PORT_CONTROL_FLAG_BINARY 1 #define PORT_CONTROL_FLAG_HEAVY 2 /* This macro is used to name a dynamic driver's init function in */ /* a way that doesn't lead to conflicts. This is crucial when using */ /* operating systems that has one namespace for all symbols */ /* (e.g. VxWorks). Example: if you have an dynamic driver C source */ /* file named echo_drv.c, you use the macro like this: */ /* int DRIVER_INIT(echo_drv)(void *handle) */ #if defined(VXWORKS) # define DRIVER_INIT(DRIVER_NAME) DRIVER_NAME ## _init #elif defined(__WIN32__) # define DRIVER_INIT(DRIVER_NAME) __declspec(dllexport) driver_init #else # define DRIVER_INIT(DRIVER_NAME) driver_init #endif typedef int (*F_PTR)(); /* a function pointer */ typedef long (*L_PTR)(); /* pointer to a function returning long */ extern int null_func(); /* This structure MUST match Binary in global.h exactly!!! */ typedef struct driver_binary { int orig_size; /* total length of binary */ char orig_bytes[1]; /* the data (char instead of byte!) */ } DriverBinary; typedef struct { int vsize; /* length of vectors */ int size; /* total size in bytes */ SysIOVec* iov; DriverBinary** binv; } ErlIOVec; /* * OLD, OBSOLETE driver entry structure. */ typedef struct driver_entry { F_PTR init; /* called at system start up (no args) */ L_PTR start; /* called when some one does an open_port args: port, command (nul-terminated), additional/alternate args for fd/vanilla/spawn driver. return value -1 means failure, other is saved and passed to the other funcs */ F_PTR stop; /* called when port is closed, and when the emulator is halted - arg: start_return */ F_PTR output; /* called when we have output from erlang to the port args: start_return, buf, buflen */ F_PTR ready_input; /* called when we have input from one of the driver's file descriptors - args: start_return, fd */ F_PTR ready_output; /* called when output is possible to one of the driver's file descriptors - args: start_return, fd */ char *driver_name; /* name supplied as {driver,Name,Args} to open_port */ F_PTR finish; /* called before unloading (DYNAMIC DRIVERS ONLY) */ void *handle; /* file handle (DYNAMIC DRIVERS ONLY) */ F_PTR control; /* "ioctl" for drivers (invoked by port_command/3) */ F_PTR timeout; /* Reserved */ F_PTR outputv; /* Reserved */ F_PTR ready_async; /* Completion routine for driver_async */ F_PTR padding1[3]; /* pad to match size of modern driver struct */ int padding2[4]; /* more pad */ F_PTR padding3[3]; /* even more padding */ } DriverEntry; /* These are the kernel functions available for driver writers */ EXTERN int driver_select _ANSI_ARGS_((int,int,int,int)); EXTERN int driver_output _ANSI_ARGS_((int, char*, int)); EXTERN int driver_output2 _ANSI_ARGS_((int, char*, int, char*, int)); EXTERN int driver_output_binary _ANSI_ARGS_((int, char*, int, DriverBinary*, int, int)); EXTERN int driver_outputv _ANSI_ARGS_((int, char*,int,ErlIOVec*,int)); EXTERN int driver_vec_to_buf _ANSI_ARGS_((ErlIOVec*, char*, int)); EXTERN int driver_set_timer _ANSI_ARGS_((int, unsigned long)); EXTERN int driver_cancel_timer _ANSI_ARGS_((int)); /* * The following functions are used to initiate a close of a port * from a driver. */ EXTERN int driver_failure_eof _ANSI_ARGS_((int)); EXTERN int driver_failure_atom _ANSI_ARGS_((int, char *)); EXTERN int driver_failure_posix _ANSI_ARGS_((int, int)); EXTERN int driver_failure _ANSI_ARGS_((int, int)); EXTERN int driver_exit _ANSI_ARGS_ ((int, int)); EXTERN char* erl_errno_id _ANSI_ARGS_((int error)); EXTERN void set_busy_port _ANSI_ARGS_((int, int)); EXTERN void add_driver_entry _ANSI_ARGS_((DriverEntry *)); EXTERN int remove_driver_entry _ANSI_ARGS_((DriverEntry *)); EXTERN void set_port_control_flags _ANSI_ARGS_((int, int)); /* Binary interface */ /* NOTE: DO NOT overwrite a binary with new data (if the data is delivered); ** since the binary is a shared object it MUST be written once. */ EXTERN DriverBinary* driver_alloc_binary _ANSI_ARGS_((int)); EXTERN DriverBinary* driver_realloc_binary _ANSI_ARGS_((DriverBinary*, int)); EXTERN void driver_free_binary _ANSI_ARGS_((DriverBinary*)); /* Queue interface */ EXTERN int driver_enqv _ANSI_ARGS_((int, ErlIOVec*, int)); EXTERN int driver_pushqv _ANSI_ARGS_((int, ErlIOVec*, int)); EXTERN int driver_deq _ANSI_ARGS_((int, int)); EXTERN SysIOVec* driver_peekq _ANSI_ARGS_((int, int*)); EXTERN int driver_sizeq _ANSI_ARGS_((int)); EXTERN int driver_enq_bin _ANSI_ARGS_((int, DriverBinary*, int, int)); EXTERN int driver_enq _ANSI_ARGS_((int, char*, int)); EXTERN int driver_pushq_bin _ANSI_ARGS_((int, DriverBinary*, int, int)); EXTERN int driver_pushq _ANSI_ARGS_((int, char*, int)); /* Memory management */ EXTERN void *driver_alloc _ANSI_ARGS_((size_t)); EXTERN void *driver_realloc _ANSI_ARGS_((void*, size_t)); EXTERN void driver_free _ANSI_ARGS_((void*)); /* Shared / dynamic link libraries */ EXTERN void *driver_dl_open _ANSI_ARGS_((char *)); EXTERN void *driver_dl_sym _ANSI_ARGS_((void *, char *)); EXTERN int driver_dl_close _ANSI_ARGS_((void *)); EXTERN char *driver_dl_error _ANSI_ARGS_((void)); /* Async IO functions */ EXTERN long driver_async _ANSI_ARGS_((int, unsigned int*, void (*)(void*), void *, void (*)(void*))); EXTERN int driver_async_cancel _ANSI_ARGS_((long)); EXTERN int driver_lock_driver _ANSI_ARGS_((int)); /* Threads */ typedef void* erl_mutex_t; typedef void* erl_cond_t; typedef void* erl_thread_t; EXTERN erl_mutex_t erts_mutex_create _ANSI_ARGS_((void)); EXTERN int erts_mutex_destroy _ANSI_ARGS_((erl_mutex_t)); EXTERN int erts_mutex_lock _ANSI_ARGS_((erl_mutex_t)); EXTERN int erts_mutex_unlock _ANSI_ARGS_((erl_mutex_t)); EXTERN erl_cond_t erts_cond_create _ANSI_ARGS_((void)); EXTERN int erts_cond_destroy _ANSI_ARGS_((erl_cond_t)); EXTERN int erts_cond_signal _ANSI_ARGS_((erl_cond_t)); EXTERN int erts_cond_broadcast _ANSI_ARGS_((erl_cond_t)); EXTERN int erts_cond_wait _ANSI_ARGS_((erl_cond_t, erl_mutex_t)); EXTERN int erts_cond_timedwait _ANSI_ARGS_((erl_cond_t, erl_mutex_t, long)); EXTERN int erts_thread_create _ANSI_ARGS_((erl_thread_t*, void* (*func)(void*), void* arg, int detached)); EXTERN erl_thread_t erts_thread_self _ANSI_ARGS_((void)); EXTERN void erts_thread_exit _ANSI_ARGS_((void*)); EXTERN int erts_thread_join _ANSI_ARGS_((erl_thread_t, void**)); EXTERN int erts_thread_kill _ANSI_ARGS_((erl_thread_t)); typedef unsigned long DriverTermData; #define TERM_DATA(x) ((DriverTermData) (x)) /* Possible types to send from driver Argument type */ #define ERL_DRV_NIL ((DriverTermData) 1) /* None */ #define ERL_DRV_ATOM ((DriverTermData) 2) /* driver_mk_atom(string) */ #define ERL_DRV_INT ((DriverTermData) 3) /* int */ #define ERL_DRV_PORT ((DriverTermData) 4) /* driver_mk_port(ix) */ #define ERL_DRV_BINARY ((DriverTermData) 5) /* ErlDriverBinary*, int */ #define ERL_DRV_STRING ((DriverTermData) 6) /* char*, int */ #define ERL_DRV_TUPLE ((DriverTermData) 7) /* int */ #define ERL_DRV_LIST ((DriverTermData) 8) /* int */ #define ERL_DRV_STRING_CONS ((DriverTermData) 9) /* char*, int */ #define ERL_DRV_PID ((DriverTermData) 10) /* driver_connected,... */ /* DriverTermData is the type to use for casts when building * terms that should be sent to connected process, * for instance a tuple on the form {tcp, Port, [Tag|Binary]} * * DriverTermData spec[] = { * ERL_DRV_ATOM, driver_mk_atom("tcp"), * ERL_DRV_PORT, driver_mk_port(drv->ix), * ERL_DRV_INT, REPLY_TAG, * ERL_DRV_BIN, 50, TERM_DATA(buffer), * ERL_DRV_LIST, 2, * ERL_DRV_TUPLE, 3, * } * */ EXTERN DriverTermData driver_mk_atom _ANSI_ARGS_ ((char*)); EXTERN DriverTermData driver_mk_port _ANSI_ARGS_ ((int)); EXTERN DriverTermData driver_connected _ANSI_ARGS_((int)); EXTERN DriverTermData driver_caller _ANSI_ARGS_((int)); EXTERN int driver_output_term _ANSI_ARGS_((int, DriverTermData *, int)); EXTERN int driver_send_term _ANSI_ARGS_((int, DriverTermData, DriverTermData *, int)); #endif