Changeset 3d4aa055 in mainline
- Timestamp:
- 2011-05-06T13:08:10Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 075c1eb, 3da17644
- Parents:
- a58dd620 (diff), 310c4df (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. - Files:
-
- 17 added
- 7 deleted
- 58 edited
- 6 moved
Legend:
- Unmodified
- Added
- Removed
-
.bzrignore
ra58dd620 r3d4aa055 70 70 ./uspace/app/virtusbkbd/vuk 71 71 ./uspace/app/virtusbhub/vuh 72 ./uspace/app/vuhid/vuh 72 73 ./uspace/app/virtusbhub/vhc_hub/* 73 74 ./uspace/app/websrv/websrv -
boot/Makefile.common
ra58dd620 r3d4aa055 144 144 $(USPACE_PATH)/app/usbinfo/usbinfo \ 145 145 $(USPACE_PATH)/app/virtusbkbd/vuk \ 146 $(USPACE_PATH)/app/v irtusbhub/vuh \146 $(USPACE_PATH)/app/vuhid/vuh \ 147 147 $(USPACE_PATH)/app/websrv/websrv 148 148 -
uspace/Makefile
ra58dd620 r3d4aa055 52 52 app/usbinfo \ 53 53 app/virtusbkbd \ 54 app/v irtusbhub\54 app/vuhid \ 55 55 app/netecho \ 56 56 app/nettest1 \ -
uspace/app/usbinfo/main.c
ra58dd620 r3d4aa055 55 55 if (str_cmp(devpath, "qemu") == 0) { 56 56 devpath = "/hw/pci0/00:01.2/uhci-rh/usb00_a1"; 57 } 58 59 /* Hack for virtual keyboard. */ 60 if (str_cmp(devpath, "virt") == 0) { 61 devpath = "/virt/usbhc/usb00_a1/usb00_a2"; 57 62 } 58 63 -
uspace/app/virtusbkbd/Makefile
ra58dd620 r3d4aa055 32 32 BINARY = vuk 33 33 34 LIBS = $(LIBUSB _PREFIX)/libusb.a $(LIBUSBVIRT_PREFIX)/libusbvirt.a34 LIBS = $(LIBUSBVIRT_PREFIX)/libusbvirt.a $(LIBUSB_PREFIX)/libusb.a 35 35 EXTRA_CFLAGS = -I$(LIBUSB_PREFIX)/include -I$(LIBUSBVIRT_PREFIX)/include -I$(LIBDRV_PREFIX)/include 36 36 -
uspace/app/virtusbkbd/stdreq.c
ra58dd620 r3d4aa055 39 39 #include "kbdconfig.h" 40 40 41 int stdreq_on_get_descriptor(struct usbvirt_device *dev, 42 usb_device_request_setup_packet_t *request, uint8_t *data) 41 int req_get_descriptor(usbvirt_device_t *device, 42 const usb_device_request_setup_packet_t *setup_packet, 43 uint8_t *data, size_t *act_size) 43 44 { 44 if ( request->value_high == USB_DESCTYPE_HID_REPORT) {45 if (setup_packet->value_high == USB_DESCTYPE_HID_REPORT) { 45 46 /* 46 47 * For simplicity, always return the same 47 48 * report descriptor. 48 49 */ 49 int rc = dev->control_transfer_reply(dev, 0, 50 usbvirt_control_reply_helper(setup_packet, 51 data, act_size, 50 52 report_descriptor, report_descriptor_size); 51 52 return rc;53 54 return EOK; 53 55 } 54 56 -
uspace/app/virtusbkbd/stdreq.h
ra58dd620 r3d4aa055 38 38 #include <usbvirt/device.h> 39 39 40 int stdreq_on_get_descriptor(usbvirt_device_t *, 41 usb_device_request_setup_packet_t *, uint8_t *); 40 int req_get_descriptor(usbvirt_device_t *device, 41 const usb_device_request_setup_packet_t *setup_packet, 42 uint8_t *data, size_t *act_size); 42 43 43 44 #endif -
uspace/app/virtusbkbd/virtusbkbd.c
ra58dd620 r3d4aa055 48 48 #include <usb/descriptor.h> 49 49 #include <usb/classes/hid.h> 50 #include <usb/debug.h> 50 51 #include <usbvirt/device.h> 51 #include <usbvirt/hub.h>52 52 53 53 #include "kbdconfig.h" … … 67 67 68 68 kb_status_t status; 69 70 static int on_incoming_data(struct usbvirt_device *dev,71 usb_endpoint_t endpoint, void *buffer, size_t size)72 {73 printf("%s: ignoring incomming data to endpoint %d\n", NAME, endpoint);74 75 return EOK;76 }77 78 69 79 70 /** Compares current and last status of pressed keys. … … 100 91 } 101 92 102 static int on_request_for_data(struct usbvirt_device *dev, 103 usb_endpoint_t endpoint, void *buffer, size_t size, size_t *actual_size) 93 static int on_request_for_data(usbvirt_device_t *dev, 94 usb_endpoint_t endpoint, usb_transfer_type_t transfer_type, 95 void *buffer, size_t size, size_t *actual_size) 104 96 { 105 97 static uint8_t last_data[2 + KB_MAX_KEYS_AT_ONCE]; … … 122 114 if (keypress_check_with_last_request(data, last_data, 123 115 2 + KB_MAX_KEYS_AT_ONCE)) { 124 *actual_size = 0; 125 return EOK; 116 return ENAK; 126 117 } 127 118 … … 131 122 } 132 123 133 static usbvirt_control_transfer_handler_t endpoint_zero_handlers[] = { 134 { 135 .request_type = USBVIRT_MAKE_CONTROL_REQUEST_TYPE( 136 USB_DIRECTION_IN, 137 USBVIRT_REQUEST_TYPE_STANDARD, 138 USBVIRT_REQUEST_RECIPIENT_DEVICE), 124 static usbvirt_control_request_handler_t endpoint_zero_handlers[] = { 125 { 126 .req_direction = USB_DIRECTION_IN, 127 .req_type = USB_REQUEST_TYPE_STANDARD, 128 .req_recipient = USB_REQUEST_RECIPIENT_INTERFACE, 139 129 .request = USB_DEVREQ_GET_DESCRIPTOR, 140 130 .name = "GetDescriptor", 141 .callback = stdreq_on_get_descriptor131 .callback = req_get_descriptor 142 132 }, 143 133 { 144 .request_type = USBVIRT_MAKE_CONTROL_REQUEST_TYPE( 145 USB_DIRECTION_IN, 146 USBVIRT_REQUEST_TYPE_CLASS, 147 USBVIRT_REQUEST_RECIPIENT_DEVICE), 148 .request = USB_DEVREQ_GET_DESCRIPTOR, 149 .name = "GetDescriptor", 150 .callback = stdreq_on_get_descriptor 151 }, 152 USBVIRT_CONTROL_TRANSFER_HANDLER_LAST 134 .callback = NULL 135 } 153 136 }; 154 137 … … 157 140 */ 158 141 static usbvirt_device_ops_t keyboard_ops = { 159 .control_transfer_handlers = endpoint_zero_handlers, 160 .on_data = on_incoming_data, 161 .on_data_request = on_request_for_data 142 .control = endpoint_zero_handlers, 143 .data_in[1] = on_request_for_data 162 144 }; 163 145 … … 197 179 .ops = &keyboard_ops, 198 180 .descriptors = &descriptors, 199 .lib_debug_level = 3,200 .lib_debug_enabled_tags = USBVIRT_DEBUGTAG_ALL,201 181 .name = "keyboard" 202 182 }; … … 262 242 263 243 264 int rc = usbvirt_ connect(&keyboard_dev);244 int rc = usbvirt_device_plug(&keyboard_dev, "/virt/usbhc/hc"); 265 245 if (rc != EOK) { 266 246 printf("%s: Unable to start communication with VHCD (%s).\n", … … 278 258 printf("%s: Terminating...\n", NAME); 279 259 280 usbvirt_disconnect(&keyboard_dev);260 //usbvirt_disconnect(&keyboard_dev); 281 261 282 262 return 0; -
uspace/app/vuhid/Makefile
ra58dd620 r3d4aa055 28 28 29 29 USPACE_PREFIX = ../.. 30 # acronym for virtual USB hu b30 # acronym for virtual USB human input device 31 31 # (it is really annoying to write long names) 32 32 BINARY = vuh 33 33 34 LIBS = $(LIBUSB_PREFIX)/libusb.a $(LIBUSBVIRT_PREFIX)/libusbvirt.a 35 EXTRA_CFLAGS = -DSTANDALONE_HUB \ 36 -DHUB_PORT_COUNT=10 \ 37 -I$(LIBUSB_PREFIX)/include -I$(LIBUSBVIRT_PREFIX)/include -I$(LIBDRV_PREFIX)/include 34 LIBS = \ 35 $(LIBUSBVIRT_PREFIX)/libusbvirt.a \ 36 $(LIBUSB_PREFIX)/libusb.a 37 EXTRA_CFLAGS = \ 38 -I$(LIBUSB_PREFIX)/include \ 39 -I$(LIBUSBVIRT_PREFIX)/include \ 40 -I$(LIBDRV_PREFIX)/include 41 42 43 SOURCES_INTERFACES = \ 44 hids/bootkbd.c 38 45 39 46 SOURCES = \ 40 47 main.c \ 41 $(STOLEN_VHC_SOURCES) 42 43 STOLEN_VHC_SOURCES = \ 44 vhc_hub/hub.c \ 45 vhc_hub/virthub.c \ 46 vhc_hub/virthubops.c 47 STOLEN_VHC_HEADERS = \ 48 vhc_hub/hub.h \ 49 vhc_hub/virthub.h 50 51 PRE_DEPEND = $(STOLEN_VHC_SOURCES) $(STOLEN_VHC_HEADERS) 52 53 EXTRA_CLEAN = $(STOLEN_VHC_SOURCES) $(STOLEN_VHC_HEADERS) 54 55 HUB_IN_VHC = $(USPACE_PREFIX)/drv/vhc/hub 48 device.c \ 49 ifaces.c \ 50 stdreq.c \ 51 $(SOURCES_INTERFACES) 52 56 53 57 54 include $(USPACE_PREFIX)/Makefile.common 58 59 vhc_hub/%.h: $(HUB_IN_VHC)/%.h60 ln -sfn ../$(HUB_IN_VHC)/$*.h $@61 vhc_hub/%.c: $(HUB_IN_VHC)/%.c62 ln -sfn ../$(HUB_IN_VHC)/$*.c $@ -
uspace/app/vuhid/stdreq.h
ra58dd620 r3d4aa055 1 1 /* 2 * Copyright (c) 201 0Vojtech Horky2 * Copyright (c) 2011 Vojtech Horky 3 3 * All rights reserved. 4 4 * … … 27 27 */ 28 28 29 /** @addtogroup drvusbvhc29 /** @addtogroup usbvirthid 30 30 * @{ 31 */ 31 */ 32 32 /** @file 33 * @brief Virtual device management.33 * Device request handlers. 34 34 */ 35 #ifndef V HCD_DEVICES_H_36 #define V HCD_DEVICES_H_35 #ifndef VUHID_STDREQ_H_ 36 #define VUHID_STDREQ_H_ 37 37 38 #include <adt/list.h> 39 #include <usb/usb.h> 38 #include <usbvirt/device.h> 40 39 41 #include "hc.h" 40 int req_get_descriptor(usbvirt_device_t *device, 41 const usb_device_request_setup_packet_t *setup_packet, 42 uint8_t *data, size_t *act_size); 42 43 43 /** Connected virtual device. */ 44 typedef struct { 45 /** Phone used when sending data to device. */ 46 int phone; 47 /** Unique identification. */ 48 sysarg_t id; 49 /** Linked-list handle. */ 50 link_t link; 51 } virtdev_connection_t; 44 int req_set_protocol(usbvirt_device_t *device, 45 const usb_device_request_setup_packet_t *setup_packet, 46 uint8_t *data, size_t *act_size); 52 47 53 virtdev_connection_t *virtdev_add_device(int, sysarg_t); 54 virtdev_connection_t *virtdev_find(sysarg_t); 55 void virtdev_destroy_device(virtdev_connection_t *); 56 int virtdev_send_to_all(transaction_t *); 48 int req_set_report(usbvirt_device_t *device, 49 const usb_device_request_setup_packet_t *setup_packet, 50 uint8_t *data, size_t *act_size); 57 51 58 52 #endif -
uspace/app/vuhid/virthid.h
ra58dd620 r3d4aa055 27 27 */ 28 28 29 /** @addtogroup usbvirth ub29 /** @addtogroup usbvirthid 30 30 * @{ 31 31 */ 32 /** 33 * @file 34 * @brief Virtual USB hub. 32 /** @file 33 * 35 34 */ 36 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <errno.h> 40 #include <str_error.h> 41 #include <bool.h> 35 #ifndef VUHID_VIRTHID_H_ 36 #define VUHID_VIRTHID_H_ 42 37 43 38 #include <usb/usb.h> 44 #include <usb/descriptor.h>45 #include <usb/classes/hub.h>46 39 #include <usbvirt/device.h> 47 #include <usbvirt/hub.h>48 40 49 #include "vhc_hub/virthub.h" 41 #define VUHID_ENDPOINT_MAX USB11_ENDPOINT_MAX 42 #define VUHID_INTERFACE_MAX 8 50 43 51 #define NAME "vuh" 44 typedef struct vuhid_interface vuhid_interface_t; 52 45 53 static usbvirt_device_t hub_device; 46 struct vuhid_interface { 47 const char *name; 48 const char *id; 49 int usb_subclass; 50 int usb_protocol; 54 51 55 #define VERBOSE_SLEEP(sec, msg, ...) \ 56 do { \ 57 char _status[HUB_PORT_COUNT + 2]; \ 58 printf(NAME ": doing nothing for %zu seconds...\n", \ 59 (size_t) (sec)); \ 60 fibril_sleep((sec)); \ 61 virthub_get_status(&hub_device, _status, HUB_PORT_COUNT + 1); \ 62 printf(NAME ": " msg " [%s]\n" #__VA_ARGS__, _status); \ 63 } while (0) 52 uint8_t *report_descriptor; 53 size_t report_descriptor_size; 64 54 65 static void fibril_sleep(size_t sec) 66 { 67 while (sec-- > 0) { 68 async_usleep(1000*1000); 69 } 70 } 55 size_t in_data_size; 56 size_t out_data_size; 71 57 72 static int dev1 = 1; 58 int (*on_data_in)(vuhid_interface_t *, void *, size_t, size_t *); 59 int (*on_data_out)(vuhid_interface_t *, void *, size_t); 60 void (*live)(vuhid_interface_t *); 73 61 74 int main(int argc, char * argv[]) 75 { 76 int rc; 62 int set_protocol; 77 63 78 printf(NAME ": virtual USB hub.\n"); 64 void *interface_data; 65 }; 79 66 80 rc = virthub_init(&hub_device); 81 if (rc != EOK) { 82 printf(NAME ": Unable to start communication with VHCD (%s).\n", 83 str_error(rc)); 84 return rc; 85 } 86 87 while (true) { 88 VERBOSE_SLEEP(8, "will pretend device plug-in..."); 89 virthub_connect_device(&hub_device, &dev1); 67 typedef struct { 68 vuhid_interface_t *in_endpoints_mapping[VUHID_ENDPOINT_MAX]; 69 size_t in_endpoint_first_free; 70 vuhid_interface_t *out_endpoints_mapping[VUHID_ENDPOINT_MAX]; 71 size_t out_endpoint_first_free; 72 vuhid_interface_t *interface_mapping[VUHID_INTERFACE_MAX]; 73 } vuhid_data_t; 90 74 91 VERBOSE_SLEEP(8, "will pretend device un-plug..."); 92 virthub_disconnect_device(&hub_device, &dev1); 93 } 75 typedef struct { 76 uint8_t length; 77 uint8_t type; 78 uint16_t hid_spec_release; 79 uint8_t country_code; 80 uint8_t descriptor_count; 81 uint8_t descriptor1_type; 82 uint16_t descriptor1_length; 83 } __attribute__ ((packed)) hid_descriptor_t; 94 84 95 usbvirt_disconnect(&hub_device); 96 97 return 0; 98 } 85 int add_interface_by_id(vuhid_interface_t **, const char *, usbvirt_device_t *); 99 86 100 101 /** @} 87 #endif 88 /** 89 * @} 102 90 */ -
uspace/drv/ohci/root_hub.c
ra58dd620 r3d4aa055 149 149 150 150 151 static void usb_create_serialized_hub_descriptor(rh_t *instance, 152 uint8_t ** out_result, 153 size_t * out_size); 154 155 static void rh_init_descriptors(rh_t *instance); 151 static int create_serialized_hub_descriptor(rh_t *instance); 152 153 static int rh_init_descriptors(rh_t *instance); 156 154 157 155 static int process_get_port_status_request(rh_t *instance, uint16_t port, … … 164 162 usb_transfer_batch_t * request); 165 163 166 static void create_interrupt_mask(rh_t *instance, void ** buffer, 167 size_t * buffer_size); 164 static void create_interrupt_mask_in_instance(rh_t *instance); 168 165 169 166 static int process_get_descriptor_request(rh_t *instance, … … 198 195 static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request); 199 196 200 static int process_interrupt(rh_t *instance, usb_transfer_batch_t * request, 201 void * change_buffer, size_t buffe_size); 197 static int process_interrupt_mask_in_instance(rh_t *instance, usb_transfer_batch_t * request); 202 198 203 199 static bool is_zeros(void * buffer, size_t size); … … 213 209 instance->port_count = 214 210 (instance->registers->rh_desc_a >> RHDA_NDS_SHIFT) & RHDA_NDS_MASK; 215 rh_init_descriptors(instance); 211 int opResult = rh_init_descriptors(instance); 212 if(opResult != EOK){ 213 return opResult; 214 } 216 215 // set port power mode to no-power-switching 217 216 instance->registers->rh_desc_a |= RHDA_NPS_FLAG; 218 217 instance->unfinished_interrupt_transfer = NULL; 219 instance->interrupt_buffer = malloc((instance->port_count + 8)/8); 218 instance->interrupt_mask_size = (instance->port_count + 8)/8; 219 instance->interrupt_buffer = malloc(instance->interrupt_mask_size); 220 if(!instance->interrupt_buffer) 221 return ENOMEM; 222 223 220 224 usb_log_info("OHCI root hub with %d ports.\n", instance->port_count); 221 225 return EOK; … … 240 244 } else if (request->ep->transfer_type == USB_TRANSFER_INTERRUPT) { 241 245 usb_log_info("Root hub got INTERRUPT packet\n"); 242 void * buffer; 243 size_t buffer_size; 244 create_interrupt_mask(instance, &buffer, 245 &buffer_size); 246 if(is_zeros(buffer,buffer_size)){ 247 usb_log_debug("no changes.."); 248 instance->unfinished_interrupt_transfer= 249 request; 246 create_interrupt_mask_in_instance(instance); 247 if(is_zeros(instance->interrupt_buffer, 248 instance->interrupt_mask_size)){ 249 usb_log_debug("no changes..\n"); 250 instance->unfinished_interrupt_transfer = request; 250 251 //will be finished later 251 252 }else{ 252 usb_log_debug("processing changes.."); 253 process_interrupt(instance, request, 254 buffer, buffer_size); 255 } 256 free(buffer); 253 usb_log_debug("processing changes..\n"); 254 process_interrupt_mask_in_instance(instance, request); 255 } 257 256 opResult = EOK; 258 257 } else { … … 265 264 /*----------------------------------------------------------------------------*/ 266 265 267 266 /** 267 * process interrupt on a hub 268 * 269 * If there is no pending interrupt transfer, nothing happens. 270 * @param instance 271 */ 268 272 void rh_interrupt(rh_t *instance) { 269 //usb_log_info("Whoa whoa wait, I`m not supposed to receive any "270 // "interrupts, am I?\n");271 273 if(!instance->unfinished_interrupt_transfer){ 272 274 return; 273 275 } 274 size_t size; 275 void * buffer; 276 create_interrupt_mask(instance, &buffer, 277 &size); 278 process_interrupt(instance,instance->unfinished_interrupt_transfer, 279 buffer,size); 280 free(buffer); 276 usb_log_debug("finalizing interrupt transfer\n"); 277 create_interrupt_mask_in_instance(instance); 278 process_interrupt_mask_in_instance(instance, 279 instance->unfinished_interrupt_transfer); 281 280 } 282 281 /*----------------------------------------------------------------------------*/ … … 289 288 * 290 289 * @param instance root hub instance 291 * @param@out out_result pointer to resultant serialized descriptor 292 * @param@out out_size size of serialized descriptor 293 */ 294 static void usb_create_serialized_hub_descriptor(rh_t *instance, 295 uint8_t ** out_result, 296 size_t * out_size) { 297 //base size 298 size_t size = 7; 299 //variable size according to port count 300 size_t var_size = instance->port_count / 8 + 301 ((instance->port_count % 8 > 0) ? 1 : 0); 302 size += 2 * var_size; 290 * @return error code 291 */ 292 static int create_serialized_hub_descriptor(rh_t *instance) { 293 size_t size = 7 + 294 ((instance->port_count +7 )/ 8) * 2; 295 size_t var_size = (instance->port_count +7 )/ 8; 303 296 uint8_t * result = (uint8_t*) malloc(size); 297 if(!result) return ENOMEM; 298 304 299 bzero(result, size); 305 300 //size … … 330 325 result[7 + var_size + i] = 255; 331 326 } 332 (*out_result) = result; 333 (*out_size) = size; 327 instance->hub_descriptor = result; 328 instance->descriptor_size = size; 329 return EOK; 334 330 } 335 331 /*----------------------------------------------------------------------------*/ … … 340 336 * be initialized only once per hub. 341 337 * @instance root hub instance 342 */ 343 static void rh_init_descriptors(rh_t *instance) { 338 * @return error code 339 */ 340 static int rh_init_descriptors(rh_t *instance) { 344 341 memcpy(&instance->descriptors.device, &ohci_rh_device_descriptor, 345 342 sizeof (ohci_rh_device_descriptor) … … 348 345 memcpy(&descriptor, &ohci_rh_conf_descriptor, 349 346 sizeof (ohci_rh_conf_descriptor)); 350 uint8_t * hub_descriptor; 351 size_t hub_desc_size;352 usb_create_serialized_hub_descriptor(instance, &hub_descriptor,353 &hub_desc_size);354 347 348 int opResult = create_serialized_hub_descriptor(instance); 349 if(opResult != EOK){ 350 return opResult; 351 } 355 352 descriptor.total_length = 356 353 sizeof (usb_standard_configuration_descriptor_t) + 357 354 sizeof (usb_standard_endpoint_descriptor_t) + 358 355 sizeof (usb_standard_interface_descriptor_t) + 359 hub_desc_size;356 instance->descriptor_size; 360 357 361 358 uint8_t * full_config_descriptor = 362 359 (uint8_t*) malloc(descriptor.total_length); 360 if(!full_config_descriptor){ 361 return ENOMEM; 362 } 363 363 memcpy(full_config_descriptor, &descriptor, sizeof (descriptor)); 364 364 memcpy(full_config_descriptor + sizeof (descriptor), … … 370 370 sizeof (ohci_rh_iface_descriptor) + 371 371 sizeof (ohci_rh_ep_descriptor), 372 hub_descriptor, hub_desc_size);373 372 instance->hub_descriptor, instance->descriptor_size); 373 374 374 instance->descriptors.configuration = full_config_descriptor; 375 375 instance->descriptors.configuration_size = descriptor.total_length; 376 return EOK; 376 377 } 377 378 /*----------------------------------------------------------------------------*/ … … 464 465 * bit i indicates change on i`th port (i>0). For more info see 465 466 * Hub and Port status bitmap specification in USB specification 466 * (chapter 11.13.4) 467 * @param instance root hub instance 468 * @param@out buffer pointer to created interrupt mas 469 * @param@out buffer_size size of created interrupt mask 470 */ 471 static void create_interrupt_mask(rh_t *instance, void ** buffer, 472 size_t * buffer_size) { 473 int bit_count = instance->port_count + 1; 474 (*buffer_size) = (bit_count+7 / 8); 475 476 (*buffer) = instance->interrupt_buffer;//malloc(*buffer_size); 477 uint8_t * bitmap = (uint8_t*) (*buffer); 467 * (chapter 11.13.4). 468 * Uses instance`s interrupt buffer to store the interrupt information. 469 * @param instance root hub instance 470 */ 471 static void create_interrupt_mask_in_instance(rh_t * instance) { 472 uint8_t * bitmap = (uint8_t*) (instance->interrupt_buffer); 478 473 uint32_t mask = (1 << (USB_HUB_FEATURE_C_HUB_LOCAL_POWER + 16)) 479 474 | (1 << (USB_HUB_FEATURE_C_HUB_OVER_CURRENT + 16)); 480 bzero(bitmap, (*buffer_size));475 bzero(bitmap, instance->interrupt_mask_size); 481 476 if (instance->registers->rh_status & mask) { 482 477 bitmap[0] = 1; … … 509 504 const uint16_t setup_request_value = setup_request->value_high; 510 505 //(setup_request->value_low << 8); 511 bool del = false;512 506 switch (setup_request_value) { 513 507 case USB_DESCTYPE_HUB: 514 508 { 515 uint8_t * descriptor; 516 usb_create_serialized_hub_descriptor( 517 instance, &descriptor, &size); 518 result_descriptor = descriptor; 519 if (result_descriptor) del = true; 509 usb_log_debug("USB_DESCTYPE_HUB\n"); 510 result_descriptor = instance->hub_descriptor; 511 size = instance->descriptor_size; 520 512 break; 521 513 } … … 568 560 request->transfered_size = size; 569 561 memcpy(request->data_buffer, result_descriptor, size); 570 if (del)571 free(result_descriptor);572 562 return EOK; 573 563 } … … 895 885 * @param instance hub instance 896 886 * @param request batch request to be processed 897 * @param change_buffer chages on hub898 * @param buffer_size size of change buffer899 887 * 900 888 * @return 901 889 */ 902 static int process_interrupt(rh_t *instance, usb_transfer_batch_t * request, 903 void * change_buffer, size_t buffe_size){ 904 create_interrupt_mask(instance, &change_buffer, 905 &(request->transfered_size)); 906 memcpy(request->data_buffer, change_buffer,request->transfered_size); 890 static int process_interrupt_mask_in_instance(rh_t *instance, usb_transfer_batch_t * request){ 891 memcpy(request->data_buffer, instance->interrupt_buffer, 892 instance->interrupt_mask_size); 893 request->transfered_size = instance->interrupt_mask_size; 907 894 instance->unfinished_interrupt_transfer = NULL; 908 895 usb_transfer_batch_finish_error(request, EOK); -
uspace/drv/ohci/root_hub.h
ra58dd620 r3d4aa055 59 59 * 60 60 * This is allocated when initializing instance, so that memory 61 * allocation is not needed when processing request. 61 * allocation is not needed when processing request. Buffer is used for 62 * interrupt bitmask. 62 63 */ 63 64 uint8_t * interrupt_buffer; 65 /** size of interrupt buffer */ 66 size_t interrupt_mask_size; 67 /** instance`s descriptor*/ 68 uint8_t * hub_descriptor; 69 /** size of hub descriptor */ 70 size_t descriptor_size; 71 72 64 73 } rh_t; 65 74 -
uspace/drv/usbhid/Makefile
ra58dd620 r3d4aa055 47 47 mouse/mousedev.c \ 48 48 lgtch-ultrax/lgtch-ultrax.c \ 49 lgtch-ultrax/keymap.c \ 49 50 $(STOLEN_LAYOUT_SOURCES) 50 51 -
uspace/drv/usbhid/generic/hiddev.c
ra58dd620 r3d4aa055 37 37 #include <usb/debug.h> 38 38 #include <usb/classes/classes.h> 39 #include <errno.h> 40 #include <str_error.h> 41 42 #include <usbhid_iface.h> 39 43 40 44 #include "hiddev.h" … … 55 59 /*----------------------------------------------------------------------------*/ 56 60 61 static size_t usb_generic_hid_get_event_length(ddf_fun_t *fun); 62 63 static int usb_generic_hid_get_event(ddf_fun_t *fun, int32_t *buffer, 64 size_t size, size_t *act_size, unsigned int flags); 65 66 /*----------------------------------------------------------------------------*/ 67 68 static usbhid_iface_t usb_generic_iface = { 69 .get_event = usb_generic_hid_get_event, 70 .get_event_length = usb_generic_hid_get_event_length 71 }; 72 73 static ddf_dev_ops_t usb_generic_hid_ops = { 74 .interfaces[USBHID_DEV_IFACE] = &usb_generic_iface 75 }; 76 77 /*----------------------------------------------------------------------------*/ 78 79 static size_t usb_generic_hid_get_event_length(ddf_fun_t *fun) 80 { 81 if (fun == NULL || fun->driver_data) { 82 return 0; 83 } 84 85 usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data; 86 87 return hid_dev->input_report_size; 88 } 89 90 /*----------------------------------------------------------------------------*/ 91 92 static int usb_generic_hid_get_event(ddf_fun_t *fun, int32_t *buffer, 93 size_t size, size_t *act_size, unsigned int flags) 94 { 95 if (fun == NULL || fun->driver_data) { 96 return EINVAL; 97 } 98 99 usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data; 100 101 if (hid_dev->input_report_size > size) { 102 return EINVAL; // TODO: other error code 103 } 104 105 /*! @todo This should probably be atomic. */ 106 memcpy(buffer, hid_dev->input_report, hid_dev->input_report_size); 107 *act_size = hid_dev->input_report_size; 108 109 // clear the buffer so that it will not be received twice 110 memset(hid_dev->input_report, 0, hid_dev->input_report_size); 111 112 return EOK; 113 } 114 115 /*----------------------------------------------------------------------------*/ 116 117 static int usb_generic_hid_create_function(usb_hid_dev_t *hid_dev) 118 { 119 /* Create the function exposed under /dev/devices. */ 120 /** @todo Generate numbers for the devices? */ 121 usb_log_debug("Creating DDF function %s...\n", HID_GENERIC_FUN_NAME); 122 ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed, 123 HID_GENERIC_FUN_NAME); 124 if (fun == NULL) { 125 usb_log_error("Could not create DDF function node.\n"); 126 return ENOMEM; 127 } 128 129 int rc = ddf_fun_bind(fun); 130 if (rc != EOK) { 131 usb_log_error("Could not bind DDF function: %s.\n", 132 str_error(rc)); 133 ddf_fun_destroy(fun); 134 return rc; 135 } 136 137 fun->ops = &usb_generic_hid_ops; 138 fun->driver_data = hid_dev; 139 140 return EOK; 141 } 142 143 /*----------------------------------------------------------------------------*/ 144 145 int usb_generic_hid_init(usb_hid_dev_t *hid_dev) 146 { 147 if (hid_dev == NULL) { 148 return EINVAL; 149 } 150 151 return usb_generic_hid_create_function(hid_dev); 152 } 153 154 /*----------------------------------------------------------------------------*/ 155 57 156 bool usb_generic_hid_polling_callback(usb_hid_dev_t *hid_dev, 58 157 uint8_t *buffer, size_t buffer_size) -
uspace/drv/usbhid/generic/hiddev.h
ra58dd620 r3d4aa055 46 46 const char *HID_GENERIC_CLASS_NAME; 47 47 48 /*----------------------------------------------------------------------------*/ 49 50 int usb_generic_hid_init(struct usb_hid_dev *hid_dev); 51 48 52 bool usb_generic_hid_polling_callback(struct usb_hid_dev *hid_dev, 49 53 uint8_t *buffer, size_t buffer_size); -
uspace/drv/usbhid/kbd/conv.c
ra58dd620 r3d4aa055 99 99 [0x30] = KC_RBRACKET, 100 100 [0x31] = KC_BACKSLASH, 101 //[0x32] = KC_, // TODO: HASH??? maybe some as 0x31 - backslash 101 //[0x32] = KC_, // TODO: HASH??? maybe same as 0x31 - backslash 102 [0x32] = KC_BACKSLASH, 102 103 [0x33] = KC_SEMICOLON, 103 104 [0x34] = KC_QUOTE, // same as APOSTROPHE? (') -
uspace/drv/usbhid/kbd/kbddev.c
ra58dd620 r3d4aa055 177 177 /*----------------------------------------------------------------------------*/ 178 178 179 static void usb_kbd_process_keycodes(const uint8_t *key_codes, size_t count,180 uint8_t report_id, void *arg);181 182 static const usb_hid_report_in_callbacks_t usb_kbd_parser_callbacks = {183 .keyboard = usb_kbd_process_keycodes184 };179 //static void usb_kbd_process_keycodes(const uint8_t *key_codes, size_t count, 180 // uint8_t report_id, void *arg); 181 182 //static const usb_hid_report_in_callbacks_t usb_kbd_parser_callbacks = { 183 // .keyboard = usb_kbd_process_keycodes 184 //}; 185 185 186 186 /*----------------------------------------------------------------------------*/ … … 203 203 /*----------------------------------------------------------------------------*/ 204 204 /** Mapping of USB modifier key codes to generic modifier key codes. */ 205 static const keycode_t usbhid_modifiers_keycodes[USB_HID_MOD_COUNT] = {206 KC_LCTRL, /* USB_HID_MOD_LCTRL */207 KC_LSHIFT, /* USB_HID_MOD_LSHIFT */208 KC_LALT, /* USB_HID_MOD_LALT */209 0, /* USB_HID_MOD_LGUI */210 KC_RCTRL, /* USB_HID_MOD_RCTRL */211 KC_RSHIFT, /* USB_HID_MOD_RSHIFT */212 KC_RALT, /* USB_HID_MOD_RALT */213 0, /* USB_HID_MOD_RGUI */214 };215 216 typedef enum usbhid_lock_code {217 USB_KBD_LOCK_NUM = 0x53,218 USB_KBD_LOCK_CAPS = 0x39,219 USB_KBD_LOCK_SCROLL = 0x47,220 USB_KBD_LOCK_COUNT = 3221 } usbhid_lock_code;222 223 static const usbhid_lock_code usbhid_lock_codes[USB_KBD_LOCK_COUNT] = {224 USB_KBD_LOCK_NUM,225 USB_KBD_LOCK_CAPS,226 USB_KBD_LOCK_SCROLL227 };205 //static const keycode_t usbhid_modifiers_keycodes[USB_HID_MOD_COUNT] = { 206 // KC_LCTRL, /* USB_HID_MOD_LCTRL */ 207 // KC_LSHIFT, /* USB_HID_MOD_LSHIFT */ 208 // KC_LALT, /* USB_HID_MOD_LALT */ 209 // 0, /* USB_HID_MOD_LGUI */ 210 // KC_RCTRL, /* USB_HID_MOD_RCTRL */ 211 // KC_RSHIFT, /* USB_HID_MOD_RSHIFT */ 212 // KC_RALT, /* USB_HID_MOD_RALT */ 213 // 0, /* USB_HID_MOD_RGUI */ 214 //}; 215 216 //typedef enum usbhid_lock_code { 217 // USB_KBD_LOCK_NUM = 0x53, 218 // USB_KBD_LOCK_CAPS = 0x39, 219 // USB_KBD_LOCK_SCROLL = 0x47, 220 // USB_KBD_LOCK_COUNT = 3 221 //} usbhid_lock_code; 222 223 //static const usbhid_lock_code usbhid_lock_codes[USB_KBD_LOCK_COUNT] = { 224 // USB_KBD_LOCK_NUM, 225 // USB_KBD_LOCK_CAPS, 226 // USB_KBD_LOCK_SCROLL 227 //}; 228 228 229 229 /*----------------------------------------------------------------------------*/ … … 299 299 return; 300 300 } 301 302 unsigned i = 0; 303 301 304 302 /* Reset the LED data. */ 305 303 memset(kbd_dev->led_data, 0, kbd_dev->led_output_size * sizeof(int32_t)); 306 307 if ((kbd_dev->mods & KM_NUM_LOCK) && (i < kbd_dev->led_output_size)) { 308 kbd_dev->led_data[i++] = USB_HID_LED_NUM_LOCK; 309 } 310 311 if ((kbd_dev->mods & KM_CAPS_LOCK) && (i < kbd_dev->led_output_size)) { 312 kbd_dev->led_data[i++] = USB_HID_LED_CAPS_LOCK; 313 } 314 315 if ((kbd_dev->mods & KM_SCROLL_LOCK) 316 && (i < kbd_dev->led_output_size)) { 317 kbd_dev->led_data[i++] = USB_HID_LED_SCROLL_LOCK; 318 } 319 320 // TODO: COMPOSE and KANA 321 322 usb_log_debug("Creating output report.\n"); 323 324 int rc = usb_hid_report_output_translate(hid_dev->parser, 325 kbd_dev->led_path, 326 USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 327 kbd_dev->output_buffer, 328 kbd_dev->output_size, kbd_dev->led_data, kbd_dev->led_output_size); 304 usb_log_debug("Creating output report:\n"); 305 306 usb_hid_report_field_t *field = usb_hid_report_get_sibling( 307 hid_dev->report, NULL, kbd_dev->led_path, 308 USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY | USB_HID_PATH_COMPARE_END, 309 USB_HID_REPORT_TYPE_OUTPUT); 310 311 while (field != NULL) { 312 313 if ((field->usage == USB_HID_LED_NUM_LOCK) 314 && (kbd_dev->mods & KM_NUM_LOCK)){ 315 field->value = 1; 316 } 317 318 if ((field->usage == USB_HID_LED_CAPS_LOCK) 319 && (kbd_dev->mods & KM_CAPS_LOCK)){ 320 field->value = 1; 321 } 322 323 if ((field->usage == USB_HID_LED_SCROLL_LOCK) 324 && (kbd_dev->mods & KM_SCROLL_LOCK)){ 325 field->value = 1; 326 } 327 328 field = usb_hid_report_get_sibling(hid_dev->report, field, 329 kbd_dev->led_path, USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY 330 | USB_HID_PATH_COMPARE_END, USB_HID_REPORT_TYPE_OUTPUT); 331 } 332 333 // TODO: what about the Report ID? 334 int rc = usb_hid_report_output_translate(hid_dev->report, 0, 335 kbd_dev->output_buffer, kbd_dev->output_size); 329 336 330 337 if (rc != EOK) { … … 485 492 */ 486 493 static void usb_kbd_check_key_changes(usb_hid_dev_t *hid_dev, 487 usb_kbd_t *kbd_dev , const uint8_t *key_codes, size_t count)494 usb_kbd_t *kbd_dev/*, const uint8_t *key_codes, size_t count*/) 488 495 { 489 496 unsigned int key; … … 499 506 */ 500 507 i = 0; 501 while (i < count && key_codes[i] != ERROR_ROLLOVER) {508 while (i < kbd_dev->key_count && kbd_dev->keys[i] != ERROR_ROLLOVER) { 502 509 ++i; 503 510 } 504 if (i != count) {511 if (i != kbd_dev->key_count) { 505 512 usb_log_debug("Phantom state occured.\n"); 506 513 // phantom state, do nothing … … 508 515 } 509 516 510 /* TODO: quite dummy right now, think of better implementation */511 assert(count == kbd_dev->key_count);512 513 517 /* 514 518 * 1) Key releases 515 519 */ 516 for (j = 0; j < count; ++j) {520 for (j = 0; j < kbd_dev->key_count; ++j) { 517 521 // try to find the old key in the new key list 518 522 i = 0; 519 523 while (i < kbd_dev->key_count 520 && k ey_codes[i] != kbd_dev->keys[j]) {524 && kbd_dev->keys[i] != kbd_dev->keys_old[j]) { 521 525 ++i; 522 526 } 523 527 524 if (i == count) {528 if (i == kbd_dev->key_count) { 525 529 // not found, i.e. the key was released 526 key = usbhid_parse_scancode(kbd_dev->keys [j]);530 key = usbhid_parse_scancode(kbd_dev->keys_old[j]); 527 531 if (!usb_kbd_is_lock(key)) { 528 532 usb_kbd_repeat_stop(kbd_dev, key); … … 541 545 // try to find the new key in the old key list 542 546 j = 0; 543 while (j < count && kbd_dev->keys[j] != key_codes[i]) { 547 while (j < kbd_dev->key_count 548 && kbd_dev->keys_old[j] != kbd_dev->keys[i]) { 544 549 ++j; 545 550 } 546 551 547 if (j == count) {552 if (j == kbd_dev->key_count) { 548 553 // not found, i.e. new key pressed 549 key = usbhid_parse_scancode(k ey_codes[i]);554 key = usbhid_parse_scancode(kbd_dev->keys[i]); 550 555 usb_log_debug2("Key pressed: %d (keycode: %d)\n", key, 551 key_codes[i]); 552 usb_kbd_push_ev(hid_dev, kbd_dev, KEY_PRESS, 553 key); 556 kbd_dev->keys[i]); 557 usb_kbd_push_ev(hid_dev, kbd_dev, KEY_PRESS, key); 554 558 if (!usb_kbd_is_lock(key)) { 555 559 usb_kbd_repeat_start(kbd_dev, key); … … 560 564 } 561 565 562 memcpy(kbd_dev->keys, key_codes, count); 563 564 usb_log_debug("New stored keycodes: %s\n", 565 usb_debug_str_buffer(kbd_dev->keys, kbd_dev->key_count, 0)); 566 // usb_log_debug("Old keys: "); 567 // for (i = 0; i < kbd_dev->key_count; ++i) { 568 // usb_log_debug("%d ", kbd_dev->keys_old[i]); 569 // } 570 // usb_log_debug("\n"); 571 572 573 // usb_log_debug("New keys: "); 574 // for (i = 0; i < kbd_dev->key_count; ++i) { 575 // usb_log_debug("%d ", kbd_dev->keys[i]); 576 // } 577 // usb_log_debug("\n"); 578 579 memcpy(kbd_dev->keys_old, kbd_dev->keys, kbd_dev->key_count * 4); 580 581 usb_log_debug2("New stored keys: "); 582 for (i = 0; i < kbd_dev->key_count; ++i) { 583 usb_log_debug2("%d ", kbd_dev->keys_old[i]); 584 } 585 usb_log_debug2("\n"); 566 586 } 567 587 … … 585 605 * @sa usb_kbd_check_key_changes(), usb_kbd_check_modifier_changes() 586 606 */ 587 static void usb_kbd_process_keycodes(const uint8_t *key_codes, size_t count,588 uint8_t report_id, void *arg)589 {590 if (arg == NULL) {591 usb_log_warning("Missing argument in callback "592 "usbhid_process_keycodes().\n");593 return;594 }595 596 usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;597 598 if (hid_dev->data == NULL) {599 usb_log_warning("Missing KBD device structure in callback.\n");600 return;601 }602 603 usb_kbd_t *kbd_dev = (usb_kbd_t *)hid_dev->data;604 605 usb_log_debug("Got keys from parser (report id: %u): %s\n",606 report_id, usb_debug_str_buffer(key_codes, count, 0));607 608 if (count != kbd_dev->key_count) {609 usb_log_warning("Number of received keycodes (%zu) differs from"610 " expected (%zu).\n", count, kbd_dev->key_count);611 return;612 }613 614 ///usb_kbd_check_modifier_changes(kbd_dev, key_codes, count);615 usb_kbd_check_key_changes(hid_dev, kbd_dev, key_codes, count);616 }607 //static void usb_kbd_process_keycodes(const uint8_t *key_codes, size_t count, 608 // uint8_t report_id, void *arg) 609 //{ 610 // if (arg == NULL) { 611 // usb_log_warning("Missing argument in callback " 612 // "usbhid_process_keycodes().\n"); 613 // return; 614 // } 615 616 // usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg; 617 618 // if (hid_dev->data == NULL) { 619 // usb_log_warning("Missing KBD device structure in callback.\n"); 620 // return; 621 // } 622 623 // usb_kbd_t *kbd_dev = (usb_kbd_t *)hid_dev->data; 624 625 // usb_log_debug("Got keys from parser (report id: %u): %s\n", 626 // report_id, usb_debug_str_buffer(key_codes, count, 0)); 627 628 // if (count != kbd_dev->key_count) { 629 // usb_log_warning("Number of received keycodes (%zu) differs from" 630 // " expected (%zu).\n", count, kbd_dev->key_count); 631 // return; 632 // } 633 634 // ///usb_kbd_check_modifier_changes(kbd_dev, key_codes, count); 635 // usb_kbd_check_key_changes(hid_dev, kbd_dev, key_codes, count); 636 //} 617 637 618 638 /*----------------------------------------------------------------------------*/ … … 638 658 uint8_t *buffer, size_t actual_size) 639 659 { 640 assert(hid_dev->parser != NULL); 660 assert(hid_dev->report != NULL); 661 assert(hid_dev != NULL); 662 assert(hid_dev->data != NULL); 663 664 usb_kbd_t *kbd_dev = (usb_kbd_t *)hid_dev->data; 641 665 642 666 usb_log_debug("Calling usb_hid_parse_report() with " … … 648 672 usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0); 649 673 //usb_hid_report_path_set_report_id(path, 0); 650 651 int rc = usb_hid_parse_report(hid_dev->parser, buffer, 652 actual_size, path, 674 675 uint8_t report_id; 676 int rc = usb_hid_parse_report(hid_dev->report, buffer, actual_size, 677 &report_id); 678 679 if (rc != EOK) { 680 usb_log_warning("Error in usb_hid_parse_report():" 681 "%s\n", str_error(rc)); 682 } 683 684 usb_hid_report_path_set_report_id (path, report_id); 685 686 // fill in the currently pressed keys 687 688 usb_hid_report_field_t *field = usb_hid_report_get_sibling( 689 hid_dev->report, NULL, path, 653 690 USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 654 &usb_kbd_parser_callbacks, hid_dev); 655 691 USB_HID_REPORT_TYPE_INPUT); 692 unsigned i = 0; 693 694 while (field != NULL) { 695 usb_log_debug2("FIELD (%p) - VALUE(%d) USAGE(%u)\n", 696 field, field->value, field->usage); 697 698 assert(i < kbd_dev->key_count); 699 // if (i == kbd_dev->key_count) { 700 // break; 701 // } 702 703 // save the key usage 704 /* TODO: maybe it's not good to save value, nor usage 705 * as the value may be e.g. 1 for LEDs and usage may be 706 * value of the LED. On the other hand, in case of normal 707 * keys, the usage is more important and we must check 708 * that. One possible solution: distinguish between those 709 * two parts of the Report somehow. 710 */ 711 if (field->value != 0) { 712 kbd_dev->keys[i] = field->usage; 713 } 714 else { 715 kbd_dev->keys[i] = 0; 716 } 717 usb_log_debug2("Saved %u. key usage %d\n", i, kbd_dev->keys[i]); 718 719 ++i; 720 field = usb_hid_report_get_sibling(hid_dev->report, field, path, 721 USB_HID_PATH_COMPARE_END 722 | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 723 USB_HID_REPORT_TYPE_INPUT); 724 } 725 656 726 usb_hid_report_path_free(path); 657 727 658 if (rc != EOK) { 659 usb_log_warning("Error in usb_hid_boot_keyboard_input_report():" 660 "%s\n", str_error(rc)); 661 } 728 usb_kbd_check_key_changes(hid_dev, kbd_dev); 662 729 } 663 730 … … 696 763 697 764 return kbd_dev; 765 } 766 767 /*----------------------------------------------------------------------------*/ 768 769 static int usb_kbd_create_function(usb_hid_dev_t *hid_dev) 770 { 771 assert(hid_dev != NULL); 772 assert(hid_dev->usb_dev != NULL); 773 774 /* Create the function exposed under /dev/devices. */ 775 usb_log_debug("Creating DDF function %s...\n", HID_KBD_FUN_NAME); 776 ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed, 777 HID_KBD_FUN_NAME); 778 if (fun == NULL) { 779 usb_log_error("Could not create DDF function node.\n"); 780 return ENOMEM; 781 } 782 783 /* 784 * Store the initialized HID device and HID ops 785 * to the DDF function. 786 */ 787 fun->ops = &hid_dev->ops; 788 fun->driver_data = hid_dev; // TODO: maybe change to hid_dev->data 789 790 int rc = ddf_fun_bind(fun); 791 if (rc != EOK) { 792 usb_log_error("Could not bind DDF function: %s.\n", 793 str_error(rc)); 794 ddf_fun_destroy(fun); 795 return rc; 796 } 797 798 usb_log_debug("Adding DDF function to class %s...\n", 799 HID_KBD_CLASS_NAME); 800 rc = ddf_fun_add_to_class(fun, HID_KBD_CLASS_NAME); 801 if (rc != EOK) { 802 usb_log_error( 803 "Could not add DDF function to class %s: %s.\n", 804 HID_KBD_CLASS_NAME, str_error(rc)); 805 ddf_fun_destroy(fun); 806 return rc; 807 } 808 809 return EOK; 698 810 } 699 811 … … 747 859 748 860 kbd_dev->key_count = usb_hid_report_input_length( 749 hid_dev-> parser, path,861 hid_dev->report, path, 750 862 USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY); 751 863 usb_hid_report_path_free(path); … … 753 865 usb_log_debug("Size of the input report: %zu\n", kbd_dev->key_count); 754 866 755 kbd_dev->keys = ( uint8_t *)calloc(kbd_dev->key_count, sizeof(uint8_t));867 kbd_dev->keys = (int32_t *)calloc(kbd_dev->key_count, sizeof(int32_t)); 756 868 757 869 if (kbd_dev->keys == NULL) { … … 761 873 } 762 874 875 kbd_dev->keys_old = 876 (int32_t *)calloc(kbd_dev->key_count, sizeof(int32_t)); 877 878 if (kbd_dev->keys_old == NULL) { 879 usb_log_fatal("No memory!\n"); 880 free(kbd_dev->keys); 881 free(kbd_dev); 882 return ENOMEM; 883 } 884 763 885 /* 764 886 * Output report 765 887 */ 766 888 kbd_dev->output_size = 0; 767 kbd_dev->output_buffer = usb_hid_report_output(hid_dev-> parser,768 &kbd_dev->output_size );769 if (kbd_dev->output_buffer == NULL && kbd_dev->output_size != 0) {889 kbd_dev->output_buffer = usb_hid_report_output(hid_dev->report, 890 &kbd_dev->output_size, 0); 891 if (kbd_dev->output_buffer == NULL) { 770 892 usb_log_warning("Error creating output report buffer.\n"); 771 893 free(kbd_dev->keys); 772 free(kbd_dev); 773 return ENOMEM; 894 return ENOMEM; /* TODO: other error code */ 774 895 } 775 896 … … 780 901 kbd_dev->led_path, USB_HIDUT_PAGE_LED, 0); 781 902 782 kbd_dev->led_output_size = usb_hid_report_output_size(hid_dev-> parser,903 kbd_dev->led_output_size = usb_hid_report_output_size(hid_dev->report, 783 904 kbd_dev->led_path, 784 905 USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY); … … 854 975 usb_log_debug("HID/KBD device structure initialized.\n"); 855 976 977 usb_log_debug("Creating KBD function...\n"); 978 int rc = usb_kbd_create_function(hid_dev); 979 if (rc != EOK) { 980 usb_kbd_free(&kbd_dev); 981 return rc; 982 } 983 856 984 return EOK; 857 985 } … … 908 1036 } 909 1037 910 // free the output buffer 911 usb_hid_report_output_free((*kbd_dev)->output_buffer); 1038 // free all buffers 1039 if ((*kbd_dev)->keys != NULL) { 1040 free((*kbd_dev)->keys); 1041 } 1042 if ((*kbd_dev)->keys_old != NULL) { 1043 free((*kbd_dev)->keys_old); 1044 } 1045 if ((*kbd_dev)->led_data != NULL) { 1046 free((*kbd_dev)->led_data); 1047 } 1048 if ((*kbd_dev)->led_path != NULL) { 1049 usb_hid_report_path_free((*kbd_dev)->led_path); 1050 } 1051 if ((*kbd_dev)->output_buffer != NULL) { 1052 usb_hid_report_output_free((*kbd_dev)->output_buffer); 1053 } 912 1054 913 1055 free(*kbd_dev); … … 929 1071 } else { 930 1072 usb_kbd_free(&kbd_dev); 1073 hid_dev->data = NULL; 931 1074 } 932 1075 } … … 937 1080 int usb_kbd_set_boot_protocol(usb_hid_dev_t *hid_dev) 938 1081 { 939 int rc = usb_hid_parse_report_descriptor(hid_dev-> parser,1082 int rc = usb_hid_parse_report_descriptor(hid_dev->report, 940 1083 USB_KBD_BOOT_REPORT_DESCRIPTOR, 941 1084 USB_KBD_BOOT_REPORT_DESCRIPTOR_SIZE); -
uspace/drv/usbhid/kbd/kbddev.h
ra58dd620 r3d4aa055 65 65 */ 66 66 typedef struct usb_kbd_t { 67 /** Previously pressed keys (not translated to key codes). */ 68 int32_t *keys_old; 67 69 /** Currently pressed keys (not translated to key codes). */ 68 uint8_t *keys;70 int32_t *keys; 69 71 /** Count of stored keys (i.e. number of keys in the report). */ 70 72 size_t key_count; -
uspace/drv/usbhid/lgtch-ultrax/keymap.h
ra58dd620 r3d4aa055 1 1 /* 2 * Copyright (c) 201 0 Vojtech Horky2 * Copyright (c) 2011 Lubos Slovak 3 3 * All rights reserved. 4 4 * … … 27 27 */ 28 28 29 /** @addtogroup libusbvirt29 /** @addtogroup drvusbhid 30 30 * @{ 31 31 */ 32 32 /** @file 33 * @brief Debugging support.33 * USB multimedia key to keycode mapping. 34 34 */ 35 #include <stdio.h>36 #include <bool.h>37 35 38 #include "private.h" 36 #ifndef USB_HID_LGTCH_ULTRAX_KEYMAP_H_ 37 #define USB_HID_LGTCH_ULTRAX_KEYMAP_H_ 39 38 39 unsigned int usb_lgtch_map_usage(int usage); 40 40 41 static void debug_print(int level, uint8_t tag, 42 int current_level, uint8_t enabled_tags, 43 const char *format, va_list args) 44 { 45 if (level > current_level) { 46 return; 47 } 48 49 if ((tag & enabled_tags) == 0) { 50 return; 51 } 52 53 bool print_prefix = true; 54 55 if ((format[0] == '%') && (format[1] == 'M')) { 56 format += 2; 57 print_prefix = false; 58 } 59 60 if (print_prefix) { 61 printf("[vusb]: "); 62 while (--level > 0) { 63 printf(" "); 64 } 65 } 66 67 vprintf(format, args); 68 69 if (print_prefix) { 70 printf("\n"); 71 } 72 } 73 74 75 void user_debug(usbvirt_device_t *device, int level, uint8_t tag, 76 const char *format, ...) 77 { 78 va_list args; 79 va_start(args, format); 80 81 debug_print(level, tag, 82 device->debug_level, device->debug_enabled_tags, 83 format, args); 84 85 va_end(args); 86 } 87 88 void lib_debug(usbvirt_device_t *device, int level, uint8_t tag, 89 const char *format, ...) 90 { 91 va_list args; 92 va_start(args, format); 93 94 debug_print(level, tag, 95 device->lib_debug_level, device->lib_debug_enabled_tags, 96 format, args); 97 98 va_end(args); 99 } 41 #endif /* USB_HID_LGTCH_ULTRAX_KEYMAP_H_ */ 100 42 101 43 /** -
uspace/drv/usbhid/lgtch-ultrax/lgtch-ultrax.c
ra58dd620 r3d4aa055 38 38 #include "lgtch-ultrax.h" 39 39 #include "../usbhid.h" 40 #include "keymap.h" 40 41 41 42 #include <usb/classes/hidparser.h> 42 43 #include <usb/debug.h> 44 #include <usb/classes/hidut.h> 45 43 46 #include <errno.h> 44 47 #include <str_error.h> 45 48 49 #include <ipc/kbd.h> 50 #include <io/console.h> 51 46 52 #define NAME "lgtch-ultrax" 47 53 48 /*----------------------------------------------------------------------------*/ 49 50 static void usb_lgtch_process_keycodes(const uint8_t *key_codes, size_t count, 51 uint8_t report_id, void *arg); 52 53 static const usb_hid_report_in_callbacks_t usb_lgtch_parser_callbacks = { 54 .keyboard = usb_lgtch_process_keycodes 54 typedef enum usb_lgtch_flags { 55 USB_LGTCH_STATUS_UNINITIALIZED = 0, 56 USB_LGTCH_STATUS_INITIALIZED = 1, 57 USB_LGTCH_STATUS_TO_DESTROY = -1 58 } usb_lgtch_flags; 59 60 /*----------------------------------------------------------------------------*/ 61 /** 62 * Logitech UltraX device type. 63 */ 64 typedef struct usb_lgtch_ultrax_t { 65 /** Previously pressed keys (not translated to key codes). */ 66 int32_t *keys_old; 67 /** Currently pressed keys (not translated to key codes). */ 68 int32_t *keys; 69 /** Count of stored keys (i.e. number of keys in the report). */ 70 size_t key_count; 71 72 /** IPC phone to the console device (for sending key events). */ 73 int console_phone; 74 75 /** Information for auto-repeat of keys. */ 76 // usb_kbd_repeat_t repeat; 77 78 /** Mutex for accessing the information about auto-repeat. */ 79 // fibril_mutex_t *repeat_mtx; 80 81 /** State of the structure (for checking before use). 82 * 83 * 0 - not initialized 84 * 1 - initialized 85 * -1 - ready for destroying 86 */ 87 int initialized; 88 } usb_lgtch_ultrax_t; 89 90 91 /*----------------------------------------------------------------------------*/ 92 /** 93 * Default handler for IPC methods not handled by DDF. 94 * 95 * Currently recognizes only one method (IPC_M_CONNECT_TO_ME), in which case it 96 * assumes the caller is the console and thus it stores IPC phone to it for 97 * later use by the driver to notify about key events. 98 * 99 * @param fun Device function handling the call. 100 * @param icallid Call id. 101 * @param icall Call data. 102 */ 103 static void default_connection_handler(ddf_fun_t *fun, 104 ipc_callid_t icallid, ipc_call_t *icall) 105 { 106 usb_log_debug(NAME " default_connection_handler()\n"); 107 108 sysarg_t method = IPC_GET_IMETHOD(*icall); 109 110 usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data; 111 112 if (hid_dev == NULL || hid_dev->data == NULL) { 113 async_answer_0(icallid, EINVAL); 114 return; 115 } 116 117 assert(hid_dev != NULL); 118 assert(hid_dev->data != NULL); 119 usb_lgtch_ultrax_t *lgtch_dev = (usb_lgtch_ultrax_t *)hid_dev->data; 120 121 if (method == IPC_M_CONNECT_TO_ME) { 122 int callback = IPC_GET_ARG5(*icall); 123 124 if (lgtch_dev->console_phone != -1) { 125 async_answer_0(icallid, ELIMIT); 126 return; 127 } 128 129 lgtch_dev->console_phone = callback; 130 usb_log_debug(NAME " Saved phone to console: %d\n", callback); 131 async_answer_0(icallid, EOK); 132 return; 133 } 134 135 async_answer_0(icallid, EINVAL); 136 } 137 138 /*----------------------------------------------------------------------------*/ 139 140 static ddf_dev_ops_t lgtch_ultrax_ops = { 141 .default_handler = default_connection_handler 55 142 }; 56 143 57 144 /*----------------------------------------------------------------------------*/ 58 145 59 static void usb_lgtch_process_keycodes(const uint8_t *key_codes, size_t count, 60 uint8_t report_id, void *arg) 61 { 62 // TODO: checks 63 64 usb_log_debug(NAME " Got keys from parser (report id: %u): %s\n", 65 report_id, usb_debug_str_buffer(key_codes, count, 0)); 146 //static void usb_lgtch_process_keycodes(const uint8_t *key_codes, size_t count, 147 // uint8_t report_id, void *arg); 148 149 //static const usb_hid_report_in_callbacks_t usb_lgtch_parser_callbacks = { 150 // .keyboard = usb_lgtch_process_keycodes 151 //}; 152 153 ///*----------------------------------------------------------------------------*/ 154 155 //static void usb_lgtch_process_keycodes(const uint8_t *key_codes, size_t count, 156 // uint8_t report_id, void *arg) 157 //{ 158 // // TODO: checks 159 160 // usb_log_debug(NAME " Got keys from parser (report id: %u): %s\n", 161 // report_id, usb_debug_str_buffer(key_codes, count, 0)); 162 //} 163 164 /*----------------------------------------------------------------------------*/ 165 /** 166 * Processes key events. 167 * 168 * @note This function was copied from AT keyboard driver and modified to suit 169 * USB keyboard. 170 * 171 * @note Lock keys are not sent to the console, as they are completely handled 172 * in the driver. It may, however, be required later that the driver 173 * sends also these keys to application (otherwise it cannot use those 174 * keys at all). 175 * 176 * @param hid_dev 177 * @param lgtch_dev 178 * @param type Type of the event (press / release). Recognized values: 179 * KEY_PRESS, KEY_RELEASE 180 * @param key Key code of the key according to HID Usage Tables. 181 */ 182 static void usb_lgtch_push_ev(usb_hid_dev_t *hid_dev, int type, 183 unsigned int key) 184 { 185 assert(hid_dev != NULL); 186 assert(hid_dev->data != NULL); 187 188 usb_lgtch_ultrax_t *lgtch_dev = (usb_lgtch_ultrax_t *)hid_dev->data; 189 190 console_event_t ev; 191 192 ev.type = type; 193 ev.key = key; 194 ev.mods = 0; 195 196 ev.c = 0; 197 198 usb_log_debug2(NAME " Sending key %d to the console\n", ev.key); 199 if (lgtch_dev->console_phone < 0) { 200 usb_log_warning( 201 "Connection to console not ready, key discarded.\n"); 202 return; 203 } 204 205 async_msg_4(lgtch_dev->console_phone, KBD_EVENT, ev.type, ev.key, 206 ev.mods, ev.c); 207 } 208 209 /*----------------------------------------------------------------------------*/ 210 211 static void usb_lgtch_free(usb_lgtch_ultrax_t **lgtch_dev) 212 { 213 if (lgtch_dev == NULL || *lgtch_dev == NULL) { 214 return; 215 } 216 217 // hangup phone to the console 218 async_hangup((*lgtch_dev)->console_phone); 219 220 // if ((*lgtch_dev)->repeat_mtx != NULL) { 221 // /* TODO: replace by some check and wait */ 222 // assert(!fibril_mutex_is_locked((*lgtch_dev)->repeat_mtx)); 223 // free((*lgtch_dev)->repeat_mtx); 224 // } 225 226 // free all buffers 227 if ((*lgtch_dev)->keys != NULL) { 228 free((*lgtch_dev)->keys); 229 } 230 if ((*lgtch_dev)->keys_old != NULL) { 231 free((*lgtch_dev)->keys_old); 232 } 233 234 free(*lgtch_dev); 235 *lgtch_dev = NULL; 236 } 237 238 /*----------------------------------------------------------------------------*/ 239 240 static int usb_lgtch_create_function(usb_hid_dev_t *hid_dev) 241 { 242 /* Create the function exposed under /dev/devices. */ 243 ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed, 244 NAME); 245 if (fun == NULL) { 246 usb_log_error("Could not create DDF function node.\n"); 247 return ENOMEM; 248 } 249 250 /* 251 * Store the initialized HID device and HID ops 252 * to the DDF function. 253 */ 254 fun->ops = &lgtch_ultrax_ops; 255 fun->driver_data = hid_dev; // TODO: maybe change to hid_dev->data 256 257 int rc = ddf_fun_bind(fun); 258 if (rc != EOK) { 259 usb_log_error("Could not bind DDF function: %s.\n", 260 str_error(rc)); 261 // TODO: Can / should I destroy the DDF function? 262 ddf_fun_destroy(fun); 263 return rc; 264 } 265 266 rc = ddf_fun_add_to_class(fun, "keyboard"); 267 if (rc != EOK) { 268 usb_log_error( 269 "Could not add DDF function to class 'keyboard': %s.\n", 270 str_error(rc)); 271 // TODO: Can / should I destroy the DDF function? 272 ddf_fun_destroy(fun); 273 return rc; 274 } 275 276 return EOK; 277 } 278 279 /*----------------------------------------------------------------------------*/ 280 281 int usb_lgtch_init(struct usb_hid_dev *hid_dev) 282 { 283 if (hid_dev == NULL || hid_dev->usb_dev == NULL) { 284 return EINVAL; /*! @todo Other return code? */ 285 } 286 287 usb_log_debug(NAME " Initializing HID/lgtch_ultrax structure...\n"); 288 289 usb_lgtch_ultrax_t *lgtch_dev = (usb_lgtch_ultrax_t *)malloc( 290 sizeof(usb_lgtch_ultrax_t)); 291 if (lgtch_dev == NULL) { 292 return ENOMEM; 293 } 294 295 lgtch_dev->console_phone = -1; 296 297 usb_hid_report_path_t *path = usb_hid_report_path(); 298 usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_CONSUMER, 0); 299 300 usb_hid_report_path_set_report_id(path, 1); 301 302 lgtch_dev->key_count = usb_hid_report_input_length( 303 hid_dev->report, path, 304 USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY); 305 usb_hid_report_path_free(path); 306 307 usb_log_debug(NAME " Size of the input report: %zu\n", 308 lgtch_dev->key_count); 309 310 lgtch_dev->keys = (int32_t *)calloc(lgtch_dev->key_count, 311 sizeof(int32_t)); 312 313 if (lgtch_dev->keys == NULL) { 314 usb_log_fatal("No memory!\n"); 315 free(lgtch_dev); 316 return ENOMEM; 317 } 318 319 lgtch_dev->keys_old = 320 (int32_t *)calloc(lgtch_dev->key_count, sizeof(int32_t)); 321 322 if (lgtch_dev->keys_old == NULL) { 323 usb_log_fatal("No memory!\n"); 324 free(lgtch_dev->keys); 325 free(lgtch_dev); 326 return ENOMEM; 327 } 328 329 /*! @todo Autorepeat */ 330 331 // save the KBD device structure into the HID device structure 332 hid_dev->data = lgtch_dev; 333 334 lgtch_dev->initialized = USB_LGTCH_STATUS_INITIALIZED; 335 usb_log_debug(NAME " HID/lgtch_ultrax device structure initialized.\n"); 336 337 int rc = usb_lgtch_create_function(hid_dev); 338 if (rc != EOK) { 339 usb_lgtch_free(&lgtch_dev); 340 return rc; 341 } 342 343 usb_log_debug(NAME " HID/lgtch_ultrax structure initialized.\n"); 344 345 return EOK; 346 } 347 348 /*----------------------------------------------------------------------------*/ 349 350 void usb_lgtch_deinit(struct usb_hid_dev *hid_dev) 351 { 352 if (hid_dev == NULL) { 353 return; 354 } 355 356 if (hid_dev->data != NULL) { 357 usb_lgtch_ultrax_t *lgtch_dev = 358 (usb_lgtch_ultrax_t *)hid_dev->data; 359 // if (usb_kbd_is_initialized(kbd_dev)) { 360 // usb_kbd_mark_unusable(kbd_dev); 361 // } else { 362 usb_lgtch_free(&lgtch_dev); 363 hid_dev->data = NULL; 364 // } 365 } 66 366 } 67 367 … … 81 381 usb_hid_report_path_t *path = usb_hid_report_path(); 82 382 usb_hid_report_path_append_item(path, 0xc, 0); 83 usb_hid_report_path_set_report_id(path, 1); 84 85 int rc = usb_hid_parse_report(hid_dev->parser, buffer, 86 buffer_size, path, 87 USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 88 &usb_lgtch_parser_callbacks, hid_dev); 383 384 uint8_t report_id; 385 386 int rc = usb_hid_parse_report(hid_dev->report, buffer, buffer_size, 387 &report_id); 388 389 if (rc != EOK) { 390 usb_log_warning(NAME "Error in usb_hid_parse_report(): %s\n", 391 str_error(rc)); 392 return true; 393 } 394 395 usb_hid_report_path_set_report_id(path, report_id); 396 397 usb_hid_report_field_t *field = usb_hid_report_get_sibling( 398 hid_dev->report, NULL, path, USB_HID_PATH_COMPARE_END 399 | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 400 USB_HID_REPORT_TYPE_INPUT); 401 402 unsigned int key; 403 404 /*! @todo Is this iterating OK if done multiple times? 405 * @todo The parsing is not OK 406 */ 407 while (field != NULL) { 408 usb_log_debug(NAME " KEY VALUE(%X) USAGE(%X)\n", field->value, 409 field->usage); 410 411 key = usb_lgtch_map_usage(field->usage); 412 usb_lgtch_push_ev(hid_dev, KEY_PRESS, key); 413 414 field = usb_hid_report_get_sibling( 415 hid_dev->report, field, path, USB_HID_PATH_COMPARE_END 416 | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 417 USB_HID_REPORT_TYPE_INPUT); 418 } 89 419 90 420 usb_hid_report_path_free(path); 91 92 if (rc != EOK) {93 usb_log_warning("Error in usb_hid_boot_keyboard_input_report():"94 "%s\n", str_error(rc));95 }96 421 97 422 return true; -
uspace/drv/usbhid/lgtch-ultrax/lgtch-ultrax.h
ra58dd620 r3d4aa055 40 40 41 41 struct usb_hid_dev; 42 //struct usb_hid_subdriver_mapping;43 42 44 43 /*----------------------------------------------------------------------------*/ 45 44 46 //extern struct usb_hid_subdriver_mapping usb_lgtch_mapping;45 int usb_lgtch_init(struct usb_hid_dev *hid_dev); 47 46 48 /*----------------------------------------------------------------------------*/ 49 50 //int usb_lgtch_init(struct usb_hid_dev *hid_dev); 47 void usb_lgtch_deinit(struct usb_hid_dev *hid_dev); 51 48 52 49 bool usb_lgtch_polling_callback(struct usb_hid_dev *hid_dev, uint8_t *buffer, -
uspace/drv/usbhid/main.c
ra58dd620 r3d4aa055 99 99 usb_log_debug("USB/HID device structure initialized.\n"); 100 100 101 /* Create the function exposed under /dev/devices. */102 ddf_fun_t *hid_fun = ddf_fun_create(dev->ddf_dev, fun_exposed,103 usb_hid_get_function_name(hid_dev));104 if (hid_fun == NULL) {105 usb_log_error("Could not create DDF function node.\n");106 usb_hid_free(&hid_dev);107 return ENOMEM;108 }109 110 101 /* 111 * Store the initialized HID device and HID ops 112 * to the DDF function. 113 */ 114 hid_fun->ops = &hid_dev->ops; 115 hid_fun->driver_data = hid_dev; // TODO: maybe change to hid_dev->data 116 117 rc = ddf_fun_bind(hid_fun); 118 if (rc != EOK) { 119 usb_log_error("Could not bind DDF function: %s.\n", 120 str_error(rc)); 121 // TODO: Can / should I destroy the DDF function? 122 ddf_fun_destroy(hid_fun); 123 usb_hid_free(&hid_dev); 124 return rc; 125 } 126 127 rc = ddf_fun_add_to_class(hid_fun, usb_hid_get_class_name(hid_dev)); 128 if (rc != EOK) { 129 usb_log_error( 130 "Could not add DDF function to class 'hid': %s.\n", 131 str_error(rc)); 132 // TODO: Can / should I destroy the DDF function? 133 ddf_fun_destroy(hid_fun); 134 usb_hid_free(&hid_dev); 135 return rc; 136 } 102 * 1) subdriver vytvori vlastnu ddf_fun, vlastne ddf_dev_ops, ktore da 103 * do nej. 104 * 2) do tych ops do .interfaces[DEV_IFACE_USBHID (asi)] priradi 105 * vyplnenu strukturu usbhid_iface_t. 106 * 3) klientska aplikacia - musi si rucne vytvorit telefon 107 * (devman_device_connect() - cesta k zariadeniu (/hw/pci0/...) az 108 * k tej fcii. 109 * pouzit usb/classes/hid/iface.h - prvy int je telefon 110 */ 137 111 138 112 /* Start automated polling function. -
uspace/drv/usbhid/mouse/mousedev.c
ra58dd620 r3d4aa055 39 39 #include <usb/classes/hid.h> 40 40 #include <usb/classes/hidreq.h> 41 #include <usb/classes/hidut.h> 41 42 #include <errno.h> 42 43 #include <str_error.h> … … 45 46 #include "mousedev.h" 46 47 #include "../usbhid.h" 48 49 #define NAME "mouse" 47 50 48 51 /*----------------------------------------------------------------------------*/ … … 62 65 /** Default idle rate for mouses. */ 63 66 static const uint8_t IDLE_RATE = 0; 67 static const size_t USB_MOUSE_BUTTON_COUNT = 3; 64 68 65 69 /*----------------------------------------------------------------------------*/ … … 170 174 /*----------------------------------------------------------------------------*/ 171 175 172 static bool usb_mouse_process_boot_report(usb_ mouse_t *mouse_dev,176 static bool usb_mouse_process_boot_report(usb_hid_dev_t *hid_dev, 173 177 uint8_t *buffer, size_t buffer_size) 174 178 { 179 usb_mouse_t *mouse_dev = (usb_mouse_t *)hid_dev->data; 180 175 181 usb_log_debug2("got buffer: %s.\n", 176 182 usb_debug_str_buffer(buffer, buffer_size, 0)); 177 178 uint8_t butt = buffer[0]; 179 char str_buttons[4] = { 180 butt & 1 ? '#' : '.', 181 butt & 2 ? '#' : '.', 182 butt & 4 ? '#' : '.', 183 0 184 }; 185 186 int shift_x = ((int) buffer[1]) - 127; 187 int shift_y = ((int) buffer[2]) - 127; 188 int wheel = ((int) buffer[3]) - 127; 189 190 if (buffer[1] == 0) { 191 shift_x = 0; 192 } 193 if (buffer[2] == 0) { 194 shift_y = 0; 195 } 196 if (buffer[3] == 0) { 197 wheel = 0; 198 } 199 200 if (mouse_dev->console_phone >= 0) { 201 usb_log_debug("Console phone: %d\n", mouse_dev->console_phone); 202 if ((shift_x != 0) || (shift_y != 0)) { 203 /* FIXME: guessed for QEMU */ 183 184 if (mouse_dev->console_phone < 0) { 185 usb_log_error(NAME " No console phone.\n"); 186 return false; // ?? 187 } 188 189 /* 190 * parse the input report 191 */ 192 193 usb_log_debug(NAME " Calling usb_hid_parse_report() with " 194 "buffer %s\n", usb_debug_str_buffer(buffer, buffer_size, 0)); 195 196 uint8_t report_id; 197 198 int rc = usb_hid_parse_report(hid_dev->report, buffer, buffer_size, 199 &report_id); 200 201 if (rc != EOK) { 202 usb_log_warning(NAME "Error in usb_hid_parse_report(): %s\n", 203 str_error(rc)); 204 return true; 205 } 206 207 /* 208 * X 209 */ 210 int shift_x = 0; 211 212 usb_hid_report_path_t *path = usb_hid_report_path(); 213 usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_GENERIC_DESKTOP, 214 USB_HIDUT_USAGE_GENERIC_DESKTOP_X); 215 216 usb_hid_report_path_set_report_id(path, report_id); 217 218 usb_hid_report_field_t *field = usb_hid_report_get_sibling( 219 hid_dev->report, NULL, path, USB_HID_PATH_COMPARE_END, 220 USB_HID_REPORT_TYPE_INPUT); 221 222 if (field != NULL) { 223 usb_log_debug(NAME " VALUE(%X) USAGE(%X)\n", field->value, 224 field->usage); 225 shift_x = field->value; 226 } 227 228 usb_hid_report_path_free(path); 229 230 /* 231 * Y 232 */ 233 int shift_y = 0; 234 235 path = usb_hid_report_path(); 236 usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_GENERIC_DESKTOP, 237 USB_HIDUT_USAGE_GENERIC_DESKTOP_Y); 238 239 usb_hid_report_path_set_report_id(path, report_id); 240 241 field = usb_hid_report_get_sibling( 242 hid_dev->report, NULL, path, USB_HID_PATH_COMPARE_END, 243 USB_HID_REPORT_TYPE_INPUT); 244 245 if (field != NULL) { 246 usb_log_debug(NAME " VALUE(%X) USAGE(%X)\n", field->value, 247 field->usage); 248 shift_y = field->value; 249 } 250 251 usb_hid_report_path_free(path); 252 253 if ((shift_x != 0) || (shift_y != 0)) { 254 async_req_2_0(mouse_dev->console_phone, 255 MEVENT_MOVE, shift_x, shift_y); 256 } 257 258 /* 259 * Buttons 260 */ 261 path = usb_hid_report_path(); 262 usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_BUTTON, 0); 263 usb_hid_report_path_set_report_id(path, report_id); 264 265 field = usb_hid_report_get_sibling( 266 hid_dev->report, NULL, path, USB_HID_PATH_COMPARE_END 267 | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 268 USB_HID_REPORT_TYPE_INPUT); 269 270 while (field != NULL) { 271 usb_log_debug(NAME " VALUE(%X) USAGE(%X)\n", field->value, 272 field->usage); 273 274 if (mouse_dev->buttons[field->usage - field->usage_minimum] == 0 275 && field->value != 0) { 204 276 async_req_2_0(mouse_dev->console_phone, 205 MEVENT_MOVE, 206 - shift_x / 10, - shift_y / 10); 207 } else { 208 usb_log_error("No move reported\n"); 209 } 210 if (butt) { 211 /* FIXME: proper button clicking. */ 212 async_req_2_0(mouse_dev->console_phone, 213 MEVENT_BUTTON, 1, 1); 214 async_req_2_0(mouse_dev->console_phone, 215 MEVENT_BUTTON, 1, 0); 216 } 217 } else { 218 usb_log_error("No console phone in mouse!!\n"); 219 } 220 221 usb_log_debug("buttons=%s dX=%+3d dY=%+3d wheel=%+3d\n", 222 str_buttons, shift_x, shift_y, wheel); 223 224 /* Guess. */ 225 //async_usleep(1000); 226 // no sleep right now 277 MEVENT_BUTTON, field->usage, 1); 278 mouse_dev->buttons[field->usage - field->usage_minimum] 279 = field->value; 280 } else if ( 281 mouse_dev->buttons[field->usage - field->usage_minimum] != 0 282 && field->value == 0) { 283 async_req_2_0(mouse_dev->console_phone, 284 MEVENT_BUTTON, field->usage, 0); 285 mouse_dev->buttons[field->usage - field->usage_minimum] 286 = field->value; 287 } 288 289 field = usb_hid_report_get_sibling( 290 hid_dev->report, field, path, USB_HID_PATH_COMPARE_END 291 | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 292 USB_HID_REPORT_TYPE_INPUT); 293 } 294 295 usb_hid_report_path_free(path); 227 296 228 297 return true; 298 } 299 300 /*----------------------------------------------------------------------------*/ 301 302 static int usb_mouse_create_function(usb_hid_dev_t *hid_dev) 303 { 304 /* Create the function exposed under /dev/devices. */ 305 usb_log_debug("Creating DDF function %s...\n", HID_MOUSE_FUN_NAME); 306 ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed, 307 HID_MOUSE_FUN_NAME); 308 if (fun == NULL) { 309 usb_log_error("Could not create DDF function node.\n"); 310 return ENOMEM; 311 } 312 313 /* 314 * Store the initialized HID device and HID ops 315 * to the DDF function. 316 */ 317 fun->ops = &hid_dev->ops; 318 fun->driver_data = hid_dev; // TODO: maybe change to hid_dev->data 319 320 int rc = ddf_fun_bind(fun); 321 if (rc != EOK) { 322 usb_log_error("Could not bind DDF function: %s.\n", 323 str_error(rc)); 324 ddf_fun_destroy(fun); 325 return rc; 326 } 327 328 usb_log_debug("Adding DDF function to class %s...\n", 329 HID_MOUSE_CLASS_NAME); 330 rc = ddf_fun_add_to_class(fun, HID_MOUSE_CLASS_NAME); 331 if (rc != EOK) { 332 usb_log_error( 333 "Could not add DDF function to class %s: %s.\n", 334 HID_MOUSE_CLASS_NAME, str_error(rc)); 335 ddf_fun_destroy(fun); 336 return rc; 337 } 338 339 return EOK; 229 340 } 230 341 … … 248 359 } 249 360 361 mouse_dev->buttons = (int32_t *)calloc(USB_MOUSE_BUTTON_COUNT, 362 sizeof(int32_t)); 363 364 if (mouse_dev->buttons == NULL) { 365 usb_log_fatal("No memory!\n"); 366 free(mouse_dev); 367 return ENOMEM; 368 } 369 250 370 // save the Mouse device structure into the HID device structure 251 371 hid_dev->data = mouse_dev; … … 255 375 256 376 // TODO: how to know if the device supports the request??? 257 usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe, 258 hid_dev->usb_dev->interface_no, IDLE_RATE); 377 // usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe, 378 // hid_dev->usb_dev->interface_no, IDLE_RATE); 379 380 int rc = usb_mouse_create_function(hid_dev); 381 if (rc != EOK) { 382 usb_mouse_free(&mouse_dev); 383 return rc; 384 } 259 385 260 386 return EOK; … … 280 406 return false; 281 407 } 282 usb_mouse_t *mouse_dev = (usb_mouse_t *)hid_dev->data; 283 284 return usb_mouse_process_boot_report(mouse_dev, buffer, buffer_size); 408 409 return usb_mouse_process_boot_report(hid_dev, buffer, buffer_size); 285 410 } 286 411 … … 296 421 int usb_mouse_set_boot_protocol(usb_hid_dev_t *hid_dev) 297 422 { 298 int rc = usb_hid_parse_report_descriptor(hid_dev-> parser,423 int rc = usb_hid_parse_report_descriptor(hid_dev->report, 299 424 USB_MOUSE_BOOT_REPORT_DESCRIPTOR, 300 425 USB_MOUSE_BOOT_REPORT_DESCRIPTOR_SIZE); -
uspace/drv/usbhid/mouse/mousedev.h
ra58dd620 r3d4aa055 49 49 /** IPC phone to console (consumer). */ 50 50 int console_phone; 51 52 int32_t *buttons; 51 53 } usb_mouse_t; 52 54 -
uspace/drv/usbhid/subdrivers.c
ra58dd620 r3d4aa055 55 55 USB_HID_PATH_COMPARE_END 56 56 | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 57 0,58 0,57 -1, 58 -1, 59 59 { 60 60 .init = usb_kbd_init, … … 73 73 0xc30e, 74 74 { 75 .init = NULL,76 .deinit = NULL,75 .init = usb_lgtch_init, 76 .deinit = usb_lgtch_deinit, 77 77 .poll = usb_lgtch_polling_callback, 78 78 .poll_end = NULL 79 79 } 80 80 }, 81 {NULL, -1, 0, 0, 0, {NULL, NULL, NULL, NULL}}81 {NULL, -1, 0, -1, -1, {NULL, NULL, NULL, NULL}} 82 82 }; 83 83 -
uspace/drv/usbhid/subdrivers.h
ra58dd620 r3d4aa055 56 56 int report_id; 57 57 int compare; 58 uint16_t vendor_id;59 uint16_t product_id;58 int vendor_id; 59 int product_id; 60 60 usb_hid_subdriver_t subdriver; 61 61 } usb_hid_subdriver_mapping_t; -
uspace/drv/usbhid/usbhid.c
ra58dd620 r3d4aa055 136 136 137 137 // set the init callback 138 hid_dev->subdrivers[0].init = NULL;138 hid_dev->subdrivers[0].init = usb_generic_hid_init; 139 139 140 140 // set the polling callback … … 158 158 const usb_hid_subdriver_mapping_t *mapping) 159 159 { 160 return false; 160 assert(hid_dev != NULL); 161 assert(hid_dev->usb_dev != NULL); 162 163 return (hid_dev->usb_dev->descriptors.device.vendor_id 164 == mapping->vendor_id 165 && hid_dev->usb_dev->descriptors.device.product_id 166 == mapping->product_id); 161 167 } 162 168 … … 192 198 } 193 199 194 assert(hid_dev-> parser!= NULL);200 assert(hid_dev->report != NULL); 195 201 196 202 usb_log_debug("Compare flags: %d\n", mapping->compare); 197 size_t size = usb_hid_report_input_length(hid_dev-> parser, usage_path,203 size_t size = usb_hid_report_input_length(hid_dev->report, usage_path, 198 204 mapping->compare); 199 205 usb_log_debug("Size of the input report: %zuB\n", size); … … 251 257 while (count < USB_HID_MAX_SUBDRIVERS && 252 258 (mapping->usage_path != NULL 253 || mapping->vendor_id != 0 || mapping->product_id != 0)) {259 || mapping->vendor_id >= 0 || mapping->product_id >= 0)) { 254 260 // check the vendor & product ID 255 if (mapping->vendor_id != 0 && mapping->product_id ==0) {256 usb_log_warning("Missing Product ID for Vendor ID % u\n",261 if (mapping->vendor_id >= 0 && mapping->product_id < 0) { 262 usb_log_warning("Missing Product ID for Vendor ID %d\n", 257 263 mapping->vendor_id); 258 264 return EINVAL; 259 265 } 260 if (mapping->product_id != 0 && mapping->vendor_id ==0) {261 usb_log_warning("Missing Vendor ID for Product ID % u\n",266 if (mapping->product_id >= 0 && mapping->vendor_id < 0) { 267 usb_log_warning("Missing Vendor ID for Product ID %d\n", 262 268 mapping->product_id); 263 269 return EINVAL; … … 267 273 matched = false; 268 274 269 if (mapping->vendor_id != 0) {270 assert(mapping->product_id != 0);275 if (mapping->vendor_id >= 0) { 276 assert(mapping->product_id >= 0); 271 277 usb_log_debug("Comparing device against vendor ID %u" 272 278 " and product ID %u.\n", mapping->vendor_id, … … 341 347 } 342 348 343 hid_dev-> parser = (usb_hid_report_parser_t *)(malloc(sizeof(344 usb_hid_report_ parser_t)));345 if (hid_dev-> parser== NULL) {349 hid_dev->report = (usb_hid_report_t *)(malloc(sizeof( 350 usb_hid_report_t))); 351 if (hid_dev->report == NULL) { 346 352 usb_log_fatal("No memory!\n"); 347 353 free(hid_dev); … … 382 388 return rc; 383 389 } 384 385 /* Initialize the report parser. */ 386 rc = usb_hid_parser_init(hid_dev->parser); 387 if (rc != EOK) { 388 usb_log_error("Failed to initialize report parser.\n"); 389 //usb_hid_free(&hid_dev); 390 return rc; 391 } 392 390 393 391 /* Get the report descriptor and parse it. */ 394 392 rc = usb_hid_process_report_descriptor(hid_dev->usb_dev, 395 hid_dev-> parser);393 hid_dev->report); 396 394 397 395 bool fallback = false; … … 492 490 usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg; 493 491 492 int allocated = (hid_dev->input_report != NULL); 493 494 if (!allocated 495 || hid_dev->input_report_size < buffer_size) { 496 uint8_t *input_old = hid_dev->input_report; 497 uint8_t *input_new = (uint8_t *)malloc(buffer_size); 498 499 if (input_new == NULL) { 500 usb_log_error("Failed to allocate space for input " 501 "buffer. This event may not be reported\n"); 502 memset(hid_dev->input_report, 0, 503 hid_dev->input_report_size); 504 } else { 505 memcpy(input_new, input_old, 506 hid_dev->input_report_size); 507 hid_dev->input_report = input_new; 508 if (allocated) { 509 free(input_old); 510 } 511 } 512 } 513 514 /*! @todo This should probably be atomic. */ 515 memcpy(hid_dev->input_report, buffer, buffer_size); 516 hid_dev->input_report_size = buffer_size; 517 494 518 bool cont = false; 495 519 … … 530 554 /*----------------------------------------------------------------------------*/ 531 555 532 const char *usb_hid_get_function_name(const usb_hid_dev_t *hid_dev)533 {534 switch (hid_dev->poll_pipe_index) {535 case USB_HID_KBD_POLL_EP_NO:536 return HID_KBD_FUN_NAME;537 break;538 case USB_HID_MOUSE_POLL_EP_NO:539 return HID_MOUSE_FUN_NAME;540 break;541 default:542 return HID_GENERIC_FUN_NAME;543 }544 }545 546 /*----------------------------------------------------------------------------*/ 547 548 const char *usb_hid_get_class_name(const usb_hid_dev_t *hid_dev)549 {550 // this means that only boot protocol keyboards will be connected551 // to the console; there is probably no better way to do this552 553 switch (hid_dev->poll_pipe_index) {554 case USB_HID_KBD_POLL_EP_NO:555 return HID_KBD_CLASS_NAME;556 break;557 case USB_HID_MOUSE_POLL_EP_NO:558 return HID_MOUSE_CLASS_NAME;559 break;560 default:561 return HID_GENERIC_CLASS_NAME;562 }563 }556 //const char *usb_hid_get_function_name(const usb_hid_dev_t *hid_dev) 557 //{ 558 // switch (hid_dev->poll_pipe_index) { 559 // case USB_HID_KBD_POLL_EP_NO: 560 // return HID_KBD_FUN_NAME; 561 // break; 562 // case USB_HID_MOUSE_POLL_EP_NO: 563 // return HID_MOUSE_FUN_NAME; 564 // break; 565 // default: 566 // return HID_GENERIC_FUN_NAME; 567 // } 568 //} 569 570 /*----------------------------------------------------------------------------*/ 571 572 //const char *usb_hid_get_class_name(const usb_hid_dev_t *hid_dev) 573 //{ 574 // // this means that only boot protocol keyboards will be connected 575 // // to the console; there is probably no better way to do this 576 577 // switch (hid_dev->poll_pipe_index) { 578 // case USB_HID_KBD_POLL_EP_NO: 579 // return HID_KBD_CLASS_NAME; 580 // break; 581 // case USB_HID_MOUSE_POLL_EP_NO: 582 // return HID_MOUSE_CLASS_NAME; 583 // break; 584 // default: 585 // return HID_GENERIC_CLASS_NAME; 586 // } 587 //} 564 588 565 589 /*----------------------------------------------------------------------------*/ … … 591 615 592 616 // destroy the parser 593 if ((*hid_dev)-> parser!= NULL) {594 usb_hid_free_report _parser((*hid_dev)->parser);617 if ((*hid_dev)->report != NULL) { 618 usb_hid_free_report((*hid_dev)->report); 595 619 } 596 620 -
uspace/drv/usbhid/usbhid.h
ra58dd620 r3d4aa055 91 91 92 92 /** HID Report parser. */ 93 usb_hid_report_parser_t *parser; 93 usb_hid_report_t *report; 94 95 uint8_t *input_report; 96 97 size_t input_report_size; 94 98 95 99 /** Arbitrary data (e.g. a special structure for handling keyboard). */ … … 120 124 void *arg); 121 125 122 const char *usb_hid_get_function_name(const usb_hid_dev_t *hid_dev);126 //const char *usb_hid_get_function_name(const usb_hid_dev_t *hid_dev); 123 127 124 const char *usb_hid_get_class_name(const usb_hid_dev_t *hid_dev);128 //const char *usb_hid_get_class_name(const usb_hid_dev_t *hid_dev); 125 129 126 130 void usb_hid_free(usb_hid_dev_t **hid_dev); -
uspace/drv/usbhub/main.c
ra58dd620 r3d4aa055 55 55 }; 56 56 57 57 /** 58 * usb hub driver operations 59 * 60 * The most important one is add_device, which is set to usb_hub_add_device. 61 */ 58 62 static usb_driver_ops_t usb_hub_driver_ops = { 59 63 .add_device = usb_hub_add_device 60 64 }; 61 65 66 /** 67 * hub endpoints, excluding control endpoint 68 */ 62 69 static usb_endpoint_description_t *usb_hub_endpoints[] = { 63 70 &hub_status_change_endpoint_description, … … 65 72 }; 66 73 74 /** 75 * static usb hub driver information 76 */ 67 77 static usb_driver_t usb_hub_driver = { 68 78 .name = NAME, -
uspace/drv/usbhub/ports.c
ra58dd620 r3d4aa055 167 167 168 168 //close address 169 //if (hub->attached_devs[port].address != 0) {170 169 if(hub->ports[port].attached_device.address >= 0){ 171 170 /*uncomment this code to use it when DDF allows device removal … … 182 181 */ 183 182 } else { 184 // TODO: is this really reason to print a warning?185 183 usb_log_warning("Device removed before being registered.\n"); 186 184 -
uspace/drv/usbhub/usbhub.c
ra58dd620 r3d4aa055 73 73 74 74 75 /// \TODO malloc checking76 77 75 //********************************************* 78 76 // … … 248 246 hub_info->ports = malloc( 249 247 sizeof (usb_hub_port_t) * (hub_info->port_count + 1)); 248 if(!hub_info->ports){ 249 return ENOMEM; 250 } 250 251 size_t port; 251 252 for (port = 0; port < hub_info->port_count + 1; ++port) { … … 255 256 usb_log_debug("is_power_switched\n"); 256 257 257 for (port = 1; port <= hub_info->port_count; ++port) {258 usb_log_debug("powering port %d\n",port);259 opResult = usb_hub_set_port_feature(hub_info->control_pipe,260 port, USB_HUB_FEATURE_PORT_POWER);261 if (opResult != EOK) {262 usb_log_error("cannot power on port %zu: %s.\n",263 port, str_error(opResult));264 }265 }266 258 if(!has_individual_port_powering){ 267 259 usb_log_debug("!has_individual_port_powering\n"); … … 273 265 } 274 266 } 267 268 for (port = 1; port <= hub_info->port_count; ++port) { 269 usb_log_debug("Powering port %zu.\n",port); 270 opResult = usb_hub_set_port_feature(hub_info->control_pipe, 271 port, USB_HUB_FEATURE_PORT_POWER); 272 if (opResult != EOK) { 273 usb_log_error("cannot power on port %zu: %s.\n", 274 port, str_error(opResult)); 275 } 276 } 277 275 278 }else{ 276 usb_log_debug("!is_power_switched \n");279 usb_log_debug("!is_power_switched, not going to be powered\n"); 277 280 } 278 281 usb_log_debug2("freeing data\n"); … … 408 411 static int usb_process_hub_power_change(usb_hub_info_t * hub_info, 409 412 usb_hub_status_t status) { 410 int opResult ;413 int opResult = EOK; 411 414 if (!usb_hub_is_status(status,USB_HUB_FEATURE_HUB_LOCAL_POWER)) { 412 415 //restart power on hub … … 428 431 } 429 432 } 430 opResult = usb_hub_clear_feature(hub_info->control_pipe, 431 USB_HUB_FEATURE_C_HUB_LOCAL_POWER); 433 } 434 if(opResult!=EOK){ 435 return opResult;//no feature clearing 436 } 437 opResult = usb_hub_clear_feature(hub_info->control_pipe, 438 USB_HUB_FEATURE_C_HUB_LOCAL_POWER); 432 439 if (opResult != EOK) { 433 usb_log_error("cannnot clear hub power change flag: " 434 "%d\n", 435 opResult); 436 } 440 usb_log_error("cannnot clear hub power change flag: " 441 "%d\n", 442 opResult); 437 443 } 438 444 return opResult; -
uspace/drv/usbkbd/kbddev.c
ra58dd620 r3d4aa055 128 128 0x15, 0x00, // Logical Minimum (0), 129 129 0x25, 0x01, // Logical Maximum (1), 130 //0x85, 0x00, // Report ID, 131 //0xA4, // Push 130 132 0x81, 0x02, // Input (Data, Variable, Absolute), ; Modifier byte 131 0x95, 0x01, // Report Count (1), 132 0x75, 0x08, // Report Size (8), 133 //0xB4, // Pop 134 0x75, 0x08, // Report Size (1), 135 0x95, 0x01, // Report Count (8), 133 136 0x81, 0x01, // Input (Constant), ; Reserved byte 134 137 0x95, 0x05, // Report Count (5), … … 268 271 return; 269 272 } 270 273 271 274 unsigned i = 0; 272 275 … … 290 293 291 294 usb_log_debug("Creating output report.\n"); 292 293 int rc = usb_hid_report_output_translate(kbd_dev->parser,294 kbd_dev->led_path,295 USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,296 kbd_dev->output_buffer,297 kbd_dev->output_ size, kbd_dev->led_data, kbd_dev->led_output_size);295 296 //usb_hid_report_output_set_data(kbd_dev->parser, kbd_dev->led_path, 297 // USB_HID_PATH_COMPARE_END , kbd_dev->led_data, 298 // kbd_dev->led_output_size); 299 int rc = usb_hid_report_output_translate(kbd_dev->parser, 0, 300 kbd_dev->output_buffer, kbd_dev->output_size); 298 301 299 302 if (rc != EOK) { … … 563 566 assert(kbd_dev != NULL); 564 567 565 usb_log_debug("Got keys from parser (report id: % u): %s\n",566 report_id,usb_debug_str_buffer(key_codes, count, 0));568 usb_log_debug("Got keys from parser (report id: %d): %s\n", report_id, 569 usb_debug_str_buffer(key_codes, count, 0)); 567 570 568 571 if (count != kbd_dev->key_count) { … … 614 617 usb_hid_report_path_t *path = usb_hid_report_path(); 615 618 usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0); 616 usb_hid_report_path_set_report_id(path, 0); 617 618 int rc = usb_hid_parse_report(kbd_dev->parser, buffer, 619 actual_size, path, 620 USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 621 callbacks, kbd_dev); 619 620 uint8_t report_id; 621 int rc = usb_hid_parse_report(kbd_dev->parser, buffer, actual_size, &report_id); 622 usb_hid_descriptor_print (kbd_dev->parser); 622 623 623 624 usb_hid_report_path_free (path); … … 663 664 memset(kbd_dev, 0, sizeof(usb_kbd_t)); 664 665 665 kbd_dev->parser = (usb_hid_report_ parser_t *)(malloc(sizeof(666 usb_hid_report_ parser_t)));666 kbd_dev->parser = (usb_hid_report_t *)(malloc(sizeof( 667 usb_hid_report_t))); 667 668 if (kbd_dev->parser == NULL) { 668 669 usb_log_fatal("No memory!\n"); … … 732 733 733 734 /* Initialize the report parser. */ 734 rc = usb_hid_parser_init(kbd_dev->parser);735 if (rc != EOK) {736 usb_log_error("Failed to initialize report parser.\n");737 return rc;738 }735 //rc = usb_hid_parser_init(kbd_dev->parser); 736 //if (rc != EOK) { 737 // usb_log_error("Failed to initialize report parser.\n"); 738 // return rc; 739 //} 739 740 740 741 /* Get the report descriptor and parse it. */ … … 771 772 772 773 kbd_dev->key_count = usb_hid_report_input_length( 773 kbd_dev->parser, path, 774 USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY); 774 kbd_dev->parser, path, USB_HID_PATH_COMPARE_END); 775 775 usb_hid_report_path_free (path); 776 776 … … 789 789 kbd_dev->output_size = 0; 790 790 kbd_dev->output_buffer = usb_hid_report_output(kbd_dev->parser, 791 &kbd_dev->output_size );792 if (kbd_dev->output_buffer == NULL && kbd_dev->output_size != 0) {791 &kbd_dev->output_size, 0x00); 792 if (kbd_dev->output_buffer == NULL) { 793 793 usb_log_warning("Error creating output report buffer.\n"); 794 794 free(kbd_dev->keys); … … 801 801 usb_hid_report_path_append_item( 802 802 kbd_dev->led_path, USB_HIDUT_PAGE_LED, 0); 803 usb_hid_report_path_set_report_id(kbd_dev->led_path, 0x00); 803 804 804 805 kbd_dev->led_output_size = usb_hid_report_output_size(kbd_dev->parser, … … 849 850 * Set Idle rate 850 851 */ 851 usb_kbd_set_led(kbd_dev); 852 usb_kbd_set_led(kbd_dev); 852 853 853 854 usbhid_req_set_idle(&kbd_dev->usb_dev->ctrl_pipe, … … 934 935 // destroy the parser 935 936 if ((*kbd_dev)->parser != NULL) { 936 usb_hid_free_report _parser((*kbd_dev)->parser);937 usb_hid_free_report((*kbd_dev)->parser); 937 938 } 938 939 -
uspace/drv/usbkbd/kbddev.h
ra58dd620 r3d4aa055 106 106 107 107 /** HID Report parser. */ 108 usb_hid_report_ parser_t *parser;108 usb_hid_report_t *parser; 109 109 110 110 /** State of the structure (for checking before use). -
uspace/drv/vhc/Makefile
ra58dd620 r3d4aa055 39 39 40 40 SOURCES = \ 41 hub/virthub.c \ 41 42 hub/hub.c \ 42 hub/virthub.c \43 43 hub/virthubops.c \ 44 44 conndev.c \ 45 45 connhost.c \ 46 dev ices.c \47 h c.c \48 hcd.c \49 hub.c46 devconn.c \ 47 hub.c \ 48 main.c \ 49 transfer.c 50 50 51 51 include $(USPACE_PREFIX)/Makefile.common -
uspace/drv/vhc/conn.h
ra58dd620 r3d4aa055 40 40 #include <usb_iface.h> 41 41 #include "vhcd.h" 42 #include "devices.h"43 44 void connection_handler_host(sysarg_t);45 42 46 43 extern usbhc_iface_t vhc_iface; 47 44 extern usb_iface_t vhc_usb_iface; 48 45 extern usb_iface_t rh_usb_iface; 49 50 void address_init(void);51 52 46 53 47 void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *); -
uspace/drv/vhc/conndev.c
ra58dd620 r3d4aa055 1 1 /* 2 * Copyright (c) 201 0Vojtech Horky2 * Copyright (c) 2011 Vojtech Horky 3 3 * All rights reserved. 4 4 * … … 31 31 */ 32 32 /** @file 33 * @briefConnection handling of calls from virtual device (implementation).33 * Connection handling of calls from virtual device (implementation). 34 34 */ 35 35 36 36 #include <assert.h> 37 37 #include <errno.h> 38 #include <usbvirt/hub.h> 38 #include <ddf/driver.h> 39 #include "conn.h" 39 40 40 #include "conn.h" 41 #include "hc.h" 42 #include "hub.h" 43 44 #define DEVICE_NAME_MAXLENGTH 32 45 46 static int get_device_name(int phone, char *buffer, size_t len) 47 { 48 ipc_call_t answer_data; 49 sysarg_t answer_rc; 50 aid_t req; 51 int rc; 52 53 req = async_send_0(phone, 54 IPC_M_USBVIRT_GET_NAME, 55 &answer_data); 56 57 rc = async_data_read_start(phone, buffer, len); 58 if (rc != EOK) { 59 async_wait_for(req, NULL); 60 return EINVAL; 61 } 62 63 async_wait_for(req, &answer_rc); 64 rc = (int)answer_rc; 65 66 if (IPC_GET_ARG1(answer_data) < len) { 67 len = IPC_GET_ARG1(answer_data); 68 } else { 69 len--; 70 } 71 buffer[len] = 0; 72 73 return rc; 74 } 41 static fibril_local uintptr_t plugged_device_handle = 0; 75 42 76 43 /** Default handler for IPC methods not handled by DDF. … … 83 50 ipc_callid_t icallid, ipc_call_t *icall) 84 51 { 52 vhc_data_t *vhc = fun->dev->driver_data; 85 53 sysarg_t method = IPC_GET_IMETHOD(*icall); 86 54 87 55 if (method == IPC_M_CONNECT_TO_ME) { 88 56 int callback = IPC_GET_ARG5(*icall); 89 virtdev_connection_t *dev90 = virtdev_add_device(callback, (sysarg_t)fibril_get_id());91 if ( !dev) {92 async_answer_0(icallid, EEXISTS);57 int rc = vhc_virtdev_plug(vhc, callback, 58 &plugged_device_handle); 59 if (rc != EOK) { 60 async_answer_0(icallid, rc); 93 61 async_hangup(callback); 94 62 return; 95 63 } 64 96 65 async_answer_0(icallid, EOK); 97 66 98 char devname[DEVICE_NAME_MAXLENGTH + 1];99 int rc = get_device_name(callback, devname, DEVICE_NAME_MAXLENGTH);100 101 67 usb_log_info("New virtual device `%s' (id = %" PRIxn ").\n", 102 rc == EOK ? devname : "<unknown>", dev->id);68 rc == EOK ? "XXX" : "<unknown>", plugged_device_handle); 103 69 104 70 return; … … 108 74 } 109 75 110 /** Callback for DDFwhen client disconnects.76 /** Callback when client disconnects. 111 77 * 112 * @param fun Device function the client was connected to. 78 * Used to unplug virtual USB device. 79 * 80 * @param fun 113 81 */ 114 82 void on_client_close(ddf_fun_t *fun) 115 83 { 116 /*117 * Maybe a virtual device is being unplugged. 118 */119 virtdev_connection_t *dev = virtdev_find((sysarg_t)fibril_get_id());120 if (dev == NULL) {121 return;84 vhc_data_t *vhc = fun->dev->driver_data; 85 86 if (plugged_device_handle != 0) { 87 usb_log_info("Virtual device disconnected (id = %" PRIxn ").\n", 88 plugged_device_handle); 89 vhc_virtdev_unplug(vhc, plugged_device_handle); 122 90 } 123 124 usb_log_info("Virtual device disconnected (id = %" PRIxn ").\n",125 dev->id);126 virtdev_destroy_device(dev);127 91 } 128 92 -
uspace/drv/vhc/connhost.c
ra58dd620 r3d4aa055 1 1 /* 2 * Copyright (c) 201 0Vojtech Horky2 * Copyright (c) 2011 Vojtech Horky 3 3 * All rights reserved. 4 4 * … … 31 31 */ 32 32 /** @file 33 * @brief Connection handling of calls from host (implementation).33 * Host controller interface implementation. 34 34 */ 35 35 #include <assert.h> … … 38 38 #include <usb/addrkeep.h> 39 39 #include <usb/ddfiface.h> 40 40 #include <usb/debug.h> 41 #include <usbhc_iface.h> 41 42 #include "vhcd.h" 42 #include "conn.h" 43 #include "hc.h" 44 45 46 typedef struct { 47 usb_direction_t direction; 48 usbhc_iface_transfer_out_callback_t out_callback; 49 usbhc_iface_transfer_in_callback_t in_callback; 50 ddf_fun_t *fun; 51 size_t reported_size; 52 void *arg; 53 } transfer_info_t; 54 55 typedef struct { 56 usb_direction_t direction; 57 usb_target_t target; 58 usbhc_iface_transfer_out_callback_t out_callback; 59 usbhc_iface_transfer_in_callback_t in_callback; 60 ddf_fun_t *fun; 61 void *arg; 62 void *data_buffer; 63 size_t data_buffer_size; 64 } control_transfer_info_t; 65 66 static void universal_callback(void *buffer, size_t size, 67 int outcome, void *arg) 68 { 69 transfer_info_t *transfer = (transfer_info_t *) arg; 70 71 if (transfer->reported_size != (size_t) -1) { 72 size = transfer->reported_size; 73 } 74 75 switch (transfer->direction) { 76 case USB_DIRECTION_IN: 77 transfer->in_callback(transfer->fun, 78 outcome, size, 79 transfer->arg); 80 break; 81 case USB_DIRECTION_OUT: 82 transfer->out_callback(transfer->fun, 83 outcome, 84 transfer->arg); 85 break; 86 default: 87 assert(false && "unreachable"); 88 break; 89 } 90 91 free(transfer); 92 } 93 94 static transfer_info_t *create_transfer_info(ddf_fun_t *fun, 95 usb_direction_t direction, void *arg) 96 { 97 transfer_info_t *transfer = malloc(sizeof(transfer_info_t)); 98 99 transfer->direction = direction; 100 transfer->in_callback = NULL; 101 transfer->out_callback = NULL; 102 transfer->arg = arg; 103 transfer->fun = fun; 104 transfer->reported_size = (size_t) -1; 105 106 return transfer; 107 } 108 109 static void control_abort_prematurely(control_transfer_info_t *transfer, 110 size_t size, int outcome) 111 { 112 switch (transfer->direction) { 113 case USB_DIRECTION_IN: 114 transfer->in_callback(transfer->fun, 115 outcome, size, 116 transfer->arg); 117 break; 118 case USB_DIRECTION_OUT: 119 transfer->out_callback(transfer->fun, 120 outcome, 121 transfer->arg); 122 break; 123 default: 124 assert(false && "unreachable"); 125 break; 126 } 127 } 128 129 static void control_callback_two(void *buffer, size_t size, 130 int outcome, void *arg) 131 { 132 control_transfer_info_t *ctrl_transfer = (control_transfer_info_t *) arg; 133 134 if (outcome != EOK) { 135 control_abort_prematurely(ctrl_transfer, outcome, size); 136 free(ctrl_transfer); 137 return; 138 } 139 140 transfer_info_t *transfer = create_transfer_info(ctrl_transfer->fun, 141 ctrl_transfer->direction, ctrl_transfer->arg); 142 transfer->out_callback = ctrl_transfer->out_callback; 143 transfer->in_callback = ctrl_transfer->in_callback; 144 transfer->reported_size = size; 145 146 switch (ctrl_transfer->direction) { 147 case USB_DIRECTION_IN: 148 hc_add_transaction_to_device(false, ctrl_transfer->target, 149 USB_TRANSFER_CONTROL, 150 NULL, 0, 151 universal_callback, transfer); 152 break; 153 case USB_DIRECTION_OUT: 154 hc_add_transaction_from_device(ctrl_transfer->target, 155 USB_TRANSFER_CONTROL, 156 NULL, 0, 157 universal_callback, transfer); 158 break; 159 default: 160 assert(false && "unreachable"); 161 break; 162 } 163 164 free(ctrl_transfer); 165 } 166 167 static void control_callback_one(void *buffer, size_t size, 168 int outcome, void *arg) 169 { 170 control_transfer_info_t *transfer = (control_transfer_info_t *) arg; 171 172 if (outcome != EOK) { 173 control_abort_prematurely(transfer, outcome, size); 174 free(transfer); 175 return; 176 } 177 178 switch (transfer->direction) { 179 case USB_DIRECTION_IN: 180 hc_add_transaction_from_device(transfer->target, 181 USB_TRANSFER_CONTROL, 182 transfer->data_buffer, transfer->data_buffer_size, 183 control_callback_two, transfer); 184 break; 185 case USB_DIRECTION_OUT: 186 hc_add_transaction_to_device(false, transfer->target, 187 USB_TRANSFER_CONTROL, 188 transfer->data_buffer, transfer->data_buffer_size, 189 control_callback_two, transfer); 190 break; 191 default: 192 assert(false && "unreachable"); 193 break; 194 } 195 } 196 197 static control_transfer_info_t *create_control_transfer_info(ddf_fun_t *fun, 198 usb_direction_t direction, usb_target_t target, 199 void *data_buffer, size_t data_buffer_size, 200 void *arg) 201 { 202 control_transfer_info_t *transfer 203 = malloc(sizeof(control_transfer_info_t)); 204 205 transfer->direction = direction; 206 transfer->target = target; 207 transfer->in_callback = NULL; 208 transfer->out_callback = NULL; 209 transfer->arg = arg; 210 transfer->fun = fun; 211 transfer->data_buffer = data_buffer; 212 transfer->data_buffer_size = data_buffer_size; 213 214 return transfer; 215 } 216 217 static int enqueue_transfer_out(ddf_fun_t *fun, 218 usb_target_t target, usb_transfer_type_t transfer_type, 219 void *buffer, size_t size, 220 usbhc_iface_transfer_out_callback_t callback, void *arg) 221 { 222 usb_log_debug2("Transfer OUT [%d.%d (%s); %zu].\n", 223 target.address, target.endpoint, 224 usb_str_transfer_type(transfer_type), 225 size); 226 227 transfer_info_t *transfer 228 = create_transfer_info(fun, USB_DIRECTION_OUT, arg); 229 transfer->out_callback = callback; 230 231 hc_add_transaction_to_device(false, target, transfer_type, buffer, size, 232 universal_callback, transfer); 233 234 return EOK; 235 } 236 237 static int enqueue_transfer_in(ddf_fun_t *fun, 238 usb_target_t target, usb_transfer_type_t transfer_type, 239 void *buffer, size_t size, 240 usbhc_iface_transfer_in_callback_t callback, void *arg) 241 { 242 usb_log_debug2("Transfer IN [%d.%d (%s); %zu].\n", 243 target.address, target.endpoint, 244 usb_str_transfer_type(transfer_type), 245 size); 246 247 transfer_info_t *transfer 248 = create_transfer_info(fun, USB_DIRECTION_IN, arg); 249 transfer->in_callback = callback; 250 251 hc_add_transaction_from_device(target, transfer_type, buffer, size, 252 universal_callback, transfer); 253 254 return EOK; 255 } 256 257 43 44 #define GET_VHC_DATA(fun) \ 45 ((vhc_data_t *)fun->dev->driver_data) 46 #define VHC_DATA(vhc, fun) \ 47 vhc_data_t *vhc = GET_VHC_DATA(fun); assert(vhc->magic == 0xdeadbeef) 48 49 #define UNSUPPORTED(methodname) \ 50 usb_log_warning("Unsupported interface method `%s()' in %s:%d.\n", \ 51 methodname, __FILE__, __LINE__) 52 53 /** Found free USB address. 54 * 55 * @param[in] fun Device function the action was invoked on. 56 * @param[in] speed Speed of the device that will get this address. 57 * @param[out] address Non-null pointer where to store the free address. 58 * @return Error code. 59 */ 60 static int request_address(ddf_fun_t *fun, usb_speed_t speed, 61 usb_address_t *address) 62 { 63 VHC_DATA(vhc, fun); 64 65 usb_address_t addr = device_keeper_get_free_address(&vhc->dev_keeper, 66 USB_SPEED_HIGH); 67 if (addr < 0) { 68 return addr; 69 } 70 71 if (address != NULL) { 72 *address = addr; 73 } 74 75 return EOK; 76 } 77 78 /** Bind USB address with device devman handle. 79 * 80 * @param[in] fun Device function the action was invoked on. 81 * @param[in] address USB address of the device. 82 * @param[in] handle Devman handle of the device. 83 * @return Error code. 84 */ 85 static int bind_address(ddf_fun_t *fun, 86 usb_address_t address, devman_handle_t handle) 87 { 88 VHC_DATA(vhc, fun); 89 usb_log_debug("Binding handle %" PRIun " to address %d.\n", 90 handle, address); 91 usb_device_keeper_bind(&vhc->dev_keeper, address, handle); 92 93 return EOK; 94 } 95 96 /** Release previously requested address. 97 * 98 * @param[in] fun Device function the action was invoked on. 99 * @param[in] address USB address to be released. 100 * @return Error code. 101 */ 102 static int release_address(ddf_fun_t *fun, usb_address_t address) 103 { 104 VHC_DATA(vhc, fun); 105 usb_log_debug("Releasing address %d...\n", address); 106 usb_device_keeper_release(&vhc->dev_keeper, address); 107 108 return ENOTSUP; 109 } 110 111 /** Register endpoint for bandwidth reservation. 112 * 113 * @param[in] fun Device function the action was invoked on. 114 * @param[in] address USB address of the device. 115 * @param[in] speed Endpoint speed (invalid means to use device one). 116 * @param[in] endpoint Endpoint number. 117 * @param[in] transfer_type USB transfer type. 118 * @param[in] direction Endpoint data direction. 119 * @param[in] max_packet_size Max packet size of the endpoint. 120 * @param[in] interval Polling interval. 121 * @return Error code. 122 */ 123 static int register_endpoint(ddf_fun_t *fun, 124 usb_address_t address, usb_speed_t speed, usb_endpoint_t endpoint, 125 usb_transfer_type_t transfer_type, usb_direction_t direction, 126 size_t max_packet_size, unsigned int interval) 127 { 128 VHC_DATA(vhc, fun); 129 130 endpoint_t *ep = malloc(sizeof(endpoint_t)); 131 if (ep == NULL) { 132 return ENOMEM; 133 } 134 135 int rc = endpoint_init(ep, address, endpoint, direction, transfer_type, 136 USB_SPEED_FULL, 1); 137 if (rc != EOK) { 138 free(ep); 139 return rc; 140 } 141 142 rc = usb_endpoint_manager_register_ep(&vhc->ep_manager, ep, 1); 143 if (rc != EOK) { 144 endpoint_destroy(ep); 145 return rc; 146 } 147 148 return EOK; 149 } 150 151 /** Unregister endpoint (free some bandwidth reservation). 152 * 153 * @param[in] fun Device function the action was invoked on. 154 * @param[in] address USB address of the device. 155 * @param[in] endpoint Endpoint number. 156 * @param[in] direction Endpoint data direction. 157 * @return Error code. 158 */ 159 static int unregister_endpoint(ddf_fun_t *fun, usb_address_t address, 160 usb_endpoint_t endpoint, usb_direction_t direction) 161 { 162 VHC_DATA(vhc, fun); 163 164 endpoint_t *ep = usb_endpoint_manager_get_ep(&vhc->ep_manager, 165 address, endpoint, direction, NULL); 166 if (ep == NULL) { 167 return ENOENT; 168 } 169 170 int rc = usb_endpoint_manager_unregister_ep(&vhc->ep_manager, 171 address, endpoint, direction); 172 173 return rc; 174 } 175 176 /** Schedule interrupt out transfer. 177 * 178 * The callback is supposed to be called once the transfer (on the wire) is 179 * complete regardless of the outcome. 180 * However, the callback could be called only when this function returns 181 * with success status (i.e. returns EOK). 182 * 183 * @param[in] fun Device function the action was invoked on. 184 * @param[in] target Target pipe (address and endpoint number) specification. 185 * @param[in] data Data to be sent (in USB endianess, allocated and deallocated 186 * by the caller). 187 * @param[in] size Size of the @p data buffer in bytes. 188 * @param[in] callback Callback to be issued once the transfer is complete. 189 * @param[in] arg Pass-through argument to the callback. 190 * @return Error code. 191 */ 258 192 static int interrupt_out(ddf_fun_t *fun, usb_target_t target, 259 193 void *data, size_t size, 260 194 usbhc_iface_transfer_out_callback_t callback, void *arg) 261 195 { 262 return enqueue_transfer_out(fun, target, USB_TRANSFER_INTERRUPT, 263 data, size, 264 callback, arg); 265 } 266 196 VHC_DATA(vhc, fun); 197 198 vhc_transfer_t *transfer = vhc_transfer_create(target.address, 199 target.endpoint, USB_DIRECTION_OUT, USB_TRANSFER_INTERRUPT, 200 fun, arg); 201 if (transfer == NULL) { 202 return ENOMEM; 203 } 204 205 transfer->data_buffer = data; 206 transfer->data_buffer_size = size; 207 transfer->callback_out = callback; 208 209 int rc = vhc_virtdev_add_transfer(vhc, transfer); 210 if (rc != EOK) { 211 free(transfer); 212 return rc; 213 } 214 215 return EOK; 216 } 217 218 /** Schedule interrupt in transfer. 219 * 220 * The callback is supposed to be called once the transfer (on the wire) is 221 * complete regardless of the outcome. 222 * However, the callback could be called only when this function returns 223 * with success status (i.e. returns EOK). 224 * 225 * @param[in] fun Device function the action was invoked on. 226 * @param[in] target Target pipe (address and endpoint number) specification. 227 * @param[in] data Buffer where to store the data (in USB endianess, 228 * allocated and deallocated by the caller). 229 * @param[in] size Size of the @p data buffer in bytes. 230 * @param[in] callback Callback to be issued once the transfer is complete. 231 * @param[in] arg Pass-through argument to the callback. 232 * @return Error code. 233 */ 267 234 static int interrupt_in(ddf_fun_t *fun, usb_target_t target, 268 235 void *data, size_t size, 269 236 usbhc_iface_transfer_in_callback_t callback, void *arg) 270 237 { 271 return enqueue_transfer_in(fun, target, USB_TRANSFER_INTERRUPT, 272 data, size, 273 callback, arg); 274 } 275 238 VHC_DATA(vhc, fun); 239 240 vhc_transfer_t *transfer = vhc_transfer_create(target.address, 241 target.endpoint, USB_DIRECTION_IN, USB_TRANSFER_INTERRUPT, 242 fun, arg); 243 if (transfer == NULL) { 244 return ENOMEM; 245 } 246 247 transfer->data_buffer = data; 248 transfer->data_buffer_size = size; 249 transfer->callback_in = callback; 250 251 int rc = vhc_virtdev_add_transfer(vhc, transfer); 252 if (rc != EOK) { 253 free(transfer); 254 return rc; 255 } 256 257 return EOK; 258 } 259 260 /** Schedule bulk out transfer. 261 * 262 * The callback is supposed to be called once the transfer (on the wire) is 263 * complete regardless of the outcome. 264 * However, the callback could be called only when this function returns 265 * with success status (i.e. returns EOK). 266 * 267 * @param[in] fun Device function the action was invoked on. 268 * @param[in] target Target pipe (address and endpoint number) specification. 269 * @param[in] data Data to be sent (in USB endianess, allocated and deallocated 270 * by the caller). 271 * @param[in] size Size of the @p data buffer in bytes. 272 * @param[in] callback Callback to be issued once the transfer is complete. 273 * @param[in] arg Pass-through argument to the callback. 274 * @return Error code. 275 */ 276 static int bulk_out(ddf_fun_t *fun, usb_target_t target, 277 void *data, size_t size, 278 usbhc_iface_transfer_out_callback_t callback, void *arg) 279 { 280 UNSUPPORTED("bulk_out"); 281 282 return ENOTSUP; 283 } 284 285 /** Schedule bulk in transfer. 286 * 287 * The callback is supposed to be called once the transfer (on the wire) is 288 * complete regardless of the outcome. 289 * However, the callback could be called only when this function returns 290 * with success status (i.e. returns EOK). 291 * 292 * @param[in] fun Device function the action was invoked on. 293 * @param[in] target Target pipe (address and endpoint number) specification. 294 * @param[in] data Buffer where to store the data (in USB endianess, 295 * allocated and deallocated by the caller). 296 * @param[in] size Size of the @p data buffer in bytes. 297 * @param[in] callback Callback to be issued once the transfer is complete. 298 * @param[in] arg Pass-through argument to the callback. 299 * @return Error code. 300 */ 301 static int bulk_in(ddf_fun_t *fun, usb_target_t target, 302 void *data, size_t size, 303 usbhc_iface_transfer_in_callback_t callback, void *arg) 304 { 305 UNSUPPORTED("bulk_in"); 306 307 return ENOTSUP; 308 } 309 310 /** Schedule control write transfer. 311 * 312 * The callback is supposed to be called once the transfer (on the wire) is 313 * complete regardless of the outcome. 314 * However, the callback could be called only when this function returns 315 * with success status (i.e. returns EOK). 316 * 317 * @param[in] fun Device function the action was invoked on. 318 * @param[in] target Target pipe (address and endpoint number) specification. 319 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated 320 * and deallocated by the caller). 321 * @param[in] setup_packet_size Size of @p setup_packet buffer in bytes. 322 * @param[in] data_buffer Data buffer (in USB endianess, allocated and 323 * deallocated by the caller). 324 * @param[in] data_buffer_size Size of @p data_buffer buffer in bytes. 325 * @param[in] callback Callback to be issued once the transfer is complete. 326 * @param[in] arg Pass-through argument to the callback. 327 * @return Error code. 328 */ 276 329 static int control_write(ddf_fun_t *fun, usb_target_t target, 277 330 void *setup_packet, size_t setup_packet_size, 278 void *data , size_t data_size,331 void *data_buffer, size_t data_buffer_size, 279 332 usbhc_iface_transfer_out_callback_t callback, void *arg) 280 333 { 281 control_transfer_info_t *transfer 282 = create_control_transfer_info(fun, USB_DIRECTION_OUT, target, 283 data, data_size, arg); 284 transfer->out_callback = callback; 285 286 hc_add_transaction_to_device(true, target, USB_TRANSFER_CONTROL, 287 setup_packet, setup_packet_size, 288 control_callback_one, transfer); 289 290 return EOK; 291 } 292 334 VHC_DATA(vhc, fun); 335 336 vhc_transfer_t *transfer = vhc_transfer_create(target.address, 337 target.endpoint, USB_DIRECTION_OUT, USB_TRANSFER_CONTROL, 338 fun, arg); 339 if (transfer == NULL) { 340 return ENOMEM; 341 } 342 343 transfer->setup_buffer = setup_packet; 344 transfer->setup_buffer_size = setup_packet_size; 345 transfer->data_buffer = data_buffer; 346 transfer->data_buffer_size = data_buffer_size; 347 transfer->callback_out = callback; 348 349 int rc = vhc_virtdev_add_transfer(vhc, transfer); 350 if (rc != EOK) { 351 free(transfer); 352 return rc; 353 } 354 355 return EOK; 356 } 357 358 /** Schedule control read transfer. 359 * 360 * The callback is supposed to be called once the transfer (on the wire) is 361 * complete regardless of the outcome. 362 * However, the callback could be called only when this function returns 363 * with success status (i.e. returns EOK). 364 * 365 * @param[in] fun Device function the action was invoked on. 366 * @param[in] target Target pipe (address and endpoint number) specification. 367 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated 368 * and deallocated by the caller). 369 * @param[in] setup_packet_size Size of @p setup_packet buffer in bytes. 370 * @param[in] data_buffer Buffer where to store the data (in USB endianess, 371 * allocated and deallocated by the caller). 372 * @param[in] data_buffer_size Size of @p data_buffer buffer in bytes. 373 * @param[in] callback Callback to be issued once the transfer is complete. 374 * @param[in] arg Pass-through argument to the callback. 375 * @return Error code. 376 */ 293 377 static int control_read(ddf_fun_t *fun, usb_target_t target, 294 378 void *setup_packet, size_t setup_packet_size, 295 void *data , size_t data_size,379 void *data_buffer, size_t data_buffer_size, 296 380 usbhc_iface_transfer_in_callback_t callback, void *arg) 297 381 { 298 control_transfer_info_t *transfer 299 = create_control_transfer_info(fun, USB_DIRECTION_IN, target, 300 data, data_size, arg); 301 transfer->in_callback = callback; 302 303 hc_add_transaction_to_device(true, target, USB_TRANSFER_CONTROL, 304 setup_packet, setup_packet_size, 305 control_callback_one, transfer); 306 307 return EOK; 308 } 309 310 static usb_address_keeping_t addresses; 382 VHC_DATA(vhc, fun); 383 384 vhc_transfer_t *transfer = vhc_transfer_create(target.address, 385 target.endpoint, USB_DIRECTION_IN, USB_TRANSFER_CONTROL, 386 fun, arg); 387 if (transfer == NULL) { 388 return ENOMEM; 389 } 390 391 transfer->setup_buffer = setup_packet; 392 transfer->setup_buffer_size = setup_packet_size; 393 transfer->data_buffer = data_buffer; 394 transfer->data_buffer_size = data_buffer_size; 395 transfer->callback_in = callback; 396 397 int rc = vhc_virtdev_add_transfer(vhc, transfer); 398 if (rc != EOK) { 399 free(transfer); 400 return rc; 401 } 402 403 return EOK; 404 } 311 405 312 406 static int tell_address(ddf_fun_t *fun, devman_handle_t handle, 313 407 usb_address_t *address) 314 408 { 315 usb_log_debug("tell_address(fun \"%s\", handle %zu)\n", 316 fun->name, (size_t) fun->handle); 317 usb_address_t addr = usb_address_keeping_find(&addresses, handle); 409 UNSUPPORTED("tell_address"); 410 411 return ENOTSUP; 412 } 413 414 static int usb_iface_get_hc_handle_rh_impl(ddf_fun_t *root_hub_fun, 415 devman_handle_t *handle) 416 { 417 VHC_DATA(vhc, root_hub_fun); 418 419 *handle = vhc->hc_fun->handle; 420 421 return EOK; 422 } 423 424 static int tell_address_rh(ddf_fun_t *root_hub_fun, devman_handle_t handle, 425 usb_address_t *address) 426 { 427 VHC_DATA(vhc, root_hub_fun); 428 429 if (handle == 0) { 430 handle = root_hub_fun->handle; 431 } 432 433 usb_log_debug("tell_address_rh(handle=%" PRIun ")\n", handle); 434 usb_address_t addr = usb_device_keeper_find(&vhc->dev_keeper, handle); 318 435 if (addr < 0) { 319 436 return addr; 320 } 321 322 *address = addr; 323 return EOK; 324 } 325 326 static int request_address(ddf_fun_t *fun, usb_speed_t ignored, 327 usb_address_t *address) 328 { 329 usb_address_t addr = usb_address_keeping_request(&addresses); 330 if (addr < 0) { 331 return (int)addr; 332 } 333 334 *address = addr; 335 return EOK; 336 } 337 338 static int release_address(ddf_fun_t *fun, usb_address_t address) 339 { 340 return usb_address_keeping_release(&addresses, address); 341 } 342 343 static int bind_address(ddf_fun_t *fun, usb_address_t address, 344 devman_handle_t handle) 345 { 346 usb_address_keeping_devman_bind(&addresses, address, handle); 347 return EOK; 348 } 349 350 static int usb_iface_get_hc_handle_rh_impl(ddf_fun_t *root_hub_fun, 351 devman_handle_t *handle) 352 { 353 ddf_fun_t *hc_fun = root_hub_fun->driver_data; 354 assert(hc_fun != NULL); 355 356 *handle = hc_fun->handle; 357 358 usb_log_debug("usb_iface_get_hc_handle_rh_impl returns %zu\n", *handle); 359 360 return EOK; 361 } 362 363 static int tell_address_rh(ddf_fun_t *root_hub_fun, devman_handle_t handle, 364 usb_address_t *address) 365 { 366 ddf_fun_t *hc_fun = root_hub_fun->driver_data; 367 assert(hc_fun != NULL); 368 369 return tell_address(hc_fun, root_hub_fun->handle, address); 370 } 371 372 void address_init(void) 373 { 374 usb_address_keeping_init(&addresses, 50); 437 } else { 438 *address = addr; 439 return EOK; 440 } 375 441 } 376 442 … … 380 446 .release_address = release_address, 381 447 448 .register_endpoint = register_endpoint, 449 .unregister_endpoint = unregister_endpoint, 450 382 451 .interrupt_out = interrupt_out, 383 452 .interrupt_in = interrupt_in, 453 454 .bulk_in = bulk_in, 455 .bulk_out = bulk_out, 384 456 385 457 .control_write = control_write, -
uspace/drv/vhc/hub.c
ra58dd620 r3d4aa055 34 34 */ 35 35 #include <usb/classes/classes.h> 36 #include <usbvirt/hub.h>37 36 #include <usbvirt/device.h> 38 37 #include <errno.h> … … 45 44 46 45 #include "hub.h" 47 #include "hub/virthub.h"46 //#include "hub/virthub.h" 48 47 #include "vhcd.h" 49 48 #include "conn.h" 50 49 51 usbvirt_device_t virtual_hub_device; 50 usbvirt_device_t virtual_hub_device = { 51 .name = "root hub", 52 .ops = &hub_ops, 53 .address = 0 54 }; 55 52 56 static ddf_dev_ops_t rh_ops = { 53 57 .interfaces[USB_DEV_IFACE] = &rh_usb_iface, -
uspace/drv/vhc/hub.h
ra58dd620 r3d4aa055 39 39 #include <ddf/driver.h> 40 40 41 #include "devices.h"42 41 #include "hub/hub.h" 43 42 #include "hub/virthub.h" -
uspace/drv/vhc/hub/hub.c
ra58dd620 r3d4aa055 34 34 */ 35 35 #include <usb/classes/classes.h> 36 #include <usbvirt/hub.h>37 36 #include <usbvirt/device.h> 38 37 #include <errno.h> … … 41 40 #include <stdlib.h> 42 41 #include <ddf/driver.h> 42 #include <usb/debug.h> 43 43 44 44 #include "hub.h" … … 96 96 * @param index Port index (one based). 97 97 */ 98 static void hub_init_port(hub_port_t *port, size_t index)98 static void hub_init_port(hub_port_t *port, hub_t *hub, size_t index) 99 99 { 100 100 port->connected_device = NULL; … … 102 102 port->state = HUB_PORT_STATE_NOT_CONFIGURED; 103 103 port->status_change = 0; 104 port->hub = hub; 104 105 } 105 106 … … 112 113 size_t i; 113 114 for (i = 0; i < HUB_PORT_COUNT; i++) { 114 hub_init_port(&hub->ports[i], i + 1);115 hub_init_port(&hub->ports[i], hub, i + 1); 115 116 } 116 117 hub->custom_data = NULL; 118 hub->signal_changes = true; 117 119 fibril_mutex_initialize(&hub->guard); 118 120 } … … 229 231 } 230 232 233 usb_log_debug("Setting port %zu to state %d.\n", port_index, state); 234 231 235 switch (state) { 232 236 case HUB_PORT_STATE_POWERED_OFF: … … 236 240 break; 237 241 case HUB_PORT_STATE_RESUMING: 242 port->state = state; 238 243 set_port_state_delayed(hub, port_index, 239 244 10, state, HUB_PORT_STATE_ENABLED); 240 245 break; 241 246 case HUB_PORT_STATE_RESETTING: 247 port->state = state; 242 248 set_port_state_delayed(hub, port_index, 243 249 10, state, HUB_PORT_STATE_ENABLED); … … 415 421 { 416 422 assert(port != NULL); 423 uint16_t old_value = port->status_change; 417 424 port->status_change |= change; 425 usb_log_debug("Changing status change on %zu: %04x => %04x\n", 426 port->index, 427 (unsigned int) old_value, (unsigned int) port->status_change); 428 port->hub->signal_changes = true; 418 429 } 419 430 … … 428 439 assert(port != NULL); 429 440 port->status_change &= (~change); 441 port->hub->signal_changes = true; 430 442 } 431 443 -
uspace/drv/vhc/hub/hub.h
ra58dd620 r3d4aa055 72 72 } hub_status_change_t; 73 73 74 typedef struct hub hub_t; 75 74 76 /** Hub port information. */ 75 77 typedef struct { … … 82 84 /** Status change bitmap. */ 83 85 uint16_t status_change; 86 /** Containing hub. */ 87 hub_t *hub; 84 88 } hub_port_t; 85 89 86 90 /** Hub device type. */ 87 typedef struct{91 struct hub { 88 92 /** Hub ports. */ 89 93 hub_port_t ports[HUB_PORT_COUNT]; … … 92 96 /** Access guard to the whole hub. */ 93 97 fibril_mutex_t guard; 94 } hub_t; 98 /** Last value of status change bitmap. */ 99 bool signal_changes; 100 }; 95 101 96 102 void hub_init(hub_t *); -
uspace/drv/vhc/hub/virthub.c
ra58dd620 r3d4aa055 34 34 */ 35 35 #include <usb/classes/classes.h> 36 #include <usbvirt/hub.h>37 36 #include <usbvirt/device.h> 38 37 #include <assert.h> … … 153 152 dev->ops = &hub_ops; 154 153 dev->descriptors = &descriptors; 155 dev->lib_debug_level = 0;156 dev->lib_debug_enabled_tags = USBVIRT_DEBUGTAG_ALL;157 154 158 155 hub_t *hub = malloc(sizeof(hub_t)); … … 164 161 dev->device_data = hub; 165 162 166 int rc; 167 #ifdef STANDALONE_HUB 168 dev->name = "hub"; 169 rc = usbvirt_connect(dev); 170 #else 171 rc = usbvirt_connect_local(dev); 172 #endif 173 174 return rc; 163 return EOK; 175 164 } 176 165 … … 181 170 * @return Port device was connected to. 182 171 */ 183 int virthub_connect_device(usbvirt_device_t *dev, v irtdev_connection_t *conn)172 int virthub_connect_device(usbvirt_device_t *dev, vhc_virtdev_t *conn) 184 173 { 185 174 assert(dev != NULL); … … 201 190 * @return Error code. 202 191 */ 203 int virthub_disconnect_device(usbvirt_device_t *dev, v irtdev_connection_t *conn)192 int virthub_disconnect_device(usbvirt_device_t *dev, vhc_virtdev_t *conn) 204 193 { 205 194 assert(dev != NULL); … … 212 201 hub_release(hub); 213 202 214 return E NOTSUP;203 return EOK; 215 204 } 216 205 … … 221 210 * @return Whether port is signalling to the device. 222 211 */ 223 bool virthub_is_device_enabled(usbvirt_device_t *dev, v irtdev_connection_t *conn)212 bool virthub_is_device_enabled(usbvirt_device_t *dev, vhc_virtdev_t *conn) 224 213 { 225 214 assert(dev != NULL); -
uspace/drv/vhc/hub/virthub.h
ra58dd620 r3d4aa055 42 42 #define virtdev_connection_t int 43 43 #else 44 #include "../ devices.h"44 #include "../vhcd.h" 45 45 #endif 46 46 … … 80 80 81 81 int virthub_init(usbvirt_device_t *); 82 int virthub_connect_device(usbvirt_device_t *, v irtdev_connection_t *);83 int virthub_disconnect_device(usbvirt_device_t *, v irtdev_connection_t *);84 bool virthub_is_device_enabled(usbvirt_device_t *, v irtdev_connection_t *);82 int virthub_connect_device(usbvirt_device_t *, vhc_virtdev_t *); 83 int virthub_disconnect_device(usbvirt_device_t *, vhc_virtdev_t *); 84 bool virthub_is_device_enabled(usbvirt_device_t *, vhc_virtdev_t *); 85 85 void virthub_get_status(usbvirt_device_t *, char *, size_t); 86 86 -
uspace/drv/vhc/hub/virthubops.c
ra58dd620 r3d4aa055 35 35 #include <errno.h> 36 36 #include <usb/classes/hub.h> 37 #include <usbvirt/device.h> 37 38 #include "virthub.h" 38 39 #include "hub.h" 39 40 40 41 /** Callback when device changes states. */ 41 static void on_state_change( struct usbvirt_device*dev,42 static void on_state_change(usbvirt_device_t *dev, 42 43 usbvirt_device_state_t old_state, usbvirt_device_state_t new_state) 43 44 { … … 61 62 62 63 /** Callback for data request. */ 63 static int req_on_ data(struct usbvirt_device*dev,64 usb_endpoint_t endpoint, 65 void *buffer, size_t size, size_t *actual_size)64 static int req_on_status_change_pipe(usbvirt_device_t *dev, 65 usb_endpoint_t endpoint, usb_transfer_type_t tr_type, 66 void *buffer, size_t buffer_size, size_t *actual_size) 66 67 { 67 68 if (endpoint != HUB_STATUS_CHANGE_PIPE) { 68 return EINVAL; 69 return ESTALL; 70 } 71 if (tr_type != USB_TRANSFER_INTERRUPT) { 72 return ESTALL; 69 73 } 70 74 71 hub_t *hub = (hub_t *)dev->device_data;75 hub_t *hub = dev->device_data; 72 76 73 77 hub_acquire(hub); 74 78 79 if (!hub->signal_changes) { 80 hub_release(hub); 81 82 return ENAK; 83 } 84 85 75 86 uint8_t change_map = hub_get_status_change_bitmap(hub); 76 87 77 88 uint8_t *b = (uint8_t *) buffer; 78 if ( size > 0) {89 if (buffer_size > 0) { 79 90 *b = change_map; 80 91 *actual_size = 1; 92 } else { 93 *actual_size = 0; 81 94 } 82 95 96 hub->signal_changes = false; 97 83 98 hub_release(hub); 84 99 … … 94 109 */ 95 110 static int req_clear_hub_feature(usbvirt_device_t *dev, 96 usb_device_request_setup_packet_t *request,97 uint8_t *data)111 const usb_device_request_setup_packet_t *request, uint8_t *data, 112 size_t *act_size) 98 113 { 99 114 return ENOTSUP; … … 108 123 */ 109 124 static int req_clear_port_feature(usbvirt_device_t *dev, 110 usb_device_request_setup_packet_t *request,111 uint8_t *data)125 const usb_device_request_setup_packet_t *request, uint8_t *data, 126 size_t *act_size) 112 127 { 113 128 int rc; … … 188 203 */ 189 204 static int req_get_bus_state(usbvirt_device_t *dev, 190 usb_device_request_setup_packet_t *request,191 uint8_t *data)205 const usb_device_request_setup_packet_t *request, uint8_t *data, 206 size_t *act_size) 192 207 { 193 208 return ENOTSUP; … … 202 217 */ 203 218 static int req_get_descriptor(usbvirt_device_t *dev, 204 usb_device_request_setup_packet_t *request,205 uint8_t *data)219 const usb_device_request_setup_packet_t *request, uint8_t *data, 220 size_t *act_size) 206 221 { 207 222 if (request->value_high == USB_DESCTYPE_HUB) { 208 int rc = dev->control_transfer_reply(dev, 0,223 usbvirt_control_reply_helper(request, data, act_size, 209 224 &hub_descriptor, hub_descriptor.length); 210 225 211 return rc;226 return EOK; 212 227 } 213 228 /* Let the framework handle all the rest. */ … … 223 238 */ 224 239 static int req_get_hub_status(usbvirt_device_t *dev, 225 usb_device_request_setup_packet_t *request,226 uint8_t *data)240 const usb_device_request_setup_packet_t *request, uint8_t *data, 241 size_t *act_size) 227 242 { 228 243 uint32_t hub_status = 0; 229 244 230 return dev->control_transfer_reply(dev, 0,245 usbvirt_control_reply_helper(request, data, act_size, 231 246 &hub_status, sizeof(hub_status)); 247 248 return EOK; 232 249 } 233 250 … … 240 257 */ 241 258 static int req_get_port_status(usbvirt_device_t *dev, 242 usb_device_request_setup_packet_t *request,243 uint8_t *data)259 const usb_device_request_setup_packet_t *request, uint8_t *data, 260 size_t *act_size) 244 261 { 245 262 hub_t *hub = (hub_t *) dev->device_data; … … 251 268 hub_release(hub); 252 269 253 return dev->control_transfer_reply(dev, 0, &status, 4); 270 usbvirt_control_reply_helper(request, data, act_size, 271 &status, sizeof(status)); 272 273 return EOK; 254 274 } 255 275 … … 262 282 */ 263 283 static int req_set_hub_feature(usbvirt_device_t *dev, 264 usb_device_request_setup_packet_t *request,265 uint8_t *data)284 const usb_device_request_setup_packet_t *request, uint8_t *data, 285 size_t *act_size) 266 286 { 267 287 return ENOTSUP; … … 276 296 */ 277 297 static int req_set_port_feature(usbvirt_device_t *dev, 278 usb_device_request_setup_packet_t *request,279 uint8_t *data)298 const usb_device_request_setup_packet_t *request, uint8_t *data, 299 size_t *act_size) 280 300 { 281 301 int rc; … … 330 350 331 351 /** Recipient: other. */ 332 #define REC_OTHER USB VIRT_REQUEST_RECIPIENT_OTHER352 #define REC_OTHER USB_REQUEST_RECIPIENT_OTHER 333 353 /** Recipient: device. */ 334 #define REC_DEVICE USB VIRT_REQUEST_RECIPIENT_DEVICE354 #define REC_DEVICE USB_REQUEST_RECIPIENT_DEVICE 335 355 /** Direction: in. */ 336 356 #define DIR_IN USB_DIRECTION_IN … … 338 358 #define DIR_OUT USB_DIRECTION_OUT 339 359 360 340 361 /** Create a class request. 341 362 * … … 345 366 */ 346 367 #define CLASS_REQ(direction, recipient, req) \ 347 .request_type = USBVIRT_MAKE_CONTROL_REQUEST_TYPE(direction, \ 348 USBVIRT_REQUEST_TYPE_CLASS, recipient), \ 368 .req_direction = direction, \ 369 .req_recipient = recipient, \ 370 .req_type = USB_REQUEST_TYPE_CLASS, \ 349 371 .request = req 350 372 … … 356 378 */ 357 379 #define STD_REQ(direction, recipient, req) \ 358 .request_type = USBVIRT_MAKE_CONTROL_REQUEST_TYPE(direction, \ 359 USBVIRT_REQUEST_TYPE_STANDARD, recipient), \ 380 .req_direction = direction, \ 381 .req_recipient = recipient, \ 382 .req_type = USB_REQUEST_TYPE_STANDARD, \ 360 383 .request = req 361 384 362 385 /** Hub operations on control endpoint zero. */ 363 static usbvirt_control_ transfer_handler_t endpoint_zero_handlers[] = {386 static usbvirt_control_request_handler_t endpoint_zero_handlers[] = { 364 387 { 365 388 STD_REQ(DIR_IN, REC_DEVICE, USB_DEVREQ_GET_DESCRIPTOR), … … 417 440 .callback = req_set_port_feature 418 441 }, 419 USBVIRT_CONTROL_TRANSFER_HANDLER_LAST 442 { 443 .callback = NULL 444 } 420 445 }; 421 446 … … 423 448 /** Hub operations. */ 424 449 usbvirt_device_ops_t hub_ops = { 425 .control_transfer_handlers = endpoint_zero_handlers, 426 .on_data = NULL, 427 .on_data_request = req_on_data, 428 .on_state_change = on_state_change, 450 .control = endpoint_zero_handlers, 451 .data_in[HUB_STATUS_CHANGE_PIPE] = req_on_status_change_pipe, 452 .state_changed = on_state_change, 429 453 }; 430 454 -
uspace/drv/vhc/main.c
ra58dd620 r3d4aa055 1 1 /* 2 * Copyright (c) 201 0Vojtech Horky2 * Copyright (c) 2011 Vojtech Horky 3 3 * All rights reserved. 4 4 * … … 31 31 */ 32 32 /** @file 33 * @brief Virtual host controller driver.33 * Virtual host controller. 34 34 */ 35 35 … … 48 48 #include <usb_iface.h> 49 49 #include "vhcd.h" 50 #include "hc.h"51 #include "devices.h"52 50 #include "hub.h" 53 51 #include "conn.h" … … 65 63 int rc; 66 64 67 /*68 * Currently, we know how to simulate only single HC.69 */70 65 if (vhc_count > 0) { 71 66 return ELIMIT; 72 67 } 73 68 74 /* 75 * Create exposed function representing the host controller 76 * itself. 77 */ 69 vhc_data_t *data = malloc(sizeof(vhc_data_t)); 70 if (data == NULL) { 71 usb_log_fatal("Failed to allocate memory.\n"); 72 return ENOMEM; 73 } 74 data->magic = 0xDEADBEEF; 75 rc = usb_endpoint_manager_init(&data->ep_manager, (size_t) -1); 76 if (rc != EOK) { 77 usb_log_fatal("Failed to initialize endpoint manager.\n"); 78 free(data); 79 return rc; 80 } 81 usb_device_keeper_init(&data->dev_keeper); 82 78 83 ddf_fun_t *hc = ddf_fun_create(dev, fun_exposed, "hc"); 79 84 if (hc == NULL) { 80 85 usb_log_fatal("Failed to create device function.\n"); 86 free(data); 81 87 return ENOMEM; 82 88 } 83 89 84 90 hc->ops = &vhc_ops; 91 list_initialize(&data->devices); 92 fibril_mutex_initialize(&data->guard); 93 data->hub = &virtual_hub_device; 94 data->hc_fun = hc; 95 96 dev->driver_data = data; 85 97 86 98 rc = ddf_fun_bind(hc); … … 88 100 usb_log_fatal("Failed to bind HC function: %s.\n", 89 101 str_error(rc)); 102 free(data); 90 103 return rc; 91 104 } … … 93 106 ddf_fun_add_to_class(hc, "usbhc"); 94 107 95 /*96 * Initialize our hub and announce its presence.97 */98 108 virtual_hub_device_init(hc); 99 109 100 110 usb_log_info("Virtual USB host controller ready (dev %zu, hc %zu).\n", 101 111 (size_t) dev->handle, (size_t) hc->handle); 112 113 114 115 rc = vhc_virtdev_plug_hub(data, data->hub, NULL); 116 if (rc != EOK) { 117 usb_log_fatal("Failed to plug root hub: %s.\n", str_error(rc)); 118 free(data); 119 return rc; 120 } 102 121 103 122 return EOK; … … 116 135 int main(int argc, char * argv[]) 117 136 { 118 /*119 * Temporary workaround. Wait a little bit to be the last driver120 * in devman output.121 */122 //sleep(5);123 124 137 usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME); 125 138 126 139 printf(NAME ": virtual USB host controller driver.\n"); 127 140 128 /*129 * Initialize address management.130 */131 address_init();132 133 /*134 * Run the transfer scheduler.135 */136 hc_manager();137 138 /*139 * We are also a driver within devman framework.140 */141 141 return ddf_driver_main(&vhc_driver); 142 142 } -
uspace/drv/vhc/vhcd.h
ra58dd620 r3d4aa055 37 37 38 38 #include <usb/debug.h> 39 #include <usbvirt/device.h> 40 #include <usb/host/usb_endpoint_manager.h> 41 #include <usb/host/device_keeper.h> 42 #include <usbhc_iface.h> 39 43 40 44 #define NAME "vhc" 41 #define NAME_DEV "hcd-virt-dev"42 #define NAMESPACE "usb"43 45 44 #define DEVMAP_PATH_HC NAMESPACE "/" NAME 45 #define DEVMAP_PATH_DEV NAMESPACE "/" NAME_DEV 46 typedef struct { 47 link_t link; 48 int dev_phone; 49 usbvirt_device_t *dev_local; 50 bool plugged; 51 usb_address_t address; 52 fibril_mutex_t guard; 53 link_t transfer_queue; 54 } vhc_virtdev_t; 46 55 47 //#define dprintf(level, format, ...) 48 // usb_dprintf(NAME, (level), format "\n", ##__VA_ARGS__) 49 //void dprintf_inval_call(int, ipc_call_t, sysarg_t); 56 typedef struct { 57 uint32_t magic; 58 link_t devices; 59 fibril_mutex_t guard; 60 usb_endpoint_manager_t ep_manager; 61 usb_device_keeper_t dev_keeper; 62 usbvirt_device_t *hub; 63 ddf_fun_t *hc_fun; 64 } vhc_data_t; 65 66 typedef struct { 67 link_t link; 68 usb_address_t address; 69 usb_endpoint_t endpoint; 70 usb_direction_t direction; 71 usb_transfer_type_t transfer_type; 72 void *setup_buffer; 73 size_t setup_buffer_size; 74 void *data_buffer; 75 size_t data_buffer_size; 76 ddf_fun_t *ddf_fun; 77 void *callback_arg; 78 usbhc_iface_transfer_in_callback_t callback_in; 79 usbhc_iface_transfer_out_callback_t callback_out; 80 } vhc_transfer_t; 81 82 vhc_transfer_t *vhc_transfer_create(usb_address_t, usb_endpoint_t, 83 usb_direction_t, usb_transfer_type_t, ddf_fun_t *, void *); 84 int vhc_virtdev_plug(vhc_data_t *, int, uintptr_t *); 85 int vhc_virtdev_plug_local(vhc_data_t *, usbvirt_device_t *, uintptr_t *); 86 int vhc_virtdev_plug_hub(vhc_data_t *, usbvirt_device_t *, uintptr_t *); 87 void vhc_virtdev_unplug(vhc_data_t *, uintptr_t); 88 int vhc_virtdev_add_transfer(vhc_data_t *, vhc_transfer_t *); 89 90 int vhc_transfer_queue_processor(void *arg); 91 50 92 51 93 #endif -
uspace/lib/c/include/errno.h
ra58dd620 r3d4aa055 65 65 #define EEMPTY (-302) 66 66 67 /** Negative acknowledgment. */ 68 #define ENAK (-303) 69 67 70 /** An API function is called while another blocking function is in progress. */ 68 71 #define EINPROGRESS (-10036) -
uspace/lib/drv/include/usbhid_iface.h
ra58dd620 r3d4aa055 72 72 /** USB HID device communication interface. */ 73 73 typedef struct { 74 /** Get number of items in the event.74 /** Get size of the event in bytes. 75 75 * 76 76 * @param[in] fun DDF function answering the request. 77 77 * @return Number of events or error code. 78 78 */ 79 int (*get_event_length)(ddf_fun_t *fun);79 size_t (*get_event_length)(ddf_fun_t *fun); 80 80 81 81 /** Get single event from the HID device. 82 82 * 83 83 * @param[in] fun DDF function answering the request. 84 * @param[out] usage_page Array of usage pages and usages. 85 * @param[out] usage Array of data (1:1 with @p usage). 86 * @param[in] size Size of @p usage and @p data arrays. 84 * @param[out] buffer Buffer with raw data from the device. 87 85 * @param[out] act_size Actual number of returned events. 88 86 * @param[in] flags Flags (see USBHID_IFACE_FLAG_*). 89 87 * @return Error code. 90 88 */ 91 int (*get_event)(ddf_fun_t *fun, 92 uint16_t *usage_page, uint16_t *usage, size_t size, size_t *act_size, 93 unsigned int flags); 89 int (*get_event)(ddf_fun_t *fun, int32_t *buffer, size_t size, 90 size_t *act_size, unsigned int flags); 94 91 } usbhid_iface_t; 95 92 -
uspace/lib/usb/Makefile
ra58dd620 r3d4aa055 43 43 src/dump.c \ 44 44 src/hidiface.c \ 45 src/hidpath.c \ 45 46 src/hidparser.c \ 47 src/hiddescriptor.c \ 46 48 src/hub.c \ 47 49 src/pipepriv.c \ -
uspace/lib/usb/include/usb/classes/hid.h
ra58dd620 r3d4aa055 50 50 USB_HIDREQ_SET_PROTOCOL = 11 51 51 } usb_hid_request_t; 52 53 typedef enum {54 USB_HID_REPORT_TYPE_INPUT = 1,55 USB_HID_REPORT_TYPE_OUTPUT = 2,56 USB_HID_REPORT_TYPE_FEATURE = 357 } usb_hid_report_type_t;58 52 59 53 typedef enum { -
uspace/lib/usb/include/usb/classes/hid_report_items.h
ra58dd620 r3d4aa055 1 1 /* 2 * Copyright (c) 201 0 Vojtech Horky2 * Copyright (c) 2011 Matej Klonfar 3 3 * All rights reserved. 4 4 * … … 37 37 38 38 #include <stdint.h> 39 40 /** 41 * Item prefix 42 */ 43 #define USB_HID_ITEM_SIZE(data) ((uint8_t)(data & 0x3)) 44 #define USB_HID_ITEM_TAG(data) ((uint8_t)((data & 0xF0) >> 4)) 45 #define USB_HID_ITEM_TAG_CLASS(data) ((uint8_t)((data & 0xC) >> 2)) 46 #define USB_HID_ITEM_IS_LONG(data) (data == 0xFE) 47 48 49 /** 50 * Input/Output/Feature Item flags 51 */ 52 /** Constant (1) / Variable (0) */ 53 #define USB_HID_ITEM_FLAG_CONSTANT(flags) ((flags & 0x1) == 0x1) 54 /** Variable (1) / Array (0) */ 55 #define USB_HID_ITEM_FLAG_VARIABLE(flags) ((flags & 0x2) == 0x2) 56 /** Absolute / Relative*/ 57 #define USB_HID_ITEM_FLAG_RELATIVE(flags) ((flags & 0x4) == 0x4) 58 /** Wrap / No Wrap */ 59 #define USB_HID_ITEM_FLAG_WRAP(flags) ((flags & 0x8) == 0x8) 60 #define USB_HID_ITEM_FLAG_LINEAR(flags) ((flags & 0x10) == 0x10) 61 #define USB_HID_ITEM_FLAG_PREFERRED(flags) ((flags & 0x20) == 0x20) 62 #define USB_HID_ITEM_FLAG_POSITION(flags) ((flags & 0x40) == 0x40) 63 #define USB_HID_ITEM_FLAG_VOLATILE(flags) ((flags & 0x80) == 0x80) 64 #define USB_HID_ITEM_FLAG_BUFFERED(flags) ((flags & 0x100) == 0x100) 39 65 40 66 /* MAIN ITEMS */ -
uspace/lib/usb/include/usb/classes/hidparser.h
ra58dd620 r3d4aa055 1 1 /* 2 * Copyright (c) 201 0 Vojtech Horky2 * Copyright (c) 2011 Matej Klonfar 3 3 * All rights reserved. 4 4 * … … 39 39 #include <adt/list.h> 40 40 #include <usb/classes/hid_report_items.h> 41 42 /** 43 * Item prefix 44 */ 45 #define USB_HID_ITEM_SIZE(data) ((uint8_t)(data & 0x3)) 46 #define USB_HID_ITEM_TAG(data) ((uint8_t)((data & 0xF0) >> 4)) 47 #define USB_HID_ITEM_TAG_CLASS(data) ((uint8_t)((data & 0xC) >> 2)) 48 #define USB_HID_ITEM_IS_LONG(data) (data == 0xFE) 49 50 51 /** 52 * Input/Output/Feature Item flags 53 */ 54 /** Constant (1) / Variable (0) */ 55 #define USB_HID_ITEM_FLAG_CONSTANT(flags) ((flags & 0x1) == 0x1) 56 /** Variable (1) / Array (0) */ 57 #define USB_HID_ITEM_FLAG_VARIABLE(flags) ((flags & 0x2) == 0x2) 58 /** Absolute / Relative*/ 59 #define USB_HID_ITEM_FLAG_RELATIVE(flags) ((flags & 0x4) == 0x4) 60 /** Wrap / No Wrap */ 61 #define USB_HID_ITEM_FLAG_WRAP(flags) ((flags & 0x8) == 0x8) 62 #define USB_HID_ITEM_FLAG_LINEAR(flags) ((flags & 0x10) == 0x10) 63 #define USB_HID_ITEM_FLAG_PREFERRED(flags) ((flags & 0x20) == 0x20) 64 #define USB_HID_ITEM_FLAG_POSITION(flags) ((flags & 0x40) == 0x40) 65 #define USB_HID_ITEM_FLAG_VOLATILE(flags) ((flags & 0x80) == 0x80) 66 #define USB_HID_ITEM_FLAG_BUFFERED(flags) ((flags & 0x100) == 0x100) 67 68 69 /** 70 * Description of path of usage pages and usages in report descriptor 71 */ 72 #define USB_HID_PATH_COMPARE_STRICT 0 73 #define USB_HID_PATH_COMPARE_END 1 74 #define USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY 4 75 76 /** */ 77 typedef struct { 78 /** */ 79 int32_t usage_page; 80 /** */ 81 int32_t usage; 82 /** */ 83 link_t link; 84 } usb_hid_report_usage_path_t; 85 86 /** */ 87 typedef struct { 88 /** */ 89 int depth; 90 uint8_t report_id; 91 92 /** */ 93 link_t link; 94 95 } usb_hid_report_path_t; 96 97 /** 98 * Description of report items 99 */ 100 typedef struct { 101 /** */ 102 int32_t id; 103 /** */ 104 int32_t usage_minimum; 105 /** */ 106 int32_t usage_maximum; 107 /** */ 108 int32_t logical_minimum; 109 /** */ 110 int32_t logical_maximum; 111 /** */ 112 int32_t size; 113 /** */ 114 int32_t count; 115 /** */ 116 size_t offset; 117 /** */ 118 int32_t delimiter; 119 /** */ 120 int32_t unit_exponent; 121 /** */ 122 int32_t unit; 123 124 /** */ 125 int32_t string_index; 126 /** */ 127 int32_t string_minimum; 128 /** */ 129 int32_t string_maximum; 130 /** */ 131 int32_t designator_index; 132 /** */ 133 int32_t designator_minimum; 134 /** */ 135 int32_t designator_maximum; 136 /** */ 137 int32_t physical_minimum; 138 /** */ 139 int32_t physical_maximum; 140 141 /** */ 142 uint8_t item_flags; 143 144 /** */ 145 usb_hid_report_path_t *usage_path; 146 /** */ 147 link_t link; 148 } usb_hid_report_item_t; 149 150 151 /** HID report parser structure. */ 152 typedef struct { 153 /** */ 154 link_t input; 155 /** */ 156 link_t output; 157 /** */ 158 link_t feature; 159 160 int use_report_id; 161 162 /** */ 163 link_t stack; 164 } usb_hid_report_parser_t; 165 166 167 /** HID parser callbacks for IN items. */ 168 typedef struct { 169 /** Callback for keyboard. 170 * 171 * @param key_codes Array of pressed key (including modifiers). 172 * @param count Length of @p key_codes. 173 * @param arg Custom argument. 174 */ 175 void (*keyboard)(const uint8_t *key_codes, size_t count, const uint8_t report_id, void *arg); 176 } usb_hid_report_in_callbacks_t; 177 178 179 typedef enum { 180 USB_HID_MOD_LCTRL = 0x01, 181 USB_HID_MOD_LSHIFT = 0x02, 182 USB_HID_MOD_LALT = 0x04, 183 USB_HID_MOD_LGUI = 0x08, 184 USB_HID_MOD_RCTRL = 0x10, 185 USB_HID_MOD_RSHIFT = 0x20, 186 USB_HID_MOD_RALT = 0x40, 187 USB_HID_MOD_RGUI = 0x80, 188 USB_HID_MOD_COUNT = 8 189 } usb_hid_modifiers_t; 190 191 //typedef enum { 192 // USB_HID_LED_NUM_LOCK = 0x1, 193 // USB_HID_LED_CAPS_LOCK = 0x2, 194 // USB_HID_LED_SCROLL_LOCK = 0x4, 195 // USB_HID_LED_COMPOSE = 0x8, 196 // USB_HID_LED_KANA = 0x10, 197 // USB_HID_LED_COUNT = 5 198 //} usb_hid_led_t; 199 200 static const usb_hid_modifiers_t 201 usb_hid_modifiers_consts[USB_HID_MOD_COUNT] = { 202 USB_HID_MOD_LCTRL, 203 USB_HID_MOD_LSHIFT, 204 USB_HID_MOD_LALT, 205 USB_HID_MOD_LGUI, 206 USB_HID_MOD_RCTRL, 207 USB_HID_MOD_RSHIFT, 208 USB_HID_MOD_RALT, 209 USB_HID_MOD_RGUI 210 }; 211 212 //static const usb_hid_led_t usb_hid_led_consts[USB_HID_LED_COUNT] = { 213 // USB_HID_LED_NUM_LOCK, 214 // USB_HID_LED_CAPS_LOCK, 215 // USB_HID_LED_SCROLL_LOCK, 216 // USB_HID_LED_COMPOSE, 217 // USB_HID_LED_KANA 218 //}; 219 220 //#define USB_HID_BOOT_KEYBOARD_NUM_LOCK 0x01 221 //#define USB_HID_BOOT_KEYBOARD_CAPS_LOCK 0x02 222 //#define USB_HID_BOOT_KEYBOARD_SCROLL_LOCK 0x04 223 //#define USB_HID_BOOT_KEYBOARD_COMPOSE 0x08 224 //#define USB_HID_BOOT_KEYBOARD_KANA 0x10 225 226 /* 227 * Descriptor parser functions 228 */ 229 /** */ 230 int usb_hid_parser_init(usb_hid_report_parser_t *parser); 231 232 /** */ 233 int usb_hid_parse_report_descriptor(usb_hid_report_parser_t *parser, 234 const uint8_t *data, size_t size); 235 236 /** */ 237 void usb_hid_free_report_parser(usb_hid_report_parser_t *parser); 238 239 /** */ 240 void usb_hid_descriptor_print(usb_hid_report_parser_t *parser); 241 242 /* 243 * Boot protocol functions 244 */ 245 /** */ 246 int usb_hid_boot_keyboard_input_report(const uint8_t *data, size_t size, 247 const usb_hid_report_in_callbacks_t *callbacks, void *arg); 248 249 /** */ 250 int usb_hid_boot_keyboard_output_report(uint8_t leds, uint8_t *data, size_t size); 41 #include <usb/classes/hidpath.h> 42 #include <usb/classes/hidtypes.h> 43 #include <usb/classes/hiddescriptor.h> 251 44 252 45 … … 255 48 */ 256 49 /** */ 257 int usb_hid_parse_report(const usb_hid_report_parser_t *parser, 258 const uint8_t *data, size_t size, 259 usb_hid_report_path_t *path, int flags, 260 const usb_hid_report_in_callbacks_t *callbacks, void *arg); 50 int usb_hid_parse_report(const usb_hid_report_t *report, const uint8_t *data, 51 size_t size, uint8_t *report_id); 261 52 262 53 /** */ 263 size_t usb_hid_report_input_length(const usb_hid_report_ parser_t *parser,54 size_t usb_hid_report_input_length(const usb_hid_report_t *report, 264 55 usb_hid_report_path_t *path, int flags); 265 266 267 268 /*269 * usage path functions270 */271 /** */272 usb_hid_report_path_t *usb_hid_report_path(void);273 274 /** */275 void usb_hid_report_path_free(usb_hid_report_path_t *path);276 277 /** */278 int usb_hid_report_path_set_report_id(usb_hid_report_path_t *usage_path, uint8_t report_id);279 280 /** */281 int usb_hid_report_path_append_item(usb_hid_report_path_t *usage_path, int32_t usage_page, int32_t usage);282 283 /** */284 void usb_hid_report_remove_last_item(usb_hid_report_path_t *usage_path);285 286 /** */287 void usb_hid_report_null_last_item(usb_hid_report_path_t *usage_path);288 289 /** */290 void usb_hid_report_set_last_item(usb_hid_report_path_t *usage_path, int32_t tag, int32_t data);291 292 /** */293 int usb_hid_report_compare_usage_path(usb_hid_report_path_t *report_path, usb_hid_report_path_t *path, int flags);294 295 /** */296 usb_hid_report_path_t *usb_hid_report_path_clone(usb_hid_report_path_t *usage_path);297 298 56 299 57 /* … … 301 59 */ 302 60 /** Allocates output report buffer*/ 303 uint8_t *usb_hid_report_output(usb_hid_report_parser_t *parser, size_t *size); 61 uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size, 62 uint8_t report_id); 304 63 305 64 /** Frees output report buffer*/ … … 307 66 308 67 /** Returns size of output for given usage path */ 309 size_t usb_hid_report_output_size(usb_hid_report_ parser_t *parser,68 size_t usb_hid_report_output_size(usb_hid_report_t *report, 310 69 usb_hid_report_path_t *path, int flags); 311 70 312 /** Updates the output report buffer by translated given data */ 313 int usb_hid_report_output_translate(usb_hid_report_parser_t *parser, 314 usb_hid_report_path_t *path, int flags, 315 uint8_t *buffer, size_t size, 316 int32_t *data, size_t data_size); 71 /** Makes the output report buffer by translated given data */ 72 int usb_hid_report_output_translate(usb_hid_report_t *report, uint8_t report_id, 73 uint8_t *buffer, size_t size); 74 75 /** */ 76 usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report, 77 usb_hid_report_field_t *field, 78 usb_hid_report_path_t *path, 79 int flags, 80 usb_hid_report_type_t type); 81 82 /** */ 83 uint8_t usb_hid_report_get_report_id(usb_hid_report_t *report, 84 uint8_t report_id, 85 usb_hid_report_type_t type); 86 317 87 #endif 318 88 /** -
uspace/lib/usb/include/usb/classes/hidreport.h
ra58dd620 r3d4aa055 57 57 */ 58 58 int usb_hid_process_report_descriptor(usb_device_t *dev, 59 usb_hid_report_ parser_t *parser);59 usb_hid_report_t *report); 60 60 61 61 #endif /* LIBUSB_HIDREPORT_H_ */ -
uspace/lib/usb/include/usb/classes/hidut.h
ra58dd620 r3d4aa055 46 46 USB_HIDUT_PAGE_KEYBOARD = 7, 47 47 USB_HIDUT_PAGE_LED = 8, 48 USB_HIDUT_PAGE_BUTTON = 9 49 /* USB_HIDUT_PAGE_ = , */ 48 USB_HIDUT_PAGE_BUTTON = 9, 49 USB_HIDUT_PAGE_ORDINAL = 0x0a, 50 USB_HIDUT_PAGE_TELEPHONY_DEVICE = 0x0b, 51 USB_HIDUT_PAGE_CONSUMER = 0x0c 50 52 } usb_hidut_usage_page_t; 51 53 … … 57 59 USB_HIDUT_USAGE_GENERIC_DESKTOP_GAMEPAD = 5, 58 60 USB_HIDUT_USAGE_GENERIC_DESKTOP_KEYBOARD = 6, 59 USB_HIDUT_USAGE_GENERIC_DESKTOP_KEYPAD = 7 61 USB_HIDUT_USAGE_GENERIC_DESKTOP_KEYPAD = 7, 62 USB_HIDUT_USAGE_GENERIC_DESKTOP_X = 0x30, 63 USB_HIDUT_USAGE_GENERIC_DESKTOP_Y = 0x31, 64 USB_HIDUT_USAGE_GENERIC_DESKTOP_WHEEL = 0x38 60 65 /* USB_HIDUT_USAGE_GENERIC_DESKTOP_ = , */ 61 66 -
uspace/lib/usb/include/usb/usb.h
ra58dd620 r3d4aa055 96 96 USB_REQUEST_RECIPIENT_DEVICE = 0, 97 97 USB_REQUEST_RECIPIENT_INTERFACE = 1, 98 USB_REQUEST_RECIPIENT_ENDPOINT = 2 98 USB_REQUEST_RECIPIENT_ENDPOINT = 2, 99 USB_REQUEST_RECIPIENT_OTHER = 3 99 100 } usb_request_recipient_t; 100 101 -
uspace/lib/usb/src/debug.c
ra58dd620 r3d4aa055 158 158 159 159 /** Fibril local storage for the dumped buffer. */ 160 static fibril_local char buffer_dump[BUFFER_DUMP_LEN]; 160 static fibril_local char buffer_dump[2][BUFFER_DUMP_LEN]; 161 /** Fibril local storage for buffer switching. */ 162 static fibril_local int buffer_dump_index = 0; 161 163 162 164 /** Dump buffer into string. … … 167 169 * can not do that) and you do not have to guard it against concurrent 168 170 * calls to it. 169 * The only limitation is that each call rewrites the buffer again. 171 * The only limitation is that each second call rewrites the buffer again 172 * (internally, two buffer are used in cyclic manner). 170 173 * Thus, it is necessary to copy the buffer elsewhere (that includes printing 171 174 * to screen or writing to file). … … 173 176 * that is not a big limitation. 174 177 * 175 * @warning You cannot use this function twice in the same printf178 * @warning You cannot use this function more than twice in the same printf 176 179 * (see detailed explanation). 177 180 * … … 185 188 { 186 189 /* 187 * Remove previous string (that might also reveal double usage of 188 * this function). 190 * Remove previous string. 189 191 */ 190 bzero(buffer_dump , BUFFER_DUMP_LEN);192 bzero(buffer_dump[buffer_dump_index], BUFFER_DUMP_LEN); 191 193 192 194 if (buffer == NULL) { … … 202 204 /* How many bytes are available in the output buffer. */ 203 205 size_t buffer_remaining_size = BUFFER_DUMP_LEN - 1 - REMAINDER_STR_LEN; 204 char *it = buffer_dump ;206 char *it = buffer_dump[buffer_dump_index]; 205 207 206 208 size_t index = 0; … … 253 255 } 254 256 255 return buffer_dump; 257 /* Next time, use the other buffer. */ 258 buffer_dump_index = 1 - buffer_dump_index; 259 260 /* Need to take the old one due to previous line. */ 261 return buffer_dump[1 - buffer_dump_index]; 256 262 } 257 263 -
uspace/lib/usb/src/hidparser.c
ra58dd620 r3d4aa055 1 1 /* 2 * Copyright (c) 201 0 Vojtech Horky2 * Copyright (c) 2011 Matej Klonfar 3 3 * All rights reserved. 4 4 * … … 39 39 #include <mem.h> 40 40 #include <usb/debug.h> 41 42 /** */ 43 #define USB_HID_NEW_REPORT_ITEM 1 44 45 /** */ 46 #define USB_HID_NO_ACTION 2 47 48 /** */ 49 #define USB_HID_UNKNOWN_TAG -99 50 51 /* 52 * Private descriptor parser functions 53 */ 54 int usb_hid_report_parse_tag(uint8_t tag, uint8_t class, const uint8_t *data, size_t item_size, 55 usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path); 56 int usb_hid_report_parse_main_tag(uint8_t tag, const uint8_t *data, size_t item_size, 57 usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path); 58 int usb_hid_report_parse_global_tag(uint8_t tag, const uint8_t *data, size_t item_size, 59 usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path); 60 int usb_hid_report_parse_local_tag(uint8_t tag, const uint8_t *data, size_t item_size, 61 usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path); 62 63 void usb_hid_descriptor_print_list(link_t *head); 64 int usb_hid_report_reset_local_items(); 65 void usb_hid_free_report_list(link_t *head); 66 usb_hid_report_item_t *usb_hid_report_item_clone(const usb_hid_report_item_t *item); 41 #include <assert.h> 42 43 67 44 /* 68 45 * Data translation private functions 69 46 */ 70 int32_t usb_hid_report_tag_data_int32(const uint8_t *data, size_t size);47 uint32_t usb_hid_report_tag_data_uint32(const uint8_t *data, size_t size); 71 48 inline size_t usb_hid_count_item_offset(usb_hid_report_item_t * report_item, size_t offset); 72 int usb_hid_translate_data(usb_hid_report_ item_t *item, const uint8_t *data, size_t j);73 int32_t usb_hid_translate_data_reverse(usb_hid_report_item_t *item, int32_t value);49 int usb_hid_translate_data(usb_hid_report_field_t *item, const uint8_t *data); 50 uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, int32_t value); 74 51 int usb_pow(int a, int b); 52 75 53 76 54 // TODO: tohle ma bejt asi jinde … … 90 68 } 91 69 92 /** 93 * Initialize the report descriptor parser structure 94 * 95 * @param parser Report descriptor parser structure 96 * @return Error code 97 */ 98 int usb_hid_parser_init(usb_hid_report_parser_t *parser) 99 { 100 if(parser == NULL) { 101 return EINVAL; 102 } 103 104 list_initialize(&(parser->input)); 105 list_initialize(&(parser->output)); 106 list_initialize(&(parser->feature)); 107 108 list_initialize(&(parser->stack)); 109 110 parser->use_report_id = 0; 111 return EOK; 112 } 113 114 115 /** Parse HID report descriptor. 116 * 117 * @param parser Opaque HID report parser structure. 118 * @param data Data describing the report. 119 * @return Error code. 120 */ 121 int usb_hid_parse_report_descriptor(usb_hid_report_parser_t *parser, 122 const uint8_t *data, size_t size) 123 { 124 size_t i=0; 125 uint8_t tag=0; 126 uint8_t item_size=0; 127 int class=0; 128 int ret; 129 usb_hid_report_item_t *report_item=0; 130 usb_hid_report_item_t *new_report_item; 131 usb_hid_report_path_t *usage_path; 132 usb_hid_report_path_t *tmp_usage_path; 133 134 size_t offset_input=0; 135 size_t offset_output=0; 136 size_t offset_feature=0; 137 138 139 /* parser structure initialization*/ 140 if(usb_hid_parser_init(parser) != EOK) { 141 return EINVAL; 142 } 143 144 145 /*report item initialization*/ 146 if(!(report_item=malloc(sizeof(usb_hid_report_item_t)))){ 147 return ENOMEM; 148 } 149 memset(report_item, 0, sizeof(usb_hid_report_item_t)); 150 list_initialize(&(report_item->link)); 151 152 /* usage path context initialization */ 153 if(!(usage_path=usb_hid_report_path())){ 154 return ENOMEM; 155 } 156 157 while(i<size){ 158 if(!USB_HID_ITEM_IS_LONG(data[i])){ 159 160 if((i+USB_HID_ITEM_SIZE(data[i]))>= size){ 161 return EINVAL; // TODO ERROR CODE 162 } 163 164 tag = USB_HID_ITEM_TAG(data[i]); 165 item_size = USB_HID_ITEM_SIZE(data[i]); 166 class = USB_HID_ITEM_TAG_CLASS(data[i]); 167 168 usb_log_debug2( 169 "i(%zu) data(%X) value(%X): TAG %d, class %u, size %u - ", i, 170 data[i], usb_hid_report_tag_data_int32(data+i+1,item_size), 171 tag, class, item_size); 172 173 ret = usb_hid_report_parse_tag(tag,class,data+i+1, 174 item_size,report_item, usage_path); 175 usb_log_debug2("ret: %u\n", ret); 176 switch(ret){ 177 case USB_HID_NEW_REPORT_ITEM: 178 // store report item to report and create the new one 179 usb_log_debug("\nNEW REPORT ITEM: %X",ret); 180 181 // store current usage path 182 report_item->usage_path = usage_path; 183 184 // clone path to the new one 185 tmp_usage_path = usb_hid_report_path_clone(usage_path); 186 187 // swap 188 usage_path = tmp_usage_path; 189 tmp_usage_path = NULL; 190 191 usb_hid_report_path_set_report_id(report_item->usage_path, report_item->id); 192 if(report_item->id != 0){ 193 parser->use_report_id = 1; 194 } 195 196 switch(tag) { 197 case USB_HID_REPORT_TAG_INPUT: 198 report_item->offset = offset_input; 199 offset_input += report_item->count * report_item->size; 200 usb_log_debug(" - INPUT\n"); 201 list_append(&(report_item->link), &(parser->input)); 202 break; 203 case USB_HID_REPORT_TAG_OUTPUT: 204 report_item->offset = offset_output; 205 offset_output += report_item->count * report_item->size; 206 usb_log_debug(" - OUTPUT\n"); 207 list_append(&(report_item->link), &(parser->output)); 208 209 break; 210 case USB_HID_REPORT_TAG_FEATURE: 211 report_item->offset = offset_feature; 212 offset_feature += report_item->count * report_item->size; 213 usb_log_debug(" - FEATURE\n"); 214 list_append(&(report_item->link), &(parser->feature)); 215 break; 216 default: 217 usb_log_debug("\tjump over - tag %X\n", tag); 218 break; 219 } 220 221 /* clone current state table to the new item */ 222 if(!(new_report_item = malloc(sizeof(usb_hid_report_item_t)))) { 223 return ENOMEM; 224 } 225 memcpy(new_report_item,report_item, sizeof(usb_hid_report_item_t)); 226 link_initialize(&(new_report_item->link)); 227 228 /* reset local items */ 229 new_report_item->usage_minimum = 0; 230 new_report_item->usage_maximum = 0; 231 new_report_item->designator_index = 0; 232 new_report_item->designator_minimum = 0; 233 new_report_item->designator_maximum = 0; 234 new_report_item->string_index = 0; 235 new_report_item->string_minimum = 0; 236 new_report_item->string_maximum = 0; 237 238 /* reset usage from current usage path */ 239 usb_hid_report_usage_path_t *path = list_get_instance(&usage_path->link, usb_hid_report_usage_path_t, link); 240 path->usage = 0; 241 242 report_item = new_report_item; 243 244 break; 245 case USB_HID_REPORT_TAG_PUSH: 246 // push current state to stack 247 new_report_item = usb_hid_report_item_clone(report_item); 248 list_prepend (&parser->stack, &new_report_item->link); 249 250 break; 251 case USB_HID_REPORT_TAG_POP: 252 // restore current state from stack 253 if(list_empty (&parser->stack)) { 254 return EINVAL; 255 } 256 257 report_item = list_get_instance(&parser->stack, usb_hid_report_item_t, link); 258 list_remove (parser->stack.next); 259 260 break; 261 262 default: 263 // nothing special to do 264 break; 265 } 266 267 /* jump over the processed block */ 268 i += 1 + USB_HID_ITEM_SIZE(data[i]); 269 } 270 else{ 271 // TBD 272 i += 3 + USB_HID_ITEM_SIZE(data[i+1]); 273 } 274 275 276 } 277 278 return EOK; 279 } 280 281 282 /** 283 * Parse input report. 284 * 285 * @param data Data for report 286 * @param size Size of report 287 * @param callbacks Callbacks for report actions 288 * @param arg Custom arguments 289 * 290 * @return Error code 291 */ 292 int usb_hid_boot_keyboard_input_report(const uint8_t *data, size_t size, 293 const usb_hid_report_in_callbacks_t *callbacks, void *arg) 294 { 295 int i; 296 usb_hid_report_item_t item; 297 298 /* fill item due to the boot protocol report descriptor */ 299 // modifier keys are in the first byte 300 uint8_t modifiers = data[0]; 301 302 item.offset = 2; /* second byte is reserved */ 303 item.size = 8; 304 item.count = 6; 305 item.usage_minimum = 0; 306 item.usage_maximum = 255; 307 item.logical_minimum = 0; 308 item.logical_maximum = 255; 309 310 if (size != 8) { 311 return -1; //ERANGE; 312 } 313 314 uint8_t keys[6]; 315 for (i = 0; i < item.count; i++) { 316 keys[i] = data[i + item.offset]; 317 } 318 319 callbacks->keyboard(keys, 6, modifiers, arg); 320 return EOK; 321 } 322 323 /** 324 * Makes output report for keyboard boot protocol 325 * 326 * @param leds 327 * @param output Output report data buffer 328 * @param size Size of the output buffer 329 * @return Error code 330 */ 331 int usb_hid_boot_keyboard_output_report(uint8_t leds, uint8_t *data, size_t size) 332 { 333 if(size != 1){ 334 return -1; 335 } 336 337 /* used only first five bits, others are only padding*/ 338 *data = leds; 339 return EOK; 340 } 341 342 /** 343 * Parse one tag of the report descriptor 344 * 345 * @param Tag to parse 346 * @param Report descriptor buffer 347 * @param Size of data belongs to this tag 348 * @param Current report item structe 349 * @return Code of action to be done next 350 */ 351 int usb_hid_report_parse_tag(uint8_t tag, uint8_t class, const uint8_t *data, size_t item_size, 352 usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path) 353 { 354 int ret; 355 356 switch(class){ 357 case USB_HID_TAG_CLASS_MAIN: 358 359 if((ret=usb_hid_report_parse_main_tag(tag,data,item_size,report_item, usage_path)) == EOK) { 360 return USB_HID_NEW_REPORT_ITEM; 361 } 362 else { 363 /*TODO process the error */ 364 return ret; 365 } 366 break; 367 368 case USB_HID_TAG_CLASS_GLOBAL: 369 return usb_hid_report_parse_global_tag(tag,data,item_size,report_item, usage_path); 370 break; 371 372 case USB_HID_TAG_CLASS_LOCAL: 373 return usb_hid_report_parse_local_tag(tag,data,item_size,report_item, usage_path); 374 break; 375 default: 376 return USB_HID_NO_ACTION; 377 } 378 } 379 380 /** 381 * Parse main tags of report descriptor 382 * 383 * @param Tag identifier 384 * @param Data buffer 385 * @param Length of data buffer 386 * @param Current state table 387 * @return Error code 388 */ 389 390 int usb_hid_report_parse_main_tag(uint8_t tag, const uint8_t *data, size_t item_size, 391 usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path) 392 { 393 switch(tag) 394 { 395 case USB_HID_REPORT_TAG_INPUT: 396 case USB_HID_REPORT_TAG_OUTPUT: 397 case USB_HID_REPORT_TAG_FEATURE: 398 report_item->item_flags = *data; 399 return EOK; 400 break; 401 402 case USB_HID_REPORT_TAG_COLLECTION: 403 usb_hid_report_path_append_item(usage_path, 0, 0); 404 405 return USB_HID_NO_ACTION; 406 break; 407 408 case USB_HID_REPORT_TAG_END_COLLECTION: 409 // TODO 410 // znici posledni uroven ve vsech usage paths 411 // otazka jestli nema nicit dve, respektive novou posledni vynulovat? 412 usb_hid_report_remove_last_item(usage_path); 413 return USB_HID_NO_ACTION; 414 break; 415 default: 416 return USB_HID_NO_ACTION; 417 } 418 419 return EOK; 420 } 421 422 /** 423 * Parse global tags of report descriptor 424 * 425 * @param Tag identifier 426 * @param Data buffer 427 * @param Length of data buffer 428 * @param Current state table 429 * @return Error code 430 */ 431 int usb_hid_report_parse_global_tag(uint8_t tag, const uint8_t *data, size_t item_size, 432 usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path) 433 { 434 // TODO take care about the bit length of data 435 switch(tag) 436 { 437 case USB_HID_REPORT_TAG_USAGE_PAGE: 438 // zmeni to jenom v poslednim poli aktualni usage path 439 usb_hid_report_set_last_item(usage_path, USB_HID_TAG_CLASS_GLOBAL, 440 usb_hid_report_tag_data_int32(data,item_size)); 441 break; 442 case USB_HID_REPORT_TAG_LOGICAL_MINIMUM: 443 report_item->logical_minimum = usb_hid_report_tag_data_int32(data,item_size); 444 break; 445 case USB_HID_REPORT_TAG_LOGICAL_MAXIMUM: 446 report_item->logical_maximum = usb_hid_report_tag_data_int32(data,item_size); 447 break; 448 case USB_HID_REPORT_TAG_PHYSICAL_MINIMUM: 449 report_item->physical_minimum = usb_hid_report_tag_data_int32(data,item_size); 450 break; 451 case USB_HID_REPORT_TAG_PHYSICAL_MAXIMUM: 452 report_item->physical_maximum = usb_hid_report_tag_data_int32(data,item_size); 453 break; 454 case USB_HID_REPORT_TAG_UNIT_EXPONENT: 455 report_item->unit_exponent = usb_hid_report_tag_data_int32(data,item_size); 456 break; 457 case USB_HID_REPORT_TAG_UNIT: 458 report_item->unit = usb_hid_report_tag_data_int32(data,item_size); 459 break; 460 case USB_HID_REPORT_TAG_REPORT_SIZE: 461 report_item->size = usb_hid_report_tag_data_int32(data,item_size); 462 break; 463 case USB_HID_REPORT_TAG_REPORT_COUNT: 464 report_item->count = usb_hid_report_tag_data_int32(data,item_size); 465 break; 466 case USB_HID_REPORT_TAG_REPORT_ID: 467 report_item->id = usb_hid_report_tag_data_int32(data,item_size); 468 break; 469 case USB_HID_REPORT_TAG_PUSH: 470 case USB_HID_REPORT_TAG_POP: 471 return tag; 472 break; 473 474 default: 475 return USB_HID_NO_ACTION; 476 } 477 478 return EOK; 479 } 480 481 /** 482 * Parse local tags of report descriptor 483 * 484 * @param Tag identifier 485 * @param Data buffer 486 * @param Length of data buffer 487 * @param Current state table 488 * @return Error code 489 */ 490 int usb_hid_report_parse_local_tag(uint8_t tag, const uint8_t *data, size_t item_size, 491 usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path) 492 { 493 switch(tag) 494 { 495 case USB_HID_REPORT_TAG_USAGE: 496 usb_hid_report_set_last_item(usage_path, USB_HID_TAG_CLASS_LOCAL, 497 usb_hid_report_tag_data_int32(data,item_size)); 498 break; 499 case USB_HID_REPORT_TAG_USAGE_MINIMUM: 500 report_item->usage_minimum = usb_hid_report_tag_data_int32(data,item_size); 501 break; 502 case USB_HID_REPORT_TAG_USAGE_MAXIMUM: 503 report_item->usage_maximum = usb_hid_report_tag_data_int32(data,item_size); 504 break; 505 case USB_HID_REPORT_TAG_DESIGNATOR_INDEX: 506 report_item->designator_index = usb_hid_report_tag_data_int32(data,item_size); 507 break; 508 case USB_HID_REPORT_TAG_DESIGNATOR_MINIMUM: 509 report_item->designator_minimum = usb_hid_report_tag_data_int32(data,item_size); 510 break; 511 case USB_HID_REPORT_TAG_DESIGNATOR_MAXIMUM: 512 report_item->designator_maximum = usb_hid_report_tag_data_int32(data,item_size); 513 break; 514 case USB_HID_REPORT_TAG_STRING_INDEX: 515 report_item->string_index = usb_hid_report_tag_data_int32(data,item_size); 516 break; 517 case USB_HID_REPORT_TAG_STRING_MINIMUM: 518 report_item->string_minimum = usb_hid_report_tag_data_int32(data,item_size); 519 break; 520 case USB_HID_REPORT_TAG_STRING_MAXIMUM: 521 report_item->string_maximum = usb_hid_report_tag_data_int32(data,item_size); 522 break; 523 case USB_HID_REPORT_TAG_DELIMITER: 524 report_item->delimiter = usb_hid_report_tag_data_int32(data,item_size); 525 break; 526 527 default: 528 return USB_HID_NO_ACTION; 529 } 530 531 return EOK; 532 } 533 534 /** 535 * Converts raw data to int32 (thats the maximum length of short item data) 536 * 537 * @param Data buffer 538 * @param Size of buffer 539 * @return Converted int32 number 540 */ 541 int32_t usb_hid_report_tag_data_int32(const uint8_t *data, size_t size) 542 { 543 unsigned int i; 544 int32_t result; 545 546 result = 0; 547 for(i=0; i<size; i++) { 548 result = (result | (data[i]) << (i*8)); 549 } 550 551 return result; 552 } 553 554 555 556 /** 557 * Prints content of given list of report items. 558 * 559 * @param List of report items (usb_hid_report_item_t) 560 * @return void 561 */ 562 void usb_hid_descriptor_print_list(link_t *head) 563 { 564 usb_hid_report_item_t *report_item; 565 usb_hid_report_usage_path_t *path_item; 566 link_t *path; 567 link_t *item; 568 569 if(head == NULL || list_empty(head)) { 570 usb_log_debug("\tempty\n"); 571 return; 572 } 573 574 for(item = head->next; item != head; item = item->next) { 575 576 report_item = list_get_instance(item, usb_hid_report_item_t, link); 577 578 usb_log_debug("\tOFFSET: %zX\n", report_item->offset); 579 usb_log_debug("\tCOUNT: %X\n", report_item->count); 580 usb_log_debug("\tSIZE: %X\n", report_item->size); 581 usb_log_debug("\tCONSTANT/VAR: %X\n", USB_HID_ITEM_FLAG_CONSTANT(report_item->item_flags)); 582 usb_log_debug("\tVARIABLE/ARRAY: %X\n", USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags)); 583 usb_log_debug("\tUSAGE PATH:\n"); 584 585 path = report_item->usage_path->link.next; 586 while(path != &report_item->usage_path->link) { 587 path_item = list_get_instance(path, usb_hid_report_usage_path_t, link); 588 usb_log_debug("\t\tUSAGE PAGE: %X, USAGE: %X\n", path_item->usage_page, path_item->usage); 589 path = path->next; 590 } 591 592 usb_log_debug("\tLOGMIN: %X\n", report_item->logical_minimum); 593 usb_log_debug("\tLOGMAX: %X\n", report_item->logical_maximum); 594 usb_log_debug("\tPHYMIN: %X\n", report_item->physical_minimum); 595 usb_log_debug("\tPHYMAX: %X\n", report_item->physical_maximum); 596 usb_log_debug("\tUSAGEMIN: %X\n", report_item->usage_minimum); 597 usb_log_debug("\tUSAGEMAX: %X\n", report_item->usage_maximum); 598 599 usb_log_debug("\n"); 600 601 } 602 603 604 } 605 /** 606 * Prints content of given report descriptor in human readable format. 607 * 608 * @param parser Parsed descriptor to print 609 * @return void 610 */ 611 void usb_hid_descriptor_print(usb_hid_report_parser_t *parser) 612 { 613 if(parser == NULL) { 614 return; 615 } 616 617 usb_log_debug("INPUT:\n"); 618 usb_hid_descriptor_print_list(&parser->input); 619 620 usb_log_debug("OUTPUT: \n"); 621 usb_hid_descriptor_print_list(&parser->output); 622 623 usb_log_debug("FEATURE:\n"); 624 usb_hid_descriptor_print_list(&parser->feature); 625 626 } 627 628 /** 629 * Releases whole linked list of report items 630 * 631 * @param head Head of list of report descriptor items (usb_hid_report_item_t) 632 * @return void 633 */ 634 void usb_hid_free_report_list(link_t *head) 635 { 636 return; 637 638 usb_hid_report_item_t *report_item; 639 link_t *next; 640 641 if(head == NULL || list_empty(head)) { 642 return; 643 } 644 645 next = head->next; 646 while(next != head) { 647 648 report_item = list_get_instance(next, usb_hid_report_item_t, link); 649 650 while(!list_empty(&report_item->usage_path->link)) { 651 usb_hid_report_remove_last_item(report_item->usage_path); 652 } 653 654 655 next = next->next; 656 657 free(report_item); 658 } 659 660 return; 661 662 } 663 664 /** Frees the HID report descriptor parser structure 665 * 666 * @param parser Opaque HID report parser structure 667 * @return void 668 */ 669 void usb_hid_free_report_parser(usb_hid_report_parser_t *parser) 670 { 671 if(parser == NULL){ 672 return; 673 } 674 675 parser->use_report_id = 0; 676 677 usb_hid_free_report_list(&parser->input); 678 usb_hid_free_report_list(&parser->output); 679 usb_hid_free_report_list(&parser->feature); 680 681 return; 682 } 70 71 683 72 684 73 /** Parse and act upon a HID report. … … 688 77 * @param parser Opaque HID report parser structure. 689 78 * @param data Data for the report. 690 * @param callbacks Callbacks for report actions.691 * @param arg Custom argument (passed through to the callbacks).692 79 * @return Error code. 693 80 */ 694 int usb_hid_parse_report(const usb_hid_report_parser_t *parser, 695 const uint8_t *data, size_t size, 696 usb_hid_report_path_t *path, int flags, 697 const usb_hid_report_in_callbacks_t *callbacks, void *arg) 81 int usb_hid_parse_report(const usb_hid_report_t *report, 82 const uint8_t *data, size_t size, uint8_t *report_id) 698 83 { 699 84 link_t *list_item; 700 usb_hid_report_item_t *item; 701 uint8_t *keys; 702 uint8_t item_value; 703 size_t key_count=0; 704 size_t i=0; 705 size_t j=0; 706 uint8_t report_id = 0; 707 708 if(parser == NULL) { 85 usb_hid_report_field_t *item; 86 87 usb_hid_report_description_t *report_des; 88 usb_hid_report_type_t type = USB_HID_REPORT_TYPE_INPUT; 89 90 if(report == NULL) { 709 91 return EINVAL; 710 92 } 711 712 /* get the size of result array */ 713 key_count = usb_hid_report_input_length(parser, path, flags); 714 715 if(!(keys = malloc(sizeof(uint8_t) * key_count))){ 716 return ENOMEM; 717 } 718 719 if(parser->use_report_id != 0) { 720 report_id = data[0]; 721 usb_hid_report_path_set_report_id(path, report_id); 722 } 93 94 if(report->use_report_ids != 0) { 95 *report_id = data[0]; 96 } 97 else { 98 *report_id = 0; 99 } 100 101 102 report_des = usb_hid_report_find_description(report, *report_id, type); 723 103 724 104 /* read data */ 725 list_item = parser->input.next; 726 while(list_item != &(parser->input)) { 727 728 item = list_get_instance(list_item, usb_hid_report_item_t, link); 729 730 if(!USB_HID_ITEM_FLAG_CONSTANT(item->item_flags) && 731 (usb_hid_report_compare_usage_path(item->usage_path, path, flags) == EOK)) { 732 for(j=0; j<(size_t)(item->count); j++) { 733 if((USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0) || 734 ((item->usage_minimum == 0) && (item->usage_maximum == 0))) { 735 // variable item 736 keys[i++] = usb_hid_translate_data(item, data,j); 737 } 738 else { 739 // bitmapa 740 if((item_value = usb_hid_translate_data(item, data, j)) != 0) { 741 keys[i++] = (item->count - 1 - j) + item->usage_minimum; 742 } 743 else { 744 keys[i++] = 0; 745 } 746 } 747 } 105 list_item = report_des->report_items.next; 106 while(list_item != &(report_des->report_items)) { 107 108 item = list_get_instance(list_item, usb_hid_report_field_t, link); 109 110 if(USB_HID_ITEM_FLAG_CONSTANT(item->item_flags) == 0) { 111 112 if(USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0) { 113 114 // array 115 item->value = usb_hid_translate_data(item, data); 116 item->usage = (item->value - item->physical_minimum) + item->usage_minimum; 117 } 118 else { 119 // variable item 120 item->value = usb_hid_translate_data(item, data);