Ignore:
Timestamp:
2010-10-10T11:53:05Z (13 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
b8100da
Parents:
bc9a629
Message:

Virtual HCD refactoring

Splitted into more files, added more comments.

File:
1 edited

Legend:

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

    rbc9a629 rb371844  
    4949#include "hc.h"
    5050#include "devices.h"
     51#include "conn.h"
    5152
    52 static usb_transaction_handle_t g_handle_seed = 1;
    53 static usb_transaction_handle_t create_transaction_handle(int phone)
    54 {
    55         return g_handle_seed++;
    56 }
    57 
    58 typedef struct {
    59         int phone;
    60         usb_transaction_handle_t handle;
    61 } transaction_details_t;
    62 
    63 static void out_callback(void * buffer, size_t len, usb_transaction_outcome_t outcome, void * arg)
    64 {
    65         dprintf("out_callback(buffer, %u, %d, %p)", len, outcome, arg);
    66         (void)len;
    67         transaction_details_t * trans = (transaction_details_t *)arg;
    68        
    69         async_msg_2(trans->phone, IPC_M_USB_HCD_DATA_SENT, trans->handle, outcome);
    70        
    71         free(trans);
    72         free(buffer);
    73 }
    74 
    75 static void in_callback(void * buffer, size_t len, usb_transaction_outcome_t outcome, void * arg)
    76 {
    77         dprintf("in_callback(buffer, %u, %d, %p)", len, outcome, arg);
    78         transaction_details_t * trans = (transaction_details_t *)arg;
    79        
    80         ipc_call_t answer_data;
    81         ipcarg_t answer_rc;
    82         aid_t req;
    83         int rc;
    84        
    85         req = async_send_3(trans->phone,
    86             IPC_M_USB_HCD_DATA_RECEIVED,
    87             trans->handle, outcome,
    88             len,
    89             &answer_data);
    90        
    91         rc = async_data_write_start(trans->phone, buffer, len);
    92         if (rc != EOK) {
    93                 async_wait_for(req, NULL);
    94                 goto leave;
    95         }
    96        
    97         async_wait_for(req, &answer_rc);
    98         rc = (int)answer_rc;
    99         if (rc != EOK) {
    100                 goto leave;
    101         }
    102        
    103 leave:
    104         free(trans);
    105         free(buffer);
    106 }
    107 
    108 
    109 
    110 static void handle_data_to_function(ipc_callid_t iid, ipc_call_t icall, int callback_phone)
    111 {
    112         usb_transfer_type_t transf_type = IPC_GET_ARG3(icall);
    113         usb_target_t target = {
    114                 .address = IPC_GET_ARG1(icall),
    115                 .endpoint = IPC_GET_ARG2(icall)
    116         };
    117        
    118         dprintf("pretending transfer to function (dev=%d:%d, type=%s)",
    119             target.address, target.endpoint,
    120             usb_str_transfer_type(transf_type));
    121        
    122         if (callback_phone == -1) {
    123                 ipc_answer_0(iid, ENOENT);
    124                 return;
    125         }
    126        
    127         usb_transaction_handle_t handle
    128             = create_transaction_handle(callback_phone);
    129        
    130         size_t len;
    131         void * buffer;
    132         int rc = async_data_write_accept(&buffer, false,
    133             1, USB_MAX_PAYLOAD_SIZE,
    134             0, &len);
    135        
    136         if (rc != EOK) {
    137                 ipc_answer_0(iid, rc);
    138                 return;
    139         }
    140        
    141         transaction_details_t * trans = malloc(sizeof(transaction_details_t));
    142         trans->phone = callback_phone;
    143         trans->handle = handle;
    144        
    145         dprintf("adding transaction to HC", NAME);
    146         hc_add_transaction_to_device(transf_type, target,
    147             buffer, len,
    148             out_callback, trans);
    149        
    150         ipc_answer_1(iid, EOK, handle);
    151         dprintf("transfer to function scheduled (handle %d)", handle);
    152 }
    153 
    154 static void handle_data_from_function(ipc_callid_t iid, ipc_call_t icall, int callback_phone)
    155 {
    156         usb_transfer_type_t transf_type = IPC_GET_ARG3(icall);
    157         usb_target_t target = {
    158                 .address = IPC_GET_ARG1(icall),
    159                 .endpoint = IPC_GET_ARG2(icall)
    160         };
    161         size_t len = IPC_GET_ARG4(icall);
    162        
    163         dprintf("pretending transfer from function (dev=%d:%d, type=%s)",
    164             target.address, target.endpoint,
    165             usb_str_transfer_type(transf_type));
    166        
    167         if (callback_phone == -1) {
    168                 ipc_answer_0(iid, ENOENT);
    169                 return;
    170         }
    171        
    172         usb_transaction_handle_t handle
    173             = create_transaction_handle(callback_phone);
    174        
    175         void * buffer = malloc(len);
    176        
    177         transaction_details_t * trans = malloc(sizeof(transaction_details_t));
    178         trans->phone = callback_phone;
    179         trans->handle = handle;
    180        
    181         dprintf("adding transaction to HC", NAME);
    182         hc_add_transaction_from_device(transf_type, target,
    183             buffer, len,
    184             in_callback, trans);
    185        
    186         ipc_answer_1(iid, EOK, handle);
    187         dprintf("transfer from function scheduled (handle %d)", handle);
    188 }
    189 
    190 static 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 
    213 static 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 
    224 static 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 }
    26253
    26354static void client_connection(ipc_callid_t iid, ipc_call_t *icall)
     
    26859        printf("%s: new client connected (phone %#x).\n", NAME, phone_hash);
    26960       
    270         int callback_phone = -1;
    271        
    27261        while (true) {
    27362                ipc_callid_t callid;
     
    27564               
    27665                callid = async_get_call(&call);
    277                 dprintf("%#x calls method %d", phone_hash, IPC_GET_METHOD(call));
    278                 switch (IPC_GET_METHOD(call)) {
    279                         case IPC_M_PHONE_HUNGUP:
    280                                 if (callback_phone != -1) {
    281                                         ipc_hangup(callback_phone);
     66               
     67                /*
     68                 * We can do nothing until we have the callback phone.
     69                 * Thus, we will wait for the callback and start processing
     70                 * after that.
     71                 */
     72                int method = (int) IPC_GET_METHOD(call);
     73               
     74                if (method == IPC_M_PHONE_HUNGUP) {
     75                        ipc_answer_0(callid, EOK);
     76                        return;
     77                }
     78               
     79                if (method == IPC_M_CONNECT_TO_ME) {
     80                        int kind = IPC_GET_ARG1(call);
     81                        int callback = IPC_GET_ARG5(call);
     82                       
     83                        /*
     84                         * Determine whether host connected to us
     85                         * or a device.
     86                         */
     87                        if (kind == 0) {
     88                                ipc_answer_0(callid, EOK);
     89                                connection_handler_host(phone_hash, callback);
     90                                return;
     91                        } else if (kind == 1) {
     92                                int device_id = IPC_GET_ARG2(call);
     93                                virtdev_connection_t *dev
     94                                    = virtdev_recognise(device_id, callback);
     95                                if (!dev) {
     96                                        ipc_answer_0(callid, EEXISTS);
     97                                        ipc_hangup(callback);
     98                                        return;
    28299                                }
    283100                                ipc_answer_0(callid, EOK);
    284                                 printf("%s: hung-up on %#x.\n", NAME, phone_hash);
     101                                connection_handler_device(phone_hash, dev);
     102                                virtdev_destroy_device(dev);
    285103                                return;
    286                        
    287                         case IPC_M_CONNECT_TO_ME:
    288                                 if (callback_phone != -1) {
    289                                         ipc_answer_0(callid, ELIMIT);
    290                                 } else {
    291                                         callback_phone = IPC_GET_ARG5(call);
    292                                         ipc_answer_0(callid, EOK);
    293                                 }
    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                                 }
    302                                 break;
    303                        
    304                         case IPC_M_USB_HCD_SEND_DATA:
    305                                 handle_data_to_function(callid, call, callback_phone);
    306                                 break;
    307                        
    308                         case IPC_M_USB_HCD_RECEIVE_DATA:
    309                                 handle_data_from_function(callid, call, callback_phone);
    310                                 break;
    311                        
    312                         case IPC_M_USB_HCD_TRANSACTION_SIZE:
    313                                 ipc_answer_1(callid, EOK, USB_MAX_PAYLOAD_SIZE);
    314                                 break;
    315                        
    316                         default:
     104                        } else {
    317105                                ipc_answer_0(callid, EINVAL);
    318                                 break;
     106                                ipc_hangup(callback);
     107                                return;
     108                        }
    319109                }
     110               
     111                /*
     112                 * No other methods could be served now.
     113                 */
     114                ipc_answer_0(callid, ENOTSUP);
    320115        }
    321116}
Note: See TracChangeset for help on using the changeset viewer.