[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [qemu-xen master] hw/i2c/bitbang_i2c: Handle NACKs from devices



commit 9706e0162d2405218fd7376ffdf13baed8569a4b
Author:     Peter Maydell <peter.maydell@xxxxxxxxxx>
AuthorDate: Mon Oct 24 19:12:29 2016 +0100
Commit:     Peter Maydell <peter.maydell@xxxxxxxxxx>
CommitDate: Mon Nov 7 10:01:15 2016 +0000

    hw/i2c/bitbang_i2c: Handle NACKs from devices
    
    If the guest attempts to talk to a nonexistent device over i2c,
    the i2c_start_transfer() function will return non-zero, indicating
    that the bus is signalling a NACK. Similarly, if the i2c_send()
    function returns nonzero then the target device returned a NACK.
    Handle this possibility in the bitbang_i2c code, by returning
    the state machine to the STOPPED state and returning the NACK
    bit to the guest.
    
    This bit of missing functionality was spotted by Coverity
    (it noticed that we weren't checking the return value from
    i2c_start_transfer()).
    
    Signed-off-by: Peter Maydell <peter.maydell@xxxxxxxxxx>
    Message-id: 1477332749-27098-1-git-send-email-peter.maydell@xxxxxxxxxx
---
 hw/i2c/bitbang_i2c.c | 19 +++++++++++++++----
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/hw/i2c/bitbang_i2c.c b/hw/i2c/bitbang_i2c.c
index d3a2989..8be88ee 100644
--- a/hw/i2c/bitbang_i2c.c
+++ b/hw/i2c/bitbang_i2c.c
@@ -130,14 +130,25 @@ int bitbang_i2c_set(bitbang_i2c_interface *i2c, int line, 
int level)
         return bitbang_i2c_ret(i2c, 1);
 
     case WAITING_FOR_ACK:
+    {
+        int ret;
+
         if (i2c->current_addr < 0) {
             i2c->current_addr = i2c->buffer;
             DPRINTF("Address 0x%02x\n", i2c->current_addr);
-            i2c_start_transfer(i2c->bus, i2c->current_addr >> 1,
-                               i2c->current_addr & 1);
+            ret = i2c_start_transfer(i2c->bus, i2c->current_addr >> 1,
+                                     i2c->current_addr & 1);
         } else {
             DPRINTF("Sent 0x%02x\n", i2c->buffer);
-            i2c_send(i2c->bus, i2c->buffer);
+            ret = i2c_send(i2c->bus, i2c->buffer);
+        }
+        if (ret) {
+            /* NACK (either addressing a nonexistent device, or the
+             * device we were sending to decided to NACK us).
+             */
+            DPRINTF("Got NACK\n");
+            bitbang_i2c_enter_stop(i2c);
+            return bitbang_i2c_ret(i2c, 1);
         }
         if (i2c->current_addr & 1) {
             i2c->state = RECEIVING_BIT7;
@@ -145,7 +156,7 @@ int bitbang_i2c_set(bitbang_i2c_interface *i2c, int line, 
int level)
             i2c->state = SENDING_BIT7;
         }
         return bitbang_i2c_ret(i2c, 0);
-
+    }
     case RECEIVING_BIT7:
         i2c->buffer = i2c_recv(i2c->bus);
         DPRINTF("RX byte 0x%02x\n", i2c->buffer);
--
generated by git-patchbot for /home/xen/git/qemu-xen.git#master

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
https://lists.xenproject.org/xen-changelog

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.