Changeset 26d46d2 in mainline


Ignore:
Timestamp:
2011-04-10T22:33:27Z (13 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
1a46610, fd153d3
Parents:
c6fe469 (diff), c7bdfa7 (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:

Development branch changes

Location:
uspace
Files:
5 added
18 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/usbhid/Makefile

    rc6fe469 r26d46d2  
    4040        main.c \
    4141        usbhid.c \
     42        subdrivers.c \
    4243        kbd/conv.c \
    4344        kbd/kbddev.c \
    4445        kbd/kbdrepeat.c \
    4546        generic/hiddev.c \
     47        mouse/mousedev.c \
    4648        $(STOLEN_LAYOUT_SOURCES)
    4749
  • uspace/drv/usbhid/generic/hiddev.c

    rc6fe469 r26d46d2  
    3939
    4040#include "hiddev.h"
     41#include "usbhid.h"
    4142
    4243/*----------------------------------------------------------------------------*/
     
    5455/*----------------------------------------------------------------------------*/
    5556
    56 bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer,
    57      size_t buffer_size, void *arg)
     57bool usb_generic_hid_polling_callback(usb_hid_dev_t *hid_dev,
     58    uint8_t *buffer, size_t buffer_size)
    5859{
    59         usb_log_debug("usb_hid_polling_callback()\n");
     60        usb_log_debug("usb_hid_polling_callback(%p, %p, %zu)\n",
     61            hid_dev, buffer, buffer_size);
    6062        usb_debug_str_buffer(buffer, buffer_size, 0);
    6163        return true;
  • uspace/drv/usbhid/generic/hiddev.h

    rc6fe469 r26d46d2  
    3434 */
    3535
    36 #ifndef USB_HIDD_H_
    37 #define USB_HIDD_H_
     36#ifndef USB_HID_HIDDDEV_H_
     37#define USB_HID_HIDDDEV_H_
    3838
    3939#include <usb/devdrv.h>
     40
     41struct usb_hid_dev;
    4042
    4143usb_endpoint_description_t usb_hid_generic_poll_endpoint_description;
     
    4446const char *HID_GENERIC_CLASS_NAME;
    4547
    46 bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer,
    47      size_t buffer_size, void *arg);
     48bool usb_generic_hid_polling_callback(struct usb_hid_dev *hid_dev,
     49    uint8_t *buffer, size_t buffer_size);
    4850
    49 #endif // USB_HIDD_H_
     51#endif // USB_HID_HIDDDEV_H_
    5052
    5153/**
  • uspace/drv/usbhid/kbd/conv.h

    rc6fe469 r26d46d2  
    3434 */
    3535
    36 #ifndef USB_KBD_CONV_H_
    37 #define USB_KBD_CONV_H_
     36#ifndef USB_HID_CONV_H_
     37#define USB_HID_CONV_H_
    3838
    3939unsigned int usbhid_parse_scancode(int scancode);
    4040
    41 #endif /* USB_KBD_CONV_H_ */
     41#endif /* USB_HID_CONV_H_ */
    4242
    4343/**
  • uspace/drv/usbhid/kbd/kbddev.c

    rc6fe469 r26d46d2  
    238238 * @param icall Call data.
    239239 */
    240 void default_connection_handler(ddf_fun_t *fun,
     240static void default_connection_handler(ddf_fun_t *fun,
    241241    ipc_callid_t icallid, ipc_call_t *icall)
    242242{
     
    856856/*----------------------------------------------------------------------------*/
    857857
    858 bool usb_kbd_polling_callback(usb_device_t *dev, uint8_t *buffer,
    859      size_t buffer_size, void *arg)
    860 {
    861         if (dev == NULL || buffer == NULL || arg == NULL) {
     858bool usb_kbd_polling_callback(usb_hid_dev_t *hid_dev, uint8_t *buffer,
     859     size_t buffer_size)
     860{
     861        if (hid_dev == NULL || buffer == NULL) {
    862862                // do not continue polling (???)
    863863                return false;
    864864        }
    865        
    866         usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;
    867865       
    868866        // TODO: add return value from this function
     
    916914/*----------------------------------------------------------------------------*/
    917915
    918 void usb_kbd_deinit(struct usb_hid_dev_t *hid_dev)
     916void usb_kbd_deinit(usb_hid_dev_t *hid_dev)
    919917{
    920918        if (hid_dev == NULL) {
  • uspace/drv/usbhid/kbd/kbddev.h

    rc6fe469 r26d46d2  
    3434 */
    3535
    36 #ifndef USB_KBDDEV_H_
    37 #define USB_KBDDEV_H_
     36#ifndef USB_HID_KBDDEV_H_
     37#define USB_HID_KBDDEV_H_
    3838
    3939#include <stdint.h>
     
    4949#include "kbdrepeat.h"
    5050
    51 struct usb_hid_dev_t;
     51struct usb_hid_dev;
    5252
    5353/*----------------------------------------------------------------------------*/
     
    6565 */
    6666typedef struct usb_kbd_t {
    67         /** Structure holding generic USB device information. */
    68         //usbhid_dev_t *hid_dev;
    69         //usb_device_t *usb_dev;
    70        
    7167        /** Currently pressed keys (not translated to key codes). */
    7268        uint8_t *keys;
     
    9187        fibril_mutex_t *repeat_mtx;
    9288       
    93         /** Report descriptor. */
    94         //uint8_t *report_desc;
    95 
    96         /** Report descriptor size. */
    97         //size_t report_desc_size;
    98        
    9989        uint8_t *output_buffer;
    10090       
     
    10696       
    10797        int32_t *led_data;
    108 
    109         /** HID Report parser. */
    110         //usb_hid_report_parser_t *parser;
    11198       
    11299        /** State of the structure (for checking before use).
     
    121108/*----------------------------------------------------------------------------*/
    122109
    123 //enum {
    124 //      USB_KBD_POLL_EP_NO = 0,
    125 //      USB_HID_POLL_EP_NO = 1,
    126 //      USB_KBD_POLL_EP_COUNT = 2
    127 //};
    128 
    129 //usb_endpoint_description_t *usb_kbd_endpoints[USB_KBD_POLL_EP_COUNT + 1];
    130 
    131 //ddf_dev_ops_t keyboard_ops;
    132 
    133110usb_endpoint_description_t usb_hid_kbd_poll_endpoint_description;
    134111
     
    138115/*----------------------------------------------------------------------------*/
    139116
    140 //usb_kbd_t *usb_kbd_new(void);
     117int usb_kbd_init(struct usb_hid_dev *hid_dev);
    141118
    142 int usb_kbd_init(struct usb_hid_dev_t *hid_dev);
    143 
    144 bool usb_kbd_polling_callback(usb_device_t *dev, uint8_t *buffer,
    145      size_t buffer_size, void *arg);
    146 
    147 //void usb_kbd_polling_ended_callback(usb_device_t *dev, bool reason,
    148 //     void *arg);
     119bool usb_kbd_polling_callback(struct usb_hid_dev *hid_dev, uint8_t *buffer,
     120    size_t buffer_size);
    149121
    150122int usb_kbd_is_initialized(const usb_kbd_t *kbd_dev);
     
    154126void usb_kbd_free(usb_kbd_t **kbd_dev);
    155127
    156 void usb_kbd_push_ev(struct usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev,
     128void usb_kbd_push_ev(struct usb_hid_dev *hid_dev, usb_kbd_t *kbd_dev,
    157129    int type, unsigned int key);
    158130
     131void usb_kbd_deinit(struct usb_hid_dev *hid_dev);
    159132
    160 void usb_kbd_deinit(struct usb_hid_dev_t *hid_dev);
     133int usb_kbd_set_boot_protocol(struct usb_hid_dev *hid_dev);
    161134
    162 int usb_kbd_set_boot_protocol(struct usb_hid_dev_t *hid_dev);
    163 
    164 #endif /* USB_KBDDEV_H_ */
     135#endif /* USB_HID_KBDDEV_H_ */
    165136
    166137/**
  • uspace/drv/usbhid/kbd/kbdrepeat.h

    rc6fe469 r26d46d2  
    3434 */
    3535
    36 #ifndef USB_KBDREPEAT_H_
    37 #define USB_KBDREPEAT_H_
     36#ifndef USB_HID_KBDREPEAT_H_
     37#define USB_HID_KBDREPEAT_H_
    3838
    3939struct usb_kbd_t;
     
    6262void usb_kbd_repeat_stop(struct usb_kbd_t *kbd, unsigned int key);
    6363
    64 #endif /* USB_KBDREPEAT_H_ */
     64#endif /* USB_HID_KBDREPEAT_H_ */
    6565
    6666/**
  • uspace/drv/usbhid/layout.h

    rc6fe469 r26d46d2  
    3636 */
    3737
    38 #ifndef USB_KBD_LAYOUT_H_
    39 #define USB_KBD_LAYOUT_H_
     38#ifndef USB_HID_LAYOUT_H_
     39#define USB_HID_LAYOUT_H_
    4040
    4141#include <sys/types.h>
  • uspace/drv/usbhid/main.c

    rc6fe469 r26d46d2  
    9898        /* Create the function exposed under /dev/devices. */
    9999        ddf_fun_t *hid_fun = ddf_fun_create(dev->ddf_dev, fun_exposed,
    100             usb_hid_get_function_name(hid_dev->device_type));
     100            usb_hid_get_function_name(hid_dev));
    101101        if (hid_fun == NULL) {
    102102                usb_log_error("Could not create DDF function node.\n");
     
    122122        }
    123123       
    124         rc = ddf_fun_add_to_class(hid_fun,
    125             usb_hid_get_class_name(hid_dev->device_type));
     124        rc = ddf_fun_add_to_class(hid_fun, usb_hid_get_class_name(hid_dev));
    126125        if (rc != EOK) {
    127126                usb_log_error(
     
    142141           hid_dev->poll_pipe_index,
    143142           /* Callback when data arrives. */
    144            hid_dev->poll_callback,
     143           usb_hid_polling_callback,
    145144           /* How much data to request. */
    146145           dev->pipes[hid_dev->poll_pipe_index].pipe->max_packet_size,
  • uspace/drv/usbhid/usbhid.c

    rc6fe469 r26d46d2  
    4242#include <usb/classes/hidreq.h>
    4343#include <errno.h>
     44#include <str_error.h>
    4445
    4546#include "usbhid.h"
     
    4748#include "kbd/kbddev.h"
    4849#include "generic/hiddev.h"
    49 
    50 /*----------------------------------------------------------------------------*/
    51 
    52 /** Mouse polling endpoint description for boot protocol class. */
    53 static usb_endpoint_description_t usb_hid_mouse_poll_endpoint_description = {
    54         .transfer_type = USB_TRANSFER_INTERRUPT,
    55         .direction = USB_DIRECTION_IN,
    56         .interface_class = USB_CLASS_HID,
    57         .interface_subclass = USB_HID_SUBCLASS_BOOT,
    58         .interface_protocol = USB_HID_PROTOCOL_MOUSE,
    59         .flags = 0
    60 };
     50#include "mouse/mousedev.h"
     51#include "subdrivers.h"
     52
     53/*----------------------------------------------------------------------------*/
    6154
    6255/* Array of endpoints expected on the device, NULL terminated. */
     
    6861};
    6962
    70 static const char *HID_MOUSE_FUN_NAME = "mouse";
    71 static const char *HID_MOUSE_CLASS_NAME = "mouse";
     63static const int USB_HID_MAX_SUBDRIVERS = 10;
     64
     65/*----------------------------------------------------------------------------*/
     66
     67static int usb_hid_set_boot_kbd_subdriver(usb_hid_dev_t *hid_dev)
     68{
     69        assert(hid_dev->subdriver_count == 0);
     70       
     71        hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(
     72            sizeof(usb_hid_subdriver_t));
     73        if (hid_dev->subdrivers == NULL) {
     74                return ENOMEM;
     75        }
     76       
     77        // set the init callback
     78        hid_dev->subdrivers[0].init = usb_kbd_init;
     79       
     80        // set the polling callback
     81        hid_dev->subdrivers[0].poll = usb_kbd_polling_callback;
     82       
     83        // set the polling ended callback
     84        hid_dev->subdrivers[0].poll_end = NULL;
     85       
     86        // set the deinit callback
     87        hid_dev->subdrivers[0].deinit = usb_kbd_deinit;
     88       
     89        // set subdriver count
     90        hid_dev->subdriver_count = 1;
     91       
     92        return EOK;
     93}
     94
     95/*----------------------------------------------------------------------------*/
     96
     97static int usb_hid_set_boot_mouse_subdriver(usb_hid_dev_t *hid_dev)
     98{
     99        assert(hid_dev->subdriver_count == 0);
     100       
     101        hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(
     102            sizeof(usb_hid_subdriver_t));
     103        if (hid_dev->subdrivers == NULL) {
     104                return ENOMEM;
     105        }
     106       
     107        // set the init callback
     108        hid_dev->subdrivers[0].init = usb_mouse_init;
     109       
     110        // set the polling callback
     111        hid_dev->subdrivers[0].poll = usb_mouse_polling_callback;
     112       
     113        // set the polling ended callback
     114        hid_dev->subdrivers[0].poll_end = NULL;
     115       
     116        // set the deinit callback
     117        hid_dev->subdrivers[0].deinit = usb_mouse_deinit;
     118       
     119        // set subdriver count
     120        hid_dev->subdriver_count = 1;
     121       
     122        return EOK;
     123}
     124
     125/*----------------------------------------------------------------------------*/
     126
     127static int usb_hid_set_generic_hid_subdriver(usb_hid_dev_t *hid_dev)
     128{
     129        assert(hid_dev->subdriver_count == 0);
     130       
     131        hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(
     132            sizeof(usb_hid_subdriver_t));
     133        if (hid_dev->subdrivers == NULL) {
     134                return ENOMEM;
     135        }
     136       
     137        // set the init callback
     138        hid_dev->subdrivers[0].init = NULL;
     139       
     140        // set the polling callback
     141        hid_dev->subdrivers[0].poll = usb_generic_hid_polling_callback;
     142       
     143        // set the polling ended callback
     144        hid_dev->subdrivers[0].poll_end = NULL;
     145       
     146        // set the deinit callback
     147        hid_dev->subdrivers[0].deinit = NULL;
     148       
     149        // set subdriver count
     150        hid_dev->subdriver_count = 1;
     151       
     152        return EOK;
     153}
     154
     155/*----------------------------------------------------------------------------*/
     156
     157static bool usb_hid_ids_match(usb_hid_dev_t *hid_dev,
     158    const usb_hid_subdriver_mapping_t *mapping)
     159{
     160        return false;
     161}
     162
     163/*----------------------------------------------------------------------------*/
     164
     165static bool usb_hid_path_matches(usb_hid_dev_t *hid_dev,
     166    const usb_hid_subdriver_usage_t *path, int path_size, int compare)
     167{
     168        assert(hid_dev != NULL);
     169        assert(path != NULL);
     170       
     171        usb_hid_report_path_t *usage_path = usb_hid_report_path();
     172        if (usage_path == NULL) {
     173                usb_log_debug("Failed to create usage path.\n");
     174                return false;
     175        }
     176        int i;
     177        for (i = 0; i < path_size; ++i) {
     178                if (usb_hid_report_path_append_item(usage_path,
     179                    path[i].usage_page, path[i].usage) != EOK) {
     180                        usb_log_debug("Failed to append to usage path.\n");
     181                        usb_hid_report_path_free(usage_path);
     182                        return false;
     183                }
     184        }
     185       
     186        assert(hid_dev->parser != NULL);
     187       
     188        usb_log_debug("Compare flags: %d\n", compare);
     189        size_t size = usb_hid_report_input_length(hid_dev->parser, usage_path,
     190            compare);
     191        usb_log_debug("Size of the input report: %d\n", size);
     192       
     193        usb_hid_report_path_free(usage_path);
     194       
     195        return (size > 0);
     196}
     197
     198/*----------------------------------------------------------------------------*/
     199
     200static int usb_hid_save_subdrivers(usb_hid_dev_t *hid_dev,
     201    const usb_hid_subdriver_t **subdrivers, int count)
     202{
     203        int i;
     204       
     205        if (count <= 0) {
     206                hid_dev->subdriver_count = 0;
     207                hid_dev->subdrivers = NULL;
     208                return EOK;
     209        }
     210       
     211        hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(count *
     212            sizeof(usb_hid_subdriver_t));
     213        if (hid_dev->subdrivers == NULL) {
     214                return ENOMEM;
     215        }
     216       
     217        for (i = 0; i < count; ++i) {
     218                hid_dev->subdrivers[i].init = subdrivers[i]->init;
     219                hid_dev->subdrivers[i].deinit = subdrivers[i]->deinit;
     220                hid_dev->subdrivers[i].poll = subdrivers[i]->poll;
     221                hid_dev->subdrivers[i].poll_end = subdrivers[i]->poll_end;
     222        }
     223       
     224        hid_dev->subdriver_count = count;
     225       
     226        return EOK;
     227}
     228
     229/*----------------------------------------------------------------------------*/
     230
     231static int usb_hid_find_subdrivers(usb_hid_dev_t *hid_dev)
     232{
     233        const usb_hid_subdriver_t *subdrivers[USB_HID_MAX_SUBDRIVERS];
     234       
     235        int i = 0, count = 0;
     236        const usb_hid_subdriver_mapping_t *mapping = &usb_hid_subdrivers[i];
     237       
     238        while (count < USB_HID_MAX_SUBDRIVERS &&
     239            (mapping->usage_path != NULL
     240            || mapping->vendor_id != NULL
     241            || mapping->product_id != NULL)) {
     242                // check the vendor & product ID
     243                if (mapping->vendor_id != NULL && mapping->product_id == NULL) {
     244                        usb_log_warning("Missing Product ID for Vendor ID %s\n",
     245                            mapping->vendor_id);
     246                        return EINVAL;
     247                }
     248                if (mapping->product_id != NULL && mapping->vendor_id == NULL) {
     249                        usb_log_warning("Missing Vendor ID for Product ID %s\n",
     250                            mapping->product_id);
     251                        return EINVAL;
     252                }
     253               
     254                if (mapping->vendor_id != NULL) {
     255                        assert(mapping->product_id != NULL);
     256                        usb_log_debug("Comparing device against vendor ID %s"
     257                            " and product ID %s.\n", mapping->vendor_id,
     258                            mapping->product_id);
     259                        if (usb_hid_ids_match(hid_dev, mapping)) {
     260                                usb_log_debug("Matched.\n");
     261                                subdrivers[count++] = &mapping->subdriver;
     262                                // skip the checking of usage path
     263                                goto next;
     264                        }
     265                }
     266               
     267                if (mapping->usage_path != NULL) {
     268                        usb_log_debug("Comparing device against usage path.\n");
     269                        if (usb_hid_path_matches(hid_dev,
     270                            mapping->usage_path, mapping->path_size,
     271                            mapping->compare)) {
     272                                subdrivers[count++] = &mapping->subdriver;
     273                        } else {
     274                                usb_log_debug("Not matched.\n");
     275                        }
     276                }
     277        next:
     278                mapping = &usb_hid_subdrivers[++i];
     279        }
     280       
     281        // we have all subdrivers determined, save them into the hid device
     282        return usb_hid_save_subdrivers(hid_dev, subdrivers, count);
     283}
     284
     285/*----------------------------------------------------------------------------*/
     286
     287static int usb_hid_check_pipes(usb_hid_dev_t *hid_dev, usb_device_t *dev)
     288{
     289        int rc = EOK;
     290       
     291        if (dev->pipes[USB_HID_KBD_POLL_EP_NO].present) {
     292                usb_log_debug("Found keyboard endpoint.\n");
     293                // save the pipe index
     294                hid_dev->poll_pipe_index = USB_HID_KBD_POLL_EP_NO;
     295        } else if (dev->pipes[USB_HID_MOUSE_POLL_EP_NO].present) {
     296                usb_log_debug("Found mouse endpoint.\n");
     297                // save the pipe index
     298                hid_dev->poll_pipe_index = USB_HID_MOUSE_POLL_EP_NO;
     299        } else if (dev->pipes[USB_HID_GENERIC_POLL_EP_NO].present) {
     300                usb_log_debug("Found generic HID endpoint.\n");
     301                // save the pipe index
     302                hid_dev->poll_pipe_index = USB_HID_GENERIC_POLL_EP_NO;
     303        } else {
     304                usb_log_error("None of supported endpoints found - probably"
     305                    " not a supported device.\n");
     306                rc = ENOTSUP;
     307        }
     308       
     309        return rc;
     310}
    72311
    73312/*----------------------------------------------------------------------------*/
     
    91330        }
    92331       
     332        hid_dev->poll_pipe_index = -1;
     333       
    93334        return hid_dev;
    94335}
     
    96337/*----------------------------------------------------------------------------*/
    97338
    98 static bool usb_dummy_polling_callback(usb_device_t *dev, uint8_t *buffer,
    99      size_t buffer_size, void *arg)
    100 {
    101         usb_log_debug("Dummy polling callback.\n");
    102         return false;
    103 }
    104 
    105 /*----------------------------------------------------------------------------*/
    106 
    107 static int usb_hid_check_pipes(usb_hid_dev_t *hid_dev, usb_device_t *dev)
    108 {
    109         if (dev->pipes[USB_HID_KBD_POLL_EP_NO].present) {
    110                 usb_log_debug("Found keyboard endpoint.\n");
    111                
    112                 // save the pipe index and device type
    113                 hid_dev->poll_pipe_index = USB_HID_KBD_POLL_EP_NO;
    114                 hid_dev->device_type = USB_HID_PROTOCOL_KEYBOARD;
    115                
    116                 // set the polling callback
    117                 hid_dev->poll_callback = usb_kbd_polling_callback;
    118 
    119         } else if (dev->pipes[USB_HID_MOUSE_POLL_EP_NO].present) {
    120                 usb_log_debug("Found mouse endpoint.\n");
    121                
    122                 // save the pipe index and device type
    123                 hid_dev->poll_pipe_index = USB_HID_MOUSE_POLL_EP_NO;
    124                 hid_dev->device_type = USB_HID_PROTOCOL_MOUSE;
    125                
    126                 // set the polling callback
    127                 hid_dev->poll_callback = usb_dummy_polling_callback;
    128                
    129         } else if (dev->pipes[USB_HID_GENERIC_POLL_EP_NO].present) {
    130                 usb_log_debug("Found generic HID endpoint.\n");
    131                
    132                 // save the pipe index and device type
    133                 hid_dev->poll_pipe_index = USB_HID_GENERIC_POLL_EP_NO;
    134                 hid_dev->device_type = USB_HID_PROTOCOL_NONE;
    135                
    136                 // set the polling callback
    137                 hid_dev->poll_callback = usb_hid_polling_callback;
    138                
    139         } else {
    140                 usb_log_warning("None of supported endpoints found - probably"
    141                     " not a supported device.\n");
    142                 return ENOTSUP;
    143         }
    144        
    145         return EOK;
    146 }
    147 
    148 /*----------------------------------------------------------------------------*/
    149 
    150 static int usb_hid_init_parser(usb_hid_dev_t *hid_dev)
    151 {
    152         /* Initialize the report parser. */
    153         int rc = usb_hid_parser_init(hid_dev->parser);
    154         if (rc != EOK) {
    155                 usb_log_error("Failed to initialize report parser.\n");
    156                 return rc;
    157         }
    158        
    159         /* Get the report descriptor and parse it. */
    160         rc = usb_hid_process_report_descriptor(hid_dev->usb_dev,
    161             hid_dev->parser);
    162        
    163         if (rc != EOK) {
    164                 usb_log_warning("Could not process report descriptor.\n");
    165                
    166                 if (hid_dev->device_type == USB_HID_PROTOCOL_KEYBOARD) {
    167                         usb_log_warning("Falling back to boot protocol.\n");
    168                        
    169                         rc = usb_kbd_set_boot_protocol(hid_dev);
    170                        
    171                 } else if (hid_dev->device_type == USB_HID_PROTOCOL_MOUSE) {
    172                         usb_log_warning("No boot protocol for mouse yet.\n");
    173                         rc = ENOTSUP;
    174                 }
    175         }
    176        
    177         return rc;
    178 }
    179 
    180 /*----------------------------------------------------------------------------*/
    181 
    182339int usb_hid_init(usb_hid_dev_t *hid_dev, usb_device_t *dev)
    183340{
    184         int rc;
     341        int rc, i;
    185342       
    186343        usb_log_debug("Initializing HID structure...\n");
     
    203360        rc = usb_hid_check_pipes(hid_dev, dev);
    204361        if (rc != EOK) {
     362                usb_hid_free(&hid_dev);
    205363                return rc;
    206364        }
    207365       
    208         rc = usb_hid_init_parser(hid_dev);
     366        /* Initialize the report parser. */
     367        rc = usb_hid_parser_init(hid_dev->parser);
    209368        if (rc != EOK) {
    210                 usb_log_error("Failed to initialize HID parser.\n");
     369                usb_log_error("Failed to initialize report parser.\n");
     370                usb_hid_free(&hid_dev);
    211371                return rc;
    212372        }
    213373       
    214         switch (hid_dev->device_type) {
    215         case USB_HID_PROTOCOL_KEYBOARD:
    216                 // initialize the keyboard structure
    217                 rc = usb_kbd_init(hid_dev);
    218                 if (rc != EOK) {
    219                         usb_log_warning("Failed to initialize KBD structure."
    220                             "\n");
    221                 }
    222                 break;
    223         case USB_HID_PROTOCOL_MOUSE:
    224                 break;
    225         default:
    226 //              usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe,
    227 //                  hid_dev->usb_dev->interface_no, 0);
    228                 break;
     374        /* Get the report descriptor and parse it. */
     375        rc = usb_hid_process_report_descriptor(hid_dev->usb_dev,
     376            hid_dev->parser);
     377       
     378        bool fallback = false;
     379       
     380        if (rc == EOK) {
     381                // try to find subdrivers that may want to handle this device
     382                rc = usb_hid_find_subdrivers(hid_dev);
     383                if (rc != EOK || hid_dev->subdriver_count == 0) {
     384                        // try to fall back to the boot protocol if available
     385                        usb_log_info("No subdrivers found to handle this"
     386                            " device.\n");
     387                        fallback = true;
     388                }
     389        } else {
     390                usb_log_error("Failed to parse Report descriptor.\n");
     391                // try to fall back to the boot protocol if available
     392                fallback = true;
     393        }
     394       
     395        // TODO: remove the mouse hack
     396        if (hid_dev->poll_pipe_index == USB_HID_MOUSE_POLL_EP_NO ||
     397            fallback) {
     398                // fall back to boot protocol
     399                switch (hid_dev->poll_pipe_index) {
     400                case USB_HID_KBD_POLL_EP_NO:
     401                        usb_log_info("Falling back to kbd boot protocol.\n");
     402                        rc = usb_kbd_set_boot_protocol(hid_dev);
     403                        if (rc == EOK) {
     404                                rc = usb_hid_set_boot_kbd_subdriver(hid_dev);
     405                        }
     406                        break;
     407                case USB_HID_MOUSE_POLL_EP_NO:
     408                        usb_log_info("Falling back to mouse boot protocol.\n");
     409                        rc = usb_mouse_set_boot_protocol(hid_dev);
     410                        if (rc == EOK) {
     411                                rc = usb_hid_set_boot_mouse_subdriver(hid_dev);
     412                        }
     413                        break;
     414                default:
     415                        assert(hid_dev->poll_pipe_index
     416                            == USB_HID_GENERIC_POLL_EP_NO);
     417                       
     418                        /* TODO: this has no meaning if the report descriptor
     419                                 is not parsed */
     420                        usb_log_info("Falling back to generic HID driver.\n");
     421                        rc = usb_hid_set_generic_hid_subdriver(hid_dev);
     422                }
     423        }
     424       
     425        if (rc != EOK) {
     426                usb_log_error("No subdriver for handling this device could be"
     427                    " initialized: %s.\n", str_error(rc));
     428                usb_hid_free(&hid_dev);
     429        } else {
     430                bool ok = false;
     431               
     432                usb_log_debug("Subdriver count: %d\n",
     433                    hid_dev->subdriver_count);
     434               
     435                for (i = 0; i < hid_dev->subdriver_count; ++i) {
     436                        if (hid_dev->subdrivers[i].init != NULL) {
     437                                usb_log_debug("Initializing subdriver %d.\n",i);
     438                                rc = hid_dev->subdrivers[i].init(hid_dev);
     439                                if (rc != EOK) {
     440                                        usb_log_warning("Failed to initialize"
     441                                            " HID subdriver structure.\n");
     442                                } else {
     443                                        // at least one subdriver initialized
     444                                        ok = true;
     445                                }
     446                        } else {
     447                                ok = true;
     448                        }
     449                }
     450               
     451                rc = (ok) ? EOK : -1;   // what error to report
    229452        }
    230453       
    231454        return rc;
     455}
     456
     457/*----------------------------------------------------------------------------*/
     458
     459bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer,
     460    size_t buffer_size, void *arg)
     461{
     462        int i;
     463       
     464        if (dev == NULL || arg == NULL || buffer == NULL) {
     465                usb_log_error("Missing arguments to polling callback.\n");
     466                return false;
     467        }
     468       
     469        usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;
     470       
     471        bool cont = false;
     472       
     473        // continue if at least one of the subdrivers want to continue
     474        for (i = 0; i < hid_dev->subdriver_count; ++i) {
     475                if (hid_dev->subdrivers[i].poll != NULL
     476                    && hid_dev->subdrivers[i].poll(hid_dev, buffer,
     477                    buffer_size)) {
     478                        cont = true;
     479                }
     480        }
     481       
     482        return cont;
    232483}
    233484
     
    237488     void *arg)
    238489{
     490        int i;
     491       
    239492        if (dev == NULL || arg == NULL) {
    240493                return;
     
    243496        usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;
    244497       
     498        for (i = 0; i < hid_dev->subdriver_count; ++i) {
     499                if (hid_dev->subdrivers[i].poll_end != NULL) {
     500                        hid_dev->subdrivers[i].poll_end(hid_dev, reason);
     501                }
     502        }
     503       
    245504        usb_hid_free(&hid_dev);
    246505}
     
    248507/*----------------------------------------------------------------------------*/
    249508
    250 const char *usb_hid_get_function_name(usb_hid_iface_protocol_t device_type)
    251 {
    252         switch (device_type) {
    253         case USB_HID_PROTOCOL_KEYBOARD:
     509const char *usb_hid_get_function_name(const usb_hid_dev_t *hid_dev)
     510{
     511        switch (hid_dev->poll_pipe_index) {
     512        case USB_HID_KBD_POLL_EP_NO:
    254513                return HID_KBD_FUN_NAME;
    255514                break;
    256         case USB_HID_PROTOCOL_MOUSE:
     515        case USB_HID_MOUSE_POLL_EP_NO:
    257516                return HID_MOUSE_FUN_NAME;
    258517                break;
     
    264523/*----------------------------------------------------------------------------*/
    265524
    266 const char *usb_hid_get_class_name(usb_hid_iface_protocol_t device_type)
    267 {
    268         switch (device_type) {
    269         case USB_HID_PROTOCOL_KEYBOARD:
     525const char *usb_hid_get_class_name(const usb_hid_dev_t *hid_dev)
     526{
     527        // this means that only boot protocol keyboards will be connected
     528        // to the console; there is probably no better way to do this
     529       
     530        switch (hid_dev->poll_pipe_index) {
     531        case USB_HID_KBD_POLL_EP_NO:
    270532                return HID_KBD_CLASS_NAME;
    271533                break;
    272         case USB_HID_PROTOCOL_MOUSE:
     534        case USB_HID_MOUSE_POLL_EP_NO:
    273535                return HID_MOUSE_CLASS_NAME;
    274536                break;
     
    282544void usb_hid_free(usb_hid_dev_t **hid_dev)
    283545{
     546        int i;
     547       
    284548        if (hid_dev == NULL || *hid_dev == NULL) {
    285549                return;
    286550        }
    287551       
    288         switch ((*hid_dev)->device_type) {
    289         case USB_HID_PROTOCOL_KEYBOARD:
    290                 usb_kbd_deinit(*hid_dev);
    291                 break;
    292         case USB_HID_PROTOCOL_MOUSE:
    293                 break;
    294         default:
    295                 break;
     552        assert((*hid_dev)->subdrivers != NULL
     553            || (*hid_dev)->subdriver_count == 0);
     554       
     555        for (i = 0; i < (*hid_dev)->subdriver_count; ++i) {
     556                if ((*hid_dev)->subdrivers[i].deinit != NULL) {
     557                        (*hid_dev)->subdrivers[i].deinit(*hid_dev);
     558                }
     559        }
     560       
     561        // free the subdrivers info
     562        if ((*hid_dev)->subdrivers != NULL) {
     563                free((*hid_dev)->subdrivers);
    296564        }
    297565
  • uspace/drv/usbhid/usbhid.h

    rc6fe469 r26d46d2  
    3434 */
    3535
    36 #ifndef USB_USBHID_H_
    37 #define USB_USBHID_H_
     36#ifndef USB_HID_USBHID_H_
     37#define USB_HID_USBHID_H_
    3838
    3939#include <stdint.h>
     
    4545#include <usb/classes/hid.h>
    4646
     47struct usb_hid_dev;
     48
     49typedef int (*usb_hid_driver_init_t)(struct usb_hid_dev *);
     50typedef void (*usb_hid_driver_deinit_t)(struct usb_hid_dev *);
     51typedef bool (*usb_hid_driver_poll)(struct usb_hid_dev *, uint8_t *, size_t);
     52typedef int (*usb_hid_driver_poll_ended)(struct usb_hid_dev *, bool reason);
     53
     54// TODO: add function and class name??
     55typedef struct usb_hid_subdriver {     
     56        /** Function to be called when initializing HID device. */
     57        usb_hid_driver_init_t init;
     58        /** Function to be called when destroying the HID device structure. */
     59        usb_hid_driver_deinit_t deinit;
     60        /** Function to be called when data arrives from the device. */
     61        usb_hid_driver_poll poll;
     62        /** Function to be called when polling ends. */
     63        usb_hid_driver_poll_ended poll_end;
     64} usb_hid_subdriver_t;
     65
    4766/*----------------------------------------------------------------------------*/
    4867/**
    4968 * Structure for holding general HID device data.
    5069 */
    51 typedef struct usb_hid_dev_t {
     70typedef struct usb_hid_dev {
    5271        /** Structure holding generic USB device information. */
    5372        usb_device_t *usb_dev;
     
    5978        int poll_pipe_index;
    6079       
    61         /** Function to be called when data arrives from the device. */
    62         usb_polling_callback_t poll_callback;
     80        /** Subdrivers. */
     81        usb_hid_subdriver_t *subdrivers;
     82       
     83        /** Number of subdrivers. */
     84        int subdriver_count;
    6385       
    6486        /** Report descriptor. */
     
    7395        /** Arbitrary data (e.g. a special structure for handling keyboard). */
    7496        void *data;
    75        
    76         /** Type of the device (keyboard, mouse, generic HID device). */
    77         usb_hid_iface_protocol_t device_type;
    7897} usb_hid_dev_t;
    7998
     
    95114int usb_hid_init(usb_hid_dev_t *hid_dev, usb_device_t *dev);
    96115
     116bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer,
     117    size_t buffer_size, void *arg);
     118
    97119void usb_hid_polling_ended_callback(usb_device_t *dev, bool reason,
    98120     void *arg);
    99121
    100 const char *usb_hid_get_function_name(usb_hid_iface_protocol_t device_type);
     122const char *usb_hid_get_function_name(const usb_hid_dev_t *hid_dev);
    101123
    102 const char *usb_hid_get_class_name(usb_hid_iface_protocol_t device_type);
     124const char *usb_hid_get_class_name(const usb_hid_dev_t *hid_dev);
    103125
    104126void usb_hid_free(usb_hid_dev_t **hid_dev);
    105127
    106 #endif /* USB_USBHID_H_ */
     128#endif /* USB_HID_USBHID_H_ */
    107129
    108130/**
  • uspace/drv/usbhid/usbhid.ma

    rc6fe469 r26d46d2  
    11100 usb&interface&class=HID&subclass=0x01&protocol=0x01
    2 100 usb&interface&class=HID&subclass=0x01&protocol=0x02
     21000 usb&interface&class=HID&subclass=0x01&protocol=0x02
    33100 usb&interface&class=HID
  • uspace/lib/usb/Makefile

    rc6fe469 r26d46d2  
    3434SOURCES = \
    3535        src/addrkeep.c \
     36        src/altiface.c \
    3637        src/class.c \
    3738        src/ddfiface.c \
  • uspace/lib/usb/include/usb/devdrv.h

    rc6fe469 r26d46d2  
    174174    usb_endpoint_mapping_t **, size_t *);
    175175int usb_device_destroy_pipes(ddf_dev_t *, usb_endpoint_mapping_t *, size_t);
     176int usb_device_create(ddf_dev_t *, usb_endpoint_description_t **, usb_device_t **, const char **);
    176177
    177178size_t usb_interface_count_alternates(uint8_t *, size_t, uint8_t);
     179int usb_alternate_interfaces_create(uint8_t *, size_t, int,
     180    usb_alternate_interfaces_t **);
    178181
    179182#endif
  • uspace/lib/usb/include/usb/request.h

    rc6fe469 r26d46d2  
    5050/** USB endpoint status - endpoint is halted (stalled). */
    5151#define USB_ENDPOINT_STATUS_HALTED ((uint16_t)(1 << 0))
     52
     53/** USB feature selector - endpoint halt (stall). */
     54#define USB_FEATURE_SELECTOR_ENDPOINT_HALT (0)
     55
     56/** USB feature selector - device remote wake-up. */
     57#define USB_FEATURE_SELECTOR_REMOTE_WAKEUP (1)
    5258
    5359/** Standard device request. */
     
    135141    char **);
    136142
     143int usb_request_clear_endpoint_halt(usb_pipe_t *, uint16_t);
     144
    137145#endif
    138146/**
  • uspace/lib/usb/src/devdrv.c

    rc6fe469 r26d46d2  
    100100    usb_device_t *dev, int alternate_setting)
    101101{
     102        if (endpoints == NULL) {
     103                dev->pipes = NULL;
     104                dev->pipes_count = 0;
     105                return EOK;
     106        }
     107
    102108        usb_endpoint_mapping_t *pipes;
    103109        size_t pipes_count;
     
    109115
    110116        if (rc != EOK) {
    111                 usb_log_error(
    112                     "Failed to create endpoint pipes for `%s': %s.\n",
    113                     dev->ddf_dev->name, str_error(rc));
    114117                return rc;
    115118        }
     
    117120        dev->pipes = pipes;
    118121        dev->pipes_count = pipes_count;
    119 
    120         return EOK;
    121 }
    122 
    123 /** Initialize all endpoint pipes.
    124  *
    125  * @param drv The driver.
    126  * @param dev The device to be initialized.
    127  * @return Error code.
    128  */
    129 static int initialize_pipes(usb_device_t *dev)
    130 {
    131         int rc;
    132 
    133         rc = usb_device_connection_initialize_from_device(&dev->wire,
    134             dev->ddf_dev);
    135         if (rc != EOK) {
    136                 usb_log_error(
    137                     "Failed initializing connection on device `%s'. %s.\n",
    138                     dev->ddf_dev->name, str_error(rc));
    139                 return rc;
    140         }
    141 
    142         rc = usb_pipe_initialize_default_control(&dev->ctrl_pipe,
    143             &dev->wire);
    144         if (rc != EOK) {
    145                 usb_log_error("Failed to initialize default control pipe " \
    146                     "on device `%s': %s.\n",
    147                     dev->ddf_dev->name, str_error(rc));
    148                 return rc;
    149         }
    150 
    151         rc = usb_pipe_probe_default_control(&dev->ctrl_pipe);
    152         if (rc != EOK) {
    153                 usb_log_error(
    154                     "Probing default control pipe on device `%s' failed: %s.\n",
    155                     dev->ddf_dev->name, str_error(rc));
    156                 return rc;
    157         }
    158 
    159         /* Get our interface. */
    160         dev->interface_no = usb_device_get_assigned_interface(dev->ddf_dev);
    161 
    162         /*
    163          * We will do some querying of the device, it is worth to prepare
    164          * the long transfer.
    165          */
    166         rc = usb_pipe_start_long_transfer(&dev->ctrl_pipe);
    167         if (rc != EOK) {
    168                 usb_log_error("Failed to start transfer: %s.\n",
    169                     str_error(rc));
    170                 return rc;
    171         }
    172 
    173         /* Retrieve the descriptors. */
    174         rc = usb_device_retrieve_descriptors(&dev->ctrl_pipe,
    175             &dev->descriptors);
    176         if (rc != EOK) {
    177                 usb_log_error("Failed to retrieve standard device " \
    178                     "descriptors of %s: %s.\n",
    179                     dev->ddf_dev->name, str_error(rc));
    180                 return rc;
    181         }
    182 
    183 
    184         if (driver->endpoints != NULL) {
    185                 rc = initialize_other_pipes(driver->endpoints, dev, 0);
    186         }
    187 
    188         usb_pipe_end_long_transfer(&dev->ctrl_pipe);
    189 
    190         /* Rollback actions. */
    191         if (rc != EOK) {
    192                 if (dev->descriptors.configuration != NULL) {
    193                         free(dev->descriptors.configuration);
    194                 }
    195         }
    196 
    197         return rc;
    198 }
    199 
    200 /** Count number of alternate settings of a interface.
    201  *
    202  * @param config_descr Full configuration descriptor.
    203  * @param config_descr_size Size of @p config_descr in bytes.
    204  * @param interface_no Interface number.
    205  * @return Number of alternate interfaces for @p interface_no interface.
    206  */
    207 size_t usb_interface_count_alternates(uint8_t *config_descr,
    208     size_t config_descr_size, uint8_t interface_no)
    209 {
    210         assert(config_descr != NULL);
    211         assert(config_descr_size > 0);
    212 
    213         usb_dp_parser_t dp_parser = {
    214                 .nesting = usb_dp_standard_descriptor_nesting
    215         };
    216         usb_dp_parser_data_t dp_data = {
    217                 .data = config_descr,
    218                 .size = config_descr_size,
    219                 .arg = NULL
    220         };
    221 
    222         size_t alternate_count = 0;
    223 
    224         uint8_t *iface_ptr = usb_dp_get_nested_descriptor(&dp_parser,
    225             &dp_data, config_descr);
    226         while (iface_ptr != NULL) {
    227                 usb_standard_interface_descriptor_t *iface
    228                     = (usb_standard_interface_descriptor_t *) iface_ptr;
    229                 if (iface->descriptor_type == USB_DESCTYPE_INTERFACE) {
    230                         if (iface->interface_number == interface_no) {
    231                                 alternate_count++;
    232                         }
    233                 }
    234                 iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data,
    235                     config_descr, iface_ptr);
    236         }
    237 
    238         return alternate_count;
    239 }
    240 
    241 /** Initialize structures related to alternate interfaces.
    242  *
    243  * @param dev Device where alternate settings shall be initialized.
    244  * @return Error code.
    245  */
    246 static int initialize_alternate_interfaces(usb_device_t *dev)
    247 {
    248         if (dev->interface_no < 0) {
    249                 dev->alternate_interfaces = NULL;
    250                 return EOK;
    251         }
    252 
    253         usb_alternate_interfaces_t *alternates
    254             = malloc(sizeof(usb_alternate_interfaces_t));
    255 
    256         if (alternates == NULL) {
    257                 return ENOMEM;
    258         }
    259 
    260         alternates->alternative_count
    261             = usb_interface_count_alternates(dev->descriptors.configuration,
    262             dev->descriptors.configuration_size, dev->interface_no);
    263 
    264         if (alternates->alternative_count == 0) {
    265                 free(alternates);
    266                 return ENOENT;
    267         }
    268 
    269         alternates->alternatives = malloc(alternates->alternative_count
    270             * sizeof(usb_alternate_interface_descriptors_t));
    271         if (alternates->alternatives == NULL) {
    272                 free(alternates);
    273                 return ENOMEM;
    274         }
    275 
    276         alternates->current = 0;
    277 
    278         usb_dp_parser_t dp_parser = {
    279                 .nesting = usb_dp_standard_descriptor_nesting
    280         };
    281         usb_dp_parser_data_t dp_data = {
    282                 .data = dev->descriptors.configuration,
    283                 .size = dev->descriptors.configuration_size,
    284                 .arg = NULL
    285         };
    286 
    287         usb_alternate_interface_descriptors_t *cur_alt_iface
    288             = &alternates->alternatives[0];
    289 
    290         uint8_t *iface_ptr = usb_dp_get_nested_descriptor(&dp_parser,
    291             &dp_data, dp_data.data);
    292         while (iface_ptr != NULL) {
    293                 usb_standard_interface_descriptor_t *iface
    294                     = (usb_standard_interface_descriptor_t *) iface_ptr;
    295                 if ((iface->descriptor_type != USB_DESCTYPE_INTERFACE)
    296                     || (iface->interface_number != dev->interface_no)) {
    297                         iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser,
    298                             &dp_data,
    299                             dp_data.data, iface_ptr);
    300                         continue;
    301                 }
    302 
    303                 cur_alt_iface->interface = iface;
    304                 cur_alt_iface->nested_descriptors = iface_ptr + sizeof(*iface);
    305 
    306                 /* Find next interface to count size of nested descriptors. */
    307                 iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data,
    308                     dp_data.data, iface_ptr);
    309                 if (iface_ptr == NULL) {
    310                         uint8_t *next = dp_data.data + dp_data.size;
    311                         cur_alt_iface->nested_descriptors_size
    312                             = next - cur_alt_iface->nested_descriptors;
    313                 } else {
    314                         cur_alt_iface->nested_descriptors_size
    315                             = iface_ptr - cur_alt_iface->nested_descriptors;
    316                 }
    317 
    318                 cur_alt_iface++;
    319         }
    320 
    321         dev->alternate_interfaces = alternates;
    322122
    323123        return EOK;
     
    339139        int rc;
    340140
    341         usb_device_t *dev = malloc(sizeof(usb_device_t));
    342         if (dev == NULL) {
    343                 usb_log_error("Out of memory when adding device `%s'.\n",
    344                     gen_dev->name);
    345                 return ENOMEM;
    346         }
    347 
    348 
    349         dev->ddf_dev = gen_dev;
    350         dev->ddf_dev->driver_data = dev;
    351         dev->driver_data = NULL;
    352         dev->descriptors.configuration = NULL;
    353 
    354         dev->pipes_count = 0;
    355         dev->pipes = NULL;
    356 
    357         rc = initialize_pipes(dev);
    358         if (rc != EOK) {
    359                 free(dev);
    360                 return rc;
    361         }
    362 
    363         (void) initialize_alternate_interfaces(dev);
     141        usb_device_t *dev = NULL;
     142        const char *err_msg = NULL;
     143        rc = usb_device_create(gen_dev, driver->endpoints, &dev, &err_msg);
     144        if (rc != EOK) {
     145                usb_log_error("USB device `%s' creation failed (%s): %s.\n",
     146                    gen_dev->name, err_msg, str_error(rc));
     147                return rc;
     148        }
    364149
    365150        return driver->ops->add_device(dev);
     
    395180 * with usb_pipe_initialize_from_configuration().
    396181 *
     182 * @warning This is a wrapper function that does several operations that
     183 * can fail and that cannot be rollbacked easily. That means that a failure
     184 * during the SET_INTERFACE request would result in having a device with
     185 * no pipes at all (except the default control one). That is because the old
     186 * pipes needs to be unregistered at HC first and the new ones could not
     187 * be created.
     188 *
    397189 * @param dev USB device.
    398190 * @param alternate_setting Alternate setting to choose.
     
    409201        int rc;
    410202
    411         /* TODO: more transactional behavior. */
    412 
    413203        /* Destroy existing pipes. */
    414204        rc = destroy_current_pipes(dev);
     
    432222/** Retrieve basic descriptors from the device.
    433223 *
    434  * @param[in] ctrl_pipe Control pipe with opened session.
     224 * @param[in] ctrl_pipe Control endpoint pipe.
    435225 * @param[out] descriptors Where to store the descriptors.
    436226 * @return Error code.
     
    440230{
    441231        assert(descriptors != NULL);
    442         assert(usb_pipe_is_session_started(ctrl_pipe));
    443232
    444233        descriptors->configuration = NULL;
    445234
    446235        int rc;
     236
     237        /* It is worth to start a long transfer. */
     238        rc = usb_pipe_start_long_transfer(ctrl_pipe);
     239        if (rc != EOK) {
     240                return rc;
     241        }
    447242
    448243        /* Get the device descriptor. */
    449244        rc = usb_request_get_device_descriptor(ctrl_pipe, &descriptors->device);
    450245        if (rc != EOK) {
    451                 return rc;
     246                goto leave;
    452247        }
    453248
     
    456251            ctrl_pipe, 0, (void **) &descriptors->configuration,
    457252            &descriptors->configuration_size);
    458         if (rc != EOK) {
    459                 return rc;
    460         }
    461 
    462         return EOK;
     253
     254leave:
     255        usb_pipe_end_long_transfer(ctrl_pipe);
     256
     257        return rc;
    463258}
    464259
     
    641436}
    642437
     438/** Initialize control pipe in a device.
     439 *
     440 * @param dev USB device in question.
     441 * @param errmsg Where to store error context.
     442 * @return
     443 */
     444static int init_wire_and_ctrl_pipe(usb_device_t *dev, const char **errmsg)
     445{
     446        int rc;
     447
     448        rc = usb_device_connection_initialize_from_device(&dev->wire,
     449            dev->ddf_dev);
     450        if (rc != EOK) {
     451                *errmsg = "device connection initialization";
     452                return rc;
     453        }
     454
     455        rc = usb_pipe_initialize_default_control(&dev->ctrl_pipe,
     456            &dev->wire);
     457        if (rc != EOK) {
     458                *errmsg = "default control pipe initialization";
     459                return rc;
     460        }
     461
     462        return EOK;
     463}
     464
     465
     466/** Create new instance of USB device.
     467 *
     468 * @param[in] ddf_dev Generic DDF device backing the USB one.
     469 * @param[in] endpoints NULL terminated array of endpoints (NULL for none).
     470 * @param[out] dev_ptr Where to store pointer to the new device.
     471 * @param[out] errstr_ptr Where to store description of context
     472 *      (in case error occurs).
     473 * @return Error code.
     474 */
     475int usb_device_create(ddf_dev_t *ddf_dev,
     476    usb_endpoint_description_t **endpoints,
     477    usb_device_t **dev_ptr, const char **errstr_ptr)
     478{
     479        assert(dev_ptr != NULL);
     480        assert(ddf_dev != NULL);
     481
     482        int rc;
     483
     484        usb_device_t *dev = malloc(sizeof(usb_device_t));
     485        if (dev == NULL) {
     486                *errstr_ptr = "structure allocation";
     487                return ENOMEM;
     488        }
     489
     490        // FIXME: proper deallocation in case of errors
     491
     492        dev->ddf_dev = ddf_dev;
     493        dev->driver_data = NULL;
     494        dev->descriptors.configuration = NULL;
     495        dev->alternate_interfaces = NULL;
     496
     497        dev->pipes_count = 0;
     498        dev->pipes = NULL;
     499
     500        /* Initialize backing wire and control pipe. */
     501        rc = init_wire_and_ctrl_pipe(dev, errstr_ptr);
     502        if (rc != EOK) {
     503                return rc;
     504        }
     505
     506        /* Get our interface. */
     507        dev->interface_no = usb_device_get_assigned_interface(dev->ddf_dev);
     508
     509        /* Retrieve standard descriptors. */
     510        rc = usb_device_retrieve_descriptors(&dev->ctrl_pipe,
     511            &dev->descriptors);
     512        if (rc != EOK) {
     513                *errstr_ptr = "descriptor retrieval";
     514                return rc;
     515        }
     516
     517        /* Create alternate interfaces. */
     518        rc = usb_alternate_interfaces_create(dev->descriptors.configuration,
     519            dev->descriptors.configuration_size, dev->interface_no,
     520            &dev->alternate_interfaces);
     521        if (rc != EOK) {
     522                /* We will try to silently ignore this. */
     523                dev->alternate_interfaces = NULL;
     524        }
     525
     526        rc = initialize_other_pipes(endpoints, dev, 0);
     527        if (rc != EOK) {
     528                *errstr_ptr = "pipes initialization";
     529                return rc;
     530        }
     531
     532        *errstr_ptr = NULL;
     533        *dev_ptr = dev;
     534
     535        return EOK;
     536}
     537
    643538/**
    644539 * @}
  • uspace/lib/usb/src/hidparser.c

    rc6fe469 r26d46d2  
    900900        item->usage_page = usage_page;
    901901       
     902        usb_log_debug("Appending usage %d, usage page %d\n", usage, usage_page);
     903       
    902904        list_append (&usage_path->link, &item->link);
    903905        usage_path->depth++;
  • uspace/lib/usb/src/request.c

    rc6fe469 r26d46d2  
    871871}
    872872
     873/** Clear halt bit of an endpoint pipe (after pipe stall).
     874 *
     875 * @param pipe Control pipe.
     876 * @param ep_index Endpoint index (in native endianness).
     877 * @return Error code.
     878 */
     879int usb_request_clear_endpoint_halt(usb_pipe_t *pipe, uint16_t ep_index)
     880{
     881        return usb_request_clear_feature(pipe,
     882            USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_ENDPOINT,
     883            uint16_host2usb(USB_FEATURE_SELECTOR_ENDPOINT_HALT),
     884            uint16_host2usb(ep_index));
     885}
     886
    873887/**
    874888 * @}
Note: See TracChangeset for help on using the changeset viewer.