Changeset 361e61b in mainline for uspace/lib/usb/src


Ignore:
Timestamp:
2011-03-21T14:23:15Z (15 years ago)
Author:
Matej Klonfar <maklf@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
55e388a1
Parents:
c32688d (diff), 48fe0c9 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

merge with development

Location:
uspace/lib/usb/src
Files:
3 added
6 edited
1 moved

Legend:

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

    rc32688d r361e61b  
    258258}
    259259
     260/** Browser of the descriptor tree.
     261 *
     262 * @see usb_dp_walk_simple
     263 *
     264 * @param parser Descriptor parser.
     265 * @param data Data for descriptor parser.
     266 * @param root Pointer to current root of the tree.
     267 * @param depth Current nesting depth.
     268 * @param callback Callback for each found descriptor.
     269 * @param arg Custom (user) argument.
     270 */
     271static void usb_dp_browse_simple_internal(usb_dp_parser_t *parser,
     272    usb_dp_parser_data_t *data, uint8_t *root, size_t depth,
     273    void (*callback)(uint8_t *, size_t, void *), void *arg)
     274{
     275        if (root == NULL) {
     276                return;
     277        }
     278        callback(root, depth, arg);
     279        uint8_t *child = usb_dp_get_nested_descriptor(parser, data, root);
     280        do {
     281                usb_dp_browse_simple_internal(parser, data, child, depth + 1,
     282                    callback, arg);
     283                child = usb_dp_get_sibling_descriptor(parser, data,
     284                    root, child);
     285        } while (child != NULL);
     286}
     287
     288/** Browse flatten descriptor tree.
     289 *
     290 * The callback is called with following arguments: pointer to the start
     291 * of the descriptor (somewhere inside @p descriptors), depth of the nesting
     292 * (starting from 0 for the first descriptor) and the custom argument.
     293 * Note that the size of the descriptor is not passed because it can
     294 * be read from the first byte of the descriptor.
     295 *
     296 * @param descriptors Descriptor data.
     297 * @param descriptors_size Size of descriptor data (in bytes).
     298 * @param descriptor_nesting Possible descriptor nesting.
     299 * @param callback Callback for each found descriptor.
     300 * @param arg Custom (user) argument.
     301 */
     302void usb_dp_walk_simple(uint8_t *descriptors, size_t descriptors_size,
     303    usb_dp_descriptor_nesting_t *descriptor_nesting,
     304    void (*callback)(uint8_t *, size_t, void *), void *arg)
     305{
     306        if ((descriptors == NULL) || (descriptors_size == 0)
     307            || (descriptor_nesting == NULL) || (callback == NULL)) {
     308                return;
     309        }
     310
     311        usb_dp_parser_data_t data = {
     312                .data = descriptors,
     313                .size = descriptors_size,
     314                .arg = NULL
     315        };
     316
     317        usb_dp_parser_t parser = {
     318                .nesting = descriptor_nesting
     319        };
     320
     321        usb_dp_browse_simple_internal(&parser, &data, descriptors,
     322            0, callback, arg);
     323}
    260324
    261325/** @}
  • uspace/lib/usb/src/host/device_keeper.c

    rc32688d r361e61b  
    2727 */
    2828
    29 /** @addtogroup drvusbuhci
     29/** @addtogroup libusb
    3030 * @{
    3131 */
     
    3636#include <errno.h>
    3737#include <usb/debug.h>
    38 
    39 #include "device_keeper.h"
    40 
    41 /*----------------------------------------------------------------------------*/
    42 /** Initializes device keeper structure.
     38#include <usb/host/device_keeper.h>
     39
     40/*----------------------------------------------------------------------------*/
     41/** Initialize device keeper structure.
    4342 *
    4443 * @param[in] instance Memory place to initialize.
     44 *
     45 * Set all values to false/0.
    4546 */
    4647void device_keeper_init(device_keeper_t *instance)
     
    5455                instance->devices[i].occupied = false;
    5556                instance->devices[i].handle = 0;
    56                 instance->devices[i].toggle_status = 0;
    57         }
    58 }
    59 /*----------------------------------------------------------------------------*/
    60 /** Attempts to obtain address 0, blocks.
     57                instance->devices[i].toggle_status[0] = 0;
     58                instance->devices[i].toggle_status[1] = 0;
     59        }
     60}
     61/*----------------------------------------------------------------------------*/
     62/** Attempt to obtain address 0, blocks.
    6163 *
    6264 * @param[in] instance Device keeper structure to use.
     
    7678}
    7779/*----------------------------------------------------------------------------*/
    78 /** Attempts to obtain address 0, blocks.
     80/** Attempt to obtain address 0, blocks.
    7981 *
    8082 * @param[in] instance Device keeper structure to use.
     
    9092}
    9193/*----------------------------------------------------------------------------*/
    92 /** Checks setup data for signs of toggle reset.
     94/** Check setup packet data for signs of toggle reset.
    9395 *
    9496 * @param[in] instance Device keeper structure to use.
    9597 * @param[in] target Device to receive setup packet.
    9698 * @param[in] data Setup packet data.
     99 *
     100 * Really ugly one.
    97101 */
    98102void device_keeper_reset_if_need(
     
    105109            || !instance->devices[target.address].occupied) {
    106110                fibril_mutex_unlock(&instance->guard);
     111                usb_log_error("Invalid data when checking for toggle reset.\n");
    107112                return;
    108113        }
     
    114119                if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) {
    115120                        /* endpoint number is < 16, thus first byte is enough */
    116                         instance->devices[target.address].toggle_status &=
     121                        instance->devices[target.address].toggle_status[0] &=
     122                            ~(1 << data[4]);
     123                        instance->devices[target.address].toggle_status[1] &=
    117124                            ~(1 << data[4]);
    118125                }
     
    123130                /* target must be device */
    124131                if ((data[0] & 0xf) == 0) {
    125                         instance->devices[target.address].toggle_status = 0;
     132                        instance->devices[target.address].toggle_status[0] = 0;
     133                        instance->devices[target.address].toggle_status[1] = 0;
    126134                }
    127135        break;
     
    130138}
    131139/*----------------------------------------------------------------------------*/
    132 /** Gets current value of endpoint toggle.
     140/** Get current value of endpoint toggle.
    133141 *
    134142 * @param[in] instance Device keeper structure to use.
     
    136144 * @return Error code
    137145 */
    138 int device_keeper_get_toggle(device_keeper_t *instance, usb_target_t target)
    139 {
    140         assert(instance);
     146int device_keeper_get_toggle(
     147    device_keeper_t *instance, usb_target_t target, usb_direction_t direction)
     148{
     149        assert(instance);
     150        /* only control pipes are bi-directional and those do not need toggle */
     151        if (direction == USB_DIRECTION_BOTH)
     152                return ENOENT;
    141153        int ret;
    142154        fibril_mutex_lock(&instance->guard);
     
    144156            || target.address >= USB_ADDRESS_COUNT || target.address < 0
    145157            || !instance->devices[target.address].occupied) {
     158                usb_log_error("Invalid data when asking for toggle value.\n");
    146159                ret = EINVAL;
    147160        } else {
    148                 ret =
    149                     (instance->devices[target.address].toggle_status
     161                ret = (instance->devices[target.address].toggle_status[direction]
    150162                        >> target.endpoint) & 1;
    151163        }
     
    154166}
    155167/*----------------------------------------------------------------------------*/
    156 /** Sets current value of endpoint toggle.
     168/** Set current value of endpoint toggle.
    157169 *
    158170 * @param[in] instance Device keeper structure to use.
    159171 * @param[in] target Device and endpoint used.
    160  * @param[in] toggle Current toggle value.
     172 * @param[in] toggle Toggle value.
    161173 * @return Error code.
    162174 */
    163 int device_keeper_set_toggle(
    164     device_keeper_t *instance, usb_target_t target, bool toggle)
    165 {
    166         assert(instance);
     175int device_keeper_set_toggle(device_keeper_t *instance,
     176    usb_target_t target, usb_direction_t direction, bool toggle)
     177{
     178        assert(instance);
     179        /* only control pipes are bi-directional and those do not need toggle */
     180        if (direction == USB_DIRECTION_BOTH)
     181                return ENOENT;
    167182        int ret;
    168183        fibril_mutex_lock(&instance->guard);
     
    170185            || target.address >= USB_ADDRESS_COUNT || target.address < 0
    171186            || !instance->devices[target.address].occupied) {
     187                usb_log_error("Invalid data when setting toggle value.\n");
    172188                ret = EINVAL;
    173189        } else {
    174190                if (toggle) {
    175                         instance->devices[target.address].toggle_status |= (1 << target.endpoint);
     191                        instance->devices[target.address].toggle_status[direction]
     192                            |= (1 << target.endpoint);
    176193                } else {
    177                         instance->devices[target.address].toggle_status &= ~(1 << target.endpoint);
     194                        instance->devices[target.address].toggle_status[direction]
     195                            &= ~(1 << target.endpoint);
    178196                }
    179197                ret = EOK;
     
    183201}
    184202/*----------------------------------------------------------------------------*/
    185 /** Gets a free USB address
     203/** Get a free USB address
    186204 *
    187205 * @param[in] instance Device keeper structure to use.
     
    210228        instance->devices[new_address].occupied = true;
    211229        instance->devices[new_address].speed = speed;
    212         instance->devices[new_address].toggle_status = 0;
     230        instance->devices[new_address].toggle_status[0] = 0;
     231        instance->devices[new_address].toggle_status[1] = 0;
    213232        instance->last_address = new_address;
    214233        fibril_mutex_unlock(&instance->guard);
     
    216235}
    217236/*----------------------------------------------------------------------------*/
    218 /** Binds USB address to devman handle.
     237/** Bind USB address to devman handle.
    219238 *
    220239 * @param[in] instance Device keeper structure to use.
     
    234253}
    235254/*----------------------------------------------------------------------------*/
    236 /** Releases used USB address.
     255/** Release used USB address.
    237256 *
    238257 * @param[in] instance Device keeper structure to use.
     
    251270}
    252271/*----------------------------------------------------------------------------*/
    253 /** Finds USB address associated with the device
     272/** Find USB address associated with the device
    254273 *
    255274 * @param[in] instance Device keeper structure to use.
     
    274293}
    275294/*----------------------------------------------------------------------------*/
    276 /** Gets speed associated with the address
     295/** Get speed associated with the address
    277296 *
    278297 * @param[in] instance Device keeper structure to use.
  • uspace/lib/usb/src/hub.c

    rc32688d r361e61b  
    235235                goto leave_release_default_address;
    236236        }
     237        rc = usb_endpoint_pipe_probe_default_control(&ctrl_pipe);
     238        if (rc != EOK) {
     239                rc = ENOTCONN;
     240                goto leave_release_default_address;
     241        }
    237242
    238243        rc = usb_endpoint_pipe_start_session(&ctrl_pipe);
  • uspace/lib/usb/src/pipes.c

    rc32688d r361e61b  
    4242#include <assert.h>
    4343
     44#define IPC_AGAIN_DELAY (1000 * 2) /* 2ms */
     45
    4446/** Tell USB address assigned to given device.
    4547 *
     
    5153{
    5254        sysarg_t address;
    53 
    5455
    5556        /*
     
    9697}
    9798
     99/** Tell USB address assigned to given device.
     100 *
     101 * @param dev_handle Devman handle of the USB device in question.
     102 * @return USB address or negative error code.
     103 */
     104usb_address_t usb_device_get_assigned_address(devman_handle_t dev_handle)
     105{
     106        int parent_phone = devman_parent_device_connect(dev_handle,
     107            IPC_FLAG_BLOCKING);
     108        if (parent_phone < 0) {
     109                return parent_phone;
     110        }
     111
     112        sysarg_t address;
     113
     114        int rc = async_req_2_1(parent_phone, DEV_IFACE_ID(USB_DEV_IFACE),
     115            IPC_M_USB_GET_ADDRESS,
     116            dev_handle, &address);
     117
     118        if (rc != EOK) {
     119                return rc;
     120        }
     121
     122        async_hangup(parent_phone);
     123
     124        return (usb_address_t) address;
     125}
     126
    98127/** Initialize connection to USB device.
    99128 *
     
    123152        }
    124153
    125         my_address = get_my_address(parent_phone, dev);
    126         if (my_address < 0) {
    127                 rc = my_address;
    128                 goto leave;
    129         }
     154        /*
     155         * Asking for "my" address may require several attempts.
     156         * That is because following scenario may happen:
     157         *  - parent driver (i.e. driver of parent device) announces new device
     158         *    and devman launches current driver
     159         *  - parent driver is preempted and thus does not send address-handle
     160         *    binding to HC driver
     161         *  - this driver gets here and wants the binding
     162         *  - the HC does not know the binding yet and thus it answers ENOENT
     163         *  So, we need to wait for the HC to learn the binding.
     164         */
     165        do {
     166                my_address = get_my_address(parent_phone, dev);
     167
     168                if (my_address == ENOENT) {
     169                        /* Be nice, let other fibrils run and try again. */
     170                        async_usleep(IPC_AGAIN_DELAY);
     171                } else if (my_address < 0) {
     172                        /* Some other problem, no sense trying again. */
     173                        rc = my_address;
     174                        goto leave;
     175                }
     176
     177        } while (my_address < 0);
    130178
    131179        rc = usb_device_connection_initialize(connection,
  • uspace/lib/usb/src/pipesinit.c

    rc32688d r361e61b  
    3737#include <usb/pipes.h>
    3838#include <usb/dp.h>
     39#include <usb/request.h>
     40#include <usbhc_iface.h>
    3941#include <errno.h>
    4042#include <assert.h>
     43
     44#define CTRL_PIPE_MIN_PACKET_SIZE 8
     45#define DEV_DESCR_MAX_PACKET_SIZE_OFFSET 7
    4146
    4247
     
    369374
    370375        int rc = usb_endpoint_pipe_initialize(pipe, connection,
    371             0, USB_TRANSFER_CONTROL, 8, USB_DIRECTION_BOTH);
     376            0, USB_TRANSFER_CONTROL, CTRL_PIPE_MIN_PACKET_SIZE,
     377            USB_DIRECTION_BOTH);
    372378
    373379        return rc;
     380}
     381
     382/** Probe default control pipe for max packet size.
     383 *
     384 * The function tries to get the correct value of max packet size several
     385 * time before giving up.
     386 *
     387 * The session on the pipe shall not be started.
     388 *
     389 * @param pipe Default control pipe.
     390 * @return Error code.
     391 */
     392int usb_endpoint_pipe_probe_default_control(usb_endpoint_pipe_t *pipe)
     393{
     394        assert(pipe);
     395        assert(DEV_DESCR_MAX_PACKET_SIZE_OFFSET < CTRL_PIPE_MIN_PACKET_SIZE);
     396
     397        if ((pipe->direction != USB_DIRECTION_BOTH) ||
     398            (pipe->transfer_type != USB_TRANSFER_CONTROL) ||
     399            (pipe->endpoint_no != 0)) {
     400                return EINVAL;
     401        }
     402
     403#define TRY_LOOP(attempt_var) \
     404        for (attempt_var = 0; attempt_var < 3; attempt_var++)
     405
     406        size_t failed_attempts;
     407        int rc;
     408
     409        TRY_LOOP(failed_attempts) {
     410                rc = usb_endpoint_pipe_start_session(pipe);
     411                if (rc == EOK) {
     412                        break;
     413                }
     414        }
     415        if (rc != EOK) {
     416                return rc;
     417        }
     418
     419
     420        uint8_t dev_descr_start[CTRL_PIPE_MIN_PACKET_SIZE];
     421        size_t transferred_size;
     422        TRY_LOOP(failed_attempts) {
     423                rc = usb_request_get_descriptor(pipe, USB_REQUEST_TYPE_STANDARD,
     424                    USB_REQUEST_RECIPIENT_DEVICE, USB_DESCTYPE_DEVICE,
     425                    0, 0, dev_descr_start, CTRL_PIPE_MIN_PACKET_SIZE,
     426                    &transferred_size);
     427                if (rc == EOK) {
     428                        if (transferred_size != CTRL_PIPE_MIN_PACKET_SIZE) {
     429                                rc = ELIMIT;
     430                                continue;
     431                        }
     432                        break;
     433                }
     434        }
     435        usb_endpoint_pipe_end_session(pipe);
     436        if (rc != EOK) {
     437                return rc;
     438        }
     439
     440        pipe->max_packet_size
     441            = dev_descr_start[DEV_DESCR_MAX_PACKET_SIZE_OFFSET];
     442
     443        return EOK;
     444}
     445
     446/** Register endpoint with the host controller.
     447 *
     448 * @param pipe Pipe to be registered.
     449 * @param interval Polling interval.
     450 * @param hc_connection Connection to the host controller (must be opened).
     451 * @return Error code.
     452 */
     453int usb_endpoint_pipe_register(usb_endpoint_pipe_t *pipe,
     454    unsigned int interval,
     455    usb_hc_connection_t *hc_connection)
     456{
     457        assert(pipe);
     458        assert(hc_connection);
     459
     460        if (!usb_hc_connection_is_opened(hc_connection)) {
     461                return EBADF;
     462        }
     463
     464#define _PACK(high, low) ((high) * 256 + (low))
     465
     466        return async_req_5_0(hc_connection->hc_phone,
     467            DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_REGISTER_ENDPOINT,
     468            _PACK(pipe->wire->address, pipe->endpoint_no),
     469            _PACK(pipe->transfer_type, pipe->direction),
     470            pipe->max_packet_size, interval);
     471
     472#undef _PACK
     473}
     474
     475/** Revert endpoint registration with the host controller.
     476 *
     477 * @param pipe Pipe to be unregistered.
     478 * @param hc_connection Connection to the host controller (must be opened).
     479 * @return Error code.
     480 */
     481int usb_endpoint_pipe_unregister(usb_endpoint_pipe_t *pipe,
     482    usb_hc_connection_t *hc_connection)
     483{
     484        assert(pipe);
     485        assert(hc_connection);
     486
     487        if (!usb_hc_connection_is_opened(hc_connection)) {
     488                return EBADF;
     489        }
     490
     491        return async_req_4_0(hc_connection->hc_phone,
     492            DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_UNREGISTER_ENDPOINT,
     493            pipe->wire->address, pipe->endpoint_no, pipe->direction);
    374494}
    375495
  • uspace/lib/usb/src/recognise.c

    rc32688d r361e61b  
    247247#undef VENDOR_ONLY_FMT
    248248#undef VENDOR_ONLY_ARGS
     249
     250        /* As a last resort, try fallback driver. */
     251        ADD_MATCHID_OR_RETURN(matches, 10, "usb&interface&fallback");
    249252
    250253        return EOK;
     
    291294        }
    292295       
     296        /* As a last resort, try fallback driver. */
     297        ADD_MATCHID_OR_RETURN(matches, 10, "usb&fallback");
     298
    293299        return EOK;
    294300}
     
    369375                goto failure;
    370376        }
     377        rc = usb_endpoint_pipe_probe_default_control(&ctrl_pipe);
     378        if (rc != EOK) {
     379                goto failure;
     380        }
    371381
    372382        /*
     
    374384         * naming etc., something more descriptive could be created.
    375385         */
    376         rc = asprintf(&child_name, "usbdev%02zu", this_device_name_index);
     386        rc = asprintf(&child_name, "usb%02zu_a%d",
     387            this_device_name_index, address);
    377388        if (rc < 0) {
    378389                goto failure;
  • uspace/lib/usb/src/request.c

    rc32688d r361e61b  
    157157}
    158158
     159/** Retrieve status of a USB device.
     160 *
     161 * @param[in] pipe Control endpoint pipe (session must be already started).
     162 * @param[in] index Recipient index (in native endianness).
     163 * @param[in] recipient Recipient of the GET_STATUS request.
     164 * @param[out] status Recipient status (in native endianness).
     165 * @return Error code.
     166 */
     167int usb_request_get_status(usb_endpoint_pipe_t *pipe,
     168    usb_request_recipient_t recipient, uint16_t index,
     169    uint16_t *status)
     170{
     171        if ((recipient == USB_REQUEST_RECIPIENT_DEVICE) && (index != 0)) {
     172                return EINVAL;
     173        }
     174
     175        if (status == NULL) {
     176                return EBADMEM;
     177        }
     178
     179        uint16_t status_usb_endianess;
     180        size_t data_transfered_size;
     181        int rc = usb_control_request_get(pipe, USB_REQUEST_TYPE_STANDARD,
     182            recipient, USB_DEVREQ_GET_STATUS, 0, uint16_host2usb(index),
     183            &status_usb_endianess, 2, &data_transfered_size);
     184        if (rc != EOK) {
     185                return rc;
     186        }
     187        if (data_transfered_size != 2) {
     188                return ELIMIT;
     189        }
     190
     191        *status = uint16_usb2host(status_usb_endianess);
     192
     193        return EOK;
     194}
     195
     196/** Clear or disable specific device feature.
     197 *
     198 * @param[in] pipe Control endpoint pipe (session must be already started).
     199 * @param[in] request_type Request type (standard/class/vendor).
     200 * @param[in] recipient Recipient of the CLEAR_FEATURE request.
     201 * @param[in] feature_selector Feature selector (in native endianness).
     202 * @param[in] index Recipient index (in native endianness).
     203 * @return Error code.
     204 */
     205int usb_request_clear_feature(usb_endpoint_pipe_t *pipe,
     206    usb_request_type_t request_type, usb_request_recipient_t recipient,
     207    uint16_t feature_selector, uint16_t index)
     208{
     209        if (request_type == USB_REQUEST_TYPE_STANDARD) {
     210                if ((recipient == USB_REQUEST_RECIPIENT_DEVICE)
     211                    && (index != 0)) {
     212                        return EINVAL;
     213                }
     214        }
     215
     216        int rc = usb_control_request_set(pipe, request_type, recipient,
     217            USB_DEVREQ_CLEAR_FEATURE,
     218            uint16_host2usb(feature_selector), uint16_host2usb(index),
     219            NULL, 0);
     220
     221        return rc;
     222}
     223
     224/** Set or enable specific device feature.
     225 *
     226 * @param[in] pipe Control endpoint pipe (session must be already started).
     227 * @param[in] request_type Request type (standard/class/vendor).
     228 * @param[in] recipient Recipient of the SET_FEATURE request.
     229 * @param[in] feature_selector Feature selector (in native endianness).
     230 * @param[in] index Recipient index (in native endianness).
     231 * @return Error code.
     232 */
     233int usb_request_set_feature(usb_endpoint_pipe_t *pipe,
     234    usb_request_type_t request_type, usb_request_recipient_t recipient,
     235    uint16_t feature_selector, uint16_t index)
     236{
     237        if (request_type == USB_REQUEST_TYPE_STANDARD) {
     238                if ((recipient == USB_REQUEST_RECIPIENT_DEVICE)
     239                    && (index != 0)) {
     240                        return EINVAL;
     241                }
     242        }
     243
     244        int rc = usb_control_request_set(pipe, request_type, recipient,
     245            USB_DEVREQ_SET_FEATURE,
     246            uint16_host2usb(feature_selector), uint16_host2usb(index),
     247            NULL, 0);
     248
     249        return rc;
     250}
     251
    159252/** Change address of connected device.
    160253 * This function automatically updates the backing connection to point to
     
    473566}
    474567
     568/** Update existing or add new USB descriptor to a USB device.
     569 *
     570 * @param[in] pipe Control endpoint pipe (session must be already started).
     571 * @param[in] request_type Request type (standard/class/vendor).
     572 * @param[in] recipient Request recipient (device/interface/endpoint).
     573 * @param[in] descriptor_type Descriptor type (device/configuration/HID/...).
     574 * @param[in] descriptor_index Descriptor index.
     575 * @param[in] language Language index (in native endianness).
     576 * @param[in] buffer Buffer with the new descriptor (in USB endianness).
     577 * @param[in] size Size of the @p buffer in bytes (in native endianness).
     578 * @return Error code.
     579 */
     580int usb_request_set_descriptor(usb_endpoint_pipe_t *pipe,
     581    usb_request_type_t request_type, usb_request_recipient_t recipient,
     582    uint8_t descriptor_type, uint8_t descriptor_index,
     583    uint16_t language,
     584    void *buffer, size_t size)
     585{
     586        if (buffer == NULL) {
     587                return EBADMEM;
     588        }
     589        if (size == 0) {
     590                return EINVAL;
     591        }
     592
     593        /* FIXME: proper endianness. */
     594        uint16_t wValue = descriptor_index | (descriptor_type << 8);
     595
     596        return usb_control_request_set(pipe,
     597            request_type, recipient,
     598            USB_DEVREQ_SET_DESCRIPTOR,
     599            wValue, language,
     600            buffer, size);
     601}
     602
     603/** Get current configuration value of USB device.
     604 *
     605 * @param[in] pipe Control endpoint pipe (session must be already started).
     606 * @param[out] configuration_value Current configuration value.
     607 * @return Error code.
     608 */
     609int usb_request_get_configuration(usb_endpoint_pipe_t *pipe,
     610    uint8_t *configuration_value)
     611{
     612        uint8_t value;
     613        size_t actual_size;
     614
     615        int rc = usb_control_request_get(pipe,
     616            USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
     617            USB_DEVREQ_GET_CONFIGURATION,
     618            0, 0,
     619            &value, 1, &actual_size);
     620
     621        if (rc != EOK) {
     622                return rc;
     623        }
     624        if (actual_size != 1) {
     625                return ELIMIT;
     626        }
     627
     628        if (configuration_value != NULL) {
     629                *configuration_value = value;
     630        }
     631
     632        return EOK;
     633}
     634
    475635/** Set configuration of USB device.
    476636 *
     
    488648            USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
    489649            USB_DEVREQ_SET_CONFIGURATION, config_value, 0,
     650            NULL, 0);
     651}
     652
     653/** Get selected alternate setting for USB interface.
     654 *
     655 * @param[in] pipe Control endpoint pipe (session must be already started).
     656 * @param[in] interface_index Interface index.
     657 * @param[out] alternate_setting Alternate setting for the interface.
     658 * @return Error code.
     659 */
     660int usb_request_get_interface(usb_endpoint_pipe_t *pipe,
     661    uint8_t interface_index, uint8_t *alternate_setting)
     662{
     663        uint8_t value;
     664        size_t actual_size;
     665
     666        int rc = usb_control_request_get(pipe,
     667            USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_INTERFACE,
     668            USB_DEVREQ_GET_INTERFACE,
     669            0, uint16_host2usb((uint16_t) interface_index),
     670            &value, 1, &actual_size);
     671
     672        if (rc != EOK) {
     673                return rc;
     674        }
     675        if (actual_size != 1) {
     676                return ELIMIT;
     677        }
     678
     679        if (alternate_setting != NULL) {
     680                *alternate_setting = value;
     681        }
     682
     683        return EOK;
     684}
     685
     686/** Select alternate setting for USB interface.
     687 *
     688 * @param[in] pipe Control endpoint pipe (session must be already started).
     689 * @param[in] interface_index Interface index.
     690 * @param[in] alternate_setting Alternate setting to select.
     691 * @return Error code.
     692 */
     693int usb_request_set_interface(usb_endpoint_pipe_t *pipe,
     694    uint8_t interface_index, uint8_t alternate_setting)
     695{
     696        return usb_control_request_set(pipe,
     697            USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_INTERFACE,
     698            USB_DEVREQ_SET_INTERFACE,
     699            uint16_host2usb((uint16_t) alternate_setting),
     700            uint16_host2usb((uint16_t) interface_index),
    490701            NULL, 0);
    491702}
Note: See TracChangeset for help on using the changeset viewer.