Changeset dc4c19e in mainline for uspace/drv/uhci-hcd/iface.c


Ignore:
Timestamp:
2011-04-10T12:18:09Z (13 years ago)
Author:
Lubos Slovak <lubos.slovak@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
60c0573
Parents:
a49e171 (diff), 82e8861 (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:

Development changes

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/uhci-hcd/iface.c

    ra49e171 rdc4c19e  
    4141#include "hc.h"
    4242
    43 /** Reserve default address interface function
    44  *
    45  * @param[in] fun DDF function that was called.
    46  * @param[in] speed Speed to associate with the new default address.
    47  * @return Error code.
    48  */
    49 static int reserve_default_address(ddf_fun_t *fun, usb_speed_t speed)
    50 {
     43static inline int setup_batch(
     44    ddf_fun_t *fun, usb_target_t target, usb_direction_t direction,
     45    void *data, size_t size, void * setup_data, size_t setup_size,
     46    usbhc_iface_transfer_in_callback_t in,
     47    usbhc_iface_transfer_out_callback_t out, void *arg, const char* name,
     48    hc_t **hc, usb_transfer_batch_t **batch)
     49{
     50        assert(hc);
     51        assert(batch);
    5152        assert(fun);
    52         hc_t *hc = fun_to_hc(fun);
    53         assert(hc);
    54         usb_log_debug("Default address request with speed %d.\n", speed);
    55         usb_device_keeper_reserve_default_address(&hc->manager, speed);
    56         return EOK;
    57 #if 0
    58         endpoint_t *ep = malloc(sizeof(endpoint_t));
    59         if (ep == NULL)
     53        *hc = fun_to_hc(fun);
     54        assert(*hc);
     55
     56        size_t res_bw;
     57        endpoint_t *ep = usb_endpoint_manager_get_ep(&(*hc)->ep_manager,
     58            target.address, target.endpoint, direction, &res_bw);
     59        if (ep == NULL) {
     60                usb_log_error("Endpoint(%d:%d) not registered for %s.\n",
     61                    target.address, target.endpoint, name);
     62                return ENOENT;
     63        }
     64
     65        usb_log_debug("%s %d:%d %zu(%zu).\n",
     66            name, target.address, target.endpoint, size, ep->max_packet_size);
     67
     68        const size_t bw = bandwidth_count_usb11(
     69            ep->speed, ep->transfer_type, size, ep->max_packet_size);
     70        if (res_bw < bw) {
     71                usb_log_error("Endpoint(%d:%d) %s needs %zu bw "
     72                    "but only %zu is reserved.\n",
     73                    target.address, target.endpoint, name, bw, res_bw);
     74                return ENOSPC;
     75        }
     76
     77        *batch = batch_get(
     78                fun, ep, data, size, setup_data, setup_size, in, out, arg);
     79        if (!*batch)
    6080                return ENOMEM;
    61         const size_t max_packet_size = speed == USB_SPEED_LOW ? 8 : 64;
    62         endpoint_init(ep, USB_TRANSFER_CONTROL, speed, max_packet_size);
    63         int ret;
    64 try_retgister:
    65         ret = usb_endpoint_manager_register_ep(&hc->ep_manager,
    66             USB_ADDRESS_DEFAULT, 0, USB_DIRECTION_BOTH, ep, endpoint_destroy, 0);
    67         if (ret == EEXISTS) {
    68                 async_usleep(1000);
    69                 goto try_retgister;
    70         }
    71         if (ret != EOK) {
    72                 endpoint_destroy(ep);
    73         }
    74         return ret;
    75 #endif
    76 }
    77 /*----------------------------------------------------------------------------*/
    78 /** Release default address interface function
    79  *
    80  * @param[in] fun DDF function that was called.
    81  * @return Error code.
    82  */
    83 static int release_default_address(ddf_fun_t *fun)
    84 {
    85         assert(fun);
    86         hc_t *hc = fun_to_hc(fun);
    87         assert(hc);
    88         usb_log_debug("Default address release.\n");
    89 //      return usb_endpoint_manager_unregister_ep(&hc->ep_manager,
    90 //          USB_ADDRESS_DEFAULT, 0, USB_DIRECTION_BOTH);
    91         usb_device_keeper_release_default_address(&hc->manager);
    9281        return EOK;
    9382}
     
    151140/*----------------------------------------------------------------------------*/
    152141static int register_endpoint(
    153     ddf_fun_t *fun, usb_address_t address, usb_endpoint_t endpoint,
     142    ddf_fun_t *fun, usb_address_t address, usb_speed_t ep_speed,
     143    usb_endpoint_t endpoint,
    154144    usb_transfer_type_t transfer_type, usb_direction_t direction,
    155145    size_t max_packet_size, unsigned int interval)
     
    157147        hc_t *hc = fun_to_hc(fun);
    158148        assert(hc);
    159         const usb_speed_t speed =
    160             usb_device_keeper_get_speed(&hc->manager, address);
    161         const size_t size =
    162             (transfer_type == USB_TRANSFER_INTERRUPT
    163             || transfer_type == USB_TRANSFER_ISOCHRONOUS) ?
    164             max_packet_size : 0;
     149        const size_t size = max_packet_size;
    165150        int ret;
     151        usb_speed_t speed = usb_device_keeper_get_speed(&hc->manager, address);
     152        if (speed >= USB_SPEED_MAX) {
     153                speed = ep_speed;
     154        }
     155        usb_log_debug("Register endpoint %d:%d %s %s(%d) %zu(%zu) %u.\n",
     156            address, endpoint, usb_str_transfer_type(transfer_type),
     157            usb_str_speed(speed), direction, size, max_packet_size, interval);
     158
    166159
    167160        endpoint_t *ep = malloc(sizeof(endpoint_t));
     
    175168        }
    176169
    177         usb_log_debug("Register endpoint %d:%d %s %s(%d) %zu(%zu) %u.\n",
    178             address, endpoint, usb_str_transfer_type(transfer_type),
    179             usb_str_speed(speed), direction, size, max_packet_size, interval);
    180 
    181170        ret = usb_endpoint_manager_register_ep(&hc->ep_manager, ep, size);
    182171        if (ret != EOK) {
    183172                endpoint_destroy(ep);
    184         } else {
    185                 usb_device_keeper_add_ep(&hc->manager, address, ep);
    186173        }
    187174        return ret;
     
    204191 * @param[in] fun DDF function that was called.
    205192 * @param[in] target USB device to write to.
    206  * @param[in] max_packet_size maximum size of data packet the device accepts
    207193 * @param[in] data Source of data.
    208194 * @param[in] size Size of data source.
     
    212198 */
    213199static int interrupt_out(
    214     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
     200    ddf_fun_t *fun, usb_target_t target, void *data,
    215201    size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
    216202{
    217         assert(fun);
    218         hc_t *hc = fun_to_hc(fun);
    219         assert(hc);
    220 
    221         usb_log_debug("Interrupt OUT %d:%d %zu(%zu).\n",
    222             target.address, target.endpoint, size, max_packet_size);
    223 
    224         size_t res_bw;
    225         endpoint_t *ep = usb_endpoint_manager_get_ep(&hc->ep_manager,
    226             target.address, target.endpoint, USB_DIRECTION_OUT, &res_bw);
    227         if (ep == NULL) {
    228                 usb_log_error("Endpoint(%d:%d) not registered for INT OUT.\n",
    229                         target.address, target.endpoint);
    230                 return ENOENT;
    231         }
    232         const size_t bw = bandwidth_count_usb11(ep->speed, ep->transfer_type,
    233             size, ep->max_packet_size);
    234         if (res_bw < bw)
    235         {
    236                 usb_log_error("Endpoint(%d:%d) INT IN needs %zu bw "
    237                     "but only %zu is reserved.\n",
    238                     target.address, target.endpoint, bw, res_bw);
    239                 return ENOENT;
    240         }
    241         assert(ep->speed ==
    242             usb_device_keeper_get_speed(&hc->manager, target.address));
    243         assert(ep->max_packet_size == max_packet_size);
    244         assert(ep->transfer_type == USB_TRANSFER_INTERRUPT);
    245 
    246         usb_transfer_batch_t *batch =
    247             batch_get(fun, target, ep->transfer_type, ep->max_packet_size,
    248                 ep->speed, data, size, NULL, 0, NULL, callback, arg, ep);
    249         if (!batch)
    250                 return ENOMEM;
     203        usb_transfer_batch_t *batch = NULL;
     204        hc_t *hc = NULL;
     205        int ret = setup_batch(fun, target, USB_DIRECTION_OUT, data, size,
     206            NULL, 0, NULL, callback, arg, "Interrupt OUT", &hc, &batch);
     207        if (ret != EOK)
     208                return ret;
    251209        batch_interrupt_out(batch);
    252         const int ret = hc_schedule(hc, batch);
     210        ret = hc_schedule(hc, batch);
    253211        if (ret != EOK) {
    254212                batch_dispose(batch);
     
    261219 * @param[in] fun DDF function that was called.
    262220 * @param[in] target USB device to write to.
    263  * @param[in] max_packet_size maximum size of data packet the device accepts
    264221 * @param[out] data Data destination.
    265222 * @param[in] size Size of data source.
     
    269226 */
    270227static int interrupt_in(
    271     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
     228    ddf_fun_t *fun, usb_target_t target, void *data,
    272229    size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
    273230{
    274         assert(fun);
    275         hc_t *hc = fun_to_hc(fun);
    276         assert(hc);
    277 
    278         usb_log_debug("Interrupt IN %d:%d %zu(%zu).\n",
    279             target.address, target.endpoint, size, max_packet_size);
    280 
    281         size_t res_bw;
    282         endpoint_t *ep = usb_endpoint_manager_get_ep(&hc->ep_manager,
    283             target.address, target.endpoint, USB_DIRECTION_IN, &res_bw);
    284         if (ep == NULL) {
    285                 usb_log_error("Endpoint(%d:%d) not registered for INT IN.\n",
    286                     target.address, target.endpoint);
    287                 return ENOENT;
    288         }
    289         const size_t bw = bandwidth_count_usb11(ep->speed, ep->transfer_type,
    290             size, ep->max_packet_size);
    291         if (res_bw < bw)
    292         {
    293                 usb_log_error("Endpoint(%d:%d) INT IN needs %zu bw "
    294                     "but only %zu bw is reserved.\n",
    295                     target.address, target.endpoint, bw, res_bw);
    296                 return ENOENT;
    297         }
    298 
    299         assert(ep->speed ==
    300             usb_device_keeper_get_speed(&hc->manager, target.address));
    301         assert(ep->max_packet_size == max_packet_size);
    302         assert(ep->transfer_type == USB_TRANSFER_INTERRUPT);
    303 
    304         usb_transfer_batch_t *batch =
    305             batch_get(fun, target, ep->transfer_type, ep->max_packet_size,
    306                 ep->speed, data, size, NULL, 0, callback, NULL, arg, ep);
    307         if (!batch)
    308                 return ENOMEM;
     231        usb_transfer_batch_t *batch = NULL;
     232        hc_t *hc = NULL;
     233        int ret = setup_batch(fun, target, USB_DIRECTION_IN, data, size,
     234            NULL, 0, callback, NULL, arg, "Interrupt IN", &hc, &batch);
     235        if (ret != EOK)
     236                return ret;
    309237        batch_interrupt_in(batch);
    310         const int ret = hc_schedule(hc, batch);
     238        ret = hc_schedule(hc, batch);
    311239        if (ret != EOK) {
    312240                batch_dispose(batch);
     
    319247 * @param[in] fun DDF function that was called.
    320248 * @param[in] target USB device to write to.
    321  * @param[in] max_packet_size maximum size of data packet the device accepts
    322249 * @param[in] data Source of data.
    323250 * @param[in] size Size of data source.
     
    327254 */
    328255static int bulk_out(
    329     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
     256    ddf_fun_t *fun, usb_target_t target, void *data,
    330257    size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
    331258{
    332         assert(fun);
    333         hc_t *hc = fun_to_hc(fun);
    334         assert(hc);
    335 
    336         usb_log_debug("Bulk OUT %d:%d %zu(%zu).\n",
    337             target.address, target.endpoint, size, max_packet_size);
    338 
    339         endpoint_t *ep = usb_endpoint_manager_get_ep(&hc->ep_manager,
    340             target.address, target.endpoint, USB_DIRECTION_OUT, NULL);
    341         if (ep == NULL) {
    342                 usb_log_error("Endpoint(%d:%d) not registered for BULK OUT.\n",
    343                         target.address, target.endpoint);
    344                 return ENOENT;
    345         }
    346         assert(ep->speed ==
    347             usb_device_keeper_get_speed(&hc->manager, target.address));
    348         assert(ep->max_packet_size == max_packet_size);
    349         assert(ep->transfer_type == USB_TRANSFER_BULK);
    350 
    351         usb_transfer_batch_t *batch =
    352             batch_get(fun, target, ep->transfer_type, ep->max_packet_size,
    353                 ep->speed, data, size, NULL, 0, NULL, callback, arg, ep);
    354         if (!batch)
    355                 return ENOMEM;
     259        usb_transfer_batch_t *batch = NULL;
     260        hc_t *hc = NULL;
     261        int ret = setup_batch(fun, target, USB_DIRECTION_OUT, data, size,
     262            NULL, 0, NULL, callback, arg, "Bulk OUT", &hc, &batch);
     263        if (ret != EOK)
     264                return ret;
    356265        batch_bulk_out(batch);
    357         const int ret = hc_schedule(hc, batch);
     266        ret = hc_schedule(hc, batch);
    358267        if (ret != EOK) {
    359268                batch_dispose(batch);
     
    366275 * @param[in] fun DDF function that was called.
    367276 * @param[in] target USB device to write to.
    368  * @param[in] max_packet_size maximum size of data packet the device accepts
    369277 * @param[out] data Data destination.
    370278 * @param[in] size Size of data source.
     
    374282 */
    375283static int bulk_in(
    376     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
     284    ddf_fun_t *fun, usb_target_t target, void *data,
    377285    size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
    378286{
    379         assert(fun);
    380         hc_t *hc = fun_to_hc(fun);
    381         assert(hc);
    382         usb_log_debug("Bulk IN %d:%d %zu(%zu).\n",
    383             target.address, target.endpoint, size, max_packet_size);
    384 
    385         endpoint_t *ep = usb_endpoint_manager_get_ep(&hc->ep_manager,
    386             target.address, target.endpoint, USB_DIRECTION_IN, NULL);
    387         if (ep == NULL) {
    388                 usb_log_error("Endpoint(%d:%d) not registered for BULK IN.\n",
    389                         target.address, target.endpoint);
    390                 return ENOENT;
    391         }
    392         assert(ep->speed ==
    393             usb_device_keeper_get_speed(&hc->manager, target.address));
    394         assert(ep->max_packet_size == max_packet_size);
    395         assert(ep->transfer_type == USB_TRANSFER_BULK);
    396 
    397         usb_transfer_batch_t *batch =
    398             batch_get(fun, target, ep->transfer_type, ep->max_packet_size,
    399                 ep->speed, data, size, NULL, 0, callback, NULL, arg, ep);
    400         if (!batch)
    401                 return ENOMEM;
     287        usb_transfer_batch_t *batch = NULL;
     288        hc_t *hc = NULL;
     289        int ret = setup_batch(fun, target, USB_DIRECTION_IN, data, size,
     290            NULL, 0, callback, NULL, arg, "Bulk IN", &hc, &batch);
     291        if (ret != EOK)
     292                return ret;
    402293        batch_bulk_in(batch);
    403         const int ret = hc_schedule(hc, batch);
     294        ret = hc_schedule(hc, batch);
    404295        if (ret != EOK) {
    405296                batch_dispose(batch);
     
    412303 * @param[in] fun DDF function that was called.
    413304 * @param[in] target USB device to write to.
    414  * @param[in] max_packet_size maximum size of data packet the device accepts.
    415305 * @param[in] setup_data Data to send with SETUP transfer.
    416306 * @param[in] setup_size Size of data to send with SETUP transfer (always 8B).
     
    422312 */
    423313static int control_write(
    424     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,
     314    ddf_fun_t *fun, usb_target_t target,
    425315    void *setup_data, size_t setup_size, void *data, size_t size,
    426316    usbhc_iface_transfer_out_callback_t callback, void *arg)
    427317{
    428         assert(fun);
    429         hc_t *hc = fun_to_hc(fun);
    430         assert(hc);
    431         usb_speed_t speed =
    432             usb_device_keeper_get_speed(&hc->manager, target.address);
    433         usb_log_debug("Control WRITE (%d) %d:%d %zu(%zu).\n",
    434             speed, target.address, target.endpoint, size, max_packet_size);
    435         endpoint_t *ep = usb_endpoint_manager_get_ep(&hc->ep_manager,
    436             target.address, target.endpoint, USB_DIRECTION_BOTH, NULL);
    437         if (ep == NULL) {
    438                 usb_log_warning("Endpoint(%d:%d) not registered for CONTROL.\n",
    439                         target.address, target.endpoint);
    440         }
    441 
    442         if (setup_size != 8)
    443                 return EINVAL;
    444 
    445         usb_transfer_batch_t *batch =
    446             batch_get(fun, target, USB_TRANSFER_CONTROL, max_packet_size, speed,
    447                 data, size, setup_data, setup_size, NULL, callback, arg, ep);
    448         if (!batch)
    449                 return ENOMEM;
    450         usb_device_keeper_reset_if_need(&hc->manager, target, setup_data);
     318        usb_transfer_batch_t *batch = NULL;
     319        hc_t *hc = NULL;
     320        int ret = setup_batch(fun, target, USB_DIRECTION_BOTH, data, size,
     321            setup_data, setup_size, NULL, callback, arg, "Control WRITE",
     322            &hc, &batch);
     323        if (ret != EOK)
     324                return ret;
     325        usb_endpoint_manager_reset_if_need(&hc->ep_manager, target, setup_data);
    451326        batch_control_write(batch);
    452         const int ret = hc_schedule(hc, batch);
     327        ret = hc_schedule(hc, batch);
    453328        if (ret != EOK) {
    454329                batch_dispose(batch);
     
    461336 * @param[in] fun DDF function that was called.
    462337 * @param[in] target USB device to write to.
    463  * @param[in] max_packet_size maximum size of data packet the device accepts.
    464338 * @param[in] setup_data Data to send with SETUP packet.
    465339 * @param[in] setup_size Size of data to send with SETUP packet (should be 8B).
     
    471345 */
    472346static int control_read(
    473     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,
     347    ddf_fun_t *fun, usb_target_t target,
    474348    void *setup_data, size_t setup_size, void *data, size_t size,
    475349    usbhc_iface_transfer_in_callback_t callback, void *arg)
    476350{
    477         assert(fun);
    478         hc_t *hc = fun_to_hc(fun);
    479         assert(hc);
    480         usb_speed_t speed =
    481             usb_device_keeper_get_speed(&hc->manager, target.address);
    482 
    483         usb_log_debug("Control READ(%d) %d:%d %zu(%zu).\n",
    484             speed, target.address, target.endpoint, size, max_packet_size);
    485         endpoint_t *ep = usb_endpoint_manager_get_ep(&hc->ep_manager,
    486             target.address, target.endpoint, USB_DIRECTION_BOTH, NULL);
    487         if (ep == NULL) {
    488                 usb_log_warning("Endpoint(%d:%d) not registered for CONTROL.\n",
    489                         target.address, target.endpoint);
    490         }
    491         usb_transfer_batch_t *batch =
    492             batch_get(fun, target, USB_TRANSFER_CONTROL, max_packet_size, speed,
    493                 data, size, setup_data, setup_size, callback, NULL, arg, ep);
    494         if (!batch)
    495                 return ENOMEM;
     351        usb_transfer_batch_t *batch = NULL;
     352        hc_t *hc = NULL;
     353        int ret = setup_batch(fun, target, USB_DIRECTION_BOTH, data, size,
     354            setup_data, setup_size, callback, NULL, arg, "Control READ",
     355            &hc, &batch);
     356        if (ret != EOK)
     357                return ret;
    496358        batch_control_read(batch);
    497         const int ret = hc_schedule(hc, batch);
     359        ret = hc_schedule(hc, batch);
    498360        if (ret != EOK) {
    499361                batch_dispose(batch);
     
    503365/*----------------------------------------------------------------------------*/
    504366usbhc_iface_t hc_iface = {
    505         .reserve_default_address = reserve_default_address,
    506         .release_default_address = release_default_address,
    507367        .request_address = request_address,
    508368        .bind_address = bind_address,
Note: See TracChangeset for help on using the changeset viewer.