You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by cc...@apache.org on 2016/11/08 22:55:02 UTC

[12/22] incubator-mynewt-core git commit: moved location to services from profiles

moved location to services from profiles


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/64b1cd98
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/64b1cd98
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/64b1cd98

Branch: refs/heads/develop
Commit: 64b1cd986c864006dc8e644a0e94788302157adc
Parents: 3440607
Author: Brian Giori <br...@gmail.com>
Authored: Mon Aug 1 17:11:54 2016 -0700
Committer: Brian Giori <br...@gmail.com>
Committed: Mon Aug 1 17:11:54 2016 -0700

----------------------------------------------------------------------
 .../ans/include/profiles/ans/ble_svc_ans.h      |  87 ----
 net/nimble/host/profiles/ans/pkg.yml            |  31 --
 net/nimble/host/profiles/ans/src/ble_svc_ans.c  | 467 -------------------
 .../ans/include/profiles/ans/ble_svc_ans.h      |  87 ++++
 net/nimble/host/services/ans/pkg.yml            |  31 ++
 net/nimble/host/services/ans/src/ble_svc_ans.c  | 467 +++++++++++++++++++
 6 files changed, 585 insertions(+), 585 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/64b1cd98/net/nimble/host/profiles/ans/include/profiles/ans/ble_svc_ans.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/profiles/ans/include/profiles/ans/ble_svc_ans.h b/net/nimble/host/profiles/ans/include/profiles/ans/ble_svc_ans.h
