Changeset 47c573a in mainline


Ignore:
Timestamp:
2011-02-14T21:01:28Z (13 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
d4ee4e2, fa2f79d
Parents:
567d002
Message:

Pipe API independent of the old one

The low IPC level was copied from the old API, modified and also
fortified.

This is a first step towards complete removal of the old API.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/usb/src/pipesio.c

    r567d002 r47c573a  
    3636 * guarantee that a call to particular function will not trigger a fibril
    3737 * switch.
    38  * The initialization functions may actually involve contacting some other
    39  * task, starting/ending a session might involve asynchronous IPC and since
    40  * the transfer functions uses IPC, asynchronous nature of them is obvious.
    41  * The pseudo synchronous versions for the transfers internally call the
    42  * asynchronous ones and so fibril switch is possible in them as well.
     38 *
     39 * Note about the implementation: the transfer requests are always divided
     40 * into two functions.
     41 * The outer one does checking of input parameters (e.g. that session was
     42 * already started, buffers are not NULL etc), while the inner one
     43 * (with _no_checks suffix) does the actual IPC (it checks for IPC errors,
     44 * obviously).
    4345 */
    4446#include <usb/usb.h>
     
    4648#include <errno.h>
    4749#include <assert.h>
    48 #include <usb/usbdrv.h>
    49 
    50 #define _PREPARE_TARGET(varname, pipe) \
    51         usb_target_t varname = { \
    52                 .address = (pipe)->wire->address, \
    53                 .endpoint = (pipe)->endpoint_no \
    54         }
    55 
    56 
    57 /** Request a read (in) transfer on an endpoint pipe.
     50#include <usbhc_iface.h>
     51
     52/** Request an in transfer, no checking of input parameters.
    5853 *
    5954 * @param[in] pipe Pipe used for the transfer.
     
    6358 * @return Error code.
    6459 */
     60static int usb_endpoint_pipe_read_no_checks(usb_endpoint_pipe_t *pipe,
     61    void *buffer, size_t size, size_t *size_transfered)
     62{
     63        /*
     64         * Get corresponding IPC method.
     65         * In future, replace with static array of mappings
     66         * transfer type -> method.
     67         */
     68        usbhc_iface_funcs_t ipc_method;
     69        switch (pipe->transfer_type) {
     70                case USB_TRANSFER_INTERRUPT:
     71                        ipc_method = IPC_M_USBHC_INTERRUPT_IN;
     72                        break;
     73                default:
     74                        return ENOTSUP;
     75        }
     76
     77        /*
     78         * Make call identifying target USB device and type of transfer.
     79         */
     80        aid_t opening_request = async_send_3(pipe->hc_phone,
     81            DEV_IFACE_ID(USBHC_DEV_IFACE), ipc_method,
     82            pipe->wire->address, pipe->endpoint_no,
     83            NULL);
     84        if (opening_request == 0) {
     85                return ENOMEM;
     86        }
     87
     88        /*
     89         * Retrieve the data.
     90         */
     91        ipc_call_t data_request_call;
     92        aid_t data_request = async_data_read(pipe->hc_phone, buffer, size,
     93            &data_request_call);
     94
     95        if (data_request == 0) {
     96                /*
     97                 * FIXME:
     98                 * How to let the other side know that we want to abort?
     99                 */
     100                async_wait_for(opening_request, NULL);
     101                return ENOMEM;
     102        }
     103
     104        /*
     105         * Wait for the answer.
     106         */
     107        sysarg_t data_request_rc;
     108        sysarg_t opening_request_rc;
     109        async_wait_for(data_request, &data_request_rc);
     110        async_wait_for(opening_request, &opening_request_rc);
     111
     112        if (data_request_rc != EOK) {
     113                return (int) data_request_rc;
     114        }
     115        if (opening_request_rc != EOK) {
     116                return (int) opening_request_rc;
     117        }
     118
     119        *size_transfered = IPC_GET_ARG2(data_request_call);
     120
     121        return EOK;
     122}
     123
     124
     125/** Request a read (in) transfer on an endpoint pipe.
     126 *
     127 * @param[in] pipe Pipe used for the transfer.
     128 * @param[out] buffer Buffer where to store the data.
     129 * @param[in] size Size of the buffer (in bytes).
     130 * @param[out] size_transfered Number of bytes that were actually transfered.
     131 * @return Error code.
     132 */
    65133int usb_endpoint_pipe_read(usb_endpoint_pipe_t *pipe,
    66134    void *buffer, size_t size, size_t *size_transfered)
     
    68136        assert(pipe);
    69137
     138        if (buffer == NULL) {
     139                        return EINVAL;
     140        }
     141
     142        if (size == 0) {
     143                return EINVAL;
     144        }
     145
    70146        if (pipe->hc_phone < 0) {
    71147                return EBADF;
     
    76152        }
    77153
     154        if (pipe->transfer_type == USB_TRANSFER_CONTROL) {
     155                return EBADF;
     156        }
     157
     158        size_t act_size = 0;
    78159        int rc;
    79         _PREPARE_TARGET(target, pipe);
    80         usb_handle_t handle;
    81 
     160
     161        rc = usb_endpoint_pipe_read_no_checks(pipe, buffer, size, &act_size);
     162        if (rc != EOK) {
     163                return rc;
     164        }
     165
     166        if (size_transfered != NULL) {
     167                *size_transfered = act_size;
     168        }
     169
     170        return EOK;
     171}
     172
     173
     174
     175
     176/** Request an out transfer, no checking of input parameters.
     177 *
     178 * @param[in] pipe Pipe used for the transfer.
     179 * @param[in] buffer Buffer with data to transfer.
     180 * @param[in] size Size of the buffer (in bytes).
     181 * @return Error code.
     182 */
     183static int usb_endpoint_pipe_write_no_check(usb_endpoint_pipe_t *pipe,
     184    void *buffer, size_t size)
     185{
     186        /*
     187         * Get corresponding IPC method.
     188         * In future, replace with static array of mappings
     189         * transfer type -> method.
     190         */
     191        usbhc_iface_funcs_t ipc_method;
    82192        switch (pipe->transfer_type) {
    83193                case USB_TRANSFER_INTERRUPT:
    84                         rc = usb_drv_async_interrupt_in(pipe->hc_phone, target,
    85                             buffer, size, size_transfered, &handle);
    86                         break;
    87                 case USB_TRANSFER_CONTROL:
    88                         rc = EBADF;
     194                        ipc_method = IPC_M_USBHC_INTERRUPT_OUT;
    89195                        break;
    90196                default:
    91                         rc = ENOTSUP;
    92                         break;
    93         }
    94 
     197                        return ENOTSUP;
     198        }
     199
     200        /*
     201         * Make call identifying target USB device and type of transfer.
     202         */
     203        aid_t opening_request = async_send_3(pipe->hc_phone,
     204            DEV_IFACE_ID(USBHC_DEV_IFACE), ipc_method,
     205            pipe->wire->address, pipe->endpoint_no,
     206            NULL);
     207        if (opening_request == 0) {
     208                return ENOMEM;
     209        }
     210
     211        /*
     212         * Send the data.
     213         */
     214        int rc = async_data_write_start(pipe->hc_phone, buffer, size);
    95215        if (rc != EOK) {
     216                async_wait_for(opening_request, NULL);
    96217                return rc;
    97218        }
    98219
    99         rc = usb_drv_async_wait_for(handle);
    100 
    101         return rc;
     220        /*
     221         * Wait for the answer.
     222         */
     223        sysarg_t opening_request_rc;
     224        async_wait_for(opening_request, &opening_request_rc);
     225
     226        return (int) opening_request_rc;
    102227}
    103228
     
    114239        assert(pipe);
    115240
     241        if (buffer == NULL) {
     242                return EINVAL;
     243        }
     244
     245        if (size == 0) {
     246                return EINVAL;
     247        }
     248
    116249        if (pipe->hc_phone < 0) {
    117250                return EBADF;
     
    122255        }
    123256
    124         int rc;
    125         _PREPARE_TARGET(target, pipe);
    126         usb_handle_t handle;
    127 
    128         switch (pipe->transfer_type) {
    129                 case USB_TRANSFER_INTERRUPT:
    130                         rc = usb_drv_async_interrupt_out(pipe->hc_phone, target,
    131                             buffer, size, &handle);
    132                         break;
    133                 case USB_TRANSFER_CONTROL:
    134                         rc = EBADF;
    135                         break;
    136                 default:
    137                         rc = ENOTSUP;
    138                         break;
    139         }
    140 
    141         if (rc != EOK) {
    142                 return rc;
    143         }
    144 
    145         rc = usb_drv_async_wait_for(handle);
     257        if (pipe->transfer_type == USB_TRANSFER_CONTROL) {
     258                return EBADF;
     259        }
     260
     261        int rc = usb_endpoint_pipe_write_no_check(pipe, buffer, size);
    146262
    147263        return rc;
     
    149265
    150266
    151 /** Request a control read transfer on an endpoint pipe.
    152  *
    153  * This function encapsulates all three stages of a control transfer.
     267/** Request a control read transfer, no checking of input parameters.
    154268 *
    155269 * @param[in] pipe Pipe used for the transfer.
     
    162276 * @return Error code.
    163277 */
     278static int usb_endpoint_pipe_control_read_no_check(usb_endpoint_pipe_t *pipe,
     279    void *setup_buffer, size_t setup_buffer_size,
     280    void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size)
     281{
     282        /*
     283         * Make call identifying target USB device and control transfer type.
     284         */
     285        aid_t opening_request = async_send_3(pipe->hc_phone,
     286            DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_CONTROL_READ,
     287            pipe->wire->address, pipe->endpoint_no,
     288            NULL);
     289        if (opening_request == 0) {
     290                return ENOMEM;
     291        }
     292
     293        /*
     294         * Send the setup packet.
     295         */
     296        int rc = async_data_write_start(pipe->hc_phone,
     297            setup_buffer, setup_buffer_size);
     298        if (rc != EOK) {
     299                async_wait_for(opening_request, NULL);
     300                return rc;
     301        }
     302
     303        /*
     304         * Retrieve the data.
     305         */
     306        ipc_call_t data_request_call;
     307        aid_t data_request = async_data_read(pipe->hc_phone,
     308            data_buffer, data_buffer_size,
     309            &data_request_call);
     310        if (data_request == 0) {
     311                async_wait_for(opening_request, NULL);
     312                return ENOMEM;
     313        }
     314
     315        /*
     316         * Wait for the answer.
     317         */
     318        sysarg_t data_request_rc;
     319        sysarg_t opening_request_rc;
     320        async_wait_for(data_request, &data_request_rc);
     321        async_wait_for(opening_request, &opening_request_rc);
     322
     323        if (data_request_rc != EOK) {
     324                return (int) data_request_rc;
     325        }
     326        if (opening_request_rc != EOK) {
     327                return (int) opening_request_rc;
     328        }
     329
     330        *data_transfered_size = IPC_GET_ARG2(data_request_call);
     331
     332        return EOK;
     333}
     334
     335/** Request a control read transfer on an endpoint pipe.
     336 *
     337 * This function encapsulates all three stages of a control transfer.
     338 *
     339 * @param[in] pipe Pipe used for the transfer.
     340 * @param[in] setup_buffer Buffer with the setup packet.
     341 * @param[in] setup_buffer_size Size of the setup packet (in bytes).
     342 * @param[out] data_buffer Buffer for incoming data.
     343 * @param[in] data_buffer_size Size of the buffer for incoming data (in bytes).
     344 * @param[out] data_transfered_size Number of bytes that were actually
     345 *                                  transfered during the DATA stage.
     346 * @return Error code.
     347 */
    164348int usb_endpoint_pipe_control_read(usb_endpoint_pipe_t *pipe,
    165349    void *setup_buffer, size_t setup_buffer_size,
     
    168352        assert(pipe);
    169353
     354        if ((setup_buffer == NULL) || (setup_buffer_size == 0)) {
     355                return EINVAL;
     356        }
     357
     358        if ((data_buffer == NULL) || (data_buffer_size == 0)) {
     359                return EINVAL;
     360        }
     361
    170362        if (pipe->hc_phone < 0) {
    171363                return EBADF;
     
    177369        }
    178370
    179         int rc;
    180         _PREPARE_TARGET(target, pipe);
    181         usb_handle_t handle;
    182 
    183         rc = usb_drv_async_control_read(pipe->hc_phone, target,
     371        size_t act_size = 0;
     372        int rc = usb_endpoint_pipe_control_read_no_check(pipe,
    184373            setup_buffer, setup_buffer_size,
    185             data_buffer, data_buffer_size, data_transfered_size,
    186             &handle);
     374            data_buffer, data_buffer_size, &act_size);
    187375
    188376        if (rc != EOK) {
     
    190378        }
    191379
    192         rc = usb_drv_async_wait_for(handle);
    193 
    194         return rc;
    195 }
    196 
    197 
    198 /** Request a control write transfer on an endpoint pipe.
    199  *
    200  * This function encapsulates all three stages of a control transfer.
     380        if (data_transfered_size != NULL) {
     381                *data_transfered_size = act_size;
     382        }
     383
     384        return EOK;
     385}
     386
     387
     388/** Request a control write transfer, no checking of input parameters.
    201389 *
    202390 * @param[in] pipe Pipe used for the transfer.
     
    207395 * @return Error code.
    208396 */
     397static int usb_endpoint_pipe_control_write_no_check(usb_endpoint_pipe_t *pipe,
     398    void *setup_buffer, size_t setup_buffer_size,
     399    void *data_buffer, size_t data_buffer_size)
     400{
     401        /*
     402         * Make call identifying target USB device and control transfer type.
     403         */
     404        aid_t opening_request = async_send_4(pipe->hc_phone,
     405            DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_CONTROL_WRITE,
     406            pipe->wire->address, pipe->endpoint_no,
     407            data_buffer_size,
     408            NULL);
     409        if (opening_request == 0) {
     410                return ENOMEM;
     411        }
     412
     413        /*
     414         * Send the setup packet.
     415         */
     416        int rc = async_data_write_start(pipe->hc_phone,
     417            setup_buffer, setup_buffer_size);
     418        if (rc != EOK) {
     419                async_wait_for(opening_request, NULL);
     420                return rc;
     421        }
     422
     423        /*
     424         * Send the data (if any).
     425         */
     426        if (data_buffer_size > 0) {
     427                rc = async_data_write_start(pipe->hc_phone,
     428                    data_buffer, data_buffer_size);
     429                if (rc != EOK) {
     430                        async_wait_for(opening_request, NULL);
     431                        return rc;
     432                }
     433        }
     434
     435        /*
     436         * Wait for the answer.
     437         */
     438        sysarg_t opening_request_rc;
     439        async_wait_for(opening_request, &opening_request_rc);
     440
     441        return (int) opening_request_rc;
     442}
     443
     444/** Request a control write transfer on an endpoint pipe.
     445 *
     446 * This function encapsulates all three stages of a control transfer.
     447 *
     448 * @param[in] pipe Pipe used for the transfer.
     449 * @param[in] setup_buffer Buffer with the setup packet.
     450 * @param[in] setup_buffer_size Size of the setup packet (in bytes).
     451 * @param[in] data_buffer Buffer with data to be sent.
     452 * @param[in] data_buffer_size Size of the buffer with outgoing data (in bytes).
     453 * @return Error code.
     454 */
    209455int usb_endpoint_pipe_control_write(usb_endpoint_pipe_t *pipe,
    210456    void *setup_buffer, size_t setup_buffer_size,
     
    213459        assert(pipe);
    214460
     461        if ((setup_buffer == NULL) || (setup_buffer_size == 0)) {
     462                return EINVAL;
     463        }
     464
     465        if ((data_buffer == NULL) && (data_buffer_size > 0)) {
     466                return EINVAL;
     467        }
     468
     469        if ((data_buffer != NULL) && (data_buffer_size == 0)) {
     470                return EINVAL;
     471        }
     472
    215473        if (pipe->hc_phone < 0) {
    216474                return EBADF;
     
    222480        }
    223481
    224         int rc;
    225         _PREPARE_TARGET(target, pipe);
    226         usb_handle_t handle;
    227 
    228         rc = usb_drv_async_control_write(pipe->hc_phone, target,
    229             setup_buffer, setup_buffer_size,
    230             data_buffer, data_buffer_size,
    231             &handle);
    232 
    233         if (rc != EOK) {
    234                 return rc;
    235         }
    236 
    237         rc = usb_drv_async_wait_for(handle);
     482        int rc = usb_endpoint_pipe_control_write_no_check(pipe,
     483            setup_buffer, setup_buffer_size, data_buffer, data_buffer_size);
    238484
    239485        return rc;
Note: See TracChangeset for help on using the changeset viewer.