summaryrefslogtreecommitdiff
path: root/drivers/i2c/i2c-api.c
diff options
context:
space:
mode:
authorSrikant Patnaik2015-01-11 12:28:04 +0530
committerSrikant Patnaik2015-01-11 12:28:04 +0530
commit871480933a1c28f8a9fed4c4d34d06c439a7a422 (patch)
tree8718f573808810c2a1e8cb8fb6ac469093ca2784 /drivers/i2c/i2c-api.c
parent9d40ac5867b9aefe0722bc1f110b965ff294d30d (diff)
downloadFOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.gz
FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.bz2
FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.zip
Moved, renamed, and deleted files
The original directory structure was scattered and unorganized. Changes are basically to make it look like kernel structure.
Diffstat (limited to 'drivers/i2c/i2c-api.c')
-rwxr-xr-xdrivers/i2c/i2c-api.c216
1 files changed, 216 insertions, 0 deletions
diff --git a/drivers/i2c/i2c-api.c b/drivers/i2c/i2c-api.c
new file mode 100755
index 00000000..d01335bb
--- /dev/null
+++ b/drivers/i2c/i2c-api.c
@@ -0,0 +1,216 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+
+#define I2C_API_FAKE_ADDR 0x7f
+#define I2C_MINORS 256
+
+struct i2c_api {
+ struct list_head list;
+ struct i2c_client *client;
+};
+
+static LIST_HEAD(i2c_api_list);
+static DEFINE_SPINLOCK(i2c_api_list_lock);
+
+static struct i2c_api *get_i2c_api(int bus_id)
+{
+ struct i2c_api *i2c_api;
+
+ spin_lock(&i2c_api_list_lock);
+ list_for_each_entry(i2c_api, &i2c_api_list, list) {
+ if (i2c_api->client->adapter->nr == bus_id)
+ goto found;
+ }
+ i2c_api = NULL;
+
+found:
+ spin_unlock(&i2c_api_list_lock);
+ return i2c_api;
+}
+
+static struct i2c_api *add_i2c_api(struct i2c_client *client)
+{
+ struct i2c_api *i2c_api;
+
+ if (client->adapter->nr >= I2C_MINORS) {
+ printk(KERN_ERR "i2c_api: Out of device minors (%d)\n",
+ client->adapter->nr);
+ return NULL;
+ }
+
+ i2c_api = kzalloc(sizeof(*i2c_api), GFP_KERNEL);
+ if (!i2c_api)
+ return NULL;
+ i2c_api->client = client;
+
+ spin_lock(&i2c_api_list_lock);
+ list_add_tail(&i2c_api->list, &i2c_api_list);
+ spin_unlock(&i2c_api_list_lock);
+ return i2c_api;
+}
+
+static void del_i2c_api(struct i2c_api *i2c_api)
+{
+ spin_lock(&i2c_api_list_lock);
+ list_del(&i2c_api->list);
+ spin_unlock(&i2c_api_list_lock);
+ kfree(i2c_api);
+}
+
+static int i2c_api_do_xfer(int bus_id, char chip_addr, char sub_addr, int mode,
+ char *buf, unsigned int size)
+{
+/** you could define more transfer mode here, implement it following. */
+#define I2C_API_XFER_MODE_SEND 0x0 /* standard send */
+#define I2C_API_XFER_MODE_RECV 0x1 /* standard receive */
+#define I2C_API_XFER_MODE_SEND_NO_SUBADDR 0x2 /* send without sub-address */
+#define I2C_API_XFER_MODE_RECV_NO_SUBADDR 0x3 /* receive without sub-address */
+
+ int ret = 0;
+ char *tmp;
+ struct i2c_api *i2c_api = get_i2c_api(bus_id);
+
+ if (!i2c_api)
+ return -ENODEV;
+
+ i2c_api->client->addr = chip_addr;
+ switch (mode) {
+ case I2C_API_XFER_MODE_SEND:
+ tmp = kmalloc(size + 1,GFP_KERNEL);
+ if (tmp == NULL)
+ return -ENOMEM;
+ tmp[0] = sub_addr;
+ memcpy(&tmp[1], buf, size);
+ ret = i2c_master_send(i2c_api->client, tmp, size + 1);
+ ret = (ret == size + 1) ? size : ret;
+ kfree(tmp);
+ break;
+
+ case I2C_API_XFER_MODE_RECV:
+ ret = i2c_master_send(i2c_api->client, &sub_addr, 1);
+ if (ret < 0)
+ return ret;
+ ret = i2c_master_recv(i2c_api->client, buf, size);
+ break;
+
+ case I2C_API_XFER_MODE_SEND_NO_SUBADDR:
+ ret = i2c_master_send(i2c_api->client, buf, size);
+ break;
+
+ case I2C_API_XFER_MODE_RECV_NO_SUBADDR:
+ ret = i2c_master_recv(i2c_api->client, buf, size);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+ return ret;
+}
+
+int i2c_api_do_send(int bus_id, char chip_addr, char sub_addr, char *buf, unsigned int size)
+{
+ return i2c_api_do_xfer(bus_id, chip_addr, sub_addr, I2C_API_XFER_MODE_SEND, buf, size);
+}
+
+int i2c_api_do_recv(int bus_id, char chip_addr, char sub_addr, char *buf, unsigned int size)
+{
+ return i2c_api_do_xfer(bus_id, chip_addr, sub_addr, I2C_API_XFER_MODE_RECV, buf, size);
+}
+
+int i2c_api_do_send_without_subaddr(int bus_id, char chip_addr, char *buf, unsigned int size)
+{
+ return i2c_api_do_xfer(bus_id, chip_addr, 0, I2C_API_XFER_MODE_SEND_NO_SUBADDR, buf, size);
+}
+
+int i2c_api_do_recv_without_subaddr(int bus_id, char chip_addr, char *buf, unsigned int size)
+{
+ return i2c_api_do_xfer(bus_id, chip_addr, 0, I2C_API_XFER_MODE_RECV_NO_SUBADDR, buf, size);
+}
+
+int i2c_api_attach(struct i2c_adapter *adap)
+{
+ struct i2c_board_info info;
+ struct i2c_client *client;
+
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ strlcpy(info.type, "i2c_api", I2C_NAME_SIZE);
+ info.addr = I2C_API_FAKE_ADDR;
+ client = i2c_new_device(adap, &info);
+ if (client)
+ add_i2c_api(client);
+ printk(KERN_INFO "i2c_api_attach adap[%d]\n", adap->nr);
+ return 0;
+}
+
+int i2c_api_detach(struct i2c_adapter *adap)
+{
+ struct i2c_api *i2c_api;
+
+ i2c_api = get_i2c_api(adap->nr);
+ if (i2c_api)
+ del_i2c_api(i2c_api);
+ return 0;
+}
+
+static const unsigned short normal_addr[] = { I2C_API_FAKE_ADDR, I2C_CLIENT_END };
+static const unsigned short ignore[] = { I2C_CLIENT_END };
+/*static struct i2c_client_address_data addr_data =
+{
+ .normal_i2c = normal_addr,
+ .probe = ignore,
+ .ignore = ignore,
+ .forces = NULL,
+};*/
+
+static const struct i2c_device_id id[] = {
+ {"I2C-API", 0},
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, id);
+
+static struct i2c_driver i2c_api_driver = {
+ .id_table = id,
+ .attach_adapter = i2c_api_attach,
+ .detach_adapter = i2c_api_detach,
+ .command = NULL,
+ .driver = {
+ .name = "I2C-API",
+ .owner = THIS_MODULE,
+ },
+ //.address_data = &addr_data,
+};
+
+static int __init i2c_api_init(void)
+{
+ int ret = i2c_add_driver(&i2c_api_driver);
+
+ if (ret) {
+ printk(KERN_ERR "[%s] Driver registration failed, module not inserted.\n", __func__);
+ return ret;
+ }
+
+ return 0 ;
+}
+
+static void __exit i2c_api_exit(void)
+{
+ i2c_del_driver(&i2c_api_driver);
+}
+
+MODULE_AUTHOR("Loon, <Loonzhong@wondermedia.com.cn>");
+MODULE_DESCRIPTION("I2C i2c_api Driver");
+MODULE_LICENSE("GPL");
+
+module_init(i2c_api_init);
+module_exit(i2c_api_exit);
+
+EXPORT_SYMBOL_GPL(i2c_api_do_send);
+EXPORT_SYMBOL_GPL(i2c_api_do_recv);
+EXPORT_SYMBOL_GPL(i2c_api_do_send_without_subaddr);
+EXPORT_SYMBOL_GPL(i2c_api_do_recv_without_subaddr);