Changeset b8b1e631 in mainline for uspace/lib/usbdev/src/pipesio.c


Ignore:
Timestamp:
2011-12-03T11:10:06Z (12 years ago)
Author:
Frantisek Princ <frantisek.princ@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
30413b31
Parents:
07fd4cd1 (diff), 1f5c9c96 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge with mainline

File:
1 edited

Legend:

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

    r07fd4cd1 rb8b1e631  
    6262 * @return Error code.
    6363 */
    64 static int usb_pipe_read_no_checks(usb_pipe_t *pipe,
     64static int usb_pipe_read_no_check(usb_pipe_t *pipe, uint64_t setup,
    6565    void *buffer, size_t size, size_t *size_transfered)
    6666{
    67         /* Only interrupt and bulk transfers are supported */
     67        /* Isochronous transfer are not supported (yet) */
    6868        if (pipe->transfer_type != USB_TRANSFER_INTERRUPT &&
    69             pipe->transfer_type != USB_TRANSFER_BULK)
     69            pipe->transfer_type != USB_TRANSFER_BULK &&
     70            pipe->transfer_type != USB_TRANSFER_CONTROL)
    7071            return ENOTSUP;
    7172
    72         const usb_target_t target =
    73             {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }};
    74        
     73        int ret = pipe_add_ref(pipe, false);
     74        if (ret != EOK) {
     75                return ret;
     76        }
     77
    7578        /* Ensure serialization over the phone. */
    7679        pipe_start_transaction(pipe);
    7780        async_exch_t *exch = async_exchange_begin(pipe->hc_sess);
    78        
    79         /*
    80          * Make call identifying target USB device and type of transfer.
    81          */
    82         aid_t opening_request = async_send_2(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    83             IPC_M_USBHC_READ, target.packed, NULL);
    84        
    85         if (opening_request == 0) {
    86                 async_exchange_end(exch);
     81        if (!exch) {
    8782                pipe_end_transaction(pipe);
     83                pipe_drop_ref(pipe);
    8884                return ENOMEM;
    8985        }
    90        
    91         /*
    92          * Retrieve the data.
    93          */
    94         ipc_call_t data_request_call;
    95         aid_t data_request = async_data_read(exch, buffer, size,
    96             &data_request_call);
    97        
    98         /*
    99          * Since now on, someone else might access the backing phone
    100          * without breaking the transfer IPC protocol.
    101          */
     86
     87        ret = usbhc_read(exch, pipe->wire->address, pipe->endpoint_no,
     88            setup, buffer, size, size_transfered);
    10289        async_exchange_end(exch);
    10390        pipe_end_transaction(pipe);
    104        
    105         if (data_request == 0) {
    106                 /*
    107                  * FIXME:
    108                  * How to let the other side know that we want to abort?
    109                  */
    110                 async_wait_for(opening_request, NULL);
    111                 return ENOMEM;
    112         }
    113        
    114         /*
    115          * Wait for the answer.
    116          */
    117         sysarg_t data_request_rc;
    118         sysarg_t opening_request_rc;
    119         async_wait_for(data_request, &data_request_rc);
    120         async_wait_for(opening_request, &opening_request_rc);
    121        
    122         if (data_request_rc != EOK) {
    123                 /* Prefer the return code of the opening request. */
    124                 if (opening_request_rc != EOK) {
    125                         return (int) opening_request_rc;
    126                 } else {
    127                         return (int) data_request_rc;
    128                 }
    129         }
    130         if (opening_request_rc != EOK) {
    131                 return (int) opening_request_rc;
    132         }
    133        
    134         *size_transfered = IPC_GET_ARG2(data_request_call);
    135        
    136         return EOK;
    137 }
    138 
    139 
    140 /** Request a read (in) transfer on an endpoint pipe.
    141  *
    142  * @param[in] pipe Pipe used for the transfer.
    143  * @param[out] buffer Buffer where to store the data.
    144  * @param[in] size Size of the buffer (in bytes).
    145  * @param[out] size_transfered Number of bytes that were actually transfered.
    146  * @return Error code.
    147  */
    148 int usb_pipe_read(usb_pipe_t *pipe,
    149     void *buffer, size_t size, size_t *size_transfered)
    150 {
    151         assert(pipe);
    152 
    153         if (buffer == NULL) {
    154                 return EINVAL;
    155         }
    156 
    157         if (size == 0) {
    158                 return EINVAL;
    159         }
    160 
    161         if (pipe->direction != USB_DIRECTION_IN) {
    162                 return EBADF;
    163         }
    164 
    165         if (pipe->transfer_type == USB_TRANSFER_CONTROL) {
    166                 return EBADF;
    167         }
    168 
    169         int rc;
    170         rc = pipe_add_ref(pipe, false);
    171         if (rc != EOK) {
    172                 return rc;
    173         }
    174 
    175 
    176         size_t act_size = 0;
    177 
    178         rc = usb_pipe_read_no_checks(pipe, buffer, size, &act_size);
    179 
    18091        pipe_drop_ref(pipe);
    181 
    182         if (rc != EOK) {
    183                 return rc;
    184         }
    185 
    186         if (size_transfered != NULL) {
    187                 *size_transfered = act_size;
    188         }
    189 
    190         return EOK;
    191 }
    192 
    193 
    194 
     92        return ret;
     93}
    19594
    19695/** Request an out transfer, no checking of input parameters.
     
    201100 * @return Error code.
    202101 */
    203 static int usb_pipe_write_no_check(usb_pipe_t *pipe,
    204     void *buffer, size_t size)
     102static int usb_pipe_write_no_check(usb_pipe_t *pipe, uint64_t setup,
     103    const void *buffer, size_t size)
    205104{
    206105        /* Only interrupt and bulk transfers are supported */
    207106        if (pipe->transfer_type != USB_TRANSFER_INTERRUPT &&
    208             pipe->transfer_type != USB_TRANSFER_BULK)
     107            pipe->transfer_type != USB_TRANSFER_BULK &&
     108            pipe->transfer_type != USB_TRANSFER_CONTROL)
    209109            return ENOTSUP;
    210110
    211         const usb_target_t target =
    212             {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }};
     111        int ret = pipe_add_ref(pipe, false);
     112        if (ret != EOK) {
     113                return ret;
     114        }
    213115
    214116        /* Ensure serialization over the phone. */
    215117        pipe_start_transaction(pipe);
    216118        async_exch_t *exch = async_exchange_begin(pipe->hc_sess);
    217        
    218         /*
    219          * Make call identifying target USB device and type of transfer.
    220          */
    221         aid_t opening_request = async_send_3(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    222             IPC_M_USBHC_WRITE, target.packed, size, NULL);
    223        
    224         if (opening_request == 0) {
    225                 async_exchange_end(exch);
     119        if (!exch) {
    226120                pipe_end_transaction(pipe);
     121                pipe_drop_ref(pipe);
    227122                return ENOMEM;
    228123        }
    229        
    230         /*
    231          * Send the data.
    232          */
    233         int rc = async_data_write_start(exch, buffer, size);
    234        
    235         /*
    236          * Since now on, someone else might access the backing phone
    237          * without breaking the transfer IPC protocol.
    238          */
     124        ret = usbhc_write(exch, pipe->wire->address, pipe->endpoint_no,
     125            setup, buffer, size);
    239126        async_exchange_end(exch);
    240127        pipe_end_transaction(pipe);
    241        
    242         if (rc != EOK) {
    243                 async_wait_for(opening_request, NULL);
    244                 return rc;
    245         }
    246        
    247         /*
    248          * Wait for the answer.
    249          */
    250         sysarg_t opening_request_rc;
    251         async_wait_for(opening_request, &opening_request_rc);
    252        
    253         return (int) opening_request_rc;
    254 }
    255 
    256 /** Request a write (out) transfer on an endpoint pipe.
    257  *
    258  * @param[in] pipe Pipe used for the transfer.
    259  * @param[in] buffer Buffer with data to transfer.
    260  * @param[in] size Size of the buffer (in bytes).
    261  * @return Error code.
    262  */
    263 int usb_pipe_write(usb_pipe_t *pipe,
    264     void *buffer, size_t size)
    265 {
    266         assert(pipe);
    267 
    268         if (buffer == NULL) {
    269                 return EINVAL;
    270         }
    271 
    272         if (size == 0) {
    273                 return EINVAL;
    274         }
    275 
    276         if (pipe->direction != USB_DIRECTION_OUT) {
    277                 return EBADF;
    278         }
    279 
    280         if (pipe->transfer_type == USB_TRANSFER_CONTROL) {
    281                 return EBADF;
    282         }
    283 
    284         int rc;
    285 
    286         rc = pipe_add_ref(pipe, false);
    287         if (rc != EOK) {
    288                 return rc;
    289         }
    290 
    291         rc = usb_pipe_write_no_check(pipe, buffer, size);
    292 
    293128        pipe_drop_ref(pipe);
    294 
    295         return rc;
     129        return ret;
    296130}
    297131
     
    309143
    310144
    311         /* Prevent indefinite recursion. */
     145        /* Prevent infinite recursion. */
    312146        pipe->auto_reset_halt = false;
    313147        usb_request_clear_endpoint_halt(pipe, 0);
     
    315149}
    316150
    317 
    318 /** Request a control read transfer, no checking of input parameters.
     151/** Request a control read transfer on an endpoint pipe.
     152 *
     153 * This function encapsulates all three stages of a control transfer.
    319154 *
    320155 * @param[in] pipe Pipe used for the transfer.
     
    327162 * @return Error code.
    328163 */
    329 static int usb_pipe_control_read_no_check(usb_pipe_t *pipe,
    330     const void *setup_buffer, size_t setup_buffer_size,
    331     void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size)
    332 {
    333         /* Ensure serialization over the phone. */
    334         pipe_start_transaction(pipe);
    335 
    336         const usb_target_t target =
    337             {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }};
    338 
    339         assert(setup_buffer_size == 8);
    340         uint64_t setup_packet;
    341         memcpy(&setup_packet, setup_buffer, 8);
    342         /*
    343          * Make call identifying target USB device and control transfer type.
    344          */
    345         async_exch_t *exch = async_exchange_begin(pipe->hc_sess);
    346         aid_t opening_request = async_send_4(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    347             IPC_M_USBHC_READ, target.packed,
    348             (setup_packet & UINT32_MAX), (setup_packet >> 32), NULL);
    349 
    350         if (opening_request == 0) {
    351                 async_exchange_end(exch);
    352                 return ENOMEM;
    353         }
    354 
    355         /*
    356          * Retrieve the data.
    357          */
    358         ipc_call_t data_request_call;
    359         aid_t data_request = async_data_read(exch, data_buffer,
    360             data_buffer_size, &data_request_call);
    361        
    362         /*
    363          * Since now on, someone else might access the backing phone
    364          * without breaking the transfer IPC protocol.
    365          */
    366         async_exchange_end(exch);
    367         pipe_end_transaction(pipe);
    368        
    369         if (data_request == 0) {
    370                 async_wait_for(opening_request, NULL);
    371                 return ENOMEM;
    372         }
    373 
    374         /*
    375          * Wait for the answer.
    376          */
    377         sysarg_t data_request_rc;
    378         sysarg_t opening_request_rc;
    379         async_wait_for(data_request, &data_request_rc);
    380         async_wait_for(opening_request, &opening_request_rc);
    381 
    382         if (data_request_rc != EOK) {
    383                 /* Prefer the return code of the opening request. */
    384                 if (opening_request_rc != EOK) {
    385                         return (int) opening_request_rc;
    386                 } else {
    387                         return (int) data_request_rc;
    388                 }
    389         }
    390         if (opening_request_rc != EOK) {
    391                 return (int) opening_request_rc;
    392         }
    393 
    394         *data_transfered_size = IPC_GET_ARG2(data_request_call);
    395 
    396         return EOK;
    397 }
    398 
    399 /** Request a control read transfer on an endpoint pipe.
    400  *
    401  * This function encapsulates all three stages of a control transfer.
    402  *
    403  * @param[in] pipe Pipe used for the transfer.
    404  * @param[in] setup_buffer Buffer with the setup packet.
    405  * @param[in] setup_buffer_size Size of the setup packet (in bytes).
    406  * @param[out] data_buffer Buffer for incoming data.
    407  * @param[in] data_buffer_size Size of the buffer for incoming data (in bytes).
    408  * @param[out] data_transfered_size Number of bytes that were actually
    409  *                                  transfered during the DATA stage.
    410  * @return Error code.
    411  */
    412164int usb_pipe_control_read(usb_pipe_t *pipe,
    413165    const void *setup_buffer, size_t setup_buffer_size,
     
    416168        assert(pipe);
    417169
    418         if ((setup_buffer == NULL) || (setup_buffer_size == 0)) {
     170        if ((setup_buffer == NULL) || (setup_buffer_size != 8)) {
    419171                return EINVAL;
    420172        }
     
    429181        }
    430182
    431         int rc;
    432 
    433         rc = pipe_add_ref(pipe, false);
    434         if (rc != EOK) {
    435                 return rc;
    436         }
     183        uint64_t setup_packet;
     184        memcpy(&setup_packet, setup_buffer, 8);
    437185
    438186        size_t act_size = 0;
    439         rc = usb_pipe_control_read_no_check(pipe,
    440             setup_buffer, setup_buffer_size,
     187        const int rc = usb_pipe_read_no_check(pipe, setup_packet,
    441188            data_buffer, data_buffer_size, &act_size);
    442189
     
    445192        }
    446193
    447         pipe_drop_ref(pipe);
    448 
    449         if (rc != EOK) {
    450                 return rc;
    451         }
    452 
    453         if (data_transfered_size != NULL) {
     194        if (rc == EOK && data_transfered_size != NULL) {
    454195                *data_transfered_size = act_size;
    455196        }
    456197
    457         return EOK;
    458 }
    459 
    460 
    461 /** Request a control write transfer, no checking of input parameters.
     198        return rc;
     199}
     200
     201/** Request a control write transfer on an endpoint pipe.
     202 *
     203 * This function encapsulates all three stages of a control transfer.
    462204 *
    463205 * @param[in] pipe Pipe used for the transfer.
     
    468210 * @return Error code.
    469211 */
    470 static int usb_pipe_control_write_no_check(usb_pipe_t *pipe,
    471     const void *setup_buffer, size_t setup_buffer_size,
    472     const void *data_buffer, size_t data_buffer_size)
    473 {
    474         /* Ensure serialization over the phone. */
    475         pipe_start_transaction(pipe);
    476 
    477         const usb_target_t target =
    478             {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }};
    479         assert(setup_buffer_size == 8);
    480         uint64_t setup_packet;
    481         memcpy(&setup_packet, setup_buffer, 8);
    482 
    483         /*
    484          * Make call identifying target USB device and control transfer type.
    485          */
    486         async_exch_t *exch = async_exchange_begin(pipe->hc_sess);
    487         aid_t opening_request = async_send_5(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    488             IPC_M_USBHC_WRITE, target.packed, data_buffer_size,
    489             (setup_packet & UINT32_MAX), (setup_packet >> 32), NULL);
    490        
    491         if (opening_request == 0) {
    492                 async_exchange_end(exch);
    493                 pipe_end_transaction(pipe);
    494                 return ENOMEM;
    495         }
    496 
    497         /*
    498          * Send the data (if any).
    499          */
    500         if (data_buffer_size > 0) {
    501                 int rc = async_data_write_start(exch, data_buffer, data_buffer_size);
    502                
    503                 /* All data sent, pipe can be released. */
    504                 async_exchange_end(exch);
    505                 pipe_end_transaction(pipe);
    506        
    507                 if (rc != EOK) {
    508                         async_wait_for(opening_request, NULL);
    509                         return rc;
    510                 }
    511         } else {
    512                 /* No data to send, we can release the pipe for others. */
    513                 async_exchange_end(exch);
    514                 pipe_end_transaction(pipe);
    515         }
    516        
    517         /*
    518          * Wait for the answer.
    519          */
    520         sysarg_t opening_request_rc;
    521         async_wait_for(opening_request, &opening_request_rc);
    522 
    523         return (int) opening_request_rc;
    524 }
    525 
    526 /** Request a control write transfer on an endpoint pipe.
    527  *
    528  * This function encapsulates all three stages of a control transfer.
    529  *
    530  * @param[in] pipe Pipe used for the transfer.
    531  * @param[in] setup_buffer Buffer with the setup packet.
    532  * @param[in] setup_buffer_size Size of the setup packet (in bytes).
    533  * @param[in] data_buffer Buffer with data to be sent.
    534  * @param[in] data_buffer_size Size of the buffer with outgoing data (in bytes).
    535  * @return Error code.
    536  */
    537212int usb_pipe_control_write(usb_pipe_t *pipe,
    538213    const void *setup_buffer, size_t setup_buffer_size,
     
    541216        assert(pipe);
    542217
    543         if ((setup_buffer == NULL) || (setup_buffer_size == 0)) {
     218        if ((setup_buffer == NULL) || (setup_buffer_size != 8)) {
    544219                return EINVAL;
    545220        }
     
    558233        }
    559234
    560         int rc;
    561 
    562         rc = pipe_add_ref(pipe, false);
    563         if (rc != EOK) {
    564                 return rc;
    565         }
    566 
    567         rc = usb_pipe_control_write_no_check(pipe,
    568             setup_buffer, setup_buffer_size, data_buffer, data_buffer_size);
     235        uint64_t setup_packet;
     236        memcpy(&setup_packet, setup_buffer, 8);
     237
     238        const int rc = usb_pipe_write_no_check(pipe, setup_packet,
     239            data_buffer, data_buffer_size);
    569240
    570241        if (rc == ESTALL) {
     
    572243        }
    573244
    574         pipe_drop_ref(pipe);
    575 
    576245        return rc;
    577246}
    578247
     248/** Request a read (in) transfer on an endpoint pipe.
     249 *
     250 * @param[in] pipe Pipe used for the transfer.
     251 * @param[out] buffer Buffer where to store the data.
     252 * @param[in] size Size of the buffer (in bytes).
     253 * @param[out] size_transfered Number of bytes that were actually transfered.
     254 * @return Error code.
     255 */
     256int usb_pipe_read(usb_pipe_t *pipe,
     257    void *buffer, size_t size, size_t *size_transfered)
     258{
     259        assert(pipe);
     260
     261        if (buffer == NULL) {
     262                return EINVAL;
     263        }
     264
     265        if (size == 0) {
     266                return EINVAL;
     267        }
     268
     269        if (pipe->direction != USB_DIRECTION_IN) {
     270                return EBADF;
     271        }
     272
     273        if (pipe->transfer_type == USB_TRANSFER_CONTROL) {
     274                return EBADF;
     275        }
     276
     277        size_t act_size = 0;
     278        const int rc = usb_pipe_read_no_check(pipe, 0, buffer, size, &act_size);
     279
     280
     281        if (rc == EOK && size_transfered != NULL) {
     282                *size_transfered = act_size;
     283        }
     284
     285        return rc;
     286}
     287
     288/** Request a write (out) transfer on an endpoint pipe.
     289 *
     290 * @param[in] pipe Pipe used for the transfer.
     291 * @param[in] buffer Buffer with data to transfer.
     292 * @param[in] size Size of the buffer (in bytes).
     293 * @return Error code.
     294 */
     295int usb_pipe_write(usb_pipe_t *pipe, const void *buffer, size_t size)
     296{
     297        assert(pipe);
     298
     299        if (buffer == NULL || size == 0) {
     300                return EINVAL;
     301        }
     302
     303        if (pipe->direction != USB_DIRECTION_OUT) {
     304                return EBADF;
     305        }
     306
     307        if (pipe->transfer_type == USB_TRANSFER_CONTROL) {
     308                return EBADF;
     309        }
     310
     311        return usb_pipe_write_no_check(pipe, 0, buffer, size);
     312}
    579313
    580314/**
Note: See TracChangeset for help on using the changeset viewer.