Changeset 960bee9 in mainline for uspace/drv/uhci-hcd


Ignore:
Timestamp:
2011-03-07T16:51:59Z (15 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/fix-logger-deadlock, topic/msim-upgrade, topic/simplify-dev-export
Children:
97ff14d
Parents:
a6add7a (diff), d4beec3 (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 development/ changes

Location:
uspace/drv/uhci-hcd
Files:
8 edited

Legend:

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

    ra6add7a r960bee9  
    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);
    5354static void batch_call_in_and_dispose(batch_t *instance);
    5455static void batch_call_out_and_dispose(batch_t *instance);
     56static void batch_dispose(batch_t *instance);
    5557
    5658
     
    6062    char* setup_buffer, size_t setup_size,
    6163    usbhc_iface_transfer_in_callback_t func_in,
    62     usbhc_iface_transfer_out_callback_t func_out, void *arg)
     64    usbhc_iface_transfer_out_callback_t func_out, void *arg,
     65    device_keeper_t *manager
     66    )
    6367{
    6468        assert(func_in == NULL || func_out == NULL);
     
    8387        }
    8488
    85         instance->tds = malloc32(sizeof(transfer_descriptor_t) * instance->packets);
     89        instance->tds = malloc32(sizeof(td_t) * instance->packets);
    8690        if (instance->tds == NULL) {
    8791                usb_log_error("Failed to allocate transfer descriptors.\n");
     
    9094                return NULL;
    9195        }
    92         bzero(instance->tds, sizeof(transfer_descriptor_t) * instance->packets);
     96        bzero(instance->tds, sizeof(td_t) * instance->packets);
    9397
    9498        const size_t transport_size = max_packet_size * instance->packets;
     
    136140        instance->arg = arg;
    137141        instance->speed = speed;
     142        instance->manager = manager;
    138143
    139144        queue_head_element_td(instance->qh, addr_to_phys(instance->tds));
     
    151156        size_t i = 0;
    152157        for (;i < instance->packets; ++i) {
    153                 if (transfer_descriptor_is_active(&instance->tds[i])) {
     158                if (td_is_active(&instance->tds[i])) {
    154159                        return false;
    155160                }
    156                 instance->error = transfer_descriptor_status(&instance->tds[i]);
     161
     162                instance->error = td_status(&instance->tds[i]);
    157163                if (instance->error != EOK) {
     164                        usb_log_debug("Batch(%p) found error TD(%d):%x.\n",
     165                            instance, i, instance->tds[i].status);
     166
     167                        device_keeper_set_toggle(instance->manager, instance->target,
     168                            td_toggle(&instance->tds[i]));
    158169                        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);
     170                                goto substract_ret;
    162171                        return true;
    163172                }
    164                 instance->transfered_size +=
    165                     transfer_descriptor_actual_size(&instance->tds[i]);
    166         }
     173
     174                instance->transfered_size += td_act_size(&instance->tds[i]);
     175                if (td_is_short(&instance->tds[i]))
     176                        goto substract_ret;
     177        }
     178substract_ret:
    167179        instance->transfered_size -= instance->setup_size;
    168180        return true;
     
    192204{
    193205        assert(instance);
    194 
    195         const bool low_speed = instance->speed == USB_SPEED_LOW;
    196         int toggle = 1;
    197         size_t i = 0;
    198         for (;i < instance->packets; ++i) {
    199                 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;
    203                 toggle = 1 - toggle;
    204 
    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 
     206        batch_data(instance, USB_PID_IN);
    212207        instance->next_step = batch_call_in_and_dispose;
    213208        usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance);
     
    219214        assert(instance);
    220215        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 
     216        batch_data(instance, USB_PID_OUT);
    239217        instance->next_step = batch_call_out_and_dispose;
    240218        usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance);
     
    242220}
    243221/*----------------------------------------------------------------------------*/
    244 static void batch_control(
    245     batch_t *instance, int data_stage, int status_stage)
     222void batch_bulk_in(batch_t *instance)
     223{
     224        assert(instance);
     225        batch_data(instance, USB_PID_IN);
     226        instance->next_step = batch_call_in_and_dispose;
     227        usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
     228        batch_schedule(instance);
     229}
     230/*----------------------------------------------------------------------------*/
     231void batch_bulk_out(batch_t *instance)
     232{
     233        assert(instance);
     234        memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size);
     235        batch_data(instance, USB_PID_OUT);
     236        instance->next_step = batch_call_out_and_dispose;
     237        usb_log_debug("Batch(%p) BULK OUT initialized.\n", instance);
     238        batch_schedule(instance);
     239}
     240/*----------------------------------------------------------------------------*/
     241void batch_data(batch_t *instance, usb_packet_id pid)
     242{
     243        assert(instance);
     244        const bool low_speed = instance->speed == USB_SPEED_LOW;
     245        int toggle = device_keeper_get_toggle(instance->manager, instance->target);
     246        assert(toggle == 0 || toggle == 1);
     247
     248        size_t packet = 0;
     249        size_t remain_size = instance->buffer_size;
     250        while (remain_size > 0) {
     251                char *data =
     252                    instance->transport_buffer + instance->buffer_size
     253                    - remain_size;
     254
     255
     256                const size_t packet_size =
     257                    (instance->max_packet_size > remain_size) ?
     258                    remain_size : instance->max_packet_size;
     259
     260                td_init(&instance->tds[packet],
     261                    DEFAULT_ERROR_COUNT, packet_size, toggle, false, low_speed,
     262                    instance->target, pid, data,
     263                    &instance->tds[packet + 1]);
     264
     265                toggle = 1 - toggle;
     266                ++packet;
     267                assert(packet <= instance->packets);
     268                assert(packet_size <= remain_size);
     269                remain_size -= packet_size;
     270        }
     271        device_keeper_set_toggle(instance->manager, instance->target, toggle);
     272
     273        instance->tds[packet - 1].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG;
     274        instance->tds[packet - 1].next = 0 | LINK_POINTER_TERMINATE_FLAG;
     275}
     276/*----------------------------------------------------------------------------*/
     277void batch_control(batch_t *instance,
     278   usb_packet_id data_stage, usb_packet_id status_stage)
    246279{
    247280        assert(instance);
     
    250283        int toggle = 0;
    251284        /* setup stage */
    252         transfer_descriptor_init(instance->tds, DEFAULT_ERROR_COUNT,
     285        td_init(instance->tds, DEFAULT_ERROR_COUNT,
    253286            instance->setup_size, toggle, false, low_speed, instance->target,
    254287            USB_PID_SETUP, instance->setup_buffer, &instance->tds[1]);
     
    268301                    remain_size : instance->max_packet_size;
    269302
    270                 transfer_descriptor_init(&instance->tds[packet],
     303                td_init(&instance->tds[packet],
    271304                    DEFAULT_ERROR_COUNT, packet_size, toggle, false, low_speed,
    272305                    instance->target, data_stage, data,
     
    281314        /* status stage */
    282315        assert(packet == instance->packets - 1);
    283         transfer_descriptor_init(&instance->tds[packet], DEFAULT_ERROR_COUNT,
     316        td_init(&instance->tds[packet], DEFAULT_ERROR_COUNT,
    284317            0, 1, false, low_speed, instance->target, status_stage, NULL, NULL);
    285318
     
    323356        assert(instance);
    324357        batch_call_in(instance);
     358        batch_dispose(instance);
     359}
     360/*----------------------------------------------------------------------------*/
     361void batch_call_out_and_dispose(batch_t *instance)
     362{
     363        assert(instance);
     364        batch_call_out(instance);
     365        batch_dispose(instance);
     366}
     367/*----------------------------------------------------------------------------*/
     368void batch_dispose(batch_t *instance)
     369{
     370        assert(instance);
    325371        usb_log_debug("Batch(%p) disposing.\n", instance);
    326372        free32(instance->tds);
     
    331377}
    332378/*----------------------------------------------------------------------------*/
    333 void batch_call_out_and_dispose(batch_t *instance)
    334 {
    335         assert(instance);
    336         batch_call_out(instance);
    337         usb_log_debug("Batch(%p) disposing.\n", instance);
    338         free32(instance->tds);
    339         free32(instance->qh);
    340         free32(instance->setup_buffer);
    341         free32(instance->transport_buffer);
    342         free(instance);
    343 }
    344 /*----------------------------------------------------------------------------*/
    345379int batch_schedule(batch_t *instance)
    346380{
  • uspace/drv/uhci-hcd/batch.h

    ra6add7a r960bee9  
    4242#include "uhci_struct/transfer_descriptor.h"
    4343#include "uhci_struct/queue_head.h"
     44#include "utils/device_keeper.h"
    4445
    4546typedef struct batch
     
    6566        ddf_fun_t *fun;
    6667        queue_head_t *qh;
    67         transfer_descriptor_t *tds;
     68        td_t *tds;
    6869        void (*next_step)(struct batch*);
     70        device_keeper_t *manager;
    6971} batch_t;
    7072
     
    7476                char *setup_buffer, size_t setup_size,
    7577    usbhc_iface_transfer_in_callback_t func_in,
    76     usbhc_iface_transfer_out_callback_t func_out, void *arg);
     78    usbhc_iface_transfer_out_callback_t func_out, void *arg,
     79                device_keeper_t *manager
     80                );
    7781
    7882bool batch_is_complete(batch_t *instance);
     
    8690void batch_interrupt_out(batch_t *instance);
    8791
    88 /* DEPRECATED FUNCTIONS NEEDED BY THE OLD API */
    89 void batch_control_setup_old(batch_t *instance);
     92void batch_bulk_in(batch_t *instance);
    9093
    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);
     94void batch_bulk_out(batch_t *instance);
    9895#endif
    9996/**
  • uspace/drv/uhci-hcd/iface.c

    ra6add7a r960bee9  
    114114
    115115        batch_t *batch = batch_get(fun, target, USB_TRANSFER_INTERRUPT,
    116             max_packet_size, speed, data, size, NULL, 0, NULL, callback, arg);
     116            max_packet_size, speed, data, size, NULL, 0, NULL, callback, arg,
     117            &hc->device_manager);
    117118        if (!batch)
    118119                return ENOMEM;
     
    133134
    134135        batch_t *batch = batch_get(fun, target, USB_TRANSFER_INTERRUPT,
    135             max_packet_size, speed, data, size, NULL, 0, callback, NULL, arg);
     136            max_packet_size, speed, data, size, NULL, 0, callback, NULL, arg,
     137                        &hc->device_manager);
    136138        if (!batch)
    137139                return ENOMEM;
    138140        batch_interrupt_in(batch);
     141        return EOK;
     142}
     143/*----------------------------------------------------------------------------*/
     144static int bulk_out(ddf_fun_t *fun, usb_target_t target,
     145    size_t max_packet_size, void *data, size_t size,
     146    usbhc_iface_transfer_out_callback_t callback, void *arg)
     147{
     148        assert(fun);
     149        uhci_t *hc = fun_to_uhci(fun);
     150        assert(hc);
     151        usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
     152
     153        usb_log_debug("Bulk OUT %d:%d %zu(%zu).\n",
     154            target.address, target.endpoint, size, max_packet_size);
     155
     156        batch_t *batch = batch_get(fun, target, USB_TRANSFER_BULK,
     157            max_packet_size, speed, data, size, NULL, 0, NULL, callback, arg,
     158            &hc->device_manager);
     159        if (!batch)
     160                return ENOMEM;
     161        batch_bulk_out(batch);
     162        return EOK;
     163}
     164/*----------------------------------------------------------------------------*/
     165static int bulk_in(ddf_fun_t *fun, usb_target_t target,
     166    size_t max_packet_size, void *data, size_t size,
     167    usbhc_iface_transfer_in_callback_t callback, void *arg)
     168{
     169        assert(fun);
     170        uhci_t *hc = fun_to_uhci(fun);
     171        assert(hc);
     172        usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
     173        usb_log_debug("Bulk IN %d:%d %zu(%zu).\n",
     174            target.address, target.endpoint, size, max_packet_size);
     175
     176        batch_t *batch = batch_get(fun, target, USB_TRANSFER_BULK,
     177            max_packet_size, speed, data, size, NULL, 0, callback, NULL, arg,
     178            &hc->device_manager);
     179        if (!batch)
     180                return ENOMEM;
     181        batch_bulk_in(batch);
    139182        return EOK;
    140183}
     
    152195            target.address, target.endpoint, size, max_packet_size);
    153196
     197        if (setup_size != 8)
     198                return EINVAL;
     199
    154200        batch_t *batch = batch_get(fun, target, USB_TRANSFER_CONTROL,
    155201            max_packet_size, speed, data, size, setup_data, setup_size,
    156             NULL, callback, arg);
    157         if (!batch)
    158                 return ENOMEM;
     202            NULL, callback, arg, &hc->device_manager);
     203        if (!batch)
     204                return ENOMEM;
     205        device_keeper_reset_if_need(&hc->device_manager, target, setup_data);
    159206        batch_control_write(batch);
    160207        return EOK;
     
    175222        batch_t *batch = batch_get(fun, target, USB_TRANSFER_CONTROL,
    176223            max_packet_size, speed, data, size, setup_data, setup_size, callback,
    177             NULL, arg);
     224            NULL, arg, &hc->device_manager);
    178225        if (!batch)
    179226                return ENOMEM;
     
    181228        return EOK;
    182229}
    183 
    184 
    185230/*----------------------------------------------------------------------------*/
    186231usbhc_iface_t uhci_iface = {
     
    194239        .interrupt_in = interrupt_in,
    195240
     241        .bulk_in = bulk_in,
     242        .bulk_out = bulk_out,
     243
    196244        .control_read = control_read,
    197245        .control_write = control_write,
  • uspace/drv/uhci-hcd/uhci.c

    ra6add7a r960bee9  
    167167        /* reset hc, all states and counters */
    168168        pio_write_16(&instance->registers->usbcmd, UHCI_CMD_HCRESET);
    169         while ((pio_read_16(&instance->registers->usbcmd) & UHCI_CMD_HCRESET) != 0)
    170                 { async_usleep(10); }
     169        do { async_usleep(10); }
     170        while ((pio_read_16(&instance->registers->usbcmd) & UHCI_CMD_HCRESET) != 0);
    171171
    172172        /* set framelist pointer */
     
    175175
    176176        /* enable all interrupts, but resume interrupt */
    177         pio_write_16(&instance->registers->usbintr,
    178             UHCI_INTR_CRC | UHCI_INTR_COMPLETE | UHCI_INTR_SHORT_PACKET);
    179 
     177//      pio_write_16(&instance->registers->usbintr,
     178//          UHCI_INTR_CRC | UHCI_INTR_COMPLETE | UHCI_INTR_SHORT_PACKET);
     179
     180        uint16_t status = pio_read_16(&instance->registers->usbcmd);
     181        usb_log_warning("Previous command value: %x.\n", status);
    180182        /* Start the hc with large(64B) packet FSBR */
    181183        pio_write_16(&instance->registers->usbcmd,
     
    336338                uhci_interrupt(instance, status);
    337339                pio_write_16(&instance->registers->usbsts, 0x1f);
    338                 async_usleep(UHCI_CLEANER_TIMEOUT * 5);
     340                async_usleep(UHCI_CLEANER_TIMEOUT);
    339341        }
    340342        return EOK;
  • uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.c

    ra6add7a r960bee9  
    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);
     77        if (pid == USB_PID_SETUP) {
     78                usb_log_debug("SETUP BUFFER: %s\n",
     79                        usb_debug_str_buffer(buffer, 8, 8));
     80        }
    7281}
    7382/*----------------------------------------------------------------------------*/
    74 int transfer_descriptor_status(transfer_descriptor_t *instance)
     83int td_status(td_t *instance)
    7584{
    7685        assert(instance);
  • uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.h

    ra6add7a r960bee9  
    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 int td_toggle(td_t *instance)
     118{
     119        assert(instance);
     120        return ((instance->device & TD_DEVICE_DATA_TOGGLE_ONE_FLAG) != 0)
     121            ? 1 : 0;
     122}
     123
     124static inline bool td_is_active(td_t *instance)
    109125{
    110126        assert(instance);
  • uspace/drv/uhci-hcd/utils/device_keeper.c

    ra6add7a r960bee9  
    4949                instance->devices[i].occupied = false;
    5050                instance->devices[i].handle = 0;
     51                instance->devices[i].toggle_status = 0;
    5152        }
    5253}
     
    7374        fibril_mutex_unlock(&instance->guard);
    7475        fibril_condvar_signal(&instance->default_address_occupied);
     76}
     77/*----------------------------------------------------------------------------*/
     78void device_keeper_reset_if_need(
     79    device_keeper_t *instance, usb_target_t target, const unsigned char *data)
     80{
     81        assert(instance);
     82        fibril_mutex_lock(&instance->guard);
     83        if (target.endpoint > 15 || target.endpoint < 0
     84            || target.address >= USB_ADDRESS_COUNT || target.address < 0
     85            || !instance->devices[target.address].occupied) {
     86                goto the_end;
     87        }
     88
     89        switch (data[1])
     90        {
     91        case 0x01: /*clear feature*/
     92                /* recipient is enpoint, value is zero (ENDPOINT_STALL) */
     93                if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) {
     94                        /* enpoint number is < 16, thus first byte is enough */
     95                        instance->devices[target.address].toggle_status &= ~(1 << data[4]);
     96                }
     97        break;
     98
     99        case 0x9: /* set configuration */
     100        case 0x11: /* set interface */
     101                instance->devices[target.address].toggle_status = 0;
     102        break;
     103        }
     104the_end:
     105        fibril_mutex_unlock(&instance->guard);
     106}
     107/*----------------------------------------------------------------------------*/
     108int device_keeper_get_toggle(device_keeper_t *instance, usb_target_t target)
     109{
     110        assert(instance);
     111        int ret;
     112        fibril_mutex_lock(&instance->guard);
     113        if (target.endpoint > 15 || target.endpoint < 0
     114            || target.address >= USB_ADDRESS_COUNT || target.address < 0
     115            || !instance->devices[target.address].occupied) {
     116                ret = EINVAL;
     117        } else {
     118                ret = (instance->devices[target.address].toggle_status >> target.endpoint) & 1;
     119        }
     120        fibril_mutex_unlock(&instance->guard);
     121        return ret;
     122}
     123/*----------------------------------------------------------------------------*/
     124int device_keeper_set_toggle(
     125    device_keeper_t *instance, usb_target_t target, bool toggle)
     126{
     127        assert(instance);
     128        int ret;
     129        fibril_mutex_lock(&instance->guard);
     130        if (target.endpoint > 15 || target.endpoint < 0
     131            || target.address >= USB_ADDRESS_COUNT || target.address < 0
     132            || !instance->devices[target.address].occupied) {
     133                ret = EINVAL;
     134        } else {
     135                if (toggle) {
     136                        instance->devices[target.address].toggle_status |= (1 << target.endpoint);
     137                } else {
     138                        instance->devices[target.address].toggle_status &= ~(1 << target.endpoint);
     139                }
     140                ret = EOK;
     141        }
     142        fibril_mutex_unlock(&instance->guard);
     143        return ret;
    75144}
    76145/*----------------------------------------------------------------------------*/
     
    96165        instance->devices[new_address].occupied = true;
    97166        instance->devices[new_address].speed = speed;
     167        instance->devices[new_address].toggle_status = 0;
    98168        instance->last_address = new_address;
    99169        fibril_mutex_unlock(&instance->guard);
  • uspace/drv/uhci-hcd/utils/device_keeper.h

    ra6add7a r960bee9  
    4444        usb_speed_t speed;
    4545        bool occupied;
     46        uint16_t toggle_status;
    4647        devman_handle_t handle;
    4748};
     
    5556
    5657void device_keeper_init(device_keeper_t *instance);
     58
    5759void device_keeper_reserve_default(
    5860    device_keeper_t *instance, usb_speed_t speed);
     61
    5962void device_keeper_release_default(device_keeper_t *instance);
     63
     64void device_keeper_reset_if_need(
     65    device_keeper_t *instance, usb_target_t target, const unsigned char *setup_data);
     66
     67int device_keeper_get_toggle(device_keeper_t *instance, usb_target_t target);
     68
     69int device_keeper_set_toggle(
     70    device_keeper_t *instance, usb_target_t target, bool toggle);
    6071
    6172usb_address_t device_keeper_request(
    6273    device_keeper_t *instance, usb_speed_t speed);
     74
    6375void device_keeper_bind(
    6476    device_keeper_t *instance, usb_address_t address, devman_handle_t handle);
     77
    6578void device_keeper_release(device_keeper_t *instance, usb_address_t address);
     79
    6680usb_address_t device_keeper_find(
    6781    device_keeper_t *instance, devman_handle_t handle);
Note: See TracChangeset for help on using the changeset viewer.