Changes in / [da55d5b:c39544a] in mainline
- Location:
- uspace
- Files:
-
- 4 added
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/usbkbd/usbkbd.ma
rda55d5b rc39544a 1 1 10 usb&class=hid 2 10 usb&hid -
uspace/lib/drv/generic/remote_usbhc.c
rda55d5b rc39544a 42 42 #define USB_MAX_PAYLOAD_SIZE 1020 43 43 44 static void remote_usbhc_get_address(device_t *, void *, ipc_callid_t, ipc_call_t *); 44 45 static void remote_usbhc_get_buffer(device_t *, void *, ipc_callid_t, ipc_call_t *); 45 46 static void remote_usbhc_interrupt_out(device_t *, void *, ipc_callid_t, ipc_call_t *); 46 47 static void remote_usbhc_interrupt_in(device_t *, void *, ipc_callid_t, ipc_call_t *); 47 //static void remote_usb(device_t *, void *, ipc_callid_t, ipc_call_t *); 48 static void remote_usbhc_control_write_setup(device_t *, void *, ipc_callid_t, ipc_call_t *); 49 static void remote_usbhc_control_write_data(device_t *, void *, ipc_callid_t, ipc_call_t *); 50 static void remote_usbhc_control_write_status(device_t *, void *, ipc_callid_t, ipc_call_t *); 51 static void remote_usbhc_control_read_setup(device_t *, void *, ipc_callid_t, ipc_call_t *); 52 static void remote_usbhc_control_read_data(device_t *, void *, ipc_callid_t, ipc_call_t *); 53 static void remote_usbhc_control_read_status(device_t *, void *, ipc_callid_t, ipc_call_t *); 54 //static void remote_usbhc(device_t *, void *, ipc_callid_t, ipc_call_t *); 48 55 49 56 /** Remote USB interface operations. */ 50 57 static remote_iface_func_ptr_t remote_usbhc_iface_ops [] = { 51 &remote_usbhc_get_buffer, 52 &remote_usbhc_interrupt_out, 53 &remote_usbhc_interrupt_in 58 remote_usbhc_get_address, 59 remote_usbhc_get_buffer, 60 remote_usbhc_interrupt_out, 61 remote_usbhc_interrupt_in, 62 remote_usbhc_control_write_setup, 63 remote_usbhc_control_write_data, 64 remote_usbhc_control_write_status, 65 remote_usbhc_control_read_setup, 66 remote_usbhc_control_read_data, 67 remote_usbhc_control_read_status 54 68 }; 55 69 … … 68 82 } async_transaction_t; 69 83 84 void remote_usbhc_get_address(device_t *device, void *iface, 85 ipc_callid_t callid, ipc_call_t *call) 86 { 87 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 88 89 if (!usb_iface->tell_address) { 90 ipc_answer_0(callid, ENOTSUP); 91 return; 92 } 93 94 devman_handle_t handle = IPC_GET_ARG1(*call); 95 96 usb_address_t address; 97 int rc = usb_iface->tell_address(device, handle, &address); 98 if (rc != EOK) { 99 ipc_answer_0(callid, rc); 100 } else { 101 ipc_answer_1(callid, EOK, address); 102 } 103 } 70 104 71 105 void remote_usbhc_get_buffer(device_t *device, void *iface, … … 125 159 } 126 160 127 void remote_usbhc_interrupt_out(device_t *device, void *iface, 128 ipc_callid_t callid, ipc_call_t *call) 129 { 130 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 161 /** Process an outgoing transfer (both OUT and SETUP). 162 * 163 * @param device Target device. 164 * @param callid Initiating caller. 165 * @param call Initiating call. 166 * @param transfer_func Transfer function (might be NULL). 167 */ 168 static void remote_usbhc_out_transfer(device_t *device, 169 ipc_callid_t callid, ipc_call_t *call, 170 usbhc_iface_transfer_out_t transfer_func) 171 { 172 if (!transfer_func) { 173 ipc_answer_0(callid, ENOTSUP); 174 return; 175 } 131 176 132 177 size_t expected_len = IPC_GET_ARG3(*call); … … 149 194 } 150 195 151 if (!usb_iface->interrupt_out) {152 ipc_answer_0(callid, ENOTSUP);153 return;154 }155 156 196 async_transaction_t *trans = malloc(sizeof(async_transaction_t)); 157 197 trans->caller = callid; 158 trans->buffer = NULL;159 trans->size = 0;160 161 int rc = usb_iface->interrupt_out(device, target, buffer, len,198 trans->buffer = buffer; 199 trans->size = len; 200 201 int rc = transfer_func(device, target, buffer, len, 162 202 callback_out, trans); 163 203 164 204 if (rc != EOK) { 165 205 ipc_answer_0(callid, rc); 206 if (buffer != NULL) { 207 free(buffer); 208 } 166 209 free(trans); 167 210 } 168 211 } 169 212 170 void remote_usbhc_interrupt_in(device_t *device, void *iface, 171 ipc_callid_t callid, ipc_call_t *call) 172 { 173 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 213 /** Process an incoming transfer. 214 * 215 * @param device Target device. 216 * @param callid Initiating caller. 217 * @param call Initiating call. 218 * @param transfer_func Transfer function (might be NULL). 219 */ 220 static void remote_usbhc_in_transfer(device_t *device, 221 ipc_callid_t callid, ipc_call_t *call, 222 usbhc_iface_transfer_in_t transfer_func) 223 { 224 if (!transfer_func) { 225 ipc_answer_0(callid, ENOTSUP); 226 return; 227 } 174 228 175 229 size_t len = IPC_GET_ARG3(*call); … … 179 233 }; 180 234 181 if (!usb_iface->interrupt_in) {182 ipc_answer_0(callid, ENOTSUP);183 return;184 }185 186 235 async_transaction_t *trans = malloc(sizeof(async_transaction_t)); 187 236 trans->caller = callid; … … 189 238 trans->size = len; 190 239 191 int rc = usb_iface->interrupt_in(device, target, trans->buffer, len,240 int rc = transfer_func(device, target, trans->buffer, len, 192 241 callback_in, trans); 193 242 … … 199 248 } 200 249 250 /** Process status part of control transfer. 251 * 252 * @param device Target device. 253 * @param callid Initiating caller. 254 * @param call Initiating call. 255 * @param direction Transfer direction (read ~ in, write ~ out). 256 * @param transfer_in_func Transfer function for control read (might be NULL). 257 * @param transfer_out_func Transfer function for control write (might be NULL). 258 */ 259 static void remote_usbhc_status_transfer(device_t *device, 260 ipc_callid_t callid, ipc_call_t *call, 261 usb_direction_t direction, 262 int (*transfer_in_func)(device_t *, usb_target_t, 263 usbhc_iface_transfer_in_callback_t, void *), 264 int (*transfer_out_func)(device_t *, usb_target_t, 265 usbhc_iface_transfer_out_callback_t, void *)) 266 { 267 switch (direction) { 268 case USB_DIRECTION_IN: 269 if (!transfer_in_func) { 270 ipc_answer_0(callid, ENOTSUP); 271 return; 272 } 273 break; 274 case USB_DIRECTION_OUT: 275 if (!transfer_out_func) { 276 ipc_answer_0(callid, ENOTSUP); 277 return; 278 } 279 break; 280 default: 281 assert(false && "unreachable code"); 282 break; 283 } 284 285 usb_target_t target = { 286 .address = IPC_GET_ARG1(*call), 287 .endpoint = IPC_GET_ARG2(*call) 288 }; 289 290 async_transaction_t *trans = malloc(sizeof(async_transaction_t)); 291 trans->caller = callid; 292 trans->buffer = NULL; 293 trans->size = 0; 294 295 int rc; 296 switch (direction) { 297 case USB_DIRECTION_IN: 298 rc = transfer_in_func(device, target, 299 callback_in, trans); 300 break; 301 case USB_DIRECTION_OUT: 302 rc = transfer_out_func(device, target, 303 callback_out, trans); 304 break; 305 default: 306 assert(false && "unreachable code"); 307 break; 308 } 309 310 if (rc != EOK) { 311 ipc_answer_0(callid, rc); 312 free(trans); 313 } 314 return; 315 } 316 317 318 void remote_usbhc_interrupt_out(device_t *device, void *iface, 319 ipc_callid_t callid, ipc_call_t *call) 320 { 321 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 322 assert(usb_iface != NULL); 323 324 return remote_usbhc_out_transfer(device, callid, call, 325 usb_iface->interrupt_out); 326 } 327 328 void remote_usbhc_interrupt_in(device_t *device, void *iface, 329 ipc_callid_t callid, ipc_call_t *call) 330 { 331 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 332 assert(usb_iface != NULL); 333 334 return remote_usbhc_in_transfer(device, callid, call, 335 usb_iface->interrupt_in); 336 } 337 338 void remote_usbhc_control_write_setup(device_t *device, void *iface, 339 ipc_callid_t callid, ipc_call_t *call) 340 { 341 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 342 assert(usb_iface != NULL); 343 344 return remote_usbhc_out_transfer(device, callid, call, 345 usb_iface->control_write_setup); 346 } 347 348 void remote_usbhc_control_write_data(device_t *device, void *iface, 349 ipc_callid_t callid, ipc_call_t *call) 350 { 351 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 352 assert(usb_iface != NULL); 353 354 return remote_usbhc_out_transfer(device, callid, call, 355 usb_iface->control_write_data); 356 } 357 358 void remote_usbhc_control_write_status(device_t *device, void *iface, 359 ipc_callid_t callid, ipc_call_t *call) 360 { 361 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 362 assert(usb_iface != NULL); 363 364 return remote_usbhc_status_transfer(device, callid, call, 365 USB_DIRECTION_IN, usb_iface->control_write_status, NULL); 366 } 367 368 void remote_usbhc_control_read_setup(device_t *device, void *iface, 369 ipc_callid_t callid, ipc_call_t *call) 370 { 371 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 372 assert(usb_iface != NULL); 373 374 return remote_usbhc_out_transfer(device, callid, call, 375 usb_iface->control_read_setup); 376 } 377 378 void remote_usbhc_control_read_data(device_t *device, void *iface, 379 ipc_callid_t callid, ipc_call_t *call) 380 { 381 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 382 assert(usb_iface != NULL); 383 384 return remote_usbhc_in_transfer(device, callid, call, 385 usb_iface->control_read_data); 386 } 387 388 void remote_usbhc_control_read_status(device_t *device, void *iface, 389 ipc_callid_t callid, ipc_call_t *call) 390 { 391 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 392 assert(usb_iface != NULL); 393 394 return remote_usbhc_status_transfer(device, callid, call, 395 USB_DIRECTION_OUT, NULL, usb_iface->control_read_status); 396 } 397 398 201 399 202 400 /** -
uspace/lib/drv/include/usbhc_iface.h
rda55d5b rc39544a 92 92 */ 93 93 typedef enum { 94 /** Tell USB address assigned to device. 95 * Parameters: 96 * - devman handle id 97 * Answer: 98 * - EINVAL - unknown handle or handle not managed by this driver 99 * - ENOTSUP - operation not supported by HC (shall not happen) 100 * - arbitrary error code if returned by remote implementation 101 * - EOK - handle found, first parameter contains the USB address 102 */ 103 IPC_M_USBHC_GET_ADDRESS, 104 94 105 /** Asks for data buffer. 95 106 * See explanation at usb_iface_funcs_t. … … 155 166 usb_transaction_outcome_t, size_t, void *); 156 167 168 169 /** Out transfer processing function prototype. */ 170 typedef int (*usbhc_iface_transfer_out_t)(device_t *, usb_target_t, 171 void *, size_t, 172 usbhc_iface_transfer_out_callback_t, void *); 173 174 /** Setup transfer processing function prototype. */ 175 typedef usbhc_iface_transfer_out_t usbhc_iface_transfer_setup_t; 176 177 /** In transfer processing function prototype. */ 178 typedef int (*usbhc_iface_transfer_in_t)(device_t *, usb_target_t, 179 void *, size_t, 180 usbhc_iface_transfer_in_callback_t, void *); 181 157 182 /** USB devices communication interface. */ 158 183 typedef struct { 159 int (*interrupt_out)(device_t *, usb_target_t, 160 void *, size_t, 184 int (*tell_address)(device_t *, devman_handle_t, usb_address_t *); 185 186 usbhc_iface_transfer_out_t interrupt_out; 187 usbhc_iface_transfer_in_t interrupt_in; 188 189 usbhc_iface_transfer_setup_t control_write_setup; 190 usbhc_iface_transfer_out_t control_write_data; 191 int (*control_write_status)(device_t *, usb_target_t, 192 usbhc_iface_transfer_in_callback_t, void *); 193 194 usbhc_iface_transfer_setup_t control_read_setup; 195 usbhc_iface_transfer_in_t control_read_data; 196 int (*control_read_status)(device_t *, usb_target_t, 161 197 usbhc_iface_transfer_out_callback_t, void *); 162 int (*interrupt_in)(device_t *, usb_target_t,163 void *, size_t,164 usbhc_iface_transfer_in_callback_t, void *);165 198 } usbhc_iface_t; 166 199 -
uspace/lib/usb/Makefile
rda55d5b rc39544a 34 34 SOURCES = \ 35 35 src/hcdhubd.c \ 36 src/hcdrv.c \ 37 src/hubdrv.c \ 36 38 src/localdrv.c \ 39 src/remotedrv.c \ 37 40 src/usb.c \ 38 41 src/usbdrv.c -
uspace/lib/usb/include/usb/hcdhubd.h
rda55d5b rc39544a 37 37 38 38 #include <adt/list.h> 39 #include <bool.h> 39 40 #include <driver.h> 40 41 #include <usb/usb.h> … … 175 176 int usb_hc_async_wait_for(usb_handle_t); 176 177 178 int usb_hc_add_child_device(device_t *, const char *, const char *, bool); 177 179 178 180 #endif -
uspace/lib/usb/include/usb/usbdrv.h
rda55d5b rc39544a 48 48 void *, size_t, size_t *, usb_handle_t *); 49 49 50 int usb_drv_async_control_write_setup(int, usb_target_t, 51 void *, size_t, usb_handle_t *); 52 int usb_drv_async_control_write_data(int, usb_target_t, 53 void *, size_t, usb_handle_t *); 54 int usb_drv_async_control_write_status(int, usb_target_t, 55 usb_handle_t *); 56 57 int usb_drv_async_control_read_setup(int, usb_target_t, 58 void *, size_t, usb_handle_t *); 59 int usb_drv_async_control_read_data(int, usb_target_t, 60 void *, size_t, size_t *, usb_handle_t *); 61 int usb_drv_async_control_read_status(int, usb_target_t, 62 usb_handle_t *); 63 50 64 int usb_drv_async_wait_for(usb_handle_t); 51 65 -
uspace/lib/usb/src/hcdhubd.c
rda55d5b rc39544a 31 31 */ 32 32 /** @file 33 * @brief HC driver and hub driver (implementation).33 * @brief Common stuff for both HC driver and hub driver. 34 34 */ 35 35 #include <usb/hcdhubd.h> … … 40 40 #include <bool.h> 41 41 #include <errno.h> 42 #include <str_error.h> 42 43 #include <usb/classes/hub.h> 43 44 44 #define USB_HUB_DEVICE_NAME "usbhub" 45 46 #define USB_KBD_DEVICE_NAME "hid" 47 48 49 50 51 /** List of handled host controllers. */ 52 static LIST_INITIALIZE(hc_list); 53 54 /** Our HC driver. */ 55 static usb_hc_driver_t *hc_driver = NULL; 56 57 static usbhc_iface_t usb_interface = { 58 .interrupt_out = NULL, 59 .interrupt_in = NULL 60 }; 61 62 static device_ops_t usb_device_ops = { 63 .interfaces[USBHC_DEV_IFACE] = &usb_interface 64 }; 65 66 size_t USB_HUB_MAX_DESCRIPTOR_SIZE = 71; 67 68 uint8_t USB_HUB_DESCRIPTOR_TYPE = 0x29; 69 70 //********************************************* 71 // 72 // various utils 73 // 74 //********************************************* 75 76 void * usb_serialize_hub_descriptor(usb_hub_descriptor_t * descriptor) { 77 //base size 78 size_t size = 7; 79 //variable size according to port count 80 size_t var_size = descriptor->ports_count / 8 + ((descriptor->ports_count % 8 > 0) ? 1 : 0); 81 size += 2 * var_size; 82 uint8_t * result = (uint8_t*) malloc(size); 83 //size 84 result[0] = size; 85 //descriptor type 86 result[1] = USB_DESCTYPE_HUB; 87 result[2] = descriptor->ports_count; 88 /// @fixme handling of endianness?? 89 result[3] = descriptor->hub_characteristics / 256; 90 result[4] = descriptor->hub_characteristics % 256; 91 result[5] = descriptor->pwr_on_2_good_time; 92 result[6] = descriptor->current_requirement; 93 94 size_t i; 95 for (i = 0; i < var_size; ++i) { 96 result[7 + i] = descriptor->devices_removable[i]; 97 } 98 for (i = 0; i < var_size; ++i) { 99 result[7 + var_size + i] = 255; 100 } 101 return result; 102 } 103 104 usb_hub_descriptor_t * usb_deserialize_hub_desriptor(void * serialized_descriptor) { 105 uint8_t * sdescriptor = (uint8_t*) serialized_descriptor; 106 if (sdescriptor[1] != USB_DESCTYPE_HUB) return NULL; 107 usb_hub_descriptor_t * result = (usb_hub_descriptor_t*) malloc(sizeof (usb_hub_descriptor_t)); 108 //uint8_t size = sdescriptor[0]; 109 result->ports_count = sdescriptor[2]; 110 /// @fixme handling of endianness?? 111 result->hub_characteristics = sdescriptor[4] + 256 * sdescriptor[3]; 112 result->pwr_on_2_good_time = sdescriptor[5]; 113 result->current_requirement = sdescriptor[6]; 114 size_t var_size = result->ports_count / 8 + ((result->ports_count % 8 > 0) ? 1 : 0); 115 result->devices_removable = (uint8_t*) malloc(var_size); 116 117 size_t i; 118 for (i = 0; i < var_size; ++i) { 119 result->devices_removable[i] = sdescriptor[7 + i]; 120 } 121 return result; 122 } 123 124 125 //********************************************* 126 // 127 // hub driver code 128 // 129 //********************************************* 130 131 static void set_hub_address(usb_hc_device_t *hc, usb_address_t address); 132 133 usb_hcd_hub_info_t * usb_create_hub_info(device_t * device) { 134 usb_hcd_hub_info_t* result = (usb_hcd_hub_info_t*) malloc(sizeof (usb_hcd_hub_info_t)); 135 //get parent device 136 /// @TODO this code is not correct 137 device_t * my_hcd = device; 138 while (my_hcd->parent) 139 my_hcd = my_hcd->parent; 140 //dev-> 141 printf("%s: owner hcd found: %s\n", hc_driver->name, my_hcd->name); 142 //we add the hub into the first hc 143 //link_t *link_hc = hc_list.next; 144 //usb_hc_device_t *hc = list_get_instance(link_hc, 145 // usb_hc_device_t, link); 146 //must get generic device info 147 148 149 return result; 150 } 45 #include "hcdhubd_private.h" 151 46 152 47 /** Callback when new device is detected and must be handled by this driver. 153 48 * 154 49 * @param dev New device. 155 * @return Error code. hub added, hurrah!\n"50 * @return Error code. 156 51 */ 157 52 static int add_device(device_t *dev) { 158 /*159 * FIXME: use some magic to determine whether hub or another HC160 * was connected.161 */162 53 bool is_hc = str_cmp(dev->name, USB_HUB_DEVICE_NAME) != 0; 163 54 printf("%s: add_device(name=\"%s\")\n", hc_driver->name, dev->name); … … 167 58 * We are the HC itself. 168 59 */ 169 usb_hc_device_t *hc_dev = malloc(sizeof (usb_hc_device_t)); 170 list_initialize(&hc_dev->link); 171 hc_dev->transfer_ops = NULL; 172 173 hc_dev->generic = dev; 174 dev->ops = &usb_device_ops; 175 hc_dev->generic->driver_data = hc_dev; 176 177 int rc = hc_driver->add_hc(hc_dev); 178 if (rc != EOK) { 179 free(hc_dev); 180 return rc; 181 } 182 60 return usb_add_hc_device(dev); 61 } else { 183 62 /* 184 * FIXME: The following line causes devman to hang. 185 * Will investigate later why. 186 */ 187 // add_device_to_class(dev, "usbhc"); 188 189 list_append(&hc_dev->link, &hc_list); 190 191 //add keyboard 192 /// @TODO this is not correct code 193 194 /* 195 * Announce presence of child device. 196 */ 197 device_t *kbd = NULL; 198 match_id_t *match_id = NULL; 199 200 kbd = create_device(); 201 if (kbd == NULL) { 202 printf("ERROR: enomem\n"); 203 } 204 kbd->name = USB_KBD_DEVICE_NAME; 205 206 match_id = create_match_id(); 207 if (match_id == NULL) { 208 printf("ERROR: enomem\n"); 209 } 210 211 char *id; 212 rc = asprintf(&id, USB_KBD_DEVICE_NAME); 213 if (rc <= 0) { 214 printf("ERROR: enomem\n"); 215 return rc; 216 } 217 218 match_id->id = id; 219 match_id->score = 30; 220 221 add_match_id(&kbd->match_ids, match_id); 222 223 rc = child_device_register(kbd, dev); 224 if (rc != EOK) { 225 printf("ERROR: cannot register kbd\n"); 226 return rc; 227 } 228 229 printf("%s: registered root hub\n", dev->name); 230 return EOK; 231 232 233 234 } else { 235 usb_hc_device_t *hc = list_get_instance(hc_list.next, usb_hc_device_t, link); 236 set_hub_address(hc, 5); 237 238 /* 239 * We are some (probably deeply nested) hub. 63 * We are some (maybe deeply nested) hub. 240 64 * Thus, assign our own operations and explore already 241 65 * connected devices. 242 66 */ 243 //insert hub into list 244 //find owner hcd 245 device_t * my_hcd = dev; 246 while (my_hcd->parent) 247 my_hcd = my_hcd->parent; 248 //dev-> 249 printf("%s: owner hcd found: %s\n", hc_driver->name, my_hcd->name); 250 my_hcd = dev; 251 while (my_hcd->parent) 252 my_hcd = my_hcd->parent; 253 //dev-> 254 255 printf("%s: owner hcd found: %s\n", hc_driver->name, my_hcd->name); 256 257 //create the hub structure 258 usb_hcd_hub_info_t * hub_info = usb_create_hub_info(dev); 259 260 261 //append into the list 262 //we add the hub into the first hc 263 list_append(&hub_info->link, &hc->hubs); 264 265 266 267 return EOK; 268 //return ENOTSUP; 269 } 270 } 271 272 /** Sample usage of usb_hc_async functions. 273 * This function sets hub address using standard SET_ADDRESS request. 274 * 275 * @warning This function shall be removed once you are familiar with 276 * the usb_hc_ API. 277 * 278 * @param hc Host controller the hub belongs to. 279 * @param address New hub address. 280 */ 281 static void set_hub_address(usb_hc_device_t *hc, usb_address_t address) { 282 printf("%s: setting hub address to %d\n", hc->generic->name, address); 283 usb_target_t target = {0, 0}; 284 usb_handle_t handle; 285 int rc; 286 287 usb_device_request_setup_packet_t setup_packet = { 288 .request_type = 0, 289 .request = USB_DEVREQ_SET_ADDRESS, 290 .index = 0, 291 .length = 0, 292 }; 293 setup_packet.value = address; 294 295 rc = usb_hc_async_control_write_setup(hc, target, 296 &setup_packet, sizeof (setup_packet), &handle); 297 if (rc != EOK) { 298 return; 299 } 300 301 rc = usb_hc_async_wait_for(handle); 302 if (rc != EOK) { 303 return; 304 } 305 306 rc = usb_hc_async_control_write_status(hc, target, &handle); 307 if (rc != EOK) { 308 return; 309 } 310 311 rc = usb_hc_async_wait_for(handle); 312 if (rc != EOK) { 313 return; 314 } 315 316 printf("%s: hub address changed\n", hc->generic->name); 317 } 318 319 /** Check changes on all known hubs. 320 */ 321 static void check_hub_changes(void) { 322 /* 323 * Iterate through all HCs. 324 */ 325 link_t *link_hc; 326 for (link_hc = hc_list.next; 327 link_hc != &hc_list; 328 link_hc = link_hc->next) { 329 usb_hc_device_t *hc = list_get_instance(link_hc, 330 usb_hc_device_t, link); 331 /* 332 * Iterate through all their hubs. 333 */ 334 link_t *link_hub; 335 for (link_hub = hc->hubs.next; 336 link_hub != &hc->hubs; 337 link_hub = link_hub->next) { 338 usb_hcd_hub_info_t *hub = list_get_instance(link_hub, 339 usb_hcd_hub_info_t, link); 340 341 /* 342 * Check status change pipe of this hub. 343 */ 344 usb_target_t target = { 345 .address = hub->device->address, 346 .endpoint = 1 347 }; 348 349 // FIXME: count properly 350 size_t byte_length = (hub->port_count / 8) + 1; 351 352 void *change_bitmap = malloc(byte_length); 353 size_t actual_size; 354 usb_handle_t handle; 355 356 /* 357 * Send the request. 358 * FIXME: check returned value for possible errors 359 */ 360 usb_hc_async_interrupt_in(hc, target, 361 change_bitmap, byte_length, &actual_size, 362 &handle); 363 364 usb_hc_async_wait_for(handle); 365 366 /* 367 * TODO: handle the changes. 368 */ 369 } 67 return usb_add_hub_device(dev); 370 68 } 371 69 } … … 391 89 hc_driver = hc; 392 90 hc_driver_generic.name = hc->name; 393 394 /*395 * Launch here fibril that will periodically check all396 * attached hubs for status change.397 * WARN: This call will effectively do nothing.398 */399 check_hub_changes();400 91 401 92 /* … … 414 105 * @return Error code. 415 106 */ 416 int usb_hcd_add_root_hub(usb_hc_device_t *dev) { 107 int usb_hcd_add_root_hub(usb_hc_device_t *dev) 108 { 109 char *id; 110 int rc = asprintf(&id, "usb&hc=%s&hub", dev->generic->name); 111 if (rc <= 0) { 112 return rc; 113 } 114 115 rc = usb_hc_add_child_device(dev->generic, USB_HUB_DEVICE_NAME, id, true); 116 if (rc != EOK) { 117 free(id); 118 } 119 120 return rc; 121 } 122 123 /** Info about child device. */ 124 struct child_device_info { 125 device_t *parent; 126 const char *name; 127 const char *match_id; 128 }; 129 130 /** Adds a child device fibril worker. */ 131 static int fibril_add_child_device(void *arg) 132 { 133 struct child_device_info *child_info 134 = (struct child_device_info *) arg; 417 135 int rc; 418 136 419 /* 420 * Announce presence of child device. 421 */ 422 device_t *hub = NULL; 137 device_t *child = create_device(); 423 138 match_id_t *match_id = NULL; 424 139 425 hub = create_device(); 426 if (hub == NULL) { 140 if (child == NULL) { 427 141 rc = ENOMEM; 428 142 goto failure; 429 143 } 430 hub->name = USB_HUB_DEVICE_NAME;144 child->name = child_info->name; 431 145 432 146 match_id = create_match_id(); … … 435 149 goto failure; 436 150 } 437 438 char *id; 439 rc = asprintf(&id, "usb&hc=%s&hub", dev->generic->name); 440 if (rc <= 0) { 441 rc = ENOMEM; 442 goto failure; 443 } 444 445 match_id->id = id; 446 match_id->score = 30; 447 448 add_match_id(&hub->match_ids, match_id); 449 450 rc = child_device_register(hub, dev->generic); 151 match_id->id = child_info->match_id; 152 match_id->score = 10; 153 add_match_id(&child->match_ids, match_id); 154 155 printf("%s: adding child device `%s' with match \"%s\"\n", 156 hc_driver->name, child->name, match_id->id); 157 rc = child_device_register(child, child_info->parent); 158 printf("%s: child device `%s' registration: %s\n", 159 hc_driver->name, child->name, str_error(rc)); 160 451 161 if (rc != EOK) { 452 162 goto failure; 453 163 } 454 164 455 printf("%s: registered root hub\n", dev->generic->name); 165 goto leave; 166 167 failure: 168 if (child != NULL) { 169 child->name = NULL; 170 delete_device(child); 171 } 172 173 if (match_id != NULL) { 174 match_id->id = NULL; 175 delete_match_id(match_id); 176 } 177 178 leave: 179 free(arg); 456 180 return EOK; 457 458 failure: 459 if (hub != NULL) { 460 hub->name = NULL; 461 delete_device(hub); 462 } 463 delete_match_id(match_id); 464 465 return rc; 181 } 182 183 /** Adds a child. 184 * Due to deadlock in devman when parent registers child that oughts to be 185 * driven by the same task, the child adding is done in separate fibril. 186 * Not optimal, but it works. 187 * Update: not under all circumstances the new fibril is successful either. 188 * Thus the last parameter to let the caller choose. 189 * 190 * @param parent Parent device. 191 * @param name Device name. 192 * @param match_id Match id. 193 * @param create_fibril Whether to run the addition in new fibril. 194 * @return Error code. 195 */ 196 int usb_hc_add_child_device(device_t *parent, const char *name, 197 const char *match_id, bool create_fibril) 198 { 199 printf("%s: about to add child device `%s' (%s)\n", hc_driver->name, 200 name, match_id); 201 202 struct child_device_info *child_info 203 = malloc(sizeof(struct child_device_info)); 204 205 child_info->parent = parent; 206 child_info->name = name; 207 child_info->match_id = match_id; 208 209 if (create_fibril) { 210 fid_t fibril = fibril_create(fibril_add_child_device, child_info); 211 if (!fibril) { 212 return ENOMEM; 213 } 214 fibril_add_ready(fibril); 215 } else { 216 fibril_add_child_device(child_info); 217 } 218 219 return EOK; 220 } 221 222 /** Tell USB address of given device. 223 * 224 * @param handle Devman handle of the device. 225 * @return USB device address or error code. 226 */ 227 usb_address_t usb_get_address_by_handle(devman_handle_t handle) 228 { 229 /* TODO: search list of attached devices. */ 230 return ENOENT; 466 231 } 467 232 -
uspace/lib/usb/src/usbdrv.c
rda55d5b rc39544a 64 64 * Call parent hub to obtain device handle of respective HC. 65 65 */ 66 return ENOTSUP; 66 67 /* 68 * FIXME: currently we connect always to virtual host controller. 69 */ 70 int rc; 71 devman_handle_t handle; 72 73 rc = devman_device_get_handle("/vhc", &handle, 0); 74 if (rc != EOK) { 75 return rc; 76 } 77 78 int phone = devman_device_connect(handle, 0); 79 80 return phone; 67 81 } 68 82 … … 75 89 usb_address_t usb_drv_get_my_address(int phone, device_t *dev) 76 90 { 77 return ENOTSUP; 91 ipcarg_t address; 92 int rc = async_req_1_1(phone, IPC_M_USBHC_GET_ADDRESS, 93 dev->handle, &address); 94 95 if (rc != EOK) { 96 return rc; 97 } 98 99 return (usb_address_t) address; 78 100 } 79 101 … … 323 345 } 324 346 347 /** Start control write transfer. */ 348 int usb_drv_async_control_write_setup(int phone, usb_target_t target, 349 void *buffer, size_t size, 350 usb_handle_t *handle) 351 { 352 return async_send_buffer(phone, 353 IPC_M_USBHC_CONTROL_WRITE_SETUP, 354 target, 355 buffer, size, 356 handle); 357 } 358 359 /** Send data during control write transfer. */ 360 int usb_drv_async_control_write_data(int phone, usb_target_t target, 361 void *buffer, size_t size, 362 usb_handle_t *handle) 363 { 364 return async_send_buffer(phone, 365 IPC_M_USBHC_CONTROL_WRITE_DATA, 366 target, 367 buffer, size, 368 handle); 369 } 370 371 /** Finalize control write transfer. */ 372 int usb_drv_async_control_write_status(int phone, usb_target_t target, 373 usb_handle_t *handle) 374 { 375 return async_recv_buffer(phone, 376 IPC_M_USBHC_CONTROL_WRITE_STATUS, 377 target, 378 NULL, 0, NULL, 379 handle); 380 } 381 382 /** Start control read transfer. */ 383 int usb_drv_async_control_read_setup(int phone, usb_target_t target, 384 void *buffer, size_t size, 385 usb_handle_t *handle) 386 { 387 return async_send_buffer(phone, 388 IPC_M_USBHC_CONTROL_READ_SETUP, 389 target, 390 buffer, size, 391 handle); 392 } 393 394 /** Read data during control read transfer. */ 395 int usb_drv_async_control_read_data(int phone, usb_target_t target, 396 void *buffer, size_t size, size_t *actual_size, 397 usb_handle_t *handle) 398 { 399 return async_recv_buffer(phone, 400 IPC_M_USBHC_CONTROL_READ_DATA, 401 target, 402 buffer, size, actual_size, 403 handle); 404 } 405 406 /** Finalize control read transfer. */ 407 int usb_drv_async_control_read_status(int phone, usb_target_t target, 408 usb_handle_t *handle) 409 { 410 return async_send_buffer(phone, 411 IPC_M_USBHC_CONTROL_READ_STATUS, 412 target, 413 NULL, 0, 414 handle); 415 } 416 325 417 /** 326 418 * @}
Note:
See TracChangeset
for help on using the changeset viewer.