Changes in uspace/app/mkbd/main.c [fa8d346:e8f826b] in mainline


Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/mkbd/main.c

    rfa8d346 re8f826b  
    4545#include <devmap.h>
    4646#include <usb/dev/hub.h>
    47 #include <usb/host.h>
    48 #include <usb/driver.h>
    49 #include <usb/hid/iface.h>
     47#include <usb/hc.h>
    5048#include <usb/dev/pipes.h>
    51 #include <async.h>
    52 #include <usb/hid/usages/core.h>
    53 #include <usb/hid/hidparser.h>
    54 #include <usb/hid/hiddescriptor.h>
    55 #include <usb/hid/usages/consumer.h>
    56 #include <assert.h>
    5749
    5850#define NAME "mkbd"
     
    6052static int dev_phone = -1;
    6153
    62 static int initialize_report_parser(int dev_phone, usb_hid_report_t **report)
    63 {
    64         *report = (usb_hid_report_t *)malloc(sizeof(usb_hid_report_t));
    65         if (*report == NULL) {
     54//static void print_found_hc(size_t class_index, const char *path)
     55//{
     56//      // printf(NAME ": host controller %zu is `%s'.\n", class_index, path);
     57//      printf("Bus %02zu: %s\n", class_index, path);
     58//}
     59//static void print_found_dev(usb_address_t addr, const char *path)
     60//{
     61//      // printf(NAME ":     device with address %d is `%s'.\n", addr, path);
     62//      printf("  Device %02d: %s\n", addr, path);
     63//}
     64
     65//static void print_hc_devices(devman_handle_t hc_handle)
     66//{
     67//      int rc;
     68//      usb_hc_connection_t conn;
     69
     70//      usb_hc_connection_initialize(&conn, hc_handle);
     71//      rc = usb_hc_connection_open(&conn);
     72//      if (rc != EOK) {
     73//              printf(NAME ": failed to connect to HC: %s.\n",
     74//                  str_error(rc));
     75//              return;
     76//      }
     77//      usb_address_t addr;
     78//      for (addr = 1; addr < 5; addr++) {
     79//              devman_handle_t dev_handle;
     80//              rc = usb_hc_get_handle_by_address(&conn, addr, &dev_handle);
     81//              if (rc != EOK) {
     82//                      continue;
     83//              }
     84//              char path[MAX_PATH_LENGTH];
     85//              rc = devman_get_device_path(dev_handle, path, MAX_PATH_LENGTH);
     86//              if (rc != EOK) {
     87//                      continue;
     88//              }
     89//              print_found_dev(addr, path);
     90//      }
     91//      usb_hc_connection_close(&conn);
     92//}
     93
     94static bool try_parse_class_and_address(const char *path,
     95    devman_handle_t *out_hc_handle, usb_address_t *out_device_address)
     96{
     97        size_t class_index;
     98        size_t address;
     99        int rc;
     100        char *ptr;
     101
     102        rc = str_size_t(path, &ptr, 10, false, &class_index);
     103        if (rc != EOK) {
     104                return false;
     105        }
     106        if ((*ptr == ':') || (*ptr == '.')) {
     107                ptr++;
     108        } else {
     109                return false;
     110        }
     111        rc = str_size_t(ptr, NULL, 10, true, &address);
     112        if (rc != EOK) {
     113                return false;
     114        }
     115        rc = usb_ddf_get_hc_handle_by_class(class_index, out_hc_handle);
     116        if (rc != EOK) {
     117                return false;
     118        }
     119        if (out_device_address != NULL) {
     120                *out_device_address = (usb_address_t) address;
     121        }
     122        return true;
     123}
     124
     125static bool resolve_hc_handle_and_dev_addr(const char *devpath,
     126    devman_handle_t *out_hc_handle, usb_address_t *out_device_address)
     127{
     128        int rc;
     129
     130        /* Hack for QEMU to save-up on typing ;-). */
     131        if (str_cmp(devpath, "qemu") == 0) {
     132                devpath = "/hw/pci0/00:01.2/uhci-rh/usb00_a1";
     133        }
     134
     135        /* Hack for virtual keyboard. */
     136        if (str_cmp(devpath, "virt") == 0) {
     137                devpath = "/virt/usbhc/usb00_a1/usb00_a2";
     138        }
     139
     140        if (try_parse_class_and_address(devpath,
     141            out_hc_handle, out_device_address)) {
     142                return true;
     143        }
     144
     145        char *path = str_dup(devpath);
     146        if (path == NULL) {
    66147                return ENOMEM;
    67148        }
    68        
    69         int rc = usb_hid_report_init(*report);
    70         if (rc != EOK) {
    71                 usb_hid_free_report(*report);
    72                 *report = NULL;
    73                 printf("usb_hid_report_init() failed.\n");
    74                 return rc;
    75         }
    76        
    77         // get the report descriptor length from the device
    78         size_t report_desc_size;
    79         rc = usbhid_dev_get_report_descriptor_length(
    80             dev_phone, &report_desc_size);
    81         if (rc != EOK) {
    82                 usb_hid_free_report(*report);
    83                 *report = NULL;
    84                 printf("usbhid_dev_get_report_descriptor_length() failed.\n");
    85                 return rc;
    86         }
    87        
    88         if (report_desc_size == 0) {
    89                 usb_hid_free_report(*report);
    90                 *report = NULL;
    91                 printf("usbhid_dev_get_report_descriptor_length() returned 0.\n");
    92                 return EINVAL;  // TODO: other error code?
    93         }
    94        
    95         uint8_t *desc = (uint8_t *)malloc(report_desc_size);
    96         if (desc == NULL) {
    97                 usb_hid_free_report(*report);
    98                 *report = NULL;
    99                 return ENOMEM;
    100         }
    101        
    102         // get the report descriptor from the device
    103         size_t actual_size;
    104         rc = usbhid_dev_get_report_descriptor(dev_phone, desc, report_desc_size,
    105             &actual_size);
    106         if (rc != EOK) {
    107                 usb_hid_free_report(*report);
    108                 *report = NULL;
    109                 free(desc);
    110                 printf("usbhid_dev_get_report_descriptor() failed.\n");
    111                 return rc;
    112         }
    113        
    114         if (actual_size != report_desc_size) {
    115                 usb_hid_free_report(*report);
    116                 *report = NULL;
    117                 free(desc);
    118                 printf("usbhid_dev_get_report_descriptor() returned wrong size:"
    119                     " %zu, expected: %zu.\n", actual_size, report_desc_size);
    120                 return EINVAL;  // TODO: other error code?
    121         }
    122        
    123         // initialize the report parser
    124        
    125         rc = usb_hid_parse_report_descriptor(*report, desc, report_desc_size);
    126         free(desc);
    127        
    128         if (rc != EOK) {
    129                 free(desc);
    130                 printf("usb_hid_parse_report_descriptor() failed.\n");
    131                 return rc;
    132         }
    133        
    134         return EOK;
    135 }
    136 
    137 static void print_key(uint8_t *buffer, size_t size, usb_hid_report_t *report)
    138 {
    139         assert(buffer != NULL);
    140         assert(report != NULL);
    141        
    142         uint8_t report_id;
    143         usb_hid_parse_report(report, buffer, size, &report_id);
    144        
    145         usb_hid_report_path_t *path = usb_hid_report_path();
    146         if (path == NULL) {
    147                 return;
    148         }
    149        
    150         usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_CONSUMER, 0);
    151        
    152         usb_hid_report_path_set_report_id(path, report_id);
    153 
    154         usb_hid_report_field_t *field = usb_hid_report_get_sibling(
    155             report, NULL, path, USB_HID_PATH_COMPARE_END
    156             | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    157             USB_HID_REPORT_TYPE_INPUT);
    158        
    159         while (field != NULL) {
    160                 if (field->value != 0) {
    161                         const char *key_str =
    162                             usbhid_multimedia_usage_to_str(field->usage);
    163                         printf("Pressed key: %s\n", key_str);
    164                 }
    165                
    166                 field = usb_hid_report_get_sibling(
    167                     report, field, path, USB_HID_PATH_COMPARE_END
    168                     | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    169                     USB_HID_REPORT_TYPE_INPUT);
    170         }
    171        
    172         usb_hid_report_path_free(path);
    173 }
    174 
    175 #define MAX_PATH_LENGTH 1024
     149
     150        devman_handle_t hc = 0;
     151        bool hc_found = false;
     152        usb_address_t addr = 0;
     153        bool addr_found = false;
     154
     155        /* Remove suffixes and hope that we will encounter device node. */
     156        while (str_length(path) > 0) {
     157                /* Get device handle first. */
     158                devman_handle_t dev_handle;
     159                rc = devman_device_get_handle(path, &dev_handle, 0);
     160                if (rc != EOK) {
     161                        free(path);
     162                        return false;
     163                }
     164
     165                /* Try to find its host controller. */
     166                if (!hc_found) {
     167                        rc = usb_hc_find(dev_handle, &hc);
     168                        if (rc == EOK) {
     169                                hc_found = true;
     170                        }
     171                }
     172                /* Try to get its address. */
     173                if (!addr_found) {
     174                        addr = usb_hc_get_address_by_handle(dev_handle);
     175                        if (addr >= 0) {
     176                                addr_found = true;
     177                        }
     178                }
     179
     180                /* Speed-up. */
     181                if (hc_found && addr_found) {
     182                        break;
     183                }
     184
     185                /* Remove the last suffix. */
     186                char *slash_pos = str_rchr(path, '/');
     187                if (slash_pos != NULL) {
     188                        *slash_pos = 0;
     189                }
     190        }
     191
     192        free(path);
     193
     194        if (hc_found && addr_found) {
     195                if (out_hc_handle != NULL) {
     196                        *out_hc_handle = hc;
     197                }
     198                if (out_device_address != NULL) {
     199                        *out_device_address = addr;
     200                }
     201                return true;
     202        } else {
     203                return false;
     204        }
     205}
    176206
    177207static void print_usage(char *app_name)
     
    179209#define _INDENT "      "
    180210
    181        printf(NAME ": Print out what multimedia keys were pressed.\n\n");
    182        printf("Usage: %s device\n", app_name);
    183        printf(_INDENT "The device is a devman path to the device.\n");
     211        printf(NAME ": Print out what multimedia keys were pressed.\n\n");
     212        printf("Usage: %s device\n", app_name);
     213        printf(_INDENT "The device is a devman path to the device.\n");
    184214
    185215#undef _OPTION
     
    195225        }
    196226       
    197         //char *devpath = argv[1];
    198         const char *devpath = "/hw/pci0/00:06.0/ohci-rh/usb00_a2/HID0/hid";
     227        char *devpath = argv[1];
     228
     229        /* The initialization is here only to make compiler happy. */
     230        devman_handle_t hc_handle = 0;
     231        usb_address_t dev_addr = 0;
     232        bool found = resolve_hc_handle_and_dev_addr(devpath,
     233            &hc_handle, &dev_addr);
     234        if (!found) {
     235                fprintf(stderr, NAME ": device `%s' not found "
     236                    "or not of USB kind. Exiting.\n", devpath);
     237                return -1;
     238        }
    199239       
    200240        int rc;
    201        
    202         devman_handle_t dev_handle = 0;
    203         rc = devman_device_get_handle(devpath, &dev_handle, 0);
    204         if (rc != EOK) {
    205                 printf("Failed to get handle from devman: %s.\n",
     241        usb_hc_connection_t conn;
     242
     243        usb_hc_connection_initialize(&conn, hc_handle);
     244        rc = usb_hc_connection_open(&conn);
     245        if (rc != EOK) {
     246                printf(NAME ": failed to connect to HC: %s.\n",
    206247                    str_error(rc));
    207                 return rc;
    208         }
     248                return -1;
     249        }
     250        usb_address_t addr = 0;
     251
     252        devman_handle_t dev_handle;
     253        rc = usb_hc_get_handle_by_address(&conn, addr, &dev_handle);
     254        if (rc != EOK) {
     255                printf(NAME ": failed getting handle to the device: %s.\n",
     256                       str_error(rc));
     257                return -1;
     258        }
     259
     260        usb_hc_connection_close(&conn);
    209261       
    210262        rc = devman_device_connect(dev_handle, 0);
    211263        if (rc < 0) {
    212                 printf(NAME ": failed to connect to the device (handle %"
    213                        PRIun "): %s.\n", dev_handle, str_error(rc));
    214                 return rc;
     264                printf(NAME ": failed to connect to the device: %s.\n",
     265                       str_error(rc));
     266                return -1;
    215267        }
    216268       
     
    218270        printf("Got phone to the device: %d\n", dev_phone);
    219271       
    220         char path[MAX_PATH_LENGTH];
    221         rc = devman_get_device_path(dev_handle, path, MAX_PATH_LENGTH);
    222         if (rc != EOK) {
    223                 return ENOMEM;
    224         }
    225        
    226         printf("Device path: %s\n", path);
    227        
    228        
    229         usb_hid_report_t *report = NULL;
    230         rc = initialize_report_parser(dev_phone, &report);
    231         if (rc != EOK) {
    232                 printf("Failed to initialize report parser: %s\n",
    233                     str_error(rc));
    234                 return rc;
    235         }
    236        
    237         assert(report != NULL);
    238        
    239         size_t size;
    240         rc = usbhid_dev_get_event_length(dev_phone, &size);
    241         if (rc != EOK) {
    242                 printf("Failed to get event length: %s.\n", str_error(rc));
    243                 return rc;
    244         }
    245        
    246         printf("Event length: %zu\n", size);
    247         uint8_t *event = (uint8_t *)malloc(size);
    248         if (event == NULL) {
    249                 // hangup phone?
    250                 return ENOMEM;
    251         }
    252        
    253         printf("Event length: %zu\n", size);
    254        
    255         size_t actual_size;
    256        
    257         while (1) {
    258                 // get event from the driver
    259                 printf("Getting event from the driver.\n");
    260                
    261                 /** @todo Try blocking call. */
    262                 rc = usbhid_dev_get_event(dev_phone, event, size, &actual_size,
    263                     0);
    264                 if (rc != EOK) {
    265                         // hangup phone?
    266                         printf("Error in getting event from the HID driver:"
    267                             "%s.\n", str_error(rc));
    268                         break;
    269                 }
    270                
    271                 printf("Got buffer: %p, size: %zu\n", event, actual_size);
    272                
    273                 print_key(event, size, report);
    274                
    275                 async_usleep(10000);
    276         }
     272       
     273//      size_t class_index = 0;
     274//      size_t failed_attempts = 0;
     275
     276//      while (failed_attempts < MAX_FAILED_ATTEMPTS) {
     277//              class_index++;
     278//              devman_handle_t hc_handle = 0;
     279//              int rc = usb_ddf_get_hc_handle_by_class(class_index, &hc_handle);
     280//              if (rc != EOK) {
     281//                      failed_attempts++;
     282//                      continue;
     283//              }
     284//              char path[MAX_PATH_LENGTH];
     285//              rc = devman_get_device_path(hc_handle, path, MAX_PATH_LENGTH);
     286//              if (rc != EOK) {
     287//                      continue;
     288//              }
     289//              print_found_hc(class_index, path);
     290//              print_hc_devices(hc_handle);
     291//      }
    277292       
    278293        return 0;
Note: See TracChangeset for help on using the changeset viewer.