Changeset 7a7bfeb3 in mainline for uspace/lib/usbvirt


Ignore:
Timestamp:
2010-10-24T16:43:40Z (15 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
355f7c2
Parents:
b8a3cda
Message:

Virtual USB overhaul almost complete

The virtual HC, hub and keyboard are rewritten after changes to HCD API.
Comments will be added later.

Location:
uspace/lib/usbvirt
Files:
1 added
1 deleted
7 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/usbvirt/Makefile

    rb8a3cda r7a7bfeb3  
    3535SOURCES = \
    3636        ctrlpipe.c \
    37         incoming.c \
    3837        main.c \
    39         stdreq.c
     38        stdreq.c \
     39        transaction.c
    4040
    4141include $(USPACE_PREFIX)/Makefile.common
  • uspace/lib/usbvirt/ctrlpipe.c

    rb8a3cda r7a7bfeb3  
    5353
    5454
    55 
    56 int control_pipe(void *buffer, size_t size)
     55int control_pipe(usbvirt_control_transfer_t *transfer)
    5756{
    58         if (size < sizeof(usb_device_request_setup_packet_t)) {
     57        if (transfer->request_size < sizeof(usb_device_request_setup_packet_t)) {
    5958                return ENOMEM;
    6059        }
    6160       
    62         usb_device_request_setup_packet_t *request = (usb_device_request_setup_packet_t *) buffer;
    63         uint8_t *remaining_data = ((uint8_t *) request) + sizeof(usb_device_request_setup_packet_t);
     61        usb_device_request_setup_packet_t *request = (usb_device_request_setup_packet_t *) transfer->request;
     62        uint8_t *remaining_data = transfer->data;
    6463       
    6564        int type = request_get_type(request->request_type);
     
    8079                        break;
    8180        }
    82        
    83         device->send_data(device, 0, NULL, 0);
    8481       
    8582        if (dev_new_address != -1) {
  • uspace/lib/usbvirt/device.h

    rb8a3cda r7a7bfeb3  
    4141
    4242struct usbvirt_device;
     43struct usbvirt_control_transfer;
    4344
    4445typedef int (*usbvirt_on_device_request_t)(struct usbvirt_device *dev,
     
    7071        /** Callback for class-specific USB request. */
    7172        usbvirt_on_device_request_t on_class_device_request;
     73       
     74        int (*on_control_transfer)(struct usbvirt_device *dev,
     75            usb_endpoint_t endpoint, struct usbvirt_control_transfer *transfer);
     76       
    7277        /** Callback for all other incoming data. */
    7378        int (*on_data)(struct usbvirt_device *dev,
     79            usb_endpoint_t endpoint, void *buffer, size_t size);
     80       
     81        /** Callback for host request for data. */
     82        int (*on_data_request)(struct usbvirt_device *dev,
     83            usb_endpoint_t endpoint, void *buffer, size_t size, size_t *actual_size);
     84       
     85        /** Decides direction of control transfer. */
     86        usb_direction_t (*decide_control_transfer_direction)(
    7487            usb_endpoint_t endpoint, void *buffer, size_t size);
    7588} usbvirt_device_ops_t;
     
    117130} usbvirt_device_state_t;
    118131
     132/** Information about on-going control transfer.
     133 */
     134typedef struct usbvirt_control_transfer {
     135        usb_direction_t direction;
     136        void *request;
     137        size_t request_size;
     138        void *data;
     139        size_t data_size;
     140} usbvirt_control_transfer_t;
     141
    119142/** Virtual USB device. */
    120143typedef struct usbvirt_device {
     
    122145        usbvirt_device_ops_t *ops;
    123146       
    124         /** Send data to HC.
    125          * @warning Do not change after initializing with
    126          * usbvirt_device_init().
    127          * This function is here merely to make the interface more OOP.
     147       
     148        /** Reply onto control transfer.
    128149         */
    129         int (*send_data)(struct usbvirt_device *dev,
     150        int (*control_transfer_reply)(struct usbvirt_device *dev,
    130151            usb_endpoint_t endpoint, void *buffer, size_t size);
    131152       
     
    153174        int device_id_;
    154175       
    155         /** Main routine called when data is received from HC.
    156          * @warning Do not change after initializing with
    157          * usbvirt_device_init().
    158          * This function is here merely to make the interface more OOP.
    159          */
    160         int (*receive_data)(struct usbvirt_device *dev,
     176        int (*transaction_out)(struct usbvirt_device *dev,
    161177            usb_endpoint_t endpoint, void *buffer, size_t size);
     178        int (*transaction_setup)(struct usbvirt_device *dev,
     179            usb_endpoint_t endpoint, void *buffer, size_t size);
     180        int (*transaction_in)(struct usbvirt_device *dev,
     181            usb_endpoint_t endpoint, void *buffer, size_t size, size_t *data_size);
    162182       
     183        usbvirt_control_transfer_t current_control_transfers[USB11_ENDPOINT_MAX];
    163184} usbvirt_device_t;
    164185
  • uspace/lib/usbvirt/hub.h

    rb8a3cda r7a7bfeb3  
    4141typedef enum {
    4242        IPC_M_USBVIRT_DATA_TO_DEVICE = IPC_FIRST_USER_METHOD,
    43         IPC_M_USBVIRT_DATA_FROM_DEVICE
     43        IPC_M_USBVIRT_DATA_FROM_DEVICE,
     44        IPC_M_USBVIRT_TRANSACTION_SETUP,
     45        IPC_M_USBVIRT_TRANSACTION_OUT,
     46        IPC_M_USBVIRT_TRANSACTION_IN,
    4447} usbvirt_device_method_t;
    4548
  • uspace/lib/usbvirt/main.c

    rb8a3cda r7a7bfeb3  
    3838#include <errno.h>
    3939#include <stdlib.h>
     40#include <mem.h>
    4041
    4142#include "hub.h"
     
    4748usbvirt_device_t *device = NULL;
    4849
    49 
    50 static void handle_data_to_device(ipc_callid_t iid, ipc_call_t icall)
     50static void handle_setup_transaction(ipc_callid_t iid, ipc_call_t icall)
    5151{
    5252        usb_address_t address = IPC_GET_ARG1(icall);
    5353        usb_endpoint_t endpoint = IPC_GET_ARG2(icall);
    54         size_t expected_len = IPC_GET_ARG5(icall);
     54        size_t expected_len = IPC_GET_ARG3(icall);
    5555       
    5656        if (address != device->address) {
     
    5959        }
    6060       
     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       
    6171        size_t len = 0;
    6272        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
     87static 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       
    63108        if (expected_len > 0) {
    64                 int rc = async_data_write_accept(&buffer, false,
    65                     1, USB_MAX_PAYLOAD_SIZE,
    66                     0, &len);
    67                
     109                rc = async_data_write_accept(&buffer, false,
     110                    1, USB_MAX_PAYLOAD_SIZE, 0, &len);
     111                       
    68112                if (rc != EOK) {
    69113                        ipc_answer_0(iid, rc);
     
    72116        }
    73117       
    74         device->receive_data(device, endpoint, buffer, len);
     118        rc = device->transaction_out(device, endpoint, buffer, len);
    75119       
    76120        if (buffer != NULL) {
     
    78122        }
    79123       
    80         ipc_answer_0(iid, EOK);
    81 }
     124        ipc_answer_0(iid, rc);
     125}
     126
     127
     128
     129static 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;
     159                }
     160                async_data_read_finalize(iid, buffer, receive_len);
     161        }
     162       
     163        ipc_answer_0(iid, rc);
     164}
     165
     166
    82167
    83168static void callback_connection(ipc_callid_t iid, ipc_call_t *icall)
     
    95180                                return;
    96181                       
    97                         case IPC_M_USBVIRT_DATA_TO_DEVICE:
    98                                 handle_data_to_device(callid, call);
     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);
    99192                                break;
    100193                       
     
    106199}
    107200
     201static int control_transfer_reply(struct usbvirt_device *device,
     202            usb_endpoint_t endpoint, void *buffer, size_t size)
     203{
     204        usbvirt_control_transfer_t *transfer = &device->current_control_transfers[endpoint];
     205        if (transfer->data != NULL) {
     206                free(transfer->data);
     207        }
     208        transfer->data = malloc(size);
     209        memcpy(transfer->data, buffer, size);
     210        transfer->data_size = size;
     211       
     212        return EOK;
     213}
     214
    108215static void device_init(usbvirt_device_t *dev)
    109216{
    110         dev->send_data = usbvirt_data_to_host;
    111         dev->receive_data = handle_incoming_data;
     217        dev->transaction_out = transaction_out;
     218        dev->transaction_setup = transaction_setup;
     219        dev->transaction_in = transaction_in;
     220       
     221        dev->control_transfer_reply = control_transfer_reply;
     222       
    112223        dev->state = USBVIRT_STATE_DEFAULT;
    113224        dev->address = 0;
    114 }
    115 
    116 int usbvirt_data_to_host(struct usbvirt_device *dev,
    117     usb_endpoint_t endpoint, void *buffer, size_t size)
    118 {
    119         int phone = dev->vhcd_phone_;
    120        
    121         if (phone < 0) {
    122                 return EINVAL;
    123         }
    124         if ((buffer == NULL) && (size != 0)) {
    125                 return EINVAL;
    126         }
    127 
    128         ipc_call_t answer_data;
    129         ipcarg_t answer_rc;
    130         aid_t req;
    131         int rc;
    132        
    133         req = async_send_3(phone,
    134             IPC_M_USBVIRT_DATA_FROM_DEVICE,
    135             dev->address,
    136             endpoint,
    137             size,
    138             &answer_data);
    139        
    140         if (size > 0) {
    141                 rc = async_data_write_start(phone, buffer, size);
    142                 if (rc != EOK) {
    143                         async_wait_for(req, NULL);
    144                         return rc;
    145                 }
    146         }
    147        
    148         async_wait_for(req, &answer_rc);
    149         rc = (int)answer_rc;
    150         if (rc != EOK) {
    151                 return rc;
    152         }
    153        
    154         return EOK;
     225       
     226        size_t i;
     227        for (i = 0; i < USB11_ENDPOINT_MAX; i++) {
     228                usbvirt_control_transfer_t *transfer = &dev->current_control_transfers[i];
     229                transfer->direction = 0;
     230                transfer->request = NULL;
     231                transfer->request_size = 0;
     232                transfer->data = NULL;
     233                transfer->data_size = 0;
     234        }
    155235}
    156236
  • uspace/lib/usbvirt/private.h

    rb8a3cda r7a7bfeb3  
    5454    usb_endpoint_t endpoint, void *buffer, size_t size);
    5555
    56 int control_pipe(void *buffer, size_t size);
     56int control_pipe(usbvirt_control_transfer_t *transfer);
    5757
    5858int handle_std_request(usb_device_request_setup_packet_t *request, uint8_t *data);
     
    6060extern usb_address_t dev_new_address;
    6161
     62int transaction_setup(usbvirt_device_t *device, usb_endpoint_t endpoint,
     63    void *buffer, size_t size);
     64int transaction_out(usbvirt_device_t *device, usb_endpoint_t endpoint,
     65    void *buffer, size_t size);
     66int transaction_in(usbvirt_device_t *device, usb_endpoint_t endpoint,
     67    void *buffer, size_t size, size_t *data_size);
     68
    6269#endif
    6370/**
  • uspace/lib/usbvirt/stdreq.c

    rb8a3cda r7a7bfeb3  
    5757        if ((type == USB_DESCTYPE_DEVICE) && (index == 0)) {
    5858                if (device->descriptors && device->descriptors->device) {
    59                         return device->send_data(device, 0,
     59                        return device->control_transfer_reply(device, 0,
    6060                            device->descriptors->device,
    6161                            device->descriptors->device->length);
     
    9595                }
    9696               
    97                 int rc = device->send_data(device, 0, all_data,
    98                     config->descriptor->total_length);
     97                int rc = device->control_transfer_reply(device, 0,
     98                    all_data, config->descriptor->total_length);
    9999               
    100100                free(all_data);
Note: See TracChangeset for help on using the changeset viewer.