structi2c_bus{i2c_slave*current_dev;i2c_slave*dev;};/* Create a new I2C bus. */i2c_bus*i2c_init_bus(void){i2c_bus*bus;bus=(i2c_bus*)qemu_mallocz(sizeof(i2c_bus));returnbus;}/* Create a new slave device. */i2c_slave*i2c_slave_init(i2c_bus*bus,intaddress,intsize){i2c_slave*dev;if(size<sizeof(i2c_slave))
dev=(i2c_slave*)qemu_mallocz(size);dev->address=address;dev->next=bus->dev;bus->dev=dev;returndev;}voidi2c_set_slave_address(i2c_slave*dev,intaddress){dev->address=address;}/* Return nonzero if bus is busy. */inti2c_bus_busy(i2c_bus*bus){returnbus->current_dev!=NULL;}
/* TODO: Make this handle multiple masters. */inti2c_start_transfer(i2c_bus*bus,intaddress,intrecv){i2c_slave*dev;for(dev=bus->dev;dev;dev=dev->next){if(dev->address==address)break;}if(!dev)return1;/*Ifthebusisalreadybusy,assumethisisarepeatedstartcondition.*/bus->current_dev=dev;dev->event(dev,recv?I2C_START_RECV:I2C_START_SEND);return0;}voidi2c_end_transfer(i2c_bus*bus){i2c_slave*dev=bus->current_dev;if(!dev)return;dev->event(dev,I2C_FINISH);bus->current_dev=NULL;}inti2c_send(i2c_bus*bus,uint8_tdata){i2c_slave*dev=bus->current_dev;if(!dev)return-1;returndev->send(dev,data);}inti2c_recv(i2c_bus*bus){i2c_slave*dev=bus->current_dev;if(!dev)return-1;returndev->recv(dev);}voidi2c_nack(i2c_bus*bus){i2c_slave*dev=bus->current_dev;if(!dev)return;dev->event(dev,I2C_NACK);}