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 // connection 61 { I2C_DEVICE_SLAVE_ADDR_ITEM, B_UINT16_TYPE, { ui16: slaveAddress }}, 62 63 // description of peripheral drivers 64 { B_DEVICE_BUS, B_STRING_TYPE, { string: "i2c" }}, 65 66 { B_DEVICE_FLAGS, B_UINT32_TYPE, { ui32: B_FIND_MULTIPLE_CHILDREN }}, 67 68 { ACPI_DEVICE_HID_ITEM, B_STRING_TYPE, { string: hid }}, 69 70 { ACPI_DEVICE_CID_ITEM, B_STRING_TYPE, { string: cid[0] }}, 71 72 { ACPI_DEVICE_HANDLE_ITEM, B_UINT64_TYPE, { ui64: (addr_t)acpiHandle }}, 73 74 { NULL } 75 }; 76 77 return gDeviceManager->register_node(fNode, I2C_DEVICE_MODULE_NAME, attrs, 78 NULL, NULL); 79 } 80 81 82 status_t 83 I2CBus::Scan() 84 { 85 CALLED(); 86 if (fController->scan_bus != NULL) 87 fController->scan_bus(fCookie); 88 return B_OK; 89 } 90 91 92 status_t 93 I2CBus::AcquireBus() 94 { 95 CALLED(); 96 if (fController->acquire_bus != NULL) 97 return fController->acquire_bus(fCookie); 98 return B_OK; 99 } 100 101 102 void 103 I2CBus::ReleaseBus() 104 { 105 CALLED(); 106 if (fController->release_bus != NULL) 107 fController->release_bus(fCookie); 108 } 109 110 111 static status_t 112 i2c_init_bus(device_node *node, void **_bus) 113 { 114 CALLED(); 115 uint8 pathID; 116 if (gDeviceManager->get_attr_uint8(node, I2C_BUS_PATH_ID_ITEM, &pathID, 117 false) != B_OK) { 118 return B_ERROR; 119 } 120 121 I2CBus *bus = new(std::nothrow) I2CBus(node, pathID); 122 if (bus == NULL) 123 return B_NO_MEMORY; 124 125 status_t result = bus->InitCheck(); 126 if (result != B_OK) { 127 ERROR("failed to set up i2c bus object\n"); 128 return result; 129 } 130 131 *_bus = bus; 132 133 char name[128]; 134 snprintf(name, sizeof(name), "bus/i2c/%d/bus_raw", pathID); 135 136 return gDeviceManager->publish_device(node, name, I2C_BUS_RAW_MODULE_NAME); 137 } 138 139 140 static void 141 i2c_uninit_bus(void *_bus) 142 { 143 CALLED(); 144 I2CBus *bus = (I2CBus *)_bus; 145 delete bus; 146 } 147 148 149 static status_t 150 i2c_scan_bus(void *_bus) 151 { 152 I2CBus *bus = (I2CBus *)_bus; 153 return bus->Scan(); 154 } 155 156 157 status_t 158 i2c_bus_exec_command(void* _bus, i2c_op op, i2c_addr slaveAddress, 159 const void *cmdBuffer, size_t cmdLength, void* dataBuffer, 160 size_t dataLength) 161 { 162 CALLED(); 163 I2CBus* bus = (I2CBus*)_bus; 164 return bus->ExecCommand(op, slaveAddress, cmdBuffer, cmdLength, 165 dataBuffer, dataLength); 166 } 167 168 169 static status_t 170 i2c_bus_acquire_bus(void* _bus) 171 { 172 CALLED(); 173 I2CBus* bus = (I2CBus*)_bus; 174 return bus->AcquireBus(); 175 } 176 177 178 static void 179 i2c_bus_release_bus(void* _bus) 180 { 181 CALLED(); 182 I2CBus* bus = (I2CBus*)_bus; 183 return bus->ReleaseBus(); 184 } 185 186 187 static status_t 188 std_ops(int32 op, ...) 189 { 190 switch (op) { 191 case B_MODULE_INIT: 192 case B_MODULE_UNINIT: 193 return B_OK; 194 195 default: 196 break; 197 } 198 199 return B_ERROR; 200 } 201 202 203 i2c_bus_interface gI2CBusModule = { 204 { 205 { 206 I2C_BUS_MODULE_NAME, 207 0, 208 std_ops 209 }, 210 211 NULL, // supported devices 212 NULL, // register node 213 i2c_init_bus, 214 i2c_uninit_bus, 215 i2c_scan_bus, // register child devices 216 NULL, // rescan 217 }, 218 219 i2c_bus_exec_command, 220 i2c_bus_acquire_bus, 221 i2c_bus_release_bus, 222 }; 223 224