Update project structure and README.md

Change-Id: Ia0d3f878163c9a1d850d750b0def972aae11970e
diff --git a/.gitignore b/.gitignore
index b61d9cf..f1bfc1a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,6 @@
 .distdir
 *.zip
 site/interpreter.*
-site/*.tflite
+site/models/*.tflite
 dfu-util
 
diff --git a/.gitmodules b/.gitmodules
index 452b66b..733e7e7 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,6 +1,6 @@
 [submodule "webdfu"]
-	path = webdfu
+	path = third_party/webdfu
 	url = https://github.com/devanlai/webdfu.git
 [submodule "libedgetpu"]
-	path = libedgetpu
+	path = third_party/libedgetpu
 	url = https://coral.googlesource.com/libedgetpu
diff --git a/Makefile b/Makefile
index 9729a88..6265c22 100644
--- a/Makefile
+++ b/Makefile
@@ -14,7 +14,7 @@
 MAKEFILE_DIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST))))
 TEST_DATA_URL := https://github.com/google-coral/edgetpu/raw/master/test_data
 
-.PHONY: wasm download zip server dfu-util
+.PHONY: wasm download zip server reset clean
 
 COMPILATION_MODE ?= dbg
 ifeq ($(filter $(COMPILATION_MODE),opt dbg),)
@@ -50,21 +50,23 @@
         "$(MAKEFILE_DIR)/site"
 
 %.tflite:
-	cd $(dir $@) && wget "$(TEST_DATA_URL)/$(notdir $@)"
+	mkdir -p $(dir $@) && cd $(dir $@) && wget "$(TEST_DATA_URL)/$(notdir $@)"
 
-download: site/mobilenet_v1_1.0_224_quant.tflite \
-          site/mobilenet_v1_1.0_224_quant_edgetpu.tflite \
-          site/ssd_mobilenet_v2_coco_quant_postprocess.tflite \
-          site/ssd_mobilenet_v2_coco_quant_postprocess_edgetpu.tflite \
-          site/ssd_mobilenet_v2_face_quant_postprocess.tflite \
-          site/ssd_mobilenet_v2_face_quant_postprocess_edgetpu.tflite
+download: site/models/mobilenet_v1_1.0_224_quant.tflite \
+          site/models/mobilenet_v1_1.0_224_quant_edgetpu.tflite \
+          site/models/ssd_mobilenet_v2_coco_quant_postprocess.tflite \
+          site/models/ssd_mobilenet_v2_coco_quant_postprocess_edgetpu.tflite \
+          site/models/ssd_mobilenet_v2_face_quant_postprocess.tflite \
+          site/models/ssd_mobilenet_v2_face_quant_postprocess_edgetpu.tflite
 
-dfu-util:
-	git clone git://git.code.sf.net/p/dfu-util/dfu-util || true
-	cd $(MAKEFILE_DIR)/dfu-util && ./autogen.sh && ./configure && make
+third_party/dfu-util/src/dfu-util:
+	git -C third_party clone git://git.code.sf.net/p/dfu-util/dfu-util || true
+	cd third_party/dfu-util && ./autogen.sh && ./configure && make
 
-reset:
-	$(MAKEFILE_DIR)/dfu-util/src/dfu-util -D $(MAKEFILE_DIR)/libedgetpu/driver/usb/apex_latest_single_ep.bin -d 1a6e:089a -R || true
+reset: third_party/dfu-util/src/dfu-util
+	third_party/dfu-util/src/dfu-util \
+    -D third_party/libedgetpu/driver/usb/apex_latest_single_ep.bin \
+    -d 1a6e:089a -R || true
 
 zip:
 	zip -r site.zip site
@@ -74,7 +76,7 @@
 
 clean:
 	rm -f $(MAKEFILE_DIR)/site/interpreter.* \
-        $(MAKEFILE_DIR)/site/*.tflite
+        $(MAKEFILE_DIR)/site/models/*.tflite
 
 ################################################################################
 # Docker commands
diff --git a/README.md b/README.md
index 558a81a..fd1c20f 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,83 @@
-#  WebCoral
+# WebCoral
 
-Firmware upload is done via webdfu
+This is a project to demonstrate how to access
+[Coral USB Accelerator](https://coral.ai/products/accelerator/) from
+Chrome browser using [WebUSB](https://wicg.github.io/webusb/).
+The demo works on Linux and macOS.
 
-emscripten_toolchain for Bazel is taken from
-https://github.com/emscripten-core/emsdk/tree/master/bazel/emscripten_toolchain
+## Web Server Setup
 
-libusb.cc -- universal shim, inspired by
+Clone this repo with submodules:
+```
+git clone --recurse-submodules https://github.com/google-coral/webcoral
+```
+
+Switch directory:
+```
+cd webcoral
+```
+
+Download `.tflite` model files to `site/models`:
+```
+make download
+```
+
+Build WASM files inside Docker container:
+```
+DOCKER_SHELL_COMMAND="make wasm" make docker-shell
+```
+
+Run local web server using python:
+```
+make server
+```
+
+Server is listening on port `8000`.
+
+## System Setup
+
+On **Linux** you need to install device rules to make Coral USB device
+visible in Chrome. You probably already have them installed if you are using
+Coral products. Just in case this repo has a bash script right for that:
+```
+scripts/linux_device_rules.sh install
+```
+and corresponding uninstall command if needed:
+```
+scripts/linux_device_rules.sh uninstall
+```
+
+On **macOS** you don't need to install anything.
+
+## Device Setup
+
+Coral USB accelerator doesn't have preinstalled firmware. If you run `lsusb`
+command right after plugging USB device in, you'll see
+```
+Bus 001 Device 008: ID 1a6e:089a Global Unichip Corp.
+```
+
+This means firmware is not flashed yet. It is possible to flash firmware
+directly from Chrome or from command line. Either way after flashing you'll see:
+```
+Bus 001 Device 009: ID 18d1:9302 Google Inc.
+```
+which means that device is ready to use.
+
+To flash firmware from command line:
+```
+make reset
+```
+
+To flash from Chrome browser, point it to http://localhost:8000/ and press
+`Flash Device Firmware` button. WARNING: this only works on Linux now.
+There is an [issue](https://crbug.com/1189418) on macOS. It is already fixed and
+the fix will be available in Chrome 91.
+
+## Demo
+
+Make sure the USB device was properly flashed. Choose the model you like to run
+and press `Initialize Interpreter` button. TPU model will require to select USB
+device in the dialog. CPU model will be ready immediately. At this moment you
+can run inference on any local image file by pressing `Choose Image File`
+button.
diff --git a/WORKSPACE b/WORKSPACE
index 99d1a0e..a11ccd9 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -16,8 +16,8 @@
 # Configure libedgetpu and downstream libraries (TF and Crosstool).
 new_local_repository(
     name = "libedgetpu",
-    path = "libedgetpu",
-    build_file = "libedgetpu/BUILD"
+    path = "third_party/libedgetpu",
+    build_file = "third_party/libedgetpu/BUILD"
 )
 
 TENSORFLOW_COMMIT = "ee728bcc18abef50b968c4b4cb06523f64abf7ac"
diff --git a/site/dfu.js b/site/dfu.js
index bfebfec..8d02b7f 120000
--- a/site/dfu.js
+++ b/site/dfu.js
@@ -1 +1 @@
-../webdfu/dfu-util/dfu.js
\ No newline at end of file
+../third_party/webdfu/dfu-util/dfu.js
\ No newline at end of file
diff --git a/site/dfuse.js b/site/dfuse.js
index 90f3af9..c710bcc 120000
--- a/site/dfuse.js
+++ b/site/dfuse.js
@@ -1 +1 @@
-../webdfu/dfu-util/dfuse.js
\ No newline at end of file
+../third_party/webdfu/dfu-util/dfuse.js
\ No newline at end of file
diff --git a/site/firmware.bin b/site/firmware.bin
index fe4459a..603c4a1 120000
--- a/site/firmware.bin
+++ b/site/firmware.bin
@@ -1 +1 @@
-../libedgetpu/driver/usb/apex_latest_single_ep.bin
\ No newline at end of file
+../third_party/libedgetpu/driver/usb/apex_latest_single_ep.bin
\ No newline at end of file
diff --git a/site/index.html b/site/index.html
index e8aa5a2..0e381b2 100644
--- a/site/index.html
+++ b/site/index.html
@@ -2,17 +2,17 @@
 <html>
   <head>
     <meta charset="UTF-8">
-    <title>Coral USB Accelerator Demo</title>
+    <title>Coral USB Accelerator + WebUSB</title>
     <script src="dfu.js"></script>
     <script src="dfuse.js"></script>
-    <script src="labels.js"></script>
+    <script src="models.js"></script>
     <script src="tflite.js"></script>
     <script src="interpreter.js"></script>
   </head>
   <body>
     <h1>Coral USB Accelerator Demo</h1>
     <button id="button-firmware">1. Flash Device Firmware</button>&nbsp;<span id="firmware-status"></span><br/><br/>
-    <button id="button-init">2. Initialize Device</button>
+    <button id="button-init">2. Initialize Interpreter</button>
     <select id="model">
       <option value="mobilenet_cpu">MobileNet V1 (CPU)</option>
       <option value="mobilenet_tpu">MobileNet V1 (TPU)</option>
@@ -28,41 +28,7 @@
     <br/><br/>
 
     <!--button id="test">Inference Test</button><br/><br/-->
-
     <script>
-      const models = {
-        'mobilenet_cpu': {
-          'url': '/mobilenet_v1_1.0_224_quant.tflite',
-          'type': 'classification',
-          'labels': imagenet_labels,
-        },
-        'mobilenet_tpu': {
-          'url': '/mobilenet_v1_1.0_224_quant_edgetpu.tflite',
-          'type': 'classification',
-          'labels': imagenet_labels,
-        },
-        'ssd_mobilenet_coco_cpu': {
-          'url': '/ssd_mobilenet_v2_coco_quant_postprocess.tflite',
-          'type': 'detection',
-          'labels': coco_labels,
-        },
-        'ssd_mobilenet_coco_tpu': {
-          'url': '/ssd_mobilenet_v2_coco_quant_postprocess_edgetpu.tflite',
-          'type': 'detection',
-          'labels': coco_labels,
-        },
-        'ssd_mobilenet_face_cpu': {
-          'url': '/ssd_mobilenet_v2_face_quant_postprocess.tflite',
-          'type': 'detection',
-          'labels': ['face'],
-        },
-        'ssd_mobilenet_face_tpu': {
-          'url': '/ssd_mobilenet_v2_face_quant_postprocess_edgetpu.tflite',
-          'type': 'detection',
-          'labels': ['face'],
-        },
-      };
-
       async function loadLocalImage(file) {
         return new Promise(resolve => {
           var reader = new FileReader();
@@ -189,7 +155,7 @@
         let model;
 
         document.querySelector("#button-init").addEventListener('click', async () => {
-          model = models[document.getElementById('model').value];
+          model = TFLITE_MODELS[document.getElementById('model').value];
           console.log(model);
           interpreter = new tflite.Interpreter();
           if (await interpreter.createFromBuffer(await loadFile(model.url))) {
diff --git a/site/labels.js b/site/models.js
similarity index 96%
rename from site/labels.js
rename to site/models.js
index b47648c..23ffb92 100644
--- a/site/labels.js
+++ b/site/models.js
@@ -14,7 +14,7 @@
  * limitations under the License.
  * =============================================================================
  */
