static ssize_t ssp_sensorhub_write(struct file *file, const char __user *buf, size_t count, loff_t *pos) { struct ssp_sensorhub_data *hub_data = container_of(file->private_data, struct ssp_sensorhub_data, sensorhub_device); int ret = 0; char *buffer; if (unlikely(count < 2)) { sensorhub_err("library data length err(%d)", (int)count); return -EINVAL; } buffer = kzalloc(count * sizeof(char), GFP_KERNEL); if (unlikely(!buffer)) { sensorhub_err("allocate memory for kernel buffer err"); return -ENOMEM; } ret = copy_from_user(buffer, buf, count); if (unlikely(ret)) { sensorhub_err("memcpy for kernel buffer err"); ret = -EFAULT; goto exit; } ssp_sensorhub_log(__func__, buffer, count); if (unlikely(hub_data->ssp_data->bSspShutdown)) { sensorhub_err("stop sending library data(shutdown)"); ret = -EBUSY; goto exit; } if (buffer[0] == MSG2SSP_INST_LIB_DATA && count >= BIG_DATA_SIZE) ret = ssp_sensorhub_send_big_data(hub_data, buffer, count); else if (buffer[0] == MSG2SSP_INST_LIB_NOTI) ret = ssp_sensorhub_send_cmd(hub_data, buffer, count); else ret = ssp_sensorhub_send_instruction(hub_data, buffer, count); if (unlikely(ret <= 0)) { sensorhub_err("send library data err(%d)", ret); /* i2c transfer fail */ if (ret == ERROR) ret = -EIO; /* i2c transfer done but no ack from MCU */ else if (ret == FAIL) ret = -EAGAIN; goto exit; } ret = count; exit: kfree(buffer); return ret; }
static ssize_t ssp_sensorhub_read(struct file *file, char __user *buf, size_t count, loff_t *pos) { struct ssp_sensorhub_data *hub_data = container_of(file->private_data, struct ssp_sensorhub_data, sensorhub_device); struct sensorhub_event *event; int retries = MAX_DATA_COPY_TRY; int length = 0; int ret = 0; spin_lock_bh(&hub_data->sensorhub_lock); if (unlikely(kfifo_is_empty(&hub_data->fifo))) { sensorhub_info("no library data"); goto err; } /* first in first out */ ret = kfifo_out_peek(&hub_data->fifo, &event, sizeof(void *)); if (unlikely(!ret)) { sensorhub_err("kfifo out peek err(%d)", ret); ret = EIO; goto err; } length = event->library_length; while (retries--) { ret = copy_to_user(buf, event->library_data, event->library_length); if (likely(!ret)) break; } if (unlikely(ret)) { sensorhub_err("read library data err(%d)", ret); goto err; } ssp_sensorhub_log(__func__, event->library_data, event->library_length); /* remove first event from the list */ ret = kfifo_out(&hub_data->fifo, &event, sizeof(void *)); if (unlikely(ret != sizeof(void *))) { sensorhub_err("kfifo out err(%d)", ret); ret = EIO; goto err; } complete(&hub_data->read_done); spin_unlock_bh(&hub_data->sensorhub_lock); return length; err: spin_unlock_bh(&hub_data->sensorhub_lock); return ret ? -ret : 0; }
static long ssp_sensorhub_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct ssp_sensorhub_data *hub_data = container_of(file->private_data, struct ssp_sensorhub_data, sensorhub_device); void __user *argp = (void __user *)arg; int retries = MAX_DATA_COPY_TRY; int length = 0; int ret = 0; switch (cmd) { case IOCTL_READ_BIG_CONTEXT_DATA: mutex_lock(&hub_data->big_events_lock); length = hub_data->big_events.library_length; if (unlikely(!hub_data->big_events.library_data || !hub_data->big_events.library_length)) { sensorhub_info("no big library data"); mutex_unlock(&hub_data->big_events_lock); return 0; } while (retries--) { ret = copy_to_user(argp, hub_data->big_events.library_data, hub_data->big_events.library_length); if (likely(!ret)) break; } if (unlikely(ret)) { sensorhub_err("read big library data err(%d)", ret); mutex_unlock(&hub_data->big_events_lock); return -ret; } ssp_sensorhub_log(__func__, hub_data->big_events.library_data, hub_data->big_events.library_length); hub_data->is_big_event = false; kfree(hub_data->big_events.library_data); hub_data->big_events.library_data = NULL; hub_data->big_events.library_length = 0; complete(&hub_data->big_read_done); mutex_unlock(&hub_data->big_events_lock); break; default: sensorhub_err("ioctl cmd err(%d)", cmd); return -EINVAL; } return length; }
static int ssp_sensorhub_list(struct ssp_sensorhub_data *hub_data, char *dataframe, int length) { struct sensorhub_event *event; int ret = 0; if (unlikely(length <= 0 || length >= PAGE_SIZE)) { sensorhub_err("library length err(%d)", length); return -EINVAL; } ssp_sensorhub_log(__func__, dataframe, length); /* overwrite new event if list is full */ if (unlikely(kfifo_is_full(&hub_data->fifo))) { ret = kfifo_out(&hub_data->fifo, &event, sizeof(void *)); if (unlikely(ret != sizeof(void *))) { sensorhub_err("kfifo out err(%d)", ret); return -EIO; } sensorhub_info("overwrite event"); } /* allocate memory for new event */ kfree(hub_data->events[hub_data->event_number].library_data); hub_data->events[hub_data->event_number].library_data = kzalloc(length * sizeof(char), GFP_ATOMIC); if (unlikely(!hub_data->events[hub_data->event_number].library_data)) { sensorhub_err("allocate memory for library err"); return -ENOMEM; } /* copy new event into memory */ memcpy(hub_data->events[hub_data->event_number].library_data, dataframe, length); hub_data->events[hub_data->event_number].library_length = length; /* add new event into the end of list */ event = &hub_data->events[hub_data->event_number]; ret = kfifo_in(&hub_data->fifo, &event, sizeof(void *)); if (unlikely(ret != sizeof(void *))) { sensorhub_err("kfifo in err(%d)", ret); return -EIO; } /* not to overflow max list capacity */ if (hub_data->event_number++ >= LIST_SIZE - 1) hub_data->event_number = 0; return kfifo_len(&hub_data->fifo) / sizeof(void *); }
static ssize_t ssp_sensorhub_write(struct file *file, const char __user *buf, size_t count, loff_t *pos) { struct ssp_sensorhub_data *hub_data = container_of(file->private_data, struct ssp_sensorhub_data, sensorhub_device); int ret = 0; if (unlikely(count < 2)) { sensorhub_err("library data length err(%d)", count); return -EINVAL; } if (unlikely(hub_data->ssp_data->bSspShutdown)) { sensorhub_err("stop sending library data(shutdown)"); return -EBUSY; } ssp_sensorhub_log(__func__, buf, count); if (buf[0] == MSG2SSP_INST_LIB_DATA && count >= BIG_DATA_SIZE) ret = ssp_sensorhub_send_big_data(hub_data, buf, count); else if (buf[0] == MSG2SSP_INST_LIB_NOTI) ret = ssp_sensorhub_send_cmd(hub_data, buf, count); else ret = ssp_sensorhub_send_instruction(hub_data, buf, count); if (unlikely(ret <= 0)) { sensorhub_err("send library data err(%d)", ret); /* i2c transfer fail */ if (ret == ERROR) return -EIO; /* i2c transfer done but no ack from MCU */ else if (ret == FAIL) return -EAGAIN; else return ret; } return count; }