Changeset 2185776 in mainline for uspace/lib/usb/hcd.c


Ignore:
Timestamp:
2010-10-26T13:47:46Z (14 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
56cb9bd
Parents:
23cb44b
Message:

Async communication with HCD

Added asynchronous versions of functions for sending/retrieving
data to/from HCD. These work pretty the same as functions for
sending messages in the async framework.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/usb/hcd.c

    r23cb44b r2185776  
    3535#include "hcd.h"
    3636#include <devmap.h>
     37#include <stdlib.h>
    3738#include <fcntl.h>
    3839#include <vfs/vfs.h>
    3940#include <errno.h>
    4041
     42typedef struct {
     43        int phone;
     44        void *buffer;
     45        size_t size;
     46        size_t *size_transferred;
     47        ipc_call_t reply;
     48        aid_t request;
     49} transfer_info_t;
    4150
    4251#define NAMESPACE "usb"
     
    339348
    340349
     350
     351
     352/*
     353 * =================
     354 * async versions of the above functions
     355 * =================
     356 */
     357 
     358static int async_send_buffer(int phone, int method,
     359    usb_target_t target,
     360    void *buffer, size_t size,
     361    usb_handle_t *handle)
     362{
     363        if (phone < 0) {
     364                return EINVAL;
     365        }
     366       
     367        if ((buffer == NULL) && (size > 0)) {
     368                return EINVAL;
     369        }
     370       
     371        if (handle == NULL) {
     372                return EINVAL;
     373        }
     374
     375        transfer_info_t *transfer
     376            = (transfer_info_t *) malloc(sizeof(transfer_info_t));
     377        if (transfer == NULL) {
     378                return ENOMEM;
     379        }
     380       
     381        transfer->size_transferred = NULL;
     382        transfer->buffer = NULL;
     383        transfer->size = 0;
     384        transfer->phone = phone;
     385
     386        int rc;
     387       
     388        transfer->request = async_send_3(phone,
     389            method,
     390            target.address, target.endpoint,
     391            size,
     392            &transfer->reply);
     393       
     394        if (size > 0) {
     395                rc = async_data_write_start(phone, buffer, size);
     396                if (rc != EOK) {
     397                        async_wait_for(transfer->request, NULL);
     398                        return rc;
     399                }
     400        }
     401       
     402        *handle = (usb_handle_t) transfer;
     403       
     404        return EOK;
     405}
     406
     407static int async_recv_buffer(int phone, int method,
     408    usb_target_t target,
     409    void *buffer, size_t size, size_t *actual_size,
     410    usb_handle_t *handle)
     411{
     412        if (phone < 0) {
     413                return EINVAL;
     414        }
     415       
     416        if ((buffer == NULL) && (size > 0)) {
     417                return EINVAL;
     418        }
     419       
     420        if (handle == NULL) {
     421                return EINVAL;
     422        }
     423
     424        transfer_info_t *transfer
     425            = (transfer_info_t *) malloc(sizeof(transfer_info_t));
     426        if (transfer == NULL) {
     427                return ENOMEM;
     428        }
     429       
     430        transfer->size_transferred = actual_size;
     431        transfer->buffer = buffer;
     432        transfer->size = size;
     433        transfer->phone = phone;
     434       
     435        transfer->request = async_send_3(phone,
     436            method,
     437            target.address, target.endpoint,
     438            size,
     439            &transfer->reply);
     440       
     441        *handle = (usb_handle_t) transfer;
     442       
     443        return EOK;
     444}
     445
     446static int read_buffer_in(int phone, ipcarg_t hash,
     447    void *buffer, size_t size, size_t *actual_size)
     448{
     449        ipc_call_t answer_data;
     450        ipcarg_t answer_rc;
     451        aid_t req;
     452        int rc;
     453       
     454        req = async_send_1(phone,
     455            IPC_M_USB_HCD_GET_BUFFER_ASYNC,
     456            hash,
     457            &answer_data);
     458       
     459        rc = async_data_read_start(phone, buffer, size);
     460        if (rc != EOK) {
     461                async_wait_for(req, NULL);
     462                return EINVAL;
     463        }
     464       
     465        async_wait_for(req, &answer_rc);
     466        rc = (int)answer_rc;
     467       
     468        if (rc != EOK) {
     469                return rc;
     470        }
     471       
     472        *actual_size = IPC_GET_ARG1(answer_data);
     473       
     474        return EOK;
     475}
     476
     477
     478int usb_hcd_async_wait_for(usb_handle_t handle)
     479{
     480        if (handle == 0) {
     481                return EBADMEM;
     482        }
     483       
     484        int rc = EOK;
     485       
     486        transfer_info_t *transfer = (transfer_info_t *) handle;
     487       
     488        ipcarg_t answer_rc;
     489        async_wait_for(transfer->request, &answer_rc);
     490       
     491        if (answer_rc != EOK) {
     492                rc = (int) answer_rc;
     493                goto leave;
     494        }
     495       
     496        /*
     497         * If the buffer is not NULL, we must accept some data.
     498         */
     499        if ((transfer->buffer != NULL) && (transfer->size > 0)) {
     500                /*
     501                 * The buffer hash identifies the data on the server
     502                 * side.
     503                 * We will use it when actually reading-in the data.
     504                 */
     505                ipcarg_t buffer_hash = IPC_GET_ARG1(transfer->reply);
     506                if (buffer_hash == 0) {
     507                        rc = ENOENT;
     508                        goto leave;
     509                }
     510               
     511                size_t actual_size;
     512                rc = read_buffer_in(transfer->phone, buffer_hash,
     513                    transfer->buffer, transfer->size, &actual_size);
     514               
     515                if (rc != EOK) {
     516                        goto leave;
     517                }
     518               
     519                if (transfer->size_transferred) {
     520                        *(transfer->size_transferred) = actual_size;
     521                }
     522        }
     523       
     524leave:
     525        free(transfer);
     526       
     527        return rc;
     528}
     529
     530int usb_hcd_async_transfer_interrupt_out(int hcd_phone,
     531    usb_target_t target,
     532    void *buffer, size_t size,
     533    usb_handle_t *handle)
     534{
     535        return async_send_buffer(hcd_phone,
     536            IPC_M_USB_HCD_INTERRUPT_OUT_ASYNC,
     537            target,
     538            buffer, size,
     539            handle);
     540}
     541
     542int usb_hcd_async_transfer_interrupt_in(int hcd_phone,
     543    usb_target_t target,
     544    void *buffer, size_t size, size_t *actual_size,
     545    usb_handle_t *handle)
     546{
     547        return async_recv_buffer(hcd_phone,
     548            IPC_M_USB_HCD_INTERRUPT_IN_ASYNC,
     549            target,
     550            buffer, size, actual_size,
     551            handle);
     552}
     553
     554int usb_hcd_async_transfer_control_write_setup(int hcd_phone,
     555    usb_target_t target,
     556    void *buffer, size_t size,
     557    usb_handle_t *handle)
     558{
     559        return async_send_buffer(hcd_phone,
     560            IPC_M_USB_HCD_CONTROL_WRITE_SETUP_ASYNC,
     561            target,
     562            buffer, size,
     563            handle);
     564}
     565
     566int usb_hcd_async_transfer_control_write_data(int hcd_phone,
     567    usb_target_t target,
     568    void *buffer, size_t size,
     569    usb_handle_t *handle)
     570{
     571        return async_send_buffer(hcd_phone,
     572            IPC_M_USB_HCD_CONTROL_WRITE_DATA_ASYNC,
     573            target,
     574            buffer, size,
     575            handle);
     576}
     577
     578int usb_hcd_async_transfer_control_write_status(int hcd_phone,
     579    usb_target_t target,
     580    usb_handle_t *handle)
     581{
     582        return async_recv_buffer(hcd_phone,
     583            IPC_M_USB_HCD_CONTROL_WRITE_STATUS_ASYNC,
     584            target,
     585            NULL, 0, NULL,
     586            handle);
     587}
     588
     589int usb_hcd_async_transfer_control_read_setup(int hcd_phone,
     590    usb_target_t target,
     591    void *buffer, size_t size,
     592    usb_handle_t *handle)
     593{
     594        return async_send_buffer(hcd_phone,
     595            IPC_M_USB_HCD_CONTROL_READ_SETUP_ASYNC,
     596            target,
     597            buffer, size,
     598            handle);
     599}
     600
     601int usb_hcd_async_transfer_control_read_data(int hcd_phone,
     602    usb_target_t target,
     603    void *buffer, size_t size, size_t *actual_size,
     604    usb_handle_t *handle)
     605{
     606        return async_recv_buffer(hcd_phone,
     607            IPC_M_USB_HCD_CONTROL_READ_DATA_ASYNC,
     608            target,
     609            buffer, size, actual_size,
     610            handle);
     611}
     612
     613int usb_hcd_async_transfer_control_read_status(int hcd_phone,
     614    usb_target_t target,
     615    usb_handle_t *handle)
     616{
     617        return async_send_buffer(hcd_phone,
     618            IPC_M_USB_HCD_CONTROL_READ_STATUS_ASYNC,
     619            target,
     620            NULL, 0,
     621            handle);
     622}
     623
    341624/**
    342625 * @}
Note: See TracChangeset for help on using the changeset viewer.