Ejemplo n.º 1
0
/**
 * @brief Allocate operations for receiver buffers
 *
 * This function is allocating operation and use them as receiving buffers.
 *
 * @param max_nodes Maximum nodes.
 * @param buf_size Buffer size in operation.
 * @param queue Target queue.
 * @return 0 for success, -errno for failures.
 */
static int uart_alloc_op(int max_nodes, int buf_size, sq_queue_t *queue)
{
    struct gb_operation *operation = NULL;
    struct gb_uart_receive_data_request *request = NULL;
    struct op_node *node = NULL;
    int i = 0;

    for (i = 0; i < max_nodes; i++) {
        operation = gb_operation_create(info->cport,
                                        GB_UART_PROTOCOL_RECEIVE_DATA,
                                        sizeof(*request) + buf_size);
        if (!operation) {
            goto err_free_op;
        }

        node = malloc(sizeof(struct op_node));
        if (!node) {
            gb_operation_destroy(operation);
            goto err_free_op;
        }
        node->operation = operation;

        request = gb_operation_get_request_payload(operation);
        node->data_size = &request->size;
        node->buffer = request->data;
        put_node_back(queue, node);
    }

    return 0;

err_free_op:
    uart_free_op(queue);

    return -ENOMEM;
}
Ejemplo n.º 2
0
/**
 * @brief Modem and line status event init process
 *
 * This function creates one operations and uses that request of operation
 * for sending the status change event to peer.
 *
 * @param info Pointer to struct gb_uart_info.
 * @return 0 on success, error code on failure.
 */
static int uart_status_cb_init(struct gb_uart_info *info)
{
    int ret;

    info->ms_ls_operation =
            gb_operation_create(info->cport,
                                GB_UART_PROTOCOL_SERIAL_STATE,
                                sizeof(struct gb_uart_serial_state_request));
    if (!info->ms_ls_operation) {
        return -ENOMEM;
    }

    ret = sem_init(&info->status_sem, 0, 0);
    if (ret) {
        goto err_destroy_ms_ls_op;
    }

    ret = pthread_create(&info->status_thread, NULL, uart_status_thread, info);
    if (ret) {
        goto err_destroy_status_sem;
    }

    return 0;

err_destroy_status_sem:
    sem_destroy(&info->status_sem);
err_destroy_ms_ls_op:
    gb_operation_destroy(info->ms_ls_operation);

    return -ret;
}
Ejemplo n.º 3
0
/**
 * @brief Data receiving process thread
 *
 * This function is the thread for processing data receiving tasks. When
 * it wake up, it checks the receiving queue for processing the come in data.
 * If protocol is running out of buffer, as soon as it gets a free buffer,
 * it passes to driver for continuing the receiving.
 *
 * @param data The regular thread data.
 * @return None.
 */
