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 10I2CBus::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 31I2CBus::~I2CBus() 32{ 33} 34 35 36status_t 37I2CBus::InitCheck() 38{ 39 return B_OK; 40} 41 42 43status_t 44I2CBus::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 53status_t 54I2CBus::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 84status_t 85I2CBus::Scan() 86{ 87 CALLED(); 88 if (fController->scan_bus != NULL) 89 fController->scan_bus(fCookie); 90 return B_OK; 91} 92 93 94status_t 95I2CBus::AcquireBus() 96{ 97 CALLED(); 98 if (fController->acquire_bus != NULL) 99 return fController->acquire_bus(fCookie); 100 return B_OK; 101} 102 103 104void 105I2CBus::ReleaseBus() 106{ 107 CALLED(); 108 if (fController->release_bus != NULL) 109 fController->release_bus(fCookie); 110} 111 112 113static status_t 114i2c_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 142static void 143i2c_uninit_bus(void *_bus) 144{ 145 CALLED(); 146 I2CBus *bus = (I2CBus *)_bus; 147 delete bus; 148} 149 150 151static status_t 152i2c_scan_bus(void *_bus) 153{ 154 I2CBus *bus = (I2CBus *)_bus; 155 return bus->Scan(); 156} 157 158 159status_t 160i2c_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 171static status_t 172i2c_bus_acquire_bus(void* _bus) 173{ 174 CALLED(); 175 I2CBus* bus = (I2CBus*)_bus; 176 return bus->AcquireBus(); 177} 178 179 180static void 181i2c_bus_release_bus(void* _bus) 182{ 183 CALLED(); 184 I2CBus* bus = (I2CBus*)_bus; 185 return bus->ReleaseBus(); 186} 187 188 189static status_t 190std_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 205i2c_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