Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/drv/generic/remote_usbhc.c

    r6edd494 r93f8da1  
    11/*
    2  * Copyright (c) 2010 Vojtech Horky
     2 * Copyright (c) 2010-2011 Vojtech Horky
    33 * All rights reserved.
    44 *
     
    5252static void remote_usbhc_control_read_data(device_t *, void *, ipc_callid_t, ipc_call_t *);
    5353static void remote_usbhc_control_read_status(device_t *, void *, ipc_callid_t, ipc_call_t *);
     54static void remote_usbhc_control_write(device_t *, void *, ipc_callid_t, ipc_call_t *);
     55static void remote_usbhc_control_read(device_t *, void *, ipc_callid_t, ipc_call_t *);
    5456static void remote_usbhc_reserve_default_address(device_t *, void *, ipc_callid_t, ipc_call_t *);
    5557static void remote_usbhc_release_default_address(device_t *, void *, ipc_callid_t, ipc_call_t *);
     
    8183        remote_usbhc_control_read_setup,
    8284        remote_usbhc_control_read_data,
    83         remote_usbhc_control_read_status
     85        remote_usbhc_control_read_status,
     86
     87        remote_usbhc_control_write,
     88        remote_usbhc_control_read
    8489};
    8590
     
    95100        ipc_callid_t caller;
    96101        void *buffer;
     102        void *setup_packet;
    97103        size_t size;
    98104} async_transaction_t;
    99105
     106static void async_transaction_destroy(async_transaction_t *trans)
     107{
     108        if (trans == NULL) {
     109                return;
     110        }
     111
     112        if (trans->setup_packet != NULL) {
     113                free(trans->setup_packet);
     114        }
     115        if (trans->buffer != NULL) {
     116                free(trans->buffer);
     117        }
     118
     119        free(trans);
     120}
     121
     122static async_transaction_t *async_transaction_create(ipc_callid_t caller)
     123{
     124        async_transaction_t *trans = malloc(sizeof(async_transaction_t));
     125        if (trans == NULL) {
     126                return NULL;
     127        }
     128
     129        trans->caller = caller;
     130        trans->buffer = NULL;
     131        trans->setup_packet = NULL;
     132        trans->size = 0;
     133
     134        return trans;
     135}
     136
    100137void remote_usbhc_get_address(device_t *device, void *iface,
    101138    ipc_callid_t callid, ipc_call_t *call)
     
    130167        if (trans->buffer == NULL) {
    131168                ipc_answer_0(callid, EINVAL);
    132                 free(trans);
     169                async_transaction_destroy(trans);
    133170                return;
    134171        }
     
    138175        if (!async_data_read_receive(&cid, &accepted_size)) {
    139176                ipc_answer_0(callid, EINVAL);
     177                async_transaction_destroy(trans);
    140178                return;
    141179        }
     
    148186        ipc_answer_1(callid, EOK, accepted_size);
    149187
    150         free(trans->buffer);
    151         free(trans);
     188        async_transaction_destroy(trans);
    152189}
    153190
     
    242279        async_transaction_t *trans = (async_transaction_t *)arg;
    243280
    244         // FIXME - answer according to outcome
    245         ipc_answer_0(trans->caller, EOK);
    246 
    247         free(trans);
     281        ipc_answer_0(trans->caller, outcome);
     282
     283        async_transaction_destroy(trans);
    248284}
    249285
     
    253289        async_transaction_t *trans = (async_transaction_t *)arg;
    254290
    255         // FIXME - answer according to outcome
    256         ipc_answer_1(trans->caller, EOK, (sysarg_t)trans);
     291        if (outcome != USB_OUTCOME_OK) {
     292                ipc_answer_0(trans->caller, outcome);
     293                async_transaction_destroy(trans);
     294                return;
     295        }
    257296
    258297        trans->size = actual_size;
     298        ipc_answer_1(trans->caller, USB_OUTCOME_OK, (sysarg_t)trans);
    259299}
    260300
     
    294334        }
    295335
    296         async_transaction_t *trans = malloc(sizeof(async_transaction_t));
    297         trans->caller = callid;
    298         trans->buffer = buffer;
    299         trans->size = len;
    300 
    301         int rc = transfer_func(device, target, buffer, len,
    302             callback_out, trans);
    303 
    304         if (rc != EOK) {
    305                 ipc_answer_0(callid, rc);
     336        async_transaction_t *trans = async_transaction_create(callid);
     337        if (trans == NULL) {
    306338                if (buffer != NULL) {
    307339                        free(buffer);
    308340                }
    309                 free(trans);
     341                ipc_answer_0(callid, ENOMEM);
     342                return;
     343        }
     344
     345        trans->buffer = buffer;
     346        trans->size = len;
     347
     348        int rc = transfer_func(device, target, buffer, len,
     349            callback_out, trans);
     350
     351        if (rc != EOK) {
     352                ipc_answer_0(callid, rc);
     353                async_transaction_destroy(trans);
    310354        }
    311355}
     
    333377        };
    334378
    335         async_transaction_t *trans = malloc(sizeof(async_transaction_t));
    336         trans->caller = callid;
     379        async_transaction_t *trans = async_transaction_create(callid);
     380        if (trans == NULL) {
     381                ipc_answer_0(callid, ENOMEM);
     382                return;
     383        }
    337384        trans->buffer = malloc(len);
    338385        trans->size = len;
     
    343390        if (rc != EOK) {
    344391                ipc_answer_0(callid, rc);
    345                 free(trans->buffer);
    346                 free(trans);
     392                async_transaction_destroy(trans);
    347393        }
    348394}
     
    388434        };
    389435
    390         async_transaction_t *trans = malloc(sizeof(async_transaction_t));
    391         trans->caller = callid;
    392         trans->buffer = NULL;
    393         trans->size = 0;
     436        async_transaction_t *trans = async_transaction_create(callid);
     437        if (trans == NULL) {
     438                ipc_answer_0(callid, ENOMEM);
     439                return;
     440        }
    394441
    395442        int rc;
     
    410457        if (rc != EOK) {
    411458                ipc_answer_0(callid, rc);
    412                 free(trans);
    413         }
    414         return;
     459                async_transaction_destroy(trans);
     460        }
    415461}
    416462
     
    496542}
    497543
     544void remote_usbhc_control_write(device_t *device, void *iface,
     545ipc_callid_t callid, ipc_call_t *call)
     546{
     547        usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
     548        assert(usb_iface != NULL);
     549
     550        if (!usb_iface->control_write) {
     551                ipc_answer_0(callid, ENOTSUP);
     552                return;
     553        }
     554
     555        usb_target_t target = {
     556                .address = DEV_IPC_GET_ARG1(*call),
     557                .endpoint = DEV_IPC_GET_ARG2(*call)
     558        };
     559
     560        int rc;
     561
     562        void *setup_packet = NULL;
     563        void *data_buffer = NULL;
     564        size_t setup_packet_len = 0;
     565        size_t data_buffer_len = 0;
     566
     567        rc = async_data_write_accept(&setup_packet, false,
     568            1, USB_MAX_PAYLOAD_SIZE, 0, &setup_packet_len);
     569        if (rc != EOK) {
     570                ipc_answer_0(callid, rc);
     571                return;
     572        }
     573        rc = async_data_write_accept(&data_buffer, false,
     574            1, USB_MAX_PAYLOAD_SIZE, 0, &data_buffer_len);
     575        if (rc != EOK) {
     576                ipc_answer_0(callid, rc);
     577                free(setup_packet);
     578                return;
     579        }
     580
     581        async_transaction_t *trans = async_transaction_create(callid);
     582        if (trans == NULL) {
     583                ipc_answer_0(callid, ENOMEM);
     584                free(setup_packet);
     585                free(data_buffer);
     586                return;
     587        }
     588        trans->setup_packet = setup_packet;
     589        trans->buffer = data_buffer;
     590        trans->size = data_buffer_len;
     591
     592        rc = usb_iface->control_write(device, target,
     593            setup_packet, setup_packet_len,
     594            data_buffer, data_buffer_len,
     595            callback_out, trans);
     596
     597        if (rc != EOK) {
     598                ipc_answer_0(callid, rc);
     599                async_transaction_destroy(trans);
     600        }
     601}
     602
     603
     604void remote_usbhc_control_read(device_t *device, void *iface,
     605ipc_callid_t callid, ipc_call_t *call)
     606{
     607        usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
     608        assert(usb_iface != NULL);
     609
     610        if (!usb_iface->control_read) {
     611                ipc_answer_0(callid, ENOTSUP);
     612                return;
     613        }
     614
     615        size_t data_len = DEV_IPC_GET_ARG3(*call);
     616        usb_target_t target = {
     617                .address = DEV_IPC_GET_ARG1(*call),
     618                .endpoint = DEV_IPC_GET_ARG2(*call)
     619        };
     620
     621        int rc;
     622
     623        void *setup_packet = NULL;
     624        size_t setup_packet_len = 0;
     625
     626        rc = async_data_write_accept(&setup_packet, false,
     627            1, USB_MAX_PAYLOAD_SIZE, 0, &setup_packet_len);
     628        if (rc != EOK) {
     629                ipc_answer_0(callid, rc);
     630                return;
     631        }
     632
     633        async_transaction_t *trans = async_transaction_create(callid);
     634        if (trans == NULL) {
     635                ipc_answer_0(callid, ENOMEM);
     636                free(setup_packet);
     637                return;
     638        }
     639        trans->setup_packet = setup_packet;
     640        trans->size = data_len;
     641        trans->buffer = malloc(data_len);
     642        if (trans->buffer == NULL) {
     643                ipc_answer_0(callid, ENOMEM);
     644                async_transaction_destroy(trans);
     645                return;
     646        }
     647
     648        rc = usb_iface->control_read(device, target,
     649            setup_packet, setup_packet_len,
     650            trans->buffer, trans->size,
     651            callback_in, trans);
     652
     653        if (rc != EOK) {
     654                ipc_answer_0(callid, rc);
     655                async_transaction_destroy(trans);
     656        }
     657}
     658
    498659
    499660
Note: See TracChangeset for help on using the changeset viewer.