Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/usb/src/hcdhubd.c

    rdac43be re4dbfda  
    3131 */
    3232/** @file
    33  * @brief Common stuff for both HC driver and hub driver.
     33 * @brief HC driver and hub driver (implementation).
    3434 */
    3535#include <usb/hcdhubd.h>
    3636#include <usb/devreq.h>
    3737#include <usbhc_iface.h>
    38 #include <usb/descriptor.h>
    3938#include <driver.h>
    4039#include <bool.h>
    4140#include <errno.h>
    42 #include <usb/classes/hub.h>
    43 
    44 #include "hcdhubd_private.h"
     41
     42#define USB_HUB_DEVICE_NAME "usbhub"
     43
     44/** List of handled host controllers. */
     45static LIST_INITIALIZE(hc_list);
     46
     47/** Our HC driver. */
     48static usb_hc_driver_t *hc_driver = NULL;
     49
     50static usbhc_iface_t usb_interface = {
     51        .interrupt_out = NULL,
     52        .interrupt_in = NULL
     53};
     54
     55static device_ops_t usb_device_ops = {
     56        .interfaces[USBHC_DEV_IFACE] = &usb_interface
     57};
     58
     59static void set_hub_address(usb_hc_device_t *hc, usb_address_t address);
    4560
    4661/** Callback when new device is detected and must be handled by this driver.
     
    4964 * @return Error code.
    5065 */
    51 static int add_device(device_t *dev) {
     66static int add_device(device_t *dev)
     67{
     68        /*
     69         * FIXME: use some magic to determine whether hub or another HC
     70         * was connected.
     71         */
    5272        bool is_hc = str_cmp(dev->name, USB_HUB_DEVICE_NAME) != 0;
    5373        printf("%s: add_device(name=\"%s\")\n", hc_driver->name, dev->name);
     
    5777                 * We are the HC itself.
    5878                 */
    59                 return usb_add_hc_device(dev);
     79                usb_hc_device_t *hc_dev = malloc(sizeof(usb_hc_device_t));
     80                list_initialize(&hc_dev->link);
     81                hc_dev->transfer_ops = NULL;
     82
     83                hc_dev->generic = dev;
     84                dev->ops = &usb_device_ops;
     85                hc_dev->generic->driver_data = hc_dev;
     86
     87                int rc = hc_driver->add_hc(hc_dev);
     88                if (rc != EOK) {
     89                        free(hc_dev);
     90                        return rc;
     91                }
     92
     93                /*
     94                 * FIXME: The following line causes devman to hang.
     95                 * Will investigate later why.
     96                 */
     97                // add_device_to_class(dev, "usbhc");
     98
     99                list_append(&hc_dev->link, &hc_list);
     100
     101                return EOK;
    60102        } else {
     103                usb_hc_device_t *hc = list_get_instance(hc_list.next, usb_hc_device_t, link);
     104                set_hub_address(hc, 5);
     105
    61106                /*
    62                  * We are some (maybe deeply nested) hub.
     107                 * We are some (probably deeply nested) hub.
    63108                 * Thus, assign our own operations and explore already
    64109                 * connected devices.
    65110                 */
    66                 return usb_add_hub_device(dev);
     111
     112                return ENOTSUP;
     113        }
     114}
     115
     116/** Sample usage of usb_hc_async functions.
     117 * This function sets hub address using standard SET_ADDRESS request.
     118 *
     119 * @warning This function shall be removed once you are familiar with
     120 * the usb_hc_ API.
     121 *
     122 * @param hc Host controller the hub belongs to.
     123 * @param address New hub address.
     124 */
     125static void set_hub_address(usb_hc_device_t *hc, usb_address_t address)
     126{
     127        printf("%s: setting hub address to %d\n", hc->generic->name, address);
     128        usb_target_t target = {0, 0};
     129        usb_handle_t handle;
     130        int rc;
     131
     132        usb_device_request_setup_packet_t setup_packet = {
     133                .request_type = 0,
     134                .request = USB_DEVREQ_SET_ADDRESS,
     135                .index = 0,
     136                .length = 0,
     137        };
     138        setup_packet.value = address;
     139
     140        rc = usb_hc_async_control_write_setup(hc, target,
     141            &setup_packet, sizeof(setup_packet), &handle);
     142        if (rc != EOK) {
     143                return;
     144        }
     145
     146        rc = usb_hc_async_wait_for(handle);
     147        if (rc != EOK) {
     148                return;
     149        }
     150
     151        rc = usb_hc_async_control_write_status(hc, target, &handle);
     152        if (rc != EOK) {
     153                return;
     154        }
     155
     156        rc = usb_hc_async_wait_for(handle);
     157        if (rc != EOK) {
     158                return;
     159        }
     160
     161        printf("%s: hub address changed\n", hc->generic->name);
     162}
     163
     164/** Check changes on all known hubs.
     165 */
     166static void check_hub_changes(void)
     167{
     168        /*
     169         * Iterate through all HCs.
     170         */
     171        link_t *link_hc;
     172        for (link_hc = hc_list.next;
     173            link_hc != &hc_list;
     174            link_hc = link_hc->next) {
     175                usb_hc_device_t *hc = list_get_instance(link_hc,
     176                    usb_hc_device_t, link);
     177                /*
     178                 * Iterate through all their hubs.
     179                 */
     180                link_t *link_hub;
     181                for (link_hub = hc->hubs.next;
     182                    link_hub != &hc->hubs;
     183                    link_hub = link_hub->next) {
     184                        usb_hcd_hub_info_t *hub = list_get_instance(link_hub,
     185                            usb_hcd_hub_info_t, link);
     186
     187                        /*
     188                         * Check status change pipe of this hub.
     189                         */
     190                        usb_target_t target = {
     191                                .address = hub->device->address,
     192                                .endpoint = 1
     193                        };
     194
     195                        // FIXME: count properly
     196                        size_t byte_length = (hub->port_count / 8) + 1;
     197
     198                        void *change_bitmap = malloc(byte_length);
     199                        size_t actual_size;
     200                        usb_handle_t handle;
     201
     202                        /*
     203                         * Send the request.
     204                         * FIXME: check returned value for possible errors
     205                         */
     206                        usb_hc_async_interrupt_in(hc, target,
     207                            change_bitmap, byte_length, &actual_size,
     208                            &handle);
     209
     210                        usb_hc_async_wait_for(handle);
     211
     212                        /*
     213                         * TODO: handle the changes.
     214                         */
     215                }
    67216        }
    68217}
     
    85234 * @return Error code.
    86235 */
    87 int usb_hcd_main(usb_hc_driver_t *hc) {
     236int usb_hcd_main(usb_hc_driver_t *hc)
     237{
    88238        hc_driver = hc;
    89239        hc_driver_generic.name = hc->name;
     240
     241        /*
     242         * Launch here fibril that will periodically check all
     243         * attached hubs for status change.
     244         * WARN: This call will effectively do nothing.
     245         */
     246        check_hub_changes();
    90247
    91248        /*
Note: See TracChangeset for help on using the changeset viewer.