[OTP] Handle Object Create request 85/133785/2
authorGowtham Anandha Babu <gowtham.ab@samsung.com>
Tue, 13 Jun 2017 10:23:54 +0000 (15:53 +0530)
committerGowtham Anandha Babu <gowtham.ab@samsung.com>
Tue, 13 Jun 2017 11:00:23 +0000 (16:30 +0530)
Change-Id: Ie4a4a9ab144d506c8f3c9b972e54538cc91178b5
Signed-off-by: Gowtham Anandha Babu <gowtham.ab@samsung.com>
bt-otp/bt-otpserver.c
bt-otp/bt-otpserver.h
bt-service/bt-service-otp.c

index c8e372b..d75ed46 100644 (file)
@@ -98,6 +98,14 @@ struct oacp_operation {
        int fd;
 };
 
+struct oacp_create_operation {
+       char *remote_address;
+       char *filename;
+       char *uuid;
+       uint32_t size;
+       time_t first_created;
+};
+
 static struct object_metadata *selected_object = NULL;
 static uint64_t object_id = OBJECT_START_ID;
 static GSList *otp_object_list = NULL;
@@ -110,6 +118,8 @@ char *directory = NULL;
 gboolean mutiple_obj_support = false;
 static gboolean otc_connection_status = FALSE;
 struct oacp_operation *oacp_read = NULL;
+struct oacp_create_operation *oacp_create = NULL;
+unsigned int timeout_id;
 
 static const gchar otp_introspection_xml[] =
 "<node name='/'>"
@@ -285,7 +295,7 @@ int _bt_otp_prepare_ots(void)
        char *desc_uuid;
        bt_gatt_characteristic_property_t props;
        bt_gatt_permission_t perms;
-       char supp_feat[OTP_FEATURE_LENGTH] = { 0x08, 0x00, 0x00, 0x00,
+       char supp_feat[OTP_FEATURE_LENGTH] = { 0x88, 0x00, 0x00, 0x00,
                                                0x80, 0x00, 0x00, 0x00 };
 
        ret = bluetooth_gatt_init();
@@ -321,8 +331,10 @@ int _bt_otp_prepare_ots(void)
                                                OTP_FEATURE_LENGTH);
 
        /* Characteristic Object Name */
-       props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ;
-       perms = BLUETOOTH_GATT_PERMISSION_READ;
+       props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ |
+               BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
+       perms = BLUETOOTH_GATT_PERMISSION_READ |
+               BLUETOOTH_GATT_PERMISSION_WRITE;
        char_uuid = _otp_convert_uuid_to_uuid128(OTP_OBJECT_NAME_UUID);
        ret = add_new_characteristic(char_uuid, perms, props,
                                        &otp_object_name_obj_path);
@@ -672,16 +684,13 @@ fail:
                _bt_convert_device_path_to_address(dev_path, address);
 
                BT_INFO("OTC Connected fd: %d, address %s", fd, address);
-               if (!oacp_read) {
-                       /* OTC Connected, but no on going request */
-                       goto done;
-               }
-               oacp_read->fd = fd;
-               otc_connection_status = TRUE;
+               if (oacp_read) {
+                       oacp_read->fd = fd;
+                       otc_connection_status = TRUE;
 
-               if (oacp_read->opcode == OACP_READ)
-                       _bt_otp_start_write_on_fd();
-done:
+                       if (oacp_read->opcode == OACP_READ)
+                               _bt_otp_start_write_on_fd();
+               }
                g_dbus_method_invocation_return_value(invocation, NULL);
        }
        BT_DBG("-");
@@ -908,13 +917,24 @@ fail:
        return ret;
 }
 