deleted file mode 100644
index eaf102a..0000000
--- a/net/nimble/host/profiles/ans/include/profiles/ans/ble_svc_ans.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#ifndef H_BLE_SVC_ANS_
-#define H_BLE_SVC_ANS_
-
-struct ble_hs_cfg;
-
-/* 16 Bit Alert Notification Service UUID */
-#define BLE_SVC_ANS_UUID16                                  0x1811
-
-/* 16 Bit Alert Notification Servivce Characteristic UUIDs */
-#define BLE_SVC_ANS_CHR_UUID16_SUP_NEW_ALERT_CAT            0x2a47
-#define BLE_SVC_ANS_CHR_UUID16_NEW_ALERT                    0x2a46
-#define BLE_SVC_ANS_CHR_UUID16_SUP_UNR_ALERT_CAT            0x2a48
-#define BLE_SVC_ANS_CHR_UUID16_UNR_ALERT_STAT               0x2a45
-#define BLE_SVC_ANS_CHR_UUID16_ALERT_NOT_CTRL_PT            0x2a44
-
-/* Alert Notification Service Category ID Bit Masks 
- *
- * TODO: Add remaining 2 optional categories */
-#define BLE_SVC_ANS_CAT_BM_NONE                             0x00
-#define BLE_SVC_ANS_CAT_BM_SIMPLE_ALERT                     0x01
-#define BLE_SVC_ANS_CAT_BM_EMAIL                            0x02
-#define BLE_SVC_ANS_CAT_BM_NEWS                             0x04
-#define BLE_SVC_ANS_CAT_BM_CALL                             0x08
-#define BLE_SVC_ANS_CAT_BM_MISSED_CALL                      0x10
-#define BLE_SVC_ANS_CAT_BM_SMS                              0x20
-#define BLE_SVC_ANS_CAT_BM_VOICE_MAIL                       0x40
-#define BLE_SVC_ANS_CAT_BM_SCHEDULE                         0x80    
-
-/* Alert Notification Service Category IDs
- *
- * TODO: Add remaining 2 optional categories */
-#define BLE_SVC_ANS_CAT_ID_SIMPLE_ALERT                     0
-#define BLE_SVC_ANS_CAT_ID_EMAIL                            1
-#define BLE_SVC_ANS_CAT_ID_NEWS                             2
-#define BLE_SVC_ANS_CAT_ID_CALL                             3
-#define BLE_SVC_ANS_CAT_ID_MISSED_CALL                      4
-#define BLE_SVC_ANS_CAT_ID_SMS                              5
-#define BLE_SVC_ANS_CAT_ID_VOICE_MAIL                       6
-#define BLE_SVC_ANS_CAT_ID_SCHEDULE                         7
-
-/* Number of valid ANS categories 
- *
- * TODO: Add remaining 2 optional categories */
-#define BLE_SVC_ANS_CAT_NUM                                 8
-
-/* Alert Notification Control Point Command IDs */
-#define BLE_SVC_ANS_CMD_EN_NEW_ALERT_CAT                    0
-#define BLE_SVC_ANS_CMD_EN_UNR_ALERT_CAT                    1
-#define BLE_SVC_ANS_CMD_DIS_NEW_ALERT_CAT                   2
-#define BLE_SVC_ANS_CMD_DIS_UNR_ALERT_CAT                   3
-#define BLE_SVC_ANS_CMD_NOT_NEW_ALERT_IMMEDIATE             4
-#define BLE_SVC_ANS_CMD_NOT_UNR_ALERT_IMMEDIATE             5
-
-/* Error Defeinitions */
-#define BLE_SVC_ANS_ERR_CMD_NOT_SUPPORTED                   0xA0
-
-void ble_svc_ans_on_gap_connect(uint16_t conn_handle);
-
-int ble_svc_ans_new_alert_add(uint8_t cat_id, 
-                              const char * info_str);
-int ble_svc_ans_unr_alert_add(uint8_t cat_id);
-
-int ble_svc_ans_init(struct ble_hs_cfg *cfg, 
-                     uint8_t initial_new_alert_cat,
-                     uint8_t initial_unr_alert_cat);
-
-#endif
-

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/64b1cd98/net/nimble/host/profiles/ans/pkg.yml
----------------------------------------------------------------------
diff --git a/net/nimble/host/profiles/ans/pkg.yml b/net/nimble/host/profiles/ans/pkg.yml
deleted file mode 100644
index 4cff8fd..0000000
--- a/net/nimble/host/profiles/ans/pkg.yml
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-# 
-#  http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-pkg.name: net/nimble/host/profiles/ans
-pkg.description: Alert Notification Service Server.
-pkg.author: "Apache Mynewt <de...@mynewt.incubator.apache.org>"
-pkg.homepage: "http://mynewt.apache.org/"
-pkg.keywords:
-    - ble 
-    - bluetooth
-    - ans 
-    - nimble 
-
-pkg.deps:
-    - net/nimble/host

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/64b1cd98/net/nimble/host/profiles/ans/src/ble_svc_ans.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/profiles/ans/src/ble_svc_ans.c b/net/nimble/host/profiles/ans/src/ble_svc_ans.c
deleted file mode 100644
index 2cebd8b..0000000
--- a/net/nimble/host/profiles/ans/src/ble_svc_ans.c
+++ /dev/null
@@ -1,467 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include <assert.h>
-#include <string.h>
-#include <math.h>
-#include "host/ble_hs.h"
-#include "host/ble_gap.h"
-#include "profiles/ans/ble_svc_ans.h"
-
-
-/* Max length of new alert info string */
-#define BLE_SVC_ANS_INFO_STR_MAX_LEN        18
-/* Max length of a new alert notification, max string length + 2 bytes
- * for category ID and count. */
-#define BLE_SVC_ANS_NEW_ALERT_MAX_LEN   (BLE_SVC_ANS_INFO_STR_MAX_LEN + 2)
-
-/* Supported categories bitmasks */
-static uint8_t ble_svc_ans_new_alert_cat;
-static uint8_t ble_svc_ans_unr_alert_cat; 
-
-/* Characteristic values */
-static uint8_t ble_svc_ans_new_alert_val[BLE_SVC_ANS_NEW_ALERT_MAX_LEN];
-static uint16_t ble_svc_ans_new_alert_val_len;
-static uint8_t ble_svc_ans_unr_alert_stat[2];
-static uint8_t ble_svc_ans_alert_not_ctrl_pt[2];
-
-/* Alert counts, one value for each category */
-static uint8_t ble_svc_ans_new_alert_cnt[BLE_SVC_ANS_CAT_NUM];
-static uint8_t ble_svc_ans_unr_alert_cnt[BLE_SVC_ANS_CAT_NUM];
-
-/* Charachteristic value handles */
-static uint16_t ble_svc_ans_new_alert_val_handle;
-static uint16_t ble_svc_ans_unr_alert_val_handle;
-
-/* Connection handle 
- *
- * TODO: In order to support multiple connections we would need to save
- *       the handles for every connection, not just the most recent. Then
- *       we would need to notify each connection when needed.
- * */
-static uint16_t ble_svc_ans_conn_handle;
-
-/* Access function */
-static int
-ble_svc_ans_access(uint16_t conn_handle, uint16_t attr_handle,
-                   struct ble_gatt_access_ctxt *ctxt, void *arg);
-
-/* Notify new alert */
-static int
-ble_svc_ans_new_alert_notify(uint8_t cat_id, const char * info_str);
-
-/* Notify unread alert */
-static int
-ble_svc_ans_unr_alert_notify(uint8_t cat_id);
-
-/* Save written value to local characteristic value */
-static int
-ble_svc_ans_chr_write(struct os_mbuf *om, uint16_t min_len, uint16_t max_len, 
-                      void *dst, uint16_t *len);
-
-static const struct ble_gatt_svc_def ble_svc_ans_defs[] = {
-    {
-        /*** Alert Notification Service. */
-        .type = BLE_GATT_SVC_TYPE_PRIMARY,
-        .uuid128 = BLE_UUID16(BLE_SVC_ANS_UUID16),
-        .characteristics = (struct ble_gatt_chr_def[]) { {
-            /** Supported New Alert Catagory 
-             * 
-             * This characteristic exposes what categories of new 
-             * alert are supported in the server.
-             */
-            .uuid128 = BLE_UUID16(BLE_SVC_ANS_CHR_UUID16_SUP_NEW_ALERT_CAT),
-            .access_cb = ble_svc_ans_access,
-            .flags = BLE_GATT_CHR_F_READ,
-        }, {
-            /** New Alert 
-             *
-             * This characteristic exposes information about 
-             * the count of new alerts (for a given category).
-             */
-            .uuid128 = BLE_UUID16(BLE_SVC_ANS_CHR_UUID16_NEW_ALERT),
-            .access_cb = ble_svc_ans_access,
-            .val_handle = &ble_svc_ans_new_alert_val_handle,
-            .flags = BLE_GATT_CHR_F_NOTIFY,
-        }, {
-            /** Supported Unread Alert Catagory 
-             *
-             * This characteristic exposes what categories of 
-             * unread alert are supported in the server.
-             */
-            .uuid128 = BLE_UUID16(BLE_SVC_ANS_CHR_UUID16_SUP_UNR_ALERT_CAT),
-            .access_cb = ble_svc_ans_access,
-            .flags = BLE_GATT_CHR_F_READ,
-        }, {
-            /** Unread Alert Status 
-             *
-             * This characteristic exposes the count of unread 
-             * alert events existing in the server.
-             */
-            .uuid128 = BLE_UUID16(BLE_SVC_ANS_CHR_UUID16_UNR_ALERT_STAT),
-            .access_cb = ble_svc_ans_access,
-            .val_handle = &ble_svc_ans_unr_alert_val_handle,
-            .flags = BLE_GATT_CHR_F_NOTIFY,
-        }, {
-            /** Alert Notification Control Point 
-             *
-             * This characteristic allows the peer device to 
-             * enable/disable the alert notification of new alert 
-             * and unread event more selectively than can be done 
-             * by setting or clearing the notification bit in the 
-             * Client Characteristic Configuration for each alert 
-             * characteristic.
-             */
-            .uuid128 = BLE_UUID16(BLE_SVC_ANS_CHR_UUID16_ALERT_NOT_CTRL_PT),
-            .access_cb = ble_svc_ans_access,
-            .flags = BLE_GATT_CHR_F_WRITE,
-        }, {
-            0, /* No more characteristics in this service. */
-        } },
-    },
-
-    {
-        0, /* No more services. */
-    },
-};
-
-/**
- * ANS access function
- */
-static int
-ble_svc_ans_access(uint16_t conn_handle, uint16_t attr_handle,
-                          struct ble_gatt_access_ctxt *ctxt,
-                          void *arg)
-{
-    uint16_t uuid16;
-    int rc;
-    
-    /* ANS Control point command and catagory variables */
-    uint8_t cmd_id;
-    uint8_t cat_id;
-    uint8_t cat_bit_mask; 
-    int i;
-
-    uuid16 = ble_uuid_128_to_16(ctxt->chr->uuid128);
-    assert(uuid16 != 0);
-
-    switch (uuid16) {
-    case BLE_SVC_ANS_CHR_UUID16_SUP_NEW_ALERT_CAT:
-        assert(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR);
-        rc = os_mbuf_append(ctxt->om, &ble_svc_ans_new_alert_cat,
-                            sizeof ble_svc_ans_new_alert_cat);
-        return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
-
-    case BLE_SVC_ANS_CHR_UUID16_NEW_ALERT:
-        if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
-            rc = ble_svc_ans_chr_write(ctxt->om, 0,
-                                       sizeof ble_svc_ans_new_alert_val,
-                                       ble_svc_ans_new_alert_val,
-                                       &ble_svc_ans_new_alert_val_len);
-            return rc;
-
-        } else if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) {
-            rc = os_mbuf_append(ctxt->om, &ble_svc_ans_new_alert_val,
-                                sizeof ble_svc_ans_new_alert_val);
-            return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
-        }
-
-    case BLE_SVC_ANS_CHR_UUID16_SUP_UNR_ALERT_CAT:
-        assert(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR);
-        rc = os_mbuf_append(ctxt->om, &ble_svc_ans_unr_alert_cat,
-                            sizeof ble_svc_ans_unr_alert_cat);
-        return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
-
-    case BLE_SVC_ANS_CHR_UUID16_UNR_ALERT_STAT:
-        if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
-            rc = ble_svc_ans_chr_write(ctxt->om, 
-                                       sizeof ble_svc_ans_unr_alert_stat, 
-                                       sizeof ble_svc_ans_unr_alert_stat,
-                                       &ble_svc_ans_unr_alert_stat,
-                                       NULL);
-            return rc; 
-        } else {
-            rc = os_mbuf_append(ctxt->om, &ble_svc_ans_unr_alert_stat,
-                                sizeof ble_svc_ans_unr_alert_stat);
-            return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
-        }
-
-    case BLE_SVC_ANS_CHR_UUID16_ALERT_NOT_CTRL_PT:
-        if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
-            rc = ble_svc_ans_chr_write(ctxt->om, 
-                                       sizeof ble_svc_ans_alert_not_ctrl_pt, 
-                                       sizeof ble_svc_ans_alert_not_ctrl_pt,
-                                       &ble_svc_ans_alert_not_ctrl_pt,
-                                       NULL);
-
-            /* Get command ID and category ID */
-            cmd_id = ble_svc_ans_alert_not_ctrl_pt[0];
-            cat_id = ble_svc_ans_alert_not_ctrl_pt[1];
-
-            /* Set cat_bit_mask to the appropriate bitmask based on cat_id */
-            if (cat_id < BLE_SVC_ANS_CAT_NUM) {
-                cat_bit_mask = (1 << cat_id); 
-            } else if (cat_id == 0xff) { 
-                cat_bit_mask = cat_id;
-            } else {
-                cat_bit_mask = 0;
-            }
-
-            switch (cmd_id) {
-            case BLE_SVC_ANS_CMD_EN_NEW_ALERT_CAT:
-                ble_svc_ans_new_alert_cat |= cat_bit_mask; 
-                break;
-            case BLE_SVC_ANS_CMD_EN_UNR_ALERT_CAT:
-                ble_svc_ans_unr_alert_cat |= cat_bit_mask;
-                break;
-            case BLE_SVC_ANS_CMD_DIS_NEW_ALERT_CAT:
-                ble_svc_ans_new_alert_cat &= ~cat_bit_mask;
-                break;
-            case BLE_SVC_ANS_CMD_DIS_UNR_ALERT_CAT:
-                ble_svc_ans_unr_alert_cat &= ~cat_bit_mask;
-                break;
-            case BLE_SVC_ANS_CMD_NOT_NEW_ALERT_IMMEDIATE:
-                if (cat_id == 0xff) {
-                    /* If cat_id is 0xff, notify on all enabled categories */
-                    for (i = BLE_SVC_ANS_CAT_NUM - 1; i > 0; --i) {
-                        if ((ble_svc_ans_new_alert_cat >> i) & 0x01) {
-                            ble_svc_ans_new_alert_notify(i, NULL);
-                        }
-                    }
-                } else {
-                    ble_svc_ans_new_alert_notify(cat_id, NULL);
-                }
-                break;
-            case BLE_SVC_ANS_CMD_NOT_UNR_ALERT_IMMEDIATE:
-                if (cat_id == 0xff) {
-                    /* If cat_id is 0xff, notify on all enabled categories */
-                    for (i = BLE_SVC_ANS_CAT_NUM - 1; i > 0; --i) {
-                        if ((ble_svc_ans_unr_alert_cat >> i) & 0x01) {
-                            ble_svc_ans_unr_alert_notify(i);
-                        }
-                    }
-                } else {
-                    ble_svc_ans_unr_alert_notify(cat_id);
-                }
-                break;
-            default:
-                return BLE_SVC_ANS_ERR_CMD_NOT_SUPPORTED;
-            }
-            return 0;
-        } else {
-            rc = BLE_ATT_ERR_UNLIKELY;
-        }
-        return rc;
-
-    default:
-        assert(0);
-        return BLE_ATT_ERR_UNLIKELY;
-    }
-}
-
-/**
- * This function must be called with the connection handlewhen a gap 
- * connect event is received in order to send notifications to the
- * client.
- *
- * @params conn_handle          The connection handle for the current
- *                                  connection.
- */
-void 
-ble_svc_ans_on_gap_connect(uint16_t conn_handle) 
-{
-    ble_svc_ans_conn_handle = conn_handle;
-}
-
-/**
- * Adds a new alert to the given category then notifies the client
- * if the given category is valid and enabled.
- *
- * @param cat_flag              The id for the category which should
- *                                  should be incremented and notified
- * @param info_str              The info string to be sent to the client
- *                                  with the notification.
- * 
- * @return 0 on success, non-zero error code otherwise. 
- */
-int
-ble_svc_ans_new_alert_add(uint8_t cat_id, const char * info_str)
-{
-    uint8_t cat_bit_mask; 
-    
-    if (cat_id < BLE_SVC_ANS_CAT_NUM) {
-        cat_bit_mask = (1 << cat_id); 
-    } else {
-        return BLE_HS_EINVAL;
-    }
-
-    if ((cat_bit_mask & ble_svc_ans_new_alert_cat) == 0) {
-        return BLE_HS_EINVAL;
-    }
-
-    ble_svc_ans_new_alert_cnt[cat_id] += 1;
-    return ble_svc_ans_new_alert_notify(cat_id, info_str);
-}
-
-/**
- * Adds an unread alert to the given category then notifies the client
- * if the given category is valid and enabled.
- * 
- * @param cat_flag              The flag for the category which should
- *                                  should be incremented and notified
- * 
- * @return 0 on success, non-zero error code otherwise. 
- */
-int
-ble_svc_ans_unr_alert_add(uint8_t cat_id)
-{
-    uint8_t cat_bit_mask; 
-    
-    if (cat_id < BLE_SVC_ANS_CAT_NUM) {
-        cat_bit_mask = pow(2, cat_id);
-    } else {
-        return BLE_HS_EINVAL;
-    }
-
-    if ((cat_bit_mask & ble_svc_ans_unr_alert_cat) == 0) {
-        return BLE_HS_EINVAL;
-    }
-
-    ble_svc_ans_unr_alert_cnt[cat_id] += 1;
-    return ble_svc_ans_unr_alert_notify(cat_id);
-}
-
-/**
- * Initialize the ANS with initial values for enabled categories
- * for new and unread alert characteristics. Bitwise or the 
- * catagory bitmasks to enable multiple catagories.
- * 
- * XXX: We should technically be able to change the new alert and
- *      unread alert catagories when we have no active connections.
- * 
- * @param cfg                       The host configuration
- * @param initial_new_alert_cat     Initial supported new alert category
- *                                      bitmask.
- * @param initial_unr_alert_cat     Initial supported unread alert category
- *                                      bitmask.
- *
- * @return 0 on success, non-zero error code otherwise.
- */
-int
-ble_svc_ans_init(struct ble_hs_cfg *cfg, uint8_t initial_new_alert_cat,
-                 uint8_t initial_unr_alert_cat)
-{
-    int rc;
-    
-    ble_svc_ans_new_alert_cat = initial_new_alert_cat;
-    ble_svc_ans_unr_alert_cat = initial_unr_alert_cat;
-
-    rc = ble_gatts_count_cfg(ble_svc_ans_defs, cfg);
-    if (rc != 0) {
-        return rc;
-    }
-
-    rc = ble_gatts_add_svcs(ble_svc_ans_defs);
-    if (rc != 0) {
-        return rc;
-    }
-
-    return 0;
-}
-
-/**
- * Send a new alert notification to the given category with the 
- * given info string.
- *
- * @param cat_id                The ID of the category to send the 
- *                                  notification to.
- * @param info_str              The info string to send with the 
- *                                  notification
- *
- * @return 0 on success, non-zero error code otherwise.
- */
-static int
-ble_svc_ans_new_alert_notify(uint8_t cat_id, const char * info_str)
-{
-    int info_str_len;
-
-    /* Clear notification to remove old infomation that may persist */
-    memset(&ble_svc_ans_new_alert_val, '\0', 
-           BLE_SVC_ANS_NEW_ALERT_MAX_LEN); 
-    
-    /* Set ID and count values */
-    ble_svc_ans_new_alert_val[0] = cat_id;
-    ble_svc_ans_new_alert_val[1] = ble_svc_ans_new_alert_cnt[cat_id];
-    
-    if (info_str) {
-        info_str_len = strlen(info_str);
-        if (info_str_len > BLE_SVC_ANS_INFO_STR_MAX_LEN) {
-            /* If info_str is longer than the max string length only 
-             * write up to the maximum length */
-            memcpy(&ble_svc_ans_new_alert_val[2], info_str, 
-                   BLE_SVC_ANS_INFO_STR_MAX_LEN);
-        } else {
-            memcpy(&ble_svc_ans_new_alert_val[2], info_str, info_str_len);
-        }
-    }
-    return ble_gattc_notify(ble_svc_ans_conn_handle, 
-                            ble_svc_ans_new_alert_val_handle);
-}
-
-/**
- * Send an unread alert notification to the given category.
- *
- * @param cat_id                The ID of the category to send the
- *                                  notificaiton to.
- *
- * @return 0 on success, non-zer0 error code otherwise.
- */
-static int
-ble_svc_ans_unr_alert_notify(uint8_t cat_id)
-{
-    ble_svc_ans_unr_alert_stat[0] = cat_id;
-    ble_svc_ans_unr_alert_stat[1] = ble_svc_ans_unr_alert_cnt[cat_id];
-    return ble_gattc_notify(ble_svc_ans_conn_handle, 
-                            ble_svc_ans_unr_alert_val_handle);
-}
-
-/**
- * Writes the received value from a characteristic write to 
- * the given destination.
- */
-static int
-ble_svc_ans_chr_write(struct os_mbuf *om, uint16_t min_len,
-                      uint16_t max_len, void *dst,
-                      uint16_t *len)
-{
-    uint16_t om_len;
-    int rc;
-
-    om_len = OS_MBUF_PKTLEN(om);
-    if (om_len < min_len || om_len > max_len) {
-        return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
-    }
-
-    rc = ble_hs_mbuf_to_flat(om, dst, max_len, len);
-    if (rc != 0) {
-        return BLE_ATT_ERR_UNLIKELY;
-    }
-
-    return 0;
-}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/64b1cd98/net/nimble/host/services/ans/include/profiles/ans/ble_svc_ans.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/services/ans/include/profiles/ans/ble_svc_ans.h b/net/nimble/host/services/ans/include/profiles/ans/ble_svc_ans.h
new file mode 100644
index 0000000..eaf102a
--- /dev/null
+++ b/net/nimble/host/services/ans/include/profiles/ans/ble_svc_ans.h
@@ -0,0 +1,87 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef H_BLE_SVC_ANS_
+#define H_BLE_SVC_ANS_
+
+struct ble_hs_cfg;
+
+/* 16 Bit Alert Notification Service UUID */
+#define BLE_SVC_ANS_UUID16                                  0x1811
+
+/* 16 Bit Alert Notification Servivce Characteristic UUIDs */
+#define BLE_SVC_ANS_CHR_UUID16_SUP_NEW_ALERT_CAT            0x2a47
+#define BLE_SVC_ANS_CHR_UUID16_NEW_ALERT                    0x2a46
+#define BLE_SVC_ANS_CHR_UUID16_SUP_UNR_ALERT_CAT            0x2a48
+#define BLE_SVC_ANS_CHR_UUID16_UNR_ALERT_STAT               0x2a45
+#define BLE_SVC_ANS_CHR_UUID16_ALERT_NOT_CTRL_PT            0x2a44
+
+/* Alert Notification Service Category ID Bit Masks 
+ *
+ * TODO: Add remaining 2 optional categories */
+#define BLE_SVC_ANS_CAT_BM_NONE                             0x00
+#define BLE_SVC_ANS_CAT_BM_SIMPLE_ALERT                     0x01
+#define BLE_SVC_ANS_CAT_BM_EMAIL                            0x02
+#define BLE_SVC_ANS_CAT_BM_NEWS                             0x04
+#define BLE_SVC_ANS_CAT_BM_CALL                             0x08
+#define BLE_SVC_ANS_CAT_BM_MISSED_CALL                      0x10
+#define BLE_SVC_ANS_CAT_BM_SMS                              0x20
+#define BLE_SVC_ANS_CAT_BM_VOICE_MAIL                       0x40
+#define BLE_SVC_ANS_CAT_BM_SCHEDULE                         0x80    
+
+/* Alert Notification Service Category IDs
+ *
+ * TODO: Add remaining 2 optional categories */
+#define BLE_SVC_ANS_CAT_ID_SIMPLE_ALERT                     0
+#define BLE_SVC_ANS_CAT_ID_EMAIL                            1
+#define BLE_SVC_ANS_CAT_ID_NEWS                             2
+#define BLE_SVC_ANS_CAT_ID_CALL                             3
+#define BLE_SVC_ANS_CAT_ID_MISSED_CALL                      4
+#define BLE_SVC_ANS_CAT_ID_SMS                              5
+#define BLE_SVC_ANS_CAT_ID_VOICE_MAIL                       6
+#define BLE_SVC_ANS_CAT_ID_SCHEDULE                         7
+
+/* Number of valid ANS categories 
+ *
+ * TODO: Add remaining 2 optional categories */
+#define BLE_SVC_ANS_CAT_NUM                                 8
+
+/* Alert Notification Control Point Command IDs */
+#define BLE_SVC_ANS_CMD_EN_NEW_ALERT_CAT                    0
+#define BLE_SVC_ANS_CMD_EN_UNR_ALERT_CAT                    1
+#define BLE_SVC_ANS_CMD_DIS_NEW_ALERT_CAT                   2
+#define BLE_SVC_ANS_CMD_DIS_UNR_ALERT_CAT                   3
+#define BLE_SVC_ANS_CMD_NOT_NEW_ALERT_IMMEDIATE             4
+#define BLE_SVC_ANS_CMD_NOT_UNR_ALERT_IMMEDIATE             5
+
+/* Error Defeinitions */
+#define BLE_SVC_ANS_ERR_CMD_NOT_SUPPORTED                   0xA0
+
+void ble_svc_ans_on_gap_connect(uint16_t conn_handle);
+
+int ble_svc_ans_new_alert_add(uint8_t cat_id, 
+                              const char * info_str);
+int ble_svc_ans_unr_alert_add(uint8_t cat_id);
+
+int ble_svc_ans_init(struct ble_hs_cfg *cfg, 
+                     uint8_t initial_new_alert_cat,
+                     uint8_t initial_unr_alert_cat);
+
+#endif
+

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/64b1cd98/net/nimble/host/services/ans/pkg.yml
----------------------------------------------------------------------
diff --git a/net/nimble/host/services/ans/pkg.yml b/net/nimble/host/services/ans/pkg.yml
new file mode 100644
index 0000000..91a92c6
--- /dev/null
+++ b/net/nimble/host/services/ans/pkg.yml
@@ -0,0 +1,31 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#  http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+pkg.name: net/nimble/host/services/ans
+pkg.description: Alert Notification Service Server.
+pkg.author: "Apache Mynewt <de...@mynewt.incubator.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+    - ble 
+    - bluetooth
+    - ans 
+    - nimble 
+
+pkg.deps:
+    - net/nimble/host

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/64b1cd98/net/nimble/host/services/ans/src/ble_svc_ans.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/services/ans/src/ble_svc_ans.c b/net/nimble/host/services/ans/src/ble_svc_ans.c
new file mode 100644
index 0000000..eae4598
--- /dev/null
+++ b/net/nimble/host/services/ans/src/ble_svc_ans.c
@@ -0,0 +1,467 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <math.h>
+#include "host/ble_hs.h"
+#include "host/ble_gap.h"
+#include "services/ans/ble_svc_ans.h"
+
+
+/* Max length of new alert info string */
+#define BLE_SVC_ANS_INFO_STR_MAX_LEN        18
+/* Max length of a new alert notification, max string length + 2 bytes
+ * for category ID and count. */
+#define BLE_SVC_ANS_NEW_ALERT_MAX_LEN   (BLE_SVC_ANS_INFO_STR_MAX_LEN + 2)
+
+/* Supported categories bitmasks */
+static uint8_t ble_svc_ans_new_alert_cat;
+static uint8_t ble_svc_ans_unr_alert_cat; 
+
+/* Characteristic values */
+static uint8_t ble_svc_ans_new_alert_val[BLE_SVC_ANS_NEW_ALERT_MAX_LEN];
+static uint16_t ble_svc_ans_new_alert_val_len;
+static uint8_t ble_svc_ans_unr_alert_stat[2];
+static uint8_t ble_svc_ans_alert_not_ctrl_pt[2];
+
+/* Alert counts, one value for each category */
+static uint8_t ble_svc_ans_new_alert_cnt[BLE_SVC_ANS_CAT_NUM];
+static uint8_t ble_svc_ans_unr_alert_cnt[BLE_SVC_ANS_CAT_NUM];
+
+/* Charachteristic value handles */
+static uint16_t ble_svc_ans_new_alert_val_handle;
+static uint16_t ble_svc_ans_unr_alert_val_handle;
+
+/* Connection handle 
+ *
+ * TODO: In order to support multiple connections we would need to save
+ *       the handles for every connection, not just the most recent. Then
+ *       we would need to notify each connection when needed.
+ * */
+static uint16_t ble_svc_ans_conn_handle;
+
+/* Access function */
+static int
+ble_svc_ans_access(uint16_t conn_handle, uint16_t attr_handle,
+                   struct ble_gatt_access_ctxt *ctxt, void *arg);
+
+/* Notify new alert */
+static int
+ble_svc_ans_new_alert_notify(uint8_t cat_id, const char * info_str);
+
+/* Notify unread alert */
+static int
+ble_svc_ans_unr_alert_notify(uint8_t cat_id);
+
+/* Save written value to local characteristic value */
+static int
+ble_svc_ans_chr_write(struct os_mbuf *om, uint16_t min_len, uint16_t max_len, 
+                      void *dst, uint16_t *len);
+
+static const struct ble_gatt_svc_def ble_svc_ans_defs[] = {
+    {
+        /*** Alert Notification Service. */
+        .type = BLE_GATT_SVC_TYPE_PRIMARY,
+        .uuid128 = BLE_UUID16(BLE_SVC_ANS_UUID16),
+        .characteristics = (struct ble_gatt_chr_def[]) { {
+            /** Supported New Alert Catagory 
+             * 
+             * This characteristic exposes what categories of new 
+             * alert are supported in the server.
+             */
+            .uuid128 = BLE_UUID16(BLE_SVC_ANS_CHR_UUID16_SUP_NEW_ALERT_CAT),
+            .access_cb = ble_svc_ans_access,
+            .flags = BLE_GATT_CHR_F_READ,
+        }, {
+            /** New Alert 
+             *
+             * This characteristic exposes information about 
+             * the count of new alerts (for a given category).
+             */
+            .uuid128 = BLE_UUID16(BLE_SVC_ANS_CHR_UUID16_NEW_ALERT),
+            .access_cb = ble_svc_ans_access,
+            .val_handle = &ble_svc_ans_new_alert_val_handle,
+            .flags = BLE_GATT_CHR_F_NOTIFY,
+        }, {
+            /** Supported Unread Alert Catagory 
+             *
+             * This characteristic exposes what categories of 
+             * unread alert are supported in the server.
+             */
+            .uuid128 = BLE_UUID16(BLE_SVC_ANS_CHR_UUID16_SUP_UNR_ALERT_CAT),
+            .access_cb = ble_svc_ans_access,
+            .flags = BLE_GATT_CHR_F_READ,
+        }, {
+            /** Unread Alert Status 
+             *
+             * This characteristic exposes the count of unread 
+             * alert events existing in the server.
+             */
+            .uuid128 = BLE_UUID16(BLE_SVC_ANS_CHR_UUID16_UNR_ALERT_STAT),
+            .access_cb = ble_svc_ans_access,
+            .val_handle = &ble_svc_ans_unr_alert_val_handle,
+            .flags = BLE_GATT_CHR_F_NOTIFY,
+        }, {
+            /** Alert Notification Control Point 
+             *
+             * This characteristic allows the peer device to 
+             * enable/disable the alert notification of new alert 
+             * and unread event more selectively than can be done 
+             * by setting or clearing the notification bit in the 
+             * Client Characteristic Configuration for each alert 
+             * characteristic.
+             */
+            .uuid128 = BLE_UUID16(BLE_SVC_ANS_CHR_UUID16_ALERT_NOT_CTRL_PT),
+            .access_cb = ble_svc_ans_access,
+            .flags = BLE_GATT_CHR_F_WRITE,
+        }, {
+            0, /* No more characteristics in this service. */
+        } },
+    },
+
+    {
+        0, /* No more services. */
+    },
+};
+
+/**
+ * ANS access function
+ */
+static int
+ble_svc_ans_access(uint16_t conn_handle, uint16_t attr_handle,
+                          struct ble_gatt_access_ctxt *ctxt,
+                          void *arg)
+{
+    uint16_t uuid16;
+    int rc;
+    
+    /* ANS Control point command and catagory variables */
+    uint8_t cmd_id;
+    uint8_t cat_id;
+    uint8_t cat_bit_mask; 
+    int i;
+
+    uuid16 = ble_uuid_128_to_16(ctxt->chr->uuid128);
+    assert(uuid16 != 0);
+
+    switch (uuid16) {
+    case BLE_SVC_ANS_CHR_UUID16_SUP_NEW_ALERT_CAT:
+        assert(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR);
+        rc = os_mbuf_append(ctxt->om, &ble_svc_ans_new_alert_cat,
+                            sizeof ble_svc_ans_new_alert_cat);
+        return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
+
+    case BLE_SVC_ANS_CHR_UUID16_NEW_ALERT:
+        if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
+            rc = ble_svc_ans_chr_write(ctxt->om, 0,
+                                       sizeof ble_svc_ans_new_alert_val,
+                                       ble_svc_ans_new_alert_val,
+                                       &ble_svc_ans_new_alert_val_len);
+            return rc;
+
+        } else if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) {
+            rc = os_mbuf_append(ctxt->om, &ble_svc_ans_new_alert_val,
+                                sizeof ble_svc_ans_new_alert_val);
+            return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
+        }
+
+    case BLE_SVC_ANS_CHR_UUID16_SUP_UNR_ALERT_CAT:
+        assert(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR);
+        rc = os_mbuf_append(ctxt->om, &ble_svc_ans_unr_alert_cat,
+                            sizeof ble_svc_ans_unr_alert_cat);
+        return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
+
+    case BLE_SVC_ANS_CHR_UUID16_UNR_ALERT_STAT:
+        if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
+            rc = ble_svc_ans_chr_write(ctxt->om, 
+                                       sizeof ble_svc_ans_unr_alert_stat, 
+                                       sizeof ble_svc_ans_unr_alert_stat,
+                                       &ble_svc_ans_unr_alert_stat,
+                                       NULL);
+            return rc; 
+        } else {
+            rc = os_mbuf_append(ctxt->om, &ble_svc_ans_unr_alert_stat,
+                                sizeof ble_svc_ans_unr_alert_stat);
+            return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
+        }
+
+    case BLE_SVC_ANS_CHR_UUID16_ALERT_NOT_CTRL_PT:
+        if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
+            rc = ble_svc_ans_chr_write(ctxt->om, 
+                                       sizeof ble_svc_ans_alert_not_ctrl_pt, 
+                                       sizeof ble_svc_ans_alert_not_ctrl_pt,
+                                       &ble_svc_ans_alert_not_ctrl_pt,
+                                       NULL);
+
+            /* Get command ID and category ID */
+            cmd_id = ble_svc_ans_alert_not_ctrl_pt[0];
+            cat_id = ble_svc_ans_alert_not_ctrl_pt[1];
+
+            /* Set cat_bit_mask to the appropriate bitmask based on cat_id */
+            if (cat_id < BLE_SVC_ANS_CAT_NUM) {
+                cat_bit_mask = (1 << cat_id); 
+            } else if (cat_id == 0xff) { 
+                cat_bit_mask = cat_id;
+            } else {
+                cat_bit_mask = 0;
+            }
+
+            switch (cmd_id) {
+            case BLE_SVC_ANS_CMD_EN_NEW_ALERT_CAT:
+                ble_svc_ans_new_alert_cat |= cat_bit_mask; 
+                break;
+            case BLE_SVC_ANS_CMD_EN_UNR_ALERT_CAT:
+                ble_svc_ans_unr_alert_cat |= cat_bit_mask;
+                break;
+            case BLE_SVC_ANS_CMD_DIS_NEW_ALERT_CAT:
+                ble_svc_ans_new_alert_cat &= ~cat_bit_mask;
+                break;
+            case BLE_SVC_ANS_CMD_DIS_UNR_ALERT_CAT:
+                ble_svc_ans_unr_alert_cat &= ~cat_bit_mask;
+                break;
+            case BLE_SVC_ANS_CMD_NOT_NEW_ALERT_IMMEDIATE:
+                if (cat_id == 0xff) {
+                    /* If cat_id is 0xff, notify on all enabled categories */
+                    for (i = BLE_SVC_ANS_CAT_NUM - 1; i > 0; --i) {
+                        if ((ble_svc_ans_new_alert_cat >> i) & 0x01) {
+                            ble_svc_ans_new_alert_notify(i, NULL);
+                        }
+                    }
+                } else {
+                    ble_svc_ans_new_alert_notify(cat_id, NULL);
+                }
+                break;
+            case BLE_SVC_ANS_CMD_NOT_UNR_ALERT_IMMEDIATE:
+                if (cat_id == 0xff) {
+                    /* If cat_id is 0xff, notify on all enabled categories */
+                    for (i = BLE_SVC_ANS_CAT_NUM - 1; i > 0; --i) {
+                        if ((ble_svc_ans_unr_alert_cat >> i) & 0x01) {
+                            ble_svc_ans_unr_alert_notify(i);
+                        }
+                    }
+                } else {
+                    ble_svc_ans_unr_alert_notify(cat_id);
+                }
+                break;
+            default:
+                return BLE_SVC_ANS_ERR_CMD_NOT_SUPPORTED;
+            }
+            return 0;
+        } else {
+            rc = BLE_ATT_ERR_UNLIKELY;
+        }
+        return rc;
+
+    default:
+        assert(0);
+        return BLE_ATT_ERR_UNLIKELY;
+    }
+}
+
+/**
+ * This function must be called with the connection handlewhen a gap 
+ * connect event is received in order to send notifications to the
+ * client.
+ *
+ * @params conn_handle          The connection handle for the current
+ *                                  connection.
+ */
+void 
+ble_svc_ans_on_gap_connect(uint16_t conn_handle) 
+{
+    ble_svc_ans_conn_handle = conn_handle;
+}
+
+/**
+ * Adds a new alert to the given category then notifies the client
+ * if the given category is valid and enabled.
+ *
+ * @param cat_flag              The id for the category which should
+ *                                  should be incremented and notified
+ * @param info_str              The info string to be sent to the client
+ *                                  with the notification.
+ * 
+ * @return 0 on success, non-zero error code otherwise. 
+ */
+int
+ble_svc_ans_new_alert_add(uint8_t cat_id, const char * info_str)
+{
+    uint8_t cat_bit_mask; 
+    
+    if (cat_id < BLE_SVC_ANS_CAT_NUM) {
+        cat_bit_mask = (1 << cat_id); 
+    } else {
+        return BLE_HS_EINVAL;
+    }
+
+    if ((cat_bit_mask & ble_svc_ans_new_alert_cat) == 0) {
+        return BLE_HS_EINVAL;
+    }
+
+    ble_svc_ans_new_alert_cnt[cat_id] += 1;
+    return ble_svc_ans_new_alert_notify(cat_id, info_str);
+}
+
+/**
+ * Adds an unread alert to the given category then notifies the client
+ * if the given category is valid and enabled.
+ * 
+ * @param cat_flag              The flag for the category which should
+ *                                  should be incremented and notified
+ * 
+ * @return 0 on success, non-zero error code otherwise. 
+ */
+int
+ble_svc_ans_unr_alert_add(uint8_t cat_id)
+{
+    uint8_t cat_bit_mask; 
+    
+    if (cat_id < BLE_SVC_ANS_CAT_NUM) {
+        cat_bit_mask = pow(2, cat_id);
+    } else {
+        return BLE_HS_EINVAL;
+    }
+
+    if ((cat_bit_mask & ble_svc_ans_unr_alert_cat) == 0) {
+        return BLE_HS_EINVAL;
+    }
+
+    ble_svc_ans_unr_alert_cnt[cat_id] += 1;
+    return ble_svc_ans_unr_alert_notify(cat_id);
+}
+
+/**
+ * Initialize the ANS with initial values for enabled categories
+ * for new and unread alert characteristics. Bitwise or the 
+ * catagory bitmasks to enable multiple catagories.
+ * 
+ * XXX: We should technically be able to change the new alert and
+ *      unread alert catagories when we have no active connections.
+ * 
+ * @param cfg                       The host configuration
+ * @param initial_new_alert_cat     Initial supported new alert category
+ *                                      bitmask.
+ * @param initial_unr_alert_cat     Initial supported unread alert category
+ *                                      bitmask.
+ *
+ * @return 0 on success, non-zero error code otherwise.
+ */
+int
+ble_svc_ans_init(struct ble_hs_cfg *cfg, uint8_t initial_new_alert_cat,
+                 uint8_t initial_unr_alert_cat)
+{
+    int rc;
+    
+    ble_svc_ans_new_alert_cat = initial_new_alert_cat;
+    ble_svc_ans_unr_alert_cat = initial_unr_alert_cat;
+
+    rc = ble_gatts_count_cfg(ble_svc_ans_defs, cfg);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rc = ble_gatts_add_svcs(ble_svc_ans_defs);
+    if (rc != 0) {
+        return rc;
+    }
+
+    return 0;
+}
+
+/**
+ * Send a new alert notification to the given category with the 
+ * given info string.
+ *
+ * @param cat_id                The ID of the category to send the 
+ *                                  notification to.
+ * @param info_str              The info string to send with the 
+ *                                  notification
+ *
+ * @return 0 on success, non-zero error code otherwise.
+ */
+static int
+ble_svc_ans_new_alert_notify(uint8_t cat_id, const char * info_str)
+{
+    int info_str_len;
+
+    /* Clear notification to remove old infomation that may persist */
+    memset(&ble_svc_ans_new_alert_val, '\0', 
+           BLE_SVC_ANS_NEW_ALERT_MAX_LEN); 
+    
+    /* Set ID and count values */
+    ble_svc_ans_new_alert_val[0] = cat_id;
+    ble_svc_ans_new_alert_val[1] = ble_svc_ans_new_alert_cnt[cat_id];
+    
+    if (info_str) {
+        info_str_len = strlen(info_str);
+        if (info_str_len > BLE_SVC_ANS_INFO_STR_MAX_LEN) {
+            /* If info_str is longer than the max string length only 
+             * write up to the maximum length */
+            memcpy(&ble_svc_ans_new_alert_val[2], info_str, 
+                   BLE_SVC_ANS_INFO_STR_MAX_LEN);
+        } else {
+            memcpy(&ble_svc_ans_new_alert_val[2], info_str, info_str_len);
+        }
+    }
+    return ble_gattc_notify(ble_svc_ans_conn_handle, 
+                            ble_svc_ans_new_alert_val_handle);
+}
+
+/**
+ * Send an unread alert notification to the given category.
+ *
+ * @param cat_id                The ID of the category to send the
+ *                                  notificaiton to.
+ *
+ * @return 0 on success, non-zer0 error code otherwise.
+ */
+static int
+ble_svc_ans_unr_alert_notify(uint8_t cat_id)
+{
+    ble_svc_ans_unr_alert_stat[0] = cat_id;
+    ble_svc_ans_unr_alert_stat[1] = ble_svc_ans_unr_alert_cnt[cat_id];
+    return ble_gattc_notify(ble_svc_ans_conn_handle, 
+                            ble_svc_ans_unr_alert_val_handle);
+}
+
+/**
+ * Writes the received value from a characteristic write to 
+ * the given destination.
+ */
+static int
+ble_svc_ans_chr_write(struct os_mbuf *om, uint16_t min_len,
+                      uint16_t max_len, void *dst,
+                      uint16_t *len)
+{
+    uint16_t om_len;
+    int rc;
+
+    om_len = OS_MBUF_PKTLEN(om);
+    if (om_len < min_len || om_len > max_len) {
+        return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
+    }
+
+    rc = ble_hs_mbuf_to_flat(om, dst, max_len, len);
+    if (rc != 0) {
+        return BLE_ATT_ERR_UNLIKELY;
+    }
+
+    return 0;
+}