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 I2CDevice::I2CDevice(device_node *node, I2CBus* bus, i2c_addr slaveAddress) 11 : 12 fNode(node), 13 fBus(bus), 14 fSlaveAddress(slaveAddress) 15 { 16 CALLED(); 17 } 18 19 20 I2CDevice::~I2CDevice() 21 { 22 } 23 24 25 status_t 26 I2CDevice::InitCheck() 27 { 28 return B_OK; 29 } 30 31 32 status_t 33 I2CDevice::ExecCommand(i2c_op op, const void *cmdBuffer, 34 size_t cmdLength, void* dataBuffer, size_t dataLength) 35 { 36 CALLED(); 37 return fBus->ExecCommand(op, fSlaveAddress, cmdBuffer, cmdLength, 38 dataBuffer, dataLength); 39 } 40 41 42 status_t 43 I2CDevice::AcquireBus() 44 { 45 CALLED(); 46 return fBus->AcquireBus(); 47 } 48 49 50 void 51 I2CDevice::ReleaseBus() 52 { 53 CALLED(); 54 fBus->ReleaseBus(); 55 } 56 57 58 static status_t 59 i2c_init_device(device_node *node, void **_device) 60 { 61 CALLED(); 62 I2CBus* bus; 63 64 { 65 device_node *parent = gDeviceManager->get_parent_node(node); 66 gDeviceManager->get_driver(parent, NULL, (void **)&bus); 67 gDeviceManager->put_node(parent); 68 } 69 70 uint16 slaveAddress; 71 if (gDeviceManager->get_attr_uint16(node, I2C_DEVICE_SLAVE_ADDR_ITEM, 72 &slaveAddress, false) != B_OK) { 73 return B_ERROR; 74 } 75 76 77 I2CDevice *device = new(std::nothrow) I2CDevice(node, bus, slaveAddress); 78 if (device == NULL) 79 return B_NO_MEMORY; 80 81 status_t result = device->InitCheck(); 82 if (result != B_OK) { 83 ERROR("failed to set up i2c device object\n"); 84 return result; 85 } 86 87 *_device = device; 88 89 return B_OK; 90 } 91 92 93 static void 94 i2c_uninit_device(void *_device) 95 { 96 CALLED(); 97 I2CDevice *device = (I2CDevice *)_device; 98 delete device; 99 } 100 101 102 static void 103 i2c_device_removed(void *_device) 104 { 105 CALLED(); 106 //I2CDevice *device = (I2CDevice *)_device; 107 } 108 109 110 static status_t 111 i2c_exec_command(i2c_device _device, i2c_op op, const void *cmdBuffer, 112 size_t cmdLength, void* dataBuffer, size_t dataLength) 113 { 114 I2CDevice *device = (I2CDevice *)_device; 115 return device->ExecCommand(op, cmdBuffer, cmdLength, dataBuffer, dataLength); 116 } 117 118 119 static status_t 120 i2c_acquire_bus(i2c_device _device) 121 { 122 I2CDevice *device = (I2CDevice *)_device; 123 return device->AcquireBus(); 124 } 125 126 127 static void 128 i2c_release_bus(i2c_device _device) 129 { 130 I2CDevice *device = (I2CDevice *)_device; 131 return device->ReleaseBus(); 132 } 133 134 135 static status_t 136 std_ops(int32 op, ...) 137 { 138 switch (op) { 139 case B_MODULE_INIT: 140 { 141 // Link to I2C bus. 142 // I2C device driver must have I2C bus loaded, but it calls its 143 // functions directly instead via official interface, so this 144 // pointer is never read. 145 module_info *dummy; 146 return get_module(I2C_BUS_MODULE_NAME, &dummy); 147 } 148 case B_MODULE_UNINIT: 149 return put_module(I2C_BUS_MODULE_NAME); 150 151 default: 152 return B_ERROR; 153 } 154 } 155 156 157 i2c_device_interface gI2CDeviceModule = { 158 { 159 { 160 I2C_DEVICE_MODULE_NAME, 161 0, 162 std_ops 163 }, 164 165 NULL, // supported devices 166 NULL, // register node 167 i2c_init_device, 168 (void (*)(void *)) i2c_uninit_device, 169 NULL, // register child devices 170 NULL, // rescan 171 (void (*)(void *)) i2c_device_removed 172 }, 173 i2c_exec_command, 174 i2c_acquire_bus, 175 i2c_release_bus, 176 }; 177