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