Changeset 9d9ffdd in mainline for uspace/drv


Ignore:
Timestamp:
2011-03-11T15:42:43Z (15 years ago)
Author:
Matej Klonfar <maklf@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
0bd4810c
Parents:
60a228f (diff), a8def7d (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 hidd

Location:
uspace/drv
Files:
12 added
39 edited
1 moved

Legend:

Unmodified
Added
Removed
  • uspace/drv/pciintel/pci.c

    r60a228f r9d9ffdd  
    5959#include <ddi.h>
    6060#include <libarch/ddi.h>
     61#include <pci_dev_iface.h>
    6162
    6263#include "pci.h"
     
    9394  sysarg_t apic;
    9495  sysarg_t i8259;
     96
    9597        int irc_phone = -1;
    9698        int irc_service = 0;
     
    102104        }
    103105
    104   if (irc_service) {
    105     while (irc_phone < 0)
    106       irc_phone = service_connect_blocking(irc_service, 0, 0);
    107   } else {
     106  if (irc_service == 0)
    108107                return false;
    109         }
     108
     109        irc_phone = service_connect_blocking(irc_service, 0, 0);
     110        if (irc_phone < 0)
     111                return false;
    110112
    111113        size_t i;
     
    113115                if (dev_data->hw_resources.resources[i].type == INTERRUPT) {
    114116                        int irq = dev_data->hw_resources.resources[i].res.interrupt.irq;
    115                         async_msg_1(irc_phone, IRC_ENABLE_INTERRUPT, irq);
     117                        int rc = async_req_1_0(irc_phone, IRC_ENABLE_INTERRUPT, irq);
     118                        if (rc != EOK) {
     119                                async_hangup(irc_phone);
     120                                return false;
     121                        }
    116122                }
    117123        }
     
    119125        async_hangup(irc_phone);
    120126        return true;
     127}
     128
     129static int pci_config_space_write_32(
     130    ddf_fun_t *fun, uint32_t address, uint32_t data)
     131{
     132        if (address > 252)
     133                return EINVAL;
     134        pci_conf_write_32(PCI_FUN(fun), address, data);
     135        return EOK;
     136}
     137
     138static int pci_config_space_write_16(
     139    ddf_fun_t *fun, uint32_t address, uint16_t data)
     140{
     141        if (address > 254)
     142                return EINVAL;
     143        pci_conf_write_16(PCI_FUN(fun), address, data);
     144        return EOK;
     145}
     146
     147static int pci_config_space_write_8(
     148    ddf_fun_t *fun, uint32_t address, uint8_t data)
     149{
     150        if (address > 255)
     151                return EINVAL;
     152        pci_conf_write_8(PCI_FUN(fun), address, data);
     153        return EOK;
     154}
     155
     156static int pci_config_space_read_32(
     157    ddf_fun_t *fun, uint32_t address, uint32_t *data)
     158{
     159        if (address > 252)
     160                return EINVAL;
     161        *data = pci_conf_read_32(PCI_FUN(fun), address);
     162        return EOK;
     163}
     164
     165static int pci_config_space_read_16(
     166    ddf_fun_t *fun, uint32_t address, uint16_t *data)
     167{
     168        if (address > 254)
     169                return EINVAL;
     170        *data = pci_conf_read_16(PCI_FUN(fun), address);
     171        return EOK;
     172}
     173
     174static int pci_config_space_read_8(
     175    ddf_fun_t *fun, uint32_t address, uint8_t *data)
     176{
     177        if (address > 255)
     178                return EINVAL;
     179        *data = pci_conf_read_8(PCI_FUN(fun), address);
     180        return EOK;
    121181}
    122182
     
    126186};
    127187
    128 static ddf_dev_ops_t pci_fun_ops;
     188static pci_dev_iface_t pci_dev_ops = {
     189        .config_space_read_8 = &pci_config_space_read_8,
     190        .config_space_read_16 = &pci_config_space_read_16,
     191        .config_space_read_32 = &pci_config_space_read_32,
     192        .config_space_write_8 = &pci_config_space_write_8,
     193        .config_space_write_16 = &pci_config_space_write_16,
     194        .config_space_write_32 = &pci_config_space_write_32
     195};
     196
     197static ddf_dev_ops_t pci_fun_ops = {
     198        .interfaces[HW_RES_DEV_IFACE] = &pciintel_hw_res_ops,
     199        .interfaces[PCI_DEV_IFACE] = &pci_dev_ops
     200};
    129201
    130202static int pci_add_device(ddf_dev_t *);
     
    593665{
    594666        pci_fun_ops.interfaces[HW_RES_DEV_IFACE] = &pciintel_hw_res_ops;
     667        pci_fun_ops.interfaces[PCI_DEV_IFACE] = &pci_dev_ops;
    595668}
    596669
  • uspace/drv/uhci-hcd/batch.c

    r60a228f r9d9ffdd  
    3535#include <str_error.h>
    3636
     37#include <usb/usb.h>
    3738#include <usb/debug.h>
    3839
     
    4647static int batch_schedule(batch_t *instance);
    4748
     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);
    4852static void batch_call_in(batch_t *instance);
    4953static void batch_call_out(batch_t *instance);
    5054static void batch_call_in_and_dispose(batch_t *instance);
    5155static void batch_call_out_and_dispose(batch_t *instance);
    52 
    53 
     56static void batch_dispose(batch_t *instance);
     57
     58
     59/** Allocates memory and initializes internal data structures.
     60 *
     61 * @param[in] fun DDF function to pass to callback.
     62 * @param[in] target Device and endpoint target of the transaction.
     63 * @param[in] transfer_type Interrupt, Control or Bulk.
     64 * @param[in] max_packet_size maximum allowed size of data packets.
     65 * @param[in] speed Speed of the transaction.
     66 * @param[in] buffer Data source/destination.
     67 * @param[in] size Size of the buffer.
     68 * @param[in] setup_buffer Setup data source (if not NULL)
     69 * @param[in] setup_size Size of setup_buffer (should be always 8)
     70 * @param[in] func_in function to call on inbound transaction completion
     71 * @param[in] func_out function to call on outbound transaction completion
     72 * @param[in] arg additional parameter to func_in or func_out
     73 * @param[in] manager Pointer to toggle management structure.
     74 * @return False, if there is an active TD, true otherwise.
     75 */
    5476batch_t * batch_get(ddf_fun_t *fun, usb_target_t target,
    5577    usb_transfer_type_t transfer_type, size_t max_packet_size,
     
    5779    char* setup_buffer, size_t setup_size,
    5880    usbhc_iface_transfer_in_callback_t func_in,
    59     usbhc_iface_transfer_out_callback_t func_out, void *arg)
     81    usbhc_iface_transfer_out_callback_t func_out, void *arg,
     82    device_keeper_t *manager
     83    )
    6084{
    6185        assert(func_in == NULL || func_out == NULL);
    6286        assert(func_in != NULL || func_out != NULL);
    6387
     88#define CHECK_NULL_DISPOSE_RETURN(ptr, message...) \
     89        if (ptr == NULL) { \
     90                usb_log_error(message); \
     91                if (instance) { \
     92                        batch_dispose(instance); \
     93                } \
     94                return NULL; \
     95        } else (void)0
     96
    6497        batch_t *instance = malloc(sizeof(batch_t));
    65         if (instance == NULL) {
    66                 usb_log_error("Failed to allocate batch instance.\n");
    67                 return NULL;
    68         }
    69 
    70         instance->qh = queue_head_get();
    71         if (instance->qh == NULL) {
    72                 usb_log_error("Failed to allocate queue head.\n");
    73                 free(instance);
    74                 return NULL;
    75         }
     98        CHECK_NULL_DISPOSE_RETURN(instance,
     99            "Failed to allocate batch instance.\n");
     100        bzero(instance, sizeof(batch_t));
     101
     102        instance->qh = malloc32(sizeof(queue_head_t));
     103        CHECK_NULL_DISPOSE_RETURN(instance->qh,
     104            "Failed to allocate batch queue head.\n");
     105        queue_head_init(instance->qh);
    76106
    77107        instance->packets = (size + max_packet_size - 1) / max_packet_size;
     
    80110        }
    81111
    82         instance->tds = malloc32(sizeof(transfer_descriptor_t) * instance->packets);
    83         if (instance->tds == NULL) {
    84                 usb_log_error("Failed to allocate transfer descriptors.\n");
    85                 queue_head_dispose(instance->qh);
    86                 free(instance);
    87                 return NULL;
    88         }
    89         bzero(instance->tds, sizeof(transfer_descriptor_t) * instance->packets);
    90 
    91         const size_t transport_size = max_packet_size * instance->packets;
    92 
    93         instance->transport_buffer =
    94            (size > 0) ? malloc32(transport_size) : NULL;
    95         if ((size > 0) && (instance->transport_buffer == NULL)) {
    96                 usb_log_error("Failed to allocate device accessible buffer.\n");
    97                 queue_head_dispose(instance->qh);
    98                 free32(instance->tds);
    99                 free(instance);
    100                 return NULL;
    101         }
    102 
    103         instance->setup_buffer = setup_buffer ? malloc32(setup_size) : NULL;
    104         if ((setup_size > 0) && (instance->setup_buffer == NULL)) {
    105                 usb_log_error("Failed to allocate device accessible setup buffer.\n");
    106                 queue_head_dispose(instance->qh);
    107                 free32(instance->tds);
    108                 free32(instance->transport_buffer);
    109                 free(instance);
    110                 return NULL;
    111         }
    112         if (instance->setup_buffer) {
     112        instance->tds = malloc32(sizeof(td_t) * instance->packets);
     113        CHECK_NULL_DISPOSE_RETURN(
     114            instance->tds, "Failed to allocate transfer descriptors.\n");
     115        bzero(instance->tds, sizeof(td_t) * instance->packets);
     116
     117//      const size_t transport_size = max_packet_size * instance->packets;
     118
     119        if (size > 0) {
     120                instance->transport_buffer = malloc32(size);
     121                CHECK_NULL_DISPOSE_RETURN(instance->transport_buffer,
     122                    "Failed to allocate device accessible buffer.\n");
     123        }
     124
     125        if (setup_size > 0) {
     126                instance->setup_buffer = malloc32(setup_size);
     127                CHECK_NULL_DISPOSE_RETURN(instance->setup_buffer,
     128                    "Failed to allocate device accessible setup buffer.\n");
    113129                memcpy(instance->setup_buffer, setup_buffer, setup_size);
    114130        }
    115131
     132
     133        link_initialize(&instance->link);
     134
    116135        instance->max_packet_size = max_packet_size;
    117 
    118         link_initialize(&instance->link);
    119 
    120136        instance->target = target;
    121137        instance->transfer_type = transfer_type;
    122 
    123         if (func_out)
    124                 instance->callback_out = func_out;
    125         if (func_in)
    126                 instance->callback_in = func_in;
    127 
    128138        instance->buffer = buffer;
    129139        instance->buffer_size = size;
     
    132142        instance->arg = arg;
    133143        instance->speed = speed;
    134 
    135         queue_head_element_td(instance->qh, addr_to_phys(instance->tds));
     144        instance->manager = manager;
     145
     146        if (func_out)
     147                instance->callback_out = func_out;
     148        if (func_in)
     149                instance->callback_in = func_in;
     150
     151        queue_head_set_element_td(instance->qh, addr_to_phys(instance->tds));
     152
    136153        usb_log_debug("Batch(%p) %d:%d memory structures ready.\n",
    137154            instance, target.address, target.endpoint);
     
    139156}
    140157/*----------------------------------------------------------------------------*/
     158/** Checks batch TDs for activity.
     159 *
     160 * @param[in] instance Batch structure to use.
     161 * @return False, if there is an active TD, true otherwise.
     162 */
    141163bool batch_is_complete(batch_t *instance)
    142164{
     
    147169        size_t i = 0;
    148170        for (;i < instance->packets; ++i) {
    149                 if (transfer_descriptor_is_active(&instance->tds[i])) {
     171                if (td_is_active(&instance->tds[i])) {
    150172                        return false;
    151173                }
    152                 instance->error = transfer_descriptor_status(&instance->tds[i]);
     174
     175                instance->error = td_status(&instance->tds[i]);
    153176                if (instance->error != EOK) {
     177                        usb_log_debug("Batch(%p) found error TD(%d):%x.\n",
     178                            instance, i, instance->tds[i].status);
     179
     180                        device_keeper_set_toggle(instance->manager,
     181                            instance->target, td_toggle(&instance->tds[i]));
    154182                        if (i > 0)
    155                                 instance->transfered_size -= instance->setup_size;
    156                         usb_log_debug("Batch(%p) found error TD(%d):%x.\n",
    157                           instance, i, instance->tds[i].status);
     183                                goto substract_ret;
    158184                        return true;
    159185                }
    160                 instance->transfered_size +=
    161                     transfer_descriptor_actual_size(&instance->tds[i]);
    162         }
     186
     187                instance->transfered_size += td_act_size(&instance->tds[i]);
     188                if (td_is_short(&instance->tds[i]))
     189                        goto substract_ret;
     190        }
     191substract_ret:
    163192        instance->transfered_size -= instance->setup_size;
    164193        return true;
    165194}
    166195/*----------------------------------------------------------------------------*/
     196/** Prepares control write transaction.
     197 *
     198 * @param[in] instance Batch structure to use.
     199 */
    167200void batch_control_write(batch_t *instance)
    168201{
    169202        assert(instance);
    170 
     203        /* we are data out, we are supposed to provide data */
     204        memcpy(instance->transport_buffer, instance->buffer,
     205            instance->buffer_size);
     206        batch_control(instance, USB_PID_OUT, USB_PID_IN);
     207        instance->next_step = batch_call_out_and_dispose;
     208        usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance);
     209        batch_schedule(instance);
     210}
     211/*----------------------------------------------------------------------------*/
     212/** Prepares control read transaction.
     213 *
     214 * @param[in] instance Batch structure to use.
     215 */
     216void batch_control_read(batch_t *instance)
     217{
     218        assert(instance);
     219        batch_control(instance, USB_PID_IN, USB_PID_OUT);
     220        instance->next_step = batch_call_in_and_dispose;
     221        usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance);
     222        batch_schedule(instance);
     223}
     224/*----------------------------------------------------------------------------*/
     225/** Prepares interrupt in transaction.
     226 *
     227 * @param[in] instance Batch structure to use.
     228 */
     229void batch_interrupt_in(batch_t *instance)
     230{
     231        assert(instance);
     232        batch_data(instance, USB_PID_IN);
     233        instance->next_step = batch_call_in_and_dispose;
     234        usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance);
     235        batch_schedule(instance);
     236}
     237/*----------------------------------------------------------------------------*/
     238/** Prepares interrupt out transaction.
     239 *
     240 * @param[in] instance Batch structure to use.
     241 */
     242void batch_interrupt_out(batch_t *instance)
     243{
     244        assert(instance);
    171245        /* we are data out, we are supposed to provide data */
    172246        memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size);
     247        batch_data(instance, USB_PID_OUT);
     248        instance->next_step = batch_call_out_and_dispose;
     249        usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance);
     250        batch_schedule(instance);
     251}
     252/*----------------------------------------------------------------------------*/
     253/** Prepares bulk in transaction.
     254 *
     255 * @param[in] instance Batch structure to use.
     256 */
     257void batch_bulk_in(batch_t *instance)
     258{
     259        assert(instance);
     260        batch_data(instance, USB_PID_IN);
     261        instance->next_step = batch_call_in_and_dispose;
     262        usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
     263        batch_schedule(instance);
     264}
     265/*----------------------------------------------------------------------------*/
     266/** Prepares bulk out transaction.
     267 *
     268 * @param[in] instance Batch structure to use.
     269 */
     270void batch_bulk_out(batch_t *instance)
     271{
     272        assert(instance);
     273        memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size);
     274        batch_data(instance, USB_PID_OUT);
     275        instance->next_step = batch_call_out_and_dispose;
     276        usb_log_debug("Batch(%p) BULK OUT initialized.\n", instance);
     277        batch_schedule(instance);
     278}
     279/*----------------------------------------------------------------------------*/
     280/** Prepares generic data transaction
     281 *
     282 * @param[in] instance Batch structure to use.
     283 * @param[in] pid to use for data packets.
     284 */
     285void batch_data(batch_t *instance, usb_packet_id pid)
     286{
     287        assert(instance);
     288        const bool low_speed = instance->speed == USB_SPEED_LOW;
     289        int toggle =
     290            device_keeper_get_toggle(instance->manager, instance->target);
     291        assert(toggle == 0 || toggle == 1);
     292
     293        size_t packet = 0;
     294        size_t remain_size = instance->buffer_size;
     295        while (remain_size > 0) {
     296                char *data =
     297                    instance->transport_buffer + instance->buffer_size
     298                    - remain_size;
     299
     300                const size_t packet_size =
     301                    (instance->max_packet_size > remain_size) ?
     302                    remain_size : instance->max_packet_size;
     303
     304                td_t *next_packet = (packet + 1 < instance->packets)
     305                    ? &instance->tds[packet + 1] : NULL;
     306
     307                assert(packet < instance->packets);
     308                assert(packet_size <= remain_size);
     309
     310                td_init(
     311                    &instance->tds[packet], DEFAULT_ERROR_COUNT, packet_size,
     312                    toggle, false, low_speed, instance->target, pid, data,
     313                    next_packet);
     314
     315
     316                toggle = 1 - toggle;
     317                remain_size -= packet_size;
     318                ++packet;
     319        }
     320        device_keeper_set_toggle(instance->manager, instance->target, toggle);
     321}
     322/*----------------------------------------------------------------------------*/
     323/** Prepares generic control transaction
     324 *
     325 * @param[in] instance Batch structure to use.
     326 * @param[in] data_stage to use for data packets.
     327 * @param[in] status_stage to use for data packets.
     328 */
     329void batch_control(batch_t *instance,
     330   usb_packet_id data_stage, usb_packet_id status_stage)
     331{
     332        assert(instance);
    173333
    174334        const bool low_speed = instance->speed == USB_SPEED_LOW;
    175335        int toggle = 0;
    176336        /* setup stage */
    177         transfer_descriptor_init(instance->tds, DEFAULT_ERROR_COUNT,
    178             instance->setup_size, toggle, false, low_speed,
    179             instance->target, USB_PID_SETUP, instance->setup_buffer,
    180             &instance->tds[1]);
    181 
    182         /* data stage */
    183         size_t i = 1;
    184         for (;i < instance->packets - 1; ++i) {
    185                 char *data =
    186                     instance->transport_buffer + ((i - 1) * instance->max_packet_size);
    187                 toggle = 1 - toggle;
    188 
    189                 transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
    190                     instance->max_packet_size, toggle++, false, low_speed,
    191                     instance->target, USB_PID_OUT, data, &instance->tds[i + 1]);
    192         }
    193 
    194         /* status stage */
    195         i = instance->packets - 1;
    196         transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
    197             0, 1, false, low_speed, instance->target, USB_PID_IN, NULL, NULL);
    198 
    199         instance->tds[i].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG;
    200         usb_log_debug2("Control write last TD status: %x.\n",
    201                 instance->tds[i].status);
    202 
    203         instance->next_step = batch_call_out_and_dispose;
    204         usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance);
    205         batch_schedule(instance);
    206 }
    207 /*----------------------------------------------------------------------------*/
    208 void batch_control_read(batch_t *instance)
    209 {
    210         assert(instance);
    211 
    212         const bool low_speed = instance->speed == USB_SPEED_LOW;
    213         int toggle = 0;
    214         /* setup stage */
    215         transfer_descriptor_init(instance->tds, DEFAULT_ERROR_COUNT,
     337        td_init(instance->tds, DEFAULT_ERROR_COUNT,
    216338            instance->setup_size, toggle, false, low_speed, instance->target,
    217339            USB_PID_SETUP, instance->setup_buffer, &instance->tds[1]);
    218340
    219341        /* data stage */
    220         size_t i = 1;
    221         for (;i < instance->packets - 1; ++i) {
     342        size_t packet = 1;
     343        size_t remain_size = instance->buffer_size;
     344        while (remain_size > 0) {
    222345                char *data =
    223                     instance->transport_buffer + ((i - 1) * instance->max_packet_size);
     346                    instance->transport_buffer + instance->buffer_size
     347                    - remain_size;
     348
    224349                toggle = 1 - toggle;
    225350
    226                 transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
    227                     instance->max_packet_size, toggle, false, low_speed,
    228                                 instance->target, USB_PID_IN, data, &instance->tds[i + 1]);
     351                const size_t packet_size =
     352                    (instance->max_packet_size > remain_size) ?
     353                    remain_size : instance->max_packet_size;
     354
     355                td_init(
     356                    &instance->tds[packet], DEFAULT_ERROR_COUNT, packet_size,
     357                    toggle, false, low_speed, instance->target, data_stage,
     358                    data, &instance->tds[packet + 1]);
     359
     360                ++packet;
     361                assert(packet < instance->packets);
     362                assert(packet_size <= remain_size);
     363                remain_size -= packet_size;
    229364        }
    230365
    231366        /* status stage */
    232         i = instance->packets - 1;
    233         transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
    234             0, 1, false, low_speed, instance->target, USB_PID_OUT, NULL, NULL);
    235 
    236         instance->tds[i].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG;
    237         usb_log_debug2("Control read last TD status: %x.\n",
    238                 instance->tds[i].status);
    239 
    240         instance->next_step = batch_call_in_and_dispose;
    241         usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance);
    242         batch_schedule(instance);
    243 }
    244 /*----------------------------------------------------------------------------*/
    245 void batch_interrupt_in(batch_t *instance)
    246 {
    247         assert(instance);
    248 
    249         const bool low_speed = instance->speed == USB_SPEED_LOW;
    250         int toggle = 1;
    251         size_t i = 0;
    252         for (;i < instance->packets; ++i) {
    253                 char *data =
    254                     instance->transport_buffer + (i  * instance->max_packet_size);
    255                 transfer_descriptor_t *next = (i + 1) < instance->packets ?
    256                     &instance->tds[i + 1] : NULL;
    257                 toggle = 1 - toggle;
    258 
    259                 transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
    260                     instance->max_packet_size, toggle, false, low_speed,
    261                     instance->target, USB_PID_IN, data, next);
    262         }
    263 
    264         instance->tds[i - 1].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG;
    265 
    266         instance->next_step = batch_call_in_and_dispose;
    267         usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance);
    268         batch_schedule(instance);
    269 }
    270 /*----------------------------------------------------------------------------*/
    271 void batch_interrupt_out(batch_t *instance)
    272 {
    273         assert(instance);
    274 
    275         memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size);
    276 
    277         const bool low_speed = instance->speed == USB_SPEED_LOW;
    278         int toggle = 1;
    279         size_t i = 0;
    280         for (;i < instance->packets; ++i) {
    281                 char *data =
    282                     instance->transport_buffer + (i  * instance->max_packet_size);
    283                 transfer_descriptor_t *next = (i + 1) < instance->packets ?
    284                     &instance->tds[i + 1] : NULL;
    285                 toggle = 1 - toggle;
    286 
    287                 transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
    288                     instance->max_packet_size, toggle++, false, low_speed,
    289                     instance->target, USB_PID_OUT, data, next);
    290         }
    291 
    292         instance->tds[i - 1].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG;
    293 
    294         instance->next_step = batch_call_out_and_dispose;
    295         usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance);
    296         batch_schedule(instance);
    297 }
    298 /*----------------------------------------------------------------------------*/
     367        assert(packet == instance->packets - 1);
     368        td_init(&instance->tds[packet], DEFAULT_ERROR_COUNT,
     369            0, 1, false, low_speed, instance->target, status_stage, NULL, NULL);
     370
     371
     372        instance->tds[packet].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG;
     373        usb_log_debug2("Control last TD status: %x.\n",
     374            instance->tds[packet].status);
     375}
     376/*----------------------------------------------------------------------------*/
     377/** Prepares data, gets error status and calls callback in.
     378 *
     379 * @param[in] instance Batch structure to use.
     380 */
    299381void batch_call_in(batch_t *instance)
    300382{
     
    302384        assert(instance->callback_in);
    303385
    304         memcpy(instance->buffer, instance->transport_buffer, instance->buffer_size);
     386        /* we are data in, we need data */
     387        memcpy(instance->buffer, instance->transport_buffer,
     388            instance->buffer_size);
    305389
    306390        int err = instance->error;
     
    309393            instance->transfered_size);
    310394
    311         instance->callback_in(instance->fun,
    312             err, instance->transfered_size,
    313             instance->arg);
    314 }
    315 /*----------------------------------------------------------------------------*/
     395        instance->callback_in(
     396            instance->fun, err, instance->transfered_size, instance->arg);
     397}
     398/*----------------------------------------------------------------------------*/
     399/** Gets error status and calls callback out.
     400 *
     401 * @param[in] instance Batch structure to use.
     402 */
    316403void batch_call_out(batch_t *instance)
    317404{
     
    326413}
    327414/*----------------------------------------------------------------------------*/
     415/** Prepares data, gets error status, calls callback in and dispose.
     416 *
     417 * @param[in] instance Batch structure to use.
     418 */
    328419void batch_call_in_and_dispose(batch_t *instance)
    329420{
    330421        assert(instance);
    331422        batch_call_in(instance);
     423        batch_dispose(instance);
     424}
     425/*----------------------------------------------------------------------------*/
     426/** Gets error status, calls callback out and dispose.
     427 *
     428 * @param[in] instance Batch structure to use.
     429 */
     430void batch_call_out_and_dispose(batch_t *instance)
     431{
     432        assert(instance);
     433        batch_call_out(instance);
     434        batch_dispose(instance);
     435}
     436/*----------------------------------------------------------------------------*/
     437/** Correctly disposes all used data structures.
     438 *
     439 * @param[in] instance Batch structure to use.
     440 */
     441void batch_dispose(batch_t *instance)
     442{
     443        assert(instance);
    332444        usb_log_debug("Batch(%p) disposing.\n", instance);
     445        /* free32 is NULL safe */
    333446        free32(instance->tds);
    334447        free32(instance->qh);
     
    338451}
    339452/*----------------------------------------------------------------------------*/
    340 void batch_call_out_and_dispose(batch_t *instance)
    341 {
    342         assert(instance);
    343         batch_call_out(instance);
    344         usb_log_debug("Batch(%p) disposing.\n", instance);
    345         free32(instance->tds);
    346         free32(instance->qh);
    347         free32(instance->setup_buffer);
    348         free32(instance->transport_buffer);
    349         free(instance);
    350 }
    351 /*----------------------------------------------------------------------------*/
    352453int batch_schedule(batch_t *instance)
    353454{
  • uspace/drv/uhci-hcd/batch.h

    r60a228f r9d9ffdd  
    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

    r60a228f r9d9ffdd  
    4343#include "utils/device_keeper.h"
    4444
     45/** Reserve default address interface function
     46 *
     47 * @param[in] fun DDF function that was called.
     48 * @param[in] speed Speed to associate with the new default address.
     49 * @return Error code.
     50 */
    4551/*----------------------------------------------------------------------------*/
    4652static int reserve_default_address(ddf_fun_t *fun, usb_speed_t speed)
     
    5460}
    5561/*----------------------------------------------------------------------------*/
     62/** Release default address interface function
     63 *
     64 * @param[in] fun DDF function that was called.
     65 * @return Error code.
     66 */
    5667static int release_default_address(ddf_fun_t *fun)
    5768{
     
    6475}
    6576/*----------------------------------------------------------------------------*/
     77/** Request address interface function
     78 *
     79 * @param[in] fun DDF function that was called.
     80 * @param[in] speed Speed to associate with the new default address.
     81 * @param[out] address Place to write a new address.
     82 * @return Error code.
     83 */
    6684static int request_address(ddf_fun_t *fun, usb_speed_t speed,
    6785    usb_address_t *address)
     
    8098}
    8199/*----------------------------------------------------------------------------*/
     100/** Bind address interface function
     101 *
     102 * @param[in] fun DDF function that was called.
     103 * @param[in] address Address of the device
     104 * @param[in] handle Devman handle of the device driver.
     105 * @return Error code.
     106 */
    82107static int bind_address(
    83108  ddf_fun_t *fun, usb_address_t address, devman_handle_t handle)
     
    91116}
    92117/*----------------------------------------------------------------------------*/
     118/** Release address interface function
     119 *
     120 * @param[in] fun DDF function that was called.
     121 * @param[in] address USB address to be released.
     122 * @return Error code.
     123 */
    93124static int release_address(ddf_fun_t *fun, usb_address_t address)
    94125{
     
    101132}
    102133/*----------------------------------------------------------------------------*/
     134/** Interrupt out transaction interface function
     135 *
     136 * @param[in] fun DDF function that was called.
     137 * @param[in] target USB device to write to.
     138 * @param[in] max_packet_size maximum size of data packet the device accepts
     139 * @param[in] data Source of data.
     140 * @param[in] size Size of data source.
     141 * @param[in] callback Function to call on transaction completion
     142 * @param[in] arg Additional for callback function.
     143 * @return Error code.
     144 */
    103145static int interrupt_out(ddf_fun_t *fun, usb_target_t target,
    104146    size_t max_packet_size, void *data, size_t size,
     
    114156
    115157        batch_t *batch = batch_get(fun, target, USB_TRANSFER_INTERRUPT,
    116             max_packet_size, speed, data, size, NULL, 0, NULL, callback, arg);
     158            max_packet_size, speed, data, size, NULL, 0, NULL, callback, arg,
     159            &hc->device_manager);
    117160        if (!batch)
    118161                return ENOMEM;
     
    121164}
    122165/*----------------------------------------------------------------------------*/
     166/** Interrupt in transaction interface function
     167 *
     168 * @param[in] fun DDF function that was called.
     169 * @param[in] target USB device to write to.
     170 * @param[in] max_packet_size maximum size of data packet the device accepts
     171 * @param[out] data Data destination.
     172 * @param[in] size Size of data source.
     173 * @param[in] callback Function to call on transaction completion
     174 * @param[in] arg Additional for callback function.
     175 * @return Error code.
     176 */
    123177static int interrupt_in(ddf_fun_t *fun, usb_target_t target,
    124178    size_t max_packet_size, void *data, size_t size,
     
    133187
    134188        batch_t *batch = batch_get(fun, target, USB_TRANSFER_INTERRUPT,
    135             max_packet_size, speed, data, size, NULL, 0, callback, NULL, arg);
     189            max_packet_size, speed, data, size, NULL, 0, callback, NULL, arg,
     190                        &hc->device_manager);
    136191        if (!batch)
    137192                return ENOMEM;
     
    140195}
    141196/*----------------------------------------------------------------------------*/
     197/** Bulk out transaction interface function
     198 *
     199 * @param[in] fun DDF function that was called.
     200 * @param[in] target USB device to write to.
     201 * @param[in] max_packet_size maximum size of data packet the device accepts
     202 * @param[in] data Source of data.
     203 * @param[in] size Size of data source.
     204 * @param[in] callback Function to call on transaction completion
     205 * @param[in] arg Additional for callback function.
     206 * @return Error code.
     207 */
     208static int bulk_out(ddf_fun_t *fun, usb_target_t target,
     209    size_t max_packet_size, void *data, size_t size,
     210    usbhc_iface_transfer_out_callback_t callback, void *arg)
     211{
     212        assert(fun);
     213        uhci_t *hc = fun_to_uhci(fun);
     214        assert(hc);
     215        usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
     216
     217        usb_log_debug("Bulk OUT %d:%d %zu(%zu).\n",
     218            target.address, target.endpoint, size, max_packet_size);
     219
     220        batch_t *batch = batch_get(fun, target, USB_TRANSFER_BULK,
     221            max_packet_size, speed, data, size, NULL, 0, NULL, callback, arg,
     222            &hc->device_manager);
     223        if (!batch)
     224                return ENOMEM;
     225        batch_bulk_out(batch);
     226        return EOK;
     227}
     228/*----------------------------------------------------------------------------*/
     229/** Bulk in transaction interface function
     230 *
     231 * @param[in] fun DDF function that was called.
     232 * @param[in] target USB device to write to.
     233 * @param[in] max_packet_size maximum size of data packet the device accepts
     234 * @param[out] data Data destination.
     235 * @param[in] size Size of data source.
     236 * @param[in] callback Function to call on transaction completion
     237 * @param[in] arg Additional for callback function.
     238 * @return Error code.
     239 */
     240static int bulk_in(ddf_fun_t *fun, usb_target_t target,
     241    size_t max_packet_size, void *data, size_t size,
     242    usbhc_iface_transfer_in_callback_t callback, void *arg)
     243{
     244        assert(fun);
     245        uhci_t *hc = fun_to_uhci(fun);
     246        assert(hc);
     247        usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
     248        usb_log_debug("Bulk IN %d:%d %zu(%zu).\n",
     249            target.address, target.endpoint, size, max_packet_size);
     250
     251        batch_t *batch = batch_get(fun, target, USB_TRANSFER_BULK,
     252            max_packet_size, speed, data, size, NULL, 0, callback, NULL, arg,
     253            &hc->device_manager);
     254        if (!batch)
     255                return ENOMEM;
     256        batch_bulk_in(batch);
     257        return EOK;
     258}
     259/*----------------------------------------------------------------------------*/
     260/** Control write transaction interface function
     261 *
     262 * @param[in] fun DDF function that was called.
     263 * @param[in] target USB device to write to.
     264 * @param[in] max_packet_size maximum size of data packet the device accepts.
     265 * @param[in] setup_data Data to send with SETUP packet.
     266 * @param[in] setup_size Size of data to send with SETUP packet (should be 8B).
     267 * @param[in] data Source of data.
     268 * @param[in] size Size of data source.
     269 * @param[in] callback Function to call on transaction completion.
     270 * @param[in] arg Additional for callback function.
     271 * @return Error code.
     272 */
    142273static int control_write(ddf_fun_t *fun, usb_target_t target,
    143274    size_t max_packet_size,
     
    152283            target.address, target.endpoint, size, max_packet_size);
    153284
     285        if (setup_size != 8)
     286                return EINVAL;
     287
    154288        batch_t *batch = batch_get(fun, target, USB_TRANSFER_CONTROL,
    155289            max_packet_size, speed, data, size, setup_data, setup_size,
    156             NULL, callback, arg);
    157         if (!batch)
    158                 return ENOMEM;
     290            NULL, callback, arg, &hc->device_manager);
     291        if (!batch)
     292                return ENOMEM;
     293        device_keeper_reset_if_need(&hc->device_manager, target, setup_data);
    159294        batch_control_write(batch);
    160295        return EOK;
    161296}
    162297/*----------------------------------------------------------------------------*/
     298/** Control read transaction interface function
     299 *
     300 * @param[in] fun DDF function that was called.
     301 * @param[in] target USB device to write to.
     302 * @param[in] max_packet_size maximum size of data packet the device accepts.
     303 * @param[in] setup_data Data to send with SETUP packet.
     304 * @param[in] setup_size Size of data to send with SETUP packet (should be 8B).
     305 * @param[out] data Source of data.
     306 * @param[in] size Size of data source.
     307 * @param[in] callback Function to call on transaction completion.
     308 * @param[in] arg Additional for callback function.
     309 * @return Error code.
     310 */
    163311static int control_read(ddf_fun_t *fun, usb_target_t target,
    164312    size_t max_packet_size,
     
    175323        batch_t *batch = batch_get(fun, target, USB_TRANSFER_CONTROL,
    176324            max_packet_size, speed, data, size, setup_data, setup_size, callback,
    177             NULL, arg);
     325            NULL, arg, &hc->device_manager);
    178326        if (!batch)
    179327                return ENOMEM;
     
    181329        return EOK;
    182330}
    183 
    184 
    185331/*----------------------------------------------------------------------------*/
    186332usbhc_iface_t uhci_iface = {
     
    194340        .interrupt_in = interrupt_in,
    195341
     342        .bulk_in = bulk_in,
     343        .bulk_out = bulk_out,
     344
    196345        .control_read = control_read,
    197346        .control_write = control_write,
  • uspace/drv/uhci-hcd/main.c

    r60a228f r9d9ffdd  
    3434#include <ddf/driver.h>
    3535#include <ddf/interrupt.h>
     36#include <device/hw_res.h>
     37#include <errno.h>
     38#include <str_error.h>
     39
    3640#include <usb_iface.h>
    3741#include <usb/ddfiface.h>
    38 #include <device/hw_res.h>
    39 
    40 #include <errno.h>
    41 
    4242#include <usb/debug.h>
    4343
     
    5050
    5151static int uhci_add_device(ddf_dev_t *device);
    52 
    5352/*----------------------------------------------------------------------------*/
    5453static driver_ops_t uhci_driver_ops = {
     
    6160};
    6261/*----------------------------------------------------------------------------*/
     62/** IRQ handling callback, identifies devic
     63 *
     64 * @param[in] dev DDF instance of the device to use.
     65 * @param[in] iid (Unused).
     66 * @param[in] call Pointer to the call that represents interrupt.
     67 */
    6368static void irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call)
    6469{
     
    7075}
    7176/*----------------------------------------------------------------------------*/
    72 #define CHECK_RET_RETURN(ret, message...) \
     77/** Initializes a new ddf driver instance of UHCI hcd.
     78 *
     79 * @param[in] device DDF instance of the device to initialize.
     80 * @return Error code.
     81 *
     82 * Gets and initialies hardware resources, disables any legacy support,
     83 * and reports root hub device.
     84 */
     85int uhci_add_device(ddf_dev_t *device)
     86{
     87        assert(device);
     88        uhci_t *hcd = NULL;
     89#define CHECK_RET_FREE_HC_RETURN(ret, message...) \
    7390if (ret != EOK) { \
    7491        usb_log_error(message); \
     92        if (hcd != NULL) \
     93                free(hcd); \
    7594        return ret; \
    7695}
    77 
    78 static int uhci_add_device(ddf_dev_t *device)
    79 {
    80         assert(device);
    8196
    8297        usb_log_info("uhci_add_device() called\n");
     
    88103        int ret =
    89104            pci_get_my_registers(device, &io_reg_base, &io_reg_size, &irq);
    90 
    91         CHECK_RET_RETURN(ret,
     105        CHECK_RET_FREE_HC_RETURN(ret,
    92106            "Failed(%d) to get I/O addresses:.\n", ret, device->handle);
    93107        usb_log_info("I/O regs at 0x%X (size %zu), IRQ %d.\n",
    94108            io_reg_base, io_reg_size, irq);
    95109
    96 //      ret = pci_enable_interrupts(device);
    97 //      CHECK_RET_RETURN(ret, "Failed(%d) to get enable interrupts:\n", ret);
     110        ret = pci_disable_legacy(device);
     111        CHECK_RET_FREE_HC_RETURN(ret,
     112            "Failed(%d) to disable legacy USB: %s.\n", ret, str_error(ret));
    98113
    99         uhci_t *uhci_hc = malloc(sizeof(uhci_t));
    100         ret = (uhci_hc != NULL) ? EOK : ENOMEM;
    101         CHECK_RET_RETURN(ret, "Failed to allocate memory for uhci hcd driver.\n");
     114#if 0
     115        ret = pci_enable_interrupts(device);
     116        if (ret != EOK) {
     117                usb_log_warning(
     118                    "Failed(%d) to enable interrupts, fall back to polling.\n",
     119                    ret);
     120        }
     121#endif
    102122
    103         ret = uhci_init(uhci_hc, device, (void*)io_reg_base, io_reg_size);
    104         if (ret != EOK) {
    105                 usb_log_error("Failed to init uhci-hcd.\n");
    106                 free(uhci_hc);
    107                 return ret;
    108         }
     123        hcd = malloc(sizeof(uhci_t));
     124        ret = (hcd != NULL) ? EOK : ENOMEM;
     125        CHECK_RET_FREE_HC_RETURN(ret,
     126            "Failed(%d) to allocate memory for uhci hcd.\n", ret);
     127
     128        ret = uhci_init(hcd, device, (void*)io_reg_base, io_reg_size);
     129        CHECK_RET_FREE_HC_RETURN(ret, "Failed(%d) to init uhci-hcd.\n", ret);
     130#undef CHECK_RET_FREE_HC_RETURN
    109131
    110132        /*
    111          * We might free uhci_hc, but that does not matter since no one
     133         * We might free hcd, but that does not matter since no one
    112134         * else would access driver_data anyway.
    113135         */
    114         device->driver_data = uhci_hc;
     136        device->driver_data = hcd;
     137
     138        ddf_fun_t *rh = NULL;
     139#define CHECK_RET_FINI_FREE_RETURN(ret, message...) \
     140if (ret != EOK) { \
     141        usb_log_error(message); \
     142        if (hcd != NULL) {\
     143                uhci_fini(hcd); \
     144                free(hcd); \
     145        } \
     146        if (rh != NULL) \
     147                free(rh); \
     148        return ret; \
     149}
     150
     151        /* It does no harm if we register this on polling */
    115152        ret = register_interrupt_handler(device, irq, irq_handler,
    116             &uhci_hc->interrupt_code);
    117         if (ret != EOK) {
    118                 usb_log_error("Failed to register interrupt handler.\n");
    119                 uhci_fini(uhci_hc);
    120                 free(uhci_hc);
    121                 return ret;
    122         }
     153            &hcd->interrupt_code);
     154        CHECK_RET_FINI_FREE_RETURN(ret,
     155            "Failed(%d) to register interrupt handler.\n", ret);
    123156
    124         ddf_fun_t *rh;
    125157        ret = setup_root_hub(&rh, device);
    126         if (ret != EOK) {
    127                 usb_log_error("Failed to setup uhci root hub.\n");
    128                 uhci_fini(uhci_hc);
    129                 free(uhci_hc);
    130                 return ret;
    131         }
    132         rh->driver_data = uhci_hc->ddf_instance;
     158        CHECK_RET_FINI_FREE_RETURN(ret,
     159            "Failed(%d) to setup UHCI root hub.\n", ret);
     160        rh->driver_data = hcd->ddf_instance;
    133161
    134162        ret = ddf_fun_bind(rh);
    135         if (ret != EOK) {
    136                 usb_log_error("Failed to register root hub.\n");
    137                 uhci_fini(uhci_hc);
    138                 free(uhci_hc);
    139                 free(rh);
    140                 return ret;
    141         }
     163        CHECK_RET_FINI_FREE_RETURN(ret,
     164            "Failed(%d) to register UHCI root hub.\n", ret);
    142165
    143166        return EOK;
     167#undef CHECK_RET_FINI_FREE_RETURN
    144168}
    145169/*----------------------------------------------------------------------------*/
     170/** Initializes global driver structures (NONE).
     171 *
     172 * @param[in] argc Nmber of arguments in argv vector (ignored).
     173 * @param[in] argv Cmdline argument vector (ignored).
     174 * @return Error code.
     175 *
     176 * Driver debug level is set here.
     177 */
    146178int main(int argc, char *argv[])
    147179{
  • uspace/drv/uhci-hcd/pci.c

    r60a228f r9d9ffdd  
    4040
    4141#include <usb/debug.h>
     42#include <pci_dev_iface.h>
    4243
    4344#include "pci.h"
     
    6465
    6566        int rc;
    66 
    6767        hw_resource_list_t hw_resources;
    6868        rc = hw_res_get_resource_list(parent_phone, &hw_resources);
     
    8181        for (i = 0; i < hw_resources.count; i++) {
    8282                hw_resource_t *res = &hw_resources.resources[i];
    83                 switch (res->type) {
    84                         case INTERRUPT:
    85                                 irq = res->res.interrupt.irq;
    86                                 irq_found = true;
    87                                 usb_log_debug2("Found interrupt: %d.\n", irq);
    88                                 break;
    89                         case IO_RANGE:
    90                                 io_address = res->res.io_range.address;
    91                                 io_size = res->res.io_range.size;
    92                                 usb_log_debug2("Found io: %llx %zu.\n",
    93                                     res->res.io_range.address, res->res.io_range.size);
    94                                 io_found = true;
    95                                 break;
    96                         default:
    97                                 break;
     83                switch (res->type)
     84                {
     85                case INTERRUPT:
     86                        irq = res->res.interrupt.irq;
     87                        irq_found = true;
     88                        usb_log_debug2("Found interrupt: %d.\n", irq);
     89                        break;
     90
     91                case IO_RANGE:
     92                        io_address = res->res.io_range.address;
     93                        io_size = res->res.io_range.size;
     94                        usb_log_debug2("Found io: %llx %zu.\n",
     95                            res->res.io_range.address, res->res.io_range.size);
     96                        io_found = true;
     97
     98                default:
     99                        break;
    98100                }
    99101        }
    100102
    101         if (!io_found) {
    102                 rc = ENOENT;
    103                 goto leave;
    104         }
    105 
    106         if (!irq_found) {
     103        if (!io_found || !irq_found) {
    107104                rc = ENOENT;
    108105                goto leave;
     
    120117}
    121118/*----------------------------------------------------------------------------*/
     119/** Calls the PCI driver with a request to enable interrupts
     120 *
     121 * @param[in] device Device asking for interrupts
     122 * @return Error code.
     123 */
    122124int pci_enable_interrupts(ddf_dev_t *device)
    123125{
     
    128130        return enabled ? EOK : EIO;
    129131}
     132/*----------------------------------------------------------------------------*/
     133/** Calls the PCI driver with a request to clear legacy support register
     134 *
     135 * @param[in] device Device asking to disable interrupts
     136 * @return Error code.
     137 */
     138int pci_disable_legacy(ddf_dev_t *device)
     139{
     140        assert(device);
     141        int parent_phone =
     142            devman_parent_device_connect(device->handle, IPC_FLAG_BLOCKING);
     143        if (parent_phone < 0) {
     144                return parent_phone;
     145        }
     146
     147        /* See UHCI design guide for these values,
     148         * write all WC bits in USB legacy register */
     149        sysarg_t address = 0xc0;
     150        sysarg_t value = 0x8f00;
     151
     152        int rc = async_req_3_0(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
     153            IPC_M_CONFIG_SPACE_WRITE_16, address, value);
     154        async_hangup(parent_phone);
     155
     156        return rc;
     157}
     158/*----------------------------------------------------------------------------*/
    130159/**
    131160 * @}
  • uspace/drv/uhci-hcd/pci.h

    r60a228f r9d9ffdd  
    4040int pci_get_my_registers(ddf_dev_t *, uintptr_t *, size_t *, int *);
    4141int pci_enable_interrupts(ddf_dev_t *);
     42int pci_disable_legacy(ddf_dev_t *);
    4243
    4344#endif
  • uspace/drv/uhci-hcd/root_hub.c

    r60a228f r9d9ffdd  
    4545
    4646/*----------------------------------------------------------------------------*/
    47 static int usb_iface_get_hc_handle_rh_impl(ddf_fun_t *root_hub_fun,
    48     devman_handle_t *handle)
     47/** Gets handle of the respective hc (parent device).
     48 *
     49 * @param[in] root_hub_fun Root hub function seeking hc handle.
     50 * @param[out] handle Place to write the handle.
     51 * @return Error code.
     52 */
     53static int usb_iface_get_hc_handle_rh_impl(
     54    ddf_fun_t *root_hub_fun, devman_handle_t *handle)
    4955{
     56        /* TODO: Can't this use parent pointer? */
    5057        ddf_fun_t *hc_fun = root_hub_fun->driver_data;
    5158        assert(hc_fun != NULL);
     
    5663}
    5764/*----------------------------------------------------------------------------*/
    58 static int usb_iface_get_address_rh_impl(ddf_fun_t *fun, devman_handle_t handle,
    59     usb_address_t *address)
     65/** Gets USB address of the calling device.
     66 *
     67 * @param[in] fun Root hub function.
     68 * @param[in] handle Handle of the device seeking address.
     69 * @param[out] address Place to store found address.
     70 * @return Error code.
     71 */
     72static int usb_iface_get_address_rh_impl(
     73    ddf_fun_t *fun, devman_handle_t handle, usb_address_t *address)
    6074{
     75        /* TODO: What does this do? Is it neccessary? Can't it use implemented
     76         * hc function?*/
    6177        assert(fun);
    6278        ddf_fun_t *hc_fun = fun->driver_data;
     
    6581        assert(hc);
    6682
    67         usb_address_t addr = device_keeper_find(&hc->device_manager,
    68             handle);
     83        usb_address_t addr = device_keeper_find(&hc->device_manager, handle);
    6984        if (addr < 0) {
    7085                return addr;
     
    8398};
    8499/*----------------------------------------------------------------------------*/
     100/** Gets root hub hw resources.
     101 *
     102 * @param[in] fun Root hub function.
     103 * @return Pointer to the resource list used by the root hub.
     104 */
    85105static hw_resource_list_t *get_resource_list(ddf_fun_t *dev)
    86106{
     
    91111        assert(hc);
    92112
    93         //TODO: fix memory leak
     113        /* TODO: fix memory leak */
    94114        hw_resource_list_t *resource_list = malloc(sizeof(hw_resource_list_t));
    95115        assert(resource_list);
  • uspace/drv/uhci-hcd/transfer_list.c

    r60a228f r9d9ffdd  
    3838#include "transfer_list.h"
    3939
     40static void transfer_list_remove_batch(
     41    transfer_list_t *instance, batch_t *batch);
     42/*----------------------------------------------------------------------------*/
     43/** Initializes transfer list structures.
     44 *
     45 * @param[in] instance Memory place to use.
     46 * @param[in] name Name of te new list.
     47 * @return Error code
     48 *
     49 * Allocates memory for internat queue_head_t structure.
     50 */
    4051int transfer_list_init(transfer_list_t *instance, const char *name)
    4152{
     
    4354        instance->next = NULL;
    4455        instance->name = name;
    45         instance->queue_head = queue_head_get();
     56        instance->queue_head = malloc32(sizeof(queue_head_t));
    4657        if (!instance->queue_head) {
    4758                usb_log_error("Failed to allocate queue head.\n");
    4859                return ENOMEM;
    4960        }
    50         instance->queue_head_pa = (uintptr_t)addr_to_phys(instance->queue_head);
     61        instance->queue_head_pa = addr_to_phys(instance->queue_head);
    5162
    5263        queue_head_init(instance->queue_head);
     
    5667}
    5768/*----------------------------------------------------------------------------*/
     69/** Set the next list in chain.
     70 *
     71 * @param[in] instance List to lead.
     72 * @param[in] next List to append.
     73 * @return Error code
     74 */
    5875void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next)
    5976{
     
    6683}
    6784/*----------------------------------------------------------------------------*/
     85/** Submits a new transfer batch to list and queue.
     86 *
     87 * @param[in] instance List to use.
     88 * @param[in] batch Transfer batch to submit.
     89 * @return Error code
     90 */
    6891void transfer_list_add_batch(transfer_list_t *instance, batch_t *batch)
    6992{
    7093        assert(instance);
    7194        assert(batch);
    72         usb_log_debug2("Adding batch(%p) to queue %s.\n", batch, instance->name);
     95        usb_log_debug2(
     96            "Adding batch(%p) to queue %s.\n", batch, instance->name);
    7397
    7498        uint32_t pa = (uintptr_t)addr_to_phys(batch->qh);
     
    97121        queue_head_append_qh(last->qh, pa);
    98122        list_append(&batch->link, &instance->batch_list);
     123
    99124        usb_log_debug("Batch(%p) added to queue %s last, first is %p.\n",
    100                 batch, instance->name, first );
     125                batch, instance->name, first);
    101126        fibril_mutex_unlock(&instance->guard);
    102127}
    103128/*----------------------------------------------------------------------------*/
    104 static void transfer_list_remove_batch(
    105     transfer_list_t *instance, batch_t *batch)
     129/** Removes a transfer batch from list and queue.
     130 *
     131 * @param[in] instance List to use.
     132 * @param[in] batch Transfer batch to remove.
     133 * @return Error code
     134 */
     135void transfer_list_remove_batch(transfer_list_t *instance, batch_t *batch)
    106136{
    107137        assert(instance);
     
    109139        assert(instance->queue_head);
    110140        assert(batch->qh);
    111         usb_log_debug2("Removing batch(%p) from queue %s.\n", batch, instance->name);
     141        usb_log_debug2(
     142            "Removing batch(%p) from queue %s.\n", batch, instance->name);
    112143
    113         /* I'm the first one here */
    114144        if (batch->link.prev == &instance->batch_list) {
    115                 usb_log_debug("Batch(%p) removed (FIRST) from queue %s, next element %x.\n",
    116                         batch, instance->name, batch->qh->next_queue);
     145                /* I'm the first one here */
     146                usb_log_debug(
     147                    "Batch(%p) removed (FIRST) from %s, next element %x.\n",
     148                    batch, instance->name, batch->qh->next_queue);
    117149                instance->queue_head->element = batch->qh->next_queue;
    118150        } else {
    119                 usb_log_debug("Batch(%p) removed (NOT FIRST) from queue, next element %x.\n",
    120                         batch, instance->name, batch->qh->next_queue);
    121                 batch_t *prev = list_get_instance(batch->link.prev, batch_t, link);
     151                usb_log_debug(
     152                    "Batch(%p) removed (FIRST:NO) from %s, next element %x.\n",
     153                    batch, instance->name, batch->qh->next_queue);
     154                batch_t *prev =
     155                    list_get_instance(batch->link.prev, batch_t, link);
    122156                prev->qh->next_queue = batch->qh->next_queue;
    123157        }
     
    125159}
    126160/*----------------------------------------------------------------------------*/
     161/** Checks list for finished transfers.
     162 *
     163 * @param[in] instance List to use.
     164 * @return Error code
     165 */
    127166void transfer_list_remove_finished(transfer_list_t *instance)
    128167{
  • uspace/drv/uhci-hcd/transfer_list.h

    r60a228f r9d9ffdd  
    5858{
    5959        assert(instance);
    60         queue_head_dispose(instance->queue_head);
     60        free32(instance->queue_head);
    6161}
    6262void transfer_list_remove_finished(transfer_list_t *instance);
  • uspace/drv/uhci-hcd/uhci.c

    r60a228f r9d9ffdd  
    6161};
    6262
    63 static int usb_iface_get_address(ddf_fun_t *fun, devman_handle_t handle,
    64     usb_address_t *address)
     63/** Gets USB address of the calling device.
     64 *
     65 * @param[in] fun UHCI hc function.
     66 * @param[in] handle Handle of the device seeking address.
     67 * @param[out] address Place to store found address.
     68 * @return Error code.
     69 */
     70static int usb_iface_get_address(
     71    ddf_fun_t *fun, devman_handle_t handle, usb_address_t *address)
    6572{
    6673        assert(fun);
     
    9097        .interfaces[USBHC_DEV_IFACE] = &uhci_iface,
    9198};
    92 
     99/*----------------------------------------------------------------------------*/
    93100static int uhci_init_transfer_lists(uhci_t *instance);
    94101static int uhci_init_mem_structures(uhci_t *instance);
     
    99106
    100107static bool allowed_usb_packet(
    101         bool low_speed, usb_transfer_type_t, size_t size);
    102 
    103 
     108    bool low_speed, usb_transfer_type_t transfer, size_t size);
     109/*----------------------------------------------------------------------------*/
     110/** Initializes UHCI hcd driver structure
     111 *
     112 * @param[in] instance Memory place to initialize.
     113 * @param[in] dev DDF device.
     114 * @param[in] regs Address of I/O control registers.
     115 * @param[in] size Size of I/O control registers.
     116 * @return Error code.
     117 * @note Should be called only once on any structure.
     118 */
    104119int uhci_init(uhci_t *instance, ddf_dev_t *dev, void *regs, size_t reg_size)
    105120{
     
    115130        } else (void) 0
    116131
    117         /*
    118          * Create UHCI function.
    119          */
     132        /* Create UHCI function. */
    120133        instance->ddf_instance = ddf_fun_create(dev, fun_exposed, "uhci");
    121134        ret = (instance->ddf_instance == NULL) ? ENOMEM : EOK;
    122         CHECK_RET_DEST_FUN_RETURN(ret, "Failed to create UHCI device function.\n");
     135        CHECK_RET_DEST_FUN_RETURN(ret,
     136            "Failed to create UHCI device function.\n");
    123137
    124138        instance->ddf_instance->ops = &uhci_ops;
     
    126140
    127141        ret = ddf_fun_bind(instance->ddf_instance);
    128         CHECK_RET_DEST_FUN_RETURN(ret, "Failed(%d) to bind UHCI device function: %s.\n",
     142        CHECK_RET_DEST_FUN_RETURN(ret,
     143            "Failed(%d) to bind UHCI device function: %s.\n",
    129144            ret, str_error(ret));
    130145
     
    132147        regs_t *io;
    133148        ret = pio_enable(regs, reg_size, (void**)&io);
    134         CHECK_RET_DEST_FUN_RETURN(ret, "Failed(%d) to gain access to registers at %p: %s.\n",
     149        CHECK_RET_DEST_FUN_RETURN(ret,
     150            "Failed(%d) to gain access to registers at %p: %s.\n",
    135151            ret, str_error(ret), io);
    136152        instance->registers = io;
    137         usb_log_debug("Device registers at %p(%u) accessible.\n", io, reg_size);
     153        usb_log_debug("Device registers at %p(%u) accessible.\n",
     154            io, reg_size);
    138155
    139156        ret = uhci_init_mem_structures(instance);
    140         CHECK_RET_DEST_FUN_RETURN(ret, "Failed to initialize UHCI memory structures.\n");
     157        CHECK_RET_DEST_FUN_RETURN(ret,
     158            "Failed to initialize UHCI memory structures.\n");
    141159
    142160        uhci_init_hw(instance);
    143 
    144         instance->cleaner = fibril_create(uhci_interrupt_emulator, instance);
     161        instance->cleaner =
     162            fibril_create(uhci_interrupt_emulator, instance);
    145163        fibril_add_ready(instance->cleaner);
    146164
     
    153171}
    154172/*----------------------------------------------------------------------------*/
     173/** Initializes UHCI hcd hw resources.
     174 *
     175 * @param[in] instance UHCI structure to use.
     176 */
    155177void uhci_init_hw(uhci_t *instance)
    156178{
    157         /* reset everything, who knows what touched it before us */
    158         pio_write_16(&instance->registers->usbcmd, UHCI_CMD_GLOBAL_RESET);
     179        assert(instance);
     180        regs_t *registers = instance->registers;
     181
     182        /* Reset everything, who knows what touched it before us */
     183        pio_write_16(&registers->usbcmd, UHCI_CMD_GLOBAL_RESET);
    159184        async_usleep(10000); /* 10ms according to USB spec */
    160         pio_write_16(&instance->registers->usbcmd, 0);
    161 
    162         /* reset hc, all states and counters */
    163         pio_write_16(&instance->registers->usbcmd, UHCI_CMD_HCRESET);
    164         while ((pio_read_16(&instance->registers->usbcmd) & UHCI_CMD_HCRESET) != 0)
    165                 { async_usleep(10); }
    166 
    167         /* set framelist pointer */
     185        pio_write_16(&registers->usbcmd, 0);
     186
     187        /* Reset hc, all states and counters */
     188        pio_write_16(&registers->usbcmd, UHCI_CMD_HCRESET);
     189        do { async_usleep(10); }
     190        while ((pio_read_16(&registers->usbcmd) & UHCI_CMD_HCRESET) != 0);
     191
     192        /* Set framelist pointer */
    168193        const uint32_t pa = addr_to_phys(instance->frame_list);
    169         pio_write_32(&instance->registers->flbaseadd, pa);
    170 
    171         /* enable all interrupts, but resume interrupt */
    172         pio_write_16(&instance->registers->usbintr,
    173                   UHCI_INTR_CRC | UHCI_INTR_COMPLETE | UHCI_INTR_SHORT_PACKET);
     194        pio_write_32(&registers->flbaseadd, pa);
     195
     196        /* Enable all interrupts, but resume interrupt */
     197//      pio_write_16(&instance->registers->usbintr,
     198//          UHCI_INTR_CRC | UHCI_INTR_COMPLETE | UHCI_INTR_SHORT_PACKET);
     199
     200        uint16_t status = pio_read_16(&registers->usbcmd);
     201        if (status != 0)
     202                usb_log_warning("Previous command value: %x.\n", status);
    174203
    175204        /* Start the hc with large(64B) packet FSBR */
    176         pio_write_16(&instance->registers->usbcmd,
     205        pio_write_16(&registers->usbcmd,
    177206            UHCI_CMD_RUN_STOP | UHCI_CMD_MAX_PACKET | UHCI_CMD_CONFIGURE);
    178207}
    179208/*----------------------------------------------------------------------------*/
     209/** Initializes UHCI hcd memory structures.
     210 *
     211 * @param[in] instance UHCI structure to use.
     212 * @return Error code
     213 * @note Should be called only once on any structure.
     214 */
    180215int uhci_init_mem_structures(uhci_t *instance)
    181216{
     
    189224        } else (void) 0
    190225
    191         /* init interrupt code */
     226        /* Init interrupt code */
    192227        instance->interrupt_code.cmds = malloc(sizeof(uhci_cmds));
    193228        int ret = (instance->interrupt_code.cmds == NULL) ? ENOMEM : EOK;
    194         CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to allocate interrupt cmds space.\n");
     229        CHECK_RET_DEST_CMDS_RETURN(ret,
     230            "Failed to allocate interrupt cmds space.\n");
    195231
    196232        {
    197233                irq_cmd_t *interrupt_commands = instance->interrupt_code.cmds;
    198234                memcpy(interrupt_commands, uhci_cmds, sizeof(uhci_cmds));
    199                 interrupt_commands[0].addr = (void*)&instance->registers->usbsts;
    200                 interrupt_commands[1].addr = (void*)&instance->registers->usbsts;
     235                interrupt_commands[0].addr =
     236                    (void*)&instance->registers->usbsts;
     237                interrupt_commands[1].addr =
     238                    (void*)&instance->registers->usbsts;
    201239                instance->interrupt_code.cmdcount =
    202                                 sizeof(uhci_cmds) / sizeof(irq_cmd_t);
    203         }
    204 
    205         /* init transfer lists */
     240                    sizeof(uhci_cmds) / sizeof(irq_cmd_t);
     241        }
     242
     243        /* Init transfer lists */
    206244        ret = uhci_init_transfer_lists(instance);
    207         CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to initialize transfer lists.\n");
     245        CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to init transfer lists.\n");
    208246        usb_log_debug("Initialized transfer lists.\n");
    209247
    210         /* frame list initialization */
     248        /* Init USB frame list page*/
    211249        instance->frame_list = get_page();
    212250        ret = instance ? EOK : ENOMEM;
     
    214252        usb_log_debug("Initialized frame list.\n");
    215253
    216         /* initialize all frames to point to the first queue head */
     254        /* Set all frames to point to the first queue head */
    217255        const uint32_t queue =
    218256          instance->transfers_interrupt.queue_head_pa
     
    224262        }
    225263
    226         /* init address keeper(libusb) */
     264        /* Init device keeper*/
    227265        device_keeper_init(&instance->device_manager);
    228266        usb_log_debug("Initialized device manager.\n");
     
    232270}
    233271/*----------------------------------------------------------------------------*/
     272/** Initializes UHCI hcd transfer lists.
     273 *
     274 * @param[in] instance UHCI structure to use.
     275 * @return Error code
     276 * @note Should be called only once on any structure.
     277 */
    234278int uhci_init_transfer_lists(uhci_t *instance)
    235279{
     
    249293        ret = transfer_list_init(&instance->transfers_bulk_full, "BULK_FULL");
    250294        CHECK_RET_CLEAR_RETURN(ret, "Failed to init BULK list.");
    251         ret = transfer_list_init(&instance->transfers_control_full, "CONTROL_FULL");
     295
     296        ret = transfer_list_init(
     297            &instance->transfers_control_full, "CONTROL_FULL");
    252298        CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL FULL list.");
    253         ret = transfer_list_init(&instance->transfers_control_slow, "CONTROL_SLOW");
     299
     300        ret = transfer_list_init(
     301            &instance->transfers_control_slow, "CONTROL_SLOW");
    254302        CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL SLOW list.");
     303
    255304        ret = transfer_list_init(&instance->transfers_interrupt, "INTERRUPT");
    256305        CHECK_RET_CLEAR_RETURN(ret, "Failed to init INTERRUPT list.");
     
    269318#endif
    270319
    271         instance->transfers[0][USB_TRANSFER_INTERRUPT] =
     320        /* Assign pointers to be used during scheduling */
     321        instance->transfers[USB_SPEED_FULL][USB_TRANSFER_INTERRUPT] =
    272322          &instance->transfers_interrupt;
    273         instance->transfers[1][USB_TRANSFER_INTERRUPT] =
     323        instance->transfers[USB_SPEED_LOW][USB_TRANSFER_INTERRUPT] =
    274324          &instance->transfers_interrupt;
    275         instance->transfers[0][USB_TRANSFER_CONTROL] =
     325        instance->transfers[USB_SPEED_FULL][USB_TRANSFER_CONTROL] =
    276326          &instance->transfers_control_full;
    277         instance->transfers[1][USB_TRANSFER_CONTROL] =
     327        instance->transfers[USB_SPEED_LOW][USB_TRANSFER_CONTROL] =
    278328          &instance->transfers_control_slow;
    279         instance->transfers[0][USB_TRANSFER_BULK] =
     329        instance->transfers[USB_SPEED_FULL][USB_TRANSFER_BULK] =
    280330          &instance->transfers_bulk_full;
    281331
     
    284334}
    285335/*----------------------------------------------------------------------------*/
     336/** Schedules batch for execution.
     337 *
     338 * @param[in] instance UHCI structure to use.
     339 * @param[in] batch Transfer batch to schedule.
     340 * @return Error code
     341 */
    286342int uhci_schedule(uhci_t *instance, batch_t *batch)
    287343{
     
    291347        if (!allowed_usb_packet(
    292348            low_speed, batch->transfer_type, batch->max_packet_size)) {
    293                 usb_log_warning("Invalid USB packet specified %s SPEED %d %zu.\n",
    294                           low_speed ? "LOW" : "FULL" , batch->transfer_type,
     349                usb_log_warning(
     350                    "Invalid USB packet specified %s SPEED %d %zu.\n",
     351                    low_speed ? "LOW" : "FULL" , batch->transfer_type,
    295352                    batch->max_packet_size);
    296353                return ENOTSUP;
     
    306363}
    307364/*----------------------------------------------------------------------------*/
     365/** Takes action based on the interrupt cause.
     366 *
     367 * @param[in] instance UHCI structure to use.
     368 * @param[in] status Value of the stsatus regiser at the time of interrupt.
     369 */
    308370void uhci_interrupt(uhci_t *instance, uint16_t status)
    309371{
    310372        assert(instance);
    311 //      if ((status & (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)) == 0)
    312 //              return;
    313 //      usb_log_debug2("UHCI interrupt: %X.\n", status);
     373        /* TODO: Check interrupt cause here */
    314374        transfer_list_remove_finished(&instance->transfers_interrupt);
    315375        transfer_list_remove_finished(&instance->transfers_control_slow);
     
    318378}
    319379/*----------------------------------------------------------------------------*/
     380/** Polling function, emulates interrupts.
     381 *
     382 * @param[in] arg UHCI structure to use.
     383 * @return EOK
     384 */
    320385int uhci_interrupt_emulator(void* arg)
    321386{
     
    331396                uhci_interrupt(instance, status);
    332397                pio_write_16(&instance->registers->usbsts, 0x1f);
    333                 async_usleep(UHCI_CLEANER_TIMEOUT * 5);
     398                async_usleep(UHCI_CLEANER_TIMEOUT);
    334399        }
    335400        return EOK;
    336401}
    337402/*---------------------------------------------------------------------------*/
     403/** Debug function, checks consistency of memory structures.
     404 *
     405 * @param[in] arg UHCI structure to use.
     406 * @return EOK
     407 */
    338408int uhci_debug_checker(void *arg)
    339409{
    340410        uhci_t *instance = (uhci_t*)arg;
    341411        assert(instance);
     412
     413#define QH(queue) \
     414        instance->transfers_##queue.queue_head
     415
    342416        while (1) {
    343417                const uint16_t cmd = pio_read_16(&instance->registers->usbcmd);
    344418                const uint16_t sts = pio_read_16(&instance->registers->usbsts);
    345                 const uint16_t intr = pio_read_16(&instance->registers->usbintr);
     419                const uint16_t intr =
     420                    pio_read_16(&instance->registers->usbintr);
     421
    346422                if (((cmd & UHCI_CMD_RUN_STOP) != 1) || (sts != 0)) {
    347423                        usb_log_debug2("Command: %X Status: %X Intr: %x\n",
     
    353429                if (frame_list != addr_to_phys(instance->frame_list)) {
    354430                        usb_log_debug("Framelist address: %p vs. %p.\n",
    355                                 frame_list, addr_to_phys(instance->frame_list));
    356                 }
     431                            frame_list, addr_to_phys(instance->frame_list));
     432                }
     433
    357434                int frnum = pio_read_16(&instance->registers->frnum) & 0x3ff;
    358435                usb_log_debug2("Framelist item: %d \n", frnum );
    359436
    360                 queue_head_t* qh = instance->transfers_interrupt.queue_head;
    361 
    362                 if ((instance->frame_list[frnum] & (~0xf)) != (uintptr_t)addr_to_phys(qh)) {
     437                uintptr_t expected_pa = instance->frame_list[frnum] & (~0xf);
     438                uintptr_t real_pa = addr_to_phys(QH(interrupt));
     439                if (expected_pa != real_pa) {
    363440                        usb_log_debug("Interrupt QH: %p vs. %p.\n",
    364                                 instance->frame_list[frnum] & (~0xf), addr_to_phys(qh));
    365                 }
    366 
    367                 if ((qh->next_queue & (~0xf))
    368                   != (uintptr_t)addr_to_phys(instance->transfers_control_slow.queue_head)) {
    369                         usb_log_debug("Control Slow QH: %p vs. %p.\n", qh->next_queue & (~0xf),
    370                                 addr_to_phys(instance->transfers_control_slow.queue_head));
    371                 }
    372                 qh = instance->transfers_control_slow.queue_head;
    373 
    374                 if ((qh->next_queue & (~0xf))
    375                   != (uintptr_t)addr_to_phys(instance->transfers_control_full.queue_head)) {
    376                         usb_log_debug("Control Full QH: %p vs. %p.\n", qh->next_queue & (~0xf),
    377                                 addr_to_phys(instance->transfers_control_full.queue_head));\
    378                 }
    379                 qh = instance->transfers_control_full.queue_head;
    380 
    381                 if ((qh->next_queue & (~0xf))
    382                   != (uintptr_t)addr_to_phys(instance->transfers_bulk_full.queue_head)) {
    383                         usb_log_debug("Bulk QH: %p vs. %p.\n", qh->next_queue & (~0xf),
    384                                 addr_to_phys(instance->transfers_bulk_full.queue_head));
    385                 }
    386 /*
    387         uint16_t cmd = pio_read_16(&instance->registers->usbcmd);
    388         cmd |= UHCI_CMD_RUN_STOP;
    389         pio_write_16(&instance->registers->usbcmd, cmd);
    390 */
     441                            expected_pa, real_pa);
     442                }
     443
     444                expected_pa = QH(interrupt)->next_queue & (~0xf);
     445                real_pa = addr_to_phys(QH(control_slow));
     446                if (expected_pa != real_pa) {
     447                        usb_log_debug("Control Slow QH: %p vs. %p.\n",
     448                            expected_pa, real_pa);
     449                }
     450
     451                expected_pa = QH(control_slow)->next_queue & (~0xf);
     452                real_pa = addr_to_phys(QH(control_full));
     453                if (expected_pa != real_pa) {
     454                        usb_log_debug("Control Full QH: %p vs. %p.\n",
     455                            expected_pa, real_pa);
     456                }
     457
     458                expected_pa = QH(control_full)->next_queue & (~0xf);
     459                real_pa = addr_to_phys(QH(bulk_full));
     460                if (expected_pa != real_pa ) {
     461                        usb_log_debug("Bulk QH: %p vs. %p.\n",
     462                            expected_pa, real_pa);
     463                }
    391464                async_usleep(UHCI_DEBUGER_TIMEOUT);
    392465        }
    393         return 0;
    394 }
    395 /*----------------------------------------------------------------------------*/
     466        return EOK;
     467#undef QH
     468}
     469/*----------------------------------------------------------------------------*/
     470/** Checks transfer packets, for USB validity
     471 *
     472 * @param[in] low_speed Transfer speed.
     473 * @param[in] transfer Transer type
     474 * @param[in] size Maximum size of used packets
     475 * @return EOK
     476 */
    396477bool allowed_usb_packet(
    397         bool low_speed, usb_transfer_type_t transfer, size_t size)
     478    bool low_speed, usb_transfer_type_t transfer, size_t size)
    398479{
    399480        /* see USB specification chapter 5.5-5.8 for magic numbers used here */
    400         switch(transfer) {
    401                 case USB_TRANSFER_ISOCHRONOUS:
    402                         return (!low_speed && size < 1024);
    403                 case USB_TRANSFER_INTERRUPT:
    404                         return size <= (low_speed ? 8 : 64);
    405                 case USB_TRANSFER_CONTROL: /* device specifies its own max size */
    406                         return (size <= (low_speed ? 8 : 64));
    407                 case USB_TRANSFER_BULK: /* device specifies its own max size */
    408                         return (!low_speed && size <= 64);
     481        switch(transfer)
     482        {
     483        case USB_TRANSFER_ISOCHRONOUS:
     484                return (!low_speed && size < 1024);
     485        case USB_TRANSFER_INTERRUPT:
     486                return size <= (low_speed ? 8 : 64);
     487        case USB_TRANSFER_CONTROL: /* device specifies its own max size */
     488                return (size <= (low_speed ? 8 : 64));
     489        case USB_TRANSFER_BULK: /* device specifies its own max size */
     490                return (!low_speed && size <= 64);
    409491        }
    410492        return false;
  • uspace/drv/uhci-hcd/uhci.h

    r60a228f r9d9ffdd  
    8484        device_keeper_t device_manager;
    8585
    86         volatile regs_t *registers;
     86        regs_t *registers;
    8787
    8888        link_pointer_t *frame_list;
  • uspace/drv/uhci-hcd/uhci_struct/queue_head.h

    r60a228f r9d9ffdd  
    7171}
    7272
    73 static inline void queue_head_element_td(queue_head_t *instance, uint32_t pa)
     73static inline void queue_head_set_element_td(queue_head_t *instance, uint32_t pa)
    7474{
    7575        if (pa) {
     
    7878}
    7979
    80 static inline queue_head_t * queue_head_get() {
    81         queue_head_t *ret = malloc32(sizeof(queue_head_t));
    82         if (ret)
    83                 queue_head_init(ret);
    84         return ret;
    85 }
    86 
    87 static inline void queue_head_dispose(queue_head_t *head)
    88         { free32(head); }
    89 
    90 
    9180#endif
    9281/**
  • uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.c

    r60a228f r9d9ffdd  
    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)
     40/** Initializes Transfer Descriptor
     41 *
     42 * @param[in] instance Memory place to initialize.
     43 * @param[in] err_count Number of retries hc should attempt.
     44 * @param[in] size Size of data source.
     45 * @param[in] toggle Value of toggle bit.
     46 * @param[in] iso True if TD is for Isochronous transfer.
     47 * @param[in] low_speed Target device's speed.
     48 * @param[in] target Address and endpoint receiving the transfer.
     49 * @param[in] pid Packet identification (SETUP, IN or OUT).
     50 * @param[in] buffer Source of data.
     51 * @param[in] next Net TD in transaction.
     52 * @return Error code.
     53 */
     54void td_init(td_t *instance, int err_count, size_t size, bool toggle, bool iso,
     55    bool low_speed, usb_target_t target, usb_packet_id pid, void *buffer,
     56    td_t *next)
    4357{
    4458        assert(instance);
     59        assert(size < 1024);
     60        assert((pid == USB_PID_SETUP) || (pid == USB_PID_IN)
     61            || (pid == USB_PID_OUT));
    4562
    4663        instance->next = 0
     
    4966
    5067        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;
     68            | ((err_count & TD_STATUS_ERROR_COUNT_MASK) << TD_STATUS_ERROR_COUNT_POS)
     69            | (low_speed ? TD_STATUS_LOW_SPEED_FLAG : 0)
     70            | (iso ? TD_STATUS_ISOCHRONOUS_FLAG : 0)
     71            | TD_STATUS_ERROR_ACTIVE;
    5472
    55         assert(size < 1024);
     73        if (pid == USB_PID_IN && !iso) {
     74                instance->status |= TD_STATUS_SPD_FLAG;
     75        }
     76
    5677        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);
     78            | (((size - 1) & TD_DEVICE_MAXLEN_MASK) << TD_DEVICE_MAXLEN_POS)
     79            | (toggle ? TD_DEVICE_DATA_TOGGLE_ONE_FLAG : 0)
     80            | ((target.address & TD_DEVICE_ADDRESS_MASK) << TD_DEVICE_ADDRESS_POS)
     81            | ((target.endpoint & TD_DEVICE_ENDPOINT_MASK) << TD_DEVICE_ENDPOINT_POS)
     82            | ((pid & TD_DEVICE_PID_MASK) << TD_DEVICE_PID_POS);
    6283
    6384        instance->buffer_ptr = 0;
     
    6889
    6990        usb_log_debug2("Created TD: %X:%X:%X:%X(%p).\n",
    70                 instance->next, instance->status, instance->device,
    71           instance->buffer_ptr, buffer);
     91            instance->next, instance->status, instance->device,
     92            instance->buffer_ptr, buffer);
     93        if (pid == USB_PID_SETUP) {
     94                usb_log_debug("SETUP BUFFER: %s\n",
     95                        usb_debug_str_buffer(buffer, 8, 8));
     96        }
    7297}
    7398/*----------------------------------------------------------------------------*/
    74 int transfer_descriptor_status(transfer_descriptor_t *instance)
     99/** Converts TD status into standard error code
     100 *
     101 * @param[in] instance TD structure to use.
     102 * @return Error code.
     103 */
     104int td_status(td_t *instance)
    75105{
    76106        assert(instance);
  • uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.h

    r60a228f r9d9ffdd  
    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

    r60a228f r9d9ffdd  
    3535#include <assert.h>
    3636#include <errno.h>
     37#include <usb/debug.h>
    3738
    3839#include "device_keeper.h"
    3940
    4041/*----------------------------------------------------------------------------*/
     42/** Initializes device keeper structure.
     43 *
     44 * @param[in] instance Memory place to initialize.
     45 */
    4146void device_keeper_init(device_keeper_t *instance)
    4247{
     
    4954                instance->devices[i].occupied = false;
    5055                instance->devices[i].handle = 0;
    51         }
    52 }
    53 /*----------------------------------------------------------------------------*/
    54 void device_keeper_reserve_default(
    55     device_keeper_t *instance, usb_speed_t speed)
     56                instance->devices[i].toggle_status = 0;
     57        }
     58}
     59/*----------------------------------------------------------------------------*/
     60/** Attempts to obtain address 0, blocks.
     61 *
     62 * @param[in] instance Device keeper structure to use.
     63 * @param[in] speed Speed of the device requesting default address.
     64 */
     65void device_keeper_reserve_default(device_keeper_t *instance, usb_speed_t speed)
    5666{
    5767        assert(instance);
     
    6676}
    6777/*----------------------------------------------------------------------------*/
     78/** Attempts to obtain address 0, blocks.
     79 *
     80 * @param[in] instance Device keeper structure to use.
     81 * @param[in] speed Speed of the device requesting default address.
     82 */
    6883void device_keeper_release_default(device_keeper_t *instance)
    6984{
     
    7590}
    7691/*----------------------------------------------------------------------------*/
     92/** Checks setup data for signs of toggle reset.
     93 *
     94 * @param[in] instance Device keeper structure to use.
     95 * @param[in] target Device to receive setup packet.
     96 * @param[in] data Setup packet data.
     97 */
     98void device_keeper_reset_if_need(
     99    device_keeper_t *instance, usb_target_t target, const unsigned char *data)
     100{
     101        assert(instance);
     102        fibril_mutex_lock(&instance->guard);
     103        if (target.endpoint > 15 || target.endpoint < 0
     104            || target.address >= USB_ADDRESS_COUNT || target.address < 0
     105            || !instance->devices[target.address].occupied) {
     106                fibril_mutex_unlock(&instance->guard);
     107                return;
     108        }
     109
     110        switch (data[1])
     111        {
     112        case 0x01: /*clear feature*/
     113                /* recipient is endpoint, value is zero (ENDPOINT_STALL) */
     114                if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) {
     115                        /* endpoint number is < 16, thus first byte is enough */
     116                        instance->devices[target.address].toggle_status &=
     117                            ~(1 << data[4]);
     118                }
     119        break;
     120
     121        case 0x9: /* set configuration */
     122        case 0x11: /* set interface */
     123                /* target must be device */
     124                if ((data[0] & 0xf) == 0) {
     125                        instance->devices[target.address].toggle_status = 0;
     126                }
     127        break;
     128        }
     129        fibril_mutex_unlock(&instance->guard);
     130}
     131/*----------------------------------------------------------------------------*/
     132/** Gets current value of endpoint toggle.
     133 *
     134 * @param[in] instance Device keeper structure to use.
     135 * @param[in] target Device and endpoint used.
     136 * @return Error code
     137 */
     138int device_keeper_get_toggle(device_keeper_t *instance, usb_target_t target)
     139{
     140        assert(instance);
     141        int ret;
     142        fibril_mutex_lock(&instance->guard);
     143        if (target.endpoint > 15 || target.endpoint < 0
     144            || target.address >= USB_ADDRESS_COUNT || target.address < 0
     145            || !instance->devices[target.address].occupied) {
     146                ret = EINVAL;
     147        } else {
     148                ret =
     149                    (instance->devices[target.address].toggle_status
     150                        >> target.endpoint) & 1;
     151        }
     152        fibril_mutex_unlock(&instance->guard);
     153        return ret;
     154}
     155/*----------------------------------------------------------------------------*/
     156/** Sets current value of endpoint toggle.
     157 *
     158 * @param[in] instance Device keeper structure to use.
     159 * @param[in] target Device and endpoint used.
     160 * @param[in] toggle Current toggle value.
     161 * @return Error code.
     162 */
     163int device_keeper_set_toggle(
     164    device_keeper_t *instance, usb_target_t target, bool toggle)
     165{
     166        assert(instance);
     167        int ret;
     168        fibril_mutex_lock(&instance->guard);
     169        if (target.endpoint > 15 || target.endpoint < 0
     170            || target.address >= USB_ADDRESS_COUNT || target.address < 0
     171            || !instance->devices[target.address].occupied) {
     172                ret = EINVAL;
     173        } else {
     174                if (toggle) {
     175                        instance->devices[target.address].toggle_status |= (1 << target.endpoint);
     176                } else {
     177                        instance->devices[target.address].toggle_status &= ~(1 << target.endpoint);
     178                }
     179                ret = EOK;
     180        }
     181        fibril_mutex_unlock(&instance->guard);
     182        return ret;
     183}
     184/*----------------------------------------------------------------------------*/
     185/** Gets a free USB address
     186 *
     187 * @param[in] instance Device keeper structure to use.
     188 * @param[in] speed Speed of the device requiring address.
     189 * @return Free address, or error code.
     190 */
    77191usb_address_t device_keeper_request(
    78192    device_keeper_t *instance, usb_speed_t speed)
     
    96210        instance->devices[new_address].occupied = true;
    97211        instance->devices[new_address].speed = speed;
     212        instance->devices[new_address].toggle_status = 0;
    98213        instance->last_address = new_address;
    99214        fibril_mutex_unlock(&instance->guard);
     
    101216}
    102217/*----------------------------------------------------------------------------*/
     218/** Binds USB address to devman handle.
     219 *
     220 * @param[in] instance Device keeper structure to use.
     221 * @param[in] address Device address
     222 * @param[in] handle Devman handle of the device.
     223 */
    103224void device_keeper_bind(
    104225    device_keeper_t *instance, usb_address_t address, devman_handle_t handle)
     
    113234}
    114235/*----------------------------------------------------------------------------*/
     236/** Releases used USB address.
     237 *
     238 * @param[in] instance Device keeper structure to use.
     239 * @param[in] address Device address
     240 */
    115241void device_keeper_release(device_keeper_t *instance, usb_address_t address)
    116242{
     
    125251}
    126252/*----------------------------------------------------------------------------*/
     253/** Finds USB address associated with the device
     254 *
     255 * @param[in] instance Device keeper structure to use.
     256 * @param[in] handle Devman handle of the device seeking its address.
     257 * @return USB Address, or error code.
     258 */
    127259usb_address_t device_keeper_find(
    128260    device_keeper_t *instance, devman_handle_t handle)
     
    142274}
    143275/*----------------------------------------------------------------------------*/
     276/** Gets speed associated with the address
     277 *
     278 * @param[in] instance Device keeper structure to use.
     279 * @param[in] address Address of the device.
     280 * @return USB speed.
     281 */
    144282usb_speed_t device_keeper_speed(
    145283    device_keeper_t *instance, usb_address_t address)
  • uspace/drv/uhci-hcd/utils/device_keeper.h

    r60a228f r9d9ffdd  
    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);
  • uspace/drv/uhci-hcd/utils/malloc32.h

    r60a228f r9d9ffdd  
    3434#ifndef DRV_UHCI_TRANSLATOR_H
    3535#define DRV_UHCI_TRANSLATOR_H
    36 
    37 #include <usb/usbmem.h>
    3836
    3937#include <assert.h>
  • uspace/drv/uhci-rhd/main.c

    r60a228f r9d9ffdd  
    3535#include <devman.h>
    3636#include <device/hw_res.h>
     37#include <errno.h>
    3738#include <usb_iface.h>
    3839#include <usb/ddfiface.h>
     40#include <usb/debug.h>
    3941
    40 #include <errno.h>
    4142
    42 #include <usb/debug.h>
    4343
    4444#include "root_hub.h"
     
    4747static int hc_get_my_registers(ddf_dev_t *dev,
    4848    uintptr_t *io_reg_address, size_t *io_reg_size);
    49 
     49/*----------------------------------------------------------------------------*/
    5050static int usb_iface_get_hc_handle(ddf_fun_t *fun, devman_handle_t *handle)
    5151{
     
    5858        return EOK;
    5959}
    60 
     60/*----------------------------------------------------------------------------*/
    6161static usb_iface_t uhci_rh_usb_iface = {
    6262        .get_hc_handle = usb_iface_get_hc_handle,
    6363        .get_address = usb_iface_get_address_hub_impl
    6464};
    65 
     65/*----------------------------------------------------------------------------*/
    6666static ddf_dev_ops_t uhci_rh_ops = {
    6767        .interfaces[USB_DEV_IFACE] = &uhci_rh_usb_iface,
    6868};
    69 
     69/*----------------------------------------------------------------------------*/
     70/** Initializes a new ddf driver instance of UHCI root hub.
     71 *
     72 * @param[in] device DDF instance of the device to initialize.
     73 * @return Error code.
     74 */
    7075static int uhci_rh_add_device(ddf_dev_t *device)
    7176{
     
    104109        return EOK;
    105110}
    106 
     111/*----------------------------------------------------------------------------*/
    107112static driver_ops_t uhci_rh_driver_ops = {
    108113        .add_device = uhci_rh_add_device,
    109114};
    110 
     115/*----------------------------------------------------------------------------*/
    111116static driver_t uhci_rh_driver = {
    112117        .name = NAME,
     
    114119};
    115120/*----------------------------------------------------------------------------*/
     121/** Initializes global driver structures (NONE).
     122 *
     123 * @param[in] argc Nmber of arguments in argv vector (ignored).
     124 * @param[in] argv Cmdline argument vector (ignored).
     125 * @return Error code.
     126 *
     127 * Driver debug level is set here.
     128 */
    116129int main(int argc, char *argv[])
    117130{
     
    120133}
    121134/*----------------------------------------------------------------------------*/
    122 int hc_get_my_registers(ddf_dev_t *dev,
    123     uintptr_t *io_reg_address, size_t *io_reg_size)
     135/** Get address of I/O registers.
     136 *
     137 * @param[in] dev Device asking for the addresses.
     138 * @param[out] io_reg_address Base address of the memory range.
     139 * @param[out] io_reg_size Size of the memory range.
     140 * @return Error code.
     141 */
     142int hc_get_my_registers(
     143    ddf_dev_t *dev, uintptr_t *io_reg_address, size_t *io_reg_size)
    124144{
    125145        assert(dev != NULL);
     
    146166        for (i = 0; i < hw_resources.count; i++) {
    147167                hw_resource_t *res = &hw_resources.resources[i];
    148                 switch (res->type) {
    149                         case IO_RANGE:
    150                                 io_address = (uintptr_t)
    151                                     res->res.io_range.address;
    152                                 io_size = res->res.io_range.size;
    153                                 io_found = true;
    154                                 break;
    155                         default:
    156                                 break;
     168                switch (res->type)
     169                {
     170                case IO_RANGE:
     171                        io_address = (uintptr_t) res->res.io_range.address;
     172                        io_size = res->res.io_range.size;
     173                        io_found = true;
     174
     175                default:
     176                        break;
    157177                }
    158178        }
     
    170190        }
    171191        rc = EOK;
     192
    172193leave:
    173194        async_hangup(parent_phone);
    174 
    175195        return rc;
    176196}
  • uspace/drv/uhci-rhd/port.c

    r60a228f r9d9ffdd  
    4646#include "port_status.h"
    4747
    48 static int uhci_port_new_device(uhci_port_t *port, uint16_t status);
     48static int uhci_port_new_device(uhci_port_t *port, usb_speed_t speed);
    4949static int uhci_port_remove_device(uhci_port_t *port);
    5050static int uhci_port_set_enabled(uhci_port_t *port, bool enabled);
    5151static int uhci_port_check(void *port);
    52 static int new_device_enable_port(int portno, void *arg);
    53 
    54 int uhci_port_init(
    55   uhci_port_t *port, port_status_t *address, unsigned number,
    56   unsigned usec, ddf_dev_t *rh)
     52static int uhci_port_reset_enable(int portno, void *arg);
     53/*----------------------------------------------------------------------------*/
     54/** Initializes UHCI root hub port instance.
     55 *
     56 * @param[in] port Memory structure to use.
     57 * @param[in] addr Address of I/O register.
     58 * @param[in] number Port number.
     59 * @param[in] usec Polling interval.
     60 * @param[in] rh Pointer to ddf instance fo the root hub driver.
     61 * @return Error code.
     62 *
     63 * Starts the polling fibril.
     64 */
     65int uhci_port_init(uhci_port_t *port,
     66    port_status_t *address, unsigned number, unsigned usec, ddf_dev_t *rh)
    5767{
    5868        assert(port);
     69
    5970        port->address = address;
    6071        port->number = number;
     
    6273        port->attached_device = 0;
    6374        port->rh = rh;
     75
    6476        int rc = usb_hc_connection_initialize_from_device(
    6577            &port->hc_connection, rh);
     
    7587                return ENOMEM;
    7688        }
     89
    7790        fibril_add_ready(port->checker);
    7891        usb_log_debug("Port(%p - %d): Added fibril. %x\n",
     
    8194}
    8295/*----------------------------------------------------------------------------*/
     96/** Finishes UHCI root hub port instance.
     97 *
     98 * @param[in] port Memory structure to use.
     99 *
     100 * Stops the polling fibril.
     101 */
    83102void uhci_port_fini(uhci_port_t *port)
    84103{
    85 // TODO: destroy fibril
    86 // TODO: hangup phone
    87 //      fibril_teardown(port->checker);
     104        /* TODO: Kill fibril here */
    88105        return;
    89106}
    90107/*----------------------------------------------------------------------------*/
     108/** Periodically checks port status and reports new devices.
     109 *
     110 * @param[in] port Memory structure to use.
     111 * @return Error code.
     112 */
    91113int uhci_port_check(void *port)
    92114{
    93         uhci_port_t *port_instance = port;
    94         assert(port_instance);
    95 //      port_status_write(port_instance->address, 0);
    96 
     115        uhci_port_t *instance = port;
     116        assert(instance);
     117
     118        /* Iteration count, for debug purposes only */
    97119        unsigned count = 0;
    98120
    99121        while (1) {
    100                 async_usleep(port_instance->wait_period_usec);
     122                async_usleep(instance->wait_period_usec);
    101123
    102124                /* read register value */
    103                 port_status_t port_status =
    104                         port_status_read(port_instance->address);
    105 
    106                 /* debug print */
    107                 static fibril_mutex_t dbg_mtx = FIBRIL_MUTEX_INITIALIZER(dbg_mtx);
     125                port_status_t port_status = port_status_read(instance->address);
     126
     127                /* debug print mutex */
     128                static fibril_mutex_t dbg_mtx =
     129                    FIBRIL_MUTEX_INITIALIZER(dbg_mtx);
    108130                fibril_mutex_lock(&dbg_mtx);
    109131                usb_log_debug2("Port(%p - %d): Status: %#04x. === %u\n",
    110                   port_instance->address, port_instance->number, port_status, count++);
     132                  instance->address, instance->number, port_status, count++);
    111133//              print_port_status(port_status);
    112134                fibril_mutex_unlock(&dbg_mtx);
    113135
    114                 if ((port_status & STATUS_CONNECTED_CHANGED) != 0) {
    115                         usb_log_debug("Port(%p - %d): Connected change detected: %x.\n",
    116                             port_instance->address, port_instance->number, port_status);
    117 
    118 
    119                         int rc = usb_hc_connection_open(
    120                             &port_instance->hc_connection);
    121                         if (rc != EOK) {
    122                                 usb_log_error("Port(%p - %d): Failed to connect to HC.",
    123                                     port_instance->address, port_instance->number);
    124                                 continue;
    125                         }
    126 
    127                         /* remove any old device */
    128                         if (port_instance->attached_device) {
    129                                 usb_log_debug("Port(%p - %d): Removing device.\n",
    130                                     port_instance->address, port_instance->number);
    131                                 uhci_port_remove_device(port_instance);
    132                         }
    133 
    134                         if ((port_status & STATUS_CONNECTED) != 0) {
    135                                 /* new device */
    136                                 uhci_port_new_device(port_instance, port_status);
    137                         } else {
    138                                 /* ack changes by writing one to WC bits */
    139                                 port_status_write(port_instance->address, port_status);
    140                                 usb_log_debug("Port(%p - %d): Change status ACK.\n",
    141                                                 port_instance->address, port_instance->number);
    142                         }
    143 
    144                         rc = usb_hc_connection_close(
    145                             &port_instance->hc_connection);
    146                         if (rc != EOK) {
    147                                 usb_log_error("Port(%p - %d): Failed to disconnect from HC.",
    148                                     port_instance->address, port_instance->number);
    149                         }
    150                 }
    151         }
    152         return EOK;
    153 }
    154 
     136                if ((port_status & STATUS_CONNECTED_CHANGED) == 0)
     137                        continue;
     138
     139                usb_log_debug("Port(%p - %d): Connected change detected: %x.\n",
     140                    instance->address, instance->number, port_status);
     141
     142                int rc =
     143                    usb_hc_connection_open(&instance->hc_connection);
     144                if (rc != EOK) {
     145                        usb_log_error("Port(%p - %d): Failed to connect to HC.",
     146                            instance->address, instance->number);
     147                        continue;
     148                }
     149
     150                /* Remove any old device */
     151                if (instance->attached_device) {
     152                        usb_log_debug2("Port(%p - %d): Removing device.\n",
     153                            instance->address, instance->number);
     154                        uhci_port_remove_device(instance);
     155                }
     156
     157                if ((port_status & STATUS_CONNECTED) != 0) {
     158                        /* New device */
     159                        const usb_speed_t speed =
     160                            ((port_status & STATUS_LOW_SPEED) != 0) ?
     161                            USB_SPEED_LOW : USB_SPEED_FULL;
     162                        uhci_port_new_device(instance, speed);
     163                } else {
     164                        /* Write one to WC bits, to ack changes */
     165                        port_status_write(instance->address, port_status);
     166                        usb_log_debug("Port(%p - %d): Change status ACK.\n",
     167                            instance->address, instance->number);
     168                }
     169
     170                rc = usb_hc_connection_close(&instance->hc_connection);
     171                if (rc != EOK) {
     172                        usb_log_error("Port(%p - %d): Failed to disconnect.",
     173                            instance->address, instance->number);
     174                }
     175        }
     176        return EOK;
     177}
     178/*----------------------------------------------------------------------------*/
    155179/** Callback for enabling port during adding a new device.
    156180 *
     
    159183 * @return Error code.
    160184 */
    161 static int new_device_enable_port(int portno, void *arg)
     185int uhci_port_reset_enable(int portno, void *arg)
    162186{
    163187        uhci_port_t *port = (uhci_port_t *) arg;
     
    184208                port_status_write(port->address, port_status);
    185209                async_usleep(10000);
    186                 port_status =
    187                         port_status_read(port->address);
     210                port_status = port_status_read(port->address);
    188211                port_status &= ~STATUS_IN_RESET;
    189212                port_status_write(port->address, port_status);
     
    194217        /* Enable the port. */
    195218        uhci_port_set_enabled(port, true);
    196 
    197         return EOK;
    198 }
    199 
    200 /*----------------------------------------------------------------------------*/
    201 static int uhci_port_new_device(uhci_port_t *port, uint16_t status)
     219        return EOK;
     220}
     221/*----------------------------------------------------------------------------*/
     222/** Initializes and reports connected device.
     223 *
     224 * @param[in] port Memory structure to use.
     225 * @param[in] speed Detected speed.
     226 * @return Error code.
     227 *
     228 * Uses libUSB function to do the actual work.
     229 */
     230int uhci_port_new_device(uhci_port_t *port, usb_speed_t speed)
    202231{
    203232        assert(port);
     
    209238        usb_address_t dev_addr;
    210239        int rc = usb_hc_new_device_wrapper(port->rh, &port->hc_connection,
    211             ((status & STATUS_LOW_SPEED) != 0) ? USB_SPEED_LOW : USB_SPEED_FULL,
    212             new_device_enable_port, port->number, port,
     240            speed, uhci_port_reset_enable, port->number, port,
    213241            &dev_addr, &port->attached_device, NULL, NULL, NULL);
    214242
    215243        if (rc != EOK) {
    216                 usb_log_error("Port(%p-%d): Failed(%d) adding new device: %s.\n",
     244                usb_log_error("Port(%p-%d): Failed(%d) to add device: %s.\n",
    217245                    port->address, port->number, rc, str_error(rc));
    218246                uhci_port_set_enabled(port, false);
     
    225253        return EOK;
    226254}
    227 
    228 /*----------------------------------------------------------------------------*/
    229 static int uhci_port_remove_device(uhci_port_t *port)
     255/*----------------------------------------------------------------------------*/
     256/** Removes device.
     257 *
     258 * @param[in] port Memory structure to use.
     259 * @return Error code.
     260 *
     261 * Does not work DDF does not support device removal.
     262 */
     263int uhci_port_remove_device(uhci_port_t *port)
    230264{
    231265        usb_log_error("Port(%p-%d): Don't know how to remove device %#x.\n",
    232                 port->address, port->number, (unsigned int)port->attached_device);
    233 //      uhci_port_set_enabled(port, false);
    234         return EOK;
    235 }
    236 /*----------------------------------------------------------------------------*/
    237 static int uhci_port_set_enabled(uhci_port_t *port, bool enabled)
     266            port->address, port->number, (unsigned int)port->attached_device);
     267        return EOK;
     268}
     269/*----------------------------------------------------------------------------*/
     270/** Enables and disables port.
     271 *
     272 * @param[in] port Memory structure to use.
     273 * @return Error code. (Always EOK)
     274 */
     275int uhci_port_set_enabled(uhci_port_t *port, bool enabled)
    238276{
    239277        assert(port);
    240278
    241         /* read register value */
    242         port_status_t port_status
    243                 = port_status_read(port->address);
    244 
    245         /* enable port: register write */
     279        /* Read register value */
     280        port_status_t port_status = port_status_read(port->address);
     281
     282        /* Set enabled bit */
    246283        if (enabled) {
    247284                port_status |= STATUS_ENABLED;
     
    249286                port_status &= ~STATUS_ENABLED;
    250287        }
     288
     289        /* Write new value. */
    251290        port_status_write(port->address, port_status);
    252291
  • uspace/drv/uhci-rhd/port_status.c

    r60a228f r9d9ffdd  
    6060};
    6161
     62/** Prints portr status in a human readable way.
     63 *
     64 * @param[in] value Port value to print.
     65 * @return Error code.
     66 */
    6267void print_port_status(port_status_t value)
    6368{
  • uspace/drv/uhci-rhd/root_hub.c

    r60a228f r9d9ffdd  
    4040#include "root_hub.h"
    4141
     42/** Initializes UHCI root hub instance.
     43 *
     44 * @param[in] instance Driver memory structure to use.
     45 * @param[in] addr Address of I/O registers.
     46 * @param[in] size Size of available I/O space.
     47 * @param[in] rh Pointer to ddf instance fo the root hub driver.
     48 * @return Error code.
     49 */
    4250int uhci_root_hub_init(
    4351  uhci_root_hub_t *instance, void *addr, size_t size, ddf_dev_t *rh)
     
    4755        int ret;
    4856
    49         /* allow access to root hub registers */
    50         assert(sizeof(port_status_t) * UHCI_ROOT_HUB_PORT_COUNT == size);
     57        /* Allow access to root hub port registers */
     58        assert(sizeof(port_status_t) * UHCI_ROOT_HUB_PORT_COUNT <= size);
    5159        port_status_t *regs;
    5260        ret = pio_enable(addr, size, (void**)&regs);
    53 
    5461        if (ret < 0) {
    55                 usb_log_error("Failed to gain access to port registers at %p\n", regs);
     62                usb_log_error(
     63                    "Failed to gain access to port registers at %p\n", regs);
    5664                return ret;
    5765        }
     
    6068        unsigned i = 0;
    6169        for (; i < UHCI_ROOT_HUB_PORT_COUNT; ++i) {
    62                 /* mind pointer arithmetics */
     70                /* NOTE: mind pointer arithmetics here */
    6371                ret = uhci_port_init(
    64                   &instance->ports[i], regs + i, i, ROOT_HUB_WAIT_USEC, rh);
     72                    &instance->ports[i], regs + i, i, ROOT_HUB_WAIT_USEC, rh);
    6573                if (ret != EOK) {
    6674                        unsigned j = 0;
     
    7482}
    7583/*----------------------------------------------------------------------------*/
    76 int uhci_root_hub_fini( uhci_root_hub_t* instance )
     84/** Finishes UHCI root hub instance.
     85 *
     86 * @param[in] instance Driver memory structure to use.
     87 * @return Error code.
     88 */
     89int uhci_root_hub_fini(uhci_root_hub_t* instance)
    7790{
    78         assert( instance );
    79         // TODO:
    80         //destroy fibril here
    81         //disable access to registers
     91        assert(instance);
     92        unsigned i = 0;
     93        for (; i < UHCI_ROOT_HUB_PORT_COUNT; ++i) {
     94                uhci_port_fini(&instance->ports[i]);
     95        }
    8296        return EOK;
    8397}
  • uspace/drv/usbhid/Makefile

    r60a228f r9d9ffdd  
    4242        hidreq.c \
    4343        kbddev.c \
     44        kbdrepeat.c \
    4445        hiddev.c \
    4546        $(STOLEN_LAYOUT_SOURCES)
  • uspace/drv/usbhid/conv.c

    r60a228f r9d9ffdd  
    4040#include "conv.h"
    4141
     42/**
     43 * Mapping between USB HID key codes (from HID Usage Tables) and corresponding
     44 * HelenOS key codes.
     45 */
    4246static int scanmap_simple[255] = {
    4347
     
    163167};
    164168
     169/**
     170 * Translate USB HID key codes (from HID Usage Tables) to generic key codes
     171 * recognized by HelenOS.
     172 *
     173 * @param scancode USB HID key code (from HID Usage Tables).
     174 *
     175 * @retval HelenOS key code corresponding to the given USB HID key code.
     176 */
    165177unsigned int usbhid_parse_scancode(int scancode)
    166178{
  • uspace/drv/usbhid/descdump.c

    r60a228f r9d9ffdd  
    4444#define BYTES_PER_LINE 12
    4545
     46/**
     47 * Dumps the given buffer in hexadecimal format to standard output.
     48 *
     49 * @param msg Message to print before the buffer.
     50 * @param buffer Buffer to print.
     51 * @param length Size of the buffer in bytes.
     52 */
    4653static void dump_buffer(const char *msg, const uint8_t *buffer, size_t length)
    4754{
     
    6269#define INDENT "  "
    6370
     71/**
     72 * Print standard configuration descriptor to standard output.
     73 *
     74 * @param index Index of the descriptor.
     75 * @param d Standard configuration descriptor to print.
     76 */
    6477void dump_standard_configuration_descriptor(
    6578    int index, const usb_standard_configuration_descriptor_t *d)
     
    8497}
    8598
     99/**
     100 * Print standard interface descriptor to standard output.
     101 *
     102 * @param d Standard interface descriptor to print.
     103 */
    86104void dump_standard_interface_descriptor(
    87105    const usb_standard_interface_descriptor_t *d)
     
    99117}
    100118
     119/**
     120 * Print standard endpoint descriptor to standard output.
     121 *
     122 * @param d Standard endpoint descriptor to print.
     123 */
    101124void dump_standard_endpoint_descriptor(
    102125    const usb_standard_endpoint_descriptor_t *d)
     
    126149}
    127150
     151/**
     152 * Print standard HID descriptor to standard output.
     153 *
     154 * @param d Standard HID descriptor to print.
     155 */
    128156void dump_standard_hid_descriptor_header(
    129157    const usb_standard_hid_descriptor_t *d)
     
    139167}
    140168
     169/**
     170 * Print HID class-specific descriptor header (type and length) to standard
     171 * output.
     172 *
     173 * @param d HID class-specific descriptor header to print.
     174 */
    141175void dump_standard_hid_class_descriptor_info(
    142176    const usb_standard_hid_class_descriptor_info_t *d)
     
    146180}
    147181
     182/**
     183 * Print HID class-specific descriptor (without the header) to standard output.
     184 *
     185 * @param index Index of the descriptor.
     186 * @param type Type of the HID class-specific descriptor (Report or Physical).
     187 * @param d HID class descriptor to print.
     188 * @param size Size of the descriptor in bytes.
     189 */
    148190void dump_hid_class_descriptor(int index, uint8_t type,
    149191    const uint8_t *d, size_t size )
  • uspace/drv/usbhid/hiddev.c

    r60a228f r9d9ffdd  
    5353/* Non-API functions                                                          */
    5454/*----------------------------------------------------------------------------*/
    55 
     55/**
     56 * Retreives HID Report descriptor from the device.
     57 *
     58 * This function first parses the HID descriptor from the Interface descriptor
     59 * to get the size of the Report descriptor and then requests the Report
     60 * descriptor from the device.
     61 *
     62 * @param hid_dev HID device structure.
     63 * @param config_desc Full configuration descriptor (including all nested
     64 *                    descriptors).
     65 * @param config_desc_size Size of the full configuration descriptor (in bytes).
     66 * @param iface_desc Pointer to the interface descriptor inside the full
     67 *                   configuration descriptor (@a config_desc) for the interface
     68 *                   assigned with this device (@a hid_dev).
     69 *
     70 * @retval EOK if successful.
     71 * @retval ENOENT if no HID descriptor could be found.
     72 * @retval EINVAL if the HID descriptor  or HID report descriptor have different
     73 *                size than expected.
     74 * @retval ENOMEM if some allocation failed.
     75 * @return Other value inherited from function usb_request_get_descriptor().
     76 *
     77 * @sa usb_request_get_descriptor()
     78 */
    5679static int usbhid_dev_get_report_descriptor(usbhid_dev_t *hid_dev,
    5780    uint8_t *config_desc, size_t config_desc_size, uint8_t *iface_desc)
     
    135158        }
    136159       
     160        hid_dev->report_desc_size = length;
     161       
    137162        usb_log_debug("Done.\n");
    138163       
     
    141166
    142167/*----------------------------------------------------------------------------*/
    143 
     168/**
     169 * Retreives descriptors from the device, initializes pipes and stores
     170 * important information from descriptors.
     171 *
     172 * Initializes the polling pipe described by the given endpoint description
     173 * (@a poll_ep_desc).
     174 *
     175 * Information retreived from descriptors and stored in the HID device structure:
     176 *    - Assigned interface number (the interface controlled by this instance of
     177 *                                 the driver)
     178 *    - Polling interval (from the interface descriptor)
     179 *    - Report descriptor
     180 *
     181 * @param hid_dev HID device structure to be initialized.
     182 * @param poll_ep_desc Description of the polling (Interrupt In) endpoint
     183 *                     that has to be present in the device in order to
     184 *                     successfuly initialize the structure.
     185 *
     186 * @sa usb_endpoint_pipe_initialize_from_configuration(),
     187 *     usbhid_dev_get_report_descriptor()
     188 */
    144189static int usbhid_dev_process_descriptors(usbhid_dev_t *hid_dev,
    145190    usb_endpoint_description_t *poll_ep_desc)
     
    149194        usb_log_info("Processing descriptors...\n");
    150195       
    151         // get the first configuration descriptor
    152         usb_standard_configuration_descriptor_t config_desc;
    153        
    154196        int rc;
    155         rc = usb_request_get_bare_configuration_descriptor(&hid_dev->ctrl_pipe,
    156             0, &config_desc);
    157        
    158         if (rc != EOK) {
    159                 usb_log_error("Failed to get bare config descriptor: %s.\n",
     197
     198        uint8_t *descriptors = NULL;
     199        size_t descriptors_size;
     200        rc = usb_request_get_full_configuration_descriptor_alloc(
     201            &hid_dev->ctrl_pipe, 0, (void **) &descriptors, &descriptors_size);
     202        if (rc != EOK) {
     203                usb_log_error("Failed to retrieve config descriptor: %s.\n",
    160204                    str_error(rc));
    161205                return rc;
    162         }
    163        
    164         // prepare space for all underlying descriptors
    165         uint8_t *descriptors = (uint8_t *)malloc(config_desc.total_length);
    166         if (descriptors == NULL) {
    167                 usb_log_error("No memory!.\n");
    168                 return ENOMEM;
    169         }
    170        
    171         size_t transferred = 0;
    172         // get full configuration descriptor
    173         rc = usb_request_get_full_configuration_descriptor(&hid_dev->ctrl_pipe,
    174             0, descriptors, config_desc.total_length, &transferred);
    175        
    176         if (rc != EOK) {
    177                 usb_log_error("Failed to get full config descriptor: %s.\n",
    178                     str_error(rc));
    179                 free(descriptors);
    180                 return rc;
    181         }
    182        
    183         if (transferred != config_desc.total_length) {
    184                 usb_log_error("Configuration descriptor has wrong size (%u, "
    185                     "expected %u).\n", transferred, config_desc.total_length);
    186                 free(descriptors);
    187                 return ELIMIT;
    188206        }
    189207       
     
    201219       
    202220        rc = usb_endpoint_pipe_initialize_from_configuration(
    203             endpoint_mapping, 1, descriptors, config_desc.total_length,
     221            endpoint_mapping, 1, descriptors, descriptors_size,
    204222            &hid_dev->wire);
    205223       
     
    233251        assert(endpoint_mapping[0].interface != NULL);
    234252       
    235         rc = usbhid_dev_get_report_descriptor(hid_dev, descriptors, transferred,
     253        /*
     254         * Save polling interval
     255         */
     256        hid_dev->poll_interval = endpoint_mapping[0].descriptor->poll_interval;
     257        assert(hid_dev->poll_interval > 0);
     258       
     259        rc = usbhid_dev_get_report_descriptor(hid_dev,
     260            descriptors, descriptors_size,
    236261            (uint8_t *)endpoint_mapping[0].interface);
    237262       
     
    239264       
    240265        if (rc != EOK) {
    241                 usb_log_warning("Problem with parsing Report descriptor: %s.\n",
     266                usb_log_warning("Problem with getting Report descriptor: %s.\n",
    242267                    str_error(rc));
    243268                return rc;
    244269        }
     270       
     271        rc = usb_hid_parse_report_descriptor(hid_dev->parser,
     272            hid_dev->report_desc, hid_dev->report_desc_size);
     273        if (rc != EOK) {
     274                usb_log_warning("Problem parsing Report descriptor: %s.\n",
     275                    str_error(rc));
     276                return rc;
     277        }
     278       
     279        usb_hid_descriptor_print(hid_dev->parser);
    245280       
    246281        return EOK;
     
    250285/* API functions                                                              */
    251286/*----------------------------------------------------------------------------*/
    252 
     287/**
     288 * Creates new uninitialized HID device structure.
     289 *
     290 * @return Pointer to the new HID device structure, or NULL if an error occured.
     291 */
    253292usbhid_dev_t *usbhid_dev_new(void)
    254293{
     
    263302        memset(dev, 0, sizeof(usbhid_dev_t));
    264303       
     304        dev->parser = (usb_hid_report_parser_t *)(malloc(sizeof(
     305            usb_hid_report_parser_t)));
     306        if (dev->parser == NULL) {
     307                usb_log_fatal("No memory!\n");
     308                free(dev);
     309                return NULL;
     310        }
     311       
    265312        dev->initialized = 0;
    266313       
     
    269316
    270317/*----------------------------------------------------------------------------*/
    271 
     318/**
     319 * Properly destroys the HID device structure.
     320 *
     321 * @note Currently does not clean-up the used pipes, as there are no functions
     322 *       offering such functionality.
     323 *
     324 * @param hid_dev Pointer to the structure to be destroyed.
     325 */
    272326void usbhid_dev_free(usbhid_dev_t **hid_dev)
    273327{
     
    292346
    293347/*----------------------------------------------------------------------------*/
    294 
     348/**
     349 * Initializes HID device structure.
     350 *
     351 * @param hid_dev HID device structure to be initialized.
     352 * @param dev DDF device representing the HID device.
     353 * @param poll_ep_desc Description of the polling (Interrupt In) endpoint
     354 *                     that has to be present in the device in order to
     355 *                     successfuly initialize the structure.
     356 *
     357 * @retval EOK if successful.
     358 * @retval EINVAL if some argument is missing.
     359 * @return Other value inherited from one of functions
     360 *         usb_device_connection_initialize_from_device(),
     361 *         usb_endpoint_pipe_initialize_default_control(),
     362 *         usb_endpoint_pipe_start_session(), usb_endpoint_pipe_end_session(),
     363 *         usbhid_dev_process_descriptors().
     364 *
     365 * @sa usbhid_dev_process_descriptors()
     366 */
    295367int usbhid_dev_init(usbhid_dev_t *hid_dev, ddf_dev_t *dev,
    296368    usb_endpoint_description_t *poll_ep_desc)
     
    339411                return rc;
    340412        }
     413       
     414        /*
     415         * Initialize the report parser.
     416         */
     417        rc = usb_hid_parser_init(hid_dev->parser);
     418        if (rc != EOK) {
     419                usb_log_error("Failed to initialize report parser.\n");
     420                return rc;
     421        }
    341422
    342423        /*
    343424         * Get descriptors, parse descriptors and save endpoints.
    344425         */
    345         usb_endpoint_pipe_start_session(&hid_dev->ctrl_pipe);
     426        rc = usb_endpoint_pipe_start_session(&hid_dev->ctrl_pipe);
     427        if (rc != EOK) {
     428                usb_log_error("Failed to start session on the control pipe: %s"
     429                    ".\n", str_error(rc));
     430                return rc;
     431        }
    346432       
    347433        rc = usbhid_dev_process_descriptors(hid_dev, poll_ep_desc);
    348        
    349         usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe);
    350         if (rc != EOK) {
     434        if (rc != EOK) {
     435                /* TODO: end session?? */
    351436                usb_log_error("Failed to process descriptors: %s.\n",
    352437                    str_error(rc));
     
    354439        }
    355440       
     441        rc = usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe);
     442        if (rc != EOK) {
     443                usb_log_warning("Failed to start session on the control pipe: "
     444                    "%s.\n", str_error(rc));
     445                return rc;
     446        }
     447       
    356448        hid_dev->initialized = 1;
    357449        usb_log_info("HID device structure initialized.\n");
  • uspace/drv/usbhid/hiddev.h

    r60a228f r9d9ffdd  
    4848
    4949/**
    50  * @brief USB/HID device type.
     50 * USB/HID device type.
     51 *
     52 * Holds a reference to DDF device structure, and HID-specific data, such
     53 * as information about used pipes (one Control pipe and one Interrupt In pipe),
     54 * polling interval, assigned interface number, Report descriptor and a
     55 * reference to the Report parser used to parse incoming reports and composing
     56 * outgoing reports.
    5157 */
    5258typedef struct {
     59        /** DDF device representing the controlled HID device. */
    5360        ddf_dev_t *device;
    5461
     62        /** Physical connection to the device. */
    5563        usb_device_connection_t wire;
     64        /** USB pipe corresponding to the default Control endpoint. */
    5665        usb_endpoint_pipe_t ctrl_pipe;
     66        /** USB pipe corresponding to the Interrupt In (polling) pipe. */
    5767        usb_endpoint_pipe_t poll_pipe;
    5868       
     69        /** Polling interval retreived from the Interface descriptor. */
     70        short poll_interval;
     71       
     72        /** Interface number assigned to this device. */
    5973        uint16_t iface;
    6074       
     75        /** Report descriptor. */
    6176        uint8_t *report_desc;
     77
     78        size_t report_desc_size;
     79
     80        /** HID Report parser. */
    6281        usb_hid_report_parser_t *parser;
    6382       
     83        /** State of the structure (for checking before use). */
    6484        int initialized;
    6585} usbhid_dev_t;
  • uspace/drv/usbhid/hidreq.c

    r60a228f r9d9ffdd  
    4646
    4747/*----------------------------------------------------------------------------*/
    48 
     48/**
     49 * Send Set Report request to the HID device.
     50 *
     51 * @param hid_dev HID device to send the request to.
     52 * @param type Type of the report.
     53 * @param buffer Report data.
     54 * @param buf_size Report data size (in bytes).
     55 *
     56 * @retval EOK if successful.
     57 * @retval EINVAL if no HID device is given.
     58 * @return Other value inherited from one of functions
     59 *         usb_endpoint_pipe_start_session(), usb_endpoint_pipe_end_session(),
     60 *         usb_control_request_set().
     61 */
    4962int usbhid_req_set_report(usbhid_dev_t *hid_dev,
    5063    usb_hid_report_type_t type, uint8_t *buffer, size_t buf_size)
     
    6982                return sess_rc;
    7083        }
     84       
     85        uint16_t value = 0;
     86        value |= (type << 8);
    7187
    7288        usb_log_debug("Sending Set_Report request to the device.\n");
     
    7490        rc = usb_control_request_set(&hid_dev->ctrl_pipe,
    7591            USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
    76             USB_HIDREQ_SET_REPORT, type, hid_dev->iface, buffer, buf_size);
    77 
    78         sess_rc = usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe);
    79 
    80         if (rc != EOK) {
    81                 usb_log_warning("Error sending output report to the keyboard: "
    82                     "%s.\n", str_error(rc));
    83                 return rc;
    84         }
    85 
    86         if (sess_rc != EOK) {
    87                 usb_log_warning("Error closing session: %s.\n",
    88                     str_error(sess_rc));
    89                 return sess_rc;
    90         }
    91        
    92         return EOK;
    93 }
    94 
    95 /*----------------------------------------------------------------------------*/
    96 
     92            USB_HIDREQ_SET_REPORT, value, hid_dev->iface, buffer, buf_size);
     93
     94        sess_rc = usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe);
     95
     96        if (rc != EOK) {
     97                usb_log_warning("Error sending output report to the keyboard: "
     98                    "%s.\n", str_error(rc));
     99                return rc;
     100        }
     101
     102        if (sess_rc != EOK) {
     103                usb_log_warning("Error closing session: %s.\n",
     104                    str_error(sess_rc));
     105                return sess_rc;
     106        }
     107       
     108        return EOK;
     109}
     110
     111/*----------------------------------------------------------------------------*/
     112/**
     113 * Send Set Protocol request to the HID device.
     114 *
     115 * @param hid_dev HID device to send the request to.
     116 * @param protocol Protocol to set.
     117 *
     118 * @retval EOK if successful.
     119 * @retval EINVAL if no HID device is given.
     120 * @return Other value inherited from one of functions
     121 *         usb_endpoint_pipe_start_session(), usb_endpoint_pipe_end_session(),
     122 *         usb_control_request_set().
     123 */
    97124int usbhid_req_set_protocol(usbhid_dev_t *hid_dev, usb_hid_protocol_t protocol)
    98125{
     
    142169
    143170/*----------------------------------------------------------------------------*/
     171/**
     172 * Send Set Idle request to the HID device.
     173 *
     174 * @param hid_dev HID device to send the request to.
     175 * @param duration Duration value (is multiplicated by 4 by the device to
     176 *                 get real duration in miliseconds).
     177 *
     178 * @retval EOK if successful.
     179 * @retval EINVAL if no HID device is given.
     180 * @return Other value inherited from one of functions
     181 *         usb_endpoint_pipe_start_session(), usb_endpoint_pipe_end_session(),
     182 *         usb_control_request_set().
     183 */
     184int usbhid_req_set_idle(usbhid_dev_t *hid_dev, uint8_t duration)
     185{
     186        if (hid_dev == NULL) {
     187                usb_log_error("usbhid_req_set_idle(): no HID device "
     188                    "structure given.\n");
     189                return EINVAL;
     190        }
     191       
     192        /*
     193         * No need for checking other parameters, as they are checked in
     194         * the called function (usb_control_request_set()).
     195         */
     196       
     197        int rc, sess_rc;
     198       
     199        sess_rc = usb_endpoint_pipe_start_session(&hid_dev->ctrl_pipe);
     200        if (sess_rc != EOK) {
     201                usb_log_warning("Failed to start a session: %s.\n",
     202                    str_error(sess_rc));
     203                return sess_rc;
     204        }
     205
     206        usb_log_debug("Sending Set_Idle request to the device ("
     207            "duration: %u, iface: %d).\n", duration, hid_dev->iface);
     208       
     209        uint16_t value = duration << 8;
     210       
     211        rc = usb_control_request_set(&hid_dev->ctrl_pipe,
     212            USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
     213            USB_HIDREQ_SET_IDLE, value, hid_dev->iface, NULL, 0);
     214
     215        sess_rc = usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe);
     216
     217        if (rc != EOK) {
     218                usb_log_warning("Error sending output report to the keyboard: "
     219                    "%s.\n", str_error(rc));
     220                return rc;
     221        }
     222
     223        if (sess_rc != EOK) {
     224                usb_log_warning("Error closing session: %s.\n",
     225                    str_error(sess_rc));
     226                return sess_rc;
     227        }
     228       
     229        return EOK;
     230}
     231
     232/*----------------------------------------------------------------------------*/
     233/**
     234 * Send Get Report request to the HID device.
     235 *
     236 * @param[in] hid_dev HID device to send the request to.
     237 * @param[in] type Type of the report.
     238 * @param[in][out] buffer Buffer for the report data.
     239 * @param[in] buf_size Size of the buffer (in bytes).
     240 * @param[out] actual_size Actual size of report received from the device
     241 *                         (in bytes).
     242 *
     243 * @retval EOK if successful.
     244 * @retval EINVAL if no HID device is given.
     245 * @return Other value inherited from one of functions
     246 *         usb_endpoint_pipe_start_session(), usb_endpoint_pipe_end_session(),
     247 *         usb_control_request_set().
     248 */
     249int usbhid_req_get_report(usbhid_dev_t *hid_dev, usb_hid_report_type_t type,
     250    uint8_t *buffer, size_t buf_size, size_t *actual_size)
     251{
     252        if (hid_dev == NULL) {
     253                usb_log_error("usbhid_req_set_report(): no HID device structure"
     254                    " given.\n");
     255                return EINVAL;
     256        }
     257       
     258        /*
     259         * No need for checking other parameters, as they are checked in
     260         * the called function (usb_control_request_set()).
     261         */
     262       
     263        int rc, sess_rc;
     264       
     265        sess_rc = usb_endpoint_pipe_start_session(&hid_dev->ctrl_pipe);
     266        if (sess_rc != EOK) {
     267                usb_log_warning("Failed to start a session: %s.\n",
     268                    str_error(sess_rc));
     269                return sess_rc;
     270        }
     271
     272        uint16_t value = 0;
     273        value |= (type << 8);
     274       
     275        usb_log_debug("Sending Get_Report request to the device.\n");
     276       
     277        rc = usb_control_request_get(&hid_dev->ctrl_pipe,
     278            USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
     279            USB_HIDREQ_GET_REPORT, value, hid_dev->iface, buffer, buf_size,
     280            actual_size);
     281
     282        sess_rc = usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe);
     283
     284        if (rc != EOK) {
     285                usb_log_warning("Error sending output report to the keyboard: "
     286                    "%s.\n", str_error(rc));
     287                return rc;
     288        }
     289
     290        if (sess_rc != EOK) {
     291                usb_log_warning("Error closing session: %s.\n",
     292                    str_error(sess_rc));
     293                return sess_rc;
     294        }
     295       
     296        return EOK;
     297}
     298
     299/*----------------------------------------------------------------------------*/
     300/**
     301 * Send Get Protocol request to the HID device.
     302 *
     303 * @param[in] hid_dev HID device to send the request to.
     304 * @param[out] protocol Current protocol of the device.
     305 *
     306 * @retval EOK if successful.
     307 * @retval EINVAL if no HID device is given.
     308 * @return Other value inherited from one of functions
     309 *         usb_endpoint_pipe_start_session(), usb_endpoint_pipe_end_session(),
     310 *         usb_control_request_set().
     311 */
     312int usbhid_req_get_protocol(usbhid_dev_t *hid_dev, usb_hid_protocol_t *protocol)
     313{
     314        if (hid_dev == NULL) {
     315                usb_log_error("usbhid_req_set_protocol(): no HID device "
     316                    "structure given.\n");
     317                return EINVAL;
     318        }
     319       
     320        /*
     321         * No need for checking other parameters, as they are checked in
     322         * the called function (usb_control_request_set()).
     323         */
     324       
     325        int rc, sess_rc;
     326       
     327        sess_rc = usb_endpoint_pipe_start_session(&hid_dev->ctrl_pipe);
     328        if (sess_rc != EOK) {
     329                usb_log_warning("Failed to start a session: %s.\n",
     330                    str_error(sess_rc));
     331                return sess_rc;
     332        }
     333
     334        usb_log_debug("Sending Get_Protocol request to the device ("
     335            "iface: %d).\n", hid_dev->iface);
     336       
     337        uint8_t buffer[1];
     338        size_t actual_size = 0;
     339       
     340        rc = usb_control_request_get(&hid_dev->ctrl_pipe,
     341            USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
     342            USB_HIDREQ_GET_PROTOCOL, 0, hid_dev->iface, buffer, 1, &actual_size);
     343
     344        sess_rc = usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe);
     345
     346        if (rc != EOK) {
     347                usb_log_warning("Error sending output report to the keyboard: "
     348                    "%s.\n", str_error(rc));
     349                return rc;
     350        }
     351
     352        if (sess_rc != EOK) {
     353                usb_log_warning("Error closing session: %s.\n",
     354                    str_error(sess_rc));
     355                return sess_rc;
     356        }
     357       
     358        if (actual_size != 1) {
     359                usb_log_warning("Wrong data size: %zu, expected: 1.\n",
     360                        actual_size);
     361                return ELIMIT;
     362        }
     363       
     364        *protocol = buffer[0];
     365       
     366        return EOK;
     367}
     368
     369/*----------------------------------------------------------------------------*/
     370/**
     371 * Send Get Idle request to the HID device.
     372 *
     373 * @param[in] hid_dev HID device to send the request to.
     374 * @param[out] duration Duration value (multiplicate by 4 to get real duration
     375 *                      in miliseconds).
     376 *
     377 * @retval EOK if successful.
     378 * @retval EINVAL if no HID device is given.
     379 * @return Other value inherited from one of functions
     380 *         usb_endpoint_pipe_start_session(), usb_endpoint_pipe_end_session(),
     381 *         usb_control_request_set().
     382 */
     383int usbhid_req_get_idle(usbhid_dev_t *hid_dev, uint8_t *duration)
     384{
     385        if (hid_dev == NULL) {
     386                usb_log_error("usbhid_req_set_idle(): no HID device "
     387                    "structure given.\n");
     388                return EINVAL;
     389        }
     390       
     391        /*
     392         * No need for checking other parameters, as they are checked in
     393         * the called function (usb_control_request_set()).
     394         */
     395       
     396        int rc, sess_rc;
     397       
     398        sess_rc = usb_endpoint_pipe_start_session(&hid_dev->ctrl_pipe);
     399        if (sess_rc != EOK) {
     400                usb_log_warning("Failed to start a session: %s.\n",
     401                    str_error(sess_rc));
     402                return sess_rc;
     403        }
     404
     405        usb_log_debug("Sending Get_Idle request to the device ("
     406            "iface: %d).\n", hid_dev->iface);
     407       
     408        uint16_t value = 0;
     409        uint8_t buffer[1];
     410        size_t actual_size = 0;
     411       
     412        rc = usb_control_request_get(&hid_dev->ctrl_pipe,
     413            USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
     414            USB_HIDREQ_GET_IDLE, value, hid_dev->iface, buffer, 1,
     415            &actual_size);
     416
     417        sess_rc = usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe);
     418
     419        if (rc != EOK) {
     420                usb_log_warning("Error sending output report to the keyboard: "
     421                    "%s.\n", str_error(rc));
     422                return rc;
     423        }
     424
     425        if (sess_rc != EOK) {
     426                usb_log_warning("Error closing session: %s.\n",
     427                    str_error(sess_rc));
     428                return sess_rc;
     429        }
     430       
     431        if (actual_size != 1) {
     432                usb_log_warning("Wrong data size: %zu, expected: 1.\n",
     433                        actual_size);
     434                return ELIMIT;
     435        }
     436       
     437        *duration = buffer[0];
     438       
     439        return EOK;
     440}
     441
     442/*----------------------------------------------------------------------------*/
    144443
    145444/**
  • uspace/drv/usbhid/hidreq.h

    r60a228f r9d9ffdd  
    5050int usbhid_req_set_protocol(usbhid_dev_t *hid_dev, usb_hid_protocol_t protocol);
    5151
     52int usbhid_req_set_idle(usbhid_dev_t *hid_dev, uint8_t duration);
     53
     54int usbhid_req_get_report(usbhid_dev_t *hid_dev, usb_hid_report_type_t type,
     55    uint8_t *buffer, size_t buf_size, size_t *actual_size);
     56
     57int usbhid_req_get_protocol(usbhid_dev_t *hid_dev, usb_hid_protocol_t *protocol);
     58
     59int usbhid_req_get_idle(usbhid_dev_t *hid_dev, uint8_t *duration);
     60
    5261/*----------------------------------------------------------------------------*/
    5362
  • uspace/drv/usbhid/kbddev.c

    r60a228f r9d9ffdd  
    3737#include <errno.h>
    3838#include <str_error.h>
    39 #include <fibril.h>
     39#include <stdio.h>
    4040
    4141#include <io/keycode.h>
    4242#include <ipc/kbd.h>
    4343#include <async.h>
     44#include <fibril.h>
     45#include <fibril_synch.h>
    4446
    4547#include <usb/usb.h>
     
    5557#include "layout.h"
    5658#include "conv.h"
    57 
    58 /*----------------------------------------------------------------------------*/
    59 
     59#include "kbdrepeat.h"
     60
     61/*----------------------------------------------------------------------------*/
     62/** Default modifiers when the keyboard is initialized. */
    6063static const unsigned DEFAULT_ACTIVE_MODS = KM_NUM_LOCK;
     64
     65/** Boot protocol report size (key part). */
    6166static const size_t BOOTP_REPORT_SIZE = 6;
     67
     68/** Boot protocol total report size. */
    6269static const size_t BOOTP_BUFFER_SIZE = 8;
     70
     71/** Boot protocol output report size. */
    6372static const size_t BOOTP_BUFFER_OUT_SIZE = 1;
     73
     74/** Boot protocol error key code. */
     75static const uint8_t BOOTP_ERROR_ROLLOVER = 1;
     76
     77/** Default idle rate for keyboards. */
     78static const uint8_t IDLE_RATE = 0;
     79
     80/** Delay before a pressed key starts auto-repeating. */
     81static const unsigned int DEFAULT_DELAY_BEFORE_FIRST_REPEAT = 500 * 1000;
     82
     83/** Delay between two repeats of a pressed key when auto-repeating. */
     84static const unsigned int DEFAULT_REPEAT_DELAY = 50 * 1000;
    6485
    6586/** Keyboard polling endpoint description for boot protocol class. */
     
    79100#define NUM_LAYOUTS 3
    80101
     102/** Keyboard layout map. */
    81103static layout_op_t *layout[NUM_LAYOUTS] = {
    82104        &us_qwerty_op,
     
    90112/* Modifier constants                                                         */
    91113/*----------------------------------------------------------------------------*/
    92 
     114/** Mapping of USB modifier key codes to generic modifier key codes. */
    93115static const keycode_t usbhid_modifiers_keycodes[USB_HID_MOD_COUNT] = {
    94116        KC_LCTRL,         /* USB_HID_MOD_LCTRL */
     
    111133};
    112134
    113 /** Default handler for IPC methods not handled by DDF.
    114  *
    115  * @param dev Device handling the call.
     135/**
     136 * Default handler for IPC methods not handled by DDF.
     137 *
     138 * Currently recognizes only one method (IPC_M_CONNECT_TO_ME), in which case it
     139 * assumes the caller is the console and thus it stores IPC phone to it for
     140 * later use by the driver to notify about key events.
     141 *
     142 * @param fun Device function handling the call.
    116143 * @param icallid Call id.
    117144 * @param icall Call data.
     
    144171/* Key processing functions                                                   */
    145172/*----------------------------------------------------------------------------*/
    146 
     173/**
     174 * Handles turning of LED lights on and off.
     175 *
     176 * In case of USB keyboards, the LEDs are handled in the driver, not in the
     177 * device. When there should be a change (lock key was pressed), the driver
     178 * uses a Set_Report request sent to the device to set the state of the LEDs.
     179 *
     180 * This functions sets the LED lights according to current settings of modifiers
     181 * kept in the keyboard device structure.
     182 *
     183 * @param kbd_dev Keyboard device structure.
     184 */
    147185static void usbhid_kbd_set_led(usbhid_kbd_t *kbd_dev)
    148186{
    149187        uint8_t buffer[BOOTP_BUFFER_OUT_SIZE];
    150188        int rc= 0;
    151         unsigned i;
    152189       
    153190        memset(buffer, 0, BOOTP_BUFFER_OUT_SIZE);
     
    177214        }
    178215       
    179         // TODO: REFACTOR!!!
    180        
    181         usb_log_debug("Output report buffer: ");
    182         for (i = 0; i < BOOTP_BUFFER_OUT_SIZE; ++i) {
    183                 usb_log_debug("0x%x ", buffer[i]);
    184         }
    185         usb_log_debug("\n");
    186        
    187         uint16_t value = 0;
    188         value |= (USB_HID_REPORT_TYPE_OUTPUT << 8);
    189 
     216        usb_log_debug("Output report buffer: %s\n",
     217            usb_debug_str_buffer(buffer, BOOTP_BUFFER_OUT_SIZE, 0));
     218       
    190219        assert(kbd_dev->hid_dev != NULL);
    191220        assert(kbd_dev->hid_dev->initialized);
    192         usbhid_req_set_report(kbd_dev->hid_dev, value, buffer,
    193             BOOTP_BUFFER_OUT_SIZE);
    194 }
    195 
    196 /*----------------------------------------------------------------------------*/
    197 
    198 static void usbhid_kbd_push_ev(usbhid_kbd_t *kbd_dev, int type,
    199     unsigned int key)
     221        usbhid_req_set_report(kbd_dev->hid_dev, USB_HID_REPORT_TYPE_OUTPUT,
     222            buffer, BOOTP_BUFFER_OUT_SIZE);
     223}
     224
     225/*----------------------------------------------------------------------------*/
     226/**
     227 * Processes key events.
     228 *
     229 * @note This function was copied from AT keyboard driver and modified to suit
     230 *       USB keyboard.
     231 *
     232 * @note Lock keys are not sent to the console, as they are completely handled
     233 *       in the driver. It may, however, be required later that the driver
     234 *       sends also these keys to application (otherwise it cannot use those
     235 *       keys at all).
     236 *
     237 * @param kbd_dev Keyboard device structure.
     238 * @param type Type of the event (press / release). Recognized values:
     239 *             KEY_PRESS, KEY_RELEASE
     240 * @param key Key code of the key according to HID Usage Tables.
     241 */
     242void usbhid_kbd_push_ev(usbhid_kbd_t *kbd_dev, int type, unsigned int key)
    200243{
    201244        console_event_t ev;
    202245        unsigned mod_mask;
    203246
    204         // TODO: replace by our own parsing?? or are the key codes identical??
     247        /*
     248         * These parts are copy-pasted from the AT keyboard driver.
     249         *
     250         * They definitely require some refactoring, but will keep it for later
     251         * when the console and keyboard system is changed in HelenOS.
     252         */
    205253        switch (key) {
    206254        case KC_LCTRL: mod_mask = KM_LCTRL; break;
     
    228276
    229277        if (mod_mask != 0) {
    230                 usb_log_debug2("\n\nChanging mods and lock keys\n");
    231                 usb_log_debug2("\nmods before: 0x%x\n", kbd_dev->mods);
    232                 usb_log_debug2("\nLock keys before:0x%x\n\n",
    233                     kbd_dev->lock_keys);
    234                
    235278                if (type == KEY_PRESS) {
    236                         usb_log_debug2("\nKey pressed.\n");
    237279                        /*
    238280                         * Only change lock state on transition from released
     
    240282                         * up the lock state.
    241283                         */
     284                        unsigned int locks_old = kbd_dev->lock_keys;
     285                       
    242286                        kbd_dev->mods =
    243287                            kbd_dev->mods ^ (mod_mask & ~kbd_dev->lock_keys);
     
    245289
    246290                        /* Update keyboard lock indicator lights. */
    247                         usbhid_kbd_set_led(kbd_dev);
     291                        if (kbd_dev->lock_keys != locks_old) {
     292                                usbhid_kbd_set_led(kbd_dev);
     293                        }
    248294                } else {
    249                         usb_log_debug2("\nKey released.\n");
    250295                        kbd_dev->lock_keys = kbd_dev->lock_keys & ~mod_mask;
    251296                }
    252297        }
    253298
    254         usb_log_debug2("\n\nmods after: 0x%x\n", kbd_dev->mods);
    255         usb_log_debug2("\nLock keys after: 0x%x\n\n", kbd_dev->lock_keys);
    256        
    257299        if (key == KC_CAPS_LOCK || key == KC_NUM_LOCK || key == KC_SCROLL_LOCK) {
    258300                // do not send anything to the console, this is our business
     
    281323        ev.key = key;
    282324        ev.mods = kbd_dev->mods;
    283        
    284         if (ev.mods & KM_NUM_LOCK) {
    285                 usb_log_debug("\n\nNum Lock turned on.\n\n");
    286         }
    287325
    288326        ev.c = layout[active_layout]->parse_ev(&ev);
    289327
    290328        usb_log_debug2("Sending key %d to the console\n", ev.key);
    291         assert(kbd_dev->console_phone != -1);
     329        if (kbd_dev->console_phone < 0) {
     330                usb_log_warning(
     331                    "Connection to console not ready, key discarded.\n");
     332                return;
     333        }
    292334       
    293335        async_msg_4(kbd_dev->console_phone, KBD_EVENT, ev.type, ev.key,
     
    296338
    297339/*----------------------------------------------------------------------------*/
    298 
     340/**
     341 * Checks if modifiers were pressed or released and generates key events.
     342 *
     343 * @param kbd_dev Keyboard device structure.
     344 * @param modifiers Bitmap of modifiers.
     345 *
     346 * @sa usbhid_kbd_push_ev()
     347 */
    299348static void usbhid_kbd_check_modifier_changes(usbhid_kbd_t *kbd_dev,
    300349    uint8_t modifiers)
     
    332381
    333382/*----------------------------------------------------------------------------*/
    334 
     383/**
     384 * Checks if some keys were pressed or released and generates key events.
     385 *
     386 * An event is created only when key is pressed or released. Besides handling
     387 * the events (usbhid_kbd_push_ev()), the auto-repeat fibril is notified about
     388 * key presses and releases (see usbhid_kbd_repeat_start() and
     389 * usbhid_kbd_repeat_stop()).
     390 *
     391 * @param kbd_dev Keyboard device structure.
     392 * @param key_codes Parsed keyboard report - codes of currently pressed keys
     393 *                  according to HID Usage Tables.
     394 * @param count Number of key codes in report (size of the report).
     395 *
     396 * @sa usbhid_kbd_push_ev(), usbhid_kbd_repeat_start(), usbhid_kbd_repeat_stop()
     397 */
    335398static void usbhid_kbd_check_key_changes(usbhid_kbd_t *kbd_dev,
    336     const uint8_t *key_codes)
    337 {
    338         // TODO: phantom state!!
    339        
     399    const uint8_t *key_codes, size_t count)
     400{
    340401        unsigned int key;
    341402        unsigned int i, j;
    342403       
    343         // TODO: quite dummy right now, think of better implementation
     404        /*
     405         * First of all, check if the kbd have reported phantom state.
     406         */
     407        i = 0;
     408        // all fields should report Error Rollover
     409        while (i < count &&
     410            key_codes[i] == BOOTP_ERROR_ROLLOVER) {
     411                ++i;
     412        }
     413        if (i == count) {
     414                usb_log_debug("Phantom state occured.\n");
     415                // phantom state, do nothing
     416                return;
     417        }
     418       
     419        /* TODO: quite dummy right now, think of better implementation */
     420        assert(count == kbd_dev->key_count);
    344421       
    345422        /*
    346423         * 1) Key releases
    347424         */
    348         for (j = 0; j < kbd_dev->keycode_count; ++j) {
     425        for (j = 0; j < count; ++j) {
    349426                // try to find the old key in the new key list
    350427                i = 0;
    351                 while (i < kbd_dev->keycode_count
    352                     && key_codes[i] != kbd_dev->keycodes[j]) {
     428                while (i < kbd_dev->key_count
     429                    && key_codes[i] != kbd_dev->keys[j]) {
    353430                        ++i;
    354431                }
    355432               
    356                 if (i == kbd_dev->keycode_count) {
     433                if (i == count) {
    357434                        // not found, i.e. the key was released
    358                         key = usbhid_parse_scancode(kbd_dev->keycodes[j]);
     435                        key = usbhid_parse_scancode(kbd_dev->keys[j]);
     436                        usbhid_kbd_repeat_stop(kbd_dev, key);
    359437                        usbhid_kbd_push_ev(kbd_dev, KEY_RELEASE, key);
    360                         usb_log_debug2("\nKey released: %d\n", key);
     438                        usb_log_debug2("Key released: %d\n", key);
    361439                } else {
    362440                        // found, nothing happens
     
    367445         * 1) Key presses
    368446         */
    369         for (i = 0; i < kbd_dev->keycode_count; ++i) {
     447        for (i = 0; i < kbd_dev->key_count; ++i) {
    370448                // try to find the new key in the old key list
    371449                j = 0;
    372                 while (j < kbd_dev->keycode_count
    373                     && kbd_dev->keycodes[j] != key_codes[i]) {
     450                while (j < count && kbd_dev->keys[j] != key_codes[i]) {
    374451                        ++j;
    375452                }
    376453               
    377                 if (j == kbd_dev->keycode_count) {
     454                if (j == count) {
    378455                        // not found, i.e. new key pressed
    379456                        key = usbhid_parse_scancode(key_codes[i]);
    380                         usb_log_debug2("\nKey pressed: %d (keycode: %d)\n", key,
     457                        usb_log_debug2("Key pressed: %d (keycode: %d)\n", key,
    381458                            key_codes[i]);
    382459                        usbhid_kbd_push_ev(kbd_dev, KEY_PRESS, key);
     460                        usbhid_kbd_repeat_start(kbd_dev, key);
    383461                } else {
    384462                        // found, nothing happens
     
    386464        }
    387465       
    388         memcpy(kbd_dev->keycodes, key_codes, kbd_dev->keycode_count);
    389        
    390         usb_log_debug2("\nNew stored keycodes: ");
    391         for (i = 0; i < kbd_dev->keycode_count; ++i) {
    392                 usb_log_debug2("%d ", kbd_dev->keycodes[i]);
    393         }
     466        memcpy(kbd_dev->keys, key_codes, count);
     467
     468        usb_log_debug("New stored keycodes: %s\n",
     469            usb_debug_str_buffer(kbd_dev->keys, kbd_dev->key_count, 0));
    394470}
    395471
     
    397473/* Callbacks for parser                                                       */
    398474/*----------------------------------------------------------------------------*/
    399 
     475/**
     476 * Callback function for the HID report parser.
     477 *
     478 * This function is called by the HID report parser with the parsed report.
     479 * The parsed report is used to check if any events occured (key was pressed or
     480 * released, modifier was pressed or released).
     481 *
     482 * @param key_codes Parsed keyboard report - codes of currently pressed keys
     483 *                  according to HID Usage Tables.
     484 * @param count Number of key codes in report (size of the report).
     485 * @param modifiers Bitmap of modifiers (Ctrl, Alt, Shift, GUI).
     486 * @param arg User-specified argument. Expects pointer to the keyboard device
     487 *            structure representing the keyboard.
     488 *
     489 * @sa usbhid_kbd_check_key_changes(), usbhid_kbd_check_modifier_changes()
     490 */
    400491static void usbhid_kbd_process_keycodes(const uint8_t *key_codes, size_t count,
    401492    uint8_t modifiers, void *arg)
     
    406497                return;
    407498        }
    408 
    409         usb_log_debug2("Got keys from parser: ");
    410         unsigned i;
    411         for (i = 0; i < count; ++i) {
    412                 usb_log_debug2("%d ", key_codes[i]);
    413         }
    414         usb_log_debug2("\n");
    415499       
    416500        usbhid_kbd_t *kbd_dev = (usbhid_kbd_t *)arg;
    417501        assert(kbd_dev != NULL);
    418        
    419         if (count != kbd_dev->keycode_count) {
     502
     503        usb_log_debug("Got keys from parser: %s\n",
     504            usb_debug_str_buffer(key_codes, count, 0));
     505       
     506        if (count != kbd_dev->key_count) {
    420507                usb_log_warning("Number of received keycodes (%d) differs from"
    421                     " expected number (%d).\n", count, kbd_dev->keycode_count);
     508                    " expected number (%d).\n", count, kbd_dev->key_count);
    422509                return;
    423510        }
    424511       
    425512        usbhid_kbd_check_modifier_changes(kbd_dev, modifiers);
    426         usbhid_kbd_check_key_changes(kbd_dev, key_codes);
     513        usbhid_kbd_check_key_changes(kbd_dev, key_codes, count);
    427514}
    428515
     
    430517/* General kbd functions                                                      */
    431518/*----------------------------------------------------------------------------*/
    432 
     519/**
     520 * Processes data received from the device in form of report.
     521 *
     522 * This function uses the HID report parser to translate the data received from
     523 * the device into generic USB HID key codes and into generic modifiers bitmap.
     524 * The parser then calls the given callback (usbhid_kbd_process_keycodes()).
     525 *
     526 * @note Currently, only the boot protocol is supported.
     527 *
     528 * @param kbd_dev Keyboard device structure (must be initialized).
     529 * @param buffer Data from the keyboard (i.e. the report).
     530 * @param actual_size Size of the data from keyboard (report size) in bytes.
     531 *
     532 * @sa usbhid_kbd_process_keycodes(), usb_hid_boot_keyboard_input_report().
     533 */
    433534static void usbhid_kbd_process_data(usbhid_kbd_t *kbd_dev,
    434535                                    uint8_t *buffer, size_t actual_size)
    435536{
     537        assert(kbd_dev->initialized);
     538        assert(kbd_dev->hid_dev->parser != NULL);
     539       
    436540        usb_hid_report_in_callbacks_t *callbacks =
    437541            (usb_hid_report_in_callbacks_t *)malloc(
     
    440544        callbacks->keyboard = usbhid_kbd_process_keycodes;
    441545
    442         //usb_hid_parse_report(kbd_dev->parser, buffer, actual_size, callbacks,
    443         //    NULL);
    444         /*usb_log_debug2("Calling usb_hid_boot_keyboard_input_report() with size"
    445             " %zu\n", actual_size);*/
    446         //dump_buffer("bufffer: ", buffer, actual_size);
    447        
    448         int rc = usb_hid_boot_keyboard_input_report(buffer, actual_size,
    449             callbacks, kbd_dev);
     546        usb_log_debug("Calling usb_hid_parse_report() with "
     547            "buffer %s\n", usb_debug_str_buffer(buffer, actual_size, 0));
     548       
     549//      int rc = usb_hid_boot_keyboard_input_report(buffer, actual_size,
     550//          callbacks, kbd_dev);
     551        int rc = usb_hid_parse_report(kbd_dev->hid_dev->parser, buffer,
     552            actual_size, callbacks, kbd_dev);
    450553       
    451554        if (rc != EOK) {
     
    458561/* HID/KBD structure manipulation                                             */
    459562/*----------------------------------------------------------------------------*/
    460 
     563/**
     564 * Creates a new USB/HID keyboard structure.
     565 *
     566 * The structure returned by this function is not initialized. Use
     567 * usbhid_kbd_init() to initialize it prior to polling.
     568 *
     569 * @return New uninitialized structure for representing a USB/HID keyboard or
     570 *         NULL if not successful (memory error).
     571 */
    461572static usbhid_kbd_t *usbhid_kbd_new(void)
    462573{
     
    484595
    485596/*----------------------------------------------------------------------------*/
    486 
     597/**
     598 * Properly destroys the USB/HID keyboard structure.
     599 *
     600 * @param kbd_dev Pointer to the structure to be destroyed.
     601 */
    487602static void usbhid_kbd_free(usbhid_kbd_t **kbd_dev)
    488603{
     
    499614        }
    500615       
     616        if ((*kbd_dev)->repeat_mtx != NULL) {
     617                /* TODO: replace by some check and wait */
     618                assert(!fibril_mutex_is_locked((*kbd_dev)->repeat_mtx));
     619                free((*kbd_dev)->repeat_mtx);
     620        }
     621
    501622        free(*kbd_dev);
    502623        *kbd_dev = NULL;
     
    504625
    505626/*----------------------------------------------------------------------------*/
    506 
     627/**
     628 * Initialization of the USB/HID keyboard structure.
     629 *
     630 * This functions initializes required structures from the device's descriptors.
     631 *
     632 * During initialization, the keyboard is switched into boot protocol, the idle
     633 * rate is set to 0 (infinity), resulting in the keyboard only reporting event
     634 * when a key is pressed or released. Finally, the LED lights are turned on
     635 * according to the default setup of lock keys.
     636 *
     637 * @note By default, the keyboards is initialized with Num Lock turned on and
     638 *       other locks turned off.
     639 *
     640 * @param kbd_dev Keyboard device structure to be initialized.
     641 * @param dev DDF device structure of the keyboard.
     642 *
     643 * @retval EOK if successful.
     644 * @retval EINVAL if some parameter is not given.
     645 * @return Other value inherited from function usbhid_dev_init().
     646 */
    507647static int usbhid_kbd_init(usbhid_kbd_t *kbd_dev, ddf_dev_t *dev)
    508648{
     
    539679       
    540680        // save the size of the report (boot protocol report by default)
    541         kbd_dev->keycode_count = BOOTP_REPORT_SIZE;
    542         kbd_dev->keycodes = (uint8_t *)calloc(
    543             kbd_dev->keycode_count, sizeof(uint8_t));
    544        
    545         if (kbd_dev->keycodes == NULL) {
     681        kbd_dev->key_count = BOOTP_REPORT_SIZE;
     682        kbd_dev->keys = (uint8_t *)calloc(
     683            kbd_dev->key_count, sizeof(uint8_t));
     684       
     685        if (kbd_dev->keys == NULL) {
    546686                usb_log_fatal("No memory!\n");
    547                 return rc;
     687                return ENOMEM;
    548688        }
    549689       
     
    552692        kbd_dev->lock_keys = 0;
    553693       
     694        kbd_dev->repeat.key_new = 0;
     695        kbd_dev->repeat.key_repeated = 0;
     696        kbd_dev->repeat.delay_before = DEFAULT_DELAY_BEFORE_FIRST_REPEAT;
     697        kbd_dev->repeat.delay_between = DEFAULT_REPEAT_DELAY;
     698       
     699        kbd_dev->repeat_mtx = (fibril_mutex_t *)(
     700            malloc(sizeof(fibril_mutex_t)));
     701        if (kbd_dev->repeat_mtx == NULL) {
     702                usb_log_fatal("No memory!\n");
     703                free(kbd_dev->keys);
     704                return ENOMEM;
     705        }
     706       
     707        fibril_mutex_initialize(kbd_dev->repeat_mtx);
     708       
    554709        /*
    555710         * Set boot protocol.
    556711         * Set LEDs according to initial setup.
     712         * Set Idle rate
    557713         */
    558714        assert(kbd_dev->hid_dev != NULL);
    559715        assert(kbd_dev->hid_dev->initialized);
    560         usbhid_req_set_protocol(kbd_dev->hid_dev, USB_HID_PROTOCOL_BOOT);
     716        //usbhid_req_set_protocol(kbd_dev->hid_dev, USB_HID_PROTOCOL_BOOT);
    561717       
    562718        usbhid_kbd_set_led(kbd_dev);
     719       
     720        usbhid_req_set_idle(kbd_dev->hid_dev, IDLE_RATE);
    563721       
    564722        kbd_dev->initialized = 1;
     
    571729/* HID/KBD polling                                                            */
    572730/*----------------------------------------------------------------------------*/
    573 
     731/**
     732 * Main keyboard polling function.
     733 *
     734 * This function uses the Interrupt In pipe of the keyboard to poll for events.
     735 * The keyboard is initialized in a way that it reports only when a key is
     736 * pressed or released, so there is no actual need for any sleeping between
     737 * polls (see usbhid_kbd_try_add_device() or usbhid_kbd_init()).
     738 *
     739 * @param kbd_dev Initialized keyboard structure representing the device to
     740 *                poll.
     741 *
     742 * @sa usbhid_kbd_process_data()
     743 */
    574744static void usbhid_kbd_poll(usbhid_kbd_t *kbd_dev)
    575745{
     
    589759
    590760        while (true) {
    591                 async_usleep(1000 * 10);
    592 
    593761                sess_rc = usb_endpoint_pipe_start_session(
    594762                    &kbd_dev->hid_dev->poll_pipe);
     
    596764                        usb_log_warning("Failed to start a session: %s.\n",
    597765                            str_error(sess_rc));
    598                         continue;
     766                        break;
    599767                }
    600768
     
    608776                        usb_log_warning("Error polling the keyboard: %s.\n",
    609777                            str_error(rc));
    610                         continue;
     778                        break;
    611779                }
    612780
     
    614782                        usb_log_warning("Error closing session: %s.\n",
    615783                            str_error(sess_rc));
    616                         continue;
     784                        break;
    617785                }
    618786
     
    631799                usb_log_debug("Calling usbhid_kbd_process_data()\n");
    632800                usbhid_kbd_process_data(kbd_dev, buffer, actual_size);
    633         }
    634 
    635         // not reached
    636         assert(0);
    637 }
    638 
    639 /*----------------------------------------------------------------------------*/
    640 
     801               
     802                // disabled for now, no reason to sleep
     803                //async_usleep(kbd_dev->hid_dev->poll_interval);
     804        }
     805}
     806
     807/*----------------------------------------------------------------------------*/
     808/**
     809 * Function executed by the main driver fibril.
     810 *
     811 * Just starts polling the keyboard for events.
     812 *
     813 * @param arg Initialized keyboard device structure (of type usbhid_kbd_t)
     814 *            representing the device.
     815 *
     816 * @retval EOK if the fibril finished polling the device.
     817 * @retval EINVAL if no device was given in the argument.
     818 *
     819 * @sa usbhid_kbd_poll()
     820 *
     821 * @todo Change return value - only case when the fibril finishes is in case
     822 *       of some error, so the error should probably be propagated from function
     823 *       usbhid_kbd_poll() to here and up.
     824 */
    641825static int usbhid_kbd_fibril(void *arg)
    642826{
     
    660844/* API functions                                                              */
    661845/*----------------------------------------------------------------------------*/
    662 
     846/**
     847 * Function for adding a new device of type USB/HID/keyboard.
     848 *
     849 * This functions initializes required structures from the device's descriptors
     850 * and starts new fibril for polling the keyboard for events and another one for
     851 * handling auto-repeat of keys.
     852 *
     853 * During initialization, the keyboard is switched into boot protocol, the idle
     854 * rate is set to 0 (infinity), resulting in the keyboard only reporting event
     855 * when a key is pressed or released. Finally, the LED lights are turned on
     856 * according to the default setup of lock keys.
     857 *
     858 * @note By default, the keyboards is initialized with Num Lock turned on and
     859 *       other locks turned off.
     860 * @note Currently supports only boot-protocol keyboards.
     861 *
     862 * @param dev Device to add.
     863 *
     864 * @retval EOK if successful.
     865 * @retval ENOMEM if there
     866 * @return Other error code inherited from one of functions usbhid_kbd_init(),
     867 *         ddf_fun_bind() and ddf_fun_add_to_class().
     868 *
     869 * @sa usbhid_kbd_fibril(), usbhid_kbd_repeat_fibril()
     870 */
    663871int usbhid_kbd_try_add_device(ddf_dev_t *dev)
    664872{
     
    682890                    "structure.\n");
    683891                ddf_fun_destroy(kbd_fun);
    684                 return EINVAL;  // TODO: some other code??
     892                return ENOMEM;  // TODO: some other code??
    685893        }
    686894       
     
    731939        }
    732940        fibril_add_ready(fid);
     941       
     942        /*
     943         * Create new fibril for auto-repeat
     944         */
     945        fid = fibril_create(usbhid_kbd_repeat_fibril, kbd_dev);
     946        if (fid == 0) {
     947                usb_log_error("Failed to start fibril for KBD auto-repeat");
     948                return ENOMEM;
     949        }
     950        fibril_add_ready(fid);
    733951
    734952        (void)keyboard_ops;
  • uspace/drv/usbhid/kbddev.h

    r60a228f r9d9ffdd  
    3939#include <stdint.h>
    4040
     41#include <fibril_synch.h>
     42
    4143#include <usb/classes/hid.h>
     44#include <usb/classes/hidparser.h>
    4245#include <ddf/driver.h>
    4346#include <usb/pipes.h>
     
    4649
    4750/*----------------------------------------------------------------------------*/
     51/**
     52 * Structure for keeping information needed for auto-repeat of keys.
     53 */
     54typedef struct {
     55        /** Last pressed key. */
     56        unsigned int key_new;
     57        /** Key to be repeated. */
     58        unsigned int key_repeated;
     59        /** Delay before first repeat in microseconds. */
     60        unsigned int delay_before;
     61        /** Delay between repeats in microseconds. */
     62        unsigned int delay_between;
     63} usbhid_kbd_repeat_t;
    4864
    4965/**
    50  * @brief USB/HID keyboard device type.
     66 * USB/HID keyboard device type.
     67 *
     68 * Holds a reference to generic USB/HID device structure and keyboard-specific
     69 * data, such as currently pressed keys, modifiers and lock keys.
     70 *
     71 * Also holds a IPC phone to the console (since there is now no other way to
     72 * communicate with it).
     73 *
     74 * @note Storing active lock keys in this structure results in their setting
     75 *       being device-specific.
    5176 */
    5277typedef struct {
     78        /** Structure holding generic USB/HID device information. */
    5379        usbhid_dev_t *hid_dev;
    5480       
    55         uint8_t *keycodes;
    56         size_t keycode_count;
     81        /** Currently pressed keys (not translated to key codes). */
     82        uint8_t *keys;
     83        /** Count of stored keys (i.e. number of keys in the report). */
     84        size_t key_count;
     85        /** Currently pressed modifiers (bitmap). */
    5786        uint8_t modifiers;
    5887       
     88        /** Currently active modifiers including locks. Sent to the console. */
    5989        unsigned mods;
     90       
     91        /** Currently active lock keys. */
    6092        unsigned lock_keys;
    6193       
     94        /** IPC phone to the console device (for sending key events). */
    6295        int console_phone;
    6396       
     97        /** Information for auto-repeat of keys. */
     98        usbhid_kbd_repeat_t repeat;
     99       
     100        /** Mutex for accessing the information about auto-repeat. */
     101        fibril_mutex_t *repeat_mtx;
     102       
     103        /** State of the structure (for checking before use). */
    64104        int initialized;
    65105} usbhid_kbd_t;
     
    69109int usbhid_kbd_try_add_device(ddf_dev_t *dev);
    70110
     111void usbhid_kbd_push_ev(usbhid_kbd_t *kbd_dev, int type, unsigned int key);
     112
    71113#endif /* USBHID_KBDDEV_H_ */
    72114
  • uspace/drv/usbhid/main.c

    r60a228f r9d9ffdd  
    4747
    4848/*----------------------------------------------------------------------------*/
    49 
     49/**
     50 * Callback for passing a new device to the driver.
     51 *
     52 * @note Currently, only boot-protocol keyboards are supported by this driver.
     53 *
     54 * @param dev Structure representing the new device.
     55 *
     56 * @retval EOK if successful.
     57 * @retval EREFUSED if the device is not supported.
     58 */
    5059static int usbhid_add_device(ddf_dev_t *dev)
    5160{
     
    8089int main(int argc, char *argv[])
    8190{
    82         usb_log_enable(USB_LOG_LEVEL_INFO, NAME);
     91        usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
    8392        return ddf_driver_main(&kbd_driver);
    8493}
  • uspace/drv/usbhid/usbhid.ma

    r60a228f r9d9ffdd  
    1 10 usb&class=hid
    2 10 usb&class=HID
     1100 usb&interface&class=HID&subclass=0x01&protocol=0x01
    3210 usb&interface&class=HID
    4 10 usb&hid
  • uspace/drv/usbhub/usbhub.c

    r60a228f r9d9ffdd  
    149149        }
    150150
    151         //configuration descriptor
    152         /// \TODO check other configurations?
    153         usb_standard_configuration_descriptor_t config_descriptor;
    154         opResult = usb_request_get_bare_configuration_descriptor(
     151        /* Retrieve full configuration descriptor. */
     152        uint8_t *descriptors = NULL;
     153        size_t descriptors_size = 0;
     154        opResult = usb_request_get_full_configuration_descriptor_alloc(
    155155            &hub->endpoints.control, 0,
    156         &config_descriptor);
    157         if(opResult!=EOK){
    158                 dprintf(USB_LOG_LEVEL_ERROR, "could not get configuration descriptor, %d",opResult);
     156            (void **) &descriptors, &descriptors_size);
     157        if (opResult != EOK) {
     158                usb_log_error("Could not get configuration descriptor: %s.\n",
     159                    str_error(opResult));
    159160                return opResult;
    160161        }
    161         //set configuration
     162        usb_standard_configuration_descriptor_t *config_descriptor
     163            = (usb_standard_configuration_descriptor_t *) descriptors;
     164
     165        /* Set configuration. */
    162166        opResult = usb_request_set_configuration(&hub->endpoints.control,
    163                 config_descriptor.configuration_number);
    164 
    165         if (opResult != EOK) {
    166                 dprintf(USB_LOG_LEVEL_ERROR,
    167                                 "something went wrong when setting hub`s configuration, %d",
    168                                 opResult);
     167            config_descriptor->configuration_number);
     168
     169        if (opResult != EOK) {
     170                usb_log_error("Failed to set hub configuration: %s.\n",
     171                    str_error(opResult));
    169172                return opResult;
    170173        }
    171174        dprintf(USB_LOG_LEVEL_DEBUG, "\tused configuration %d",
    172                         config_descriptor.configuration_number);
    173 
    174         //full configuration descriptor
    175         size_t transferred = 0;
    176         uint8_t * descriptors = (uint8_t *)malloc(config_descriptor.total_length);
    177         if (descriptors == NULL) {
    178                 dprintf(USB_LOG_LEVEL_ERROR, "insufficient memory");
    179                 return ENOMEM;
    180         }
    181         opResult = usb_request_get_full_configuration_descriptor(&hub->endpoints.control,
    182             0, descriptors,
    183             config_descriptor.total_length, &transferred);
    184         if(opResult!=EOK){
    185                 free(descriptors);
    186                 dprintf(USB_LOG_LEVEL_ERROR,
    187                                 "could not get full configuration descriptor, %d",opResult);
    188                 return opResult;
    189         }
    190         if (transferred != config_descriptor.total_length) {
    191                 dprintf(USB_LOG_LEVEL_ERROR,
    192                                 "received incorrect full configuration descriptor");
    193                 return ELIMIT;
    194         }
     175                        config_descriptor->configuration_number);
    195176
    196177        usb_endpoint_mapping_t endpoint_mapping[1] = {
     
    204185        opResult = usb_endpoint_pipe_initialize_from_configuration(
    205186            endpoint_mapping, 1,
    206             descriptors, config_descriptor.total_length,
     187            descriptors, descriptors_size,
    207188            &hub->device_connection);
    208189        if (opResult != EOK) {
     
    252233        dprintf(USB_LOG_LEVEL_DEBUG, "starting control transaction");
    253234        usb_endpoint_pipe_start_session(&result->endpoints.control);
     235        opResult = usb_request_set_configuration(&result->endpoints.control, 1);
     236        assert(opResult == EOK);
     237
    254238        opResult = usb_request_get_descriptor(&result->endpoints.control,
    255239                        USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_DEVICE,
     
    262246                dprintf(USB_LOG_LEVEL_ERROR, "failed when receiving hub descriptor, badcode = %d",opResult);
    263247                free(serialized_descriptor);
    264                 return result;
     248                free(result);
     249                return NULL;
    265250        }
    266251        dprintf(USB_LOG_LEVEL_DEBUG2, "deserializing descriptor");
     
    268253        if(descriptor==NULL){
    269254                dprintf(USB_LOG_LEVEL_WARNING, "could not deserialize descriptor ");
    270                 result->port_count = 1;///\TODO this code is only for debug!!!
    271                 return result;
     255                free(result);
     256                return NULL;
    272257        }
    273258
     
    305290
    306291        usb_hub_info_t * hub_info = usb_create_hub_info(dev);
     292        if(!hub_info){
     293                return EINTR;
     294        }
    307295
    308296        int opResult;
     
    313301        opResult = usb_hub_process_configuration_descriptors(hub_info);
    314302        if(opResult != EOK){
    315                 dprintf(USB_LOG_LEVEL_ERROR,"could not get condiguration descriptors, %d",
     303                dprintf(USB_LOG_LEVEL_ERROR,"could not get configuration descriptors, %d",
    316304                                opResult);
    317305                return opResult;
  • uspace/drv/usbmid/explore.c

    r60a228f r9d9ffdd  
    4242#include "usbmid.h"
    4343
    44 /** Allocate and retrieve full configuration descriptor.
    45  *
    46  * @param[in] dev USB device.
    47  * @param[in] config_index Configuration index.
    48  * @param[out] size Pointer where to store size of the allocated buffer.
    49  * @return Allocated full configuration descriptor.
    50  * @retval NULL Error occured.
    51  */
    52 static void *get_configuration_descriptor(usbmid_device_t *dev,
    53     size_t config_index, size_t *size)
    54 {
    55         usb_standard_configuration_descriptor_t config_descriptor;
    56         int rc = usb_request_get_bare_configuration_descriptor(&dev->ctrl_pipe,
    57             config_index, &config_descriptor);
    58         if (rc != EOK) {
    59                 usb_log_error("Failed getting configuration descriptor: %s.\n",
    60                     str_error(rc));
    61                 return NULL;
    62         }
    63 
    64         void *full_config_descriptor = malloc(config_descriptor.total_length);
    65         if (full_config_descriptor == NULL) {
    66                 usb_log_fatal("Out of memory (wanted: %zuB).\n",
    67                     (size_t) config_descriptor.total_length);
    68                 return NULL;
    69         }
    70 
    71         size_t full_config_descriptor_size;
    72         rc = usb_request_get_full_configuration_descriptor(&dev->ctrl_pipe,
    73             config_index,
    74             full_config_descriptor, config_descriptor.total_length,
    75             &full_config_descriptor_size);
    76         if (rc != EOK) {
    77                 usb_log_error("Failed getting configuration descriptor: %s.\n",
    78                     str_error(rc));
    79                 free(full_config_descriptor);
    80                 return NULL;
    81         }
    82 
    83         if (full_config_descriptor_size != config_descriptor.total_length) {
    84                 usb_log_error("Failed getting full configuration descriptor.\n");
    85                 free(full_config_descriptor);
    86                 return NULL;
    87         }
    88 
    89         if (size != NULL) {
    90                 *size = full_config_descriptor_size;
    91         }
    92 
    93         return full_config_descriptor;
    94 }
    95 
    9644/** Find starting indexes of all interface descriptors in a configuration.
    9745 *
     
    178126
    179127        size_t config_descriptor_size;
    180         uint8_t *config_descriptor_raw = get_configuration_descriptor(dev, 0,
    181             &config_descriptor_size);
    182         if (config_descriptor_raw == NULL) {
     128        uint8_t *config_descriptor_raw = NULL;
     129        rc = usb_request_get_full_configuration_descriptor_alloc(
     130            &dev->ctrl_pipe, 0,
     131            (void **) &config_descriptor_raw, &config_descriptor_size);
     132        if (rc != EOK) {
     133                usb_log_error("Failed getting full config descriptor: %s.\n",
     134                    str_error(rc));
    183135                return false;
    184136        }
     
    207159        }
    208160
     161        /* Select the first configuration */
     162        rc = usb_request_set_configuration(&dev->ctrl_pipe,
     163            config_descriptor->configuration_number);
     164        if (rc != EOK) {
     165                usb_log_error("Failed to set device configuration: %s.\n",
     166                    str_error(rc));
     167                free(config_descriptor_raw);
     168                free(interface_descriptors);
     169                return false;
     170        }
     171
     172
     173        /* Create control function */
    209174        ddf_fun_t *ctl_fun = ddf_fun_create(dev->dev, fun_exposed, "ctl");
    210175        if (ctl_fun == NULL) {
     
    223188        }
    224189
     190        /* Spawn interface children */
    225191        size_t i;
    226192        for (i = 0; i < interface_descriptors_count; i++) {
  • uspace/drv/usbmid/main.c

    r60a228f r9d9ffdd  
    4444#include "usbmid.h"
    4545
     46/** Callback when new MID device is attached to the host.
     47 *
     48 * @param gen_dev Generic DDF device representing the new device.
     49 * @return Error code.
     50 */
    4651static int usbmid_add_device(ddf_dev_t *gen_dev)
    4752{
     
    8691}
    8792
     93/** USB MID driver ops. */
    8894static driver_ops_t mid_driver_ops = {
    8995        .add_device = usbmid_add_device,
    9096};
    9197
     98/** USB MID driver. */
    9299static driver_t mid_driver = {
    93100        .name = NAME,
  • uspace/drv/usbmid/usbmid.c

    r60a228f r9d9ffdd  
    6767}
    6868
     69/** DDF interface of the child - interface function. */
    6970static usb_iface_t child_usb_iface = {
    7071        .get_hc_handle = usb_iface_get_hc_handle_hub_child_impl,
     
    7374};
    7475
    75 
     76/** Operations for children - interface functions. */
    7677static ddf_dev_ops_t child_device_ops = {
    7778        .interfaces[USB_DEV_IFACE] = &child_usb_iface
    7879};
    7980
     81/** Operations of the device itself. */
    8082static ddf_dev_ops_t mid_device_ops = {
    8183        .interfaces[USB_DEV_IFACE] = &usb_iface_hub_impl
     
    123125/** Create new interface for USB MID device.
    124126 *
    125  * @param dev Backing generic DDF child device (representing interface).
     127 * @param fun Backing generic DDF device function (representing interface).
    126128 * @param iface_no Interface number.
    127129 * @return New interface.
  • uspace/drv/usbmid/usbmid.h

    r60a228f r9d9ffdd  
    4444#define NAME "usbmid"
    4545
     46/** USB MID device container. */
    4647typedef struct {
    4748        /** Device container. */
     
    5455} usbmid_device_t;
    5556
     57
     58/** Container for single interface in a MID device. */
    5659typedef struct {
    5760        /** Function container. */
  • uspace/drv/usbmouse/main.c

    r60a228f r9d9ffdd  
    11/*
    2  * Copyright (c) 2011 Matus Dekanek
     2 * Copyright (c) 2011 Vojtech Horky
    33 * All rights reserved.
    44 *
     
    2727 */
    2828
    29 #ifndef USBMEM_H
    30 #define USBMEM_H
    31 
    32 
    33 // group should be changed - this is not usb specific
    34 /** @addtogroup usb
     29/** @addtogroup drvusbmouse
    3530 * @{
    3631 */
    37 /** @file definitions of memory management with address translation, used mostly in usb stack
     32/**
     33 * @file
     34 * Main routines of USB boot protocol mouse driver.
     35 */
     36#include "mouse.h"
     37#include <usb/debug.h>
     38#include <errno.h>
     39#include <str_error.h>
     40
     41/** Callback when new mouse device is attached and recognised by DDF.
    3842 *
    39  * USB HCD needs traslation between physical and virtual addresses. These
    40  * functions implement such functionality. For each allocated virtual address
    41  * the memory manager gets also it`s physical translation and remembers it.
    42  * Addresses allocated byt this manager can be therefore translated from and to
    43  * physical addresses.
    44  * Typical use:
    45  * void * address = mman_malloc(some_size);
    46  * void * physical_address = mman_getPA(address);
    47  * void * the_same_address = mman_getVA(physical_address);
    48  * void * null_address = mman_getPA(non_existing_address);
    49  * mman_free(address);
    50  * // physical_address, adress and the_same_address are no longer valid here
    51  *
    52  *
    53  * @note Addresses allocated by this memory manager should be as well
    54  * deallocated byt it.
    55  *
     43 * @param dev Representation of a generic DDF device.
     44 * @return Error code.
    5645 */
     46static int usbmouse_add_device(ddf_dev_t *dev)
     47{
     48        int rc = usb_mouse_create(dev);
     49        if (rc != EOK) {
     50                usb_log_error("Failed to initialize device driver: %s.\n",
     51                    str_error(rc));
     52                return rc;
     53        }
    5754
    58 #include <sys/types.h>
     55        fid_t poll_fibril = fibril_create(usb_mouse_polling_fibril, dev);
     56        if (poll_fibril == 0) {
     57                usb_log_error("Failed to initialize polling fibril.\n");
     58                /* FIXME: free allocated resources. */
     59                return ENOMEM;
     60        }
    5961
    60 extern void * mman_malloc(
    61     size_t size,
    62     size_t alignment,
    63     unsigned long max_physical_address);
     62        fibril_add_ready(poll_fibril);
    6463
    65 extern void * mman_getVA(void * addr);
     64        usb_log_info("controlling new mouse (handle %llu).\n",
     65            dev->handle);
    6666
    67 extern void * mman_getPA(void * addr);
     67        return EOK;
     68}
    6869
    69 extern void mman_free(void * addr);
     70/** USB mouse driver ops. */
     71static driver_ops_t mouse_driver_ops = {
     72        .add_device = usbmouse_add_device,
     73};
    7074
     75/** USB mouse driver. */
     76static driver_t mouse_driver = {
     77        .name = NAME,
     78        .driver_ops = &mouse_driver_ops
     79};
    7180
     81int main(int argc, char *argv[])
     82{
     83        usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
    7284
     85        return ddf_driver_main(&mouse_driver);
     86}
    7387
    74 
    75 
    76 /** @}
     88/**
     89 * @}
    7790 */
    78 
    79 
    80 #endif  /* USBMEM_H */
    81 
  • uspace/drv/vhc/conndev.c

    r60a228f r9d9ffdd  
    110110/** Callback for DDF when client disconnects.
    111111 *
    112  * @param d Device the client was connected to.
     112 * @param fun Device function the client was connected to.
    113113 */
    114114void on_client_close(ddf_fun_t *fun)
Note: See TracChangeset for help on using the changeset viewer.