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

Changeset ca07cd3 in mainline


Ignore:
Timestamp:
2010-10-25T13:23:33Z (10 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
master
Children:
23cb44b
Parents:
355f7c2
Message:

Code cleanup, various bugfixes

The internal functions of virtual device framework always get
device structure as parameter, thus possible enabling more devices
within single task (that is not possible because currently there
is no way to pass extra argument into callback_connection()).

Also, added some missing comments and completely removed the device
id nonsense (devices can send their descriptors and the hub is able
to enable/disable its ports).

Location:
uspace
Files:
1 added
1 deleted
14 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/virtusbkbd/virtusbkbd.c

    r355f7c2 rca07cd3  
    5050#include <usbvirt/device.h>
    5151#include <usbvirt/hub.h>
    52 #include <usbvirt/ids.h>
    5352
    5453#include "kbdconfig.h"
     
    154153        .ops = &keyboard_ops,
    155154        .descriptors = &descriptors,
    156         .device_id_ = USBVIRT_DEV_KEYBOARD_ID
     155        .name = "keyboard"
    157156};
    158157
     
    230229        printf("%s: Terminating...\n", NAME);
    231230       
    232         usbvirt_disconnect();
     231        usbvirt_disconnect(&keyboard_dev);
    233232       
    234233        return 0;
  • uspace/lib/usbvirt/Makefile

    r355f7c2 rca07cd3  
    3434
    3535SOURCES = \
     36        callback.c \
    3637        ctrlpipe.c \
    3738        main.c \
  • uspace/lib/usbvirt/ctrlpipe.c

    r355f7c2 rca07cd3  
    4747usb_address_t dev_new_address = -1;
    4848
     49/** Tell request type.
     50 * By type is meant either standard, class, vendor or other.
     51 */
    4952static int request_get_type(uint8_t request_type)
    5053{
     
    5255}
    5356
    54 
    55 int control_pipe(usbvirt_control_transfer_t *transfer)
     57/** Handle communication over control pipe zero.
     58 */
     59int control_pipe(usbvirt_device_t *device, usbvirt_control_transfer_t *transfer)
    5660{
    5761        if (transfer->request_size < sizeof(usb_device_request_setup_packet_t)) {
     
    6872        switch (type) {
    6973                case REQUEST_TYPE_STANDARD:
    70                         rc = handle_std_request(request, remaining_data);
     74                        rc = handle_std_request(device, request, remaining_data);
    7175                        break;
    7276                case REQUEST_TYPE_CLASS:
     
    8084        }
    8185       
    82         if (dev_new_address != -1) {
     86        if (device->new_address != -1) {
    8387                /*
    8488                 * TODO: handle when this request is invalid (e.g.
    8589                 * setting address when in configured state).
    8690                 */
    87                 if (dev_new_address == 0) {
     91                if (device->new_address == 0) {
    8892                        device->state = USBVIRT_STATE_DEFAULT;
    8993                } else {
    9094                        device->state = USBVIRT_STATE_ADDRESS;
    9195                }
    92                 device->address = dev_new_address;
     96                device->address = device->new_address;
    9397               
    94                 dev_new_address = -1;
     98                device->new_address = -1;
    9599        }
    96100       
  • uspace/lib/usbvirt/device.h

    r355f7c2 rca07cd3  
    4040#include <usb/devreq.h>
    4141
    42 struct usbvirt_device;
     42typedef struct usbvirt_device usbvirt_device_t;
    4343struct usbvirt_control_transfer;
    4444
    45 typedef int (*usbvirt_on_device_request_t)(struct usbvirt_device *dev,
     45typedef int (*usbvirt_on_device_request_t)(usbvirt_device_t *dev,
    4646        usb_device_request_setup_packet_t *request,
    4747        uint8_t *data);
     
    7272        usbvirt_on_device_request_t on_class_device_request;
    7373       
    74         int (*on_control_transfer)(struct usbvirt_device *dev,
     74        int (*on_control_transfer)(usbvirt_device_t *dev,
    7575            usb_endpoint_t endpoint, struct usbvirt_control_transfer *transfer);
    7676       
    7777        /** Callback for all other incoming data. */
    78         int (*on_data)(struct usbvirt_device *dev,
     78        int (*on_data)(usbvirt_device_t *dev,
    7979            usb_endpoint_t endpoint, void *buffer, size_t size);
    8080       
    8181        /** Callback for host request for data. */
    82         int (*on_data_request)(struct usbvirt_device *dev,
     82        int (*on_data_request)(usbvirt_device_t *dev,
    8383            usb_endpoint_t endpoint, void *buffer, size_t size, size_t *actual_size);
    8484       
     
    133133 */
    134134typedef struct usbvirt_control_transfer {
     135        /** Transfer direction (read/write control transfer). */
    135136        usb_direction_t direction;
     137        /** Request data. */
    136138        void *request;
     139        /** Size of request data. */
    137140        size_t request_size;
     141        /** Payload. */
    138142        void *data;
     143        /** Size of payload. */
    139144        size_t data_size;
    140145} usbvirt_control_transfer_t;
    141146
    142147/** Virtual USB device. */
    143 typedef struct usbvirt_device {
     148struct usbvirt_device {
    144149        /** Callback device operations. */
    145150        usbvirt_device_ops_t *ops;
    146151       
    147        
    148152        /** Reply onto control transfer.
    149153         */
    150         int (*control_transfer_reply)(struct usbvirt_device *dev,
     154        int (*control_transfer_reply)(usbvirt_device_t *dev,
    151155            usb_endpoint_t endpoint, void *buffer, size_t size);
    152156       
    153         /* Device attributes. */
     157        /** Device name.
     158         * Used in debug prints and sent to virtual host controller.
     159         */
     160        const char *name;
    154161       
    155162        /** Standard descriptors. */
     
    158165        /** Current device state. */
    159166        usbvirt_device_state_t state;
     167       
    160168        /** Device address. */
    161169        usb_address_t address;
     170        /** New device address.
     171         * This field is used during SET_ADDRESS request.
     172         * On all other occasions, it holds invalid address (e.g. -1).
     173         */
     174        usb_address_t new_address;
    162175       
    163         /* Private attributes. */
    164        
    165         /** Phone to HC.
    166          * @warning Do not change, this is private variable.
    167          */
    168         int vhcd_phone_;
    169        
    170         /** Device id.
    171          * This item will be removed when device enumeration and
    172          * recognition is implemented.
    173          */
    174         int device_id_;
    175        
    176         int (*transaction_out)(struct usbvirt_device *dev,
     176        /** Process OUT transaction. */
     177        int (*transaction_out)(usbvirt_device_t *dev,
    177178            usb_endpoint_t endpoint, void *buffer, size_t size);
    178         int (*transaction_setup)(struct usbvirt_device *dev,
     179        /** Process SETUP transaction. */
     180        int (*transaction_setup)(usbvirt_device_t *dev,
    179181            usb_endpoint_t endpoint, void *buffer, size_t size);
    180         int (*transaction_in)(struct usbvirt_device *dev,
     182        /** Process IN transaction. */
     183        int (*transaction_in)(usbvirt_device_t *dev,
    181184            usb_endpoint_t endpoint, void *buffer, size_t size, size_t *data_size);
    182185       
     186        /** State information on control-transfer endpoints. */
    183187        usbvirt_control_transfer_t current_control_transfers[USB11_ENDPOINT_MAX];
    184 } usbvirt_device_t;
     188};
    185189
    186190#endif
  • uspace/lib/usbvirt/hub.h

    r355f7c2 rca07cd3  
    3838#include "device.h"
    3939
     40/** USB transaction type.
     41 * This types does not correspond directly to types in USB specification,
     42 * as actually DATA transactions are marked with these types to identify
     43 * their direction (and tag).
     44 */
     45typedef enum {
     46        USBVIRT_TRANSACTION_SETUP,
     47        USBVIRT_TRANSACTION_IN,
     48        USBVIRT_TRANSACTION_OUT
     49} usbvirt_transaction_type_t;
    4050
     51const char *usbvirt_str_transaction_type(usbvirt_transaction_type_t type);
     52
     53/** Telephony methods of virtual devices. */
    4154typedef enum {
    42         IPC_M_USBVIRT_DATA_TO_DEVICE = IPC_FIRST_USER_METHOD,
    43         IPC_M_USBVIRT_DATA_FROM_DEVICE,
     55        IPC_M_USBVIRT_GET_NAME = IPC_FIRST_USER_METHOD,
    4456        IPC_M_USBVIRT_TRANSACTION_SETUP,
    4557        IPC_M_USBVIRT_TRANSACTION_OUT,
     
    4860
    4961int usbvirt_connect(usbvirt_device_t *, const char *);
    50 int usbvirt_disconnect(void);
    5162int usbvirt_connect_local(usbvirt_device_t *);
     63int usbvirt_disconnect(usbvirt_device_t *dev);
    5264
    5365#endif
  • uspace/lib/usbvirt/main.c

    r355f7c2 rca07cd3  
    3131 */
    3232/** @file
    33  * @brief Main handler for virtual USB device.
     33 * @brief Device registration with virtual USB framework.
    3434 */
    3535#include <devmap.h>
     
    3939#include <stdlib.h>
    4040#include <mem.h>
     41#include <assert.h>
    4142
    4243#include "hub.h"
     
    4647#define NAMESPACE "usb"
    4748
    48 usbvirt_device_t *device = NULL;
    49 
    50 static void handle_setup_transaction(ipc_callid_t iid, ipc_call_t icall)
    51 {
    52         usb_address_t address = IPC_GET_ARG1(icall);
    53         usb_endpoint_t endpoint = IPC_GET_ARG2(icall);
    54         size_t expected_len = IPC_GET_ARG3(icall);
    55        
    56         if (address != device->address) {
    57                 ipc_answer_0(iid, EADDRNOTAVAIL);
    58                 return;
    59         }
    60        
    61         if ((endpoint < 0) || (endpoint >= USB11_ENDPOINT_MAX)) {
    62                 ipc_answer_0(iid, EINVAL);
    63                 return;
    64         }
    65        
    66         if (expected_len == 0) {
    67                 ipc_answer_0(iid, EINVAL);
    68                 return;
    69         }
    70        
    71         size_t len = 0;
    72         void * buffer = NULL;
    73         int rc = async_data_write_accept(&buffer, false,
    74             1, USB_MAX_PAYLOAD_SIZE, 0, &len);
    75                
    76         if (rc != EOK) {
    77                 ipc_answer_0(iid, rc);
    78                 return;
    79         }
    80        
    81         rc = device->transaction_setup(device, endpoint, buffer, len);
    82        
    83         ipc_answer_0(iid, rc);
    84 }
    85 
    86 
    87 static void handle_out_transaction(ipc_callid_t iid, ipc_call_t icall)
    88 {
    89         usb_address_t address = IPC_GET_ARG1(icall);
    90         usb_endpoint_t endpoint = IPC_GET_ARG2(icall);
    91         size_t expected_len = IPC_GET_ARG3(icall);
    92        
    93         if (address != device->address) {
    94                 ipc_answer_0(iid, EADDRNOTAVAIL);
    95                 return;
    96         }
    97        
    98         if ((endpoint < 0) || (endpoint >= USB11_ENDPOINT_MAX)) {
    99                 ipc_answer_0(iid, EINVAL);
    100                 return;
    101         }
    102        
    103         int rc = EOK;
    104        
    105         size_t len = 0;
    106         void *buffer = NULL;
    107        
    108         if (expected_len > 0) {
    109                 rc = async_data_write_accept(&buffer, false,
    110                     1, USB_MAX_PAYLOAD_SIZE, 0, &len);
    111                        
    112                 if (rc != EOK) {
    113                         ipc_answer_0(iid, rc);
    114                         return;
     49/** Virtual device wrapper. */
     50typedef struct {
     51        /** Actual device. */
     52        usbvirt_device_t *device;
     53        /** Phone to host controller. */
     54        int vhcd_phone;
     55        /** Device id. */
     56        ipcarg_t id;
     57        /** Linked-list member. */
     58        link_t link;
     59} virtual_device_t;
     60
     61/*** List of known device. */
     62static LIST_INITIALIZE(device_list);
     63
     64/** Find virtual device wrapper based on the contents. */
     65static virtual_device_t *find_device(usbvirt_device_t *device)
     66{
     67        if (list_empty(&device_list)) {
     68                return NULL;
     69        }
     70       
     71        link_t *pos;
     72        for (pos = device_list.next; pos != &device_list; pos = pos->next) {
     73                virtual_device_t *dev
     74                    = list_get_instance(pos, virtual_device_t, link);
     75                if (dev->device == device) {
     76                        return dev;
    11577                }
    11678        }
    11779       
    118         rc = device->transaction_out(device, endpoint, buffer, len);
    119        
    120         if (buffer != NULL) {
    121                 free(buffer);
    122         }
    123        
    124         ipc_answer_0(iid, rc);
    125 }
    126 
    127 
    128 
    129 static void handle_in_transaction(ipc_callid_t iid, ipc_call_t icall)
    130 {
    131         usb_address_t address = IPC_GET_ARG1(icall);
    132         usb_endpoint_t endpoint = IPC_GET_ARG2(icall);
    133         size_t expected_len = IPC_GET_ARG3(icall);
    134        
    135         if (address != device->address) {
    136                 ipc_answer_0(iid, EADDRNOTAVAIL);
    137                 return;
    138         }
    139        
    140         if ((endpoint < 0) || (endpoint >= USB11_ENDPOINT_MAX)) {
    141                 ipc_answer_0(iid, EINVAL);
    142                 return;
    143         }
    144        
    145         int rc = EOK;
    146        
    147         void *buffer = expected_len > 0 ? malloc(expected_len) : NULL;
    148         size_t len;
    149        
    150         rc = device->transaction_in(device, endpoint, buffer, expected_len, &len);
    151         /*
    152          * If the request was processed, we will send data back.
    153          */
    154         if (rc == EOK) {
    155                 size_t receive_len;
    156                 if (!async_data_read_receive(&iid, &receive_len)) {
    157                         ipc_answer_0(iid, EINVAL);
    158                         return;
     80        return NULL;
     81}
     82
     83/** Find virtual device wrapper by its id. */
     84static virtual_device_t *find_device_by_id(ipcarg_t id)
     85{
     86        if (list_empty(&device_list)) {
     87                return NULL;
     88        }
     89       
     90        link_t *pos;
     91        for (pos = device_list.next; pos != &device_list; pos = pos->next) {
     92                virtual_device_t *dev
     93                    = list_get_instance(pos, virtual_device_t, link);
     94                if (dev->id == id) {
     95                        return dev;
    15996                }
    160                 async_data_read_finalize(iid, buffer, receive_len);
    161         }
    162        
    163         ipc_answer_0(iid, rc);
    164 }
    165 
    166 
    167 
    168 static void callback_connection(ipc_callid_t iid, ipc_call_t *icall)
    169 {
    170         ipc_answer_0(iid, EOK);
    171        
    172         while (true) {
    173                 ipc_callid_t callid;
    174                 ipc_call_t call;
    175                
    176                 callid = async_get_call(&call);
    177                 switch (IPC_GET_METHOD(call)) {
    178                         case IPC_M_PHONE_HUNGUP:
    179                                 ipc_answer_0(callid, EOK);
    180                                 return;
    181                        
    182                         case IPC_M_USBVIRT_TRANSACTION_SETUP:
    183                                 handle_setup_transaction(callid, call);
    184                                 break;
    185                        
    186                         case IPC_M_USBVIRT_TRANSACTION_OUT:
    187                                 handle_out_transaction(callid, call);
    188                                 break;
    189                                
    190                         case IPC_M_USBVIRT_TRANSACTION_IN:
    191                                 handle_in_transaction(callid, call);
    192                                 break;
    193                        
    194                         default:
    195                                 ipc_answer_0(callid, EINVAL);
    196                                 break;
    197                 }
    198         }
    199 }
    200 
    201 static int control_transfer_reply(struct usbvirt_device *device,
     97        }
     98       
     99        return NULL;
     100}
     101
     102/** Reply to a control transfer. */
     103static int control_transfer_reply(usbvirt_device_t *device,
    202104            usb_endpoint_t endpoint, void *buffer, size_t size)
    203105{
     
    213115}
    214116
     117/** Initialize virtual device. */
    215118static void device_init(usbvirt_device_t *dev)
    216119{
     
    223126        dev->state = USBVIRT_STATE_DEFAULT;
    224127        dev->address = 0;
     128        dev->new_address = -1;
    225129       
    226130        size_t i;
     
    235139}
    236140
     141/** Add a virtual device.
     142 * The returned device (if not NULL) shall be destroy via destroy_device().
     143 */
     144static virtual_device_t *add_device(usbvirt_device_t *dev)
     145{
     146        assert(find_device(dev) == NULL);
     147        virtual_device_t *new_device
     148            = (virtual_device_t *) malloc(sizeof(virtual_device_t));
     149       
     150        new_device->device = dev;
     151        link_initialize(&new_device->link);
     152       
     153        list_append(&new_device->link, &device_list);
     154       
     155        return new_device;
     156}
     157
     158/** Destroy virtual device. */
     159static void destroy_device(virtual_device_t *dev)
     160{
     161        if (dev->vhcd_phone > 0) {
     162                ipc_hangup(dev->vhcd_phone);
     163        }
     164       
     165        list_remove(&dev->link);
     166       
     167        free(dev);
     168}
     169
     170/** Callback connection handler. */
     171static void callback_connection(ipc_callid_t iid, ipc_call_t *icall)
     172{
     173        // FIXME - determine which device just called back
     174        virtual_device_t *dev = find_device_by_id(0);
     175        if (dev == NULL) {
     176                ipc_answer_0(iid, EINVAL);
     177                printf("Ooops\n");
     178                return;
     179        }
     180       
     181        device_callback_connection(dev->device, iid, icall);
     182}
     183
    237184/** Create necessary phones for comunication with virtual HCD.
    238185 * This function wraps following calls:
     
    254201int usbvirt_connect(usbvirt_device_t *dev, const char *hcd_path)
    255202{
     203        virtual_device_t *virtual_device = find_device(dev);
     204        if (virtual_device != NULL) {
     205                return EEXISTS;
     206        }
     207       
    256208        char dev_path[DEVMAP_NAME_MAXLEN + 1];
    257209        snprintf(dev_path, DEVMAP_NAME_MAXLEN,
     
    270222       
    271223        ipcarg_t phonehash;
    272         int rc = ipc_connect_to_me(hcd_phone, 1, dev->device_id_, 0, &phonehash);
     224        int rc = ipc_connect_to_me(hcd_phone, 1, 0, 0, &phonehash);
    273225        if (rc != EOK) {
    274226                return rc;
    275227        }
    276228       
    277         dev->vhcd_phone_ = hcd_phone;
    278229        device_init(dev);
    279230       
    280         device = dev;
     231        virtual_device = add_device(dev);
     232        virtual_device->vhcd_phone = hcd_phone;
     233        virtual_device->id = 0;
    281234       
    282235        async_new_connection(phonehash, 0, NULL, callback_connection);
     
    290243 *
    291244 * @param dev Device to connect.
    292  * @return Always EOK.
     245 * @return Error code.
     246 * @retval EOK Device connected.
     247 * @retval EEXISTS This device is already connected.
    293248 */
    294249int usbvirt_connect_local(usbvirt_device_t *dev)
    295250{
    296         dev->vhcd_phone_ = -1;
     251        virtual_device_t *virtual_device = find_device(dev);
     252        if (virtual_device != NULL) {
     253                return EEXISTS;
     254        }
     255       
    297256        device_init(dev);
    298257       
    299         device = dev;
     258        virtual_device = add_device(dev);
     259        virtual_device->vhcd_phone = -1;
     260        virtual_device->id = 0;
    300261       
    301262        return EOK;
     
    304265/** Disconnects device from HCD.
    305266 *
    306  * @return Always EOK.
    307  */
    308 int usbvirt_disconnect(void)
    309 {
    310         ipc_hangup(device->vhcd_phone_);
    311        
    312         device = NULL;
     267 * @param dev Device to be disconnected.
     268 * @return Error code.
     269 * @retval EOK Device connected.
     270 * @retval ENOENT This device is not connected.
     271 */
     272int usbvirt_disconnect(usbvirt_device_t *dev)
     273{
     274        virtual_device_t *virtual_device = find_device(dev);
     275        if (virtual_device == NULL) {
     276                return ENOENT;
     277        }
     278       
     279        destroy_device(virtual_device);
    313280       
    314281        return EOK;
  • uspace/lib/usbvirt/private.h

    r355f7c2 rca07cd3  
    3939#include "hub.h"
    4040
    41 extern usbvirt_device_t *device;
    4241
    4342#define DEVICE_HAS_OP(dev, op) \
     
    5453    usb_endpoint_t endpoint, void *buffer, size_t size);
    5554
    56 int control_pipe(usbvirt_control_transfer_t *transfer);
     55int control_pipe(usbvirt_device_t *device, usbvirt_control_transfer_t *transfer);
    5756
    58 int handle_std_request(usb_device_request_setup_packet_t *request, uint8_t *data);
     57int handle_std_request(usbvirt_device_t *device, usb_device_request_setup_packet_t *request, uint8_t *data);
    5958
    60 extern usb_address_t dev_new_address;
     59void device_callback_connection(usbvirt_device_t *device, ipc_callid_t iid, ipc_call_t *icall);
    6160
    6261int transaction_setup(usbvirt_device_t *device, usb_endpoint_t endpoint,
  • uspace/lib/usbvirt/stdreq.c

    r355f7c2 rca07cd3  
    4949 */
    5050 
    51 static int handle_get_descriptor(uint8_t type, uint8_t index, uint16_t language,
     51/** GET_DESCRIPTOR handler. */
     52static int handle_get_descriptor(usbvirt_device_t *device,
     53    uint8_t type, uint8_t index, uint16_t language,
    5254    uint16_t length)
    5355{
     
    106108}
    107109
    108 static int handle_set_address(uint16_t new_address,
     110/** SET_ADDRESS handler. */
     111static int handle_set_address(usbvirt_device_t *device,
     112    uint16_t new_address,
    109113    uint16_t zero1, uint16_t zero2)
    110114{
     
    117121        }
    118122       
    119         dev_new_address = new_address;
     123        device->new_address = new_address;
    120124       
    121125        return EOK;
    122126}
    123127
    124 static int handle_set_configuration(uint16_t configuration_value,
     128/** SET_CONFIGURATION handler. */
     129static int handle_set_configuration(usbvirt_device_t *device,
     130    uint16_t configuration_value,
    125131    uint16_t zero1, uint16_t zero2)
    126132{
     
    177183        } while (false)
    178184
    179 
    180 int handle_std_request(usb_device_request_setup_packet_t *request, uint8_t *data)
     185/** Handle standard device request. */
     186int handle_std_request(usbvirt_device_t *device,
     187    usb_device_request_setup_packet_t *request, uint8_t *data)
    181188{
    182189        HANDLE_REQUEST(request, data, USB_DEVREQ_GET_DESCRIPTOR,
    183190            device, on_get_descriptor,
    184             handle_get_descriptor(request->value_low, request->value_high,
     191            handle_get_descriptor(device, request->value_low, request->value_high,
    185192                request->index, request->length));
    186193       
    187194        HANDLE_REQUEST(request, data, USB_DEVREQ_SET_ADDRESS,
    188195            device, on_set_address,
    189             handle_set_address(request->value,
     196            handle_set_address(device, request->value,
    190197                request->index, request->length));
    191198       
    192199        HANDLE_REQUEST(request, data, USB_DEVREQ_SET_CONFIGURATION,
    193200            device, on_set_configuration,
    194             handle_set_configuration(request->value,
     201            handle_set_configuration(device, request->value,
    195202                request->index, request->length));
    196203       
  • uspace/lib/usbvirt/transaction.c

    r355f7c2 rca07cd3  
    3838#include <mem.h>
    3939
    40 #include "ids.h"
     40#include "hub.h"
    4141#include "private.h"
    4242
    43 static usb_direction_t setup_transaction_direction(usb_endpoint_t, void *, size_t);
    44 static void process_control_transfer(usb_endpoint_t, usbvirt_control_transfer_t *);
     43static usb_direction_t setup_transaction_direction(usbvirt_device_t *,
     44    usb_endpoint_t, void *, size_t);
     45static void process_control_transfer(usbvirt_device_t *,
     46    usb_endpoint_t, usbvirt_control_transfer_t *);
    4547
    4648/** Convert virtual USB transaction type to string.
     
    6062}
    6163
     64/** SETUP transaction handling.
     65 * The setup transaction only prepares control transfer on given endpoint.
     66 */
    6267int transaction_setup(usbvirt_device_t *device, usb_endpoint_t endpoint,
    6368    void *buffer, size_t size)
     
    7277        }
    7378       
    74         transfer->direction = setup_transaction_direction(endpoint,
     79        transfer->direction = setup_transaction_direction(device, endpoint,
    7580            buffer, size);
    7681        transfer->request = buffer;
     
    7984        transfer->data_size = 0;
    8085       
     86        if (transfer->direction == USB_DIRECTION_IN) {
     87                process_control_transfer(device, endpoint, transfer);
     88        }
     89       
    8190        return EOK;
    8291}
    8392
     93/** OUT transaction handling.
     94 * The OUT transaction can trigger processing of a control transfer.
     95 */
    8496int transaction_out(usbvirt_device_t *device, usb_endpoint_t endpoint,
    8597    void *buffer, size_t size)
     
    133145}
    134146
     147/** IN transaction handling.
     148 * The IN transaction can trigger processing of a control transfer.
     149 */
    135150int transaction_in(usbvirt_device_t *device, usb_endpoint_t endpoint,
    136151    void *buffer, size_t size, size_t *data_size)
     
    145160                         * This means end of input data.
    146161                         */
    147                         process_control_transfer(endpoint, transfer);
     162                        process_control_transfer(device, endpoint, transfer);
    148163                } else {
    149164                        /*
     
    151166                         * of the buffer.
    152167                         */
    153                         // TODO: implement
     168                        // FIXME: handle when the HC wants the data back
     169                        // in more chunks
     170                        size_t actual_size = 0;
     171                        if (transfer->data) {
     172                                actual_size = transfer->data_size;
     173                        }
     174                        if (actual_size > size) {
     175                                actual_size = size;
     176                        }
     177                        if (actual_size > 0) {
     178                                memcpy(buffer, transfer->data, actual_size);
     179                                if (data_size) {
     180                                        *data_size = actual_size;
     181                                }
     182                        }
    154183                }
    155184               
     
    170199}
    171200
    172 
    173 static usb_direction_t setup_transaction_direction(usb_endpoint_t endpoint,
     201/** Determine direction of control transfer.
     202 * First, try the user provided callback, otherwise guess, believing that
     203 * it uses the same format as control pipe 0.
     204 */
     205static usb_direction_t setup_transaction_direction(usbvirt_device_t *device,
     206    usb_endpoint_t endpoint,
    174207    void *data, size_t size)
    175208{
     
    202235}
    203236
    204 static void process_control_transfer(usb_endpoint_t endpoint,
     237/** Process control transfer.
     238 */
     239static void process_control_transfer(usbvirt_device_t *device,
     240    usb_endpoint_t endpoint,
    205241    usbvirt_control_transfer_t *transfer)
    206242{
     
    213249        if (rc == EFORWARD) {
    214250                if (endpoint == 0) {
    215                         rc = control_pipe(transfer);
     251                        rc = control_pipe(device, transfer);
    216252                }
    217253        }
  • uspace/srv/hw/bus/usb/hcd/virtual/conndev.c

    r355f7c2 rca07cd3  
    4242#include "hub.h"
    4343
     44#define DEVICE_NAME_MAXLENGTH 32
     45
     46static int get_device_name(int phone, char *buffer, size_t len)
     47{
     48        ipc_call_t answer_data;
     49        ipcarg_t answer_rc;
     50        aid_t req;
     51        int rc;
     52       
     53        req = async_send_0(phone,
     54            IPC_M_USBVIRT_GET_NAME,
     55            &answer_data);
     56       
     57        rc = async_data_read_start(phone, buffer, len);
     58        if (rc != EOK) {
     59                async_wait_for(req, NULL);
     60                return EINVAL;
     61        }
     62       
     63        async_wait_for(req, &answer_rc);
     64        rc = (int)answer_rc;
     65       
     66        if (IPC_GET_ARG1(answer_data) < len) {
     67                len = IPC_GET_ARG1(answer_data);
     68        } else {
     69                len--;
     70        }
     71        buffer[len] = 0;
     72       
     73        return rc;
     74}
     75
    4476/** Connection handler for communcation with virtual device.
    4577 *
     
    5385        assert(dev != NULL);
    5486       
    55         dprintf(0, "virtual device connected through phone %#x", phone_hash);
     87        char devname[DEVICE_NAME_MAXLENGTH + 1];
     88        int rc = get_device_name(dev->phone, devname, DEVICE_NAME_MAXLENGTH);
     89       
     90        dprintf(0, "virtual device connected (phone: %#x, name: %s)",
     91            phone_hash, rc == EOK ? devname : "<unknown>");
     92       
    5693       
    5794        while (true) {
  • uspace/srv/hw/bus/usb/hcd/virtual/devices.c

    r355f7c2 rca07cd3  
    4343#include <str_error.h>
    4444
    45 #include <usbvirt/ids.h>
    4645#include <usbvirt/hub.h>
    4746
     
    5554
    5655LIST_INITIALIZE(devices);
    57 
    58 /** Recognise device by id.
    59  *
    60  * @param id Device id.
    61  * @param phone Callback phone.
    62  */
    63 virtdev_connection_t *virtdev_recognise(int id, int phone)
    64 {
    65         virtdev_connection_t * dev = virtdev_add_device(phone);
    66        
    67         /*
    68          * We do not want to mess-up the virtdev_add_device() as
    69          * the id is needed only before device probing/detection
    70          * is implemented.
    71          *
    72          * However, that does not mean that this will happen soon.
    73          */
    74         if (dev) {
    75                 dev->id = id;
    76         }
    77        
    78         return dev;
    79 }
    8056
    8157/** Create virtual device.
  • uspace/srv/hw/bus/usb/hcd/virtual/devices.h

    r355f7c2 rca07cd3  
    4545        /** Phone used when sending data to device. */
    4646        int phone;
    47         /** Device id. */
    48         int id;
    4947        /** Linked-list handle. */
    5048        link_t link;
    5149} virtdev_connection_t;
    5250
    53 virtdev_connection_t *virtdev_recognise(int, int);
    5451virtdev_connection_t *virtdev_add_device(int);
    5552void virtdev_destroy_device(virtdev_connection_t *);
  • uspace/srv/hw/bus/usb/hcd/virtual/hc.h

    r355f7c2 rca07cd3  
    3737
    3838#include <usb/hcd.h>
    39 #include <usbvirt/ids.h>
     39#include <usbvirt/hub.h>
    4040
    4141/** Callback after transaction is sent to USB.
  • uspace/srv/hw/bus/usb/hcd/virtual/hcd.c

    r355f7c2 rca07cd3  
    8989                                return;
    9090                        } else if (kind == 1) {
    91                                 int device_id = IPC_GET_ARG2(call);
    9291                                virtdev_connection_t *dev
    93                                     = virtdev_recognise(device_id, callback);
     92                                    = virtdev_add_device(callback);
    9493                                if (!dev) {
    9594                                        ipc_answer_0(callid, EEXISTS);
Note: See TracChangeset for help on using the changeset viewer.