Changes in / [da55d5b:c39544a] in mainline


Ignore:
Location:
uspace
Files:
4 added
8 edited

Legend:

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

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

    rda55d5b rc39544a  
    4242#define USB_MAX_PAYLOAD_SIZE 1020
    4343
     44static void remote_usbhc_get_address(device_t *, void *, ipc_callid_t, ipc_call_t *);
    4445static void remote_usbhc_get_buffer(device_t *, void *, ipc_callid_t, ipc_call_t *);
    4546static void remote_usbhc_interrupt_out(device_t *, void *, ipc_callid_t, ipc_call_t *);
    4647static void remote_usbhc_interrupt_in(device_t *, void *, ipc_callid_t, ipc_call_t *);
    47 //static void remote_usb(device_t *, void *, ipc_callid_t, ipc_call_t *);
     48static void remote_usbhc_control_write_setup(device_t *, void *, ipc_callid_t, ipc_call_t *);
     49static void remote_usbhc_control_write_data(device_t *, void *, ipc_callid_t, ipc_call_t *);
     50static void remote_usbhc_control_write_status(device_t *, void *, ipc_callid_t, ipc_call_t *);
     51static void remote_usbhc_control_read_setup(device_t *, void *, ipc_callid_t, ipc_call_t *);
     52static void remote_usbhc_control_read_data(device_t *, void *, ipc_callid_t, ipc_call_t *);
     53static 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 *);
    4855
    4956/** Remote USB interface operations. */
    5057static remote_iface_func_ptr_t remote_usbhc_iface_ops [] = {
    51         &remote_usbhc_get_buffer,
    52         &remote_usbhc_interrupt_out,
    53         &remote_usbhc_interrupt_in
     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
    5468};
    5569
     
    6882} async_transaction_t;
    6983
     84void 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}
    70104
    71105void remote_usbhc_get_buffer(device_t *device, void *iface,
     
    125159}
    126160
    127 void 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;
     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 */
     168static 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        }
    131176
    132177        size_t expected_len = IPC_GET_ARG3(*call);
     
    149194        }
    150195
    151         if (!usb_iface->interrupt_out) {
    152                 ipc_answer_0(callid, ENOTSUP);
    153                 return;
    154         }
    155 
    156196        async_transaction_t *trans = malloc(sizeof(async_transaction_t));
    157197        trans->caller = callid;
    158         trans->buffer = NULL;
    159         trans->size = 0;
    160 
    161         int rc = usb_iface->interrupt_out(device, target, buffer, len,
     198        trans->buffer = buffer;
     199        trans->size = len;
     200
     201        int rc = transfer_func(device, target, buffer, len,
    162202            callback_out, trans);
    163203
    164204        if (rc != EOK) {
    165205                ipc_answer_0(callid, rc);
     206                if (buffer != NULL) {
     207                        free(buffer);
     208                }
    166209                free(trans);
    167210        }
    168211}
    169212
    170 void 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;
     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 */
     220static 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        }
    174228
    175229        size_t len = IPC_GET_ARG3(*call);
     
    179233        };
    180234
    181         if (!usb_iface->interrupt_in) {
    182                 ipc_answer_0(callid, ENOTSUP);
    183                 return;
    184         }
    185 
    186235        async_transaction_t *trans = malloc(sizeof(async_transaction_t));
    187236        trans->caller = callid;
     
    189238        trans->size = len;
    190239
    191         int rc = usb_iface->interrupt_in(device, target, trans->buffer, len,
     240        int rc = transfer_func(device, target, trans->buffer, len,
    192241            callback_in, trans);
    193242
     
    199248}
    200249
     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 */
     259static 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
     318void 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
     328void 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
     338void 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
     348void 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
     358void 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
     368void 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
     378void 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
     388void 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
    201399
    202400/**
  • uspace/lib/drv/include/usbhc_iface.h

    rda55d5b rc39544a  
    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
    94105        /** Asks for data buffer.
    95106         * See explanation at usb_iface_funcs_t.
     
    155166    usb_transaction_outcome_t, size_t, void *);
    156167
     168
     169/** Out transfer processing function prototype. */
     170typedef 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. */
     175typedef usbhc_iface_transfer_out_t usbhc_iface_transfer_setup_t;
     176
     177/** In transfer processing function prototype. */
     178typedef int (*usbhc_iface_transfer_in_t)(device_t *, usb_target_t,
     179    void *, size_t,
     180    usbhc_iface_transfer_in_callback_t, void *);
     181
    157182/** USB devices communication interface. */
    158183typedef struct {
    159         int (*interrupt_out)(device_t *, usb_target_t,
    160             void *, size_t,
     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,
     192            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,
    161197            usbhc_iface_transfer_out_callback_t, void *);
    162         int (*interrupt_in)(device_t *, usb_target_t,
    163             void *, size_t,
    164             usbhc_iface_transfer_in_callback_t, void *);
    165198} usbhc_iface_t;
    166199
  • uspace/lib/usb/Makefile

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

    rda55d5b rc39544a  
    3737
    3838#include <adt/list.h>
     39#include <bool.h>
    3940#include <driver.h>
    4041#include <usb/usb.h>
     
    175176int usb_hc_async_wait_for(usb_handle_t);
    176177
     178int usb_hc_add_child_device(device_t *, const char *, const char *, bool);
    177179
    178180#endif
  • uspace/lib/usb/include/usb/usbdrv.h

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

    rda55d5b rc39544a  
    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>
     
    4040#include <bool.h>
    4141#include <errno.h>
     42#include <str_error.h>
    4243#include <usb/classes/hub.h>
    4344
    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 }
     45#include "hcdhubd_private.h"
    15146
    15247/** Callback when new device is detected and must be handled by this driver.
    15348 *
    15449 * @param dev New device.
    155  * @return Error code.hub added, hurrah!\n"
     50 * @return Error code.
    15651 */
    15752static int add_device(device_t *dev) {
    158         /*
    159          * FIXME: use some magic to determine whether hub or another HC
    160          * was connected.
    161          */
    16253        bool is_hc = str_cmp(dev->name, USB_HUB_DEVICE_NAME) != 0;
    16354        printf("%s: add_device(name=\"%s\")\n", hc_driver->name, dev->name);
     
    16758                 * We are the HC itself.
    16859                 */
    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 
     60                return usb_add_hc_device(dev);
     61        } else {
    18362                /*
    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.
     63                 * We are some (maybe deeply nested) hub.
    24064                 * Thus, assign our own operations and explore already
    24165                 * connected devices.
    24266                 */
    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                 }
     67                return usb_add_hub_device(dev);
    37068        }
    37169}
     
    39189        hc_driver = hc;
    39290        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();
    40091
    40192        /*
     
    414105 * @return Error code.
    415106 */
    416 int usb_hcd_add_root_hub(usb_hc_device_t *dev) {
     107int 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. */
     124struct 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. */
     131static int fibril_add_child_device(void *arg)
     132{
     133        struct child_device_info *child_info
     134            = (struct child_device_info *) arg;
    417135        int rc;
    418136
    419         /*
    420          * Announce presence of child device.
    421          */
    422         device_t *hub = NULL;
     137        device_t *child = create_device();
    423138        match_id_t *match_id = NULL;
    424139
    425         hub = create_device();
    426         if (hub == NULL) {
     140        if (child == NULL) {
    427141                rc = ENOMEM;
    428142                goto failure;
    429143        }
    430         hub->name = USB_HUB_DEVICE_NAME;
     144        child->name = child_info->name;
    431145
    432146        match_id = create_match_id();
     
    435149                goto failure;
    436150        }
    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);
     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
    451161        if (rc != EOK) {
    452162                goto failure;
    453163        }
    454164
    455         printf("%s: registered root hub\n", dev->generic->name);
     165        goto leave;
     166
     167failure:
     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
     178leave:
     179        free(arg);
    456180        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;
     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 */
     196int 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 */
     227usb_address_t usb_get_address_by_handle(devman_handle_t handle)
     228{
     229        /* TODO: search list of attached devices. */
     230        return ENOENT;
    466231}
    467232
  • uspace/lib/usb/src/usbdrv.c

    rda55d5b rc39544a  
    6464         * Call parent hub to obtain device handle of respective HC.
    6565         */
    66         return ENOTSUP;
     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;
    6781}
    6882
     
    7589usb_address_t usb_drv_get_my_address(int phone, device_t *dev)
    7690{
    77         return ENOTSUP;
     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;
    78100}
    79101
     
    323345}
    324346
     347/** Start control write transfer. */
     348int 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. */
     360int 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. */
     372int 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. */
     383int 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. */
     395int 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. */
     407int 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
    325417/**
    326418 * @}
Note: See TracChangeset for help on using the changeset viewer.