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

Changeset bc9a629 in mainline


Ignore:
Timestamp:
2010-10-10T09:00:53Z (11 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master
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.

Files:
6 added
10 edited

Legend:

Unmodified
Added
Removed
  • .bzrignore

    r4bc309b rbc9a629  
    5353./uspace/app/trace/trace
    5454./uspace/app/usb/usb
     55./uspace/app/virtusbkbd/vuk
    5556./uspace/dist/app/bdsh
    5657./uspace/dist/app/edit
     
    7273./uspace/dist/app/trace
    7374./uspace/dist/app/usb
     75./uspace/dist/app/vuk
    7476./uspace/dist/cfg/net/general
    7577./uspace/dist/cfg/net/lo
  • boot/Makefile.common

    r4bc309b rbc9a629  
    134134        $(USPACE_PATH)/app/stats/stats \
    135135        $(USPACE_PATH)/app/usb/usb \
     136        $(USPACE_PATH)/app/virtusbkbd/vuk \
    136137        $(USPACE_PATH)/app/tasks/tasks \
    137138        $(USPACE_PATH)/app/top/top
  • uspace/Makefile

    r4bc309b rbc9a629  
    4949        app/trace \
    5050        app/top \
     51        app/virtusbkbd \
    5152        srv/clip \
    5253        srv/devmap \
  • uspace/app/usb/example.c

    r4bc309b rbc9a629  
    129129                usb_transaction_handle_t handle;
    130130
    131                 usb_target_t target = { 11 + i, 3 };
     131                usb_target_t target = { i, 0 };
    132132                int rc = usb_hcd_send_data_to_function(hcd_phone,
    133133                    target, USB_TRANSFER_ISOCHRONOUS,
  • uspace/lib/usb/Makefile

    r4bc309b rbc9a629  
    3131
    3232SOURCES = \
    33         hcd.c
     33        hcd.c \
     34        virtdev.c
    3435
    3536include $(USPACE_PREFIX)/Makefile.common
  • uspace/lib/usb/hcd.h

    r4bc309b rbc9a629  
    7575        usb_endpoint_t endpoint;
    7676} usb_target_t;
     77
     78static inline int usb_target_same(usb_target_t a, usb_target_t b)
     79{
     80        return (a.address == b.address)
     81            && (a.endpoint == b.endpoint);
     82}
    7783
    7884/** Opaque handle of active USB transaction.
  • uspace/srv/hw/bus/usb/hcd/virtual/Makefile

    r4bc309b rbc9a629  
    3333
    3434SOURCES = \
     35        devices.c \
    3536        hc.c \
    3637        hcd.c
  • 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
  • uspace/srv/hw/bus/usb/hcd/virtual/hc.h

    r4bc309b rbc9a629  
    4242void hc_manager(void);
    4343
    44 void hc_add_out_transaction(usb_transfer_type_t type, usb_target_t target,
     44void hc_add_transaction_to_device(usb_transfer_type_t type, usb_target_t target,
    4545    void * buffer, size_t len,
    4646    hc_transaction_done_callback_t callback, void * arg);
    4747
    48 void hc_add_in_transaction(usb_transfer_type_t type, usb_target_t target,
     48void hc_add_transaction_from_device(usb_transfer_type_t type, usb_target_t target,
    4949    void * buffer, size_t len,
    5050    hc_transaction_done_callback_t callback, void * arg);
    5151
     52int hc_fillin_transaction_from_device(usb_transfer_type_t type, usb_target_t target,
     53    void * buffer, size_t len);
    5254
    5355#endif
  • uspace/srv/hw/bus/usb/hcd/virtual/hcd.c

    r4bc309b rbc9a629  
    4545
    4646#include <usb/hcd.h>
     47#include <usb/virtdev.h>
    4748#include "vhcd.h"
    4849#include "hc.h"
     50#include "devices.h"
    4951
    5052static usb_transaction_handle_t g_handle_seed = 1;
     
    6163static void out_callback(void * buffer, size_t len, usb_transaction_outcome_t outcome, void * arg)
    6264{
     65        dprintf("out_callback(buffer, %u, %d, %p)", len, outcome, arg);
    6366        (void)len;
    6467        transaction_details_t * trans = (transaction_details_t *)arg;
     
    7275static void in_callback(void * buffer, size_t len, usb_transaction_outcome_t outcome, void * arg)
    7376{
     77        dprintf("in_callback(buffer, %u, %d, %p)", len, outcome, arg);
    7478        transaction_details_t * trans = (transaction_details_t *)arg;
    7579       
     
    140144       
    141145        dprintf("adding transaction to HC", NAME);
    142         hc_add_out_transaction(transf_type, target,
     146        hc_add_transaction_to_device(transf_type, target,
    143147            buffer, len,
    144148            out_callback, trans);
     
    176180       
    177181        dprintf("adding transaction to HC", NAME);
    178         hc_add_in_transaction(transf_type, target,
     182        hc_add_transaction_from_device(transf_type, target,
    179183            buffer, len,
    180184            in_callback, trans);
     
    184188}
    185189
     190static void handle_data_from_device(ipc_callid_t iid, ipc_call_t icall, virtdev_connection_t *dev)
     191{
     192        usb_endpoint_t endpoint = IPC_GET_ARG1(icall);
     193        usb_target_t target = {
     194                .address = dev->address,
     195                .endpoint = endpoint
     196        };
     197        size_t len;
     198        void * buffer;
     199        int rc = async_data_write_accept(&buffer, false,
     200            1, USB_MAX_PAYLOAD_SIZE,
     201            0, &len);
     202       
     203        if (rc != EOK) {
     204                ipc_answer_0(iid, rc);
     205                return;
     206        }
     207       
     208        rc = hc_fillin_transaction_from_device(USB_TRANSFER_INTERRUPT, target, buffer, len);
     209       
     210        ipc_answer_0(iid, rc);
     211}
     212
     213static virtdev_connection_t *recognise_device(int id, int callback_phone)
     214{
     215        switch (id) {
     216                case USB_VIRTDEV_KEYBOARD_ID:
     217                        return virtdev_add_device(
     218                            USB_VIRTDEV_KEYBOARD_ADDRESS, callback_phone);
     219                default:
     220                        return NULL;
     221        }               
     222}
     223
     224static void device_client_connection(int callback_phone, int device_id)
     225{
     226        virtdev_connection_t *dev = recognise_device(device_id, callback_phone);
     227        if (!dev) {
     228                if (callback_phone != -1) {
     229                        ipc_hangup(callback_phone);
     230                }
     231                return;
     232        }
     233        dprintf("device %d connected", device_id);
     234        while (true) {
     235                ipc_callid_t callid;
     236                ipc_call_t call;
     237               
     238                callid = async_get_call(&call);
     239               
     240                switch (IPC_GET_METHOD(call)) {
     241                        case IPC_M_PHONE_HUNGUP:
     242                                if (callback_phone != -1) {
     243                                        ipc_hangup(callback_phone);
     244                                }
     245                                ipc_answer_0(callid, EOK);
     246                                dprintf("hung-up on device %d", device_id);
     247                                virtdev_destroy_device(dev);
     248                                return;
     249                        case IPC_M_CONNECT_TO_ME:
     250                                ipc_answer_0(callid, ELIMIT);
     251                                break;
     252                        case IPC_M_USB_VIRTDEV_DATA_FROM_DEVICE:
     253                                dprintf("data from device %d", device_id);
     254                                handle_data_from_device(callid, call, dev);
     255                                break;
     256                        default:
     257                                ipc_answer_0(callid, EINVAL);
     258                                break;
     259                }
     260        }
     261}
    186262
    187263static void client_connection(ipc_callid_t iid, ipc_call_t *icall)
     
    216292                                        ipc_answer_0(callid, EOK);
    217293                                }
     294                                if (IPC_GET_ARG1(call) == 1) {
     295                                        /* Virtual device was just connected
     296                                         * to us. This is handled elsewhere.
     297                                         */
     298                                        device_client_connection(callback_phone,
     299                                            IPC_GET_ARG2(call));
     300                                        return;
     301                                }
    218302                                break;
    219303                       
Note: See TracChangeset for help on using the changeset viewer.