text: /*
   * Copyright 2020, Jérôme Duval, jerome.duval@gmail.com.
   * Distributed under the terms of the MIT License.
   */
  
  
  #include "I2CPrivate.h"
  
  
  I2CDevice::I2CDevice(device_node *node, I2CBus* bus, i2c_addr slaveAddress)
  	:
  	fNode(node),
  	fBus(bus),
  	fSlaveAddress(slaveAddress)
  {
  	CALLED();
  }
  
  
  I2CDevice::~I2CDevice()
  {
  }
  
  
  status_t
  I2CDevice::InitCheck()
  {
  	return B_OK;
  }
  
  
  status_t
  I2CDevice::ExecCommand(i2c_op op, const void *cmdBuffer,
  	size_t cmdLength, void* dataBuffer, size_t dataLength)
  {
  	CALLED();
  	return fBus->ExecCommand(op, fSlaveAddress, cmdBuffer, cmdLength,
  		dataBuffer, dataLength);
  }
  
  
  status_t
  I2CDevice::AcquireBus()
  {
  	CALLED();
  	return fBus->AcquireBus();
  }
  
  
  void
  I2CDevice::ReleaseBus()
  {
  	CALLED();
  	fBus->ReleaseBus();
  }
  
  
  static status_t
  i2c_init_device(device_node *node, void **_device)
  {
  	CALLED();
  	I2CBus* bus;
  
  	{
  		device_node *parent = gDeviceManager->get_parent_node(node);
  		gDeviceManager->get_driver(parent, NULL, (void **)&bus);
  		gDeviceManager->put_node(parent);
  	}
  
  	uint16 slaveAddress;
  	if (gDeviceManager->get_attr_uint16(node, I2C_DEVICE_SLAVE_ADDR_ITEM,
  		&slaveAddress, false) != B_OK) {
  		return B_ERROR;
  	}
  
  
  	I2CDevice *device = new(std::nothrow) I2CDevice(node, bus, slaveAddress);
  	if (device == NULL)
  		return B_NO_MEMORY;
  
  	status_t result = device->InitCheck();
  	if (result != B_OK) {
  		ERROR("failed to set up i2c device object\n");
  		return result;
  	}
  
  	*_device = device;
  
  	return B_OK;
  }
  
  
  static void
  i2c_uninit_device(void *_device)
  {
  	CALLED();
  	I2CDevice *device = (I2CDevice *)_device;
  	delete device;
  }
  
  
  static void
  i2c_device_removed(void *_device)
  {
  	CALLED();
  	//I2CDevice *device = (I2CDevice *)_device;
  }
  
  
  static status_t
  i2c_exec_command(i2c_device _device, i2c_op op, const void *cmdBuffer,
  	size_t cmdLength, void* dataBuffer, size_t dataLength)
  {
  	I2CDevice *device = (I2CDevice *)_device;
  	return device->ExecCommand(op, cmdBuffer, cmdLength, dataBuffer, dataLength);
  }
  
  
  static status_t
  i2c_acquire_bus(i2c_device _device)
  {
  	I2CDevice *device = (I2CDevice *)_device;
  	return device->AcquireBus();
  }
  
  
  static void
  i2c_release_bus(i2c_device _device)
  {
  	I2CDevice *device = (I2CDevice *)_device;
  	return device->ReleaseBus();
  }
  
  
  static status_t
  std_ops(int32 op, ...)
  {
  	switch (op) {
  		case B_MODULE_INIT:
  		{
  			// Link to I2C bus.
  			// I2C device driver must have I2C bus loaded, but it calls its
  			// functions directly instead via official interface, so this
  			// pointer is never read.
  			module_info *dummy;
  			return get_module(I2C_BUS_MODULE_NAME, &dummy);
  		}
  		case B_MODULE_UNINIT:
  			return put_module(I2C_BUS_MODULE_NAME);
  
  		default:
  			return B_ERROR;
  	}
  }
  
  
  i2c_device_interface gI2CDeviceModule = {
  	{
  		{
  			I2C_DEVICE_MODULE_NAME,
  			0,
  			std_ops
  		},
  
  		NULL,	// supported devices
  		NULL,	// register node
  		i2c_init_device,
  		(void (*)(void *)) i2c_uninit_device,
  		NULL,	// register child devices
  		NULL,	// rescan
  		(void (*)(void *)) i2c_device_removed
  	},
  	i2c_exec_command,
  	i2c_acquire_bus,
  	i2c_release_bus,
  };
  