1 /* 2 * Copyright (c) 2006-2018, RT-Thread Development Team 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 * 6 * Change Logs: 7 * Date Author Notes 8 * 2017-07-14 aubr.cool 1st version 9 */ 10 #include <rtthread.h> 11 #include <rtdevice.h> 12 #include "fm24clxx.h" 13 14 struct fm24clxx_device 15 { 16 struct rt_device parent; 17 struct rt_i2c_bus_device *bus; 18 }; 19 20 /* RT-Thread device interface */ 21 22 static rt_err_t fm24clxx_init(rt_device_t dev) 23 { 24 return RT_EOK; 25 } 26 static rt_err_t fm24clxx_open(rt_device_t dev, rt_uint16_t oflag) 27 { 28 return RT_EOK; 29 } 30 31 static rt_err_t fm24clxx_close(rt_device_t dev) 32 { 33 return RT_EOK; 34 } 35 36 static rt_err_t fm24clxx_control(rt_device_t dev, int cmd, void *args) 37 { 38 return RT_EOK; 39 } 40 41 static rt_size_t fm24clxx_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) 42 { 43 struct fm24clxx_device *fm24clxx; 44 const struct fm24clxx_config *cfg; 45 struct rt_i2c_msg msg[2]; 46 rt_uint8_t mem_addr[2] = {0,}; 47 rt_size_t ret = 0; 48 RT_ASSERT(dev != 0); 49 50 fm24clxx = (struct fm24clxx_device *) dev; 51 52 RT_ASSERT(fm24clxx->parent.user_data != 0); 53 cfg = (const struct fm24clxx_config *) fm24clxx->parent.user_data; 54 55 if(pos > cfg->size) 56 { 57 return 0; 58 } 59 60 if(pos + size > cfg->size) 61 { 62 size = cfg->size - pos; 63 } 64 65 msg[0].addr = cfg->addr; 66 msg[0].flags = cfg->flags | RT_I2C_WR; 67 mem_addr[0] = (pos >> 8); 68 mem_addr[1] = (rt_uint8_t) pos; 69 msg[0].buf = (rt_uint8_t *) mem_addr; 70 msg[0].len = 2; 71 72 msg[1].addr = cfg->addr; 73 msg[1].flags = cfg->flags | RT_I2C_RD; 74 msg[1].buf = (rt_uint8_t *) buffer; 75 msg[1].len = size; 76 77 ret = rt_i2c_transfer(fm24clxx->bus, msg, 2); 78 return (ret == 2) ? size : 0; 79 } 80 81 static rt_size_t fm24clxx_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) 82 { 83 struct fm24clxx_device *fm24clxx; 84 const struct fm24clxx_config *cfg; 85 struct rt_i2c_msg msg[2]; 86 rt_uint8_t mem_addr[2] = {0,}; 87 rt_size_t ret = 0; 88 RT_ASSERT(dev != 0); 89 90 fm24clxx = (struct fm24clxx_device *) dev; 91 92 RT_ASSERT(fm24clxx->parent.user_data != 0); 93 cfg = (const struct fm24clxx_config *) fm24clxx->parent.user_data; 94 95 if(pos > cfg->size) 96 { 97 return 0; 98 } 99 100 if(pos + size > cfg->size) 101 { 102 size = cfg->size - pos; 103 } 104 105 msg[0].addr = cfg->addr; 106 msg[0].flags = cfg->flags | RT_I2C_WR; 107 mem_addr[0] = (pos >> 8); 108 mem_addr[1] = (rt_uint8_t) pos; 109 msg[0].buf = (rt_uint8_t *) mem_addr; 110 msg[0].len = 2; 111 112 msg[1].addr = cfg->addr; 113 msg[1].flags = cfg->flags | RT_I2C_WR | RT_I2C_NO_START; 114 msg[1].buf = (rt_uint8_t *) buffer; 115 msg[1].len = size; 116 117 ret = rt_i2c_transfer(fm24clxx->bus, msg, 2); 118 return (ret == 2) ? size : 0; 119 } 120 121 #ifdef RT_USING_DEVICE_OPS 122 const static struct rt_device fm24clxx_ops = 123 { 124 fm24clxx_init, 125 fm24clxx_open, 126 fm24clxx_close, 127 fm24clxx_read, 128 fm24clxx_write, 129 fm24clxx_control 130 }; 131 #endif 132 133 rt_err_t fm24clxx_register(const char *fm_device_name, const char *i2c_bus, void *user_data) 134 { 135 static struct fm24clxx_device fm24clxx_drv; 136 struct rt_i2c_bus_device *bus; 137 138 bus = rt_i2c_bus_device_find(i2c_bus); 139 if (bus == RT_NULL) 140 { 141 return RT_ENOSYS; 142 } 143 144 fm24clxx_drv.bus = bus; 145 fm24clxx_drv.parent.type = RT_Device_Class_Block; 146 #ifdef RT_USING_DEVICE_OPS 147 fm24clxx_drv.parent.ops = &fm24clxx_ops; 148 #else 149 fm24clxx_drv.parent.init = fm24clxx_init; 150 fm24clxx_drv.parent.open = fm24clxx_open; 151 fm24clxx_drv.parent.close = fm24clxx_close; 152 fm24clxx_drv.parent.read = fm24clxx_read; 153 fm24clxx_drv.parent.write = fm24clxx_write; 154 fm24clxx_drv.parent.control = fm24clxx_control; 155 #endif 156 157 fm24clxx_drv.parent.user_data = user_data; 158 159 return rt_device_register(&fm24clxx_drv.parent, fm_device_name, RT_DEVICE_FLAG_RDWR); 160 }