/*
* HIDPP protocol for Logitech Unifying receivers
*
* Copyright (c) 2011 Logitech (c)
* Copyright (c) 2012-2013 Google (c)
* Copyright (c) 2013-2014 Red Hat 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; version 2 of the License.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/device.h>
#include <linux/hid.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/kfifo.h>
#include <linux/input/mt.h>
#include <asm/unaligned.h>
#include "hid-ids.h"
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>");
MODULE_AUTHOR("Nestor Lopez Casado <nlopezcasad@logitech.com>");
#define REPORT_ID_HIDPP_SHORT 0x10
#define REPORT_ID_HIDPP_LONG 0x11
#define HIDPP_REPORT_SHORT_LENGTH 7
#define HIDPP_REPORT_LONG_LENGTH 20
#define HIDPP_QUIRK_CLASS_WTP BIT(0)
/* bits 1..20 are reserved for classes */
#define HIDPP_QUIRK_DELAYED_INIT BIT(21)
#define HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS BIT(22)
#define HIDPP_QUIRK_MULTI_INPUT BIT(23)
/*
* There are two hidpp protocols in use, the first version hidpp10 is known
* as register access protocol or RAP, the second version hidpp20 is known as
* feature access protocol or FAP
*
* Most older devices (including the Unifying usb receiver) use the RAP protocol
* where as most newer devices use the FAP protocol. Both protocols are
* compatible with the underlying transport, which could be usb, Unifiying, or
* bluetooth. The message lengths are defined by the hid vendor specific report
* descriptor for the HIDPP_SHORT report type (total message lenth 7 bytes) and
* the HIDPP_LONG report type (total message length 20 bytes)
*
* The RAP protocol uses both report types, whereas the FAP only uses HIDPP_LONG
* messages. The Unifying receiver itself responds to RAP messages (device index
* is 0xFF for the receiver), and all messages (short or long) with a device
* index between 1 and 6 are passed untouched to the corresponding paired
* Unifying device.
*
* The paired device can be RAP or FAP, it will receive the message untouched
* from the Unifiying receiver.
*/
struct fap {
u8 feature_index;
u8 funcindex_clientid;
u8 params[HIDPP_REPORT_LONG_LENGTH - 4U];
};
struct rap {
u8 sub_id;
u8 reg_address;
u8 params[HIDPP_REPORT_LONG_LENGTH - 4U];
};
struct hidpp_report {
u8 report_id;
u8 device_index;
union {
struct fap fap;
struct rap rap;
u8 rawbytes[sizeof(struct fap)];
};
} __packed;
struct hidpp_device {
struct hid_device *hid_dev;
struct mutex send_mutex;
void *send_receive_buf;
char *name; /* will never be NULL and should not be freed */
wait_queue_head_t wait;
bool answer_available;
u8 protocol_major;
u8 protocol_minor;
void *private_data;
struct work_struct work;
struct kfifo delayed_work_fifo;
atomic_t connected;
struct input_dev *delayed_input;
unsigned long quirks;
};
/* HID++ 1.0 error codes */
#define HIDPP_ERROR 0x8f
#define HIDPP_ERROR_SUCCESS 0x00
#define HIDPP_ERROR_INVALID_SUBID 0x01
#define HIDPP_ERROR_INVALID_ADRESS 0x02
#define HIDPP_ERROR_INVALID_VALUE 0x03
#define HIDPP_ERROR_CONNECT_FAIL 0x04
#define HIDPP_ERROR_TOO_MANY_DEVICES 0x05
#define HIDPP_ERROR_ALREADY_EXISTS 0x06
#define HIDPP_ERROR_BUSY 0x07
#define HIDPP_ERROR_UNKNOWN_DEVICE 0x08
#define HIDPP_ERROR_RESOURCE_ERROR 0x09
#define HIDPP_ERROR_REQUEST_UNAVAILABLE 0x0a
#define HIDPP_ERROR_INVALID_PARAM_VALUE 0x0b
#define HIDPP_ERROR_WRONG_PIN_CODE 0x0c
/* HID++ 2.0 error codes */
#define HIDPP20_ERROR 0xff
static void hidpp_connect_event(struct hidpp_device *hidpp_dev);
static int __hidpp_send_report(struct hid_device *hdev<