Changeset 92574f4 in mainline for uspace/lib/usb/src/request.c


Ignore:
Timestamp:
2011-02-24T12:03:27Z (13 years ago)
Author:
Lubos Slovak <lubos.slovak@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
e7b7ebd5
Parents:
4837092 (diff), a80849c (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:

Merged development (changes in DDF, etc.).

Conflicts in uspace/drv/usbkbd/main.c

File:
1 edited

Legend:

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

    r4837092 r92574f4  
    3434 */
    3535#include <usb/request.h>
    36 #include <usb/devreq.h>
    3736#include <errno.h>
     37#include <assert.h>
    3838
    3939#define MAX_DATA_LENGTH ((size_t)(0xFFFF))
     
    230230}
    231231
     232/** Retrieve USB descriptor, allocate space for it.
     233 *
     234 * @param[in] pipe Control endpoint pipe (session must be already started).
     235 * @param[in] request_type Request type (standard/class/vendor).
     236 * @param[in] descriptor_type Descriptor type (device/configuration/HID/...).
     237 * @param[in] descriptor_index Descriptor index.
     238 * @param[in] language Language index.
     239 * @param[out] buffer_ptr Where to store pointer to allocated buffer.
     240 * @param[out] buffer_size Where to store the size of the descriptor.
     241 * @return
     242 */
     243int usb_request_get_descriptor_alloc(usb_endpoint_pipe_t * pipe,
     244    usb_request_type_t request_type,
     245    uint8_t descriptor_type, uint8_t descriptor_index,
     246    uint16_t language,
     247    void **buffer_ptr, size_t *buffer_size)
     248{
     249        if (buffer_ptr == NULL) {
     250                return EBADMEM;
     251        }
     252
     253        int rc;
     254
     255        /*
     256         * Get only first byte to retrieve descriptor length.
     257         */
     258        uint8_t tmp_buffer[1];
     259        size_t bytes_transfered;
     260        rc = usb_request_get_descriptor(pipe, request_type,
     261            descriptor_type, descriptor_index, language,
     262            &tmp_buffer, 1, &bytes_transfered);
     263        if (rc != EOK) {
     264                return rc;
     265        }
     266        if (bytes_transfered != 1) {
     267                /* FIXME: some better error code? */
     268                return ESTALL;
     269        }
     270
     271        size_t size = tmp_buffer[0];
     272        if (size == 0) {
     273                /* FIXME: some better error code? */
     274                return ESTALL;
     275        }
     276
     277        /*
     278         * Allocate buffer and get the descriptor again.
     279         */
     280        void *buffer = malloc(size);
     281        if (buffer == NULL) {
     282                return ENOMEM;
     283        }
     284
     285        rc = usb_request_get_descriptor(pipe, request_type,
     286            descriptor_type, descriptor_index, language,
     287            buffer, size, &bytes_transfered);
     288        if (rc != EOK) {
     289                free(buffer);
     290                return rc;
     291        }
     292        if (bytes_transfered != size) {
     293                free(buffer);
     294                /* FIXME: some better error code? */
     295                return ESTALL;
     296        }
     297
     298        *buffer_ptr = buffer;
     299        if (buffer_size != NULL) {
     300                *buffer_size = size;
     301        }
     302
     303        return EOK;
     304}
     305
    232306/** Retrieve standard device descriptor of a USB device.
    233307 *
     
    355429}
    356430
     431/** Get list of supported languages by USB device.
     432 *
     433 * @param[in] pipe Control endpoint pipe (session must be already started).
     434 * @param[out] languages_ptr Where to store pointer to allocated array of
     435 *      supported languages.
     436 * @param[out] languages_count Number of supported languages.
     437 * @return Error code.
     438 */
     439int usb_request_get_supported_languages(usb_endpoint_pipe_t *pipe,
     440    l18_win_locales_t **languages_ptr, size_t *languages_count)
     441{
     442        int rc;
     443
     444        if (languages_ptr == NULL) {
     445                return EBADMEM;
     446        }
     447        if (languages_count == NULL) {
     448                return EBADMEM;
     449        }
     450
     451        uint8_t *string_descriptor = NULL;
     452        size_t string_descriptor_size = 0;
     453        rc = usb_request_get_descriptor_alloc(pipe,
     454            USB_REQUEST_TYPE_STANDARD, USB_DESCTYPE_STRING, 0, 0,
     455            (void **) &string_descriptor, &string_descriptor_size);
     456        if (rc != EOK) {
     457                return rc;
     458        }
     459        if (string_descriptor_size <= 2) {
     460                free(string_descriptor);
     461                return EEMPTY;
     462        }
     463        /* Substract first 2 bytes (length and descriptor type). */
     464        string_descriptor_size -= 2;
     465
     466        /* Odd number of bytes - descriptor is broken? */
     467        if ((string_descriptor_size % 2) != 0) {
     468                /* FIXME: shall we return with error or silently ignore? */
     469                free(string_descriptor);
     470                return ESTALL;
     471        }
     472
     473        size_t langs_count = string_descriptor_size / 2;
     474        l18_win_locales_t *langs
     475            = malloc(sizeof(l18_win_locales_t) * langs_count);
     476        if (langs == NULL) {
     477                free(string_descriptor);
     478                return ENOMEM;
     479        }
     480
     481        size_t i;
     482        for (i = 0; i < langs_count; i++) {
     483                /* Language code from the descriptor is in USB endianess. */
     484                /* FIXME: is this really correct? */
     485                uint16_t lang_code = (string_descriptor[2 + 2 * i + 1] << 8)
     486                    + string_descriptor[2 + 2 * i];
     487                langs[i] = uint16_usb2host(lang_code);
     488        }
     489
     490        free(string_descriptor);
     491
     492        *languages_ptr = langs;
     493        *languages_count =langs_count;
     494
     495        return EOK;
     496}
     497
     498/** Get string (descriptor) from USB device.
     499 *
     500 * The string is returned in native encoding of the operating system.
     501 * For HelenOS, that is UTF-8.
     502 *
     503 * @param[in] pipe Control endpoint pipe (session must be already started).
     504 * @param[in] index String index (in native endianess).
     505 * @param[in] lang String language (in native endianess).
     506 * @param[out] string_ptr Where to store allocated string in native encoding.
     507 * @return Error code.
     508 */
     509int usb_request_get_string(usb_endpoint_pipe_t *pipe,
     510    size_t index, l18_win_locales_t lang, char **string_ptr)
     511{
     512        if (string_ptr == NULL) {
     513                return EBADMEM;
     514        }
     515        /* Index is actually one byte value. */
     516        if (index > 0xFF) {
     517                return ERANGE;
     518        }
     519        /* Language is actually two byte value. */
     520        if (lang > 0xFFFF) {
     521                return ERANGE;
     522        }
     523
     524        int rc;
     525
     526        /* Prepare dynamically allocated variables. */
     527        uint8_t *string = NULL;
     528        wchar_t *string_chars = NULL;
     529
     530        /* Get the actual descriptor. */
     531        size_t string_size;
     532        rc = usb_request_get_descriptor_alloc(pipe,
     533            USB_REQUEST_TYPE_STANDARD, USB_DESCTYPE_STRING,
     534            index, uint16_host2usb(lang),
     535            (void **) &string, &string_size);
     536        if (rc != EOK) {
     537                goto leave;
     538        }
     539
     540        if (string_size <= 2) {
     541                rc =  EEMPTY;
     542                goto leave;
     543        }
     544        /* Substract first 2 bytes (length and descriptor type). */
     545        string_size -= 2;
     546
     547        /* Odd number of bytes - descriptor is broken? */
     548        if ((string_size % 2) != 0) {
     549                /* FIXME: shall we return with error or silently ignore? */
     550                rc = ESTALL;
     551                goto leave;
     552        }
     553
     554        size_t string_char_count = string_size / 2;
     555        string_chars = malloc(sizeof(wchar_t) * (string_char_count + 1));
     556        if (string_chars == NULL) {
     557                rc = ENOMEM;
     558                goto leave;
     559        }
     560
     561        /*
     562         * Build a wide string.
     563         * And do not forget to set NULL terminator (string descriptors
     564         * do not have them).
     565         */
     566        size_t i;
     567        for (i = 0; i < string_char_count; i++) {
     568                uint16_t uni_char = (string[2 + 2 * i + 1] << 8)
     569                    + string[2 + 2 * i];
     570                string_chars[i] = uni_char;
     571        }
     572        string_chars[string_char_count] = 0;
     573
     574
     575        /* Convert to normal string. */
     576        char *str = wstr_to_astr(string_chars);
     577        if (str == NULL) {
     578                rc = ENOMEM;
     579                goto leave;
     580        }
     581
     582        *string_ptr = str;
     583        rc = EOK;
     584
     585leave:
     586        if (string != NULL) {
     587                free(string);
     588        }
     589        if (string_chars != NULL) {
     590                free(string_chars);
     591        }
     592
     593        return rc;
     594}
     595
    357596/**
    358597 * @}
Note: See TracChangeset for help on using the changeset viewer.