Changeset 00db345a in mainline


Ignore:
Timestamp:
2011-03-05T11:51:14Z (13 years ago)
Author:
Lubos Slovak <lubos.slovak@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
1efe89b
Parents:
7ac73a4 (diff), 474d08e (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.

Location:
uspace
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/uhci-hcd/batch.c

    r7ac73a4 r00db345a  
    4747static int batch_schedule(batch_t *instance);
    4848
    49 static void batch_control(
    50     batch_t *instance, int data_stage, int status_stage);
     49static void batch_control(batch_t *instance,
     50    usb_packet_id data_stage, usb_packet_id status_stage);
     51static void batch_data(batch_t *instance, usb_packet_id pid);
    5152static void batch_call_in(batch_t *instance);
    5253static void batch_call_out(batch_t *instance);
     
    8384        }
    8485
    85         instance->tds = malloc32(sizeof(transfer_descriptor_t) * instance->packets);
     86        instance->tds = malloc32(sizeof(td_t) * instance->packets);
    8687        if (instance->tds == NULL) {
    8788                usb_log_error("Failed to allocate transfer descriptors.\n");
     
    9091                return NULL;
    9192        }
    92         bzero(instance->tds, sizeof(transfer_descriptor_t) * instance->packets);
     93        bzero(instance->tds, sizeof(td_t) * instance->packets);
    9394
    9495        const size_t transport_size = max_packet_size * instance->packets;
     
    151152        size_t i = 0;
    152153        for (;i < instance->packets; ++i) {
    153                 if (transfer_descriptor_is_active(&instance->tds[i])) {
     154                if (td_is_active(&instance->tds[i])) {
    154155                        return false;
    155156                }
    156                 instance->error = transfer_descriptor_status(&instance->tds[i]);
     157
     158                instance->error = td_status(&instance->tds[i]);
    157159                if (instance->error != EOK) {
     160                        usb_log_debug("Batch(%p) found error TD(%d):%x.\n",
     161                            instance, i, instance->tds[i].status);
    158162                        if (i > 0)
    159                                 instance->transfered_size -= instance->setup_size;
    160                         usb_log_debug("Batch(%p) found error TD(%d):%x.\n",
    161                           instance, i, instance->tds[i].status);
     163                                goto substract_ret;
    162164                        return true;
    163165                }
    164                 instance->transfered_size +=
    165                     transfer_descriptor_actual_size(&instance->tds[i]);
    166         }
     166
     167                instance->transfered_size += td_act_size(&instance->tds[i]);
     168                if (td_is_short(&instance->tds[i]))
     169                        goto substract_ret;
     170        }
     171substract_ret:
    167172        instance->transfered_size -= instance->setup_size;
    168173        return true;
     
    192197{
    193198        assert(instance);
    194 
     199        batch_data(instance, USB_PID_IN);
     200        instance->next_step = batch_call_in_and_dispose;
     201        usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance);
     202        batch_schedule(instance);
     203}
     204/*----------------------------------------------------------------------------*/
     205void batch_interrupt_out(batch_t *instance)
     206{
     207        assert(instance);
     208        memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size);
     209        batch_data(instance, USB_PID_OUT);
     210        instance->next_step = batch_call_out_and_dispose;
     211        usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance);
     212        batch_schedule(instance);
     213}
     214/*----------------------------------------------------------------------------*/
     215void batch_bulk_in(batch_t *instance)
     216{
     217        assert(instance);
     218        batch_data(instance, USB_PID_IN);
     219        instance->next_step = batch_call_in_and_dispose;
     220        usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
     221        batch_schedule(instance);
     222}
     223/*----------------------------------------------------------------------------*/
     224void batch_bulk_out(batch_t *instance)
     225{
     226        assert(instance);
     227        memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size);
     228        batch_data(instance, USB_PID_OUT);
     229        instance->next_step = batch_call_out_and_dispose;
     230        usb_log_debug("Batch(%p) BULK OUT initialized.\n", instance);
     231        batch_schedule(instance);
     232}
     233/*----------------------------------------------------------------------------*/
     234static void batch_data(batch_t *instance, usb_packet_id pid)
     235{
     236        assert(instance);
    195237        const bool low_speed = instance->speed == USB_SPEED_LOW;
    196238        int toggle = 1;
    197         size_t i = 0;
    198         for (;i < instance->packets; ++i) {
     239
     240        size_t packet = 0;
     241        size_t remain_size = instance->buffer_size;
     242        while (remain_size > 0) {
    199243                char *data =
    200                     instance->transport_buffer + (i  * instance->max_packet_size);
    201                 transfer_descriptor_t *next = (i + 1) < instance->packets ?
    202                     &instance->tds[i + 1] : NULL;
     244                    instance->transport_buffer + instance->buffer_size
     245                    - remain_size;
     246
    203247                toggle = 1 - toggle;
    204248
    205                 transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
    206                     instance->max_packet_size, toggle, false, low_speed,
    207                     instance->target, USB_PID_IN, data, next);
    208         }
    209 
    210         instance->tds[i - 1].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG;
    211 
    212         instance->next_step = batch_call_in_and_dispose;
    213         usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance);
    214         batch_schedule(instance);
    215 }
    216 /*----------------------------------------------------------------------------*/
    217 void batch_interrupt_out(batch_t *instance)
    218 {
    219         assert(instance);
    220         memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size);
    221 
    222         const bool low_speed = instance->speed == USB_SPEED_LOW;
    223         int toggle = 1;
    224         size_t i = 0;
    225         for (;i < instance->packets; ++i) {
    226                 char *data =
    227                     instance->transport_buffer + (i  * instance->max_packet_size);
    228                 transfer_descriptor_t *next = (i + 1) < instance->packets ?
    229                     &instance->tds[i + 1] : NULL;
    230                 toggle = 1 - toggle;
    231 
    232                 transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
    233                     instance->max_packet_size, toggle++, false, low_speed,
    234                     instance->target, USB_PID_OUT, data, next);
    235         }
    236 
    237         instance->tds[i - 1].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG;
    238 
    239         instance->next_step = batch_call_out_and_dispose;
    240         usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance);
    241         batch_schedule(instance);
    242 }
    243 /*----------------------------------------------------------------------------*/
    244 static void batch_control(
    245     batch_t *instance, int data_stage, int status_stage)
     249                const size_t packet_size =
     250                    (instance->max_packet_size > remain_size) ?
     251                    remain_size : instance->max_packet_size;
     252
     253                td_init(&instance->tds[packet],
     254                    DEFAULT_ERROR_COUNT, packet_size, toggle, false, low_speed,
     255                    instance->target, pid, data,
     256                    &instance->tds[packet + 1]);
     257
     258                ++packet;
     259                assert(packet <= instance->packets);
     260                assert(packet_size <= remain_size);
     261                remain_size -= packet_size;
     262        }
     263
     264        instance->tds[packet - 1].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG;
     265        instance->tds[packet - 1].next = 0 | LINK_POINTER_TERMINATE_FLAG;
     266}
     267/*----------------------------------------------------------------------------*/
     268static void batch_control(batch_t *instance,
     269   usb_packet_id data_stage, usb_packet_id status_stage)
    246270{
    247271        assert(instance);
     
    250274        int toggle = 0;
    251275        /* setup stage */
    252         transfer_descriptor_init(instance->tds, DEFAULT_ERROR_COUNT,
     276        td_init(instance->tds, DEFAULT_ERROR_COUNT,
    253277            instance->setup_size, toggle, false, low_speed, instance->target,
    254278            USB_PID_SETUP, instance->setup_buffer, &instance->tds[1]);
     
    268292                    remain_size : instance->max_packet_size;
    269293
    270                 transfer_descriptor_init(&instance->tds[packet],
     294                td_init(&instance->tds[packet],
    271295                    DEFAULT_ERROR_COUNT, packet_size, toggle, false, low_speed,
    272296                    instance->target, data_stage, data,
     
    281305        /* status stage */
    282306        assert(packet == instance->packets - 1);
    283         transfer_descriptor_init(&instance->tds[packet], DEFAULT_ERROR_COUNT,
     307        td_init(&instance->tds[packet], DEFAULT_ERROR_COUNT,
    284308            0, 1, false, low_speed, instance->target, status_stage, NULL, NULL);
    285309
  • uspace/drv/uhci-hcd/batch.h

    r7ac73a4 r00db345a  
    6565        ddf_fun_t *fun;
    6666        queue_head_t *qh;
    67         transfer_descriptor_t *tds;
     67        td_t *tds;
    6868        void (*next_step)(struct batch*);
    6969} batch_t;
     
    8686void batch_interrupt_out(batch_t *instance);
    8787
    88 /* DEPRECATED FUNCTIONS NEEDED BY THE OLD API */
    89 void batch_control_setup_old(batch_t *instance);
     88void batch_bulk_in(batch_t *instance);
    9089
    91 void batch_control_write_data_old(batch_t *instance);
    92 
    93 void batch_control_read_data_old(batch_t *instance);
    94 
    95 void batch_control_write_status_old(batch_t *instance);
    96 
    97 void batch_control_read_status_old(batch_t *instance);
     90void batch_bulk_out(batch_t *instance);
    9891#endif
    9992/**
  • uspace/drv/uhci-hcd/iface.c

    r7ac73a4 r00db345a  
    140140}
    141141/*----------------------------------------------------------------------------*/
     142static int bulk_out(ddf_fun_t *fun, usb_target_t target,
     143    size_t max_packet_size, void *data, size_t size,
     144    usbhc_iface_transfer_out_callback_t callback, void *arg)
     145{
     146        assert(fun);
     147        uhci_t *hc = fun_to_uhci(fun);
     148        assert(hc);
     149        usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
     150
     151        usb_log_debug("Bulk OUT %d:%d %zu(%zu).\n",
     152            target.address, target.endpoint, size, max_packet_size);
     153
     154        batch_t *batch = batch_get(fun, target, USB_TRANSFER_BULK,
     155            max_packet_size, speed, data, size, NULL, 0, NULL, callback, arg);
     156        if (!batch)
     157                return ENOMEM;
     158        batch_bulk_out(batch);
     159        return EOK;
     160}
     161/*----------------------------------------------------------------------------*/
     162static int bulk_in(ddf_fun_t *fun, usb_target_t target,
     163    size_t max_packet_size, void *data, size_t size,
     164    usbhc_iface_transfer_in_callback_t callback, void *arg)
     165{
     166        assert(fun);
     167        uhci_t *hc = fun_to_uhci(fun);
     168        assert(hc);
     169        usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
     170        usb_log_debug("Bulk IN %d:%d %zu(%zu).\n",
     171            target.address, target.endpoint, size, max_packet_size);
     172
     173        batch_t *batch = batch_get(fun, target, USB_TRANSFER_BULK,
     174            max_packet_size, speed, data, size, NULL, 0, callback, NULL, arg);
     175        if (!batch)
     176                return ENOMEM;
     177        batch_bulk_in(batch);
     178        return EOK;
     179}
     180/*----------------------------------------------------------------------------*/
    142181static int control_write(ddf_fun_t *fun, usb_target_t target,
    143182    size_t max_packet_size,
     
    181220        return EOK;
    182221}
    183 
    184 
    185222/*----------------------------------------------------------------------------*/
    186223usbhc_iface_t uhci_iface = {
     
    194231        .interrupt_in = interrupt_in,
    195232
     233        .bulk_in = bulk_in,
     234        .bulk_out = bulk_out,
     235
    196236        .control_read = control_read,
    197237        .control_write = control_write,
  • uspace/drv/uhci-hcd/uhci.c

    r7ac73a4 r00db345a  
    336336                uhci_interrupt(instance, status);
    337337                pio_write_16(&instance->registers->usbsts, 0x1f);
    338                 async_usleep(UHCI_CLEANER_TIMEOUT * 5);
     338                async_usleep(UHCI_CLEANER_TIMEOUT);
    339339        }
    340340        return EOK;
  • uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.c

    r7ac73a4 r00db345a  
    3838#include "utils/malloc32.h"
    3939
    40 void transfer_descriptor_init(transfer_descriptor_t *instance,
    41     int error_count, size_t size, bool toggle, bool isochronous, bool low_speed,
    42     usb_target_t target, int pid, void *buffer, transfer_descriptor_t *next)
     40void td_init(td_t *instance, int err_count, size_t size, bool toggle, bool iso,
     41    bool low_speed, usb_target_t target, usb_packet_id pid, void *buffer, td_t *next)
    4342{
    4443        assert(instance);
     44        assert(size < 1024);
     45        assert((pid == USB_PID_SETUP) || (pid == USB_PID_IN) || (pid == USB_PID_OUT));
    4546
    4647        instance->next = 0
     
    4950
    5051        instance->status = 0
    51           | ((error_count & TD_STATUS_ERROR_COUNT_MASK) << TD_STATUS_ERROR_COUNT_POS)
    52                 | (low_speed ? TD_STATUS_LOW_SPEED_FLAG : 0)
    53           | TD_STATUS_ERROR_ACTIVE;
     52            | ((err_count & TD_STATUS_ERROR_COUNT_MASK) << TD_STATUS_ERROR_COUNT_POS)
     53            | (low_speed ? TD_STATUS_LOW_SPEED_FLAG : 0)
     54            | (iso ? TD_STATUS_ISOCHRONOUS_FLAG : 0)
     55            | TD_STATUS_ERROR_ACTIVE;
    5456
    55         assert(size < 1024);
     57        if (pid == USB_PID_IN && !iso) {
     58                instance->status |= TD_STATUS_SPD_FLAG;
     59        }
     60
    5661        instance->device = 0
    57                 | (((size - 1) & TD_DEVICE_MAXLEN_MASK) << TD_DEVICE_MAXLEN_POS)
    58                 | (toggle ? TD_DEVICE_DATA_TOGGLE_ONE_FLAG : 0)
    59                 | ((target.address & TD_DEVICE_ADDRESS_MASK) << TD_DEVICE_ADDRESS_POS)
    60                 | ((target.endpoint & TD_DEVICE_ENDPOINT_MASK) << TD_DEVICE_ENDPOINT_POS)
    61                 | ((pid & TD_DEVICE_PID_MASK) << TD_DEVICE_PID_POS);
     62            | (((size - 1) & TD_DEVICE_MAXLEN_MASK) << TD_DEVICE_MAXLEN_POS)
     63            | (toggle ? TD_DEVICE_DATA_TOGGLE_ONE_FLAG : 0)
     64            | ((target.address & TD_DEVICE_ADDRESS_MASK) << TD_DEVICE_ADDRESS_POS)
     65            | ((target.endpoint & TD_DEVICE_ENDPOINT_MASK) << TD_DEVICE_ENDPOINT_POS)
     66            | ((pid & TD_DEVICE_PID_MASK) << TD_DEVICE_PID_POS);
    6267
    6368        instance->buffer_ptr = 0;
     
    6873
    6974        usb_log_debug2("Created TD: %X:%X:%X:%X(%p).\n",
    70                 instance->next, instance->status, instance->device,
    71           instance->buffer_ptr, buffer);
     75            instance->next, instance->status, instance->device,
     76            instance->buffer_ptr, buffer);
    7277}
    7378/*----------------------------------------------------------------------------*/
    74 int transfer_descriptor_status(transfer_descriptor_t *instance)
     79int td_status(td_t *instance)
    7580{
    7681        assert(instance);
  • uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.h

    r7ac73a4 r00db345a  
    8888         * we don't use it anyway
    8989         */
    90 } __attribute__((packed)) transfer_descriptor_t;
     90} __attribute__((packed)) td_t;
    9191
    9292
    93 void transfer_descriptor_init(transfer_descriptor_t *instance,
    94     int error_count, size_t size, bool toggle, bool isochronous, bool low_speed,
    95     usb_target_t target, int pid, void *buffer, transfer_descriptor_t * next);
     93void td_init(td_t *instance, int error_count, size_t size, bool toggle, bool iso,
     94    bool low_speed, usb_target_t target, usb_packet_id pid, void *buffer,
     95    td_t *next);
    9696
    97 int transfer_descriptor_status(transfer_descriptor_t *instance);
     97int td_status(td_t *instance);
    9898
    99 static inline size_t transfer_descriptor_actual_size(
    100     transfer_descriptor_t *instance)
     99static inline size_t td_act_size(td_t *instance)
    101100{
    102101        assert(instance);
    103102        return
    104             ((instance->status >> TD_STATUS_ACTLEN_POS) + 1) & TD_STATUS_ACTLEN_MASK;
     103            ((instance->status >> TD_STATUS_ACTLEN_POS) + 1)
     104            & TD_STATUS_ACTLEN_MASK;
    105105}
    106106
    107 static inline bool transfer_descriptor_is_active(
    108     transfer_descriptor_t *instance)
     107static inline bool td_is_short(td_t *instance)
     108{
     109        const size_t act_size = td_act_size(instance);
     110        const size_t max_size =
     111            ((instance->device >> TD_DEVICE_MAXLEN_POS) + 1)
     112            & TD_DEVICE_MAXLEN_MASK;
     113        return
     114            (instance->status | TD_STATUS_SPD_FLAG) && act_size < max_size;
     115}
     116
     117static inline bool td_is_active(td_t *instance)
    109118{
    110119        assert(instance);
  • uspace/drv/usbhub/usbhub.c

    r7ac73a4 r00db345a  
    233233        dprintf(USB_LOG_LEVEL_DEBUG, "starting control transaction");
    234234        usb_endpoint_pipe_start_session(&result->endpoints.control);
     235        opResult = usb_request_set_configuration(&result->endpoints.control, 1);
     236        assert(opResult == EOK);
     237
    235238        opResult = usb_request_get_descriptor(&result->endpoints.control,
    236239                        USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_DEVICE,
     
    243246                dprintf(USB_LOG_LEVEL_ERROR, "failed when receiving hub descriptor, badcode = %d",opResult);
    244247                free(serialized_descriptor);
    245                 return result;
     248                free(result);
     249                return NULL;
    246250        }
    247251        dprintf(USB_LOG_LEVEL_DEBUG2, "deserializing descriptor");
     
    249253        if(descriptor==NULL){
    250254                dprintf(USB_LOG_LEVEL_WARNING, "could not deserialize descriptor ");
    251                 result->port_count = 1;///\TODO this code is only for debug!!!
    252                 return result;
     255                free(result);
     256                return NULL;
    253257        }
    254258
     
    286290
    287291        usb_hub_info_t * hub_info = usb_create_hub_info(dev);
     292        if(!hub_info){
     293                return EINTR;
     294        }
    288295
    289296        int opResult;
     
    294301        opResult = usb_hub_process_configuration_descriptors(hub_info);
    295302        if(opResult != EOK){
    296                 dprintf(USB_LOG_LEVEL_ERROR,"could not get condiguration descriptors, %d",
     303                dprintf(USB_LOG_LEVEL_ERROR,"could not get configuration descriptors, %d",
    297304                                opResult);
    298305                return opResult;
  • uspace/drv/usbmouse/main.c

    r7ac73a4 r00db345a  
    7474int main(int argc, char *argv[])
    7575{
    76         usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
     76        usb_log_enable(USB_LOG_LEVEL_DEBUG2, NAME);
    7777
    7878        return ddf_driver_main(&mouse_driver);
  • uspace/drv/usbmouse/mouse.c

    r7ac73a4 r00db345a  
    3737#include <usb/debug.h>
    3838#include <errno.h>
     39#include <str_error.h>
    3940#include <ipc/mouse.h>
    4041
     
    6465
    6566                size_t actual_size;
     67                int rc;
    6668
    67                 /* FIXME: check for errors. */
    68                 usb_endpoint_pipe_start_session(&mouse->poll_pipe);
     69                /*
     70                 * Error checking note:
     71                 * - failure when starting a session is considered
     72                 *   temporary (e.g. out of phones, next try might succeed)
     73                 * - failure of transfer considered fatal (probably the
     74                 *   device was unplugged)
     75                 * - session closing not checked (shall not fail anyway)
     76                 */
    6977
    70                 usb_endpoint_pipe_read(&mouse->poll_pipe,
     78                rc = usb_endpoint_pipe_start_session(&mouse->poll_pipe);
     79                if (rc != EOK) {
     80                        usb_log_warning("Failed to start session, will try again: %s.\n",
     81                            str_error(rc));
     82                        continue;
     83                }
     84
     85                rc = usb_endpoint_pipe_read(&mouse->poll_pipe,
    7186                    buffer, buffer_size, &actual_size);
    7287
    7388                usb_endpoint_pipe_end_session(&mouse->poll_pipe);
     89
     90                if (rc != EOK) {
     91                        usb_log_error("Failed reading mouse input: %s.\n",
     92                            str_error(rc));
     93                        break;
     94                }
     95
     96                usb_log_debug2("got buffer: %s.\n",
     97                    usb_debug_str_buffer(buffer, buffer_size, 0));
    7498
    7599                uint8_t butt = buffer[0];
     
    115139        }
    116140
     141        /*
     142         * Device was probably unplugged.
     143         * Hang-up the phone to the console.
     144         * FIXME: release allocated memory.
     145         */
     146        async_hangup(mouse->console_phone);
     147        mouse->console_phone = -1;
     148
     149        usb_log_error("Mouse polling fibril terminated.\n");
     150
    117151        return EOK;
    118152}
  • uspace/lib/usb/include/usb/debug.h

    r7ac73a4 r00db345a  
    7979        usb_log_printf(USB_LOG_LEVEL_DEBUG2, format, ##__VA_ARGS__)
    8080
     81const char *usb_debug_str_buffer(uint8_t *, size_t, size_t);
    8182
    8283
  • uspace/lib/usb/src/debug.c

    r7ac73a4 r00db345a  
    252252}
    253253
     254
     255#define REMAINDER_STR_FMT " (%zu)..."
     256/* string + terminator + number width (enough for 4GB)*/
     257#define REMAINDER_STR_LEN (5 + 1 + 10)
     258#define BUFFER_DUMP_GROUP_SIZE 4
     259#define BUFFER_DUMP_LEN 240 /* Ought to be enough for everybody ;-). */
     260static fibril_local char buffer_dump[BUFFER_DUMP_LEN];
     261
     262/** Dump buffer into string.
     263 *
     264 * The function dumps given buffer into hexadecimal format and stores it
     265 * in a static fibril local string.
     266 * That means that you do not have to deallocate the string (actually, you
     267 * can not do that) and you do not have to save it agains concurrent
     268 * calls to it.
     269 * The only limitation is that each call rewrites the buffer again.
     270 * Thus, it is necessary to copy the buffer elsewhere (that includes printing
     271 * to screen or writing to file).
     272 * Since this function is expected to be used for debugging prints only,
     273 * that is not a big limitation.
     274 *
     275 * @warning You cannot use this function twice in the same printf
     276 * (see detailed explanation).
     277 *
     278 * @param buffer Buffer to be printed (can be NULL).
     279 * @param size Size of the buffer in bytes (can be zero).
     280 * @param dumped_size How many bytes to actually dump (zero means all).
     281 * @return Dumped buffer as a static (but fibril local) string.
     282 */
     283const char *usb_debug_str_buffer(uint8_t *buffer, size_t size,
     284    size_t dumped_size)
     285{
     286        /*
     287         * Remove previous string (that might also reveal double usage of
     288         * this function).
     289         */
     290        bzero(buffer_dump, BUFFER_DUMP_LEN);
     291
     292        if (buffer == NULL) {
     293                return "(null)";
     294        }
     295        if (size == 0) {
     296                return "(empty)";
     297        }
     298        if ((dumped_size == 0) || (dumped_size > size)) {
     299                dumped_size = size;
     300        }
     301
     302        /* How many bytes are available in the output buffer. */
     303        size_t buffer_remaining_size = BUFFER_DUMP_LEN - 1 - REMAINDER_STR_LEN;
     304        char *it = buffer_dump;
     305
     306        size_t index = 0;
     307
     308        while (index < size) {
     309                /* Determine space before the number. */
     310                const char *space_before;
     311                if (index == 0) {
     312                        space_before = "";
     313                } else if ((index % BUFFER_DUMP_GROUP_SIZE) == 0) {
     314                        space_before = "  ";
     315                } else {
     316                        space_before = " ";
     317                }
     318
     319                /*
     320                 * Add the byte as a hexadecimal number plus the space.
     321                 * We do it into temporary buffer to ensure that always
     322                 * the whole byte is printed.
     323                 */
     324                int val = buffer[index];
     325                char current_byte[16];
     326                int printed = snprintf(current_byte, 16,
     327                    "%s%02x", space_before, val);
     328                if (printed < 0) {
     329                        break;
     330                }
     331
     332                if ((size_t) printed > buffer_remaining_size) {
     333                        break;
     334                }
     335
     336                /* We can safely add 1, because space for end 0 is reserved. */
     337                str_append(it, buffer_remaining_size + 1, current_byte);
     338
     339                buffer_remaining_size -= printed;
     340                /* Point at the terminator 0. */
     341                it += printed;
     342                index++;
     343
     344                if (index >= dumped_size) {
     345                        break;
     346                }
     347        }
     348
     349        /* Add how many bytes were not printed. */
     350        if (index < size) {
     351                snprintf(it, REMAINDER_STR_LEN,
     352                    REMAINDER_STR_FMT, size - index);
     353        }
     354
     355        return buffer_dump;
     356}
     357
     358
    254359/**
    255360 * @}
Note: See TracChangeset for help on using the changeset viewer.