Changes in / [c39544a:da55d5b] in mainline


Ignore:
Location:
uspace
Files:
4 deleted
8 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/usbkbd/usbkbd.ma

    rc39544a rda55d5b  
    1110 usb&class=hid
    2 10 usb&hid
  • uspace/lib/drv/generic/remote_usbhc.c

    rc39544a rda55d5b  
    4242#define USB_MAX_PAYLOAD_SIZE 1020
    4343
    44 static void remote_usbhc_get_address(device_t *, void *, ipc_callid_t, ipc_call_t *);
    4544static void remote_usbhc_get_buffer(device_t *, void *, ipc_callid_t, ipc_call_t *);
    4645static void remote_usbhc_interrupt_out(device_t *, void *, ipc_callid_t, ipc_call_t *);
    4746static void remote_usbhc_interrupt_in(device_t *, void *, ipc_callid_t, ipc_call_t *);
    48 static void remote_usbhc_control_write_setup(device_t *, void *, ipc_callid_t, ipc_call_t *);
    49 static void remote_usbhc_control_write_data(device_t *, void *, ipc_callid_t, ipc_call_t *);
    50 static void remote_usbhc_control_write_status(device_t *, void *, ipc_callid_t, ipc_call_t *);
    51 static void remote_usbhc_control_read_setup(device_t *, void *, ipc_callid_t, ipc_call_t *);
    52 static void remote_usbhc_control_read_data(device_t *, void *, ipc_callid_t, ipc_call_t *);
    53 static void remote_usbhc_control_read_status(device_t *, void *, ipc_callid_t, ipc_call_t *);
    54 //static void remote_usbhc(device_t *, void *, ipc_callid_t, ipc_call_t *);
     47//static void remote_usb(device_t *, void *, ipc_callid_t, ipc_call_t *);
    5548
    5649/** Remote USB interface operations. */
    5750static remote_iface_func_ptr_t remote_usbhc_iface_ops [] = {
    58         remote_usbhc_get_address,
    59         remote_usbhc_get_buffer,
    60         remote_usbhc_interrupt_out,
    61         remote_usbhc_interrupt_in,
    62         remote_usbhc_control_write_setup,
    63         remote_usbhc_control_write_data,
    64         remote_usbhc_control_write_status,
    65         remote_usbhc_control_read_setup,
    66         remote_usbhc_control_read_data,
    67         remote_usbhc_control_read_status
     51        &remote_usbhc_get_buffer,
     52        &remote_usbhc_interrupt_out,
     53        &remote_usbhc_interrupt_in
    6854};
    6955
     
    8268} async_transaction_t;
    8369
    84 void remote_usbhc_get_address(device_t *device, void *iface,
    85     ipc_callid_t callid, ipc_call_t *call)
    86 {
    87         usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
    88 
    89         if (!usb_iface->tell_address) {
    90                 ipc_answer_0(callid, ENOTSUP);
    91                 return;
    92         }
    93 
    94         devman_handle_t handle = IPC_GET_ARG1(*call);
    95 
    96         usb_address_t address;
    97         int rc = usb_iface->tell_address(device, handle, &address);
    98         if (rc != EOK) {
    99                 ipc_answer_0(callid, rc);
    100         } else {
    101                 ipc_answer_1(callid, EOK, address);
    102         }
    103 }
    10470
    10571void remote_usbhc_get_buffer(device_t *device, void *iface,
     
    159125}
    160126
    161 /** Process an outgoing transfer (both OUT and SETUP).
    162  *
    163  * @param device Target device.
    164  * @param callid Initiating caller.
    165  * @param call Initiating call.
    166  * @param transfer_func Transfer function (might be NULL).
    167  */
    168 static void remote_usbhc_out_transfer(device_t *device,
    169     ipc_callid_t callid, ipc_call_t *call,
    170     usbhc_iface_transfer_out_t transfer_func)
    171 {
    172         if (!transfer_func) {
    173                 ipc_answer_0(callid, ENOTSUP);
    174                 return;
    175         }
     127void remote_usbhc_interrupt_out(device_t *device, void *iface,
     128            ipc_callid_t callid, ipc_call_t *call)
     129{
     130        usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
    176131
    177132        size_t expected_len = IPC_GET_ARG3(*call);
     
    194149        }
    195150
     151        if (!usb_iface->interrupt_out) {
     152                ipc_answer_0(callid, ENOTSUP);
     153                return;
     154        }
     155
    196156        async_transaction_t *trans = malloc(sizeof(async_transaction_t));
    197157        trans->caller = callid;
    198         trans->buffer = buffer;
    199         trans->size = len;
    200 
    201         int rc = transfer_func(device, target, buffer, len,
     158        trans->buffer = NULL;
     159        trans->size = 0;
     160
     161        int rc = usb_iface->interrupt_out(device, target, buffer, len,
    202162            callback_out, trans);
    203163
    204164        if (rc != EOK) {
    205165                ipc_answer_0(callid, rc);
    206                 if (buffer != NULL) {
    207                         free(buffer);
    208                 }
    209166                free(trans);
    210167        }
    211168}
    212169
    213 /** Process an incoming transfer.
    214  *
    215  * @param device Target device.
    216  * @param callid Initiating caller.
    217  * @param call Initiating call.
    218  * @param transfer_func Transfer function (might be NULL).
    219  */
    220 static void remote_usbhc_in_transfer(device_t *device,
    221     ipc_callid_t callid, ipc_call_t *call,
    222     usbhc_iface_transfer_in_t transfer_func)
    223 {
    224         if (!transfer_func) {
    225                 ipc_answer_0(callid, ENOTSUP);
    226                 return;
    227         }
     170void remote_usbhc_interrupt_in(device_t *device, void *iface,
     171            ipc_callid_t callid, ipc_call_t *call)
     172{
     173        usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
    228174
    229175        size_t len = IPC_GET_ARG3(*call);
     
    233179        };
    234180
     181        if (!usb_iface->interrupt_in) {
     182                ipc_answer_0(callid, ENOTSUP);
     183                return;
     184        }
     185
    235186        async_transaction_t *trans = malloc(sizeof(async_transaction_t));
    236187        trans->caller = callid;
     
    238189        trans->size = len;
    239190
    240         int rc = transfer_func(device, target, trans->buffer, len,
     191        int rc = usb_iface->interrupt_in(device, target, trans->buffer, len,
    241192            callback_in, trans);
    242193
     
    248199}
    249200
    250 /** Process status part of control transfer.
    251  *
    252  * @param device Target device.
    253  * @param callid Initiating caller.
    254  * @param call Initiating call.
    255  * @param direction Transfer direction (read ~ in, write ~ out).
    256  * @param transfer_in_func Transfer function for control read (might be NULL).
    257  * @param transfer_out_func Transfer function for control write (might be NULL).
    258  */
    259 static void remote_usbhc_status_transfer(device_t *device,
    260     ipc_callid_t callid, ipc_call_t *call,
    261     usb_direction_t direction,
    262     int (*transfer_in_func)(device_t *, usb_target_t,
    263         usbhc_iface_transfer_in_callback_t, void *),
    264     int (*transfer_out_func)(device_t *, usb_target_t,
    265         usbhc_iface_transfer_out_callback_t, void *))
    266 {
    267         switch (direction) {
    268                 case USB_DIRECTION_IN:
    269                         if (!transfer_in_func) {
    270                                 ipc_answer_0(callid, ENOTSUP);
    271                                 return;
    272                         }
    273                         break;
    274                 case USB_DIRECTION_OUT:
    275                         if (!transfer_out_func) {
    276                                 ipc_answer_0(callid, ENOTSUP);
    277                                 return;
    278                         }
    279                         break;
    280                 default:
    281                         assert(false && "unreachable code");
    282                         break;
    283         }
    284 
    285         usb_target_t target = {
    286                 .address = IPC_GET_ARG1(*call),
    287                 .endpoint = IPC_GET_ARG2(*call)
    288         };
    289 
    290         async_transaction_t *trans = malloc(sizeof(async_transaction_t));
    291         trans->caller = callid;
    292         trans->buffer = NULL;
    293         trans->size = 0;
    294 
    295         int rc;
    296         switch (direction) {
    297                 case USB_DIRECTION_IN:
    298                         rc = transfer_in_func(device, target,
    299                             callback_in, trans);
    300                         break;
    301                 case USB_DIRECTION_OUT:
    302                         rc = transfer_out_func(device, target,
    303                             callback_out, trans);
    304                         break;
    305                 default:
    306                         assert(false && "unreachable code");
    307                         break;
    308         }
    309 
    310         if (rc != EOK) {
    311                 ipc_answer_0(callid, rc);
    312                 free(trans);
    313         }
    314         return;
    315 }
    316 
    317 
    318 void remote_usbhc_interrupt_out(device_t *device, void *iface,
    319     ipc_callid_t callid, ipc_call_t *call)
    320 {
    321         usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
    322         assert(usb_iface != NULL);
    323 
    324         return remote_usbhc_out_transfer(device, callid, call,
    325             usb_iface->interrupt_out);
    326 }
    327 
    328 void remote_usbhc_interrupt_in(device_t *device, void *iface,
    329     ipc_callid_t callid, ipc_call_t *call)
    330 {
    331         usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
    332         assert(usb_iface != NULL);
    333 
    334         return remote_usbhc_in_transfer(device, callid, call,
    335             usb_iface->interrupt_in);
    336 }
    337 
    338 void remote_usbhc_control_write_setup(device_t *device, void *iface,
    339     ipc_callid_t callid, ipc_call_t *call)
    340 {
    341         usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
    342         assert(usb_iface != NULL);
    343 
    344         return remote_usbhc_out_transfer(device, callid, call,
    345             usb_iface->control_write_setup);
    346 }
    347 
    348 void remote_usbhc_control_write_data(device_t *device, void *iface,
    349     ipc_callid_t callid, ipc_call_t *call)
    350 {
    351         usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
    352         assert(usb_iface != NULL);
    353 
    354         return remote_usbhc_out_transfer(device, callid, call,
    355             usb_iface->control_write_data);
    356 }
    357 
    358 void remote_usbhc_control_write_status(device_t *device, void *iface,
    359     ipc_callid_t callid, ipc_call_t *call)
    360 {
    361         usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
    362         assert(usb_iface != NULL);
    363 
    364         return remote_usbhc_status_transfer(device, callid, call,
    365             USB_DIRECTION_IN, usb_iface->control_write_status, NULL);
    366 }
    367 
    368 void remote_usbhc_control_read_setup(device_t *device, void *iface,
    369     ipc_callid_t callid, ipc_call_t *call)
    370 {
    371         usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
    372         assert(usb_iface != NULL);
    373 
    374         return remote_usbhc_out_transfer(device, callid, call,
    375             usb_iface->control_read_setup);
    376 }
    377 
    378 void remote_usbhc_control_read_data(device_t *device, void *iface,
    379             ipc_callid_t callid, ipc_call_t *call)
    380 {
    381         usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
    382         assert(usb_iface != NULL);
    383 
    384         return remote_usbhc_in_transfer(device, callid, call,
    385             usb_iface->control_read_data);
    386 }
    387 
    388 void remote_usbhc_control_read_status(device_t *device, void *iface,
    389             ipc_callid_t callid, ipc_call_t *call)
    390 {
    391         usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
    392         assert(usb_iface != NULL);
    393 
    394         return remote_usbhc_status_transfer(device, callid, call,
    395             USB_DIRECTION_OUT, NULL, usb_iface->control_read_status);
    396 }
    397 
    398 
    399201
    400202/**
  • uspace/lib/drv/include/usbhc_iface.h

    rc39544a rda55d5b  
    9292 */
    9393typedef enum {
    94         /** Tell USB address assigned to device.
    95          * Parameters:
    96          * - devman handle id
    97          * Answer:
    98          * - EINVAL - unknown handle or handle not managed by this driver
    99          * - ENOTSUP - operation not supported by HC (shall not happen)
    100          * - arbitrary error code if returned by remote implementation
    101          * - EOK - handle found, first parameter contains the USB address
    102          */
    103         IPC_M_USBHC_GET_ADDRESS,
    104 
    10594        /** Asks for data buffer.
    10695         * See explanation at usb_iface_funcs_t.
     
    166155    usb_transaction_outcome_t, size_t, void *);
    167156
    168 
    169 /** Out transfer processing function prototype. */
    170 typedef int (*usbhc_iface_transfer_out_t)(device_t *, usb_target_t,
    171     void *, size_t,
    172     usbhc_iface_transfer_out_callback_t, void *);
    173 
    174 /** Setup transfer processing function prototype. */
    175 typedef usbhc_iface_transfer_out_t usbhc_iface_transfer_setup_t;
    176 
    177 /** In transfer processing function prototype. */
    178 typedef int (*usbhc_iface_transfer_in_t)(device_t *, usb_target_t,
    179     void *, size_t,
    180     usbhc_iface_transfer_in_callback_t, void *);
    181 
    182157/** USB devices communication interface. */
    183158typedef struct {
    184         int (*tell_address)(device_t *, devman_handle_t, usb_address_t *);
    185 
    186         usbhc_iface_transfer_out_t interrupt_out;
    187         usbhc_iface_transfer_in_t interrupt_in;
    188 
    189         usbhc_iface_transfer_setup_t control_write_setup;
    190         usbhc_iface_transfer_out_t control_write_data;
    191         int (*control_write_status)(device_t *, usb_target_t,
     159        int (*interrupt_out)(device_t *, usb_target_t,
     160            void *, size_t,
     161            usbhc_iface_transfer_out_callback_t, void *);
     162        int (*interrupt_in)(device_t *, usb_target_t,
     163            void *, size_t,
    192164            usbhc_iface_transfer_in_callback_t, void *);
    193 
    194         usbhc_iface_transfer_setup_t control_read_setup;
    195         usbhc_iface_transfer_in_t control_read_data;
    196         int (*control_read_status)(device_t *, usb_target_t,
    197             usbhc_iface_transfer_out_callback_t, void *);
    198165} usbhc_iface_t;
    199166
  • uspace/lib/usb/Makefile

    rc39544a rda55d5b  
    3434SOURCES = \
    3535        src/hcdhubd.c \
    36         src/hcdrv.c \
    37         src/hubdrv.c \
    3836        src/localdrv.c \
    39         src/remotedrv.c \
    4037        src/usb.c \
    4138        src/usbdrv.c
  • uspace/lib/usb/include/usb/hcdhubd.h

    rc39544a rda55d5b  
    3737
    3838#include <adt/list.h>
    39 #include <bool.h>
    4039#include <driver.h>
    4140#include <usb/usb.h>
     
    176175int usb_hc_async_wait_for(usb_handle_t);
    177176
    178 int usb_hc_add_child_device(device_t *, const char *, const char *, bool);
    179177
    180178#endif
  • uspace/lib/usb/include/usb/usbdrv.h

    rc39544a rda55d5b  
    4848    void *, size_t, size_t *, usb_handle_t *);
    4949
    50 int usb_drv_async_control_write_setup(int, usb_target_t,
    51     void *, size_t, usb_handle_t *);
    52 int usb_drv_async_control_write_data(int, usb_target_t,
    53     void *, size_t, usb_handle_t *);
    54 int usb_drv_async_control_write_status(int, usb_target_t,
    55     usb_handle_t *);
    56 
    57 int usb_drv_async_control_read_setup(int, usb_target_t,
    58     void *, size_t, usb_handle_t *);
    59 int usb_drv_async_control_read_data(int, usb_target_t,
    60     void *, size_t, size_t *, usb_handle_t *);
    61 int usb_drv_async_control_read_status(int, usb_target_t,
    62     usb_handle_t *);
    63 
    6450int usb_drv_async_wait_for(usb_handle_t);
    6551
  • uspace/lib/usb/src/hcdhubd.c

    rc39544a rda55d5b  
    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>
     
    4040#include <bool.h>
    4141#include <errno.h>
    42 #include <str_error.h>
    4342#include <usb/classes/hub.h>
    4443
    45 #include "hcdhubd_private.h"
     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. */
     52static LIST_INITIALIZE(hc_list);
     53
     54/** Our HC driver. */
     55static usb_hc_driver_t *hc_driver = NULL;
     56
     57static usbhc_iface_t usb_interface = {
     58        .interrupt_out = NULL,
     59        .interrupt_in = NULL
     60};
     61
     62static device_ops_t usb_device_ops = {
     63        .interfaces[USBHC_DEV_IFACE] = &usb_interface
     64};
     65
     66size_t USB_HUB_MAX_DESCRIPTOR_SIZE = 71;
     67
     68uint8_t USB_HUB_DESCRIPTOR_TYPE = 0x29;
     69
     70//*********************************************
     71//
     72//  various utils
     73//
     74//*********************************************
     75
     76void * 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
     104usb_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
     131static void set_hub_address(usb_hc_device_t *hc, usb_address_t address);
     132
     133usb_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}
    46151
    47152/** Callback when new device is detected and must be handled by this driver.
    48153 *
    49154 * @param dev New device.
    50  * @return Error code.
     155 * @return Error code.hub added, hurrah!\n"
    51156 */
    52157static int add_device(device_t *dev) {
     158        /*
     159         * FIXME: use some magic to determine whether hub or another HC
     160         * was connected.
     161         */
    53162        bool is_hc = str_cmp(dev->name, USB_HUB_DEVICE_NAME) != 0;
    54163        printf("%s: add_device(name=\"%s\")\n", hc_driver->name, dev->name);
     
    58167                 * We are the HC itself.
    59168                 */
    60                 return usb_add_hc_device(dev);
     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
     183                /*
     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
    61234        } 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
    62238                /*
    63                  * We are some (maybe deeply nested) hub.
     239                 * We are some (probably deeply nested) hub.
    64240                 * Thus, assign our own operations and explore already
    65241                 * connected devices.
    66242                 */
    67                 return usb_add_hub_device(dev);
     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 */
     281static 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 */
     321static 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                }
    68370        }
    69371}
     
    89391        hc_driver = hc;
    90392        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();
    91400
    92401        /*
     
    105414 * @return Error code.
    106415 */
    107 int usb_hcd_add_root_hub(usb_hc_device_t *dev)
    108 {
    109         char *id;
    110         int rc = asprintf(&id, "usb&hc=%s&hub", dev->generic->name);
    111         if (rc <= 0) {
    112                 return rc;
    113         }
    114 
    115         rc = usb_hc_add_child_device(dev->generic, USB_HUB_DEVICE_NAME, id, true);
    116         if (rc != EOK) {
    117                 free(id);
    118         }
    119 
    120         return rc;
    121 }
    122 
    123 /** Info about child device. */
    124 struct child_device_info {
    125         device_t *parent;
    126         const char *name;
    127         const char *match_id;
    128 };
    129 
    130 /** Adds a child device fibril worker. */
    131 static int fibril_add_child_device(void *arg)
    132 {
    133         struct child_device_info *child_info
    134             = (struct child_device_info *) arg;
     416int usb_hcd_add_root_hub(usb_hc_device_t *dev) {
    135417        int rc;
    136418
    137         device_t *child = create_device();
     419        /*
     420         * Announce presence of child device.
     421         */
     422        device_t *hub = NULL;
    138423        match_id_t *match_id = NULL;
    139424
    140         if (child == NULL) {
     425        hub = create_device();
     426        if (hub == NULL) {
    141427                rc = ENOMEM;
    142428                goto failure;
    143429        }
    144         child->name = child_info->name;
     430        hub->name = USB_HUB_DEVICE_NAME;
    145431
    146432        match_id = create_match_id();
     
    149435                goto failure;
    150436        }
    151         match_id->id = child_info->match_id;
    152         match_id->score = 10;
    153         add_match_id(&child->match_ids, match_id);
    154 
    155         printf("%s: adding child device `%s' with match \"%s\"\n",
    156             hc_driver->name, child->name, match_id->id);
    157         rc = child_device_register(child, child_info->parent);
    158         printf("%s: child device `%s' registration: %s\n",
    159             hc_driver->name, child->name, str_error(rc));
    160 
     437
     438        char *id;
     439        rc = asprintf(&id, "usb&hc=%s&hub", dev->generic->name);
     440        if (rc <= 0) {
     441                rc = ENOMEM;
     442                goto failure;
     443        }
     444
     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);
    161451        if (rc != EOK) {
    162452                goto failure;
    163453        }
    164454
    165         goto leave;
     455        printf("%s: registered root hub\n", dev->generic->name);
     456        return EOK;
    166457
    167458failure:
    168         if (child != NULL) {
    169                 child->name = NULL;
    170                 delete_device(child);
    171         }
    172 
    173         if (match_id != NULL) {
    174                 match_id->id = NULL;
    175                 delete_match_id(match_id);
    176         }
    177 
    178 leave:
    179         free(arg);
    180         return EOK;
    181 }
    182 
    183 /** Adds a child.
    184  * Due to deadlock in devman when parent registers child that oughts to be
    185  * driven by the same task, the child adding is done in separate fibril.
    186  * Not optimal, but it works.
    187  * Update: not under all circumstances the new fibril is successful either.
    188  * Thus the last parameter to let the caller choose.
    189  *
    190  * @param parent Parent device.
    191  * @param name Device name.
    192  * @param match_id Match id.
    193  * @param create_fibril Whether to run the addition in new fibril.
    194  * @return Error code.
    195  */
    196 int usb_hc_add_child_device(device_t *parent, const char *name,
    197     const char *match_id, bool create_fibril)
    198 {
    199         printf("%s: about to add child device `%s' (%s)\n", hc_driver->name,
    200             name, match_id);
    201 
    202         struct child_device_info *child_info
    203             = malloc(sizeof(struct child_device_info));
    204 
    205         child_info->parent = parent;
    206         child_info->name = name;
    207         child_info->match_id = match_id;
    208 
    209         if (create_fibril) {
    210                 fid_t fibril = fibril_create(fibril_add_child_device, child_info);
    211                 if (!fibril) {
    212                         return ENOMEM;
    213                 }
    214                 fibril_add_ready(fibril);
    215         } else {
    216                 fibril_add_child_device(child_info);
    217         }
    218 
    219         return EOK;
    220 }
    221 
    222 /** Tell USB address of given device.
    223  *
    224  * @param handle Devman handle of the device.
    225  * @return USB device address or error code.
    226  */
    227 usb_address_t usb_get_address_by_handle(devman_handle_t handle)
    228 {
    229         /* TODO: search list of attached devices. */
    230         return ENOENT;
     459        if (hub != NULL) {
     460                hub->name = NULL;
     461                delete_device(hub);
     462        }
     463        delete_match_id(match_id);
     464
     465        return rc;
    231466}
    232467
  • uspace/lib/usb/src/usbdrv.c

    rc39544a rda55d5b  
    6464         * Call parent hub to obtain device handle of respective HC.
    6565         */
    66 
    67         /*
    68          * FIXME: currently we connect always to virtual host controller.
    69          */
    70         int rc;
    71         devman_handle_t handle;
    72 
    73         rc = devman_device_get_handle("/vhc", &handle, 0);
    74         if (rc != EOK) {
    75                 return rc;
    76         }
    77        
    78         int phone = devman_device_connect(handle, 0);
    79 
    80         return phone;
     66        return ENOTSUP;
    8167}
    8268
     
    8975usb_address_t usb_drv_get_my_address(int phone, device_t *dev)
    9076{
    91         ipcarg_t address;
    92         int rc = async_req_1_1(phone, IPC_M_USBHC_GET_ADDRESS,
    93             dev->handle, &address);
    94 
    95         if (rc != EOK) {
    96                 return rc;
    97         }
    98 
    99         return (usb_address_t) address;
     77        return ENOTSUP;
    10078}
    10179
     
    345323}
    346324
    347 /** Start control write transfer. */
    348 int usb_drv_async_control_write_setup(int phone, usb_target_t target,
    349     void *buffer, size_t size,
    350     usb_handle_t *handle)
    351 {
    352         return async_send_buffer(phone,
    353             IPC_M_USBHC_CONTROL_WRITE_SETUP,
    354             target,
    355             buffer, size,
    356             handle);
    357 }
    358 
    359 /** Send data during control write transfer. */
    360 int usb_drv_async_control_write_data(int phone, usb_target_t target,
    361     void *buffer, size_t size,
    362     usb_handle_t *handle)
    363 {
    364         return async_send_buffer(phone,
    365             IPC_M_USBHC_CONTROL_WRITE_DATA,
    366             target,
    367             buffer, size,
    368             handle);
    369 }
    370 
    371 /** Finalize control write transfer. */
    372 int usb_drv_async_control_write_status(int phone, usb_target_t target,
    373     usb_handle_t *handle)
    374 {
    375         return async_recv_buffer(phone,
    376             IPC_M_USBHC_CONTROL_WRITE_STATUS,
    377             target,
    378             NULL, 0, NULL,
    379             handle);
    380 }
    381 
    382 /** Start control read transfer. */
    383 int usb_drv_async_control_read_setup(int phone, usb_target_t target,
    384     void *buffer, size_t size,
    385     usb_handle_t *handle)
    386 {
    387         return async_send_buffer(phone,
    388             IPC_M_USBHC_CONTROL_READ_SETUP,
    389             target,
    390             buffer, size,
    391             handle);
    392 }
    393 
    394 /** Read data during control read transfer. */
    395 int usb_drv_async_control_read_data(int phone, usb_target_t target,
    396     void *buffer, size_t size, size_t *actual_size,
    397     usb_handle_t *handle)
    398 {
    399         return async_recv_buffer(phone,
    400             IPC_M_USBHC_CONTROL_READ_DATA,
    401             target,
    402             buffer, size, actual_size,
    403             handle);
    404 }
    405 
    406 /** Finalize control read transfer. */
    407 int usb_drv_async_control_read_status(int phone, usb_target_t target,
    408     usb_handle_t *handle)
    409 {
    410         return async_send_buffer(phone,
    411             IPC_M_USBHC_CONTROL_READ_STATUS,
    412             target,
    413             NULL, 0,
    414             handle);
    415 }
    416 
    417325/**
    418326 * @}
Note: See TracChangeset for help on using the changeset viewer.