-const imagenet_labels = [
+const IMAGENET_LABELS = [
   "background",
   "tench, Tinca tinca",
   "goldfish, Carassius auratus",
@@ -1018,7 +1018,7 @@
   "toilet tissue, toilet paper, bathroom tissue"
 ];
 
-const coco_labels = [
+const COCO_LABELS = [
   'person',
   'bicycle',
   'car',
@@ -1110,3 +1110,42 @@
   'hair drier',
   'toothbrush',
 ];
+
+const TFLITE_MODELS = {
+  'mobilenet_cpu': {
+    'url': '/models/mobilenet_v1_1.0_224_quant.tflite',
+    'type': 'classification',
+    'device': 'cpu',
+    'labels': IMAGENET_LABELS,
+  },
+  'mobilenet_tpu': {
+    'url': '/models/mobilenet_v1_1.0_224_quant_edgetpu.tflite',
+    'type': 'classification',
+    'device': 'tpu',
+    'labels': IMAGENET_LABELS,
+  },
+  'ssd_mobilenet_coco_cpu': {
+    'url': '/models/ssd_mobilenet_v2_coco_quant_postprocess.tflite',
+    'type': 'detection',
+    'device': 'cpu',
+    'labels': COCO_LABELS,
+  },
+  'ssd_mobilenet_coco_tpu': {
+    'url': '/models/ssd_mobilenet_v2_coco_quant_postprocess_edgetpu.tflite',
+    'type': 'detection',
+    'device': 'tpu',
+    'labels': COCO_LABELS,
+  },
+  'ssd_mobilenet_face_cpu': {
+    'url': '/models/ssd_mobilenet_v2_face_quant_postprocess.tflite',
+    'type': 'detection',
+    'device': 'cpu',
+    'labels': ['face'],
+  },
+  'ssd_mobilenet_face_tpu': {
+    'url': '/models/ssd_mobilenet_v2_face_quant_postprocess_edgetpu.tflite',
+    'type': 'detection',
+    'device': 'tpu',
+    'labels': ['face'],
+  },
+};
diff --git a/libedgetpu b/third_party/libedgetpu
similarity index 100%
rename from libedgetpu
rename to third_party/libedgetpu
diff --git a/webdfu b/third_party/webdfu
similarity index 100%
rename from webdfu
rename to third_party/webdfu