Changeset fd07e526 in mainline for uspace/lib


Ignore:
Timestamp:
2011-09-16T14:50:20Z (15 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.
Location:
uspace/lib
Files:
3 added
1 deleted
13 edited
3 moved

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/as.c

    r47fecbb rfd07e526  
    123123 * @retval ENOENT Mapping not found.
    124124 */
    125 int as_get_physical_mapping(void *address, uintptr_t *frame)
     125int as_get_physical_mapping(const void *address, uintptr_t *frame)
    126126{
    127127        uintptr_t tmp_frame;
  • uspace/lib/c/include/as.h

    r47fecbb rfd07e526  
    6060extern void *set_maxheapsize(size_t);
    6161extern void *as_get_mappable_page(size_t);
    62 extern int as_get_physical_mapping(void *, uintptr_t *);
     62extern int as_get_physical_mapping(const void *, uintptr_t *);
    6363
    6464#endif
  • 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/**
  • uspace/lib/drv/include/usbhc_iface.h

    r47fecbb rfd07e526  
    123123        IPC_M_USBHC_RELEASE_ADDRESS,
    124124
    125 
    126         /** Send interrupt data to device.
    127          * See explanation at usb_iface_funcs_t (OUT transaction).
    128          */
    129         IPC_M_USBHC_INTERRUPT_OUT,
    130 
    131         /** Get interrupt data from device.
    132          * See explanation at usb_iface_funcs_t (IN transaction).
    133          */
    134         IPC_M_USBHC_INTERRUPT_IN,
    135 
    136         /** Send bulk data to device.
    137          * See explanation at usb_iface_funcs_t (OUT transaction).
    138          */
    139         IPC_M_USBHC_BULK_OUT,
    140 
    141         /** Get bulk data from device.
    142          * See explanation at usb_iface_funcs_t (IN transaction).
    143          */
    144         IPC_M_USBHC_BULK_IN,
    145 
    146         /** Issue control WRITE transfer.
    147          * See explanation at usb_iface_funcs_t (OUT transaction) for
    148          * call parameters.
    149          * This call is immediately followed by two IPC data writes
    150          * from the caller (setup packet and actual data).
    151          */
    152         IPC_M_USBHC_CONTROL_WRITE,
    153 
    154         /** Issue control READ transfer.
    155          * See explanation at usb_iface_funcs_t (IN transaction) for
    156          * call parameters.
    157          * This call is immediately followed by IPC data write from the caller
    158          * (setup packet) and IPC data read (buffer that was read).
    159          */
    160         IPC_M_USBHC_CONTROL_READ,
    161 
    162125        /** Register endpoint attributes at host controller.
    163126         * This is used to reserve portion of USB bandwidth.
     
    185148         * - ENOENT - unknown endpoint
    186149         */
    187         IPC_M_USBHC_UNREGISTER_ENDPOINT
     150        IPC_M_USBHC_UNREGISTER_ENDPOINT,
     151
     152        /** Get data from device.
     153         * See explanation at usb_iface_funcs_t (IN transaction).
     154         */
     155        IPC_M_USBHC_READ,
     156
     157        /** Send data to device.
     158         * See explanation at usb_iface_funcs_t (OUT transaction).
     159         */
     160        IPC_M_USBHC_WRITE,
    188161} usbhc_iface_funcs_t;
    189162
    190163/** Callback for outgoing transfer. */
    191 typedef void (*usbhc_iface_transfer_out_callback_t)(ddf_fun_t *,
    192     int, void *);
     164typedef void (*usbhc_iface_transfer_out_callback_t)(ddf_fun_t *, int, void *);
    193165
    194166/** Callback for incoming transfer. */
    195167typedef void (*usbhc_iface_transfer_in_callback_t)(ddf_fun_t *,
    196168    int, size_t, void *);
    197 
    198 
    199 /** Out transfer processing function prototype. */
    200 typedef int (*usbhc_iface_transfer_out_t)(ddf_fun_t *, usb_target_t,
    201     void *, size_t,
    202     usbhc_iface_transfer_out_callback_t, void *);
    203 
    204 /** Setup transfer processing function prototype. @deprecated */
    205 typedef usbhc_iface_transfer_out_t usbhc_iface_transfer_setup_t;
    206 
    207 /** In transfer processing function prototype. */
    208 typedef int (*usbhc_iface_transfer_in_t)(ddf_fun_t *, usb_target_t,
    209     void *, size_t,
    210     usbhc_iface_transfer_in_callback_t, void *);
    211169
    212170/** USB host controller communication interface. */
     
    223181            usb_direction_t);
    224182
    225         usbhc_iface_transfer_out_t interrupt_out;
    226         usbhc_iface_transfer_in_t interrupt_in;
     183        int (*read)(ddf_fun_t *, usb_target_t, uint64_t, uint8_t *, size_t,
     184            usbhc_iface_transfer_in_callback_t, void *);
    227185
    228         usbhc_iface_transfer_out_t bulk_out;
    229         usbhc_iface_transfer_in_t bulk_in;
    230 
    231         int (*control_write)(ddf_fun_t *, usb_target_t,
    232             void *, size_t, void *, size_t,
    233             usbhc_iface_transfer_out_callback_t, void *);
    234 
    235         int (*control_read)(ddf_fun_t *, usb_target_t,
    236             void *, size_t, void *, size_t,
    237             usbhc_iface_transfer_in_callback_t, void *);
     186        int (*write)(ddf_fun_t *, usb_target_t, uint64_t, const uint8_t *,
     187            size_t, usbhc_iface_transfer_out_callback_t, void *);
    238188} usbhc_iface_t;
    239189
  • uspace/lib/usb/include/usb/hc.h

    r47fecbb rfd07e526  
    6262    devman_handle_t *);
    6363
    64 int usb_hc_get_address_by_handle(devman_handle_t);
     64usb_address_t usb_hc_get_address_by_handle(devman_handle_t);
    6565
    6666int usb_hc_find(devman_handle_t, devman_handle_t *);
  • uspace/lib/usb/include/usb/usb.h

    r47fecbb rfd07e526  
    3636#define LIBUSB_USB_H_
    3737
     38#include <bool.h>
    3839#include <sys/types.h>
    3940#include <byteorder.h>
     
    105106 * Negative values could be used to indicate error.
    106107 */
    107 typedef int usb_address_t;
     108typedef int16_t usb_address_t;
    108109
    109110/** Default USB address. */
     
    115116 * Negative values could be used to indicate error.
    116117 */
    117 typedef int usb_endpoint_t;
     118typedef int16_t usb_endpoint_t;
    118119
    119120/** Maximum endpoint number in USB 1.1.
     
    125126 * Pair address + endpoint is identification of transaction recipient.
    126127 */
    127 typedef struct {
    128         usb_address_t address;
    129         usb_endpoint_t endpoint;
     128typedef union {
     129        struct {
     130                usb_address_t address;
     131                usb_endpoint_t endpoint;
     132        } __attribute__((packed));
     133        uint32_t packed;
    130134} usb_target_t;
     135
     136/** Check USB target for allowed values (address and endpoint).
     137 *
     138 * @param target.
     139 * @return True, if values are wihtin limits, false otherwise.
     140 */
     141static inline bool usb_target_is_valid(usb_target_t target)
     142{
     143        return !(target.endpoint > 15 || target.endpoint < 0
     144            || target.address >= USB11_ADDRESS_MAX || target.address < 0);
     145}
    131146
    132147/** Compare USB targets (addresses and endpoints).
  • uspace/lib/usbdev/src/pipesinit.c

    r47fecbb rfd07e526  
    486486                return EBADF;
    487487       
     488        const usb_target_t target =
     489            {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }};
    488490#define _PACK2(high, low) (((high) << 16) + (low))
    489491#define _PACK3(high, middle, low) (((((high) << 8) + (middle)) << 8) + (low))
     
    491493        async_exch_t *exch = async_exchange_begin(hc_connection->hc_sess);
    492494        int rc = async_req_4_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    493             IPC_M_USBHC_REGISTER_ENDPOINT,
    494             _PACK2(pipe->wire->address, pipe->endpoint_no),
     495            IPC_M_USBHC_REGISTER_ENDPOINT, target.packed,
    495496            _PACK3(speed, pipe->transfer_type, pipe->direction),
    496497            _PACK2(pipe->max_packet_size, interval));
  • uspace/lib/usbdev/src/pipesio.c

    r47fecbb rfd07e526  
    6565    void *buffer, size_t size, size_t *size_transfered)
    6666{
    67         /*
    68          * Get corresponding IPC method.
    69          * In future, replace with static array of mappings
    70          * transfer type -> method.
    71          */
    72         usbhc_iface_funcs_t ipc_method;
    73         switch (pipe->transfer_type) {
    74                 case USB_TRANSFER_INTERRUPT:
    75                         ipc_method = IPC_M_USBHC_INTERRUPT_IN;
    76                         break;
    77                 case USB_TRANSFER_BULK:
    78                         ipc_method = IPC_M_USBHC_BULK_IN;
    79                         break;
    80                 default:
    81                         return ENOTSUP;
    82         }
     67        /* Only interrupt and bulk transfers are supported */
     68        if (pipe->transfer_type != USB_TRANSFER_INTERRUPT &&
     69            pipe->transfer_type != USB_TRANSFER_BULK)
     70            return ENOTSUP;
     71
     72        const usb_target_t target =
     73            {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }};
    8374       
    8475        /* Ensure serialization over the phone. */
     
    8980         * Make call identifying target USB device and type of transfer.
    9081         */
    91         aid_t opening_request = async_send_3(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    92             ipc_method, pipe->wire->address, pipe->endpoint_no, NULL);
     82        aid_t opening_request = async_send_2(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
     83            IPC_M_USBHC_READ, target.packed, NULL);
    9384       
    9485        if (opening_request == 0) {
     
    213204    void *buffer, size_t size)
    214205{
    215         /*
    216          * Get corresponding IPC method.
    217          * In future, replace with static array of mappings
    218          * transfer type -> method.
    219          */
    220         usbhc_iface_funcs_t ipc_method;
    221         switch (pipe->transfer_type) {
    222                 case USB_TRANSFER_INTERRUPT:
    223                         ipc_method = IPC_M_USBHC_INTERRUPT_OUT;
    224                         break;
    225                 case USB_TRANSFER_BULK:
    226                         ipc_method = IPC_M_USBHC_BULK_OUT;
    227                         break;
    228                 default:
    229                         return ENOTSUP;
    230         }
     206        /* Only interrupt and bulk transfers are supported */
     207        if (pipe->transfer_type != USB_TRANSFER_INTERRUPT &&
     208            pipe->transfer_type != USB_TRANSFER_BULK)
     209            return ENOTSUP;
     210
     211        const usb_target_t target =
     212            {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }};
    231213
    232214        /* Ensure serialization over the phone. */
     
    238220         */
    239221        aid_t opening_request = async_send_3(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    240             ipc_method, pipe->wire->address, pipe->endpoint_no, NULL);
     222            IPC_M_USBHC_WRITE, target.packed, size, NULL);
    241223       
    242224        if (opening_request == 0) {
     
    352334        pipe_start_transaction(pipe);
    353335
     336        const usb_target_t target =
     337            {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }};
     338
     339        assert(setup_buffer_size == 8);
     340        uint64_t setup_packet;
     341        memcpy(&setup_packet, setup_buffer, 8);
    354342        /*
    355343         * Make call identifying target USB device and control transfer type.
    356344         */
    357345        async_exch_t *exch = async_exchange_begin(pipe->hc_sess);
    358         aid_t opening_request = async_send_3(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    359             IPC_M_USBHC_CONTROL_READ, pipe->wire->address, pipe->endpoint_no,
    360             NULL);
    361        
     346        aid_t opening_request = async_send_4(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
     347            IPC_M_USBHC_READ, target.packed,
     348            (setup_packet & UINT32_MAX), (setup_packet >> 32), NULL);
     349
    362350        if (opening_request == 0) {
    363351                async_exchange_end(exch);
    364352                return ENOMEM;
    365353        }
    366        
    367         /*
    368          * Send the setup packet.
    369          */
    370         int rc = async_data_write_start(exch, setup_buffer, setup_buffer_size);
    371         if (rc != EOK) {
    372                 async_exchange_end(exch);
    373                 pipe_end_transaction(pipe);
    374                 async_wait_for(opening_request, NULL);
    375                 return rc;
    376         }
    377        
     354
    378355        /*
    379356         * Retrieve the data.
     
    498475        pipe_start_transaction(pipe);
    499476
     477        const usb_target_t target =
     478            {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }};
     479        assert(setup_buffer_size == 8);
     480        uint64_t setup_packet;
     481        memcpy(&setup_packet, setup_buffer, 8);
     482
    500483        /*
    501484         * Make call identifying target USB device and control transfer type.
    502485         */
    503486        async_exch_t *exch = async_exchange_begin(pipe->hc_sess);
    504         aid_t opening_request = async_send_4(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    505             IPC_M_USBHC_CONTROL_WRITE, pipe->wire->address, pipe->endpoint_no,
    506             data_buffer_size, NULL);
     487        aid_t opening_request = async_send_5(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
     488            IPC_M_USBHC_WRITE, target.packed, data_buffer_size,
     489            (setup_packet & UINT32_MAX), (setup_packet >> 32), NULL);
    507490       
    508491        if (opening_request == 0) {
     
    511494                return ENOMEM;
    512495        }
    513        
    514         /*
    515          * Send the setup packet.
    516          */
    517         int rc = async_data_write_start(exch, setup_buffer, setup_buffer_size);
    518         if (rc != EOK) {
    519                 async_exchange_end(exch);
    520                 pipe_end_transaction(pipe);
    521                 async_wait_for(opening_request, NULL);
    522                 return rc;
    523         }
    524        
     496
    525497        /*
    526498         * Send the data (if any).
    527499         */
    528500        if (data_buffer_size > 0) {
    529                 rc = async_data_write_start(exch, data_buffer, data_buffer_size);
     501                int rc = async_data_write_start(exch, data_buffer, data_buffer_size);
    530502               
    531503                /* All data sent, pipe can be released. */
  • uspace/lib/usbhost/Makefile

    r47fecbb rfd07e526  
    3232        -I$(LIBUSB_PREFIX)/include \
    3333        -I$(LIBDRV_PREFIX)/include \
    34         -Iinclude
     34        -Iinclude 
    3535
    3636SOURCES = \
    37         src/batch.c \
    38         src/device_keeper.c \
    3937        src/endpoint.c \
    40         src/usb_endpoint_manager.c
     38        src/iface.c \
     39        src/usb_device_manager.c \
     40        src/usb_endpoint_manager.c \
     41        src/usb_transfer_batch.c
    4142
    4243include $(USPACE_PREFIX)/Makefile.common
  • uspace/lib/usbhost/include/usb/host/endpoint.h

    r47fecbb rfd07e526  
    5454        fibril_condvar_t avail;
    5555        volatile bool active;
     56        void (*destroy_hook)(struct endpoint *);
    5657        struct {
    5758                void *data;
     
    6869
    6970void endpoint_set_hc_data(endpoint_t *instance,
    70     void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int));
     71    void *data, void (*destroy_hook)(endpoint_t *),
     72    int (*toggle_get)(void *), void (*toggle_set)(void *, int));
    7173
    7274void endpoint_clear_hc_data(endpoint_t *instance);
  • uspace/lib/usbhost/include/usb/host/usb_device_manager.h

    r47fecbb rfd07e526  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 
    2928/** @addtogroup libusbhost
    3029 * @{
    3130 */
    3231/** @file
    33  * Device keeper structure and functions.
     32 * Device manager structure and functions.
    3433 *
    3534 * Typical USB host controller needs to keep track of various settings for
     
    3837 * This structure shall simplify the management.
    3938 */
    40 #ifndef LIBUSBHOST_HOST_DEVICE_KEEPER_H
    41 #define LIBUSBHOST_HOST_DEVICE_KEEPER_H
     39#ifndef LIBUSBHOST_HOST_USB_DEVICE_MANAGER_H
     40#define LIBUSBHOST_HOST_USB_DEVICE_MANAGER_H
    4241
    4342#include <adt/list.h>
     
    5756};
    5857
    59 /** Host controller device keeper.
     58/** Host controller device manager.
    6059 * You shall not access members directly but only using functions below.
    6160 */
     
    6463        fibril_mutex_t guard;
    6564        usb_address_t last_address;
    66 } usb_device_keeper_t;
     65} usb_device_manager_t;
    6766
    68 void usb_device_keeper_init(usb_device_keeper_t *instance);
     67void usb_device_manager_init(usb_device_manager_t *instance);
    6968
    70 usb_address_t device_keeper_get_free_address(usb_device_keeper_t *instance,
    71     usb_speed_t speed);
     69usb_address_t usb_device_manager_get_free_address(
     70    usb_device_manager_t *instance, usb_speed_t speed);
    7271
    73 void usb_device_keeper_bind(usb_device_keeper_t *instance,
     72void usb_device_manager_bind(usb_device_manager_t *instance,
    7473    usb_address_t address, devman_handle_t handle);
    7574
    76 void usb_device_keeper_release(usb_device_keeper_t *instance,
     75void usb_device_manager_release(usb_device_manager_t *instance,
    7776    usb_address_t address);
    7877
    79 usb_address_t usb_device_keeper_find(usb_device_keeper_t *instance,
     78usb_address_t usb_device_manager_find(usb_device_manager_t *instance,
    8079    devman_handle_t handle);
    8180
    82 bool usb_device_keeper_find_by_address(usb_device_keeper_t *instance,
     81bool usb_device_manager_find_by_address(usb_device_manager_t *instance,
    8382    usb_address_t address, devman_handle_t *handle);
    8483
    85 usb_speed_t usb_device_keeper_get_speed(usb_device_keeper_t *instance,
     84usb_speed_t usb_device_manager_get_speed(usb_device_manager_t *instance,
    8685    usb_address_t address);
    8786#endif
  • uspace/lib/usbhost/include/usb/host/usb_endpoint_manager.h

    r47fecbb rfd07e526  
    3838 */
    3939#ifndef LIBUSBHOST_HOST_USB_ENDPOINT_MANAGER_H
    40 #define LIBUSBHOST_HOST_YSB_ENDPOINT_MANAGER_H
     40#define LIBUSBHOST_HOST_USB_ENDPOINT_MANAGER_H
    4141
    4242#include <stdlib.h>
     
    5252        hash_table_t ep_table;
    5353        fibril_mutex_t guard;
    54         fibril_condvar_t change;
    5554        size_t free_bw;
     55        size_t (*bw_count)(usb_speed_t, usb_transfer_type_t, size_t, size_t);
    5656} usb_endpoint_manager_t;
    5757
     
    6060
    6161int usb_endpoint_manager_init(usb_endpoint_manager_t *instance,
    62     size_t available_bandwidth);
     62    size_t available_bandwidth,
     63    size_t (*bw_count)(usb_speed_t, usb_transfer_type_t, size_t, size_t));
    6364
    6465void usb_endpoint_manager_destroy(usb_endpoint_manager_t *instance);
     
    7778    usb_endpoint_manager_t *instance, usb_target_t target, const uint8_t *data);
    7879
     80/** Wrapper combining allocation and insertion */
    7981static inline int usb_endpoint_manager_add_ep(usb_endpoint_manager_t *instance,
    8082    usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction,
  • uspace/lib/usbhost/src/endpoint.c

    r47fecbb rfd07e526  
    5353                instance->toggle = 0;
    5454                instance->active = false;
     55                instance->destroy_hook = NULL;
     56                instance->hc_data.data = NULL;
     57                instance->hc_data.toggle_get = NULL;
     58                instance->hc_data.toggle_set = NULL;
    5559                fibril_mutex_initialize(&instance->guard);
    5660                fibril_condvar_initialize(&instance->avail);
     
    6468        assert(instance);
    6569        assert(!instance->active);
     70        if (instance->hc_data.data) {
     71                assert(instance->destroy_hook);
     72                instance->destroy_hook(instance);
     73        }
    6674        free(instance);
    6775}
    6876/*----------------------------------------------------------------------------*/
    6977void endpoint_set_hc_data(endpoint_t *instance,
    70     void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int))
     78    void *data, void (*destroy_hook)(endpoint_t *),
     79    int (*toggle_get)(void *), void (*toggle_set)(void *, int))
    7180{
    7281        assert(instance);
     82        instance->destroy_hook = destroy_hook;
    7383        instance->hc_data.data = data;
    7484        instance->hc_data.toggle_get = toggle_get;
     
    7989{
    8090        assert(instance);
     91        instance->destroy_hook = NULL;
    8192        instance->hc_data.data = NULL;
    8293        instance->hc_data.toggle_get = NULL;
  • uspace/lib/usbhost/src/usb_device_manager.c

    r47fecbb rfd07e526  
    3131 */
    3232/** @file
    33  * Device keeper structure and functions (implementation).
     33 * Device manager structure and functions (implementation).
    3434 */
    3535#include <assert.h>
    3636#include <errno.h>
    3737#include <usb/debug.h>
    38 #include <usb/host/device_keeper.h>
    39 
    40 /*----------------------------------------------------------------------------*/
    41 /** Initialize device keeper structure.
     38#include <usb/host/usb_device_manager.h>
     39
     40/*----------------------------------------------------------------------------*/
     41/** Initialize device manager structure.
    4242 *
    4343 * @param[in] instance Memory place to initialize.
     
    4545 * Set all values to false/0.
    4646 */
    47 void usb_device_keeper_init(usb_device_keeper_t *instance)
     47void usb_device_manager_init(usb_device_manager_t *instance)
    4848{
    4949        assert(instance);
     
    6363/** Get a free USB address
    6464 *
    65  * @param[in] instance Device keeper structure to use.
     65 * @param[in] instance Device manager structure to use.
    6666 * @param[in] speed Speed of the device requiring address.
    6767 * @return Free address, or error code.
    6868 */
    69 usb_address_t device_keeper_get_free_address(
    70     usb_device_keeper_t *instance, usb_speed_t speed)
     69usb_address_t usb_device_manager_get_free_address(
     70    usb_device_manager_t *instance, usb_speed_t speed)
    7171{
    7272        assert(instance);
     
    9797/** Bind USB address to devman handle.
    9898 *
    99  * @param[in] instance Device keeper structure to use.
     99 * @param[in] instance Device manager structure to use.
    100100 * @param[in] address Device address
    101101 * @param[in] handle Devman handle of the device.
    102102 */
    103 void usb_device_keeper_bind(usb_device_keeper_t *instance,
     103void usb_device_manager_bind(usb_device_manager_t *instance,
    104104    usb_address_t address, devman_handle_t handle)
    105105{
     
    117117/** Release used USB address.
    118118 *
    119  * @param[in] instance Device keeper structure to use.
     119 * @param[in] instance Device manager structure to use.
    120120 * @param[in] address Device address
    121121 */
    122 void usb_device_keeper_release(
    123     usb_device_keeper_t *instance, usb_address_t address)
     122void usb_device_manager_release(
     123    usb_device_manager_t *instance, usb_address_t address)
    124124{
    125125        assert(instance);
     
    136136/** Find USB address associated with the device
    137137 *
    138  * @param[in] instance Device keeper structure to use.
     138 * @param[in] instance Device manager structure to use.
    139139 * @param[in] handle Devman handle of the device seeking its address.
    140140 * @return USB Address, or error code.
    141141 */
    142 usb_address_t usb_device_keeper_find(
    143     usb_device_keeper_t *instance, devman_handle_t handle)
     142usb_address_t usb_device_manager_find(
     143    usb_device_manager_t *instance, devman_handle_t handle)
    144144{
    145145        assert(instance);
     
    161161 * Intentionally refuse to find handle of default address.
    162162 *
    163  * @param[in] instance Device keeper structure to use.
     163 * @param[in] instance Device manager structure to use.
    164164 * @param[in] address Address the caller wants to find.
    165165 * @param[out] handle Where to store found handle.
    166166 * @return Whether such address is currently occupied.
    167167 */
    168 bool usb_device_keeper_find_by_address(usb_device_keeper_t *instance,
     168bool usb_device_manager_find_by_address(usb_device_manager_t *instance,
    169169    usb_address_t address, devman_handle_t *handle)
    170170{
     
    191191/** Get speed associated with the address
    192192 *
    193  * @param[in] instance Device keeper structure to use.
     193 * @param[in] instance Device manager structure to use.
    194194 * @param[in] address Address of the device.
    195195 * @return USB speed.
    196196 */
    197 usb_speed_t usb_device_keeper_get_speed(
    198     usb_device_keeper_t *instance, usb_address_t address)
     197usb_speed_t usb_device_manager_get_speed(
     198    usb_device_manager_t *instance, usb_address_t address)
    199199{
    200200        assert(instance);
  • uspace/lib/usbhost/src/usb_endpoint_manager.c

    r47fecbb rfd07e526  
    4545static hash_index_t node_hash(unsigned long key[])
    4646{
    47         hash_index_t hash = 0;
    48         unsigned i = 0;
    49         for (;i < MAX_KEYS; ++i) {
    50                 hash ^= key[i];
    51         }
    52         hash %= BUCKET_COUNT;
    53         return hash;
     47        /* USB endpoints use 4 bits, thus ((key[0] << 4) | key[1])
     48         * produces unique value for every address.endpoint pair */
     49        return ((key[0] << 4) | key[1]) % BUCKET_COUNT;
    5450}
    5551/*----------------------------------------------------------------------------*/
     
    6359        switch (keys) {
    6460        case 3:
    65                 match = match && (key[2] == node->ep->direction);
     61                match = match &&
     62                    ((key[2] == node->ep->direction)
     63                    || (node->ep->direction == USB_DIRECTION_BOTH));
    6664        case 2:
    6765                match = match && (key[1] == (unsigned long)node->ep->endpoint);
     
    140138/*----------------------------------------------------------------------------*/
    141139int usb_endpoint_manager_init(usb_endpoint_manager_t *instance,
    142     size_t available_bandwidth)
     140    size_t available_bandwidth,
     141    size_t (*bw_count)(usb_speed_t, usb_transfer_type_t, size_t, size_t))
    143142{
    144143        assert(instance);
    145144        fibril_mutex_initialize(&instance->guard);
    146         fibril_condvar_initialize(&instance->change);
    147145        instance->free_bw = available_bandwidth;
    148         bool ht =
     146        instance->bw_count = bw_count;
     147        const bool ht =
    149148            hash_table_create(&instance->ep_table, BUCKET_COUNT, MAX_KEYS, &op);
    150149        return ht ? EOK : ENOMEM;
     
    159158    endpoint_t *ep, size_t data_size)
    160159{
     160        assert(instance);
     161        assert(instance->bw_count);
    161162        assert(ep);
    162         size_t bw = bandwidth_count_usb11(ep->speed, ep->transfer_type,
     163        const size_t bw = instance->bw_count(ep->speed, ep->transfer_type,
    163164            data_size, ep->max_packet_size);
    164         assert(instance);
     165
     166        fibril_mutex_lock(&instance->guard);
     167
     168        if (bw > instance->free_bw) {
     169                fibril_mutex_unlock(&instance->guard);
     170                return ENOSPC;
     171        }
    165172
    166173        unsigned long key[MAX_KEYS] =
    167174            {ep->address, ep->endpoint, ep->direction};
    168         fibril_mutex_lock(&instance->guard);
    169 
    170         link_t *item =
     175
     176        const link_t *item =
    171177            hash_table_find(&instance->ep_table, key);
    172178        if (item != NULL) {
    173179                fibril_mutex_unlock(&instance->guard);
    174180                return EEXISTS;
    175         }
    176 
    177         if (bw > instance->free_bw) {
    178                 fibril_mutex_unlock(&instance->guard);
    179                 return ENOSPC;
    180181        }
    181182
     
    193194        instance->free_bw -= bw;
    194195        fibril_mutex_unlock(&instance->guard);
    195         fibril_condvar_broadcast(&instance->change);
    196196        return EOK;
    197197}
     
    211211
    212212        node_t *node = hash_table_get_instance(item, node_t, link);
    213         if (node->ep->active)
     213        if (node->ep->active) {
     214                fibril_mutex_unlock(&instance->guard);
    214215                return EBUSY;
     216        }
    215217
    216218        instance->free_bw += node->bw;
     
    218220
    219221        fibril_mutex_unlock(&instance->guard);
    220         fibril_condvar_broadcast(&instance->change);
    221222        return EOK;
    222223}
     
    230231
    231232        fibril_mutex_lock(&instance->guard);
    232         link_t *item = hash_table_find(&instance->ep_table, key);
     233        const link_t *item = hash_table_find(&instance->ep_table, key);
    233234        if (item == NULL) {
    234235                fibril_mutex_unlock(&instance->guard);
    235236                return NULL;
    236237        }
    237         node_t *node = hash_table_get_instance(item, node_t, link);
     238        const node_t *node = hash_table_get_instance(item, node_t, link);
    238239        if (bw)
    239240                *bw = node->bw;
     
    255256{
    256257        assert(instance);
    257         if (target.endpoint > 15 || target.endpoint < 0
    258             || target.address >= USB11_ADDRESS_MAX || target.address < 0) {
     258        if (!usb_target_is_valid(target)) {
    259259                usb_log_error("Invalid data when checking for toggle reset.\n");
    260260                return;
    261261        }
    262262
     263        assert(data);
    263264        switch (data[1])
    264265        {
    265         case 0x01: /*clear feature*/
    266                 /* recipient is endpoint, value is zero (ENDPOINT_STALL) */
     266        case 0x01: /* Clear Feature -- resets only cleared ep */
     267                /* Recipient is endpoint, value is zero (ENDPOINT_STALL) */
    267268                if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) {
    268269                        /* endpoint number is < 16, thus first byte is enough */
     
    276277        break;
    277278
    278         case 0x9: /* set configuration */
    279         case 0x11: /* set interface */
    280                 /* target must be device */
     279        case 0x9: /* Set Configuration */
     280        case 0x11: /* Set Interface */
     281                /* Recipient must be device */
    281282                if ((data[0] & 0xf) == 0) {
    282283                        usb_target_t reset_target =
  • uspace/lib/usbhost/src/usb_transfer_batch.c

    r47fecbb rfd07e526  
    3737#include <usb/usb.h>
    3838#include <usb/debug.h>
    39 #include <usb/host/batch.h>
     39#include <usb/host/usb_transfer_batch.h>
     40#include <usb/host/hcd.h>
    4041
    41 void usb_transfer_batch_call_in(usb_transfer_batch_t *instance);
    42 void usb_transfer_batch_call_out(usb_transfer_batch_t *instance);
    43 
    44 void usb_transfer_batch_init(
    45     usb_transfer_batch_t *instance,
     42usb_transfer_batch_t * usb_transfer_batch_get(
    4643    endpoint_t *ep,
    4744    char *buffer,
    48     char *data_buffer,
    4945    size_t buffer_size,
    50     char *setup_buffer,
    51     size_t setup_size,
     46    uint64_t setup_buffer,
    5247    usbhc_iface_transfer_in_callback_t func_in,
    5348    usbhc_iface_transfer_out_callback_t func_out,
     
    5550    ddf_fun_t *fun,
    5651    void *private_data,
    57     void (*private_data_dtor)(void *p_data)
     52    void (*private_data_dtor)(void *)
    5853    )
    5954{
    60         assert(instance);
    61         link_initialize(&instance->link);
    62         instance->ep = ep;
    63         instance->callback_in = func_in;
    64         instance->callback_out = func_out;
    65         instance->arg = arg;
    66         instance->buffer = buffer;
    67         instance->data_buffer = data_buffer;
    68         instance->buffer_size = buffer_size;
    69         instance->setup_buffer = setup_buffer;
    70         instance->setup_size = setup_size;
    71         instance->fun = fun;
    72         instance->private_data = private_data;
    73         instance->private_data_dtor = private_data_dtor;
    74         instance->transfered_size = 0;
    75         instance->next_step = NULL;
    76         instance->error = EOK;
    77         endpoint_use(instance->ep);
     55        usb_transfer_batch_t *instance = malloc(sizeof(usb_transfer_batch_t));
     56        if (instance) {
     57                instance->ep = ep;
     58                instance->callback_in = func_in;
     59                instance->callback_out = func_out;
     60                instance->arg = arg;
     61                instance->buffer = buffer;
     62                instance->buffer_size = buffer_size;
     63                instance->setup_size = 0;
     64                instance->fun = fun;
     65                instance->private_data = private_data;
     66                instance->private_data_dtor = private_data_dtor;
     67                instance->transfered_size = 0;
     68                instance->error = EOK;
     69                if (ep && ep->transfer_type == USB_TRANSFER_CONTROL) {
     70                        memcpy(instance->setup_buffer, &setup_buffer,
     71                            USB_SETUP_PACKET_SIZE);
     72                        instance->setup_size = USB_SETUP_PACKET_SIZE;
     73                }
     74                if (instance->ep)
     75                        endpoint_use(instance->ep);
     76        }
     77        return instance;
    7878}
    7979/*----------------------------------------------------------------------------*/
    80 /** Helper function, calls callback and correctly destroys batch structure.
     80/** Mark batch as finished and run callback.
    8181 *
    8282 * @param[in] instance Batch structure to use.
     83 * @param[in] data Data to copy to the output buffer.
     84 * @param[in] size Size of @p data.
    8385 */
    84 void usb_transfer_batch_call_in_and_dispose(usb_transfer_batch_t *instance)
    85 {
    86         assert(instance);
    87         usb_transfer_batch_call_in(instance);
    88         usb_transfer_batch_dispose(instance);
    89 }
    90 /*----------------------------------------------------------------------------*/
    91 /** Helper function calls callback and correctly destroys batch structure.
    92  *
    93  * @param[in] instance Batch structure to use.
    94  */
    95 void usb_transfer_batch_call_out_and_dispose(usb_transfer_batch_t *instance)
    96 {
    97         assert(instance);
    98         usb_transfer_batch_call_out(instance);
    99         usb_transfer_batch_dispose(instance);
    100 }
    101 /*----------------------------------------------------------------------------*/
    102 /** Mark batch as finished and continue with next step.
    103  *
    104  * @param[in] instance Batch structure to use.
    105  *
    106  */
    107 void usb_transfer_batch_finish(usb_transfer_batch_t *instance)
     86void usb_transfer_batch_finish(
     87    usb_transfer_batch_t *instance, const void *data, size_t size)
    10888{
    10989        assert(instance);
    11090        assert(instance->ep);
    111         assert(instance->next_step);
    112         endpoint_release(instance->ep);
    113         instance->next_step(instance);
     91        /* we care about the data and there are some to copy */
     92        if (instance->ep->direction != USB_DIRECTION_OUT
     93            && data) {
     94                const size_t min_size =
     95                    size < instance->buffer_size ? size : instance->buffer_size;
     96                memcpy(instance->buffer, data, min_size);
     97        }
     98        if (instance->callback_out)
     99                usb_transfer_batch_call_out(instance);
     100        if (instance->callback_in)
     101                usb_transfer_batch_call_in(instance);
     102
    114103}
    115104/*----------------------------------------------------------------------------*/
     
    124113        assert(instance);
    125114        assert(instance->callback_in);
    126         assert(instance->ep);
    127 
    128         /* We are data in, we need data */
    129         memcpy(instance->buffer, instance->data_buffer, instance->buffer_size);
    130115
    131116        usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " completed (%zuB): %s.\n",
     
    150135            str_error(instance->error));
    151136
     137        if (instance->ep->transfer_type == USB_TRANSFER_CONTROL
     138            && instance->error == EOK) {
     139                const usb_target_t target =
     140                    {{ instance->ep->address, instance->ep->endpoint }};
     141                reset_ep_if_need(
     142                    fun_to_hcd(instance->fun), target, instance->setup_buffer);
     143        }
     144
    152145        instance->callback_out(instance->fun,
    153146            instance->error, instance->arg);
     
    160153void usb_transfer_batch_dispose(usb_transfer_batch_t *instance)
    161154{
    162         assert(instance);
     155        if (!instance)
     156                return;
    163157        usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " disposing.\n",
    164158            instance, USB_TRANSFER_BATCH_ARGS(*instance));
     159        if (instance->ep) {
     160                endpoint_release(instance->ep);
     161        }
    165162        if (instance->private_data) {
    166163                assert(instance->private_data_dtor);
Note: See TracChangeset for help on using the changeset viewer.