xref: /haiku/src/add-ons/kernel/bus_managers/i2c/I2CBus.cpp (revision 02354704729d38c3b078c696adc1bbbd33cbcf72)
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 
10 I2CBus::I2CBus(device_node *node, uint8 id)
11 	:
12 	fNode(node),
13 	fID(id),
14 	fController(NULL),
15 	fCookie(NULL)
16 {
17 	CALLED();
18 	device_node *parent = gDeviceManager->get_parent_node(node);
19 	status_t status = gDeviceManager->get_driver(parent,
20 		(driver_module_info **)&fController, &fCookie);
21 	gDeviceManager->put_node(parent);
22 
23 	if (status != B_OK)
24 		return;
25 
26 	fController->set_i2c_bus(fCookie, this);
27 
28 }
29 
30 
31 I2CBus::~I2CBus()
32 {
33 }
34 
35 
36 status_t
37 I2CBus::InitCheck()
38 {
39 	return B_OK;
40 }
41 
42 
43 status_t
44 I2CBus::ExecCommand(i2c_op op, i2c_addr slaveAddress, const void *cmdBuffer,
45 	size_t cmdLength, void* dataBuffer, size_t dataLength)
46 {
47 	CALLED();
48 	return fController->exec_command(fCookie, op, slaveAddress, cmdBuffer, cmdLength,
49 		dataBuffer, dataLength);
50 }
51 
52 
53 status_t
54 I2CBus::RegisterDevice(i2c_addr slaveAddress, char* hid, char** cid,
55 	acpi_handle acpiHandle)
56 {
57 	CALLED();
58 
59 	device_attr attrs[] = {
60 		{ B_DEVICE_PRETTY_NAME, B_STRING_TYPE, { string: "I2C device" }},
61 
62 		// connection
63 		{ I2C_DEVICE_SLAVE_ADDR_ITEM, B_UINT16_TYPE, { ui16: slaveAddress }},
64 
65 		// description of peripheral drivers
66 		{ B_DEVICE_BUS, B_STRING_TYPE, { string: "i2c" }},
67 
68 		{ B_DEVICE_FLAGS, B_UINT32_TYPE, { ui32: B_FIND_MULTIPLE_CHILDREN }},
69 
70 		{ ACPI_DEVICE_HID_ITEM, B_STRING_TYPE, { string: hid }},
71 
72 		{ ACPI_DEVICE_CID_ITEM, B_STRING_TYPE, { string: cid[0] }},
73 
74 		{ ACPI_DEVICE_HANDLE_ITEM, B_UINT64_TYPE, { ui64: (addr_t)acpiHandle }},
75 
76 		{ NULL }
77 	};
78 
79 	return gDeviceManager->register_node(fNode, I2C_DEVICE_MODULE_NAME, attrs,
80 		NULL, NULL);
81 }
82 
83 
84 status_t
85 I2CBus::Scan()
86 {
87 	CALLED();
88 	if (fController->scan_bus != NULL)
89 		fController->scan_bus(fCookie);
90 	return B_OK;
91 }
92 
93 
94 status_t
95 I2CBus::AcquireBus()
96 {
97 	CALLED();
98 	if (fController->acquire_bus != NULL)
99 		return fController->acquire_bus(fCookie);
100 	return B_OK;
101 }
102 
103 
104 void
105 I2CBus::ReleaseBus()
106 {
107 	CALLED();
108 	if (fController->release_bus != NULL)
109 		fController->release_bus(fCookie);
110 }
111 
112 
113 static status_t
114 i2c_init_bus(device_node *node, void **_bus)
115 {
116 	CALLED();
117 	uint8 pathID;
118 	if (gDeviceManager->get_attr_uint8(node, I2C_BUS_PATH_ID_ITEM, &pathID,
119 		false) != B_OK) {
120 		return B_ERROR;
121 	}
122 
123 	I2CBus *bus = new(std::nothrow) I2CBus(node, pathID);
124 	if (bus == NULL)
125 		return B_NO_MEMORY;
126 
127 	status_t result = bus->InitCheck();
128 	if (result != B_OK) {
129 		ERROR("failed to set up i2c bus object\n");
130 		return result;
131 	}
132 
133 	*_bus = bus;
134 
135 	char name[128];
136 	snprintf(name, sizeof(name), "bus/i2c/%d/bus_raw", pathID);
137 
138 	return gDeviceManager->publish_device(node, name, I2C_BUS_RAW_MODULE_NAME);
139 }
140 
141 
142 static void
143 i2c_uninit_bus(void *_bus)
144 {
145 	CALLED();
146 	I2CBus *bus = (I2CBus *)_bus;
147 	delete bus;
148 }
149 
150 
151 static status_t
152 i2c_scan_bus(void *_bus)
153 {
154 	I2CBus *bus = (I2CBus *)_bus;
155 	return bus->Scan();
156 }
157 
158 
159 status_t
160 i2c_bus_exec_command(void* _bus, i2c_op op, i2c_addr slaveAddress,
161 		const void *cmdBuffer, size_t cmdLength, void* dataBuffer,
162 		size_t dataLength)
163 {
164 	CALLED();
165 	I2CBus* bus = (I2CBus*)_bus;
166 	return bus->ExecCommand(op, slaveAddress, cmdBuffer, cmdLength,
167 		dataBuffer, dataLength);
168 }
169 
170 
171 static status_t
172 i2c_bus_acquire_bus(void* _bus)
173 {
174 	CALLED();
175 	I2CBus* bus = (I2CBus*)_bus;
176 	return bus->AcquireBus();
177 }
178 
179 
180 static void
181 i2c_bus_release_bus(void* _bus)
182 {
183 	CALLED();
184 	I2CBus* bus = (I2CBus*)_bus;
185 	return bus->ReleaseBus();
186 }
187 
188 
189 static status_t
190 std_ops(int32 op, ...)
191 {
192 	switch (op) {
193 		case B_MODULE_INIT:
194 		case B_MODULE_UNINIT:
195 			return B_OK;
196 
197 		default:
198 			break;
199 	}
200 
201 	return B_ERROR;
202 }
203 
204 
205 i2c_bus_interface gI2CBusModule = {
206 	{
207 		{
208 			I2C_BUS_MODULE_NAME,
209 			0,
210 			std_ops
211 		},
212 
213 		NULL, // supported devices
214 		NULL, // register node
215 		i2c_init_bus,
216 		i2c_uninit_bus,
217 		i2c_scan_bus, // register child devices
218 		NULL, // rescan
219 	},
220 
221 	i2c_bus_exec_command,
222 	i2c_bus_acquire_bus,
223 	i2c_bus_release_bus,
224 };
225 
226