diff --git a/drivers/hid/hid-rkvr.c b/drivers/hid/hid-rkvr.c deleted file mode 100644 index e38d38620f10..000000000000 --- a/drivers/hid/hid-rkvr.c +++ /dev/null @@ -1,1478 +0,0 @@ -/* - * Rockchip VR driver for Linux - * - * Copyright (C) ROCKCHIP, Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - */ - -/* - * Driver for Rockchip VR devices. Based on hidraw driver. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "hid-rkvr.h" -#include "hid-ids.h" - -#define USB_TRACKER_INTERFACE_PROTOCOL 0 -/* define rkvr interface number */ -#define RKVR_INTERFACE_USB_AUDIO_ID 1 -#define RKVR_INTERFACE_USB_SENSOR_ID 2 -#define RKVR_INTERFACE_USB_AUDIO_KEY_ID 1 -/* number of reports to buffer */ -#define RKVR_HIDRAW_BUFFER_SIZE 64 -#define RKVR_HIDRAW_MAX_DEVICES 8 -#define RKVR_FIRST_MINOR 0 -#define RK_HID_GEAR_TOUCH - -static struct class *rkvr_class; - -static struct hidraw *rkvr_hidraw_table[RKVR_HIDRAW_MAX_DEVICES]; - -static struct hid_capability -{ - __u8 suspend_notify; -} rkvr_hid_capability[RKVR_HIDRAW_MAX_DEVICES]; -static DEFINE_MUTEX(minors_lock); - -struct keymap_t { - __u16 key_menu_up:1; - __u16 key_menu_down:1; - __u16 key_home_up:1; - __u16 key_home_down:1; - __u16 key_power_up:1; - __u16 key_power_down:1; - __u16 key_volup_up:1; - __u16 key_volup_down:1; - __u16 key_voldn_up:1; - __u16 key_voldn_down:1; - __u16 key_esc_up:1; - __u16 key_esc_down:1; - /*for touch panel **/ - __u16 key_up_pressed:1; - __u16 key_up_released:1; - __u16 key_down_pressed:1; - __u16 key_down_released:1; - __u16 key_left_pressed:1; - __u16 key_left_released:1; - __u16 key_right_pressed:1; - __u16 key_right_released:1; - __u16 key_enter_pressed:1; - __u16 key_enter_released:1; - __u16 key_pressed:1; - __u16 psensor_on:1; - __u16 psensor_off:1; -} __packed; - -union rkvr_data_t { - struct rkvr_data { - __u8 buf_head[6]; - __u8 buf_sensortemperature[2]; - __u8 buf_sensor[40]; - __u8 buf_reserve[10]; - struct keymap_t key_map; - } rkvr_data; - __u8 buf[62]; -} __packed; - -static int rkvr_major; -static struct cdev rkvr_cdev; -static unsigned int count_array[15] = {0,}; -static unsigned long old_jiffy_array[15] = {0,}; -static int rkvr_index; -static int opens; - -struct sensor_hid_data { - void *priv; - int (*send_event)(char *raw_data, size_t raw_len, void *priv); -} sensorData; - -static DEFINE_MUTEX(device_list_lock); -static struct list_head rkvr_hid_hw_device_list = { - .next = &rkvr_hid_hw_device_list, - .prev = &rkvr_hid_hw_device_list -}; - -static struct rkvr_iio_hw_device *inv_hid_alloc(const char *name) -{ - struct rkvr_iio_hw_device *p; - const char *s; - - if (!name) - return 0; - s = kstrdup_const(name, GFP_KERNEL); - if (!s) - goto error; - p = kzalloc(sizeof(*p), GFP_KERNEL); - if (!p) - goto error; - p->name = s; - return p; -error: - pr_err("%s error!\n", __func__); - if (s) - kfree_const(s); - return 0; -} - -static void inv_hid_free(struct rkvr_iio_hw_device *hw_device) -{ - kfree_const(hw_device->name); - kfree(hw_device); -} - -static int inv_hid_register_devcie(struct rkvr_iio_hw_device *hw_device) -{ - - mutex_lock(&device_list_lock); - if (hw_device->name && (!list_empty(&rkvr_hid_hw_device_list))) { - struct rkvr_iio_hw_device *p; - - list_for_each_entry(p, &rkvr_hid_hw_device_list, l) { - if (!strcmp(hw_device->name, p->name)) { - pr_err("%s already exist ,abort\n", hw_device->name); - mutex_unlock(&device_list_lock); - return -1; - } - } - } - list_add_tail(&hw_device->l, &rkvr_hid_hw_device_list); - mutex_unlock(&device_list_lock); - return 0; -} - -static void inv_hid_unregister_and_destroy_devcie_by_name(const char *name) -{ - struct rkvr_iio_hw_device *p = NULL; - - mutex_lock(&device_list_lock); - list_for_each_entry(p, &rkvr_hid_hw_device_list, l) { - if (!strcmp(name, p->name)) { - list_del(&p->l); - break; - } - } - if (p) { - pr_info("find dev with name %s,free now\n", name); - inv_hid_free(p); - } - mutex_unlock(&device_list_lock); -} - -static ssize_t rkvr_hidraw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) -{ - struct hidraw_list *list = file->private_data; - int ret = 0, len; - DECLARE_WAITQUEUE(wait, current); - - mutex_lock(&list->read_mutex); - while (ret == 0) { - if (list->head == list->tail) { - add_wait_queue(&list->hidraw->wait, &wait); - set_current_state(TASK_INTERRUPTIBLE); - - while (list->head == list->tail) { - if (signal_pending(current)) { - ret = -ERESTARTSYS; - break; - } - if (!list->hidraw->exist) { - ret = -EIO; - break; - } - if (file->f_flags & O_NONBLOCK) { - ret = -EAGAIN; - break; - } - - /* allow O_NONBLOCK to work well from other threads */ - mutex_unlock(&list->read_mutex); - schedule(); - mutex_lock(&list->read_mutex); - set_current_state(TASK_INTERRUPTIBLE); - } - - set_current_state(TASK_RUNNING); - remove_wait_queue(&list->hidraw->wait, &wait); - } - - if (ret) - goto out; - - len = list->buffer[list->tail].len > count ? - count : list->buffer[list->tail].len; - - if (list->buffer[list->tail].value) { - if (copy_to_user(buffer, list->buffer[list->tail].value, len)) { - ret = -EFAULT; - goto out; - } - ret = len; - if (opens > 0 && rkvr_index < 15) { - if (++count_array[rkvr_index] >= 1000) { - unsigned long cur_jiffy = jiffies; - - hid_dbg(list->hidraw->hid, "rkvr: %d Hz, read(%d) (%d:%s)\n", (int)(1000 * HZ / (cur_jiffy - old_jiffy_array[rkvr_index])), rkvr_index, current->pid, current->comm); - count_array[rkvr_index] = 0; - old_jiffy_array[rkvr_index] = cur_jiffy; - } - if (++rkvr_index >= opens) - rkvr_index = 0; - } else { - rkvr_index = 0; - } - } - - kfree(list->buffer[list->tail].value); - list->buffer[list->tail].value = NULL; - list->tail = (list->tail + 1) & (RKVR_HIDRAW_BUFFER_SIZE - 1); - } -out: - mutex_unlock(&list->read_mutex); - return ret; -} - -/* The first byte is expected to be a report number. - * This function is to be called with the minors_lock mutex held - */ -static ssize_t rkvr_hidraw_send_report(struct file *file, const char __user *buffer, size_t count, unsigned char report_type) -{ - unsigned int minor = iminor(file_inode(file)); - struct hid_device *dev; - __u8 *buf; - int ret = 0; - - if (!rkvr_hidraw_table[minor] || !rkvr_hidraw_table[minor]->exist) { - ret = -ENODEV; - goto out; - } - - dev = rkvr_hidraw_table[minor]->hid; - - if (count > HID_MAX_BUFFER_SIZE) { - hid_warn(dev, "rkvr - pid %d passed too large report\n", - task_pid_nr(current)); - ret = -EINVAL; - goto out; - } - - if (count < 2) { - hid_warn(dev, "rkvr - pid %d passed too short report\n", - task_pid_nr(current)); - ret = -EINVAL; - goto out; - } - - buf = kmalloc(count * sizeof(__u8), GFP_KERNEL); - if (!buf) { - ret = -ENOMEM; - goto out; - } - - if (copy_from_user(buf, buffer, count)) { - ret = -EFAULT; - goto out_free; - } - - if ((report_type == HID_OUTPUT_REPORT) && - !(dev->quirks & HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP)) { - ret = hid_hw_output_report(dev, buf, count); - /* - * compatibility with old implementation of USB-HID and I2C-HID: - * if the device does not support receiving output reports, - * on an interrupt endpoint, fallback to SET_REPORT HID command. - */ - if (ret != -ENOSYS) - goto out_free; - } - - ret = hid_hw_raw_request(dev, buf[0], buf, count, report_type, - HID_REQ_SET_REPORT); - -out_free: - kfree(buf); -out: - return ret; -} - -/* the first byte is expected to be a report number */ -static ssize_t rkvr_hidraw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) -{ - ssize_t ret; - - mutex_lock(&minors_lock); - ret = rkvr_hidraw_send_report(file, buffer, count, HID_OUTPUT_REPORT); - mutex_unlock(&minors_lock); - return ret; -} - -/* This function performs a Get_Report transfer over the control endpoint - * per section 7.2.1 of the HID specification, version 1.1. The first byte - * of buffer is the report number to request, or 0x0 if the defice does not - * use numbered reports. The report_type parameter can be HID_FEATURE_REPORT - * or HID_INPUT_REPORT. This function is to be called with the minors_lock - * mutex held. - */ -static ssize_t rkvr_hidraw_get_report(struct file *file, char __user *buffer, size_t count, unsigned char report_type) -{ - unsigned int minor = iminor(file_inode(file)); - struct hid_device *dev; - __u8 *buf; - int ret = 0, len; - unsigned char report_number; - - dev = rkvr_hidraw_table[minor]->hid; - - if (!dev->ll_driver->raw_request) { - ret = -ENODEV; - goto out; - } - - if (count > HID_MAX_BUFFER_SIZE) { - hid_warn(dev, "rkvr - hidraw: pid %d passed too large report\n", - task_pid_nr(current)); - ret = -EINVAL; - goto out; - } - - if (count < 2) { - hid_warn(dev, "rkvr - hidraw: pid %d passed too short report\n", - task_pid_nr(current)); - ret = -EINVAL; - goto out; - } - - buf = kmalloc(count * sizeof(__u8), GFP_KERNEL); - if (!buf) { - ret = -ENOMEM; - goto out; - } - - /* - * Read the first byte from the user. This is the report number, - * which is passed to hid_hw_raw_request(). - */ - if (copy_from_user(&report_number, buffer, 1)) { - ret = -EFAULT; - goto out_free; - } - - ret = hid_hw_raw_request(dev, report_number, buf, count, report_type, - HID_REQ_GET_REPORT); - if (ret < 0) - goto out_free; - len = (ret < count) ? ret : count; - - if (copy_to_user(buffer, buf, len)) { - ret = -EFAULT; - goto out_free; - } - - ret = len; - -out_free: - kfree(buf); -out: - return ret; -} - -static unsigned int rkvr_hidraw_poll(struct file *file, poll_table *wait) -{ - struct hidraw_list *list = file->private_data; - - poll_wait(file, &list->hidraw->wait, wait); - if (list->head != list->tail) - return POLLIN | POLLRDNORM; - if (!list->hidraw->exist) - return POLLERR | POLLHUP; - - return 0; -} - -static int rkvr_hidraw_open(struct inode *inode, struct file *file) -{ - unsigned int minor = iminor(inode); - struct hidraw *dev; - struct hidraw_list *list; - unsigned long flags; - int err = 0; - - list = kzalloc(sizeof(*list), GFP_KERNEL); - if (!list) { - err = -ENOMEM; - goto out; - } - - mutex_lock(&minors_lock); - if (!rkvr_hidraw_table[minor] || !rkvr_hidraw_table[minor]->exist) { - err = -ENODEV; - goto out_unlock; - } - - dev = rkvr_hidraw_table[minor]; - if (!dev->open++) { - err = hid_hw_power(dev->hid, PM_HINT_FULLON); - if (err < 0) { - dev->open--; - goto out_unlock; - } - - err = hid_hw_open(dev->hid); - - if (err < 0) { - hid_hw_power(dev->hid, PM_HINT_NORMAL); - dev->open--; - goto out_unlock; - } - } - - list->hidraw = rkvr_hidraw_table[minor]; - mutex_init(&list->read_mutex); - spin_lock_irqsave(&rkvr_hidraw_table[minor]->list_lock, flags); - list_add_tail(&list->node, &rkvr_hidraw_table[minor]->list); - spin_unlock_irqrestore(&rkvr_hidraw_table[minor]->list_lock, flags); - file->private_data = list; - - opens = dev->open; - -out_unlock: - mutex_unlock(&minors_lock); -out: - if (err < 0) - kfree(list); - - return err; -} - -static int rkvr_hidraw_fasync(int fd, struct file *file, int on) -{ - struct hidraw_list *list = file->private_data; - - return fasync_helper(fd, file, on, &list->fasync); -} - -static void rkvr_drop_ref(struct hidraw *hidraw, int exists_bit) -{ - if (exists_bit) { /*hw removed**/ - hidraw->exist = 0; - if (hidraw->open) { - hid_hw_close(hidraw->hid); - wake_up_interruptible(&hidraw->wait); - } - } else { - --hidraw->open; - } - - if (!hidraw->open) { - if (!hidraw->exist) { /*no opened && no hardware,delete all**/ - rkvr_hidraw_table[hidraw->minor] = NULL; - kfree(hidraw); - } else { - /* close device for last reader */ - hid_hw_power(hidraw->hid, PM_HINT_NORMAL); - hid_hw_close(hidraw->hid); - } - } -} - -static int rkvr_hidraw_release(struct inode *inode, struct file *file) -{ - unsigned int minor = iminor(inode); - struct hidraw_list *list = file->private_data; - unsigned long flags; - - mutex_lock(&minors_lock); - - spin_lock_irqsave(&rkvr_hidraw_table[minor]->list_lock, flags); - list_del(&list->node); - spin_unlock_irqrestore(&rkvr_hidraw_table[minor]->list_lock, flags); - - kfree(list); - rkvr_drop_ref(rkvr_hidraw_table[minor], 0); - - mutex_unlock(&minors_lock); - - return 0; -} - -static void rkvr_send_key_event(struct input_dev *input, int key_value, int state) -{ - if (!input) { - return; - } - if (state) { - input_report_key(input, key_value, 1); - input_sync(input); - } else { - input_report_key(input, key_value, 0); - input_sync(input); - } -} - -static int rkvr_keys_event(struct hid_device *hdev, void *data, unsigned long len) -{ - struct input_dev *input = hdev->hiddev; - union rkvr_data_t *rkvr_data = (union rkvr_data_t *)data; - - if (rkvr_data->rkvr_data.key_map.key_menu_up) - rkvr_send_key_event(input, KEY_MENU, 0); - else if (rkvr_data->rkvr_data.key_map.key_menu_down) - rkvr_send_key_event(input, KEY_MENU, 1); - else if (rkvr_data->rkvr_data.key_map.key_home_up) - rkvr_send_key_event(input, KEY_HOME, 0); - else if (rkvr_data->rkvr_data.key_map.key_home_down) - rkvr_send_key_event(input, KEY_HOME, 1); - else if (rkvr_data->rkvr_data.key_map.key_power_up) - rkvr_send_key_event(input, KEY_POWER, 0); - else if (rkvr_data->rkvr_data.key_map.key_power_down) - rkvr_send_key_event(input, KEY_POWER, 1); - else if (rkvr_data->rkvr_data.key_map.key_volup_up) - rkvr_send_key_event(input, KEY_VOLUMEUP, 0); - else if (rkvr_data->rkvr_data.key_map.key_volup_down) - rkvr_send_key_event(input, KEY_VOLUMEUP, 1); - else if (rkvr_data->rkvr_data.key_map.key_voldn_up) - rkvr_send_key_event(input, KEY_VOLUMEDOWN, 0); - else if (rkvr_data->rkvr_data.key_map.key_voldn_down) - rkvr_send_key_event(input, KEY_VOLUMEDOWN, 1); - else if (rkvr_data->rkvr_data.key_map.key_esc_up) - rkvr_send_key_event(input, KEY_ESC, 0); - else if (rkvr_data->rkvr_data.key_map.key_esc_down) - rkvr_send_key_event(input, KEY_ESC, 1); - else if (rkvr_data->rkvr_data.key_map.key_up_pressed) { - rkvr_send_key_event(input, KEY_UP, 1); - rkvr_send_key_event(input, KEY_UP, 0); - } else if (rkvr_data->rkvr_data.key_map.key_down_pressed) { - rkvr_send_key_event(input, KEY_DOWN, 1); - rkvr_send_key_event(input, KEY_DOWN, 0); - } else if (rkvr_data->rkvr_data.key_map.key_left_pressed) { - rkvr_send_key_event(input, KEY_LEFT, 1); - rkvr_send_key_event(input, KEY_LEFT, 0); - } else if (rkvr_data->rkvr_data.key_map.key_right_pressed) { - rkvr_send_key_event(input, KEY_RIGHT, 1); - rkvr_send_key_event(input, KEY_RIGHT, 0); - } else if (rkvr_data->rkvr_data.key_map.key_enter_pressed) { - input_event(input, EV_MSC, MSC_SCAN, 0x90001); - rkvr_send_key_event(input, BTN_MOUSE, 1); - input_event(input, EV_MSC, MSC_SCAN, 0x90001); - rkvr_send_key_event(input, BTN_MOUSE, 0); - } - - if (rkvr_data->rkvr_data.key_map.psensor_on) { - hid_info(hdev, "event: psensor_on\n"); - rkvr_send_key_event(input, KEY_POWER, 1); - rkvr_send_key_event(input, KEY_POWER, 0); - } else if (rkvr_data->rkvr_data.key_map.psensor_off) { - hid_info(hdev, "event: psensor_off\n"); - rkvr_send_key_event(input, KEY_POWER, 1); - rkvr_send_key_event(input, KEY_POWER, 0); - } - - return 0; -} - -static int rkvr_report_event(struct hid_device *hid, u8 *data, int len) -{ - struct hidraw *dev = hid->hidraw; - struct hidraw_list *list; - int ret = 0; - unsigned long flags; - union rkvr_data_t *rkvr_data = (union rkvr_data_t *)data; - struct sensor_hid_data *pdata = hid_get_drvdata(hid); - - spin_lock_irqsave(&dev->list_lock, flags); - if (hid->hiddev) { - rkvr_keys_event(hid, data, len); - } - if (pdata && pdata->priv && pdata->send_event) { - pdata->send_event(rkvr_data->buf, len, pdata->priv); - spin_unlock_irqrestore(&dev->list_lock, flags); - } else { - list_for_each_entry(list, &dev->list, node) { - int new_head = (list->head + 1) & (RKVR_HIDRAW_BUFFER_SIZE - 1); - - if (new_head == list->tail) - continue; - - list->buffer[list->head].value = kmemdup(data, len, GFP_ATOMIC); - if (!list->buffer[list->head].value) { - ret = -ENOMEM; - break; - } - - list->buffer[list->head].len = len; - list->head = new_head; - kill_fasync(&list->fasync, SIGIO, POLL_IN); - } - spin_unlock_irqrestore(&dev->list_lock, flags); - wake_up_interruptible(&dev->wait); - } - return ret; -} - -/****************************************** - *-------------------- - *| ID | BUF ..... | - *-------------------- - * - ******************************************/ -static int rkvr_send_report(struct device *dev, unsigned char *data, size_t len) -{ - struct hid_device *hid = container_of(dev, struct hid_device, dev); - unsigned char reportnum = HID_REPORT_ID_RKVR; - unsigned char rtype = HID_OUTPUT_REPORT; - int ret = -EINVAL; - - ret = hid_hw_raw_request(hid, reportnum, (unsigned char *)data, len, rtype, HID_REQ_SET_REPORT); - if (ret != len) { - hid_err(hid, "rkvr_send_report fail\n"); - ret = -EIO; - goto fail; - } - hid_info(hid, "rkvr_send_report ok\n"); - ret = 0; -fail: - return ret; -} - -static int rkvr_recv_report(struct device *dev, u8 type, u8 *data, int len) -{ - struct hid_device *hid = container_of(dev, struct hid_device, dev); - unsigned char report_number = type; - unsigned char report_type = HID_MISC_REPORT; - char buf[1 + sizeof(*data) * len]; - int readlen = 1 + sizeof(*data) * len; - int ret; - - ret = hid_hw_raw_request(hid, report_number, (unsigned char *)buf, readlen, report_type, HID_REQ_GET_REPORT); - if (ret != readlen) { - hid_info(hid, "rkvr_recv_report fail\n"); - return -1; - } - memcpy(data, &buf[1], len); - hid_info(hid, "rkvr_recv_report %02x\n", type); - - return 0; -} - -/* - * for enable sensor data - ************************************ - * buf contents ----> - * first 8 bytes :random digits - * left bytes :encryt data - * eg:32654:3AA4618F6B455D37F06279EC2D6BC478C759443277F3E4E982203562E7ED - *********************************** - */ - -static int hid_report_sync(struct device *dev, const char *data, size_t count) -{ - struct hid_device *hid = container_of(dev, struct hid_device, dev); - u64 *tmp; - unsigned char buf[64] = {HID_REPORT_ID_RKVR, RKVR_ID_SYNC}; - unsigned char buf2[3] = {0}; - char *colon; - int i, ret = 0; - char *p; - size_t len; - - p = kmalloc(sizeof(*p) * count, GFP_KERNEL); - if (!p) { - hid_err(hid, "no mem\n"); - return -ENOMEM; - } - memcpy(p, data, count); - colon = strnchr(p, count, ':'); - if (!colon) { - hid_err(hid, "must have conlon\n"); - ret = -EINVAL; - goto fail; - } - if (colon - p + 1 >= count) { - hid_err(hid, "must have sync string after conlon\n"); - ret = -EINVAL; - goto fail; - } - colon[0] = 0; - colon++; - tmp = (u64 *)(buf + 2); - if (kstrtoull(p, 10, tmp)) { - hid_err(hid, "convert rand string fail,only decimal string allowed\n"); - ret = -EINVAL; - goto fail; - } - hid_info(hid, "uint64 %llu\n", *(u64 *)(buf + 2)); - len = min((count - (colon - p)) / 2, sizeof(buf) - (sizeof(*tmp) + 2)); - for (i = 0; i < len; i++) { - buf2[0] = colon[i * 2]; - buf2[1] = colon[i * 2 + 1]; - if (kstrtou8(buf2, 16, &buf[sizeof(*tmp) + 2 + i])) { - hid_err(hid, "err sync string,only hex string allowed\n"); - ret = -EINVAL; - goto fail; - } - } - len = i + sizeof(*tmp) + 2; - ret = rkvr_send_report(dev, (unsigned char *)buf, len); - if (ret) { - hid_err(hid, "hid_report_encrypt fail\n"); - ret = -EIO; - goto fail; - } - hid_info(hid, "hid_report_encrypt ok\n"); - ret = count; -fail: - kfree(p); - - return ret; -} - -static int hid_get_capability(struct device *dev, struct hid_capability *caps) -{ - struct hid_device *hid = container_of(dev, struct hid_device, dev); - u8 data = 0; - - caps->suspend_notify = 0; - if (!rkvr_recv_report(dev, RKVR_ID_CAPS, &data, 1)) { - hid_info(hid, "hid_get_capability %d\n", data); - caps->suspend_notify = data; - return 0; - } - return -1; -} - -static void hid_report_fill_rw(unsigned char *buf, u8 reg, u8 *data, int len, int w) -{ - if (w) - buf[0] = (1 << 7) | (len & 0x7f); - else - buf[0] = len & 0x7f; - buf[1] = reg; - memcpy(&buf[2], data, len); -} - -#if DEBUG_SYS - -static int hid_report_readreg(struct device *dev, u8 reg, u8 *data, int len) -{ - struct hid_device *hid = container_of(dev, struct hid_device, dev); - unsigned char report_number = reg; - unsigned char report_type = HID_REGR_REPORT; - char buf[1 + sizeof(*data) * len]; - int readlen = 1 + sizeof(*data) * len; - int ret; - - ret = hid_hw_raw_request(hid, report_number, (unsigned char *)buf, readlen, report_type, HID_REQ_GET_REPORT); - if (ret != readlen) { - hid_info(hid, "id_hw_raw_request fail\n"); - } else { - memcpy(data, &buf[1], readlen); - hid_info(hid, "hid_report_readreg %02x %02x\n", reg, data[0]); - } - - return 0; -} - -static int hid_report_writereg(struct device *dev, u8 reg, u8 data) -{ - struct hid_device *hid = container_of(dev, struct hid_device, dev); - unsigned char report_number = HID_REPORT_ID_W; - unsigned char report_type = HID_REGW_REPORT; - char buf[3 + sizeof(data)]; - int ret; - - hid_report_fill_rw(&buf[1], reg, &data, sizeof(data), 1); - ret = hid_hw_raw_request(hid, report_number, (unsigned char *)buf, 4, report_type, HID_REQ_SET_REPORT); - if (ret != 4) - hid_info(hid, "id_hw_raw_request fail\n"); - else - hid_info(hid, "id_hw_raw_request ok\n"); - - return 0; -} - -static ssize_t rkvr_dev_attr_debug_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct hidraw *devraw; - - devraw = dev_get_drvdata(dev); - if (0 == strncmp(buf, "write", 5)) - hid_report_writereg(&devraw->hid->dev, 0, 0); - hid_info(devraw->hid, "%s\n", buf); - - return count; -} - -static ssize_t rkvr_dev_attr_debug_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - size_t count = 0; - u8 mpu6500_id = 0; - struct hidraw *devraw; - - devraw = dev_get_drvdata(dev); - if (!hid_report_readreg(&devraw->hid->dev, 0x75 | 0x80, &mpu6500_id, 1)) - count += sprintf(&buf[count], "reg value %d\n", mpu6500_id); - else - count += sprintf(&buf[count], "read fail\n"); - - return count; -} -static DEVICE_ATTR(debug, 0664, rkvr_dev_attr_debug_show, rkvr_dev_attr_debug_store); - -static ssize_t rkvr_dev_attr_sync_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct hidraw *devraw = dev_get_drvdata(dev); - int ret; - - ret = hid_report_sync(&devraw->hid->dev, buf, count - 1); - return ret > 0 ? count : ret; -} - -static DEVICE_ATTR(sync, S_IWUSR, NULL, rkvr_dev_attr_sync_store); -#endif - -static int rkvr_hid_read(struct rkvr_iio_hw_device *hdev, int reg, unsigned char *data, int len) -{ - struct hid_device *hid = container_of(hdev->dev, struct hid_device, dev); - unsigned char report_number = reg; - unsigned char report_type = HID_REGR_REPORT; - char buf[1 + sizeof(*data) * len]; - int readlen = 1 + sizeof(*data) * len; - int ret; - - ret = hid_hw_raw_request(hid, report_number, (unsigned char *)buf, readlen, report_type, HID_REQ_GET_REPORT); - if (ret != readlen) { - hid_err(hid, "id_hw_raw_request fail\n"); - } else { - memcpy(data, &buf[1], sizeof(*data) * len); - } - - return 0; -} - -static int rkvr_hid_write(struct rkvr_iio_hw_device *hdev, int reg, unsigned char data) -{ - struct hid_device *hid = container_of(hdev->dev, struct hid_device, dev); - unsigned char report_number = HID_REPORT_ID_W; - unsigned char report_type = HID_REGW_REPORT; - char buf[3 + sizeof(data)]; - int ret; - - hid_report_fill_rw(&buf[1], reg, &data, sizeof(data), 1); - ret = hid_hw_raw_request(hid, report_number, (unsigned char *)buf, 4, report_type, HID_REQ_SET_REPORT); - if (ret != 4) - hid_info(hid, "id_hw_raw_request fail\n"); - else - hid_info(hid, "id_hw_raw_request ok\n"); - - return 0; -} - -static int rkvr_hid_open(struct rkvr_iio_hw_device *hdev) -{ - struct hid_device *hid; - int err; - - hid = container_of(hdev->dev, struct hid_device, dev); - err = hid_hw_power(hid, PM_HINT_FULLON); - if (err < 0) - return err; - err = hid_hw_open(hid); - if (err < 0) { - hid_hw_power(hid, PM_HINT_NORMAL); - return err; - } - - return 0; -} - -static void rkvr_hid_close(struct rkvr_iio_hw_device *hdev) -{ - struct hid_device *hid; - - hid = container_of(hdev->dev, struct hid_device, dev); - hid_hw_power(hid, PM_HINT_NORMAL); - hid_hw_close(hid); -} - -#if DYNAMIC_LOAD_MPU6500 -static int register_mpu6500; -struct platform_device mpu6500_dev = { - .name = "mpu6500", -}; -#endif - -static int rkvr_connect(struct hid_device *hid) -{ - int minor, result; - struct hidraw *dev; - - /* we accept any HID device, no matter the applications */ - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) - return -ENOMEM; - result = -EINVAL; - mutex_lock(&minors_lock); - for (minor = 0; minor < RKVR_HIDRAW_MAX_DEVICES; minor++) { - if (rkvr_hidraw_table[minor]) - continue; - rkvr_hidraw_table[minor] = dev; - result = 0; - break; - } - if (result) { - mutex_unlock(&minors_lock); - kfree(dev); - goto out; - } - - dev->dev = device_create(rkvr_class, &hid->dev, MKDEV(rkvr_major, minor), - NULL, "%s%d", "rkvr", minor); - - if (IS_ERR(dev->dev)) { - rkvr_hidraw_table[minor] = NULL; - mutex_unlock(&minors_lock); - result = PTR_ERR(dev->dev); - kfree(dev); - goto out; - } - - dev_set_drvdata(dev->dev, dev); -#if DEBUG_SYS - device_create_file(dev->dev, &dev_attr_debug); - device_create_file(dev->dev, &dev_attr_sync); -#endif - - { - struct rkvr_iio_hw_device *hw_device; - - hw_device = inv_hid_alloc("hid-rkvr"); - if (!hw_device) { - hid_err(hid, "inv_hid_alloc(\"hid-rkvr\") fail\n"); - rkvr_hidraw_table[minor] = NULL; - mutex_unlock(&minors_lock); - result = PTR_ERR(dev->dev); - kfree(dev); - goto out; - } - hw_device->dev = &hid->dev; - hw_device->open = rkvr_hid_open; - hw_device->close = rkvr_hid_close; - hw_device->read = rkvr_hid_read; - hw_device->write = rkvr_hid_write; - if (inv_hid_register_devcie(hw_device)) { - hid_err(hid, "inv_hid_register_devcie(\"hid-rkvr\") fail\n"); - inv_hid_free(hw_device); - rkvr_hidraw_table[minor] = NULL; - mutex_unlock(&minors_lock); - result = PTR_ERR(dev->dev); - kfree(dev); - goto out; - } - } - -#if DYNAMIC_LOAD_MPU6500 - if (!register_mpu6500) { - register_mpu6500 = 1; - hid_info(hid, "--->platform_device_register-->\n"); - platform_device_register(&mpu6500_dev); - } -#endif - - if (hid_hw_open(hid)) { - rkvr_hidraw_table[minor] = NULL; - mutex_unlock(&minors_lock); - result = PTR_ERR(dev->dev); - kfree(dev); - hid_err(hid, "rkvr_connect:hid_hw_open fail\n"); - goto out; - } - - init_waitqueue_head(&dev->wait); - spin_lock_init(&dev->list_lock); - INIT_LIST_HEAD(&dev->list); - - dev->hid = hid; - dev->minor = minor; - dev->exist = 1; - hid->hidraw = dev; /*struct hidraw * **/ - - hid_get_capability(&hid->dev, &rkvr_hid_capability[minor]); - - mutex_unlock(&minors_lock); -out: - return result; -} - -static int rkvr_keys_remove(struct hid_device *hdev) -{ - struct input_dev *input = hdev->hiddev; - - input_unregister_device(input); - return 0; -} - -static unsigned int key_codes[] = { - KEY_MENU, - KEY_HOME, - KEY_POWER, - KEY_VOLUMEUP, - KEY_VOLUMEDOWN, - KEY_WAKEUP, - KEY_ESC, - KEY_LEFT, - KEY_RIGHT, - KEY_UP, - KEY_DOWN, - KEY_ENTER, - BTN_MOUSE -}; - -static int __must_check rkvr_keys_probe(struct hid_device *hdev) -{ - - struct device *dev = &hdev->dev; - struct input_dev *input = NULL; - int i, error = 0; - - input = devm_input_allocate_device(dev); - if (!input) { - hid_err(hdev, "input_allocate_device fail\n"); - return -ENOMEM; - } - input->name = "rkvr-keypad"; - input->phys = "rkvr-keys/input0"; - input->dev.parent = dev; - input->id.bustype = BUS_HOST; - input->id.vendor = 0x071b; - input->id.product = 0x3205; - input->id.version = 0x0001; - - for (i = 0; i < sizeof(key_codes) / sizeof(key_codes[0]); i++) { - hid_info(hdev, "input_set_capability %d\n", key_codes[i]); - input_set_capability(input, EV_KEY, key_codes[i]); - } - -#ifdef RK_HID_GEAR_TOUCH - set_bit(EV_REL, input->evbit); - input_set_capability(input, EV_REL, REL_X); - input_set_capability(input, EV_REL, REL_Y); - input_set_capability(input, EV_MSC, MSC_SCAN); - input_set_capability(input, EV_KEY, 0x110); -#endif - - error = input_register_device(input); - if (error) { - hid_err(hdev, "rkvr-s: Unable to register input device, error: %d\n", error); - return error; - } - hdev->hiddev = input; - - return 0; -} - -static inline int __must_check rkvr_hw_start(struct hid_device *hdev, unsigned int connect_mask) -{ - int ret = hdev->ll_driver->start(hdev); - - if (ret) - return ret; - ret = rkvr_connect(hdev); - if (ret) - hdev->ll_driver->stop(hdev); - - return ret; -} - -static void rkvr_disconnect(struct hid_device *hid) -{ - struct hidraw *hidraw = hid->hidraw; - - mutex_lock(&minors_lock); - /* always unregistering inv_hid_device when hardware disconnect */ - inv_hid_unregister_and_destroy_devcie_by_name("hid-rkvr"); -#if DEBUG_SYS - device_remove_file(hidraw->dev, &dev_attr_debug); - device_remove_file(hidraw->dev, &dev_attr_sync); -#endif - - device_destroy(rkvr_class, MKDEV(rkvr_major, hidraw->minor)); - rkvr_drop_ref(hidraw, 1); - mutex_unlock(&minors_lock); -} - -static void rkvr_hw_stop(struct hid_device *hdev) -{ - rkvr_disconnect(hdev); - hdev->ll_driver->stop(hdev); -} - -static long rkvr_hidraw_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - struct inode *inode = file_inode(file); - unsigned int minor = iminor(inode); - long ret = 0; - struct hidraw *dev; - void __user *user_arg = (void __user *)arg; - - mutex_lock(&minors_lock); - dev = rkvr_hidraw_table[minor]; - if (!dev) { - ret = -ENODEV; - goto out; - } - - switch (cmd) { - case HIDIOCGRDESCSIZE: - if (put_user(dev->hid->rsize, (int __user *)arg)) - ret = -EFAULT; - break; - - case HIDIOCGRDESC: - { - __u32 len; - - if (get_user(len, (int __user *)arg)) - ret = -EFAULT; - else if (len > HID_MAX_DESCRIPTOR_SIZE - 1) - ret = -EINVAL; - else if (copy_to_user(user_arg + offsetof( - struct hidraw_report_descriptor, - value[0]), - dev->hid->rdesc, - min(dev->hid->rsize, len))) - ret = -EFAULT; - break; - } - case HIDIOCGRAWINFO: - { - struct hidraw_devinfo dinfo; - - dinfo.bustype = dev->hid->bus; - dinfo.vendor = dev->hid->vendor; - dinfo.product = dev->hid->product; - if (copy_to_user(user_arg, &dinfo, sizeof(dinfo))) - ret = -EFAULT; - break; - } - default: - { - struct hid_device *hid = dev->hid; - - if (_IOC_TYPE(cmd) != 'H') { - ret = -EINVAL; - break; - } - - if (_IOC_NR(cmd) == _IOC_NR(HIDIOCSFEATURE(0))) { - int len = _IOC_SIZE(cmd); - - ret = rkvr_hidraw_send_report(file, user_arg, len, HID_FEATURE_REPORT); - break; - } - if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGFEATURE(0))) { - int len = _IOC_SIZE(cmd); - - ret = rkvr_hidraw_get_report(file, user_arg, len, HID_FEATURE_REPORT); - break; - } - - if (_IOC_NR(cmd) == _IOC_NR(HIDRKVRHANDSHAKE(0))) { - int len = _IOC_SIZE(cmd); - char *buf; - - buf = kzalloc(len + 1, GFP_KERNEL); - if (!buf) { - ret = -ENOMEM; - break; - } - if (copy_from_user(buf, user_arg, len)) { - ret = -EFAULT; - kfree(buf); - break; - } - ret = hid_report_sync(&hid->dev, buf, len); - kfree(buf); - break; - } - - /* Begin Read-only ioctls. */ - if (_IOC_DIR(cmd) != _IOC_READ) { - ret = -EINVAL; - break; - } - - if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWNAME(0))) { - int len = strlen(hid->name) + 1; - - if (len > _IOC_SIZE(cmd)) - len = _IOC_SIZE(cmd); - ret = copy_to_user(user_arg, hid->name, len) ? - -EFAULT : len; - break; - } - - if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWPHYS(0))) { - int len = strlen(hid->phys) + 1; - - if (len > _IOC_SIZE(cmd)) - len = _IOC_SIZE(cmd); - ret = copy_to_user(user_arg, hid->phys, len) ? - -EFAULT : len; - break; - } - } - - ret = -ENOTTY; - } -out: - mutex_unlock(&minors_lock); - return ret; -} - -static const struct file_operations rkvr_ops = { - .owner = THIS_MODULE, - .read = rkvr_hidraw_read, - .write = rkvr_hidraw_write, - .poll = rkvr_hidraw_poll, - .open = rkvr_hidraw_open, - .release = rkvr_hidraw_release, - .unlocked_ioctl = rkvr_hidraw_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = rkvr_hidraw_ioctl, -#endif - .fasync = rkvr_hidraw_fasync, - .llseek = noop_llseek, -}; - -int rkvr_sensor_register_callback(int (*callback)(char *, size_t, void *), void *priv) -{ - sensorData.priv = priv; - sensorData.send_event = callback; - - return 0; -} -EXPORT_SYMBOL_GPL(rkvr_sensor_register_callback); - -static int rkvr_fb_event_notify(struct notifier_block *self, - unsigned long action, void *data) -{ - int i; - unsigned char buf[3] = {HID_REPORT_ID_RKVR, RKVR_ID_IDLE, 0}; - struct hid_device *hid; - struct fb_event *event = data; - int blank_mode; - - if (action != FB_EARLY_EVENT_BLANK && action != FB_EVENT_BLANK) - return NOTIFY_OK; - - blank_mode = *((int *)event->data); - - mutex_lock(&minors_lock); - for (i = 0; i < RKVR_HIDRAW_MAX_DEVICES; i++) { - if (!rkvr_hidraw_table[i] || !rkvr_hidraw_table[i]->exist) - continue; - if (!rkvr_hid_capability[i].suspend_notify) { - continue; - } - hid = rkvr_hidraw_table[i]->hid; - if (action == FB_EARLY_EVENT_BLANK) { - switch (blank_mode) { - case FB_BLANK_UNBLANK: - break; - default: - rkvr_send_report(&hid->dev, buf, 3); - break; - } - } else if (action == FB_EVENT_BLANK) { - switch (blank_mode) { - case FB_BLANK_UNBLANK: - buf[2] = 1; - rkvr_send_report(&hid->dev, buf, 3); - break; - default: - break; - } - } - } - mutex_unlock(&minors_lock); - return NOTIFY_OK; -} - -static struct notifier_block rkvr_fb_notifier = { - .notifier_call = rkvr_fb_event_notify, -}; - -static int rkvr_probe(struct hid_device *hdev, const struct hid_device_id *id) -{ - int retval; - struct usb_interface *intf = to_usb_interface(hdev->dev.parent); - - retval = hid_parse(hdev); - if (retval) { - hid_err(hdev, "rkvr - parse failed\n"); - goto exit; - } - hid_set_drvdata(hdev, &sensorData); - if (intf->cur_altsetting->desc.bInterfaceNumber == RKVR_INTERFACE_USB_SENSOR_ID) { - retval = rkvr_keys_probe(hdev); - if (retval) { - hid_err(hdev, "rkvr_keys_probe failed\n"); - goto exit_stop; - } - retval = rkvr_hw_start(hdev, 0); - if (retval) { - hid_err(hdev, "rkvr - rkvr hw start failed\n"); - rkvr_keys_remove(hdev); - goto exit_stop; - } - } else { - retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); - if (retval) { - hid_err(hdev, "rkvr - hid hw start failed\n"); - goto exit; - } - } - - return 0; - -exit_stop: - hid_hw_stop(hdev); -exit: - return retval; -} - -static void rkvr_remove(struct hid_device *hdev) -{ - struct usb_interface *intf = to_usb_interface(hdev->dev.parent); - - if (intf->cur_altsetting->desc.bInterfaceNumber == RKVR_INTERFACE_USB_SENSOR_ID) { - rkvr_hw_stop(hdev); - rkvr_keys_remove(hdev); - } else { - hid_hw_stop(hdev); - } -} - -static int rkvr_raw_event(struct hid_device *hdev, struct hid_report *report, u8 *data, int size) -{ - int retval = 0; - static unsigned int count; - static unsigned long old_jiffy; - - struct usb_interface *intf = to_usb_interface(hdev->dev.parent); - - if (intf->cur_altsetting->desc.bInterfaceNumber != RKVR_INTERFACE_USB_SENSOR_ID) { - hid_info(hdev, "%s,ignored interface number is %d\n", __func__, - intf->cur_altsetting->desc.bInterfaceNumber); - return 0; - } - - /* print sensor poll frequency */ - if (++count >= 1000) { - unsigned long cur_jiffy = jiffies; - - hid_dbg(hdev, "rkvr: %d Hz, hidrkvr %d\n", (int)(1000 * HZ / (cur_jiffy - old_jiffy)), (hdev->hidraw ? 1 : 0)); - count = 0; - old_jiffy = cur_jiffy; - } - - if (hdev->hidraw || hdev->hiddev) { - retval = rkvr_report_event(hdev, data, size); - if (retval < 0) - hid_info(hdev, "rkvr: raw event err %d\n", retval); - } - - return retval; -} - -static const struct hid_device_id rkvr_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_ROCKCHIP, USB_DEVICE_ID_NANOC) }, - { } -}; - -MODULE_DEVICE_TABLE(hid, rkvr_devices); - -static struct hid_driver rkvr_driver = { - .name = "rkvr", - .id_table = rkvr_devices, - .probe = rkvr_probe, - .remove = rkvr_remove, - .raw_event = rkvr_raw_event -}; - -static int __init rkvr_init(void) -{ - int retval; - dev_t dev_id; - - rkvr_class = class_create(THIS_MODULE, "rkvr"); - if (IS_ERR(rkvr_class)) - return PTR_ERR(rkvr_class); - - retval = hid_register_driver(&rkvr_driver); - if (retval < 0) { - pr_warn("rkvr_init - Can't register drive.\n"); - goto out_class; - } - - retval = alloc_chrdev_region(&dev_id, RKVR_FIRST_MINOR, - RKVR_HIDRAW_MAX_DEVICES, "rkvr"); - if (retval < 0) { - pr_warn("rkvr_init - Can't allocate chrdev region.\n"); - goto out_register; - } - - rkvr_major = MAJOR(dev_id); - cdev_init(&rkvr_cdev, &rkvr_ops); - cdev_add(&rkvr_cdev, dev_id, RKVR_HIDRAW_MAX_DEVICES); - - retval = fb_register_client(&rkvr_fb_notifier); - if (retval) { - pr_warn("rkvr_init - Can't register fb notifier\n"); - goto out_chardev; - } - return 0; -out_chardev: - unregister_chrdev_region(dev_id, RKVR_HIDRAW_MAX_DEVICES); -out_register: - hid_unregister_driver(&rkvr_driver); -out_class: - class_destroy(rkvr_class); - - return retval; -} - -static void __exit rkvr_exit(void) -{ - dev_t dev_id = MKDEV(rkvr_major, 0); - - fb_unregister_client(&rkvr_fb_notifier); - cdev_del(&rkvr_cdev); - - unregister_chrdev_region(dev_id, RKVR_HIDRAW_MAX_DEVICES); - - hid_unregister_driver(&rkvr_driver); - class_destroy(rkvr_class); -} - -module_init(rkvr_init); -module_exit(rkvr_exit); - -MODULE_AUTHOR("zwp"); -MODULE_DESCRIPTION("USB ROCKCHIP VR char device driver."); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/hid/hid-rkvr.h b/drivers/hid/hid-rkvr.h deleted file mode 100644 index 138556358fc4..000000000000 --- a/drivers/hid/hid-rkvr.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2016 ROCKCHIP, Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - */ -#ifndef __HID_RKVR_H -#define __HID_RKVR_H - -#define HIDRKVRHANDSHAKE(len) _IOC(_IOC_WRITE, 'H', 0x1A, len) - -#define HID_REPORT_ID_RKVR 3 -#define RKVR_ID_IDLE 1 -#define RKVR_ID_SYNC 2 -#define RKVR_ID_CAPS 3 - -#define HID_REPORT_ID_R 4 -#define HID_REPORT_ID_W 5 -#define HID_REPORT_ID_CRYP 6 - -#define HID_REGR_REPORT (4 - 1) -#define HID_REGW_REPORT (5 - 1) -#define HID_MISC_REPORT (6 - 1) - -#define HID_SYNCW_REPORT (7 - 1) -#define HID_SYNCR_REPORT (8 - 1) - -enum tracker_message_type { - TrackerMessage_None = 0, - TrackerMessage_Sensors = 1, - TrackerMessage_Unknown = 0x100, - TrackerMessage_SizeError = 0x101, -}; - -#define DEBUG_SYS 1 - -#define DYNAMIC_LOAD_MPU6500 0 - -int rkvr_sensor_register_callback(int (*callback)(char *, size_t, void *), void *priv); - -struct rkvr_iio_hw_device { - struct device *dev; - const char *name; - int is_open; - struct list_head l; - int (*open)(struct rkvr_iio_hw_device *hdev); - void (*close)(struct rkvr_iio_hw_device *hdev); - int (*power)(struct rkvr_iio_hw_device *hdev, int level); - int (*idle)(struct rkvr_iio_hw_device *hdev, int report, int idle, int reqtype); - int (*read)(struct rkvr_iio_hw_device *hdev, int reg, unsigned char *data, int len); - int (*write)(struct rkvr_iio_hw_device *hdev, int reg, unsigned char data); -}; - -#endif