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
I2CBus(device_node * node,uint8 id)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
~I2CBus()31 I2CBus::~I2CBus()
32 {
33 }
34
35
36 status_t
InitCheck()37 I2CBus::InitCheck()
38 {
39 return B_OK;
40 }
41
42
43 status_t
ExecCommand(i2c_op op,i2c_addr slaveAddress,const void * cmdBuffer,size_t cmdLength,void * dataBuffer,size_t dataLength)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
RegisterDevice(i2c_addr slaveAddress,char * hid,char ** cid,acpi_handle acpiHandle)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
Scan()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
AcquireBus()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
ReleaseBus()105 I2CBus::ReleaseBus()
106 {
107 CALLED();
108 if (fController->release_bus != NULL)
109 fController->release_bus(fCookie);
110 }
111
112
113 static status_t
i2c_init_bus(device_node * node,void ** _bus)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
i2c_uninit_bus(void * _bus)143 i2c_uninit_bus(void *_bus)
144 {
145 CALLED();
146 I2CBus *bus = (I2CBus *)_bus;
147 delete bus;
148 }
149
150
151 static status_t
i2c_scan_bus(void * _bus)152 i2c_scan_bus(void *_bus)
153 {
154 I2CBus *bus = (I2CBus *)_bus;
155 return bus->Scan();
156 }
157
158
159 status_t
i2c_bus_exec_command(void * _bus,i2c_op op,i2c_addr slaveAddress,const void * cmdBuffer,size_t cmdLength,void * dataBuffer,size_t dataLength)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
i2c_bus_acquire_bus(void * _bus)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
i2c_bus_release_bus(void * _bus)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
std_ops(int32 op,...)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