Changeset 9d9ffdd in mainline for uspace/drv
- 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
- Files:
-
- 12 added
- 39 edited
- 1 moved
-
ehci-hcd/Makefile (added)
-
ehci-hcd/ehci-hcd.ma (added)
-
ehci-hcd/main.c (added)
-
ehci-hcd/pci.c (added)
-
ehci-hcd/pci.h (added)
-
pciintel/pci.c (modified) (7 diffs)
-
uhci-hcd/batch.c (modified) (11 diffs)
-
uhci-hcd/batch.h (modified) (4 diffs)
-
uhci-hcd/iface.c (modified) (14 diffs)
-
uhci-hcd/main.c (modified) (5 diffs)
-
uhci-hcd/pci.c (modified) (5 diffs)
-
uhci-hcd/pci.h (modified) (1 diff)
-
uhci-hcd/root_hub.c (modified) (5 diffs)
-
uhci-hcd/transfer_list.c (modified) (7 diffs)
-
uhci-hcd/transfer_list.h (modified) (1 diff)
-
uhci-hcd/uhci.c (modified) (19 diffs)
-
uhci-hcd/uhci.h (modified) (1 diff)
-
uhci-hcd/uhci_struct/queue_head.h (modified) (2 diffs)
-
uhci-hcd/uhci_struct/transfer_descriptor.c (modified) (3 diffs)
-
uhci-hcd/uhci_struct/transfer_descriptor.h (modified) (1 diff)
-
uhci-hcd/utils/device_keeper.c (modified) (9 diffs)
-
uhci-hcd/utils/device_keeper.h (modified) (2 diffs)
-
uhci-hcd/utils/malloc32.h (modified) (1 diff)
-
uhci-rhd/main.c (modified) (8 diffs)
-
uhci-rhd/port.c (modified) (10 diffs)
-
uhci-rhd/port_status.c (modified) (1 diff)
-
uhci-rhd/root_hub.c (modified) (4 diffs)
-
usbhid/Makefile (modified) (1 diff)
-
usbhid/conv.c (modified) (2 diffs)
-
usbhid/descdump.c (modified) (7 diffs)
-
usbhid/hiddev.c (modified) (13 diffs)
-
usbhid/hiddev.h (modified) (1 diff)
-
usbhid/hidreq.c (modified) (4 diffs)
-
usbhid/hidreq.h (modified) (1 diff)
-
usbhid/kbddev.c (modified) (34 diffs)
-
usbhid/kbddev.h (modified) (3 diffs)
-
usbhid/kbdrepeat.c (added)
-
usbhid/kbdrepeat.h (added)
-
usbhid/main.c (modified) (2 diffs)
-
usbhid/usbhid.ma (modified) (1 diff)
-
usbhub/usbhub.c (modified) (7 diffs)
-
usbmid/explore.c (modified) (4 diffs)
-
usbmid/main.c (modified) (2 diffs)
-
usbmid/usbmid.c (modified) (3 diffs)
-
usbmid/usbmid.h (modified) (2 diffs)
-
usbmouse/Makefile (added)
-
usbmouse/init.c (added)
-
usbmouse/main.c (moved) (moved from uspace/lib/usb/include/usb/usbmem.h ) (2 diffs)
-
usbmouse/mouse.c (added)
-
usbmouse/mouse.h (added)
-
usbmouse/usbmouse.ma (added)
-
vhc/conndev.c (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/pciintel/pci.c
r60a228f r9d9ffdd 59 59 #include <ddi.h> 60 60 #include <libarch/ddi.h> 61 #include <pci_dev_iface.h> 61 62 62 63 #include "pci.h" … … 93 94 sysarg_t apic; 94 95 sysarg_t i8259; 96 95 97 int irc_phone = -1; 96 98 int irc_service = 0; … … 102 104 } 103 105 104 if (irc_service) { 105 while (irc_phone < 0) 106 irc_phone = service_connect_blocking(irc_service, 0, 0); 107 } else { 106 if (irc_service == 0) 108 107 return false; 109 } 108 109 irc_phone = service_connect_blocking(irc_service, 0, 0); 110 if (irc_phone < 0) 111 return false; 110 112 111 113 size_t i; … … 113 115 if (dev_data->hw_resources.resources[i].type == INTERRUPT) { 114 116 int irq = dev_data->hw_resources.resources[i].res.interrupt.irq; 115 async_msg_1(irc_phone, IRC_ENABLE_INTERRUPT, irq); 117 int rc = async_req_1_0(irc_phone, IRC_ENABLE_INTERRUPT, irq); 118 if (rc != EOK) { 119 async_hangup(irc_phone); 120 return false; 121 } 116 122 } 117 123 } … … 119 125 async_hangup(irc_phone); 120 126 return true; 127 } 128 129 static int pci_config_space_write_32( 130 ddf_fun_t *fun, uint32_t address, uint32_t data) 131 { 132 if (address > 252) 133 return EINVAL; 134 pci_conf_write_32(PCI_FUN(fun), address, data); 135 return EOK; 136 } 137 138 static int pci_config_space_write_16( 139 ddf_fun_t *fun, uint32_t address, uint16_t data) 140 { 141 if (address > 254) 142 return EINVAL; 143 pci_conf_write_16(PCI_FUN(fun), address, data); 144 return EOK; 145 } 146 147 static int pci_config_space_write_8( 148 ddf_fun_t *fun, uint32_t address, uint8_t data) 149 { 150 if (address > 255) 151 return EINVAL; 152 pci_conf_write_8(PCI_FUN(fun), address, data); 153 return EOK; 154 } 155 156 static int pci_config_space_read_32( 157 ddf_fun_t *fun, uint32_t address, uint32_t *data) 158 { 159 if (address > 252) 160 return EINVAL; 161 *data = pci_conf_read_32(PCI_FUN(fun), address); 162 return EOK; 163 } 164 165 static int pci_config_space_read_16( 166 ddf_fun_t *fun, uint32_t address, uint16_t *data) 167 { 168 if (address > 254) 169 return EINVAL; 170 *data = pci_conf_read_16(PCI_FUN(fun), address); 171 return EOK; 172 } 173 174 static int pci_config_space_read_8( 175 ddf_fun_t *fun, uint32_t address, uint8_t *data) 176 { 177 if (address > 255) 178 return EINVAL; 179 *data = pci_conf_read_8(PCI_FUN(fun), address); 180 return EOK; 121 181 } 122 182 … … 126 186 }; 127 187 128 static ddf_dev_ops_t pci_fun_ops; 188 static pci_dev_iface_t pci_dev_ops = { 189 .config_space_read_8 = &pci_config_space_read_8, 190 .config_space_read_16 = &pci_config_space_read_16, 191 .config_space_read_32 = &pci_config_space_read_32, 192 .config_space_write_8 = &pci_config_space_write_8, 193 .config_space_write_16 = &pci_config_space_write_16, 194 .config_space_write_32 = &pci_config_space_write_32 195 }; 196 197 static ddf_dev_ops_t pci_fun_ops = { 198 .interfaces[HW_RES_DEV_IFACE] = &pciintel_hw_res_ops, 199 .interfaces[PCI_DEV_IFACE] = &pci_dev_ops 200 }; 129 201 130 202 static int pci_add_device(ddf_dev_t *); … … 593 665 { 594 666 pci_fun_ops.interfaces[HW_RES_DEV_IFACE] = &pciintel_hw_res_ops; 667 pci_fun_ops.interfaces[PCI_DEV_IFACE] = &pci_dev_ops; 595 668 } 596 669 -
uspace/drv/uhci-hcd/batch.c
r60a228f r9d9ffdd 35 35 #include <str_error.h> 36 36 37 #include <usb/usb.h> 37 38 #include <usb/debug.h> 38 39 … … 46 47 static int batch_schedule(batch_t *instance); 47 48 49 static void batch_control(batch_t *instance, 50 usb_packet_id data_stage, usb_packet_id status_stage); 51 static void batch_data(batch_t *instance, usb_packet_id pid); 48 52 static void batch_call_in(batch_t *instance); 49 53 static void batch_call_out(batch_t *instance); 50 54 static void batch_call_in_and_dispose(batch_t *instance); 51 55 static void batch_call_out_and_dispose(batch_t *instance); 52 53 56 static void batch_dispose(batch_t *instance); 57 58 59 /** Allocates memory and initializes internal data structures. 60 * 61 * @param[in] fun DDF function to pass to callback. 62 * @param[in] target Device and endpoint target of the transaction. 63 * @param[in] transfer_type Interrupt, Control or Bulk. 64 * @param[in] max_packet_size maximum allowed size of data packets. 65 * @param[in] speed Speed of the transaction. 66 * @param[in] buffer Data source/destination. 67 * @param[in] size Size of the buffer. 68 * @param[in] setup_buffer Setup data source (if not NULL) 69 * @param[in] setup_size Size of setup_buffer (should be always 8) 70 * @param[in] func_in function to call on inbound transaction completion 71 * @param[in] func_out function to call on outbound transaction completion 72 * @param[in] arg additional parameter to func_in or func_out 73 * @param[in] manager Pointer to toggle management structure. 74 * @return False, if there is an active TD, true otherwise. 75 */ 54 76 batch_t * batch_get(ddf_fun_t *fun, usb_target_t target, 55 77 usb_transfer_type_t transfer_type, size_t max_packet_size, … … 57 79 char* setup_buffer, size_t setup_size, 58 80 usbhc_iface_transfer_in_callback_t func_in, 59 usbhc_iface_transfer_out_callback_t func_out, void *arg) 81 usbhc_iface_transfer_out_callback_t func_out, void *arg, 82 device_keeper_t *manager 83 ) 60 84 { 61 85 assert(func_in == NULL || func_out == NULL); 62 86 assert(func_in != NULL || func_out != NULL); 63 87 88 #define CHECK_NULL_DISPOSE_RETURN(ptr, message...) \ 89 if (ptr == NULL) { \ 90 usb_log_error(message); \ 91 if (instance) { \ 92 batch_dispose(instance); \ 93 } \ 94 return NULL; \ 95 } else (void)0 96 64 97 batch_t *instance = malloc(sizeof(batch_t)); 65 if (instance == NULL) { 66 usb_log_error("Failed to allocate batch instance.\n"); 67 return NULL; 68 } 69 70 instance->qh = queue_head_get(); 71 if (instance->qh == NULL) { 72 usb_log_error("Failed to allocate queue head.\n"); 73 free(instance); 74 return NULL; 75 } 98 CHECK_NULL_DISPOSE_RETURN(instance, 99 "Failed to allocate batch instance.\n"); 100 bzero(instance, sizeof(batch_t)); 101 102 instance->qh = malloc32(sizeof(queue_head_t)); 103 CHECK_NULL_DISPOSE_RETURN(instance->qh, 104 "Failed to allocate batch queue head.\n"); 105 queue_head_init(instance->qh); 76 106 77 107 instance->packets = (size + max_packet_size - 1) / max_packet_size; … … 80 110 } 81 111 82 instance->tds = malloc32(sizeof(transfer_descriptor_t) * instance->packets); 83 if (instance->tds == NULL) { 84 usb_log_error("Failed to allocate transfer descriptors.\n"); 85 queue_head_dispose(instance->qh); 86 free(instance); 87 return NULL; 88 } 89 bzero(instance->tds, sizeof(transfer_descriptor_t) * instance->packets); 90 91 const size_t transport_size = max_packet_size * instance->packets; 92 93 instance->transport_buffer = 94 (size > 0) ? malloc32(transport_size) : NULL; 95 if ((size > 0) && (instance->transport_buffer == NULL)) { 96 usb_log_error("Failed to allocate device accessible buffer.\n"); 97 queue_head_dispose(instance->qh); 98 free32(instance->tds); 99 free(instance); 100 return NULL; 101 } 102 103 instance->setup_buffer = setup_buffer ? malloc32(setup_size) : NULL; 104 if ((setup_size > 0) && (instance->setup_buffer == NULL)) { 105 usb_log_error("Failed to allocate device accessible setup buffer.\n"); 106 queue_head_dispose(instance->qh); 107 free32(instance->tds); 108 free32(instance->transport_buffer); 109 free(instance); 110 return NULL; 111 } 112 if (instance->setup_buffer) { 112 instance->tds = malloc32(sizeof(td_t) * instance->packets); 113 CHECK_NULL_DISPOSE_RETURN( 114 instance->tds, "Failed to allocate transfer descriptors.\n"); 115 bzero(instance->tds, sizeof(td_t) * instance->packets); 116 117 // const size_t transport_size = max_packet_size * instance->packets; 118 119 if (size > 0) { 120 instance->transport_buffer = malloc32(size); 121 CHECK_NULL_DISPOSE_RETURN(instance->transport_buffer, 122 "Failed to allocate device accessible buffer.\n"); 123 } 124 125 if (setup_size > 0) { 126 instance->setup_buffer = malloc32(setup_size); 127 CHECK_NULL_DISPOSE_RETURN(instance->setup_buffer, 128 "Failed to allocate device accessible setup buffer.\n"); 113 129 memcpy(instance->setup_buffer, setup_buffer, setup_size); 114 130 } 115 131 132 133 link_initialize(&instance->link); 134 116 135 instance->max_packet_size = max_packet_size; 117 118 link_initialize(&instance->link);119 120 136 instance->target = target; 121 137 instance->transfer_type = transfer_type; 122 123 if (func_out)124 instance->callback_out = func_out;125 if (func_in)126 instance->callback_in = func_in;127 128 138 instance->buffer = buffer; 129 139 instance->buffer_size = size; … … 132 142 instance->arg = arg; 133 143 instance->speed = speed; 134 135 queue_head_element_td(instance->qh, addr_to_phys(instance->tds)); 144 instance->manager = manager; 145 146 if (func_out) 147 instance->callback_out = func_out; 148 if (func_in) 149 instance->callback_in = func_in; 150 151 queue_head_set_element_td(instance->qh, addr_to_phys(instance->tds)); 152 136 153 usb_log_debug("Batch(%p) %d:%d memory structures ready.\n", 137 154 instance, target.address, target.endpoint); … … 139 156 } 140 157 /*----------------------------------------------------------------------------*/ 158 /** Checks batch TDs for activity. 159 * 160 * @param[in] instance Batch structure to use. 161 * @return False, if there is an active TD, true otherwise. 162 */ 141 163 bool batch_is_complete(batch_t *instance) 142 164 { … … 147 169 size_t i = 0; 148 170 for (;i < instance->packets; ++i) { 149 if (t ransfer_descriptor_is_active(&instance->tds[i])) {171 if (td_is_active(&instance->tds[i])) { 150 172 return false; 151 173 } 152 instance->error = transfer_descriptor_status(&instance->tds[i]); 174 175 instance->error = td_status(&instance->tds[i]); 153 176 if (instance->error != EOK) { 177 usb_log_debug("Batch(%p) found error TD(%d):%x.\n", 178 instance, i, instance->tds[i].status); 179 180 device_keeper_set_toggle(instance->manager, 181 instance->target, td_toggle(&instance->tds[i])); 154 182 if (i > 0) 155 instance->transfered_size -= instance->setup_size; 156 usb_log_debug("Batch(%p) found error TD(%d):%x.\n", 157 instance, i, instance->tds[i].status); 183 goto substract_ret; 158 184 return true; 159 185 } 160 instance->transfered_size += 161 transfer_descriptor_actual_size(&instance->tds[i]); 162 } 186 187 instance->transfered_size += td_act_size(&instance->tds[i]); 188 if (td_is_short(&instance->tds[i])) 189 goto substract_ret; 190 } 191 substract_ret: 163 192 instance->transfered_size -= instance->setup_size; 164 193 return true; 165 194 } 166 195 /*----------------------------------------------------------------------------*/ 196 /** Prepares control write transaction. 197 * 198 * @param[in] instance Batch structure to use. 199 */ 167 200 void batch_control_write(batch_t *instance) 168 201 { 169 202 assert(instance); 170 203 /* we are data out, we are supposed to provide data */ 204 memcpy(instance->transport_buffer, instance->buffer, 205 instance->buffer_size); 206 batch_control(instance, USB_PID_OUT, USB_PID_IN); 207 instance->next_step = batch_call_out_and_dispose; 208 usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance); 209 batch_schedule(instance); 210 } 211 /*----------------------------------------------------------------------------*/ 212 /** Prepares control read transaction. 213 * 214 * @param[in] instance Batch structure to use. 215 */ 216 void batch_control_read(batch_t *instance) 217 { 218 assert(instance); 219 batch_control(instance, USB_PID_IN, USB_PID_OUT); 220 instance->next_step = batch_call_in_and_dispose; 221 usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance); 222 batch_schedule(instance); 223 } 224 /*----------------------------------------------------------------------------*/ 225 /** Prepares interrupt in transaction. 226 * 227 * @param[in] instance Batch structure to use. 228 */ 229 void batch_interrupt_in(batch_t *instance) 230 { 231 assert(instance); 232 batch_data(instance, USB_PID_IN); 233 instance->next_step = batch_call_in_and_dispose; 234 usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance); 235 batch_schedule(instance); 236 } 237 /*----------------------------------------------------------------------------*/ 238 /** Prepares interrupt out transaction. 239 * 240 * @param[in] instance Batch structure to use. 241 */ 242 void batch_interrupt_out(batch_t *instance) 243 { 244 assert(instance); 171 245 /* we are data out, we are supposed to provide data */ 172 246 memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size); 247 batch_data(instance, USB_PID_OUT); 248 instance->next_step = batch_call_out_and_dispose; 249 usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance); 250 batch_schedule(instance); 251 } 252 /*----------------------------------------------------------------------------*/ 253 /** Prepares bulk in transaction. 254 * 255 * @param[in] instance Batch structure to use. 256 */ 257 void batch_bulk_in(batch_t *instance) 258 { 259 assert(instance); 260 batch_data(instance, USB_PID_IN); 261 instance->next_step = batch_call_in_and_dispose; 262 usb_log_debug("Batch(%p) BULK IN initialized.\n", instance); 263 batch_schedule(instance); 264 } 265 /*----------------------------------------------------------------------------*/ 266 /** Prepares bulk out transaction. 267 * 268 * @param[in] instance Batch structure to use. 269 */ 270 void batch_bulk_out(batch_t *instance) 271 { 272 assert(instance); 273 memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size); 274 batch_data(instance, USB_PID_OUT); 275 instance->next_step = batch_call_out_and_dispose; 276 usb_log_debug("Batch(%p) BULK OUT initialized.\n", instance); 277 batch_schedule(instance); 278 } 279 /*----------------------------------------------------------------------------*/ 280 /** Prepares generic data transaction 281 * 282 * @param[in] instance Batch structure to use. 283 * @param[in] pid to use for data packets. 284 */ 285 void batch_data(batch_t *instance, usb_packet_id pid) 286 { 287 assert(instance); 288 const bool low_speed = instance->speed == USB_SPEED_LOW; 289 int toggle = 290 device_keeper_get_toggle(instance->manager, instance->target); 291 assert(toggle == 0 || toggle == 1); 292 293 size_t packet = 0; 294 size_t remain_size = instance->buffer_size; 295 while (remain_size > 0) { 296 char *data = 297 instance->transport_buffer + instance->buffer_size 298 - remain_size; 299 300 const size_t packet_size = 301 (instance->max_packet_size > remain_size) ? 302 remain_size : instance->max_packet_size; 303 304 td_t *next_packet = (packet + 1 < instance->packets) 305 ? &instance->tds[packet + 1] : NULL; 306 307 assert(packet < instance->packets); 308 assert(packet_size <= remain_size); 309 310 td_init( 311 &instance->tds[packet], DEFAULT_ERROR_COUNT, packet_size, 312 toggle, false, low_speed, instance->target, pid, data, 313 next_packet); 314 315 316 toggle = 1 - toggle; 317 remain_size -= packet_size; 318 ++packet; 319 } 320 device_keeper_set_toggle(instance->manager, instance->target, toggle); 321 } 322 /*----------------------------------------------------------------------------*/ 323 /** Prepares generic control transaction 324 * 325 * @param[in] instance Batch structure to use. 326 * @param[in] data_stage to use for data packets. 327 * @param[in] status_stage to use for data packets. 328 */ 329 void batch_control(batch_t *instance, 330 usb_packet_id data_stage, usb_packet_id status_stage) 331 { 332 assert(instance); 173 333 174 334 const bool low_speed = instance->speed == USB_SPEED_LOW; 175 335 int toggle = 0; 176 336 /* setup stage */ 177 transfer_descriptor_init(instance->tds, DEFAULT_ERROR_COUNT, 178 instance->setup_size, toggle, false, low_speed, 179 instance->target, USB_PID_SETUP, instance->setup_buffer, 180 &instance->tds[1]); 181 182 /* data stage */ 183 size_t i = 1; 184 for (;i < instance->packets - 1; ++i) { 185 char *data = 186 instance->transport_buffer + ((i - 1) * instance->max_packet_size); 187 toggle = 1 - toggle; 188 189 transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT, 190 instance->max_packet_size, toggle++, false, low_speed, 191 instance->target, USB_PID_OUT, data, &instance->tds[i + 1]); 192 } 193 194 /* status stage */ 195 i = instance->packets - 1; 196 transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT, 197 0, 1, false, low_speed, instance->target, USB_PID_IN, NULL, NULL); 198 199 instance->tds[i].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG; 200 usb_log_debug2("Control write last TD status: %x.\n", 201 instance->tds[i].status); 202 203 instance->next_step = batch_call_out_and_dispose; 204 usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance); 205 batch_schedule(instance); 206 } 207 /*----------------------------------------------------------------------------*/ 208 void batch_control_read(batch_t *instance) 209 { 210 assert(instance); 211 212 const bool low_speed = instance->speed == USB_SPEED_LOW; 213 int toggle = 0; 214 /* setup stage */ 215 transfer_descriptor_init(instance->tds, DEFAULT_ERROR_COUNT, 337 td_init(instance->tds, DEFAULT_ERROR_COUNT, 216 338 instance->setup_size, toggle, false, low_speed, instance->target, 217 339 USB_PID_SETUP, instance->setup_buffer, &instance->tds[1]); 218 340 219 341 /* data stage */ 220 size_t i = 1; 221 for (;i < instance->packets - 1; ++i) { 342 size_t packet = 1; 343 size_t remain_size = instance->buffer_size; 344 while (remain_size > 0) { 222 345 char *data = 223 instance->transport_buffer + ((i - 1) * instance->max_packet_size); 346 instance->transport_buffer + instance->buffer_size 347 - remain_size; 348 224 349 toggle = 1 - toggle; 225 350 226 transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT, 227 instance->max_packet_size, toggle, false, low_speed, 228 instance->target, USB_PID_IN, data, &instance->tds[i + 1]); 351 const size_t packet_size = 352 (instance->max_packet_size > remain_size) ? 353 remain_size : instance->max_packet_size; 354 355 td_init( 356 &instance->tds[packet], DEFAULT_ERROR_COUNT, packet_size, 357 toggle, false, low_speed, instance->target, data_stage, 358 data, &instance->tds[packet + 1]); 359 360 ++packet; 361 assert(packet < instance->packets); 362 assert(packet_size <= remain_size); 363 remain_size -= packet_size; 229 364 } 230 365 231 366 /* status stage */ 232 i = instance->packets - 1; 233 transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT, 234 0, 1, false, low_speed, instance->target, USB_PID_OUT, NULL, NULL); 235 236 instance->tds[i].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG; 237 usb_log_debug2("Control read last TD status: %x.\n", 238 instance->tds[i].status); 239 240 instance->next_step = batch_call_in_and_dispose; 241 usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance); 242 batch_schedule(instance); 243 } 244 /*----------------------------------------------------------------------------*/ 245 void batch_interrupt_in(batch_t *instance) 246 { 247 assert(instance); 248 249 const bool low_speed = instance->speed == USB_SPEED_LOW; 250 int toggle = 1; 251 size_t i = 0; 252 for (;i < instance->packets; ++i) { 253 char *data = 254 instance->transport_buffer + (i * instance->max_packet_size); 255 transfer_descriptor_t *next = (i + 1) < instance->packets ? 256 &instance->tds[i + 1] : NULL; 257 toggle = 1 - toggle; 258 259 transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT, 260 instance->max_packet_size, toggle, false, low_speed, 261 instance->target, USB_PID_IN, data, next); 262 } 263 264 instance->tds[i - 1].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG; 265 266 instance->next_step = batch_call_in_and_dispose; 267 usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance); 268 batch_schedule(instance); 269 } 270 /*----------------------------------------------------------------------------*/ 271 void batch_interrupt_out(batch_t *instance) 272 { 273 assert(instance); 274 275 memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size); 276 277 const bool low_speed = instance->speed == USB_SPEED_LOW; 278 int toggle = 1; 279 size_t i = 0; 280 for (;i < instance->packets; ++i) { 281 char *data = 282 instance->transport_buffer + (i * instance->max_packet_size); 283 transfer_descriptor_t *next = (i + 1) < instance->packets ? 284 &instance->tds[i + 1] : NULL; 285 toggle = 1 - toggle; 286 287 transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT, 288 instance->max_packet_size, toggle++, false, low_speed, 289 instance->target, USB_PID_OUT, data, next); 290 } 291 292 instance->tds[i - 1].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG; 293 294 instance->next_step = batch_call_out_and_dispose; 295 usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance); 296 batch_schedule(instance); 297 } 298 /*----------------------------------------------------------------------------*/ 367 assert(packet == instance->packets - 1); 368 td_init(&instance->tds[packet], DEFAULT_ERROR_COUNT, 369 0, 1, false, low_speed, instance->target, status_stage, NULL, NULL); 370 371 372 instance->tds[packet].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG; 373 usb_log_debug2("Control last TD status: %x.\n", 374 instance->tds[packet].status); 375 } 376 /*----------------------------------------------------------------------------*/ 377 /** Prepares data, gets error status and calls callback in. 378 * 379 * @param[in] instance Batch structure to use. 380 */ 299 381 void batch_call_in(batch_t *instance) 300 382 { … … 302 384 assert(instance->callback_in); 303 385 304 memcpy(instance->buffer, instance->transport_buffer, instance->buffer_size); 386 /* we are data in, we need data */ 387 memcpy(instance->buffer, instance->transport_buffer, 388 instance->buffer_size); 305 389 306 390 int err = instance->error; … … 309 393 instance->transfered_size); 310 394 311 instance->callback_in(instance->fun, 312 err, instance->transfered_size, 313 instance->arg); 314 } 315 /*----------------------------------------------------------------------------*/ 395 instance->callback_in( 396 instance->fun, err, instance->transfered_size, instance->arg); 397 } 398 /*----------------------------------------------------------------------------*/ 399 /** Gets error status and calls callback out. 400 * 401 * @param[in] instance Batch structure to use. 402 */ 316 403 void batch_call_out(batch_t *instance) 317 404 { … … 326 413 } 327 414 /*----------------------------------------------------------------------------*/ 415 /** Prepares data, gets error status, calls callback in and dispose. 416 * 417 * @param[in] instance Batch structure to use. 418 */ 328 419 void batch_call_in_and_dispose(batch_t *instance) 329 420 { 330 421 assert(instance); 331 422 batch_call_in(instance); 423 batch_dispose(instance); 424 } 425 /*----------------------------------------------------------------------------*/ 426 /** Gets error status, calls callback out and dispose. 427 * 428 * @param[in] instance Batch structure to use. 429 */ 430 void batch_call_out_and_dispose(batch_t *instance) 431 { 432 assert(instance); 433 batch_call_out(instance); 434 batch_dispose(instance); 435 } 436 /*----------------------------------------------------------------------------*/ 437 /** Correctly disposes all used data structures. 438 * 439 * @param[in] instance Batch structure to use. 440 */ 441 void batch_dispose(batch_t *instance) 442 { 443 assert(instance); 332 444 usb_log_debug("Batch(%p) disposing.\n", instance); 445 /* free32 is NULL safe */ 333 446 free32(instance->tds); 334 447 free32(instance->qh); … … 338 451 } 339 452 /*----------------------------------------------------------------------------*/ 340 void batch_call_out_and_dispose(batch_t *instance)341 {342 assert(instance);343 batch_call_out(instance);344 usb_log_debug("Batch(%p) disposing.\n", instance);345 free32(instance->tds);346 free32(instance->qh);347 free32(instance->setup_buffer);348 free32(instance->transport_buffer);349 free(instance);350 }351 /*----------------------------------------------------------------------------*/352 453 int batch_schedule(batch_t *instance) 353 454 { -
uspace/drv/uhci-hcd/batch.h
r60a228f r9d9ffdd 42 42 #include "uhci_struct/transfer_descriptor.h" 43 43 #include "uhci_struct/queue_head.h" 44 #include "utils/device_keeper.h" 44 45 45 46 typedef struct batch … … 65 66 ddf_fun_t *fun; 66 67 queue_head_t *qh; 67 t ransfer_descriptor_t *tds;68 td_t *tds; 68 69 void (*next_step)(struct batch*); 70 device_keeper_t *manager; 69 71 } batch_t; 70 72 … … 74 76 char *setup_buffer, size_t setup_size, 75 77 usbhc_iface_transfer_in_callback_t func_in, 76 usbhc_iface_transfer_out_callback_t func_out, void *arg); 78 usbhc_iface_transfer_out_callback_t func_out, void *arg, 79 device_keeper_t *manager 80 ); 77 81 78 82 bool batch_is_complete(batch_t *instance); … … 86 90 void batch_interrupt_out(batch_t *instance); 87 91 88 /* DEPRECATED FUNCTIONS NEEDED BY THE OLD API */ 89 void batch_control_setup_old(batch_t *instance); 92 void batch_bulk_in(batch_t *instance); 90 93 91 void batch_control_write_data_old(batch_t *instance); 92 93 void batch_control_read_data_old(batch_t *instance); 94 95 void batch_control_write_status_old(batch_t *instance); 96 97 void batch_control_read_status_old(batch_t *instance); 94 void batch_bulk_out(batch_t *instance); 98 95 #endif 99 96 /** -
uspace/drv/uhci-hcd/iface.c
r60a228f r9d9ffdd 43 43 #include "utils/device_keeper.h" 44 44 45 /** Reserve default address interface function 46 * 47 * @param[in] fun DDF function that was called. 48 * @param[in] speed Speed to associate with the new default address. 49 * @return Error code. 50 */ 45 51 /*----------------------------------------------------------------------------*/ 46 52 static int reserve_default_address(ddf_fun_t *fun, usb_speed_t speed) … … 54 60 } 55 61 /*----------------------------------------------------------------------------*/ 62 /** Release default address interface function 63 * 64 * @param[in] fun DDF function that was called. 65 * @return Error code. 66 */ 56 67 static int release_default_address(ddf_fun_t *fun) 57 68 { … … 64 75 } 65 76 /*----------------------------------------------------------------------------*/ 77 /** Request address interface function 78 * 79 * @param[in] fun DDF function that was called. 80 * @param[in] speed Speed to associate with the new default address. 81 * @param[out] address Place to write a new address. 82 * @return Error code. 83 */ 66 84 static int request_address(ddf_fun_t *fun, usb_speed_t speed, 67 85 usb_address_t *address) … … 80 98 } 81 99 /*----------------------------------------------------------------------------*/ 100 /** Bind address interface function 101 * 102 * @param[in] fun DDF function that was called. 103 * @param[in] address Address of the device 104 * @param[in] handle Devman handle of the device driver. 105 * @return Error code. 106 */ 82 107 static int bind_address( 83 108 ddf_fun_t *fun, usb_address_t address, devman_handle_t handle) … … 91 116 } 92 117 /*----------------------------------------------------------------------------*/ 118 /** Release address interface function 119 * 120 * @param[in] fun DDF function that was called. 121 * @param[in] address USB address to be released. 122 * @return Error code. 123 */ 93 124 static int release_address(ddf_fun_t *fun, usb_address_t address) 94 125 { … … 101 132 } 102 133 /*----------------------------------------------------------------------------*/ 134 /** Interrupt out transaction interface function 135 * 136 * @param[in] fun DDF function that was called. 137 * @param[in] target USB device to write to. 138 * @param[in] max_packet_size maximum size of data packet the device accepts 139 * @param[in] data Source of data. 140 * @param[in] size Size of data source. 141 * @param[in] callback Function to call on transaction completion 142 * @param[in] arg Additional for callback function. 143 * @return Error code. 144 */ 103 145 static int interrupt_out(ddf_fun_t *fun, usb_target_t target, 104 146 size_t max_packet_size, void *data, size_t size, … … 114 156 115 157 batch_t *batch = batch_get(fun, target, USB_TRANSFER_INTERRUPT, 116 max_packet_size, speed, data, size, NULL, 0, NULL, callback, arg); 158 max_packet_size, speed, data, size, NULL, 0, NULL, callback, arg, 159 &hc->device_manager); 117 160 if (!batch) 118 161 return ENOMEM; … … 121 164 } 122 165 /*----------------------------------------------------------------------------*/ 166 /** Interrupt in transaction interface function 167 * 168 * @param[in] fun DDF function that was called. 169 * @param[in] target USB device to write to. 170 * @param[in] max_packet_size maximum size of data packet the device accepts 171 * @param[out] data Data destination. 172 * @param[in] size Size of data source. 173 * @param[in] callback Function to call on transaction completion 174 * @param[in] arg Additional for callback function. 175 * @return Error code. 176 */ 123 177 static int interrupt_in(ddf_fun_t *fun, usb_target_t target, 124 178 size_t max_packet_size, void *data, size_t size, … … 133 187 134 188 batch_t *batch = batch_get(fun, target, USB_TRANSFER_INTERRUPT, 135 max_packet_size, speed, data, size, NULL, 0, callback, NULL, arg); 189 max_packet_size, speed, data, size, NULL, 0, callback, NULL, arg, 190 &hc->device_manager); 136 191 if (!batch) 137 192 return ENOMEM; … … 140 195 } 141 196 /*----------------------------------------------------------------------------*/ 197 /** Bulk out transaction interface function 198 * 199 * @param[in] fun DDF function that was called. 200 * @param[in] target USB device to write to. 201 * @param[in] max_packet_size maximum size of data packet the device accepts 202 * @param[in] data Source of data. 203 * @param[in] size Size of data source. 204 * @param[in] callback Function to call on transaction completion 205 * @param[in] arg Additional for callback function. 206 * @return Error code. 207 */ 208 static int bulk_out(ddf_fun_t *fun, usb_target_t target, 209 size_t max_packet_size, void *data, size_t size, 210 usbhc_iface_transfer_out_callback_t callback, void *arg) 211 { 212 assert(fun); 213 uhci_t *hc = fun_to_uhci(fun); 214 assert(hc); 215 usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address); 216 217 usb_log_debug("Bulk OUT %d:%d %zu(%zu).\n", 218 target.address, target.endpoint, size, max_packet_size); 219 220 batch_t *batch = batch_get(fun, target, USB_TRANSFER_BULK, 221 max_packet_size, speed, data, size, NULL, 0, NULL, callback, arg, 222 &hc->device_manager); 223 if (!batch) 224 return ENOMEM; 225 batch_bulk_out(batch); 226 return EOK; 227 } 228 /*----------------------------------------------------------------------------*/ 229 /** Bulk in transaction interface function 230 * 231 * @param[in] fun DDF function that was called. 232 * @param[in] target USB device to write to. 233 * @param[in] max_packet_size maximum size of data packet the device accepts 234 * @param[out] data Data destination. 235 * @param[in] size Size of data source. 236 * @param[in] callback Function to call on transaction completion 237 * @param[in] arg Additional for callback function. 238 * @return Error code. 239 */ 240 static int bulk_in(ddf_fun_t *fun, usb_target_t target, 241 size_t max_packet_size, void *data, size_t size, 242 usbhc_iface_transfer_in_callback_t callback, void *arg) 243 { 244 assert(fun); 245 uhci_t *hc = fun_to_uhci(fun); 246 assert(hc); 247 usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address); 248 usb_log_debug("Bulk IN %d:%d %zu(%zu).\n", 249 target.address, target.endpoint, size, max_packet_size); 250 251 batch_t *batch = batch_get(fun, target, USB_TRANSFER_BULK, 252 max_packet_size, speed, data, size, NULL, 0, callback, NULL, arg, 253 &hc->device_manager); 254 if (!batch) 255 return ENOMEM; 256 batch_bulk_in(batch); 257 return EOK; 258 } 259 /*----------------------------------------------------------------------------*/ 260 /** Control write transaction interface function 261 * 262 * @param[in] fun DDF function that was called. 263 * @param[in] target USB device to write to. 264 * @param[in] max_packet_size maximum size of data packet the device accepts. 265 * @param[in] setup_data Data to send with SETUP packet. 266 * @param[in] setup_size Size of data to send with SETUP packet (should be 8B). 267 * @param[in] data Source of data. 268 * @param[in] size Size of data source. 269 * @param[in] callback Function to call on transaction completion. 270 * @param[in] arg Additional for callback function. 271 * @return Error code. 272 */ 142 273 static int control_write(ddf_fun_t *fun, usb_target_t target, 143 274 size_t max_packet_size, … … 152 283 target.address, target.endpoint, size, max_packet_size); 153 284 285 if (setup_size != 8) 286 return EINVAL; 287 154 288 batch_t *batch = batch_get(fun, target, USB_TRANSFER_CONTROL, 155 289 max_packet_size, speed, data, size, setup_data, setup_size, 156 NULL, callback, arg); 157 if (!batch) 158 return ENOMEM; 290 NULL, callback, arg, &hc->device_manager); 291 if (!batch) 292 return ENOMEM; 293 device_keeper_reset_if_need(&hc->device_manager, target, setup_data); 159 294 batch_control_write(batch); 160 295 return EOK; 161 296 } 162 297 /*----------------------------------------------------------------------------*/ 298 /** Control read transaction interface function 299 * 300 * @param[in] fun DDF function that was called. 301 * @param[in] target USB device to write to. 302 * @param[in] max_packet_size maximum size of data packet the device accepts. 303 * @param[in] setup_data Data to send with SETUP packet. 304 * @param[in] setup_size Size of data to send with SETUP packet (should be 8B). 305 * @param[out] data Source of data. 306 * @param[in] size Size of data source. 307 * @param[in] callback Function to call on transaction completion. 308 * @param[in] arg Additional for callback function. 309 * @return Error code. 310 */ 163 311 static int control_read(ddf_fun_t *fun, usb_target_t target, 164 312 size_t max_packet_size, … … 175 323 batch_t *batch = batch_get(fun, target, USB_TRANSFER_CONTROL, 176 324 max_packet_size, speed, data, size, setup_data, setup_size, callback, 177 NULL, arg );325 NULL, arg, &hc->device_manager); 178 326 if (!batch) 179 327 return ENOMEM; … … 181 329 return EOK; 182 330 } 183 184 185 331 /*----------------------------------------------------------------------------*/ 186 332 usbhc_iface_t uhci_iface = { … … 194 340 .interrupt_in = interrupt_in, 195 341 342 .bulk_in = bulk_in, 343 .bulk_out = bulk_out, 344 196 345 .control_read = control_read, 197 346 .control_write = control_write, -
uspace/drv/uhci-hcd/main.c
r60a228f r9d9ffdd 34 34 #include <ddf/driver.h> 35 35 #include <ddf/interrupt.h> 36 #include <device/hw_res.h> 37 #include <errno.h> 38 #include <str_error.h> 39 36 40 #include <usb_iface.h> 37 41 #include <usb/ddfiface.h> 38 #include <device/hw_res.h>39 40 #include <errno.h>41 42 42 #include <usb/debug.h> 43 43 … … 50 50 51 51 static int uhci_add_device(ddf_dev_t *device); 52 53 52 /*----------------------------------------------------------------------------*/ 54 53 static driver_ops_t uhci_driver_ops = { … … 61 60 }; 62 61 /*----------------------------------------------------------------------------*/ 62 /** IRQ handling callback, identifies devic 63 * 64 * @param[in] dev DDF instance of the device to use. 65 * @param[in] iid (Unused). 66 * @param[in] call Pointer to the call that represents interrupt. 67 */ 63 68 static void irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call) 64 69 { … … 70 75 } 71 76 /*----------------------------------------------------------------------------*/ 72 #define CHECK_RET_RETURN(ret, message...) \ 77 /** Initializes a new ddf driver instance of UHCI hcd. 78 * 79 * @param[in] device DDF instance of the device to initialize. 80 * @return Error code. 81 * 82 * Gets and initialies hardware resources, disables any legacy support, 83 * and reports root hub device. 84 */ 85 int uhci_add_device(ddf_dev_t *device) 86 { 87 assert(device); 88 uhci_t *hcd = NULL; 89 #define CHECK_RET_FREE_HC_RETURN(ret, message...) \ 73 90 if (ret != EOK) { \ 74 91 usb_log_error(message); \ 92 if (hcd != NULL) \ 93 free(hcd); \ 75 94 return ret; \ 76 95 } 77 78 static int uhci_add_device(ddf_dev_t *device)79 {80 assert(device);81 96 82 97 usb_log_info("uhci_add_device() called\n"); … … 88 103 int ret = 89 104 pci_get_my_registers(device, &io_reg_base, &io_reg_size, &irq); 90 91 CHECK_RET_RETURN(ret, 105 CHECK_RET_FREE_HC_RETURN(ret, 92 106 "Failed(%d) to get I/O addresses:.\n", ret, device->handle); 93 107 usb_log_info("I/O regs at 0x%X (size %zu), IRQ %d.\n", 94 108 io_reg_base, io_reg_size, irq); 95 109 96 // ret = pci_enable_interrupts(device); 97 // CHECK_RET_RETURN(ret, "Failed(%d) to get enable interrupts:\n", ret); 110 ret = pci_disable_legacy(device); 111 CHECK_RET_FREE_HC_RETURN(ret, 112 "Failed(%d) to disable legacy USB: %s.\n", ret, str_error(ret)); 98 113 99 uhci_t *uhci_hc = malloc(sizeof(uhci_t)); 100 ret = (uhci_hc != NULL) ? EOK : ENOMEM; 101 CHECK_RET_RETURN(ret, "Failed to allocate memory for uhci hcd driver.\n"); 114 #if 0 115 ret = pci_enable_interrupts(device); 116 if (ret != EOK) { 117 usb_log_warning( 118 "Failed(%d) to enable interrupts, fall back to polling.\n", 119 ret); 120 } 121 #endif 102 122 103 ret = uhci_init(uhci_hc, device, (void*)io_reg_base, io_reg_size); 104 if (ret != EOK) { 105 usb_log_error("Failed to init uhci-hcd.\n"); 106 free(uhci_hc); 107 return ret; 108 } 123 hcd = malloc(sizeof(uhci_t)); 124 ret = (hcd != NULL) ? EOK : ENOMEM; 125 CHECK_RET_FREE_HC_RETURN(ret, 126 "Failed(%d) to allocate memory for uhci hcd.\n", ret); 127 128 ret = uhci_init(hcd, device, (void*)io_reg_base, io_reg_size); 129 CHECK_RET_FREE_HC_RETURN(ret, "Failed(%d) to init uhci-hcd.\n", ret); 130 #undef CHECK_RET_FREE_HC_RETURN 109 131 110 132 /* 111 * We might free uhci_hc, but that does not matter since no one133 * We might free hcd, but that does not matter since no one 112 134 * else would access driver_data anyway. 113 135 */ 114 device->driver_data = uhci_hc; 136 device->driver_data = hcd; 137 138 ddf_fun_t *rh = NULL; 139 #define CHECK_RET_FINI_FREE_RETURN(ret, message...) \ 140 if (ret != EOK) { \ 141 usb_log_error(message); \ 142 if (hcd != NULL) {\ 143 uhci_fini(hcd); \ 144 free(hcd); \ 145 } \ 146 if (rh != NULL) \ 147 free(rh); \ 148 return ret; \ 149 } 150 151 /* It does no harm if we register this on polling */ 115 152 ret = register_interrupt_handler(device, irq, irq_handler, 116 &uhci_hc->interrupt_code); 117 if (ret != EOK) { 118 usb_log_error("Failed to register interrupt handler.\n"); 119 uhci_fini(uhci_hc); 120 free(uhci_hc); 121 return ret; 122 } 153 &hcd->interrupt_code); 154 CHECK_RET_FINI_FREE_RETURN(ret, 155 "Failed(%d) to register interrupt handler.\n", ret); 123 156 124 ddf_fun_t *rh;125 157 ret = setup_root_hub(&rh, device); 126 if (ret != EOK) { 127 usb_log_error("Failed to setup uhci root hub.\n"); 128 uhci_fini(uhci_hc); 129 free(uhci_hc); 130 return ret; 131 } 132 rh->driver_data = uhci_hc->ddf_instance; 158 CHECK_RET_FINI_FREE_RETURN(ret, 159 "Failed(%d) to setup UHCI root hub.\n", ret); 160 rh->driver_data = hcd->ddf_instance; 133 161 134 162 ret = ddf_fun_bind(rh); 135 if (ret != EOK) { 136 usb_log_error("Failed to register root hub.\n"); 137 uhci_fini(uhci_hc); 138 free(uhci_hc); 139 free(rh); 140 return ret; 141 } 163 CHECK_RET_FINI_FREE_RETURN(ret, 164 "Failed(%d) to register UHCI root hub.\n", ret); 142 165 143 166 return EOK; 167 #undef CHECK_RET_FINI_FREE_RETURN 144 168 } 145 169 /*----------------------------------------------------------------------------*/ 170 /** Initializes global driver structures (NONE). 171 * 172 * @param[in] argc Nmber of arguments in argv vector (ignored). 173 * @param[in] argv Cmdline argument vector (ignored). 174 * @return Error code. 175 * 176 * Driver debug level is set here. 177 */ 146 178 int main(int argc, char *argv[]) 147 179 { -
uspace/drv/uhci-hcd/pci.c
r60a228f r9d9ffdd 40 40 41 41 #include <usb/debug.h> 42 #include <pci_dev_iface.h> 42 43 43 44 #include "pci.h" … … 64 65 65 66 int rc; 66 67 67 hw_resource_list_t hw_resources; 68 68 rc = hw_res_get_resource_list(parent_phone, &hw_resources); … … 81 81 for (i = 0; i < hw_resources.count; i++) { 82 82 hw_resource_t *res = &hw_resources.resources[i]; 83 switch (res->type) { 84 case INTERRUPT: 85 irq = res->res.interrupt.irq; 86 irq_found = true; 87 usb_log_debug2("Found interrupt: %d.\n", irq); 88 break; 89 case IO_RANGE: 90 io_address = res->res.io_range.address; 91 io_size = res->res.io_range.size; 92 usb_log_debug2("Found io: %llx %zu.\n", 93 res->res.io_range.address, res->res.io_range.size); 94 io_found = true; 95 break; 96 default: 97 break; 83 switch (res->type) 84 { 85 case INTERRUPT: 86 irq = res->res.interrupt.irq; 87 irq_found = true; 88 usb_log_debug2("Found interrupt: %d.\n", irq); 89 break; 90 91 case IO_RANGE: 92 io_address = res->res.io_range.address; 93 io_size = res->res.io_range.size; 94 usb_log_debug2("Found io: %llx %zu.\n", 95 res->res.io_range.address, res->res.io_range.size); 96 io_found = true; 97 98 default: 99 break; 98 100 } 99 101 } 100 102 101 if (!io_found) { 102 rc = ENOENT; 103 goto leave; 104 } 105 106 if (!irq_found) { 103 if (!io_found || !irq_found) { 107 104 rc = ENOENT; 108 105 goto leave; … … 120 117 } 121 118 /*----------------------------------------------------------------------------*/ 119 /** Calls the PCI driver with a request to enable interrupts 120 * 121 * @param[in] device Device asking for interrupts 122 * @return Error code. 123 */ 122 124 int pci_enable_interrupts(ddf_dev_t *device) 123 125 { … … 128 130 return enabled ? EOK : EIO; 129 131 } 132 /*----------------------------------------------------------------------------*/ 133 /** Calls the PCI driver with a request to clear legacy support register 134 * 135 * @param[in] device Device asking to disable interrupts 136 * @return Error code. 137 */ 138 int pci_disable_legacy(ddf_dev_t *device) 139 { 140 assert(device); 141 int parent_phone = 142 devman_parent_device_connect(device->handle, IPC_FLAG_BLOCKING); 143 if (parent_phone < 0) { 144 return parent_phone; 145 } 146 147 /* See UHCI design guide for these values, 148 * write all WC bits in USB legacy register */ 149 sysarg_t address = 0xc0; 150 sysarg_t value = 0x8f00; 151 152 int rc = async_req_3_0(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE), 153 IPC_M_CONFIG_SPACE_WRITE_16, address, value); 154 async_hangup(parent_phone); 155 156 return rc; 157 } 158 /*----------------------------------------------------------------------------*/ 130 159 /** 131 160 * @} -
uspace/drv/uhci-hcd/pci.h
r60a228f r9d9ffdd 40 40 int pci_get_my_registers(ddf_dev_t *, uintptr_t *, size_t *, int *); 41 41 int pci_enable_interrupts(ddf_dev_t *); 42 int pci_disable_legacy(ddf_dev_t *); 42 43 43 44 #endif -
uspace/drv/uhci-hcd/root_hub.c
r60a228f r9d9ffdd 45 45 46 46 /*----------------------------------------------------------------------------*/ 47 static int usb_iface_get_hc_handle_rh_impl(ddf_fun_t *root_hub_fun, 48 devman_handle_t *handle) 47 /** Gets handle of the respective hc (parent device). 48 * 49 * @param[in] root_hub_fun Root hub function seeking hc handle. 50 * @param[out] handle Place to write the handle. 51 * @return Error code. 52 */ 53 static int usb_iface_get_hc_handle_rh_impl( 54 ddf_fun_t *root_hub_fun, devman_handle_t *handle) 49 55 { 56 /* TODO: Can't this use parent pointer? */ 50 57 ddf_fun_t *hc_fun = root_hub_fun->driver_data; 51 58 assert(hc_fun != NULL); … … 56 63 } 57 64 /*----------------------------------------------------------------------------*/ 58 static int usb_iface_get_address_rh_impl(ddf_fun_t *fun, devman_handle_t handle, 59 usb_address_t *address) 65 /** Gets USB address of the calling device. 66 * 67 * @param[in] fun Root hub function. 68 * @param[in] handle Handle of the device seeking address. 69 * @param[out] address Place to store found address. 70 * @return Error code. 71 */ 72 static int usb_iface_get_address_rh_impl( 73 ddf_fun_t *fun, devman_handle_t handle, usb_address_t *address) 60 74 { 75 /* TODO: What does this do? Is it neccessary? Can't it use implemented 76 * hc function?*/ 61 77 assert(fun); 62 78 ddf_fun_t *hc_fun = fun->driver_data; … … 65 81 assert(hc); 66 82 67 usb_address_t addr = device_keeper_find(&hc->device_manager, 68 handle); 83 usb_address_t addr = device_keeper_find(&hc->device_manager, handle); 69 84 if (addr < 0) { 70 85 return addr; … … 83 98 }; 84 99 /*----------------------------------------------------------------------------*/ 100 /** Gets root hub hw resources. 101 * 102 * @param[in] fun Root hub function. 103 * @return Pointer to the resource list used by the root hub. 104 */ 85 105 static hw_resource_list_t *get_resource_list(ddf_fun_t *dev) 86 106 { … … 91 111 assert(hc); 92 112 93 / /TODO: fix memory leak113 /* TODO: fix memory leak */ 94 114 hw_resource_list_t *resource_list = malloc(sizeof(hw_resource_list_t)); 95 115 assert(resource_list); -
uspace/drv/uhci-hcd/transfer_list.c
r60a228f r9d9ffdd 38 38 #include "transfer_list.h" 39 39 40 static void transfer_list_remove_batch( 41 transfer_list_t *instance, batch_t *batch); 42 /*----------------------------------------------------------------------------*/ 43 /** Initializes transfer list structures. 44 * 45 * @param[in] instance Memory place to use. 46 * @param[in] name Name of te new list. 47 * @return Error code 48 * 49 * Allocates memory for internat queue_head_t structure. 50 */ 40 51 int transfer_list_init(transfer_list_t *instance, const char *name) 41 52 { … … 43 54 instance->next = NULL; 44 55 instance->name = name; 45 instance->queue_head = queue_head_get();56 instance->queue_head = malloc32(sizeof(queue_head_t)); 46 57 if (!instance->queue_head) { 47 58 usb_log_error("Failed to allocate queue head.\n"); 48 59 return ENOMEM; 49 60 } 50 instance->queue_head_pa = (uintptr_t)addr_to_phys(instance->queue_head);61 instance->queue_head_pa = addr_to_phys(instance->queue_head); 51 62 52 63 queue_head_init(instance->queue_head); … … 56 67 } 57 68 /*----------------------------------------------------------------------------*/ 69 /** Set the next list in chain. 70 * 71 * @param[in] instance List to lead. 72 * @param[in] next List to append. 73 * @return Error code 74 */ 58 75 void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next) 59 76 { … … 66 83 } 67 84 /*----------------------------------------------------------------------------*/ 85 /** Submits a new transfer batch to list and queue. 86 * 87 * @param[in] instance List to use. 88 * @param[in] batch Transfer batch to submit. 89 * @return Error code 90 */ 68 91 void transfer_list_add_batch(transfer_list_t *instance, batch_t *batch) 69 92 { 70 93 assert(instance); 71 94 assert(batch); 72 usb_log_debug2("Adding batch(%p) to queue %s.\n", batch, instance->name); 95 usb_log_debug2( 96 "Adding batch(%p) to queue %s.\n", batch, instance->name); 73 97 74 98 uint32_t pa = (uintptr_t)addr_to_phys(batch->qh); … … 97 121 queue_head_append_qh(last->qh, pa); 98 122 list_append(&batch->link, &instance->batch_list); 123 99 124 usb_log_debug("Batch(%p) added to queue %s last, first is %p.\n", 100 batch, instance->name, first );125 batch, instance->name, first); 101 126 fibril_mutex_unlock(&instance->guard); 102 127 } 103 128 /*----------------------------------------------------------------------------*/ 104 static void transfer_list_remove_batch( 105 transfer_list_t *instance, batch_t *batch) 129 /** Removes a transfer batch from list and queue. 130 * 131 * @param[in] instance List to use. 132 * @param[in] batch Transfer batch to remove. 133 * @return Error code 134 */ 135 void transfer_list_remove_batch(transfer_list_t *instance, batch_t *batch) 106 136 { 107 137 assert(instance); … … 109 139 assert(instance->queue_head); 110 140 assert(batch->qh); 111 usb_log_debug2("Removing batch(%p) from queue %s.\n", batch, instance->name); 141 usb_log_debug2( 142 "Removing batch(%p) from queue %s.\n", batch, instance->name); 112 143 113 /* I'm the first one here */114 144 if (batch->link.prev == &instance->batch_list) { 115 usb_log_debug("Batch(%p) removed (FIRST) from queue %s, next element %x.\n", 116 batch, instance->name, batch->qh->next_queue); 145 /* I'm the first one here */ 146 usb_log_debug( 147 "Batch(%p) removed (FIRST) from %s, next element %x.\n", 148 batch, instance->name, batch->qh->next_queue); 117 149 instance->queue_head->element = batch->qh->next_queue; 118 150 } else { 119 usb_log_debug("Batch(%p) removed (NOT FIRST) from queue, next element %x.\n", 120 batch, instance->name, batch->qh->next_queue); 121 batch_t *prev = list_get_instance(batch->link.prev, batch_t, link); 151 usb_log_debug( 152 "Batch(%p) removed (FIRST:NO) from %s, next element %x.\n", 153 batch, instance->name, batch->qh->next_queue); 154 batch_t *prev = 155 list_get_instance(batch->link.prev, batch_t, link); 122 156 prev->qh->next_queue = batch->qh->next_queue; 123 157 } … … 125 159 } 126 160 /*----------------------------------------------------------------------------*/ 161 /** Checks list for finished transfers. 162 * 163 * @param[in] instance List to use. 164 * @return Error code 165 */ 127 166 void transfer_list_remove_finished(transfer_list_t *instance) 128 167 { -
uspace/drv/uhci-hcd/transfer_list.h
r60a228f r9d9ffdd 58 58 { 59 59 assert(instance); 60 queue_head_dispose(instance->queue_head);60 free32(instance->queue_head); 61 61 } 62 62 void transfer_list_remove_finished(transfer_list_t *instance); -
uspace/drv/uhci-hcd/uhci.c
r60a228f r9d9ffdd 61 61 }; 62 62 63 static int usb_iface_get_address(ddf_fun_t *fun, devman_handle_t handle, 64 usb_address_t *address) 63 /** Gets USB address of the calling device. 64 * 65 * @param[in] fun UHCI hc function. 66 * @param[in] handle Handle of the device seeking address. 67 * @param[out] address Place to store found address. 68 * @return Error code. 69 */ 70 static int usb_iface_get_address( 71 ddf_fun_t *fun, devman_handle_t handle, usb_address_t *address) 65 72 { 66 73 assert(fun); … … 90 97 .interfaces[USBHC_DEV_IFACE] = &uhci_iface, 91 98 }; 92 99 /*----------------------------------------------------------------------------*/ 93 100 static int uhci_init_transfer_lists(uhci_t *instance); 94 101 static int uhci_init_mem_structures(uhci_t *instance); … … 99 106 100 107 static bool allowed_usb_packet( 101 bool low_speed, usb_transfer_type_t, size_t size); 102 103 108 bool low_speed, usb_transfer_type_t transfer, size_t size); 109 /*----------------------------------------------------------------------------*/ 110 /** Initializes UHCI hcd driver structure 111 * 112 * @param[in] instance Memory place to initialize. 113 * @param[in] dev DDF device. 114 * @param[in] regs Address of I/O control registers. 115 * @param[in] size Size of I/O control registers. 116 * @return Error code. 117 * @note Should be called only once on any structure. 118 */ 104 119 int uhci_init(uhci_t *instance, ddf_dev_t *dev, void *regs, size_t reg_size) 105 120 { … … 115 130 } else (void) 0 116 131 117 /* 118 * Create UHCI function. 119 */ 132 /* Create UHCI function. */ 120 133 instance->ddf_instance = ddf_fun_create(dev, fun_exposed, "uhci"); 121 134 ret = (instance->ddf_instance == NULL) ? ENOMEM : EOK; 122 CHECK_RET_DEST_FUN_RETURN(ret, "Failed to create UHCI device function.\n"); 135 CHECK_RET_DEST_FUN_RETURN(ret, 136 "Failed to create UHCI device function.\n"); 123 137 124 138 instance->ddf_instance->ops = &uhci_ops; … … 126 140 127 141 ret = ddf_fun_bind(instance->ddf_instance); 128 CHECK_RET_DEST_FUN_RETURN(ret, "Failed(%d) to bind UHCI device function: %s.\n", 142 CHECK_RET_DEST_FUN_RETURN(ret, 143 "Failed(%d) to bind UHCI device function: %s.\n", 129 144 ret, str_error(ret)); 130 145 … … 132 147 regs_t *io; 133 148 ret = pio_enable(regs, reg_size, (void**)&io); 134 CHECK_RET_DEST_FUN_RETURN(ret, "Failed(%d) to gain access to registers at %p: %s.\n", 149 CHECK_RET_DEST_FUN_RETURN(ret, 150 "Failed(%d) to gain access to registers at %p: %s.\n", 135 151 ret, str_error(ret), io); 136 152 instance->registers = io; 137 usb_log_debug("Device registers at %p(%u) accessible.\n", io, reg_size); 153 usb_log_debug("Device registers at %p(%u) accessible.\n", 154 io, reg_size); 138 155 139 156 ret = uhci_init_mem_structures(instance); 140 CHECK_RET_DEST_FUN_RETURN(ret, "Failed to initialize UHCI memory structures.\n"); 157 CHECK_RET_DEST_FUN_RETURN(ret, 158 "Failed to initialize UHCI memory structures.\n"); 141 159 142 160 uhci_init_hw(instance); 143 144 instance->cleaner =fibril_create(uhci_interrupt_emulator, instance);161 instance->cleaner = 162 fibril_create(uhci_interrupt_emulator, instance); 145 163 fibril_add_ready(instance->cleaner); 146 164 … … 153 171 } 154 172 /*----------------------------------------------------------------------------*/ 173 /** Initializes UHCI hcd hw resources. 174 * 175 * @param[in] instance UHCI structure to use. 176 */ 155 177 void uhci_init_hw(uhci_t *instance) 156 178 { 157 /* reset everything, who knows what touched it before us */ 158 pio_write_16(&instance->registers->usbcmd, UHCI_CMD_GLOBAL_RESET); 179 assert(instance); 180 regs_t *registers = instance->registers; 181 182 /* Reset everything, who knows what touched it before us */ 183 pio_write_16(®isters->usbcmd, UHCI_CMD_GLOBAL_RESET); 159 184 async_usleep(10000); /* 10ms according to USB spec */ 160 pio_write_16(& instance->registers->usbcmd, 0);161 162 /* reset hc, all states and counters */163 pio_write_16(& instance->registers->usbcmd, UHCI_CMD_HCRESET);164 while ((pio_read_16(&instance->registers->usbcmd) & UHCI_CMD_HCRESET) != 0)165 { async_usleep(10); }166 167 /* set framelist pointer */185 pio_write_16(®isters->usbcmd, 0); 186 187 /* Reset hc, all states and counters */ 188 pio_write_16(®isters->usbcmd, UHCI_CMD_HCRESET); 189 do { async_usleep(10); } 190 while ((pio_read_16(®isters->usbcmd) & UHCI_CMD_HCRESET) != 0); 191 192 /* Set framelist pointer */ 168 193 const uint32_t pa = addr_to_phys(instance->frame_list); 169 pio_write_32(&instance->registers->flbaseadd, pa); 170 171 /* enable all interrupts, but resume interrupt */ 172 pio_write_16(&instance->registers->usbintr, 173 UHCI_INTR_CRC | UHCI_INTR_COMPLETE | UHCI_INTR_SHORT_PACKET); 194 pio_write_32(®isters->flbaseadd, pa); 195 196 /* Enable all interrupts, but resume interrupt */ 197 // pio_write_16(&instance->registers->usbintr, 198 // UHCI_INTR_CRC | UHCI_INTR_COMPLETE | UHCI_INTR_SHORT_PACKET); 199 200 uint16_t status = pio_read_16(®isters->usbcmd); 201 if (status != 0) 202 usb_log_warning("Previous command value: %x.\n", status); 174 203 175 204 /* Start the hc with large(64B) packet FSBR */ 176 pio_write_16(& instance->registers->usbcmd,205 pio_write_16(®isters->usbcmd, 177 206 UHCI_CMD_RUN_STOP | UHCI_CMD_MAX_PACKET | UHCI_CMD_CONFIGURE); 178 207 } 179 208 /*----------------------------------------------------------------------------*/ 209 /** Initializes UHCI hcd memory structures. 210 * 211 * @param[in] instance UHCI structure to use. 212 * @return Error code 213 * @note Should be called only once on any structure. 214 */ 180 215 int uhci_init_mem_structures(uhci_t *instance) 181 216 { … … 189 224 } else (void) 0 190 225 191 /* init interrupt code */226 /* Init interrupt code */ 192 227 instance->interrupt_code.cmds = malloc(sizeof(uhci_cmds)); 193 228 int ret = (instance->interrupt_code.cmds == NULL) ? ENOMEM : EOK; 194 CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to allocate interrupt cmds space.\n"); 229 CHECK_RET_DEST_CMDS_RETURN(ret, 230 "Failed to allocate interrupt cmds space.\n"); 195 231 196 232 { 197 233 irq_cmd_t *interrupt_commands = instance->interrupt_code.cmds; 198 234 memcpy(interrupt_commands, uhci_cmds, sizeof(uhci_cmds)); 199 interrupt_commands[0].addr = (void*)&instance->registers->usbsts; 200 interrupt_commands[1].addr = (void*)&instance->registers->usbsts; 235 interrupt_commands[0].addr = 236 (void*)&instance->registers->usbsts; 237 interrupt_commands[1].addr = 238 (void*)&instance->registers->usbsts; 201 239 instance->interrupt_code.cmdcount = 202 sizeof(uhci_cmds) / sizeof(irq_cmd_t);203 } 204 205 /* init transfer lists */240 sizeof(uhci_cmds) / sizeof(irq_cmd_t); 241 } 242 243 /* Init transfer lists */ 206 244 ret = uhci_init_transfer_lists(instance); 207 CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to init ializetransfer lists.\n");245 CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to init transfer lists.\n"); 208 246 usb_log_debug("Initialized transfer lists.\n"); 209 247 210 /* frame list initialization*/248 /* Init USB frame list page*/ 211 249 instance->frame_list = get_page(); 212 250 ret = instance ? EOK : ENOMEM; … … 214 252 usb_log_debug("Initialized frame list.\n"); 215 253 216 /* initializeall frames to point to the first queue head */254 /* Set all frames to point to the first queue head */ 217 255 const uint32_t queue = 218 256 instance->transfers_interrupt.queue_head_pa … … 224 262 } 225 263 226 /* init address keeper(libusb)*/264 /* Init device keeper*/ 227 265 device_keeper_init(&instance->device_manager); 228 266 usb_log_debug("Initialized device manager.\n"); … … 232 270 } 233 271 /*----------------------------------------------------------------------------*/ 272 /** Initializes UHCI hcd transfer lists. 273 * 274 * @param[in] instance UHCI structure to use. 275 * @return Error code 276 * @note Should be called only once on any structure. 277 */ 234 278 int uhci_init_transfer_lists(uhci_t *instance) 235 279 { … … 249 293 ret = transfer_list_init(&instance->transfers_bulk_full, "BULK_FULL"); 250 294 CHECK_RET_CLEAR_RETURN(ret, "Failed to init BULK list."); 251 ret = transfer_list_init(&instance->transfers_control_full, "CONTROL_FULL"); 295 296 ret = transfer_list_init( 297 &instance->transfers_control_full, "CONTROL_FULL"); 252 298 CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL FULL list."); 253 ret = transfer_list_init(&instance->transfers_control_slow, "CONTROL_SLOW"); 299 300 ret = transfer_list_init( 301 &instance->transfers_control_slow, "CONTROL_SLOW"); 254 302 CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL SLOW list."); 303 255 304 ret = transfer_list_init(&instance->transfers_interrupt, "INTERRUPT"); 256 305 CHECK_RET_CLEAR_RETURN(ret, "Failed to init INTERRUPT list."); … … 269 318 #endif 270 319 271 instance->transfers[0][USB_TRANSFER_INTERRUPT] = 320 /* Assign pointers to be used during scheduling */ 321 instance->transfers[USB_SPEED_FULL][USB_TRANSFER_INTERRUPT] = 272 322 &instance->transfers_interrupt; 273 instance->transfers[ 1][USB_TRANSFER_INTERRUPT] =323 instance->transfers[USB_SPEED_LOW][USB_TRANSFER_INTERRUPT] = 274 324 &instance->transfers_interrupt; 275 instance->transfers[ 0][USB_TRANSFER_CONTROL] =325 instance->transfers[USB_SPEED_FULL][USB_TRANSFER_CONTROL] = 276 326 &instance->transfers_control_full; 277 instance->transfers[ 1][USB_TRANSFER_CONTROL] =327 instance->transfers[USB_SPEED_LOW][USB_TRANSFER_CONTROL] = 278 328 &instance->transfers_control_slow; 279 instance->transfers[ 0][USB_TRANSFER_BULK] =329 instance->transfers[USB_SPEED_FULL][USB_TRANSFER_BULK] = 280 330 &instance->transfers_bulk_full; 281 331 … … 284 334 } 285 335 /*----------------------------------------------------------------------------*/ 336 /** Schedules batch for execution. 337 * 338 * @param[in] instance UHCI structure to use. 339 * @param[in] batch Transfer batch to schedule. 340 * @return Error code 341 */ 286 342 int uhci_schedule(uhci_t *instance, batch_t *batch) 287 343 { … … 291 347 if (!allowed_usb_packet( 292 348 low_speed, batch->transfer_type, batch->max_packet_size)) { 293 usb_log_warning("Invalid USB packet specified %s SPEED %d %zu.\n", 294 low_speed ? "LOW" : "FULL" , batch->transfer_type, 349 usb_log_warning( 350 "Invalid USB packet specified %s SPEED %d %zu.\n", 351 low_speed ? "LOW" : "FULL" , batch->transfer_type, 295 352 batch->max_packet_size); 296 353 return ENOTSUP; … … 306 363 } 307 364 /*----------------------------------------------------------------------------*/ 365 /** Takes action based on the interrupt cause. 366 * 367 * @param[in] instance UHCI structure to use. 368 * @param[in] status Value of the stsatus regiser at the time of interrupt. 369 */ 308 370 void uhci_interrupt(uhci_t *instance, uint16_t status) 309 371 { 310 372 assert(instance); 311 // if ((status & (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)) == 0) 312 // return; 313 // usb_log_debug2("UHCI interrupt: %X.\n", status); 373 /* TODO: Check interrupt cause here */ 314 374 transfer_list_remove_finished(&instance->transfers_interrupt); 315 375 transfer_list_remove_finished(&instance->transfers_control_slow); … … 318 378 } 319 379 /*----------------------------------------------------------------------------*/ 380 /** Polling function, emulates interrupts. 381 * 382 * @param[in] arg UHCI structure to use. 383 * @return EOK 384 */ 320 385 int uhci_interrupt_emulator(void* arg) 321 386 { … … 331 396 uhci_interrupt(instance, status); 332 397 pio_write_16(&instance->registers->usbsts, 0x1f); 333 async_usleep(UHCI_CLEANER_TIMEOUT * 5);398 async_usleep(UHCI_CLEANER_TIMEOUT); 334 399 } 335 400 return EOK; 336 401 } 337 402 /*---------------------------------------------------------------------------*/ 403 /** Debug function, checks consistency of memory structures. 404 * 405 * @param[in] arg UHCI structure to use. 406 * @return EOK 407 */ 338 408 int uhci_debug_checker(void *arg) 339 409 { 340 410 uhci_t *instance = (uhci_t*)arg; 341 411 assert(instance); 412 413 #define QH(queue) \ 414 instance->transfers_##queue.queue_head 415 342 416 while (1) { 343 417 const uint16_t cmd = pio_read_16(&instance->registers->usbcmd); 344 418 const uint16_t sts = pio_read_16(&instance->registers->usbsts); 345 const uint16_t intr = pio_read_16(&instance->registers->usbintr); 419 const uint16_t intr = 420 pio_read_16(&instance->registers->usbintr); 421 346 422 if (((cmd & UHCI_CMD_RUN_STOP) != 1) || (sts != 0)) { 347 423 usb_log_debug2("Command: %X Status: %X Intr: %x\n", … … 353 429 if (frame_list != addr_to_phys(instance->frame_list)) { 354 430 usb_log_debug("Framelist address: %p vs. %p.\n", 355 frame_list, addr_to_phys(instance->frame_list)); 356 } 431 frame_list, addr_to_phys(instance->frame_list)); 432 } 433 357 434 int frnum = pio_read_16(&instance->registers->frnum) & 0x3ff; 358 435 usb_log_debug2("Framelist item: %d \n", frnum ); 359 436 360 queue_head_t* qh = instance->transfers_interrupt.queue_head;361 362 if ( (instance->frame_list[frnum] & (~0xf)) != (uintptr_t)addr_to_phys(qh)) {437 uintptr_t expected_pa = instance->frame_list[frnum] & (~0xf); 438 uintptr_t real_pa = addr_to_phys(QH(interrupt)); 439 if (expected_pa != real_pa) { 363 440 usb_log_debug("Interrupt QH: %p vs. %p.\n", 364 instance->frame_list[frnum] & (~0xf), addr_to_phys(qh)); 365 } 366 367 if ((qh->next_queue & (~0xf)) 368 != (uintptr_t)addr_to_phys(instance->transfers_control_slow.queue_head)) { 369 usb_log_debug("Control Slow QH: %p vs. %p.\n", qh->next_queue & (~0xf), 370 addr_to_phys(instance->transfers_control_slow.queue_head)); 371 } 372 qh = instance->transfers_control_slow.queue_head; 373 374 if ((qh->next_queue & (~0xf)) 375 != (uintptr_t)addr_to_phys(instance->transfers_control_full.queue_head)) { 376 usb_log_debug("Control Full QH: %p vs. %p.\n", qh->next_queue & (~0xf), 377 addr_to_phys(instance->transfers_control_full.queue_head));\ 378 } 379 qh = instance->transfers_control_full.queue_head; 380 381 if ((qh->next_queue & (~0xf)) 382 != (uintptr_t)addr_to_phys(instance->transfers_bulk_full.queue_head)) { 383 usb_log_debug("Bulk QH: %p vs. %p.\n", qh->next_queue & (~0xf), 384 addr_to_phys(instance->transfers_bulk_full.queue_head)); 385 } 386 /* 387 uint16_t cmd = pio_read_16(&instance->registers->usbcmd); 388 cmd |= UHCI_CMD_RUN_STOP; 389 pio_write_16(&instance->registers->usbcmd, cmd); 390 */ 441 expected_pa, real_pa); 442 } 443 444 expected_pa = QH(interrupt)->next_queue & (~0xf); 445 real_pa = addr_to_phys(QH(control_slow)); 446 if (expected_pa != real_pa) { 447 usb_log_debug("Control Slow QH: %p vs. %p.\n", 448 expected_pa, real_pa); 449 } 450 451 expected_pa = QH(control_slow)->next_queue & (~0xf); 452 real_pa = addr_to_phys(QH(control_full)); 453 if (expected_pa != real_pa) { 454 usb_log_debug("Control Full QH: %p vs. %p.\n", 455 expected_pa, real_pa); 456 } 457 458 expected_pa = QH(control_full)->next_queue & (~0xf); 459 real_pa = addr_to_phys(QH(bulk_full)); 460 if (expected_pa != real_pa ) { 461 usb_log_debug("Bulk QH: %p vs. %p.\n", 462 expected_pa, real_pa); 463 } 391 464 async_usleep(UHCI_DEBUGER_TIMEOUT); 392 465 } 393 return 0; 394 } 395 /*----------------------------------------------------------------------------*/ 466 return EOK; 467 #undef QH 468 } 469 /*----------------------------------------------------------------------------*/ 470 /** Checks transfer packets, for USB validity 471 * 472 * @param[in] low_speed Transfer speed. 473 * @param[in] transfer Transer type 474 * @param[in] size Maximum size of used packets 475 * @return EOK 476 */ 396 477 bool allowed_usb_packet( 397 bool low_speed, usb_transfer_type_t transfer, size_t size)478 bool low_speed, usb_transfer_type_t transfer, size_t size) 398 479 { 399 480 /* see USB specification chapter 5.5-5.8 for magic numbers used here */ 400 switch(transfer) { 401 case USB_TRANSFER_ISOCHRONOUS: 402 return (!low_speed && size < 1024); 403 case USB_TRANSFER_INTERRUPT: 404 return size <= (low_speed ? 8 : 64); 405 case USB_TRANSFER_CONTROL: /* device specifies its own max size */ 406 return (size <= (low_speed ? 8 : 64)); 407 case USB_TRANSFER_BULK: /* device specifies its own max size */ 408 return (!low_speed && size <= 64); 481 switch(transfer) 482 { 483 case USB_TRANSFER_ISOCHRONOUS: 484 return (!low_speed && size < 1024); 485 case USB_TRANSFER_INTERRUPT: 486 return size <= (low_speed ? 8 : 64); 487 case USB_TRANSFER_CONTROL: /* device specifies its own max size */ 488 return (size <= (low_speed ? 8 : 64)); 489 case USB_TRANSFER_BULK: /* device specifies its own max size */ 490 return (!low_speed && size <= 64); 409 491 } 410 492 return false; -
uspace/drv/uhci-hcd/uhci.h
r60a228f r9d9ffdd 84 84 device_keeper_t device_manager; 85 85 86 volatileregs_t *registers;86 regs_t *registers; 87 87 88 88 link_pointer_t *frame_list; -
uspace/drv/uhci-hcd/uhci_struct/queue_head.h
r60a228f r9d9ffdd 71 71 } 72 72 73 static inline void queue_head_ element_td(queue_head_t *instance, uint32_t pa)73 static inline void queue_head_set_element_td(queue_head_t *instance, uint32_t pa) 74 74 { 75 75 if (pa) { … … 78 78 } 79 79 80 static inline queue_head_t * queue_head_get() {81 queue_head_t *ret = malloc32(sizeof(queue_head_t));82 if (ret)83 queue_head_init(ret);84 return ret;85 }86 87 static inline void queue_head_dispose(queue_head_t *head)88 { free32(head); }89 90 91 80 #endif 92 81 /** -
uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.c
r60a228f r9d9ffdd 38 38 #include "utils/malloc32.h" 39 39 40 void transfer_descriptor_init(transfer_descriptor_t *instance, 41 int error_count, size_t size, bool toggle, bool isochronous, bool low_speed, 42 usb_target_t target, int pid, void *buffer, transfer_descriptor_t *next) 40 /** Initializes Transfer Descriptor 41 * 42 * @param[in] instance Memory place to initialize. 43 * @param[in] err_count Number of retries hc should attempt. 44 * @param[in] size Size of data source. 45 * @param[in] toggle Value of toggle bit. 46 * @param[in] iso True if TD is for Isochronous transfer. 47 * @param[in] low_speed Target device's speed. 48 * @param[in] target Address and endpoint receiving the transfer. 49 * @param[in] pid Packet identification (SETUP, IN or OUT). 50 * @param[in] buffer Source of data. 51 * @param[in] next Net TD in transaction. 52 * @return Error code. 53 */ 54 void td_init(td_t *instance, int err_count, size_t size, bool toggle, bool iso, 55 bool low_speed, usb_target_t target, usb_packet_id pid, void *buffer, 56 td_t *next) 43 57 { 44 58 assert(instance); 59 assert(size < 1024); 60 assert((pid == USB_PID_SETUP) || (pid == USB_PID_IN) 61 || (pid == USB_PID_OUT)); 45 62 46 63 instance->next = 0 … … 49 66 50 67 instance->status = 0 51 | ((error_count & TD_STATUS_ERROR_COUNT_MASK) << TD_STATUS_ERROR_COUNT_POS) 52 | (low_speed ? TD_STATUS_LOW_SPEED_FLAG : 0) 53 | TD_STATUS_ERROR_ACTIVE; 68 | ((err_count & TD_STATUS_ERROR_COUNT_MASK) << TD_STATUS_ERROR_COUNT_POS) 69 | (low_speed ? TD_STATUS_LOW_SPEED_FLAG : 0) 70 | (iso ? TD_STATUS_ISOCHRONOUS_FLAG : 0) 71 | TD_STATUS_ERROR_ACTIVE; 54 72 55 assert(size < 1024); 73 if (pid == USB_PID_IN && !iso) { 74 instance->status |= TD_STATUS_SPD_FLAG; 75 } 76 56 77 instance->device = 0 57 | (((size - 1) & TD_DEVICE_MAXLEN_MASK) << TD_DEVICE_MAXLEN_POS)58 | (toggle ? TD_DEVICE_DATA_TOGGLE_ONE_FLAG : 0)59 | ((target.address & TD_DEVICE_ADDRESS_MASK) << TD_DEVICE_ADDRESS_POS)60 | ((target.endpoint & TD_DEVICE_ENDPOINT_MASK) << TD_DEVICE_ENDPOINT_POS)61 | ((pid & TD_DEVICE_PID_MASK) << TD_DEVICE_PID_POS);78 | (((size - 1) & TD_DEVICE_MAXLEN_MASK) << TD_DEVICE_MAXLEN_POS) 79 | (toggle ? TD_DEVICE_DATA_TOGGLE_ONE_FLAG : 0) 80 | ((target.address & TD_DEVICE_ADDRESS_MASK) << TD_DEVICE_ADDRESS_POS) 81 | ((target.endpoint & TD_DEVICE_ENDPOINT_MASK) << TD_DEVICE_ENDPOINT_POS) 82 | ((pid & TD_DEVICE_PID_MASK) << TD_DEVICE_PID_POS); 62 83 63 84 instance->buffer_ptr = 0; … … 68 89 69 90 usb_log_debug2("Created TD: %X:%X:%X:%X(%p).\n", 70 instance->next, instance->status, instance->device, 71 instance->buffer_ptr, buffer); 91 instance->next, instance->status, instance->device, 92 instance->buffer_ptr, buffer); 93 if (pid == USB_PID_SETUP) { 94 usb_log_debug("SETUP BUFFER: %s\n", 95 usb_debug_str_buffer(buffer, 8, 8)); 96 } 72 97 } 73 98 /*----------------------------------------------------------------------------*/ 74 int transfer_descriptor_status(transfer_descriptor_t *instance) 99 /** Converts TD status into standard error code 100 * 101 * @param[in] instance TD structure to use. 102 * @return Error code. 103 */ 104 int td_status(td_t *instance) 75 105 { 76 106 assert(instance); -
uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.h
r60a228f r9d9ffdd 88 88 * we don't use it anyway 89 89 */ 90 } __attribute__((packed)) t ransfer_descriptor_t;90 } __attribute__((packed)) td_t; 91 91 92 92 93 void t ransfer_descriptor_init(transfer_descriptor_t *instance,94 int error_count, size_t size, bool toggle, bool isochronous, bool low_speed,95 usb_target_t target, int pid, void *buffer, transfer_descriptor_t *next);93 void td_init(td_t *instance, int error_count, size_t size, bool toggle, bool iso, 94 bool low_speed, usb_target_t target, usb_packet_id pid, void *buffer, 95 td_t *next); 96 96 97 int t ransfer_descriptor_status(transfer_descriptor_t *instance);97 int td_status(td_t *instance); 98 98 99 static inline size_t transfer_descriptor_actual_size( 100 transfer_descriptor_t *instance) 99 static inline size_t td_act_size(td_t *instance) 101 100 { 102 101 assert(instance); 103 102 return 104 ((instance->status >> TD_STATUS_ACTLEN_POS) + 1) & TD_STATUS_ACTLEN_MASK; 103 ((instance->status >> TD_STATUS_ACTLEN_POS) + 1) 104 & TD_STATUS_ACTLEN_MASK; 105 105 } 106 106 107 static inline bool transfer_descriptor_is_active( 108 transfer_descriptor_t *instance) 107 static inline bool td_is_short(td_t *instance) 108 { 109 const size_t act_size = td_act_size(instance); 110 const size_t max_size = 111 ((instance->device >> TD_DEVICE_MAXLEN_POS) + 1) 112 & TD_DEVICE_MAXLEN_MASK; 113 return 114 (instance->status | TD_STATUS_SPD_FLAG) && act_size < max_size; 115 } 116 117 static inline int td_toggle(td_t *instance) 118 { 119 assert(instance); 120 return ((instance->device & TD_DEVICE_DATA_TOGGLE_ONE_FLAG) != 0) 121 ? 1 : 0; 122 } 123 124 static inline bool td_is_active(td_t *instance) 109 125 { 110 126 assert(instance); -
uspace/drv/uhci-hcd/utils/device_keeper.c
r60a228f r9d9ffdd 35 35 #include <assert.h> 36 36 #include <errno.h> 37 #include <usb/debug.h> 37 38 38 39 #include "device_keeper.h" 39 40 40 41 /*----------------------------------------------------------------------------*/ 42 /** Initializes device keeper structure. 43 * 44 * @param[in] instance Memory place to initialize. 45 */ 41 46 void device_keeper_init(device_keeper_t *instance) 42 47 { … … 49 54 instance->devices[i].occupied = false; 50 55 instance->devices[i].handle = 0; 51 } 52 } 53 /*----------------------------------------------------------------------------*/ 54 void device_keeper_reserve_default( 55 device_keeper_t *instance, usb_speed_t speed) 56 instance->devices[i].toggle_status = 0; 57 } 58 } 59 /*----------------------------------------------------------------------------*/ 60 /** Attempts to obtain address 0, blocks. 61 * 62 * @param[in] instance Device keeper structure to use. 63 * @param[in] speed Speed of the device requesting default address. 64 */ 65 void device_keeper_reserve_default(device_keeper_t *instance, usb_speed_t speed) 56 66 { 57 67 assert(instance); … … 66 76 } 67 77 /*----------------------------------------------------------------------------*/ 78 /** Attempts to obtain address 0, blocks. 79 * 80 * @param[in] instance Device keeper structure to use. 81 * @param[in] speed Speed of the device requesting default address. 82 */ 68 83 void device_keeper_release_default(device_keeper_t *instance) 69 84 { … … 75 90 } 76 91 /*----------------------------------------------------------------------------*/ 92 /** Checks setup data for signs of toggle reset. 93 * 94 * @param[in] instance Device keeper structure to use. 95 * @param[in] target Device to receive setup packet. 96 * @param[in] data Setup packet data. 97 */ 98 void device_keeper_reset_if_need( 99 device_keeper_t *instance, usb_target_t target, const unsigned char *data) 100 { 101 assert(instance); 102 fibril_mutex_lock(&instance->guard); 103 if (target.endpoint > 15 || target.endpoint < 0 104 || target.address >= USB_ADDRESS_COUNT || target.address < 0 105 || !instance->devices[target.address].occupied) { 106 fibril_mutex_unlock(&instance->guard); 107 return; 108 } 109 110 switch (data[1]) 111 { 112 case 0x01: /*clear feature*/ 113 /* recipient is endpoint, value is zero (ENDPOINT_STALL) */ 114 if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) { 115 /* endpoint number is < 16, thus first byte is enough */ 116 instance->devices[target.address].toggle_status &= 117 ~(1 << data[4]); 118 } 119 break; 120 121 case 0x9: /* set configuration */ 122 case 0x11: /* set interface */ 123 /* target must be device */ 124 if ((data[0] & 0xf) == 0) { 125 instance->devices[target.address].toggle_status = 0; 126 } 127 break; 128 } 129 fibril_mutex_unlock(&instance->guard); 130 } 131 /*----------------------------------------------------------------------------*/ 132 /** Gets current value of endpoint toggle. 133 * 134 * @param[in] instance Device keeper structure to use. 135 * @param[in] target Device and endpoint used. 136 * @return Error code 137 */ 138 int device_keeper_get_toggle(device_keeper_t *instance, usb_target_t target) 139 { 140 assert(instance); 141 int ret; 142 fibril_mutex_lock(&instance->guard); 143 if (target.endpoint > 15 || target.endpoint < 0 144 || target.address >= USB_ADDRESS_COUNT || target.address < 0 145 || !instance->devices[target.address].occupied) { 146 ret = EINVAL; 147 } else { 148 ret = 149 (instance->devices[target.address].toggle_status 150 >> target.endpoint) & 1; 151 } 152 fibril_mutex_unlock(&instance->guard); 153 return ret; 154 } 155 /*----------------------------------------------------------------------------*/ 156 /** Sets current value of endpoint toggle. 157 * 158 * @param[in] instance Device keeper structure to use. 159 * @param[in] target Device and endpoint used. 160 * @param[in] toggle Current toggle value. 161 * @return Error code. 162 */ 163 int device_keeper_set_toggle( 164 device_keeper_t *instance, usb_target_t target, bool toggle) 165 { 166 assert(instance); 167 int ret; 168 fibril_mutex_lock(&instance->guard); 169 if (target.endpoint > 15 || target.endpoint < 0 170 || target.address >= USB_ADDRESS_COUNT || target.address < 0 171 || !instance->devices[target.address].occupied) { 172 ret = EINVAL; 173 } else { 174 if (toggle) { 175 instance->devices[target.address].toggle_status |= (1 << target.endpoint); 176 } else { 177 instance->devices[target.address].toggle_status &= ~(1 << target.endpoint); 178 } 179 ret = EOK; 180 } 181 fibril_mutex_unlock(&instance->guard); 182 return ret; 183 } 184 /*----------------------------------------------------------------------------*/ 185 /** Gets a free USB address 186 * 187 * @param[in] instance Device keeper structure to use. 188 * @param[in] speed Speed of the device requiring address. 189 * @return Free address, or error code. 190 */ 77 191 usb_address_t device_keeper_request( 78 192 device_keeper_t *instance, usb_speed_t speed) … … 96 210 instance->devices[new_address].occupied = true; 97 211 instance->devices[new_address].speed = speed; 212 instance->devices[new_address].toggle_status = 0; 98 213 instance->last_address = new_address; 99 214 fibril_mutex_unlock(&instance->guard); … … 101 216 } 102 217 /*----------------------------------------------------------------------------*/ 218 /** Binds USB address to devman handle. 219 * 220 * @param[in] instance Device keeper structure to use. 221 * @param[in] address Device address 222 * @param[in] handle Devman handle of the device. 223 */ 103 224 void device_keeper_bind( 104 225 device_keeper_t *instance, usb_address_t address, devman_handle_t handle) … … 113 234 } 114 235 /*----------------------------------------------------------------------------*/ 236 /** Releases used USB address. 237 * 238 * @param[in] instance Device keeper structure to use. 239 * @param[in] address Device address 240 */ 115 241 void device_keeper_release(device_keeper_t *instance, usb_address_t address) 116 242 { … … 125 251 } 126 252 /*----------------------------------------------------------------------------*/ 253 /** Finds USB address associated with the device 254 * 255 * @param[in] instance Device keeper structure to use. 256 * @param[in] handle Devman handle of the device seeking its address. 257 * @return USB Address, or error code. 258 */ 127 259 usb_address_t device_keeper_find( 128 260 device_keeper_t *instance, devman_handle_t handle) … … 142 274 } 143 275 /*----------------------------------------------------------------------------*/ 276 /** Gets speed associated with the address 277 * 278 * @param[in] instance Device keeper structure to use. 279 * @param[in] address Address of the device. 280 * @return USB speed. 281 */ 144 282 usb_speed_t device_keeper_speed( 145 283 device_keeper_t *instance, usb_address_t address) -
uspace/drv/uhci-hcd/utils/device_keeper.h
r60a228f r9d9ffdd 44 44 usb_speed_t speed; 45 45 bool occupied; 46 uint16_t toggle_status; 46 47 devman_handle_t handle; 47 48 }; … … 55 56 56 57 void device_keeper_init(device_keeper_t *instance); 58 57 59 void device_keeper_reserve_default( 58 60 device_keeper_t *instance, usb_speed_t speed); 61 59 62 void device_keeper_release_default(device_keeper_t *instance); 63 64 void device_keeper_reset_if_need( 65 device_keeper_t *instance, usb_target_t target, const unsigned char *setup_data); 66 67 int device_keeper_get_toggle(device_keeper_t *instance, usb_target_t target); 68 69 int device_keeper_set_toggle( 70 device_keeper_t *instance, usb_target_t target, bool toggle); 60 71 61 72 usb_address_t device_keeper_request( 62 73 device_keeper_t *instance, usb_speed_t speed); 74 63 75 void device_keeper_bind( 64 76 device_keeper_t *instance, usb_address_t address, devman_handle_t handle); 77 65 78 void device_keeper_release(device_keeper_t *instance, usb_address_t address); 79 66 80 usb_address_t device_keeper_find( 67 81 device_keeper_t *instance, devman_handle_t handle); -
uspace/drv/uhci-hcd/utils/malloc32.h
r60a228f r9d9ffdd 34 34 #ifndef DRV_UHCI_TRANSLATOR_H 35 35 #define DRV_UHCI_TRANSLATOR_H 36 37 #include <usb/usbmem.h>38 36 39 37 #include <assert.h> -
uspace/drv/uhci-rhd/main.c
r60a228f r9d9ffdd 35 35 #include <devman.h> 36 36 #include <device/hw_res.h> 37 #include <errno.h> 37 38 #include <usb_iface.h> 38 39 #include <usb/ddfiface.h> 40 #include <usb/debug.h> 39 41 40 #include <errno.h>41 42 42 #include <usb/debug.h>43 43 44 44 #include "root_hub.h" … … 47 47 static int hc_get_my_registers(ddf_dev_t *dev, 48 48 uintptr_t *io_reg_address, size_t *io_reg_size); 49 49 /*----------------------------------------------------------------------------*/ 50 50 static int usb_iface_get_hc_handle(ddf_fun_t *fun, devman_handle_t *handle) 51 51 { … … 58 58 return EOK; 59 59 } 60 60 /*----------------------------------------------------------------------------*/ 61 61 static usb_iface_t uhci_rh_usb_iface = { 62 62 .get_hc_handle = usb_iface_get_hc_handle, 63 63 .get_address = usb_iface_get_address_hub_impl 64 64 }; 65 65 /*----------------------------------------------------------------------------*/ 66 66 static ddf_dev_ops_t uhci_rh_ops = { 67 67 .interfaces[USB_DEV_IFACE] = &uhci_rh_usb_iface, 68 68 }; 69 69 /*----------------------------------------------------------------------------*/ 70 /** Initializes a new ddf driver instance of UHCI root hub. 71 * 72 * @param[in] device DDF instance of the device to initialize. 73 * @return Error code. 74 */ 70 75 static int uhci_rh_add_device(ddf_dev_t *device) 71 76 { … … 104 109 return EOK; 105 110 } 106 111 /*----------------------------------------------------------------------------*/ 107 112 static driver_ops_t uhci_rh_driver_ops = { 108 113 .add_device = uhci_rh_add_device, 109 114 }; 110 115 /*----------------------------------------------------------------------------*/ 111 116 static driver_t uhci_rh_driver = { 112 117 .name = NAME, … … 114 119 }; 115 120 /*----------------------------------------------------------------------------*/ 121 /** Initializes global driver structures (NONE). 122 * 123 * @param[in] argc Nmber of arguments in argv vector (ignored). 124 * @param[in] argv Cmdline argument vector (ignored). 125 * @return Error code. 126 * 127 * Driver debug level is set here. 128 */ 116 129 int main(int argc, char *argv[]) 117 130 { … … 120 133 } 121 134 /*----------------------------------------------------------------------------*/ 122 int hc_get_my_registers(ddf_dev_t *dev, 123 uintptr_t *io_reg_address, size_t *io_reg_size) 135 /** Get address of I/O registers. 136 * 137 * @param[in] dev Device asking for the addresses. 138 * @param[out] io_reg_address Base address of the memory range. 139 * @param[out] io_reg_size Size of the memory range. 140 * @return Error code. 141 */ 142 int hc_get_my_registers( 143 ddf_dev_t *dev, uintptr_t *io_reg_address, size_t *io_reg_size) 124 144 { 125 145 assert(dev != NULL); … … 146 166 for (i = 0; i < hw_resources.count; i++) { 147 167 hw_resource_t *res = &hw_resources.resources[i]; 148 switch (res->type) {149 case IO_RANGE:150 io_address = (uintptr_t)151 res->res.io_range.address;152 io_size = res->res.io_range.size;153 io_found = true;154 break; 155 default:156 break;168 switch (res->type) 169 { 170 case IO_RANGE: 171 io_address = (uintptr_t) res->res.io_range.address; 172 io_size = res->res.io_range.size; 173 io_found = true; 174 175 default: 176 break; 157 177 } 158 178 } … … 170 190 } 171 191 rc = EOK; 192 172 193 leave: 173 194 async_hangup(parent_phone); 174 175 195 return rc; 176 196 } -
uspace/drv/uhci-rhd/port.c
r60a228f r9d9ffdd 46 46 #include "port_status.h" 47 47 48 static int uhci_port_new_device(uhci_port_t *port, u int16_t status);48 static int uhci_port_new_device(uhci_port_t *port, usb_speed_t speed); 49 49 static int uhci_port_remove_device(uhci_port_t *port); 50 50 static int uhci_port_set_enabled(uhci_port_t *port, bool enabled); 51 51 static int uhci_port_check(void *port); 52 static int new_device_enable_port(int portno, void *arg); 53 54 int uhci_port_init( 55 uhci_port_t *port, port_status_t *address, unsigned number, 56 unsigned usec, ddf_dev_t *rh) 52 static int uhci_port_reset_enable(int portno, void *arg); 53 /*----------------------------------------------------------------------------*/ 54 /** Initializes UHCI root hub port instance. 55 * 56 * @param[in] port Memory structure to use. 57 * @param[in] addr Address of I/O register. 58 * @param[in] number Port number. 59 * @param[in] usec Polling interval. 60 * @param[in] rh Pointer to ddf instance fo the root hub driver. 61 * @return Error code. 62 * 63 * Starts the polling fibril. 64 */ 65 int uhci_port_init(uhci_port_t *port, 66 port_status_t *address, unsigned number, unsigned usec, ddf_dev_t *rh) 57 67 { 58 68 assert(port); 69 59 70 port->address = address; 60 71 port->number = number; … … 62 73 port->attached_device = 0; 63 74 port->rh = rh; 75 64 76 int rc = usb_hc_connection_initialize_from_device( 65 77 &port->hc_connection, rh); … … 75 87 return ENOMEM; 76 88 } 89 77 90 fibril_add_ready(port->checker); 78 91 usb_log_debug("Port(%p - %d): Added fibril. %x\n", … … 81 94 } 82 95 /*----------------------------------------------------------------------------*/ 96 /** Finishes UHCI root hub port instance. 97 * 98 * @param[in] port Memory structure to use. 99 * 100 * Stops the polling fibril. 101 */ 83 102 void uhci_port_fini(uhci_port_t *port) 84 103 { 85 // TODO: destroy fibril 86 // TODO: hangup phone 87 // fibril_teardown(port->checker); 104 /* TODO: Kill fibril here */ 88 105 return; 89 106 } 90 107 /*----------------------------------------------------------------------------*/ 108 /** Periodically checks port status and reports new devices. 109 * 110 * @param[in] port Memory structure to use. 111 * @return Error code. 112 */ 91 113 int uhci_port_check(void *port) 92 114 { 93 uhci_port_t * port_instance = port;94 assert( port_instance);95 // port_status_write(port_instance->address, 0); 96 115 uhci_port_t *instance = port; 116 assert(instance); 117 118 /* Iteration count, for debug purposes only */ 97 119 unsigned count = 0; 98 120 99 121 while (1) { 100 async_usleep( port_instance->wait_period_usec);122 async_usleep(instance->wait_period_usec); 101 123 102 124 /* read register value */ 103 port_status_t port_status = 104 port_status_read(port_instance->address); 105 106 /* debug print */107 static fibril_mutex_t dbg_mtx =FIBRIL_MUTEX_INITIALIZER(dbg_mtx);125 port_status_t port_status = port_status_read(instance->address); 126 127 /* debug print mutex */ 128 static fibril_mutex_t dbg_mtx = 129 FIBRIL_MUTEX_INITIALIZER(dbg_mtx); 108 130 fibril_mutex_lock(&dbg_mtx); 109 131 usb_log_debug2("Port(%p - %d): Status: %#04x. === %u\n", 110 port_instance->address, port_instance->number, port_status, count++);132 instance->address, instance->number, port_status, count++); 111 133 // print_port_status(port_status); 112 134 fibril_mutex_unlock(&dbg_mtx); 113 135 114 if ((port_status & STATUS_CONNECTED_CHANGED) != 0) { 115 usb_log_debug("Port(%p - %d): Connected change detected: %x.\n", 116 port_instance->address, port_instance->number, port_status); 117 118 119 int rc = usb_hc_connection_open( 120 &port_instance->hc_connection); 121 if (rc != EOK) { 122 usb_log_error("Port(%p - %d): Failed to connect to HC.", 123 port_instance->address, port_instance->number); 124 continue; 125 } 126 127 /* remove any old device */ 128 if (port_instance->attached_device) { 129 usb_log_debug("Port(%p - %d): Removing device.\n", 130 port_instance->address, port_instance->number); 131 uhci_port_remove_device(port_instance); 132 } 133 134 if ((port_status & STATUS_CONNECTED) != 0) { 135 /* new device */ 136 uhci_port_new_device(port_instance, port_status); 137 } else { 138 /* ack changes by writing one to WC bits */ 139 port_status_write(port_instance->address, port_status); 140 usb_log_debug("Port(%p - %d): Change status ACK.\n", 141 port_instance->address, port_instance->number); 142 } 143 144 rc = usb_hc_connection_close( 145 &port_instance->hc_connection); 146 if (rc != EOK) { 147 usb_log_error("Port(%p - %d): Failed to disconnect from HC.", 148 port_instance->address, port_instance->number); 149 } 150 } 151 } 152 return EOK; 153 } 154 136 if ((port_status & STATUS_CONNECTED_CHANGED) == 0) 137 continue; 138 139 usb_log_debug("Port(%p - %d): Connected change detected: %x.\n", 140 instance->address, instance->number, port_status); 141 142 int rc = 143 usb_hc_connection_open(&instance->hc_connection); 144 if (rc != EOK) { 145 usb_log_error("Port(%p - %d): Failed to connect to HC.", 146 instance->address, instance->number); 147 continue; 148 } 149 150 /* Remove any old device */ 151 if (instance->attached_device) { 152 usb_log_debug2("Port(%p - %d): Removing device.\n", 153 instance->address, instance->number); 154 uhci_port_remove_device(instance); 155 } 156 157 if ((port_status & STATUS_CONNECTED) != 0) { 158 /* New device */ 159 const usb_speed_t speed = 160 ((port_status & STATUS_LOW_SPEED) != 0) ? 161 USB_SPEED_LOW : USB_SPEED_FULL; 162 uhci_port_new_device(instance, speed); 163 } else { 164 /* Write one to WC bits, to ack changes */ 165 port_status_write(instance->address, port_status); 166 usb_log_debug("Port(%p - %d): Change status ACK.\n", 167 instance->address, instance->number); 168 } 169 170 rc = usb_hc_connection_close(&instance->hc_connection); 171 if (rc != EOK) { 172 usb_log_error("Port(%p - %d): Failed to disconnect.", 173 instance->address, instance->number); 174 } 175 } 176 return EOK; 177 } 178 /*----------------------------------------------------------------------------*/ 155 179 /** Callback for enabling port during adding a new device. 156 180 * … … 159 183 * @return Error code. 160 184 */ 161 static int new_device_enable_port(int portno, void *arg)185 int uhci_port_reset_enable(int portno, void *arg) 162 186 { 163 187 uhci_port_t *port = (uhci_port_t *) arg; … … 184 208 port_status_write(port->address, port_status); 185 209 async_usleep(10000); 186 port_status = 187 port_status_read(port->address); 210 port_status = port_status_read(port->address); 188 211 port_status &= ~STATUS_IN_RESET; 189 212 port_status_write(port->address, port_status); … … 194 217 /* Enable the port. */ 195 218 uhci_port_set_enabled(port, true); 196 197 return EOK; 198 } 199 200 /*----------------------------------------------------------------------------*/ 201 static int uhci_port_new_device(uhci_port_t *port, uint16_t status) 219 return EOK; 220 } 221 /*----------------------------------------------------------------------------*/ 222 /** Initializes and reports connected device. 223 * 224 * @param[in] port Memory structure to use. 225 * @param[in] speed Detected speed. 226 * @return Error code. 227 * 228 * Uses libUSB function to do the actual work. 229 */ 230 int uhci_port_new_device(uhci_port_t *port, usb_speed_t speed) 202 231 { 203 232 assert(port); … … 209 238 usb_address_t dev_addr; 210 239 int rc = usb_hc_new_device_wrapper(port->rh, &port->hc_connection, 211 ((status & STATUS_LOW_SPEED) != 0) ? USB_SPEED_LOW : USB_SPEED_FULL, 212 new_device_enable_port, port->number, port, 240 speed, uhci_port_reset_enable, port->number, port, 213 241 &dev_addr, &port->attached_device, NULL, NULL, NULL); 214 242 215 243 if (rc != EOK) { 216 usb_log_error("Port(%p-%d): Failed(%d) adding newdevice: %s.\n",244 usb_log_error("Port(%p-%d): Failed(%d) to add device: %s.\n", 217 245 port->address, port->number, rc, str_error(rc)); 218 246 uhci_port_set_enabled(port, false); … … 225 253 return EOK; 226 254 } 227 228 /*----------------------------------------------------------------------------*/ 229 static int uhci_port_remove_device(uhci_port_t *port) 255 /*----------------------------------------------------------------------------*/ 256 /** Removes device. 257 * 258 * @param[in] port Memory structure to use. 259 * @return Error code. 260 * 261 * Does not work DDF does not support device removal. 262 */ 263 int uhci_port_remove_device(uhci_port_t *port) 230 264 { 231 265 usb_log_error("Port(%p-%d): Don't know how to remove device %#x.\n", 232 port->address, port->number, (unsigned int)port->attached_device); 233 // uhci_port_set_enabled(port, false); 234 return EOK; 235 } 236 /*----------------------------------------------------------------------------*/ 237 static int uhci_port_set_enabled(uhci_port_t *port, bool enabled) 266 port->address, port->number, (unsigned int)port->attached_device); 267 return EOK; 268 } 269 /*----------------------------------------------------------------------------*/ 270 /** Enables and disables port. 271 * 272 * @param[in] port Memory structure to use. 273 * @return Error code. (Always EOK) 274 */ 275 int uhci_port_set_enabled(uhci_port_t *port, bool enabled) 238 276 { 239 277 assert(port); 240 278 241 /* read register value */ 242 port_status_t port_status 243 = port_status_read(port->address); 244 245 /* enable port: register write */ 279 /* Read register value */ 280 port_status_t port_status = port_status_read(port->address); 281 282 /* Set enabled bit */ 246 283 if (enabled) { 247 284 port_status |= STATUS_ENABLED; … … 249 286 port_status &= ~STATUS_ENABLED; 250 287 } 288 289 /* Write new value. */ 251 290 port_status_write(port->address, port_status); 252 291 -
uspace/drv/uhci-rhd/port_status.c
r60a228f r9d9ffdd 60 60 }; 61 61 62 /** Prints portr status in a human readable way. 63 * 64 * @param[in] value Port value to print. 65 * @return Error code. 66 */ 62 67 void print_port_status(port_status_t value) 63 68 { -
uspace/drv/uhci-rhd/root_hub.c
r60a228f r9d9ffdd 40 40 #include "root_hub.h" 41 41 42 /** Initializes UHCI root hub instance. 43 * 44 * @param[in] instance Driver memory structure to use. 45 * @param[in] addr Address of I/O registers. 46 * @param[in] size Size of available I/O space. 47 * @param[in] rh Pointer to ddf instance fo the root hub driver. 48 * @return Error code. 49 */ 42 50 int uhci_root_hub_init( 43 51 uhci_root_hub_t *instance, void *addr, size_t size, ddf_dev_t *rh) … … 47 55 int ret; 48 56 49 /* allow access to root hubregisters */50 assert(sizeof(port_status_t) * UHCI_ROOT_HUB_PORT_COUNT == size);57 /* Allow access to root hub port registers */ 58 assert(sizeof(port_status_t) * UHCI_ROOT_HUB_PORT_COUNT <= size); 51 59 port_status_t *regs; 52 60 ret = pio_enable(addr, size, (void**)®s); 53 54 61 if (ret < 0) { 55 usb_log_error("Failed to gain access to port registers at %p\n", regs); 62 usb_log_error( 63 "Failed to gain access to port registers at %p\n", regs); 56 64 return ret; 57 65 } … … 60 68 unsigned i = 0; 61 69 for (; i < UHCI_ROOT_HUB_PORT_COUNT; ++i) { 62 /* mind pointer arithmetics*/70 /* NOTE: mind pointer arithmetics here */ 63 71 ret = uhci_port_init( 64 &instance->ports[i], regs + i, i, ROOT_HUB_WAIT_USEC, rh);72 &instance->ports[i], regs + i, i, ROOT_HUB_WAIT_USEC, rh); 65 73 if (ret != EOK) { 66 74 unsigned j = 0; … … 74 82 } 75 83 /*----------------------------------------------------------------------------*/ 76 int uhci_root_hub_fini( uhci_root_hub_t* instance ) 84 /** Finishes UHCI root hub instance. 85 * 86 * @param[in] instance Driver memory structure to use. 87 * @return Error code. 88 */ 89 int uhci_root_hub_fini(uhci_root_hub_t* instance) 77 90 { 78 assert( instance ); 79 // TODO: 80 //destroy fibril here 81 //disable access to registers 91 assert(instance); 92 unsigned i = 0; 93 for (; i < UHCI_ROOT_HUB_PORT_COUNT; ++i) { 94 uhci_port_fini(&instance->ports[i]); 95 } 82 96 return EOK; 83 97 } -
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 -
uspace/drv/usbhub/usbhub.c
r60a228f r9d9ffdd 149 149 } 150 150 151 / /configuration descriptor152 /// \TODO check other configurations?153 usb_standard_configuration_descriptor_t config_descriptor;154 opResult = usb_request_get_ bare_configuration_descriptor(151 /* Retrieve full configuration descriptor. */ 152 uint8_t *descriptors = NULL; 153 size_t descriptors_size = 0; 154 opResult = usb_request_get_full_configuration_descriptor_alloc( 155 155 &hub->endpoints.control, 0, 156 &config_descriptor); 157 if(opResult!=EOK){ 158 dprintf(USB_LOG_LEVEL_ERROR, "could not get configuration descriptor, %d",opResult); 156 (void **) &descriptors, &descriptors_size); 157 if (opResult != EOK) { 158 usb_log_error("Could not get configuration descriptor: %s.\n", 159 str_error(opResult)); 159 160 return opResult; 160 161 } 161 //set configuration 162 usb_standard_configuration_descriptor_t *config_descriptor 163 = (usb_standard_configuration_descriptor_t *) descriptors; 164 165 /* Set configuration. */ 162 166 opResult = usb_request_set_configuration(&hub->endpoints.control, 163 config_descriptor.configuration_number); 164 165 if (opResult != EOK) { 166 dprintf(USB_LOG_LEVEL_ERROR, 167 "something went wrong when setting hub`s configuration, %d", 168 opResult); 167 config_descriptor->configuration_number); 168 169 if (opResult != EOK) { 170 usb_log_error("Failed to set hub configuration: %s.\n", 171 str_error(opResult)); 169 172 return opResult; 170 173 } 171 174 dprintf(USB_LOG_LEVEL_DEBUG, "\tused configuration %d", 172 config_descriptor.configuration_number); 173 174 //full configuration descriptor 175 size_t transferred = 0; 176 uint8_t * descriptors = (uint8_t *)malloc(config_descriptor.total_length); 177 if (descriptors == NULL) { 178 dprintf(USB_LOG_LEVEL_ERROR, "insufficient memory"); 179 return ENOMEM; 180 } 181 opResult = usb_request_get_full_configuration_descriptor(&hub->endpoints.control, 182 0, descriptors, 183 config_descriptor.total_length, &transferred); 184 if(opResult!=EOK){ 185 free(descriptors); 186 dprintf(USB_LOG_LEVEL_ERROR, 187 "could not get full configuration descriptor, %d",opResult); 188 return opResult; 189 } 190 if (transferred != config_descriptor.total_length) { 191 dprintf(USB_LOG_LEVEL_ERROR, 192 "received incorrect full configuration descriptor"); 193 return ELIMIT; 194 } 175 config_descriptor->configuration_number); 195 176 196 177 usb_endpoint_mapping_t endpoint_mapping[1] = { … … 204 185 opResult = usb_endpoint_pipe_initialize_from_configuration( 205 186 endpoint_mapping, 1, 206 descriptors, config_descriptor.total_length,187 descriptors, descriptors_size, 207 188 &hub->device_connection); 208 189 if (opResult != EOK) { … … 252 233 dprintf(USB_LOG_LEVEL_DEBUG, "starting control transaction"); 253 234 usb_endpoint_pipe_start_session(&result->endpoints.control); 235 opResult = usb_request_set_configuration(&result->endpoints.control, 1); 236 assert(opResult == EOK); 237 254 238 opResult = usb_request_get_descriptor(&result->endpoints.control, 255 239 USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_DEVICE, … … 262 246 dprintf(USB_LOG_LEVEL_ERROR, "failed when receiving hub descriptor, badcode = %d",opResult); 263 247 free(serialized_descriptor); 264 return result; 248 free(result); 249 return NULL; 265 250 } 266 251 dprintf(USB_LOG_LEVEL_DEBUG2, "deserializing descriptor"); … … 268 253 if(descriptor==NULL){ 269 254 dprintf(USB_LOG_LEVEL_WARNING, "could not deserialize descriptor "); 270 result->port_count = 1;///\TODO this code is only for debug!!!271 return result;255 free(result); 256 return NULL; 272 257 } 273 258 … … 305 290 306 291 usb_hub_info_t * hub_info = usb_create_hub_info(dev); 292 if(!hub_info){ 293 return EINTR; 294 } 307 295 308 296 int opResult; … … 313 301 opResult = usb_hub_process_configuration_descriptors(hub_info); 314 302 if(opResult != EOK){ 315 dprintf(USB_LOG_LEVEL_ERROR,"could not get con diguration descriptors, %d",303 dprintf(USB_LOG_LEVEL_ERROR,"could not get configuration descriptors, %d", 316 304 opResult); 317 305 return opResult; -
uspace/drv/usbmid/explore.c
r60a228f r9d9ffdd 42 42 #include "usbmid.h" 43 43 44 /** Allocate and retrieve full configuration descriptor.45 *46 * @param[in] dev USB device.47 * @param[in] config_index Configuration index.48 * @param[out] size Pointer where to store size of the allocated buffer.49 * @return Allocated full configuration descriptor.50 * @retval NULL Error occured.51 */52 static void *get_configuration_descriptor(usbmid_device_t *dev,53 size_t config_index, size_t *size)54 {55 usb_standard_configuration_descriptor_t config_descriptor;56 int rc = usb_request_get_bare_configuration_descriptor(&dev->ctrl_pipe,57 config_index, &config_descriptor);58 if (rc != EOK) {59 usb_log_error("Failed getting configuration descriptor: %s.\n",60 str_error(rc));61 return NULL;62 }63 64 void *full_config_descriptor = malloc(config_descriptor.total_length);65 if (full_config_descriptor == NULL) {66 usb_log_fatal("Out of memory (wanted: %zuB).\n",67 (size_t) config_descriptor.total_length);68 return NULL;69 }70 71 size_t full_config_descriptor_size;72 rc = usb_request_get_full_configuration_descriptor(&dev->ctrl_pipe,73 config_index,74 full_config_descriptor, config_descriptor.total_length,75 &full_config_descriptor_size);76 if (rc != EOK) {77 usb_log_error("Failed getting configuration descriptor: %s.\n",78 str_error(rc));79 free(full_config_descriptor);80 return NULL;81 }82 83 if (full_config_descriptor_size != config_descriptor.total_length) {84 usb_log_error("Failed getting full configuration descriptor.\n");85 free(full_config_descriptor);86 return NULL;87 }88 89 if (size != NULL) {90 *size = full_config_descriptor_size;91 }92 93 return full_config_descriptor;94 }95 96 44 /** Find starting indexes of all interface descriptors in a configuration. 97 45 * … … 178 126 179 127 size_t config_descriptor_size; 180 uint8_t *config_descriptor_raw = get_configuration_descriptor(dev, 0, 181 &config_descriptor_size); 182 if (config_descriptor_raw == NULL) { 128 uint8_t *config_descriptor_raw = NULL; 129 rc = usb_request_get_full_configuration_descriptor_alloc( 130 &dev->ctrl_pipe, 0, 131 (void **) &config_descriptor_raw, &config_descriptor_size); 132 if (rc != EOK) { 133 usb_log_error("Failed getting full config descriptor: %s.\n", 134 str_error(rc)); 183 135 return false; 184 136 } … … 207 159 } 208 160 161 /* Select the first configuration */ 162 rc = usb_request_set_configuration(&dev->ctrl_pipe, 163 config_descriptor->configuration_number); 164 if (rc != EOK) { 165 usb_log_error("Failed to set device configuration: %s.\n", 166 str_error(rc)); 167 free(config_descriptor_raw); 168 free(interface_descriptors); 169 return false; 170 } 171 172 173 /* Create control function */ 209 174 ddf_fun_t *ctl_fun = ddf_fun_create(dev->dev, fun_exposed, "ctl"); 210 175 if (ctl_fun == NULL) { … … 223 188 } 224 189 190 /* Spawn interface children */ 225 191 size_t i; 226 192 for (i = 0; i < interface_descriptors_count; i++) { -
uspace/drv/usbmid/main.c
r60a228f r9d9ffdd 44 44 #include "usbmid.h" 45 45 46 /** Callback when new MID device is attached to the host. 47 * 48 * @param gen_dev Generic DDF device representing the new device. 49 * @return Error code. 50 */ 46 51 static int usbmid_add_device(ddf_dev_t *gen_dev) 47 52 { … … 86 91 } 87 92 93 /** USB MID driver ops. */ 88 94 static driver_ops_t mid_driver_ops = { 89 95 .add_device = usbmid_add_device, 90 96 }; 91 97 98 /** USB MID driver. */ 92 99 static driver_t mid_driver = { 93 100 .name = NAME, -
uspace/drv/usbmid/usbmid.c
r60a228f r9d9ffdd 67 67 } 68 68 69 /** DDF interface of the child - interface function. */ 69 70 static usb_iface_t child_usb_iface = { 70 71 .get_hc_handle = usb_iface_get_hc_handle_hub_child_impl, … … 73 74 }; 74 75 75 76 /** Operations for children - interface functions. */ 76 77 static ddf_dev_ops_t child_device_ops = { 77 78 .interfaces[USB_DEV_IFACE] = &child_usb_iface 78 79 }; 79 80 81 /** Operations of the device itself. */ 80 82 static ddf_dev_ops_t mid_device_ops = { 81 83 .interfaces[USB_DEV_IFACE] = &usb_iface_hub_impl … … 123 125 /** Create new interface for USB MID device. 124 126 * 125 * @param dev Backing generic DDF child device(representing interface).127 * @param fun Backing generic DDF device function (representing interface). 126 128 * @param iface_no Interface number. 127 129 * @return New interface. -
uspace/drv/usbmid/usbmid.h
r60a228f r9d9ffdd 44 44 #define NAME "usbmid" 45 45 46 /** USB MID device container. */ 46 47 typedef struct { 47 48 /** Device container. */ … … 54 55 } usbmid_device_t; 55 56 57 58 /** Container for single interface in a MID device. */ 56 59 typedef struct { 57 60 /** Function container. */ -
uspace/drv/usbmouse/main.c
r60a228f r9d9ffdd 1 1 /* 2 * Copyright (c) 2011 Matus Dekanek2 * Copyright (c) 2011 Vojtech Horky 3 3 * All rights reserved. 4 4 * … … 27 27 */ 28 28 29 #ifndef USBMEM_H 30 #define USBMEM_H 31 32 33 // group should be changed - this is not usb specific 34 /** @addtogroup usb 29 /** @addtogroup drvusbmouse 35 30 * @{ 36 31 */ 37 /** @file definitions of memory management with address translation, used mostly in usb stack 32 /** 33 * @file 34 * Main routines of USB boot protocol mouse driver. 35 */ 36 #include "mouse.h" 37 #include <usb/debug.h> 38 #include <errno.h> 39 #include <str_error.h> 40 41 /** Callback when new mouse device is attached and recognised by DDF. 38 42 * 39 * USB HCD needs traslation between physical and virtual addresses. These 40 * functions implement such functionality. For each allocated virtual address 41 * the memory manager gets also it`s physical translation and remembers it. 42 * Addresses allocated byt this manager can be therefore translated from and to 43 * physical addresses. 44 * Typical use: 45 * void * address = mman_malloc(some_size); 46 * void * physical_address = mman_getPA(address); 47 * void * the_same_address = mman_getVA(physical_address); 48 * void * null_address = mman_getPA(non_existing_address); 49 * mman_free(address); 50 * // physical_address, adress and the_same_address are no longer valid here 51 * 52 * 53 * @note Addresses allocated by this memory manager should be as well 54 * deallocated byt it. 55 * 43 * @param dev Representation of a generic DDF device. 44 * @return Error code. 56 45 */ 46 static int usbmouse_add_device(ddf_dev_t *dev) 47 { 48 int rc = usb_mouse_create(dev); 49 if (rc != EOK) { 50 usb_log_error("Failed to initialize device driver: %s.\n", 51 str_error(rc)); 52 return rc; 53 } 57 54 58 #include <sys/types.h> 55 fid_t poll_fibril = fibril_create(usb_mouse_polling_fibril, dev); 56 if (poll_fibril == 0) { 57 usb_log_error("Failed to initialize polling fibril.\n"); 58 /* FIXME: free allocated resources. */ 59 return ENOMEM; 60 } 59 61 60 extern void * mman_malloc( 61 size_t size, 62 size_t alignment, 63 unsigned long max_physical_address); 62 fibril_add_ready(poll_fibril); 64 63 65 extern void * mman_getVA(void * addr); 64 usb_log_info("controlling new mouse (handle %llu).\n", 65 dev->handle); 66 66 67 extern void * mman_getPA(void * addr); 67 return EOK; 68 } 68 69 69 extern void mman_free(void * addr); 70 /** USB mouse driver ops. */ 71 static driver_ops_t mouse_driver_ops = { 72 .add_device = usbmouse_add_device, 73 }; 70 74 75 /** USB mouse driver. */ 76 static driver_t mouse_driver = { 77 .name = NAME, 78 .driver_ops = &mouse_driver_ops 79 }; 71 80 81 int main(int argc, char *argv[]) 82 { 83 usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME); 72 84 85 return ddf_driver_main(&mouse_driver); 86 } 73 87 74 75 76 /** @} 88 /** 89 * @} 77 90 */ 78 79 80 #endif /* USBMEM_H */81 -
uspace/drv/vhc/conndev.c
r60a228f r9d9ffdd 110 110 /** Callback for DDF when client disconnects. 111 111 * 112 * @param d Devicethe client was connected to.112 * @param fun Device function the client was connected to. 113 113 */ 114 114 void on_client_close(ddf_fun_t *fun)
Note:
See TracChangeset
for help on using the changeset viewer.
