Line data Source code
1 : /********************************************************************\
2 :
3 : Name: nulldev.c
4 : Created by: Stefan Ritt
5 :
6 : Contents: NULL Device Driver. This file can be used as a
7 : template to write a read device driver
8 :
9 : $Id$
10 :
11 : \********************************************************************/
12 :
13 : #include <stdio.h>
14 : #include <stdlib.h>
15 : #include <stdarg.h>
16 : #include <string.h>
17 : #include <math.h>
18 : #include "midas.h"
19 :
20 : /*---- globals -----------------------------------------------------*/
21 :
22 : #define DEFAULT_TIMEOUT 10000 /* 10 sec. */
23 :
24 : /* Store any parameters the device driver needs in following
25 : structure. Edit the NULLDEV_SETTINGS_STR accordingly. This
26 : contains usually the address of the device. For a CAMAC device
27 : this could be crate and station for example. */
28 :
29 : typedef struct {
30 : int address;
31 : } NULLDEV_SETTINGS;
32 :
33 : #define NULLDEV_SETTINGS_STR "\
34 : Address = INT : 1\n\
35 : "
36 :
37 : /* following structure contains private variables to the device
38 : driver. It is necessary to store it here in case the device
39 : driver is used for more than one device in one frontend. If it
40 : would be stored in a global variable, one device could over-
41 : write the other device's variables. */
42 :
43 : typedef struct {
44 : NULLDEV_SETTINGS nulldev_settings;
45 : float *array;
46 : INT num_channels;
47 : INT(*bd) (INT cmd, ...); /* bus driver entry function */
48 : void *bd_info; /* private info of bus driver */
49 : HNDLE hkey; /* ODB key for bus driver info */
50 : } NULLDEV_INFO;
51 :
52 : /*---- device driver routines --------------------------------------*/
53 :
54 : typedef INT(func_t) (INT cmd, ...);
55 :
56 : /* the init function creates a ODB record which contains the
57 : settings and initialized it variables as well as the bus driver */
58 :
59 0 : INT nulldev_init(HNDLE hkey, NULLDEV_INFO **pinfo, INT channels, func_t *bd)
60 : {
61 : int status, size;
62 : HNDLE hDB, hkeydd;
63 : NULLDEV_INFO *info;
64 :
65 : /* allocate info structure */
66 0 : info = (NULLDEV_INFO*) calloc(1, sizeof(NULLDEV_INFO));
67 0 : *pinfo = info;
68 :
69 0 : cm_get_experiment_database(&hDB, NULL);
70 :
71 : /* create NULLDEV settings record */
72 0 : status = db_create_record(hDB, hkey, "DD", NULLDEV_SETTINGS_STR);
73 0 : if (status != DB_SUCCESS)
74 0 : return FE_ERR_ODB;
75 :
76 0 : db_find_key(hDB, hkey, "DD", &hkeydd);
77 0 : size = sizeof(info->nulldev_settings);
78 0 : db_get_record(hDB, hkeydd, &info->nulldev_settings, &size, 0);
79 :
80 : /* initialize driver */
81 0 : info->num_channels = channels;
82 0 : info->array = (float*) calloc(channels, sizeof(float));
83 0 : info->bd = bd;
84 0 : info->hkey = hkey;
85 :
86 0 : if (!bd)
87 0 : return FE_ERR_ODB;
88 :
89 : /* initialize bus driver */
90 0 : status = info->bd(CMD_INIT, info->hkey, &info->bd_info);
91 :
92 0 : if (status != SUCCESS)
93 0 : return status;
94 :
95 : /* initialization of device, something like ... */
96 0 : BD_PUTS("init");
97 :
98 0 : return FE_SUCCESS;
99 : }
100 :
101 : /*----------------------------------------------------------------------------*/
102 :
103 0 : INT nulldev_exit(NULLDEV_INFO * info)
104 : {
105 : /* call EXIT function of bus driver, usually closes device */
106 0 : info->bd(CMD_EXIT, info->bd_info);
107 :
108 : /* free local variables */
109 0 : if (info->array)
110 0 : free(info->array);
111 :
112 0 : free(info);
113 :
114 0 : return FE_SUCCESS;
115 : }
116 :
117 : /*----------------------------------------------------------------------------*/
118 :
119 0 : INT nulldev_set(NULLDEV_INFO * info, INT channel, float value)
120 : {
121 : char str[80];
122 :
123 : /* set channel to a specific value, something like ... */
124 0 : sprintf(str, "SET %d %lf", channel, value);
125 0 : BD_PUTS(str);
126 0 : BD_GETS(str, sizeof(str), ">", DEFAULT_TIMEOUT);
127 :
128 : /* simulate writing by storing value in local array, has to be removed
129 : in a real driver */
130 0 : if (channel < info->num_channels)
131 0 : info->array[channel] = value;
132 :
133 0 : return FE_SUCCESS;
134 : }
135 :
136 : /*----------------------------------------------------------------------------*/
137 :
138 0 : INT nulldev_get(NULLDEV_INFO * info, INT channel, float *pvalue)
139 : {
140 : char str[80];
141 :
142 : /* read value from channel, something like ... */
143 0 : sprintf(str, "GET %d", channel);
144 0 : BD_PUTS(str);
145 0 : BD_GETS(str, sizeof(str), ">", DEFAULT_TIMEOUT);
146 :
147 0 : *pvalue = (float) atof(str);
148 :
149 : /* simulate reading by generating some sine wave data */
150 0 : if (channel < info->num_channels) {
151 0 : time_t t = time(NULL);
152 0 : *pvalue = 5 + 5 * sin(M_PI * t / 60) + 10 * channel;
153 : } else
154 0 : *pvalue = 0.f;
155 :
156 0 : return FE_SUCCESS;
157 : }
158 :
159 : /*---- device driver entry point -----------------------------------*/
160 :
161 0 : INT nulldev(INT cmd, ...)
162 : {
163 : va_list argptr;
164 : HNDLE hKey;
165 : INT channel, status;
166 : float value, *pvalue;
167 : NULLDEV_INFO *info;
168 :
169 0 : va_start(argptr, cmd);
170 0 : status = FE_SUCCESS;
171 :
172 0 : switch (cmd) {
173 0 : case CMD_INIT: {
174 0 : hKey = va_arg(argptr, HNDLE);
175 0 : NULLDEV_INFO** pinfo = va_arg(argptr, NULLDEV_INFO **);
176 0 : channel = va_arg(argptr, INT);
177 0 : va_arg(argptr, DWORD);
178 0 : func_t *bd = va_arg(argptr, func_t *);
179 0 : status = nulldev_init(hKey, pinfo, channel, bd);
180 0 : break;
181 : }
182 0 : case CMD_EXIT:
183 0 : info = va_arg(argptr, NULLDEV_INFO *);
184 0 : status = nulldev_exit(info);
185 0 : break;
186 :
187 0 : case CMD_SET:
188 0 : info = va_arg(argptr, NULLDEV_INFO *);
189 0 : channel = va_arg(argptr, INT);
190 0 : value = (float) va_arg(argptr, double); // floats are passed as double
191 0 : status = nulldev_set(info, channel, value);
192 0 : break;
193 :
194 0 : case CMD_GET:
195 0 : info = va_arg(argptr, NULLDEV_INFO *);
196 0 : channel = va_arg(argptr, INT);
197 0 : pvalue = va_arg(argptr, float *);
198 0 : status = nulldev_get(info, channel, pvalue);
199 0 : break;
200 :
201 0 : default:
202 0 : break;
203 : }
204 :
205 0 : va_end(argptr);
206 :
207 0 : return status;
208 : }
209 :
210 : /*------------------------------------------------------------------*/
|