Ignore:
Timestamp:
2010-10-10T09:00:53Z (14 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
b371844
Parents:
4bc309b
Message:

Start work on virtual USB keyboard

The virtual HC(D) is now able to serve as HCD towards central USB driver
as well as virtual HC towards virtual devices.

Each device is a separate task that communicates with VHCD through simple
protocol.

Will clean and comment the code in next revisions. Promise.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/hw/bus/usb/hcd/virtual/hc.c

    r4bc309b rbc9a629  
    4040#include <stdlib.h>
    4141#include <stdio.h>
     42#include <errno.h>
     43#include <str_error.h>
     44
     45#include <usb/virtdev.h>
    4246
    4347#include "vhcd.h"
    4448#include "hc.h"
     49#include "devices.h"
    4550
    4651#define USLEEP_BASE (500 * 1000)
     
    6065        } while (0)
    6166
    62 static link_t transaction_list;
     67static link_t transaction_to_device_list;
     68static link_t transaction_from_device_list;
    6369
    6470
     
    97103            usb_str_transaction_outcome(outcome));
    98104       
     105        dprintf("  callback %p (%p, %u, %d, %p)", transaction->callback,
     106            transaction->buffer, transaction->len, outcome,
     107            transaction->callback_arg);
     108       
    99109        transaction->callback(transaction->buffer, transaction->len, outcome,
    100110            transaction->callback_arg);
    101 }
    102 
     111        dprintf("callback processed");
     112}
     113
     114#if 0
    103115static void process_transaction(transaction_t * transaction)
    104116{
     
    113125        process_transaction_with_outcome(transaction, outcome);
    114126}
     127#endif
    115128
    116129void hc_manager(void)
    117130{
    118         list_initialize(&transaction_list);
     131        list_initialize(&transaction_to_device_list);
     132        list_initialize(&transaction_from_device_list);
    119133       
    120134        static unsigned int seed = 4573;
     
    125139                async_usleep(USLEEP_BASE + (pseudo_random(&seed) % USLEEP_VAR));
    126140               
    127                 if (list_empty(&transaction_list)) {
     141                if (list_empty(&transaction_to_device_list)) {
    128142                        continue;
    129143                }
    130144               
    131                 link_t * first_transaction_link = transaction_list.next;
    132                 transaction_t * first_transaction
     145                link_t * first_transaction_link = transaction_to_device_list.next;
     146                transaction_t * transaction
    133147                    = transaction_get_instance(first_transaction_link);
    134148                list_remove(first_transaction_link);
    135149               
    136                 process_transaction(first_transaction);
    137                
    138                 free(first_transaction);
    139         }
    140 }
    141 
    142 static void hc_add_transaction(usb_transfer_type_t type, usb_target_t target,
     150                virtdev_connection_t *dev = virtdev_find_by_address(
     151                    transaction->target.address);
     152                if (dev != NULL) {
     153                        dprintf("sending data to device at %d.%d (phone %d)\n",
     154                            dev->address, transaction->target.endpoint,
     155                            dev->phone);
     156                        ipc_call_t answer_data;
     157                        ipcarg_t answer_rc;
     158                        aid_t req;
     159                        int rc;
     160                       
     161                        req = async_send_2(dev->phone,
     162                            IPC_M_USB_VIRTDEV_DATA_TO_DEVICE,
     163                            transaction->target.endpoint,
     164                            transaction->type,
     165                            &answer_data);
     166                       
     167                        rc = async_data_write_start(dev->phone,
     168                            transaction->buffer, transaction->len);
     169                        if (rc != EOK) {
     170                                async_wait_for(req, NULL);
     171                        } else {
     172                                async_wait_for(req, &answer_rc);
     173                                rc = (int)answer_rc;
     174                        }
     175                } else {
     176                        process_transaction_with_outcome(transaction,
     177                            USB_OUTCOME_OK);
     178                }
     179               
     180                free(transaction);
     181        }
     182}
     183
     184static transaction_t *transaction_create(usb_transfer_type_t type, usb_target_t target,
    143185    usb_direction_t direction,
    144186    void * buffer, size_t len,
     
    156198        transaction->callback_arg = arg;
    157199       
    158         dprintf("adding transaction " TRANSACTION_FORMAT,
    159             TRANSACTION_PRINTF(*transaction));
    160 
    161         list_append(&transaction->link, &transaction_list);
    162 }
    163 
    164 void hc_add_out_transaction(usb_transfer_type_t type, usb_target_t target,
     200        return transaction;
     201}
     202
     203
     204void hc_add_transaction_to_device(usb_transfer_type_t type, usb_target_t target,
    165205    void * buffer, size_t len,
    166206    hc_transaction_done_callback_t callback, void * arg)
    167207{
    168         hc_add_transaction(type, target, USB_DIRECTION_OUT,
    169             buffer, len, callback, arg);
    170 }
    171 
    172 void hc_add_in_transaction(usb_transfer_type_t type, usb_target_t target,
     208        transaction_t *transaction = transaction_create(type, target,
     209            USB_DIRECTION_OUT, buffer, len, callback, arg);
     210        list_append(&transaction->link, &transaction_to_device_list);
     211}
     212
     213void hc_add_transaction_from_device(usb_transfer_type_t type, usb_target_t target,
    173214    void * buffer, size_t len,
    174215    hc_transaction_done_callback_t callback, void * arg)
    175216{
    176         static unsigned int seed = 216;
    177        
    178         size_t i;
    179         char * data = (char *)buffer;
    180         for (i = 0; i < len; i++, data++) {
    181                 *data = 'A' + (pseudo_random(&seed) % ('Z' - 'A'));
    182         }
    183        
    184         unsigned int shortening = pseudo_random(&seed) % SHORTENING_VAR;
    185         if (len > shortening) {
    186                 len -= shortening;
    187         }
    188        
    189         hc_add_transaction(type, target, USB_DIRECTION_IN,
    190             buffer, len, callback, arg);
     217        transaction_t *transaction = transaction_create(type, target,
     218            USB_DIRECTION_IN, buffer, len, callback, arg);
     219        list_append(&transaction->link, &transaction_from_device_list);
     220}
     221
     222int hc_fillin_transaction_from_device(usb_transfer_type_t type, usb_target_t target,
     223    void * buffer, size_t len)
     224{
     225        dprintf("finding transaction to fill data in...");
     226        /*
     227         * Find correct transaction envelope in the list.
     228         */
     229        if (list_empty(&transaction_from_device_list)) {
     230                return ENOENT;
     231        }
     232       
     233        transaction_t *transaction = NULL;
     234        link_t *pos = transaction_from_device_list.next;
     235       
     236        while (pos != &transaction_from_device_list) {
     237                transaction_t *t = transaction_get_instance(pos);
     238                if (usb_target_same(t->target, target)) {
     239                        transaction = t;
     240                        break;
     241                }
     242                pos = pos->next;
     243        }
     244        if (transaction == NULL) {
     245                return ENOENT;
     246        }
     247       
     248        /*
     249         * Remove the transaction from the list as it will be processed now.
     250         */
     251        list_remove(&transaction->link);
     252       
     253        if (transaction->len < len) {
     254                process_transaction_with_outcome(transaction, USB_OUTCOME_BABBLE);
     255                return ENOMEM;
     256        }
     257       
     258        /*
     259         * Copy the data and finish processing the transaction.
     260         */
     261        transaction->len = len;
     262        memcpy(transaction->buffer, buffer, len);
     263       
     264        process_transaction_with_outcome(transaction, USB_OUTCOME_OK);
     265       
     266        dprintf(" ...transaction " TRANSACTION_FORMAT " sent back",
     267            TRANSACTION_PRINTF(*transaction));
     268       
     269       
     270        free(transaction);
     271       
     272        return EOK;
    191273}
    192274
Note: See TracChangeset for help on using the changeset viewer.