~ubuntu-branches/ubuntu/trusty/geis/trusty

« back to all changes in this revision

Viewing changes to libgeis/geis_device.c

  • Committer: Package Import Robot
  • Author(s): Chase Douglas
  • Date: 2012-07-30 08:51:42 UTC
  • Revision ID: package-import@ubuntu.com-20120730085142-jrc33ygjvt0ob1wl
Tags: upstream-2.2.11
ImportĀ upstreamĀ versionĀ 2.2.11

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * @file libgeis/geis_region.c
 
3
 * @brief implementation of the GEIS v2.0 API Input Device module
 
4
 *
 
5
 * Copyright 2010, 2010 Canonical Ltd.
 
6
 *
 
7
 * This library is free software; you can redistribute it and/or modify it under
 
8
 * the terms of the GNU Lesser General Public License as published by the Free
 
9
 * Software Foundation; either version 3 of the License, or (at your option) any
 
10
 * later version.
 
11
 *
 
12
 * This library is distributed in the hope that it will be useful, but WITHOUT
 
13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 
14
 * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
 
15
 * details.
 
16
 *
 
17
 * You should have received a copy of the GNU Lesser General Public License
 
18
 * along with this program; if not, write to the Free Software Foundation, Inc.,
 
19
 * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 
20
 */
 
21
#include "geis_config.h"
 
22
#include "geis_device.h"
 
23
 
 
24
#include "geis_atomic.h"
 
25
#include "geis_attr.h"
 
26
#include "geis_logging.h"
 
27
#include <stdlib.h>
 
28
#include <string.h>
 
29
 
 
30
 
 
31
struct _GeisDevice
 
32
{
 
33
  GeisRefCount ref_count;
 
34
  GeisAttrBag  attr_bag;
 
35
};
 
36
 
 
37
struct _GeisDeviceBag
 
38
{
 
39
  GeisDevice *device_store;
 
40
  GeisSize    device_store_size;
 
41
  GeisSize    device_count;
 
42
};
 
43
 
 
44
static const int device_bag_growth_constant = 2;
 
45
 
 
46
 
 
47
GeisDeviceBag
 
48
geis_device_bag_new()
 
49
{
 
50
  GeisDeviceBag bag = calloc(1, sizeof(struct _GeisDeviceBag));
 
51
  if (!bag)
 
52
  {
 
53
    geis_error("error allocating device bag");
 
54
    goto final_exit;
 
55
  }
 
56
 
 
57
  bag->device_store = calloc(1, sizeof(struct _GeisDevice));
 
58
  if (!bag->device_store)
 
59
  {
 
60
    geis_error("error allocating device bag store");
 
61
    goto unwind_bag;
 
62
  }
 
63
 
 
64
  bag->device_store_size = 1;
 
65
  bag->device_count = 0;
 
66
  goto final_exit;
 
67
 
 
68
unwind_bag:
 
69
  free(bag);
 
70
  bag = NULL;
 
71
final_exit:
 
72
  return bag;
 
73
}
 
74
 
 
75
 
 
76
void
 
77
geis_device_bag_delete(GeisDeviceBag bag)
 
78
{
 
79
  GeisSize i;
 
80
  for (i = bag->device_count; i > 0; --i)
 
81
  {
 
82
    geis_device_unref(bag->device_store[i-1]);
 
83
  }
 
84
  free(bag->device_store);
 
85
  free(bag);
 
86
}
 
87
 
 
88
 
 
89
GeisSize
 
90
geis_device_bag_count(GeisDeviceBag bag)
 
91
{
 
92
  return bag->device_count;
 
93
}
 
94
 
 
95
 
 
96
GeisDevice
 
97
geis_device_bag_device(GeisDeviceBag bag, GeisSize index)
 
98
{
 
99
  GeisDevice device = NULL;
 
100
  if (index >= bag->device_count)
 
101
  {
 
102
    geis_warning("device bag index out of range");
 
103
  }
 
104
  else
 
105
  {
 
106
    device = bag->device_store[index];
 
107
  }
 
108
  return device;
 
109
}
 
110
 
 
111
 
 
112
GeisStatus
 
113
geis_device_bag_insert(GeisDeviceBag bag, GeisDevice device)
 
114
{
 
115
  GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR;
 
116
  for (GeisSize i = 0; i < bag->device_count; ++i)
 
117
  {
 
118
    if (bag->device_store[i] == device)
 
119
    {
 
120
      geis_device_ref(device);
 
121
      goto final_exit;
 
122
    }
 
123
  }
 
124
 
 
125
  if (bag->device_count >= bag->device_store_size)
 
126
  {
 
127
    GeisSize new_store_size = bag->device_store_size * device_bag_growth_constant;
 
128
    GeisDevice *new_store = realloc(bag->device_store,
 
129
             new_store_size * sizeof(struct _GeisDevice));
 
130
    if (!new_store)
 
131
    {
 
132
      geis_error("failed to reallocate device bag");
 
133
      goto final_exit;
 
134
    }
 
135
    bag->device_store = new_store;
 
136
    bag->device_store_size = new_store_size;
 
137
  }
 
138
  bag->device_store[bag->device_count++] = geis_device_ref(device);
 
139
  status = GEIS_STATUS_SUCCESS;
 
140
 
 
141
final_exit:
 
142
  return status;
 
143
}
 
144
 
 
145
 
 
146
GeisStatus
 
147
geis_device_bag_remove(GeisDeviceBag bag, GeisDevice device)
 
