Ignore:
File:
1 edited

Legend:

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

    rbbce2c2 reb2f7dd  
    4141
    4242#define USB_MAX_PAYLOAD_SIZE 1020
    43 
     43#define HACK_MAX_PACKET_SIZE 8
     44#define HACK_MAX_PACKET_SIZE_INTERRUPT_IN 4
     45
     46static void remote_usbhc_interrupt_out(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     47static void remote_usbhc_interrupt_in(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     48static void remote_usbhc_bulk_out(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     49static void remote_usbhc_bulk_in(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     50static void remote_usbhc_control_write(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     51static void remote_usbhc_control_read(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    4452static void remote_usbhc_request_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    4553static void remote_usbhc_bind_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     
    4856static void remote_usbhc_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    4957static void remote_usbhc_unregister_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    50 static void remote_usbhc_read(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    51 static void remote_usbhc_write(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    5258//static void remote_usbhc(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    5359
    5460/** Remote USB host controller interface operations. */
    55 static remote_iface_func_ptr_t remote_usbhc_iface_ops[] = {
    56         [IPC_M_USBHC_REQUEST_ADDRESS] = remote_usbhc_request_address,
    57         [IPC_M_USBHC_BIND_ADDRESS] = remote_usbhc_bind_address,
    58         [IPC_M_USBHC_GET_HANDLE_BY_ADDRESS] = remote_usbhc_find_by_address,
    59         [IPC_M_USBHC_RELEASE_ADDRESS] = remote_usbhc_release_address,
    60 
    61         [IPC_M_USBHC_REGISTER_ENDPOINT] = remote_usbhc_register_endpoint,
    62         [IPC_M_USBHC_UNREGISTER_ENDPOINT] = remote_usbhc_unregister_endpoint,
    63 
    64         [IPC_M_USBHC_READ] = remote_usbhc_read,
    65         [IPC_M_USBHC_WRITE] = remote_usbhc_write,
     61static remote_iface_func_ptr_t remote_usbhc_iface_ops [] = {
     62        remote_usbhc_request_address,
     63        remote_usbhc_bind_address,
     64        remote_usbhc_find_by_address,
     65        remote_usbhc_release_address,
     66
     67        remote_usbhc_interrupt_out,
     68        remote_usbhc_interrupt_in,
     69
     70        remote_usbhc_bulk_out,
     71        remote_usbhc_bulk_in,
     72
     73        remote_usbhc_control_write,
     74        remote_usbhc_control_read,
     75
     76        remote_usbhc_register_endpoint,
     77        remote_usbhc_unregister_endpoint
    6678};
    6779
     
    7890        ipc_callid_t data_caller;
    7991        void *buffer;
     92        void *setup_packet;
    8093        size_t size;
    8194} async_transaction_t;
     
    8598        if (trans == NULL) {
    8699                return;
     100        }
     101
     102        if (trans->setup_packet != NULL) {
     103                free(trans->setup_packet);
    87104        }
    88105        if (trans->buffer != NULL) {
     
    103120        trans->data_caller = 0;
    104121        trans->buffer = NULL;
     122        trans->setup_packet = NULL;
    105123        trans->size = 0;
    106124
     
    117135                return;
    118136        }
    119 
     137       
    120138        usb_speed_t speed = DEV_IPC_GET_ARG1(*call);
    121139
     
    221239        async_transaction_destroy(trans);
    222240}
     241
     242/** Process an outgoing transfer (both OUT and SETUP).
     243 *
     244 * @param device Target device.
     245 * @param callid Initiating caller.
     246 * @param call Initiating call.
     247 * @param transfer_func Transfer function (might be NULL).
     248 */
     249static void remote_usbhc_out_transfer(ddf_fun_t *fun,
     250    ipc_callid_t callid, ipc_call_t *call,
     251    usbhc_iface_transfer_out_t transfer_func)
     252{
     253        if (!transfer_func) {
     254                async_answer_0(callid, ENOTSUP);
     255                return;
     256        }
     257
     258        usb_target_t target = {
     259                .address = DEV_IPC_GET_ARG1(*call),
     260                .endpoint = DEV_IPC_GET_ARG2(*call)
     261        };
     262
     263        size_t len = 0;
     264        void *buffer = NULL;
     265
     266        int rc = async_data_write_accept(&buffer, false,
     267            1, USB_MAX_PAYLOAD_SIZE,
     268            0, &len);
     269
     270        if (rc != EOK) {
     271                async_answer_0(callid, rc);
     272                return;
     273        }
     274
     275        async_transaction_t *trans = async_transaction_create(callid);
     276        if (trans == NULL) {
     277                if (buffer != NULL) {
     278                        free(buffer);
     279                }
     280                async_answer_0(callid, ENOMEM);
     281                return;
     282        }
     283
     284        trans->buffer = buffer;
     285        trans->size = len;
     286
     287        rc = transfer_func(fun, target,
     288            buffer, len,
     289            callback_out, trans);
     290
     291        if (rc != EOK) {
     292                async_answer_0(callid, rc);
     293                async_transaction_destroy(trans);
     294        }
     295}
     296
     297/** Process an incoming transfer.
     298 *
     299 * @param device Target device.
     300 * @param callid Initiating caller.
     301 * @param call Initiating call.
     302 * @param transfer_func Transfer function (might be NULL).
     303 */
     304static void remote_usbhc_in_transfer(ddf_fun_t *fun,
     305    ipc_callid_t callid, ipc_call_t *call,
     306    usbhc_iface_transfer_in_t transfer_func)
     307{
     308        if (!transfer_func) {
     309                async_answer_0(callid, ENOTSUP);
     310                return;
     311        }
     312
     313        usb_target_t target = {
     314                .address = DEV_IPC_GET_ARG1(*call),
     315                .endpoint = DEV_IPC_GET_ARG2(*call)
     316        };
     317
     318        size_t len;
     319        ipc_callid_t data_callid;
     320        if (!async_data_read_receive(&data_callid, &len)) {
     321                async_answer_0(callid, EPARTY);
     322                return;
     323        }
     324
     325        async_transaction_t *trans = async_transaction_create(callid);
     326        if (trans == NULL) {
     327                async_answer_0(data_callid, ENOMEM);
     328                async_answer_0(callid, ENOMEM);
     329                return;
     330        }
     331        trans->data_caller = data_callid;
     332        trans->buffer = malloc(len);
     333        trans->size = len;
     334
     335        int rc = transfer_func(fun, target,
     336            trans->buffer, len,
     337            callback_in, trans);
     338
     339        if (rc != EOK) {
     340                async_answer_0(data_callid, rc);
     341                async_answer_0(callid, rc);
     342                async_transaction_destroy(trans);
     343        }
     344}
     345
     346void remote_usbhc_interrupt_out(ddf_fun_t *fun, void *iface,
     347    ipc_callid_t callid, ipc_call_t *call)
     348{
     349        usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
     350        assert(usb_iface != NULL);
     351
     352        return remote_usbhc_out_transfer(fun, callid, call,
     353            usb_iface->interrupt_out);
     354}
     355
     356void remote_usbhc_interrupt_in(ddf_fun_t *fun, void *iface,
     357    ipc_callid_t callid, ipc_call_t *call)
     358{
     359        usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
     360        assert(usb_iface != NULL);
     361
     362        return remote_usbhc_in_transfer(fun, callid, call,
     363            usb_iface->interrupt_in);
     364}
     365
     366void remote_usbhc_bulk_out(ddf_fun_t *fun, void *iface,
     367    ipc_callid_t callid, ipc_call_t *call)
     368{
     369        usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
     370        assert(usb_iface != NULL);
     371
     372        return remote_usbhc_out_transfer(fun, callid, call,
     373            usb_iface->bulk_out);
     374}
     375
     376void remote_usbhc_bulk_in(ddf_fun_t *fun, void *iface,
     377    ipc_callid_t callid, ipc_call_t *call)
     378{
     379        usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
     380        assert(usb_iface != NULL);
     381
     382        return remote_usbhc_in_transfer(fun, callid, call,
     383            usb_iface->bulk_in);
     384}
     385
     386void remote_usbhc_control_write(ddf_fun_t *fun, void *iface,
     387ipc_callid_t callid, ipc_call_t *call)
     388{
     389        usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
     390        assert(usb_iface != NULL);
     391
     392        if (!usb_iface->control_write) {
     393                async_answer_0(callid, ENOTSUP);
     394                return;
     395        }
     396
     397        usb_target_t target = {
     398                .address = DEV_IPC_GET_ARG1(*call),
     399                .endpoint = DEV_IPC_GET_ARG2(*call)
     400        };
     401        size_t data_buffer_len = DEV_IPC_GET_ARG3(*call);
     402
     403        int rc;
     404
     405        void *setup_packet = NULL;
     406        void *data_buffer = NULL;
     407        size_t setup_packet_len = 0;
     408
     409        rc = async_data_write_accept(&setup_packet, false,
     410            1, USB_MAX_PAYLOAD_SIZE, 0, &setup_packet_len);
     411        if (rc != EOK) {
     412                async_answer_0(callid, rc);
     413                return;
     414        }
     415
     416        if (data_buffer_len > 0) {
     417                rc = async_data_write_accept(&data_buffer, false,
     418                    1, USB_MAX_PAYLOAD_SIZE, 0, &data_buffer_len);
     419                if (rc != EOK) {
     420                        async_answer_0(callid, rc);
     421                        free(setup_packet);
     422                        return;
     423                }
     424        }
     425
     426        async_transaction_t *trans = async_transaction_create(callid);
     427        if (trans == NULL) {
     428                async_answer_0(callid, ENOMEM);
     429                free(setup_packet);
     430                free(data_buffer);
     431                return;
     432        }
     433        trans->setup_packet = setup_packet;
     434        trans->buffer = data_buffer;
     435        trans->size = data_buffer_len;
     436
     437        rc = usb_iface->control_write(fun, target,
     438            setup_packet, setup_packet_len,
     439            data_buffer, data_buffer_len,
     440            callback_out, trans);
     441
     442        if (rc != EOK) {
     443                async_answer_0(callid, rc);
     444                async_transaction_destroy(trans);
     445        }
     446}
     447
     448
     449void remote_usbhc_control_read(ddf_fun_t *fun, void *iface,
     450ipc_callid_t callid, ipc_call_t *call)
     451{
     452        usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
     453        assert(usb_iface != NULL);
     454
     455        if (!usb_iface->control_read) {
     456                async_answer_0(callid, ENOTSUP);
     457                return;
     458        }
     459
     460        usb_target_t target = {
     461                .address = DEV_IPC_GET_ARG1(*call),
     462                .endpoint = DEV_IPC_GET_ARG2(*call)
     463        };
     464
     465        int rc;
     466
     467        void *setup_packet = NULL;
     468        size_t setup_packet_len = 0;
     469        size_t data_len = 0;
     470
     471        rc = async_data_write_accept(&setup_packet, false,
     472            1, USB_MAX_PAYLOAD_SIZE, 0, &setup_packet_len);
     473        if (rc != EOK) {
     474                async_answer_0(callid, rc);
     475                return;
     476        }
     477
     478        ipc_callid_t data_callid;
     479        if (!async_data_read_receive(&data_callid, &data_len)) {
     480                async_answer_0(callid, EPARTY);
     481                free(setup_packet);
     482                return;
     483        }
     484
     485        async_transaction_t *trans = async_transaction_create(callid);
     486        if (trans == NULL) {
     487                async_answer_0(data_callid, ENOMEM);
     488                async_answer_0(callid, ENOMEM);
     489                free(setup_packet);
     490                return;
     491        }
     492        trans->data_caller = data_callid;
     493        trans->setup_packet = setup_packet;
     494        trans->size = data_len;
     495        trans->buffer = malloc(data_len);
     496        if (trans->buffer == NULL) {
     497                async_answer_0(data_callid, ENOMEM);
     498                async_answer_0(callid, ENOMEM);
     499                async_transaction_destroy(trans);
     500                return;
     501        }
     502
     503        rc = usb_iface->control_read(fun, target,
     504            setup_packet, setup_packet_len,
     505            trans->buffer, trans->size,
     506            callback_in, trans);
     507
     508        if (rc != EOK) {
     509                async_answer_0(data_callid, rc);
     510                async_answer_0(callid, rc);
     511                async_transaction_destroy(trans);
     512        }
     513}
     514
    223515
    224516void remote_usbhc_register_endpoint(ddf_fun_t *fun, void *iface,
     
    243535        type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % (1 << 8)
    244536
    245         const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) };
     537        _INIT_FROM_HIGH_DATA2(usb_address_t, address, 1);
     538        _INIT_FROM_LOW_DATA2(usb_endpoint_t, endpoint, 1);
    246539
    247540        _INIT_FROM_HIGH_DATA3(usb_speed_t, speed, 2);
     
    258551#undef _INIT_FROM_LOW_DATA3
    259552
    260         int rc = usb_iface->register_endpoint(fun, target.address, speed,
    261             target.endpoint, transfer_type, direction, max_packet_size, interval);
     553        int rc = usb_iface->register_endpoint(fun, address, speed, endpoint,
     554            transfer_type, direction, max_packet_size, interval);
    262555
    263556        async_answer_0(callid, rc);
    264557}
     558
    265559
    266560void remote_usbhc_unregister_endpoint(ddf_fun_t *fun, void *iface,
     
    284578}
    285579
    286 void remote_usbhc_read(
    287     ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
    288 {
    289         assert(fun);
    290         assert(iface);
    291         assert(call);
    292 
    293         const usbhc_iface_t *hc_iface = iface;
    294 
    295         if (!hc_iface->read) {
    296                 async_answer_0(callid, ENOTSUP);
    297                 return;
    298         }
    299 
    300         const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) };
    301         const uint64_t setup =
    302             ((uint64_t)DEV_IPC_GET_ARG2(*call)) |
    303             (((uint64_t)DEV_IPC_GET_ARG3(*call)) << 32);
    304 
    305         async_transaction_t *trans = async_transaction_create(callid);
    306         if (trans == NULL) {
    307                 async_answer_0(callid, ENOMEM);
    308                 return;
    309         }
    310 
    311         if (!async_data_read_receive(&trans->data_caller, &trans->size)) {
    312                 async_answer_0(callid, EPARTY);
    313                 return;
    314         }
    315 
    316         trans->buffer = malloc(trans->size);
    317         if (trans->buffer == NULL) {
    318                 async_answer_0(trans->data_caller, ENOMEM);
    319                 async_answer_0(callid, ENOMEM);
    320                 async_transaction_destroy(trans);
    321         }
    322 
    323         const int rc = hc_iface->read(
    324             fun, target, setup, trans->buffer, trans->size, callback_in, trans);
    325 
    326         if (rc != EOK) {
    327                 async_answer_0(trans->data_caller, rc);
    328                 async_answer_0(callid, rc);
    329                 async_transaction_destroy(trans);
    330         }
    331 }
    332 
    333 void remote_usbhc_write(
    334     ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
    335 {
    336         assert(fun);
    337         assert(iface);
    338         assert(call);
    339 
    340         const usbhc_iface_t *hc_iface = iface;
    341 
    342         if (!hc_iface->write) {
    343                 async_answer_0(callid, ENOTSUP);
    344                 return;
    345         }
    346 
    347         const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) };
    348         const size_t data_buffer_len = DEV_IPC_GET_ARG2(*call);
    349         const uint64_t setup =
    350             ((uint64_t)DEV_IPC_GET_ARG3(*call)) |
    351             (((uint64_t)DEV_IPC_GET_ARG4(*call)) << 32);
    352 
    353         async_transaction_t *trans = async_transaction_create(callid);
    354         if (trans == NULL) {
    355                 async_answer_0(callid, ENOMEM);
    356                 return;
    357         }
    358 
    359         if (data_buffer_len > 0) {
    360                 int rc = async_data_write_accept(&trans->buffer, false,
    361                     1, USB_MAX_PAYLOAD_SIZE,
    362                     0, &trans->size);
    363 
    364                 if (rc != EOK) {
    365                         async_answer_0(callid, rc);
    366                         async_transaction_destroy(trans);
    367                         return;
    368                 }
    369         }
    370 
    371         int rc = hc_iface->write(
    372             fun, target, setup, trans->buffer, trans->size, callback_out, trans);
    373 
    374         if (rc != EOK) {
    375                 async_answer_0(callid, rc);
    376                 async_transaction_destroy(trans);
    377         }
    378 }
    379 
    380580
    381581/**
Note: See TracChangeset for help on using the changeset viewer.