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;
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='/'>"
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();
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);
_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("-");
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);
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;
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;
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;