148
{
 
149
  GeisSize i;
 
150
  GeisStatus status = GEIS_STATUS_SUCCESS;
 
151
  for (i = 0; i < bag->device_count; ++i)
 
152
  {
 
153
    if (bag->device_store[i] == device)
 
154
    {
 
155
      GeisSize j;
 
156
      geis_device_unref(bag->device_store[i]);
 
157
      --bag->device_count;
 
158
      for (j = i; j < bag->device_count; ++j)
 
159
      {
 
160
        bag->device_store[j] = bag->device_store[j+1];
 
161
      }
 
162
      break;
 
163
    }
 
164
  }
 
165
  return status;
 
166
}
 
167
 
 
168
 
 
169
/*
 
170
 * Creates a new, empty device.
 
171
 */
 
172
GeisDevice
 
173
geis_device_new(GeisString name, GeisInteger id)
 
174
{
 
175
  GeisAttr attr;
 
176
  GeisDevice device = calloc(1, sizeof(struct _GeisDevice));
 
177
  if (!device)
 
178
  {
 
179
    geis_error("error allocating input device");
 
180
    goto final_exit;
 
181
  }
 
182
 
 
183
  device->attr_bag = geis_attr_bag_new(4);
 
184
  if (!device->attr_bag)
 
185
  {
 
186
    geis_debug("error allocating attr bag");
 
187
    goto unwind_device;
 
188
  }
 
189
 
 
190
  attr = geis_attr_new(GEIS_DEVICE_ATTRIBUTE_NAME,
 
191
                       GEIS_ATTR_TYPE_STRING,
 
192
                       (void *)name);
 
193
  if (!attr)
 
194
  {
 
195
    geis_debug("error allocating device name attr");
 
196
    goto unwind_attrs;
 
197
  }
 
198
  geis_attr_bag_insert(device->attr_bag, attr);
 
199
 
 
200
  attr = geis_attr_new(GEIS_DEVICE_ATTRIBUTE_ID,
 
201
                       GEIS_ATTR_TYPE_INTEGER,
 
202
                       &id);
 
203
  if (!attr)
 
204
  {
 
205
    geis_debug("error allocating device id attr");
 
206
    goto unwind_attrs;
 
207
  }
 
208
  geis_attr_bag_insert(device->attr_bag, attr);
 
209
 
 
210
  geis_device_ref(device);
 
211
  goto final_exit;
 
212
 
 
213
unwind_attrs:
 
214
  geis_attr_bag_delete(device->attr_bag);
 
215
unwind_device:
 
216
  free(device);
 
217
  device = NULL;
 
218
final_exit:
 
219
  return device;
 
220
}
 
221
 
 
222
 
 
223
/*
 
224
 * Destroys a device.
 
225
 */
 
226
static void
 
227
_device_delete(GeisDevice device)
 
228
{
 
229
  geis_attr_bag_delete(device->attr_bag);
 
230
  free(device);
 
231
}
 
232
 
 
233
 
 
234
/*
 
235
 * Adds a reference count to a device.
 
236
 */
 
237
GeisDevice
 
238
geis_device_ref(GeisDevice device)
 
239
{
 
240
  geis_atomic_ref(&device->ref_count);
 
241
  return device;
 
242
}
 
243
 
 
244
 
 
245
/*
 
246
 * Removes a reference count from a device.
 
247
 */
 
248
void
 
249
geis_device_unref(GeisDevice device)
 
250
{
 
251
  if (0 ==  geis_atomic_unref(&device->ref_count))
 
252
  {
 
253
    _device_delete(device);
 
254
  }
 
255
}
 
256
 
 
257
 
 
258
/*
 
259
 * Gets the name of the input device.
 
260
 */
 
261
GeisString
 
262
geis_device_name(GeisDevice device)
 
263
{
 
264
  GeisString device_name = NULL;
 
265
  GeisAttr name_attr = geis_attr_bag_find(device->attr_bag,
 
266
                                          GEIS_DEVICE_ATTRIBUTE_NAME);
 
267
  if (name_attr)
 
268
  {
 
269
    device_name = geis_attr_value_to_string(name_attr);
 
270
  }
 
271
  return device_name;
 
272
}
 
273
 
 
274
 
 
275
/*
 
276
 * Gets the system identifier of the iput device.
 
277
 */
 
278
GeisInteger
 
279
geis_device_id(GeisDevice device)
 
280
{
 
281
  GeisInteger device_id = -1;
 
282
  GeisAttr attr = geis_attr_bag_find(device->attr_bag, GEIS_DEVICE_ATTRIBUTE_ID);
 
283
  if (attr)
 
284
  {
 
285
    device_id = geis_attr_value_to_integer(attr);
 
286
  }
 
287
  return device_id;
 
288
}
 
289
 
 
290
 
 
291
/*
 
292
 * Gets the number of attributes of the device.
 
293
 */
 
294
GeisSize
 
295
geis_device_attr_count(GeisDevice device)
 
296
{
 
297
  return geis_attr_bag_count(device->attr_bag);
 
298
}
 
299
 
 
300
 
 
301
/*
 
302
 * Inserts an attr into a device.
 
303
 */
 
304
void
 
305
geis_device_add_attr(GeisDevice device, GeisAttr attr)
 
306
{
 
307
  geis_attr_bag_insert(device->attr_bag, attr);
 
308
}
 
309
 
 
310
 
 
311
/*
 
312
 * Gets the indicated attribute of the device.
 
313
 */
 
314
GeisAttr
 
315
geis_device_attr(GeisDevice device, GeisSize index)
 
316
{
 
317
  return geis_attr_bag_attr(device->attr_bag, index);
 
318
}
 
319
 
 
320
/*
 
321
 * Gets a named attr.
 
322
 */
 
323
GeisAttr
 
324
geis_device_attr_by_name(GeisDevice device, GeisString attr_name)
 
325
{
 
326
  return geis_attr_bag_find(device->attr_bag, attr_name);
 
327
}