Changeset 79ae36dd in mainline for uspace/lib/usbdev


Ignore:
Timestamp:
2011-06-08T19:01:55Z (14 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
0eff68e
Parents:
764d71e
Message:

new async framework with integrated exchange tracking

  • strict isolation between low-level IPC and high-level async framework with integrated exchange tracking
    • each IPC connection is represented by an async_sess_t structure
    • each IPC exchange is represented by an async_exch_t structure
    • exchange management is either based on atomic messages (EXCHANGE_ATOMIC), locking (EXCHANGE_SERIALIZE) or connection cloning (EXCHANGE_CLONE)
  • async_obsolete: temporary compatibility layer to keep old async clients working (several pieces of code are currently broken, but only non-essential functionality)
  • IPC_M_PHONE_HANGUP is now method no. 0 (for elegant boolean evaluation)
  • IPC_M_DEBUG_ALL has been renamed to IPC_M_DEBUG
  • IPC_M_PING has been removed (VFS protocol now has VFS_IN_PING)
  • console routines in libc have been rewritten for better abstraction
  • additional use for libc-private header files (FILE structure opaque to the client)
  • various cstyle changes (typos, indentation, missing externs in header files, improved comments, etc.)
Location:
uspace/lib/usbdev
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/usbdev/include/usb/dev/pipes.h

    r764d71e r79ae36dd  
    4343#include <ddf/driver.h>
    4444#include <fibril_synch.h>
     45#include <async.h>
    4546
    4647/** Abstraction of a physical connection to the device.
     
    6263 *
    6364 * Locking order: if you want to lock both mutexes
    64  * (@c guard and @c hc_phone_mutex), lock @c guard first.
    65  * It is not necessary to lock @c guard if you want to lock @c hc_phone_mutex
     65 * (@c guard and @c hc_sess_mutex), lock @c guard first.
     66 * It is not necessary to lock @c guard if you want to lock @c hc_sess_mutex
    6667 * only.
    6768 */
     
    8586        size_t max_packet_size;
    8687
    87         /** Phone to the host controller.
    88          * Negative when no session is active.
    89          * It is an error to access this member without @c hc_phone_mutex
     88        /** Session to the host controller.
     89         * NULL when no session is active.
     90         * It is an error to access this member without @c hc_sess_mutex
    9091         * being locked.
    9192         * If call over the phone is to be made, it must be preceeded by
    9293         * call to pipe_add_ref() [internal libusb function].
    9394         */
    94         int hc_phone;
     95        async_sess_t *hc_sess;
    9596
    96         /** Guard for serialization of requests over the phone. */
    97         fibril_mutex_t hc_phone_mutex;
     97        /** Guard for serialization of requests over the session. */
     98        fibril_mutex_t hc_sess_mutex;
    9899
    99100        /** Number of active transfers over the pipe. */
  • uspace/lib/usbdev/src/hub.c

    r764d71e r79ae36dd  
    4242#include <usb/debug.h>
    4343#include <time.h>
     44#include <async.h>
    4445
    4546/** How much time to wait between attempts to register endpoint 0:0.
     
    7172{
    7273        CHECK_CONNECTION(connection);
    73 
     74       
     75        async_exch_t *exch = async_exchange_begin(connection->hc_sess);
     76       
    7477        sysarg_t address;
    75         int rc = async_req_2_1(connection->hc_phone,
    76             DEV_IFACE_ID(USBHC_DEV_IFACE),
     78        int rc = async_req_2_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    7779            IPC_M_USBHC_REQUEST_ADDRESS, speed,
    7880            &address);
    79         if (rc != EOK) {
     81       
     82        async_exchange_end(exch);
     83       
     84        if (rc != EOK)
    8085                return (usb_address_t) rc;
    81         } else {
    82                 return (usb_address_t) address;
    83         }
     86       
     87        return (usb_address_t) address;
    8488}
    8589
     
    9498{
    9599        CHECK_CONNECTION(connection);
    96         if (attached_device == NULL) {
     100       
     101        if (attached_device == NULL)
    97102                return EBADMEM;
    98         }
    99 
    100         return async_req_3_0(connection->hc_phone,
    101             DEV_IFACE_ID(USBHC_DEV_IFACE),
     103       
     104        async_exch_t *exch = async_exchange_begin(connection->hc_sess);
     105        int rc = async_req_3_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    102106            IPC_M_USBHC_BIND_ADDRESS,
    103107            attached_device->address, attached_device->handle);
     108        async_exchange_end(exch);
     109       
     110        return rc;
    104111}
    105112
     
    114121{
    115122        CHECK_CONNECTION(connection);
    116 
    117         return async_req_2_0(connection->hc_phone,
    118             DEV_IFACE_ID(USBHC_DEV_IFACE),
     123       
     124        async_exch_t *exch = async_exchange_begin(connection->hc_sess);
     125        int rc = async_req_2_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    119126            IPC_M_USBHC_RELEASE_ADDRESS, address);
     127        async_exchange_end(exch);
     128       
     129        return rc;
    120130}
    121131
     
    192202        usb_hc_connection_t hc_conn = {
    193203                .hc_handle = connection->hc_handle,
    194                 .hc_phone = -1
     204                .hc_sess = NULL
    195205        };
    196206
  • uspace/lib/usbdev/src/pipepriv.c

    r764d71e r79ae36dd  
    4444void pipe_start_transaction(usb_pipe_t *pipe)
    4545{
    46         fibril_mutex_lock(&pipe->hc_phone_mutex);
     46        fibril_mutex_lock(&pipe->hc_sess_mutex);
    4747}
    4848
     
    5353void pipe_end_transaction(usb_pipe_t *pipe)
    5454{
    55         fibril_mutex_unlock(&pipe->hc_phone_mutex);
     55        fibril_mutex_unlock(&pipe->hc_sess_mutex);
    5656}
    5757
     
    8585{
    8686        pipe_acquire(pipe);
    87 
     87       
    8888        if (pipe->refcount == 0) {
    8989                /* Need to open the phone by ourselves. */
    90                 int phone = devman_device_connect(pipe->wire->hc_handle, 0);
    91                 if (phone < 0) {
     90                async_sess_t *sess =
     91                    devman_device_connect(EXCHANGE_SERIALIZE, pipe->wire->hc_handle, 0);
     92                if (!sess) {
    9293                        if (hide_failure) {
    9394                                pipe->refcount_soft++;
    94                                 phone = EOK;
     95                                pipe_release(pipe);
     96                                return EOK;
    9597                        }
     98                       
    9699                        pipe_release(pipe);
    97                         return phone;
     100                        return ENOMEM;
    98101                }
     102               
    99103                /*
    100104                 * No locking is needed, refcount is zero and whole pipe
    101105                 * mutex is locked.
    102106                 */
    103                 pipe->hc_phone = phone;
     107               
     108                pipe->hc_sess = sess;
    104109        }
     110       
    105111        pipe->refcount++;
    106 
    107112        pipe_release(pipe);
    108 
     113       
    109114        return EOK;
    110115}
     
    117122{
    118123        pipe_acquire(pipe);
     124       
    119125        if (pipe->refcount_soft > 0) {
    120126                pipe->refcount_soft--;
     
    122128                return;
    123129        }
     130       
    124131        assert(pipe->refcount > 0);
     132       
    125133        pipe->refcount--;
     134       
    126135        if (pipe->refcount == 0) {
    127136                /* We were the last users, let's hang-up. */
    128                 async_hangup(pipe->hc_phone);
    129                 pipe->hc_phone = -1;
     137                async_hangup(pipe->hc_sess);
     138                pipe->hc_sess = NULL;
    130139        }
     140       
    131141        pipe_release(pipe);
    132142}
  • uspace/lib/usbdev/src/pipes.c

    r764d71e r79ae36dd  
    4848/** Tell USB address assigned to given device.
    4949 *
    50  * @param phone Phone to parent device.
     50 * @param sess Session to parent device.
    5151 * @param dev Device in question.
    5252 * @return USB address or error code.
    5353 */
    54 static usb_address_t get_my_address(int phone, ddf_dev_t *dev)
    55 {
    56         sysarg_t address;
    57 
     54static usb_address_t get_my_address(async_sess_t *sess, ddf_dev_t *dev)
     55{
     56        async_exch_t *exch = async_exchange_begin(sess);
     57       
    5858        /*
    5959         * We are sending special value as a handle - zero - to get
     
    6161         * when registering our device @p dev.
    6262         */
    63         int rc = async_req_2_1(phone, DEV_IFACE_ID(USB_DEV_IFACE),
    64             IPC_M_USB_GET_ADDRESS,
    65             0, &address);
    66 
    67         if (rc != EOK) {
     63        sysarg_t address;
     64        int rc = async_req_2_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
     65            IPC_M_USB_GET_ADDRESS, 0, &address);
     66       
     67        async_exchange_end(exch);
     68       
     69        if (rc != EOK)
    6870                return rc;
    69         }
    70 
     71       
    7172        return (usb_address_t) address;
    7273}
     
    7980int usb_device_get_assigned_interface(ddf_dev_t *device)
    8081{
    81         int parent_phone = devman_parent_device_connect(device->handle,
     82        async_sess_t *parent_sess =
     83            devman_parent_device_connect(EXCHANGE_SERIALIZE, device->handle,
    8284            IPC_FLAG_BLOCKING);
    83         if (parent_phone < 0) {
     85        if (!parent_sess)
    8486                return -1;
    85         }
    86 
     87       
     88        async_exch_t *exch = async_exchange_begin(parent_sess);
     89       
    8790        sysarg_t iface_no;
    88         int rc = async_req_2_1(parent_phone, DEV_IFACE_ID(USB_DEV_IFACE),
    89             IPC_M_USB_GET_INTERFACE,
    90             device->handle, &iface_no);
    91 
    92         async_hangup(parent_phone);
    93 
    94         if (rc != EOK) {
     91        int rc = async_req_2_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
     92            IPC_M_USB_GET_INTERFACE, device->handle, &iface_no);
     93       
     94        async_exchange_end(exch);
     95        async_hangup(parent_sess);
     96       
     97        if (rc != EOK)
    9598                return -1;
    96         }
    97 
     99       
    98100        return (int) iface_no;
    99101}
     
    110112        assert(connection);
    111113        assert(dev);
    112 
     114       
    113115        int rc;
    114116        devman_handle_t hc_handle;
    115117        usb_address_t my_address;
    116 
     118       
    117119        rc = usb_hc_find(dev->handle, &hc_handle);
    118         if (rc != EOK) {
     120        if (rc != EOK)
    119121                return rc;
    120         }
    121 
    122         int parent_phone = devman_parent_device_connect(dev->handle,
     122       
     123        async_sess_t *parent_sess =
     124            devman_parent_device_connect(EXCHANGE_SERIALIZE, dev->handle,
    123125            IPC_FLAG_BLOCKING);
    124         if (parent_phone < 0) {
    125                 return parent_phone;
    126         }
    127 
     126        if (!parent_sess)
     127                return ENOMEM;
     128       
    128129        /*
    129130         * Asking for "my" address may require several attempts.
     
    137138         *  So, we need to wait for the HC to learn the binding.
    138139         */
     140       
    139141        do {
    140                 my_address = get_my_address(parent_phone, dev);
    141 
     142                my_address = get_my_address(parent_sess, dev);
     143               
    142144                if (my_address == ENOENT) {
    143145                        /* Be nice, let other fibrils run and try again. */
     
    148150                        goto leave;
    149151                }
    150 
     152       
    151153        } while (my_address < 0);
    152 
     154       
    153155        rc = usb_device_connection_initialize(connection,
    154156            hc_handle, my_address);
    155 
     157       
    156158leave:
    157         async_hangup(parent_phone);
     159        async_hangup(parent_sess);
    158160        return rc;
    159161}
  • uspace/lib/usbdev/src/pipesinit.c

    r764d71e r79ae36dd  
    358358        fibril_mutex_initialize(&pipe->guard);
    359359        pipe->wire = connection;
    360         pipe->hc_phone = -1;
    361         fibril_mutex_initialize(&pipe->hc_phone_mutex);
     360        pipe->hc_sess = NULL;
     361        fibril_mutex_initialize(&pipe->hc_sess_mutex);
    362362        pipe->endpoint_no = endpoint_no;
    363363        pipe->transfer_type = transfer_type;
     
    482482        assert(pipe);
    483483        assert(hc_connection);
    484 
    485         if (!usb_hc_connection_is_opened(hc_connection)) {
     484       
     485        if (!usb_hc_connection_is_opened(hc_connection))
    486486                return EBADF;
    487         }
    488 
     487       
    489488#define _PACK2(high, low) (((high) << 16) + (low))
    490489#define _PACK3(high, middle, low) (((((high) << 8) + (middle)) << 8) + (low))
    491 
    492         return async_req_4_0(hc_connection->hc_phone,
    493             DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_REGISTER_ENDPOINT,
     490       
     491        async_exch_t *exch = async_exchange_begin(hc_connection->hc_sess);
     492        int rc = async_req_4_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
     493            IPC_M_USBHC_REGISTER_ENDPOINT,
    494494            _PACK2(pipe->wire->address, pipe->endpoint_no),
    495495            _PACK3(speed, pipe->transfer_type, pipe->direction),
    496496            _PACK2(pipe->max_packet_size, interval));
    497 
     497        async_exchange_end(exch);
     498       
    498499#undef _PACK2
    499500#undef _PACK3
     501       
     502        return rc;
    500503}
    501504
     
    511514        assert(pipe);
    512515        assert(hc_connection);
    513 
    514         if (!usb_hc_connection_is_opened(hc_connection)) {
     516       
     517        if (!usb_hc_connection_is_opened(hc_connection))
    515518                return EBADF;
    516         }
    517 
    518         return async_req_4_0(hc_connection->hc_phone,
    519             DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_UNREGISTER_ENDPOINT,
     519       
     520        async_exch_t *exch = async_exchange_begin(hc_connection->hc_sess);
     521        int rc = async_req_4_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
     522            IPC_M_USBHC_UNREGISTER_ENDPOINT,
    520523            pipe->wire->address, pipe->endpoint_no, pipe->direction);
     524        async_exchange_end(exch);
     525       
     526        return rc;
    521527}
    522528
  • uspace/lib/usbdev/src/pipesio.c

    r764d71e r79ae36dd  
    4444 * obviously).
    4545 */
     46
    4647#include <usb/usb.h>
    4748#include <usb/dev/pipes.h>
     
    5051#include <usbhc_iface.h>
    5152#include <usb/dev/request.h>
     53#include <async.h>
    5254#include "pipepriv.h"
    5355
     
    7981                        return ENOTSUP;
    8082        }
    81 
     83       
    8284        /* Ensure serialization over the phone. */
    8385        pipe_start_transaction(pipe);
    84 
     86        async_exch_t *exch = async_exchange_begin(pipe->hc_sess);
     87       
    8588        /*
    8689         * Make call identifying target USB device and type of transfer.
    8790         */
    88         aid_t opening_request = async_send_3(pipe->hc_phone,
    89             DEV_IFACE_ID(USBHC_DEV_IFACE), ipc_method,
    90             pipe->wire->address, pipe->endpoint_no,
    91             NULL);
     91        aid_t opening_request = async_send_3(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
     92            ipc_method, pipe->wire->address, pipe->endpoint_no, NULL);
     93       
    9294        if (opening_request == 0) {
     95                async_exchange_end(exch);
    9396                pipe_end_transaction(pipe);
    9497                return ENOMEM;
    9598        }
    96 
     99       
    97100        /*
    98101         * Retrieve the data.
    99102         */
    100103        ipc_call_t data_request_call;
    101         aid_t data_request = async_data_read(pipe->hc_phone, buffer, size,
     104        aid_t data_request = async_data_read(exch, buffer, size,
    102105            &data_request_call);
    103 
     106       
    104107        /*
    105108         * Since now on, someone else might access the backing phone
    106109         * without breaking the transfer IPC protocol.
    107110         */
     111        async_exchange_end(exch);
    108112        pipe_end_transaction(pipe);
    109 
     113       
    110114        if (data_request == 0) {
    111115                /*
     
    116120                return ENOMEM;
    117121        }
    118 
     122       
    119123        /*
    120124         * Wait for the answer.
     
    124128        async_wait_for(data_request, &data_request_rc);
    125129        async_wait_for(opening_request, &opening_request_rc);
    126 
     130       
    127131        if (data_request_rc != EOK) {
    128132                /* Prefer the return code of the opening request. */
     
    136140                return (int) opening_request_rc;
    137141        }
    138 
     142       
    139143        *size_transfered = IPC_GET_ARG2(data_request_call);
    140 
     144       
    141145        return EOK;
    142146}
     
    228232        /* Ensure serialization over the phone. */
    229233        pipe_start_transaction(pipe);
    230 
     234        async_exch_t *exch = async_exchange_begin(pipe->hc_sess);
     235       
    231236        /*
    232237         * Make call identifying target USB device and type of transfer.
    233238         */
    234         aid_t opening_request = async_send_3(pipe->hc_phone,
    235             DEV_IFACE_ID(USBHC_DEV_IFACE), ipc_method,
    236             pipe->wire->address, pipe->endpoint_no,
    237             NULL);
     239        aid_t opening_request = async_send_3(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
     240            ipc_method, pipe->wire->address, pipe->endpoint_no, NULL);
     241       
    238242        if (opening_request == 0) {
     243                async_exchange_end(exch);
    239244                pipe_end_transaction(pipe);
    240245                return ENOMEM;
    241246        }
    242 
     247       
    243248        /*
    244249         * Send the data.
    245250         */
    246         int rc = async_data_write_start(pipe->hc_phone, buffer, size);
    247 
     251        int rc = async_data_write_start(exch, buffer, size);
     252       
    248253        /*
    249254         * Since now on, someone else might access the backing phone
    250255         * without breaking the transfer IPC protocol.
    251256         */
     257        async_exchange_end(exch);
    252258        pipe_end_transaction(pipe);
    253 
     259       
    254260        if (rc != EOK) {
    255261                async_wait_for(opening_request, NULL);
    256262                return rc;
    257263        }
    258 
     264       
    259265        /*
    260266         * Wait for the answer.
     
    262268        sysarg_t opening_request_rc;
    263269        async_wait_for(opening_request, &opening_request_rc);
    264 
     270       
    265271        return (int) opening_request_rc;
    266272}
     
    349355         * Make call identifying target USB device and control transfer type.
    350356         */
    351         aid_t opening_request = async_send_3(pipe->hc_phone,
    352             DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_CONTROL_READ,
    353             pipe->wire->address, pipe->endpoint_no,
     357        async_exch_t *exch = async_exchange_begin(pipe->hc_sess);
     358        aid_t opening_request = async_send_3(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
     359            IPC_M_USBHC_CONTROL_READ, pipe->wire->address, pipe->endpoint_no,
    354360            NULL);
     361       
    355362        if (opening_request == 0) {
     363                async_exchange_end(exch);
    356364                return ENOMEM;
    357365        }
    358 
     366       
    359367        /*
    360368         * Send the setup packet.
    361369         */
    362         int rc = async_data_write_start(pipe->hc_phone,
    363             setup_buffer, setup_buffer_size);
    364         if (rc != EOK) {
     370        int rc = async_data_write_start(exch, setup_buffer, setup_buffer_size);
     371        if (rc != EOK) {
     372                async_exchange_end(exch);
    365373                pipe_end_transaction(pipe);
    366374                async_wait_for(opening_request, NULL);
    367375                return rc;
    368376        }
    369 
     377       
    370378        /*
    371379         * Retrieve the data.
    372380         */
    373381        ipc_call_t data_request_call;
    374         aid_t data_request = async_data_read(pipe->hc_phone,
    375             data_buffer, data_buffer_size,
    376             &data_request_call);
    377 
     382        aid_t data_request = async_data_read(exch, data_buffer,
     383            data_buffer_size, &data_request_call);
     384       
    378385        /*
    379386         * Since now on, someone else might access the backing phone
    380387         * without breaking the transfer IPC protocol.
    381388         */
     389        async_exchange_end(exch);
    382390        pipe_end_transaction(pipe);
    383 
    384 
     391       
    385392        if (data_request == 0) {
    386393                async_wait_for(opening_request, NULL);
     
    494501         * Make call identifying target USB device and control transfer type.
    495502         */
    496         aid_t opening_request = async_send_4(pipe->hc_phone,
    497             DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_CONTROL_WRITE,
    498             pipe->wire->address, pipe->endpoint_no,
    499             data_buffer_size,
    500             NULL);
     503        async_exch_t *exch = async_exchange_begin(pipe->hc_sess);
     504        aid_t opening_request = async_send_4(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
     505            IPC_M_USBHC_CONTROL_WRITE, pipe->wire->address, pipe->endpoint_no,
     506            data_buffer_size, NULL);
     507       
    501508        if (opening_request == 0) {
     509                async_exchange_end(exch);
    502510                pipe_end_transaction(pipe);
    503511                return ENOMEM;
    504512        }
    505 
     513       
    506514        /*
    507515         * Send the setup packet.
    508516         */
    509         int rc = async_data_write_start(pipe->hc_phone,
    510             setup_buffer, setup_buffer_size);
    511         if (rc != EOK) {
     517        int rc = async_data_write_start(exch, setup_buffer, setup_buffer_size);
     518        if (rc != EOK) {
     519                async_exchange_end(exch);
    512520                pipe_end_transaction(pipe);
    513521                async_wait_for(opening_request, NULL);
    514522                return rc;
    515523        }
    516 
     524       
    517525        /*
    518526         * Send the data (if any).
    519527         */
    520528        if (data_buffer_size > 0) {
    521                 rc = async_data_write_start(pipe->hc_phone,
    522                     data_buffer, data_buffer_size);
    523 
     529                rc = async_data_write_start(exch, data_buffer, data_buffer_size);
     530               
    524531                /* All data sent, pipe can be released. */
     532                async_exchange_end(exch);
    525533                pipe_end_transaction(pipe);
    526 
     534       
    527535                if (rc != EOK) {
    528536                        async_wait_for(opening_request, NULL);
     
    531539        } else {
    532540                /* No data to send, we can release the pipe for others. */
     541                async_exchange_end(exch);
    533542                pipe_end_transaction(pipe);
    534543        }
    535 
     544       
    536545        /*
    537546         * Wait for the answer.
Note: See TracChangeset for help on using the changeset viewer.