[Feature][T8TSK-250][ADBD]add adb debug patch

Only Configure: No
Affected branch: GSW3.0-No-Connman
Affected module: adbd
Is it addected on both ZXIC and MTK: only MTK
Self-test: Yes
Doc Update: No

Change-Id: Id158d099ac8b9661a4fa1b51e731be951da56ed8
diff --git a/src/devtools/adb/usb_linux_client.c b/src/devtools/adb/usb_linux_client.c
index 2466275..da39951 100644
--- a/src/devtools/adb/usb_linux_client.c
+++ b/src/devtools/adb/usb_linux_client.c
@@ -58,6 +58,15 @@
 #define FFS_CONTOL_MAX_EPOLL_EVENT 50
 #define DEBUG   0
 
+#define USB_FFS_WAKE_LOCK_ID           "usb_adbd_wakelock"
+#define USB_FFS_WAKE_LOCK_TIMEOUT      (2 * 1000)
+
+static const char* sTag = "adbd_usb";
+adb_mutex_t g_wake_lock;
+timer_t g_wake_unlock_timer;
+bool g_wake_lock_acquired;
+typedef void (*timer_routine) (int id);
+
 struct usb_handle
 {
     adb_cond_t notify;
@@ -75,6 +84,7 @@
     int bulk_out; /* "out" from the host's perspective => source for adbd */
     int bulk_in;  /* "in" from the host's perspective => sink for adbd */
     bool ffs_control_thread_created;
+    bool ffs_control_suspend_mode;
 };
 
 static const struct {
@@ -312,10 +322,12 @@
     h->bulk_out = -1;
     h->control = -1;
     h->ffs_control_thread_created = false;
+    h->ffs_control_suspend_mode = false;
     h->fd = -1;
 
     adb_cond_init(&h->notify, 0);
     adb_mutex_init(&h->lock, 0);
+    adb_mutex_init(&g_wake_lock, 0);
 
     // Open the file /dev/android_adb_enable to trigger
     // the enabling of the adb USB function in the kernel.
@@ -335,6 +347,94 @@
     }
 }
 
