170 lines
5.3 KiB
C

#ifndef __HID_LOGITECH_HIDPP_H
#define __HID_LOGITECH_HIDPP_H
/*
* HIDPP protocol
*
* Copyright (c) 2011 Logitech (c)
*/
/*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Should you need to contact me, the author, you can do so by e-mail send
* your message to Benjamin Tissoires <benjamin.tissoires at gmail com>
*
*/
#include <linux/kfifo.h>
#define REPORT_ID_HIDPP_SHORT 0x10
#define REPORT_ID_HIDPP_LONG 0x11
#define REPORT_ID_HIDPP_REL 0x20
#define HIDPP_REPORT_SHORT_LENGTH 7
#define HIDPP_REPORT_LONG_LENGTH 20
/* 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;
void *driver_data;
int (*raw_event)(struct hidpp_device *hidpp_dev, struct hidpp_report *report);
int (*device_init)(struct hidpp_device *hidpp_dev);
void (*connect_change)(struct hidpp_device *hidpp_dev, bool connected);
/* private */
struct work_struct work;
struct mutex send_mutex;
struct kfifo delayed_work_fifo;
spinlock_t lock;
void *send_receive_buf;
wait_queue_head_t wait;
bool answer_available;
bool initialized;
int init_retry;
};
extern int hidpp_raw_event(struct hid_device *hdev, struct hid_report *report,
u8 *data, int size);
extern void hidpp_connect_change(struct hidpp_device *hidpp_dev, bool connected);
extern int hidpp_init(struct hidpp_device *hidpp_dev, struct hid_device *hid_dev);
extern void hidpp_delayed_init(struct hidpp_device *hidpp_device);
extern void hidpp_remove(struct hidpp_device *hidpp_dev);
extern int hidpp_send_command_sync(struct hidpp_device *hidpp_dev,
u16 feature, u8 cmd, u8 *params, int param_count,
struct hidpp_report *response);
extern int hidpp_send_fap_command_sync(struct hidpp_device *hidpp_dev,
u8 feat_index, u8 funcindex_clientid, u8 *params, int param_count,
struct hidpp_report *response);
extern int hidpp_send_rap_command_sync(struct hidpp_device *hidpp_dev,
u8 report_id, u8 sub_id, u8 reg_address, u8 *params,
int param_count, struct hidpp_report *response);
static inline int hidpp_send_hidpp2_sync(struct hidpp_device *hidpp_dev,
u8 type,
u8 feature_index,
u8 sub_index,
u8 software_id,
u8 *params,
int params_count,
struct hidpp_report *response)
{
return hidpp_send_rap_command_sync(hidpp_dev,
type,
feature_index,
(sub_index << 4) | software_id,
params,
params_count,
response);
}
extern int hidpp_get_hidpp2_feature_index(struct hidpp_device *hidpp_dev,
u8 software_id,
u16 feature_id,
u8 *feature_idx);
#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
#define HIDPP_TYPE_KEYBOARD 0x00
#define HIDPP_TYPE_REMOTE_CONTROL 0x01
#define HIDPP_TYPE_NUMPAD 0x02
#define HIDPP_TYPE_MOUSE 0x03
#define HIDPP_TYPE_TOUCHPAD 0x04
#define HIDPP_TYPE_TRACKBALL 0x05
#define HIDPP_TYPE_PRESENTER 0x06
#define HIDPP_TYPE_RECEIVER 0x07
#define T651_REPORT_TYPE_MOUSE 0x02
#endif