Ignore:
File:
1 edited

Legend:

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

    r72363a1 r3937bda  
    3434 */
    3535#include <usb/usbdrv.h>
     36#include <usbhc_iface.h>
     37#include <usb_iface.h>
    3638#include <errno.h>
    37 
     39#include <str_error.h>
     40
     41/** Information about pending transaction on HC. */
     42typedef struct {
     43        /** Phone to host controller driver. */
     44        int phone;
     45        /** Data buffer. */
     46        void *buffer;
     47        /** Buffer size. */
     48        size_t size;
     49        /** Storage for actual number of bytes transferred. */
     50        size_t *size_transferred;
     51        /** Initial call reply data. */
     52        ipc_call_t reply;
     53        /** Initial call identifier. */
     54        aid_t request;
     55        /** Reply data for data read call. */
     56        ipc_call_t read_reply;
     57        /** Data read call identifier. */
     58        aid_t read_request;
     59} transfer_info_t;
    3860
    3961/** Find handle of host controller the device is physically attached to.
     
    4567int usb_drv_find_hc(device_t *dev, devman_handle_t *handle)
    4668{
    47         return ENOTSUP;
     69        if (dev == NULL) {
     70                return EBADMEM;
     71        }
     72        if (handle == NULL) {
     73                return EBADMEM;
     74        }
     75
     76        int parent_phone = devman_parent_device_connect(dev->handle,
     77            IPC_FLAG_BLOCKING);
     78        if (parent_phone < 0) {
     79                return parent_phone;
     80        }
     81
     82        devman_handle_t h;
     83        int rc = async_req_1_1(parent_phone, DEV_IFACE_ID(USB_DEV_IFACE),
     84            IPC_M_USB_GET_HOST_CONTROLLER_HANDLE, &h);
     85
     86        async_hangup(parent_phone);
     87
     88        if (rc != EOK) {
     89                return rc;
     90        }
     91
     92        *handle = h;
     93
     94        return EOK;
    4895}
    4996
     
    58105    unsigned int flags)
    59106{
    60         return ENOTSUP;
     107        return devman_device_connect(hc_handle, flags);
    61108}
    62109
     
    69116int usb_drv_hc_connect_auto(device_t *dev, unsigned int flags)
    70117{
    71         return ENOTSUP;
     118        int rc;
     119        devman_handle_t hc_handle;
     120
     121        /*
     122         * Call parent hub to obtain device handle of respective HC.
     123         */
     124        rc = usb_drv_find_hc(dev, &hc_handle);
     125        if (rc != EOK) {
     126                return rc;
     127        }
     128       
     129        return usb_drv_hc_connect(dev, hc_handle, flags);
    72130}
    73131
     
    80138usb_address_t usb_drv_get_my_address(int phone, device_t *dev)
    81139{
    82         return ENOTSUP;
     140        sysarg_t address;
     141        int rc = async_req_2_1(phone, DEV_IFACE_ID(USBHC_DEV_IFACE),
     142            IPC_M_USBHC_GET_ADDRESS,
     143            dev->handle, &address);
     144
     145        if (rc != EOK) {
     146                return rc;
     147        }
     148
     149        return (usb_address_t) address;
    83150}
    84151
     
    90157int usb_drv_reserve_default_address(int phone)
    91158{
    92         return ENOTSUP;
     159        return async_req_1_0(phone, DEV_IFACE_ID(USBHC_DEV_IFACE),
     160            IPC_M_USBHC_RESERVE_DEFAULT_ADDRESS);
    93161}
    94162
     
    100168int usb_drv_release_default_address(int phone)
    101169{
    102         return ENOTSUP;
     170        return async_req_1_0(phone, DEV_IFACE_ID(USBHC_DEV_IFACE),
     171            IPC_M_USBHC_RELEASE_DEFAULT_ADDRESS);
    103172}
    104173
     
    110179usb_address_t usb_drv_request_address(int phone)
    111180{
    112         return ENOTSUP;
     181        sysarg_t address;
     182        int rc = async_req_1_1(phone, DEV_IFACE_ID(USBHC_DEV_IFACE),
     183            IPC_M_USBHC_REQUEST_ADDRESS, &address);
     184        if (rc != EOK) {
     185                return rc;
     186        } else {
     187                return (usb_address_t) address;
     188        }
    113189}
    114190
     
    123199    devman_handle_t handle)
    124200{
    125         return ENOTSUP;
     201        int rc = async_req_3_0(phone, DEV_IFACE_ID(USBHC_DEV_IFACE),
     202            IPC_M_USBHC_BIND_ADDRESS,
     203            address, handle);
     204
     205        return rc;
    126206}
    127207
     
    134214int usb_drv_release_address(int phone, usb_address_t address)
    135215{
    136         return ENOTSUP;
    137 }
     216        return async_req_2_0(phone, DEV_IFACE_ID(USBHC_DEV_IFACE),
     217            IPC_M_USBHC_RELEASE_ADDRESS, address);
     218}
     219
     220/** Send data to HCD.
     221 *
     222 * @param phone Phone to HC.
     223 * @param method Method used for calling.
     224 * @param target Targeted device.
     225 * @param buffer Data buffer (NULL to skip data transfer phase).
     226 * @param size Buffer size (must be zero when @p buffer is NULL).
     227 * @param handle Storage for transaction handle (cannot be NULL).
     228 * @return Error status.
     229 * @retval EINVAL Invalid parameter.
     230 * @retval ENOMEM Not enough memory to complete the operation.
     231 */
     232static int async_send_buffer(int phone, int method,
     233    usb_target_t target,
     234    void *buffer, size_t size,
     235    usb_handle_t *handle)
     236{
     237        if (phone < 0) {
     238                return EINVAL;
     239        }
     240
     241        if ((buffer == NULL) && (size > 0)) {
     242                return EINVAL;
     243        }
     244
     245        if (handle == NULL) {
     246                return EINVAL;
     247        }
     248
     249        transfer_info_t *transfer
     250            = (transfer_info_t *) malloc(sizeof(transfer_info_t));
     251        if (transfer == NULL) {
     252                return ENOMEM;
     253        }
     254
     255        transfer->read_request = 0;
     256        transfer->size_transferred = NULL;
     257        transfer->buffer = NULL;
     258        transfer->size = 0;
     259        transfer->phone = phone;
     260
     261        int rc;
     262
     263        transfer->request = async_send_4(phone,
     264            DEV_IFACE_ID(USBHC_DEV_IFACE),
     265            method,
     266            target.address, target.endpoint,
     267            size,
     268            &transfer->reply);
     269
     270        if (size > 0) {
     271                rc = async_data_write_start(phone, buffer, size);
     272                if (rc != EOK) {
     273                        async_wait_for(transfer->request, NULL);
     274                        return rc;
     275                }
     276        }
     277
     278        *handle = (usb_handle_t) transfer;
     279
     280        return EOK;
     281}
     282
     283/** Prepare data retrieval.
     284 *
     285 * @param phone Opened phone to HCD.
     286 * @param method Method used for calling.
     287 * @param target Targeted device.
     288 * @param buffer Buffer where to store retrieved data
     289 *      (NULL to skip data transfer phase).
     290 * @param size Buffer size (must be zero when @p buffer is NULL).
     291 * @param actual_size Storage where actual number of bytes transferred will
     292 *      be stored.
     293 * @param handle Storage for transaction handle (cannot be NULL).
     294 * @return Error status.
     295 * @retval EINVAL Invalid parameter.
     296 * @retval ENOMEM Not enough memory to complete the operation.
     297 */
     298static int async_recv_buffer(int phone, int method,
     299    usb_target_t target,
     300    void *buffer, size_t size, size_t *actual_size,
     301    usb_handle_t *handle)
     302{
     303        if (phone < 0) {
     304                return EINVAL;
     305        }
     306
     307        if ((buffer == NULL) && (size > 0)) {
     308                return EINVAL;
     309        }
     310
     311        if (handle == NULL) {
     312                return EINVAL;
     313        }
     314
     315        transfer_info_t *transfer
     316            = (transfer_info_t *) malloc(sizeof(transfer_info_t));
     317        if (transfer == NULL) {
     318                return ENOMEM;
     319        }
     320
     321        transfer->read_request = 0;
     322        transfer->size_transferred = actual_size;
     323        transfer->buffer = buffer;
     324        transfer->size = size;
     325        transfer->phone = phone;
     326
     327        transfer->request = async_send_4(phone,
     328            DEV_IFACE_ID(USBHC_DEV_IFACE),
     329            method,
     330            target.address, target.endpoint,
     331            size,
     332            &transfer->reply);
     333
     334        if (buffer != NULL) {
     335                transfer->read_request = async_data_read(phone, buffer, size,
     336                    &transfer->read_reply);
     337        }
     338
     339        *handle = (usb_handle_t) transfer;
     340
     341        return EOK;
     342}
     343
    138344
    139345/** Blocks caller until given USB transaction is finished.
     
    149355int usb_drv_async_wait_for(usb_handle_t handle)
    150356{
    151         return ENOTSUP;
     357        if (handle == 0) {
     358                return EBADMEM;
     359        }
     360
     361        int rc = EOK;
     362
     363        transfer_info_t *transfer = (transfer_info_t *) handle;
     364
     365        sysarg_t answer_rc;
     366
     367        /*
     368         * If the buffer is not NULL, we must accept some data.
     369         */
     370        if ((transfer->buffer != NULL) && (transfer->size > 0)) {
     371                async_wait_for(transfer->read_request, &answer_rc);
     372
     373                if (answer_rc != EOK) {
     374                        rc = (int) answer_rc;
     375                        goto leave;
     376                }
     377
     378                if (transfer->size_transferred != NULL) {
     379                        *(transfer->size_transferred)
     380                            = IPC_GET_ARG2(transfer->read_reply);
     381                }
     382        }
     383
     384        async_wait_for(transfer->request, &answer_rc);
     385
     386        if (answer_rc != EOK) {
     387                rc = (int) answer_rc;
     388                goto leave;
     389        }
     390
     391leave:
     392        free(transfer);
     393
     394        return rc;
    152395}
    153396
     
    157400    usb_handle_t *handle)
    158401{
    159         return ENOTSUP;
     402        return async_send_buffer(phone,
     403            IPC_M_USBHC_INTERRUPT_OUT,
     404            target,
     405            buffer, size,
     406            handle);
    160407}
    161408
     
    165412    usb_handle_t *handle)
    166413{
    167         return ENOTSUP;
     414        return async_recv_buffer(phone,
     415            IPC_M_USBHC_INTERRUPT_IN,
     416            target,
     417            buffer, size, actual_size,
     418            handle);
    168419}
    169420
     
    173424    usb_handle_t *handle)
    174425{
    175         return ENOTSUP;
     426        return async_send_buffer(phone,
     427            IPC_M_USBHC_CONTROL_WRITE_SETUP,
     428            target,
     429            buffer, size,
     430            handle);
    176431}
    177432
     
    181436    usb_handle_t *handle)
    182437{
    183         return ENOTSUP;
     438        return async_send_buffer(phone,
     439            IPC_M_USBHC_CONTROL_WRITE_DATA,
     440            target,
     441            buffer, size,
     442            handle);
    184443}
    185444
     
    188447    usb_handle_t *handle)
    189448{
    190         return ENOTSUP;
     449        return async_recv_buffer(phone,
     450            IPC_M_USBHC_CONTROL_WRITE_STATUS,
     451            target,
     452            NULL, 0, NULL,
     453            handle);
    191454}
    192455
     
    197460    usb_handle_t *handle)
    198461{
    199         return ENOTSUP;
     462        // FIXME - check input parameters instead of asserting them
     463        assert(phone > 0);
     464        assert(setup_packet != NULL);
     465        assert(setup_packet_size > 0);
     466        assert(((buffer != NULL) && (buffer_size > 0))
     467            || ((buffer == NULL) && (buffer_size == 0)));
     468        assert(handle != NULL);
     469
     470        transfer_info_t *transfer
     471            = (transfer_info_t *) malloc(sizeof(transfer_info_t));
     472        if (transfer == NULL) {
     473                return ENOMEM;
     474        }
     475
     476        transfer->read_request = 0;
     477        transfer->size_transferred = NULL;
     478        transfer->buffer = NULL;
     479        transfer->size = 0;
     480        transfer->phone = phone;
     481
     482        int rc;
     483
     484        transfer->request = async_send_3(phone,
     485            DEV_IFACE_ID(USBHC_DEV_IFACE),
     486            IPC_M_USBHC_CONTROL_WRITE,
     487            target.address, target.endpoint,
     488            &transfer->reply);
     489
     490        rc = async_data_write_start(phone, setup_packet, setup_packet_size);
     491        if (rc != EOK) {
     492                async_wait_for(transfer->request, NULL);
     493                return rc;
     494        }
     495
     496        if (buffer_size > 0) {
     497                rc = async_data_write_start(phone, buffer, buffer_size);
     498                if (rc != EOK) {
     499                        async_wait_for(transfer->request, NULL);
     500                        return rc;
     501                }
     502        }
     503
     504        *handle = (usb_handle_t) transfer;
     505
     506        return EOK;
    200507}
    201508
     
    205512    usb_handle_t *handle)
    206513{
    207         return ENOTSUP;
     514        return async_send_buffer(phone,
     515            IPC_M_USBHC_CONTROL_READ_SETUP,
     516            target,
     517            buffer, size,
     518            handle);
    208519}
    209520
     
    213524    usb_handle_t *handle)
    214525{
    215         return ENOTSUP;
     526        return async_recv_buffer(phone,
     527            IPC_M_USBHC_CONTROL_READ_DATA,
     528            target,
     529            buffer, size, actual_size,
     530            handle);
    216531}
    217532
     
    220535    usb_handle_t *handle)
    221536{
    222         return ENOTSUP;
     537        return async_send_buffer(phone,
     538            IPC_M_USBHC_CONTROL_READ_STATUS,
     539            target,
     540            NULL, 0,
     541            handle);
    223542}
    224543
     
    229548    usb_handle_t *handle)
    230549{
    231         return ENOTSUP;
     550        // FIXME - check input parameters instead of asserting them
     551        assert(phone > 0);
     552        assert(setup_packet != NULL);
     553        assert(setup_packet_size > 0);
     554        assert(buffer != NULL);
     555        assert(buffer_size > 0);
     556        assert(handle != NULL);
     557
     558        transfer_info_t *transfer
     559            = (transfer_info_t *) malloc(sizeof(transfer_info_t));
     560        if (transfer == NULL) {
     561                return ENOMEM;
     562        }
     563
     564        transfer->size_transferred = actual_size;
     565        transfer->buffer = buffer;
     566        transfer->size = buffer_size;
     567        transfer->phone = phone;
     568
     569        int rc;
     570
     571        transfer->request = async_send_4(phone,
     572            DEV_IFACE_ID(USBHC_DEV_IFACE),
     573            IPC_M_USBHC_CONTROL_READ,
     574            target.address, target.endpoint,
     575            buffer_size,
     576            &transfer->reply);
     577
     578        rc = async_data_write_start(phone, setup_packet, setup_packet_size);
     579        if (rc != EOK) {
     580                async_wait_for(transfer->request, NULL);
     581                return rc;
     582        }
     583
     584        transfer->read_request = async_data_read(phone, buffer, buffer_size,
     585            &transfer->read_reply);
     586
     587        *handle = (usb_handle_t) transfer;
     588
     589        return EOK;
    232590}
    233591
Note: See TracChangeset for help on using the changeset viewer.