summaryrefslogtreecommitdiffstats
path: root/pcilib/pcipywrap.c
blob: bed4b310fae1b0b9388e52497867a94dfcffcc9e (plain)
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
#include "pci.h"
#include "error.h"
#include "pcipywrap.h"

/*!
 * \brief Global pointer to pcilib_t context.
 * Used by __setPcilib and read_register.
 */
pcilib_t* __ctx = 0;

/*!
 * \brief Wraps for pcilib_open function.
 * \param[in] fpga_device path to the device file [/dev/fpga0]
 * \param[in] model specifies the model of hardware, autodetected if NULL is passed
 * \return Pointer to pcilib_t, created by pcilib_open, serialized to bytearray
 */
PyObject* __createPcilibInstance(const char *fpga_device, const char *model)
{
	//opening device
    pcilib_t* ctx = pcilib_open(fpga_device, model);
    
    //serializing object
    return PyByteArray_FromStringAndSize((const char*)&ctx, sizeof(pcilib_t*));
}

/*!
 * \brief Sets python exeption text. Function interface same as printf.
 */
void setPyExeptionText(const char* msg, ...)
{
	char *buf;
	size_t sz;
	
	va_list vl, vl_copy;
    va_start(vl, msg);
	va_copy(vl_copy, vl);
	
	sz = vsnprintf(NULL, 0, msg, vl);
	buf = (char *)malloc(sz + 1);
	
	if(!buf)
	{
		PyErr_SetString(PyExc_Exception, "Memory error");
		return;
	}

	vsnprintf(buf, sz+1, msg, vl_copy);
	va_end(vl_copy);
	va_end(vl);
	
	PyErr_SetString(PyExc_Exception, buf);
	free(buf);
}

/*!
 * \brief Sets pcilib context to wraper.
 * \param[in] addr Pointer to pcilib_t, serialized to bytearray
 * \return true, serialized to PyObject, NULL with exeption text, if failed.
 */
PyObject* __setPcilib(PyObject* addr)
{
	if(!PyByteArray_Check(addr))
	{
		setPyExeptionText(PyExc_Exception, "Incorrect addr type. Only bytearray is allowed");
		return;
	}
	
	//deserializing adress
	char* pAddr = PyByteArray_AsString(addr);
	
	//hard copy context adress
	for(int i = 0; i < sizeof(pcilib_t*) + 10; i++)
		((char*)&__ctx)[i] = pAddr[i];

	free(pAddr);
	
	return PyInt_FromLong((long)1);
}

PyObject* pcilib_convert_val_to_pyobject(pcilib_t* ctx, pcilib_value_t *val, void (*errstream)(const char* msg, ...))
{
	int err;
	
	switch(val->type)
	{
		case PCILIB_TYPE_INVALID:
            errstream("Invalid register output type (PCILIB_TYPE_INVALID)");
			return NULL;
			
		case PCILIB_TYPE_STRING:
            errstream("Invalid register output type (PCILIB_TYPE_STRING)");
			return NULL;
		
		case PCILIB_TYPE_LONG:
		{
			long ret;
			ret = pcilib_get_value_as_int(__ctx, val, &err);
			
			if(err)
			{
                errstream("Failed: pcilib_get_value_as_int (%i)", err);
				return NULL;
			}
			return PyInt_FromLong((long) ret);
		}
		
		case PCILIB_TYPE_DOUBLE:
		{
			double ret;
			ret = pcilib_get_value_as_float(__ctx, val, &err);
			
			if(err)
			{
                errstream("Failed: pcilib_get_value_as_int (%i)", err);
				return NULL;
			}
			return PyFloat_FromDouble((double) ret);
		}
		
		default:
            errstream("Invalid register output type (unknown)");
			return NULL;
	}
}

int pcilib_convert_pyobject_to_val(pcilib_t* ctx, PyObject* pyVal, pcilib_value_t *val)
{
	int err;
	
    if(PyInt_Check(pyVal))
    {
        err = pcilib_set_value_from_int(ctx, val, PyInt_AsLong(pyVal));
    }
    else
        if(PyFloat_Check(pyVal))
            err = pcilib_set_value_from_float(ctx, val, PyFloat_AsDouble(pyVal));
        else
            if(PyString_Check(pyVal))
                err = pcilib_set_value_from_static_string(ctx, val, PyString_AsString(pyVal));
                else
                {
                    pcilib_error("Invalid input. Input type should be int, float or string.");
                    return PCILIB_ERROR_NOTSUPPORTED;
                }
    if(err)
        return err;
        
    return 0;
}


/*!
 * \brief Reads register value.
 * \param[in] regname the name of the register
 * \param[in] bank should specify the bank name if register with the same name may occur in multiple banks, NULL otherwise
 * \return register value, can be integer or float type
 */
PyObject* read_register(const char *regname, const char *bank)
{
	if(!__ctx)
	{
		setPyExeptionText("pcilib_t handler not initialized");
		return NULL;
	}
    
    pcilib_get_dma_description(__ctx);

	pcilib_value_t val = {0};
    pcilib_register_value_t reg_value;
	
	int err; 
	
	err = pcilib_read_register(__ctx, bank, regname, &reg_value);
	if(err)
	{
		setPyExeptionText("Failed: read_register (%i)", err);
		return NULL;
	}
	
	err = pcilib_set_value_from_register_value(__ctx, &val, reg_value);
	if(err)
	{
		setPyExeptionText("Failed: pcilib_set_value_from_register_value (%i)", err);
		return NULL;
	}

    return pcilib_convert_val_to_pyobject(__ctx, &val, setPyExeptionText);
}


PyObject* get_property(const char *prop)
{
	if(!__ctx)
	{
		setPyExeptionText("pcilib_t handler not initialized");
		return NULL;
	}
	
	int err;
	pcilib_value_t val = {0};
	
	err  = pcilib_get_property(__ctx, prop, &val);
	
	if(err)
	{
			setPyExeptionText("Failed pcilib_get_property (%i)", err);
			return NULL;
	}
	
    return pcilib_convert_val_to_pyobject(__ctx, &val, setPyExeptionText);
}

PyObject* set_property(const char *prop, PyObject* val)
{
	int err;
	
	if(!__ctx)
	{
		setPyExeptionText("pcilib_t handler not initialized");
		return NULL;
	}
	
	pcilib_value_t val_internal = {0};
	err = pcilib_convert_pyobject_to_val(__ctx, val, &val_internal);
	if(err)
	{
		setPyExeptionText("pcilib_convert_pyobject_to_val (%i)", err);
		return NULL;
	}
	
	err  = pcilib_set_property(__ctx, prop, &val_internal);
	
	if(err)
	{
		setPyExeptionText("Failed pcilib_get_property (%i)", err);
		return NULL;
	}
	
	return PyInt_FromLong((long)1);
}