Ignore:
Timestamp:
2011-09-16T14:50:20Z (13 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
432a269, d1e18573
Parents:
47fecbb (diff), 82a31261 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge USB changes from bzr://krabicka.net/orome/helenos/usb/

  • Move common HC code from uhci/ohci drivers to libusbhost
  • Rewrite USB HC interface to have common read/write functions for all transfer types.
  • Restructure hc drivers to avoid some hooks and void* casts
  • Cleanup the code and remove unnecessary mallocs.
File:
1 edited

Legend:

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

    r47fecbb rfd07e526  
    4141
    4242#define USB_MAX_PAYLOAD_SIZE 1020
    43 #define HACK_MAX_PACKET_SIZE 8
    44 #define HACK_MAX_PACKET_SIZE_INTERRUPT_IN 4
    45 
    46 static void remote_usbhc_interrupt_out(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    47 static void remote_usbhc_interrupt_in(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    48 static void remote_usbhc_bulk_out(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    49 static void remote_usbhc_bulk_in(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    50 static void remote_usbhc_control_write(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    51 static void remote_usbhc_control_read(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     43
    5244static void remote_usbhc_request_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    5345static void remote_usbhc_bind_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     
    5648static void remote_usbhc_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    5749static void remote_usbhc_unregister_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     50static void remote_usbhc_read(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     51static void remote_usbhc_write(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    5852//static void remote_usbhc(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    5953
    6054/** Remote USB host controller interface operations. */
    61 static 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
     55static 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,
    7866};
    7967
     
    9078        ipc_callid_t data_caller;
    9179        void *buffer;
    92         void *setup_packet;
    9380        size_t size;
    9481} async_transaction_t;
     
    9885        if (trans == NULL) {
    9986                return;
    100         }
    101 
    102         if (trans->setup_packet != NULL) {
    103                 free(trans->setup_packet);
    10487        }
    10588        if (trans->buffer != NULL) {
     
    120103        trans->data_caller = 0;
    121104        trans->buffer = NULL;
    122         trans->setup_packet = NULL;
    123105        trans->size = 0;
    124106
     
    135117                return;
    136118        }
    137        
     119
    138120        usb_speed_t speed = DEV_IPC_GET_ARG1(*call);
    139121
     
    239221        async_transaction_destroy(trans);
    240222}
    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  */
    249 static 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  */
    304 static 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 
    346 void 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 
    356 void 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 
    366 void 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 
    376 void 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 
    386 void remote_usbhc_control_write(ddf_fun_t *fun, void *iface,
    387 ipc_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 
    449 void remote_usbhc_control_read(ddf_fun_t *fun, void *iface,
    450 ipc_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 
    515223
    516224void remote_usbhc_register_endpoint(ddf_fun_t *fun, void *iface,
     
    535243        type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % (1 << 8)
    536244
    537         _INIT_FROM_HIGH_DATA2(usb_address_t, address, 1);
    538         _INIT_FROM_LOW_DATA2(usb_endpoint_t, endpoint, 1);
     245        const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) };
    539246
    540247        _INIT_FROM_HIGH_DATA3(usb_speed_t, speed, 2);
     
    551258#undef _INIT_FROM_LOW_DATA3
    552259
    553         int rc = usb_iface->register_endpoint(fun, address, speed, endpoint,
    554             transfer_type, direction, max_packet_size, interval);
     260        int rc = usb_iface->register_endpoint(fun, target.address, speed,
     261            target.endpoint, transfer_type, direction, max_packet_size, interval);
    555262
    556263        async_answer_0(callid, rc);
    557264}
    558 
    559265
    560266void remote_usbhc_unregister_endpoint(ddf_fun_t *fun, void *iface,
     
    578284}
    579285
     286void 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
     333void 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
    580380
    581381/**
Note: See TracChangeset for help on using the changeset viewer.