Changeset ef75332 in mainline for uspace/lib/usb/src/hcdhubd.c


Ignore:
Timestamp:
2010-11-27T08:07:18Z (14 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
36bcf84f
Parents:
8e423a2d (diff), dac43be (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 with vojtechhorky/

File:
1 edited

Legend:

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

    r8e423a2d ref75332  
    3131 */
    3232/** @file
    33  * @brief HC driver and hub driver (implementation).
     33 * @brief Common stuff for both HC driver and hub driver.
    3434 */
    3535#include <usb/hcdhubd.h>
     
    4242#include <usb/classes/hub.h>
    4343
    44 #define USB_HUB_DEVICE_NAME "usbhub"
    45 
    46 #define USB_KBD_DEVICE_NAME "hid"
    47 
    48 
    49 
    50 
    51 /** List of handled host controllers. */
    52 static LIST_INITIALIZE(hc_list);
    53 
    54 /** Our HC driver. */
    55 static usb_hc_driver_t *hc_driver = NULL;
    56 
    57 static usbhc_iface_t usb_interface = {
    58         .interrupt_out = NULL,
    59         .interrupt_in = NULL
    60 };
    61 
    62 static device_ops_t usb_device_ops = {
    63         .interfaces[USBHC_DEV_IFACE] = &usb_interface
    64 };
    65 
    66 size_t USB_HUB_MAX_DESCRIPTOR_SIZE = 71;
    67 
    68 uint8_t USB_HUB_DESCRIPTOR_TYPE = 0x29;
    69 
    70 //*********************************************
    71 //
    72 //  various utils
    73 //
    74 //*********************************************
    75 
    76 void * usb_serialize_hub_descriptor(usb_hub_descriptor_t * descriptor) {
    77         //base size
    78         size_t size = 7;
    79         //variable size according to port count
    80         size_t var_size = descriptor->ports_count / 8 + ((descriptor->ports_count % 8 > 0) ? 1 : 0);
    81         size += 2 * var_size;
    82         uint8_t * result = (uint8_t*) malloc(size);
    83         //size
    84         result[0] = size;
    85         //descriptor type
    86         result[1] = USB_DESCTYPE_HUB;
    87         result[2] = descriptor->ports_count;
    88         /// @fixme handling of endianness??
    89         result[3] = descriptor->hub_characteristics / 256;
    90         result[4] = descriptor->hub_characteristics % 256;
    91         result[5] = descriptor->pwr_on_2_good_time;
    92         result[6] = descriptor->current_requirement;
    93 
    94         size_t i;
    95         for (i = 0; i < var_size; ++i) {
    96                 result[7 + i] = descriptor->devices_removable[i];
    97         }
    98         for (i = 0; i < var_size; ++i) {
    99                 result[7 + var_size + i] = 255;
    100         }
    101         return result;
    102 }
    103 
    104 usb_hub_descriptor_t * usb_deserialize_hub_desriptor(void * serialized_descriptor) {
    105         uint8_t * sdescriptor = (uint8_t*) serialized_descriptor;
    106         if (sdescriptor[1] != USB_DESCTYPE_HUB) return NULL;
    107         usb_hub_descriptor_t * result = (usb_hub_descriptor_t*) malloc(sizeof (usb_hub_descriptor_t));
    108         //uint8_t size = sdescriptor[0];
    109         result->ports_count = sdescriptor[2];
    110         /// @fixme handling of endianness??
    111         result->hub_characteristics = sdescriptor[4] + 256 * sdescriptor[3];
    112         result->pwr_on_2_good_time = sdescriptor[5];
    113         result->current_requirement = sdescriptor[6];
    114         size_t var_size = result->ports_count / 8 + ((result->ports_count % 8 > 0) ? 1 : 0);
    115         result->devices_removable = (uint8_t*) malloc(var_size);
    116 
    117         size_t i;
    118         for (i = 0; i < var_size; ++i) {
    119                 result->devices_removable[i] = sdescriptor[7 + i];
    120         }
    121         return result;
    122 }
    123 
    124 
    125 //*********************************************
    126 //
    127 //  hub driver code
    128 //
    129 //*********************************************
    130 
    131 static void set_hub_address(usb_hc_device_t *hc, usb_address_t address);
    132 
    133 usb_hcd_hub_info_t * usb_create_hub_info(device_t * device) {
    134         usb_hcd_hub_info_t* result = (usb_hcd_hub_info_t*) malloc(sizeof (usb_hcd_hub_info_t));
    135         //get parent device
    136         /// @TODO this code is not correct
    137         device_t * my_hcd = device;
    138         while (my_hcd->parent)
    139                 my_hcd = my_hcd->parent;
    140         //dev->
    141         printf("%s: owner hcd found: %s\n", hc_driver->name, my_hcd->name);
    142         //we add the hub into the first hc
    143         //link_t *link_hc = hc_list.next;
    144         //usb_hc_device_t *hc = list_get_instance(link_hc,
    145         //              usb_hc_device_t, link);
    146         //must get generic device info
    147 
    148 
    149         return result;
    150 }
     44#include "hcdhubd_private.h"
    15145
    15246/** Callback when new device is detected and must be handled by this driver.
    15347 *
    15448 * @param dev New device.
    155  * @return Error code.hub added, hurrah!\n"
     49 * @return Error code.
    15650 */
    15751static int add_device(device_t *dev) {
    158         /*
    159          * FIXME: use some magic to determine whether hub or another HC
    160          * was connected.
    161          */
    16252        bool is_hc = str_cmp(dev->name, USB_HUB_DEVICE_NAME) != 0;
    16353        printf("%s: add_device(name=\"%s\")\n", hc_driver->name, dev->name);
     
    16757                 * We are the HC itself.
    16858                 */
    169                 usb_hc_device_t *hc_dev = malloc(sizeof (usb_hc_device_t));
    170                 list_initialize(&hc_dev->link);
    171                 hc_dev->transfer_ops = NULL;
    172 
    173                 hc_dev->generic = dev;
    174                 dev->ops = &usb_device_ops;
    175                 hc_dev->generic->driver_data = hc_dev;
    176 
    177                 int rc = hc_driver->add_hc(hc_dev);
    178                 if (rc != EOK) {
    179                         free(hc_dev);
    180                         return rc;
    181                 }
    182 
     59                return usb_add_hc_device(dev);
     60        } else {
    18361                /*
    184                  * FIXME: The following line causes devman to hang.
    185                  * Will investigate later why.
    186                  */
    187                 // add_device_to_class(dev, "usbhc");
    188 
    189                 list_append(&hc_dev->link, &hc_list);
    190 
    191                 //add keyboard
    192                 /// @TODO this is not correct code
    193                
    194                 /*
    195                  * Announce presence of child device.
    196                  */
    197                 device_t *kbd = NULL;
    198                 match_id_t *match_id = NULL;
    199 
    200                 kbd = create_device();
    201                 if (kbd == NULL) {
    202                         printf("ERROR: enomem\n");
    203                 }
    204                 kbd->name = USB_KBD_DEVICE_NAME;
    205 
    206                 match_id = create_match_id();
    207                 if (match_id == NULL) {
    208                         printf("ERROR: enomem\n");
    209                 }
    210 
    211                 char *id;
    212                 rc = asprintf(&id, USB_KBD_DEVICE_NAME);
    213                 if (rc <= 0) {
    214                         printf("ERROR: enomem\n");
    215                         return rc;
    216                 }
    217 
    218                 match_id->id = id;
    219                 match_id->score = 30;
    220 
    221                 add_match_id(&kbd->match_ids, match_id);
    222 
    223                 rc = child_device_register(kbd, dev);
    224                 if (rc != EOK) {
    225                         printf("ERROR: cannot register kbd\n");
    226                         return rc;
    227                 }
    228 
    229                 printf("%s: registered root hub\n", dev->name);
    230                 return EOK;
    231 
    232 
    233 
    234         } else {
    235                 usb_hc_device_t *hc = list_get_instance(hc_list.next, usb_hc_device_t, link);
    236                 set_hub_address(hc, 5);
    237 
    238                 /*
    239                  * We are some (probably deeply nested) hub.
     62                 * We are some (maybe deeply nested) hub.
    24063                 * Thus, assign our own operations and explore already
    24164                 * connected devices.
    24265                 */
    243                 //insert hub into list
    244                 //find owner hcd
    245                 device_t * my_hcd = dev;
    246                 while (my_hcd->parent)
    247                         my_hcd = my_hcd->parent;
    248                 //dev->
    249                 printf("%s: owner hcd found: %s\n", hc_driver->name, my_hcd->name);
    250                 my_hcd = dev;
    251                 while (my_hcd->parent)
    252                         my_hcd = my_hcd->parent;
    253                 //dev->
    254 
    255                 printf("%s: owner hcd found: %s\n", hc_driver->name, my_hcd->name);
    256                
    257                 //create the hub structure
    258                 usb_hcd_hub_info_t * hub_info = usb_create_hub_info(dev);
    259 
    260 
    261                 //append into the list
    262                 //we add the hub into the first hc
    263                 list_append(&hub_info->link, &hc->hubs);
    264 
    265 
    266 
    267                 return EOK;
    268                 //return ENOTSUP;
    269         }
    270 }
    271 
    272 /** Sample usage of usb_hc_async functions.
    273  * This function sets hub address using standard SET_ADDRESS request.
    274  *
    275  * @warning This function shall be removed once you are familiar with
    276  * the usb_hc_ API.
    277  *
    278  * @param hc Host controller the hub belongs to.
    279  * @param address New hub address.
    280  */
    281 static void set_hub_address(usb_hc_device_t *hc, usb_address_t address) {
    282         printf("%s: setting hub address to %d\n", hc->generic->name, address);
    283         usb_target_t target = {0, 0};
    284         usb_handle_t handle;
    285         int rc;
    286 
    287         usb_device_request_setup_packet_t setup_packet = {
    288                 .request_type = 0,
    289                 .request = USB_DEVREQ_SET_ADDRESS,
    290                 .index = 0,
    291                 .length = 0,
    292         };
    293         setup_packet.value = address;
    294 
    295         rc = usb_hc_async_control_write_setup(hc, target,
    296                         &setup_packet, sizeof (setup_packet), &handle);
    297         if (rc != EOK) {
    298                 return;
    299         }
    300 
    301         rc = usb_hc_async_wait_for(handle);
    302         if (rc != EOK) {
    303                 return;
    304         }
    305 
    306         rc = usb_hc_async_control_write_status(hc, target, &handle);
    307         if (rc != EOK) {
    308                 return;
    309         }
    310 
    311         rc = usb_hc_async_wait_for(handle);
    312         if (rc != EOK) {
    313                 return;
    314         }
    315 
    316         printf("%s: hub address changed\n", hc->generic->name);
    317 }
    318 
    319 /** Check changes on all known hubs.
    320  */
    321 static void check_hub_changes(void) {
    322         /*
    323          * Iterate through all HCs.
    324          */
    325         link_t *link_hc;
    326         for (link_hc = hc_list.next;
    327                         link_hc != &hc_list;
    328                         link_hc = link_hc->next) {
    329                 usb_hc_device_t *hc = list_get_instance(link_hc,
    330                                 usb_hc_device_t, link);
    331                 /*
    332                  * Iterate through all their hubs.
    333                  */
    334                 link_t *link_hub;
    335                 for (link_hub = hc->hubs.next;
    336                                 link_hub != &hc->hubs;
    337                                 link_hub = link_hub->next) {
    338                         usb_hcd_hub_info_t *hub = list_get_instance(link_hub,
    339                                         usb_hcd_hub_info_t, link);
    340 
    341                         /*
    342                          * Check status change pipe of this hub.
    343                          */
    344                         usb_target_t target = {
    345                                 .address = hub->device->address,
    346                                 .endpoint = 1
    347                         };
    348 
    349                         // FIXME: count properly
    350                         size_t byte_length = (hub->port_count / 8) + 1;
    351 
    352                         void *change_bitmap = malloc(byte_length);
    353                         size_t actual_size;
    354                         usb_handle_t handle;
    355 
    356                         /*
    357                          * Send the request.
    358                          * FIXME: check returned value for possible errors
    359                          */
    360                         usb_hc_async_interrupt_in(hc, target,
    361                                         change_bitmap, byte_length, &actual_size,
    362                                         &handle);
    363 
    364                         usb_hc_async_wait_for(handle);
    365 
    366                         /*
    367                          * TODO: handle the changes.
    368                          */
    369                 }
     66                return usb_add_hub_device(dev);
    37067        }
    37168}
     
    39188        hc_driver = hc;
    39289        hc_driver_generic.name = hc->name;
    393 
    394         /*
    395          * Launch here fibril that will periodically check all
    396          * attached hubs for status change.
    397          * WARN: This call will effectively do nothing.
    398          */
    399         check_hub_changes();
    40090
    40191        /*
Note: See TracChangeset for help on using the changeset viewer.