mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 12:28:41 +08:00
Merge branches 'for-4.13/ish' and 'for-4.13/ite' into for-linus
Conflicts: drivers/hid/hid-core.c
This commit is contained in:
commit
604250ddcf
@ -388,6 +388,13 @@ config HID_ICADE
|
|||||||
To compile this driver as a module, choose M here: the
|
To compile this driver as a module, choose M here: the
|
||||||
module will be called hid-icade.
|
module will be called hid-icade.
|
||||||
|
|
||||||
|
config HID_ITE
|
||||||
|
tristate "ITE devices"
|
||||||
|
depends on HID
|
||||||
|
default !EXPERT
|
||||||
|
---help---
|
||||||
|
Support for ITE devices not fully compliant with HID standard.
|
||||||
|
|
||||||
config HID_TWINHAN
|
config HID_TWINHAN
|
||||||
tristate "Twinhan IR remote control"
|
tristate "Twinhan IR remote control"
|
||||||
depends on HID
|
depends on HID
|
||||||
|
@ -50,6 +50,7 @@ obj-$(CONFIG_HID_HOLTEK) += hid-holtek-mouse.o
|
|||||||
obj-$(CONFIG_HID_HOLTEK) += hid-holtekff.o
|
obj-$(CONFIG_HID_HOLTEK) += hid-holtekff.o
|
||||||
obj-$(CONFIG_HID_HYPERV_MOUSE) += hid-hyperv.o
|
obj-$(CONFIG_HID_HYPERV_MOUSE) += hid-hyperv.o
|
||||||
obj-$(CONFIG_HID_ICADE) += hid-icade.o
|
obj-$(CONFIG_HID_ICADE) += hid-icade.o
|
||||||
|
obj-$(CONFIG_HID_ITE) += hid-ite.o
|
||||||
obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o
|
obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o
|
||||||
obj-$(CONFIG_HID_KEYTOUCH) += hid-keytouch.o
|
obj-$(CONFIG_HID_KEYTOUCH) += hid-keytouch.o
|
||||||
obj-$(CONFIG_HID_KYE) += hid-kye.o
|
obj-$(CONFIG_HID_KYE) += hid-kye.o
|
||||||
|
@ -1985,6 +1985,9 @@ static const struct hid_device_id hid_have_special_driver[] = {
|
|||||||
#if IS_ENABLED(CONFIG_HID_ICADE)
|
#if IS_ENABLED(CONFIG_HID_ICADE)
|
||||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) },
|
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) },
|
||||||
#endif
|
#endif
|
||||||
|
#if IS_ENABLED(CONFIG_HID_ITE)
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_ITE, USB_DEVICE_ID_ITE8595) },
|
||||||
|
#endif
|
||||||
#if IS_ENABLED(CONFIG_HID_KENSINGTON)
|
#if IS_ENABLED(CONFIG_HID_KENSINGTON)
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
|
||||||
#endif
|
#endif
|
||||||
|
@ -565,6 +565,7 @@
|
|||||||
#define USB_DEVICE_ID_ITE_LENOVO_YOGA 0x8386
|
#define USB_DEVICE_ID_ITE_LENOVO_YOGA 0x8386
|
||||||
#define USB_DEVICE_ID_ITE_LENOVO_YOGA2 0x8350
|
#define USB_DEVICE_ID_ITE_LENOVO_YOGA2 0x8350
|
||||||
#define USB_DEVICE_ID_ITE_LENOVO_YOGA900 0x8396
|
#define USB_DEVICE_ID_ITE_LENOVO_YOGA900 0x8396
|
||||||
|
#define USB_DEVICE_ID_ITE8595 0x8595
|
||||||
|
|
||||||
#define USB_VENDOR_ID_JABRA 0x0b0e
|
#define USB_VENDOR_ID_JABRA 0x0b0e
|
||||||
#define USB_DEVICE_ID_JABRA_SPEAK_410 0x0412
|
#define USB_DEVICE_ID_JABRA_SPEAK_410 0x0412
|
||||||
|
@ -656,6 +656,15 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
|||||||
case HID_GD_START: map_key_clear(BTN_START); break;
|
case HID_GD_START: map_key_clear(BTN_START); break;
|
||||||
case HID_GD_SELECT: map_key_clear(BTN_SELECT); break;
|
case HID_GD_SELECT: map_key_clear(BTN_SELECT); break;
|
||||||
|
|
||||||
|
case HID_GD_RFKILL_BTN:
|
||||||
|
/* MS wireless radio ctl extension, also check CA */
|
||||||
|
if (field->application == HID_GD_WIRELESS_RADIO_CTLS) {
|
||||||
|
map_key_clear(KEY_RFKILL);
|
||||||
|
/* We need to simulate the btn release */
|
||||||
|
field->flags |= HID_MAIN_ITEM_RELATIVE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default: goto unknown;
|
default: goto unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
56
drivers/hid/hid-ite.c
Normal file
56
drivers/hid/hid-ite.c
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* HID driver for some ITE "special" devices
|
||||||
|
* Copyright (c) 2017 Hans de Goede <hdegoede@redhat.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include <linux/input.h>
|
||||||
|
#include <linux/hid.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
|
||||||
|
#include "hid-ids.h"
|
||||||
|
|
||||||
|
static int ite_event(struct hid_device *hdev, struct hid_field *field,
|
||||||
|
struct hid_usage *usage, __s32 value)
|
||||||
|
{
|
||||||
|
struct input_dev *input;
|
||||||
|
|
||||||
|
if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
input = field->hidinput->input;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The ITE8595 always reports 0 as value for the rfkill button. Luckily
|
||||||
|
* it is the only button in its report, and it sends a report on
|
||||||
|
* release only, so receiving a report means the button was pressed.
|
||||||
|
*/
|
||||||
|
if (usage->hid == HID_GD_RFKILL_BTN) {
|
||||||
|
input_event(input, EV_KEY, KEY_RFKILL, 1);
|
||||||
|
input_sync(input);
|
||||||
|
input_event(input, EV_KEY, KEY_RFKILL, 0);
|
||||||
|
input_sync(input);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct hid_device_id ite_devices[] = {
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_ITE, USB_DEVICE_ID_ITE8595) },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(hid, ite_devices);
|
||||||
|
|
||||||
|
static struct hid_driver ite_driver = {
|
||||||
|
.name = "itetech",
|
||||||
|
.id_table = ite_devices,
|
||||||
|
.event = ite_event,
|
||||||
|
};
|
||||||
|
module_hid_driver(ite_driver);
|
||||||
|
|
||||||
|
MODULE_LICENSE("GPL");
|
@ -1,5 +1,5 @@
|
|||||||
menu "Intel ISH HID support"
|
menu "Intel ISH HID support"
|
||||||
depends on X86_64 && PCI
|
depends on (X86_64 || COMPILE_TEST) && PCI
|
||||||
|
|
||||||
config INTEL_ISH_HID
|
config INTEL_ISH_HID
|
||||||
tristate "Intel Integrated Sensor Hub"
|
tristate "Intel Integrated Sensor Hub"
|
||||||
|
@ -26,6 +26,8 @@
|
|||||||
#define BXT_Bx_DEVICE_ID 0x1AA2
|
#define BXT_Bx_DEVICE_ID 0x1AA2
|
||||||
#define APL_Ax_DEVICE_ID 0x5AA2
|
#define APL_Ax_DEVICE_ID 0x5AA2
|
||||||
#define SPT_Ax_DEVICE_ID 0x9D35
|
#define SPT_Ax_DEVICE_ID 0x9D35
|
||||||
|
#define CNL_Ax_DEVICE_ID 0x9DFC
|
||||||
|
#define GLK_Ax_DEVICE_ID 0x31A2
|
||||||
|
|
||||||
#define REVISION_ID_CHT_A0 0x6
|
#define REVISION_ID_CHT_A0 0x6
|
||||||
#define REVISION_ID_CHT_Ax_SI 0x0
|
#define REVISION_ID_CHT_Ax_SI 0x0
|
||||||
|
@ -296,17 +296,12 @@ static int write_ipc_from_queue(struct ishtp_device *dev)
|
|||||||
/* If sending MNG_SYNC_FW_CLOCK, update clock again */
|
/* If sending MNG_SYNC_FW_CLOCK, update clock again */
|
||||||
if (IPC_HEADER_GET_PROTOCOL(doorbell_val) == IPC_PROTOCOL_MNG &&
|
if (IPC_HEADER_GET_PROTOCOL(doorbell_val) == IPC_PROTOCOL_MNG &&
|
||||||
IPC_HEADER_GET_MNG_CMD(doorbell_val) == MNG_SYNC_FW_CLOCK) {
|
IPC_HEADER_GET_MNG_CMD(doorbell_val) == MNG_SYNC_FW_CLOCK) {
|
||||||
struct timespec ts_system;
|
|
||||||
struct timeval tv_utc;
|
|
||||||
uint64_t usec_system, usec_utc;
|
uint64_t usec_system, usec_utc;
|
||||||
struct ipc_time_update_msg time_update;
|
struct ipc_time_update_msg time_update;
|
||||||
struct time_sync_format ts_format;
|
struct time_sync_format ts_format;
|
||||||
|
|
||||||
get_monotonic_boottime(&ts_system);
|
usec_system = ktime_to_us(ktime_get_boottime());
|
||||||
do_gettimeofday(&tv_utc);
|
usec_utc = ktime_to_us(ktime_get_real());
|
||||||
usec_system = (timespec_to_ns(&ts_system)) / NSEC_PER_USEC;
|
|
||||||
usec_utc = (uint64_t)tv_utc.tv_sec * 1000000 +
|
|
||||||
((uint32_t)tv_utc.tv_usec);
|
|
||||||
ts_format.ts1_source = HOST_SYSTEM_TIME_USEC;
|
ts_format.ts1_source = HOST_SYSTEM_TIME_USEC;
|
||||||
ts_format.ts2_source = HOST_UTC_TIME_USEC;
|
ts_format.ts2_source = HOST_UTC_TIME_USEC;
|
||||||
ts_format.reserved = 0;
|
ts_format.reserved = 0;
|
||||||
@ -575,15 +570,13 @@ static void fw_reset_work_fn(struct work_struct *unused)
|
|||||||
static void _ish_sync_fw_clock(struct ishtp_device *dev)
|
static void _ish_sync_fw_clock(struct ishtp_device *dev)
|
||||||
{
|
{
|
||||||
static unsigned long prev_sync;
|
static unsigned long prev_sync;
|
||||||
struct timespec ts;
|
|
||||||
uint64_t usec;
|
uint64_t usec;
|
||||||
|
|
||||||
if (prev_sync && jiffies - prev_sync < 20 * HZ)
|
if (prev_sync && jiffies - prev_sync < 20 * HZ)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
prev_sync = jiffies;
|
prev_sync = jiffies;
|
||||||
get_monotonic_boottime(&ts);
|
usec = ktime_to_us(ktime_get_boottime());
|
||||||
usec = (timespec_to_ns(&ts)) / NSEC_PER_USEC;
|
|
||||||
ipc_send_mng_msg(dev, MNG_SYNC_FW_CLOCK, &usec, sizeof(uint64_t));
|
ipc_send_mng_msg(dev, MNG_SYNC_FW_CLOCK, &usec, sizeof(uint64_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +35,8 @@ static const struct pci_device_id ish_pci_tbl[] = {
|
|||||||
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, BXT_Bx_DEVICE_ID)},
|
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, BXT_Bx_DEVICE_ID)},
|
||||||
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, APL_Ax_DEVICE_ID)},
|
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, APL_Ax_DEVICE_ID)},
|
||||||
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, SPT_Ax_DEVICE_ID)},
|
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, SPT_Ax_DEVICE_ID)},
|
||||||
|
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, CNL_Ax_DEVICE_ID)},
|
||||||
|
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, GLK_Ax_DEVICE_ID)},
|
||||||
{0, }
|
{0, }
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(pci, ish_pci_tbl);
|
MODULE_DEVICE_TABLE(pci, ish_pci_tbl);
|
||||||
|
@ -136,10 +136,9 @@ static void process_recv(struct ishtp_cl *hid_ishtp_cl, void *recv_buf,
|
|||||||
if (1 + sizeof(struct device_info) * i >=
|
if (1 + sizeof(struct device_info) * i >=
|
||||||
payload_len) {
|
payload_len) {
|
||||||
dev_err(&client_data->cl_device->dev,
|
dev_err(&client_data->cl_device->dev,
|
||||||
"[hid-ish]: [ENUM_DEVICES]: content size %lu is bigger than payload_len %u\n",
|
"[hid-ish]: [ENUM_DEVICES]: content size %zu is bigger than payload_len %zu\n",
|
||||||
1 + sizeof(struct device_info)
|
1 + sizeof(struct device_info)
|
||||||
* i,
|
* i, payload_len);
|
||||||
(unsigned int)payload_len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (1 + sizeof(struct device_info) * i >=
|
if (1 + sizeof(struct device_info) * i >=
|
||||||
|
@ -803,7 +803,7 @@ void ishtp_cl_send_msg(struct ishtp_device *dev, struct ishtp_cl *cl)
|
|||||||
* @ishtp_hdr: Pointer to message header
|
* @ishtp_hdr: Pointer to message header
|
||||||
*
|
*
|
||||||
* Receive and dispatch ISHTP client messages. This function executes in ISR
|
* Receive and dispatch ISHTP client messages. This function executes in ISR
|
||||||
* context
|
* or work queue context
|
||||||
*/
|
*/
|
||||||
void recv_ishtp_cl_msg(struct ishtp_device *dev,
|
void recv_ishtp_cl_msg(struct ishtp_device *dev,
|
||||||
struct ishtp_msg_hdr *ishtp_hdr)
|
struct ishtp_msg_hdr *ishtp_hdr)
|
||||||
@ -813,7 +813,6 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev,
|
|||||||
struct ishtp_cl_rb *new_rb;
|
struct ishtp_cl_rb *new_rb;
|
||||||
unsigned char *buffer = NULL;
|
unsigned char *buffer = NULL;
|
||||||
struct ishtp_cl_rb *complete_rb = NULL;
|
struct ishtp_cl_rb *complete_rb = NULL;
|
||||||
unsigned long dev_flags;
|
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int rb_count;
|
int rb_count;
|
||||||
|
|
||||||
@ -828,7 +827,7 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev,
|
|||||||
goto eoi;
|
goto eoi;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock_irqsave(&dev->read_list_spinlock, dev_flags);
|
spin_lock_irqsave(&dev->read_list_spinlock, flags);
|
||||||
rb_count = -1;
|
rb_count = -1;
|
||||||
list_for_each_entry(rb, &dev->read_list.list, list) {
|
list_for_each_entry(rb, &dev->read_list.list, list) {
|
||||||
++rb_count;
|
++rb_count;
|
||||||
@ -840,8 +839,7 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev,
|
|||||||
|
|
||||||
/* If no Rx buffer is allocated, disband the rb */
|
/* If no Rx buffer is allocated, disband the rb */
|
||||||
if (rb->buffer.size == 0 || rb->buffer.data == NULL) {
|
if (rb->buffer.size == 0 || rb->buffer.data == NULL) {
|
||||||
spin_unlock_irqrestore(&dev->read_list_spinlock,
|
spin_unlock_irqrestore(&dev->read_list_spinlock, flags);
|
||||||
dev_flags);
|
|
||||||
dev_err(&cl->device->dev,
|
dev_err(&cl->device->dev,
|
||||||
"Rx buffer is not allocated.\n");
|
"Rx buffer is not allocated.\n");
|
||||||
list_del(&rb->list);
|
list_del(&rb->list);
|
||||||
@ -857,8 +855,7 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev,
|
|||||||
* back FC, so communication will be stuck anyway)
|
* back FC, so communication will be stuck anyway)
|
||||||
*/
|
*/
|
||||||
if (rb->buffer.size < ishtp_hdr->length + rb->buf_idx) {
|
if (rb->buffer.size < ishtp_hdr->length + rb->buf_idx) {
|
||||||
spin_unlock_irqrestore(&dev->read_list_spinlock,
|
spin_unlock_irqrestore(&dev->read_list_spinlock, flags);
|
||||||
dev_flags);
|
|
||||||
dev_err(&cl->device->dev,
|
dev_err(&cl->device->dev,
|
||||||
"message overflow. size %d len %d idx %ld\n",
|
"message overflow. size %d len %d idx %ld\n",
|
||||||
rb->buffer.size, ishtp_hdr->length,
|
rb->buffer.size, ishtp_hdr->length,
|
||||||
@ -884,14 +881,13 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev,
|
|||||||
* the whole msg arrived, send a new FC, and add a new
|
* the whole msg arrived, send a new FC, and add a new
|
||||||
* rb buffer for the next coming msg
|
* rb buffer for the next coming msg
|
||||||
*/
|
*/
|
||||||
spin_lock_irqsave(&cl->free_list_spinlock, flags);
|
spin_lock(&cl->free_list_spinlock);
|
||||||
|
|
||||||
if (!list_empty(&cl->free_rb_list.list)) {
|
if (!list_empty(&cl->free_rb_list.list)) {
|
||||||
new_rb = list_entry(cl->free_rb_list.list.next,
|
new_rb = list_entry(cl->free_rb_list.list.next,
|
||||||
struct ishtp_cl_rb, list);
|
struct ishtp_cl_rb, list);
|
||||||
list_del_init(&new_rb->list);
|
list_del_init(&new_rb->list);
|
||||||
spin_unlock_irqrestore(&cl->free_list_spinlock,
|
spin_unlock(&cl->free_list_spinlock);
|
||||||
flags);
|
|
||||||
new_rb->cl = cl;
|
new_rb->cl = cl;
|
||||||
new_rb->buf_idx = 0;
|
new_rb->buf_idx = 0;
|
||||||
INIT_LIST_HEAD(&new_rb->list);
|
INIT_LIST_HEAD(&new_rb->list);
|
||||||
@ -900,8 +896,7 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev,
|
|||||||
|
|
||||||
ishtp_hbm_cl_flow_control_req(dev, cl);
|
ishtp_hbm_cl_flow_control_req(dev, cl);
|
||||||
} else {
|
} else {
|
||||||
spin_unlock_irqrestore(&cl->free_list_spinlock,
|
spin_unlock(&cl->free_list_spinlock);
|
||||||
flags);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* One more fragment in message (even if this was last) */
|
/* One more fragment in message (even if this was last) */
|
||||||
@ -914,7 +909,7 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock_irqrestore(&dev->read_list_spinlock, dev_flags);
|
spin_unlock_irqrestore(&dev->read_list_spinlock, flags);
|
||||||
/* If it's nobody's message, just read and discard it */
|
/* If it's nobody's message, just read and discard it */
|
||||||
if (!buffer) {
|
if (!buffer) {
|
||||||
uint8_t rd_msg_buf[ISHTP_RD_MSG_BUF_SIZE];
|
uint8_t rd_msg_buf[ISHTP_RD_MSG_BUF_SIZE];
|
||||||
@ -925,7 +920,8 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (complete_rb) {
|
if (complete_rb) {
|
||||||
getnstimeofday(&cl->ts_rx);
|
cl = complete_rb->cl;
|
||||||
|
cl->ts_rx = ktime_get();
|
||||||
++cl->recv_msg_cnt_ipc;
|
++cl->recv_msg_cnt_ipc;
|
||||||
ishtp_cl_read_complete(complete_rb);
|
ishtp_cl_read_complete(complete_rb);
|
||||||
}
|
}
|
||||||
@ -940,7 +936,7 @@ eoi:
|
|||||||
* @hbm: hbm buffer
|
* @hbm: hbm buffer
|
||||||
*
|
*
|
||||||
* Receive and dispatch ISHTP client messages using DMA. This function executes
|
* Receive and dispatch ISHTP client messages using DMA. This function executes
|
||||||
* in ISR context
|
* in ISR or work queue context
|
||||||
*/
|
*/
|
||||||
void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg,
|
void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg,
|
||||||
struct dma_xfer_hbm *hbm)
|
struct dma_xfer_hbm *hbm)
|
||||||
@ -950,10 +946,10 @@ void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg,
|
|||||||
struct ishtp_cl_rb *new_rb;
|
struct ishtp_cl_rb *new_rb;
|
||||||
unsigned char *buffer = NULL;
|
unsigned char *buffer = NULL;
|
||||||
struct ishtp_cl_rb *complete_rb = NULL;
|
struct ishtp_cl_rb *complete_rb = NULL;
|
||||||
unsigned long dev_flags;
|
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock_irqsave(&dev->read_list_spinlock, dev_flags);
|
spin_lock_irqsave(&dev->read_list_spinlock, flags);
|
||||||
|
|
||||||
list_for_each_entry(rb, &dev->read_list.list, list) {
|
list_for_each_entry(rb, &dev->read_list.list, list) {
|
||||||
cl = rb->cl;
|
cl = rb->cl;
|
||||||
if (!cl || !(cl->host_client_id == hbm->host_client_id &&
|
if (!cl || !(cl->host_client_id == hbm->host_client_id &&
|
||||||
@ -965,8 +961,7 @@ void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg,
|
|||||||
* If no Rx buffer is allocated, disband the rb
|
* If no Rx buffer is allocated, disband the rb
|
||||||
*/
|
*/
|
||||||
if (rb->buffer.size == 0 || rb->buffer.data == NULL) {
|
if (rb->buffer.size == 0 || rb->buffer.data == NULL) {
|
||||||
spin_unlock_irqrestore(&dev->read_list_spinlock,
|
spin_unlock_irqrestore(&dev->read_list_spinlock, flags);
|
||||||
dev_flags);
|
|
||||||
dev_err(&cl->device->dev,
|
dev_err(&cl->device->dev,
|
||||||
"response buffer is not allocated.\n");
|
"response buffer is not allocated.\n");
|
||||||
list_del(&rb->list);
|
list_del(&rb->list);
|
||||||
@ -982,8 +977,7 @@ void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg,
|
|||||||
* back FC, so communication will be stuck anyway)
|
* back FC, so communication will be stuck anyway)
|
||||||
*/
|
*/
|
||||||
if (rb->buffer.size < hbm->msg_length) {
|
if (rb->buffer.size < hbm->msg_length) {
|
||||||
spin_unlock_irqrestore(&dev->read_list_spinlock,
|
spin_unlock_irqrestore(&dev->read_list_spinlock, flags);
|
||||||
dev_flags);
|
|
||||||
dev_err(&cl->device->dev,
|
dev_err(&cl->device->dev,
|
||||||
"message overflow. size %d len %d idx %ld\n",
|
"message overflow. size %d len %d idx %ld\n",
|
||||||
rb->buffer.size, hbm->msg_length, rb->buf_idx);
|
rb->buffer.size, hbm->msg_length, rb->buf_idx);
|
||||||
@ -1007,14 +1001,13 @@ void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg,
|
|||||||
* the whole msg arrived, send a new FC, and add a new
|
* the whole msg arrived, send a new FC, and add a new
|
||||||
* rb buffer for the next coming msg
|
* rb buffer for the next coming msg
|
||||||
*/
|
*/
|
||||||
spin_lock_irqsave(&cl->free_list_spinlock, flags);
|
spin_lock(&cl->free_list_spinlock);
|
||||||
|
|
||||||
if (!list_empty(&cl->free_rb_list.list)) {
|
if (!list_empty(&cl->free_rb_list.list)) {
|
||||||
new_rb = list_entry(cl->free_rb_list.list.next,
|
new_rb = list_entry(cl->free_rb_list.list.next,
|
||||||
struct ishtp_cl_rb, list);
|
struct ishtp_cl_rb, list);
|
||||||
list_del_init(&new_rb->list);
|
list_del_init(&new_rb->list);
|
||||||
spin_unlock_irqrestore(&cl->free_list_spinlock,
|
spin_unlock(&cl->free_list_spinlock);
|
||||||
flags);
|
|
||||||
new_rb->cl = cl;
|
new_rb->cl = cl;
|
||||||
new_rb->buf_idx = 0;
|
new_rb->buf_idx = 0;
|
||||||
INIT_LIST_HEAD(&new_rb->list);
|
INIT_LIST_HEAD(&new_rb->list);
|
||||||
@ -1023,8 +1016,7 @@ void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg,
|
|||||||
|
|
||||||
ishtp_hbm_cl_flow_control_req(dev, cl);
|
ishtp_hbm_cl_flow_control_req(dev, cl);
|
||||||
} else {
|
} else {
|
||||||
spin_unlock_irqrestore(&cl->free_list_spinlock,
|
spin_unlock(&cl->free_list_spinlock);
|
||||||
flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* One more fragment in message (this is always last) */
|
/* One more fragment in message (this is always last) */
|
||||||
@ -1037,7 +1029,7 @@ void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock_irqrestore(&dev->read_list_spinlock, dev_flags);
|
spin_unlock_irqrestore(&dev->read_list_spinlock, flags);
|
||||||
/* If it's nobody's message, just read and discard it */
|
/* If it's nobody's message, just read and discard it */
|
||||||
if (!buffer) {
|
if (!buffer) {
|
||||||
dev_err(dev->devc, "Dropped Rx (DMA) msg - no request\n");
|
dev_err(dev->devc, "Dropped Rx (DMA) msg - no request\n");
|
||||||
@ -1045,7 +1037,8 @@ void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (complete_rb) {
|
if (complete_rb) {
|
||||||
getnstimeofday(&cl->ts_rx);
|
cl = complete_rb->cl;
|
||||||
|
cl->ts_rx = ktime_get();
|
||||||
++cl->recv_msg_cnt_dma;
|
++cl->recv_msg_cnt_dma;
|
||||||
ishtp_cl_read_complete(complete_rb);
|
ishtp_cl_read_complete(complete_rb);
|
||||||
}
|
}
|
||||||
|
@ -118,9 +118,9 @@ struct ishtp_cl {
|
|||||||
unsigned int out_flow_ctrl_cnt;
|
unsigned int out_flow_ctrl_cnt;
|
||||||
|
|
||||||
/* Rx msg ... out FC timing */
|
/* Rx msg ... out FC timing */
|
||||||
struct timespec ts_rx;
|
ktime_t ts_rx;
|
||||||
struct timespec ts_out_fc;
|
ktime_t ts_out_fc;
|
||||||
struct timespec ts_max_fc_delay;
|
ktime_t ts_max_fc_delay;
|
||||||
void *client_data;
|
void *client_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -321,13 +321,10 @@ int ishtp_hbm_cl_flow_control_req(struct ishtp_device *dev,
|
|||||||
if (!rv) {
|
if (!rv) {
|
||||||
++cl->out_flow_ctrl_creds;
|
++cl->out_flow_ctrl_creds;
|
||||||
++cl->out_flow_ctrl_cnt;
|
++cl->out_flow_ctrl_cnt;
|
||||||
getnstimeofday(&cl->ts_out_fc);
|
cl->ts_out_fc = ktime_get();
|
||||||
if (cl->ts_rx.tv_sec && cl->ts_rx.tv_nsec) {
|
if (cl->ts_rx) {
|
||||||
struct timespec ts_diff;
|
ktime_t ts_diff = ktime_sub(cl->ts_out_fc, cl->ts_rx);
|
||||||
|
if (ktime_after(ts_diff, cl->ts_max_fc_delay))
|
||||||
ts_diff = timespec_sub(cl->ts_out_fc, cl->ts_rx);
|
|
||||||
if (timespec_compare(&ts_diff, &cl->ts_max_fc_delay)
|
|
||||||
> 0)
|
|
||||||
cl->ts_max_fc_delay = ts_diff;
|
cl->ts_max_fc_delay = ts_diff;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -182,6 +182,11 @@ struct hid_item {
|
|||||||
#define HID_GD_KEYBOARD 0x00010006
|
#define HID_GD_KEYBOARD 0x00010006
|
||||||
#define HID_GD_KEYPAD 0x00010007
|
#define HID_GD_KEYPAD 0x00010007
|
||||||
#define HID_GD_MULTIAXIS 0x00010008
|
#define HID_GD_MULTIAXIS 0x00010008
|
||||||
|
/*
|
||||||
|
* Microsoft Win8 Wireless Radio Controls extensions CA, see:
|
||||||
|
* http://www.usb.org/developers/hidpage/HUTRR40RadioHIDUsagesFinal.pdf
|
||||||
|
*/
|
||||||
|
#define HID_GD_WIRELESS_RADIO_CTLS 0x0001000c
|
||||||
#define HID_GD_X 0x00010030
|
#define HID_GD_X 0x00010030
|
||||||
#define HID_GD_Y 0x00010031
|
#define HID_GD_Y 0x00010031
|
||||||
#define HID_GD_Z 0x00010032
|
#define HID_GD_Z 0x00010032
|
||||||
@ -210,6 +215,10 @@ struct hid_item {
|
|||||||
#define HID_GD_DOWN 0x00010091
|
#define HID_GD_DOWN 0x00010091
|
||||||
#define HID_GD_RIGHT 0x00010092
|
#define HID_GD_RIGHT 0x00010092
|
||||||
#define HID_GD_LEFT 0x00010093
|
#define HID_GD_LEFT 0x00010093
|
||||||
|
/* Microsoft Win8 Wireless Radio Controls CA usage codes */
|
||||||
|
#define HID_GD_RFKILL_BTN 0x000100c6
|
||||||
|
#define HID_GD_RFKILL_LED 0x000100c7
|
||||||
|
#define HID_GD_RFKILL_SWITCH 0x000100c8
|
||||||
|
|
||||||
#define HID_DC_BATTERYSTRENGTH 0x00060020
|
#define HID_DC_BATTERYSTRENGTH 0x00060020
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user