#include <linux/bitops.h>
#include <linux/gpio/driver.h>
#include <linux/hid.h>
#include <linux/hidraw.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/nls.h>
#include <linux/string_choices.h>
#include <linux/usb/ch9.h>
#include "hid-ids.h"
#define CP2112_REPORT_MAX_LENGTH …
#define CP2112_GPIO_CONFIG_LENGTH …
#define CP2112_GPIO_GET_LENGTH …
#define CP2112_GPIO_SET_LENGTH …
#define CP2112_GPIO_MAX_GPIO …
#define CP2112_GPIO_ALL_GPIO_MASK …
enum { … };
enum { … };
enum { … };
struct cp2112_smbus_config_report { … } __packed;
struct cp2112_usb_config_report { … } __packed;
struct cp2112_read_req_report { … } __packed;
struct cp2112_write_read_req_report { … } __packed;
struct cp2112_write_req_report { … } __packed;
struct cp2112_force_read_report { … } __packed;
struct cp2112_xfer_status_report { … } __packed;
struct cp2112_string_report { … } __packed;
static const int XFER_STATUS_RETRIES = …;
static const int RESPONSE_TIMEOUT = …;
static const struct hid_device_id cp2112_devices[] = …;
MODULE_DEVICE_TABLE(hid, cp2112_devices);
struct cp2112_device { … };
static int gpio_push_pull = …;
module_param(gpio_push_pull, int, 0644);
MODULE_PARM_DESC(…) …;
static int cp2112_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
{ … }
static void cp2112_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{ … }
static int cp2112_gpio_get_all(struct gpio_chip *chip)
{ … }
static int cp2112_gpio_get(struct gpio_chip *chip, unsigned int offset)
{ … }
static int cp2112_gpio_direction_output(struct gpio_chip *chip,
unsigned offset, int value)
{ … }
static int cp2112_hid_get(struct hid_device *hdev, unsigned char report_number,
u8 *data, size_t count, unsigned char report_type)
{ … }
static int cp2112_hid_output(struct hid_device *hdev, u8 *data, size_t count,
unsigned char report_type)
{ … }
static int cp2112_wait(struct cp2112_device *dev, atomic_t *avail)
{ … }
static int cp2112_xfer_status(struct cp2112_device *dev)
{ … }
static int cp2112_read(struct cp2112_device *dev, u8 *data, size_t size)
{ … }
static int cp2112_read_req(void *buf, u8 slave_address, u16 length)
{ … }
static int cp2112_write_read_req(void *buf, u8 slave_address, u16 length,
u8 command, u8 *data, u8 data_length)
{ … }
static int cp2112_write_req(void *buf, u8 slave_address, u8 command, u8 *data,
u8 data_length)
{ … }
static int cp2112_i2c_write_req(void *buf, u8 slave_address, u8 *data,
u8 data_length)
{ … }
static int cp2112_i2c_write_read_req(void *buf, u8 slave_address,
u8 *addr, int addr_length,
int read_length)
{ … }
static int cp2112_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
int num)
{ … }
static int cp2112_xfer(struct i2c_adapter *adap, u16 addr,
unsigned short flags, char read_write, u8 command,
int size, union i2c_smbus_data *data)
{ … }
static u32 cp2112_functionality(struct i2c_adapter *adap)
{ … }
static const struct i2c_algorithm smbus_algorithm = …;
static int cp2112_get_usb_config(struct hid_device *hdev,
struct cp2112_usb_config_report *cfg)
{ … }
static int cp2112_set_usb_config(struct hid_device *hdev,
struct cp2112_usb_config_report *cfg)
{ … }
static void chmod_sysfs_attrs(struct hid_device *hdev);
#define CP2112_CONFIG_ATTR …
CP2112_CONFIG_ATTR(vendor_id, ({
u16 vid;
if (sscanf(buf, "%hi", &vid) != 1)
return -EINVAL;
cfg.vid = cpu_to_le16(vid);
cfg.mask = 0x01;
}), "0x%04x\n", le16_to_cpu(cfg.vid));
CP2112_CONFIG_ATTR(product_id, ({
u16 pid;
if (sscanf(buf, "%hi", &pid) != 1)
return -EINVAL;
cfg.pid = cpu_to_le16(pid);
cfg.mask = 0x02;
}), "0x%04x\n", le16_to_cpu(cfg.pid));
CP2112_CONFIG_ATTR(max_power, ({
int mA;
if (sscanf(buf, "%i", &mA) != 1)
return -EINVAL;
cfg.max_power = (mA + 1) / 2;
cfg.mask = 0x04;
}), "%u mA\n", cfg.max_power * 2);
CP2112_CONFIG_ATTR(power_mode, ({
if (sscanf(buf, "%hhi", &cfg.power_mode) != 1)
return -EINVAL;
cfg.mask = 0x08;
}), "%u\n", cfg.power_mode);
CP2112_CONFIG_ATTR(release_version, ({
if (sscanf(buf, "%hhi.%hhi", &cfg.release_major, &cfg.release_minor)
!= 2)
return -EINVAL;
cfg.mask = 0x10;
}), "%u.%u\n", cfg.release_major, cfg.release_minor);
#undef CP2112_CONFIG_ATTR
static ssize_t pstr_store(struct device *kdev, struct device_attribute *kattr,
const char *buf, size_t count, int number)
{ … }
static ssize_t pstr_show(struct device *kdev, struct device_attribute *kattr,
char *buf, int number)
{ … }
#define CP2112_PSTR_ATTR …
CP2112_PSTR_ATTR(manufacturer, CP2112_MANUFACTURER_STRING);
CP2112_PSTR_ATTR(product, CP2112_PRODUCT_STRING);
CP2112_PSTR_ATTR(serial, CP2112_SERIAL_STRING);
#undef CP2112_PSTR_ATTR
static const struct attribute_group cp2112_attr_group = …;
static void chmod_sysfs_attrs(struct hid_device *hdev)
{ … }
static void cp2112_gpio_irq_ack(struct irq_data *d)
{ … }
static void cp2112_gpio_irq_mask(struct irq_data *d)
{ … }
static void cp2112_gpio_irq_unmask(struct irq_data *d)
{ … }
static void cp2112_gpio_poll_callback(struct work_struct *work)
{ … }
static unsigned int cp2112_gpio_irq_startup(struct irq_data *d)
{ … }
static void cp2112_gpio_irq_shutdown(struct irq_data *d)
{ … }
static int cp2112_gpio_irq_type(struct irq_data *d, unsigned int type)
{ … }
static const struct irq_chip cp2112_gpio_irqchip = …;
static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
{ … }
static void cp2112_remove(struct hid_device *hdev)
{ … }
static int cp2112_raw_event(struct hid_device *hdev, struct hid_report *report,
u8 *data, int size)
{ … }
static struct hid_driver cp2112_driver = …;
module_hid_driver(…) …;
MODULE_DESCRIPTION(…) …;
MODULE_AUTHOR(…) …;
MODULE_LICENSE(…) …;