Commit | Line | Data |
---|---|---|
6fa3eb70 S |
1 | /* alps/ALPS_SW/TRUNK/MAIN/alps/kernel/drivers/hwmon/mt6516/hwmsen_dev.c |
2 | * | |
3 | * (C) Copyright 2009 | |
4 | * MediaTek <www.MediaTek.com> | |
5 | * | |
6 | * Sensor devices | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or modify | |
9 | * it under the terms of the GNU General Public License as published by | |
10 | * the Free Software Foundation; either version 2 of the License, or | |
11 | * (at your option) any later version. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with this program; if not, write to the Free Software | |
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
21 | */ | |
22 | #include <linux/interrupt.h> | |
23 | #include <linux/miscdevice.h> | |
24 | #include <linux/platform_device.h> | |
25 | #include <asm/uaccess.h> | |
26 | #include <linux/delay.h> | |
27 | #include <linux/input.h> | |
28 | #include <linux/workqueue.h> | |
29 | #include <linux/wait.h> | |
30 | #include <linux/slab.h> | |
31 | ||
32 | ||
33 | #include <linux/hwmsensor.h> | |
34 | #include <linux/hwmsen_helper.h> | |
35 | #include <linux/hwmsen_dev.h> | |
36 | //add for fix resume issue | |
37 | #include <linux/earlysuspend.h> | |
38 | #include <linux/wakelock.h> | |
39 | //add for fix resume issue end | |
40 | ||
41 | #include <cust_alsps.h> | |
42 | #include <aal_control.h> | |
43 | ||
44 | #define SENSOR_INVALID_VALUE -1 | |
45 | #define MAX_CHOOSE_G_NUM 5 | |
46 | #define MAX_CHOOSE_M_NUM 5 | |
47 | #if defined(CONFIG_HAS_EARLYSUSPEND) | |
48 | static void hwmsen_early_suspend(struct early_suspend *h); | |
49 | static void hwmsen_late_resume(struct early_suspend *h); | |
50 | #endif | |
51 | static void update_workqueue_polling_rate(int newDelay); | |
52 | ||
53 | struct workqueue_struct * sensor_workqueue = NULL; | |
54 | ||
55 | /****************************************************************************** | |
56 | * structure / enumeration / macro / definition | |
57 | *****************************************************************************/ | |
58 | ||
59 | struct sensor_delay | |
60 | { | |
61 | int handle; | |
62 | uint32_t delay; | |
63 | }; | |
64 | ||
65 | struct hwmsen_context { /*sensor context*/ | |
66 | atomic_t enable; | |
67 | atomic_t delay; | |
68 | uint32_t delayCountSet; | |
69 | uint32_t delayCount; | |
70 | ||
71 | struct hwmsen_object obj; | |
72 | }; | |
73 | ||
74 | #if defined(CONFIG_MTK_AUTO_DETECT_ACCELEROMETER) | |
75 | static char gsensor_name[25]; | |
76 | static struct sensor_init_info* gsensor_init_list[MAX_CHOOSE_G_NUM]= {0}; //modified | |
77 | #endif | |
78 | #if defined(CONFIG_MTK_AUTO_DETECT_MAGNETOMETER) | |
79 | static char msensor_name[25]; | |
80 | static struct sensor_init_info* msensor_init_list[MAX_CHOOSE_G_NUM]= {0}; //modified | |
81 | #endif | |
82 | #if defined(CONFIG_MTK_AUTO_DETECT_ALSPS) | |
83 | static char alsps_name[25]; | |
84 | static struct sensor_init_info* alsps_init_list[MAX_CHOOSE_G_NUM]= {0}; //modified | |
85 | #endif | |
86 | ||
87 | /*----------------------------------------------------------------------------*/ | |
88 | struct dev_context { | |
89 | int polling_running; | |
90 | struct mutex lock; | |
91 | struct hwmsen_context* cxt[MAX_ANDROID_SENSOR_NUM+1]; | |
92 | }; | |
93 | /*-------------Sensor daa-----------------------------------------------------*/ | |
94 | struct hwmsen_data{ | |
95 | hwm_sensor_data sensors_data[MAX_ANDROID_SENSOR_NUM+1]; | |
96 | int data_updata[MAX_ANDROID_SENSOR_NUM+1]; | |
97 | struct mutex lock; | |
98 | }; | |
99 | /*----------------------------------------------------------------------------*/ | |
100 | typedef enum { | |
101 | HWM_TRC_REPORT_NUM = 0x0001, | |
102 | HWM_TRC_REPORT_EVT = 0x0002, | |
103 | HWM_TRC_REPORT_INF = 0X0004, | |
104 | } HWM_TRC; | |
105 | /*----------------------------------------------------------------------------*/ | |
106 | #define C_MAX_OBJECT_NUM 1 | |
107 | struct hwmdev_object { | |
108 | struct input_dev *idev; | |
109 | struct miscdevice mdev; | |
110 | struct dev_context *dc; | |
111 | struct work_struct report; | |
112 | atomic_t delay; /*polling period for reporting input event*/ | |
113 | atomic_t wake; /*user-space request to wake-up, used with stop*/ | |
114 | struct timer_list timer; /* polling timer */ | |
115 | atomic_t trace; | |
116 | uint32_t active_sensor; // Active, but hwmsen don't need data sensor. Maybe other need it's data. | |
117 | uint32_t active_data_sensor; // Active and hwmsen need data sensor. | |
118 | #if defined(CONFIG_HAS_EARLYSUSPEND) | |
119 | //add for fix resume issue | |
120 | struct early_suspend early_drv; | |
121 | struct wake_lock read_data_wake_lock; | |
122 | atomic_t early_suspend; | |
123 | //add for fix resume end | |
124 | #endif //#if defined(CONFIG_HAS_EARLYSUSPEND) | |
125 | }; | |
126 | ||
127 | static bool enable_again = false; | |
128 | static struct hwmdev_object *hwm_obj = NULL; | |
129 | /****************************************************************************** | |
130 | * static variables | |
131 | *****************************************************************************/ | |
132 | ||
133 | static struct hwmsen_data obj_data ={ | |
134 | .lock =__MUTEX_INITIALIZER(obj_data.lock), | |
135 | }; | |
136 | static struct dev_context dev_cxt = { | |
137 | .lock = __MUTEX_INITIALIZER(dev_cxt.lock), | |
138 | }; | |
139 | /*----------------------------------------------------------------------------*/ | |
140 | ||
141 | ||
142 | //AAL functions********************************************************************** | |
143 | int hwmsen_aal_enable(int en) | |
144 | { | |
145 | struct hwmsen_context *cxt = NULL; | |
146 | int err = 0; | |
147 | int enable = 0; | |
148 | ||
149 | if(!hwm_obj) | |
150 | { | |
151 | HWM_ERR("AAL hwmdev obj pointer is NULL!\n"); | |
152 | return -EINVAL; | |
153 | } | |
154 | else if((hwm_obj->dc->cxt[ID_LIGHT]) == NULL) | |
155 | { | |
156 | HWM_ERR("the sensor (%d) is not attached!!\n", ID_LIGHT); | |
157 | return -ENODEV; | |
158 | } | |
159 | ||
160 | mutex_lock(&hwm_obj->dc->lock); | |
161 | cxt = hwm_obj->dc->cxt[ID_LIGHT]; | |
162 | ||
163 | if(en == 1){ | |
164 | if((hwm_obj->active_data_sensor & (1 << ID_LIGHT))==0){ | |
165 | HWM_LOG("enable sensor(%d) by AAL operation\n", ID_LIGHT); | |
166 | if (cxt->obj.sensor_operate(cxt->obj.self, SENSOR_ENABLE, &en, sizeof(int), NULL, 0, NULL) != 0) | |
167 | { | |
168 | HWM_ERR("enable sensor(%d) err = %d\n", ID_LIGHT, err); | |
169 | err = -EINVAL; | |
170 | } | |
171 | } | |
172 | }else{ | |
173 | if((hwm_obj->active_data_sensor & (1 << ID_LIGHT))==0){ | |
174 | HWM_LOG("disable sensor(%d) by AAL operation\n", ID_LIGHT); | |
175 | if (cxt->obj.sensor_operate(cxt->obj.self, SENSOR_ENABLE, &en, sizeof(int), NULL, 0, NULL) != 0) | |
176 | { | |
177 | HWM_ERR("disable sensor(%d) err = %d\n", ID_LIGHT, err); | |
178 | err = -EINVAL; | |
179 | } | |
180 | } | |
181 | } | |
182 | mutex_unlock(&hwm_obj->dc->lock); | |
183 | ||
184 | return err; | |
185 | } | |
186 | ||
187 | int hwmsen_aal_get_data() | |
188 | { | |
189 | struct hwmsen_context *cxt = NULL; | |
190 | int err = 0; | |
191 | int enable = 0; | |
192 | int out_size; | |
193 | hwm_sensor_data sensor_data; | |
194 | int als_data = 0; | |
195 | ||
196 | //HWM_LOG("hwmsen_aal_get_data1\n"); | |
197 | if(!hwm_obj) | |
198 | { | |
199 | HWM_ERR("AAL hwmdev obj pointer is NULL!\n"); | |
200 | return -EINVAL; | |
201 | } | |
202 | else if((hwm_obj->dc->cxt[ID_LIGHT]) == NULL) | |
203 | { | |
204 | HWM_ERR("the sensor (%d) is not attached!!\n", ID_LIGHT); | |
205 | return -ENODEV; | |
206 | } | |
207 | ||
208 | mutex_lock(&hwm_obj->dc->lock); | |
209 | cxt = hwm_obj->dc->cxt[ID_LIGHT]; | |
210 | //HWM_LOG("hwmsen_aal_get_data2\n"); | |
211 | err = cxt->obj.sensor_operate(cxt->obj.self,SENSOR_GET_DATA, NULL, 0, | |
212 | &sensor_data, sizeof(hwm_sensor_data), &out_size); | |
213 | if(err) | |
214 | { | |
215 | mutex_unlock(&hwm_obj->dc->lock); | |
216 | HWM_ERR("get data from sensor (%d) fails!!\n", ID_LIGHT); | |
217 | return -ENODEV; | |
218 | } | |
219 | else | |
220 | { | |
221 | als_data = sensor_data.values[0]; | |
222 | } | |
223 | mutex_unlock(&hwm_obj->dc->lock); | |
224 | //HWM_LOG("hwmsen_aal_get_data3\n"); | |
225 | return als_data; | |
226 | } | |
227 | ||
228 | int hwmsen_aal_get_status() | |
229 | { | |
230 | return 0; | |
231 | } | |
232 | //************************************************************************************ | |
233 | ||
234 | /****************************************************************************** | |
235 | * Local functions | |
236 | *****************************************************************************/ | |
237 | static void hwmsen_work_func(struct work_struct *work) | |
238 | { | |
239 | ||
240 | //HWM_LOG("+++++++++++++++++++++++++hwmsen_work_func workqueue performed!+++++++++++++++++++++++++++++\n"); | |
241 | //struct hwmdev_object *obj = container_of(work, struct hwmdev_object, report); | |
242 | struct hwmdev_object *obj = hwm_obj; | |
243 | struct hwmsen_context *cxt = NULL; | |
244 | int out_size; | |
245 | hwm_sensor_data sensor_data; | |
246 | uint32_t event_type = 0; | |
247 | int64_t nt; | |
248 | struct timespec time; | |
249 | int err, idx; | |
250 | //int trc = atomic_read(&obj->trace); | |
251 | ||
252 | if (obj == NULL) | |
253 | { | |
254 | HWM_ERR("obj point is NULL!\n"); | |
255 | return; | |
256 | } | |
257 | ||
258 | ||
259 | if(atomic_read(&obj->wake)) | |
260 | { | |
261 | input_event(obj->idev, EV_SYN, SYN_CONFIG, 0); | |
262 | atomic_set(&obj->wake, 0); | |
263 | return; | |
264 | } | |
265 | ||
266 | memset(&sensor_data, 0, sizeof(sensor_data)); | |
267 | time.tv_sec = time.tv_nsec = 0; | |
4b9e9796 | 268 | get_monotonic_boottime(&time); |
6fa3eb70 S |
269 | nt = time.tv_sec*1000000000LL+time.tv_nsec; |
270 | //mutex_lock(&obj_data.lock); | |
271 | for(idx = 0; idx < MAX_ANDROID_SENSOR_NUM; idx++) | |
272 | { | |
273 | cxt = obj->dc->cxt[idx]; | |
274 | if((cxt == NULL) || (cxt->obj.sensor_operate == NULL) | |
275 | || !(obj->active_data_sensor&(0x01<<idx))) | |
276 | { | |
277 | continue; | |
278 | } | |
279 | ||
280 | // Interrupt sensor | |
281 | if(cxt->obj.polling == 0) | |
282 | { | |
283 | if(obj_data.data_updata[idx] == 1) | |
284 | { | |
285 | mutex_lock(&obj_data.lock); | |
286 | event_type |= (1 << idx); | |
287 | obj_data.data_updata[idx] = 0; | |
288 | mutex_unlock(&obj_data.lock); | |
289 | } | |
290 | continue; | |
291 | } | |
292 | ||
293 | ||
294 | //added to surpport set delay to specified sensor | |
295 | if(cxt->delayCount > 0) | |
296 | { | |
297 | //HWM_LOG("sensor(%d) delayCount = %d\n",idx,cxt->delayCount); | |
298 | cxt->delayCount--; | |
299 | if(0 == cxt->delayCount) | |
300 | { | |
301 | cxt->delayCount = cxt->delayCountSet; | |
302 | //HWM_LOG("sensor(%d) go to get data\n",idx); | |
303 | } | |
304 | else | |
305 | { | |
306 | //HWM_LOG("sensor(%d) wait for next work\n",idx); | |
307 | continue; | |
308 | } | |
309 | } | |
310 | ||
311 | err = cxt->obj.sensor_operate(cxt->obj.self,SENSOR_GET_DATA, NULL, 0, | |
312 | &sensor_data, sizeof(hwm_sensor_data), &out_size); | |
313 | ||
314 | if(err) | |
315 | { | |
316 | HWM_ERR("get data from sensor (%d) fails!!\n", idx); | |
317 | continue; | |
318 | } | |
319 | else | |
320 | { | |
321 | if((idx == ID_LIGHT) ||(idx == ID_PRESSURE) | |
322 | ||(idx == ID_PROXIMITY) || (idx == ID_TEMPRERATURE)) | |
323 | { | |
324 | // data changed, update the data | |
325 | if(sensor_data.values[0] != obj_data.sensors_data[idx].values[0]) | |
326 | { | |
327 | mutex_lock(&obj_data.lock); | |
328 | obj_data.sensors_data[idx].values[0] = sensor_data.values[0]; | |
329 | obj_data.sensors_data[idx].value_divide = sensor_data.value_divide; | |
330 | obj_data.sensors_data[idx].status = sensor_data.status; | |
331 | obj_data.sensors_data[idx].time = nt; | |
332 | event_type |= (1 << idx); | |
333 | mutex_unlock(&obj_data.lock); | |
334 | //HWM_LOG("get %d sensor, values: %d!\n", idx, sensor_data.values[0]); | |
335 | } | |
336 | } | |
337 | else | |
338 | { | |
339 | // data changed, update the data | |
340 | if((sensor_data.values[0] != obj_data.sensors_data[idx].values[0]) | |
341 | || (sensor_data.values[1] != obj_data.sensors_data[idx].values[1]) | |
342 | || (sensor_data.values[2] != obj_data.sensors_data[idx].values[2]) | |
4b9e9796 | 343 | || (idx == ID_MAGNETIC) || (idx == ID_ACCELEROMETER)) |
6fa3eb70 S |
344 | { |
345 | if( 0 == sensor_data.values[0] && 0==sensor_data.values[1] | |
346 | && 0 == sensor_data.values[2]) | |
347 | { | |
348 | ||
349 | continue; | |
350 | } | |
351 | mutex_lock(&obj_data.lock); | |
352 | obj_data.sensors_data[idx].values[0] = sensor_data.values[0]; | |
353 | obj_data.sensors_data[idx].values[1] = sensor_data.values[1]; | |
354 | obj_data.sensors_data[idx].values[2] = sensor_data.values[2]; | |
355 | obj_data.sensors_data[idx].value_divide = sensor_data.value_divide; | |
356 | obj_data.sensors_data[idx].status = sensor_data.status; | |
357 | obj_data.sensors_data[idx].time = nt; | |
358 | event_type |= (1 << idx); | |
359 | mutex_unlock(&obj_data.lock); | |
360 | //HWM_LOG("get %d sensor, values: %d, %d, %d!\n", idx, | |
361 | //sensor_data.values[0], sensor_data.values[1], sensor_data.values[2]); | |
362 | } | |
363 | } | |
364 | } | |
365 | } | |
366 | ||
367 | // | |
368 | //mutex_unlock(&obj_data.lock); | |
369 | ||
370 | if(enable_again == true) | |
371 | { | |
372 | event_type = obj->active_data_sensor; | |
373 | enable_again = false; | |
374 | //filter -1 value | |
375 | for(idx = 0; idx <= MAX_ANDROID_SENSOR_NUM; idx++) | |
376 | { | |
377 | if(ID_ACCELEROMETER==idx || ID_MAGNETIC==idx || ID_ORIENTATION==idx | |
378 | ||ID_GYROSCOPE==idx || ID_TEMPRERATURE==idx | |
379 | ||ID_LINEAR_ACCELERATION==idx || ID_ROTATION_VECTOR==idx | |
380 | ||ID_GRAVITY==idx) | |
381 | { | |
382 | if(SENSOR_INVALID_VALUE == obj_data.sensors_data[idx].values[0] || | |
383 | SENSOR_INVALID_VALUE == obj_data.sensors_data[idx].values[1] || | |
384 | SENSOR_INVALID_VALUE == obj_data.sensors_data[idx].values[2]) | |
385 | { | |
386 | event_type &= ~(1 << idx); | |
387 | //HWM_LOG("idx=%d,obj->active_sensor after clear: %d\n",idx); | |
388 | } | |
389 | } | |
390 | ||
391 | if(ID_PROXIMITY==idx || ID_LIGHT==idx || ID_PRESSURE==idx) | |
392 | { | |
393 | if(SENSOR_INVALID_VALUE == obj_data.sensors_data[idx].values[0]) | |
394 | { | |
395 | event_type &= ~(1 << idx); | |
396 | //HWM_LOG("idx=%d,obj->active_sensor after clear: %d\n",idx); | |
397 | } | |
398 | } | |
399 | } | |
400 | //HWM_LOG("event type after enable: %d\n", event_type); | |
401 | } | |
402 | ||
403 | if((event_type&(1 << ID_PROXIMITY))&& SENSOR_INVALID_VALUE == obj_data.sensors_data[ID_PROXIMITY].values[0]) | |
404 | { | |
405 | event_type &= ~(1 << ID_PROXIMITY); | |
406 | //HWM_LOG("remove ps event!!!!!!!!!!!\n"); | |
407 | } | |
408 | ||
409 | if(event_type != 0) | |
410 | { | |
411 | input_report_rel(obj->idev, EVENT_TYPE_SENSOR, event_type); | |
412 | input_sync(obj->idev);//modified | |
413 | //HWM_LOG("event type: %d\n", event_type); | |
414 | } | |
415 | else | |
416 | { | |
417 | //HWM_LOG("no available sensor!!\n"); | |
418 | } | |
419 | ||
420 | if(obj->dc->polling_running == 1) | |
421 | { | |
422 | mod_timer(&obj->timer, jiffies + atomic_read(&obj->delay)/(1000/HZ)); | |
423 | } | |
424 | } | |
425 | ||
426 | /****************************************************************************** | |
427 | * export functions | |
428 | *****************************************************************************/ | |
429 | int hwmsen_get_interrupt_data(int sensor, hwm_sensor_data *data) | |
430 | { | |
431 | //HWM_LOG("++++++++++++++++++++++++++++hwmsen_get_interrupt_data function sensor = %d\n",sensor); | |
432 | struct dev_context *mcxt = &dev_cxt; | |
433 | struct hwmdev_object *obj = hwm_obj; | |
434 | int64_t nt; | |
435 | struct timespec time; | |
436 | ||
437 | if((sensor > MAX_ANDROID_SENSOR_NUM) || (mcxt->cxt[sensor] == NULL) | |
438 | || (mcxt->cxt[sensor]->obj.polling != 0)) | |
439 | { | |
440 | HWM_ERR("sensor %d!\n", sensor); | |
441 | return -EINVAL; | |
442 | } | |
443 | else | |
444 | { | |
445 | time.tv_sec = time.tv_nsec = 0; | |
4b9e9796 | 446 | get_monotonic_boottime(&time); |
6fa3eb70 S |
447 | nt = time.tv_sec*1000000000LL+time.tv_nsec; |
448 | if((sensor == ID_LIGHT) ||(sensor == ID_PRESSURE) | |
449 | ||(sensor == ID_PROXIMITY) || (sensor == ID_TEMPRERATURE)) | |
450 | { | |
451 | // data changed, update the data | |
452 | if(data->values[0] != obj_data.sensors_data[sensor].values[0]) | |
453 | { | |
454 | mutex_lock(&obj_data.lock); | |
455 | obj_data.data_updata[sensor] = 1; | |
456 | obj_data.sensors_data[sensor].values[0] = data->values[0]; | |
457 | obj_data.sensors_data[sensor].time = nt; | |
458 | obj_data.sensors_data[sensor].value_divide = data->value_divide; | |
459 | mutex_unlock(&obj_data.lock); | |
460 | } | |
461 | } | |
462 | else | |
463 | { | |
464 | // data changed, update the data | |
465 | if((data->values[0] != obj_data.sensors_data[sensor].values[0]) | |
466 | || (data->values[1] != obj_data.sensors_data[sensor].values[1]) | |
467 | || (data->values[2] != obj_data.sensors_data[sensor].values[2])) | |
468 | { | |
469 | mutex_lock(&obj_data.lock); | |
470 | obj_data.sensors_data[sensor].values[0] = data->values[0]; | |
471 | obj_data.sensors_data[sensor].values[1] = data->values[1]; | |
472 | obj_data.sensors_data[sensor].values[2] = data->values[2]; | |
473 | obj_data.sensors_data[sensor].value_divide = data->value_divide; | |
474 | obj_data.data_updata[sensor] = 1; | |
475 | obj_data.sensors_data[sensor].time = nt; | |
476 | mutex_unlock(&obj_data.lock); | |
477 | } | |
478 | } | |
479 | ||
480 | if(obj->dc->polling_running == 1) | |
481 | { | |
482 | hwmsen_work_func(NULL); | |
483 | } | |
484 | ||
485 | return 0; | |
486 | } | |
487 | } | |
488 | /*----------------------------------------------------------------------------*/ | |
489 | EXPORT_SYMBOL_GPL(hwmsen_get_interrupt_data); | |
490 | ||
491 | /*----------------------------------------------------------------------------*/ | |
492 | static void hwmsen_poll(unsigned long data) | |
493 | { | |
494 | struct hwmdev_object *obj = (struct hwmdev_object *)data; | |
495 | if(obj != NULL) | |
496 | { | |
497 | queue_work(sensor_workqueue, &obj->report); | |
498 | } | |
499 | } | |
500 | /*----------------------------------------------------------------------------*/ | |
501 | static struct hwmdev_object *hwmsen_alloc_object(void) | |
502 | { | |
503 | ||
504 | struct hwmdev_object *obj = kzalloc(sizeof(*obj), GFP_KERNEL); | |
505 | HWM_FUN(f); | |
506 | ||
507 | if(!obj) | |
508 | { | |
509 | HWM_ERR("Alloc hwmsen object error!\n"); | |
510 | return NULL; | |
511 | } | |
512 | ||
513 | obj->dc = &dev_cxt; | |
514 | obj->active_data_sensor = 0; | |
515 | obj->active_sensor = 0; | |
516 | atomic_set(&obj->delay, 200); /*5Hz*/// set work queue delay time 200ms | |
517 | atomic_set(&obj->wake, 0); | |
518 | sensor_workqueue = create_singlethread_workqueue("sensor_polling"); | |
519 | if (!sensor_workqueue) | |
520 | { | |
521 | kfree(obj); | |
522 | return NULL; | |
523 | } | |
524 | INIT_WORK(&obj->report, hwmsen_work_func); | |
525 | init_timer(&obj->timer); | |
526 | obj->timer.expires = jiffies + atomic_read(&obj->delay)/(1000/HZ); | |
527 | obj->timer.function = hwmsen_poll; | |
528 | obj->timer.data = (unsigned long)obj; | |
529 | return obj; | |
530 | } | |
531 | ||
532 | /*Sensor device driver attach to hwmsen device------------------------------------------------*/ | |
533 | int hwmsen_attach(int sensor, struct hwmsen_object *obj) | |
534 | { | |
535 | ||
536 | struct dev_context *mcxt = &dev_cxt; | |
537 | int err = 0; | |
538 | HWM_FUN(f); | |
539 | if((mcxt == NULL) || (sensor > MAX_ANDROID_SENSOR_NUM)) | |
540 | { | |
541 | err = -EINVAL; | |
542 | goto err_exit; | |
543 | } | |
544 | ||
545 | mutex_lock(&mcxt->lock); | |
546 | if(mcxt->cxt[sensor] != NULL) | |
547 | { | |
548 | err = -EEXIST; | |
549 | goto err_exit; | |
550 | } | |
551 | else | |
552 | { | |
553 | mcxt->cxt[sensor] = kzalloc(sizeof(struct hwmsen_context), GFP_KERNEL); | |
554 | if(mcxt->cxt[sensor] == NULL) | |
555 | { | |
556 | err = -EPERM; | |
557 | goto err_exit; | |
558 | } | |
559 | atomic_set(&mcxt->cxt[sensor]->enable, 0); | |
560 | memcpy(&mcxt->cxt[sensor]->obj, obj, sizeof(*obj)); | |
561 | ||
562 | // add for android2.3 set sensors default polling delay time is 200ms | |
563 | atomic_set(&mcxt->cxt[sensor]->delay, 200); | |
564 | ||
565 | ||
566 | } | |
567 | ||
568 | err_exit: | |
569 | mutex_unlock(&mcxt->lock); | |
570 | return err; | |
571 | } | |
572 | /*----------------------------------------------------------------------------*/ | |
573 | EXPORT_SYMBOL_GPL(hwmsen_attach); | |
574 | /*----------------------------------------------------------------------------*/ | |
575 | int hwmsen_detach(int sensor) | |
576 | { | |
577 | ||
578 | int err = 0; | |
579 | struct dev_context *mcxt = &dev_cxt; | |
580 | HWM_FUN(f); | |
581 | if ((sensor > MAX_ANDROID_SENSOR_NUM) || (mcxt->cxt[sensor] == NULL)) | |
582 | { | |
583 | err = -EINVAL; | |
584 | goto err_exit; | |
585 | } | |
586 | ||
587 | mutex_lock(&mcxt->lock); | |
588 | kfree(mcxt->cxt[sensor]); | |
589 | mcxt->cxt[sensor] = NULL; | |
590 | ||
591 | err_exit: | |
592 | mutex_unlock(&mcxt->lock); | |
593 | return 0; | |
594 | } | |
595 | /*----------------------------------------------------------------------------*/ | |
596 | EXPORT_SYMBOL_GPL(hwmsen_detach); | |
597 | /*----------------------------------------------------------------------------*/ | |
598 | static int hwmsen_enable(struct hwmdev_object *obj, int sensor, int enable) | |
599 | { | |
600 | struct hwmsen_context *cxt = NULL; | |
601 | int err = 0; | |
602 | uint32_t sensor_type; | |
603 | ||
604 | sensor_type = 1 << sensor; | |
605 | ||
4b9e9796 S |
606 | if (sensor > MAX_ANDROID_SENSOR_NUM || sensor < 0) { |
607 | HWM_ERR("handle %d!\n", sensor); | |
608 | return -EINVAL; | |
609 | } | |
610 | ||
6fa3eb70 S |
611 | if(!obj) |
612 | { | |
613 | HWM_ERR("hwmdev obj pointer is NULL!\n"); | |
614 | return -EINVAL; | |
615 | } | |
616 | else if(obj->dc->cxt[sensor] == NULL) | |
617 | { | |
618 | HWM_ERR("the sensor (%d) is not attached!!\n", sensor); | |
619 | return -ENODEV; | |
620 | } | |
6fa3eb70 S |
621 | |
622 | mutex_lock(&obj->dc->lock); | |
623 | cxt = obj->dc->cxt[sensor]; | |
624 | ||
625 | ||
626 | if(enable == 1) | |
627 | { | |
628 | //{@for mt6582 blocking issue work around | |
629 | if(sensor == 7){ | |
630 | HWM_LOG("P-sensor disable LDO low power\n"); | |
631 | pmic_ldo_suspend_enable(0); | |
632 | } | |
633 | //@} | |
634 | enable_again = true; | |
635 | obj->active_data_sensor |= sensor_type; | |
636 | if((obj->active_sensor & sensor_type) == 0) // no no-data active | |
637 | { | |
638 | if (cxt->obj.sensor_operate(cxt->obj.self, SENSOR_ENABLE, &enable,sizeof(int), NULL, 0, NULL) != 0) | |
639 | { | |
640 | if (cxt->obj.sensor_operate(cxt->obj.self, SENSOR_ENABLE, &enable,sizeof(int), NULL, 0, NULL) != 0) | |
641 | { | |
642 | if (cxt->obj.sensor_operate(cxt->obj.self, SENSOR_ENABLE, &enable,sizeof(int), NULL, 0, NULL) != 0) | |
643 | { | |
644 | HWM_ERR("activate sensor(%d) 3 times err = %d\n", sensor, err); | |
645 | err = -EINVAL; | |
646 | goto exit; | |
647 | } | |
648 | } | |
649 | ||
650 | } | |
651 | update_workqueue_polling_rate(200); | |
652 | atomic_set(&cxt->enable, 1); | |
653 | } | |
654 | ||
655 | // Need to complete the interrupt sensor work | |
656 | if((0 == obj->dc->polling_running) && (obj->active_data_sensor != 0)) | |
657 | { | |
658 | obj->dc->polling_running = 1; | |
659 | //obj->timer.expires = jiffies + atomic_read(&obj->delay)/(1000/HZ); | |
660 | //add_timer(&obj->timer); | |
661 | mod_timer(&obj->timer, jiffies + atomic_read(&obj->delay)/(1000/HZ)); | |
662 | ||
663 | } | |
664 | ||
665 | } | |
666 | else if ((enable == 0)) | |
667 | { | |
668 | //{@for mt6582 blocking issue work around | |
669 | if(sensor == 7){ | |
670 | HWM_LOG("P-sensor enable LDO low power\n"); | |
671 | pmic_ldo_suspend_enable(1); | |
672 | ||
673 | } | |
674 | //@} | |
675 | ||
676 | obj->active_data_sensor &= ~sensor_type; | |
677 | if((obj->active_sensor & sensor_type) == 0) // no no-data active | |
678 | { | |
679 | #ifdef CONFIG_CUSTOM_KERNEL_ALSPS | |
680 | if(sensor == 4 && aal_use == 1){ | |
681 | HWM_ERR("AAL is used ingnore common light disable\n"); | |
682 | err = 0; | |
683 | } | |
684 | else | |
685 | #endif | |
686 | { | |
687 | ||
688 | if(cxt->obj.sensor_operate(cxt->obj.self, SENSOR_ENABLE, &enable,sizeof(int), NULL, 0, NULL) != 0) | |
689 | { | |
690 | HWM_ERR("deactiva sensor(%d) err = %d\n", sensor, err); | |
691 | err = -EINVAL; | |
692 | goto exit; | |
693 | } | |
694 | } | |
695 | ||
696 | atomic_set(&cxt->enable, 0); | |
697 | update_workqueue_polling_rate(200);// re-update workqueue polling rate | |
698 | } | |
699 | ||
700 | if((1 == obj->dc->polling_running) && (obj->active_data_sensor == 0)) | |
701 | { | |
702 | obj->dc->polling_running = 0; | |
703 | del_timer_sync(&obj->timer); | |
704 | cancel_work_sync(&obj->report); | |
705 | ||
706 | } | |
707 | ||
708 | obj_data.sensors_data[sensor].values[0] = SENSOR_INVALID_VALUE; | |
709 | obj_data.sensors_data[sensor].values[1] = SENSOR_INVALID_VALUE; | |
710 | obj_data.sensors_data[sensor].values[2] = SENSOR_INVALID_VALUE; | |
711 | ||
712 | } | |
713 | ||
714 | HWM_LOG("sensor(%d), flag(%d)\n", sensor, enable); | |
715 | ||
716 | exit: | |
717 | ||
718 | mutex_unlock(&obj->dc->lock); | |
719 | return err; | |
720 | } | |
721 | ||
722 | /*-------------no data sensor enable/disable--------------------------------------*/ | |
723 | static int hwmsen_enable_nodata(struct hwmdev_object *obj, int sensor, int enable) | |
724 | { | |
725 | struct hwmsen_context *cxt = NULL; | |
726 | int err = 0; | |
727 | uint32_t sensor_type; | |
728 | HWM_FUN(f); | |
729 | sensor_type = 1 << sensor; | |
730 | ||
4b9e9796 S |
731 | if (sensor > MAX_ANDROID_SENSOR_NUM || sensor < 0) { |
732 | HWM_ERR("handle %d!\n", sensor); | |
733 | return -EINVAL; | |
734 | } | |
735 | ||
6fa3eb70 S |
736 | if(NULL == obj) |
737 | { | |
738 | HWM_ERR("hwmdev obj pointer is NULL!\n"); | |
739 | return -EINVAL; | |
740 | } | |
741 | else if(obj->dc->cxt[sensor] == NULL) | |
742 | { | |
743 | HWM_ERR("the sensor (%d) is not attached!!\n", sensor); | |
744 | return -ENODEV; | |
745 | } | |
6fa3eb70 S |
746 | |
747 | mutex_lock(&obj->dc->lock); | |
748 | cxt = obj->dc->cxt[sensor]; | |
749 | ||
750 | if(enable == 1) | |
751 | { | |
752 | obj->active_sensor |= sensor_type; | |
753 | ||
754 | if((obj->active_data_sensor & sensor_type) == 0) // no data active | |
755 | { | |
756 | if(cxt->obj.sensor_operate(cxt->obj.self, SENSOR_ENABLE, &enable, sizeof(int), NULL, 0, NULL) != 0) | |
757 | { | |
758 | HWM_ERR("activate sensor(%d) err = %d\n", sensor, err); | |
759 | err = -EINVAL; | |
760 | goto exit; | |
761 | } | |
762 | ||
763 | atomic_set(&cxt->enable, 1); | |
764 | } | |
765 | } | |
766 | else | |
767 | { | |
768 | obj->active_sensor &= ~sensor_type; | |
769 | ||
770 | if((obj->active_data_sensor & sensor_type) == 0) // no data active | |
771 | { | |
772 | if(cxt->obj.sensor_operate(cxt->obj.self, SENSOR_ENABLE, &enable,sizeof(int), NULL, 0, NULL) != 0) | |
773 | { | |
774 | HWM_ERR("Deactivate sensor(%d) err = %d\n", sensor, err); | |
775 | err = -EINVAL; | |
776 | goto exit; | |
777 | } | |
778 | ||
779 | atomic_set(&cxt->enable, 0); | |
780 | } | |
781 | ||
782 | } | |
783 | ||
784 | exit: | |
785 | ||
786 | mutex_unlock(&obj->dc->lock); | |
787 | return err; | |
788 | } | |
789 | /*------------set delay--------------------------------------------------------*/ | |
790 | static int hwmsen_set_delay(int delay, int handle ) | |
791 | { | |
792 | int err = 0; | |
793 | struct hwmsen_context *cxt = NULL; | |
794 | ||
4b9e9796 S |
795 | if (handle > MAX_ANDROID_SENSOR_NUM || handle < 0) { |
796 | HWM_ERR("handle %d!\n", handle); | |
797 | return -EINVAL; | |
798 | } | |
6fa3eb70 S |
799 | cxt = hwm_obj->dc->cxt[handle]; |
800 | if(NULL == cxt ||(cxt->obj.sensor_operate == NULL)) | |
801 | { | |
802 | HWM_ERR("have no this sensor %d or operator point is null!\r\n", handle); | |
803 | } | |
804 | else //if(atomic_read(&cxt->enable) != 0) //always update delay even sensor is not enabled. | |
805 | { | |
806 | if(cxt->obj.sensor_operate(cxt->obj.self, SENSOR_DELAY, &delay,sizeof(int), NULL, 0, NULL) != 0) | |
807 | { | |
808 | HWM_ERR("%d sensor's sensor_operate function error %d!\r\n",handle,err); | |
809 | return err; | |
810 | } | |
811 | //record sensor delay | |
812 | atomic_set(&cxt->delay, delay); | |
813 | } | |
814 | return err; | |
815 | } | |
816 | /*----------------------------------------------------------------------------*/ | |
817 | static int hwmsen_wakeup(struct hwmdev_object *obj) | |
818 | { | |
819 | HWM_FUN(f); | |
820 | if(obj == NULL) | |
821 | { | |
822 | HWM_ERR("null pointer!!\n"); | |
823 | return -EINVAL; | |
824 | } | |
825 | ||
826 | input_event(obj->idev, EV_SYN, SYN_CONFIG, 0); | |
827 | ||
828 | return 0; | |
829 | } | |
830 | /*----------------------------------------------------------------------------*/ | |
831 | static ssize_t hwmsen_show_hwmdev(struct device* dev, | |
832 | struct device_attribute *attr, char *buf) | |
833 | { | |
834 | ||
835 | //struct hwmdev_object *devobj = (struct hwmdev_object*)dev_get_drvdata(dev); | |
836 | int len = 0; | |
837 | printk("sensor test: hwmsen_show_hwmdev function!\n"); | |
838 | /* | |
839 | if (!devobj || !devobj->dc) { | |
840 | HWM_ERR("null pointer: %p, %p", devobj, (!devobj) ? (NULL) : (devobj->dc)); | |
841 | return 0; | |
842 | } | |
843 | for (idx = 0; idx < C_MAX_HWMSEN_NUM; idx++) | |
844 | len += snprintf(buf+len, PAGE_SIZE-len, " %d", idx); | |
845 | len += snprintf(buf+len, PAGE_SIZE-len, "\n"); | |
846 | for (idx = 0; idx < C_MAX_HWMSEN_NUM; idx++) | |
847 | len += snprintf(buf+len, PAGE_SIZE-len, " %d", atomic_read(&devobj->dc->cxt[idx].enable)); | |
848 | len += snprintf(buf+len, PAGE_SIZE-len, "\n"); | |
849 | */ | |
850 | return len; | |
851 | } | |
852 | /*----------------------------------------------------------------------------*/ | |
853 | static ssize_t hwmsen_store_active(struct device* dev, struct device_attribute *attr, | |
854 | const char *buf, size_t count) | |
855 | { | |
856 | /* | |
857 | printk("sensor test: hwmsen_store_active function!\n"); | |
858 | struct hwmdev_object *devobj = (struct hwmdev_object*)dev_get_drvdata(dev); | |
859 | int sensor, enable, err, idx; | |
860 | ||
861 | if (!devobj || !devobj->dc) { | |
862 | HWM_ERR("null pointer!!\n"); | |
863 | return count; | |
864 | } | |
865 | ||
866 | if (!strncmp(buf, "all-start", 9)) { | |
867 | for (idx = 0; idx < C_MAX_HWMSEN_NUM; idx++) | |
868 | hwmsen_enable(devobj, idx, 1); | |
869 | } else if (!strncmp(buf, "all-stop", 8)) { | |
870 | for (idx = 0; idx < C_MAX_HWMSEN_NUM; idx++) | |
871 | hwmsen_enable(devobj, idx, 0); | |
872 | } else if (2 == sscanf(buf, "%d %d", &sensor, &enable)) { | |
873 | if ((err = hwmsen_enable(devobj, sensor, enable))) | |
874 | HWM_ERR("sensor enable failed: %d\n", err); | |
875 | } | |
876 | */ | |
877 | return count; | |
878 | } | |
879 | /*----------------------------------------------------------------------------*/ | |
880 | static ssize_t hwmsen_show_delay(struct device* dev, | |
881 | struct device_attribute *attr, char *buf) | |
882 | { | |
883 | /* | |
884 | struct hwmdev_object *devobj = (struct hwmdev_object*)dev_get_drvdata(dev); | |
885 | printk("sensor test: hwmsen_show_delay function!\n"); | |
886 | if (!devobj || !devobj->dc) { | |
887 | HWM_ERR("null pointer!!\n"); | |
888 | return 0; | |
889 | } | |
890 | ||
891 | return snprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&devobj->delay)); | |
892 | */ | |
893 | ||
894 | return 0; | |
895 | ||
896 | } | |
897 | /*----------------------------------------------------------------------------*/ | |
898 | static ssize_t hwmsen_store_delay(struct device* dev, struct device_attribute *attr, | |
899 | const char *buf, size_t count) | |
900 | { | |
901 | /* | |
902 | struct hwmdev_object *devobj = (struct hwmdev_object*)dev_get_drvdata(dev); | |
903 | int delay; | |
904 | printk("sensor test: hwmsen_show_delay function!\n"); | |
905 | if (!devobj || !devobj->dc) { | |
906 | HWM_ERR("null pointer!!\n"); | |
907 | return count; | |
908 | } | |
909 | ||
910 | if (1 != sscanf(buf, "%d", &delay)) { | |
911 | HWM_ERR("invalid format!!\n"); | |
912 | return count; | |
913 | } | |
914 | ||
915 | atomic_set(&devobj->delay, delay); | |
916 | */ | |
917 | return count; | |
918 | } | |
919 | /*----------------------------------------------------------------------------*/ | |
920 | static ssize_t hwmsen_show_wake(struct device* dev, | |
921 | struct device_attribute *attr, char *buf) | |
922 | { | |
923 | /* | |
924 | printk("sensor test: hwmsen_show_wake function!\n"); | |
925 | struct hwmdev_object *devobj = (struct hwmdev_object*)dev_get_drvdata(dev); | |
926 | ||
927 | if (!devobj || !devobj->dc) { | |
928 | HWM_ERR("null pointer!!\n"); | |
929 | return 0; | |
930 | } | |
931 | return snprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&devobj->wake)); | |
932 | */ | |
933 | return 0; | |
934 | } | |
935 | /*----------------------------------------------------------------------------*/ | |
936 | static ssize_t hwmsen_store_wake(struct device* dev, struct device_attribute *attr, | |
937 | const char *buf, size_t count) | |
938 | { | |
939 | /* | |
940 | struct hwmdev_object *devobj = (struct hwmdev_object*)dev_get_drvdata(dev); | |
941 | int wake, err; | |
942 | printk("sensor test: hwmsen_store_wake function!\n"); | |
943 | if (!devobj || !devobj->dc) { | |
944 | HWM_ERR("null pointer!!\n"); | |
945 | return count; | |
946 | } | |
947 | ||
948 | if (1 != sscanf(buf, "%d", &wake)) { | |
949 | HWM_ERR("invalid format!!\n"); | |
950 | return count; | |
951 | } | |
952 | ||
953 | if ((err = hwmsen_wakeup(devobj))) { | |
954 | HWM_ERR("wakeup sensor fail, %d\n", err); | |
955 | return count; | |
956 | } | |
957 | */ | |
958 | return count; | |
959 | } | |
960 | ||
961 | /*----------------------------------------------------------------------------*/ | |
962 | static ssize_t hwmsen_show_trace(struct device *dev, | |
963 | struct device_attribute *attr, char *buf) | |
964 | { | |
965 | ||
966 | struct i2c_client *client = to_i2c_client(dev); | |
967 | struct hwmdev_object *obj = i2c_get_clientdata(client); | |
968 | HWM_FUN(f); | |
969 | ||
970 | return snprintf(buf, PAGE_SIZE, "0x%08X\n", atomic_read(&obj->trace)); | |
971 | } | |
972 | /*----------------------------------------------------------------------------*/ | |
973 | static ssize_t hwmsen_store_trace(struct device* dev, | |
974 | struct device_attribute *attr, const char *buf, size_t count) | |
975 | { | |
976 | struct i2c_client *client = to_i2c_client(dev); | |
977 | struct hwmdev_object *obj = i2c_get_clientdata(client); | |
978 | int trc; | |
979 | HWM_FUN(f); | |
980 | ||
981 | if (1 == sscanf(buf, "0x%x\n", &trc)) | |
982 | { | |
983 | atomic_set(&obj->trace, trc); | |
984 | } | |
985 | else | |
986 | { | |
987 | HWM_ERR("set trace level fail!!\n"); | |
988 | } | |
989 | return count; | |
990 | } | |
991 | /*----------------------------------------------------------------------------*/ | |
992 | static ssize_t hwmsen_show_sensordevnum(struct device *dev, | |
993 | struct device_attribute *attr, char *buf) | |
994 | { | |
995 | const char *devname = NULL; | |
996 | devname = dev_name(&hwm_obj->idev->dev); | |
997 | ||
998 | return snprintf(buf, PAGE_SIZE, "%s\n", devname+5); | |
999 | } | |
1000 | DEVICE_ATTR(hwmdev, S_IRUGO, hwmsen_show_hwmdev, NULL); | |
1001 | DEVICE_ATTR(active, S_IWUSR | S_IRUGO, hwmsen_show_hwmdev, hwmsen_store_active); | |
1002 | DEVICE_ATTR(delay, S_IWUSR | S_IRUGO, hwmsen_show_delay, hwmsen_store_delay); | |
1003 | DEVICE_ATTR(wake, S_IWUSR | S_IRUGO, hwmsen_show_wake, hwmsen_store_wake); | |
1004 | DEVICE_ATTR(trace, S_IWUSR | S_IRUGO, hwmsen_show_trace, hwmsen_store_trace); | |
1005 | DEVICE_ATTR(hwmsensordevnum, S_IRUGO, hwmsen_show_sensordevnum, NULL); | |
1006 | /*----------------------------------------------------------------------------*/ | |
1007 | static struct device_attribute *hwmsen_attr_list[] = | |
1008 | { | |
1009 | &dev_attr_hwmdev, | |
1010 | &dev_attr_active, | |
1011 | &dev_attr_delay, | |
1012 | &dev_attr_wake, | |
1013 | &dev_attr_trace, | |
1014 | &dev_attr_hwmsensordevnum, | |
1015 | }; | |
1016 | ||
1017 | ||
1018 | /*----------------------------------------------------------------------------*/ | |
1019 | static int hwmsen_create_attr(struct device *dev) | |
1020 | { | |
1021 | int idx, err = 0; | |
1022 | int num = (int)(sizeof(hwmsen_attr_list)/sizeof(hwmsen_attr_list[0])); | |
1023 | HWM_FUN(); | |
1024 | if(!dev) | |
1025 | { | |
1026 | return -EINVAL; | |
1027 | } | |
1028 | ||
1029 | for(idx = 0; idx < num; idx++) | |
1030 | { | |
1031 | if((err = device_create_file(dev, hwmsen_attr_list[idx]))) | |
1032 | { | |
1033 | HWM_ERR("device_create_file (%s) = %d\n", hwmsen_attr_list[idx]->attr.name, err); | |
1034 | break; | |
1035 | } | |
1036 | } | |
1037 | ||
1038 | return err; | |
1039 | } | |
1040 | /*----------------------------------------------------------------------------*/ | |
1041 | static int hwmsen_delete_attr(struct device *dev) | |
1042 | { | |
1043 | ||
1044 | int idx ,err = 0; | |
1045 | int num = (int)(sizeof(hwmsen_attr_list)/sizeof(hwmsen_attr_list[0])); | |
1046 | HWM_FUN(f); | |
1047 | if (!dev) | |
1048 | { | |
1049 | return -EINVAL; | |
1050 | } | |
1051 | ||
1052 | ||
1053 | for (idx = 0; idx < num; idx++) | |
1054 | { | |
1055 | device_remove_file(dev, hwmsen_attr_list[idx]); | |
1056 | } | |
1057 | ||
1058 | return err; | |
1059 | } | |
1060 | ||
1061 | /*----------------------------------------------------------------*/ | |
1062 | static int init_static_data(void) | |
1063 | { | |
1064 | int i = 0; | |
1065 | // memset(&obj_data, 0, sizeof(struct hwmsen_data)); | |
1066 | // obj_data.lock = __MUTEX_INITIALIZER(obj_data.lock); | |
1067 | for(i=0; i < MAX_ANDROID_SENSOR_NUM; i++) | |
1068 | { | |
1069 | dev_cxt.cxt[i] = NULL; | |
1070 | memset(&obj_data.sensors_data[i], SENSOR_INVALID_VALUE, sizeof(hwm_sensor_data)); | |
1071 | obj_data.sensors_data[i].sensor = i; | |
1072 | ||
1073 | } | |
1074 | return 0; | |
1075 | } | |
1076 | /*----------------------------------------------------------------*/ | |
1077 | static int hwmsen_open(struct inode *node , struct file *fp) | |
1078 | { | |
1079 | HWM_FUN(f); | |
1080 | //struct file_private* data = kzalloc(sizeof(struct file_private), GFP_KERNEL); | |
1081 | // fp->private_data = data; | |
1082 | fp->private_data = NULL; | |
1083 | return nonseekable_open(node,fp); | |
1084 | } | |
1085 | /*----------------------------------------------------------------------------*/ | |
1086 | static int hwmsen_release(struct inode *node, struct file *fp) | |
1087 | { | |
1088 | HWM_FUN(f); | |
1089 | kfree(fp->private_data); | |
1090 | fp->private_data = NULL; | |
1091 | return 0; | |
1092 | } | |
1093 | /*----------------------------------------------------------------------------*/ | |
1094 | static void update_workqueue_polling_rate(int newDelay) | |
1095 | { | |
1096 | atomic_t delaytemp; | |
1097 | int i=0; | |
1098 | int idx=0; | |
1099 | struct hwmsen_context *cxt = NULL; | |
1100 | struct hwmdev_object *obj = hwm_obj; | |
1101 | HWM_FUN(f); | |
1102 | atomic_set(&delaytemp, 200);//used to finding fastest sensor polling rate | |
1103 | ||
1104 | for(i = 0; i < MAX_ANDROID_SENSOR_NUM; i++) | |
1105 | { | |
1106 | if(hwm_obj->active_data_sensor & 1<<i) | |
1107 | { | |
1108 | if(atomic_read(&delaytemp) > atomic_read(&(hwm_obj->dc->cxt[i]->delay))) | |
1109 | { | |
1110 | atomic_set(&delaytemp, atomic_read(&(hwm_obj->dc->cxt[i]->delay)));// work queue polling delay base time | |
1111 | } | |
1112 | } | |
1113 | } | |
1114 | //use the fastest sensor polling delay as work queue polling delay base time | |
1115 | if(atomic_read(&delaytemp) > newDelay) | |
1116 | { | |
1117 | atomic_set(&hwm_obj->delay, newDelay);// work queue polling delay base time | |
1118 | HWM_LOG("set new workqueue base time=%d\n",atomic_read(&hwm_obj->delay)); | |
1119 | } | |
1120 | else | |
1121 | { | |
1122 | atomic_set(&hwm_obj->delay, atomic_read(&delaytemp)); | |
1123 | HWM_LOG("set old fastest sensor delay as workqueue base time=%d\n",atomic_read(&hwm_obj->delay)); | |
1124 | } | |
1125 | ||
1126 | //upadate all sensors delayCountSet | |
1127 | for(idx = 0; idx < MAX_ANDROID_SENSOR_NUM; idx++) | |
1128 | { | |
1129 | cxt = obj->dc->cxt[idx]; | |
1130 | if((cxt == NULL) || (cxt->obj.sensor_operate == NULL) | |
1131 | || !(obj->active_data_sensor&(0x01<<idx))) | |
1132 | { | |
1133 | continue; | |
1134 | } | |
1135 | ||
1136 | if(0 == atomic_read(&cxt->delay)) | |
1137 | { | |
1138 | cxt->delayCount = cxt->delayCountSet = 0; | |
1139 | HWM_LOG("%s,set delayCountSet=0 delay =%d handle=%d\r\n",__func__, atomic_read(&cxt->delay), idx); | |
1140 | } | |
1141 | if(atomic_read(&cxt->delay) <= atomic_read(&hwm_obj->delay)) | |
1142 | { | |
1143 | cxt->delayCount = cxt->delayCountSet = 0; | |
1144 | HWM_LOG("%s,set delayCountSet=0 delay =%d handle=%d\r\n",__func__, atomic_read(&cxt->delay), idx); | |
1145 | } | |
1146 | else | |
1147 | { | |
1148 | i= atomic_read(&cxt->delay)/atomic_read(&hwm_obj->delay); | |
1149 | cxt->delayCount = cxt->delayCountSet = i; | |
1150 | HWM_LOG("%s:set delayCountSet=%d delay =%d handle=%d\r\n",__func__, i, atomic_read(&cxt->delay), idx); | |
1151 | #if 0 | |
1152 | switch(i) | |
1153 | { | |
1154 | case 3: | |
1155 | // 200/60 ;60/20 | |
1156 | cxt->delayCount = cxt->delayCountSet = 3; | |
1157 | HWM_LOG("%s:set delayCountSet=3 delay =%d handle=%d\r\n",__func__,atomic_read(&cxt->delay), idx); | |
1158 | break; | |
1159 | case 10: | |
1160 | // 200/20 | |
1161 | cxt->delayCount = cxt->delayCountSet = 10; | |
1162 | HWM_LOG("%s:set delayCountSet=10 delay =%d handle=%d\r\n",__func__, atomic_read(&cxt->delay), idx); | |
1163 | break; | |
1164 | } | |
1165 | #endif | |
1166 | } | |
1167 | } | |
1168 | } | |
1169 | ||
1170 | //static int hwmsen_ioctl(struct inode *node, struct file *fp, | |
1171 | // unsigned int cmd, unsigned long arg) | |
1172 | static long hwmsen_unlocked_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) | |
1173 | { | |
1174 | //HWM_LOG("IO parament %d!\r\n", cmd); | |
1175 | void __user *argp = (void __user*)arg; | |
1176 | uint32_t flag; | |
1177 | struct sensor_delay delayPara; | |
1178 | hwm_trans_data hwm_sensors_data; | |
1179 | int i = 0; | |
1180 | atomic_t delaytemp; | |
1181 | atomic_set(&delaytemp, 200);//used to finding fastest sensor polling rate | |
1182 | //int delaytemp=200;//used to finding fastest sensor polling rate | |
1183 | ||
1184 | if(!hwm_obj) | |
1185 | { | |
1186 | HWM_ERR("null pointer!!\n"); | |
1187 | return -EINVAL; | |
1188 | } | |
1189 | ||
1190 | switch(cmd) | |
1191 | { | |
1192 | case HWM_IO_SET_DELAY: | |
1193 | // android2.3 sensor system has 4 sample delay 0ms 20ms 60ms 200ms | |
1194 | if(copy_from_user(&delayPara, argp, sizeof(delayPara))) | |
1195 | { | |
1196 | HWM_ERR("copy_from_user fail!!\n"); | |
1197 | return -EFAULT; | |
1198 | } | |
1199 | HWM_LOG("ioctl delay handle=%d,delay =%d\n",delayPara.handle,delayPara.delay); | |
1200 | hwmsen_set_delay(delayPara.delay,delayPara.handle);//modified for android2.3 | |
1201 | update_workqueue_polling_rate(delayPara.delay); | |
1202 | ||
1203 | break; | |
1204 | ||
1205 | case HWM_IO_SET_WAKE: | |
1206 | hwmsen_wakeup(hwm_obj); | |
1207 | break; | |
1208 | ||
1209 | case HWM_IO_ENABLE_SENSOR: | |
1210 | if(copy_from_user(&flag, argp, sizeof(flag))) | |
1211 | { | |
1212 | HWM_ERR("copy_from_user fail!!\n"); | |
1213 | return -EFAULT; | |
1214 | } | |
1215 | hwmsen_enable(hwm_obj, flag, 1); | |
1216 | break; | |
1217 | ||
1218 | case HWM_IO_DISABLE_SENSOR: | |
1219 | if(copy_from_user(&flag, argp, sizeof(flag))) | |
1220 | { | |
1221 | HWM_ERR("copy_from_user fail!!\n"); | |
1222 | return -EFAULT; | |
1223 | } | |
1224 | hwmsen_enable(hwm_obj, flag, 0); | |
1225 | break; | |
1226 | ||
1227 | case HWM_IO_GET_SENSORS_DATA: | |
1228 | if(copy_from_user(&hwm_sensors_data, argp, sizeof(hwm_sensors_data))) | |
1229 | { | |
1230 | HWM_ERR("copy_from_user fail!!\n"); | |
1231 | return -EFAULT; | |
1232 | } | |
1233 | mutex_lock(&obj_data.lock); | |
1234 | memcpy(hwm_sensors_data.data, &(obj_data.sensors_data),sizeof(hwm_sensor_data) * MAX_ANDROID_SENSOR_NUM); | |
1235 | for(i = 0; i < MAX_ANDROID_SENSOR_NUM; i++) | |
1236 | { | |
1237 | if(hwm_sensors_data.date_type & 1<<i) | |
1238 | { | |
1239 | hwm_sensors_data.data[i].update = 1; | |
1240 | } | |
1241 | else | |
1242 | { | |
1243 | hwm_sensors_data.data[i].update = 0; | |
1244 | } | |
1245 | } | |
1246 | mutex_unlock(&obj_data.lock); | |
1247 | if(copy_to_user(argp, &hwm_sensors_data, sizeof(hwm_sensors_data))) | |
1248 | { | |
1249 | HWM_ERR("copy_to_user fail!!\n"); | |
1250 | return -EFAULT; | |
1251 | } | |
1252 | break; | |
1253 | ||
1254 | case HWM_IO_ENABLE_SENSOR_NODATA: | |
1255 | if(copy_from_user(&flag, argp, sizeof(flag))) | |
1256 | { | |
1257 | HWM_ERR("copy_from_user fail!!\n"); | |
1258 | return -EFAULT; | |
1259 | } | |
1260 | hwmsen_enable_nodata(hwm_obj, flag, 1); | |
1261 | break; | |
1262 | ||
1263 | case HWM_IO_DISABLE_SENSOR_NODATA: | |
1264 | if(copy_from_user(&flag, argp, sizeof(flag))) | |
1265 | { | |
1266 | HWM_ERR("copy_from_user fail!!\n"); | |
1267 | return -EFAULT; | |
1268 | } | |
1269 | hwmsen_enable_nodata(hwm_obj, flag, 0); | |
1270 | break; | |
1271 | ||
1272 | default: | |
1273 | HWM_ERR("have no this paramenter %d!!\n", cmd); | |
1274 | return -ENOIOCTLCMD; | |
1275 | } | |
1276 | ||
1277 | return 0; | |
1278 | } | |
1279 | /*----------------------------------------------------------------------------*/ | |
1280 | static struct file_operations hwmsen_fops = { | |
1281 | // .owner = THIS_MODULE, | |
1282 | .open = hwmsen_open, | |
1283 | .release = hwmsen_release, | |
1284 | // .ioctl = hwmsen_ioctl, | |
1285 | .unlocked_ioctl = hwmsen_unlocked_ioctl, | |
1286 | }; | |
1287 | /*----------------------------------------------------------------------------*/ | |
1288 | static int hwmsen_probe(struct platform_device *pdev) | |
1289 | { | |
1290 | ||
1291 | int err; | |
1292 | //HWM_LOG("+++++++++++++++++hwmsen_probe!!\n"); | |
1293 | ||
1294 | HWM_FUN(f); | |
1295 | init_static_data(); | |
1296 | hwm_obj = hwmsen_alloc_object(); | |
1297 | if (!hwm_obj) | |
1298 | { | |
1299 | err = -ENOMEM; | |
1300 | HWM_ERR("unable to allocate devobj!\n"); | |
1301 | goto exit_alloc_data_failed; | |
1302 | } | |
1303 | ||
1304 | hwm_obj->idev = input_allocate_device(); | |
1305 | if (!hwm_obj->idev) | |
1306 | { | |
1307 | err = -ENOMEM; | |
1308 | HWM_ERR("unable to allocate input device!\n"); | |
1309 | goto exit_alloc_input_dev_failed; | |
1310 | } | |
1311 | ||
1312 | set_bit(EV_REL, hwm_obj->idev->evbit); | |
1313 | set_bit(EV_SYN, hwm_obj->idev->evbit); | |
1314 | ||
1315 | input_set_capability(hwm_obj->idev, EV_REL, EVENT_TYPE_SENSOR); | |
1316 | hwm_obj->idev->name = HWM_INPUTDEV_NAME; | |
1317 | if((err = input_register_device(hwm_obj->idev))) | |
1318 | { | |
1319 | HWM_ERR("unable to register input device!\n"); | |
1320 | goto exit_input_register_device_failed; | |
1321 | } | |
1322 | input_set_drvdata(hwm_obj->idev, hwm_obj); | |
1323 | ||
1324 | hwm_obj->mdev.minor = MISC_DYNAMIC_MINOR; | |
1325 | hwm_obj->mdev.name = HWM_SENSOR_DEV_NAME; | |
1326 | hwm_obj->mdev.fops = &hwmsen_fops; | |
1327 | if((err = misc_register(&hwm_obj->mdev))) | |
1328 | { | |
1329 | HWM_ERR("unable to register sensor device!!\n"); | |
1330 | goto exit_misc_register_failed; | |
1331 | } | |
1332 | dev_set_drvdata(hwm_obj->mdev.this_device, hwm_obj); | |
1333 | ||
1334 | if(hwmsen_create_attr(hwm_obj->mdev.this_device) != 0) | |
1335 | { | |
1336 | HWM_ERR("unable to create attributes!!\n"); | |
1337 | goto exit_hwmsen_create_attr_failed; | |
1338 | } | |
1339 | #if defined(CONFIG_HAS_EARLYSUSPEND) | |
1340 | // add for fix resume bug | |
1341 | atomic_set(&(hwm_obj->early_suspend), 0); | |
1342 | hwm_obj->early_drv.level = EARLY_SUSPEND_LEVEL_STOP_DRAWING - 1, | |
1343 | hwm_obj->early_drv.suspend = hwmsen_early_suspend, | |
1344 | hwm_obj->early_drv.resume = hwmsen_late_resume, | |
1345 | register_early_suspend(&hwm_obj->early_drv); | |
1346 | wake_lock_init(&(hwm_obj->read_data_wake_lock),WAKE_LOCK_SUSPEND,"read_data_wake_lock"); | |
1347 | // add for fix resume bug end | |
1348 | #endif //#if defined(CONFIG_HAS_EARLYSUSPEND) | |
1349 | return 0; | |
1350 | ||
1351 | exit_hwmsen_create_attr_failed: | |
1352 | exit_misc_register_failed: | |
1353 | // exit_get_hwmsen_info_failed: | |
1354 | exit_input_register_device_failed: | |
1355 | input_free_device(hwm_obj->idev); | |
1356 | ||
1357 | exit_alloc_input_dev_failed: | |
1358 | kfree(hwm_obj); | |
1359 | ||
1360 | exit_alloc_data_failed: | |
1361 | return err; | |
1362 | } | |
1363 | /*----------------------------------------------------------------------------*/ | |
1364 | static int hwmsen_remove(struct platform_device *pdev) | |
1365 | { | |
1366 | HWM_FUN(f); | |
1367 | ||
1368 | input_unregister_device(hwm_obj->idev); | |
1369 | hwmsen_delete_attr(hwm_obj->mdev.this_device); | |
1370 | misc_deregister(&hwm_obj->mdev); | |
1371 | kfree(hwm_obj); | |
1372 | ||
1373 | return 0; | |
1374 | } | |
1375 | #if defined(CONFIG_HAS_EARLYSUSPEND) | |
1376 | static void hwmsen_early_suspend(struct early_suspend *h) | |
1377 | { | |
1378 | //HWM_FUN(f); | |
1379 | atomic_set(&(hwm_obj->early_suspend), 1); | |
1380 | HWM_LOG(" hwmsen_early_suspend ok------->hwm_obj->early_suspend=%d \n",atomic_read(&hwm_obj->early_suspend)); | |
1381 | return ; | |
1382 | } | |
1383 | /*----------------------------------------------------------------------------*/ | |
1384 | static void hwmsen_late_resume(struct early_suspend *h) | |
1385 | { | |
1386 | //HWM_FUN(f); | |
1387 | atomic_set(&(hwm_obj->early_suspend), 0); | |
1388 | HWM_LOG(" hwmsen_late_resume ok------->hwm_obj->early_suspend=%d \n",atomic_read(&hwm_obj->early_suspend)); | |
1389 | return ; | |
1390 | } | |
1391 | #endif //#if defined(CONFIG_HAS_EARLYSUSPEND) | |
1392 | /*----------------------------------------------------------------------------*/ | |
1393 | static int hwmsen_suspend(struct platform_device *dev, pm_message_t state) | |
1394 | { | |
1395 | //HWM_FUN(f); | |
1396 | return 0; | |
1397 | } | |
1398 | /*----------------------------------------------------------------------------*/ | |
1399 | static int hwmsen_resume(struct platform_device *dev) | |
1400 | { | |
1401 | //HWM_FUN(f); | |
1402 | return 0; | |
1403 | } | |
1404 | /*----------------------------------------------------------------------------*/ | |
1405 | ||
1406 | #ifdef CONFIG_OF | |
1407 | static const struct of_device_id hwmsensor_of_match[] = { | |
1408 | { .compatible = "mediatek,hwmsensor", }, | |
1409 | {}, | |
1410 | }; | |
1411 | #endif | |
1412 | ||
1413 | static struct platform_driver hwmsen_driver = | |
1414 | { | |
1415 | .probe = hwmsen_probe, | |
1416 | .remove = hwmsen_remove, | |
1417 | .suspend = hwmsen_suspend, | |
1418 | .resume = hwmsen_resume, | |
1419 | .driver = | |
1420 | { | |
1421 | .name = HWM_SENSOR_DEV_NAME, | |
1422 | #ifdef CONFIG_OF | |
1423 | .of_match_table = hwmsensor_of_match, | |
1424 | #endif | |
1425 | // .owner = THIS_MODULE, | |
1426 | } | |
1427 | }; | |
1428 | ||
1429 | /*----------------------------------------------------------------------------*/ | |
1430 | ||
1431 | #if defined(CONFIG_MTK_AUTO_DETECT_MAGNETOMETER) | |
1432 | ||
1433 | int hwmsen_msensor_remove(struct platform_device *pdev) | |
1434 | { | |
1435 | int err =0; | |
1436 | int i=0; | |
1437 | for(i = 0; i < MAX_CHOOSE_G_NUM; i++) | |
1438 | { | |
1439 | if(0 == strcmp(msensor_name,msensor_init_list[i]->name)) | |
1440 | { | |
1441 | if(NULL == msensor_init_list[i]->uninit) | |
1442 | { | |
1443 | HWM_LOG(" hwmsen_msensor_remove null pointer \n"); | |
1444 | return -1; | |
1445 | } | |
1446 | msensor_init_list[i]->uninit(); | |
1447 | } | |
1448 | } | |
1449 | return 0; | |
1450 | } | |
1451 | ||
1452 | static int msensor_probe(struct platform_device *pdev) | |
1453 | { | |
1454 | int i =0; | |
1455 | int err=0; | |
1456 | HWM_LOG(" msensor_probe +\n"); | |
1457 | for(i = 0; i < MAX_CHOOSE_G_NUM; i++) | |
1458 | { | |
1459 | if(NULL != msensor_init_list[i]) | |
1460 | { | |
1461 | err = msensor_init_list[i]->init(); | |
1462 | if(0 == err) | |
1463 | { | |
1464 | strcpy(msensor_name,msensor_init_list[i]->name); | |
1465 | HWM_LOG(" msensor %s probe ok\n", msensor_name); | |
1466 | break; | |
1467 | } | |
1468 | } | |
1469 | } | |
1470 | return 0; | |
1471 | } | |
1472 | ||
1473 | ||
1474 | static struct platform_driver msensor_driver = { | |
1475 | .probe = msensor_probe, | |
1476 | .remove = hwmsen_msensor_remove, | |
1477 | .driver = | |
1478 | { | |
1479 | .name = "msensor", | |
1480 | // .owner = THIS_MODULE, | |
1481 | } | |
1482 | }; | |
1483 | ||
1484 | int hwmsen_msensor_add(struct sensor_init_info* obj) | |
1485 | { | |
1486 | int err=0; | |
1487 | int i =0; | |
1488 | ||
1489 | HWM_FUN(f); | |
1490 | ||
1491 | for(i =0; i < MAX_CHOOSE_G_NUM; i++ ) | |
1492 | { | |
1493 | if(NULL == msensor_init_list[i]) | |
1494 | { | |
1495 | msensor_init_list[i] = kzalloc(sizeof(struct sensor_init_info), GFP_KERNEL); | |
1496 | if(NULL == msensor_init_list[i]) | |
1497 | { | |
1498 | HWM_ERR("kzalloc error"); | |
1499 | return -1; | |
1500 | } | |
1501 | obj->platform_diver_addr = &msensor_driver; | |
1502 | msensor_init_list[i] = obj; | |
1503 | ||
1504 | break; | |
1505 | } | |
1506 | } | |
1507 | ||
1508 | return err; | |
1509 | } | |
1510 | EXPORT_SYMBOL_GPL(hwmsen_msensor_add); | |
1511 | ||
1512 | #endif | |
1513 | ||
1514 | ||
1515 | ||
1516 | #if defined(CONFIG_MTK_AUTO_DETECT_ACCELEROMETER)// | |
1517 | ||
1518 | int hwmsen_gsensor_remove(struct platform_device *pdev) | |
1519 | { | |
1520 | int i=0; | |
1521 | for(i = 0; i < MAX_CHOOSE_G_NUM; i++) | |
1522 | { | |
1523 | if(0 == strcmp(gsensor_name,gsensor_init_list[i]->name)) | |
1524 | { | |
1525 | if(NULL == gsensor_init_list[i]->uninit) | |
1526 | { | |
1527 | HWM_LOG(" hwmsen_gsensor_remove null pointer +\n"); | |
1528 | return -1; | |
1529 | } | |
1530 | gsensor_init_list[i]->uninit(); | |
1531 | } | |
1532 | } | |
1533 | return 0; | |
1534 | } | |
1535 | ||
1536 | static int gsensor_probe(struct platform_device *pdev) | |
1537 | { | |
1538 | int i =0; | |
1539 | int err=0; | |
1540 | HWM_LOG(" gsensor_probe +\n"); | |
1541 | ||
1542 | // | |
1543 | /* | |
1544 | for(i = 0; i < MAX_CHOOSE_G_NUM; i++) | |
1545 | { | |
1546 | HWM_LOG(" gsensor_init_list[i]=%d\n",gsensor_init_list[i]); | |
1547 | } | |
1548 | */ | |
1549 | // | |
1550 | for(i = 0; i < MAX_CHOOSE_G_NUM; i++) | |
1551 | { | |
1552 | HWM_LOG(" i=%d\n",i); | |
1553 | if(0 != gsensor_init_list[i]) | |
1554 | { | |
1555 | HWM_LOG(" !!!!!!!!\n"); | |
1556 | err = gsensor_init_list[i]->init(); | |
1557 | if(0 == err) | |
1558 | { | |
1559 | strcpy(gsensor_name,gsensor_init_list[i]->name); | |
1560 | HWM_LOG(" gsensor %s probe ok\n", gsensor_name); | |
1561 | break; | |
1562 | } | |
1563 | } | |
1564 | } | |
1565 | ||
1566 | if(i == MAX_CHOOSE_G_NUM) | |
1567 | { | |
1568 | HWM_LOG(" gsensor probe fail\n"); | |
1569 | } | |
1570 | return 0; | |
1571 | } | |
1572 | ||
1573 | ||
1574 | static struct platform_driver gsensor_driver = { | |
1575 | .probe = gsensor_probe, | |
1576 | .remove = hwmsen_gsensor_remove, | |
1577 | .driver = | |
1578 | { | |
1579 | .name = "gsensor", | |
1580 | // .owner = THIS_MODULE, | |
1581 | } | |
1582 | }; | |
1583 | ||
1584 | int hwmsen_gsensor_add(struct sensor_init_info* obj) | |
1585 | { | |
1586 | int err=0; | |
1587 | int i =0; | |
1588 | ||
1589 | HWM_FUN(f); | |
1590 | ||
1591 | for(i =0; i < MAX_CHOOSE_G_NUM; i++ ) | |
1592 | { | |
1593 | if(NULL == gsensor_init_list[i]) | |
1594 | { | |
1595 | gsensor_init_list[i] = kzalloc(sizeof(struct sensor_init_info), GFP_KERNEL); | |
1596 | if(NULL == gsensor_init_list[i]) | |
1597 | { | |
1598 | HWM_ERR("kzalloc error"); | |
1599 | return -1; | |
1600 | } | |
1601 | obj->platform_diver_addr = &gsensor_driver; | |
1602 | gsensor_init_list[i] = obj; | |
1603 | ||
1604 | break; | |
1605 | } | |
1606 | } | |
1607 | ||
1608 | return err; | |
1609 | } | |
1610 | EXPORT_SYMBOL_GPL(hwmsen_gsensor_add); | |
1611 | ||
1612 | #endif | |
1613 | ||
1614 | #if defined(CONFIG_MTK_AUTO_DETECT_ALSPS) | |
1615 | ||
1616 | int hwmsen_alsps_sensor_remove(struct platform_device *pdev) | |
1617 | { | |
1618 | int err =0; | |
1619 | int i=0; | |
1620 | for(i = 0; i < MAX_CHOOSE_G_NUM; i++) | |
1621 | { | |
1622 | if(0 == strcmp(alsps_name,alsps_init_list[i]->name)) | |
1623 | { | |
1624 | if(NULL == alsps_init_list[i]->uninit) | |
1625 | { | |
1626 | HWM_LOG(" hwmsen_alsps_sensor_remove null pointer \n"); | |
1627 | return -1; | |
1628 | } | |
1629 | alsps_init_list[i]->uninit(); | |
1630 | } | |
1631 | } | |
1632 | return 0; | |
1633 | } | |
1634 | ||
1635 | static int alsps_sensor_probe(struct platform_device *pdev) | |
1636 | { | |
1637 | int i =0; | |
1638 | int err=0; | |
1639 | HWM_LOG(" als_ps sensor_probe +\n"); | |
1640 | for(i = 0; i < MAX_CHOOSE_G_NUM; i++) | |
1641 | { | |
1642 | if(NULL != alsps_init_list[i]) | |
1643 | { | |
1644 | err = alsps_init_list[i]->init(); | |
1645 | if(0 == err) | |
1646 | { | |
1647 | strcpy(alsps_name,alsps_init_list[i]->name); | |
1648 | HWM_LOG(" alsps sensor %s probe ok\n", alsps_name); | |
1649 | break; | |
1650 | } | |
1651 | } | |
1652 | } | |
1653 | return 0; | |
1654 | } | |
1655 | ||
1656 | ||
1657 | static struct platform_driver alsps_sensor_driver = { | |
1658 | .probe = alsps_sensor_probe, | |
1659 | .remove = hwmsen_alsps_sensor_remove, | |
1660 | .driver = | |
1661 | { | |
1662 | .name = "als_ps", | |
1663 | } | |
1664 | }; | |
1665 | ||
1666 | int hwmsen_alsps_sensor_add(struct sensor_init_info* obj) | |
1667 | { | |
1668 | int err=0; | |
1669 | int i =0; | |
1670 | ||
1671 | HWM_FUN(f); | |
1672 | ||
1673 | for(i =0; i < MAX_CHOOSE_G_NUM; i++ ) | |
1674 | { | |
1675 | if(NULL == alsps_init_list[i]) | |
1676 | { | |
1677 | alsps_init_list[i] = kzalloc(sizeof(struct sensor_init_info), GFP_KERNEL); | |
1678 | if(NULL == alsps_init_list[i]) | |
1679 | { | |
1680 | HWM_ERR("kzalloc error"); | |
1681 | return -1; | |
1682 | } | |
1683 | obj->platform_diver_addr = &alsps_sensor_driver; | |
1684 | alsps_init_list[i] = obj; | |
1685 | ||
1686 | break; | |
1687 | } | |
1688 | } | |
1689 | ||
1690 | return err; | |
1691 | } | |
1692 | EXPORT_SYMBOL_GPL(hwmsen_alsps_sensor_add); | |
1693 | ||
1694 | #endif | |
1695 | ||
1696 | /*----------------------------------------------------------------------------*/ | |
1697 | static int __init hwmsen_init(void) | |
1698 | { | |
1699 | HWM_FUN(f); | |
1700 | if(platform_driver_register(&hwmsen_driver)) | |
1701 | { | |
1702 | HWM_ERR("failed to register sensor driver"); | |
1703 | return -ENODEV; | |
1704 | } | |
1705 | ||
1706 | ||
1707 | #if defined(CONFIG_MTK_AUTO_DETECT_ACCELEROMETER) | |
1708 | if(platform_driver_register(&gsensor_driver)) | |
1709 | { | |
1710 | HWM_ERR("failed to register gensor driver"); | |
1711 | return -ENODEV; | |
1712 | } | |
1713 | #endif | |
1714 | ||
1715 | #if defined(CONFIG_MTK_AUTO_DETECT_MAGNETOMETER) | |
1716 | if(platform_driver_register(&msensor_driver)) | |
1717 | { | |
1718 | HWM_ERR("failed to register mensor driver"); | |
1719 | return -ENODEV; | |
1720 | } | |
1721 | #endif | |
1722 | ||
1723 | #if defined(CONFIG_MTK_AUTO_DETECT_ALSPS) | |
1724 | if(platform_driver_register(&alsps_sensor_driver)) | |
1725 | { | |
1726 | HWM_ERR("failed to register alsps_sensor_driver driver"); | |
1727 | return -ENODEV; | |
1728 | } | |
1729 | #endif | |
1730 | ||
1731 | ||
1732 | return 0; | |
1733 | } | |
1734 | /*----------------------------------------------------------------------------*/ | |
1735 | static void __exit hwmsen_exit(void) | |
1736 | { | |
1737 | platform_driver_unregister(&hwmsen_driver); | |
1738 | } | |
1739 | /*----------------------------------------------------------------------------*/ | |
1740 | module_init(hwmsen_init); | |
1741 | module_exit(hwmsen_exit); | |
1742 | MODULE_LICENSE("GPL"); | |
1743 | MODULE_DESCRIPTION("sensor device driver"); | |
1744 | MODULE_AUTHOR("Chunlei Wang<chunlei.wang@mediatek.com"); |