static void *uart_rx_thread(void *data)
{
    struct gb_operation *operation = NULL;
    struct gb_uart_receive_data_request *request = NULL;
    struct buf_node *node = NULL;
    struct gb_bundle *bundle = data;
    struct gb_uart_info *info = bundle->priv;
    struct device *dev = bundle->dev;
    int ret;

    while (1) {
        sem_wait(&info->rx_sem);

        if (info->thread_stop) {
            break;
        }

        node = get_node_from(&info->data_queue);
        if (node) {
            operation = gb_operation_create(info->cport,
                                           GB_UART_PROTOCOL_RECEIVE_DATA,
                                           sizeof(*request) + node->data_size);
            if (!operation) {
                uart_report_error(GB_UART_EVENT_PROTOCOL_ERROR, __func__);
            } else {
                request = gb_operation_get_request_payload(operation);
                request->size = cpu_to_le16(node->data_size);
                request->flags = node->data_flags;
                memcpy(request->data, node->buffer, node->data_size);

                ret = gb_operation_send_request(operation, NULL, false);
                if (ret) {
                    uart_report_error(GB_UART_EVENT_PROTOCOL_ERROR, __func__);
                }
                gb_operation_destroy(operation);
            }
            put_node_back(&info->free_queue, node);
        }

        /*
         * In case there is no free node in callback.
         */
        if (info->require_node) {
            node = get_node_from(&info->free_queue);
            info->rx_node = node;
            ret = device_uart_start_receiver(dev, node->buffer,
                                             info->rx_buf_size, NULL,
                                             NULL, uart_rx_callback);
            if (ret) {
                uart_report_error(GB_UART_EVENT_DEVICE_ERROR, __func__);
            }
            info->require_node = 0;
        }
    }

    return NULL;
}
Ejemplo n.º 4
0
int gb_svc_intf_hot_unplug(uint32_t intf_id) {
    struct gb_operation *op_req;
    struct gb_svc_intf_hot_unplug_request *req;

    op_req = gb_operation_create(g_svc_cport, GB_SVC_TYPE_INTF_HOT_UNPLUG,
                                 sizeof(*req));
    if (!op_req) {
        return -ENOMEM;
    }

    req = gb_operation_get_request_payload(op_req);
    req->intf_id = intf_id;

    gb_operation_send_request_sync(op_req);
    gb_operation_destroy(op_req);

    return 0;
}
Ejemplo n.º 5
0
int gb_svc_hello(uint8_t ap_intf_id) {
    struct gb_operation *op_req;
    struct gb_svc_hello_request *req;

    op_req = gb_operation_create(g_svc_cport, GB_SVC_TYPE_HELLO,
                                 sizeof(*req));
    if (!op_req) {
        return -EPROTO;
    }

    req = gb_operation_get_request_payload(op_req);
    req->endo_id = cpu_to_le16(GB_ENDO_ID);
    req->interface_id = ap_intf_id;

    gb_operation_send_request_sync(op_req);
    gb_operation_destroy(op_req);

    return 0;
}
Ejemplo n.º 6
0
Archivo: ptp.c Proyecto: jksim/nuttx
static int gb_ptp_changed(enum ptp_change change)
{
    struct gb_operation *operation;
    uint8_t type;
    int ret;

   /* Do not notify core until connected */
    if (!ptp_info->connected)
        return 0;

    switch(change) {
    case POWER_PRESENT:
        type = GB_PTP_TYPE_EXT_POWER_CHANGED;
        break;
    case POWER_REQUIRED:
        type = GB_PTP_TYPE_POWER_REQUIRED_CHANGED;
        break;
    case POWER_AVAILABLE:
        if (!GB_PTP_SUPPORTS(ptp_info->host_major, ptp_info->host_minor,
            POWER_AVAILABLE_CHANGED))
            return 0;
        type = GB_PTP_TYPE_POWER_AVAILABLE_CHANGED;
        break;
    default:
        return -EINVAL;
    }

    operation = gb_operation_create(ptp_info->cport, type, 0);
    if (!operation) {
        gb_error("%s(): failed to create operation\n", __func__);
        return -ENOMEM;
    }

    ret = gb_operation_send_request(operation, NULL, false);
    if (ret)
        gb_error("%s(): failed to send request\n", __func__);

    gb_operation_destroy(operation);

    return ret;
}
Ejemplo n.º 7
0
int gb_svc_intf_hotplug(uint32_t intf_id, uint32_t unipro_mfg_id,
                        uint32_t unipro_prod_id, uint32_t ara_vend_id,
                        uint32_t ara_prod_id) {
    struct gb_operation *op_req;
    struct gb_svc_intf_hotplug_request *req;

    op_req = gb_operation_create(g_svc_cport, GB_SVC_TYPE_INTF_HOTPLUG, sizeof(*req));
    if (!op_req) {
        return -ENOMEM;
    }

    req = gb_operation_get_request_payload(op_req);
    req->intf_id = intf_id;
    req->data.unipro_mfg_id = unipro_mfg_id;
    req->data.unipro_prod_id = unipro_prod_id;
    req->data.ara_vend_id = ara_vend_id;
    req->data.ara_prod_id = ara_prod_id;

    gb_operation_send_request_sync(op_req);
    gb_operation_destroy(op_req);

    return 0;
}
Ejemplo n.º 8
0
/**
 * gb_operation_sync_timeout() - implement a "simple" synchronous operation
 * @connection: the Greybus connection to send this to
 * @type: the type of operation to send
 * @request: pointer to a memory buffer to copy the request from
 * @request_size: size of @request
 * @response: pointer to a memory buffer to copy the response to
 * @response_size: the size of @response.
 * @timeout: operation timeout in milliseconds
 *
 * This function implements a simple synchronous Greybus operation.  It sends
 * the provided operation request and waits (sleeps) until the corresponding
 * operation response message has been successfully received, or an error
 * occurs.  @request and @response are buffers to hold the request and response
 * data respectively, and if they are not NULL, their size must be specified in
 * @request_size and @response_size.
 *
 * If a response payload is to come back, and @response is not NULL,
 * @response_size number of bytes will be copied into @response if the operation
 * is successful.
 *
 * If there is an error, the response buffer is left alone.
 */
int gb_operation_sync_timeout(struct gb_connection *connection, int type,
				void *request, int request_size,
				void *response, int response_size,
				unsigned int timeout)
{
	struct gb_operation *operation;
	int ret;

	if ((response_size && !response) ||
	    (request_size && !request))
		return -EINVAL;

	operation = gb_operation_create(connection, type,
					request_size, response_size,
					GFP_KERNEL);
	if (!operation)
		return -ENOMEM;

	if (request_size)
		memcpy(operation->request->payload, request, request_size);

	ret = gb_operation_request_send_sync_timeout(operation, timeout);
	if (ret) {
		dev_err(&connection->hd->dev,
			"%s: synchronous operation of type 0x%02x failed: %d\n",
			connection->name, type, ret);
	} else {
		if (response_size) {
			memcpy(response, operation->response->payload,
			       response_size);
		}
	}

	gb_operation_put(operation);

	return ret;
}
Ejemplo n.º 9
0
/*
 * SVC Protocol Requests
 */
int gb_svc_protocol_version(void) {
    struct gb_operation *op_req;
    struct gb_operation *op_resp;
    struct gb_svc_protocol_version_request *version_request;
    struct gb_svc_protocol_version_response *version_response;

    op_req = gb_operation_create(g_svc_cport, GB_SVC_TYPE_PROTOCOL_VERSION,
                                 sizeof(*version_request));
    if (!op_req) {
        return -ENOMEM;
    }
    version_request = gb_operation_get_request_payload(op_req);
    version_request->major = GB_SVC_VERSION_MAJOR;
    version_request->minor = GB_SVC_VERSION_MINOR;

    gb_operation_send_request_sync(op_req);

    op_resp = gb_operation_get_response_op(op_req);
    if (!op_resp) {
        gb_operation_destroy(op_req);
        return GB_OP_PROTOCOL_BAD;
    }
    version_response = gb_operation_get_request_payload(op_resp);

    if (version_response->major > GB_SVC_VERSION_MAJOR) {
        dbg_error("unsupported major version: %u\n", version_response->major);
        gb_operation_destroy(op_req);
        return -EPROTO;
    }
    dbg_info("SVC Protocol version_major = %u version_minor = %u\n",
             version_response->major, version_response->minor);

    gb_operation_destroy(op_req);

    return 0;
}