Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 2185776 in mainline


Ignore:
Timestamp:
2010-10-26T13:47:46Z (10 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
master
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.

Location:
uspace
Files:
5 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 * @}
  • uspace/lib/usb/hcd.h

    r23cb44b r2185776  
    156156        IPC_M_USB_HCD_CONTROL_READ_DATA,
    157157        IPC_M_USB_HCD_CONTROL_READ_STATUS,
     158       
     159        IPC_M_USB_HCD_GET_BUFFER_ASYNC,
     160       
     161        IPC_M_USB_HCD_INTERRUPT_OUT_ASYNC,
     162        IPC_M_USB_HCD_INTERRUPT_IN_ASYNC,
     163       
     164        IPC_M_USB_HCD_CONTROL_WRITE_SETUP_ASYNC,
     165        IPC_M_USB_HCD_CONTROL_WRITE_DATA_ASYNC,
     166        IPC_M_USB_HCD_CONTROL_WRITE_STATUS_ASYNC,
     167       
     168        IPC_M_USB_HCD_CONTROL_READ_SETUP_ASYNC,
     169        IPC_M_USB_HCD_CONTROL_READ_DATA_ASYNC,
     170        IPC_M_USB_HCD_CONTROL_READ_STATUS_ASYNC,
    158171        /* IPC_M_USB_HCD_ */
    159172} usb_hcd_method_t;
     
    215228    usb_transaction_handle_t *);
    216229
     230int usb_hcd_async_transfer_interrupt_out(int, usb_target_t,
     231    void *, size_t, usb_handle_t *);
     232int usb_hcd_async_transfer_interrupt_in(int, usb_target_t,
     233    void *, size_t, size_t *, usb_handle_t *);
     234
     235int usb_hcd_async_transfer_control_write_setup(int, usb_target_t,
     236    void *, size_t, usb_handle_t *);
     237int usb_hcd_async_transfer_control_write_data(int, usb_target_t,
     238    void *, size_t, usb_handle_t *);
     239int usb_hcd_async_transfer_control_write_status(int, usb_target_t,
     240    usb_handle_t *);
     241
     242int usb_hcd_async_transfer_control_read_setup(int, usb_target_t,
     243    void *, size_t, usb_handle_t *);
     244int usb_hcd_async_transfer_control_read_data(int, usb_target_t,
     245    void *, size_t, size_t *, usb_handle_t *);
     246int usb_hcd_async_transfer_control_read_status(int, usb_target_t,
     247    usb_handle_t *);
     248
     249int usb_hcd_async_wait_for(usb_handle_t);
     250
    217251#endif
    218252/**
  • uspace/lib/usb/usb.h

    r23cb44b r2185776  
    3737
    3838#include <sys/types.h>
     39#include <ipc/ipc.h>
    3940
    4041/** USB transfer type. */
     
    8384}
    8485
     86/** General handle type.
     87 * Used by various USB functions as opaque handle.
     88 */
     89typedef ipcarg_t usb_handle_t;
     90
    8591#endif
    8692/**
  • uspace/srv/hw/bus/usb/hcd/virtual/connhost.c

    r23cb44b r2185776  
    5252} transaction_details_t;
    5353
     54
    5455/** Callback for outgoing transaction.
    5556 */
     
    193194
    194195
     196typedef struct {
     197        ipc_callid_t caller;
     198        void *buffer;
     199        size_t size;
     200} async_transaction_t;
     201
     202static void async_out_callback(void * buffer, size_t len,
     203    usb_transaction_outcome_t outcome, void * arg)
     204{
     205        async_transaction_t * trans = (async_transaction_t *)arg;
     206       
     207        dprintf(2, "async_out_callback(buffer, %u, %d, %p) -> %x",
     208            len, outcome, arg, trans->caller);
     209       
     210        // FIXME - answer according to outcome
     211        ipc_answer_1(trans->caller, EOK, 0);
     212       
     213        free(trans);
     214        if (buffer) {
     215                free(buffer);
     216        }
     217        dprintf(4, "async_out_callback answered");
     218}
     219
     220static void async_to_device(ipc_callid_t iid, ipc_call_t icall, bool setup_transaction)
     221{
     222        size_t expected_len = IPC_GET_ARG3(icall);
     223        usb_target_t target = {
     224                .address = IPC_GET_ARG1(icall),
     225                .endpoint = IPC_GET_ARG2(icall)
     226        };
     227       
     228        dprintf(1, "async_to_device: dev=%d:%d, size=%d, iid=%x",
     229            target.address, target.endpoint, expected_len, iid);
     230       
     231        size_t len = 0;
     232        void * buffer = NULL;
     233        if (expected_len > 0) {
     234                int rc = async_data_write_accept(&buffer, false,
     235                    1, USB_MAX_PAYLOAD_SIZE,
     236                    0, &len);
     237               
     238                if (rc != EOK) {
     239                        ipc_answer_0(iid, rc);
     240                        return;
     241                }
     242        }
     243       
     244        async_transaction_t * trans = malloc(sizeof(async_transaction_t));
     245        trans->caller = iid;
     246        trans->buffer = NULL;
     247        trans->size = 0;
     248       
     249        hc_add_transaction_to_device(setup_transaction, target,
     250            buffer, len,
     251            async_out_callback, trans);
     252       
     253        dprintf(2, "async transaction to device scheduled (%p)", trans);
     254}
     255
     256static void async_in_callback(void * buffer, size_t len,
     257    usb_transaction_outcome_t outcome, void * arg)
     258{       
     259        async_transaction_t * trans = (async_transaction_t *)arg;
     260       
     261        dprintf(2, "async_in_callback(buffer, %u, %d, %p) -> %x",
     262            len, outcome, arg, trans->caller);
     263       
     264        trans->buffer = buffer;
     265        trans->size = len;
     266       
     267        ipc_callid_t caller = trans->caller;
     268       
     269        if (buffer == NULL) {
     270                free(trans);
     271                trans = NULL;
     272        }
     273       
     274       
     275        // FIXME - answer according to outcome
     276        ipc_answer_1(caller, EOK, (ipcarg_t)trans);
     277        dprintf(4, "async_in_callback answered (%#x)", (ipcarg_t)trans);
     278}
     279
     280static void async_from_device(ipc_callid_t iid, ipc_call_t icall)
     281{
     282        usb_target_t target = {
     283                .address = IPC_GET_ARG1(icall),
     284                .endpoint = IPC_GET_ARG2(icall)
     285        };
     286        size_t len = IPC_GET_ARG3(icall);
     287       
     288        dprintf(1, "async_from_device: dev=%d:%d, size=%d, iid=%x",
     289            target.address, target.endpoint, len, iid);
     290       
     291        void * buffer = NULL;
     292        if (len > 0) {
     293                buffer = malloc(len);
     294        }
     295       
     296        async_transaction_t * trans = malloc(sizeof(async_transaction_t));
     297        trans->caller = iid;
     298        trans->buffer = NULL;
     299        trans->size = 0;
     300       
     301        hc_add_transaction_from_device(target,
     302            buffer, len,
     303            async_in_callback, trans);
     304       
     305        dprintf(2, "async transfer from device scheduled (%p)", trans);
     306}
     307
     308static void async_get_buffer(ipc_callid_t iid, ipc_call_t icall)
     309{
     310        ipcarg_t buffer_hash = IPC_GET_ARG1(icall);
     311        async_transaction_t * trans = (async_transaction_t *)buffer_hash;
     312        if (trans == NULL) {
     313                ipc_answer_0(iid, ENOENT);
     314                return;
     315        }
     316        if (trans->buffer == NULL) {
     317                ipc_answer_0(iid, EINVAL);
     318                free(trans);
     319                return;
     320        }
     321       
     322        ipc_callid_t callid;
     323        size_t accepted_size;
     324        if (!async_data_read_receive(&callid, &accepted_size)) {
     325                ipc_answer_0(iid, EINVAL);
     326                return;
     327        }
     328       
     329        if (accepted_size > trans->size) {
     330                accepted_size = trans->size;
     331        }
     332        async_data_read_finalize(callid, trans->buffer, accepted_size);
     333       
     334        ipc_answer_1(iid, EOK, accepted_size);
     335       
     336        free(trans->buffer);
     337        free(trans);
     338}
     339
    195340
    196341/** Connection handler for communcation with host.
     
    214359               
    215360                callid = async_get_call(&call);
     361               
     362                dprintf(6, "host on %#x calls [%x: %u (%u, %u, %u, %u, %u)]",
     363                    phone_hash,
     364                    callid,
     365                    IPC_GET_METHOD(call),
     366                    IPC_GET_ARG1(call), IPC_GET_ARG2(call), IPC_GET_ARG3(call),
     367                    IPC_GET_ARG4(call), IPC_GET_ARG5(call));
    216368               
    217369                switch (IPC_GET_METHOD(call)) {
     
    231383                                break;
    232384                       
     385                        /* callback-result methods */
    233386                       
    234387                        case IPC_M_USB_HCD_INTERRUPT_OUT:
     
    259412                                    true, host_phone);
    260413                                break;
    261                                
    262                         case IPC_M_USB_HCD_CONTROL_READ_DATA:
    263                         case IPC_M_USB_HCD_CONTROL_READ_STATUS:
     414                       
     415                        /* async methods */
     416                       
     417                        case IPC_M_USB_HCD_GET_BUFFER_ASYNC:
     418                                async_get_buffer(callid, call);
     419                                break;
     420       
     421                        case IPC_M_USB_HCD_INTERRUPT_OUT_ASYNC:
     422                        case IPC_M_USB_HCD_CONTROL_WRITE_DATA_ASYNC:
     423                        case IPC_M_USB_HCD_CONTROL_READ_STATUS_ASYNC:
     424                                async_to_device(callid, call, false);
     425                                break;
     426                       
     427                        case IPC_M_USB_HCD_CONTROL_WRITE_SETUP_ASYNC:
     428                        case IPC_M_USB_HCD_CONTROL_READ_SETUP_ASYNC:
     429                                async_to_device(callid, call, true);
     430                                break;
     431                       
     432                        case IPC_M_USB_HCD_INTERRUPT_IN_ASYNC:
     433                        case IPC_M_USB_HCD_CONTROL_WRITE_STATUS_ASYNC:
     434                        case IPC_M_USB_HCD_CONTROL_READ_DATA_ASYNC:
     435                                async_from_device(callid, call);
     436                                break;
     437                       
     438                        /* end of known methods */
    264439                       
    265440                        default:
  • uspace/srv/hw/bus/usb/hcd/virtual/devices.c

    r23cb44b r2185776  
    147147        if (virthub_dev.address == transaction->target.address) {
    148148                size_t tmp;
     149                dprintf(3, "sending `%s' transaction to hub",
     150                    usbvirt_str_transaction_type(transaction->type));
    149151                switch (transaction->type) {
    150152                        case USBVIRT_TRANSACTION_SETUP:
     
    170172                                break;
    171173                }
     174                dprintf(4, "transaction on hub processed...");
    172175        }
    173176       
Note: See TracChangeset for help on using the changeset viewer.