aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/obsolete/driver.h
blob: 708fe68e1a68054b89e2f1a6de7bc19939a706f4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
/*
 * %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 <stdlib.h>
#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