Changeset 9d9ffdd in mainline for uspace/drv/usbhid
- Timestamp:
- 2011-03-11T15:42:43Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 0bd4810c
- Parents:
- 60a228f (diff), a8def7d (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - Location:
- uspace/drv/usbhid
- Files:
-
- 2 added
- 11 edited
-
Makefile (modified) (1 diff)
-
conv.c (modified) (2 diffs)
-
descdump.c (modified) (7 diffs)
-
hiddev.c (modified) (13 diffs)
-
hiddev.h (modified) (1 diff)
-
hidreq.c (modified) (4 diffs)
-
hidreq.h (modified) (1 diff)
-
kbddev.c (modified) (34 diffs)
-
kbddev.h (modified) (3 diffs)
-
kbdrepeat.c (added)
-
kbdrepeat.h (added)
-
main.c (modified) (2 diffs)
-
usbhid.ma (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/usbhid/Makefile
r60a228f r9d9ffdd 42 42 hidreq.c \ 43 43 kbddev.c \ 44 kbdrepeat.c \ 44 45 hiddev.c \ 45 46 $(STOLEN_LAYOUT_SOURCES) -
uspace/drv/usbhid/conv.c
r60a228f r9d9ffdd 40 40 #include "conv.h" 41 41 42 /** 43 * Mapping between USB HID key codes (from HID Usage Tables) and corresponding 44 * HelenOS key codes. 45 */ 42 46 static int scanmap_simple[255] = { 43 47 … … 163 167 }; 164 168 169 /** 170 * Translate USB HID key codes (from HID Usage Tables) to generic key codes 171 * recognized by HelenOS. 172 * 173 * @param scancode USB HID key code (from HID Usage Tables). 174 * 175 * @retval HelenOS key code corresponding to the given USB HID key code. 176 */ 165 177 unsigned int usbhid_parse_scancode(int scancode) 166 178 { -
uspace/drv/usbhid/descdump.c
r60a228f r9d9ffdd 44 44 #define BYTES_PER_LINE 12 45 45 46 /** 47 * Dumps the given buffer in hexadecimal format to standard output. 48 * 49 * @param msg Message to print before the buffer. 50 * @param buffer Buffer to print. 51 * @param length Size of the buffer in bytes. 52 */ 46 53 static void dump_buffer(const char *msg, const uint8_t *buffer, size_t length) 47 54 { … … 62 69 #define INDENT " " 63 70 71 /** 72 * Print standard configuration descriptor to standard output. 73 * 74 * @param index Index of the descriptor. 75 * @param d Standard configuration descriptor to print. 76 */ 64 77 void dump_standard_configuration_descriptor( 65 78 int index, const usb_standard_configuration_descriptor_t *d) … … 84 97 } 85 98 99 /** 100 * Print standard interface descriptor to standard output. 101 * 102 * @param d Standard interface descriptor to print. 103 */ 86 104 void dump_standard_interface_descriptor( 87 105 const usb_standard_interface_descriptor_t *d) … … 99 117 } 100 118 119 /** 120 * Print standard endpoint descriptor to standard output. 121 * 122 * @param d Standard endpoint descriptor to print. 123 */ 101 124 void dump_standard_endpoint_descriptor( 102 125 const usb_standard_endpoint_descriptor_t *d) … … 126 149 } 127 150 151 /** 152 * Print standard HID descriptor to standard output. 153 * 154 * @param d Standard HID descriptor to print. 155 */ 128 156 void dump_standard_hid_descriptor_header( 129 157 const usb_standard_hid_descriptor_t *d) … … 139 167 } 140 168 169 /** 170 * Print HID class-specific descriptor header (type and length) to standard 171 * output. 172 * 173 * @param d HID class-specific descriptor header to print. 174 */ 141 175 void dump_standard_hid_class_descriptor_info( 142 176 const usb_standard_hid_class_descriptor_info_t *d) … … 146 180 } 147 181 182 /** 183 * Print HID class-specific descriptor (without the header) to standard output. 184 * 185 * @param index Index of the descriptor. 186 * @param type Type of the HID class-specific descriptor (Report or Physical). 187 * @param d HID class descriptor to print. 188 * @param size Size of the descriptor in bytes. 189 */ 148 190 void dump_hid_class_descriptor(int index, uint8_t type, 149 191 const uint8_t *d, size_t size ) -
uspace/drv/usbhid/hiddev.c
r60a228f r9d9ffdd 53 53 /* Non-API functions */ 54 54 /*----------------------------------------------------------------------------*/ 55 55 /** 56 * Retreives HID Report descriptor from the device. 57 * 58 * This function first parses the HID descriptor from the Interface descriptor 59 * to get the size of the Report descriptor and then requests the Report 60 * descriptor from the device. 61 * 62 * @param hid_dev HID device structure. 63 * @param config_desc Full configuration descriptor (including all nested 64 * descriptors). 65 * @param config_desc_size Size of the full configuration descriptor (in bytes). 66 * @param iface_desc Pointer to the interface descriptor inside the full 67 * configuration descriptor (@a config_desc) for the interface 68 * assigned with this device (@a hid_dev). 69 * 70 * @retval EOK if successful. 71 * @retval ENOENT if no HID descriptor could be found. 72 * @retval EINVAL if the HID descriptor or HID report descriptor have different 73 * size than expected. 74 * @retval ENOMEM if some allocation failed. 75 * @return Other value inherited from function usb_request_get_descriptor(). 76 * 77 * @sa usb_request_get_descriptor() 78 */ 56 79 static int usbhid_dev_get_report_descriptor(usbhid_dev_t *hid_dev, 57 80 uint8_t *config_desc, size_t config_desc_size, uint8_t *iface_desc) … … 135 158 } 136 159 160 hid_dev->report_desc_size = length; 161 137 162 usb_log_debug("Done.\n"); 138 163 … … 141 166 142 167 /*----------------------------------------------------------------------------*/ 143 168 /** 169 * Retreives descriptors from the device, initializes pipes and stores 170 * important information from descriptors. 171 * 172 * Initializes the polling pipe described by the given endpoint description 173 * (@a poll_ep_desc). 174 * 175 * Information retreived from descriptors and stored in the HID device structure: 176 * - Assigned interface number (the interface controlled by this instance of 177 * the driver) 178 * - Polling interval (from the interface descriptor) 179 * - Report descriptor 180 * 181 * @param hid_dev HID device structure to be initialized. 182 * @param poll_ep_desc Description of the polling (Interrupt In) endpoint 183 * that has to be present in the device in order to 184 * successfuly initialize the structure. 185 * 186 * @sa usb_endpoint_pipe_initialize_from_configuration(), 187 * usbhid_dev_get_report_descriptor() 188 */ 144 189 static int usbhid_dev_process_descriptors(usbhid_dev_t *hid_dev, 145 190 usb_endpoint_description_t *poll_ep_desc) … … 149 194 usb_log_info("Processing descriptors...\n"); 150 195 151 // get the first configuration descriptor152 usb_standard_configuration_descriptor_t config_desc;153 154 196 int rc; 155 rc = usb_request_get_bare_configuration_descriptor(&hid_dev->ctrl_pipe, 156 0, &config_desc); 157 158 if (rc != EOK) { 159 usb_log_error("Failed to get bare config descriptor: %s.\n", 197 198 uint8_t *descriptors = NULL; 199 size_t descriptors_size; 200 rc = usb_request_get_full_configuration_descriptor_alloc( 201 &hid_dev->ctrl_pipe, 0, (void **) &descriptors, &descriptors_size); 202 if (rc != EOK) { 203 usb_log_error("Failed to retrieve config descriptor: %s.\n", 160 204 str_error(rc)); 161 205 return rc; 162 }163 164 // prepare space for all underlying descriptors165 uint8_t *descriptors = (uint8_t *)malloc(config_desc.total_length);166 if (descriptors == NULL) {167 usb_log_error("No memory!.\n");168 return ENOMEM;169 }170 171 size_t transferred = 0;172 // get full configuration descriptor173 rc = usb_request_get_full_configuration_descriptor(&hid_dev->ctrl_pipe,174 0, descriptors, config_desc.total_length, &transferred);175 176 if (rc != EOK) {177 usb_log_error("Failed to get full config descriptor: %s.\n",178 str_error(rc));179 free(descriptors);180 return rc;181 }182 183 if (transferred != config_desc.total_length) {184 usb_log_error("Configuration descriptor has wrong size (%u, "185 "expected %u).\n", transferred, config_desc.total_length);186 free(descriptors);187 return ELIMIT;188 206 } 189 207 … … 201 219 202 220 rc = usb_endpoint_pipe_initialize_from_configuration( 203 endpoint_mapping, 1, descriptors, config_desc.total_length,221 endpoint_mapping, 1, descriptors, descriptors_size, 204 222 &hid_dev->wire); 205 223 … … 233 251 assert(endpoint_mapping[0].interface != NULL); 234 252 235 rc = usbhid_dev_get_report_descriptor(hid_dev, descriptors, transferred, 253 /* 254 * Save polling interval 255 */ 256 hid_dev->poll_interval = endpoint_mapping[0].descriptor->poll_interval; 257 assert(hid_dev->poll_interval > 0); 258 259 rc = usbhid_dev_get_report_descriptor(hid_dev, 260 descriptors, descriptors_size, 236 261 (uint8_t *)endpoint_mapping[0].interface); 237 262 … … 239 264 240 265 if (rc != EOK) { 241 usb_log_warning("Problem with parsing Report descriptor: %s.\n",266 usb_log_warning("Problem with getting Report descriptor: %s.\n", 242 267 str_error(rc)); 243 268 return rc; 244 269 } 270 271 rc = usb_hid_parse_report_descriptor(hid_dev->parser, 272 hid_dev->report_desc, hid_dev->report_desc_size); 273 if (rc != EOK) { 274 usb_log_warning("Problem parsing Report descriptor: %s.\n", 275 str_error(rc)); 276 return rc; 277 } 278 279 usb_hid_descriptor_print(hid_dev->parser); 245 280 246 281 return EOK; … … 250 285 /* API functions */ 251 286 /*----------------------------------------------------------------------------*/ 252 287 /** 288 * Creates new uninitialized HID device structure. 289 * 290 * @return Pointer to the new HID device structure, or NULL if an error occured. 291 */ 253 292 usbhid_dev_t *usbhid_dev_new(void) 254 293 { … … 263 302 memset(dev, 0, sizeof(usbhid_dev_t)); 264 303 304 dev->parser = (usb_hid_report_parser_t *)(malloc(sizeof( 305 usb_hid_report_parser_t))); 306 if (dev->parser == NULL) { 307 usb_log_fatal("No memory!\n"); 308 free(dev); 309 return NULL; 310 } 311 265 312 dev->initialized = 0; 266 313 … … 269 316 270 317 /*----------------------------------------------------------------------------*/ 271 318 /** 319 * Properly destroys the HID device structure. 320 * 321 * @note Currently does not clean-up the used pipes, as there are no functions 322 * offering such functionality. 323 * 324 * @param hid_dev Pointer to the structure to be destroyed. 325 */ 272 326 void usbhid_dev_free(usbhid_dev_t **hid_dev) 273 327 { … … 292 346 293 347 /*----------------------------------------------------------------------------*/ 294 348 /** 349 * Initializes HID device structure. 350 * 351 * @param hid_dev HID device structure to be initialized. 352 * @param dev DDF device representing the HID device. 353 * @param poll_ep_desc Description of the polling (Interrupt In) endpoint 354 * that has to be present in the device in order to 355 * successfuly initialize the structure. 356 * 357 * @retval EOK if successful. 358 * @retval EINVAL if some argument is missing. 359 * @return Other value inherited from one of functions 360 * usb_device_connection_initialize_from_device(), 361 * usb_endpoint_pipe_initialize_default_control(), 362 * usb_endpoint_pipe_start_session(), usb_endpoint_pipe_end_session(), 363 * usbhid_dev_process_descriptors(). 364 * 365 * @sa usbhid_dev_process_descriptors() 366 */ 295 367 int usbhid_dev_init(usbhid_dev_t *hid_dev, ddf_dev_t *dev, 296 368 usb_endpoint_description_t *poll_ep_desc) … … 339 411 return rc; 340 412 } 413 414 /* 415 * Initialize the report parser. 416 */ 417 rc = usb_hid_parser_init(hid_dev->parser); 418 if (rc != EOK) { 419 usb_log_error("Failed to initialize report parser.\n"); 420 return rc; 421 } 341 422 342 423 /* 343 424 * Get descriptors, parse descriptors and save endpoints. 344 425 */ 345 usb_endpoint_pipe_start_session(&hid_dev->ctrl_pipe); 426 rc = usb_endpoint_pipe_start_session(&hid_dev->ctrl_pipe); 427 if (rc != EOK) { 428 usb_log_error("Failed to start session on the control pipe: %s" 429 ".\n", str_error(rc)); 430 return rc; 431 } 346 432 347 433 rc = usbhid_dev_process_descriptors(hid_dev, poll_ep_desc); 348 349 usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe); 350 if (rc != EOK) { 434 if (rc != EOK) { 435 /* TODO: end session?? */ 351 436 usb_log_error("Failed to process descriptors: %s.\n", 352 437 str_error(rc)); … … 354 439 } 355 440 441 rc = usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe); 442 if (rc != EOK) { 443 usb_log_warning("Failed to start session on the control pipe: " 444 "%s.\n", str_error(rc)); 445 return rc; 446 } 447 356 448 hid_dev->initialized = 1; 357 449 usb_log_info("HID device structure initialized.\n"); -
uspace/drv/usbhid/hiddev.h
r60a228f r9d9ffdd 48 48 49 49 /** 50 * @brief USB/HID device type. 50 * USB/HID device type. 51 * 52 * Holds a reference to DDF device structure, and HID-specific data, such 53 * as information about used pipes (one Control pipe and one Interrupt In pipe), 54 * polling interval, assigned interface number, Report descriptor and a 55 * reference to the Report parser used to parse incoming reports and composing 56 * outgoing reports. 51 57 */ 52 58 typedef struct { 59 /** DDF device representing the controlled HID device. */ 53 60 ddf_dev_t *device; 54 61 62 /** Physical connection to the device. */ 55 63 usb_device_connection_t wire; 64 /** USB pipe corresponding to the default Control endpoint. */ 56 65 usb_endpoint_pipe_t ctrl_pipe; 66 /** USB pipe corresponding to the Interrupt In (polling) pipe. */ 57 67 usb_endpoint_pipe_t poll_pipe; 58 68 69 /** Polling interval retreived from the Interface descriptor. */ 70 short poll_interval; 71 72 /** Interface number assigned to this device. */ 59 73 uint16_t iface; 60 74 75 /** Report descriptor. */ 61 76 uint8_t *report_desc; 77 78 size_t report_desc_size; 79 80 /** HID Report parser. */ 62 81 usb_hid_report_parser_t *parser; 63 82 83 /** State of the structure (for checking before use). */ 64 84 int initialized; 65 85 } usbhid_dev_t; -
uspace/drv/usbhid/hidreq.c
r60a228f r9d9ffdd 46 46 47 47 /*----------------------------------------------------------------------------*/ 48 48 /** 49 * Send Set Report request to the HID device. 50 * 51 * @param hid_dev HID device to send the request to. 52 * @param type Type of the report. 53 * @param buffer Report data. 54 * @param buf_size Report data size (in bytes). 55 * 56 * @retval EOK if successful. 57 * @retval EINVAL if no HID device is given. 58 * @return Other value inherited from one of functions 59 * usb_endpoint_pipe_start_session(), usb_endpoint_pipe_end_session(), 60 * usb_control_request_set(). 61 */ 49 62 int usbhid_req_set_report(usbhid_dev_t *hid_dev, 50 63 usb_hid_report_type_t type, uint8_t *buffer, size_t buf_size) … … 69 82 return sess_rc; 70 83 } 84 85 uint16_t value = 0; 86 value |= (type << 8); 71 87 72 88 usb_log_debug("Sending Set_Report request to the device.\n"); … … 74 90 rc = usb_control_request_set(&hid_dev->ctrl_pipe, 75 91 USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 76 USB_HIDREQ_SET_REPORT, type, hid_dev->iface, buffer, buf_size); 77 78 sess_rc = usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe); 79 80 if (rc != EOK) { 81 usb_log_warning("Error sending output report to the keyboard: " 82 "%s.\n", str_error(rc)); 83 return rc; 84 } 85 86 if (sess_rc != EOK) { 87 usb_log_warning("Error closing session: %s.\n", 88 str_error(sess_rc)); 89 return sess_rc; 90 } 91 92 return EOK; 93 } 94 95 /*----------------------------------------------------------------------------*/ 96 92 USB_HIDREQ_SET_REPORT, value, hid_dev->iface, buffer, buf_size); 93 94 sess_rc = usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe); 95 96 if (rc != EOK) { 97 usb_log_warning("Error sending output report to the keyboard: " 98 "%s.\n", str_error(rc)); 99 return rc; 100 } 101 102 if (sess_rc != EOK) { 103 usb_log_warning("Error closing session: %s.\n", 104 str_error(sess_rc)); 105 return sess_rc; 106 } 107 108 return EOK; 109 } 110 111 /*----------------------------------------------------------------------------*/ 112 /** 113 * Send Set Protocol request to the HID device. 114 * 115 * @param hid_dev HID device to send the request to. 116 * @param protocol Protocol to set. 117 * 118 * @retval EOK if successful. 119 * @retval EINVAL if no HID device is given. 120 * @return Other value inherited from one of functions 121 * usb_endpoint_pipe_start_session(), usb_endpoint_pipe_end_session(), 122 * usb_control_request_set(). 123 */ 97 124 int usbhid_req_set_protocol(usbhid_dev_t *hid_dev, usb_hid_protocol_t protocol) 98 125 { … … 142 169 143 170 /*----------------------------------------------------------------------------*/ 171 /** 172 * Send Set Idle request to the HID device. 173 * 174 * @param hid_dev HID device to send the request to. 175 * @param duration Duration value (is multiplicated by 4 by the device to 176 * get real duration in miliseconds). 177 * 178 * @retval EOK if successful. 179 * @retval EINVAL if no HID device is given. 180 * @return Other value inherited from one of functions 181 * usb_endpoint_pipe_start_session(), usb_endpoint_pipe_end_session(), 182 * usb_control_request_set(). 183 */ 184 int usbhid_req_set_idle(usbhid_dev_t *hid_dev, uint8_t duration) 185 { 186 if (hid_dev == NULL) { 187 usb_log_error("usbhid_req_set_idle(): no HID device " 188 "structure given.\n"); 189 return EINVAL; 190 } 191 192 /* 193 * No need for checking other parameters, as they are checked in 194 * the called function (usb_control_request_set()). 195 */ 196 197 int rc, sess_rc; 198 199 sess_rc = usb_endpoint_pipe_start_session(&hid_dev->ctrl_pipe); 200 if (sess_rc != EOK) { 201 usb_log_warning("Failed to start a session: %s.\n", 202 str_error(sess_rc)); 203 return sess_rc; 204 } 205 206 usb_log_debug("Sending Set_Idle request to the device (" 207 "duration: %u, iface: %d).\n", duration, hid_dev->iface); 208 209 uint16_t value = duration << 8; 210 211 rc = usb_control_request_set(&hid_dev->ctrl_pipe, 212 USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 213 USB_HIDREQ_SET_IDLE, value, hid_dev->iface, NULL, 0); 214 215 sess_rc = usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe); 216 217 if (rc != EOK) { 218 usb_log_warning("Error sending output report to the keyboard: " 219 "%s.\n", str_error(rc)); 220 return rc; 221 } 222 223 if (sess_rc != EOK) { 224 usb_log_warning("Error closing session: %s.\n", 225 str_error(sess_rc)); 226 return sess_rc; 227 } 228 229 return EOK; 230 } 231 232 /*----------------------------------------------------------------------------*/ 233 /** 234 * Send Get Report request to the HID device. 235 * 236 * @param[in] hid_dev HID device to send the request to. 237 * @param[in] type Type of the report. 238 * @param[in][out] buffer Buffer for the report data. 239 * @param[in] buf_size Size of the buffer (in bytes). 240 * @param[out] actual_size Actual size of report received from the device 241 * (in bytes). 242 * 243 * @retval EOK if successful. 244 * @retval EINVAL if no HID device is given. 245 * @return Other value inherited from one of functions 246 * usb_endpoint_pipe_start_session(), usb_endpoint_pipe_end_session(), 247 * usb_control_request_set(). 248 */ 249 int usbhid_req_get_report(usbhid_dev_t *hid_dev, usb_hid_report_type_t type, 250 uint8_t *buffer, size_t buf_size, size_t *actual_size) 251 { 252 if (hid_dev == NULL) { 253 usb_log_error("usbhid_req_set_report(): no HID device structure" 254 " given.\n"); 255 return EINVAL; 256 } 257 258 /* 259 * No need for checking other parameters, as they are checked in 260 * the called function (usb_control_request_set()). 261 */ 262 263 int rc, sess_rc; 264 265 sess_rc = usb_endpoint_pipe_start_session(&hid_dev->ctrl_pipe); 266 if (sess_rc != EOK) { 267 usb_log_warning("Failed to start a session: %s.\n", 268 str_error(sess_rc)); 269 return sess_rc; 270 } 271 272 uint16_t value = 0; 273 value |= (type << 8); 274 275 usb_log_debug("Sending Get_Report request to the device.\n"); 276 277 rc = usb_control_request_get(&hid_dev->ctrl_pipe, 278 USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 279 USB_HIDREQ_GET_REPORT, value, hid_dev->iface, buffer, buf_size, 280 actual_size); 281 282 sess_rc = usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe); 283 284 if (rc != EOK) { 285 usb_log_warning("Error sending output report to the keyboard: " 286 "%s.\n", str_error(rc)); 287 return rc; 288 } 289 290 if (sess_rc != EOK) { 291 usb_log_warning("Error closing session: %s.\n", 292 str_error(sess_rc)); 293 return sess_rc; 294 } 295 296 return EOK; 297 } 298 299 /*----------------------------------------------------------------------------*/ 300 /** 301 * Send Get Protocol request to the HID device. 302 * 303 * @param[in] hid_dev HID device to send the request to. 304 * @param[out] protocol Current protocol of the device. 305 * 306 * @retval EOK if successful. 307 * @retval EINVAL if no HID device is given. 308 * @return Other value inherited from one of functions 309 * usb_endpoint_pipe_start_session(), usb_endpoint_pipe_end_session(), 310 * usb_control_request_set(). 311 */ 312 int usbhid_req_get_protocol(usbhid_dev_t *hid_dev, usb_hid_protocol_t *protocol) 313 { 314 if (hid_dev == NULL) { 315 usb_log_error("usbhid_req_set_protocol(): no HID device " 316 "structure given.\n"); 317 return EINVAL; 318 } 319 320 /* 321 * No need for checking other parameters, as they are checked in 322 * the called function (usb_control_request_set()). 323 */ 324 325 int rc, sess_rc; 326 327 sess_rc = usb_endpoint_pipe_start_session(&hid_dev->ctrl_pipe); 328 if (sess_rc != EOK) { 329 usb_log_warning("Failed to start a session: %s.\n", 330 str_error(sess_rc)); 331 return sess_rc; 332 } 333 334 usb_log_debug("Sending Get_Protocol request to the device (" 335 "iface: %d).\n", hid_dev->iface); 336 337 uint8_t buffer[1]; 338 size_t actual_size = 0; 339 340 rc = usb_control_request_get(&hid_dev->ctrl_pipe, 341 USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 342 USB_HIDREQ_GET_PROTOCOL, 0, hid_dev->iface, buffer, 1, &actual_size); 343 344 sess_rc = usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe); 345 346 if (rc != EOK) { 347 usb_log_warning("Error sending output report to the keyboard: " 348 "%s.\n", str_error(rc)); 349 return rc; 350 } 351 352 if (sess_rc != EOK) { 353 usb_log_warning("Error closing session: %s.\n", 354 str_error(sess_rc)); 355 return sess_rc; 356 } 357 358 if (actual_size != 1) { 359 usb_log_warning("Wrong data size: %zu, expected: 1.\n", 360 actual_size); 361 return ELIMIT; 362 } 363 364 *protocol = buffer[0]; 365 366 return EOK; 367 } 368 369 /*----------------------------------------------------------------------------*/ 370 /** 371 * Send Get Idle request to the HID device. 372 * 373 * @param[in] hid_dev HID device to send the request to. 374 * @param[out] duration Duration value (multiplicate by 4 to get real duration 375 * in miliseconds). 376 * 377 * @retval EOK if successful. 378 * @retval EINVAL if no HID device is given. 379 * @return Other value inherited from one of functions 380 * usb_endpoint_pipe_start_session(), usb_endpoint_pipe_end_session(), 381 * usb_control_request_set(). 382 */ 383 int usbhid_req_get_idle(usbhid_dev_t *hid_dev, uint8_t *duration) 384 { 385 if (hid_dev == NULL) { 386 usb_log_error("usbhid_req_set_idle(): no HID device " 387 "structure given.\n"); 388 return EINVAL; 389 } 390 391 /* 392 * No need for checking other parameters, as they are checked in 393 * the called function (usb_control_request_set()). 394 */ 395 396 int rc, sess_rc; 397 398 sess_rc = usb_endpoint_pipe_start_session(&hid_dev->ctrl_pipe); 399 if (sess_rc != EOK) { 400 usb_log_warning("Failed to start a session: %s.\n", 401 str_error(sess_rc)); 402 return sess_rc; 403 } 404 405 usb_log_debug("Sending Get_Idle request to the device (" 406 "iface: %d).\n", hid_dev->iface); 407 408 uint16_t value = 0; 409 uint8_t buffer[1]; 410 size_t actual_size = 0; 411 412 rc = usb_control_request_get(&hid_dev->ctrl_pipe, 413 USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 414 USB_HIDREQ_GET_IDLE, value, hid_dev->iface, buffer, 1, 415 &actual_size); 416 417 sess_rc = usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe); 418 419 if (rc != EOK) { 420 usb_log_warning("Error sending output report to the keyboard: " 421 "%s.\n", str_error(rc)); 422 return rc; 423 } 424 425 if (sess_rc != EOK) { 426 usb_log_warning("Error closing session: %s.\n", 427 str_error(sess_rc)); 428 return sess_rc; 429 } 430 431 if (actual_size != 1) { 432 usb_log_warning("Wrong data size: %zu, expected: 1.\n", 433 actual_size); 434 return ELIMIT; 435 } 436 437 *duration = buffer[0]; 438 439 return EOK; 440 } 441 442 /*----------------------------------------------------------------------------*/ 144 443 145 444 /** -
uspace/drv/usbhid/hidreq.h
r60a228f r9d9ffdd 50 50 int usbhid_req_set_protocol(usbhid_dev_t *hid_dev, usb_hid_protocol_t protocol); 51 51 52 int usbhid_req_set_idle(usbhid_dev_t *hid_dev, uint8_t duration); 53 54 int usbhid_req_get_report(usbhid_dev_t *hid_dev, usb_hid_report_type_t type, 55 uint8_t *buffer, size_t buf_size, size_t *actual_size); 56 57 int usbhid_req_get_protocol(usbhid_dev_t *hid_dev, usb_hid_protocol_t *protocol); 58 59 int usbhid_req_get_idle(usbhid_dev_t *hid_dev, uint8_t *duration); 60 52 61 /*----------------------------------------------------------------------------*/ 53 62 -
uspace/drv/usbhid/kbddev.c
r60a228f r9d9ffdd 37 37 #include <errno.h> 38 38 #include <str_error.h> 39 #include < fibril.h>39 #include <stdio.h> 40 40 41 41 #include <io/keycode.h> 42 42 #include <ipc/kbd.h> 43 43 #include <async.h> 44 #include <fibril.h> 45 #include <fibril_synch.h> 44 46 45 47 #include <usb/usb.h> … … 55 57 #include "layout.h" 56 58 #include "conv.h" 57 58 /*----------------------------------------------------------------------------*/ 59 59 #include "kbdrepeat.h" 60 61 /*----------------------------------------------------------------------------*/ 62 /** Default modifiers when the keyboard is initialized. */ 60 63 static const unsigned DEFAULT_ACTIVE_MODS = KM_NUM_LOCK; 64 65 /** Boot protocol report size (key part). */ 61 66 static const size_t BOOTP_REPORT_SIZE = 6; 67 68 /** Boot protocol total report size. */ 62 69 static const size_t BOOTP_BUFFER_SIZE = 8; 70 71 /** Boot protocol output report size. */ 63 72 static const size_t BOOTP_BUFFER_OUT_SIZE = 1; 73 74 /** Boot protocol error key code. */ 75 static const uint8_t BOOTP_ERROR_ROLLOVER = 1; 76 77 /** Default idle rate for keyboards. */ 78 static const uint8_t IDLE_RATE = 0; 79 80 /** Delay before a pressed key starts auto-repeating. */ 81 static const unsigned int DEFAULT_DELAY_BEFORE_FIRST_REPEAT = 500 * 1000; 82 83 /** Delay between two repeats of a pressed key when auto-repeating. */ 84 static const unsigned int DEFAULT_REPEAT_DELAY = 50 * 1000; 64 85 65 86 /** Keyboard polling endpoint description for boot protocol class. */ … … 79 100 #define NUM_LAYOUTS 3 80 101 102 /** Keyboard layout map. */ 81 103 static layout_op_t *layout[NUM_LAYOUTS] = { 82 104 &us_qwerty_op, … … 90 112 /* Modifier constants */ 91 113 /*----------------------------------------------------------------------------*/ 92 114 /** Mapping of USB modifier key codes to generic modifier key codes. */ 93 115 static const keycode_t usbhid_modifiers_keycodes[USB_HID_MOD_COUNT] = { 94 116 KC_LCTRL, /* USB_HID_MOD_LCTRL */ … … 111 133 }; 112 134 113 /** Default handler for IPC methods not handled by DDF. 114 * 115 * @param dev Device handling the call. 135 /** 136 * Default handler for IPC methods not handled by DDF. 137 * 138 * Currently recognizes only one method (IPC_M_CONNECT_TO_ME), in which case it 139 * assumes the caller is the console and thus it stores IPC phone to it for 140 * later use by the driver to notify about key events. 141 * 142 * @param fun Device function handling the call. 116 143 * @param icallid Call id. 117 144 * @param icall Call data. … … 144 171 /* Key processing functions */ 145 172 /*----------------------------------------------------------------------------*/ 146 173 /** 174 * Handles turning of LED lights on and off. 175 * 176 * In case of USB keyboards, the LEDs are handled in the driver, not in the 177 * device. When there should be a change (lock key was pressed), the driver 178 * uses a Set_Report request sent to the device to set the state of the LEDs. 179 * 180 * This functions sets the LED lights according to current settings of modifiers 181 * kept in the keyboard device structure. 182 * 183 * @param kbd_dev Keyboard device structure. 184 */ 147 185 static void usbhid_kbd_set_led(usbhid_kbd_t *kbd_dev) 148 186 { 149 187 uint8_t buffer[BOOTP_BUFFER_OUT_SIZE]; 150 188 int rc= 0; 151 unsigned i;152 189 153 190 memset(buffer, 0, BOOTP_BUFFER_OUT_SIZE); … … 177 214 } 178 215 179 // TODO: REFACTOR!!! 180 181 usb_log_debug("Output report buffer: "); 182 for (i = 0; i < BOOTP_BUFFER_OUT_SIZE; ++i) { 183 usb_log_debug("0x%x ", buffer[i]); 184 } 185 usb_log_debug("\n"); 186 187 uint16_t value = 0; 188 value |= (USB_HID_REPORT_TYPE_OUTPUT << 8); 189 216 usb_log_debug("Output report buffer: %s\n", 217 usb_debug_str_buffer(buffer, BOOTP_BUFFER_OUT_SIZE, 0)); 218 190 219 assert(kbd_dev->hid_dev != NULL); 191 220 assert(kbd_dev->hid_dev->initialized); 192 usbhid_req_set_report(kbd_dev->hid_dev, value, buffer, 193 BOOTP_BUFFER_OUT_SIZE); 194 } 195 196 /*----------------------------------------------------------------------------*/ 197 198 static void usbhid_kbd_push_ev(usbhid_kbd_t *kbd_dev, int type, 199 unsigned int key) 221 usbhid_req_set_report(kbd_dev->hid_dev, USB_HID_REPORT_TYPE_OUTPUT, 222 buffer, BOOTP_BUFFER_OUT_SIZE); 223 } 224 225 /*----------------------------------------------------------------------------*/ 226 /** 227 * Processes key events. 228 * 229 * @note This function was copied from AT keyboard driver and modified to suit 230 * USB keyboard. 231 * 232 * @note Lock keys are not sent to the console, as they are completely handled 233 * in the driver. It may, however, be required later that the driver 234 * sends also these keys to application (otherwise it cannot use those 235 * keys at all). 236 * 237 * @param kbd_dev Keyboard device structure. 238 * @param type Type of the event (press / release). Recognized values: 239 * KEY_PRESS, KEY_RELEASE 240 * @param key Key code of the key according to HID Usage Tables. 241 */ 242 void usbhid_kbd_push_ev(usbhid_kbd_t *kbd_dev, int type, unsigned int key) 200 243 { 201 244 console_event_t ev; 202 245 unsigned mod_mask; 203 246 204 // TODO: replace by our own parsing?? or are the key codes identical?? 247 /* 248 * These parts are copy-pasted from the AT keyboard driver. 249 * 250 * They definitely require some refactoring, but will keep it for later 251 * when the console and keyboard system is changed in HelenOS. 252 */ 205 253 switch (key) { 206 254 case KC_LCTRL: mod_mask = KM_LCTRL; break; … … 228 276 229 277 if (mod_mask != 0) { 230 usb_log_debug2("\n\nChanging mods and lock keys\n");231 usb_log_debug2("\nmods before: 0x%x\n", kbd_dev->mods);232 usb_log_debug2("\nLock keys before:0x%x\n\n",233 kbd_dev->lock_keys);234 235 278 if (type == KEY_PRESS) { 236 usb_log_debug2("\nKey pressed.\n");237 279 /* 238 280 * Only change lock state on transition from released … … 240 282 * up the lock state. 241 283 */ 284 unsigned int locks_old = kbd_dev->lock_keys; 285 242 286 kbd_dev->mods = 243 287 kbd_dev->mods ^ (mod_mask & ~kbd_dev->lock_keys); … … 245 289 246 290 /* Update keyboard lock indicator lights. */ 247 usbhid_kbd_set_led(kbd_dev); 291 if (kbd_dev->lock_keys != locks_old) { 292 usbhid_kbd_set_led(kbd_dev); 293 } 248 294 } else { 249 usb_log_debug2("\nKey released.\n");250 295 kbd_dev->lock_keys = kbd_dev->lock_keys & ~mod_mask; 251 296 } 252 297 } 253 298 254 usb_log_debug2("\n\nmods after: 0x%x\n", kbd_dev->mods);255 usb_log_debug2("\nLock keys after: 0x%x\n\n", kbd_dev->lock_keys);256 257 299 if (key == KC_CAPS_LOCK || key == KC_NUM_LOCK || key == KC_SCROLL_LOCK) { 258 300 // do not send anything to the console, this is our business … … 281 323 ev.key = key; 282 324 ev.mods = kbd_dev->mods; 283 284 if (ev.mods & KM_NUM_LOCK) {285 usb_log_debug("\n\nNum Lock turned on.\n\n");286 }287 325 288 326 ev.c = layout[active_layout]->parse_ev(&ev); 289 327 290 328 usb_log_debug2("Sending key %d to the console\n", ev.key); 291 assert(kbd_dev->console_phone != -1); 329 if (kbd_dev->console_phone < 0) { 330 usb_log_warning( 331 "Connection to console not ready, key discarded.\n"); 332 return; 333 } 292 334 293 335 async_msg_4(kbd_dev->console_phone, KBD_EVENT, ev.type, ev.key, … … 296 338 297 339 /*----------------------------------------------------------------------------*/ 298 340 /** 341 * Checks if modifiers were pressed or released and generates key events. 342 * 343 * @param kbd_dev Keyboard device structure. 344 * @param modifiers Bitmap of modifiers. 345 * 346 * @sa usbhid_kbd_push_ev() 347 */ 299 348 static void usbhid_kbd_check_modifier_changes(usbhid_kbd_t *kbd_dev, 300 349 uint8_t modifiers) … … 332 381 333 382 /*----------------------------------------------------------------------------*/ 334 383 /** 384 * Checks if some keys were pressed or released and generates key events. 385 * 386 * An event is created only when key is pressed or released. Besides handling 387 * the events (usbhid_kbd_push_ev()), the auto-repeat fibril is notified about 388 * key presses and releases (see usbhid_kbd_repeat_start() and 389 * usbhid_kbd_repeat_stop()). 390 * 391 * @param kbd_dev Keyboard device structure. 392 * @param key_codes Parsed keyboard report - codes of currently pressed keys 393 * according to HID Usage Tables. 394 * @param count Number of key codes in report (size of the report). 395 * 396 * @sa usbhid_kbd_push_ev(), usbhid_kbd_repeat_start(), usbhid_kbd_repeat_stop() 397 */ 335 398 static void usbhid_kbd_check_key_changes(usbhid_kbd_t *kbd_dev, 336 const uint8_t *key_codes) 337 { 338 // TODO: phantom state!! 339 399 const uint8_t *key_codes, size_t count) 400 { 340 401 unsigned int key; 341 402 unsigned int i, j; 342 403 343 // TODO: quite dummy right now, think of better implementation 404 /* 405 * First of all, check if the kbd have reported phantom state. 406 */ 407 i = 0; 408 // all fields should report Error Rollover 409 while (i < count && 410 key_codes[i] == BOOTP_ERROR_ROLLOVER) { 411 ++i; 412 } 413 if (i == count) { 414 usb_log_debug("Phantom state occured.\n"); 415 // phantom state, do nothing 416 return; 417 } 418 419 /* TODO: quite dummy right now, think of better implementation */ 420 assert(count == kbd_dev->key_count); 344 421 345 422 /* 346 423 * 1) Key releases 347 424 */ 348 for (j = 0; j < kbd_dev->keycode_count; ++j) {425 for (j = 0; j < count; ++j) { 349 426 // try to find the old key in the new key list 350 427 i = 0; 351 while (i < kbd_dev->key code_count352 && key_codes[i] != kbd_dev->key codes[j]) {428 while (i < kbd_dev->key_count 429 && key_codes[i] != kbd_dev->keys[j]) { 353 430 ++i; 354 431 } 355 432 356 if (i == kbd_dev->keycode_count) {433 if (i == count) { 357 434 // not found, i.e. the key was released 358 key = usbhid_parse_scancode(kbd_dev->keycodes[j]); 435 key = usbhid_parse_scancode(kbd_dev->keys[j]); 436 usbhid_kbd_repeat_stop(kbd_dev, key); 359 437 usbhid_kbd_push_ev(kbd_dev, KEY_RELEASE, key); 360 usb_log_debug2(" \nKey released: %d\n", key);438 usb_log_debug2("Key released: %d\n", key); 361 439 } else { 362 440 // found, nothing happens … … 367 445 * 1) Key presses 368 446 */ 369 for (i = 0; i < kbd_dev->key code_count; ++i) {447 for (i = 0; i < kbd_dev->key_count; ++i) { 370 448 // try to find the new key in the old key list 371 449 j = 0; 372 while (j < kbd_dev->keycode_count 373 && kbd_dev->keycodes[j] != key_codes[i]) { 450 while (j < count && kbd_dev->keys[j] != key_codes[i]) { 374 451 ++j; 375 452 } 376 453 377 if (j == kbd_dev->keycode_count) {454 if (j == count) { 378 455 // not found, i.e. new key pressed 379 456 key = usbhid_parse_scancode(key_codes[i]); 380 usb_log_debug2(" \nKey pressed: %d (keycode: %d)\n", key,457 usb_log_debug2("Key pressed: %d (keycode: %d)\n", key, 381 458 key_codes[i]); 382 459 usbhid_kbd_push_ev(kbd_dev, KEY_PRESS, key); 460 usbhid_kbd_repeat_start(kbd_dev, key); 383 461 } else { 384 462 // found, nothing happens … … 386 464 } 387 465 388 memcpy(kbd_dev->keycodes, key_codes, kbd_dev->keycode_count); 389 390 usb_log_debug2("\nNew stored keycodes: "); 391 for (i = 0; i < kbd_dev->keycode_count; ++i) { 392 usb_log_debug2("%d ", kbd_dev->keycodes[i]); 393 } 466 memcpy(kbd_dev->keys, key_codes, count); 467 468 usb_log_debug("New stored keycodes: %s\n", 469 usb_debug_str_buffer(kbd_dev->keys, kbd_dev->key_count, 0)); 394 470 } 395 471 … … 397 473 /* Callbacks for parser */ 398 474 /*----------------------------------------------------------------------------*/ 399 475 /** 476 * Callback function for the HID report parser. 477 * 478 * This function is called by the HID report parser with the parsed report. 479 * The parsed report is used to check if any events occured (key was pressed or 480 * released, modifier was pressed or released). 481 * 482 * @param key_codes Parsed keyboard report - codes of currently pressed keys 483 * according to HID Usage Tables. 484 * @param count Number of key codes in report (size of the report). 485 * @param modifiers Bitmap of modifiers (Ctrl, Alt, Shift, GUI). 486 * @param arg User-specified argument. Expects pointer to the keyboard device 487 * structure representing the keyboard. 488 * 489 * @sa usbhid_kbd_check_key_changes(), usbhid_kbd_check_modifier_changes() 490 */ 400 491 static void usbhid_kbd_process_keycodes(const uint8_t *key_codes, size_t count, 401 492 uint8_t modifiers, void *arg) … … 406 497 return; 407 498 } 408 409 usb_log_debug2("Got keys from parser: ");410 unsigned i;411 for (i = 0; i < count; ++i) {412 usb_log_debug2("%d ", key_codes[i]);413 }414 usb_log_debug2("\n");415 499 416 500 usbhid_kbd_t *kbd_dev = (usbhid_kbd_t *)arg; 417 501 assert(kbd_dev != NULL); 418 419 if (count != kbd_dev->keycode_count) { 502 503 usb_log_debug("Got keys from parser: %s\n", 504 usb_debug_str_buffer(key_codes, count, 0)); 505 506 if (count != kbd_dev->key_count) { 420 507 usb_log_warning("Number of received keycodes (%d) differs from" 421 " expected number (%d).\n", count, kbd_dev->key code_count);508 " expected number (%d).\n", count, kbd_dev->key_count); 422 509 return; 423 510 } 424 511 425 512 usbhid_kbd_check_modifier_changes(kbd_dev, modifiers); 426 usbhid_kbd_check_key_changes(kbd_dev, key_codes );513 usbhid_kbd_check_key_changes(kbd_dev, key_codes, count); 427 514 } 428 515 … … 430 517 /* General kbd functions */ 431 518 /*----------------------------------------------------------------------------*/ 432 519 /** 520 * Processes data received from the device in form of report. 521 * 522 * This function uses the HID report parser to translate the data received from 523 * the device into generic USB HID key codes and into generic modifiers bitmap. 524 * The parser then calls the given callback (usbhid_kbd_process_keycodes()). 525 * 526 * @note Currently, only the boot protocol is supported. 527 * 528 * @param kbd_dev Keyboard device structure (must be initialized). 529 * @param buffer Data from the keyboard (i.e. the report). 530 * @param actual_size Size of the data from keyboard (report size) in bytes. 531 * 532 * @sa usbhid_kbd_process_keycodes(), usb_hid_boot_keyboard_input_report(). 533 */ 433 534 static void usbhid_kbd_process_data(usbhid_kbd_t *kbd_dev, 434 535 uint8_t *buffer, size_t actual_size) 435 536 { 537 assert(kbd_dev->initialized); 538 assert(kbd_dev->hid_dev->parser != NULL); 539 436 540 usb_hid_report_in_callbacks_t *callbacks = 437 541 (usb_hid_report_in_callbacks_t *)malloc( … … 440 544 callbacks->keyboard = usbhid_kbd_process_keycodes; 441 545 442 //usb_hid_parse_report(kbd_dev->parser, buffer, actual_size, callbacks, 443 // NULL); 444 /*usb_log_debug2("Calling usb_hid_boot_keyboard_input_report() with size" 445 " %zu\n", actual_size);*/ 446 //dump_buffer("bufffer: ", buffer, actual_size); 447 448 int rc = usb_hid_boot_keyboard_input_report(buffer, actual_size, 449 callbacks, kbd_dev); 546 usb_log_debug("Calling usb_hid_parse_report() with " 547 "buffer %s\n", usb_debug_str_buffer(buffer, actual_size, 0)); 548 549 // int rc = usb_hid_boot_keyboard_input_report(buffer, actual_size, 550 // callbacks, kbd_dev); 551 int rc = usb_hid_parse_report(kbd_dev->hid_dev->parser, buffer, 552 actual_size, callbacks, kbd_dev); 450 553 451 554 if (rc != EOK) { … … 458 561 /* HID/KBD structure manipulation */ 459 562 /*----------------------------------------------------------------------------*/ 460 563 /** 564 * Creates a new USB/HID keyboard structure. 565 * 566 * The structure returned by this function is not initialized. Use 567 * usbhid_kbd_init() to initialize it prior to polling. 568 * 569 * @return New uninitialized structure for representing a USB/HID keyboard or 570 * NULL if not successful (memory error). 571 */ 461 572 static usbhid_kbd_t *usbhid_kbd_new(void) 462 573 { … … 484 595 485 596 /*----------------------------------------------------------------------------*/ 486 597 /** 598 * Properly destroys the USB/HID keyboard structure. 599 * 600 * @param kbd_dev Pointer to the structure to be destroyed. 601 */ 487 602 static void usbhid_kbd_free(usbhid_kbd_t **kbd_dev) 488 603 { … … 499 614 } 500 615 616 if ((*kbd_dev)->repeat_mtx != NULL) { 617 /* TODO: replace by some check and wait */ 618 assert(!fibril_mutex_is_locked((*kbd_dev)->repeat_mtx)); 619 free((*kbd_dev)->repeat_mtx); 620 } 621 501 622 free(*kbd_dev); 502 623 *kbd_dev = NULL; … … 504 625 505 626 /*----------------------------------------------------------------------------*/ 506 627 /** 628 * Initialization of the USB/HID keyboard structure. 629 * 630 * This functions initializes required structures from the device's descriptors. 631 * 632 * During initialization, the keyboard is switched into boot protocol, the idle 633 * rate is set to 0 (infinity), resulting in the keyboard only reporting event 634 * when a key is pressed or released. Finally, the LED lights are turned on 635 * according to the default setup of lock keys. 636 * 637 * @note By default, the keyboards is initialized with Num Lock turned on and 638 * other locks turned off. 639 * 640 * @param kbd_dev Keyboard device structure to be initialized. 641 * @param dev DDF device structure of the keyboard. 642 * 643 * @retval EOK if successful. 644 * @retval EINVAL if some parameter is not given. 645 * @return Other value inherited from function usbhid_dev_init(). 646 */ 507 647 static int usbhid_kbd_init(usbhid_kbd_t *kbd_dev, ddf_dev_t *dev) 508 648 { … … 539 679 540 680 // save the size of the report (boot protocol report by default) 541 kbd_dev->key code_count = BOOTP_REPORT_SIZE;542 kbd_dev->key codes = (uint8_t *)calloc(543 kbd_dev->key code_count, sizeof(uint8_t));544 545 if (kbd_dev->key codes == NULL) {681 kbd_dev->key_count = BOOTP_REPORT_SIZE; 682 kbd_dev->keys = (uint8_t *)calloc( 683 kbd_dev->key_count, sizeof(uint8_t)); 684 685 if (kbd_dev->keys == NULL) { 546 686 usb_log_fatal("No memory!\n"); 547 return rc;687 return ENOMEM; 548 688 } 549 689 … … 552 692 kbd_dev->lock_keys = 0; 553 693 694 kbd_dev->repeat.key_new = 0; 695 kbd_dev->repeat.key_repeated = 0; 696 kbd_dev->repeat.delay_before = DEFAULT_DELAY_BEFORE_FIRST_REPEAT; 697 kbd_dev->repeat.delay_between = DEFAULT_REPEAT_DELAY; 698 699 kbd_dev->repeat_mtx = (fibril_mutex_t *)( 700 malloc(sizeof(fibril_mutex_t))); 701 if (kbd_dev->repeat_mtx == NULL) { 702 usb_log_fatal("No memory!\n"); 703 free(kbd_dev->keys); 704 return ENOMEM; 705 } 706 707 fibril_mutex_initialize(kbd_dev->repeat_mtx); 708 554 709 /* 555 710 * Set boot protocol. 556 711 * Set LEDs according to initial setup. 712 * Set Idle rate 557 713 */ 558 714 assert(kbd_dev->hid_dev != NULL); 559 715 assert(kbd_dev->hid_dev->initialized); 560 usbhid_req_set_protocol(kbd_dev->hid_dev, USB_HID_PROTOCOL_BOOT);716 //usbhid_req_set_protocol(kbd_dev->hid_dev, USB_HID_PROTOCOL_BOOT); 561 717 562 718 usbhid_kbd_set_led(kbd_dev); 719 720 usbhid_req_set_idle(kbd_dev->hid_dev, IDLE_RATE); 563 721 564 722 kbd_dev->initialized = 1; … … 571 729 /* HID/KBD polling */ 572 730 /*----------------------------------------------------------------------------*/ 573 731 /** 732 * Main keyboard polling function. 733 * 734 * This function uses the Interrupt In pipe of the keyboard to poll for events. 735 * The keyboard is initialized in a way that it reports only when a key is 736 * pressed or released, so there is no actual need for any sleeping between 737 * polls (see usbhid_kbd_try_add_device() or usbhid_kbd_init()). 738 * 739 * @param kbd_dev Initialized keyboard structure representing the device to 740 * poll. 741 * 742 * @sa usbhid_kbd_process_data() 743 */ 574 744 static void usbhid_kbd_poll(usbhid_kbd_t *kbd_dev) 575 745 { … … 589 759 590 760 while (true) { 591 async_usleep(1000 * 10);592 593 761 sess_rc = usb_endpoint_pipe_start_session( 594 762 &kbd_dev->hid_dev->poll_pipe); … … 596 764 usb_log_warning("Failed to start a session: %s.\n", 597 765 str_error(sess_rc)); 598 continue;766 break; 599 767 } 600 768 … … 608 776 usb_log_warning("Error polling the keyboard: %s.\n", 609 777 str_error(rc)); 610 continue;778 break; 611 779 } 612 780 … … 614 782 usb_log_warning("Error closing session: %s.\n", 615 783 str_error(sess_rc)); 616 continue;784 break; 617 785 } 618 786 … … 631 799 usb_log_debug("Calling usbhid_kbd_process_data()\n"); 632 800 usbhid_kbd_process_data(kbd_dev, buffer, actual_size); 633 } 634 635 // not reached 636 assert(0); 637 } 638 639 /*----------------------------------------------------------------------------*/ 640 801 802 // disabled for now, no reason to sleep 803 //async_usleep(kbd_dev->hid_dev->poll_interval); 804 } 805 } 806 807 /*----------------------------------------------------------------------------*/ 808 /** 809 * Function executed by the main driver fibril. 810 * 811 * Just starts polling the keyboard for events. 812 * 813 * @param arg Initialized keyboard device structure (of type usbhid_kbd_t) 814 * representing the device. 815 * 816 * @retval EOK if the fibril finished polling the device. 817 * @retval EINVAL if no device was given in the argument. 818 * 819 * @sa usbhid_kbd_poll() 820 * 821 * @todo Change return value - only case when the fibril finishes is in case 822 * of some error, so the error should probably be propagated from function 823 * usbhid_kbd_poll() to here and up. 824 */ 641 825 static int usbhid_kbd_fibril(void *arg) 642 826 { … … 660 844 /* API functions */ 661 845 /*----------------------------------------------------------------------------*/ 662 846 /** 847 * Function for adding a new device of type USB/HID/keyboard. 848 * 849 * This functions initializes required structures from the device's descriptors 850 * and starts new fibril for polling the keyboard for events and another one for 851 * handling auto-repeat of keys. 852 * 853 * During initialization, the keyboard is switched into boot protocol, the idle 854 * rate is set to 0 (infinity), resulting in the keyboard only reporting event 855 * when a key is pressed or released. Finally, the LED lights are turned on 856 * according to the default setup of lock keys. 857 * 858 * @note By default, the keyboards is initialized with Num Lock turned on and 859 * other locks turned off. 860 * @note Currently supports only boot-protocol keyboards. 861 * 862 * @param dev Device to add. 863 * 864 * @retval EOK if successful. 865 * @retval ENOMEM if there 866 * @return Other error code inherited from one of functions usbhid_kbd_init(), 867 * ddf_fun_bind() and ddf_fun_add_to_class(). 868 * 869 * @sa usbhid_kbd_fibril(), usbhid_kbd_repeat_fibril() 870 */ 663 871 int usbhid_kbd_try_add_device(ddf_dev_t *dev) 664 872 { … … 682 890 "structure.\n"); 683 891 ddf_fun_destroy(kbd_fun); 684 return E INVAL; // TODO: some other code??892 return ENOMEM; // TODO: some other code?? 685 893 } 686 894 … … 731 939 } 732 940 fibril_add_ready(fid); 941 942 /* 943 * Create new fibril for auto-repeat 944 */ 945 fid = fibril_create(usbhid_kbd_repeat_fibril, kbd_dev); 946 if (fid == 0) { 947 usb_log_error("Failed to start fibril for KBD auto-repeat"); 948 return ENOMEM; 949 } 950 fibril_add_ready(fid); 733 951 734 952 (void)keyboard_ops; -
uspace/drv/usbhid/kbddev.h
r60a228f r9d9ffdd 39 39 #include <stdint.h> 40 40 41 #include <fibril_synch.h> 42 41 43 #include <usb/classes/hid.h> 44 #include <usb/classes/hidparser.h> 42 45 #include <ddf/driver.h> 43 46 #include <usb/pipes.h> … … 46 49 47 50 /*----------------------------------------------------------------------------*/ 51 /** 52 * Structure for keeping information needed for auto-repeat of keys. 53 */ 54 typedef struct { 55 /** Last pressed key. */ 56 unsigned int key_new; 57 /** Key to be repeated. */ 58 unsigned int key_repeated; 59 /** Delay before first repeat in microseconds. */ 60 unsigned int delay_before; 61 /** Delay between repeats in microseconds. */ 62 unsigned int delay_between; 63 } usbhid_kbd_repeat_t; 48 64 49 65 /** 50 * @brief USB/HID keyboard device type. 66 * USB/HID keyboard device type. 67 * 68 * Holds a reference to generic USB/HID device structure and keyboard-specific 69 * data, such as currently pressed keys, modifiers and lock keys. 70 * 71 * Also holds a IPC phone to the console (since there is now no other way to 72 * communicate with it). 73 * 74 * @note Storing active lock keys in this structure results in their setting 75 * being device-specific. 51 76 */ 52 77 typedef struct { 78 /** Structure holding generic USB/HID device information. */ 53 79 usbhid_dev_t *hid_dev; 54 80 55 uint8_t *keycodes; 56 size_t keycode_count; 81 /** Currently pressed keys (not translated to key codes). */ 82 uint8_t *keys; 83 /** Count of stored keys (i.e. number of keys in the report). */ 84 size_t key_count; 85 /** Currently pressed modifiers (bitmap). */ 57 86 uint8_t modifiers; 58 87 88 /** Currently active modifiers including locks. Sent to the console. */ 59 89 unsigned mods; 90 91 /** Currently active lock keys. */ 60 92 unsigned lock_keys; 61 93 94 /** IPC phone to the console device (for sending key events). */ 62 95 int console_phone; 63 96 97 /** Information for auto-repeat of keys. */ 98 usbhid_kbd_repeat_t repeat; 99 100 /** Mutex for accessing the information about auto-repeat. */ 101 fibril_mutex_t *repeat_mtx; 102 103 /** State of the structure (for checking before use). */ 64 104 int initialized; 65 105 } usbhid_kbd_t; … … 69 109 int usbhid_kbd_try_add_device(ddf_dev_t *dev); 70 110 111 void usbhid_kbd_push_ev(usbhid_kbd_t *kbd_dev, int type, unsigned int key); 112 71 113 #endif /* USBHID_KBDDEV_H_ */ 72 114 -
uspace/drv/usbhid/main.c
r60a228f r9d9ffdd 47 47 48 48 /*----------------------------------------------------------------------------*/ 49 49 /** 50 * Callback for passing a new device to the driver. 51 * 52 * @note Currently, only boot-protocol keyboards are supported by this driver. 53 * 54 * @param dev Structure representing the new device. 55 * 56 * @retval EOK if successful. 57 * @retval EREFUSED if the device is not supported. 58 */ 50 59 static int usbhid_add_device(ddf_dev_t *dev) 51 60 { … … 80 89 int main(int argc, char *argv[]) 81 90 { 82 usb_log_enable(USB_LOG_LEVEL_ INFO, NAME);91 usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME); 83 92 return ddf_driver_main(&kbd_driver); 84 93 } -
uspace/drv/usbhid/usbhid.ma
r60a228f r9d9ffdd 1 10 usb&class=hid 2 10 usb&class=HID 1 100 usb&interface&class=HID&subclass=0x01&protocol=0x01 3 2 10 usb&interface&class=HID 4 10 usb&hid
Note:
See TracChangeset
for help on using the changeset viewer.
