Merge pull request #125 from vrahane/img_mgmt_erase_stop_dfu

cmd/img_mgmt: Call dfu stop cb on erase
diff --git a/README.md b/README.md
index 887f686..286f82d 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
 # mcumgr
 
-This is mcumgr, version 0.1.0
+This is mcumgr, version 0.2.0
 
 mcumgr is a management library for 32-bit MCUs.   The goal of mcumgr is to
 define a common management infrastructure with pluggable transport and encoding
diff --git a/cborattr/include/cborattr/cborattr.h b/cborattr/include/cborattr/cborattr.h
index 30e2612..d025e64 100644
--- a/cborattr/include/cborattr/cborattr.h
+++ b/cborattr/include/cborattr/cborattr.h
@@ -48,6 +48,7 @@
     CborAttrByteStringType,
     CborAttrTextStringType,
     CborAttrBooleanType,
+    CborAttrHalfFloatType,
     CborAttrFloatType,
     CborAttrDoubleType,
     CborAttrArrayType,
@@ -85,6 +86,9 @@
         struct {
             double *store;
         } reals;
+        struct{
+            uint16_t *store;
+        } halffloats;
         struct {
             bool *store;
         } booleans;
@@ -99,6 +103,7 @@
     union {
         long long int *integer;
         long long unsigned int *uinteger;
+        uint16_t *halffloat;
         double *real;
         float *fval;
         char *string;
@@ -116,6 +121,7 @@
         double real;
         bool boolean;
         float fval;
+        uint16_t halffloat;
     } dflt;
     size_t len;
     bool nodefault;
@@ -139,6 +145,7 @@
         long long unsigned int uinteger;
         double real;
         float fval;
+        uint16_t halffloat;
         const char *string;
         bool boolean;
         struct {
diff --git a/cborattr/src/cborattr.c b/cborattr/src/cborattr.c
index 31131b7..e5177d6 100644
--- a/cborattr/src/cborattr.c
+++ b/cborattr/src/cborattr.c
@@ -67,6 +67,11 @@
         }
 	break;
 #if FLOAT_SUPPORT
+    case CborAttrHalfFloatType:
+        if (ct == CborHalfFloatType) {
+            return 1;
+        }
+        break;
     case CborAttrFloatType:
         if (ct == CborFloatType) {
             return 1;
@@ -120,6 +125,9 @@
             targetaddr = (char *)&cursor->addr.uinteger[offset];
             break;
 #if FLOAT_SUPPORT
+        case CborAttrHalfFloatType:
+            targetaddr = (char *)&cursor->addr.halffloat[offset];
+            break;
         case CborAttrFloatType:
             targetaddr = (char *)&cursor->addr.fval[offset];
             break;
@@ -180,6 +188,9 @@
                     memcpy(lptr, &cursor->dflt.boolean, sizeof(bool));
                     break;
 #if FLOAT_SUPPORT
+                case CborAttrHalfFloatType:
+                    memcpy(lptr, &cursor->dflt.halffloat, sizeof(uint16_t));
+                    break;
                 case CborAttrFloatType:
                     memcpy(lptr, &cursor->dflt.fval, sizeof(float));
                     break;
@@ -261,6 +272,9 @@
                 err |= cbor_value_get_uint64(&cur_value, lptr);
                 break;
 #if FLOAT_SUPPORT
+            case CborAttrHalfFloatType:
+                err |= cbor_value_get_half_float(&cur_value, lptr);
+                break;
             case CborAttrFloatType:
                 err |= cbor_value_get_float(&cur_value, lptr);
                 break;
@@ -332,6 +346,10 @@
             err |= cbor_value_get_uint64(&elem, lptr);
             break;
 #if FLOAT_SUPPORT
+        case CborAttrHalfFloatType:
+            lptr = &arr->arr.halffloats.store[off];
+            err |= cbor_value_get_half_float(&elem, lptr);
+            break;
         case CborAttrFloatType:
         case CborAttrDoubleType:
             lptr = &arr->arr.reals.store[off];
@@ -491,6 +509,10 @@
         break;
 
 #if FLOAT_SUPPORT
+    case CborAttrHalfFloatType:
+        rc = cbor_encode_half_float(enc, &val->halffloat);
+        break;
+
     case CborAttrFloatType:
         rc = cbor_encode_float(enc, val->fval);
         break;
diff --git a/cmd/fs_mgmt/port/zephyr/src/zephyr_fs_mgmt.c b/cmd/fs_mgmt/port/zephyr/src/zephyr_fs_mgmt.c
index f3eb2e4..f63ae2b 100644
--- a/cmd/fs_mgmt/port/zephyr/src/zephyr_fs_mgmt.c
+++ b/cmd/fs_mgmt/port/zephyr/src/zephyr_fs_mgmt.c
@@ -49,6 +49,7 @@
     ssize_t bytes_read;
     int rc;
 
+    fs_file_t_init(&file);
     rc = fs_open(&file, path, FS_O_READ);
     if (rc != 0) {
         return MGMT_ERR_ENOENT;
@@ -123,6 +124,7 @@
         }
     }
 
