Ignore:
File:
1 edited

Legend:

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

    re936e8e r2a11192  
    3131 */
    3232/** @file
    33  * USB endpoint pipes miscellaneous functions.
     33 * Communication between device drivers and host controller driver.
     34 *
     35 * Note on synchronousness of the operations: there is ABSOLUTELY NO
     36 * guarantee that a call to particular function will not trigger a fibril
     37 * 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.
    3443 */
    3544#include <usb/usb.h>
    3645#include <usb/pipes.h>
    37 #include <usbhc_iface.h>
    38 #include <usb_iface.h>
    3946#include <errno.h>
    4047#include <assert.h>
    41 
    42 /** Tell USB address assigned to given device.
    43  *
    44  * @param phone Phone to parent device.
    45  * @param dev Device in question.
    46  * @return USB address or error code.
    47  */
    48 static usb_address_t get_my_address(int phone, device_t *dev)
    49 {
    50         sysarg_t address;
    51         int rc = async_req_2_1(phone, DEV_IFACE_ID(USB_DEV_IFACE),
    52             IPC_M_USB_GET_ADDRESS,
    53             dev->handle, &address);
    54 
     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/** Initialize connection to USB device.
     57 *
     58 * @param connection Connection structure to be initialized.
     59 * @param device Generic device backing the USB device.
     60 * @return Error code.
     61 */
     62int usb_device_connection_initialize_from_device(
     63    usb_device_connection_t *connection, device_t *device)
     64{
     65        assert(connection);
     66        assert(device);
     67
     68        int rc;
     69        devman_handle_t hc_handle;
     70        usb_address_t my_address;
     71
     72        rc = usb_drv_find_hc(device, &hc_handle);
    5573        if (rc != EOK) {
    5674                return rc;
    5775        }
    5876
    59         return (usb_address_t) address;
    60 }
    61 
    62 /** Tell USB interface assigned to given device.
    63  *
    64  * @param device Device in question.
    65  * @return Interface number (negative code means any).
    66  */
    67 int usb_device_get_assigned_interface(device_t *device)
    68 {
    69         int parent_phone = devman_parent_device_connect(device->handle,
    70             IPC_FLAG_BLOCKING);
    71         if (parent_phone < 0) {
    72                 return -1;
    73         }
    74 
    75         sysarg_t iface_no;
    76         int rc = async_req_2_1(parent_phone, DEV_IFACE_ID(USB_DEV_IFACE),
    77             IPC_M_USB_GET_INTERFACE,
    78             device->handle, &iface_no);
    79 
    80         async_hangup(parent_phone);
    81 
    82         if (rc != EOK) {
    83                 return -1;
    84         }
    85 
    86         return (int) iface_no;
    87 }
    88 
    89 /** Initialize connection to USB device.
    90  *
    91  * @param connection Connection structure to be initialized.
    92  * @param device Generic device backing the USB device.
    93  * @return Error code.
    94  */
    95 int usb_device_connection_initialize_from_device(
    96     usb_device_connection_t *connection, device_t *device)
    97 {
    98         assert(connection);
    99         assert(device);
    100 
    101         int rc;
    102         devman_handle_t hc_handle;
    103         usb_address_t my_address;
    104 
    105         rc = usb_hc_find(device->handle, &hc_handle);
    106         if (rc != EOK) {
    107                 return rc;
    108         }
    109 
    110         int parent_phone = devman_parent_device_connect(device->handle,
    111             IPC_FLAG_BLOCKING);
    112         if (parent_phone < 0) {
    113                 return parent_phone;
    114         }
    115 
    116         my_address = get_my_address(parent_phone, device);
     77        int hc_phone = devman_device_connect(hc_handle, 0);
     78        if (hc_phone < 0) {
     79                return hc_phone;
     80        }
     81
     82        my_address = usb_drv_get_my_address(hc_phone, device);
    11783        if (my_address < 0) {
    11884                rc = my_address;
     
    12490
    12591leave:
    126         async_hangup(parent_phone);
     92        ipc_hangup(hc_phone);
    12793        return rc;
    12894}
     
    151117}
    152118
    153 /** Initialize connection to USB device on default address.
    154  *
    155  * @param dev_connection Device connection structure to be initialized.
    156  * @param hc_connection Initialized connection to host controller.
    157  * @return Error code.
    158  */
    159 int usb_device_connection_initialize_on_default_address(
    160     usb_device_connection_t *dev_connection,
    161     usb_hc_connection_t *hc_connection)
    162 {
    163         assert(dev_connection);
    164 
    165         if (hc_connection == NULL) {
    166                 return EBADMEM;
    167         }
    168 
    169         return usb_device_connection_initialize(dev_connection,
    170             hc_connection->hc_handle, (usb_address_t) 0);
     119/** Initialize USB endpoint pipe.
     120 *
     121 * @param pipe Endpoint pipe to be initialized.
     122 * @param connection Connection to the USB device backing this pipe (the wire).
     123 * @param endpoint_no Endpoint number (in USB 1.1 in range 0 to 15).
     124 * @param transfer_type Transfer type (e.g. interrupt or bulk).
     125 * @param direction Endpoint direction (in/out).
     126 * @return Error code.
     127 */
     128int usb_endpoint_pipe_initialize(usb_endpoint_pipe_t *pipe,
     129    usb_device_connection_t *connection, usb_endpoint_t endpoint_no,
     130    usb_transfer_type_t transfer_type, usb_direction_t direction)
     131{
     132        assert(pipe);
     133        assert(connection);
     134
     135        pipe->wire = connection;
     136        pipe->hc_phone = -1;
     137        pipe->endpoint_no = endpoint_no;
     138        pipe->transfer_type = transfer_type;
     139        pipe->direction = direction;
     140
     141        return EOK;
     142}
     143
     144
     145/** Initialize USB endpoint pipe as the default zero control pipe.
     146 *
     147 * @param pipe Endpoint pipe to be initialized.
     148 * @param connection Connection to the USB device backing this pipe (the wire).
     149 * @return Error code.
     150 */
     151int usb_endpoint_pipe_initialize_default_control(usb_endpoint_pipe_t *pipe,
     152    usb_device_connection_t *connection)
     153{
     154        assert(pipe);
     155        assert(connection);
     156
     157        int rc = usb_endpoint_pipe_initialize(pipe, connection,
     158            0, USB_TRANSFER_CONTROL, USB_DIRECTION_BOTH);
     159
     160        return rc;
    171161}
    172162
     
    191181        assert(pipe);
    192182
    193         if (usb_endpoint_pipe_is_session_started(pipe)) {
     183        if (pipe->hc_phone >= 0) {
    194184                return EBUSY;
    195185        }
     
    217207        assert(pipe);
    218208
    219         if (!usb_endpoint_pipe_is_session_started(pipe)) {
     209        if (pipe->hc_phone < 0) {
    220210                return ENOENT;
    221211        }
    222212
    223         int rc = async_hangup(pipe->hc_phone);
     213        int rc = ipc_hangup(pipe->hc_phone);
    224214        if (rc != EOK) {
    225215                return rc;
     
    231221}
    232222
    233 /** Tell whether a session is started (open) on the endpoint pipe.
    234  *
    235  * The expected usage of this function is in assertions for some
    236  * nested functions.
    237  *
    238  * @param pipe Endpoint pipe in question.
    239  * @return Whether @p pipe has opened a session.
    240  */
    241 bool usb_endpoint_pipe_is_session_started(usb_endpoint_pipe_t *pipe)
    242 {
    243         return (pipe->hc_phone >= 0);
    244 }
     223
     224/** Request a read (in) transfer on an endpoint pipe.
     225 *
     226 * @param[in] pipe Pipe used for the transfer.
     227 * @param[out] buffer Buffer where to store the data.
     228 * @param[in] size Size of the buffer (in bytes).
     229 * @param[out] size_transfered Number of bytes that were actually transfered.
     230 * @return Error code.
     231 */
     232int usb_endpoint_pipe_read(usb_endpoint_pipe_t *pipe,
     233    void *buffer, size_t size, size_t *size_transfered)
     234{
     235        assert(pipe);
     236
     237        int rc;
     238        usb_handle_t handle;
     239
     240        rc = usb_endpoint_pipe_async_read(pipe, buffer, size, size_transfered,
     241            &handle);
     242        if (rc != EOK) {
     243                return rc;
     244        }
     245
     246        rc = usb_endpoint_pipe_wait_for(pipe, handle);
     247        return rc;
     248}
     249
     250/** Request a write (out) transfer on an endpoint pipe.
     251 *
     252 * @param[in] pipe Pipe used for the transfer.
     253 * @param[in] buffer Buffer with data to transfer.
     254 * @param[in] size Size of the buffer (in bytes).
     255 * @return Error code.
     256 */
     257int usb_endpoint_pipe_write(usb_endpoint_pipe_t *pipe,
     258    void *buffer, size_t size)
     259{
     260        assert(pipe);
     261
     262        int rc;
     263        usb_handle_t handle;
     264
     265        rc = usb_endpoint_pipe_async_write(pipe, buffer, size, &handle);
     266        if (rc != EOK) {
     267                return rc;
     268        }
     269
     270        rc = usb_endpoint_pipe_wait_for(pipe, handle);
     271        return rc;
     272}
     273
     274
     275/** Request a control read transfer on an endpoint pipe.
     276 *
     277 * This function encapsulates all three stages of a control transfer.
     278 *
     279 * @param[in] pipe Pipe used for the transfer.
     280 * @param[in] setup_buffer Buffer with the setup packet.
     281 * @param[in] setup_buffer_size Size of the setup packet (in bytes).
     282 * @param[out] data_buffer Buffer for incoming data.
     283 * @param[in] data_buffer_size Size of the buffer for incoming data (in bytes).
     284 * @param[out] data_transfered_size Number of bytes that were actually
     285 *                                  transfered during the DATA stage.
     286 * @return Error code.
     287 */
     288int usb_endpoint_pipe_control_read(usb_endpoint_pipe_t *pipe,
     289    void *setup_buffer, size_t setup_buffer_size,
     290    void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size)
     291{
     292        assert(pipe);
     293
     294        int rc;
     295        usb_handle_t handle;
     296
     297        rc = usb_endpoint_pipe_async_control_read(pipe,
     298            setup_buffer, setup_buffer_size,
     299            data_buffer, data_buffer_size, data_transfered_size,
     300            &handle);
     301        if (rc != EOK) {
     302                return rc;
     303        }
     304
     305        rc = usb_endpoint_pipe_wait_for(pipe, handle);
     306        return rc;
     307}
     308
     309
     310/** Request a control write transfer on an endpoint pipe.
     311 *
     312 * This function encapsulates all three stages of a control transfer.
     313 *
     314 * @param[in] pipe Pipe used for the transfer.
     315 * @param[in] setup_buffer Buffer with the setup packet.
     316 * @param[in] setup_buffer_size Size of the setup packet (in bytes).
     317 * @param[in] data_buffer Buffer with data to be sent.
     318 * @param[in] data_buffer_size Size of the buffer with outgoing data (in bytes).
     319 * @return Error code.
     320 */
     321int usb_endpoint_pipe_control_write(usb_endpoint_pipe_t *pipe,
     322    void *setup_buffer, size_t setup_buffer_size,
     323    void *data_buffer, size_t data_buffer_size)
     324{
     325        assert(pipe);
     326
     327        int rc;
     328        usb_handle_t handle;
     329
     330        rc = usb_endpoint_pipe_async_control_write(pipe,
     331            setup_buffer, setup_buffer_size,
     332            data_buffer, data_buffer_size,
     333            &handle);
     334        if (rc != EOK) {
     335                return rc;
     336        }
     337
     338        rc = usb_endpoint_pipe_wait_for(pipe, handle);
     339        return rc;
     340}
     341
     342
     343/** Request a read (in) transfer on an endpoint pipe (asynchronous version).
     344 *
     345 * @param[in] pipe Pipe used for the transfer.
     346 * @param[out] buffer Buffer where to store the data.
     347 * @param[in] size Size of the buffer (in bytes).
     348 * @param[out] size_transfered Number of bytes that were actually transfered.
     349 * @param[out] handle Handle of the transfer.
     350 * @return Error code.
     351 */
     352int usb_endpoint_pipe_async_read(usb_endpoint_pipe_t *pipe,
     353    void *buffer, size_t size, size_t *size_transfered,
     354    usb_handle_t *handle)
     355{
     356        assert(pipe);
     357
     358        if (pipe->hc_phone < 0) {
     359                return EBADF;
     360        }
     361
     362        if (pipe->direction != USB_DIRECTION_IN) {
     363                return EBADF;
     364        }
     365
     366        int rc;
     367        _PREPARE_TARGET(target, pipe);
     368
     369        switch (pipe->transfer_type) {
     370                case USB_TRANSFER_INTERRUPT:
     371                        rc = usb_drv_async_interrupt_in(pipe->hc_phone, target,
     372                            buffer, size, size_transfered, handle);
     373                        break;
     374                case USB_TRANSFER_CONTROL:
     375                        rc = EBADF;
     376                        break;
     377                default:
     378                        rc = ENOTSUP;
     379                        break;
     380        }
     381
     382        return rc;
     383}
     384
     385
     386/** Request a write (out) transfer on an endpoint pipe (asynchronous version).
     387 *
     388 * @param[in] pipe Pipe used for the transfer.
     389 * @param[in] buffer Buffer with data to transfer.
     390 * @param[in] size Size of the buffer (in bytes).
     391 * @param[out] handle Handle of the transfer.
     392 * @return Error code.
     393 */
     394int usb_endpoint_pipe_async_write(usb_endpoint_pipe_t *pipe,
     395    void *buffer, size_t size,
     396    usb_handle_t *handle)
     397{
     398        assert(pipe);
     399
     400        if (pipe->hc_phone < 0) {
     401                return EBADF;
     402        }
     403
     404        if (pipe->direction != USB_DIRECTION_OUT) {
     405                return EBADF;
     406        }
     407
     408        int rc;
     409        _PREPARE_TARGET(target, pipe);
     410
     411        switch (pipe->transfer_type) {
     412                case USB_TRANSFER_INTERRUPT:
     413                        rc = usb_drv_async_interrupt_out(pipe->hc_phone, target,
     414                            buffer, size, handle);
     415                        break;
     416                case USB_TRANSFER_CONTROL:
     417                        rc = EBADF;
     418                        break;
     419                default:
     420                        rc = ENOTSUP;
     421                        break;
     422        }
     423
     424        return rc;
     425}
     426
     427
     428/** Request a control read transfer on an endpoint pipe (asynchronous version).
     429 *
     430 * This function encapsulates all three stages of a control transfer.
     431 *
     432 * @param[in] pipe Pipe used for the transfer.
     433 * @param[in] setup_buffer Buffer with the setup packet.
     434 * @param[in] setup_buffer_size Size of the setup packet (in bytes).
     435 * @param[out] data_buffer Buffer for incoming data.
     436 * @param[in] data_buffer_size Size of the buffer for incoming data (in bytes).
     437 * @param[out] data_transfered_size Number of bytes that were actually
     438 *                                  transfered during the DATA stage.
     439 * @param[out] handle Handle of the transfer.
     440 * @return Error code.
     441 */
     442int usb_endpoint_pipe_async_control_read(usb_endpoint_pipe_t *pipe,
     443    void *setup_buffer, size_t setup_buffer_size,
     444    void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size,
     445    usb_handle_t *handle)
     446{
     447        assert(pipe);
     448
     449        if (pipe->hc_phone < 0) {
     450                return EBADF;
     451        }
     452
     453        if ((pipe->direction != USB_DIRECTION_BOTH)
     454            || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
     455                return EBADF;
     456        }
     457
     458        int rc;
     459        _PREPARE_TARGET(target, pipe);
     460
     461        rc = usb_drv_async_control_read(pipe->hc_phone, target,
     462            setup_buffer, setup_buffer_size,
     463            data_buffer, data_buffer_size, data_transfered_size,
     464            handle);
     465
     466        return rc;
     467}
     468
     469
     470/** Request a control write transfer on an endpoint pipe (asynchronous version).
     471 *
     472 * This function encapsulates all three stages of a control transfer.
     473 *
     474 * @param[in] pipe Pipe used for the transfer.
     475 * @param[in] setup_buffer Buffer with the setup packet.
     476 * @param[in] setup_buffer_size Size of the setup packet (in bytes).
     477 * @param[in] data_buffer Buffer with data to be sent.
     478 * @param[in] data_buffer_size Size of the buffer with outgoing data (in bytes).
     479 * @param[out] handle Handle of the transfer.
     480 * @return Error code.
     481 */
     482int usb_endpoint_pipe_async_control_write(usb_endpoint_pipe_t *pipe,
     483    void *setup_buffer, size_t setup_buffer_size,
     484    void *data_buffer, size_t data_buffer_size,
     485    usb_handle_t *handle)
     486{
     487        assert(pipe);
     488
     489        if (pipe->hc_phone < 0) {
     490                return EBADF;
     491        }
     492
     493        if ((pipe->direction != USB_DIRECTION_BOTH)
     494            || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
     495                return EBADF;
     496        }
     497
     498        int rc;
     499        _PREPARE_TARGET(target, pipe);
     500
     501        rc = usb_drv_async_control_write(pipe->hc_phone, target,
     502            setup_buffer, setup_buffer_size,
     503            data_buffer, data_buffer_size,
     504            handle);
     505
     506        return rc;
     507}
     508
     509/** Wait for transfer completion.
     510 *
     511 * The function blocks the caller fibril until the transfer associated
     512 * with given @p handle is completed.
     513 *
     514 * @param[in] pipe Pipe the transfer executed on.
     515 * @param[in] handle Transfer handle.
     516 * @return Error code.
     517 */
     518int usb_endpoint_pipe_wait_for(usb_endpoint_pipe_t *pipe, usb_handle_t handle)
     519{
     520        return usb_drv_async_wait_for(handle);
     521}
     522
    245523
    246524/**
Note: See TracChangeset for help on using the changeset viewer.