Changes in / [a9c674e0:a80849c] in mainline


Ignore:
Location:
uspace
Files:
1 added
8 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/usbinfo/dump.c

    ra9c674e0 ra80849c  
    5353
    5454
    55 static const char *get_indent(size_t level)
     55const char *get_indent(size_t level)
    5656{
    5757        static const char *indents[] = {
  • uspace/app/usbinfo/info.c

    ra9c674e0 ra80849c  
    129129            config_descriptor.total_length);
    130130
     131        /*
     132         * Get supported languages of STRING descriptors.
     133         */
     134        l18_win_locales_t *langs;
     135        size_t langs_count;
     136        rc = usb_request_get_supported_languages(&ctrl_pipe,
     137            &langs, &langs_count);
     138        if (rc != EOK) {
     139                fprintf(stderr,
     140                    NAME ": failed to get list of supported languages: %s.\n",
     141                    str_error(rc));
     142                goto skip_strings;
     143        }
     144
     145        printf("String languages (%zu):", langs_count);
     146        size_t i;
     147        for (i = 0; i < langs_count; i++) {
     148                printf(" 0x%04x", (int) langs[i]);
     149        }
     150        printf(".\n");
     151
     152        /*
     153         * Dump all strings in all available langages;
     154         */
     155        for (i = 0; i < langs_count; i++) {
     156                l18_win_locales_t lang = langs[i];
     157
     158                printf("%sStrings for language 0x%04x:\n", get_indent(0),
     159                    (int) lang);
     160
     161                /*
     162                 * Try all indexes - we will see what pops-up ;-).
     163                 * However, to speed things up, we will stop after
     164                 * encountering several broken (or nonexistent ones)
     165                 * descriptors in line.
     166                 */
     167                size_t idx;
     168                size_t failed_count = 0;
     169                for (idx = 1; idx < 0xFF; idx++) {
     170                        char *string;
     171                        rc = usb_request_get_string(&ctrl_pipe, idx, lang,
     172                            &string);
     173                        if (rc != EOK) {
     174                                failed_count++;
     175                                if (failed_count > 3) {
     176                                        break;
     177                                }
     178                                continue;
     179                        }
     180                        printf("%sString #%zu: \"%s\"\n", get_indent(1),
     181                            idx, string);
     182                        free(string);
     183                        failed_count = 0; /* Reset failed counter. */
     184                }
     185        }
     186
     187
     188skip_strings:
     189
    131190        rc = EOK;
     191
    132192leave:
    133193        /* Ignoring errors here. */
  • uspace/app/usbinfo/usbinfo.h

    ra9c674e0 ra80849c  
    4545
    4646void dump_buffer(const char *, size_t, const uint8_t *, size_t);
     47const char *get_indent(size_t);
    4748void dump_match_ids(match_id_list_t *matches);
    4849void dump_usb_descriptor(uint8_t *, size_t);
  • uspace/lib/c/generic/str_error.c

    ra9c674e0 ra80849c  
    7777                case EAGAIN:
    7878                        return "Resource temporarily unavailable";
     79                case EEMPTY:
     80                        return "Resource is empty";
    7981                default:
    8082                        break;
  • uspace/lib/c/include/errno.h

    ra9c674e0 ra80849c  
    6262#define ESTALL (-301)
    6363
     64/** Empty resource (no data). */
     65#define EEMPTY (-302)
     66
    6467/** An API function is called while another blocking function is in progress. */
    6568#define EINPROGRESS  (-10036)
  • uspace/lib/usb/include/usb/request.h

    ra9c674e0 ra80849c  
    3737
    3838#include <sys/types.h>
     39#include <l18n/langs.h>
    3940#include <usb/usb.h>
    4041#include <usb/pipes.h>
     
    9697int usb_request_get_descriptor(usb_endpoint_pipe_t *, usb_request_type_t,
    9798    uint8_t, uint8_t, uint16_t, void *, size_t, size_t *);
     99int usb_request_get_descriptor_alloc(usb_endpoint_pipe_t *, usb_request_type_t,
     100    uint8_t, uint8_t, uint16_t, void **, size_t *);
    98101int usb_request_get_device_descriptor(usb_endpoint_pipe_t *,
    99102    usb_standard_device_descriptor_t *);
     
    104107int usb_request_set_configuration(usb_endpoint_pipe_t *, uint8_t);
    105108
     109int usb_request_get_supported_languages(usb_endpoint_pipe_t *,
     110    l18_win_locales_t **, size_t *);
     111int usb_request_get_string(usb_endpoint_pipe_t *, size_t, l18_win_locales_t,
     112    char **);
     113
    106114#endif
    107115/**
  • uspace/lib/usb/src/recognise.c

    ra9c674e0 ra80849c  
    310310        }
    311311
    312         /*
    313          * As a fallback, provide the simplest match id possible.
    314          */
    315         ADD_MATCHID_OR_RETURN(matches, 1, "usb&fallback");
    316 
    317312        return EOK;
    318313}
  • uspace/lib/usb/src/request.c

    ra9c674e0 ra80849c  
    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.