Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 91db50ac in mainline


Ignore:
Timestamp:
2010-11-19T21:50:46Z (11 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master
Children:
7034be15
Parents:
63b4f90
Message:

USB driver to HC communication uses DDF interfaces

Started work on using interfaces on the background of communication
between HC and USB driver. However, for driver developers, this will
be hidden completely.

Location:
uspace
Files:
3 added
11 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/usbkbd/main.c

    r63b4f90 r91db50ac  
    3030#include <errno.h>
    3131
     32#define BUFFER_SIZE 32
     33
     34/* Call this periodically to check keyboard status changes. */
     35static void poll_keyboard(device_t *dev)
     36{
     37        int rc;
     38        usb_handle_t handle;
     39        char buffer[BUFFER_SIZE];
     40        size_t actual_size;
     41        usb_endpoint_t poll_endpoint = 1;
     42
     43        rc = usb_drv_async_interrupt_in(dev->parent_phone, poll_endpoint,
     44            buffer, BUFFER_SIZE, &actual_size, &handle);
     45        if (rc != EOK) {
     46                return;
     47        }
     48
     49        rc = usb_drv_async_wait_for(handle);
     50        if (rc != EOK) {
     51                return;
     52        }
     53
     54        /*
     55         * If the keyboard answered with NAK, it returned no data.
     56         * This implies that no change happened since last query.
     57         */
     58        if (actual_size == 0) {
     59                return;
     60        }
     61
     62        /*
     63         * Process pressed keys.
     64         */
     65}
     66
    3267static int add_kbd_device(device_t *dev)
    3368{
     
    3873         * When everything is okay, connect to "our" HC.
    3974         */
    40         int rc = usb_drv_hc_connect(dev, 0);
    41         if (rc != EOK) {
     75        int phone = usb_drv_hc_connect(dev, 0);
     76        if (phone < 0) {
    4277                /*
    4378                 * Connecting to HC failed, roll-back and announce
    4479                 * failure.
    4580                 */
    46                 return rc;
     81                return phone;
    4782        }
     83
     84        dev->parent_phone = phone;
     85
     86        /*
     87         * Just for fun ;-).
     88         */
     89        poll_keyboard(dev);
    4890
    4991        /*
  • uspace/lib/c/include/ipc/dev_iface.h

    r63b4f90 r91db50ac  
    3838        HW_RES_DEV_IFACE = 0,   
    3939        CHAR_DEV_IFACE,
     40        USB_DEV_IFACE,
    4041        // TODO add more interfaces
    4142        DEV_IFACE_MAX
  • uspace/lib/drv/Makefile

    r63b4f90 r91db50ac  
    2929
    3030USPACE_PREFIX = ../..
    31 EXTRA_CFLAGS = -Iinclude
     31EXTRA_CFLAGS = -Iinclude -I$(LIB_PREFIX)
    3232LIBRARY = libdrv
    3333
     
    3636        generic/dev_iface.c \
    3737        generic/remote_res.c \
     38        generic/remote_usb.c \
    3839        generic/remote_char.c
    3940
  • uspace/lib/drv/generic/dev_iface.c

    r63b4f90 r91db50ac  
    3939#include "remote_res.h"
    4040#include "remote_char.h"
     41#include "remote_usb.h"
    4142
    4243static iface_dipatch_table_t remote_ifaces = {
    4344        .ifaces = {
    4445                &remote_res_iface,
    45                 &remote_char_iface
     46                &remote_char_iface,
     47                &remote_usb_iface
    4648        }
    4749};
  • uspace/lib/usb/Makefile

    r63b4f90 r91db50ac  
    3030LIBRARY = libusb
    3131LIBS = $(LIBDRV_PREFIX)/libdrv.a
    32 EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
     32EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include -I$(LIB_PREFIX)
    3333
    3434SOURCES = \
  • uspace/lib/usb/hcd.c

    r63b4f90 r91db50ac  
    5858#define NAMESPACE "usb"
    5959
    60 
    61 /** String representation of USB transaction outcome. */
    62 const char * usb_str_transaction_outcome(usb_transaction_outcome_t o)
    63 {
    64         switch (o) {
    65                 case USB_OUTCOME_OK:
    66                         return "ok";
    67                 case USB_OUTCOME_CRCERROR:
    68                         return "CRC error";
    69                 case USB_OUTCOME_BABBLE:
    70                         return "babble";
    71                 default:
    72                         return "unknown";
    73         }
    74 }
    7560
    7661/** Create necessary phones for communicating with HCD.
  • uspace/lib/usb/hcd.h

    r63b4f90 r91db50ac  
    4949typedef ipcarg_t usb_transaction_handle_t;
    5050
    51 /** USB transaction outcome. */
    52 typedef enum {
    53         USB_OUTCOME_OK,
    54         USB_OUTCOME_CRCERROR,
    55         USB_OUTCOME_BABBLE
    56 } usb_transaction_outcome_t;
    5751
    5852/** USB packet identifier. */
     
    8377} usb_packet_id;
    8478
    85 const char * usb_str_transaction_outcome(usb_transaction_outcome_t o);
    86 
    8779/** IPC methods for HCD.
    8880 *
  • uspace/lib/usb/usb.c

    r63b4f90 r91db50ac  
    5454}
    5555
     56/** String representation of USB transaction outcome. */
     57const char * usb_str_transaction_outcome(usb_transaction_outcome_t o)
     58{
     59        switch (o) {
     60                case USB_OUTCOME_OK:
     61                        return "ok";
     62                case USB_OUTCOME_CRCERROR:
     63                        return "CRC error";
     64                case USB_OUTCOME_BABBLE:
     65                        return "babble";
     66                default:
     67                        return "unknown";
     68        }
     69}
     70
    5671
    5772/**
  • uspace/lib/usb/usb.h

    r63b4f90 r91db50ac  
    5555} usb_direction_t;
    5656
     57/** USB transaction outcome. */
     58typedef enum {
     59        USB_OUTCOME_OK,
     60        USB_OUTCOME_CRCERROR,
     61        USB_OUTCOME_BABBLE
     62} usb_transaction_outcome_t;
     63
     64const char * usb_str_transaction_outcome(usb_transaction_outcome_t o);
     65
    5766/** USB address type.
    5867 * Negative values could be used to indicate error.
  • uspace/lib/usb/usbdrv.c

    r63b4f90 r91db50ac  
    3434 */
    3535#include "usbdrv.h"
     36#include <usb_iface.h>
    3637#include <errno.h>
    3738
     39/** Information about pending transaction on HC. */
     40typedef struct {
     41        /** Phone to host controller driver. */
     42        int phone;
     43        /** Data buffer. */
     44        void *buffer;
     45        /** Buffer size. */
     46        size_t size;
     47        /** Storage for actual number of bytes transferred. */
     48        size_t *size_transferred;
     49        /** Initial call replay data. */
     50        ipc_call_t reply;
     51        /** Initial call identifier. */
     52        aid_t request;
     53} transfer_info_t;
     54
    3855/** Connect to host controller the device is physically attached to.
    39  * This function sets the phone_parent property in the device_t struct.
    4056 *
    4157 * @param handle Device handle.
    4258 * @param flags Connection flags (blocking connection).
    43  * @return Error code.
     59 * @return Phone to corresponding HC or error code.
    4460 */
    4561int usb_drv_hc_connect(device_t *dev, unsigned int flags)
     
    5167}
    5268
     69/** Send data to HCD.
     70 *
     71 * @param phone Phone to HC.
     72 * @param method Method used for calling.
     73 * @param endpoint Device endpoint.
     74 * @param buffer Data buffer (NULL to skip data transfer phase).
     75 * @param size Buffer size (must be zero when @p buffer is NULL).
     76 * @param handle Storage for transaction handle (cannot be NULL).
     77 * @return Error status.
     78 * @retval EINVAL Invalid parameter.
     79 * @retval ENOMEM Not enough memory to complete the operation.
     80 */
     81static int async_send_buffer(int phone, int method,
     82    usb_endpoint_t endpoint,
     83    void *buffer, size_t size,
     84    usb_handle_t *handle)
     85{
     86        if (phone < 0) {
     87                return EINVAL;
     88        }
     89
     90        if ((buffer == NULL) && (size > 0)) {
     91                return EINVAL;
     92        }
     93
     94        if (handle == NULL) {
     95                return EINVAL;
     96        }
     97
     98        transfer_info_t *transfer
     99            = (transfer_info_t *) malloc(sizeof(transfer_info_t));
     100        if (transfer == NULL) {
     101                return ENOMEM;
     102        }
     103
     104        transfer->size_transferred = NULL;
     105        transfer->buffer = NULL;
     106        transfer->size = 0;
     107        transfer->phone = phone;
     108
     109        int rc;
     110
     111        transfer->request = async_send_3(phone,
     112            DEV_IFACE_ID(USB_DEV_IFACE),
     113            method,
     114            endpoint,
     115            size,
     116            &transfer->reply);
     117
     118        if (size > 0) {
     119                rc = async_data_write_start(phone, buffer, size);
     120                if (rc != EOK) {
     121                        async_wait_for(transfer->request, NULL);
     122                        return rc;
     123                }
     124        }
     125
     126        *handle = (usb_handle_t) transfer;
     127
     128        return EOK;
     129}
     130
     131/** Prepare data retrieval.
     132 *
     133 * @param phone Opened phone to HCD.
     134 * @param method Method used for calling.
     135 * @param endpoint Device endpoint.
     136 * @param buffer Buffer where to store retrieved data
     137 *      (NULL to skip data transfer phase).
     138 * @param size Buffer size (must be zero when @p buffer is NULL).
     139 * @param actual_size Storage where actual number of bytes transferred will
     140 *      be stored.
     141 * @param handle Storage for transaction handle (cannot be NULL).
     142 * @return Error status.
     143 * @retval EINVAL Invalid parameter.
     144 * @retval ENOMEM Not enough memory to complete the operation.
     145 */
     146static int async_recv_buffer(int phone, int method,
     147    usb_endpoint_t endpoint,
     148    void *buffer, size_t size, size_t *actual_size,
     149    usb_handle_t *handle)
     150{
     151        if (phone < 0) {
     152                return EINVAL;
     153        }
     154
     155        if ((buffer == NULL) && (size > 0)) {
     156                return EINVAL;
     157        }
     158
     159        if (handle == NULL) {
     160                return EINVAL;
     161        }
     162
     163        transfer_info_t *transfer
     164            = (transfer_info_t *) malloc(sizeof(transfer_info_t));
     165        if (transfer == NULL) {
     166                return ENOMEM;
     167        }
     168
     169        transfer->size_transferred = actual_size;
     170        transfer->buffer = buffer;
     171        transfer->size = size;
     172        transfer->phone = phone;
     173
     174        transfer->request = async_send_3(phone,
     175            DEV_IFACE_ID(USB_DEV_IFACE),
     176            method,
     177            endpoint,
     178            size,
     179            &transfer->reply);
     180
     181        *handle = (usb_handle_t) transfer;
     182
     183        return EOK;
     184}
     185
     186/** Read buffer from HCD.
     187 *
     188 * @param phone Opened phone to HCD.
     189 * @param hash Buffer hash (obtained after completing IN transaction).
     190 * @param buffer Buffer where to store data data.
     191 * @param size Buffer size.
     192 * @param actual_size Storage where actual number of bytes transferred will
     193 *      be stored.
     194 * @return Error status.
     195 */
     196static int read_buffer_in(int phone, ipcarg_t hash,
     197    void *buffer, size_t size, size_t *actual_size)
     198{
     199        ipc_call_t answer_data;
     200        ipcarg_t answer_rc;
     201        aid_t req;
     202        int rc;
     203
     204        req = async_send_2(phone,
     205            DEV_IFACE_ID(USB_DEV_IFACE),
     206            IPC_M_USB_GET_BUFFER,
     207            hash,
     208            &answer_data);
     209
     210        rc = async_data_read_start(phone, buffer, size);
     211        if (rc != EOK) {
     212                async_wait_for(req, NULL);
     213                return EINVAL;
     214        }
     215
     216        async_wait_for(req, &answer_rc);
     217        rc = (int)answer_rc;
     218
     219        if (rc != EOK) {
     220                return rc;
     221        }
     222
     223        *actual_size = IPC_GET_ARG1(answer_data);
     224
     225        return EOK;
     226}
     227
     228/** Blocks caller until given USB transaction is finished.
     229 * After the transaction is finished, the user can access all output data
     230 * given to initial call function.
     231 *
     232 * @param handle Transaction handle.
     233 * @return Error status.
     234 * @retval EOK No error.
     235 * @retval EBADMEM Invalid handle.
     236 * @retval ENOENT Data buffer associated with transaction does not exist.
     237 */
     238int usb_drv_async_wait_for(usb_handle_t handle)
     239{
     240        if (handle == 0) {
     241                return EBADMEM;
     242        }
     243
     244        int rc = EOK;
     245
     246        transfer_info_t *transfer = (transfer_info_t *) handle;
     247
     248        ipcarg_t answer_rc;
     249        async_wait_for(transfer->request, &answer_rc);
     250
     251        if (answer_rc != EOK) {
     252                rc = (int) answer_rc;
     253                goto leave;
     254        }
     255
     256        /*
     257         * If the buffer is not NULL, we must accept some data.
     258         */
     259        if ((transfer->buffer != NULL) && (transfer->size > 0)) {
     260                /*
     261                 * The buffer hash identifies the data on the server
     262                 * side.
     263                 * We will use it when actually reading-in the data.
     264                 */
     265                ipcarg_t buffer_hash = IPC_GET_ARG1(transfer->reply);
     266                if (buffer_hash == 0) {
     267                        rc = ENOENT;
     268                        goto leave;
     269                }
     270
     271                size_t actual_size;
     272                rc = read_buffer_in(transfer->phone, buffer_hash,
     273                    transfer->buffer, transfer->size, &actual_size);
     274
     275                if (rc != EOK) {
     276                        goto leave;
     277                }
     278
     279                if (transfer->size_transferred) {
     280                        *(transfer->size_transferred) = actual_size;
     281                }
     282        }
     283
     284leave:
     285        free(transfer);
     286
     287        return rc;
     288}
     289
     290/** Send interrupt data to device. */
     291int usb_drv_async_interrupt_out(int phone, usb_endpoint_t endpoint,
     292    void *buffer, size_t size,
     293    usb_handle_t *handle)
     294{
     295        return async_send_buffer(phone,
     296            IPC_M_USB_INTERRUPT_OUT,
     297            endpoint,
     298            buffer, size,
     299            handle);
     300}
     301
     302/** Request interrupt data from device. */
     303int usb_drv_async_interrupt_in(int phone, usb_endpoint_t endpoint,
     304    void *buffer, size_t size, size_t *actual_size,
     305    usb_handle_t *handle)
     306{
     307        return async_recv_buffer(phone,
     308            IPC_M_USB_INTERRUPT_IN,
     309            endpoint,
     310            buffer, size, actual_size,
     311            handle);
     312}
    53313
    54314/**
  • uspace/lib/usb/usbdrv.h

    r63b4f90 r91db50ac  
    4141int usb_drv_hc_connect(device_t *, unsigned int);
    4242
    43 /** Set endpoint properties (direction, type). */
    44 int usb_drv_set_endpoint_properties(device_t *, usb_endpoint_t,
    45     usb_transfer_type_t, usb_direction_t);
     43int usb_drv_async_interrupt_out(int, usb_endpoint_t,
     44    void *, size_t, usb_handle_t *);
     45int usb_drv_async_interrupt_in(int, usb_endpoint_t,
     46    void *, size_t, size_t *, usb_handle_t *);
    4647
    47 /* First variant - repeat transfer type. */
    48 int usb_drv_interrupt_out(device_t *, usb_endpoint_t,
    49     void *, size_t, usb_handle_t *);
    50 
    51 /* Second variant - let the HC determine transfer type by endpoint number. */
    52 int usb_drv_transfer_out(device_t *, usb_endpoint_t,
    53     void *, size_t, usb_handle_t *);
    54 
    55 
    56 /** Wait for usb_drv_transfer_* to complete. */
    57 int usb_drv_wait_for(usb_handle_t);
     48int usb_drv_async_wait_for(usb_handle_t);
    5849
    5950#endif
Note: See TracChangeset for help on using the changeset viewer.