diff options
Diffstat (limited to 'tizen/DEVICE')
-rw-r--r-- | tizen/DEVICE/CMakeLists.txt | 28 | ||||
-rw-r--r-- | tizen/DEVICE/include/file.h | 75 | ||||
-rw-r--r-- | tizen/DEVICE/src/file.c | 460 | ||||
-rw-r--r-- | tizen/DEVICE/src/haptic.c | 225 | ||||
-rw-r--r-- | tizen/DEVICE/src/sysnoti.c | 163 |
5 files changed, 951 insertions, 0 deletions
diff --git a/tizen/DEVICE/CMakeLists.txt b/tizen/DEVICE/CMakeLists.txt new file mode 100644 index 0000000..6db8080 --- /dev/null +++ b/tizen/DEVICE/CMakeLists.txt @@ -0,0 +1,28 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) + +SET(SRCS + src/haptic.c) + +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include) + +SET(DEPENDENTS "dlog deviced device-node") + +INCLUDE(FindPkgConfig) +pkg_check_modules(rpkgs REQUIRED ${DEPENDENTS}) + +FOREACH(flag ${rpkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden") +SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -g -fno-omit-frame-pointer") +SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Wl,--no-as-needed") + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") + +ADD_DEFINITIONS("-DPREFIX=\"${PREFIX}\"") +ADD_DEFINITIONS("-DENABLE_DLOG_OUT -DSLP_DEBUG") + +ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS}) +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${rpkgs_LDFLAGS}) +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${LIB_INSTALL_DIR}) diff --git a/tizen/DEVICE/include/file.h b/tizen/DEVICE/include/file.h new file mode 100644 index 0000000..798ad5d --- /dev/null +++ b/tizen/DEVICE/include/file.h @@ -0,0 +1,75 @@ +/* + * haptic-module-tizen + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#ifndef __FILE_H__ +#define __FILE_H__ + +#define GCC_PACK __attribute__((packed)) + +/* little-endian form */ +#define mmioHeaderID(ch0,ch1,ch2,ch3) \ + ((unsigned int)(unsigned char)(ch0) | ((unsigned int)(unsigned char)(ch1) << 8) | \ + ((unsigned int)(unsigned char)(ch2) << 16) | ((unsigned int)(unsigned char)(ch3) << 24)) + +#define HEADER_ID mmioHeaderID('T','H','F','M') // 0x4D464854 +#define FMT_ID mmioHeaderID('f','m','t',' ') // 0x20746D66 +#define DATA_ID mmioHeaderID('d','a','t','a') // 0x61746164 + +typedef unsigned int ID; /* a four character code */ + +typedef struct _FormatChunk { + ID chunkID; /* chunk ID */ + int chunkSize; /* chunk Size */ + unsigned short wChannels; /* number of channels (Mono = 1, Stereo = 2, etc.) */ + unsigned short wBlockAlign; /* block size of data (wChannels*1byte) */ + unsigned int dwMagnitude; /* max magnitude */ + unsigned int dwDuration; /* duration */ +} GCC_PACK FormatChunk; + +typedef struct _DataChunk { + ID chunkID; + int chunkSize; + unsigned char pData[]; +} GCC_PACK DataChunk; + +typedef struct _HapticFile { + ID chunkID; /* chunk ID */ + int chunkSize; /* chunk Size */ + FormatChunk fmt; /* Format chunk */ + DataChunk data; /* Data chunk */ +} GCC_PACK HapticFile; + +typedef struct _HapticElement { + int duration; + int level; +} HapticElement; + +int GetHapticLevelMax(int *max); + +int InitializeBuffer(unsigned char *vibe_buffer, int max_bufsize); +int InsertElement(unsigned char *vibe_buffer, int max_bufsize, HapticElement *element); +int GetBufferSize(const unsigned char *vibe_buffer, int *size); +int GetBufferDuration(const unsigned char *vibe_buffer, int *duration); +int PlayOneshot(int handle, int duration, int level); +int PlayBuffer(int handle, const unsigned char *vibe_buffer, int iteration, int level); +int Stop(int handle); +int OpenDevice(int handle); +int CloseDevice(int handle); +int GetState(int handle, int *state); + +#endif // __FIEL_H__ diff --git a/tizen/DEVICE/src/file.c b/tizen/DEVICE/src/file.c new file mode 100644 index 0000000..1a6ae80 --- /dev/null +++ b/tizen/DEVICE/src/file.c @@ -0,0 +1,460 @@ +/* + * haptic-module-tizen + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> +#include <pthread.h> +#include <device-node.h> + +#include "file.h" +#include "haptic_module_log.h" + +#define BITPERMS 50 +#define MAX_LEVEL 255.0f +#define DEFAULT_EFFECT_HANDLE 0x02 + +#define STATE_PLAY 0 +#define STATE_STOP 1 + +#define PREDEF_HAPTIC "haptic" + +enum { + OPEN = 0, + CLOSE, + PLAY, + ONESHOT, + STOP, + LEVEL, +}; + +typedef struct { + int handle; + unsigned char **ppbuffer; + int channels; + int length; + int iteration; +} BUFFER; + +static pthread_t tid; +static BUFFER gbuffer; +static int stop; +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + +static int _check_valid_haptic_format(HapticFile *file) +{ + if (file->chunkID != HEADER_ID) + return -1; + + if (file->fmt.chunkID != FMT_ID) + return -1; + + if (file->data.chunkID != DATA_ID) + return -1; + + return 0; +} + +static int __haptic_predefine_action(int handle, int prop, int val) +{ + char buf_pid[32]; + char buf_prop[32]; + char buf_handle[32]; + char buf_val[32]; + + snprintf(buf_pid, sizeof(buf_pid), "%d", getpid()); + snprintf(buf_prop, sizeof(buf_prop), "%d", prop); + snprintf(buf_handle, sizeof(buf_handle), "%d", handle); + snprintf(buf_val, sizeof(buf_val), "%d", val); + + MODULE_LOG("pid : %s(%d), prop : %s, handle : %s", buf_pid, pthread_self(), buf_prop, buf_handle); + return __haptic_call_predef_action(PREDEF_HAPTIC, 4, buf_pid, buf_prop, buf_handle, buf_val); +} + +static int _create_thread(void* data, void*(*func)(void*)) +{ + if (tid) { + MODULE_ERROR("pthread already created"); + return -1; + } + + if (pthread_create(&tid, NULL, func, data) != 0) { + MODULE_ERROR("pthread_create is failed : %s", strerror(errno)); + return -1; + } + + return 0; +} + +static int _cancel_thread(void) +{ + int *ptr; + int ret; + + if (!tid) { + MODULE_LOG("pthread not initialized"); + return 0; + } + + MODULE_LOG("cancel thread!!!"); + + stop = 1; + + while (pthread_mutex_trylock(&mutex) == EBUSY) { + usleep(100); + MODULE_LOG("Already locked.."); + } + + pthread_mutex_unlock(&mutex); + + if ((ret = pthread_cancel(tid)) < 0) { + MODULE_ERROR("pthread_cancel is failed : %s, ret(%d)", strerror(errno), ret); + return -1; + } + + if (pthread_join(tid, (void**)&ptr) < 0) { + MODULE_ERROR("pthread_join is failed : %s", strerror(errno)); + return -1; + } + + stop = 0; + + tid = 0; + if (ptr == PTHREAD_CANCELED) { + MODULE_LOG("pthread canceled"); + } else { + MODULE_LOG("pthread already finished"); + } + + return 0; +} + +static void __clean_up(void *arg) +{ + BUFFER *pbuffer = (BUFFER*)arg; + int i; + + MODULE_LOG("clean up handler!!! : %d", tid); + + for (i = 0; i < pbuffer->channels; ++i) { + free(pbuffer->ppbuffer[i]); + pbuffer->ppbuffer[i] = NULL; + } + + free(pbuffer->ppbuffer); + pbuffer->ppbuffer = NULL; + + pbuffer->channels = 0; + pbuffer->length = 0; + + if(stop){ + __haptic_predefine_action(gbuffer.handle, STOP, NULL); + pthread_mutex_unlock(&mutex); + } +} + +static void* __play_cb(void *arg) +{ + BUFFER *pbuffer = (BUFFER*)arg; + int i, j, k; + unsigned char ch; + unsigned char prev = -1; + + MODULE_LOG("Start thread"); + + pthread_cleanup_push(__clean_up, arg); + + /* Copy buffer from source buffer */ + for (i = 0; i < pbuffer->iteration; i++) { + for (j = 0; j < pbuffer->length; ++j) { + for (k = 0; k < pbuffer->channels; ++k) { + pthread_mutex_lock(&mutex); + if (stop) { + pthread_exit((void*)0); + } + ch = pbuffer->ppbuffer[k][j]; + if (ch != prev) { + __haptic_predefine_action(pbuffer->handle, LEVEL, ch); + prev = ch; + } + pthread_mutex_unlock(&mutex); + usleep(BITPERMS * 1000); + } + } + } + + pthread_mutex_lock(&mutex); + __haptic_predefine_action(gbuffer.handle, STOP, NULL); + pthread_mutex_unlock(&mutex); + + pthread_cleanup_pop(1); + pthread_exit((void *)0); +} + +int GetHapticLevelMax(int *max) +{ + int status; + status = device_get_property(DEVICE_TYPE_VIBRATOR, PROP_VIBRATOR_LEVEL_MAX, max); + if (status < 0) { + MODULE_ERROR("device_get_property fail : %d", status); + return -1; + } + return 0; +} + +int InitializeBuffer(unsigned char *vibe_buffer, int max_bufsize) +{ + HapticFile *pfile; + + if (max_bufsize < sizeof(HapticFile)) { + MODULE_ERROR("buffer lacks a memory : size(%d) minimum size(%d)", + max_bufsize, sizeof(HapticFile)); + return -1; + } + + memset(vibe_buffer, 0, sizeof(char)*max_bufsize); + + pfile = (HapticFile*)vibe_buffer; + + pfile->chunkID = HEADER_ID; + pfile->chunkSize = sizeof(HapticFile); + pfile->fmt.chunkID = FMT_ID; + pfile->fmt.chunkSize = sizeof(FormatChunk); + pfile->fmt.wChannels = 1; + pfile->fmt.wBlockAlign = 1; // wChannels*1byte + pfile->fmt.dwMagnitude = 99; + pfile->fmt.dwDuration = 0; + pfile->data.chunkID = DATA_ID; + pfile->data.chunkSize = sizeof(DataChunk); + return 0; +} + +int InsertElement(unsigned char *vibe_buffer, int max_bufsize, HapticElement *element) +{ + HapticFile *pfile; + int databuf; + int needbuf; + int duration; + unsigned char level; + int i; + + pfile = (HapticFile*)vibe_buffer; + if (_check_valid_haptic_format(pfile) < 0) { + MODULE_ERROR("this buffer is not HapticFormat"); + return -1; + } + + duration = element->duration/BITPERMS; + level = (unsigned char)((unsigned int)element->level*MAX_LEVEL/100); + + databuf = max_bufsize - sizeof(HapticFile); + needbuf = (pfile->fmt.dwDuration + duration)*pfile->fmt.wBlockAlign; + MODULE_LOG("Need buffer size : %d", needbuf); + + if (databuf < needbuf) { + MODULE_ERROR("buffer lacks a memory : data buf(%d), need buf(%d)", databuf, needbuf); + return -1; + } + + for (i = pfile->fmt.dwDuration; i < pfile->fmt.dwDuration+duration; i++) { + pfile->data.pData[i] = level; + } + + pfile->chunkSize = sizeof(HapticFile)+needbuf ; + pfile->fmt.dwDuration = pfile->fmt.dwDuration+duration; + pfile->data.chunkSize = sizeof(DataChunk)+needbuf; + return 0; +} + +int GetBufferSize(const unsigned char *vibe_buffer, int *size) +{ + HapticFile *pfile; + + pfile = (HapticFile*)vibe_buffer; + if (_check_valid_haptic_format(pfile) < 0) { + MODULE_ERROR("this buffer is not HapticFormat"); + return -1; + } + + *size = pfile->chunkSize; + return 0; +} + +int GetBufferDuration(const unsigned char *vibe_buffer, int *duration) +{ + HapticFile *pfile; + + pfile = (HapticFile*)vibe_buffer; + if (_check_valid_haptic_format(pfile) < 0) { + MODULE_ERROR("this buffer is not HapticFormat"); + return -1; + } + + *duration = pfile->fmt.dwDuration; + return 0; +} + +int PlayOneshot(int handle, int duration, int level) +{ + char buf_pid[32]; + char buf_prop[32]; + char buf_handle[32]; + char buf_duration[32]; + char buf_level[32]; + + if (_cancel_thread() < 0) { + MODULE_ERROR("_cancel_thread fail"); + return -1; + } + + snprintf(buf_pid, sizeof(buf_pid), "%d", getpid()); + snprintf(buf_prop, sizeof(buf_prop), "%d", ONESHOT); + snprintf(buf_handle, sizeof(buf_handle), "%d", handle); + snprintf(buf_duration, sizeof(buf_duration), "%d", duration); + snprintf(buf_level, sizeof(buf_level), "%d", level); + + MODULE_LOG("pid : %s, prop : %s, handle : %s", buf_pid, buf_prop, buf_handle); + return __haptic_call_predef_action(PREDEF_HAPTIC, 5, buf_pid, buf_prop, + buf_handle, buf_duration, buf_level); +} + +int PlayBuffer(int handle, const unsigned char *vibe_buffer, int iteration, int level) +{ + HapticFile *pfile; + unsigned char **ppbuffer; + unsigned int channels, length, align; + unsigned char data; + int i, j; + + pfile = (HapticFile*)vibe_buffer; + if (_check_valid_haptic_format(pfile) < 0) { + MODULE_ERROR("this buffer is not HapticFormat"); + return -1; + } + + /* Temporary code + This code does not support handle and multi channel concept. + Only this code adds to test for playing file. */ + + if (_cancel_thread() < 0) { + MODULE_ERROR("_cancel_thread fail"); + return -1; + } + + channels = pfile->fmt.wChannels; + align = pfile->fmt.wBlockAlign; + length = (pfile->data.chunkSize-8)/align; + MODULE_LOG("channels : %d, length : %d, align : %d, level : %d", channels, length, align, level); + + /* Create buffer */ + ppbuffer = (unsigned char**)malloc(sizeof(unsigned char*)*channels); + for (i = 0; i < channels; ++i) { + ppbuffer[i] = (unsigned char*)malloc(sizeof(unsigned char)*length); + memset(ppbuffer[i], 0, sizeof(unsigned char)*length); + } + + /* Copy buffer from source buffer */ + for (i = 0; i < length; ++i) { + for (j = 0; j < channels; ++j) { + data = (unsigned char)(pfile->data.pData[i*align+j]); + ppbuffer[j][i] = (unsigned char)(data*level/0xFF); + MODULE_LOG("ppbuffer[%2d][%2d] : data(%x) -> (%x)", j, i, data, ppbuffer[j][i]); + } + } + + gbuffer.handle = handle; + gbuffer.ppbuffer = ppbuffer; + gbuffer.channels = channels; + gbuffer.length = length; + gbuffer.iteration = iteration; + + __haptic_predefine_action(gbuffer.handle, PLAY, NULL); + + /* Start thread */ + if (_create_thread(&gbuffer, __play_cb) < 0) { + MODULE_ERROR("_create_thread fail"); + return -1; + } + + return 0; +} + +int Stop(int handle) +{ + char buf_pid[32]; + char buf_prop[32]; + char buf_handle[32]; + + if (_cancel_thread() < 0) { + MODULE_ERROR("_cancel_thread fail"); + return -1; + } + + snprintf(buf_pid, sizeof(buf_pid), "%d", getpid()); + snprintf(buf_prop, sizeof(buf_prop), "%d", STOP); + snprintf(buf_handle, sizeof(buf_handle), "%d", handle); + + MODULE_LOG("pid : %s, prop : %s, handle : %s", buf_pid, buf_prop, buf_handle); + return __haptic_call_predef_action(PREDEF_HAPTIC, 3, buf_pid, buf_prop, buf_handle); +} + +int OpenDevice(int handle) +{ + char buf_pid[32]; + char buf_prop[32]; + char buf_handle[32]; + + snprintf(buf_pid, sizeof(buf_pid), "%d", getpid()); + snprintf(buf_prop, sizeof(buf_prop), "%d", OPEN); + snprintf(buf_handle, sizeof(buf_handle), "%d", handle); + + MODULE_LOG("pid : %s, prop : %s, handle : %s", buf_pid, buf_prop, buf_handle); + return __haptic_call_predef_action(PREDEF_HAPTIC, 3, buf_pid, buf_prop, buf_handle); +} + +int CloseDevice(int handle) +{ + char buf_pid[32]; + char buf_prop[32]; + char buf_handle[32]; + + if (_cancel_thread() < 0) { + MODULE_ERROR("_cancel_thread fail"); + return -1; + } + + snprintf(buf_pid, sizeof(buf_pid), "%d", getpid()); + snprintf(buf_prop, sizeof(buf_prop), "%d", CLOSE); + snprintf(buf_handle, sizeof(buf_handle), "%d", handle); + + MODULE_LOG("pid : %s, prop : %s, handle : %s", buf_pid, buf_prop, buf_handle); + return __haptic_call_predef_action(PREDEF_HAPTIC, 3, buf_pid, buf_prop, buf_handle); +} + +int GetState(int handle, int *state) +{ + if (gbuffer.handle == handle) { + *state = STATE_PLAY; + return 0; + } + + *state = STATE_STOP; + return 0; +} diff --git a/tizen/DEVICE/src/haptic.c b/tizen/DEVICE/src/haptic.c new file mode 100644 index 0000000..34d1ba3 --- /dev/null +++ b/tizen/DEVICE/src/haptic.c @@ -0,0 +1,225 @@ +/* + * haptic-module-tizen + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <assert.h> +#include <time.h> +#include <device-node.h> + +#include <haptic-plugin-intf.h> +#include "haptic_module_log.h" +#include "file.h" + +#ifndef EXTAPI +#define EXTAPI __attribute__ ((visibility("default"))) +#endif + +#define DEFAULT_EFFECT_HANDLE 0xFFFF +#define DEFAULT_MOTOR_COUNT 1 + +/* START of Static Function Section */ +static int convert_feedback_level(int feedback) +{ + static int max = -1; + int ret; + + if (max == -1) { + ret = device_get_property(DEVICE_TYPE_VIBRATOR, + PROP_VIBRATOR_LEVEL_MAX, &max); + if (ret < 0) + return ret; + } + + return feedback * max / HAPTIC_MODULE_FEEDBACK_MAX; +} + +static void *_create_handle(void) +{ + static int i = 0; + return ((getpid()<<16)|(time(NULL)+(i++))); +} +/* END of Static Function Section */ + +static int _get_device_count(int *count) +{ + if (count == NULL) + return HAPTIC_MODULE_INVALID_ARGUMENT; + + *count = DEFAULT_MOTOR_COUNT; + return HAPTIC_MODULE_ERROR_NONE; +} + +static int _open_device(int device_index, int *device_handle) +{ + int status; + + if (device_index < HAPTIC_MODULE_DEVICE_0 || device_index > HAPTIC_MODULE_DEVICE_ALL) + return HAPTIC_MODULE_INVALID_ARGUMENT; + + if (device_handle == NULL) + return HAPTIC_MODULE_INVALID_ARGUMENT; + + *device_handle = _create_handle(); + return HAPTIC_MODULE_ERROR_NONE; +} + +static int _close_device(int device_handle) +{ + int status; + + if (device_handle < 0) + return HAPTIC_MODULE_INVALID_ARGUMENT; + + return HAPTIC_MODULE_ERROR_NONE; +} + +static int _vibrate_monotone(int device_handle, int duration, int feedback, int priority, int *effect_handle) +{ + int level, ret; + + if (device_handle < 0) + return HAPTIC_MODULE_INVALID_ARGUMENT; + + if (duration < 0) + return HAPTIC_MODULE_INVALID_ARGUMENT; + + if (feedback < HAPTIC_MODULE_FEEDBACK_MIN || feedback > HAPTIC_MODULE_FEEDBACK_MAX) + return HAPTIC_MODULE_INVALID_ARGUMENT; + + if (priority < HAPTIC_MODULE_PRIORITY_MIN || priority > HAPTIC_MODULE_PRIORITY_HIGH) + return HAPTIC_MODULE_INVALID_ARGUMENT; + + if (effect_handle == NULL) + return HAPTIC_MODULE_INVALID_ARGUMENT; + + if (feedback == HAPTIC_MODULE_FEEDBACK_MIN) + return HAPTIC_MODULE_ERROR_NONE; + + level = convert_feedback_level(feedback); + if (level < 0) { + MODULE_ERROR("fail to convert haptic level : %d", level); + return HAPTIC_MODULE_OPERATION_FAILED; + } + + ret = device_set_property(DEVICE_TYPE_VIBRATOR, + PROP_VIBRATOR_LEVEL, level); + if (ret < 0) { + MODULE_ERROR("fail to set haptic level : %d", ret); + return HAPTIC_MODULE_OPERATION_FAILED; + } + + ret = device_set_property(DEVICE_TYPE_VIBRATOR, + PROP_VIBRATOR_ONESHOT, duration); + if (ret < 0) { + MODULE_ERROR("fail to set oneshot : %d", ret); + return HAPTIC_MODULE_OPERATION_FAILED; + } + + *effect_handle = DEFAULT_EFFECT_HANDLE; + return HAPTIC_MODULE_ERROR_NONE; +} + +static int _vibrate_buffer(int device_handle, const unsigned char *vibe_buffer, int iteration, int feedback, int priority, int *effect_handle) +{ + MODULE_ERROR("This device is not supported this function(%s)", __func__); + return HAPTIC_MODULE_NOT_SUPPORTED; +} + +static int _stop_device(int device_handle) +{ + int ret; + + if (device_handle < 0) + return HAPTIC_MODULE_INVALID_ARGUMENT; + + ret = device_set_property(DEVICE_TYPE_VIBRATOR, + PROP_VIBRATOR_ENABLE, 0); + if (ret < 0) { + MODULE_ERROR("fail to stop haptic device : %d", ret); + return HAPTIC_MODULE_OPERATION_FAILED; + } + + return HAPTIC_MODULE_ERROR_NONE; +} + +static int _get_device_state(int device_handle, int *state) +{ + int ret; + int cur_state; + + if (device_handle < 0) + return HAPTIC_MODULE_INVALID_ARGUMENT; + + if (state == NULL) + return HAPTIC_MODULE_INVALID_ARGUMENT; + + ret = device_get_property(DEVICE_TYPE_VIBRATOR, + PROP_VIBRATOR_ENABLE, &cur_state); + if (ret < 0) { + MODULE_ERROR("fail to get haptic enble value : %d", ret); + return HAPTIC_MODULE_OPERATION_FAILED; + } + + *state = (cur_state == 0 ? + HAPTIC_MODULE_STATE_STOP : HAPTIC_MODULE_STATE_PLAYING); + + return HAPTIC_MODULE_ERROR_NONE; +} + +static int _create_effect(unsigned char *vibe_buffer, int max_bufsize, haptic_module_effect_element *elem_arr, int max_elemcnt) +{ + MODULE_ERROR("This device is not supported this function(%s)", __func__); + return HAPTIC_MODULE_NOT_SUPPORTED; +} + +static int _get_buffer_duration(int device_handle, const unsigned char *vibe_buffer, int *buffer_duration) +{ + MODULE_ERROR("This device is not supported this function(%s)", __func__); + return HAPTIC_MODULE_NOT_SUPPORTED; +} + +static int _convert_binary(void) +{ + MODULE_ERROR("This device is not supported this function(%s)", __func__); + return HAPTIC_MODULE_NOT_SUPPORTED; +} + +static const struct haptic_plugin_ops haptic_plugin_tizen = { + .get_device_count = _get_device_count, + .open_device = _open_device, + .close_device = _close_device, + .vibrate_monotone = _vibrate_monotone, + .vibrate_buffer = _vibrate_buffer, + .stop_device = _stop_device, + .get_device_state = _get_device_state, + .create_effect = _create_effect, + .get_buffer_duration = _get_buffer_duration, + .convert_binary = _convert_binary, +}; + +EXTAPI +const struct haptic_plugin_ops *get_haptic_plugin_interface(void) +{ + return &haptic_plugin_tizen; +} diff --git a/tizen/DEVICE/src/sysnoti.c b/tizen/DEVICE/src/sysnoti.c new file mode 100644 index 0000000..56aaad8 --- /dev/null +++ b/tizen/DEVICE/src/sysnoti.c @@ -0,0 +1,163 @@ +/* + * haptic-module-tizen + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <stdarg.h> +#include <errno.h> + +#include "haptic_module_log.h" + +#define HAPTIC_RETRY_READ_COUNT 5 +#define HAPTIC_PARAM_CNT 3 +#define HAPTIC_MAXSTR 100 +#define HAPTIC_MAXARG 16 +#define PREDEF_HAPTIC "haptic" +#define SYSNOTI_SOCKET_PATH "/tmp/sn" + +enum sysnoti_cmd { + ADD_HAPTIC_ACTION, + CALL_HAPTIC_ACTION, +}; + +struct sysnoti_type { + int pid; + int cmd; + char *type; + char *path; + int argc; + char *argv[HAPTIC_MAXARG]; +}; + +static inline int __send_int(int fd, int val) +{ + return write(fd, &val, sizeof(int)); +} + +static inline int __send_str(int fd, char *str) +{ + int len; + int r; + + if (str == NULL) { + len = 0; + r = write(fd, &len, sizeof(int)); + } else { + len = strlen(str); + if (len > HAPTIC_MAXSTR) + len = HAPTIC_MAXSTR; + r = write(fd, &len, sizeof(int)); + r = write(fd, str, len); + } + + return r; +} + +static int __sysnoti_send(struct sysnoti_type *msg) +{ + int sockfd; + int len; + struct sockaddr_un addr; + int retry_cnt; + int ret; + int i; + int r; + + sockfd = socket(AF_UNIX, SOCK_STREAM, 0); + if (sockfd == -1) { + MODULE_ERROR("socket create failed"); + return -1; + } + + bzero(&addr, sizeof(addr)); + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, SYSNOTI_SOCKET_PATH, sizeof(addr.sun_path) - 1); + len = sizeof(addr); + + if (connect(sockfd, (struct sockaddr *)&addr, len) < 0) { + MODULE_ERROR("connect failed"); + close(sockfd); + return -1; + } + MODULE_LOG("connect : %x", sockfd); + + __send_int(sockfd, msg->pid); + __send_int(sockfd, msg->cmd); + __send_str(sockfd, msg->type); + __send_str(sockfd, msg->path); + __send_int(sockfd, msg->argc); + for (i = 0; i < msg->argc; i++) + __send_str(sockfd, msg->argv[i]); + + MODULE_LOG("read"); + retry_cnt = 0; + while ((r = read(sockfd, &ret, sizeof(int))) < 0) { + + if (errno != EINTR) { + MODULE_LOG("read fail : %s(%d)", strerror(errno), errno); + ret = -1; + break; + } + + if (retry_cnt == HAPTIC_RETRY_READ_COUNT) { + MODULE_ERROR("retry(%d) fail", retry_cnt); + ret = -1; + break; + } + + MODULE_ERROR("Re-read for error(EINTR)"); + ++retry_cnt; + } + + MODULE_LOG("close (ret : %d) : %x", ret, sockfd); + close(sockfd); + return ret; +} + +int __haptic_call_predef_action(const char *type, int num, ...) +{ + struct sysnoti_type msg; + char *args; + va_list argptr; + int i; + + if (type == NULL || num > HAPTIC_MAXARG) { + errno = EINVAL; + return -1; + } + + msg.pid = getpid(); + msg.cmd = CALL_HAPTIC_ACTION; + msg.type = (char *)type; + msg.path = NULL; + msg.argc = num; + + va_start(argptr, num); + for (i = 0; i < num; i++) { + args = va_arg(argptr, char *); + msg.argv[i] = args; + } + va_end(argptr); + + return __sysnoti_send(&msg); +} + |