Tizen 2.0 Release
[adaptation/intel_mfld/sensor-plugins-mfld-blackbay.git] / src / baseprocessor.cpp
1 /* Medfield sensor plugins
2  * Copyright (C) 2013 Intel Corporation
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; version 2.1.
7  *
8  * This library is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * Lesser General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public
14  * License along with this library; if not, write to the Free Software
15  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301USA
16  */
17
18 #include <stdio.h>
19 #include <limits.h>
20 #include <dirent.h>
21 #include <fcntl.h>
22 #include <unistd.h>
23 #include <linux/input.h>
24 #include <errno.h>
25 #include "baseprocessor.h"
26 #include "log.h"
27 #include <algorithm>
28 #include <libudev.h>
29
30
31 BaseProcessor::BaseProcessor():
32      mId(0),
33      mVersion(0),
34      mStartCount(0),
35      mFd(-1),
36      mInputEventCount(0)
37 {
38      set_main(started,0,this);
39      memset(&mValues,0,sizeof(mValues));
40 }
41
42 BaseProcessor::~BaseProcessor()
43 {
44      if (mFd != -1)
45           close(mFd);
46 }
47
48 bool BaseProcessor::add_input(csensor_module *sensor)
49 {
50      DbgPrint("");
51      return true;
52 }
53
54 bool BaseProcessor::add_input(cfilter_module *filter)
55 {
56      DbgPrint("");
57      return true;
58 }
59
60 cprocessor_module *BaseProcessor::create_new(void)
61 {
62      DbgPrint("");
63      return this;
64 }
65
66 void BaseProcessor::destroy(cprocessor_module *module)
67 {
68      DbgPrint("");
69 }
70
71 const char *BaseProcessor::name(void)
72 {
73      DbgPrint("");
74      return mName.c_str();
75 }
76
77 int BaseProcessor::version(void)
78 {
79      DbgPrint("");
80      return mVersion;
81 }
82
83 int BaseProcessor::id(void)
84 {
85      DbgPrint("");
86      return mId;
87 }
88
89 bool BaseProcessor::update_name(char *name)
90 {
91      DbgPrint("");
92      mName = name;
93      return true;
94 }
95
96 bool BaseProcessor::update_version(int version)
97 {
98      DbgPrint("");
99      mVersion = version;
100      return true;
101 }
102
103 bool BaseProcessor::update_id(int id)
104 {
105      DbgPrint("");
106      mId = id;
107      return true;
108 }
109
110 long BaseProcessor::value(char *port)
111 {
112      DbgPrint("");
113      return 1;
114 }
115
116 long BaseProcessor::value(int id)
117 {
118      DbgPrint("");
119      return 1;
120 }
121
122
123 bool BaseProcessor::add_callback_func(cmd_reg_t *param)
124 {
125      DbgPrint("%s",mName.c_str());
126
127      if (!check_callback_event(param))
128           return false;
129
130      mCallbacks.push_back(*param);
131
132      return true;
133 }
134
135
136
137 bool operator==(const cmd_reg_t &a, const cmd_reg_t &b)
138 {
139      return (a.type == b.type && a.event_type == b.event_type &&
140              a.interval == b.interval);
141 }
142
143
144 bool BaseProcessor::remove_callback_func(cmd_reg_t *toRemove)
145 {
146      DbgPrint("");
147      std::vector<cmd_reg_t>::iterator iter;
148
149      iter = std::find(mCallbacks.begin(),mCallbacks.end(),*toRemove);
150
151      if (iter == mCallbacks.end())
152           return false;
153
154      mCallbacks.erase(iter,iter);
155
156
157      return true;
158 }
159
160 bool BaseProcessor::check_callback_event(cmd_reg_t *param)
161 {
162      DbgPrint("");
163      if (!param)
164           return false;
165
166      std::vector<int>::const_iterator iter;
167
168      for (iter = mSupportedEvents.begin(); iter != mSupportedEvents.end(); iter++) {
169           if ((*iter) == param->event_type)
170                return true;
171      }
172
173      DbgPrint("Requested event was not found");
174      return false;
175 }
176
177 long BaseProcessor::set_cmd(int type , int property , long input_value)
178 {
179      DbgPrint("");
180      return 0;
181
182 }
183
184 int BaseProcessor::get_property(unsigned int property_level , void *property_struct)
185 {
186      DbgPrint("Name %s level %d ",mName.c_str(), property_level);
187
188      if (!property_struct)
189           return -1;
190
191      base_property_struct *result = (base_property_struct*) property_struct;
192      return get_property(property_level, *result );
193 }
194
195 int BaseProcessor::get_property(unsigned int property_level , base_property_struct &result)
196 {
197      return -1;
198 }
199
200 int BaseProcessor::get_struct_value(unsigned int struct_type , void *struct_values)
201 {
202      DbgPrint("");
203      int count;
204
205      mValueMutex.lock();
206
207      data_accuracy accuracy = ACCURACY_UNDEFINED;
208      data_unit_idx_t unit = IDX_UNDEFINED_UNIT;
209
210      if (!fill_values(struct_type, count, unit, accuracy)) {
211           DbgPrint("Fill values returned false");
212           mValueMutex.unlock();
213           return -3;
214      }
215
216      base_data_struct *result = (base_data_struct *)struct_values;
217
218      for (int i = 0; i < count; i++) {
219           result->values[i] = this->mValues[i];
220           DbgPrint("result [%d] is %f",i, result->values[i] );
221      }
222      result->values_num = count;
223      result->data_accuracy = accuracy;
224
225
226      mValueMutex.unlock();
227
228      return 0;
229
230 }
231
232
233 void* BaseProcessor::started(void *ctx)
234 {
235      DbgPrint("");
236      return ((BaseProcessor *) ctx)->started();
237 }
238
239 void* BaseProcessor::started()
240 {
241      DbgPrint("");
242      if (mFd != -1 && mInputEventCount) {
243           input_event *events = new input_event[mInputEventCount];
244           const ssize_t readByteCount = read(mFd, events, mInputEventCount * sizeof(input_event));
245           DbgPrint("%s Readed %d bytes",mName.c_str(),readByteCount);
246
247           //Ignore partial event reads
248           if (readByteCount > 0 && readByteCount % sizeof(input_event) == 0) {
249                const int readEventCount = readByteCount / sizeof(input_event);
250                std::vector <input_event *> eventVector;
251                DbgPrint("Count of events is %d",readEventCount);
252                for (int i = 0; i < readEventCount; i++) {
253                     eventVector.push_back(&(events[i]));
254                }
255
256
257                mValueMutex.lock();
258                process_input_events(eventVector);
259                mValueMutex.unlock();
260           }
261
262           delete [] events;
263      }
264      return (void *) cworker::STARTED;
265 }
266
267 void BaseProcessor::process_input_events(const std::vector<input_event*> &events)
268 {
269      std::vector<input_event *>::const_iterator iterator;
270      for (iterator = events.begin(); iterator != events.end(); iterator++) {
271           const input_event& event = (**iterator);
272           switch(event.type) {
273           case EV_REL:
274           case EV_ABS:
275                DbgPrint("%s sensor got input code %d value %d\n",mName.c_str(), event.code, event.value);
276                if (event.code < sizeof(mValues)/sizeof(float))
277                     mValues[event.code] = event.value;
278                break;
279
280           case EV_SYN:
281                DbgPrint("Syn event");
282                break;
283
284           default:
285                DbgPrint("Unknown event type %d", event.type);
286
287           }
288      }
289 }
290
291 bool BaseProcessor::start(void)
292 {
293      mStartCount++;
294
295      if (mStartCount > 1)
296           return true;
297
298      enable();
299
300      return cprocessor_module::start();
301 }
302
303 bool BaseProcessor::stop(void)
304 {
305      DbgPrint();
306      if (mStartCount > 0)
307           mStartCount--;
308
309      if (mStartCount > 0)
310           return true;
311
312      return cprocessor_module::stop();
313 }
314
315 bool BaseProcessor::enable()
316 {
317      writeToSysfs("enable","1",1);
318      return true;
319 }
320
321
322 bool BaseProcessor::disable()
323 {
324      writeToSysfs("enable","0",1);
325      return true;
326 }
327
328
329 bool BaseProcessor::find_input_device_by_name(const char *inputName)
330 {
331      const char *dirname = "/dev/input";
332      char devname[PATH_MAX];
333
334      char *filename;
335      DIR *dir;
336      struct dirent *de;
337
338      DbgPrint("");
339      mFd = -1;
340
341      dir = opendir(dirname);
342      if(dir == NULL)
343           return mFd;
344
345      memset(devname,0,PATH_MAX);
346      strcpy(devname, dirname);
347      filename = devname + strlen(devname);
348      *filename++ = '/';
349      strcpy(devname, dirname);
350      filename = devname + strlen(devname);
351      *filename++ = '/';
352
353      while ((de = readdir(dir))) {
354           if (de->d_type == DT_DIR)
355                continue;
356
357           strcpy(filename, de->d_name);
358           filename[strlen(de->d_name)] = 0;
359
360           mFd = open(devname,O_RDONLY);
361           if (mFd <= 0) {
362                DbgPrint("Not opened %s",devname);
363                continue;
364           }
365
366           char name[80];
367           if (ioctl(mFd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
368                name[0] = '\0';
369                DbgPrint("Ioctl error");
370           } else
371                DbgPrint("Found device %s: %s",devname,name);
372
373           if (!strcmp(name, inputName)) {
374                DbgPrint("Found input device for sensor %s: %s",devname,name);
375                break;
376           } else {
377                close(mFd);
378                mFd = -1;
379           }
380      }
381
382      closedir(dir);
383
384      return mFd != -1;
385 }
386
387 const char *BaseProcessor::find_device_from_udev(const char *driver)
388 {
389      udev_device *dev = NULL;
390      udev *udev = NULL;
391      udev_enumerate *enumerator = NULL;
392      bool result = false;
393      struct udev_list_entry *devices = NULL, *dev_list_entry = NULL;
394      const char *devicePath = "";
395
396      DbgPrint("");
397
398      mSysfsPath = "";
399
400      udev = udev_new();
401
402
403      if (udev == NULL) {
404           DbgPrint("Failed to initialize udev %d",errno);
405           return NULL;
406      }
407
408      enumerator = udev_enumerate_new(udev);
409
410      if (!enumerator) {
411           DbgPrint("Failed to initialize enumerator");
412           goto release_udev;
413      }
414
415      //This class is only meant to be used for sensors
416      //which are connected by i2c bus
417      udev_enumerate_add_match_subsystem(enumerator,"i2c");
418      udev_enumerate_add_match_property(enumerator,"DRIVER",driver);
419
420      if (udev_enumerate_scan_devices(enumerator) != 0) {
421           DbgPrint("Failed to scan devices");
422           goto release_enumerator;
423      }
424
425      devices = udev_enumerate_get_list_entry(enumerator);
426
427      udev_list_entry_foreach(dev_list_entry, devices) {
428
429           const char *path = udev_list_entry_get_name(dev_list_entry);
430           DbgPrint("Found device named: %s value",path);
431
432           dev = udev_device_new_from_syspath(udev,path);
433
434           if (dev) {
435                devicePath = udev_device_get_devpath(dev);
436                udev_device_unref(dev);
437                break;
438           }
439      }
440
441      mSysfsPath = "/sys";
442      mSysfsPath += devicePath;
443
444      result = true;
445
446 release_enumerator:
447      udev_enumerate_unref(enumerator);
448 release_udev:
449      udev_unref(udev);
450
451      return devicePath;
452 }
453
454
455 bool BaseProcessor::writeToSysfs(const char *filename, const char *buffer, int count)
456 {
457      DbgPrint("%s",name());
458
459      if (!mSysfsPath.empty()) {
460           std::string fullpath = mSysfsPath;
461           fullpath.append("/");
462           fullpath.append(filename);
463           const char *cpath = fullpath.c_str();
464
465           DbgPrint("Trying to open sysfs file entry %s",cpath);
466           int fd = open(cpath,O_WRONLY);
467           if (fd > 0) {
468                DbgPrint("Sysfs file entry opened");
469                int writeCount = write(fd,buffer,count);
470                if (writeCount == count) {
471                     close(fd);
472                     return true;
473                }
474                close(fd);
475           }
476      }
477      DbgPrint("There was error opening sysfs file %s",strerror(errno));
478
479      return false;
480 }