1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
|
/*
* DDC/CI bus driver
*
* Copyright (c) 2015 Christoph Grenz
*/
/*
* 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; either version 2 of the License, or (at your option)
* any later version.
*/
#ifndef _DDCCI_H
#define _DDCCI_H
#include <linux/mod_devicetable.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <linux/version.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 2, 0)
#define CSTRUCT const struct
#else
#define CSTRUCT struct
#endif
#define DDCCI_MODULE_PREFIX "ddcci:"
/* Special addresses */
/* default device address (even) */
#define DDCCI_DEFAULT_DEVICE_ADDR 0x6E
/* receiving host address for communication with default device address */
#define DDCCI_HOST_ADDR_EVEN 0x50
/* sending host address for communication with default device address */
#define DDCCI_HOST_ADDR_ODD 0x51
/* Command codes */
/* Identification Request */
#define DDCCI_COMMAND_ID 0xf1
/* Identification Reply */
#define DDCCI_REPLY_ID 0xe1
/* Capabilities Request */
#define DDCCI_COMMAND_CAPS 0xf3
/* Capabilities Reply */
#define DDCCI_REPLY_CAPS 0xe3
/* Quirks */
/* Device always responds with unset protocol flag */
#define DDCCI_QUIRK_NO_PFLAG BIT(1)
/* Device needs writing one byte at a time */
#define DDCCI_QUIRK_WRITE_BYTEWISE BIT(2)
/* Device repeats first byte on read */
#define DDCCI_QUIRK_SKIP_FIRST_BYTE BIT(3)
/* Flags */
#define DDCCI_FLAG_REMOVED BIT(1)
#define DDCCI_FLAG_DEPENDENT BIT(2)
#define DDCCI_FLAG_EXTERNAL BIT(3)
extern struct bus_type ddcci_bus_type;
struct ddcci_bus_drv_data;
/* struct ddcci_device_id - identifies DDC/CI devices for probing */
struct ddcci_device_id {
char prot[9];
char type[9];
char model[9];
char vendor[9];
char module[9];
kernel_ulong_t driver_data; /* Data private to the driver */
};
#define DDCCI_ANY_ID "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
/**
* struct ddcci_device - represent an DDC/CI device
* @outer_addr: Outer device address (I2C address << 1).
* @inner_addr: Inner device address.
* @flags: Device flags.
* @capabilities: Device capability string.
* @capabilities_len: Length of capability string.
* @i2c_client: Parent I2C device.
* @bus_drv_data: Driver internal data structure.
* @dev: Driver model device node for the slave.
* @cdev: Character device structure
* @cdev_sem: RW semaphore for exclusive access on character device.
* @prot: Device class ("protocol", from capability string)
* @type: Device subclass ("type", from capability string)
* @model: Device model (from capability string)
* @vendor: Device vendor (from identification command response)
* @module: Device module (from identification command response)
* @device_number: Device serial (from identification command response)
*/
struct ddcci_device {
unsigned short outer_addr;
unsigned short inner_addr;
int flags;
char *capabilities;
size_t capabilities_len;
struct i2c_client *i2c_client;
struct ddcci_bus_drv_data *bus_drv_data;
struct device dev;
struct cdev cdev;
struct rw_semaphore cdev_sem;
char prot[9];
char type[9];
char model[9];
char vendor[9];
char module[9];
int device_number;
};
#define to_ddcci_device(d) container_of(d, struct ddcci_device, dev)
/**
* struct ddcci_driver - represent an DDC/CI device driver
* @probe: Callback for device binding
* @remove: Callback for device unbinding
* @driver: Device driver model driver
* @id_table: List of DDC/CI devices supported by this driver
*
* The driver.owner field should be set to the module owner of this driver.
* The driver.name field should be set to the name of this driver.
*/
struct ddcci_driver {
int (*probe)(struct ddcci_device *, const struct ddcci_device_id *);
int (*remove)(struct ddcci_device *);
struct device_driver driver;
struct ddcci_device_id *id_table;
};
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 11, 0)
#define to_ddcci_driver(d) container_of_const(d, struct ddcci_driver, driver)
#define DDCCI_DRV_CONST const
#else
#define to_ddcci_driver(d) container_of(d, struct ddcci_driver, driver)
#define DDCCI_DRV_CONST
#endif
int ddcci_register_driver(struct module *owner, struct ddcci_driver *driver);
#define ddcci_add_driver(driver) \
ddcci_register_driver(THIS_MODULE, driver)
void ddcci_del_driver(struct ddcci_driver *driver);
struct ddcci_device *ddcci_verify_device(CSTRUCT device *dev);
#define module_ddcci_driver(__ddcci_driver) \
module_driver(__ddcci_driver, ddcci_add_driver, \
ddcci_del_driver)
int ddcci_device_write(struct ddcci_device *, bool p_flag, unsigned char *data,
unsigned char length);
int ddcci_device_read(struct ddcci_device *, bool p_flag, unsigned char *buffer,
unsigned char length);
int ddcci_device_writeread(struct ddcci_device *, bool p_flag,
unsigned char *buffer, unsigned char length,
unsigned char maxlength);
static inline void *ddcci_get_drvdata(const struct ddcci_device *dev)
{
return dev_get_drvdata(&dev->dev);
}
static inline void ddcci_set_drvdata(struct ddcci_device *dev, void *data)
{
dev_set_drvdata(&dev->dev, data);
}
unsigned long ddcci_quirks(struct ddcci_device *dev);
const char *ddcci_find_capstr_item(const char *capabilities, const char *tag,
size_t *length);
#endif
|