Ignore:
File:
1 edited

Legend:

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

    rda55d5b re4dbfda  
    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>
    4341
    4442#define USB_HUB_DEVICE_NAME "usbhub"
    45 
    46 #define USB_KBD_DEVICE_NAME "hid"
    47 
    48 
    49 
    5043
    5144/** List of handled host controllers. */
     
    6457};
    6558
    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 
    13159static void set_hub_address(usb_hc_device_t *hc, usb_address_t address);
    13260
    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 }
    151 
    15261/** Callback when new device is detected and must be handled by this driver.
    15362 *
    15463 * @param dev New device.
    155  * @return Error code.hub added, hurrah!\n"
    156  */
    157 static int add_device(device_t *dev) {
     64 * @return Error code.
     65 */
     66static int add_device(device_t *dev)
     67{
    15868        /*
    15969         * FIXME: use some magic to determine whether hub or another HC
     
    16777                 * We are the HC itself.
    16878                 */
    169                 usb_hc_device_t *hc_dev = malloc(sizeof (usb_hc_device_t));
     79                usb_hc_device_t *hc_dev = malloc(sizeof(usb_hc_device_t));
    17080                list_initialize(&hc_dev->link);
    17181                hc_dev->transfer_ops = NULL;
     
    18999                list_append(&hc_dev->link, &hc_list);
    190100
    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);
    230101                return EOK;
    231 
    232 
    233 
    234102        } else {
    235103                usb_hc_device_t *hc = list_get_instance(hc_list.next, usb_hc_device_t, link);
     
    241109                 * connected devices.
    242110                 */
    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;
     111
     112                return ENOTSUP;
    269113        }
    270114}
     
    279123 * @param address New hub address.
    280124 */
    281 static void set_hub_address(usb_hc_device_t *hc, usb_address_t address) {
     125static void set_hub_address(usb_hc_device_t *hc, usb_address_t address)
     126{
    282127        printf("%s: setting hub address to %d\n", hc->generic->name, address);
    283128        usb_target_t target = {0, 0};
     
    294139
    295140        rc = usb_hc_async_control_write_setup(hc, target,
    296                         &setup_packet, sizeof (setup_packet), &handle);
     141            &setup_packet, sizeof(setup_packet), &handle);
    297142        if (rc != EOK) {
    298143                return;
     
    319164/** Check changes on all known hubs.
    320165 */
    321 static void check_hub_changes(void) {
     166static void check_hub_changes(void)
     167{
    322168        /*
    323169         * Iterate through all HCs.
     
    325171        link_t *link_hc;
    326172        for (link_hc = hc_list.next;
    327                         link_hc != &hc_list;
    328                         link_hc = link_hc->next) {
     173            link_hc != &hc_list;
     174            link_hc = link_hc->next) {
    329175                usb_hc_device_t *hc = list_get_instance(link_hc,
    330                                 usb_hc_device_t, link);
     176                    usb_hc_device_t, link);
    331177                /*
    332178                 * Iterate through all their hubs.
     
    334180                link_t *link_hub;
    335181                for (link_hub = hc->hubs.next;
    336                                 link_hub != &hc->hubs;
    337                                 link_hub = link_hub->next) {
     182                    link_hub != &hc->hubs;
     183                    link_hub = link_hub->next) {
    338184                        usb_hcd_hub_info_t *hub = list_get_instance(link_hub,
    339                                         usb_hcd_hub_info_t, link);
     185                            usb_hcd_hub_info_t, link);
    340186
    341187                        /*
     
    359205                         */
    360206                        usb_hc_async_interrupt_in(hc, target,
    361                                         change_bitmap, byte_length, &actual_size,
    362                                         &handle);
     207                            change_bitmap, byte_length, &actual_size,
     208                            &handle);
    363209
    364210                        usb_hc_async_wait_for(handle);
     
    388234 * @return Error code.
    389235 */
    390 int usb_hcd_main(usb_hc_driver_t *hc) {
     236int usb_hcd_main(usb_hc_driver_t *hc)
     237{
    391238        hc_driver = hc;
    392239        hc_driver_generic.name = hc->name;
     
    414261 * @return Error code.
    415262 */
    416 int usb_hcd_add_root_hub(usb_hc_device_t *dev) {
     263int usb_hcd_add_root_hub(usb_hc_device_t *dev)
     264{
     265        char *id;
     266        int rc = asprintf(&id, "usb&hc=%s&hub", dev->generic->name);
     267        if (rc <= 0) {
     268                return rc;
     269        }
     270
     271        rc = usb_hc_add_child_device(dev->generic, USB_HUB_DEVICE_NAME, id);
     272        if (rc != EOK) {
     273                free(id);
     274        }
     275
     276        return rc;
     277}
     278
     279/** Info about child device. */
     280struct child_device_info {
     281        device_t *parent;
     282        const char *name;
     283        const char *match_id;
     284};
     285
     286/** Adds a child device fibril worker. */
     287static int fibril_add_child_device(void *arg)
     288{
     289        struct child_device_info *child_info
     290            = (struct child_device_info *) arg;
    417291        int rc;
    418292
    419         /*
    420          * Announce presence of child device.
    421          */
    422         device_t *hub = NULL;
     293        device_t *child = create_device();
    423294        match_id_t *match_id = NULL;
    424295
    425         hub = create_device();
    426         if (hub == NULL) {
     296        if (child == NULL) {
    427297                rc = ENOMEM;
    428298                goto failure;
    429299        }
    430         hub->name = USB_HUB_DEVICE_NAME;
     300        child->name = child_info->name;
    431301
    432302        match_id = create_match_id();
     
    435305                goto failure;
    436306        }
    437 
    438         char *id;
    439         rc = asprintf(&id, "usb&hc=%s&hub", dev->generic->name);
    440         if (rc <= 0) {
    441                 rc = ENOMEM;
     307        match_id->id = child_info->match_id;
     308        match_id->score = 10;
     309        printf("adding child device with match \"%s\"\n", match_id->id);
     310        add_match_id(&child->match_ids, match_id);
     311
     312        rc = child_device_register(child, child_info->parent);
     313        if (rc != EOK) {
    442314                goto failure;
    443315        }
    444316
    445         match_id->id = id;
    446         match_id->score = 30;
    447 
    448         add_match_id(&hub->match_ids, match_id);
    449 
    450         rc = child_device_register(hub, dev->generic);
    451         if (rc != EOK) {
    452                 goto failure;
    453         }
    454 
    455         printf("%s: registered root hub\n", dev->generic->name);
     317        goto leave;
     318
     319failure:
     320        if (child != NULL) {
     321                child->name = NULL;
     322                delete_device(child);
     323        }
     324
     325        if (match_id != NULL) {
     326                match_id->id = NULL;
     327                delete_match_id(match_id);
     328        }
     329
     330leave:
     331        free(arg);
     332        return rc;
     333}
     334
     335/** Adds a child.
     336 * Due to deadlock in devman when parent registers child that oughts to be
     337 * driven by the same task, the child adding is done in separate fibril.
     338 * Not optimal, but it works.
     339 *
     340 * @param parent Parent device.
     341 * @param name Device name.
     342 * @param match_id Match id.
     343 * @return Error code.
     344 */
     345int usb_hc_add_child_device(device_t *parent, const char *name,
     346    const char *match_id)
     347{
     348        struct child_device_info *child_info
     349            = malloc(sizeof(struct child_device_info));
     350
     351        child_info->parent = parent;
     352        child_info->name = name;
     353        child_info->match_id = match_id;
     354
     355        fid_t fibril = fibril_create(fibril_add_child_device, child_info);
     356        if (!fibril) {
     357                return ENOMEM;
     358        }
     359        fibril_add_ready(fibril);
     360
    456361        return EOK;
    457 
    458 failure:
    459         if (hub != NULL) {
    460                 hub->name = NULL;
    461                 delete_device(hub);
    462         }
    463         delete_match_id(match_id);
    464 
    465         return rc;
    466362}
    467363
Note: See TracChangeset for help on using the changeset viewer.