aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/sensorhub/ssp_sensorhub.c
diff options
context:
space:
mode:
authorSamsung OSRC <osrc@samsung.com>2013-01-20 14:10:20 -0500
committerCurtis Menard <curtis.menard@gmail.com>2013-01-20 14:10:20 -0500
commitfa4e880a9894605db70ef2ee88902d139eb48989 (patch)
tree6e95d6cd15cfb281599f74b966db7049d4fd5690 /drivers/sensorhub/ssp_sensorhub.c
parent10b2523bd76efada8f212f55b5b36889091b991a (diff)
downloadkernel_samsung_smdk4412-fa4e880a9894605db70ef2ee88902d139eb48989.zip
kernel_samsung_smdk4412-fa4e880a9894605db70ef2ee88902d139eb48989.tar.gz
kernel_samsung_smdk4412-fa4e880a9894605db70ef2ee88902d139eb48989.tar.bz2
Sensorhub: Update sensors and firmware
From Samsung SPH-L900 update source. Change-Id: Ib1dcf851ce5e723661169d7cb4ee8bc8ff647226 Signed-off-by: Curtis Menard <curtis.menard@gmail.com>
Diffstat (limited to 'drivers/sensorhub/ssp_sensorhub.c')
-rw-r--r--drivers/sensorhub/ssp_sensorhub.c402
1 files changed, 244 insertions, 158 deletions
diff --git a/drivers/sensorhub/ssp_sensorhub.c b/drivers/sensorhub/ssp_sensorhub.c
index b51d09a..bfa80d0 100644
--- a/drivers/sensorhub/ssp_sensorhub.c
+++ b/drivers/sensorhub/ssp_sensorhub.c
@@ -15,92 +15,103 @@
#include "ssp.h"
-/* sensorhub ioctl command */
-#define SENSORHUB_IOCTL_MAGIC 'S'
-#define IOCTL_READ_CONTEXT_DATA _IOR(SENSORHUB_IOCTL_MAGIC, 3, char *)
-
+static const struct fast_data {
+ char library_data[3];
+} fast_data_table[] = {
+ { { 1, 1, 7 } },
+};
static ssize_t ssp_sensorhub_write(struct file *file, const char __user *buf,
size_t count, loff_t *pos)
{
- struct ssp_data *data = container_of(file->private_data,
- struct ssp_data, sensorhub_device);
+ struct ssp_sensorhub_data *hub_data
+ = container_of(file->private_data,
+ struct ssp_sensorhub_data, sensorhub_device);
int ret = 0;
int i;
u8 instruction = buf[0];
- if (data == NULL) {
- pr_err("%s: invalid ssp_data structure", __func__);
- return -ENOMEM;
- }
-
if (count == 0) {
pr_err("%s: library command length err(%d)", __func__, count);
return -EINVAL;
}
for (i = 0; i < count; i++)
- pr_info("%s[%d] = %d", __func__, i, buf[i]);
+ pr_info("%s[%d] = 0x%x", __func__, i, buf[i]);
if (buf[0] == MSG2SSP_INST_LIBRARY_REMOVE)
instruction = REMOVE_LIBRARY;
else if (buf[0] == MSG2SSP_INST_LIBRARY_ADD)
instruction = ADD_LIBRARY;
- ret = send_instruction(data, instruction,
+ if (hub_data->ssp_data->bSspShutdown) {
+ pr_err("%s: stop sending command(no ssp_data)", __func__);
+ return -ENOMEM;
+ }
+
+ ret = send_instruction(hub_data->ssp_data, instruction,
(u8)buf[1], (u8 *)(buf+2), count-2);
- if (ret < 0)
+ if (ret <= 0)
pr_err("%s: send library command err(%d)", __func__, ret);
- return ret;
+ /* i2c transfer fail */
+ if (ret == ERROR)
+ return -EIO;
+ /* no ack from MCU */
+ else if (ret == FAIL)
+ return -EAGAIN;
+ /* success */
+ else
+ return count;
}
static long ssp_sensorhub_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
void __user *argp = (void __user *)arg;
- struct ssp_data *data = container_of(file->private_data,
- struct ssp_data, sensorhub_device);
+ struct ssp_sensorhub_data *hub_data
+ = container_of(file->private_data,
+ struct ssp_sensorhub_data, sensorhub_device);
int ret = 0;
int i = 0;
switch (cmd) {
case IOCTL_READ_CONTEXT_DATA:
/* for receive_msg */
- if (!data->large_library_length &&
- data->large_library_data == NULL) {
+ if (!hub_data->large_library_length &&
+ hub_data->large_library_data == NULL) {
ret = copy_to_user(argp,
- data->first_event->library_data,
- data->first_event->length);
+ hub_data->first_event->library_data,
+ hub_data->first_event->length);
if (ret < 0) {
pr_err("%s: send library data err(%d)",
__func__, ret);
- complete(&data->transfer_done);
+ complete(&hub_data->transfer_done);
goto exit;
}
- for (i = 0; i < data->first_event->length; i++) {
- pr_info("%s[%d] = %d", __func__, i,
- data->first_event->library_data[i]);
+ for (i = 0; i < hub_data->first_event->length; i++) {
+ pr_info("%s[%d] = 0x%x", __func__, i,
+ hub_data->first_event->library_data[i]);
}
- data->transfer_try = 0;
- complete(&data->transfer_done);
+ hub_data->transfer_try = 0;
+ complete(&hub_data->transfer_done);
/* for receive_large_msg */
} else {
pr_info("%s: receive_large_msg ioctl", __func__);
- ret = copy_to_user(argp, data->large_library_data,
- data->large_library_length);
+ ret = copy_to_user(argp, hub_data->large_library_data,
+ hub_data->large_library_length);
if (ret < 0) {
pr_err("%s: send large library data err(%d)",
__func__, ret);
goto exit;
}
- kfree(data->large_library_data);
- data->large_library_length = 0;
+ kfree(hub_data->large_library_data);
+ hub_data->large_library_length = 0;
}
break;
@@ -113,17 +124,19 @@ exit:
return ret;
}
-static const struct file_operations ssp_sensorhub_fops = {
+static struct file_operations ssp_sensorhub_fops = {
.owner = THIS_MODULE,
.open = nonseekable_open,
.write = ssp_sensorhub_write,
.unlocked_ioctl = ssp_sensorhub_ioctl,
};
-void ssp_report_sensorhub_notice(struct ssp_data *data, char notice)
+void ssp_report_sensorhub_notice(struct ssp_data *ssp_data, char notice)
{
- input_report_rel(data->sensorhub_input_dev, REL_RY, notice);
- input_sync(data->sensorhub_input_dev);
+ struct ssp_sensorhub_data *hub_data = ssp_data->hub_data;
+
+ input_report_rel(hub_data->sensorhub_input_dev, REL_RY, notice);
+ input_sync(hub_data->sensorhub_input_dev);
if (notice == MSG2SSP_AP_STATUS_WAKEUP)
pr_info("%s: wake up", __func__);
@@ -131,22 +144,43 @@ void ssp_report_sensorhub_notice(struct ssp_data *data, char notice)
pr_info("%s: sleep", __func__);
else if (notice == MSG2SSP_AP_STATUS_RESET)
pr_info("%s: reset", __func__);
+ else
+ pr_err("%s: invalid notice", __func__);
}
-static void ssp_report_sensorhub_length(struct ssp_data *data,
+static void ssp_report_sensorhub_length(struct ssp_sensorhub_data *hub_data,
int length)
{
- input_report_rel(data->sensorhub_input_dev, REL_RX, length);
- input_sync(data->sensorhub_input_dev);
+ input_report_rel(hub_data->sensorhub_input_dev, REL_RX, length);
+ input_sync(hub_data->sensorhub_input_dev);
pr_info("%s = %d", __func__, length);
}
-static int ssp_queue_sensorhub_events(struct ssp_data *data,
+static int ssp_sensorhub_is_fast_data(char *data, int start)
+{
+ int i, j;
+
+ for (i = 0; i < ARRAY_SIZE(fast_data_table); i++) {
+ for (j = 0; j < sizeof(fast_data_table[0]); j++) {
+ if (data[start + j] !=
+ fast_data_table[i].library_data[j])
+ break;
+ }
+ if (j == sizeof(fast_data_table[0]))
+ return i;
+ }
+
+ return -EINVAL;
+}
+
+static int ssp_queue_sensorhub_events(struct ssp_sensorhub_data *hub_data,
char *dataframe, int start, int end)
{
struct sensorhub_event *event;
int length = end - start;
- int entries = 0;
+ int event_number = hub_data->event_number;
+ int events = 0;
+ int ret = 0;
int i = 0;
if (length <= 0) {
@@ -155,52 +189,67 @@ static int ssp_queue_sensorhub_events(struct ssp_data *data,
}
/* how many events in the list? */
- list_for_each_entry(event, &data->events_head.list, list)
- entries++;
+ spin_lock_bh(&hub_data->sensorhub_lock);
+ list_for_each_entry(event, &hub_data->events_head.list, list)
+ events++;
+ spin_unlock_bh(&hub_data->sensorhub_lock);
/* drop event if queue is full */
- if (entries >= LIBRARY_MAX_NUM) {
+ if (events >= LIBRARY_MAX_NUM) {
pr_info("%s: queue is full", __func__);
- data->transfer_ready++;
- return -ENOMEM;
+ hub_data->transfer_ready++;
+ ret = ssp_sensorhub_is_fast_data(dataframe, start);
+ if (ret >= 0)
+ event_number = LIBRARY_MAX_NUM + ret;
+ else
+ return -ENOMEM;
}
/* allocate memory for new event */
- if (data->events[data->event_number].library_data != NULL)
- kfree(data->events[data->event_number].library_data);
+ if (hub_data->events[event_number].library_data != NULL)
+ kfree(hub_data->events[event_number].library_data);
- data->events[data->event_number].library_data
+ hub_data->events[event_number].library_data
= kzalloc(length * sizeof(char), GFP_KERNEL);
- if (data->events[data->event_number].library_data == NULL) {
+ if (hub_data->events[event_number].library_data == NULL) {
pr_err("%s: allocate memory for library data err", __func__);
return -ENOMEM;
}
/* copy sensorhub event into queue */
while (start < end) {
- data->events[data->event_number].library_data[i++]
+ hub_data->events[event_number].library_data[i++]
= dataframe[start++];
- pr_info("%s[%d] = %d", __func__, i-1,
- data->events[data->event_number].library_data[i-1]);
+ pr_info("%s[%d] = 0x%x", __func__, i-1,
+ hub_data->events[event_number].library_data[i-1]);
+ }
+ hub_data->events[event_number].length = length;
+
+ if (events <= LIBRARY_MAX_NUM) {
+ /* add new event at the end of queue */
+ spin_lock_bh(&hub_data->sensorhub_lock);
+ list_add_tail(&hub_data->events[event_number].list,
+ &hub_data->events_head.list);
+ if (events++ < LIBRARY_MAX_NUM)
+ hub_data->transfer_ready = 0;
+ spin_unlock_bh(&hub_data->sensorhub_lock);
+
+ /* do not exceed max queue number */
+ if (hub_data->event_number++ >= LIBRARY_MAX_NUM - 1)
+ hub_data->event_number = 0;
+ } else {
+ spin_lock_bh(&hub_data->sensorhub_lock);
+ list_replace(hub_data->events_head.list.prev,
+ &hub_data->events[event_number].list);
+ spin_unlock_bh(&hub_data->sensorhub_lock);
}
- data->events[data->event_number].length = length;
-
- /* add new sensorhug event at the end of queue */
- spin_lock_bh(&data->sensorhub_lock);
- list_add_tail(&data->events[data->event_number].list,
- &data->events_head.list);
- data->transfer_ready = 0;
- spin_unlock_bh(&data->sensorhub_lock);
- pr_info("%s: total %d entries", __func__, entries + 1);
-
- /* do not exceed max queue number */
- if (data->event_number++ >= LIBRARY_MAX_NUM - 1)
- data->event_number = 0;
- return length;
+ pr_info("%s: total %d events", __func__, events);
+ return events;
}
-static int ssp_receive_large_msg(struct ssp_data *data, u8 sub_cmd)
+static int ssp_receive_large_msg(struct ssp_sensorhub_data *hub_data,
+ u8 sub_cmd)
{
char send_data[2] = { 0, };
char receive_data[2] = { 0, };
@@ -216,7 +265,8 @@ static int ssp_receive_large_msg(struct ssp_data *data, u8 sub_cmd)
send_data[1] = sub_cmd;
/* receive_data(msg length) is two byte because msg is large */
- ret = ssp_i2c_read(data, send_data, 2, receive_data, 2, 0);
+ ret = ssp_i2c_read(hub_data->ssp_data, send_data, 2,
+ receive_data, 2, 0);
if (ret < 0) {
pr_err("%s: MSG2SSP_STT i2c err(%d)", __func__, ret);
return ret;
@@ -236,8 +286,8 @@ static int ssp_receive_large_msg(struct ssp_data *data, u8 sub_cmd)
/* receive the first msg data */
send_data[0] = MSG2SSP_SRM;
large_msg_data = kzalloc((length * sizeof(char)), GFP_KERNEL);
- ret = ssp_i2c_read(data, send_data, 1,
- large_msg_data, length, 0);
+ ret = ssp_i2c_read(hub_data->ssp_data, send_data, 1,
+ large_msg_data, length, 0);
if (ret < 0) {
pr_err("%s: receive 1st large msg err(%d)", __func__, ret);
kfree(large_msg_data);
@@ -245,21 +295,22 @@ static int ssp_receive_large_msg(struct ssp_data *data, u8 sub_cmd)
}
/* empty the previous large library data */
- if (data->large_library_length != 0)
- kfree(data->large_library_data);
+ if (hub_data->large_library_length != 0)
+ kfree(hub_data->large_library_data);
/* large_msg_data[0] of the first msg: total number of large msg
* large_msg_data[1-2] of the first msg: total msg length
* large_msg_data[3-N] of the first msg: the first msg data itself */
total_msg_number = large_msg_data[0];
- data->large_library_length = (int)((unsigned int)large_msg_data[1] << 8)
+ hub_data->large_library_length
+ = (int)((unsigned int)large_msg_data[1] << 8)
+ (unsigned int)large_msg_data[2];
- data->large_library_data
- = kzalloc((data->large_library_length * sizeof(char)),
+ hub_data->large_library_data
+ = kzalloc((hub_data->large_library_length * sizeof(char)),
GFP_KERNEL);
/* copy the fist msg data into large_library_data */
- memcpy(data->large_library_data, &large_msg_data[3],
+ memcpy(hub_data->large_library_data, &large_msg_data[3],
(length - 3) * sizeof(char));
kfree(large_msg_data);
@@ -272,7 +323,8 @@ static int ssp_receive_large_msg(struct ssp_data *data, u8 sub_cmd)
send_data[1] = 0x81 + msg_number;
/* receive_data(msg length) is two byte because msg is large */
- ret = ssp_i2c_read(data, send_data, 2, receive_data, 2, 0);
+ ret = ssp_i2c_read(hub_data->ssp_data, send_data, 2,
+ receive_data, 2, 0);
if (ret < 0) {
pr_err("%s: MSG2SSP_STT i2c err(%d)",
__func__, ret);
@@ -293,8 +345,8 @@ static int ssp_receive_large_msg(struct ssp_data *data, u8 sub_cmd)
/* receive Nth msg data */
send_data[0] = MSG2SSP_SRM;
- ret = ssp_i2c_read(data, send_data, 1,
- large_msg_data, length, 0);
+ ret = ssp_i2c_read(hub_data->ssp_data, send_data, 1,
+ large_msg_data, length, 0);
if (ret < 0) {
pr_err("%s: recieve %dth large msg err(%d)",
__func__, msg_number + 2, ret);
@@ -303,106 +355,124 @@ static int ssp_receive_large_msg(struct ssp_data *data, u8 sub_cmd)
}
/* copy(append) Nth msg data into large_library_data */
- memcpy(&data->large_library_data[data_locater],
+ memcpy(&hub_data->large_library_data[data_locater],
large_msg_data, length * sizeof(char));
data_locater += length;
kfree(large_msg_data);
}
- return data->large_library_length;
+ return hub_data->large_library_length;
}
static int ssp_senosrhub_thread_func(void *arg)
{
- struct ssp_data *data = (struct ssp_data *)arg;
+ struct ssp_sensorhub_data *hub_data = (struct ssp_sensorhub_data *)arg;
struct sensorhub_event *event;
- int entries = 0;
+ int events = 0;
int ret = 0;
while (!kthread_should_stop()) {
/* run if only event queue is not empty */
- wait_event_interruptible(data->sensorhub_waitqueue,
+ wait_event_interruptible(hub_data->sensorhub_waitqueue,
kthread_should_stop() ||
- !list_empty(&data->events_head.list));
+ !list_empty(&hub_data->events_head.list));
- /* quit while loop and do not report length anymore
+ /* exit thread if kthread should stop */
+ if (unlikely(kthread_should_stop())) {
+ pr_info("%s: kthread_stop()", __func__);
+ break;
+ }
+
+ /* exit thread
* if user does not get data with consecutive trials
*/
- if (data->transfer_try++ >= LIBRARY_MAX_TRY) {
+ if (unlikely(hub_data->transfer_try++ >= LIBRARY_MAX_TRY)) {
pr_err("%s: user does not get data", __func__);
break;
}
- /* first in first out */
- data->first_event = list_first_entry(&data->events_head.list,
- struct sensorhub_event, list);
- if (IS_ERR(data->first_event)) {
- pr_err("%s: no sensor event entry", __func__);
- continue;
- }
-
/* report sensorhub event to user */
- if (data->transfer_ready == 0) {
- ssp_report_sensorhub_length(data,
- data->first_event->length);
- wake_lock_timeout(&data->sensorhub_wake_lock, 5*HZ);
- data->transfer_ready++;
+ if (hub_data->transfer_ready == 0) {
+ /* first in first out */
+ hub_data->first_event
+ = list_first_entry(&hub_data->events_head.list,
+ struct sensorhub_event, list);
+ if (IS_ERR(hub_data->first_event)) {
+ pr_err("%s: first event err(%ld)", __func__,
+ PTR_ERR(hub_data->first_event));
+ continue;
+ }
+
+ /* report sensorhub event to user */
+ ssp_report_sensorhub_length(hub_data,
+ hub_data->first_event->length);
+ wake_lock_timeout(&hub_data->sensorhub_wake_lock, 5*HZ);
+ hub_data->transfer_ready++;
}
/* wait until user gets data */
- ret = wait_for_completion_timeout(&data->transfer_done, 3*HZ);
+ ret = wait_for_completion_timeout(&hub_data->transfer_done,
+ 3*HZ);
if (ret == 0) {
pr_err("%s: wait timed out", __func__);
- data->transfer_ready = 0;
+ hub_data->transfer_ready = 0;
} else if (ret < 0) {
pr_err("%s: wait_for_completion_timeout err(%d)",
__func__, ret);
}
- /* delete first entry only if transfer succeed */
- if (data->transfer_try == 0) {
- if (!list_empty(&data->events_head.list)) {
- spin_lock_bh(&data->sensorhub_lock);
- list_del(&data->first_event->list);
- data->transfer_ready = 0;
- spin_unlock_bh(&data->sensorhub_lock);
- entries = 0;
- list_for_each_entry(event,
- &data->events_head.list, list)
- entries++;
- pr_info("%s: %d entries remain",
- __func__, entries);
- }
+ /* remove first event only if transfer succeed */
+ if (hub_data->transfer_try == 0) {
+ /* remove first event */
+ spin_lock_bh(&hub_data->sensorhub_lock);
+ if (!list_empty(&hub_data->events_head.list))
+ list_del(&hub_data->first_event->list);
+ hub_data->transfer_ready = 0;
+
+ /* how many events in the list? */
+ events = 0;
+ list_for_each_entry(event,
+ &hub_data->events_head.list, list)
+ events++;
+ spin_unlock_bh(&hub_data->sensorhub_lock);
+
+ pr_info("%s: %d events remain", __func__, events);
continue;
}
/* throw away extra events */
- if (data->transfer_ready > EVENT_WAIT_COUNT)
- data->transfer_ready = 0;
+ if (hub_data->transfer_ready > EVENT_WAIT_COUNT)
+ hub_data->transfer_ready = 0;
usleep_range(10000, 10000);
}
+ pr_info("%s: exit", __func__);
return ret;
}
-int ssp_handle_sensorhub_data(struct ssp_data *data, char *dataframe,
+int ssp_handle_sensorhub_data(struct ssp_data *ssp_data, char *dataframe,
int start, int end)
{
+ struct ssp_sensorhub_data *hub_data = ssp_data->hub_data;
+
/* add new sensorhub event into queue */
- int ret = ssp_queue_sensorhub_events(data, dataframe, start, end);
- wake_up(&data->sensorhub_waitqueue);
+ int ret = ssp_queue_sensorhub_events(hub_data, dataframe, start, end);
+ wake_up(&hub_data->sensorhub_waitqueue);
return ret;
}
-int ssp_handle_sensorhub_large_data(struct ssp_data *data, u8 sub_cmd)
+int ssp_handle_sensorhub_large_data(struct ssp_data *ssp_data, u8 sub_cmd)
{
+ struct ssp_sensorhub_data *hub_data = ssp_data->hub_data;
+
/* receive large size of library data */
- int ret = ssp_receive_large_msg(data, sub_cmd);
+ int ret = ssp_receive_large_msg(hub_data, sub_cmd);
if (ret >= 0) {
- ssp_report_sensorhub_length(data, data->large_library_length);
- wake_lock_timeout(&data->sensorhub_wake_lock, 3*HZ);
+ ssp_report_sensorhub_length(hub_data,
+ hub_data->large_library_length);
+ wake_lock_timeout(&hub_data->sensorhub_wake_lock, 3*HZ);
} else {
pr_err("%s: ssp_receive_large_msg err(%d)", __func__, ret);
}
@@ -410,77 +480,93 @@ int ssp_handle_sensorhub_large_data(struct ssp_data *data, u8 sub_cmd)
return ret;
}
-int ssp_initialize_sensorhub(struct ssp_data *data)
+int ssp_initialize_sensorhub(struct ssp_data *ssp_data)
{
+ struct ssp_sensorhub_data *hub_data;
int ret;
+ hub_data = kzalloc(sizeof(*hub_data), GFP_KERNEL);
+ if (!hub_data) {
+ pr_err("%s: failed to allocate memory for sensorhub data",
+ __func__);
+ return -ENOMEM;
+ }
+ hub_data->ssp_data = ssp_data;
+ ssp_data->hub_data = hub_data;
+
/* allocate sensorhub input devices */
- data->sensorhub_input_dev = input_allocate_device();
- if (!data->sensorhub_input_dev) {
+ hub_data->sensorhub_input_dev = input_allocate_device();
+ if (!hub_data->sensorhub_input_dev) {
pr_err("%s: allocate sensorhub input devices err", __func__);
ret = -ENOMEM;
goto err_input_allocate_device_sensorhub;
}
- wake_lock_init(&data->sensorhub_wake_lock, WAKE_LOCK_SUSPEND,
+ wake_lock_init(&hub_data->sensorhub_wake_lock, WAKE_LOCK_SUSPEND,
"sensorhub_wake_lock");
- INIT_LIST_HEAD(&data->events_head.list);
- init_waitqueue_head(&data->sensorhub_waitqueue);
- init_completion(&data->transfer_done);
- spin_lock_init(&data->sensorhub_lock);
+ INIT_LIST_HEAD(&hub_data->events_head.list);
+ init_waitqueue_head(&hub_data->sensorhub_waitqueue);
+ init_completion(&hub_data->transfer_done);
+ spin_lock_init(&hub_data->sensorhub_lock);
- ret = input_register_device(data->sensorhub_input_dev);
+ ret = input_register_device(hub_data->sensorhub_input_dev);
if (ret < 0) {
pr_err("%s: could not register sensorhub input device(%d)",
__func__, ret);
- input_free_device(data->sensorhub_input_dev);
+ input_free_device(hub_data->sensorhub_input_dev);
goto err_input_register_device_sensorhub;
}
- data->sensorhub_input_dev->name = "ssp_context";
- input_set_drvdata(data->sensorhub_input_dev, data);
- input_set_capability(data->sensorhub_input_dev, EV_REL, REL_RX);
- input_set_capability(data->sensorhub_input_dev, EV_REL, REL_RY);
+ hub_data->sensorhub_input_dev->name = "ssp_context";
+ input_set_drvdata(hub_data->sensorhub_input_dev, hub_data);
+ input_set_capability(hub_data->sensorhub_input_dev, EV_REL, REL_RX);
+ input_set_capability(hub_data->sensorhub_input_dev, EV_REL, REL_RY);
/* create sensorhub device node */
- data->sensorhub_device.minor = MISC_DYNAMIC_MINOR;
- data->sensorhub_device.name = "ssp_sensorhub";
- data->sensorhub_device.fops = &ssp_sensorhub_fops;
+ hub_data->sensorhub_device.minor = MISC_DYNAMIC_MINOR;
+ hub_data->sensorhub_device.name = "ssp_sensorhub";
+ hub_data->sensorhub_device.fops = &ssp_sensorhub_fops;
- ret = misc_register(&data->sensorhub_device);
+ ret = misc_register(&hub_data->sensorhub_device);
if (ret < 0) {
pr_err("%s: misc_register() failed", __func__);
goto err_misc_register;
}
- data->sensorhub_task = kthread_run(ssp_senosrhub_thread_func,
- (void *)data, "ssp_sensorhub_task");
- if (IS_ERR(data->sensorhub_task)) {
- ret = PTR_ERR(data->sensorhub_task);
+ hub_data->sensorhub_task = kthread_run(ssp_senosrhub_thread_func,
+ (void *)hub_data, "ssp_sensorhub_task");
+ if (IS_ERR(hub_data->sensorhub_task)) {
+ ret = PTR_ERR(hub_data->sensorhub_task);
goto err_kthread_create;
}
return 0;
err_kthread_create:
- misc_deregister(&data->sensorhub_device);
+ misc_deregister(&hub_data->sensorhub_device);
err_misc_register:
- input_unregister_device(data->sensorhub_input_dev);
+ input_unregister_device(hub_data->sensorhub_input_dev);
err_input_register_device_sensorhub:
- complete_all(&data->transfer_done);
- wake_lock_destroy(&data->sensorhub_wake_lock);
+ complete_all(&hub_data->transfer_done);
+ wake_lock_destroy(&hub_data->sensorhub_wake_lock);
err_input_allocate_device_sensorhub:
+ kfree(hub_data);
return ret;
}
-void ssp_remove_sensorhub(struct ssp_data *data)
+void ssp_remove_sensorhub(struct ssp_data *ssp_data)
{
- complete_all(&data->transfer_done);
- if (data->sensorhub_task)
- kthread_stop(data->sensorhub_task);
- misc_deregister(&data->sensorhub_device);
- input_unregister_device(data->sensorhub_input_dev);
- wake_lock_destroy(&data->sensorhub_wake_lock);
+ struct ssp_sensorhub_data *hub_data = ssp_data->hub_data;
+
+ ssp_sensorhub_fops.write = NULL;
+ ssp_sensorhub_fops.unlocked_ioctl = NULL;
+ misc_deregister(&hub_data->sensorhub_device);
+ input_unregister_device(hub_data->sensorhub_input_dev);
+ wake_lock_destroy(&hub_data->sensorhub_wake_lock);
+ complete_all(&hub_data->transfer_done);
+ if (hub_data->sensorhub_task)
+ kthread_stop(hub_data->sensorhub_task);
+ kfree(hub_data);
}
MODULE_DESCRIPTION("Samsung Sensor Platform(SSP) sensorhub driver");