1 /*
2 * Copyright 2020, Jérôme Duval, jerome.duval@gmail.com.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7 #include "I2CPrivate.h"
8
9
I2CDevice(device_node * node,I2CBus * bus,i2c_addr slaveAddress)10 I2CDevice::I2CDevice(device_node *node, I2CBus* bus, i2c_addr slaveAddress)
11 :
12 fNode(node),
13 fBus(bus),
14 fSlaveAddress(slaveAddress)
15 {
16 CALLED();
17 }
18
19
~I2CDevice()20 I2CDevice::~I2CDevice()
21 {
22 }
23
24
25 status_t
InitCheck()26 I2CDevice::InitCheck()
27 {
28 return B_OK;
29 }
30
31
32 status_t
ExecCommand(i2c_op op,const void * cmdBuffer,size_t cmdLength,void * dataBuffer,size_t dataLength)33 I2CDevice::ExecCommand(i2c_op op, const void *cmdBuffer,
34 size_t cmdLength, void* dataBuffer, size_t dataLength)
35 {
36 CALLED();
37 return fBus->ExecCommand(op, fSlaveAddress, cmdBuffer, cmdLength,
38 dataBuffer, dataLength);
39 }
40
41
42 status_t
AcquireBus()43 I2CDevice::AcquireBus()
44 {
45 CALLED();
46 return fBus->AcquireBus();
47 }
48
49
50 void
ReleaseBus()51 I2CDevice::ReleaseBus()
52 {
53 CALLED();
54 fBus->ReleaseBus();
55 }
56
57
58 static status_t
i2c_init_device(device_node * node,void ** _device)59 i2c_init_device(device_node *node, void **_device)
60 {
61 CALLED();
62 I2CBus* bus;
63
64 {
65 device_node *parent = gDeviceManager->get_parent_node(node);
66 gDeviceManager->get_driver(parent, NULL, (void **)&bus);
67 gDeviceManager->put_node(parent);
68 }
69
70 uint16 slaveAddress;
71 if (gDeviceManager->get_attr_uint16(node, I2C_DEVICE_SLAVE_ADDR_ITEM,
72 &slaveAddress, false) != B_OK) {
73 return B_ERROR;
74 }
75
76
77 I2CDevice *device = new(std::nothrow) I2CDevice(node, bus, slaveAddress);
78 if (device == NULL)
79 return B_NO_MEMORY;
80
81 status_t result = device->InitCheck();
82 if (result != B_OK) {
83 ERROR("failed to set up i2c device object\n");
84 return result;
85 }
86
87 *_device = device;
88
89 return B_OK;
90 }
91
92
93 static void
i2c_uninit_device(void * _device)94 i2c_uninit_device(void *_device)
95 {
96 CALLED();
97 I2CDevice *device = (I2CDevice *)_device;
98 delete device;
99 }
100
101
102 static void
i2c_device_removed(void * _device)103 i2c_device_removed(void *_device)
104 {
105 CALLED();
106 //I2CDevice *device = (I2CDevice *)_device;
107 }
108
109
110 static status_t
i2c_exec_command(i2c_device _device,i2c_op op,const void * cmdBuffer,size_t cmdLength,void * dataBuffer,size_t dataLength)111 i2c_exec_command(i2c_device _device, i2c_op op, const void *cmdBuffer,
112 size_t cmdLength, void* dataBuffer, size_t dataLength)
113 {
114 I2CDevice *device = (I2CDevice *)_device;
115 return device->ExecCommand(op, cmdBuffer, cmdLength, dataBuffer, dataLength);
116 }
117
118
119 static status_t
i2c_acquire_bus(i2c_device _device)120 i2c_acquire_bus(i2c_device _device)
121 {
122 I2CDevice *device = (I2CDevice *)_device;
123 return device->AcquireBus();
124 }
125
126
127 static void
i2c_release_bus(i2c_device _device)128 i2c_release_bus(i2c_device _device)
129 {
130 I2CDevice *device = (I2CDevice *)_device;
131 return device->ReleaseBus();
132 }
133
134
135 static status_t
std_ops(int32 op,...)136 std_ops(int32 op, ...)
137 {
138 switch (op) {
139 case B_MODULE_INIT:
140 {
141 // Link to I2C bus.
142 // I2C device driver must have I2C bus loaded, but it calls its
143 // functions directly instead via official interface, so this
144 // pointer is never read.
145 module_info *dummy;
146 return get_module(I2C_BUS_MODULE_NAME, &dummy);
147 }
148 case B_MODULE_UNINIT:
149 return put_module(I2C_BUS_MODULE_NAME);
150
151 default:
152 return B_ERROR;
153 }
154 }
155
156
157 i2c_device_interface gI2CDeviceModule = {
158 {
159 {
160 I2C_DEVICE_MODULE_NAME,
161 0,
162 std_ops
163 },
164
165 NULL, // supported devices
166 NULL, // register node
167 i2c_init_device,
168 (void (*)(void *)) i2c_uninit_device,
169 NULL, // register child devices
170 NULL, // rescan
171 (void (*)(void *)) i2c_device_removed
172 },
173 i2c_exec_command,
174 i2c_acquire_bus,
175 i2c_release_bus,
176 };
177