linux/drivers/hid/hid-mcp2221.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * MCP2221A - Microchip USB to I2C Host Protocol Bridge
 *
 * Copyright (c) 2020, Rishi Gupta <[email protected]>
 *
 * Datasheet: https://ww1.microchip.com/downloads/en/DeviceDoc/20005565B.pdf
 */

#include <linux/module.h>
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/bitfield.h>
#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/hid.h>
#include <linux/hidraw.h>
#include <linux/i2c.h>
#include <linux/gpio/driver.h>
#include <linux/iio/iio.h>
#include "hid-ids.h"

/* Commands codes in a raw output report */
enum {};

/* Response codes in a raw input report */
enum {};

/* MCP GPIO direction encoding */
enum {};

#define MCP_NGPIO

/* MCP GPIO set command layout */
struct mcp_set_gpio {} __packed;

/* MCP GPIO get command layout */
struct mcp_get_gpio {} __packed;

/*
 * There is no way to distinguish responses. Therefore next command
 * is sent only after response to previous has been received. Mutex
 * lock is used for this purpose mainly.
 */
struct mcp2221 {};

struct mcp2221_iio {};

/*
 * Default i2c bus clock frequency 400 kHz. Modify this if you
 * want to set some other frequency (min 50 kHz - max 400 kHz).
 */
static uint i2c_clk_freq =;

/* Synchronously send output report to the device */
static int mcp_send_report(struct mcp2221 *mcp,
					u8 *out_report, size_t len)
{}

/*
 * Send o/p report to the device and wait for i/p report to be
 * received from the device. If the device does not respond,
 * we timeout.
 */
static int mcp_send_data_req_status(struct mcp2221 *mcp,
			u8 *out_report, int len)
{}

/* Check pass/fail for actual communication with i2c slave */
static int mcp_chk_last_cmd_status(struct mcp2221 *mcp)
{}

/* Cancels last command releasing i2c bus just in case occupied */
static int mcp_cancel_last_cmd(struct mcp2221 *mcp)
{}

/* Check if the last command succeeded or failed and return the result.
 * If the command did fail, cancel that command which will free the i2c bus.
 */
static int mcp_chk_last_cmd_status_free_bus(struct mcp2221 *mcp)
{}

static int mcp_set_i2c_speed(struct mcp2221 *mcp)
{}

/*
 * An output report can contain minimum 1 and maximum 60 user data
 * bytes. If the number of data bytes is more then 60, we send it
 * in chunks of 60 bytes. Last chunk may contain exactly 60 or less
 * bytes. Total number of bytes is informed in very first report to
 * mcp2221, from that point onwards it first collect all the data
 * from host and then send to i2c slave device.
 */
static int mcp_i2c_write(struct mcp2221 *mcp,
				struct i2c_msg *msg, int type, u8 last_status)
{}

/*
 * Device reads all data (0 - 65535 bytes) from i2c slave device and
 * stores it in device itself. This data is read back from device to
 * host in multiples of 60 bytes using input reports.
 */
static int mcp_i2c_smbus_read(struct mcp2221 *mcp,
				struct i2c_msg *msg, int type, u16 smbus_addr,
				u8 smbus_len, u8 *smbus_buf)
{}

static int mcp_i2c_xfer(struct i2c_adapter *adapter,
				struct i2c_msg msgs[], int num)
{}

static int mcp_smbus_write(struct mcp2221 *mcp, u16 addr,
				u8 command, u8 *buf, u8 len, int type,
				u8 last_status)
{}

static int mcp_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
				unsigned short flags, char read_write,
				u8 command, int size,
				union i2c_smbus_data *data)
{}

static u32 mcp_i2c_func(struct i2c_adapter *adapter)
{}

static const struct i2c_algorithm mcp_i2c_algo =;

#if IS_REACHABLE(CONFIG_GPIOLIB)
static int mcp_gpio_get(struct gpio_chip *gc,
				unsigned int offset)
{}

static void mcp_gpio_set(struct gpio_chip *gc,
				unsigned int offset, int value)
{}

static int mcp_gpio_dir_set(struct mcp2221 *mcp,
				unsigned int offset, u8 val)
{}

static int mcp_gpio_direction_input(struct gpio_chip *gc,
				unsigned int offset)
{}

static int mcp_gpio_direction_output(struct gpio_chip *gc,
				unsigned int offset, int value)
{}

static int mcp_gpio_get_direction(struct gpio_chip *gc,
				unsigned int offset)
{}
#endif

/* Gives current state of i2c engine inside mcp2221 */
static int mcp_get_i2c_eng_state(struct mcp2221 *mcp,
				u8 *data, u8 idx)
{}

/*
 * MCP2221 uses interrupt endpoint for input reports. This function
 * is called by HID layer when it receives i/p report from mcp2221,
 * which is actually a response to the previously sent command.
 *
 * MCP2221A firmware specific return codes are parsed and 0 or
 * appropriate negative error code is returned. Delayed response
 * results in timeout error and stray reponses results in -EIO.
 */
static int mcp2221_raw_event(struct hid_device *hdev,
				struct hid_report *report, u8 *data, int size)
{}

/* Device resource managed function for HID unregistration */
static void mcp2221_hid_unregister(void *ptr)
{}

/* This is needed to be sure hid_hw_stop() isn't called twice by the subsystem */
static void mcp2221_remove(struct hid_device *hdev)
{}

#if IS_REACHABLE(CONFIG_IIO)
static int mcp2221_read_raw(struct iio_dev *indio_dev,
			    struct iio_chan_spec const *channel, int *val,
			    int *val2, long mask)
{}

static int mcp2221_write_raw(struct iio_dev *indio_dev,
			     struct iio_chan_spec const *chan,
			     int val, int val2, long mask)
{}

static const struct iio_info mcp2221_info =;

static int mcp_iio_channels(struct mcp2221 *mcp)
{}

static void mcp_init_work(struct work_struct *work)
{}
#endif

static int mcp2221_probe(struct hid_device *hdev,
					const struct hid_device_id *id)
{}

static const struct hid_device_id mcp2221_devices[] =;
MODULE_DEVICE_TABLE(hid, mcp2221_devices);

static struct hid_driver mcp2221_driver =;

/* Register with HID core */
module_hid_driver();

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();