+    fs_file_t_init(&file);
     rc = fs_open(&file, path, FS_O_CREATE | FS_O_WRITE);
     if (rc != 0) {
         return MGMT_ERR_EUNKNOWN;
diff --git a/cmd/img_mgmt/include/img_mgmt/img_mgmt.h b/cmd/img_mgmt/include/img_mgmt/img_mgmt.h
index 78e6ba5..0e4230b 100644
--- a/cmd/img_mgmt/include/img_mgmt/img_mgmt.h
+++ b/cmd/img_mgmt/include/img_mgmt/img_mgmt.h
@@ -74,6 +74,7 @@
 
 /** Represents an individual upload request. */
 struct img_mgmt_upload_req {
+    unsigned long long int image;   /* 0 by default */
     unsigned long long int off;     /* -1 if unspecified */
     unsigned long long int size;    /* -1 if unspecified */
     size_t data_len;
@@ -120,6 +121,11 @@
 void img_mgmt_register_group(void);
 
 /**
+ * @brief Unregisters the image management command handler group.
+ */ 
+void img_mgmt_unregister_group(void);
+
+/*
  * @brief Read info of an image give the slot number
  *
  * @param image_slot     Image slot to read info from
diff --git a/cmd/img_mgmt/port/zephyr/src/zephyr_img_mgmt.c b/cmd/img_mgmt/port/zephyr/src/zephyr_img_mgmt.c
index d6169b8..777aad5 100644
--- a/cmd/img_mgmt/port/zephyr/src/zephyr_img_mgmt.c
+++ b/cmd/img_mgmt/port/zephyr/src/zephyr_img_mgmt.c
@@ -194,14 +194,16 @@
     bool empty;
     int rc;
 
-    rc = zephyr_img_mgmt_flash_check_empty(FLASH_AREA_ID(image_1),
-                                           &empty);
+    /* Select non-active slot */
+    const int best_id = img_mgmt_find_best_area_id();
+
+    rc = zephyr_img_mgmt_flash_check_empty(best_id, &empty);
     if (rc != 0) {
         return MGMT_ERR_EUNKNOWN;
     }
 
     if (!empty) {
-        rc = boot_erase_img_bank(FLASH_AREA_ID(image_1));
+        rc = boot_erase_img_bank(best_id);
         if (rc != 0) {
             return MGMT_ERR_EUNKNOWN;
         }
@@ -290,7 +292,7 @@
 			}
 		}
 #endif
-		rc = flash_img_init(ctx);
+		rc = flash_img_init_id(ctx, img_mgmt_find_best_area_id());
 
 		if (rc != 0) {
 			return MGMT_ERR_EUNKNOWN;
@@ -328,7 +330,7 @@
         goto end;
     }
 
-    rc = flash_area_open(FLASH_AREA_ID(image_1), &fa);
+    rc = flash_area_open(img_mgmt_find_best_area_id(), &fa);
     if (rc != 0) {
         LOG_ERR("Can't bind to the flash area (err %d)", rc);
         rc = MGMT_ERR_EUNKNOWN;
diff --git a/cmd/img_mgmt/src/img_mgmt.c b/cmd/img_mgmt/src/img_mgmt.c
index f66dc62..e938568 100644
--- a/cmd/img_mgmt/src/img_mgmt.c
+++ b/cmd/img_mgmt/src/img_mgmt.c
@@ -398,42 +398,49 @@
         .data_len = 0,
         .data_sha_len = 0,
         .upgrade = false,
+        .image = 0,
     };
 
     const struct cbor_attr_t off_attr[] = {
         [0] = {
+            .attribute = "image",
+            .type = CborAttrUnsignedIntegerType,
+            .addr.uinteger = &req.image,
+            .nodefault = true
+        },
+        [1] = {
             .attribute = "data",
             .type = CborAttrByteStringType,
             .addr.bytestring.data = req.img_data,
             .addr.bytestring.len = &req.data_len,
             .len = sizeof(req.img_data)
         },
-        [1] = {
+        [2] = {
             .attribute = "len",
             .type = CborAttrUnsignedIntegerType,
             .addr.uinteger = &req.size,
             .nodefault = true
         },
-        [2] = {
+        [3] = {
             .attribute = "off",
             .type = CborAttrUnsignedIntegerType,
             .addr.uinteger = &req.off,
             .nodefault = true
         },
-        [3] = {
+        [4] = {
             .attribute = "sha",
             .type = CborAttrByteStringType,
             .addr.bytestring.data = req.data_sha,
             .addr.bytestring.len = &req.data_sha_len,
             .len = sizeof(req.data_sha)
         },
-        [4] = {
+        [5] = {
             .attribute = "upgrade",
             .type = CborAttrBooleanType,
             .addr.boolean = &req.upgrade,
             .dflt.boolean = false,
         },
-        [5] = { 0 },
+        [6] = { 0 },
     };
     int rc;
     const char *errstr = NULL;
@@ -612,3 +619,9 @@
 {
     mgmt_register_group(&img_mgmt_group);
 }
+
+void
+img_mgmt_unregister_group(void)
+{
+    mgmt_unregister_group(&img_mgmt_group);
+}
diff --git a/cmd/img_mgmt/src/img_mgmt_state.c b/cmd/img_mgmt/src/img_mgmt_state.c
index ffbdd8e..3f291a4 100644
--- a/cmd/img_mgmt/src/img_mgmt_state.c
+++ b/cmd/img_mgmt/src/img_mgmt_state.c
@@ -46,32 +46,32 @@
     swap_type = img_mgmt_impl_swap_type();
     switch (swap_type) {
     case IMG_MGMT_SWAP_TYPE_NONE:
-        if (query_slot == 0) {
+        if (query_slot == IMG_MGMT_BOOT_CURR_SLOT) {
             flags |= IMG_MGMT_STATE_F_CONFIRMED;
             flags |= IMG_MGMT_STATE_F_ACTIVE;
         }
         break;
 
     case IMG_MGMT_SWAP_TYPE_TEST:
-        if (query_slot == 0) {
+        if (query_slot == IMG_MGMT_BOOT_CURR_SLOT) {
             flags |= IMG_MGMT_STATE_F_CONFIRMED;
-        } else if (query_slot == 1) {
+        } else {
             flags |= IMG_MGMT_STATE_F_PENDING;
         }
         break;
 
     case IMG_MGMT_SWAP_TYPE_PERM:
-        if (query_slot == 0) {
+        if (query_slot == IMG_MGMT_BOOT_CURR_SLOT) {
             flags |= IMG_MGMT_STATE_F_CONFIRMED;
-        } else if (query_slot == 1) {
+        } else {
             flags |= IMG_MGMT_STATE_F_PENDING | IMG_MGMT_STATE_F_PERMANENT;
         }
         break;
 
     case IMG_MGMT_SWAP_TYPE_REVERT:
-        if (query_slot == 0) {
+        if (query_slot == IMG_MGMT_BOOT_CURR_SLOT) {
             flags |= IMG_MGMT_STATE_F_ACTIVE;
-        } else if (query_slot == 1) {
+        } else {
             flags |= IMG_MGMT_STATE_F_CONFIRMED;
         }
         break;
@@ -79,7 +79,7 @@
 
     /* Slot 0 is always active. */
     /* XXX: The slot 0 assumption only holds when running from flash. */
-    if (query_slot == 0) {
+    if (query_slot == IMG_MGMT_BOOT_CURR_SLOT) {
         flags |= IMG_MGMT_STATE_F_ACTIVE;
     }
 
@@ -143,18 +143,19 @@
 
 done:
     /* Log the image hash if we know it. */
-    rc = img_mgmt_read_info(slot, NULL, hash, NULL);
-    if (rc != 0) {
+    if (img_mgmt_read_info(slot, NULL, hash, NULL)) {
         hashp = NULL;
     } else {
         hashp = hash;
     }
 
     if (permanent) {
-        return img_mgmt_impl_log_confirm(rc, hashp);
+        (void) img_mgmt_impl_log_confirm(rc, hashp);
     } else {
-        return img_mgmt_impl_log_pending(rc, hashp);
+        (void) img_mgmt_impl_log_pending(rc, hashp);
     }
+
+    return rc;
 }
 
 /**
@@ -300,7 +301,7 @@
     /* Determine which slot is being operated on. */
     if (hash_len == 0) {
         if (confirm) {
-            slot = 0;
+            slot = IMG_MGMT_BOOT_CURR_SLOT;
         } else {
             /* A 'test' without a hash is invalid. */
             return MGMT_ERR_EINVAL;
@@ -312,7 +313,7 @@
         }
     }
 
-    if (slot == 0 && confirm) {
+    if (slot == IMG_MGMT_BOOT_CURR_SLOT && confirm) {
         /* Confirm current setup. */
         rc = img_mgmt_state_confirm();
     } else {
diff --git a/mgmt/include/mgmt/mgmt.h b/mgmt/include/mgmt/mgmt.h
index 7ad22df..cb7e896 100644
--- a/mgmt/include/mgmt/mgmt.h
+++ b/mgmt/include/mgmt/mgmt.h
@@ -367,6 +367,14 @@
 void mgmt_register_group(struct mgmt_group *group);
 
 /**
+ * @brief Unregisters a full command group.
+ *
+ * @param group                 The group to register.
+ */
+void
+mgmt_unregister_group(struct mgmt_group *group);
+
+/**
  * @brief Finds a registered command handler.
  *
  * @param group_id              The group of the command to find.
diff --git a/mgmt/src/mgmt.c b/mgmt/src/mgmt.c
index 08343bb..361211a 100644
--- a/mgmt/src/mgmt.c
+++ b/mgmt/src/mgmt.c
@@ -71,6 +71,35 @@
     streamer->cfg->free_buf(buf, streamer->cb_arg);
 }
 
+void
+mgmt_unregister_group(struct mgmt_group *group)
+{
+    struct mgmt_group *curr = mgmt_group_list, *prev = NULL;
+
+    if (!group) {
+        return;
+    }
+
+    if (curr == group) {
+        mgmt_group_list = curr->mg_next;
+        return;
+    }
+
+    while (curr && curr != group) {
+        prev = curr;
+        curr = curr->mg_next;
+    }
+
+    if (!prev || !curr) {
+        return;
+    }
+
+    prev->mg_next = curr->mg_next;
+    if (curr->mg_next == NULL) {
+        mgmt_group_list_end = curr;
+    }
+}
+
 static struct mgmt_group *
 mgmt_find_group(uint16_t group_id, uint16_t command_id)
 {
diff --git a/repository.yml b/repository.yml
index 43006fc..c8917dd 100644
--- a/repository.yml
+++ b/repository.yml
@@ -21,7 +21,8 @@
 repo.versions:
     "0.0.0": "master"
     "0.1.0": "mcumgr_0_1_0_tag"
+    "0.2.0": "mcumgr_0_2_0_tag"
 
 
     "0-dev": "0.0.0"       # master
-    "0-latest": "0.1.0"    # latest release
+    "0-latest": "0.2.0"    # latest release
diff --git a/samples/smp_svr/zephyr/prj.conf b/samples/smp_svr/zephyr/prj.conf
index fe7fdcd..ce0551b 100644
--- a/samples/smp_svr/zephyr/prj.conf
+++ b/samples/smp_svr/zephyr/prj.conf
@@ -8,7 +8,8 @@
 CONFIG_BOOTLOADER_MCUBOOT=y
 
 # Allow for large Bluetooth data packets.
-CONFIG_BT_L2CAP_TX_MTU=260
+CONFIG_BT_L2CAP_TX_MTU=252
+CONFIG_BT_L2CAP_RX_MTU=252
 CONFIG_BT_RX_BUF_LEN=260
 
 # Enable the Bluetooth (unauthenticated) and shell mcumgr transports.
diff --git a/samples/smp_svr/zephyr/prj_tiny.conf b/samples/smp_svr/zephyr/prj_tiny.conf
index 9f526ba..c53800d 100644
--- a/samples/smp_svr/zephyr/prj_tiny.conf
+++ b/samples/smp_svr/zephyr/prj_tiny.conf
@@ -12,7 +12,8 @@
 CONFIG_BOOTLOADER_MCUBOOT=y
 
 # Allow for large Bluetooth data packets.
-CONFIG_BT_L2CAP_TX_MTU=260
+CONFIG_BT_L2CAP_TX_MTU=252
+CONFIG_BT_L2CAP_RX_MTU=252
 CONFIG_BT_RX_BUF_LEN=260
 
 # Enable the Bluetooth (unauthenticated) and UART mcumgr transports.