Changeset 54464f6a in mainline for uspace/lib/usbdev/src


Ignore:
Timestamp:
2011-11-11T19:48:33Z (14 years ago)
Author:
Maurizio Lombardi <m.lombardi85@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
50a01a9
Parents:
c2e50d7 (diff), 747ef72 (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 mainline changes

Location:
uspace/lib/usbdev/src
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/usbdev/src/altiface.c

    rc2e50d7 r54464f6a  
    9090 * @return Error code.
    9191 */
    92 int usb_alternate_interfaces_create(const uint8_t *config_descr,
    93     size_t config_descr_size, int interface_number,
    94     usb_alternate_interfaces_t **alternates_ptr)
     92int usb_alternate_interfaces_init(usb_alternate_interfaces_t *alternates,
     93    const uint8_t *config_descr, size_t config_descr_size, int interface_number)
    9594{
    96         assert(alternates_ptr != NULL);
     95        assert(alternates != NULL);
    9796        assert(config_descr != NULL);
    9897        assert(config_descr_size > 0);
    9998
    100         *alternates_ptr = NULL;
     99        alternates->alternatives = NULL;
     100        alternates->alternative_count = 0;
     101        alternates->current = 0;
     102
    101103        if (interface_number < 0) {
    102104                return EOK;
    103         }
    104 
    105         usb_alternate_interfaces_t *alternates
    106             = malloc(sizeof(usb_alternate_interfaces_t));
    107         if (alternates == NULL) {
    108                 return ENOMEM;
    109105        }
    110106
     
    114110
    115111        if (alternates->alternative_count == 0) {
    116                 free(alternates);
    117112                return ENOENT;
    118113        }
     
    121116            sizeof(usb_alternate_interface_descriptors_t));
    122117        if (alternates->alternatives == NULL) {
    123                 free(alternates);
    124118                return ENOMEM;
    125119        }
    126120
    127         alternates->current = 0;
    128 
    129         usb_dp_parser_t dp_parser = {
     121        const usb_dp_parser_t dp_parser = {
    130122                .nesting = usb_dp_standard_descriptor_nesting
    131123        };
    132         usb_dp_parser_data_t dp_data = {
     124        const usb_dp_parser_data_t dp_data = {
    133125                .data = config_descr,
    134126                .size = config_descr_size,
     
    147139                    || (iface->interface_number != interface_number)) {
    148140                        iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser,
    149                             &dp_data,
    150                             dp_data.data, iface_ptr);
     141                            &dp_data, dp_data.data, iface_ptr);
    151142                        continue;
    152143                }
     
    170161        }
    171162
    172         *alternates_ptr = alternates;
    173 
    174163        return EOK;
    175164}
    176165
    177 void usb_alternate_interfaces_destroy(usb_alternate_interfaces_t *alternate)
     166void usb_alternate_interfaces_deinit(usb_alternate_interfaces_t *alternate)
    178167{
    179168        if (!alternate)
    180169                return;
    181170        free(alternate->alternatives);
    182         free(alternate);
    183171}
    184172/**
  • uspace/lib/usbdev/src/devdrv.c

    rc2e50d7 r54464f6a  
    8181 * @return Number of pipes (excluding default control pipe).
    8282 */
    83 static size_t count_other_pipes(const usb_endpoint_description_t **endpoints)
    84 {
    85         size_t count = 0;
    86         if (endpoints == NULL) {
    87                 return 0;
    88         }
    89 
    90         while (endpoints[count] != NULL) {
    91                 count++;
    92         }
    93 
     83static inline size_t count_other_pipes(
     84    const usb_endpoint_description_t **endpoints)
     85{
     86        size_t count;
     87        for (count = 0; endpoints && endpoints[count] != NULL; ++count);
    9488        return count;
    9589}
     
    10498    usb_device_t *dev, int alternate_setting)
    10599{
     100        assert(dev);
     101
    106102        if (endpoints == NULL) {
    107103                dev->pipes = NULL;
     
    300296
    301297        return rc;
     298}
     299
     300/** Cleanup structure initialized via usb_device_retrieve_descriptors.
     301 *
     302 * @param[in] descriptors Where to store the descriptors.
     303 */
     304void usb_device_release_descriptors(usb_device_descriptors_t *descriptors)
     305{
     306        assert(descriptors);
     307        free(descriptors->configuration);
     308        descriptors->configuration = NULL;
    302309}
    303310
     
    319326 *      (not NULL terminated).
    320327 * @param[out] pipes_count_ptr Where to store number of pipes
    321  *      (set to if you wish to ignore the count).
     328 *      (set to NULL if you wish to ignore the count).
    322329 * @return Error code.
    323330 */
     
    340347        const size_t pipe_count = count_other_pipes(endpoints);
    341348        if (pipe_count == 0) {
    342                 *pipes_count_ptr = pipe_count;
     349                if (pipes_count_ptr)
     350                        *pipes_count_ptr = pipe_count;
    343351                *pipes_ptr = NULL;
    344352                return EOK;
     
    346354
    347355        usb_endpoint_mapping_t *pipes
    348             = malloc(sizeof(usb_endpoint_mapping_t) * pipe_count);
     356            = calloc(pipe_count, sizeof(usb_endpoint_mapping_t));
    349357        if (pipes == NULL) {
    350358                return ENOMEM;
    351359        }
    352360
    353         /* Initialize to NULL to allow smooth rollback. */
    354         for (i = 0; i < pipe_count; i++) {
    355                 pipes[i].pipe = NULL;
    356         }
    357 
    358361        /* Now allocate and fully initialize. */
    359362        for (i = 0; i < pipe_count; i++) {
    360                 pipes[i].pipe = malloc(sizeof(usb_pipe_t));
    361                 if (pipes[i].pipe == NULL) {
    362                         rc = ENOMEM;
    363                         goto rollback_free_only;
    364                 }
    365363                pipes[i].description = endpoints[i];
    366364                pipes[i].interface_no = interface_no;
     
    389387        for (i = 0; i < pipe_count; i++) {
    390388                if (pipes[i].present) {
    391                         rc = usb_pipe_register(pipes[i].pipe,
     389                        rc = usb_pipe_register(&pipes[i].pipe,
    392390                            pipes[i].descriptor->poll_interval, &hc_conn);
    393391                        if (rc != EOK) {
     
    398396
    399397        if (usb_hc_connection_close(&hc_conn) != EOK)
    400                 usb_log_warning("usb_device_create_pipes(): "
    401                     "Failed to close connection.\n");
     398                usb_log_warning("%s: Failed to close connection.\n",
     399                    __FUNCTION__);
    402400
    403401        *pipes_ptr = pipes;
     
    417415        for (i = 0; i < pipe_count; i++) {
    418416                if (pipes[i].present) {
    419                         usb_pipe_unregister(pipes[i].pipe, &hc_conn);
     417                        usb_pipe_unregister(&pipes[i].pipe, &hc_conn);
    420418                }
    421419        }
     
    431429         */
    432430rollback_free_only:
    433         for (i = 0; i < pipe_count; i++) {
    434                 if (pipes[i].pipe != NULL) {
    435                         free(pipes[i].pipe);
    436                 }
    437         }
    438431        free(pipes);
    439432
     
    477470                    i, pipes[i].present ? "" : "not ");
    478471                if (pipes[i].present)
    479                         usb_pipe_unregister(pipes[i].pipe, &hc_conn);
    480                 free(pipes[i].pipe);
     472                        usb_pipe_unregister(&pipes[i].pipe, &hc_conn);
    481473        }
    482474
     
    489481        return EOK;
    490482}
    491 
    492 /** Initialize control pipe in a device.
    493  *
    494  * @param dev USB device in question.
    495  * @param errmsg Where to store error context.
    496  * @return
    497  */
    498 static int init_wire_and_ctrl_pipe(usb_device_t *dev, const char **errmsg)
    499 {
    500         int rc;
    501 
    502         rc = usb_device_connection_initialize_from_device(&dev->wire,
    503             dev->ddf_dev);
    504         if (rc != EOK) {
    505                 *errmsg = "device connection initialization";
    506                 return rc;
    507         }
    508 
    509         rc = usb_pipe_initialize_default_control(&dev->ctrl_pipe,
    510             &dev->wire);
    511         if (rc != EOK) {
    512                 *errmsg = "default control pipe initialization";
    513                 return rc;
    514         }
    515 
    516         return EOK;
    517 }
    518 
    519483
    520484/** Initialize new instance of USB device.
     
    533497        assert(ddf_dev != NULL);
    534498
     499        *errstr_ptr = NULL;
     500
    535501        usb_dev->ddf_dev = ddf_dev;
    536502        usb_dev->driver_data = NULL;
    537503        usb_dev->descriptors.configuration = NULL;
    538         usb_dev->alternate_interfaces = NULL;
    539504        usb_dev->pipes_count = 0;
    540505        usb_dev->pipes = NULL;
    541506
    542507        /* Initialize backing wire and control pipe. */
    543         int rc = init_wire_and_ctrl_pipe(usb_dev, errstr_ptr);
    544         if (rc != EOK) {
     508        int rc = usb_device_connection_initialize_from_device(
     509            &usb_dev->wire, ddf_dev);
     510        if (rc != EOK) {
     511                *errstr_ptr = "device connection initialization";
     512                return rc;
     513        }
     514
     515        /* This pipe was registered by the hub driver,
     516         * during device initialization. */
     517        rc = usb_pipe_initialize_default_control(&usb_dev->ctrl_pipe,
     518            &usb_dev->wire);
     519        if (rc != EOK) {
     520                *errstr_ptr = "default control pipe initialization";
    545521                return rc;
    546522        }
     
    553529            &usb_dev->descriptors);
    554530        if (rc != EOK) {
    555                 /* Nothing allocated, nothing to free. */
    556531                *errstr_ptr = "descriptor retrieval";
    557532                return rc;
    558533        }
    559534
    560         /* Create alternate interfaces. We will silently ignore failure. */
    561         //TODO Why ignore?
    562         usb_alternate_interfaces_create(usb_dev->descriptors.configuration,
    563             usb_dev->descriptors.configuration_size, usb_dev->interface_no,
    564             &usb_dev->alternate_interfaces);
    565 
    566         rc = initialize_other_pipes(endpoints, usb_dev, 0);
     535        /* Create alternate interfaces. We will silently ignore failure.
     536         * We might either control one interface or an entire device,
     537         * it makes no sense to speak about alternate interfaces when
     538         * controlling a device. */
     539        rc = usb_alternate_interfaces_init(&usb_dev->alternate_interfaces,
     540            usb_dev->descriptors.configuration,
     541            usb_dev->descriptors.configuration_size, usb_dev->interface_no);
     542        const int alternate_iface =
     543            (rc == EOK) ? usb_dev->alternate_interfaces.current : 0;
     544
     545        /* TODO Add comment here. */
     546        rc = initialize_other_pipes(endpoints, usb_dev, alternate_iface);
    567547        if (rc != EOK) {
    568548                /* Full configuration descriptor is allocated. */
    569                 free(usb_dev->descriptors.configuration);
     549                usb_device_release_descriptors(&usb_dev->descriptors);
    570550                /* Alternate interfaces may be allocated */
    571                 usb_alternate_interfaces_destroy(usb_dev->alternate_interfaces);
     551                usb_alternate_interfaces_deinit(&usb_dev->alternate_interfaces);
    572552                *errstr_ptr = "pipes initialization";
    573553                return rc;
    574554        }
    575 
    576         *errstr_ptr = NULL;
    577555
    578556        return EOK;
     
    591569                destroy_current_pipes(dev);
    592570
    593                 usb_alternate_interfaces_destroy(dev->alternate_interfaces);
    594                 free(dev->descriptors.configuration);
     571                usb_alternate_interfaces_deinit(&dev->alternate_interfaces);
     572                usb_device_release_descriptors(&dev->descriptors);
    595573                free(dev->driver_data);
    596574        }
  • uspace/lib/usbdev/src/devpoll.c

    rc2e50d7 r54464f6a  
    7373
    7474        usb_pipe_t *pipe
    75             = polling_data->dev->pipes[polling_data->pipe_index].pipe;
     75            = &polling_data->dev->pipes[polling_data->pipe_index].pipe;
    7676       
    7777        if (polling_data->debug > 0) {
     
    208208                return EINVAL;
    209209        }
    210         if ((dev->pipes[pipe_index].pipe->transfer_type != USB_TRANSFER_INTERRUPT)
    211             || (dev->pipes[pipe_index].pipe->direction != USB_DIRECTION_IN)) {
     210        if ((dev->pipes[pipe_index].pipe.transfer_type != USB_TRANSFER_INTERRUPT)
     211            || (dev->pipes[pipe_index].pipe.direction != USB_DIRECTION_IN)) {
    212212                return EINVAL;
    213213        }
    214214
    215         usb_device_auto_polling_t *auto_polling
    216             = malloc(sizeof(usb_device_auto_polling_t));
    217         if (auto_polling == NULL) {
    218                 return ENOMEM;
    219         }
    220 
    221         auto_polling->debug = 1;
    222         auto_polling->auto_clear_halt = true;
    223         auto_polling->delay = 0;
    224         auto_polling->max_failures = MAX_FAILED_ATTEMPTS;
    225         auto_polling->on_data = callback;
    226         auto_polling->on_polling_end = terminated_callback;
    227         auto_polling->on_error = NULL;
    228 
    229         int rc = usb_device_auto_polling(dev, pipe_index, auto_polling,
     215        const usb_device_auto_polling_t auto_polling = {
     216                .debug = 1,
     217                .auto_clear_halt = true,
     218                .delay = 0,
     219                .max_failures = MAX_FAILED_ATTEMPTS,
     220                .on_data = callback,
     221                .on_polling_end = terminated_callback,
     222                .on_error = NULL,
     223        };
     224
     225        return usb_device_auto_polling(dev, pipe_index, &auto_polling,
    230226           request_size, arg);
    231 
    232         free(auto_polling);
    233 
    234         return rc;
    235227}
    236228
     
    253245 */
    254246int usb_device_auto_polling(usb_device_t *dev, size_t pipe_index,
    255     usb_device_auto_polling_t *polling,
     247    const usb_device_auto_polling_t *polling,
    256248    size_t request_size, void *arg)
    257249{
     
    262254                return EINVAL;
    263255        }
    264         if ((dev->pipes[pipe_index].pipe->transfer_type != USB_TRANSFER_INTERRUPT)
    265             || (dev->pipes[pipe_index].pipe->direction != USB_DIRECTION_IN)) {
     256        if ((dev->pipes[pipe_index].pipe.transfer_type != USB_TRANSFER_INTERRUPT)
     257            || (dev->pipes[pipe_index].pipe.direction != USB_DIRECTION_IN)) {
    266258                return EINVAL;
    267259        }
  • uspace/lib/usbdev/src/dp.c

    rc2e50d7 r54464f6a  
    5757
    5858/** Nesting of standard USB descriptors. */
    59 usb_dp_descriptor_nesting_t usb_dp_standard_descriptor_nesting[] = {
     59const usb_dp_descriptor_nesting_t usb_dp_standard_descriptor_nesting[] = {
    6060        NESTING(CONFIGURATION, INTERFACE),
    6161        NESTING(INTERFACE, ENDPOINT),
  • uspace/lib/usbdev/src/hub.c

    rc2e50d7 r54464f6a  
    6666 *
    6767 * @param connection Opened connection to host controller.
     68 * @param preferred Preferred SUB address.
     69 * @param strict Fail if the preferred address is not avialable.
    6870 * @param speed Speed of the new device (device that will be assigned
    6971 *    the returned address).
     
    7173 */
    7274usb_address_t usb_hc_request_address(usb_hc_connection_t *connection,
    73     usb_speed_t speed)
     75    usb_address_t preferred, bool strict, usb_speed_t speed)
    7476{
    7577        CHECK_CONNECTION(connection);
     
    7880       
    7981        sysarg_t address;
    80         int rc = async_req_2_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    81             IPC_M_USBHC_REQUEST_ADDRESS, speed,
    82             &address);
     82        int rc = async_req_4_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
     83            IPC_M_USBHC_REQUEST_ADDRESS, preferred, strict, speed, &address);
    8384       
    8485        async_exchange_end(exch);
     
    132133}
    133134
    134 
    135 static void unregister_control_endpoint_on_default_address(
    136     usb_hc_connection_t *connection)
     135/** Change address of connected device.
     136 * This function automatically updates the backing connection to point to
     137 * the new address. It also unregisterrs the old endpoint and registers
     138 * a new one.
     139 * This creates whole bunch of problems:
     140 *  1. All pipes using this wire are broken because they are not
     141 *     registered for new address
     142 *  2. All other pipes for this device are using wrong address,
     143 *     possibly targeting completely different device
     144 *
     145 * @param pipe Control endpoint pipe (session must be already started).
     146 * @param new_address New USB address to be set (in native endianness).
     147 * @return Error code.
     148 */
     149static int usb_request_set_address(usb_pipe_t *pipe, usb_address_t new_address,
     150    usb_hc_connection_t *hc_conn)
    137151{
    138         usb_device_connection_t dev_conn;
    139         int rc = usb_device_connection_initialize_on_default_address(&dev_conn,
    140             connection);
    141         if (rc != EOK) {
    142                 return;
    143         }
    144 
    145         usb_pipe_t ctrl_pipe;
    146         rc = usb_pipe_initialize_default_control(&ctrl_pipe, &dev_conn);
    147         if (rc != EOK) {
    148                 return;
    149         }
    150 
    151         usb_pipe_unregister(&ctrl_pipe, connection);
     152        if ((new_address < 0) || (new_address >= USB11_ADDRESS_MAX)) {
     153                return EINVAL;
     154        }
     155        assert(pipe);
     156        assert(hc_conn);
     157        assert(pipe->wire != NULL);
     158
     159        const uint16_t addr = uint16_host2usb((uint16_t)new_address);
     160
     161        int rc = usb_control_request_set(pipe,
     162            USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
     163            USB_DEVREQ_SET_ADDRESS, addr, 0, NULL, 0);
     164
     165        if (rc != EOK) {
     166                return rc;
     167        }
     168
     169        /* TODO: prevent others from accessing the wire now. */
     170        if (usb_pipe_unregister(pipe, hc_conn) != EOK) {
     171                usb_log_warning(
     172                    "Failed to unregister the old pipe on address change.\n");
     173        }
     174        /* The address is already changed so set it in the wire */
     175        pipe->wire->address = new_address;
     176        rc = usb_pipe_register(pipe, 0, hc_conn);
     177        if (rc != EOK)
     178                return EADDRNOTAVAIL;
     179
     180        return EOK;
    152181}
    153182
     
    171200 *
    172201 * @param[in] parent Parent device (i.e. the hub device).
    173  * @param[in] connection Connection to host controller.
     202 * @param[in] connection Connection to host controller. Must be non-null.
    174203 * @param[in] dev_speed New device speed.
    175204 * @param[in] enable_port Function for enabling signaling through the port the
     
    177206 * @param[in] arg Any data argument to @p enable_port.
    178207 * @param[out] assigned_address USB address of the device.
    179  * @param[in] dev_ops Child device ops.
     208 * @param[in] dev_ops Child device ops. Will use default if not provided.
    180209 * @param[in] new_dev_data Arbitrary pointer to be stored in the child
    181  *      as @c driver_data.
     210 *      as @c driver_data. Will allocate and assign usb_hub_attached_device_t
     211 *      structure if NULL.
    182212 * @param[out] new_fun Storage where pointer to allocated child function
    183  *      will be written.
     213 *      will be written. Must be non-null.
    184214 * @return Error code.
     215 * @retval EINVAL Either connection or new_fun is a NULL pointer.
    185216 * @retval ENOENT Connection to HC not opened.
    186217 * @retval EADDRNOTAVAIL Failed retrieving free address from host controller.
     
    195226    ddf_dev_ops_t *dev_ops, void *new_dev_data, ddf_fun_t **new_fun)
    196227{
    197         assert(connection != NULL);
     228        if (new_fun == NULL || connection == NULL)
     229                return EINVAL;
     230
    198231        // FIXME: this is awful, we are accessing directly the structure.
     232        // TODO: Why not use provided connection?
    199233        usb_hc_connection_t hc_conn = {
    200234                .hc_handle = connection->hc_handle,
     
    215249        }
    216250
    217 
    218251        /*
    219252         * Request new address.
    220253         */
    221         usb_address_t dev_addr = usb_hc_request_address(&hc_conn, dev_speed);
     254        usb_address_t dev_addr =
     255            usb_hc_request_address(&hc_conn, 0, false, dev_speed);
    222256        if (dev_addr < 0) {
    223257                rc = EADDRNOTAVAIL;
     
    240274
    241275        usb_pipe_t ctrl_pipe;
    242         rc = usb_pipe_initialize_default_control(&ctrl_pipe,
    243             &dev_conn);
     276        rc = usb_pipe_initialize_default_control(&ctrl_pipe, &dev_conn);
    244277        if (rc != EOK) {
    245278                rc = ENOTCONN;
     
    248281
    249282        do {
    250                 rc = usb_pipe_register_with_speed(&ctrl_pipe, dev_speed, 0,
    251                     &hc_conn);
    252                 if (rc != EOK) {
     283                rc = usb_hc_request_address(&hc_conn, USB_ADDRESS_DEFAULT,
     284                    true, dev_speed);
     285                if (rc == ENOENT) {
    253286                        /* Do not overheat the CPU ;-). */
    254287                        async_usleep(ENDPOINT_0_0_REGISTER_ATTEMPT_DELAY_USEC);
    255288                }
    256         } while (rc != EOK);
     289        } while (rc == ENOENT);
     290        if (rc < 0) {
     291                goto leave_release_free_address;
     292        }
     293
     294        /* Register control pipe on default address. */
     295        rc = usb_pipe_register(&ctrl_pipe, 0, &hc_conn);
     296        if (rc != EOK) {
     297                rc = ENOTCONN;
     298                goto leave_release_default_address;
     299        }
     300
    257301        struct timeval end_time;
    258302
     
    267311         * above might use much of this time so we should only wait to fill
    268312         * up the 100ms quota*/
    269         suseconds_t elapsed = tv_sub(&end_time, &start_time);
     313        const suseconds_t elapsed = tv_sub(&end_time, &start_time);
    270314        if (elapsed < 100000) {
    271315                async_usleep(100000 - elapsed);
    272316        }
    273317
    274         /*
    275          * Endpoint is registered. We can enable the port and change
    276          * device address.
    277          */
     318        /* Endpoint is registered. We can enable the port and change address. */
    278319        rc = enable_port(arg);
    279320        if (rc != EOK) {
     
    287328        async_usleep(10000);
    288329
     330        /* Get max_packet_size value. */
    289331        rc = usb_pipe_probe_default_control(&ctrl_pipe);
    290332        if (rc != EOK) {
     
    293335        }
    294336
    295         rc = usb_request_set_address(&ctrl_pipe, dev_addr);
     337        rc = usb_request_set_address(&ctrl_pipe, dev_addr, &hc_conn);
    296338        if (rc != EOK) {
    297339                rc = ESTALL;
     
    299341        }
    300342
    301         /*
    302          * Address changed. We can release the original endpoint, thus
    303          * allowing other to access the default address.
    304          */
    305         unregister_control_endpoint_on_default_address(&hc_conn);
    306 
    307         /*
    308          * Time to register the new endpoint.
    309          */
    310         rc = usb_pipe_register(&ctrl_pipe, 0, &hc_conn);
    311         if (rc != EOK) {
    312                 goto leave_release_free_address;
    313         }
    314 
    315         /*
    316          * It is time to register the device with devman.
    317          */
     343        /* Address changed. We can release the default, thus
     344         * allowing other to access the default address. */
     345        usb_hc_unregister_device(&hc_conn, USB_ADDRESS_DEFAULT);
     346
     347        /* Register the device with devman. */
    318348        /* FIXME: create device_register that will get opened ctrl pipe. */
    319349        ddf_fun_t *child_fun;
    320         rc = usb_device_register_child_in_devman(dev_addr, dev_conn.hc_handle,
     350        rc = usb_device_register_child_in_devman(&ctrl_pipe,
    321351            parent, dev_ops, new_dev_data, &child_fun);
    322352        if (rc != EOK) {
    323                 rc = ESTALL;
    324353                goto leave_release_free_address;
    325354        }
    326355
    327         /*
    328          * And now inform the host controller about the handle.
    329          */
    330         usb_hub_attached_device_t new_device = {
     356        const usb_hub_attached_device_t new_device = {
    331357                .address = dev_addr,
    332358                .fun = child_fun,
    333359        };
     360
     361
     362        /* Inform the host controller about the handle. */
    334363        rc = usb_hc_register_device(&hc_conn, &new_device);
    335364        if (rc != EOK) {
     365                /* We know nothing about that data. */
     366                if (new_dev_data)
     367                        child_fun->driver_data = NULL;
     368                /* The child function is already created. */
     369                ddf_fun_destroy(child_fun);
    336370                rc = EDESTADDRREQ;
    337371                goto leave_release_free_address;
    338372        }
    339373
    340 
    341         /*
    342          * And we are done.
    343          */
    344374        if (assigned_address != NULL) {
    345375                *assigned_address = dev_addr;
    346376        }
    347         if (new_fun != NULL) {
    348                 *new_fun = child_fun;
    349         }
     377
     378        *new_fun = child_fun;
    350379
    351380        rc = EOK;
     
    357386         */
    358387leave_release_default_address:
    359         usb_pipe_unregister(&ctrl_pipe, &hc_conn);
     388        usb_hc_unregister_device(&hc_conn, USB_ADDRESS_DEFAULT);
    360389
    361390leave_release_free_address:
    362         usb_hc_unregister_device(&hc_conn, dev_addr);
     391        /* This might be either 0:0 or dev_addr:0 */
     392        if (usb_pipe_unregister(&ctrl_pipe, &hc_conn) != EOK)
     393                usb_log_warning("%s: Failed to unregister default pipe.\n",
     394                    __FUNCTION__);
     395
     396        if (usb_hc_unregister_device(&hc_conn, dev_addr) != EOK)
     397                usb_log_warning("%s: Failed to unregister device.\n",
     398                    __FUNCTION__);
    363399
    364400close_connection:
    365401        if (usb_hc_connection_close(&hc_conn) != EOK)
    366                 usb_log_warning("usb_hc_new_device_wrapper(): Failed to close "
    367                     "connection.\n");
     402                usb_log_warning("%s: Failed to close hc connection.\n",
     403                    __FUNCTION__);
    368404
    369405        return rc;
  • uspace/lib/usbdev/src/pipes.c

    rc2e50d7 r54464f6a  
    5656        async_exch_t *exch = async_exchange_begin(sess);
    5757       
    58         /*
    59          * We are sending special value as a handle - zero - to get
    60          * handle of the parent function (that handle was used
    61          * when registering our device @p dev.
    62          */
    6358        sysarg_t address;
    64         int rc = async_req_2_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
    65             IPC_M_USB_GET_ADDRESS, 0, &address);
     59        int rc = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
     60            IPC_M_USB_GET_MY_ADDRESS, &address);
    6661       
    6762        async_exchange_end(exch);
     
    8075int usb_device_get_assigned_interface(const ddf_dev_t *device)
    8176{
     77        assert(device);
    8278        async_sess_t *parent_sess =
    8379            devman_parent_device_connect(EXCHANGE_ATOMIC, device->handle,
  • uspace/lib/usbdev/src/pipesinit.c

    rc2e50d7 r54464f6a  
    192192        }
    193193
    194         if (ep_mapping->pipe == NULL) {
    195                 return EBADMEM;
    196         }
    197194        if (ep_mapping->present) {
    198195                return EEXISTS;
    199196        }
    200197
    201         int rc = usb_pipe_initialize(ep_mapping->pipe, wire,
     198        int rc = usb_pipe_initialize(&ep_mapping->pipe, wire,
    202199            ep_no, description.transfer_type, endpoint->max_packet_size,
    203200            description.direction);
     
    254251 *
    255252 * The mapping array is expected to conform to following rules:
    256  * - @c pipe must point to already allocated structure with uninitialized pipe
     253 * - @c pipe must be uninitialized pipe
    257254 * - @c description must point to prepared endpoint description
    258255 * - @c descriptor does not need to be initialized (will be overwritten)
     
    297294        }
    298295
    299         /*
    300          * Go through the mapping and set all endpoints to not present.
    301          */
    302         size_t i;
    303         for (i = 0; i < mapping_count; i++) {
     296        /* Go through the mapping and set all endpoints to not present. */
     297        for (size_t i = 0; i < mapping_count; i++) {
    304298                mapping[i].present = false;
    305299                mapping[i].descriptor = NULL;
     
    307301        }
    308302
    309         /*
    310          * Prepare the descriptor parser.
    311          */
     303        /* Prepare the descriptor parser. */
    312304        const usb_dp_parser_t dp_parser = {
    313305                .nesting = descriptor_nesting
     
    454446 * @return Error code.
    455447 */
    456 int usb_pipe_register(usb_pipe_t *pipe,
    457     unsigned int interval,
    458     usb_hc_connection_t *hc_connection)
    459 {
    460         return usb_pipe_register_with_speed(pipe, USB_SPEED_MAX + 1,
    461             interval, hc_connection);
    462 }
    463 
    464 /** Register endpoint with a speed at the host controller.
    465  *
    466  * You will rarely need to use this function because it is needed only
    467  * if the registered endpoint is of address 0 and there is no other way
    468  * to tell speed of the device at address 0.
    469  *
    470  * @param pipe Pipe to be registered.
    471  * @param speed Speed of the device
    472  *      (invalid speed means use previously specified one).
    473  * @param interval Polling interval.
    474  * @param hc_connection Connection to the host controller (must be opened).
    475  * @return Error code.
    476  */
    477 int usb_pipe_register_with_speed(usb_pipe_t *pipe, usb_speed_t speed,
    478     unsigned int interval,
     448int usb_pipe_register(usb_pipe_t *pipe, unsigned interval,
    479449    usb_hc_connection_t *hc_connection)
    480450{
    481451        assert(pipe);
    482452        assert(hc_connection);
    483        
     453
    484454        if (!usb_hc_connection_is_opened(hc_connection))
    485455                return EBADF;
    486        
     456
    487457        const usb_target_t target =
    488458            {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }};
    489 #define _PACK2(high, low) (((high) << 16) + (low))
    490 #define _PACK3(high, middle, low) (((((high) << 8) + (middle)) << 8) + (low))
    491        
     459#define _PACK2(high, low) (((high & 0xffff) << 16) | (low & 0xffff))
     460
    492461        async_exch_t *exch = async_exchange_begin(hc_connection->hc_sess);
    493462        int rc = async_req_4_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    494463            IPC_M_USBHC_REGISTER_ENDPOINT, target.packed,
    495             _PACK3(speed, pipe->transfer_type, pipe->direction),
     464            _PACK2(pipe->transfer_type, pipe->direction),
    496465            _PACK2(pipe->max_packet_size, interval));
    497466        async_exchange_end(exch);
    498        
     467
    499468#undef _PACK2
    500 #undef _PACK3
    501        
    502469        return rc;
    503470}
  • uspace/lib/usbdev/src/recognise.c

    rc2e50d7 r54464f6a  
    3535#include <sys/types.h>
    3636#include <fibril_synch.h>
     37#include <usb/debug.h>
     38#include <usb/dev/hub.h>
    3739#include <usb/dev/pipes.h>
    3840#include <usb/dev/recognise.h>
     
    5052
    5153/** DDF operations of child devices. */
    52 ddf_dev_ops_t child_ops = {
     54static ddf_dev_ops_t child_ops = {
    5355        .interfaces[USB_DEV_IFACE] = &usb_iface_hub_child_impl
    5456};
     
    6466#define BCD_ARGS(a) BCD_INT((a)), BCD_FRAC((a))
    6567
    66 /* FIXME: make this dynamic */
    67 #define MATCH_STRING_MAX 256
    68 
    6968/** Add formatted match id.
    7069 *
     
    7574 */
    7675static int usb_add_match_id(match_id_list_t *matches, int score,
    77     const char *format, ...)
     76    const char *match_str)
    7877{
    79         char *match_str = NULL;
    80         match_id_t *match_id = NULL;
    81         int rc;
    82        
    83         match_str = malloc(MATCH_STRING_MAX + 1);
    84         if (match_str == NULL) {
    85                 rc = ENOMEM;
    86                 goto failure;
    87         }
    88 
    89         /*
    90          * FIXME: replace with dynamic allocation of exact size
    91          */
    92         va_list args;
    93         va_start(args, format   );
    94         vsnprintf(match_str, MATCH_STRING_MAX, format, args);
    95         match_str[MATCH_STRING_MAX] = 0;
    96         va_end(args);
    97 
    98         match_id = create_match_id();
     78        assert(matches);
     79
     80        match_id_t *match_id = create_match_id();
    9981        if (match_id == NULL) {
    100                 rc = ENOMEM;
    101                 goto failure;
     82                return ENOMEM;
    10283        }
    10384
     
    10788
    10889        return EOK;
    109        
    110 failure:
    111         if (match_str != NULL) {
    112                 free(match_str);
    113         }
    114         if (match_id != NULL) {
    115                 match_id->id = NULL;
    116                 delete_match_id(match_id);
    117         }
    118        
    119         return rc;
    12090}
    12191
     
    12999#define ADD_MATCHID_OR_RETURN(match_ids, score, format, ...) \
    130100        do { \
    131                 int __rc = usb_add_match_id((match_ids), (score), \
    132                     format, ##__VA_ARGS__); \
     101                char *str = NULL; \
     102                int __rc = asprintf(&str, format, ##__VA_ARGS__); \
     103                if (__rc > 0) { \
     104                        __rc = usb_add_match_id((match_ids), (score), str); \
     105                } \
    133106                if (__rc != EOK) { \
     107                        free(str); \
    134108                        return __rc; \
    135109                } \
     
    150124    match_id_list_t *matches)
    151125{
    152         if (desc_interface == NULL) {
    153                 return EINVAL;
    154         }
    155         if (matches == NULL) {
     126        if (desc_interface == NULL || matches == NULL) {
    156127                return EINVAL;
    157128        }
     
    314285    match_id_list_t *matches)
    315286{
     287        assert(ctrl_pipe);
    316288        int rc;
    317289        /*
     
    336308/** Probe for device kind and register it in devman.
    337309 *
    338  * @param[in] address Address of the (unknown) attached device.
    339  * @param[in] hc_handle Handle of the host controller.
     310 * @param[in] ctrl_pipe Control pipe to the device.
    340311 * @param[in] parent Parent device.
    341  * @param[in] dev_ops Child device ops.
     312 * @param[in] dev_ops Child device ops. Default child_ops will be used if NULL.
    342313 * @param[in] dev_data Arbitrary pointer to be stored in the child
    343314 *      as @c driver_data.
     
    346317 * @return Error code.
    347318 */
    348 int usb_device_register_child_in_devman(usb_address_t address,
    349     devman_handle_t hc_handle, ddf_dev_t *parent,
    350     ddf_dev_ops_t *dev_ops, void *dev_data, ddf_fun_t **child_fun)
     319int usb_device_register_child_in_devman(usb_pipe_t *ctrl_pipe,
     320    ddf_dev_t *parent, ddf_dev_ops_t *dev_ops, void *dev_data,
     321    ddf_fun_t **child_fun)
    351322{
    352         size_t this_device_name_index;
     323        if (child_fun == NULL || ctrl_pipe == NULL)
     324                return EINVAL;
     325
     326        if (!dev_ops && dev_data) {
     327                usb_log_warning("Using standard fun ops with arbitrary "
     328                    "driver data. This does not have to work.\n");
     329        }
    353330
    354331        fibril_mutex_lock(&device_name_index_mutex);
    355         this_device_name_index = device_name_index;
    356         device_name_index++;
     332        const size_t this_device_name_index = device_name_index++;
    357333        fibril_mutex_unlock(&device_name_index_mutex);
    358334
    359335        ddf_fun_t *child = NULL;
    360         char *child_name = NULL;
    361336        int rc;
    362         usb_device_connection_t dev_connection;
    363         usb_pipe_t ctrl_pipe;
    364 
    365         rc = usb_device_connection_initialize(&dev_connection, hc_handle, address);
    366         if (rc != EOK) {
    367                 goto failure;
    368         }
    369 
    370         rc = usb_pipe_initialize_default_control(&ctrl_pipe,
    371             &dev_connection);
    372         if (rc != EOK) {
    373                 goto failure;
    374         }
    375         rc = usb_pipe_probe_default_control(&ctrl_pipe);
    376         if (rc != EOK) {
    377                 goto failure;
    378         }
    379337
    380338        /*
     
    382340         * naming etc., something more descriptive could be created.
    383341         */
    384         rc = asprintf(&child_name, "usb%02zu_a%d",
    385             this_device_name_index, address);
     342        char child_name[12]; /* The format is: "usbAB_aXYZ", length 11 */
     343        rc = snprintf(child_name, sizeof(child_name),
     344            "usb%02zu_a%d", this_device_name_index, ctrl_pipe->wire->address);
    386345        if (rc < 0) {
    387346                goto failure;
     
    401360
    402361        child->driver_data = dev_data;
    403 
    404         rc = usb_device_create_match_ids(&ctrl_pipe, &child->match_ids);
     362        /* Store the attached device in fun driver data if there is no
     363         * other data */
     364        if (!dev_data) {
     365                usb_hub_attached_device_t *new_device = ddf_fun_data_alloc(
     366                    child, sizeof(usb_hub_attached_device_t));
     367                if (!new_device) {
     368                        rc = ENOMEM;
     369                        goto failure;
     370                }
     371                new_device->address = ctrl_pipe->wire->address;
     372                new_device->fun = child;
     373        }
     374
     375
     376        rc = usb_device_create_match_ids(ctrl_pipe, &child->match_ids);
    405377        if (rc != EOK) {
    406378                goto failure;
     
    412384        }
    413385
    414         if (child_fun != NULL) {
    415                 *child_fun = child;
    416         }
    417 
     386        *child_fun = child;
    418387        return EOK;
    419388
    420389failure:
    421390        if (child != NULL) {
    422                 child->name = NULL;
     391                /* We know nothing about the data if it came from outside. */
     392                if (dev_data) {
     393                        child->driver_data = NULL;
     394                }
    423395                /* This takes care of match_id deallocation as well. */
    424396                ddf_fun_destroy(child);
    425397        }
    426         if (child_name != NULL) {
    427                 free(child_name);
    428         }
    429398
    430399        return rc;
  • uspace/lib/usbdev/src/request.c

    rc2e50d7 r54464f6a  
    250250}
    251251
    252 /** Change address of connected device.
    253  * This function automatically updates the backing connection to point to
    254  * the new address.
    255  *
    256  * @param pipe Control endpoint pipe (session must be already started).
    257  * @param new_address New USB address to be set (in native endianness).
    258  * @return Error code.
    259  */
    260 int usb_request_set_address(usb_pipe_t *pipe,
    261     usb_address_t new_address)
    262 {
    263         if ((new_address < 0) || (new_address >= USB11_ADDRESS_MAX)) {
    264                 return EINVAL;
    265         }
    266 
    267         uint16_t addr = uint16_host2usb((uint16_t)new_address);
    268 
    269         int rc = usb_control_request_set(pipe,
    270             USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
    271             USB_DEVREQ_SET_ADDRESS,
    272             addr, 0,
    273             NULL, 0);
    274 
    275         if (rc != EOK) {
    276                 return rc;
    277         }
    278 
    279         assert(pipe->wire != NULL);
    280         /* TODO: prevent other from accessing wire now. */
    281         pipe->wire->address = new_address;
    282 
    283         return EOK;
    284 }
    285 
    286252/** Retrieve USB descriptor of a USB device.
    287253 *
Note: See TracChangeset for help on using the changeset viewer.