+////////////////////// wake lock ///////////////////////////////
+timer_t timer_init(timer_routine cb, int id) {
+    struct sigevent sevp;
+    timer_t timerid;
+
+    memset(&sevp, 0, sizeof(sevp));
+    sevp.sigev_value.sival_int = id;
+    sevp.sigev_notify = SIGEV_THREAD;
+    sevp.sigev_notify_function = (void*)cb;
+
+    if(timer_create(CLOCK_BOOTTIME, &sevp, &timerid) == -1) {
+       D("timer_init() timer_create() failed, reason=[%s]%d",
+            strerror(errno), errno);
+        return NULL;
+    }
+    return timerid;
+}
+
+bool timer_start(timer_t timerid, int milliseconds) {
+    struct itimerspec expire;
+    expire.it_interval.tv_sec = 0;
+    expire.it_interval.tv_nsec = 0;
+    expire.it_value.tv_sec = milliseconds/1000;
+    expire.it_value.tv_nsec = (milliseconds%1000)*1000000;
+    if(timer_settime(timerid, 0, &expire, NULL) == -1) {
+        D("timer_start() timer_settime() failed, reason=[%s]%d", strerror(errno), errno);
+        return false;
+    }
+    return true;
+}
+
+bool timer_stop(timer_t timerid) {
+    return timer_start(timerid, 0);
+}
+
+bool usb_ffs_wake_lock() {
+#if !defined(__LBS_OS_LINUX__)    //no permission to open wake_lock on Linux
+    int fd = adb_open("/sys/power/wake_lock", O_RDWR | O_NONBLOCK);
+    if(fd == -1) {
+        D("[%s] open() failed, reason=[%s]%d", sTag, strerror(errno), errno);
+        return false;
+    }
+
+    int ret = adb_write(fd, USB_FFS_WAKE_LOCK_ID, strlen(USB_FFS_WAKE_LOCK_ID));
+    if(ret == -1) {
+        D("[%s] write() failed id=[%s], reason=[%s]%d", sTag, USB_FFS_WAKE_LOCK_ID, strerror(errno), errno);
+        adb_close(fd);
+        return false;
+    }
+
+    adb_close(fd);
+#endif
+    return true;
+}
+
+bool usb_ffs_wake_unlock() {
+#if !defined(__LBS_OS_LINUX__)    //no permission to open wake_lock on Linux
+    int fd = adb_open("/sys/power/wake_unlock", O_RDWR | O_NONBLOCK);
+    if(fd == -1) {
+        D("[%s] open() failed, reason=[%s]%d", sTag, strerror(errno), errno);
+        return false;
+    }
+
+    int ret = adb_write(fd, USB_FFS_WAKE_LOCK_ID, strlen(USB_FFS_WAKE_LOCK_ID));
+    if(ret == -1) {
+        D("[%s] write() failed id=[%s], reason=[%s]%d", sTag,
+                USB_FFS_WAKE_LOCK_ID, strerror(errno), errno);
+        adb_close(fd);
+        return false;
+    }
+
+    adb_close(fd);
+#endif
+    return true;
+}
+
+static void usb_ffs_timer_wake_unlock_routine(int id) {
+    //do not use the internal msg or it will cause infinite loop in epoll_wait
+    adb_mutex_lock(&g_wake_lock);
+    if(g_wake_lock_acquired) {
+        if(usb_ffs_wake_unlock()) {
+            g_wake_lock_acquired = false;
+        }
+    }
+    if (DEBUG) D("[%s] unlock wake_lock_acquired=[%d]", sTag, g_wake_lock_acquired);
+    adb_mutex_unlock(&g_wake_lock);
+}
+
 static void *ffs_control_read_msg_thread(void *_h)
 {
     usb_handle *h = _h;
@@ -404,6 +504,13 @@
     D("event.type: %s\n", ffs_get_event_type_code(event.type));
 
     switch (event.type) {
+        case FUNCTIONFS_SUSPEND:
+            D("received FUNCTIONFS_SUSPEND set suspend mode 1");
+            h->ffs_control_suspend_mode = true;
+            break;
+        case FUNCTIONFS_RESUME:
+            D("received FUNCTIONFS_RESUME");
+            break;
         case FUNCTIONFS_SETUP: {
             D("received FUNCTIONFS_SETUP");
             D("bRequestType = %d",(int)(event.u.setup.bRequestType));
@@ -460,6 +567,7 @@
     int control_fd = h->control;
     struct epoll_event events[FFS_CONTOL_MAX_EPOLL_EVENT];
 
+    g_wake_unlock_timer = timer_init(usb_ffs_timer_wake_unlock_routine, 0);
     int epfd = epoll_create(FFS_CONTOL_MAX_EPOLL_EVENT);
     if(epfd == -1) {
         D("ERR: epoll_create() fail reason=[%s]", strerror(errno));
@@ -475,6 +583,14 @@
         D("Before ffs control thread epoll_wait");
         n = epoll_wait(epfd, events, FFS_CONTOL_MAX_EPOLL_EVENT , -1);
 
+        adb_mutex_lock(&g_wake_lock);
+        timer_stop(g_wake_unlock_timer);
+        if (!g_wake_lock_acquired) {
+            g_wake_lock_acquired = usb_ffs_wake_lock();
+            if (DEBUG) D("[%s] wake_lock_acquired=[%d]", sTag, g_wake_lock_acquired);
+        }
+        adb_mutex_unlock(&g_wake_lock);
+
         for(i = 0; i < n; i++) {
             if(events[i].data.fd == control_fd) {
                 if(events[i].events & EPOLLIN) {
@@ -483,6 +599,8 @@
                 }
             }
         }
+
+        timer_start(g_wake_unlock_timer, USB_FFS_WAKE_LOCK_TIMEOUT);
     }
 }
 
@@ -646,11 +764,22 @@
 
     D("about to read (fd=%d, len=%d)\n", h->bulk_out, len);
     n = bulk_read(h->bulk_out, data, len);
-    if (n != len) {
+    if (h->ffs_control_suspend_mode) {
+        if (n < 0) {
+            int ret_err  = -1 * errno;
+            D("Suspended bulk_read() ERROR: fd = %d, n = %d, errno = %d (%s) ret_err=%d\n",
+                h->bulk_out, n, errno, strerror(errno), ret_err);
+            return ret_err;
+        } else {
+            D("Suspended bulk_read: fd = %d, n = %d, errno = %d (%s) len:%d data:%s\n",
+                h->bulk_out, n, errno, strerror(errno), len, data);
+        }
+    } else if (n != len) {
         D("ERROR: fd = %d, n = %d, errno = %d (%s)\n",
             h->bulk_out, n, errno, strerror(errno));
         return -1;
     }
+    h->ffs_control_suspend_mode = false;
     D("[ done fd=%d ]\n", h->bulk_out);
     return 0;
 }
@@ -705,6 +834,7 @@
 
     adb_cond_init(&h->notify, 0);
     adb_mutex_init(&h->lock, 0);
+    adb_mutex_init(&g_wake_lock, 0);
 
     D("[ usb_init - starting thread ]\n");
     if (adb_thread_create(&tid, usb_ffs_open_thread, h)){