Changeset 47e3a8e in mainline


Ignore:
Timestamp:
2010-10-15T16:32:57Z (14 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
186d630
Parents:
73301a0
Message:

Virtual USB device tracks its address

Now, each virtual device tracks its address and its state.

The virtual HC dispatches all transactions to all devices, thus
more precisely simulating situation on USB. The usbvirt framework
then decides whether it can accept the data or not, based on
their destination address.

Location:
uspace
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/usbvirt/device.h

    r73301a0 r47e3a8e  
    106106} usbvirt_descriptors_t;
    107107
     108/** Possible states of virtual USB device.
     109 * Notice that these are not 1:1 mappings to those in USB specification.
     110 */
     111typedef enum {
     112        USBVIRT_STATE_DEFAULT,
     113        USBVIRT_STATE_ADDRESS,
     114        USBVIRT_STATE_CONFIGURED
     115} usbvirt_device_state_t;
    108116
     117/** Virtual USB device. */
    109118typedef struct usbvirt_device {
    110119        /** Callback device operations. */
     
    126135        usbvirt_descriptors_t *descriptors;
    127136       
     137        /** Current device state. */
     138        usbvirt_device_state_t state;
     139        /** Device address. */
     140        usb_address_t address;
    128141       
    129142        /* Private attributes. */
  • uspace/lib/usbvirt/main.c

    r73301a0 r47e3a8e  
    5050static void handle_data_to_device(ipc_callid_t iid, ipc_call_t icall)
    5151{
    52         usb_endpoint_t endpoint = IPC_GET_ARG1(icall);
     52        usb_address_t address = IPC_GET_ARG1(icall);
     53        usb_endpoint_t endpoint = IPC_GET_ARG2(icall);
     54       
     55        if (address != device->address) {
     56                ipc_answer_0(iid, EADDRNOTAVAIL);
     57                return;
     58        }
    5359       
    5460        size_t len;
     
    95101}
    96102
     103static void device_init(usbvirt_device_t *dev)
     104{
     105        dev->send_data = usbvirt_data_to_host;
     106        dev->state = USBVIRT_STATE_DEFAULT;
     107        dev->address = 0;
     108}
     109
    97110int usbvirt_data_to_host(struct usbvirt_device *dev,
    98111    usb_endpoint_t endpoint, void *buffer, size_t size)
     
    112125        int rc;
    113126       
    114         req = async_send_1(phone,
     127        req = async_send_2(phone,
    115128            IPC_M_USBVIRT_DATA_FROM_DEVICE,
     129            dev->address,
    116130            endpoint,
    117131            &answer_data);
     
    174188       
    175189        dev->vhcd_phone_ = hcd_phone;
    176         dev->send_data = usbvirt_data_to_host;
     190        device_init(dev);
    177191       
    178192        device = dev;
  • uspace/lib/usbvirt/stdreq.c

    r73301a0 r47e3a8e  
    118118       
    119119        /*
    120          * TODO: inform the HC that device has new address assigned.
     120         * TODO: handle when this request is invalid (e.g.
     121         * setting address when in configured state).
    121122         */
     123        if (new_address == 0) {
     124                device->state = USBVIRT_STATE_DEFAULT;
     125        } else {
     126                device->state = USBVIRT_STATE_ADDRESS;
     127        }
     128       
     129        device->address = new_address;
     130       
    122131        return EOK;
    123132}
  • uspace/srv/hw/bus/usb/hcd/virtual/conndev.c

    r73301a0 r47e3a8e  
    4646    virtdev_connection_t *dev)
    4747{
    48         usb_endpoint_t endpoint = IPC_GET_ARG1(icall);
    4948        usb_target_t target = {
    50                 .address = dev->address,
    51                 .endpoint = endpoint
     49                .address = IPC_GET_ARG1(icall),
     50                .endpoint = IPC_GET_ARG2(icall)
    5251        };
    5352       
     
    8079        assert(dev != NULL);
    8180       
    82         dprintf("phone%#x: virtual device %d connected [%d]",
    83             phone_hash, dev->id, dev->address);
     81        dprintf("phone%#x: virtual device %d connected",
     82            phone_hash, dev->id);
    8483       
    8584        while (true) {
     
    9392                                ipc_hangup(dev->phone);
    9493                                ipc_answer_0(callid, EOK);
    95                                 dprintf("phone%#x: device %d [%d] hang-up",
    96                                     phone_hash, dev->id, dev->address);
     94                                dprintf("phone%#x: device %d hang-up",
     95                                    phone_hash, dev->id);
    9796                                return;
    9897                       
  • uspace/srv/hw/bus/usb/hcd/virtual/devices.c

    r73301a0 r47e3a8e  
    4444
    4545#include <usbvirt/ids.h>
     46#include <usbvirt/hub.h>
    4647
    4748#include "devices.h"
     
    6364        switch (id) {
    6465                case USBVIRT_DEV_KEYBOARD_ID:
    65                         dev = virtdev_add_device(
    66                             USBVIRT_DEV_KEYBOARD_ADDRESS, phone);
     66                        dev = virtdev_add_device(phone);
    6767                        break;
    6868                default:
     
    8484}
    8585
    86 /** Find virtual device by its USB address.
    87  *
    88  * @retval NULL No virtual device at given address.
    89  */
    90 virtdev_connection_t *virtdev_find_by_address(usb_address_t address)
    91 {
    92         link_t *pos;
    93         list_foreach(pos, &devices) {
    94                 virtdev_connection_t *dev
    95                     = list_get_instance(pos, virtdev_connection_t, link);
    96                 if (dev->address == address) {
    97                         return dev;
    98                 }
    99         }
    100        
    101         return NULL;
    102 }
    103 
    10486/** Create virtual device.
    10587 *
     
    10991 * @retval NULL Out of memory or address already occupied.
    11092 */
    111 virtdev_connection_t *virtdev_add_device(usb_address_t address, int phone)
     93virtdev_connection_t *virtdev_add_device(int phone)
    11294{
    113         link_t *pos;
    114         list_foreach(pos, &devices) {
    115                 virtdev_connection_t *dev
    116                     = list_get_instance(pos, virtdev_connection_t, link);
    117                 if (dev->address == address) {
    118                         return NULL;
    119                 }
    120         }
    121        
    12295        virtdev_connection_t *dev = (virtdev_connection_t *)
    12396            malloc(sizeof(virtdev_connection_t));
    12497        dev->phone = phone;
    125         dev->address = address;
    12698        list_append(&dev->link, &devices);
    12799       
     
    137109}
    138110
     111/** Send data to all connected devices.
     112 *
     113 * @param transaction Transaction to be sent over the bus.
     114 */
     115usb_transaction_outcome_t virtdev_send_to_all(transaction_t *transaction)
     116{
     117        link_t *pos;
     118        list_foreach(pos, &devices) {
     119                virtdev_connection_t *dev
     120                    = list_get_instance(pos, virtdev_connection_t, link);
     121               
     122                ipc_call_t answer_data;
     123                ipcarg_t answer_rc;
     124                aid_t req;
     125                int rc;
     126               
     127                req = async_send_3(dev->phone,
     128                    IPC_M_USBVIRT_DATA_TO_DEVICE,
     129                    transaction->target.address,
     130                    transaction->target.endpoint,
     131                    transaction->type,
     132                    &answer_data);
     133               
     134                rc = async_data_write_start(dev->phone,
     135                    transaction->buffer, transaction->len);
     136                if (rc != EOK) {
     137                        async_wait_for(req, NULL);
     138                } else {
     139                        async_wait_for(req, &answer_rc);
     140                        rc = (int)answer_rc;
     141                }
     142        }
     143       
     144        /*
     145         * TODO: maybe screw some transactions to get more
     146         * real-life image.
     147         */
     148        return USB_OUTCOME_OK;
     149}
     150
    139151/**
    140152 * @}
  • uspace/srv/hw/bus/usb/hcd/virtual/devices.h

    r73301a0 r47e3a8e  
    3939#include <usb/hcd.h>
    4040
     41#include "hc.h"
     42
    4143/** Connected virtual device. */
    4244typedef struct {
    43         /** Assigned USB address. */
    44         usb_address_t address;
    4545        /** Phone used when sending data to device. */
    4646        int phone;
     
    5252
    5353virtdev_connection_t *virtdev_recognise(int, int);
    54 virtdev_connection_t *virtdev_find_by_address(usb_address_t);
    55 virtdev_connection_t *virtdev_add_device(usb_address_t, int);
     54virtdev_connection_t *virtdev_add_device(int);
    5655void virtdev_destroy_device(virtdev_connection_t *);
     56usb_transaction_outcome_t virtdev_send_to_all(transaction_t *);
    5757
    5858#endif
  • uspace/srv/hw/bus/usb/hcd/virtual/hc.c

    r73301a0 r47e3a8e  
    6868static link_t transaction_from_device_list;
    6969
    70 /** Pending transaction details. */
    71 typedef struct {
    72         /** Linked-list link. */
    73         link_t link;
    74         /** Device address. */
    75         usb_target_t target;
    76         /** Direction of the transaction. */
    77         usb_direction_t direction;
    78         /** Transfer type. */
    79         usb_transfer_type_t type;
    80         /** Transaction data buffer. */
    81         void * buffer;
    82         /** Transaction data length. */
    83         size_t len;
    84         /** Callback after transaction is done. */
    85         hc_transaction_done_callback_t callback;
    86         /** Argument to the callback. */
    87         void * callback_arg;
    88 } transaction_t;
    89 
    9070#define TRANSACTION_FORMAT "T[%d:%d %s %s (%d)]"
    9171#define TRANSACTION_PRINTF(t) \
     
    136116                }
    137117               
    138                 link_t * first_transaction_link = transaction_to_device_list.next;
    139                 transaction_t * transaction
     118                link_t *first_transaction_link = transaction_to_device_list.next;
     119                transaction_t *transaction
    140120                    = transaction_get_instance(first_transaction_link);
    141121                list_remove(first_transaction_link);
    142122               
    143                 virtdev_connection_t *dev = virtdev_find_by_address(
    144                     transaction->target.address);
    145                 usb_transaction_outcome_t outcome = USB_OUTCOME_OK;
    146                
    147                 if (dev != NULL) {
    148                         dprintf("sending data to device at %d.%d (phone %d)",
    149                             dev->address, transaction->target.endpoint,
    150                             dev->phone);
    151                         ipc_call_t answer_data;
    152                         ipcarg_t answer_rc;
    153                         aid_t req;
    154                         int rc;
    155                        
    156                         req = async_send_2(dev->phone,
    157                             IPC_M_USBVIRT_DATA_TO_DEVICE,
    158                             transaction->target.endpoint,
    159                             transaction->type,
    160                             &answer_data);
    161                        
    162                         rc = async_data_write_start(dev->phone,
    163                             transaction->buffer, transaction->len);
    164                         if (rc != EOK) {
    165                                 async_wait_for(req, NULL);
    166                         } else {
    167                                 async_wait_for(req, &answer_rc);
    168                                 rc = (int)answer_rc;
    169                         }
    170                        
    171                         if (rc != EOK) {
    172                                 outcome = USB_OUTCOME_BABBLE;
    173                         }
    174                 } else {
    175                         outcome = USB_OUTCOME_CRCERROR;
    176                 }
     123                usb_transaction_outcome_t outcome;
     124                outcome = virtdev_send_to_all(transaction);
    177125               
    178126                process_transaction_with_outcome(transaction, outcome);
  • uspace/srv/hw/bus/usb/hcd/virtual/hc.h

    r73301a0 r47e3a8e  
    4848    usb_transaction_outcome_t outcome, void *arg);
    4949
     50/** Pending transaction details. */
     51typedef struct {
     52        /** Linked-list link. */
     53        link_t link;
     54        /** Device address. */
     55        usb_target_t target;
     56        /** Direction of the transaction. */
     57        usb_direction_t direction;
     58        /** Transfer type. */
     59        usb_transfer_type_t type;
     60        /** Transaction data buffer. */
     61        void * buffer;
     62        /** Transaction data length. */
     63        size_t len;
     64        /** Callback after transaction is done. */
     65        hc_transaction_done_callback_t callback;
     66        /** Argument to the callback. */
     67        void * callback_arg;
     68} transaction_t;
     69
    5070void hc_manager(void);
    5171
Note: See TracChangeset for help on using the changeset viewer.