+static bool __bt_oacp_create_timeout_cb(gpointer user_data)
+{
+       if (oacp_create) {
+               g_free(oacp_create->uuid);
+               g_free(oacp_create);
+               oacp_create = NULL;
+       }
+       return TRUE;
+}
+
 int _bt_otp_oacp_write_cb(char *value, int len, int offset,
                                                        char *remote_addr, struct indicate_info *info)
 {
        int ret = OACP_SUCCESS;
        int app_err = BLUETOOTH_ERROR_NONE;
        int opcode = value[0];
-       uint32_t object_offset, length;
+       uint32_t object_offset, length, object_size;
+       char *uuid;
 
        BT_INFO("OACP Opcode 0x%d", opcode);
 
@@ -925,7 +945,29 @@ int _bt_otp_oacp_write_cb(char *value, int len, int offset,
 
        switch (opcode) {
        case OACP_CREATE:
-               ret = OACP_OPCODE_NOT_SUPPORTED;
+               BT_INFO("OACP_CREATE");
+               object_size = (uint32_t)(value[4] & 0xFF) << 24 |
+                               (uint32_t)(value[3] & 0xFF) << 16 |
+                               (uint32_t)(value[2] & 0xFF) << 8  |
+                               (uint32_t)(value[1] & 0xFF);
+
+               uuid = g_strndup(value + 5, len - 5);
+               BT_INFO("Size = %lu, UUID = %s", object_size, uuid);
+
+               if (oacp_create) {
+                       /* Create operation already going on. */
+                       ret = OACP_OPERATION_FAILED;
+                       goto fail;
+               }
+               oacp_create = g_malloc0(sizeof(struct oacp_create_operation));
+               oacp_create->size = object_size;
+               oacp_create->uuid = g_strdup(uuid);
+               if (timeout_id > 0)
+                       g_source_remove(timeout_id);
+               timeout_id = g_timeout_add(BT_OACP_CREATE_MAX_TIMEOUT,
+                       (GSourceFunc)__bt_oacp_create_timeout_cb, NULL);
+               g_free(uuid);
+               ret = OACP_SUCCESS;
                break;
        case OACP_DELETE:
                ret = OACP_OPCODE_NOT_SUPPORTED;
@@ -1175,6 +1217,68 @@ fail:
        return BLUETOOTH_ERROR_NONE;
 }
 
+int _bt_otp_obj_name_cb(char *value, int len)
+{
+       int ret = BLUETOOTH_ERROR_NONE;
+
+       struct object_metadata *object = NULL;
+       struct stat st;
+       char *file_path;
+       char *filename;
+       int length;
+       FILE *fp = NULL;
+
+       filename = g_strndup(value, len);
+       length = len + strlen(BT_OTP_BASE_DIR_PATH) + 1;
+       file_path = malloc(length);
+
+       snprintf(file_path, length, "%s%s",
+                       BT_OTP_BASE_DIR_PATH, filename);
+       BT_DBG("file_path = [%s]", file_path);
+
+       fp = fopen(file_path, "a");
+       if (!fp) {
+               BT_DBG("fopen() failed : %s", strerror(errno));
+               ret = BLUETOOTH_ERROR_INTERNAL;
+               goto fail;
+       }
+
+       if (stat(file_path, &st) == -1) {
+               BT_INFO("stat failed: (%d)\n", errno);
+               ret = BLUETOOTH_ERROR_INTERNAL;
+               goto fail;
+       }
+
+       object = g_new0(struct object_metadata, 1);
+
+       object->name = g_strdup(filename);
+       object->type = _otp_convert_uuid_to_uuid128(oacp_create->uuid);
+       object->first_created = st.st_ctime;
+       object->last_modified = st.st_ctime;
+       object->curr_size = (uint32_t)st.st_size;
+       object->alloc_size = oacp_create->size;
+       object->id = object_id;
+       object->props = OBJECT_READ | OBJECT_WRITE;
+
+       otp_object_list = g_slist_append(otp_object_list,
+                                               object);
+
+       update_obj_metadata_charc_value(object);
+       selected_object = object;
+       obj_curr_index = g_slist_length(otp_object_list) - 1;
+       object_id++;
+fail:
+       if (fp)
+               fclose(fp);
+       g_free(filename);
+       free(file_path);
+       g_free(oacp_create->uuid);
+       g_free(oacp_create);
+       oacp_create = NULL;
+
+       return ret;
+}
+
 static struct otp_char_info *otp_get_char_value(const char *path)
 {
        GSList *tmp = NULL;
@@ -1322,6 +1426,20 @@ void _bt_otp_gatt_char_property_changed_event(GVariant *msg,
                                                result = _bt_otp_oacp_write_cb(value, len, offset, addr, &info);
                                        } else if (!g_strcmp0(char_path, otp_olcp_obj_path)) {
                                                result = _bt_otp_olcp_write_cb(value, len, offset, &info);
+                                       } else if (!g_strcmp0(char_path, otp_object_name_obj_path)) {
+                                               if (oacp_create) {
+                                                       /* OACP_CREATE is ongoing */
+                                                       result = _bt_otp_obj_name_cb(value, len);
+                                               } else {
+                                                       /* Dont permit writting object name except while creating object.
+                                                        * As this is directly pointing local objects.
+                                                        */
+                                                       result = BLUETOOTH_ERROR_WRITE_REQUEST_REJECTED;
+                                               }
+                                       } else if (!g_strcmp0(char_path, otp_object_first_created_obj_path)) {
+                                               _bt_otp_set_char_value(otp_object_first_created_obj_path, value, len);
+                                       } else if (!g_strcmp0(char_path, otp_object_last_modified_obj_path)) {
+                                               _bt_otp_set_char_value(otp_object_last_modified_obj_path, value, len);
                                        } else {
                                                BT_ERR("Wrong Object Path %s", char_path);
                                                result = BLUETOOTH_ERROR_INTERNAL;
index fa4aa1f..98f6c7a 100755 (executable)
 
 #define BT_ADDRESS_STRING_SIZE 18
 
+#define BT_OTP_BASE_DIR_PATH "/home/owner/media/otp/"
+
+#define BT_OACP_CREATE_MAX_TIMEOUT 10000 /* Timeout for OACP_CREATE in msec */
+
 /* OTP Service and Chanracteristics UUID */
 #define OTP_UUID                       "1825"
 #define OTP_FEATURE_UUID               "2abd"
index dc8716d..0c61c19 100644 (file)
@@ -799,6 +799,7 @@ int _bt_otp_write_characteristic_value(int request_id, char *sender, char *handl
                otp_notification_info_list = g_slist_append(otp_notification_info_list, info);
        }
        info->req_id = request_id;
+       /* Set timeout only for cp charc */
        info->notification_timeout_id = g_timeout_add(BT_INDICATION_TIMEOUT_MAX,
                        (GSourceFunc)__bt_otp_indication_timeout_cb, (gpointer)info->handle);